• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Test program for dwarf location functions.
2    Copyright (C) 2013, 2015, 2017, 2018 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 <string.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33 
34 #include "system.h"
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_Addr cfi_debug_bias;
43 Dwarf_CFI *cfi_eh;
44 Dwarf_Addr cfi_eh_bias;
45 
46 bool is_ET_REL;
47 bool is_debug;
48 
49 // Whether the current function has a DW_AT_frame_base defined.
50 // Needed for DW_OP_fbreg.
51 bool has_frame_base;
52 
53 static void
print_die(Dwarf_Die * die,const char * what,int indent)54 print_die (Dwarf_Die *die, const char *what, int indent)
55 {
56   Dwarf_Addr entrypc;
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);
61   else
62     printf ("%*s[%" PRIx64 "] %s '%s'\n", indent * 2, "",
63 	    dwarf_dieoffset (die), what, name);
64 }
65 
66 static const char *
dwarf_encoding_string(unsigned int code)67 dwarf_encoding_string (unsigned int code)
68 {
69   static const char *const known[] =
70     {
71 #define DWARF_ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME,
72       DWARF_ALL_KNOWN_DW_ATE
73 #undef DWARF_ONE_KNOWN_DW_ATE
74     };
75 
76   if (likely (code < sizeof (known) / sizeof (known[0])))
77     return known[code];
78 
79   return "<unknown encoding>";
80 }
81 
82 static const char *
dwarf_tag_string(unsigned int tag)83 dwarf_tag_string (unsigned int tag)
84 {
85   switch (tag)
86     {
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
90     default:
91       return "<unknown tag>";
92     }
93 }
94 
95 static const char *
dwarf_attr_string(unsigned int attrnum)96 dwarf_attr_string (unsigned int attrnum)
97 {
98   switch (attrnum)
99     {
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
103     default:
104       return "<unknown attr>";
105     }
106 }
107 
108 static const char *
dwarf_form_string(unsigned int form)109 dwarf_form_string (unsigned int form)
110 {
111   switch (form)
112     {
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
116     default:
117       return "<unknown form>";
118     }
119 }
120 
121 /* BASE must be a base type DIE referenced by a typed DWARF expression op.  */
122 static void
print_base_type(Dwarf_Die * base)123 print_base_type (Dwarf_Die *base)
124 {
125   if (dwarf_tag (base) != DW_TAG_base_type)
126     error (EXIT_FAILURE, 0, "not a base type");
127 
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");
133 
134   Dwarf_Attribute bsize;
135   Dwarf_Word bits;
136   if (dwarf_attr (base, DW_AT_byte_size, &bsize) != NULL
137       && dwarf_formudata (&bsize, &bits) == 0)
138     bits *= 8;
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");
142 
143   printf ("{%s,%s,%" PRIu64 "@[%" PRIx64 "]}",
144 	  dwarf_diename (base),
145 	  dwarf_encoding_string (enctype),
146 	  bits,
147 	  dwarf_dieoffset (base));
148 }
149 
150 static const char *
dwarf_opcode_string(unsigned int code)151 dwarf_opcode_string (unsigned int code)
152 {
153   static const char *const known[] =
154     {
155 #define DWARF_ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
156       DWARF_ALL_KNOWN_DW_OP
157 #undef DWARF_ONE_KNOWN_DW_OP
158     };
159 
160   if (likely (code < sizeof (known) / sizeof (known[0])))
161     return known[code];
162 
163   return "<unknown opcode>";
164 }
165 
166 // Forward reference for print_expr_block.
167 static void print_expr (Dwarf_Attribute *, Dwarf_Op *, Dwarf_Addr, int);
168 
169 static void
print_expr_block(Dwarf_Attribute * attr,Dwarf_Op * exprs,int len,Dwarf_Addr addr,int depth)170 print_expr_block (Dwarf_Attribute *attr, Dwarf_Op *exprs, int len,
171 		  Dwarf_Addr addr, int depth)
172 {
173   printf ("{");
174   for (int i = 0; i < len; i++)
175     {
176       print_expr (attr, &exprs[i], addr, depth);
177       printf ("%s", (i + 1 < len ? ", " : ""));
178     }
179   printf ("}");
180 }
181 
182 static void
print_expr_block_addrs(Dwarf_Attribute * attr,Dwarf_Addr begin,Dwarf_Addr end,Dwarf_Op * exprs,int len)183 print_expr_block_addrs (Dwarf_Attribute *attr,
184 			Dwarf_Addr begin, Dwarf_Addr end,
185 			Dwarf_Op *exprs, int len)
186 {
187   printf ("      [%" PRIx64 ",%" PRIx64 ") ", begin, end);
188   print_expr_block (attr, exprs, len, begin, 0);
189   printf ("\n");
190 }
191 
192 static void
print_expr(Dwarf_Attribute * attr,Dwarf_Op * expr,Dwarf_Addr addr,int depth)193 print_expr (Dwarf_Attribute *attr, Dwarf_Op *expr, Dwarf_Addr addr, int depth)
194 {
195 #define MAX_DEPTH 64
196   if (depth++ > MAX_DEPTH)
197     error (EXIT_FAILURE, 0, "print_expr recursion depth exceeded");
198 
199   uint8_t atom = expr->atom;
200   const char *opname = dwarf_opcode_string (atom);
201 
202   switch (atom)
203     {
204     case DW_OP_deref:
205     case DW_OP_dup:
206     case DW_OP_drop:
207     case DW_OP_over:
208     case DW_OP_swap:
209     case DW_OP_rot:
210     case DW_OP_xderef:
211     case DW_OP_abs:
212     case DW_OP_and:
213     case DW_OP_div:
214     case DW_OP_minus:
215     case DW_OP_mod:
216     case DW_OP_mul:
217     case DW_OP_neg:
218     case DW_OP_not:
219     case DW_OP_or:
220     case DW_OP_plus:
221     case DW_OP_shl:
222     case DW_OP_shr:
223     case DW_OP_shra:
224     case DW_OP_xor:
225     case DW_OP_eq:
226     case DW_OP_ge:
227     case DW_OP_gt:
228     case DW_OP_le:
229     case DW_OP_lt:
230     case DW_OP_ne:
231     case DW_OP_lit0 ... DW_OP_lit31:
232     case DW_OP_reg0 ... DW_OP_reg31:
233     case DW_OP_nop:
234     case DW_OP_stack_value:
235       /* No arguments. */
236       printf ("%s", opname);
237       break;
238 
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);
245       break;
246 
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);
252       break;
253 
254     case DW_OP_call_frame_cfa:
255       /* No arguments. Special. Pushes Call Frame Address as computed
256 	 by CFI data (dwarf_cfi_addrframe will fetch that info (either from
257 	 the .eh_frame or .debug_frame CFI) and dwarf_frame_cfa translatesr
258          the CFI instructions into a plain DWARF expression.
259 	 Never used in CFI itself. */
260 
261       if (attr == NULL)
262 	error (EXIT_FAILURE, 0, "%s used in CFI", opname);
263 
264       printf ("%s ", opname);
265       if (cfi_eh == NULL && cfi_debug == NULL && !is_debug)
266 	error (EXIT_FAILURE, 0, "DW_OP_call_frame_cfa used but no cfi found.");
267 
268       Dwarf_Frame *frame;
269       if (dwarf_cfi_addrframe (cfi_eh, addr + cfi_eh_bias, &frame) == 0
270 	  || dwarf_cfi_addrframe (cfi_debug, addr + cfi_debug_bias,
271 				  &frame) == 0)
272 	{
273 	  Dwarf_Op *cfa_ops;
274 	  size_t cfa_nops;
275 	  if (dwarf_frame_cfa (frame, &cfa_ops, &cfa_nops) != 0)
276 	    error (EXIT_FAILURE, 0, "dwarf_frame_cfa 0x%" PRIx64 ": %s",
277 		   addr, dwarf_errmsg (-1));
278 	  if (cfa_nops < 1)
279 	    error (EXIT_FAILURE, 0, "dwarf_frame_cfa no ops");
280 	  print_expr_block (NULL, cfa_ops, cfa_nops, 0, depth);
281 	  free (frame);
282 	}
283       else if (is_ET_REL || is_debug)
284 	{
285 	  /* XXX In ET_REL files there might be an .eh_frame with relocations
286 	     we don't handle (e.g. X86_64_PC32). Maybe we should?  */
287 	  printf ("{...}");
288 	}
289       else
290 	error (EXIT_FAILURE, 0, "dwarf_cfi_addrframe 0x%" PRIx64 ": %s",
291 	       addr, dwarf_errmsg (-1));
292       break;
293 
294     case DW_OP_push_object_address:
295       /* No arguments. Special. Pushes object address explicitly.
296        Normally only done implicitly by DW_AT_data_member_location.
297        Never used in CFI. */
298       if (attr == NULL)
299 	error (EXIT_FAILURE, 0, "%s used in CFI", opname);
300       printf ("%s", opname);
301       break;
302 
303     case DW_OP_addr:
304       /* 1 address argument. */
305       printf ("%s(0x%" PRIx64 ")", opname, (Dwarf_Addr) expr->number);
306       break;
307 
308     case DW_OP_const1u:
309     case DW_OP_const2u:
310     case DW_OP_const4u:
311     case DW_OP_const8u:
312     case DW_OP_constu:
313     case DW_OP_pick:
314     case DW_OP_plus_uconst:
315     case DW_OP_regx:
316     case DW_OP_piece:
317     case DW_OP_deref_size:
318     case DW_OP_xderef_size:
319       /* 1 numeric unsigned argument. */
320       printf ("%s(%" PRIu64 ")", opname, expr->number);
321       break;
322 
323     case DW_OP_call2:
324     case DW_OP_call4:
325     case DW_OP_call_ref:
326       /* 1 DIE offset argument for more ops in location attribute of DIE.
327          Never used in CFI.  */
328       {
329 	if (attr == NULL)
330 	  error (EXIT_FAILURE, 0, "%s used in CFI", opname);
331 
332 	Dwarf_Attribute call_attr;
333 	if (dwarf_getlocation_attr (attr, expr, &call_attr) != 0)
334 	  error (EXIT_FAILURE, 0, "dwarf_getlocation_attr for %s error %s",
335 		 opname, dwarf_errmsg (-1));
336 
337 	Dwarf_Die call_die;
338 	if (dwarf_getlocation_die (attr, expr, &call_die) != 0)
339 	  error (EXIT_FAILURE, 0, "dwarf_getlocation_die for %s error %s",
340 		 opname, dwarf_errmsg (-1));
341 
342 	Dwarf_Op *call_ops;
343 	size_t call_len;
344 	if (dwarf_getlocation (&call_attr, &call_ops, &call_len) != 0)
345 	  error (EXIT_FAILURE, 0, "dwarf_getlocation for entry: %s",
346 		 dwarf_errmsg (-1));
347 
348 	printf ("%s([%" PRIx64 "]) ", opname, dwarf_dieoffset (&call_die));
349 	print_expr_block (&call_attr, call_ops, call_len, addr, depth);
350       }
351       break;
352 
353     case DW_OP_const1s:
354     case DW_OP_const2s:
355     case DW_OP_const4s:
356     case DW_OP_const8s:
357     case DW_OP_consts:
358     case DW_OP_skip:
359     case DW_OP_bra:
360     case DW_OP_breg0 ... DW_OP_breg31:
361       /* 1 numeric signed argument. */
362       printf ("%s(%" PRId64 ")", opname, (Dwarf_Sword) expr->number);
363       break;
364 
365     case DW_OP_fbreg:
366       /* 1 numeric signed argument. Offset from frame base. */
367       if (attr == NULL)
368 	  error (EXIT_FAILURE, 0, "%s used in CFI", opname);
369 
370       if (! has_frame_base)
371 	error (EXIT_FAILURE, 0, "DW_OP_fbreg used without a frame base");
372 
373       printf ("%s(%" PRId64 ")", opname, (Dwarf_Sword) expr->number);
374       break;
375 
376     case DW_OP_bregx:
377       /* 2 arguments, unsigned register number, signed offset. */
378       printf ("%s(%" PRIu64 ",%" PRId64 ")", opname,
379 	      expr->number, (Dwarf_Sword) expr->number2);
380       break;
381 
382     case DW_OP_bit_piece:
383       /* 2 arguments, unsigned size, unsigned offset. */
384       printf ("%s(%" PRIu64 ",%" PRIu64 ")", opname,
385 	      expr->number, expr->number2);
386       break;
387 
388     case DW_OP_implicit_value:
389       /* Special, unsigned size plus block. */
390       {
391 	Dwarf_Attribute const_attr;
392 	Dwarf_Block block;
393 	if (dwarf_getlocation_attr (attr, expr, &const_attr) != 0)
394 	  error (EXIT_FAILURE, 0, "dwarf_getlocation_attr: %s",
395 		 dwarf_errmsg (-1));
396 
397 	if (dwarf_formblock (&const_attr, &block) != 0)
398 	  error (EXIT_FAILURE, 0, "dwarf_formblock: %s",
399 		 dwarf_errmsg (-1));
400 
401 	/* This is the "old" way. Check they result in the same.  */
402 	Dwarf_Block block_impl;
403 	if (dwarf_getlocation_implicit_value (attr, expr, &block_impl) != 0)
404 	  error (EXIT_FAILURE, 0, "dwarf_getlocation_implicit_value: %s",
405 		 dwarf_errmsg (-1));
406 
407 	assert (expr->number == block.length);
408 	assert (block.length == block_impl.length);
409 	printf ("%s(%" PRIu64 "){", opname, block.length);
410 	for (size_t i = 0; i < block.length; i++)
411 	  {
412 	    printf ("%02x", block.data[i]);
413 	    assert (block.data[i] == block_impl.data[i]);
414 	  }
415 	printf("}");
416       }
417       break;
418 
419     case DW_OP_implicit_pointer:
420     case DW_OP_GNU_implicit_pointer:
421       /* Special, DIE offset, signed offset. Referenced DIE has a
422 	 location or const_value attribute. */
423       {
424 	if (attr == NULL)
425 	  error (EXIT_FAILURE, 0, "%s used in CFI", opname);
426 
427 	Dwarf_Attribute attrval;
428 	if (dwarf_getlocation_implicit_pointer (attr, expr, &attrval) != 0)
429 	  error (EXIT_FAILURE, 0, "dwarf_getlocation_implicit_pointer: %s",
430 		 dwarf_errmsg (-1));
431 
432 	// Sanity check, results should be the same.
433 	Dwarf_Attribute attrval2;
434 	if (dwarf_getlocation_attr (attr, expr, &attrval2) != 0)
435 	  error (EXIT_FAILURE, 0, "dwarf_getlocation_attr: %s",
436 		 dwarf_errmsg (-1));
437 
438 	assert (dwarf_whatattr (&attrval) == dwarf_whatattr (&attrval2));
439 	assert (dwarf_whatform (&attrval) == dwarf_whatform (&attrval2));
440 	// In theory two different valp pointers could point to the same
441 	// value. But here we really expect them to be the equal.
442 	assert (attrval.valp == attrval2.valp);
443 
444 	Dwarf_Die impl_die;
445 	if (dwarf_getlocation_die (attr, expr, &impl_die) != 0)
446 	  error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
447 		 dwarf_errmsg (-1));
448 
449 	printf ("%s([%" PRIx64 "],%" PRId64 ") ", opname,
450 		dwarf_dieoffset (&impl_die), expr->number2);
451 
452 	if (dwarf_whatattr (&attrval) == DW_AT_const_value)
453 	  printf ("<constant value>"); // Lookup type...
454 	else
455 	  {
456 	    // Lookup the location description at the current address.
457 	    Dwarf_Op *exprval;
458 	    size_t exprval_len;
459 	    int locs = dwarf_getlocation_addr (&attrval, addr,
460 					       &exprval, &exprval_len, 1);
461 	    if (locs == 0)
462 	      printf ("<no location>"); // This means "optimized out".
463 	    else if (locs == 1)
464 	      print_expr_block (&attrval, exprval, exprval_len, addr, depth);
465 	    else
466 	      error (EXIT_FAILURE, 0,
467 		     "dwarf_getlocation_addr attrval at addr 0x%" PRIx64
468 		     ", locs (%d): %s", addr, locs, dwarf_errmsg (-1));
469 	  }
470       }
471       break;
472 
473     case DW_OP_GNU_variable_value:
474       /* Special, DIE offset. Referenced DIE has a location or const_value
475 	 attribute. */
476       {
477 	if (attr == NULL)
478 	  error (EXIT_FAILURE, 0, "%s used in CFI", opname);
479 
480 	Dwarf_Attribute attrval;
481 	if (dwarf_getlocation_attr (attr, expr, &attrval) != 0)
482 	  error (EXIT_FAILURE, 0, "dwarf_getlocation_attr: %s",
483 		 dwarf_errmsg (-1));
484 
485 	Dwarf_Die impl_die;
486 	if (dwarf_getlocation_die (attr, expr, &impl_die) != 0)
487 	  error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
488 		 dwarf_errmsg (-1));
489 
490 	printf ("%s([%" PRIx64 "]) ", opname, dwarf_dieoffset (&impl_die));
491 
492 	if (dwarf_whatattr (&attrval) == DW_AT_const_value)
493 	  printf ("<constant value>"); // Lookup type...
494 	else
495 	  {
496 	    // Lookup the location description at the current address.
497 	    Dwarf_Op *exprval;
498 	    size_t exprval_len;
499 	    int locs = dwarf_getlocation_addr (&attrval, addr,
500 					       &exprval, &exprval_len, 1);
501 	    if (locs == 0)
502 	      printf ("<no location>"); // This means "optimized out".
503 	    else if (locs == 1)
504 	      print_expr_block (&attrval, exprval, exprval_len, addr, depth);
505 	    else
506 	      error (EXIT_FAILURE, 0,
507 		     "dwarf_getlocation_addr attrval at addr 0x%" PRIx64
508 		     ", locs (%d): %s", addr, locs, dwarf_errmsg (-1));
509 	  }
510       }
511       break;
512 
513     case DW_OP_entry_value:
514     case DW_OP_GNU_entry_value:
515       /* Special, unsigned size plus expression block. All registers
516 	 inside the block should be interpreted as they had on
517 	 entering the function. dwarf_getlocation_attr will return an
518 	 attribute containing the block as locexpr which can be
519 	 retrieved with dwarf_getlocation.  */
520       {
521 	Dwarf_Attribute entry_attr;
522 	if (dwarf_getlocation_attr (attr, expr, &entry_attr) != 0)
523 	  error (EXIT_FAILURE, 0, "dwarf_getlocation_attr: %s",
524 		 dwarf_errmsg (-1));
525 
526 	Dwarf_Op *entry_ops;
527 	size_t entry_len;
528 	if (dwarf_getlocation (&entry_attr, &entry_ops, &entry_len) != 0)
529 	  error (EXIT_FAILURE, 0, "dwarf_getlocation for entry: %s",
530 		 dwarf_errmsg (-1));
531 
532 	printf ("%s(%zd) ", opname, entry_len);
533 	print_expr_block (attr, entry_ops, entry_len, addr, depth);
534       }
535       break;
536 
537     case DW_OP_GNU_parameter_ref:
538       /* Special, unsigned CU relative DIE offset pointing to a
539 	 DW_TAG_formal_parameter. The value that parameter had at the
540 	 call site of the current function will be put on the DWARF
541 	 stack. The value can be retrieved by finding the
542 	 DW_TAG_GNU_call_site_parameter which has as
543 	 DW_AT_abstract_origin the same formal parameter DIE. */
544       {
545 	Dwarf_Die param;
546 	if (dwarf_getlocation_die (attr, expr, &param) != 0)
547 	  error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
548 		 dwarf_errmsg (-1));
549 	// XXX actually lookup DW_TAG_GNU_call_site_parameter
550 	printf ("%s[%" PRIx64 "]", opname, dwarf_dieoffset (&param));
551 	assert (expr->number == dwarf_cuoffset (&param));
552 	if (dwarf_tag (&param) != DW_TAG_formal_parameter)
553 	  error (EXIT_FAILURE, 0, "Not a formal parameter");
554       }
555       break;
556 
557     case DW_OP_convert:
558     case DW_OP_GNU_convert:
559     case DW_OP_reinterpret:
560     case DW_OP_GNU_reinterpret:
561       /* Special, unsigned CU relative DIE offset pointing to a
562 	 DW_TAG_base_type. Pops a value, converts or reinterprets the
563 	 value to the given type. When the argument is zero the value
564 	 becomes untyped again. */
565       {
566 	Dwarf_Die type;
567 	Dwarf_Off off = expr->number;
568 	if (off != 0)
569 	  {
570 	    if (dwarf_getlocation_die (attr, expr, &type) != 0)
571 	      error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
572 		     dwarf_errmsg (-1));
573 	    off = dwarf_dieoffset (&type);
574 	    assert (expr->number == dwarf_cuoffset (&type));
575 	    printf ("%s", opname);
576 	    print_base_type (&type);
577 	  }
578 	else
579 	  printf ("%s[%" PRIu64 "]", opname, off);
580 
581       }
582       break;
583 
584     case DW_OP_regval_type:
585     case DW_OP_GNU_regval_type:
586       /* Special, unsigned register number plus unsigned CU relative
587          DIE offset pointing to a DW_TAG_base_type. */
588       {
589 	Dwarf_Die type;
590 	if (dwarf_getlocation_die (attr, expr, &type) != 0)
591 	  error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
592 		 dwarf_errmsg (-1));
593 	assert (expr->number2 == dwarf_cuoffset (&type));
594 	// XXX check size against base_type size?
595 	printf ("%s(reg%" PRIu64 ")", opname, expr->number);
596 	print_base_type (&type);
597       }
598       break;
599 
600     case DW_OP_deref_type:
601     case DW_OP_GNU_deref_type:
602       /* Special, unsigned size plus unsigned CU relative DIE offset
603 	 pointing to a DW_TAG_base_type. */
604       {
605 	Dwarf_Die type;
606 	if (dwarf_getlocation_die (attr, expr, &type) != 0)
607 	  error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
608 		 dwarf_errmsg (-1));
609 	assert (expr->number2 == dwarf_cuoffset (&type));
610 	// XXX check size against base_type size?
611 	printf ("%s(%" PRIu64 ")", opname, expr->number);
612 	print_base_type (&type);
613       }
614       break;
615 
616     case DW_OP_xderef_type:
617       /* Special, unsigned size plus unsigned DIE offset
618 	 pointing to a DW_TAG_base_type. */
619       {
620 	Dwarf_Die type;
621 	if (dwarf_getlocation_die (attr, expr, &type) != 0)
622 	  error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
623 		 dwarf_errmsg (-1));
624 	// XXX check size against base_type size?
625 	printf ("%s(%" PRIu64 ")", opname, expr->number);
626 	print_base_type (&type);
627       }
628       break;
629 
630     case DW_OP_const_type:
631     case DW_OP_GNU_const_type:
632       /* Special, unsigned CU relative DIE offset pointing to a
633 	 DW_TAG_base_type, an unsigned size length plus a block with
634 	 the constant value. */
635       {
636 	Dwarf_Die type;
637 	if (dwarf_getlocation_die (attr, expr, &type) != 0)
638 	  error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
639 		 dwarf_errmsg (-1));
640 	assert (expr->number == dwarf_cuoffset (&type));
641 
642 	Dwarf_Attribute const_attr;
643 	if (dwarf_getlocation_attr (attr, expr, &const_attr) != 0)
644 	  error (EXIT_FAILURE, 0, "dwarf_getlocation_attr for type: %s",
645 		 dwarf_errmsg (-1));
646 
647 	Dwarf_Block block;
648 	if (dwarf_formblock (&const_attr, &block) != 0)
649 	  error (EXIT_FAILURE, 0, "dwarf_formblock for type: %s",
650 		 dwarf_errmsg (-1));
651 
652 	printf ("%s", opname);
653 	print_base_type (&type);
654 	printf ("(%" PRIu64 ")[", block.length);
655 	for (size_t i = 0; i < block.length; i++)
656 	  printf ("%02x", block.data[i]);
657 	printf("]");
658       }
659       break;
660 
661     case DW_OP_GNU_addr_index:
662     case DW_OP_addrx:
663       /* Address from the .debug_addr section (indexed based on CU).  */
664       {
665 	Dwarf_Attribute addr_attr;
666 	if (dwarf_getlocation_attr (attr, expr, &addr_attr) != 0)
667 	  error (EXIT_FAILURE, 0, "dwarf_getlocation_attr for addr: %s",
668 		 dwarf_errmsg (-1));
669 
670 	Dwarf_Addr address;
671 	if (dwarf_formaddr (&addr_attr, &address) != 0)
672 	  error (EXIT_FAILURE, 0, "dwarf_formaddr address failed: %s",
673 		 dwarf_errmsg (-1));
674 
675 	printf ("addr: 0x%" PRIx64, address);
676       }
677       break;
678 
679     case DW_OP_GNU_const_index:
680     case DW_OP_constx:
681       /* Constant from the .debug_addr section (indexed based on CU).  */
682       {
683 	Dwarf_Attribute addr_attr;
684 	if (dwarf_getlocation_attr (attr, expr, &addr_attr) != 0)
685 	  error (EXIT_FAILURE, 0, "dwarf_getlocation_attr for addr: %s",
686 		 dwarf_errmsg (-1));
687 
688 	Dwarf_Word constant;
689 	if (dwarf_formudata (&addr_attr, &constant) != 0)
690 	  error (EXIT_FAILURE, 0, "dwarf_formudata constant failed: %s",
691 		 dwarf_errmsg (-1));
692 
693 	printf ("const: 0x%" PRIx64, constant);
694       }
695       break;
696 
697     default:
698       error (EXIT_FAILURE, 0, "unhandled opcode: DW_OP_%s (0x%x)",
699 	     opname, atom);
700     }
701 }
702 
703 /* Get all variables and print their value expressions. */
704 static void
print_varlocs(Dwarf_Die * funcdie)705 print_varlocs (Dwarf_Die *funcdie)
706 {
707   // Display frame base for function if it exists.
708   // Should be used for DW_OP_fbreg.
709   has_frame_base = dwarf_hasattr (funcdie, DW_AT_frame_base);
710   if (has_frame_base)
711     {
712       Dwarf_Attribute fb_attr;
713       if (dwarf_attr (funcdie, DW_AT_frame_base, &fb_attr) == NULL)
714 	error (EXIT_FAILURE, 0, "dwarf_attr fb: %s", dwarf_errmsg (-1));
715 
716       Dwarf_Op *fb_expr;
717       size_t fb_exprlen;
718       if (dwarf_getlocation (&fb_attr, &fb_expr, &fb_exprlen) == 0)
719 	{
720 	  // Covers all of function.
721 	  Dwarf_Addr entrypc;
722 	  if (dwarf_entrypc (funcdie, &entrypc) != 0)
723 	    error (EXIT_FAILURE, 0, "dwarf_entrypc: %s", dwarf_errmsg (-1));
724 
725 	  printf ("    frame_base: ");
726 	  if (entrypc == 0)
727 	    printf ("XXX zero address"); // XXX bad DWARF?
728 	  else
729 	    print_expr_block (&fb_attr, fb_expr, fb_exprlen, entrypc, 0);
730 	  printf ("\n");
731 	}
732       else
733 	{
734 	  Dwarf_Addr base, start, end;
735 	  ptrdiff_t off = 0;
736 	  printf ("    frame_base:\n");
737           while ((off = dwarf_getlocations (&fb_attr, off, &base,
738 					    &start, &end,
739 					    &fb_expr, &fb_exprlen)) > 0)
740 	    {
741 	      printf ("      (%" PRIx64 ",%" PRIx64 ") ", start, end);
742 	      print_expr_block (&fb_attr, fb_expr, fb_exprlen, start, 0);
743 	      printf ("\n");
744 	    }
745 
746 	  if (off < 0)
747 	    error (EXIT_FAILURE, 0, "dwarf_getlocations fb: %s",
748 		   dwarf_errmsg (-1));
749 	}
750     }
751   else if (dwarf_tag (funcdie) == DW_TAG_inlined_subroutine)
752     {
753       // See whether the subprogram we are inlined into has a frame
754       // base we should use.
755       Dwarf_Die *scopes;
756       int n = dwarf_getscopes_die (funcdie, &scopes);
757       if (n <= 0)
758 	error (EXIT_FAILURE, 0, "dwarf_getscopes_die: %s", dwarf_errmsg (-1));
759 
760       while (n-- > 0)
761 	if (dwarf_tag (&scopes[n]) == DW_TAG_subprogram
762 	    && dwarf_hasattr (&scopes[n], DW_AT_frame_base))
763 	  {
764 	    has_frame_base = true;
765 	    break;
766 	  }
767       free (scopes);
768     }
769 
770   if (! dwarf_haschildren (funcdie))
771     return;
772 
773   Dwarf_Die child;
774   int res = dwarf_child (funcdie, &child);
775   if (res < 0)
776     error (EXIT_FAILURE, 0, "dwarf_child: %s", dwarf_errmsg (-1));
777 
778   /* We thought there was a child, but the child list was actually
779      empty. This isn't technically an error in the DWARF, but it is
780      certainly non-optimimal.  */
781   if (res == 1)
782     return;
783 
784   do
785     {
786       int tag = dwarf_tag (&child);
787       if (tag == DW_TAG_variable || tag == DW_TAG_formal_parameter)
788 	{
789 	  const char *what = tag == DW_TAG_variable ? "variable" : "parameter";
790 	  print_die (&child, what, 2);
791 
792 	  if (dwarf_hasattr (&child, DW_AT_location))
793 	    {
794 	      Dwarf_Attribute attr;
795 	      if (dwarf_attr (&child, DW_AT_location, &attr) == NULL)
796 		error (EXIT_FAILURE, 0, "dwarf_attr: %s", dwarf_errmsg (-1));
797 
798 	      Dwarf_Op *expr;
799 	      size_t exprlen;
800 	      if (dwarf_getlocation (&attr, &expr, &exprlen) == 0)
801 		{
802 		  // Covers all ranges of the function.
803 		  // Evaluate the expression block for each range.
804 		  ptrdiff_t offset = 0;
805 		  Dwarf_Addr base, begin, end;
806 		  do
807 		    {
808 		      offset = dwarf_ranges (funcdie, offset, &base,
809 					     &begin, &end);
810 		      if (offset < 0)
811 			error (EXIT_FAILURE, 0, "dwarf_ranges: %s",
812 			       dwarf_errmsg (-1));
813 
814 		      if (offset > 0)
815 			{
816 			  if (exprlen == 0)
817 			    printf ("      (%"
818 				    PRIx64 ",%" PRIx64
819 				    ") <empty expression>\n", begin, end);
820 			  else
821 			    print_expr_block_addrs (&attr, begin, end,
822 						    expr, exprlen);
823 			}
824 		    }
825 		  while (offset > 0);
826 
827 		  if (offset < 0)
828 		    error (EXIT_FAILURE, 0, "dwarf_ranges: %s",
829 			   dwarf_errmsg (-1));
830 		}
831 	      else
832 		{
833 		  Dwarf_Addr base, begin, end;
834 		  ptrdiff_t offset = 0;
835 		  while ((offset = dwarf_getlocations (&attr, offset,
836 						       &base, &begin, &end,
837 						       &expr, &exprlen)) > 0)
838 		    if (begin >= end)
839 		      printf ("      (%" PRIx64 ",%" PRIx64
840 			      ") <empty range>\n", begin, end); // XXX report?
841 		    else
842 		      {
843 			print_expr_block_addrs (&attr, begin, end,
844 						expr, exprlen);
845 
846 			// Extra sanity check for dwarf_getlocation_addr
847 			// Must at least find one range for begin and end-1.
848 			Dwarf_Op *expraddr;
849 			size_t expraddr_len;
850 			int locs = dwarf_getlocation_addr (&attr, begin,
851 							   &expraddr,
852 							   &expraddr_len, 1);
853 			assert (locs == 1);
854 			locs = dwarf_getlocation_addr (&attr, end - 1,
855 						       &expraddr,
856 						       &expraddr_len, 1);
857 			assert (locs == 1);
858 		      }
859 
860 		  if (offset < 0)
861 		    error (EXIT_FAILURE, 0, "dwarf_getlocations: %s",
862 			   dwarf_errmsg (-1));
863 		}
864 	    }
865 	  else if (dwarf_hasattr (&child, DW_AT_const_value))
866 	    {
867 	      printf ("      <constant value>\n"); // Lookup type and print.
868 	    }
869 	  else
870 	    {
871 	      printf ("      <no value>\n");
872 	    }
873 	}
874     }
875   while (dwarf_siblingof (&child, &child) == 0);
876 }
877 
878 static int
handle_instance(Dwarf_Die * funcdie,void * arg)879 handle_instance (Dwarf_Die *funcdie, void *arg __attribute__ ((unused)))
880 {
881   print_die (funcdie, "inlined function", 1);
882   print_varlocs (funcdie);
883 
884   return DWARF_CB_OK;
885 }
886 
887 static int
handle_function(Dwarf_Die * funcdie,void * arg)888 handle_function (Dwarf_Die *funcdie, void *arg __attribute__((unused)))
889 {
890   if (dwarf_func_inline (funcdie) > 0)
891     {
892       // abstract inline definition, find all inlined instances.
893 
894       // Note this is convenient for listing all instances together
895       // so you can easily compare the location expressions describing
896       // the variables and parameters, but it isn't very efficient
897       // since it will walk the DIE tree multiple times.
898       if (dwarf_func_inline_instances (funcdie, &handle_instance, NULL) != 0)
899 	error (EXIT_FAILURE, 0, "dwarf_func_inline_instances: %s",
900 	       dwarf_errmsg (-1));
901     }
902   else
903     {
904       // Contains actual code, not just a declaration?
905       Dwarf_Addr entrypc;
906       if (dwarf_entrypc (funcdie, &entrypc) == 0)
907 	{
908 	  print_die (funcdie, "function", 1);
909 	  print_varlocs (funcdie);
910 	}
911     }
912 
913   return DWARF_CB_OK;
914 }
915 
916 struct attr_arg
917 {
918   int depth;
919   Dwarf_Addr entrypc;
920 };
921 
922 static int
handle_attr(Dwarf_Attribute * attr,void * arg)923 handle_attr (Dwarf_Attribute *attr, void *arg)
924 {
925   int depth = ((struct attr_arg *) arg)->depth;
926   Dwarf_Addr entrypc = ((struct attr_arg *) arg)->entrypc;
927 
928   unsigned int code = dwarf_whatattr (attr);
929   unsigned int form = dwarf_whatform (attr);
930 
931   printf ("%*s%s (%s)", depth * 2, "",
932 	  dwarf_attr_string (code), dwarf_form_string (form));
933 
934   /* If we can get an DWARF expression (or location lists) from this
935      attribute we'll print it, otherwise we'll ignore it.  But if
936      there is an error while the attribute has the "correct" form then
937      we'll report an error (we can only really check DW_FORM_exprloc
938      other forms can be ambiguous).  */
939   Dwarf_Op *expr;
940   size_t exprlen;
941   bool printed = false;
942   int res = dwarf_getlocation (attr, &expr, &exprlen);
943   if (res == 0)
944     {
945       printf (" ");
946       print_expr_block (attr, expr, exprlen, entrypc, 0);
947       printf ("\n");
948       printed = true;
949     }
950   else if (form == DW_FORM_exprloc)
951     {
952       error (0, 0, "%s dwarf_getlocation failed: %s",
953 	     dwarf_attr_string (code), dwarf_errmsg (-1));
954       return DWARF_CB_ABORT;
955     }
956   else
957     {
958       Dwarf_Addr base, begin, end;
959       ptrdiff_t offset = 0;
960       while ((offset = dwarf_getlocations (attr, offset,
961 					   &base, &begin, &end,
962 					   &expr, &exprlen)) > 0)
963 	{
964 	  if (! printed)
965 	    printf ("\n");
966 	  printf ("%*s", depth * 2, "");
967 	  print_expr_block_addrs (attr, begin, end, expr, exprlen);
968 	  printed = true;
969 	}
970     }
971 
972   if (! printed)
973     printf ("\n");
974 
975   return DWARF_CB_OK;
976 }
977 
978 static void
handle_die(Dwarf_Die * die,int depth,bool outer_has_frame_base,Dwarf_Addr outer_entrypc)979 handle_die (Dwarf_Die *die, int depth, bool outer_has_frame_base,
980 	    Dwarf_Addr outer_entrypc)
981 {
982   /* CU DIE already printed.  */
983   if (depth > 0)
984     {
985       const char *name = dwarf_diename (die);
986       if (name != NULL)
987 	printf ("%*s[%" PRIx64 "] %s \"%s\"\n", depth * 2, "",
988 		dwarf_dieoffset (die), dwarf_tag_string (dwarf_tag (die)),
989 		name);
990       else
991 	printf ("%*s[%" PRIx64 "] %s\n", depth * 2, "",
992 		dwarf_dieoffset (die), dwarf_tag_string (dwarf_tag (die)));
993     }
994 
995   struct attr_arg arg;
996   arg.depth = depth + 1;
997 
998   /* The (lowest) address to use for (looking up) operands that depend
999      on address.  */
1000   Dwarf_Addr die_entrypc;
1001   if (dwarf_entrypc (die, &die_entrypc) != 0 || die_entrypc == 0)
1002     {
1003       /* Try to get the lowest address of the first range covered.  */
1004       Dwarf_Addr base, start, end;
1005       if (dwarf_ranges (die, 0, &base, &start, &end) <= 0 || start == 0)
1006 	die_entrypc = outer_entrypc;
1007       else
1008 	die_entrypc = start;
1009     }
1010   arg.entrypc = die_entrypc;
1011 
1012   /* Whether this or the any outer DIE has a frame base. Used as
1013      sanity check when printing expressions that use DW_OP_fbreg.  */
1014   bool die_has_frame_base = dwarf_hasattr (die, DW_AT_frame_base);
1015   die_has_frame_base |= outer_has_frame_base;
1016   has_frame_base = die_has_frame_base;
1017 
1018   /* Look through all attributes to find those that contain DWARF
1019      expressions and print those.  We expect to handle all attributes,
1020      anything else is an error.  */
1021   if (dwarf_getattrs (die, handle_attr, &arg, 0) != 1)
1022     error (EXIT_FAILURE, 0, "Couldn't get all attributes: %s",
1023 	   dwarf_errmsg (-1));
1024 
1025   /* Handle children and siblings recursively depth first.  */
1026   Dwarf_Die child;
1027   if (dwarf_haschildren (die) != 0 && dwarf_child (die, &child) == 0)
1028     handle_die (&child, depth + 1, die_has_frame_base, die_entrypc);
1029 
1030   Dwarf_Die sibling;
1031   if (dwarf_siblingof (die, &sibling) == 0)
1032     handle_die (&sibling, depth, outer_has_frame_base, outer_entrypc);
1033 }
1034 
1035 int
main(int argc,char * argv[])1036 main (int argc, char *argv[])
1037 {
1038   /* With --exprlocs we process all DIEs looking for any attribute
1039      which contains an DWARF expression (but not location lists) and
1040      print those.  Otherwise we process all function DIEs and print
1041      all DWARF expressions and location lists associated with
1042      parameters and variables). It must be the first argument,
1043      or the second, after --debug.  */
1044   bool exprlocs = false;
1045 
1046   /* With --debug we ignore not being able to find .eh_frame.
1047      It must come as first argument.  */
1048   is_debug = false;
1049   if (argc > 1)
1050     {
1051       if (strcmp ("--exprlocs", argv[1]) == 0)
1052 	{
1053 	  exprlocs = true;
1054 	  argv[1] = "";
1055 	}
1056       else if (strcmp ("--debug", argv[1]) == 0)
1057 	{
1058 	  is_debug = true;
1059 	  argv[1] = "";
1060 	}
1061     }
1062 
1063   if (argc > 2)
1064     {
1065       if (strcmp ("--exprlocs", argv[2]) == 0)
1066 	{
1067 	  exprlocs = true;
1068 	  argv[2] = "";
1069 	}
1070     }
1071 
1072   int remaining;
1073   Dwfl *dwfl;
1074   (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining,
1075                      &dwfl);
1076   assert (dwfl != NULL);
1077 
1078   Dwarf_Die *cu = NULL;
1079   Dwarf_Addr dwbias;
1080   bool found_cu = false;
1081   while ((cu = dwfl_nextcu (dwfl, cu, &dwbias)) != NULL)
1082     {
1083       /* Only walk actual compile units (not partial units) that
1084 	 contain code if we are only interested in the function variable
1085 	 locations.  */
1086       Dwarf_Die cudie;
1087       Dwarf_Die subdie;
1088       uint8_t unit_type;
1089       if (dwarf_cu_info (cu->cu, NULL, &unit_type, &cudie, &subdie,
1090 		         NULL, NULL, NULL) != 0)
1091 	error (EXIT_FAILURE, 0, "dwarf_cu_info: %s", dwarf_errmsg (-1));
1092       if (unit_type == DW_UT_skeleton)
1093 	cudie = subdie;
1094 
1095       Dwarf_Addr cubase;
1096       if (dwarf_tag (&cudie) == DW_TAG_compile_unit
1097 	  && (exprlocs || dwarf_lowpc (&cudie, &cubase) == 0))
1098 	{
1099 	  found_cu = true;
1100 
1101 	  Dwfl_Module *mod = dwfl_cumodule (cu);
1102 	  Dwarf_Addr modbias;
1103 	  dw = dwfl_module_getdwarf (mod, &modbias);
1104 	  assert (dwbias == modbias);
1105 
1106 	  const char *mainfile;
1107 	  const char *modname = dwfl_module_info (mod, NULL,
1108 						  NULL, NULL,
1109 						  NULL, NULL,
1110 						  &mainfile,
1111 						  NULL);
1112 	  if (modname == NULL)
1113 	    error (EXIT_FAILURE, 0, "dwfl_module_info: %s", dwarf_errmsg (-1));
1114 
1115 	  const char *name = (modname[0] != '\0'
1116 			      ? modname
1117 			      :  basename (mainfile));
1118 	  printf ("module '%s'\n", name);
1119 	  print_die (&cudie, "CU", 0);
1120 
1121 	  Dwarf_Addr elfbias;
1122 	  Elf *elf = dwfl_module_getelf (mod, &elfbias);
1123 
1124 	  // CFI. We need both since sometimes neither is complete.
1125 	  cfi_debug = dwfl_module_dwarf_cfi (mod, &cfi_debug_bias);
1126 	  cfi_eh = dwfl_module_eh_cfi (mod, &cfi_eh_bias);
1127 
1128 	  // No bias needed, same file.
1129 	  assert (cfi_debug == NULL || cfi_debug_bias == 0);
1130 
1131 	  // We are a bit forgiving for object files.  There might be
1132 	  // relocations we don't handle that are needed in some
1133 	  // places...
1134 	  GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (elf, &ehdr_mem);
1135 	  is_ET_REL = ehdr->e_type == ET_REL;
1136 
1137 	  if (exprlocs)
1138 	    {
1139 	      Dwarf_Addr entrypc;
1140 	      if (dwarf_entrypc (&cudie, &entrypc) != 0)
1141 		entrypc = 0;
1142 
1143 	      /* XXX - Passing true for has_frame_base is not really true.
1144 		 We do it because we want to resolve all DIEs and all
1145 		 attributes. Technically we should check that the DIE
1146 		 (types) are referenced from variables that are defined in
1147 		 a context (function) that has a frame base.  */
1148 	      handle_die (&cudie, 0, true /* Should be false */, entrypc);
1149 	    }
1150 	  else if (dwarf_getfuncs (&cudie, handle_function, NULL, 0) != 0)
1151 	    error (EXIT_FAILURE, 0, "dwarf_getfuncs %s",
1152 		   dwarf_errmsg (-1));
1153 	}
1154     }
1155 
1156   if (! found_cu)
1157     error (EXIT_FAILURE, 0, "No DWARF CU found?");
1158 
1159   dwfl_end (dwfl);
1160   return 0;
1161 }
1162