# Dumping the compiled code from a chrome binary [Rendered](https://chromium.googlesource.com/chromium/src/+/main/docs/disassemble_code.md) ## Background Sometimes you want to look at the disassembled code of a method, e.g. you have a stack trace like ``` 0xd3c90a78(libmonochrome.so -vector.h:1047 ) blink::EventDispatcher::Dispatch() 0xde86db5a 0xd3c8fcdd(libmonochrome.so -event_dispatcher.cc:59 )blink::EventDispatcher::DispatchEvent(blink::Node&, blink::Event*) ``` Where something from `vector.h` has been inlined in `Dispatch()` and so you don't know what line in of `Dispatch()` is actually crashing. Or you want to compare the code before and after a "no-op" change that has resulted in a perf regression or you want to see what methods have been inlined in the final binary (e.g. AFDO can result in more/less inlining, depending what was observed when the AFDO data was collected). This doc tells you how to dump the assembly for a method and how to deal with stack traces involving inlined code. ## Differences for Googlers There are some tasks, like disassembling official release builds of chrome that have Google-specific instructions. You can find them [here](https://goto.google.com/disassemble-chrome-code) ## Building an unstripped binary Below are the ninja arguments for the `rel_ng` trybot but with extra symbols enabled. We can include even more symbols with `symbol_level` of `2` instead of `1` but the binary size is much greater. ``` is_official_build = true dcheck_always_on = true is_component_build = false is_debug = false blink_symbol_level = 1 symbol_level = 1 # Restricted options. May not make sense for non-Googlers. use_goma = true proprietary_codecs = true ffmpeg_branding = "Chrome" ``` This should be close to a release-optimized binary e.g. it applies Automatic Feedback Directed Optimization. You might want to switch to `dcheck_always_on=false`. To build, run ```shell ninja -C out/RelNgSym ``` You probably will want to add some more command line options to this, depending on your usual build parallelism. ## Getting the right objdump You can dump the asm from the binary or `.so` file using `objdump`. You can dump the symbols using `nm`. Both are from GNU binutils. For x86 code, if you are running Linux, you probably have it already. If you are trying to examine Android code, it's likely ARM or MIPS. In that case you can install an alternate binutils package or (maybe better) use the one that ships in Android's SDK. ## Finding the address of the compiled code So, let's say we are looking for `blink::StyleInvalidator::Invalidate`. First we dump out the symbols from the binary. This takes a few seconds. ```shell nm out/RelNgSym/chrome > /tmp/symbols ``` Now we need to get the start and end address of the function. This is a little hacky but we can find the end address by finding the next function (with symbol level `2` we get entries which give an address and length but nm is slower). So now run ```shell grep -A1 "blink::StyleInvalidator::Invalidate(" /tmp/symbols ``` and you should see the something like ``` 000000000769d230 t blink::StyleInvalidator::Invalidate(blink::Element&, blink::StyleInvalidator::SiblingData&) 000000000769ce10 t blink::StyleInvalidator::Invalidate(blink::Document&, blink::Element*) 000000000769d950 t blink::StyleInvalidator::SiblingData::MatchCurrentInvalidationSets(blink::Element&, blink::StyleInvalidator&) ``` So we have found 2 overloads for this symbol and let's say we want the latter. So the function starts at `0x769ce10` and ends at `0x769d950` (the address of the next symbol). ## Dumping code Using the relevant objdump binary, we can now dump the assembly code with ``` objdump -j .text -D -l -C --start-addr=0x769ce10 --stop-addr=0x769d950 out/RelNgSym/chrome ``` and you get something like ``` out/RelNgSym/chrome: file format elf64-x86-64 Disassembly of section .text: 000000000769ce10 : _ZN5blink16StyleInvalidator10InvalidateERNS_8DocumentEPNS_7ElementE(): ./../../third_party/blink/renderer/core/css/invalidation/style_invalidator.cc:31 769ce10: 55 push %rbp 769ce11: 48 89 e5 mov %rsp,%rbp 769ce14: 41 57 push %r15 769ce16: 41 56 push %r14 769ce18: 41 55 push %r13 769ce1a: 41 54 push %r12 769ce1c: 53 push %rbx 769ce1d: 48 81 ec 28 01 00 00 sub $0x128,%rsp 769ce24: 49 89 d4 mov %rdx,%r12 769ce27: 49 89 f7 mov %rsi,%r15 769ce2a: 49 89 fe mov %rdi,%r14 769ce2d: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax 769ce34: 00 00 769ce36: 48 89 45 d0 mov %rax,-0x30(%rbp) InlineBuffer(): ./../../third_party/blink/renderer/platform/wtf/vector.h:864 769ce3a: 4c 8d ad c8 fe ff ff lea -0x138(%rbp),%r13 VectorBufferBase(): ./../../third_party/blink/renderer/platform/wtf/vector.h:465 769ce41: 4c 89 ad b8 fe ff ff mov %r13,-0x148(%rbp) 769ce48: 48 c7 85 c0 fe ff ff movq $0x10,-0x140(%rbp) 769ce4f: 10 00 00 00 SiblingData(): ./../../third_party/blink/renderer/core/css/invalidation/style_invalidator.h:87 769ce53: c7 45 c8 00 00 00 00 movl $0x0,-0x38(%rbp) GetFlag(): ./../../third_party/blink/renderer/core/dom/node.h:909 769ce5a: 8b 46 10 mov 0x10(%rsi),%eax 769ce5d: 66 85 c0 test %ax,%ax _ZN5blink16StyleInvalidator10InvalidateERNS_8DocumentEPNS_7ElementE(): ./../../third_party/blink/renderer/core/css/invalidation/style_invalidator.cc:34 769ce60: 0f 88 28 01 00 00 js 769cf8e ./../../third_party/blink/renderer/core/css/invalidation/style_invalidator.cc:41 769ce66: 4d 85 e4 test %r12,%r12 769ce69: 0f 84 85 00 00 00 je 769cef4 769ce6f: 48 8d 95 b8 fe ff ff lea -0x148(%rbp),%rdx ./../../third_party/blink/renderer/core/css/invalidation/style_invalidator.cc:42 769ce76: 4c 89 f7 mov %r14,%rdi 769ce79: 4c 89 e6 mov %r12,%rsi 769ce7c: e8 af 03 00 00 callq 769d230 IsEmpty(): ./../../third_party/blink/renderer/platform/wtf/vector.h:1039 769ce81: 83 bd c4 fe ff ff 00 cmpl $0x0,-0x13c(%rbp) _ZN5blink16StyleInvalidator10InvalidateERNS_8DocumentEPNS_7ElementE(): ./../../third_party/blink/renderer/core/css/invalidation/style_invalidator.cc:43 769ce88: 74 56 je 769cee0 769ce8a: 4c 89 e3 mov %r12,%rbx 769ce8d: 0f 1f 00 nopl (%rax) 769ce90: 48 8b 5b 30 mov 0x30(%rbx),%rbx NextSibling(): ./../../third_party/blink/renderer/core/dom/element_traversal.h:530 (discriminator 2) 769ce94: 48 85 db test %rbx,%rbx 769ce97: 74 47 je 769cee0 ... ``` ## Further reading https://chromium.googlesource.com/chromium/src/+/main/docs/linux/minidump_to_core.md#Source-debugging https://www.chromium.org/developers/how-tos/debugging-on-windows