]> git.saurik.com Git - apple/libc.git/blob - gen/assumes.c
076e59cb3808abd727d192eb7077e29d39d4fdcc
[apple/libc.git] / gen / assumes.c
1 #include <dispatch/dispatch.h>
2 #include <uuid/uuid.h>
3 #include <sys/types.h>
4 #include <sys/sysctl.h>
5 #include <mach-o/loader.h>
6 #include <sys/types.h>
7 #include <execinfo.h>
8 #include <stdio.h>
9 #include <dlfcn.h>
10 #include <asl.h>
11 #include <errno.h>
12 #include "assumes.h"
13
14 /* TODO: Re-enable after deciding how best to interact with this symbol. */
15 /*
16 * NOTE: 8006611: converted to using libCrashReporterClient.a, so shouldn't
17 * use __crashreporter_info__.
18 */
19 #if 0
20 static char __crashreporter_info_buff__[2048];
21 const char *__crashreporter_info__ = &__crashreporter_info_buff__[0];
22 asm (".desc __crashreporter_info__, 0x10");
23 #endif
24
25 #define osx_atomic_cmpxchg(p, o, n) __sync_bool_compare_and_swap((p), (o), (n))
26
27 static const char *
28 _osx_basename(const char *p)
29 {
30 return ((strrchr(p, '/') ? : p - 1) + 1);
31 }
32
33 static char *
34 _osx_get_build(void)
35 {
36 static char s_build[16];
37 static long s_once = 0;
38 if (osx_atomic_cmpxchg(&s_once, 0, 1)) {
39 int mib[] = { CTL_KERN, KERN_OSVERSION };
40 size_t sz = sizeof(s_build);
41
42 (void)sysctl(mib, 2, s_build, &sz, NULL, 0);
43 }
44
45 return s_build;
46 }
47
48 static void
49 _osx_get_image_uuid(void *hdr, uuid_t uuid)
50 {
51 #if __LP64__
52 struct mach_header_64 *_hdr = (struct mach_header_64 *)hdr;
53 #else
54 struct mach_header *_hdr = (struct mach_header *)hdr;
55 #endif /* __LP64__ */
56
57 size_t i = 0;
58 size_t next = sizeof(*_hdr);
59 struct load_command *cur = NULL;
60 for (i = 0; i < _hdr->ncmds; i++) {
61 cur = (struct load_command *)((uintptr_t)_hdr + next);
62 if (cur->cmd == LC_UUID) {
63 struct uuid_command *cmd = (struct uuid_command *)cur;
64 uuid_copy(uuid, cmd->uuid);
65 break;
66 }
67 next += cur->cmdsize;
68 }
69
70 if (i == _hdr->ncmds) {
71 uuid_clear(uuid);
72 }
73 }
74
75 void
76 _osx_assumes_log(uint64_t code)
77 {
78 Dl_info info;
79
80 const char *image_name = NULL;
81 uintptr_t offset = 0;
82 uuid_string_t uuid_str;
83
84 void *arr[2];
85 /* Get our caller's address so we can look it up with dladdr(3) and
86 * get info about the image.
87 */
88 if (backtrace(arr, 2) == 2) {
89 /* dladdr(3) returns non-zero on success... for some reason. */
90 if (dladdr(arr[1], &info)) {
91 uuid_t uuid;
92 _osx_get_image_uuid(info.dli_fbase, uuid);
93
94 uuid_unparse(uuid, uuid_str);
95 image_name = _osx_basename(info.dli_fname);
96
97 offset = arr[1] - info.dli_fbase;
98 }
99 } else {
100 uuid_t null_uuid;
101 uuid_string_t uuid_str;
102
103 uuid_clear(null_uuid);
104 uuid_unparse(null_uuid, uuid_str);
105
106 image_name = "unknown";
107 }
108
109 char name[256];
110 (void)snprintf(name, sizeof(name), "com.apple.assumes.%s", image_name);
111
112 char sig[64];
113 (void)snprintf(sig, sizeof(sig), "%s:%lu", uuid_str, offset);
114
115 char result[24];
116 (void)snprintf(result, sizeof(result), "0x%llx", code);
117
118 char *prefix = "Bug";
119 char message[1024];
120 (void)snprintf(message, sizeof(message), "%s: %s: %s + %lu [%s]: %s", prefix, _osx_get_build(), image_name, offset, uuid_str, result);
121
122 aslmsg msg = asl_new(ASL_TYPE_MSG);
123 if (msg != NULL) {
124 /* MessageTracer messages aren't logged to the regular syslog store, so
125 * we pre-log the message without any MessageTracer attributes so that
126 * we can see it in our regular syslog.
127 */
128 (void)asl_log(NULL, msg, ASL_LEVEL_ERR, "%s", message);
129
130 (void)asl_set(msg, "com.apple.message.domain", name);
131 (void)asl_set(msg, "com.apple.message.signature", sig);
132 (void)asl_set(msg, "com.apple.message.value", result);
133
134 (void)asl_log(NULL, msg, ASL_LEVEL_ERR, "%s", message);
135 asl_free(msg);
136 }
137 }
138
139 /* For osx_assert(). We need to think more about how best to set the __crashreporter_info__ string.
140 * For example, calling into two functions will basically smash the register state at the time of
141 * the assertion failure, causing potentially valuable information to be lost. Also, just setting
142 * the __crashreporter_info__ to a static string only involves one instruction, whereas a function
143 * call involves... well, more.
144 */
145 #if 0
146 void
147 osx_hardware_trap(const char *fmt, ...)
148 {
149 va_list ap;
150 va_start(ap, fmt);
151
152 osx_hardware_trapv(fmt, ap);
153
154 va_end(ap);
155 }
156
157 void
158 osx_hardware_trapv(const char *fmt, va_list ap)
159 {
160 (void)vsnprintf(__crashreporter_info_buff__, sizeof(__crashreporter_info_buff__), fmt, ap);
161 fflush(NULL);
162 __builtin_trap();
163 }
164 #endif