From d6fefba4476bd84c1be37ce119685bb14d27f914 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Thu, 28 May 2015 19:45:43 +0000 Subject: [PATCH] COFF: Teach Chunk to write to a mmap'ed output file. Previously Writer directly handles writes to a file. Chunks needed to give Writer a continuous chunk of memory. That was inefficent if you construct data in chunks because it would require two memory copies (one to construct a chunk and the other is to write that to a file). This patch teaches chunk to write directly to a file. From readability point of view, this is also good because you no longer have to call hasData() before calling getData(). llvm-svn: 238464 --- lld/COFF/Chunks.cpp | 22 ++++++++++++++-------- lld/COFF/Chunks.h | 34 ++++++++++++++++------------------ lld/COFF/Writer.cpp | 3 +-- 3 files changed, 31 insertions(+), 28 deletions(-) diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp index f7ec37be844f..f37e935a9b01 100644 --- a/lld/COFF/Chunks.cpp +++ b/lld/COFF/Chunks.cpp @@ -35,11 +35,11 @@ SectionChunk::SectionChunk(ObjectFile *F, const coff_section *H, uint32_t SI) Align = uint32_t(1) << Shift; } -const uint8_t *SectionChunk::getData() const { +void SectionChunk::writeTo(uint8_t *Buf) { assert(hasData()); ArrayRef Data; File->getCOFFObj()->getSectionContents(Header, Data); - return Data.data(); + memcpy(Buf + FileOff, Data.data(), Data.size()); } // Returns true if this chunk should be considered as a GC root. @@ -157,9 +157,12 @@ uint32_t CommonChunk::getPermissions() const { IMAGE_SCN_MEM_WRITE; } -StringChunk::StringChunk(StringRef S) : Data(S.size() + 1) { - memcpy(Data.data(), S.data(), S.size()); - Data[S.size()] = 0; +void StringChunk::writeTo(uint8_t *Buf) { + memcpy(Buf + FileOff, Str.data(), Str.size()); +} + +void ImportThunkChunk::writeTo(uint8_t *Buf) { + memcpy(Buf + FileOff, ImportThunkData, sizeof(ImportThunkData)); } void ImportThunkChunk::applyRelocations(uint8_t *Buf) { @@ -168,9 +171,12 @@ void ImportThunkChunk::applyRelocations(uint8_t *Buf) { write32le(Buf + FileOff + 2, Operand); } -HintNameChunk::HintNameChunk(StringRef Name) - : Data(RoundUpToAlignment(Name.size() + 4, 2)) { - memcpy(&Data[2], Name.data(), Name.size()); +HintNameChunk::HintNameChunk(StringRef N) + : Name(N), Size(RoundUpToAlignment(Name.size() + 4, 2)) {} + +void HintNameChunk::writeTo(uint8_t *Buf) { + // The first two bytes is Hint/Name field. + memcpy(Buf + FileOff + 2, Name.data(), Name.size()); } void LookupChunk::applyRelocations(uint8_t *Buf) { diff --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h index 62fa12b776db..c2168fc6c5bf 100644 --- a/lld/COFF/Chunks.h +++ b/lld/COFF/Chunks.h @@ -39,15 +39,12 @@ class Chunk { public: virtual ~Chunk() = default; - // Returns the pointer to data. It is illegal to call this function if - // this is a common or BSS chunk. - virtual const uint8_t *getData() const { - llvm_unreachable("unimplemented getData"); - } - // Returns the size of this chunk (even if this is a common or BSS.) virtual size_t getSize() const = 0; + // Write this chunk to a mmap'ed file. Buf is pointing to beginning of file. + virtual void writeTo(uint8_t *Buf) {} + // The writer sets and uses the addresses. uint64_t getRVA() { return RVA; } uint64_t getFileOff() { return FileOff; } @@ -61,9 +58,9 @@ public: // calling this function. virtual void applyRelocations(uint8_t *Buf) {} - // Returns true if getData() returns a valid pointer to data. - // BSS chunks return false. If false is returned, the space occupied - // by this chunk is filled with zeros. + // Returns true if this has non-zero data. BSS chunks return + // false. If false is returned, the space occupied by this chunk + // will be filled with zeros. virtual bool hasData() const { return true; } // Returns readable/writable/executable bits. @@ -117,8 +114,8 @@ class SectionChunk : public Chunk { public: SectionChunk(ObjectFile *File, const coff_section *Header, uint32_t SectionIndex); - const uint8_t *getData() const override; size_t getSize() const override { return Header->SizeOfRawData; } + void writeTo(uint8_t *Buf) override; void applyRelocations(uint8_t *Buf) override; bool hasData() const override; uint32_t getPermissions() const override; @@ -165,12 +162,12 @@ private: // A chunk for linker-created strings. class StringChunk : public Chunk { public: - explicit StringChunk(StringRef S); - const uint8_t *getData() const override { return &Data[0]; } - size_t getSize() const override { return Data.size(); } + explicit StringChunk(StringRef S) : Str(S) {} + size_t getSize() const override { return Str.size() + 1; } + void writeTo(uint8_t *Buf) override; private: - std::vector Data; + StringRef Str; }; // All chunks below are for the DLL import descriptor table and @@ -186,8 +183,8 @@ static const uint8_t ImportThunkData[] = { class ImportThunkChunk : public Chunk { public: explicit ImportThunkChunk(Defined *S) : ImpSymbol(S) {} - const uint8_t *getData() const override { return ImportThunkData; } size_t getSize() const override { return sizeof(ImportThunkData); } + void writeTo(uint8_t *Buf) override; void applyRelocations(uint8_t *Buf) override; private: @@ -198,11 +195,12 @@ private: class HintNameChunk : public Chunk { public: explicit HintNameChunk(StringRef Name); - const uint8_t *getData() const override { return Data.data(); } - size_t getSize() const override { return Data.size(); } + size_t getSize() const override { return Size; } + void writeTo(uint8_t *Buf) override; private: - std::vector Data; + StringRef Name; + size_t Size; }; // A chunk for the import descriptor table. diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp index 3e9abd35d892..3bfee4e3d90b 100644 --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -312,8 +312,7 @@ void Writer::writeSections() { if (Sec->getPermissions() & IMAGE_SCN_CNT_CODE) memset(Buf + Sec->getFileOff(), 0xCC, Sec->getRawSize()); for (Chunk *C : Sec->getChunks()) - if (C->hasData()) - memcpy(Buf + C->getFileOff(), C->getData(), C->getSize()); + C->writeTo(Buf); } }