Skip to content

Commit

Permalink
add iodebug support for all rings complement bochs-emu#64 (bochs-emu#66)
Browse files Browse the repository at this point in the history
This PR is for "I/O Interface to Bochs Debugger" from ring3 (port range:
**0x8A00 - 0x8A01**)

PR bochs-emu#64 was for E9 HACK (port **0xE9**)

By enabling the iodebug's 'all_rings' option, you can utilize the port
I/O Interface to Bochs Debugger from ring3. This PR allows the code
running inside Bochs (ring3) to monitor memory ranges, trace individual
instructions, and observe register values during execution.


https://bochs.sourceforge.io/doc/docbook/development/debugger-advanced.html

IMO very useful for:

- user-mode sandbox (ex Cuckoo)
- malware analysis
- API/SYSCALL hook/monitor from ring3
- automation + instrumentation from user mode code
...

A complement for PR bochs-emu#64

**This PR is 100% backward compatibility**

![IODEBUG ALL
RINGS](https://github.com/bochs-emu/Bochs/assets/9882181/6308ad0f-c189-43f3-a92b-dccde3542ad6)

btw, @stlintel I'm not certain about:
- if misc is the ideal location for this.. should I create a new
iodebug-option for this?
- should I remove the #if in 'new bx_param_bool_c'?
- the new .bochsrc entry makes sense for you?
  • Loading branch information
therealdreg authored Aug 27, 2023
1 parent da43cc4 commit 86eff75
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 0 deletions.
13 changes: 13 additions & 0 deletions bochs/.bochsrc
Original file line number Diff line number Diff line change
Expand Up @@ -1319,6 +1319,19 @@ speaker: enabled=1, mode=sound, volume=15
#=======================================================================
#port_e9_hack: enabled=1

#=======================================================================
# IODEBUG:
# I/O Interface to Bochs Debugger plugin allows the code running inside
# Bochs to monitor memory ranges, trace individual instructions, and
# observe register values during execution. By enabling the 'all_rings'
# option, you can utilize the iodebug ports from ring3. For more
# information, refer to "Advanced debugger usage" documentation.
#
# Example:
# iodebug: all_rings=1
#=======================================================================
#iodebug: all_rings=1

#=======================================================================
# fullscreen: ONLY IMPLEMENTED ON AMIGA
# Request that Bochs occupy the entire screen instead of a
Expand Down
1 change: 1 addition & 0 deletions bochs/PARAM_TREE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ sound
misc
port_e9_hack
port_e9_hack_all_rings
iodebug_all_rings
gdbstub
port
text_base
Expand Down
30 changes: 30 additions & 0 deletions bochs/config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1686,6 +1686,15 @@ void bx_init_options()
"Debug messages written to i/o port 0xE9 from ring3 will be displayed on console",
0);

#if BX_SUPPORT_IODEBUG
// iodebug all rings
new bx_param_bool_c(misc,
"iodebug_all_rings",
"Enable iodebug ports for all rings",
"I/O Interface to Bochs Debugger plugin for all rings",
0);
#endif

// GDB stub
menu = new bx_list_c(misc, "gdbstub", "GDB Stub Options");
menu->set_options(menu->SHOW_PARENT | menu->USE_BOX_TITLE);
Expand Down Expand Up @@ -1771,6 +1780,9 @@ void bx_init_options()
misc->add(SIM->get_param(BXPN_USER_SHORTCUT));
misc->add(SIM->get_param(BXPN_PORT_E9_HACK));
misc->add(SIM->get_param(BXPN_PORT_E9_HACK_ALL_RINGS));
#if BX_SUPPORT_IODEBUG
misc->add(SIM->get_param(BXPN_IODEBUG_ALL_RINGS));
#endif
misc->set_options(misc->SHOW_PARENT | misc->SHOW_GROUP_NAME);
}

