/* $NetBSD: normalise-cc.c,v 1.7 2022/04/04 11:22:51 riastradh Exp $ */ /*- * Copyright (c) 2009, 2017 Joerg Sonnenberger . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include "common.h" static void normalise_path_list(struct arglist *args, struct argument *arg, const char *prefix, const char *sysroot_prefix, const char *val, int strip_relative) { const char *sep; struct argument *arg2; while ((sep = strchr(val, ':')) != NULL) { if (sep == val || (strip_relative && !isabs(val[0]))) { val = sep + 1; continue; } arg2 = argument_new(concat2(prefix, val, sep - val)); TAILQ_INSERT_AFTER(args, arg, arg2, link); arg = arg2; if (sysroot_prefix && sysroot) { char *sysroot_val = concat2(sysroot, val, sep - val); arg2 = argument_new(concat(sysroot_prefix, sysroot_val)); free(sysroot_val); TAILQ_INSERT_AFTER(args, arg, arg2, link); arg = arg2; } val = sep + 1; } if (val[0] == '\0' || (strip_relative && !isabs(val[0]))) return; arg2 = argument_new(concat(prefix, val)); TAILQ_INSERT_AFTER(args, arg, arg2, link); arg = arg2; if (sysroot_prefix && sysroot) { char *sysroot_val = concat(sysroot, val); arg2 = argument_new(concat(sysroot_prefix, sysroot_val)); free(sysroot_val); TAILQ_INSERT_AFTER(args, arg, arg2, link); arg = arg2; } } void operation_mode_cc(struct arglist *args) { struct argument *arg; current_operation_mode = mode_link_executable; TAILQ_FOREACH(arg, args, link) { if (arg->val[0] != '-') continue; if (strcmp(arg->val, "-E") == 0) { current_operation_mode = mode_preprocess; continue; } if (strcmp(arg->val, "-S") == 0) { current_operation_mode = mode_assemble; continue; } if (strcmp(arg->val, "-c") == 0) { current_operation_mode = mode_compile; continue; } if (strcmp(arg->val, "-shared") == 0) { current_operation_mode = mode_link_shared; continue; } } } void normalise_cc(struct arglist *args) { struct argument *arg, *arg2, *arg3; const char *next, *last; size_t len; TAILQ_FOREACH_SAFE(arg, args, link, arg2) { if (arg->val[0] != '-') continue; if (strcmp(arg->val, "-Xlinker") == 0) { if (arg2 == NULL) errx(255, "Missing argument for %s", arg->val); if (strncmp(arg2->val, "-Wl,", 4) == 0) { argument_unlink(args, &arg); continue; } argument_update(arg2, concat("-Wl,", arg2->val)); argument_unlink(args, &arg); continue; } if (strncmp(arg->val, "-Wl,", 4) == 0 && (next = strchr(arg->val + 4, ',')) != NULL) { last = arg->val + 4; do { arg3 = argument_new(concat2("-Wl,", last, next - last)); if (arg2 != NULL) TAILQ_INSERT_BEFORE(arg2, arg3, link); else TAILQ_INSERT_TAIL(args, arg3, link); last = next + 1; } while ((next = strchr(last, ',')) != NULL); arg3 = argument_new(concat("-Wl,", last)); if (arg2 != NULL) TAILQ_INSERT_BEFORE(arg2, arg3, link); else TAILQ_INSERT_TAIL(args, arg3, link); argument_unlink(args, &arg); continue; } } TAILQ_FOREACH_SAFE(arg, args, link, arg2) { if (strcmp(arg->val, "-o") == 0) { /* Output to stdout ("-") is explicitly valid. */ if (arg2 == NULL || (arg2->val[0] == '-' && arg2->val[1] != '\0')) errx(255, "Missing argument for %s", arg->val); arg2 = TAILQ_NEXT(arg2, link); continue; } if (strcmp(arg->val, "-dylib_file") == 0 || strcmp(arg->val, "-dylib_install_name") == 0 || strcmp(arg->val, "-install_name") == 0 || strcmp(arg->val, "-seg_addr_table_filename") == 0 || strcmp(arg->val, "--dynamic-linker") == 0) { if (arg2 == NULL || arg2->val[0] == '-') errx(255, "Missing argument for %s", arg->val); arg2 = TAILQ_NEXT(arg2, link); continue; } if (isabs(arg->val[0])) { next = strrchr(arg->val, '/'); ++next; if (strncmp(next, "lib", 3)) continue; next += 3; len = strspn(next, library_name_chars); if (len == 0) continue; last = next + len; if (strncmp(last, ".so", 3) == 0 || strncmp(last, ".sl", 3) == 0) last += 3; else if (strncmp(last, ".dylib", 6) == 0) last += 6; else continue; if (last[0] && (last[0] != '.' || last[1] < '0' || last[1] > '9')) continue; arg3 = argument_new(xasprintf("-l%*.*s", (int)len, (int)len, next)); next = strrchr(arg->val, '/'); len = next - arg->val; argument_update(arg, xasprintf("-L%*.*s", (int)len, (int)len, arg->val)); TAILQ_INSERT_AFTER(args, arg, arg3, link); continue; } if (arg->val[0] != '-') continue; if (strcmp(arg->val, "-I") == 0 || strcmp(arg->val, "-D") == 0 || strcmp(arg->val, "-L") == 0) { if (arg2 == NULL || arg2->val[0] == '-') errx(255, "Missing argument for %s", arg->val); argument_update(arg, concat(arg->val, arg2->val)); argument_unlink(args, &arg2); continue; } if (strcmp(arg->val, "-Wl,-L") == 0) { if (arg2 == NULL || strncmp(arg2->val, "-Wl,", 4)) errx(255, "Missing argument for %s", arg->val); argument_update(arg, concat("-L", arg2->val + 4)); argument_unlink(args, &arg2); continue; } if (strcmp(arg->val, "-Wl,-rpath-link") == 0) { if (arg2 == NULL || strncmp(arg2->val, "-Wl,", 4)) errx(255, "Missing argument for %s", arg->val); normalise_path_list(args, arg, "-Wl,-rpath-link,", NULL, arg2->val + 4, 0); argument_unlink(args, &arg); argument_unlink(args, &arg2); continue; } if (strcmp(arg->val, "-R") == 0) { if (arg2 == NULL || arg2->val[0] == '-') errx(255, "Missing argument for %s", arg->val); normalise_path_list(args, arg, "-Wl,-rpath,", "-Wl,-rpath-link,"/*sysroot*/, arg2->val, 1); argument_unlink(args, &arg); argument_unlink(args, &arg2); continue; } if (strcmp(arg->val, "-Wl,-R") == 0 || strcmp(arg->val, "-Wl,-rpath") == 0 || strcmp(arg->val, "-Wl,--rpath") == 0) { if (arg2 == NULL || strncmp(arg2->val, "-Wl,", 4)) errx(255, "Missing argument for %s", arg->val); normalise_path_list(args, arg, "-Wl,-rpath,", "-Wl,-rpath-link,"/*sysroot*/, arg2->val + 4, 1); argument_unlink(args, &arg); argument_unlink(args, &arg2); continue; } if (strncmp(arg->val, "-Wl,-R", 6) == 0) { normalise_path_list(args, arg, "-Wl,-rpath,", "-Wl,-rpath-link,"/*sysroot*/, arg->val + 6, 1); argument_unlink(args, &arg); continue; } if (strncmp(arg->val, "-R", 2) == 0) { normalise_path_list(args, arg, "-Wl,-rpath,", "-Wl,-rpath-link,"/*sysroot*/, arg->val + 2, 1); argument_unlink(args, &arg); continue; } if (strncmp(arg->val, "-Wl,-rpath,", 10) == 0) { normalise_path_list(args, arg, "-Wl,-rpath,", "-Wl,-rpath-link,"/*sysroot*/, arg->val + 10, 1); argument_unlink(args, &arg); continue; } } }