1 /* Test program for dwarf location functions.
2 Copyright (C) 2013 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)
30 #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.
43 Dwarf_Addr cfi_eh_bias;
45 // Whether the current function has a DW_AT_frame_base defined.
46 // Needed for DW_OP_fbreg.
50 print_die (Dwarf_Die *die, const char *what, int indent)
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);
58 printf ("%*s[%" PRIx64 "] %s '%s'\n", indent * 2, "",
59 dwarf_dieoffset (die), what, name);
63 dwarf_encoding_string (unsigned int code)
65 static const char *const known[] =
67 #define ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME,
69 #undef ONE_KNOWN_DW_ATE
72 if (likely (code < sizeof (known) / sizeof (known[0])))
78 /* BASE must be a base type DIE referenced by a typed DWARF expression op. */
80 print_base_type (Dwarf_Die *base)
82 assert (dwarf_tag (base) == DW_TAG_base_type);
84 Dwarf_Attribute encoding;
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");
90 Dwarf_Attribute bsize;
92 if (dwarf_attr (base, DW_AT_byte_size, &bsize) != NULL
93 && dwarf_formudata (&bsize, &bits) == 0)
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");
99 printf ("{%s,%s,%" PRIu64 "@[%" PRIx64 "]}",
100 dwarf_diename (base),
101 dwarf_encoding_string (enctype),
103 dwarf_dieoffset (base));
107 dwarf_opcode_string (unsigned int code)
109 static const char *const known[] =
111 #define ONE_KNOWN_DW_OP_DESC(NAME, CODE, DESC) ONE_KNOWN_DW_OP (NAME, CODE)
112 #define ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
114 #undef ONE_KNOWN_DW_OP
115 #undef ONE_KNOWN_DW_OP_DESC
118 if (likely (code < sizeof (known) / sizeof (known[0])))
124 // Forward reference for print_expr_block.
125 static void print_expr (Dwarf_Attribute *, Dwarf_Op *, Dwarf_Addr);
128 print_expr_block (Dwarf_Attribute *attr, Dwarf_Op *exprs, int len,
132 for (int i = 0; i < len; i++)
134 print_expr (attr, &exprs[i], addr);
135 printf ("%s", (i + 1 < len ? ", " : ""));
141 print_expr_block_addrs (Dwarf_Attribute *attr,
142 Dwarf_Addr begin, Dwarf_Addr end,
143 Dwarf_Op *exprs, int len)
145 printf (" [%" PRIx64 ",%" PRIx64 ") ", begin, end);
146 print_expr_block (attr, exprs, len, begin);
151 print_expr (Dwarf_Attribute *attr, Dwarf_Op *expr, Dwarf_Addr addr)
153 uint8_t atom = expr->atom;
154 const char *opname = dwarf_opcode_string (atom);
155 assert (opname != NULL);
186 case DW_OP_lit0 ... DW_OP_lit31:
187 case DW_OP_reg0 ... DW_OP_reg31:
189 case DW_OP_stack_value:
191 printf ("%s", opname);
194 case DW_OP_form_tls_address:
195 /* No arguments. Special. Pops an address and pushes the
196 corresponding address in the current thread local
197 storage. Uses the thread local storage block of the defining
198 module (executable, shared library). */
199 printf ("%s", opname);
202 case DW_OP_GNU_push_tls_address:
203 /* No arguments. Special. Not the same as DW_OP_form_tls_address.
204 Pops an offset into the current thread local strorage and
205 pushes back the actual address. */
206 printf ("%s", opname);
209 case DW_OP_call_frame_cfa:
210 /* No arguments. Special. Pushes Call Frame Address as computed
211 by CFI data (dwarf_cfi_addrframe will fetch that info (either from
212 the .eh_frame or .debug_frame CFI) and dwarf_frame_cfa translatesr
213 the CFI instructions into a plain DWARF expression.
214 Never used in CFI itself. */
217 error (EXIT_FAILURE, 0, "%s used in CFI", opname);
219 printf ("%s ", opname);
220 if (cfi_eh == NULL && cfi_debug == NULL)
221 error (EXIT_FAILURE, 0, "DW_OP_call_frame_cfa used but no cfi found.");
224 if (dwarf_cfi_addrframe (cfi_eh, addr + cfi_eh_bias, &frame) != 0
225 && dwarf_cfi_addrframe (cfi_debug, addr, &frame) != 0)
226 error (EXIT_FAILURE, 0, "dwarf_cfi_addrframe 0x%" PRIx64 ": %s",
227 addr, dwarf_errmsg (-1));
231 if (dwarf_frame_cfa (frame, &cfa_ops, &cfa_nops) != 0)
232 error (EXIT_FAILURE, 0, "dwarf_frame_cfa 0x%" PRIx64 ": %s",
233 addr, dwarf_errmsg (-1));
235 error (EXIT_FAILURE, 0, "dwarf_frame_cfa no ops");
236 print_expr_block (NULL, cfa_ops, cfa_nops, 0);
240 case DW_OP_push_object_address:
241 /* No arguments. Special. Pushes object address explicitly.
242 Normally only done implicitly by DW_AT_data_member_location.
243 Never used in CFI. */
245 error (EXIT_FAILURE, 0, "%s used in CFI", opname);
246 printf ("%s", opname);
250 /* 1 address argument. */
251 printf ("%s(0x%" PRIx64 ")", opname, (Dwarf_Addr) expr->number);
260 case DW_OP_plus_uconst:
263 case DW_OP_deref_size:
264 case DW_OP_xderef_size:
265 /* 1 numeric unsigned argument. */
266 printf ("%s(%" PRIu64 ")", opname, expr->number);
272 /* 1 DIE offset argument for more ops in location attribute of DIE.
273 Never used in CFI. */
276 error (EXIT_FAILURE, 0, "%s used in CFI", opname);
278 Dwarf_Attribute call_attr;
279 if (dwarf_getlocation_attr (attr, expr, &call_attr) != 0)
280 error (EXIT_FAILURE, 0, "dwarf_getlocation_attr for %s error %s",
281 opname, dwarf_errmsg (-1));
284 if (dwarf_getlocation_die (attr, expr, &call_die) != 0)
285 error (EXIT_FAILURE, 0, "dwarf_getlocation_die for %s error %s",
286 opname, dwarf_errmsg (-1));
290 if (dwarf_getlocation (&call_attr, &call_ops, &call_len) != 0)
291 error (EXIT_FAILURE, 0, "dwarf_getlocation for entry: %s",
294 printf ("%s([%" PRIx64 "]) ", opname, dwarf_dieoffset (&call_die));
295 print_expr_block (&call_attr, call_ops, call_len, addr);
306 case DW_OP_breg0 ... DW_OP_breg31:
307 /* 1 numeric signed argument. */
308 printf ("%s(%" PRId64 ")", opname, (Dwarf_Sword) expr->number);
312 /* 1 numeric signed argument. Offset from frame base. */
314 error (EXIT_FAILURE, 0, "%s used in CFI", opname);
316 if (! has_frame_base)
317 error (EXIT_FAILURE, 0, "DW_OP_fbreg used without a frame base");
319 printf ("%s(%" PRId64 ")", opname, (Dwarf_Sword) expr->number);
323 /* 2 arguments, unsigned register number, signed offset. */
324 printf ("%s(%" PRIu64 ",%" PRId64 ")", opname,
325 expr->number, (Dwarf_Sword) expr->number2);
328 case DW_OP_bit_piece:
329 /* 2 arguments, unsigned size, unsigned offset. */
330 printf ("%s(%" PRIu64 ",%" PRIu64 ")", opname,
331 expr->number, expr->number2);
334 case DW_OP_implicit_value:
335 /* Special, unsigned size plus block. */
337 Dwarf_Attribute const_attr;
339 if (dwarf_getlocation_attr (attr, expr, &const_attr) != 0)
340 error (EXIT_FAILURE, 0, "dwarf_getlocation_attr: %s",
343 if (dwarf_formblock (&const_attr, &block) != 0)
344 error (EXIT_FAILURE, 0, "dwarf_formblock: %s",
347 /* This is the "old" way. Check they result in the same. */
348 Dwarf_Block block_impl;
349 if (dwarf_getlocation_implicit_value (attr, expr, &block_impl) != 0)
350 error (EXIT_FAILURE, 0, "dwarf_getlocation_implicit_value: %s",
353 assert (expr->number == block.length);
354 assert (block.length == block_impl.length);
355 printf ("%s(%" PRIu64 "){", opname, block.length);
356 for (size_t i = 0; i < block.length; i++)
358 printf ("%02x", block.data[i]);
359 assert (block.data[i] == block_impl.data[i]);
365 case DW_OP_GNU_implicit_pointer:
366 /* Special, DIE offset, signed offset. Referenced DIE has a
367 location or const_value attribute. */
370 error (EXIT_FAILURE, 0, "%s used in CFI", opname);
372 Dwarf_Attribute attrval;
373 if (dwarf_getlocation_implicit_pointer (attr, expr, &attrval) != 0)
374 error (EXIT_FAILURE, 0, "dwarf_getlocation_implicit_pointer: %s",
377 // Sanity check, results should be the same.
378 Dwarf_Attribute attrval2;
379 if (dwarf_getlocation_attr (attr, expr, &attrval2) != 0)
380 error (EXIT_FAILURE, 0, "dwarf_getlocation_attr: %s",
383 assert (dwarf_whatattr (&attrval) == dwarf_whatattr (&attrval2));
384 assert (dwarf_whatform (&attrval) == dwarf_whatform (&attrval2));
385 // In theory two different valp pointers could point to the same
386 // value. But here we really expect them to be the equal.
387 assert (attrval.valp == attrval2.valp);
390 if (dwarf_getlocation_die (attr, expr, &impl_die) != 0)
391 error (EXIT_FAILURE, 0, "dwarf_getlocation_due: %s",
394 printf ("%s([%" PRIx64 "],%" PRId64 ") ", opname,
395 dwarf_dieoffset (&impl_die), expr->number2);
397 if (dwarf_whatattr (&attrval) == DW_AT_const_value)
398 printf ("<constant value>"); // Lookup type...
401 // Lookup the location description at the current address.
404 int locs = dwarf_getlocation_addr (&attrval, addr,
405 &exprval, &exprval_len, 1);
407 printf ("<no location>"); // This means "optimized out".
409 print_expr_block (&attrval, exprval, exprval_len, addr);
411 error (EXIT_FAILURE, 0,
412 "dwarf_getlocation_addr attrval at addr 0x%" PRIx64
413 ", locs (%d): %s", addr, locs, dwarf_errmsg (-1));
418 case DW_OP_GNU_entry_value:
419 /* Special, unsigned size plus expression block. All registers
420 inside the block should be interpreted as they had on
421 entering the function. dwarf_getlocation_attr will return an
422 attribute containing the block as locexpr which can be
423 retrieved with dwarf_getlocation. */
425 Dwarf_Attribute entry_attr;
426 if (dwarf_getlocation_attr (attr, expr, &entry_attr) != 0)
427 error (EXIT_FAILURE, 0, "dwarf_getlocation_attr: %s",
432 if (dwarf_getlocation (&entry_attr, &entry_ops, &entry_len) != 0)
433 error (EXIT_FAILURE, 0, "dwarf_getlocation for entry: %s",
436 printf ("%s(%zd) ", opname, entry_len);
437 print_expr_block (attr, entry_ops, entry_len, addr);
441 case DW_OP_GNU_parameter_ref:
442 /* Special, unsigned CU relative DIE offset pointing to a
443 DW_TAG_formal_parameter. The value that parameter had at the
444 call site of the current function will be put on the DWARF
445 stack. The value can be retrieved by finding the
446 DW_TAG_GNU_call_site_parameter which has as
447 DW_AT_abstract_origin the same formal parameter DIE. */
450 if (dwarf_getlocation_die (attr, expr, ¶m) != 0)
451 error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
453 // XXX actually lookup DW_TAG_GNU_call_site_parameter
454 printf ("%s[%" PRIx64 "]", opname, dwarf_dieoffset (¶m));
455 assert (expr->number == dwarf_cuoffset (¶m));
456 assert (dwarf_tag (¶m) == DW_TAG_formal_parameter);
460 case DW_OP_GNU_convert:
461 case DW_OP_GNU_reinterpret:
462 /* Special, unsigned CU relative DIE offset pointing to a
463 DW_TAG_base_type. Pops a value, converts or reinterprets the
464 value to the given type. When the argument is zero the value
465 becomes untyped again. */
468 Dwarf_Off off = expr->number;
471 if (dwarf_getlocation_die (attr, expr, &type) != 0)
472 error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
474 off = dwarf_dieoffset (&type);
475 assert (expr->number == dwarf_cuoffset (&type));
476 printf ("%s", opname);
477 print_base_type (&type);
480 printf ("%s[%" PRIu64 "]", opname, off);
485 case DW_OP_GNU_regval_type:
486 /* Special, unsigned register number plus unsigned CU relative
487 DIE offset pointing to a DW_TAG_base_type. */
490 if (dwarf_getlocation_die (attr, expr, &type) != 0)
491 error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
493 assert (expr->number2 == dwarf_cuoffset (&type));
494 // XXX check size against base_type size?
495 printf ("%s(reg%" PRIu64 ")", opname, expr->number);
496 print_base_type (&type);
500 case DW_OP_GNU_deref_type:
501 /* Special, unsigned size plus unsigned CU relative DIE offset
502 pointing to a DW_TAG_base_type. */
505 if (dwarf_getlocation_die (attr, expr, &type) != 0)
506 error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
508 assert (expr->number2 == dwarf_cuoffset (&type));
509 // XXX check size against base_type size?
510 printf ("%s(%" PRIu64 ")", opname, expr->number);
511 print_base_type (&type);
515 case DW_OP_GNU_const_type:
516 /* Special, unsigned CU relative DIE offset pointing to a
517 DW_TAG_base_type, an unsigned size length plus a block with
518 the constant value. */
521 if (dwarf_getlocation_die (attr, expr, &type) != 0)
522 error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
524 assert (expr->number == dwarf_cuoffset (&type));
526 Dwarf_Attribute const_attr;
527 if (dwarf_getlocation_attr (attr, expr, &const_attr) != 0)
528 error (EXIT_FAILURE, 0, "dwarf_getlocation_attr for type: %s",
532 if (dwarf_formblock (&const_attr, &block) != 0)
533 error (EXIT_FAILURE, 0, "dwarf_formblock for type: %s",
536 printf ("%s", opname);
537 print_base_type (&type);
538 printf ("(%" PRIu64 ")[", block.length);
539 for (size_t i = 0; i < block.length; i++)
540 printf ("%02x", block.data[i]);
546 error (EXIT_FAILURE, 0, "unhandled opcode: DW_OP_%s (0x%x)",
551 /* Get all variables and print their value expressions. */
553 print_varlocs (Dwarf_Die *funcdie)
555 // Display frame base for function if it exists.
556 // Should be used for DW_OP_fbreg.
557 has_frame_base = dwarf_hasattr (funcdie, DW_AT_frame_base);
560 Dwarf_Attribute fb_attr;
561 if (dwarf_attr (funcdie, DW_AT_frame_base, &fb_attr) == NULL)
562 error (EXIT_FAILURE, 0, "dwarf_attr fb: %s", dwarf_errmsg (-1));
566 if (dwarf_getlocation (&fb_attr, &fb_expr, &fb_exprlen) == 0)
568 // Covers all of function.
570 if (dwarf_entrypc (funcdie, &entrypc) != 0)
571 error (EXIT_FAILURE, 0, "dwarf_entrypc: %s", dwarf_errmsg (-1));
573 printf (" frame_base: ");
575 printf ("XXX zero address"); // XXX bad DWARF?
577 print_expr_block (&fb_attr, fb_expr, fb_exprlen, entrypc);
582 Dwarf_Addr base, start, end;
584 printf (" frame_base:\n");
585 while ((off = dwarf_getlocations (&fb_attr, off, &base,
587 &fb_expr, &fb_exprlen)) > 0)
589 printf (" (%" PRIx64 ",%" PRIx64 ") ", start, end);
590 print_expr_block (&fb_attr, fb_expr, fb_exprlen, start);
595 error (EXIT_FAILURE, 0, "dwarf_getlocations fb: %s",
599 else if (dwarf_tag (funcdie) == DW_TAG_inlined_subroutine)
601 // See whether the subprogram we are inlined into has a frame
602 // base we should use.
604 int n = dwarf_getscopes_die (funcdie, &scopes);
606 error (EXIT_FAILURE, 0, "dwarf_getscopes_die: %s", dwarf_errmsg (-1));
609 if (dwarf_tag (&scopes[n]) == DW_TAG_subprogram
610 && dwarf_hasattr (&scopes[n], DW_AT_frame_base))
612 has_frame_base = true;
618 if (! dwarf_haschildren (funcdie))
622 int res = dwarf_child (funcdie, &child);
624 error (EXIT_FAILURE, 0, "dwarf_child: %s", dwarf_errmsg (-1));
626 /* We thought there was a child, but the child list was actually
627 empty. This isn't technically an error in the DWARF, but it is
628 certainly non-optimimal. */
634 int tag = dwarf_tag (&child);
635 if (tag == DW_TAG_variable || tag == DW_TAG_formal_parameter)
637 const char *what = tag == DW_TAG_variable ? "variable" : "parameter";
638 print_die (&child, what, 2);
640 if (dwarf_hasattr (&child, DW_AT_location))
642 Dwarf_Attribute attr;
643 if (dwarf_attr (&child, DW_AT_location, &attr) == NULL)
644 error (EXIT_FAILURE, 0, "dwarf_attr: %s", dwarf_errmsg (-1));
648 if (dwarf_getlocation (&attr, &expr, &exprlen) == 0)
650 // Covers all ranges of the function.
651 // Evaluate the expression block for each range.
652 ptrdiff_t offset = 0;
653 Dwarf_Addr base, begin, end;
656 offset = dwarf_ranges (funcdie, offset, &base,
659 error (EXIT_FAILURE, 0, "dwarf_ranges: %s",
667 ") <empty expression>\n", begin, end);
669 print_expr_block_addrs (&attr, begin, end,
676 error (EXIT_FAILURE, 0, "dwarf_ranges: %s",
681 Dwarf_Addr base, begin, end;
682 ptrdiff_t offset = 0;
683 while ((offset = dwarf_getlocations (&attr, offset,
685 &expr, &exprlen)) > 0)
687 printf (" (%" PRIx64 ",%" PRIx64
688 ") <empty range>\n", begin, end); // XXX report?
691 print_expr_block_addrs (&attr, begin, end,
694 // Extra sanity check for dwarf_getlocation_addr
695 // Must at least find one range for begin and end-1.
698 int locs = dwarf_getlocation_addr (&attr, begin,
702 locs = dwarf_getlocation_addr (&attr, end - 1,
709 error (EXIT_FAILURE, 0, "dwarf_getlocations: %s",
713 else if (dwarf_hasattr (&child, DW_AT_const_value))
715 printf (" <constant value>\n"); // Lookup type and print.
719 printf (" <no value>\n");
723 while (dwarf_siblingof (&child, &child) == 0);
727 handle_instance (Dwarf_Die *funcdie, void *arg __attribute__ ((unused)))
729 print_die (funcdie, "inlined function", 1);
730 print_varlocs (funcdie);
736 handle_function (Dwarf_Die *funcdie, void *arg __attribute__((unused)))
738 if (dwarf_func_inline (funcdie) > 0)
740 // abstract inline definition, find all inlined instances.
742 // Note this is convenient for listing all instances together
743 // so you can easily compare the location expressions describing
744 // the variables and parameters, but it isn't very efficient
745 // since it will walk the DIE tree multiple times.
746 if (dwarf_func_inline_instances (funcdie, &handle_instance, NULL) != 0)
747 error (EXIT_FAILURE, 0, "dwarf_func_inline_instances: %s",
752 // Contains actual code, not just a declaration?
754 if (dwarf_entrypc (funcdie, &entrypc) == 0)
756 print_die (funcdie, "function", 1);
757 print_varlocs (funcdie);
765 main (int argc, char *argv[])
769 (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining,
771 assert (dwfl != NULL);
773 Dwarf_Die *cu = NULL;
775 while ((cu = dwfl_nextcu (dwfl, cu, &dwbias)) != NULL)
777 /* Only walk actual compile units (not partial units) that
780 if (dwarf_tag (cu) == DW_TAG_compile_unit
781 && dwarf_lowpc (cu, &cubase) == 0)
783 Dwfl_Module *mod = dwfl_cumodule (cu);
785 dw = dwfl_module_getdwarf (mod, &modbias);
786 assert (dwbias == modbias);
788 const char *mainfile;
789 const char *modname = dwfl_module_info (mod, NULL,
795 error (EXIT_FAILURE, 0, "dwfl_module_info: %s", dwarf_errmsg (-1));
797 const char *name = (modname[0] != '\0'
799 : basename (mainfile));
800 printf ("module '%s'\n", name);
801 print_die (cu, "CU", 0);
804 Elf *elf = dwfl_module_getelf (mod, &elfbias);
806 // CFI. We need both since sometimes neither is complete.
807 cfi_debug = dwarf_getcfi (dw); // No bias needed, same file.
808 cfi_eh = dwarf_getcfi_elf (elf);
809 cfi_eh_bias = dwbias - elfbias;
811 // Get the actual CU DIE and walk all functions inside it.
815 if (dwarf_diecu (cu, &cudie, &addrsize, &offsize) == NULL)
816 error (EXIT_FAILURE, 0, "dwarf_diecu %s", dwarf_errmsg (-1));
818 if (dwarf_getfuncs (cu, handle_function, NULL, 0) != 0)
819 error (EXIT_FAILURE, 0, "dwarf_getfuncs %s",