]> git.saurik.com Git - apple/ld64.git/commitdiff
ld64-242.tar.gz developer-tools-63 v242
authorApple <opensource@apple.com>
Tue, 19 Aug 2014 22:19:03 +0000 (22:19 +0000)
committerApple <opensource@apple.com>
Tue, 19 Aug 2014 22:19:03 +0000 (22:19 +0000)
16 files changed:
ld64.xcodeproj/project.pbxproj
src/abstraction/MachOFileAbstraction.hpp
src/create_configure
src/ld/InputFiles.cpp
src/ld/Options.cpp
src/ld/Options.h
src/ld/Resolver.cpp
src/ld/ld.hpp
src/ld/parsers/libunwind/DwarfInstructions.hpp
src/ld/parsers/lto_file.cpp
src/ld/parsers/lto_file.h
src/ld/parsers/macho_relocatable_file.cpp
src/ld/parsers/macho_relocatable_file.h
src/ld/passes/compact_unwind.cpp
src/other/ObjectDump.cpp
src/other/unwinddump.cpp

index 854356efcb5c3cf9fc8cd45ed1a19ce6a7563c73..b4d1749023a5b6e6b79f26849d3bd6228fc1c808 100644 (file)
@@ -3,7 +3,7 @@
        archiveVersion = 1;
        classes = {
        };
-       objectVersion = 42;
+       objectVersion = 46;
        objects = {
 
 /* Begin PBXAggregateTarget section */
                F9023C3006D5A227001BBF46 /* Project object */ = {
                        isa = PBXProject;
                        attributes = {
+                               LastUpgradeCheck = 0600;
                                ORGANIZATIONNAME = "Apple Inc.";
                        };
                        buildConfigurationList = F933D92309291AC90083EAC8 /* Build configuration list for PBXProject "ld64" */;
-                       compatibilityVersion = "Xcode 2.4";
+                       compatibilityVersion = "Xcode 3.2";
                        developmentRegion = English;
                        hasScannedForEncodings = 0;
                        knownRegions = (
                F933D92409291AC90083EAC8 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               ARCHS = "$(ARCHS_STANDARD_64_BIT_PRE_XCODE_3_1)";
-                               ARCHS_STANDARD_64_BIT_PRE_XCODE_3_1 = x86_64;
                                GCC_DYNAMIC_NO_PIC = NO;
                                GCC_TREAT_WARNINGS_AS_ERRORS = NO;
+                               ONLY_ACTIVE_ARCH = YES;
                        };
                        name = Debug;
                };
                F933D92509291AC90083EAC8 /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               ARCHS = "$(ARCHS_STANDARD_64_BIT_PRE_XCODE_3_1)";
-                               ARCHS_STANDARD_64_BIT_PRE_XCODE_3_1 = x86_64;
                                GCC_DYNAMIC_NO_PIC = NO;
                                GCC_TREAT_WARNINGS_AS_ERRORS = NO;
                        };
                F9849FF810B5DE8E009E9878 /* Release-assert */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               ARCHS = "$(ARCHS_STANDARD_64_BIT_PRE_XCODE_3_1)";
-                               ARCHS_STANDARD_64_BIT_PRE_XCODE_3_1 = x86_64;
                                GCC_DYNAMIC_NO_PIC = NO;
                                GCC_TREAT_WARNINGS_AS_ERRORS = NO;
                        };
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
+                               COMBINE_HIDPI_IMAGES = YES;
                                COPY_PHASE_STRIP = NO;
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                GCC_ENABLE_FIX_AND_CONTINUE = NO;
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
+                               COMBINE_HIDPI_IMAGES = YES;
                                COPY_PHASE_STRIP = NO;
                                GCC_DYNAMIC_NO_PIC = NO;
                                GCC_MODEL_TUNING = G5;
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
+                               COMBINE_HIDPI_IMAGES = YES;
                                COPY_PHASE_STRIP = NO;
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                GCC_ENABLE_FIX_AND_CONTINUE = NO;
index 8b58efd2357e3d6b7f83012634bf8914fcb3dec7..ae61d7c1893bfe102c1a6db52571f6d33d5cc97c 100644 (file)
 
 
 // hack until arm64 headers are worked out
-#define CPU_TYPE_ARM64                 (CPU_TYPE_ARM | CPU_ARCH_ABI64)
-#define CPU_SUBTYPE_ARM64_ALL  0
-#define CPU_SUBTYPE_ARM64_V8    1
+#ifndef CPU_TYPE_ARM64
+       #define CPU_TYPE_ARM64                  (CPU_TYPE_ARM | CPU_ARCH_ABI64)
+#endif
+#ifndef CPU_SUBTYPE_ARM64_ALL
+       #define CPU_SUBTYPE_ARM64_ALL   0
+#endif
+#ifndef CPU_SUBTYPE_ARM64_V8
+       #define CPU_SUBTYPE_ARM64_V8    1
+#endif
+
 
 #define ARM64_RELOC_UNSIGNED            0 // for pointers
 #define ARM64_RELOC_SUBTRACTOR          1 // must be followed by a ARM64_RELOC_UNSIGNED
 
 #define UNWIND_ARM64_DWARF_SECTION_OFFSET               0x00FFFFFF
 
+#define UNW_ARM_D31 287
+
 
 #ifndef LC_SOURCE_VERSION
        #define LC_SOURCE_VERSION 0x2A
        #define CPU_SUBTYPE_X86_64_H    ((cpu_subtype_t) 8) 
 #endif 
 
