diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h index 932b2078848d..5853ee1e4ada 100644 --- a/lld/COFF/Config.h +++ b/lld/COFF/Config.h @@ -20,6 +20,7 @@ namespace lld { namespace coff { +using llvm::COFF::IMAGE_FILE_MACHINE_AMD64; using llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN; using llvm::COFF::WindowsSubsystem; using llvm::StringRef; @@ -45,6 +46,7 @@ struct Export { // Global configuration. struct Configuration { enum ManifestKind { SideBySide, Embed, No }; + bool is64() { return MachineType == IMAGE_FILE_MACHINE_AMD64; } llvm::COFF::MachineTypes MachineType = IMAGE_FILE_MACHINE_UNKNOWN; bool Verbose = false; diff --git a/lld/COFF/DLL.cpp b/lld/COFF/DLL.cpp index 891fb0bb1f5e..d89aa23de969 100644 --- a/lld/COFF/DLL.cpp +++ b/lld/COFF/DLL.cpp @@ -31,13 +31,13 @@ using namespace llvm::support::endian; using namespace llvm::COFF; using llvm::RoundUpToAlignment; -static const size_t LookupChunkSize = sizeof(uint64_t); - namespace lld { namespace coff { // Import table +static int ptrSize() { return Config->is64() ? 8 : 4; } + // A chunk for the import descriptor table. class HintNameChunk : public Chunk { public: @@ -63,7 +63,7 @@ private: class LookupChunk : public Chunk { public: explicit LookupChunk(Chunk *C) : HintName(C) {} - size_t getSize() const override { return LookupChunkSize; } + size_t getSize() const override { return ptrSize(); } void writeTo(uint8_t *Buf) override { write32le(Buf + FileOff, HintName->getRVA()); @@ -78,12 +78,16 @@ public: class OrdinalOnlyChunk : public Chunk { public: explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) {} - size_t getSize() const override { return sizeof(uint64_t); } + size_t getSize() const override { return ptrSize(); } void writeTo(uint8_t *Buf) override { // An import-by-ordinal slot has MSB 1 to indicate that // this is import-by-ordinal (and not import-by-name). - write64le(Buf + FileOff, (uint64_t(1) << 63) | Ordinal); + if (Config->is64()) { + write64le(Buf + FileOff, (1ULL << 63) | Ordinal); + } else { + write32le(Buf + FileOff, (1ULL << 31) | Ordinal); + } } uint16_t Ordinal; @@ -125,7 +129,7 @@ uint64_t IdataContents::getDirSize() { } uint64_t IdataContents::getIATSize() { - return Addresses.size() * LookupChunkSize; + return Addresses.size() * ptrSize(); } // Returns a list of .idata contents. @@ -196,8 +200,8 @@ void IdataContents::create() { Hints.push_back(std::move(C)); } // Terminate with null values. - Lookups.push_back(make_unique(LookupChunkSize)); - Addresses.push_back(make_unique(LookupChunkSize)); + Lookups.push_back(make_unique(ptrSize())); + Addresses.push_back(make_unique(ptrSize())); for (int I = 0, E = Syms.size(); I < E; ++I) Syms[I]->setLocation(Addresses[Base + I].get()); diff --git a/lld/test/COFF/Inputs/hello32.yaml b/lld/test/COFF/Inputs/hello32.yaml new file mode 100644 index 000000000000..ea5a5c84c4f1 --- /dev/null +++ b/lld/test/COFF/Inputs/hello32.yaml @@ -0,0 +1,82 @@ +--- +header: + Machine: IMAGE_FILE_MACHINE_I386 + Characteristics: [] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: 33DB538D0500000000508D05000000005053E80000000050E800000000 + Relocations: + - VirtualAddress: 5 + SymbolName: caption + Type: IMAGE_REL_I386_DIR32 + - VirtualAddress: 12 + SymbolName: message + Type: IMAGE_REL_I386_DIR32 + - VirtualAddress: 19 + SymbolName: '_MessageBoxA@16' + Type: IMAGE_REL_I386_REL32 + - VirtualAddress: 25 + SymbolName: '_ExitProcess@4' + Type: IMAGE_REL_I386_REL32 + - Name: .data + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 16 + SectionData: 48656C6C6F0048656C6C6F20576F726C642100 +symbols: + - Name: .text + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 29 + NumberOfRelocations: 4 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: .data + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 19 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: '_ExitProcess@4' + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: '_MessageBoxA@16' + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: message + Value: 6 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: caption + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: '_main@0' + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/lld/test/COFF/Inputs/std32.lib b/lld/test/COFF/Inputs/std32.lib new file mode 100644 index 000000000000..7401ff3faf9e Binary files /dev/null and b/lld/test/COFF/Inputs/std32.lib differ diff --git a/lld/test/COFF/imports32.test b/lld/test/COFF/imports32.test new file mode 100644 index 000000000000..878b583e5722 --- /dev/null +++ b/lld/test/COFF/imports32.test @@ -0,0 +1,15 @@ +# RUN: yaml2obj < %p/Inputs/hello32.yaml > %t.obj +# RUN: lld -flavor link2 %t.obj %p/Inputs/std32.lib /subsystem:console \ +# RUN: /entry:_main@0 /out:%t.exe +# RUN: llvm-readobj -coff-imports %t.exe | FileCheck %s + +CHECK: Format: COFF-i386 +CHECK: Arch: i386 +CHECK: AddressSize: 32bit +CHECK: Import { +CHECK: Name: std32.dll +CHECK: ImportLookupTableRVA: 0x3028 +CHECK: ImportAddressTableRVA: 0x3034 +CHECK: Symbol: ExitProcess (0) +CHECK: Symbol: MessageBoxA (1) +CHECK: }