• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..--

include/memunreachable/22-Nov-2023-8746

tests/22-Nov-2023-1,7831,228

.clang-formatD22-Nov-2023226 1110

Allocator.cppD22-Nov-202312.2 KiB469336

Allocator.hD22-Nov-20236.1 KiB219132

Android.bpD22-Nov-20232.1 KiB10193

Binder.cppD22-Nov-20232.2 KiB8144

Binder.hD22-Nov-2023863 297

HeapWalker.cppD22-Nov-20235.2 KiB180133

HeapWalker.hD22-Nov-20233.9 KiB13388

Leak.hD22-Nov-20231.6 KiB6131

LeakFolding.cppD22-Nov-20234.2 KiB13995

LeakFolding.hD22-Nov-20232.4 KiB10162

LeakPipe.cppD22-Nov-20232.3 KiB9460

LeakPipe.hD22-Nov-20234.7 KiB195136

LineBuffer.cppD22-Nov-20232 KiB6740

LineBuffer.hD22-Nov-20231 KiB4117

LinkedList.hD22-Nov-20231.6 KiB6440

MemUnreachable.cppD22-Nov-202317.5 KiB547391

OWNERSD22-Nov-202337 32

ProcessMappings.cppD22-Nov-20232 KiB7146

ProcessMappings.hD22-Nov-20231.1 KiB4116

PtracerThread.cppD22-Nov-20233.8 KiB156112

PtracerThread.hD22-Nov-20231.5 KiB5626

README.mdD22-Nov-20235.2 KiB7253

ScopedAlarm.hD22-Nov-20231.6 KiB5833

ScopedDisableMalloc.hD22-Nov-20232.8 KiB11065

ScopedPipe.hD22-Nov-20231.8 KiB8148

ScopedSignalHandler.hD22-Nov-20232.4 KiB8247

Semaphore.hD22-Nov-20231.4 KiB6135

Tarjan.hD22-Nov-20233.5 KiB13999

ThreadCapture.cppD22-Nov-20239.6 KiB368278

ThreadCapture.hD22-Nov-20231.5 KiB5930

anon_vma_naming.hD22-Nov-2023846 266

bionic.hD22-Nov-20231.1 KiB3613

log.hD22-Nov-20231.7 KiB5829

README.md

1libmemunreachable
2================
3
4Introduction
5--------------
6libmemunreachable is a zero-overhead native memory leak detector.  It uses an imprecise mark-and-sweep garbage collector pass over all native memory, reporting any unreachable blocks as leaks.  It is similar to the [Heap Checker from tcmalloc](http://htmlpreview.github.io/?https://github.com/gperftools/gperftools/blob/master/doc/heap_checker.html), but with a few key differences to remove the overhead.  Instead of instrumenting every call to malloc and free, it queries the allocator (jemalloc) for active allocations when leak detection is requested.  In addition, it performs a very short stop-the-world data collection on the main process, and then forks a copy of the process to perform the mark-and-sweep, minimizing disruption to the original process.
7
8In the default (zero-overhead) mode, the returned data on leaks is limited to the address, approximate (upper bound) size, and the the first 32 bytes of the contents of the leaked allocation.  If malloc_debug backtraces are enabled they will be included in the leak information, but backtracing allocations requires significant overhead.
9
10----------
11
12Usage
13-------
14
15### C interface ###
16
17#### `bool LogUnreachableMemory(bool log_contents, size_t limit)` ####
18Writes a description of leaked memory to the log.  A summary is always written, followed by details of up to `limit` leaks.  If `log_contents` is `true`, details include up to 32 bytes of the contents of each leaked allocation.
19Returns true if leak detection succeeded.
20
21#### `bool NoLeaks()` ####
22Returns `true` if no unreachable memory was found.
23
24### C++ interface ###
25
26####`bool GetUnreachableMemory(UnreachableMemoryInfo& info, size_t limit = 100)`####
27Updates an `UnreachableMemoryInfo` object with information on leaks, including details on up to `limit` leaks.  Returns true if leak detection succeeded.
28
29#### `std::string GetUnreachableMemoryString(bool log_contents = false, size_t limit = 100)` ####
30Returns a description of leaked memory.  A summary is always written, followed by details of up to `limit` leaks.  If `log_contents` is `true`, details include up to 32 bytes of the contents of each leaked allocation.
31Returns true if leak detection succeeded.
32
33Implementation
34-------------------
35The sequence of steps required to perform a leak detection pass is divided into three processes - the original process, the collection process, and the sweeper process.
36
37 1. *Original process*: Leak detection is requested by calling `GetUnreachableMemory()`
38 2. Allocations are disabled using `malloc_disable()`
39 3. The collection process is spawned.  The collection process, created using clone, is similar to a normal `fork()` child process, except that it shares the address space of the parent - any writes by the original process are visible to the collection process, and vice-versa. If we forked instead of using clone, the address space might get out of sync with observed post-ptrace thread state, since it takes some time to pause the parent.
40 4. *Collection process*: All threads in the original process are paused with `ptrace()`.
41 5. Registers contents, active stack areas, and memory mapping information are collected.
42 6. *Original process*: Allocations are re-enabled using `malloc_enable()`, but all threads are still paused with `ptrace()`.
43 7. *Collection process*: The sweeper process is spawned using a normal `fork()`.  The sweeper process has a copy of all memory from the original process, including all the data collected by the collection process.
44 8. Collection process releases all threads from `ptrace` and exits
45 9. *Original process*: All threads continue, the thread that called `GetUnreachableMemory()` blocks waiting for leak data over a pipe.
46 10. *Sweeper process*: A list of all active allocations is produced by examining the memory mappings and calling `malloc_iterate()` on any heap mappings.
47 11. A list of all roots is produced from globals (.data and .bss sections of binaries), and registers and stacks from each thread.
48 12. The mark-and-sweep pass is performed starting from roots.
49 13. Unmarked allocations are sent over the pipe back to the original process.
50
51----------
52
53
54Components
55---------------
56- `MemUnreachable.cpp`: Entry points, implements the sequencing described above.
57- `PtracerThread.cpp`: Used to clone the collection process with shared address space.
58- `ThreadCapture.cpp`: Pauses threads in the main process and collects register contents.
59- `ProcessMappings.cpp`: Collects snapshots of `/proc/pid/maps`.
60- `HeapWalker.cpp`: Performs the mark-and-sweep pass over active allocations.
61- `LeakPipe.cpp`: transfers data describing leaks from the sweeper process to the original process.
62
63
64Heap allocator requirements
65----------------------------------
66libmemunreachable requires a small interface to the allocator in order to collect information about active allocations.
67
68 - `malloc_disable()`: prevent any thread from mutating internal allocator state.
69 - `malloc enable()`: re-enable allocations in all threads.
70 - `malloc_iterate()`: call a callback on each active allocation in a given heap region.
71 - `malloc_backtrace()`: return the backtrace from when the allocation at the given address was allocated, if it was collected.
72