+#define UNWIND_ARM_MODE_MASK                          0x0F000000
+#define UNWIND_ARM_MODE_FRAME                         0x01000000
+#define UNWIND_ARM_MODE_FRAME_D                       0x02000000
+#define UNWIND_ARM_MODE_DWARF                         0x04000000
+#define  UNWIND_ARM_FRAME_STACK_ADJUST_MASK           0x00C00000
+
+#define UNWIND_ARM_FRAME_FIRST_PUSH_R4                0x00000001
+#define UNWIND_ARM_FRAME_FIRST_PUSH_R5                0x00000002
+#define UNWIND_ARM_FRAME_FIRST_PUSH_R6                0x00000004
+  
+#define UNWIND_ARM_FRAME_SECOND_PUSH_R8               0x00000008
+#define UNWIND_ARM_FRAME_SECOND_PUSH_R9               0x00000010
+#define UNWIND_ARM_FRAME_SECOND_PUSH_R10              0x00000020
+#define UNWIND_ARM_FRAME_SECOND_PUSH_R11              0x00000040
+#define UNWIND_ARM_FRAME_SECOND_PUSH_R12              0x00000080
+#define UNWIND_ARM_FRAME_D_REG_COUNT_MASK             0x00000F00
+#define UNWIND_ARM_DWARF_SECTION_OFFSET               0x00FFFFFF
 
 struct ArchInfo {
        const char*                     archName;
@@ -508,10 +537,10 @@ static const ArchInfo archInfoArray[] = {
        #define SUPPORT_ARCH_arm_any 1
 #endif
 #if SUPPORT_ARCH_arm64
-       { "arm64", CPU_TYPE_ARM64,   CPU_SUBTYPE_ARM64_ALL,  "arm64-",    "",   false,  false },
+       { "arm64", CPU_TYPE_ARM64,   CPU_SUBTYPE_ARM64_ALL,  "arm64-",  "aarch64-",  false,  false },
 #endif
 #if SUPPORT_ARCH_arm64v8
-       { "arm64v8", CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_V8,   "arm64v8-",  "",   true,  false },
+       { "arm64v8", CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_V8,   "arm64v8-",  "aarch64-",   true,  false },
 #endif
        { NULL, 0, 0, NULL, NULL, false, false }
 };
index 8ca92bee0f6335ff5f5b5a87e1db0660a01943e1..f99123191cd04dd3576012832ab2d892b2240f0c 100755 (executable)
@@ -11,7 +11,7 @@ else
 fi
 
 if [ -z "${RC_SUPPORTED_ARCHS}" ]; then
-       RC_SUPPORTED_ARCHS="i386 x86_64 x86_64h armv6 armv7 armv7s armv7m arm64"
+       RC_SUPPORTED_ARCHS="i386 x86_64 x86_64h armv6 armv7 armv7s armv7m armv7k arm64"
 fi
 
 for ANARCH in ${RC_SUPPORTED_ARCHS}
index 595b5d19cdc7d53fa500324914584c39536e6a64..30c0875de7af9e3311a2212a310e8b1c38f4c60c 100644 (file)
@@ -293,6 +293,7 @@ ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib
        objOpts.forceDwarfConversion= (_options.outputKind() == Options::kDyld);
        objOpts.neverConvertDwarf   = !_options.needsUnwindInfoSection();
        objOpts.verboseOptimizationHints = _options.verboseOptimizationHints();
+       objOpts.armUsesZeroCostExceptions = _options.armUsesZeroCostExceptions();
        objOpts.subType                         = _options.subArchitecture();
        ld::relocatable::File* objResult = mach_o::relocatable::parse(p, len, info.path, info.modTime, info.ordinal, objOpts);
        if ( objResult != NULL ) {
@@ -586,7 +587,6 @@ void InputFiles::addLinkerOptionLibraries(ld::Internal& state, ld::File::AtomHan
                                ld::dylib::File* dylibReader = dynamic_cast<ld::dylib::File*>(reader);
                                if ( dylibReader != NULL ) {
                                        if ( ! dylibReader->installPathVersionSpecific() ) {
-                                               dylibReader->forEachAtom(handler);
                                                dylibReader->setImplicitlyLinked();
                                                this->addDylib(dylibReader, info);
                                        }
@@ -613,7 +613,6 @@ void InputFiles::addLinkerOptionLibraries(ld::Internal& state, ld::File::AtomHan
                                ld::dylib::File* dylibReader = dynamic_cast<ld::dylib::File*>(reader);
                                ld::archive::File* archiveReader = dynamic_cast<ld::archive::File*>(reader);
                                if ( dylibReader != NULL ) {
-                                       dylibReader->forEachAtom(handler);
                                        dylibReader->setImplicitlyLinked();
                                        this->addDylib(dylibReader, info);
                                }
index aa4f6ee85205f7c62c05704ae1916ca3e98805fb..228a0df8678cb584d331ec94d7b9d346e8144431 100644 (file)
@@ -601,6 +601,11 @@ void Options::setArchitecture(cpu_type_t type, cpu_subtype_t subtype)
        fArchitectureName = "unknown architecture";
 }
 
+bool Options::armUsesZeroCostExceptions() const
+{
+       return ( (fArchitecture == CPU_TYPE_ARM) && (fSubArchitecture == CPU_SUBTYPE_ARM_V7K) );
+}
+
 void Options::parseArch(const char* arch)
 {
        if ( arch == NULL )
@@ -3889,8 +3894,26 @@ void Options::reconfigureDefaults()
                        }
                        break;
                case CPU_TYPE_ARM:
-                       fAddCompactUnwindEncoding = false;
-                       fRemoveDwarfUnwindIfCompactExists = false;
+                       if ( armUsesZeroCostExceptions() )  {
+                               switch ( fOutputKind ) {
+                                       case Options::kObjectFile:
+                                       case Options::kStaticExecutable:
+                                       case Options::kPreload:
+                                       case Options::kKextBundle:
+                                               fAddCompactUnwindEncoding = false;
+                                               break;
+                                       case Options::kDyld:
+                                       case Options::kDynamicLibrary:
+                                       case Options::kDynamicBundle:
+                                       case Options::kDynamicExecutable:
+                                               fAddCompactUnwindEncoding = true;
+                                               break;
+                               }
+                       }
+                       else {
+                               fAddCompactUnwindEncoding = false;
+                               fRemoveDwarfUnwindIfCompactExists = false;
+                       }
                        break;
                case 0:
                        // if -arch is missing, assume we don't want compact unwind info
@@ -4270,25 +4293,32 @@ void Options::reconfigureDefaults()
        // <rdar://problem/12258065> ARM64 needs 16KB page size for user land code
        // <rdar://problem/15974532> make armv7[s] use 16KB pages in user land code for iOS 8 or later
        if ( fSegmentAlignment == 4096 ) {
-               if ( (fArchitecture == CPU_TYPE_ARM64) 
-               || ((fArchitecture == CPU_TYPE_ARM) && (fIOSVersionMin >= ld::iOS_8_0) && 
-                       ((fSubArchitecture == CPU_SUBTYPE_ARM_V7S) || (fSubArchitecture == CPU_SUBTYPE_ARM_V7))) ) {
-                       switch ( fOutputKind ) {
-                               case Options::kDynamicExecutable:
-                               case Options::kDynamicLibrary:
-                               case Options::kDynamicBundle:
-                               case Options::kDyld:
+               switch ( fOutputKind ) {
+                       case Options::kDynamicExecutable:
+                       case Options::kDynamicLibrary:
+                       case Options::kDynamicBundle:
+                       case Options::kDyld:
+                               if ( (fArchitecture == CPU_TYPE_ARM64) 
+                               || ((fArchitecture == CPU_TYPE_ARM) && (fIOSVersionMin >= ld::iOS_8_0) && 
+                                       ((fSubArchitecture == CPU_SUBTYPE_ARM_V7S) || (fSubArchitecture == CPU_SUBTYPE_ARM_V7))) ) {
                                        fSegmentAlignment = 4096*4;
-                                       break;
-                               case Options::kStaticExecutable:
-                               case Options::kKextBundle:
-                               case Options::kObjectFile:
-                               case Options::kPreload:
-                                       break;
-                       }
+                               }
+                               break;
+                       case Options::kStaticExecutable:
+                       case Options::kKextBundle:
+                               // <rdar://problem/14676611> 16KB segments for arm64 kexts
+                               if ( (fArchitecture == CPU_TYPE_ARM64) && (fIOSVersionMin >= ld::iOS_9_0) ) {
+                                       fSegmentAlignment = 4096*4;
+                               }
+                               break;
+                       case Options::kObjectFile:
+                       case Options::kPreload:
+                               break;
                }
        }
 
+
+
        // <rdar://problem/13624134> linker should not convert dwarf unwind if .o file has compact unwind section
        switch ( fOutputKind ) {
                case Options::kDynamicExecutable:
@@ -4316,6 +4346,13 @@ void Options::reconfigureDefaults()
                        break;
        }
        
+       // Make sure -image_base matches alignment
+       uint64_t alignedBaseAddress = (fBaseAddress+fSegmentAlignment-1) & (-fSegmentAlignment);
+       if ( alignedBaseAddress != fBaseAddress ) {
+               warning("base address 0x%llX is not properly aligned. Changing it to 0x%llX", fBaseAddress, alignedBaseAddress);
+               fBaseAddress = alignedBaseAddress;
+       }
+
 }
 
 void Options::checkIllegalOptionCombinations()
index 8395fc90057d27fc9304da64cd73173181822af4..39ee6fe8db34f384d996c12dbcdceba00224bd0e 100644 (file)
@@ -390,6 +390,7 @@ public:
                                                                linkerOptions() const { return fLinkerOptions; }
        FileInfo                                        findFramework(const char* frameworkName) const;
        FileInfo                                        findLibrary(const char* rootName, bool dylibsOnly=false) const;
+       bool                                            armUsesZeroCostExceptions() const;
        const std::vector<SectionRename>& sectionRenames() const { return fSectionRenames; }
        const std::vector<SegmentRename>& segmentRenames() const { return fSegmentRenames; }
        bool                                            moveRoSymbol(const char* symName, const char* filePath, const char*& seg, bool& wildCardMatch) const;
index a5405a9951057673fb0cdf1cd9c5a629acebdec2..8a72b67dcd20ff1c1f16f674d99a01f50551e858 100644 (file)
@@ -330,17 +330,14 @@ void Resolver::doLinkerOption(const std::vector<const char*>& linkerOption, cons
        }
 }
 
-static void userReadableSwiftVersion(uint8_t value, char versionString[64])
+static void userReadableSwiftVersion(uint8_t value, char versionString[32])
 {
        switch (value) {
                case 1:
                        strcpy(versionString, "1.0");
                        break;
-               case 2:
-                       strcpy(versionString, "1.1");
-                       break;
                default:
-                       sprintf(versionString, "unknown ABI version 0x%02X", value);
+                       sprintf(versionString, "0x%02X", value);
        }
 }
 
@@ -403,8 +400,8 @@ void Resolver::doFile(const ld::File& file)
                                _internal.swiftVersion = file.swiftVersion();
                        }
                        else if ( file.swiftVersion() != _internal.swiftVersion ) {
-                               char fileVersion[64];
-                               char otherVersion[64];
+                               char fileVersion[32];
+                               char otherVersion[32];
                                userReadableSwiftVersion(file.swiftVersion(), fileVersion);
                                userReadableSwiftVersion(_internal.swiftVersion, otherVersion);
                                if ( file.swiftVersion() > _internal.swiftVersion ) {
@@ -513,7 +510,7 @@ void Resolver::doFile(const ld::File& file)
                        if ( (_options.iOSVersionMin() != iOSVersionUnset) && (_options.iOSVersionMin() < iOS_8_0) ) {
                                // <rdar://problem/17598404> only warn about linking against embedded dylib if it is built for iOS 8 or later
                                if ( dylibFile->iOSMinVersion() >= iOS_8_0 )
-                                       throwf("embedded dylibs/frameworks are only supported on iOS 8.0 and later (%s)", depInstallName);
+                                       warning("embedded dylibs/frameworks are only supported on iOS 8.0 and later (%s)", depInstallName);
                        }
                }
                if ( _options.sharedRegionEligible() ) {
@@ -1550,6 +1547,7 @@ void Resolver::linkTimeOptimize()
        optOpt.needsUnwindInfoSection           = _options.needsUnwindInfoSection();
        optOpt.keepDwarfUnwind                          = _options.keepDwarfUnwind();
        optOpt.verboseOptimizationHints     = _options.verboseOptimizationHints();
+       optOpt.armUsesZeroCostExceptions    = _options.armUsesZeroCostExceptions();
        optOpt.arch                                                     = _options.architecture();
        optOpt.mcpu                                                     = _options.mcpuLTO();
        optOpt.llvmOptions                                      = &_options.llvmOptions();
index 8c3de4f19b0b6b5bd0bdebdcb56d70f76966bcd1..889cf2cd3bc080db7c0b71e12fef985e33211835 100644 (file)
@@ -168,7 +168,7 @@ enum MacVersionMin { macVersionUnset=0, mac10_4=0x000A0400, mac10_5=0x000A0500,
 enum IOSVersionMin { iOSVersionUnset=0, iOS_2_0=0x00020000, iOS_3_1=0x00030100, 
                                                iOS_4_2=0x00040200, iOS_4_3=0x00040300, iOS_5_0=0x00050000,
                                                iOS_6_0=0x00060000, iOS_7_0=0x00070000, iOS_8_0=0x00080000,
-                                               iOS_Future=0x10000000};
+                                               iOS_9_0=0x00090000, iOS_Future=0x10000000};
  
 namespace relocatable {
        //
index 18355404b5ffeddf6147da587dc8ba19c87e06c2..c14c38f871b596a00d12bb76491bd3ae1b6aba29 100644 (file)
@@ -167,6 +167,14 @@ private:
                                                                                                const Registers_arm64&, const typename CFI_Parser<A>::PrologInfo& prolog,
                                                                                                char warningBuffer[1024]);
        
+  // arm specific variants
+       static bool   isReturnAddressRegister(int regNum, const Registers_arm&);
+       static pint_t getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, const Registers_arm&);
+       static compact_unwind_encoding_t encodeToUseDwarf(const Registers_arm&);
+       static compact_unwind_encoding_t createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr,
+                                                                                               const Registers_arm&, const typename CFI_Parser<A>::PrologInfo& prolog,
+                                                                                               char warningBuffer[1024]);
+       
 };
 
 
@@ -1962,6 +1970,29 @@ compact_unwind_encoding_t DwarfInstructions<A,R>::createCompactEncodingFromProlo
 }
 
 
