Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf updates from Ingo Molnar:
 "The main updates in this cycle were:

   - Lots of perf tooling changes too voluminous to list (big perf trace
     and perf stat improvements, lots of libtraceevent reorganization,
     etc.), so I'll list the authors and refer to the changelog for
     details:

       Benjamin Peterson, Jérémie Galarneau, Kim Phillips, Peter
       Zijlstra, Ravi Bangoria, Sangwon Hong, Sean V Kelley, Steven
       Rostedt, Thomas Gleixner, Ding Xiang, Eduardo Habkost, Thomas
       Richter, Andi Kleen, Sanskriti Sharma, Adrian Hunter, Tzvetomir
       Stoyanov, Arnaldo Carvalho de Melo, Jiri Olsa.

     ... with the bulk of the changes written by Jiri Olsa, Tzvetomir
     Stoyanov and Arnaldo Carvalho de Melo.

   - Continued intel_rdt work with a focus on playing well with perf
     events. This also imported some non-perf RDT work due to
     dependencies. (Reinette Chatre)

   - Implement counter freezing for Arch Perfmon v4 (Skylake and newer).
     This allows to speed up the PMI handler by avoiding unnecessary MSR
     writes and make it more accurate. (Andi Kleen)

   - kprobes cleanups and simplification (Masami Hiramatsu)

   - Intel Goldmont PMU updates (Kan Liang)

   - ... plus misc other fixes and updates"

* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (155 commits)
  kprobes/x86: Use preempt_enable() in optimized_callback()
  x86/intel_rdt: Prevent pseudo-locking from using stale pointers
  kprobes, x86/ptrace.h: Make regs_get_kernel_stack_nth() not fault on bad stack
  perf/x86/intel: Export mem events only if there's PEBS support
  x86/cpu: Drop pointless static qualifier in punit_dev_state_show()
  x86/intel_rdt: Fix initial allocation to consider CDP
  x86/intel_rdt: CBM overlap should also check for overlap with CDP peer
  x86/intel_rdt: Introduce utility to obtain CDP peer
  tools lib traceevent, perf tools: Move struct tep_handler definition in a local header file
  tools lib traceevent: Separate out tep_strerror() for strerror_r() issues
  perf python: More portable way to make CFLAGS work with clang
  perf python: Make clang_has_option() work on Python 3
  perf tools: Free temporary 'sys' string in read_event_files()
  perf tools: Avoid double free in read_event_file()
  perf tools: Free 'printk' string in parse_ftrace_printk()
  perf tools: Cleanup trace-event-info 'tdata' leak
  perf strbuf: Match va_{add,copy} with va_end
  perf test: S390 does not support watchpoints in test 22
  perf auxtrace: Include missing asm/bitsperlong.h to get BITS_PER_LONG
  tools include: Adopt linux/bits.h
  ...
This commit is contained in:
Linus Torvalds
2018-10-23 13:32:18 +01:00
141 changed files with 6259 additions and 3868 deletions

View File

@@ -3,8 +3,6 @@
#define _TOOLS_LINUX_BITOPS_H_
#include <asm/types.h>
#include <linux/compiler.h>
#ifndef __WORDSIZE
#define __WORDSIZE (__SIZEOF_LONG__ * 8)
#endif
@@ -12,10 +10,9 @@
#ifndef BITS_PER_LONG
# define BITS_PER_LONG __WORDSIZE
#endif
#include <linux/bits.h>
#include <linux/compiler.h>
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
#define BITS_PER_BYTE 8
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
#define BITS_TO_U64(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64))
#define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32))

View File

@@ -0,0 +1,26 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LINUX_BITS_H
#define __LINUX_BITS_H
#include <asm/bitsperlong.h>
#define BIT(nr) (1UL << (nr))
#define BIT_ULL(nr) (1ULL << (nr))
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
#define BIT_ULL_MASK(nr) (1ULL << ((nr) % BITS_PER_LONG_LONG))
#define BIT_ULL_WORD(nr) ((nr) / BITS_PER_LONG_LONG)
#define BITS_PER_BYTE 8
/*
* Create a contiguous bitmask starting at bit position @l and ending at
* position @h. For example
* GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000.
*/
#define GENMASK(h, l) \
(((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h))))
#define GENMASK_ULL(h, l) \
(((~0ULL) - (1ULL << (l)) + 1) & \
(~0ULL >> (BITS_PER_LONG_LONG - 1 - (h))))
#endif /* __LINUX_BITS_H */

View File

@@ -52,4 +52,11 @@ static inline bool __must_check IS_ERR_OR_NULL(__force const void *ptr)
return unlikely(!ptr) || IS_ERR_VALUE((unsigned long)ptr);
}
static inline int __must_check PTR_ERR_OR_ZERO(__force const void *ptr)
{
if (IS_ERR(ptr))
return PTR_ERR(ptr);
else
return 0;
}
#endif /* _LINUX_ERR_H */

View File

