int main (int argc, char *argv[]) { assert (argc >= 3); const char *name = argv[1]; ptrdiff_t cuoff = strtol (argv[2], NULL, 0); bool new_style = argc > 3; int fd = open (name, O_RDONLY); Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ); Dwarf_Die cudie_mem, *cudie = dwarf_offdie (dbg, cuoff, &cudie_mem); for (ptrdiff_t off = new_style ? DWARF_GETMACROS_START : 0; (off = dwarf_getmacros (cudie, mac, dbg, off)); ) if (off == -1) { puts (dwarf_errmsg (dwarf_errno ())); break; } dwarf_end (dbg); return 0; }
/** * Tries to read DWARF info from the location given by path, and * attach it to the given bin_info instance if it exists. * * @param bin bin_info instance for which to set DWARF info * @param path Presumed location of the DWARF info * @returns 0 on success, negative value on failure */ static int bin_info_set_dwarf_info_from_path(struct bin_info *bin, char *path) { int fd = -1, ret = 0; struct bt_dwarf_cu *cu = NULL; Dwarf *dwarf_info = NULL; if (!bin || !path) { goto error; } fd = open(path, O_RDONLY); if (fd < 0) { fd = -errno; goto error; } dwarf_info = dwarf_begin(fd, DWARF_C_READ); if (!dwarf_info) { goto error; } /* * Check if the dwarf info has any CU. If not, the * executable's object file contains no DWARF info. */ cu = bt_dwarf_cu_create(dwarf_info); if (!cu) { goto error; } ret = bt_dwarf_cu_next(cu); if (ret) { goto error; } bin->dwarf_fd = fd; bin->dwarf_path = strdup(path); if (!bin->dwarf_path) { goto error; } bin->dwarf_info = dwarf_info; free(cu); return 0; error: if (fd >= 0) { close(fd); fd = -1; } dwarf_end(dwarf_info); g_free(dwarf_info); free(cu); return fd; }
int main (int argc, char *argv[]) { int cnt; for (cnt = 1; cnt < argc; ++cnt) { int fd = open (argv[cnt], O_RDONLY); Dwarf *dbg; printf ("file: %s\n", basename (argv[cnt])); dbg = dwarf_begin (fd, DWARF_C_READ); if (dbg == NULL) { printf ("%s not usable\n", argv[cnt]); close (fd); continue; } Dwarf_Off off = 0; Dwarf_Off old_off = 0; size_t hsize; Dwarf_Off abbrev; uint8_t addresssize; uint8_t offsetsize; while (dwarf_nextcu (dbg, off, &off, &hsize, &abbrev, &addresssize, &offsetsize) == 0) { printf ("New CU: off = %llu, hsize = %zu, ab = %llu, as = %" PRIu8 ", os = %" PRIu8 "\n", (unsigned long long int) old_off, hsize, (unsigned long long int) abbrev, addresssize, offsetsize); Dwarf_Die die; if (dwarf_offdie (dbg, old_off + hsize, &die) != NULL) handle (dbg, &die, 1); old_off = off; } dwarf_end (dbg); close (fd); } return 0; }
BT_HIDDEN void bin_info_destroy(struct bin_info *bin) { if (!bin) { return; } dwarf_end(bin->dwarf_info); free(bin->debug_info_dir); free(bin->elf_path); free(bin->dwarf_path); g_free(bin->build_id); free(bin->dbg_link_filename); elf_end(bin->elf_file); close(bin->elf_fd); close(bin->dwarf_fd); g_free(bin); }
int main (int argc, char **argv) { assert (argc > 1); int i = open (argv[1], O_RDONLY); assert (i >= 0); Dwarf *dw = dwarf_begin (i, DWARF_C_READ); assert (dw != NULL); Dwarf_Die die_mem, *die; die = dwarf_offdie (dw, 11, &die_mem); assert (die == &die_mem); assert (dwarf_tag (die) == 0); die = dwarf_offdie (dw, 11, &die_mem); assert (die == &die_mem); assert (dwarf_tag (die) == 0); dwarf_end (dw); return 0; }
int main (int argc, char *argv[]) { for (int i = 1; i < argc; ++i) { int fd = open (argv[i], O_RDONLY); Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ); if (dbg != NULL) { Dwarf_Off off = 0; size_t cuhl; Dwarf_Off noff; while (dwarf_nextcu (dbg, off, &noff, &cuhl, NULL, NULL, NULL) == 0) { Dwarf_Die die_mem; Dwarf_Die *die = dwarf_offdie (dbg, off + cuhl, &die_mem); Dwarf_Die iter_mem; Dwarf_Die *iter = &iter_mem; dwarf_child (die, &iter_mem); while (1) { if (dwarf_tag (iter) == DW_TAG_variable) { Dwarf_Attribute attr_mem; Dwarf_Die form_mem; dwarf_formref_die (dwarf_attr (iter, DW_AT_type, &attr_mem), &form_mem); } if (dwarf_siblingof (iter, &iter_mem) != 0) break; } off = noff; } off = 0; uint64_t type_sig; while (dwarf_next_unit (dbg, off, &noff, &cuhl, NULL, NULL, NULL, NULL, &type_sig, NULL) == 0) { Dwarf_Die die_mem; Dwarf_Die *die = dwarf_offdie_types (dbg, off + cuhl, &die_mem); if (die == NULL) printf ("fail\n"); else printf ("ok\n"); off = noff; } dwarf_end (dbg); } close (fd); } }
int main(int argc, char **argv) { Dwarf_Off off, lastoff; Dwarf *dw; size_t hdr_size; int cufd, error; argv0 = argv[0]; if (argc < 3) usage(); structname = argv[1]; binary = argv[2]; elf_version(EV_CURRENT); cufd = open(binary, O_RDONLY); if (cufd == -1) err(EX_USAGE, "open"); dw = dwarf_begin(cufd, DWARF_C_READ); if (dw == NULL) { error = dwarf_errno(); if (error == DWARF_E_NO_REGFILE) errx(EX_USAGE, "%s: Not a regular file", binary); dwarf_err_errno(EX_DATAERR, error, "dwarf_begin"); } get_elf_pointer_size(dw); /* XXX worry about .debug_types sections later. */ lastoff = off = 0; while (dwarf_nextcu(dw, off, &off, &hdr_size, NULL, NULL, NULL) == 0) { Dwarf_Die cu_die, die; int x; if (dwarf_offdie(dw, lastoff + hdr_size, &cu_die) == NULL) continue; lastoff = off; /* * A CU may be empty because e.g. an empty (or fully #if0'd) * file is compiled. */ if (dwarf_child(&cu_die, &die)) continue; /* Loop through all DIEs in the CU. */ do { if (isstruct(dwarf_tag(&die)) && dwarf_haschildren(&die) && dwarf_diename(&die) && strcmp(dwarf_diename(&die), structname) == 0) { structprobe(dw, &die); goto out; } } while ((x = dwarf_siblingof(&die, &die)) == 0); if (x == -1) dwarf_err(EX_DATAERR, "dwarf_siblingof"); } out: if (dwarf_end(dw)) dwarf_err(EX_SOFTWARE, "dwarf_end"); return (EX_OK); }
/* Search function from function name */ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data) { struct dwarf_callback_param *param = data; struct probe_finder *pf = param->data; struct perf_probe_point *pp = &pf->pev->point; /* Check tag and diename */ if (dwarf_tag(sp_die) != DW_TAG_subprogram || die_compare_name(sp_die, pp->function) != 0) return DWARF_CB_OK; pf->fname = dwarf_decl_file(sp_die); if (pp->line) { /* Function relative line */ dwarf_decl_line(sp_die, &pf->lno); pf->lno += pp->line; param->retval = find_probe_point_by_line(pf); } else if (!dwarf_func_inline(sp_die)) { /* Real function */ if (pp->lazy_line) param->retval = find_probe_point_lazy(sp_die, pf); else { if (dwarf_entrypc(sp_die, &pf->addr) != 0) { pr_warning("Failed to get entry pc of %s.\n", dwarf_diename(sp_die)); param->retval = -ENOENT; return DWARF_CB_ABORT; } pf->addr += pp->offset; /* TODO: Check the address in this function */ param->retval = convert_probe_point(sp_die, pf); } } else { struct dwarf_callback_param _param = {.data = (void *)pf, .retval = 0}; /* Inlined function: search instances */ dwarf_func_inline_instances(sp_die, probe_point_inline_cb, &_param); param->retval = _param.retval; } return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */ } static int find_probe_point_by_func(struct probe_finder *pf) { struct dwarf_callback_param _param = {.data = (void *)pf, .retval = 0}; dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0); return _param.retval; } /* Find kprobe_trace_events specified by perf_probe_event from debuginfo */ int find_kprobe_trace_events(int fd, struct perf_probe_event *pev, struct kprobe_trace_event **tevs, int max_tevs) { struct probe_finder pf = {.pev = pev, .max_tevs = max_tevs}; struct perf_probe_point *pp = &pev->point; Dwarf_Off off, noff; size_t cuhl; Dwarf_Die *diep; Dwarf *dbg; int ret = 0; pf.tevs = zalloc(sizeof(struct kprobe_trace_event) * max_tevs); if (pf.tevs == NULL) return -ENOMEM; *tevs = pf.tevs; pf.ntevs = 0; dbg = dwarf_begin(fd, DWARF_C_READ); if (!dbg) { pr_warning("No dwarf info found in the vmlinux - " "please rebuild with CONFIG_DEBUG_INFO=y.\n"); free(pf.tevs); *tevs = NULL; return -EBADF; } #if _ELFUTILS_PREREQ(0, 142) /* Get the call frame information from this dwarf */ pf.cfi = dwarf_getcfi(dbg); #endif off = 0; line_list__init(&pf.lcache); /* Loop on CUs (Compilation Unit) */ while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) && ret >= 0) { /* Get the DIE(Debugging Information Entry) of this CU */ diep = dwarf_offdie(dbg, off + cuhl, &pf.cu_die); if (!diep) continue; /* Check if target file is included. */ if (pp->file) pf.fname = cu_find_realpath(&pf.cu_die, pp->file); else pf.fname = NULL; if (!pp->file || pf.fname) { if (pp->function) ret = find_probe_point_by_func(&pf); else if (pp->lazy_line) ret = find_probe_point_lazy(NULL, &pf); else { pf.lno = pp->line; ret = find_probe_point_by_line(&pf); } } off = noff; } line_list__free(&pf.lcache); dwarf_end(dbg); return (ret < 0) ? ret : pf.ntevs; } /* Reverse search */ int find_perf_probe_point(int fd, unsigned long addr, struct perf_probe_point *ppt) { Dwarf_Die cudie, spdie, indie; Dwarf *dbg; Dwarf_Line *line; Dwarf_Addr laddr, eaddr; const char *tmp; int lineno, ret = 0; bool found = false; dbg = dwarf_begin(fd, DWARF_C_READ); if (!dbg) return -EBADF; /* Find cu die */ if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr, &cudie)) { ret = -EINVAL; goto end; } /* Find a corresponding line */ line = dwarf_getsrc_die(&cudie, (Dwarf_Addr)addr); if (line) { if (dwarf_lineaddr(line, &laddr) == 0 && (Dwarf_Addr)addr == laddr && dwarf_lineno(line, &lineno) == 0) { tmp = dwarf_linesrc(line, NULL, NULL); if (tmp) { ppt->line = lineno; ppt->file = strdup(tmp); if (ppt->file == NULL) { ret = -ENOMEM; goto end; } found = true; } } } /* Find a corresponding function */ if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) { tmp = dwarf_diename(&spdie); if (!tmp || dwarf_entrypc(&spdie, &eaddr) != 0) goto end; if (ppt->line) { if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr, &indie)) { /* addr in an inline function */ tmp = dwarf_diename(&indie); if (!tmp) goto end; ret = dwarf_decl_line(&indie, &lineno); } else { if (eaddr == addr) { /* Function entry */ lineno = ppt->line; ret = 0; } else ret = dwarf_decl_line(&spdie, &lineno); } if (ret == 0) { /* Make a relative line number */ ppt->line -= lineno; goto found; } } /* We don't have a line number, let's use offset */ ppt->offset = addr - (unsigned long)eaddr; found: ppt->function = strdup(tmp); if (ppt->function == NULL) { ret = -ENOMEM; goto end; } found = true; } end: dwarf_end(dbg); if (ret >= 0) ret = found ? 1 : 0; return ret; } /* Add a line and store the src path */ static int line_range_add_line(const char *src, unsigned int lineno, struct line_range *lr) { /* Copy real path */ if (!lr->path) { lr->path = strdup(src); if (lr->path == NULL) return -ENOMEM; } return line_list__add_line(&lr->line_list, lineno); } /* Search function declaration lines */ static int line_range_funcdecl_cb(Dwarf_Die *sp_die, void *data) { struct dwarf_callback_param *param = data; struct line_finder *lf = param->data; const char *src; int lineno; src = dwarf_decl_file(sp_die); if (src && strtailcmp(src, lf->fname) != 0) return DWARF_CB_OK; if (dwarf_decl_line(sp_die, &lineno) != 0 || (lf->lno_s > lineno || lf->lno_e < lineno)) return DWARF_CB_OK; param->retval = line_range_add_line(src, lineno, lf->lr); if (param->retval < 0) return DWARF_CB_ABORT; return DWARF_CB_OK; } static int find_line_range_func_decl_lines(struct line_finder *lf) { struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0}; dwarf_getfuncs(&lf->cu_die, line_range_funcdecl_cb, ¶m, 0); return param.retval; } /* Find line range from its line number */ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf) { Dwarf_Lines *lines; Dwarf_Line *line; size_t nlines, i; Dwarf_Addr addr; int lineno, ret = 0; const char *src; Dwarf_Die die_mem; line_list__init(&lf->lr->line_list); if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) { pr_warning("No source lines found in this CU.\n"); return -ENOENT; } /* Search probable lines on lines list */ for (i = 0; i < nlines; i++) { line = dwarf_onesrcline(lines, i); if (dwarf_lineno(line, &lineno) != 0 || (lf->lno_s > lineno || lf->lno_e < lineno)) continue; if (sp_die) { /* Address filtering 1: does sp_die include addr? */ if (dwarf_lineaddr(line, &addr) != 0 || !dwarf_haspc(sp_die, addr)) continue; /* Address filtering 2: No child include addr? */ if (die_find_inlinefunc(sp_die, addr, &die_mem)) continue; } /* TODO: Get fileno from line, but how? */ src = dwarf_linesrc(line, NULL, NULL); if (strtailcmp(src, lf->fname) != 0) continue; ret = line_range_add_line(src, lineno, lf->lr); if (ret < 0) return ret; } /* * Dwarf lines doesn't include function declarations. We have to * check functions list or given function. */ if (sp_die) { src = dwarf_decl_file(sp_die); if (src && dwarf_decl_line(sp_die, &lineno) == 0 && (lf->lno_s <= lineno && lf->lno_e >= lineno)) ret = line_range_add_line(src, lineno, lf->lr); } else ret = find_line_range_func_decl_lines(lf); /* Update status */ if (ret >= 0) if (!list_empty(&lf->lr->line_list)) ret = lf->found = 1; else ret = 0; /* Lines are not found */ else { free(lf->lr->path); lf->lr->path = NULL; } return ret; } static int line_range_inline_cb(Dwarf_Die *in_die, void *data) { struct dwarf_callback_param *param = data; param->retval = find_line_range_by_line(in_die, param->data); return DWARF_CB_ABORT; /* No need to find other instances */ } /* Search function from function name */ static int line_range_search_cb(Dwarf_Die *sp_die, void *data) { struct dwarf_callback_param *param = data; struct line_finder *lf = param->data; struct line_range *lr = lf->lr; if (dwarf_tag(sp_die) == DW_TAG_subprogram && die_compare_name(sp_die, lr->function) == 0) { lf->fname = dwarf_decl_file(sp_die); dwarf_decl_line(sp_die, &lr->offset); pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset); lf->lno_s = lr->offset + lr->start; if (lf->lno_s < 0) /* Overflow */ lf->lno_s = INT_MAX; lf->lno_e = lr->offset + lr->end; if (lf->lno_e < 0) /* Overflow */ lf->lno_e = INT_MAX; pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e); lr->start = lf->lno_s; lr->end = lf->lno_e; if (dwarf_func_inline(sp_die)) { struct dwarf_callback_param _param; _param.data = (void *)lf; _param.retval = 0; dwarf_func_inline_instances(sp_die, line_range_inline_cb, &_param); param->retval = _param.retval; } else param->retval = find_line_range_by_line(sp_die, lf); return DWARF_CB_ABORT; } return DWARF_CB_OK; } static int find_line_range_by_func(struct line_finder *lf) { struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0}; dwarf_getfuncs(&lf->cu_die, line_range_search_cb, ¶m, 0); return param.retval; } int find_line_range(int fd, struct line_range *lr) { struct line_finder lf = {.lr = lr, .found = 0}; int ret = 0; Dwarf_Off off = 0, noff; size_t cuhl; Dwarf_Die *diep; Dwarf *dbg; dbg = dwarf_begin(fd, DWARF_C_READ); if (!dbg) { pr_warning("No dwarf info found in the vmlinux - " "please rebuild with CONFIG_DEBUG_INFO=y.\n"); return -EBADF; } /* Loop on CUs (Compilation Unit) */ while (!lf.found && ret >= 0) { if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0) break; /* Get the DIE(Debugging Information Entry) of this CU */ diep = dwarf_offdie(dbg, off + cuhl, &lf.cu_die); if (!diep) continue; /* Check if target file is included. */ if (lr->file) lf.fname = cu_find_realpath(&lf.cu_die, lr->file); else lf.fname = 0; if (!lr->file || lf.fname) { if (lr->function) ret = find_line_range_by_func(&lf); else { lf.lno_s = lr->start; lf.lno_e = lr->end; ret = find_line_range_by_line(NULL, &lf); } } off = noff; } pr_debug("path: %lx\n", (unsigned long)lr->path); dwarf_end(dbg); return (ret < 0) ? ret : lf.found; }
int main (int argc, char *argv[]) { int result = 0; int cnt; for (cnt = 1; cnt < argc; ++cnt) { int fd = open (argv[cnt], O_RDONLY); Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ); if (dbg == NULL) { printf ("%s not usable\n", argv[cnt]); result = 1; if (fd != -1) close (fd); continue; } Dwarf_Off o = 0; Dwarf_Off ncu; Dwarf_Off ao; size_t cuhl; uint8_t asz; uint8_t osz; while (dwarf_nextcu (dbg, o, &ncu, &cuhl, &ao, &asz, &osz) == 0) { printf ("cuhl = %zu, o = %llu, asz = %hhu, osz = %hhu, ncu = %llu\n", cuhl, (unsigned long long int) ao, asz, osz, (unsigned long long int) ncu); Dwarf_Die die_mem; Dwarf_Die *die = dwarf_offdie (dbg, o + cuhl, &die_mem); if (die == NULL) { printf ("%s: cannot get CU die\n", argv[cnt]); result = 1; break; } Dwarf_Files *files; size_t nfiles; if (dwarf_getsrcfiles (die, &files, &nfiles) != 0) { printf ("%s: cannot get files\n", argv[cnt]); result = 1; break; } for (int i = 0; i < nfiles; ++i) printf (" file[%d] = \"%s\"\n", i, dwarf_filesrc (files, i, NULL, NULL)); o = ncu; } dwarf_end (dbg); close (fd); } return result; }
int main (int argc, char *argv[]) { int result = 0; int cnt; for (cnt = 1; cnt < argc; ++cnt) { int fd = open (argv[cnt], O_RDONLY); Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ); if (dbg == NULL) { printf ("%s not usable\n", argv[cnt]); result = 1; close (fd); continue; } Dwarf_Aranges *aranges; size_t naranges; if (dwarf_getaranges (dbg, &aranges, &naranges) != 0) printf ("%s: cannot get aranges\n", argv[cnt]); else { for (size_t i = 0; i < ntestaddr; ++i) { Dwarf_Arange *found; found = dwarf_getarange_addr (aranges, testaddr[i]); if (found != NULL) { Dwarf_Off cu_offset; if (dwarf_getarangeinfo (found, NULL, NULL, &cu_offset) != 0) { puts ("failed to get CU die offset"); result = 1; } else { const char *cuname; Dwarf_Die cu_die; if (dwarf_offdie (dbg, cu_offset, &cu_die) == NULL || (cuname = dwarf_diename (&cu_die)) == NULL) { puts ("failed to get CU die"); result = 1; } else printf ("CU name: \"%s\"\n", cuname); } } else printf ("%#llx: not in range\n", (unsigned long long int) testaddr[i]); } for (size_t i = 0; i < naranges; ++i) { Dwarf_Arange *arange = dwarf_onearange (aranges, i); if (arange == NULL) { printf ("cannot get arange %zu: %s\n", i, dwarf_errmsg (-1)); break; } Dwarf_Addr start; Dwarf_Word length; Dwarf_Off cu_offset; if (dwarf_getarangeinfo (arange, &start, &length, &cu_offset) != 0) { printf ("cannot get info from aranges[%zu]\n", i); result = 1; } else { printf (" [%2zu] start: %#llx, length: %llu, cu: %llu\n", i, (unsigned long long int) start, (unsigned long long int) length, (unsigned long long int) cu_offset); const char *cuname; Dwarf_Die cu_die; if (dwarf_offdie (dbg, cu_offset, &cu_die) == NULL || (cuname = dwarf_diename (&cu_die)) == NULL) { puts ("failed to get CU die"); result = 1; } else printf ("CU name: \"%s\"\n", cuname); } } } dwarf_end (dbg); close (fd); } return result; }
int main (int argc, char *argv[]) { int cnt; for (cnt = 1; cnt < argc; ++cnt) { int fd = open (argv[cnt], O_RDONLY); Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ); if (dbg == NULL) { printf ("%s not usable: %s\n", argv[cnt], dwarf_errmsg (-1)); close (fd); continue; } Dwarf_Off cuoff = 0; Dwarf_Off old_cuoff = 0; size_t hsize; while (dwarf_nextcu (dbg, cuoff, &cuoff, &hsize, NULL, NULL, NULL) == 0) { /* Get the DIE for the CU. */ Dwarf_Die die; if (dwarf_offdie (dbg, old_cuoff + hsize, &die) == NULL) /* Something went wrong. */ break; Dwarf_Off offset = 0; while (1) { size_t length; Dwarf_Abbrev *abbrev = dwarf_getabbrev (&die, offset, &length); if (abbrev == NULL || abbrev == DWARF_END_ABBREV) /* End of the list. */ break; unsigned tag = dwarf_getabbrevtag (abbrev); if (tag == 0) { printf ("dwarf_getabbrevtag at offset %llu returned error: %s\n", (unsigned long long int) offset, dwarf_errmsg (-1)); break; } unsigned code = dwarf_getabbrevcode (abbrev); if (code == 0) { printf ("dwarf_getabbrevcode at offset %llu returned error: %s\n", (unsigned long long int) offset, dwarf_errmsg (-1)); break; } int children = dwarf_abbrevhaschildren (abbrev); if (children < 0) { printf ("dwarf_abbrevhaschildren at offset %llu returned error: %s\n", (unsigned long long int) offset, dwarf_errmsg (-1)); break; } printf ("abbrev[%llu]: code = %u, tag = %u, children = %d\n", (unsigned long long int) offset, code, tag, children); size_t attrcnt; if (dwarf_getattrcnt (abbrev, &attrcnt) != 0) { printf ("dwarf_getattrcnt at offset %llu returned error: %s\n", (unsigned long long int) offset, dwarf_errmsg (-1)); break; } unsigned int attr_num; unsigned int attr_form; Dwarf_Off aboffset; size_t j; for (j = 0; j < attrcnt; ++j) if (dwarf_getabbrevattr (abbrev, j, &attr_num, &attr_form, &aboffset)) printf ("dwarf_getabbrevattr for abbrev[%llu] and index %zu failed\n", (unsigned long long int) offset, j); else printf ("abbrev[%llu]: attr[%zu]: code = %u, form = %u, offset = %" PRIu64 "\n", (unsigned long long int) offset, j, attr_num, attr_form, (uint64_t) aboffset); offset += length; } old_cuoff = cuoff; } if (dwarf_end (dbg) != 0) printf ("dwarf_end failed for %s: %s\n", argv[cnt], dwarf_errmsg (-1)); close (fd); } return 0; }