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"
28 #include "push_console.h"
30 #include "static_init.h"
33 #include "thread_state.h"
36 IMPLEMENTATION [32bit]:
37 #define ADDR_FMT "%08lx"
39 IMPLEMENTATION [64bit]:
40 #define ADDR_FMT "%016lx"
48 Jdb_tcb_ptr(Address addr = 0)
49 : _base(addr & ~(Config::thread_block_size-1)),
50 _offs(addr & (Config::thread_block_size-1))
53 Jdb_tcb_ptr(Jdb_tcb_ptr const &p)
54 : _base(p.base()), _offs(p.offs())
57 inline bool valid() const
58 { return _offs <= Config::thread_block_size-sizeof(Mword); }
60 bool operator > (int offs) const
62 return offs < 0 ? _offs > Config::thread_block_size + offs*sizeof(Mword)
63 : _offs > offs*sizeof(Mword);
66 Jdb_tcb_ptr &operator += (int offs)
67 { _offs += offs*sizeof(Mword); return *this; }
69 inline Address addr() const
70 { return _base + _offs; }
72 inline Mword value() const
73 { return *(Mword*)(_base + _offs); }
75 inline void value(Mword v)
76 { *(Mword*)(_base + _offs) = v; }
78 inline bool is_user_value() const;
80 inline const char *user_value_desc() const;
82 inline Mword top_value(int offs) const
83 { return *((Mword*)(Cpu::stack_align(_base + Config::thread_block_size)) + offs); }
85 inline Address base() const
88 inline Address offs() const
91 inline void offs(Address offs)
94 inline bool is_kern_code() const
95 { return (Address)&Mem_layout::image_start <= value()
96 && value() <= (Address)&Mem_layout::ecode; };
98 inline bool is_kobject() const
99 { return Kobject_dbg::is_kobj(reinterpret_cast<void *>(value())); }
106 class Jdb_disasm_view
122 bool memdump_is_colored;
124 bool edit_registers();
128 class Jdb_tcb : public Jdb_module, public Jdb_kobject_handler
130 static Kobject *threadid;
131 static Address address;
132 static char first_char;
133 static char auto_tcb;
136 static void print_return_frame_regs(Jdb_tcb_ptr const ¤t, Mword ksp);
137 static void print_entry_frame_regs(Space *task);
138 static void info_thread_state(Thread *t);
140 static Jdb_disasm_view _disasm_view;
141 static Jdb_stack_view _stack_view;
146 Kobject *Jdb_tcb::threadid;
147 Address Jdb_tcb::address;
148 char Jdb_tcb::first_char;
149 char Jdb_tcb::auto_tcb;
150 Jdb_disasm_view Jdb_tcb::_disasm_view(Jdb_tcb::Disasm_x, Jdb_tcb::Disasm_y);
151 Jdb_stack_view Jdb_tcb::_stack_view (Jdb_tcb::Stack_y);
154 // available from jdb_dump module
155 extern int jdb_dump_addr_task (Address addr, Space *task, int level)
156 __attribute__((weak));
159 Jdb_stack_view::Jdb_stack_view(unsigned y)
160 : start_y(y), absy(0), memdump_is_colored(true)
165 Jdb_stack_view::cols()
167 return Jdb_screen::cols() - 1;
172 Jdb_stack_view::bytes_per_line()
173 { return cols() * sizeof(Mword); }
177 Jdb_stack_view::init(Address ksp, Jdb_entry_frame *_ef, bool _is_current)
179 current = Jdb_tcb_ptr(ksp);
181 absy = current.offs() / bytes_per_line();
182 addx = (current.offs() % bytes_per_line()) / sizeof(Mword);
185 is_current = _is_current;
190 Jdb_stack_view::print_value(Jdb_tcb_ptr const &p, bool highl = false)
192 if (!p.valid() || !Jdb_util::is_mapped((void const*)p.addr()))
194 printf(" %.*s", Jdb_screen::Mword_size_bmode, Jdb_screen::Mword_not_mapped);
198 const char *s1="", *s2="";
204 else if (p.is_user_value())
209 else if (memdump_is_colored)
211 if (p.is_kern_code())
213 s1 = JDB_ANSI_COLOR(lightblue);
216 else if (p.is_kobject())
218 s1 = JDB_ANSI_COLOR(lightgreen);
221 /* else if (p.in_backtrace(...
228 printf(" %s"ADDR_FMT"%s", s1, p.value(), s2);
234 Jdb_stack_view::dump()//Jdb_tcb_ptr const ¤t)
236 Jdb_tcb_ptr p = current;
237 p.offs(absy * bytes_per_line());
239 Jdb::cursor(start_y, 1);
241 for (unsigned y = 0; y < Jdb_screen::height() - start_y; ++y)
243 Kconsole::console()->getchar_chance();
247 printf(" %03lx ", p.addr() & 0xfff);
248 for (unsigned x = 0; x < cols(); ++x, p+=1)
259 Jdb_stack_view::posx()
260 { return addx * (Jdb_screen::Mword_size_bmode + 1) + 9; }
264 Jdb_stack_view::posy()
265 { return addy + start_y; }
269 Jdb_stack_view::highlight(bool highl)
271 current.offs(absy*bytes_per_line() + addy*bytes_per_line() + addx * sizeof(Mword));
272 Jdb_tcb_ptr first_col = current;
273 first_col.offs(absy*bytes_per_line() + addy*bytes_per_line());
275 if (!current.valid())
278 Jdb::cursor(posy(), 1);
280 printf("%08lx", current.addr() & 0xffffffff);
282 printf(" %03lx ", first_col.addr() & 0xfff);
283 Jdb::cursor(posy(), posx());
284 print_value(current, highl);
289 if (current.is_kern_code())
290 strcpy(kobj_desc, "Kernel code"); // todo: print kernel function name
291 else if (current.is_user_value())
292 snprintf(kobj_desc, sizeof(kobj_desc), "Return frame: %s",
293 current.user_value_desc());
295 if (Kobject *o = Kobject::pointer_to_obj(reinterpret_cast<void *>(current.value())))
297 Jdb_kobject::obj_description(kobj_desc, sizeof(kobj_desc), true, o);
298 kobj_desc[sizeof(kobj_desc) - 1] = 0;
301 Jdb::printf_statline("tcb", "<CR>=dump <Space>=Disas",
307 Jdb_stack_view::handle_key(int key, bool *redraw)
309 Mword lines = Jdb_screen::height() - start_y;
310 Mword max_lines = (Config::thread_block_size + bytes_per_line() - 1)/bytes_per_line();
311 Address max_absy = max_lines - lines;
313 if (lines > max_lines)
316 if (lines > max_lines - absy)
317 lines = max_lines - absy;
322 return Jdb::std_cursor_key(key, this->cols(), lines, max_absy,
323 &absy, &addy, &addx, redraw);
330 Jdb_stack_view::edit_stack(bool *redraw)
337 Jdb::cursor(posy(), posx());
338 printf(" %.*s", Jdb_screen::Mword_size_bmode, Jdb_screen::Mword_blank);
339 Jdb::printf_statline("tcb",
340 is_current ? "<Space>=edit registers" : 0,
341 "edit <"ADDR_FMT"> = "ADDR_FMT,
342 current.addr(), current.value());
344 Jdb::cursor(posy(), posx() + 1);
345 c = Jdb_core::getchar();
353 if (c != ' ' || !is_current)
357 Jdb::printf_statline("tcb", 0, "edit <"ADDR_FMT"> = "ADDR_FMT,
358 current.addr(), current.value());
359 Jdb::cursor(posy(), posx() + 1);
360 if (!Jdb_input::get_mword(&value, c, 16))
362 Jdb::cursor(posy(), posx());
363 print_value(current);
367 current.value(value);
372 Jdb::cursor(posy(), posx());
373 print_value(current);
382 Jdb_disasm_view::Jdb_disasm_view(unsigned x, unsigned y)
388 Jdb_disasm_view::show(Jdb_tcb_ptr const &p, Space *s)
390 if (!Jdb_disasm::avail())
393 Address disass_addr = p.top_value(-5);
395 putstr(Jdb::esc_emph);
396 Jdb_disasm::show_disasm_line(-40, disass_addr, 0, s);
398 Jdb::cursor(_y + 1, _x);
399 Jdb_disasm::show_disasm_line(-40, disass_addr, 0, s);
405 : Jdb_module("INFO"), Jdb_kobject_handler(Thread::static_kobj_type)
407 static Jdb_handler enter(at_jdb_enter);
409 Jdb::jdb_enter.add(&enter);
410 Jdb_kobject::module()->register_handler(this);
414 Jdb_tcb::at_jdb_enter()
418 // clear any keystrokes in queue
419 Jdb::set_next_cmd(0);
420 Jdb::push_cons()->push('t');
421 Jdb::push_cons()->push(' ');
428 Jdb_tcb::parent(Kobject *o)
430 Thread *t = Kobject::dcast<Thread*>(o);
434 return static_cast<Task*>(t->space());
437 PRIVATE static inline
439 Jdb_tcb::vcpu_state_str(Mword state, char *s, int len)
441 snprintf(s, len, "%c%c%c%c%c%c",
442 (state & Vcpu_state::F_fpu_enabled) ? 'F' : 'f',
443 (state & Vcpu_state::F_user_mode) ? 'U' : 'u',
444 (state & Vcpu_state::F_debug_exc) ? 'D' : 'd',
445 (state & Vcpu_state::F_exceptions) ? 'E' : 'e',
446 (state & Vcpu_state::F_page_faults) ? 'P' : 'p',
447 (state & Vcpu_state::F_irqs) ? 'I' : 'i');
453 Jdb_module::Action_code
454 Jdb_tcb::show(Thread *t, int level)
458 Thread *t_current = Jdb::get_current_active();
459 bool is_current_thread;
460 bool redraw_screen = true;
461 Jdb_entry_frame *ef = Jdb::get_entry_frame(Jdb::current_cpu);
463 Address bt_start = 0;
466 if (!t && !t_current)
470 = (Config::thread_block_size * Mem_layout::max_threads()) - 1;
471 const Mword tsksz = Config::thread_block_size*L4_uid::threads_per_task();
472 LThread_num task = ((Address)Jdb::get_thread() & mask) / tsksz;
476 print_entry_frame_regs(0);
484 is_current_thread = t == t_current;
489 puts(" Invalid thread");
496 Jdb::clear_screen(Jdb::FANCY);
497 redraw_screen = false;
504 Jdb::clear_screen(Jdb::NOFANCY);
505 redraw_screen = false;
511 Jdb_kobject::print_uid(t, 3);
512 print_thread_uid_raw(t);
513 printf("CPU %3u ", t->cpu());
515 printf("\tprio: %02x mode: %s\n",
517 t->mode() & Context::Periodic ?
518 t->mode() & Context::Nonstrict ? "Per (IRT)" : "Per (SP)" : "Con");
520 printf("state: %03lx ", t->state());
521 t->print_state_long();
523 putstr("\n\nwait for: ");
527 Jdb_thread::print_partner(t, 4);
529 putstr(" polling: ");
530 Jdb_thread::print_snd_partner(t, 3);
532 putstr("\trcv descr: ");
534 if (t->state() & Thread_ipc_receiving_mask)
535 printf("%08lx", t->rcv_regs()->from_spec());
541 Jdb_kobject::print_uid(Thread::lookup(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()));
573 printf("%08lx", (Mword)t->utcb());
575 putstr("\nexc-hndl: ");
576 print_kobject(t, t->_exc_handler.raw());
579 putstr("\tready lnk: ");
580 if (t->state() & 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");
600 putstr("\tprsent lnk: ");
601 if (t->Present_list_item::next())
602 Jdb_kobject::print_uid(static_cast<Thread*>(t->Present_list_item::next()), 3);
605 if (t->Present_list_item::prev())
606 Jdb_kobject::print_uid(static_cast<Thread*>(t->Present_list_item::prev()), 4);
612 if (t->state() & Thread_vcpu_enabled)
616 printf("c=%s s=%s e-ip=%08lx e-sp=%08lx S=",
617 vcpu_state_str(t->vcpu_state()->state, st1, sizeof(st1)),
618 vcpu_state_str(t->vcpu_state()->_saved_state, st2, sizeof(st2)),
619 t->vcpu_state()->_entry_ip, t->vcpu_state()->_entry_sp);
620 print_kobject(static_cast<Task*>(t->vcpu_user_space()));
626 Address ksp = is_current_thread ? ef->ksp()
627 : (Address)t->get_kernel_sp();
630 Address tcb = (Address)context_of((void*)ksp);
632 _stack_view.init(ksp, ef, is_current_thread);
634 if (is_current_thread)
635 print_entry_frame_regs(t->space());
637 else if (t->space() != Kernel_task::kernel_task())
640 info_thread_state(t);
642 print_return_frame_regs(_stack_view.current, ksp);
644 _disasm_view.show(_stack_view.current, t->space());
650 printf("kernel SP="ADDR_FMT, ksp);
655 // dump the stack from ksp bottom right to tcb_top
658 for (bool redraw=false; ; )
660 _stack_view.highlight(true);
661 int c=Jdb_core::getchar();
662 _stack_view.highlight(false);
663 Jdb::cursor(Jdb_screen::height(), 6);
665 if (c == KEY_CURSOR_HOME && level > 0)
668 if (!_stack_view.handle_key(c, &redraw))
673 if (jdb_dump_addr_task && _stack_view.current.valid())
675 if (!jdb_dump_addr_task(_stack_view.current.value(),
676 _stack_view.current.is_user_value() ? t->space() : 0, level+1))
678 redraw_screen = true;
682 //bt_start = search_bt_start(tcb, (Mword*)ksp, is_current_thread);
686 if (Jdb_disasm::avail() && _stack_view.current.valid())
688 printf("V %lx\n", _stack_view.current.value());
689 if (!Jdb_disasm::show(_stack_view.current.value(),
690 _stack_view.current.is_user_value() ? t->space() : 0, level+1, true))
692 redraw_screen = true;
696 if (Jdb_disasm::avail() && _stack_view.current.valid())
698 Jdb::printf_statline("tcb", "<CR>=disassemble here",
699 "u[address=%08lx task=%lx] ",
700 _stack_view.current.value(),
701 Kobject_dbg::pointer_to_id(t->space()));
702 int c1 = Jdb_core::getchar();
703 if ((c1 != KEY_RETURN) && (c1 != ' '))
705 Jdb::printf_statline("tcb", 0, "u");
706 Jdb::execute_command("u", c1);
710 if (!Jdb_disasm::show(_stack_view.current.value(),
711 _stack_view.current.is_user_value() ? t->space() : 0, level+1, true))
713 redraw_screen = true;
717 case 'r': // ready-list
718 putstr("[n]ext/[p]revious in ready list?");
719 switch (Jdb_core::getchar())
724 t = static_cast<Thread*>(t->_ready_next);
731 t = static_cast<Thread*>(t->_ready_prev);
738 case 'p': // present-list or show_pages
739 putstr("[n]ext/[p]revious in present list?");
740 switch (c=Jdb_core::getchar())
743 if (t->Present_list_item::next())
745 t = static_cast<Thread*>(t->Present_list_item::next());
750 if (t->Present_list_item::prev())
752 t = static_cast<Thread*>(t->Present_list_item::prev());
757 Jdb::execute_command("p", c);
762 _stack_view.memdump_is_colored = !_stack_view.memdump_is_colored;
766 Jdb::abort_command();
769 if (Jdb::is_toplevel_cmd(c))
781 /* --- original L4 screen ------------------------------------------------------
782 thread: 0081 (001.01) <00020401 00080000> prio: 10
783 state : 85, ready lists: 81 mcp: ff
785 wait for: -- rcv descr: 00000000 partner: 00000000
786 sndq : 0081 0081 timeouts: 00000000 waddr0/1: 000/000
787 cpu time: 0000000000 timeslice: 01/0a
789 pager : -- prsent lnk: 0080 0080
790 ipreempt: -- ready link : 0080 0080
793 EAX=00202dfe ESI=00020401 DS=0008 late wakeup lnk:
794 EBX=00000028 EDI=00080000 ES=0008
795 ECX=00000003 EBP=e0020400
796 EDX=00000001 ESP=e00207b4
803 7a0: 0000897b 00000020 00240082
804 7c0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
805 7e0: 00000000 00000000 ffffff80 00000000 0000001b 00003200 00000000 00000013
807 ------------------------------------------------------------------------------*/
810 Jdb_module::Action_code
811 Jdb_tcb::action(int cmd, void *&args, char const *&fmt, int &next_char)
813 static Address tcb_addr = 0;
816 if (args == &first_char)
822 printf("%c\n", first_char);
823 auto_tcb = first_char == '+';
827 fmt = " addr="ADDR_FMT" => ";
829 return Jdb_module::EXTRA_INPUT;
834 return Jdb_module::EXTRA_INPUT;
841 next_char = first_char;
842 return Jdb_module::EXTRA_INPUT_WITH_NEXTCHAR;
845 else if (args == &address)
847 address &= ~(Config::thread_block_size-1);
848 Jdb_kobject::print_uid(reinterpret_cast<Thread*>(address), 3);
851 else if (args == &tcb_addr)
852 show((Thread*)tcb_addr, 0);
855 Thread *t = Kobject::dcast<Thread *>(threadid);
859 printf("\nNot a thread\n");
868 Jdb_tcb::follow_link(Kobject *o)
870 Thread *t = Kobject::dcast<Thread*>(o);
871 if (t->space() == Kernel_task::kernel_task())
873 return static_cast<Kobject*>(static_cast<Task*>(t->space()));
878 Jdb_tcb::show_kobject(Kobject *o, int level)
880 Thread *t = Kobject::dcast<Thread*>(o);
881 return show(t, level);
886 Jdb_tcb::show_kobject_short(char *buf, int max, Kobject *o)
888 Thread *t = Kobject::dcast<Thread*>(o);
889 Thread *cur_t = Jdb::get_current_active();
891 if (t->space() == Kernel_task::kernel_task())
893 cnt = snprintf(buf, max, " {KERNEL} C=%u", t->cpu());
897 if (t->space() == Kernel_task::kernel_task())
898 return cnt + snprintf(buf, max, " R=%ld%s", t->ref_cnt(),
899 cur_t == t ? " "JDB_ANSI_COLOR(green)"current"JDB_ANSI_END : "");
901 return cnt + snprintf(buf, max, " C=%u S=D:%lx R=%ld %s", t->cpu(),
902 Kobject_dbg::pointer_to_id(t->space()),
904 cur_t == t ? " "JDB_ANSI_COLOR(green)"current"JDB_ANSI_END : "");
909 Jdb_tcb::kobject_type() const
911 return JDB_ANSI_COLOR(green) "Thread" JDB_ANSI_COLOR(default);
915 Jdb_module::Cmd const *
916 Jdb_tcb::cmds() const
920 { 0, "t", "tcb", "%C",
921 "t[<threadid>]\tshow current/given thread control block (TCB)\n"
922 "t{+|-}\tshow current thread control block at Jdb every entry\n",
930 Jdb_tcb::num_cmds() const
933 static Jdb_tcb jdb_tcb INIT_PRIORITY(JDB_MODULE_INIT_PRIO);
936 jdb_show_tcb(Thread *t, int level)
937 { return Jdb_tcb::show(t, level); }
941 Jdb_tcb::print_thread_uid_raw(Thread *t)
948 Jdb_tcb::print_kobject(Mword n)
950 printf("[C:%4lx] ", n);
955 Jdb_tcb::print_kobject(Kobject *o)
957 printf("D:%4lx ", o ? o->dbg_id() : 0);
962 Jdb_tcb::print_kobject(Thread *t, Mword capidx)
964 Space *space = t->space();
967 print_kobject(capidx);
971 Obj_space::Capability *c = space->obj_space()->get_cap(capidx);
972 if (!c || !c->valid())
974 print_kobject(capidx);
978 printf("[C:%4lx] D:%4lx", capidx, c->obj()->dbg_info()->dbg_id());
982 //-----------------------------------------------------------------------------
983 // prompt extension for thread names
984 class Jdb_thread_name_ext : public Jdb_prompt_ext
993 Jdb_thread_name_ext::ext()
995 if (Jdb::get_current_active())
997 Jdb_kobject_name *nx = Jdb_kobject_extension::find_extension<Jdb_kobject_name>(Jdb::get_current_active());
998 if (nx && nx->name()[0])
999 printf("[%*.*s] ", nx->max_len(), nx->max_len(), nx->name());
1005 Jdb_thread_name_ext::update()
1007 Jdb::get_current(Jdb::current_cpu);
1010 static Jdb_thread_name_ext jdb_thread_name_ext INIT_PRIORITY(JDB_MODULE_INIT_PRIO);