From 35aad41c1be05217281675373193d3512d650764 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Tue, 27 Mar 2018 17:09:23 +0000 Subject: [PATCH] Force SHF_MERGE optimizations with -r. Some tools (dwarfdump for example) get confused by the current -O0 -r output since it has multiple copies of .debug_str. We cannot just merge sections with the same name as they can have different sh_entsize. We could have duplicated logic for merging sections based on name and sh_entsize, but it seems better to just use the existing logic by enabling optimizations. llvm-svn: 328640 --- lld/ELF/InputFiles.cpp | 16 +++++++++--- lld/test/ELF/merge-reloc-O0.s | 48 +++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 lld/test/ELF/merge-reloc-O0.s diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 7f676258cf64..c3cdb0996cdc 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -312,9 +312,19 @@ ObjFile::getShtGroupEntries(const Elf_Shdr &Sec) { } template bool ObjFile::shouldMerge(const Elf_Shdr &Sec) { - // We don't merge sections if -O0 (default is -O1). This makes sometimes - // the linker significantly faster, although the output will be bigger. - if (Config->Optimize == 0) + // On a regular link we don't merge sections if -O0 (default is -O1). This + // sometimes makes the linker significantly faster, although the output will + // be bigger. + // + // Doing the same for -r would create a problem as it would combine sections + // with different sh_entsize. One option would be to just copy every SHF_MERGE + // section as is to the output. While this would produce a valid ELF file with + // usable SHF_MERGE sections, tools like (llvm-)?dwarfdump get confused when + // they see two .debug_str. We could have separate logic for combining + // SHF_MERGE sections based both on their name and sh_entsize, but that seems + // to be more trouble than it is worth. Instead, we just use the regular (-O1) + // logic for -r. + if (Config->Optimize == 0 && !Config->Relocatable) return false; // A mergeable section with size 0 is useless because they don't have diff --git a/lld/test/ELF/merge-reloc-O0.s b/lld/test/ELF/merge-reloc-O0.s new file mode 100644 index 000000000000..daf5c34b6c0a --- /dev/null +++ b/lld/test/ELF/merge-reloc-O0.s @@ -0,0 +1,48 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: ld.lld %t.o -r -o %t2.o -O0 +# RUN: llvm-readobj -s -section-data %t2.o | FileCheck %s + +# We combine just the sections with the same name and sh_entsize. + +# CHECK: Name: .foo +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_MERGE +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 16 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: 8 +# CHECK-NEXT: EntrySize: 8 +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: 41000000 00000000 42000000 00000000 +# CHECK-NEXT: ) + +# CHECK: Name: .foo +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_MERGE +# CHECK-NEXT: ] +# CHECK-NEXT: Address: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: 4 +# CHECK-NEXT: EntrySize: 4 +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: 41000000 42000000 +# CHECK-NEXT: ) + + .section .foo, "aM",@progbits,8,unique,0 + .quad 0x41 + .section .foo, "aM",@progbits,8,unique,1 + .quad 0x42 + .section .foo, "aM",@progbits,4,unique,2 + .long 0x41 + .long 0x42 -- GitLab