@@ -23,6 +23,13 @@ void pager_init(const char *pager_env)
subcmd_config.pager_env = pager_env;
}
static const char *forced_pager;
void force_pager(const char *pager)
{
forced_pager = pager;
}
static void pager_preexec(void)
{
/*
@@ -66,7 +73,9 @@ void setup_pager(void)
const char *pager = getenv(subcmd_config.pager_env);
struct winsize sz;
if (!isatty(1))
if (forced_pager)
pager = forced_pager;
if (!isatty(1) && !forced_pager)
return;
if (ioctl(1, TIOCGWINSZ, &sz) == 0)
pager_columns = sz.ws_col;

View File

@@ -7,5 +7,6 @@ extern void pager_init(const char *pager_env);
extern void setup_pager(void);
extern int pager_in_use(void);
extern int pager_get_columns(void);
extern void force_pager(const char *);
#endif /* __SUBCMD_PAGER_H */

View File

@@ -4,6 +4,8 @@ libtraceevent-y += trace-seq.o
libtraceevent-y += parse-filter.o
libtraceevent-y += parse-utils.o
libtraceevent-y += kbuffer-parse.o
libtraceevent-y += tep_strerror.o
libtraceevent-y += event-parse-api.o
plugin_jbd2-y += plugin_jbd2.o
plugin_hrtimer-y += plugin_hrtimer.o

View File

@@ -0,0 +1,275 @@
// SPDX-License-Identifier: LGPL-2.1
/*
* Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
*
*/
#include "event-parse.h"
#include "event-parse-local.h"
#include "event-utils.h"
/**
* tep_get_first_event - returns the first event in the events array
* @tep: a handle to the tep_handle
*
* This returns pointer to the first element of the events array
* If @tep is NULL, NULL is returned.
*/
struct tep_event_format *tep_get_first_event(struct tep_handle *tep)
{
if (tep && tep->events)
return tep->events[0];
return NULL;
}
/**
* tep_get_events_count - get the number of defined events
* @tep: a handle to the tep_handle
*
* This returns number of elements in event array
* If @tep is NULL, 0 is returned.
*/
int tep_get_events_count(struct tep_handle *tep)
{
if(tep)
return tep->nr_events;
return 0;
}
/**
* tep_set_flag - set event parser flag
* @tep: a handle to the tep_handle
* @flag: flag, or combination of flags to be set
* can be any combination from enum tep_flag
*
* This sets a flag or mbination of flags from enum tep_flag
*/
void tep_set_flag(struct tep_handle *tep, int flag)
{
if(tep)
tep->flags |= flag;
}
unsigned short __tep_data2host2(struct tep_handle *pevent, unsigned short data)
{
unsigned short swap;
if (!pevent || pevent->host_bigendian == pevent->file_bigendian)
return data;
swap = ((data & 0xffULL) << 8) |
((data & (0xffULL << 8)) >> 8);
return swap;
}
unsigned int __tep_data2host4(struct tep_handle *pevent, unsigned int data)
{
unsigned int swap;
if (!pevent || pevent->host_bigendian == pevent->file_bigendian)
return data;
swap = ((data & 0xffULL) << 24) |
((data & (0xffULL << 8)) << 8) |
((data & (0xffULL << 16)) >> 8) |
((data & (0xffULL << 24)) >> 24);
return swap;
}
unsigned long long
__tep_data2host8(struct tep_handle *pevent, unsigned long long data)
{
unsigned long long swap;
if (!pevent || pevent->host_bigendian == pevent->file_bigendian)
return data;
swap = ((data & 0xffULL) << 56) |
((data & (0xffULL << 8)) << 40) |
((data & (0xffULL << 16)) << 24) |
((data & (0xffULL << 24)) << 8) |
((data & (0xffULL << 32)) >> 8) |
((data & (0xffULL << 40)) >> 24) |
((data & (0xffULL << 48)) >> 40) |
((data & (0xffULL << 56)) >> 56);
return swap;
}
/**
* tep_get_header_page_size - get size of the header page
* @pevent: a handle to the tep_handle
*
* This returns size of the header page
* If @pevent is NULL, 0 is returned.
*/
int tep_get_header_page_size(struct tep_handle *pevent)
{
if(pevent)
return pevent->header_page_size_size;
return 0;
}
/**
* tep_get_cpus - get the number of CPUs
* @pevent: a handle to the tep_handle
*
* This returns the number of CPUs
* If @pevent is NULL, 0 is returned.
*/
int tep_get_cpus(struct tep_handle *pevent)
{
if(pevent)
return pevent->cpus;
return 0;
}
/**
* tep_set_cpus - set the number of CPUs
* @pevent: a handle to the tep_handle
*
* This sets the number of CPUs
*/
void tep_set_cpus(struct tep_handle *pevent, int cpus)
{
if(pevent)
pevent->cpus = cpus;
}
/**
* tep_get_long_size - get the size of a long integer on the current machine
* @pevent: a handle to the tep_handle
*
* This returns the size of a long integer on the current machine
* If @pevent is NULL, 0 is returned.
*/
int tep_get_long_size(struct tep_handle *pevent)
{
if(pevent)
return pevent->long_size;
return 0;
}
/**
* tep_set_long_size - set the size of a long integer on the current machine
* @pevent: a handle to the tep_handle
* @size: size, in bytes, of a long integer
*
* This sets the size of a long integer on the current machine
*/
void tep_set_long_size(struct tep_handle *pevent, int long_size)
{
if(pevent)
pevent->long_size = long_size;
}
/**
* tep_get_page_size - get the size of a memory page on the current machine
* @pevent: a handle to the tep_handle
*
* This returns the size of a memory page on the current machine
* If @pevent is NULL, 0 is returned.
*/
int tep_get_page_size(struct tep_handle *pevent)
{
if(pevent)
return pevent->page_size;
return 0;
}
/**
* tep_set_page_size - set the size of a memory page on the current machine
* @pevent: a handle to the tep_handle
* @_page_size: size of a memory page, in bytes
*
* This sets the size of a memory page on the current machine
*/
void tep_set_page_size(struct tep_handle *pevent, int _page_size)
{
if(pevent)
pevent->page_size = _page_size;
}
/**
* tep_is_file_bigendian - get if the file is in big endian order
* @pevent: a handle to the tep_handle
*
* This returns if the file is in big endian order
* If @pevent is NULL, 0 is returned.
*/
int tep_is_file_bigendian(struct tep_handle *pevent)
{
if(pevent)
return pevent->file_bigendian;
return 0;
}
/**
* tep_set_file_bigendian - set if the file is in big endian order
* @pevent: a handle to the tep_handle
* @endian: non zero, if the file is in big endian order
*
* This sets if the file is in big endian order
*/
void tep_set_file_bigendian(struct tep_handle *pevent, enum tep_endian endian)
{
if(pevent)
pevent->file_bigendian = endian;
}
/**
* tep_is_host_bigendian - get if the order of the current host is big endian
* @pevent: a handle to the tep_handle
*
* This gets if the order of the current host is big endian
* If @pevent is NULL, 0 is returned.
*/
int tep_is_host_bigendian(struct tep_handle *pevent)
{
if(pevent)
return pevent->host_bigendian;
return 0;
}
/**
* tep_set_host_bigendian - set the order of the local host
* @pevent: a handle to the tep_handle
* @endian: non zero, if the local host has big endian order
*
* This sets the order of the local host
*/
void tep_set_host_bigendian(struct tep_handle *pevent, enum tep_endian endian)
{
if(pevent)
pevent->host_bigendian = endian;
}
/**
* tep_is_latency_format - get if the latency output format is configured
* @pevent: a handle to the tep_handle
*
* This gets if the latency output format is configured
* If @pevent is NULL, 0 is returned.
*/
int tep_is_latency_format(struct tep_handle *pevent)
{
if(pevent)
return pevent->latency_format;
return 0;
}
/**
* tep_set_latency_format - set the latency output format
* @pevent: a handle to the tep_handle
* @lat: non zero for latency output format
*
* This sets the latency output format
*/
void tep_set_latency_format(struct tep_handle *pevent, int lat)
{
if(pevent)
pevent->latency_format = lat;
}

View File

@@ -0,0 +1,92 @@
// SPDX-License-Identifier: LGPL-2.1
/*
* Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
*
*/
#ifndef _PARSE_EVENTS_INT_H
#define _PARSE_EVENTS_INT_H
struct cmdline;
struct cmdline_list;
struct func_map;
struct func_list;
struct event_handler;
struct func_resolver;
struct tep_handle {
int ref_count;
int header_page_ts_offset;
int header_page_ts_size;
int header_page_size_offset;
int header_page_size_size;
int header_page_data_offset;
int header_page_data_size;
int header_page_overwrite;
enum tep_endian file_bigendian;
enum tep_endian host_bigendian;
int latency_format;
int old_format;
int cpus;
int long_size;
int page_size;
struct cmdline *cmdlines;
struct cmdline_list *cmdlist;
int cmdline_count;
struct func_map *func_map;
struct func_resolver *func_resolver;
struct func_list *funclist;
unsigned int func_count;
struct printk_map *printk_map;
struct printk_list *printklist;
unsigned int printk_count;
struct tep_event_format **events;
int nr_events;
struct tep_event_format **sort_events;
enum tep_event_sort_type last_type;
int type_offset;
int type_size;
int pid_offset;
int pid_size;
int pc_offset;
int pc_size;
int flags_offset;
int flags_size;
int ld_offset;
int ld_size;
int print_raw;
int test_filters;
int flags;
struct tep_format_field *bprint_ip_field;
struct tep_format_field *bprint_fmt_field;
struct tep_format_field *bprint_buf_field;
struct event_handler *handlers;
struct tep_function_handler *func_handlers;
/* cache */
struct tep_event_format *last_event;
char *trace_clock;
};
#endif /* _PARSE_EVENTS_INT_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -14,7 +14,9 @@
#include <unistd.h>
#include <dirent.h>
#include "event-parse.h"
#include "event-parse-local.h"
#include "event-utils.h"
#include "trace-seq.h"
#define LOCAL_PLUGIN_DIR ".traceevent/plugins"
@@ -30,8 +32,8 @@ static struct trace_plugin_options {
char *value;
} *trace_plugin_options;
struct plugin_list {
struct plugin_list *next;
struct tep_plugin_list {
struct tep_plugin_list *next;
char *name;
void *handle;
};
@@ -258,7 +260,7 @@ void tep_plugin_remove_options(struct tep_plugin_option *options)
*/
void tep_print_plugins(struct trace_seq *s,
const char *prefix, const char *suffix,
const struct plugin_list *list)
const struct tep_plugin_list *list)
{
while (list) {
trace_seq_printf(s, "%s%s%s", prefix, list->name, suffix);
@@ -270,9 +272,9 @@ static void
load_plugin(struct tep_handle *pevent, const char *path,
const char *file, void *data)
{
struct plugin_list **plugin_list = data;
struct tep_plugin_list **plugin_list = data;
tep_plugin_load_func func;
struct plugin_list *list;
struct tep_plugin_list *list;
const char *alias;
char *plugin;
void *handle;
@@ -416,20 +418,20 @@ load_plugins(struct tep_handle *pevent, const char *suffix,
free(path);
}
struct plugin_list*
struct tep_plugin_list*
tep_load_plugins(struct tep_handle *pevent)
{
struct plugin_list *list = NULL;
struct tep_plugin_list *list = NULL;
load_plugins(pevent, ".so", load_plugin, &list);
return list;
}
void
tep_unload_plugins(struct plugin_list *plugin_list, struct tep_handle *pevent)
tep_unload_plugins(struct tep_plugin_list *plugin_list, struct tep_handle *pevent)
{
tep_plugin_unload_func func;
struct plugin_list *list;
struct tep_plugin_list *list;
while (plugin_list) {
list = plugin_list;

File diff suppressed because it is too large Load Diff

View File

@@ -23,6 +23,7 @@
#include "event-parse.h"
#include "event-utils.h"
#include "trace-seq.h"
static struct func_stack {
int size;
@@ -123,7 +124,7 @@ static int add_and_get_index(const char *parent, const char *child, int cpu)
}
static int function_handler(struct trace_seq *s, struct tep_record *record,
struct event_format *event, void *context)
struct tep_event_format *event, void *context)
{
struct tep_handle *pevent = event->pevent;
unsigned long long function;

View File

@@ -23,10 +23,11 @@
#include <string.h>
#include "event-parse.h"
#include "trace-seq.h"
static int timer_expire_handler(struct trace_seq *s,
struct tep_record *record,
struct event_format *event, void *context)
struct tep_event_format *event, void *context)
{
trace_seq_printf(s, "hrtimer=");
@@ -46,7 +47,7 @@ static int timer_expire_handler(struct trace_seq *s,
static int timer_start_handler(struct trace_seq *s,
struct tep_record *record,
struct event_format *event, void *context)
struct tep_event_format *event, void *context)
{
trace_seq_printf(s, "hrtimer=");

View File

@@ -22,6 +22,7 @@
#include <string.h>
#include "event-parse.h"
#include "trace-seq.h"
#define MINORBITS 20
#define MINORMASK ((1U << MINORBITS) - 1)

View File

@@ -22,11 +22,12 @@
#include <string.h>
#include "event-parse.h"
#include "trace-seq.h"
static int call_site_handler(struct trace_seq *s, struct tep_record *record,
struct event_format *event, void *context)
struct tep_event_format *event, void *context)
{
struct format_field *field;
struct tep_format_field *field;
unsigned long long val, addr;
void *data = record->data;
const char *func;

View File

@@ -23,6 +23,7 @@
#include <stdint.h>
#include "event-parse.h"
#include "trace-seq.h"
#ifdef HAVE_UDIS86
@@ -248,7 +249,7 @@ static const char *find_exit_reason(unsigned isa, int val)
}
static int print_exit_reason(struct trace_seq *s, struct tep_record *record,
struct event_format *event, const char *field)
struct tep_event_format *event, const char *field)
{
unsigned long long isa;
unsigned long long val;
@@ -269,7 +270,7 @@ static int print_exit_reason(struct trace_seq *s, struct tep_record *record,
}
static int kvm_exit_handler(struct trace_seq *s, struct tep_record *record,
struct event_format *event, void *context)
struct tep_event_format *event, void *context)
{
unsigned long long info1 = 0, info2 = 0;
@@ -292,7 +293,7 @@ static int kvm_exit_handler(struct trace_seq *s, struct tep_record *record,
static int kvm_emulate_insn_handler(struct trace_seq *s,
struct tep_record *record,
struct event_format *event, void *context)
struct tep_event_format *event, void *context)
{
unsigned long long rip, csbase, len, flags, failed;
int llen;
@@ -331,7 +332,7 @@ static int kvm_emulate_insn_handler(struct trace_seq *s,
static int kvm_nested_vmexit_inject_handler(struct trace_seq *s, struct tep_record *record,
struct event_format *event, void *context)
struct tep_event_format *event, void *context)
{
if (print_exit_reason(s, record, event, "exit_code") < 0)
return -1;
@@ -345,7 +346,7 @@ static int kvm_nested_vmexit_inject_handler(struct trace_seq *s, struct tep_reco
}
static int kvm_nested_vmexit_handler(struct trace_seq *s, struct tep_record *record,
struct event_format *event, void *context)
struct tep_event_format *event, void *context)
{
tep_print_num_field(s, "rip %llx ", event, "rip", record, 1);
@@ -371,7 +372,7 @@ union kvm_mmu_page_role {
};
static int kvm_mmu_print_role(struct trace_seq *s, struct tep_record *record,
struct event_format *event, void *context)
struct tep_event_format *event, void *context)
{
unsigned long long val;
static const char *access_str[] = {
@@ -418,7 +419,7 @@ static int kvm_mmu_print_role(struct trace_seq *s, struct tep_record *record,
static int kvm_mmu_get_page_handler(struct trace_seq *s,
struct tep_record *record,
struct event_format *event, void *context)
struct tep_event_format *event, void *context)
{
unsigned long long val;

View File

@@ -22,13 +22,14 @@
#include <string.h>
#include "event-parse.h"
#include "trace-seq.h"
#define INDENT 65
static void print_string(struct trace_seq *s, struct event_format *event,
static void print_string(struct trace_seq *s, struct tep_event_format *event,
const char *name, const void *data)
{
struct format_field *f = tep_find_field(event, name);
struct tep_format_field *f = tep_find_field(event, name);
int offset;
int length;
@@ -59,7 +60,7 @@ static void print_string(struct trace_seq *s, struct event_format *event,
static int drv_bss_info_changed(struct trace_seq *s,
struct tep_record *record,
struct event_format *event, void *context)
struct tep_event_format *event, void *context)
{
void *data = record->data;

View File

@@ -22,6 +22,7 @@
#include <string.h>
#include "event-parse.h"
#include "trace-seq.h"
static void write_state(struct trace_seq *s, int val)
{
@@ -44,7 +45,7 @@ static void write_state(struct trace_seq *s, int val)
trace_seq_putc(s, 'R');
}
static void write_and_save_comm(struct format_field *field,
static void write_and_save_comm(struct tep_format_field *field,
struct tep_record *record,
struct trace_seq *s, int pid)
{
@@ -66,9 +67,9 @@ static void write_and_save_comm(struct format_field *field,
static int sched_wakeup_handler(struct trace_seq *s,
struct tep_record *record,
struct event_format *event, void *context)
struct tep_event_format *event, void *context)
{
struct format_field *field;
struct tep_format_field *field;
unsigned long long val;
if (tep_get_field_val(s, event, "pid", record, &val, 1))
@@ -95,9 +96,9 @@ static int sched_wakeup_handler(struct trace_seq *s,
static int sched_switch_handler(struct trace_seq *s,
struct tep_record *record,
struct event_format *event, void *context)
struct tep_event_format *event, void *context)
{
struct format_field *field;
struct tep_format_field *field;
unsigned long long val;
if (tep_get_field_val(s, event, "prev_pid", record, &val, 1))

View File

@@ -3,6 +3,7 @@
#include <string.h>
#include <inttypes.h>
#include "event-parse.h"
#include "trace-seq.h"
typedef unsigned long sector_t;
typedef uint64_t u64;

View File

@@ -3,6 +3,7 @@
#include <stdlib.h>
#include <string.h>
#include "event-parse.h"
#include "trace-seq.h"
#define __HYPERVISOR_set_trap_table 0
#define __HYPERVISOR_mmu_update 1

View File

@@ -0,0 +1,53 @@
// SPDX-License-Identifier: LGPL-2.1
#undef _GNU_SOURCE
#include <string.h>
#include <stdio.h>
#include "event-parse.h"
#undef _PE
#define _PE(code, str) str
static const char * const tep_error_str[] = {
TEP_ERRORS
};
#undef _PE
/*
* The tools so far have been using the strerror_r() GNU variant, that returns
* a string, be it the buffer passed or something else.
*
* But that, besides being tricky in cases where we expect that the function
* using strerror_r() returns the error formatted in a provided buffer (we have
* to check if it returned something else and copy that instead), breaks the
* build on systems not using glibc, like Alpine Linux, where musl libc is
* used.
*
* So, introduce yet another wrapper, str_error_r(), that has the GNU
* interface, but uses the portable XSI variant of strerror_r(), so that users
* rest asured that the provided buffer is used and it is what is returned.
*/
int tep_strerror(struct tep_handle *tep __maybe_unused,
enum tep_errno errnum, char *buf, size_t buflen)
{
const char *msg;
int idx;
if (!buflen)
return 0;
if (errnum >= 0) {
int err = strerror_r(errnum, buf, buflen);
buf[buflen - 1] = 0;
return err;
}
if (errnum <= __TEP_ERRNO__START ||
errnum >= __TEP_ERRNO__END)
return -1;
idx = errnum - __TEP_ERRNO__START - 1;
msg = tep_error_str[idx];
snprintf(buf, buflen, "%s", msg);
return 0;
}

View File

@@ -3,6 +3,8 @@
* Copyright (C) 2009 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
*
*/
#include "trace-seq.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

View File

@@ -0,0 +1,55 @@
// SPDX-License-Identifier: LGPL-2.1
/*
* Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
*
*/
#ifndef _TRACE_SEQ_H
#define _TRACE_SEQ_H
#include <stdarg.h>
#include <stdio.h>
/* ----------------------- trace_seq ----------------------- */
#ifndef TRACE_SEQ_BUF_SIZE
#define TRACE_SEQ_BUF_SIZE 4096
#endif
enum trace_seq_fail {
TRACE_SEQ__GOOD,
TRACE_SEQ__BUFFER_POISONED,
TRACE_SEQ__MEM_ALLOC_FAILED,
};
/*
* Trace sequences are used to allow a function to call several other functions
* to create a string of data to use (up to a max of PAGE_SIZE).
*/
struct trace_seq {
char *buffer;
unsigned int buffer_size;
unsigned int len;
unsigned int readpos;
enum trace_seq_fail state;
};
void trace_seq_init(struct trace_seq *s);
void trace_seq_reset(struct trace_seq *s);
void trace_seq_destroy(struct trace_seq *s);
extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3)));
extern int trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
__attribute__ ((format (printf, 2, 0)));
extern int trace_seq_puts(struct trace_seq *s, const char *str);
extern int trace_seq_putc(struct trace_seq *s, unsigned char c);
extern void trace_seq_terminate(struct trace_seq *s);
extern int trace_seq_do_fprintf(struct trace_seq *s, FILE *fp);
extern int trace_seq_do_printf(struct trace_seq *s);
#endif /* _TRACE_SEQ_H */

View File

@@ -779,7 +779,9 @@ endif
ifndef NO_LIBBPF
$(call QUIET_INSTALL, bpf-headers) \
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf'; \
$(INSTALL) include/bpf/*.h -t '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf'
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf/linux'; \
$(INSTALL) include/bpf/*.h -t '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf'; \
$(INSTALL) include/bpf/linux/*.h -t '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf/linux'
$(call QUIET_INSTALL, bpf-examples) \
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_examples_instdir_SQ)/bpf'; \
$(INSTALL) examples/bpf/*.c -t '$(DESTDIR_SQ)$(perf_examples_instdir_SQ)/bpf'

View File

@@ -8,6 +8,63 @@ struct arm64_annotate {
jump_insn;
};
static int arm64_mov__parse(struct arch *arch __maybe_unused,
struct ins_operands *ops,
struct map_symbol *ms __maybe_unused)
{
char *s = strchr(ops->raw, ','), *target, *endptr;
if (s == NULL)
return -1;
*s = '\0';
ops->source.raw = strdup(ops->raw);
*s = ',';
if (ops->source.raw == NULL)
return -1;
target = ++s;
ops->target.raw = strdup(target);
if (ops->target.raw == NULL)
goto out_free_source;
ops->target.addr = strtoull(target, &endptr, 16);
if (endptr == target)
goto out_free_target;
s = strchr(endptr, '<');
if (s == NULL)
goto out_free_target;
endptr = strchr(s + 1, '>');
if (endptr == NULL)
goto out_free_target;
*endptr = '\0';
*s = ' ';
ops->target.name = strdup(s);
*s = '<';
*endptr = '>';
if (ops->target.name == NULL)
goto out_free_target;
return 0;
out_free_target:
zfree(&ops->target.raw);
out_free_source:
zfree(&ops->source.raw);
return -1;
}
static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
struct ins_operands *ops);
static struct ins_ops arm64_mov_ops = {
.parse = arm64_mov__parse,
.scnprintf = mov__scnprintf,
};
static struct ins_ops *arm64__associate_instruction_ops(struct arch *arch, const char *name)
{
struct arm64_annotate *arm = arch->priv;
@@ -21,7 +78,7 @@ static struct ins_ops *arm64__associate_instruction_ops(struct arch *arch, const
else if (!strcmp(name, "ret"))
ops = &ret_ops;
else
return NULL;
ops = &arm64_mov_ops;
arch__associate_ins_ops(arch, name, ops);
return ops;

View File

@@ -100,8 +100,6 @@ out_free_source:
return -1;
}
static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
struct ins_operands *ops);
static struct ins_ops s390_mov_ops = {
.parse = s390_mov__parse,

View File

@@ -283,12 +283,11 @@ out_put:
return ret;
}
static int process_feature_event(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session)
static int process_feature_event(struct perf_session *session,
union perf_event *event)
{
if (event->feat.feat_id < HEADER_LAST_FEATURE)
return perf_event__process_feature(tool, event, session);
return perf_event__process_feature(session, event);
return 0;
}

View File

@@ -86,12 +86,10 @@ static int perf_event__drop_oe(struct perf_tool *tool __maybe_unused,
}
#endif
static int perf_event__repipe_op2_synth(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session
__maybe_unused)
static int perf_event__repipe_op2_synth(struct perf_session *session,
union perf_event *event)
{
return perf_event__repipe_synth(tool, event);
return perf_event__repipe_synth(session->tool, event);
}
static int perf_event__repipe_attr(struct perf_tool *tool,
@@ -133,10 +131,10 @@ static int copy_bytes(struct perf_inject *inject, int fd, off_t size)
return 0;
}
static s64 perf_event__repipe_auxtrace(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session)
static s64 perf_event__repipe_auxtrace(struct perf_session *session,
union perf_event *event)
{
struct perf_tool *tool = session->tool;
struct perf_inject *inject = container_of(tool, struct perf_inject,
tool);
int ret;
@@ -174,9 +172,8 @@ static s64 perf_event__repipe_auxtrace(struct perf_tool *tool,
#else
static s64
perf_event__repipe_auxtrace(struct perf_tool *tool __maybe_unused,
union perf_event *event __maybe_unused,
struct perf_session *session __maybe_unused)
perf_event__repipe_auxtrace(struct perf_session *session __maybe_unused,
union perf_event *event __maybe_unused)
{
pr_err("AUX area tracing not supported\n");
return -EINVAL;
@@ -362,26 +359,24 @@ static int perf_event__repipe_exit(struct perf_tool *tool,
return err;
}
static int perf_event__repipe_tracing_data(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session)
static int perf_event__repipe_tracing_data(struct perf_session *session,
union perf_event *event)
{
int err;
perf_event__repipe_synth(tool, event);
err = perf_event__process_tracing_data(tool, event, session);
perf_event__repipe_synth(session->tool, event);
err = perf_event__process_tracing_data(session, event);
return err;
}
static int perf_event__repipe_id_index(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session)
static int perf_event__repipe_id_index(struct perf_session *session,
union perf_event *event)
{
int err;
perf_event__repipe_synth(tool, event);
err = perf_event__process_id_index(tool, event, session);
perf_event__repipe_synth(session->tool, event);
err = perf_event__process_id_index(session, event);
return err;
}
@@ -803,7 +798,8 @@ int cmd_inject(int argc, const char **argv)
"kallsyms pathname"),
OPT_BOOLEAN('f', "force", &data.force, "don't complain, do it"),
OPT_CALLBACK_OPTARG(0, "itrace", &inject.itrace_synth_opts,
NULL, "opts", "Instruction Tracing options",
NULL, "opts", "Instruction Tracing options\n"
ITRACE_HELP,
itrace_parse_synth_opts),
OPT_BOOLEAN(0, "strip", &inject.strip,
"strip non-synthesized events (use with --itrace)"),

View File

@@ -106,9 +106,12 @@ static bool switch_output_time(struct record *rec)
trigger_is_ready(&switch_output_trigger);
}
static int record__write(struct record *rec, void *bf, size_t size)
static int record__write(struct record *rec, struct perf_mmap *map __maybe_unused,
void *bf, size_t size)
{
if (perf_data__write(rec->session->data, bf, size) < 0) {
struct perf_data_file *file = &rec->session->data->file;
if (perf_data_file__write(file, bf, size) < 0) {
pr_err("failed to write perf data, error: %m\n");
return -1;
}
@@ -127,15 +130,15 @@ static int process_synthesized_event(struct perf_tool *tool,
struct machine *machine __maybe_unused)
{
struct record *rec = container_of(tool, struct record, tool);
return record__write(rec, event, event->header.size);
return record__write(rec, NULL, event, event->header.size);
}
static int record__pushfn(void *to, void *bf, size_t size)
static int record__pushfn(struct perf_mmap *map, void *to, void *bf, size_t size)
{
struct record *rec = to;
rec->samples++;
return record__write(rec, bf, size);
return record__write(rec, map, bf, size);
}
static volatile int done;
@@ -170,6 +173,7 @@ static void record__sig_exit(void)
#ifdef HAVE_AUXTRACE_SUPPORT
static int record__process_auxtrace(struct perf_tool *tool,
struct perf_mmap *map,
union perf_event *event, void *data1,
size_t len1, void *data2, size_t len2)
{
@@ -197,21 +201,21 @@ static int record__process_auxtrace(struct perf_tool *tool,
if (padding)
padding = 8 - padding;
record__write(rec, event, event->header.size);
record__write(rec, data1, len1);
record__write(rec, map, event, event->header.size);
record__write(rec, map, data1, len1);
if (len2)
record__write(rec, data2, len2);
record__write(rec, &pad, padding);
record__write(rec, map, data2, len2);
record__write(rec, map, &pad, padding);
return 0;
}
static int record__auxtrace_mmap_read(struct record *rec,
struct auxtrace_mmap *mm)
struct perf_mmap *map)
{
int ret;
ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool,
ret = auxtrace_mmap__read(map, rec->itr, &rec->tool,
record__process_auxtrace);
if (ret < 0)
return ret;
@@ -223,11 +227,11 @@ static int record__auxtrace_mmap_read(struct record *rec,
}
static int record__auxtrace_mmap_read_snapshot(struct record *rec,
struct auxtrace_mmap *mm)
struct perf_mmap *map)
{
int ret;
ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool,
ret = auxtrace_mmap__read_snapshot(map, rec->itr, &rec->tool,
record__process_auxtrace,
rec->opts.auxtrace_snapshot_size);
if (ret < 0)
@@ -245,13 +249,12 @@ static int record__auxtrace_read_snapshot_all(struct record *rec)
int rc = 0;
for (i = 0; i < rec->evlist->nr_mmaps; i++) {
struct auxtrace_mmap *mm =
&rec->evlist->mmap[i].auxtrace_mmap;
struct perf_mmap *map = &rec->evlist->mmap[i];
if (!mm->base)
if (!map->auxtrace_mmap.base)
continue;
if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) {
if (record__auxtrace_mmap_read_snapshot(rec, map) != 0) {
rc = -1;
goto out;
}
@@ -295,7 +298,7 @@ static int record__auxtrace_init(struct record *rec)
static inline
int record__auxtrace_mmap_read(struct record *rec __maybe_unused,
struct auxtrace_mmap *mm __maybe_unused)
struct perf_mmap *map __maybe_unused)
{
return 0;
}
@@ -529,17 +532,17 @@ static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evli
return 0;
for (i = 0; i < evlist->nr_mmaps; i++) {
struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap;
struct perf_mmap *map = &maps[i];
if (maps[i].base) {
if (perf_mmap__push(&maps[i], rec, record__pushfn) != 0) {
if (map->base) {
if (perf_mmap__push(map, rec, record__pushfn) != 0) {
rc = -1;
goto out;
}
}
if (mm->base && !rec->opts.auxtrace_snapshot_mode &&
record__auxtrace_mmap_read(rec, mm) != 0) {
if (map->auxtrace_mmap.base && !rec->opts.auxtrace_snapshot_mode &&
record__auxtrace_mmap_read(rec, map) != 0) {
rc = -1;
goto out;
}
@@ -550,7 +553,7 @@ static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evli
* at least one event.
*/
if (bytes_written != rec->bytes_written)
rc = record__write(rec, &finished_round_event, sizeof(finished_round_event));
rc = record__write(rec, NULL, &finished_round_event, sizeof(finished_round_event));
if (overwrite)
perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY);
@@ -758,7 +761,7 @@ static int record__synthesize(struct record *rec, bool tail)
* We need to synthesize events first, because some
* features works on top of them (on report side).
*/
err = perf_event__synthesize_attrs(tool, session,
err = perf_event__synthesize_attrs(tool, rec->evlist,
process_synthesized_event);
if (err < 0) {
pr_err("Couldn't synthesize attrs.\n");

View File

@@ -201,14 +201,13 @@ static void setup_forced_leader(struct report *report,
perf_evlist__force_leader(evlist);
}
static int process_feature_event(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session __maybe_unused)
static int process_feature_event(struct perf_session *session,
union perf_event *event)
{
struct report *rep = container_of(tool, struct report, tool);
struct report *rep = container_of(session->tool, struct report, tool);
if (event->feat.feat_id < HEADER_LAST_FEATURE)
return perf_event__process_feature(tool, event, session);
return perf_event__process_feature(session, event);
if (event->feat.feat_id != HEADER_LAST_FEATURE) {
pr_err("failed: wrong feature ID: %" PRIu64 "\n",
@@ -1106,7 +1105,7 @@ int cmd_report(int argc, const char **argv)
OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
"how to display percentage of filtered entries", parse_filter_percentage),
OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
"Instruction Tracing options",
"Instruction Tracing options\n" ITRACE_HELP,
itrace_parse_synth_opts),
OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename,
"Show full source file name path for source lines"),

View File

@@ -406,9 +406,10 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
PERF_OUTPUT_WEIGHT))
return -EINVAL;
if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
if (PRINT_FIELD(SYM) &&
!(evsel->attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) {
pr_err("Display of symbols requested but neither sample IP nor "
"sample address\nis selected. Hence, no addresses to convert "
"sample address\navailable. Hence, no addresses to convert "
"to symbols.\n");
return -EINVAL;
}
@@ -417,10 +418,9 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
"selected.\n");
return -EINVAL;
}
if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR) &&
!PRINT_FIELD(BRSTACK) && !PRINT_FIELD(BRSTACKSYM) && !PRINT_FIELD(BRSTACKOFF)) {
pr_err("Display of DSO requested but no address to convert. Select\n"
"sample IP, sample address, brstack, brstacksym, or brstackoff.\n");
if (PRINT_FIELD(DSO) &&
!(evsel->attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) {
pr_err("Display of DSO requested but no address to convert.\n");
return -EINVAL;
}
if (PRINT_FIELD(SRCLINE) && !PRINT_FIELD(IP)) {
@@ -1115,6 +1115,7 @@ static int perf_sample__fprintf_callindent(struct perf_sample *sample,
const char *name = NULL;
static int spacing;
int len = 0;
int dlen = 0;
u64 ip = 0;
/*
@@ -1141,6 +1142,12 @@ static int perf_sample__fprintf_callindent(struct perf_sample *sample,
ip = sample->ip;
}
if (PRINT_FIELD(DSO) && !(PRINT_FIELD(IP) || PRINT_FIELD(ADDR))) {
dlen += fprintf(fp, "(");
dlen += map__fprintf_dsoname(al->map, fp);
dlen += fprintf(fp, ")\t");
}
if (name)
len = fprintf(fp, "%*s%s", (int)depth * 4, "", name);
else if (ip)
@@ -1159,7 +1166,7 @@ static int perf_sample__fprintf_callindent(struct perf_sample *sample,
if (len < spacing)
len += fprintf(fp, "%*s", spacing - len, "");
return len;
return len + dlen;
}
static int perf_sample__fprintf_insn(struct perf_sample *sample,
@@ -1255,6 +1262,18 @@ static struct {
{0, NULL}
};
static const char *sample_flags_to_name(u32 flags)
{
int i;
for (i = 0; sample_flags[i].name ; i++) {
if (sample_flags[i].flags == flags)
return sample_flags[i].name;
}
return NULL;
}
static int perf_sample__fprintf_flags(u32 flags, FILE *fp)
{
const char *chars = PERF_IP_FLAG_CHARS;
@@ -1264,11 +1283,20 @@ static int perf_sample__fprintf_flags(u32 flags, FILE *fp)
char str[33];
int i, pos = 0;
for (i = 0; sample_flags[i].name ; i++) {
if (sample_flags[i].flags == (flags & ~PERF_IP_FLAG_IN_TX)) {
name = sample_flags[i].name;
break;
}
name = sample_flags_to_name(flags & ~PERF_IP_FLAG_IN_TX);
if (name)
return fprintf(fp, " %-15s%4s ", name, in_tx ? "(x)" : "");
if (flags & PERF_IP_FLAG_TRACE_BEGIN) {
name = sample_flags_to_name(flags & ~(PERF_IP_FLAG_IN_TX | PERF_IP_FLAG_TRACE_BEGIN));
if (name)
return fprintf(fp, " tr strt %-7s%4s ", name, in_tx ? "(x)" : "");
}
if (flags & PERF_IP_FLAG_TRACE_END) {
name = sample_flags_to_name(flags & ~(PERF_IP_FLAG_IN_TX | PERF_IP_FLAG_TRACE_END));
if (name)
return fprintf(fp, " tr end %-7s%4s ", name, in_tx ? "(x)" : "");
}
for (i = 0; i < n; i++, flags >>= 1) {
@@ -1281,10 +1309,7 @@ static int perf_sample__fprintf_flags(u32 flags, FILE *fp)
}
str[pos] = 0;
if (name)
return fprintf(fp, " %-7s%4s ", name, in_tx ? "(x)" : "");
return fprintf(fp, " %-11s ", str);
return fprintf(fp, " %-19s ", str);
}
struct printer_data {
@@ -1544,7 +1569,8 @@ struct metric_ctx {
FILE *fp;
};
static void script_print_metric(void *ctx, const char *color,
static void script_print_metric(struct perf_stat_config *config __maybe_unused,
void *ctx, const char *color,
const char *fmt,
const char *unit, double val)
{
@@ -1562,7 +1588,8 @@ static void script_print_metric(void *ctx, const char *color,
fprintf(mctx->fp, " %s\n", unit);
}
static void script_new_line(void *ctx)
static void script_new_line(struct perf_stat_config *config __maybe_unused,
void *ctx)
{
struct metric_ctx *mctx = ctx;
@@ -1608,7 +1635,7 @@ static void perf_sample__fprint_metric(struct perf_script *script,
evsel_script(evsel)->val = val;
if (evsel_script(evsel->leader)->gnum == evsel->leader->nr_members) {
for_each_group_member (ev2, evsel->leader) {
perf_stat__print_shadow_stats(ev2,
perf_stat__print_shadow_stats(&stat_config, ev2,
evsel_script(ev2)->val,
sample->cpu,
&ctx,
@@ -2489,6 +2516,8 @@ parse:
output[j].fields &= ~all_output_options[i].field;
else
output[j].fields |= all_output_options[i].field;
output[j].user_set = true;
output[j].wildcard_set = true;
}
}
} else {
@@ -2499,7 +2528,8 @@ parse:
rc = -EINVAL;
goto out;
}
output[type].fields |= all_output_options[i].field;
output[type].user_set = true;
output[type].wildcard_set = true;
}
}
@@ -2963,9 +2993,8 @@ static void script__setup_sample_type(struct perf_script *script)
}
}
static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_session *session)
static int process_stat_round_event(struct perf_session *session,
union perf_event *event)
{
struct stat_round_event *round = &event->stat_round;
struct perf_evsel *counter;
@@ -2979,9 +3008,8 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
return 0;
}
static int process_stat_config_event(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_session *session __maybe_unused)
static int process_stat_config_event(struct perf_session *session __maybe_unused,
union perf_event *event)
{
perf_event__read_stat_config(&stat_config, &event->stat_config);
return 0;
@@ -3007,10 +3035,10 @@ static int set_maps(struct perf_script *script)
}
static
int process_thread_map_event(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session __maybe_unused)
int process_thread_map_event(struct perf_session *session,
union perf_event *event)
{
struct perf_tool *tool = session->tool;
struct perf_script *script = container_of(tool, struct perf_script, tool);
if (script->threads) {
@@ -3026,10 +3054,10 @@ int process_thread_map_event(struct perf_tool *tool,
}
static
int process_cpu_map_event(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_session *session __maybe_unused)
int process_cpu_map_event(struct perf_session *session,
union perf_event *event)
{
struct perf_tool *tool = session->tool;
struct perf_script *script = container_of(tool, struct perf_script, tool);
if (script->cpus) {
@@ -3044,21 +3072,21 @@ int process_cpu_map_event(struct perf_tool *tool __maybe_unused,
return set_maps(script);
}
static int process_feature_event(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session)
static int process_feature_event(struct perf_session *session,
union perf_event *event)
{
if (event->feat.feat_id < HEADER_LAST_FEATURE)
return perf_event__process_feature(tool, event, session);
return perf_event__process_feature(session, event);
return 0;
}
#ifdef HAVE_AUXTRACE_SUPPORT
static int perf_script__process_auxtrace_info(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session)
static int perf_script__process_auxtrace_info(struct perf_session *session,
union perf_event *event)
{
int ret = perf_event__process_auxtrace_info(tool, event, session);
struct perf_tool *tool = session->tool;
int ret = perf_event__process_auxtrace_info(session, event);
if (ret == 0) {
struct perf_script *script = container_of(tool, struct perf_script, tool);
@@ -3193,7 +3221,7 @@ int cmd_script(int argc, const char **argv)
OPT_BOOLEAN(0, "ns", &nanosecs,
"Use 9 decimal places when displaying time"),
OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
"Instruction Tracing options",
"Instruction Tracing options\n" ITRACE_HELP,
itrace_parse_synth_opts),
OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename,
"Show full source file name path for source lines"),

File diff suppressed because it is too large Load Diff

View File

@@ -181,7 +181,7 @@ static int __tp_field__init_uint(struct tp_field *field, int size, int offset, b
return 0;
}
static int tp_field__init_uint(struct tp_field *field, struct format_field *format_field, bool needs_swap)
static int tp_field__init_uint(struct tp_field *field, struct tep_format_field *format_field, bool needs_swap)
{
return __tp_field__init_uint(field, format_field->size, format_field->offset, needs_swap);
}
@@ -198,7 +198,7 @@ static int __tp_field__init_ptr(struct tp_field *field, int offset)
return 0;
}
static int tp_field__init_ptr(struct tp_field *field, struct format_field *format_field)
static int tp_field__init_ptr(struct tp_field *field, struct tep_format_field *format_field)
{
return __tp_field__init_ptr(field, format_field->offset);
}
@@ -214,7 +214,7 @@ static int perf_evsel__init_tp_uint_field(struct perf_evsel *evsel,
struct tp_field *field,
const char *name)
{
struct format_field *format_field = perf_evsel__field(evsel, name);
struct tep_format_field *format_field = perf_evsel__field(evsel, name);
if (format_field == NULL)
return -1;
@@ -230,7 +230,7 @@ static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
struct tp_field *field,
const char *name)
{
struct format_field *format_field = perf_evsel__field(evsel, name);
struct tep_format_field *format_field = perf_evsel__field(evsel, name);
if (format_field == NULL)
return -1;
@@ -288,6 +288,13 @@ static int perf_evsel__init_augmented_syscall_tp_args(struct perf_evsel *evsel)
return __tp_field__init_ptr(&sc->args, sc->id.offset + sizeof(u64));
}
static int perf_evsel__init_augmented_syscall_tp_ret(struct perf_evsel *evsel)
{
struct syscall_tp *sc = evsel->priv;
return __tp_field__init_uint(&sc->ret, sizeof(u64), sc->id.offset + sizeof(u64), evsel->needs_swap);
}
static int perf_evsel__init_raw_syscall_tp(struct perf_evsel *evsel, void *handler)
{
evsel->priv = malloc(sizeof(struct syscall_tp));
@@ -498,16 +505,6 @@ static const char *clockid[] = {
};
static DEFINE_STRARRAY(clockid);
static const char *socket_families[] = {
"UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
"BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
"SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
"RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
"BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
"ALG", "NFC", "VSOCK",
};
static DEFINE_STRARRAY(socket_families);
static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
struct syscall_arg *arg)
{
@@ -631,6 +628,8 @@ static struct syscall_fmt {
} syscall_fmts[] = {
{ .name = "access",
.arg = { [1] = { .scnprintf = SCA_ACCMODE, /* mode */ }, }, },
{ .name = "bind",
.arg = { [1] = { .scnprintf = SCA_SOCKADDR, /* umyaddr */ }, }, },
{ .name = "bpf",
.arg = { [0] = STRARRAY(cmd, bpf_cmd), }, },
{ .name = "brk", .hexret = true,
@@ -645,6 +644,8 @@ static struct syscall_fmt {
[4] = { .name = "tls", .scnprintf = SCA_HEX, }, }, },
{ .name = "close",
.arg = { [0] = { .scnprintf = SCA_CLOSE_FD, /* fd */ }, }, },
{ .name = "connect",
.arg = { [1] = { .scnprintf = SCA_SOCKADDR, /* servaddr */ }, }, },
{ .name = "epoll_ctl",
.arg = { [1] = STRARRAY(op, epoll_ctl_ops), }, },
{ .name = "eventfd2",
@@ -801,7 +802,8 @@ static struct syscall_fmt {
{ .name = "sendmsg",
.arg = { [2] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
{ .name = "sendto",
.arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
.arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ },
[4] = { .scnprintf = SCA_SOCKADDR, /* addr */ }, }, },
{ .name = "set_tid_address", .errpid = true, },
{ .name = "setitimer",
.arg = { [0] = STRARRAY(which, itimers), }, },
@@ -830,6 +832,7 @@ static struct syscall_fmt {
.arg = { [2] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
{ .name = "tkill",
.arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
{ .name = "umount2", .alias = "umount", },
{ .name = "uname", .alias = "newuname", },
{ .name = "unlinkat",
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
@@ -856,13 +859,15 @@ static struct syscall_fmt *syscall_fmt__find(const char *name)
/*
* is_exit: is this "exit" or "exit_group"?
* is_open: is this "open" or "openat"? To associate the fd returned in sys_exit with the pathname in sys_enter.
* args_size: sum of the sizes of the syscall arguments, anything after that is augmented stuff: pathname for openat, etc.
*/
struct syscall {
struct event_format *tp_format;
struct tep_event_format *tp_format;
int nr_args;
int args_size;
bool is_exit;
bool is_open;
struct format_field *args;
struct tep_format_field *args;
const char *name;
struct syscall_fmt *fmt;
struct syscall_arg_fmt *arg_fmt;
@@ -1095,11 +1100,21 @@ static void thread__set_filename_pos(struct thread *thread, const char *bf,
ttrace->filename.entry_str_pos = bf - ttrace->entry_str;
}
static size_t syscall_arg__scnprintf_augmented_string(struct syscall_arg *arg, char *bf, size_t size)
{
struct augmented_arg *augmented_arg = arg->augmented.args;
return scnprintf(bf, size, "%.*s", augmented_arg->size, augmented_arg->value);
}
static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
struct syscall_arg *arg)
{
unsigned long ptr = arg->val;
if (arg->augmented.args)
return syscall_arg__scnprintf_augmented_string(arg, bf, size);
if (!arg->trace->vfs_getname)
return scnprintf(bf, size, "%#x", ptr);
@@ -1142,11 +1157,9 @@ static void sig_handler(int sig)
interrupted = sig == SIGINT;
}
static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
u64 duration, bool duration_calculated, u64 tstamp, FILE *fp)
static size_t trace__fprintf_comm_tid(struct trace *trace, struct thread *thread, FILE *fp)
{
size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
printed += fprintf_duration(duration, duration_calculated, fp);
size_t printed = 0;
if (trace->multiple_threads) {
if (trace->show_comm)
@@ -1157,6 +1170,14 @@ static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thre
return printed;
}
static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
u64 duration, bool duration_calculated, u64 tstamp, FILE *fp)
{
size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
printed += fprintf_duration(duration, duration_calculated, fp);
return printed + trace__fprintf_comm_tid(trace, thread, fp);
}
static int trace__process_event(struct trace *trace, struct machine *machine,
union perf_event *event, struct perf_sample *sample)
{
@@ -1258,10 +1279,12 @@ static int syscall__alloc_arg_fmts(struct syscall *sc, int nr_args)
static int syscall__set_arg_fmts(struct syscall *sc)
{
struct format_field *field;
struct tep_format_field *field, *last_field = NULL;
int idx = 0, len;
for (field = sc->args; field; field = field->next, ++idx) {
last_field = field;
if (sc->fmt && sc->fmt->arg[idx].scnprintf)
continue;
@@ -1270,7 +1293,7 @@ static int syscall__set_arg_fmts(struct syscall *sc)
strcmp(field->name, "path") == 0 ||
strcmp(field->name, "pathname") == 0))
sc->arg_fmt[idx].scnprintf = SCA_FILENAME;
else if (field->flags & FIELD_IS_POINTER)
else if (field->flags & TEP_FIELD_IS_POINTER)
sc->arg_fmt[idx].scnprintf = syscall_arg__scnprintf_hex;
else if (strcmp(field->type, "pid_t") == 0)
sc->arg_fmt[idx].scnprintf = SCA_PID;
@@ -1292,6 +1315,9 @@ static int syscall__set_arg_fmts(struct syscall *sc)
}
}
if (last_field)
sc->args_size = last_field->offset + last_field->size;
return 0;
}
@@ -1472,14 +1498,18 @@ static size_t syscall__scnprintf_val(struct syscall *sc, char *bf, size_t size,
}
static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
unsigned char *args, struct trace *trace,
struct thread *thread)
unsigned char *args, void *augmented_args, int augmented_args_size,
struct trace *trace, struct thread *thread)
{
size_t printed = 0;
unsigned long val;
u8 bit = 1;
struct syscall_arg arg = {
.args = args,
.augmented = {
.size = augmented_args_size,
.args = augmented_args,
},
.idx = 0,
.mask = 0,
.trace = trace,
@@ -1495,7 +1525,7 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
ttrace->ret_scnprintf = NULL;
if (sc->args != NULL) {
struct format_field *field;
struct tep_format_field *field;
for (field = sc->args; field;
field = field->next, ++arg.idx, bit <<= 1) {
@@ -1654,6 +1684,17 @@ static int trace__fprintf_sample(struct trace *trace, struct perf_evsel *evsel,
return printed;
}
static void *syscall__augmented_args(struct syscall *sc, struct perf_sample *sample, int *augmented_args_size)
{
void *augmented_args = NULL;
*augmented_args_size = sample->raw_size - sc->args_size;
if (*augmented_args_size > 0)
augmented_args = sample->raw_data + sc->args_size;
return augmented_args;
}
static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
union perf_event *event __maybe_unused,
struct perf_sample *sample)
@@ -1663,6 +1704,8 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
size_t printed = 0;
struct thread *thread;
int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
int augmented_args_size = 0;
void *augmented_args = NULL;
struct syscall *sc = trace__syscall_info(trace, evsel, id);
struct thread_trace *ttrace;
@@ -1686,13 +1729,24 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
if (!(trace->duration_filter || trace->summary_only || trace->min_stack))
trace__printf_interrupted_entry(trace);
/*
* If this is raw_syscalls.sys_enter, then it always comes with the 6 possible
* arguments, even if the syscall being handled, say "openat", uses only 4 arguments
* this breaks syscall__augmented_args() check for augmented args, as we calculate
* syscall->args_size using each syscalls:sys_enter_NAME tracefs format file,
* so when handling, say the openat syscall, we end up getting 6 args for the
* raw_syscalls:sys_enter event, when we expected just 4, we end up mistakenly
* thinking that the extra 2 u64 args are the augmented filename, so just check
* here and avoid using augmented syscalls when the evsel is the raw_syscalls one.
*/
if (evsel != trace->syscalls.events.sys_enter)
augmented_args = syscall__augmented_args(sc, sample, &augmented_args_size);
ttrace->entry_time = sample->time;
msg = ttrace->entry_str;
printed += scnprintf(msg + printed, trace__entry_str_size - printed, "%s(", sc->name);
printed += syscall__scnprintf_args(sc, msg + printed, trace__entry_str_size - printed,
args, trace, thread);
args, augmented_args, augmented_args_size, trace, thread);
if (sc->is_exit) {
if (!(trace->duration_filter || trace->summary_only || trace->failure_only || trace->min_stack)) {
@@ -1723,7 +1777,8 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct perf_evsel *evse
int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
struct syscall *sc = trace__syscall_info(trace, evsel, id);
char msg[1024];
void *args;
void *args, *augmented_args = NULL;
int augmented_args_size;
if (sc == NULL)
return -1;
@@ -1738,7 +1793,8 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct perf_evsel *evse
goto out_put;
args = perf_evsel__sc_tp_ptr(evsel, args, sample);
syscall__scnprintf_args(sc, msg, sizeof(msg), args, trace, thread);
augmented_args = syscall__augmented_args(sc, sample, &augmented_args_size);
syscall__scnprintf_args(sc, msg, sizeof(msg), args, augmented_args, augmented_args_size, trace, thread);
fprintf(trace->output, "%s", msg);
err = 0;
out_put:
@@ -2022,6 +2078,7 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
union perf_event *event __maybe_unused,
struct perf_sample *sample)
{
struct thread *thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
int callchain_ret = 0;
if (sample->callchain) {
@@ -2039,13 +2096,31 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
if (trace->trace_syscalls)
fprintf(trace->output, "( ): ");
if (thread)
trace__fprintf_comm_tid(trace, thread, trace->output);
if (evsel == trace->syscalls.events.augmented) {
int id = perf_evsel__sc_tp_uint(evsel, id, sample);
struct syscall *sc = trace__syscall_info(trace, evsel, id);
if (sc) {
fprintf(trace->output, "%s(", sc->name);
trace__fprintf_sys_enter(trace, evsel, sample);
fputc(')', trace->output);
goto newline;
}
/*
* XXX: Not having the associated syscall info or not finding/adding
* the thread should never happen, but if it does...
* fall thru and print it as a bpf_output event.
*/
}
fprintf(trace->output, "%s:", evsel->name);
if (perf_evsel__is_bpf_output(evsel)) {
if (evsel == trace->syscalls.events.augmented)
trace__fprintf_sys_enter(trace, evsel, sample);
else
bpf_output__fprintf(trace, sample);
bpf_output__fprintf(trace, sample);
} else if (evsel->tp_format) {
if (strncmp(evsel->tp_format->name, "sys_enter_", 10) ||
trace__fprintf_sys_enter(trace, evsel, sample)) {
@@ -2055,12 +2130,14 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
}
}
newline:
fprintf(trace->output, "\n");
if (callchain_ret > 0)
trace__fprintf_callchain(trace, sample);
else if (callchain_ret < 0)
pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
thread__put(thread);
out:
return 0;
}
@@ -3276,12 +3353,8 @@ int cmd_trace(int argc, const char **argv)
goto out;
}
if (evsel) {
if (perf_evsel__init_augmented_syscall_tp(evsel) ||
perf_evsel__init_augmented_syscall_tp_args(evsel))
goto out;
if (evsel)
trace.syscalls.events.augmented = evsel;
}
err = bpf__setup_stdout(trace.evlist);
if (err) {
@@ -3326,6 +3399,34 @@ int cmd_trace(int argc, const char **argv)
}
}
/*
* If we are augmenting syscalls, then combine what we put in the
* __augmented_syscalls__ BPF map with what is in the
* syscalls:sys_exit_FOO tracepoints, i.e. just like we do without BPF,
* combining raw_syscalls:sys_enter with raw_syscalls:sys_exit.
*
* We'll switch to look at two BPF maps, one for sys_enter and the
* other for sys_exit when we start augmenting the sys_exit paths with
* buffers that are being copied from kernel to userspace, think 'read'
* syscall.
*/
if (trace.syscalls.events.augmented) {
evsel = trace.syscalls.events.augmented;
if (perf_evsel__init_augmented_syscall_tp(evsel) ||
perf_evsel__init_augmented_syscall_tp_args(evsel))
goto out;
evsel->handler = trace__sys_enter;
evlist__for_each_entry(trace.evlist, evsel) {
if (strstarts(perf_evsel__name(evsel), "syscalls:sys_exit_")) {
perf_evsel__init_augmented_syscall_tp(evsel);
perf_evsel__init_augmented_syscall_tp_ret(evsel);
evsel->handler = trace__sys_exit;
}
}
}
if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
return trace__record(&trace, argc-1, &argv[1]);

View File

@@ -14,6 +14,7 @@ include/uapi/linux/sched.h
include/uapi/linux/stat.h
include/uapi/linux/vhost.h
include/uapi/sound/asound.h
include/linux/bits.h
include/linux/hash.h
include/uapi/linux/hw_breakpoint.h
arch/x86/include/asm/disabled-features.h

View File

@@ -30,3 +30,4 @@ perf-test mainporcelain common
perf-timechart mainporcelain common
perf-top mainporcelain common
perf-trace mainporcelain audit
perf-version mainporcelain common

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Augment the openat syscall with the contents of the filename pointer argument.
* Augment syscalls with the contents of the pointer arguments.
*
* Test it with:
*
@@ -10,15 +10,14 @@
* the last one should be the one for '/etc/passwd'.
*
* This matches what is marshalled into the raw_syscall:sys_enter payload
* expected by the 'perf trace' beautifiers, and can be used by them unmodified,
* which will be done as that feature is implemented in the next csets, for now
* it will appear in a dump done by the default tracepoint handler in 'perf trace',
* that uses bpf_output__fprintf() to just dump those contents, as done with
* the bpf-output event associated with the __bpf_output__ map declared in
* tools/perf/include/bpf/stdio.h.
* expected by the 'perf trace' beautifiers, and can be used by them, that will
* check if perf_sample->raw_data is more than what is expected for each
* syscalls:sys_{enter,exit}_SYSCALL tracepoint, uing the extra data as the
* contents of pointer arguments.
*/
#include <stdio.h>
#include <linux/socket.h>
struct bpf_map SEC("maps") __augmented_syscalls__ = {
.type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
@@ -27,6 +26,44 @@ struct bpf_map SEC("maps") __augmented_syscalls__ = {
.max_entries = __NR_CPUS__,
};
struct syscall_exit_args {
unsigned long long common_tp_fields;
long syscall_nr;
long ret;
};
struct augmented_filename {
unsigned int size;
int reserved;
char value[256];
};
#define augmented_filename_syscall(syscall) \
struct augmented_enter_##syscall##_args { \
struct syscall_enter_##syscall##_args args; \
struct augmented_filename filename; \
}; \
int syscall_enter(syscall)(struct syscall_enter_##syscall##_args *args) \
{ \
struct augmented_enter_##syscall##_args augmented_args = { .filename.reserved = 0, }; \
unsigned int len = sizeof(augmented_args); \
probe_read(&augmented_args.args, sizeof(augmented_args.args), args); \
augmented_args.filename.size = probe_read_str(&augmented_args.filename.value, \
sizeof(augmented_args.filename.value), \
args->filename_ptr); \
if (augmented_args.filename.size < sizeof(augmented_args.filename.value)) { \
len -= sizeof(augmented_args.filename.value) - augmented_args.filename.size; \
len &= sizeof(augmented_args.filename.value) - 1; \
} \
perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, \
&augmented_args, len); \
return 0; \
} \
int syscall_exit(syscall)(struct syscall_exit_args *args) \
{ \
return 1; /* 0 as soon as we start copying data returned by the kernel, e.g. 'read' */ \
}
struct syscall_enter_openat_args {
unsigned long long common_tp_fields;
long syscall_nr;
@@ -36,20 +73,101 @@ struct syscall_enter_openat_args {
long mode;
};
struct augmented_enter_openat_args {
struct syscall_enter_openat_args args;
char filename[64];
augmented_filename_syscall(openat);
struct syscall_enter_open_args {
unsigned long long common_tp_fields;
long syscall_nr;
char *filename_ptr;
long flags;
long mode;
};
int syscall_enter(openat)(struct syscall_enter_openat_args *args)
{
struct augmented_enter_openat_args augmented_args;
augmented_filename_syscall(open);
probe_read(&augmented_args.args, sizeof(augmented_args.args), args);
probe_read_str(&augmented_args.filename, sizeof(augmented_args.filename), args->filename_ptr);
perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU,
&augmented_args, sizeof(augmented_args));
return 1;
struct syscall_enter_inotify_add_watch_args {
unsigned long long common_tp_fields;
long syscall_nr;
long fd;
char *filename_ptr;
long mask;
};
augmented_filename_syscall(inotify_add_watch);
struct statbuf;
struct syscall_enter_newstat_args {
unsigned long long common_tp_fields;
long syscall_nr;
char *filename_ptr;
struct stat *statbuf;
};
augmented_filename_syscall(newstat);
#ifndef _K_SS_MAXSIZE
#define _K_SS_MAXSIZE 128
#endif
#define augmented_sockaddr_syscall(syscall) \
struct augmented_enter_##syscall##_args { \
struct syscall_enter_##syscall##_args args; \
struct sockaddr_storage addr; \
}; \
int syscall_enter(syscall)(struct syscall_enter_##syscall##_args *args) \
{ \
struct augmented_enter_##syscall##_args augmented_args; \
unsigned long addrlen = sizeof(augmented_args.addr); \
probe_read(&augmented_args.args, sizeof(augmented_args.args), args); \
/* FIXME_CLANG_OPTIMIZATION_THAT_ACCESSES_USER_CONTROLLED_ADDRLEN_DESPITE_THIS_CHECK */ \
/* if (addrlen > augmented_args.args.addrlen) */ \
/* addrlen = augmented_args.args.addrlen; */ \
/* */ \
probe_read(&augmented_args.addr, addrlen, args->addr_ptr); \
perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, \
&augmented_args, \
sizeof(augmented_args) - sizeof(augmented_args.addr) + addrlen); \
return 0; \
} \
int syscall_exit(syscall)(struct syscall_exit_args *args) \
{ \
return 1; /* 0 as soon as we start copying data returned by the kernel, e.g. 'read' */ \
}
struct sockaddr;
struct syscall_enter_bind_args {
unsigned long long common_tp_fields;
long syscall_nr;
long fd;
struct sockaddr *addr_ptr;
unsigned long addrlen;
};
augmented_sockaddr_syscall(bind);
struct syscall_enter_connect_args {
unsigned long long common_tp_fields;
long syscall_nr;
long fd;
struct sockaddr *addr_ptr;
unsigned long addrlen;
};
augmented_sockaddr_syscall(connect);
struct syscall_enter_sendto_args {
unsigned long long common_tp_fields;
long syscall_nr;
long fd;
void *buff;
long len;
unsigned long flags;
struct sockaddr *addr_ptr;
long addr_len;
};
augmented_sockaddr_syscall(sendto);
license(GPL);

View File

@@ -0,0 +1,80 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Augment the filename syscalls with the contents of the filename pointer argument
* filtering only those that do not start with /etc/.
*
* Test it with:
*
* perf trace -e tools/perf/examples/bpf/augmented_syscalls.c cat /etc/passwd > /dev/null
*
* It'll catch some openat syscalls related to the dynamic linked and
* the last one should be the one for '/etc/passwd'.
*
* This matches what is marshalled into the raw_syscall:sys_enter payload
* expected by the 'perf trace' beautifiers, and can be used by them unmodified,
* which will be done as that feature is implemented in the next csets, for now
* it will appear in a dump done by the default tracepoint handler in 'perf trace',
* that uses bpf_output__fprintf() to just dump those contents, as done with
* the bpf-output event associated with the __bpf_output__ map declared in
* tools/perf/include/bpf/stdio.h.
*/
#include <stdio.h>
struct bpf_map SEC("maps") __augmented_syscalls__ = {
.type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
.key_size = sizeof(int),
.value_size = sizeof(u32),
.max_entries = __NR_CPUS__,
};
struct augmented_filename {
int size;
int reserved;
char value[64];
};
#define augmented_filename_syscall_enter(syscall) \
struct augmented_enter_##syscall##_args { \
struct syscall_enter_##syscall##_args args; \
struct augmented_filename filename; \
}; \
int syscall_enter(syscall)(struct syscall_enter_##syscall##_args *args) \
{ \
char etc[6] = "/etc/"; \
struct augmented_enter_##syscall##_args augmented_args = { .filename.reserved = 0, }; \
probe_read(&augmented_args.args, sizeof(augmented_args.args), args); \
augmented_args.filename.size = probe_read_str(&augmented_args.filename.value, \
sizeof(augmented_args.filename.value), \
args->filename_ptr); \
if (__builtin_memcmp(augmented_args.filename.value, etc, 4) != 0) \
return 0; \
perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, \
&augmented_args, \
(sizeof(augmented_args) - sizeof(augmented_args.filename.value) + \
augmented_args.filename.size)); \
return 0; \
}
struct syscall_enter_openat_args {
unsigned long long common_tp_fields;
long syscall_nr;
long dfd;
char *filename_ptr;
long flags;
long mode;
};
augmented_filename_syscall_enter(openat);
struct syscall_enter_open_args {
unsigned long long common_tp_fields;
long syscall_nr;
char *filename_ptr;
long flags;
long mode;
};
augmented_filename_syscall_enter(open);
license(GPL);

View File

@@ -26,6 +26,9 @@ struct bpf_map {
#define syscall_enter(name) \
SEC("syscalls:sys_enter_" #name) syscall_enter_ ## name
#define syscall_exit(name) \
SEC("syscalls:sys_exit_" #name) syscall_exit_ ## name
#define license(name) \
char _license[] SEC("license") = #name; \
int _version SEC("version") = LINUX_VERSION_CODE;

View File

@@ -0,0 +1,24 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _UAPI_LINUX_SOCKET_H
#define _UAPI_LINUX_SOCKET_H
/*
* Desired design of maximum size and alignment (see RFC2553)
*/
#define _K_SS_MAXSIZE 128 /* Implementation specific max size */
#define _K_SS_ALIGNSIZE (__alignof__ (struct sockaddr *))
/* Implementation specific desired alignment */
typedef unsigned short __kernel_sa_family_t;
struct __kernel_sockaddr_storage {
__kernel_sa_family_t ss_family; /* address family */
/* Following field(s) are implementation specific */
char __data[_K_SS_MAXSIZE - sizeof(unsigned short)];
/* space to achieve desired size, */
/* _SS_MAXSIZE value minus size of ss_family */
} __attribute__ ((aligned(_K_SS_ALIGNSIZE))); /* force desired alignment */
#define sockaddr_storage __kernel_sockaddr_storage
#endif /* _UAPI_LINUX_SOCKET_H */

View File

@@ -0,0 +1,23 @@
[
{
"ArchStdEvent": "BR_IMMED_SPEC",
},
{
"ArchStdEvent": "BR_RETURN_SPEC",
},
{
"ArchStdEvent": "BR_INDIRECT_SPEC",
},
{
"PublicDescription": "Mispredicted or not predicted branch speculatively executed",
"EventCode": "0x10",
"EventName": "BR_MIS_PRED",
"BriefDescription": "Branch mispredicted"
},
{
"PublicDescription": "Predictable branch speculatively executed",
"EventCode": "0x12",
"EventName": "BR_PRED",
"BriefDescription": "Predictable branch"
},
]

View File

@@ -0,0 +1,26 @@
[
{
"ArchStdEvent": "BUS_ACCESS_RD",
},
{
"ArchStdEvent": "BUS_ACCESS_WR",
},
{
"ArchStdEvent": "BUS_ACCESS_SHARED",
},
{
"ArchStdEvent": "BUS_ACCESS_NOT_SHARED",
},
{
"ArchStdEvent": "BUS_ACCESS_NORMAL",
},
{
"ArchStdEvent": "BUS_ACCESS_PERIPH",
},
{
"PublicDescription": "Bus access",
"EventCode": "0x19",
"EventName": "BUS_ACCESS",
"BriefDescription": "Bus access"
},
]

View File

@@ -0,0 +1,191 @@
[
{
"ArchStdEvent": "L1D_CACHE_RD",
},
{
"ArchStdEvent": "L1D_CACHE_WR",
},
{
"ArchStdEvent": "L1D_CACHE_REFILL_RD",
},
{
"ArchStdEvent": "L1D_CACHE_INVAL",
},
{
"ArchStdEvent": "L1D_TLB_REFILL_RD",
},
{
"ArchStdEvent": "L1D_TLB_REFILL_WR",
},
{
"ArchStdEvent": "L2D_CACHE_RD",
},
{
"ArchStdEvent": "L2D_CACHE_WR",
},
{
"ArchStdEvent": "L2D_CACHE_REFILL_RD",
},
{
"ArchStdEvent": "L2D_CACHE_REFILL_WR",
},
{
"ArchStdEvent": "L2D_CACHE_WB_VICTIM",
},
{
"ArchStdEvent": "L2D_CACHE_WB_CLEAN",
},
{
"ArchStdEvent": "L2D_CACHE_INVAL",
},
{
"PublicDescription": "Level 1 instruction cache refill",
"EventCode": "0x01",
"EventName": "L1I_CACHE_REFILL",
"BriefDescription": "L1I cache refill"
},
{
"PublicDescription": "Level 1 instruction TLB refill",
"EventCode": "0x02",
"EventName": "L1I_TLB_REFILL",
"BriefDescription": "L1I TLB refill"
},
{
"PublicDescription": "Level 1 data cache refill",
"EventCode": "0x03",
"EventName": "L1D_CACHE_REFILL",
"BriefDescription": "L1D cache refill"
},
{
"PublicDescription": "Level 1 data cache access",
"EventCode": "0x04",
"EventName": "L1D_CACHE_ACCESS",
"BriefDescription": "L1D cache access"
},
{
"PublicDescription": "Level 1 data TLB refill",
"EventCode": "0x05",
"EventName": "L1D_TLB_REFILL",
"BriefDescription": "L1D TLB refill"
},
{
"PublicDescription": "Level 1 instruction cache access",
"EventCode": "0x14",
"EventName": "L1I_CACHE_ACCESS",
"BriefDescription": "L1I cache access"
},
{
"PublicDescription": "Level 2 data cache access",
"EventCode": "0x16",
"EventName": "L2D_CACHE_ACCESS",
"BriefDescription": "L2D cache access"
},
{
"PublicDescription": "Level 2 data refill",
"EventCode": "0x17",
"EventName": "L2D_CACHE_REFILL",
"BriefDescription": "L2D cache refill"
},
{
"PublicDescription": "Level 2 data cache, Write-Back",
"EventCode": "0x18",
"EventName": "L2D_CACHE_WB",
"BriefDescription": "L2D cache Write-Back"
},
{
"PublicDescription": "Level 1 data TLB access. This event counts any load or store operation which accesses the data L1 TLB",
"EventCode": "0x25",
"EventName": "L1D_TLB_ACCESS",
"BriefDescription": "L1D TLB access"
},
{
"PublicDescription": "Level 1 instruction TLB access. This event counts any instruction fetch which accesses the instruction L1 TLB",
"EventCode": "0x26",
"EventName": "L1I_TLB_ACCESS",
"BriefDescription": "L1I TLB access"
},
{
"PublicDescription": "Level 2 access to data TLB that caused a page table walk. This event counts on any data access which causes L2D_TLB_REFILL to count",
"EventCode": "0x34",
"EventName": "L2D_TLB_ACCESS",
"BriefDescription": "L2D TLB access"
},
{
"PublicDescription": "Level 2 access to instruciton TLB that caused a page table walk. This event counts on any instruciton access which causes L2I_TLB_REFILL to count",
"EventCode": "0x35",
"EventName": "L2I_TLB_ACCESS",
"BriefDescription": "L2D TLB access"
},
{
"PublicDescription": "Branch target buffer misprediction",
"EventCode": "0x102",
"EventName": "BTB_MIS_PRED",
"BriefDescription": "BTB misprediction"
},
{
"PublicDescription": "ITB miss",
"EventCode": "0x103",
"EventName": "ITB_MISS",
"BriefDescription": "ITB miss"
},
{
"PublicDescription": "DTB miss",
"EventCode": "0x104",
"EventName": "DTB_MISS",
"BriefDescription": "DTB miss"
},
{
"PublicDescription": "Level 1 data cache late miss",
"EventCode": "0x105",
"EventName": "L1D_CACHE_LATE_MISS",
"BriefDescription": "L1D cache late miss"
},
{
"PublicDescription": "Level 1 data cache prefetch request",
"EventCode": "0x106",
"EventName": "L1D_CACHE_PREFETCH",
"BriefDescription": "L1D cache prefetch"
},
{
"PublicDescription": "Level 2 data cache prefetch request",
"EventCode": "0x107",
"EventName": "L2D_CACHE_PREFETCH",
"BriefDescription": "L2D cache prefetch"
},
{
"PublicDescription": "Level 1 stage 2 TLB refill",
"EventCode": "0x111",
"EventName": "L1_STAGE2_TLB_REFILL",
"BriefDescription": "L1 stage 2 TLB refill"
},
{
"PublicDescription": "Page walk cache level-0 stage-1 hit",
"EventCode": "0x112",
"EventName": "PAGE_WALK_L0_STAGE1_HIT",
"BriefDescription": "Page walk, L0 stage-1 hit"
},
{
"PublicDescription": "Page walk cache level-1 stage-1 hit",
"EventCode": "0x113",
"EventName": "PAGE_WALK_L1_STAGE1_HIT",
"BriefDescription": "Page walk, L1 stage-1 hit"
},
{
"PublicDescription": "Page walk cache level-2 stage-1 hit",
"EventCode": "0x114",
"EventName": "PAGE_WALK_L2_STAGE1_HIT",
"BriefDescription": "Page walk, L2 stage-1 hit"
},
{
"PublicDescription": "Page walk cache level-1 stage-2 hit",
"EventCode": "0x115",
"EventName": "PAGE_WALK_L1_STAGE2_HIT",
"BriefDescription": "Page walk, L1 stage-2 hit"
},
{
"PublicDescription": "Page walk cache level-2 stage-2 hit",
"EventCode": "0x116",
"EventName": "PAGE_WALK_L2_STAGE2_HIT",
"BriefDescription": "Page walk, L2 stage-2 hit"
},
]

View File

@@ -0,0 +1,20 @@
[
{
"PublicDescription": "The number of core clock cycles",
"EventCode": "0x11",
"EventName": "CPU_CYCLES",
"BriefDescription": "Clock cycles"
},
{
"PublicDescription": "FSU clocking gated off cycle",
"EventCode": "0x101",
"EventName": "FSU_CLOCK_OFF_CYCLES",
"BriefDescription": "FSU clocking gated off cycle"
},
{
"PublicDescription": "Wait state cycle",
"EventCode": "0x110",
"EventName": "Wait_CYCLES",
"BriefDescription": "Wait state cycle"
},
]

View File

@@ -1,32 +0,0 @@
[
{
"ArchStdEvent": "L1D_CACHE_RD",
},
{
"ArchStdEvent": "L1D_CACHE_WR",
},
{
"ArchStdEvent": "L1D_CACHE_REFILL_RD",
},
{
"ArchStdEvent": "L1D_CACHE_REFILL_WR",
},
{
"ArchStdEvent": "L1D_TLB_REFILL_RD",
},
{
"ArchStdEvent": "L1D_TLB_REFILL_WR",
},
{
"ArchStdEvent": "L1D_TLB_RD",
},
{
"ArchStdEvent": "L1D_TLB_WR",
},
{
"ArchStdEvent": "BUS_ACCESS_RD",
},
{
"ArchStdEvent": "BUS_ACCESS_WR",
}
]

View File

@@ -0,0 +1,50 @@
[
{
"ArchStdEvent": "EXC_UNDEF",
},
{
"ArchStdEvent": "EXC_SVC",
},
{
"ArchStdEvent": "EXC_PABORT",
},
{
"ArchStdEvent": "EXC_DABORT",
},
{
"ArchStdEvent": "EXC_IRQ",
},
{
"ArchStdEvent": "EXC_FIQ",
},
{
"ArchStdEvent": "EXC_HVC",
},
{
"ArchStdEvent": "EXC_TRAP_PABORT",
},
{
"ArchStdEvent": "EXC_TRAP_DABORT",
},
{
"ArchStdEvent": "EXC_TRAP_OTHER",
},
{
"ArchStdEvent": "EXC_TRAP_IRQ",
},
{
"ArchStdEvent": "EXC_TRAP_FIQ",
},
{
"PublicDescription": "Exception taken",
"EventCode": "0x09",
"EventName": "EXC_TAKEN",
"BriefDescription": "Exception taken"
},
{
"PublicDescription": "Instruction architecturally executed, condition check pass, exception return",
"EventCode": "0x0a",
"EventName": "EXC_RETURN",
"BriefDescription": "Exception return"
},
]

View File

@@ -0,0 +1,89 @@
[
{
"ArchStdEvent": "LD_SPEC",
},
{
"ArchStdEvent": "ST_SPEC",
},
{
"ArchStdEvent": "LDST_SPEC",
},
{
"ArchStdEvent": "DP_SPEC",
},
{
"ArchStdEvent": "ASE_SPEC",
},
{
"ArchStdEvent": "VFP_SPEC",
},
{
"ArchStdEvent": "PC_WRITE_SPEC",
},
{
"ArchStdEvent": "CRYPTO_SPEC",
},
{
"ArchStdEvent": "ISB_SPEC",
},
{
"ArchStdEvent": "DSB_SPEC",
},
{
"ArchStdEvent": "DMB_SPEC",
},
{
"ArchStdEvent": "RC_LD_SPEC",
},
{
"ArchStdEvent": "RC_ST_SPEC",
},
{
"PublicDescription": "Instruction architecturally executed, software increment",
"EventCode": "0x00",
"EventName": "SW_INCR",
"BriefDescription": "Software increment"
},
{
"PublicDescription": "Instruction architecturally executed",
"EventCode": "0x08",
"EventName": "INST_RETIRED",
"BriefDescription": "Instruction retired"
},
{
"PublicDescription": "Instruction architecturally executed, condition code check pass, write to CONTEXTIDR",
"EventCode": "0x0b",
"EventName": "CID_WRITE_RETIRED",
"BriefDescription": "Write to CONTEXTIDR"
},
{
"PublicDescription": "Operation speculatively executed",
"EventCode": "0x1b",
"EventName": "INST_SPEC",
"BriefDescription": "Speculatively executed"
},
{
"PublicDescription": "Instruction architecturally executed (condition check pass), write to TTBR",
"EventCode": "0x1c",
"EventName": "TTBR_WRITE_RETIRED",
"BriefDescription": "Instruction executed, TTBR write"
},
{
"PublicDescription": "Instruction architecturally executed, branch. This event counts all branches, taken or not. This excludes exception entries, debug entries and CCFAIL branches",
"EventCode": "0x21",
"EventName": "BR_RETIRED",
"BriefDescription": "Branch retired"
},
{
"PublicDescription": "Instruction architecturally executed, mispredicted branch. This event counts any branch counted by BR_RETIRED which is not correctly predicted and causes a pipeline flush",
"EventCode": "0x22",
"EventName": "BR_MISPRED_RETIRED",
"BriefDescription": "Mispredicted branch retired"
},
{
"PublicDescription": "Operation speculatively executed, NOP",
"EventCode": "0x100",
"EventName": "NOP_SPEC",
"BriefDescription": "Speculatively executed, NOP"
},
]

View File

@@ -0,0 +1,14 @@
[
{
"ArchStdEvent": "LDREX_SPEC",
},
{
"ArchStdEvent": "STREX_PASS_SPEC",
},
{
"ArchStdEvent": "STREX_FAIL_SPEC",
},
{
"ArchStdEvent": "STREX_SPEC",
},
]

View File

@@ -0,0 +1,29 @@
[
{
"ArchStdEvent": "MEM_ACCESS_RD",
},
{
"ArchStdEvent": "MEM_ACCESS_WR",
},
{
"ArchStdEvent": "UNALIGNED_LD_SPEC",
},
{
"ArchStdEvent": "UNALIGNED_ST_SPEC",
},
{
"ArchStdEvent": "UNALIGNED_LDST_SPEC",
},
{
"PublicDescription": "Data memory access",
"EventCode": "0x13",
"EventName": "MEM_ACCESS",
"BriefDescription": "Memory access"
},
{
"PublicDescription": "Local memory error. This event counts any correctable or uncorrectable memory error (ECC or parity) in the protected core RAMs",
"EventCode": "0x1a",
"EventName": "MEM_ERROR",
"BriefDescription": "Memory error"
},
]

View File

@@ -0,0 +1,50 @@
[
{
"PublicDescription": "Decode starved for instruction cycle",
"EventCode": "0x108",
"EventName": "DECODE_STALL",
"BriefDescription": "Decode starved"
},
{
"PublicDescription": "Op dispatch stalled cycle",
"EventCode": "0x109",
"EventName": "DISPATCH_STALL",
"BriefDescription": "Dispatch stalled"
},
{
"PublicDescription": "IXA Op non-issue",
"EventCode": "0x10a",
"EventName": "IXA_STALL",
"BriefDescription": "IXA stalled"
},
{
"PublicDescription": "IXB Op non-issue",
"EventCode": "0x10b",
"EventName": "IXB_STALL",
"BriefDescription": "IXB stalled"
},
{
"PublicDescription": "BX Op non-issue",
"EventCode": "0x10c",
"EventName": "BX_STALL",
"BriefDescription": "BX stalled"
},
{
"PublicDescription": "LX Op non-issue",
"EventCode": "0x10d",
"EventName": "LX_STALL",
"BriefDescription": "LX stalled"
},
{
"PublicDescription": "SX Op non-issue",
"EventCode": "0x10e",
"EventName": "SX_STALL",
"BriefDescription": "SX stalled"
},
{
"PublicDescription": "FX Op non-issue",
"EventCode": "0x10f",
"EventName": "FX_STALL",
"BriefDescription": "FX stalled"
},
]

View File

@@ -21,6 +21,7 @@ perf-y += python-use.o
perf-y += bp_signal.o
perf-y += bp_signal_overflow.o
perf-y += bp_account.o
perf-y += wp.o
perf-y += task-exit.o
perf-y += sw-clock.o
perf-y += mmap-thread-lookup.o

View File

@@ -120,6 +120,16 @@ static struct test generic_tests[] = {
.func = test__bp_accounting,
.is_supported = test__bp_signal_is_supported,
},
{
.desc = "Watchpoint",
.func = test__wp,
.is_supported = test__wp_is_supported,
.subtest = {
.skip_if_fail = false,
.get_nr = test__wp_subtest_get_nr,
.get_desc = test__wp_subtest_get_desc,
},
},
{
.desc = "Number of exit events of a simple workload",
.func = test__task_exit,

View File

@@ -8,7 +8,7 @@
static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name,
int size, bool should_be_signed)
{
struct format_field *field = perf_evsel__field(evsel, name);
struct tep_format_field *field = perf_evsel__field(evsel, name);
int is_signed;
int ret = 0;
@@ -17,7 +17,7 @@ static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name,
return -1;
}
is_signed = !!(field->flags | FIELD_IS_SIGNED);
is_signed = !!(field->flags | TEP_FIELD_IS_SIGNED);
if (should_be_signed && !is_signed) {
pr_debug("%s: \"%s\" signedness(%d) is wrong, should be %d\n",
evsel->name, name, is_signed, should_be_signed);

View File

@@ -48,7 +48,7 @@ trace_libc_inet_pton_backtrace() {
*)
eventattr='max-stack=3'
echo "getaddrinfo\+0x[[:xdigit:]]+[[:space:]]\($libc\)$" >> $expected
echo ".*\+0x[[:xdigit:]]+[[:space:]]\(.*/bin/ping.*\)$" >> $expected
echo ".*(\+0x[[:xdigit:]]+|\[unknown\])[[:space:]]\(.*/bin/ping.*\)$" >> $expected
;;
esac

View File

@@ -59,6 +59,9 @@ int test__python_use(struct test *test, int subtest);
int test__bp_signal(struct test *test, int subtest);
int test__bp_signal_overflow(struct test *test, int subtest);
int test__bp_accounting(struct test *test, int subtest);
int test__wp(struct test *test, int subtest);
const char *test__wp_subtest_get_desc(int subtest);
int test__wp_subtest_get_nr(void);
int test__task_exit(struct test *test, int subtest);
int test__mem(struct test *test, int subtest);
int test__sw_clock_freq(struct test *test, int subtest);
@@ -106,6 +109,7 @@ int test__unit_number__scnprint(struct test *test, int subtest);
int test__mem2node(struct test *t, int subtest);
bool test__bp_signal_is_supported(void);
bool test__wp_is_supported(void);
#if defined(__arm__) || defined(__aarch64__)
#ifdef HAVE_DWARF_UNWIND_SUPPORT

241
tools/perf/tests/wp.c Normal file
View File

@@ -0,0 +1,241 @@
// SPDX-License-Identifier: GPL-2.0
#include <stdlib.h>
#include <sys/ioctl.h>
#include <linux/hw_breakpoint.h>
#include "tests.h"
#include "debug.h"
#include "cloexec.h"
#define WP_TEST_ASSERT_VAL(fd, text, val) \
do { \
long long count; \
wp_read(fd, &count, sizeof(long long)); \
TEST_ASSERT_VAL(text, count == val); \
} while (0)
volatile u64 data1;
volatile u8 data2[3];
static int wp_read(int fd, long long *count, int size)
{
int ret = read(fd, count, size);
if (ret != size) {
pr_debug("failed to read: %d\n", ret);
return -1;
}
return 0;
}
static void get__perf_event_attr(struct perf_event_attr *attr, int wp_type,
void *wp_addr, unsigned long wp_len)
{
memset(attr, 0, sizeof(struct perf_event_attr));
attr->type = PERF_TYPE_BREAKPOINT;
attr->size = sizeof(struct perf_event_attr);
attr->config = 0;
attr->bp_type = wp_type;
attr->bp_addr = (unsigned long)wp_addr;
attr->bp_len = wp_len;
attr->sample_period = 1;
attr->sample_type = PERF_SAMPLE_IP;
attr->exclude_kernel = 1;
attr->exclude_hv = 1;
}
static int __event(int wp_type, void *wp_addr, unsigned long wp_len)
{
int fd;
struct perf_event_attr attr;
get__perf_event_attr(&attr, wp_type, wp_addr, wp_len);
fd = sys_perf_event_open(&attr, 0, -1, -1,
perf_event_open_cloexec_flag());
if (fd < 0)
pr_debug("failed opening event %x\n", attr.bp_type);
return fd;
}
static int wp_ro_test(void)
{
int fd;
unsigned long tmp, tmp1 = rand();
fd = __event(HW_BREAKPOINT_R, (void *)&data1, sizeof(data1));
if (fd < 0)
return -1;
tmp = data1;
WP_TEST_ASSERT_VAL(fd, "RO watchpoint", 1);
data1 = tmp1 + tmp;
WP_TEST_ASSERT_VAL(fd, "RO watchpoint", 1);
close(fd);
return 0;
}
static int wp_wo_test(void)
{
int fd;
unsigned long tmp, tmp1 = rand();
fd = __event(HW_BREAKPOINT_W, (void *)&data1, sizeof(data1));
if (fd < 0)
return -1;
tmp = data1;
WP_TEST_ASSERT_VAL(fd, "WO watchpoint", 0);
data1 = tmp1 + tmp;
WP_TEST_ASSERT_VAL(fd, "WO watchpoint", 1);
close(fd);
return 0;
}
static int wp_rw_test(void)
{
int fd;
unsigned long tmp, tmp1 = rand();
fd = __event(HW_BREAKPOINT_R | HW_BREAKPOINT_W, (void *)&data1,
sizeof(data1));
if (fd < 0)
return -1;
tmp = data1;
WP_TEST_ASSERT_VAL(fd, "RW watchpoint", 1);
data1 = tmp1 + tmp;
WP_TEST_ASSERT_VAL(fd, "RW watchpoint", 2);
close(fd);
return 0;
}
static int wp_modify_test(void)
{
int fd, ret;
unsigned long tmp = rand();
struct perf_event_attr new_attr;
fd = __event(HW_BREAKPOINT_W, (void *)&data1, sizeof(data1));
if (fd < 0)
return -1;
data1 = tmp;
WP_TEST_ASSERT_VAL(fd, "Modify watchpoint", 1);
/* Modify watchpoint with disabled = 1 */
get__perf_event_attr(&new_attr, HW_BREAKPOINT_W, (void *)&data2[0],
sizeof(u8) * 2);
new_attr.disabled = 1;
ret = ioctl(fd, PERF_EVENT_IOC_MODIFY_ATTRIBUTES, &new_attr);
if (ret < 0) {
pr_debug("ioctl(PERF_EVENT_IOC_MODIFY_ATTRIBUTES) failed\n");
close(fd);
return ret;
}
data2[1] = tmp; /* Not Counted */
WP_TEST_ASSERT_VAL(fd, "Modify watchpoint", 1);
/* Enable the event */
ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);
if (ret < 0) {
pr_debug("Failed to enable event\n");
close(fd);
return ret;
}
data2[1] = tmp; /* Counted */
WP_TEST_ASSERT_VAL(fd, "Modify watchpoint", 2);
data2[2] = tmp; /* Not Counted */
WP_TEST_ASSERT_VAL(fd, "Modify watchpoint", 2);
close(fd);
return 0;
}
static bool wp_ro_supported(void)
{
#if defined (__x86_64__) || defined (__i386__)
return false;
#else
return true;
#endif
}
static void wp_ro_skip_msg(void)
{
#if defined (__x86_64__) || defined (__i386__)
pr_debug("Hardware does not support read only watchpoints.\n");
#endif
}
static struct {
const char *desc;
int (*target_func)(void);
bool (*is_supported)(void);
void (*skip_msg)(void);
} wp_testcase_table[] = {
{
.desc = "Read Only Watchpoint",
.target_func = &wp_ro_test,
.is_supported = &wp_ro_supported,
.skip_msg = &wp_ro_skip_msg,
},
{
.desc = "Write Only Watchpoint",
.target_func = &wp_wo_test,
},
{
.desc = "Read / Write Watchpoint",
.target_func = &wp_rw_test,
},
{
.desc = "Modify Watchpoint",
.target_func = &wp_modify_test,
},
};
int test__wp_subtest_get_nr(void)
{
return (int)ARRAY_SIZE(wp_testcase_table);
}
const char *test__wp_subtest_get_desc(int i)
{
if (i < 0 || i >= (int)ARRAY_SIZE(wp_testcase_table))
return NULL;
return wp_testcase_table[i].desc;
}
int test__wp(struct test *test __maybe_unused, int i)
{
if (i < 0 || i >= (int)ARRAY_SIZE(wp_testcase_table))
return TEST_FAIL;
if (wp_testcase_table[i].is_supported &&
!wp_testcase_table[i].is_supported()) {
wp_testcase_table[i].skip_msg();
return TEST_SKIP;
}
return !wp_testcase_table[i].target_func() ? TEST_OK : TEST_FAIL;
}
/* The s390 so far does not have support for
* instruction breakpoint using the perf_event_open() system call.
*/
bool test__wp_is_supported(void)
{
#if defined(__s390x__)
return false;
#else
return true;
#endif
}

View File

@@ -7,5 +7,6 @@ endif
libperf-y += kcmp.o
libperf-y += pkey_alloc.o
libperf-y += prctl.o
libperf-y += sockaddr.o
libperf-y += socket.o
libperf-y += statx.o

View File

@@ -30,9 +30,36 @@ struct thread;
size_t pid__scnprintf_fd(struct trace *trace, pid_t pid, int fd, char *bf, size_t size);
extern struct strarray strarray__socket_families;
/**
* augmented_arg: extra payload for syscall pointer arguments
* If perf_sample->raw_size is more than what a syscall sys_enter_FOO puts,
* then its the arguments contents, so that we can show more than just a
* pointer. This will be done initially with eBPF, the start of that is at the
* tools/perf/examples/bpf/augmented_syscalls.c example for the openat, but
* will eventually be done automagically caching the running kernel tracefs
* events data into an eBPF C script, that then gets compiled and its .o file
* cached for subsequent use. For char pointers like the ones for 'open' like
* syscalls its easy, for the rest we should use DWARF or better, BTF, much
* more compact.
*
* @size: 8 if all we need is an integer, otherwise all of the augmented arg.
* @int_arg: will be used for integer like pointer contents, like 'accept's 'upeer_addrlen'
* @value: u64 aligned, for structs, pathnames
*/
struct augmented_arg {
int size;
int int_arg;
u64 value[];
};
/**
* @val: value of syscall argument being formatted
* @args: All the args, use syscall_args__val(arg, nth) to access one
* @augmented_args: Extra data that can be collected, for instance, with eBPF for expanding the pathname for open, etc
* @augmented_args_size: augmented_args total payload size
* @thread: tid state (maps, pid, tid, etc)
* @trace: 'perf trace' internals: all threads, etc
* @parm: private area, may be an strarray, for instance
@@ -43,6 +70,10 @@ size_t pid__scnprintf_fd(struct trace *trace, pid_t pid, int fd, char *bf, size_
struct syscall_arg {
unsigned long val;
unsigned char *args;
struct {
struct augmented_arg *args;
int size;
} augmented;
struct thread *thread;
struct trace *trace;
void *parm;
@@ -106,6 +137,9 @@ size_t syscall_arg__scnprintf_prctl_arg2(char *bf, size_t size, struct syscall_a
size_t syscall_arg__scnprintf_prctl_arg3(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_PRCTL_ARG3 syscall_arg__scnprintf_prctl_arg3
size_t syscall_arg__scnprintf_sockaddr(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_SOCKADDR syscall_arg__scnprintf_sockaddr
size_t syscall_arg__scnprintf_socket_protocol(char *bf, size_t size, struct syscall_arg *arg);
#define SCA_SK_PROTO syscall_arg__scnprintf_socket_protocol

View File

@@ -0,0 +1,76 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2018, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
#include "trace/beauty/beauty.h"
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <arpa/inet.h>
static const char *socket_families[] = {
"UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
"BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
"SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
"RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
"BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
"ALG", "NFC", "VSOCK",
};
DEFINE_STRARRAY(socket_families);
static size_t af_inet__scnprintf(struct sockaddr *sa, char *bf, size_t size)
{
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
char tmp[16];
return scnprintf(bf, size, ", port: %d, addr: %s", ntohs(sin->sin_port),
inet_ntop(sin->sin_family, &sin->sin_addr, tmp, sizeof(tmp)));
}
static size_t af_inet6__scnprintf(struct sockaddr *sa, char *bf, size_t size)
{
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
u32 flowinfo = ntohl(sin6->sin6_flowinfo);
char tmp[512];
size_t printed = scnprintf(bf, size, ", port: %d, addr: %s", ntohs(sin6->sin6_port),
inet_ntop(sin6->sin6_family, &sin6->sin6_addr, tmp, sizeof(tmp)));
if (flowinfo != 0)
printed += scnprintf(bf + printed, size - printed, ", flowinfo: %lu", flowinfo);
if (sin6->sin6_scope_id != 0)
printed += scnprintf(bf + printed, size - printed, ", scope_id: %lu", sin6->sin6_scope_id);
return printed;
}
static size_t af_local__scnprintf(struct sockaddr *sa, char *bf, size_t size)
{
struct sockaddr_un *sun = (struct sockaddr_un *)sa;
return scnprintf(bf, size, ", path: %s", sun->sun_path);
}
static size_t (*af_scnprintfs[])(struct sockaddr *sa, char *bf, size_t size) = {
[AF_LOCAL] = af_local__scnprintf,
[AF_INET] = af_inet__scnprintf,
[AF_INET6] = af_inet6__scnprintf,
};
static size_t syscall_arg__scnprintf_augmented_sockaddr(struct syscall_arg *arg, char *bf, size_t size)
{
struct sockaddr *sa = (struct sockaddr *)arg->augmented.args;
char family[32];
size_t printed;
strarray__scnprintf(&strarray__socket_families, family, sizeof(family), "%d", sa->sa_family);
printed = scnprintf(bf, size, "{ .family: %s", family);
if (sa->sa_family < ARRAY_SIZE(af_scnprintfs) && af_scnprintfs[sa->sa_family])
printed += af_scnprintfs[sa->sa_family](sa, bf + printed, size - printed);
return printed + scnprintf(bf + printed, size - printed, " }");
}
size_t syscall_arg__scnprintf_sockaddr(char *bf, size_t size, struct syscall_arg *arg)
{
if (arg->augmented.args)
return syscall_arg__scnprintf_augmented_sockaddr(arg, bf, size);
return scnprintf(bf, size, "%#x", arg->val);
}

View File

@@ -73,6 +73,7 @@ libperf-y += vdso.o
libperf-y += counts.o
libperf-y += stat.o
libperf-y += stat-shadow.o
libperf-y += stat-display.o
libperf-y += record.o
libperf-y += srcline.o
libperf-y += data.o

View File

@@ -906,9 +906,8 @@ out_free:
return err;
}
int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_session *session)
int perf_event__process_auxtrace_info(struct perf_session *session,
union perf_event *event)
{
enum auxtrace_type type = event->auxtrace_info.type;
@@ -932,9 +931,8 @@ int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused,
}
}
s64 perf_event__process_auxtrace(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session)
s64 perf_event__process_auxtrace(struct perf_session *session,
union perf_event *event)
{
s64 err;
@@ -950,7 +948,7 @@ s64 perf_event__process_auxtrace(struct perf_tool *tool,
if (!session->auxtrace || event->header.type != PERF_RECORD_AUXTRACE)
return -EINVAL;
err = session->auxtrace->process_auxtrace_event(session, event, tool);
err = session->auxtrace->process_auxtrace_event(session, event, session->tool);
if (err < 0)
return err;
@@ -1185,9 +1183,8 @@ void events_stats__auxtrace_error_warn(const struct events_stats *stats)
}
}
int perf_event__process_auxtrace_error(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_session *session)
int perf_event__process_auxtrace_error(struct perf_session *session,
union perf_event *event)
{
if (auxtrace__dont_decode(session))
return 0;
@@ -1196,11 +1193,12 @@ int perf_event__process_auxtrace_error(struct perf_tool *tool __maybe_unused,
return 0;
}
static int __auxtrace_mmap__read(struct auxtrace_mmap *mm,
static int __auxtrace_mmap__read(struct perf_mmap *map,
struct auxtrace_record *itr,
struct perf_tool *tool, process_auxtrace_t fn,
bool snapshot, size_t snapshot_size)
{
struct auxtrace_mmap *mm = &map->auxtrace_mmap;
u64 head, old = mm->prev, offset, ref;
unsigned char *data = mm->base;
size_t size, head_off, old_off, len1, len2, padding;
@@ -1287,7 +1285,7 @@ static int __auxtrace_mmap__read(struct auxtrace_mmap *mm,
ev.auxtrace.tid = mm->tid;
ev.auxtrace.cpu = mm->cpu;
if (fn(tool, &ev, data1, len1, data2, len2))
if (fn(tool, map, &ev, data1, len1, data2, len2))
return -1;
mm->prev = head;
@@ -1306,18 +1304,18 @@ static int __auxtrace_mmap__read(struct auxtrace_mmap *mm,
return 1;
}
int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr,
int auxtrace_mmap__read(struct perf_mmap *map, struct auxtrace_record *itr,
struct perf_tool *tool, process_auxtrace_t fn)
{
return __auxtrace_mmap__read(mm, itr, tool, fn, false, 0);
return __auxtrace_mmap__read(map, itr, tool, fn, false, 0);
}
int auxtrace_mmap__read_snapshot(struct auxtrace_mmap *mm,
int auxtrace_mmap__read_snapshot(struct perf_mmap *map,
struct auxtrace_record *itr,
struct perf_tool *tool, process_auxtrace_t fn,
size_t snapshot_size)
{
return __auxtrace_mmap__read(mm, itr, tool, fn, true, snapshot_size);
return __auxtrace_mmap__read(map, itr, tool, fn, true, snapshot_size);
}
/**

View File

@@ -23,6 +23,7 @@
#include <linux/list.h>
#include <linux/perf_event.h>
#include <linux/types.h>
#include <asm/bitsperlong.h>
#include "../perf.h"
#include "event.h"
@@ -33,6 +34,7 @@ union perf_event;
struct perf_session;
struct perf_evlist;
struct perf_tool;
struct perf_mmap;
struct option;
struct record_opts;
struct auxtrace_info_event;
@@ -434,13 +436,14 @@ void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp,
bool per_cpu);
typedef int (*process_auxtrace_t)(struct perf_tool *tool,
struct perf_mmap *map,
union perf_event *event, void *data1,
size_t len1, void *data2, size_t len2);
int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr,
int auxtrace_mmap__read(struct perf_mmap *map, struct auxtrace_record *itr,
struct perf_tool *tool, process_auxtrace_t fn);
int auxtrace_mmap__read_snapshot(struct auxtrace_mmap *mm,
int auxtrace_mmap__read_snapshot(struct perf_mmap *map,
struct auxtrace_record *itr,
struct perf_tool *tool, process_auxtrace_t fn,
size_t snapshot_size);
@@ -517,15 +520,12 @@ int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr,
struct perf_tool *tool,
struct perf_session *session,
perf_event__handler_t process);
int perf_event__process_auxtrace_info(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session);
s64 perf_event__process_auxtrace(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session);
int perf_event__process_auxtrace_error(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session);
int perf_event__process_auxtrace_info(struct perf_session *session,
union perf_event *event);
s64 perf_event__process_auxtrace(struct perf_session *session,
union perf_event *event);
int perf_event__process_auxtrace_error(struct perf_session *session,
union perf_event *event);
int itrace_parse_synth_opts(const struct option *opt, const char *str,
int unset);
void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts);
@@ -577,6 +577,23 @@ static inline void auxtrace__free(struct perf_session *session)
return session->auxtrace->free(session);
}
#define ITRACE_HELP \
" i: synthesize instructions events\n" \
" b: synthesize branches events\n" \
" c: synthesize branches events (calls only)\n" \
" r: synthesize branches events (returns only)\n" \
" x: synthesize transactions events\n" \
" w: synthesize ptwrite events\n" \
" p: synthesize power events\n" \
" e: synthesize error events\n" \
" d: create a debug log\n" \
" g[len]: synthesize a call chain (use with i or x)\n" \
" l[len]: synthesize last branch entries (use with i or x)\n" \
" sNUMBER: skip initial number of events\n" \
" PERIOD[ns|us|ms|i|t]: specify period to sample stream\n" \
" concatenate multiple options. Default is ibxwpe or cewp\n"
#else
static inline struct auxtrace_record *
@@ -717,6 +734,8 @@ void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp,
struct perf_evlist *evlist, int idx,
bool per_cpu);
#define ITRACE_HELP ""
#endif
#endif

View File

@@ -1615,7 +1615,7 @@ struct perf_evsel *bpf__setup_output_event(struct perf_evlist *evlist, const cha
int bpf__setup_stdout(struct perf_evlist *evlist)
{
struct perf_evsel *evsel = bpf__setup_output_event(evlist, "__bpf_stdout__");
return IS_ERR(evsel) ? PTR_ERR(evsel) : 0;
return PTR_ERR_OR_ZERO(evsel);
}
#define ERRNO_OFFSET(e) ((e) - __BPF_LOADER_ERRNO__START)

View File

@@ -182,20 +182,20 @@ err_put_field:
}
static struct bt_ctf_field_type*
get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field)
get_tracepoint_field_type(struct ctf_writer *cw, struct tep_format_field *field)
{
unsigned long flags = field->flags;
if (flags & FIELD_IS_STRING)
if (flags & TEP_FIELD_IS_STRING)
return cw->data.string;
if (!(flags & FIELD_IS_SIGNED)) {
if (!(flags & TEP_FIELD_IS_SIGNED)) {
/* unsigned long are mostly pointers */
if (flags & FIELD_IS_LONG || flags & FIELD_IS_POINTER)
if (flags & TEP_FIELD_IS_LONG || flags & TEP_FIELD_IS_POINTER)
return cw->data.u64_hex;
}
if (flags & FIELD_IS_SIGNED) {
if (flags & TEP_FIELD_IS_SIGNED) {
if (field->size == 8)
return cw->data.s64;
else
@@ -287,7 +287,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
struct bt_ctf_event_class *event_class,
struct bt_ctf_event *event,
struct perf_sample *sample,
struct format_field *fmtf)
struct tep_format_field *fmtf)
{
struct bt_ctf_field_type *type;
struct bt_ctf_field *array_field;
@@ -304,10 +304,10 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
name = fmtf->alias;
offset = fmtf->offset;
len = fmtf->size;
if (flags & FIELD_IS_STRING)
flags &= ~FIELD_IS_ARRAY;
if (flags & TEP_FIELD_IS_STRING)
flags &= ~TEP_FIELD_IS_ARRAY;
if (flags & FIELD_IS_DYNAMIC) {
if (flags & TEP_FIELD_IS_DYNAMIC) {
unsigned long long tmp_val;
tmp_val = tep_read_number(fmtf->event->pevent,
@@ -317,7 +317,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
offset &= 0xffff;
}
if (flags & FIELD_IS_ARRAY) {
if (flags & TEP_FIELD_IS_ARRAY) {
type = bt_ctf_event_class_get_field_by_name(
event_class, name);
@@ -338,7 +338,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
type = get_tracepoint_field_type(cw, fmtf);
for (i = 0; i < n_items; i++) {
if (flags & FIELD_IS_ARRAY)
if (flags & TEP_FIELD_IS_ARRAY)
field = bt_ctf_field_array_get_field(array_field, i);
else
field = bt_ctf_field_create(type);
@@ -348,7 +348,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
return -1;
}
if (flags & FIELD_IS_STRING)
if (flags & TEP_FIELD_IS_STRING)
ret = string_set_value(field, data + offset + i * len);
else {
unsigned long long value_int;
@@ -357,7 +357,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
fmtf->event->pevent,
data + offset + i * len, len);
if (!(flags & FIELD_IS_SIGNED))
if (!(flags & TEP_FIELD_IS_SIGNED))
ret = bt_ctf_field_unsigned_integer_set_value(
field, value_int);
else
@@ -369,7 +369,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
pr_err("failed to set file value %s\n", name);
goto err_put_field;
}
if (!(flags & FIELD_IS_ARRAY)) {
if (!(flags & TEP_FIELD_IS_ARRAY)) {
ret = bt_ctf_event_set_payload(event, name, field);
if (ret) {
pr_err("failed to set payload %s\n", name);
@@ -378,7 +378,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
}
bt_ctf_field_put(field);
}
if (flags & FIELD_IS_ARRAY) {
if (flags & TEP_FIELD_IS_ARRAY) {
ret = bt_ctf_event_set_payload(event, name, array_field);
if (ret) {
pr_err("Failed add payload array %s\n", name);
@@ -396,10 +396,10 @@ err_put_field:
static int add_tracepoint_fields_values(struct ctf_writer *cw,
struct bt_ctf_event_class *event_class,
struct bt_ctf_event *event,
struct format_field *fields,
struct tep_format_field *fields,
struct perf_sample *sample)
{
struct format_field *field;
struct tep_format_field *field;
int ret;
for (field = fields; field; field = field->next) {
@@ -417,8 +417,8 @@ static int add_tracepoint_values(struct ctf_writer *cw,
struct perf_evsel *evsel,
struct perf_sample *sample)
{
struct format_field *common_fields = evsel->tp_format->format.common_fields;
struct format_field *fields = evsel->tp_format->format.fields;
struct tep_format_field *common_fields = evsel->tp_format->format.common_fields;
struct tep_format_field *fields = evsel->tp_format->format.fields;
int ret;
ret = add_tracepoint_fields_values(cw, event_class, event,
@@ -970,7 +970,7 @@ out:
static int event_class_add_field(struct bt_ctf_event_class *event_class,
struct bt_ctf_field_type *type,
struct format_field *field)
struct tep_format_field *field)
{
struct bt_ctf_field_type *t = NULL;
char *name;
@@ -1009,10 +1009,10 @@ static int event_class_add_field(struct bt_ctf_event_class *event_class,
}
static int add_tracepoint_fields_types(struct ctf_writer *cw,
struct format_field *fields,
struct tep_format_field *fields,
struct bt_ctf_event_class *event_class)
{
struct format_field *field;
struct tep_format_field *field;
int ret;
for (field = fields; field; field = field->next) {
@@ -1030,15 +1030,15 @@ static int add_tracepoint_fields_types(struct ctf_writer *cw,
* type and don't care that it is an array. What we don't
* support is an array of strings.
*/
if (flags & FIELD_IS_STRING)
flags &= ~FIELD_IS_ARRAY;
if (flags & TEP_FIELD_IS_STRING)
flags &= ~TEP_FIELD_IS_ARRAY;
if (flags & FIELD_IS_ARRAY)
if (flags & TEP_FIELD_IS_ARRAY)
type = bt_ctf_field_type_array_create(type, field->arraylen);
ret = event_class_add_field(event_class, type, field);
if (flags & FIELD_IS_ARRAY)
if (flags & TEP_FIELD_IS_ARRAY)
bt_ctf_field_type_put(type);
if (ret) {
@@ -1055,8 +1055,8 @@ static int add_tracepoint_types(struct ctf_writer *cw,
struct perf_evsel *evsel,
struct bt_ctf_event_class *class)
{
struct format_field *common_fields = evsel->tp_format->format.common_fields;
struct format_field *fields = evsel->tp_format->format.fields;
struct tep_format_field *common_fields = evsel->tp_format->format.common_fields;
struct tep_format_field *fields = evsel->tp_format->format.fields;
int ret;
ret = add_tracepoint_fields_types(cw, common_fields, class);
@@ -1578,7 +1578,7 @@ int bt_convert__perf2ctf(const char *input, const char *path,
{
struct perf_session *session;
struct perf_data data = {
.file.path = input,
.file = { .path = input, .fd = -1 },
.mode = PERF_DATA_MODE_READ,
.force = opts->force,
};

View File

@@ -463,6 +463,28 @@ int db_export__branch_types(struct db_export *dbe)
if (err)
break;
}
/* Add trace begin / end variants */
for (i = 0; branch_types[i].name ; i++) {
const char *name = branch_types[i].name;
u32 type = branch_types[i].branch_type;
char buf[64];
if (type == PERF_IP_FLAG_BRANCH ||
(type & (PERF_IP_FLAG_TRACE_BEGIN | PERF_IP_FLAG_TRACE_END)))
continue;
snprintf(buf, sizeof(buf), "trace begin / %s", name);
err = db_export__branch_type(dbe, type | PERF_IP_FLAG_TRACE_BEGIN, buf);
if (err)
break;
snprintf(buf, sizeof(buf), "%s / trace end", name);
err = db_export__branch_type(dbe, type | PERF_IP_FLAG_TRACE_END, buf);
if (err)
break;
}
return err;
}

View File

@@ -2685,7 +2685,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
return 0;
}
struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name)
struct tep_format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name)
{
return tep_find_field(evsel->tp_format, name);
}
@@ -2693,7 +2693,7 @@ struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *nam
void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample,
const char *name)
{
struct format_field *field = perf_evsel__field(evsel, name);
struct tep_format_field *field = perf_evsel__field(evsel, name);
int offset;
if (!field)
@@ -2701,7 +2701,7 @@ void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample,
offset = field->offset;
if (field->flags & FIELD_IS_DYNAMIC) {
if (field->flags & TEP_FIELD_IS_DYNAMIC) {
offset = *(int *)(sample->raw_data + field->offset);
offset &= 0xffff;
}
@@ -2709,7 +2709,7 @@ void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample,
return sample->raw_data + offset;
}
u64 format_field__intval(struct format_field *field, struct perf_sample *sample,
u64 format_field__intval(struct tep_format_field *field, struct perf_sample *sample,
bool needs_swap)
{
u64 value;
@@ -2751,7 +2751,7 @@ u64 format_field__intval(struct format_field *field, struct perf_sample *sample,
u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
const char *name)
{
struct format_field *field = perf_evsel__field(evsel, name);
struct tep_format_field *field = perf_evsel__field(evsel, name);
if (!field)
return 0;
@@ -2943,3 +2943,32 @@ struct perf_env *perf_evsel__env(struct perf_evsel *evsel)
return evsel->evlist->env;
return NULL;
}
static int store_evsel_ids(struct perf_evsel *evsel, struct perf_evlist *evlist)
{
int cpu, thread;
for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) {
for (thread = 0; thread < xyarray__max_y(evsel->fd);
thread++) {
int fd = FD(evsel, cpu, thread);
if (perf_evlist__id_add_fd(evlist, evsel,
cpu, thread, fd) < 0)
return -1;
}
}
return 0;
}
int perf_evsel__store_ids(struct perf_evsel *evsel, struct perf_evlist *evlist)
{
struct cpu_map *cpus = evsel->cpus;
struct thread_map *threads = evsel->threads;
if (perf_evsel__alloc_id(evsel, cpus->nr, threads->nr))
return -ENOMEM;
return store_evsel_ids(evsel, evlist);
}

View File

@@ -102,7 +102,7 @@ struct perf_evsel {
char *name;
double scale;
const char *unit;
struct event_format *tp_format;
struct tep_event_format *tp_format;
off_t id_offset;
struct perf_stat_evsel *stats;
void *priv;
@@ -211,7 +211,7 @@ static inline struct perf_evsel *perf_evsel__newtp(const char *sys, const char *
struct perf_evsel *perf_evsel__new_cycles(bool precise);
struct event_format *event_format__new(const char *sys, const char *name);
struct tep_event_format *event_format__new(const char *sys, const char *name);
void perf_evsel__init(struct perf_evsel *evsel,
struct perf_event_attr *attr, int idx);
@@ -296,11 +296,11 @@ static inline char *perf_evsel__strval(struct perf_evsel *evsel,
return perf_evsel__rawptr(evsel, sample, name);
}
struct format_field;
struct tep_format_field;
u64 format_field__intval(struct format_field *field, struct perf_sample *sample, bool needs_swap);
u64 format_field__intval(struct tep_format_field *field, struct perf_sample *sample, bool needs_swap);
struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name);
struct tep_format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name);
#define perf_evsel__match(evsel, t, c) \
(evsel->attr.type == PERF_TYPE_##t && \
@@ -481,4 +481,5 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
struct perf_env *perf_evsel__env(struct perf_evsel *evsel);
int perf_evsel__store_ids(struct perf_evsel *evsel, struct perf_evlist *evlist);
#endif /* __PERF_EVSEL_H */

View File

@@ -73,7 +73,7 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
}
if (details->trace_fields) {
struct format_field *field;
struct tep_format_field *field;
if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
printed += comma_fprintf(fp, &first, " (not a tracepoint)");

View File

@@ -3206,7 +3206,7 @@ static int read_attr(int fd, struct perf_header *ph,
static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel,
struct tep_handle *pevent)
{
struct event_format *event;
struct tep_event_format *event;
char bf[128];
/* already prepared */
@@ -3448,10 +3448,10 @@ int perf_event__synthesize_features(struct perf_tool *tool,
return ret;
}
int perf_event__process_feature(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session __maybe_unused)
int perf_event__process_feature(struct perf_session *session,
union perf_event *event)
{
struct perf_tool *tool = session->tool;
struct feat_fd ff = { .fd = 0 };
struct feature_event *fe = (struct feature_event *)event;
int type = fe->header.type;
@@ -3637,13 +3637,13 @@ size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp)
}
int perf_event__synthesize_attrs(struct perf_tool *tool,
struct perf_session *session,
perf_event__handler_t process)
struct perf_evlist *evlist,
perf_event__handler_t process)
{
struct perf_evsel *evsel;
int err = 0;
evlist__for_each_entry(session->evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids,
evsel->id, process);
if (err) {
@@ -3856,9 +3856,8 @@ int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
return aligned_size;
}
int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_session *session)
int perf_event__process_tracing_data(struct perf_session *session,
union perf_event *event)
{
ssize_t size_read, padding, size = event->tracing_data.size;
int fd = perf_data__fd(session->data);
@@ -3924,9 +3923,8 @@ int perf_event__synthesize_build_id(struct perf_tool *tool,
return err;
}
int perf_event__process_build_id(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_session *session)
int perf_event__process_build_id(struct perf_session *session,
union perf_event *event)
{
__event_process_build_id(&event->build_id,
event->build_id.filename,

View File

@@ -116,15 +116,14 @@ int perf_event__synthesize_extra_attr(struct perf_tool *tool,
perf_event__handler_t process,
bool is_pipe);
int perf_event__process_feature(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session);
int perf_event__process_feature(struct perf_session *session,
union perf_event *event);
int perf_event__synthesize_attr(struct perf_tool *tool,
struct perf_event_attr *attr, u32 ids, u64 *id,
perf_event__handler_t process);
int perf_event__synthesize_attrs(struct perf_tool *tool,
struct perf_session *session,
struct perf_evlist *evlist,
perf_event__handler_t process);
int perf_event__synthesize_event_update_unit(struct perf_tool *tool,
struct perf_evsel *evsel,
@@ -148,17 +147,15 @@ size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp);
int perf_event__synthesize_tracing_data(struct perf_tool *tool,
int fd, struct perf_evlist *evlist,
perf_event__handler_t process);
int perf_event__process_tracing_data(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session);
int perf_event__process_tracing_data(struct perf_session *session,
union perf_event *event);
int perf_event__synthesize_build_id(struct perf_tool *tool,
struct dso *pos, u16 misc,
perf_event__handler_t process,
struct machine *machine);
int perf_event__process_build_id(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session);
int perf_event__process_build_id(struct perf_session *session,
union perf_event *event);
bool is_perf_magic(u64 magic);
#define NAME_ALIGN 64

View File

@@ -1165,7 +1165,7 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder)
decoder->pge = false;
decoder->continuous_period = false;
decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
decoder->state.to_ip = 0;
decoder->state.type |= INTEL_PT_TRACE_END;
return 0;
}
if (err == INTEL_PT_RETURN)
@@ -1179,9 +1179,13 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder)
decoder->continuous_period = false;
decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
decoder->state.from_ip = decoder->ip;
decoder->state.to_ip = 0;
if (decoder->packet.count != 0)
if (decoder->packet.count == 0) {
decoder->state.to_ip = 0;
} else {
decoder->state.to_ip = decoder->last_ip;
decoder->ip = decoder->last_ip;
}
decoder->state.type |= INTEL_PT_TRACE_END;
} else {
decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
decoder->state.from_ip = decoder->ip;
@@ -1208,7 +1212,8 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder)
decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
decoder->ip = to_ip;
decoder->state.from_ip = decoder->ip;
decoder->state.to_ip = 0;
decoder->state.to_ip = to_ip;
decoder->state.type |= INTEL_PT_TRACE_END;
return 0;
}
intel_pt_log_at("ERROR: Conditional branch when expecting indirect branch",
@@ -1640,14 +1645,15 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder)
case INTEL_PT_TIP_PGD:
decoder->state.from_ip = decoder->ip;
decoder->state.to_ip = 0;
if (decoder->packet.count != 0) {
if (decoder->packet.count == 0) {
decoder->state.to_ip = 0;
} else {
intel_pt_set_ip(decoder);
intel_pt_log("Omitting PGD ip " x64_fmt "\n",
decoder->ip);
decoder->state.to_ip = decoder->ip;
}
decoder->pge = false;
decoder->continuous_period = false;
decoder->state.type |= INTEL_PT_TRACE_END;
return 0;
case INTEL_PT_TIP_PGE:
@@ -1661,6 +1667,7 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder)
intel_pt_set_ip(decoder);
decoder->state.to_ip = decoder->ip;
}
decoder->state.type |= INTEL_PT_TRACE_BEGIN;
return 0;
case INTEL_PT_TIP:
@@ -1739,6 +1746,7 @@ next:
intel_pt_set_ip(decoder);
decoder->state.from_ip = 0;
decoder->state.to_ip = decoder->ip;
decoder->state.type |= INTEL_PT_TRACE_BEGIN;
return 0;
}
@@ -2077,9 +2085,13 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD;
if (intel_pt_have_ip(decoder))
intel_pt_set_ip(decoder);
if (decoder->ip)
return 0;
break;
if (!decoder->ip)
break;
if (decoder->packet.type == INTEL_PT_TIP_PGE)
decoder->state.type |= INTEL_PT_TRACE_BEGIN;
if (decoder->packet.type == INTEL_PT_TIP_PGD)
decoder->state.type |= INTEL_PT_TRACE_END;
return 0;
case INTEL_PT_FUP:
if (intel_pt_have_ip(decoder))

View File

@@ -37,6 +37,8 @@ enum intel_pt_sample_type {
INTEL_PT_EX_STOP = 1 << 6,
INTEL_PT_PWR_EXIT = 1 << 7,
INTEL_PT_CBR_CHG = 1 << 8,
INTEL_PT_TRACE_BEGIN = 1 << 9,
INTEL_PT_TRACE_END = 1 << 10,
};
enum intel_pt_period_type {

View File

@@ -908,6 +908,11 @@ static void intel_pt_sample_flags(struct intel_pt_queue *ptq)
ptq->insn_len = ptq->state->insn_len;
memcpy(ptq->insn, ptq->state->insn, INTEL_PT_INSN_BUF_SZ);
}
if (ptq->state->type & INTEL_PT_TRACE_BEGIN)
ptq->flags |= PERF_IP_FLAG_TRACE_BEGIN;
if (ptq->state->type & INTEL_PT_TRACE_END)
ptq->flags |= PERF_IP_FLAG_TRACE_END;
}
static int intel_pt_setup_queue(struct intel_pt *pt,

View File

@@ -19,7 +19,7 @@
#define CLANG_BPF_CMD_DEFAULT_TEMPLATE \
"$CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS "\
"-DLINUX_VERSION_CODE=$LINUX_VERSION_CODE " \
"$CLANG_OPTIONS $KERNEL_INC_OPTIONS $PERF_BPF_INC_OPTIONS " \
"$CLANG_OPTIONS $PERF_BPF_INC_OPTIONS $KERNEL_INC_OPTIONS " \
"-Wno-unused-value -Wno-pointer-sign " \
"-working-directory $WORKING_DIR " \
"-c \"$CLANG_SOURCE\" -target bpf $CLANG_EMIT_LLVM -O2 -o - $LLVM_OPTIONS_PIPE"

View File

@@ -320,12 +320,11 @@ int map__load(struct map *map)
build_id__sprintf(map->dso->build_id,
sizeof(map->dso->build_id),
sbuild_id);
pr_warning("%s with build id %s not found",
name, sbuild_id);
pr_debug("%s with build id %s not found", name, sbuild_id);
} else
pr_warning("Failed to open %s", name);
pr_debug("Failed to open %s", name);
pr_warning(", continuing without symbols\n");
pr_debug(", continuing without symbols\n");
return -1;
} else if (nr == 0) {
#ifdef HAVE_LIBELF_SUPPORT
@@ -334,12 +333,11 @@ int map__load(struct map *map)
if (len > sizeof(DSO__DELETED) &&
strcmp(name + real_len + 1, DSO__DELETED) == 0) {
pr_warning("%.*s was updated (is prelink enabled?). "
pr_debug("%.*s was updated (is prelink enabled?). "
"Restart the long running apps that use it!\n",
(int)real_len, name);
} else {
pr_warning("no symbols found in %s, maybe install "
"a debug package?\n", name);
pr_debug("no symbols found in %s, maybe install a debug package?\n", name);
}
#endif
return -1;
@@ -712,8 +710,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp
if (verbose >= 2) {
if (use_browser) {
pr_warning("overlapping maps in %s "
"(disable tui for more info)\n",
pr_debug("overlapping maps in %s (disable tui for more info)\n",
map->dso->name);
} else {
fputs("overlapping maps:\n", fp);

View File

@@ -281,7 +281,7 @@ int perf_mmap__read_init(struct perf_mmap *map)
}
int perf_mmap__push(struct perf_mmap *md, void *to,
int push(void *to, void *buf, size_t size))
int push(struct perf_mmap *map, void *to, void *buf, size_t size))
{
u64 head = perf_mmap__read_head(md);
unsigned char *data = md->base + page_size;
@@ -300,7 +300,7 @@ int perf_mmap__push(struct perf_mmap *md, void *to,
size = md->mask + 1 - (md->start & md->mask);
md->start += size;
if (push(to, buf, size) < 0) {
if (push(md, to, buf, size) < 0) {
rc = -1;
goto out;
}
@@ -310,7 +310,7 @@ int perf_mmap__push(struct perf_mmap *md, void *to,
size = md->end - md->start;
md->start += size;
if (push(to, buf, size) < 0) {
if (push(md, to, buf, size) < 0) {
rc = -1;
goto out;
}

View File

@@ -93,7 +93,7 @@ union perf_event *perf_mmap__read_forward(struct perf_mmap *map);
union perf_event *perf_mmap__read_event(struct perf_mmap *map);
int perf_mmap__push(struct perf_mmap *md, void *to,
int push(void *to, void *buf, size_t size));
int push(struct perf_mmap *map, void *to, void *buf, size_t size));
size_t perf_mmap__mmap_len(struct perf_mmap *map);

View File

@@ -80,14 +80,20 @@ static union perf_event *dup_event(struct ordered_events *oe,
return oe->copy_on_queue ? __dup_event(oe, event) : event;
}
static void free_dup_event(struct ordered_events *oe, union perf_event *event)
static void __free_dup_event(struct ordered_events *oe, union perf_event *event)
{
if (event && oe->copy_on_queue) {
if (event) {
oe->cur_alloc_size -= event->header.size;
free(event);
}
}
static void free_dup_event(struct ordered_events *oe, union perf_event *event)
{
if (oe->copy_on_queue)
__free_dup_event(oe, event);
}
#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct ordered_event))
static struct ordered_event *alloc_event(struct ordered_events *oe,
union perf_event *event)
@@ -95,21 +101,49 @@ static struct ordered_event *alloc_event(struct ordered_events *oe,
struct list_head *cache = &oe->cache;
struct ordered_event *new = NULL;
union perf_event *new_event;
size_t size;
new_event = dup_event(oe, event);
if (!new_event)
return NULL;
/*
* We maintain the following scheme of buffers for ordered
* event allocation:
*
* to_free list -> buffer1 (64K)
* buffer2 (64K)
* ...
*
* Each buffer keeps an array of ordered events objects:
* buffer -> event[0]
* event[1]
* ...
*
* Each allocated ordered event is linked to one of
* following lists:
* - time ordered list 'events'
* - list of currently removed events 'cache'
*
* Allocation of the ordered event uses the following order
* to get the memory:
* - use recently removed object from 'cache' list
* - use available object in current allocation buffer
* - allocate new buffer if the current buffer is full
*
* Removal of ordered event object moves it from events to
* the cache list.
*/
size = sizeof(*oe->buffer) + MAX_SAMPLE_BUFFER * sizeof(*new);
if (!list_empty(cache)) {
new = list_entry(cache->next, struct ordered_event, list);
list_del(&new->list);
} else if (oe->buffer) {
new = oe->buffer + oe->buffer_idx;
new = &oe->buffer->event[oe->buffer_idx];
if (++oe->buffer_idx == MAX_SAMPLE_BUFFER)
oe->buffer = NULL;
} else if (oe->cur_alloc_size < oe->max_alloc_size) {
size_t size = MAX_SAMPLE_BUFFER * sizeof(*new);
} else if ((oe->cur_alloc_size + size) < oe->max_alloc_size) {
oe->buffer = malloc(size);
if (!oe->buffer) {
free_dup_event(oe, new_event);
@@ -122,11 +156,11 @@ static struct ordered_event *alloc_event(struct ordered_events *oe,
oe->cur_alloc_size += size;
list_add(&oe->buffer->list, &oe->to_free);
/* First entry is abused to maintain the to_free list. */
oe->buffer_idx = 2;
new = oe->buffer + 1;
oe->buffer_idx = 1;
new = &oe->buffer->event[0];
} else {
pr("allocation limit reached %" PRIu64 "B\n", oe->max_alloc_size);
return NULL;
}
new->event = new_event;
@@ -300,15 +334,38 @@ void ordered_events__init(struct ordered_events *oe, ordered_events__deliver_t d
oe->deliver = deliver;
}
static void
ordered_events_buffer__free(struct ordered_events_buffer *buffer,
unsigned int max, struct ordered_events *oe)
{
if (oe->copy_on_queue) {
unsigned int i;
for (i = 0; i < max; i++)
__free_dup_event(oe, buffer->event[i].event);
}
free(buffer);
}
void ordered_events__free(struct ordered_events *oe)
{
while (!list_empty(&oe->to_free)) {
struct ordered_event *event;
struct ordered_events_buffer *buffer, *tmp;
event = list_entry(oe->to_free.next, struct ordered_event, list);
list_del(&event->list);
free_dup_event(oe, event->event);
free(event);
if (list_empty(&oe->to_free))
return;
/*
* Current buffer might not have all the events allocated
* yet, we need to free only allocated ones ...
*/
list_del(&oe->buffer->list);
ordered_events_buffer__free(oe->buffer, oe->buffer_idx, oe);
/* ... and continue with the rest */
list_for_each_entry_safe(buffer, tmp, &oe->to_free, list) {
list_del(&buffer->list);
ordered_events_buffer__free(buffer, MAX_SAMPLE_BUFFER, oe);
}
}

View File

@@ -25,23 +25,28 @@ struct ordered_events;
typedef int (*ordered_events__deliver_t)(struct ordered_events *oe,
struct ordered_event *event);
struct ordered_events_buffer {
struct list_head list;
struct ordered_event event[0];
};
struct ordered_events {
u64 last_flush;
u64 next_flush;
u64 max_timestamp;
u64 max_alloc_size;
u64 cur_alloc_size;
struct list_head events;
struct list_head cache;
struct list_head to_free;
struct ordered_event *buffer;
struct ordered_event *last;
ordered_events__deliver_t deliver;
int buffer_idx;
unsigned int nr_events;
enum oe_flush last_flush_type;
u32 nr_unordered_events;
bool copy_on_queue;
u64 last_flush;
u64 next_flush;
u64 max_timestamp;
u64 max_alloc_size;
u64 cur_alloc_size;
struct list_head events;
struct list_head cache;
struct list_head to_free;
struct ordered_events_buffer *buffer;
struct ordered_event *last;
ordered_events__deliver_t deliver;
int buffer_idx;
unsigned int nr_events;
enum oe_flush last_flush_type;
u32 nr_unordered_events;
bool copy_on_queue;
};
int ordered_events__queue(struct ordered_events *oe, union perf_event *event,

View File

@@ -340,7 +340,7 @@ static bool is_tracepoint(struct pyrf_event *pevent)
}
static PyObject*
tracepoint_field(struct pyrf_event *pe, struct format_field *field)
tracepoint_field(struct pyrf_event *pe, struct tep_format_field *field)
{
struct tep_handle *pevent = field->event->pevent;
void *data = pe->sample.raw_data;
@@ -348,28 +348,28 @@ tracepoint_field(struct pyrf_event *pe, struct format_field *field)
unsigned long long val;
unsigned int offset, len;
if (field->flags & FIELD_IS_ARRAY) {
if (field->flags & TEP_FIELD_IS_ARRAY) {
offset = field->offset;
len = field->size;
if (field->flags & FIELD_IS_DYNAMIC) {
if (field->flags & TEP_FIELD_IS_DYNAMIC) {
val = tep_read_number(pevent, data + offset, len);
offset = val;
len = offset >> 16;
offset &= 0xffff;
}
if (field->flags & FIELD_IS_STRING &&
if (field->flags & TEP_FIELD_IS_STRING &&
is_printable_array(data + offset, len)) {
ret = _PyUnicode_FromString((char *)data + offset);
} else {
ret = PyByteArray_FromStringAndSize((const char *) data + offset, len);
field->flags &= ~FIELD_IS_STRING;
field->flags &= ~TEP_FIELD_IS_STRING;
}
} else {
val = tep_read_number(pevent, data + field->offset,
field->size);
if (field->flags & FIELD_IS_POINTER)
if (field->flags & TEP_FIELD_IS_POINTER)
ret = PyLong_FromUnsignedLong((unsigned long) val);
else if (field->flags & FIELD_IS_SIGNED)
else if (field->flags & TEP_FIELD_IS_SIGNED)
ret = PyLong_FromLong((long) val);
else
ret = PyLong_FromUnsignedLong((unsigned long) val);
@@ -383,10 +383,10 @@ get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name)
{
const char *str = _PyUnicode_AsString(PyObject_Str(attr_name));
struct perf_evsel *evsel = pevent->evsel;
struct format_field *field;
struct tep_format_field *field;
if (!evsel->tp_format) {
struct event_format *tp_format;
struct tep_event_format *tp_format;
tp_format = trace_event__tp_format_id(evsel->attr.config);
if (!tp_format)
@@ -1240,7 +1240,7 @@ static struct {
static PyObject *pyrf__tracepoint(struct pyrf_evsel *pevsel,
PyObject *args, PyObject *kwargs)
{
struct event_format *tp_format;
struct tep_event_format *tp_format;
static char *kwlist[] = { "sys", "name", NULL };
char *sys = NULL;
char *name = NULL;

View File

@@ -147,6 +147,9 @@
#include <linux/bitops.h>
#include <linux/log2.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "cpumap.h"
#include "color.h"
#include "evsel.h"
@@ -159,6 +162,7 @@
#include "auxtrace.h"
#include "s390-cpumsf.h"
#include "s390-cpumsf-kernel.h"
#include "config.h"
struct s390_cpumsf {
struct auxtrace auxtrace;
@@ -170,6 +174,8 @@ struct s390_cpumsf {
u32 pmu_type;
u16 machine_type;
bool data_queued;
bool use_logfile;
char *logdir;
};
struct s390_cpumsf_queue {
@@ -177,6 +183,7 @@ struct s390_cpumsf_queue {
unsigned int queue_nr;
struct auxtrace_buffer *buffer;
int cpu;
FILE *logfile;
};
/* Display s390 CPU measurement facility basic-sampling data entry */
@@ -595,6 +602,12 @@ static int s390_cpumsf_run_decoder(struct s390_cpumsf_queue *sfq,
buffer->use_size = buffer->size;
buffer->use_data = buffer->data;
}
if (sfq->logfile) { /* Write into log file */
size_t rc = fwrite(buffer->data, buffer->size, 1,
sfq->logfile);
if (rc != 1)
pr_err("Failed to write auxiliary data\n");
}
} else
buffer = sfq->buffer;
@@ -606,6 +619,13 @@ static int s390_cpumsf_run_decoder(struct s390_cpumsf_queue *sfq,
return -ENOMEM;
buffer->use_size = buffer->size;
buffer->use_data = buffer->data;
if (sfq->logfile) { /* Write into log file */
size_t rc = fwrite(buffer->data, buffer->size, 1,
sfq->logfile);
if (rc != 1)
pr_err("Failed to write auxiliary data\n");
}
}
pr_debug4("%s queue_nr:%d buffer:%" PRId64 " offset:%#" PRIx64 " size:%#zx rest:%#zx\n",
__func__, sfq->queue_nr, buffer->buffer_nr, buffer->offset,
@@ -640,6 +660,23 @@ s390_cpumsf_alloc_queue(struct s390_cpumsf *sf, unsigned int queue_nr)
sfq->sf = sf;
sfq->queue_nr = queue_nr;
sfq->cpu = -1;
if (sf->use_logfile) {
char *name;
int rc;
rc = (sf->logdir)
? asprintf(&name, "%s/aux.smp.%02x",
sf->logdir, queue_nr)
: asprintf(&name, "aux.smp.%02x", queue_nr);
if (rc > 0)
sfq->logfile = fopen(name, "w");
if (sfq->logfile == NULL) {
pr_err("Failed to open auxiliary log file %s,"
"continue...\n", name);
sf->use_logfile = false;
}
free(name);
}
return sfq;
}
@@ -850,8 +887,16 @@ static void s390_cpumsf_free_queues(struct perf_session *session)
struct auxtrace_queues *queues = &sf->queues;
unsigned int i;
for (i = 0; i < queues->nr_queues; i++)
for (i = 0; i < queues->nr_queues; i++) {
struct s390_cpumsf_queue *sfq = (struct s390_cpumsf_queue *)
queues->queue_array[i].priv;
if (sfq != NULL && sfq->logfile) {
fclose(sfq->logfile);
sfq->logfile = NULL;
}
zfree(&queues->queue_array[i].priv);
}
auxtrace_queues__free(queues);
}
@@ -864,6 +909,7 @@ static void s390_cpumsf_free(struct perf_session *session)
auxtrace_heap__free(&sf->heap);
s390_cpumsf_free_queues(session);
session->auxtrace = NULL;
free(sf->logdir);
free(sf);
}
@@ -877,17 +923,55 @@ static int s390_cpumsf_get_type(const char *cpuid)
/* Check itrace options set on perf report command.
* Return true, if none are set or all options specified can be
* handled on s390.
* handled on s390 (currently only option 'd' for logging.
* Return false otherwise.
*/
static bool check_auxtrace_itrace(struct itrace_synth_opts *itops)
{
bool ison = false;
if (!itops || !itops->set)
return true;
pr_err("No --itrace options supported\n");
ison = itops->inject || itops->instructions || itops->branches ||
itops->transactions || itops->ptwrites ||
itops->pwr_events || itops->errors ||
itops->dont_decode || itops->calls || itops->returns ||
itops->callchain || itops->thread_stack ||
itops->last_branch;
if (!ison)
return true;
pr_err("Unsupported --itrace options specified\n");
return false;
}
/* Check for AUXTRACE dump directory if it is needed.
* On failure print an error message but continue.
* Return 0 on wrong keyword in config file and 1 otherwise.
*/
static int s390_cpumsf__config(const char *var, const char *value, void *cb)
{
struct s390_cpumsf *sf = cb;
struct stat stbuf;
int rc;
if (strcmp(var, "auxtrace.dumpdir"))
return 0;
sf->logdir = strdup(value);
if (sf->logdir == NULL) {
pr_err("Failed to find auxtrace log directory %s,"
" continue with current directory...\n", value);
return 1;
}
rc = stat(sf->logdir, &stbuf);
if (rc == -1 || !S_ISDIR(stbuf.st_mode)) {
pr_err("Missing auxtrace log directory %s,"
" continue with current directory...\n", value);
free(sf->logdir);
sf->logdir = NULL;
}
return 1;
}
int s390_cpumsf_process_auxtrace_info(union perf_event *event,
struct perf_session *session)
{
@@ -906,6 +990,9 @@ int s390_cpumsf_process_auxtrace_info(union perf_event *event,
err = -EINVAL;
goto err_free;
}
sf->use_logfile = session->itrace_synth_opts->log;
if (sf->use_logfile)
perf_config(s390_cpumsf__config, sf);
err = auxtrace_queues__init(&sf->queues);
if (err)
@@ -940,6 +1027,7 @@ err_free_queues:
auxtrace_queues__free(&sf->queues);
session->auxtrace = NULL;
err_free:
free(sf->logdir);
free(sf);
return err;
}

View File

@@ -99,7 +99,7 @@ static void define_symbolic_value(const char *ev_name,
LEAVE;
}
static void define_symbolic_values(struct print_flag_sym *field,
static void define_symbolic_values(struct tep_print_flag_sym *field,
const char *ev_name,
const char *field_name)
{
@@ -157,7 +157,7 @@ static void define_flag_value(const char *ev_name,
LEAVE;
}
static void define_flag_values(struct print_flag_sym *field,
static void define_flag_values(struct tep_print_flag_sym *field,
const char *ev_name,
const char *field_name)
{
@@ -189,62 +189,62 @@ static void define_flag_field(const char *ev_name,
LEAVE;
}
static void define_event_symbols(struct event_format *event,
static void define_event_symbols(struct tep_event_format *event,
const char *ev_name,
struct print_arg *args)
struct tep_print_arg *args)
{
if (args == NULL)
return;
switch (args->type) {
case PRINT_NULL:
case TEP_PRINT_NULL:
break;
case PRINT_ATOM:
case TEP_PRINT_ATOM:
define_flag_value(ev_name, cur_field_name, "0",
args->atom.atom);
zero_flag_atom = 0;
break;
case PRINT_FIELD:
case TEP_PRINT_FIELD:
free(cur_field_name);
cur_field_name = strdup(args->field.name);
break;
case PRINT_FLAGS:
case TEP_PRINT_FLAGS:
define_event_symbols(event, ev_name, args->flags.field);
define_flag_field(ev_name, cur_field_name, args->flags.delim);
define_flag_values(args->flags.flags, ev_name, cur_field_name);
break;
case PRINT_SYMBOL:
case TEP_PRINT_SYMBOL:
define_event_symbols(event, ev_name, args->symbol.field);
define_symbolic_field(ev_name, cur_field_name);
define_symbolic_values(args->symbol.symbols, ev_name,
cur_field_name);
break;
case PRINT_HEX:
case PRINT_HEX_STR:
case TEP_PRINT_HEX:
case TEP_PRINT_HEX_STR:
define_event_symbols(event, ev_name, args->hex.field);
define_event_symbols(event, ev_name, args->hex.size);
break;
case PRINT_INT_ARRAY:
case TEP_PRINT_INT_ARRAY:
define_event_symbols(event, ev_name, args->int_array.field);
define_event_symbols(event, ev_name, args->int_array.count);
define_event_symbols(event, ev_name, args->int_array.el_size);
break;
case PRINT_BSTRING:
case PRINT_DYNAMIC_ARRAY:
case PRINT_DYNAMIC_ARRAY_LEN:
case PRINT_STRING:
case PRINT_BITMASK:
case TEP_PRINT_BSTRING:
case TEP_PRINT_DYNAMIC_ARRAY:
case TEP_PRINT_DYNAMIC_ARRAY_LEN:
case TEP_PRINT_STRING:
case TEP_PRINT_BITMASK:
break;
case PRINT_TYPE:
case TEP_PRINT_TYPE:
define_event_symbols(event, ev_name, args->typecast.item);
break;
case PRINT_OP:
case TEP_PRINT_OP:
if (strcmp(args->op.op, ":") == 0)
zero_flag_atom = 1;
define_event_symbols(event, ev_name, args->op.left);
define_event_symbols(event, ev_name, args->op.right);
break;
case PRINT_FUNC:
case TEP_PRINT_FUNC:
default:
pr_err("Unsupported print arg type\n");
/* we should warn... */
@@ -338,8 +338,8 @@ static void perl_process_tracepoint(struct perf_sample *sample,
struct addr_location *al)
{
struct thread *thread = al->thread;
struct event_format *event = evsel->tp_format;
struct format_field *field;
struct tep_event_format *event = evsel->tp_format;
struct tep_format_field *field;
static char handler[256];
unsigned long long val;
unsigned long s, ns;
@@ -388,9 +388,9 @@ static void perl_process_tracepoint(struct perf_sample *sample,
/* common fields other than pid can be accessed via xsub fns */
for (field = event->format.fields; field; field = field->next) {
if (field->flags & FIELD_IS_STRING) {
if (field->flags & TEP_FIELD_IS_STRING) {
int offset;
if (field->flags & FIELD_IS_DYNAMIC) {
if (field->flags & TEP_FIELD_IS_DYNAMIC) {
offset = *(int *)(data + field->offset);
offset &= 0xffff;
} else
@@ -399,7 +399,7 @@ static void perl_process_tracepoint(struct perf_sample *sample,
} else { /* FIELD_IS_NUMERIC */
val = read_size(event, data + field->offset,
field->size);
if (field->flags & FIELD_IS_SIGNED) {
if (field->flags & TEP_FIELD_IS_SIGNED) {
XPUSHs(sv_2mortal(newSViv(val)));
} else {
XPUSHs(sv_2mortal(newSVuv(val)));
@@ -537,8 +537,8 @@ static int perl_stop_script(void)
static int perl_generate_script(struct tep_handle *pevent, const char *outfile)
{
struct event_format *event = NULL;
struct format_field *f;
struct tep_event_format *event = NULL;
struct tep_format_field *f;
char fname[PATH_MAX];
int not_first, count;
FILE *ofp;
@@ -646,11 +646,11 @@ sub print_backtrace\n\
count++;
fprintf(ofp, "%s=", f->name);
if (f->flags & FIELD_IS_STRING ||
f->flags & FIELD_IS_FLAG ||
f->flags & FIELD_IS_SYMBOLIC)
if (f->flags & TEP_FIELD_IS_STRING ||
f->flags & TEP_FIELD_IS_FLAG ||
f->flags & TEP_FIELD_IS_SYMBOLIC)
fprintf(ofp, "%%s");
else if (f->flags & FIELD_IS_SIGNED)
else if (f->flags & TEP_FIELD_IS_SIGNED)
fprintf(ofp, "%%d");
else
fprintf(ofp, "%%u");
@@ -668,7 +668,7 @@ sub print_backtrace\n\
if (++count % 5 == 0)
fprintf(ofp, "\n\t ");
if (f->flags & FIELD_IS_FLAG) {
if (f->flags & TEP_FIELD_IS_FLAG) {
if ((count - 1) % 5 != 0) {
fprintf(ofp, "\n\t ");
count = 4;
@@ -678,7 +678,7 @@ sub print_backtrace\n\
event->name);
fprintf(ofp, "\"%s\", $%s)", f->name,
f->name);
} else if (f->flags & FIELD_IS_SYMBOLIC) {
} else if (f->flags & TEP_FIELD_IS_SYMBOLIC) {
if ((count - 1) % 5 != 0) {
fprintf(ofp, "\n\t ");
count = 4;

View File

@@ -193,7 +193,7 @@ static void try_call_object(const char *handler_name, PyObject *args)
call_object(handler, args, handler_name);
}
static void define_value(enum print_arg_type field_type,
static void define_value(enum tep_print_arg_type field_type,
const char *ev_name,
const char *field_name,
const char *field_value,
@@ -204,7 +204,7 @@ static void define_value(enum print_arg_type field_type,
unsigned long long value;
unsigned n = 0;
if (field_type == PRINT_SYMBOL)
if (field_type == TEP_PRINT_SYMBOL)
handler_name = "define_symbolic_value";
t = PyTuple_New(4);
@@ -223,8 +223,8 @@ static void define_value(enum print_arg_type field_type,
Py_DECREF(t);
}
static void define_values(enum print_arg_type field_type,
struct print_flag_sym *field,
static void define_values(enum tep_print_arg_type field_type,
struct tep_print_flag_sym *field,
const char *ev_name,
const char *field_name)
{
@@ -235,7 +235,7 @@ static void define_values(enum print_arg_type field_type,
define_values(field_type, field->next, ev_name, field_name);
}
static void define_field(enum print_arg_type field_type,
static void define_field(enum tep_print_arg_type field_type,
const char *ev_name,
const char *field_name,
const char *delim)
@@ -244,10 +244,10 @@ static void define_field(enum print_arg_type field_type,
PyObject *t;
unsigned n = 0;
if (field_type == PRINT_SYMBOL)
if (field_type == TEP_PRINT_SYMBOL)
handler_name = "define_symbolic_field";
if (field_type == PRINT_FLAGS)
if (field_type == TEP_PRINT_FLAGS)
t = PyTuple_New(3);
else
t = PyTuple_New(2);
@@ -256,7 +256,7 @@ static void define_field(enum print_arg_type field_type,
PyTuple_SetItem(t, n++, _PyUnicode_FromString(ev_name));
PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_name));
if (field_type == PRINT_FLAGS)
if (field_type == TEP_PRINT_FLAGS)
PyTuple_SetItem(t, n++, _PyUnicode_FromString(delim));
try_call_object(handler_name, t);
@@ -264,54 +264,54 @@ static void define_field(enum print_arg_type field_type,
Py_DECREF(t);
}
static void define_event_symbols(struct event_format *event,
static void define_event_symbols(struct tep_event_format *event,
const char *ev_name,
struct print_arg *args)
struct tep_print_arg *args)
{
if (args == NULL)
return;
switch (args->type) {
case PRINT_NULL:
case TEP_PRINT_NULL:
break;
case PRINT_ATOM:
define_value(PRINT_FLAGS, ev_name, cur_field_name, "0",
case TEP_PRINT_ATOM:
define_value(TEP_PRINT_FLAGS, ev_name, cur_field_name, "0",
args->atom.atom);
zero_flag_atom = 0;
break;
case PRINT_FIELD:
case TEP_PRINT_FIELD:
free(cur_field_name);
cur_field_name = strdup(args->field.name);
break;
case PRINT_FLAGS:
case TEP_PRINT_FLAGS:
define_event_symbols(event, ev_name, args->flags.field);
define_field(PRINT_FLAGS, ev_name, cur_field_name,
define_field(TEP_PRINT_FLAGS, ev_name, cur_field_name,
args->flags.delim);
define_values(PRINT_FLAGS, args->flags.flags, ev_name,
define_values(TEP_PRINT_FLAGS, args->flags.flags, ev_name,
cur_field_name);
break;
case PRINT_SYMBOL:
case TEP_PRINT_SYMBOL:
define_event_symbols(event, ev_name, args->symbol.field);
define_field(PRINT_SYMBOL, ev_name, cur_field_name, NULL);
define_values(PRINT_SYMBOL, args->symbol.symbols, ev_name,
define_field(TEP_PRINT_SYMBOL, ev_name, cur_field_name, NULL);
define_values(TEP_PRINT_SYMBOL, args->symbol.symbols, ev_name,
cur_field_name);
break;
case PRINT_HEX:
case PRINT_HEX_STR:
case TEP_PRINT_HEX:
case TEP_PRINT_HEX_STR:
define_event_symbols(event, ev_name, args->hex.field);
define_event_symbols(event, ev_name, args->hex.size);
break;
case PRINT_INT_ARRAY:
case TEP_PRINT_INT_ARRAY:
define_event_symbols(event, ev_name, args->int_array.field);
define_event_symbols(event, ev_name, args->int_array.count);
define_event_symbols(event, ev_name, args->int_array.el_size);
break;
case PRINT_STRING:
case TEP_PRINT_STRING:
break;
case PRINT_TYPE:
case TEP_PRINT_TYPE:
define_event_symbols(event, ev_name, args->typecast.item);
break;
case PRINT_OP:
case TEP_PRINT_OP:
if (strcmp(args->op.op, ":") == 0)
zero_flag_atom = 1;
define_event_symbols(event, ev_name, args->op.left);
@@ -319,11 +319,11 @@ static void define_event_symbols(struct event_format *event,
break;
default:
/* gcc warns for these? */
case PRINT_BSTRING:
case PRINT_DYNAMIC_ARRAY:
case PRINT_DYNAMIC_ARRAY_LEN:
case PRINT_FUNC:
case PRINT_BITMASK:
case TEP_PRINT_BSTRING:
case TEP_PRINT_DYNAMIC_ARRAY:
case TEP_PRINT_DYNAMIC_ARRAY_LEN:
case TEP_PRINT_FUNC:
case TEP_PRINT_BITMASK:
/* we should warn... */
return;
}
@@ -332,10 +332,10 @@ static void define_event_symbols(struct event_format *event,
define_event_symbols(event, ev_name, args->next);
}
static PyObject *get_field_numeric_entry(struct event_format *event,
struct format_field *field, void *data)
static PyObject *get_field_numeric_entry(struct tep_event_format *event,
struct tep_format_field *field, void *data)
{
bool is_array = field->flags & FIELD_IS_ARRAY;
bool is_array = field->flags & TEP_FIELD_IS_ARRAY;
PyObject *obj = NULL, *list = NULL;
unsigned long long val;
unsigned int item_size, n_items, i;
@@ -353,7 +353,7 @@ static PyObject *get_field_numeric_entry(struct event_format *event,
val = read_size(event, data + field->offset + i * item_size,
item_size);
if (field->flags & FIELD_IS_SIGNED) {
if (field->flags & TEP_FIELD_IS_SIGNED) {
if ((long long)val >= LONG_MIN &&
(long long)val <= LONG_MAX)
obj = _PyLong_FromLong(val);
@@ -790,11 +790,11 @@ static void python_process_tracepoint(struct perf_sample *sample,
struct perf_evsel *evsel,
struct addr_location *al)
{
struct event_format *event = evsel->tp_format;
struct tep_event_format *event = evsel->tp_format;
PyObject *handler, *context, *t, *obj = NULL, *callchain;
PyObject *dict = NULL, *all_entries_dict = NULL;
static char handler_name[256];
struct format_field *field;
struct tep_format_field *field;
unsigned long s, ns;
unsigned n = 0;
int pid;
@@ -867,22 +867,22 @@ static void python_process_tracepoint(struct perf_sample *sample,
unsigned int offset, len;
unsigned long long val;
if (field->flags & FIELD_IS_ARRAY) {
if (field->flags & TEP_FIELD_IS_ARRAY) {
offset = field->offset;
len = field->size;
if (field->flags & FIELD_IS_DYNAMIC) {
if (field->flags & TEP_FIELD_IS_DYNAMIC) {
val = tep_read_number(scripting_context->pevent,
data + offset, len);
offset = val;
len = offset >> 16;
offset &= 0xffff;
}
if (field->flags & FIELD_IS_STRING &&
if (field->flags & TEP_FIELD_IS_STRING &&
is_printable_array(data + offset, len)) {
obj = _PyUnicode_FromString((char *) data + offset);
} else {
obj = PyByteArray_FromStringAndSize((const char *) data + offset, len);
field->flags &= ~FIELD_IS_STRING;
field->flags &= ~TEP_FIELD_IS_STRING;
}
} else { /* FIELD_IS_NUMERIC */
obj = get_field_numeric_entry(event, field, data);
@@ -1590,8 +1590,8 @@ static int python_stop_script(void)
static int python_generate_script(struct tep_handle *pevent, const char *outfile)
{
struct event_format *event = NULL;
struct format_field *f;
struct tep_event_format *event = NULL;
struct tep_format_field *f;
char fname[PATH_MAX];
int not_first, count;
FILE *ofp;
@@ -1686,12 +1686,12 @@ static int python_generate_script(struct tep_handle *pevent, const char *outfile
count++;
fprintf(ofp, "%s=", f->name);
if (f->flags & FIELD_IS_STRING ||
f->flags & FIELD_IS_FLAG ||
f->flags & FIELD_IS_ARRAY ||
f->flags & FIELD_IS_SYMBOLIC)
if (f->flags & TEP_FIELD_IS_STRING ||
f->flags & TEP_FIELD_IS_FLAG ||
f->flags & TEP_FIELD_IS_ARRAY ||
f->flags & TEP_FIELD_IS_SYMBOLIC)
fprintf(ofp, "%%s");
else if (f->flags & FIELD_IS_SIGNED)
else if (f->flags & TEP_FIELD_IS_SIGNED)
fprintf(ofp, "%%d");
else
fprintf(ofp, "%%u");
@@ -1709,7 +1709,7 @@ static int python_generate_script(struct tep_handle *pevent, const char *outfile
if (++count % 5 == 0)
fprintf(ofp, "\n\t\t");
if (f->flags & FIELD_IS_FLAG) {
if (f->flags & TEP_FIELD_IS_FLAG) {
if ((count - 1) % 5 != 0) {
fprintf(ofp, "\n\t\t");
count = 4;
@@ -1719,7 +1719,7 @@ static int python_generate_script(struct tep_handle *pevent, const char *outfile
event->name);
fprintf(ofp, "\"%s\", %s)", f->name,
f->name);
} else if (f->flags & FIELD_IS_SYMBOLIC) {
} else if (f->flags & TEP_FIELD_IS_SYMBOLIC) {
if ((count - 1) % 5 != 0) {
fprintf(ofp, "\n\t\t");
count = 4;

View File

@@ -199,12 +199,10 @@ void perf_session__delete(struct perf_session *session)
free(session);
}
static int process_event_synth_tracing_data_stub(struct perf_tool *tool
static int process_event_synth_tracing_data_stub(struct perf_session *session
__maybe_unused,
union perf_event *event
__maybe_unused,
struct perf_session *session
__maybe_unused)
__maybe_unused)
{
dump_printf(": unhandled!\n");
return 0;
@@ -277,10 +275,8 @@ static int skipn(int fd, off_t n)
return 0;
}
static s64 process_event_auxtrace_stub(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_session *session
__maybe_unused)
static s64 process_event_auxtrace_stub(struct perf_session *session __maybe_unused,
union perf_event *event)
{
dump_printf(": unhandled!\n");
if (perf_data__is_pipe(session->data))
@@ -288,9 +284,8 @@ static s64 process_event_auxtrace_stub(struct perf_tool *tool __maybe_unused,
return event->auxtrace.size;
}
static int process_event_op2_stub(struct perf_tool *tool __maybe_unused,
union perf_event *event __maybe_unused,
struct perf_session *session __maybe_unused)
static int process_event_op2_stub(struct perf_session *session __maybe_unused,
union perf_event *event __maybe_unused)
{
dump_printf(": unhandled!\n");
return 0;
@@ -298,9 +293,8 @@ static int process_event_op2_stub(struct perf_tool *tool __maybe_unused,
static
int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused,
union perf_event *event __maybe_unused,
struct perf_session *session __maybe_unused)
int process_event_thread_map_stub(struct perf_session *session __maybe_unused,
union perf_event *event __maybe_unused)
{
if (dump_trace)
perf_event__fprintf_thread_map(event, stdout);
@@ -310,9 +304,8 @@ int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused,
}
static
int process_event_cpu_map_stub(struct perf_tool *tool __maybe_unused,
union perf_event *event __maybe_unused,
struct perf_session *session __maybe_unused)
int process_event_cpu_map_stub(struct perf_session *session __maybe_unused,
union perf_event *event __maybe_unused)
{
if (dump_trace)
perf_event__fprintf_cpu_map(event, stdout);
@@ -322,9 +315,8 @@ int process_event_cpu_map_stub(struct perf_tool *tool __maybe_unused,
}
static
int process_event_stat_config_stub(struct perf_tool *tool __maybe_unused,
union perf_event *event __maybe_unused,
struct perf_session *session __maybe_unused)
int process_event_stat_config_stub(struct perf_session *session __maybe_unused,
union perf_event *event __maybe_unused)
{
if (dump_trace)
perf_event__fprintf_stat_config(event, stdout);
@@ -333,10 +325,8 @@ int process_event_stat_config_stub(struct perf_tool *tool __maybe_unused,
return 0;
}
static int process_stat_stub(struct perf_tool *tool __maybe_unused,
union perf_event *event __maybe_unused,
struct perf_session *perf_session
__maybe_unused)
static int process_stat_stub(struct perf_session *perf_session __maybe_unused,
union perf_event *event)
{
if (dump_trace)
perf_event__fprintf_stat(event, stdout);
@@ -345,10 +335,8 @@ static int process_stat_stub(struct perf_tool *tool __maybe_unused,
return 0;
}
static int process_stat_round_stub(struct perf_tool *tool __maybe_unused,
union perf_event *event __maybe_unused,
struct perf_session *perf_session
__maybe_unused)
static int process_stat_round_stub(struct perf_session *perf_session __maybe_unused,
union perf_event *event)
{
if (dump_trace)
perf_event__fprintf_stat_round(event, stdout);
@@ -1374,37 +1362,37 @@ static s64 perf_session__process_user_event(struct perf_session *session,
case PERF_RECORD_HEADER_TRACING_DATA:
/* setup for reading amidst mmap */
lseek(fd, file_offset, SEEK_SET);
return tool->tracing_data(tool, event, session);
return tool->tracing_data(session, event);
case PERF_RECORD_HEADER_BUILD_ID:
return tool->build_id(tool, event, session);
return tool->build_id(session, event);
case PERF_RECORD_FINISHED_ROUND:
return tool->finished_round(tool, event, oe);
case PERF_RECORD_ID_INDEX:
return tool->id_index(tool, event, session);
return tool->id_index(session, event);
case PERF_RECORD_AUXTRACE_INFO:
return tool->auxtrace_info(tool, event, session);
return tool->auxtrace_info(session, event);
case PERF_RECORD_AUXTRACE:
/* setup for reading amidst mmap */
lseek(fd, file_offset + event->header.size, SEEK_SET);
return tool->auxtrace(tool, event, session);
return tool->auxtrace(session, event);
case PERF_RECORD_AUXTRACE_ERROR:
perf_session__auxtrace_error_inc(session, event);
return tool->auxtrace_error(tool, event, session);
return tool->auxtrace_error(session, event);
case PERF_RECORD_THREAD_MAP:
return tool->thread_map(tool, event, session);
return tool->thread_map(session, event);
case PERF_RECORD_CPU_MAP:
return tool->cpu_map(tool, event, session);
return tool->cpu_map(session, event);
case PERF_RECORD_STAT_CONFIG:
return tool->stat_config(tool, event, session);
return tool->stat_config(session, event);
case PERF_RECORD_STAT:
return tool->stat(tool, event, session);
return tool->stat(session, event);
case PERF_RECORD_STAT_ROUND:
return tool->stat_round(tool, event, session);
return tool->stat_round(session, event);
case PERF_RECORD_TIME_CONV:
session->time_conv = event->time_conv;
return tool->time_conv(tool, event, session);
return tool->time_conv(session, event);
case PERF_RECORD_HEADER_FEATURE:
return tool->feature(tool, event, session);
return tool->feature(session, event);
default:
return -EINVAL;
}
@@ -2133,9 +2121,8 @@ out:
return err;
}
int perf_event__process_id_index(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_session *session)
int perf_event__process_id_index(struct perf_session *session,
union perf_event *event)
{
struct perf_evlist *evlist = session->evlist;
struct id_index_event *ie = &event->id_index;

View File

@@ -120,9 +120,8 @@ int perf_session__deliver_synth_event(struct perf_session *session,
union perf_event *event,
struct perf_sample *sample);
int perf_event__process_id_index(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session);
int perf_event__process_id_index(struct perf_session *session,
union perf_event *event);
int perf_event__synthesize_id_index(struct perf_tool *tool,
perf_event__handler_t process,

View File

@@ -5,16 +5,18 @@ from subprocess import Popen, PIPE
from re import sub
def clang_has_option(option):
return [o for o in Popen(['clang', option], stderr=PIPE).stderr.readlines() if "unknown argument" in o] == [ ]
return [o for o in Popen(['clang', option], stderr=PIPE).stderr.readlines() if b"unknown argument" in o] == [ ]
cc = getenv("CC")
if cc == "clang":
from _sysconfigdata import build_time_vars
build_time_vars["CFLAGS"] = sub("-specs=[^ ]+", "", build_time_vars["CFLAGS"])
if not clang_has_option("-mcet"):
build_time_vars["CFLAGS"] = sub("-mcet", "", build_time_vars["CFLAGS"])
if not clang_has_option("-fcf-protection"):
build_time_vars["CFLAGS"] = sub("-fcf-protection", "", build_time_vars["CFLAGS"])
from distutils.sysconfig import get_config_vars
vars = get_config_vars()
for var in ('CFLAGS', 'OPT'):
vars[var] = sub("-specs=[^ ]+", "", vars[var])
if not clang_has_option("-mcet"):
vars[var] = sub("-mcet", "", vars[var])
if not clang_has_option("-fcf-protection"):
vars[var] = sub("-fcf-protection", "", vars[var])
from distutils.core import setup, Extension

View File

@@ -1884,7 +1884,7 @@ static int __sort_dimension__add_hpp_output(struct sort_dimension *sd,
struct hpp_dynamic_entry {
struct perf_hpp_fmt hpp;
struct perf_evsel *evsel;
struct format_field *field;
struct tep_format_field *field;
unsigned dynamic_len;
bool raw_trace;
};
@@ -1899,7 +1899,7 @@ static int hde_width(struct hpp_dynamic_entry *hde)
if (namelen > len)
len = namelen;
if (!(hde->field->flags & FIELD_IS_STRING)) {
if (!(hde->field->flags & TEP_FIELD_IS_STRING)) {
/* length for print hex numbers */
fieldlen = hde->field->size * 2 + 2;
}
@@ -1915,7 +1915,7 @@ static void update_dynamic_len(struct hpp_dynamic_entry *hde,
struct hist_entry *he)
{
char *str, *pos;
struct format_field *field = hde->field;
struct tep_format_field *field = hde->field;
size_t namelen;
bool last = false;
@@ -2000,7 +2000,7 @@ static int __sort__hde_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
struct hpp_dynamic_entry *hde;
size_t len = fmt->user_len;
char *str, *pos;
struct format_field *field;
struct tep_format_field *field;
size_t namelen;
bool last = false;
int ret;
@@ -2060,7 +2060,7 @@ static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt,
struct hist_entry *a, struct hist_entry *b)
{
struct hpp_dynamic_entry *hde;
struct format_field *field;
struct tep_format_field *field;
unsigned offset, size;
hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
@@ -2071,7 +2071,7 @@ static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt,
}
field = hde->field;
if (field->flags & FIELD_IS_DYNAMIC) {
if (field->flags & TEP_FIELD_IS_DYNAMIC) {
unsigned long long dyn;
tep_read_number_field(field, a->raw_data, &dyn);
@@ -2117,7 +2117,7 @@ static void hde_free(struct perf_hpp_fmt *fmt)
}
static struct hpp_dynamic_entry *
__alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field,
__alloc_dynamic_entry(struct perf_evsel *evsel, struct tep_format_field *field,
int level)
{
struct hpp_dynamic_entry *hde;
@@ -2252,7 +2252,7 @@ static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_nam
}
static int __dynamic_dimension__add(struct perf_evsel *evsel,
struct format_field *field,
struct tep_format_field *field,
bool raw_trace, int level)
{
struct hpp_dynamic_entry *hde;
@@ -2270,7 +2270,7 @@ static int __dynamic_dimension__add(struct perf_evsel *evsel,
static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace, int level)
{
int ret;
struct format_field *field;
struct tep_format_field *field;
field = evsel->tp_format->format.fields;
while (field) {
@@ -2305,7 +2305,7 @@ static int add_all_matching_fields(struct perf_evlist *evlist,
{
int ret = -ESRCH;
struct perf_evsel *evsel;
struct format_field *field;
struct tep_format_field *field;
evlist__for_each_entry(evlist, evsel) {
if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
@@ -2327,7 +2327,7 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok,
{
char *str, *event_name, *field_name, *opt_name;
struct perf_evsel *evsel;
struct format_field *field;
struct tep_format_field *field;
bool raw_trace = symbol_conf.raw_trace;
int ret = 0;

File diff suppressed because it is too large Load Diff

View File

@@ -410,7 +410,8 @@ static double runtime_stat_n(struct runtime_stat *st,
return v->stats.n;
}
static void print_stalled_cycles_frontend(int cpu,
static void print_stalled_cycles_frontend(struct perf_stat_config *config,
int cpu,
struct perf_evsel *evsel, double avg,
struct perf_stat_output_ctx *out,
struct runtime_stat *st)
@@ -427,13 +428,14 @@ static void print_stalled_cycles_frontend(int cpu,
color = get_ratio_color(GRC_STALLED_CYCLES_FE, ratio);
if (ratio)
out->print_metric(out->ctx, color, "%7.2f%%", "frontend cycles idle",
out->print_metric(config, out->ctx, color, "%7.2f%%", "frontend cycles idle",
ratio);
else
out->print_metric(out->ctx, NULL, NULL, "frontend cycles idle", 0);
out->print_metric(config, out->ctx, NULL, NULL, "frontend cycles idle", 0);
}
static void print_stalled_cycles_backend(int cpu,
static void print_stalled_cycles_backend(struct perf_stat_config *config,
int cpu,
struct perf_evsel *evsel, double avg,
struct perf_stat_output_ctx *out,
struct runtime_stat *st)
@@ -449,10 +451,11 @@ static void print_stalled_cycles_backend(int cpu,
color = get_ratio_color(GRC_STALLED_CYCLES_BE, ratio);
out->print_metric(out->ctx, color, "%7.2f%%", "backend cycles idle", ratio);
out->print_metric(config, out->ctx, color, "%7.2f%%", "backend cycles idle", ratio);
}
static void print_branch_misses(int cpu,
static void print_branch_misses(struct perf_stat_config *config,
int cpu,
struct perf_evsel *evsel,
double avg,
struct perf_stat_output_ctx *out,
@@ -469,10 +472,11 @@ static void print_branch_misses(int cpu,
color = get_ratio_color(GRC_CACHE_MISSES, ratio);
out->print_metric(out->ctx, color, "%7.2f%%", "of all branches", ratio);
out->print_metric(config, out->ctx, color, "%7.2f%%", "of all branches", ratio);
}
static void print_l1_dcache_misses(int cpu,
static void print_l1_dcache_misses(struct perf_stat_config *config,
int cpu,
struct perf_evsel *evsel,
double avg,
struct perf_stat_output_ctx *out,
@@ -490,10 +494,11 @@ static void print_l1_dcache_misses(int cpu,
color = get_ratio_color(GRC_CACHE_MISSES, ratio);
out->print_metric(out->ctx, color, "%7.2f%%", "of all L1-dcache hits", ratio);
out->print_metric(config, out->ctx, color, "%7.2f%%", "of all L1-dcache hits", ratio);
}
static void print_l1_icache_misses(int cpu,
static void print_l1_icache_misses(struct perf_stat_config *config,
int cpu,
struct perf_evsel *evsel,
double avg,
struct perf_stat_output_ctx *out,
@@ -510,10 +515,11 @@ static void print_l1_icache_misses(int cpu,
ratio = avg / total * 100.0;
color = get_ratio_color(GRC_CACHE_MISSES, ratio);
out->print_metric(out->ctx, color, "%7.2f%%", "of all L1-icache hits", ratio);
out->print_metric(config, out->ctx, color, "%7.2f%%", "of all L1-icache hits", ratio);
}
static void print_dtlb_cache_misses(int cpu,
static void print_dtlb_cache_misses(struct perf_stat_config *config,
int cpu,
struct perf_evsel *evsel,
double avg,
struct perf_stat_output_ctx *out,
@@ -529,10 +535,11 @@ static void print_dtlb_cache_misses(int cpu,
ratio = avg / total * 100.0;
color = get_ratio_color(GRC_CACHE_MISSES, ratio);
out->print_metric(out->ctx, color, "%7.2f%%", "of all dTLB cache hits", ratio);
out->print_metric(config, out->ctx, color, "%7.2f%%", "of all dTLB cache hits", ratio);
}
static void print_itlb_cache_misses(int cpu,
static void print_itlb_cache_misses(struct perf_stat_config *config,
int cpu,
struct perf_evsel *evsel,
double avg,
struct perf_stat_output_ctx *out,
@@ -548,10 +555,11 @@ static void print_itlb_cache_misses(int cpu,
ratio = avg / total * 100.0;
color = get_ratio_color(GRC_CACHE_MISSES, ratio);
out->print_metric(out->ctx, color, "%7.2f%%", "of all iTLB cache hits", ratio);
out->print_metric(config, out->ctx, color, "%7.2f%%", "of all iTLB cache hits", ratio);
}
static void print_ll_cache_misses(int cpu,
static void print_ll_cache_misses(struct perf_stat_config *config,
int cpu,
struct perf_evsel *evsel,
double avg,
struct perf_stat_output_ctx *out,
@@ -567,7 +575,7 @@ static void print_ll_cache_misses(int cpu,
ratio = avg / total * 100.0;
color = get_ratio_color(GRC_CACHE_MISSES, ratio);
out->print_metric(out->ctx, color, "%7.2f%%", "of all LL-cache hits", ratio);
out->print_metric(config, out->ctx, color, "%7.2f%%", "of all LL-cache hits", ratio);
}
/*
@@ -674,7 +682,8 @@ static double td_be_bound(int ctx, int cpu, struct runtime_stat *st)
return sanitize_val(1.0 - sum);
}
static void print_smi_cost(int cpu, struct perf_evsel *evsel,
static void print_smi_cost(struct perf_stat_config *config,
int cpu, struct perf_evsel *evsel,
struct perf_stat_output_ctx *out,
struct runtime_stat *st)
{
@@ -694,11 +703,12 @@ static void print_smi_cost(int cpu, struct perf_evsel *evsel,
if (cost > 10)
color = PERF_COLOR_RED;
out->print_metric(out->ctx, color, "%8.1f%%", "SMI cycles%", cost);
out->print_metric(out->ctx, NULL, "%4.0f", "SMI#", smi_num);
out->print_metric(config, out->ctx, color, "%8.1f%%", "SMI cycles%", cost);
out->print_metric(config, out->ctx, NULL, "%4.0f", "SMI#", smi_num);
}
static void generic_metric(const char *metric_expr,
static void generic_metric(struct perf_stat_config *config,
const char *metric_expr,
struct perf_evsel **metric_events,
char *name,
const char *metric_name,
@@ -737,20 +747,21 @@ static void generic_metric(const char *metric_expr,
const char *p = metric_expr;
if (expr__parse(&ratio, &pctx, &p) == 0)
print_metric(ctxp, NULL, "%8.1f",
print_metric(config, ctxp, NULL, "%8.1f",
metric_name ?
metric_name :
out->force_header ? name : "",
ratio);
else
print_metric(ctxp, NULL, NULL,
print_metric(config, ctxp, NULL, NULL,
out->force_header ?
(metric_name ? metric_name : name) : "", 0);
} else
print_metric(ctxp, NULL, NULL, "", 0);
print_metric(config, ctxp, NULL, NULL, "", 0);
}
void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
void perf_stat__print_shadow_stats(struct perf_stat_config *config,
struct perf_evsel *evsel,
double avg, int cpu,
struct perf_stat_output_ctx *out,
struct rblist *metric_events,
@@ -769,10 +780,10 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
if (total) {
ratio = avg / total;
print_metric(ctxp, NULL, "%7.2f ",
print_metric(config, ctxp, NULL, "%7.2f ",
"insn per cycle", ratio);
} else {
print_metric(ctxp, NULL, NULL, "insn per cycle", 0);
print_metric(config, ctxp, NULL, NULL, "insn per cycle", 0);
}
total = runtime_stat_avg(st, STAT_STALLED_CYCLES_FRONT,
@@ -783,20 +794,20 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
ctx, cpu));
if (total && avg) {
out->new_line(ctxp);
out->new_line(config, ctxp);
ratio = total / avg;
print_metric(ctxp, NULL, "%7.2f ",
print_metric(config, ctxp, NULL, "%7.2f ",
"stalled cycles per insn",
ratio);
} else if (have_frontend_stalled) {
print_metric(ctxp, NULL, NULL,
print_metric(config, ctxp, NULL, NULL,
"stalled cycles per insn", 0);
}
} else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES)) {
if (runtime_stat_n(st, STAT_BRANCHES, ctx, cpu) != 0)
print_branch_misses(cpu, evsel, avg, out, st);
print_branch_misses(config, cpu, evsel, avg, out, st);
else
print_metric(ctxp, NULL, NULL, "of all branches", 0);
print_metric(config, ctxp, NULL, NULL, "of all branches", 0);
} else if (
evsel->attr.type == PERF_TYPE_HW_CACHE &&
evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1D |
@@ -804,9 +815,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
if (runtime_stat_n(st, STAT_L1_DCACHE, ctx, cpu) != 0)
print_l1_dcache_misses(cpu, evsel, avg, out, st);
print_l1_dcache_misses(config, cpu, evsel, avg, out, st);
else
print_metric(ctxp, NULL, NULL, "of all L1-dcache hits", 0);
print_metric(config, ctxp, NULL, NULL, "of all L1-dcache hits", 0);
} else if (
evsel->attr.type == PERF_TYPE_HW_CACHE &&
evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1I |
@@ -814,9 +825,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
if (runtime_stat_n(st, STAT_L1_ICACHE, ctx, cpu) != 0)
print_l1_icache_misses(cpu, evsel, avg, out, st);
print_l1_icache_misses(config, cpu, evsel, avg, out, st);
else
print_metric(ctxp, NULL, NULL, "of all L1-icache hits", 0);
print_metric(config, ctxp, NULL, NULL, "of all L1-icache hits", 0);
} else if (
evsel->attr.type == PERF_TYPE_HW_CACHE &&
evsel->attr.config == ( PERF_COUNT_HW_CACHE_DTLB |
@@ -824,9 +835,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
if (runtime_stat_n(st, STAT_DTLB_CACHE, ctx, cpu) != 0)
print_dtlb_cache_misses(cpu, evsel, avg, out, st);
print_dtlb_cache_misses(config, cpu, evsel, avg, out, st);
else
print_metric(ctxp, NULL, NULL, "of all dTLB cache hits", 0);
print_metric(config, ctxp, NULL, NULL, "of all dTLB cache hits", 0);
} else if (
evsel->attr.type == PERF_TYPE_HW_CACHE &&
evsel->attr.config == ( PERF_COUNT_HW_CACHE_ITLB |
@@ -834,9 +845,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
if (runtime_stat_n(st, STAT_ITLB_CACHE, ctx, cpu) != 0)
print_itlb_cache_misses(cpu, evsel, avg, out, st);
print_itlb_cache_misses(config, cpu, evsel, avg, out, st);
else
print_metric(ctxp, NULL, NULL, "of all iTLB cache hits", 0);
print_metric(config, ctxp, NULL, NULL, "of all iTLB cache hits", 0);
} else if (
evsel->attr.type == PERF_TYPE_HW_CACHE &&
evsel->attr.config == ( PERF_COUNT_HW_CACHE_LL |
@@ -844,9 +855,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
if (runtime_stat_n(st, STAT_LL_CACHE, ctx, cpu) != 0)
print_ll_cache_misses(cpu, evsel, avg, out, st);
print_ll_cache_misses(config, cpu, evsel, avg, out, st);
else
print_metric(ctxp, NULL, NULL, "of all LL-cache hits", 0);
print_metric(config, ctxp, NULL, NULL, "of all LL-cache hits", 0);
} else if (perf_evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)) {
total = runtime_stat_avg(st, STAT_CACHEREFS, ctx, cpu);
@@ -854,32 +865,32 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
ratio = avg * 100 / total;
if (runtime_stat_n(st, STAT_CACHEREFS, ctx, cpu) != 0)
print_metric(ctxp, NULL, "%8.3f %%",
print_metric(config, ctxp, NULL, "%8.3f %%",
"of all cache refs", ratio);
else
print_metric(ctxp, NULL, NULL, "of all cache refs", 0);
print_metric(config, ctxp, NULL, NULL, "of all cache refs", 0);
} else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) {
print_stalled_cycles_frontend(cpu, evsel, avg, out, st);
print_stalled_cycles_frontend(config, cpu, evsel, avg, out, st);
} else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_BACKEND)) {
print_stalled_cycles_backend(cpu, evsel, avg, out, st);
print_stalled_cycles_backend(config, cpu, evsel, avg, out, st);
} else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) {
total = runtime_stat_avg(st, STAT_NSECS, 0, cpu);
if (total) {
ratio = avg / total;
print_metric(ctxp, NULL, "%8.3f", "GHz", ratio);
print_metric(config, ctxp, NULL, "%8.3f", "GHz", ratio);
} else {
print_metric(ctxp, NULL, NULL, "Ghz", 0);
print_metric(config, ctxp, NULL, NULL, "Ghz", 0);
}
} else if (perf_stat_evsel__is(evsel, CYCLES_IN_TX)) {
total = runtime_stat_avg(st, STAT_CYCLES, ctx, cpu);
if (total)
print_metric(ctxp, NULL,
print_metric(config, ctxp, NULL,
"%7.2f%%", "transactional cycles",
100.0 * (avg / total));
else
print_metric(ctxp, NULL, NULL, "transactional cycles",
print_metric(config, ctxp, NULL, NULL, "transactional cycles",
0);
} else if (perf_stat_evsel__is(evsel, CYCLES_IN_TX_CP)) {
total = runtime_stat_avg(st, STAT_CYCLES, ctx, cpu);
@@ -888,10 +899,10 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
if (total2 < avg)
total2 = avg;
if (total)
print_metric(ctxp, NULL, "%7.2f%%", "aborted cycles",
print_metric(config, ctxp, NULL, "%7.2f%%", "aborted cycles",
100.0 * ((total2-avg) / total));
else
print_metric(ctxp, NULL, NULL, "aborted cycles", 0);
print_metric(config, ctxp, NULL, NULL, "aborted cycles", 0);
} else if (perf_stat_evsel__is(evsel, TRANSACTION_START)) {
total = runtime_stat_avg(st, STAT_CYCLES_IN_TX,
ctx, cpu);
@@ -900,10 +911,10 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
ratio = total / avg;
if (runtime_stat_n(st, STAT_CYCLES_IN_TX, ctx, cpu) != 0)
print_metric(ctxp, NULL, "%8.0f",
print_metric(config, ctxp, NULL, "%8.0f",
"cycles / transaction", ratio);
else
print_metric(ctxp, NULL, NULL, "cycles / transaction",
print_metric(config, ctxp, NULL, NULL, "cycles / transaction",
0);
} else if (perf_stat_evsel__is(evsel, ELISION_START)) {
total = runtime_stat_avg(st, STAT_CYCLES_IN_TX,
@@ -912,33 +923,33 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
if (avg)
ratio = total / avg;
print_metric(ctxp, NULL, "%8.0f", "cycles / elision", ratio);
print_metric(config, ctxp, NULL, "%8.0f", "cycles / elision", ratio);
} else if (perf_evsel__is_clock(evsel)) {
if ((ratio = avg_stats(&walltime_nsecs_stats)) != 0)
print_metric(ctxp, NULL, "%8.3f", "CPUs utilized",
print_metric(config, ctxp, NULL, "%8.3f", "CPUs utilized",
avg / (ratio * evsel->scale));
else
print_metric(ctxp, NULL, NULL, "CPUs utilized", 0);
print_metric(config, ctxp, NULL, NULL, "CPUs utilized", 0);
} else if (perf_stat_evsel__is(evsel, TOPDOWN_FETCH_BUBBLES)) {
double fe_bound = td_fe_bound(ctx, cpu, st);
if (fe_bound > 0.2)
color = PERF_COLOR_RED;
print_metric(ctxp, color, "%8.1f%%", "frontend bound",
print_metric(config, ctxp, color, "%8.1f%%", "frontend bound",
fe_bound * 100.);
} else if (perf_stat_evsel__is(evsel, TOPDOWN_SLOTS_RETIRED)) {
double retiring = td_retiring(ctx, cpu, st);
if (retiring > 0.7)
color = PERF_COLOR_GREEN;
print_metric(ctxp, color, "%8.1f%%", "retiring",
print_metric(config, ctxp, color, "%8.1f%%", "retiring",
retiring * 100.);
} else if (perf_stat_evsel__is(evsel, TOPDOWN_RECOVERY_BUBBLES)) {
double bad_spec = td_bad_spec(ctx, cpu, st);
if (bad_spec > 0.1)
color = PERF_COLOR_RED;
print_metric(ctxp, color, "%8.1f%%", "bad speculation",
print_metric(config, ctxp, color, "%8.1f%%", "bad speculation",
bad_spec * 100.);
} else if (perf_stat_evsel__is(evsel, TOPDOWN_SLOTS_ISSUED)) {
double be_bound = td_be_bound(ctx, cpu, st);
@@ -955,12 +966,12 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
if (be_bound > 0.2)
color = PERF_COLOR_RED;
if (td_total_slots(ctx, cpu, st) > 0)
print_metric(ctxp, color, "%8.1f%%", name,
print_metric(config, ctxp, color, "%8.1f%%", name,
be_bound * 100.);
else
print_metric(ctxp, NULL, NULL, name, 0);
print_metric(config, ctxp, NULL, NULL, name, 0);
} else if (evsel->metric_expr) {
generic_metric(evsel->metric_expr, evsel->metric_events, evsel->name,
generic_metric(config, evsel->metric_expr, evsel->metric_events, evsel->name,
evsel->metric_name, avg, cpu, out, st);
} else if (runtime_stat_n(st, STAT_NSECS, 0, cpu) != 0) {
char unit = 'M';
@@ -975,9 +986,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
unit = 'K';
}
snprintf(unit_buf, sizeof(unit_buf), "%c/sec", unit);
print_metric(ctxp, NULL, "%8.3f", unit_buf, ratio);
print_metric(config, ctxp, NULL, "%8.3f", unit_buf, ratio);
} else if (perf_stat_evsel__is(evsel, SMI_NUM)) {
print_smi_cost(cpu, evsel, out, st);
print_smi_cost(config, cpu, evsel, out, st);
} else {
num = 0;
}
@@ -987,12 +998,12 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
list_for_each_entry (mexp, &me->head, nd) {
if (num++ > 0)
out->new_line(ctxp);
generic_metric(mexp->metric_expr, mexp->metric_events,
out->new_line(config, ctxp);
generic_metric(config, mexp->metric_expr, mexp->metric_events,
evsel->name, mexp->metric_name,
avg, cpu, out, st);
}
}
if (num == 0)
print_metric(ctxp, NULL, NULL, NULL, 0);
print_metric(config, ctxp, NULL, NULL, NULL, 0);
}

View File

@@ -374,9 +374,8 @@ int perf_stat_process_counter(struct perf_stat_config *config,
return 0;
}
int perf_event__process_stat_event(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_session *session)
int perf_event__process_stat_event(struct perf_session *session,
union perf_event *event)
{
struct perf_counts_values count;
struct stat_event *st = &event->stat;
@@ -435,3 +434,98 @@ size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp)
return ret;
}
int create_perf_stat_counter(struct perf_evsel *evsel,
struct perf_stat_config *config,
struct target *target)
{
struct perf_event_attr *attr = &evsel->attr;
struct perf_evsel *leader = evsel->leader;
if (config->scale) {
attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
PERF_FORMAT_TOTAL_TIME_RUNNING;
}
/*
* The event is part of non trivial group, let's enable
* the group read (for leader) and ID retrieval for all
* members.
*/
if (leader->nr_members > 1)
attr->read_format |= PERF_FORMAT_ID|PERF_FORMAT_GROUP;
attr->inherit = !config->no_inherit;
/*
* Some events get initialized with sample_(period/type) set,
* like tracepoints. Clear it up for counting.
*/
attr->sample_period = 0;
if (config->identifier)
attr->sample_type = PERF_SAMPLE_IDENTIFIER;
/*
* Disabling all counters initially, they will be enabled
* either manually by us or by kernel via enable_on_exec
* set later.
*/
if (perf_evsel__is_group_leader(evsel)) {
attr->disabled = 1;
/*
* In case of initial_delay we enable tracee
* events manually.
*/
if (target__none(target) && !config->initial_delay)
attr->enable_on_exec = 1;
}
if (target__has_cpu(target) && !target__has_per_thread(target))
return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
return perf_evsel__open_per_thread(evsel, evsel->threads);
}
int perf_stat_synthesize_config(struct perf_stat_config *config,
struct perf_tool *tool,
struct perf_evlist *evlist,
perf_event__handler_t process,
bool attrs)
{
int err;
if (attrs) {
err = perf_event__synthesize_attrs(tool, evlist, process);
if (err < 0) {
pr_err("Couldn't synthesize attrs.\n");
return err;
}
}
err = perf_event__synthesize_extra_attr(tool, evlist, process,
attrs);
err = perf_event__synthesize_thread_map2(tool, evlist->threads,
process, NULL);
if (err < 0) {
pr_err("Couldn't synthesize thread map.\n");
return err;
}
err = perf_event__synthesize_cpu_map(tool, evlist->cpus,
process, NULL);
if (err < 0) {
pr_err("Couldn't synthesize thread map.\n");
return err;
}
err = perf_event__synthesize_stat_config(tool, config, process, NULL);
if (err < 0) {
pr_err("Couldn't synthesize config.\n");
return err;
}
return 0;
}

View File

@@ -4,8 +4,14 @@
#include <linux/types.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include "xyarray.h"
#include "rblist.h"
#include "perf.h"
#include "event.h"
struct stats {
double n, mean, M2;
@@ -84,15 +90,42 @@ struct runtime_stat {
struct rblist value_list;
};
typedef int (*aggr_get_id_t)(struct perf_stat_config *config,
struct cpu_map *m, int cpu);
struct perf_stat_config {
enum aggr_mode aggr_mode;
bool scale;
FILE *output;
unsigned int interval;
unsigned int timeout;
int times;
struct runtime_stat *stats;
int stats_num;
enum aggr_mode aggr_mode;
bool scale;
bool no_inherit;
bool identifier;
bool csv_output;
bool interval_clear;
bool metric_only;
bool null_run;
bool ru_display;
bool big_num;
bool no_merge;
bool walltime_run_table;
FILE *output;
unsigned int interval;
unsigned int timeout;
unsigned int initial_delay;
unsigned int unit_width;
unsigned int metric_only_len;
int times;
int run_count;
int print_free_counters_hint;
int print_mixed_hw_group_error;
struct runtime_stat *stats;
int stats_num;
const char *csv_sep;
struct stats *walltime_nsecs_stats;
struct rusage ru_data;
struct cpu_map *aggr_map;
aggr_get_id_t aggr_get_id;
struct cpu_map *cpus_aggr_map;
u64 *walltime_run;
struct rblist metric_events;
};
void update_stats(struct stats *stats, u64 val);
@@ -130,9 +163,10 @@ bool __perf_evsel_stat__is(struct perf_evsel *evsel,
extern struct runtime_stat rt_stat;
extern struct stats walltime_nsecs_stats;
typedef void (*print_metric_t)(void *ctx, const char *color, const char *unit,
typedef void (*print_metric_t)(struct perf_stat_config *config,
void *ctx, const char *color, const char *unit,
const char *fmt, double val);
typedef void (*new_line_t )(void *ctx);
typedef void (*new_line_t)(struct perf_stat_config *config, void *ctx);
void runtime_stat__init(struct runtime_stat *st);
void runtime_stat__exit(struct runtime_stat *st);
@@ -148,7 +182,8 @@ struct perf_stat_output_ctx {
bool force_header;
};
void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
void perf_stat__print_shadow_stats(struct perf_stat_config *config,
struct perf_evsel *evsel,
double avg, int cpu,
struct perf_stat_output_ctx *out,
struct rblist *metric_events,
@@ -164,11 +199,25 @@ int perf_stat_process_counter(struct perf_stat_config *config,
struct perf_tool;
union perf_event;
struct perf_session;
int perf_event__process_stat_event(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session);
int perf_event__process_stat_event(struct perf_session *session,
union perf_event *event);
size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp);
int create_perf_stat_counter(struct perf_evsel *evsel,
struct perf_stat_config *config,
struct target *target);
int perf_stat_synthesize_config(struct perf_stat_config *config,
struct perf_tool *tool,
struct perf_evlist *evlist,
perf_event__handler_t process,
bool attrs);
void
perf_evlist__print_counters(struct perf_evlist *evlist,
struct perf_stat_config *config,
struct target *_target,
struct timespec *ts,
int argc, const char **argv);
#endif

View File

@@ -98,19 +98,25 @@ static int strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap)
va_copy(ap_saved, ap);
len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
if (len < 0)
if (len < 0) {
va_end(ap_saved);
return len;
}
if (len > strbuf_avail(sb)) {
ret = strbuf_grow(sb, len);
if (ret)
if (ret) {
va_end(ap_saved);
return ret;
}
len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved);
va_end(ap_saved);
if (len > strbuf_avail(sb)) {
pr_debug("this should not happen, your vsnprintf is broken");
va_end(ap_saved);
return -EINVAL;
}
}
va_end(ap_saved);
return strbuf_setlen(sb, sb->len + len);
}

View File

@@ -36,6 +36,7 @@
* @branch_count: the branch count when the entry was created
* @cp: call path
* @no_call: a 'call' was not seen
* @trace_end: a 'call' but trace ended
*/
struct thread_stack_entry {
u64 ret_addr;
@@ -44,6 +45,7 @@ struct thread_stack_entry {
u64 branch_count;
struct call_path *cp;
bool no_call;
bool trace_end;
};
/**
@@ -112,7 +114,8 @@ static struct thread_stack *thread_stack__new(struct thread *thread,
return ts;
}
static int thread_stack__push(struct thread_stack *ts, u64 ret_addr)
static int thread_stack__push(struct thread_stack *ts, u64 ret_addr,
bool trace_end)
{
int err = 0;
@@ -124,6 +127,7 @@ static int thread_stack__push(struct thread_stack *ts, u64 ret_addr)
}
}
ts->stack[ts->cnt].trace_end = trace_end;
ts->stack[ts->cnt++].ret_addr = ret_addr;
return err;
@@ -150,6 +154,18 @@ static void thread_stack__pop(struct thread_stack *ts, u64 ret_addr)
}
}
static void thread_stack__pop_trace_end(struct thread_stack *ts)
{
size_t i;
for (i = ts->cnt; i; ) {
if (ts->stack[--i].trace_end)
ts->cnt = i;
else
return;
}
}
static bool thread_stack__in_kernel(struct thread_stack *ts)
{
if (!ts->cnt)
@@ -254,10 +270,19 @@ int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
ret_addr = from_ip + insn_len;
if (ret_addr == to_ip)
return 0; /* Zero-length calls are excluded */
return thread_stack__push(thread->ts, ret_addr);
} else if (flags & PERF_IP_FLAG_RETURN) {
if (!from_ip)
return 0;
return thread_stack__push(thread->ts, ret_addr,
flags & PERF_IP_FLAG_TRACE_END);
} else if (flags & PERF_IP_FLAG_TRACE_BEGIN) {
/*
* If the caller did not change the trace number (which would
* have flushed the stack) then try to make sense of the stack.
* Possibly, tracing began after returning to the current
* address, so try to pop that. Also, do not expect a call made
* when the trace ended, to return, so pop that.
*/
thread_stack__pop(thread->ts, to_ip);
thread_stack__pop_trace_end(thread->ts);
} else if ((flags & PERF_IP_FLAG_RETURN) && from_ip) {
thread_stack__pop(thread->ts, to_ip);
}
@@ -332,7 +357,7 @@ void call_return_processor__free(struct call_return_processor *crp)
static int thread_stack__push_cp(struct thread_stack *ts, u64 ret_addr,
u64 timestamp, u64 ref, struct call_path *cp,
bool no_call)
bool no_call, bool trace_end)
{
struct thread_stack_entry *tse;
int err;
@@ -350,6 +375,7 @@ static int thread_stack__push_cp(struct thread_stack *ts, u64 ret_addr,
tse->branch_count = ts->branch_count;
tse->cp = cp;
tse->no_call = no_call;
tse->trace_end = trace_end;
return 0;
}
@@ -423,7 +449,7 @@ static int thread_stack__bottom(struct thread *thread, struct thread_stack *ts,
return -ENOMEM;
return thread_stack__push_cp(thread->ts, ip, sample->time, ref, cp,
true);
true, false);
}
static int thread_stack__no_call_return(struct thread *thread,
@@ -455,7 +481,7 @@ static int thread_stack__no_call_return(struct thread *thread,
if (!cp)
return -ENOMEM;
return thread_stack__push_cp(ts, 0, sample->time, ref,
cp, true);
cp, true, false);
}
} else if (thread_stack__in_kernel(ts) && sample->ip < ks) {
/* Return to userspace, so pop all kernel addresses */
@@ -480,7 +506,7 @@ static int thread_stack__no_call_return(struct thread *thread,
return -ENOMEM;
err = thread_stack__push_cp(ts, sample->addr, sample->time, ref, cp,
true);
true, false);
if (err)
return err;
@@ -500,7 +526,7 @@ static int thread_stack__trace_begin(struct thread *thread,
/* Pop trace end */
tse = &ts->stack[ts->cnt - 1];
if (tse->cp->sym == NULL && tse->cp->ip == 0) {
if (tse->trace_end) {
err = thread_stack__call_return(thread, ts, --ts->cnt,
timestamp, ref, false);
if (err)
@@ -529,7 +555,7 @@ static int thread_stack__trace_end(struct thread_stack *ts,
ret_addr = sample->ip + sample->insn_len;
return thread_stack__push_cp(ts, ret_addr, sample->time, ref, cp,
false);
false, true);
}
int thread_stack__process(struct thread *thread, struct comm *comm,
@@ -579,6 +605,7 @@ int thread_stack__process(struct thread *thread, struct comm *comm,
ts->last_time = sample->time;
if (sample->flags & PERF_IP_FLAG_CALL) {
bool trace_end = sample->flags & PERF_IP_FLAG_TRACE_END;
struct call_path_root *cpr = ts->crp->cpr;
struct call_path *cp;
u64 ret_addr;
@@ -596,7 +623,7 @@ int thread_stack__process(struct thread *thread, struct comm *comm,
if (!cp)
return -ENOMEM;
err = thread_stack__push_cp(ts, ret_addr, sample->time, ref,
cp, false);
cp, false, trace_end);
} else if (sample->flags & PERF_IP_FLAG_RETURN) {
if (!sample->ip || !sample->addr)
return 0;

View File

@@ -26,15 +26,12 @@ typedef int (*event_attr_op)(struct perf_tool *tool,
union perf_event *event,
struct perf_evlist **pevlist);
typedef int (*event_op2)(struct perf_tool *tool, union perf_event *event,
struct perf_session *session);
typedef int (*event_op2)(struct perf_session *session, union perf_event *event);
typedef s64 (*event_op3)(struct perf_session *session, union perf_event *event);
typedef int (*event_oe)(struct perf_tool *tool, union perf_event *event,
struct ordered_events *oe);
typedef s64 (*event_op3)(struct perf_tool *tool, union perf_event *event,
struct perf_session *session);
enum show_feature_header {
SHOW_FEAT_NO_HEADER = 0,
SHOW_FEAT_HEADER,

View File

@@ -531,12 +531,14 @@ struct tracing_data *tracing_data_get(struct list_head *pattrs,
"/tmp/perf-XXXXXX");
if (!mkstemp(tdata->temp_file)) {
pr_debug("Can't make temp file");
free(tdata);
return NULL;
}
temp_fd = open(tdata->temp_file, O_RDWR);
if (temp_fd < 0) {
pr_debug("Can't read '%s'", tdata->temp_file);
free(tdata);
return NULL;
}

View File

@@ -33,14 +33,15 @@ static int get_common_field(struct scripting_context *context,
int *offset, int *size, const char *type)
{
struct tep_handle *pevent = context->pevent;
struct event_format *event;
struct format_field *field;
struct tep_event_format *event;
struct tep_format_field *field;
if (!*size) {
if (!pevent->events)
event = tep_get_first_event(pevent);
if (!event)
return 0;
event = pevent->events[0];
field = tep_find_common_field(event, type);
if (!field)
return 0;
@@ -94,9 +95,9 @@ int common_pc(struct scripting_context *context)
}
unsigned long long
raw_field_value(struct event_format *event, const char *name, void *data)
raw_field_value(struct tep_event_format *event, const char *name, void *data)
{
struct format_field *field;
struct tep_format_field *field;
unsigned long long val;
field = tep_find_any_field(event, name);
@@ -108,12 +109,12 @@ raw_field_value(struct event_format *event, const char *name, void *data)
return val;
}
unsigned long long read_size(struct event_format *event, void *ptr, int size)
unsigned long long read_size(struct tep_event_format *event, void *ptr, int size)
{
return tep_read_number(event->pevent, ptr, size);
}
void event_format__fprintf(struct event_format *event,
void event_format__fprintf(struct tep_event_format *event,
int cpu, void *data, int size, FILE *fp)
{
struct tep_record record;
@@ -130,7 +131,7 @@ void event_format__fprintf(struct event_format *event,
trace_seq_destroy(&s);
}
void event_format__print(struct event_format *event,
void event_format__print(struct tep_event_format *event,
int cpu, void *data, int size)
{
return event_format__fprintf(event, cpu, data, size, stdout);
@@ -158,6 +159,7 @@ void parse_ftrace_printk(struct tep_handle *pevent,
printk = strdup(fmt+1);
line = strtok_r(NULL, "\n", &next);
tep_register_print_string(pevent, printk, addr);
free(printk);
}
}
@@ -188,29 +190,33 @@ int parse_event_file(struct tep_handle *pevent,
return tep_parse_event(pevent, buf, size, sys);
}
struct event_format *trace_find_next_event(struct tep_handle *pevent,
struct event_format *event)
struct tep_event_format *trace_find_next_event(struct tep_handle *pevent,
struct tep_event_format *event)
{
static int idx;
int events_count;
struct tep_event_format *all_events;
if (!pevent || !pevent->events)
all_events = tep_get_first_event(pevent);
events_count = tep_get_events_count(pevent);
if (!pevent || !all_events || events_count < 1)
return NULL;
if (!event) {
idx = 0;
return pevent->events[0];
return all_events;
}
if (idx < pevent->nr_events && event == pevent->events[idx]) {
if (idx < events_count && event == (all_events + idx)) {
idx++;
if (idx == pevent->nr_events)
if (idx == events_count)
return NULL;
return pevent->events[idx];
return (all_events + idx);
}
for (idx = 1; idx < pevent->nr_events; idx++) {
if (event == pevent->events[idx - 1])
return pevent->events[idx];
for (idx = 1; idx < events_count; idx++) {
if (event == (all_events + (idx - 1)))
return (all_events + idx);
}
return NULL;
}

View File

@@ -102,7 +102,7 @@ static unsigned int read4(struct tep_handle *pevent)
if (do_read(&data, 4) < 0)
return 0;
return __data2host4(pevent, data);
return __tep_data2host4(pevent, data);
}
static unsigned long long read8(struct tep_handle *pevent)
@@ -111,7 +111,7 @@ static unsigned long long read8(struct tep_handle *pevent)
if (do_read(&data, 8) < 0)
return 0;
return __data2host8(pevent, data);
return __tep_data2host8(pevent, data);
}
static char *read_string(void)
@@ -241,7 +241,7 @@ static int read_header_files(struct tep_handle *pevent)
* The commit field in the page is of type long,
* use that instead, since it represents the kernel.
*/
tep_set_long_size(pevent, pevent->header_page_size_size);
tep_set_long_size(pevent, tep_get_header_page_size(pevent));
}
free(header_page);
@@ -297,10 +297,8 @@ static int read_event_file(struct tep_handle *pevent, char *sys,
}
ret = do_read(buf, size);
if (ret < 0) {
free(buf);
if (ret < 0)
goto out;
}
ret = parse_event_file(pevent, buf, size, sys);
if (ret < 0)
@@ -349,9 +347,12 @@ static int read_event_files(struct tep_handle *pevent)
for (x=0; x < count; x++) {
size = read8(pevent);
ret = read_event_file(pevent, sys, size);
if (ret)
if (ret) {
free(sys);
return ret;
}
}
free(sys);
}
return 0;
}

View File

@@ -72,12 +72,12 @@ void trace_event__cleanup(struct trace_event *t)
/*
* Returns pointer with encoded error via <linux/err.h> interface.
*/
static struct event_format*
static struct tep_event_format*
tp_format(const char *sys, const char *name)
{
char *tp_dir = get_events_file(sys);
struct tep_handle *pevent = tevent.pevent;
struct event_format *event = NULL;
struct tep_event_format *event = NULL;
char path[PATH_MAX];
size_t size;
char *data;
@@ -102,7 +102,7 @@ tp_format(const char *sys, const char *name)
/*
* Returns pointer with encoded error via <linux/err.h> interface.
*/
struct event_format*
struct tep_event_format*
trace_event__tp_format(const char *sys, const char *name)
{
if (!tevent_initialized && trace_event__init2())
@@ -111,7 +111,7 @@ trace_event__tp_format(const char *sys, const char *name)
return tp_format(sys, name);
}
struct event_format *trace_event__tp_format_id(int id)
struct tep_event_format *trace_event__tp_format_id(int id)
{
if (!tevent_initialized && trace_event__init2())
return ERR_PTR(-ENOMEM);

View File

@@ -3,6 +3,7 @@
#define _PERF_UTIL_TRACE_EVENT_H
#include <traceevent/event-parse.h>
#include <traceevent/trace-seq.h>
#include "parse-events.h"
struct machine;
@@ -10,28 +11,28 @@ struct perf_sample;
union perf_event;
struct perf_tool;
struct thread;
struct plugin_list;
struct tep_plugin_list;
struct trace_event {
struct tep_handle *pevent;
struct plugin_list *plugin_list;
struct tep_plugin_list *plugin_list;
};
int trace_event__init(struct trace_event *t);
void trace_event__cleanup(struct trace_event *t);
int trace_event__register_resolver(struct machine *machine,
tep_func_resolver_t *func);
struct event_format*
struct tep_event_format*
trace_event__tp_format(const char *sys, const char *name);
struct event_format *trace_event__tp_format_id(int id);
struct tep_event_format *trace_event__tp_format_id(int id);
int bigendian(void);
void event_format__fprintf(struct event_format *event,
void event_format__fprintf(struct tep_event_format *event,
int cpu, void *data, int size, FILE *fp);
void event_format__print(struct event_format *event,
void event_format__print(struct tep_event_format *event,
int cpu, void *data, int size);
int parse_ftrace_file(struct tep_handle *pevent, char *buf, unsigned long size);
@@ -39,7 +40,7 @@ int parse_event_file(struct tep_handle *pevent,
char *buf, unsigned long size, char *sys);
unsigned long long
raw_field_value(struct event_format *event, const char *name, void *data);
raw_field_value(struct tep_event_format *event, const char *name, void *data);
void parse_proc_kallsyms(struct tep_handle *pevent, char *file, unsigned int size);
void parse_ftrace_printk(struct tep_handle *pevent, char *file, unsigned int size);
@@ -47,9 +48,9 @@ void parse_saved_cmdline(struct tep_handle *pevent, char *file, unsigned int siz
ssize_t trace_report(int fd, struct trace_event *tevent, bool repipe);
struct event_format *trace_find_next_event(struct tep_handle *pevent,
struct event_format *event);
unsigned long long read_size(struct event_format *event, void *ptr, int size);
struct tep_event_format *trace_find_next_event(struct tep_handle *pevent,
struct tep_event_format *event);
unsigned long long read_size(struct tep_event_format *event, void *ptr, int size);
unsigned long long eval_flag(const char *flag);
int read_tracing_data(int fd, struct list_head *pattrs);

View File

@@ -221,7 +221,7 @@ out:
return err;
}
static int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size)
int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size)
{
void *ptr;
loff_t pgoff;

Some files were not shown because too many files have changed in this diff Show More