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 17crashlog_t crashlog = {}; 18 19size_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