Skip to content
Snippets Groups Projects
Commit 1d9dae0e authored by Horst Schirmeier's avatar Horst Schirmeier
Browse files

bochs: translate virtual to linear addresses

This change makes MemoryAccessListeners deliver linear addresses
instead of virtual ones deprived of their segment selector.  Even in
modern operating systems, segment selectors are still used for, e.g.,
thread-local storage.

The hooks within MemAccess.ah could maybe be implemented in a simpler
and less fragile way using the BX_INSTR_LIN_ACCESS instrumentation
hook, but this needs more investigation.

Change-Id: I0cee6271d6812d0a29b3a24f34d605a327ced7da
parent 246938d4
No related branches found
No related tags found
No related merge requests found
......@@ -15,14 +15,21 @@
#include "../SALInst.hpp"
#include "BochsHelpers.hpp"
// FIXME: We currently assume a "flat" memory model and ignore the segment
// parameter of all memory accesses.
// FIXME: This aspect currently only retrieves linear addresses, not
// physical ones. Addresses may become invalid once the guest OS switches
// to a different page table. Nevertheless, linear addresses come in quite
// handy for matching with high-level data structures.
// TODO: Instruction fetch?
// TODO: Warn on uncovered memory accesses.
aspect MemAccess {
fail::address_t rmw_address;
// It would be nice to hook bx_cpu_c::access_write_linear(), but
// unfortunately it seems quite commonplace in Bochs code to bypass it.
// TODO: Investigate using the BX_INSTR_LIN_ACCESS instrumentation hook
// instead.
pointcut write_methods() =
"% ...::bx_cpu_c::write_virtual_%(...)" && // -> access32/64.cc
// not an actual memory access:
......@@ -64,8 +71,11 @@ aspect MemAccess {
advice execution (write_methods()) : after ()
{
fail::ConcreteCPU& triggerCPU = fail::simulator.detectCPU(getCPU(tjp->that()));
unsigned s = *(tjp->arg<0>()); // segment selector
uint32_t offset = *(tjp->arg<1>());
uint32_t laddr = tjp->that()->get_laddr32(s, offset);
fail::simulator.onMemoryAccess(&triggerCPU,
*(tjp->arg<1>()), sizeof(*(tjp->arg<2>())), true,
laddr, sizeof(*(tjp->arg<2>())), true,
getCPU(tjp->that())->prev_rip);
}
......@@ -82,8 +92,10 @@ aspect MemAccess {
//std::cerr << "WOOOOOT write_methods_new_stack" << std::endl;
// TODO: Log-level?
fail::ConcreteCPU& triggerCPU = fail::simulator.detectCPU(getCPU(tjp->that()));
uint32_t offset = *(tjp->arg<1>());
uint32_t laddr = (Bit32u)((*(tjp->arg<0>()))->cache.u.segment.base) + offset;
fail::simulator.onMemoryAccess(&triggerCPU,
*(tjp->arg<1>()), sizeof(*(tjp->arg<3>())), true,
laddr, sizeof(*(tjp->arg<3>())), true,
getCPU(tjp->that())->prev_rip);
}
......@@ -122,16 +134,22 @@ aspect MemAccess {
advice execution (read_methods()) : before ()
{
fail::ConcreteCPU& triggerCPU = fail::simulator.detectCPU(getCPU(tjp->that()));
unsigned s = *(tjp->arg<0>()); // segment selector
uint32_t offset = *(tjp->arg<1>());
uint32_t laddr = tjp->that()->get_laddr32(s, offset);
fail::simulator.onMemoryAccess(&triggerCPU,
*(tjp->arg<1>()), sizeof(*(tjp->result())), false,
laddr, sizeof(*(tjp->result())), false,
getCPU(tjp->that())->prev_rip);
}
advice execution (read_methods_dqword()) : before ()
{
fail::ConcreteCPU& triggerCPU = fail::simulator.detectCPU(getCPU(tjp->that()));
unsigned s = *(tjp->arg<0>()); // segment selector
uint32_t offset = *(tjp->arg<1>());
uint32_t laddr = tjp->that()->get_laddr32(s, offset);
fail::simulator.onMemoryAccess(&triggerCPU,
*(tjp->arg<1>()), 16, false,
laddr, 16, false,
getCPU(tjp->that())->prev_rip);
}
#endif
......@@ -139,12 +157,15 @@ aspect MemAccess {
advice execution (read_methods_RMW()) : before ()
{
#if defined(CONFIG_EVENT_MEMREAD) || defined(CONFIG_EVENT_MEMWRITE)
rmw_address = *(tjp->arg<1>());
unsigned s = *(tjp->arg<0>()); // segment selector
uint32_t offset = *(tjp->arg<1>());
uint32_t laddr = tjp->that()->get_laddr32(s, offset);
rmw_address = laddr;
#endif
#ifdef CONFIG_EVENT_MEMREAD
fail::ConcreteCPU& triggerCPU = fail::simulator.detectCPU(getCPU(tjp->that()));
fail::simulator.onMemoryAccess(&triggerCPU,
*(tjp->arg<1>()), sizeof(*(tjp->result())), false,
laddr, sizeof(*(tjp->result())), false,
getCPU(tjp->that())->prev_rip);
#endif
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment