LocationList location_list( simgrid::mc::ObjectInformation& info, Dwarf_Attribute& attr) { LocationList locations; std::ptrdiff_t offset = 0; while (1) { Dwarf_Addr base, start, end; Dwarf_Op *ops; std::size_t len; offset = dwarf_getlocations( &attr, offset, &base, &start, &end, &ops, &len); if (offset == 0) break; else if (offset == -1) xbt_die("Error while loading location list"); std::uint64_t base_address = (std::uint64_t) info.base_address(); LocationListEntry::range_type range; if (start == 0) // If start == 0, this is not a location list: range = { 0, UINT64_MAX }; else range = { base_address + start, base_address + end }; locations.push_back({ DwarfExpression(ops, ops+len), range }); } return locations; }
/* Get all variables and print their value expressions. */ static void print_varlocs (Dwarf_Die *funcdie) { // Display frame base for function if it exists. // Should be used for DW_OP_fbreg. has_frame_base = dwarf_hasattr (funcdie, DW_AT_frame_base); if (has_frame_base) { Dwarf_Attribute fb_attr; if (dwarf_attr (funcdie, DW_AT_frame_base, &fb_attr) == NULL) error (EXIT_FAILURE, 0, "dwarf_attr fb: %s", dwarf_errmsg (-1)); Dwarf_Op *fb_expr; size_t fb_exprlen; if (dwarf_getlocation (&fb_attr, &fb_expr, &fb_exprlen) == 0) { // Covers all of function. Dwarf_Addr entrypc; if (dwarf_entrypc (funcdie, &entrypc) != 0) error (EXIT_FAILURE, 0, "dwarf_entrypc: %s", dwarf_errmsg (-1)); printf (" frame_base: "); if (entrypc == 0) printf ("XXX zero address"); // XXX bad DWARF? else print_expr_block (&fb_attr, fb_expr, fb_exprlen, entrypc); printf ("\n"); } else { Dwarf_Addr base, start, end; ptrdiff_t off = 0; printf (" frame_base:\n"); while ((off = dwarf_getlocations (&fb_attr, off, &base, &start, &end, &fb_expr, &fb_exprlen)) > 0) { printf (" (%" PRIx64 ",%" PRIx64 ") ", start, end); print_expr_block (&fb_attr, fb_expr, fb_exprlen, start); printf ("\n"); } if (off < 0) error (EXIT_FAILURE, 0, "dwarf_getlocations fb: %s", dwarf_errmsg (-1)); } } else if (dwarf_tag (funcdie) == DW_TAG_inlined_subroutine) { // See whether the subprogram we are inlined into has a frame // base we should use. Dwarf_Die *scopes; int n = dwarf_getscopes_die (funcdie, &scopes); if (n <= 0) error (EXIT_FAILURE, 0, "dwarf_getscopes_die: %s", dwarf_errmsg (-1)); while (n-- > 0) if (dwarf_tag (&scopes[n]) == DW_TAG_subprogram && dwarf_hasattr (&scopes[n], DW_AT_frame_base)) { has_frame_base = true; break; } free (scopes); } if (! dwarf_haschildren (funcdie)) return; Dwarf_Die child; int res = dwarf_child (funcdie, &child); if (res < 0) error (EXIT_FAILURE, 0, "dwarf_child: %s", dwarf_errmsg (-1)); /* We thought there was a child, but the child list was actually empty. This isn't technically an error in the DWARF, but it is certainly non-optimimal. */ if (res == 1) return; do { int tag = dwarf_tag (&child); if (tag == DW_TAG_variable || tag == DW_TAG_formal_parameter) { const char *what = tag == DW_TAG_variable ? "variable" : "parameter"; print_die (&child, what, 2); if (dwarf_hasattr (&child, DW_AT_location)) { Dwarf_Attribute attr; if (dwarf_attr (&child, DW_AT_location, &attr) == NULL) error (EXIT_FAILURE, 0, "dwarf_attr: %s", dwarf_errmsg (-1)); Dwarf_Op *expr; size_t exprlen; if (dwarf_getlocation (&attr, &expr, &exprlen) == 0) { // Covers all ranges of the function. // Evaluate the expression block for each range. ptrdiff_t offset = 0; Dwarf_Addr base, begin, end; do { offset = dwarf_ranges (funcdie, offset, &base, &begin, &end); if (offset < 0) error (EXIT_FAILURE, 0, "dwarf_ranges: %s", dwarf_errmsg (-1)); if (offset > 0) { if (exprlen == 0) printf (" (%" PRIx64 ",%" PRIx64 ") <empty expression>\n", begin, end); else print_expr_block_addrs (&attr, begin, end, expr, exprlen); } } while (offset > 0); if (offset < 0) error (EXIT_FAILURE, 0, "dwarf_ranges: %s", dwarf_errmsg (-1)); } else { Dwarf_Addr base, begin, end; ptrdiff_t offset = 0; while ((offset = dwarf_getlocations (&attr, offset, &base, &begin, &end, &expr, &exprlen)) > 0) if (begin >= end) printf (" (%" PRIx64 ",%" PRIx64 ") <empty range>\n", begin, end); // XXX report? else { print_expr_block_addrs (&attr, begin, end, expr, exprlen); // Extra sanity check for dwarf_getlocation_addr // Must at least find one range for begin and end-1. Dwarf_Op *expraddr; size_t expraddr_len; int locs = dwarf_getlocation_addr (&attr, begin, &expraddr, &expraddr_len, 1); assert (locs == 1); locs = dwarf_getlocation_addr (&attr, end - 1, &expraddr, &expraddr_len, 1); assert (locs == 1); } if (offset < 0) error (EXIT_FAILURE, 0, "dwarf_getlocations: %s", dwarf_errmsg (-1)); } } else if (dwarf_hasattr (&child, DW_AT_const_value)) { printf (" <constant value>\n"); // Lookup type and print. } else { printf (" <no value>\n"); } } } while (dwarf_siblingof (&child, &child) == 0); }