Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8fb47446ed | ||
|
|
4e0373fe5e |
@@ -212,7 +212,7 @@ INTERFACES_JDB := jdb_handler_queue jdb_module jdb_pic \
|
||||
jdb_trace_set jdb_entry_frame \
|
||||
jdb_kobject jdb_kobject_names \
|
||||
jdb_util jdb_space jdb_utcb \
|
||||
jdb_trap_state jdb_ipi jdb_rcupdate jdb_bt \
|
||||
jdb_trap_state jdb_ipi jdb_rcupdate \
|
||||
jdb_ipc_gate jdb_obj_space jdb_log jdb_factory \
|
||||
jdb_thread jdb_scheduler jdb_sender_list\
|
||||
jdb_perf jdb_vm jdb_regex jdb_disasm jdb_bp \
|
||||
@@ -231,7 +231,6 @@ jdb_tcb_IMPL := jdb_tcb jdb_tcb-arm
|
||||
jdb_ptab_IMPL := jdb_ptab jdb_ptab-ia32-ux-arm jdb_ptab-arm
|
||||
jdb_entry_frame_IMPL := jdb_entry_frame-arm
|
||||
jdb_trace_set_IMPL := jdb_trace_set jdb_trace_set-arm
|
||||
jdb_bt_IMPL := jdb_bt-arm
|
||||
jdb_bp := jdb_bp
|
||||
thread_IMPL += thread-debug
|
||||
|
||||
|
||||
@@ -1,474 +0,0 @@
|
||||
IMPLEMENTATION[arm]:
|
||||
|
||||
/* jdb_bt-ia32-ux.cpp adapted for ARM */
|
||||
|
||||
#include <cstdio>
|
||||
#include <cctype>
|
||||
|
||||
#include "config.h"
|
||||
#include "jdb.h"
|
||||
#include "jdb_input.h"
|
||||
#include "jdb_kobject.h"
|
||||
#include "jdb_lines.h"
|
||||
#include "jdb_module.h"
|
||||
#include "jdb_symbol.h"
|
||||
#include "mem_layout.h"
|
||||
#include "keycodes.h"
|
||||
#include "thread_object.h"
|
||||
#include "task.h"
|
||||
|
||||
class Jdb_bt : public Jdb_module, public Jdb_input_task_addr
|
||||
{
|
||||
public:
|
||||
Jdb_bt() FIASCO_INIT;
|
||||
private:
|
||||
static char dummy;
|
||||
static char first_char;
|
||||
static char first_char_addr;
|
||||
static Address addr;
|
||||
static Thread * tid;
|
||||
static Kobject *ko_tid;
|
||||
static Space * task;
|
||||
};
|
||||
|
||||
char Jdb_bt::dummy;
|
||||
char Jdb_bt::first_char;
|
||||
char Jdb_bt::first_char_addr;
|
||||
Address Jdb_bt::addr;
|
||||
Thread * Jdb_bt::tid;
|
||||
Space *Jdb_bt::task;
|
||||
Kobject *Jdb_bt::ko_tid;
|
||||
|
||||
// determine the user level ebp and eip considering the current thread state
|
||||
static void
|
||||
Jdb_bt::get_user_eip_ebp(Address &eip, Address &ebp)
|
||||
{
|
||||
if (!task)
|
||||
{
|
||||
// kernel thread doesn't execute user code -- at least we hope so :-)
|
||||
ebp = eip = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
Thread *t = tid;
|
||||
Address tcb_next = (Address)context_of(t->get_kernel_sp()) + Context::Size;
|
||||
Mword *ktop = (Mword *)(Cpu::stack_align(tcb_next));
|
||||
#if 0
|
||||
Jdb::Guessed_thread_state state = Jdb::guess_thread_state(t);
|
||||
|
||||
eip = ktop[-5];
|
||||
#endif
|
||||
|
||||
eip = t->user_ip();
|
||||
ebp = ktop[-7]; /* r11 */
|
||||
|
||||
#if 0
|
||||
if (state == Jdb::s_ipc)
|
||||
{
|
||||
// If thread is in IPC, EBP lays on the stack (see C-bindings). EBP
|
||||
// location is by now dependent from ipc-type, maybe different for
|
||||
// other syscalls, maybe unstable during calls but only for user EBP.
|
||||
Mword entry_esp = ktop[-2];
|
||||
Mword entry_ss = ktop[-1];
|
||||
|
||||
if (entry_ss & 3)
|
||||
{
|
||||
// kernel entered from user level
|
||||
if (eip >= Mem_layout::Syscalls)
|
||||
{
|
||||
if ((entry_esp & (sizeof(Mword)-1))
|
||||
|| !Jdb::peek((Address*)entry_esp, task, eip))
|
||||
{
|
||||
printf("\n esp page invalid");
|
||||
ebp = eip = 0;
|
||||
return;
|
||||
}
|
||||
entry_esp += sizeof(Mword);
|
||||
}
|
||||
|
||||
if ((entry_esp & (sizeof(Mword)-1))
|
||||
||!Jdb::peek((Mword*)entry_esp, task, ebp))
|
||||
{
|
||||
printf("\n esp page invalid");
|
||||
ebp = eip = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (state == Jdb::s_pagefault)
|
||||
{
|
||||
// see pagefault handler gate stack layout
|
||||
ebp = ktop[-6];
|
||||
}
|
||||
else if (state == Jdb::s_slowtrap)
|
||||
{
|
||||
// see slowtrap handler gate stack layout
|
||||
ebp = ktop[-13];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Thread is doing (probaly) no IPC currently so we guess the
|
||||
// user ebp by following the kernel ebp upwards. Some kernel
|
||||
// entry pathes (e.g. timer interrupt) push the ebp register
|
||||
// like gcc.
|
||||
ebp = get_user_ebp_following_kernel_stack();
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
#if 0
|
||||
static Mword
|
||||
Jdb_bt::get_user_ebp_following_kernel_stack()
|
||||
{
|
||||
if (!Config::Have_frame_ptr)
|
||||
return 0;
|
||||
|
||||
Mword ebp, dummy;
|
||||
|
||||
get_kernel_eip_ebp(dummy, dummy, ebp);
|
||||
|
||||
for (int i=0; i<30 /* sanity check */; i++)
|
||||
{
|
||||
Mword m1, m2;
|
||||
|
||||
if ( (ebp == 0) || (ebp & (sizeof(Mword)-1))
|
||||
|| !Jdb::peek((Address*)ebp, 0 /*kernel*/, m1)
|
||||
|| !Jdb::peek((Address*)ebp+1, 0 /*kernel*/, m2))
|
||||
// invalid ebp -- leaving
|
||||
return 0;
|
||||
|
||||
ebp = m1;
|
||||
|
||||
if (!Mem_layout::in_kernel_code(m2))
|
||||
{
|
||||
#if 0
|
||||
if (m2 < Kmem::mem_user_max)
|
||||
// valid user ebp found
|
||||
return m1;
|
||||
else
|
||||
// invalid ebp
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
struct Is_current
|
||||
{
|
||||
Thread *tid;
|
||||
mutable Thread *c;
|
||||
mutable Cpu_number cpu;
|
||||
|
||||
void operator () (Cpu_number _cpu) const
|
||||
{
|
||||
Thread *t = Jdb::get_thread(_cpu);
|
||||
if (t == tid)
|
||||
{ c = t; cpu = _cpu; }
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
static void
|
||||
Jdb_bt::get_kernel_eip_ebp(Mword &eip1, Mword &eip2, Mword &ebp)
|
||||
{
|
||||
if (tid == Jdb::get_current_active())
|
||||
{
|
||||
ebp = (Mword)__builtin_frame_address(3);
|
||||
eip1 = eip2 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Is_current is_current;
|
||||
|
||||
is_current.tid = tid;
|
||||
is_current.c = 0;
|
||||
is_current.cpu = Cpu_number(0);
|
||||
|
||||
Jdb::foreach_cpu(is_current);
|
||||
|
||||
Mword *ksp;
|
||||
Mword tcb;
|
||||
|
||||
if (is_current.c)
|
||||
{
|
||||
ksp = (Mword*)Jdb::entry_frame.cpu(is_current.cpu)->sp();
|
||||
tcb = (Mword)is_current.c;
|
||||
printf("\n current on cpu %u\n", cxx::int_value<Cpu_number>(is_current.cpu));
|
||||
}
|
||||
else
|
||||
{
|
||||
ksp = (Mword*) tid->get_kernel_sp();
|
||||
tcb = Mword(tid); //Mem_layout::Tcbs + tid.gthread()*Context::size;
|
||||
}
|
||||
|
||||
Mword tcb_next = tcb + Context::Size;
|
||||
|
||||
// search for valid ebp/eip
|
||||
for (int i=0; (Address)(ksp+i+1)<tcb_next-20; i++)
|
||||
{
|
||||
if (Mem_layout::in_kernel_code(ksp[i+1]) &&
|
||||
ksp[i] >= tcb+0x180 &&
|
||||
ksp[i] < tcb_next-20 &&
|
||||
ksp[i] > (Address)(ksp+i))
|
||||
{
|
||||
// valid frame pointer found
|
||||
ebp = ksp[i ];
|
||||
eip1 = ksp[i+1];
|
||||
eip2 = ksp[0];
|
||||
return;
|
||||
}
|
||||
}
|
||||
ebp = eip1 = eip2 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Show one backtrace item we found. Add symbol name and line info */
|
||||
static void
|
||||
Jdb_bt::show_item(int nr, Address ksp, Address addr, Address_type user)
|
||||
{
|
||||
char buffer[74];
|
||||
|
||||
printf(" %s#%d " L4_PTR_FMT " " L4_PTR_FMT "", nr<10 ? " ": "", nr, ksp, addr);
|
||||
|
||||
Address sym_addr = addr;
|
||||
if (Jdb_symbol::match_addr_to_symbol_fuzzy(&sym_addr,
|
||||
user == ADDR_KERNEL ? 0 : task,
|
||||
buffer,
|
||||
56 < sizeof(buffer)
|
||||
? 56 : sizeof(buffer))
|
||||
// if the previous symbol is to far away assume that there is no
|
||||
// symbol for that entry
|
||||
&& (addr-sym_addr < 1024))
|
||||
{
|
||||
printf(" : %s", buffer);
|
||||
if (addr-sym_addr)
|
||||
printf(" %s+ 0x%lx\033[m", Jdb::esc_line, addr-sym_addr);
|
||||
}
|
||||
#if 0
|
||||
// search appropriate line backwards starting from addr-1 because we
|
||||
// don't want to see the line info for the next statement after the
|
||||
// call but the line info for the call itself
|
||||
Address line_addr = addr-1;
|
||||
if (Jdb_lines::match_addr_to_line_fuzzy(&line_addr,
|
||||
user == ADDR_KERNEL ? 0 : task,
|
||||
buffer, sizeof(buffer)-1, 0)
|
||||
// if the previous line is to far away assume that there is no
|
||||
// line for that entry
|
||||
&& (addr-line_addr < 128))
|
||||
printf("\n%6s%s%s\033[m", "", Jdb::esc_line, buffer);
|
||||
#endif
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
static void
|
||||
Jdb_bt::show_without_ebp()
|
||||
{
|
||||
Mword *ksp = (Mword*) tid->get_kernel_sp();
|
||||
Mword tcb_next = Mword(tid) + Context::Size;
|
||||
|
||||
// search for valid eip
|
||||
for (int i=0, j=1; (Address)(ksp+i)<tcb_next-20; i++)
|
||||
{
|
||||
if (Mem_layout::in_kernel_code(ksp[i]))
|
||||
show_item(j++, (Address)(ksp+i), ksp[i], ADDR_KERNEL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
Jdb_bt::show(Mword ebp, Mword eip1, Mword eip2, Address_type user)
|
||||
{
|
||||
for (int i=0; i<40 /*sanity check*/; i++)
|
||||
{
|
||||
Mword m1, m2;
|
||||
|
||||
if (i > 1)
|
||||
{
|
||||
/* stack layout:
|
||||
*
|
||||
* lr1 <-
|
||||
* fp1 |
|
||||
* ... |
|
||||
* lr2 |
|
||||
* fp2 --
|
||||
*/
|
||||
if ( (ebp == 0) || (ebp & (sizeof(Mword)-1))
|
||||
|| !Jdb::peek((Address*)ebp-1, task, m1)
|
||||
|| !Jdb::peek((Address*)ebp, task, m2))
|
||||
// invalid ebp -- leaving
|
||||
return;
|
||||
|
||||
ebp = m1;
|
||||
#if 0
|
||||
if ( (user==ADDR_KERNEL && !Mem_layout::in_kernel_code(m2))
|
||||
||(user==ADDR_USER && (m2==0 || m2>Kmem::mem_user_max)))
|
||||
// no valid eip found -- leaving
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
else if (i == 1)
|
||||
{
|
||||
if (eip1 == 0)
|
||||
continue;
|
||||
m2 = eip1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (eip2 == 0)
|
||||
continue;
|
||||
m2 = eip2;
|
||||
}
|
||||
|
||||
show_item(i, ebp, m2, user);
|
||||
}
|
||||
}
|
||||
|
||||
PUBLIC
|
||||
Jdb_module::Action_code
|
||||
Jdb_bt::action(int cmd, void *&args, char const *&fmt, int &next_char)
|
||||
{
|
||||
if (cmd == 0)
|
||||
{
|
||||
Address eip, ebp;
|
||||
|
||||
if (args == &dummy)
|
||||
{
|
||||
// default value for thread
|
||||
tid = Jdb::get_current_active();
|
||||
fmt = "%C";
|
||||
args = &first_char;
|
||||
return EXTRA_INPUT;
|
||||
}
|
||||
else if (args == &first_char)
|
||||
{
|
||||
if (first_char == 't')
|
||||
{
|
||||
putstr("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\033[K");
|
||||
fmt = " thread=%q";
|
||||
args = &ko_tid;
|
||||
return EXTRA_INPUT;
|
||||
}
|
||||
else if (first_char == 'a')
|
||||
{
|
||||
putstr("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\033[K");
|
||||
fmt = " addr=%C";
|
||||
args = &Jdb_input_task_addr::first_char;
|
||||
return EXTRA_INPUT;
|
||||
}
|
||||
else if (first_char != KEY_RETURN && first_char != ' ')
|
||||
{
|
||||
// ignore wrong input
|
||||
fmt = "%C";
|
||||
return EXTRA_INPUT;
|
||||
}
|
||||
else
|
||||
// backtrace from current thread
|
||||
goto start_backtrace;
|
||||
}
|
||||
else if (args == &ko_tid)
|
||||
{
|
||||
{
|
||||
tid = 0;
|
||||
Kobject* o = ko_tid;
|
||||
|
||||
if (o)
|
||||
tid = Kobject::dcast<Thread_object*>(o);
|
||||
|
||||
if (!tid)
|
||||
{
|
||||
puts(" Invalid thread id");
|
||||
return NOTHING;
|
||||
}
|
||||
}
|
||||
|
||||
start_backtrace:
|
||||
task = tid->space();
|
||||
get_user_eip_ebp(eip, ebp);
|
||||
|
||||
start_backtrace_known_ebp:
|
||||
printf("\n\nbacktrace (thread %lx, fp=" L4_PTR_FMT
|
||||
", pc=" L4_PTR_FMT "):\n",
|
||||
tid->dbg_info()->dbg_id(), ebp, eip);
|
||||
if (task != 0)
|
||||
show(ebp, eip, 0, ADDR_USER);
|
||||
#if 0
|
||||
if (!Config::Have_frame_ptr)
|
||||
{
|
||||
puts("\n --kernel-bt-follows-- "
|
||||
"(don't trust w/o frame pointer!!)");
|
||||
task = 0;
|
||||
show_without_ebp();
|
||||
}
|
||||
else
|
||||
{
|
||||
Mword eip2;
|
||||
puts("\n --kernel-bt-follows--");
|
||||
get_kernel_eip_ebp(eip, eip2, ebp);
|
||||
task = 0;
|
||||
show(ebp, eip, eip2, ADDR_KERNEL);
|
||||
}
|
||||
#endif
|
||||
putchar('\n');
|
||||
}
|
||||
else
|
||||
{
|
||||
Jdb_module::Action_code code;
|
||||
|
||||
switch ((code = Jdb_input_task_addr::action(args, fmt, next_char)))
|
||||
{
|
||||
case ERROR:
|
||||
return ERROR;
|
||||
case NOTHING:
|
||||
task = Jdb_input_task_addr::space();
|
||||
eip = 0;
|
||||
ebp = Jdb_input_task_addr::addr();
|
||||
goto start_backtrace_known_ebp;
|
||||
default:
|
||||
return code;
|
||||
}
|
||||
}
|
||||
} else if (cmd == 1) {
|
||||
if ((args == &dummy) && (dummy == 't'))
|
||||
Jdb::execute_command("bt");
|
||||
|
||||
}
|
||||
return NOTHING;
|
||||
}
|
||||
|
||||
PUBLIC
|
||||
Jdb_module::Cmd const *
|
||||
Jdb_bt::cmds() const
|
||||
{
|
||||
static Cmd cs[] =
|
||||
{
|
||||
{ 0, "bt", "backtrace", " [a]ddr/[t]hread",
|
||||
"bt[t<threadid>][<addr>]\tshow backtrace of current/given "
|
||||
"thread/addr",
|
||||
&dummy },
|
||||
/*
|
||||
* The "bt" command only works with the help of the "b" command,
|
||||
* which is currently not registered by another module on ARM
|
||||
*/
|
||||
{ 1, "b", "b_dummy", "%c",
|
||||
"b\tdummy command to make the 'bt' command work in the\n"
|
||||
"\tabsence of a real 'b' command",
|
||||
&dummy },
|
||||
};
|
||||
return cs;
|
||||
}
|
||||
|
||||
PUBLIC
|
||||
int
|
||||
Jdb_bt::num_cmds() const
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
IMPLEMENT
|
||||
Jdb_bt::Jdb_bt()
|
||||
: Jdb_module("INFO")
|
||||
{}
|
||||
|
||||
static Jdb_bt jdb_bt INIT_PRIORITY(JDB_MODULE_INIT_PRIO);
|
||||
|
||||
@@ -36,7 +36,7 @@ private:
|
||||
|
||||
friend class _foo;
|
||||
|
||||
enum { LIST_UNSORTED, LIST_SORT_PRIO, LIST_SORT_TID, LIST_SORT_SPACE, LIST_SORT_CONSUMED_TIME,
|
||||
enum { LIST_UNSORTED, LIST_SORT_PRIO, LIST_SORT_TID, LIST_SORT_SPACE,
|
||||
LIST_SORT_END };
|
||||
|
||||
};
|
||||
@@ -71,7 +71,7 @@ const char*
|
||||
Jdb_thread_list::get_mode_str(void)
|
||||
{
|
||||
static const char * const mode_str[] =
|
||||
{ "(unsorted)", "(prio-sorted)", "(tid-sorted)", "(space-sorted)", "(cpu time-sorted)" };
|
||||
{ "(unsorted)", "(prio-sorted)", "(tid-sorted)", "(space-sorted)" };
|
||||
|
||||
return mode_str[_mode];
|
||||
}
|
||||
@@ -205,14 +205,6 @@ Jdb_thread_list::get_space_dbgid(Thread *t)
|
||||
return Kobject_dbg::pointer_to_id(t->space());
|
||||
}
|
||||
|
||||
// helper function for iter() -- use consumed time as sorting key
|
||||
static
|
||||
long
|
||||
Jdb_thread_list::get_consumed_time(Thread *t)
|
||||
{
|
||||
return t->consumed_time();
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
IMPLEMENTATION [sched_wfq || sched_fp_wfq]:
|
||||
@@ -480,13 +472,6 @@ Jdb_thread_list::iter(int count, Thread **t_start,
|
||||
|
||||
// fall through
|
||||
|
||||
case LIST_SORT_CONSUMED_TIME:
|
||||
// list threads sorted by consumed time
|
||||
if (!get_key)
|
||||
get_key = get_consumed_time;
|
||||
|
||||
// fall through
|
||||
|
||||
case LIST_SORT_TID:
|
||||
// list threads sorted by thread id
|
||||
{
|
||||
@@ -706,13 +691,6 @@ Jdb_thread_list::list_threads_show_thread(Thread *t)
|
||||
|
||||
printf("%-6s", to);
|
||||
|
||||
/* consumed time */
|
||||
char time_str[12];
|
||||
Jdb::write_ll_ns(t->consumed_time()*1000, time_str,
|
||||
11 < sizeof(time_str) ? 11 : sizeof(time_str), false);
|
||||
printf(" %s ", time_str);
|
||||
|
||||
/* state */
|
||||
if (long_output)
|
||||
{
|
||||
Jdb_thread::print_state_long(t, 47);
|
||||
@@ -743,7 +721,7 @@ static void
|
||||
Jdb_thread_list::show_header()
|
||||
{
|
||||
Jdb::cursor();
|
||||
printf("%s id cpu name pr sp wait to%s cpu time state\033[m\033[K",
|
||||
printf("%s id cpu name pr sp wait to%s state\033[m\033[K",
|
||||
Jdb::esc_emph, Config::Stack_depth ? " stack" : "");
|
||||
}
|
||||
|
||||
|
||||
@@ -24,9 +24,9 @@ if (!defined $ARGV[0])
|
||||
exit 1;
|
||||
}
|
||||
|
||||
my $nm = 'genode-x86-nm';
|
||||
my $nm = 'nm';
|
||||
$nm = "$ENV{'SYSTEM_TARGET'}$nm" if defined $ENV{"SYSTEM_TARGET"};
|
||||
$nm = 'genode-arm-nm' if !(system("file -L $ARGV[0] | grep -qw ARM") >> 8);
|
||||
$nm = 'arm-linux-nm' if !(system("file -L $ARGV[0] | grep -qw ARM") >> 8);
|
||||
|
||||
while (@ARGV)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user