COFF: Check for incompatible machine types.

llvm-svn: 241647
This commit is contained in:
Rui Ueyama 2015-07-07 23:39:18 +00:00
parent ed6edbf17a
commit 84936e0b43
5 changed files with 90 additions and 20 deletions

View File

@ -30,9 +30,7 @@
#include <memory>
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 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
}
}
// 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<MachineTypes>(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())

View File

@ -118,6 +118,7 @@ void printHelp(const char *Argv0);
// For /machine option.
ErrorOr<MachineTypes> getMachineType(llvm::opt::InputArgList *Args);
StringRef machineTypeToStr(MachineTypes MT);
// Parses a string in the form of "<integer>[,<integer>]".
std::error_code parseNumbers(StringRef Arg, uint64_t *Addr,

View File

@ -96,6 +96,19 @@ ErrorOr<MachineTypes> getMachineType(llvm::opt::InputArgList *Args) {
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 "<integer>[,<integer>]".
std::error_code parseNumbers(StringRef Arg, uint64_t *Addr, uint64_t *Size) {
StringRef S1, S2;

View File

@ -111,11 +111,6 @@ std::error_code ObjectFile::parse() {
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())

View File

@ -1,20 +1,61 @@
# 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 %t.obj >& %t.log
# RUN: FileCheck -check-prefix=INCOMPAT %s < %t.log
# RUN: sed -e s/MACHINETYPE/IMAGE_FILE_MACHINE_I386/ %s | yaml2obj > %t1.obj
# RUN: sed -e s/MACHINETYPE/IMAGE_FILE_MACHINE_AMD64/ %s | \
# RUN: sed -e s/main/foo/ | yaml2obj > %t2.obj
# RUN: not lld -flavor link2 /entry:main /subsystem:console /out:%t.exe \
# RUN: %t1.obj %t2.obj >& %t.log
# RUN: FileCheck -check-prefix=INCOMPAT %s < %t.log
# INCOMPAT: .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
...