Commit f57b05ed532ccf3b3e22878a5678ca10de50ad29
Committed by
Arnaldo Carvalho de Melo
1 parent
fc8ed7be73
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>
Showing 3 changed files with 42 additions and 27 deletions Side-by-side Diff
tools/perf/util/header.c
... | ... | @@ -726,7 +726,16 @@ |
726 | 726 | return -1; |
727 | 727 | |
728 | 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 | 739 | memcpy(bev.build_id, old_bev.build_id, sizeof(bev.build_id)); |
731 | 740 | __event_process_build_id(&bev, filename, session); |
732 | 741 |
tools/perf/util/symbol.c
... | ... | @@ -2181,32 +2181,27 @@ |
2181 | 2181 | return ret; |
2182 | 2182 | } |
2183 | 2183 | |
2184 | -struct dso *dso__new_kernel(const char *name) | |
2184 | +static struct dso* | |
2185 | +dso__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 | + /* | |
2189 | + * The kernel dso could be created by build_id processing. | |
2190 | + */ | |
2191 | + struct dso *dso = __dsos__findnew(&machine->kernel_dsos, name); | |
2187 | 2192 | |
2193 | + /* | |
2194 | + * We need to run this in all cases, since during the build_id | |
2195 | + * processing we had no idea this was the kernel dso. | |
2196 | + */ | |
2188 | 2197 | if (dso != NULL) { |
2189 | - dso__set_short_name(dso, "[kernel]"); | |
2190 | - dso->kernel = DSO_TYPE_KERNEL; | |
2198 | + dso__set_short_name(dso, short_name); | |
2199 | + dso->kernel = dso_type; | |
2191 | 2200 | } |
2192 | 2201 | |
2193 | 2202 | return dso; |
2194 | 2203 | } |
2195 | 2204 | |
2196 | -static struct dso *dso__new_guest_kernel(struct machine *machine, | |
2197 | - const char *name) | |
2198 | -{ | |
2199 | - char bf[PATH_MAX]; | |
2200 | - struct dso *dso = dso__new(name ?: machine__mmap_name(machine, bf, | |
2201 | - sizeof(bf))); | |
2202 | - if (dso != NULL) { | |
2203 | - dso__set_short_name(dso, "[guest.kernel]"); | |
2204 | - dso->kernel = DSO_TYPE_GUEST_KERNEL; | |
2205 | - } | |
2206 | - | |
2207 | - return dso; | |
2208 | -} | |
2209 | - | |
2210 | 2205 | void dso__read_running_kernel_build_id(struct dso *dso, struct machine *machine) |
2211 | 2206 | { |
2212 | 2207 | char path[PATH_MAX]; |
2213 | 2208 | |
2214 | 2209 | |
2215 | 2210 | |
2216 | 2211 | |
2217 | 2212 | |
... | ... | @@ -2219,24 +2214,36 @@ |
2219 | 2214 | dso->has_build_id = true; |
2220 | 2215 | } |
2221 | 2216 | |
2222 | -static struct dso *machine__create_kernel(struct machine *machine) | |
2217 | +static struct dso *machine__get_kernel(struct machine *machine) | |
2223 | 2218 | { |
2224 | 2219 | const char *vmlinux_name = NULL; |
2225 | 2220 | struct dso *kernel; |
2226 | 2221 | |
2227 | 2222 | if (machine__is_host(machine)) { |
2228 | 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 | 2230 | } else { |
2231 | + char bf[PATH_MAX]; | |
2232 | + | |
2231 | 2233 | if (machine__is_default_guest(machine)) |
2232 | 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 | 2245 | dso__read_running_kernel_build_id(kernel, machine); |
2238 | - dsos__add(&machine->kernel_dsos, kernel); | |
2239 | - } | |
2246 | + | |
2240 | 2247 | return kernel; |
2241 | 2248 | } |
2242 | 2249 | |
... | ... | @@ -2340,7 +2347,7 @@ |
2340 | 2347 | |
2341 | 2348 | int 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 | 2352 | if (kernel == NULL || |
2346 | 2353 | __machine__create_kernel_maps(machine, kernel) < 0) |
tools/perf/util/symbol.h