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