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:
Rui Ueyama 2015-06-26 21:40:15 +00:00
parent a3c6f0048c
commit 382dc96e29
4 changed files with 54 additions and 33 deletions

View File

@ -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();

View File

@ -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;

View File

@ -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());
}
}

View File

@ -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: }