mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-28 03:46:06 +00:00
COFF: Fix delay-import tables.
There were a few issues with the previous delay-import tables. - "Attribute" field should have been 1 instead of 0. (I don't know the meaning of this field, though.) - LEA and CALL operands had wrong addresses. - Address tables are in .didat (which is read-only). They should have been in .data. llvm-svn: 240837
This commit is contained in:
parent
a3c6f0048c
commit
382dc96e29
@ -228,6 +228,7 @@ public:
|
||||
|
||||
void writeTo(uint8_t *Buf) override {
|
||||
auto *E = (delay_import_directory_table_entry *)(Buf + FileOff);
|
||||
E->Attributes = 1;
|
||||
E->Name = DLLName->getRVA();
|
||||
E->ModuleHandle = ModuleHandle->getRVA();
|
||||
E->DelayImportAddressTable = AddressTab->getRVA();
|
||||
@ -272,15 +273,14 @@ static const uint8_t Thunk[] = {
|
||||
// A chunk for the delay import thunk.
|
||||
class ThunkChunk : public Chunk {
|
||||
public:
|
||||
ThunkChunk(Defined *I, Defined *H) : Imp(I), Helper(H) {}
|
||||
|
||||
ThunkChunk(Defined *I, Chunk *D, Defined *H) : Imp(I), Desc(D), Helper(H) {}
|
||||
size_t getSize() const override { return sizeof(Thunk); }
|
||||
|
||||
void writeTo(uint8_t *Buf) override {
|
||||
memcpy(Buf + FileOff, Thunk, sizeof(Thunk));
|
||||
write32le(Buf + FileOff + 36, Imp->getRVA());
|
||||
write32le(Buf + FileOff + 43, Desc->getRVA());
|
||||
write32le(Buf + FileOff + 48, Helper->getRVA());
|
||||
write32le(Buf + FileOff + 36, Imp->getRVA() - RVA - 40);
|
||||
write32le(Buf + FileOff + 43, Desc->getRVA() - RVA - 47);
|
||||
write32le(Buf + FileOff + 48, Helper->getRVA() - RVA - 52);
|
||||
}
|
||||
|
||||
Defined *Imp = nullptr;
|
||||
@ -288,14 +288,10 @@ public:
|
||||
Defined *Helper = nullptr;
|
||||
};
|
||||
|
||||
std::vector<Chunk *> DelayLoadContents::getChunks(Defined *H) {
|
||||
Helper = H;
|
||||
create();
|
||||
std::vector<Chunk *> DelayLoadContents::getChunks() {
|
||||
std::vector<Chunk *> V;
|
||||
for (std::unique_ptr<Chunk> &C : Dirs)
|
||||
V.push_back(C.get());
|
||||
for (std::unique_ptr<Chunk> &C : Addresses)
|
||||
V.push_back(C.get());
|
||||
for (std::unique_ptr<Chunk> &C : Names)
|
||||
V.push_back(C.get());
|
||||
for (std::unique_ptr<Chunk> &C : HintNames)
|
||||
@ -307,11 +303,34 @@ std::vector<Chunk *> DelayLoadContents::getChunks(Defined *H) {
|
||||
return V;
|
||||
}
|
||||
|
||||
std::vector<Chunk *> DelayLoadContents::getDataChunks() {
|
||||
std::vector<Chunk *> V;
|
||||
for (std::unique_ptr<Chunk> &C : ModuleHandles)
|
||||
V.push_back(C.get());
|
||||
for (std::unique_ptr<Chunk> &C : Addresses)
|
||||
V.push_back(C.get());
|
||||
return V;
|
||||
}
|
||||
|
||||
uint64_t DelayLoadContents::getDirSize() {
|
||||
return Dirs.size() * sizeof(delay_import_directory_table_entry);
|
||||
}
|
||||
|
||||
void DelayLoadContents::create() {
|
||||
// A chunk for the import descriptor table.
|
||||
class DelayAddressChunk : public Chunk {
|
||||
public:
|
||||
explicit DelayAddressChunk(Chunk *C) : Thunk(C) {}
|
||||
size_t getSize() const override { return 8; }
|
||||
|
||||
void writeTo(uint8_t *Buf) override {
|
||||
write64le(Buf + FileOff, Thunk->getRVA() + Config->ImageBase);
|
||||
}
|
||||
|
||||
Chunk *Thunk;
|
||||
};
|
||||
|
||||
void DelayLoadContents::create(Defined *H) {
|
||||
Helper = H;
|
||||
std::map<StringRef, std::vector<DefinedImportData *>> Map =
|
||||
binImports(Imports);
|
||||
|
||||
@ -320,11 +339,15 @@ void DelayLoadContents::create() {
|
||||
StringRef Name = P.first;
|
||||
std::vector<DefinedImportData *> &Syms = P.second;
|
||||
|
||||
// Create the delay import table header.
|
||||
if (!DLLNames.count(Name))
|
||||
DLLNames[Name] = make_unique<StringChunk>(Name);
|
||||
auto Dir = make_unique<DelayDirectoryChunk>(DLLNames[Name].get());
|
||||
|
||||
size_t Base = Addresses.size();
|
||||
for (DefinedImportData *S : Syms) {
|
||||
auto T = make_unique<ThunkChunk>(S, Helper);
|
||||
auto A = make_unique<LookupChunk>(T.get());
|
||||
T->Desc = A.get();
|
||||
auto T = make_unique<ThunkChunk>(S, Dir.get(), Helper);
|
||||
auto A = make_unique<DelayAddressChunk>(T.get());
|
||||
Addresses.push_back(std::move(A));
|
||||
Thunks.push_back(std::move(T));
|
||||
auto C =
|
||||
@ -333,8 +356,8 @@ void DelayLoadContents::create() {
|
||||
HintNames.push_back(std::move(C));
|
||||
}
|
||||
// Terminate with null values.
|
||||
Addresses.push_back(make_unique<NullChunk>(LookupChunkSize));
|
||||
Names.push_back(make_unique<NullChunk>(LookupChunkSize));
|
||||
Addresses.push_back(make_unique<NullChunk>(8));
|
||||
Names.push_back(make_unique<NullChunk>(8));
|
||||
|
||||
for (int I = 0, E = Syms.size(); I < E; ++I)
|
||||
Syms[I]->setLocation(Addresses[Base + I].get());
|
||||
@ -342,10 +365,7 @@ void DelayLoadContents::create() {
|
||||
MH->setAlign(8);
|
||||
ModuleHandles.push_back(std::unique_ptr<Chunk>(MH));
|
||||
|
||||
// Create the delay import table header.
|
||||
if (!DLLNames.count(Name))
|
||||
DLLNames[Name] = make_unique<StringChunk>(Name);
|
||||
auto Dir = make_unique<DelayDirectoryChunk>(DLLNames[Name].get());
|
||||
// Fill the delay import table header fields.
|
||||
Dir->ModuleHandle = MH;
|
||||
Dir->AddressTab = Addresses[Base].get();
|
||||
Dir->NameTab = Names[Base].get();
|
||||
|
@ -48,15 +48,15 @@ class DelayLoadContents {
|
||||
public:
|
||||
void add(DefinedImportData *Sym) { Imports.push_back(Sym); }
|
||||
bool empty() { return Imports.empty(); }
|
||||
std::vector<Chunk *> getChunks(Defined *Helper);
|
||||
std::vector<std::unique_ptr<Chunk>> &getDataChunks() { return ModuleHandles; }
|
||||
void create(Defined *Helper);
|
||||
std::vector<Chunk *> getChunks();
|
||||
std::vector<Chunk *> getDataChunks();
|
||||
std::vector<std::unique_ptr<Chunk>> &getCodeChunks() { return Thunks; }
|
||||
|
||||
uint64_t getDirRVA() { return Dirs[0]->getRVA(); }
|
||||
uint64_t getDirSize();
|
||||
|
||||
private:
|
||||
void create();
|
||||
Defined *Helper;
|
||||
std::vector<DefinedImportData *> Imports;
|
||||
std::vector<std::unique_ptr<Chunk>> Dirs;
|
||||
|
@ -203,15 +203,16 @@ void Writer::createImportTables() {
|
||||
Sec->addChunk(C);
|
||||
}
|
||||
if (!DelayIdata.empty()) {
|
||||
DelayIdata.create(Symtab->find("__delayLoadHelper2"));
|
||||
OutputSection *Sec = createSection(".didat");
|
||||
for (Chunk *C : DelayIdata.getChunks(Symtab->find("__delayLoadHelper2")))
|
||||
for (Chunk *C : DelayIdata.getChunks())
|
||||
Sec->addChunk(C);
|
||||
Sec = createSection(".data");
|
||||
for (Chunk *C : DelayIdata.getDataChunks())
|
||||
Sec->addChunk(C);
|
||||
Sec = createSection(".text");
|
||||
for (std::unique_ptr<Chunk> &C : DelayIdata.getCodeChunks())
|
||||
Sec->addChunk(C.get());
|
||||
Sec = createSection(".data");
|
||||
for (std::unique_ptr<Chunk> &C : DelayIdata.getDataChunks())
|
||||
Sec->addChunk(C.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,22 +5,22 @@
|
||||
|
||||
CHECK: DelayImport {
|
||||
CHECK-NEXT: Name: std64.dll
|
||||
CHECK-NEXT: Attributes: 0x0
|
||||
CHECK-NEXT: Attributes: 0x1
|
||||
CHECK-NEXT: ModuleHandle: 0x1018
|
||||
CHECK-NEXT: ImportAddressTable: 0x3040
|
||||
CHECK-NEXT: ImportNameTable: 0x3060
|
||||
CHECK-NEXT: ImportAddressTable: 0x1020
|
||||
CHECK-NEXT: ImportNameTable: 0x3040
|
||||
CHECK-NEXT: BoundDelayImportTable: 0x0
|
||||
CHECK-NEXT: UnloadDelayImportTable: 0x0
|
||||
CHECK-NEXT: Import {
|
||||
CHECK-NEXT: Symbol: ExitProcess (0)
|
||||
CHECK-NEXT: Address: 0x2066
|
||||
CHECK-NEXT: Address: 0x140002066
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: Import {
|
||||
CHECK-NEXT: Symbol: (50)
|
||||
CHECK-NEXT: Address: 0x20BD
|
||||
CHECK-NEXT: Address: 0x1400020BD
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: Import {
|
||||
CHECK-NEXT: Symbol: MessageBoxA (1)
|
||||
CHECK-NEXT: Address: 0x2114
|
||||
CHECK-NEXT: Address: 0x140002114
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: }
|
||||
|
Loading…
x
Reference in New Issue
Block a user