Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/llvm/llvm-project.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2015-07-09 22:54:13 +0300
committerRui Ueyama <ruiu@google.com>2015-07-09 22:54:13 +0300
commitea533cde30df7b9941b27606168e0664344f580d (patch)
tree56dbcffc7c2a0f5edafb7ecb9474223d3c9571c6 /lld/COFF/Driver.cpp
parent594e676cbe475dc879980e919731c3614aa083eb (diff)
COFF: Infer machine type earlier than before.
Previously, we infer machine type at the very end of linking after all symbols are resolved. That's actually too late because machine type affects how we mangle symbols (whether or not we need to add "_"). For example, /entry:foo adds "_foo" to the symbol table if x86 but "foo" if x64. This patch moves the code to infer machine type, so that machine type is inferred based on input files given via the command line (but not based on .directives files). llvm-svn: 241843
Diffstat (limited to 'lld/COFF/Driver.cpp')
-rw-r--r--lld/COFF/Driver.cpp104
1 files changed, 57 insertions, 47 deletions
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index 522bc9bf0f9f..01280b68f4d7 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -209,6 +209,7 @@ Undefined *LinkerDriver::addUndefined(StringRef Name) {
// Symbol names are mangled by appending "_" prefix on x86.
StringRef LinkerDriver::mangle(StringRef Sym) {
+ assert(Config->MachineType != IMAGE_FILE_MACHINE_UNKNOWN);
if (Config->MachineType == IMAGE_FILE_MACHINE_I386)
return Alloc.save("_" + Sym);
return Sym;
@@ -293,8 +294,9 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
Config->Force = true;
// Handle /entry
+ StringRef Entry;
if (auto *Arg = Args.getLastArg(OPT_entry))
- Config->Entry = addUndefined(mangle(Arg->getValue()));
+ Entry = Arg->getValue();
// Handle /debug
if (Args.hasArg(OPT_debug))
@@ -314,8 +316,8 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
Config->DLL = true;
Config->ImageBase = 0x180000000U;
Config->ManifestID = 2;
- if (Config->Entry == nullptr && !Config->NoEntry)
- Config->Entry = addUndefined("_DllMainCRTStartup");
+ if (Entry.empty() && !Config->NoEntry)
+ Entry = "_DllMainCRTStartup";
}
// Handle /fixed
@@ -497,21 +499,21 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
// Create a list of input files. Files can be given as arguments
// for /defaultlib option.
- std::vector<StringRef> InputPaths;
- std::vector<MemoryBufferRef> Inputs;
+ std::vector<StringRef> Paths;
+ std::vector<MemoryBufferRef> MBs;
for (auto *Arg : Args.filtered(OPT_INPUT))
if (Optional<StringRef> Path = findFile(Arg->getValue()))
- InputPaths.push_back(*Path);
+ Paths.push_back(*Path);
for (auto *Arg : Args.filtered(OPT_defaultlib))
if (Optional<StringRef> Path = findLib(Arg->getValue()))
- InputPaths.push_back(*Path);
- for (StringRef Path : InputPaths) {
+ Paths.push_back(*Path);
+ for (StringRef Path : Paths) {
ErrorOr<MemoryBufferRef> MBOrErr = openFile(Path);
if (auto EC = MBOrErr.getError()) {
llvm::errs() << "cannot open " << Path << ": " << EC.message() << "\n";
return false;
}
- Inputs.push_back(MBOrErr.get());
+ MBs.push_back(MBOrErr.get());
}
// Windows specific -- Create a resource file containing a manifest file.
@@ -520,42 +522,72 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
if (MBOrErr.getError())
return false;
std::unique_ptr<MemoryBuffer> MB = std::move(MBOrErr.get());
- Inputs.push_back(MB->getMemBufferRef());
+ MBs.push_back(MB->getMemBufferRef());
OwningMBs.push_back(std::move(MB)); // take ownership
}
// Windows specific -- Input files can be Windows resource files (.res files).
// We invoke cvtres.exe to convert resource files to a regular COFF file
// then link the result file normally.
+ std::vector<MemoryBufferRef> Resources;
auto NotResource = [](MemoryBufferRef MB) {
return identify_magic(MB.getBuffer()) != file_magic::windows_resource;
};
- auto It = std::stable_partition(Inputs.begin(), Inputs.end(), NotResource);
- if (It != Inputs.end()) {
- std::vector<MemoryBufferRef> Files(It, Inputs.end());
- auto MBOrErr = convertResToCOFF(Files);
- if (MBOrErr.getError())
- return false;
- std::unique_ptr<MemoryBuffer> MB = std::move(MBOrErr.get());
- Inputs.erase(It, Inputs.end());
- Inputs.push_back(MB->getMemBufferRef());
- OwningMBs.push_back(std::move(MB)); // take ownership
+ auto It = std::stable_partition(MBs.begin(), MBs.end(), NotResource);
+ if (It != MBs.end()) {
+ Resources.insert(Resources.end(), It, MBs.end());
+ MBs.erase(It, MBs.end());
}
- 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.
- for (MemoryBufferRef MB : Inputs)
+ for (MemoryBufferRef MB : MBs)
Symtab.addFile(createFile(MB));
if (auto EC = Symtab.step()) {
llvm::errs() << EC.message() << "\n";
return false;
}
+ // Determine machine type and check if all object files are
+ // for the same CPU type. Note that this needs to be done before
+ // any call to mangle().
+ for (std::unique_ptr<InputFile> &File : Symtab.getFiles()) {
+ MachineTypes MT = File->getMachineType();
+ 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() << "warning: /machine is not specified. x64 is assumed.\n";
+ Config->MachineType = IMAGE_FILE_MACHINE_AMD64;
+ }
+
+ // Windows specific -- Convert Windows resource files to a COFF file.
+ if (!Resources.empty()) {
+ auto MBOrErr = convertResToCOFF(Resources);
+ if (MBOrErr.getError())
+ return false;
+ std::unique_ptr<MemoryBuffer> MB = std::move(MBOrErr.get());
+ Symtab.addFile(createFile(MB->getMemBufferRef()));
+ OwningMBs.push_back(std::move(MB)); // take ownership
+ }
+
+ if (!Entry.empty())
+ Config->Entry = addUndefined(mangle(Entry));
+ Symtab.addAbsolute(mangle("__ImageBase"), Config->ImageBase);
+
// Windows specific -- If entry point name is not given, we need to
// infer that from user-defined entry name.
- if (Config->Entry == nullptr && !Config->NoEntry) {
+ if (Entry.empty() && !Config->NoEntry) {
StringRef S = findDefaultEntry();
if (S.empty()) {
llvm::errs() << "entry point must be defined\n";
@@ -566,7 +598,7 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
llvm::outs() << "Entry name inferred: " << S << "\n";
}
- // Read as much files as we can.
+ // Read as much files as we can from directives sections.
if (auto EC = Symtab.run()) {
llvm::errs() << EC.message() << "\n";
return false;
@@ -630,28 +662,6 @@ 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())