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