summaryrefslogtreecommitdiff
path: root/tools/perf
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Makefile4
-rw-r--r--tools/perf/tests/code-reading.c4
-rw-r--r--tools/perf/tests/kmod-path.c136
-rw-r--r--tools/perf/util/annotate.c4
-rw-r--r--tools/perf/util/compress.h2
-rw-r--r--tools/perf/util/dso.c111
-rw-r--r--tools/perf/util/dso.h13
-rw-r--r--tools/perf/util/evlist.c2
-rw-r--r--tools/perf/util/llvm-utils.c31
-rw-r--r--tools/perf/util/llvm-utils.h9
-rw-r--r--tools/perf/util/lzma.c20
-rw-r--r--tools/perf/util/machine.c4
-rw-r--r--tools/perf/util/mmap.c3
-rw-r--r--tools/perf/util/mmap.h3
-rw-r--r--tools/perf/util/parse-events.c20
-rw-r--r--tools/perf/util/python.c20
-rw-r--r--tools/perf/util/zlib.c18
17 files changed, 246 insertions, 158 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 225454416ed5..7902a5681fc8 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -84,10 +84,10 @@ endif # has_clean
endif # MAKECMDGOALS
#
-# The clean target is not really parallel, don't print the jobs info:
+# Explicitly disable parallelism for the clean target.
#
clean:
- $(make)
+ $(make) -j1
#
# The build-test target is not really parallel, don't print the jobs info,
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 4892bd2dc33e..6b049f3f5cf4 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -232,6 +232,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
u64 objdump_addr;
const char *objdump_name;
char decomp_name[KMOD_DECOMP_LEN];
+ bool decomp = false;
int ret;
pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr);
@@ -305,6 +306,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
return -1;
}
+ decomp = true;
objdump_name = decomp_name;
}
@@ -312,7 +314,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
objdump_addr = map__rip_2objdump(al.map, al.addr);
ret = read_via_objdump(objdump_name, objdump_addr, buf2, len);
- if (dso__needs_decompress(al.map->dso))
+ if (decomp)
unlink(objdump_name);
if (ret > 0) {
diff --git a/tools/perf/tests/kmod-path.c b/tools/perf/tests/kmod-path.c
index 148dd31cc201..0579a70bbbff 100644
--- a/tools/perf/tests/kmod-path.c
+++ b/tools/perf/tests/kmod-path.c
@@ -5,34 +5,28 @@
#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)
+static int test(const char *path, bool alloc_name, bool kmod,
+ int comp, const char *name)
{
struct kmod_path m;
memset(&m, 0x0, sizeof(m));
TEST_ASSERT_VAL("kmod_path__parse",
- !__kmod_path__parse(&m, path, alloc_name, alloc_ext));
+ !__kmod_path__parse(&m, path, alloc_name));
- 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);
+ pr_debug("%s - alloc name %d, kmod %d, comp %d, name '%s'\n",
+ path, alloc_name, m.kmod, m.comp, m.name);
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;
}
@@ -45,118 +39,118 @@ static int test_is_kernel_module(const char *path, int cpumode, bool expect)
return 0;
}
-#define T(path, an, ae, k, c, n, e) \
- TEST_ASSERT_VAL("failed", !test(path, an, ae, k, c, n, e))
+#define T(path, an, k, c, n) \
+ TEST_ASSERT_VAL("failed", !test(path, an, k, c, n))
#define M(path, c, e) \
TEST_ASSERT_VAL("failed", !test_is_kernel_module(path, c, e))
int test__kmod_path__parse(struct test *t __maybe_unused, int subtest __maybe_unused)
{
- /* 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 kmod comp name */
+ T("/xxxx/xxxx/x-x.ko", true , true, 0 , "[x_x]");
+ T("/xxxx/xxxx/x-x.ko", false , true, 0 , NULL );
+ T("/xxxx/xxxx/x-x.ko", true , true, 0 , "[x_x]");
+ T("/xxxx/xxxx/x-x.ko", false , true, 0 , NULL );
M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_KERNEL, true);
M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_USER, false);
#ifdef HAVE_ZLIB_SUPPORT
- /* 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 kmod comp name */
+ T("/xxxx/xxxx/x.ko.gz", true , true, 1 , "[x]");
+ T("/xxxx/xxxx/x.ko.gz", false , true, 1 , NULL );
+ T("/xxxx/xxxx/x.ko.gz", true , true, 1 , "[x]");
+ T("/xxxx/xxxx/x.ko.gz", false , true, 1 , NULL );
M("/xxxx/xxxx/x.ko.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
M("/xxxx/xxxx/x.ko.gz", PERF_RECORD_MISC_KERNEL, true);
M("/xxxx/xxxx/x.ko.gz", PERF_RECORD_MISC_USER, false);
- /* 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 kmod comp name */
+ T("/xxxx/xxxx/x.gz", true , false, 1 , "x.gz");
+ T("/xxxx/xxxx/x.gz", false , false, 1 , NULL );
+ T("/xxxx/xxxx/x.gz", true , false, 1 , "x.gz");
+ T("/xxxx/xxxx/x.gz", false , false, 1 , NULL );
M("/xxxx/xxxx/x.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
M("/xxxx/xxxx/x.gz", PERF_RECORD_MISC_KERNEL, false);
M("/xxxx/xxxx/x.gz", PERF_RECORD_MISC_USER, false);
- /* 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 kmod comp name */
+ T("x.gz", true , false, 1 , "x.gz");
+ T("x.gz", false , false, 1 , NULL );
+ T("x.gz", true , false, 1 , "x.gz");
+ T("x.gz", false , false, 1 , NULL );
M("x.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
M("x.gz", PERF_RECORD_MISC_KERNEL, false);
M("x.gz", PERF_RECORD_MISC_USER, false);
- /* 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);
+ /* path alloc_name kmod comp name */
+ T("x.ko.gz", true , true, 1 , "[x]");
+ T("x.ko.gz", false , true, 1 , NULL );
+ T("x.ko.gz", true , true, 1 , "[x]");
+ T("x.ko.gz", false , true, 1 , NULL );
M("x.ko.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
M("x.ko.gz", PERF_RECORD_MISC_KERNEL, true);
M("x.ko.gz", PERF_RECORD_MISC_USER, false);
#endif
- /* path alloc_name alloc_ext kmod comp name ext */
- T("[test_module]", true , true , true, false, "[test_module]", NULL);
- T("[test_module]", false , true , true, false, NULL , NULL);
- T("[test_module]", true , false , true, false, "[test_module]", NULL);
- T("[test_module]", false , false , true, false, NULL , NULL);
+ /* path alloc_name kmod comp name */
+ T("[test_module]", true , true, false, "[test_module]");
+ T("[test_module]", false , true, false, NULL );
+ T("[test_module]", true , true, false, "[test_module]");
+ T("[test_module]", false , true, false, NULL );
M("[test_module]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
M("[test_module]", PERF_RECORD_MISC_KERNEL, true);
M("[test_module]", PERF_RECORD_MISC_USER, false);
- /* path alloc_name alloc_ext kmod comp name ext */
- T("[test.module]", true , true , true, false, "[test.module]", NULL);
- T("[test.module]", false , true , true, false, NULL , NULL);
- T("[test.module]", true , false , true, false, "[test.module]", NULL);
- T("[test.module]", false , false , true, false, NULL , NULL);
+ /* path alloc_name kmod comp name */
+ T("[test.module]", true , true, false, "[test.module]");
+ T("[test.module]", false , true, false, NULL );
+ T("[test.module]", true , true, false, "[test.module]");
+ T("[test.module]", false , true, false, NULL );
M("[test.module]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
M("[test.module]", PERF_RECORD_MISC_KERNEL, true);
M("[test.module]", PERF_RECORD_MISC_USER, false);
- /* path alloc_name alloc_ext kmod comp name ext */
- T("[vdso]", true , true , false, false, "[vdso]", NULL);
- T("[vdso]", false , true , false, false, NULL , NULL);
- T("[vdso]", true , false , false, false, "[vdso]", NULL);
- T("[vdso]", false , false , false, false, NULL , NULL);
+ /* path alloc_name kmod comp name */
+ T("[vdso]", true , false, false, "[vdso]");
+ T("[vdso]", false , false, false, NULL );
+ T("[vdso]", true , false, false, "[vdso]");
+ T("[vdso]", false , false, false, NULL );
M("[vdso]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
M("[vdso]", PERF_RECORD_MISC_KERNEL, false);
M("[vdso]", PERF_RECORD_MISC_USER, false);
- T("[vdso32]", true , true , false, false, "[vdso32]", NULL);
- T("[vdso32]", false , true , false, false, NULL , NULL);
- T("[vdso32]", true , false , false, false, "[vdso32]", NULL);
- T("[vdso32]", false , false , false, false, NULL , NULL);
+ T("[vdso32]", true , false, false, "[vdso32]");
+ T("[vdso32]", false , false, false, NULL );
+ T("[vdso32]", true , false, false, "[vdso32]");
+ T("[vdso32]", false , false, false, NULL );
M("[vdso32]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
M("[vdso32]", PERF_RECORD_MISC_KERNEL, false);
M("[vdso32]", PERF_RECORD_MISC_USER, false);
- T("[vdsox32]", true , true , false, false, "[vdsox32]", NULL);
- T("[vdsox32]", false , true , false, false, NULL , NULL);
- T("[vdsox32]", true , false , false, false, "[vdsox32]", NULL);
- T("[vdsox32]", false , false , false, false, NULL , NULL);
+ T("[vdsox32]", true , false, false, "[vdsox32]");
+ T("[vdsox32]", false , false, false, NULL );
+ T("[vdsox32]", true , false, false, "[vdsox32]");
+ T("[vdsox32]", false , false, false, NULL );
M("[vdsox32]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
M("[vdsox32]", PERF_RECORD_MISC_KERNEL, false);
M("[vdsox32]", PERF_RECORD_MISC_USER, false);
- /* path alloc_name alloc_ext kmod comp name ext */
- T("[vsyscall]", true , true , false, false, "[vsyscall]", NULL);
- T("[vsyscall]", false , true , false, false, NULL , NULL);
- T("[vsyscall]", true , false , false, false, "[vsyscall]", NULL);
- T("[vsyscall]", false , false , false, false, NULL , NULL);
+ /* path alloc_name kmod comp name */
+ T("[vsyscall]", true , false, false, "[vsyscall]");
+ T("[vsyscall]", false , false, false, NULL );
+ T("[vsyscall]", true , false, false, "[vsyscall]");
+ T("[vsyscall]", false , false, false, NULL );
M("[vsyscall]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
M("[vsyscall]", PERF_RECORD_MISC_KERNEL, false);
M("[vsyscall]", PERF_RECORD_MISC_USER, false);
- /* path alloc_name alloc_ext kmod comp name ext */
- T("[kernel.kallsyms]", true , true , false, false, "[kernel.kallsyms]", NULL);
- T("[kernel.kallsyms]", false , true , false, false, NULL , NULL);
- T("[kernel.kallsyms]", true , false , false, false, "[kernel.kallsyms]", NULL);
- T("[kernel.kallsyms]", false , false , false, false, NULL , NULL);
+ /* path alloc_name kmod comp name */
+ T("[kernel.kallsyms]", true , false, false, "[kernel.kallsyms]");
+ T("[kernel.kallsyms]", false , false, false, NULL );
+ T("[kernel.kallsyms]", true , false, false, "[kernel.kallsyms]");
+ T("[kernel.kallsyms]", false , false, false, NULL );
M("[kernel.kallsyms]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
M("[kernel.kallsyms]", PERF_RECORD_MISC_KERNEL, false);
M("[kernel.kallsyms]", PERF_RECORD_MISC_USER, false);
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index e4268b948e0e..20061cf42288 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -1629,6 +1629,7 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
char symfs_filename[PATH_MAX];
struct kcore_extract kce;
bool delete_extract = false;
+ bool decomp = false;
int stdout_fd[2];
int lineno = 0;
int nline;
@@ -1662,6 +1663,7 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
tmp, sizeof(tmp)) < 0)
goto out;
+ decomp = true;
strcpy(symfs_filename, tmp);
}
@@ -1748,7 +1750,7 @@ out_free_command:
out_remove_tmp:
close(stdout_fd[0]);
- if (dso__needs_decompress(dso))
+ if (decomp)
unlink(symfs_filename);
if (delete_extract)
diff --git a/tools/perf/util/compress.h b/tools/perf/util/compress.h
index ecca688a25fb..892e92e7e7fc 100644
--- a/tools/perf/util/compress.h
+++ b/tools/perf/util/compress.h
@@ -4,10 +4,12 @@
#ifdef HAVE_ZLIB_SUPPORT
int gzip_decompress_to_file(const char *input, int output_fd);
+bool gzip_is_compressed(const char *input);
#endif
#ifdef HAVE_LZMA_SUPPORT
int lzma_decompress_to_file(const char *input, int output_fd);
+bool lzma_is_compressed(const char *input);
#endif
#endif /* PERF_COMPRESS_H */
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 51cf82cf1882..bbed90e5d9bb 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -189,28 +189,34 @@ int dso__read_binary_type_filename(const struct dso *dso,
return ret;
}
+enum {
+ COMP_ID__NONE = 0,
+};
+
static const struct {
const char *fmt;
int (*decompress)(const char *input, int output);
+ bool (*is_compressed)(const char *input);
} compressions[] = {
+ [COMP_ID__NONE] = { .fmt = NULL, },
#ifdef HAVE_ZLIB_SUPPORT
- { "gz", gzip_decompress_to_file },
+ { "gz", gzip_decompress_to_file, gzip_is_compressed },
#endif
#ifdef HAVE_LZMA_SUPPORT
- { "xz", lzma_decompress_to_file },
+ { "xz", lzma_decompress_to_file, lzma_is_compressed },
#endif
- { NULL, NULL },
+ { NULL, NULL, NULL },
};
-bool is_supported_compression(const char *ext)
+static int is_supported_compression(const char *ext)
{
unsigned i;
- for (i = 0; compressions[i].fmt; i++) {
+ for (i = 1; compressions[i].fmt; i++) {
if (!strcmp(ext, compressions[i].fmt))
- return true;
+ return i;
}
- return false;
+ return COMP_ID__NONE;
}
bool is_kernel_module(const char *pathname, int cpumode)
@@ -239,80 +245,73 @@ bool is_kernel_module(const char *pathname, int cpumode)
return m.kmod;
}
-bool decompress_to_file(const char *ext, const char *filename, int output_fd)
-{
- unsigned i;
-
- for (i = 0; compressions[i].fmt; i++) {
- if (!strcmp(ext, compressions[i].fmt))
- return !compressions[i].decompress(filename,
- output_fd);
- }
- return false;
-}
-
bool dso__needs_decompress(struct dso *dso)
{
return dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP ||
dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP;
}
-static int decompress_kmodule(struct dso *dso, const char *name, char *tmpbuf)
+static int decompress_kmodule(struct dso *dso, const char *name,
+ char *pathname, size_t len)
{
+ char tmpbuf[] = KMOD_DECOMP_NAME;
int fd = -1;
- struct kmod_path m;
if (!dso__needs_decompress(dso))
return -1;
- if (kmod_path__parse_ext(&m, dso->long_name))
+ if (dso->comp == COMP_ID__NONE)
return -1;
- if (!m.comp)
- goto out;
+ /*
+ * We have proper compression id for DSO and yet the file
+ * behind the 'name' can still be plain uncompressed object.
+ *
+ * The reason is behind the logic we open the DSO object files,
+ * when we try all possible 'debug' objects until we find the
+ * data. So even if the DSO is represented by 'krava.xz' module,
+ * we can end up here opening ~/.debug/....23432432/debug' file
+ * which is not compressed.
+ *
+ * To keep this transparent, we detect this and return the file
+ * descriptor to the uncompressed file.
+ */
+ if (!compressions[dso->comp].is_compressed(name))
+ return open(name, O_RDONLY);
fd = mkstemp(tmpbuf);
if (fd < 0) {
dso->load_errno = errno;
- goto out;
+ return -1;
}
- if (!decompress_to_file(m.ext, name, fd)) {
+ if (compressions[dso->comp].decompress(name, fd)) {
dso->load_errno = DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE;
close(fd);
fd = -1;
}
-out:
- free(m.ext);
+ if (!pathname || (fd < 0))
+ unlink(tmpbuf);
+
+ if (pathname && (fd >= 0))
+ strncpy(pathname, tmpbuf, len);
+
return fd;
}
int dso__decompress_kmodule_fd(struct dso *dso, const char *name)
{
- char tmpbuf[] = KMOD_DECOMP_NAME;
- int fd;
-
- fd = decompress_kmodule(dso, name, tmpbuf);
- unlink(tmpbuf);
- return fd;
+ return decompress_kmodule(dso, name, NULL, 0);
}
int dso__decompress_kmodule_path(struct dso *dso, const char *name,
char *pathname, size_t len)
{
- char tmpbuf[] = KMOD_DECOMP_NAME;
- int fd;
+ int fd = decompress_kmodule(dso, name, pathname, len);
- fd = decompress_kmodule(dso, name, tmpbuf);
- if (fd < 0) {
- unlink(tmpbuf);
- return -1;
- }
-
- strncpy(pathname, tmpbuf, len);
close(fd);
- return 0;
+ return fd >= 0 ? 0 : -1;
}
/*
@@ -332,7 +331,7 @@ int dso__decompress_kmodule_path(struct dso *dso, const char *name,
* 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)
+ bool alloc_name)
{
const char *name = strrchr(path, '/');
const char *ext = strrchr(path, '.');
@@ -372,10 +371,9 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
return 0;
}
- if (is_supported_compression(ext + 1)) {
- m->comp = true;
+ m->comp = is_supported_compression(ext + 1);
+ if (m->comp > COMP_ID__NONE)
ext -= 3;
- }
/* Check .ko extension only if there's enough name left. */
if (ext > name)
@@ -393,14 +391,6 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
strxfrchar(m->name, '-', '_');
}
- if (alloc_ext && m->comp) {
- m->ext = strdup(ext + 4);
- if (!m->ext) {
- free((void *) m->name);
- return -ENOMEM;
- }
- }
-
return 0;
}
@@ -413,8 +403,10 @@ void dso__set_module_info(struct dso *dso, struct kmod_path *m,
dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
/* _KMODULE_COMP should be next to _KMODULE */
- if (m->kmod && m->comp)
+ if (m->kmod && m->comp) {
dso->symtab_type++;
+ dso->comp = m->comp;
+ }
dso__set_short_name(dso, strdup(m->name), true);
}
@@ -468,6 +460,7 @@ static int __open_dso(struct dso *dso, struct machine *machine)
int fd = -EINVAL;
char *root_dir = (char *)"";
char *name = malloc(PATH_MAX);
+ bool decomp = false;
if (!name)
return -ENOMEM;
@@ -491,12 +484,13 @@ static int __open_dso(struct dso *dso, struct machine *machine)
goto out;
}
+ decomp = true;
strcpy(name, newpath);
}
fd = do_open(name);
- if (dso__needs_decompress(dso))
+ if (decomp)
unlink(name);
out:
@@ -1218,6 +1212,7 @@ struct dso *dso__new(const char *name)
dso->a2l_fails = 1;
dso->kernel = DSO_TYPE_USER;
dso->needs_swap = DSO_SWAP__UNSET;
+ dso->comp = COMP_ID__NONE;
RB_CLEAR_NODE(&dso->rb_node);
dso->root = NULL;
INIT_LIST_HEAD(&dso->node);
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index ef69de2e69ea..c5380500bed4 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -175,6 +175,7 @@ struct dso {
u16 short_name_len;
void *dwfl; /* DWARF debug info */
struct auxtrace_cache *auxtrace_cache;
+ int comp;
/* dso data file */
struct {
@@ -250,9 +251,7 @@ int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir);
char dso__symtab_origin(const struct dso *dso);
int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type,
char *root_dir, char *filename, size_t size);
-bool is_supported_compression(const char *ext);
bool is_kernel_module(const char *pathname, int cpumode);
-bool decompress_to_file(const char *ext, const char *filename, int output_fd);
bool dso__needs_decompress(struct dso *dso);
int dso__decompress_kmodule_fd(struct dso *dso, const char *name);
int dso__decompress_kmodule_path(struct dso *dso, const char *name,
@@ -263,17 +262,15 @@ int dso__decompress_kmodule_path(struct dso *dso, const char *name,
struct kmod_path {
char *name;
- char *ext;
- bool comp;
+ int comp;
bool kmod;
};
int __kmod_path__parse(struct kmod_path *m, const char *path,
- bool alloc_name, bool alloc_ext);
+ bool alloc_name);
-#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)
+#define kmod_path__parse(__m, __p) __kmod_path__parse(__m, __p, false)
+#define kmod_path__parse_name(__m, __p) __kmod_path__parse(__m, __p, true)
void dso__set_module_info(struct dso *dso, struct kmod_path *m,
struct machine *machine);
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index e7a4b31a84fb..be440df29615 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -803,7 +803,7 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
if (*output == -1) {
*output = fd;
- if (perf_mmap__mmap(&maps[idx], mp, *output) < 0)
+ if (perf_mmap__mmap(&maps[idx], mp, *output, evlist_cpu) < 0)
return -1;
} else {
if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index 5e94857dfca2..19262f98cd4e 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -22,12 +22,14 @@
"$CLANG_OPTIONS $KERNEL_INC_OPTIONS $PERF_BPF_INC_OPTIONS " \
"-Wno-unused-value -Wno-pointer-sign " \
"-working-directory $WORKING_DIR " \
- "-c \"$CLANG_SOURCE\" -target bpf -O2 -o -"
+ "-c \"$CLANG_SOURCE\" -target bpf $CLANG_EMIT_LLVM -O2 -o - $LLVM_OPTIONS_PIPE"
struct llvm_param llvm_param = {
.clang_path = "clang",
+ .llc_path = "llc",
.clang_bpf_cmd_template = CLANG_BPF_CMD_DEFAULT_TEMPLATE,
.clang_opt = NULL,
+ .opts = NULL,
.kbuild_dir = NULL,
.kbuild_opts = NULL,
.user_set_param = false,
@@ -51,6 +53,8 @@ int perf_llvm_config(const char *var, const char *value)
llvm_param.kbuild_opts = strdup(value);
else if (!strcmp(var, "dump-obj"))
llvm_param.dump_obj = !!perf_config_bool(var, value);
+ else if (!strcmp(var, "opts"))
+ llvm_param.opts = strdup(value);
else {
pr_debug("Invalid LLVM config option: %s\n", value);
return -1;
@@ -430,11 +434,13 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
unsigned int kernel_version;
char linux_version_code_str[64];
const char *clang_opt = llvm_param.clang_opt;
- char clang_path[PATH_MAX], abspath[PATH_MAX], nr_cpus_avail_str[64];
+ char clang_path[PATH_MAX], llc_path[PATH_MAX], abspath[PATH_MAX], nr_cpus_avail_str[64];
char serr[STRERR_BUFSIZE];
char *kbuild_dir = NULL, *kbuild_include_opts = NULL,
*perf_bpf_include_opts = NULL;
const char *template = llvm_param.clang_bpf_cmd_template;
+ char *pipe_template = NULL;
+ const char *opts = llvm_param.opts;
char *command_echo = NULL, *command_out;
char *perf_include_dir = system_path(PERF_INCLUDE_DIR);
@@ -484,6 +490,26 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
force_set_env("PERF_BPF_INC_OPTIONS", perf_bpf_include_opts);
force_set_env("WORKING_DIR", kbuild_dir ? : ".");
+ if (opts) {
+ err = search_program(llvm_param.llc_path, "llc", llc_path);
+ if (err) {
+ pr_err("ERROR:\tunable to find llc.\n"
+ "Hint:\tTry to install latest clang/llvm to support BPF. Check your $PATH\n"
+ " \tand 'llc-path' option in [llvm] section of ~/.perfconfig.\n");
+ version_notice();
+ goto errout;
+ }
+
+ if (asprintf(&pipe_template, "%s -emit-llvm | %s -march=bpf %s -filetype=obj -o -",
+ template, llc_path, opts) < 0) {
+ pr_err("ERROR:\tnot enough memory to setup command line\n");
+ goto errout;
+ }
+
+ template = pipe_template;
+
+ }
+
/*
* Since we may reset clang's working dir, path of source file
* should be transferred into absolute path, except we want
@@ -535,6 +561,7 @@ errout:
free(obj_buf);
free(perf_bpf_include_opts);
free(perf_include_dir);
+ free(pipe_template);
if (p_obj_buf)
*p_obj_buf = NULL;
if (p_obj_buf_sz)
diff --git a/tools/perf/util/llvm-utils.h b/tools/perf/util/llvm-utils.h
index d3ad8deb5db4..bf3f3f4c4fe2 100644
--- a/tools/perf/util/llvm-utils.h
+++ b/tools/perf/util/llvm-utils.h
@@ -11,6 +11,8 @@
struct llvm_param {
/* Path of clang executable */
const char *clang_path;
+ /* Path of llc executable */
+ const char *llc_path;
/*
* Template of clang bpf compiling. 5 env variables
* can be used:
@@ -23,6 +25,13 @@ struct llvm_param {
const char *clang_bpf_cmd_template;
/* Will be filled in $CLANG_OPTIONS */
const char *clang_opt;
+ /*
+ * If present it'll add -emit-llvm to $CLANG_OPTIONS to pipe
+ * the clang output to llc, useful for new llvm options not
+ * yet selectable via 'clang -mllvm option', such as -mattr=dwarfris
+ * in clang 6.0/llvm 7
+ */
+ const char *opts;
/* Where to find kbuild system */
const char *kbuild_dir;
/*
diff --git a/tools/perf/util/lzma.c b/tools/perf/util/lzma.c
index 07498eaddc08..b1dd29a9d915 100644
--- a/tools/perf/util/lzma.c
+++ b/tools/perf/util/lzma.c
@@ -3,9 +3,13 @@
#include <lzma.h>
#include <stdio.h>
#include <linux/compiler.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
#include "compress.h"
#include "util.h"
#include "debug.h"
+#include <unistd.h>
#define BUFSIZE 8192
@@ -99,3 +103,19 @@ err_fclose:
fclose(infile);
return err;
}
+
+bool lzma_is_compressed(const char *input)
+{
+ int fd = open(input, O_RDONLY);
+ const uint8_t magic[6] = { 0xFD, '7', 'z', 'X', 'Z', 0x00 };
+ char buf[6] = { 0 };
+ ssize_t rc;
+
+ if (fd < 0)
+ return -1;
+
+ rc = read(fd, buf, sizeof(buf));
+ close(fd);
+ return rc == sizeof(buf) ?
+ memcmp(buf, magic, sizeof(buf)) == 0 : false;
+}
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index b300a3973448..c4acd2001db0 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1212,8 +1212,10 @@ static int map_groups__set_module_path(struct map_groups *mg, const char *path,
* Full name could reveal us kmod compression, so
* we need to update the symtab_type if needed.
*/
- if (m->comp && is_kmod_dso(map->dso))
+ if (m->comp && is_kmod_dso(map->dso)) {
map->dso->symtab_type++;
+ map->dso->comp = m->comp;
+ }
return 0;
}
diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c
index fc832676a798..215f69f41672 100644
--- a/tools/perf/util/mmap.c
+++ b/tools/perf/util/mmap.c
@@ -164,7 +164,7 @@ void perf_mmap__munmap(struct perf_mmap *map)
auxtrace_mmap__munmap(&map->auxtrace_mmap);
}
-int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd)
+int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd, int cpu)
{
/*
* The last one will be done at perf_mmap__consume(), so that we
@@ -191,6 +191,7 @@ int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd)
return -1;
}
map->fd = fd;
+ map->cpu = cpu;
if (auxtrace_mmap__mmap(&map->auxtrace_mmap,
&mp->auxtrace_mp, map->base, fd))
diff --git a/tools/perf/util/mmap.h b/tools/perf/util/mmap.h
index d82294db1295..05a6d47c7956 100644
--- a/tools/perf/util/mmap.h
+++ b/tools/perf/util/mmap.h
@@ -18,6 +18,7 @@ struct perf_mmap {
void *base;
int mask;
int fd;
+ int cpu;
refcount_t refcnt;
u64 prev;
u64 start;
@@ -60,7 +61,7 @@ struct mmap_params {
struct auxtrace_mmap_params auxtrace_mp;
};
-int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd);
+int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd, int cpu);
void perf_mmap__munmap(struct perf_mmap *map);
void perf_mmap__get(struct perf_mmap *map);
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 15eec49e71a1..f8cd3e7c9186 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1991,8 +1991,11 @@ static int set_filter(struct perf_evsel *evsel, const void *arg)
int nr_addr_filters = 0;
struct perf_pmu *pmu = NULL;
- if (evsel == NULL)
- goto err;
+ if (evsel == NULL) {
+ fprintf(stderr,
+ "--filter option should follow a -e tracepoint or HW tracer option\n");
+ return -1;
+ }
if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
if (perf_evsel__append_tp_filter(evsel, str) < 0) {
@@ -2014,8 +2017,11 @@ static int set_filter(struct perf_evsel *evsel, const void *arg)
perf_pmu__scan_file(pmu, "nr_addr_filters",
"%d", &nr_addr_filters);
- if (!nr_addr_filters)
- goto err;
+ if (!nr_addr_filters) {
+ fprintf(stderr,
+ "This CPU does not support address filtering\n");
+ return -1;
+ }
if (perf_evsel__append_addr_filter(evsel, str) < 0) {
fprintf(stderr,
@@ -2024,12 +2030,6 @@ static int set_filter(struct perf_evsel *evsel, const void *arg)
}
return 0;
-
-err:
- fprintf(stderr,
- "--filter option should follow a -e tracepoint or HW tracer option\n");
-
- return -1;
}
int parse_filter(const struct option *opt, const char *str,
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index f74fbb652a4f..ce501ba14b08 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -11,6 +11,7 @@
#include "cpumap.h"
#include "print_binary.h"
#include "thread_map.h"
+#include "mmap.h"
#if PY_MAJOR_VERSION < 3
#define _PyUnicode_FromString(arg) \
@@ -976,6 +977,20 @@ static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist,
return Py_BuildValue("i", evlist->nr_entries);
}
+static struct perf_mmap *get_md(struct perf_evlist *evlist, int cpu)
+{
+ int i;
+
+ for (i = 0; i < evlist->nr_mmaps; i++) {
+ struct perf_mmap *md = &evlist->mmap[i];
+
+ if (md->cpu == cpu)
+ return md;
+ }
+
+ return NULL;
+}
+
static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
PyObject *args, PyObject *kwargs)
{
@@ -990,7 +1005,10 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
&cpu, &sample_id_all))
return NULL;
- md = &evlist->mmap[cpu];
+ md = get_md(evlist, cpu);
+ if (!md)
+ return NULL;
+
if (perf_mmap__read_init(md) < 0)
goto end;
diff --git a/tools/perf/util/zlib.c b/tools/perf/util/zlib.c
index a725b958cf31..902ce6384f57 100644
--- a/tools/perf/util/zlib.c
+++ b/tools/perf/util/zlib.c
@@ -5,6 +5,8 @@
#include <sys/stat.h>
#include <sys/mman.h>
#include <zlib.h>
+#include <linux/compiler.h>
+#include <unistd.h>
#include "util/compress.h"
#include "util/util.h"
@@ -79,3 +81,19 @@ out_close:
return ret == Z_STREAM_END ? 0 : -1;
}
+
+bool gzip_is_compressed(const char *input)
+{
+ int fd = open(input, O_RDONLY);
+ const uint8_t magic[2] = { 0x1f, 0x8b };
+ char buf[2] = { 0 };
+ ssize_t rc;
+
+ if (fd < 0)
+ return -1;
+
+ rc = read(fd, buf, sizeof(buf));
+ close(fd);
+ return rc == sizeof(buf) ?
+ memcmp(buf, magic, sizeof(buf)) == 0 : false;
+}