aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Pitre <nicolas.pitre@linaro.org>2010-08-11 01:20:14 -0400
committerNicolas Pitre <nicolas.pitre@linaro.org>2010-08-11 01:20:14 -0400
commit21ee0ab5fa80eb7307079e1a126f642fe7a937a6 (patch)
treef32505494b46b02cd9072fc399b57d73e27f1c98
parent5aa8d1a23dfdc1e331c134164009cc929c63447e (diff)
parent7987abe499b0721ca8a5629758e0ce3e07d34dc6 (diff)
Merge remote branch 'willd/for-linaro'
Conflicts: arch/arm/mm/flush.c
-rw-r--r--tools/perf/builtin-buildid-list.c4
-rw-r--r--tools/perf/builtin-diff.c2
-rw-r--r--tools/perf/builtin-report.c2
-rw-r--r--tools/perf/util/event.c10
-rw-r--r--tools/perf/util/map.c22
-rw-r--r--tools/perf/util/map.h2
-rw-r--r--tools/perf/util/session.c22
-rw-r--r--tools/perf/util/symbol.c206
-rw-r--r--tools/perf/util/symbol.h1
9 files changed, 121 insertions, 150 deletions
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 99890728409..44a47e13bd6 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -43,10 +43,8 @@ static int __cmd_buildid_list(void)
if (session == NULL)
return -1;
- if (with_hits) {
- symbol_conf.full_paths = true;
+ if (with_hits)
perf_session__process_events(session, &build_id__mark_dso_hit_ops);
- }
perf_session__fprintf_dsos_buildid(session, stdout, with_hits);
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index a6e2fdc7a04..33730c8211d 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -185,8 +185,6 @@ static const struct option options[] = {
OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
"load module symbols - WARNING: use only with -k and LIVE kernel"),
- OPT_BOOLEAN('P', "full-paths", &symbol_conf.full_paths,
- "Don't shorten the pathnames taking into account the cwd"),
OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
"only consider symbols in these dsos"),
OPT_STRING('C', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index fd7407c7205..47e304e21cf 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -464,8 +464,6 @@ static const struct option options[] = {
"pretty printing style key: normal raw"),
OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
"sort by key(s): pid, comm, dso, symbol, parent"),
- OPT_BOOLEAN('P', "full-paths", &symbol_conf.full_paths,
- "Don't shorten the pathnames taking into account the cwd"),
OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
"Show sample percentage for different cpu modes"),
OPT_STRING('p', "parent", &parent_pattern, "regex",
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 2fbf6a463c8..2e5352565eb 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -151,7 +151,6 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
continue;
pbf += n + 3;
if (*pbf == 'x') { /* vm_exec */
- u64 vm_pgoff;
char *execname = strchr(bf, '/');
/* Catch VDSO */
@@ -162,12 +161,7 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
continue;
pbf += 3;
- n = hex2u64(pbf, &vm_pgoff);
- /* pgoff is in bytes, not pages */
- if (n >= 0)
- ev.mmap.pgoff = vm_pgoff << getpagesize();
- else
- ev.mmap.pgoff = 0;
+ n = hex2u64(pbf, &ev.mmap.pgoff);
size = strlen(execname);
execname[size - 1] = '\0'; /* Remove \n */
@@ -517,7 +511,7 @@ int event__process_mmap(event_t *self, struct perf_session *session)
map = map__new(&machine->user_dsos, self->mmap.start,
self->mmap.len, self->mmap.pgoff,
self->mmap.pid, self->mmap.filename,
- MAP__FUNCTION, session->cwd, session->cwdlen);
+ MAP__FUNCTION);
if (thread == NULL || map == NULL)
goto out_problem;
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index e672f2fef65..37cab903853 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -17,16 +17,6 @@ static inline int is_anon_memory(const char *filename)
return strcmp(filename, "//anon") == 0;
}
-static int strcommon(const char *pathname, char *cwd, int cwdlen)
-{
- int n = 0;
-
- while (n < cwdlen && pathname[n] == cwd[n])
- ++n;
-
- return n;
-}
-
void map__init(struct map *self, enum map_type type,
u64 start, u64 end, u64 pgoff, struct dso *dso)
{
@@ -43,7 +33,7 @@ void map__init(struct map *self, enum map_type type,
struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
u64 pgoff, u32 pid, char *filename,
- enum map_type type, char *cwd, int cwdlen)
+ enum map_type type)
{
struct map *self = malloc(sizeof(*self));
@@ -52,16 +42,6 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
struct dso *dso;
int anon;
- if (cwd) {
- int n = strcommon(filename, cwd, cwdlen);
-
- if (n == cwdlen) {
- snprintf(newfilename, sizeof(newfilename),
- ".%s", filename + n);
- filename = newfilename;
- }
- }
-
anon = is_anon_memory(filename);
if (anon) {
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index f3913451282..3b2f706c0ba 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -106,7 +106,7 @@ void map__init(struct map *self, enum map_type type,
u64 start, u64 end, u64 pgoff, struct dso *dso);
struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
u64 pgoff, u32 pid, char *filename,
- enum map_type type, char *cwd, int cwdlen);
+ enum map_type type);
void map__delete(struct map *self);
struct map *map__clone(struct map *self);
int map__overlap(struct map *l, struct map *r);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index c422cd67631..c777c25af65 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -94,8 +94,6 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc
self->hists_tree = RB_ROOT;
self->last_match = NULL;
self->mmap_window = 32;
- self->cwd = NULL;
- self->cwdlen = 0;
self->machines = RB_ROOT;
self->repipe = repipe;
INIT_LIST_HEAD(&self->ordered_samples.samples_head);
@@ -128,7 +126,6 @@ void perf_session__delete(struct perf_session *self)
{
perf_header__exit(&self->header);
close(self->fd);
- free(self->cwd);
free(self);
}
@@ -830,23 +827,6 @@ int perf_session__process_events(struct perf_session *self,
if (perf_session__register_idle_thread(self) == NULL)
return -ENOMEM;
- if (!symbol_conf.full_paths) {
- char bf[PATH_MAX];
-
- if (getcwd(bf, sizeof(bf)) == NULL) {
- err = -errno;
-out_getcwd_err:
- pr_err("failed to get the current directory\n");
- goto out_err;
- }
- self->cwd = strdup(bf);
- if (self->cwd == NULL) {
- err = -ENOMEM;
- goto out_getcwd_err;
- }
- self->cwdlen = strlen(self->cwd);
- }
-
if (!self->fd_pipe)
err = __perf_session__process_events(self,
self->header.data_offset,
@@ -854,7 +834,7 @@ out_getcwd_err:
self->size, ops);
else
err = __perf_session__process_pipe_events(self, ops);
-out_err:
+
return err;
}
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 5b276833e2b..c991525908b 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -25,6 +25,8 @@
#define NT_GNU_BUILD_ID 3
#endif
+static bool dso__build_id_equal(const struct dso *self, u8 *build_id);
+static int elf_read_build_id(Elf *elf, void *bf, size_t size);
static void dsos__add(struct list_head *head, struct dso *dso);
static struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
static int dso__load_kernel_sym(struct dso *self, struct map *map,
@@ -934,7 +936,8 @@ static bool elf_sec__is_a(GElf_Shdr *self, Elf_Data *secstrs, enum map_type type
}
static int dso__load_sym(struct dso *self, struct map *map, const char *name,
- int fd, symbol_filter_t filter, int kmodule)
+ int fd, symbol_filter_t filter, int kmodule,
+ int want_symtab)
{
struct kmap *kmap = self->kernel ? map__kmap(map) : NULL;
struct map *curr_map = map;
@@ -953,17 +956,32 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
if (elf == NULL) {
- pr_err("%s: cannot read %s ELF file.\n", __func__, name);
+ pr_debug("%s: cannot read %s ELF file.\n", __func__, name);
goto out_close;
}
if (gelf_getehdr(elf, &ehdr) == NULL) {
- pr_err("%s: cannot get elf header.\n", __func__);
+ pr_debug("%s: cannot get elf header.\n", __func__);
goto out_elf_end;
}
+ /* Always reject images with a mismatched build-id: */
+ if (self->has_build_id) {
+ u8 build_id[BUILD_ID_SIZE];
+
+ if (elf_read_build_id(elf, build_id,
+ BUILD_ID_SIZE) != BUILD_ID_SIZE)
+ goto out_elf_end;
+
+ if (!dso__build_id_equal(self, build_id))
+ goto out_elf_end;
+ }
+
sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
if (sec == NULL) {
+ if (want_symtab)
+ goto out_elf_end;
+
sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL);
if (sec == NULL)
goto out_elf_end;
@@ -1075,7 +1093,15 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
"sh_addr: %#Lx sh_offset: %#Lx\n", __func__,
(u64)sym.st_value, (u64)shdr.sh_addr,
(u64)shdr.sh_offset);
- sym.st_value -= shdr.sh_addr - shdr.sh_offset;
+ /* Assumptions:
+ * a) shdr.sh_addr - shdr.sh_offset ==
+ * map->start - map->pgoff
+ * b) map->pgoff == 0
+ * These are true iff we are looking at a function
+ * symbol in the main executable segment _and_
+ * the main executable segment starts at the start of
+ * the ELF image (normally true). */
+ sym.st_value -= map->start;
}
/*
* We need to figure out if the object was created from C++ sources
@@ -1151,37 +1177,26 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
*/
#define NOTE_ALIGN(n) (((n) + 3) & -4U)
-int filename__read_build_id(const char *filename, void *bf, size_t size)
+static int elf_read_build_id(Elf *elf, void *bf, size_t size)
{
- int fd, err = -1;
+ int err = -1;
GElf_Ehdr ehdr;
GElf_Shdr shdr;
Elf_Data *data;
Elf_Scn *sec;
Elf_Kind ek;
void *ptr;
- Elf *elf;
if (size < BUILD_ID_SIZE)
goto out;
- fd = open(filename, O_RDONLY);
- if (fd < 0)
- goto out;
-
- elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
- if (elf == NULL) {
- pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
- goto out_close;
- }
-
ek = elf_kind(elf);
if (ek != ELF_K_ELF)
- goto out_elf_end;
+ goto out;
if (gelf_getehdr(elf, &ehdr) == NULL) {
pr_err("%s: cannot get elf header.\n", __func__);
- goto out_elf_end;
+ goto out;
}
sec = elf_section_by_name(elf, &ehdr, &shdr,
@@ -1190,12 +1205,12 @@ int filename__read_build_id(const char *filename, void *bf, size_t size)
sec = elf_section_by_name(elf, &ehdr, &shdr,
".notes", NULL);
if (sec == NULL)
- goto out_elf_end;
+ goto out;
}
data = elf_getdata(sec, NULL);
if (data == NULL)
- goto out_elf_end;
+ goto out;
ptr = data->d_buf;
while (ptr < (data->d_buf + data->d_size)) {
@@ -1217,7 +1232,31 @@ int filename__read_build_id(const char *filename, void *bf, size_t size)
}
ptr += descsz;
}
-out_elf_end:
+
+out:
+ return err;
+}
+
+int filename__read_build_id(const char *filename, void *bf, size_t size)
+{
+ int fd, err = -1;
+ Elf *elf;
+
+ if (size < BUILD_ID_SIZE)
+ goto out;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ goto out;
+
+ elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
+ if (elf == NULL) {
+ pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
+ goto out_close;
+ }
+
+ err = elf_read_build_id(elf, bf, size);
+
elf_end(elf);
out_close:
close(fd);
@@ -1293,11 +1332,11 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
{
int size = PATH_MAX;
char *name;
- u8 build_id[BUILD_ID_SIZE];
int ret = -1;
int fd;
struct machine *machine;
const char *root_dir;
+ int want_symtab;
dso__set_loaded(self, map->type);
@@ -1324,13 +1363,18 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
return ret;
}
- self->origin = DSO__ORIG_BUILD_ID_CACHE;
- if (dso__build_id_filename(self, name, size) != NULL)
- goto open_file;
-more:
- do {
- self->origin++;
+ /* Iterate over candidate debug images.
+ * On the first pass, only load images if they have a full symtab.
+ * Failing that, do a second pass where we accept .dynsym also
+ */
+ for (self->origin = DSO__ORIG_BUILD_ID_CACHE, want_symtab = 1;
+ self->origin != DSO__ORIG_NOT_FOUND;
+ self->origin++) {
switch (self->origin) {
+ case DSO__ORIG_BUILD_ID_CACHE:
+ if (dso__build_id_filename(self, name, size) == NULL)
+ continue;
+ break;
case DSO__ORIG_FEDORA:
snprintf(name, size, "/usr/lib/debug%s.debug",
self->long_name);
@@ -1339,21 +1383,20 @@ more:
snprintf(name, size, "/usr/lib/debug%s",
self->long_name);
break;
- case DSO__ORIG_BUILDID:
- if (filename__read_build_id(self->long_name, build_id,
- sizeof(build_id))) {
- char build_id_hex[BUILD_ID_SIZE * 2 + 1];
- build_id__sprintf(build_id, sizeof(build_id),
- build_id_hex);
- snprintf(name, size,
- "/usr/lib/debug/.build-id/%.2s/%s.debug",
- build_id_hex, build_id_hex + 2);
- if (self->has_build_id)
- goto compare_build_id;
- break;
+ case DSO__ORIG_BUILDID: {
+ char build_id_hex[BUILD_ID_SIZE * 2 + 1];
+
+ if (!self->has_build_id)
+ continue;
+
+ build_id__sprintf(self->build_id,
+ sizeof(self->build_id),
+ build_id_hex);
+ snprintf(name, size,
+ "/usr/lib/debug/.build-id/%.2s/%s.debug",
+ build_id_hex, build_id_hex + 2);
}
- self->origin++;
- /* Fall thru */
+ break;
case DSO__ORIG_DSO:
snprintf(name, size, "%s", self->long_name);
break;
@@ -1366,36 +1409,41 @@ more:
break;
default:
- goto out;
+ /*
+ * If we wanted a full symtab but no image had one,
+ * relax our requirements and repeat the search.
+ */
+ if (want_symtab) {
+ want_symtab = 0;
+ self->origin = DSO__ORIG_BUILD_ID_CACHE;
+ } else
+ continue;
}
- if (self->has_build_id) {
- if (filename__read_build_id(name, build_id,
- sizeof(build_id)) < 0)
- goto more;
-compare_build_id:
- if (!dso__build_id_equal(self, build_id))
- goto more;
- }
-open_file:
+ /* Name is now the name of the next image to try */
fd = open(name, O_RDONLY);
- } while (fd < 0);
+ if (fd < 0)
+ continue;
- ret = dso__load_sym(self, map, name, fd, filter, 0);
- close(fd);
+ ret = dso__load_sym(self, map, name, fd, filter, 0,
+ want_symtab);
+ close(fd);
- /*
- * Some people seem to have debuginfo files _WITHOUT_ debug info!?!?
- */
- if (!ret)
- goto more;
+ /*
+ * Some people seem to have debuginfo files _WITHOUT_ debug
+ * info!?!?
+ */
+ if (!ret)
+ continue;
- if (ret > 0) {
- int nr_plt = dso__synthesize_plt_symbols(self, map, filter);
- if (nr_plt > 0)
- ret += nr_plt;
+ if (ret > 0) {
+ int nr_plt = dso__synthesize_plt_symbols(self, map, filter);
+ if (nr_plt > 0)
+ ret += nr_plt;
+ break;
+ }
}
-out:
+
free(name);
if (ret < 0 && strstr(self->name, " (deleted)") != NULL)
return 0;
@@ -1656,36 +1704,12 @@ static int dso__load_vmlinux(struct dso *self, struct map *map,
{
int err = -1, fd;
- if (self->has_build_id) {
- u8 build_id[BUILD_ID_SIZE];
-
- if (filename__read_build_id(vmlinux, build_id,
- sizeof(build_id)) < 0) {
- pr_debug("No build_id in %s, ignoring it\n", vmlinux);
- return -1;
- }
- if (!dso__build_id_equal(self, build_id)) {
- char expected_build_id[BUILD_ID_SIZE * 2 + 1],
- vmlinux_build_id[BUILD_ID_SIZE * 2 + 1];
-
- build_id__sprintf(self->build_id,
- sizeof(self->build_id),
- expected_build_id);
- build_id__sprintf(build_id, sizeof(build_id),
- vmlinux_build_id);
- pr_debug("build_id in %s is %s while expected is %s, "
- "ignoring it\n", vmlinux, vmlinux_build_id,
- expected_build_id);
- return -1;
- }
- }
-
fd = open(vmlinux, O_RDONLY);
if (fd < 0)
return -1;
dso__set_loaded(self, map->type);
- err = dso__load_sym(self, map, vmlinux, fd, filter, 0);
+ err = dso__load_sym(self, map, vmlinux, fd, filter, 0, 0);
close(fd);
if (err > 0)
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 5e02d2c1715..5ce2ee16fca 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -70,7 +70,6 @@ struct symbol_conf {
show_nr_samples,
use_callchain,
exclude_other,
- full_paths,
show_cpu_utilization;
const char *vmlinux_name,
*field_sep;