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. |