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