Fix broken export table if .rdata is merged with .text.

Previously, we assumed that .rdata is zero-filled, so when writing
an COFF import table, we didn't write anything if the data is zero.
That assumption was wrong because .rdata can be merged with .text.
If .rdata is merged with .text, they are initialized with 0xcc which
is a trap instruction.

This patch removes that assumption from code.

Should be merged to 8.0 branch as this is a regression.

Fixes https://bugs.llvm.org/show_bug.cgi?id=39826

Differential Revision: https://reviews.llvm.org/D57168

llvm-svn: 352082
This commit is contained in:
Rui Ueyama 2019-01-24 19:02:31 +00:00
parent c12a634326
commit 18972d1ee9
2 changed files with 28 additions and 1 deletions

View File

@ -46,6 +46,7 @@ public:
}
void writeTo(uint8_t *Buf) const override {
memset(Buf + OutputSectionOff, 0, getSize());
write16le(Buf + OutputSectionOff, Hint);
memcpy(Buf + OutputSectionOff + 2, Name.data(), Name.size());
}
@ -62,7 +63,10 @@ public:
size_t getSize() const override { return Config->Wordsize; }
void writeTo(uint8_t *Buf) const override {
write32le(Buf + OutputSectionOff, HintName->getRVA());
if (Config->is64())
write64le(Buf + OutputSectionOff, HintName->getRVA());
else
write32le(Buf + OutputSectionOff, HintName->getRVA());
}
Chunk *HintName;
@ -98,6 +102,8 @@ public:
size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); }
void writeTo(uint8_t *Buf) const override {
memset(Buf + OutputSectionOff, 0, getSize());
auto *E = (coff_import_directory_table_entry *)(Buf + OutputSectionOff);
E->ImportLookupTableRVA = LookupTab->getRVA();
E->NameRVA = DLLName->getRVA();
@ -117,6 +123,10 @@ public:
bool hasData() const override { return false; }
size_t getSize() const override { return Size; }
void writeTo(uint8_t *Buf) const override {
memset(Buf + OutputSectionOff, 0, Size);
}
private:
size_t Size;
};
@ -159,6 +169,8 @@ public:
}
void writeTo(uint8_t *Buf) const override {
memset(Buf + OutputSectionOff, 0, getSize());
auto *E = (delay_import_directory_table_entry *)(Buf + OutputSectionOff);
E->Attributes = 1;
E->Name = DLLName->getRVA();
@ -391,6 +403,8 @@ public:
}
void writeTo(uint8_t *Buf) const override {
memset(Buf + OutputSectionOff, 0, getSize());
auto *E = (export_directory_table_entry *)(Buf + OutputSectionOff);
E->NameRVA = DLLName->getRVA();
E->OrdinalBase = 0;

View File

@ -34,3 +34,16 @@ IMPORT-NEXT: Symbol: ExitProcess (0)
IMPORT-NEXT: Symbol: (50)
IMPORT-NEXT: Symbol: MessageBoxA (1)
IMPORT-NEXT: }
# RUN: lld-link /out:%t.exe /entry:main /subsystem:console /merge:.rdata=.text \
# RUN: %p/Inputs/hello64.obj %p/Inputs/std64.lib /include:ExitProcess
# RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=MERGE %s
MERGE: Import {
MERGE-NEXT: Name: std64.dll
MERGE-NEXT: ImportLookupTableRVA: 0x1090
MERGE-NEXT: ImportAddressTableRVA: 0x10B0
MERGE-NEXT: Symbol: ExitProcess (0)
MERGE-NEXT: Symbol: (50)
MERGE-NEXT: Symbol: MessageBoxA (1)
MERGE-NEXT: }