perf tools: Update copy of libbpf's hashmap.c
[linux-2.6-microblaze.git] / tools / perf / util / probe-event.c
index 99d36ac..8eae2af 100644 (file)
 #include <linux/ctype.h>
 #include <linux/zalloc.h>
 
+#ifdef HAVE_DEBUGINFOD_SUPPORT
+#include <elfutils/debuginfod.h>
+#endif
+
 #define PERFPROBE_GROUP "probe"
 
 bool probe_event_dry_run;      /* Dry run flag */
@@ -129,9 +133,10 @@ static int kernel_get_symbol_address_by_name(const char *name, u64 *addr,
        struct map *map;
 
        /* ref_reloc_sym is just a label. Need a special fix*/
-       reloc_sym = kernel_get_ref_reloc_sym(NULL);
+       reloc_sym = kernel_get_ref_reloc_sym(&map);
        if (reloc_sym && strcmp(name, reloc_sym->name) == 0)
-               *addr = (reloc) ? reloc_sym->addr : reloc_sym->unrelocated_addr;
+               *addr = (!map->reloc || reloc) ? reloc_sym->addr :
+                       reloc_sym->unrelocated_addr;
        else {
                sym = machine__find_kernel_symbol_by_name(host_machine, name, &map);
                if (!sym)
@@ -337,6 +342,8 @@ static int kernel_get_module_dso(const char *module, struct dso **pdso)
 
        map = machine__kernel_map(host_machine);
        dso = map->dso;
+       if (!dso->has_build_id)
+               dso__read_running_kernel_build_id(dso, host_machine);
 
        vmlinux_name = symbol_conf.vmlinux_name;
        dso->load_errno = 0;
@@ -452,6 +459,49 @@ static int get_alternative_line_range(struct debuginfo *dinfo,
        return ret;
 }
 
+#ifdef HAVE_DEBUGINFOD_SUPPORT
+static struct debuginfo *open_from_debuginfod(struct dso *dso, struct nsinfo *nsi,
+                                             bool silent)
+{
+       debuginfod_client *c = debuginfod_begin();
+       char sbuild_id[SBUILD_ID_SIZE + 1];
+       struct debuginfo *ret = NULL;
+       struct nscookie nsc;
+       char *path;
+       int fd;
+
+       if (!c)
+               return NULL;
+
+       build_id__sprintf(&dso->bid, sbuild_id);
+       fd = debuginfod_find_debuginfo(c, (const unsigned char *)sbuild_id,
+                                       0, &path);
+       if (fd >= 0)
+               close(fd);
+       debuginfod_end(c);
+       if (fd < 0) {
+               if (!silent)
+                       pr_debug("Failed to find debuginfo in debuginfod.\n");
+               return NULL;
+       }
+       if (!silent)
+               pr_debug("Load debuginfo from debuginfod (%s)\n", path);
+
+       nsinfo__mountns_enter(nsi, &nsc);
+       ret = debuginfo__new((const char *)path);
+       nsinfo__mountns_exit(&nsc);
+       return ret;
+}
+#else
+static inline
+struct debuginfo *open_from_debuginfod(struct dso *dso __maybe_unused,
+                                      struct nsinfo *nsi __maybe_unused,
+                                      bool silent __maybe_unused)
+{
+       return NULL;
+}
+#endif
+
 /* Open new debuginfo of given module */
 static struct debuginfo *open_debuginfo(const char *module, struct nsinfo *nsi,
                                        bool silent)
@@ -471,6 +521,10 @@ static struct debuginfo *open_debuginfo(const char *module, struct nsinfo *nsi,
                                        strcpy(reason, "(unknown)");
                        } else
                                dso__strerror_load(dso, reason, STRERR_BUFSIZE);
+                       if (dso)
+                               ret = open_from_debuginfod(dso, nsi, silent);
+                       if (ret)
+                               return ret;
                        if (!silent) {
                                if (module)
                                        pr_err("Module %s is not loaded, please specify its full path name.\n", module);
@@ -795,7 +849,8 @@ post_process_kernel_probe_trace_events(struct probe_trace_event *tevs,
                        free(tevs[i].point.symbol);
                tevs[i].point.symbol = tmp;
                tevs[i].point.offset = tevs[i].point.address -
-                                      reloc_sym->unrelocated_addr;
+                       (map->reloc ? reloc_sym->unrelocated_addr :
+                                     reloc_sym->addr);
        }
        return skipped;
 }
@@ -950,6 +1005,7 @@ static int _show_one_line(FILE *fp, int l, bool skip, bool show_num)
 static int __show_line_range(struct line_range *lr, const char *module,
                             bool user)
 {
+       struct build_id bid;
        int l = 1;
        struct int_node *ln;
        struct debuginfo *dinfo;
@@ -957,6 +1013,7 @@ static int __show_line_range(struct line_range *lr, const char *module,
        int ret;
        char *tmp;
        char sbuf[STRERR_BUFSIZE];
+       char sbuild_id[SBUILD_ID_SIZE] = "";
 
        /* Search a line range */
        dinfo = open_debuginfo(module, NULL, false);
@@ -969,6 +1026,10 @@ static int __show_line_range(struct line_range *lr, const char *module,
                if (!ret)
                        ret = debuginfo__find_line_range(dinfo, lr);
        }
+       if (dinfo->build_id) {
+               build_id__init(&bid, dinfo->build_id, BUILD_ID_SIZE);
+               build_id__sprintf(&bid, sbuild_id);
+       }
        debuginfo__delete(dinfo);
        if (ret == 0 || ret == -ENOENT) {
                pr_warning("Specified source line is not found.\n");
@@ -980,7 +1041,7 @@ static int __show_line_range(struct line_range *lr, const char *module,
 
        /* Convert source file path */
        tmp = lr->path;
-       ret = get_real_path(tmp, lr->comp_dir, &lr->path);
+       ret = find_source_path(tmp, sbuild_id, lr->comp_dir, &lr->path);
 
        /* Free old path when new path is assigned */
        if (tmp != lr->path)