15 static const char * const reg_names[];
19 s_unknown, s_ipc, s_syscall, s_pagefault, s_fputrap,
20 s_interrupt, s_timer_interrupt, s_slowtrap, s_user_invoke,
21 } Guessed_thread_state;
23 enum { MIN_SCREEN_HEIGHT = 20, MIN_SCREEN_WIDTH = 80 };
25 template < typename T > static T peek(T const *addr, Address_type user);
27 static int (*bp_test_log_only)();
28 static int (*bp_test_break)(char *errbuf, size_t bufsize);
31 static unsigned short rows, cols;
38 #include <sys/ioctl.h>
43 #include "initcalls.h"
45 #include "jdb_dbinfo.h"
46 #include "jdb_screen.h"
47 #include "kernel_console.h"
48 #include "kernel_task.h"
49 #include "kernel_thread.h"
52 #include "libc_support.h"
54 #include "mem_layout.h"
55 #include "push_console.h"
58 #include "static_init.h"
60 #include "thread_state.h"
61 #include "trap_state.h"
65 int (*Jdb::bp_test_log_only)();
66 int (*Jdb::bp_test_break)(char *errbuf, size_t bufsize);
68 unsigned short Jdb::rows, Jdb::cols;
70 const char * const Jdb::reg_names[] =
71 { "EAX", "EBX", "ECX", "EDX", "EBP", "ESI", "EDI", "EIP", "ESP", "EFL" };
73 static Proc::Status jdb_irq_state;
77 Jdb::enter_trap_handler(unsigned /*cpu*/)
81 // Set terminal raw mode
84 // Flush all output streams
90 Jdb::leave_trap_handler(unsigned)
92 // Restore terminal mode
95 // Flush all output streams
99 signal (SIGIO, SIG_IGN); // Ignore hardware interrupts
102 PROTECTED static inline
104 Jdb::monitor_address(unsigned, void *)
109 Jdb::handle_user_request(unsigned /*cpu*/)
114 Jdb::test_checksums()
118 // disable interrupts before entering the kernel debugger
121 Jdb::save_disable_irqs(unsigned cpu)
124 jdb_irq_state = Proc::cli_save();
127 // restore interrupts after leaving the kernel debugger
130 Jdb::restore_irqs(unsigned cpu)
133 Proc::sti_restore(jdb_irq_state);
136 STATIC_INITIALIZE_P(Jdb,JDB_INIT_PRIO);
138 PUBLIC static FIASCO_INIT
142 // Install JDB handler
143 Trap_state::base_handler = (Trap_state::Handler)enter_jdb;
145 // be sure that Push_console comes very first
146 static Push_console c;
147 Kconsole::console()->register_console(&c, 0);
149 register_libc_atexit(leave_getchar);
151 Thread::set_int3_handler(handle_int3_threadctx);
159 ioctl (fileno (stdin), TIOCGWINSZ, &win);
163 if (rows < MIN_SCREEN_HEIGHT || cols < MIN_SCREEN_WIDTH)
164 printf ("%sTerminal probably too small, should be at least %dx%d!\033[0m\n",
165 esc_emph, MIN_SCREEN_WIDTH, MIN_SCREEN_HEIGHT);
167 Jdb_screen::set_height(rows);
168 Jdb_screen::set_width(cols);
171 /** handle int3 debug extension */
172 PUBLIC static inline NOEXPORT
174 Jdb::int3_extension()
176 Jdb_entry_frame *entry_frame = Jdb::entry_frame.cpu(0);
177 Address addr = entry_frame->ip();
178 Address_type user = (entry_frame->cs() & 3) ? ADDR_USER : ADDR_KERNEL;
179 Unsigned8 todo = peek ((Unsigned8 *) addr, user);
180 Space *space = NULL; //get_task_id(0);
182 if (todo == 0x3c && peek ((Unsigned8 *) (addr+1), user) == 13)
185 entry_frame->_ax = Vkey::get();
190 else if (todo != 0xeb)
192 snprintf (error_buffer.cpu(0), sizeof (error_buffer.cpu(0)), "INT 3");
196 // todo == 0xeb => enter_kdebug()
198 Mword len = peek ((Unsigned8 *) ++addr, user);
201 peek (((Unsigned8 *) addr + 1), user) == '*' &&
202 peek (((Unsigned8 *) addr + 2), user) == '#')
204 char c = peek (((Unsigned8 *) addr + 3), user);
207 ? execute_command_ni(space, (char const *) entry_frame->_ax)
208 : execute_command_ni(space, (char const *)(addr + 3), len-2))
209 return 1; // => leave Jdb
212 len = len < sizeof(error_buffer.cpu(0))-1 ? len : sizeof(error_buffer.cpu(0))-1;
213 for (i = 0; i < len; i++)
214 error_buffer.cpu(0)[i] = peek ((Unsigned8 *) ++addr, user);
215 error_buffer.cpu(0)[i] = 0;
221 Jdb::handle_special_cmds(int)
226 Jdb::handle_debug_traps(unsigned cpu)
228 switch (entry_frame.cpu(cpu)->_trapno)
231 snprintf (error_buffer.cpu(cpu), sizeof (error_buffer.cpu(cpu)), "Interception");
234 if (int3_extension())
237 if (get_thread(cpu)->d_taskno())
239 if (bp_test_log_only && bp_test_log_only())
242 && bp_test_break(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(cpu))))
253 Jdb::handle_nested_trap(Jdb_entry_frame *e)
255 printf("Trap in JDB: IP:%08lx\n", e->ip());
260 Jdb::handle_conditional_breakpoint(unsigned /*cpu*/)
266 Jdb::get_register(char *reg)
271 putchar(reg_name[0] = 'E');
278 putchar(reg_name[i] = c & 0xdf);
284 if (*((unsigned*)reg_name) == *((unsigned*)reg_names[i]))
297 Jdb::translate_task(Address /*addr*/, Space *task)
299 // we have no idea if addr belongs to kernel or user space
300 // since kernel and user occupy different address spaces
306 Jdb::virt_to_kvirt(Address virt, Mem_space* space)
308 Mem_space::Phys_addr phys;
309 Mem_space::Size size;
314 // We can directly access it via virtual addresses if it's kernel code
315 // (which is always mapped, but doesn't appear in the kernel pagetable)
316 // or if we find a mapping for it in the kernel's master pagetable.
317 return (virt >= (Address)&Mem_layout::load &&
318 virt < (Kernel_thread::init_done()
319 ? (Address)&Mem_layout::end
320 : (Address)&Mem_layout::initcall_end)
321 || Kernel_task::kernel_task()->mem_space()->v_lookup (
322 Mem_space::Addr::create(virt), 0, 0, 0))
329 // We can't directly access it because it's in a different host process
330 // but if the task's pagetable has a mapping for it, we can translate
331 // task-virtual -> physical -> kernel-virtual address and then access.
332 return (space->v_lookup (Mem_space::Addr::create(virt), &phys, &size, 0))
333 ? (Address) Kmem::phys_to_virt (phys.value() + (virt & (size.value()-1)))
338 IMPLEMENT inline NEEDS ["space.h"]
339 template <typename T>
341 Jdb::peek (T const *addr, Address_type user)
343 return current_mem_space()->peek(addr, user);
348 Jdb::peek_task(Address virt, Space *space, void *value, int width)
350 // make sure we don't cross a page boundary
351 if (virt & (width-1))
354 Address kvirt = virt_to_kvirt(virt, space?space->mem_space():0);
355 if (kvirt == (Address)-1)
358 memcpy(value, (void*)kvirt, width);
364 Jdb::poke_task(Address virt, Space *space, void const *value, int width)
366 // make sure we don't cross a page boundary
367 if (virt & (width-1))
370 Address kvirt = virt_to_kvirt(virt, space?space->mem_space():0);
372 if (kvirt == (Address)-1)
375 memcpy((void*)kvirt, value, width);
381 Jdb::is_adapter_memory(Address /*addr*/, Space * /*task*/)
386 #define WEAK __attribute__((weak))
387 extern "C" char in_slowtrap, in_page_fault, in_handle_fputrap;
388 extern "C" char in_interrupt, in_timer_interrupt, in_timer_interrupt_slow;
389 extern "C" char i30_ret_switch WEAK, in_slow_ipc1 WEAK;
390 extern "C" char in_slow_ipc2 WEAK, in_slow_ipc4;
391 extern "C" char in_sc_ipc1 WEAK, in_sc_ipc2 WEAK, in_syscall WEAK;
394 /** Try to guess the thread state of t by walking down the kernel stack and
395 * locking at the first return address we find. */
397 static Jdb::Guessed_thread_state
398 Jdb::guess_thread_state(Thread *t)
400 Guessed_thread_state state = s_unknown;
401 Mword *ktop = (Mword*)((Mword)context_of(t->get_kernel_sp()) +
402 Config::thread_block_size);
404 for (int i=-1; i>-26; i--)
408 if (ktop[i] == (Mword)&in_page_fault)
410 if ((ktop[i] == (Mword)&i30_ret_switch) ||// shortcut.S, int 0x30
411 (ktop[i] == (Mword)&in_slow_ipc1) || // shortcut.S, int 0x30
412 (ktop[i] == (Mword)&in_slow_ipc4) || // entry.S, int 0x30
413 #if !defined(CONFIG_ASSEMBLER_IPC_SHORTCUT)
414 (ktop[i] == (Mword)&in_sc_ipc1) || // entry.S, int 0x30
415 (ktop[i] == (Mword)&in_sc_ipc2) || // entry.S, sysenter
419 else if (ktop[i] == (Mword)&in_syscall)
421 else if (ktop[i] == (Mword)&Thread::user_invoke)
422 state = s_user_invoke;
423 else if (ktop[i] == (Mword)&in_handle_fputrap)
425 else if (ktop[i] == (Mword)&in_interrupt)
427 else if ((ktop[i] == (Mword)&in_timer_interrupt) ||
428 (ktop[i] == (Mword)&in_timer_interrupt_slow))
429 state = s_timer_interrupt;
430 else if (ktop[i] == (Mword)&in_slowtrap)
432 if (state != s_unknown)
437 if (state == s_unknown && (t->state() & Thread_ipc_mask))
443 // Don't make these members of Jdb else we have to include <termios.h>
444 // into the Jdb interface ...
445 static struct termios raw, new_raw;
446 static int getchar_entered;
448 /** prepare Linux console for raw input */
453 if (!getchar_entered++)
455 tcgetattr (fileno (stdin), &raw);
456 memcpy(&new_raw, &raw, sizeof(new_raw));
457 new_raw.c_lflag &= ~(ICANON|ECHO);
458 new_raw.c_cc[VMIN] = 0;
459 new_raw.c_cc[VTIME] = 1;
460 tcsetattr (fileno (stdin), TCSAFLUSH, &new_raw);
464 /** restore Linux console. */
469 if (!--getchar_entered)
470 tcsetattr (fileno (stdin), TCSAFLUSH, &raw);
473 PROTECTED static inline
474 template< typename T >
476 Jdb::set_monitored_address(T *dest, T val)
479 PROTECTED static inline
480 template< typename T >
481 T Jdb::monitor_address(unsigned, T volatile *addr)
486 //----------------------------------------------------------------------------
487 IMPLEMENTATION [ux && mp]:
491 Jdb::send_nmi(unsigned /*cpu*/)