dwarf4.h
Go to the documentation of this file.
1 //
2 // Bareflank Unwind Library
3 //
4 // Copyright (C) 2015 Assured Information Security, Inc.
5 // Author: Rian Quinn <quinnr@ainfosec.com>
6 // Author: Brendan Kerrigan <kerriganb@ainfosec.com>
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 2.1 of the License, or (at your option) any later version.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
17 //
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 
22 #ifndef DWARF4_H
23 #define DWARF4_H
24 
25 #include <stdint.h>
26 #include <eh_frame.h>
27 #include <registers_intel_x64.h>
28 
29 #define MAX_ROWS 17
30 
31 // -----------------------------------------------------------------------------
32 // Overview
33 // -----------------------------------------------------------------------------
34 //
35 // The DWARF specification describes all of the compiled debug information that
36 // GCC and Clang use. For unwinding, we only care about the Call Frame
37 // Information (section 6.4). For this implementation, we used the 4th version
38 // of this specification:
39 //
40 // http://www.dwarfstd.org/doc/DWARF4.pdf
41 //
42 // When compiling, information about each stack frame is stored (usually
43 // referred to as a function call, but it could be more than that), in a
44 // section called .debug_frames and .eh_frames. We only care about the
45 // .eh_frames section for this implementation. Also note that there are
46 // differences, so you need to read both specifications (see eh_frame.h).
47 //
48 // The call frame information might seem complicated but it is pretty simple
49 // (at least for x86_64). Take for example, the following function
50 //
51 // 00410814:
52 // push rbp
53 // mov rbp,rsp
54 // <throw>...
55 // pop rbp
56 // ret
57 //
58 // This function is really simple (it does nothing). No suppose, the code
59 // threw an exception. The stack has been altered, and needs to be unwound.
60 // We cannot simply unwind all of the instructions because we are part of the
61 // way into the function, and thus can only unwind instructions up the throw
62 // (or if you keep unwinding, from the call instruction of the previous
63 // function, and so on....). The DWARF instructions for this code are as
64 // follows (you can get these by running readelf):
65 //
66 // CIE Part:
67 // DW_CFA_def_cfa: r7 (rsp) ofs 8
68 // DW_CFA_offset: r16 (rip) at cfa-8
69 //
70 // FDE Part:
71 // DW_CFA_advance_loc: 1 to 00410814
72 // DW_CFA_def_cfa_offset: 16
73 // DW_CFA_offset: r6 (rbp) at cfa-16
74 // DW_CFA_advance_loc: 3 to 00410817
75 // DW_CFA_def_cfa_register: r6 (rbp)
76 // <stop>
77 // DW_CFA_advance_loc: 15 to 00410826
78 // DW_CFA_def_cfa: r7 (rsp) ofs 8
79 //
80 // We only care about the instructions up to the stop location, which is
81 // where the throw occurred. The first part of these instructions move an
82 // invisible "cursor" to location: 00410814, which is the initial push
83 // instruction. Here it says that if you want access to the Canonical Frame
84 // Address (cfa), you can find it in register r7 (which is the stack pointer),
85 // with an offset of 8 (prior to the cursor being moved, i.e. the CIE part).
86 // It also says that you can find the return address -8 into the CFA, which
87 // make sense (executing a call instruction places the return address onto
88 // the stack, which means it's the first "thing" on the call frame). Once the
89 // push instruction occurs (i.e. DW_CFA_advance_loc), you are then given an
90 // instruction that says the CFA is now located 16 bytes from r7. This makes
91 // sense because r7 is the stack pointer, and pushing rbp to the stack will
92 // cause the stack pointer to move. The CFA is always located in the same spot,
93 // and thus to calculate the the location of the CFA, you need a new offset.
94 // The next instruction states that rbp can be located -16 from the CFA, which
95 // makes sense because we just pushed it onto the stack. This can later be
96 // used to recover rbp when unwinding. Once that is done, the invisible cursor
97 // is moved to 00410817 stating that the CFA can now be located using RBP.
98 // This is done because RSP is about to be modified a ton, and this will keep
99 // the calculated of CFA simple. The next set of instruction roll back some
100 // of the previous instructions because the code is now cleaning itself up.
101 // In our example, we don't want to use these instructions because our throw,
102 // occurs prior to these cleanup instructions. This is why we care about the
103 // _loc instructions. They tell us when to stop looking for instructions.
104 //
105 // The DWARF specification states that you are building a "table", which you
106 // are. The table would look like this
107 //
108 // --
109 // -----
110 // --------
111 // -----
112 // --
113 //
114 // Each row is the same as the next, with a couple more instructions added,
115 // until you hit cleanup code. This is really useful for a debugger, but for
116 // the unwinder, the only information that we care about is the "current" row.
117 // For this reason, we don't need to follow the "add a row" instructions that
118 // you will see in the spec. We simple keep modifying the existing row. Note
119 // that this implementation does have a couple of limitations that at some
120 // point we might want to address:
121 //
122 // - At the moment we don't have expression support. We have not been able to
123 // reproduce any example that would generate this code, so we have left it
124 // out for now to simplify the implementation. At some point, we might want
125 // to add support for this.
126 //
127 // - Right now we don't support the restore instructions because that requires
128 // the initial row (what's defined in the CIE). The problem is, this would
129 // double the about of stack space we require, and we are pretty limited in
130 // the kernel (on Linux it's only 8k), so for now, we have left it out as
131 // we have not seen these instructions either.
132 //
133 // - We also do not support the state instructions. The way this is usually
134 // implemented is with a malloc/free, which should not be used in an unwinder
135 // because a throw might be due to bad_alloc. For this reason, GCC does
136 // not output these instructions so we should be fine here.
137 //
138 
139 // -----------------------------------------------------------------------------
140 // Call Frame Information (section 6.4.1)
141 // -----------------------------------------------------------------------------
142 
144 {
152 };
153 
154 // -----------------------------------------------------------------------------
155 // Call Frame Information (section 7.23)
156 // -----------------------------------------------------------------------------
157 
158 #define DW_CFA_advance_loc 0x40
159 #define DW_CFA_offset 0x80
160 #define DW_CFA_restore 0xC0
161 #define DW_CFA_nop 0x00
162 #define DW_CFA_set_loc 0x01
163 #define DW_CFA_advance_loc1 0x02
164 #define DW_CFA_advance_loc2 0x03
165 #define DW_CFA_advance_loc4 0x04
166 #define DW_CFA_offset_extended 0x05
167 #define DW_CFA_restore_extended 0x06
168 #define DW_CFA_undefined 0x07
169 #define DW_CFA_same_value 0x08
170 #define DW_CFA_register 0x09
171 #define DW_CFA_remember_state 0x0A
172 #define DW_CFA_restore_state 0x0B
173 #define DW_CFA_def_cfa 0x0C
174 #define DW_CFA_def_cfa_register 0x0D
175 #define DW_CFA_def_cfa_offset 0x0E
176 #define DW_CFA_def_cfa_expression 0x0F
177 #define DW_CFA_expression 0x10
178 #define DW_CFA_offset_extended_sf 0x11
179 #define DW_CFA_def_cfa_sf 0x12
180 #define DW_CFA_def_cfa_offset_sf 0x13
181 #define DW_CFA_val_offset 0x14
182 #define DW_CFA_val_offset_sf 0x15
183 #define DW_CFA_val_expression 0x16
184 
185 #define DW_OP_addr 0x03
186 #define DW_OP_deref 0x06
187 #define DW_OP_const1u 0x08
188 #define DW_OP_const1s 0x09
189 #define DW_OP_const2u 0x0A
190 #define DW_OP_const2s 0x0B
191 #define DW_OP_const4u 0x0C
192 #define DW_OP_const4s 0x0D
193 #define DW_OP_const8u 0x0E
194 #define DW_OP_const8s 0x0F
195 #define DW_OP_constu 0x10
196 #define DW_OP_consts 0x11
197 #define DW_OP_dup 0x12
198 #define DW_OP_drop 0x13
199 #define DW_OP_over 0x14
200 #define DW_OP_pick 0x15
201 #define DW_OP_swap 0x16
202 #define DW_OP_rot 0x17
203 #define DW_OP_xderef 0x18
204 #define DW_OP_abs 0x19
205 #define DW_OP_and 0x1A
206 #define DW_OP_div 0x1B
207 #define DW_OP_minus 0x1C
208 #define DW_OP_mod 0x1D
209 #define DW_OP_mul 0x1E
210 #define DW_OP_neg 0x1F
211 #define DW_OP_not 0x20
212 #define DW_OP_or 0x21
213 #define DW_OP_plus 0x22
214 #define DW_OP_plus_uconst 0x23
215 #define DW_OP_shl 0x24
216 #define DW_OP_shr 0x25
217 #define DW_OP_shra 0x26
218 #define DW_OP_xor 0x27
219 #define DW_OP_skip 0x2F
220 #define DW_OP_bra 0x28
221 #define DW_OP_eq 0x29
222 #define DW_OP_ge 0x2A
223 #define DW_OP_gt 0x2B
224 #define DW_OP_le 0x2C
225 #define DW_OP_lt 0x2D
226 #define DW_OP_ne 0x2E
227 #define DW_OP_lit0 0x30
228 #define DW_OP_lit1 0x31
229 #define DW_OP_lit2 0x32
230 #define DW_OP_lit3 0x33
231 #define DW_OP_lit4 0x34
232 #define DW_OP_lit5 0x35
233 #define DW_OP_lit6 0x36
234 #define DW_OP_lit7 0x37
235 #define DW_OP_lit8 0x38
236 #define DW_OP_lit9 0x39
237 #define DW_OP_lit10 0x3A
238 #define DW_OP_lit11 0x3B
239 #define DW_OP_lit12 0x3C
240 #define DW_OP_lit13 0x3D
241 #define DW_OP_lit14 0x3E
242 #define DW_OP_lit15 0x3F
243 #define DW_OP_lit16 0x40
244 #define DW_OP_lit17 0x41
245 #define DW_OP_lit18 0x42
246 #define DW_OP_lit19 0x43
247 #define DW_OP_lit20 0x44
248 #define DW_OP_lit21 0x45
249 #define DW_OP_lit22 0x46
250 #define DW_OP_lit23 0x47
251 #define DW_OP_lit24 0x48
252 #define DW_OP_lit25 0x49
253 #define DW_OP_lit26 0x4A
254 #define DW_OP_lit27 0x4B
255 #define DW_OP_lit28 0x4C
256 #define DW_OP_lit29 0x4D
257 #define DW_OP_lit30 0x4E
258 #define DW_OP_lit31 0x4F
259 #define DW_OP_reg0 0x50
260 #define DW_OP_reg1 0x51
261 #define DW_OP_reg2 0x52
262 #define DW_OP_reg3 0x53
263 #define DW_OP_reg4 0x54
264 #define DW_OP_reg5 0x55
265 #define DW_OP_reg6 0x56
266 #define DW_OP_reg7 0x57
267 #define DW_OP_reg8 0x58
268 #define DW_OP_reg9 0x59
269 #define DW_OP_reg10 0x5A
270 #define DW_OP_reg11 0x5B
271 #define DW_OP_reg12 0x5C
272 #define DW_OP_reg13 0x5D
273 #define DW_OP_reg14 0x5E
274 #define DW_OP_reg15 0x5F
275 #define DW_OP_reg16 0x60
276 #define DW_OP_reg17 0x61
277 #define DW_OP_reg18 0x62
278 #define DW_OP_reg19 0x63
279 #define DW_OP_reg20 0x64
280 #define DW_OP_reg21 0x65
281 #define DW_OP_reg22 0x66
282 #define DW_OP_reg23 0x67
283 #define DW_OP_reg24 0x68
284 #define DW_OP_reg25 0x69
285 #define DW_OP_reg26 0x6A
286 #define DW_OP_reg27 0x6B
287 #define DW_OP_reg28 0x6C
288 #define DW_OP_reg29 0x6D
289 #define DW_OP_reg30 0x6E
290 #define DW_OP_reg31 0x6F
291 #define DW_OP_breg0 0x70
292 #define DW_OP_breg1 0x71
293 #define DW_OP_breg2 0x72
294 #define DW_OP_breg3 0x73
295 #define DW_OP_breg4 0x74
296 #define DW_OP_breg5 0x75
297 #define DW_OP_breg6 0x76
298 #define DW_OP_breg7 0x77
299 #define DW_OP_breg8 0x78
300 #define DW_OP_breg9 0x79
301 #define DW_OP_breg10 0x7A
302 #define DW_OP_breg11 0x7B
303 #define DW_OP_breg12 0x7C
304 #define DW_OP_breg13 0x7D
305 #define DW_OP_breg14 0x7E
306 #define DW_OP_breg15 0x7F
307 #define DW_OP_breg16 0x80
308 #define DW_OP_breg17 0x81
309 #define DW_OP_breg18 0x82
310 #define DW_OP_breg19 0x83
311 #define DW_OP_breg20 0x84
312 #define DW_OP_breg21 0x85
313 #define DW_OP_breg22 0x86
314 #define DW_OP_breg23 0x87
315 #define DW_OP_breg24 0x88
316 #define DW_OP_breg25 0x89
317 #define DW_OP_breg26 0x8A
318 #define DW_OP_breg27 0x8B
319 #define DW_OP_breg28 0x8C
320 #define DW_OP_breg29 0x8D
321 #define DW_OP_breg30 0x8E
322 #define DW_OP_breg31 0x8F
323 #define DW_OP_regx 0x90
324 #define DW_OP_fbreg 0x91
325 #define DW_OP_bregx 0x92
326 #define DW_OP_piece 0x93
327 #define DW_OP_deref_size 0x94
328 #define DW_OP_xderef_size 0x95
329 #define DW_OP_nop 0x96
330 #define DW_OP_push_object_addres 0x97
331 #define DW_OP_call2 0x98
332 #define DW_OP_call4 0x99
333 #define DW_OP_call_ref 0x9A
334 #define DW_OP_form_tls_address 0x9B
335 #define DW_OP_call_frame_cfa 0x9C
336 #define DW_OP_bit_piece 0x9D
337 #define DW_OP_implicit_value 0x9E
338 #define DW_OP_stack_value 0x9F
339 #define DW_OP_lo_user 0xE0
340 #define DW_OP_hi_user 0xFF
341 
342 // -----------------------------------------------------------------------------
343 // DWARF Class
344 // -----------------------------------------------------------------------------
345 
346 class dwarf4
347 {
348 public:
349 
359  static int64_t decode_sleb128(char **addr);
360 
370  static uint64_t decode_uleb128(char **addr);
371 
384  static void unwind(const fd_entry &fde, register_state *state = nullptr);
385 };
386 
387 #endif
static void unwind(const fd_entry &fde, register_state *state=nullptr)
Definition: dwarf4.cpp:1668
Definition: dwarf4.h:346
static uint64_t decode_uleb128(char **addr)
Definition: dwarf4.cpp:1644
register_rules
Definition: dwarf4.h:143
static int64_t decode_sleb128(char **addr)
Definition: dwarf4.cpp:1622
constexpr const auto addr
Definition: cpuid_x64.h:80
Definition: eh_frame.h:510