diff options
| -rw-r--r-- | tools/perf/util/dso.c | 75 | ||||
| -rw-r--r-- | tools/perf/util/dso.h | 7 | ||||
| -rw-r--r-- | tools/perf/util/machine.c | 19 | ||||
| -rw-r--r-- | tools/perf/util/symbol-elf.c | 35 | ||||
| -rw-r--r-- | tools/perf/util/symbol.c | 8 |
5 files changed, 141 insertions, 3 deletions
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 0247acfdfaca..36a607cf8f50 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c | |||
| @@ -21,8 +21,10 @@ char dso__symtab_origin(const struct dso *dso) | |||
| 21 | [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b', | 21 | [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b', |
| 22 | [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd', | 22 | [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd', |
| 23 | [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K', | 23 | [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K', |
| 24 | [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP] = 'm', | ||
| 24 | [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g', | 25 | [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g', |
| 25 | [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G', | 26 | [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G', |
| 27 | [DSO_BINARY_TYPE__GUEST_KMODULE_COMP] = 'M', | ||
| 26 | [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V', | 28 | [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V', |
| 27 | }; | 29 | }; |
| 28 | 30 | ||
| @@ -112,11 +114,13 @@ int dso__read_binary_type_filename(const struct dso *dso, | |||
| 112 | break; | 114 | break; |
| 113 | 115 | ||
| 114 | case DSO_BINARY_TYPE__GUEST_KMODULE: | 116 | case DSO_BINARY_TYPE__GUEST_KMODULE: |
| 117 | case DSO_BINARY_TYPE__GUEST_KMODULE_COMP: | ||
| 115 | path__join3(filename, size, symbol_conf.symfs, | 118 | path__join3(filename, size, symbol_conf.symfs, |
| 116 | root_dir, dso->long_name); | 119 | root_dir, dso->long_name); |
| 117 | break; | 120 | break; |
| 118 | 121 | ||
| 119 | case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: | 122 | case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: |
| 123 | case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP: | ||
| 120 | __symbol__join_symfs(filename, size, dso->long_name); | 124 | __symbol__join_symfs(filename, size, dso->long_name); |
| 121 | break; | 125 | break; |
| 122 | 126 | ||
| @@ -137,6 +141,77 @@ int dso__read_binary_type_filename(const struct dso *dso, | |||
| 137 | return ret; | 141 | return ret; |
| 138 | } | 142 | } |
| 139 | 143 | ||
| 144 | static int decompress_dummy(const char *input __maybe_unused, | ||
| 145 | int output __maybe_unused) | ||
| 146 | { | ||
| 147 | return -1; | ||
| 148 | } | ||
| 149 | |||
| 150 | static const struct { | ||
| 151 | const char *fmt; | ||
| 152 | int (*decompress)(const char *input, int output); | ||
| 153 | } compressions[] = { | ||
| 154 | { "gz", decompress_dummy }, | ||
| 155 | { NULL, }, | ||
| 156 | }; | ||
| 157 | |||
| 158 | bool is_supported_compression(const char *ext) | ||
| 159 | { | ||
| 160 | unsigned i; | ||
| 161 | |||
| 162 | for (i = 0; compressions[i].fmt; i++) { | ||
| 163 | if (!strcmp(ext, compressions[i].fmt)) | ||
| 164 | return true; | ||
| 165 | } | ||
| 166 | return false; | ||
| 167 | } | ||
| 168 | |||
| 169 | bool is_kmodule_extension(const char *ext) | ||
| 170 | { | ||
| 171 | if (strncmp(ext, "ko", 2)) | ||
| 172 | return false; | ||
| 173 | |||
| 174 | if (ext[2] == '\0' || (ext[2] == '.' && is_supported_compression(ext+3))) | ||
| 175 | return true; | ||
| 176 | |||
| 177 | return false; | ||
| 178 | } | ||
| 179 | |||
| 180 | bool is_kernel_module(const char *pathname, bool *compressed) | ||
| 181 | { | ||
| 182 | const char *ext = strrchr(pathname, '.'); | ||
| 183 | |||
| 184 | if (ext == NULL) | ||
| 185 | return false; | ||
| 186 | |||
| 187 | if (is_supported_compression(ext + 1)) { | ||
| 188 | if (compressed) | ||
| 189 | *compressed = true; | ||
| 190 | ext -= 3; | ||
| 191 | } else if (compressed) | ||
| 192 | *compressed = false; | ||
| 193 | |||
| 194 | return is_kmodule_extension(ext + 1); | ||
| 195 | } | ||
| 196 | |||
| 197 | bool decompress_to_file(const char *ext, const char *filename, int output_fd) | ||
| 198 | { | ||
| 199 | unsigned i; | ||
| 200 | |||
| 201 | for (i = 0; compressions[i].fmt; i++) { | ||
| 202 | if (!strcmp(ext, compressions[i].fmt)) | ||
| 203 | return !compressions[i].decompress(filename, | ||
| 204 | output_fd); | ||
| 205 | } | ||
| 206 | return false; | ||
| 207 | } | ||
| 208 | |||
| 209 | bool dso__needs_decompress(struct dso *dso) | ||
| 210 | { | ||
| 211 | return dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP || | ||
| 212 | dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP; | ||
| 213 | } | ||
| 214 | |||
| 140 | /* | 215 | /* |
| 141 | * Global list of open DSOs and the counter. | 216 | * Global list of open DSOs and the counter. |
| 142 | */ | 217 | */ |
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index a316e4af321f..3782c82c6e44 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h | |||
| @@ -22,7 +22,9 @@ enum dso_binary_type { | |||
| 22 | DSO_BINARY_TYPE__BUILDID_DEBUGINFO, | 22 | DSO_BINARY_TYPE__BUILDID_DEBUGINFO, |
| 23 | DSO_BINARY_TYPE__SYSTEM_PATH_DSO, | 23 | DSO_BINARY_TYPE__SYSTEM_PATH_DSO, |
| 24 | DSO_BINARY_TYPE__GUEST_KMODULE, | 24 | DSO_BINARY_TYPE__GUEST_KMODULE, |
| 25 | DSO_BINARY_TYPE__GUEST_KMODULE_COMP, | ||
| 25 | DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, | 26 | DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, |
| 27 | DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP, | ||
| 26 | DSO_BINARY_TYPE__KCORE, | 28 | DSO_BINARY_TYPE__KCORE, |
| 27 | DSO_BINARY_TYPE__GUEST_KCORE, | 29 | DSO_BINARY_TYPE__GUEST_KCORE, |
| 28 | DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, | 30 | DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, |
| @@ -185,6 +187,11 @@ int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir); | |||
| 185 | char dso__symtab_origin(const struct dso *dso); | 187 | char dso__symtab_origin(const struct dso *dso); |
| 186 | int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type, | 188 | int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type, |
| 187 | char *root_dir, char *filename, size_t size); | 189 | char *root_dir, char *filename, size_t size); |
| 190 | bool is_supported_compression(const char *ext); | ||
| 191 | bool is_kmodule_extension(const char *ext); | ||
| 192 | bool is_kernel_module(const char *pathname, bool *compressed); | ||
| 193 | bool decompress_to_file(const char *ext, const char *filename, int output_fd); | ||
| 194 | bool dso__needs_decompress(struct dso *dso); | ||
| 188 | 195 | ||
| 189 | /* | 196 | /* |
| 190 | * The dso__data_* external interface provides following functions: | 197 | * The dso__data_* external interface provides following functions: |
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 51a630301afa..946c7d62cb6e 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
| @@ -464,6 +464,7 @@ struct map *machine__new_module(struct machine *machine, u64 start, | |||
| 464 | { | 464 | { |
| 465 | struct map *map; | 465 | struct map *map; |
| 466 | struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename); | 466 | struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename); |
| 467 | bool compressed; | ||
| 467 | 468 | ||
| 468 | if (dso == NULL) | 469 | if (dso == NULL) |
| 469 | return NULL; | 470 | return NULL; |
| @@ -476,6 +477,11 @@ struct map *machine__new_module(struct machine *machine, u64 start, | |||
| 476 | dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE; | 477 | dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE; |
| 477 | else | 478 | else |
| 478 | dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE; | 479 | dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE; |
| 480 | |||
| 481 | /* _KMODULE_COMP should be next to _KMODULE */ | ||
| 482 | if (is_kernel_module(filename, &compressed) && compressed) | ||
| 483 | dso->symtab_type++; | ||
| 484 | |||
| 479 | map_groups__insert(&machine->kmaps, map); | 485 | map_groups__insert(&machine->kmaps, map); |
| 480 | return map; | 486 | return map; |
| 481 | } | 487 | } |
| @@ -861,8 +867,14 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg, | |||
| 861 | struct map *map; | 867 | struct map *map; |
| 862 | char *long_name; | 868 | char *long_name; |
| 863 | 869 | ||
| 864 | if (dot == NULL || strcmp(dot, ".ko")) | 870 | if (dot == NULL) |
| 865 | continue; | 871 | continue; |
| 872 | |||
| 873 | /* On some system, modules are compressed like .ko.gz */ | ||
| 874 | if (is_supported_compression(dot + 1) && | ||
| 875 | is_kmodule_extension(dot - 2)) | ||
| 876 | dot -= 3; | ||
| 877 | |||
| 866 | snprintf(dso_name, sizeof(dso_name), "[%.*s]", | 878 | snprintf(dso_name, sizeof(dso_name), "[%.*s]", |
| 867 | (int)(dot - dent->d_name), dent->d_name); | 879 | (int)(dot - dent->d_name), dent->d_name); |
| 868 | 880 | ||
| @@ -1044,6 +1056,11 @@ static int machine__process_kernel_mmap_event(struct machine *machine, | |||
| 1044 | dot = strrchr(name, '.'); | 1056 | dot = strrchr(name, '.'); |
| 1045 | if (dot == NULL) | 1057 | if (dot == NULL) |
| 1046 | goto out_problem; | 1058 | goto out_problem; |
| 1059 | /* On some system, modules are compressed like .ko.gz */ | ||
| 1060 | if (is_supported_compression(dot + 1)) | ||
| 1061 | dot -= 3; | ||
| 1062 | if (!is_kmodule_extension(dot + 1)) | ||
| 1063 | goto out_problem; | ||
| 1047 | snprintf(short_module_name, sizeof(short_module_name), | 1064 | snprintf(short_module_name, sizeof(short_module_name), |
| 1048 | "[%.*s]", (int)(dot - name), name); | 1065 | "[%.*s]", (int)(dot - name), name); |
| 1049 | strxfrchar(short_module_name, '-', '_'); | 1066 | strxfrchar(short_module_name, '-', '_'); |
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 1e23a5bfb044..efc7eb6b8f0f 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c | |||
| @@ -546,6 +546,35 @@ static int dso__swap_init(struct dso *dso, unsigned char eidata) | |||
| 546 | return 0; | 546 | return 0; |
| 547 | } | 547 | } |
| 548 | 548 | ||
| 549 | static int decompress_kmodule(struct dso *dso, const char *name, | ||
| 550 | enum dso_binary_type type) | ||
| 551 | { | ||
| 552 | int fd; | ||
| 553 | const char *ext = strrchr(name, '.'); | ||
| 554 | char tmpbuf[] = "/tmp/perf-kmod-XXXXXX"; | ||
| 555 | |||
| 556 | if ((type != DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP && | ||
| 557 | type != DSO_BINARY_TYPE__GUEST_KMODULE_COMP) || | ||
| 558 | type != dso->symtab_type) | ||
| 559 | return -1; | ||
| 560 | |||
| 561 | if (!ext || !is_supported_compression(ext + 1)) | ||
| 562 | return -1; | ||
| 563 | |||
| 564 | fd = mkstemp(tmpbuf); | ||
| 565 | if (fd < 0) | ||
| 566 | return -1; | ||
| 567 | |||
| 568 | if (!decompress_to_file(ext + 1, name, fd)) { | ||
| 569 | close(fd); | ||
| 570 | fd = -1; | ||
| 571 | } | ||
| 572 | |||
| 573 | unlink(tmpbuf); | ||
| 574 | |||
| 575 | return fd; | ||
| 576 | } | ||
| 577 | |||
| 549 | bool symsrc__possibly_runtime(struct symsrc *ss) | 578 | bool symsrc__possibly_runtime(struct symsrc *ss) |
| 550 | { | 579 | { |
| 551 | return ss->dynsym || ss->opdsec; | 580 | return ss->dynsym || ss->opdsec; |
| @@ -571,7 +600,11 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name, | |||
| 571 | Elf *elf; | 600 | Elf *elf; |
| 572 | int fd; | 601 | int fd; |
| 573 | 602 | ||
| 574 | fd = open(name, O_RDONLY); | 603 | if (dso__needs_decompress(dso)) |
| 604 | fd = decompress_kmodule(dso, name, type); | ||
| 605 | else | ||
| 606 | fd = open(name, O_RDONLY); | ||
| 607 | |||
| 575 | if (fd < 0) | 608 | if (fd < 0) |
| 576 | return -1; | 609 | return -1; |
| 577 | 610 | ||
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 078331140d8c..c69915c9d5bc 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
| @@ -51,7 +51,9 @@ static enum dso_binary_type binary_type_symtab[] = { | |||
| 51 | DSO_BINARY_TYPE__BUILDID_DEBUGINFO, | 51 | DSO_BINARY_TYPE__BUILDID_DEBUGINFO, |
| 52 | DSO_BINARY_TYPE__SYSTEM_PATH_DSO, | 52 | DSO_BINARY_TYPE__SYSTEM_PATH_DSO, |
| 53 | DSO_BINARY_TYPE__GUEST_KMODULE, | 53 | DSO_BINARY_TYPE__GUEST_KMODULE, |
| 54 | DSO_BINARY_TYPE__GUEST_KMODULE_COMP, | ||
| 54 | DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, | 55 | DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, |
| 56 | DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP, | ||
| 55 | DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, | 57 | DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, |
| 56 | DSO_BINARY_TYPE__NOT_FOUND, | 58 | DSO_BINARY_TYPE__NOT_FOUND, |
| 57 | }; | 59 | }; |
| @@ -1300,7 +1302,9 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod, | |||
| 1300 | return dso->kernel == DSO_TYPE_GUEST_KERNEL; | 1302 | return dso->kernel == DSO_TYPE_GUEST_KERNEL; |
| 1301 | 1303 | ||
| 1302 | case DSO_BINARY_TYPE__GUEST_KMODULE: | 1304 | case DSO_BINARY_TYPE__GUEST_KMODULE: |
| 1305 | case DSO_BINARY_TYPE__GUEST_KMODULE_COMP: | ||
| 1303 | case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: | 1306 | case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: |
| 1307 | case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP: | ||
| 1304 | /* | 1308 | /* |
| 1305 | * kernel modules know their symtab type - it's set when | 1309 | * kernel modules know their symtab type - it's set when |
| 1306 | * creating a module dso in machine__new_module(). | 1310 | * creating a module dso in machine__new_module(). |
| @@ -1368,7 +1372,9 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) | |||
| 1368 | return -1; | 1372 | return -1; |
| 1369 | 1373 | ||
| 1370 | kmod = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE || | 1374 | kmod = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE || |
| 1371 | dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE; | 1375 | dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP || |
| 1376 | dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE || | ||
| 1377 | dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP; | ||
| 1372 | 1378 | ||
| 1373 | /* | 1379 | /* |
| 1374 | * Iterate over candidate debug images. | 1380 | * Iterate over candidate debug images. |
