5 /* Pointer encodings, from dwarf2.h. */
8 DW_EH_PE_absptr = 0x00, /* */
9 DW_EH_PE_omit = 0xff, /* Value is not there */
11 DW_EH_PE_uleb128 = 0x01,
12 DW_EH_PE_udata2 = 0x02,
13 DW_EH_PE_udata4 = 0x03,
14 DW_EH_PE_udata8 = 0x04,
15 DW_EH_PE_sleb128 = 0x09,
16 DW_EH_PE_sdata2 = 0x0A,
17 DW_EH_PE_sdata4 = 0x0B,
18 DW_EH_PE_sdata8 = 0x0C,
19 DW_EH_PE_signed = 0x08,
21 DW_EH_PE_pcrel = 0x10, /* Value is *(cur + val) */
22 DW_EH_PE_textrel = 0x20, /* Value is *(&text + val) */
23 DW_EH_PE_datarel = 0x30, /* Value is *(&data + val) */
24 DW_EH_PE_funcrel = 0x40, /* Value is *(fde.pc_begin + val) */
25 DW_EH_PE_aligned = 0x50, /* Value is absolute, and stored
28 DW_EH_PE_indirect = 0x80
31 typedef struct EncodedPointer EncodedPointer;
34 PointerEncoding encoding;
39 get_length (const guchar **data)
43 len = *(guint32 *)*data;
47 if (len == 0xffffffff)
49 len = *(guint64 *)data;
57 decode_uleb128 (const guchar **data)
68 result |= (b & 0x7f) << shift;
77 decode_sleb128 (const guchar **data)
88 result |= (b & 0x7f) << shift;
92 if (b & 0x40 && shift < 64)
93 result |= - (1 << shift);
99 decode_block (const guchar **data)
105 len = decode_uleb128 (data);
111 decode_address (const guchar **data)
116 r = *(guint32 *)*data;
122 decode_instruction (const guchar **data)
124 int opcode = *(*data)++;
125 int high2 = (opcode & 0xc0) >> 6;
126 int low6 = (opcode & 0x3f);
130 return "DW_CFA_advance_loc";
132 else if (high2 == 0x02)
134 g_print ("register: %d\n", low6);
135 g_print ("offset: %llu\n", decode_uleb128 (data));
137 return "DW_CFA_offset";
139 else if (high2 == 0x03)
141 return "DW_CFA_restore";
145 g_assert ((opcode & 0xc0) == 0);
153 g_print ("addr: %p\n", (void *)decode_address (data));
154 return "DW_CFA_set_loc";
158 return "DW_CFA_advance_loc1";
162 return "DW_CFA_advance_loc2";
166 return "DW_CFA_advance_loc4";
169 decode_uleb128 (data);
170 decode_uleb128 (data);
171 return "DW_CFA_offset_extended";
174 decode_uleb128 (data);
175 return "DW_CFA_restore_extended";
178 decode_uleb128 (data);
179 return "DW_CFA_undefined";
182 decode_uleb128 (data);
183 return "DW_CFA_same_value";
186 decode_uleb128 (data);
187 decode_uleb128 (data);
188 return "DW_CFA_register";
191 return "DW_CFA_remember_state";
194 return "DW_CFA_restore_state";
197 g_print ("reg: %llu\n", decode_uleb128 (data));
198 g_print ("off: %llu\n", decode_uleb128 (data));
199 return "DW_CFA_def_cfa";
202 decode_uleb128 (data);
203 return "DW_CFA_def_cfa_register";
206 decode_uleb128 (data);
207 return "DW_CFA_def_cfa_offset";
211 return "DW_CFA_def_cfa_expression";
214 decode_uleb128 (data);
216 return "DW_CFA_expression";
219 decode_uleb128 (data);
220 decode_sleb128 (data);
221 return "DW_CFA_offset_extended_sf";
224 decode_uleb128 (data);
225 decode_sleb128 (data);
226 return "DW_CFA_def_cfa_sf";
229 decode_sleb128 (data);
230 return "DW_CFA_def_cfa_offset_sf";
233 decode_uleb128 (data);
234 decode_uleb128 (data);
235 return "DW_CFA_val_offset";
238 decode_uleb128 (data);
239 decode_sleb128 (data);
240 return "DW_CFA_val_offset_sf";
243 decode_uleb128 (data);
245 return "DW_CFA_val_expression";
248 return "DW_CFA_lo_user";
251 return "DW_CFA_hi_user";
254 return "UNKNOWN INSTRUCTION";
259 typedef struct CIE CIE;
262 PointerEncoding encoding;
266 decode_cie (const guchar **data, const guchar *end)
268 gboolean has_augmentation;
274 g_print ("version: %d\n", *(*data)++);
276 augmentation = (*data);
278 *data += strlen (*data) + 1;
280 g_print ("code alignment: %llu\n", decode_uleb128 (data));
282 g_print ("data alignment: %lld\n", decode_sleb128 (data));
284 g_print ("return register: %llu\n", decode_uleb128 (data));
286 g_print ("augmentation: %s\n", augmentation);
288 if (augmentation[0] == 'z')
290 aug_len = decode_uleb128 (data);
292 g_print ("len: %llu\n", aug_len);
294 for (i = 1; augmentation[i] != 0; ++i)
296 if (augmentation[i] == 'L')
304 if (has_augmentation)
306 g_print ("%x\n", **data);
312 g_print (" %s\n", decode_instruction (data));
316 decode_fde (const guchar **data, const guchar *end)
324 decode_entry (const guchar **data, gboolean eh_frame)
331 len = get_length (data);
338 g_print ("length: %llu\n", len);
340 /* CIE_id is 0 for eh frames, and 0xffffffff/0xffffffffffffffff for .debug_frame */
342 id = *(guint32 *)*data;
344 g_print ("id: %lld\n", id);
346 is_cie = (eh_frame && id == 0) || (!eh_frame && id == 0xffffffff);
349 g_print ("is cie\n");
351 g_print ("is not cie\n");
356 decode_cie (data, end);
358 decode_fde (data, end);
363 /* The correct API is probably something like
366 * unwind (ElfParser *parser,
369 * MemoryReader reader,
374 unwind (ElfParser *elf)
379 if ((data = elf_parser_get_debug_frame (elf)))
381 g_print ("Using .debug_frame\n");
384 else if ((data = elf_parser_get_eh_frame (elf)))
386 g_print ("Using .eh_frame\n");
391 g_print ("no debug info found\n");
395 while (decode_entry (&data, eh_f))