[PATCH] D29324: [ELF] - Allow to combine sections of type SHT_NOTE with different attributes.

Rafael Avila de Espindola via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 31 06:57:56 PST 2017


Can you confirm what gold and bfd do on this case? They force the non
allocatable section into being allocated?


George Rimar via Phabricator <reviews at reviews.llvm.org> writes:

> grimar created this revision.
>
> One of linux scripts (arch/x86/kernel/vmlinux.lds) has next line:
>
> .notes : AT(ADDR(.notes) - 0xffffffff80000000) { __start_notes = .; *(.note.*) __stop_notes = .; } :text :note
>
> when built with --build-id, we create allocatable .note.gnu.build-id, what is fine.
> And .note.* section script wants to combine is non-allocatable and we error out.
>
> Patch allows combining note sections with different flags.
>
>
> https://reviews.llvm.org/D29324
>
> Files:
>   ELF/OutputSections.cpp
>   test/ELF/incompatible-section-flags-notes.s
>
>
> Index: test/ELF/incompatible-section-flags-notes.s
> ===================================================================
> --- test/ELF/incompatible-section-flags-notes.s
> +++ test/ELF/incompatible-section-flags-notes.s
> @@ -0,0 +1,8 @@
> +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
> +# RUN: echo "SECTIONS { .notes : { *(.note.*) } }" > %t.script
> +# RUN: ld.lld --script %t.script --build-id %t.o -o %t
> +
> +## Check that synthetic allocatable note section ".note.gnu.build-id"
> +## links fine with non-allocatable .note.1
> +.section .note.1, "", @note
> +.quad 0
> Index: ELF/OutputSections.cpp
> ===================================================================
> --- ELF/OutputSections.cpp
> +++ ELF/OutputSections.cpp
> @@ -640,6 +640,25 @@
>    return Flags & (SHF_ALLOC | SHF_TLS);
>  }
>  
> +template <class ELFT>
> +static void checkFlagsCompatibility(OutputSectionBase *OS,
> +                                    InputSectionBase<ELFT> *C) {
> +  uint64_t OutSecFlags = getIncompatibleFlags(OS->Flags);
> +  uint64_t Flags = getIncompatibleFlags(C->Flags);
> +  if (OutSecFlags == Flags)
> +    return;
> +
> +  // If flags incompatible, we still allow to combine them
> +  // if sections is a type of SHT_NOTE. As an example
> +  // some scripts from linux kernel combines allocatable
> +  // and non-allocatable SHT_NOTE section together.
> +  if (C->Type == SHT_NOTE)
> +    return;
> +
> +  error("Section has flags incompatible with others with the same name " +
> +        toString(C));
> +}
> +
>  // We allow sections of types listed below to merged into a
>  // single progbits section. This is typically done by linker
>  // scripts. Merging nobits and progbits will force disk space
> @@ -659,9 +678,7 @@
>    uintX_t Flags = getOutFlags(C);
>    OutputSectionBase *&Sec = Map[Key];
>    if (Sec) {
> -    if (getIncompatibleFlags(Sec->Flags) != getIncompatibleFlags(C->Flags))
> -      error("Section has flags incompatible with others with the same name " +
> -            toString(C));
> +    checkFlagsCompatibility(Sec, C);
>      if (Sec->Type != C->Type) {
>        if (canMergeToProgbits(Sec->Type) && canMergeToProgbits(C->Type))
>          Sec->Type = SHT_PROGBITS;
>
>
> Index: test/ELF/incompatible-section-flags-notes.s
> ===================================================================
> --- test/ELF/incompatible-section-flags-notes.s
> +++ test/ELF/incompatible-section-flags-notes.s
> @@ -0,0 +1,8 @@
> +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
> +# RUN: echo "SECTIONS { .notes : { *(.note.*) } }" > %t.script
> +# RUN: ld.lld --script %t.script --build-id %t.o -o %t
> +
> +## Check that synthetic allocatable note section ".note.gnu.build-id"
> +## links fine with non-allocatable .note.1
> +.section .note.1, "", @note
> +.quad 0
> Index: ELF/OutputSections.cpp
> ===================================================================
> --- ELF/OutputSections.cpp
> +++ ELF/OutputSections.cpp
> @@ -640,6 +640,25 @@
>    return Flags & (SHF_ALLOC | SHF_TLS);
>  }
>  
> +template <class ELFT>
> +static void checkFlagsCompatibility(OutputSectionBase *OS,
> +                                    InputSectionBase<ELFT> *C) {
> +  uint64_t OutSecFlags = getIncompatibleFlags(OS->Flags);
> +  uint64_t Flags = getIncompatibleFlags(C->Flags);
> +  if (OutSecFlags == Flags)
> +    return;
> +
> +  // If flags incompatible, we still allow to combine them
> +  // if sections is a type of SHT_NOTE. As an example
> +  // some scripts from linux kernel combines allocatable
> +  // and non-allocatable SHT_NOTE section together.
> +  if (C->Type == SHT_NOTE)
> +    return;
> +
> +  error("Section has flags incompatible with others with the same name " +
> +        toString(C));
> +}
> +
>  // We allow sections of types listed below to merged into a
>  // single progbits section. This is typically done by linker
>  // scripts. Merging nobits and progbits will force disk space
> @@ -659,9 +678,7 @@
>    uintX_t Flags = getOutFlags(C);
>    OutputSectionBase *&Sec = Map[Key];
>    if (Sec) {
> -    if (getIncompatibleFlags(Sec->Flags) != getIncompatibleFlags(C->Flags))
> -      error("Section has flags incompatible with others with the same name " +
> -            toString(C));
> +    checkFlagsCompatibility(Sec, C);
>      if (Sec->Type != C->Type) {
>        if (canMergeToProgbits(Sec->Type) && canMergeToProgbits(C->Type))
>          Sec->Type = SHT_PROGBITS;


More information about the llvm-commits mailing list