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_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, ¶m) != 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 (¶m));
557 assert (expr->number == dwarf_cuoffset (¶m));
558 if (dwarf_tag (¶m) != DW_TAG_formal_parameter)
559 error (EXIT_FAILURE, 0, "Not a formal parameter");
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
print_varlocs(Dwarf_Die * funcdie)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
handle_instance(Dwarf_Die * funcdie,void * arg)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
handle_function(Dwarf_Die * funcdie,void * arg)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
handle_attr(Dwarf_Attribute * attr,void * arg)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
handle_die(Dwarf_Die * die,int depth,bool outer_has_frame_base,Dwarf_Addr outer_entrypc)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
main(int argc,char * argv[])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 : xbasename (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 }
1168