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
This commit is contained in:
@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user