Dwfl_Module * dwfl_linemodule (Dwfl_Line *line) { if (line == NULL) return NULL; return dwfl_linecu (line)->mod; }
const char * dwfl_lineinfo (Dwfl_Line *line, Dwarf_Addr *addr, int *linep, int *colp, Dwarf_Word *mtime, Dwarf_Word *length) { if (line == NULL) return NULL; struct dwfl_cu *cu = dwfl_linecu (line); const Dwarf_Line *info = &cu->die.cu->lines->info[line->idx]; if (addr != NULL) *addr = dwfl_adjusted_dwarf_addr (cu->mod, info->addr); if (linep != NULL) *linep = info->line; if (colp != NULL) *colp = info->column; struct Dwarf_Fileinfo_s *file = &info->files->info[info->file]; if (mtime != NULL) *mtime = file->mtime; if (length != NULL) *length = file->length; return file->name; }
int main (int argc, char *argv[]) { int cnt; Dwfl *dwfl = NULL; (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &cnt, &dwfl); assert (dwfl != NULL); Dwarf_Die *cu = NULL; Dwarf_Addr bias; do { cu = dwfl_nextcu (dwfl, cu, &bias); if (cu != NULL) { Dwfl_Module *mod = dwfl_cumodule (cu); const char *modname = (dwfl_module_info (mod, NULL, NULL, NULL, NULL, NULL, NULL, NULL) ?: "<unknown>"); const char *cuname = (dwarf_diename (cu) ?: "<unknown>"); printf ("mod: %s CU: [%" PRIx64 "] %s\n", modname, dwarf_dieoffset (cu), cuname); size_t lines; if (dwfl_getsrclines (cu, &lines) != 0) continue; // No lines... for (size_t i = 0; i < lines; i++) { Dwfl_Line *line = dwfl_onesrcline (cu, i); Dwarf_Addr addr; int lineno; int colno; Dwarf_Word mtime; Dwarf_Word length; const char *src = dwfl_lineinfo (line, &addr, &lineno, &colno, &mtime, &length); Dwarf_Addr dw_bias; Dwarf_Line *dw_line = dwfl_dwarf_line (line, &dw_bias); assert (bias == dw_bias); Dwarf_Addr dw_addr; if (dwarf_lineaddr (dw_line, &dw_addr) != 0) error (EXIT_FAILURE, 0, "dwarf_lineaddr: %s", dwarf_errmsg (-1)); assert (addr == dw_addr + dw_bias); unsigned int dw_op_index; if (dwarf_lineop_index (dw_line, &dw_op_index) != 0) error (EXIT_FAILURE, 0, "dwarf_lineop_index: %s", dwarf_errmsg (-1)); int dw_lineno; if (dwarf_lineno (dw_line, &dw_lineno) != 0) error (EXIT_FAILURE, 0, "dwarf_lineno: %s", dwarf_errmsg (-1)); assert (lineno == dw_lineno); int dw_colno; if (dwarf_linecol (dw_line, &dw_colno) != 0) error (EXIT_FAILURE, 0, "dwarf_lineno: %s", dwarf_errmsg (-1)); assert (colno == dw_colno); bool begin; if (dwarf_linebeginstatement (dw_line, &begin) != 0) error (EXIT_FAILURE, 0, "dwarf_linebeginstatement: %s", dwarf_errmsg (-1)); bool end; if (dwarf_lineendsequence (dw_line, &end) != 0) error (EXIT_FAILURE, 0, "dwarf_lineendsequence: %s", dwarf_errmsg (-1)); bool pend; if (dwarf_lineprologueend (dw_line, &pend) != 0) error (EXIT_FAILURE, 0, "dwarf_lineprologueend: %s", dwarf_errmsg (-1)); bool ebegin; if (dwarf_lineepiloguebegin (dw_line, &ebegin) != 0) error (EXIT_FAILURE, 0, "dwarf_lineepiloguebegin: %s", dwarf_errmsg (-1)); bool block; if (dwarf_lineblock (dw_line, &block) != 0) error (EXIT_FAILURE, 0, "dwarf_lineblock: %s", dwarf_errmsg (-1)); unsigned int isa; if (dwarf_lineisa (dw_line, &isa) != 0) error (EXIT_FAILURE, 0, "dwarf_lineisa: %s", dwarf_errmsg (-1)); unsigned int disc; if (dwarf_linediscriminator (dw_line, &disc) != 0) error (EXIT_FAILURE, 0, "dwarf_linediscriminator: %s", dwarf_errmsg (-1)); const char *dw_src; Dwarf_Word dw_mtime; Dwarf_Word dw_length; dw_src = dwarf_linesrc (dw_line, &dw_mtime, &dw_length); assert (strcmp (src, dw_src) == 0); assert (mtime == dw_mtime); assert (length == dw_length); printf ("%zd %#" PRIx64 " %s:%d:%d\n" " time: %#" PRIX64 ", len: %" PRIu64 ", idx: %d, b: %d, e: %d" ", pe: %d, eb: %d, block: %d" ", isa: %d, disc: %d\n", i, addr, src, lineno, colno, mtime, length, dw_op_index, begin, end, pend, ebegin, block, isa, disc); Dwarf_Die *linecu = dwfl_linecu (line); assert (cu == linecu); Dwfl_Module *linemod = dwfl_linemodule (line); assert (mod == linemod); } } } while (cu != NULL); dwfl_end (dwfl); return 0; }
int dwfl_module_getsrc_file (Dwfl_Module *mod, const char *fname, int lineno, int column, Dwfl_Line ***srcsp, size_t *nsrcs) { if (mod == NULL) return -1; if (mod->dw == NULL) { Dwarf_Addr bias; if (INTUSE(dwfl_module_getdwarf) (mod, &bias) == NULL) return -1; } bool is_basename = strchr (fname, '/') == NULL; size_t max_match = *nsrcs ?: ~0u; size_t act_match = *nsrcs; size_t cur_match = 0; Dwfl_Line **match = *nsrcs == 0 ? NULL : *srcsp; struct dwfl_cu *cu = NULL; Dwfl_Error error; while ((error = __libdwfl_nextcu (mod, cu, &cu)) == DWFL_E_NOERROR && cu != NULL && (error = __libdwfl_cu_getsrclines (cu)) == DWFL_E_NOERROR) { inline const char *INTUSE(dwarf_line_file) (const Dwarf_Line *line) { return line->files->info[line->file].name; } inline Dwarf_Line *dwfl_line (const Dwfl_Line *line) { return &dwfl_linecu (line)->die.cu->lines->info[line->idx]; } inline const char *dwfl_line_file (const Dwfl_Line *line) { return INTUSE(dwarf_line_file) (dwfl_line (line)); } /* Search through all the line number records for a matching file and line/column number. If any of the numbers is zero, no match is performed. */ const char *lastfile = NULL; bool lastmatch = false; for (size_t cnt = 0; cnt < cu->die.cu->lines->nlines; ++cnt) { Dwarf_Line *line = &cu->die.cu->lines->info[cnt]; if (unlikely (line->file >= line->files->nfiles)) { __libdwfl_seterrno (DWFL_E (LIBDW, DWARF_E_INVALID_DWARF)); return -1; } else { const char *file = INTUSE(dwarf_line_file) (line); if (file != lastfile) { /* Match the name with the name the user provided. */ lastfile = file; lastmatch = !strcmp (is_basename ? basename (file) : file, fname); } } if (!lastmatch) continue; /* See whether line and possibly column match. */ if (lineno != 0 && (lineno > line->line || (column != 0 && column > line->column))) /* Cannot match. */ continue; /* Determine whether this is the best match so far. */ size_t inner; for (inner = 0; inner < cur_match; ++inner) if (dwfl_line_file (match[inner]) == INTUSE(dwarf_line_file) (line)) break; if (inner < cur_match && (dwfl_line (match[inner])->line != line->line || dwfl_line (match[inner])->line != lineno || (column != 0 && (dwfl_line (match[inner])->column != line->column || dwfl_line (match[inner])->column != column)))) { /* We know about this file already. If this is a better match for the line number, use it. */ if (dwfl_line (match[inner])->line >= line->line && (dwfl_line (match[inner])->line != line->line || dwfl_line (match[inner])->column >= line->column)) /* Use the new line. Otherwise the old one. */ match[inner] = &cu->lines->idx[cnt]; continue; } if (cur_match < max_match) { if (cur_match == act_match) { /* Enlarge the array for the results. */ act_match += 10; Dwfl_Line **newp = realloc (match, act_match * sizeof (Dwfl_Line *)); if (newp == NULL) { free (match); __libdwfl_seterrno (DWFL_E_NOMEM); return -1; } match = newp; } match[cur_match++] = &cu->lines->idx[cnt]; } } } if (cur_match > 0) { assert (*nsrcs == 0 || *srcsp == match); *nsrcs = cur_match; *srcsp = match; return 0; } __libdwfl_seterrno (DWFL_E_NO_MATCH); return -1; }
static inline Dwarf_Line * dwfl_line (const Dwfl_Line *line) { return &dwfl_linecu (line)->die.cu->lines->info[line->idx]; }