diff options
| -rw-r--r-- | tools/perf/tests/Build | 1 | ||||
| -rw-r--r-- | tools/perf/tests/builtin-test.c | 4 | ||||
| -rw-r--r-- | tools/perf/tests/kmod-path.c | 73 | ||||
| -rw-r--r-- | tools/perf/tests/tests.h | 1 | ||||
| -rw-r--r-- | tools/perf/util/dso.c | 66 | ||||
| -rw-r--r-- | tools/perf/util/dso.h | 14 |
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 | |||
| 30 | perf-y += code-reading.o | 30 | perf-y += code-reading.o |
| 31 | perf-y += sample-parsing.o | 31 | perf-y += sample-parsing.o |
| 32 | perf-y += parse-no-sample-id-all.o | 32 | perf-y += parse-no-sample-id-all.o |
| 33 | perf-y += kmod-path.o | ||
| 33 | 34 | ||
| 34 | perf-$(CONFIG_X86) += perf-time-to-tsc.o | 35 | perf-$(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 | |||
| 6 | static 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 | |||
| 40 | int 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); | |||
| 51 | int test__switch_tracking(void); | 51 | int test__switch_tracking(void); |
| 52 | int test__fdarray__filter(void); | 52 | int test__fdarray__filter(void); |
| 53 | int test__fdarray__add(void); | 53 | int test__fdarray__add(void); |
| 54 | int 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 | */ | ||
| 230 | int __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 | */ |
| 217 | static LIST_HEAD(dso__data_open); | 283 | static 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); | |||
| 195 | bool decompress_to_file(const char *ext, const char *filename, int output_fd); | 195 | bool decompress_to_file(const char *ext, const char *filename, int output_fd); |
| 196 | bool dso__needs_decompress(struct dso *dso); | 196 | bool dso__needs_decompress(struct dso *dso); |
| 197 | 197 | ||
| 198 | struct kmod_path { | ||
| 199 | char *name; | ||
| 200 | char *ext; | ||
| 201 | bool comp; | ||
| 202 | bool kmod; | ||
| 203 | }; | ||
| 204 | |||
| 205 | int __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 |
