aboutsummaryrefslogtreecommitdiffstats
path: root/system_cmds/zlog.tproj/SymbolicationHelper.c
diff options
context:
space:
mode:
Diffstat (limited to 'system_cmds/zlog.tproj/SymbolicationHelper.c')
-rw-r--r--system_cmds/zlog.tproj/SymbolicationHelper.c181
1 files changed, 181 insertions, 0 deletions
diff --git a/system_cmds/zlog.tproj/SymbolicationHelper.c b/system_cmds/zlog.tproj/SymbolicationHelper.c
new file mode 100644
index 0000000..68a1285
--- /dev/null
+++ b/system_cmds/zlog.tproj/SymbolicationHelper.c
@@ -0,0 +1,181 @@
+//
+// SymbolicationHelper.c
+// zlog
+//
+// Created by Rasha Eqbal on 2/26/18.
+//
+
+#include "SymbolicationHelper.h"
+
+/*
+ * Most of the CoreSymbolication code here has been copied from ioclasscount in the IOKitTools project.
+ */
+
+#define kAddressKey CFSTR("Address")
+#define kNameKey CFSTR("Name")
+#define kPathKey CFSTR("Path")
+#define kSegmentsKey CFSTR("Segments")
+#define kSizeKey CFSTR("Size")
+#define kUuidKey CFSTR("UUID")
+
+static void AddSymbolOwnerSummary(CSSymbolOwnerRef owner, CFMutableDictionaryRef binaryImages);
+static void ShowBinaryImage(const void *key, const void *value, void *context);
+
+/*
+ * Symbolicates 'addr' using the 'symbolicator' passed in.
+ * Adds owner info to 'binaryImages' for offline symbolication.
+ *
+ * Top-level function that needs to be called on each frame address in the backtrace.
+ */
+void PrintSymbolicatedAddress(CSSymbolicatorRef symbolicator, mach_vm_address_t addr, CFMutableDictionaryRef binaryImages)
+{
+ printf("0x%llx", addr);
+
+ CSSymbolOwnerRef ownerInfo = CSSymbolicatorGetSymbolOwnerWithAddressAtTime(symbolicator, addr, kCSNow);
+ if (!CSIsNull(ownerInfo)) {
+ const char *moduleName = CSSymbolOwnerGetName(ownerInfo);
+ if (moduleName) {
+ printf(" <%s>", moduleName);
+ }
+ }
+
+ CSSymbolRef symbolInfo = CSSymbolicatorGetSymbolWithAddressAtTime(symbolicator, addr, kCSNow);
+ if (!CSIsNull(symbolInfo)) {
+ printf(" %s", CSSymbolGetName(symbolInfo));
+ }
+
+ CSSourceInfoRef sourceInfo = CSSymbolicatorGetSourceInfoWithAddressAtTime(symbolicator, addr, kCSNow);
+ if (!CSIsNull(sourceInfo)) {
+ const char *fileName = CSSourceInfoGetPath(sourceInfo);
+ if (fileName) {
+ printf(" at %s:%d", fileName, CSSourceInfoGetLineNumber(sourceInfo));
+ }
+ }
+ printf("\n");
+
+ AddSymbolOwnerSummary(ownerInfo, binaryImages);
+}
+
+/*
+ * Adds symbolication information for 'owner' to 'binaryImages' to help with offline symbolication.
+ *
+ * This is called from PrintSymbolicatedAddress() on the symbol owner for each address it symbolicates.
+ */
+static void AddSymbolOwnerSummary(CSSymbolOwnerRef owner, CFMutableDictionaryRef binaryImages)
+{
+ const CFUUIDBytes *uuidBytes = NULL;
+ CFUUIDRef uuid = NULL;
+ CFStringRef uuidString = NULL, path = NULL, name = NULL;
+ CFMutableDictionaryRef summaryDict = NULL;
+ __block CSSegmentRef textSegment = kCSNull, textExecSegment = kCSNull;
+ CSSegmentRef segment = kCSNull;
+ CSRange range;
+ CFNumberRef address = NULL, size = NULL;
+
+#define RETURN_IF_NULL(ptr) \
+if (!(ptr)) { \
+goto cleanup; \
+}
+
+ uuidBytes = CSSymbolOwnerGetCFUUIDBytes(owner);
+ if (uuidBytes) {
+ uuid = CFUUIDCreateFromUUIDBytes(NULL, *uuidBytes);
+ if (uuid) {
+ uuidString = CFUUIDCreateString(kCFAllocatorDefault, uuid);
+ }
+ }
+ RETURN_IF_NULL(uuidString);
+
+ if (!CFDictionaryContainsKey(binaryImages, uuidString)) {
+ summaryDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ RETURN_IF_NULL(summaryDict);
+
+ CFDictionarySetValue(summaryDict, kUuidKey, uuidString);
+
+ path = CFStringCreateWithCString(kCFAllocatorDefault, CSSymbolOwnerGetPath(owner), kCFStringEncodingUTF8);
+ RETURN_IF_NULL(path);
+ CFDictionarySetValue(summaryDict, kPathKey, path);
+
+ name = CFStringCreateWithCString(kCFAllocatorDefault, CSSymbolOwnerGetName(owner), kCFStringEncodingUTF8);
+ RETURN_IF_NULL(name);
+ CFDictionarySetValue(summaryDict, kNameKey, name);
+
+ CSSymbolOwnerForeachSegment(owner, ^(CSSegmentRef segment) {
+ if (strcmp(CSRegionGetName(segment), "__TEXT SEGMENT") == 0) {
+ textSegment = segment;
+ CSRetain(textSegment);
+ } else if (strcmp(CSRegionGetName(segment), "__TEXT_EXEC SEGMENT") == 0) {
+ textExecSegment = segment;
+ CSRetain(textExecSegment);
+ }
+ });
+
+ segment = !CSIsNull(textExecSegment) ? textExecSegment : textSegment;
+ if (CSIsNull(segment)) {
+ goto cleanup;
+ }
+ range = CSRegionGetRange(segment);
+
+ address = CFNumberCreate(NULL, kCFNumberLongLongType, &range.location);
+ RETURN_IF_NULL(address);
+ CFDictionarySetValue(summaryDict, kAddressKey, address);
+
+ size = CFNumberCreate(NULL, kCFNumberLongLongType, &range.length);
+ RETURN_IF_NULL(size);
+ CFDictionarySetValue(summaryDict, kSizeKey, size);
+
+ CFDictionarySetValue(binaryImages, uuidString, summaryDict);
+ }
+
+cleanup:
+ if (size) CFRelease(size);
+ if (address) CFRelease(address);
+ if (!CSIsNull(textExecSegment)) CSRelease(textExecSegment);
+ if (!CSIsNull(textSegment)) CSRelease(textSegment);
+ if (name) CFRelease(name);
+ if (path) CFRelease(path);
+ if (summaryDict) CFRelease(summaryDict);
+ if (uuidString) CFRelease(uuidString);
+ if (uuid) CFRelease(uuid);
+}
+
+/*
+ * Prints offline symbolication information for the images passed in 'binaryImages'.
+ *
+ * Top-level function that needs to be called if the tool wants to include support
+ * for offline symbolication.
+ */
+void PrintBinaryImagesInfo(CFMutableDictionaryRef binaryImages)
+{
+ if (CFDictionaryGetCount(binaryImages) > 0) {
+ printf("\nBinary Images:\n");
+ CFDictionaryApplyFunction(binaryImages, ShowBinaryImage, NULL);
+ } else {
+ printf("No binary images\n");
+ }
+}
+
+/*
+ * Prints information about a binary image necessary for offline symbolication.
+ *
+ * This is called from PrintBinaryImagesInfo() on each element in 'binaryImages'.
+ */
+static void ShowBinaryImage(const void *key, const void *value, void *context)
+{
+ char nameString[256] = {0}, uuidString[256] = {0}, pathString[256] = {0};
+ CFStringRef uuid = (CFStringRef)key;
+ CFStringGetCString(uuid, uuidString, sizeof(uuidString), kCFStringEncodingASCII);
+ CFDictionaryRef summary = (CFDictionaryRef)value;
+
+ CFStringRef name = CFDictionaryGetValue(summary, kNameKey);
+ CFStringGetCString(name, nameString, sizeof(nameString), kCFStringEncodingASCII);
+ CFStringRef path = CFDictionaryGetValue(summary, kPathKey);
+ CFStringGetCString(path, pathString, sizeof(pathString), kCFStringEncodingASCII);
+ CFNumberRef addressNumber = CFDictionaryGetValue(summary, kAddressKey);
+ CFNumberRef sizeNumber = CFDictionaryGetValue(summary, kSizeKey);
+ int64_t address, size;
+ CFNumberGetValue(addressNumber, kCFNumberSInt64Type, &address);
+ CFNumberGetValue(sizeNumber, kCFNumberSInt64Type, &size);
+
+ printf("%p - %p %s <%s> %s\n", (void*)address, (void*)address + size, nameString, uuidString, pathString);
+}