diff --git a/DevTools/UserspaceEmulator/MallocTracer.cpp b/DevTools/UserspaceEmulator/MallocTracer.cpp index 48cff29c37..6f88d9a446 100644 --- a/DevTools/UserspaceEmulator/MallocTracer.cpp +++ b/DevTools/UserspaceEmulator/MallocTracer.cpp @@ -87,6 +87,34 @@ void MallocTracer::target_did_free(Badge, FlatPtr address) Emulator::the().dump_backtrace(); } +void MallocTracer::target_did_realloc(Badge, 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(*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) { diff --git a/DevTools/UserspaceEmulator/MallocTracer.h b/DevTools/UserspaceEmulator/MallocTracer.h index a38f93823f..fb7f99a307 100644 --- a/DevTools/UserspaceEmulator/MallocTracer.h +++ b/DevTools/UserspaceEmulator/MallocTracer.h @@ -40,6 +40,7 @@ public: void target_did_malloc(Badge, FlatPtr address, size_t); void target_did_free(Badge, FlatPtr address); + void target_did_realloc(Badge, FlatPtr address, size_t); void audit_read(FlatPtr address, size_t); void audit_write(FlatPtr address, size_t); diff --git a/DevTools/UserspaceEmulator/SoftCPU.cpp b/DevTools/UserspaceEmulator/SoftCPU.cpp index 2c5bb3fdce..7ffbebee88 100644 --- a/DevTools/UserspaceEmulator/SoftCPU.cpp +++ b/DevTools/UserspaceEmulator/SoftCPU.cpp @@ -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(); } diff --git a/Libraries/LibC/malloc.cpp b/Libraries/LibC/malloc.cpp index 63bd2cde1d..cdf3295d9f 100644 --- a/Libraries/LibC/malloc.cpp +++ b/Libraries/LibC/malloc.cpp @@ -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));