Index: COFF/Driver.h =================================================================== --- COFF/Driver.h +++ COFF/Driver.h @@ -118,6 +118,7 @@ // For /machine option. ErrorOr getMachineType(llvm::opt::InputArgList *Args); +StringRef machineTypeToStr(MachineTypes MT); // Parses a string in the form of "[,]". std::error_code parseNumbers(StringRef Arg, uint64_t *Addr, Index: COFF/Driver.cpp =================================================================== --- COFF/Driver.cpp +++ COFF/Driver.cpp @@ -30,9 +30,7 @@ #include using namespace llvm; -using llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN; -using llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI; -using llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI; +using namespace llvm::COFF; using llvm::sys::Process; using llvm::sys::fs::OpenFlags; using llvm::sys::fs::file_magic; @@ -625,6 +623,28 @@ } } + // Check if all object files are for the same CPU type and + // compatible with /machine option (if given). + for (ObjectFile *File : Symtab.ObjectFiles) { + auto MT = static_cast(File->getCOFFObj()->getMachine()); + if (MT == IMAGE_FILE_MACHINE_UNKNOWN) + continue; + if (Config->MachineType == IMAGE_FILE_MACHINE_UNKNOWN) { + Config->MachineType = MT; + continue; + } + if (Config->MachineType != MT) { + llvm::errs() << File->getShortName() << ": machine type " + << machineTypeToStr(MT) << " conflicts with " + << machineTypeToStr(Config->MachineType) << "\n"; + return false; + } + } + if (Config->MachineType == IMAGE_FILE_MACHINE_UNKNOWN) { + llvm::errs() << "machine type must be specified\n"; + return false; + } + // Windows specific -- when we are creating a .dll file, we also // need to create a .lib file. if (!Config->Exports.empty()) Index: COFF/DriverUtils.cpp =================================================================== --- COFF/DriverUtils.cpp +++ COFF/DriverUtils.cpp @@ -96,6 +96,19 @@ return IMAGE_FILE_MACHINE_UNKNOWN; } +StringRef machineTypeToStr(MachineTypes MT) { + switch (MT) { + case IMAGE_FILE_MACHINE_ARMNT: + return "arm"; + case IMAGE_FILE_MACHINE_AMD64: + return "x64"; + case IMAGE_FILE_MACHINE_I386: + return "x86"; + default: + llvm_unreachable("unknown machine type"); + } +} + // Parses a string in the form of "[,]". std::error_code parseNumbers(StringRef Arg, uint64_t *Addr, uint64_t *Size) { StringRef S1, S2; Index: COFF/InputFiles.cpp =================================================================== --- COFF/InputFiles.cpp +++ COFF/InputFiles.cpp @@ -111,11 +111,6 @@ llvm::errs() << getName() << " is not a COFF file.\n"; return make_error_code(LLDError::InvalidFile); } - if (COFFObj->getMachine() != IMAGE_FILE_MACHINE_AMD64 && - COFFObj->getMachine() != IMAGE_FILE_MACHINE_UNKNOWN) { - llvm::errs() << getName() << " is not an x64 object file.\n"; - return make_error_code(LLDError::InvalidFile); - } // Read section and symbol tables. if (auto EC = initializeChunks()) Index: test/COFF/machine.test =================================================================== --- test/COFF/machine.test +++ test/COFF/machine.test @@ -1,20 +1,54 @@ -# RUN: lld -flavor link2 /entry:main /subsystem:console /machine:x64 \ -# RUN: /out:%t.exe %p/Inputs/ret42.obj +# RUN: sed -e s/MACHINETYPE/IMAGE_FILE_MACHINE_AMD64/ %s | yaml2obj > %t.obj +# RUN: lld -flavor link2 /entry:main /subsystem:console /out:%t.exe %t.obj # RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=AMD64 %s # RUN: lld -flavor link2 /entry:main /subsystem:console /machine:x64 \ -# RUN: /out:%t.exe %p/Inputs/ret42.lib -# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=AMD64 %s -# RUN: lld -flavor link2 /entry:main /subsystem:console /out:%t.exe \ -# RUN: %p/Inputs/ret42.obj -# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=AMD64 %s -# RUN: lld -flavor link2 /entry:main /subsystem:console /out:%t.exe \ -# RUN: %p/Inputs/ret42.lib +# RUN: /out:%t.exe %t.obj # RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=AMD64 %s -AMD64: Machine: IMAGE_FILE_MACHINE_AMD64 +# AMD64: Machine: IMAGE_FILE_MACHINE_AMD64 +# RUN: sed -e s/MACHINETYPE/IMAGE_FILE_MACHINE_I386/ %s | yaml2obj > %t.obj +# 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 %p/Inputs/ret42.obj +# RUN: /out:%t.exe %t.obj # RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=I386 %s -I386: Machine: IMAGE_FILE_MACHINE_I386 +# 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 %p/Inputs/ret42.obj >& %t.log +# RUN: FileCheck -check-prefix=INCOMPAT %s < %t.log + +# INCOMPAT: ret42.obj: machine type x64 conflicts with x86 + +--- +header: + Machine: MACHINETYPE + Characteristics: [ ] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: 000000000000 +symbols: + - Name: .text + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 6 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: main + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +...