aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Olsa <jolsa@kernel.org>2015-02-05 09:40:25 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-03-21 13:53:41 -0400
commit3c8a67f50a1e68b912d1d74db6b455cac54ec4b4 (patch)
tree1d03faa7eaa676cf7eefa53f2f938409929dee72
parent80a32e5b498a7547073e5e4b2b804edc7219979d (diff)
perf tools: Add kmod_path__parse function
Provides united way of parsing kernel module path into several components. The new kmod_path__parse function and few defines: int __kmod_path__parse(struct kmod_path *m, const char *path, bool alloc_name, bool alloc_ext); #define kmod_path__parse(__m, __p) __kmod_path__parse(__m, __p, false, false) #define kmod_path__parse_name(__m, __p) __kmod_path__parse(__m, __p, true , false) #define kmod_path__parse_ext(__m, __p) __kmod_path__parse(__m, __p, false, true) parse kernel module @path and updates @m argument like: @comp - true if @path contains supported compression suffix, false otherwise @kmod - true if @path contains '.ko' suffix in right position, false otherwise @name - if (@alloc_name && @kmod) is true, it contains strdup-ed base name of the kernel module without suffixes, otherwise strudup-ed base name of @path @ext - if (@alloc_ext && @comp) is true, it contains strdup-ed string the compression suffix It returns 0 if there's no strdup error, -ENOMEM otherwise. Signed-off-by: Jiri Olsa <jolsa@kernel.org> Acked-by: Namhyung Kim <namhyung@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com> Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.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/n/tip-9t6eqg8j610r94l743hkntiv@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/tests/Build1
-rw-r--r--tools/perf/tests/builtin-test.c4
-rw-r--r--tools/perf/tests/kmod-path.c73
-rw-r--r--tools/perf/tests/tests.h1
-rw-r--r--tools/perf/util/dso.c66
-rw-r--r--tools/perf/util/dso.h14
6 files changed, 159 insertions, 0 deletions
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 2de01a4b4084..6a8801b32017 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -30,6 +30,7 @@ perf-y += keep-tracking.o
30perf-y += code-reading.o 30perf-y += code-reading.o
31perf-y += sample-parsing.o 31perf-y += sample-parsing.o
32perf-y += parse-no-sample-id-all.o 32perf-y += parse-no-sample-id-all.o
33perf-y += kmod-path.o
33 34
34perf-$(CONFIG_X86) += perf-time-to-tsc.o 35perf-$(CONFIG_X86) += perf-time-to-tsc.o
35 36
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index ed8e05c6839a..4f4098167112 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -167,6 +167,10 @@ static struct test {
167 .func = test__fdarray__add, 167 .func = test__fdarray__add,
168 }, 168 },
169 { 169 {
170 .desc = "Test kmod_path__parse function",
171 .func = test__kmod_path__parse,
172 },
173 {
170 .func = NULL, 174 .func = NULL,
171 }, 175 },
172}; 176};
diff --git a/tools/perf/tests/kmod-path.c b/tools/perf/tests/kmod-path.c
new file mode 100644
index 000000000000..e8d7cbb9320c
--- /dev/null
+++ b/tools/perf/tests/kmod-path.c
@@ -0,0 +1,73 @@
1#include <stdbool.h>
2#include "tests.h"
3#include "dso.h"
4#include "debug.h"
5
6static int test(const char *path, bool alloc_name, bool alloc_ext,
7 bool kmod, bool comp, const char *name, const char *ext)
8{
9 struct kmod_path m;
10
11 memset(&m, 0x0, sizeof(m));
12
13 TEST_ASSERT_VAL("kmod_path__parse",
14 !__kmod_path__parse(&m, path, alloc_name, alloc_ext));
15
16 pr_debug("%s - alloc name %d, alloc ext %d, kmod %d, comp %d, name '%s', ext '%s'\n",
17 path, alloc_name, alloc_ext, m.kmod, m.comp, m.name, m.ext);
18
19 TEST_ASSERT_VAL("wrong kmod", m.kmod == kmod);
20 TEST_ASSERT_VAL("wrong comp", m.comp == comp);
21
22 if (ext)
23 TEST_ASSERT_VAL("wrong ext", m.ext && !strcmp(ext, m.ext));
24 else
25 TEST_ASSERT_VAL("wrong ext", !m.ext);
26
27 if (name)
28 TEST_ASSERT_VAL("wrong name", m.name && !strcmp(name, m.name));
29 else
30 TEST_ASSERT_VAL("wrong name", !m.name);
31
32 free(m.name);
33 free(m.ext);
34 return 0;
35}
36
37#define T(path, an, ae, k, c, n, e) \
38 TEST_ASSERT_VAL("failed", !test(path, an, ae, k, c, n, e))
39
40int test__kmod_path__parse(void)
41{
42 /* path alloc_name alloc_ext kmod comp name ext */
43 T("/xxxx/xxxx/x-x.ko", true , true , true, false, "[x_x]", NULL);
44 T("/xxxx/xxxx/x-x.ko", false , true , true, false, NULL , NULL);
45 T("/xxxx/xxxx/x-x.ko", true , false , true, false, "[x_x]", NULL);
46 T("/xxxx/xxxx/x-x.ko", false , false , true, false, NULL , NULL);
47
48 /* path alloc_name alloc_ext kmod comp name ext */
49 T("/xxxx/xxxx/x.ko.gz", true , true , true, true, "[x]", "gz");
50 T("/xxxx/xxxx/x.ko.gz", false , true , true, true, NULL , "gz");
51 T("/xxxx/xxxx/x.ko.gz", true , false , true, true, "[x]", NULL);
52 T("/xxxx/xxxx/x.ko.gz", false , false , true, true, NULL , NULL);
53
54 /* path alloc_name alloc_ext kmod comp name ext */
55 T("/xxxx/xxxx/x.gz", true , true , false, true, "x.gz" ,"gz");
56 T("/xxxx/xxxx/x.gz", false , true , false, true, NULL ,"gz");
57 T("/xxxx/xxxx/x.gz", true , false , false, true, "x.gz" , NULL);
58 T("/xxxx/xxxx/x.gz", false , false , false, true, NULL , NULL);
59
60 /* path alloc_name alloc_ext kmod comp name ext */
61 T("x.gz", true , true , false, true, "x.gz", "gz");
62 T("x.gz", false , true , false, true, NULL , "gz");
63 T("x.gz", true , false , false, true, "x.gz", NULL);
64 T("x.gz", false , false , false, true, NULL , NULL);
65
66 /* path alloc_name alloc_ext kmod comp name ext */
67 T("x.ko.gz", true , true , true, true, "[x]", "gz");
68 T("x.ko.gz", false , true , true, true, NULL , "gz");
69 T("x.ko.gz", true , false , true, true, "[x]", NULL);
70 T("x.ko.gz", false , false , true, true, NULL , NULL);
71
72 return 0;
73}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 00e776a87a9c..52758a33f64c 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -51,6 +51,7 @@ int test__hists_cumulate(void);
51int test__switch_tracking(void); 51int test__switch_tracking(void);
52int test__fdarray__filter(void); 52int test__fdarray__filter(void);
53int test__fdarray__add(void); 53int test__fdarray__add(void);
54int test__kmod_path__parse(void);
54 55
55#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) 56#if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
56#ifdef HAVE_DWARF_UNWIND_SUPPORT 57#ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index be368414036c..3e6863feb066 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -212,6 +212,72 @@ bool dso__needs_decompress(struct dso *dso)
212} 212}
213 213
214/* 214/*
215 * Parses kernel module specified in @path and updates
216 * @m argument like:
217 *
218 * @comp - true if @path contains supported compression suffix,
219 * false otherwise
220 * @kmod - true if @path contains '.ko' suffix in right position,
221 * false otherwise
222 * @name - if (@alloc_name && @kmod) is true, it contains strdup-ed base name
223 * of the kernel module without suffixes, otherwise strudup-ed
224 * base name of @path
225 * @ext - if (@alloc_ext && @comp) is true, it contains strdup-ed string
226 * the compression suffix
227 *
228 * Returns 0 if there's no strdup error, -ENOMEM otherwise.
229 */
230int __kmod_path__parse(struct kmod_path *m, const char *path,
231 bool alloc_name, bool alloc_ext)
232{
233 const char *name = strrchr(path, '/');
234 const char *ext = strrchr(path, '.');
235
236 memset(m, 0x0, sizeof(*m));
237 name = name ? name + 1 : path;
238
239 /* No extension, just return name. */
240 if (ext == NULL) {
241 if (alloc_name) {
242 m->name = strdup(name);
243 return m->name ? 0 : -ENOMEM;
244 }
245 return 0;
246 }
247
248 if (is_supported_compression(ext + 1)) {
249 m->comp = true;
250 ext -= 3;
251 }
252
253 /* Check .ko extension only if there's enough name left. */
254 if (ext > name)
255 m->kmod = !strncmp(ext, ".ko", 3);
256
257 if (alloc_name) {
258 if (m->kmod) {
259 if (asprintf(&m->name, "[%.*s]", (int) (ext - name), name) == -1)
260 return -ENOMEM;
261 } else {
262 if (asprintf(&m->name, "%s", name) == -1)
263 return -ENOMEM;
264 }
265
266 strxfrchar(m->name, '-', '_');
267 }
268
269 if (alloc_ext && m->comp) {
270 m->ext = strdup(ext + 4);
271 if (!m->ext) {
272 free((void *) m->name);
273 return -ENOMEM;
274 }
275 }
276
277 return 0;
278}
279
280/*
215 * Global list of open DSOs and the counter. 281 * Global list of open DSOs and the counter.
216 */ 282 */
217static LIST_HEAD(dso__data_open); 283static LIST_HEAD(dso__data_open);
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 408c65f1a757..384cd2918e8f 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -195,6 +195,20 @@ bool is_kernel_module(const char *pathname, bool *compressed);
195bool decompress_to_file(const char *ext, const char *filename, int output_fd); 195bool decompress_to_file(const char *ext, const char *filename, int output_fd);
196bool dso__needs_decompress(struct dso *dso); 196bool dso__needs_decompress(struct dso *dso);
197 197
198struct kmod_path {
199 char *name;
200 char *ext;
201 bool comp;
202 bool kmod;
203};
204
205int __kmod_path__parse(struct kmod_path *m, const char *path,
206 bool alloc_name, bool alloc_ext);
207
208#define kmod_path__parse(__m, __p) __kmod_path__parse(__m, __p, false, false)
209#define kmod_path__parse_name(__m, __p) __kmod_path__parse(__m, __p, true , false)
210#define kmod_path__parse_ext(__m, __p) __kmod_path__parse(__m, __p, false, true)
211
198/* 212/*
199 * The dso__data_* external interface provides following functions: 213 * The dso__data_* external interface provides following functions:
200 * dso__data_fd 214 * dso__data_fd