[PATCH] D39959: [ELF] - Allow merging of strings sections for -relocatable output.
Rafael Avila de Espindola via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 13 08:44:52 PST 2017
What is it that prevent us from just using elf::mergeSections for -r?
If I remember correctly, we don't want to merge input strings when that
would reduce what the final link can do (--gc-sections for example). But
with SHF_MERGE, they should always be fine to merge.
Cheers,
Rafael
George Rimar via Phabricator <reviews at reviews.llvm.org> writes:
> grimar created this revision.
> Herald added subscribers: arichardson, aprantl, emaste.
>
> This is PR35223.
>
> r317406 stopped merging SHF_MERGE sections when -r is given.
> Previously we used Alignment, Flags and section Name together to
> generate a complex key for merging sections. For -r case all 3 were used,
> but for regular case we merged sections by name only for a long time
> and r317406 changed behavior to merge sections by name for all outputs,
> that allowed to simplify code and sped up linker a bit.
>
> But above broke -relocatable output in sence that tools like dwarfdump (both gnu
> and llvm one) expects to see single .debug_str section in output.
> After the r317406 we started producing unique output section for each input
> and tools are upset.
>
> I suggest to allow relocatable output to merge SHF_MERGE strings sections.
> In case when input sections has different sh_entsize, I think we can just drop
> the SHF_MERGE flag and merge them. That looks consistent with what ld.bfd
> do and should not be an issue, because I believe normally string sections
> always have sh_entsize = 1. llvm-mc even ignores any values explicitly set for .debug_str
> sh_entsize and renders 1 to output, though gas allows different values.
>
>
> https://reviews.llvm.org/D39959
>
> Files:
> ELF/LinkerScript.cpp
> test/ELF/relocatable-mergeable.s
>
> Index: test/ELF/relocatable-mergeable.s
> ===================================================================
> --- test/ELF/relocatable-mergeable.s
> +++ test/ELF/relocatable-mergeable.s
> @@ -0,0 +1,67 @@
> +# REQUIRES: x86
> +
> +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1
> +# RUN: ld.lld %t1 -o %t2 -r
> +# RUN: llvm-readobj -sections %t2 | FileCheck %s
> +
> +## Check we merged 2 .strings sections together and dropped SHF_MERGE flag
> +## because they have different sh_entsize. Check we created separate output
> +## section for each non-string mergeable input and keeped SHF_MERGE.
> +
> +# CHECK: Section {
> +# CHECK: Index:
> +# CHECK: Name: .strings
> +# CHECK-NEXT: Type: SHT_PROGBITS
> +# CHECK-NEXT: Flags [
> +# CHECK-NEXT: SHF_STRINGS
> +# CHECK-NEXT: ]
> +# CHECK-NEXT: Address:
> +# CHECK-NEXT: Offset:
> +# CHECK-NEXT: Size: 8
> +# CHECK-NEXT: Link:
> +# CHECK-NEXT: Info:
> +# CHECK-NEXT: AddressAlignment:
> +# CHECK-NEXT: EntrySize: 3
> +# CHECK-NEXT: }
> +# CHECK-NEXT: Section {
> +# CHECK-NEXT: Index:
> +# CHECK-NEXT: Name: .nonstrings
> +# CHECK-NEXT: Type: SHT_PROGBITS
> +# CHECK-NEXT: Flags [
> +# CHECK-NEXT: SHF_MERGE
> +# CHECK-NEXT: ]
> +# CHECK-NEXT: Address:
> +# CHECK-NEXT: Offset:
> +# CHECK-NEXT: Size: 4
> +# CHECK-NEXT: Link:
> +# CHECK-NEXT: Info:
> +# CHECK-NEXT: AddressAlignment:
> +# CHECK-NEXT: EntrySize: 2
> +# CHECK-NEXT: }
> +# CHECK-NEXT: Section {
> +# CHECK-NEXT: Index:
> +# CHECK-NEXT: Name: .nonstrings
> +# CHECK-NEXT: Type: SHT_PROGBITS
> +# CHECK-NEXT: Flags [
> +# CHECK-NEXT: SHF_MERGE
> +# CHECK-NEXT: ]
> +# CHECK-NEXT: Address:
> +# CHECK-NEXT: Offset:
> +# CHECK-NEXT: Size: 4
> +# CHECK-NEXT: Link:
> +# CHECK-NEXT: Info:
> +# CHECK-NEXT: AddressAlignment:
> +# CHECK-NEXT: EntrySize: 4
> +# CHECK-NEXT: }
> +
> +.section .strings,"MS", at progbits,1,unique,10
> +.asciz "foo"
> +
> +.section .nonstrings,"M", at progbits,2,unique,20
> +.long 11
> +
> +.section .strings,"MS", at progbits,3,unique,30
> +.asciz "bar"
> +
> +.section .nonstrings,"M", at progbits,4,unique,40
> +.long 22
> Index: ELF/LinkerScript.cpp
> ===================================================================
> --- ELF/LinkerScript.cpp
> +++ ELF/LinkerScript.cpp
> @@ -427,6 +427,16 @@
> return nullptr;
> }
>
> +static void addMergeableStringSection(OutputSection *Sec,
> + InputSectionBase *IS) {
> + assert(Config->Relocatable);
> + if (Sec->Entsize != IS->Entsize)
> + Sec->Flags &= ~SHF_MERGE;
> + if (!(Sec->Flags & SHF_MERGE))
> + IS->Flags &= ~SHF_MERGE;
> + Sec->addSection(cast<InputSection>(IS));
> +}
> +
> static OutputSection *createSection(InputSectionBase *IS,
> StringRef OutsecName) {
> OutputSection *Sec = Script->createOutputSection(OutsecName, "<internal>");
> @@ -466,11 +476,23 @@
> return Out->RelocationSection;
> }
>
> - // When control reaches here, mergeable sections have already been
> - // merged except the -r case. If that's the case, we do not combine them
> - // and let final link to handle this optimization.
> - if (Config->Relocatable && (IS->Flags & SHF_MERGE))
> - return createSection(IS, OutsecName);
> + // When control reaches here, mergeable sections have already been merged
> + // except the -r case. If that's the case, we do not really want to care about
> + // merging sections, leaving this task for final link. But unfortunately we
> + // still need to do that for .debug_str sections, because different tools
> + // like dwarfdump expects to see single instance in the output. To handle this
> + // case we merge string sections and just drop SHF_MERGE optimization flag if
> + // entry sizes of input and output sections are different. That normally
> + // should not happen as entry size usually is always 1 for strings sections.
> + if (Config->Relocatable && (IS->Flags & SHF_MERGE)) {
> + OutputSection *&Sec = Map[OutsecName];
> + if (!Sec || !(IS->Flags & SHF_STRINGS)) {
> + Sec = createSection(IS, OutsecName);
> + return Sec;
> + }
> + addMergeableStringSection(Sec, IS);
> + return nullptr;
> + }
>
> // The ELF spec just says
> // ----------------------------------------------------------------
More information about the llvm-commits
mailing list