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>
This commit is contained in:
parent
80a32e5b49
commit
3c8a67f50a
|
@ -30,6 +30,7 @@ perf-y += keep-tracking.o
|
||||||
perf-y += code-reading.o
|
perf-y += code-reading.o
|
||||||
perf-y += sample-parsing.o
|
perf-y += sample-parsing.o
|
||||||
perf-y += parse-no-sample-id-all.o
|
perf-y += parse-no-sample-id-all.o
|
||||||
|
perf-y += kmod-path.o
|
||||||
|
|
||||||
perf-$(CONFIG_X86) += perf-time-to-tsc.o
|
perf-$(CONFIG_X86) += perf-time-to-tsc.o
|
||||||
|
|
||||||
|
|
|
@ -166,6 +166,10 @@ static struct test {
|
||||||
.desc = "Add fd to a fdarray, making it autogrow",
|
.desc = "Add fd to a fdarray, making it autogrow",
|
||||||
.func = test__fdarray__add,
|
.func = test__fdarray__add,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.desc = "Test kmod_path__parse function",
|
||||||
|
.func = test__kmod_path__parse,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.func = NULL,
|
.func = NULL,
|
||||||
},
|
},
|
||||||
|
|
73
tools/perf/tests/kmod-path.c
Normal file
73
tools/perf/tests/kmod-path.c
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "tests.h"
|
||||||
|
#include "dso.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
static int test(const char *path, bool alloc_name, bool alloc_ext,
|
||||||
|
bool kmod, bool comp, const char *name, const char *ext)
|
||||||
|
{
|
||||||
|
struct kmod_path m;
|
||||||
|
|
||||||
|
memset(&m, 0x0, sizeof(m));
|
||||||
|
|
||||||
|
TEST_ASSERT_VAL("kmod_path__parse",
|
||||||
|
!__kmod_path__parse(&m, path, alloc_name, alloc_ext));
|
||||||
|
|
||||||
|
pr_debug("%s - alloc name %d, alloc ext %d, kmod %d, comp %d, name '%s', ext '%s'\n",
|
||||||
|
path, alloc_name, alloc_ext, m.kmod, m.comp, m.name, m.ext);
|
||||||
|
|
||||||
|
TEST_ASSERT_VAL("wrong kmod", m.kmod == kmod);
|
||||||
|
TEST_ASSERT_VAL("wrong comp", m.comp == comp);
|
||||||
|
|
||||||
|
if (ext)
|
||||||
|
TEST_ASSERT_VAL("wrong ext", m.ext && !strcmp(ext, m.ext));
|
||||||
|
else
|
||||||
|
TEST_ASSERT_VAL("wrong ext", !m.ext);
|
||||||
|
|
||||||
|
if (name)
|
||||||
|
TEST_ASSERT_VAL("wrong name", m.name && !strcmp(name, m.name));
|
||||||
|
else
|
||||||
|
TEST_ASSERT_VAL("wrong name", !m.name);
|
||||||
|
|
||||||
|
free(m.name);
|
||||||
|
free(m.ext);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define T(path, an, ae, k, c, n, e) \
|
||||||
|
TEST_ASSERT_VAL("failed", !test(path, an, ae, k, c, n, e))
|
||||||
|
|
||||||
|
int test__kmod_path__parse(void)
|
||||||
|
{
|
||||||
|
/* path alloc_name alloc_ext kmod comp name ext */
|
||||||
|
T("/xxxx/xxxx/x-x.ko", true , true , true, false, "[x_x]", NULL);
|
||||||
|
T("/xxxx/xxxx/x-x.ko", false , true , true, false, NULL , NULL);
|
||||||
|
T("/xxxx/xxxx/x-x.ko", true , false , true, false, "[x_x]", NULL);
|
||||||
|
T("/xxxx/xxxx/x-x.ko", false , false , true, false, NULL , NULL);
|
||||||
|
|
||||||
|
/* path alloc_name alloc_ext kmod comp name ext */
|
||||||
|
T("/xxxx/xxxx/x.ko.gz", true , true , true, true, "[x]", "gz");
|
||||||
|
T("/xxxx/xxxx/x.ko.gz", false , true , true, true, NULL , "gz");
|
||||||
|
T("/xxxx/xxxx/x.ko.gz", true , false , true, true, "[x]", NULL);
|
||||||
|
T("/xxxx/xxxx/x.ko.gz", false , false , true, true, NULL , NULL);
|
||||||
|
|
||||||
|
/* path alloc_name alloc_ext kmod comp name ext */
|
||||||
|
T("/xxxx/xxxx/x.gz", true , true , false, true, "x.gz" ,"gz");
|
||||||
|
T("/xxxx/xxxx/x.gz", false , true , false, true, NULL ,"gz");
|
||||||
|
T("/xxxx/xxxx/x.gz", true , false , false, true, "x.gz" , NULL);
|
||||||
|
T("/xxxx/xxxx/x.gz", false , false , false, true, NULL , NULL);
|
||||||
|
|
||||||
|
/* path alloc_name alloc_ext kmod comp name ext */
|
||||||
|
T("x.gz", true , true , false, true, "x.gz", "gz");
|
||||||
|
T("x.gz", false , true , false, true, NULL , "gz");
|
||||||
|
T("x.gz", true , false , false, true, "x.gz", NULL);
|
||||||
|
T("x.gz", false , false , false, true, NULL , NULL);
|
||||||
|
|
||||||
|
/* path alloc_name alloc_ext kmod comp name ext */
|
||||||
|
T("x.ko.gz", true , true , true, true, "[x]", "gz");
|
||||||
|
T("x.ko.gz", false , true , true, true, NULL , "gz");
|
||||||
|
T("x.ko.gz", true , false , true, true, "[x]", NULL);
|
||||||
|
T("x.ko.gz", false , false , true, true, NULL , NULL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -51,6 +51,7 @@ int test__hists_cumulate(void);
|
||||||
int test__switch_tracking(void);
|
int test__switch_tracking(void);
|
||||||
int test__fdarray__filter(void);
|
int test__fdarray__filter(void);
|
||||||
int test__fdarray__add(void);
|
int test__fdarray__add(void);
|
||||||
|
int test__kmod_path__parse(void);
|
||||||
|
|
||||||
#if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
|
#if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
|
||||||
#ifdef HAVE_DWARF_UNWIND_SUPPORT
|
#ifdef HAVE_DWARF_UNWIND_SUPPORT
|
||||||
|
|
|
@ -211,6 +211,72 @@ bool dso__needs_decompress(struct dso *dso)
|
||||||
dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP;
|
dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parses kernel module specified in @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
|
||||||
|
*
|
||||||
|
* Returns 0 if there's no strdup error, -ENOMEM otherwise.
|
||||||
|
*/
|
||||||
|
int __kmod_path__parse(struct kmod_path *m, const char *path,
|
||||||
|
bool alloc_name, bool alloc_ext)
|
||||||
|
{
|
||||||
|
const char *name = strrchr(path, '/');
|
||||||
|
const char *ext = strrchr(path, '.');
|
||||||
|
|
||||||
|
memset(m, 0x0, sizeof(*m));
|
||||||
|
name = name ? name + 1 : path;
|
||||||
|
|
||||||
|
/* No extension, just return name. */
|
||||||
|
if (ext == NULL) {
|
||||||
|
if (alloc_name) {
|
||||||
|
m->name = strdup(name);
|
||||||
|
return m->name ? 0 : -ENOMEM;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_supported_compression(ext + 1)) {
|
||||||
|
m->comp = true;
|
||||||
|
ext -= 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check .ko extension only if there's enough name left. */
|
||||||
|
if (ext > name)
|
||||||
|
m->kmod = !strncmp(ext, ".ko", 3);
|
||||||
|
|
||||||
|
if (alloc_name) {
|
||||||
|
if (m->kmod) {
|
||||||
|
if (asprintf(&m->name, "[%.*s]", (int) (ext - name), name) == -1)
|
||||||
|
return -ENOMEM;
|
||||||
|
} else {
|
||||||
|
if (asprintf(&m->name, "%s", name) == -1)
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
strxfrchar(m->name, '-', '_');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alloc_ext && m->comp) {
|
||||||
|
m->ext = strdup(ext + 4);
|
||||||
|
if (!m->ext) {
|
||||||
|
free((void *) m->name);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Global list of open DSOs and the counter.
|
* Global list of open DSOs and the counter.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -195,6 +195,20 @@ bool is_kernel_module(const char *pathname, bool *compressed);
|
||||||
bool decompress_to_file(const char *ext, const char *filename, int output_fd);
|
bool decompress_to_file(const char *ext, const char *filename, int output_fd);
|
||||||
bool dso__needs_decompress(struct dso *dso);
|
bool dso__needs_decompress(struct dso *dso);
|
||||||
|
|
||||||
|
struct kmod_path {
|
||||||
|
char *name;
|
||||||
|
char *ext;
|
||||||
|
bool comp;
|
||||||
|
bool kmod;
|
||||||
|
};
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The dso__data_* external interface provides following functions:
|
* The dso__data_* external interface provides following functions:
|
||||||
* dso__data_fd
|
* dso__data_fd
|
||||||
|
|
Loading…
Reference in a new issue