1 /* Test program for dwarf location functions.
2 Copyright (C) 2013, 2015 Red Hat, Inc.
3 This file is part of elfutils.
4
5 This file is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 elfutils is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17
18 #include <config.h>
19 #include <assert.h>
20 #include <argp.h>
21 #include <inttypes.h>
22 #include <errno.h>
23 #include ELFUTILS_HEADER(dw)
24 #include ELFUTILS_HEADER(dwfl)
25 #include <dwarf.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <error.h>
29 #include <string.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34
35 #include "../libdw/known-dwarf.h"
36
37 // The Dwarf, Dwarf_CFIs and address bias of
38 // cfi table to adjust DWARF addresses against.
39 // Needed for DW_OP_call_frame_cfa.
40 static Dwarf *dw;
41 Dwarf_CFI *cfi_debug;
42 Dwarf_CFI *cfi_eh;
43 Dwarf_Addr cfi_eh_bias;
44
45 // Whether the current function has a DW_AT_frame_base defined.
46 // Needed for DW_OP_fbreg.
47 bool has_frame_base;
48
49 static void
print_die(Dwarf_Die * die,const char * what,int indent)50 print_die (Dwarf_Die *die, const char *what, int indent)
51 {
52 Dwarf_Addr entrypc;
53 const char *name = dwarf_diename (die) ?: "<unknown>";
54 if (dwarf_entrypc (die, &entrypc) == 0)
55 printf ("%*s[%" PRIx64 "] %s '%s'@%" PRIx64 "\n", indent * 2, "",
56 dwarf_dieoffset (die), what, name, entrypc);
57 else
58 printf ("%*s[%" PRIx64 "] %s '%s'\n", indent * 2, "",
59 dwarf_dieoffset (die), what, name);
60 }
61
62 static const char *
dwarf_encoding_string(unsigned int code)63 dwarf_encoding_string (unsigned int code)
64 {
65 static const char *const known[] =
66 {
67 #define DWARF_ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME,
68 DWARF_ALL_KNOWN_DW_ATE
69 #undef DWARF_ONE_KNOWN_DW_ATE
70 };
71
72 if (likely (code < sizeof (known) / sizeof (known[0])))
73 return known[code];
74
75 return NULL;
76 }
77
78 /* BASE must be a base type DIE referenced by a typed DWARF expression op. */
79 static void
print_base_type(Dwarf_Die * base)80 print_base_type (Dwarf_Die *base)
81 {
82 assert (dwarf_tag (base) == DW_TAG_base_type);
83
84 Dwarf_Attribute encoding;
85 Dwarf_Word enctype = 0;
86 if (dwarf_attr (base, DW_AT_encoding, &encoding) == NULL
87 || dwarf_formudata (&encoding, &enctype) != 0)
88 error (EXIT_FAILURE, 0, "base type without encoding");
89
90 Dwarf_Attribute bsize;
91 Dwarf_Word bits;
92 if (dwarf_attr (base, DW_AT_byte_size, &bsize) != NULL
93 && dwarf_formudata (&bsize, &bits) == 0)
94 bits *= 8;
95 else if (dwarf_attr (base, DW_AT_bit_size, &bsize) == NULL
96 || dwarf_formudata (&bsize, &bits) != 0)
97 error (EXIT_FAILURE, 0, "base type without byte or bit size");
98
99 printf ("{%s,%s,%" PRIu64 "@[%" PRIx64 "]}",
100 dwarf_diename (base),
101 dwarf_encoding_string (enctype),
102 bits,
103 dwarf_dieoffset (base));
104 }
105
106 static const char *
dwarf_opcode_string(unsigned int code)107 dwarf_opcode_string (unsigned int code)
108 {
109 static const char *const known[] =
110 {
111 #define DWARF_ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
112 DWARF_ALL_KNOWN_DW_OP
113 #undef DWARF_ONE_KNOWN_DW_OP
114 };
115
116 if (likely (code < sizeof (known) / sizeof (known[0])))
117 return known[code];
118
119 return NULL;
120 }
121
122 // Forward reference for print_expr_block.
123 static void print_expr (Dwarf_Attribute *, Dwarf_Op *, Dwarf_Addr);
124
125 static void
print_expr_block(Dwarf_Attribute * attr,Dwarf_Op * exprs,int len,Dwarf_Addr addr)126 print_expr_block (Dwarf_Attribute *attr, Dwarf_Op *exprs, int len,
127 Dwarf_Addr addr)
128 {
129 printf ("{");
130 for (int i = 0; i < len; i++)
131 {
132 print_expr (attr, &exprs[i], addr);
133 printf ("%s", (i + 1 < len ? ", " : ""));
134 }
135 printf ("}");
136 }
137
138 static void
print_expr_block_addrs(Dwarf_Attribute * attr,Dwarf_Addr begin,Dwarf_Addr end,Dwarf_Op * exprs,int len)139 print_expr_block_addrs (Dwarf_Attribute *attr,
140 Dwarf_Addr begin, Dwarf_Addr end,
141 Dwarf_Op *exprs, int len)
142 {
143 printf (" [%" PRIx64 ",%" PRIx64 ") ", begin, end);
144 print_expr_block (attr, exprs, len, begin);
145 printf ("\n");
146 }
147
148 static void
print_expr(Dwarf_Attribute * attr,Dwarf_Op * expr,Dwarf_Addr addr)149 print_expr (Dwarf_Attribute *attr, Dwarf_Op *expr, Dwarf_Addr addr)
150 {
151 uint8_t atom = expr->atom;
152 const char *opname = dwarf_opcode_string (atom);
153 assert (opname != NULL);
154
155 switch (atom)
156 {
157 case DW_OP_deref:
158 case DW_OP_dup:
159 case DW_OP_drop:
160 case DW_OP_over:
161 case DW_OP_swap:
162 case DW_OP_rot:
163 case DW_OP_xderef:
164 case DW_OP_abs:
165 case DW_OP_and:
166 case DW_OP_div:
167 case DW_OP_minus:
168 case DW_OP_mod:
169 case DW_OP_mul:
170 case DW_OP_neg:
171 case DW_OP_not:
172 case DW_OP_or:
173 case DW_OP_plus:
174 case DW_OP_shl:
175 case DW_OP_shr:
176 case DW_OP_shra:
177 case DW_OP_xor:
178 case DW_OP_eq:
179 case DW_OP_ge:
180 case DW_OP_gt:
181 case DW_OP_le:
182 case DW_OP_lt:
183 case DW_OP_ne:
184 case DW_OP_lit0 ... DW_OP_lit31:
185 case DW_OP_reg0 ... DW_OP_reg31:
186 case DW_OP_nop:
187 case DW_OP_stack_value:
188 /* No arguments. */
189 printf ("%s", opname);
190 break;
191
192 case DW_OP_form_tls_address:
193 /* No arguments. Special. Pops an address and pushes the
194 corresponding address in the current thread local
195 storage. Uses the thread local storage block of the defining
196 module (executable, shared library). */
197 printf ("%s", opname);
198 break;
199
200 case DW_OP_GNU_push_tls_address:
201 /* No arguments. Special. Not the same as DW_OP_form_tls_address.
202 Pops an offset into the current thread local strorage and
203 pushes back the actual address. */
204 printf ("%s", opname);
205 break;
206
207 case DW_OP_call_frame_cfa:
208 /* No arguments. Special. Pushes Call Frame Address as computed
209 by CFI data (dwarf_cfi_addrframe will fetch that info (either from
210 the .eh_frame or .debug_frame CFI) and dwarf_frame_cfa translatesr
211 the CFI instructions into a plain DWARF expression.
212 Never used in CFI itself. */
213
214 if (attr == NULL)
215 error (EXIT_FAILURE, 0, "%s used in CFI", opname);
216
217 printf ("%s ", opname);
218 if (cfi_eh == NULL && cfi_debug == NULL)
219 error (EXIT_FAILURE, 0, "DW_OP_call_frame_cfa used but no cfi found.");
220
221 Dwarf_Frame *frame;
222 if (dwarf_cfi_addrframe (cfi_eh, addr + cfi_eh_bias, &frame) != 0
223 && dwarf_cfi_addrframe (cfi_debug, addr, &frame) != 0)
224 error (EXIT_FAILURE, 0, "dwarf_cfi_addrframe 0x%" PRIx64 ": %s",
225 addr, dwarf_errmsg (-1));
226
227 Dwarf_Op *cfa_ops;
228 size_t cfa_nops;
229 if (dwarf_frame_cfa (frame, &cfa_ops, &cfa_nops) != 0)
230 error (EXIT_FAILURE, 0, "dwarf_frame_cfa 0x%" PRIx64 ": %s",
231 addr, dwarf_errmsg (-1));
232 if (cfa_nops < 1)
233 error (EXIT_FAILURE, 0, "dwarf_frame_cfa no ops");
234 print_expr_block (NULL, cfa_ops, cfa_nops, 0);
235 free (frame);
236 break;
237
238 case DW_OP_push_object_address:
239 /* No arguments. Special. Pushes object address explicitly.
240 Normally only done implicitly by DW_AT_data_member_location.
241 Never used in CFI. */
242 if (attr == NULL)
243 error (EXIT_FAILURE, 0, "%s used in CFI", opname);
244 printf ("%s", opname);
245 break;
246
247 case DW_OP_addr:
248 /* 1 address argument. */
249 printf ("%s(0x%" PRIx64 ")", opname, (Dwarf_Addr) expr->number);
250 break;
251
252 case DW_OP_const1u:
253 case DW_OP_const2u:
254 case DW_OP_const4u:
255 case DW_OP_const8u:
256 case DW_OP_constu:
257 case DW_OP_pick:
258 case DW_OP_plus_uconst:
259 case DW_OP_regx:
260 case DW_OP_piece:
261 case DW_OP_deref_size:
262 case DW_OP_xderef_size:
263 /* 1 numeric unsigned argument. */
264 printf ("%s(%" PRIu64 ")", opname, expr->number);
265 break;
266
267 case DW_OP_call2:
268 case DW_OP_call4:
269 case DW_OP_call_ref:
270 /* 1 DIE offset argument for more ops in location attribute of DIE.
271 Never used in CFI. */
272 {
273 if (attr == NULL)
274 error (EXIT_FAILURE, 0, "%s used in CFI", opname);
275
276 Dwarf_Attribute call_attr;
277 if (dwarf_getlocation_attr (attr, expr, &call_attr) != 0)
278 error (EXIT_FAILURE, 0, "dwarf_getlocation_attr for %s error %s",
279 opname, dwarf_errmsg (-1));
280
281 Dwarf_Die call_die;
282 if (dwarf_getlocation_die (attr, expr, &call_die) != 0)
283 error (EXIT_FAILURE, 0, "dwarf_getlocation_die for %s error %s",
284 opname, dwarf_errmsg (-1));
285
286 Dwarf_Op *call_ops;
287 size_t call_len;
288 if (dwarf_getlocation (&call_attr, &call_ops, &call_len) != 0)
289 error (EXIT_FAILURE, 0, "dwarf_getlocation for entry: %s",
290 dwarf_errmsg (-1));
291
292 printf ("%s([%" PRIx64 "]) ", opname, dwarf_dieoffset (&call_die));
293 print_expr_block (&call_attr, call_ops, call_len, addr);
294 }
295 break;
296
297 case DW_OP_const1s:
298 case DW_OP_const2s:
299 case DW_OP_const4s:
300 case DW_OP_const8s:
301 case DW_OP_consts:
302 case DW_OP_skip:
303 case DW_OP_bra:
304 case DW_OP_breg0 ... DW_OP_breg31:
305 /* 1 numeric signed argument. */
306 printf ("%s(%" PRId64 ")", opname, (Dwarf_Sword) expr->number);
307 break;
308
309 case DW_OP_fbreg:
310 /* 1 numeric signed argument. Offset from frame base. */
311 if (attr == NULL)
312 error (EXIT_FAILURE, 0, "%s used in CFI", opname);
313
314 if (! has_frame_base)
315 error (EXIT_FAILURE, 0, "DW_OP_fbreg used without a frame base");
316
317 printf ("%s(%" PRId64 ")", opname, (Dwarf_Sword) expr->number);
318 break;
319
320 case DW_OP_bregx:
321 /* 2 arguments, unsigned register number, signed offset. */
322 printf ("%s(%" PRIu64 ",%" PRId64 ")", opname,
323 expr->number, (Dwarf_Sword) expr->number2);
324 break;
325
326 case DW_OP_bit_piece:
327 /* 2 arguments, unsigned size, unsigned offset. */
328 printf ("%s(%" PRIu64 ",%" PRIu64 ")", opname,
329 expr->number, expr->number2);
330 break;
331
332 case DW_OP_implicit_value:
333 /* Special, unsigned size plus block. */
334 {
335 Dwarf_Attribute const_attr;
336 Dwarf_Block block;
337 if (dwarf_getlocation_attr (attr, expr, &const_attr) != 0)
338 error (EXIT_FAILURE, 0, "dwarf_getlocation_attr: %s",
339 dwarf_errmsg (-1));
340
341 if (dwarf_formblock (&const_attr, &block) != 0)
342 error (EXIT_FAILURE, 0, "dwarf_formblock: %s",
343 dwarf_errmsg (-1));
344
345 /* This is the "old" way. Check they result in the same. */
346 Dwarf_Block block_impl;
347 if (dwarf_getlocation_implicit_value (attr, expr, &block_impl) != 0)
348 error (EXIT_FAILURE, 0, "dwarf_getlocation_implicit_value: %s",
349 dwarf_errmsg (-1));
350
351 assert (expr->number == block.length);
352 assert (block.length == block_impl.length);
353 printf ("%s(%" PRIu64 "){", opname, block.length);
354 for (size_t i = 0; i < block.length; i++)
355 {
356 printf ("%02x", block.data[i]);
357 assert (block.data[i] == block_impl.data[i]);
358 }
359 printf("}");
360 }
361 break;
362
363 case DW_OP_GNU_implicit_pointer:
364 /* Special, DIE offset, signed offset. Referenced DIE has a
365 location or const_value attribute. */
366 {
367 if (attr == NULL)
368 error (EXIT_FAILURE, 0, "%s used in CFI", opname);
369
370 Dwarf_Attribute attrval;
371 if (dwarf_getlocation_implicit_pointer (attr, expr, &attrval) != 0)
372 error (EXIT_FAILURE, 0, "dwarf_getlocation_implicit_pointer: %s",
373 dwarf_errmsg (-1));
374
375 // Sanity check, results should be the same.
376 Dwarf_Attribute attrval2;
377 if (dwarf_getlocation_attr (attr, expr, &attrval2) != 0)
378 error (EXIT_FAILURE, 0, "dwarf_getlocation_attr: %s",
379 dwarf_errmsg (-1));
380
381 assert (dwarf_whatattr (&attrval) == dwarf_whatattr (&attrval2));
382 assert (dwarf_whatform (&attrval) == dwarf_whatform (&attrval2));
383 // In theory two different valp pointers could point to the same
384 // value. But here we really expect them to be the equal.
385 assert (attrval.valp == attrval2.valp);
386
387 Dwarf_Die impl_die;
388 if (dwarf_getlocation_die (attr, expr, &impl_die) != 0)
389 error (EXIT_FAILURE, 0, "dwarf_getlocation_due: %s",
390 dwarf_errmsg (-1));
391
392 printf ("%s([%" PRIx64 "],%" PRId64 ") ", opname,
393 dwarf_dieoffset (&impl_die), expr->number2);
394
395 if (dwarf_whatattr (&attrval) == DW_AT_const_value)
396 printf ("<constant value>"); // Lookup type...
397 else
398 {
399 // Lookup the location description at the current address.
400 Dwarf_Op *exprval;
401 size_t exprval_len;
402 int locs = dwarf_getlocation_addr (&attrval, addr,
403 &exprval, &exprval_len, 1);
404 if (locs == 0)
405 printf ("<no location>"); // This means "optimized out".
406 else if (locs == 1)
407 print_expr_block (&attrval, exprval, exprval_len, addr);
408 else
409 error (EXIT_FAILURE, 0,
410 "dwarf_getlocation_addr attrval at addr 0x%" PRIx64
411 ", locs (%d): %s", addr, locs, dwarf_errmsg (-1));
412 }
413 }
414 break;
415
416 case DW_OP_GNU_entry_value:
417 /* Special, unsigned size plus expression block. All registers
418 inside the block should be interpreted as they had on
419 entering the function. dwarf_getlocation_attr will return an
420 attribute containing the block as locexpr which can be
421 retrieved with dwarf_getlocation. */
422 {
423 Dwarf_Attribute entry_attr;
424 if (dwarf_getlocation_attr (attr, expr, &entry_attr) != 0)
425 error (EXIT_FAILURE, 0, "dwarf_getlocation_attr: %s",
426 dwarf_errmsg (-1));
427
428 Dwarf_Op *entry_ops;
429 size_t entry_len;
430 if (dwarf_getlocation (&entry_attr, &entry_ops, &entry_len) != 0)
431 error (EXIT_FAILURE, 0, "dwarf_getlocation for entry: %s",
432 dwarf_errmsg (-1));
433
434 printf ("%s(%zd) ", opname, entry_len);
435 print_expr_block (attr, entry_ops, entry_len, addr);
436 }
437 break;
438
439 case DW_OP_GNU_parameter_ref:
440 /* Special, unsigned CU relative DIE offset pointing to a
441 DW_TAG_formal_parameter. The value that parameter had at the
442 call site of the current function will be put on the DWARF
443 stack. The value can be retrieved by finding the
444 DW_TAG_GNU_call_site_parameter which has as
445 DW_AT_abstract_origin the same formal parameter DIE. */
446 {
447 Dwarf_Die param;
448 if (dwarf_getlocation_die (attr, expr, ¶m) != 0)
449 error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
450 dwarf_errmsg (-1));
451 // XXX actually lookup DW_TAG_GNU_call_site_parameter
452 printf ("%s[%" PRIx64 "]", opname, dwarf_dieoffset (¶m));
453 assert (expr->number == dwarf_cuoffset (¶m));
454 assert (dwarf_tag (¶m) == DW_TAG_formal_parameter);
455 }
456 break;
457
458 case DW_OP_GNU_convert:
459 case DW_OP_GNU_reinterpret:
460 /* Special, unsigned CU relative DIE offset pointing to a
461 DW_TAG_base_type. Pops a value, converts or reinterprets the
462 value to the given type. When the argument is zero the value
463 becomes untyped again. */
464 {
465 Dwarf_Die type;
466 Dwarf_Off off = expr->number;
467 if (off != 0)
468 {
469 if (dwarf_getlocation_die (attr, expr, &type) != 0)
470 error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
471 dwarf_errmsg (-1));
472 off = dwarf_dieoffset (&type);
473 assert (expr->number == dwarf_cuoffset (&type));
474 printf ("%s", opname);
475 print_base_type (&type);
476 }
477 else
478 printf ("%s[%" PRIu64 "]", opname, off);
479
480 }
481 break;
482
483 case DW_OP_GNU_regval_type:
484 /* Special, unsigned register number plus unsigned CU relative
485 DIE offset pointing to a DW_TAG_base_type. */
486 {
487 Dwarf_Die type;
488 if (dwarf_getlocation_die (attr, expr, &type) != 0)
489 error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
490 dwarf_errmsg (-1));
491 assert (expr->number2 == dwarf_cuoffset (&type));
492 // XXX check size against base_type size?
493 printf ("%s(reg%" PRIu64 ")", opname, expr->number);
494 print_base_type (&type);
495 }
496 break;
497
498 case DW_OP_GNU_deref_type:
499 /* Special, unsigned size plus unsigned CU relative DIE offset
500 pointing to a DW_TAG_base_type. */
501 {
502 Dwarf_Die type;
503 if (dwarf_getlocation_die (attr, expr, &type) != 0)
504 error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
505 dwarf_errmsg (-1));
506 assert (expr->number2 == dwarf_cuoffset (&type));
507 // XXX check size against base_type size?
508 printf ("%s(%" PRIu64 ")", opname, expr->number);
509 print_base_type (&type);
510 }
511 break;
512
513 case DW_OP_GNU_const_type:
514 /* Special, unsigned CU relative DIE offset pointing to a
515 DW_TAG_base_type, an unsigned size length plus a block with
516 the constant value. */
517 {
518 Dwarf_Die type;
519 if (dwarf_getlocation_die (attr, expr, &type) != 0)
520 error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
521 dwarf_errmsg (-1));
522 assert (expr->number == dwarf_cuoffset (&type));
523
524 Dwarf_Attribute const_attr;
525 if (dwarf_getlocation_attr (attr, expr, &const_attr) != 0)
526 error (EXIT_FAILURE, 0, "dwarf_getlocation_attr for type: %s",
527 dwarf_errmsg (-1));
528
529 Dwarf_Block block;
530 if (dwarf_formblock (&const_attr, &block) != 0)
531 error (EXIT_FAILURE, 0, "dwarf_formblock for type: %s",
532 dwarf_errmsg (-1));
533
534 printf ("%s", opname);
535 print_base_type (&type);
536 printf ("(%" PRIu64 ")[", block.length);
537 for (size_t i = 0; i < block.length; i++)
538 printf ("%02x", block.data[i]);
539 printf("]");
540 }
541 break;
542
543 default:
544 error (EXIT_FAILURE, 0, "unhandled opcode: DW_OP_%s (0x%x)",
545 opname, atom);
546 }
547 }
548
549 /* Get all variables and print their value expressions. */
550 static void
print_varlocs(Dwarf_Die * funcdie)551 print_varlocs (Dwarf_Die *funcdie)
552 {
553 // Display frame base for function if it exists.
554 // Should be used for DW_OP_fbreg.
555 has_frame_base = dwarf_hasattr (funcdie, DW_AT_frame_base);
556 if (has_frame_base)
557 {
558 Dwarf_Attribute fb_attr;
559 if (dwarf_attr (funcdie, DW_AT_frame_base, &fb_attr) == NULL)
560 error (EXIT_FAILURE, 0, "dwarf_attr fb: %s", dwarf_errmsg (-1));
561
562 Dwarf_Op *fb_expr;
563 size_t fb_exprlen;
564 if (dwarf_getlocation (&fb_attr, &fb_expr, &fb_exprlen) == 0)
565 {
566 // Covers all of function.
567 Dwarf_Addr entrypc;
568 if (dwarf_entrypc (funcdie, &entrypc) != 0)
569 error (EXIT_FAILURE, 0, "dwarf_entrypc: %s", dwarf_errmsg (-1));
570
571 printf (" frame_base: ");
572 if (entrypc == 0)
573 printf ("XXX zero address"); // XXX bad DWARF?
574 else
575 print_expr_block (&fb_attr, fb_expr, fb_exprlen, entrypc);
576 printf ("\n");
577 }
578 else
579 {
580 Dwarf_Addr base, start, end;
581 ptrdiff_t off = 0;
582 printf (" frame_base:\n");
583 while ((off = dwarf_getlocations (&fb_attr, off, &base,
584 &start, &end,
585 &fb_expr, &fb_exprlen)) > 0)
586 {
587 printf (" (%" PRIx64 ",%" PRIx64 ") ", start, end);
588 print_expr_block (&fb_attr, fb_expr, fb_exprlen, start);
589 printf ("\n");
590 }
591
592 if (off < 0)
593 error (EXIT_FAILURE, 0, "dwarf_getlocations fb: %s",
594 dwarf_errmsg (-1));
595 }
596 }
597 else if (dwarf_tag (funcdie) == DW_TAG_inlined_subroutine)
598 {
599 // See whether the subprogram we are inlined into has a frame
600 // base we should use.
601 Dwarf_Die *scopes;
602 int n = dwarf_getscopes_die (funcdie, &scopes);
603 if (n <= 0)
604 error (EXIT_FAILURE, 0, "dwarf_getscopes_die: %s", dwarf_errmsg (-1));
605
606 while (n-- > 0)
607 if (dwarf_tag (&scopes[n]) == DW_TAG_subprogram
608 && dwarf_hasattr (&scopes[n], DW_AT_frame_base))
609 {
610 has_frame_base = true;
611 break;
612 }
613 free (scopes);
614 }
615
616 if (! dwarf_haschildren (funcdie))
617 return;
618
619 Dwarf_Die child;
620 int res = dwarf_child (funcdie, &child);
621 if (res < 0)
622 error (EXIT_FAILURE, 0, "dwarf_child: %s", dwarf_errmsg (-1));
623
624 /* We thought there was a child, but the child list was actually
625 empty. This isn't technically an error in the DWARF, but it is
626 certainly non-optimimal. */
627 if (res == 1)
628 return;
629
630 do
631 {
632 int tag = dwarf_tag (&child);
633 if (tag == DW_TAG_variable || tag == DW_TAG_formal_parameter)
634 {
635 const char *what = tag == DW_TAG_variable ? "variable" : "parameter";
636 print_die (&child, what, 2);
637
638 if (dwarf_hasattr (&child, DW_AT_location))
639 {
640 Dwarf_Attribute attr;
641 if (dwarf_attr (&child, DW_AT_location, &attr) == NULL)
642 error (EXIT_FAILURE, 0, "dwarf_attr: %s", dwarf_errmsg (-1));
643
644 Dwarf_Op *expr;
645 size_t exprlen;
646 if (dwarf_getlocation (&attr, &expr, &exprlen) == 0)
647 {
648 // Covers all ranges of the function.
649 // Evaluate the expression block for each range.
650 ptrdiff_t offset = 0;
651 Dwarf_Addr base, begin, end;
652 do
653 {
654 offset = dwarf_ranges (funcdie, offset, &base,
655 &begin, &end);
656 if (offset < 0)
657 error (EXIT_FAILURE, 0, "dwarf_ranges: %s",
658 dwarf_errmsg (-1));
659
660 if (offset > 0)
661 {
662 if (exprlen == 0)
663 printf (" (%"
664 PRIx64 ",%" PRIx64
665 ") <empty expression>\n", begin, end);
666 else
667 print_expr_block_addrs (&attr, begin, end,
668 expr, exprlen);
669 }
670 }
671 while (offset > 0);
672
673 if (offset < 0)
674 error (EXIT_FAILURE, 0, "dwarf_ranges: %s",
675 dwarf_errmsg (-1));
676 }
677 else
678 {
679 Dwarf_Addr base, begin, end;
680 ptrdiff_t offset = 0;
681 while ((offset = dwarf_getlocations (&attr, offset,
682 &base, &begin, &end,
683 &expr, &exprlen)) > 0)
684 if (begin >= end)
685 printf (" (%" PRIx64 ",%" PRIx64
686 ") <empty range>\n", begin, end); // XXX report?
687 else
688 {
689 print_expr_block_addrs (&attr, begin, end,
690 expr, exprlen);
691
692 // Extra sanity check for dwarf_getlocation_addr
693 // Must at least find one range for begin and end-1.
694 Dwarf_Op *expraddr;
695 size_t expraddr_len;
696 int locs = dwarf_getlocation_addr (&attr, begin,
697 &expraddr,
698 &expraddr_len, 1);
699 assert (locs == 1);
700 locs = dwarf_getlocation_addr (&attr, end - 1,
701 &expraddr,
702 &expraddr_len, 1);
703 assert (locs == 1);
704 }
705
706 if (offset < 0)
707 error (EXIT_FAILURE, 0, "dwarf_getlocations: %s",
708 dwarf_errmsg (-1));
709 }
710 }
711 else if (dwarf_hasattr (&child, DW_AT_const_value))
712 {
713 printf (" <constant value>\n"); // Lookup type and print.
714 }
715 else
716 {
717 printf (" <no value>\n");
718 }
719 }
720 }
721 while (dwarf_siblingof (&child, &child) == 0);
722 }
723
724 static int
handle_instance(Dwarf_Die * funcdie,void * arg)725 handle_instance (Dwarf_Die *funcdie, void *arg __attribute__ ((unused)))
726 {
727 print_die (funcdie, "inlined function", 1);
728 print_varlocs (funcdie);
729
730 return DWARF_CB_OK;
731 }
732
733 static int
handle_function(Dwarf_Die * funcdie,void * arg)734 handle_function (Dwarf_Die *funcdie, void *arg __attribute__((unused)))
735 {
736 if (dwarf_func_inline (funcdie) > 0)
737 {
738 // abstract inline definition, find all inlined instances.
739
740 // Note this is convenient for listing all instances together
741 // so you can easily compare the location expressions describing
742 // the variables and parameters, but it isn't very efficient
743 // since it will walk the DIE tree multiple times.
744 if (dwarf_func_inline_instances (funcdie, &handle_instance, NULL) != 0)
745 error (EXIT_FAILURE, 0, "dwarf_func_inline_instances: %s",
746 dwarf_errmsg (-1));
747 }
748 else
749 {
750 // Contains actual code, not just a declaration?
751 Dwarf_Addr entrypc;
752 if (dwarf_entrypc (funcdie, &entrypc) == 0)
753 {
754 print_die (funcdie, "function", 1);
755 print_varlocs (funcdie);
756 }
757 }
758
759 return DWARF_CB_OK;
760 }
761
762 int
main(int argc,char * argv[])763 main (int argc, char *argv[])
764 {
765 int remaining;
766 Dwfl *dwfl;
767 (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining,
768 &dwfl);
769 assert (dwfl != NULL);
770
771 Dwarf_Die *cu = NULL;
772 Dwarf_Addr dwbias;
773 while ((cu = dwfl_nextcu (dwfl, cu, &dwbias)) != NULL)
774 {
775 /* Only walk actual compile units (not partial units) that
776 contain code. */
777 Dwarf_Addr cubase;
778 if (dwarf_tag (cu) == DW_TAG_compile_unit
779 && dwarf_lowpc (cu, &cubase) == 0)
780 {
781 Dwfl_Module *mod = dwfl_cumodule (cu);
782 Dwarf_Addr modbias;
783 dw = dwfl_module_getdwarf (mod, &modbias);
784 assert (dwbias == modbias);
785
786 const char *mainfile;
787 const char *modname = dwfl_module_info (mod, NULL,
788 NULL, NULL,
789 NULL, NULL,
790 &mainfile,
791 NULL);
792 if (modname == NULL)
793 error (EXIT_FAILURE, 0, "dwfl_module_info: %s", dwarf_errmsg (-1));
794
795 const char *name = (modname[0] != '\0'
796 ? modname
797 : basename (mainfile));
798 printf ("module '%s'\n", name);
799 print_die (cu, "CU", 0);
800
801 Dwarf_Addr elfbias;
802 Elf *elf = dwfl_module_getelf (mod, &elfbias);
803
804 // CFI. We need both since sometimes neither is complete.
805 cfi_debug = dwarf_getcfi (dw); // No bias needed, same file.
806 cfi_eh = dwarf_getcfi_elf (elf);
807 cfi_eh_bias = dwbias - elfbias;
808
809 // Get the actual CU DIE and walk all functions inside it.
810 Dwarf_Die cudie;
811 uint8_t offsize;
812 uint8_t addrsize;
813 if (dwarf_diecu (cu, &cudie, &addrsize, &offsize) == NULL)
814 error (EXIT_FAILURE, 0, "dwarf_diecu %s", dwarf_errmsg (-1));
815
816 if (dwarf_getfuncs (cu, handle_function, NULL, 0) != 0)
817 error (EXIT_FAILURE, 0, "dwarf_getfuncs %s",
818 dwarf_errmsg (-1));
819 }
820 }
821
822 dwfl_end (dwfl);
823 return 0;
824 }
825