summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
diff options
context:
space:
mode:
authorNick Kledzik <kledzik@apple.com>2014-09-04 20:08:30 +0000
committerNick Kledzik <kledzik@apple.com>2014-09-04 20:08:30 +0000
commit635f9c71589dd2cb80257e29aa02c5e5dd03742b (patch)
treeb0a68779a7099d805d0187d8ae9bd872da0ad3c6 /lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
parent9b3e3dfc54d9823074407323b0a60ebd223cd721 (diff)
downloadbcm5719-llvm-635f9c71589dd2cb80257e29aa02c5e5dd03742b.tar.gz
bcm5719-llvm-635f9c71589dd2cb80257e29aa02c5e5dd03742b.zip
[mach-o] Let darwin driver infer arch from .o files if -arch not used.
Mach-O has a "fat" (or "universal") variant where the same contents built for different architectures are concatenated into one file with a table-of-contents header at the start. But this leaves a dilemma for the linker - which architecture to use. Normally, the linker command line -arch is used to force which slice of any fat files are used. The clang compiler always passes -arch to the linker when invoking it. But some Makefiles invoke the linker directly and don’t specify the -arch option. For those cases, the linker scans all input files in command line order and finds the first non-fat object file. Whatever architecture it is becomes the architecture for the link. llvm-svn: 217189
Diffstat (limited to 'lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp')
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp73
1 files changed, 54 insertions, 19 deletions
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
index 6fcee3bf059..9997ca0245c 100644
--- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
@@ -117,6 +117,59 @@ template <typename T> static T readBigEndian(T t) {
return t;
}
+
+static bool isMachOHeader(const mach_header *mh, bool &is64, bool &swap) {
+ switch (mh->magic) {
+ case llvm::MachO::MH_MAGIC:
+ is64 = false;
+ swap = false;
+ return true;
+ case llvm::MachO::MH_MAGIC_64:
+ is64 = true;
+ swap = false;
+ return true;
+ case llvm::MachO::MH_CIGAM:
+ is64 = false;
+ swap = true;
+ return true;
+ case llvm::MachO::MH_CIGAM_64:
+ is64 = true;
+ swap = true;
+ return true;
+ default:
+ return false;
+ }
+}
+
+
+bool isThinObjectFile(StringRef path, MachOLinkingContext::Arch &arch) {
+ // Try opening and mapping file at path.
+ ErrorOr<std::unique_ptr<MemoryBuffer>> b = MemoryBuffer::getFileOrSTDIN(path);
+ if (b.getError())
+ return false;
+
+ // If file length < 32 it is too small to be mach-o object file.
+ StringRef fileBuffer = b->get()->getBuffer();
+ if (fileBuffer.size() < 32)
+ return false;
+
+ // If file buffer does not start with MH_MAGIC (and variants), not obj file.
+ const mach_header *mh = reinterpret_cast<const mach_header *>(
+ fileBuffer.begin());
+ bool is64, swap;
+ if (!isMachOHeader(mh, is64, swap))
+ return false;
+
+ // If not MH_OBJECT, not object file.
+ if (read32(swap, mh->filetype) != MH_OBJECT)
+ return false;
+
+ // Lookup up arch from cpu/subtype pair.
+ arch = MachOLinkingContext::archFromCpuType(read32(swap, mh->cputype),
+ read32(swap, mh->cpusubtype));
+ return true;
+}
+
/// Reads a mach-o file and produces an in-memory normalized view.
ErrorOr<std::unique_ptr<NormalizedFile>>
readBinary(std::unique_ptr<MemoryBuffer> &mb,
@@ -162,26 +215,8 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb,
}
bool is64, swap;
- switch (mh->magic) {
- case llvm::MachO::MH_MAGIC:
- is64 = false;
- swap = false;
- break;
- case llvm::MachO::MH_MAGIC_64:
- is64 = true;
- swap = false;
- break;
- case llvm::MachO::MH_CIGAM:
- is64 = false;
- swap = true;
- break;
- case llvm::MachO::MH_CIGAM_64:
- is64 = true;
- swap = true;
- break;
- default:
+ if (!isMachOHeader(mh, is64, swap))
return make_error_code(llvm::errc::executable_format_error);
- }
// Endian swap header, if needed.
mach_header headerCopy;
OpenPOWER on IntegriCloud