Re: [PATCH] basic perf support for sparc

From: Kyle McMartin
Date: Sun Aug 02 2009 - 16:11:55 EST


On Sun, Aug 02, 2009 at 09:50:43PM +0200, Ingo Molnar wrote:
> We are sticking to a given version of the API. We could turn that
> into a function pointer and fill it in during startup via dlopen().
> If it's NULL then we dont call it and assume a value of NULL.
>
> Mind submitting such a version of your fix? It would nicely decrease
> the build requirements cross section surface of perf.
>

Assuming I remember how to use dlopen/dlsym, this might work.
Unfortunately I can't easily test anything this weekend, so
I don't actually know if it works... but it links ok.

cheers, Kyle

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index a5e9b87..8fb2e12 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -345,7 +345,7 @@ BUILTIN_OBJS += builtin-stat.o
BUILTIN_OBJS += builtin-top.o

PERFLIBS = $(LIB_FILE)
-EXTLIBS = -lbfd
+EXTLIBS = -ldl

#
# Platform specific tweaks
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 2810605..e41cb71 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -4,9 +4,9 @@
#include "symbol.h"

#include <libelf.h>
+#include <dlfcn.h>
#include <gelf.h>
#include <elf.h>
-#include <bfd.h>

const char *sym_hist_filter;

@@ -512,6 +512,11 @@ out:
return 0;
}

+static char *perf_bfd_demangle(void __used *v,
+ const char __used *name, int __used opt) {
+ return NULL;
+}
+
static int dso__load_sym(struct dso *self, int fd, const char *name,
symbol_filter_t filter, int verbose, struct module *mod)
{
@@ -526,6 +531,8 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
Elf_Scn *sec, *sec_strndx;
Elf *elf;
int nr = 0, kernel = !strcmp("[kernel]", self->name);
+ char *(*demangle)(void *v, const char *name, int opt) = NULL;
+ void *handle;

elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
if (elf == NULL) {
@@ -578,6 +585,13 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
NULL) != NULL);
} else self->adjust_symbols = 0;

+ handle = dlopen("libbfd.so", RTLD_NOW);
+ if (!handle)
+ demangle = perf_bfd_demangle;
+ demangle = dlsym(handle, "bfd_demangle");
+ if (!demangle)
+ demangle = perf_bfd_demangle;
+
elf_symtab__for_each_symbol(syms, nr_syms, index, sym) {
struct symbol *f;
const char *name;
@@ -592,7 +606,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,

sec = elf_getscn(elf, sym.st_shndx);
if (!sec)
- goto out_elf_end;
+ goto out_dlclose;

gelf_getshdr(sec, &shdr);

@@ -617,7 +631,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
else {
fprintf(stderr, "dso__load_sym() module %s lookup of %s failed\n",
mod->name, section_name);
- goto out_elf_end;
+ goto out_dlclose;
}
}
/*
@@ -626,7 +640,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
* to it...
*/
name = elf_sym__name(&sym, symstrs);
- demangled = bfd_demangle(NULL, name, DMGL_PARAMS | DMGL_ANSI);
+ demangled = demangle(NULL, name, DMGL_PARAMS | DMGL_ANSI);
if (demangled != NULL)
name = demangled;

@@ -634,7 +648,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
self->sym_priv_size, obj_start, verbose);
free(demangled);
if (!f)
- goto out_elf_end;
+ goto out_dlclose;

if (filter && filter(self, f))
symbol__delete(f, self->sym_priv_size);
@@ -646,6 +660,9 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
}

err = nr;
+out_dlclose:
+ if (handle)
+ dlclose(handle);
out_elf_end:
elf_end(elf);
out_close:
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/