diff --git a/lld/MachO/InputFiles.h b/lld/MachO/InputFiles.h --- a/lld/MachO/InputFiles.h +++ b/lld/MachO/InputFiles.h @@ -203,6 +203,23 @@ return nullptr; } +template +const std::vector findCommands(const void *anyHdr, + Types... types) { + std::vector cmds; + std::initializer_list typesList{types...}; + const auto *hdr = reinterpret_cast(anyHdr); + const uint8_t *p = + reinterpret_cast(hdr) + target->headerSize; + for (uint32_t i = 0, n = hdr->ncmds; i < n; ++i) { + auto *cmd = reinterpret_cast(p); + if (llvm::is_contained(typesList, cmd->cmd)) + cmds.push_back(cmd); + p += cmd->cmdsize; + } + return cmds; +} + } // namespace macho std::string toString(const macho::InputFile *file); diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp --- a/lld/MachO/InputFiles.cpp +++ b/lld/MachO/InputFiles.cpp @@ -102,41 +102,42 @@ return VersionTuple(major, minor, subMinor); } -static Optional getPlatformInfo(const InputFile *input) { +static std::vector getPlatformInfos(const InputFile *input) { if (!isa(input) && !isa(input)) - return None; + return {}; const char *hdr = 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; + std::vector platformInfos; + for (auto *cmd : findCommands(hdr, LC_BUILD_VERSION)) { + PlatformInfo info; + info.target.Platform = static_cast(cmd->platform); + info.minimum = decodeVersion(cmd->minos); + platformInfos.emplace_back(std::move(info)); } - if (const auto *cmd = findCommand( - hdr, LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, - LC_VERSION_MIN_TVOS, LC_VERSION_MIN_WATCHOS)) { + for (auto *cmd : findCommands( + hdr, LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, + LC_VERSION_MIN_TVOS, LC_VERSION_MIN_WATCHOS)) { + PlatformInfo info; switch (cmd->cmd) { case LC_VERSION_MIN_MACOSX: - platformInfo.target.Platform = PlatformKind::macOS; + info.target.Platform = PlatformKind::macOS; break; case LC_VERSION_MIN_IPHONEOS: - platformInfo.target.Platform = PlatformKind::iOS; + info.target.Platform = PlatformKind::iOS; break; case LC_VERSION_MIN_TVOS: - platformInfo.target.Platform = PlatformKind::tvOS; + info.target.Platform = PlatformKind::tvOS; break; case LC_VERSION_MIN_WATCHOS: - platformInfo.target.Platform = PlatformKind::watchOS; + info.target.Platform = PlatformKind::watchOS; break; } - platformInfo.minimum = decodeVersion(cmd->version); - return platformInfo; + info.minimum = decodeVersion(cmd->version); + platformInfos.emplace_back(std::move(info)); } - return None; + return platformInfos; } static PlatformKind removeSimulator(PlatformKind platform) { @@ -153,22 +154,33 @@ } static bool checkCompatibility(const InputFile *input) { - Optional platformInfo = getPlatformInfo(input); - if (!platformInfo) + std::vector platformInfos = getPlatformInfos(input); + if (platformInfos.empty()) return true; - if (removeSimulator(config->platform()) != - removeSimulator(platformInfo->target.Platform)) { - error(toString(input) + " has platform " + - getPlatformName(platformInfo->target.Platform) + + auto it = find_if(platformInfos, [&](const PlatformInfo &info) { + return removeSimulator(info.target.Platform) == + removeSimulator(config->platform()); + }); + if (it == platformInfos.end()) { + std::string platformNames; + raw_string_ostream os(platformNames); + interleave( + platformInfos, os, + [&](const PlatformInfo &info) { + os << getPlatformName(info.target.Platform); + }, + "/"); + error(toString(input) + " has platform " + platformNames + Twine(", which is different from target platform ") + getPlatformName(config->platform())); return false; } - if (platformInfo->minimum <= config->platformInfo.minimum) + + if (it->minimum <= config->platformInfo.minimum) return true; - error(toString(input) + " has version " + - platformInfo->minimum.getAsString() + + + error(toString(input) + " has version " + it->minimum.getAsString() + ", which is newer than target minimum of " + config->platformInfo.minimum.getAsString()); return false; diff --git a/lld/test/MachO/Inputs/MacOSX.sdk/usr/lib/libSystem.tbd b/lld/test/MachO/Inputs/MacOSX.sdk/usr/lib/libSystem.tbd --- a/lld/test/MachO/Inputs/MacOSX.sdk/usr/lib/libSystem.tbd +++ b/lld/test/MachO/Inputs/MacOSX.sdk/usr/lib/libSystem.tbd @@ -1,64 +1,72 @@ --- !tapi-tbd tbd-version: 4 -targets: [ x86_64-macos, arm64-macos ] +targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos ] uuids: - target: x86_64-macos value: 00000000-0000-0000-0000-000000000000 + - target: x86_64-maccatalyst + value: 00000000-0000-0000-0000-000000000000 - target: arm64-macos value: 00000000-0000-0000-0000-000000000001 install-name: '/usr/lib/libSystem.dylib' current-version: 0001.001.1 reexported-libraries: - - targets: [ x86_64-macos, arm64-macos ] + - targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos ] libraries: [ '/usr/lib/system/libdyld.dylib', '/usr/lib/system/libsystem_c.dylib', '/usr/lib/system/libsystem_m.dylib' ] --- !tapi-tbd tbd-version: 4 -targets: [ x86_64-macos, arm64-macos ] +targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos ] uuids: - target: x86_64-macos value: 00000000-0000-0000-0000-000000000002 + - target: x86_64-maccatalyst + value: 00000000-0000-0000-0000-000000000000 - target: arm64-macos value: 00000000-0000-0000-0000-000000000003 install-name: '/usr/lib/system/libdyld.dylib' current-version: 0001.001.1 parent-umbrella: - - targets: [ x86_64-macos, arm64-macos ] + - targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos ] umbrella: System exports: - - targets: [ x86_64-macos, arm64-macos ] + - targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos ] symbols: [ dyld_stub_binder, __tlv_bootstrap ] --- !tapi-tbd tbd-version: 4 -targets: [ x86_64-macos, arm64-macos ] +targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos ] uuids: - target: x86_64-macos value: 00000000-0000-0000-0000-000000000003 + - target: x86_64-maccatalyst + value: 00000000-0000-0000-0000-000000000000 - target: arm64-macos value: 00000000-0000-0000-0000-000000000004 install-name: '/usr/lib/system/libsystem_c.dylib' current-version: 0001.001.1 parent-umbrella: - - targets: [ x86_64-macos, arm64-macos ] + - targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos ] umbrella: System exports: - - targets: [ x86_64-macos, arm64-macos ] + - targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos ] symbols: [ ] --- !tapi-tbd tbd-version: 4 -targets: [ x86_64-macos, arm64-macos ] +targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos ] uuids: - target: x86_64-macos value: 00000000-0000-0000-0000-000000000004 + - target: x86_64-maccatalyst + value: 00000000-0000-0000-0000-000000000000 - target: arm64-macos value: 00000000-0000-0000-0000-000000000005 install-name: '/usr/lib/system/libsystem_m.dylib' current-version: 0001.001.1 parent-umbrella: - - targets: [ x86_64-macos, arm64-macos ] + - targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos ] umbrella: System exports: - - targets: [ x86_64-macos, arm64-macos ] + - targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos ] symbols: [ ___nan ] ... diff --git a/lld/test/MachO/zippered.yaml b/lld/test/MachO/zippered.yaml new file mode 100644 --- /dev/null +++ b/lld/test/MachO/zippered.yaml @@ -0,0 +1,64 @@ +# REQUIRES: x86 +# RUN: rm -rf %t; mkdir %t +# RUN: yaml2obj %s > %t/test.dylib +# RUN: echo "" | llvm-mc -filetype=obj -triple=x86_64-apple-macos10.15 -o %t/test_macos.o +# RUN: echo "" | llvm-mc -filetype=obj -triple=x86_64-apple-ios13.15.0-macabi -o %t/test_maccatalyst.o +# RUN: echo "" | llvm-mc -filetype=obj -triple=x86_64-apple-ios13.15.0 -o %t/test_ios.o + +# RUN: %lld -lSystem -dylib %t/test.dylib %t/test_macos.o -o /dev/null +# RUN: %lld -lSystem -dylib -platform_version mac-catalyst 13.15.0 14.0 %t/test.dylib %t/test_maccatalyst.o -o /dev/null + +# RUN: not %lld -lSystem -dylib -platform_version ios 13.15.0 14.0 %t/test.dylib %t/test_ios.o -o /dev/null 2>&1 | FileCheck %s +# CHECK: test.dylib has platform macOS/macCatalyst, which is different from target platform iOS + +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x1000007 + cpusubtype: 0x3 + filetype: 0x6 + ncmds: 4 + sizeofcmds: 600 + flags: 0x100085 + reserved: 0x0 +LoadCommands: + - cmd: LC_ID_DYLIB + cmdsize: 32 + dylib: + name: 24 + timestamp: 1 + current_version: 0 + compatibility_version: 0 + PayloadString: test + ZeroPadBytes: 4 + - cmd: LC_DYLD_INFO_ONLY + cmdsize: 48 + rebase_off: 0 + rebase_size: 0 + bind_off: 0 + bind_size: 0 + weak_bind_off: 0 + weak_bind_size: 0 + lazy_bind_off: 0 + lazy_bind_size: 0 + export_off: 0 + export_size: 0 + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 1 + minos: 659200 + sdk: 720896 + ntools: 1 + Tools: + - tool: 3 + version: 39913472 + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 6 + minos: 855808 + sdk: 917504 + ntools: 1 + Tools: + - tool: 3 + version: 39913472 +...