Currently perf decompresses kernel modules when loading symbol table but it missed to do it when reading raw data. Move decompress_kmodule() to util/dso.c and do not unlink it immediately.
Signed-off-by: Namhyung Kim <[email protected]> --- tools/perf/util/dso.c | 56 ++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/dso.h | 2 ++ tools/perf/util/symbol-elf.c | 40 ++++--------------------------- 3 files changed, 63 insertions(+), 35 deletions(-) diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index b27d127cdf68..8dc1f147547c 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -350,6 +350,45 @@ void dso__set_module_info(struct dso *dso, struct kmod_path *m, dso__set_short_name(dso, strdup(m->name), true); } +int dso__decompress_kmodule(struct dso *dso, const char *filename, + char *buf, size_t sz) +{ + struct kmod_path m = {}; + int ret = -1; + int fd = -1; + + if (!dso__needs_decompress(dso)) + return -1; + + if (kmod_path__parse_ext(&m, filename) < 0) + goto out; + + if (!is_supported_compression(m.ext)) + goto out; + + snprintf(buf, sz, "/tmp/perf-kmod-XXXXXX"); + + fd = mkstemp(buf); + if (fd < 0) { + dso->load_errno = errno; + goto out; + } + + pr_debug("decompressing to %s\n", buf); + if (!decompress_to_file(m.ext, filename, fd)) { + dso->load_errno = DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE; + unlink(buf); + close(fd); + goto out; + } + ret = fd; + +out: + free(m.ext); + + return ret; +} + /* * Global list of open DSOs and the counter. */ @@ -399,6 +438,7 @@ static int __open_dso(struct dso *dso, struct machine *machine) int fd; char *root_dir = (char *)""; char *name = malloc(PATH_MAX); + bool needs_unlink = false; if (!name) return -ENOMEM; @@ -415,7 +455,23 @@ static int __open_dso(struct dso *dso, struct machine *machine) if (!is_regular_file(name)) return -EINVAL; + if (dso__needs_decompress(dso)) { + char buf[32]; + + fd = dso__decompress_kmodule(dso, name, buf, sizeof(buf)); + if (fd < 0) + return -1; + + close(fd); + strcpy(name, buf); + needs_unlink = true; + } + fd = do_open(name); + + if (needs_unlink) + unlink(name); + free(name); return fd; } diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index 5fe2ab5877bd..c1e4b94d41aa 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h @@ -244,6 +244,8 @@ bool is_supported_compression(const char *ext); bool is_kernel_module(const char *pathname, int cpumode); bool decompress_to_file(const char *ext, const char *filename, int output_fd); bool dso__needs_decompress(struct dso *dso); +int dso__decompress_kmodule(struct dso *dso, const char *filename, + char *buf, size_t sz); struct kmod_path { char *name; diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 1fb2efae4f02..b335f91f0cb3 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -637,40 +637,6 @@ static int dso__swap_init(struct dso *dso, unsigned char eidata) return 0; } -static int decompress_kmodule(struct dso *dso, const char *name, - enum dso_binary_type type) -{ - int fd = -1; - char tmpbuf[] = "/tmp/perf-kmod-XXXXXX"; - struct kmod_path m; - - if (type != DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP && - type != DSO_BINARY_TYPE__GUEST_KMODULE_COMP && - type != DSO_BINARY_TYPE__BUILD_ID_CACHE) - return -1; - - if (kmod_path__parse_ext(&m, dso->long_name) || !m.comp) - return -1; - - fd = mkstemp(tmpbuf); - if (fd < 0) { - dso->load_errno = errno; - goto out; - } - - if (!decompress_to_file(m.ext, name, fd)) { - dso->load_errno = DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE; - close(fd); - fd = -1; - } - - unlink(tmpbuf); - -out: - free(m.ext); - return fd; -} - bool symsrc__possibly_runtime(struct symsrc *ss) { return ss->dynsym || ss->opdsec; @@ -702,9 +668,13 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name, int fd; if (dso__needs_decompress(dso)) { - fd = decompress_kmodule(dso, name, type); + char buf[32]; + + fd = dso__decompress_kmodule(dso, name, buf, sizeof(buf)); if (fd < 0) return -1; + + unlink(buf); } else { fd = open(name, O_RDONLY); if (fd < 0) { -- 2.13.0

