Commit 98d7e741 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'perf-tools-fixes-2020-06-02' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux

Pull perf tooling fixes from Arnaldo Carvalho de Melo:

 - Update various UAPI headers, some automatically adding support for a
   new MSR and the faccess2 syscall.

 - Fix corner case NULL deref in the histograms code.

 - Fix corner case NULL deref in 'perf stat' aggregation code.

 - Fix array pointer deref and old style declaration in the parsing of
   events.

 - Fix segfault when processing ZSTD compressed perf.data files in 'perf
   script' due to lack of initialization of the ZSTD library.

 - Handle __attribute__((user)) in libtraceevent fixing the parsing of
   syscall tracepoints with user buffers.

 - Make libtraevent aware of __builtin_expect() appearing in tracepoint
   fields.

 - Make the BPF prologue generation use bpf_probe_read_{user,kernel}().

 - Fix the '@user' attribute parsing in kprobes variables in 'perf
   probe'.

 - Fix error message when asking for -fsanitize=address without required
   libraries.

* tag 'perf-tools-fixes-2020-06-02' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux: (22 commits)
  perf build: Fix error message when asking for -fsanitize=address without required libraries
  tools lib traceevent: Add handler for __builtin_expect()
  tools lib traceevent: Handle __attribute__((user)) in field names
  tools lib traceevent: Add append() function helper for appending strings
  tools headers UAPI: Sync linux/fs.h with the kernel sources
  tools include UAPI: Sync linux/vhost.h with the kernel sources
  tools arch x86: Sync the msr-index.h copy with the kernel sources
  perf script: Initialize zstd_data
  perf pmu: Remove unused declaration
  perf parse-events: Fix an old style declaration
  perf parse-events: Fix an incompatible pointer
  perf bpf: Fix bpf prologue generation
  perf probe: Fix user attribute access in kprobes
  perf stat: Fix NULL pointer dereference
  perf report: Fix NULL pointer dereference in hists__fprintf_nr_sample_events()
  tools headers UAPI: Sync kvm.h headers with the kernel sources
  tools headers UAPI: Sync drm/i915_drm.h with the kernel sources
  tools headers UAPI: Sync linux/fscrypt.h with the kernel sources
  perf beauty: Add support to STATX_MNT_ID in the 'statx' syscall 'mask' argument
  tools headers uapi: Sync linux/stat.h with the kernel sources
  ...
