From bee7e226299dacc6d80d9cf6f1585c3d5d0645e0 Mon Sep 17 00:00:00 2001 From: Apple Date: Tue, 18 Sep 2018 21:29:56 +0000 Subject: [PATCH] ld64-302.3.tar.gz --- ld64.xcodeproj/project.pbxproj | 70 ++++++++-- src/abstraction/MachOFileAbstraction.hpp | 101 ++++++++++++++- src/create_configure | 6 + src/ld/HeaderAndLoadCommands.hpp | 75 +++++++++-- src/ld/InputFiles.cpp | 9 +- src/ld/Options.cpp | 151 ++++++++++++++++++---- src/ld/Options.h | 14 +- src/ld/OutputFile.cpp | 97 +++++++++----- src/ld/Resolver.cpp | 47 ++++++- src/ld/ld.hpp | 7 +- src/ld/parsers/generic_dylib_file.hpp | 2 +- src/ld/parsers/lto_file.cpp | 83 +++++++----- src/ld/parsers/lto_file.h | 4 + src/ld/parsers/macho_dylib_file.cpp | 15 ++- src/ld/parsers/macho_relocatable_file.cpp | 36 +++++- src/ld/parsers/textstub_dylib_file.cpp | 4 + src/ld/passes/code_dedup.cpp | 1 + src/other/machochecker.cpp | 6 +- src/other/unwinddump.cpp | 2 - 19 files changed, 589 insertions(+), 141 deletions(-) diff --git a/ld64.xcodeproj/project.pbxproj b/ld64.xcodeproj/project.pbxproj index 600aeac..7b7260e 100644 --- a/ld64.xcodeproj/project.pbxproj +++ b/ld64.xcodeproj/project.pbxproj @@ -290,6 +290,7 @@ F984A13B10B614CF009E9878 /* stub_arm_classic.hpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.cpp.h; path = stub_arm_classic.hpp; sourceTree = ""; tabWidth = 4; usesTabs = 1; }; F984A38010BB4B0D009E9878 /* branch_island.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = branch_island.cpp; sourceTree = ""; tabWidth = 4; usesTabs = 1; }; F984A38110BB4B0D009E9878 /* branch_island.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = branch_island.h; sourceTree = ""; tabWidth = 4; usesTabs = 1; }; + F98565241E98090F00528B1C /* dwarf2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2.h; path = src/ld/dwarf2.h; sourceTree = ""; }; F989D0391062E6350014B60C /* stub_x86_64.hpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.cpp.h; path = stub_x86_64.hpp; sourceTree = ""; tabWidth = 4; usesTabs = 1; }; F989D30B106826020014B60C /* OutputFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OutputFile.cpp; path = src/ld/OutputFile.cpp; sourceTree = ""; tabWidth = 4; usesTabs = 1; }; F989D30C106826020014B60C /* OutputFile.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = OutputFile.h; path = src/ld/OutputFile.h; sourceTree = ""; tabWidth = 4; usesTabs = 1; }; @@ -572,6 +573,7 @@ B091FB641ABA3AFB00CC8193 /* Bitcode.hpp */, F9EA7582097882F3008B4F1D /* debugline.c */, F9EA7583097882F3008B4F1D /* debugline.h */, + F98565241E98090F00528B1C /* dwarf2.h */, B3B672411406D42800A376BB /* Snapshot.cpp */, B3B672441406D44300A376BB /* Snapshot.h */, ); @@ -761,7 +763,7 @@ F9023C3006D5A227001BBF46 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0600; + LastUpgradeCheck = 0900; ORGANIZATIONNAME = "Apple Inc."; }; buildConfigurationList = F933D92309291AC90083EAC8 /* Build configuration list for PBXProject "ld64" */; @@ -1139,7 +1141,6 @@ 83046A801C8FF23E00024A7E /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; COPY_PHASE_STRIP = NO; @@ -1173,7 +1174,6 @@ 83046A811C8FF23E00024A7E /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; COPY_PHASE_STRIP = YES; @@ -1200,7 +1200,6 @@ 83046A821C8FF23E00024A7E /* Release-assert */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; COPY_PHASE_STRIP = YES; @@ -1227,7 +1226,6 @@ F933D91C09291AC90083EAC8 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; CLANG_CXX_LIBRARY = "libc++"; COPY_PHASE_STRIP = NO; @@ -1300,7 +1298,6 @@ F933D91D09291AC90083EAC8 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; CLANG_CXX_LIBRARY = "libc++"; COPY_PHASE_STRIP = NO; @@ -1377,7 +1374,6 @@ F933D92009291AC90083EAC8 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; CLANG_CXX_LIBRARY = "libc++"; COPY_PHASE_STRIP = NO; @@ -1425,7 +1421,6 @@ F933D92109291AC90083EAC8 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; CLANG_CXX_LIBRARY = "libc++"; COPY_PHASE_STRIP = YES; @@ -1463,8 +1458,27 @@ F933D92409291AC90083EAC8 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + EXCLUDED_INSTALLSRC_SUBDIRECTORY_PATTERNS = "$(inherited) build DerivedData"; GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; GCC_TREAT_WARNINGS_AS_ERRORS = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx.internal; }; @@ -1473,8 +1487,27 @@ F933D92509291AC90083EAC8 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + EXCLUDED_INSTALLSRC_SUBDIRECTORY_PATTERNS = "$(inherited) build DerivedData"; GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; GCC_TREAT_WARNINGS_AS_ERRORS = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; SDKROOT = macosx.internal; }; name = Release; @@ -1500,8 +1533,27 @@ F9849FF810B5DE8E009E9878 /* Release-assert */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + EXCLUDED_INSTALLSRC_SUBDIRECTORY_PATTERNS = "$(inherited) build DerivedData"; GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; GCC_TREAT_WARNINGS_AS_ERRORS = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; SDKROOT = macosx.internal; }; name = "Release-assert"; @@ -1520,7 +1572,6 @@ F9849FFA10B5DE8E009E9878 /* Release-assert */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; CLANG_CXX_LIBRARY = "libc++"; COPY_PHASE_STRIP = NO; @@ -1645,7 +1696,6 @@ F9849FFD10B5DE8E009E9878 /* Release-assert */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; CLANG_CXX_LIBRARY = "libc++"; COPY_PHASE_STRIP = YES; diff --git a/src/abstraction/MachOFileAbstraction.hpp b/src/abstraction/MachOFileAbstraction.hpp index a417877..252e413 100644 --- a/src/abstraction/MachOFileAbstraction.hpp +++ b/src/abstraction/MachOFileAbstraction.hpp @@ -507,6 +507,53 @@ #define DYLD_CACHE_ADJ_V2_IMAGE_OFF_32 0x0C +#ifndef LC_BUILD_VERSION + #define LC_BUILD_VERSION 0x32 /* build for platform min OS version */ + + /* + * The build_version_command contains the min OS version on which this + * binary was built to run for its platform. The list of known platforms and + * tool values following it. + */ + struct build_version_command { + uint32_t cmd; /* LC_BUILD_VERSION */ + uint32_t cmdsize; /* sizeof(struct build_version_command) plus */ + /* ntools * sizeof(struct build_tool_version) */ + uint32_t platform; /* platform */ + uint32_t minos; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ + uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ + uint32_t ntools; /* number of tool entries following this */ + }; + + struct build_tool_version { + uint32_t tool; /* enum for the tool */ + uint32_t version; /* version number of the tool */ + }; + + /* Known values for the platform field above. */ + #define PLATFORM_MACOS 1 + #define PLATFORM_IOS 2 + #define PLATFORM_TVOS 3 + #define PLATFORM_WATCHOS 4 + #define PLATFORM_BRIDGEOS 5 + + /* Known values for the tool field above. */ + #define TOOL_CLANG 1 + #define TOOL_SWIFT 2 + #define TOOL_LD 3 +#endif + +#ifndef LC_NOTE + #define LC_NOTE 0x31 + struct note_command { + uint32_t cmd; /* LC_NOTE */ + uint32_t cmdsize; /* sizeof(struct note_command) */ + char data_owner[16]; /* owner name for this LC_NOTE */ + uint64_t offset; /* file offset of this data */ + uint64_t size; /* length of data region */ + }; +#endif + // kind target-address fixup-addr [adj] @@ -577,7 +624,7 @@ static const ArchInfo archInfoArray[] = { #define SUPPORT_ARCH_arm_any 1 #endif #if SUPPORT_ARCH_arm64 - { "arm64", CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_ALL, "arm64-", "aarch64-", false, false }, + { "arm64", CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_ALL, "arm64-", "aarch64-", true, false }, #endif #if SUPPORT_ARCH_arm64v8 { "arm64v8", CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_V8, "arm64v8-", "aarch64-", true, false }, @@ -1662,6 +1709,58 @@ private: }; + +// +// mach-o build version load command +// +template +class macho_build_version_command { +public: + uint32_t cmd() const INLINE { return E::get32(fields.cmd); } + void set_cmd(uint32_t value) INLINE { E::set32(fields.cmd, value); } + + uint32_t cmdsize() const INLINE { return E::get32(fields.cmdsize); } + void set_cmdsize(uint32_t value) INLINE { E::set32(fields.cmdsize, value); } + + uint32_t platform() const INLINE { return fields.platform; } + void set_platform(uint32_t value) INLINE { E::set32(fields.platform, value); } + + uint32_t minos() const INLINE { return fields.minos; } + void set_minos(uint32_t value) INLINE { E::set32(fields.minos, value); } + + uint32_t sdk() const INLINE { return fields.sdk; } + void set_sdk(uint32_t value) INLINE { E::set32(fields.sdk, value); } + + uint32_t ntools() const INLINE { return fields.ntools; } + void set_ntools(uint32_t value) INLINE { E::set32(fields.ntools, value); } + + + typedef typename P::E E; +private: + build_version_command fields; +}; + + +// +// mach-o build version load command +// +template +class macho_build_tool_version { +public: + uint32_t tool() const INLINE { return E::get32(fields.tool); } + void set_tool(uint32_t value) INLINE { E::set32(fields.tool, value); } + + uint32_t version() const INLINE { return E::get32(fields.version); } + void set_version(uint32_t value) INLINE { E::set32(fields.version, value); } + + typedef typename P::E E; +private: + build_tool_version fields; +}; + + + + // // mach-o __LD, __compact_unwind section in object files // diff --git a/src/create_configure b/src/create_configure index 3643079..a740779 100755 --- a/src/create_configure +++ b/src/create_configure @@ -46,3 +46,9 @@ else fi echo "#define BITCODE_XAR_VERSION \"1.0\"" >> ${DERIVED_FILE_DIR}/configure.h + +if [ -n "${RC_ProjectSourceVersion}" ]; then + echo "#define LD64_VERSION_NUM ${RC_ProjectSourceVersion}" >> ${DERIVED_FILE_DIR}/configure.h +else + echo "#define LD64_VERSION_NUM 0" >> ${DERIVED_FILE_DIR}/configure.h +fi diff --git a/src/ld/HeaderAndLoadCommands.hpp b/src/ld/HeaderAndLoadCommands.hpp index a7d6620..fbcc13f 100644 --- a/src/ld/HeaderAndLoadCommands.hpp +++ b/src/ld/HeaderAndLoadCommands.hpp @@ -106,6 +106,7 @@ private: uint8_t* copyRoutinesLoadCommand(uint8_t* p) const; uint8_t* copyUUIDLoadCommand(uint8_t* p) const; uint8_t* copyVersionLoadCommand(uint8_t* p) const; + uint8_t* copyBuildVersionLoadCommand(uint8_t* p) const; uint8_t* copySourceVersionLoadCommand(uint8_t* p) const; uint8_t* copyThreadsLoadCommand(uint8_t* p) const; uint8_t* copyEntryPointLoadCommand(uint8_t* p) const; @@ -145,10 +146,12 @@ private: bool _hasRPathLoadCommands; bool _hasSubFrameworkLoadCommand; bool _hasVersionLoadCommand; + bool _hasBuildVersionLoadCommand; bool _hasFunctionStartsLoadCommand; bool _hasDataInCodeLoadCommand; bool _hasSourceVersionLoadCommand; bool _hasOptimizationHints; + Options::Platform _platform; uint32_t _dylibLoadCommmandsCount; uint32_t _allowableClientLoadCommmandsCount; uint32_t _dyldEnvironExrasCount; @@ -159,6 +162,7 @@ private: mutable uint32_t _linkeditCmdOffset; mutable uint32_t _symboltableCmdOffset; std::vector< std::vector > _linkerOptions; + std::unordered_set& _toolsVersions; static ld::Section _s_section; static ld::Section _s_preload_section; @@ -177,7 +181,8 @@ HeaderAndLoadCommandsAtom::HeaderAndLoadCommandsAtom(const Options& opts, ld: ld::Atom::scopeTranslationUnit, ld::Atom::typeUnclassified, ld::Atom::symbolTableNotIn, false, false, false, (opts.outputKind() == Options::kPreload) ? ld::Atom::Alignment(0) : ld::Atom::Alignment(log2(opts.segmentAlignment())) ), - _options(opts), _state(state), _writer(writer), _address(0), _uuidCmdInOutputBuffer(NULL), _linkeditCmdOffset(0), _symboltableCmdOffset(0) + _options(opts), _state(state), _writer(writer), _address(0), _uuidCmdInOutputBuffer(NULL), _linkeditCmdOffset(0), _symboltableCmdOffset(0), + _toolsVersions(state.toolsVersions) { bzero(_uuid, 16); _hasDyldInfoLoadCommand = opts.makeCompressedDyldInfo(); @@ -233,9 +238,21 @@ HeaderAndLoadCommandsAtom::HeaderAndLoadCommandsAtom(const Options& opts, ld: } _hasRPathLoadCommands = (_options.rpaths().size() != 0); _hasSubFrameworkLoadCommand = (_options.umbrellaName() != NULL); - _hasVersionLoadCommand = _options.addVersionLoadCommand() || - (!state.objectFileFoundWithNoVersion && (_options.outputKind() == Options::kObjectFile) - && ((_options.platform() != Options::kPlatformUnknown) || (state.derivedPlatformLoadCommand != 0)) ); + _platform = _options.platform(); + if ( (_platform == Options::kPlatformUnknown) && (_state.derivedPlatform != 0) ) + _platform = (Options::Platform)_state.derivedPlatform; + if ( _options.addVersionLoadCommand() ) { + _hasBuildVersionLoadCommand = _options.addBuildVersionLoadCommand(); + _hasVersionLoadCommand = !_hasBuildVersionLoadCommand; + } + else if (((_options.outputKind() == Options::kObjectFile) && (_platform != Options::kPlatformUnknown) && !state.objectFileFoundWithNoVersion) ) { + _hasBuildVersionLoadCommand = (_platform == Options::kPlatform_bridgeOS); + _hasVersionLoadCommand = !_hasBuildVersionLoadCommand; + } + else { + _hasVersionLoadCommand = false; + _hasBuildVersionLoadCommand = false; + } _hasFunctionStartsLoadCommand = _options.addFunctionStarts(); _hasDataInCodeLoadCommand = _options.addDataInCodeInfo(); _hasSourceVersionLoadCommand = _options.needsSourceVersionLoadCommand(); @@ -410,6 +427,9 @@ uint64_t HeaderAndLoadCommandsAtom::size() const if ( _hasVersionLoadCommand ) sz += sizeof(macho_version_min_command

); + if ( _hasBuildVersionLoadCommand ) + sz += alignedSize(sizeof(macho_build_version_command

) + sizeof(macho_build_tool_version

)*_toolsVersions.size()); + if ( _hasSourceVersionLoadCommand ) sz += sizeof(macho_source_version_command

); @@ -513,6 +533,9 @@ uint32_t HeaderAndLoadCommandsAtom::commandsCount() const if ( _hasVersionLoadCommand ) ++count; + if ( _hasBuildVersionLoadCommand ) + ++count; + if ( _hasSourceVersionLoadCommand ) ++count; @@ -680,7 +703,7 @@ uint32_t HeaderAndLoadCommandsAtom::cpuSubType() const template <> uint32_t HeaderAndLoadCommandsAtom::cpuSubType() const { - return CPU_SUBTYPE_ARM64_ALL; + return _state.cpuSubType; } @@ -1159,14 +1182,7 @@ template uint8_t* HeaderAndLoadCommandsAtom::copyVersionLoadCommand(uint8_t* p) const { macho_version_min_command

* cmd = (macho_version_min_command

*)p; - switch (_options.platform()) { - case Options::kPlatformUnknown: - assert(_state.derivedPlatformLoadCommand != 0 && "unknown platform"); - cmd->set_cmd(_state.derivedPlatformLoadCommand); - cmd->set_cmdsize(sizeof(macho_version_min_command

)); - cmd->set_version(_state.minOSVersion); - cmd->set_sdk(0); - break; + switch (_platform) { case Options::kPlatformOSX: cmd->set_cmd(LC_VERSION_MIN_MACOSX); cmd->set_cmdsize(sizeof(macho_version_min_command

)); @@ -1193,10 +1209,40 @@ uint8_t* HeaderAndLoadCommandsAtom::copyVersionLoadCommand(uint8_t* p) const cmd->set_sdk(_options.sdkVersion()); break; #endif + case Options::kPlatformUnknown: + assert(0 && "unknown platform"); + break; + case Options::kPlatform_bridgeOS: + assert(0 && "bridgeOS uses LC_BUILD_VERSION"); + break; } return p + sizeof(macho_version_min_command

); } + + +template +uint8_t* HeaderAndLoadCommandsAtom::copyBuildVersionLoadCommand(uint8_t* p) const +{ + macho_build_version_command

* cmd = (macho_build_version_command

*)p; + + cmd->set_cmd(LC_BUILD_VERSION); + cmd->set_cmdsize(alignedSize(sizeof(macho_build_version_command

) + sizeof(macho_build_tool_version

)*_toolsVersions.size())); + cmd->set_platform(_options.platform()); + cmd->set_minos(_state.minOSVersion); + cmd->set_sdk(_options.sdkVersion()); + cmd->set_ntools(_toolsVersions.size()); + macho_build_tool_version

* tools = (macho_build_tool_version

*)(p + sizeof(macho_build_version_command

)); + for (uint64_t tool : _toolsVersions) { + tools->set_tool((uint64_t)tool >> 32); + tools->set_version(tool & 0xFFFFFFFF); + ++tools; + } + + return p + cmd->cmdsize(); +} + + template uint8_t* HeaderAndLoadCommandsAtom::copySourceVersionLoadCommand(uint8_t* p) const { @@ -1553,6 +1599,9 @@ void HeaderAndLoadCommandsAtom::copyRawContent(uint8_t buffer[]) const if ( _hasVersionLoadCommand ) p = this->copyVersionLoadCommand(p); + if ( _hasBuildVersionLoadCommand ) + p = this->copyBuildVersionLoadCommand(p); + if ( _hasSourceVersionLoadCommand ) p = this->copySourceVersionLoadCommand(p); diff --git a/src/ld/InputFiles.cpp b/src/ld/InputFiles.cpp index 79401f2..1c69de6 100644 --- a/src/ld/InputFiles.cpp +++ b/src/ld/InputFiles.cpp @@ -1232,8 +1232,15 @@ void InputFiles::forEachInitialAtom(ld::File::AtomHandler& handler, ld::Internal } break; } - file->forEachAtom(handler); + try { + file->forEachAtom(handler); + } + catch (const char* msg) { + asprintf((char**)&_exception, "%s file '%s'", msg, file->path()); + } } + if (_exception) + throw _exception; markExplicitlyLinkedDylibs(); addLinkerOptionLibraries(state, handler); diff --git a/src/ld/Options.cpp b/src/ld/Options.cpp index d36bc02..b739786 100644 --- a/src/ld/Options.cpp +++ b/src/ld/Options.cpp @@ -53,6 +53,8 @@ extern "C" size_t fnd_get_demangled_name(const char *mangledName, char *outputBu // upward dependency on lto::version() namespace lto { extern const char* version(); + extern unsigned static_api_version(); + extern unsigned runtime_api_version(); } // magic to place command line in crash reports @@ -171,7 +173,7 @@ Options::Options(int argc, const char* argv[]) fObjcGcCompaction(false), fObjCGc(false), fObjCGcOnly(false), fDemangle(false), fTLVSupport(false), fVersionLoadCommand(false), fVersionLoadCommandForcedOn(false), - fVersionLoadCommandForcedOff(false), fFunctionStartsLoadCommand(false), + fVersionLoadCommandForcedOff(false), fBuildVersionLoadCommand(false), fFunctionStartsLoadCommand(false), fFunctionStartsForcedOn(false), fFunctionStartsForcedOff(false), fDataInCodeInfoLoadCommand(false), fDataInCodeInfoLoadCommandForcedOn(false), fDataInCodeInfoLoadCommandForcedOff(false), fCanReExportSymbols(false), fObjcCategoryMerging(true), fPageAlignDataAtoms(false), @@ -190,11 +192,12 @@ Options::Options(int argc, const char* argv[]) fBundleBitcode(false), fHideSymbols(false), fVerifyBitcode(false), fReverseMapUUIDRename(false), fDeDupe(true), fVerboseDeDupe(false), fReverseMapPath(NULL), fLTOCodegenOnly(false), - fIgnoreAutoLink(false), fAllowDeadDups(false), fAllowWeakImports(true), fBitcodeKind(kBitcodeProcess), + fIgnoreAutoLink(false), fAllowDeadDups(false), fAllowWeakImports(true), fNoInitializers(false), fBitcodeKind(kBitcodeProcess), fPlatform(kPlatformUnknown), fDebugInfoStripping(kDebugInfoMinimal), fTraceOutputFile(NULL), fMacVersionMin(ld::macVersionUnset), fIOSVersionMin(ld::iOSVersionUnset), fWatchOSVersionMin(ld::wOSVersionUnset), fSaveTempFiles(false), fSnapshotRequested(false), fPipelineFifo(NULL), - fDependencyInfoPath(NULL), fDependencyFileDescriptor(-1), fTraceFileDescriptor(-1), fMaxDefaultCommonAlign(0) + fDependencyInfoPath(NULL), fDependencyFileDescriptor(-1), fTraceFileDescriptor(-1), fMaxDefaultCommonAlign(0), + fUnalignedPointerTreatment(kUnalignedPointerIgnore) { this->checkForClassic(argc, argv); this->parsePreCommandLineEnvironmentSettings(); @@ -598,8 +601,10 @@ uint32_t Options::minOSversion() const case Options::kPlatform_tvOS: return iOSVersionMin(); #endif - default: - break; + case kPlatform_bridgeOS: + return iOSVersionMin(); + case kPlatformUnknown: + return 0; } return 0; } @@ -613,7 +618,8 @@ void Options::setArchitecture(cpu_type_t type, cpu_subtype_t subtype, Options::P fArchitectureName = t->archName; fHasPreferredSubType = t->isSubType; fArchSupportsThumb2 = t->supportsThumb2; - fPlatform = platform; + if ( fPlatform == kPlatformUnknown) + fPlatform = platform; switch ( type ) { case CPU_TYPE_I386: case CPU_TYPE_X86_64: @@ -1501,12 +1507,8 @@ bool Options::minOS(ld::MacVersionMin requiredMacMin, ld::IOSVersionMin required if ( fMacVersionMin != ld::macVersionUnset ) { return ( fMacVersionMin >= requiredMacMin ); } - else if ( fWatchOSVersionMin != ld::wOSVersionUnset ) { - // Hack until we fully track watch and ios versions seperately - return ( (fWatchOSVersionMin + 0x00070000) >= requirediPhoneOSMin); - } else { - return ( fIOSVersionMin >= requirediPhoneOSMin ); + return min_iOS(requirediPhoneOSMin); } } @@ -1516,6 +1518,10 @@ bool Options::min_iOS(ld::IOSVersionMin requirediOSMin) // Hack until we fully track watch and ios versions seperately return ( (fWatchOSVersionMin + 0x00070000) >= requirediOSMin); } + else if ( fPlatform == Options::kPlatform_bridgeOS ) { + // Hack until we fully track bridge and ios versions seperately + return ( (fIOSVersionMin + 0x00090000) >= requirediOSMin); + } else { return ( fIOSVersionMin >= requirediOSMin ); } @@ -2180,6 +2186,8 @@ std::string Options::getPlatformStr() const return "AppleTVOS"; break; #endif + case Options::kPlatform_bridgeOS: + return "bridgeOS"; case Options::kPlatformUnknown: return "Unknown"; } @@ -2247,6 +2255,10 @@ std::vector Options::writeBitcodeLinkOptions() const linkCommand.push_back(getVersionString32((unsigned)fIOSVersionMin)); break; #endif + case Options::kPlatform_bridgeOS: + linkCommand.push_back("-bridgeos_version_min"); + linkCommand.push_back(getVersionString32((unsigned)fIOSVersionMin)); + break; case Options::kPlatformUnknown: if ( fOutputKind != Options::kObjectFile ) { throwf("platform is unknown for final bitcode bundle," @@ -2991,6 +3003,13 @@ void Options::parse(int argc, const char* argv[]) fTargetIOSSimulator = true; } #endif + else if ( strcmp(arg, "-bridgeos_version_min") == 0 ) { + const char* vers = argv[++i]; + if ( vers == NULL ) + throw "-bridgeos_version_min missing version argument"; + setIOSVersionMin(vers); + fPlatform = kPlatform_bridgeOS; + } else if ( strcmp(arg, "-multiply_defined") == 0 ) { //warnObsolete(arg); ++i; @@ -3252,8 +3271,8 @@ void Options::parse(int argc, const char* argv[]) if ( fReverseMapPath == NULL ) throw "missing argument to -bitcode_symbol_map"; struct stat statbuf; - ::stat(fReverseMapPath, &statbuf); - if (S_ISDIR(statbuf.st_mode)) { + int ret = ::stat(fReverseMapPath, &statbuf); + if ( ret == 0 && S_ISDIR(statbuf.st_mode)) { char tempPath[PATH_MAX]; sprintf(tempPath, "%s/XXXXXX", fReverseMapPath); int tempFile = ::mkstemp(tempPath); @@ -3845,6 +3864,9 @@ void Options::parse(int argc, const char* argv[]) else if ( strcmp(argv[i], "-no_weak_imports") == 0 ) { fAllowWeakImports = false; } + else if ( strcmp(argv[i], "-no_inits") == 0 ) { + fNoInitializers = true; + } // put this last so that it does not interfer with other options starting with 'i' else if ( strncmp(arg, "-i", 2) == 0 ) { const char* colon = strchr(arg, ':'); @@ -3946,7 +3968,8 @@ void Options::buildSearchPaths(int argc, const char* argv[]) if ( argc == 2 ) { const char* ltoVers = lto::version(); if ( ltoVers != NULL ) - fprintf(stderr, "LTO support using: %s\n", ltoVers); + fprintf(stderr, "LTO support using: %s (static support for %d, runtime is %d)\n", + ltoVers, lto::static_api_version(), lto::runtime_api_version()); fprintf(stderr, "TAPI support using: %s\n", tapi::Version::getFullVersionAsString().c_str()); exit(0); } @@ -4240,6 +4263,12 @@ void Options::parsePostCommandLineEnvironmentSettings() } + +static bool sharedCacheEligiblePath(const char* path) +{ + return ( (strncmp(path, "/usr/lib/", 9) == 0) || (strncmp(path, "/System/Library/", 16) == 0) ); +} + void Options::reconfigureDefaults() { // sync reader options @@ -4569,10 +4598,9 @@ void Options::reconfigureDefaults() // determine if info for shared region should be added if ( fOutputKind == Options::kDynamicLibrary ) { - if ( minOS(ld::mac10_5, ld::iOS_3_1) && !fTargetIOSSimulator ) + if ( minOS(ld::mac10_5, ld::iOS_3_1) ) if ( !fPrebind && !fSharedRegionEligibleForceOff ) - if ( (strncmp(this->installPath(), "/usr/lib/", 9) == 0) - || (strncmp(this->installPath(), "/System/Library/", 16) == 0) ) + if ( sharedCacheEligiblePath(this->installPath()) ) fSharedRegionEligible = true; } else if ( fOutputKind == Options::kDyld ) { @@ -4580,12 +4608,8 @@ void Options::reconfigureDefaults() fSharedRegionEligible = true; } - // warn if -rpath is used with OS dylibs - if ( fSharedRegionEligible && !fRPaths.empty() ) - warning("-rpath cannot be used with dylibs that will be in the dyld shared cache"); - // automatically use __DATA_CONST in iOS dylibs - if ( fSharedRegionEligible && minOS(ld::mac10_Future, ld::iOS_9_0) && !fUseDataConstSegmentForceOff ) { + if ( fSharedRegionEligible && minOS(ld::mac10_Future, ld::iOS_9_0) && !fUseDataConstSegmentForceOff && !fTargetIOSSimulator) { fUseDataConstSegment = true; } if ( fUseDataConstSegmentForceOn ) { @@ -4621,9 +4645,19 @@ void Options::reconfigureDefaults() // Use V2 shared cache info when targetting newer OSs if ( fSharedRegionEligible && minOS(ld::mac10_12, ld::iOS_9_0)) { fSharedRegionEncodingV2 = true; - // only use v2 for Swift dylibs on Mac OS X - if ( (fPlatform == kPlatformOSX) && (strncmp(this->installPath(), "/System/Library/PrivateFrameworks/Swift/", 40) != 0) ) + if ( fPlatform == kPlatformOSX ) { fSharedRegionEncodingV2 = false; + // only use v2 for Swift dylibs on Mac OS X + if ( strncmp(this->installPath(), "/System/Library/PrivateFrameworks/Swift/", 40) == 0 ) + fSharedRegionEncodingV2 = true; + // an other OS frameworks that use swift need v2 + for (const char* searchPath : fLibrarySearchPaths ) { + if ( strstr(searchPath, "xctoolchain/usr/lib/swift/macos") != NULL ) { + fSharedRegionEncodingV2 = true; + break; + } + } + } fIgnoreOptimizationHints = true; } @@ -5142,6 +5176,19 @@ void Options::reconfigureDefaults() } } + + // Automatically use OrderFiles found in the AppleInternal SDK + if ( (fFinalName != NULL) && fOrderedSymbols.empty() && !fSDKPaths.empty() ) { + char path[PATH_MAX]; + strlcpy(path , fSDKPaths.front(), sizeof(path)); + strlcat(path , "/AppleInternal/OrderFiles/", sizeof(path)); + strlcat(path , fFinalName, sizeof(path)); + strlcat(path , ".order", sizeof(path)); + FileInfo info; + if ( info.checkFileExists(*this, path) ) + parseOrderFile(path, false); + } + // Reduce the default alignment of structures/arrays to save memory in embedded systems if ( fMaxDefaultCommonAlign == 0 ) { if ( fOutputKind == Options::kPreload ) @@ -5149,6 +5196,56 @@ void Options::reconfigureDefaults() else fMaxDefaultCommonAlign = 15; } + + // Add warnings for issues likely to cause OS verification issues + if ( fSharedRegionEligible && !fRPaths.empty() ) { + // warn if -rpath is used with OS dylibs + warning("OS dylibs should not add rpaths (linker option: -rpath) (Xcode build setting: LD_RUNPATH_SEARCH_PATHS)"); + } + if ( (fOutputKind == Options::kDynamicLibrary) && (fDylibInstallName != NULL) && (fFinalName != NULL) && sharedCacheEligiblePath(fFinalName) ) { + if ( strncmp(fDylibInstallName, "@rpath", 6) == 0 ) + warning("OS dylibs should not use @rpath for -install_name. Use absolute path instead"); + if ( strcmp(fDylibInstallName, fFinalName) != 0 ) { + bool different = true; + // some projects end up with double slash in -final_output path + if ( strstr(fFinalName, "//") != NULL ) { + char fixedPath[strlen(fFinalName)+1]; + char* t = fixedPath; + bool lastWasSlash = false; + for (const char* s=fFinalName; *s != '\0'; ++s) { + if ( *s == '/' ) { + if ( !lastWasSlash ) + *t++ = *s; + lastWasSlash = true; + } + else { + *t++ = *s; + lastWasSlash = false; + } + } + *t = '\0'; + different = (strcmp(fDylibInstallName, fixedPath) != 0); + } + if ( different ) + warning("OS dylibs -install_name should match its real absolute path"); + } + } + + // set if unaligned pointers are warnings or errors + if ( fMacVersionMin >= ld::mac10_12 ) { + // ignore unaligned pointers when targeting older macOS versions + if ( fSharedRegionEligible ) + fUnalignedPointerTreatment = Options::kUnalignedPointerWarning; + else + fUnalignedPointerTreatment = Options::kUnalignedPointerIgnore; + } + else if ( min_iOS(ld::iOS_10_0) ) { + fUnalignedPointerTreatment = Options::kUnalignedPointerWarning; + } + else { + fUnalignedPointerTreatment = Options::kUnalignedPointerIgnore; + } + } void Options::checkIllegalOptionCombinations() @@ -5164,6 +5261,7 @@ void Options::checkIllegalOptionCombinations() break; case kPlatformiOS: case kPlatformWatchOS: + case kPlatform_bridgeOS: #if SUPPORT_APPLE_TV case kPlatform_tvOS: #endif @@ -5237,6 +5335,7 @@ void Options::checkIllegalOptionCombinations() break; case kPlatformiOS: case kPlatformWatchOS: + case kPlatform_bridgeOS: #if SUPPORT_APPLE_TV case Options::kPlatform_tvOS: #endif @@ -5666,6 +5765,10 @@ void Options::checkIllegalOptionCombinations() warning("embedded dylibs/frameworks only run on iOS 8 or later"); } + // bridgeOS always generates new load command + if ( fVersionLoadCommand && (fPlatform == kPlatform_bridgeOS) ) { + fBuildVersionLoadCommand = true; + } // produce nicer error when no input if ( fInputFiles.empty() ) { diff --git a/src/ld/Options.h b/src/ld/Options.h index d489fd6..4ff780c 100644 --- a/src/ld/Options.h +++ b/src/ld/Options.h @@ -88,8 +88,9 @@ public: enum LocalSymbolHandling { kLocalSymbolsAll, kLocalSymbolsNone, kLocalSymbolsSelectiveInclude, kLocalSymbolsSelectiveExclude }; enum BitcodeMode { kBitcodeProcess, kBitcodeAsData, kBitcodeMarker, kBitcodeStrip }; enum DebugInfoStripping { kDebugInfoNone, kDebugInfoMinimal, kDebugInfoFull }; + enum UnalignedPointerTreatment { kUnalignedPointerError, kUnalignedPointerWarning, kUnalignedPointerIgnore }; #if SUPPORT_APPLE_TV - enum Platform { kPlatformUnknown, kPlatformOSX, kPlatformiOS, kPlatformWatchOS, kPlatform_tvOS }; + enum Platform { kPlatformUnknown, kPlatformOSX=1, kPlatformiOS=2, kPlatformWatchOS=3, kPlatform_tvOS=4, kPlatform_bridgeOS=5 }; #else enum Platform { kPlatformUnknown, kPlatformOSX, kPlatformiOS, kPlatformWatchOS }; #endif @@ -123,6 +124,8 @@ public: case kPlatform_tvOS: return "tvOS"; #endif + case kPlatform_bridgeOS: + return "bridgeOS"; case kPlatformUnknown: default: return "(unknown)"; @@ -144,6 +147,9 @@ public: case 4: strcpy(versionString, "3.0"); break; + case 5: + strcpy(versionString, "4.0"); + break; default: sprintf(versionString, "unknown ABI version 0x%02X", value); } @@ -428,6 +434,7 @@ public: bool objcGcOnly() const { return fObjCGcOnly; } bool canUseThreadLocalVariables() const { return fTLVSupport; } bool addVersionLoadCommand() const { return fVersionLoadCommand && (fPlatform != kPlatformUnknown); } + bool addBuildVersionLoadCommand() const { return fBuildVersionLoadCommand; } bool addFunctionStarts() const { return fFunctionStartsLoadCommand; } bool addDataInCodeInfo() const { return fDataInCodeInfoLoadCommand; } bool canReExportSymbols() const { return fCanReExportSymbols; } @@ -461,6 +468,7 @@ public: bool ignoreAutoLink() const { return fIgnoreAutoLink; } bool allowDeadDuplicates() const { return fAllowDeadDups; } bool allowWeakImports() const { return fAllowWeakImports; } + bool noInitializers() const { return fNoInitializers; } BitcodeMode bitcodeKind() const { return fBitcodeKind; } bool sharedRegionEncodingV2() const { return fSharedRegionEncodingV2; } bool useDataConstSegment() const { return fUseDataConstSegment; } @@ -504,6 +512,7 @@ public: bool hasDataSymbolMoves() const { return !fSymbolsMovesData.empty(); } bool hasCodeSymbolMoves() const { return !fSymbolsMovesCode.empty(); } void writeToTraceFile(const char* buffer, size_t len) const; + UnalignedPointerTreatment unalignedPointerTreatment() const { return fUnalignedPointerTreatment; } static uint32_t parseVersionNumber32(const char*); @@ -730,6 +739,7 @@ private: bool fVersionLoadCommand; bool fVersionLoadCommandForcedOn; bool fVersionLoadCommandForcedOff; + bool fBuildVersionLoadCommand; bool fFunctionStartsLoadCommand; bool fFunctionStartsForcedOn; bool fFunctionStartsForcedOff; @@ -778,6 +788,7 @@ private: bool fIgnoreAutoLink; bool fAllowDeadDups; bool fAllowWeakImports; + bool fNoInitializers; BitcodeMode fBitcodeKind; Platform fPlatform; DebugInfoStripping fDebugInfoStripping; @@ -817,6 +828,7 @@ private: mutable int fDependencyFileDescriptor; mutable int fTraceFileDescriptor; uint8_t fMaxDefaultCommonAlign; + UnalignedPointerTreatment fUnalignedPointerTreatment; }; diff --git a/src/ld/OutputFile.cpp b/src/ld/OutputFile.cpp index 3b775c9..044f850 100644 --- a/src/ld/OutputFile.cpp +++ b/src/ld/OutputFile.cpp @@ -684,7 +684,7 @@ void OutputFile::rangeCheckRIP32(int64_t displacement, ld::Internal& state, cons printSectionLayout(state); const ld::Atom* target; - throwf("32-bit RIP relative reference out of range (%lld max is +/-4GB): from %s (0x%08llX) to %s (0x%08llX)", + throwf("32-bit RIP relative reference out of range (%lld max is +/-2GB): from %s (0x%08llX) to %s (0x%08llX)", displacement, atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fixup), addressOf(state, fixup, &target)); } @@ -2948,7 +2948,7 @@ void OutputFile::buildSymbolTable(ld::Internal& state) ++machoSectionIndex; for (std::vector::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) { const ld::Atom* atom = *ait; - if ( setMachoSectionIndex ) + if ( setMachoSectionIndex ) (const_cast(atom))->setMachoSection(machoSectionIndex); else if ( sect->type() == ld::Section::typeMachHeader ) (const_cast(atom))->setMachoSection(1); // __mh_execute_header is not in any section by needs n_sect==1 @@ -4275,12 +4275,18 @@ void OutputFile::addDyldInfo(ld::Internal& state, ld::Internal::FinalSection* s } } if ( ((address & (pointerSize-1)) != 0) && (rebaseType == REBASE_TYPE_POINTER) ) { - if ( (pointerSize == 8) && ((address & 7) == 4) ) { - // for now, don't warning about 8-byte pointers only 4-byte aligned - } - else { - warning("pointer not aligned at address 0x%llX (%s + %lld from %s)", - address, atom->name(), (address - atom->finalAddress()), atom->safeFilePath()); + switch ( _options.unalignedPointerTreatment() ) { + case Options::kUnalignedPointerError: + throwf("pointer not aligned at address 0x%llX (%s + %lld from %s)", + address, atom->name(), (address - atom->finalAddress()), atom->safeFilePath()); + break; + case Options::kUnalignedPointerWarning: + warning("pointer not aligned at address 0x%llX (%s + %lld from %s)", + address, atom->name(), (address - atom->finalAddress()), atom->safeFilePath()); + break; + case Options::kUnalignedPointerIgnore: + // do nothing + break; } } _rebaseInfo.push_back(RebaseInfo(rebaseType, address)); @@ -4291,12 +4297,18 @@ void OutputFile::addDyldInfo(ld::Internal& state, ld::Internal::FinalSection* s sect->hasExternalRelocs = true; // so dyld knows to change permissions on __TEXT segment } if ( ((address & (pointerSize-1)) != 0) && (type == BIND_TYPE_POINTER) ) { - if ( (pointerSize == 8) && ((address & 7) == 4) ) { - // for now, don't warning about 8-byte pointers only 4-byte aligned - } - else { - warning("pointer not aligned at address 0x%llX (%s + %lld from %s)", - address, atom->name(), (address - atom->finalAddress()), atom->safeFilePath()); + switch ( _options.unalignedPointerTreatment() ) { + case Options::kUnalignedPointerError: + throwf("pointer not aligned at address 0x%llX (%s + %lld from %s)", + address, atom->name(), (address - atom->finalAddress()), atom->safeFilePath()); + break; + case Options::kUnalignedPointerWarning: + warning("pointer not aligned at address 0x%llX (%s + %lld from %s)", + address, atom->name(), (address - atom->finalAddress()), atom->safeFilePath()); + break; + case Options::kUnalignedPointerIgnore: + // do nothing + break; } } _bindingInfo.push_back(BindingInfo(type, this->compressedOrdinalForAtom(target), target->name(), weak_import, address, addend)); @@ -5236,6 +5248,7 @@ void OutputFile::synthesizeDebugNotes(ld::Internal& state) // make a vector of atoms that come from files compiled with dwarf debug info std::vector atomsNeedingDebugNotes; std::set atomsWithStabs; + std::set filesSeenWithStabs; atomsNeedingDebugNotes.reserve(1024); const ld::relocatable::File* objFile = NULL; bool objFileHasDwarf = false; @@ -5285,8 +5298,11 @@ void OutputFile::synthesizeDebugNotes(ld::Internal& state) } if ( objFileHasDwarf ) atomsNeedingDebugNotes.push_back(atom); - if ( objFileHasStabs ) + if ( objFileHasStabs ) { atomsWithStabs.insert(atom); + if ( objFile != NULL ) + filesSeenWithStabs.insert(objFile); + } } } } @@ -5480,33 +5496,44 @@ void OutputFile::synthesizeDebugNotes(ld::Internal& state) endFileStab.string = ""; state.stabs.push_back(endFileStab); } - - // copy any stabs from .o file - std::set filesSeenWithStabs; - for (std::set::iterator it=atomsWithStabs.begin(); it != atomsWithStabs.end(); it++) { - const ld::Atom* atom = *it; - objFile = dynamic_cast(atom->file()); - if ( objFile != NULL ) { - if ( filesSeenWithStabs.count(objFile) == 0 ) { - filesSeenWithStabs.insert(objFile); - const std::vector* stabs = objFile->stabs(); - if ( stabs != NULL ) { - for(std::vector::const_iterator sit = stabs->begin(); sit != stabs->end(); ++sit) { - ld::relocatable::File::Stab stab = *sit; - // ignore stabs associated with atoms that were dead stripped or coalesced away - if ( (sit->atom != NULL) && (atomsWithStabs.count(sit->atom) == 0) ) + + // copy any stabs from .o files + bool deadStripping = _options.deadCodeStrip(); + for (const ld::relocatable::File* obj : filesSeenWithStabs) { + const std::vector* filesStabs = obj->stabs(); + if ( filesStabs != NULL ) { + for (const ld::relocatable::File::Stab& stab : *filesStabs ) { + // ignore stabs associated with atoms that were dead stripped or coalesced away + if ( (stab.atom != NULL) && (atomsWithStabs.count(stab.atom) == 0) ) + continue; + // Value of N_SO stabs should be address of first atom from translation unit + if ( (stab.type == N_SO) && (stab.string != NULL) && (stab.string[0] != '\0') ) { + uint64_t lowestAtomAddress = 0; + const ld::Atom* lowestAddressAtom = NULL; + for (const ld::relocatable::File::Stab& stab2 : *filesStabs ) { + if ( stab2.atom == NULL ) continue; - // Value of N_SO stabs should be address of first atom from translation unit - if ( (stab.type == N_SO) && (stab.string != NULL) && (stab.string[0] != '\0') ) { - stab.atom = atom; + // skip over atoms that were dead stripped + if ( deadStripping && !stab2.atom->live() ) + continue; + if ( stab2.atom->coalescedAway() ) + continue; + uint64_t atomAddr = stab2.atom->objectAddress(); + if ( (lowestAddressAtom == NULL) || (atomAddr < lowestAtomAddress) ) { + lowestAddressAtom = stab2.atom; + lowestAtomAddress = atomAddr; } - state.stabs.push_back(stab); } + ld::relocatable::File::Stab altStab = stab; + altStab.atom = lowestAddressAtom; + state.stabs.push_back(altStab); + } + else { + state.stabs.push_back(stab); } } } } - } diff --git a/src/ld/Resolver.cpp b/src/ld/Resolver.cpp index 24af5f8..831fa7f 100644 --- a/src/ld/Resolver.cpp +++ b/src/ld/Resolver.cpp @@ -51,7 +51,6 @@ #include #include "Options.h" - #include "ld.hpp" #include "Bitcode.hpp" #include "InputFiles.h" @@ -59,6 +58,10 @@ #include "Resolver.h" #include "parsers/lto_file.h" +#include "configure.h" + +#define VAL(x) #x +#define STRINGIFY(x) VAL(x) namespace ld { namespace tool { @@ -284,7 +287,7 @@ void Resolver::initializeState() _internal.cpuSubType = _options.subArchitecture(); _internal.minOSVersion = _options.minOSversion(); - _internal.derivedPlatformLoadCommand = 0; + _internal.derivedPlatform = 0; // In -r mode, look for -linker_option additions if ( _options.outputKind() == Options::kObjectFile ) { @@ -293,6 +296,11 @@ void Resolver::initializeState() doLinkerOption(*it, "command line"); } } +#ifdef LD64_VERSION_NUM + uint32_t packedNum = Options::parseVersionNumber32(STRINGIFY(LD64_VERSION_NUM)); + uint64_t combined = (uint64_t)TOOL_LD << 32 | packedNum; + _internal.toolsVersions.insert(combined); +#endif } void Resolver::buildAtomList() @@ -366,6 +374,7 @@ void Resolver::doFile(const ld::File& file) // No bitcode section, figure out if the object file comes from LTO/compiler static library switch ( _options.platform() ) { case Options::kPlatformOSX: + case Options::kPlatform_bridgeOS: case Options::kPlatformUnknown: warning("all bitcode will be dropped because '%s' was built without bitcode. " "You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. ", file.path()); @@ -475,14 +484,19 @@ void Resolver::doFile(const ld::File& file) uint32_t objMinOS = objFile->minOSVersion(); if ( !objMinOS ) _internal.objectFileFoundWithNoVersion = true; - - uint32_t objPlatformLC = objFile->platformLoadCommand(); - if ( (objPlatformLC != 0) && (_internal.derivedPlatformLoadCommand == 0) && (_options.outputKind() == Options::kObjectFile) ) - _internal.derivedPlatformLoadCommand = objPlatformLC; - if ( (_options.outputKind() == Options::kObjectFile) && (objMinOS > _internal.minOSVersion) ) _internal.minOSVersion = objMinOS; + uint32_t objPlatform = objFile->platform(); + if ( (objPlatform != 0) && (_options.outputKind() == Options::kObjectFile) && (_internal.derivedPlatform == 0) ) + _internal.derivedPlatform = objPlatform; + + // update set of known tools used + for (const std::pair& entry : objFile->toolVersions()) { + uint64_t combined = (uint64_t)entry.first << 32 | entry.second; + _internal.toolsVersions.insert(combined); + } + // update cpu-sub-type cpu_subtype_t nextObjectSubType = file.cpuSubType(); switch ( _options.architecture() ) { @@ -505,6 +519,19 @@ void Resolver::doFile(const ld::File& file) } break; + case CPU_TYPE_ARM64: + if ( _options.subArchitecture() != nextObjectSubType ) { + if ( _options.allowSubArchitectureMismatches() ) { + warning("object file %s was built for different arm64 sub-type (%d) than link command line (%d)", + file.path(), nextObjectSubType, _options.subArchitecture()); + } + else { + throwf("object file %s was built for different arm64 sub-type (%d) than link command line (%d)", + file.path(), nextObjectSubType, _options.subArchitecture()); + } + } + break; + case CPU_TYPE_I386: _internal.cpuSubType = CPU_SUBTYPE_I386_ALL; break; @@ -547,6 +574,7 @@ void Resolver::doFile(const ld::File& file) strncmp(tcLibPath, tempPath, strlen(tcLibPath)) != 0 ) { switch ( _options.platform() ) { case Options::kPlatformOSX: + case Options::kPlatform_bridgeOS: case Options::kPlatformUnknown: warning("all bitcode will be dropped because '%s' was built without bitcode. " "You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target.", file.path()); @@ -766,6 +794,11 @@ void Resolver::doAtom(const ld::Atom& atom) if ( atom.section().type() == ld::Section::typeTempAlias ) _haveAliases = true; + // prevent initializers if -no_inits used + if ( (atom.section().type() == ld::Section::typeInitializerPointers) && _options.noInitializers() ) { + throw "-no_inits specified, but initializer found"; + } + if ( _options.deadCodeStrip() ) { // add to set of dead-strip-roots, all symbols that the compiler marks as don't strip if ( atom.dontDeadStrip() ) diff --git a/src/ld/ld.hpp b/src/ld/ld.hpp index 8351e3f..5e9164f 100644 --- a/src/ld/ld.hpp +++ b/src/ld/ld.hpp @@ -157,7 +157,7 @@ public: virtual uint32_t cpuSubType() const { return 0; } virtual uint32_t subFileCount() const { return 1; } virtual uint32_t minOSVersion() const { return 0; } - virtual uint32_t platformLoadCommand() const { return 0; } + virtual uint32_t platform() const { return 0; } bool fileExists() const { return _modTime != 0; } Type type() const { return _type; } virtual Bitcode* getBitcode() const { return NULL; } @@ -213,6 +213,7 @@ namespace relocatable { const char* string; }; typedef const std::vector< std::vector > LinkerOptionsList; + typedef std::vector> ToolVersionList; File(const char* pth, time_t modTime, Ordinal ord) : ld::File(pth, modTime, ord, Reloc) { } @@ -224,6 +225,7 @@ namespace relocatable { virtual bool canScatterAtoms() const = 0; virtual bool hasLongBranchStubs() { return false; } virtual LinkerOptionsList* linkerOptions() const = 0; + virtual const ToolVersionList& toolVersions() const = 0; virtual SourceKind sourceKind() const { return kSourceUnknown; } virtual const uint8_t* fileContent() const { return nullptr; } }; @@ -919,6 +921,7 @@ public: std::vector filesFromCompilerRT; std::vector deadAtoms; std::unordered_set allUndefProxies; + std::unordered_set toolsVersions; const ld::dylib::File* bundleLoader; const Atom* entryPoint; const Atom* classicBindingHelper; @@ -929,7 +932,7 @@ public: uint8_t swiftVersion; uint32_t cpuSubType; uint32_t minOSVersion; - uint32_t derivedPlatformLoadCommand; + uint32_t derivedPlatform; bool objectFileFoundWithNoVersion; bool allObjectFilesScatterable; bool someObjectFileHasDwarf; diff --git a/src/ld/parsers/generic_dylib_file.hpp b/src/ld/parsers/generic_dylib_file.hpp index 529e4ab..eb9d0ea 100644 --- a/src/ld/parsers/generic_dylib_file.hpp +++ b/src/ld/parsers/generic_dylib_file.hpp @@ -133,7 +133,7 @@ public: virtual ld::File::ObjcConstraint objCConstraint() const override final { return _objcConstraint; } virtual uint8_t swiftVersion() const override final { return _swiftVersion; } virtual uint32_t minOSVersion() const override final { return _minVersionInDylib; } - virtual uint32_t platformLoadCommand() const override final { return _platformInDylib; } + virtual uint32_t platform() const override final { return _platformInDylib; } virtual ld::Bitcode* getBitcode() const override final { return _bitcode.get(); } diff --git a/src/ld/parsers/lto_file.cpp b/src/ld/parsers/lto_file.cpp index 6915ae6..586516c 100644 --- a/src/ld/parsers/lto_file.cpp +++ b/src/ld/parsers/lto_file.cpp @@ -46,9 +46,6 @@ #include "macho_relocatable_file.h" #include "lto_file.h" -// #defines are a work around for -#define __STDC_LIMIT_MACROS 1 -#define __STDC_CONSTANT_MACROS 1 #include "llvm-c/lto.h" namespace lto { @@ -109,6 +106,7 @@ public: const std::vector* stabs() const override { return NULL; } bool canScatterAtoms() const override { return true; } LinkerOptionsList* linkerOptions() const override { return NULL; } + const ToolVersionList& toolVersions() const override { return _toolVersions; } bool isThinLTO() const { return _isThinLTO; } void setIsThinLTO(bool ThinLTO) { _isThinLTO = ThinLTO; } // fixme rdar://24734472 objCConstraint() and objcHasCategoryClassProperties() @@ -148,6 +146,7 @@ private: ld::Fixup _fixupToInternal; ld::relocatable::File::DebugInfoKind _debugInfo; uint32_t _cpuSubType; + ToolVersionList _toolVersions; // unused, may some day contain version of clang the created bitcode }; // @@ -550,7 +549,7 @@ void File::addToThinGenerator(thinlto_code_gen_t generator, int id) { assert(!_module && "Expected module to be disposed"); std::string pathWithID = _path; pathWithID += std::to_string(id); - ::thinlto_codegen_add_module(generator, pathWithID.c_str(), (const char *)_content, _contentLength); + ::thinlto_codegen_add_module(generator, strdup(pathWithID.c_str()), (const char *)_content, _contentLength); } #endif @@ -1146,7 +1145,7 @@ thinlto_code_gen_t Parser::init_thinlto_codegen(const std::vector& const char* name = llvmAtom->name(); if ( deadllvmAtoms.find(name) == deadllvmAtoms.end() ) { if ( logMustPreserve ) - fprintf(stderr, "lto_codegen_add_must_preserve_symbol(%s) because linker coalesce away and replace with a mach-o atom\n", name); + fprintf(stderr, "thinlto_codegen_add_must_preserve_symbol(%s) because linker coalesce away and replace with a mach-o atom\n", name); ::thinlto_codegen_add_must_preserve_symbol(thingenerator, name, strlen(name)); deadllvmAtoms[name] = (Atom*)llvmAtom; } @@ -1167,15 +1166,15 @@ thinlto_code_gen_t Parser::init_thinlto_codegen(const std::vector& // 2 - included in nonLLVMRefs set. // If a symbol is not listed in exportList then LTO is free to optimize it away. if ( (atom->scope() == ld::Atom::scopeGlobal) && options.preserveAllGlobals ) { - if ( logMustPreserve ) fprintf(stderr, "lto_codegen_add_must_preserve_symbol(%s) because global symbol\n", name); + if ( logMustPreserve ) fprintf(stderr, "thinlto_codegen_add_must_preserve_symbol(%s) because global symbol\n", name); ::thinlto_codegen_add_must_preserve_symbol(thingenerator, name, strlen(name)); } else if ( nonLLVMRefs.find(name) != nonLLVMRefs.end() ) { - if ( logMustPreserve ) fprintf(stderr, "lto_codegen_add_must_preserve_symbol(%s) because referenced from outside of ThinLTO\n", name); + if ( logMustPreserve ) fprintf(stderr, "thinlto_codegen_add_must_preserve_symbol(%s) because referenced from outside of ThinLTO\n", name); ::thinlto_codegen_add_must_preserve_symbol(thingenerator, name, strlen(name)); } else if ( LLVMRefs.find(name) != LLVMRefs.end() ) { - if ( logMustPreserve ) fprintf(stderr, "lto_codegen_add_must_preserve_symbol(%s) because referenced from another file\n", name); + if ( logMustPreserve ) fprintf(stderr, "thinlto_codegen_add_cross_referenced_symbol(%s) because referenced from another file\n", name); ::thinlto_codegen_add_cross_referenced_symbol(thingenerator, name, strlen(name)); } else { if ( logMustPreserve ) fprintf(stderr, "NOT preserving(%s)\n", name); @@ -1264,7 +1263,7 @@ bool Parser::optimizeThinLTO(const std::vector& files, } // Add the optimized bitcode to the codegen generator now. - ::thinlto_codegen_add_module(thingenerator, tempMachoPath.c_str(), (const char *)machOFile.Buffer, machOFile.Size); + ::thinlto_codegen_add_module(thingenerator, strdup(tempMachoPath.c_str()), (const char *)machOFile.Buffer, machOFile.Size); } } @@ -1295,10 +1294,34 @@ bool Parser::optimizeThinLTO(const std::vector& files, if ( numObjects == 0 ) throwf("could not do ThinLTO codegen (thinlto_codegen_process didn't produce any object): '%s', using libLTO version '%s'", ::lto_get_error_message(), ::lto_get_version()); + auto get_thinlto_buffer_or_load_file = [&] (unsigned ID) { +#if LTO_API_VERSION >= 21 + if ( useFileBasedAPI ) { + const char* path = thinlto_module_get_object_file(thingenerator, ID); + // map in whole file + struct stat stat_buf; + int fd = ::open(path, O_RDONLY, 0); + if ( fd == -1 ) + throwf("can't open thinlto file '%s', errno=%d", path, errno); + if ( ::fstat(fd, &stat_buf) != 0 ) + throwf("fstat thinlto file '%s' failed, errno=%d\n", path, errno); + size_t len = stat_buf.st_size; + if ( len < 20 ) + throwf("ThinLTO file '%s' too small (length=%zu)", path, len); + const char* p = (const char*)::mmap(NULL, len, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0); + if ( p == (const char*)(-1) ) + throwf("can't map file, errno=%d", errno); + ::close(fd); + return LTOObjectBuffer{ p, len }; + } +#endif + return thinlto_module_get_object(thingenerator, ID); + }; + // if requested, save off objects files if ( options.saveTemps ) { for (unsigned bufID = 0; bufID < numObjects; ++bufID) { - auto machOFile = thinlto_module_get_object(thingenerator, bufID); + auto machOFile = get_thinlto_buffer_or_load_file(bufID); std::string tempMachoPath = options.outputFilePath; tempMachoPath += "."; tempMachoPath += std::to_string(bufID); @@ -1327,30 +1350,6 @@ bool Parser::optimizeThinLTO(const std::vector& files, } } - auto get_thinlto_buffer_or_load_file = [&] (unsigned ID) { -#if LTO_API_VERSION >= 21 - if ( useFileBasedAPI ) { - const char* path = thinlto_module_get_object_file(thingenerator, ID); - // map in whole file - struct stat stat_buf; - int fd = ::open(path, O_RDONLY, 0); - if ( fd == -1 ) - throwf("can't open thinlto file '%s', errno=%d", path, errno); - if ( ::fstat(fd, &stat_buf) != 0 ) - throwf("fstat thinlto file '%s' failed, errno=%d\n", path, errno); - size_t len = stat_buf.st_size; - if ( len < 20 ) - throwf("ThinLTO file '%s' too small (length=%zu)", path, len); - const char* p = (const char*)::mmap(NULL, len, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0); - if ( p == (const char*)(-1) ) - throwf("can't map file, errno=%d", errno); - ::close(fd); - return LTOObjectBuffer{ p, len }; - } -#endif - return thinlto_module_get_object(thingenerator, ID); - }; - auto ordinal = ld::File::Ordinal::LTOOrdinal().nextFileListOrdinal(); for (unsigned bufID = 0; bufID < numObjects; ++bufID) { auto machOFile = get_thinlto_buffer_or_load_file(bufID); @@ -1644,6 +1643,22 @@ const char* version() return ::lto_get_version(); } +// +// used by "ld -v" to report static version of libLTO.dylib API being compiled +// +unsigned int static_api_version() +{ + return LTO_API_VERSION; +} + +// +// used by "ld -v" to report version of libLTO.dylib being used +// +unsigned int runtime_api_version() +{ + return ::lto_api_version(); +} + // // used by ld for error reporting diff --git a/src/ld/parsers/lto_file.h b/src/ld/parsers/lto_file.h index b582a8b..a086548 100644 --- a/src/ld/parsers/lto_file.h +++ b/src/ld/parsers/lto_file.h @@ -31,6 +31,10 @@ namespace lto { extern const char* version(); +extern unsigned int runtime_api_version(); + +extern unsigned int static_api_version(); + extern bool libLTOisLoaded(); extern const char* archName(const uint8_t* fileContent, uint64_t fileLength); diff --git a/src/ld/parsers/macho_dylib_file.cpp b/src/ld/parsers/macho_dylib_file.cpp index 56b327a..b740c55 100644 --- a/src/ld/parsers/macho_dylib_file.cpp +++ b/src/ld/parsers/macho_dylib_file.cpp @@ -200,6 +200,14 @@ File::File(const uint8_t* fileContent, uint64_t fileLength, const char* path, this->_platformInDylib = cmd->cmd(); lcPlatform = Options::platformForLoadCommand(this->_platformInDylib); break; + case LC_BUILD_VERSION: + { + const macho_build_version_command

* buildVersCmd = (macho_build_version_command

*)cmd; + this->_platformInDylib = buildVersCmd->platform(); + this->_minVersionInDylib = buildVersCmd->minos(); + lcPlatform = (Options::Platform)this->_platformInDylib; + } + break; case LC_CODE_SIGNATURE: break; case macho_segment_command

