]> git.saurik.com Git - apple/xnu.git/blob - libkern/gen/OSDebug.cpp
f4c4d67605632e4cc1920ec9ec7227a3c946701e
[apple/xnu.git] / libkern / gen / OSDebug.cpp
1 /*
2 * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 // NOTE: This file is only c++ so I can get static initialisers going
30 #include <libkern/OSDebug.h>
31
32 #include <sys/cdefs.h>
33
34 #include <stdarg.h>
35 #include <mach/mach_types.h>
36 #include <mach/kmod.h>
37 #include <kern/lock.h>
38
39 #include <libkern/libkern.h> // From bsd's libkern directory
40
41 __BEGIN_DECLS
42 // From osmfk/kern/thread.h but considered to be private
43 extern vm_offset_t min_valid_stack_address(void);
44 extern vm_offset_t max_valid_stack_address(void);
45
46 // From osfmk/kmod.c
47 extern void kmod_dump_log(vm_offset_t *addr, unsigned int cnt);
48 __END_DECLS
49
50 static mutex_t *sOSReportLock = mutex_alloc(0);
51
52 /* Report a message with a 4 entry backtrace - very slow */
53 void
54 OSReportWithBacktrace(const char *str, ...)
55 {
56 char buf[128];
57 void *bt[9];
58 const unsigned cnt = sizeof(bt) / sizeof(bt[0]);
59 va_list listp;
60
61 // Ignore the our and our callers stackframes, skipping frames 0 & 1
62 (void) OSBacktrace(bt, cnt);
63
64 va_start(listp, str);
65 vsnprintf(buf, sizeof(buf), str, listp);
66 va_end(listp);
67
68 mutex_lock(sOSReportLock);
69 {
70 printf("%s\nBacktrace %p %p %p %p %p %p %p\n",
71 buf, bt[2], bt[3], bt[4], bt[5], bt[6], bt[7], bt[8]);
72 kmod_dump_log((vm_offset_t *) &bt[2], cnt - 2);
73 }
74 mutex_unlock(sOSReportLock);
75 }
76
77 static vm_offset_t minstackaddr = min_valid_stack_address();
78 static vm_offset_t maxstackaddr = max_valid_stack_address();
79
80 unsigned OSBacktrace(void **bt, unsigned maxAddrs)
81 {
82 unsigned frame;
83
84 #if __ppc__
85 vm_offset_t stackptr, stackptr_prev;
86 const vm_offset_t * const mem = (vm_offset_t *) 0;
87 unsigned i = 0;
88
89 __asm__ volatile("mflr %0" : "=r" (stackptr));
90 bt[i++] = (void *) stackptr;
91
92 __asm__ volatile("mr %0,r1" : "=r" (stackptr));
93 for ( ; i < maxAddrs; i++) {
94 // Validate we have a reasonable stackptr
95 if ( !(minstackaddr <= stackptr && stackptr < maxstackaddr)
96 || (stackptr & 3))
97 break;
98
99 stackptr_prev = stackptr;
100 stackptr = mem[stackptr_prev >> 2];
101 if ((stackptr_prev ^ stackptr) > 8 * 1024) // Sanity check
102 break;
103
104 vm_offset_t addr = mem[(stackptr >> 2) + 2];
105 if ((addr & 3) || (addr < 0x8000)) // More sanity checks
106 break;
107 bt[i] = (void *) addr;
108 }
109 frame = i;
110
111 for ( ; i < maxAddrs; i++)
112 bt[i] = (void *) 0;
113 #elif 0 && __i386__ // Note that this should be ported for i386
114 // This function is not safe, we should get this code ported appropriately
115 if (maxAddrs > 16) {
116 for (frame = 16; frame < maxAddrs; frame++)
117 bt[frame] = __builtin_return_address(frame);
118 maxAddrs = 16;
119 }
120
121 switch(maxAddrs) {
122 case 15+1: bt[15] = __builtin_return_address(15);
123 case 14+1: bt[14] = __builtin_return_address(14);
124 case 13+1: bt[13] = __builtin_return_address(13);
125 case 12+1: bt[12] = __builtin_return_address(12);
126 case 11+1: bt[11] = __builtin_return_address(11);
127 case 10+1: bt[10] = __builtin_return_address(10);
128 case 9+1: bt[ 9] = __builtin_return_address( 9);
129 case 8+1: bt[ 8] = __builtin_return_address( 8);
130 case 7+1: bt[ 7] = __builtin_return_address( 7);
131 case 6+1: bt[ 6] = __builtin_return_address( 6);
132 case 5+1: bt[ 5] = __builtin_return_address( 5);
133 case 4+1: bt[ 4] = __builtin_return_address( 4);
134 case 3+1: bt[ 3] = __builtin_return_address( 3);
135 case 2+1: bt[ 2] = __builtin_return_address( 2);
136 case 1+1: bt[ 1] = __builtin_return_address( 1);
137 case 0+1: bt[ 0] = __builtin_return_address( 0);
138 case 0: default: break;
139 }
140
141 frame = maxAddrs;
142 #else
143 // This function is not safe, we should get this code ported appropriately
144 if (maxAddrs > 16) {
145 for (frame = 16; frame < maxAddrs; frame++)
146 bt[frame] = 0;
147 maxAddrs = 16;
148 }
149
150 switch (maxAddrs) {
151 case 15+1: bt[15] = __builtin_return_address(15);
152 case 14+1: bt[14] = __builtin_return_address(14);
153 case 13+1: bt[13] = __builtin_return_address(13);
154 case 12+1: bt[12] = __builtin_return_address(12);
155 case 11+1: bt[11] = __builtin_return_address(11);
156 case 10+1: bt[10] = __builtin_return_address(10);
157 case 9+1: bt[ 9] = __builtin_return_address( 9);
158 case 8+1: bt[ 8] = __builtin_return_address( 8);
159 case 7+1: bt[ 7] = __builtin_return_address( 7);
160 case 6+1: bt[ 6] = __builtin_return_address( 6);
161 case 5+1: bt[ 5] = __builtin_return_address( 5);
162 case 4+1: bt[ 4] = __builtin_return_address( 4);
163 case 3+1: bt[ 3] = __builtin_return_address( 3);
164 case 2+1: bt[ 2] = __builtin_return_address( 2);
165 case 1+1: bt[ 1] = __builtin_return_address( 1);
166 case 0+1: bt[ 0] = __builtin_return_address( 0);
167 case 0:
168 default :
169 break;
170 }
171
172 frame = maxAddrs;
173 #endif
174
175 return frame;
176 }