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