1# Debug dwarf unwinding 2 3Dwarf unwinding is the default way of getting call graphs in simpleperf. In this process, 4simpleperf asks the kernel to add stack and register data to each sample. Then it uses 5[libunwindstack](https://cs.android.com/android/platform/superproject/+/master:system/unwinding/libunwindstack/) 6to unwind the call stack. libunwindstack uses dwarf sections (like .debug_frame or .eh_frame) in 7elf files to know how to unwind the stack. 8 9By default, `simpleperf record` unwinds a sample before saving it to disk, to reduce space consumed 10by stack data. But this behavior makes it harder to reproduce unwinding problems. So we added 11debug-unwind command, to help debug and profile dwarf unwinding. Below are two use cases. 12 13[TOC] 14 15## Debug failed unwinding cases 16 17Unwinding a sample can fail for different reasons: not enough stack or register data, unknown 18thread maps, no dwarf info, bugs in code, etc. And to fix them, we need to get error details 19and be able to reproduce them. simpleperf record cmd has two options for this: 20`--keep-failed-unwinding-result` keeps error code for failed unwinding samples. It's lightweight 21and gives us a brief idea why unwinding stops. 22`--keep-failed-unwinding-debug-info` keeps stack and register data for failed unwinding samples. It 23can be used to reproduce the unwinding process given proper elf files. Below is an example. 24 25```sh 26# Run record cmd and keep failed unwinding debug info. 27$ simpleperf64 record --app com.example.android.displayingbitmaps -g --duration 10 \ 28 --keep-failed-unwinding-debug-info 29... 30simpleperf I cmd_record.cpp:762] Samples recorded: 22026. Samples lost: 0. 31 32# Generate a text report containing failed unwinding cases. 33$ simpleperf debug-unwind --generate-report -o report.txt 34 35# Pull report.txt on host and show it using debug_unwind_reporter.py. 36# Show summary. 37$ debug_unwind_reporter.py -i report.txt --summary 38# Show summary of samples failed at a symbol. 39$ debug_unwind_reporter.py -i report.txt --summary --include-end-symbol SocketInputStream_socketRead0 40# Show details of samples failed at a symbol. 41$ debug_unwind_reporter.py -i report.txt --include-end-symbol SocketInputStream_socketRead0 42 43# Reproduce unwinding a failed case. 44$ simpleperf debug-unwind --unwind-sample --sample-time 256666343213301 45 46# Generate a test file containing a failed case and elf files for debugging it. 47$ simpleperf debug-unwind --generate-test-file --sample-time 256666343213301 --keep-binaries-in-test-file \ 48 /apex/com.android.runtime/lib64/bionic/libc.so,/apex/com.android.art/lib64/libopenjdk.so -o test.data 49``` 50 51## Profile unwinding process 52 53We can also record samples without unwinding them. Then we can use debug-unwind cmd to unwind the 54samples after recording. Below is an example. 55 56```sh 57# Record samples without unwinding them. 58$ simpleperf record --app com.example.android.displayingbitmaps -g --duration 10 \ 59 --no-unwind 60... 61simpleperf I cmd_record.cpp:762] Samples recorded: 9923. Samples lost: 0. 62 63# Use debug-unwind cmd to unwind samples. 64$ simpleperf debug-unwind --unwind-sample 65``` 66 67We can profile the unwinding process, get hot functions for improvement. 68 69```sh 70# Profile debug-unwind cmd. 71$ simpleperf record -g -o perf_unwind.data simpleperf debug-unwind --unwind-sample --skip-sample-print 72 73# Then pull perf_unwind.data and report it. 74$ report_html.py -i perf_unwind.data 75 76# We can also add source code annotation in report.html. 77$ binary_cache_builder.py -i perf_unwind.data -lib <path to aosp-master>/out/target/product/<device-name>/symbols/system 78$ report_html.py -i perf_unwind.data --add_source_code --source_dirs <path to aosp-master>/system/ 79``` 80