From 8039dae26d4f0523c19d3f17a8b19faa7c9d5141 Mon Sep 17 00:00:00 2001 From: "Michael J. Spencer" Date: Wed, 29 Jul 2015 00:30:10 +0000 Subject: [PATCH] [ELF2] Emit section table. llvm-svn: 243506 --- lld/ELF/Chunks.h | 10 +++++++ lld/ELF/Writer.cpp | 35 ++++++++++++++++++++----- lld/ELF/Writer.h | 6 ++++- lld/test/elf2/basic.test | 68 ++++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 106 insertions(+), 13 deletions(-) diff --git a/lld/ELF/Chunks.h b/lld/ELF/Chunks.h index 3080502..836a980 100644 --- a/lld/ELF/Chunks.h +++ b/lld/ELF/Chunks.h @@ -26,6 +26,8 @@ class OutputSection; // doesn't even have actual data (if common or bss). class Chunk { public: + enum Kind { SectionKind, OtherKind }; + Kind kind() const { return ChunkKind; } virtual ~Chunk() = default; // Returns the size of this chunk (even if this is a common or BSS.) @@ -54,6 +56,9 @@ public: OutputSection *getOutputSection() { return Out; } protected: + Chunk(Kind K = OtherKind) : ChunkKind(K) {} + const Kind ChunkKind; + // The VA of this chunk in the output. The writer sets a value. uint64_t VA = 0; @@ -78,6 +83,11 @@ public: size_t getSize() const override { return Header->sh_size; } void writeTo(uint8_t *Buf) override; StringRef getSectionName() const override { return SectionName; } + const Elf_Shdr *getSectionHdr() const { return Header; } + + static bool classof(const Chunk *C) { + return C->kind() == SectionKind; + } private: // A file this chunk was created from. diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index d11378f..615a5ef 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -57,6 +57,22 @@ void OutputSection::addChunk(Chunk *C) { C->setFileOff(Off); Off += C->getSize(); Header.sh_size = Off; + if (auto SC = dyn_cast>(C)) + Header.sh_type = SC->getSectionHdr()->sh_type; +} + +template +void OutputSection::writeHeaderTo(Elf_Shdr_Impl *SHdr) { + SHdr->sh_name = Header.sh_name; + SHdr->sh_type = Header.sh_type; + SHdr->sh_flags = Header.sh_flags; + SHdr->sh_addr = Header.sh_addr; + SHdr->sh_offset = Header.sh_offset; + SHdr->sh_size = Header.sh_size; + SHdr->sh_link = Header.sh_link; + SHdr->sh_info = Header.sh_info; + SHdr->sh_addralign = Header.sh_addralign; + SHdr->sh_entsize = Header.sh_entsize; } // Create output section objects and add them to OutputSections. @@ -75,10 +91,7 @@ template void Writer::createSections() { // Visits all sections to assign incremental, non-overlapping RVAs and // file offsets. template void Writer::assignAddresses() { - SizeOfHeaders = RoundUpToAlignment(sizeof(Elf_Ehdr_Impl) + - sizeof(Elf_Shdr_Impl) * - OutputSections.size(), - PageSize); + SizeOfHeaders = RoundUpToAlignment(sizeof(Elf_Ehdr_Impl), PageSize); uint64_t VA = 0x1000; // The first page is kept unmapped. uint64_t FileOff = SizeOfHeaders; for (OutputSection *Sec : OutputSections) { @@ -87,7 +100,9 @@ template void Writer::assignAddresses() { VA += RoundUpToAlignment(Sec->getSize(), PageSize); FileOff += RoundUpToAlignment(Sec->getSize(), 8); } - SizeOfImage = SizeOfHeaders + RoundUpToAlignment(VA - 0x1000, PageSize); + // Add space for section headers. + SectionHeaderOff = FileOff; + FileOff += (OutputSections.size() + 1) * sizeof(Elf_Shdr_Impl); FileSize = SizeOfHeaders + RoundUpToAlignment(FileOff - SizeOfHeaders, 8); } @@ -108,12 +123,12 @@ template void Writer::writeHeader() { EHdr->e_version = EV_CURRENT; EHdr->e_entry = 0x401000; EHdr->e_phoff = sizeof(Elf_Ehdr_Impl); - EHdr->e_shoff = 0; + EHdr->e_shoff = SectionHeaderOff; EHdr->e_ehsize = sizeof(Elf_Ehdr_Impl); EHdr->e_phentsize = sizeof(Elf_Phdr_Impl); EHdr->e_phnum = 1; EHdr->e_shentsize = sizeof(Elf_Shdr_Impl); - EHdr->e_shnum = 0; + EHdr->e_shnum = OutputSections.size() + 1; EHdr->e_shstrndx = 0; auto PHdrs = reinterpret_cast *>(Buf + EHdr->e_phoff); @@ -125,6 +140,12 @@ template void Writer::writeHeader() { PHdrs->p_filesz = FileSize; PHdrs->p_memsz = FileSize; PHdrs->p_align = 0x4000; + + auto SHdrs = reinterpret_cast *>(Buf + EHdr->e_shoff); + // First entry is null. + ++SHdrs; + for (OutputSection *Sec : OutputSections) + Sec->writeHeaderTo(SHdrs++); } template void Writer::openFile(StringRef Path) { diff --git a/lld/ELF/Writer.h b/lld/ELF/Writer.h index f71c80f..55538eb 100644 --- a/lld/ELF/Writer.h +++ b/lld/ELF/Writer.h @@ -27,6 +27,8 @@ public: void setFileOffset(uint64_t); void addChunk(Chunk *C); std::vector &getChunks() { return Chunks; } + template + void writeHeaderTo(llvm::object::Elf_Shdr_Impl *SHdr); // Returns the size of the section in the output file. uint64_t getSize() { return Header.sh_size; } @@ -40,6 +42,8 @@ private: // The writer writes a SymbolTable result to a file. template class Writer { public: + typedef typename llvm::object::ELFFile::uintX_t uintX_t; + explicit Writer(SymbolTable *T); ~Writer(); void write(StringRef Path); @@ -57,8 +61,8 @@ private: std::vector OutputSections; uint64_t FileSize; - uint64_t SizeOfImage; uint64_t SizeOfHeaders; + uintX_t SectionHeaderOff; std::vector> Chunks; }; diff --git a/lld/test/elf2/basic.test b/lld/test/elf2/basic.test index 39fb40f..8eec081 100644 --- a/lld/test/elf2/basic.test +++ b/lld/test/elf2/basic.test @@ -1,6 +1,6 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t # RUN: lld -flavor gnu2 %t -o %t2 -# RUN: llvm-readobj -file-headers -program-headers %t2 | FileCheck %s +# RUN: llvm-readobj -file-headers -sections -program-headers %t2 | FileCheck %s # REQUIRES: x86 # exits with return code 42 on linux @@ -25,24 +25,82 @@ _start: # CHECK-NEXT: Version: 1 # CHECK-NEXT: Entry: 0x401000 # CHECK-NEXT: ProgramHeaderOffset: 0x40 -# CHECK-NEXT: SectionHeaderOffset: 0x0 +# CHECK-NEXT: SectionHeaderOffset: 0x1010 # CHECK-NEXT: Flags [ (0x0) # CHECK-NEXT: ] # CHECK-NEXT: HeaderSize: 64 # CHECK-NEXT: ProgramHeaderEntrySize: 56 # CHECK-NEXT: ProgramHeaderCount: 1 # CHECK-NEXT: SectionHeaderEntrySize: 64 -# CHECK-NEXT: SectionHeaderCount: 0 +# CHECK-NEXT: SectionHeaderCount: 4 # CHECK-NEXT: StringTableSectionIndex: 0 # CHECK-NEXT: } +# CHECK-NEXT: Sections [ +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: 0 +# CHECK-NEXT: Name: (0) +# CHECK-NEXT: Type: SHT_NULL (0x0) +# CHECK-NEXT: Flags [ (0x0) +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x0 +# CHECK-NEXT: Offset: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Link: 0 +# CHECK-NEXT: Info: 0 +# CHECK-NEXT: AddressAlignment: 0 +# CHECK-NEXT: EntrySize: 0 +# CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: 1 +# CHECK-NEXT: Name: (0) +# CHECK-NEXT: Type: SHT_NULL (0x0) +# CHECK-NEXT: Flags [ (0x0) +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x1000 +# CHECK-NEXT: Offset: 0x1000 +# CHECK-NEXT: Size: 16 +# CHECK-NEXT: Link: 0 +# CHECK-NEXT: Info: 0 +# CHECK-NEXT: AddressAlignment: 0 +# CHECK-NEXT: EntrySize: 0 +# CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: 2 +# CHECK-NEXT: Name: (0) +# CHECK-NEXT: Type: SHT_NULL (0x0) +# CHECK-NEXT: Flags [ (0x0) +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x2000 +# CHECK-NEXT: Offset: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Link: 0 +# CHECK-NEXT: Info: 0 +# CHECK-NEXT: AddressAlignment: 0 +# CHECK-NEXT: EntrySize: 0 +# CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: 3 +# CHECK-NEXT: Name: (0) +# CHECK-NEXT: Type: SHT_NULL (0x0) +# CHECK-NEXT: Flags [ (0x0) +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x2000 +# CHECK-NEXT: Offset: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Link: 0 +# CHECK-NEXT: Info: 0 +# CHECK-NEXT: AddressAlignment: 0 +# CHECK-NEXT: EntrySize: 0 +# CHECK-NEXT: } +# CHECK-NEXT: ] # CHECK-NEXT: ProgramHeaders [ # CHECK-NEXT: ProgramHeader { # CHECK-NEXT: Type: PT_LOAD (0x1) # CHECK-NEXT: Offset: 0x0 # CHECK-NEXT: VirtualAddress: 0x400000 # CHECK-NEXT: PhysicalAddress: 0x400000 -# CHECK-NEXT: FileSize: 4112 -# CHECK-NEXT: MemSize: 4112 +# CHECK-NEXT: FileSize: 4368 +# CHECK-NEXT: MemSize: 4368 # CHECK-NEXT: Flags [ (0x5) # CHECK-NEXT: PF_R (0x4) # CHECK-NEXT: PF_X (0x1) -- 2.7.4