/* Find probe points from lazy pattern */ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf) { int ret = 0; char *fpath; if (intlist__empty(pf->lcache)) { const char *comp_dir; comp_dir = cu_get_comp_dir(&pf->cu_die); ret = get_real_path(pf->fname, comp_dir, &fpath); if (ret < 0) { pr_warning("Failed to find source file path.\n"); return ret; } /* Matching lazy line pattern */ ret = find_lazy_match_lines(pf->lcache, fpath, pf->pev->point.lazy_line); free(fpath); if (ret <= 0) return ret; } return die_walk_lines(sp_die, probe_point_lazy_walker, pf); }
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 debuginfo__find_line_range(struct debuginfo *self, 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; const char *comp_dir; if (lr->function) { struct pubname_callback_param pubname_param = { .function = lr->function, .file = lr->file, .cu_die = &lf.cu_die, .sp_die = &lf.sp_die, .found = 0}; struct dwarf_callback_param line_range_param = { .data = (void *)&lf, .retval = 0}; dwarf_getpubnames(self->dbg, pubname_search_cb, &pubname_param, 0); if (pubname_param.found) { line_range_search_cb(&lf.sp_die, &line_range_param); if (lf.found) goto found; } } while (!lf.found && ret >= 0) { if (dwarf_nextcu(self->dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0) break; diep = dwarf_offdie(self->dbg, off + cuhl, &lf.cu_die); if (!diep) continue; 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; } found: if (lf.found) { comp_dir = cu_get_comp_dir(&lf.cu_die); if (comp_dir) { lr->comp_dir = strdup(comp_dir); if (!lr->comp_dir) ret = -ENOMEM; } } pr_debug("path: %s\n", lr->path); return (ret < 0) ? ret : lf.found; }
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 debuginfo__find_line_range(struct debuginfo *self, 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; const char *comp_dir; /* Fastpath: lookup by function name from .debug_pubnames section */ if (lr->function) { struct pubname_callback_param pubname_param = { .function = lr->function, .file = lr->file, .cu_die = &lf.cu_die, .sp_die = &lf.sp_die, .found = 0}; struct dwarf_callback_param line_range_param = { .data = (void *)&lf, .retval = 0}; dwarf_getpubnames(self->dbg, pubname_search_cb, &pubname_param, 0); if (pubname_param.found) { line_range_search_cb(&lf.sp_die, &line_range_param); if (lf.found) goto found; } } /* Loop on CUs (Compilation Unit) */ while (!lf.found && ret >= 0) { if (dwarf_nextcu(self->dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0) break; /* Get the DIE(Debugging Information Entry) of this CU */ diep = dwarf_offdie(self->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; } found: /* Store comp_dir */ if (lf.found) { comp_dir = cu_get_comp_dir(&lf.cu_die); if (comp_dir) { lr->comp_dir = strdup(comp_dir); if (!lr->comp_dir) ret = -ENOMEM; } } pr_debug("path: %s\n", lr->path); return (ret < 0) ? ret : lf.found; }
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 debuginfo__find_line_range(struct debuginfo *dbg, 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; const char *comp_dir; /* Fastpath: lookup by function name from .debug_pubnames section */ if (lr->function) { struct pubname_callback_param pubname_param = { .function = lr->function, .file = lr->file, .cu_die = &lf.cu_die, .sp_die = &lf.sp_die, .found = 0}; struct dwarf_callback_param line_range_param = { .data = (void *)&lf, .retval = 0}; dwarf_getpubnames(dbg->dbg, pubname_search_cb, &pubname_param, 0); if (pubname_param.found) { line_range_search_cb(&lf.sp_die, &line_range_param); if (lf.found) goto found; } } /* Loop on CUs (Compilation Unit) */ while (!lf.found && ret >= 0) { if (dwarf_nextcu(dbg->dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0) break; /* Get the DIE(Debugging Information Entry) of this CU */ diep = dwarf_offdie(dbg->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; } found: /* Store comp_dir */ if (lf.found) { comp_dir = cu_get_comp_dir(&lf.cu_die); if (comp_dir) { lr->comp_dir = strdup(comp_dir); if (!lr->comp_dir) ret = -ENOMEM; } } pr_debug("path: %s\n", lr->path); return (ret < 0) ? ret : lf.found; } /* * Find a src file from a DWARF tag path. Prepend optional source path prefix * and chop off leading directories that do not exist. Result is passed back as * a newly allocated path on success. * Return 0 if file was found and readable, -errno otherwise. */ int get_real_path(const char *raw_path, const char *comp_dir, char **new_path) { const char *prefix = symbol_conf.source_prefix; if (!prefix) { if (raw_path[0] != '/' && comp_dir) /* If not an absolute path, try to use comp_dir */ prefix = comp_dir; else { if (access(raw_path, R_OK) == 0) { *new_path = strdup(raw_path); return *new_path ? 0 : -ENOMEM; } else return -errno; } } *new_path = malloc((strlen(prefix) + strlen(raw_path) + 2)); if (!*new_path) return -ENOMEM; for (;;) { sprintf(*new_path, "%s/%s", prefix, raw_path); if (access(*new_path, R_OK) == 0) return 0; if (!symbol_conf.source_prefix) { /* In case of searching comp_dir, don't retry */ zfree(new_path); return -errno; } switch (errno) { case ENAMETOOLONG: case ENOENT: case EROFS: case EFAULT: raw_path = strchr(++raw_path, '/'); if (!raw_path) { zfree(new_path); return -ENOENT; } continue; default: zfree(new_path); return -errno; } } }
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 = NULL; Dwfl *dwfl; Dwarf_Addr bias; /* Currently ignored */ const char *comp_dir; dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias); if (!dbg) { pr_warning("No debug information 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; } /* Store comp_dir */ if (lf.found) { comp_dir = cu_get_comp_dir(&lf.cu_die); if (comp_dir) { lr->comp_dir = strdup(comp_dir); if (!lr->comp_dir) ret = -ENOMEM; } } pr_debug("path: %s\n", lr->path); dwfl_end(dwfl); return (ret < 0) ? ret : lf.found; }