@@ -147,6 +147,11 @@ static const char LD_OPT_RPATH_LINK[] = "-rpath-link";
147147static const char LD_OPT_RPATH [] = "-rpath" ;
148148static const char LD_OPT_UNRESOLVED_SYMBOLS [] = "--unresolved-symbols=ignore-in-shared-libs" ;
149149static 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
151156static const char M_ANDROID_API [] = "__ANDROID_API__=" ;
152157static 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+
333411static 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