1 // Copyright 2018 The Fuchsia Authors
2 //
3 // Use of this source code is governed by a MIT-style
4 // license that can be found in the LICENSE file or at
5 // https://opensource.org/licenses/MIT
6
7 #include <lib/crashlog.h>
8
9 #include <ctype.h>
10 #include <inttypes.h>
11 #include <kernel/thread.h>
12 #include <lib/version.h>
13 #include <platform.h>
14 #include <printf.h>
15 #include <string.h>
16
17 crashlog_t crashlog = {};
18
crashlog_to_string(char * out,const size_t out_len)19 size_t crashlog_to_string(char* out, const size_t out_len) {
20 char* buf = out;
21 size_t remain = out_len;
22 size_t len;
23
24 buf[0] = '\0';
25
26 len = snprintf(buf, remain, "ZIRCON KERNEL PANIC\n\n");
27 if (len > remain) {
28 return out_len;
29 }
30 remain -= len;
31 buf += len;
32
33 len = snprintf(buf, remain, "UPTIME (ms)\n%" PRIi64 "\n\n", current_time() / ZX_MSEC(1));
34 if (len > remain) {
35 return out_len;
36 }
37 remain -= len;
38 buf += len;
39
40 // Keep the format and values in sync with the symbolizer.
41 // Print before the registers (KASLR offset).
42 #if defined(__x86_64__)
43 const char* arch = "x86_64";
44 #elif defined(__aarch64__)
45 const char* arch = "aarch64";
46 #endif
47 len = snprintf(buf, remain, "VERSION\narch: %s\nbuild_id: %s\ndso: id=%s base=%#lx name=zircon.elf\n\n", arch, version.buildid, version.elf_build_id, crashlog.base_address);
48 if (len > remain) {
49 return out_len;
50 }
51 remain -= len;
52 buf += len;
53
54 if (crashlog.iframe) {
55 #if defined(__aarch64__)
56 len = snprintf(buf, remain, "REGISTERS\n"
57 " x0: %#18" PRIx64 "\n"
58 " x1: %#18" PRIx64 "\n"
59 " x2: %#18" PRIx64 "\n"
60 " x3: %#18" PRIx64 "\n"
61 " x4: %#18" PRIx64 "\n"
62 " x5: %#18" PRIx64 "\n"
63 " x6: %#18" PRIx64 "\n"
64 " x7: %#18" PRIx64 "\n"
65 " x8: %#18" PRIx64 "\n"
66 " x9: %#18" PRIx64 "\n"
67 " x10: %#18" PRIx64 "\n"
68 " x11: %#18" PRIx64 "\n"
69 " x12: %#18" PRIx64 "\n"
70 " x13: %#18" PRIx64 "\n"
71 " x14: %#18" PRIx64 "\n"
72 " x15: %#18" PRIx64 "\n"
73 " x16: %#18" PRIx64 "\n"
74 " x17: %#18" PRIx64 "\n"
75 " x18: %#18" PRIx64 "\n"
76 " x19: %#18" PRIx64 "\n"
77 " x20: %#18" PRIx64 "\n"
78 " x21: %#18" PRIx64 "\n"
79 " x22: %#18" PRIx64 "\n"
80 " x23: %#18" PRIx64 "\n"
81 " x24: %#18" PRIx64 "\n"
82 " x25: %#18" PRIx64 "\n"
83 " x26: %#18" PRIx64 "\n"
84 " x27: %#18" PRIx64 "\n"
85 " x28: %#18" PRIx64 "\n"
86 " x29: %#18" PRIx64 "\n"
87 " lr: %#18" PRIx64 "\n"
88 " usp: %#18" PRIx64 "\n"
89 " elr: %#18" PRIx64 "\n"
90 "spsr: %#18" PRIx64 "\n"
91 "\n",
92 crashlog.iframe->r[0],
93 crashlog.iframe->r[1],
94 crashlog.iframe->r[2],
95 crashlog.iframe->r[3],
96 crashlog.iframe->r[4],
97 crashlog.iframe->r[5],
98 crashlog.iframe->r[6],
99 crashlog.iframe->r[7],
100 crashlog.iframe->r[8],
101 crashlog.iframe->r[9],
102 crashlog.iframe->r[10],
103 crashlog.iframe->r[11],
104 crashlog.iframe->r[12],
105 crashlog.iframe->r[13],
106 crashlog.iframe->r[14],
107 crashlog.iframe->r[15],
108 crashlog.iframe->r[16],
109 crashlog.iframe->r[17],
110 crashlog.iframe->r[18],
111 crashlog.iframe->r[19],
112 crashlog.iframe->r[20],
113 crashlog.iframe->r[21],
114 crashlog.iframe->r[22],
115 crashlog.iframe->r[23],
116 crashlog.iframe->r[24],
117 crashlog.iframe->r[25],
118 crashlog.iframe->r[26],
119 crashlog.iframe->r[27],
120 crashlog.iframe->r[28],
121 crashlog.iframe->r[29],
122 crashlog.iframe->lr,
123 crashlog.iframe->usp,
124 crashlog.iframe->elr,
125 crashlog.iframe->spsr);
126 if (len > remain) {
127 return out_len;
128 }
129 remain -= len;
130 buf += len;
131 #elif defined(__x86_64__)
132 len = snprintf(buf, remain, "REGISTERS\n"
133 " CS: %#18" PRIx64 "\n"
134 " RIP: %#18" PRIx64 "\n"
135 " EFL: %#18" PRIx64 "\n"
136 " CR2: %#18lx\n"
137 " RAX: %#18" PRIx64 "\n"
138 " RBX: %#18" PRIx64 "\n"
139 " RCX: %#18" PRIx64 "\n"
140 " RDX: %#18" PRIx64 "\n"
141 " RSI: %#18" PRIx64 "\n"
142 " RDI: %#18" PRIx64 "\n"
143 " RBP: %#18" PRIx64 "\n"
144 " RSP: %#18" PRIx64 "\n"
145 " R8: %#18" PRIx64 "\n"
146 " R9: %#18" PRIx64 "\n"
147 " R10: %#18" PRIx64 "\n"
148 " R11: %#18" PRIx64 "\n"
149 " R12: %#18" PRIx64 "\n"
150 " R13: %#18" PRIx64 "\n"
151 " R14: %#18" PRIx64 "\n"
152 " R15: %#18" PRIx64 "\n"
153 "errc: %#18" PRIx64 "\n"
154 "\n",
155 crashlog.iframe->cs,
156 crashlog.iframe->ip,
157 crashlog.iframe->flags,
158 x86_get_cr2(),
159 crashlog.iframe->rax,
160 crashlog.iframe->rbx,
161 crashlog.iframe->rcx,
162 crashlog.iframe->rdx,
163 crashlog.iframe->rsi,
164 crashlog.iframe->rdi,
165 crashlog.iframe->rbp,
166 crashlog.iframe->user_sp,
167 crashlog.iframe->r8,
168 crashlog.iframe->r9,
169 crashlog.iframe->r10,
170 crashlog.iframe->r11,
171 crashlog.iframe->r12,
172 crashlog.iframe->r13,
173 crashlog.iframe->r14,
174 crashlog.iframe->r15,
175 crashlog.iframe->err_code);
176 if (len > remain) {
177 return out_len;
178 }
179 remain -= len;
180 buf += len;
181 #endif
182 }
183
184 len = snprintf(buf, remain, "BACKTRACE (up to 16 calls)\n");
185 if (len > remain) {
186 return out_len;
187 }
188 remain -= len;
189 buf += len;
190
191 len = thread_append_current_backtrace(buf, remain);
192 if (len > remain) {
193 return out_len;
194 }
195 remain -= len;
196 buf += len;
197
198 len = snprintf(buf, remain, "\n");
199 if (len > remain) {
200 return out_len;
201 }
202 remain -= len;
203 buf += len;
204
205 return out_len - remain;
206 }
207