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