|
@@ -184,13 +184,19 @@ static struct map *kernel_get_module_map(const char *module)
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
-struct map *get_target_map(const char *target, bool user)
|
|
|
|
|
|
+struct map *get_target_map(const char *target, struct nsinfo *nsi, bool user)
|
|
{
|
|
{
|
|
/* Init maps of given executable or kernel */
|
|
/* Init maps of given executable or kernel */
|
|
- if (user)
|
|
|
|
- return dso__new_map(target);
|
|
|
|
- else
|
|
|
|
|
|
+ if (user) {
|
|
|
|
+ struct map *map;
|
|
|
|
+
|
|
|
|
+ map = dso__new_map(target);
|
|
|
|
+ if (map && map->dso)
|
|
|
|
+ map->dso->nsinfo = nsinfo__get(nsi);
|
|
|
|
+ return map;
|
|
|
|
+ } else {
|
|
return kernel_get_module_map(target);
|
|
return kernel_get_module_map(target);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
static int convert_exec_to_group(const char *exec, char **result)
|
|
static int convert_exec_to_group(const char *exec, char **result)
|
|
@@ -366,7 +372,8 @@ found:
|
|
static int find_alternative_probe_point(struct debuginfo *dinfo,
|
|
static int find_alternative_probe_point(struct debuginfo *dinfo,
|
|
struct perf_probe_point *pp,
|
|
struct perf_probe_point *pp,
|
|
struct perf_probe_point *result,
|
|
struct perf_probe_point *result,
|
|
- const char *target, bool uprobes)
|
|
|
|
|
|
+ const char *target, struct nsinfo *nsi,
|
|
|
|
+ bool uprobes)
|
|
{
|
|
{
|
|
struct map *map = NULL;
|
|
struct map *map = NULL;
|
|
struct symbol *sym;
|
|
struct symbol *sym;
|
|
@@ -377,7 +384,7 @@ static int find_alternative_probe_point(struct debuginfo *dinfo,
|
|
if (!pp->function || pp->file)
|
|
if (!pp->function || pp->file)
|
|
return -ENOTSUP;
|
|
return -ENOTSUP;
|
|
|
|
|
|
- map = get_target_map(target, uprobes);
|
|
|
|
|
|
+ map = get_target_map(target, nsi, uprobes);
|
|
if (!map)
|
|
if (!map)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
@@ -421,8 +428,8 @@ static int get_alternative_probe_event(struct debuginfo *dinfo,
|
|
|
|
|
|
memcpy(tmp, &pev->point, sizeof(*tmp));
|
|
memcpy(tmp, &pev->point, sizeof(*tmp));
|
|
memset(&pev->point, 0, sizeof(pev->point));
|
|
memset(&pev->point, 0, sizeof(pev->point));
|
|
- ret = find_alternative_probe_point(dinfo, tmp, &pev->point,
|
|
|
|
- pev->target, pev->uprobes);
|
|
|
|
|
|
+ ret = find_alternative_probe_point(dinfo, tmp, &pev->point, pev->target,
|
|
|
|
+ pev->nsi, pev->uprobes);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
memcpy(&pev->point, tmp, sizeof(*tmp));
|
|
memcpy(&pev->point, tmp, sizeof(*tmp));
|
|
|
|
|
|
@@ -444,7 +451,7 @@ static int get_alternative_line_range(struct debuginfo *dinfo,
|
|
if (lr->end != INT_MAX)
|
|
if (lr->end != INT_MAX)
|
|
len = lr->end - lr->start;
|
|
len = lr->end - lr->start;
|
|
ret = find_alternative_probe_point(dinfo, &pp, &result,
|
|
ret = find_alternative_probe_point(dinfo, &pp, &result,
|
|
- target, user);
|
|
|
|
|
|
+ target, NULL, user);
|
|
if (!ret) {
|
|
if (!ret) {
|
|
lr->function = result.function;
|
|
lr->function = result.function;
|
|
lr->file = result.file;
|
|
lr->file = result.file;
|
|
@@ -457,12 +464,14 @@ static int get_alternative_line_range(struct debuginfo *dinfo,
|
|
}
|
|
}
|
|
|
|
|
|
/* Open new debuginfo of given module */
|
|
/* Open new debuginfo of given module */
|
|
-static struct debuginfo *open_debuginfo(const char *module, bool silent)
|
|
|
|
|
|
+static struct debuginfo *open_debuginfo(const char *module, struct nsinfo *nsi,
|
|
|
|
+ bool silent)
|
|
{
|
|
{
|
|
const char *path = module;
|
|
const char *path = module;
|
|
char reason[STRERR_BUFSIZE];
|
|
char reason[STRERR_BUFSIZE];
|
|
struct debuginfo *ret = NULL;
|
|
struct debuginfo *ret = NULL;
|
|
struct dso *dso = NULL;
|
|
struct dso *dso = NULL;
|
|
|
|
+ struct nscookie nsc;
|
|
int err;
|
|
int err;
|
|
|
|
|
|
if (!module || !strchr(module, '/')) {
|
|
if (!module || !strchr(module, '/')) {
|
|
@@ -480,6 +489,7 @@ static struct debuginfo *open_debuginfo(const char *module, bool silent)
|
|
}
|
|
}
|
|
path = dso->long_name;
|
|
path = dso->long_name;
|
|
}
|
|
}
|
|
|
|
+ nsinfo__mountns_enter(nsi, &nsc);
|
|
ret = debuginfo__new(path);
|
|
ret = debuginfo__new(path);
|
|
if (!ret && !silent) {
|
|
if (!ret && !silent) {
|
|
pr_warning("The %s file has no debug information.\n", path);
|
|
pr_warning("The %s file has no debug information.\n", path);
|
|
@@ -489,6 +499,7 @@ static struct debuginfo *open_debuginfo(const char *module, bool silent)
|
|
pr_warning("Rebuild with -g, ");
|
|
pr_warning("Rebuild with -g, ");
|
|
pr_warning("or install an appropriate debuginfo package.\n");
|
|
pr_warning("or install an appropriate debuginfo package.\n");
|
|
}
|
|
}
|
|
|
|
+ nsinfo__mountns_exit(&nsc);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -516,7 +527,7 @@ static struct debuginfo *debuginfo_cache__open(const char *module, bool silent)
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
- debuginfo_cache = open_debuginfo(module, silent);
|
|
|
|
|
|
+ debuginfo_cache = open_debuginfo(module, NULL, silent);
|
|
if (!debuginfo_cache)
|
|
if (!debuginfo_cache)
|
|
zfree(&debuginfo_cache_path);
|
|
zfree(&debuginfo_cache_path);
|
|
out:
|
|
out:
|
|
@@ -531,14 +542,18 @@ static void debuginfo_cache__exit(void)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-static int get_text_start_address(const char *exec, unsigned long *address)
|
|
|
|
|
|
+static int get_text_start_address(const char *exec, unsigned long *address,
|
|
|
|
+ struct nsinfo *nsi)
|
|
{
|
|
{
|
|
Elf *elf;
|
|
Elf *elf;
|
|
GElf_Ehdr ehdr;
|
|
GElf_Ehdr ehdr;
|
|
GElf_Shdr shdr;
|
|
GElf_Shdr shdr;
|
|
int fd, ret = -ENOENT;
|
|
int fd, ret = -ENOENT;
|
|
|
|
+ struct nscookie nsc;
|
|
|
|
|
|
|
|
+ nsinfo__mountns_enter(nsi, &nsc);
|
|
fd = open(exec, O_RDONLY);
|
|
fd = open(exec, O_RDONLY);
|
|
|
|
+ nsinfo__mountns_exit(&nsc);
|
|
if (fd < 0)
|
|
if (fd < 0)
|
|
return -errno;
|
|
return -errno;
|
|
|
|
|
|
@@ -582,7 +597,7 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
|
|
ret = -EINVAL;
|
|
ret = -EINVAL;
|
|
goto error;
|
|
goto error;
|
|
}
|
|
}
|
|
- ret = get_text_start_address(tp->module, &stext);
|
|
|
|
|
|
+ ret = get_text_start_address(tp->module, &stext, NULL);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
goto error;
|
|
goto error;
|
|
addr += stext;
|
|
addr += stext;
|
|
@@ -659,7 +674,7 @@ post_process_offline_probe_trace_events(struct probe_trace_event *tevs,
|
|
|
|
|
|
/* Prepare a map for offline binary */
|
|
/* Prepare a map for offline binary */
|
|
map = dso__new_map(pathname);
|
|
map = dso__new_map(pathname);
|
|
- if (!map || get_text_start_address(pathname, &stext) < 0) {
|
|
|
|
|
|
+ if (!map || get_text_start_address(pathname, &stext, NULL) < 0) {
|
|
pr_warning("Failed to get ELF symbols for %s\n", pathname);
|
|
pr_warning("Failed to get ELF symbols for %s\n", pathname);
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
@@ -676,7 +691,8 @@ post_process_offline_probe_trace_events(struct probe_trace_event *tevs,
|
|
}
|
|
}
|
|
|
|
|
|
static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
|
|
static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
|
|
- int ntevs, const char *exec)
|
|
|
|
|
|
+ int ntevs, const char *exec,
|
|
|
|
+ struct nsinfo *nsi)
|
|
{
|
|
{
|
|
int i, ret = 0;
|
|
int i, ret = 0;
|
|
unsigned long stext = 0;
|
|
unsigned long stext = 0;
|
|
@@ -684,7 +700,7 @@ static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
|
|
if (!exec)
|
|
if (!exec)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
- ret = get_text_start_address(exec, &stext);
|
|
|
|
|
|
+ ret = get_text_start_address(exec, &stext, nsi);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
@@ -715,7 +731,7 @@ post_process_module_probe_trace_events(struct probe_trace_event *tevs,
|
|
if (!module)
|
|
if (!module)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
- map = get_target_map(module, false);
|
|
|
|
|
|
+ map = get_target_map(module, NULL, false);
|
|
if (!map || debuginfo__get_text_offset(dinfo, &text_offs, true) < 0) {
|
|
if (!map || debuginfo__get_text_offset(dinfo, &text_offs, true) < 0) {
|
|
pr_warning("Failed to get ELF symbols for %s\n", module);
|
|
pr_warning("Failed to get ELF symbols for %s\n", module);
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
@@ -802,7 +818,8 @@ static int post_process_probe_trace_events(struct perf_probe_event *pev,
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
if (uprobe)
|
|
if (uprobe)
|
|
- ret = add_exec_to_probe_trace_events(tevs, ntevs, module);
|
|
|
|
|
|
+ ret = add_exec_to_probe_trace_events(tevs, ntevs, module,
|
|
|
|
+ pev->nsi);
|
|
else if (module)
|
|
else if (module)
|
|
/* Currently ref_reloc_sym based probe is not for drivers */
|
|
/* Currently ref_reloc_sym based probe is not for drivers */
|
|
ret = post_process_module_probe_trace_events(tevs, ntevs,
|
|
ret = post_process_module_probe_trace_events(tevs, ntevs,
|
|
@@ -825,7 +842,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
|
|
struct debuginfo *dinfo;
|
|
struct debuginfo *dinfo;
|
|
int ntevs, ret = 0;
|
|
int ntevs, ret = 0;
|
|
|
|
|
|
- dinfo = open_debuginfo(pev->target, !need_dwarf);
|
|
|
|
|
|
+ dinfo = open_debuginfo(pev->target, pev->nsi, !need_dwarf);
|
|
if (!dinfo) {
|
|
if (!dinfo) {
|
|
if (need_dwarf)
|
|
if (need_dwarf)
|
|
return -ENOENT;
|
|
return -ENOENT;
|
|
@@ -945,7 +962,7 @@ static int __show_line_range(struct line_range *lr, const char *module,
|
|
char sbuf[STRERR_BUFSIZE];
|
|
char sbuf[STRERR_BUFSIZE];
|
|
|
|
|
|
/* Search a line range */
|
|
/* Search a line range */
|
|
- dinfo = open_debuginfo(module, false);
|
|
|
|
|
|
+ dinfo = open_debuginfo(module, NULL, false);
|
|
if (!dinfo)
|
|
if (!dinfo)
|
|
return -ENOENT;
|
|
return -ENOENT;
|
|
|
|
|
|
@@ -1021,14 +1038,18 @@ end:
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
-int show_line_range(struct line_range *lr, const char *module, bool user)
|
|
|
|
|
|
+int show_line_range(struct line_range *lr, const char *module,
|
|
|
|
+ struct nsinfo *nsi, bool user)
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
|
|
+ struct nscookie nsc;
|
|
|
|
|
|
ret = init_probe_symbol_maps(user);
|
|
ret = init_probe_symbol_maps(user);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
return ret;
|
|
return ret;
|
|
|
|
+ nsinfo__mountns_enter(nsi, &nsc);
|
|
ret = __show_line_range(lr, module, user);
|
|
ret = __show_line_range(lr, module, user);
|
|
|
|
+ nsinfo__mountns_exit(&nsc);
|
|
exit_probe_symbol_maps();
|
|
exit_probe_symbol_maps();
|
|
|
|
|
|
return ret;
|
|
return ret;
|
|
@@ -1111,7 +1132,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
- dinfo = open_debuginfo(pevs->target, false);
|
|
|
|
|
|
+ dinfo = open_debuginfo(pevs->target, pevs->nsi, false);
|
|
if (!dinfo) {
|
|
if (!dinfo) {
|
|
ret = -ENOENT;
|
|
ret = -ENOENT;
|
|
goto out;
|
|
goto out;
|
|
@@ -1155,6 +1176,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
|
|
|
|
|
|
int show_line_range(struct line_range *lr __maybe_unused,
|
|
int show_line_range(struct line_range *lr __maybe_unused,
|
|
const char *module __maybe_unused,
|
|
const char *module __maybe_unused,
|
|
|
|
+ struct nsinfo *nsi __maybe_unused,
|
|
bool user __maybe_unused)
|
|
bool user __maybe_unused)
|
|
{
|
|
{
|
|
pr_warning("Debuginfo-analysis is not supported.\n");
|
|
pr_warning("Debuginfo-analysis is not supported.\n");
|
|
@@ -2703,6 +2725,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
|
|
struct probe_trace_event *tev = NULL;
|
|
struct probe_trace_event *tev = NULL;
|
|
struct probe_cache *cache = NULL;
|
|
struct probe_cache *cache = NULL;
|
|
struct strlist *namelist[2] = {NULL, NULL};
|
|
struct strlist *namelist[2] = {NULL, NULL};
|
|
|
|
+ struct nscookie nsc;
|
|
|
|
|
|
up = pev->uprobes ? 1 : 0;
|
|
up = pev->uprobes ? 1 : 0;
|
|
fd[up] = __open_probe_file_and_namelist(up, &namelist[up]);
|
|
fd[up] = __open_probe_file_and_namelist(up, &namelist[up]);
|
|
@@ -2729,7 +2752,9 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ nsinfo__mountns_enter(pev->nsi, &nsc);
|
|
ret = probe_file__add_event(fd[up], tev);
|
|
ret = probe_file__add_event(fd[up], tev);
|
|
|
|
+ nsinfo__mountns_exit(&nsc);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
break;
|
|
break;
|
|
|
|
|
|
@@ -2805,7 +2830,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
|
|
int ret, i, j, skipped = 0;
|
|
int ret, i, j, skipped = 0;
|
|
char *mod_name;
|
|
char *mod_name;
|
|
|
|
|
|
- map = get_target_map(pev->target, pev->uprobes);
|
|
|
|
|
|
+ map = get_target_map(pev->target, pev->nsi, pev->uprobes);
|
|
if (!map) {
|
|
if (!map) {
|
|
ret = -EINVAL;
|
|
ret = -EINVAL;
|
|
goto out;
|
|
goto out;
|
|
@@ -3345,13 +3370,16 @@ int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs)
|
|
void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs)
|
|
void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs)
|
|
{
|
|
{
|
|
int i, j;
|
|
int i, j;
|
|
|
|
+ struct perf_probe_event *pev;
|
|
|
|
|
|
/* Loop 3: cleanup and free trace events */
|
|
/* Loop 3: cleanup and free trace events */
|
|
for (i = 0; i < npevs; i++) {
|
|
for (i = 0; i < npevs; i++) {
|
|
|
|
+ pev = &pevs[i];
|
|
for (j = 0; j < pevs[i].ntevs; j++)
|
|
for (j = 0; j < pevs[i].ntevs; j++)
|
|
clear_probe_trace_event(&pevs[i].tevs[j]);
|
|
clear_probe_trace_event(&pevs[i].tevs[j]);
|
|
zfree(&pevs[i].tevs);
|
|
zfree(&pevs[i].tevs);
|
|
pevs[i].ntevs = 0;
|
|
pevs[i].ntevs = 0;
|
|
|
|
+ nsinfo__zput(pev->nsi);
|
|
clear_perf_probe_event(&pevs[i]);
|
|
clear_perf_probe_event(&pevs[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -3409,8 +3437,8 @@ out:
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
-int show_available_funcs(const char *target, struct strfilter *_filter,
|
|
|
|
- bool user)
|
|
|
|
|
|
+int show_available_funcs(const char *target, struct nsinfo *nsi,
|
|
|
|
+ struct strfilter *_filter, bool user)
|
|
{
|
|
{
|
|
struct rb_node *nd;
|
|
struct rb_node *nd;
|
|
struct map *map;
|
|
struct map *map;
|
|
@@ -3421,7 +3449,7 @@ int show_available_funcs(const char *target, struct strfilter *_filter,
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
/* Get a symbol map */
|
|
/* Get a symbol map */
|
|
- map = get_target_map(target, user);
|
|
|
|
|
|
+ map = get_target_map(target, nsi, user);
|
|
if (!map) {
|
|
if (!map) {
|
|
pr_err("Failed to get a map for %s\n", (target) ? : "kernel");
|
|
pr_err("Failed to get a map for %s\n", (target) ? : "kernel");
|
|
return -EINVAL;
|
|
return -EINVAL;
|