1 INTERFACE[ia32,amd64,ux]:
13 enum Mode { INSTRUCTION=0, WRITE=1, PORTIO=2, ACCESS=3 };
14 enum Log { BREAK=0, LOG=1 };
56 static char const * const mode_names[4];
62 static int global_breakpoints();
63 static void init_arch();
66 static void at_jdb_enter();
67 static void at_jdb_leave();
68 static Breakpoint bps[4];
72 IMPLEMENTATION[ia32,amd64,ux]:
77 #include "jdb_input.h"
78 #include "jdb_module.h"
79 #include "jdb_handler_queue.h"
80 #include "jdb_screen.h"
83 #include "static_init.h"
86 class Jdb_set_bp : public Jdb_module, public Jdb_input_task_addr
89 Jdb_set_bp() FIASCO_INIT;
91 static char breakpoint_cmd;
92 static char breakpoint_restrict_cmd;
93 static Mword breakpoint_number;
94 static Mword breakpoint_length;
95 static Mword breakpoint_restrict_task;
96 static Mword breakpoint_restrict_thread;
103 static Restrict_reg breakpoint_restrict_reg;
110 static Restrict_addr breakpoint_restrict_addr;
114 Breakpoint Jdb_bp::bps[4];
116 char const * const Breakpoint::mode_names[4] =
118 "instruction", "write access", "i/o access", "r/w access"
121 char Jdb_set_bp::breakpoint_cmd;
122 char Jdb_set_bp::breakpoint_restrict_cmd;
123 Mword Jdb_set_bp::breakpoint_number;
124 Mword Jdb_set_bp::breakpoint_length;
125 Mword Jdb_set_bp::breakpoint_restrict_task;
126 Mword Jdb_set_bp::breakpoint_restrict_thread;
127 Jdb_set_bp::Restrict_reg Jdb_set_bp::breakpoint_restrict_reg;
128 Jdb_set_bp::Restrict_addr Jdb_set_bp::breakpoint_restrict_addr;
129 int Jdb_set_bp::state;
132 Breakpoint::Breakpoint()
134 restrict.thread.thread = 0;
135 restrict.task.task = 0;
138 PUBLIC inline NOEXPORT
145 PUBLIC inline NOEXPORT
152 PUBLIC inline NOEXPORT
154 Breakpoint::break_at_instruction()
156 return mode == INSTRUCTION;
159 PUBLIC inline NOEXPORT
161 Breakpoint::match_addr(Address virt, Mode m)
163 return !unused() && addr == virt && mode == m;
166 PUBLIC inline NOEXPORT
168 Breakpoint::set_logmode(char m)
170 log = (m == '*') ? LOG : BREAK;
173 PUBLIC inline NOEXPORT
175 Breakpoint::is_break()
177 return !unused() && log == BREAK;
182 Breakpoint::restrict_task(int other, Mword task)
184 restrict.task.other = other;
185 restrict.task.task = task;
188 PUBLIC inline NOEXPORT
190 Breakpoint::restrict_thread(int other, Mword thread)
192 restrict.thread.other = other;
193 restrict.thread.thread = thread;
196 PUBLIC inline NOEXPORT
198 Breakpoint::restrict_register(char reg, Mword y, Mword z)
200 restrict.reg.reg = reg;
205 PUBLIC inline NOEXPORT
207 Breakpoint::restrict_memory(Mword addr, Mword len, Mword y, Mword z)
209 restrict.mem.addr = addr;
210 restrict.mem.len = len;
215 PUBLIC inline NOEXPORT
217 Breakpoint::clear_restriction()
219 restrict.thread.thread = 0;
220 restrict.task.task = 0;
221 restrict.reg.reg = 0;
222 restrict.mem.len = 0;
231 printf("%5s on %12s at " L4_PTR_FMT,
232 log ? "LOG" : "BREAK", mode_names[mode & 3], addr);
233 if (mode != INSTRUCTION)
234 printf(" len %d", len);
238 if ( restrict.thread.thread == 0
239 && restrict.task.task == 0
240 && restrict.reg.reg == 0
241 && restrict.mem.len == 0)
242 puts(" (not restricted)");
247 printf("\n%32s", "restricted to ");
248 if (restrict.thread.thread != (GThread_num)-1)
251 printf("thread%s %x.%x\n",
252 restrict.thread.other ? " !=" : "",
253 L4_uid::task_from_gthread (restrict.thread.thread),
254 L4_uid::lthread_from_gthread (restrict.thread.thread));
256 if (restrict.task.task)
259 printf("%32s", "and ");
260 printf("task%s %p\n",
261 restrict.task.other ? " !=" : "",
265 if (restrict.reg.reg != 0)
268 printf("%32s", "and ");
269 printf("register %s in ["L4_PTR_FMT", "L4_PTR_FMT"]\n",
270 (restrict.reg.reg > 0) && (restrict.reg.reg < 10)
271 ? Jdb_screen::Reg_names[restrict.reg.reg-1]
273 restrict.reg.y, restrict.reg.z);
275 if (restrict.mem.len != 0)
278 printf("%32s", "and ");
279 printf("%d-byte var at "L4_PTR_FMT" in ["L4_PTR_FMT", "
281 restrict.mem.len, restrict.mem.addr,
282 restrict.mem.y, restrict.mem.z);
290 // return TRUE if the breakpoint does NOT match
291 // return FALSE if all restrictions do match
294 Breakpoint::restricted(Thread *t)
296 Jdb_entry_frame *e = Jdb::get_entry_frame(Jdb::current_cpu);
298 Space *task = t->space();
300 // investigate for thread restriction
301 if (restrict.thread.thread != (GThread_num)-1)
303 if (restrict.thread.other ^ (restrict.thread.thread != t->id().gthread()))
307 // investigate for task restriction
308 if (restrict.task.task)
310 if (restrict.task.other ^ (restrict.task.task != task))
314 // investigate for register restriction
315 if (restrict.reg.reg)
317 Mword val = e->get_reg(restrict.reg.reg);
318 Mword y = restrict.reg.y;
319 Mword z = restrict.reg.z;
321 // return true if rules do NOT match
322 if ( (y <= z && (val < y || val > z))
323 ||(y > z && (val >= z || val <= y)))
327 // investigate for variable restriction
328 if (restrict.mem.len)
331 Mword y = restrict.mem.y;
332 Mword z = restrict.mem.z;
334 if (Jdb::peek_task(restrict.mem.addr, task, &val, restrict.mem.len) != 0)
337 // return true if rules do NOT match
338 if ( (y <= z && (val < y || val > z))
339 ||(y > z && (val >= z || val <= y)))
348 Breakpoint::test_break(Thread *t, char *errbuf, size_t bufsize)
353 Space *task = t->space();
355 snprintf(errbuf, bufsize, "break on %s at " L4_PTR_FMT,
356 mode_names[mode], addr);
357 if (mode==WRITE || mode==ACCESS)
359 // If it's a write or access (read) breakpoint, we look at the
360 // appropriate place and print the bytes we find there. We do
361 // not need to look if the page is present because the x86 CPU
362 // enters the debug exception immediately _after_ the memory
363 // access was performed.
364 size_t size = strlen(errbuf);
368 if (len > sizeof(Mword))
371 if (Jdb::peek_task(addr, task, &val, len) != 0)
374 snprintf(errbuf, bufsize, " [%08lx]", val);
379 // Create log entry if breakpoint matches
382 Breakpoint::test_log(Thread *t)
384 Jdb_entry_frame *e = Jdb::get_entry_frame(Jdb::current_cpu);
386 if (log && !restricted(t))
388 Space *task = t->space();
392 if (mode == WRITE || mode == ACCESS)
394 // If it's a write or access (read) breakpoint, we look at the
395 // appropriate place and print the bytes we find there. We do
396 // not need to look if the page is present because the x86 CPU
397 // enters the debug exception immediately _after_ the memory
398 // access was performed.
399 if (len > sizeof(Mword))
402 if (Jdb::peek_task(addr, task, &value, len) != 0)
406 // is called with disabled interrupts
407 Tb_entry_bp *tb = static_cast<Tb_entry_bp*>(Jdb_tbuf::new_entry());
408 tb->set(t, e->ip(), mode, len, value, addr);
409 Jdb_tbuf::commit_entry();
414 STATIC_INITIALIZE_P(Jdb_bp, JDB_MODULE_INIT_PRIO);
416 PUBLIC static FIASCO_INIT
420 static Jdb_handler enter(at_jdb_enter);
421 static Jdb_handler leave(at_jdb_leave);
423 Jdb::jdb_enter.add(&enter);
424 Jdb::jdb_leave.add(&leave);
431 Jdb_bp::clr_dr7(int num, Mword &dr7)
433 dr7 &= ~(((3 + (3 <<2)) << (16 + 4*num)) + (3 << (2*num)));
438 Jdb_bp::set_dr7(int num, Mword len, Breakpoint::Mode mode, Mword &dr7)
440 dr7 |= ((((mode & 3) + ((len-1)<<2)) << (16 + 4*num)) + (2 << (2*num)));
441 dr7 |= 0x200; /* exact breakpoint enable (not available on P6 and below) */
446 Jdb_bp::set_breakpoint(int num, Address addr, Mword len,
447 Breakpoint::Mode mode, Breakpoint::Log log,
450 if (set_debug_address_register(num, addr, len, mode, task))
452 bps[num].set(addr, len, mode, log);
461 Jdb_bp::clr_breakpoint(int num)
463 clr_debug_address_register(num);
467 PUBLIC static inline NOEXPORT
469 Jdb_bp::logmode_breakpoint(int num, char mode)
471 bps[num].set_logmode(mode);
476 Jdb_bp::first_unused()
480 for (i=0; i<4 && !bps[i].unused(); i++)
486 // Return 1 if a breakpoint hits
489 Jdb_bp::test_break(Mword dr6, char *errbuf, size_t bufsize)
491 Thread *t = Jdb::get_thread(0);
492 Jdb_entry_frame *e = Jdb::get_entry_frame(0);
494 for (int i=0; i<4; i++)
497 if (bps[i].break_at_instruction())
498 e->flags(e->flags() | EFLAGS_RF);
499 if (bps[i].test_break(t, errbuf, bufsize))
506 // Create log entry if breakpoint matches.
507 // Return 1 if debugger should stop
510 Jdb_bp::test_log(Mword &dr6)
512 Thread *t = Jdb::get_thread(0);
513 Jdb_entry_frame *e = Jdb::get_entry_frame(0);
515 for (int i=0; i<4; i++)
518 if (!bps[i].is_break())
522 // consider instruction breakpoints
523 if (bps[i].break_at_instruction())
524 e->flags(e->flags() | EFLAGS_RF);
533 Jdb_bp::test_match(Address addr, Breakpoint::Mode mode)
535 for (int i=0; i<4; i++)
536 if (bps[i].match_addr(addr, mode))
544 Jdb_bp::instruction_bp_at_addr(Address addr)
545 { return test_match(addr, Breakpoint::INSTRUCTION); }
548 PUBLIC static inline NOEXPORT
550 Jdb_bp::restrict_task(int num, int other, Mword task)
552 bps[num].restrict_task(other, task);
555 PUBLIC static inline NOEXPORT
557 Jdb_bp::restrict_thread(int num, int other, Mword thread)
559 bps[num].restrict_thread(other, thread);
562 PUBLIC static inline NOEXPORT
564 Jdb_bp::restrict_register(int num, char reg, Mword y, Mword z)
566 bps[num].restrict_register(reg, y, z);
569 PUBLIC static inline NOEXPORT
571 Jdb_bp::restrict_memory(int num, Mword addr, Mword len, Mword y, Mword z)
573 bps[num].restrict_memory(addr, len, y, z);
576 PUBLIC static inline NOEXPORT
578 Jdb_bp::clear_restriction(int num)
580 bps[num].clear_restriction();
589 for(int i=0; i<4; i++)
591 printf(" #%d: ", i+1);
599 //---------------------------------------------------------------------------//
602 Jdb_set_bp::Jdb_set_bp()
603 : Jdb_module("DEBUGGING")
607 Jdb_module::Action_code
608 Jdb_set_bp::action(int cmd, void *&args, char const *&fmt, int &next_char)
610 Jdb_module::Action_code code;
611 Breakpoint::Mode mode;
615 if (args == &breakpoint_cmd)
617 switch (breakpoint_cmd)
620 if (!(Cpu::boot_cpu()->features() & FEAT_DE))
622 puts(" I/O breakpoints not supported by this CPU");
629 if ((breakpoint_number = Jdb_bp::first_unused()) < 4)
632 args = &Jdb_input_task_addr::first_char;
633 state = 1; // breakpoints are global for all tasks
636 puts(" No breakpoints available");
639 // show all breakpoints
645 // set logmode of breakpoint to <STOP>
647 // set logmode of breakpoint to <LOG>
649 // restrict breakpoint
651 args = &breakpoint_number;
655 Jdb::execute_command("bt");
664 code = Jdb_input_task_addr::action(args, fmt, next_char);
670 // more input for Jdb_input_task_addr
673 if (breakpoint_number < 1 || breakpoint_number > 4)
675 // input is 1..4 but numbers are 0..3
676 breakpoint_number -= 1;
677 // we know the breakpoint number
678 switch (breakpoint_cmd)
681 Jdb_bp::clr_breakpoint(breakpoint_number);
686 Jdb_bp::logmode_breakpoint(breakpoint_number, breakpoint_cmd);
691 args = &breakpoint_restrict_cmd;
701 if (breakpoint_cmd != 'i')
703 fmt = " len (1, 2 or 4)=%1x";
704 args = &breakpoint_length;
708 breakpoint_length = 1; // must be 1 for instruction breakpoints
712 if (breakpoint_length != 1 && breakpoint_length != 2 &&
713 breakpoint_length != 4)
715 switch (breakpoint_cmd)
717 default : return ERROR;
718 case 'i': mode = Breakpoint::INSTRUCTION; break;
719 case 'w': mode = Breakpoint::WRITE; break;
720 case 'p': mode = Breakpoint::PORTIO; break;
721 case 'a': mode = Breakpoint::ACCESS; break;
723 // abort if no address was given
724 if (Jdb_input_task_addr::addr() == (Address)-1)
726 Jdb_bp::set_breakpoint(breakpoint_number, Jdb_input_task_addr::addr(),
727 breakpoint_length, mode, Breakpoint::BREAK,
728 Jdb_input_task_addr::task());
732 // restrict command read
733 switch (breakpoint_restrict_cmd)
737 fmt = (breakpoint_restrict_cmd=='A')
738 ? "task!="L4_ADDR_INPUT_FMT"\n"
739 : "task=="L4_ADDR_INPUT_FMT"\n";
740 args = &breakpoint_restrict_task;
745 fmt = (breakpoint_restrict_cmd=='T')
746 ? "thread!=%t\n" : "thread==%t\n";
747 args = &breakpoint_restrict_thread;
751 if (!Jdb::get_register(&breakpoint_restrict_reg.reg))
753 fmt = " in ["L4_ADDR_INPUT_FMT"-"L4_ADDR_INPUT_FMT"]\n";
754 args = &breakpoint_restrict_reg.low;
760 putchar(breakpoint_restrict_cmd);
761 fmt = "-byte addr="L4_ADDR_INPUT_FMT
762 " between["L4_ADDR_INPUT_FMT"-"L4_ADDR_INPUT_FMT"]\n";
763 args = &breakpoint_restrict_addr;
767 Jdb_bp::clear_restriction(breakpoint_number);
775 // breakpoint restrict task read
776 Jdb_bp::restrict_task(breakpoint_number,
777 breakpoint_restrict_cmd == 'A',
778 breakpoint_restrict_task);
781 // breakpoint restrict thread read
782 Jdb_bp::restrict_thread(breakpoint_number,
783 breakpoint_restrict_cmd == 'T',
784 breakpoint_restrict_thread);
787 // breakpoint restrict register in range
788 Jdb_bp::restrict_register(breakpoint_number,
789 breakpoint_restrict_reg.reg,
790 breakpoint_restrict_reg.low,
791 breakpoint_restrict_reg.high);
794 // breakpoint restrict x-byte-value in range
795 Jdb_bp::restrict_memory(breakpoint_number,
796 breakpoint_restrict_addr.addr,
797 breakpoint_restrict_cmd - '0',
798 breakpoint_restrict_addr.low,
799 breakpoint_restrict_addr.high);
807 Jdb_module::Cmd const *
808 Jdb_set_bp::cmds() const
812 { 0, "b", "bp", "%c",
813 "b{i|a|w|p}<addr>\tset breakpoint on instruction/access/write/io "
815 "b{-|+|*}<num>\tdisable/enable/log breakpoint\n"
816 "bl\tlist breakpoints\n"
817 "br<num>{t|T|a|A|e|1|2|4}\trestrict breakpoint to "
818 "(!)thread/(!)task/reg/mem",
827 Jdb_set_bp::num_cmds() const
832 static Jdb_set_bp jdb_set_bp INIT_PRIORITY(JDB_MODULE_INIT_PRIO);