UserspaceEmulator: Keep Emulator& closer to the action in some places

This avoids the cost of calling Emulator::the() in some very hot paths.
This commit is contained in:
Andreas Kling 2020-11-16 14:39:05 +01:00
parent d14695f823
commit 1965fc5b98
Notes: sideshowbarker 2024-07-19 01:22:06 +09:00
9 changed files with 127 additions and 70 deletions

View File

@ -2,6 +2,7 @@ set(SOURCES
Emulator.cpp
MallocTracer.cpp
MmapRegion.cpp
Region.cpp
SharedBufferRegion.cpp
SimpleRegion.cpp
SoftCPU.cpp

View File

@ -72,9 +72,10 @@ Emulator& Emulator::the()
Emulator::Emulator(const Vector<String>& arguments, const Vector<String>& environment, NonnullRefPtr<ELF::Loader> elf)
: m_elf(move(elf))
, m_mmu(*this)
, m_cpu(*this)
{
m_malloc_tracer = make<MallocTracer>();
m_malloc_tracer = make<MallocTracer>(*this);
ASSERT(!s_the);
s_the = this;
setup_stack(arguments, environment);

View File

@ -36,14 +36,15 @@
namespace UserspaceEmulator {
MallocTracer::MallocTracer()
MallocTracer::MallocTracer(Emulator& emulator)
: m_emulator(emulator)
{
}
template<typename Callback>
inline void MallocTracer::for_each_mallocation(Callback callback) const
{
Emulator::the().mmu().for_each_region([&](auto& region) {
m_emulator.mmu().for_each_region([&](auto& region) {
if (region.is_mmap() && static_cast<const MmapRegion&>(region).is_malloc_block()) {
auto* malloc_data = static_cast<MmapRegion&>(region).malloc_metadata();
for (auto& mallocation : malloc_data->mallocations) {
@ -57,7 +58,7 @@ inline void MallocTracer::for_each_mallocation(Callback callback) const
void MallocTracer::target_did_malloc(Badge<SoftCPU>, FlatPtr address, size_t size)
{
auto* region = Emulator::the().mmu().find_region({ 0x20, address });
auto* region = m_emulator.mmu().find_region({ 0x20, address });
ASSERT(region);
ASSERT(region->is_mmap());
auto& mmap_region = static_cast<MmapRegion&>(*region);
@ -72,7 +73,7 @@ void MallocTracer::target_did_malloc(Badge<SoftCPU>, FlatPtr address, size_t siz
ASSERT(existing_mallocation->freed);
existing_mallocation->size = size;
existing_mallocation->freed = false;
existing_mallocation->malloc_backtrace = Emulator::the().raw_backtrace();
existing_mallocation->malloc_backtrace = m_emulator.raw_backtrace();
existing_mallocation->free_backtrace.clear();
return;
}
@ -92,7 +93,7 @@ void MallocTracer::target_did_malloc(Badge<SoftCPU>, FlatPtr address, size_t siz
malloc_data->mallocations.resize(1);
dbgln("Tracking malloc block @ {:p} with chunk_size={}, chunk_count={}", malloc_data->address, malloc_data->chunk_size, malloc_data->mallocations.size());
}
malloc_data->mallocation_for_address(address) = { address, size, true, false, Emulator::the().raw_backtrace(), Vector<FlatPtr>() };
malloc_data->mallocation_for_address(address) = { address, size, true, false, m_emulator.raw_backtrace(), Vector<FlatPtr>() };
}
ALWAYS_INLINE Mallocation& MallocRegionMetadata::mallocation_for_address(FlatPtr address) const
@ -120,22 +121,22 @@ void MallocTracer::target_did_free(Badge<SoftCPU>, FlatPtr address)
if (mallocation->freed) {
reportln("\n=={}== \033[31;1mDouble free()\033[0m, {:p}", getpid(), address);
reportln("=={}== Address {} has already been passed to free()", getpid(), address);
Emulator::the().dump_backtrace();
m_emulator.dump_backtrace();
} else {
mallocation->freed = true;
mallocation->free_backtrace = Emulator::the().raw_backtrace();
mallocation->free_backtrace = m_emulator.raw_backtrace();
}
return;
}
reportln("\n=={}== \033[31;1mInvalid free()\033[0m, {:p}", getpid(), address);
reportln("=={}== Address {} has never been returned by malloc()", getpid(), address);
Emulator::the().dump_backtrace();
m_emulator.dump_backtrace();
}
void MallocTracer::target_did_realloc(Badge<SoftCPU>, FlatPtr address, size_t size)
{
auto* region = Emulator::the().mmu().find_region({ 0x20, address });
auto* region = m_emulator.mmu().find_region({ 0x20, address });
ASSERT(region);
ASSERT(region->is_mmap());
auto& mmap_region = static_cast<MmapRegion&>(*region);
@ -158,7 +159,7 @@ void MallocTracer::target_did_realloc(Badge<SoftCPU>, FlatPtr address, size_t si
existing_mallocation->size = size;
// FIXME: Should we track malloc/realloc backtrace separately perhaps?
existing_mallocation->malloc_backtrace = Emulator::the().raw_backtrace();
existing_mallocation->malloc_backtrace = m_emulator.raw_backtrace();
}
Mallocation* MallocTracer::find_mallocation(const Region& region, FlatPtr address)
@ -179,7 +180,7 @@ Mallocation* MallocTracer::find_mallocation(const Region& region, FlatPtr addres
Mallocation* MallocTracer::find_mallocation(FlatPtr address)
{
auto* region = Emulator::the().mmu().find_region({ 0x23, address });
auto* region = m_emulator.mmu().find_region({ 0x23, address });
if (!region)
return nullptr;
return find_mallocation(*region, address);
@ -216,26 +217,26 @@ void MallocTracer::audit_read(const Region& region, FlatPtr address, size_t size
if (!m_auditing_enabled)
return;
if (Emulator::the().is_in_malloc_or_free())
if (m_emulator.is_in_malloc_or_free())
return;
auto* mallocation = find_mallocation(region, address);
if (!mallocation) {
reportln("\n=={}== \033[31;1mHeap buffer overflow\033[0m, invalid {}-byte read at address {:p}", getpid(), size, address);
Emulator::the().dump_backtrace();
m_emulator.dump_backtrace();
auto* mallocation_before = find_mallocation_before(address);
auto* mallocation_after = find_mallocation_after(address);
size_t distance_to_mallocation_before = mallocation_before ? (address - mallocation_before->address - mallocation_before->size) : 0;
size_t distance_to_mallocation_after = mallocation_after ? (mallocation_after->address - address) : 0;
if (mallocation_before && (!mallocation_after || distance_to_mallocation_before < distance_to_mallocation_after)) {
reportln("=={}== Address is {} byte(s) after block of size {}, identity {:p}, allocated at:", getpid(), distance_to_mallocation_before, mallocation_before->size, mallocation_before->address);
Emulator::the().dump_backtrace(mallocation_before->malloc_backtrace);
m_emulator.dump_backtrace(mallocation_before->malloc_backtrace);
return;
}
if (mallocation_after && (!mallocation_before || distance_to_mallocation_after < distance_to_mallocation_before)) {
reportln("=={}== Address is {} byte(s) before block of size {}, identity {:p}, allocated at:", getpid(), distance_to_mallocation_after, mallocation_after->size, mallocation_after->address);
Emulator::the().dump_backtrace(mallocation_after->malloc_backtrace);
m_emulator.dump_backtrace(mallocation_after->malloc_backtrace);
}
return;
}
@ -244,11 +245,11 @@ void MallocTracer::audit_read(const Region& region, FlatPtr address, size_t size
if (mallocation->freed) {
reportln("\n=={}== \033[31;1mUse-after-free\033[0m, invalid {}-byte read at address {:p}", getpid(), size, address);
Emulator::the().dump_backtrace();
m_emulator.dump_backtrace();
reportln("=={}== Address is {} byte(s) into block of size {}, allocated at:", getpid(), offset_into_mallocation, mallocation->size);
Emulator::the().dump_backtrace(mallocation->malloc_backtrace);
m_emulator.dump_backtrace(mallocation->malloc_backtrace);
reportln("=={}== Later freed at:", getpid());
Emulator::the().dump_backtrace(mallocation->free_backtrace);
m_emulator.dump_backtrace(mallocation->free_backtrace);
return;
}
}
@ -258,25 +259,25 @@ void MallocTracer::audit_write(const Region& region, FlatPtr address, size_t siz
if (!m_auditing_enabled)
return;
if (Emulator::the().is_in_malloc_or_free())
if (m_emulator.is_in_malloc_or_free())
return;
auto* mallocation = find_mallocation(region, address);
if (!mallocation) {
reportln("\n=={}== \033[31;1mHeap buffer overflow\033[0m, invalid {}-byte write at address {:p}", getpid(), size, address);
Emulator::the().dump_backtrace();
m_emulator.dump_backtrace();
auto* mallocation_before = find_mallocation_before(address);
auto* mallocation_after = find_mallocation_after(address);
size_t distance_to_mallocation_before = mallocation_before ? (address - mallocation_before->address - mallocation_before->size) : 0;
size_t distance_to_mallocation_after = mallocation_after ? (mallocation_after->address - address) : 0;
if (mallocation_before && (!mallocation_after || distance_to_mallocation_before < distance_to_mallocation_after)) {
reportln("=={}== Address is {} byte(s) after block of size {}, identity {:p}, allocated at:", getpid(), distance_to_mallocation_before, mallocation_before->size, mallocation_before->address);
Emulator::the().dump_backtrace(mallocation_before->malloc_backtrace);
m_emulator.dump_backtrace(mallocation_before->malloc_backtrace);
return;
}
if (mallocation_after && (!mallocation_before || distance_to_mallocation_after < distance_to_mallocation_before)) {
reportln("=={}== Address is {} byte(s) before block of size {}, identity {:p}, allocated at:", getpid(), distance_to_mallocation_after, mallocation_after->size, mallocation_after->address);
Emulator::the().dump_backtrace(mallocation_after->malloc_backtrace);
m_emulator.dump_backtrace(mallocation_after->malloc_backtrace);
}
return;
}
@ -285,11 +286,11 @@ void MallocTracer::audit_write(const Region& region, FlatPtr address, size_t siz
if (mallocation->freed) {
reportln("\n=={}== \033[31;1mUse-after-free\033[0m, invalid {}-byte write at address {:p}", getpid(), size, address);
Emulator::the().dump_backtrace();
m_emulator.dump_backtrace();
reportln("=={}== Address is {} byte(s) into block of size {}, allocated at:", getpid(), offset_into_mallocation, mallocation->size);
Emulator::the().dump_backtrace(mallocation->malloc_backtrace);
m_emulator.dump_backtrace(mallocation->malloc_backtrace);
reportln("=={}== Later freed at:", getpid());
Emulator::the().dump_backtrace(mallocation->free_backtrace);
m_emulator.dump_backtrace(mallocation->free_backtrace);
return;
}
}
@ -308,7 +309,7 @@ bool MallocTracer::is_reachable(const Mallocation& mallocation) const
return IterationDecision::Continue;
size_t pointers_in_mallocation = other_mallocation.size / sizeof(u32);
for (size_t i = 0; i < pointers_in_mallocation; ++i) {
auto value = Emulator::the().mmu().read32({ 0x20, other_mallocation.address + i * sizeof(u32) });
auto value = m_emulator.mmu().read32({ 0x20, other_mallocation.address + i * sizeof(u32) });
if (value.value() == mallocation.address && !value.is_uninitialized()) {
#ifdef REACHABLE_DEBUG
reportln("mallocation {:p} is reachable from other mallocation {:p}", mallocation.address, other_mallocation.address);
@ -324,7 +325,7 @@ bool MallocTracer::is_reachable(const Mallocation& mallocation) const
return true;
// 2. Search in other memory regions for pointers to this mallocation
Emulator::the().mmu().for_each_region([&](auto& region) {
m_emulator.mmu().for_each_region([&](auto& region) {
// Skip the stack
if (region.is_stack())
return IterationDecision::Continue;
@ -364,7 +365,7 @@ void MallocTracer::dump_leak_report()
++leaks_found;
bytes_leaked += mallocation.size;
reportln("\n=={}== \033[31;1mLeak\033[0m, {}-byte allocation at address {:p}", getpid(), mallocation.size, mallocation.address);
Emulator::the().dump_backtrace(mallocation.malloc_backtrace);
m_emulator.dump_backtrace(mallocation.malloc_backtrace);
return IterationDecision::Continue;
});

View File

@ -35,7 +35,7 @@
namespace UserspaceEmulator {
class MmapRegion;
class Emulator;
class SoftCPU;
struct Mallocation {
@ -66,7 +66,7 @@ public:
class MallocTracer {
public:
MallocTracer();
explicit MallocTracer(Emulator&);
void target_did_malloc(Badge<SoftCPU>, FlatPtr address, size_t);
void target_did_free(Badge<SoftCPU>, FlatPtr address);
@ -87,6 +87,8 @@ private:
Mallocation* find_mallocation_after(FlatPtr);
bool is_reachable(const Mallocation&) const;
Emulator& m_emulator;
bool m_auditing_enabled { true };
};

View File

@ -69,12 +69,12 @@ ValueWithShadow<u8> MmapRegion::read8(FlatPtr offset)
{
if (!is_readable()) {
reportln("8-bit read from unreadable MmapRegion @ {:p}", base() + offset);
Emulator::the().dump_backtrace();
emulator().dump_backtrace();
TODO();
}
if (is_malloc_block()) {
if (auto* tracer = Emulator::the().malloc_tracer())
if (auto* tracer = emulator().malloc_tracer())
tracer->audit_read(*this, base() + offset, 1);
}
@ -86,12 +86,12 @@ ValueWithShadow<u16> MmapRegion::read16(u32 offset)
{
if (!is_readable()) {
reportln("16-bit read from unreadable MmapRegion @ {:p}", base() + offset);
Emulator::the().dump_backtrace();
emulator().dump_backtrace();
TODO();
}
if (is_malloc_block()) {
if (auto* tracer = Emulator::the().malloc_tracer())
if (auto* tracer = emulator().malloc_tracer())
tracer->audit_read(*this, base() + offset, 2);
}
@ -103,12 +103,12 @@ ValueWithShadow<u32> MmapRegion::read32(u32 offset)
{
if (!is_readable()) {
reportln("32-bit read from unreadable MmapRegion @ {:p}", base() + offset);
Emulator::the().dump_backtrace();
emulator().dump_backtrace();
TODO();
}
if (is_malloc_block()) {
if (auto* tracer = Emulator::the().malloc_tracer())
if (auto* tracer = emulator().malloc_tracer())
tracer->audit_read(*this, base() + offset, 4);
}
@ -120,12 +120,12 @@ ValueWithShadow<u64> MmapRegion::read64(u32 offset)
{
if (!is_readable()) {
reportln("64-bit read from unreadable MmapRegion @ {:p}", base() + offset);
Emulator::the().dump_backtrace();
emulator().dump_backtrace();
TODO();
}
if (is_malloc_block()) {
if (auto* tracer = Emulator::the().malloc_tracer())
if (auto* tracer = emulator().malloc_tracer())
tracer->audit_read(*this, base() + offset, 8);
}
@ -137,12 +137,12 @@ void MmapRegion::write8(u32 offset, ValueWithShadow<u8> value)
{
if (!is_writable()) {
reportln("8-bit write from unwritable MmapRegion @ {:p}", base() + offset);
Emulator::the().dump_backtrace();
emulator().dump_backtrace();
TODO();
}
if (is_malloc_block()) {
if (auto* tracer = Emulator::the().malloc_tracer())
if (auto* tracer = emulator().malloc_tracer())
tracer->audit_write(*this, base() + offset, 1);
}
@ -155,12 +155,12 @@ void MmapRegion::write16(u32 offset, ValueWithShadow<u16> value)
{
if (!is_writable()) {
reportln("16-bit write from unwritable MmapRegion @ {:p}", base() + offset);
Emulator::the().dump_backtrace();
emulator().dump_backtrace();
TODO();
}
if (is_malloc_block()) {
if (auto* tracer = Emulator::the().malloc_tracer())
if (auto* tracer = emulator().malloc_tracer())
tracer->audit_write(*this, base() + offset, 2);
}
@ -173,12 +173,12 @@ void MmapRegion::write32(u32 offset, ValueWithShadow<u32> value)
{
if (!is_writable()) {
reportln("32-bit write from unwritable MmapRegion @ {:p}", base() + offset);
Emulator::the().dump_backtrace();
emulator().dump_backtrace();
TODO();
}
if (is_malloc_block()) {
if (auto* tracer = Emulator::the().malloc_tracer())
if (auto* tracer = emulator().malloc_tracer())
tracer->audit_write(*this, base() + offset, 4);
}
@ -192,12 +192,12 @@ void MmapRegion::write64(u32 offset, ValueWithShadow<u64> value)
{
if (!is_writable()) {
reportln("64-bit write from unwritable MmapRegion @ {:p}", base() + offset);
Emulator::the().dump_backtrace();
emulator().dump_backtrace();
TODO();
}
if (is_malloc_block()) {
if (auto* tracer = Emulator::the().malloc_tracer())
if (auto* tracer = emulator().malloc_tracer())
tracer->audit_write(*this, base() + offset, 8);
}

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "Region.h"
#include "Emulator.h"
namespace UserspaceEmulator {
Region::Region(u32 base, u32 size)
: m_emulator(Emulator::the())
, m_base(base)
, m_size(size)
{
}
}

View File

@ -31,6 +31,8 @@
namespace UserspaceEmulator {
class Emulator;
class Region {
public:
virtual ~Region() { }
@ -72,14 +74,15 @@ public:
virtual u8* data() = 0;
virtual u8* shadow_data() = 0;
Emulator& emulator() { return m_emulator; }
const Emulator& emulator() const { return m_emulator; }
protected:
Region(u32 base, u32 size)
: m_base(base)
, m_size(size)
{
}
Region(u32 base, u32 size);
private:
Emulator& m_emulator;
u32 m_base { 0 };
u32 m_size { 0 };

View File

@ -34,6 +34,11 @@
namespace UserspaceEmulator {
SoftMMU::SoftMMU(Emulator& emulator)
: m_emulator(emulator)
{
}
Region* SoftMMU::find_region(X86::LogicalAddress address)
{
if (address.selector() == 0x28)
@ -82,13 +87,13 @@ ValueWithShadow<u8> SoftMMU::read8(X86::LogicalAddress address)
auto* region = find_region(address);
if (!region) {
reportln("SoftMMU::read8: No region for @ {:p}", address.offset());
Emulator::the().dump_backtrace();
m_emulator.dump_backtrace();
TODO();
}
if (!region->is_readable()) {
reportln("SoftMMU::read8: Non-readable region @ {:p}", address.offset());
Emulator::the().dump_backtrace();
m_emulator.dump_backtrace();
TODO();
}
@ -100,13 +105,13 @@ ValueWithShadow<u16> SoftMMU::read16(X86::LogicalAddress address)
auto* region = find_region(address);
if (!region) {
reportln("SoftMMU::read16: No region for @ {:p}", address.offset());
Emulator::the().dump_backtrace();
m_emulator.dump_backtrace();
TODO();
}
if (!region->is_readable()) {
reportln("SoftMMU::read16: Non-readable region @ {:p}", address.offset());
Emulator::the().dump_backtrace();
m_emulator.dump_backtrace();
TODO();
}
@ -118,13 +123,13 @@ ValueWithShadow<u32> SoftMMU::read32(X86::LogicalAddress address)
auto* region = find_region(address);
if (!region) {
reportln("SoftMMU::read32: No region for @ {:p}", address.offset());
Emulator::the().dump_backtrace();
m_emulator.dump_backtrace();
TODO();
}
if (!region->is_readable()) {
reportln("SoftMMU::read32: Non-readable region @ {:p}", address.offset());
Emulator::the().dump_backtrace();
m_emulator.dump_backtrace();
TODO();
}
@ -136,13 +141,13 @@ ValueWithShadow<u64> SoftMMU::read64(X86::LogicalAddress address)
auto* region = find_region(address);
if (!region) {
reportln("SoftMMU::read64: No region for @ {:p}", address.offset());
Emulator::the().dump_backtrace();
m_emulator.dump_backtrace();
TODO();
}
if (!region->is_readable()) {
reportln("SoftMMU::read64: Non-readable region @ {:p}", address.offset());
Emulator::the().dump_backtrace();
m_emulator.dump_backtrace();
TODO();
}
@ -154,13 +159,13 @@ void SoftMMU::write8(X86::LogicalAddress address, ValueWithShadow<u8> value)
auto* region = find_region(address);
if (!region) {
reportln("SoftMMU::write8: No region for @ {:p}", address.offset());
Emulator::the().dump_backtrace();
m_emulator.dump_backtrace();
TODO();
}
if (!region->is_writable()) {
reportln("SoftMMU::write8: Non-writable region @ {:p}", address.offset());
Emulator::the().dump_backtrace();
m_emulator.dump_backtrace();
TODO();
}
region->write8(address.offset() - region->base(), value);
@ -171,13 +176,13 @@ void SoftMMU::write16(X86::LogicalAddress address, ValueWithShadow<u16> value)
auto* region = find_region(address);
if (!region) {
reportln("SoftMMU::write16: No region for @ {:p}", address.offset());
Emulator::the().dump_backtrace();
m_emulator.dump_backtrace();
TODO();
}
if (!region->is_writable()) {
reportln("SoftMMU::write16: Non-writable region @ {:p}", address.offset());
Emulator::the().dump_backtrace();
m_emulator.dump_backtrace();
TODO();
}
@ -189,13 +194,13 @@ void SoftMMU::write32(X86::LogicalAddress address, ValueWithShadow<u32> value)
auto* region = find_region(address);
if (!region) {
reportln("SoftMMU::write32: No region for @ {:p}", address.offset());
Emulator::the().dump_backtrace();
m_emulator.dump_backtrace();
TODO();
}
if (!region->is_writable()) {
reportln("SoftMMU::write32: Non-writable region @ {:p}", address.offset());
Emulator::the().dump_backtrace();
m_emulator.dump_backtrace();
TODO();
}
@ -207,13 +212,13 @@ void SoftMMU::write64(X86::LogicalAddress address, ValueWithShadow<u64> value)
auto* region = find_region(address);
if (!region) {
reportln("SoftMMU::write64: No region for @ {:p}", address.offset());
Emulator::the().dump_backtrace();
m_emulator.dump_backtrace();
TODO();
}
if (!region->is_writable()) {
reportln("SoftMMU::write64: Non-writable region @ {:p}", address.offset());
Emulator::the().dump_backtrace();
m_emulator.dump_backtrace();
TODO();
}
@ -257,7 +262,7 @@ bool SoftMMU::fast_fill_memory8(X86::LogicalAddress address, size_t size, ValueW
return false;
if (region->is_mmap() && static_cast<const MmapRegion&>(*region).is_malloc_block()) {
if (auto* tracer = Emulator::the().malloc_tracer()) {
if (auto* tracer = m_emulator.malloc_tracer()) {
// FIXME: Add a way to audit an entire range of memory instead of looping here!
for (size_t i = 0; i < size; ++i) {
tracer->audit_write(*region, address.offset() + (i * sizeof(u8)), sizeof(u8));
@ -282,7 +287,7 @@ bool SoftMMU::fast_fill_memory32(X86::LogicalAddress address, size_t count, Valu
return false;
if (region->is_mmap() && static_cast<const MmapRegion&>(*region).is_malloc_block()) {
if (auto* tracer = Emulator::the().malloc_tracer()) {
if (auto* tracer = m_emulator.malloc_tracer()) {
// FIXME: Add a way to audit an entire range of memory instead of looping here!
for (size_t i = 0; i < count; ++i) {
tracer->audit_write(*region, address.offset() + (i * sizeof(u32)), sizeof(u32));

View File

@ -36,10 +36,13 @@
namespace UserspaceEmulator {
class Emulator;
class SharedBufferRegion;
class SoftMMU {
public:
explicit SoftMMU(Emulator&);
ValueWithShadow<u8> read8(X86::LogicalAddress);
ValueWithShadow<u16> read16(X86::LogicalAddress);
ValueWithShadow<u32> read32(X86::LogicalAddress);
@ -80,6 +83,8 @@ public:
}
private:
Emulator& m_emulator;
Region* m_page_to_region_map[786432];
OwnPtr<Region> m_tls_region;