1Malloc Debug 2============ 3 4Malloc debug is a method of debugging native memory problems. It can help 5detect memory corruption, memory leaks, and use after free issues. 6 7This documentation describes how to enable this feature on Android N or later 8versions of the Android OS. 9 10The documentation for malloc debug on older versions of Android is 11[here](README_marshmallow_and_earlier.md). 12 13In order to enable malloc debug, you must be able to set special system 14properties using the setprop command from the shell. This requires the 15ability to run as root on the device. 16 17When malloc debug is enabled, it works by adding a shim layer that replaces 18the normal allocation calls. The replaced calls are: 19 20* `malloc` 21* `free` 22* `calloc` 23* `realloc` 24* `posix_memalign` 25* `memalign` 26* `aligned_alloc` 27* `malloc_usable_size` 28 29On 32 bit systems, these two deprecated functions are also replaced: 30 31* `pvalloc` 32* `valloc` 33 34Any errors detected by the library are reported in the log. 35 36NOTE: There is a small behavioral change beginning in P for realloc. 37Before, a realloc from one size to a smaller size would not update the 38backtrace related to the allocation. Starting in P, every single realloc 39call changes the backtrace for the pointer no matter whether the pointer 40returned has changed or not. 41 42 43Controlling Malloc Debug Behavior 44--------------------------------- 45Malloc debug is controlled by individual options. Each option can be enabled 46individually, or in a group of other options. Every single option can be 47combined with every other option. 48 49Option Descriptions 50------------------- 51### front\_guard[=SIZE\_BYTES] 52Enables a small buffer placed before the allocated data. This is an attempt 53to find memory corruption occuring to a region before the original allocation. 54On first allocation, this front guard is written with a specific pattern (0xaa). 55When the allocation is freed, the guard is checked to verify it has not been 56modified. If any part of the front guard is modified, an error will be reported 57in the log indicating what bytes changed. 58 59If the backtrace option is also enabled, then any error message will include 60the backtrace of the allocation site. 61 62If SIZE\_BYTES is present, it indicates the number of bytes in the guard. 63The default is 32 bytes, the max bytes is 16384. SIZE\_BYTES will be 64padded so that it is a multiple of 8 bytes on 32 bit systems and 16 bytes 65on 64 bit systems to make sure that the allocation returned is aligned 66properly. 67 68This option adds a special header to all allocations that contains the guard 69and information about the original allocation. 70 71Example error: 72 73 04-10 12:00:45.621 7412 7412 E malloc_debug: +++ ALLOCATION 0x12345678 SIZE 100 HAS A CORRUPTED FRONT GUARD 74 04-10 12:00:45.622 7412 7412 E malloc_debug: allocation[-32] = 0x00 (expected 0xaa) 75 04-10 12:00:45.622 7412 7412 E malloc_debug: allocation[-15] = 0x02 (expected 0xaa) 76 77### rear\_guard[=SIZE\_BYTES] 78Enables a small buffer placed after the allocated data. This is an attempt 79to find memory corruption occuring to a region after the original allocation. 80On first allocation, this rear guard is written with a specific pattern (0xbb). 81When the allocation is freed, the guard is checked to verify it has not been 82modified. If any part of the rear guard is modified, an error will be reported 83in the log indicating what bytes changed. 84 85If SIZE\_BYTES is present, it indicates the number of bytes in the guard. 86The default is 32 bytes, the max bytes is 16384. 87 88This option adds a special header to all allocations that contains 89information about the original allocation. 90 91Example error: 92 93 04-10 12:00:45.621 7412 7412 E malloc_debug: +++ ALLOCATION 0x12345678 SIZE 100 HAS A CORRUPTED REAR GUARD 94 04-10 12:00:45.622 7412 7412 E malloc_debug: allocation[130] = 0xbf (expected 0xbb) 95 04-10 12:00:45.622 7412 7412 E malloc_debug: allocation[131] = 0x00 (expected 0xbb) 96 97### guard[=SIZE\_BYTES] 98Enables both a front guard and a rear guard on all allocations. 99 100If SIZE\_BYTES is present, it indicates the number of bytes in both guards. 101The default is 32 bytes, the max bytes is 16384. 102 103### backtrace[=MAX\_FRAMES] 104Enable capturing the backtrace of each allocation site. 105This option will slow down allocations by an order of magnitude. If the 106system runs too slowly with this option enabled, decreasing the maximum number 107of frames captured will speed the allocations up. 108 109Note that any backtrace frames that occur within the malloc backtrace library 110itself are not recorded. 111 112If MAX\_FRAMES is present, it indicates the maximum number of frames to 113capture in a backtrace. The default is 16 frames, the maximumum value 114this can be set to is 256. 115 116Before P, this option adds a special header to all allocations that contains 117the backtrace and information about the original allocation. After that, this 118option will not add a special header. 119 120As of P, this option will also enable dumping backtrace heap data to a 121file when the process receives the signal SIGRTMAX - 17 ( which is 47 on most 122Android devices). The format of this dumped data is the same format as 123that dumped when running am dumpheap -n. The default is to dump this data 124to the file /data/local/tmp/backtrace\_heap.**PID**.txt. This is useful when 125used with native only executables that run for a while since these processes 126are not spawned from a zygote process. 127 128Note that when the signal is received, the heap is not dumped until the next 129malloc/free occurs. 130 131### backtrace\_enable\_on\_signal[=MAX\_FRAMES] 132Enable capturing the backtrace of each allocation site. If the 133backtrace capture is toggled when the process receives the signal 134SIGRTMAX - 19 (which is 45 on most Android devices). When this 135option is used alone, backtrace capture starts out disabled until the signal 136is received. If both this option and the backtrace option are set, then 137backtrace capture is enabled until the signal is received. 138 139If MAX\_FRAMES is present, it indicates the maximum number of frames to 140capture in a backtrace. The default is 16 frames, the maximumum value 141this can be set to is 256. 142 143Before P, this option adds a special header to all allocations that contains 144the backtrace and information about the original allocation. After that, this 145option will not add a special header. 146 147### backtrace\_dump\_on\_exit 148As of P, when the backtrace option has been enabled, this causes the backtrace 149dump heap data to be dumped to a file when the program exits. If the backtrace 150option has not been enabled, this does nothing. The default is to dump this 151to the file named /data/local/tmp/backtrace\_heap.**PID**.exit.txt. 152 153The file location can be changed by setting the backtrace\_dump\_prefix 154option. 155 156### backtrace\_dump\_prefix 157As of P, when the backtrace options has been enabled, this sets the prefix 158used for dumping files when the signal SIGRTMAX - 17 is received or when 159the program exits and backtrace\_dump\_on\_exit is set. 160 161The default is /data/local/tmp/backtrace\_heap. 162 163When this value is changed from the default, then the filename chosen 164on the signal will be backtrace\_dump\_prefix.**PID**.txt. The filename chosen 165when the program exits will be backtrace\_dump\_prefix.**PID**.exit.txt. 166 167### fill\_on\_alloc[=MAX\_FILLED\_BYTES] 168Any allocation routine, other than calloc, will result in the allocation being 169filled with the value 0xeb. When doing a realloc to a larger size, the bytes 170above the original usable size will be set to 0xeb. 171 172If MAX\_FILLED\_BYTES is present, it will only fill up to the specified number 173of bytes in the allocation. The default is to fill the entire allocation. 174 175### fill\_on\_free[=MAX\_FILLED\_BYTES] 176When an allocation is freed, fill it with 0xef. 177 178If MAX\_FILLED\_BYTES is present, it will only fill up to the specified number 179of bytes in the allocation. The default is to fill the entire allocation. 180 181### fill[=MAX\_FILLED\_BYTES] 182This enables both the fill\_on\_alloc option and the fill\_on\_free option. 183 184If MAX\_FILLED\_BYTES is present, it will only fill up to the specified number 185of bytes in the allocation. The default is to fill the entire allocation. 186 187### expand\_alloc[=EXPAND\_BYTES] 188Add an extra amount to allocate for every allocation. 189 190If XX is present, it is the number of bytes to expand the allocation by. 191The default is 16 bytes, the max bytes is 16384. 192 193### free\_track[=ALLOCATION\_COUNT] 194When a pointer is freed, do not free the memory right away, but add it to 195a list of freed allocations. In addition to being added to the list, the 196entire allocation is filled with the value 0xef, and the backtrace at 197the time of the free is recorded. The backtrace recording is completely 198separate from the backtrace option, and happens automatically if this 199option is enabled. By default, a maximum of 16 frames will be recorded, 200but this value can be changed using the free\_track\_backtrace\_num\_frames 201option. It can also be completely disabled by setting the option to zero. 202See the full description of this option below. 203 204When the list is full, an allocation is removed from the list and is 205checked to make sure that none of the contents have been modified since 206being placed on the list. When the program terminates, all of the allocations 207left on the list are verified. 208 209If ALLOCATION\_COUNT is present, it indicates the total number of allocations 210in the list. The default is to record 100 freed allocations, the max 211allocations to record is 16384. 212 213Before P, this option adds a special header to all allocations that contains 214the backtrace and information about the original allocation. After that, this 215option will not add a special header. 216 217Example error: 218 219 04-15 12:00:31.304 7412 7412 E malloc_debug: +++ ALLOCATION 0x12345678 USED AFTER FREE 220 04-15 12:00:31.305 7412 7412 E malloc_debug: allocation[20] = 0xaf (expected 0xef) 221 04-15 12:00:31.305 7412 7412 E malloc_debug: allocation[99] = 0x12 (expected 0xef) 222 04-15 12:00:31.305 7412 7412 E malloc_debug: Backtrace at time of free: 223 04-15 12:00:31.305 7412 7412 E malloc_debug: #00 pc 00029310 /system/lib/libc.so 224 04-15 12:00:31.305 7412 7412 E malloc_debug: #01 pc 00021438 /system/lib/libc.so (newlocale+160) 225 04-15 12:00:31.305 7412 7412 E malloc_debug: #02 pc 000a9e38 /system/lib/libc++.so 226 04-15 12:00:31.305 7412 7412 E malloc_debug: #03 pc 000a28a8 /system/lib/libc++.so 227 228In addition, there is another type of error message that can occur if 229an allocation has a special header applied, and the header is corrupted 230before the verification occurs. This is the error message that will be found 231in the log: 232 233 04-15 12:00:31.604 7412 7412 E malloc_debug: +++ ALLOCATION 0x12345678 HAS CORRUPTED HEADER TAG 0x1cc7dc00 AFTER FREE 234 235### free\_track\_backtrace\_num\_frames[=MAX\_FRAMES] 236This option only has meaning if free\_track is set. It indicates how many 237backtrace frames to capture when an allocation is freed. 238 239If MAX\_FRAMES is present, it indicates the number of frames to capture. 240If the value is set to zero, then no backtrace will be captured when the 241allocation is freed. The default is to record 16 frames, the max number of 242frames to to record is 256. 243 244### leak\_track 245Track all live allocations. When the program terminates, all of the live 246allocations will be dumped to the log. If the backtrace option was enabled, 247then the log will include the backtrace of the leaked allocations. This 248option is not useful when enabled globally because a lot of programs do not 249free everything before the program terminates. 250 251Before P, this option adds a special header to all allocations that contains 252the backtrace and information about the original allocation. After that, this 253option will not add a special header. 254 255Example leak error found in the log: 256 257 04-15 12:35:33.304 7412 7412 E malloc_debug: +++ APP leaked block of size 100 at 0x2be3b0b0 (leak 1 of 2) 258 04-15 12:35:33.304 7412 7412 E malloc_debug: Backtrace at time of allocation: 259 04-15 12:35:33.305 7412 7412 E malloc_debug: #00 pc 00029310 /system/lib/libc.so 260 04-15 12:35:33.305 7412 7412 E malloc_debug: #01 pc 00021438 /system/lib/libc.so (newlocale+160) 261 04-15 12:35:33.305 7412 7412 E malloc_debug: #02 pc 000a9e38 /system/lib/libc++.so 262 04-15 12:35:33.305 7412 7412 E malloc_debug: #03 pc 000a28a8 /system/lib/libc++.so 263 04-15 12:35:33.305 7412 7412 E malloc_debug: +++ APP leaked block of size 24 at 0x7be32380 (leak 2 of 2) 264 04-15 12:35:33.305 7412 7412 E malloc_debug: Backtrace at time of allocation: 265 04-15 12:35:33.305 7412 7412 E malloc_debug: #00 pc 00029310 /system/lib/libc.so 266 04-15 12:35:33.305 7412 7412 E malloc_debug: #01 pc 00021438 /system/lib/libc.so (newlocale+160) 267 04-15 12:35:33.305 7412 7412 E malloc_debug: #02 pc 000a9e38 /system/lib/libc++.so 268 04-15 12:35:33.305 7412 7412 E malloc_debug: #03 pc 000a28a8 /system/lib/libc++.so 269 270### record\_allocs[=TOTAL\_ENTRIES] 271Keep track of every allocation/free made on every thread and dump them 272to a file when the signal SIGRTMAX - 18 (which is 46 on most Android devices) 273is received. 274 275If TOTAL\_ENTRIES is set, then it indicates the total number of 276allocation/free records that can be retained. If the number of records 277reaches the TOTAL\_ENTRIES value, then any further allocations/frees are 278not recorded. The default value is 8,000,000 and the maximum value this 279can be set to is 50,000,000. 280 281Once the signal is received, and the current records are written to the 282file, all current records are deleted. Any allocations/frees occuring while 283the data is being dumped to the file are ignored. 284 285**NOTE**: This option is not available until the O release of Android. 286 287The allocation data is written in a human readable format. Every line begins 288with the THREAD\_ID returned by gettid(), which is the thread that is making 289the allocation/free. If a new thread is created, no special line is added 290to the file. However, when a thread completes, a special entry is added to 291the file indicating this. 292 293The thread complete line is: 294 295**THREAD\_ID**: thread\_done 0x0 296 297Example: 298 299 187: thread_done 0x0 300 301Below is how each type of allocation/free call ends up in the file dump. 302 303pointer = malloc(size) 304 305**THREAD\_ID**: malloc pointer size 306 307Example: 308 309 186: malloc 0xb6038060 20 310 311free(pointer) 312 313**THREAD\_ID**: free pointer 314 315Example: 316 317 186: free 0xb6038060 318 319pointer = calloc(nmemb, size) 320 321**THREAD\_ID**: calloc pointer nmemb size 322 323Example: 324 325 186: calloc 0xb609f080 32 4 326 327new\_pointer = realloc(old\_pointer, size) 328 329**THREAD\_ID**: realloc new\_pointer old\_pointer size 330 331Example: 332 333 186: realloc 0xb609f080 0xb603e9a0 12 334 335pointer = memalign(alignment, size) 336 337**THREAD\_ID**: memalign pointer alignment size 338 339pointer = aligned\_alloc(alignment, size) 340 341**THREAD\_ID**: memalign pointer alignment size 342 343posix\_memalign(&pointer, alignment, size) 344 345**THREAD\_ID**: memalign pointer alignment size 346 347Example: 348 349 186: memalign 0x85423660 16 104 350 351pointer = valloc(size) 352 353**THREAD\_ID**: memalign pointer 4096 size 354 355Example: 356 357 186: memalign 0x85423660 4096 112 358 359pointer = pvalloc(size) 360 361**THREAD\_ID**: memalign pointer 4096 <b>SIZE\_ROUNDED\_UP\_TO\_4096</b> 362 363Example: 364 365 186: memalign 0x85423660 4096 8192 366 367### record\_allocs\_file[=FILE\_NAME] 368This option only has meaning if record\_allocs is set. It indicates the 369file where the recorded allocations will be found. 370 371If FILE\_NAME is set, then it indicates where the record allocation data 372will be placed. 373 374**NOTE**: This option is not available until the O release of Android. 375 376### verify\_pointers 377Track all live allocations to determine if a pointer is used that does not 378exist. This option is a lightweight way to verify that all 379free/malloc\_usable\_size/realloc calls are passed valid pointers. 380 381Example error: 382 383 04-15 12:00:31.304 7412 7412 E malloc_debug: +++ ALLOCATION 0x12345678 UNKNOWN POINTER (free) 384 04-15 12:00:31.305 7412 7412 E malloc_debug: Backtrace at time of failure: 385 04-15 12:00:31.305 7412 7412 E malloc_debug: #00 pc 00029310 /system/lib/libc.so 386 04-15 12:00:31.305 7412 7412 E malloc_debug: #01 pc 00021438 /system/lib/libc.so (newlocale+160) 387 04-15 12:00:31.305 7412 7412 E malloc_debug: #02 pc 000a9e38 /system/lib/libc++.so 388 04-15 12:00:31.305 7412 7412 E malloc_debug: #03 pc 000a28a8 /system/lib/libc++.so 389 390Where the name of the function varies depending on the function that called 391with a bad pointer. Only three functions do this checking: free, 392malloc\_usable\_size, realloc. 393 394**NOTE**: This option is not available until the P release of Android. 395 396Additional Errors 397----------------- 398There are a few other error messages that might appear in the log. 399 400### Use After Free 401 04-15 12:00:31.304 7412 7412 E malloc_debug: +++ ALLOCATION 0x12345678 USED AFTER FREE (free) 402 04-15 12:00:31.305 7412 7412 E malloc_debug: Backtrace of original free: 403 04-15 12:00:31.305 7412 7412 E malloc_debug: #00 pc 00029310 /system/lib/libc.so 404 04-15 12:00:31.305 7412 7412 E malloc_debug: #01 pc 00021438 /system/lib/libc.so (newlocale+160) 405 04-15 12:00:31.305 7412 7412 E malloc_debug: #02 pc 000a9e38 /system/lib/libc++.so 406 04-15 12:00:31.305 7412 7412 E malloc_debug: #03 pc 000a28a8 /system/lib/libc++.so 407 04-15 12:00:31.305 7412 7412 E malloc_debug: Backtrace at time of failure: 408 04-15 12:00:31.305 7412 7412 E malloc_debug: #00 pc 00029310 /system/lib/libc.so 409 04-15 12:00:31.305 7412 7412 E malloc_debug: #01 pc 00021438 /system/lib/libc.so (newlocale+160) 410 04-15 12:00:31.305 7412 7412 E malloc_debug: #02 pc 000a9e38 /system/lib/libc++.so 411 04-15 12:00:31.305 7412 7412 E malloc_debug: #03 pc 000a28a8 /system/lib/libc++.so 412 413This indicates that code is attempting to free an already freed pointer. The 414name in parenthesis indicates that the application called the function 415*free* with the bad pointer. 416 417For example, this message: 418 419 04-15 12:00:31.304 7412 7412 E malloc_debug: +++ ALLOCATION 0x12345678 USED AFTER FREE (realloc) 420 421Would indicate that the application called the *realloc* function 422with an already freed pointer. 423 424### Invalid Tag 425 04-15 12:00:31.304 7412 7412 E malloc_debug: +++ ALLOCATION 0x12345678 HAS INVALID TAG 1ee7d000 (malloc_usable_size) 426 04-15 12:00:31.305 7412 7412 E malloc_debug: Backtrace at time of failure: 427 04-15 12:00:31.305 7412 7412 E malloc_debug: #00 pc 00029310 /system/lib/libc.so 428 04-15 12:00:31.305 7412 7412 E malloc_debug: #01 pc 00021438 /system/lib/libc.so (newlocale+160) 429 04-15 12:00:31.305 7412 7412 E malloc_debug: #02 pc 000a9e38 /system/lib/libc++.so 430 04-15 12:00:31.305 7412 7412 E malloc_debug: #03 pc 000a28a8 /system/lib/libc++.so 431 432This indicates that a function (malloc\_usable\_size) was called with 433a pointer that is either not allocated memory, or that the memory of 434the pointer has been corrupted. 435 436As with the other error message, the function in parenthesis is the 437function that was called with the bad pointer. 438 439Backtrace Heap Dump Format 440========================== 441 442This section describes the format of the backtrace heap dump. This data is 443generated by am dumpheap -n or, as of P, by the signal or on exit. 444 445The data has this header: 446 447 Android Native Heap Dump v1.0 448 449 Total memory: XXXX 450 Allocation records: YYYY 451 Backtrace size: ZZZZ 452 453Total memory is the total of all of the currently live allocations. 454Allocation records is the total number of allocation records. 455Backtrace size is the maximum number of backtrace frames that can be present. 456 457Following this header are two different sections, the first section is the 458allocation records, the second section is the map data. 459 460The allocation record data has this format: 461 462 z ZYGOTE_CHILD_ALLOC sz ALLOCATION_SIZE num NUM_ALLOCATIONS bt FRAMES 463 464ZYGOTE\_CHILD\_ALLOC is either 0 or 1. 0 means this was allocated by the 465zygote process or in a process not spawned from the zygote. 1 means this 466was allocated by an application after it forked off from the zygote process. 467 468ALLOCATION\_SIZE is the size of the allocation. 469NUM\_ALLOCATIONS is the number of allocations that have this size and have the 470same backtrace. 471FRAMES is a list of instruction pointers that represent the backtrace of the 472allocation. 473 474Example: 475 476 z 0 sz 400 num 1 bt 0000a230 0000b500 477 z 1 sz 500 num 3 bt 0000b000 0000c000 478 479The first allocation record was created by the zygote of size 400 only one 480with this backtrace/size and a backtrace of 0xa230, 0xb500. 481The second allocation record was create by an application spawned from the 482zygote of size 500, where there are three of these allocation with the same 483backtrace/size and a backtrace of 0xb000, 0xc000. 484 485The final section is the map data for the process: 486 487 MAPS 488 7fe9181000-7fe91a2000 rw-p 00000000 00:00 0 /system/lib/libc.so 489 . 490 . 491 . 492 END 493 494The map data is simply the output of /proc/PID/maps. This data can be used to 495decode the frames in the backtraces. 496 497There is a tool to visualize this data, development/scripts/native\_heapdump\_viewer.py. 498 499Examples 500======== 501 502### For platform developers 503 504Enable backtrace tracking of all allocation for all processes: 505 506 adb shell stop 507 adb shell setprop libc.debug.malloc.options backtrace 508 adb shell start 509 510Enable backtrace tracking for a specific process (ls): 511 512 adb shell setprop libc.debug.malloc.options backtrace 513 adb shell setprop libc.debug.malloc.program ls 514 adb shell ls 515 516Enable backtrace tracking for the zygote and zygote based processes: 517 518 adb shell stop 519 adb shell setprop libc.debug.malloc.program app_process 520 adb shell setprop libc.debug.malloc.options backtrace 521 adb shell start 522 523Enable multiple options (backtrace and guard): 524 525 adb shell stop 526 adb shell setprop libc.debug.malloc.options "\"backtrace guard\"" 527 adb shell start 528 529Note: The two levels of quoting in the adb shell command is necessary. 530The outer layer of quoting is for the shell on the host, to ensure that the 531inner layer of quoting is sent to the device, to make 'backtrace guard' 532a single argument. 533 534Enable malloc debug using an environment variable (pre-O Android release): 535 536 adb shell 537 # setprop libc.debug.malloc.env_enabled 1 538 # setprop libc.debug.malloc.options backtrace 539 # export LIBC_DEBUG_MALLOC_ENABLE=1 540 # ls 541 542Enable malloc debug using an environment variable (Android O or later): 543 544 adb shell 545 # export LIBC_DEBUG_MALLOC_OPTIONS=backtrace 546 # ls 547 548Any process spawned from this shell will run with malloc debug enabled 549using the backtrace option. 550 551 adb shell stop 552 adb shell setprop libc.debug.malloc.options backtrace 553 adb shell start 554 adb shell am dumpheap -n <PID_TO_DUMP> /data/local/tmp/heap.txt 555 556It is possible to use the backtrace\_enable\_on\_signal option as well, 557but, obviously, it must be enabled through the signal before the file will 558contain any data. 559 560### For app developers 561 562Enable malloc debug for a specific program/application (Android O or later): 563 564 adb shell setprop wrap.<APP> '"LIBC_DEBUG_MALLOC_OPTIONS=backtrace logwrapper"' 565 566For example, to enable malloc debug for the google search box (Android O or later): 567 568 adb shell setprop wrap.com.google.android.googlequicksearchbox '"LIBC_DEBUG_MALLOC_OPTIONS=backtrace logwrapper"' 569 adb shell am force-stop com.google.android.googlequicksearchbox 570 571NOTE: On pre-O versions of the Android OS, property names had a length limit 572of 32. This meant that to create a wrap property with the name of the app, it 573was necessary to truncate the name to fit. On O, property names can be 574an order of magnitude larger, so there should be no need to truncate the name 575at all. 576 577To detect leaks while an app is running: 578 579 adb shell dumpsys meminfo --unreachable <PID_OF_APP> 580 581Without also enabling malloc debug, this command will only tell 582you whether it can detect leaked memory, not where those leaks are 583occurring. If you enable malloc debug with the backtrace option for your 584app before running the dumpsys command, you'll get backtraces showing 585where the memory was allocated. 586 587For backtraces from your app to be useful, you'll want to keep the 588symbols in your app's shared libraries rather than stripping them. That 589way you'll see the location of the leak directly without having to use 590something like the <code>ndk-stack</code> tool. 591 592### Analyzing heap dumps 593 594To analyze the data produced by the dumpheap command, run this script: 595 596 development/scripts/native_heapdump_viewer.py 597 598In order for the script to properly symbolize the stacks in the file, 599make sure the script is executed from the tree that built the image. 600 601To collect, transfer, and analyze a dump: 602 603 adb shell am dumpheap -n <PID_TO_DUMP> /data/local/tmp/heap.txt 604 adb shell pull /data/local/tmp/heap.txt . 605 python development/scripts/native_heapdump_viewer.py --symbols /some/path/to/symbols/ heap.txt > heap_info.txt 606 607At the moment, the script will look for symbols in the given directory, 608using the path the .so file would have on the device. So if your .so file 609is at `/data/app/.../lib/arm/libx.so` on the device, it will need to be at 610`/some/path/to/symbols/data/app/.../lib/arm/libx.so` locally given the 611command line above. That is: you need to mirror the directory structure 612for the app in the symbols directory. 613