summaryrefslogtreecommitdiff
path: root/DevTools/UserspaceEmulator
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-07-16 17:14:58 +0200
committerAndreas Kling <kling@serenityos.org>2020-07-16 19:21:45 +0200
commit441918be7e0e3755979ee94312e6a5d23a2953ac (patch)
tree65317ad2213ed5a2cd0c2b373b64e69007fc30bd /DevTools/UserspaceEmulator
parentf6584bfc360a3605b84fcfa343791224925fa415 (diff)
downloadserenity-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.cpp32
-rw-r--r--DevTools/UserspaceEmulator/Emulator.h2
-rw-r--r--DevTools/UserspaceEmulator/MallocTracer.cpp9
-rw-r--r--DevTools/UserspaceEmulator/MallocTracer.h3
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);