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