8 //-----------------------------------------------------------------
14 #include "entry_frame.h"
16 #include "jdb_disasm.h"
17 #include "jdb_handler_queue.h"
18 #include "jdb_input.h"
19 #include "jdb_kobject.h"
20 #include "jdb_kobject_names.h"
21 #include "jdb_module.h"
22 #include "jdb_screen.h"
23 #include "jdb_thread.h"
25 #include "kernel_console.h"
26 #include "kernel_task.h"
29 #include "push_console.h"
31 #include "static_init.h"
33 #include "thread_object.h"
34 #include "thread_state.h"
37 IMPLEMENTATION [32bit]:
38 #define ADDR_FMT "%08lx"
40 IMPLEMENTATION [64bit]:
41 #define ADDR_FMT "%016lx"
49 Jdb_tcb_ptr(Address addr = 0)
50 : _base(addr & ~(Context::Size-1)),
51 _offs(addr & (Context::Size-1))
54 Jdb_tcb_ptr(Jdb_tcb_ptr const &p)
55 : _base(p.base()), _offs(p.offs())
58 inline bool valid() const
59 { return _offs <= Context::Size-sizeof(Mword); }
61 bool operator > (int offs) const
63 return offs < 0 ? _offs > Context::Size + offs*sizeof(Mword)
64 : _offs > offs*sizeof(Mword);
67 Jdb_tcb_ptr &operator += (int offs)
68 { _offs += offs*sizeof(Mword); return *this; }
70 inline Address addr() const
71 { return _base + _offs; }
73 inline Mword value() const
74 { return *(Mword*)(_base + _offs); }
76 inline void value(Mword v)
77 { *(Mword*)(_base + _offs) = v; }
79 inline bool is_user_value() const;
81 inline const char *user_value_desc() const;
83 inline Mword top_value(int offs) const
84 { return *((Mword*)(Cpu::stack_align(_base + Context::Size)) + offs); }
86 inline Address base() const
89 inline Address offs() const
92 inline void offs(Address offs)
95 inline bool is_kern_code() const
96 { return (Address)&Mem_layout::image_start <= value()
97 && value() <= (Address)&Mem_layout::ecode; };
99 inline bool is_kobject() const
100 { return Kobject_dbg::is_kobj(reinterpret_cast<void *>(value())); }
107 class Jdb_disasm_view
123 bool memdump_is_colored;
125 bool edit_registers();
129 class Jdb_tcb : public Jdb_module, public Jdb_kobject_handler
131 static Kobject *threadid;
132 static Address address;
133 static char first_char;
134 static char auto_tcb;
137 static void print_return_frame_regs(Jdb_tcb_ptr const ¤t, Mword ksp);
138 static void print_entry_frame_regs(Thread *t);
139 static void info_thread_state(Thread *t);
141 static Jdb_disasm_view _disasm_view;
142 static Jdb_stack_view _stack_view;
147 Kobject *Jdb_tcb::threadid;
148 Address Jdb_tcb::address;
149 char Jdb_tcb::first_char;
150 char Jdb_tcb::auto_tcb;
151 Jdb_disasm_view Jdb_tcb::_disasm_view(Jdb_tcb::Disasm_x, Jdb_tcb::Disasm_y);
152 Jdb_stack_view Jdb_tcb::_stack_view (Jdb_tcb::Stack_y);
155 // available from jdb_dump module
156 extern int jdb_dump_addr_task (Address addr, Space *task, int level)
157 __attribute__((weak));
160 // default implementations: --------------------------------------------
162 // nothing special to do for edit registers
163 IMPLEMENT_DEFAULT bool Jdb_stack_view::edit_registers() { return true; }
167 Jdb_stack_view::Jdb_stack_view(unsigned y)
168 : start_y(y), absy(0), memdump_is_colored(true)
173 Jdb_stack_view::cols()
175 return Jdb_screen::cols() - 1;
180 Jdb_stack_view::bytes_per_line()
181 { return cols() * sizeof(Mword); }
185 Jdb_stack_view::init(Address ksp, Jdb_entry_frame *_ef, bool _is_current)
187 current = Jdb_tcb_ptr(ksp);
189 absy = current.offs() / bytes_per_line();
190 addx = (current.offs() % bytes_per_line()) / sizeof(Mword);
193 is_current = _is_current;
198 Jdb_stack_view::print_value(Jdb_tcb_ptr const &p, bool highl = false)
200 if (!p.valid() || !Jdb_util::is_mapped((void const*)p.addr()))
202 printf(" %.*s", (int)Jdb_screen::Mword_size_bmode, Jdb_screen::Mword_not_mapped);
206 const char *s1="", *s2="";
212 else if (p.is_user_value())
217 else if (memdump_is_colored)
219 if (p.is_kern_code())
221 s1 = JDB_ANSI_COLOR(lightblue);
224 else if (p.is_kobject())
226 s1 = JDB_ANSI_COLOR(lightgreen);
229 /* else if (p.in_backtrace(...
236 printf(" %s" ADDR_FMT "%s", s1, p.value(), s2);
242 Jdb_stack_view::dump(bool dump_only)
249 p = Jdb_tcb_ptr(current.base());
250 ylen = Context::Size / bytes_per_line();
256 p.offs(absy * bytes_per_line());
257 Jdb::cursor(start_y, 1);
258 ylen = Jdb_screen::height() - start_y;
261 for (unsigned y = 0; y < ylen; ++y)
263 Kconsole::console()->getchar_chance();
267 printf(" %03lx ", p.addr() & 0xfff);
268 for (unsigned x = 0; x < cols(); ++x, p+=1)
279 Jdb_stack_view::posx()
280 { return addx * (Jdb_screen::Mword_size_bmode + 1) + 9; }
284 Jdb_stack_view::posy()
285 { return addy + start_y; }
289 Jdb_stack_view::highlight(bool highl)
291 current.offs(absy*bytes_per_line() + addy*bytes_per_line() + addx * sizeof(Mword));
292 Jdb_tcb_ptr first_col = current;
293 first_col.offs(absy*bytes_per_line() + addy*bytes_per_line());
295 if (!current.valid())
298 Jdb::cursor(posy(), 1);
300 printf("%08lx", current.addr() & 0xffffffff);
302 printf(" %03lx ", first_col.addr() & 0xfff);
303 Jdb::cursor(posy(), posx());
304 print_value(current, highl);
306 String_buf<120> kobj_desc;
307 Kobject_dbg::Iterator o;
309 if (current.is_kern_code())
310 kobj_desc.printf("Kernel code"); // todo: print kernel function name
311 else if (current.is_user_value())
312 kobj_desc.printf("Return frame: %s", current.user_value_desc());
313 else if ((o = Kobject_dbg::pointer_to_obj(reinterpret_cast<void *>(current.value()))) != Kobject_dbg::end())
314 Jdb_kobject::obj_description(&kobj_desc, true, *o);
316 Jdb::printf_statline("tcb", "<CR>=dump <Space>=Disas",
317 "%s", kobj_desc.c_str());
322 Jdb_stack_view::handle_key(int key, bool *redraw)
324 Mword lines = Jdb_screen::height() - start_y;
325 Mword max_lines = (Context::Size + bytes_per_line() - 1)/bytes_per_line();
326 Address max_absy = max_lines - lines;
328 if (lines > max_lines)
331 if (lines > max_lines - absy)
332 lines = max_lines - absy;
337 return Jdb::std_cursor_key(key, this->cols(), lines, max_absy,
338 &absy, &addy, &addx, redraw);
345 Jdb_stack_view::edit_stack(bool *redraw)
352 Jdb::cursor(posy(), posx());
353 printf(" %.*s", (int)Jdb_screen::Mword_size_bmode, Jdb_screen::Mword_blank);
354 Jdb::printf_statline("tcb",
355 is_current ? "<Space>=edit registers" : 0,
356 "edit <" ADDR_FMT "> = " ADDR_FMT,
357 current.addr(), current.value());
359 Jdb::cursor(posy(), posx() + 1);
360 c = Jdb_core::getchar();
368 if (c != ' ' || !is_current)
372 Jdb::printf_statline("tcb", 0, "edit <" ADDR_FMT "> = " ADDR_FMT,
373 current.addr(), current.value());
374 Jdb::cursor(posy(), posx() + 1);
375 if (!Jdb_input::get_mword(&value, c, 16))
377 Jdb::cursor(posy(), posx());
378 print_value(current);
382 current.value(value);
387 Jdb::cursor(posy(), posx());
388 print_value(current);
397 Jdb_disasm_view::Jdb_disasm_view(unsigned x, unsigned y)
403 Jdb_disasm_view::show(Jdb_tcb_ptr const &p, Space *s, bool dump_only)
405 if (!Jdb_disasm::avail())
408 Address disass_addr = p.top_value(-5);
411 for (unsigned i = 0; i < 20; ++i)
412 Jdb_disasm::show_disasm_line(Jdb_screen::width(), disass_addr, 0, s);
417 putstr(Jdb::esc_emph);
418 Jdb_disasm::show_disasm_line(-40, disass_addr, 0, s);
420 Jdb::cursor(_y + 1, _x);
421 Jdb_disasm::show_disasm_line(-40, disass_addr, 0, s);
427 : Jdb_module("INFO"), Jdb_kobject_handler((Thread*)0)
429 static Jdb_handler enter(at_jdb_enter);
431 Jdb::jdb_enter.add(&enter);
432 Jdb_kobject::module()->register_handler(this);
436 Jdb_tcb::at_jdb_enter()
440 // clear any keystrokes in queue
441 Jdb::set_next_cmd(0);
442 Jdb::push_cons()->push('t');
443 Jdb::push_cons()->push(' ');
450 Jdb_tcb::parent(Kobject_common *o)
452 Thread *t = cxx::dyn_cast<Thread*>(o);
456 return static_cast<Task*>(t->space());
459 PRIVATE static inline
461 Jdb_tcb::vcpu_state_str(Mword state, char *s, int len)
463 snprintf(s, len, "%c%c%c%c%c%c",
464 (state & Vcpu_state::F_fpu_enabled) ? 'F' : 'f',
465 (state & Vcpu_state::F_user_mode) ? 'U' : 'u',
466 (state & Vcpu_state::F_debug_exc) ? 'D' : 'd',
467 (state & Vcpu_state::F_exceptions) ? 'E' : 'e',
468 (state & Vcpu_state::F_page_faults) ? 'P' : 'p',
469 (state & Vcpu_state::F_irqs) ? 'I' : 'i');
475 Jdb_module::Action_code
476 Jdb_tcb::show(Thread *t, int level, bool dump_only)
478 Thread *t_current = Jdb::get_current_active();
479 bool is_current_thread;
480 bool redraw_screen = !dump_only;
481 Jdb_entry_frame *ef = Jdb::get_entry_frame(Jdb::current_cpu);
483 Address bt_start = 0;
486 if (!t && !t_current)
492 is_current_thread = t == t_current;
496 Jdb::clear_screen(Jdb::FANCY);
497 redraw_screen = false;
504 Jdb::clear_screen(Jdb::NOFANCY);
505 redraw_screen = false;
508 String_buf<12> time_str;
511 Jdb_kobject::print_uid(t, 3);
512 print_thread_uid_raw(t);
513 printf("\tCPU: %u:%u ", cxx::int_value<Cpu_number>(t->home_cpu()),
514 cxx::int_value<Cpu_number>(t->get_current_cpu()));
516 printf("\tprio: %02x\n",
517 (unsigned)t->sched()->prio());
519 printf("state : %03lx ", t->state(false));
520 Jdb_thread::print_state_long(t);
522 putstr("\nwait for: ");
526 Jdb_thread::print_partner(t, 4);
528 putstr("\tpolling: ");
529 Jdb_thread::print_snd_partner(t, 3);
531 putstr("\trcv descr: ");
533 if ((t->state(false) & Thread_ipc_mask) == Thread_receive_wait
535 printf("%08lx", t->rcv_regs()->from_spec());
541 //if (t->thread_lock()->lock_owner())
542 // Jdb_kobject::print_uid(static_cast<Thread*>(t->thread_lock()->lock_owner()), 3);
544 putstr("\t\t\ttimeout : ");
545 if (t->_timeout && t->_timeout->is_set())
547 Signed64 diff = (t->_timeout->get_timeout(Kip::k()->clock)) * 1000;
549 time_str.printf("over");
551 Jdb::write_ll_ns(&time_str, diff, false);
553 time_str.terminate();
554 printf("%-13s", time_str.begin());
558 putstr("\ncpu time: ");
559 Jdb::write_ll_ns(&time_str, t->consumed_time()*1000, false);
560 time_str.terminate();
561 printf("%-13s", time_str.begin());
563 printf("\t\ttimeslice: %llu/%llu %cs\n"
565 t->sched()->left(), ~0ULL/*t->sched()->quantum()*/, Config::char_micro);
566 print_kobject(t, t->_pager.raw());
569 if (t->space() == Kernel_task::kernel_task())
572 print_kobject(static_cast<Task*>(t->space()));
574 putstr("\nexc-hndl: ");
575 print_kobject(t, t->_exc_handler.raw());
577 printf("\tUTCB : %08lx/%08lx",
578 (Mword)t->utcb().kern(), (Mword)t->utcb().usr().get());
581 putstr("\tready lnk: ");
582 if (t->state(false) & Thread_ready)
585 Jdb_kobject::print_uid(Thread::lookup(t->_ready_next), 3);
586 else if (is_current_thread)
589 putstr("\033[31;1m???.??\033[m");
591 Jdb_kobject::print_uid(Thread::lookup(t->_ready_prev), 4);
592 else if (is_current_thread)
595 putstr(" \033[31;1m???.??\033[m");
605 if (t->state(false) & Thread_vcpu_enabled)
609 Vcpu_state *v = t->vcpu_state().kern();
610 printf("%08lx/%08lx S=", (Mword)v, (Mword)t->vcpu_state().usr().get());
611 print_kobject(static_cast<Task*>(t->vcpu_user_space()));
613 printf("vCPU : c=%s s=%s sf=%c e-ip=%08lx e-sp=%08lx\n",
614 vcpu_state_str(v->state, st1, sizeof(st1)),
615 vcpu_state_str(v->_saved_state, st2, sizeof(st2)),
616 (v->sticky_flags & Vcpu_state::Sf_irq_pending) ? 'P' : '-',
617 v->_entry_ip, v->_entry_sp);
620 putstr("---\nvCPU : ---\n");
622 Address ksp = is_current_thread ? ef->ksp()
623 : (Address)t->get_kernel_sp();
626 Address tcb = (Address)context_of((void*)ksp);
628 _stack_view.init(ksp, ef, is_current_thread);
630 if (is_current_thread)
631 print_entry_frame_regs(t);
633 else if (t->space() != Kernel_task::kernel_task())
637 info_thread_state(t);
639 print_return_frame_regs(_stack_view.current, ksp);
641 _disasm_view.show(_stack_view.current, t->space(), dump_only);
648 printf("kernel SP=" ADDR_FMT, ksp);
653 // dump the stack from ksp bottom right to tcb_top
654 _stack_view.dump(dump_only);
659 for (bool redraw=false; ; )
661 _stack_view.highlight(true);
662 int c=Jdb_core::getchar();
663 _stack_view.highlight(false);
664 Jdb::cursor(Jdb_screen::height(), 6);
666 if (c == KEY_CURSOR_HOME && level > 0)
669 if (!_stack_view.handle_key(c, &redraw))
674 if (jdb_dump_addr_task && _stack_view.current.valid())
676 if (!jdb_dump_addr_task(_stack_view.current.value(),
677 _stack_view.current.is_user_value() ? t->space() : 0, level+1))
679 redraw_screen = true;
683 //bt_start = search_bt_start(tcb, (Mword*)ksp, is_current_thread);
687 if (Jdb_disasm::avail() && _stack_view.current.valid())
689 printf("V %lx\n", _stack_view.current.value());
690 if (!Jdb_disasm::show(_stack_view.current.value(),
691 _stack_view.current.is_user_value() ? t->space() : 0, level+1, true))
693 redraw_screen = true;
697 if (Jdb_disasm::avail() && _stack_view.current.valid())
699 Jdb::printf_statline("tcb", "<CR>=disassemble here",
700 "u[address=%08lx task=%lx] ",
701 _stack_view.current.value(),
702 Kobject_dbg::pointer_to_id(t->space()));
703 int c1 = Jdb_core::getchar();
704 if ((c1 != KEY_RETURN) && (c1 != ' '))
706 Jdb::printf_statline("tcb", 0, "u");
707 Jdb::execute_command("u", c1);
711 if (!Jdb_disasm::show(_stack_view.current.value(),
712 _stack_view.current.is_user_value() ? t->space() : 0, level+1, true))
714 redraw_screen = true;
718 case 'r': // ready-list
719 putstr("[n]ext/[p]revious in ready list?");
720 switch (Jdb_core::getchar())
725 t = static_cast<Thread*>(t->_ready_next);
732 t = static_cast<Thread*>(t->_ready_prev);
740 _stack_view.memdump_is_colored = !_stack_view.memdump_is_colored;
744 Jdb::abort_command();
747 if (Jdb::is_toplevel_cmd(c))
759 /* --- original L4 screen ------------------------------------------------------
760 thread: 0081 (001.01) <00020401 00080000> prio: 10
761 state : 85, ready lists: 81 mcp: ff
763 wait for: -- rcv descr: 00000000 partner: 00000000
764 sndq : 0081 0081 timeouts: 00000000 waddr0/1: 000/000
765 cpu time: 0000000000 timeslice: 01/0a
767 pager : -- prsent lnk: 0080 0080
768 ipreempt: -- ready link : 0080 0080
771 EAX=00202dfe ESI=00020401 DS=0008 late wakeup lnk:
772 EBX=00000028 EDI=00080000 ES=0008
773 ECX=00000003 EBP=e0020400
774 EDX=00000001 ESP=e00207b4
781 7a0: 0000897b 00000020 00240082
782 7c0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
783 7e0: 00000000 00000000 ffffff80 00000000 0000001b 00003200 00000000 00000013
785 ------------------------------------------------------------------------------*/
788 Jdb_module::Action_code
789 Jdb_tcb::action(int cmd, void *&args, char const *&fmt, int &next_char)
791 static Address tcb_addr = 0;
794 if (args == &first_char)
800 printf("%c\n", first_char);
801 auto_tcb = first_char == '+';
805 fmt = " addr=" ADDR_FMT " => ";
807 return Jdb_module::EXTRA_INPUT;
812 return Jdb_module::EXTRA_INPUT;
819 next_char = first_char;
820 return Jdb_module::EXTRA_INPUT_WITH_NEXTCHAR;
823 else if (args == &address)
825 address &= ~(Context::Size-1);
826 Jdb_kobject::print_uid(reinterpret_cast<Thread*>(address), 3);
829 else if (args == &tcb_addr)
830 show((Thread*)tcb_addr, 0, false);
833 Thread *t = cxx::dyn_cast<Thread *>(threadid);
837 printf("\nNot a thread\n");
842 if (args == &first_char)
846 next_char = first_char;
847 return Jdb_module::EXTRA_INPUT_WITH_NEXTCHAR;
849 else if (args == &threadid)
851 Thread *t = cxx::dyn_cast<Thread *>(threadid);
862 Jdb_tcb::follow_link(Kobject_common *o)
864 Thread *t = cxx::dyn_cast<Thread *>(Kobject::from_dbg(o->dbg_info()));
865 if (t->space() == Kernel_task::kernel_task())
867 return static_cast<Kobject*>(static_cast<Task*>(t->space()));
872 Jdb_tcb::show_kobject(Kobject_common *o, int level)
874 Thread *t = cxx::dyn_cast<Thread *>(Kobject::from_dbg(o->dbg_info()));
875 return show(t, level, false);
880 Jdb_tcb::is_current(Thread *t)
882 return t == Jdb::get_thread(t->get_current_cpu());
887 Jdb_tcb::print_cpu(String_buffer *buf, Thread *t)
889 buf->printf(" C=%u", cxx::int_value<Cpu_number>(t->home_cpu()));
890 if (t->home_cpu() != t->get_current_cpu())
891 buf->printf(":%u", cxx::int_value<Cpu_number>(t->get_current_cpu()));
896 Jdb_tcb::show_kobject_short(String_buffer *buf, Kobject_common *o)
898 Thread *t = cxx::dyn_cast<Thread *>(Kobject::from_dbg(o->dbg_info()));
899 bool is_current = Jdb_tcb::is_current(t);
900 if (t == Context::kernel_context(t->home_cpu()))
902 buf->printf(" {KERNEL}");
906 if (t->space() == Kernel_task::kernel_task())
907 buf->printf(" R=%ld rdy %s", t->ref_cnt(),
908 is_current ? " " JDB_ANSI_COLOR(green) "cur" JDB_ANSI_END : "");
913 buf->printf(" S=D:%lx R=%ld%s%s",
914 Kobject_dbg::pointer_to_id(t->space()),
916 t->in_ready_list() ? " rdy" : "",
917 is_current ? " " JDB_ANSI_COLOR(green) "cur" JDB_ANSI_END : "");
923 Jdb_tcb::kobject_type(Kobject_common *) const
925 return JDB_ANSI_COLOR(green) "Thread" JDB_ANSI_COLOR(default);
929 Jdb_module::Cmd const *
930 Jdb_tcb::cmds() const
934 { 0, "t", "tcb", "%C",
935 "t[<threadid>]\tshow current/given thread control block (TCB)\n"
936 "t{+|-}\tshow current thread control block at every JDB entry\n",
938 { 1, "", "tcbdump", "%C", 0, &first_char },
945 Jdb_tcb::num_cmds() const
948 static Jdb_tcb jdb_tcb INIT_PRIORITY(JDB_MODULE_INIT_PRIO);
951 jdb_show_tcb(Thread *t, int level)
952 { return Jdb_tcb::show(t, level, false); }
956 Jdb_tcb::print_thread_uid_raw(Thread *t)
963 Jdb_tcb::print_kobject(Cap_index n)
965 printf("[C:%4lx] ", cxx::int_value<Cap_index>(n));
970 Jdb_tcb::print_kobject(Kobject *o)
972 printf("D:%4lx ", o ? o->dbg_info()->dbg_id() : 0);
977 Jdb_tcb::print_kobject(Thread *t, Cap_index capidx)
979 Space *space = t->space();
980 if (!space || space->obj_map_max_address() <= capidx)
982 print_kobject(capidx);
986 Obj_space::Capability *c = space->jdb_lookup_cap(capidx);
987 if (!c || !c->valid())
989 print_kobject(capidx);
993 if (Kobject_dbg::pointer_to_obj(c->obj()) == Kobject_dbg::end())
995 printf("[C:%4lx] NOB: %p\n", cxx::int_value<Cap_index>(capidx), c->obj());
999 printf("[C:%4lx] D:%4lx", cxx::int_value<Cap_index>(capidx),
1000 c->obj()->dbg_info()->dbg_id());
1004 //-----------------------------------------------------------------------------
1005 // prompt extension for thread names
1006 class Jdb_thread_name_ext : public Jdb_prompt_ext
1015 Jdb_thread_name_ext::ext()
1017 if (Jdb::get_current_active())
1019 Jdb_kobject_name *nx = Jdb_kobject_extension::find_extension<Jdb_kobject_name>(Jdb::get_current_active());
1020 if (nx && nx->name()[0])
1021 printf("[%*.*s] ", nx->max_len(), nx->max_len(), nx->name());
1027 Jdb_thread_name_ext::update()
1029 Jdb::get_current(Jdb::current_cpu);
1032 static Jdb_thread_name_ext jdb_thread_name_ext INIT_PRIORITY(JDB_MODULE_INIT_PRIO);