parents 5e857ce6 6a1515c9
...@@ -362,6 +362,7 @@ ...@@ -362,6 +362,7 @@
#define X86_FEATURE_AVX512_4FMAPS (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */ #define X86_FEATURE_AVX512_4FMAPS (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */
#define X86_FEATURE_FSRM (18*32+ 4) /* Fast Short Rep Mov */ #define X86_FEATURE_FSRM (18*32+ 4) /* Fast Short Rep Mov */
#define X86_FEATURE_AVX512_VP2INTERSECT (18*32+ 8) /* AVX-512 Intersect for D/Q */ #define X86_FEATURE_AVX512_VP2INTERSECT (18*32+ 8) /* AVX-512 Intersect for D/Q */
#define X86_FEATURE_SRBDS_CTRL (18*32+ 9) /* "" SRBDS mitigation MSR available */
#define X86_FEATURE_MD_CLEAR (18*32+10) /* VERW clears CPU buffers */ #define X86_FEATURE_MD_CLEAR (18*32+10) /* VERW clears CPU buffers */
#define X86_FEATURE_TSX_FORCE_ABORT (18*32+13) /* "" TSX_FORCE_ABORT */ #define X86_FEATURE_TSX_FORCE_ABORT (18*32+13) /* "" TSX_FORCE_ABORT */
#define X86_FEATURE_PCONFIG (18*32+18) /* Intel PCONFIG */ #define X86_FEATURE_PCONFIG (18*32+18) /* Intel PCONFIG */
...@@ -407,5 +408,6 @@ ...@@ -407,5 +408,6 @@
#define X86_BUG_SWAPGS X86_BUG(21) /* CPU is affected by speculation through SWAPGS */ #define X86_BUG_SWAPGS X86_BUG(21) /* CPU is affected by speculation through SWAPGS */
#define X86_BUG_TAA X86_BUG(22) /* CPU is affected by TSX Async Abort(TAA) */ #define X86_BUG_TAA X86_BUG(22) /* CPU is affected by TSX Async Abort(TAA) */
#define X86_BUG_ITLB_MULTIHIT X86_BUG(23) /* CPU may incur MCE during certain page attribute changes */ #define X86_BUG_ITLB_MULTIHIT X86_BUG(23) /* CPU may incur MCE during certain page attribute changes */
#define X86_BUG_SRBDS X86_BUG(24) /* CPU may leak RNG bits if not mitigated */
#endif /* _ASM_X86_CPUFEATURES_H */ #endif /* _ASM_X86_CPUFEATURES_H */
...@@ -128,6 +128,10 @@ ...@@ -128,6 +128,10 @@
#define TSX_CTRL_RTM_DISABLE BIT(0) /* Disable RTM feature */ #define TSX_CTRL_RTM_DISABLE BIT(0) /* Disable RTM feature */
#define TSX_CTRL_CPUID_CLEAR BIT(1) /* Disable TSX enumeration */ #define TSX_CTRL_CPUID_CLEAR BIT(1) /* Disable TSX enumeration */
/* SRBDS support */
#define MSR_IA32_MCU_OPT_CTRL 0x00000123
#define RNGDS_MITG_DIS BIT(0)
#define MSR_IA32_SYSENTER_CS 0x00000174 #define MSR_IA32_SYSENTER_CS 0x00000174
#define MSR_IA32_SYSENTER_ESP 0x00000175 #define MSR_IA32_SYSENTER_ESP 0x00000175
#define MSR_IA32_SYSENTER_EIP 0x00000176 #define MSR_IA32_SYSENTER_EIP 0x00000176
......
...@@ -385,33 +385,48 @@ struct kvm_sync_regs { ...@@ -385,33 +385,48 @@ struct kvm_sync_regs {
#define KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT (1 << 4) #define KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT (1 << 4)
#define KVM_STATE_NESTED_FORMAT_VMX 0 #define KVM_STATE_NESTED_FORMAT_VMX 0
#define KVM_STATE_NESTED_FORMAT_SVM 1 /* unused */ #define KVM_STATE_NESTED_FORMAT_SVM 1
#define KVM_STATE_NESTED_GUEST_MODE 0x00000001 #define KVM_STATE_NESTED_GUEST_MODE 0x00000001
#define KVM_STATE_NESTED_RUN_PENDING 0x00000002 #define KVM_STATE_NESTED_RUN_PENDING 0x00000002
#define KVM_STATE_NESTED_EVMCS 0x00000004 #define KVM_STATE_NESTED_EVMCS 0x00000004
#define KVM_STATE_NESTED_MTF_PENDING 0x00000008 #define KVM_STATE_NESTED_MTF_PENDING 0x00000008
#define KVM_STATE_NESTED_GIF_SET 0x00000100
#define KVM_STATE_NESTED_SMM_GUEST_MODE 0x00000001 #define KVM_STATE_NESTED_SMM_GUEST_MODE 0x00000001
#define KVM_STATE_NESTED_SMM_VMXON 0x00000002 #define KVM_STATE_NESTED_SMM_VMXON 0x00000002
#define KVM_STATE_NESTED_VMX_VMCS_SIZE 0x1000 #define KVM_STATE_NESTED_VMX_VMCS_SIZE 0x1000
#define KVM_STATE_NESTED_SVM_VMCB_SIZE 0x1000
#define KVM_STATE_VMX_PREEMPTION_TIMER_DEADLINE 0x00000001
struct kvm_vmx_nested_state_data { struct kvm_vmx_nested_state_data {
__u8 vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE]; __u8 vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
__u8 shadow_vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE]; __u8 shadow_vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
__u64 preemption_timer_deadline;
}; };
struct kvm_vmx_nested_state_hdr { struct kvm_vmx_nested_state_hdr {
__u32 flags;
__u64 vmxon_pa; __u64 vmxon_pa;
__u64 vmcs12_pa; __u64 vmcs12_pa;
__u64 preemption_timer_deadline;
struct { struct {
__u16 flags; __u16 flags;
} smm; } smm;
}; };
struct kvm_svm_nested_state_data {
/* Save area only used if KVM_STATE_NESTED_RUN_PENDING. */
__u8 vmcb12[KVM_STATE_NESTED_SVM_VMCB_SIZE];
};
struct kvm_svm_nested_state_hdr {
__u64 vmcb_pa;
};
/* for KVM_CAP_NESTED_STATE */ /* for KVM_CAP_NESTED_STATE */
struct kvm_nested_state { struct kvm_nested_state {
__u16 flags; __u16 flags;
...@@ -420,6 +435,7 @@ struct kvm_nested_state { ...@@ -420,6 +435,7 @@ struct kvm_nested_state {
union { union {
struct kvm_vmx_nested_state_hdr vmx; struct kvm_vmx_nested_state_hdr vmx;
struct kvm_svm_nested_state_hdr svm;
/* Pad the header to 128 bytes. */ /* Pad the header to 128 bytes. */
__u8 pad[120]; __u8 pad[120];
...@@ -432,6 +448,7 @@ struct kvm_nested_state { ...@@ -432,6 +448,7 @@ struct kvm_nested_state {
*/ */
union { union {
struct kvm_vmx_nested_state_data vmx[0]; struct kvm_vmx_nested_state_data vmx[0];
struct kvm_svm_nested_state_data svm[0];
} data; } data;
}; };
......
...@@ -2,7 +2,14 @@ ...@@ -2,7 +2,14 @@
#ifndef _UAPI_ASM_X86_UNISTD_H #ifndef _UAPI_ASM_X86_UNISTD_H
#define _UAPI_ASM_X86_UNISTD_H #define _UAPI_ASM_X86_UNISTD_H
/* x32 syscall flag bit */ /*
* x32 syscall flag bit. Some user programs expect syscall NR macros
* and __X32_SYSCALL_BIT to have type int, even though syscall numbers
* are, for practical purposes, unsigned long.
*
* Fortunately, expressions like (nr & ~__X32_SYSCALL_BIT) do the right
* thing regardless.
*/
#define __X32_SYSCALL_BIT 0x40000000 #define __X32_SYSCALL_BIT 0x40000000
#ifndef __KERNEL__ #ifndef __KERNEL__
......
...@@ -150,6 +150,9 @@ ...@@ -150,6 +150,9 @@
{ EXIT_REASON_UMWAIT, "UMWAIT" }, \ { EXIT_REASON_UMWAIT, "UMWAIT" }, \
{ EXIT_REASON_TPAUSE, "TPAUSE" } { EXIT_REASON_TPAUSE, "TPAUSE" }
#define VMX_EXIT_REASON_FLAGS \
{ VMX_EXIT_REASONS_FAILED_VMENTRY, "FAILED_VMENTRY" }
#define VMX_ABORT_SAVE_GUEST_MSR_FAIL 1 #define VMX_ABORT_SAVE_GUEST_MSR_FAIL 1
#define VMX_ABORT_LOAD_HOST_PDPTE_FAIL 2 #define VMX_ABORT_LOAD_HOST_PDPTE_FAIL 2
#define VMX_ABORT_LOAD_HOST_MSR_FAIL 4 #define VMX_ABORT_LOAD_HOST_MSR_FAIL 4
......
...@@ -855,9 +855,11 @@ __SYSCALL(__NR_clone3, sys_clone3) ...@@ -855,9 +855,11 @@ __SYSCALL(__NR_clone3, sys_clone3)
__SYSCALL(__NR_openat2, sys_openat2) __SYSCALL(__NR_openat2, sys_openat2)
#define __NR_pidfd_getfd 438 #define __NR_pidfd_getfd 438
__SYSCALL(__NR_pidfd_getfd, sys_pidfd_getfd) __SYSCALL(__NR_pidfd_getfd, sys_pidfd_getfd)
#define __NR_faccessat2 439
__SYSCALL(__NR_faccessat2, sys_faccessat2)
#undef __NR_syscalls #undef __NR_syscalls
#define __NR_syscalls 439 #define __NR_syscalls 440
/* /*
* 32 bit systems traditionally used different * 32 bit systems traditionally used different
......
...@@ -1969,6 +1969,30 @@ enum drm_i915_perf_property_id { ...@@ -1969,6 +1969,30 @@ enum drm_i915_perf_property_id {
*/ */
DRM_I915_PERF_PROP_HOLD_PREEMPTION, DRM_I915_PERF_PROP_HOLD_PREEMPTION,
/**
* Specifying this pins all contexts to the specified SSEU power
* configuration for the duration of the recording.
*
* This parameter's value is a pointer to a struct
* drm_i915_gem_context_param_sseu.
*
* This property is available in perf revision 4.
*/
DRM_I915_PERF_PROP_GLOBAL_SSEU,
/**
* This optional parameter specifies the timer interval in nanoseconds
* at which the i915 driver will check the OA buffer for available data.
* Minimum allowed value is 100 microseconds. A default value is used by
* the driver if this parameter is not specified. Note that larger timer
* values will reduce cpu consumption during OA perf captures. However,
* excessively large values would potentially result in OA buffer
* overwrites as captures reach end of the OA buffer.
*
* This property is available in perf revision 5.
*/
DRM_I915_PERF_PROP_POLL_OA_PERIOD,
DRM_I915_PERF_PROP_MAX /* non-ABI */ DRM_I915_PERF_PROP_MAX /* non-ABI */
}; };
......
...@@ -84,10 +84,20 @@ ...@@ -84,10 +84,20 @@
#define DN_ATTRIB 0x00000020 /* File changed attibutes */ #define DN_ATTRIB 0x00000020 /* File changed attibutes */
#define DN_MULTISHOT 0x80000000 /* Don't remove notifier */ #define DN_MULTISHOT 0x80000000 /* Don't remove notifier */
/*
* The constants AT_REMOVEDIR and AT_EACCESS have the same value. AT_EACCESS is
* meaningful only to faccessat, while AT_REMOVEDIR is meaningful only to
* unlinkat. The two functions do completely different things and therefore,
* the flags can be allowed to overlap. For example, passing AT_REMOVEDIR to
* faccessat would be undefined behavior and thus treating it equivalent to
* AT_EACCESS is valid undefined behavior.
*/
#define AT_FDCWD -100 /* Special value used to indicate #define AT_FDCWD -100 /* Special value used to indicate
openat should use the current openat should use the current
working directory. */ working directory. */
#define AT_SYMLINK_NOFOLLOW 0x100 /* Do not follow symbolic links. */ #define AT_SYMLINK_NOFOLLOW 0x100 /* Do not follow symbolic links. */
#define AT_EACCESS 0x200 /* Test access permitted for
effective IDs, not real IDs. */
#define AT_REMOVEDIR 0x200 /* Remove directory instead of #define AT_REMOVEDIR 0x200 /* Remove directory instead of
unlinking file. */ unlinking file. */
#define AT_SYMLINK_FOLLOW 0x400 /* Follow symbolic links. */ #define AT_SYMLINK_FOLLOW 0x400 /* Follow symbolic links. */
......
...@@ -262,6 +262,7 @@ struct fsxattr { ...@@ -262,6 +262,7 @@ struct fsxattr {
#define FS_EA_INODE_FL 0x00200000 /* Inode used for large EA */ #define FS_EA_INODE_FL 0x00200000 /* Inode used for large EA */
#define FS_EOFBLOCKS_FL 0x00400000 /* Reserved for ext4 */ #define FS_EOFBLOCKS_FL 0x00400000 /* Reserved for ext4 */
#define FS_NOCOW_FL 0x00800000 /* Do not cow file */ #define FS_NOCOW_FL 0x00800000 /* Do not cow file */
#define FS_DAX_FL 0x02000000 /* Inode is DAX */
#define FS_INLINE_DATA_FL 0x10000000 /* Reserved for ext4 */ #define FS_INLINE_DATA_FL 0x10000000 /* Reserved for ext4 */
#define FS_PROJINHERIT_FL 0x20000000 /* Create with parents projid */ #define FS_PROJINHERIT_FL 0x20000000 /* Create with parents projid */
#define FS_CASEFOLD_FL 0x40000000 /* Folder is case insensitive */ #define FS_CASEFOLD_FL 0x40000000 /* Folder is case insensitive */
......
...@@ -19,7 +19,8 @@ ...@@ -19,7 +19,8 @@
#define FSCRYPT_POLICY_FLAGS_PAD_MASK 0x03 #define FSCRYPT_POLICY_FLAGS_PAD_MASK 0x03
#define FSCRYPT_POLICY_FLAG_DIRECT_KEY 0x04 #define FSCRYPT_POLICY_FLAG_DIRECT_KEY 0x04
#define FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64 0x08 #define FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64 0x08
#define FSCRYPT_POLICY_FLAGS_VALID 0x0F #define FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32 0x10
#define FSCRYPT_POLICY_FLAGS_VALID 0x1F
/* Encryption algorithms */ /* Encryption algorithms */
#define FSCRYPT_MODE_AES_256_XTS 1 #define FSCRYPT_MODE_AES_256_XTS 1
......
...@@ -188,10 +188,13 @@ struct kvm_s390_cmma_log { ...@@ -188,10 +188,13 @@ struct kvm_s390_cmma_log {
struct kvm_hyperv_exit { struct kvm_hyperv_exit {
#define KVM_EXIT_HYPERV_SYNIC 1 #define KVM_EXIT_HYPERV_SYNIC 1
#define KVM_EXIT_HYPERV_HCALL 2 #define KVM_EXIT_HYPERV_HCALL 2
#define KVM_EXIT_HYPERV_SYNDBG 3
__u32 type; __u32 type;
__u32 pad1;
union { union {
struct { struct {
__u32 msr; __u32 msr;
__u32 pad2;
__u64 control; __u64 control;
__u64 evt_page; __u64 evt_page;
__u64 msg_page; __u64 msg_page;
...@@ -201,6 +204,15 @@ struct kvm_hyperv_exit { ...@@ -201,6 +204,15 @@ struct kvm_hyperv_exit {
__u64 result; __u64 result;
__u64 params[2]; __u64 params[2];
} hcall; } hcall;
struct {
__u32 msr;
__u32 pad2;
__u64 control;
__u64 status;
__u64 send_page;
__u64 recv_page;
__u64 pending_page;
} syndbg;
} u; } u;
}; };
...@@ -1017,6 +1029,8 @@ struct kvm_ppc_resize_hpt { ...@@ -1017,6 +1029,8 @@ struct kvm_ppc_resize_hpt {
#define KVM_CAP_S390_VCPU_RESETS 179 #define KVM_CAP_S390_VCPU_RESETS 179
#define KVM_CAP_S390_PROTECTED 180 #define KVM_CAP_S390_PROTECTED 180
#define KVM_CAP_PPC_SECURE_GUEST 181 #define KVM_CAP_PPC_SECURE_GUEST 181
#define KVM_CAP_HALT_POLL 182
#define KVM_CAP_ASYNC_PF_INT 183
#ifdef KVM_CAP_IRQ_ROUTING #ifdef KVM_CAP_IRQ_ROUTING
......
...@@ -123,7 +123,10 @@ struct statx { ...@@ -123,7 +123,10 @@ struct statx {
__u32 stx_dev_major; /* ID of device containing file [uncond] */ __u32 stx_dev_major; /* ID of device containing file [uncond] */
__u32 stx_dev_minor; __u32 stx_dev_minor;
/* 0x90 */ /* 0x90 */
__u64 __spare2[14]; /* Spare space for future expansion */ __u64 stx_mnt_id;
__u64 __spare2;
/* 0xa0 */
__u64 __spare3[12]; /* Spare space for future expansion */
/* 0x100 */ /* 0x100 */
}; };
...@@ -148,6 +151,7 @@ struct statx { ...@@ -148,6 +151,7 @@ struct statx {
#define STATX_BLOCKS 0x00000400U /* Want/got stx_blocks */ #define STATX_BLOCKS 0x00000400U /* Want/got stx_blocks */
#define STATX_BASIC_STATS 0x000007ffU /* The stuff in the normal stat struct */ #define STATX_BASIC_STATS 0x000007ffU /* The stuff in the normal stat struct */
#define STATX_BTIME 0x00000800U /* Want/got stx_btime */ #define STATX_BTIME 0x00000800U /* Want/got stx_btime */
#define STATX_MNT_ID 0x00001000U /* Got stx_mnt_id */
#define STATX__RESERVED 0x80000000U /* Reserved for future struct statx expansion */ #define STATX__RESERVED 0x80000000U /* Reserved for future struct statx expansion */
...@@ -177,7 +181,9 @@ struct statx { ...@@ -177,7 +181,9 @@ struct statx {
#define STATX_ATTR_NODUMP 0x00000040 /* [I] File is not to be dumped */ #define STATX_ATTR_NODUMP 0x00000040 /* [I] File is not to be dumped */
#define STATX_ATTR_ENCRYPTED 0x00000800 /* [I] File requires key to decrypt in fs */ #define STATX_ATTR_ENCRYPTED 0x00000800 /* [I] File requires key to decrypt in fs */
#define STATX_ATTR_AUTOMOUNT 0x00001000 /* Dir: Automount trigger */ #define STATX_ATTR_AUTOMOUNT 0x00001000 /* Dir: Automount trigger */
#define STATX_ATTR_MOUNT_ROOT 0x00002000 /* Root of a mount */
#define STATX_ATTR_VERITY 0x00100000 /* [I] Verity protected file */ #define STATX_ATTR_VERITY 0x00100000 /* [I] Verity protected file */
#define STATX_ATTR_DAX 0x00002000 /* [I] File is DAX */
#endif /* _UAPI_LINUX_STAT_H */ #endif /* _UAPI_LINUX_STAT_H */
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/ioctl.h> #include <linux/ioctl.h>
#define VHOST_FILE_UNBIND -1
/* ioctls */ /* ioctls */
#define VHOST_VIRTIO 0xAF #define VHOST_VIRTIO 0xAF
...@@ -140,4 +142,6 @@ ...@@ -140,4 +142,6 @@
/* Get the max ring size. */ /* Get the max ring size. */
#define VHOST_VDPA_GET_VRING_NUM _IOR(VHOST_VIRTIO, 0x76, __u16) #define VHOST_VDPA_GET_VRING_NUM _IOR(VHOST_VIRTIO, 0x76, __u16)
/* Set event fd for config interrupt*/
#define VHOST_VDPA_SET_CONFIG_CALL _IOW(VHOST_VIRTIO, 0x77, int)
#endif #endif
...@@ -1425,13 +1425,28 @@ static unsigned int type_size(const char *name) ...@@ -1425,13 +1425,28 @@ static unsigned int type_size(const char *name)
return 0; return 0;
} }
static int append(char **buf, const char *delim, const char *str)
{
char *new_buf;
new_buf = realloc(*buf, strlen(*buf) + strlen(delim) + strlen(str) + 1);
if (!new_buf)
return -1;
strcat(new_buf, delim);
strcat(new_buf, str);
*buf = new_buf;
return 0;
}
static int event_read_fields(struct tep_event *event, struct tep_format_field **fields) static int event_read_fields(struct tep_event *event, struct tep_format_field **fields)
{ {
struct tep_format_field *field = NULL; struct tep_format_field *field = NULL;
enum tep_event_type type; enum tep_event_type type;
char *token; char *token;
char *last_token; char *last_token;
char *delim = " ";
int count = 0; int count = 0;
int ret;
do { do {
unsigned int size_dynamic = 0; unsigned int size_dynamic = 0;
...@@ -1490,24 +1505,51 @@ static int event_read_fields(struct tep_event *event, struct tep_format_field ** ...@@ -1490,24 +1505,51 @@ static int event_read_fields(struct tep_event *event, struct tep_format_field **
field->flags |= TEP_FIELD_IS_POINTER; field->flags |= TEP_FIELD_IS_POINTER;
if (field->type) { if (field->type) {
char *new_type; ret = append(&field->type, delim, last_token);
new_type = realloc(field->type,
strlen(field->type) +
strlen(last_token) + 2);
if (!new_type) {
free(last_token);
goto fail;
}
field->type = new_type;
strcat(field->type, " ");
strcat(field->type, last_token);
free(last_token); free(last_token);
if (ret < 0)
goto fail;
} else } else
field->type = last_token; field->type = last_token;
last_token = token; last_token = token;
delim = " ";
continue; continue;
} }
/* Handle __attribute__((user)) */
if ((type == TEP_EVENT_DELIM) &&
strcmp("__attribute__", last_token) == 0 &&
token[0] == '(') {
int depth = 1;
int ret;
ret = append(&field->type, " ", last_token);
ret |= append(&field->type, "", "(");
if (ret < 0)
goto fail;
delim = " ";
while ((type = read_token(&token)) != TEP_EVENT_NONE) {
if (type == TEP_EVENT_DELIM) {
if (token[0] == '(')
depth++;
else if (token[0] == ')')
depth--;
if (!depth)
break;
ret = append(&field->type, "", token);
delim = "";
} else {
ret = append(&field->type, delim, token);
delim = " ";
}
if (ret < 0)
goto fail;
free(last_token);
last_token = token;
}
continue;
}
break; break;
} }
...@@ -1523,8 +1565,6 @@ static int event_read_fields(struct tep_event *event, struct tep_format_field ** ...@@ -1523,8 +1565,6 @@ static int event_read_fields(struct tep_event *event, struct tep_format_field **
if (strcmp(token, "[") == 0) { if (strcmp(token, "[") == 0) {
enum tep_event_type last_type = type; enum tep_event_type last_type = type;
char *brackets = token; char *brackets = token;
char *new_brackets;
int len;
field->flags |= TEP_FIELD_IS_ARRAY; field->flags |= TEP_FIELD_IS_ARRAY;
...@@ -1536,29 +1576,27 @@ static int event_read_fields(struct tep_event *event, struct tep_format_field ** ...@@ -1536,29 +1576,27 @@ static int event_read_fields(struct tep_event *event, struct tep_format_field **
field->arraylen = 0; field->arraylen = 0;
while (strcmp(token, "]") != 0) { while (strcmp(token, "]") != 0) {
const char *delim;
if (last_type == TEP_EVENT_ITEM && if (last_type == TEP_EVENT_ITEM &&
type == TEP_EVENT_ITEM) type == TEP_EVENT_ITEM)
len = 2; delim = " ";
else else
len = 1; delim = "";
last_type = type; last_type = type;
new_brackets = realloc(brackets, ret = append(&brackets, delim, token);
strlen(brackets) + if (ret < 0) {
strlen(token) + len);
if (!new_brackets) {
free(brackets); free(brackets);
goto fail; goto fail;
} }
brackets = new_brackets;
if (len == 2)
strcat(brackets, " ");
strcat(brackets, token);
/* We only care about the last token */ /* We only care about the last token */
field->arraylen = strtoul(token, NULL, 0); field->arraylen = strtoul(token, NULL, 0);
free_token(token); free_token(token);
type = read_token(&token); type = read_token(&token);
if (type == TEP_EVENT_NONE) { if (type == TEP_EVENT_NONE) {
free(brackets);
do_warning_event(event, "failed to find token"); do_warning_event(event, "failed to find token");
goto fail; goto fail;
} }
...@@ -1566,13 +1604,11 @@ static int event_read_fields(struct tep_event *event, struct tep_format_field ** ...@@ -1566,13 +1604,11 @@ static int event_read_fields(struct tep_event *event, struct tep_format_field **
free_token(token); free_token(token);
new_brackets = realloc(brackets, strlen(brackets) + 2); ret = append(&brackets, "", "]");
if (!new_brackets) { if (ret < 0) {
free(brackets); free(brackets);
goto fail; goto fail;
} }
brackets = new_brackets;
strcat(brackets, "]");
/* add brackets to type */ /* add brackets to type */
...@@ -1582,34 +1618,23 @@ static int event_read_fields(struct tep_event *event, struct tep_format_field ** ...@@ -1582,34 +1618,23 @@ static int event_read_fields(struct tep_event *event, struct tep_format_field **
* the format: type [] item; * the format: type [] item;
*/ */
if (type == TEP_EVENT_ITEM) { if (type == TEP_EVENT_ITEM) {
char *new_type; ret = append(&field->type, " ", field->name);
new_type = realloc(field->type, if (ret < 0) {
strlen(field->type) +
strlen(field->name) +
strlen(brackets) + 2);
if (!new_type) {
free(brackets); free(brackets);
goto fail; goto fail;
} }
field->type = new_type; ret = append(&field->type, "", brackets);
strcat(field->type, " ");
strcat(field->type, field->name);
size_dynamic = type_size(field->name); size_dynamic = type_size(field->name);
free_token(field->name); free_token(field->name);
strcat(field->type, brackets);
field->name = field->alias = token; field->name = field->alias = token;
type = read_token(&token); type = read_token(&token);
} else { } else {
char *new_type; ret = append(&field->type, "", brackets);
new_type = realloc(field->type, if (ret < 0) {
strlen(field->type) +
strlen(brackets) + 1);
if (!new_type) {
free(brackets); free(brackets);
goto fail; goto fail;
} }
field->type = new_type;
strcat(field->type, brackets);
} }
free(brackets); free(brackets);
} }
...@@ -2046,19 +2071,16 @@ process_op(struct tep_event *event, struct tep_print_arg *arg, char **tok) ...@@ -2046,19 +2071,16 @@ process_op(struct tep_event *event, struct tep_print_arg *arg, char **tok)
/* could just be a type pointer */ /* could just be a type pointer */
if ((strcmp(arg->op.op, "*") == 0) && if ((strcmp(arg->op.op, "*") == 0) &&
type == TEP_EVENT_DELIM && (strcmp(token, ")") == 0)) { type == TEP_EVENT_DELIM && (strcmp(token, ")") == 0)) {
char *new_atom; int ret;
if (left->type != TEP_PRINT_ATOM) { if (left->type != TEP_PRINT_ATOM) {
do_warning_event(event, "bad pointer type"); do_warning_event(event, "bad pointer type");
goto out_free; goto out_free;
} }
new_atom = realloc(left->atom.atom, ret = append(&left->atom.atom, " ", "*");
strlen(left->atom.atom) + 3); if (ret < 0)
if (!new_atom)
goto out_warn_free; goto out_warn_free;
left->atom.atom = new_atom;
strcat(left->atom.atom, " *");
free(arg->op.op); free(arg->op.op);
*arg = *left; *arg = *left;
free(left); free(left);
...@@ -3062,6 +3084,37 @@ process_func_handler(struct tep_event *event, struct tep_function_handler *func, ...@@ -3062,6 +3084,37 @@ process_func_handler(struct tep_event *event, struct tep_function_handler *func,
return TEP_EVENT_ERROR; return TEP_EVENT_ERROR;
} }
static enum tep_event_type
process_builtin_expect(struct tep_event *event, struct tep_print_arg *arg, char **tok)
{
enum tep_event_type type;
char *token = NULL;
/* Handle __builtin_expect( cond, #) */
type = process_arg(event, arg, &token);
if (type != TEP_EVENT_DELIM || token[0] != ',')
goto out_free;
free_token(token);
/* We don't care what the second parameter is of the __builtin_expect() */
if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
goto out_free;
if (read_expected(TEP_EVENT_DELIM, ")") < 0)
goto out_free;
free_token(token);
type = read_token_item(tok);
return type;
out_free:
free_token(token);
*tok = NULL;
return TEP_EVENT_ERROR;
}
static enum tep_event_type static enum tep_event_type
process_function(struct tep_event *event, struct tep_print_arg *arg, process_function(struct tep_event *event, struct tep_print_arg *arg,
char *token, char **tok) char *token, char **tok)
...@@ -3106,6 +3159,10 @@ process_function(struct tep_event *event, struct tep_print_arg *arg, ...@@ -3106,6 +3159,10 @@ process_function(struct tep_event *event, struct tep_print_arg *arg,
free_token(token); free_token(token);
return process_dynamic_array_len(event, arg, tok); return process_dynamic_array_len(event, arg, tok);
} }
if (strcmp(token, "__builtin_expect") == 0) {
free_token(token);
return process_builtin_expect(event, arg, tok);
}
func = find_func_handler(event->tep, token); func = find_func_handler(event->tep, token);
if (func) { if (func) {
...@@ -3151,18 +3208,15 @@ process_arg_token(struct tep_event *event, struct tep_print_arg *arg, ...@@ -3151,18 +3208,15 @@ process_arg_token(struct tep_event *event, struct tep_print_arg *arg,
} }
/* atoms can be more than one token long */ /* atoms can be more than one token long */
while (type == TEP_EVENT_ITEM) { while (type == TEP_EVENT_ITEM) {
char *new_atom; int ret;
new_atom = realloc(atom,
strlen(atom) + strlen(token) + 2); ret = append(&atom, " ", token);
if (!new_atom) { if (ret < 0) {
free(atom); free(atom);
*tok = NULL; *tok = NULL;
free_token(token); free_token(token);
return TEP_EVENT_ERROR; return TEP_EVENT_ERROR;
} }
atom = new_atom;
strcat(atom, " ");
strcat(atom, token);
free_token(token); free_token(token);
type = read_token_item(&token); type = read_token_item(&token);
} }
......
...@@ -396,6 +396,18 @@ else ...@@ -396,6 +396,18 @@ else
NO_LIBBPF := 1 NO_LIBBPF := 1
NO_JVMTI := 1 NO_JVMTI := 1
else else
ifneq ($(filter s% -fsanitize=address%,$(EXTRA_CFLAGS),),)
ifneq ($(shell ldconfig -p | grep libasan >/dev/null 2>&1; echo $$?), 0)
msg := $(error No libasan found, please install libasan);
endif
endif
ifneq ($(filter s% -fsanitize=undefined%,$(EXTRA_CFLAGS),),)
ifneq ($(shell ldconfig -p | grep libubsan >/dev/null 2>&1; echo $$?), 0)
msg := $(error No libubsan found, please install libubsan);
endif
endif
ifneq ($(filter s% -static%,$(LDFLAGS),),) ifneq ($(filter s% -static%,$(LDFLAGS),),)
msg := $(error No static glibc found, please install glibc-static); msg := $(error No static glibc found, please install glibc-static);
else else
......
...@@ -359,6 +359,7 @@ ...@@ -359,6 +359,7 @@
435 common clone3 sys_clone3 435 common clone3 sys_clone3
437 common openat2 sys_openat2 437 common openat2 sys_openat2
438 common pidfd_getfd sys_pidfd_getfd 438 common pidfd_getfd sys_pidfd_getfd
439 common faccessat2 sys_faccessat2
# #
# x32-specific system call numbers start at 512 to avoid cache impact # x32-specific system call numbers start at 512 to avoid cache impact
......
...@@ -478,8 +478,7 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report ...@@ -478,8 +478,7 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
if (rep->time_str) if (rep->time_str)
ret += fprintf(fp, " (time slices: %s)", rep->time_str); ret += fprintf(fp, " (time slices: %s)", rep->time_str);
if (symbol_conf.show_ref_callgraph && if (symbol_conf.show_ref_callgraph && evname && strstr(evname, "call-graph=no")) {
strstr(evname, "call-graph=no")) {
ret += fprintf(fp, ", show reference callgraph"); ret += fprintf(fp, ", show reference callgraph");
} }
......
...@@ -3837,6 +3837,9 @@ int cmd_script(int argc, const char **argv) ...@@ -3837,6 +3837,9 @@ int cmd_script(int argc, const char **argv)
if (err) if (err)
goto out_delete; goto out_delete;
if (zstd_init(&(session->zstd_data), 0) < 0)
pr_warning("Decompression initialization failed. Reported data may be incomplete.\n");
err = __cmd_script(&script); err = __cmd_script(&script);
flush_scripting(); flush_scripting();
......
...@@ -65,6 +65,7 @@ size_t syscall_arg__scnprintf_statx_mask(char *bf, size_t size, struct syscall_a ...@@ -65,6 +65,7 @@ size_t syscall_arg__scnprintf_statx_mask(char *bf, size_t size, struct syscall_a
P_FLAG(SIZE); P_FLAG(SIZE);
P_FLAG(BLOCKS); P_FLAG(BLOCKS);
P_FLAG(BTIME); P_FLAG(BTIME);
P_FLAG(MNT_ID);
#undef P_FLAG #undef P_FLAG
......
...@@ -142,7 +142,8 @@ static int ...@@ -142,7 +142,8 @@ static int
gen_read_mem(struct bpf_insn_pos *pos, gen_read_mem(struct bpf_insn_pos *pos,
int src_base_addr_reg, int src_base_addr_reg,
int dst_addr_reg, int dst_addr_reg,
long offset) long offset,
int probeid)
{ {
/* mov arg3, src_base_addr_reg */ /* mov arg3, src_base_addr_reg */
if (src_base_addr_reg != BPF_REG_ARG3) if (src_base_addr_reg != BPF_REG_ARG3)
...@@ -159,7 +160,7 @@ gen_read_mem(struct bpf_insn_pos *pos, ...@@ -159,7 +160,7 @@ gen_read_mem(struct bpf_insn_pos *pos,
ins(BPF_MOV64_REG(BPF_REG_ARG1, dst_addr_reg), pos); ins(BPF_MOV64_REG(BPF_REG_ARG1, dst_addr_reg), pos);
/* Call probe_read */ /* Call probe_read */
ins(BPF_EMIT_CALL(BPF_FUNC_probe_read), pos); ins(BPF_EMIT_CALL(probeid), pos);
/* /*
* Error processing: if read fail, goto error code, * Error processing: if read fail, goto error code,
* will be relocated. Target should be the start of * will be relocated. Target should be the start of
...@@ -241,7 +242,7 @@ static int ...@@ -241,7 +242,7 @@ static int
gen_prologue_slowpath(struct bpf_insn_pos *pos, gen_prologue_slowpath(struct bpf_insn_pos *pos,
struct probe_trace_arg *args, int nargs) struct probe_trace_arg *args, int nargs)
{ {
int err, i; int err, i, probeid;
for (i = 0; i < nargs; i++) { for (i = 0; i < nargs; i++) {
struct probe_trace_arg *arg = &args[i]; struct probe_trace_arg *arg = &args[i];
...@@ -276,11 +277,16 @@ gen_prologue_slowpath(struct bpf_insn_pos *pos, ...@@ -276,11 +277,16 @@ gen_prologue_slowpath(struct bpf_insn_pos *pos,
stack_offset), pos); stack_offset), pos);
ref = arg->ref; ref = arg->ref;
probeid = BPF_FUNC_probe_read_kernel;
while (ref) { while (ref) {
pr_debug("prologue: arg %d: offset %ld\n", pr_debug("prologue: arg %d: offset %ld\n",
i, ref->offset); i, ref->offset);
if (ref->user_access)
probeid = BPF_FUNC_probe_read_user;
err = gen_read_mem(pos, BPF_REG_3, BPF_REG_7, err = gen_read_mem(pos, BPF_REG_3, BPF_REG_7,
ref->offset); ref->offset, probeid);
if (err) { if (err) {
pr_err("prologue: failed to generate probe_read function call\n"); pr_err("prologue: failed to generate probe_read function call\n");
goto errout; goto errout;
......
...@@ -26,7 +26,7 @@ do { \ ...@@ -26,7 +26,7 @@ do { \
YYABORT; \ YYABORT; \
} while (0) } while (0)
static struct list_head* alloc_list() static struct list_head* alloc_list(void)
{ {
struct list_head *list; struct list_head *list;
...@@ -349,7 +349,7 @@ PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc ...@@ -349,7 +349,7 @@ PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc
struct list_head *list; struct list_head *list;
char pmu_name[128]; char pmu_name[128];
snprintf(&pmu_name, 128, "%s-%s", $1, $3); snprintf(pmu_name, sizeof(pmu_name), "%s-%s", $1, $3);
free($1); free($1);
free($3); free($3);
if (parse_events_multi_pmu_add(_parse_state, pmu_name, &list) < 0) if (parse_events_multi_pmu_add(_parse_state, pmu_name, &list) < 0)
......
...@@ -86,7 +86,6 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, ...@@ -86,7 +86,6 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
struct perf_pmu_info *info); struct perf_pmu_info *info);
struct list_head *perf_pmu__alias(struct perf_pmu *pmu, struct list_head *perf_pmu__alias(struct perf_pmu *pmu,
struct list_head *head_terms); struct list_head *head_terms);
int perf_pmu_wrap(void);
void perf_pmu_error(struct list_head *list, char *name, char const *msg); void perf_pmu_error(struct list_head *list, char *name, char const *msg);
int perf_pmu__new_format(struct list_head *list, char *name, int perf_pmu__new_format(struct list_head *list, char *name,
......
...@@ -1575,7 +1575,7 @@ static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg) ...@@ -1575,7 +1575,7 @@ static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
} }
tmp = strchr(str, '@'); tmp = strchr(str, '@');
if (tmp && tmp != str && strcmp(tmp + 1, "user")) { /* user attr */ if (tmp && tmp != str && !strcmp(tmp + 1, "user")) { /* user attr */
if (!user_access_is_supported()) { if (!user_access_is_supported()) {
semantic_error("ftrace does not support user access\n"); semantic_error("ftrace does not support user access\n");
return -EINVAL; return -EINVAL;
...@@ -1995,7 +1995,10 @@ static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref, ...@@ -1995,7 +1995,10 @@ static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref,
if (depth < 0) if (depth < 0)
return depth; return depth;
} }
err = strbuf_addf(buf, "%+ld(", ref->offset); if (ref->user_access)
err = strbuf_addf(buf, "%s%ld(", "+u", ref->offset);
else
err = strbuf_addf(buf, "%+ld(", ref->offset);
return (err < 0) ? err : depth; return (err < 0) ? err : depth;
} }
......
...@@ -1044,7 +1044,7 @@ static struct { ...@@ -1044,7 +1044,7 @@ static struct {
DEFINE_TYPE(FTRACE_README_PROBE_TYPE_X, "*type: * x8/16/32/64,*"), DEFINE_TYPE(FTRACE_README_PROBE_TYPE_X, "*type: * x8/16/32/64,*"),
DEFINE_TYPE(FTRACE_README_KRETPROBE_OFFSET, "*place (kretprobe): *"), DEFINE_TYPE(FTRACE_README_KRETPROBE_OFFSET, "*place (kretprobe): *"),
DEFINE_TYPE(FTRACE_README_UPROBE_REF_CTR, "*ref_ctr_offset*"), DEFINE_TYPE(FTRACE_README_UPROBE_REF_CTR, "*ref_ctr_offset*"),
DEFINE_TYPE(FTRACE_README_USER_ACCESS, "*[u]<offset>*"), DEFINE_TYPE(FTRACE_README_USER_ACCESS, "*u]<offset>*"),
DEFINE_TYPE(FTRACE_README_MULTIPROBE_EVENT, "*Create/append/*"), DEFINE_TYPE(FTRACE_README_MULTIPROBE_EVENT, "*Create/append/*"),
DEFINE_TYPE(FTRACE_README_IMMEDIATE_VALUE, "*\\imm-value,*"), DEFINE_TYPE(FTRACE_README_IMMEDIATE_VALUE, "*\\imm-value,*"),
}; };
......
...@@ -668,7 +668,7 @@ static void print_aggr(struct perf_stat_config *config, ...@@ -668,7 +668,7 @@ static void print_aggr(struct perf_stat_config *config,
int s; int s;
bool first; bool first;
if (!(config->aggr_map || config->aggr_get_id)) if (!config->aggr_map || !config->aggr_get_id)
return; return;
aggr_update_shadow(config, evlist); aggr_update_shadow(config, evlist);
...@@ -1169,7 +1169,7 @@ static void print_percore(struct perf_stat_config *config, ...@@ -1169,7 +1169,7 @@ static void print_percore(struct perf_stat_config *config,
int s; int s;
bool first = true; bool first = true;
if (!(config->aggr_map || config->aggr_get_id)) if (!config->aggr_map || !config->aggr_get_id)
return; return;
if (config->percore_show_thread) if (config->percore_show_thread)
......
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