COFF: In chunks, store the offset from the start of the output section. NFC.

This is more convenient than the offset from the start of the file as we
don't have to worry about it changing when we move the output section.

This is a port of r245008 from ELF.

llvm-svn: 245018
This commit is contained in:
Rafael Espindola 2015-08-14 03:30:59 +00:00
parent f9cbd039bd
commit 5c546a1437
5 changed files with 49 additions and 49 deletions

View File

@ -129,11 +129,11 @@ void SectionChunk::writeTo(uint8_t *Buf) {
return;
// Copy section contents from source object file to output file.
ArrayRef<uint8_t> A = getContents();
memcpy(Buf + FileOff, A.data(), A.size());
memcpy(Buf + OutputSectionOff, A.data(), A.size());
// Apply relocations.
for (const coff_relocation &Rel : Relocs) {
uint8_t *Off = Buf + FileOff + Rel.VirtualAddress;
uint8_t *Off = Buf + OutputSectionOff + Rel.VirtualAddress;
SymbolBody *Body = File->getSymbolBody(Rel.SymbolTableIndex)->repl();
Defined *Sym = cast<Defined>(Body);
uint64_t P = RVA + Rel.VirtualAddress;
@ -243,7 +243,7 @@ uint32_t CommonChunk::getPermissions() const {
}
void StringChunk::writeTo(uint8_t *Buf) {
memcpy(Buf + FileOff, Str.data(), Str.size());
memcpy(Buf + OutputSectionOff, Str.data(), Str.size());
}
ImportThunkChunkX64::ImportThunkChunkX64(Defined *S) : ImpSymbol(S) {
@ -253,9 +253,9 @@ ImportThunkChunkX64::ImportThunkChunkX64(Defined *S) : ImpSymbol(S) {
}
void ImportThunkChunkX64::writeTo(uint8_t *Buf) {
memcpy(Buf + FileOff, ImportThunkX86, sizeof(ImportThunkX86));
memcpy(Buf + OutputSectionOff, ImportThunkX86, sizeof(ImportThunkX86));
// The first two bytes is a JMP instruction. Fill its operand.
write32le(Buf + FileOff + 2, ImpSymbol->getRVA() - RVA - getSize());
write32le(Buf + OutputSectionOff + 2, ImpSymbol->getRVA() - RVA - getSize());
}
void ImportThunkChunkX86::getBaserels(std::vector<Baserel> *Res) {
@ -263,9 +263,10 @@ void ImportThunkChunkX86::getBaserels(std::vector<Baserel> *Res) {
}
void ImportThunkChunkX86::writeTo(uint8_t *Buf) {
memcpy(Buf + FileOff, ImportThunkX86, sizeof(ImportThunkX86));
memcpy(Buf + OutputSectionOff, ImportThunkX86, sizeof(ImportThunkX86));
// The first two bytes is a JMP instruction. Fill its operand.
write32le(Buf + FileOff + 2, ImpSymbol->getRVA() + Config->ImageBase);
write32le(Buf + OutputSectionOff + 2,
ImpSymbol->getRVA() + Config->ImageBase);
}
void ImportThunkChunkARM::getBaserels(std::vector<Baserel> *Res) {
@ -273,9 +274,9 @@ void ImportThunkChunkARM::getBaserels(std::vector<Baserel> *Res) {
}
void ImportThunkChunkARM::writeTo(uint8_t *Buf) {
memcpy(Buf + FileOff, ImportThunkARM, sizeof(ImportThunkARM));
memcpy(Buf + OutputSectionOff, ImportThunkARM, sizeof(ImportThunkARM));
// Fix mov.w and mov.t operands.
applyMOV32T(Buf + FileOff, ImpSymbol->getRVA() + Config->ImageBase);
applyMOV32T(Buf + OutputSectionOff, ImpSymbol->getRVA() + Config->ImageBase);
}
void LocalImportChunk::getBaserels(std::vector<Baserel> *Res) {
@ -288,14 +289,14 @@ size_t LocalImportChunk::getSize() const {
void LocalImportChunk::writeTo(uint8_t *Buf) {
if (Config->is64()) {
write64le(Buf + FileOff, Sym->getRVA() + Config->ImageBase);
write64le(Buf + OutputSectionOff, Sym->getRVA() + Config->ImageBase);
} else {
write32le(Buf + FileOff, Sym->getRVA() + Config->ImageBase);
write32le(Buf + OutputSectionOff, Sym->getRVA() + Config->ImageBase);
}
}
void SEHTableChunk::writeTo(uint8_t *Buf) {
ulittle32_t *Begin = reinterpret_cast<ulittle32_t *>(Buf + FileOff);
ulittle32_t *Begin = reinterpret_cast<ulittle32_t *>(Buf + OutputSectionOff);
size_t Cnt = 0;
for (Defined *D : Syms)
Begin[Cnt++] = D->getRVA();
@ -319,7 +320,7 @@ BaserelChunk::BaserelChunk(uint32_t Page, Baserel *Begin, Baserel *End) {
}
void BaserelChunk::writeTo(uint8_t *Buf) {
memcpy(Buf + FileOff, Data.data(), Data.size());
memcpy(Buf + OutputSectionOff, Data.data(), Data.size());
}
uint8_t Baserel::getDefaultType() {

View File

@ -62,10 +62,10 @@ public:
// The writer sets and uses the addresses.
uint64_t getRVA() { return RVA; }
uint64_t getFileOff() { return FileOff; }
uint64_t getOutputSectionOff() { return OutputSectionOff; }
uint32_t getAlign() { return Align; }
void setRVA(uint64_t V) { RVA = V; }
void setFileOff(uint64_t V) { FileOff = V; }
void setOutputSectionOff(uint64_t V) { OutputSectionOff = V; }
// Returns true if this has non-zero data. BSS chunks return
// false. If false is returned, the space occupied by this chunk
@ -101,8 +101,8 @@ protected:
// The RVA of this chunk in the output. The writer sets a value.
uint64_t RVA = 0;
// The offset from beginning of the output file. The writer sets a value.
uint64_t FileOff = 0;
// The offset from beginning of the output section. The writer sets a value.
uint64_t OutputSectionOff = 0;
// The output section for this chunk.
OutputSection *Out = nullptr;

View File

@ -50,8 +50,8 @@ public:
}
void writeTo(uint8_t *Buf) override {
write16le(Buf + FileOff, Hint);
memcpy(Buf + FileOff + 2, Name.data(), Name.size());
write16le(Buf + OutputSectionOff, Hint);
memcpy(Buf + OutputSectionOff + 2, Name.data(), Name.size());
}
private:
@ -66,7 +66,7 @@ public:
size_t getSize() const override { return ptrSize(); }
void writeTo(uint8_t *Buf) override {
write32le(Buf + FileOff, HintName->getRVA());
write32le(Buf + OutputSectionOff, HintName->getRVA());
}
Chunk *HintName;
@ -84,9 +84,9 @@ public:
// An import-by-ordinal slot has MSB 1 to indicate that
// this is import-by-ordinal (and not import-by-name).
if (Config->is64()) {
write64le(Buf + FileOff, (1ULL << 63) | Ordinal);
write64le(Buf + OutputSectionOff, (1ULL << 63) | Ordinal);
} else {
write32le(Buf + FileOff, (1ULL << 31) | Ordinal);
write32le(Buf + OutputSectionOff, (1ULL << 31) | Ordinal);
}
}
@ -100,7 +100,7 @@ public:
size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); }
void writeTo(uint8_t *Buf) override {
auto *E = (coff_import_directory_table_entry *)(Buf + FileOff);
auto *E = (coff_import_directory_table_entry *)(Buf + OutputSectionOff);
E->ImportLookupTableRVA = LookupTab->getRVA();
E->NameRVA = DLLName->getRVA();
E->ImportAddressTableRVA = AddressTab->getRVA();
@ -156,7 +156,7 @@ public:
}
void writeTo(uint8_t *Buf) override {
auto *E = (delay_import_directory_table_entry *)(Buf + FileOff);
auto *E = (delay_import_directory_table_entry *)(Buf + OutputSectionOff);
E->Attributes = 1;
E->Name = DLLName->getRVA();
E->ModuleHandle = ModuleHandle->getRVA();
@ -219,10 +219,10 @@ public:
size_t getSize() const override { return sizeof(ThunkX64); }
void writeTo(uint8_t *Buf) override {
memcpy(Buf + FileOff, ThunkX64, sizeof(ThunkX64));
write32le(Buf + FileOff + 36, Imp->getRVA() - RVA - 40);
write32le(Buf + FileOff + 43, Desc->getRVA() - RVA - 47);
write32le(Buf + FileOff + 48, Helper->getRVA() - RVA - 52);
memcpy(Buf + OutputSectionOff, ThunkX64, sizeof(ThunkX64));
write32le(Buf + OutputSectionOff + 36, Imp->getRVA() - RVA - 40);
write32le(Buf + OutputSectionOff + 43, Desc->getRVA() - RVA - 47);
write32le(Buf + OutputSectionOff + 48, Helper->getRVA() - RVA - 52);
}
Defined *Imp = nullptr;
@ -238,10 +238,10 @@ public:
size_t getSize() const override { return sizeof(ThunkX86); }
void writeTo(uint8_t *Buf) override {
memcpy(Buf + FileOff, ThunkX86, sizeof(ThunkX86));
write32le(Buf + FileOff + 3, Imp->getRVA() + Config->ImageBase);
write32le(Buf + FileOff + 8, Desc->getRVA() + Config->ImageBase);
write32le(Buf + FileOff + 13, Helper->getRVA() - RVA - 17);
memcpy(Buf + OutputSectionOff, ThunkX86, sizeof(ThunkX86));
write32le(Buf + OutputSectionOff + 3, Imp->getRVA() + Config->ImageBase);
write32le(Buf + OutputSectionOff + 8, Desc->getRVA() + Config->ImageBase);
write32le(Buf + OutputSectionOff + 13, Helper->getRVA() - RVA - 17);
}
void getBaserels(std::vector<Baserel> *Res) override {
@ -262,9 +262,9 @@ public:
void writeTo(uint8_t *Buf) override {
if (Config->is64()) {
write64le(Buf + FileOff, Thunk->getRVA() + Config->ImageBase);
write64le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase);
} else {
write32le(Buf + FileOff, Thunk->getRVA() + Config->ImageBase);
write32le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase);
}
}
@ -290,7 +290,7 @@ public:
}
void writeTo(uint8_t *Buf) override {
auto *E = (export_directory_table_entry *)(Buf + FileOff);
auto *E = (export_directory_table_entry *)(Buf + OutputSectionOff);
E->NameRVA = DLLName->getRVA();
E->OrdinalBase = 0;
E->AddressTableEntries = MaxOrdinal + 1;
@ -316,7 +316,7 @@ public:
void writeTo(uint8_t *Buf) override {
for (Export &E : Config->Exports) {
auto *D = cast<Defined>(E.Sym->repl());
write32le(Buf + FileOff + E.Ordinal * 4, D->getRVA());
write32le(Buf + OutputSectionOff + E.Ordinal * 4, D->getRVA());
}
}
@ -330,7 +330,7 @@ public:
size_t getSize() const override { return Chunks.size() * 4; }
void writeTo(uint8_t *Buf) override {
uint8_t *P = Buf + FileOff;
uint8_t *P = Buf + OutputSectionOff;
for (Chunk *C : Chunks) {
write32le(P, C->getRVA());
P += 4;
@ -347,7 +347,7 @@ public:
size_t getSize() const override { return Size * 2; }
void writeTo(uint8_t *Buf) override {
uint8_t *P = Buf + FileOff;
uint8_t *P = Buf + OutputSectionOff;
for (Export &E : Config->Exports) {
if (E.Noname)
continue;

View File

@ -175,8 +175,8 @@ public:
return S->kind() == DefinedRegularKind;
}
uint64_t getFileOff() {
return (*Data)->getFileOff() + Sym->Value;
uint64_t getOutputSectionOff() {
return (*Data)->getOutputSectionOff() + Sym->Value;
}
uint64_t getRVA() { return (*Data)->getRVA() + Sym->Value; }
@ -202,7 +202,7 @@ public:
}
uint64_t getRVA() { return Data->getRVA(); }
uint64_t getFileOff() { return Data->getFileOff(); }
uint64_t getOutputSectionOff() { return Data->getOutputSectionOff(); }
private:
friend SymbolBody;
@ -316,7 +316,7 @@ public:
}
uint64_t getRVA() { return Location->getRVA(); }
uint64_t getFileOff() { return Location->getFileOff(); }
uint64_t getOutputSectionOff() { return Location->getOutputSectionOff(); }
StringRef getDLLName() { return DLLName; }
StringRef getExternalName() { return ExternalName; }
@ -344,7 +344,7 @@ public:
}
uint64_t getRVA() { return Data->getRVA(); }
uint64_t getFileOff() { return Data->getFileOff(); }
uint64_t getOutputSectionOff() { return Data->getOutputSectionOff(); }
Chunk *getChunk() { return Data.get(); }
private:
@ -366,7 +366,7 @@ public:
}
uint64_t getRVA() { return Data.getRVA(); }
uint64_t getFileOff() { return Data.getFileOff(); }
uint64_t getOutputSectionOff() { return Data.getOutputSectionOff(); }
Chunk *getChunk() { return &Data; }

View File

@ -159,8 +159,6 @@ void OutputSection::setFileOffset(uint64_t Off) {
if (Header.SizeOfRawData == 0)
return;
Header.PointerToRawData = Off;
for (Chunk *C : Chunks)
C->setFileOff(C->getFileOff() + Off);
}
void OutputSection::addChunk(Chunk *C) {
@ -169,7 +167,7 @@ void OutputSection::addChunk(Chunk *C) {
uint64_t Off = Header.VirtualSize;
Off = RoundUpToAlignment(Off, C->getAlign());
C->setRVA(Off);
C->setFileOff(Off);
C->setOutputSectionOff(Off);
Off += C->getSize();
Header.VirtualSize = Off;
if (C->hasData())
@ -705,13 +703,14 @@ void Writer::fixSafeSEHSymbols() {
void Writer::writeSections() {
uint8_t *Buf = Buffer->getBufferStart();
for (OutputSection *Sec : OutputSections) {
uint8_t *SecBuf = Buf + Sec->getFileOff();
// Fill gaps between functions in .text with INT3 instructions
// instead of leaving as NUL bytes (which can be interpreted as
// ADD instructions).
if (Sec->getPermissions() & IMAGE_SCN_CNT_CODE)
memset(Buf + Sec->getFileOff(), 0xCC, Sec->getRawSize());
memset(SecBuf, 0xCC, Sec->getRawSize());
for (Chunk *C : Sec->getChunks())
C->writeTo(Buf);
C->writeTo(SecBuf);
}
}