#include <vector>
#include <set>
-#include <ext/hash_set>
-
+#include <unordered_set>
+#include "configure.h"
#include "MachOFileAbstraction.hpp"
#include "Architectures.hpp"
typedef typename A::P::E E;
typedef typename A::P::uint_t pint_t;
- class CStringEquals
- {
- public:
- bool operator()(const char* left, const char* right) const { return (strcmp(left, right) == 0); }
- };
-
- typedef __gnu_cxx::hash_set<const char*, __gnu_cxx::hash<const char*>, CStringEquals> StringSet;
-
UnwindPrinter(const uint8_t* fileContent, uint32_t fileLength,
const char* path, bool showFunctionNames);
bool findUnwindSection();
};
-template <> const char* UnwindPrinter<ppc>::archName() { return "ppc"; }
-template <> const char* UnwindPrinter<ppc64>::archName() { return "ppc64"; }
template <> const char* UnwindPrinter<x86>::archName() { return "i386"; }
template <> const char* UnwindPrinter<x86_64>::archName() { return "x86_64"; }
template <> const char* UnwindPrinter<arm>::archName() { return "arm"; }
-
+#if SUPPORT_ARCH_arm64
+template <> const char* UnwindPrinter<arm64>::archName() { return "arm64"; }
+#endif
template <>
bool UnwindPrinter<x86>::validFile(const uint8_t* fileContent)
}
+#if SUPPORT_ARCH_arm64
+template <>
+bool UnwindPrinter<arm64>::validFile(const uint8_t* fileContent)
+{
+ const macho_header<P>* header = (const macho_header<P>*)fileContent;
+ if ( header->magic() != MH_MAGIC_64 )
+ return false;
+ if ( header->cputype() != CPU_TYPE_ARM64 )
+ return false;
+ switch (header->filetype()) {
+ case MH_EXECUTE:
+ case MH_DYLIB:
+ case MH_BUNDLE:
+ case MH_DYLINKER:
+ case MH_OBJECT:
+ return true;
+ }
+ return false;
+}
+#endif
+
template <typename A>
UnwindPrinter<A>::UnwindPrinter(const uint8_t* fileContent, uint32_t fileLength, const char* path, bool showFunctionNames)
: fHeader(NULL), fLength(fileLength), fUnwindSection(NULL),
}
-
+#if SUPPORT_ARCH_arm64
+template <>
+void UnwindPrinter<arm64>::decode(uint32_t encoding, const uint8_t* funcStart, char* str)
+{
+ uint32_t stackSize;
+ switch ( encoding & UNWIND_ARM64_MODE_MASK ) {
+ case UNWIND_ARM64_MODE_FRAMELESS:
+ stackSize = EXTRACT_BITS(encoding, UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK);
+ if ( stackSize == 0 )
+ strcpy(str, "no frame, no saved registers ");
+ else
+ sprintf(str, "stack size=%d: ", 16 * stackSize);
+ if ( encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR )
+ strcat(str, "x19/20 ");
+ if ( encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR )
+ strcat(str, "x21/22 ");
+ if ( encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR )
+ strcat(str, "x23/24 ");
+ if ( encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR )
+ strcat(str, "x25/26 ");
+ if ( encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR )
+ strcat(str, "x27/28 ");
+ if ( encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR )
+ strcat(str, "d8/9 ");
+ if ( encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR )
+ strcat(str, "d10/11 ");
+ if ( encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR )
+ strcat(str, "d12/13 ");
+ if ( encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR )
+ strcat(str, "d14/15 ");
+ break;
+ break;
+ case UNWIND_ARM64_MODE_DWARF:
+ sprintf(str, "dwarf offset 0x%08X, ", encoding & UNWIND_X86_64_DWARF_SECTION_OFFSET);
+ break;
+ case UNWIND_ARM64_MODE_FRAME:
+ strcpy(str, "std frame: ");
+ if ( encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR )
+ strcat(str, "x19/20 ");
+ if ( encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR )
+ strcat(str, "x21/22 ");
+ if ( encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR )
+ strcat(str, "x23/24 ");
+ if ( encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR )
+ strcat(str, "x25/26 ");
+ if ( encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR )
+ strcat(str, "x27/28 ");
+ if ( encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR )
+ strcat(str, "d8/9 ");
+ if ( encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR )
+ strcat(str, "d10/11 ");
+ if ( encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR )
+ strcat(str, "d12/13 ");
+ if ( encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR )
+ strcat(str, "d14/15 ");
+ break;
+ case UNWIND_ARM64_MODE_FRAME_OLD:
+ strcpy(str, "old frame: ");
+ if ( encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR_OLD )
+ strcat(str, "x21/22 ");
+ if ( encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR_OLD )
+ strcat(str, "x23/24 ");
+ if ( encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR_OLD )
+ strcat(str, "x25/26 ");
+ if ( encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR_OLD )
+ strcat(str, "x27/28 ");
+ if ( encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR_OLD )
+ strcat(str, "d8/9 ");
+ if ( encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR_OLD )
+ strcat(str, "d10/11 ");
+ if ( encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR_OLD )
+ strcat(str, "d12/13 ");
+ if ( encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR_OLD )
+ strcat(str, "d14/15 ");
+ break;
+ }
+}
+#endif
template <>
const char* UnwindPrinter<x86_64>::personalityName(const macho_relocation_info<x86_64::P>* reloc)
return &fStrings[sym.n_strx()];
}
+#if SUPPORT_ARCH_arm64
+template <>
+const char* UnwindPrinter<arm64>::personalityName(const macho_relocation_info<arm64::P>* reloc)
+{
+ //assert(reloc->r_extern() && "reloc not extern on personality column in __compact_unwind section");
+ //assert((reloc->r_type() == ARM64_RELOC_UNSIGNED) && "wrong reloc type on personality column in __compact_unwind section");
+ const macho_nlist<P>& sym = fSymbols[reloc->r_symbolnum()];
+ return &fStrings[sym.n_strx()];
+}
+#endif
+
template <typename A>
bool UnwindPrinter<A>::hasExernReloc(uint64_t sectionOffset, const char** personalityStr, pint_t* addr)
{
printf(" lsda: 0x%08llX %s+0x%X\n", (uint64_t)entry->lsda(), lsdaName, lsdaOffset);
}
}
-
}
char encodingString[100];
decode(entry[j].encoding(), ((const uint8_t*)fHeader)+funcOffset, encodingString);
const char* name = showFunctionNames ? functionName(funcOffset+fMachHeaderAddress) : "";
- printf("\t\t\t[%3u] funcOffset=0x%08X, encoding=0x%08X (%-40s) %s\n",
+ printf("\t\t\t[%3u] funcOffset=0x%08X, encoding=0x%08X (%-56s) %s\n",
j, funcOffset, entry[j].encoding(), encodingString, name);
}
}
fprintf(stderr, "MISSING LSDA entry for %s\n", name);
}
}
- printf("\t\t\t[%3u] funcOffset=0x%08X, encoding[%3u]=0x%08X (%-40s) %s\n",
+ printf("\t\t\t[%3u] funcOffset=0x%08X, encoding[%3u]=0x%08X (%-56s) %s\n",
j, funcOff, encodingIndex, encoding, encodingString, name);
}
}
else
throw "in universal file, x86_64 slice does not contain x86_64 mach-o";
break;
+#if SUPPORT_ARCH_arm64
+ case CPU_TYPE_ARM64:
+ if ( UnwindPrinter<arm64>::validFile(p + offset) )
+ UnwindPrinter<arm64>::make(p + offset, size, path, showFunctionNames);
+ else
+ throw "in universal file, arm64 slice does not contain arm mach-o";
+ break;
+#endif
default:
throwf("in universal file, unknown architecture slice 0x%x\n", cputype);
}
else if ( UnwindPrinter<x86_64>::validFile(p) && onlyArchs.count(CPU_TYPE_X86_64) ) {
UnwindPrinter<x86_64>::make(p, length, path, showFunctionNames);
}
+#if SUPPORT_ARCH_arm64
+ else if ( UnwindPrinter<arm64>::validFile(p) && onlyArchs.count(CPU_TYPE_ARM64) ) {
+ UnwindPrinter<arm64>::make(p, length, path, showFunctionNames);
+ }
+#endif
else {
throw "not a known file type";
}
onlyArchs.insert(CPU_TYPE_I386);
else if ( strcmp(arch, "x86_64") == 0 )
onlyArchs.insert(CPU_TYPE_X86_64);
+#if SUPPORT_ARCH_arm64
+ else if ( strcmp(arch, "arm64") == 0 )
+ onlyArchs.insert(CPU_TYPE_ARM64);
+#endif
else
throwf("unknown architecture %s", arch);
}
if ( onlyArchs.size() == 0 ) {
onlyArchs.insert(CPU_TYPE_I386);
onlyArchs.insert(CPU_TYPE_X86_64);
+#if SUPPORT_ARCH_arm64
+ onlyArchs.insert(CPU_TYPE_ARM64);
+#endif
}
// process each file