Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 94cb9e38 authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo Committed by Ingo Molnar
Browse files

perf report: Add debug help for the finding of symbol bugs - show the symtab...


perf report: Add debug help for the finding of symbol bugs - show the symtab origin (DSO, build-id, kernel, etc)

Used with perf report --verbose:

[acme@doppio linux-2.6-tip]$ perf report -v | head -16
     5.17%  firefox  /usr/lib64/xulrunner-1.9.1/libxul.so   0x00000000005d8eee f [.] imgContainer::DrawFrameTo(gfxIImageFrame*, gfxIImageFrame*, nsRect&)
     2.56%  firefox  /lib64/libpthread-2.10.1.so            0x0000000000008e02 d [.] __pthread_mutex_lock_internal
     1.94%  firefox  /usr/lib64/xulrunner-1.9.1/libxul.so   0x0000000000d0af8f f [.] SearchTable
     1.75%  firefox  [kernel]                               0xffffffffff60013b k [.] vread_hpet
     1.63%  firefox  /lib64/libpthread-2.10.1.so            0x000000000000a404 d [.] __pthread_mutex_unlock
     1.47%  firefox  /usr/lib64/xulrunner-1.9.1/libmozjs.so 0x00000000000482ea f [.] js_Interpret
     1.42%  firefox  /usr/lib64/xulrunner-1.9.1/libmozjs.so 0x000000000003eda3 f [.] JS_CallTracer
     1.24%  firefox  [kernel]                               0xffffffff8102ca4a k [k] read_hpet
     1.16%  firefox  [kernel]                               0xffffffff810f3dd4 k [k] fget_light
     1.11%  firefox  /usr/lib64/xulrunner-1.9.1/libmozjs.so 0x00000000000567ff f [.] js_TraceObject
     0.98%  firefox  /usr/lib64/firefox-3.5.2/firefox       0x000000000000dd23 b [.] arena_ralloc
[acme@doppio linux-2.6-tip]$

The new field is just after the symbol address. To help in
figuring out symbol resolution bugs.

Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Acked-by: default avatarPeter Zijlstra <peterz@infradead.org>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 8f18aec5
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -700,7 +700,8 @@ sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used)
	size_t ret = 0;
	size_t ret = 0;


	if (verbose)
	if (verbose)
		ret += repsep_fprintf(fp, "%#018llx  ", (u64)self->ip);
		ret += repsep_fprintf(fp, "%#018llx %c ", (u64)self->ip,
				      dso__symtab_origin(self->dso));


	ret += repsep_fprintf(fp, "[%c] ", self->level);
	ret += repsep_fprintf(fp, "[%c] ", self->level);
	if (self->sym) {
	if (self->sym) {
+46 −11
Original line number Original line Diff line number Diff line
@@ -24,6 +24,16 @@ const char *sym_hist_filter;
#define DMGL_ANSI        (1 << 1)       /* Include const, volatile, etc */
#define DMGL_ANSI        (1 << 1)       /* Include const, volatile, etc */
#endif
#endif


enum dso_origin {
	DSO__ORIG_KERNEL = 0,
	DSO__ORIG_JAVA_JIT,
	DSO__ORIG_FEDORA,
	DSO__ORIG_UBUNTU,
	DSO__ORIG_BUILDID,
	DSO__ORIG_DSO,
	DSO__ORIG_NOT_FOUND,
};

static struct symbol *symbol__new(u64 start, u64 len,
static struct symbol *symbol__new(u64 start, u64 len,
				  const char *name, unsigned int priv_size,
				  const char *name, unsigned int priv_size,
				  u64 obj_start, int verbose)
				  u64 obj_start, int verbose)
@@ -81,6 +91,7 @@ struct dso *dso__new(const char *name, unsigned int sym_priv_size)
		self->sym_priv_size = sym_priv_size;
		self->sym_priv_size = sym_priv_size;
		self->find_symbol = dso__find_symbol;
		self->find_symbol = dso__find_symbol;
		self->slen_calculated = 0;
		self->slen_calculated = 0;
		self->origin = DSO__ORIG_NOT_FOUND;
	}
	}


	return self;
	return self;
@@ -710,7 +721,7 @@ static char *dso__read_build_id(struct dso *self, int verbose)
		++raw;
		++raw;
		bid += 2;
		bid += 2;
	}
	}
	if (verbose)
	if (verbose >= 2)
		printf("%s(%s): %s\n", __func__, self->name, build_id);
		printf("%s(%s): %s\n", __func__, self->name, build_id);
