UserspaceEmulator+LibC: Have UE notice realloc() and update accounting

When a mallocation is shrunk/grown without moving, UE needs to update
its precise metadata about the mallocation, since it tracks *exactly*
how many bytes were allocated, not just the malloc chunk size.
This commit is contained in:
Andreas Kling 2020-11-08 10:10:41 +01:00
parent a0e25b2d31
commit c4dd77a170
Notes: sideshowbarker 2024-07-19 01:30:53 +09:00
4 changed files with 41 additions and 1 deletions

View file

@ -87,6 +87,34 @@ void MallocTracer::target_did_free(Badge<SoftCPU>, FlatPtr address)
Emulator::the().dump_backtrace();
}
void MallocTracer::target_did_realloc(Badge<SoftCPU>, FlatPtr address, size_t size)
{
auto* region = Emulator::the().mmu().find_region({ 0x20, address });
ASSERT(region);
ASSERT(region->is_mmap());
auto& mmap_region = static_cast<MmapRegion&>(*region);
ASSERT(mmap_region.is_malloc_block());
auto* existing_mallocation = find_mallocation(address);
ASSERT(existing_mallocation);
ASSERT(!existing_mallocation->freed);
size_t old_size = existing_mallocation->size;
auto* shadow_bits = mmap_region.shadow_data() + address - mmap_region.base();
if (size > old_size) {
memset(shadow_bits + old_size, 1, size - old_size);
} else {
memset(shadow_bits + size, 1, old_size - size);
}
existing_mallocation->size = size;
// FIXME: Should we track malloc/realloc backtrace separately perhaps?
existing_mallocation->malloc_backtrace = Emulator::the().raw_backtrace();
}
MallocTracer::Mallocation* MallocTracer::find_mallocation(FlatPtr address)
{
for (auto& mallocation : m_mallocations) {

View file

@ -40,6 +40,7 @@ public:
void target_did_malloc(Badge<SoftCPU>, FlatPtr address, size_t);
void target_did_free(Badge<SoftCPU>, FlatPtr address);
void target_did_realloc(Badge<SoftCPU>, FlatPtr address, size_t);
void audit_read(FlatPtr address, size_t);
void audit_write(FlatPtr address, size_t);

View file

@ -111,6 +111,9 @@ void SoftCPU::did_receive_secret_data()
} else if (m_secret_data[0] == 2) {
if (auto* tracer = m_emulator.malloc_tracer())
tracer->target_did_free({}, m_secret_data[1]);
} else if (m_secret_data[0] == 3) {
if (auto* tracer = m_emulator.malloc_tracer())
tracer->target_did_realloc({}, m_secret_data[2], m_secret_data[1]);
} else {
ASSERT_NOT_REACHED();
}

View file

@ -57,6 +57,11 @@ ALWAYS_INLINE static void ue_notify_free(const void* ptr)
send_secret_data_to_userspace_emulator(2, (FlatPtr)ptr, 0);
}
ALWAYS_INLINE static void ue_notify_realloc(const void* ptr, size_t size)
{
send_secret_data_to_userspace_emulator(3, size, (FlatPtr)ptr);
}
static LibThread::Lock& malloc_lock()
{
static u32 lock_storage[sizeof(LibThread::Lock) / sizeof(u32)];
@ -470,8 +475,11 @@ void* realloc(void* ptr, size_t size)
LOCKER(malloc_lock());
auto existing_allocation_size = malloc_size(ptr);
if (size <= existing_allocation_size)
if (size <= existing_allocation_size) {
ue_notify_realloc(ptr, size);
return ptr;
}
auto* new_ptr = malloc(size);
if (new_ptr) {
memcpy(new_ptr, ptr, min(existing_allocation_size, size));