Skip to content

Commit 49512a2

Browse files
committed
Enable DT_RELR relocations on supported targets
1 parent 1f2b42b commit 49512a2

1 file changed

Lines changed: 141 additions & 2 deletions

File tree

tools/gcc-wrapper/main.c

Lines changed: 141 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,11 @@ static const char LD_OPT_RPATH_LINK[] = "-rpath-link";
147147
static const char LD_OPT_RPATH[] = "-rpath";
148148
static const char LD_OPT_UNRESOLVED_SYMBOLS[] = "--unresolved-symbols=ignore-in-shared-libs";
149149
static const char LD_OPT_NO_ROSEGMENT[] = "--no-rosegment";
150+
static const char LD_OPT_Z[] = "-z";
151+
static const char LD_OPT_PACK_RELATIVE_RELOCS[] = "pack-relative-relocs";
152+
153+
static const char LLD_OPT_USE_ANDROID_RELR_TAGS[] = "--use-android-relr-tags";
154+
static const char LLD_OPT_PACK_DYN_RELOCS[] = "--pack-dyn-relocs=relr";
150155

151156
static const char M_ANDROID_API[] = "__ANDROID_API__=";
152157
static const char M_ANDROID_MIN_SDK_VERSION[] = "__ANDROID_MIN_SDK_VERSION__=";
@@ -330,6 +335,79 @@ static int target_supports_neon(const char* const name) {
330335

331336
}
332337

