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) {
if (!hasData())
return;
// Copy section contents from source object file to output file.
ArrayRef<uint8_t> Data;
File->getCOFFObj()->getSectionContents(Header, Data);
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.
@ -80,13 +87,6 @@ void SectionChunk::addAssociative(SectionChunk *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 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); }
@ -163,11 +163,8 @@ void StringChunk::writeTo(uint8_t *Buf) {
void ImportThunkChunk::writeTo(uint8_t *Buf) {
memcpy(Buf + FileOff, ImportThunkData, sizeof(ImportThunkData));
}
void ImportThunkChunk::applyRelocations(uint8_t *Buf) {
// The first two bytes is a JMP instruction. Fill its operand.
uint32_t Operand = ImpSymbol->getRVA() - RVA - getSize();
// The first two bytes are a JMP instruction. Fill its operand.
write32le(Buf + FileOff + 2, Operand);
}
@ -182,7 +179,7 @@ void HintNameChunk::writeTo(uint8_t *Buf) {
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());
}
@ -192,7 +189,7 @@ void OrdinalOnlyChunk::writeTo(uint8_t *Buf) {
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);
E->ImportLookupTableRVA = LookupTab->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.)
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) {}
// The writer sets and uses the addresses.
@ -52,12 +55,6 @@ public:
void setRVA(uint64_t V) { RVA = 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
// false. If false is returned, the space occupied by this chunk
// will be filled with zeros.
@ -116,7 +113,6 @@ public:
uint32_t SectionIndex);
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;
StringRef getSectionName() const override { return SectionName; }
@ -185,7 +181,6 @@ public:
explicit ImportThunkChunk(Defined *S) : ImpSymbol(S) {}
size_t getSize() const override { return sizeof(ImportThunkData); }
void writeTo(uint8_t *Buf) override;
void applyRelocations(uint8_t *Buf) override;
private:
Defined *ImpSymbol;
@ -207,9 +202,8 @@ private:
class LookupChunk : public Chunk {
public:
explicit LookupChunk(Chunk *C) : HintName(C) {}
bool hasData() const override { return false; }
size_t getSize() const override { return sizeof(uint64_t); }
void applyRelocations(uint8_t *Buf) override;
void writeTo(uint8_t *Buf) override;
Chunk *HintName;
};
@ -219,7 +213,6 @@ public:
class OrdinalOnlyChunk : public Chunk {
public:
explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) {}
bool hasData() const override { return true; }
size_t getSize() const override { return sizeof(uint64_t); }
void writeTo(uint8_t *Buf) override;
uint16_t Ordinal;
@ -229,9 +222,8 @@ public:
class DirectoryChunk : public Chunk {
public:
explicit DirectoryChunk(Chunk *N) : DLLName(N) {}
bool hasData() const override { return false; }
size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); }
void applyRelocations(uint8_t *Buf) override;
void writeTo(uint8_t *Buf) override;
Chunk *DLLName;
Chunk *LookupTab;

View File

@ -413,13 +413,6 @@ OutputSection *Writer::createSection(StringRef Name) {
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) {
markLive();
createSections();
@ -430,7 +423,6 @@ std::error_code Writer::write(StringRef OutputPath) {
return EC;
writeHeader();
writeSections();
applyRelocations();
return Buffer->commit();
}