summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp')
-rw-r--r--lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp247
1 files changed, 204 insertions, 43 deletions
diff --git a/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp b/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp
index 0b2d0772294..f60f32ea43c 100644
--- a/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp
@@ -10,83 +10,244 @@
#include "lld/ReaderWriter/MachOTargetInfo.h"
#include "GOTPass.hpp"
#include "StubsPass.hpp"
+#include "ReferenceKinds.h"
+#include "MachOFormat.hpp"
-#include "lld/Core/LinkerOptions.h"
#include "lld/Core/PassManager.h"
+#include "lld/ReaderWriter/Reader.h"
+#include "lld/ReaderWriter/Writer.h"
#include "lld/Passes/LayoutPass.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/Support/MachO.h"
+
+using lld::mach_o::KindHandler;
+
namespace lld {
+
+
+MachOTargetInfo::PackedVersion::PackedVersion(StringRef str) {
+ if (parse(str, *this))
+ llvm_unreachable("bad version string");
+}
+
+/// Construct 32-bit PackedVersion from string "X.Y.Z" where
+/// bits are xxxx.yy.zz. Largest number is 65535.255.255
+bool MachOTargetInfo::PackedVersion::parse(StringRef str,
+ MachOTargetInfo::PackedVersion &result) {
+ result._value = 0;
+
+ if (str.empty())
+ return false;
+
+ SmallVector<StringRef, 3> parts;
+ llvm::SplitString(str, parts, ".");
+
+ unsigned long long num;
+ if (llvm::getAsUnsignedInteger(parts[0], 10, num))
+ return true;
+ if (num > 65535)
+ return true;
+ result._value = num << 16;
+
+ if (parts.size() > 1) {
+ if (llvm::getAsUnsignedInteger(parts[1], 10, num))
+ return true;
+ if (num > 255)
+ return true;
+ result._value |= (num << 8);
+ }
+
+ if (parts.size() > 2) {
+ if (llvm::getAsUnsignedInteger(parts[2], 10, num))
+ return true;
+ if (num > 255)
+ return true;
+ result._value |= num;
+ }
+
+ return false;
+}
+
+bool MachOTargetInfo::PackedVersion::operator<(
+ const PackedVersion &rhs) const {
+ return _value < rhs._value;
+}
+
+bool MachOTargetInfo::PackedVersion::operator>=(
+ const PackedVersion &rhs) const {
+ return _value >= rhs._value;
+}
+
+bool MachOTargetInfo::PackedVersion::operator==(
+ const PackedVersion &rhs) const {
+ return _value == rhs._value;
+}
+
+
+MachOTargetInfo::MachOTargetInfo()
+ : _outputFileType(mach_o::MH_EXECUTE)
+ , _outputFileTypeStatic(false)
+ , _arch(arch_unknown)
+ , _os(OS::macOSX)
+ , _osMinVersion("0.0")
+ , _pageZeroSize(0x1000)
+ , _kindHandler(nullptr) {
+}
+
+
+MachOTargetInfo::~MachOTargetInfo() {
+}
+
uint32_t MachOTargetInfo::getCPUType() const {
- switch (getTriple().getArch()) {
- case llvm::Triple::x86:
- return llvm::MachO::CPUTypeI386;
- case llvm::Triple::x86_64:
- return llvm::MachO::CPUTypeX86_64;
- case llvm::Triple::arm:
- return llvm::MachO::CPUTypeARM;
- default:
+ switch (_arch) {
+ case MachOTargetInfo::arch_x86:
+ return mach_o::CPU_TYPE_I386;
+ case MachOTargetInfo::arch_x86_64:
+ return mach_o::CPU_TYPE_X86_64;
+ case MachOTargetInfo::arch_armv6:
+ case MachOTargetInfo::arch_armv7:
+ case MachOTargetInfo::arch_armv7s:
+ return mach_o::CPU_TYPE_ARM;
+ case MachOTargetInfo::arch_unknown:
llvm_unreachable("Unknown arch type");
}
}
uint32_t MachOTargetInfo::getCPUSubType() const {
- switch (getTriple().getArch()) {
- case llvm::Triple::x86:
- return llvm::MachO::CPUSubType_I386_ALL;
- case llvm::Triple::x86_64:
- return llvm::MachO::CPUSubType_X86_64_ALL;
- case llvm::Triple::arm:
- return llvm::MachO::CPUSubType_ARM_ALL;
- default:
+ switch (_arch) {
+ case MachOTargetInfo::arch_x86:
+ return mach_o::CPU_SUBTYPE_X86_ALL;
+ case MachOTargetInfo::arch_x86_64:
+ return mach_o::CPU_SUBTYPE_X86_64_ALL;
+ case MachOTargetInfo::arch_armv6:
+ return mach_o::CPU_SUBTYPE_ARM_V6;
+ case MachOTargetInfo::arch_armv7:
+ return mach_o::CPU_SUBTYPE_ARM_V7;
+ case MachOTargetInfo::arch_armv7s:
+ return mach_o::CPU_SUBTYPE_ARM_V7S;
+ case MachOTargetInfo::arch_unknown:
llvm_unreachable("Unknown arch type");
}
}
-bool MachOTargetInfo::addEntryPointLoadCommand() const {
- switch (_options._outputKind) {
- case OutputKind::StaticExecutable:
- case OutputKind::DynamicExecutable:
+
+bool MachOTargetInfo::outputTypeHasEntry() const {
+ switch (_outputFileType) {
+ case mach_o::MH_EXECUTE:
+ case mach_o::MH_DYLINKER:
+ case mach_o::MH_PRELOAD:
return true;
default:
return false;
}
}
+
+bool MachOTargetInfo::minOS(StringRef mac, StringRef iOS) const {
+ switch (_os) {
+ case OS::macOSX:
+ return (_osMinVersion >= PackedVersion(mac));
+ case OS::iOS:
+ case OS::iOS_simulator:
+ return (_osMinVersion >= PackedVersion(iOS));
+ }
+ llvm_unreachable("target not configured for iOS or MacOSX");
+}
+
+bool MachOTargetInfo::addEntryPointLoadCommand() const {
+ if ((_outputFileType == mach_o::MH_EXECUTE) && !_outputFileTypeStatic) {
+ return minOS("10.8", "6.0");
+ }
+ return false;
+}
+
bool MachOTargetInfo::addUnixThreadLoadCommand() const {
- switch (_options._outputKind) {
- case OutputKind::StaticExecutable:
- case OutputKind::DynamicExecutable:
+ switch (_outputFileType) {
+ case mach_o::MH_EXECUTE:
+ if (_outputFileTypeStatic)
+ return true;
+ else
+ return !minOS("10.8", "6.0");
+ break;
+ case mach_o::MH_DYLINKER:
+ case mach_o::MH_PRELOAD:
return true;
default:
return false;
}
}
-class GenericMachOTargetInfo LLVM_FINAL : public MachOTargetInfo {
-public:
- GenericMachOTargetInfo(const LinkerOptions &lo) : MachOTargetInfo(lo) {}
+bool MachOTargetInfo::validate(raw_ostream &diagnostics) {
+ if ((_outputFileType == mach_o::MH_EXECUTE) && _entrySymbolName.empty()) {
+ if (_outputFileTypeStatic) {
+ _entrySymbolName = "start";
+ }
+ else {
+ // If targeting newer OS, use _main
+ if (addEntryPointLoadCommand())
+ _entrySymbolName = "_main";
- virtual uint64_t getPageSize() const { return 0x1000; }
- virtual uint64_t getPageZeroSize() const { return getPageSize(); }
-
- virtual StringRef getEntry() const {
- if (!_options._entrySymbol.empty())
- return _options._entrySymbol;
- return "_main";
+ // If targeting older OS, use start (in crt1.o)
+ if (addUnixThreadLoadCommand())
+ _entrySymbolName = "start";
+ }
}
- virtual void addPasses(PassManager &pm) const {
- pm.add(std::unique_ptr<Pass>(new mach_o::GOTPass));
- pm.add(std::unique_ptr<Pass>(new mach_o::StubsPass(*this)));
- pm.add(std::unique_ptr<Pass>(new LayoutPass()));
+ return false;
+}
+
+bool MachOTargetInfo::setOS(OS os, StringRef minOSVersion) {
+ _os = os;
+ return PackedVersion::parse(minOSVersion, _osMinVersion);
+}
+
+void MachOTargetInfo::addPasses(PassManager &pm) const {
+ pm.add(std::unique_ptr<Pass>(new mach_o::GOTPass));
+ pm.add(std::unique_ptr<Pass>(new mach_o::StubsPass(*this)));
+ pm.add(std::unique_ptr<Pass>(new LayoutPass()));
+}
+
+
+
+error_code MachOTargetInfo::parseFile(std::unique_ptr<MemoryBuffer> &mb,
+ std::vector<std::unique_ptr<File>> &result) const {
+// if (!_machoReader)
+// _machoReader = createReaderMachO(*this);
+// error_code ec = _machoReader->parseFile(mb,result);
+// if (ec) {
+ if (!_yamlReader)
+ _yamlReader = createReaderYAML(*this);
+ return _yamlReader->parseFile(mb,result);
+// }
+
+ return error_code::success();
+}
+
+
+Writer &MachOTargetInfo::writer() const {
+ if (!_writer) {
+ _writer = createWriterMachO(*this);
}
-};
+ return *_writer;
+}
+
+KindHandler &MachOTargetInfo::kindHandler() const {
+ if (!_kindHandler)
+ _kindHandler = KindHandler::create(_arch);
+ return *_kindHandler;
+}
-std::unique_ptr<MachOTargetInfo>
-MachOTargetInfo::create(const LinkerOptions &lo) {
- return std::unique_ptr<MachOTargetInfo>(new GenericMachOTargetInfo(lo));
+ErrorOr<Reference::Kind>
+MachOTargetInfo::relocKindFromString(StringRef str) const {
+ return kindHandler().stringToKind(str);
+ }
+
+ErrorOr<std::string>
+MachOTargetInfo::stringFromRelocKind(Reference::Kind kind) const {
+ return std::string(kindHandler().kindToString(kind));
}
+
+
} // end namespace lld
OpenPOWER on IntegriCloud