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