Fergal Daly | 21879c06 | 2018-10-16 07:30:31 | [diff] [blame] | 1 | # Dumping the compiled code from a chrome binary |
| 2 | |
John Palmer | 046f987 | 2021-05-24 01:24:56 | [diff] [blame] | 3 | [Rendered](https://chromium.googlesource.com/chromium/src/+/main/docs/disassemble_code.md) |
Fergal Daly | ff6d4d58 | 2019-08-28 22:21:20 | [diff] [blame] | 4 | |
Fergal Daly | 21879c06 | 2018-10-16 07:30:31 | [diff] [blame] | 5 | ## Background |
| 6 | |
| 7 | Sometimes you want to look at the disassembled code of a method, |
| 8 | e.g. you have a stack trace like |
| 9 | |
| 10 | ``` |
| 11 | 0xd3c90a78(libmonochrome.so -vector.h:1047 ) blink::EventDispatcher::Dispatch() |
| 12 | 0xde86db5a |
| 13 | 0xd3c8fcdd(libmonochrome.so -event_dispatcher.cc:59 )blink::EventDispatcher::DispatchEvent(blink::Node&, blink::Event*) |
| 14 | ``` |
| 15 | |
| 16 | Where something from `vector.h` has been inlined in `Dispatch()` |
| 17 | and so you don't know what line in of `Dispatch()` is actually crashing. |
| 18 | Or you want to compare the code before and after a "no-op" change |
| 19 | that has resulted in a perf regression |
| 20 | or you want to see what methods have been inlined in the final binary |
| 21 | (e.g. AFDO can result in more/less inlining, |
| 22 | depending what was observed when the AFDO data was collected). |
| 23 | |
| 24 | This doc tells you how to dump the assembly for a method |
| 25 | and how to deal with stack traces involving inlined code. |
| 26 | |
| 27 | ## Differences for Googlers |
| 28 | |
| 29 | There are some tasks, |
| 30 | like disassembling official release builds of chrome |
| 31 | that have Google-specific instructions. |
| 32 | You can find them [here](https://goto.google.com/disassemble-chrome-code) |
| 33 | |
| 34 | ## Building an unstripped binary |
| 35 | |
| 36 | Below are the ninja arguments for the `rel_ng` trybot |
| 37 | but with extra symbols enabled. |
| 38 | We can include even more symbols with `symbol_level` of `2` instead of `1` |
| 39 | but the binary size is much greater. |
| 40 | |
| 41 | ``` |
| 42 | is_official_build = true |
| 43 | dcheck_always_on = true |
| 44 | is_component_build = false |
| 45 | is_debug = false |
Fergal Daly | 21879c06 | 2018-10-16 07:30:31 | [diff] [blame] | 46 | blink_symbol_level = 1 |
| 47 | symbol_level = 1 |
| 48 | |
| 49 | # Restricted options. May not make sense for non-Googlers. |
| 50 | use_goma = true |
| 51 | proprietary_codecs = true |
| 52 | ffmpeg_branding = "Chrome" |
| 53 | ``` |
| 54 | |
| 55 | This should be close to a release-optimized binary |
| 56 | e.g. it applies Automatic Feedback Directed Optimization. |
| 57 | You might want to switch to `dcheck_always_on=false`. |
| 58 | |
| 59 | To build, run |
| 60 | |
| 61 | ```shell |
| 62 | ninja -C out/RelNgSym |
| 63 | ``` |
| 64 | |
| 65 | You probably will want to add some more command line options to this, |
| 66 | depending on your usual build paralellism. |
| 67 | |
| 68 | ## Getting the right objdump |
| 69 | |
| 70 | You can dump the asm from the binary or `.so` file using `objdump`. |
| 71 | You can dump the symbols using `nm`. |
| 72 | Both are from GNU binutils. |
| 73 | For x86 code, if you are running Linux, |
| 74 | you probably have it already. |
| 75 | |
| 76 | If you are trying to examine Android code, |
| 77 | it's likely ARM or MIPS. |
| 78 | In that case you can install an alternate binutils package |
| 79 | or (maybe better) use the one that ships in Android's SDK. |
| 80 | |
| 81 | ## Finding the address of the compiled code |
| 82 | |
| 83 | So, let's say we are looking for `blink::StyleInvalidator::Invalidate`. |
| 84 | First we dump out the symbols from the binary. |
| 85 | This takes a few seconds. |
| 86 | |
| 87 | ```shell |
| 88 | nm out/RelNgSym/chrome > /tmp/symbols |
| 89 | ``` |
| 90 | |
| 91 | Now we need to get the start and end address of the function. |
| 92 | This is a little hacky but we can find the end address |
| 93 | by finding the next function |
| 94 | (with symbol level `2` we get entries |
| 95 | which give an address and length |
| 96 | but nm is slower). |
| 97 | So now run |
| 98 | |
| 99 | ```shell |
| 100 | grep -A1 "blink::StyleInvalidator::Invalidate(" /tmp/symbols |
| 101 | ``` |
| 102 | |
| 103 | and you should see the something like |
| 104 | |
| 105 | ``` |
| 106 | 000000000769d230 t blink::StyleInvalidator::Invalidate(blink::Element&, blink::StyleInvalidator::SiblingData&) |
| 107 | 000000000769ce10 t blink::StyleInvalidator::Invalidate(blink::Document&, blink::Element*) |
| 108 | 000000000769d950 t blink::StyleInvalidator::SiblingData::MatchCurrentInvalidationSets(blink::Element&, blink::StyleInvalidator&) |
| 109 | ``` |
| 110 | |
| 111 | So we have found 2 overloads for this symbol |
| 112 | and let's say we want the latter. |
| 113 | So the function starts at `0x769ce10` |
| 114 | and ends at `0x769d950` |
| 115 | (the address of the next symbol). |
| 116 | |
| 117 | ## Dumping code |
| 118 | |
| 119 | Using the relevant objdump binary, we can now dump the assembly code with |
| 120 | |
| 121 | ``` |
| 122 | objdump -j .text -D -l -C --start-addr=0x769ce10 --stop-addr=0x769d950 out/RelNgSym/chrome |
| 123 | ``` |
| 124 | |
| 125 | and you get something like |
| 126 | |
| 127 | ``` |
| 128 | out/RelNgSym/chrome: file format elf64-x86-64 |
| 129 | |
| 130 | |
| 131 | Disassembly of section .text: |
| 132 | |
| 133 | 000000000769ce10 <blink::StyleInvalidator::Invalidate(blink::Document&, blink::Element*)>: |
| 134 | _ZN5blink16StyleInvalidator10InvalidateERNS_8DocumentEPNS_7ElementE(): |
| 135 | ./../../third_party/blink/renderer/core/css/invalidation/style_invalidator.cc:31 |
| 136 | 769ce10: 55 push %rbp |
| 137 | 769ce11: 48 89 e5 mov %rsp,%rbp |
| 138 | 769ce14: 41 57 push %r15 |
| 139 | 769ce16: 41 56 push %r14 |
| 140 | 769ce18: 41 55 push %r13 |
| 141 | 769ce1a: 41 54 push %r12 |
| 142 | 769ce1c: 53 push %rbx |
| 143 | 769ce1d: 48 81 ec 28 01 00 00 sub $0x128,%rsp |
| 144 | 769ce24: 49 89 d4 mov %rdx,%r12 |
| 145 | 769ce27: 49 89 f7 mov %rsi,%r15 |
| 146 | 769ce2a: 49 89 fe mov %rdi,%r14 |
| 147 | 769ce2d: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax |
| 148 | 769ce34: 00 00 |
| 149 | 769ce36: 48 89 45 d0 mov %rax,-0x30(%rbp) |
| 150 | InlineBuffer(): |
| 151 | ./../../third_party/blink/renderer/platform/wtf/vector.h:864 |
| 152 | 769ce3a: 4c 8d ad c8 fe ff ff lea -0x138(%rbp),%r13 |
| 153 | VectorBufferBase(): |
| 154 | ./../../third_party/blink/renderer/platform/wtf/vector.h:465 |
| 155 | 769ce41: 4c 89 ad b8 fe ff ff mov %r13,-0x148(%rbp) |
| 156 | 769ce48: 48 c7 85 c0 fe ff ff movq $0x10,-0x140(%rbp) |
| 157 | 769ce4f: 10 00 00 00 |
| 158 | SiblingData(): |
| 159 | ./../../third_party/blink/renderer/core/css/invalidation/style_invalidator.h:87 |
| 160 | 769ce53: c7 45 c8 00 00 00 00 movl $0x0,-0x38(%rbp) |
| 161 | GetFlag(): |
| 162 | ./../../third_party/blink/renderer/core/dom/node.h:909 |
| 163 | 769ce5a: 8b 46 10 mov 0x10(%rsi),%eax |
| 164 | 769ce5d: 66 85 c0 test %ax,%ax |
| 165 | _ZN5blink16StyleInvalidator10InvalidateERNS_8DocumentEPNS_7ElementE(): |
| 166 | ./../../third_party/blink/renderer/core/css/invalidation/style_invalidator.cc:34 |
| 167 | 769ce60: 0f 88 28 01 00 00 js 769cf8e <blink::StyleInvalidator::Invalidate(blink::Document&, blink::Element*)+0x17e> |
| 168 | ./../../third_party/blink/renderer/core/css/invalidation/style_invalidator.cc:41 |
| 169 | 769ce66: 4d 85 e4 test %r12,%r12 |
| 170 | 769ce69: 0f 84 85 00 00 00 je 769cef4 <blink::StyleInvalidator::Invalidate(blink::Document&, blink::Element*)+0xe4> |
| 171 | 769ce6f: 48 8d 95 b8 fe ff ff lea -0x148(%rbp),%rdx |
| 172 | ./../../third_party/blink/renderer/core/css/invalidation/style_invalidator.cc:42 |
| 173 | 769ce76: 4c 89 f7 mov %r14,%rdi |
| 174 | 769ce79: 4c 89 e6 mov %r12,%rsi |
| 175 | 769ce7c: e8 af 03 00 00 callq 769d230 <blink::StyleInvalidator::Invalidate(blink::Element&, blink::StyleInvalidator::SiblingData&)> |
| 176 | IsEmpty(): |
| 177 | ./../../third_party/blink/renderer/platform/wtf/vector.h:1039 |
| 178 | 769ce81: 83 bd c4 fe ff ff 00 cmpl $0x0,-0x13c(%rbp) |
| 179 | _ZN5blink16StyleInvalidator10InvalidateERNS_8DocumentEPNS_7ElementE(): |
| 180 | ./../../third_party/blink/renderer/core/css/invalidation/style_invalidator.cc:43 |
| 181 | 769ce88: 74 56 je 769cee0 <blink::StyleInvalidator::Invalidate(blink::Document&, blink::Element*)+0xd0> |
| 182 | 769ce8a: 4c 89 e3 mov %r12,%rbx |
| 183 | 769ce8d: 0f 1f 00 nopl (%rax) |
| 184 | 769ce90: 48 8b 5b 30 mov 0x30(%rbx),%rbx |
| 185 | NextSibling(): |
| 186 | ./../../third_party/blink/renderer/core/dom/element_traversal.h:530 (discriminator 2) |
| 187 | 769ce94: 48 85 db test %rbx,%rbx |
| 188 | 769ce97: 74 47 je 769cee0 <blink::StyleInvalidator::Invalidate(blink::Document&, blink::Element*)+0xd0> |
| 189 | |
| 190 | ... |
| 191 | ``` |
| 192 | |
| 193 | |
| 194 | ## Further reading |
| 195 | |
John Palmer | 046f987 | 2021-05-24 01:24:56 | [diff] [blame] | 196 | https://chromium.googlesource.com/chromium/src/+/main/docs/linux/minidump_to_core.md#Source-debugging |
Fergal Daly | 21879c06 | 2018-10-16 07:30:31 | [diff] [blame] | 197 | |
| 198 | https://www.chromium.org/developers/how-tos/debugging-on-windows |