Expand Down Expand Up @@ -3221,6 +3233,21 @@ static int parse_line_formatted(const char *context, int num_params, char *param
if (parse_port_e9_hack(context, (const char **)(params + 1), num_params - 1) < 0) {
return -1;
}
} else if (!strcmp(params[0], "iodebug")) {
#if BX_SUPPORT_IODEBUG
if (num_params != 2) {
PARSE_ERR(("%s: iodebug directive: wrong # args.", context));
}
if (!strncmp(params[1], "all_rings=", 10)) {
if (parse_param_bool(params[1], 10, BXPN_IODEBUG_ALL_RINGS) < 0) {
PARSE_ERR(("%s: all_rings option malformed.", context));
}
} else {
PARSE_ERR(("%s: iodebug: invalid parameter %s", context, params[1]));
}
#else
PARSE_WARN(("%s: Bochs is not compiled with iodebug support", context));
#endif
} else if (!strcmp(params[0], "load32bitOSImage")) {
PARSE_ERR(("%s: load32bitOSImage: This legacy feature is no longer supported.", context));
} else if (SIM->is_addon_option(params[0])) {
Expand Down Expand Up @@ -3577,6 +3604,9 @@ int bx_write_configuration(const char *rc, int overwrite)
bx_write_debugger_options(fp);
fprintf(fp, "port_e9_hack: enabled=%d\n", SIM->get_param_bool(BXPN_PORT_E9_HACK)->get());
fprintf(fp, "port_e9_hack_all_rings: enabled=%d\n", SIM->get_param_bool(BXPN_PORT_E9_HACK_ALL_RINGS)->get());
#if BX_SUPPORT_IODEBUG
fprintf(fp, "iodebug_all_rings: enabled=%d\n", SIM->get_param_bool(BXPN_IODEBUG_ALL_RINGS)->get());
#endif
fprintf(fp, "private_colormap: enabled=%d\n", SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->get());
#if BX_WITH_AMIGAOS
fprintf(fp, "fullscreen: enabled=%d\n", SIM->get_param_bool(BXPN_FULLSCREEN)->get());
Expand Down
6 changes: 6 additions & 0 deletions bochs/cpu/io.cc
Original file line number Diff line number Diff line change
Expand Up @@ -869,6 +869,12 @@ bool BX_CPP_AttrRegparmN(3) BX_CPU_C::allow_io(bxInstruction_c *i, Bit16u port,
if (0xe9 == port && port_e9_hack_all_rings)
return(1); // port e9 hack can be used by unprivileged code

#if BX_SUPPORT_IODEBUG
static bool iodebug_all_rings = SIM->get_param_bool(BXPN_IODEBUG_ALL_RINGS)->get();
if (0x8A00 == (port & 0xfffe) && iodebug_all_rings)
return(1); // iodebug ports (0x8A00 & 0x8A01) can be used by unprivileged code
#endif /* if BX_SUPPORT_IODEBUG */

if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL > BX_CPU_THIS_PTR get_IOPL())))
{
if (BX_CPU_THIS_PTR tr.cache.valid==0 ||
Expand Down
14 changes: 14 additions & 0 deletions bochs/doc/docbook/user/user.dbk
Original file line number Diff line number Diff line change
Expand Up @@ -5218,6 +5218,20 @@ option, you can utilize the port e9 hack from ring3.
</para>
</section>

<section><title>IODEBUG</title>
<para>
Example:
<screen>
iodebug: all_rings=1
</screen>
I/O Interface to Bochs Debugger plugin allows the code running inside
Bochs to monitor memory ranges, trace individual instructions, and
observe register values during execution. By enabling the 'all_rings'
option, you can utilize the iodebug ports from ring3. For more
information, refer to "Advanced debugger usage" documentation.
</para>
</section>

</section> <!--end of bochsrc section-->

<section id="keymap"><title>How to write your own keymap table</title>
Expand Down
1 change: 1 addition & 0 deletions bochs/param_names.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@
#define BXPN_SOUND_ES1370 "sound.es1370"
#define BXPN_PORT_E9_HACK "misc.port_e9_hack"
#define BXPN_PORT_E9_HACK_ALL_RINGS "misc.port_e9_hack_all_rings"
#define BXPN_IODEBUG_ALL_RINGS "misc.iodebug_all_rings"
#define BXPN_GDBSTUB "misc.gdbstub"
#define BXPN_LOG_FILENAME "log.filename"
#define BXPN_LOG_PREFIX "log.prefix"
Expand Down

0 comments on commit 86eff75

Please sign in to comment.