+
+
+//
+//     arm specific functions
+//
+
+template <typename A, typename R>
+compact_unwind_encoding_t DwarfInstructions<A,R>::encodeToUseDwarf(const Registers_arm&) 
+{
+       return UNWIND_ARM_MODE_DWARF;
+}
+
+
+template <typename A, typename R>
+compact_unwind_encoding_t DwarfInstructions<A,R>::createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr,
+                                                                                               const Registers_arm& r, const typename CFI_Parser<A>::PrologInfo& prolog,
+                                                                                               char warningBuffer[1024])
+{
+       warningBuffer[0] = '\0';
+       return UNWIND_ARM_MODE_DWARF;
+}
+
+
 } // namespace libunwind
 
 
index f2cb8ca364980c1c0c654bd64f71f69930b0f685..fbba2375185fa8ca655addd995867954e61eb8c2 100644 (file)
@@ -302,6 +302,7 @@ ld::relocatable::File* Parser::parseMachOFile(const uint8_t* p, size_t len, cons
        objOpts.forceDwarfConversion = false;
        objOpts.neverConvertDwarf   = false;
        objOpts.verboseOptimizationHints = options.verboseOptimizationHints;
+       objOpts.armUsesZeroCostExceptions = options.armUsesZeroCostExceptions;
 
        objOpts.subType                         = 0;
        
@@ -485,8 +486,6 @@ void Parser::ltoDiagnosticHandler(lto_codegen_diagnostic_severity_t severity, co
        switch ( severity ) {
 #if LTO_API_VERSION >= 10
                case LTO_DS_REMARK:
-                       fprintf(stderr, "ld: LTO remark: %s\n", message);
-                       break;
 #endif
                case LTO_DS_NOTE:
                case LTO_DS_WARNING:
index 332215d5d706b852e41a9a29bfdb3581e8e9215c..dcd6e36abbe7929ba8ca21000b6c7e4e7ad03c4b 100644 (file)
@@ -57,6 +57,7 @@ struct OptimizeOptions {
        bool                                                            needsUnwindInfoSection; 
        bool                                                            keepDwarfUnwind; 
        bool                                                            verboseOptimizationHints;
+       bool                                                            armUsesZeroCostExceptions;
        cpu_type_t                                                      arch;
        const char*                                                     mcpu;
        const std::vector<const char*>*         llvmOptions;
index d3990e371b816eeff5787253d714244198f0470d..49d333e97d05315d482c01557830506b0ae9ce0d 100644 (file)
@@ -435,6 +435,7 @@ protected:
        virtual unsigned long                   contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const;
        virtual bool                                    canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs, 
                                                                                                        const ld::IndirectBindingTable& ind) const;
+       virtual bool                                    ignoreLabel(const char* label) const;
 };
 
 template <typename A>
@@ -454,6 +455,7 @@ protected:
        virtual unsigned long                   contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const;
        virtual bool                                    canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs, 
                                                                                                        const ld::IndirectBindingTable& ind) const;
+       virtual bool                                    ignoreLabel(const char* label) const;
 };
 
 template <typename A>
