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. 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; 47bool is_debug; 48 49// Whether the current function has a DW_AT_frame_base defined. 50// Needed for DW_OP_fbreg. 51bool has_frame_base; 52 53static void 54print_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 66static const char * 67dwarf_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 82static const char * 83dwarf_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 95static const char * 96dwarf_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 108static const char * 109dwarf_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. */ 122static void 123print_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 150static const char * 151dwarf_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. 167static void print_expr (Dwarf_Attribute *, Dwarf_Op *, Dwarf_Addr, int); 168 169static void 170print_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 182static void 183print_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 192static void 193print_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. */ 704static void 705print_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 878static int 879handle_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 887static int 888handle_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 916struct attr_arg 917{ 918 int depth; 919 Dwarf_Addr entrypc; 920}; 921 922static int 923handle_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 978static void 979handle_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 1035int 1036main (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