aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorJiri Olsa <jolsa@redhat.com>2011-06-01 15:43:46 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2011-08-11 07:58:03 -0400
commitf57b05ed532ccf3b3e22878a5678ca10de50ad29 (patch)
tree97fed90fc6181939af5a29dfc9624163832b34e6 /tools
parentfc8ed7be738ffb1b3b0140ed2de6def38b9a7101 (diff)
perf report: Use properly build_id kernel binaries
If we bring the recorded perf data together with kernel binary from another machine using: on server A: perf archive on server B: tar xjvf perf.data.tar.bz2 -C ~/.debug the build_id kernel dso is not properly recognized during the "perf report" command on server B. The reason is, that build_id dsos are added during the session initialization, while the kernel maps are created during the sample event processing. The machine__create_kernel_maps functions ends up creating new dso object for kernel, but it does not check if we already have one added by build_id processing. Also the build_id reading ABI quirk added in commit: - commit b25114817a73bbd2b84ce9dba02ee1ef8989a947 perf build-id: Add quirk to deal with perf.data file format breakage populates the "struct build_id_event::pid" with 0, which is later interpreted as DEFAULT_GUEST_KERNEL_ID. This is not always correct, so it's better to guess the pid value based on the "struct build_id_event::header::misc" value. - Tested with data generated on x86 kernel version v2.6.34 and reported back on x86_64 current kernel. - Not tested for guest kernel case. Note the problem stays for PERF_RECORD_MMAP events recorded by perf that does not use proper pid (HOST_KERNEL_ID/DEFAULT_GUEST_KERNEL_ID). They are misinterpreted within the current perf code. Probably there's not much we can do about that. Cc: Avi Kivity <avi@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Yanmin Zhang <yanmin_zhang@linux.intel.com> Link: http://lkml.kernel.org/r/20110601194346.GB1934@jolsa.brq.redhat.com Signed-off-by: Jiri Olsa <jolsa@redhat.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/util/header.c11
-rw-r--r--tools/perf/util/symbol.c57
-rw-r--r--tools/perf/util/symbol.h1
3 files changed, 42 insertions, 27 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index d4f3101773db..b6c1ad123ca9 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -726,7 +726,16 @@ static int perf_header__read_build_ids_abi_quirk(struct perf_header *header,
726 return -1; 726 return -1;
727 727
728 bev.header = old_bev.header; 728 bev.header = old_bev.header;
729 bev.pid = 0; 729
730 /*
731 * As the pid is the missing value, we need to fill
732 * it properly. The header.misc value give us nice hint.
733 */
734 bev.pid = HOST_KERNEL_ID;
735 if (bev.header.misc == PERF_RECORD_MISC_GUEST_USER ||
736 bev.header.misc == PERF_RECORD_MISC_GUEST_KERNEL)
737 bev.pid = DEFAULT_GUEST_KERNEL_ID;
738
730 memcpy(bev.build_id, old_bev.build_id, sizeof(bev.build_id)); 739 memcpy(bev.build_id, old_bev.build_id, sizeof(bev.build_id));
731 __event_process_build_id(&bev, filename, session); 740 __event_process_build_id(&bev, filename, session);
732 741
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index a8b53714542a..e142c21ae9a5 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -2181,27 +2181,22 @@ size_t machines__fprintf_dsos_buildid(struct rb_root *machines,
2181 return ret; 2181 return ret;
2182} 2182}
2183 2183
2184struct dso *dso__new_kernel(const char *name) 2184static struct dso*
2185dso__kernel_findnew(struct machine *machine, const char *name,
2186 const char *short_name, int dso_type)
2185{ 2187{
2186 struct dso *dso = dso__new(name ?: "[kernel.kallsyms]"); 2188 /*
2187 2189 * The kernel dso could be created by build_id processing.
2188 if (dso != NULL) { 2190 */
2189 dso__set_short_name(dso, "[kernel]"); 2191 struct dso *dso = __dsos__findnew(&machine->kernel_dsos, name);
2190 dso->kernel = DSO_TYPE_KERNEL;
2191 }
2192
2193 return dso;
2194}
2195 2192
2196static struct dso *dso__new_guest_kernel(struct machine *machine, 2193 /*
2197 const char *name) 2194 * We need to run this in all cases, since during the build_id
2198{ 2195 * processing we had no idea this was the kernel dso.
2199 char bf[PATH_MAX]; 2196 */
2200 struct dso *dso = dso__new(name ?: machine__mmap_name(machine, bf,
2201 sizeof(bf)));
2202 if (dso != NULL) { 2197 if (dso != NULL) {
2203 dso__set_short_name(dso, "[guest.kernel]"); 2198 dso__set_short_name(dso, short_name);
2204 dso->kernel = DSO_TYPE_GUEST_KERNEL; 2199 dso->kernel = dso_type;
2205 } 2200 }
2206 2201
2207 return dso; 2202 return dso;
@@ -2219,24 +2214,36 @@ void dso__read_running_kernel_build_id(struct dso *dso, struct machine *machine)
2219 dso->has_build_id = true; 2214 dso->has_build_id = true;
2220} 2215}
2221 2216
2222static struct dso *machine__create_kernel(struct machine *machine) 2217static struct dso *machine__get_kernel(struct machine *machine)
2223{ 2218{
2224 const char *vmlinux_name = NULL; 2219 const char *vmlinux_name = NULL;
2225 struct dso *kernel; 2220 struct dso *kernel;
2226 2221
2227 if (machine__is_host(machine)) { 2222 if (machine__is_host(machine)) {
2228 vmlinux_name = symbol_conf.vmlinux_name; 2223 vmlinux_name = symbol_conf.vmlinux_name;
2229 kernel = dso__new_kernel(vmlinux_name); 2224 if (!vmlinux_name)
2225 vmlinux_name = "[kernel.kallsyms]";
2226
2227 kernel = dso__kernel_findnew(machine, vmlinux_name,
2228 "[kernel]",
2229 DSO_TYPE_KERNEL);
2230 } else { 2230 } else {
2231 char bf[PATH_MAX];
2232
2231 if (machine__is_default_guest(machine)) 2233 if (machine__is_default_guest(machine))
2232 vmlinux_name = symbol_conf.default_guest_vmlinux_name; 2234 vmlinux_name = symbol_conf.default_guest_vmlinux_name;
2233 kernel = dso__new_guest_kernel(machine, vmlinux_name); 2235 if (!vmlinux_name)
2236 vmlinux_name = machine__mmap_name(machine, bf,
2237 sizeof(bf));
2238
2239 kernel = dso__kernel_findnew(machine, vmlinux_name,
2240 "[guest.kernel]",
2241 DSO_TYPE_GUEST_KERNEL);
2234 } 2242 }
2235 2243
2236 if (kernel != NULL) { 2244 if (kernel != NULL && (!kernel->has_build_id))
2237 dso__read_running_kernel_build_id(kernel, machine); 2245 dso__read_running_kernel_build_id(kernel, machine);
2238 dsos__add(&machine->kernel_dsos, kernel); 2246
2239 }
2240 return kernel; 2247 return kernel;
2241} 2248}
2242 2249
@@ -2340,7 +2347,7 @@ void machine__destroy_kernel_maps(struct machine *machine)
2340 2347
2341int machine__create_kernel_maps(struct machine *machine) 2348int machine__create_kernel_maps(struct machine *machine)
2342{ 2349{
2343 struct dso *kernel = machine__create_kernel(machine); 2350 struct dso *kernel = machine__get_kernel(machine);
2344 2351
2345 if (kernel == NULL || 2352 if (kernel == NULL ||
2346 __machine__create_kernel_maps(machine, kernel) < 0) 2353 __machine__create_kernel_maps(machine, kernel) < 0)
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 325ee36a9d29..4f377d92e75a 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -155,7 +155,6 @@ struct dso {
155}; 155};
156 156
157struct dso *dso__new(const char *name); 157struct dso *dso__new(const char *name);
158struct dso *dso__new_kernel(const char *name);
159void dso__delete(struct dso *dso); 158void dso__delete(struct dso *dso);
160 159
161int dso__name_len(const struct dso *dso); 160int dso__name_len(const struct dso *dso);