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)
459 Thread *t_current = Jdb::get_current_active();
460 bool is_current_thread;
461 bool redraw_screen = true;
462 Jdb_entry_frame *ef = Jdb::get_entry_frame(Jdb::current_cpu);
464 Address bt_start = 0;
467 if (!t && !t_current)
471 = (Config::thread_block_size * Mem_layout::max_threads()) - 1;
472 const Mword tsksz = Config::thread_block_size*L4_uid::threads_per_task();
473 LThread_num task = ((Address)Jdb::get_thread() & mask) / tsksz;
477 print_entry_frame_regs(0);
485 is_current_thread = t == t_current;
490 puts(" Invalid thread");
497 Jdb::clear_screen(Jdb::FANCY);
498 redraw_screen = false;
505 Jdb::clear_screen(Jdb::NOFANCY);
506 redraw_screen = false;
512 Jdb_kobject::print_uid(t->kobject(), 3);
513 print_thread_uid_raw(t);
514 printf("CPU %3u ", t->cpu());
516 printf("\tprio: %02x mode: %s\n",
518 t->mode() & Context::Periodic ?
519 t->mode() & Context::Nonstrict ? "Per (IRT)" : "Per (SP)" : "Con");
521 printf("state: %03lx ", t->state());
522 t->print_state_long();
524 putstr("\n\nwait for: ");
528 Jdb_thread::print_partner(t, 4);
530 putstr(" polling: ");
531 Jdb_thread::print_snd_partner(t, 3);
533 putstr("\trcv descr: ");
535 if (t->state() & Thread_ipc_receiving_mask)
536 printf("%08lx", t->rcv_regs()->from_spec());
542 if (t->thread_lock()->lock_owner())
543 Jdb_kobject::print_uid(Thread::lookup(t->thread_lock()->lock_owner())->kobject(), 3);
545 putstr("\t\t\ttimeout : ");
546 if (t->_timeout && t->_timeout->is_set())
548 Signed64 diff = (t->_timeout->get_timeout(Kip::k()->clock)) * 1000;
550 strcpy(time_str, "over");
552 Jdb::write_ll_ns(diff, time_str,
553 11 < sizeof(time_str)-1 ? 11 : sizeof(time_str)-1,
555 printf("%-13s", time_str);
558 putstr("\ncpu time: ");
559 Jdb::write_ll_ns(t->consumed_time()*1000, time_str,
560 11 < sizeof(time_str) ? 11 : sizeof(time_str), false);
561 printf("%-13s", time_str);
563 printf("\t\ttimeslice: %llu/%llu %cs\n"
565 t->sched()->left(), 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()));
575 printf("%08lx", (Mword)t->utcb());
577 putstr("\nexc-hndl: ");
578 print_kobject(t, t->_exc_handler.raw());
581 putstr("\tready lnk: ");
582 if (t->state() & 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");
602 putstr("\tprsent lnk: ");
603 if (t->Present_list_item::next())
604 Jdb_kobject::print_uid(static_cast<Thread*>(t->Present_list_item::next())->kobject(), 3);
607 if (t->Present_list_item::prev())
608 Jdb_kobject::print_uid(static_cast<Thread*>(t->Present_list_item::prev())->kobject(), 4);
614 if (t->state() & Thread_vcpu_enabled)
618 printf("c=%s s=%s sf=%c e-ip=%08lx e-sp=%08lx S=",
619 vcpu_state_str(t->vcpu_state()->state, st1, sizeof(st1)),
620 vcpu_state_str(t->vcpu_state()->_saved_state, st2, sizeof(st2)),
621 (t->vcpu_state()->sticky_flags & Vcpu_state::Sf_irq_pending) ? 'P' : '-',
622 t->vcpu_state()->_entry_ip, t->vcpu_state()->_entry_sp);
623 print_kobject(static_cast<Task*>(t->vcpu_user_space()));
629 Address ksp = is_current_thread ? ef->ksp()
630 : (Address)t->get_kernel_sp();
633 Address tcb = (Address)context_of((void*)ksp);
635 _stack_view.init(ksp, ef, is_current_thread);
637 if (is_current_thread)
638 print_entry_frame_regs(t->space());
640 else if (t->space() != Kernel_task::kernel_task())
643 info_thread_state(t);
645 print_return_frame_regs(_stack_view.current, ksp);
647 _disasm_view.show(_stack_view.current, t->space());
653 printf("kernel SP="ADDR_FMT, ksp);
658 // dump the stack from ksp bottom right to tcb_top
661 for (bool redraw=false; ; )
663 _stack_view.highlight(true);
664 int c=Jdb_core::getchar();
665 _stack_view.highlight(false);
666 Jdb::cursor(Jdb_screen::height(), 6);
668 if (c == KEY_CURSOR_HOME && level > 0)
671 if (!_stack_view.handle_key(c, &redraw))
676 if (jdb_dump_addr_task && _stack_view.current.valid())
678 if (!jdb_dump_addr_task(_stack_view.current.value(),
679 _stack_view.current.is_user_value() ? t->space() : 0, level+1))
681 redraw_screen = true;
685 //bt_start = search_bt_start(tcb, (Mword*)ksp, is_current_thread);
689 if (Jdb_disasm::avail() && _stack_view.current.valid())
691 printf("V %lx\n", _stack_view.current.value());
692 if (!Jdb_disasm::show(_stack_view.current.value(),
693 _stack_view.current.is_user_value() ? t->space() : 0, level+1, true))
695 redraw_screen = true;
699 if (Jdb_disasm::avail() && _stack_view.current.valid())
701 Jdb::printf_statline("tcb", "<CR>=disassemble here",
702 "u[address=%08lx task=%lx] ",
703 _stack_view.current.value(),
704 Kobject_dbg::pointer_to_id(t->space()));
705 int c1 = Jdb_core::getchar();
706 if ((c1 != KEY_RETURN) && (c1 != ' '))
708 Jdb::printf_statline("tcb", 0, "u");
709 Jdb::execute_command("u", c1);
713 if (!Jdb_disasm::show(_stack_view.current.value(),
714 _stack_view.current.is_user_value() ? t->space() : 0, level+1, true))
716 redraw_screen = true;
720 case 'r': // ready-list
721 putstr("[n]ext/[p]revious in ready list?");
722 switch (Jdb_core::getchar())
727 t = static_cast<Thread*>(t->_ready_next);
734 t = static_cast<Thread*>(t->_ready_prev);
741 case 'p': // present-list or show_pages
742 putstr("[n]ext/[p]revious in present list?");
743 switch (c=Jdb_core::getchar())
746 if (t->Present_list_item::next())
748 t = static_cast<Thread*>(t->Present_list_item::next());
753 if (t->Present_list_item::prev())
755 t = static_cast<Thread*>(t->Present_list_item::prev());
760 Jdb::execute_command("p", c);
765 _stack_view.memdump_is_colored = !_stack_view.memdump_is_colored;
769 Jdb::abort_command();
772 if (Jdb::is_toplevel_cmd(c))
784 /* --- original L4 screen ------------------------------------------------------
785 thread: 0081 (001.01) <00020401 00080000> prio: 10
786 state : 85, ready lists: 81 mcp: ff
788 wait for: -- rcv descr: 00000000 partner: 00000000
789 sndq : 0081 0081 timeouts: 00000000 waddr0/1: 000/000
790 cpu time: 0000000000 timeslice: 01/0a
792 pager : -- prsent lnk: 0080 0080
793 ipreempt: -- ready link : 0080 0080
796 EAX=00202dfe ESI=00020401 DS=0008 late wakeup lnk:
797 EBX=00000028 EDI=00080000 ES=0008
798 ECX=00000003 EBP=e0020400
799 EDX=00000001 ESP=e00207b4
806 7a0: 0000897b 00000020 00240082
807 7c0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
808 7e0: 00000000 00000000 ffffff80 00000000 0000001b 00003200 00000000 00000013
810 ------------------------------------------------------------------------------*/
813 Jdb_module::Action_code
814 Jdb_tcb::action(int cmd, void *&args, char const *&fmt, int &next_char)
816 static Address tcb_addr = 0;
819 if (args == &first_char)
825 printf("%c\n", first_char);
826 auto_tcb = first_char == '+';
830 fmt = " addr="ADDR_FMT" => ";
832 return Jdb_module::EXTRA_INPUT;
837 return Jdb_module::EXTRA_INPUT;
844 next_char = first_char;
845 return Jdb_module::EXTRA_INPUT_WITH_NEXTCHAR;
848 else if (args == &address)
850 address &= ~(Config::thread_block_size-1);
851 Jdb_kobject::print_uid(reinterpret_cast<Thread*>(address)->kobject(), 3);
854 else if (args == &tcb_addr)
855 show((Thread*)tcb_addr, 0);
858 Thread *t = Kobject::dcast<Thread_object *>(threadid);
862 printf("\nNot a thread\n");
871 Jdb_tcb::follow_link(Kobject *o)
873 Thread *t = Kobject::dcast<Thread_object *>(o);
874 if (t->space() == Kernel_task::kernel_task())
876 return static_cast<Kobject*>(static_cast<Task*>(t->space()));
881 Jdb_tcb::show_kobject(Kobject *o, int level)
883 Thread *t = Kobject::dcast<Thread_object *>(o);
884 return show(t, level);
889 Jdb_tcb::show_kobject_short(char *buf, int max, Kobject *o)
891 Thread *t = Kobject::dcast<Thread_object *>(o);
892 Thread *cur_t = Jdb::get_current_active();
894 if (t->space() == Kernel_task::kernel_task())
896 cnt = snprintf(buf, max, " {KERNEL} C=%u", t->cpu());
900 if (t->space() == Kernel_task::kernel_task())
901 return cnt + snprintf(buf, max, " R=%ld%s", t->ref_cnt(),
902 cur_t == t ? " "JDB_ANSI_COLOR(green)"current"JDB_ANSI_END : "");
904 return cnt + snprintf(buf, max, " C=%u S=D:%lx R=%ld %s", t->cpu(),
905 Kobject_dbg::pointer_to_id(t->space()),
907 cur_t == t ? " "JDB_ANSI_COLOR(green)"current"JDB_ANSI_END : "");
912 Jdb_tcb::kobject_type() const
914 return JDB_ANSI_COLOR(green) "Thread" JDB_ANSI_COLOR(default);
918 Jdb_module::Cmd const *
919 Jdb_tcb::cmds() const
923 { 0, "t", "tcb", "%C",
924 "t[<threadid>]\tshow current/given thread control block (TCB)\n"
925 "t{+|-}\tshow current thread control block at Jdb every entry\n",
933 Jdb_tcb::num_cmds() const
936 static Jdb_tcb jdb_tcb INIT_PRIORITY(JDB_MODULE_INIT_PRIO);
939 jdb_show_tcb(Thread *t, int level)
940 { return Jdb_tcb::show(t, level); }
944 Jdb_tcb::print_thread_uid_raw(Thread *t)
951 Jdb_tcb::print_kobject(Mword n)
953 printf("[C:%4lx] ", n);
958 Jdb_tcb::print_kobject(Kobject *o)
960 printf("D:%4lx ", o ? o->dbg_id() : 0);
965 Jdb_tcb::print_kobject(Thread *t, Mword capidx)
967 Space *space = t->space();
970 print_kobject(capidx);
974 Obj_space::Capability *c = space->obj_space()->get_cap(capidx);
975 if (!c || !c->valid())
977 print_kobject(capidx);
981 printf("[C:%4lx] D:%4lx", capidx, c->obj()->dbg_info()->dbg_id());
985 //-----------------------------------------------------------------------------
986 // prompt extension for thread names
987 class Jdb_thread_name_ext : public Jdb_prompt_ext
996 Jdb_thread_name_ext::ext()
998 if (Jdb::get_current_active())
1000 Jdb_kobject_name *nx = Jdb_kobject_extension::find_extension<Jdb_kobject_name>(Jdb::get_current_active()->kobject());
1001 if (nx && nx->name()[0])
1002 printf("[%*.*s] ", nx->max_len(), nx->max_len(), nx->name());
1008 Jdb_thread_name_ext::update()
1010 Jdb::get_current(Jdb::current_cpu);
1013 static Jdb_thread_name_ext jdb_thread_name_ext INIT_PRIORITY(JDB_MODULE_INIT_PRIO);