[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 08:20:59 PST 2017


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

So, this really looks like a bug in the kernel. Even some of its flags
are marked alloc.

Can you try changing include/linux/elfnote.h to have

#define ELFNOTE(name, type, desc)               \
        ELFNOTE_START(name, type, "a")          \
                desc                    ;       \
        ELFNOTE_END

and see if that fixes the problem?

Even better would be for the macro to use "linux_notes" instead of
".note.name". That way the linker automatically concatenates the notes
and creates the symbols for accessing them.

Cheers,
Rafael

> 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