@@ -473,6 +475,7 @@ protected:
        virtual unsigned long                   contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const;
        virtual bool                                    canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs, 
                                                                                                        const ld::IndirectBindingTable& ind) const;
+       virtual bool                                    ignoreLabel(const char* label) const;
 };
 
 
@@ -1054,6 +1057,7 @@ public:
        bool                                                                                    forceDwarfConversion() { return _forceDwarfConversion; }
        bool                                                                                    verboseOptimizationHints() { return _verboseOptimizationHints; }
        bool                                                                                    neverConvertDwarf() { return _neverConvertDwarf; }
+       bool                                                                                    armUsesZeroCostExceptions() { return _armUsesZeroCostExceptions; }
 
        macho_data_in_code_entry<P>*                                    dataInCodeStart() { return _dataInCodeStart; }
        macho_data_in_code_entry<P>*                                    dataInCodeEnd()   { return _dataInCodeEnd; }
@@ -1204,6 +1208,7 @@ private:
        bool                                                                            _forceDwarfConversion;
        bool                                                                            _neverConvertDwarf;
        bool                                                                            _verboseOptimizationHints;
+       bool                                                                            _armUsesZeroCostExceptions;
        unsigned int                                                            _stubsSectionNum;
        const macho_section<P>*                                         _stubsMachOSection;
        std::vector<const char*>                                        _dtraceProviderInfo;
@@ -1632,6 +1637,8 @@ ld::relocatable::File* Parser<A>::parse(const ParserOptions& opts)
        // respond to -t option
        if ( opts.logAllFiles )
                printf("%s\n", _path);
+               
+       _armUsesZeroCostExceptions = opts.armUsesZeroCostExceptions;
 
        // parse start of mach-o file
        if ( ! parseLoadCommands() )
