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