From 5c835e1ae5e177591ddb64be3f6a473ef6bfa4bb Mon Sep 17 00:00:00 2001 From: Alexander Shaposhnikov Date: Wed, 21 Apr 2021 05:41:14 -0700 Subject: [PATCH] [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 --- lld/MachO/Config.h | 2 +- lld/MachO/Driver.cpp | 25 +++--- lld/MachO/InputFiles.cpp | 117 ++++++++++++++++--------- lld/MachO/InputFiles.h | 1 + lld/MachO/LTO.cpp | 7 +- lld/MachO/MapFile.cpp | 5 +- lld/MachO/OutputSegment.cpp | 2 +- lld/MachO/SyntheticSections.cpp | 2 +- lld/MachO/Writer.cpp | 84 +++++++++++++++--- lld/test/MachO/lc-build-version.s | 74 +++++++++++++--- lld/test/MachO/load-command-sequence.s | 2 +- lld/test/MachO/local-got.s | 4 +- lld/test/MachO/x86-64-relocs.s | 2 +- 13 files changed, 237 insertions(+), 90 deletions(-) diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h index d36a290fa66c..def14abc5b51 100644 --- a/lld/MachO/Config.h +++ b/lld/MachO/Config.h @@ -33,6 +33,7 @@ using SectionRenameMap = llvm::DenseMap; using SegmentRenameMap = llvm::DenseMap; 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 = diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp index 6591f73ffac0..32d70495cf87 100644 --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -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 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 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()); diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp index 139b4cdded46..6edeb2ccc284 100644 --- a/lld/MachO/InputFiles.cpp +++ b/lld/MachO/InputFiles.cpp @@ -95,6 +95,71 @@ SetVector macho::inputFiles; std::unique_ptr 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 +static Optional getPlatformInfo(const InputFile *input) { + if (!isa(input) && !isa(input)) + return None; + + using Header = typename LP::mach_header; + auto *hdr = reinterpret_cast(input->mb.getBufferStart()); + PlatformInfo platformInfo; + if (const auto *cmd = + findCommand(hdr, LC_BUILD_VERSION)) { + platformInfo.target.Platform = static_cast(cmd->platform); + platformInfo.minimum = decodeVersion(cmd->minos); + return platformInfo; + } else if (const auto *cmd = + findCommand(hdr, LC_VERSION_MIN_MACOSX)) { + platformInfo.target.Platform = PlatformKind::macOS; + platformInfo.minimum = decodeVersion(cmd->version); + return platformInfo; + } else if (const auto *cmd = findCommand( + hdr, LC_VERSION_MIN_IPHONEOS)) { + platformInfo.target.Platform = PlatformKind::iOS; + platformInfo.minimum = decodeVersion(cmd->version); + return platformInfo; + } else if (const auto *cmd = + findCommand(hdr, LC_VERSION_MIN_TVOS)) { + platformInfo.target.Platform = PlatformKind::tvOS; + platformInfo.minimum = decodeVersion(cmd->version); + } else if (const auto *cmd = findCommand( + hdr, LC_VERSION_MIN_WATCHOS)) { + platformInfo.target.Platform = PlatformKind::watchOS; + platformInfo.minimum = decodeVersion(cmd->version); + return platformInfo; + } + + return None; +} + +template static bool checkCompatibility(const InputFile *input) { + Optional platformInfo = getPlatformInfo(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 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(cmd->platform)) { - error(toString(input) + " has platform " + - getPlatformName(static_cast(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 @@ -542,18 +581,15 @@ template void ObjFile::parse() { auto *hdr = reinterpret_cast(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(hdr, LC_BUILD_VERSION)) { - if (!hasCompatVersion(this, cmd)) - return; - } + if (!checkCompatibility(this)) + return; if (const load_command *cmd = findCommand(hdr, LC_LINKER_OPTION)) { auto *c = reinterpret_cast(cmd); @@ -719,11 +755,8 @@ template void DylibFile::parse(DylibFile *umbrella) { return; } - if (const build_version_command *cmd = - findCommand(hdr, LC_BUILD_VERSION)) { - if (!hasCompatVersion(this, cmd)) - return; - } + if (!checkCompatibility(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); } } diff --git a/lld/MachO/InputFiles.h b/lld/MachO/InputFiles.h index e3f04944df85..6ead6900e19c 100644 --- a/lld/MachO/InputFiles.h +++ b/lld/MachO/InputFiles.h @@ -37,6 +37,7 @@ class TarWriter; namespace lld { namespace macho { +struct PlatformInfo; class InputSection; class Symbol; struct Reloc; diff --git a/lld/MachO/LTO.cpp b/lld/MachO/LTO.cpp index f04b950553f8..a3d4b44749cb 100644 --- a/lld/MachO/LTO.cpp +++ b/lld/MachO/LTO.cpp @@ -117,9 +117,10 @@ std::vector BitcodeCompiler::compile() { uint32_t modTime = 0; if (!config->ltoObjPath.empty()) { filePath = config->ltoObjPath; - path::append(filePath, Twine(i) + "." + - getArchitectureName(config->target.Arch) + - ".lto.o"); + path::append(filePath, + Twine(i) + "." + + getArchitectureName(config->platformInfo.target.Arch) + + ".lto.o"); saveBuffer(buf[i], filePath); modTime = getModTime(filePath); } diff --git a/lld/MachO/MapFile.cpp b/lld/MachO/MapFile.cpp index acc89e405a54..42726809ff64 100644 --- a/lld/MachO/MapFile.cpp +++ b/lld/MachO/MapFile.cpp @@ -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"; diff --git a/lld/MachO/OutputSegment.cpp b/lld/MachO/OutputSegment.cpp index 71da2ef8eb48..039001b8e13d 100644 --- a/lld/MachO/OutputSegment.cpp +++ b/lld/MachO/OutputSegment.cpp @@ -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); } diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp index 72854bc0d68b..afa6777f8ecc 100644 --- a/lld/MachO/SyntheticSections.cpp +++ b/lld/MachO/SyntheticSections.cpp @@ -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; diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp index b2ce72e84fc3..7cd3de863913 100644 --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -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(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(buf); c->cmd = LC_BUILD_VERSION; c->cmdsize = getSize(); - c->platform = static_cast(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(platformInfo.target.Platform); + c->minos = encodeVersion(platformInfo.minimum); + c->sdk = encodeVersion(platformInfo.sdk); c->ntools = ntools; auto *t = reinterpret_cast(&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 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 void Writer::createLoadCommands() { uint8_t segIndex = 0; for (OutputSegment *seg : outputSegments) { @@ -589,8 +643,10 @@ template void Writer::createLoadCommands() { uuidCommand = make(); in.header->addLoadCommand(uuidCommand); - in.header->addLoadCommand( - make(config->target.Platform, config->platformInfo)); + if (useLCBuildVersion(config->platformInfo)) + in.header->addLoadCommand(make(config->platformInfo)); + else + in.header->addLoadCommand(make(config->platformInfo)); int64_t dylibOrdinal = 1; for (InputFile *file : inputFiles) { diff --git a/lld/test/MachO/lc-build-version.s b/lld/test/MachO/lc-build-version.s index eb4f422bef12..d7bd8be26f4b 100644 --- a/lld/test/MachO/lc-build-version.s +++ b/lld/test/MachO/lc-build-version.s @@ -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 diff --git a/lld/test/MachO/load-command-sequence.s b/lld/test/MachO/load-command-sequence.s index 734b7d1c6595..81051bf1431c 100644 --- a/lld/test/MachO/load-command-sequence.s +++ b/lld/test/MachO/load-command-sequence.s @@ -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 diff --git a/lld/test/MachO/local-got.s b/lld/test/MachO/local-got.s index 9e48c7ec600b..e4a1c5e9b979 100644 --- a/lld/test/MachO/local-got.s +++ b/lld/test/MachO/local-got.s @@ -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. diff --git a/lld/test/MachO/x86-64-relocs.s b/lld/test/MachO/x86-64-relocs.s index 8e9474454001..c5627c49583f 100644 --- a/lld/test/MachO/x86-64-relocs.s +++ b/lld/test/MachO/x86-64-relocs.s @@ -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