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
This commit is contained in:
Rui Ueyama 2015-05-28 19:45:43 +00:00
parent dcda9979ba
commit d6fefba447
3 changed files with 31 additions and 28 deletions

View File

@ -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<uint8_t> 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) {

View File

@ -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<uint8_t> 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<uint8_t> Data;
StringRef Name;
size_t Size;
};
// A chunk for the import descriptor table.

View File

@ -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);
}
}