Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -1895,7 +1895,14 @@ InputSectionBase *C) { uintX_t Flags = getOutFlags(C); OutputSectionBase *&Sec = Map[Key]; - if (Sec) { + + // If --relocatable, we do not merge regular input sections + // and instead let the final link merge them. This behavior + // is different from GNU linkers, but we chose this behavior + // because 1) --gc-sections and --icf work better with fine- + // grained inputs and 2) reading some sections such as .ARM.exidx + // and reproduce it for later use is not easy. + if (!Config->Relocatable && Sec) { Sec->updateFlags(Flags); return {Sec, false}; } Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -89,6 +89,10 @@ template StringRef elf::getOutputSectionName(InputSectionBase *S) { + // If --relocatable, we don't merge sections. + if (Config->Relocatable) + return S->Name; + StringRef Name = S->Name; for (StringRef V : {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.", Index: test/ELF/relocatable-ehframe.s =================================================================== --- test/ELF/relocatable-ehframe.s +++ test/ELF/relocatable-ehframe.s @@ -20,13 +20,15 @@ # CHECK-NEXT: ) # CHECK: Relocations [ -# CHECK-NEXT: Section {{.*}} .rela.eh_frame { +# CHECK-NEXT: Section (11) .rela.eh_frame { # CHECK-NEXT: 0x20 R_X86_64_PC32 foo 0x0 # CHECK-NEXT: 0x34 R_X86_64_PC32 bar 0x0 # CHECK-NEXT: 0x48 R_X86_64_PC32 dah 0x0 -# CHECK-NEXT: 0x78 R_X86_64_PC32 foo1 0x0 -# CHECK-NEXT: 0x8C R_X86_64_PC32 bar1 0x0 -# CHECK-NEXT: 0xA0 R_X86_64_PC32 dah1 0x0 +# CHECK-NEXT: } +# CHECK-NEXT: Section (12) .rela.eh_frame { +# CHECK-NEXT: 0x20 R_X86_64_PC32 foo1 0x0 +# CHECK-NEXT: 0x34 R_X86_64_PC32 bar1 0x0 +# CHECK-NEXT: 0x48 R_X86_64_PC32 dah1 0x0 # CHECK-NEXT: } # CHECK-NEXT: ] Index: test/ELF/relocatable-reloc.s =================================================================== --- test/ELF/relocatable-reloc.s +++ test/ELF/relocatable-reloc.s @@ -7,8 +7,10 @@ .quad foo // CHECK: Relocations [ -// CHECK-NEXT: Section ({{.*}}) .rela.text { +// CHECK-NEXT: Section (3) .rela.text { +// CHECK-NEXT: 0x0 R_X86_64_64 foo 0x0 +// CHECK-NEXT: } +// CHECK-NEXT: Section (4) .rela.text { // CHECK-NEXT: 0x0 R_X86_64_64 foo 0x0 -// CHECK-NEXT: 0x8 R_X86_64_64 foo 0x0 // CHECK-NEXT: } // CHECK-NEXT: ] Index: test/ELF/relocatable.s =================================================================== --- test/ELF/relocatable.s +++ test/ELF/relocatable.s @@ -4,16 +4,16 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/relocatable2.s -o %t3.o # RUN: ld.lld -r %t1.o %t2.o %t3.o -o %t # RUN: llvm-readobj -file-headers -sections -program-headers -symbols -r %t | FileCheck %s -# RUN: llvm-objdump -s -d %t | FileCheck -check-prefix=CHECKTEXT %s +# RUN: llvm-objdump -s -d %t | FileCheck -check-prefix=TEXT %s ## Test --relocatable alias # RUN: ld.lld --relocatable %t1.o %t2.o %t3.o -o %t # RUN: llvm-readobj -file-headers -sections -program-headers -symbols -r %t | FileCheck %s -# RUN: llvm-objdump -s -d %t | FileCheck -check-prefix=CHECKTEXT %s +# RUN: llvm-objdump -s -d %t | FileCheck -check-prefix=TEXT %s ## Verify that we can use our relocation output as input to produce executable # RUN: ld.lld -e main %t -o %texec -# RUN: llvm-readobj -file-headers %texec | FileCheck -check-prefix=CHECKEXE %s +# RUN: llvm-readobj -file-headers %texec | FileCheck -check-prefix=EXE %s # CHECK: ElfHeader { # CHECK-NEXT: Ident { @@ -37,60 +37,67 @@ # CHECK-NEXT: ProgramHeaderEntrySize: 0 # CHECK-NEXT: ProgramHeaderCount: 0 # CHECK-NEXT: SectionHeaderEntrySize: 64 -# CHECK-NEXT: SectionHeaderCount: 7 -# CHECK-NEXT: StringTableSectionIndex: 5 +# CHECK-NEXT: SectionHeaderCount: 13 +# CHECK-NEXT: StringTableSectionIndex: 11 # CHECK-NEXT: } -# CHECK: Relocations [ -# CHECK-NEXT: Section (3) .rela.text { -# CHECK-NEXT: 0x3 R_X86_64_32S x 0x0 -# CHECK-NEXT: 0xE R_X86_64_32S y 0x0 -# CHECK-NEXT: 0x23 R_X86_64_32S xx 0x0 -# CHECK-NEXT: 0x2E R_X86_64_32S yy 0x0 -# CHECK-NEXT: 0x43 R_X86_64_32S xxx 0x0 -# CHECK-NEXT: 0x4E R_X86_64_32S yyy 0x0 -# CHECK-NEXT: } +# CHECK: Relocations [ +# CHECK-NEXT: Section (7) .rela.text { +# CHECK-NEXT: 0x3 R_X86_64_32S x 0x0 +# CHECK-NEXT: 0xE R_X86_64_32S y 0x0 +# CHECK-NEXT: } +# CHECK-NEXT: Section (8) .rela.text { +# CHECK-NEXT: 0x3 R_X86_64_32S xx 0x0 +# CHECK-NEXT: 0xE R_X86_64_32S yy 0x0 +# CHECK-NEXT: } +# CHECK-NEXT: Section (9) .rela.text { +# CHECK-NEXT: 0x3 R_X86_64_32S xxx 0x0 +# CHECK-NEXT: 0xE R_X86_64_32S yyy 0x0 +# CHECK-NEXT: } +# CHECK-NEXT: ] -# CHECKTEXT: Disassembly of section .text: -# CHECKTEXT-NEXT: main: -# CHECKTEXT-NEXT: 0: c7 04 25 00 00 00 00 05 00 00 00 movl $5, 0 -# CHECKTEXT-NEXT: b: c7 04 25 00 00 00 00 07 00 00 00 movl $7, 0 -# CHECKTEXT: foo: -# CHECKTEXT-NEXT: 20: c7 04 25 00 00 00 00 01 00 00 00 movl $1, 0 -# CHECKTEXT-NEXT: 2b: c7 04 25 00 00 00 00 02 00 00 00 movl $2, 0 -# CHECKTEXT: bar: -# CHECKTEXT-NEXT: 40: c7 04 25 00 00 00 00 08 00 00 00 movl $8, 0 -# CHECKTEXT-NEXT: 4b: c7 04 25 00 00 00 00 09 00 00 00 movl $9, 0 +# TEXT: Disassembly of section .text: +# TEXT-NEXT: main: +# TEXT-NEXT: 0: c7 04 25 00 00 00 00 05 00 00 00 movl $5, 0 +# TEXT-NEXT: b: c7 04 25 00 00 00 00 07 00 00 00 movl $7, 0 +# TEXT-NEXT: Disassembly of section .text: +# TEXT-NEXT: foo: +# TEXT-NEXT: 0: c7 04 25 00 00 00 00 01 00 00 00 movl $1, 0 +# TEXT-NEXT: b: c7 04 25 00 00 00 00 02 00 00 00 movl $2, 0 +# TEXT-NEXT: Disassembly of section .text: +# TEXT-NEXT: bar: +# TEXT-NEXT: 0: c7 04 25 00 00 00 00 08 00 00 00 movl $8, 0 +# TEXT-NEXT: b: c7 04 25 00 00 00 00 09 00 00 00 movl $9, 0 -# CHECKEXE: Format: ELF64-x86-64 -# CHECKEXE-NEXT: Arch: x86_64 -# CHECKEXE-NEXT: AddressSize: 64bit -# CHECKEXE-NEXT: LoadName: -# CHECKEXE-NEXT: ElfHeader { -# CHECKEXE-NEXT: Ident { -# CHECKEXE-NEXT: Magic: (7F 45 4C 46) -# CHECKEXE-NEXT: Class: 64-bit -# CHECKEXE-NEXT: DataEncoding: LittleEndian -# CHECKEXE-NEXT: FileVersion: 1 -# CHECKEXE-NEXT: OS/ABI: SystemV (0x0) -# CHECKEXE-NEXT: ABIVersion: 0 -# CHECKEXE-NEXT: Unused: (00 00 00 00 00 00 00) -# CHECKEXE-NEXT: } -# CHECKEXE-NEXT: Type: Executable -# CHECKEXE-NEXT: Machine: EM_X86_64 -# CHECKEXE-NEXT: Version: 1 -# CHECKEXE-NEXT: Entry: 0x11000 -# CHECKEXE-NEXT: ProgramHeaderOffset: 0x40 -# CHECKEXE-NEXT: SectionHeaderOffset: 0x11E8 -# CHECKEXE-NEXT: Flags [ -# CHECKEXE-NEXT: ] -# CHECKEXE-NEXT: HeaderSize: 64 -# CHECKEXE-NEXT: ProgramHeaderEntrySize: 56 -# CHECKEXE-NEXT: ProgramHeaderCount: 5 -# CHECKEXE-NEXT: SectionHeaderEntrySize: 64 -# CHECKEXE-NEXT: SectionHeaderCount: 6 -# CHECKEXE-NEXT: StringTableSectionIndex: 4 -# CHECKEXE-NEXT: } +# EXE: Format: ELF64-x86-64 +# EXE-NEXT: Arch: x86_64 +# EXE-NEXT: AddressSize: 64bit +# EXE-NEXT: LoadName: +# EXE-NEXT: ElfHeader { +# EXE-NEXT: Ident { +# EXE-NEXT: Magic: (7F 45 4C 46) +# EXE-NEXT: Class: 64-bit +# EXE-NEXT: DataEncoding: LittleEndian +# EXE-NEXT: FileVersion: 1 +# EXE-NEXT: OS/ABI: SystemV (0x0) +# EXE-NEXT: ABIVersion: 0 +# EXE-NEXT: Unused: (00 00 00 00 00 00 00) +# EXE-NEXT: } +# EXE-NEXT: Type: Executable +# EXE-NEXT: Machine: EM_X86_64 +# EXE-NEXT: Version: 1 +# EXE-NEXT: Entry: 0x11000 +# EXE-NEXT: ProgramHeaderOffset: 0x40 +# EXE-NEXT: SectionHeaderOffset: 0x11E8 +# EXE-NEXT: Flags [ +# EXE-NEXT: ] +# EXE-NEXT: HeaderSize: 64 +# EXE-NEXT: ProgramHeaderEntrySize: 56 +# EXE-NEXT: ProgramHeaderCount: 5 +# EXE-NEXT: SectionHeaderEntrySize: 64 +# EXE-NEXT: SectionHeaderCount: 6 +# EXE-NEXT: StringTableSectionIndex: 4 +# EXE-NEXT: } .text .type x,@object