// 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.)
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;
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.
C->setFileOff(Off);
Off += C->getSize();
Header.sh_size = Off;
+ if (auto SC = dyn_cast<SectionChunk<ELF64LE>>(C))
+ Header.sh_type = SC->getSectionHdr()->sh_type;
+}
+
+template <class ELFT>
+void OutputSection::writeHeaderTo(Elf_Shdr_Impl<ELFT> *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.
// Visits all sections to assign incremental, non-overlapping RVAs and
// file offsets.
template <class ELFT> void Writer<ELFT>::assignAddresses() {
- SizeOfHeaders = RoundUpToAlignment(sizeof(Elf_Ehdr_Impl<ELFT>) +
- sizeof(Elf_Shdr_Impl<ELFT>) *
- OutputSections.size(),
- PageSize);
+ SizeOfHeaders = RoundUpToAlignment(sizeof(Elf_Ehdr_Impl<ELFT>), PageSize);
uint64_t VA = 0x1000; // The first page is kept unmapped.
uint64_t FileOff = SizeOfHeaders;
for (OutputSection *Sec : OutputSections) {
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<ELFT>);
FileSize = SizeOfHeaders + RoundUpToAlignment(FileOff - SizeOfHeaders, 8);
}
EHdr->e_version = EV_CURRENT;
EHdr->e_entry = 0x401000;
EHdr->e_phoff = sizeof(Elf_Ehdr_Impl<ELFT>);
- EHdr->e_shoff = 0;
+ EHdr->e_shoff = SectionHeaderOff;
EHdr->e_ehsize = sizeof(Elf_Ehdr_Impl<ELFT>);
EHdr->e_phentsize = sizeof(Elf_Phdr_Impl<ELFT>);
EHdr->e_phnum = 1;
EHdr->e_shentsize = sizeof(Elf_Shdr_Impl<ELFT>);
- EHdr->e_shnum = 0;
+ EHdr->e_shnum = OutputSections.size() + 1;
EHdr->e_shstrndx = 0;
auto PHdrs = reinterpret_cast<Elf_Phdr_Impl<ELFT> *>(Buf + EHdr->e_phoff);
PHdrs->p_filesz = FileSize;
PHdrs->p_memsz = FileSize;
PHdrs->p_align = 0x4000;
+
+ auto SHdrs = reinterpret_cast<Elf_Shdr_Impl<ELFT> *>(Buf + EHdr->e_shoff);
+ // First entry is null.
+ ++SHdrs;
+ for (OutputSection *Sec : OutputSections)
+ Sec->writeHeaderTo<ELFT>(SHdrs++);
}
template <class ELFT> void Writer<ELFT>::openFile(StringRef Path) {
void setFileOffset(uint64_t);
void addChunk(Chunk *C);
std::vector<Chunk *> &getChunks() { return Chunks; }
+ template <class ELFT>
+ void writeHeaderTo(llvm::object::Elf_Shdr_Impl<ELFT> *SHdr);
// Returns the size of the section in the output file.
uint64_t getSize() { return Header.sh_size; }
// The writer writes a SymbolTable result to a file.
template <class ELFT> class Writer {
public:
+ typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
+
explicit Writer(SymbolTable<ELFT> *T);
~Writer();
void write(StringRef Path);
std::vector<OutputSection *> OutputSections;
uint64_t FileSize;
- uint64_t SizeOfImage;
uint64_t SizeOfHeaders;
+ uintX_t SectionHeaderOff;
std::vector<std::unique_ptr<Chunk>> Chunks;
};
# 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
# 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)