add iodebug support for all rings complement #64 (#66)

This PR is for "I/O Interface to Bochs Debugger" from ring3 (port range:
**0x8A00 - 0x8A01**)

PR #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 #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?
This commit is contained in:
Dreg 2023-08-27 18:34:01 +02:00 committed by GitHub
parent da43cc4580
commit 86eff7597d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 65 additions and 0 deletions

View File

@ -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

View File

@ -286,6 +286,7 @@ sound
misc
port_e9_hack
port_e9_hack_all_rings
iodebug_all_rings
gdbstub
port
text_base

View File

@ -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);
@ -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);
}
@ -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])) {
@ -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());

View File

@ -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 ||

View File

@ -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>

View File

@ -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"