Skip to content

Commit

Permalink
COFF: Move machine type auto-detection to SymbolTable.
Browse files Browse the repository at this point in the history
The new mechanism is less code, and fixes the case where all inputs
are archives.

Differential Revision: http://reviews.llvm.org/D10136

llvm-svn: 238618
  • Loading branch information
pcc committed May 29, 2015
1 parent 4d37b2a commit 246ccc5
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 27 deletions.
25 changes: 0 additions & 25 deletions lld/COFF/DriverUtils.cpp
Expand Up @@ -87,24 +87,6 @@ std::string findFile(StringRef Filename) {
return Filename;
}

// Peeks at the file header to get architecture (e.g. i386 or AMD64).
// Returns "unknown" if it's not a valid object file.
static MachineTypes getFileMachineType(StringRef Path) {
file_magic Magic;
if (identify_magic(Path, Magic))
return IMAGE_FILE_MACHINE_UNKNOWN;
if (Magic != file_magic::coff_object)
return IMAGE_FILE_MACHINE_UNKNOWN;
ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = MemoryBuffer::getFile(Path);
if (BufOrErr.getError())
return IMAGE_FILE_MACHINE_UNKNOWN;
std::error_code EC;
llvm::object::COFFObjectFile Obj(BufOrErr.get()->getMemBufferRef(), EC);
if (EC)
return IMAGE_FILE_MACHINE_UNKNOWN;
return static_cast<MachineTypes>(Obj.getMachine());
}

// Returns /machine's value.
ErrorOr<MachineTypes> getMachineType(llvm::opt::InputArgList *Args) {
if (auto *Arg = Args->getLastArg(OPT_machine)) {
Expand All @@ -118,13 +100,6 @@ ErrorOr<MachineTypes> getMachineType(llvm::opt::InputArgList *Args) {
return make_dynamic_error_code("unknown /machine argument" + S);
return MT;
}
// If /machine option is missing, we need to take a look at
// the magic byte of the first object file to infer machine type.
for (auto *Arg : Args->filtered(OPT_INPUT)) {
MachineTypes MT = getFileMachineType(Arg->getValue());
if (MT != IMAGE_FILE_MACHINE_UNKNOWN)
return MT;
}
return IMAGE_FILE_MACHINE_UNKNOWN;
}

Expand Down
4 changes: 3 additions & 1 deletion lld/COFF/SymbolTable.h
Expand Up @@ -53,6 +53,9 @@ class SymbolTable {
// order to create the import descriptor table.
std::vector<std::unique_ptr<ImportFile>> ImportFiles;

// The writer needs to infer the machine type from the object files.
std::vector<std::unique_ptr<ObjectFile>> ObjectFiles;

private:
std::error_code addObject(ObjectFile *File);
std::error_code addArchive(ArchiveFile *File);
Expand All @@ -63,7 +66,6 @@ class SymbolTable {
void addInitialSymbol(SymbolBody *Body);

std::unordered_map<StringRef, Symbol *> Symtab;
std::vector<std::unique_ptr<ObjectFile>> ObjectFiles;
std::vector<std::unique_ptr<ArchiveFile>> ArchiveFiles;
std::vector<std::unique_ptr<SymbolBody>> OwnedSymbols;
llvm::BumpPtrAllocator Alloc;
Expand Down
18 changes: 17 additions & 1 deletion lld/COFF/Writer.cpp
Expand Up @@ -227,6 +227,17 @@ void Writer::assignAddresses() {
RoundUpToAlignment(FileOff - SizeOfHeaders, FileAlignment);
}

static MachineTypes
inferMachineType(std::vector<std::unique_ptr<ObjectFile>> &ObjectFiles) {
for (std::unique_ptr<ObjectFile> &File : ObjectFiles) {
// Try to infer machine type from the magic byte of the object file.
auto MT = static_cast<MachineTypes>(File->getCOFFObj()->getMachine());
if (MT != IMAGE_FILE_MACHINE_UNKNOWN)
return MT;
}
return IMAGE_FILE_MACHINE_UNKNOWN;
}

void Writer::writeHeader() {
// Write DOS stub
uint8_t *Buf = Buffer->getBufferStart();
Expand All @@ -241,10 +252,15 @@ void Writer::writeHeader() {
memcpy(Buf, PEMagic, sizeof(PEMagic));
Buf += sizeof(PEMagic);

// Determine machine type, infer if needed. TODO: diagnose conflicts.
MachineTypes MachineType = Config->MachineType;
if (MachineType == IMAGE_FILE_MACHINE_UNKNOWN)
MachineType = inferMachineType(Symtab->ObjectFiles);

// Write COFF header
auto *COFF = reinterpret_cast<coff_file_header *>(Buf);
Buf += sizeof(*COFF);
COFF->Machine = Config->MachineType;
COFF->Machine = MachineType;
COFF->NumberOfSections = OutputSections.size();
COFF->Characteristics =
(IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_RELOCS_STRIPPED |
Expand Down
Binary file added lld/test/COFF/Inputs/ret42.lib
Binary file not shown.
9 changes: 9 additions & 0 deletions lld/test/COFF/machine.test
@@ -1,6 +1,15 @@
# RUN: lld -flavor link2 /entry:main /machine:x64 /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 /machine:x64 /out:%t.exe \
# RUN: %p/Inputs/ret42.lib
# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=AMD64 %s
# RUN: lld -flavor link2 /entry:main /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 /out:%t.exe \
# RUN: %p/Inputs/ret42.lib
# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=AMD64 %s

AMD64: Machine: IMAGE_FILE_MACHINE_AMD64

Expand Down

0 comments on commit 246ccc5

Please sign in to comment.