Skip to content

Commit

Permalink
add support for more magic breakpoints fix #55
Browse files Browse the repository at this point in the history
  • Loading branch information
therealdreg committed Aug 19, 2023
1 parent bd51ec5 commit a373730
Show file tree
Hide file tree
Showing 14 changed files with 1,281 additions and 346 deletions.
14 changes: 11 additions & 3 deletions bochs/.bochsrc
Original file line number Diff line number Diff line change
Expand Up @@ -1271,13 +1271,21 @@ speaker: enabled=1, mode=sound, volume=15
#=======================================================================
# MAGIC_BREAK:
# This enables the "magic breakpoint" feature when using the debugger.
# The useless cpu instruction XCHG BX, BX causes Bochs to enter the
# The useless cpu instructions XCHG %REGW, %REGW causes Bochs to enter the
# debugger mode. This might be useful for software development.
#
# Example:
# You can specify multiple at once:
#
# %cx %dx %bx %sp %bp %si %di
#
# Example for breaking on "XCHGW %DI, %DI" or "CHGW %SP, %SP" execution
# magic_break: enabled=1 %di %sp
#
# If nothing is specified, the default will be used: XCHGW %BX, %BX
# magic_break: enabled=1
# Note: Windows XP ntldr can cause problems with XCHGW %BX, %BX
#=======================================================================
#magic_break: enabled=1
# magic_break: enabled=1

#=======================================================================
# DEBUG_SYMBOLS:
Expand Down
4 changes: 2 additions & 2 deletions bochs/bochs.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ void print_statistics_tree(bx_param_c *node, int level = 0);
// defines for GDB stub
void bx_gdbstub_init(void);
void bx_gdbstub_break(void);
int bx_gdbstub_check(unsigned int eip);
int bx_gdbstub_check(Bit64u eip);
#define GDBSTUB_STOP_NO_REASON (0xac0)

#if BX_SUPPORT_SMP
Expand All @@ -287,7 +287,7 @@ typedef struct {
bool exceptions;
bool print_timestamps;
#if BX_DEBUGGER
bool magic_break_enabled;
Bit8u magic_break;
#endif
#if BX_GDBSTUB
bool gdbstub_enabled;
Expand Down
56 changes: 55 additions & 1 deletion bochs/bx_debug/dbg_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2283,6 +2283,55 @@ void bx_dbg_lyt(void)
bx_nest_infile(layoutpath);
}

void bx_dbg_set_magic_bp_mask(Bit8u mask)
{
bx_dbg.magic_break = mask;
dbg_printf("new magic breakpoint mask created: 0x%x\n", mask);
}

Bit8u bx_dbg_get_magic_bp_mask_from_str(const char *str)
{
Bit8u new_mask = 0;

if (NULL == str)
{
return 0;
}

if (strstr(str, "%cx") != NULL)
{
new_mask |= 1 << 0;
}
if (strstr(str, "%dx") != NULL)
{
new_mask |= 1 << 1;
}
if (strstr(str, "%sp") != NULL)
{
new_mask |= 1 << 3;
}
if (strstr(str, "%bp") != NULL)
{
new_mask |= 1 << 4;
}
if (strstr(str, "%si") != NULL)
{
new_mask |= 1 << 5;
}
if (strstr(str, "%di") != NULL)
{
new_mask |= 1 << 6;
}

// %bx if not specified for backward compatibility
if (0 == new_mask || strstr(str, "%bx") != NULL)
{
new_mask |= 1 << 2;
}

return new_mask;
}

void bx_dbg_print_guard_results(void)
{
unsigned cpu, i;
Expand Down Expand Up @@ -3141,6 +3190,11 @@ void bx_dbg_print_descriptor(Bit32u lo, Bit32u hi)
default:
// task, int, trap, or call gate.
dbg_printf("target=0x%04x:0x%08x, DPL=%d", segment, offset, dpl);

const char *Sym = bx_dbg_disasm_symbolic_address(offset, 0);
if (Sym)
dbg_printf(" (%s)", Sym);

break;
}
}
Expand Down Expand Up @@ -3786,7 +3840,7 @@ void bx_dbg_print_help(void)
dbg_printf("h|help command - show short command description\n");
dbg_printf("-*- Debugger control -*-\n");
dbg_printf(" help, q|quit|exit, set, instrument, show, trace, trace-reg,\n");
dbg_printf(" trace-mem, u|disasm, ldsym, slist, addlyt, remlyt, lyt, source\n");
dbg_printf(" trace-mem, u|disasm, ldsym, setmagicbps, slist, addlyt, remlyt, lyt, source\n");
dbg_printf("-*- Execution control -*-\n");
dbg_printf(" c|cont|continue, s|step, p|n|next, modebp, vmexitbp\n");
dbg_printf("-*- Breakpoint management -*-\n");
Expand Down
2 changes: 2 additions & 0 deletions bochs/bx_debug/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ bool bx_dbg_register_debug_info(const char *devname, void *dev);
void bx_dbg_addlyt(const char* new_layoutpath);
void bx_dbg_remlyt(void);
void bx_dbg_lyt(void);
void bx_dbg_set_magic_bp_mask(Bit8u mask);
Bit8u bx_dbg_get_magic_bp_mask_from_str(const char *str);
bool bx_dbg_read_linear(unsigned which_cpu, bx_address laddr, unsigned len, Bit8u *buf);
bool bx_dbg_write_linear(unsigned which_cpu, bx_address laddr, unsigned len, Bit8u *buf);
Bit16u bx_dbg_get_selector_value(unsigned int seg_no);
Expand Down
1 change: 1 addition & 0 deletions bochs/bx_debug/lexer.l
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ read { bxlval.sval = strdup(bxtext); return(BX_TOKEN_READ); }
w|write { bxlval.sval = strdup(bxtext); return(BX_TOKEN_WRITE); }
show { bxlval.sval = strdup(bxtext); return(BX_TOKEN_SHOW); }
ldsym { bxlval.sval = strdup(bxtext); return(BX_TOKEN_LOAD_SYMBOLS); }
setmagicbps { bxlval.sval = strdup(bxtext); return(BX_TOKEN_SET_MAGIC_BREAK_POINTS); }
symbols { bxlval.sval = strdup(bxtext); return(BX_TOKEN_SYMBOLS); }
slist { bxlval.sval = strdup(bxtext); return(BX_TOKEN_LIST_SYMBOLS); }
global { bxlval.sval = strdup(bxtext); return(BX_TOKEN_GLOBAL); }
Expand Down
20 changes: 20 additions & 0 deletions bochs/bx_debug/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ Bit64u eval_value;
%token <sval> BX_TOKEN_WRITE
%token <sval> BX_TOKEN_SHOW
%token <sval> BX_TOKEN_LOAD_SYMBOLS
%token <sval> BX_TOKEN_SET_MAGIC_BREAK_POINTS
%token <sval> BX_TOKEN_SYMBOLS
%token <sval> BX_TOKEN_LIST_SYMBOLS
%token <sval> BX_TOKEN_GLOBAL
Expand Down Expand Up @@ -200,6 +201,7 @@ command:
| vmexitbp_command
| print_stack_command
| backtrace_command
| set_magic_break_points_command
| watch_point_command
| page_command
| tlb_command
Expand Down Expand Up @@ -459,6 +461,19 @@ symbol_command:
}
;

set_magic_break_points_command:
BX_TOKEN_SET_MAGIC_BREAK_POINTS '\n'
{
bx_dbg_set_magic_bp_mask(0);
free($1);
}
| BX_TOKEN_SET_MAGIC_BREAK_POINTS BX_TOKEN_STRING '\n'
{
bx_dbg_set_magic_bp_mask(bx_dbg_get_magic_bp_mask_from_str($2));
free($1); free($2);
}
;

where_command:
BX_TOKEN_WHERE '\n'
{
Expand Down Expand Up @@ -1158,6 +1173,11 @@ help_command:
dbg_printf("ldsym [global] <filename> [offset] - load symbols from file\n");
free($1);free($2);
}
| BX_TOKEN_HELP BX_TOKEN_SET_MAGIC_BREAK_POINTS '\n'
{
dbg_printf("setmagicbps \"%%cx %%dx %%bx %%sp %%bp %%si %%di\" - change magic breakpoints. setmagicbps without args disable all of them.\n");
free($1);free($2);
}
| BX_TOKEN_HELP BX_TOKEN_LIST_SYMBOLS '\n'
{
dbg_printf("slist [string] - list symbols whose preffix is string (same as 'info symbols')\n");
Expand Down
23 changes: 15 additions & 8 deletions bochs/config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@
#undef getenv
#endif

#ifdef WIN32
#define DIRECTORY_SEPARATOR "\\"
#else
#define DIRECTORY_SEPARATOR "/"
#endif

const char **config_interface_list;
const char **display_library_list;
Expand Down Expand Up @@ -852,7 +857,7 @@ void bx_init_options()
"Pathname of ROM image to load",
"", BX_PATHNAME_LEN);
path->set_format("Name of ROM BIOS image: %s");
sprintf(name, "%s/BIOS-bochs-latest", (char *)get_builtin_variable("BXSHARE"));
sprintf(name, "%s" DIRECTORY_SEPARATOR "BIOS-bochs-latest", (char *)get_builtin_variable("BXSHARE"));
path->set_initial_val(name);
bx_param_num_c *romaddr = new bx_param_num_c(rom,
"address",
Expand All @@ -876,7 +881,7 @@ void bx_init_options()
"Pathname of VGA ROM image to load",
"", BX_PATHNAME_LEN);
path->set_format("Name of VGA BIOS image: %s");
sprintf(name, "%s/VGABIOS-lgpl-latest", get_builtin_variable("BXSHARE"));
sprintf(name, "%s" DIRECTORY_SEPARATOR "VGABIOS-lgpl-latest", get_builtin_variable("BXSHARE"));
path->set_initial_val(name);
vgarom->set_options(vgarom->SERIES_ASK);

