1 /* Test program for dwarf location functions.
2 Copyright (C) 2013, 2015, 2017, 2018 Red Hat, Inc.
3 This file is part of elfutils.
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.
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.
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/>. */
23 #include ELFUTILS_HEADER(dw)
24 #include ELFUTILS_HEADER(dwfl)
29 #include <sys/types.h>
35 #include "../libdw/known-dwarf.h"
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.
42 Dwarf_Addr cfi_debug_bias;
44 Dwarf_Addr cfi_eh_bias;
49 // Whether the current function has a DW_AT_frame_base defined.
50 // Needed for DW_OP_fbreg.
54 print_die (Dwarf_Die *die, const char *what, int indent)
57 const char *name = dwarf_diename (die) ?: "<unknown>";
58 if (dwarf_entrypc (die, &entrypc) == 0)
59 printf ("%*s[%" PRIx64 "] %s '%s'@%" PRIx64 "\n", indent * 2, "",
60 dwarf_dieoffset (die), what, name, entrypc);
62 printf ("%*s[%" PRIx64 "] %s '%s'\n", indent * 2, "",
63 dwarf_dieoffset (die), what, name);
67 dwarf_encoding_string (unsigned int code)
69 static const char *const known[] =
71 #define DWARF_ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME,
72 DWARF_ALL_KNOWN_DW_ATE
73 #undef DWARF_ONE_KNOWN_DW_ATE
76 if (likely (code < sizeof (known) / sizeof (known[0])))
79 return "<unknown encoding>";
83 dwarf_tag_string (unsigned int tag)
87 #define DWARF_ONE_KNOWN_DW_TAG(NAME, CODE) case CODE: return #NAME;
88 DWARF_ALL_KNOWN_DW_TAG
89 #undef DWARF_ONE_KNOWN_DW_TAG
91 return "<unknown tag>";
96 dwarf_attr_string (unsigned int attrnum)
100 #define DWARF_ONE_KNOWN_DW_AT(NAME, CODE) case CODE: return #NAME;
101 DWARF_ALL_KNOWN_DW_AT
102 #undef DWARF_ONE_KNOWN_DW_AT
104 return "<unknown attr>";
109 dwarf_form_string (unsigned int form)
113 #define DWARF_ONE_KNOWN_DW_FORM(NAME, CODE) case CODE: return #NAME;
114 DWARF_ALL_KNOWN_DW_FORM
115 #undef DWARF_ONE_KNOWN_DW_FORM
117 return "<unknown form>";
121 /* BASE must be a base type DIE referenced by a typed DWARF expression op. */
123 print_base_type (Dwarf_Die *base)
125 if (dwarf_tag (base) != DW_TAG_base_type)
126 error (EXIT_FAILURE, 0, "not a base type");
128 Dwarf_Attribute encoding;
129 Dwarf_Word enctype = 0;
130 if (dwarf_attr (base, DW_AT_encoding, &encoding) == NULL
131 || dwarf_formudata (&encoding, &enctype) != 0)
132 error (EXIT_FAILURE, 0, "base type without encoding");
134 Dwarf_Attribute bsize;
136 if (dwarf_attr (base, DW_AT_byte_size, &bsize) != NULL
137 && dwarf_formudata (&bsize, &bits) == 0)
139 else if (dwarf_attr (base, DW_AT_bit_size, &bsize) == NULL
140 || dwarf_formudata (&bsize, &bits) != 0)
141 error (EXIT_FAILURE, 0, "base type without byte or bit size");
143 printf ("{%s,%s,%" PRIu64 "@[%" PRIx64 "]}",
144 dwarf_diename (base),
145 dwarf_encoding_string (enctype),
147 dwarf_dieoffset (base));
151 dwarf_opcode_string (unsigned int code)
153 static const char *const known[] =
155 #define DWARF_ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
156 DWARF_ALL_KNOWN_DW_OP
157 #undef DWARF_ONE_KNOWN_DW_OP
160 if (likely (code < sizeof (known) / sizeof (known[0])))
163 return "<unknown opcode>";
166 // Forward reference for print_expr_block.
167 static void print_expr (Dwarf_Attribute *, Dwarf_Op *, Dwarf_Addr, int);
170 print_expr_block (Dwarf_Attribute *attr, Dwarf_Op *exprs, int len,
171 Dwarf_Addr addr, int depth)
174 for (int i = 0; i < len; i++)
176 print_expr (attr, &exprs[i], addr, depth);
177 printf ("%s", (i + 1 < len ? ", " : ""));
183 print_expr_block_addrs (Dwarf_Attribute *attr,
184 Dwarf_Addr begin, Dwarf_Addr end,
185 Dwarf_Op *exprs, int len)
187 printf (" [%" PRIx64 ",%" PRIx64 ") ", begin, end);
188 print_expr_block (attr, exprs, len, begin, 0);
193 print_expr (Dwarf_Attribute *attr, Dwarf_Op *expr, Dwarf_Addr addr, int depth)
196 if (depth++ > MAX_DEPTH)
197 error (EXIT_FAILURE, 0, "print_expr recursion depth exceeded");
199 uint8_t atom = expr->atom;
200 const char *opname = dwarf_opcode_string (atom);
231 case DW_OP_lit0 ... DW_OP_lit31:
232 case DW_OP_reg0 ... DW_OP_reg31:
234 case DW_OP_stack_value:
236 printf ("%s", opname);
239 case DW_OP_form_tls_address:
240 /* No arguments. Special. Pops an address and pushes the
241 corresponding address in the current thread local
242 storage. Uses the thread local storage block of the defining
243 module (executable, shared library). */
244 printf ("%s", opname);
247 case DW_OP_GNU_push_tls_address:
248 /* No arguments. Special. Not the same as DW_OP_form_tls_address.
249 Pops an offset into the current thread local strorage and
250 pushes back the actual address. */
251 printf ("%s", opname);
254 case DW_OP_GNU_uninit:
255 /* No arguments. Special. It means the expression describes
256 an value which hasn't been initialized (yet). */
257 printf ("%s", opname);
260 case DW_OP_call_frame_cfa:
261 /* No arguments. Special. Pushes Call Frame Address as computed
262 by CFI data (dwarf_cfi_addrframe will fetch that info (either from
263 the .eh_frame or .debug_frame CFI) and dwarf_frame_cfa translatesr
264 the CFI instructions into a plain DWARF expression.
265 Never used in CFI itself. */
268 error (EXIT_FAILURE, 0, "%s used in CFI", opname);
270 printf ("%s ", opname);
271 if (cfi_eh == NULL && cfi_debug == NULL && !is_debug)
272 error (EXIT_FAILURE, 0, "DW_OP_call_frame_cfa used but no cfi found.");
275 if (dwarf_cfi_addrframe (cfi_eh, addr + cfi_eh_bias, &frame) == 0
276 || dwarf_cfi_addrframe (cfi_debug, addr + cfi_debug_bias,
281 if (dwarf_frame_cfa (frame, &cfa_ops, &cfa_nops) != 0)
282 error (EXIT_FAILURE, 0, "dwarf_frame_cfa 0x%" PRIx64 ": %s",
283 addr, dwarf_errmsg (-1));
285 error (EXIT_FAILURE, 0, "dwarf_frame_cfa no ops");
286 print_expr_block (NULL, cfa_ops, cfa_nops, 0, depth);
289 else if (is_ET_REL || is_debug)
291 /* XXX In ET_REL files there might be an .eh_frame with relocations
292 we don't handle (e.g. X86_64_PC32). Maybe we should? */
296 error (EXIT_FAILURE, 0, "dwarf_cfi_addrframe 0x%" PRIx64 ": %s",
297 addr, dwarf_errmsg (-1));
300 case DW_OP_push_object_address:
301 /* No arguments. Special. Pushes object address explicitly.
302 Normally only done implicitly by DW_AT_data_member_location.
303 Never used in CFI. */
305 error (EXIT_FAILURE, 0, "%s used in CFI", opname);
306 printf ("%s", opname);
310 /* 1 address argument. */
311 printf ("%s(0x%" PRIx64 ")", opname, (Dwarf_Addr) expr->number);
320 case DW_OP_plus_uconst:
323 case DW_OP_deref_size:
324 case DW_OP_xderef_size:
325 /* 1 numeric unsigned argument. */
326 printf ("%s(%" PRIu64 ")", opname, expr->number);
332 /* 1 DIE offset argument for more ops in location attribute of DIE.
333 Never used in CFI. */
336 error (EXIT_FAILURE, 0, "%s used in CFI", opname);
338 Dwarf_Attribute call_attr;
339 if (dwarf_getlocation_attr (attr, expr, &call_attr) != 0)
340 error (EXIT_FAILURE, 0, "dwarf_getlocation_attr for %s error %s",
341 opname, dwarf_errmsg (-1));
344 if (dwarf_getlocation_die (attr, expr, &call_die) != 0)
345 error (EXIT_FAILURE, 0, "dwarf_getlocation_die for %s error %s",
346 opname, dwarf_errmsg (-1));
350 if (dwarf_getlocation (&call_attr, &call_ops, &call_len) != 0)
351 error (EXIT_FAILURE, 0, "dwarf_getlocation for entry: %s",
354 printf ("%s([%" PRIx64 "]) ", opname, dwarf_dieoffset (&call_die));
355 print_expr_block (&call_attr, call_ops, call_len, addr, depth);
366 case DW_OP_breg0 ... DW_OP_breg31:
367 /* 1 numeric signed argument. */
368 printf ("%s(%" PRId64 ")", opname, (Dwarf_Sword) expr->number);
372 /* 1 numeric signed argument. Offset from frame base. */
374 error (EXIT_FAILURE, 0, "%s used in CFI", opname);
376 if (! has_frame_base)
377 error (EXIT_FAILURE, 0, "DW_OP_fbreg used without a frame base");
379 printf ("%s(%" PRId64 ")", opname, (Dwarf_Sword) expr->number);
383 /* 2 arguments, unsigned register number, signed offset. */
384 printf ("%s(%" PRIu64 ",%" PRId64 ")", opname,
385 expr->number, (Dwarf_Sword) expr->number2);
388 case DW_OP_bit_piece:
389 /* 2 arguments, unsigned size, unsigned offset. */
390 printf ("%s(%" PRIu64 ",%" PRIu64 ")", opname,
391 expr->number, expr->number2);
394 case DW_OP_implicit_value:
395 /* Special, unsigned size plus block. */
397 Dwarf_Attribute const_attr;
399 if (dwarf_getlocation_attr (attr, expr, &const_attr) != 0)
400 error (EXIT_FAILURE, 0, "dwarf_getlocation_attr: %s",
403 if (dwarf_formblock (&const_attr, &block) != 0)
404 error (EXIT_FAILURE, 0, "dwarf_formblock: %s",
407 /* This is the "old" way. Check they result in the same. */
408 Dwarf_Block block_impl;
409 if (dwarf_getlocation_implicit_value (attr, expr, &block_impl) != 0)
410 error (EXIT_FAILURE, 0, "dwarf_getlocation_implicit_value: %s",
413 assert (expr->number == block.length);
414 assert (block.length == block_impl.length);
415 printf ("%s(%" PRIu64 "){", opname, block.length);
416 for (size_t i = 0; i < block.length; i++)
418 printf ("%02x", block.data[i]);
419 assert (block.data[i] == block_impl.data[i]);
425 case DW_OP_implicit_pointer:
426 case DW_OP_GNU_implicit_pointer:
427 /* Special, DIE offset, signed offset. Referenced DIE has a
428 location or const_value attribute. */
431 error (EXIT_FAILURE, 0, "%s used in CFI", opname);
433 Dwarf_Attribute attrval;
434 if (dwarf_getlocation_implicit_pointer (attr, expr, &attrval) != 0)
435 error (EXIT_FAILURE, 0, "dwarf_getlocation_implicit_pointer: %s",
438 // Sanity check, results should be the same.
439 Dwarf_Attribute attrval2;
440 if (dwarf_getlocation_attr (attr, expr, &attrval2) != 0)
441 error (EXIT_FAILURE, 0, "dwarf_getlocation_attr: %s",
444 assert (dwarf_whatattr (&attrval) == dwarf_whatattr (&attrval2));
445 assert (dwarf_whatform (&attrval) == dwarf_whatform (&attrval2));
446 // In theory two different valp pointers could point to the same
447 // value. But here we really expect them to be the equal.
448 assert (attrval.valp == attrval2.valp);
451 if (dwarf_getlocation_die (attr, expr, &impl_die) != 0)
452 error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
455 printf ("%s([%" PRIx64 "],%" PRId64 ") ", opname,
456 dwarf_dieoffset (&impl_die), expr->number2);
458 if (dwarf_whatattr (&attrval) == DW_AT_const_value)
459 printf ("<constant value>"); // Lookup type...
462 // Lookup the location description at the current address.
465 int locs = dwarf_getlocation_addr (&attrval, addr,
466 &exprval, &exprval_len, 1);
468 printf ("<no location>"); // This means "optimized out".
470 print_expr_block (&attrval, exprval, exprval_len, addr, depth);
472 error (EXIT_FAILURE, 0,
473 "dwarf_getlocation_addr attrval at addr 0x%" PRIx64
474 ", locs (%d): %s", addr, locs, dwarf_errmsg (-1));
479 case DW_OP_GNU_variable_value:
480 /* Special, DIE offset. Referenced DIE has a location or const_value
484 error (EXIT_FAILURE, 0, "%s used in CFI", opname);
486 Dwarf_Attribute attrval;
487 if (dwarf_getlocation_attr (attr, expr, &attrval) != 0)
488 error (EXIT_FAILURE, 0, "dwarf_getlocation_attr: %s",
492 if (dwarf_getlocation_die (attr, expr, &impl_die) != 0)
493 error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
496 printf ("%s([%" PRIx64 "]) ", opname, dwarf_dieoffset (&impl_die));
498 if (dwarf_whatattr (&attrval) == DW_AT_const_value)
499 printf ("<constant value>"); // Lookup type...
502 // Lookup the location description at the current address.
505 int locs = dwarf_getlocation_addr (&attrval, addr,
506 &exprval, &exprval_len, 1);
508 printf ("<no location>"); // This means "optimized out".
510 print_expr_block (&attrval, exprval, exprval_len, addr, depth);
512 error (EXIT_FAILURE, 0,
513 "dwarf_getlocation_addr attrval at addr 0x%" PRIx64
514 ", locs (%d): %s", addr, locs, dwarf_errmsg (-1));
519 case DW_OP_entry_value:
520 case DW_OP_GNU_entry_value:
521 /* Special, unsigned size plus expression block. All registers
522 inside the block should be interpreted as they had on
523 entering the function. dwarf_getlocation_attr will return an
524 attribute containing the block as locexpr which can be
525 retrieved with dwarf_getlocation. */
527 Dwarf_Attribute entry_attr;
528 if (dwarf_getlocation_attr (attr, expr, &entry_attr) != 0)
529 error (EXIT_FAILURE, 0, "dwarf_getlocation_attr: %s",
534 if (dwarf_getlocation (&entry_attr, &entry_ops, &entry_len) != 0)
535 error (EXIT_FAILURE, 0, "dwarf_getlocation for entry: %s",
538 printf ("%s(%zd) ", opname, entry_len);
539 print_expr_block (attr, entry_ops, entry_len, addr, depth);
543 case DW_OP_GNU_parameter_ref:
544 /* Special, unsigned CU relative DIE offset pointing to a
545 DW_TAG_formal_parameter. The value that parameter had at the
546 call site of the current function will be put on the DWARF
547 stack. The value can be retrieved by finding the
548 DW_TAG_GNU_call_site_parameter which has as
549 DW_AT_abstract_origin the same formal parameter DIE. */
552 if (dwarf_getlocation_die (attr, expr, ¶m) != 0)
553 error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
555 // XXX actually lookup DW_TAG_GNU_call_site_parameter
556 printf ("%s[%" PRIx64 "]", opname, dwarf_dieoffset (¶m));
557 assert (expr->number == dwarf_cuoffset (¶m));
558 if (dwarf_tag (¶m) != DW_TAG_formal_parameter)
559 error (EXIT_FAILURE, 0, "Not a formal parameter");
564 case DW_OP_GNU_convert:
565 case DW_OP_reinterpret:
566 case DW_OP_GNU_reinterpret:
567 /* Special, unsigned CU relative DIE offset pointing to a
568 DW_TAG_base_type. Pops a value, converts or reinterprets the
569 value to the given type. When the argument is zero the value
570 becomes untyped again. */
573 Dwarf_Off off = expr->number;
576 if (dwarf_getlocation_die (attr, expr, &type) != 0)
577 error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
579 off = dwarf_dieoffset (&type);
580 assert (expr->number == dwarf_cuoffset (&type));
581 printf ("%s", opname);
582 print_base_type (&type);
585 printf ("%s[%" PRIu64 "]", opname, off);
590 case DW_OP_regval_type:
591 case DW_OP_GNU_regval_type:
592 /* Special, unsigned register number plus unsigned CU relative
593 DIE offset pointing to a DW_TAG_base_type. */
596 if (dwarf_getlocation_die (attr, expr, &type) != 0)
597 error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
599 assert (expr->number2 == dwarf_cuoffset (&type));
600 // XXX check size against base_type size?
601 printf ("%s(reg%" PRIu64 ")", opname, expr->number);
602 print_base_type (&type);
606 case DW_OP_deref_type:
607 case DW_OP_GNU_deref_type:
608 /* Special, unsigned size plus unsigned CU relative DIE offset
609 pointing to a DW_TAG_base_type. */
612 if (dwarf_getlocation_die (attr, expr, &type) != 0)
613 error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
615 assert (expr->number2 == dwarf_cuoffset (&type));
616 // XXX check size against base_type size?
617 printf ("%s(%" PRIu64 ")", opname, expr->number);
618 print_base_type (&type);
622 case DW_OP_xderef_type:
623 /* Special, unsigned size plus unsigned DIE offset
624 pointing to a DW_TAG_base_type. */
627 if (dwarf_getlocation_die (attr, expr, &type) != 0)
628 error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
630 // XXX check size against base_type size?
631 printf ("%s(%" PRIu64 ")", opname, expr->number);
632 print_base_type (&type);
636 case DW_OP_const_type:
637 case DW_OP_GNU_const_type:
638 /* Special, unsigned CU relative DIE offset pointing to a
639 DW_TAG_base_type, an unsigned size length plus a block with
640 the constant value. */
643 if (dwarf_getlocation_die (attr, expr, &type) != 0)
644 error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
646 assert (expr->number == dwarf_cuoffset (&type));
648 Dwarf_Attribute const_attr;
649 if (dwarf_getlocation_attr (attr, expr, &const_attr) != 0)
650 error (EXIT_FAILURE, 0, "dwarf_getlocation_attr for type: %s",
654 if (dwarf_formblock (&const_attr, &block) != 0)
655 error (EXIT_FAILURE, 0, "dwarf_formblock for type: %s",
658 printf ("%s", opname);
659 print_base_type (&type);
660 printf ("(%" PRIu64 ")[", block.length);
661 for (size_t i = 0; i < block.length; i++)
662 printf ("%02x", block.data[i]);
667 case DW_OP_GNU_addr_index:
669 /* Address from the .debug_addr section (indexed based on CU). */
671 Dwarf_Attribute addr_attr;
672 if (dwarf_getlocation_attr (attr, expr, &addr_attr) != 0)
673 error (EXIT_FAILURE, 0, "dwarf_getlocation_attr for addr: %s",
677 if (dwarf_formaddr (&addr_attr, &address) != 0)
678 error (EXIT_FAILURE, 0, "dwarf_formaddr address failed: %s",
681 printf ("addr: 0x%" PRIx64, address);
685 case DW_OP_GNU_const_index:
687 /* Constant from the .debug_addr section (indexed based on CU). */
689 Dwarf_Attribute addr_attr;
690 if (dwarf_getlocation_attr (attr, expr, &addr_attr) != 0)
691 error (EXIT_FAILURE, 0, "dwarf_getlocation_attr for addr: %s",
695 if (dwarf_formudata (&addr_attr, &constant) != 0)
696 error (EXIT_FAILURE, 0, "dwarf_formudata constant failed: %s",
699 printf ("const: 0x%" PRIx64, constant);
704 error (EXIT_FAILURE, 0, "unhandled opcode: DW_OP_%s (0x%x)",
709 /* Get all variables and print their value expressions. */
711 print_varlocs (Dwarf_Die *funcdie)
713 // Display frame base for function if it exists.
714 // Should be used for DW_OP_fbreg.
715 has_frame_base = dwarf_hasattr (funcdie, DW_AT_frame_base);
718 Dwarf_Attribute fb_attr;
719 if (dwarf_attr (funcdie, DW_AT_frame_base, &fb_attr) == NULL)
720 error (EXIT_FAILURE, 0, "dwarf_attr fb: %s", dwarf_errmsg (-1));
724 if (dwarf_getlocation (&fb_attr, &fb_expr, &fb_exprlen) == 0)
726 // Covers all of function.
728 if (dwarf_entrypc (funcdie, &entrypc) != 0)
729 error (EXIT_FAILURE, 0, "dwarf_entrypc: %s", dwarf_errmsg (-1));
731 printf (" frame_base: ");
733 printf ("XXX zero address"); // XXX bad DWARF?
735 print_expr_block (&fb_attr, fb_expr, fb_exprlen, entrypc, 0);
740 Dwarf_Addr base, start, end;
742 printf (" frame_base:\n");
743 while ((off = dwarf_getlocations (&fb_attr, off, &base,
745 &fb_expr, &fb_exprlen)) > 0)
747 printf (" (%" PRIx64 ",%" PRIx64 ") ", start, end);
748 print_expr_block (&fb_attr, fb_expr, fb_exprlen, start, 0);
753 error (EXIT_FAILURE, 0, "dwarf_getlocations fb: %s",
757 else if (dwarf_tag (funcdie) == DW_TAG_inlined_subroutine)
759 // See whether the subprogram we are inlined into has a frame
760 // base we should use.
762 int n = dwarf_getscopes_die (funcdie, &scopes);
764 error (EXIT_FAILURE, 0, "dwarf_getscopes_die: %s", dwarf_errmsg (-1));
767 if (dwarf_tag (&scopes[n]) == DW_TAG_subprogram
768 && dwarf_hasattr (&scopes[n], DW_AT_frame_base))
770 has_frame_base = true;
776 if (! dwarf_haschildren (funcdie))
780 int res = dwarf_child (funcdie, &child);
782 error (EXIT_FAILURE, 0, "dwarf_child: %s", dwarf_errmsg (-1));
784 /* We thought there was a child, but the child list was actually
785 empty. This isn't technically an error in the DWARF, but it is
786 certainly non-optimimal. */
792 int tag = dwarf_tag (&child);
793 if (tag == DW_TAG_variable || tag == DW_TAG_formal_parameter)
795 const char *what = tag == DW_TAG_variable ? "variable" : "parameter";
796 print_die (&child, what, 2);
798 if (dwarf_hasattr (&child, DW_AT_location))
800 Dwarf_Attribute attr;
801 if (dwarf_attr (&child, DW_AT_location, &attr) == NULL)
802 error (EXIT_FAILURE, 0, "dwarf_attr: %s", dwarf_errmsg (-1));
806 if (dwarf_getlocation (&attr, &expr, &exprlen) == 0)
808 // Covers all ranges of the function.
809 // Evaluate the expression block for each range.
810 ptrdiff_t offset = 0;
811 Dwarf_Addr base, begin, end;
814 offset = dwarf_ranges (funcdie, offset, &base,
817 error (EXIT_FAILURE, 0, "dwarf_ranges: %s",
825 ") <empty expression>\n", begin, end);
827 print_expr_block_addrs (&attr, begin, end,
834 error (EXIT_FAILURE, 0, "dwarf_ranges: %s",
839 Dwarf_Addr base, begin, end;
840 ptrdiff_t offset = 0;
841 while ((offset = dwarf_getlocations (&attr, offset,
843 &expr, &exprlen)) > 0)
845 printf (" (%" PRIx64 ",%" PRIx64
846 ") <empty range>\n", begin, end); // XXX report?
849 print_expr_block_addrs (&attr, begin, end,
852 // Extra sanity check for dwarf_getlocation_addr
853 // Must at least find one range for begin and end-1.
856 int locs = dwarf_getlocation_addr (&attr, begin,
860 locs = dwarf_getlocation_addr (&attr, end - 1,
867 error (EXIT_FAILURE, 0, "dwarf_getlocations: %s",
871 else if (dwarf_hasattr (&child, DW_AT_const_value))
873 printf (" <constant value>\n"); // Lookup type and print.
877 printf (" <no value>\n");
881 while (dwarf_siblingof (&child, &child) == 0);
885 handle_instance (Dwarf_Die *funcdie, void *arg __attribute__ ((unused)))
887 print_die (funcdie, "inlined function", 1);
888 print_varlocs (funcdie);
894 handle_function (Dwarf_Die *funcdie, void *arg __attribute__((unused)))
896 if (dwarf_func_inline (funcdie) > 0)
898 // abstract inline definition, find all inlined instances.
900 // Note this is convenient for listing all instances together
901 // so you can easily compare the location expressions describing
902 // the variables and parameters, but it isn't very efficient
903 // since it will walk the DIE tree multiple times.
904 if (dwarf_func_inline_instances (funcdie, &handle_instance, NULL) != 0)
905 error (EXIT_FAILURE, 0, "dwarf_func_inline_instances: %s",
910 // Contains actual code, not just a declaration?
912 if (dwarf_entrypc (funcdie, &entrypc) == 0)
914 print_die (funcdie, "function", 1);
915 print_varlocs (funcdie);
929 handle_attr (Dwarf_Attribute *attr, void *arg)
931 int depth = ((struct attr_arg *) arg)->depth;
932 Dwarf_Addr entrypc = ((struct attr_arg *) arg)->entrypc;
934 unsigned int code = dwarf_whatattr (attr);
935 unsigned int form = dwarf_whatform (attr);
937 printf ("%*s%s (%s)", depth * 2, "",
938 dwarf_attr_string (code), dwarf_form_string (form));
940 /* If we can get an DWARF expression (or location lists) from this
941 attribute we'll print it, otherwise we'll ignore it. But if
942 there is an error while the attribute has the "correct" form then
943 we'll report an error (we can only really check DW_FORM_exprloc
944 other forms can be ambiguous). */
947 bool printed = false;
948 int res = dwarf_getlocation (attr, &expr, &exprlen);
952 print_expr_block (attr, expr, exprlen, entrypc, 0);
956 else if (form == DW_FORM_exprloc)
958 error (0, 0, "%s dwarf_getlocation failed: %s",
959 dwarf_attr_string (code), dwarf_errmsg (-1));
960 return DWARF_CB_ABORT;
964 Dwarf_Addr base, begin, end;
965 ptrdiff_t offset = 0;
966 while ((offset = dwarf_getlocations (attr, offset,
968 &expr, &exprlen)) > 0)
972 printf ("%*s", depth * 2, "");
973 print_expr_block_addrs (attr, begin, end, expr, exprlen);
985 handle_die (Dwarf_Die *die, int depth, bool outer_has_frame_base,
986 Dwarf_Addr outer_entrypc)
988 /* CU DIE already printed. */
991 const char *name = dwarf_diename (die);
993 printf ("%*s[%" PRIx64 "] %s \"%s\"\n", depth * 2, "",
994 dwarf_dieoffset (die), dwarf_tag_string (dwarf_tag (die)),
997 printf ("%*s[%" PRIx64 "] %s\n", depth * 2, "",
998 dwarf_dieoffset (die), dwarf_tag_string (dwarf_tag (die)));
1001 struct attr_arg arg;
1002 arg.depth = depth + 1;
1004 /* The (lowest) address to use for (looking up) operands that depend
1006 Dwarf_Addr die_entrypc;
1007 if (dwarf_entrypc (die, &die_entrypc) != 0 || die_entrypc == 0)
1009 /* Try to get the lowest address of the first range covered. */
1010 Dwarf_Addr base, start, end;
1011 if (dwarf_ranges (die, 0, &base, &start, &end) <= 0 || start == 0)
1012 die_entrypc = outer_entrypc;
1014 die_entrypc = start;
1016 arg.entrypc = die_entrypc;
1018 /* Whether this or the any outer DIE has a frame base. Used as
1019 sanity check when printing expressions that use DW_OP_fbreg. */
1020 bool die_has_frame_base = dwarf_hasattr (die, DW_AT_frame_base);
1021 die_has_frame_base |= outer_has_frame_base;
1022 has_frame_base = die_has_frame_base;
1024 /* Look through all attributes to find those that contain DWARF
1025 expressions and print those. We expect to handle all attributes,
1026 anything else is an error. */
1027 if (dwarf_getattrs (die, handle_attr, &arg, 0) != 1)
1028 error (EXIT_FAILURE, 0, "Couldn't get all attributes: %s",
1031 /* Handle children and siblings recursively depth first. */
1033 if (dwarf_haschildren (die) != 0 && dwarf_child (die, &child) == 0)
1034 handle_die (&child, depth + 1, die_has_frame_base, die_entrypc);
1037 if (dwarf_siblingof (die, &sibling) == 0)
1038 handle_die (&sibling, depth, outer_has_frame_base, outer_entrypc);
1042 main (int argc, char *argv[])
1044 /* With --exprlocs we process all DIEs looking for any attribute
1045 which contains an DWARF expression (but not location lists) and
1046 print those. Otherwise we process all function DIEs and print
1047 all DWARF expressions and location lists associated with
1048 parameters and variables). It must be the first argument,
1049 or the second, after --debug. */
1050 bool exprlocs = false;
1052 /* With --debug we ignore not being able to find .eh_frame.
1053 It must come as first argument. */
1057 if (strcmp ("--exprlocs", argv[1]) == 0)
1062 else if (strcmp ("--debug", argv[1]) == 0)
1071 if (strcmp ("--exprlocs", argv[2]) == 0)
1080 (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining,
1082 assert (dwfl != NULL);
1084 Dwarf_Die *cu = NULL;
1086 bool found_cu = false;
1087 while ((cu = dwfl_nextcu (dwfl, cu, &dwbias)) != NULL)
1089 /* Only walk actual compile units (not partial units) that
1090 contain code if we are only interested in the function variable
1095 if (dwarf_cu_info (cu->cu, NULL, &unit_type, &cudie, &subdie,
1096 NULL, NULL, NULL) != 0)
1097 error (EXIT_FAILURE, 0, "dwarf_cu_info: %s", dwarf_errmsg (-1));
1098 if (unit_type == DW_UT_skeleton)
1102 if (dwarf_tag (&cudie) == DW_TAG_compile_unit
1103 && (exprlocs || dwarf_lowpc (&cudie, &cubase) == 0))
1107 Dwfl_Module *mod = dwfl_cumodule (cu);
1109 dw = dwfl_module_getdwarf (mod, &modbias);
1110 assert (dwbias == modbias);
1112 const char *mainfile;
1113 const char *modname = dwfl_module_info (mod, NULL,
1118 if (modname == NULL)
1119 error (EXIT_FAILURE, 0, "dwfl_module_info: %s", dwarf_errmsg (-1));
1121 const char *name = (modname[0] != '\0'
1123 : basename (mainfile));
1124 printf ("module '%s'\n", name);
1125 print_die (&cudie, "CU", 0);
1128 Elf *elf = dwfl_module_getelf (mod, &elfbias);
1130 // CFI. We need both since sometimes neither is complete.
1131 cfi_debug = dwfl_module_dwarf_cfi (mod, &cfi_debug_bias);
1132 cfi_eh = dwfl_module_eh_cfi (mod, &cfi_eh_bias);
1134 // No bias needed, same file.
1135 assert (cfi_debug == NULL || cfi_debug_bias == 0);
1137 // We are a bit forgiving for object files. There might be
1138 // relocations we don't handle that are needed in some
1140 GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (elf, &ehdr_mem);
1141 is_ET_REL = ehdr->e_type == ET_REL;
1146 if (dwarf_entrypc (&cudie, &entrypc) != 0)
1149 /* XXX - Passing true for has_frame_base is not really true.
1150 We do it because we want to resolve all DIEs and all
1151 attributes. Technically we should check that the DIE
1152 (types) are referenced from variables that are defined in
1153 a context (function) that has a frame base. */
1154 handle_die (&cudie, 0, true /* Should be false */, entrypc);
1156 else if (dwarf_getfuncs (&cudie, handle_function, NULL, 0) != 0)
1157 error (EXIT_FAILURE, 0, "dwarf_getfuncs %s",
1163 error (EXIT_FAILURE, 0, "No DWARF CU found?");