diff options
author | Andreas Kling <kling@serenityos.org> | 2020-07-16 17:14:58 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-07-16 19:21:45 +0200 |
commit | 441918be7e0e3755979ee94312e6a5d23a2953ac (patch) | |
tree | 65317ad2213ed5a2cd0c2b373b64e69007fc30bd /DevTools/UserspaceEmulator | |
parent | f6584bfc360a3605b84fcfa343791224925fa415 (diff) | |
download | serenity-441918be7e0e3755979ee94312e6a5d23a2953ac.zip |
UserspaceEmulator: Capture backtraces of malloc/free events
This lets us show backtraces for each leaked mallocation in the leak
report at the end. :^)
Diffstat (limited to 'DevTools/UserspaceEmulator')
-rw-r--r-- | DevTools/UserspaceEmulator/Emulator.cpp | 32 | ||||
-rw-r--r-- | DevTools/UserspaceEmulator/Emulator.h | 2 | ||||
-rw-r--r-- | DevTools/UserspaceEmulator/MallocTracer.cpp | 9 | ||||
-rw-r--r-- | DevTools/UserspaceEmulator/MallocTracer.h | 3 |
4 files changed, 32 insertions, 14 deletions
diff --git a/DevTools/UserspaceEmulator/Emulator.cpp b/DevTools/UserspaceEmulator/Emulator.cpp index 7d1c07ce76..875b78340b 100644 --- a/DevTools/UserspaceEmulator/Emulator.cpp +++ b/DevTools/UserspaceEmulator/Emulator.cpp @@ -188,24 +188,34 @@ bool Emulator::is_in_malloc_or_free() const static pid_t s_pid = getpid(); -void Emulator::dump_backtrace() +Vector<FlatPtr> Emulator::raw_backtrace() { - u32 offset = 0; - String symbol = m_elf->symbolicate(m_cpu.eip(), &offset); - - dbgprintf("==%d== %#08x %s +%#x\n", s_pid, m_cpu.eip(), symbol.characters(), offset); + Vector<FlatPtr> backtrace; + backtrace.append(m_cpu.eip()); u32 frame_ptr = m_cpu.ebp(); while (frame_ptr) { u32 ret_ptr = m_mmu.read32({ 0x20, frame_ptr + 4 }); if (!ret_ptr) - return; - symbol = m_elf->symbolicate(ret_ptr, &offset); - if (!symbol.is_null()) - dbgprintf("==%d== %#08x %s +%#x\n", s_pid, ret_ptr, symbol.characters(), offset); - + break; + backtrace.append(ret_ptr); frame_ptr = m_mmu.read32({ 0x20, frame_ptr }); } + return backtrace; +} + +void Emulator::dump_backtrace(const Vector<FlatPtr>& backtrace) +{ + for (auto& address : backtrace) { + u32 offset = 0; + String symbol = m_elf->symbolicate(address, &offset); + dbgprintf("==%d== %#08x %s +%#x\n", s_pid, m_cpu.eip(), symbol.characters(), offset); + } +} + +void Emulator::dump_backtrace() +{ + dump_backtrace(raw_backtrace()); } u32 Emulator::virt_syscall(u32 function, u32 arg1, u32 arg2, u32 arg3) @@ -306,7 +316,7 @@ u32 Emulator::virt_syscall(u32 function, u32 arg1, u32 arg2, u32 arg3) case SC_clock_gettime: return virt$clock_gettime(arg1, arg2); case SC_getrandom: - return virt$getrandom(arg1, arg2, arg3) ; + return virt$getrandom(arg1, arg2, arg3); default: warn() << "Unimplemented syscall: " << Syscall::to_string((Syscall::Function)function); diff --git a/DevTools/UserspaceEmulator/Emulator.h b/DevTools/UserspaceEmulator/Emulator.h index cd15c61400..78db94b0b3 100644 --- a/DevTools/UserspaceEmulator/Emulator.h +++ b/DevTools/UserspaceEmulator/Emulator.h @@ -46,6 +46,8 @@ public: bool load_elf(); void dump_backtrace(); + void dump_backtrace(const Vector<FlatPtr>&); + Vector<FlatPtr> raw_backtrace(); int exec(); u32 virt_syscall(u32 function, u32 arg1, u32 arg2, u32 arg3); diff --git a/DevTools/UserspaceEmulator/MallocTracer.cpp b/DevTools/UserspaceEmulator/MallocTracer.cpp index 4204fbdf40..426d4b89b5 100644 --- a/DevTools/UserspaceEmulator/MallocTracer.cpp +++ b/DevTools/UserspaceEmulator/MallocTracer.cpp @@ -45,7 +45,7 @@ void MallocTracer::target_did_malloc(Badge<SoftCPU>, FlatPtr address, size_t siz existing_mallocation->freed = false; return; } - m_mallocations.append({ address, size }); + m_mallocations.append({ address, size, false, Emulator::the().raw_backtrace(), Vector<FlatPtr>() }); } void MallocTracer::target_did_free(Badge<SoftCPU>, FlatPtr address) @@ -60,8 +60,10 @@ void MallocTracer::target_did_free(Badge<SoftCPU>, FlatPtr address) dbgprintf("==%d== \033[31;1mDouble free()\033[0m, %p\n", s_pid, address); dbgprintf("==%d== Address %p has already been passed to free()\n", s_pid, address); Emulator::the().dump_backtrace(); + } else { + mallocation.freed = true; + mallocation.free_backtrace = Emulator::the().raw_backtrace(); } - mallocation.freed = true; return; } } @@ -179,9 +181,10 @@ void MallocTracer::dump_leak_report() ++leaks_found; dbgprintf("\n"); dbgprintf("==%d== \033[31;1mLeak\033[0m, %zu-byte allocation at address %p\n", s_pid, mallocation.size, mallocation.address); + Emulator::the().dump_backtrace(mallocation.malloc_backtrace); } - dbgprintf("==%d== %zu leak(s) found\n", s_pid, leaks_found); + dbgprintf("==%d== \033[%d;1m%zu leak(s) found\033[0m\n", s_pid, leaks_found ? 31 : 32, leaks_found); } } diff --git a/DevTools/UserspaceEmulator/MallocTracer.h b/DevTools/UserspaceEmulator/MallocTracer.h index 6e28d5c882..b38b3aff3b 100644 --- a/DevTools/UserspaceEmulator/MallocTracer.h +++ b/DevTools/UserspaceEmulator/MallocTracer.h @@ -56,6 +56,9 @@ private: FlatPtr address { 0 }; size_t size { 0 }; bool freed { false }; + + Vector<FlatPtr> malloc_backtrace; + Vector<FlatPtr> free_backtrace; }; Mallocation* find_mallocation(FlatPtr); |