Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #210 #216

Merged
merged 4 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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