mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 19:57:35 +00:00
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:
parent
a0e25b2d31
commit
c4dd77a170
4 changed files with 41 additions and 1 deletions
|
@ -87,6 +87,34 @@ void MallocTracer::target_did_free(Badge<SoftCPU>, FlatPtr address)
|
||||||
Emulator::the().dump_backtrace();
|
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)
|
MallocTracer::Mallocation* MallocTracer::find_mallocation(FlatPtr address)
|
||||||
{
|
{
|
||||||
for (auto& mallocation : m_mallocations) {
|
for (auto& mallocation : m_mallocations) {
|
||||||
|
|
|
@ -40,6 +40,7 @@ public:
|
||||||
|
|
||||||
void target_did_malloc(Badge<SoftCPU>, FlatPtr address, size_t);
|
void target_did_malloc(Badge<SoftCPU>, FlatPtr address, size_t);
|
||||||
void target_did_free(Badge<SoftCPU>, FlatPtr address);
|
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_read(FlatPtr address, size_t);
|
||||||
void audit_write(FlatPtr address, size_t);
|
void audit_write(FlatPtr address, size_t);
|
||||||
|
|
|
@ -111,6 +111,9 @@ void SoftCPU::did_receive_secret_data()
|
||||||
} else if (m_secret_data[0] == 2) {
|
} else if (m_secret_data[0] == 2) {
|
||||||
if (auto* tracer = m_emulator.malloc_tracer())
|
if (auto* tracer = m_emulator.malloc_tracer())
|
||||||
tracer->target_did_free({}, m_secret_data[1]);
|
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 {
|
} else {
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,11 @@ ALWAYS_INLINE static void ue_notify_free(const void* ptr)
|
||||||
send_secret_data_to_userspace_emulator(2, (FlatPtr)ptr, 0);
|
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 LibThread::Lock& malloc_lock()
|
||||||
{
|
{
|
||||||
static u32 lock_storage[sizeof(LibThread::Lock) / sizeof(u32)];
|
static u32 lock_storage[sizeof(LibThread::Lock) / sizeof(u32)];
|
||||||
|
@ -470,8 +475,11 @@ void* realloc(void* ptr, size_t size)
|
||||||
|
|
||||||
LOCKER(malloc_lock());
|
LOCKER(malloc_lock());
|
||||||
auto existing_allocation_size = malloc_size(ptr);
|
auto existing_allocation_size = malloc_size(ptr);
|
||||||
if (size <= existing_allocation_size)
|
|
||||||
|
if (size <= existing_allocation_size) {
|
||||||
|
ue_notify_realloc(ptr, size);
|
||||||
return ptr;
|
return ptr;
|
||||||
|
}
|
||||||
auto* new_ptr = malloc(size);
|
auto* new_ptr = malloc(size);
|
||||||
if (new_ptr) {
|
if (new_ptr) {
|
||||||
memcpy(new_ptr, ptr, min(existing_allocation_size, size));
|
memcpy(new_ptr, ptr, min(existing_allocation_size, size));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue