Commit 66e5db4a authored by Ingo Molnar's avatar Ingo Molnar

Merge tag 'perf-core-for-mingo-4.19-20180820' of...

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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents 5804b110 78303650
...@@ -219,6 +219,7 @@ ...@@ -219,6 +219,7 @@
#define X86_FEATURE_IBPB ( 7*32+26) /* Indirect Branch Prediction Barrier */ #define X86_FEATURE_IBPB ( 7*32+26) /* Indirect Branch Prediction Barrier */
#define X86_FEATURE_STIBP ( 7*32+27) /* Single Thread Indirect Branch Predictors */ #define X86_FEATURE_STIBP ( 7*32+27) /* Single Thread Indirect Branch Predictors */
#define X86_FEATURE_ZEN ( 7*32+28) /* "" CPU is AMD family 0x17 (Zen) */ #define X86_FEATURE_ZEN ( 7*32+28) /* "" CPU is AMD family 0x17 (Zen) */
#define X86_FEATURE_IBRS_ENHANCED ( 7*32+29) /* Enhanced IBRS */
/* Virtualization flags: Linux defined, word 8 */ /* Virtualization flags: Linux defined, word 8 */
#define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */ #define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */
...@@ -229,7 +230,7 @@ ...@@ -229,7 +230,7 @@
#define X86_FEATURE_VMMCALL ( 8*32+15) /* Prefer VMMCALL to VMCALL */ #define X86_FEATURE_VMMCALL ( 8*32+15) /* Prefer VMMCALL to VMCALL */
#define X86_FEATURE_XENPV ( 8*32+16) /* "" Xen paravirtual guest */ #define X86_FEATURE_XENPV ( 8*32+16) /* "" Xen paravirtual guest */
#define X86_FEATURE_EPT_AD ( 8*32+17) /* Intel Extended Page Table access-dirty bit */
/* Intel-defined CPU features, CPUID level 0x00000007:0 (EBX), word 9 */ /* Intel-defined CPU features, CPUID level 0x00000007:0 (EBX), word 9 */
#define X86_FEATURE_FSGSBASE ( 9*32+ 0) /* RDFSBASE, WRFSBASE, RDGSBASE, WRGSBASE instructions*/ #define X86_FEATURE_FSGSBASE ( 9*32+ 0) /* RDFSBASE, WRFSBASE, RDGSBASE, WRGSBASE instructions*/
......
...@@ -256,7 +256,7 @@ ENTRY(__memcpy_mcsafe) ...@@ -256,7 +256,7 @@ ENTRY(__memcpy_mcsafe)
/* Copy successful. Return zero */ /* Copy successful. Return zero */
.L_done_memcpy_trap: .L_done_memcpy_trap:
xorq %rax, %rax xorl %eax, %eax
ret ret
ENDPROC(__memcpy_mcsafe) ENDPROC(__memcpy_mcsafe)
EXPORT_SYMBOL_GPL(__memcpy_mcsafe) EXPORT_SYMBOL_GPL(__memcpy_mcsafe)
......
// SPDX-License-Identifier: LGPL-2.1
/* /*
* Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
* *
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License (not later!)
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* *
* The parts for function graph printing was taken and modified from the * The parts for function graph printing was taken and modified from the
* Linux Kernel that were written by * Linux Kernel that were written by
......
// SPDX-License-Identifier: LGPL-2.1
/* /*
* Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
* *
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License (not later!)
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/ */
#include <ctype.h> #include <ctype.h>
......
/* SPDX-License-Identifier: LGPL-2.1 */
/* /*
* Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
* *
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License (not later!)
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/ */
#ifndef __UTIL_H #ifndef __UTIL_H
#define __UTIL_H #define __UTIL_H
......
// SPDX-License-Identifier: LGPL-2.1
/* /*
* Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
* *
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License (not later!)
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
......
// SPDX-License-Identifier: LGPL-2.1
/* /*
* Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
* *
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License (not later!)
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
......
// SPDX-License-Identifier: LGPL-2.1
/* /*
* Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
* *
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License (not later!)
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
......
// SPDX-License-Identifier: LGPL-2.1
/* /*
* Copyright (C) 2009 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> * Copyright (C) 2009 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
* *
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License (not later!)
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
......
...@@ -84,10 +84,10 @@ endif # has_clean ...@@ -84,10 +84,10 @@ endif # has_clean
endif # MAKECMDGOALS endif # MAKECMDGOALS
# #
# The clean target is not really parallel, don't print the jobs info: # Explicitly disable parallelism for the clean target.
# #
clean: clean:
$(make) $(make) -j1
# #
# The build-test target is not really parallel, don't print the jobs info, # The build-test target is not really parallel, don't print the jobs info,
......
...@@ -232,6 +232,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode, ...@@ -232,6 +232,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
u64 objdump_addr; u64 objdump_addr;
const char *objdump_name; const char *objdump_name;
char decomp_name[KMOD_DECOMP_LEN]; char decomp_name[KMOD_DECOMP_LEN];
bool decomp = false;
int ret; int ret;
pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr); 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,6 +306,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
return -1; return -1;
} }
decomp = true;
objdump_name = decomp_name; objdump_name = decomp_name;
} }
...@@ -312,7 +314,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode, ...@@ -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); objdump_addr = map__rip_2objdump(al.map, al.addr);
ret = read_via_objdump(objdump_name, objdump_addr, buf2, len); ret = read_via_objdump(objdump_name, objdump_addr, buf2, len);
if (dso__needs_decompress(al.map->dso)) if (decomp)
unlink(objdump_name); unlink(objdump_name);
if (ret > 0) { if (ret > 0) {
......
...@@ -5,34 +5,28 @@ ...@@ -5,34 +5,28 @@
#include "dso.h" #include "dso.h"
#include "debug.h" #include "debug.h"
static int test(const char *path, bool alloc_name, bool alloc_ext, static int test(const char *path, bool alloc_name, bool kmod,
bool kmod, bool comp, const char *name, const char *ext) int comp, const char *name)
{ {
struct kmod_path m; struct kmod_path m;
memset(&m, 0x0, sizeof(m)); memset(&m, 0x0, sizeof(m));
TEST_ASSERT_VAL("kmod_path__parse", 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", pr_debug("%s - alloc name %d, kmod %d, comp %d, name '%s'\n",
path, alloc_name, alloc_ext, m.kmod, m.comp, m.name, m.ext); path, alloc_name, m.kmod, m.comp, m.name);
TEST_ASSERT_VAL("wrong kmod", m.kmod == kmod); TEST_ASSERT_VAL("wrong kmod", m.kmod == kmod);
TEST_ASSERT_VAL("wrong comp", m.comp == comp); 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) if (name)
TEST_ASSERT_VAL("wrong name", m.name && !strcmp(name, m.name)); TEST_ASSERT_VAL("wrong name", m.name && !strcmp(name, m.name));
else else
TEST_ASSERT_VAL("wrong name", !m.name); TEST_ASSERT_VAL("wrong name", !m.name);
free(m.name); free(m.name);
free(m.ext);
return 0; return 0;
} }
...@@ -45,118 +39,118 @@ static int test_is_kernel_module(const char *path, int cpumode, bool expect) ...@@ -45,118 +39,118 @@ static int test_is_kernel_module(const char *path, int cpumode, bool expect)
return 0; return 0;
} }
#define T(path, an, ae, k, c, n, e) \ #define T(path, an, k, c, n) \
TEST_ASSERT_VAL("failed", !test(path, an, ae, k, c, n, e)) TEST_ASSERT_VAL("failed", !test(path, an, k, c, n))
#define M(path, c, e) \ #define M(path, c, e) \
TEST_ASSERT_VAL("failed", !test_is_kernel_module(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) int test__kmod_path__parse(struct test *t __maybe_unused, int subtest __maybe_unused)
{ {
/* path alloc_name alloc_ext kmod comp name ext */ /* path alloc_name kmod comp name */
T("/xxxx/xxxx/x-x.ko", true , true , true, false, "[x_x]", NULL); T("/xxxx/xxxx/x-x.ko", true , true, 0 , "[x_x]");
T("/xxxx/xxxx/x-x.ko", false , true , true, false, NULL , NULL); T("/xxxx/xxxx/x-x.ko", false , true, 0 , NULL );
T("/xxxx/xxxx/x-x.ko", true , false , true, false, "[x_x]", NULL); T("/xxxx/xxxx/x-x.ko", true , true, 0 , "[x_x]");
T("/xxxx/xxxx/x-x.ko", false , false , true, false, NULL , NULL); 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_CPUMODE_UNKNOWN, true);
M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_KERNEL, true); M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_KERNEL, true);
M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_USER, false); M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_USER, false);
#ifdef HAVE_ZLIB_SUPPORT #ifdef HAVE_ZLIB_SUPPORT
/* path alloc_name alloc_ext kmod comp name ext */ /* path alloc_name kmod comp name */
T("/xxxx/xxxx/x.ko.gz", true , true , true, true, "[x]", "gz"); T("/xxxx/xxxx/x.ko.gz", true , true, 1 , "[x]");
T("/xxxx/xxxx/x.ko.gz", false , true , true, true, NULL , "gz"); T("/xxxx/xxxx/x.ko.gz", false , true, 1 , NULL );
T("/xxxx/xxxx/x.ko.gz", true , false , true, true, "[x]", NULL); T("/xxxx/xxxx/x.ko.gz", true , true, 1 , "[x]");
T("/xxxx/xxxx/x.ko.gz", false , false , true, true, NULL , NULL); 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_CPUMODE_UNKNOWN, true);
M("/xxxx/xxxx/x.ko.gz", PERF_RECORD_MISC_KERNEL, true); M("/xxxx/xxxx/x.ko.gz", PERF_RECORD_MISC_KERNEL, true);
M("/xxxx/xxxx/x.ko.gz", PERF_RECORD_MISC_USER, false); M("/xxxx/xxxx/x.ko.gz", PERF_RECORD_MISC_USER, false);
/* path alloc_name alloc_ext kmod comp name ext */ /* path alloc_name kmod comp name */
T("/xxxx/xxxx/x.gz", true , true , false, true, "x.gz" ,"gz"); T("/xxxx/xxxx/x.gz", true , false, 1 , "x.gz");
T("/xxxx/xxxx/x.gz", false , true , false, true, NULL ,"gz"); T("/xxxx/xxxx/x.gz", false , false, 1 , NULL );
T("/xxxx/xxxx/x.gz", true , false , false, true, "x.gz" , NULL); T("/xxxx/xxxx/x.gz", true , false, 1 , "x.gz");
T("/xxxx/xxxx/x.gz", false , false , false, true, NULL , NULL); 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_CPUMODE_UNKNOWN, false);
M("/xxxx/xxxx/x.gz", PERF_RECORD_MISC_KERNEL, false); M("/xxxx/xxxx/x.gz", PERF_RECORD_MISC_KERNEL, false);
M("/xxxx/xxxx/x.gz", PERF_RECORD_MISC_USER, false); M("/xxxx/xxxx/x.gz", PERF_RECORD_MISC_USER, false);
/* path alloc_name alloc_ext kmod comp name ext */ /* path alloc_name kmod comp name */
T("x.gz", true , true , false, true, "x.gz", "gz"); T("x.gz", true , false, 1 , "x.gz");
T("x.gz", false , true , false, true, NULL , "gz"); T("x.gz", false , false, 1 , NULL );
T("x.gz", true , false , false, true, "x.gz", NULL); T("x.gz", true , false, 1 , "x.gz");
T("x.gz", false , false , false, true, NULL , NULL); T("x.gz", false , false, 1 , NULL );
M("x.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false); M("x.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
M("x.gz", PERF_RECORD_MISC_KERNEL, false); M("x.gz", PERF_RECORD_MISC_KERNEL, false);
M("x.gz", PERF_RECORD_MISC_USER, false); M("x.gz", PERF_RECORD_MISC_USER, false);
/* path alloc_name alloc_ext kmod comp name ext */ /* path alloc_name kmod comp name */
T("x.ko.gz", true , true , true, true, "[x]", "gz"); T("x.ko.gz", true , true, 1 , "[x]");
T("x.ko.gz", false , true , true, true, NULL , "gz"); T("x.ko.gz", false , true, 1 , NULL );
T("x.ko.gz", true , false , true, true, "[x]", NULL); T("x.ko.gz", true , true, 1 , "[x]");
T("x.ko.gz", false , false , true, true, NULL , NULL); 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_CPUMODE_UNKNOWN, true);
M("x.ko.gz", PERF_RECORD_MISC_KERNEL, true); M("x.ko.gz", PERF_RECORD_MISC_KERNEL, true);
M("x.ko.gz", PERF_RECORD_MISC_USER, false); M("x.ko.gz", PERF_RECORD_MISC_USER, false);
#endif #endif
/* path alloc_name alloc_ext kmod comp name ext */ /* path alloc_name kmod comp name */
T("[test_module]", true , true , true, false, "[test_module]", NULL); T("[test_module]", true , true, false, "[test_module]");
T("[test_module]", false , true , true, false, NULL , NULL); T("[test_module]", false , true, false, NULL );
T("[test_module]", true , false , true, false, "[test_module]", NULL); T("[test_module]", true , true, false, "[test_module]");
T("[test_module]", false , false , true, false, NULL , NULL); T("[test_module]", false , true, false, NULL );
M("[test_module]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true); M("[test_module]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
M("[test_module]", PERF_RECORD_MISC_KERNEL, true); M("[test_module]", PERF_RECORD_MISC_KERNEL, true);
M("[test_module]", PERF_RECORD_MISC_USER, false); M("[test_module]", PERF_RECORD_MISC_USER, false);
/* path alloc_name alloc_ext kmod comp name ext */ /* path alloc_name kmod comp name */
T("[test.module]", true , true , true, false, "[test.module]", NULL); T("[test.module]", true , true, false, "[test.module]");
T("[test.module]", false , true , true, false, NULL , NULL); T("[test.module]", false , true, false, NULL );
T("[test.module]", true , false , true, false, "[test.module]", NULL); T("[test.module]", true , true, false, "[test.module]");
T("[test.module]", false , false , true, false, NULL , NULL); T("[test.module]", false , true, false, NULL );
M("[test.module]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true); M("[test.module]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
M("[test.module]", PERF_RECORD_MISC_KERNEL, true); M("[test.module]", PERF_RECORD_MISC_KERNEL, true);
M("[test.module]", PERF_RECORD_MISC_USER, false); M("[test.module]", PERF_RECORD_MISC_USER, false);
/* path alloc_name alloc_ext kmod comp name ext */ /* path alloc_name kmod comp name */
T("[vdso]", true , true , false, false, "[vdso]", NULL); T("[vdso]", true , false, false, "[vdso]");
T("[vdso]", false , true , false, false, NULL , NULL); T("[vdso]", false , false, false, NULL );
T("[vdso]", true , false , false, false, "[vdso]", NULL); T("[vdso]", true , false, false, "[vdso]");
T("[vdso]", false , false , false, false, NULL , NULL); T("[vdso]", false , false, false, NULL );
M("[vdso]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false); M("[vdso]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
M("[vdso]", PERF_RECORD_MISC_KERNEL, false); M("[vdso]", PERF_RECORD_MISC_KERNEL, false);
M("[vdso]", PERF_RECORD_MISC_USER, false); M("[vdso]", PERF_RECORD_MISC_USER, false);
T("[vdso32]", true , true , false, false, "[vdso32]", NULL); T("[vdso32]", true , false, false, "[vdso32]");
T("[vdso32]", false , true , false, false, NULL , NULL); T("[vdso32]", false , false, false, NULL );
T("[vdso32]", true , false , false, false, "[vdso32]", NULL); T("[vdso32]", true , false, false, "[vdso32]");
T("[vdso32]", false , false , false, false, NULL , NULL); T("[vdso32]", false , false, false, NULL );
M("[vdso32]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false); M("[vdso32]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
M("[vdso32]", PERF_RECORD_MISC_KERNEL, false); M("[vdso32]", PERF_RECORD_MISC_KERNEL, false);
M("[vdso32]", PERF_RECORD_MISC_USER, false); M("[vdso32]", PERF_RECORD_MISC_USER, false);
T("[vdsox32]", true , true , false, false, "[vdsox32]", NULL); T("[vdsox32]", true , false, false, "[vdsox32]");
T("[vdsox32]", false , true , false, false, NULL , NULL); T("[vdsox32]", false , false, false, NULL );
T("[vdsox32]", true , false , false, false, "[vdsox32]", NULL); T("[vdsox32]", true , false, false, "[vdsox32]");
T("[vdsox32]", false , false , false, false, NULL , NULL); T("[vdsox32]", false , false, false, NULL );
M("[vdsox32]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false); M("[vdsox32]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
M("[vdsox32]", PERF_RECORD_MISC_KERNEL, false); M("[vdsox32]", PERF_RECORD_MISC_KERNEL, false);
M("[vdsox32]", PERF_RECORD_MISC_USER, false); M("[vdsox32]", PERF_RECORD_MISC_USER, false);
/* path alloc_name alloc_ext kmod comp name ext */ /* path alloc_name kmod comp name */
T("[vsyscall]", true , true , false, false, "[vsyscall]", NULL); T("[vsyscall]", true , false, false, "[vsyscall]");
T("[vsyscall]", false , true , false, false, NULL , NULL); T("[vsyscall]", false , false, false, NULL );
T("[vsyscall]", true , false , false, false, "[vsyscall]", NULL); T("[vsyscall]", true , false, false, "[vsyscall]");
T("[vsyscall]", false , false , false, false, NULL , NULL); T("[vsyscall]", false , false, false, NULL );
M("[vsyscall]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false); M("[vsyscall]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
M("[vsyscall]", PERF_RECORD_MISC_KERNEL, false); M("[vsyscall]", PERF_RECORD_MISC_KERNEL, false);
M("[vsyscall]", PERF_RECORD_MISC_USER, false); M("[vsyscall]", PERF_RECORD_MISC_USER, false);
/* path alloc_name alloc_ext kmod comp name ext */ /* path alloc_name kmod comp name */
T("[kernel.kallsyms]", true , true , false, false, "[kernel.kallsyms]", NULL); T("[kernel.kallsyms]", true , false, false, "[kernel.kallsyms]");
T("[kernel.kallsyms]", false , true , false, false, NULL , NULL); T("[kernel.kallsyms]", false , false, false, NULL );
T("[kernel.kallsyms]", true , false , false, false, "[kernel.kallsyms]", NULL); T("[kernel.kallsyms]", true , false, false, "[kernel.kallsyms]");
T("[kernel.kallsyms]", false , false , false, false, NULL , NULL); T("[kernel.kallsyms]", false , false, false, NULL );
M("[kernel.kallsyms]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false); M("[kernel.kallsyms]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
M("[kernel.kallsyms]", PERF_RECORD_MISC_KERNEL, false); M("[kernel.kallsyms]", PERF_RECORD_MISC_KERNEL, false);
M("[kernel.kallsyms]", PERF_RECORD_MISC_USER, false); M("[kernel.kallsyms]", PERF_RECORD_MISC_USER, false);
......
...@@ -1629,6 +1629,7 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args) ...@@ -1629,6 +1629,7 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
char symfs_filename[PATH_MAX]; char symfs_filename[PATH_MAX];
struct kcore_extract kce; struct kcore_extract kce;
bool delete_extract = false; bool delete_extract = false;
bool decomp = false;
int stdout_fd[2]; int stdout_fd[2];
int lineno = 0; int lineno = 0;
int nline; int nline;
...@@ -1662,6 +1663,7 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args) ...@@ -1662,6 +1663,7 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
tmp, sizeof(tmp)) < 0) tmp, sizeof(tmp)) < 0)
goto out; goto out;
decomp = true;
strcpy(symfs_filename, tmp); strcpy(symfs_filename, tmp);
} }
...@@ -1748,7 +1750,7 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args) ...@@ -1748,7 +1750,7 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
out_remove_tmp: out_remove_tmp:
close(stdout_fd[0]); close(stdout_fd[0]);
if (dso__needs_decompress(dso)) if (decomp)
unlink(symfs_filename); unlink(symfs_filename);
if (delete_extract) if (delete_extract)
......
...@@ -4,10 +4,12 @@ ...@@ -4,10 +4,12 @@
#ifdef HAVE_ZLIB_SUPPORT #ifdef HAVE_ZLIB_SUPPORT
int gzip_decompress_to_file(const char *input, int output_fd); int gzip_decompress_to_file(const char *input, int output_fd);
bool gzip_is_compressed(const char *input);
#endif #endif
#ifdef HAVE_LZMA_SUPPORT #ifdef HAVE_LZMA_SUPPORT
int lzma_decompress_to_file(const char *input, int output_fd); int lzma_decompress_to_file(const char *input, int output_fd);
bool lzma_is_compressed(const char *input);
#endif #endif
#endif /* PERF_COMPRESS_H */ #endif /* PERF_COMPRESS_H */
...@@ -189,28 +189,34 @@ int dso__read_binary_type_filename(const struct dso *dso, ...@@ -189,28 +189,34 @@ int dso__read_binary_type_filename(const struct dso *dso,
return ret; return ret;
} }
enum {
COMP_ID__NONE = 0,
};
static const struct { static const struct {
const char *fmt; const char *fmt;
int (*decompress)(const char *input, int output); int (*decompress)(const char *input, int output);
bool (*is_compressed)(const char *input);
} compressions[] = { } compressions[] = {
[COMP_ID__NONE] = { .fmt = NULL, },
#ifdef HAVE_ZLIB_SUPPORT #ifdef HAVE_ZLIB_SUPPORT
{ "gz", gzip_decompress_to_file }, { "gz", gzip_decompress_to_file, gzip_is_compressed },
#endif #endif
#ifdef HAVE_LZMA_SUPPORT #ifdef HAVE_LZMA_SUPPORT
{ "xz", lzma_decompress_to_file }, { "xz", lzma_decompress_to_file, lzma_is_compressed },
#endif #endif
{ NULL, NULL }, { NULL, NULL, NULL },
}; };
bool is_supported_compression(const char *ext) static int is_supported_compression(const char *ext)
{ {
unsigned i; unsigned i;
for (i = 0; compressions[i].fmt; i++) { for (i = 1; compressions[i].fmt; i++) {
if (!strcmp(ext, compressions[i].fmt)) 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) bool is_kernel_module(const char *pathname, int cpumode)
...@@ -239,80 +245,73 @@ 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; 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) bool dso__needs_decompress(struct dso *dso)
{ {
return dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP || return dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP ||
dso->symtab_type == DSO_BINARY_TYPE__GUEST_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; int fd = -1;
struct kmod_path m;
if (!dso__needs_decompress(dso)) if (!dso__needs_decompress(dso))
return -1; return -1;
if (kmod_path__parse_ext(&m, dso->long_name)) if (dso->comp == COMP_ID__NONE)
return -1; 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); fd = mkstemp(tmpbuf);
if (fd < 0) { if (fd < 0) {
dso->load_errno = errno; 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; dso->load_errno = DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE;
close(fd); close(fd);
fd = -1; fd = -1;
} }
out: if (!pathname || (fd < 0))
free(m.ext); unlink(tmpbuf);
if (pathname && (fd >= 0))
strncpy(pathname, tmpbuf, len);
return fd; return fd;
} }
int dso__decompress_kmodule_fd(struct dso *dso, const char *name) int dso__decompress_kmodule_fd(struct dso *dso, const char *name)
{ {
char tmpbuf[] = KMOD_DECOMP_NAME; return decompress_kmodule(dso, name, NULL, 0);
int fd;
fd = decompress_kmodule(dso, name, tmpbuf);
unlink(tmpbuf);
return fd;
} }
int dso__decompress_kmodule_path(struct dso *dso, const char *name, int dso__decompress_kmodule_path(struct dso *dso, const char *name,
char *pathname, size_t len) char *pathname, size_t len)
{ {
char tmpbuf[] = KMOD_DECOMP_NAME; int fd = decompress_kmodule(dso, name, pathname, len);
int fd;
fd = decompress_kmodule(dso, name, tmpbuf);
if (fd < 0) {
unlink(tmpbuf);
return -1;
}
strncpy(pathname, tmpbuf, len);
close(fd); close(fd);
return 0; return fd >= 0 ? 0 : -1;
} }
/* /*
...@@ -332,7 +331,7 @@ int dso__decompress_kmodule_path(struct dso *dso, const char *name, ...@@ -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. * Returns 0 if there's no strdup error, -ENOMEM otherwise.
*/ */
int __kmod_path__parse(struct kmod_path *m, const char *path, 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 *name = strrchr(path, '/');
const char *ext = strrchr(path, '.'); const char *ext = strrchr(path, '.');
...@@ -372,10 +371,9 @@ int __kmod_path__parse(struct kmod_path *m, const char *path, ...@@ -372,10 +371,9 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
return 0; return 0;
} }
if (is_supported_compression(ext + 1)) { m->comp = is_supported_compression(ext + 1);
m->comp = true; if (m->comp > COMP_ID__NONE)
ext -= 3; ext -= 3;
}
/* Check .ko extension only if there's enough name left. */ /* Check .ko extension only if there's enough name left. */
if (ext > name) if (ext > name)
...@@ -393,14 +391,6 @@ int __kmod_path__parse(struct kmod_path *m, const char *path, ...@@ -393,14 +391,6 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
strxfrchar(m->name, '-', '_'); strxfrchar(m->name, '-', '_');
} }
if (alloc_ext && m->comp) {
m->ext = strdup(ext + 4);
if (!m->ext) {
free((void *) m->name);
return -ENOMEM;
}
}
return 0; return 0;
} }
...@@ -413,8 +403,10 @@ void dso__set_module_info(struct dso *dso, struct kmod_path *m, ...@@ -413,8 +403,10 @@ void dso__set_module_info(struct dso *dso, struct kmod_path *m,
dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE; dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
/* _KMODULE_COMP should be next to _KMODULE */ /* _KMODULE_COMP should be next to _KMODULE */
if (m->kmod && m->comp) if (m->kmod && m->comp) {
dso->symtab_type++; dso->symtab_type++;
dso->comp = m->comp;
}
dso__set_short_name(dso, strdup(m->name), true); dso__set_short_name(dso, strdup(m->name), true);
} }
...@@ -468,6 +460,7 @@ static int __open_dso(struct dso *dso, struct machine *machine) ...@@ -468,6 +460,7 @@ static int __open_dso(struct dso *dso, struct machine *machine)
int fd = -EINVAL; int fd = -EINVAL;
char *root_dir = (char *)""; char *root_dir = (char *)"";
char *name = malloc(PATH_MAX); char *name = malloc(PATH_MAX);
bool decomp = false;
if (!name) if (!name)
return -ENOMEM; return -ENOMEM;
...@@ -491,12 +484,13 @@ static int __open_dso(struct dso *dso, struct machine *machine) ...@@ -491,12 +484,13 @@ static int __open_dso(struct dso *dso, struct machine *machine)
goto out; goto out;
} }
decomp = true;
strcpy(name, newpath); strcpy(name, newpath);
} }
fd = do_open(name); fd = do_open(name);
if (dso__needs_decompress(dso)) if (decomp)
unlink(name); unlink(name);
out: out:
...@@ -1218,6 +1212,7 @@ struct dso *dso__new(const char *name) ...@@ -1218,6 +1212,7 @@ struct dso *dso__new(const char *name)
dso->a2l_fails = 1; dso->a2l_fails = 1;
dso->kernel = DSO_TYPE_USER; dso->kernel = DSO_TYPE_USER;
dso->needs_swap = DSO_SWAP__UNSET; dso->needs_swap = DSO_SWAP__UNSET;
dso->comp = COMP_ID__NONE;
RB_CLEAR_NODE(&dso->rb_node); RB_CLEAR_NODE(&dso->rb_node);
dso->root = NULL; dso->root = NULL;
INIT_LIST_HEAD(&dso->node); INIT_LIST_HEAD(&dso->node);
......
...@@ -175,6 +175,7 @@ struct dso { ...@@ -175,6 +175,7 @@ struct dso {
u16 short_name_len; u16 short_name_len;
void *dwfl; /* DWARF debug info */ void *dwfl; /* DWARF debug info */
struct auxtrace_cache *auxtrace_cache; struct auxtrace_cache *auxtrace_cache;
int comp;
/* dso data file */ /* dso data file */
struct { struct {
...@@ -250,9 +251,7 @@ int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir); ...@@ -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); char dso__symtab_origin(const struct dso *dso);
int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type, int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type,
char *root_dir, char *filename, size_t size); 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 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); bool dso__needs_decompress(struct dso *dso);
int dso__decompress_kmodule_fd(struct dso *dso, const char *name); int dso__decompress_kmodule_fd(struct dso *dso, const char *name);
int dso__decompress_kmodule_path(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, ...@@ -263,17 +262,15 @@ int dso__decompress_kmodule_path(struct dso *dso, const char *name,
struct kmod_path { struct kmod_path {
char *name; char *name;
char *ext; int comp;
bool comp;
bool kmod; bool kmod;
}; };
int __kmod_path__parse(struct kmod_path *m, const char *path, 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(__m, __p) __kmod_path__parse(__m, __p, false)
#define kmod_path__parse_name(__m, __p) __kmod_path__parse(__m, __p, true , false) #define kmod_path__parse_name(__m, __p) __kmod_path__parse(__m, __p, true)
#define kmod_path__parse_ext(__m, __p) __kmod_path__parse(__m, __p, false, true)
void dso__set_module_info(struct dso *dso, struct kmod_path *m, void dso__set_module_info(struct dso *dso, struct kmod_path *m,
struct machine *machine); struct machine *machine);
......
...@@ -803,7 +803,7 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, ...@@ -803,7 +803,7 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
if (*output == -1) { if (*output == -1) {
*output = fd; *output = fd;
if (perf_mmap__mmap(&maps[idx], mp, *output) < 0) if (perf_mmap__mmap(&maps[idx], mp, *output, evlist_cpu) < 0)
return -1; return -1;
} else { } else {
if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0) if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
......
...@@ -22,12 +22,14 @@ ...@@ -22,12 +22,14 @@
"$CLANG_OPTIONS $KERNEL_INC_OPTIONS $PERF_BPF_INC_OPTIONS " \ "$CLANG_OPTIONS $KERNEL_INC_OPTIONS $PERF_BPF_INC_OPTIONS " \
"-Wno-unused-value -Wno-pointer-sign " \ "-Wno-unused-value -Wno-pointer-sign " \
"-working-directory $WORKING_DIR " \ "-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 = { struct llvm_param llvm_param = {
.clang_path = "clang", .clang_path = "clang",
.llc_path = "llc",
.clang_bpf_cmd_template = CLANG_BPF_CMD_DEFAULT_TEMPLATE, .clang_bpf_cmd_template = CLANG_BPF_CMD_DEFAULT_TEMPLATE,
.clang_opt = NULL, .clang_opt = NULL,
.opts = NULL,
.kbuild_dir = NULL, .kbuild_dir = NULL,
.kbuild_opts = NULL, .kbuild_opts = NULL,
.user_set_param = false, .user_set_param = false,
...@@ -51,6 +53,8 @@ int perf_llvm_config(const char *var, const char *value) ...@@ -51,6 +53,8 @@ int perf_llvm_config(const char *var, const char *value)
llvm_param.kbuild_opts = strdup(value); llvm_param.kbuild_opts = strdup(value);
else if (!strcmp(var, "dump-obj")) else if (!strcmp(var, "dump-obj"))
llvm_param.dump_obj = !!perf_config_bool(var, value); llvm_param.dump_obj = !!perf_config_bool(var, value);
else if (!strcmp(var, "opts"))
llvm_param.opts = strdup(value);
else { else {
pr_debug("Invalid LLVM config option: %s\n", value); pr_debug("Invalid LLVM config option: %s\n", value);
return -1; return -1;
...@@ -430,11 +434,13 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf, ...@@ -430,11 +434,13 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
unsigned int kernel_version; unsigned int kernel_version;
char linux_version_code_str[64]; char linux_version_code_str[64];
const char *clang_opt = llvm_param.clang_opt; 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 serr[STRERR_BUFSIZE];
char *kbuild_dir = NULL, *kbuild_include_opts = NULL, char *kbuild_dir = NULL, *kbuild_include_opts = NULL,
*perf_bpf_include_opts = NULL; *perf_bpf_include_opts = NULL;
const char *template = llvm_param.clang_bpf_cmd_template; 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 *command_echo = NULL, *command_out;
char *perf_include_dir = system_path(PERF_INCLUDE_DIR); char *perf_include_dir = system_path(PERF_INCLUDE_DIR);
...@@ -484,6 +490,26 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf, ...@@ -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("PERF_BPF_INC_OPTIONS", perf_bpf_include_opts);
force_set_env("WORKING_DIR", kbuild_dir ? : "."); 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 * Since we may reset clang's working dir, path of source file
* should be transferred into absolute path, except we want * should be transferred into absolute path, except we want
...@@ -535,6 +561,7 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf, ...@@ -535,6 +561,7 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
free(obj_buf); free(obj_buf);
free(perf_bpf_include_opts); free(perf_bpf_include_opts);
free(perf_include_dir); free(perf_include_dir);
free(pipe_template);
if (p_obj_buf) if (p_obj_buf)
*p_obj_buf = NULL; *p_obj_buf = NULL;
if (p_obj_buf_sz) if (p_obj_buf_sz)
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
struct llvm_param { struct llvm_param {
/* Path of clang executable */ /* Path of clang executable */
const char *clang_path; const char *clang_path;
/* Path of llc executable */
const char *llc_path;
/* /*
* Template of clang bpf compiling. 5 env variables * Template of clang bpf compiling. 5 env variables
* can be used: * can be used:
...@@ -23,6 +25,13 @@ struct llvm_param { ...@@ -23,6 +25,13 @@ struct llvm_param {
const char *clang_bpf_cmd_template; const char *clang_bpf_cmd_template;
/* Will be filled in $CLANG_OPTIONS */ /* Will be filled in $CLANG_OPTIONS */
const char *clang_opt; 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 */ /* Where to find kbuild system */
const char *kbuild_dir; const char *kbuild_dir;
/* /*
......
...@@ -3,9 +3,13 @@ ...@@ -3,9 +3,13 @@
#include <lzma.h> #include <lzma.h>
#include <stdio.h> #include <stdio.h>
#include <linux/compiler.h> #include <linux/compiler.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "compress.h" #include "compress.h"
#include "util.h" #include "util.h"
#include "debug.h" #include "debug.h"
#include <unistd.h>
#define BUFSIZE 8192 #define BUFSIZE 8192
...@@ -99,3 +103,19 @@ int lzma_decompress_to_file(const char *input, int output_fd) ...@@ -99,3 +103,19 @@ int lzma_decompress_to_file(const char *input, int output_fd)
fclose(infile); fclose(infile);
return err; 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;
}
...@@ -1212,8 +1212,10 @@ static int map_groups__set_module_path(struct map_groups *mg, const char *path, ...@@ -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 * Full name could reveal us kmod compression, so
* we need to update the symtab_type if needed. * 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->symtab_type++;
map->dso->comp = m->comp;
}
return 0; return 0;
} }
......
...@@ -164,7 +164,7 @@ void perf_mmap__munmap(struct perf_mmap *map) ...@@ -164,7 +164,7 @@ void perf_mmap__munmap(struct perf_mmap *map)
auxtrace_mmap__munmap(&map->auxtrace_mmap); 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 * 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,6 +191,7 @@ int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd)
return -1; return -1;
} }
map->fd = fd; map->fd = fd;
map->cpu = cpu;
if (auxtrace_mmap__mmap(&map->auxtrace_mmap, if (auxtrace_mmap__mmap(&map->auxtrace_mmap,
&mp->auxtrace_mp, map->base, fd)) &mp->auxtrace_mp, map->base, fd))
......
...@@ -18,6 +18,7 @@ struct perf_mmap { ...@@ -18,6 +18,7 @@ struct perf_mmap {
void *base; void *base;
int mask; int mask;
int fd; int fd;
int cpu;
refcount_t refcnt; refcount_t refcnt;
u64 prev; u64 prev;
u64 start; u64 start;
...@@ -60,7 +61,7 @@ struct mmap_params { ...@@ -60,7 +61,7 @@ struct mmap_params {
struct auxtrace_mmap_params auxtrace_mp; 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__munmap(struct perf_mmap *map);
void perf_mmap__get(struct perf_mmap *map); void perf_mmap__get(struct perf_mmap *map);
......
...@@ -1991,8 +1991,11 @@ static int set_filter(struct perf_evsel *evsel, const void *arg) ...@@ -1991,8 +1991,11 @@ static int set_filter(struct perf_evsel *evsel, const void *arg)
int nr_addr_filters = 0; int nr_addr_filters = 0;
struct perf_pmu *pmu = NULL; struct perf_pmu *pmu = NULL;
if (evsel == NULL) if (evsel == NULL) {
goto err; fprintf(stderr,
"--filter option should follow a -e tracepoint or HW tracer option\n");
return -1;
}
if (evsel->attr.type == PERF_TYPE_TRACEPOINT) { if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
if (perf_evsel__append_tp_filter(evsel, str) < 0) { 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,8 +2017,11 @@ static int set_filter(struct perf_evsel *evsel, const void *arg)
perf_pmu__scan_file(pmu, "nr_addr_filters", perf_pmu__scan_file(pmu, "nr_addr_filters",
"%d", &nr_addr_filters); "%d", &nr_addr_filters);
if (!nr_addr_filters) if (!nr_addr_filters) {
goto err; fprintf(stderr,
"This CPU does not support address filtering\n");
return -1;
}
if (perf_evsel__append_addr_filter(evsel, str) < 0) { if (perf_evsel__append_addr_filter(evsel, str) < 0) {
fprintf(stderr, fprintf(stderr,
...@@ -2024,12 +2030,6 @@ static int set_filter(struct perf_evsel *evsel, const void *arg) ...@@ -2024,12 +2030,6 @@ static int set_filter(struct perf_evsel *evsel, const void *arg)
} }
return 0; 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, int parse_filter(const struct option *opt, const char *str,
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "cpumap.h" #include "cpumap.h"
#include "print_binary.h" #include "print_binary.h"
#include "thread_map.h" #include "thread_map.h"
#include "mmap.h"
#if PY_MAJOR_VERSION < 3 #if PY_MAJOR_VERSION < 3
#define _PyUnicode_FromString(arg) \ #define _PyUnicode_FromString(arg) \
...@@ -976,6 +977,20 @@ static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist, ...@@ -976,6 +977,20 @@ static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist,
return Py_BuildValue("i", evlist->nr_entries); 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, static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
PyObject *args, PyObject *kwargs) PyObject *args, PyObject *kwargs)
{ {
...@@ -990,7 +1005,10 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, ...@@ -990,7 +1005,10 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
&cpu, &sample_id_all)) &cpu, &sample_id_all))
return NULL; return NULL;
md = &evlist->mmap[cpu]; md = get_md(evlist, cpu);
if (!md)
return NULL;
if (perf_mmap__read_init(md) < 0) if (perf_mmap__read_init(md) < 0)
goto end; goto end;
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <zlib.h> #include <zlib.h>
#include <linux/compiler.h>
#include <unistd.h>
#include "util/compress.h" #include "util/compress.h"
#include "util/util.h" #include "util/util.h"
...@@ -79,3 +81,19 @@ int gzip_decompress_to_file(const char *input, int output_fd) ...@@ -79,3 +81,19 @@ int gzip_decompress_to_file(const char *input, int output_fd)
return ret == Z_STREAM_END ? 0 : -1; 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;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment