1 IMPLEMENTATION[ia32,amd64,ux]:
9 #include "jdb_kobject.h"
10 #include "jdb_lines.h"
11 #include "jdb_module.h"
12 #include "jdb_symbol.h"
13 #include "mem_layout.h"
15 #include "thread_object.h"
18 class Jdb_bt : public Jdb_module, public Jdb_input_task_addr
24 static char first_char;
25 static char first_char_addr;
28 static Kobject *ko_tid;
33 char Jdb_bt::first_char;
34 char Jdb_bt::first_char_addr;
38 Kobject *Jdb_bt::ko_tid;
40 // determine the user level ebp and eip considering the current thread state
42 Jdb_bt::get_user_eip_ebp(Address &eip, Address &ebp)
46 // kernel thread doesn't execute user code -- at least we hope so :-)
52 Address tcb_next = (Address)context_of(t->get_kernel_sp()) + Context::size;
53 Mword *ktop = (Mword *)(Cpu::stack_align(tcb_next));
54 Jdb::Guessed_thread_state state = Jdb::guess_thread_state(t);
58 if (state == Jdb::s_ipc)
60 // If thread is in IPC, EBP lays on the stack (see C-bindings). EBP
61 // location is by now dependent from ipc-type, maybe different for
62 // other syscalls, maybe unstable during calls but only for user EBP.
63 Mword entry_esp = ktop[-2];
64 Mword entry_ss = ktop[-1];
68 // kernel entered from user level
69 if (eip >= Mem_layout::Syscalls)
71 if ((entry_esp & (sizeof(Mword)-1))
72 || !Jdb::peek((Address*)entry_esp, task, eip))
74 printf("\n esp page invalid");
78 entry_esp += sizeof(Mword);
81 if ((entry_esp & (sizeof(Mword)-1))
82 ||!Jdb::peek((Mword*)entry_esp, task, ebp))
84 printf("\n esp page invalid");
90 else if (state == Jdb::s_pagefault)
92 // see pagefault handler gate stack layout
95 else if (state == Jdb::s_slowtrap)
97 // see slowtrap handler gate stack layout
102 // Thread is doing (probaly) no IPC currently so we guess the
103 // user ebp by following the kernel ebp upwards. Some kernel
104 // entry pathes (e.g. timer interrupt) push the ebp register
106 ebp = get_user_ebp_following_kernel_stack();
112 Jdb_bt::get_user_ebp_following_kernel_stack()
114 if (!Config::Have_frame_ptr)
119 get_kernel_eip_ebp(dummy, dummy, ebp);
121 for (int i=0; i<30 /* sanity check */; i++)
125 if ( (ebp == 0) || (ebp & (sizeof(Mword)-1))
126 || !Jdb::peek((Address*)ebp, 0 /*kernel*/, m1)
127 || !Jdb::peek((Address*)ebp+1, 0 /*kernel*/, m2))
128 // invalid ebp -- leaving
133 if (!Mem_layout::in_kernel_code(m2))
135 if (m2 < Kmem::mem_user_max)
136 // valid user ebp found
151 mutable unsigned cpu;
153 void operator () (unsigned _cpu) const
155 Thread *t = Jdb::get_thread(_cpu);
157 { c = t; cpu = _cpu; }
163 Jdb_bt::get_kernel_eip_ebp(Mword &eip1, Mword &eip2, Mword &ebp)
165 if (tid == Jdb::get_current_active())
167 ebp = (Mword)__builtin_frame_address(3);
172 Is_current is_current;
174 is_current.tid = tid;
178 Jdb::foreach_cpu(is_current);
185 ksp = (Mword*)Jdb::entry_frame.cpu(is_current.cpu)->sp();
186 tcb = (Mword)is_current.c;
187 printf("\n current on cpu %u\n", is_current.cpu);
191 ksp = (Mword*) tid->get_kernel_sp();
192 tcb = Mword(tid); //Mem_layout::Tcbs + tid.gthread()*Context::size;
195 Mword tcb_next = tcb + Context::size;
197 // search for valid ebp/eip
198 for (int i=0; (Address)(ksp+i+1)<tcb_next-20; i++)
200 if (Mem_layout::in_kernel_code(ksp[i+1]) &&
201 ksp[i] >= tcb+0x180 &&
202 ksp[i] < tcb_next-20 &&
203 ksp[i] > (Address)(ksp+i))
205 // valid frame pointer found
212 ebp = eip1 = eip2 = 0;
216 /** Show one backtrace item we found. Add symbol name and line info */
218 Jdb_bt::show_item(int nr, Address ksp, Address addr, Address_type user)
222 printf(" %s#%d "L4_PTR_FMT" "L4_PTR_FMT"", nr<10 ? " ": "", nr, ksp, addr);
224 Address sym_addr = addr;
225 if (Jdb_symbol::match_addr_to_symbol_fuzzy(&sym_addr,
226 user == ADDR_KERNEL ? 0 : task,
229 ? 56 : sizeof(buffer))
230 // if the previous symbol is to far away assume that there is no
231 // symbol for that entry
232 && (addr-sym_addr < 1024))
234 printf(" : %s", buffer);
236 printf(" %s+ 0x%lx\033[m", Jdb::esc_line, addr-sym_addr);
239 // search appropriate line backwards starting from addr-1 because we
240 // don't want to see the line info for the next statement after the
241 // call but the line info for the call itself
242 Address line_addr = addr-1;
243 if (Jdb_lines::match_addr_to_line_fuzzy(&line_addr,
244 user == ADDR_KERNEL ? 0 : task,
245 buffer, sizeof(buffer)-1, 0)
246 // if the previous line is to far away assume that there is no
247 // line for that entry
248 && (addr-line_addr < 128))
249 printf("\n%6s%s%s\033[m", "", Jdb::esc_line, buffer);
255 Jdb_bt::show_without_ebp()
257 Mword *ksp = (Mword*) tid->get_kernel_sp();
258 Mword tcb_next = Mword(tid) + Context::size;
260 // search for valid eip
261 for (int i=0, j=1; (Address)(ksp+i)<tcb_next-20; i++)
263 if (Mem_layout::in_kernel_code(ksp[i]))
264 show_item(j++, (Address)(ksp+i), ksp[i], ADDR_KERNEL);
269 Jdb_bt::show(Mword ebp, Mword eip1, Mword eip2, Address_type user)
271 for (int i=0; i<40 /*sanity check*/; i++)
277 if ( (ebp == 0) || (ebp & (sizeof(Mword)-1))
278 || !Jdb::peek((Address*)ebp, task, m1)
279 || !Jdb::peek((Address*)ebp+1, task, m2))
280 // invalid ebp -- leaving
285 if ( (user==ADDR_KERNEL && !Mem_layout::in_kernel_code(m2))
286 ||(user==ADDR_USER && (m2==0 || m2>Kmem::mem_user_max)))
287 // no valid eip found -- leaving
303 show_item(i, ebp, m2, user);
308 Jdb_module::Action_code
309 Jdb_bt::action(int cmd, void *&args, char const *&fmt, int &next_char)
317 // default value for thread
318 tid = Jdb::get_current_active();
323 else if (args == &first_char)
325 if (first_char == 't')
327 putstr("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\033[K");
332 else if (first_char == 'a')
334 putstr("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\033[K");
336 args = &Jdb_input_task_addr::first_char;
339 else if (first_char != KEY_RETURN && first_char != ' ')
341 // ignore wrong input
346 // backtrace from current thread
347 goto start_backtrace;
349 else if (args == &ko_tid)
356 tid = Kobject::dcast<Thread_object*>(o);
360 puts(" Invalid thread id");
367 get_user_eip_ebp(eip, ebp);
369 start_backtrace_known_ebp:
370 printf("\n\nbacktrace (thread %lx, fp="L4_PTR_FMT
371 ", pc="L4_PTR_FMT"):\n",
372 tid->dbg_info()->dbg_id(), ebp, eip);
374 show(ebp, eip, 0, ADDR_USER);
375 if (!Config::Have_frame_ptr)
377 puts("\n --kernel-bt-follows-- "
378 "(don't trust w/o frame pointer!!)");
385 puts("\n --kernel-bt-follows--");
386 get_kernel_eip_ebp(eip, eip2, ebp);
388 show(ebp, eip, eip2, ADDR_KERNEL);
394 Jdb_module::Action_code code;
396 switch ((code = Jdb_input_task_addr::action(args, fmt, next_char)))
401 task = Jdb_input_task_addr::space();
403 ebp = Jdb_input_task_addr::addr();
404 goto start_backtrace_known_ebp;
414 Jdb_module::Cmd const *
419 { 0, "bt", "backtrace", " [a]ddr/[t]hread",
420 "bt[t<threadid>][<addr>]\tshow backtrace of current/given "
429 Jdb_bt::num_cmds() const
439 static Jdb_bt jdb_bt INIT_PRIORITY(JDB_MODULE_INIT_PRIO);