Skip to content

Commit e3536ef

Browse files
committed
sys-devel/binutils-config: remove duplicate -L and -rpath entries
Ever since CLT15.3 duplicate -L or -rpath entries result in warnings. These warnings, albeit just ugly, make that some packages croak or worse: abort, claiming the linker is broken (such as Ruby). This is nonsense, but cater for this by removing any duplicate paths, and not adding any paths that are already added. Signed-off-by: Fabian Groffen <[email protected]>
1 parent 643ab6c commit e3536ef

File tree

2 files changed

+150
-48
lines changed

2 files changed

+150
-48
lines changed

sys-devel/binutils-config/files/ldwrapper.c

+150-48
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,10 @@ int
197197
main(int argc, char *argv[])
198198
{
199199
int newargc = 0;
200+
int rpathcnt = 0;
200201
char **newargv = NULL;
202+
char **rpaths = NULL;
203+
char **lpaths = NULL;
201204
char *wrapper = argv[0];
202205
char *wrapperctarget = NULL;
203206
char verbose = getenv("BINUTILS_CONFIG_VERBOSE") != NULL;
@@ -214,7 +217,6 @@ main(int argc, char *argv[])
214217
size_t len;
215218
int i;
216219
int j;
217-
int k;
218220
DIR *dirp;
219221
struct dirent *dp;
220222

@@ -287,10 +289,12 @@ main(int argc, char *argv[])
287289
/* walk over the arguments to see if there's anything interesting
288290
* for us and calculate the final number of arguments */
289291
for (i = 1; i < argc; i++) {
290-
/* -L: account space for the matching -R */
291292
if (argv[i][0] == '-') {
293+
/* -L: account space for the matching -R */
292294
if (argv[i][1] == 'L')
293295
newargc++;
296+
if (argv[i][1] == 'R' || strcmp(argv[i], "-rpath") == 0)
297+
rpathcnt++;
294298
if (argv[i][1] == 'v' || argv[i][1] == 'V')
295299
verbose = 1;
296300
if ((strcmp(argv[i], "-macosx_version_min") == 0 ||
@@ -316,8 +320,6 @@ main(int argc, char *argv[])
316320
darwin_dt_ver += (int)strtol(p + 1, &p, 10);
317321
}
318322

319-
/* Note: Code below assumes that newargc is the count of -L arguments. */
320-
321323
/* If a package being cross-compiled injects standard directories, it's
322324
* non-cross-compilable on any platform, prefix or no prefix. So no
323325
* need to add PREFIX- or CTARGET-aware libdirs. */
@@ -341,13 +343,15 @@ main(int argc, char *argv[])
341343
* -rpath and the path itself */
342344
newargc *= 2;
343345

344-
/* and we will be adding two for the each of
345-
* the two system paths as well */
346-
newargc += 4;
346+
/* PREFIX rpaths */
347+
newargc += 2 * 2;
347348
}
348349

349-
/* add the 2 prefix paths (-L) and -search_paths_first */
350-
newargc += 2 + 1;
350+
/* PREFIX paths */
351+
newargc += 3;
352+
353+
/* add -search_paths_first */
354+
newargc += 1;
351355

352356
/* add -syslibroot <path> -platform_version macos <ver> 0.0 */
353357
newargc += 6;
@@ -357,6 +361,27 @@ main(int argc, char *argv[])
357361
}
358362
}
359363

364+
/* Note: Code below assumes that newargc is the count of -L arguments. */
365+
366+
/* allocate space for -L lookups/uniqueifying */
367+
lpaths = malloc(sizeof(lpaths[0]) * (newargc + 1));
368+
if (lpaths == NULL) {
369+
fprintf(stderr, "%s: failed to allocate memory for new arguments\n",
370+
wrapper);
371+
exit(1);
372+
}
373+
lpaths[0] = NULL;
374+
375+
if (!is_darwin || darwin_use_rpath) {
376+
rpaths = malloc(sizeof(rpaths[0]) * (rpathcnt + 1));
377+
if (rpaths == NULL) {
378+
fprintf(stderr, "%s: failed to allocate memory for new arguments\n",
379+
wrapper);
380+
exit(1);
381+
}
382+
rpaths[0] = NULL;
383+
}
384+
360385
/* account the original arguments */
361386
newargc += argc;
362387
/* we always add a sentinel */
@@ -476,8 +501,6 @@ main(int argc, char *argv[])
476501
newargv[j++] = "-search_paths_first";
477502
}
478503

