aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp')
-rw-r--r--llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp85
1 files changed, 85 insertions, 0 deletions
diff --git a/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp b/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
index 2d44686..0b58c54 100644
--- a/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
+++ b/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
@@ -13,8 +13,11 @@
#include "llvm/ToolDrivers/llvm-lib/LibDriver.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/BinaryFormat/COFF.h"
#include "llvm/BinaryFormat/Magic.h"
+#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/Object/ArchiveWriter.h"
+#include "llvm/Object/COFF.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
@@ -137,6 +140,21 @@ static void doList(opt::InputArgList& Args) {
fatalOpenError(std::move(Err), B->getBufferIdentifier());
}
+static StringRef machineToStr(COFF::MachineTypes MT) {
+ switch (MT) {
+ case COFF::IMAGE_FILE_MACHINE_ARMNT:
+ return "arm";
+ case COFF::IMAGE_FILE_MACHINE_ARM64:
+ return "arm64";
+ case COFF::IMAGE_FILE_MACHINE_AMD64:
+ return "x64";
+ case COFF::IMAGE_FILE_MACHINE_I386:
+ return "x86";
+ default:
+ llvm_unreachable("unknown machine type");
+ }
+}
+
int llvm::libDriverMain(ArrayRef<const char *> ArgsArr) {
BumpPtrAllocator Alloc;
StringSaver Saver(Alloc);
@@ -180,6 +198,7 @@ int llvm::libDriverMain(ArrayRef<const char *> ArgsArr) {
// Create a NewArchiveMember for each input file.
std::vector<NewArchiveMember> Members;
+ COFF::MachineTypes LibMachine = COFF::IMAGE_FILE_MACHINE_UNKNOWN;
for (auto *Arg : Args.filtered(OPT_INPUT)) {
std::string Path = findInputFile(Arg->getValue(), SearchPaths);
if (Path.empty()) {
@@ -203,6 +222,72 @@ int llvm::libDriverMain(ArrayRef<const char *> ArgsArr) {
<< ": not a COFF object, bitcode or resource file\n";
return 1;
}
+
+ // Check that all input files have the same machine type.
+ // Mixing normal objects and LTO bitcode files is fine as long as they
+ // have the same machine type.
+ // Doing this here duplicates the header parsing work that writeArchive()
+ // below does, but it's not a lot of work and it's a bit awkward to do
+ // in writeArchive() which needs to support many tools, can't assume the
+ // input is COFF, and doesn't have a good way to report errors.
+ COFF::MachineTypes FileMachine = COFF::IMAGE_FILE_MACHINE_UNKNOWN;
+ if (Magic == file_magic::coff_object) {
+ std::error_code EC;
+ object::COFFObjectFile Obj(*MOrErr->Buf, EC);
+ if (EC) {
+ llvm::errs() << Arg->getValue() << ": failed to open: " << EC.message()
+ << '\n';
+ return 1;
+ }
+ uint16_t Machine = Obj.getMachine();
+ if (Machine != COFF::IMAGE_FILE_MACHINE_I386 &&
+ Machine != COFF::IMAGE_FILE_MACHINE_AMD64 &&
+ Machine != COFF::IMAGE_FILE_MACHINE_ARMNT &&
+ Machine != COFF::IMAGE_FILE_MACHINE_ARM64) {
+ llvm::errs() << Arg->getValue() << ": unknown machine: " << Machine
+ << '\n';
+ return 1;
+ }
+ FileMachine = static_cast<COFF::MachineTypes>(Machine);
+ } else if (Magic == file_magic::bitcode) {
+ Expected<std::string> TripleStr = getBitcodeTargetTriple(*MOrErr->Buf);
+ if (!TripleStr) {
+ llvm::errs() << Arg->getValue()
+ << ": failed to get target triple from bitcode\n";
+ return 1;
+ }
+ switch (Triple(*TripleStr).getArch()) {
+ case Triple::x86:
+ FileMachine = COFF::IMAGE_FILE_MACHINE_I386;
+ break;
+ case Triple::x86_64:
+ FileMachine = COFF::IMAGE_FILE_MACHINE_AMD64;
+ break;
+ case Triple::arm:
+ FileMachine = COFF::IMAGE_FILE_MACHINE_ARMNT;
+ break;
+ case Triple::aarch64:
+ FileMachine = COFF::IMAGE_FILE_MACHINE_ARM64;
+ break;
+ default:
+ llvm::errs() << Arg->getValue() << ": unknown arch in target triple "
+ << *TripleStr << '\n';
+ return 1;
+ }
+ }
+
+ if (FileMachine != COFF::IMAGE_FILE_MACHINE_UNKNOWN) {
+ if (LibMachine == COFF::IMAGE_FILE_MACHINE_UNKNOWN)
+ LibMachine = FileMachine;
+ else if (LibMachine != FileMachine) {
+ llvm::errs() << Arg->getValue() << ": file machine type "
+ << machineToStr(FileMachine)
+ << " conflicts with library machine type "
+ << machineToStr(LibMachine) << '\n';
+ return 1;
+ }
+ }
+
Members.emplace_back(std::move(*MOrErr));
}