[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