From 1d9dae0e21a146740324dc1b720fc2a003600779 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Thu, 23 Jul 2015 20:22:26 +0200 Subject: [PATCH] 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 --- src/core/sal/bochs/MemAccess.ah | 37 ++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/src/core/sal/bochs/MemAccess.ah b/src/core/sal/bochs/MemAccess.ah index f9f180f3..52788880 100644 --- a/src/core/sal/bochs/MemAccess.ah +++ b/src/core/sal/bochs/MemAccess.ah @@ -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 }