Expand Down Expand Up @@ -3142,6 +3147,7 @@ static int parse_line_formatted(const char *context, int num_params, char *param
#endif
} else if (!strcmp(params[0], "magic_break")) {
#if BX_DEBUGGER
bx_dbg.magic_break = 0;
if (num_params != 2) {
PARSE_ERR(("%s: magic_break directive: wrong # args.", context));
}
Expand All @@ -3150,14 +3156,15 @@ static int parse_line_formatted(const char *context, int num_params, char *param
}
if (params[1][8] == '0') {
BX_INFO(("Ignoring magic break points"));
bx_dbg.magic_break_enabled = 0;
}
else if (params[1][8] == '1') {
BX_INFO(("Stopping on magic break points"));
bx_dbg.magic_break_enabled = 1;
else if (params[1][8] == '1'){
{
bx_dbg_set_magic_bp_mask(bx_dbg_get_magic_bp_mask_from_str(params[1]));
BX_INFO(("Stopping on magic break points, mask: 0x%x", bx_dbg.magic_break));
}
}
else {
PARSE_ERR(("%s: magic_break directive malformed.", context));
PARSE_ERR(("%s: magic_break directive malformed", context));
}
#else
PARSE_WARN(("%s: Bochs is not compiled with internal debugger support", context));
Expand Down Expand Up @@ -3401,7 +3408,7 @@ int bx_write_debugger_options(FILE *fp)
{
#if BX_DEBUGGER
fprintf(fp, "debugger_log: %s\n", SIM->get_param_string(BXPN_DEBUGGER_LOG_FILENAME)->getptr());
fprintf(fp, "magic_break: enabled=%d\n", bx_dbg.magic_break_enabled);
fprintf(fp, "magic_break: enabled=1 0x%x\n", bx_dbg.magic_break);
// TODO: debug symbols
#endif
#if BX_GDBSTUB
Expand Down
7 changes: 6 additions & 1 deletion bochs/cpu/cpu.cc
Original file line number Diff line number Diff line change
Expand Up @@ -775,7 +775,12 @@ bool BX_CPU_C::dbg_instruction_epilog(void)

#if BX_GDBSTUB
if (bx_dbg.gdbstub_enabled) {
unsigned reason = bx_gdbstub_check(EIP);
unsigned reason =
#if BX_SUPPORT_X86_64 == 0
bx_gdbstub_check(EIP);
#else
bx_gdbstub_check(RIP);
#endif
if (reason != GDBSTUB_STOP_NO_REASON) return(1);
}
#endif
Expand Down
12 changes: 10 additions & 2 deletions bochs/cpu/data_xfer16.cc
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,16 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::XCHG_EwGwR(bxInstruction_c *i)
Bit16u op1_16, op2_16;

#if BX_DEBUGGER
// Note for mortals: the instruction to trigger this is "xchgw %bx,%bx"
if (bx_dbg.magic_break_enabled && (i->src() == 3) && (i->dst() == 3))
/* Note for mortals: the instruction to trigger this is "xchgw %regw,%regw"
66:87C9 | xchg cx,cx | 1000011111 001 001 -> 1
66:87D2 | xchg dx,dx | 1000011111 010 010 -> 2
66:87DB | xchg bx,bx | 1000011111 011 011 -> 3
66:87E4 | xchg sp,sp | 1000011111 100 100 -> 4
66:87ED | xchg bp,bp | 1000011111 101 101 -> 5
66:87F6 | xchg si,si | 1000011111 110 110 -> 6
66:87FF | xchg di,di | 1000011111 111 111 -> 7
*/
if (bx_dbg.magic_break && i->src() == i->dst() && (bx_dbg.magic_break & (1 << (i->src() - 1))))
{
BX_CPU_THIS_PTR magic_break = 1;
BX_NEXT_INSTR(i);
Expand Down
Loading

0 comments on commit a373730

Please sign in to comment.