479-
/* position k right after the original arguments */
480-
k = j - 1 + argc;
481504
for (i = 1; i < argc; i++, j++) {
482505
if (is_darwin) {
483506
/* skip platform version stuff, we already pushed it out */
@@ -486,15 +509,13 @@ main(int argc, char *argv[])
486509
{
487510
i++;
488511
j--;
489-
k -= 2;
490512
continue;
491513
}
492514
if (strcmp(argv[i], "-platform_version") == 0 &&
493515
i < argc - 3 && strcmp(argv[i + 1], "macos") == 0)
494516
{
495517
i += 3;
496518
j--;
497-
k -= 4;
498519
continue;
499520
}
500521
}
@@ -504,10 +525,12 @@ main(int argc, char *argv[])
504525
if (is_cross || (is_darwin && !darwin_use_rpath))
505526
continue;
506527

507-
/* on ELF targets we add runpaths for all found search paths */
508-
if (argv[i][0] == '-' && argv[i][1] == 'L') {
528+
/* on ELF/Mach-O targets we add runpaths for all found search paths */
529+
if (argv[i][0] == '-' && (argv[i][1] == 'L' || argv[i][1] == 'R')) {
509530
char *path;
510-
size_t sze;
531+
int pth;
532+
char duplicate;
533+
int before = j - 1;
511534

512535
/* arguments can be in many ways here:
513536
* -L<path>
@@ -533,50 +556,129 @@ main(int argc, char *argv[])
533556
if (builddir != NULL && strncmp(builddir, path, len) == 0)
534557
continue;
535558

536-
if (is_darwin) {
537-
newargv[k] = "-rpath";
538-
newargv[++k] = path;
539-
} else {
540-
sze = 2 + strlen(path) + 1;
541-
newargv[k] = malloc(sizeof(char) * sze);
542-
if (newargv[k] == NULL) {
543-
fprintf(stderr, "%s: failed to allocate memory for "
544-
"'%s' -R argument\n", wrapper, argv[i]);
545-
exit(1);
559+
/* loop-search for this path, if it was emitted already,
560+
* suppress it -- this is not just some fancy beautification!
561+
* CLT15.3 on macOS warns about duplicate paths, and
562+
* any project that triggers on these warnings causes
563+
* problems, such as Ruby claiming the linker is broken */
564+
duplicate = 0;
565+
if (argv[i][1] == 'L') {
566+
for (pth = 0; lpaths[pth] != NULL; pth++) {
567+
if (strcmp(lpaths[pth], path) == 0) {
568+
duplicate = 1;
569+
break;
570+
}
546571
}
547-
548-
snprintf(newargv[k], sze, "-R%s", path);
572+
if (duplicate) {
573+
j = before;
574+
continue;
575+
}
576+
/* record path */
577+
lpaths[pth++] = path;
578+
lpaths[pth] = NULL;
579+
} else if (!is_darwin || darwin_use_rpath) {
580+
for (pth = 0; rpaths[pth] != NULL; pth++) {
581+
if (strcmp(rpaths[pth], path) == 0) {
582+
duplicate = 1;
583+
break;
584+
}
585+
}
586+
if (duplicate) {
587+
j = before;
588+
continue;
589+
}
590+
/* record path */
591+
rpaths[pth++] = path;
592+
rpaths[pth] = NULL;
549593
}
594+
} else if ((!is_darwin || darwin_use_rpath) &&
595+
strcmp(argv[i], "-rpath") == 0)
596+
{
597+
char *path;
598+
int pth;
599+
char duplicate;
550600

551-
k++;
601+
path = argv[i + 1];
602+
while (*path != '\0' && isspace(*path))
603+
path++;
604+
/* not absolute (or empty)?!? skip */
605+
if (*path != '/')
606+
continue;
607+
608+
/* does it refer to the build directory? skip */
609+
if (builddir != NULL && strncmp(builddir, path, len) == 0)
610+
continue;
611+
612+
duplicate = 0;
613+
for (pth = 0; rpaths[pth] != NULL; pth++) {
614+
if (strcmp(rpaths[pth], path) == 0) {
615+
duplicate = 1;
616+
break;
617+
}
618+
}
619+
if (duplicate) {
620+
j -= 2;
621+
continue;
622+
}
623+
/* record path */
624+
rpaths[pth++] = path;
625+
rpaths[pth] = NULL;
552626
}
553627
}
554628
/* add the custom paths */
555629
if (!is_cross) {
630+
int pth;
631+
#define path_not_exists(W,P) \
632+
for (pth = 0; W[pth] != NULL; pth++) { \
633+
if (strcmp(W[pth], P) == 0) \
634+
break; \
635+
} \
636+
if (W[pth] == NULL)
637+
#define add_path(P) \
638+
path_not_exists(lpaths, P) newargv[j++] = "-L" P
639+
#define add_path_rpath(P) \
640+
path_not_exists(lpaths, P) { \
641+
lpaths[pth++] = P; \
642+
lpaths[pth] = NULL; \
643+
newargv[j++] = "-L" P; \
644+
}
645+
556646
if (is_darwin) {
557647
/* FIXME: no support for cross-compiling *to* Darwin */
558-
newargv[k++] = "-L" EPREFIX "/usr/" CHOST "/lib/gcc";
559-
newargv[k++] = "-L" EPREFIX "/usr/lib";
560-
newargv[k++] = "-L" EPREFIX "/lib";
561-
562-
if (darwin_use_rpath) {
563-
newargv[k++] = "-rpath";
564-
newargv[k++] = EPREFIX "/usr/lib";
565-
newargv[k++] = "-rpath";
566-
newargv[k++] = EPREFIX "/lib";
567-
}
648+
add_path(EPREFIX "/usr/" CHOST "/lib/gcc");
649+
add_path_rpath(EPREFIX "/usr/lib");
650+
add_path_rpath(EPREFIX "/lib");
568651
} else {
569-
newargv[k++] = "-L" EPREFIX "/usr/" CHOST "/lib/gcc";
570-
newargv[k++] = "-R" EPREFIX "/usr/" CHOST "/lib/gcc";
571-
newargv[k++] = "-L" EPREFIX "/usr/" CHOST "/lib";
572-
newargv[k++] = "-R" EPREFIX "/usr/" CHOST "/lib";
573-
newargv[k++] = "-L" EPREFIX "/usr/lib";
574-
newargv[k++] = "-R" EPREFIX "/usr/lib";
575-
newargv[k++] = "-L" EPREFIX "/lib";
576-
newargv[k++] = "-R" EPREFIX "/lib";
652+
add_path_rpath(EPREFIX "/usr/" CHOST "/lib/gcc");
653+
add_path_rpath(EPREFIX "/usr/" CHOST "/lib");
654+
add_path_rpath(EPREFIX "/usr/lib");
655+
add_path_rpath(EPREFIX "/lib");
656+
}
657+
}
658+
/* add rpaths for -L entries */
659+
if (!is_darwin || darwin_use_rpath) {
660+
for (i = 0; lpaths[i] != NULL; i++) {
661+
int pth;
662+
path_not_exists(rpaths, lpaths[i]) {
663+
size_t sze;
664+
if (is_darwin && darwin_use_rpath) {
665+
newargv[j++] = "-rpath";
666+
newargv[j++] = lpaths[i];
667+
} else if (!is_darwin) {
668+
sze = 2 + strlen(lpaths[i]) + 1;
669+
newargv[j] = malloc(sizeof(char) * sze);
670+
if (newargv[j] == NULL) {
671+
fprintf(stderr, "%s: failed to allocate memory for "
672+
"'%s' -R argument\n", wrapper, argv[i]);
673+
exit(1);
674+
}
675+
676+
snprintf(newargv[j++], sze, "-R%s", lpaths[i]);
677+
}
678+
}
577679
}
578680
}
579-
newargv[k] = NULL;
681+
newargv[j] = NULL;
580682

581683
if (verbose) {
582684
fprintf(stderr, "%s: invoking %s with arguments:\n", wrapper, ld);

0 commit comments

Comments
 (0)