338+
static int check_linker_lld(const char* const name) {
339+
return name != NULL && strcmp(name, "lld") == 0;
340+
}
341+
342+
static int check_linker_mold(const char* const name) {
343+
return name != NULL && strcmp(name, "mold") == 0;
344+
}
345+
346+
347+
static int target_supports_relr(const char* const name, const char* const linker, const int version) {
348+
349+
#if defined(OBGGCC)
350+
/* The GNU C Library has supported DT_RELR since the 2.36 release. */
351+
if (version < LIBC_VERSION(2, 36)) {
352+
return 0;
353+
}
354+
355+
if (strcmp(name, "x86_64-unknown-linux-gnu") == 0) {
356+
return 1;
357+
}
358+
359+
if (strcmp(name, "i386-unknown-linux-gnu") == 0) {
360+
return 1;
361+
}
362+
363+
if (strcmp(name, "aarch64-unknown-linux-gnu") == 0) {
364+
return 1;
365+
}
366+
367+
if (check_linker_lld(linker) || check_linker_mold(linker)) {
368+
if (strcmp(name, "arm-unknown-linux-gnueabihf") == 0) {
369+
return 1;
370+
}
371+
}
372+
#elif defined(PINO)
373+
/* The Bionic C Library has supported DT_RELR since Android 9 (API level 28). */
374+
if (version < LIBC_VERSION(28, 0)) {
375+
return 0;
376+
}
377+
378+
if (strcmp(name, "x86_64-unknown-linux-android") == 0) {
379+
return 1;
380+
}
381+
382+
if (strcmp(name, "i686-unknown-linux-android") == 0) {
383+
return 1;
384+
}
385+
386+
if (strcmp(name, "aarch64-unknown-linux-android") == 0) {
387+
return 1;
388+
}
389+
390+
if (check_linker_lld(linker) || check_linker_mold(linker)) {
391+
if (strcmp(name, "armv7-unknown-linux-androideabi") == 0) {
392+
return 1;
393+
}
394+
395+
if (strcmp(name, "armv5-unknown-linux-androideabi") == 0) {
396+
return 1;
397+
}
398+
399+
if (strcmp(name, "riscv64-unknown-linux-android") == 0) {
400+
return 1;
401+
}
402+
}
403+
#else
404+
#error "I don't know how to handle this"
405+
#endif
406+
407+
return 0;
408+
409+
}
410+
333411
static const char* get_simd(const char* const name) {
334412

335413
if (strcmp(name, "i686-unknown-linux-android") == 0 || strcmp(name, "i386-unknown-linux-gnu") == 0) {
@@ -765,7 +843,7 @@ int main(int argc, char* argv[], char* envp[]) {
765843
int require_atomic_library = 0;
766844
#endif
767845

768-
int override_linker = 0;
846+
const char* override_linker = NULL;
769847

770848
int cmake_init = 0;
771849

@@ -886,6 +964,7 @@ int main(int argc, char* argv[], char* envp[]) {
886964
2 + /* -l pino-math */
887965
2 + /* -l pino-mman */
888966
1 + /* -msse<version> */
967+
4 + /* -Xlinker -z -Xlinker pack-relative-relocs */
889968
1 /* NULL */
890969
)
891970
);
@@ -905,7 +984,7 @@ int main(int argc, char* argv[], char* envp[]) {
905984
} else if (strncmp(cur, GCC_OPT_FSANITIZE, strlen(GCC_OPT_FSANITIZE)) == 0) {
906985
address_sanitizer = 1;
907986
} else if (strncmp(cur, GCC_OPT_F_USE_LD, strlen(GCC_OPT_F_USE_LD)) == 0) {
908-
override_linker = 1;
987+
override_linker = cur + strlen(GCC_OPT_F_USE_LD);
909988
} else if (strncmp(cur, GCC_OPT_F_STACK_PROTECTOR, strlen(GCC_OPT_F_STACK_PROTECTOR)) == 0) {
910989
stack_protector = 1;
911990
} else if (strcmp(cur, GCC_OPT_VERSION) == 0) {
@@ -1444,6 +1523,66 @@ int main(int argc, char* argv[], char* envp[]) {
14441523
}
14451524
#endif
14461525

1526+
/*
1527+
Enable DT_RELR relocations on supported targets.
1528+
1529+
- bfd
1530+
As of binutils 2.45, this is supported for the following architectures: AArch64, x86, and x86_64.
1531+
1532+
- gold
1533+
Not supported at all.
1534+
1535+
- LLD
1536+
LLD always accepts the flag regardless of the target architecture and never outputs an error message.
1537+
It's unclear whether it truly supports all architectures or if LLD is simply ignoring the flag when it's not supported.
1538+
1539+
- mold
1540+
Assumed to follow the same behavior as LLD.
1541+
*/
1542+
if (linking && target_supports_relr(triplet, override_linker, LIBC_VERSION(libc_major, libc_minor))) {
1543+
if (override_linker == NULL || strcmp(override_linker, "bfd") == 0) {
1544+
kargv[kargc++] = (char*) GCC_OPT_XLINKER;
1545+
kargv[kargc++] = (char*) LD_OPT_Z;
1546+
kargv[kargc++] = (char*) GCC_OPT_XLINKER;
1547+
kargv[kargc++] = (char*) LD_OPT_PACK_RELATIVE_RELOCS;
1548+
} else if (strcmp(override_linker, "mold") == 0 || strcmp(override_linker, "lld") == 0) {
1549+
#if defined(OBGGCC)
1550+
/*
1551+
DT_RELR on glibc requires a dependency on GLIBC_ABI_DT_RELR to be present,
1552+
but --pack-dyn-relocs does not add that dependency by default, which leads to this error at runtime:
1553+
1554+
$ gcc -fuse-ld=lld -Xlinker --pack-dyn-relocs <...>
1555+
$ ./main
1556+
./main: error while loading shared libraries: ./main: DT_RELR without GLIBC_ABI_DT_RELR dependency
1557+
1558+
To work around this, we use -z pack-relative-relocs instead, but this comes with the downside of not being
1559+
supported on older versions of lld and mold:
1560+
1561+
$ gcc -fuse-ld=lld -Xlinker -z -Xlinker pack-relative-relocs <...>
1562+
ld.lld: error: unknown -z value: pack-relative-relocs
1563+
collect2: error: ld returned 1 exit status
1564+
*/
1565+
kargv[kargc++] = (char*) GCC_OPT_XLINKER;
1566+
kargv[kargc++] = (char*) LD_OPT_Z;
1567+
kargv[kargc++] = (char*) GCC_OPT_XLINKER;
1568+
kargv[kargc++] = (char*) LD_OPT_PACK_RELATIVE_RELOCS;
1569+
#else
1570+
/*
1571+
Everything else should work with --pack-dyn-relocs.
1572+
*/
1573+
#if defined(PINO)
1574+
if (strcmp(override_linker, "lld") == 0) {
1575+
kargv[kargc++] = (char*) GCC_OPT_XLINKER;
1576+
kargv[kargc++] = (char*) LLD_OPT_PACK_DYN_RELOCS;
1577+
}
1578+
#endif
1579+
1580+
kargv[kargc++] = (char*) GCC_OPT_XLINKER;
1581+
kargv[kargc++] = (char*) LLD_OPT_PACK_DYN_RELOCS;
1582+
#endif
1583+
}
1584+
}
1585+
14471586
#if defined(OBGGCC)
14481587
/* Determine whether we need to implicit link with -lrt */
14491588
wants_librt = wants_libcxx && !have_rt_library && LIBC_VERSION(libc_major, libc_minor) < LIBC_VERSION(2, 17);

0 commit comments

Comments
 (0)