out_elf_end:
out_elf_end:
	elf_end(elf);
	elf_end(elf);
@@ -720,11 +731,26 @@ static char *dso__read_build_id(struct dso *self, int verbose)
	return build_id;
	return build_id;
}
}


char dso__symtab_origin(const struct dso *self)
{
	static const char origin[] = {
		[DSO__ORIG_KERNEL] =   'k',
		[DSO__ORIG_JAVA_JIT] = 'j',
		[DSO__ORIG_FEDORA] =   'f',
		[DSO__ORIG_UBUNTU] =   'u',
		[DSO__ORIG_BUILDID] =  'b',
		[DSO__ORIG_DSO] =      'd',
	};

	if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND)
		return '!';
	return origin[self->origin];
}

int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
{
{
	int size = PATH_MAX;
	int size = PATH_MAX;
	char *name = malloc(size), *build_id = NULL;
	char *name = malloc(size), *build_id = NULL;
	int variant = 0;
	int ret = -1;
	int ret = -1;
	int fd;
	int fd;


@@ -733,19 +759,26 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose)


	self->adjust_symbols = 0;
	self->adjust_symbols = 0;


	if (strncmp(self->name, "/tmp/perf-", 10) == 0)
	if (strncmp(self->name, "/tmp/perf-", 10) == 0) {
		return dso__load_perf_map(self, filter, verbose);
		ret = dso__load_perf_map(self, filter, verbose);
		self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT :
					 DSO__ORIG_NOT_FOUND;
		return ret;
	}

	self->origin = DSO__ORIG_FEDORA - 1;


more:
more:
	do {
	do {
		switch (variant) {
		self->origin++;
		case 0: /* Fedora */
		switch (self->origin) {
		case DSO__ORIG_FEDORA:
			snprintf(name, size, "/usr/lib/debug%s.debug", self->name);
			snprintf(name, size, "/usr/lib/debug%s.debug", self->name);
			break;
			break;
		case 1: /* Ubuntu */
		case DSO__ORIG_UBUNTU:
			snprintf(name, size, "/usr/lib/debug%s", self->name);
			snprintf(name, size, "/usr/lib/debug%s", self->name);
			break;
			break;
		case 2:
		case DSO__ORIG_BUILDID:
			build_id = dso__read_build_id(self, verbose);
			build_id = dso__read_build_id(self, verbose);
			if (build_id != NULL) {
			if (build_id != NULL) {
				snprintf(name, size,
				snprintf(name, size,
@@ -754,16 +787,15 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
				free(build_id);
				free(build_id);
				break;
				break;
			}
			}
			variant++;
			self->origin++;
			/* Fall thru */
			/* Fall thru */
		case 3: /* Sane people */
		case DSO__ORIG_DSO:
			snprintf(name, size, "%s", self->name);
			snprintf(name, size, "%s", self->name);
			break;
			break;


		default:
		default:
			goto out;
			goto out;
		}
		}
		variant++;


		fd = open(name, O_RDONLY);
		fd = open(name, O_RDONLY);
	} while (fd < 0);
	} while (fd < 0);
@@ -899,6 +931,9 @@ int dso__load_kernel(struct dso *self, const char *vmlinux,
	if (err <= 0)
	if (err <= 0)
		err = dso__load_kallsyms(self, filter, verbose);
		err = dso__load_kallsyms(self, filter, verbose);


	if (err > 0)
		self->origin = DSO__ORIG_KERNEL;

	return err;
	return err;
}
}


+2 −0
Original line number Original line Diff line number Diff line
@@ -26,6 +26,7 @@ struct dso {
	unsigned int	 sym_priv_size;
	unsigned int	 sym_priv_size;
	unsigned char	 adjust_symbols;
	unsigned char	 adjust_symbols;
	unsigned char	 slen_calculated;
	unsigned char	 slen_calculated;
	unsigned char	 origin;
	char		 name[0];
	char		 name[0];
};
};


@@ -49,6 +50,7 @@ int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose);
int dso__load(struct dso *self, symbol_filter_t filter, int verbose);
int dso__load(struct dso *self, symbol_filter_t filter, int verbose);


size_t dso__fprintf(struct dso *self, FILE *fp);
size_t dso__fprintf(struct dso *self, FILE *fp);
char dso__symtab_origin(const struct dso *self);


void symbol__init(void);
void symbol__init(void);
#endif /* _PERF_SYMBOL_ */
#endif /* _PERF_SYMBOL_ */