forked from OSchip/llvm-project
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:
parent
dcda9979ba
commit
d6fefba447
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue