Index: lld/trunk/ELF/OutputSections.cpp =================================================================== --- lld/trunk/ELF/OutputSections.cpp +++ lld/trunk/ELF/OutputSections.cpp @@ -640,6 +640,18 @@ return Flags & (SHF_ALLOC | SHF_TLS); } +// 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 +// to be allocated for nobits sections. Other ones don't require +// any special treatment on top of progbits, so there doesn't +// seem to be a harm in merging them. +static bool canMergeToProgbits(unsigned Type) { + return Type == SHT_NOBITS || Type == SHT_PROGBITS || Type == SHT_INIT_ARRAY || + Type == SHT_PREINIT_ARRAY || Type == SHT_FINI_ARRAY || + Type == SHT_NOTE; +} + template std::pair OutputSectionFactory::create(const SectionKey &Key, @@ -650,14 +662,13 @@ if (getIncompatibleFlags(Sec->Flags) != getIncompatibleFlags(C->Flags)) error("Section has flags incompatible with others with the same name " + toString(C)); - // Convert notbits to progbits if they are mixed. This happens is some - // linker scripts. - if (Sec->Type == SHT_NOBITS && C->Type == SHT_PROGBITS) - Sec->Type = SHT_PROGBITS; - if (Sec->Type != C->Type && - !(Sec->Type == SHT_PROGBITS && C->Type == SHT_NOBITS)) - error("Section has different type from others with the same name " + - toString(C)); + if (Sec->Type != C->Type) { + if (canMergeToProgbits(Sec->Type) && canMergeToProgbits(C->Type)) + Sec->Type = SHT_PROGBITS; + else + error("Section has different type from others with the same name " + + toString(C)); + } Sec->Flags |= Flags; return {Sec, false}; } Index: lld/trunk/test/ELF/compatible-section-types.s =================================================================== --- lld/trunk/test/ELF/compatible-section-types.s +++ lld/trunk/test/ELF/compatible-section-types.s @@ -0,0 +1,20 @@ +// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +// RUN: ld.lld -shared %t.o -o %t +// RUN: llvm-objdump -section-headers %t | FileCheck %s + +// CHECK: .foo {{0*}}28 + +.section .foo, "aw", @progbits, unique, 1 +.quad 0 + +.section .foo, "aw", @init_array, unique, 2 +.quad 0 + +.section .foo, "aw", @preinit_array, unique, 3 +.quad 0 + +.section .foo, "aw", @fini_array, unique, 4 +.quad 0 + +.section .foo, "aw", @note, unique, 5 +.quad 0 Index: lld/trunk/test/ELF/incompatible-section-types.s =================================================================== --- lld/trunk/test/ELF/incompatible-section-types.s +++ lld/trunk/test/ELF/incompatible-section-types.s @@ -1,10 +0,0 @@ -// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o -// RUN: not ld.lld -shared %t.o -o %t 2>&1 | FileCheck %s - -// CHECK: error: Section has different type from others with the same name {{.*}}incompatible-section-types.s.tmp.o:(.foo) - -.section .foo, "aw", @progbits, unique, 1 -.quad 0 - -.section .foo, "aw", @init_array, unique, 2 -.quad 0