@@ -4069,6 +4076,12 @@ uint32_t Section<A>::sectionNum(class Parser<A>& parser) const
 template <> 
 uint32_t CFISection<arm>::cfiCount(Parser<arm>& parser) 
 {
+       if ( parser.armUsesZeroCostExceptions() ) {
+               // create ObjectAddressSpace object for use by libunwind
+               OAS oas(*this, (uint8_t*)this->file().fileContent()+this->_machOSection->offset());
+               return libunwind::CFI_Parser<OAS>::getCFICount(oas, 
+                                                                                       this->_machOSection->addr(), this->_machOSection->size());
+       }
        return 0; 
 }
 
@@ -4203,8 +4216,22 @@ void CFISection<arm>::cfiParse(class Parser<arm>& parser, uint8_t* buffer,
                                                                        libunwind::CFI_Atom_Info<CFISection<arm>::OAS>::CFI_Atom_Info cfiArray[], 
                                                                        uint32_t& count, const pint_t cuStarts[], uint32_t cuCount)
 {
-       // arm does not use zero cost exceptions
-       assert(count == 0);
+       if ( !parser.armUsesZeroCostExceptions() ) {
+               // most arm do not use zero cost exceptions
+               assert(count == 0);
+               return;
+       }
+       // create ObjectAddressSpace object for use by libunwind
+       OAS oas(*this, (uint8_t*)this->file().fileContent()+this->_machOSection->offset());
+       
+       // use libuwind to parse __eh_frame data into array of CFI_Atom_Info
+       const char* msg;
+       msg = libunwind::DwarfInstructions<OAS, libunwind::Registers_arm>::parseCFIs(
+                                                       oas, this->_machOSection->addr(), this->_machOSection->size(), 
+                                                       cuStarts, cuCount, parser.keepDwarfUnwind(), parser.forceDwarfConversion(), parser.neverConvertDwarf(),
+                                                       cfiArray, count, (void*)&parser, warnFunc);
+       if ( msg != NULL ) 
+               throwf("malformed __eh_frame section: %s", msg);
 }
 
 
@@ -4385,6 +4412,29 @@ void CFISection<arm64>::addCiePersonalityFixups(class Parser<arm64>& parser, con
 }
 #endif
 
+template <>
+void CFISection<arm>::addCiePersonalityFixups(class Parser<arm>& parser, const CFI_Atom_Info* cieInfo)
+{
+       uint8_t personalityEncoding = cieInfo->u.cieInfo.personality.encodingOfTargetAddress;
+       if ( (personalityEncoding == 0x9B) || (personalityEncoding == 0x90) ) {
+               uint32_t offsetInCFI = cieInfo->u.cieInfo.personality.offsetInCFI;
+               uint32_t nlpAddr = cieInfo->u.cieInfo.personality.targetAddress;
+               Atom<arm>* cieAtom = this->findAtomByAddress(cieInfo->address);
+               Atom<arm>* nlpAtom = parser.findAtomByAddress(nlpAddr);
+               assert(nlpAtom->contentType() == ld::Atom::typeNonLazyPointer);
+               Parser<arm>::SourceLocation src(cieAtom, cieInfo->u.cieInfo.personality.offsetInCFI);
+
+               parser.addFixup(src, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, ld::Fixup::bindingByContentBound, nlpAtom);
+               parser.addFixup(src, ld::Fixup::k2of4, ld::Fixup::kindSubtractTargetAddress, cieAtom);
+               parser.addFixup(src, ld::Fixup::k3of4, ld::Fixup::kindSubtractAddend, offsetInCFI);
+               parser.addFixup(src, ld::Fixup::k4of4, ld::Fixup::kindStoreLittleEndian32);
+       }
+       else if ( personalityEncoding != 0 ) {
+               throwf("unsupported address encoding (%02X) of personality function in CIE", personalityEncoding);
+       }
+}
+
+
 
 template <typename A>
 void CFISection<A>::addCiePersonalityFixups(class Parser<A>& parser, const CFI_Atom_Info* cieInfo)
@@ -4686,6 +4736,35 @@ const char* CUSection<arm64>::personalityName(class Parser<arm64>& parser, const
 }
 #endif
 
+#if SUPPORT_ARCH_arm_any
+template <>
+const char* CUSection<arm>::personalityName(class Parser<arm>& parser, const macho_relocation_info<arm::P>* reloc)
+{
+       if ( reloc->r_extern() ) {
+               assert((reloc->r_type() == ARM_RELOC_VANILLA) && "wrong reloc type on personality column in __compact_unwind section");
+               const macho_nlist<P>& sym = parser.symbolFromIndex(reloc->r_symbolnum());
+               return parser.nameFromSymbol(sym);
+       }
+       else {
+               // support __LD, __compact_unwind personality entries which are pointer to personality non-lazy pointer
+               const pint_t* content = (pint_t*)(this->file().fileContent() + this->_machOSection->offset() + reloc->r_address());
+               pint_t nlPointerAddr = *content;
+               Section<arm>* nlSection = parser.sectionForAddress(nlPointerAddr);
+               if ( nlSection->type() == ld::Section::typeCode ) {
+                       // personality function is defined in this .o file, so this is a direct reference to it
+                       // atoms may not be constructed yet, so scan symbol table for labels
+                       const char* name = parser.scanSymbolTableForAddress(nlPointerAddr);
+                       return name;
+               }
+               else {
+                       uint32_t symIndex = parser.symbolIndexFromIndirectSectionAddress(nlPointerAddr, nlSection->machoSection());
+                       const macho_nlist<P>& nlSymbol = parser.symbolFromIndex(symIndex);
+                       return parser.nameFromSymbol(nlSymbol);
+               }
+       }
+}
+#endif
+
 
 template <typename A>
 const char* CUSection<A>::personalityName(class Parser<A>& parser, const macho_relocation_info<P>* reloc)
@@ -4709,7 +4788,7 @@ bool CUSection<x86_64>::encodingMeansUseDwarf(compact_unwind_encoding_t enc)
 template <>
 bool CUSection<arm>::encodingMeansUseDwarf(compact_unwind_encoding_t enc)
 {
-       return false;
+       return ((enc & UNWIND_ARM_MODE_MASK) == UNWIND_ARM_MODE_DWARF);
 }
 #endif
 
@@ -5069,6 +5148,11 @@ uint32_t ImplicitSizeSection<A>::appendAtoms(class Parser<A>& parser, uint8_t* p
        return count;
 }
 
