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