| Christopher Ferris | 713a8e3 | 2016-03-18 14:29:51 -0700 | [diff] [blame] | 1 | Native Memory Tracking using libc Callbacks |
| 2 | ------------------------------------------- |
| 3 | Malloc debug can be used to get information on all of the live allocations |
| 4 | in a process. The libc library in Android exports two calls that can be |
| 5 | used to gather this data from a process. This tracking can be enabled using |
| 6 | either the backtrace option or the backtrace\_enabled\_on\_signal option. |
| 7 | |
| 8 | The function to gather the data: |
| 9 | |
| Christopher Ferris | c7bfe2e | 2016-04-26 16:07:29 -0700 | [diff] [blame] | 10 | `extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overall_size, size_t* info_size, size_t* total_memory, size_t* backtrace_size);` |
| Christopher Ferris | 713a8e3 | 2016-03-18 14:29:51 -0700 | [diff] [blame] | 11 | |
| Christopher Ferris | c7bfe2e | 2016-04-26 16:07:29 -0700 | [diff] [blame] | 12 | *info* is set to a buffer allocated by the call that contains all of |
| Christopher Ferris | 713a8e3 | 2016-03-18 14:29:51 -0700 | [diff] [blame] | 13 | the allocation information. |
| Christopher Ferris | c7bfe2e | 2016-04-26 16:07:29 -0700 | [diff] [blame] | 14 | *overall\_size* is set to the total size of the buffer returned. If this |
| 15 | *info\_size* |
| Christopher Ferris | 713a8e3 | 2016-03-18 14:29:51 -0700 | [diff] [blame] | 16 | value is zero, then there are no allocation being tracked. |
| Christopher Ferris | c7bfe2e | 2016-04-26 16:07:29 -0700 | [diff] [blame] | 17 | *total\_memory* is set to the sum of all allocation sizes that are live at |
| Christopher Ferris | 713a8e3 | 2016-03-18 14:29:51 -0700 | [diff] [blame] | 18 | the point of the function call. This does not include the memory allocated |
| 19 | by the malloc debug library itself. |
| Christopher Ferris | c7bfe2e | 2016-04-26 16:07:29 -0700 | [diff] [blame] | 20 | *backtrace\_size* is set to the maximum number of backtrace entries |
| Christopher Ferris | 713a8e3 | 2016-03-18 14:29:51 -0700 | [diff] [blame] | 21 | that are present for each allocation. |
| 22 | |
| 23 | In order to free the buffer allocated by the function, call: |
| 24 | |
| Christopher Ferris | c7bfe2e | 2016-04-26 16:07:29 -0700 | [diff] [blame] | 25 | `extern "C" void free_malloc_leak_info(uint8_t* info);` |
| Christopher Ferris | 713a8e3 | 2016-03-18 14:29:51 -0700 | [diff] [blame] | 26 | |
| 27 | ### Format of info Buffer |
| Christopher Ferris | c7bfe2e | 2016-04-26 16:07:29 -0700 | [diff] [blame] | 28 | size_t size_of_original_allocation |
| Christopher Ferris | 426b00a | 2017-03-09 13:47:37 -0800 | [diff] [blame] | 29 | size_t num_allocations |
| Christopher Ferris | c7bfe2e | 2016-04-26 16:07:29 -0700 | [diff] [blame] | 30 | uintptr_t pc1 |
| 31 | uintptr_t pc2 |
| 32 | uintptr_t pc3 |
| 33 | . |
| 34 | . |
| 35 | . |
| Christopher Ferris | 713a8e3 | 2016-03-18 14:29:51 -0700 | [diff] [blame] | 36 | |
| Christopher Ferris | c7bfe2e | 2016-04-26 16:07:29 -0700 | [diff] [blame] | 37 | The number of *uintptr\_t* values is determined by the value |
| 38 | *backtrace\_size* as returned by the original call to |
| 39 | *get\_malloc\_leak\_info*. This value is not variable, it is the same |
| Christopher Ferris | 713a8e3 | 2016-03-18 14:29:51 -0700 | [diff] [blame] | 40 | for all the returned data. The value |
| Christopher Ferris | 426b00a | 2017-03-09 13:47:37 -0800 | [diff] [blame] | 41 | *num\_allocations* contains the total number of allocations with the same |
| 42 | backtrace and size as this allocation. On Android Nougat, this value was |
| 43 | incorrectly set to the number of frames in the backtrace. |
| 44 | Each *uintptr\_t* is a pc of the callstack. If the total number |
| 45 | of backtrace entries is less than *backtrace\_size*, the rest of the |
| 46 | entries are zero. |
| Christopher Ferris | 713a8e3 | 2016-03-18 14:29:51 -0700 | [diff] [blame] | 47 | The calls from within the malloc debug library are automatically removed. |
| 48 | |
| Christopher Ferris | c7bfe2e | 2016-04-26 16:07:29 -0700 | [diff] [blame] | 49 | For 32 bit systems, *size\_t* and *uintptr\_t* are both 4 byte values. |
| Christopher Ferris | 713a8e3 | 2016-03-18 14:29:51 -0700 | [diff] [blame] | 50 | |
| Christopher Ferris | c7bfe2e | 2016-04-26 16:07:29 -0700 | [diff] [blame] | 51 | For 64 bit systems, *size\_t* and *uintptr\_t* are both 8 byte values. |
| Christopher Ferris | 713a8e3 | 2016-03-18 14:29:51 -0700 | [diff] [blame] | 52 | |
| Christopher Ferris | c7bfe2e | 2016-04-26 16:07:29 -0700 | [diff] [blame] | 53 | The total number of these structures returned in *info* is |
| 54 | *overall\_size* divided by *info\_size*. |
| Christopher Ferris | 713a8e3 | 2016-03-18 14:29:51 -0700 | [diff] [blame] | 55 | |
| 56 | Note, the size value in each allocation data structure will have bit 31 set |
| Christopher Ferris | ac66d16 | 2016-09-28 14:51:12 -0700 | [diff] [blame] | 57 | if this allocation was created in a process forked from the Zygote process. |
| 58 | This helps to distinguish between native allocations created by the application. |