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, ¶m) != 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 (¶m));
552 assert (expr->number == dwarf_cuoffset (¶m));
553 if (dwarf_tag (¶m) != 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