Added "breakpoint", "watchpoint", "breakpoints", and "watchpoints"
kernel debugger commands, which can set/clear/list in-kernel break- and watchpoints. Only available when KERNEL_BREAKPOINTS is defined. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22153 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
d2056c9933
commit
bc5f008afb
|
@ -301,6 +301,182 @@ check_watch_point_parameters(void* address, uint32 type, int32 length,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - kernel debugger commands
|
||||||
|
|
||||||
|
#if KERNEL_BREAKPOINTS
|
||||||
|
|
||||||
|
static int
|
||||||
|
debugger_breakpoints(int argc, char** argv)
|
||||||
|
{
|
||||||
|
struct team* kernelTeam = team_get_kernel_team();
|
||||||
|
arch_team_debug_info& info = kernelTeam->debug_info.arch_info;
|
||||||
|
|
||||||
|
for (int32 i = 0; i < X86_BREAKPOINT_COUNT; i++) {
|
||||||
|
kprintf("breakpoint[%ld] ", i);
|
||||||
|
|
||||||
|
if (info.breakpoints[i].address != NULL) {
|
||||||
|
kprintf("%p ", info.breakpoints[i].address);
|
||||||
|
switch (info.breakpoints[i].type) {
|
||||||
|
case X86_INSTRUCTION_BREAKPOINT:
|
||||||
|
kprintf("instruction");
|
||||||
|
break;
|
||||||
|
case X86_IO_READ_WRITE_BREAKPOINT:
|
||||||
|
kprintf("io read/write");
|
||||||
|
break;
|
||||||
|
case X86_DATA_WRITE_BREAKPOINT:
|
||||||
|
kprintf("data write");
|
||||||
|
break;
|
||||||
|
case X86_DATA_READ_WRITE_BREAKPOINT:
|
||||||
|
kprintf("data read/write");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int length = 1;
|
||||||
|
switch (info.breakpoints[i].length) {
|
||||||
|
case X86_BREAKPOINT_LENGTH_1:
|
||||||
|
length = 1;
|
||||||
|
break;
|
||||||
|
case X86_BREAKPOINT_LENGTH_2:
|
||||||
|
length = 2;
|
||||||
|
break;
|
||||||
|
case X86_BREAKPOINT_LENGTH_4:
|
||||||
|
length = 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.breakpoints[i].type != X86_INSTRUCTION_BREAKPOINT)
|
||||||
|
kprintf(" %d byte%s", length, (length > 1 ? "s" : ""));
|
||||||
|
} else
|
||||||
|
kprintf("unused");
|
||||||
|
|
||||||
|
kprintf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
debugger_breakpoint_usage(const char* command)
|
||||||
|
{
|
||||||
|
if (command[0] == 'b') {
|
||||||
|
kprintf("Usage: breakpoint <address>\n");
|
||||||
|
kprintf(" breakpoint <address> clear\n");
|
||||||
|
} else {
|
||||||
|
kprintf("Usage: watchpoint <address> [ rw ] [ <size> ]\n");
|
||||||
|
kprintf(" watchpoint <address> clear\n");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
debugger_breakpoint(int argc, char** argv)
|
||||||
|
{
|
||||||
|
// get arguments
|
||||||
|
|
||||||
|
if (argc < 2 || argc > 3)
|
||||||
|
return debugger_breakpoint_usage(argv[0]);
|
||||||
|
|
||||||
|
addr_t address = strtoul(argv[1], NULL, 0);
|
||||||
|
if (address == 0)
|
||||||
|
return debugger_breakpoint_usage(argv[0]);
|
||||||
|
|
||||||
|
bool clear = false;
|
||||||
|
if (argc == 3) {
|
||||||
|
if (strcmp(argv[2], "clear") == 0)
|
||||||
|
clear = true;
|
||||||
|
else
|
||||||
|
return debugger_breakpoint_usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set/clear breakpoint
|
||||||
|
|
||||||
|
arch_team_debug_info& info = team_get_kernel_team()->debug_info.arch_info;
|
||||||
|
|
||||||
|
status_t error;
|
||||||
|
|
||||||
|
if (clear) {
|
||||||
|
error = clear_breakpoint(info, (void*)address, false);
|
||||||
|
} else {
|
||||||
|
error = set_breakpoint(info, (void*)address, X86_INSTRUCTION_BREAKPOINT,
|
||||||
|
X86_BREAKPOINT_LENGTH_1, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error == B_OK)
|
||||||
|
install_breakpoints(info);
|
||||||
|
else
|
||||||
|
kprintf("Failed to install breakpoint: %s\n", strerror(error));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
debugger_watchpoint(int argc, char** argv)
|
||||||
|
{
|
||||||
|
// get arguments
|
||||||
|
|
||||||
|
if (argc < 2 || argc > 4)
|
||||||
|
return debugger_breakpoint_usage(argv[0]);
|
||||||
|
|
||||||
|
addr_t address = strtoul(argv[1], NULL, 0);
|
||||||
|
if (address == 0)
|
||||||
|
return debugger_breakpoint_usage(argv[0]);
|
||||||
|
|
||||||
|
bool clear = false;
|
||||||
|
bool readWrite = false;
|
||||||
|
int argi = 2;
|
||||||
|
int length = 1;
|
||||||
|
if (argc >= 3) {
|
||||||
|
if (strcmp(argv[argi], "clear") == 0) {
|
||||||
|
clear = true;
|
||||||
|
argi++;
|
||||||
|
} else if (strcmp(argv[argi], "rw") == 0) {
|
||||||
|
readWrite = true;
|
||||||
|
argi++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!clear && argi < argc)
|
||||||
|
length = strtoul(argv[argi++], NULL, 0);
|
||||||
|
|
||||||
|
if (length == 0 || argi < argc)
|
||||||
|
return debugger_breakpoint_usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set/clear breakpoint
|
||||||
|
|
||||||
|
arch_team_debug_info& info = team_get_kernel_team()->debug_info.arch_info;
|
||||||
|
|
||||||
|
status_t error;
|
||||||
|
|
||||||
|
if (clear) {
|
||||||
|
error = clear_breakpoint(info, (void*)address, true);
|
||||||
|
} else {
|
||||||
|
uint32 type = readWrite ? B_DATA_READ_WRITE_WATCHPOINT
|
||||||
|
: B_DATA_WRITE_WATCHPOINT;
|
||||||
|
|
||||||
|
uint32 archType, archLength;
|
||||||
|
error = check_watch_point_parameters((void*)address, type, length,
|
||||||
|
archType, archLength);
|
||||||
|
|
||||||
|
if (error == B_OK) {
|
||||||
|
error = set_breakpoint(info, (void*)address, archType, archLength,
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error == B_OK)
|
||||||
|
install_breakpoints(info);
|
||||||
|
else
|
||||||
|
kprintf("Failed to install breakpoint: %s\n", strerror(error));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // KERNEL_BREAKPOINTS
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - in-kernel public interface
|
// #pragma mark - in-kernel public interface
|
||||||
|
|
||||||
|
|
||||||
|
@ -709,5 +885,17 @@ i386_init_user_debug()
|
||||||
|
|
||||||
unload_driver_settings(handle);
|
unload_driver_settings(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if KERNEL_BREAKPOINTS
|
||||||
|
// install debugger commands
|
||||||
|
add_debugger_command("breakpoints", &debugger_breakpoints,
|
||||||
|
"lists current break-/watchpoints");
|
||||||
|
add_debugger_command("breakpoint", &debugger_breakpoint,
|
||||||
|
"set/clear a breakpoint");
|
||||||
|
add_debugger_command("watchpoints", &debugger_breakpoints,
|
||||||
|
"lists current break-/watchpoints");
|
||||||
|
add_debugger_command("watchpoint", &debugger_watchpoint,
|
||||||
|
"set/clear a watchpoint");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue