2 // SymbolicationHelper.c
5 // Created by Rasha Eqbal on 2/26/18.
8 #include "SymbolicationHelper.h"
11 * Most of the CoreSymbolication code here has been copied from ioclasscount in the IOKitTools project.
14 #define kAddressKey CFSTR("Address")
15 #define kNameKey CFSTR("Name")
16 #define kPathKey CFSTR("Path")
17 #define kSegmentsKey CFSTR("Segments")
18 #define kSizeKey CFSTR("Size")
19 #define kUuidKey CFSTR("UUID")
21 static void AddSymbolOwnerSummary(CSSymbolOwnerRef owner
, CFMutableDictionaryRef binaryImages
);
22 static void ShowBinaryImage(const void *key
, const void *value
, void *context
);
25 * Symbolicates 'addr' using the 'symbolicator' passed in.
26 * Adds owner info to 'binaryImages' for offline symbolication.
28 * Top-level function that needs to be called on each frame address in the backtrace.
30 void PrintSymbolicatedAddress(CSSymbolicatorRef symbolicator
, mach_vm_address_t addr
, CFMutableDictionaryRef binaryImages
)
32 printf("0x%llx", addr
);
34 CSSymbolOwnerRef ownerInfo
= CSSymbolicatorGetSymbolOwnerWithAddressAtTime(symbolicator
, addr
, kCSNow
);
35 if (!CSIsNull(ownerInfo
)) {
36 const char *moduleName
= CSSymbolOwnerGetName(ownerInfo
);
38 printf(" <%s>", moduleName
);
42 CSSymbolRef symbolInfo
= CSSymbolicatorGetSymbolWithAddressAtTime(symbolicator
, addr
, kCSNow
);
43 if (!CSIsNull(symbolInfo
)) {
44 printf(" %s", CSSymbolGetName(symbolInfo
));
47 CSSourceInfoRef sourceInfo
= CSSymbolicatorGetSourceInfoWithAddressAtTime(symbolicator
, addr
, kCSNow
);
48 if (!CSIsNull(sourceInfo
)) {
49 const char *fileName
= CSSourceInfoGetPath(sourceInfo
);
51 printf(" at %s:%d", fileName
, CSSourceInfoGetLineNumber(sourceInfo
));
56 AddSymbolOwnerSummary(ownerInfo
, binaryImages
);
60 * Adds symbolication information for 'owner' to 'binaryImages' to help with offline symbolication.
62 * This is called from PrintSymbolicatedAddress() on the symbol owner for each address it symbolicates.
64 static void AddSymbolOwnerSummary(CSSymbolOwnerRef owner
, CFMutableDictionaryRef binaryImages
)
66 const CFUUIDBytes
*uuidBytes
= NULL
;
67 CFUUIDRef uuid
= NULL
;
68 CFStringRef uuidString
= NULL
, path
= NULL
, name
= NULL
;
69 CFMutableDictionaryRef summaryDict
= NULL
;
70 __block CSSegmentRef textSegment
= kCSNull
, textExecSegment
= kCSNull
;
71 CSSegmentRef segment
= kCSNull
;
73 CFNumberRef address
= NULL
, size
= NULL
;
75 #define RETURN_IF_NULL(ptr) \
80 uuidBytes
= CSSymbolOwnerGetCFUUIDBytes(owner
);
82 uuid
= CFUUIDCreateFromUUIDBytes(NULL
, *uuidBytes
);
84 uuidString
= CFUUIDCreateString(kCFAllocatorDefault
, uuid
);
87 RETURN_IF_NULL(uuidString
);
89 if (!CFDictionaryContainsKey(binaryImages
, uuidString
)) {
90 summaryDict
= CFDictionaryCreateMutable(NULL
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
91 RETURN_IF_NULL(summaryDict
);
93 CFDictionarySetValue(summaryDict
, kUuidKey
, uuidString
);
95 path
= CFStringCreateWithCString(kCFAllocatorDefault
, CSSymbolOwnerGetPath(owner
), kCFStringEncodingUTF8
);
97 CFDictionarySetValue(summaryDict
, kPathKey
, path
);
99 name
= CFStringCreateWithCString(kCFAllocatorDefault
, CSSymbolOwnerGetName(owner
), kCFStringEncodingUTF8
);
100 RETURN_IF_NULL(name
);
101 CFDictionarySetValue(summaryDict
, kNameKey
, name
);
103 CSSymbolOwnerForeachSegment(owner
, ^(CSSegmentRef segment
) {
104 if (strcmp(CSRegionGetName(segment
), "__TEXT SEGMENT") == 0) {
105 textSegment
= segment
;
106 CSRetain(textSegment
);
107 } else if (strcmp(CSRegionGetName(segment
), "__TEXT_EXEC SEGMENT") == 0) {
108 textExecSegment
= segment
;
109 CSRetain(textExecSegment
);
113 segment
= !CSIsNull(textExecSegment
) ? textExecSegment
: textSegment
;
114 if (CSIsNull(segment
)) {
117 range
= CSRegionGetRange(segment
);
119 address
= CFNumberCreate(NULL
, kCFNumberLongLongType
, &range
.location
);
120 RETURN_IF_NULL(address
);
121 CFDictionarySetValue(summaryDict
, kAddressKey
, address
);
123 size
= CFNumberCreate(NULL
, kCFNumberLongLongType
, &range
.length
);
124 RETURN_IF_NULL(size
);
125 CFDictionarySetValue(summaryDict
, kSizeKey
, size
);
127 CFDictionarySetValue(binaryImages
, uuidString
, summaryDict
);
131 if (size
) CFRelease(size
);
132 if (address
) CFRelease(address
);
133 if (!CSIsNull(textExecSegment
)) CSRelease(textExecSegment
);
134 if (!CSIsNull(textSegment
)) CSRelease(textSegment
);
135 if (name
) CFRelease(name
);
136 if (path
) CFRelease(path
);
137 if (summaryDict
) CFRelease(summaryDict
);
138 if (uuidString
) CFRelease(uuidString
);
139 if (uuid
) CFRelease(uuid
);
143 * Prints offline symbolication information for the images passed in 'binaryImages'.
145 * Top-level function that needs to be called if the tool wants to include support
146 * for offline symbolication.
148 void PrintBinaryImagesInfo(CFMutableDictionaryRef binaryImages
)
150 if (CFDictionaryGetCount(binaryImages
) > 0) {
151 printf("\nBinary Images:\n");
152 CFDictionaryApplyFunction(binaryImages
, ShowBinaryImage
, NULL
);
154 printf("No binary images\n");
159 * Prints information about a binary image necessary for offline symbolication.
161 * This is called from PrintBinaryImagesInfo() on each element in 'binaryImages'.
163 static void ShowBinaryImage(const void *key
, const void *value
, void *context
)
165 char nameString
[256] = {0}, uuidString
[256] = {0}, pathString
[256] = {0};
166 CFStringRef uuid
= (CFStringRef
)key
;
167 CFStringGetCString(uuid
, uuidString
, sizeof(uuidString
), kCFStringEncodingASCII
);
168 CFDictionaryRef summary
= (CFDictionaryRef
)value
;
170 CFStringRef name
= CFDictionaryGetValue(summary
, kNameKey
);
171 CFStringGetCString(name
, nameString
, sizeof(nameString
), kCFStringEncodingASCII
);
172 CFStringRef path
= CFDictionaryGetValue(summary
, kPathKey
);
173 CFStringGetCString(path
, pathString
, sizeof(pathString
), kCFStringEncodingASCII
);
174 CFNumberRef addressNumber
= CFDictionaryGetValue(summary
, kAddressKey
);
175 CFNumberRef sizeNumber
= CFDictionaryGetValue(summary
, kSizeKey
);
176 int64_t address
, size
;
177 CFNumberGetValue(addressNumber
, kCFNumberSInt64Type
, &address
);
178 CFNumberGetValue(sizeNumber
, kCFNumberSInt64Type
, &size
);
180 printf("%p - %p %s <%s> %s\n", (void*)address
, (void*)address
+ size
, nameString
, uuidString
, pathString
);