1 // Copyright 2016 The Fuchsia Authors
2 // Copyright (c) 2008-2015 Travis Geiselbrecht
3 //
4 // Use of this source code is governed by a MIT-style
5 // license that can be found in the LICENSE file or at
6 // https://opensource.org/licenses/MIT
7
8 #include <arch/ops.h>
9 #include <ctype.h>
10 #include <debug.h>
11 #include <dev/hw_rng.h>
12 #include <kernel/spinlock.h>
13 #include <list.h>
14 #include <platform.h>
15 #include <platform/debug.h>
16 #include <printf.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <zircon/types.h>
20 #include <zircon/time.h>
21
spin(uint32_t usecs)22 void spin(uint32_t usecs) {
23 zx_time_t start = current_time();
24
25 zx_duration_t nsecs = ZX_USEC(usecs);
26 while (zx_time_sub_time(current_time(), start) < nsecs)
27 ;
28 }
29
_panic(void * caller,void * frame,const char * fmt,...)30 void _panic(void* caller, void* frame, const char* fmt, ...) {
31 platform_panic_start();
32
33 printf("panic (caller %p frame %p): ", caller, frame);
34
35 va_list ap;
36 va_start(ap, fmt);
37 vprintf(fmt, ap);
38 va_end(ap);
39
40 platform_halt(HALT_ACTION_HALT, HALT_REASON_SW_PANIC);
41 }
42
puts_for_panic(const char * msg,size_t len)43 static void puts_for_panic(const char *msg, size_t len)
44 {
45 __printf_output_func(msg, len, NULL);
46 }
47
_panic_no_format(const char * msg,size_t len)48 void _panic_no_format(const char *msg, size_t len) {
49 platform_panic_start();
50 puts_for_panic(msg, len);
51 platform_halt(HALT_ACTION_HALT, HALT_REASON_SW_PANIC);
52 }
53
__stack_chk_fail(void)54 void __stack_chk_fail(void) {
55 panic_no_format("stack canary corrupted!\n");
56 }
57
choose_stack_guard(void)58 uintptr_t choose_stack_guard(void) {
59 uintptr_t guard;
60 if (hw_rng_get_entropy(&guard, sizeof(guard), true) != sizeof(guard)) {
61 // We can't get a random value, so use a randomish value.
62 guard = 0xdeadbeef00ff00ffUL ^ (uintptr_t)&guard;
63 }
64 return guard;
65 }
66
67 #if !DISABLE_DEBUG_OUTPUT
68
hexdump_very_ex(const void * ptr,size_t len,uint64_t disp_addr,hexdump_print_fn_t * pfn)69 void hexdump_very_ex(const void* ptr, size_t len, uint64_t disp_addr, hexdump_print_fn_t* pfn) {
70 addr_t address = (addr_t)ptr;
71 size_t count;
72
73 for (count = 0; count < len; count += 16) {
74 union {
75 uint32_t buf[4];
76 uint8_t cbuf[16];
77 } u;
78 size_t s = ROUNDUP(MIN(len - count, 16), 4);
79 size_t i;
80
81 pfn(((disp_addr + len) > 0xFFFFFFFF)
82 ? "0x%016llx: "
83 : "0x%08llx: ",
84 disp_addr + count);
85
86 for (i = 0; i < s / 4; i++) {
87 u.buf[i] = ((const uint32_t*)address)[i];
88 pfn("%08x ", u.buf[i]);
89 }
90 for (; i < 4; i++) {
91 pfn(" ");
92 }
93 pfn("|");
94
95 for (i = 0; i < 16; i++) {
96 char c = u.cbuf[i];
97 if (i < s && isprint(c)) {
98 pfn("%c", c);
99 } else {
100 pfn(".");
101 }
102 }
103 pfn("|\n");
104 address += 16;
105 }
106 }
107
hexdump8_very_ex(const void * ptr,size_t len,uint64_t disp_addr,hexdump_print_fn_t * pfn)108 void hexdump8_very_ex(const void* ptr, size_t len, uint64_t disp_addr, hexdump_print_fn_t* pfn) {
109 addr_t address = (addr_t)ptr;
110 size_t count;
111 size_t i;
112
113 for (count = 0; count < len; count += 16) {
114 pfn(((disp_addr + len) > 0xFFFFFFFF)
115 ? "0x%016llx: "
116 : "0x%08llx: ",
117 disp_addr + count);
118
119 for (i = 0; i < MIN(len - count, 16); i++) {
120 pfn("%02hhx ", *(const uint8_t*)(address + i));
121 }
122
123 for (; i < 16; i++) {
124 pfn(" ");
125 }
126
127 pfn("|");
128
129 for (i = 0; i < MIN(len - count, 16); i++) {
130 char c = ((const char*)address)[i];
131 pfn("%c", isprint(c) ? c : '.');
132 }
133
134 pfn("\n");
135 address += 16;
136 }
137 }
138
139 #endif // !DISABLE_DEBUG_OUTPUT
140