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"
87 class Jdb_set_bp : public Jdb_module, public Jdb_input_task_addr
90 Jdb_set_bp() FIASCO_INIT;
92 static char breakpoint_cmd;
93 static char breakpoint_restrict_cmd;
94 static Mword breakpoint_number;
95 static Mword breakpoint_length;
96 static Mword breakpoint_restrict_task;
97 static Mword breakpoint_restrict_thread;
104 static Restrict_reg breakpoint_restrict_reg;
111 static Restrict_addr breakpoint_restrict_addr;
115 Breakpoint Jdb_bp::bps[4];
117 char const * const Breakpoint::mode_names[4] =
119 "instruction", "write access", "i/o access", "r/w access"
122 char Jdb_set_bp::breakpoint_cmd;
123 char Jdb_set_bp::breakpoint_restrict_cmd;
124 Mword Jdb_set_bp::breakpoint_number;
125 Mword Jdb_set_bp::breakpoint_length;
126 Mword Jdb_set_bp::breakpoint_restrict_task;
127 Mword Jdb_set_bp::breakpoint_restrict_thread;
128 Jdb_set_bp::Restrict_reg Jdb_set_bp::breakpoint_restrict_reg;
129 Jdb_set_bp::Restrict_addr Jdb_set_bp::breakpoint_restrict_addr;
130 int Jdb_set_bp::state;
133 Breakpoint::Breakpoint()
135 restrict.thread.thread = 0;
136 restrict.task.task = 0;
139 PUBLIC inline NOEXPORT
146 PUBLIC inline NOEXPORT
153 PUBLIC inline NOEXPORT
155 Breakpoint::break_at_instruction()
157 return mode == INSTRUCTION;
160 PUBLIC inline NOEXPORT
162 Breakpoint::match_addr(Address virt, Mode m)
164 return !unused() && addr == virt && mode == m;
167 PUBLIC inline NOEXPORT
169 Breakpoint::set_logmode(char m)
171 log = (m == '*') ? LOG : BREAK;
174 PUBLIC inline NOEXPORT
176 Breakpoint::is_break()
178 return !unused() && log == BREAK;
183 Breakpoint::restrict_task(int other, Mword task)
185 restrict.task.other = other;
186 restrict.task.task = task;
189 PUBLIC inline NOEXPORT
191 Breakpoint::restrict_thread(int other, Mword thread)
193 restrict.thread.other = other;
194 restrict.thread.thread = thread;
197 PUBLIC inline NOEXPORT
199 Breakpoint::restrict_register(char reg, Mword y, Mword z)
201 restrict.reg.reg = reg;
206 PUBLIC inline NOEXPORT
208 Breakpoint::restrict_memory(Mword addr, Mword len, Mword y, Mword z)
210 restrict.mem.addr = addr;
211 restrict.mem.len = len;
216 PUBLIC inline NOEXPORT
218 Breakpoint::clear_restriction()
220 restrict.thread.thread = 0;
221 restrict.task.task = 0;
222 restrict.reg.reg = 0;
223 restrict.mem.len = 0;
232 printf("%5s on %12s at " L4_PTR_FMT,
233 log ? "LOG" : "BREAK", mode_names[mode & 3], addr);
234 if (mode != INSTRUCTION)
235 printf(" len %d", len);
239 if ( restrict.thread.thread == 0
240 && restrict.task.task == 0
241 && restrict.reg.reg == 0
242 && restrict.mem.len == 0)
243 puts(" (not restricted)");
248 printf("\n%32s", "restricted to ");
249 if (restrict.thread.thread != (GThread_num)-1)
252 printf("thread%s %x.%x\n",
253 restrict.thread.other ? " !=" : "",
254 L4_uid::task_from_gthread (restrict.thread.thread),
255 L4_uid::lthread_from_gthread (restrict.thread.thread));
257 if (restrict.task.task)
260 printf("%32s", "and ");
261 printf("task%s %p\n",
262 restrict.task.other ? " !=" : "",
266 if (restrict.reg.reg != 0)
269 printf("%32s", "and ");
270 printf("register %s in [" L4_PTR_FMT ", " L4_PTR_FMT "]\n",
271 (restrict.reg.reg > 0) && (restrict.reg.reg < 10)
272 ? Jdb_screen::Reg_names[restrict.reg.reg-1]
274 restrict.reg.y, restrict.reg.z);
276 if (restrict.mem.len != 0)
279 printf("%32s", "and ");
280 printf("%d-byte var at " L4_PTR_FMT " in [" L4_PTR_FMT ", "
282 restrict.mem.len, restrict.mem.addr,
283 restrict.mem.y, restrict.mem.z);
291 // return TRUE if the breakpoint does NOT match
292 // return FALSE if all restrictions do match
295 Breakpoint::restricted(Thread *t)
297 Jdb_entry_frame *e = Jdb::get_entry_frame(Jdb::current_cpu);
299 Space *task = t->space();
301 // investigate for thread restriction
302 if (restrict.thread.thread != (GThread_num)-1)
304 if (restrict.thread.other ^ (restrict.thread.thread != t->id().gthread()))
308 // investigate for task restriction
309 if (restrict.task.task)
311 if (restrict.task.other ^ (restrict.task.task != task))
315 // investigate for register restriction
316 if (restrict.reg.reg)
318 Mword val = e->get_reg(restrict.reg.reg);
319 Mword y = restrict.reg.y;
320 Mword z = restrict.reg.z;
322 // return true if rules do NOT match
323 if ( (y <= z && (val < y || val > z))
324 ||(y > z && (val >= z || val <= y)))
328 // investigate for variable restriction
329 if (restrict.mem.len)
332 Mword y = restrict.mem.y;
333 Mword z = restrict.mem.z;
335 if (Jdb::peek_task(restrict.mem.addr, task, &val, restrict.mem.len) != 0)
338 // return true if rules do NOT match
339 if ( (y <= z && (val < y || val > z))
340 ||(y > z && (val >= z || val <= y)))
349 Breakpoint::test_break(Thread *t, char *errbuf, size_t bufsize)
354 Space *task = t->space();
356 snprintf(errbuf, bufsize, "break on %s at " L4_PTR_FMT,
357 mode_names[mode], addr);
358 if (mode==WRITE || mode==ACCESS)
360 // If it's a write or access (read) breakpoint, we look at the
361 // appropriate place and print the bytes we find there. We do
362 // not need to look if the page is present because the x86 CPU
363 // enters the debug exception immediately _after_ the memory
364 // access was performed.
365 size_t size = strlen(errbuf);
369 if (len > sizeof(Mword))
372 if (Jdb::peek_task(addr, task, &val, len) != 0)
375 snprintf(errbuf, bufsize, " [%08lx]", val);
380 // Create log entry if breakpoint matches
383 Breakpoint::test_log(Thread *t)
385 Jdb_entry_frame *e = Jdb::get_entry_frame(Jdb::current_cpu);
387 if (log && !restricted(t))
389 Space *task = t->space();
393 if (mode == WRITE || mode == ACCESS)
395 // If it's a write or access (read) breakpoint, we look at the
396 // appropriate place and print the bytes we find there. We do
397 // not need to look if the page is present because the x86 CPU
398 // enters the debug exception immediately _after_ the memory
399 // access was performed.
400 if (len > sizeof(Mword))
403 if (Jdb::peek_task(addr, task, &value, len) != 0)
407 // is called with disabled interrupts
408 Tb_entry_bp *tb = static_cast<Tb_entry_bp*>(Jdb_tbuf::new_entry());
409 tb->set(t, e->ip(), mode, len, value, addr);
410 Jdb_tbuf::commit_entry();
415 STATIC_INITIALIZE_P(Jdb_bp, JDB_MODULE_INIT_PRIO);
417 PUBLIC static FIASCO_INIT
421 static Jdb_handler enter(at_jdb_enter);
422 static Jdb_handler leave(at_jdb_leave);
424 Jdb::jdb_enter.add(&enter);
425 Jdb::jdb_leave.add(&leave);
432 Jdb_bp::clr_dr7(int num, Mword &dr7)
434 dr7 &= ~(((3 + (3 <<2)) << (16 + 4*num)) + (3 << (2*num)));
439 Jdb_bp::set_dr7(int num, Mword len, Breakpoint::Mode mode, Mword &dr7)
441 // the encoding of length 8 is special
445 dr7 |= ((((mode & 3) + ((len-1)<<2)) << (16 + 4*num)) + (2 << (2*num)));
446 dr7 |= 0x200; /* exact breakpoint enable (not available on P6 and below) */
451 Jdb_bp::set_breakpoint(int num, Address addr, Mword len,
452 Breakpoint::Mode mode, Breakpoint::Log log,
455 if (set_debug_address_register(num, addr, len, mode, task))
457 bps[num].set(addr, len, mode, log);
466 Jdb_bp::clr_breakpoint(int num)
468 clr_debug_address_register(num);
472 PUBLIC static inline NOEXPORT
474 Jdb_bp::logmode_breakpoint(int num, char mode)
476 bps[num].set_logmode(mode);
481 Jdb_bp::first_unused()
485 for (i=0; i<4 && !bps[i].unused(); i++)
491 // Return 1 if a breakpoint hits
494 Jdb_bp::test_break(Mword dr6, char *errbuf, size_t bufsize)
496 Thread *t = Jdb::get_thread(0);
497 Jdb_entry_frame *e = Jdb::get_entry_frame(0);
499 for (int i=0; i<4; i++)
502 if (bps[i].break_at_instruction())
503 e->flags(e->flags() | EFLAGS_RF);
504 if (bps[i].test_break(t, errbuf, bufsize))
511 // Create log entry if breakpoint matches.
512 // Return 1 if debugger should stop
515 Jdb_bp::test_log(Mword &dr6)
517 Thread *t = Jdb::get_thread(0);
518 Jdb_entry_frame *e = Jdb::get_entry_frame(0);
520 for (int i=0; i<4; i++)
523 if (!bps[i].is_break())
527 // consider instruction breakpoints
528 if (bps[i].break_at_instruction())
529 e->flags(e->flags() | EFLAGS_RF);
538 Jdb_bp::test_match(Address addr, Breakpoint::Mode mode)
540 for (int i=0; i<4; i++)
541 if (bps[i].match_addr(addr, mode))
549 Jdb_bp::instruction_bp_at_addr(Address addr)
550 { return test_match(addr, Breakpoint::INSTRUCTION); }
553 PUBLIC static inline NOEXPORT
555 Jdb_bp::restrict_task(int num, int other, Mword task)
557 bps[num].restrict_task(other, task);
560 PUBLIC static inline NOEXPORT
562 Jdb_bp::restrict_thread(int num, int other, Mword thread)
564 bps[num].restrict_thread(other, thread);
567 PUBLIC static inline NOEXPORT
569 Jdb_bp::restrict_register(int num, char reg, Mword y, Mword z)
571 bps[num].restrict_register(reg, y, z);
574 PUBLIC static inline NOEXPORT
576 Jdb_bp::restrict_memory(int num, Mword addr, Mword len, Mword y, Mword z)
578 bps[num].restrict_memory(addr, len, y, z);
581 PUBLIC static inline NOEXPORT
583 Jdb_bp::clear_restriction(int num)
585 bps[num].clear_restriction();
594 for(int i=0; i<4; i++)
596 printf(" #%d: ", i+1);
604 //---------------------------------------------------------------------------//
607 Jdb_set_bp::Jdb_set_bp()
608 : Jdb_module("DEBUGGING")
612 Jdb_module::Action_code
613 Jdb_set_bp::action(int cmd, void *&args, char const *&fmt, int &next_char)
615 Jdb_module::Action_code code;
616 Breakpoint::Mode mode;
620 if (args == &breakpoint_cmd)
622 switch (breakpoint_cmd)
625 if (!(Cpu::boot_cpu()->features() & FEAT_DE))
627 puts(" I/O breakpoints not supported by this CPU");
634 if ((breakpoint_number = Jdb_bp::first_unused()) < 4)
637 args = &Jdb_input_task_addr::first_char;
638 state = 1; // breakpoints are global for all tasks
641 puts(" No breakpoints available");
644 // show all breakpoints
650 // set logmode of breakpoint to <STOP>
652 // set logmode of breakpoint to <LOG>
654 // restrict breakpoint
656 args = &breakpoint_number;
660 Jdb::execute_command("bt");
669 code = Jdb_input_task_addr::action(args, fmt, next_char);
675 // more input for Jdb_input_task_addr
678 if (breakpoint_number < 1 || breakpoint_number > 4)
680 // input is 1..4 but numbers are 0..3
681 breakpoint_number -= 1;
682 // we know the breakpoint number
683 switch (breakpoint_cmd)
686 Jdb_bp::clr_breakpoint(breakpoint_number);
691 Jdb_bp::logmode_breakpoint(breakpoint_number, breakpoint_cmd);
696 args = &breakpoint_restrict_cmd;
706 if (breakpoint_cmd != 'i')
708 fmt = " len (1, 2, 4...)=%1x";
709 args = &breakpoint_length;
713 breakpoint_length = 1; // must be 1 for instruction breakpoints
717 if (breakpoint_length & (breakpoint_length - 1))
719 if (breakpoint_length > sizeof(Mword))
721 switch (breakpoint_cmd)
723 default : return ERROR;
724 case 'i': mode = Breakpoint::INSTRUCTION; break;
725 case 'w': mode = Breakpoint::WRITE; break;
726 case 'p': mode = Breakpoint::PORTIO; break;
727 case 'a': mode = Breakpoint::ACCESS; break;
729 // abort if no address was given
730 if (Jdb_input_task_addr::addr() == (Address)-1)
732 Jdb_bp::set_breakpoint(breakpoint_number, Jdb_input_task_addr::addr(),
733 breakpoint_length, mode, Breakpoint::BREAK,
734 Jdb_input_task_addr::task());
738 // restrict command read
739 switch (breakpoint_restrict_cmd)
743 fmt = (breakpoint_restrict_cmd=='A')
744 ? "task!=" L4_ADDR_INPUT_FMT "\n"
745 : "task==" L4_ADDR_INPUT_FMT "\n";
746 args = &breakpoint_restrict_task;
751 fmt = (breakpoint_restrict_cmd=='T')
752 ? "thread!=%t\n" : "thread==%t\n";
753 args = &breakpoint_restrict_thread;
757 if (!Jdb::get_register(&breakpoint_restrict_reg.reg))
759 fmt = " in [" L4_ADDR_INPUT_FMT "-" L4_ADDR_INPUT_FMT "]\n";
760 args = &breakpoint_restrict_reg.low;
766 putchar(breakpoint_restrict_cmd);
767 fmt = "-byte addr=" L4_ADDR_INPUT_FMT
768 " between[" L4_ADDR_INPUT_FMT "-" L4_ADDR_INPUT_FMT "]\n";
769 args = &breakpoint_restrict_addr;
773 Jdb_bp::clear_restriction(breakpoint_number);
781 // breakpoint restrict task read
782 Jdb_bp::restrict_task(breakpoint_number,
783 breakpoint_restrict_cmd == 'A',
784 breakpoint_restrict_task);
787 // breakpoint restrict thread read
788 Jdb_bp::restrict_thread(breakpoint_number,
789 breakpoint_restrict_cmd == 'T',
790 breakpoint_restrict_thread);
793 // breakpoint restrict register in range
794 Jdb_bp::restrict_register(breakpoint_number,
795 breakpoint_restrict_reg.reg,
796 breakpoint_restrict_reg.low,
797 breakpoint_restrict_reg.high);
800 // breakpoint restrict x-byte-value in range
801 Jdb_bp::restrict_memory(breakpoint_number,
802 breakpoint_restrict_addr.addr,
803 breakpoint_restrict_cmd - '0',
804 breakpoint_restrict_addr.low,
805 breakpoint_restrict_addr.high);
813 Jdb_module::Cmd const *
814 Jdb_set_bp::cmds() const
818 { 0, "b", "bp", "%c",
819 "b{i|a|w|p}<addr>\tset breakpoint on instruction/access/write/io "
821 "b{-|+|*}<num>\tdisable/enable/log breakpoint\n"
822 "bl\tlist breakpoints\n"
823 "br<num>{t|T|a|A|e|1|2|4}\trestrict breakpoint to "
824 "(!)thread/(!)task/reg/mem",
833 Jdb_set_bp::num_cmds() const
838 static Jdb_set_bp jdb_set_bp INIT_PRIORITY(JDB_MODULE_INIT_PRIO);