Skip to content

Commit

Permalink
Artificially insert Tenet memory read/write entries when the user doe…
Browse files Browse the repository at this point in the history
…s memory reads / writes in breakpoint callbacks or anywhere else. (fix #210) (#216)
  • Loading branch information
0vercl0k authored Dec 5, 2024
1 parent a231e0a commit 1397403
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 19 deletions.
3 changes: 3 additions & 0 deletions src/wtf/backend.cc
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ bool Backend_t::VirtRead(const Gva_t Gva, uint8_t *Buffer,
const uint64_t Size2Read = std::min(Size, BytesReadable);
const uint8_t *Hva = PhysTranslate(Gpa);
memcpy(Buffer, Hva, Size2Read);
TrackTenetMemoryAccess(CurrentGva.U64(), Size2Read, BOCHSCPU_HOOK_MEM_READ);
Size -= Size2Read;
CurrentGva += Gva_t(Size2Read);
Buffer += Size2Read;
Expand Down Expand Up @@ -111,6 +112,8 @@ bool Backend_t::VirtWrite(const Gva_t Gva, const uint8_t *Buffer,
const uint64_t Size2Write = std::min(Size, BytesWriteable);
uint8_t *Hva = PhysTranslate(Gpa);
memcpy(Hva, Buffer, Size2Write);
TrackTenetMemoryAccess(CurrentGva.U64(), Size2Write,
BOCHSCPU_HOOK_MEM_WRITE);
Size -= Size2Write;
CurrentGva += Gva_t(Size2Write);
Buffer += Size2Write;
Expand Down
8 changes: 8 additions & 0 deletions src/wtf/backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,14 @@ class Backend_t {

virtual bool RevokeLastNewCoverage() = 0;

//
// Track a memory access to be able to generate a Tenet trace.
//

virtual void TrackTenetMemoryAccess(const uint64_t VirtualAddress,
const uint64_t Len,
const uint32_t MemAccess) const {}

//
// Print the registers.
//
Expand Down
58 changes: 45 additions & 13 deletions src/wtf/bochscpu_backend.cc
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,6 @@ BochscpuBackend_t::Run(const uint8_t *Buffer, const uint64_t BufferSize) {
// Reset Tenet state.
//

Tenet_.MemAccesses_.clear();
Tenet_.PastFirstInstruction_ = false;

//
Expand Down Expand Up @@ -547,6 +546,18 @@ __declspec(safebuffers)
}
}

void BochscpuBackend_t::TrackTenetMemoryAccess(const uint64_t VirtualAddress,
const uint64_t Len,
const uint32_t MemAccess) const {
//
// Log explicit details about the memory access if taking a full-trace.
//

if (TraceFile_ && TraceType_ == TraceType_t::Tenet) {
Tenet_.MemAccesses_.emplace_back(VirtualAddress, Len, MemAccess);
}
}

void BochscpuBackend_t::LinAccessHook(/*void *Context, */ uint32_t,
uint64_t VirtualAddress,
uint64_t PhysicalAddress, uintptr_t Len,
Expand All @@ -570,9 +581,7 @@ void BochscpuBackend_t::LinAccessHook(/*void *Context, */ uint32_t,
// Log explicit details about the memory access if taking a full-trace.
//

if (TraceFile_ && TraceType_ == TraceType_t::Tenet) {
Tenet_.MemAccesses_.emplace_back(VirtualAddress, Len, MemAccess);
}
TrackTenetMemoryAccess(VirtualAddress, Len, MemAccess);

//
// If this is not a write access, we don't care to go further.
Expand Down Expand Up @@ -1202,7 +1211,6 @@ MemAccessToTenetLabel(const uint32_t MemAccess) {

case BOCHSCPU_HOOK_MEM_WRITE: {
return "mw";
break;
}

default: {
Expand Down Expand Up @@ -1271,29 +1279,53 @@ void BochscpuBackend_t::DumpTenetDelta(const bool Force) {
//
// Fetch the memory that was read or written by the last executed
// instruction. The largest load that can happen today is an AVX512
// load which is 64 bytes long.
// load which is 64 bytes long... unless the access is coming from a user
// calling `VirtWrite*` in which case the access size can be of arbitrary
// size.
//
// What we'll do is only allocate a heap buffer if the `AccessInfo.Len` is
// larger than the static buffer below; this should avoid allocating /
// deallocating every time we get here.
//

std::array<uint8_t, 64> Buffer;
if (AccessInfo.Len > Buffer.size()) {
fmt::print("A memory access was bigger than {} bytes, aborting\n",
AccessInfo.Len);
std::abort();
std::array<uint8_t, 64> StaticBuffer;
std::vector<uint8_t> DynamicBuffer;
uint8_t *Buffer = nullptr;
if (AccessInfo.Len <= StaticBuffer.size()) {
Buffer = StaticBuffer.data();
} else {
DynamicBuffer.resize(AccessInfo.Len);
Buffer = DynamicBuffer.data();
}

if (!VirtRead(AccessInfo.VirtualAddress, Buffer.data(), AccessInfo.Len)) {
//
// Avoid reentrance by disabling tenet.
//

TraceType_ = TraceType_t::Rip;

if (!VirtRead(AccessInfo.VirtualAddress, Buffer, AccessInfo.Len)) {
fmt::print("VirtRead at {:#x} failed, aborting\n",
AccessInfo.VirtualAddress);
std::abort();
}

TraceType_ = TraceType_t::Tenet;

//
// Convert the raw memory bytes to a human-readable hex string.
//

std::string HexString;
HexString.reserve(AccessInfo.Len * 2);
const char HexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
for (size_t Idx = 0; Idx < AccessInfo.Len; Idx++) {
HexString = fmt::format("{}{:02X}", HexString, Buffer[Idx]);
char Hex[3];
Hex[0] = HexDigits[(Buffer[Idx] >> 4) & 0xf];
Hex[1] = HexDigits[(Buffer[Idx] >> 0) & 0xf];
Hex[2] = 0;
HexString.append(Hex);
}

//
Expand Down
5 changes: 4 additions & 1 deletion src/wtf/bochscpu_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ class BochscpuBackend_t : public Backend_t {
//

std::vector<BochscpuMemAccess_t> MemAccesses_;
} Tenet_;
} mutable Tenet_;

//
// The hooks we define onto the Cpu.
Expand Down Expand Up @@ -268,6 +268,9 @@ class BochscpuBackend_t : public Backend_t {

bool RevokeLastNewCoverage() override;

void TrackTenetMemoryAccess(const uint64_t VirtualAddress, const uint64_t Len,
const uint32_t MemAccess) const override;

//
// Hooks.
//
Expand Down
7 changes: 2 additions & 5 deletions src/wtf/wtf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,9 @@ int main(int argc, const char *argv[]) {
Opts.Run.TraceType = TraceType_t::Rip;
break;
}
#ifdef WINDOWS
case BackendType_t::Whv: {
#endif
#ifdef LINUX

case BackendType_t::Whv:
case BackendType_t::Kvm: {
#endif
Opts.Run.TraceType = TraceType_t::UniqueRip;
break;
}
Expand Down

0 comments on commit 1397403

Please sign in to comment.