]> git.cameronkatri.com Git - apple_cmds.git/blob - system_cmds/zlog.tproj/SymbolicationHelper.c
gitignore: Add executables and compressed manpages
[apple_cmds.git] / system_cmds / zlog.tproj / SymbolicationHelper.c
1 //
2 // SymbolicationHelper.c
3 // zlog
4 //
5 // Created by Rasha Eqbal on 2/26/18.
6 //
7
8 #include "SymbolicationHelper.h"
9
10 /*
11 * Most of the CoreSymbolication code here has been copied from ioclasscount in the IOKitTools project.
12 */
13
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")
20
21 static void AddSymbolOwnerSummary(CSSymbolOwnerRef owner, CFMutableDictionaryRef binaryImages);
22 static void ShowBinaryImage(const void *key, const void *value, void *context);
23
24 /*
25 * Symbolicates 'addr' using the 'symbolicator' passed in.
26 * Adds owner info to 'binaryImages' for offline symbolication.
27 *
28 * Top-level function that needs to be called on each frame address in the backtrace.
29 */
30 void PrintSymbolicatedAddress(CSSymbolicatorRef symbolicator, mach_vm_address_t addr, CFMutableDictionaryRef binaryImages)
31 {
32 printf("0x%llx", addr);
33
34 CSSymbolOwnerRef ownerInfo = CSSymbolicatorGetSymbolOwnerWithAddressAtTime(symbolicator, addr, kCSNow);
35 if (!CSIsNull(ownerInfo)) {
36 const char *moduleName = CSSymbolOwnerGetName(ownerInfo);
37 if (moduleName) {
38 printf(" <%s>", moduleName);
39 }
40 }
41
42 CSSymbolRef symbolInfo = CSSymbolicatorGetSymbolWithAddressAtTime(symbolicator, addr, kCSNow);
43 if (!CSIsNull(symbolInfo)) {
44 printf(" %s", CSSymbolGetName(symbolInfo));
45 }
46
47 CSSourceInfoRef sourceInfo = CSSymbolicatorGetSourceInfoWithAddressAtTime(symbolicator, addr, kCSNow);
48 if (!CSIsNull(sourceInfo)) {
49 const char *fileName = CSSourceInfoGetPath(sourceInfo);
50 if (fileName) {
51 printf(" at %s:%d", fileName, CSSourceInfoGetLineNumber(sourceInfo));
52 }
53 }
54 printf("\n");
55
56 AddSymbolOwnerSummary(ownerInfo, binaryImages);
57 }
58
59 /*
60 * Adds symbolication information for 'owner' to 'binaryImages' to help with offline symbolication.
61 *
62 * This is called from PrintSymbolicatedAddress() on the symbol owner for each address it symbolicates.
63 */
64 static void AddSymbolOwnerSummary(CSSymbolOwnerRef owner, CFMutableDictionaryRef binaryImages)
65 {
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;
72 CSRange range;
73 CFNumberRef address = NULL, size = NULL;
74
75 #define RETURN_IF_NULL(ptr) \
76 if (!(ptr)) { \
77 goto cleanup; \
78 }
79
80 uuidBytes = CSSymbolOwnerGetCFUUIDBytes(owner);
81 if (uuidBytes) {
82 uuid = CFUUIDCreateFromUUIDBytes(NULL, *uuidBytes);
83 if (uuid) {
84 uuidString = CFUUIDCreateString(kCFAllocatorDefault, uuid);
85 }
86 }
87 RETURN_IF_NULL(uuidString);
88
89 if (!CFDictionaryContainsKey(binaryImages, uuidString)) {
90 summaryDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
91 RETURN_IF_NULL(summaryDict);
92
93 CFDictionarySetValue(summaryDict, kUuidKey, uuidString);
94
95 path = CFStringCreateWithCString(kCFAllocatorDefault, CSSymbolOwnerGetPath(owner), kCFStringEncodingUTF8);
96 RETURN_IF_NULL(path);
97 CFDictionarySetValue(summaryDict, kPathKey, path);
98
99 name = CFStringCreateWithCString(kCFAllocatorDefault, CSSymbolOwnerGetName(owner), kCFStringEncodingUTF8);
100 RETURN_IF_NULL(name);
101 CFDictionarySetValue(summaryDict, kNameKey, name);
102
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);
110 }
111 });
112
113 segment = !CSIsNull(textExecSegment) ? textExecSegment : textSegment;
114 if (CSIsNull(segment)) {
115 goto cleanup;
116 }
117 range = CSRegionGetRange(segment);
118
119 address = CFNumberCreate(NULL, kCFNumberLongLongType, &range.location);
120 RETURN_IF_NULL(address);
121 CFDictionarySetValue(summaryDict, kAddressKey, address);
122
123 size = CFNumberCreate(NULL, kCFNumberLongLongType, &range.length);
124 RETURN_IF_NULL(size);
125 CFDictionarySetValue(summaryDict, kSizeKey, size);
126
127 CFDictionarySetValue(binaryImages, uuidString, summaryDict);
128 }
129
130 cleanup:
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);
140 }
141
142 /*
143 * Prints offline symbolication information for the images passed in 'binaryImages'.
144 *
145 * Top-level function that needs to be called if the tool wants to include support
146 * for offline symbolication.
147 */
148 void PrintBinaryImagesInfo(CFMutableDictionaryRef binaryImages)
149 {
150 if (CFDictionaryGetCount(binaryImages) > 0) {
151 printf("\nBinary Images:\n");
152 CFDictionaryApplyFunction(binaryImages, ShowBinaryImage, NULL);
153 } else {
154 printf("No binary images\n");
155 }
156 }
157
158 /*
159 * Prints information about a binary image necessary for offline symbolication.
160 *
161 * This is called from PrintBinaryImagesInfo() on each element in 'binaryImages'.
162 */
163 static void ShowBinaryImage(const void *key, const void *value, void *context)
164 {
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;
169
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);
179
180 printf("%p - %p %s <%s> %s\n", (void*)address, (void*)address + size, nameString, uuidString, pathString);
181 }