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 & ~(Config::thread_block_size-1)),
51 _offs(addr & (Config::thread_block_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 <= Config::thread_block_size-sizeof(Mword); }
61 bool operator > (int offs) const
63 return offs < 0 ? _offs > Config::thread_block_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 + Config::thread_block_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(Space *task);
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 Jdb_stack_view::Jdb_stack_view(unsigned y)
161 : start_y(y), absy(0), memdump_is_colored(true)
166 Jdb_stack_view::cols()
168 return Jdb_screen::cols() - 1;
173 Jdb_stack_view::bytes_per_line()
174 { return cols() * sizeof(Mword); }
178 Jdb_stack_view::init(Address ksp, Jdb_entry_frame *_ef, bool _is_current)
180 current = Jdb_tcb_ptr(ksp);
182 absy = current.offs() / bytes_per_line();
183 addx = (current.offs() % bytes_per_line()) / sizeof(Mword);
186 is_current = _is_current;
191 Jdb_stack_view::print_value(Jdb_tcb_ptr const &p, bool highl = false)
193 if (!p.valid() || !Jdb_util::is_mapped((void const*)p.addr()))
195 printf(" %.*s", Jdb_screen::Mword_size_bmode, Jdb_screen::Mword_not_mapped);
199 const char *s1="", *s2="";
205 else if (p.is_user_value())
210 else if (memdump_is_colored)
212 if (p.is_kern_code())
214 s1 = JDB_ANSI_COLOR(lightblue);
217 else if (p.is_kobject())
219 s1 = JDB_ANSI_COLOR(lightgreen);
222 /* else if (p.in_backtrace(...
229 printf(" %s"ADDR_FMT"%s", s1, p.value(), s2);
235 Jdb_stack_view::dump()//Jdb_tcb_ptr const ¤t)
237 Jdb_tcb_ptr p = current;
238 p.offs(absy * bytes_per_line());
240 Jdb::cursor(start_y, 1);
242 for (unsigned y = 0; y < Jdb_screen::height() - start_y; ++y)
244 Kconsole::console()->getchar_chance();
248 printf(" %03lx ", p.addr() & 0xfff);
249 for (unsigned x = 0; x < cols(); ++x, p+=1)
260 Jdb_stack_view::posx()
261 { return addx * (Jdb_screen::Mword_size_bmode + 1) + 9; }
265 Jdb_stack_view::posy()
266 { return addy + start_y; }
270 Jdb_stack_view::highlight(bool highl)
272 current.offs(absy*bytes_per_line() + addy*bytes_per_line() + addx * sizeof(Mword));
273 Jdb_tcb_ptr first_col = current;
274 first_col.offs(absy*bytes_per_line() + addy*bytes_per_line());
276 if (!current.valid())
279 Jdb::cursor(posy(), 1);
281 printf("%08lx", current.addr() & 0xffffffff);
283 printf(" %03lx ", first_col.addr() & 0xfff);
284 Jdb::cursor(posy(), posx());
285 print_value(current, highl);
290 if (current.is_kern_code())
291 strcpy(kobj_desc, "Kernel code"); // todo: print kernel function name
292 else if (current.is_user_value())
293 snprintf(kobj_desc, sizeof(kobj_desc), "Return frame: %s",
294 current.user_value_desc());
296 if (Kobject *o = Kobject::pointer_to_obj(reinterpret_cast<void *>(current.value())))
298 Jdb_kobject::obj_description(kobj_desc, sizeof(kobj_desc), true, o);
299 kobj_desc[sizeof(kobj_desc) - 1] = 0;
302 Jdb::printf_statline("tcb", "<CR>=dump <Space>=Disas",
308 Jdb_stack_view::handle_key(int key, bool *redraw)
310 Mword lines = Jdb_screen::height() - start_y;
311 Mword max_lines = (Config::thread_block_size + bytes_per_line() - 1)/bytes_per_line();
312 Address max_absy = max_lines - lines;
314 if (lines > max_lines)
317 if (lines > max_lines - absy)
318 lines = max_lines - absy;
323 return Jdb::std_cursor_key(key, this->cols(), lines, max_absy,
324 &absy, &addy, &addx, redraw);
331 Jdb_stack_view::edit_stack(bool *redraw)
338 Jdb::cursor(posy(), posx());
339 printf(" %.*s", Jdb_screen::Mword_size_bmode, Jdb_screen::Mword_blank);
340 Jdb::printf_statline("tcb",
341 is_current ? "<Space>=edit registers" : 0,
342 "edit <"ADDR_FMT"> = "ADDR_FMT,
343 current.addr(), current.value());
345 Jdb::cursor(posy(), posx() + 1);
346 c = Jdb_core::getchar();
354 if (c != ' ' || !is_current)
358 Jdb::printf_statline("tcb", 0, "edit <"ADDR_FMT"> = "ADDR_FMT,
359 current.addr(), current.value());
360 Jdb::cursor(posy(), posx() + 1);
361 if (!Jdb_input::get_mword(&value, c, 16))
363 Jdb::cursor(posy(), posx());
364 print_value(current);
368 current.value(value);
373 Jdb::cursor(posy(), posx());
374 print_value(current);
383 Jdb_disasm_view::Jdb_disasm_view(unsigned x, unsigned y)
389 Jdb_disasm_view::show(Jdb_tcb_ptr const &p, Space *s)
391 if (!Jdb_disasm::avail())
394 Address disass_addr = p.top_value(-5);
396 putstr(Jdb::esc_emph);
397 Jdb_disasm::show_disasm_line(-40, disass_addr, 0, s);
399 Jdb::cursor(_y + 1, _x);
400 Jdb_disasm::show_disasm_line(-40, disass_addr, 0, s);
406 : Jdb_module("INFO"), Jdb_kobject_handler(Thread_object::static_kobj_type)
408 static Jdb_handler enter(at_jdb_enter);
410 Jdb::jdb_enter.add(&enter);
411 Jdb_kobject::module()->register_handler(this);
415 Jdb_tcb::at_jdb_enter()
419 // clear any keystrokes in queue
420 Jdb::set_next_cmd(0);
421 Jdb::push_cons()->push('t');
422 Jdb::push_cons()->push(' ');
429 Jdb_tcb::parent(Kobject *o)
431 Thread *t = Kobject::dcast<Thread_object*>(o);
435 return static_cast<Task*>(t->space());
438 PRIVATE static inline
440 Jdb_tcb::vcpu_state_str(Mword state, char *s, int len)
442 snprintf(s, len, "%c%c%c%c%c%c",
443 (state & Vcpu_state::F_fpu_enabled) ? 'F' : 'f',
444 (state & Vcpu_state::F_user_mode) ? 'U' : 'u',
445 (state & Vcpu_state::F_debug_exc) ? 'D' : 'd',
446 (state & Vcpu_state::F_exceptions) ? 'E' : 'e',
447 (state & Vcpu_state::F_page_faults) ? 'P' : 'p',
448 (state & Vcpu_state::F_irqs) ? 'I' : 'i');
454 Jdb_module::Action_code
455 Jdb_tcb::show(Thread *t, int level)
457 Thread *t_current = Jdb::get_current_active();
458 bool is_current_thread;
459 bool redraw_screen = true;
460 Jdb_entry_frame *ef = Jdb::get_entry_frame(Jdb::current_cpu);
462 Address bt_start = 0;
465 if (!t && !t_current)
469 = (Config::thread_block_size * Mem_layout::max_threads()) - 1;
470 const Mword tsksz = Config::thread_block_size*L4_uid::threads_per_task();
471 LThread_num task = ((Address)Jdb::get_thread() & mask) / tsksz;
475 print_entry_frame_regs(0);
483 is_current_thread = t == t_current;
488 puts(" Invalid thread");
495 Jdb::clear_screen(Jdb::FANCY);
496 redraw_screen = false;
503 Jdb::clear_screen(Jdb::NOFANCY);
504 redraw_screen = false;
510 Jdb_kobject::print_uid(t, 3);
511 print_thread_uid_raw(t);
512 printf("\tCPU: %u ", t->cpu());
514 printf("\tprio: %02x mode: %s\n",
516 t->mode() & Context::Periodic ?
517 t->mode() & Context::Nonstrict ? "Per (IRT)" : "Per (SP)" : "Con");
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(" polling: ");
529 Jdb_thread::print_snd_partner(t, 3);
531 putstr("rcv descr: ");
533 if (t->state(false) & Thread_ipc_receiving_mask)
534 printf("%08lx", t->rcv_regs()->from_spec());
540 if (t->thread_lock()->lock_owner())
541 Jdb_kobject::print_uid(static_cast<Thread*>(t->thread_lock()->lock_owner()), 3);
543 putstr("\t\t\ttimeout : ");
544 if (t->_timeout && t->_timeout->is_set())
546 Signed64 diff = (t->_timeout->get_timeout(Kip::k()->clock)) * 1000;
548 strcpy(time_str, "over");
550 Jdb::write_ll_ns(diff, time_str,
551 11 < sizeof(time_str)-1 ? 11 : sizeof(time_str)-1,
553 printf("%-13s", time_str);
556 putstr("\ncpu time: ");
557 Jdb::write_ll_ns(t->consumed_time()*1000, time_str,
558 11 < sizeof(time_str) ? 11 : sizeof(time_str), false);
559 printf("%-13s", time_str);
561 printf("\t\ttimeslice: %llu/%llu %cs\n"
563 t->sched()->left(), t->sched()->quantum(), Config::char_micro);
564 print_kobject(t, t->_pager.raw());
567 if (t->space() == Kernel_task::kernel_task())
570 print_kobject(static_cast<Task*>(t->space()));
572 putstr("\nexc-hndl: ");
573 print_kobject(t, t->_exc_handler.raw());
575 printf("\tUTCB : %08lx/%08lx",
576 (Mword)t->utcb().kern(), (Mword)t->utcb().usr().get());
579 putstr("\tready lnk: ");
580 if (t->state(false) & Thread_ready)
583 Jdb_kobject::print_uid(Thread::lookup(t->_ready_next), 3);
584 else if (is_current_thread)
587 putstr("\033[31;1m???.??\033[m");
589 Jdb_kobject::print_uid(Thread::lookup(t->_ready_prev), 4);
590 else if (is_current_thread)
593 putstr(" \033[31;1m???.??\033[m");
603 if (t->state(false) & Thread_vcpu_enabled)
607 Vcpu_state *v = t->vcpu_state().kern();
608 printf("%08lx/%08lx S=", (Mword)v, (Mword)t->vcpu_state().usr().get());
609 print_kobject(static_cast<Task*>(t->vcpu_user_space()));
611 printf("vCPU : c=%s s=%s sf=%c e-ip=%08lx e-sp=%08lx\n",
612 vcpu_state_str(v->state, st1, sizeof(st1)),
613 vcpu_state_str(v->_saved_state, st2, sizeof(st2)),
614 (v->sticky_flags & Vcpu_state::Sf_irq_pending) ? 'P' : '-',
615 v->_entry_ip, v->_entry_sp);
618 putstr("---\nvCPU : ---\n");
620 Address ksp = is_current_thread ? ef->ksp()
621 : (Address)t->get_kernel_sp();
624 Address tcb = (Address)context_of((void*)ksp);
626 _stack_view.init(ksp, ef, is_current_thread);
628 if (is_current_thread)
629 print_entry_frame_regs(t->space());
631 else if (t->space() != Kernel_task::kernel_task())
634 info_thread_state(t);
636 print_return_frame_regs(_stack_view.current, ksp);
638 _disasm_view.show(_stack_view.current, t->space());
644 printf("kernel SP="ADDR_FMT, ksp);
649 // dump the stack from ksp bottom right to tcb_top
652 for (bool redraw=false; ; )
654 _stack_view.highlight(true);
655 int c=Jdb_core::getchar();
656 _stack_view.highlight(false);
657 Jdb::cursor(Jdb_screen::height(), 6);
659 if (c == KEY_CURSOR_HOME && level > 0)
662 if (!_stack_view.handle_key(c, &redraw))
667 if (jdb_dump_addr_task && _stack_view.current.valid())
669 if (!jdb_dump_addr_task(_stack_view.current.value(),
670 _stack_view.current.is_user_value() ? t->space() : 0, level+1))
672 redraw_screen = true;
676 //bt_start = search_bt_start(tcb, (Mword*)ksp, is_current_thread);
680 if (Jdb_disasm::avail() && _stack_view.current.valid())
682 printf("V %lx\n", _stack_view.current.value());
683 if (!Jdb_disasm::show(_stack_view.current.value(),
684 _stack_view.current.is_user_value() ? t->space() : 0, level+1, true))
686 redraw_screen = true;
690 if (Jdb_disasm::avail() && _stack_view.current.valid())
692 Jdb::printf_statline("tcb", "<CR>=disassemble here",
693 "u[address=%08lx task=%lx] ",
694 _stack_view.current.value(),
695 Kobject_dbg::pointer_to_id(t->space()));
696 int c1 = Jdb_core::getchar();
697 if ((c1 != KEY_RETURN) && (c1 != ' '))
699 Jdb::printf_statline("tcb", 0, "u");
700 Jdb::execute_command("u", c1);
704 if (!Jdb_disasm::show(_stack_view.current.value(),
705 _stack_view.current.is_user_value() ? t->space() : 0, level+1, true))
707 redraw_screen = true;
711 case 'r': // ready-list
712 putstr("[n]ext/[p]revious in ready list?");
713 switch (Jdb_core::getchar())
718 t = static_cast<Thread*>(t->_ready_next);
725 t = static_cast<Thread*>(t->_ready_prev);
733 _stack_view.memdump_is_colored = !_stack_view.memdump_is_colored;
737 Jdb::abort_command();
740 if (Jdb::is_toplevel_cmd(c))
752 /* --- original L4 screen ------------------------------------------------------
753 thread: 0081 (001.01) <00020401 00080000> prio: 10
754 state : 85, ready lists: 81 mcp: ff
756 wait for: -- rcv descr: 00000000 partner: 00000000
757 sndq : 0081 0081 timeouts: 00000000 waddr0/1: 000/000
758 cpu time: 0000000000 timeslice: 01/0a
760 pager : -- prsent lnk: 0080 0080
761 ipreempt: -- ready link : 0080 0080
764 EAX=00202dfe ESI=00020401 DS=0008 late wakeup lnk:
765 EBX=00000028 EDI=00080000 ES=0008
766 ECX=00000003 EBP=e0020400
767 EDX=00000001 ESP=e00207b4
774 7a0: 0000897b 00000020 00240082
775 7c0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
776 7e0: 00000000 00000000 ffffff80 00000000 0000001b 00003200 00000000 00000013
778 ------------------------------------------------------------------------------*/
781 Jdb_module::Action_code
782 Jdb_tcb::action(int cmd, void *&args, char const *&fmt, int &next_char)
784 static Address tcb_addr = 0;
787 if (args == &first_char)
793 printf("%c\n", first_char);
794 auto_tcb = first_char == '+';
798 fmt = " addr="ADDR_FMT" => ";
800 return Jdb_module::EXTRA_INPUT;
805 return Jdb_module::EXTRA_INPUT;
812 next_char = first_char;
813 return Jdb_module::EXTRA_INPUT_WITH_NEXTCHAR;
816 else if (args == &address)
818 address &= ~(Config::thread_block_size-1);
819 Jdb_kobject::print_uid(reinterpret_cast<Thread*>(address), 3);
822 else if (args == &tcb_addr)
823 show((Thread*)tcb_addr, 0);
826 Thread *t = Kobject::dcast<Thread_object *>(threadid);
830 printf("\nNot a thread\n");
839 Jdb_tcb::follow_link(Kobject_common *o)
841 Thread *t = Kobject::dcast<Thread_object *>(Kobject::from_dbg(o->dbg_info()));
842 if (t->space() == Kernel_task::kernel_task())
844 return static_cast<Kobject*>(static_cast<Task*>(t->space()));
849 Jdb_tcb::show_kobject(Kobject_common *o, int level)
851 Thread *t = Kobject::dcast<Thread_object *>(Kobject::from_dbg(o->dbg_info()));
852 return show(t, level);
857 Jdb_tcb::show_kobject_short(char *buf, int max, Kobject_common *o)
859 Thread *t = Kobject::dcast<Thread_object *>(Kobject::from_dbg(o->dbg_info()));
860 Thread *cur_t = Jdb::get_current_active();
862 if (t->space() == Kernel_task::kernel_task())
864 cnt = snprintf(buf, max, " {KERNEL} C=%u", t->cpu());
868 if (t->space() == Kernel_task::kernel_task())
869 return cnt + snprintf(buf, max, " R=%ld%s", t->ref_cnt(),
870 cur_t == t ? " "JDB_ANSI_COLOR(green)"current"JDB_ANSI_END : "");
872 return cnt + snprintf(buf, max, " C=%u S=D:%lx R=%ld %s", t->cpu(),
873 Kobject_dbg::pointer_to_id(t->space()),
875 cur_t == t ? " "JDB_ANSI_COLOR(green)"current"JDB_ANSI_END : "");
880 Jdb_tcb::kobject_type() const
882 return JDB_ANSI_COLOR(green) "Thread" JDB_ANSI_COLOR(default);
886 Jdb_module::Cmd const *
887 Jdb_tcb::cmds() const
891 { 0, "t", "tcb", "%C",
892 "t[<threadid>]\tshow current/given thread control block (TCB)\n"
893 "t{+|-}\tshow current thread control block at Jdb every entry\n",
901 Jdb_tcb::num_cmds() const
904 static Jdb_tcb jdb_tcb INIT_PRIORITY(JDB_MODULE_INIT_PRIO);
907 jdb_show_tcb(Thread *t, int level)
908 { return Jdb_tcb::show(t, level); }
912 Jdb_tcb::print_thread_uid_raw(Thread *t)
919 Jdb_tcb::print_kobject(Mword n)
921 printf("[C:%4lx] ", n);
926 Jdb_tcb::print_kobject(Kobject *o)
928 printf("D:%4lx ", o ? o->dbg_info()->dbg_id() : 0);
933 Jdb_tcb::print_kobject(Thread *t, Mword capidx)
935 Space *space = t->space();
938 print_kobject(capidx);
942 Obj_space::Capability *c = space->obj_space()->get_cap(capidx);
943 if (!c || !c->valid())
945 print_kobject(capidx);
949 printf("[C:%4lx] D:%4lx", capidx, c->obj()->dbg_info()->dbg_id());
953 //-----------------------------------------------------------------------------
954 // prompt extension for thread names
955 class Jdb_thread_name_ext : public Jdb_prompt_ext
964 Jdb_thread_name_ext::ext()
966 if (Jdb::get_current_active())
968 Jdb_kobject_name *nx = Jdb_kobject_extension::find_extension<Jdb_kobject_name>(Jdb::get_current_active());
969 if (nx && nx->name()[0])
970 printf("[%*.*s] ", nx->max_len(), nx->max_len(), nx->name());
976 Jdb_thread_name_ext::update()
978 Jdb::get_current(Jdb::current_cpu);
981 static Jdb_thread_name_ext jdb_thread_name_ext INIT_PRIORITY(JDB_MODULE_INIT_PRIO);