+template <typename A>
+bool Literal4Section<A>::ignoreLabel(const char* label) const
+{
+       return (label[0] == 'L') || (label[0] == 'l');
+}
 
 template <typename A>
 unsigned long Literal4Section<A>::contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
@@ -5094,6 +5178,12 @@ bool Literal4Section<A>::canCoalesceWith(const class Atom<A>* atom, const ld::At
 }
 
 
+template <typename A>
+bool Literal8Section<A>::ignoreLabel(const char* label) const
+{
+       return (label[0] == 'L') || (label[0] == 'l');
+}
+
 template <typename A>
 unsigned long Literal8Section<A>::contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
 {
@@ -5128,6 +5218,11 @@ bool Literal8Section<A>::canCoalesceWith(const class Atom<A>* atom, const ld::At
        return false;
 }
 
+template <typename A>
+bool Literal16Section<A>::ignoreLabel(const char* label) const
+{
+       return (label[0] == 'L') || (label[0] == 'l');
+}
 
 template <typename A>
 unsigned long Literal16Section<A>::contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
@@ -5373,7 +5468,6 @@ ld::Atom::Scope NonLazyPointerSection<A>::scopeAtAddress(Parser<A>& parser, pint
                return ld::Atom::scopeLinkageUnit; 
 }
 
-
 template <typename A>
 const uint8_t* CFStringSection<A>::targetContent(const class Atom<A>* atom, const ld::IndirectBindingTable& ind,
                                                                                                        ContentType* ct, unsigned int* count)
index 6d20847fcd02d2b244bd23f56376ef3539749b14..92e904269b5033dfbbc1897a3497de9bf8a1e77d 100644 (file)
@@ -40,6 +40,7 @@ struct ParserOptions {
        bool                    forceDwarfConversion;
        bool                    neverConvertDwarf;
        bool                    verboseOptimizationHints;
+       bool                    armUsesZeroCostExceptions;
        uint32_t                subType;
 };
 
index 3ddd9b8b9e520641fcff14d5130dd893ee69d319..6c1308d27c1e735974d8664c0e630e21abccd711 100644 (file)
@@ -304,6 +304,13 @@ bool UnwindInfoAtom<arm64>::encodingMeansUseDwarf(compact_unwind_encoding_t enc)
        return ((enc & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_DWARF);
 }
 
+template <>
+bool UnwindInfoAtom<arm>::encodingMeansUseDwarf(compact_unwind_encoding_t enc)
+{
+       return ((enc & UNWIND_ARM_MODE_MASK) == UNWIND_ARM_MODE_DWARF);
+}
+
+
 template <typename A>
 void UnwindInfoAtom<A>::compressDuplicates(const std::vector<UnwindEntry>& entries, std::vector<UnwindEntry>& uniqueEntries)
 {
@@ -418,6 +425,22 @@ void UnwindInfoAtom<arm64>::addCompressedAddressOffsetFixup(uint32_t offset, con
        _fixups.push_back(ld::Fixup(offset, ld::Fixup::k3of3, ld::Fixup::kindStoreLittleEndianLow24of32));
 }
 
+template <>
+void UnwindInfoAtom<arm>::addCompressedAddressOffsetFixup(uint32_t offset, const ld::Atom* func, const ld::Atom* fromFunc)
+{
+       if ( fromFunc->isThumb() ) {
+               _fixups.push_back(ld::Fixup(offset, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, func));
+               _fixups.push_back(ld::Fixup(offset, ld::Fixup::k2of4, ld::Fixup::kindSubtractTargetAddress, fromFunc));
+               _fixups.push_back(ld::Fixup(offset, ld::Fixup::k3of4, ld::Fixup::kindSubtractAddend, 1));
+               _fixups.push_back(ld::Fixup(offset, ld::Fixup::k4of4, ld::Fixup::kindStoreLittleEndianLow24of32));
+       }
+       else {
+               _fixups.push_back(ld::Fixup(offset, ld::Fixup::k1of3, ld::Fixup::kindSetTargetAddress, func));
+               _fixups.push_back(ld::Fixup(offset, ld::Fixup::k2of3, ld::Fixup::kindSubtractTargetAddress, fromFunc));
+               _fixups.push_back(ld::Fixup(offset, ld::Fixup::k3of3, ld::Fixup::kindStoreLittleEndianLow24of32));
+       }
+}
+
 template <>
 void UnwindInfoAtom<x86>::addCompressedEncodingFixup(uint32_t offset, const ld::Atom* fde)
 {
@@ -439,6 +462,13 @@ void UnwindInfoAtom<arm64>::addCompressedEncodingFixup(uint32_t offset, const ld
        _fixups.push_back(ld::Fixup(offset, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndianLow24of32));
 }
 
+template <>
+void UnwindInfoAtom<arm>::addCompressedEncodingFixup(uint32_t offset, const ld::Atom* fde)
+{
+       _fixups.push_back(ld::Fixup(offset, ld::Fixup::k1of2, ld::Fixup::kindSetTargetSectionOffset, fde));
+       _fixups.push_back(ld::Fixup(offset, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndianLow24of32));
+}
+
 template <>
 void UnwindInfoAtom<x86>::addRegularAddressFixup(uint32_t offset, const ld::Atom* func)
 {
@@ -460,6 +490,13 @@ void UnwindInfoAtom<arm64>::addRegularAddressFixup(uint32_t offset, const ld::At
        _fixups.push_back(ld::Fixup(offset, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndian32));
 }
 
+template <>
+void UnwindInfoAtom<arm>::addRegularAddressFixup(uint32_t offset, const ld::Atom* func)
+{
+       _fixups.push_back(ld::Fixup(offset, ld::Fixup::k1of2, ld::Fixup::kindSetTargetImageOffset, func));
+       _fixups.push_back(ld::Fixup(offset, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndian32));
+}
+
 template <>
 void UnwindInfoAtom<x86>::addRegularFDEOffsetFixup(uint32_t offset, const ld::Atom* fde)
 {
@@ -481,6 +518,13 @@ void UnwindInfoAtom<arm64>::addRegularFDEOffsetFixup(uint32_t offset, const ld::
        _fixups.push_back(ld::Fixup(offset+4, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndianLow24of32));
 }
 
+template <>
+void UnwindInfoAtom<arm>::addRegularFDEOffsetFixup(uint32_t offset, const ld::Atom* fde)
+{
+       _fixups.push_back(ld::Fixup(offset+4, ld::Fixup::k1of2, ld::Fixup::kindSetTargetSectionOffset, fde));
+       _fixups.push_back(ld::Fixup(offset+4, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndianLow24of32));
+}
+
 template <>
 void UnwindInfoAtom<x86>::addImageOffsetFixup(uint32_t offset, const ld::Atom* targ)
 {
@@ -502,6 +546,13 @@ void UnwindInfoAtom<arm64>::addImageOffsetFixup(uint32_t offset, const ld::Atom*
        _fixups.push_back(ld::Fixup(offset, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndian32));
 }
 
+template <>
+void UnwindInfoAtom<arm>::addImageOffsetFixup(uint32_t offset, const ld::Atom* targ)
+{
+       _fixups.push_back(ld::Fixup(offset, ld::Fixup::k1of2, ld::Fixup::kindSetTargetImageOffset, targ));
+       _fixups.push_back(ld::Fixup(offset, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndian32));
+}
+
 template <>
 void UnwindInfoAtom<x86>::addImageOffsetFixupPlusAddend(uint32_t offset, const ld::Atom* targ, uint32_t addend)
 {
@@ -526,6 +577,14 @@ void UnwindInfoAtom<arm64>::addImageOffsetFixupPlusAddend(uint32_t offset, const
        _fixups.push_back(ld::Fixup(offset, ld::Fixup::k3of3, ld::Fixup::kindStoreLittleEndian32));
 }
 
+template <>
+void UnwindInfoAtom<arm>::addImageOffsetFixupPlusAddend(uint32_t offset, const ld::Atom* targ, uint32_t addend)
+{
+       _fixups.push_back(ld::Fixup(offset, ld::Fixup::k1of3, ld::Fixup::kindSetTargetImageOffset, targ));
+       _fixups.push_back(ld::Fixup(offset, ld::Fixup::k2of3, ld::Fixup::kindAddAddend, addend));
+       _fixups.push_back(ld::Fixup(offset, ld::Fixup::k3of3, ld::Fixup::kindStoreLittleEndian32));
+}
+
 
 
 
@@ -839,6 +898,12 @@ static void makeFinalLinkedImageCompactUnwindSection(const Options& opts, ld::In
                case CPU_TYPE_ARM64:
                        state.addAtom(*new UnwindInfoAtom<arm64>(entries, ehFrameSize));
                        break;
+#endif
+#if SUPPORT_ARCH_arm_any
+               case CPU_TYPE_ARM:
+                       if ( opts.armUsesZeroCostExceptions() )
+                               state.addAtom(*new UnwindInfoAtom<arm>(entries, ehFrameSize));
+                       break;
 #endif
                default:
                        assert(0 && "no compact unwind for arch");
@@ -892,6 +957,8 @@ template <> ld::Fixup::Kind CompactUnwindAtom<x86_64>::_s_pointerStoreKind = ld:
 template <> ld::Fixup::Kind CompactUnwindAtom<arm64>::_s_pointerKind = ld::Fixup::kindStoreLittleEndian64;
 template <> ld::Fixup::Kind CompactUnwindAtom<arm64>::_s_pointerStoreKind = ld::Fixup::kindStoreTargetAddressLittleEndian64;
 #endif
+template <> ld::Fixup::Kind CompactUnwindAtom<arm>::_s_pointerKind = ld::Fixup::kindStoreLittleEndian32;
+template <> ld::Fixup::Kind CompactUnwindAtom<arm>::_s_pointerStoreKind = ld::Fixup::kindStoreTargetAddressLittleEndian32;
 
 template <typename A>
 CompactUnwindAtom<A>::CompactUnwindAtom(ld::Internal& state,const ld::Atom* funcAtom, uint32_t startOffset,
@@ -953,6 +1020,9 @@ static void makeCompactUnwindAtom(const Options& opts, ld::Internal& state, cons
                        state.addAtom(*new CompactUnwindAtom<arm64>(state, atom, startOffset, endOffset-startOffset, cui));
                        break;
 #endif
+               case CPU_TYPE_ARM:
+                       state.addAtom(*new CompactUnwindAtom<arm>(state, atom, startOffset, endOffset-startOffset, cui));
+                       break;
        }
 }
 
index e957e2b52b3342b100c1d8dae35cc5b89b19b892..ceab63c552264b13ac68a76b78026da1731e11aa 100644 (file)
@@ -1242,6 +1242,7 @@ static ld::relocatable::File* createReader(const char* path)
        objOpts.keepDwarfUnwind         = false;
        objOpts.forceDwarfConversion = false;
        objOpts.verboseOptimizationHints = true;
+       objOpts.armUsesZeroCostExceptions = true;
        objOpts.subType                         = sPreferredSubArch;
 #if 1
        if ( ! foundFatSlice ) {
index effd09ba08e14c2826bae276b3781b952f471e9b..f91ece313bce5ec0040bb677ca9a9d9e22063504 100644 (file)
@@ -163,6 +163,25 @@ bool UnwindPrinter<arm64>::validFile(const uint8_t* fileContent)
 }
 #endif
 
+template <>
+bool UnwindPrinter<arm>::validFile(const uint8_t* fileContent)
+{      
+       const macho_header<P>* header = (const macho_header<P>*)fileContent;
+       if ( header->magic() != MH_MAGIC )
+               return false;
+       if ( header->cputype() != CPU_TYPE_ARM )
+               return false;
+       switch (header->filetype()) {
+               case MH_EXECUTE:
+               case MH_DYLIB:
+               case MH_BUNDLE:
+               case MH_DYLINKER:
+               case MH_OBJECT:
+                       return true;
+       }
+       return false;
+}
+
 template <typename A>
 UnwindPrinter<A>::UnwindPrinter(const uint8_t* fileContent, uint32_t fileLength, const char* path, bool showFunctionNames)
  : fHeader(NULL), fLength(fileLength), fUnwindSection(NULL),
@@ -737,6 +756,91 @@ void UnwindPrinter<arm64>::decode(uint32_t encoding, const uint8_t* funcStart, c
 }
 #endif
 
+template <>
+void UnwindPrinter<arm>::decode(uint32_t encoding, const uint8_t* funcStart, char* str)
+{
+       *str = '\0';
+       switch ( encoding & UNWIND_ARM_MODE_MASK ) {
+               case UNWIND_ARM_MODE_DWARF:
+                       sprintf(str, "dwarf offset 0x%08X, ", encoding & UNWIND_ARM_DWARF_SECTION_OFFSET);
+                       break;
+               case UNWIND_ARM_MODE_FRAME:
+               case UNWIND_ARM_MODE_FRAME_D:
+                       switch ( encoding & UNWIND_ARM_FRAME_STACK_ADJUST_MASK ) {
+                               case 0x00000000:
+                                       strcpy(str, "std frame: ");
+                                       break;
+                               case 0x00400000:
+                                       strcat(str, "std frame(sp adj 4): ");
+                                       break;
+                               case 0x00800000:
+                                       strcat(str, "std frame(sp adj 8): ");
+                                       break;
+                               case 0x00C00000:
+                                       strcat(str, "std frame(sp adj 12): ");
+                                       break;
+                       }
+                       if ( encoding & UNWIND_ARM_FRAME_FIRST_PUSH_R4 )
+                               strcat(str, "r4 ");
+                       if ( encoding & UNWIND_ARM_FRAME_FIRST_PUSH_R5 )
+                               strcat(str, "r5 ");
+                       if ( encoding & UNWIND_ARM_FRAME_FIRST_PUSH_R6 )
+                               strcat(str, "r6 ");
+                               
+                       if ( encoding & 0x000000F8) 
+                               strcat(str, " / ");
+                       if ( encoding & UNWIND_ARM_FRAME_SECOND_PUSH_R8 )
+                               strcat(str, "r8 ");
+                       if ( encoding & UNWIND_ARM_FRAME_SECOND_PUSH_R9 )
+                               strcat(str, "r9 ");
+                       if ( encoding & UNWIND_ARM_FRAME_SECOND_PUSH_R10 )
+                               strcat(str, "r10 ");
+                       if ( encoding & UNWIND_ARM_FRAME_SECOND_PUSH_R11 )
+                               strcat(str, "r11 ");
+                       if ( encoding & UNWIND_ARM_FRAME_SECOND_PUSH_R12 )
+                               strcat(str, "r12 ");
+                       
+                       if ( (encoding & UNWIND_ARM_MODE_MASK) == UNWIND_ARM_MODE_FRAME_D ) {
+                               switch ( encoding & UNWIND_ARM_FRAME_D_REG_COUNT_MASK ) {
+                                       case 0x00000000:
+                                               strcat(str, " / d8 ");
+                                               break;
+                                       case 0x00000100:
+                                               strcat(str, " / d8,d10 ");
+                                               break;
+                                       case 0x00000200:
+                                               strcat(str, " / d8,d10,d12 ");
+                                               break;
+                                       case 0x00000300:
+                                               strcat(str, " / d8,d10,d12,d14 ");
+                                               break;
+                                       case 0x00000400:
+                                               strcat(str, " / d12,d14 / d8,d9,d10 ");
+                                               break;
+                                       case 0x00000500:
+                                               strcat(str, " / d14 / d8,d9,d10,d11,d12");
+                                               break;
+                                       case 0x00000600:
+                                               strcat(str, " / d8,d9,d10,d11,d12,d13,d14 ");
+                                               break;
+                                       case 0x00000700:
+                                               strcat(str, " / d8,d9,d10,d11,d12,d13,d14 ");
+                                               break;
+                                       default:
+                                               strcat(str, " / unknown D register usage ");
+                                               break;
+                               }
+                       }
+                       
+                       break;
+               default:
+                       if ( encoding == 0 )
+                               strcpy(str, "no unwind information");
+                       else
+                               strcpy(str, "unsupported compact unwind");
+                       break;
+       }
+}
 
 
 template <>
@@ -768,6 +872,14 @@ const char* UnwindPrinter<arm64>::personalityName(const macho_relocation_info<ar
 }
 #endif
 
+template <>
+const char* UnwindPrinter<arm>::personalityName(const macho_relocation_info<arm::P>* reloc)
+{
+       //assert(reloc->r_extern() && "reloc not extern on personality column in __compact_unwind section");
+       //assert((reloc->r_type() == GENERIC_RELOC_VANILLA) && "wrong reloc type on personality column in __compact_unwind section");
+       const macho_nlist<P>& sym = fSymbols[reloc->r_symbolnum()];
+       return &fStrings[sym.n_strx()];
+}
 
 template <typename A>
 bool UnwindPrinter<A>::hasExernReloc(uint64_t sectionOffset, const char** personalityStr, pint_t* addr)
@@ -1004,6 +1116,12 @@ static void dump(const char* path, const std::set<cpu_type_t>& onlyArchs, bool s
                                                        throw "in universal file, arm64 slice does not contain arm64 mach-o";
                                                break;
 #endif
+                                       case CPU_TYPE_ARM:
+                                               if ( UnwindPrinter<arm>::validFile(p + offset) )
+                                                       UnwindPrinter<arm>::make(p + offset, size, path, showFunctionNames);
+                                               else
+                                                       throw "in universal file, arm slice does not contain arm mach-o";
+                                               break;
                                        default:
                                                        throwf("in universal file, unknown architecture slice 0x%x\n", cputype);
                                        }
@@ -1021,6 +1139,9 @@ static void dump(const char* path, const std::set<cpu_type_t>& onlyArchs, bool s
                        UnwindPrinter<arm64>::make(p, length, path, showFunctionNames);
                }
 #endif         
+               else if ( UnwindPrinter<arm>::validFile(p) && onlyArchs.count(CPU_TYPE_ARM) ) {
+                       UnwindPrinter<arm>::make(p, length, path, showFunctionNames);
+               }
                else {
                        throw "not a known file type";
                }
@@ -1051,6 +1172,8 @@ int main(int argc, const char* argv[])
                                        else if ( strcmp(arch, "arm64") == 0 )
                                                onlyArchs.insert(CPU_TYPE_ARM64);
 #endif
+                                       else if ( strcmp(arch, "armv7k") == 0 )
+                                               onlyArchs.insert(CPU_TYPE_ARM);
                                        else 
                                                throwf("unknown architecture %s", arch);
                                }