xref: /haiku/src/system/kernel/arch/arm/arch_debug.cpp (revision 4535495d80c86e19e2610e7444a4fcefe3e0f8e6)
1 /*
2  * Copyright 2003-2011, Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  * 		Axel Dörfler <axeld@pinc-software.de>
7  * 		Ingo Weinhold <bonefish@cs.tu-berlin.de>
8  * 		François Revol <revol@free.fr>
9  */
10 
11 
12 #include <arch/debug.h>
13 
14 #include <arch_cpu.h>
15 #include <debug.h>
16 #include <elf.h>
17 #include <kernel.h>
18 #include <kimage.h>
19 #include <thread.h>
20 
21 
22 struct stack_frame {
23 	struct stack_frame	*previous;
24 	addr_t				return_address;
25 };
26 
27 #define NUM_PREVIOUS_LOCATIONS 32
28 
29 extern struct iframe_stack gBootFrameStack;
30 /*
31 
32 static bool
33 already_visited(uint32 *visited, int32 *_last, int32 *_num, uint32 framePointer)
34 {
35 	int32 last = *_last;
36 	int32 num = *_num;
37 	int32 i;
38 
39 	for (i = 0; i < num; i++) {
40 		if (visited[(NUM_PREVIOUS_LOCATIONS + last - i)
41 				% NUM_PREVIOUS_LOCATIONS] == framePointer) {
42 			return true;
43 		}
44 	}
45 
46 	*_last = last = (last + 1) % NUM_PREVIOUS_LOCATIONS;
47 	visited[last] = framePointer;
48 
49 	if (num < NUM_PREVIOUS_LOCATIONS)
50 		*_num = num + 1;
51 
52 	return false;
53 }
54 
55 
56 static inline stack_frame *
57 get_current_stack_frame()
58 {
59 	stack_frame *frame;
60 	asm volatile("move.l %%fp,%0" : "=r"(frame));
61 	return frame;
62 }
63 
64 
65 static status_t
66 get_next_frame(addr_t framePointer, addr_t *next, addr_t *ip)
67 {
68 	Thread *thread = thread_get_current_thread();
69 	addr_t oldFaultHandler = thread->fault_handler;
70 
71 	// set fault handler, so that we can safely access user stacks
72 	if (thread) {
73 		if (m68k_set_fault_handler(&thread->fault_handler, (addr_t)&&error))
74 			goto error;
75 	}
76 
77 	*ip = ((struct stack_frame *)framePointer)->return_address;
78 	*next = (addr_t)((struct stack_frame *)framePointer)->previous;
79 
80 	if (thread)
81 		thread->fault_handler = oldFaultHandler;
82 	return B_OK;
83 
84 error:
85 	thread->fault_handler = oldFaultHandler;
86 	return B_BAD_ADDRESS;
87 }
88 
89 
90 static void
91 print_stack_frame(Thread *thread, addr_t ip, addr_t framePointer,
92 	addr_t nextFramePointer)
93 {
94 	addr_t diff = nextFramePointer - framePointer;
95 
96 	// kernel space/user space switch
97 	if (diff & 0x80000000)
98 		diff = 0;
99 
100 	// lookup symbol
101 	const char *symbol, *image;
102 	addr_t baseAddress;
103 	bool exactMatch;
104 	status_t status = elf_debug_lookup_symbol_address(ip, &baseAddress, &symbol,
105 		&image, &exactMatch);
106 	if (status != B_OK && !IS_KERNEL_ADDRESS(ip) && thread) {
107 		// try to locate the image in the images loaded into user space
108 		status = image_debug_lookup_user_symbol_address(thread->team, ip,
109 			&baseAddress, &symbol, &image, &exactMatch);
110 	}
111 	if (status == B_OK) {
112 		if (symbol != NULL) {
113 			kprintf("%08lx (+%4ld) %08lx   <%s>:%s + 0x%04lx%s\n", framePointer,
114 				diff, ip, image, symbol, ip - baseAddress,
115 				(exactMatch ? "" : " (nearest)"));
116 		} else {
117 			kprintf("%08lx (+%4ld) %08lx   <%s@%p>:unknown + 0x%04lx\n",
118 				framePointer, diff, ip, image, (void *)baseAddress,
119 				ip - baseAddress);
120 		}
121 	} else
122 		kprintf("%08lx (+%4ld) %08lx\n", framePointer, diff, ip);
123 }
124 
125 
126 static int
127 stack_trace(int argc, char **argv)
128 {
129 	uint32 previousLocations[NUM_PREVIOUS_LOCATIONS];
130 	struct iframe_stack *frameStack;
131 	Thread *thread;
132 	addr_t framePointer;
133 	int32 i, num = 0, last = 0;
134 
135 	if (argc < 2) {
136 		thread = thread_get_current_thread();
137 		framePointer = (addr_t)get_current_stack_frame();
138 	} else {
139 kprintf("Stack traces of other threads not supported yet!\n");
140 return 0;
141 	}
142 
143 	// We don't have a thread pointer early in the boot process
144 	if (thread != NULL)
145 		frameStack = &thread->arch_info.iframes;
146 	else
147 		frameStack = &gBootFrameStack;
148 
149 	for (i = 0; i < frameStack->index; i++) {
150 		kprintf("iframe %p (end = %p)\n",
151 			frameStack->frames[i], frameStack->frames[i] + 1);
152 	}
153 
154 	if (thread != NULL) {
155 		kprintf("stack trace for thread 0x%lx \"%s\"\n", thread->id,
156 			thread->name);
157 
158 		kprintf("    kernel stack: %p to %p\n",
159 			(void *)thread->kernel_stack_base,
160 			(void *)(thread->kernel_stack_top));
161 		if (thread->user_stack_base != 0) {
162 			kprintf("      user stack: %p to %p\n",
163 				(void *)thread->user_stack_base,
164 				(void *)(thread->user_stack_base + thread->user_stack_size));
165 		}
166 	}
167 
168 	kprintf("frame            caller     <image>:function + offset\n");
169 
170 	for (;;) {
171 		// see if the frame pointer matches the iframe
172 		struct iframe *frame = NULL;
173 		for (i = 0; i < frameStack->index; i++) {
174 			if (framePointer == (addr_t)frameStack->frames[i]) {
175 				// it's an iframe
176 				frame = frameStack->frames[i];
177 				break;
178 			}
179 		}
180 
181 		if (frame) {
182 			kprintf("iframe at %p\n", frame);
183 			kprintf("   d0 0x%08lx    d1 0x%08lx    d2 0x%08lx    d3 0x%08lx\n",
184 				frame->d[0], frame->d[1], frame->d[2], frame->d[3]);
185 			kprintf("   d4 0x%08lx    d5 0x%08lx    d6 0x%08lx    d7 0x%08lx\n",
186 				frame->d[4], frame->d[5], frame->d[6], frame->d[7]);
187 			kprintf("   a0 0x%08lx    a1 0x%08lx    a2 0x%08lx    a3 0x%08lx\n",
188 				frame->a[0], frame->a[1], frame->a[2], frame->a[3]);
189 			kprintf("   a4 0x%08lx    a5 0x%08lx    a6 0x%08lx    a7 0x%08lx (sp)\n",
190 #warning M68K: a7 in iframe ??
191 				frame->a[4], frame->a[5], frame->a[6], -1L);
192 			kprintf("   pc 0x%08lx        sr 0x%04x\n",
193 				frame->cpu.pc, frame->cpu.sr);
194 #warning M68K: missing regs
195 
196 			print_stack_frame(thread, frame->cpu.pc, framePointer, frame->a[6]);
197  			framePointer = frame->a[6];
198 		} else {
199 			addr_t ip, nextFramePointer;
200 
201 			if (get_next_frame(framePointer, &nextFramePointer, &ip) != B_OK) {
202 				kprintf("%08lx -- read fault\n", framePointer);
203 				break;
204 			}
205 
206 			if (ip == 0 || framePointer == 0)
207 				break;
208 
209 			print_stack_frame(thread, ip, framePointer, nextFramePointer);
210 			framePointer = nextFramePointer;
211 		}
212 
213 		if (already_visited(previousLocations, &last, &num, framePointer)) {
214 			kprintf("circular stack frame: %p!\n", (void *)framePointer);
215 			break;
216 		}
217 		if (framePointer == 0)
218 			break;
219 	}
220 
221 
222 	return 0;
223 }
224 
225 */
226 
227 // #pragma mark -
228 
229 
230 void
231 arch_debug_save_registers(struct arch_debug_registers* registers)
232 {
233 }
234 
235 
236 bool
237 arch_debug_contains_call(Thread *thread, const char *symbol,
238 	addr_t start, addr_t end)
239 {
240 	return false;
241 }
242 
243 
244 void
245 arch_debug_stack_trace(void)
246 {
247 }
248 
249 
250 void *
251 arch_debug_get_caller(void)
252 {
253 #warning ARM:IMPLEMENT
254 	// TODO: implement me
255 	//return __builtin_frame_address(1);
256 //	struct stack_frame *frame;
257 	//frame = __builtin_frame_address(0);
258 //	frame = get_current_stack_frame();
259 //	return (void *)frame->previous->return_address;
260 	return NULL;
261 }
262 
263 
264 int32
265 arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount,
266 	int32 skipIframes, int32 skipFrames, uint32 flags)
267 {
268 #warning ARM:IMPLEMENT
269 
270 	return 0;
271 }
272 
273 
274 void*
275 arch_debug_get_interrupt_pc(bool* _isSyscall)
276 {
277 	// TODO: Implement!
278 	return NULL;
279 }
280 
281 
282 bool
283 arch_is_debug_variable_defined(const char* variableName)
284 {
285 	// TODO: Implement!
286 	return false;
287 }
288 
289 
290 status_t
291 arch_set_debug_variable(const char* variableName, uint64 value)
292 {
293 	// TODO: Implement!
294 	return B_ENTRY_NOT_FOUND;
295 }
296 
297 
298 status_t
299 arch_get_debug_variable(const char* variableName, uint64* value)
300 {
301 	// TODO: Implement!
302 	return B_ENTRY_NOT_FOUND;
303 }
304 
305 
306 status_t
307 arch_debug_init(kernel_args *args)
308 {
309 //	add_debugger_command("where", &stack_trace, "Same as \"sc\"");
310 //	add_debugger_command("bt", &stack_trace, "Same as \"sc\" (as in gdb)");
311 //	add_debugger_command("sc", &stack_trace, "Stack crawl for current thread");
312 #warning ARM:IMPLEMENT
313 
314 	return B_NO_ERROR;
315 }
316 
317 
318 void
319 arch_debug_call_with_fault_handler(cpu_ent* cpu, jmp_buf jumpBuffer,
320 	void (*function)(void*), void* parameter)
321 {
322 	// TODO: Implement fault handling! Most likely in assembly.
323 	// (see src/system/kernel/arch/x86/arch_x86.S)
324 
325 	// For now, just call the function and hope we don't crash :P
326 	function(parameter);
327 }
328 
329 
330 void
331 arch_debug_unset_current_thread(void)
332 {
333 	// TODO: Implement!
334 }
335 
336 
337