aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2018-08-23 04:29:19 -0400
committerIngo Molnar <mingo@kernel.org>2018-08-23 04:29:19 -0400
commit66e5db4a1ccc64f278653bc69dc406d184dc750a (patch)
tree962c9c7debae59ced3401c38d6894d620f68693b
parent5804b11034a21e4287daaf017c5ad60ad7af8d67 (diff)
parent78303650e4cd873c6c4276c6fe3e768ff0b46d22 (diff)
Merge tag 'perf-core-for-mingo-4.19-20180820' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: LLVM/clang/eBPF: (Arnaldo Carvalho de Melo) - Allow passing options to llc in addition to to clang. Hardware tracing: (Jack Henschel) - Improve error message for PMU address filters, clarifying availability of that feature in hardware having hardware tracing such as Intel PT. Python interface: (Jiri Olsa) - Fix read_on_cpu() interface. ELF/DWARF libraries: (Jiri Olsa) - Fix handling of the combo compressed module file + decompressed associated debuginfo file. Build (Rasmus Villemoes) - Disable parallelism for 'make clean', avoiding multiple submakes deleting the same files and causing the build to fail on systems such as Yocto. Kernel ABI copies: (Arnaldo Carvalho de Melo) - Update tools's copy of x86's cpufeatures.h. - Update arch/x86/lib/memcpy_64.S copy used in 'perf bench mem memcpy'. Miscellaneous: (Steven Rostedt) - Change libtraceevent to SPDX License format. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/arch/x86/include/asm/cpufeatures.h3
-rw-r--r--tools/arch/x86/lib/memcpy_64.S2
-rw-r--r--tools/lib/traceevent/event-parse.c16
-rw-r--r--tools/lib/traceevent/event-plugin.c16
-rw-r--r--tools/lib/traceevent/event-utils.h16
-rw-r--r--tools/lib/traceevent/kbuffer-parse.c17
-rw-r--r--tools/lib/traceevent/parse-filter.c16
-rw-r--r--tools/lib/traceevent/parse-utils.c16
-rw-r--r--tools/lib/traceevent/trace-seq.c16
-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
26 files changed, 256 insertions, 266 deletions
diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h
index 5701f5cecd31..b5c60faf8429 100644
--- a/tools/arch/x86/include/asm/cpufeatures.h
+++ b/tools/arch/x86/include/asm/cpufeatures.h
@@ -219,6 +219,7 @@
219#define X86_FEATURE_IBPB ( 7*32+26) /* Indirect Branch Prediction Barrier */ 219#define X86_FEATURE_IBPB ( 7*32+26) /* Indirect Branch Prediction Barrier */
220#define X86_FEATURE_STIBP ( 7*32+27) /* Single Thread Indirect Branch Predictors */ 220#define X86_FEATURE_STIBP ( 7*32+27) /* Single Thread Indirect Branch Predictors */
221#define X86_FEATURE_ZEN ( 7*32+28) /* "" CPU is AMD family 0x17 (Zen) */ 221#define X86_FEATURE_ZEN ( 7*32+28) /* "" CPU is AMD family 0x17 (Zen) */
222#define X86_FEATURE_IBRS_ENHANCED ( 7*32+29) /* Enhanced IBRS */
222 223
223/* Virtualization flags: Linux defined, word 8 */ 224/* Virtualization flags: Linux defined, word 8 */
224#define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */ 225#define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */
@@ -229,7 +230,7 @@
229 230
230#define X86_FEATURE_VMMCALL ( 8*32+15) /* Prefer VMMCALL to VMCALL */ 231#define X86_FEATURE_VMMCALL ( 8*32+15) /* Prefer VMMCALL to VMCALL */
231#define X86_FEATURE_XENPV ( 8*32+16) /* "" Xen paravirtual guest */ 232#define X86_FEATURE_XENPV ( 8*32+16) /* "" Xen paravirtual guest */
232 233#define X86_FEATURE_EPT_AD ( 8*32+17) /* Intel Extended Page Table access-dirty bit */
233 234
234/* Intel-defined CPU features, CPUID level 0x00000007:0 (EBX), word 9 */ 235/* Intel-defined CPU features, CPUID level 0x00000007:0 (EBX), word 9 */
235#define X86_FEATURE_FSGSBASE ( 9*32+ 0) /* RDFSBASE, WRFSBASE, RDGSBASE, WRGSBASE instructions*/ 236#define X86_FEATURE_FSGSBASE ( 9*32+ 0) /* RDFSBASE, WRFSBASE, RDGSBASE, WRGSBASE instructions*/
diff --git a/tools/arch/x86/lib/memcpy_64.S b/tools/arch/x86/lib/memcpy_64.S
index 298ef1479240..3b24dc05251c 100644
--- a/tools/arch/x86/lib/memcpy_64.S
+++ b/tools/arch/x86/lib/memcpy_64.S
@@ -256,7 +256,7 @@ ENTRY(__memcpy_mcsafe)
256 256
257 /* Copy successful. Return zero */ 257 /* Copy successful. Return zero */
258.L_done_memcpy_trap: 258.L_done_memcpy_trap:
259 xorq %rax, %rax 259 xorl %eax, %eax
260 ret 260 ret
261ENDPROC(__memcpy_mcsafe) 261ENDPROC(__memcpy_mcsafe)
262EXPORT_SYMBOL_GPL(__memcpy_mcsafe) 262EXPORT_SYMBOL_GPL(__memcpy_mcsafe)
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 6313e32680ff..ce1e20227c64 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -1,21 +1,7 @@
1// SPDX-License-Identifier: LGPL-2.1
1/* 2/*
2 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> 3 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 * 4 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, see <http://www.gnu.org/licenses>
17 *
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 * 5 *
20 * The parts for function graph printing was taken and modified from the 6 * The parts for function graph printing was taken and modified from the
21 * Linux Kernel that were written by 7 * Linux Kernel that were written by
diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c
index 8e324ed46547..f17e25097e1e 100644
--- a/tools/lib/traceevent/event-plugin.c
+++ b/tools/lib/traceevent/event-plugin.c
@@ -1,21 +1,7 @@
1// SPDX-License-Identifier: LGPL-2.1
1/* 2/*
2 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> 3 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 * 4 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, see <http://www.gnu.org/licenses>
17 *
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 */ 5 */
20 6
21#include <ctype.h> 7#include <ctype.h>
diff --git a/tools/lib/traceevent/event-utils.h b/tools/lib/traceevent/event-utils.h
index d1dc2170e402..0560b96a31d1 100644
--- a/tools/lib/traceevent/event-utils.h
+++ b/tools/lib/traceevent/event-utils.h
@@ -1,21 +1,7 @@
1/* SPDX-License-Identifier: LGPL-2.1 */
1/* 2/*
2 * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> 3 * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 * 4 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, see <http://www.gnu.org/licenses>
17 *
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 */ 5 */
20#ifndef __UTIL_H 6#ifndef __UTIL_H
21#define __UTIL_H 7#define __UTIL_H
diff --git a/tools/lib/traceevent/kbuffer-parse.c b/tools/lib/traceevent/kbuffer-parse.c
index ca424b157e46..af2a1f3b7424 100644
--- a/tools/lib/traceevent/kbuffer-parse.c
+++ b/tools/lib/traceevent/kbuffer-parse.c
@@ -1,22 +1,7 @@
1// SPDX-License-Identifier: LGPL-2.1
1/* 2/*
2 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> 3 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 * 4 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 */ 5 */
21#include <stdio.h> 6#include <stdio.h>
22#include <stdlib.h> 7#include <stdlib.h>
diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c
index 682a50e8b5f7..e76154c02ee7 100644
--- a/tools/lib/traceevent/parse-filter.c
+++ b/tools/lib/traceevent/parse-filter.c
@@ -1,21 +1,7 @@
1// SPDX-License-Identifier: LGPL-2.1
1/* 2/*
2 * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> 3 * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 * 4 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, see <http://www.gnu.org/licenses>
17 *
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 */ 5 */
20#include <stdio.h> 6#include <stdio.h>
21#include <stdlib.h> 7#include <stdlib.h>
diff --git a/tools/lib/traceevent/parse-utils.c b/tools/lib/traceevent/parse-utils.c
index eda07fa31dca..77e4ec6402dd 100644
--- a/tools/lib/traceevent/parse-utils.c
+++ b/tools/lib/traceevent/parse-utils.c
@@ -1,21 +1,7 @@
1// SPDX-License-Identifier: LGPL-2.1
1/* 2/*
2 * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> 3 * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 * 4 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, see <http://www.gnu.org/licenses>
17 *
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 */ 5 */
20#include <stdio.h> 6#include <stdio.h>
21#include <stdlib.h> 7#include <stdlib.h>
diff --git a/tools/lib/traceevent/trace-seq.c b/tools/lib/traceevent/trace-seq.c
index 292dc9f1d233..e3bac4543d3b 100644
--- a/tools/lib/traceevent/trace-seq.c
+++ b/tools/lib/traceevent/trace-seq.c
@@ -1,21 +1,7 @@
1// SPDX-License-Identifier: LGPL-2.1
1/* 2/*
2 * Copyright (C) 2009 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> 3 * Copyright (C) 2009 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 * 4 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, see <http://www.gnu.org/licenses>
17 *
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 */ 5 */
20#include <stdio.h> 6#include <stdio.h>
21#include <stdlib.h> 7#include <stdlib.h>
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
84endif # MAKECMDGOALS 84endif # MAKECMDGOALS
85 85
86# 86#
87# The clean target is not really parallel, don't print the jobs info: 87# Explicitly disable parallelism for the clean target.
88# 88#
89clean: 89clean:
90 $(make) 90 $(make) -j1
91 91
92# 92#
93# The build-test target is not really parallel, don't print the jobs info, 93# 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,
232 u64 objdump_addr; 232 u64 objdump_addr;
233 const char *objdump_name; 233 const char *objdump_name;
234 char decomp_name[KMOD_DECOMP_LEN]; 234 char decomp_name[KMOD_DECOMP_LEN];
235 bool decomp = false;
235 int ret; 236 int ret;
236 237
237 pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr); 238 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,
305 return -1; 306 return -1;
306 } 307 }
307 308
309 decomp = true;
308 objdump_name = decomp_name; 310 objdump_name = decomp_name;
309 } 311 }
310 312
@@ -312,7 +314,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
312 objdump_addr = map__rip_2objdump(al.map, al.addr); 314 objdump_addr = map__rip_2objdump(al.map, al.addr);
313 ret = read_via_objdump(objdump_name, objdump_addr, buf2, len); 315 ret = read_via_objdump(objdump_name, objdump_addr, buf2, len);
314 316
315 if (dso__needs_decompress(al.map->dso)) 317 if (decomp)
316 unlink(objdump_name); 318 unlink(objdump_name);
317 319
318 if (ret > 0) { 320 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 @@
5#include "dso.h" 5#include "dso.h"
6#include "debug.h" 6#include "debug.h"
7 7
8static int test(const char *path, bool alloc_name, bool alloc_ext, 8static int test(const char *path, bool alloc_name, bool kmod,
9 bool kmod, bool comp, const char *name, const char *ext) 9 int comp, const char *name)
10{ 10{
11 struct kmod_path m; 11 struct kmod_path m;
12 12
13 memset(&m, 0x0, sizeof(m)); 13 memset(&m, 0x0, sizeof(m));
14 14
15 TEST_ASSERT_VAL("kmod_path__parse", 15 TEST_ASSERT_VAL("kmod_path__parse",
16 !__kmod_path__parse(&m, path, alloc_name, alloc_ext)); 16 !__kmod_path__parse(&m, path, alloc_name));
17 17
18 pr_debug("%s - alloc name %d, alloc ext %d, kmod %d, comp %d, name '%s', ext '%s'\n", 18 pr_debug("%s - alloc name %d, kmod %d, comp %d, name '%s'\n",
19 path, alloc_name, alloc_ext, m.kmod, m.comp, m.name, m.ext); 19 path, alloc_name, m.kmod, m.comp, m.name);
20 20
21 TEST_ASSERT_VAL("wrong kmod", m.kmod == kmod); 21 TEST_ASSERT_VAL("wrong kmod", m.kmod == kmod);
22 TEST_ASSERT_VAL("wrong comp", m.comp == comp); 22 TEST_ASSERT_VAL("wrong comp", m.comp == comp);
23 23
24 if (ext)
25 TEST_ASSERT_VAL("wrong ext", m.ext && !strcmp(ext, m.ext));
26 else
27 TEST_ASSERT_VAL("wrong ext", !m.ext);
28
29 if (name) 24 if (name)
30 TEST_ASSERT_VAL("wrong name", m.name && !strcmp(name, m.name)); 25 TEST_ASSERT_VAL("wrong name", m.name && !strcmp(name, m.name));
31 else 26 else
32 TEST_ASSERT_VAL("wrong name", !m.name); 27 TEST_ASSERT_VAL("wrong name", !m.name);
33 28
34 free(m.name); 29 free(m.name);
35 free(m.ext);
36 return 0; 30 return 0;
37} 31}
38 32
@@ -45,118 +39,118 @@ static int test_is_kernel_module(const char *path, int cpumode, bool expect)
45 return 0; 39 return 0;
46} 40}
47 41
48#define T(path, an, ae, k, c, n, e) \ 42#define T(path, an, k, c, n) \
49 TEST_ASSERT_VAL("failed", !test(path, an, ae, k, c, n, e)) 43 TEST_ASSERT_VAL("failed", !test(path, an, k, c, n))
50 44
51#define M(path, c, e) \ 45#define M(path, c, e) \
52 TEST_ASSERT_VAL("failed", !test_is_kernel_module(path, c, e)) 46 TEST_ASSERT_VAL("failed", !test_is_kernel_module(path, c, e))
53 47
54int test__kmod_path__parse(struct test *t __maybe_unused, int subtest __maybe_unused) 48int test__kmod_path__parse(struct test *t __maybe_unused, int subtest __maybe_unused)
55{ 49{
56 /* path alloc_name alloc_ext kmod comp name ext */ 50 /* path alloc_name kmod comp name */
57 T("/xxxx/xxxx/x-x.ko", true , true , true, false, "[x_x]", NULL); 51 T("/xxxx/xxxx/x-x.ko", true , true, 0 , "[x_x]");
58 T("/xxxx/xxxx/x-x.ko", false , true , true, false, NULL , NULL); 52 T("/xxxx/xxxx/x-x.ko", false , true, 0 , NULL );
59 T("/xxxx/xxxx/x-x.ko", true , false , true, false, "[x_x]", NULL); 53 T("/xxxx/xxxx/x-x.ko", true , true, 0 , "[x_x]");
60 T("/xxxx/xxxx/x-x.ko", false , false , true, false, NULL , NULL); 54 T("/xxxx/xxxx/x-x.ko", false , true, 0 , NULL );
61 M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true); 55 M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
62 M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_KERNEL, true); 56 M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_KERNEL, true);
63 M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_USER, false); 57 M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_USER, false);
64 58
65#ifdef HAVE_ZLIB_SUPPORT 59#ifdef HAVE_ZLIB_SUPPORT
66 /* path alloc_name alloc_ext kmod comp name ext */ 60 /* path alloc_name kmod comp name */
67 T("/xxxx/xxxx/x.ko.gz", true , true , true, true, "[x]", "gz"); 61 T("/xxxx/xxxx/x.ko.gz", true , true, 1 , "[x]");
68 T("/xxxx/xxxx/x.ko.gz", false , true , true, true, NULL , "gz"); 62 T("/xxxx/xxxx/x.ko.gz", false , true, 1 , NULL );
69 T("/xxxx/xxxx/x.ko.gz", true , false , true, true, "[x]", NULL); 63 T("/xxxx/xxxx/x.ko.gz", true , true, 1 , "[x]");
70 T("/xxxx/xxxx/x.ko.gz", false , false , true, true, NULL , NULL); 64 T("/xxxx/xxxx/x.ko.gz", false , true, 1 , NULL );
71 M("/xxxx/xxxx/x.ko.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true); 65 M("/xxxx/xxxx/x.ko.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
72 M("/xxxx/xxxx/x.ko.gz", PERF_RECORD_MISC_KERNEL, true); 66 M("/xxxx/xxxx/x.ko.gz", PERF_RECORD_MISC_KERNEL, true);
73 M("/xxxx/xxxx/x.ko.gz", PERF_RECORD_MISC_USER, false); 67 M("/xxxx/xxxx/x.ko.gz", PERF_RECORD_MISC_USER, false);
74 68
75 /* path alloc_name alloc_ext kmod comp name ext */ 69 /* path alloc_name kmod comp name */
76 T("/xxxx/xxxx/x.gz", true , true , false, true, "x.gz" ,"gz"); 70 T("/xxxx/xxxx/x.gz", true , false, 1 , "x.gz");
77 T("/xxxx/xxxx/x.gz", false , true , false, true, NULL ,"gz"); 71 T("/xxxx/xxxx/x.gz", false , false, 1 , NULL );
78 T("/xxxx/xxxx/x.gz", true , false , false, true, "x.gz" , NULL); 72 T("/xxxx/xxxx/x.gz", true , false, 1 , "x.gz");
79 T("/xxxx/xxxx/x.gz", false , false , false, true, NULL , NULL); 73 T("/xxxx/xxxx/x.gz", false , false, 1 , NULL );
80 M("/xxxx/xxxx/x.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false); 74 M("/xxxx/xxxx/x.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
81 M("/xxxx/xxxx/x.gz", PERF_RECORD_MISC_KERNEL, false); 75 M("/xxxx/xxxx/x.gz", PERF_RECORD_MISC_KERNEL, false);
82 M("/xxxx/xxxx/x.gz", PERF_RECORD_MISC_USER, false); 76 M("/xxxx/xxxx/x.gz", PERF_RECORD_MISC_USER, false);
83 77
84 /* path alloc_name alloc_ext kmod comp name ext */ 78 /* path alloc_name kmod comp name */
85 T("x.gz", true , true , false, true, "x.gz", "gz"); 79 T("x.gz", true , false, 1 , "x.gz");
86 T("x.gz", false , true , false, true, NULL , "gz"); 80 T("x.gz", false , false, 1 , NULL );
87 T("x.gz", true , false , false, true, "x.gz", NULL); 81 T("x.gz", true , false, 1 , "x.gz");
88 T("x.gz", false , false , false, true, NULL , NULL); 82 T("x.gz", false , false, 1 , NULL );
89 M("x.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false); 83 M("x.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
90 M("x.gz", PERF_RECORD_MISC_KERNEL, false); 84 M("x.gz", PERF_RECORD_MISC_KERNEL, false);
91 M("x.gz", PERF_RECORD_MISC_USER, false); 85 M("x.gz", PERF_RECORD_MISC_USER, false);
92 86
93 /* path alloc_name alloc_ext kmod comp name ext */ 87 /* path alloc_name kmod comp name */
94 T("x.ko.gz", true , true , true, true, "[x]", "gz"); 88 T("x.ko.gz", true , true, 1 , "[x]");
95 T("x.ko.gz", false , true , true, true, NULL , "gz"); 89 T("x.ko.gz", false , true, 1 , NULL );
96 T("x.ko.gz", true , false , true, true, "[x]", NULL); 90 T("x.ko.gz", true , true, 1 , "[x]");
97 T("x.ko.gz", false , false , true, true, NULL , NULL); 91 T("x.ko.gz", false , true, 1 , NULL );
98 M("x.ko.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true); 92 M("x.ko.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
99 M("x.ko.gz", PERF_RECORD_MISC_KERNEL, true); 93 M("x.ko.gz", PERF_RECORD_MISC_KERNEL, true);
100 M("x.ko.gz", PERF_RECORD_MISC_USER, false); 94 M("x.ko.gz", PERF_RECORD_MISC_USER, false);
101#endif 95#endif
102 96
103 /* path alloc_name alloc_ext kmod comp name ext */ 97 /* path alloc_name kmod comp name */
104 T("[test_module]", true , true , true, false, "[test_module]", NULL); 98 T("[test_module]", true , true, false, "[test_module]");
105 T("[test_module]", false , true , true, false, NULL , NULL); 99 T("[test_module]", false , true, false, NULL );
106 T("[test_module]", true , false , true, false, "[test_module]", NULL); 100 T("[test_module]", true , true, false, "[test_module]");
107 T("[test_module]", false , false , true, false, NULL , NULL); 101 T("[test_module]", false , true, false, NULL );
108 M("[test_module]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true); 102 M("[test_module]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
109 M("[test_module]", PERF_RECORD_MISC_KERNEL, true); 103 M("[test_module]", PERF_RECORD_MISC_KERNEL, true);
110 M("[test_module]", PERF_RECORD_MISC_USER, false); 104 M("[test_module]", PERF_RECORD_MISC_USER, false);
111 105
112 /* path alloc_name alloc_ext kmod comp name ext */ 106 /* path alloc_name kmod comp name */
113 T("[test.module]", true , true , true, false, "[test.module]", NULL); 107 T("[test.module]", true , true, false, "[test.module]");
114 T("[test.module]", false , true , true, false, NULL , NULL); 108 T("[test.module]", false , true, false, NULL );
115 T("[test.module]", true , false , true, false, "[test.module]", NULL); 109 T("[test.module]", true , true, false, "[test.module]");
116 T("[test.module]", false , false , true, false, NULL , NULL); 110 T("[test.module]", false , true, false, NULL );
117 M("[test.module]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true); 111 M("[test.module]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
118 M("[test.module]", PERF_RECORD_MISC_KERNEL, true); 112 M("[test.module]", PERF_RECORD_MISC_KERNEL, true);
119 M("[test.module]", PERF_RECORD_MISC_USER, false); 113 M("[test.module]", PERF_RECORD_MISC_USER, false);
120 114
121 /* path alloc_name alloc_ext kmod comp name ext */ 115 /* path alloc_name kmod comp name */
122 T("[vdso]", true , true , false, false, "[vdso]", NULL); 116 T("[vdso]", true , false, false, "[vdso]");
123 T("[vdso]", false , true , false, false, NULL , NULL); 117 T("[vdso]", false , false, false, NULL );
124 T("[vdso]", true , false , false, false, "[vdso]", NULL); 118 T("[vdso]", true , false, false, "[vdso]");
125 T("[vdso]", false , false , false, false, NULL , NULL); 119 T("[vdso]", false , false, false, NULL );
126 M("[vdso]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false); 120 M("[vdso]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
127 M("[vdso]", PERF_RECORD_MISC_KERNEL, false); 121 M("[vdso]", PERF_RECORD_MISC_KERNEL, false);
128 M("[vdso]", PERF_RECORD_MISC_USER, false); 122 M("[vdso]", PERF_RECORD_MISC_USER, false);
129 123
130 T("[vdso32]", true , true , false, false, "[vdso32]", NULL); 124 T("[vdso32]", true , false, false, "[vdso32]");
131 T("[vdso32]", false , true , false, false, NULL , NULL); 125 T("[vdso32]", false , false, false, NULL );
132 T("[vdso32]", true , false , false, false, "[vdso32]", NULL); 126 T("[vdso32]", true , false, false, "[vdso32]");
133 T("[vdso32]", false , false , false, false, NULL , NULL); 127 T("[vdso32]", false , false, false, NULL );
134 M("[vdso32]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false); 128 M("[vdso32]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
135 M("[vdso32]", PERF_RECORD_MISC_KERNEL, false); 129 M("[vdso32]", PERF_RECORD_MISC_KERNEL, false);
136 M("[vdso32]", PERF_RECORD_MISC_USER, false); 130 M("[vdso32]", PERF_RECORD_MISC_USER, false);
137 131
138 T("[vdsox32]", true , true , false, false, "[vdsox32]", NULL); 132 T("[vdsox32]", true , false, false, "[vdsox32]");
139 T("[vdsox32]", false , true , false, false, NULL , NULL); 133 T("[vdsox32]", false , false, false, NULL );
140 T("[vdsox32]", true , false , false, false, "[vdsox32]", NULL); 134 T("[vdsox32]", true , false, false, "[vdsox32]");
141 T("[vdsox32]", false , false , false, false, NULL , NULL); 135 T("[vdsox32]", false , false, false, NULL );
142 M("[vdsox32]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false); 136 M("[vdsox32]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
143 M("[vdsox32]", PERF_RECORD_MISC_KERNEL, false); 137 M("[vdsox32]", PERF_RECORD_MISC_KERNEL, false);
144 M("[vdsox32]", PERF_RECORD_MISC_USER, false); 138 M("[vdsox32]", PERF_RECORD_MISC_USER, false);
145 139
146 /* path alloc_name alloc_ext kmod comp name ext */ 140 /* path alloc_name kmod comp name */
147 T("[vsyscall]", true , true , false, false, "[vsyscall]", NULL); 141 T("[vsyscall]", true , false, false, "[vsyscall]");
148 T("[vsyscall]", false , true , false, false, NULL , NULL); 142 T("[vsyscall]", false , false, false, NULL );
149 T("[vsyscall]", true , false , false, false, "[vsyscall]", NULL); 143 T("[vsyscall]", true , false, false, "[vsyscall]");
150 T("[vsyscall]", false , false , false, false, NULL , NULL); 144 T("[vsyscall]", false , false, false, NULL );
151 M("[vsyscall]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false); 145 M("[vsyscall]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
152 M("[vsyscall]", PERF_RECORD_MISC_KERNEL, false); 146 M("[vsyscall]", PERF_RECORD_MISC_KERNEL, false);
153 M("[vsyscall]", PERF_RECORD_MISC_USER, false); 147 M("[vsyscall]", PERF_RECORD_MISC_USER, false);
154 148
155 /* path alloc_name alloc_ext kmod comp name ext */ 149 /* path alloc_name kmod comp name */
156 T("[kernel.kallsyms]", true , true , false, false, "[kernel.kallsyms]", NULL); 150 T("[kernel.kallsyms]", true , false, false, "[kernel.kallsyms]");
157 T("[kernel.kallsyms]", false , true , false, false, NULL , NULL); 151 T("[kernel.kallsyms]", false , false, false, NULL );
158 T("[kernel.kallsyms]", true , false , false, false, "[kernel.kallsyms]", NULL); 152 T("[kernel.kallsyms]", true , false, false, "[kernel.kallsyms]");
159 T("[kernel.kallsyms]", false , false , false, false, NULL , NULL); 153 T("[kernel.kallsyms]", false , false, false, NULL );
160 M("[kernel.kallsyms]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false); 154 M("[kernel.kallsyms]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
161 M("[kernel.kallsyms]", PERF_RECORD_MISC_KERNEL, false); 155 M("[kernel.kallsyms]", PERF_RECORD_MISC_KERNEL, false);
162 M("[kernel.kallsyms]", PERF_RECORD_MISC_USER, false); 156 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)
1629 char symfs_filename[PATH_MAX]; 1629 char symfs_filename[PATH_MAX];
1630 struct kcore_extract kce; 1630 struct kcore_extract kce;
1631 bool delete_extract = false; 1631 bool delete_extract = false;
1632 bool decomp = false;
1632 int stdout_fd[2]; 1633 int stdout_fd[2];
1633 int lineno = 0; 1634 int lineno = 0;
1634 int nline; 1635 int nline;
@@ -1662,6 +1663,7 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1662 tmp, sizeof(tmp)) < 0) 1663 tmp, sizeof(tmp)) < 0)
1663 goto out; 1664 goto out;
1664 1665
1666 decomp = true;
1665 strcpy(symfs_filename, tmp); 1667 strcpy(symfs_filename, tmp);
1666 } 1668 }
1667 1669
@@ -1748,7 +1750,7 @@ out_free_command:
1748out_remove_tmp: 1750out_remove_tmp:
1749 close(stdout_fd[0]); 1751 close(stdout_fd[0]);
1750 1752
1751 if (dso__needs_decompress(dso)) 1753 if (decomp)
1752 unlink(symfs_filename); 1754 unlink(symfs_filename);
1753 1755
1754 if (delete_extract) 1756 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 @@
4 4
5#ifdef HAVE_ZLIB_SUPPORT 5#ifdef HAVE_ZLIB_SUPPORT
6int gzip_decompress_to_file(const char *input, int output_fd); 6int gzip_decompress_to_file(const char *input, int output_fd);
7bool gzip_is_compressed(const char *input);
7#endif 8#endif
8 9
9#ifdef HAVE_LZMA_SUPPORT 10#ifdef HAVE_LZMA_SUPPORT
10int lzma_decompress_to_file(const char *input, int output_fd); 11int lzma_decompress_to_file(const char *input, int output_fd);
12bool lzma_is_compressed(const char *input);
11#endif 13#endif
12 14
13#endif /* PERF_COMPRESS_H */ 15#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,
189 return ret; 189 return ret;
190} 190}
191 191
192enum {
193 COMP_ID__NONE = 0,
194};
195
192static const struct { 196static const struct {
193 const char *fmt; 197 const char *fmt;
194 int (*decompress)(const char *input, int output); 198 int (*decompress)(const char *input, int output);
199 bool (*is_compressed)(const char *input);
195} compressions[] = { 200} compressions[] = {
201 [COMP_ID__NONE] = { .fmt = NULL, },
196#ifdef HAVE_ZLIB_SUPPORT 202#ifdef HAVE_ZLIB_SUPPORT
197 { "gz", gzip_decompress_to_file }, 203 { "gz", gzip_decompress_to_file, gzip_is_compressed },
198#endif 204#endif
199#ifdef HAVE_LZMA_SUPPORT 205#ifdef HAVE_LZMA_SUPPORT
200 { "xz", lzma_decompress_to_file }, 206 { "xz", lzma_decompress_to_file, lzma_is_compressed },
201#endif 207#endif
202 { NULL, NULL }, 208 { NULL, NULL, NULL },
203}; 209};
204 210
205bool is_supported_compression(const char *ext) 211static int is_supported_compression(const char *ext)
206{ 212{
207 unsigned i; 213 unsigned i;
208 214
209 for (i = 0; compressions[i].fmt; i++) { 215 for (i = 1; compressions[i].fmt; i++) {
210 if (!strcmp(ext, compressions[i].fmt)) 216 if (!strcmp(ext, compressions[i].fmt))
211 return true; 217 return i;
212 } 218 }
213 return false; 219 return COMP_ID__NONE;
214} 220}
215 221
216bool is_kernel_module(const char *pathname, int cpumode) 222bool is_kernel_module(const char *pathname, int cpumode)
@@ -239,80 +245,73 @@ bool is_kernel_module(const char *pathname, int cpumode)
239 return m.kmod; 245 return m.kmod;
240} 246}
241 247
242bool decompress_to_file(const char *ext, const char *filename, int output_fd)
243{
244 unsigned i;
245
246 for (i = 0; compressions[i].fmt; i++) {
247 if (!strcmp(ext, compressions[i].fmt))
248 return !compressions[i].decompress(filename,
249 output_fd);
250 }
251 return false;
252}
253
254bool dso__needs_decompress(struct dso *dso) 248bool dso__needs_decompress(struct dso *dso)
255{ 249{
256 return dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP || 250 return dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP ||
257 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP; 251 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP;
258} 252}
259 253
260static int decompress_kmodule(struct dso *dso, const char *name, char *tmpbuf) 254static int decompress_kmodule(struct dso *dso, const char *name,
255 char *pathname, size_t len)
261{ 256{
257 char tmpbuf[] = KMOD_DECOMP_NAME;
262 int fd = -1; 258 int fd = -1;
263 struct kmod_path m;
264 259
265 if (!dso__needs_decompress(dso)) 260 if (!dso__needs_decompress(dso))
266 return -1; 261 return -1;
267 262
268 if (kmod_path__parse_ext(&m, dso->long_name)) 263 if (dso->comp == COMP_ID__NONE)
269 return -1; 264 return -1;
270 265
271 if (!m.comp) 266 /*
272 goto out; 267 * We have proper compression id for DSO and yet the file
268 * behind the 'name' can still be plain uncompressed object.
269 *
270 * The reason is behind the logic we open the DSO object files,
271 * when we try all possible 'debug' objects until we find the
272 * data. So even if the DSO is represented by 'krava.xz' module,
273 * we can end up here opening ~/.debug/....23432432/debug' file
274 * which is not compressed.
275 *
276 * To keep this transparent, we detect this and return the file
277 * descriptor to the uncompressed file.
278 */
279 if (!compressions[dso->comp].is_compressed(name))
280 return open(name, O_RDONLY);
273 281
274 fd = mkstemp(tmpbuf); 282 fd = mkstemp(tmpbuf);
275 if (fd < 0) { 283 if (fd < 0) {
276 dso->load_errno = errno; 284 dso->load_errno = errno;
277 goto out; 285 return -1;
278 } 286 }
279 287
280 if (!decompress_to_file(m.ext, name, fd)) { 288 if (compressions[dso->comp].decompress(name, fd)) {
281 dso->load_errno = DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE; 289 dso->load_errno = DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE;
282 close(fd); 290 close(fd);
283 fd = -1; 291 fd = -1;
284 } 292 }
285 293
286out: 294 if (!pathname || (fd < 0))
287 free(m.ext); 295 unlink(tmpbuf);
296
297 if (pathname && (fd >= 0))
298 strncpy(pathname, tmpbuf, len);
299
288 return fd; 300 return fd;
289} 301}
290 302
291int dso__decompress_kmodule_fd(struct dso *dso, const char *name) 303int dso__decompress_kmodule_fd(struct dso *dso, const char *name)
292{ 304{
293 char tmpbuf[] = KMOD_DECOMP_NAME; 305 return decompress_kmodule(dso, name, NULL, 0);
294 int fd;
295
296 fd = decompress_kmodule(dso, name, tmpbuf);
297 unlink(tmpbuf);
298 return fd;
299} 306}
300 307
301int dso__decompress_kmodule_path(struct dso *dso, const char *name, 308int dso__decompress_kmodule_path(struct dso *dso, const char *name,
302 char *pathname, size_t len) 309 char *pathname, size_t len)
303{ 310{
304 char tmpbuf[] = KMOD_DECOMP_NAME; 311 int fd = decompress_kmodule(dso, name, pathname, len);
305 int fd;
306 312
307 fd = decompress_kmodule(dso, name, tmpbuf);
308 if (fd < 0) {
309 unlink(tmpbuf);
310 return -1;
311 }
312
313 strncpy(pathname, tmpbuf, len);
314 close(fd); 313 close(fd);
315 return 0; 314 return fd >= 0 ? 0 : -1;
316} 315}
317 316
318/* 317/*
@@ -332,7 +331,7 @@ int dso__decompress_kmodule_path(struct dso *dso, const char *name,
332 * Returns 0 if there's no strdup error, -ENOMEM otherwise. 331 * Returns 0 if there's no strdup error, -ENOMEM otherwise.
333 */ 332 */
334int __kmod_path__parse(struct kmod_path *m, const char *path, 333int __kmod_path__parse(struct kmod_path *m, const char *path,
335 bool alloc_name, bool alloc_ext) 334 bool alloc_name)
336{ 335{
337 const char *name = strrchr(path, '/'); 336 const char *name = strrchr(path, '/');
338 const char *ext = strrchr(path, '.'); 337 const char *ext = strrchr(path, '.');
@@ -372,10 +371,9 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
372 return 0; 371 return 0;
373 } 372 }
374 373
375 if (is_supported_compression(ext + 1)) { 374 m->comp = is_supported_compression(ext + 1);
376 m->comp = true; 375 if (m->comp > COMP_ID__NONE)
377 ext -= 3; 376 ext -= 3;
378 }
379 377
380 /* Check .ko extension only if there's enough name left. */ 378 /* Check .ko extension only if there's enough name left. */
381 if (ext > name) 379 if (ext > name)
@@ -393,14 +391,6 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
393 strxfrchar(m->name, '-', '_'); 391 strxfrchar(m->name, '-', '_');
394 } 392 }
395 393
396 if (alloc_ext && m->comp) {
397 m->ext = strdup(ext + 4);
398 if (!m->ext) {
399 free((void *) m->name);
400 return -ENOMEM;
401 }
402 }
403
404 return 0; 394 return 0;
405} 395}
406 396
@@ -413,8 +403,10 @@ void dso__set_module_info(struct dso *dso, struct kmod_path *m,
413 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE; 403 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
414 404
415 /* _KMODULE_COMP should be next to _KMODULE */ 405 /* _KMODULE_COMP should be next to _KMODULE */
416 if (m->kmod && m->comp) 406 if (m->kmod && m->comp) {
417 dso->symtab_type++; 407 dso->symtab_type++;
408 dso->comp = m->comp;
409 }
418 410
419 dso__set_short_name(dso, strdup(m->name), true); 411 dso__set_short_name(dso, strdup(m->name), true);
420} 412}
@@ -468,6 +460,7 @@ static int __open_dso(struct dso *dso, struct machine *machine)
468 int fd = -EINVAL; 460 int fd = -EINVAL;
469 char *root_dir = (char *)""; 461 char *root_dir = (char *)"";
470 char *name = malloc(PATH_MAX); 462 char *name = malloc(PATH_MAX);
463 bool decomp = false;
471 464
472 if (!name) 465 if (!name)
473 return -ENOMEM; 466 return -ENOMEM;
@@ -491,12 +484,13 @@ static int __open_dso(struct dso *dso, struct machine *machine)
491 goto out; 484 goto out;
492 } 485 }
493 486
487 decomp = true;
494 strcpy(name, newpath); 488 strcpy(name, newpath);
495 } 489 }
496 490
497 fd = do_open(name); 491 fd = do_open(name);
498 492
499 if (dso__needs_decompress(dso)) 493 if (decomp)
500 unlink(name); 494 unlink(name);
501 495
502out: 496out:
@@ -1218,6 +1212,7 @@ struct dso *dso__new(const char *name)
1218 dso->a2l_fails = 1; 1212 dso->a2l_fails = 1;
1219 dso->kernel = DSO_TYPE_USER; 1213 dso->kernel = DSO_TYPE_USER;
1220 dso->needs_swap = DSO_SWAP__UNSET; 1214 dso->needs_swap = DSO_SWAP__UNSET;
1215 dso->comp = COMP_ID__NONE;
1221 RB_CLEAR_NODE(&dso->rb_node); 1216 RB_CLEAR_NODE(&dso->rb_node);
1222 dso->root = NULL; 1217 dso->root = NULL;
1223 INIT_LIST_HEAD(&dso->node); 1218 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 {
175 u16 short_name_len; 175 u16 short_name_len;
176 void *dwfl; /* DWARF debug info */ 176 void *dwfl; /* DWARF debug info */
177 struct auxtrace_cache *auxtrace_cache; 177 struct auxtrace_cache *auxtrace_cache;
178 int comp;
178 179
179 /* dso data file */ 180 /* dso data file */
180 struct { 181 struct {
@@ -250,9 +251,7 @@ int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir);
250char dso__symtab_origin(const struct dso *dso); 251char dso__symtab_origin(const struct dso *dso);
251int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type, 252int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type,
252 char *root_dir, char *filename, size_t size); 253 char *root_dir, char *filename, size_t size);
253bool is_supported_compression(const char *ext);
254bool is_kernel_module(const char *pathname, int cpumode); 254bool is_kernel_module(const char *pathname, int cpumode);
255bool decompress_to_file(const char *ext, const char *filename, int output_fd);
256bool dso__needs_decompress(struct dso *dso); 255bool dso__needs_decompress(struct dso *dso);
257int dso__decompress_kmodule_fd(struct dso *dso, const char *name); 256int dso__decompress_kmodule_fd(struct dso *dso, const char *name);
258int dso__decompress_kmodule_path(struct dso *dso, const char *name, 257int 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,
263 262
264struct kmod_path { 263struct kmod_path {
265 char *name; 264 char *name;
266 char *ext; 265 int comp;
267 bool comp;
268 bool kmod; 266 bool kmod;
269}; 267};
270 268
271int __kmod_path__parse(struct kmod_path *m, const char *path, 269int __kmod_path__parse(struct kmod_path *m, const char *path,
272 bool alloc_name, bool alloc_ext); 270 bool alloc_name);
273 271
274#define kmod_path__parse(__m, __p) __kmod_path__parse(__m, __p, false, false) 272#define kmod_path__parse(__m, __p) __kmod_path__parse(__m, __p, false)
275#define kmod_path__parse_name(__m, __p) __kmod_path__parse(__m, __p, true , false) 273#define kmod_path__parse_name(__m, __p) __kmod_path__parse(__m, __p, true)
276#define kmod_path__parse_ext(__m, __p) __kmod_path__parse(__m, __p, false, true)
277 274
278void dso__set_module_info(struct dso *dso, struct kmod_path *m, 275void dso__set_module_info(struct dso *dso, struct kmod_path *m,
279 struct machine *machine); 276 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,
803 if (*output == -1) { 803 if (*output == -1) {
804 *output = fd; 804 *output = fd;
805 805
806 if (perf_mmap__mmap(&maps[idx], mp, *output) < 0) 806 if (perf_mmap__mmap(&maps[idx], mp, *output, evlist_cpu) < 0)
807 return -1; 807 return -1;
808 } else { 808 } else {
809 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0) 809 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 @@
22 "$CLANG_OPTIONS $KERNEL_INC_OPTIONS $PERF_BPF_INC_OPTIONS " \ 22 "$CLANG_OPTIONS $KERNEL_INC_OPTIONS $PERF_BPF_INC_OPTIONS " \
23 "-Wno-unused-value -Wno-pointer-sign " \ 23 "-Wno-unused-value -Wno-pointer-sign " \
24 "-working-directory $WORKING_DIR " \ 24 "-working-directory $WORKING_DIR " \
25 "-c \"$CLANG_SOURCE\" -target bpf -O2 -o -" 25 "-c \"$CLANG_SOURCE\" -target bpf $CLANG_EMIT_LLVM -O2 -o - $LLVM_OPTIONS_PIPE"
26 26
27struct llvm_param llvm_param = { 27struct llvm_param llvm_param = {
28 .clang_path = "clang", 28 .clang_path = "clang",
29 .llc_path = "llc",
29 .clang_bpf_cmd_template = CLANG_BPF_CMD_DEFAULT_TEMPLATE, 30 .clang_bpf_cmd_template = CLANG_BPF_CMD_DEFAULT_TEMPLATE,
30 .clang_opt = NULL, 31 .clang_opt = NULL,
32 .opts = NULL,
31 .kbuild_dir = NULL, 33 .kbuild_dir = NULL,
32 .kbuild_opts = NULL, 34 .kbuild_opts = NULL,
33 .user_set_param = false, 35 .user_set_param = false,
@@ -51,6 +53,8 @@ int perf_llvm_config(const char *var, const char *value)
51 llvm_param.kbuild_opts = strdup(value); 53 llvm_param.kbuild_opts = strdup(value);
52 else if (!strcmp(var, "dump-obj")) 54 else if (!strcmp(var, "dump-obj"))
53 llvm_param.dump_obj = !!perf_config_bool(var, value); 55 llvm_param.dump_obj = !!perf_config_bool(var, value);
56 else if (!strcmp(var, "opts"))
57 llvm_param.opts = strdup(value);
54 else { 58 else {
55 pr_debug("Invalid LLVM config option: %s\n", value); 59 pr_debug("Invalid LLVM config option: %s\n", value);
56 return -1; 60 return -1;
@@ -430,11 +434,13 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
430 unsigned int kernel_version; 434 unsigned int kernel_version;
431 char linux_version_code_str[64]; 435 char linux_version_code_str[64];
432 const char *clang_opt = llvm_param.clang_opt; 436 const char *clang_opt = llvm_param.clang_opt;
433 char clang_path[PATH_MAX], abspath[PATH_MAX], nr_cpus_avail_str[64]; 437 char clang_path[PATH_MAX], llc_path[PATH_MAX], abspath[PATH_MAX], nr_cpus_avail_str[64];
434 char serr[STRERR_BUFSIZE]; 438 char serr[STRERR_BUFSIZE];
435 char *kbuild_dir = NULL, *kbuild_include_opts = NULL, 439 char *kbuild_dir = NULL, *kbuild_include_opts = NULL,
436 *perf_bpf_include_opts = NULL; 440 *perf_bpf_include_opts = NULL;
437 const char *template = llvm_param.clang_bpf_cmd_template; 441 const char *template = llvm_param.clang_bpf_cmd_template;
442 char *pipe_template = NULL;
443 const char *opts = llvm_param.opts;
438 char *command_echo = NULL, *command_out; 444 char *command_echo = NULL, *command_out;
439 char *perf_include_dir = system_path(PERF_INCLUDE_DIR); 445 char *perf_include_dir = system_path(PERF_INCLUDE_DIR);
440 446
@@ -484,6 +490,26 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
484 force_set_env("PERF_BPF_INC_OPTIONS", perf_bpf_include_opts); 490 force_set_env("PERF_BPF_INC_OPTIONS", perf_bpf_include_opts);
485 force_set_env("WORKING_DIR", kbuild_dir ? : "."); 491 force_set_env("WORKING_DIR", kbuild_dir ? : ".");
486 492
493 if (opts) {
494 err = search_program(llvm_param.llc_path, "llc", llc_path);
495 if (err) {
496 pr_err("ERROR:\tunable to find llc.\n"
497 "Hint:\tTry to install latest clang/llvm to support BPF. Check your $PATH\n"
498 " \tand 'llc-path' option in [llvm] section of ~/.perfconfig.\n");
499 version_notice();
500 goto errout;
501 }
502
503 if (asprintf(&pipe_template, "%s -emit-llvm | %s -march=bpf %s -filetype=obj -o -",
504 template, llc_path, opts) < 0) {
505 pr_err("ERROR:\tnot enough memory to setup command line\n");
506 goto errout;
507 }
508
509 template = pipe_template;
510
511 }
512
487 /* 513 /*
488 * Since we may reset clang's working dir, path of source file 514 * Since we may reset clang's working dir, path of source file
489 * should be transferred into absolute path, except we want 515 * should be transferred into absolute path, except we want
@@ -535,6 +561,7 @@ errout:
535 free(obj_buf); 561 free(obj_buf);
536 free(perf_bpf_include_opts); 562 free(perf_bpf_include_opts);
537 free(perf_include_dir); 563 free(perf_include_dir);
564 free(pipe_template);
538 if (p_obj_buf) 565 if (p_obj_buf)
539 *p_obj_buf = NULL; 566 *p_obj_buf = NULL;
540 if (p_obj_buf_sz) 567 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 @@
11struct llvm_param { 11struct llvm_param {
12 /* Path of clang executable */ 12 /* Path of clang executable */
13 const char *clang_path; 13 const char *clang_path;
14 /* Path of llc executable */
15 const char *llc_path;
14 /* 16 /*
15 * Template of clang bpf compiling. 5 env variables 17 * Template of clang bpf compiling. 5 env variables
16 * can be used: 18 * can be used:
@@ -23,6 +25,13 @@ struct llvm_param {
23 const char *clang_bpf_cmd_template; 25 const char *clang_bpf_cmd_template;
24 /* Will be filled in $CLANG_OPTIONS */ 26 /* Will be filled in $CLANG_OPTIONS */
25 const char *clang_opt; 27 const char *clang_opt;
28 /*
29 * If present it'll add -emit-llvm to $CLANG_OPTIONS to pipe
30 * the clang output to llc, useful for new llvm options not
31 * yet selectable via 'clang -mllvm option', such as -mattr=dwarfris
32 * in clang 6.0/llvm 7
33 */
34 const char *opts;
26 /* Where to find kbuild system */ 35 /* Where to find kbuild system */
27 const char *kbuild_dir; 36 const char *kbuild_dir;
28 /* 37 /*
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 @@
3#include <lzma.h> 3#include <lzma.h>
4#include <stdio.h> 4#include <stdio.h>
5#include <linux/compiler.h> 5#include <linux/compiler.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <fcntl.h>
6#include "compress.h" 9#include "compress.h"
7#include "util.h" 10#include "util.h"
8#include "debug.h" 11#include "debug.h"
12#include <unistd.h>
9 13
10#define BUFSIZE 8192 14#define BUFSIZE 8192
11 15
@@ -99,3 +103,19 @@ err_fclose:
99 fclose(infile); 103 fclose(infile);
100 return err; 104 return err;
101} 105}
106
107bool lzma_is_compressed(const char *input)
108{
109 int fd = open(input, O_RDONLY);
110 const uint8_t magic[6] = { 0xFD, '7', 'z', 'X', 'Z', 0x00 };
111 char buf[6] = { 0 };
112 ssize_t rc;
113
114 if (fd < 0)
115 return -1;
116
117 rc = read(fd, buf, sizeof(buf));
118 close(fd);
119 return rc == sizeof(buf) ?
120 memcmp(buf, magic, sizeof(buf)) == 0 : false;
121}
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,
1212 * Full name could reveal us kmod compression, so 1212 * Full name could reveal us kmod compression, so
1213 * we need to update the symtab_type if needed. 1213 * we need to update the symtab_type if needed.
1214 */ 1214 */
1215 if (m->comp && is_kmod_dso(map->dso)) 1215 if (m->comp && is_kmod_dso(map->dso)) {
1216 map->dso->symtab_type++; 1216 map->dso->symtab_type++;
1217 map->dso->comp = m->comp;
1218 }
1217 1219
1218 return 0; 1220 return 0;
1219} 1221}
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)
164 auxtrace_mmap__munmap(&map->auxtrace_mmap); 164 auxtrace_mmap__munmap(&map->auxtrace_mmap);
165} 165}
166 166
167int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd) 167int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd, int cpu)
168{ 168{
169 /* 169 /*
170 * The last one will be done at perf_mmap__consume(), so that we 170 * 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)
191 return -1; 191 return -1;
192 } 192 }
193 map->fd = fd; 193 map->fd = fd;
194 map->cpu = cpu;
194 195
195 if (auxtrace_mmap__mmap(&map->auxtrace_mmap, 196 if (auxtrace_mmap__mmap(&map->auxtrace_mmap,
196 &mp->auxtrace_mp, map->base, fd)) 197 &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 {
18 void *base; 18 void *base;
19 int mask; 19 int mask;
20 int fd; 20 int fd;
21 int cpu;
21 refcount_t refcnt; 22 refcount_t refcnt;
22 u64 prev; 23 u64 prev;
23 u64 start; 24 u64 start;
@@ -60,7 +61,7 @@ struct mmap_params {
60 struct auxtrace_mmap_params auxtrace_mp; 61 struct auxtrace_mmap_params auxtrace_mp;
61}; 62};
62 63
63int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd); 64int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd, int cpu);
64void perf_mmap__munmap(struct perf_mmap *map); 65void perf_mmap__munmap(struct perf_mmap *map);
65 66
66void perf_mmap__get(struct perf_mmap *map); 67void 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)
1991 int nr_addr_filters = 0; 1991 int nr_addr_filters = 0;
1992 struct perf_pmu *pmu = NULL; 1992 struct perf_pmu *pmu = NULL;
1993 1993
1994 if (evsel == NULL) 1994 if (evsel == NULL) {
1995 goto err; 1995 fprintf(stderr,
1996 "--filter option should follow a -e tracepoint or HW tracer option\n");
1997 return -1;
1998 }
1996 1999
1997 if (evsel->attr.type == PERF_TYPE_TRACEPOINT) { 2000 if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
1998 if (perf_evsel__append_tp_filter(evsel, str) < 0) { 2001 if (perf_evsel__append_tp_filter(evsel, str) < 0) {
@@ -2014,8 +2017,11 @@ static int set_filter(struct perf_evsel *evsel, const void *arg)
2014 perf_pmu__scan_file(pmu, "nr_addr_filters", 2017 perf_pmu__scan_file(pmu, "nr_addr_filters",
2015 "%d", &nr_addr_filters); 2018 "%d", &nr_addr_filters);
2016 2019
2017 if (!nr_addr_filters) 2020 if (!nr_addr_filters) {
2018 goto err; 2021 fprintf(stderr,
2022 "This CPU does not support address filtering\n");
2023 return -1;
2024 }
2019 2025
2020 if (perf_evsel__append_addr_filter(evsel, str) < 0) { 2026 if (perf_evsel__append_addr_filter(evsel, str) < 0) {
2021 fprintf(stderr, 2027 fprintf(stderr,
@@ -2024,12 +2030,6 @@ static int set_filter(struct perf_evsel *evsel, const void *arg)
2024 } 2030 }
2025 2031
2026 return 0; 2032 return 0;
2027
2028err:
2029 fprintf(stderr,
2030 "--filter option should follow a -e tracepoint or HW tracer option\n");
2031
2032 return -1;
2033} 2033}
2034 2034
2035int parse_filter(const struct option *opt, const char *str, 2035int 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 @@
11#include "cpumap.h" 11#include "cpumap.h"
12#include "print_binary.h" 12#include "print_binary.h"
13#include "thread_map.h" 13#include "thread_map.h"
14#include "mmap.h"
14 15
15#if PY_MAJOR_VERSION < 3 16#if PY_MAJOR_VERSION < 3
16#define _PyUnicode_FromString(arg) \ 17#define _PyUnicode_FromString(arg) \
@@ -976,6 +977,20 @@ static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist,
976 return Py_BuildValue("i", evlist->nr_entries); 977 return Py_BuildValue("i", evlist->nr_entries);
977} 978}
978 979
980static struct perf_mmap *get_md(struct perf_evlist *evlist, int cpu)
981{
982 int i;
983
984 for (i = 0; i < evlist->nr_mmaps; i++) {
985 struct perf_mmap *md = &evlist->mmap[i];
986
987 if (md->cpu == cpu)
988 return md;
989 }
990
991 return NULL;
992}
993
979static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, 994static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
980 PyObject *args, PyObject *kwargs) 995 PyObject *args, PyObject *kwargs)
981{ 996{
@@ -990,7 +1005,10 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
990 &cpu, &sample_id_all)) 1005 &cpu, &sample_id_all))
991 return NULL; 1006 return NULL;
992 1007
993 md = &evlist->mmap[cpu]; 1008 md = get_md(evlist, cpu);
1009 if (!md)
1010 return NULL;
1011
994 if (perf_mmap__read_init(md) < 0) 1012 if (perf_mmap__read_init(md) < 0)
995 goto end; 1013 goto end;
996 1014
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 @@
5#include <sys/stat.h> 5#include <sys/stat.h>
6#include <sys/mman.h> 6#include <sys/mman.h>
7#include <zlib.h> 7#include <zlib.h>
8#include <linux/compiler.h>
9#include <unistd.h>
8 10
9#include "util/compress.h" 11#include "util/compress.h"
10#include "util/util.h" 12#include "util/util.h"
@@ -79,3 +81,19 @@ out_close:
79 81
80 return ret == Z_STREAM_END ? 0 : -1; 82 return ret == Z_STREAM_END ? 0 : -1;
81} 83}
84
85bool gzip_is_compressed(const char *input)
86{
87 int fd = open(input, O_RDONLY);
88 const uint8_t magic[2] = { 0x1f, 0x8b };
89 char buf[2] = { 0 };
90 ssize_t rc;
91
92 if (fd < 0)
93 return -1;
94
95 rc = read(fd, buf, sizeof(buf));
96 close(fd);
97 return rc == sizeof(buf) ?
98 memcmp(buf, magic, sizeof(buf)) == 0 : false;
99}