/* Print all locations in the whole DIE tree of a single file using dwfl to handle ET_REL files (which need the .debug sections to be relocated) and to automatically get separate debuginfo. gcc -Wall -Wextra -g -O2 -o dwfl_dwarf dwfl_dwarf.c -ldw */ /* We want the sane basename function. */ #define _GNU_SOURCE #include #include #include #include #include #include #include void handle_die (Dwarf_Die *die) { do { Dwarf_Attribute attr; if ((dwarf_attr (die, DW_AT_location, &attr) != NULL)) { printf ("[%" PRIx64 "]", dwarf_dieoffset (die)); ptrdiff_t off = 0; Dwarf_Addr base, start, end; do { Dwarf_Op *expr; size_t exprlen; off = dwarf_getlocations(&attr, off, &base, &start, &end, &expr, &exprlen); if (off > 0) printf ("(%" PRIx64 ",%" PRIx64 ")[%zd] ", start, end, exprlen); } while (off > 0); printf ("\n"); } Dwarf_Die child; if (dwarf_child (die, &child) == 0) handle_die (&child); } while (dwarf_siblingof (die, die) == 0); } static const Dwfl_Callbacks dwfl_callbacks = { .find_debuginfo = dwfl_standard_find_debuginfo, .section_address = dwfl_offline_section_address, .find_elf = dwfl_build_id_find_elf, }; int main (int argc, char **argv) { if (argc == 2) { const char *file = argv[1]; const char *base = basename (file); /* Create a one elf module file Dwfl. */ Dwfl *dwfl = dwfl_begin (&dwfl_callbacks); dwfl_report_begin (dwfl); Dwfl_Module *mod = dwfl_report_elf (dwfl, base, file, -1, 0, true); dwfl_report_end (dwfl, NULL, NULL); Dwarf_Addr bias; Dwarf *dbg = dwfl_module_getdwarf(mod, &bias); if (dbg != NULL) { /* Should be zero with one module. */ printf ("bias: %" PRIx64 "\n", bias); Dwarf_CU *cu = NULL; Dwarf_Half version; Dwarf_Die cudie, subdie; uint8_t unit_type; while (dwarf_get_units (dbg, cu, &cu, &version, &unit_type, &cudie, &subdie) == 0) handle_die (&cudie); } dwfl_end (dwfl); } }