forked from OSchip/llvm-project
COFF: Fix import thunks and name mangling for x86.
With this patch, LLD is now able to correctly link a "hello world" program written in assembly for 32-bit x86. llvm-svn: 241771
This commit is contained in:
parent
6335057824
commit
7c3e23fffd
|
@ -245,7 +245,9 @@ ImportThunkChunk::ImportThunkChunk(Defined *S) : ImpSymbol(S) {
|
|||
void ImportThunkChunk::writeTo(uint8_t *Buf) {
|
||||
memcpy(Buf + FileOff, ImportThunkData, sizeof(ImportThunkData));
|
||||
// The first two bytes is a JMP instruction. Fill its operand.
|
||||
uint32_t Operand = ImpSymbol->getRVA() - RVA - getSize();
|
||||
uint32_t Operand = Config->is64()
|
||||
? ImpSymbol->getRVA() - RVA - getSize()
|
||||
: ImpSymbol->getRVA() + Config->ImageBase;
|
||||
write32le(Buf + FileOff + 2, Operand);
|
||||
}
|
||||
|
||||
|
|
|
@ -207,6 +207,13 @@ Undefined *LinkerDriver::addUndefined(StringRef Name) {
|
|||
return U;
|
||||
}
|
||||
|
||||
// Symbol names are mangled by appending "_" prefix on x86.
|
||||
StringRef LinkerDriver::mangle(StringRef Sym) {
|
||||
if (Config->MachineType == IMAGE_FILE_MACHINE_I386)
|
||||
return Alloc.save("_" + Sym);
|
||||
return Sym;
|
||||
}
|
||||
|
||||
// Windows specific -- find default entry point name.
|
||||
StringRef LinkerDriver::findDefaultEntry() {
|
||||
// User-defined main functions and their corresponding entry points.
|
||||
|
@ -217,9 +224,9 @@ StringRef LinkerDriver::findDefaultEntry() {
|
|||
{"wWinMain", "wWinMainCRTStartup"},
|
||||
};
|
||||
for (auto E : Entries) {
|
||||
Symbol *Sym = Symtab.find(E[0]);
|
||||
Symbol *Sym = Symtab.find(mangle(E[0]));
|
||||
if (Sym && !isa<Undefined>(Sym->Body))
|
||||
return E[1];
|
||||
return mangle(E[1]);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
@ -227,9 +234,9 @@ StringRef LinkerDriver::findDefaultEntry() {
|
|||
WindowsSubsystem LinkerDriver::inferSubsystem() {
|
||||
if (Config->DLL)
|
||||
return IMAGE_SUBSYSTEM_WINDOWS_GUI;
|
||||
if (Symtab.find("main") || Symtab.find("wmain"))
|
||||
if (Symtab.find(mangle("main")) || Symtab.find(mangle("wmain")))
|
||||
return IMAGE_SUBSYSTEM_WINDOWS_CUI;
|
||||
if (Symtab.find("WinMain") || Symtab.find("wWinMain"))
|
||||
if (Symtab.find(mangle("WinMain")) || Symtab.find(mangle("wWinMain")))
|
||||
return IMAGE_SUBSYSTEM_WINDOWS_GUI;
|
||||
return IMAGE_SUBSYSTEM_UNKNOWN;
|
||||
}
|
||||
|
@ -287,7 +294,7 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
|
|||
|
||||
// Handle /entry
|
||||
if (auto *Arg = Args.getLastArg(OPT_entry))
|
||||
Config->Entry = addUndefined(Arg->getValue());
|
||||
Config->Entry = addUndefined(mangle(Arg->getValue()));
|
||||
|
||||
// Handle /debug
|
||||
if (Args.hasArg(OPT_debug))
|
||||
|
@ -535,7 +542,7 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
|
|||
OwningMBs.push_back(std::move(MB)); // take ownership
|
||||
}
|
||||
|
||||
Symtab.addAbsolute("__ImageBase", Config->ImageBase);
|
||||
Symtab.addAbsolute(mangle("__ImageBase"), Config->ImageBase);
|
||||
|
||||
// Read all input files given via the command line. Note that step()
|
||||
// doesn't read files that are specified by directive sections.
|
||||
|
|
|
@ -93,6 +93,7 @@ private:
|
|||
std::set<std::string> VisitedFiles;
|
||||
|
||||
Undefined *addUndefined(StringRef Sym);
|
||||
StringRef mangle(StringRef Sym);
|
||||
|
||||
// Windows specific -- "main" is not the only main function in Windows.
|
||||
// You can choose one from these four -- {w,}{WinMain,main}.
|
||||
|
|
|
@ -395,8 +395,11 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
|
|||
COFF->Machine = Config->MachineType;
|
||||
COFF->NumberOfSections = OutputSections.size();
|
||||
COFF->Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE;
|
||||
if (Is64)
|
||||
if (Is64) {
|
||||
COFF->Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
|
||||
} else {
|
||||
COFF->Characteristics |= IMAGE_FILE_32BIT_MACHINE;
|
||||
}
|
||||
if (Config->DLL)
|
||||
COFF->Characteristics |= IMAGE_FILE_DLL;
|
||||
if (!Config->Relocatable)
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
# 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 -file-headers %t.exe | FileCheck -check-prefix=HEADER %s
|
||||
# RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORTS %s
|
||||
|
||||
HEADER: Format: COFF-i386
|
||||
HEADER-NEXT: Arch: i386
|
||||
HEADER-NEXT: AddressSize: 32bit
|
||||
HEADER-NEXT: ImageFileHeader {
|
||||
HEADER-NEXT: Machine: IMAGE_FILE_MACHINE_I386 (0x14C)
|
||||
HEADER-NEXT: SectionCount: 3
|
||||
HEADER-NEXT: TimeDateStamp: 1970-01-01 00:00:00 (0x0)
|
||||
HEADER-NEXT: PointerToSymbolTable: 0x0
|
||||
HEADER-NEXT: SymbolCount: 0
|
||||
HEADER-NEXT: OptionalHeaderSize: 224
|
||||
HEADER-NEXT: Characteristics [ (0x102)
|
||||
HEADER-NEXT: IMAGE_FILE_32BIT_MACHINE (0x100)
|
||||
HEADER-NEXT: IMAGE_FILE_EXECUTABLE_IMAGE (0x2)
|
||||
HEADER-NEXT: ]
|
||||
HEADER-NEXT: }
|
||||
HEADER-NEXT: ImageOptionalHeader {
|
||||
HEADER-NEXT: MajorLinkerVersion: 0
|
||||
HEADER-NEXT: MinorLinkerVersion: 0
|
||||
HEADER-NEXT: SizeOfCode: 512
|
||||
HEADER-NEXT: SizeOfInitializedData: 1024
|
||||
HEADER-NEXT: SizeOfUninitializedData: 0
|
||||
HEADER-NEXT: AddressOfEntryPoint: 0x2000
|
||||
HEADER-NEXT: BaseOfCode: 0x2000
|
||||
HEADER-NEXT: BaseOfData: 0x0
|
||||
HEADER-NEXT: ImageBase: 0x40000000
|
||||
HEADER-NEXT: SectionAlignment: 4096
|
||||
HEADER-NEXT: FileAlignment: 512
|
||||
HEADER-NEXT: MajorOperatingSystemVersion: 6
|
||||
HEADER-NEXT: MinorOperatingSystemVersion: 0
|
||||
HEADER-NEXT: MajorImageVersion: 0
|
||||
HEADER-NEXT: MinorImageVersion: 0
|
||||
HEADER-NEXT: MajorSubsystemVersion: 6
|
||||
HEADER-NEXT: MinorSubsystemVersion: 0
|
||||
HEADER-NEXT: SizeOfImage: 16384
|
||||
HEADER-NEXT: SizeOfHeaders: 4096
|
||||
HEADER-NEXT: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI (0x3)
|
||||
HEADER-NEXT: Characteristics [ (0x8160)
|
||||
HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE (0x40)
|
||||
HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA (0x20)
|
||||
HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_NX_COMPAT (0x100)
|
||||
HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE (0x8000)
|
||||
HEADER-NEXT: ]
|
||||
HEADER-NEXT: SizeOfStackReserve: 1048576
|
||||
HEADER-NEXT: SizeOfStackCommit: 4096
|
||||
HEADER-NEXT: SizeOfHeapReserve: 1048576
|
||||
HEADER-NEXT: SizeOfHeapCommit: 4096
|
||||
HEADER-NEXT: NumberOfRvaAndSize: 16
|
||||
HEADER-NEXT: DataDirectory {
|
||||
HEADER-NEXT: ExportTableRVA: 0x0
|
||||
HEADER-NEXT: ExportTableSize: 0x0
|
||||
HEADER-NEXT: ImportTableRVA: 0x3000
|
||||
HEADER-NEXT: ImportTableSize: 0x28
|
||||
HEADER-NEXT: ResourceTableRVA: 0x0
|
||||
HEADER-NEXT: ResourceTableSize: 0x0
|
||||
HEADER-NEXT: ExceptionTableRVA: 0x0
|
||||
HEADER-NEXT: ExceptionTableSize: 0x0
|
||||
HEADER-NEXT: CertificateTableRVA: 0x0
|
||||
HEADER-NEXT: CertificateTableSize: 0x0
|
||||
HEADER-NEXT: BaseRelocationTableRVA: 0x0
|
||||
HEADER-NEXT: BaseRelocationTableSize: 0x0
|
||||
HEADER-NEXT: DebugRVA: 0x0
|
||||
HEADER-NEXT: DebugSize: 0x0
|
||||
HEADER-NEXT: ArchitectureRVA: 0x0
|
||||
HEADER-NEXT: ArchitectureSize: 0x0
|
||||
HEADER-NEXT: GlobalPtrRVA: 0x0
|
||||
HEADER-NEXT: GlobalPtrSize: 0x0
|
||||
HEADER-NEXT: TLSTableRVA: 0x0
|
||||
HEADER-NEXT: TLSTableSize: 0x0
|
||||
HEADER-NEXT: LoadConfigTableRVA: 0x0
|
||||
HEADER-NEXT: LoadConfigTableSize: 0x0
|
||||
HEADER-NEXT: BoundImportRVA: 0x0
|
||||
HEADER-NEXT: BoundImportSize: 0x0
|
||||
HEADER-NEXT: IATRVA: 0x3034
|
||||
HEADER-NEXT: IATSize: 0xC
|
||||
HEADER-NEXT: DelayImportDescriptorRVA: 0x0
|
||||
HEADER-NEXT: DelayImportDescriptorSize: 0x0
|
||||
HEADER-NEXT: CLRRuntimeHeaderRVA: 0x0
|
||||
HEADER-NEXT: CLRRuntimeHeaderSize: 0x0
|
||||
HEADER-NEXT: ReservedRVA: 0x0
|
||||
HEADER-NEXT: ReservedSize: 0x0
|
||||
HEADER-NEXT: }
|
||||
HEADER-NEXT: }
|
||||
HEADER-NEXT: DOSHeader {
|
||||
HEADER-NEXT: Magic: MZ
|
||||
HEADER-NEXT: UsedBytesInTheLastPage: 0
|
||||
HEADER-NEXT: FileSizeInPages: 0
|
||||
HEADER-NEXT: NumberOfRelocationItems: 0
|
||||
HEADER-NEXT: HeaderSizeInParagraphs: 0
|
||||
HEADER-NEXT: MinimumExtraParagraphs: 0
|
||||
HEADER-NEXT: MaximumExtraParagraphs: 0
|
||||
HEADER-NEXT: InitialRelativeSS: 0
|
||||
HEADER-NEXT: InitialSP: 0
|
||||
HEADER-NEXT: Checksum: 0
|
||||
HEADER-NEXT: InitialIP: 0
|
||||
HEADER-NEXT: InitialRelativeCS: 0
|
||||
HEADER-NEXT: AddressOfRelocationTable: 64
|
||||
HEADER-NEXT: OverlayNumber: 0
|
||||
HEADER-NEXT: OEMid: 0
|
||||
HEADER-NEXT: OEMinfo: 0
|
||||
HEADER-NEXT: AddressOfNewExeHeader: 64
|
||||
HEADER-NEXT: }
|
||||
|
||||
IMPORTS: Format: COFF-i386
|
||||
IMPORTS: Arch: i386
|
||||
IMPORTS: AddressSize: 32bit
|
||||
IMPORTS: Import {
|
||||
IMPORTS: Name: std32.dll
|
||||
IMPORTS: ImportLookupTableRVA: 0x3028
|
||||
IMPORTS: ImportAddressTableRVA: 0x3034
|
||||
IMPORTS: Symbol: ExitProcess (0)
|
||||
IMPORTS: Symbol: MessageBoxA (1)
|
||||
IMPORTS: }
|
|
@ -1,15 +0,0 @@
|
|||
# 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: }
|
|
@ -11,14 +11,14 @@
|
|||
# RUN: lld -flavor link2 /entry:main /subsystem:console /out:%t.exe %t.obj
|
||||
# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=I386 %s
|
||||
# RUN: lld -flavor link2 /entry:main /subsystem:console /machine:x86 \
|
||||
# RUN: /out:%t.exe %t.obj
|
||||
# RUN: /out:%t.exe %t.obj /fixed
|
||||
# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=I386 %s
|
||||
|
||||
# I386: Machine: IMAGE_FILE_MACHINE_I386
|
||||
|
||||
# RUN: sed -e s/MACHINETYPE/IMAGE_FILE_MACHINE_AMD64/ %s | yaml2obj > %t.obj
|
||||
# RUN: not lld -flavor link2 /entry:main /subsystem:console /machine:x86 \
|
||||
# RUN: /out:%t.exe %t.obj >& %t.log
|
||||
# RUN: /out:%t.exe %t.obj /fixed >& %t.log
|
||||
# RUN: FileCheck -check-prefix=INCOMPAT %s < %t.log
|
||||
|
||||
# RUN: sed -e s/MACHINETYPE/IMAGE_FILE_MACHINE_I386/ %s | yaml2obj > %t1.obj
|
||||
|
|
Loading…
Reference in New Issue