1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
docs / disassemble_code.md [blame]
# 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_remoteexec = 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 <blink::StyleInvalidator::Invalidate(blink::Document&, blink::Element*)>:
_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 <blink::StyleInvalidator::Invalidate(blink::Document&, blink::Element*)+0x17e>
./../../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 <blink::StyleInvalidator::Invalidate(blink::Document&, blink::Element*)+0xe4>
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 <blink::StyleInvalidator::Invalidate(blink::Element&, blink::StyleInvalidator::SiblingData&)>
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 <blink::StyleInvalidator::Invalidate(blink::Document&, blink::Element*)+0xd0>
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 <blink::StyleInvalidator::Invalidate(blink::Document&, blink::Element*)+0xd0>
...
```
## 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