From a7471795ae391a71cd66213300a173bcea9fd672 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Thu, 13 Aug 2015 17:04:50 +0000 Subject: [PATCH] Take name, type and flags in consideration when concatenating sections. This is mandated by the ELF spec. llvm-svn: 244911 --- lld/ELF/Writer.cpp | 36 ++++++++++++++++++++++++++++-- lld/test/elf2/string-table.s | 43 ++++++++++++++++++++++++++---------- 2 files changed, 65 insertions(+), 14 deletions(-) diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 77093cfec5bd..f598dae9bef0 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -63,6 +63,7 @@ private: template class Writer { public: typedef typename llvm::object::ELFFile::uintX_t uintX_t; + typedef typename llvm::object::ELFFile::Elf_Shdr Elf_Shdr; Writer(SymbolTable *T) : Symtab(T) {} void run(); @@ -140,13 +141,44 @@ template void OutputSection::writeHeaderTo(Elf_Shdr *SHdr) { *SHdr = Header; } +namespace { +template struct SectionKey { + typedef typename std::conditional::type uintX_t; + StringRef Name; + uint32_t sh_type; + uintX_t sh_flags; +}; +} +namespace llvm { +template struct DenseMapInfo> { + static SectionKey getEmptyKey() { + return SectionKey{DenseMapInfo::getEmptyKey(), 0, 0}; + } + static SectionKey getTombstoneKey() { + return SectionKey{DenseMapInfo::getTombstoneKey(), 0, + 0}; + } + static unsigned getHashValue(const SectionKey &Val) { + return hash_combine(Val.Name, Val.sh_type, Val.sh_flags); + } + static bool isEqual(const SectionKey &LHS, + const SectionKey &RHS) { + return DenseMapInfo::isEqual(LHS.Name, RHS.Name) && + LHS.sh_type == RHS.sh_type && LHS.sh_flags == RHS.sh_flags; + } +}; +} + // Create output section objects and add them to OutputSections. template void Writer::createSections() { - SmallDenseMap *> Map; + SmallDenseMap, OutputSection *> Map; for (std::unique_ptr &FileB : Symtab->ObjectFiles) { auto &File = cast>(*FileB); for (SectionChunk *C : File.getChunks()) { - OutputSection *&Sec = Map[C->getSectionName()]; + const Elf_Shdr *H = C->getSectionHdr(); + SectionKey Key{C->getSectionName(), H->sh_type, + H->sh_flags}; + OutputSection *&Sec = Map[Key]; if (!Sec) { Sec = new (CAlloc.Allocate()) OutputSection(C->getSectionName()); OutputSections.push_back(Sec); diff --git a/lld/test/elf2/string-table.s b/lld/test/elf2/string-table.s index 81b740d31d3a..80e35ae59cad 100644 --- a/lld/test/elf2/string-table.s +++ b/lld/test/elf2/string-table.s @@ -6,28 +6,47 @@ .global _start _start: -.section foobar +.section foobar,"",@progbits,unique,1 +.section foobar,"T",@progbits,unique,2 +.section foobar,"",@nobits,unique,3 +.section foobar,"",@nobits,unique,4 + .section bar, "a" // Both sections are in the output and that the alloc section is first: // CHECK: Name: bar -// CHECK-NEXT: Type: SHT_PROGBITS -// CHECK-NEXT: Flags [ -// CHECK-NEXT: SHF_ALLOC -// CHECK-NEXT: ] -// CHECK-NEXT: Address: 0x1000 +// CHECK-NEXT: Type: SHT_PROGBITS +// CHECK-NEXT: Flags [ +// CHECK-NEXT: SHF_ALLOC +// CHECK-NEXT: ] +// CHECK-NEXT: Address: 0x1000 // CHECK: Name: foobar -// CHECK-NEXT: Type: SHT_PROGBITS -// CHECK-NEXT: Flags [ -// CHECK-NEXT: ] -// CHECK-NEXT: Address: 0x0 +// CHECK-NEXT: Type: SHT_PROGBITS +// CHECK-NEXT: Flags [ +// CHECK-NEXT: ] +// CHECK-NEXT: Address: 0x0 + +// CHECK: Name: foobar +// CHECK-NEXT: Type: SHT_PROGBITS +// CHECK-NEXT: Flags [ +// CHECK-NEXT: SHF_TLS +// CHECK-NEXT: ] +// CHECK-NEXT: Address: 0x0 + +// CHECK: Name: foobar +// CHECK-NEXT: Type: SHT_NOBITS +// CHECK-NEXT: Flags [ +// CHECK-NEXT: ] +// CHECK-NEXT: Address: 0x0 + +// CHECK-NOT: Name: foobar // Test that the sting "bar" is merged into "foobar" // CHECK: Section { -// CHECK: Index: 6 -// CHECK-NEXT: Name: .strtab +// CHECK: Index: +// CHECK: Name: .strtab // CHECK-NEXT: Type: SHT_STRTAB (0x3) // CHECK-NEXT: Flags [ (0x0) // CHECK-NEXT: ]