::CMD: @@ -266,6 +274,7 @@ File::File(const uint8_t* fileContent, uint64_t fileLength, const char* path, if ( !this->_allowSimToMacOSXLinking ) { switch (platform) { case Options::kPlatformOSX: + case Options::kPlatform_bridgeOS: case Options::kPlatformiOS: if ( lcPlatform == Options::kPlatformUnknown ) break; @@ -305,6 +314,7 @@ File::File(const uint8_t* fileContent, uint64_t fileLength, const char* path, else { switch (platform) { case Options::kPlatformOSX: + case Options::kPlatform_bridgeOS: case Options::kPlatformiOS: if ( lcPlatform == Options::kPlatformUnknown ) break; @@ -557,7 +567,7 @@ void File::addSymbol(const char* name, bool weakDef, bool tlv, pint_t address this->_ignoreExports.insert(strdup(symName)); } else if ( strncmp(symAction, "install_name$", 13) == 0 ) { - this->_dylibInstallPath = symName; + this->_dylibInstallPath = strdup(symName); this->_installPathOverride = true; // CoreGraphics redirects to ApplicationServices, but with wrong compat version if ( strcmp(this->_dylibInstallPath, "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices") == 0 ) @@ -764,7 +774,8 @@ bool isDylibFile(const uint8_t* fileContent, cpu_type_t* result, cpu_subtype_t* } if ( Parser::validFile(fileContent, false) ) { *result = CPU_TYPE_ARM64; - *subResult = CPU_SUBTYPE_ARM64_ALL; + const auto* header = reinterpret_cast>*>(fileContent); + *subResult = header->cpusubtype(); return true; } return false; diff --git a/src/ld/parsers/macho_relocatable_file.cpp b/src/ld/parsers/macho_relocatable_file.cpp index c4ecd36..8a3e792 100644 --- a/src/ld/parsers/macho_relocatable_file.cpp +++ b/src/ld/parsers/macho_relocatable_file.cpp @@ -84,7 +84,7 @@ public: _swiftVersion(0), _cpuSubType(0), _minOSVersion(0), - _platform(0), + _platform(Options::kPlatformUnknown), _canScatterAtoms(false), _objcHasCategoryClassPropertiesField(false), _srcKind(kSourceUnknown) { } @@ -95,7 +95,7 @@ public: virtual bool justInTimeforEachAtom(const char* name, ld::File::AtomHandler&) const { return false; } virtual uint32_t minOSVersion() const { return _minOSVersion; } - virtual uint32_t platformLoadCommand() const { return _platform; } + virtual uint32_t platform() const { return _platform; } // overrides of ld::relocatable::File virtual ObjcConstraint objCConstraint() const { return _objConstraint; } @@ -107,6 +107,7 @@ public: virtual bool canScatterAtoms() const { return _canScatterAtoms; } virtual const char* translationUnitSource() const; virtual LinkerOptionsList* linkerOptions() const { return &_linkerOptions; } + virtual const ToolVersionList& toolVersions() const { return _toolVersions; } virtual uint8_t swiftVersion() const { return _swiftVersion; } virtual ld::Bitcode* getBitcode() const { return _bitcode.get(); } virtual SourceKind sourceKind() const { return _srcKind; } @@ -141,12 +142,13 @@ private: uint8_t _swiftVersion; uint32_t _cpuSubType; uint32_t _minOSVersion; - uint32_t _platform; + Options::Platform _platform; bool _canScatterAtoms; bool _objcHasCategoryClassPropertiesField; std::vector > _linkerOptions; std::unique_ptr _bitcode; SourceKind _srcKind; + ToolVersionList _toolVersions; }; @@ -2092,10 +2094,25 @@ bool Parser::parseLoadCommands(Options::Platform platform, uint32_t linkMinOS #endif if ( ignoreMismatchPlatform ) break; - _file->_platform = cmd->cmd(); lcPlatform = Options::platformForLoadCommand(cmd->cmd()); + _file->_platform = lcPlatform; _file->_minOSVersion = ((macho_version_min_command

*)cmd)->version(); break; + case LC_BUILD_VERSION: + { + const macho_build_version_command

* buildVersCmd = (macho_build_version_command

*)cmd; + if ( ignoreMismatchPlatform ) + break; + lcPlatform = (Options::Platform)buildVersCmd->platform(); + _file->_platform = lcPlatform; + _file->_minOSVersion = buildVersCmd->minos(); + const macho_build_tool_version

* entry = (macho_build_tool_version

*)((uint8_t*)cmd + sizeof(macho_build_version_command

)); + for (uint32_t t=0; t < buildVersCmd->ntools(); ++t) { + _file->_toolVersions.push_back(std::make_pair(entry->tool(), entry->version())); + ++entry; + } + } + break; case macho_segment_command

::CMD: if ( segment != NULL ) throw "more than one LC_SEGMENT found in object file"; @@ -2124,6 +2141,7 @@ bool Parser::parseLoadCommands(Options::Platform platform, uint32_t linkMinOS if ( lcPlatform == Options::kPlatformUnknown ) break; // fall through if the Platform is not Unknown + case Options::kPlatform_bridgeOS: case Options::kPlatformWatchOS: // Error when using bitcocde, warning otherwise. if (_usingBitcode) @@ -2197,6 +2215,14 @@ Options::Platform Parser::findPlatform(const macho_header

* header) return Options::kPlatformOSX; case LC_VERSION_MIN_IPHONEOS: return Options::kPlatformiOS; + case LC_VERSION_MIN_WATCHOS: + return Options::kPlatformWatchOS; + #if SUPPORT_APPLE_TV + case LC_VERSION_MIN_TVOS: + return Options::kPlatform_tvOS; + #endif + case LC_BUILD_VERSION: + return (Options::Platform)((macho_build_version_command

*)cmd)->platform(); } cmd = (const macho_load_command

*)(((char*)cmd)+cmd->cmdsize()); if ( cmd > cmdsEnd ) @@ -7897,7 +7923,7 @@ bool isObjectFile(const uint8_t* fileContent, cpu_type_t* result, cpu_subtype_t* if ( mach_o::relocatable::Parser::validFile(fileContent, false, 0) ) { const macho_header >* header = (const macho_header >*)fileContent; *result = CPU_TYPE_ARM64; - *subResult = CPU_SUBTYPE_ARM64_ALL; + *subResult = header->cpusubtype(); *platform = Parser::findPlatform(header); return true; } diff --git a/src/ld/parsers/textstub_dylib_file.cpp b/src/ld/parsers/textstub_dylib_file.cpp index 0b83d41..076736e 100644 --- a/src/ld/parsers/textstub_dylib_file.cpp +++ b/src/ld/parsers/textstub_dylib_file.cpp @@ -92,6 +92,10 @@ static Options::Platform mapPlatform(tapi::Platform platform) { return Options::kPlatformWatchOS; case tapi::Platform::tvOS: return Options::kPlatform_tvOS; + #if ((TAPI_API_VERSION_MAJOR == 1 && TAPI_API_VERSION_MINOR >= 2) || (TAPI_API_VERSION_MAJOR > 1)) + case tapi::Platform::bridgeOS: + return Options::kPlatform_bridgeOS; + #endif } return Options::kPlatformUnknown; diff --git a/src/ld/passes/code_dedup.cpp b/src/ld/passes/code_dedup.cpp index c6bc8fb..bba9b8e 100644 --- a/src/ld/passes/code_dedup.cpp +++ b/src/ld/passes/code_dedup.cpp @@ -328,6 +328,7 @@ void doPass(const Options& opts, ld::Internal& state) textAtoms.insert(pos, aliasAtom); state.atomToSection[aliasAtom] = textSection; replacementMap[dupAtom] = aliasAtom; + (const_cast(dupAtom))->setCoalescedAway(); } } } diff --git a/src/other/machochecker.cpp b/src/other/machochecker.cpp index 0b08844..eddcbc9 100644 --- a/src/other/machochecker.cpp +++ b/src/other/machochecker.cpp @@ -462,6 +462,8 @@ void MachOChecker::checkLoadCommands() case LC_DATA_IN_CODE: case LC_DYLIB_CODE_SIGN_DRS: case LC_SOURCE_VERSION: + case LC_NOTE: + case LC_BUILD_VERSION: break; case LC_RPATH: fHasLC_RPATH = true; @@ -739,7 +741,7 @@ void MachOChecker::checkLoadCommands() if ( fIndirectTableCount != 0 ) { if ( fDynamicSymbolTable->indirectsymoff() < linkEditSegment->fileoff() ) throw "indirect symbol table not in __LINKEDIT"; - if ( (fDynamicSymbolTable->indirectsymoff()+fIndirectTableCount*8) > (linkEditSegment->fileoff()+linkEditSegment->filesize()) ) + if ( (fDynamicSymbolTable->indirectsymoff()+fIndirectTableCount*4) > (linkEditSegment->fileoff()+linkEditSegment->filesize()) ) throw "indirect symbol table not in __LINKEDIT"; if ( (fDynamicSymbolTable->indirectsymoff() % sizeof(pint_t)) != 0 ) throw "indirect symbol table not pointer aligned"; @@ -1544,13 +1546,11 @@ bool MachOChecker::addressIsBindingSite(pint_t targetAddr) uint64_t segOffset = 0; uint32_t count; uint32_t skip; - uint8_t flags; const char* symbolName = NULL; int libraryOrdinal = 0; int segIndex; int64_t addend = 0; pint_t segStartAddr = 0; - pint_t addr; bool done = false; while ( !done && (p < end) ) { uint8_t immediate = *p & BIND_IMMEDIATE_MASK; diff --git a/src/other/unwinddump.cpp b/src/other/unwinddump.cpp index 5b264d1..70d4c9a 100644 --- a/src/other/unwinddump.cpp +++ b/src/other/unwinddump.cpp @@ -215,7 +215,6 @@ void UnwindPrinter::getSymbolTableInfo() const macho_load_command

* const cmds = (macho_load_command

*)((uint8_t*)fHeader + sizeof(macho_header

)); const macho_load_command

* cmd = cmds; for (uint32_t i = 0; i < cmd_count; ++i) { - uint32_t size = cmd->cmdsize(); const uint8_t* endOfCmd = ((uint8_t*)cmd)+cmd->cmdsize(); if ( endOfCmd > endOfLoadCommands ) throwf("load command #%d extends beyond the end of the load commands", i); @@ -289,7 +288,6 @@ bool UnwindPrinter::findUnwindSection() const macho_load_command

* const cmds = (macho_load_command

*)((uint8_t*)fHeader + sizeof(macho_header

)); const macho_load_command

* cmd = cmds; for (uint32_t i = 0; i < cmd_count; ++i) { - uint32_t size = cmd->cmdsize(); const uint8_t* endOfCmd = ((uint8_t*)cmd)+cmd->cmdsize(); if ( endOfCmd > endOfLoadCommands ) throwf("load command #%d extends beyond the end of the load commands", i); -- 2.45.2