diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1355,6 +1355,17 @@ const DenseMap &order) { StringRef name = sec->name; + // Never sort these. + if (name == ".init" || name == ".fini") + return; + + // Sort input sections by priority using the list provided + // by --symbol-ordering-file or --shuffle-sections=. + if (!order.empty()) + for (BaseCommand *b : sec->sectionCommands) + if (auto *isd = dyn_cast(b)) + sortISDBySectionOrder(isd, order); + // Sort input sections by section name suffixes for // __attribute__((init_priority(N))). if (name == ".init_array" || name == ".fini_array") { @@ -1370,10 +1381,6 @@ return; } - // Never sort these. - if (name == ".init" || name == ".fini") - return; - // .toc is allocated just after .got and is accessed using GOT-relative // relocations. Object files compiled with small code model have an // addressable range of [.got, .got + 0xFFFC] for GOT-relative relocations. @@ -1391,13 +1398,6 @@ }); return; } - - // Sort input sections by priority using the list provided - // by --symbol-ordering-file. - if (!order.empty()) - for (BaseCommand *b : sec->sectionCommands) - if (auto *isd = dyn_cast(b)) - sortISDBySectionOrder(isd, order); } // If no layout was provided by linker script, we want to apply default diff --git a/lld/test/ELF/shuffle-sections-init-fini.s b/lld/test/ELF/shuffle-sections-init-fini.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/shuffle-sections-init-fini.s @@ -0,0 +1,48 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o + +# RUN: ld.lld %t.o -o %t +# RUN: llvm-readelf -x .init -x .fini -x .init_array -x .fini_array %t | \ +# RUN: FileCheck --check-prefixes=CHECK,ORDERED %s + +# RUN: ld.lld --shuffle-sections=1 %t.o -o %t1 +# RUN: llvm-readelf -x .init -x .fini -x .init_array -x .fini_array %t1 | \ +# RUN: FileCheck --check-prefixes=CHECK,SHUFFLED %s + +## .init and .fini rely on a particular order, e.g. crti.o crtbegin.o crtend.o crtn.o +## Don't shuffle them. +# CHECK: Hex dump of section '.init' +# CHECK-NEXT: 00010203 04050607 08090a0b + +# CHECK: Hex dump of section '.fini' +# CHECK-NEXT: 00010203 04050607 08090a0b + +## SHT_INIT_ARRAY/SHT_FINI_ARRAY with explicit priorities are still ordered. +# CHECK: Hex dump of section '.init_array' +# CHECK-NEXT: 0x{{[0-9a-f]+}} ff +# ORDERED-SAME: 000102 03040506 0708090a 0b +# SHUFFLED-NOT: 000102 03040506 0708090a 0b + +# CHECK: Hex dump of section '.fini_array' +# CHECK-NEXT: 0x{{[0-9a-f]+}} ff +# ORDERED-SAME: 000102 03040506 0708090a 0b +# SHUFFLED-NOT: 000102 03040506 0708090a 0b + +## Random number engines have different implementations. +## When the number of input sections are large, it is almost guaranteed +## to have an unordered result with --shuffle-sections=. +.irp i,0,1,2,3,4,5,6,7,8,9,10,11 + .section .init,"ax",@progbits,unique,\i + .byte \i + .section .fini,"ax",@progbits,unique,\i + .byte \i + .section .init_array,"aw",@init_array,unique,\i + .byte \i + .section .fini_array,"aw",@fini_array,unique,\i + .byte \i +.endr + +.section .init_array.1,"aw",@init_array +.byte 255 +.section .fini_array.1,"aw",@fini_array +.byte 255