forked from OSchip/llvm-project
[lld][MachO] Add support for LC_VERSION_MIN_* load commands
This diff adds initial support for the legacy LC_VERSION_MIN_* load commands. Test plan: make check-lld-macho Differential revision: https://reviews.llvm.org/D100523
This commit is contained in:
parent
8c16c8b7ef
commit
5c835e1ae5
|
@ -33,6 +33,7 @@ using SectionRenameMap = llvm::DenseMap<NamePair, NamePair>;
|
|||
using SegmentRenameMap = llvm::DenseMap<llvm::StringRef, llvm::StringRef>;
|
||||
|
||||
struct PlatformInfo {
|
||||
llvm::MachO::Target target;
|
||||
llvm::VersionTuple minimum;
|
||||
llvm::VersionTuple sdk;
|
||||
};
|
||||
|
@ -101,7 +102,6 @@ struct Configuration {
|
|||
llvm::StringRef ltoObjPath;
|
||||
llvm::StringRef thinLTOJobs;
|
||||
bool demangle = false;
|
||||
llvm::MachO::Target target;
|
||||
PlatformInfo platformInfo;
|
||||
NamespaceKind namespaceKind = NamespaceKind::twolevel;
|
||||
UndefinedSymbolTreatment undefinedSymbolTreatment =
|
||||
|
|
|
@ -616,9 +616,10 @@ static TargetInfo *createTargetInfo(InputArgList &args) {
|
|||
fatal("must specify -arch");
|
||||
PlatformKind platform = parsePlatformVersion(args);
|
||||
|
||||
config->target = MachO::Target(getArchitectureFromName(archName), platform);
|
||||
config->platformInfo.target =
|
||||
MachO::Target(getArchitectureFromName(archName), platform);
|
||||
|
||||
switch (getCPUTypeFromArchitecture(config->target.Arch).first) {
|
||||
switch (getCPUTypeFromArchitecture(config->platformInfo.target.Arch).first) {
|
||||
case CPU_TYPE_X86_64:
|
||||
return createX86_64TargetInfo();
|
||||
case CPU_TYPE_ARM64:
|
||||
|
@ -699,17 +700,18 @@ static const char *getReproduceOption(InputArgList &args) {
|
|||
static bool isPie(InputArgList &args) {
|
||||
if (config->outputType != MH_EXECUTE || args.hasArg(OPT_no_pie))
|
||||
return false;
|
||||
if (config->target.Arch == AK_arm64 || config->target.Arch == AK_arm64e ||
|
||||
config->target.Arch == AK_arm64_32)
|
||||
if (config->platformInfo.target.Arch == AK_arm64 ||
|
||||
config->platformInfo.target.Arch == AK_arm64e ||
|
||||
config->platformInfo.target.Arch == AK_arm64_32)
|
||||
return true;
|
||||
|
||||
// TODO: add logic here as we support more archs. E.g. i386 should default
|
||||
// to PIE from 10.7
|
||||
assert(config->target.Arch == AK_x86_64 ||
|
||||
config->target.Arch == AK_x86_64h ||
|
||||
config->target.Arch == AK_arm64_32);
|
||||
assert(config->platformInfo.target.Arch == AK_x86_64 ||
|
||||
config->platformInfo.target.Arch == AK_x86_64h ||
|
||||
config->platformInfo.target.Arch == AK_arm64_32);
|
||||
|
||||
PlatformKind kind = config->target.Platform;
|
||||
PlatformKind kind = config->platformInfo.target.Platform;
|
||||
if (kind == PlatformKind::macOS &&
|
||||
config->platformInfo.minimum >= VersionTuple(10, 6))
|
||||
return true;
|
||||
|
@ -1029,7 +1031,7 @@ bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
|
|||
StringRef segName = arg->getValue(0);
|
||||
uint32_t maxProt = parseProtection(arg->getValue(1));
|
||||
uint32_t initProt = parseProtection(arg->getValue(2));
|
||||
if (maxProt != initProt && config->target.Arch != AK_i386)
|
||||
if (maxProt != initProt && config->platformInfo.target.Arch != AK_i386)
|
||||
error("invalid argument '" + arg->getAsString(args) +
|
||||
"': max and init must be the same for non-i386 archs");
|
||||
if (segName == segment_names::linkEdit)
|
||||
|
@ -1051,8 +1053,9 @@ bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
|
|||
|
||||
config->adhocCodesign = args.hasFlag(
|
||||
OPT_adhoc_codesign, OPT_no_adhoc_codesign,
|
||||
(config->target.Arch == AK_arm64 || config->target.Arch == AK_arm64e) &&
|
||||
config->target.Platform == PlatformKind::macOS);
|
||||
(config->platformInfo.target.Arch == AK_arm64 ||
|
||||
config->platformInfo.target.Arch == AK_arm64e) &&
|
||||
config->platformInfo.target.Platform == PlatformKind::macOS);
|
||||
|
||||
if (args.hasArg(OPT_v)) {
|
||||
message(getLLDVersion());
|
||||
|
|
|
@ -95,6 +95,71 @@ SetVector<InputFile *> macho::inputFiles;
|
|||
std::unique_ptr<TarWriter> macho::tar;
|
||||
int InputFile::idCount = 0;
|
||||
|
||||
static VersionTuple decodeVersion(uint32_t version) {
|
||||
unsigned major = version >> 16;
|
||||
unsigned minor = (version >> 8) & 0xffu;
|
||||
unsigned subMinor = version & 0xffu;
|
||||
return VersionTuple(major, minor, subMinor);
|
||||
}
|
||||
|
||||
template <class LP>
|
||||
static Optional<PlatformInfo> getPlatformInfo(const InputFile *input) {
|
||||
if (!isa<ObjFile>(input) && !isa<DylibFile>(input))
|
||||
return None;
|
||||
|
||||
using Header = typename LP::mach_header;
|
||||
auto *hdr = reinterpret_cast<const Header *>(input->mb.getBufferStart());
|
||||
PlatformInfo platformInfo;
|
||||
if (const auto *cmd =
|
||||
findCommand<build_version_command>(hdr, LC_BUILD_VERSION)) {
|
||||
platformInfo.target.Platform = static_cast<PlatformKind>(cmd->platform);
|
||||
platformInfo.minimum = decodeVersion(cmd->minos);
|
||||
return platformInfo;
|
||||
} else if (const auto *cmd =
|
||||
findCommand<version_min_command>(hdr, LC_VERSION_MIN_MACOSX)) {
|
||||
platformInfo.target.Platform = PlatformKind::macOS;
|
||||
platformInfo.minimum = decodeVersion(cmd->version);
|
||||
return platformInfo;
|
||||
} else if (const auto *cmd = findCommand<version_min_command>(
|
||||
hdr, LC_VERSION_MIN_IPHONEOS)) {
|
||||
platformInfo.target.Platform = PlatformKind::iOS;
|
||||
platformInfo.minimum = decodeVersion(cmd->version);
|
||||
return platformInfo;
|
||||
} else if (const auto *cmd =
|
||||
findCommand<version_min_command>(hdr, LC_VERSION_MIN_TVOS)) {
|
||||
platformInfo.target.Platform = PlatformKind::tvOS;
|
||||
platformInfo.minimum = decodeVersion(cmd->version);
|
||||
} else if (const auto *cmd = findCommand<version_min_command>(
|
||||
hdr, LC_VERSION_MIN_WATCHOS)) {
|
||||
platformInfo.target.Platform = PlatformKind::watchOS;
|
||||
platformInfo.minimum = decodeVersion(cmd->version);
|
||||
return platformInfo;
|
||||
}
|
||||
|
||||
return None;
|
||||
}
|
||||
|
||||
template <class LP> static bool checkCompatibility(const InputFile *input) {
|
||||
Optional<PlatformInfo> platformInfo = getPlatformInfo<LP>(input);
|
||||
if (!platformInfo)
|
||||
return true;
|
||||
// TODO: Correctly detect simulator platforms or relax this check.
|
||||
if (config->platformInfo.target.Platform != platformInfo->target.Platform) {
|
||||
error(toString(input) + " has platform " +
|
||||
getPlatformName(platformInfo->target.Platform) +
|
||||
Twine(", which is different from target platform ") +
|
||||
getPlatformName(config->platformInfo.target.Platform));
|
||||
return false;
|
||||
}
|
||||
if (platformInfo->minimum >= config->platformInfo.minimum)
|
||||
return true;
|
||||
error(toString(input) + " has version " +
|
||||
platformInfo->minimum.getAsString() +
|
||||
", which is incompatible with target version of " +
|
||||
config->platformInfo.minimum.getAsString());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Open a given file path and return it as a memory-mapped file.
|
||||
Optional<MemoryBufferRef> macho::readFile(StringRef path) {
|
||||
// Open a file.
|
||||
|
@ -365,32 +430,6 @@ static macho::Symbol *createDefined(const NList &sym, StringRef name,
|
|||
/*isExternal=*/false, /*isPrivateExtern=*/false);
|
||||
}
|
||||
|
||||
// Checks if the version specified in `cmd` is compatible with target
|
||||
// version. IOW, check if cmd's version >= config's version.
|
||||
static bool hasCompatVersion(const InputFile *input,
|
||||
const build_version_command *cmd) {
|
||||
|
||||
if (config->target.Platform != static_cast<PlatformKind>(cmd->platform)) {
|
||||
error(toString(input) + " has platform " +
|
||||
getPlatformName(static_cast<PlatformKind>(cmd->platform)) +
|
||||
Twine(", which is different from target platform ") +
|
||||
getPlatformName(config->target.Platform));
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned major = cmd->minos >> 16;
|
||||
unsigned minor = (cmd->minos >> 8) & 0xffu;
|
||||
unsigned subMinor = cmd->minos & 0xffu;
|
||||
VersionTuple version(major, minor, subMinor);
|
||||
if (version >= config->platformInfo.minimum)
|
||||
return true;
|
||||
|
||||
error(toString(input) + " has version " + version.getAsString() +
|
||||
", which is incompatible with target version of " +
|
||||
config->platformInfo.minimum.getAsString());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Absolute symbols are defined symbols that do not have an associated
|
||||
// InputSection. They cannot be weak.
|
||||
template <class NList>
|
||||
|
@ -542,18 +581,15 @@ template <class LP> void ObjFile::parse() {
|
|||
auto *hdr = reinterpret_cast<const Header *>(mb.getBufferStart());
|
||||
|
||||
Architecture arch = getArchitectureFromCpuType(hdr->cputype, hdr->cpusubtype);
|
||||
if (arch != config->target.Arch) {
|
||||
if (arch != config->platformInfo.target.Arch) {
|
||||
error(toString(this) + " has architecture " + getArchitectureName(arch) +
|
||||
" which is incompatible with target architecture " +
|
||||
getArchitectureName(config->target.Arch));
|
||||
getArchitectureName(config->platformInfo.target.Arch));
|
||||
return;
|
||||
}
|
||||
|
||||
if (const auto *cmd =
|
||||
findCommand<build_version_command>(hdr, LC_BUILD_VERSION)) {
|
||||
if (!hasCompatVersion(this, cmd))
|
||||
if (!checkCompatibility<LP>(this))
|
||||
return;
|
||||
}
|
||||
|
||||
if (const load_command *cmd = findCommand(hdr, LC_LINKER_OPTION)) {
|
||||
auto *c = reinterpret_cast<const linker_option_command *>(cmd);
|
||||
|
@ -719,11 +755,8 @@ template <class LP> void DylibFile::parse(DylibFile *umbrella) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (const build_version_command *cmd =
|
||||
findCommand<build_version_command>(hdr, LC_BUILD_VERSION)) {
|
||||
if (!hasCompatVersion(this, cmd))
|
||||
if (!checkCompatibility<LP>(this))
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize symbols.
|
||||
DylibFile *exportingFile = isImplicitlyLinked(dylibName) ? this : umbrella;
|
||||
|
@ -791,9 +824,9 @@ DylibFile::DylibFile(const InterfaceFile &interface, DylibFile *umbrella,
|
|||
"/usr/lib/system/libsystem_pthread.dylib"};
|
||||
|
||||
if (!is_contained(skipPlatformChecks, dylibName) &&
|
||||
!is_contained(interface.targets(), config->target)) {
|
||||
!is_contained(interface.targets(), config->platformInfo.target)) {
|
||||
error(toString(this) + " is incompatible with " +
|
||||
std::string(config->target));
|
||||
std::string(config->platformInfo.target));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -806,7 +839,7 @@ DylibFile::DylibFile(const InterfaceFile &interface, DylibFile *umbrella,
|
|||
// TODO(compnerd) filter out symbols based on the target platform
|
||||
// TODO: handle weak defs, thread locals
|
||||
for (const auto *symbol : interface.symbols()) {
|
||||
if (!symbol->getArchitectures().has(config->target.Arch))
|
||||
if (!symbol->getArchitectures().has(config->platformInfo.target.Arch))
|
||||
continue;
|
||||
|
||||
switch (symbol->getKind()) {
|
||||
|
@ -834,7 +867,7 @@ DylibFile::DylibFile(const InterfaceFile &interface, DylibFile *umbrella,
|
|||
for (InterfaceFileRef intfRef : interface.reexportedLibraries()) {
|
||||
InterfaceFile::const_target_range targets = intfRef.targets();
|
||||
if (is_contained(skipPlatformChecks, intfRef.getInstallName()) ||
|
||||
is_contained(targets, config->target))
|
||||
is_contained(targets, config->platformInfo.target))
|
||||
loadReexport(intfRef.getInstallName(), exportingFile, topLevel);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ class TarWriter;
|
|||
namespace lld {
|
||||
namespace macho {
|
||||
|
||||
struct PlatformInfo;
|
||||
class InputSection;
|
||||
class Symbol;
|
||||
struct Reloc;
|
||||
|
|
|
@ -117,8 +117,9 @@ std::vector<ObjFile *> BitcodeCompiler::compile() {
|
|||
uint32_t modTime = 0;
|
||||
if (!config->ltoObjPath.empty()) {
|
||||
filePath = config->ltoObjPath;
|
||||
path::append(filePath, Twine(i) + "." +
|
||||
getArchitectureName(config->target.Arch) +
|
||||
path::append(filePath,
|
||||
Twine(i) + "." +
|
||||
getArchitectureName(config->platformInfo.target.Arch) +
|
||||
".lto.o");
|
||||
saveBuffer(buf[i], filePath);
|
||||
modTime = getModTime(filePath);
|
||||
|
|
|
@ -108,8 +108,9 @@ void macho::writeMapFile() {
|
|||
os << format("# Path: %s\n", config->outputFile.str().c_str());
|
||||
|
||||
// Dump output architecture.
|
||||
os << format("# Arch: %s\n",
|
||||
getArchitectureName(config->target.Arch).str().c_str());
|
||||
os << format(
|
||||
"# Arch: %s\n",
|
||||
getArchitectureName(config->platformInfo.target.Arch).str().c_str());
|
||||
|
||||
// Dump table of object files.
|
||||
os << "# Object files:\n";
|
||||
|
|
|
@ -37,7 +37,7 @@ static uint32_t initProt(StringRef name) {
|
|||
}
|
||||
|
||||
static uint32_t maxProt(StringRef name) {
|
||||
assert(config->target.Arch != AK_i386 &&
|
||||
assert(config->platformInfo.target.Arch != AK_i386 &&
|
||||
"TODO: i386 has different maxProt requirements");
|
||||
return initProt(name);
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ static uint32_t cpuSubtype() {
|
|||
|
||||
if (config->outputType == MH_EXECUTE && !config->staticLink &&
|
||||
target->cpuSubtype == CPU_SUBTYPE_X86_64_ALL &&
|
||||
config->target.Platform == PlatformKind::macOS &&
|
||||
config->platformInfo.target.Platform == PlatformKind::macOS &&
|
||||
config->platformInfo.minimum >= VersionTuple(10, 5))
|
||||
subtype |= CPU_SUBTYPE_LIB64;
|
||||
|
||||
|
|
|
@ -359,10 +359,54 @@ private:
|
|||
StringRef path;
|
||||
};
|
||||
|
||||
static uint32_t encodeVersion(const VersionTuple &version) {
|
||||
return ((version.getMajor() << 020) |
|
||||
(version.getMinor().getValueOr(0) << 010) |
|
||||
version.getSubminor().getValueOr(0));
|
||||
}
|
||||
|
||||
class LCMinVersion : public LoadCommand {
|
||||
public:
|
||||
explicit LCMinVersion(const PlatformInfo &platformInfo)
|
||||
: platformInfo(platformInfo) {}
|
||||
|
||||
uint32_t getSize() const override { return sizeof(version_min_command); }
|
||||
|
||||
void writeTo(uint8_t *buf) const override {
|
||||
auto *c = reinterpret_cast<version_min_command *>(buf);
|
||||
switch (platformInfo.target.Platform) {
|
||||
case PlatformKind::macOS:
|
||||
c->cmd = LC_VERSION_MIN_MACOSX;
|
||||
break;
|
||||
case PlatformKind::iOS:
|
||||
case PlatformKind::iOSSimulator:
|
||||
c->cmd = LC_VERSION_MIN_IPHONEOS;
|
||||
break;
|
||||
case PlatformKind::tvOS:
|
||||
case PlatformKind::tvOSSimulator:
|
||||
c->cmd = LC_VERSION_MIN_TVOS;
|
||||
break;
|
||||
case PlatformKind::watchOS:
|
||||
case PlatformKind::watchOSSimulator:
|
||||
c->cmd = LC_VERSION_MIN_WATCHOS;
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("invalid platform");
|
||||
break;
|
||||
}
|
||||
c->cmdsize = getSize();
|
||||
c->version = encodeVersion(platformInfo.minimum);
|
||||
c->sdk = encodeVersion(platformInfo.sdk);
|
||||
}
|
||||
|
||||
private:
|
||||
const PlatformInfo &platformInfo;
|
||||
};
|
||||
|
||||
class LCBuildVersion : public LoadCommand {
|
||||
public:
|
||||
LCBuildVersion(PlatformKind platform, const PlatformInfo &platformInfo)
|
||||
: platform(platform), platformInfo(platformInfo) {}
|
||||
explicit LCBuildVersion(const PlatformInfo &platformInfo)
|
||||
: platformInfo(platformInfo) {}
|
||||
|
||||
const int ntools = 1;
|
||||
|
||||
|
@ -374,21 +418,17 @@ public:
|
|||
auto *c = reinterpret_cast<build_version_command *>(buf);
|
||||
c->cmd = LC_BUILD_VERSION;
|
||||
c->cmdsize = getSize();
|
||||
c->platform = static_cast<uint32_t>(platform);
|
||||
c->minos = ((platformInfo.minimum.getMajor() << 020) |
|
||||
(platformInfo.minimum.getMinor().getValueOr(0) << 010) |
|
||||
platformInfo.minimum.getSubminor().getValueOr(0));
|
||||
c->sdk = ((platformInfo.sdk.getMajor() << 020) |
|
||||
(platformInfo.sdk.getMinor().getValueOr(0) << 010) |
|
||||
platformInfo.sdk.getSubminor().getValueOr(0));
|
||||
c->platform = static_cast<uint32_t>(platformInfo.target.Platform);
|
||||
c->minos = encodeVersion(platformInfo.minimum);
|
||||
c->sdk = encodeVersion(platformInfo.sdk);
|
||||
c->ntools = ntools;
|
||||
auto *t = reinterpret_cast<build_tool_version *>(&c[1]);
|
||||
t->tool = TOOL_LD;
|
||||
t->version = (LLVM_VERSION_MAJOR << 020) | (LLVM_VERSION_MINOR << 010) |
|
||||
LLVM_VERSION_PATCH;
|
||||
t->version = encodeVersion(llvm::VersionTuple(
|
||||
LLVM_VERSION_MAJOR, LLVM_VERSION_MINOR, LLVM_VERSION_PATCH));
|
||||
}
|
||||
|
||||
PlatformKind platform;
|
||||
private:
|
||||
const PlatformInfo &platformInfo;
|
||||
};
|
||||
|
||||
|
@ -553,6 +593,20 @@ void Writer::scanSymbols() {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: ld64 enforces the old load commands in a few other cases.
|
||||
static bool useLCBuildVersion(const PlatformInfo &platformInfo) {
|
||||
static const std::map<PlatformKind, llvm::VersionTuple> minVersion = {
|
||||
{PlatformKind::macOS, llvm::VersionTuple(10, 14)},
|
||||
{PlatformKind::iOS, llvm::VersionTuple(12, 0)},
|
||||
{PlatformKind::iOSSimulator, llvm::VersionTuple(13, 0)},
|
||||
{PlatformKind::tvOS, llvm::VersionTuple(12, 0)},
|
||||
{PlatformKind::tvOSSimulator, llvm::VersionTuple(13, 0)},
|
||||
{PlatformKind::watchOS, llvm::VersionTuple(5, 0)},
|
||||
{PlatformKind::watchOSSimulator, llvm::VersionTuple(6, 0)}};
|
||||
auto it = minVersion.find(platformInfo.target.Platform);
|
||||
return it == minVersion.end() ? true : platformInfo.minimum >= it->second;
|
||||
}
|
||||
|
||||
template <class LP> void Writer::createLoadCommands() {
|
||||
uint8_t segIndex = 0;
|
||||
for (OutputSegment *seg : outputSegments) {
|
||||
|
@ -589,8 +643,10 @@ template <class LP> void Writer::createLoadCommands() {
|
|||
uuidCommand = make<LCUuid>();
|
||||
in.header->addLoadCommand(uuidCommand);
|
||||
|
||||
in.header->addLoadCommand(
|
||||
make<LCBuildVersion>(config->target.Platform, config->platformInfo));
|
||||
if (useLCBuildVersion(config->platformInfo))
|
||||
in.header->addLoadCommand(make<LCBuildVersion>(config->platformInfo));
|
||||
else
|
||||
in.header->addLoadCommand(make<LCMinVersion>(config->platformInfo));
|
||||
|
||||
int64_t dylibOrdinal = 1;
|
||||
for (InputFile *file : inputFiles) {
|
||||
|
|
|
@ -1,16 +1,68 @@
|
|||
# REQUIRES: x86
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o
|
||||
# RUN: %lld -platform_version macos 10.14.1 10.15 -o %t %t.o
|
||||
# RUN: llvm-objdump --macho --all-headers %t | FileCheck %s
|
||||
|
||||
# CHECK: cmd LC_BUILD_VERSION
|
||||
# CHECK-NEXT: cmdsize 32
|
||||
# CHECK-NEXT: platform macos
|
||||
# CHECK-NEXT: sdk 10.15
|
||||
# CHECK-NEXT: minos 10.14.1
|
||||
# CHECK-NEXT: ntools 1
|
||||
# CHECK-NEXT: tool ld
|
||||
# CHECK-NEXT: version {{[0-9\.]+}}
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o
|
||||
|
||||
# RUN: %lld -platform_version macos 10.14 10.15 -o %t.macos_10_14 %t.o
|
||||
# RUN: llvm-objdump --macho --all-headers %t.macos_10_14 | FileCheck %s --check-prefix=MACOS_10_14
|
||||
|
||||
# MACOS_10_14: cmd LC_BUILD_VERSION
|
||||
# MACOS_10_14-NEXT: cmdsize 32
|
||||
# MACOS_10_14-NEXT: platform macos
|
||||
# MACOS_10_14-NEXT: sdk 10.15
|
||||
# MACOS_10_14-NEXT: minos 10.14
|
||||
# MACOS_10_14-NEXT: ntools 1
|
||||
# MACOS_10_14-NEXT: tool ld
|
||||
# MACOS_10_14-NEXT: version {{[0-9\.]+}}
|
||||
|
||||
# RUN: %lld -platform_version macos 10.13 10.15 -o %t.macos_10_13 %t.o
|
||||
# RUN: llvm-objdump --macho --all-headers %t.macos_10_13 | FileCheck %s --check-prefix=MACOS_10_13
|
||||
|
||||
# MACOS_10_13: cmd LC_VERSION_MIN_MACOSX
|
||||
# MACOS_10_13-NEXT: cmdsize 16
|
||||
# MACOS_10_13-NEXT: version 10.13
|
||||
# MACOS_10_13-NEXT: sdk 10.15
|
||||
|
||||
# RUN: %lld -platform_version ios 12.0 10.15 -o %t.ios_12_0 %t.o
|
||||
# RUN: llvm-objdump --macho --all-headers %t.ios_12_0 | FileCheck %s --check-prefix=IOS_12_0
|
||||
# RUN: %lld -platform_version ios-simulator 13.0 10.15 -o %t.ios_sim_13_0 %t.o
|
||||
# RUN: llvm-objdump --macho --all-headers %t.ios_sim_13_0 | FileCheck %s --check-prefix=IOS_12_0
|
||||
|
||||
# IOS_12_0: cmd LC_BUILD_VERSION
|
||||
|
||||
# RUN: %lld -platform_version ios 11.0 10.15 -o %t.ios_11_0 %t.o
|
||||
# RUN: llvm-objdump --macho --all-headers %t.ios_11_0 | FileCheck %s --check-prefix=IOS_11_0
|
||||
# RUN: %lld -platform_version ios-simulator 12.0 10.15 -o %t.ios_sim_12_0 %t.o
|
||||
# RUN: llvm-objdump --macho --all-headers %t.ios_sim_12_0 | FileCheck %s --check-prefix=IOS_11_0
|
||||
|
||||
# IOS_11_0: cmd LC_VERSION_MIN_IPHONEOS
|
||||
|
||||
# RUN: %lld -platform_version tvos 12.0 10.15 -o %t.tvos_12_0 %t.o
|
||||
# RUN: llvm-objdump --macho --all-headers %t.tvos_12_0 | FileCheck %s --check-prefix=TVOS_12_0
|
||||
# RUN: %lld -platform_version tvos-simulator 13.0 10.15 -o %t.tvos_sim_13_0 %t.o
|
||||
# RUN: llvm-objdump --macho --all-headers %t.tvos_sim_13_0 | FileCheck %s --check-prefix=TVOS_12_0
|
||||
|
||||
# TVOS_12_0: cmd LC_BUILD_VERSION
|
||||
|
||||
# RUN: %lld -platform_version tvos 11.0 10.15 -o %t.tvos_11_0 %t.o
|
||||
# RUN: llvm-objdump --macho --all-headers %t.tvos_11_0 | FileCheck %s --check-prefix=TVOS_11_0
|
||||
# RUN: %lld -platform_version tvos-simulator 12.0 10.15 -o %t.tvos_sim_12_0 %t.o
|
||||
# RUN: llvm-objdump --macho --all-headers %t.tvos_sim_12_0 | FileCheck %s --check-prefix=TVOS_11_0
|
||||
|
||||
# TVOS_11_0: cmd LC_VERSION_MIN_TVOS
|
||||
|
||||
# RUN: %lld -platform_version watchos 5.0 10.15 -o %t.watchos_5_0 %t.o
|
||||
# RUN: llvm-objdump --macho --all-headers %t.watchos_5_0 | FileCheck %s --check-prefix=WATCHOS_5_0
|
||||
# RUN: %lld -platform_version watchos-simulator 6.0 10.15 -o %t.watchos_sim_6_0 %t.o
|
||||
# RUN: llvm-objdump --macho --all-headers %t.watchos_sim_6_0 | FileCheck %s --check-prefix=WATCHOS_5_0
|
||||
|
||||
# WATCHOS_5_0: cmd LC_BUILD_VERSION
|
||||
|
||||
# RUN: %lld -platform_version watchos 4.0 10.15 -o %t.watchos_4_0 %t.o
|
||||
# RUN: llvm-objdump --macho --all-headers %t.watchos_4_0 | FileCheck %s --check-prefix=WATCHOS_4_0
|
||||
# RUN: %lld -platform_version watchos-simulator 5.0 10.15 -o %t.watchos_sim_5_0 %t.o
|
||||
# RUN: llvm-objdump --macho --all-headers %t.watchos_sim_5_0 | FileCheck %s --check-prefix=WATCHOS_4_0
|
||||
|
||||
# WATCHOS_4_0: cmd LC_VERSION_MIN_WATCHOS
|
||||
|
||||
.text
|
||||
.global _main
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
# DYLIB: cmd LC_ID_DYLIB
|
||||
|
||||
# COMMON: cmd LC_UUID
|
||||
# COMMON: cmd LC_BUILD_VERSION
|
||||
# COMMON: cmd LC_VERSION_MIN_MACOSX
|
||||
# COMMON: cmd LC_LOAD_DYLIB
|
||||
|
||||
.section __TEXT,__cstring
|
||||
|
|
|
@ -12,12 +12,12 @@
|
|||
## address offset and the contents at that address very similarly, so am using
|
||||
## --match-full-lines to make sure we match on the right thing.
|
||||
# CHECK: Contents of section __TEXT,__cstring:
|
||||
# CHECK-NEXT: 100000434 {{.*}}
|
||||
# CHECK-NEXT: 100000424 {{.*}}
|
||||
|
||||
## 1st 8 bytes refer to the start of __cstring + 0xe, 2nd 8 bytes refer to the
|
||||
## start of __cstring
|
||||
# CHECK: Contents of section __DATA_CONST,__got:
|
||||
# CHECK-NEXT: [[#%X,ADDR:]] 42040000 01000000 34040000 01000000 {{.*}}
|
||||
# CHECK-NEXT: [[#%X,ADDR:]] 32040000 01000000 24040000 01000000 {{.*}}
|
||||
# CHECK-NEXT: [[#ADDR + 16]] 00000000 00000000 {{.*}}
|
||||
|
||||
## Check that the rebase table is empty.
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
# RUN: llvm-objdump --section=__const --full-contents %t | FileCheck %s --check-prefix=NONPCREL
|
||||
# NONPCREL: Contents of section __DATA,__const:
|
||||
# NONPCREL-NEXT: 100001000 18040000 01000000 18040000 01000000
|
||||
# NONPCREL-NEXT: 100001000 08040000 01000000 08040000 01000000
|
||||
|
||||
.section __TEXT,__text
|
||||
.globl _main, _f
|
||||
|
|
Loading…
Reference in New Issue