1 IMPLEMENTATION[ia32,amd64,ux]:
9 #include "jdb_input_task.h"
10 #include "jdb_kobject.h"
11 #include "jdb_lines.h"
12 #include "jdb_module.h"
13 #include "jdb_symbol.h"
14 #include "mem_layout.h"
16 #include "thread_object.h"
19 class Jdb_bt : public Jdb_module, public Jdb_input_task_addr
25 static char first_char;
26 static char first_char_addr;
29 static Kobject *ko_tid;
34 char Jdb_bt::first_char;
35 char Jdb_bt::first_char_addr;
39 Kobject *Jdb_bt::ko_tid;
41 // determine the user level ebp and eip considering the current thread state
43 Jdb_bt::get_user_eip_ebp(Address &eip, Address &ebp)
47 // kernel thread doesn't execute user code -- at least we hope so :-)
53 Address tcb_next = (Address)context_of(t->get_kernel_sp()) + Context::Size;
54 Mword *ktop = (Mword *)(Cpu::stack_align(tcb_next));
55 Jdb::Guessed_thread_state state = Jdb::guess_thread_state(t);
59 if (state == Jdb::s_ipc)
61 // If thread is in IPC, EBP lays on the stack (see C-bindings). EBP
62 // location is by now dependent from ipc-type, maybe different for
63 // other syscalls, maybe unstable during calls but only for user EBP.
64 Mword entry_esp = ktop[-2];
65 Mword entry_ss = ktop[-1];
69 // kernel entered from user level
70 if (eip >= Mem_layout::Syscalls)
72 if ((entry_esp & (sizeof(Mword)-1))
73 || !Jdb::peek((Address*)entry_esp, task, eip))
75 printf("\n esp page invalid");
79 entry_esp += sizeof(Mword);
82 if ((entry_esp & (sizeof(Mword)-1))
83 ||!Jdb::peek((Mword*)entry_esp, task, ebp))
85 printf("\n esp page invalid");
91 else if (state == Jdb::s_pagefault)
93 // see pagefault handler gate stack layout
96 else if (state == Jdb::s_slowtrap)
98 // see slowtrap handler gate stack layout
103 // Thread is doing (probaly) no IPC currently so we guess the
104 // user ebp by following the kernel ebp upwards. Some kernel
105 // entry pathes (e.g. timer interrupt) push the ebp register
107 ebp = get_user_ebp_following_kernel_stack();
113 Jdb_bt::get_user_ebp_following_kernel_stack()
115 if (!Config::Have_frame_ptr)
120 get_kernel_eip_ebp(dummy, dummy, ebp);
122 for (int i=0; i<30 /* sanity check */; i++)
126 if ( (ebp == 0) || (ebp & (sizeof(Mword)-1))
127 || !Jdb::peek((Address*)ebp, 0 /*kernel*/, m1)
128 || !Jdb::peek((Address*)ebp+1, 0 /*kernel*/, m2))
129 // invalid ebp -- leaving
134 if (!Mem_layout::in_kernel_code(m2))
136 if (m2 <= Mem_layout::User_max)
137 // valid user ebp found
152 mutable Cpu_number cpu;
154 void operator () (Cpu_number _cpu) const
156 Thread *t = Jdb::get_thread(_cpu);
158 { c = t; cpu = _cpu; }
164 Jdb_bt::get_kernel_eip_ebp(Mword &eip1, Mword &eip2, Mword &ebp)
166 if (tid == Jdb::get_current_active())
168 ebp = (Mword)__builtin_frame_address(3);
173 Is_current is_current;
175 is_current.tid = tid;
177 is_current.cpu = Cpu_number::boot_cpu();
179 Jdb::foreach_cpu(is_current);
186 ksp = (Mword*)Jdb::entry_frame.cpu(is_current.cpu)->sp();
187 tcb = (Mword)is_current.c;
188 printf("\n current on cpu %u\n",
189 cxx::int_value<Cpu_number>(is_current.cpu));
193 ksp = (Mword*) tid->get_kernel_sp();
194 tcb = Mword(tid); //Mem_layout::Tcbs + tid.gthread()*Context::size;
197 Mword tcb_next = tcb + Context::Size;
199 // search for valid ebp/eip
200 for (int i=0; (Address)(ksp+i+1)<tcb_next-20; i++)
202 if (Mem_layout::in_kernel_code(ksp[i+1]) &&
203 ksp[i] >= tcb+0x180 &&
204 ksp[i] < tcb_next-20 &&
205 ksp[i] > (Address)(ksp+i))
207 // valid frame pointer found
214 ebp = eip1 = eip2 = 0;
218 /** Show one backtrace item we found. Add symbol name and line info */
220 Jdb_bt::show_item(int nr, Address ksp, Address addr, Address_type user)
224 printf(" %s#%d " L4_PTR_FMT " " L4_PTR_FMT "", nr<10 ? " ": "", nr, ksp, addr);
226 Address sym_addr = addr;
227 if (Jdb_symbol::match_addr_to_symbol_fuzzy(&sym_addr,
228 user == ADDR_KERNEL ? 0 : task,
231 ? 56 : sizeof(buffer))
232 // if the previous symbol is to far away assume that there is no
233 // symbol for that entry
234 && (addr-sym_addr < 1024))
236 printf(" : %s", buffer);
238 printf(" %s+ 0x%lx\033[m", Jdb::esc_line, addr-sym_addr);
241 // search appropriate line backwards starting from addr-1 because we
242 // don't want to see the line info for the next statement after the
243 // call but the line info for the call itself
244 Address line_addr = addr-1;
245 if (Jdb_lines::match_addr_to_line_fuzzy(&line_addr,
246 user == ADDR_KERNEL ? 0 : task,
247 buffer, sizeof(buffer)-1, 0)
248 // if the previous line is to far away assume that there is no
249 // line for that entry
250 && (addr-line_addr < 128))
251 printf("\n%6s%s%s\033[m", "", Jdb::esc_line, buffer);
257 Jdb_bt::show_without_ebp()
259 Mword *ksp = (Mword*) tid->get_kernel_sp();
260 Mword tcb_next = Mword(tid) + Context::Size;
262 // search for valid eip
263 for (int i=0, j=1; (Address)(ksp+i)<tcb_next-20; i++)
265 if (Mem_layout::in_kernel_code(ksp[i]))
266 show_item(j++, (Address)(ksp+i), ksp[i], ADDR_KERNEL);
271 Jdb_bt::show(Mword ebp, Mword eip1, Mword eip2, Address_type user)
273 for (int i=0; i<40 /*sanity check*/; i++)
279 if ( (ebp == 0) || (ebp & (sizeof(Mword)-1))
280 || !Jdb::peek((Address*)ebp, task, m1)
281 || !Jdb::peek((Address*)ebp+1, task, m2))
282 // invalid ebp -- leaving
287 if ( (user==ADDR_KERNEL && !Mem_layout::in_kernel_code(m2))
288 ||(user==ADDR_USER && (m2==0 || m2 > Mem_layout::User_max)))
289 // no valid eip found -- leaving
305 show_item(i, ebp, m2, user);
310 Jdb_module::Action_code
311 Jdb_bt::action(int cmd, void *&args, char const *&fmt, int &next_char)
319 // default value for thread
320 tid = Jdb::get_current_active();
325 else if (args == &first_char)
327 if (first_char == 't')
329 putstr("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\033[K");
334 else if (first_char == 'a')
336 putstr("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\033[K");
338 args = &Jdb_input_task_addr::first_char;
341 else if (first_char != KEY_RETURN && first_char != ' ')
343 // ignore wrong input
348 // backtrace from current thread
349 goto start_backtrace;
351 else if (args == &ko_tid)
358 tid = Kobject::dcast<Thread_object*>(o);
362 puts(" Invalid thread id");
369 get_user_eip_ebp(eip, ebp);
371 start_backtrace_known_ebp:
372 printf("\n\nbacktrace (thread %lx, fp=" L4_PTR_FMT
373 ", pc=" L4_PTR_FMT "):\n",
374 tid->dbg_info()->dbg_id(), ebp, eip);
376 show(ebp, eip, 0, ADDR_USER);
377 if (!Config::Have_frame_ptr)
379 puts("\n --kernel-bt-follows-- "
380 "(don't trust w/o frame pointer!!)");
387 puts("\n --kernel-bt-follows--");
388 get_kernel_eip_ebp(eip, eip2, ebp);
390 show(ebp, eip, eip2, ADDR_KERNEL);
396 Jdb_module::Action_code code;
398 switch ((code = Jdb_input_task_addr::action(args, fmt, next_char)))
403 task = Jdb_input_task_addr::space();
405 ebp = Jdb_input_task_addr::addr();
406 goto start_backtrace_known_ebp;
416 Jdb_module::Cmd const *
421 { 0, "bt", "backtrace", " [a]ddr/[t]hread",
422 "bt[t<threadid>][<addr>]\tshow backtrace of current/given "
431 Jdb_bt::num_cmds() const
441 static Jdb_bt jdb_bt INIT_PRIORITY(JDB_MODULE_INIT_PRIO);