Skip to content

Commit

Permalink
improvement of the magic breakpoints fix #55 (#58)
Browse files Browse the repository at this point in the history
  • Loading branch information
therealdreg authored Aug 20, 2023
1 parent b7d4445 commit 244033e
Show file tree
Hide file tree
Showing 9 changed files with 152 additions and 19 deletions.
15 changes: 12 additions & 3 deletions bochs/.bochsrc
Original file line number Diff line number Diff line change
Expand Up @@ -1271,13 +1271,22 @@ 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 "XCHG %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
2 changes: 1 addition & 1 deletion bochs/bochs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
46 changes: 45 additions & 1 deletion bochs/bx_debug/dbg_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2283,6 +2283,50 @@ void bx_dbg_lyt(void)
bx_nest_infile(layoutpath);
}

void bx_dbg_set_magic_bp_mask(Bit8u new_mask)
{
bx_dbg.magic_break = new_mask;
bx_dbg_print_magic_bp_mask_from_str(bx_dbg.magic_break);
}

void bx_dbg_clr_magic_bp_mask(Bit8u mask)
{
bx_dbg.magic_break &= ~mask;
bx_dbg_print_magic_bp_mask_from_str(bx_dbg.magic_break);
}

static const char* const magic_bp_regs[] = { "ax" /* not accessible */, "cx", "dx", "bx", "sp", "bp", "si", "di" };

void bx_dbg_print_magic_bp_mask_from_str(Bit8u mask)
{
dbg_printf("magic breakpoint mask: 0x%x ", mask);

for (int i = 1; i < 8; i++) {
if (mask & (1 << i)) {
dbg_printf("%s ", magic_bp_regs[i]);
}
}

dbg_printf("\n");
}

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

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

for (int i = 1; i < 8; i++) {
if (strstr(str, magic_bp_regs[i]) != NULL) {
new_mask |= (1 << i);
}
}

return new_mask;
}

void bx_dbg_print_guard_results(void)
{
unsigned cpu, i;
Expand Down Expand Up @@ -3796,7 +3840,7 @@ void bx_dbg_print_help(void)
dbg_printf(" c|cont|continue, s|step, p|n|next, modebp, vmexitbp\n");
dbg_printf("-*- Breakpoint management -*-\n");
dbg_printf(" vb|vbreak, lb|lbreak, pb|pbreak|b|break, sb, sba, blist,\n");
dbg_printf(" bpe, bpd, d|del|delete, watch, unwatch\n");
dbg_printf(" bpe, bpd, d|del|delete, watch, unwatch, setmagicbps, clrmagicbps\n");
dbg_printf("-*- CPU and memory contents -*-\n");
dbg_printf(" x, xp, setpmem, writemem, loadmem, crc, info, deref,\n");
dbg_printf(" r|reg|regs|registers, fp|fpu, mmx, sse, sreg, dreg, creg,\n");
Expand Down
4 changes: 4 additions & 0 deletions bochs/bx_debug/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ 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 new_mask);
void bx_dbg_clr_magic_bp_mask(Bit8u mask);
Bit8u bx_dbg_get_magic_bp_mask_from_str(const char *str);
void bx_dbg_print_magic_bp_mask_from_str(Bit8u mask);
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
2 changes: 2 additions & 0 deletions bochs/bx_debug/lexer.l
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ 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); }
clrmagicbps { bxlval.sval = strdup(bxtext); return(BX_TOKEN_CLEAR_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
40 changes: 40 additions & 0 deletions bochs/bx_debug/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ 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_CLEAR_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 +202,8 @@ command:
| vmexitbp_command
| print_stack_command
| backtrace_command
| set_magic_break_points_command
| clr_magic_break_points_command
| watch_point_command
| page_command
| tlb_command
Expand Down Expand Up @@ -459,6 +463,32 @@ 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);
}
;

clr_magic_break_points_command:
BX_TOKEN_CLEAR_MAGIC_BREAK_POINTS '\n'
{
bx_dbg_set_magic_bp_mask(0);
free($1);
}
| BX_TOKEN_CLEAR_MAGIC_BREAK_POINTS BX_TOKEN_STRING '\n'
{
bx_dbg_clr_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 +1188,16 @@ 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\" - set new magic breakpoints. You can specify multiple at once. Using the setmagicbps command without any arguments will disable all of them\n");
free($1);free($2);
}
| BX_TOKEN_HELP BX_TOKEN_CLEAR_MAGIC_BREAK_POINTS '\n'
{
dbg_printf("clrmagicbps \"cx dx bx sp bp si di\" - clear magic breakpoints. You can specify multiple at once. Using the clrmagicbps command without any arguments will 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
19 changes: 10 additions & 9 deletions bochs/config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3147,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 @@ -3155,14 +3156,14 @@ 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 {
PARSE_ERR(("%s: magic_break directive malformed.", context));
} else if (params[1][8] == '1') {
bx_dbg_set_magic_bp_mask(bx_dbg_get_magic_bp_mask_from_str(params[1]));
if (0 == bx_dbg.magic_break) {
// bx if not specified for backward compatibility
bx_dbg_set_magic_bp_mask(bx_dbg_get_magic_bp_mask_from_str("bx"));
}
} else {
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 @@ -3406,7 +3407,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
13 changes: 10 additions & 3 deletions bochs/cpu/data_xfer16.cc
Original file line number Diff line number Diff line change
Expand Up @@ -219,9 +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())))) {
BX_CPU_THIS_PTR magic_break = 1;
BX_NEXT_INSTR(i);
}
Expand Down
30 changes: 28 additions & 2 deletions bochs/doc/docbook/user/user.dbk
Original file line number Diff line number Diff line change
Expand Up @@ -5167,13 +5167,21 @@ This enables the GDB stub. See <xref linkend="debugging-with-gdb">.

<section><title>magic_break</title>
<para>
Example:
Example for breaking on "XCHGW %DI, %DI" or "XCHGW %SP, %SP" execution
<screen>
magic_break: enabled=1 di sp
</screen>
If nothing is specified, the default will be used: XCHGW %BX, %BX
Note: Windows XP ntldr can cause problems with XCHGW %BX, %BX
<screen>
magic_break: enabled=1
</screen>
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 instruction XCHGW REGW, REGW causes Bochs to enter the
debugger mode. This might be useful for software development.
<screen>
cx dx bx sp bp si di
</screen>
</para>
</section>

Expand Down Expand Up @@ -7391,6 +7399,24 @@ context.
<para>
The symbol file consists of zero or more lines of the format <screen>"%x %s"</screen>.

<screen>setmagicbps "cx dx bx sp bp si di"</screen>

Set new magic breakpoints. You can specify multiple at once. Using the setmagicbps command without any arguments will disable all of them

Example for breaking on "XCHGW %DI, %DI" or "XCHGW %SP, %SP" execution
<screen>
setmagicbps "di sp"
</screen>

<screen>clrmagicbps "cx dx bx sp bp si di"</screen>

Clear magic breakpoints. You can specify multiple at once. Using the clrmagicbps command without any arguments will disable all of them

Example for clearing "XCHGW %DI, %DI" and "XCHGW %SP, %SP"
<screen>
clrmagicbps "di sp"
</screen>

<screen>show [<varname>string</varname>]</screen>

<screen>
Expand Down

0 comments on commit 244033e

Please sign in to comment.