aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorNamhyung Kim <namhyung@kernel.org>2014-11-03 20:14:27 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2014-11-04 08:15:53 -0500
commitc00c48fc6e6ef63d83a7417923a06b08089bb34b (patch)
tree08908b7bc276599a2f25550995040112c18dc78c /tools/perf/util
parent758008b262f70be41104e4e33ba99181ac03775d (diff)
perf symbols: Preparation for compressed kernel module support
This patch adds basic support to handle compressed kernel module as some distro (such as Archlinux) carries on it now. The actual work using compression library will be added later. Signed-off-by: Namhyung Kim <namhyung@kernel.org> Acked-by: Jiri Olsa <jolsa@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: David Ahern <dsahern@gmail.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Namhyung Kim <namhyung.kim@lge.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/r/1415063674-17206-2-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/dso.c75
-rw-r--r--tools/perf/util/dso.h7
-rw-r--r--tools/perf/util/machine.c19
-rw-r--r--tools/perf/util/symbol-elf.c35
-rw-r--r--tools/perf/util/symbol.c8
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
144static int decompress_dummy(const char *input __maybe_unused,
145 int output __maybe_unused)
146{
147 return -1;
148}
149
150static const struct {
151 const char *fmt;
152 int (*decompress)(const char *input, int output);
153} compressions[] = {
154 { "gz", decompress_dummy },
155 { NULL, },
156};
157
158bool 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
169bool 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
180bool 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
197bool 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
209bool 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);
185char dso__symtab_origin(const struct dso *dso); 187char dso__symtab_origin(const struct dso *dso);
186int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type, 188int 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);
190bool is_supported_compression(const char *ext);
191bool is_kmodule_extension(const char *ext);
192bool is_kernel_module(const char *pathname, bool *compressed);
193bool decompress_to_file(const char *ext, const char *filename, int output_fd);
194bool 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
549static 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
549bool symsrc__possibly_runtime(struct symsrc *ss) 578bool 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.