aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/util/probe-event.c40
-rw-r--r--tools/perf/util/probe-finder.c86
-rw-r--r--tools/perf/util/probe-finder.h1
3 files changed, 26 insertions, 101 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 1ce2cb9845b6..8e34c8d47813 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -248,6 +248,18 @@ static struct debuginfo *open_debuginfo(const char *module)
248 return debuginfo__new(path); 248 return debuginfo__new(path);
249} 249}
250 250
251static struct ref_reloc_sym *__kernel_get_ref_reloc_sym(void)
252{
253 /* kmap->ref_reloc_sym should be set if host_machine is initialized */
254 struct kmap *kmap;
255
256 if (map__load(host_machine->vmlinux_maps[MAP__FUNCTION], NULL) < 0)
257 return NULL;
258
259 kmap = map__kmap(host_machine->vmlinux_maps[MAP__FUNCTION]);
260 return kmap->ref_reloc_sym;
261}
262
251/* 263/*
252 * Convert trace point to probe point with debuginfo 264 * Convert trace point to probe point with debuginfo
253 * Currently only handles kprobes. 265 * Currently only handles kprobes.
@@ -256,18 +268,27 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
256 struct perf_probe_point *pp) 268 struct perf_probe_point *pp)
257{ 269{
258 struct symbol *sym; 270 struct symbol *sym;
271 struct ref_reloc_sym *reloc_sym;
259 struct map *map; 272 struct map *map;
260 u64 addr; 273 u64 addr = 0;
261 int ret = -ENOENT; 274 int ret = -ENOENT;
262 struct debuginfo *dinfo; 275 struct debuginfo *dinfo;
263 276
264 sym = __find_kernel_function_by_name(tp->symbol, &map); 277 /* ref_reloc_sym is just a label. Need a special fix*/
265 if (sym) { 278 reloc_sym = __kernel_get_ref_reloc_sym();
266 addr = map->unmap_ip(map, sym->start + tp->offset); 279 if (reloc_sym && strcmp(tp->symbol, reloc_sym->name) == 0)
280 addr = reloc_sym->unrelocated_addr + tp->offset;
281 else {
282 sym = __find_kernel_function_by_name(tp->symbol, &map);
283 if (sym)
284 addr = map->unmap_ip(map, sym->start + tp->offset) -
285 map->reloc;
286 }
287 if (addr) {
267 pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol, 288 pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol,
268 tp->offset, addr); 289 tp->offset, addr);
269 290
270 dinfo = debuginfo__new_online_kernel(addr); 291 dinfo = open_debuginfo(tp->module);
271 if (dinfo) { 292 if (dinfo) {
272 ret = debuginfo__find_probe_point(dinfo, 293 ret = debuginfo__find_probe_point(dinfo,
273 (unsigned long)addr, pp); 294 (unsigned long)addr, pp);
@@ -383,15 +404,6 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
383 return ret; 404 return ret;
384} 405}
385 406
386static struct ref_reloc_sym *__kernel_get_ref_reloc_sym(void)
387{
388 /* kmap->ref_reloc_sym should be set if host_machine is initialized */
389 struct kmap *kmap;
390
391 kmap = map__kmap(host_machine->vmlinux_maps[MAP__FUNCTION]);
392 return kmap->ref_reloc_sym;
393}
394
395/* Post processing the probe events */ 407/* Post processing the probe events */
396static int post_process_probe_trace_events(struct probe_trace_event *tevs, 408static int post_process_probe_trace_events(struct probe_trace_event *tevs,
397 int ntevs, const char *module, 409 int ntevs, const char *module,
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index e5e589fdef9b..4f6e277c457c 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -89,79 +89,6 @@ error:
89 return -ENOENT; 89 return -ENOENT;
90} 90}
91 91
92#if _ELFUTILS_PREREQ(0, 148)
93/* This method is buggy if elfutils is older than 0.148 */
94static int __linux_kernel_find_elf(Dwfl_Module *mod,
95 void **userdata,
96 const char *module_name,
97 Dwarf_Addr base,
98 char **file_name, Elf **elfp)
99{
100 int fd;
101 const char *path = kernel_get_module_path(module_name);
102
103 pr_debug2("Use file %s for %s\n", path, module_name);
104 if (path) {
105 fd = open(path, O_RDONLY);
106 if (fd >= 0) {
107 *file_name = strdup(path);
108 return fd;
109 }
110 }
111 /* If failed, try to call standard method */
112 return dwfl_linux_kernel_find_elf(mod, userdata, module_name, base,
113 file_name, elfp);
114}
115
116static const Dwfl_Callbacks kernel_callbacks = {
117 .find_debuginfo = dwfl_standard_find_debuginfo,
118 .debuginfo_path = &debuginfo_path,
119
120 .find_elf = __linux_kernel_find_elf,
121 .section_address = dwfl_linux_kernel_module_section_address,
122};
123
124/* Get a Dwarf from live kernel image */
125static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg,
126 Dwarf_Addr addr)
127{
128 dbg->dwfl = dwfl_begin(&kernel_callbacks);
129 if (!dbg->dwfl)
130 return -EINVAL;
131
132 /* Load the kernel dwarves: Don't care the result here */
133 dwfl_linux_kernel_report_kernel(dbg->dwfl);
134 dwfl_linux_kernel_report_modules(dbg->dwfl);
135
136 dbg->dbg = dwfl_addrdwarf(dbg->dwfl, addr, &dbg->bias);
137 /* Here, check whether we could get a real dwarf */
138 if (!dbg->dbg) {
139 pr_debug("Failed to find kernel dwarf at %lx\n",
140 (unsigned long)addr);
141 dwfl_end(dbg->dwfl);
142 memset(dbg, 0, sizeof(*dbg));
143 return -ENOENT;
144 }
145
146 return 0;
147}
148#else
149/* With older elfutils, this just support kernel module... */
150static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg,
151 Dwarf_Addr addr __maybe_unused)
152{
153 const char *path = kernel_get_module_path("kernel");
154
155 if (!path) {
156 pr_err("Failed to find vmlinux path\n");
157 return -ENOENT;
158 }
159
160 pr_debug2("Use file %s for debuginfo\n", path);
161 return debuginfo__init_offline_dwarf(dbg, path);
162}
163#endif
164
165struct debuginfo *debuginfo__new(const char *path) 92struct debuginfo *debuginfo__new(const char *path)
166{ 93{
167 struct debuginfo *dbg = zalloc(sizeof(*dbg)); 94 struct debuginfo *dbg = zalloc(sizeof(*dbg));
@@ -174,19 +101,6 @@ struct debuginfo *debuginfo__new(const char *path)
174 return dbg; 101 return dbg;
175} 102}
176 103
177struct debuginfo *debuginfo__new_online_kernel(unsigned long addr)
178{
179 struct debuginfo *dbg = zalloc(sizeof(*dbg));
180
181 if (!dbg)
182 return NULL;
183
184 if (debuginfo__init_online_kernel_dwarf(dbg, (Dwarf_Addr)addr) < 0)
185 zfree(&dbg);
186
187 return dbg;
188}
189
190void debuginfo__delete(struct debuginfo *dbg) 104void debuginfo__delete(struct debuginfo *dbg)
191{ 105{
192 if (dbg) { 106 if (dbg) {
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 592c4dac3be9..3fc597365ce6 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -31,7 +31,6 @@ struct debuginfo {
31}; 31};
32 32
33extern struct debuginfo *debuginfo__new(const char *path); 33extern struct debuginfo *debuginfo__new(const char *path);
34extern struct debuginfo *debuginfo__new_online_kernel(unsigned long addr);
35extern void debuginfo__delete(struct debuginfo *dbg); 34extern void debuginfo__delete(struct debuginfo *dbg);
36 35
37/* Find probe_trace_events specified by perf_probe_event from debuginfo */ 36/* Find probe_trace_events specified by perf_probe_event from debuginfo */