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