COFF: Merge Chunk::applyRelocations with Chunk::writeTo.

In this design, Chunk is the only thing that knows how to write
its contents to output file as well as how to apply relocations
there. The writer shouldn't know about the details.

llvm-svn: 239216
This commit is contained in:
Rui Ueyama 2015-06-06 04:07:39 +00:00
parent 468f670021
commit 743afa0736
3 changed files with 16 additions and 35 deletions

View File

@ -37,9 +37,16 @@ SectionChunk::SectionChunk(ObjectFile *F, const coff_section *H, uint32_t SI)
void SectionChunk::writeTo(uint8_t *Buf) { void SectionChunk::writeTo(uint8_t *Buf) {
if (!hasData()) if (!hasData())
return; return;
// Copy section contents from source object file to output file.
ArrayRef<uint8_t> Data; ArrayRef<uint8_t> Data;
File->getCOFFObj()->getSectionContents(Header, Data); File->getCOFFObj()->getSectionContents(Header, Data);
memcpy(Buf + FileOff, Data.data(), Data.size()); memcpy(Buf + FileOff, Data.data(), Data.size());
// Apply relocations.
for (const auto &I : getSectionRef().relocations()) {
const coff_relocation *Rel = File->getCOFFObj()->getCOFFRelocation(I);
applyReloc(Buf, Rel);
}
} }
// Returns true if this chunk should be considered as a GC root. // Returns true if this chunk should be considered as a GC root.
@ -80,13 +87,6 @@ void SectionChunk::addAssociative(SectionChunk *Child) {
AssocChildren.push_back(Child); AssocChildren.push_back(Child);
} }
void SectionChunk::applyRelocations(uint8_t *Buf) {
for (const auto &I : getSectionRef().relocations()) {
const coff_relocation *Rel = File->getCOFFObj()->getCOFFRelocation(I);
applyReloc(Buf, Rel);
}
}
static void add16(uint8_t *P, int32_t V) { write16le(P, read16le(P) + V); } static void add16(uint8_t *P, int32_t V) { write16le(P, read16le(P) + V); }
static void add32(uint8_t *P, int32_t V) { write32le(P, read32le(P) + V); } static void add32(uint8_t *P, int32_t V) { write32le(P, read32le(P) + V); }
static void add64(uint8_t *P, int64_t V) { write64le(P, read64le(P) + V); } static void add64(uint8_t *P, int64_t V) { write64le(P, read64le(P) + V); }
@ -163,11 +163,8 @@ void StringChunk::writeTo(uint8_t *Buf) {
void ImportThunkChunk::writeTo(uint8_t *Buf) { void ImportThunkChunk::writeTo(uint8_t *Buf) {
memcpy(Buf + FileOff, ImportThunkData, sizeof(ImportThunkData)); memcpy(Buf + FileOff, ImportThunkData, sizeof(ImportThunkData));
} // The first two bytes is a JMP instruction. Fill its operand.
void ImportThunkChunk::applyRelocations(uint8_t *Buf) {
uint32_t Operand = ImpSymbol->getRVA() - RVA - getSize(); uint32_t Operand = ImpSymbol->getRVA() - RVA - getSize();
// The first two bytes are a JMP instruction. Fill its operand.
write32le(Buf + FileOff + 2, Operand); write32le(Buf + FileOff + 2, Operand);
} }
@ -182,7 +179,7 @@ void HintNameChunk::writeTo(uint8_t *Buf) {
memcpy(Buf + FileOff + 2, Name.data(), Name.size()); memcpy(Buf + FileOff + 2, Name.data(), Name.size());
} }
void LookupChunk::applyRelocations(uint8_t *Buf) { void LookupChunk::writeTo(uint8_t *Buf) {
write32le(Buf + FileOff, HintName->getRVA()); write32le(Buf + FileOff, HintName->getRVA());
} }
@ -192,7 +189,7 @@ void OrdinalOnlyChunk::writeTo(uint8_t *Buf) {
write64le(Buf + FileOff, (uint64_t(1) << 63) | Ordinal); write64le(Buf + FileOff, (uint64_t(1) << 63) | Ordinal);
} }
void DirectoryChunk::applyRelocations(uint8_t *Buf) { void DirectoryChunk::writeTo(uint8_t *Buf) {
auto *E = (coff_import_directory_table_entry *)(Buf + FileOff); auto *E = (coff_import_directory_table_entry *)(Buf + FileOff);
E->ImportLookupTableRVA = LookupTab->getRVA(); E->ImportLookupTableRVA = LookupTab->getRVA();
E->NameRVA = DLLName->getRVA(); E->NameRVA = DLLName->getRVA();

View File

@ -42,7 +42,10 @@ public:
// Returns the size of this chunk (even if this is a common or BSS.) // Returns the size of this chunk (even if this is a common or BSS.)
virtual size_t getSize() const = 0; virtual size_t getSize() const = 0;
// Write this chunk to a mmap'ed file. Buf is pointing to beginning of file. // Write this chunk to a mmap'ed file, assuming Buf is pointing to
// beginning of the file. Because this function may use RVA values
// of other chunks for relocations, you need to set them properly
// before calling this function.
virtual void writeTo(uint8_t *Buf) {} virtual void writeTo(uint8_t *Buf) {}
// The writer sets and uses the addresses. // The writer sets and uses the addresses.
@ -52,12 +55,6 @@ public:
void setRVA(uint64_t V) { RVA = V; } void setRVA(uint64_t V) { RVA = V; }
void setFileOff(uint64_t V) { FileOff = V; } void setFileOff(uint64_t V) { FileOff = V; }
// Applies relocations, assuming Buffer points to beginning of an
// mmap'ed output file. Because this function uses file offsets and
// RVA values of other chunks, you need to set them properly before
// calling this function.
virtual void applyRelocations(uint8_t *Buf) {}
// Returns true if this has non-zero data. BSS chunks return // Returns true if this has non-zero data. BSS chunks return
// false. If false is returned, the space occupied by this chunk // false. If false is returned, the space occupied by this chunk
// will be filled with zeros. // will be filled with zeros.
@ -116,7 +113,6 @@ public:
uint32_t SectionIndex); uint32_t SectionIndex);
size_t getSize() const override { return Header->SizeOfRawData; } size_t getSize() const override { return Header->SizeOfRawData; }
void writeTo(uint8_t *Buf) override; void writeTo(uint8_t *Buf) override;
void applyRelocations(uint8_t *Buf) override;
bool hasData() const override; bool hasData() const override;
uint32_t getPermissions() const override; uint32_t getPermissions() const override;
StringRef getSectionName() const override { return SectionName; } StringRef getSectionName() const override { return SectionName; }
@ -185,7 +181,6 @@ public:
explicit ImportThunkChunk(Defined *S) : ImpSymbol(S) {} explicit ImportThunkChunk(Defined *S) : ImpSymbol(S) {}
size_t getSize() const override { return sizeof(ImportThunkData); } size_t getSize() const override { return sizeof(ImportThunkData); }
void writeTo(uint8_t *Buf) override; void writeTo(uint8_t *Buf) override;
void applyRelocations(uint8_t *Buf) override;
private: private:
Defined *ImpSymbol; Defined *ImpSymbol;
@ -207,9 +202,8 @@ private:
class LookupChunk : public Chunk { class LookupChunk : public Chunk {
public: public:
explicit LookupChunk(Chunk *C) : HintName(C) {} explicit LookupChunk(Chunk *C) : HintName(C) {}
bool hasData() const override { return false; }
size_t getSize() const override { return sizeof(uint64_t); } size_t getSize() const override { return sizeof(uint64_t); }
void applyRelocations(uint8_t *Buf) override; void writeTo(uint8_t *Buf) override;
Chunk *HintName; Chunk *HintName;
}; };
@ -219,7 +213,6 @@ public:
class OrdinalOnlyChunk : public Chunk { class OrdinalOnlyChunk : public Chunk {
public: public:
explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) {} explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) {}
bool hasData() const override { return true; }
size_t getSize() const override { return sizeof(uint64_t); } size_t getSize() const override { return sizeof(uint64_t); }
void writeTo(uint8_t *Buf) override; void writeTo(uint8_t *Buf) override;
uint16_t Ordinal; uint16_t Ordinal;
@ -229,9 +222,8 @@ public:
class DirectoryChunk : public Chunk { class DirectoryChunk : public Chunk {
public: public:
explicit DirectoryChunk(Chunk *N) : DLLName(N) {} explicit DirectoryChunk(Chunk *N) : DLLName(N) {}
bool hasData() const override { return false; }
size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); } size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); }
void applyRelocations(uint8_t *Buf) override; void writeTo(uint8_t *Buf) override;
Chunk *DLLName; Chunk *DLLName;
Chunk *LookupTab; Chunk *LookupTab;

View File

@ -413,13 +413,6 @@ OutputSection *Writer::createSection(StringRef Name) {
return Sec; return Sec;
} }
void Writer::applyRelocations() {
uint8_t *Buf = Buffer->getBufferStart();
for (OutputSection *Sec : OutputSections)
for (Chunk *C : Sec->getChunks())
C->applyRelocations(Buf);
}
std::error_code Writer::write(StringRef OutputPath) { std::error_code Writer::write(StringRef OutputPath) {
markLive(); markLive();
createSections(); createSections();
@ -430,7 +423,6 @@ std::error_code Writer::write(StringRef OutputPath) {
return EC; return EC;
writeHeader(); writeHeader();
writeSections(); writeSections();
applyRelocations();
return Buffer->commit(); return Buffer->commit();
} }