mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
Merge branch 'perf/parse-events-4' of git://github.com/fweisbec/tracing into perf/core
Conflicts: tools/perf/Makefile This tree from Frederic unifies the perf and trace-cmd trace event format parsing code into a single library. Powertop and other tools will also be able to make use of it. Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
73787190d0
18 changed files with 9142 additions and 3294 deletions
303
tools/lib/traceevent/Makefile
Normal file
303
tools/lib/traceevent/Makefile
Normal file
|
@ -0,0 +1,303 @@
|
|||
# trace-cmd version
|
||||
EP_VERSION = 1
|
||||
EP_PATCHLEVEL = 1
|
||||
EP_EXTRAVERSION = 0
|
||||
|
||||
# file format version
|
||||
FILE_VERSION = 6
|
||||
|
||||
MAKEFLAGS += --no-print-directory
|
||||
|
||||
|
||||
# Makefiles suck: This macro sets a default value of $(2) for the
|
||||
# variable named by $(1), unless the variable has been set by
|
||||
# environment or command line. This is necessary for CC and AR
|
||||
# because make sets default values, so the simpler ?= approach
|
||||
# won't work as expected.
|
||||
define allow-override
|
||||
$(if $(or $(findstring environment,$(origin $(1))),\
|
||||
$(findstring command line,$(origin $(1)))),,\
|
||||
$(eval $(1) = $(2)))
|
||||
endef
|
||||
|
||||
# Allow setting CC and AR, or setting CROSS_COMPILE as a prefix.
|
||||
$(call allow-override,CC,$(CROSS_COMPILE)gcc)
|
||||
$(call allow-override,AR,$(CROSS_COMPILE)ar)
|
||||
|
||||
EXT = -std=gnu99
|
||||
INSTALL = install
|
||||
|
||||
# Use DESTDIR for installing into a different root directory.
|
||||
# This is useful for building a package. The program will be
|
||||
# installed in this directory as if it was the root directory.
|
||||
# Then the build tool can move it later.
|
||||
DESTDIR ?=
|
||||
DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))'
|
||||
|
||||
prefix ?= /usr/local
|
||||
bindir_relative = bin
|
||||
bindir = $(prefix)/$(bindir_relative)
|
||||
man_dir = $(prefix)/share/man
|
||||
man_dir_SQ = '$(subst ','\'',$(man_dir))'
|
||||
html_install = $(prefix)/share/kernelshark/html
|
||||
html_install_SQ = '$(subst ','\'',$(html_install))'
|
||||
img_install = $(prefix)/share/kernelshark/html/images
|
||||
img_install_SQ = '$(subst ','\'',$(img_install))'
|
||||
|
||||
export man_dir man_dir_SQ html_install html_install_SQ INSTALL
|
||||
export img_install img_install_SQ
|
||||
export DESTDIR DESTDIR_SQ
|
||||
|
||||
# copy a bit from Linux kbuild
|
||||
|
||||
ifeq ("$(origin V)", "command line")
|
||||
VERBOSE = $(V)
|
||||
endif
|
||||
ifndef VERBOSE
|
||||
VERBOSE = 0
|
||||
endif
|
||||
|
||||
ifeq ("$(origin O)", "command line")
|
||||
BUILD_OUTPUT := $(O)
|
||||
endif
|
||||
|
||||
ifeq ($(BUILD_SRC),)
|
||||
ifneq ($(BUILD_OUTPUT),)
|
||||
|
||||
define build_output
|
||||
$(if $(VERBOSE:1=),@)$(MAKE) -C $(BUILD_OUTPUT) \
|
||||
BUILD_SRC=$(CURDIR) -f $(CURDIR)/Makefile $1
|
||||
endef
|
||||
|
||||
saved-output := $(BUILD_OUTPUT)
|
||||
BUILD_OUTPUT := $(shell cd $(BUILD_OUTPUT) && /bin/pwd)
|
||||
$(if $(BUILD_OUTPUT),, \
|
||||
$(error output directory "$(saved-output)" does not exist))
|
||||
|
||||
all: sub-make
|
||||
|
||||
gui: force
|
||||
$(call build_output, all_cmd)
|
||||
|
||||
$(filter-out gui,$(MAKECMDGOALS)): sub-make
|
||||
|
||||
sub-make: force
|
||||
$(call build_output, $(MAKECMDGOALS))
|
||||
|
||||
|
||||
# Leave processing to above invocation of make
|
||||
skip-makefile := 1
|
||||
|
||||
endif # BUILD_OUTPUT
|
||||
endif # BUILD_SRC
|
||||
|
||||
# We process the rest of the Makefile if this is the final invocation of make
|
||||
ifeq ($(skip-makefile),)
|
||||
|
||||
srctree := $(if $(BUILD_SRC),$(BUILD_SRC),$(CURDIR))
|
||||
objtree := $(CURDIR)
|
||||
src := $(srctree)
|
||||
obj := $(objtree)
|
||||
|
||||
export prefix bindir src obj
|
||||
|
||||
# Shell quotes
|
||||
bindir_SQ = $(subst ','\'',$(bindir))
|
||||
bindir_relative_SQ = $(subst ','\'',$(bindir_relative))
|
||||
|
||||
LIB_FILE = libtraceevent.a libtraceevent.so
|
||||
|
||||
CONFIG_INCLUDES =
|
||||
CONFIG_LIBS =
|
||||
CONFIG_FLAGS =
|
||||
|
||||
VERSION = $(EP_VERSION)
|
||||
PATCHLEVEL = $(EP_PATCHLEVEL)
|
||||
EXTRAVERSION = $(EP_EXTRAVERSION)
|
||||
|
||||
OBJ = $@
|
||||
N =
|
||||
|
||||
export Q VERBOSE
|
||||
|
||||
EVENT_PARSE_VERSION = $(EP_VERSION).$(EP_PATCHLEVEL).$(EP_EXTRAVERSION)
|
||||
|
||||
INCLUDES = -I. -I/usr/local/include $(CONFIG_INCLUDES)
|
||||
|
||||
# Set compile option CFLAGS if not set elsewhere
|
||||
CFLAGS ?= -g -Wall
|
||||
|
||||
# Append required CFLAGS
|
||||
override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ)
|
||||
override CFLAGS += $(udis86-flags)
|
||||
|
||||
ifeq ($(VERBOSE),1)
|
||||
Q =
|
||||
print_compile =
|
||||
print_app_build =
|
||||
print_fpic_compile =
|
||||
print_shared_lib_compile =
|
||||
print_plugin_obj_compile =
|
||||
print_plugin_build =
|
||||
print_install =
|
||||
else
|
||||
Q = @
|
||||
print_compile = echo ' CC '$(OBJ);
|
||||
print_app_build = echo ' BUILD '$(OBJ);
|
||||
print_fpic_compile = echo ' CC FPIC '$(OBJ);
|
||||
print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ);
|
||||
print_plugin_obj_compile = echo ' CC PLUGIN OBJ '$(OBJ);
|
||||
print_plugin_build = echo ' CC PLUGI '$(OBJ);
|
||||
print_static_lib_build = echo ' BUILD STATIC LIB '$(OBJ);
|
||||
print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2';
|
||||
endif
|
||||
|
||||
do_fpic_compile = \
|
||||
($(print_fpic_compile) \
|
||||
$(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@)
|
||||
|
||||
do_app_build = \
|
||||
($(print_app_build) \
|
||||
$(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS))
|
||||
|
||||
do_compile_shared_library = \
|
||||
($(print_shared_lib_compile) \
|
||||
$(CC) --shared $^ -o $@)
|
||||
|
||||
do_compile_plugin_obj = \
|
||||
($(print_plugin_obj_compile) \
|
||||
$(CC) -c $(CFLAGS) -fPIC -o $@ $<)
|
||||
|
||||
do_plugin_build = \
|
||||
($(print_plugin_build) \
|
||||
$(CC) $(CFLAGS) -shared -nostartfiles -o $@ $<)
|
||||
|
||||
do_build_static_lib = \
|
||||
($(print_static_lib_build) \
|
||||
$(RM) $@; $(AR) rcs $@ $^)
|
||||
|
||||
|
||||
define do_compile
|
||||
$(print_compile) \
|
||||
$(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@;
|
||||
endef
|
||||
|
||||
$(obj)/%.o: $(src)/%.c
|
||||
$(Q)$(call do_compile)
|
||||
|
||||
%.o: $(src)/%.c
|
||||
$(Q)$(call do_compile)
|
||||
|
||||
PEVENT_LIB_OBJS = event-parse.o trace-seq.o parse-filter.o parse-utils.o
|
||||
|
||||
ALL_OBJS = $(PEVENT_LIB_OBJS)
|
||||
|
||||
CMD_TARGETS = $(LIB_FILE)
|
||||
|
||||
TARGETS = $(CMD_TARGETS)
|
||||
|
||||
|
||||
all: all_cmd
|
||||
|
||||
all_cmd: $(CMD_TARGETS)
|
||||
|
||||
libtraceevent.so: $(PEVENT_LIB_OBJS)
|
||||
$(Q)$(do_compile_shared_library)
|
||||
|
||||
libtraceevent.a: $(PEVENT_LIB_OBJS)
|
||||
$(Q)$(do_build_static_lib)
|
||||
|
||||
$(PEVENT_LIB_OBJS): %.o: $(src)/%.c
|
||||
$(Q)$(do_fpic_compile)
|
||||
|
||||
define make_version.h
|
||||
(echo '/* This file is automatically generated. Do not modify. */'; \
|
||||
echo \#define VERSION_CODE $(shell \
|
||||
expr $(VERSION) \* 256 + $(PATCHLEVEL)); \
|
||||
echo '#define EXTRAVERSION ' $(EXTRAVERSION); \
|
||||
echo '#define VERSION_STRING "'$(VERSION).$(PATCHLEVEL).$(EXTRAVERSION)'"'; \
|
||||
echo '#define FILE_VERSION '$(FILE_VERSION); \
|
||||
) > $1
|
||||
endef
|
||||
|
||||
define update_version.h
|
||||
($(call make_version.h, $@.tmp); \
|
||||
if [ -r $@ ] && cmp -s $@ $@.tmp; then \
|
||||
rm -f $@.tmp; \
|
||||
else \
|
||||
echo ' UPDATE $@'; \
|
||||
mv -f $@.tmp $@; \
|
||||
fi);
|
||||
endef
|
||||
|
||||
ep_version.h: force
|
||||
$(Q)$(N)$(call update_version.h)
|
||||
|
||||
VERSION_FILES = ep_version.h
|
||||
|
||||
define update_dir
|
||||
(echo $1 > $@.tmp; \
|
||||
if [ -r $@ ] && cmp -s $@ $@.tmp; then \
|
||||
rm -f $@.tmp; \
|
||||
else \
|
||||
echo ' UPDATE $@'; \
|
||||
mv -f $@.tmp $@; \
|
||||
fi);
|
||||
endef
|
||||
|
||||
## make deps
|
||||
|
||||
all_objs := $(sort $(ALL_OBJS))
|
||||
all_deps := $(all_objs:%.o=.%.d)
|
||||
|
||||
define check_deps
|
||||
$(CC) -M $(CFLAGS) $< > $@;
|
||||
endef
|
||||
|
||||
$(gui_deps): ks_version.h
|
||||
$(non_gui_deps): tc_version.h
|
||||
|
||||
$(all_deps): .%.d: $(src)/%.c
|
||||
$(Q)$(call check_deps)
|
||||
|
||||
$(all_objs) : %.o : .%.d
|
||||
|
||||
dep_includes := $(wildcard $(all_deps))
|
||||
|
||||
ifneq ($(dep_includes),)
|
||||
include $(dep_includes)
|
||||
endif
|
||||
|
||||
tags: force
|
||||
$(RM) tags
|
||||
find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px
|
||||
|
||||
TAGS: force
|
||||
$(RM) TAGS
|
||||
find . -name '*.[ch]' | xargs etags
|
||||
|
||||
define do_install
|
||||
$(print_install) \
|
||||
if [ ! -d '$(DESTDIR_SQ)$2' ]; then \
|
||||
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \
|
||||
fi; \
|
||||
$(INSTALL) $1 '$(DESTDIR_SQ)$2'
|
||||
endef
|
||||
|
||||
install_lib: all_cmd install_plugins install_python
|
||||
$(Q)$(call do_install,$(LIB_FILE),$(bindir_SQ))
|
||||
|
||||
install: install_lib
|
||||
|
||||
clean:
|
||||
$(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES).*.d
|
||||
$(RM) tags TAGS
|
||||
|
||||
endif # skip-makefile
|
||||
|
||||
PHONY += force
|
||||
force:
|
||||
|
||||
# Declare the contents of the .PHONY variable as phony. We keep that
|
||||
# information in a variable so we can use it in if_changed and friends.
|
||||
.PHONY: $(PHONY)
|
5065
tools/lib/traceevent/event-parse.c
Normal file
5065
tools/lib/traceevent/event-parse.c
Normal file
File diff suppressed because it is too large
Load diff
804
tools/lib/traceevent/event-parse.h
Normal file
804
tools/lib/traceevent/event-parse.h
Normal file
|
@ -0,0 +1,804 @@
|
|||
/*
|
||||
* Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License (not later!)
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
#ifndef _PARSE_EVENTS_H
|
||||
#define _PARSE_EVENTS_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <regex.h>
|
||||
|
||||
#ifndef __unused
|
||||
#define __unused __attribute__ ((unused))
|
||||
#endif
|
||||
|
||||
/* ----------------------- trace_seq ----------------------- */
|
||||
|
||||
|
||||
#ifndef TRACE_SEQ_BUF_SIZE
|
||||
#define TRACE_SEQ_BUF_SIZE 4096
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG_RECORD
|
||||
#define DEBUG_RECORD 0
|
||||
#endif
|
||||
|
||||
struct pevent_record {
|
||||
unsigned long long ts;
|
||||
unsigned long long offset;
|
||||
long long missed_events; /* buffer dropped events before */
|
||||
int record_size; /* size of binary record */
|
||||
int size; /* size of data */
|
||||
void *data;
|
||||
int cpu;
|
||||
int ref_count;
|
||||
int locked; /* Do not free, even if ref_count is zero */
|
||||
void *private;
|
||||
#if DEBUG_RECORD
|
||||
struct pevent_record *prev;
|
||||
struct pevent_record *next;
|
||||
long alloc_addr;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* 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;
|
||||
};
|
||||
|
||||
void trace_seq_init(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_printf(struct trace_seq *s);
|
||||
|
||||
|
||||
/* ----------------------- pevent ----------------------- */
|
||||
|
||||
struct pevent;
|
||||
struct event_format;
|
||||
|
||||
typedef int (*pevent_event_handler_func)(struct trace_seq *s,
|
||||
struct pevent_record *record,
|
||||
struct event_format *event,
|
||||
void *context);
|
||||
|
||||
typedef int (*pevent_plugin_load_func)(struct pevent *pevent);
|
||||
typedef int (*pevent_plugin_unload_func)(void);
|
||||
|
||||
struct plugin_option {
|
||||
struct plugin_option *next;
|
||||
void *handle;
|
||||
char *file;
|
||||
char *name;
|
||||
char *plugin_alias;
|
||||
char *description;
|
||||
char *value;
|
||||
void *private;
|
||||
int set;
|
||||
};
|
||||
|
||||
/*
|
||||
* Plugin hooks that can be called:
|
||||
*
|
||||
* PEVENT_PLUGIN_LOADER: (required)
|
||||
* The function name to initialized the plugin.
|
||||
*
|
||||
* int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
|
||||
*
|
||||
* PEVENT_PLUGIN_UNLOADER: (optional)
|
||||
* The function called just before unloading
|
||||
*
|
||||
* int PEVENT_PLUGIN_UNLOADER(void)
|
||||
*
|
||||
* PEVENT_PLUGIN_OPTIONS: (optional)
|
||||
* Plugin options that can be set before loading
|
||||
*
|
||||
* struct plugin_option PEVENT_PLUGIN_OPTIONS[] = {
|
||||
* {
|
||||
* .name = "option-name",
|
||||
* .plugin_alias = "overide-file-name", (optional)
|
||||
* .description = "description of option to show users",
|
||||
* },
|
||||
* {
|
||||
* .name = NULL,
|
||||
* },
|
||||
* };
|
||||
*
|
||||
* Array must end with .name = NULL;
|
||||
*
|
||||
*
|
||||
* .plugin_alias is used to give a shorter name to access
|
||||
* the vairable. Useful if a plugin handles more than one event.
|
||||
*
|
||||
* PEVENT_PLUGIN_ALIAS: (optional)
|
||||
* The name to use for finding options (uses filename if not defined)
|
||||
*/
|
||||
#define PEVENT_PLUGIN_LOADER pevent_plugin_loader
|
||||
#define PEVENT_PLUGIN_UNLOADER pevent_plugin_unloader
|
||||
#define PEVENT_PLUGIN_OPTIONS pevent_plugin_options
|
||||
#define PEVENT_PLUGIN_ALIAS pevent_plugin_alias
|
||||
#define _MAKE_STR(x) #x
|
||||
#define MAKE_STR(x) _MAKE_STR(x)
|
||||
#define PEVENT_PLUGIN_LOADER_NAME MAKE_STR(PEVENT_PLUGIN_LOADER)
|
||||
#define PEVENT_PLUGIN_UNLOADER_NAME MAKE_STR(PEVENT_PLUGIN_UNLOADER)
|
||||
#define PEVENT_PLUGIN_OPTIONS_NAME MAKE_STR(PEVENT_PLUGIN_OPTIONS)
|
||||
#define PEVENT_PLUGIN_ALIAS_NAME MAKE_STR(PEVENT_PLUGIN_ALIAS)
|
||||
|
||||
#define NSECS_PER_SEC 1000000000ULL
|
||||
#define NSECS_PER_USEC 1000ULL
|
||||
|
||||
enum format_flags {
|
||||
FIELD_IS_ARRAY = 1,
|
||||
FIELD_IS_POINTER = 2,
|
||||
FIELD_IS_SIGNED = 4,
|
||||
FIELD_IS_STRING = 8,
|
||||
FIELD_IS_DYNAMIC = 16,
|
||||
FIELD_IS_LONG = 32,
|
||||
FIELD_IS_FLAG = 64,
|
||||
FIELD_IS_SYMBOLIC = 128,
|
||||
};
|
||||
|
||||
struct format_field {
|
||||
struct format_field *next;
|
||||
struct event_format *event;
|
||||
char *type;
|
||||
char *name;
|
||||
int offset;
|
||||
int size;
|
||||
unsigned int arraylen;
|
||||
unsigned int elementsize;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
struct format {
|
||||
int nr_common;
|
||||
int nr_fields;
|
||||
struct format_field *common_fields;
|
||||
struct format_field *fields;
|
||||
};
|
||||
|
||||
struct print_arg_atom {
|
||||
char *atom;
|
||||
};
|
||||
|
||||
struct print_arg_string {
|
||||
char *string;
|
||||
int offset;
|
||||
};
|
||||
|
||||
struct print_arg_field {
|
||||
char *name;
|
||||
struct format_field *field;
|
||||
};
|
||||
|
||||
struct print_flag_sym {
|
||||
struct print_flag_sym *next;
|
||||
char *value;
|
||||
char *str;
|
||||
};
|
||||
|
||||
struct print_arg_typecast {
|
||||
char *type;
|
||||
struct print_arg *item;
|
||||
};
|
||||
|
||||
struct print_arg_flags {
|
||||
struct print_arg *field;
|
||||
char *delim;
|
||||
struct print_flag_sym *flags;
|
||||
};
|
||||
|
||||
struct print_arg_symbol {
|
||||
struct print_arg *field;
|
||||
struct print_flag_sym *symbols;
|
||||
};
|
||||
|
||||
struct print_arg_dynarray {
|
||||
struct format_field *field;
|
||||
struct print_arg *index;
|
||||
};
|
||||
|
||||
struct print_arg;
|
||||
|
||||
struct print_arg_op {
|
||||
char *op;
|
||||
int prio;
|
||||
struct print_arg *left;
|
||||
struct print_arg *right;
|
||||
};
|
||||
|
||||
struct pevent_function_handler;
|
||||
|
||||
struct print_arg_func {
|
||||
struct pevent_function_handler *func;
|
||||
struct print_arg *args;
|
||||
};
|
||||
|
||||
enum print_arg_type {
|
||||
PRINT_NULL,
|
||||
PRINT_ATOM,
|
||||
PRINT_FIELD,
|
||||
PRINT_FLAGS,
|
||||
PRINT_SYMBOL,
|
||||
PRINT_TYPE,
|
||||
PRINT_STRING,
|
||||
PRINT_BSTRING,
|
||||
PRINT_DYNAMIC_ARRAY,
|
||||
PRINT_OP,
|
||||
PRINT_FUNC,
|
||||
};
|
||||
|
||||
struct print_arg {
|
||||
struct print_arg *next;
|
||||
enum print_arg_type type;
|
||||
union {
|
||||
struct print_arg_atom atom;
|
||||
struct print_arg_field field;
|
||||
struct print_arg_typecast typecast;
|
||||
struct print_arg_flags flags;
|
||||
struct print_arg_symbol symbol;
|
||||
struct print_arg_func func;
|
||||
struct print_arg_string string;
|
||||
struct print_arg_op op;
|
||||
struct print_arg_dynarray dynarray;
|
||||
};
|
||||
};
|
||||
|
||||
struct print_fmt {
|
||||
char *format;
|
||||
struct print_arg *args;
|
||||
};
|
||||
|
||||
struct event_format {
|
||||
struct pevent *pevent;
|
||||
char *name;
|
||||
int id;
|
||||
int flags;
|
||||
struct format format;
|
||||
struct print_fmt print_fmt;
|
||||
char *system;
|
||||
pevent_event_handler_func handler;
|
||||
void *context;
|
||||
};
|
||||
|
||||
enum {
|
||||
EVENT_FL_ISFTRACE = 0x01,
|
||||
EVENT_FL_ISPRINT = 0x02,
|
||||
EVENT_FL_ISBPRINT = 0x04,
|
||||
EVENT_FL_ISFUNCENT = 0x10,
|
||||
EVENT_FL_ISFUNCRET = 0x20,
|
||||
|
||||
EVENT_FL_FAILED = 0x80000000
|
||||
};
|
||||
|
||||
enum event_sort_type {
|
||||
EVENT_SORT_ID,
|
||||
EVENT_SORT_NAME,
|
||||
EVENT_SORT_SYSTEM,
|
||||
};
|
||||
|
||||
enum event_type {
|
||||
EVENT_ERROR,
|
||||
EVENT_NONE,
|
||||
EVENT_SPACE,
|
||||
EVENT_NEWLINE,
|
||||
EVENT_OP,
|
||||
EVENT_DELIM,
|
||||
EVENT_ITEM,
|
||||
EVENT_DQUOTE,
|
||||
EVENT_SQUOTE,
|
||||
};
|
||||
|
||||
typedef unsigned long long (*pevent_func_handler)(struct trace_seq *s,
|
||||
unsigned long long *args);
|
||||
|
||||
enum pevent_func_arg_type {
|
||||
PEVENT_FUNC_ARG_VOID,
|
||||
PEVENT_FUNC_ARG_INT,
|
||||
PEVENT_FUNC_ARG_LONG,
|
||||
PEVENT_FUNC_ARG_STRING,
|
||||
PEVENT_FUNC_ARG_PTR,
|
||||
PEVENT_FUNC_ARG_MAX_TYPES
|
||||
};
|
||||
|
||||
enum pevent_flag {
|
||||
PEVENT_NSEC_OUTPUT = 1, /* output in NSECS */
|
||||
};
|
||||
|
||||
struct cmdline;
|
||||
struct cmdline_list;
|
||||
struct func_map;
|
||||
struct func_list;
|
||||
struct event_handler;
|
||||
|
||||
struct pevent {
|
||||
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;
|
||||
|
||||
int file_bigendian;
|
||||
int host_bigendian;
|
||||
|
||||
int latency_format;
|
||||
|
||||
int old_format;
|
||||
|
||||
int cpus;
|
||||
int long_size;
|
||||
|
||||
struct cmdline *cmdlines;
|
||||
struct cmdline_list *cmdlist;
|
||||
int cmdline_count;
|
||||
|
||||
struct func_map *func_map;
|
||||
struct func_list *funclist;
|
||||
unsigned int func_count;
|
||||
|
||||
struct printk_map *printk_map;
|
||||
struct printk_list *printklist;
|
||||
unsigned int printk_count;
|
||||
|
||||
|
||||
struct event_format **events;
|
||||
int nr_events;
|
||||
struct event_format **sort_events;
|
||||
enum 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 format_field *bprint_ip_field;
|
||||
struct format_field *bprint_fmt_field;
|
||||
struct format_field *bprint_buf_field;
|
||||
|
||||
struct event_handler *handlers;
|
||||
struct pevent_function_handler *func_handlers;
|
||||
|
||||
/* cache */
|
||||
struct event_format *last_event;
|
||||
};
|
||||
|
||||
static inline void pevent_set_flag(struct pevent *pevent, int flag)
|
||||
{
|
||||
pevent->flags |= flag;
|
||||
}
|
||||
|
||||
static inline unsigned short
|
||||
__data2host2(struct pevent *pevent, unsigned short data)
|
||||
{
|
||||
unsigned short swap;
|
||||
|
||||
if (pevent->host_bigendian == pevent->file_bigendian)
|
||||
return data;
|
||||
|
||||
swap = ((data & 0xffULL) << 8) |
|
||||
((data & (0xffULL << 8)) >> 8);
|
||||
|
||||
return swap;
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
__data2host4(struct pevent *pevent, unsigned int data)
|
||||
{
|
||||
unsigned int swap;
|
||||
|
||||
if (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;
|
||||
}
|
||||
|
||||
static inline unsigned long long
|
||||
__data2host8(struct pevent *pevent, unsigned long long data)
|
||||
{
|
||||
unsigned long long swap;
|
||||
|
||||
if (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;
|
||||
}
|
||||
|
||||
#define data2host2(pevent, ptr) __data2host2(pevent, *(unsigned short *)(ptr))
|
||||
#define data2host4(pevent, ptr) __data2host4(pevent, *(unsigned int *)(ptr))
|
||||
#define data2host8(pevent, ptr) \
|
||||
({ \
|
||||
unsigned long long __val; \
|
||||
\
|
||||
memcpy(&__val, (ptr), sizeof(unsigned long long)); \
|
||||
__data2host8(pevent, __val); \
|
||||
})
|
||||
|
||||
/* taken from kernel/trace/trace.h */
|
||||
enum trace_flag_type {
|
||||
TRACE_FLAG_IRQS_OFF = 0x01,
|
||||
TRACE_FLAG_IRQS_NOSUPPORT = 0x02,
|
||||
TRACE_FLAG_NEED_RESCHED = 0x04,
|
||||
TRACE_FLAG_HARDIRQ = 0x08,
|
||||
TRACE_FLAG_SOFTIRQ = 0x10,
|
||||
};
|
||||
|
||||
int pevent_register_comm(struct pevent *pevent, const char *comm, int pid);
|
||||
int pevent_register_function(struct pevent *pevent, char *name,
|
||||
unsigned long long addr, char *mod);
|
||||
int pevent_register_print_string(struct pevent *pevent, char *fmt,
|
||||
unsigned long long addr);
|
||||
int pevent_pid_is_registered(struct pevent *pevent, int pid);
|
||||
|
||||
void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
|
||||
struct pevent_record *record);
|
||||
|
||||
int pevent_parse_header_page(struct pevent *pevent, char *buf, unsigned long size,
|
||||
int long_size);
|
||||
|
||||
int pevent_parse_event(struct pevent *pevent, const char *buf,
|
||||
unsigned long size, const char *sys);
|
||||
|
||||
void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event,
|
||||
const char *name, struct pevent_record *record,
|
||||
int *len, int err);
|
||||
|
||||
int pevent_get_field_val(struct trace_seq *s, struct event_format *event,
|
||||
const char *name, struct pevent_record *record,
|
||||
unsigned long long *val, int err);
|
||||
int pevent_get_common_field_val(struct trace_seq *s, struct event_format *event,
|
||||
const char *name, struct pevent_record *record,
|
||||
unsigned long long *val, int err);
|
||||
int pevent_get_any_field_val(struct trace_seq *s, struct event_format *event,
|
||||
const char *name, struct pevent_record *record,
|
||||
unsigned long long *val, int err);
|
||||
|
||||
int pevent_print_num_field(struct trace_seq *s, const char *fmt,
|
||||
struct event_format *event, const char *name,
|
||||
struct pevent_record *record, int err);
|
||||
|
||||
int pevent_register_event_handler(struct pevent *pevent, int id, char *sys_name, char *event_name,
|
||||
pevent_event_handler_func func, void *context);
|
||||
int pevent_register_print_function(struct pevent *pevent,
|
||||
pevent_func_handler func,
|
||||
enum pevent_func_arg_type ret_type,
|
||||
char *name, ...);
|
||||
|
||||
struct format_field *pevent_find_common_field(struct event_format *event, const char *name);
|
||||
struct format_field *pevent_find_field(struct event_format *event, const char *name);
|
||||
struct format_field *pevent_find_any_field(struct event_format *event, const char *name);
|
||||
|
||||
const char *pevent_find_function(struct pevent *pevent, unsigned long long addr);
|
||||
unsigned long long
|
||||
pevent_find_function_address(struct pevent *pevent, unsigned long long addr);
|
||||
unsigned long long pevent_read_number(struct pevent *pevent, const void *ptr, int size);
|
||||
int pevent_read_number_field(struct format_field *field, const void *data,
|
||||
unsigned long long *value);
|
||||
|
||||
struct event_format *pevent_find_event(struct pevent *pevent, int id);
|
||||
|
||||
struct event_format *
|
||||
pevent_find_event_by_name(struct pevent *pevent, const char *sys, const char *name);
|
||||
|
||||
void pevent_data_lat_fmt(struct pevent *pevent,
|
||||
struct trace_seq *s, struct pevent_record *record);
|
||||
int pevent_data_type(struct pevent *pevent, struct pevent_record *rec);
|
||||
struct event_format *pevent_data_event_from_type(struct pevent *pevent, int type);
|
||||
int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec);
|
||||
const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid);
|
||||
void pevent_event_info(struct trace_seq *s, struct event_format *event,
|
||||
struct pevent_record *record);
|
||||
|
||||
struct event_format **pevent_list_events(struct pevent *pevent, enum event_sort_type);
|
||||
struct format_field **pevent_event_common_fields(struct event_format *event);
|
||||
struct format_field **pevent_event_fields(struct event_format *event);
|
||||
|
||||
static inline int pevent_get_cpus(struct pevent *pevent)
|
||||
{
|
||||
return pevent->cpus;
|
||||
}
|
||||
|
||||
static inline void pevent_set_cpus(struct pevent *pevent, int cpus)
|
||||
{
|
||||
pevent->cpus = cpus;
|
||||
}
|
||||
|
||||
static inline int pevent_get_long_size(struct pevent *pevent)
|
||||
{
|
||||
return pevent->long_size;
|
||||
}
|
||||
|
||||
static inline void pevent_set_long_size(struct pevent *pevent, int long_size)
|
||||
{
|
||||
pevent->long_size = long_size;
|
||||
}
|
||||
|
||||
static inline int pevent_is_file_bigendian(struct pevent *pevent)
|
||||
{
|
||||
return pevent->file_bigendian;
|
||||
}
|
||||
|
||||
static inline void pevent_set_file_bigendian(struct pevent *pevent, int endian)
|
||||
{
|
||||
pevent->file_bigendian = endian;
|
||||
}
|
||||
|
||||
static inline int pevent_is_host_bigendian(struct pevent *pevent)
|
||||
{
|
||||
return pevent->host_bigendian;
|
||||
}
|
||||
|
||||
static inline void pevent_set_host_bigendian(struct pevent *pevent, int endian)
|
||||
{
|
||||
pevent->host_bigendian = endian;
|
||||
}
|
||||
|
||||
static inline int pevent_is_latency_format(struct pevent *pevent)
|
||||
{
|
||||
return pevent->latency_format;
|
||||
}
|
||||
|
||||
static inline void pevent_set_latency_format(struct pevent *pevent, int lat)
|
||||
{
|
||||
pevent->latency_format = lat;
|
||||
}
|
||||
|
||||
struct pevent *pevent_alloc(void);
|
||||
void pevent_free(struct pevent *pevent);
|
||||
void pevent_ref(struct pevent *pevent);
|
||||
void pevent_unref(struct pevent *pevent);
|
||||
|
||||
/* access to the internal parser */
|
||||
void pevent_buffer_init(const char *buf, unsigned long long size);
|
||||
enum event_type pevent_read_token(char **tok);
|
||||
void pevent_free_token(char *token);
|
||||
int pevent_peek_char(void);
|
||||
const char *pevent_get_input_buf(void);
|
||||
unsigned long long pevent_get_input_buf_ptr(void);
|
||||
|
||||
/* for debugging */
|
||||
void pevent_print_funcs(struct pevent *pevent);
|
||||
void pevent_print_printk(struct pevent *pevent);
|
||||
|
||||
/* ----------------------- filtering ----------------------- */
|
||||
|
||||
enum filter_boolean_type {
|
||||
FILTER_FALSE,
|
||||
FILTER_TRUE,
|
||||
};
|
||||
|
||||
enum filter_op_type {
|
||||
FILTER_OP_AND = 1,
|
||||
FILTER_OP_OR,
|
||||
FILTER_OP_NOT,
|
||||
};
|
||||
|
||||
enum filter_cmp_type {
|
||||
FILTER_CMP_NONE,
|
||||
FILTER_CMP_EQ,
|
||||
FILTER_CMP_NE,
|
||||
FILTER_CMP_GT,
|
||||
FILTER_CMP_LT,
|
||||
FILTER_CMP_GE,
|
||||
FILTER_CMP_LE,
|
||||
FILTER_CMP_MATCH,
|
||||
FILTER_CMP_NOT_MATCH,
|
||||
FILTER_CMP_REGEX,
|
||||
FILTER_CMP_NOT_REGEX,
|
||||
};
|
||||
|
||||
enum filter_exp_type {
|
||||
FILTER_EXP_NONE,
|
||||
FILTER_EXP_ADD,
|
||||
FILTER_EXP_SUB,
|
||||
FILTER_EXP_MUL,
|
||||
FILTER_EXP_DIV,
|
||||
FILTER_EXP_MOD,
|
||||
FILTER_EXP_RSHIFT,
|
||||
FILTER_EXP_LSHIFT,
|
||||
FILTER_EXP_AND,
|
||||
FILTER_EXP_OR,
|
||||
FILTER_EXP_XOR,
|
||||
FILTER_EXP_NOT,
|
||||
};
|
||||
|
||||
enum filter_arg_type {
|
||||
FILTER_ARG_NONE,
|
||||
FILTER_ARG_BOOLEAN,
|
||||
FILTER_ARG_VALUE,
|
||||
FILTER_ARG_FIELD,
|
||||
FILTER_ARG_EXP,
|
||||
FILTER_ARG_OP,
|
||||
FILTER_ARG_NUM,
|
||||
FILTER_ARG_STR,
|
||||
};
|
||||
|
||||
enum filter_value_type {
|
||||
FILTER_NUMBER,
|
||||
FILTER_STRING,
|
||||
FILTER_CHAR
|
||||
};
|
||||
|
||||
struct fliter_arg;
|
||||
|
||||
struct filter_arg_boolean {
|
||||
enum filter_boolean_type value;
|
||||
};
|
||||
|
||||
struct filter_arg_field {
|
||||
struct format_field *field;
|
||||
};
|
||||
|
||||
struct filter_arg_value {
|
||||
enum filter_value_type type;
|
||||
union {
|
||||
char *str;
|
||||
unsigned long long val;
|
||||
};
|
||||
};
|
||||
|
||||
struct filter_arg_op {
|
||||
enum filter_op_type type;
|
||||
struct filter_arg *left;
|
||||
struct filter_arg *right;
|
||||
};
|
||||
|
||||
struct filter_arg_exp {
|
||||
enum filter_exp_type type;
|
||||
struct filter_arg *left;
|
||||
struct filter_arg *right;
|
||||
};
|
||||
|
||||
struct filter_arg_num {
|
||||
enum filter_cmp_type type;
|
||||
struct filter_arg *left;
|
||||
struct filter_arg *right;
|
||||
};
|
||||
|
||||
struct filter_arg_str {
|
||||
enum filter_cmp_type type;
|
||||
struct format_field *field;
|
||||
char *val;
|
||||
char *buffer;
|
||||
regex_t reg;
|
||||
};
|
||||
|
||||
struct filter_arg {
|
||||
enum filter_arg_type type;
|
||||
union {
|
||||
struct filter_arg_boolean boolean;
|
||||
struct filter_arg_field field;
|
||||
struct filter_arg_value value;
|
||||
struct filter_arg_op op;
|
||||
struct filter_arg_exp exp;
|
||||
struct filter_arg_num num;
|
||||
struct filter_arg_str str;
|
||||
};
|
||||
};
|
||||
|
||||
struct filter_type {
|
||||
int event_id;
|
||||
struct event_format *event;
|
||||
struct filter_arg *filter;
|
||||
};
|
||||
|
||||
struct event_filter {
|
||||
struct pevent *pevent;
|
||||
int filters;
|
||||
struct filter_type *event_filters;
|
||||
};
|
||||
|
||||
struct event_filter *pevent_filter_alloc(struct pevent *pevent);
|
||||
|
||||
#define FILTER_NONE -2
|
||||
#define FILTER_NOEXIST -1
|
||||
#define FILTER_MISS 0
|
||||
#define FILTER_MATCH 1
|
||||
|
||||
enum filter_trivial_type {
|
||||
FILTER_TRIVIAL_FALSE,
|
||||
FILTER_TRIVIAL_TRUE,
|
||||
FILTER_TRIVIAL_BOTH,
|
||||
};
|
||||
|
||||
int pevent_filter_add_filter_str(struct event_filter *filter,
|
||||
const char *filter_str,
|
||||
char **error_str);
|
||||
|
||||
|
||||
int pevent_filter_match(struct event_filter *filter,
|
||||
struct pevent_record *record);
|
||||
|
||||
int pevent_event_filtered(struct event_filter *filter,
|
||||
int event_id);
|
||||
|
||||
void pevent_filter_reset(struct event_filter *filter);
|
||||
|
||||
void pevent_filter_clear_trivial(struct event_filter *filter,
|
||||
enum filter_trivial_type type);
|
||||
|
||||
void pevent_filter_free(struct event_filter *filter);
|
||||
|
||||
char *pevent_filter_make_string(struct event_filter *filter, int event_id);
|
||||
|
||||
int pevent_filter_remove_event(struct event_filter *filter,
|
||||
int event_id);
|
||||
|
||||
int pevent_filter_event_has_trivial(struct event_filter *filter,
|
||||
int event_id,
|
||||
enum filter_trivial_type type);
|
||||
|
||||
int pevent_filter_copy(struct event_filter *dest, struct event_filter *source);
|
||||
|
||||
int pevent_update_trivial(struct event_filter *dest, struct event_filter *source,
|
||||
enum filter_trivial_type type);
|
||||
|
||||
int pevent_filter_compare(struct event_filter *filter1, struct event_filter *filter2);
|
||||
|
||||
#endif /* _PARSE_EVENTS_H */
|
80
tools/lib/traceevent/event-utils.h
Normal file
80
tools/lib/traceevent/event-utils.h
Normal file
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License (not later!)
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
#ifndef __UTIL_H
|
||||
#define __UTIL_H
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
/* Can be overridden */
|
||||
void die(const char *fmt, ...);
|
||||
void *malloc_or_die(unsigned int size);
|
||||
void warning(const char *fmt, ...);
|
||||
void pr_stat(const char *fmt, ...);
|
||||
void vpr_stat(const char *fmt, va_list ap);
|
||||
|
||||
/* Always available */
|
||||
void __die(const char *fmt, ...);
|
||||
void __warning(const char *fmt, ...);
|
||||
void __pr_stat(const char *fmt, ...);
|
||||
|
||||
void __vdie(const char *fmt, ...);
|
||||
void __vwarning(const char *fmt, ...);
|
||||
void __vpr_stat(const char *fmt, ...);
|
||||
|
||||
static inline char *strim(char *string)
|
||||
{
|
||||
char *ret;
|
||||
|
||||
if (!string)
|
||||
return NULL;
|
||||
while (*string) {
|
||||
if (!isspace(*string))
|
||||
break;
|
||||
string++;
|
||||
}
|
||||
ret = string;
|
||||
|
||||
string = ret + strlen(ret) - 1;
|
||||
while (string > ret) {
|
||||
if (!isspace(*string))
|
||||
break;
|
||||
string--;
|
||||
}
|
||||
string[1] = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int has_text(const char *text)
|
||||
{
|
||||
if (!text)
|
||||
return 0;
|
||||
|
||||
while (*text) {
|
||||
if (!isspace(*text))
|
||||
return 1;
|
||||
text++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
2262
tools/lib/traceevent/parse-filter.c
Normal file
2262
tools/lib/traceevent/parse-filter.c
Normal file
File diff suppressed because it is too large
Load diff
110
tools/lib/traceevent/parse-utils.c
Normal file
110
tools/lib/traceevent/parse-utils.c
Normal file
|
@ -0,0 +1,110 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define __weak __attribute__((weak))
|
||||
|
||||
void __vdie(const char *fmt, va_list ap)
|
||||
{
|
||||
int ret = errno;
|
||||
|
||||
if (errno)
|
||||
perror("trace-cmd");
|
||||
else
|
||||
ret = -1;
|
||||
|
||||
fprintf(stderr, " ");
|
||||
vfprintf(stderr, fmt, ap);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
exit(ret);
|
||||
}
|
||||
|
||||
void __die(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
__vdie(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void __weak die(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
__vdie(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void __vwarning(const char *fmt, va_list ap)
|
||||
{
|
||||
if (errno)
|
||||
perror("trace-cmd");
|
||||
errno = 0;
|
||||
|
||||
fprintf(stderr, " ");
|
||||
vfprintf(stderr, fmt, ap);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void __warning(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
__vwarning(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void __weak warning(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
__vwarning(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void __vpr_stat(const char *fmt, va_list ap)
|
||||
{
|
||||
vprintf(fmt, ap);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void __pr_stat(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
__vpr_stat(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void __weak vpr_stat(const char *fmt, va_list ap)
|
||||
{
|
||||
__vpr_stat(fmt, ap);
|
||||
}
|
||||
|
||||
void __weak pr_stat(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
__vpr_stat(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void __weak *malloc_or_die(unsigned int size)
|
||||
{
|
||||
void *data;
|
||||
|
||||
data = malloc(size);
|
||||
if (!data)
|
||||
die("malloc");
|
||||
return data;
|
||||
}
|
200
tools/lib/traceevent/trace-seq.c
Normal file
200
tools/lib/traceevent/trace-seq.c
Normal file
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License (not later!)
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "event-parse.h"
|
||||
#include "event-utils.h"
|
||||
|
||||
/*
|
||||
* The TRACE_SEQ_POISON is to catch the use of using
|
||||
* a trace_seq structure after it was destroyed.
|
||||
*/
|
||||
#define TRACE_SEQ_POISON ((void *)0xdeadbeef)
|
||||
#define TRACE_SEQ_CHECK(s) \
|
||||
do { \
|
||||
if ((s)->buffer == TRACE_SEQ_POISON) \
|
||||
die("Usage of trace_seq after it was destroyed"); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* trace_seq_init - initialize the trace_seq structure
|
||||
* @s: a pointer to the trace_seq structure to initialize
|
||||
*/
|
||||
void trace_seq_init(struct trace_seq *s)
|
||||
{
|
||||
s->len = 0;
|
||||
s->readpos = 0;
|
||||
s->buffer_size = TRACE_SEQ_BUF_SIZE;
|
||||
s->buffer = malloc_or_die(s->buffer_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* trace_seq_destroy - free up memory of a trace_seq
|
||||
* @s: a pointer to the trace_seq to free the buffer
|
||||
*
|
||||
* Only frees the buffer, not the trace_seq struct itself.
|
||||
*/
|
||||
void trace_seq_destroy(struct trace_seq *s)
|
||||
{
|
||||
if (!s)
|
||||
return;
|
||||
TRACE_SEQ_CHECK(s);
|
||||
free(s->buffer);
|
||||
s->buffer = TRACE_SEQ_POISON;
|
||||
}
|
||||
|
||||
static void expand_buffer(struct trace_seq *s)
|
||||
{
|
||||
s->buffer_size += TRACE_SEQ_BUF_SIZE;
|
||||
s->buffer = realloc(s->buffer, s->buffer_size);
|
||||
if (!s->buffer)
|
||||
die("Can't allocate trace_seq buffer memory");
|
||||
}
|
||||
|
||||
/**
|
||||
* trace_seq_printf - sequence printing of trace information
|
||||
* @s: trace sequence descriptor
|
||||
* @fmt: printf format string
|
||||
*
|
||||
* It returns 0 if the trace oversizes the buffer's free
|
||||
* space, 1 otherwise.
|
||||
*
|
||||
* The tracer may use either sequence operations or its own
|
||||
* copy to user routines. To simplify formating of a trace
|
||||
* trace_seq_printf is used to store strings into a special
|
||||
* buffer (@s). Then the output may be either used by
|
||||
* the sequencer or pulled into another buffer.
|
||||
*/
|
||||
int
|
||||
trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int len;
|
||||
int ret;
|
||||
|
||||
TRACE_SEQ_CHECK(s);
|
||||
|
||||
try_again:
|
||||
len = (s->buffer_size - 1) - s->len;
|
||||
|
||||
va_start(ap, fmt);
|
||||
ret = vsnprintf(s->buffer + s->len, len, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (ret >= len) {
|
||||
expand_buffer(s);
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
s->len += ret;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* trace_seq_vprintf - sequence printing of trace information
|
||||
* @s: trace sequence descriptor
|
||||
* @fmt: printf format string
|
||||
*
|
||||
* The tracer may use either sequence operations or its own
|
||||
* copy to user routines. To simplify formating of a trace
|
||||
* trace_seq_printf is used to store strings into a special
|
||||
* buffer (@s). Then the output may be either used by
|
||||
* the sequencer or pulled into another buffer.
|
||||
*/
|
||||
int
|
||||
trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
|
||||
{
|
||||
int len;
|
||||
int ret;
|
||||
|
||||
TRACE_SEQ_CHECK(s);
|
||||
|
||||
try_again:
|
||||
len = (s->buffer_size - 1) - s->len;
|
||||
|
||||
ret = vsnprintf(s->buffer + s->len, len, fmt, args);
|
||||
|
||||
if (ret >= len) {
|
||||
expand_buffer(s);
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
s->len += ret;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* trace_seq_puts - trace sequence printing of simple string
|
||||
* @s: trace sequence descriptor
|
||||
* @str: simple string to record
|
||||
*
|
||||
* The tracer may use either the sequence operations or its own
|
||||
* copy to user routines. This function records a simple string
|
||||
* into a special buffer (@s) for later retrieval by a sequencer
|
||||
* or other mechanism.
|
||||
*/
|
||||
int trace_seq_puts(struct trace_seq *s, const char *str)
|
||||
{
|
||||
int len;
|
||||
|
||||
TRACE_SEQ_CHECK(s);
|
||||
|
||||
len = strlen(str);
|
||||
|
||||
while (len > ((s->buffer_size - 1) - s->len))
|
||||
expand_buffer(s);
|
||||
|
||||
memcpy(s->buffer + s->len, str, len);
|
||||
s->len += len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int trace_seq_putc(struct trace_seq *s, unsigned char c)
|
||||
{
|
||||
TRACE_SEQ_CHECK(s);
|
||||
|
||||
while (s->len >= (s->buffer_size - 1))
|
||||
expand_buffer(s);
|
||||
|
||||
s->buffer[s->len++] = c;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void trace_seq_terminate(struct trace_seq *s)
|
||||
{
|
||||
TRACE_SEQ_CHECK(s);
|
||||
|
||||
/* There's always one character left on the buffer */
|
||||
s->buffer[s->len] = 0;
|
||||
}
|
||||
|
||||
int trace_seq_do_printf(struct trace_seq *s)
|
||||
{
|
||||
TRACE_SEQ_CHECK(s);
|
||||
return printf("%.*s", s->len, s->buffer);
|
||||
}
|
|
@ -149,7 +149,7 @@ endif
|
|||
|
||||
### --- END CONFIGURATION SECTION ---
|
||||
|
||||
BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)/util -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
|
||||
BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)/util -I$(EVENT_PARSE_DIR) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
|
||||
BASIC_LDFLAGS =
|
||||
|
||||
# Guard against environment variables
|
||||
|
@ -178,6 +178,17 @@ $(OUTPUT)python/perf.so: $(PYRF_OBJS) $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
|
|||
|
||||
SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH))
|
||||
|
||||
EVENT_PARSE_DIR = ../lib/traceevent/
|
||||
|
||||
ifeq ("$(origin O)", "command line")
|
||||
EP_PATH=$(OUTPUT)/
|
||||
else
|
||||
EP_PATH=$(EVENT_PARSE_DIR)/
|
||||
endif
|
||||
|
||||
LIBPARSEVENT = $(EP_PATH)libtraceevent.a
|
||||
EP_LIB := -L$(EP_PATH) -ltraceevent
|
||||
|
||||
#
|
||||
# Single 'perf' binary right now:
|
||||
#
|
||||
|
@ -300,6 +311,7 @@ LIB_H += util/cpumap.h
|
|||
LIB_H += util/top.h
|
||||
LIB_H += $(ARCH_INCLUDE)
|
||||
LIB_H += util/cgroup.h
|
||||
LIB_H += $(EVENT_PARSE_DIR)event-parse.h
|
||||
LIB_H += util/target.h
|
||||
|
||||
LIB_OBJS += $(OUTPUT)util/abspath.o
|
||||
|
@ -398,7 +410,7 @@ BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o
|
|||
BUILTIN_OBJS += $(OUTPUT)builtin-test.o
|
||||
BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
|
||||
|
||||
PERFLIBS = $(LIB_FILE)
|
||||
PERFLIBS = $(LIB_FILE) $(LIBPARSEVENT)
|
||||
|
||||
# Files needed for the python binding, perf.so
|
||||
# pyrf is just an internal name needed for all those wrappers.
|
||||
|
@ -807,6 +819,10 @@ $(sort $(dir $(DIRECTORY_DEPS))):
|
|||
$(LIB_FILE): $(LIB_OBJS)
|
||||
$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
|
||||
|
||||
# libparsevent.a
|
||||
$(LIBPARSEVENT):
|
||||
make -C $(EVENT_PARSE_DIR) $(COMMAND_O) libtraceevent.a
|
||||
|
||||
help:
|
||||
@echo 'Perf make targets:'
|
||||
@echo ' doc - make *all* documentation (see below)'
|
||||
|
|
|
@ -192,7 +192,7 @@ static void insert_caller_stat(unsigned long call_site,
|
|||
}
|
||||
|
||||
static void process_alloc_event(void *data,
|
||||
struct event *event,
|
||||
struct event_format *event,
|
||||
int cpu,
|
||||
u64 timestamp __used,
|
||||
struct thread *thread __used,
|
||||
|
@ -253,7 +253,7 @@ static struct alloc_stat *search_alloc_stat(unsigned long ptr,
|
|||
}
|
||||
|
||||
static void process_free_event(void *data,
|
||||
struct event *event,
|
||||
struct event_format *event,
|
||||
int cpu,
|
||||
u64 timestamp __used,
|
||||
struct thread *thread __used)
|
||||
|
@ -281,7 +281,7 @@ static void process_free_event(void *data,
|
|||
static void process_raw_event(union perf_event *raw_event __used, void *data,
|
||||
int cpu, u64 timestamp, struct thread *thread)
|
||||
{
|
||||
struct event *event;
|
||||
struct event_format *event;
|
||||
int type;
|
||||
|
||||
type = trace_parse_common_type(data);
|
||||
|
|
|
@ -356,25 +356,25 @@ struct trace_release_event {
|
|||
|
||||
struct trace_lock_handler {
|
||||
void (*acquire_event)(struct trace_acquire_event *,
|
||||
struct event *,
|
||||
struct event_format *,
|
||||
int cpu,
|
||||
u64 timestamp,
|
||||
struct thread *thread);
|
||||
|
||||
void (*acquired_event)(struct trace_acquired_event *,
|
||||
struct event *,
|
||||
struct event_format *,
|
||||
int cpu,
|
||||
u64 timestamp,
|
||||
struct thread *thread);
|
||||
|
||||
void (*contended_event)(struct trace_contended_event *,
|
||||
struct event *,
|
||||
struct event_format *,
|
||||
int cpu,
|
||||
u64 timestamp,
|
||||
struct thread *thread);
|
||||
|
||||
void (*release_event)(struct trace_release_event *,
|
||||
struct event *,
|
||||
struct event_format *,
|
||||
int cpu,
|
||||
u64 timestamp,
|
||||
struct thread *thread);
|
||||
|
@ -416,7 +416,7 @@ enum acquire_flags {
|
|||
|
||||
static void
|
||||
report_lock_acquire_event(struct trace_acquire_event *acquire_event,
|
||||
struct event *__event __used,
|
||||
struct event_format *__event __used,
|
||||
int cpu __used,
|
||||
u64 timestamp __used,
|
||||
struct thread *thread __used)
|
||||
|
@ -480,7 +480,7 @@ end:
|
|||
|
||||
static void
|
||||
report_lock_acquired_event(struct trace_acquired_event *acquired_event,
|
||||
struct event *__event __used,
|
||||
struct event_format *__event __used,
|
||||
int cpu __used,
|
||||
u64 timestamp __used,
|
||||
struct thread *thread __used)
|
||||
|
@ -536,7 +536,7 @@ end:
|
|||
|
||||
static void
|
||||
report_lock_contended_event(struct trace_contended_event *contended_event,
|
||||
struct event *__event __used,
|
||||
struct event_format *__event __used,
|
||||
int cpu __used,
|
||||
u64 timestamp __used,
|
||||
struct thread *thread __used)
|
||||
|
@ -583,7 +583,7 @@ end:
|
|||
|
||||
static void
|
||||
report_lock_release_event(struct trace_release_event *release_event,
|
||||
struct event *__event __used,
|
||||
struct event_format *__event __used,
|
||||
int cpu __used,
|
||||
u64 timestamp __used,
|
||||
struct thread *thread __used)
|
||||
|
@ -647,7 +647,7 @@ static struct trace_lock_handler *trace_handler;
|
|||
|
||||
static void
|
||||
process_lock_acquire_event(void *data,
|
||||
struct event *event __used,
|
||||
struct event_format *event __used,
|
||||
int cpu __used,
|
||||
u64 timestamp __used,
|
||||
struct thread *thread __used)
|
||||
|
@ -666,7 +666,7 @@ process_lock_acquire_event(void *data,
|
|||
|
||||
static void
|
||||
process_lock_acquired_event(void *data,
|
||||
struct event *event __used,
|
||||
struct event_format *event __used,
|
||||
int cpu __used,
|
||||
u64 timestamp __used,
|
||||
struct thread *thread __used)
|
||||
|
@ -684,7 +684,7 @@ process_lock_acquired_event(void *data,
|
|||
|
||||
static void
|
||||
process_lock_contended_event(void *data,
|
||||
struct event *event __used,
|
||||
struct event_format *event __used,
|
||||
int cpu __used,
|
||||
u64 timestamp __used,
|
||||
struct thread *thread __used)
|
||||
|
@ -702,7 +702,7 @@ process_lock_contended_event(void *data,
|
|||
|
||||
static void
|
||||
process_lock_release_event(void *data,
|
||||
struct event *event __used,
|
||||
struct event_format *event __used,
|
||||
int cpu __used,
|
||||
u64 timestamp __used,
|
||||
struct thread *thread __used)
|
||||
|
@ -721,7 +721,7 @@ process_lock_release_event(void *data,
|
|||
static void
|
||||
process_raw_event(void *data, int cpu, u64 timestamp, struct thread *thread)
|
||||
{
|
||||
struct event *event;
|
||||
struct event_format *event;
|
||||
int type;
|
||||
|
||||
type = trace_parse_common_type(data);
|
||||
|
|
|
@ -728,34 +728,34 @@ struct trace_migrate_task_event {
|
|||
struct trace_sched_handler {
|
||||
void (*switch_event)(struct trace_switch_event *,
|
||||
struct machine *,
|
||||
struct event *,
|
||||
struct event_format *,
|
||||
int cpu,
|
||||
u64 timestamp,
|
||||
struct thread *thread);
|
||||
|
||||
void (*runtime_event)(struct trace_runtime_event *,
|
||||
struct machine *,
|
||||
struct event *,
|
||||
struct event_format *,
|
||||
int cpu,
|
||||
u64 timestamp,
|
||||
struct thread *thread);
|
||||
|
||||
void (*wakeup_event)(struct trace_wakeup_event *,
|
||||
struct machine *,
|
||||
struct event *,
|
||||
struct event_format *,
|
||||
int cpu,
|
||||
u64 timestamp,
|
||||
struct thread *thread);
|
||||
|
||||
void (*fork_event)(struct trace_fork_event *,
|
||||
struct event *,
|
||||
struct event_format *,
|
||||
int cpu,
|
||||
u64 timestamp,
|
||||
struct thread *thread);
|
||||
|
||||
void (*migrate_task_event)(struct trace_migrate_task_event *,
|
||||
struct machine *machine,
|
||||
struct event *,
|
||||
struct event_format *,
|
||||
int cpu,
|
||||
u64 timestamp,
|
||||
struct thread *thread);
|
||||
|
@ -765,7 +765,7 @@ struct trace_sched_handler {
|
|||
static void
|
||||
replay_wakeup_event(struct trace_wakeup_event *wakeup_event,
|
||||
struct machine *machine __used,
|
||||
struct event *event,
|
||||
struct event_format *event,
|
||||
int cpu __used,
|
||||
u64 timestamp __used,
|
||||
struct thread *thread __used)
|
||||
|
@ -792,7 +792,7 @@ static u64 cpu_last_switched[MAX_CPUS];
|
|||
static void
|
||||
replay_switch_event(struct trace_switch_event *switch_event,
|
||||
struct machine *machine __used,
|
||||
struct event *event,
|
||||
struct event_format *event,
|
||||
int cpu,
|
||||
u64 timestamp,
|
||||
struct thread *thread __used)
|
||||
|
@ -835,7 +835,7 @@ replay_switch_event(struct trace_switch_event *switch_event,
|
|||
|
||||
static void
|
||||
replay_fork_event(struct trace_fork_event *fork_event,
|
||||
struct event *event,
|
||||
struct event_format *event,
|
||||
int cpu __used,
|
||||
u64 timestamp __used,
|
||||
struct thread *thread __used)
|
||||
|
@ -944,7 +944,7 @@ static void thread_atoms_insert(struct thread *thread)
|
|||
|
||||
static void
|
||||
latency_fork_event(struct trace_fork_event *fork_event __used,
|
||||
struct event *event __used,
|
||||
struct event_format *event __used,
|
||||
int cpu __used,
|
||||
u64 timestamp __used,
|
||||
struct thread *thread __used)
|
||||
|
@ -1026,7 +1026,7 @@ add_sched_in_event(struct work_atoms *atoms, u64 timestamp)
|
|||
static void
|
||||
latency_switch_event(struct trace_switch_event *switch_event,
|
||||
struct machine *machine,
|
||||
struct event *event __used,
|
||||
struct event_format *event __used,
|
||||
int cpu,
|
||||
u64 timestamp,
|
||||
struct thread *thread __used)
|
||||
|
@ -1079,7 +1079,7 @@ latency_switch_event(struct trace_switch_event *switch_event,
|
|||
static void
|
||||
latency_runtime_event(struct trace_runtime_event *runtime_event,
|
||||
struct machine *machine,
|
||||
struct event *event __used,
|
||||
struct event_format *event __used,
|
||||
int cpu,
|
||||
u64 timestamp,
|
||||
struct thread *this_thread __used)
|
||||
|
@ -1102,7 +1102,7 @@ latency_runtime_event(struct trace_runtime_event *runtime_event,
|
|||
static void
|
||||
latency_wakeup_event(struct trace_wakeup_event *wakeup_event,
|
||||
struct machine *machine,
|
||||
struct event *__event __used,
|
||||
struct event_format *__event __used,
|
||||
int cpu __used,
|
||||
u64 timestamp,
|
||||
struct thread *thread __used)
|
||||
|
@ -1150,7 +1150,7 @@ latency_wakeup_event(struct trace_wakeup_event *wakeup_event,
|
|||
static void
|
||||
latency_migrate_task_event(struct trace_migrate_task_event *migrate_task_event,
|
||||
struct machine *machine,
|
||||
struct event *__event __used,
|
||||
struct event_format *__event __used,
|
||||
int cpu __used,
|
||||
u64 timestamp,
|
||||
struct thread *thread __used)
|
||||
|
@ -1361,7 +1361,7 @@ static struct trace_sched_handler *trace_handler;
|
|||
|
||||
static void
|
||||
process_sched_wakeup_event(struct perf_tool *tool __used,
|
||||
struct event *event,
|
||||
struct event_format *event,
|
||||
struct perf_sample *sample,
|
||||
struct machine *machine,
|
||||
struct thread *thread)
|
||||
|
@ -1398,7 +1398,7 @@ static char next_shortname2 = '0';
|
|||
static void
|
||||
map_switch_event(struct trace_switch_event *switch_event,
|
||||
struct machine *machine,
|
||||
struct event *event __used,
|
||||
struct event_format *event __used,
|
||||
int this_cpu,
|
||||
u64 timestamp,
|
||||
struct thread *thread __used)
|
||||
|
@ -1476,7 +1476,7 @@ map_switch_event(struct trace_switch_event *switch_event,
|
|||
|
||||
static void
|
||||
process_sched_switch_event(struct perf_tool *tool __used,
|
||||
struct event *event,
|
||||
struct event_format *event,
|
||||
struct perf_sample *sample,
|
||||
struct machine *machine,
|
||||
struct thread *thread)
|
||||
|
@ -1512,7 +1512,7 @@ process_sched_switch_event(struct perf_tool *tool __used,
|
|||
|
||||
static void
|
||||
process_sched_runtime_event(struct perf_tool *tool __used,
|
||||
struct event *event,
|
||||
struct event_format *event,
|
||||
struct perf_sample *sample,
|
||||
struct machine *machine,
|
||||
struct thread *thread)
|
||||
|
@ -1532,7 +1532,7 @@ process_sched_runtime_event(struct perf_tool *tool __used,
|
|||
|
||||
static void
|
||||
process_sched_fork_event(struct perf_tool *tool __used,
|
||||
struct event *event,
|
||||
struct event_format *event,
|
||||
struct perf_sample *sample,
|
||||
struct machine *machine __used,
|
||||
struct thread *thread)
|
||||
|
@ -1554,7 +1554,7 @@ process_sched_fork_event(struct perf_tool *tool __used,
|
|||
|
||||
static void
|
||||
process_sched_exit_event(struct perf_tool *tool __used,
|
||||
struct event *event,
|
||||
struct event_format *event,
|
||||
struct perf_sample *sample __used,
|
||||
struct machine *machine __used,
|
||||
struct thread *thread __used)
|
||||
|
@ -1565,7 +1565,7 @@ process_sched_exit_event(struct perf_tool *tool __used,
|
|||
|
||||
static void
|
||||
process_sched_migrate_task_event(struct perf_tool *tool __used,
|
||||
struct event *event,
|
||||
struct event_format *event,
|
||||
struct perf_sample *sample,
|
||||
struct machine *machine,
|
||||
struct thread *thread)
|
||||
|
@ -1586,7 +1586,7 @@ process_sched_migrate_task_event(struct perf_tool *tool __used,
|
|||
sample->time, thread);
|
||||
}
|
||||
|
||||
typedef void (*tracepoint_handler)(struct perf_tool *tool, struct event *event,
|
||||
typedef void (*tracepoint_handler)(struct perf_tool *tool, struct event_format *event,
|
||||
struct perf_sample *sample,
|
||||
struct machine *machine,
|
||||
struct thread *thread);
|
||||
|
|
|
@ -261,7 +261,7 @@ static void print_sample_start(struct perf_sample *sample,
|
|||
struct perf_event_attr *attr)
|
||||
{
|
||||
int type;
|
||||
struct event *event;
|
||||
struct event_format *event;
|
||||
const char *evname = NULL;
|
||||
unsigned long secs;
|
||||
unsigned long usecs;
|
||||
|
|
|
@ -37,7 +37,7 @@ PyMODINIT_FUNC initperf_trace_context(void);
|
|||
#define FTRACE_MAX_EVENT \
|
||||
((1 << (sizeof(unsigned short) * 8)) - 1)
|
||||
|
||||
struct event *events[FTRACE_MAX_EVENT];
|
||||
struct event_format *events[FTRACE_MAX_EVENT];
|
||||
|
||||
#define MAX_FIELDS 64
|
||||
#define N_COMMON_FIELDS 7
|
||||
|
@ -136,7 +136,7 @@ static void define_field(enum print_arg_type field_type,
|
|||
Py_DECREF(t);
|
||||
}
|
||||
|
||||
static void define_event_symbols(struct event *event,
|
||||
static void define_event_symbols(struct event_format *event,
|
||||
const char *ev_name,
|
||||
struct print_arg *args)
|
||||
{
|
||||
|
@ -178,6 +178,10 @@ static void define_event_symbols(struct event *event,
|
|||
define_event_symbols(event, ev_name, args->op.right);
|
||||
break;
|
||||
default:
|
||||
/* gcc warns for these? */
|
||||
case PRINT_BSTRING:
|
||||
case PRINT_DYNAMIC_ARRAY:
|
||||
case PRINT_FUNC:
|
||||
/* we should warn... */
|
||||
return;
|
||||
}
|
||||
|
@ -186,10 +190,10 @@ static void define_event_symbols(struct event *event,
|
|||
define_event_symbols(event, ev_name, args->next);
|
||||
}
|
||||
|
||||
static inline struct event *find_cache_event(int type)
|
||||
static inline struct event_format *find_cache_event(int type)
|
||||
{
|
||||
static char ev_name[256];
|
||||
struct event *event;
|
||||
struct event_format *event;
|
||||
|
||||
if (events[type])
|
||||
return events[type];
|
||||
|
@ -216,7 +220,7 @@ static void python_process_event(union perf_event *pevent __unused,
|
|||
struct format_field *field;
|
||||
unsigned long long val;
|
||||
unsigned long s, ns;
|
||||
struct event *event;
|
||||
struct event_format *event;
|
||||
unsigned n = 0;
|
||||
int type;
|
||||
int pid;
|
||||
|
@ -436,7 +440,7 @@ out:
|
|||
|
||||
static int python_generate_script(const char *outfile)
|
||||
{
|
||||
struct event *event = NULL;
|
||||
struct event_format *event = NULL;
|
||||
struct format_field *f;
|
||||
char fname[PATH_MAX];
|
||||
int not_first, count;
|
||||
|
|
|
@ -68,7 +68,7 @@ struct events {
|
|||
};
|
||||
|
||||
|
||||
void *malloc_or_die(unsigned int size)
|
||||
static void *malloc_or_die(unsigned int size)
|
||||
{
|
||||
void *data;
|
||||
|
||||
|
@ -448,6 +448,8 @@ static void tracing_data_header(void)
|
|||
else
|
||||
buf[0] = 0;
|
||||
|
||||
read_trace_init(buf[0], buf[0]);
|
||||
|
||||
write_or_die(buf, 1);
|
||||
|
||||
/* save size of long */
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -52,6 +52,16 @@ static unsigned long page_size;
|
|||
static ssize_t calc_data_size;
|
||||
static bool repipe;
|
||||
|
||||
static void *malloc_or_die(int size)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
ret = malloc(size);
|
||||
if (!ret)
|
||||
die("malloc");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int do_read(int fd, void *buf, int size)
|
||||
{
|
||||
int rsize = size;
|
||||
|
@ -109,7 +119,7 @@ static unsigned int read4(void)
|
|||
unsigned int data;
|
||||
|
||||
read_or_die(&data, 4);
|
||||
return __data2host4(data);
|
||||
return __data2host4(perf_pevent, data);
|
||||
}
|
||||
|
||||
static unsigned long long read8(void)
|
||||
|
@ -117,7 +127,7 @@ static unsigned long long read8(void)
|
|||
unsigned long long data;
|
||||
|
||||
read_or_die(&data, 8);
|
||||
return __data2host8(data);
|
||||
return __data2host8(perf_pevent, data);
|
||||
}
|
||||
|
||||
static char *read_string(void)
|
||||
|
@ -282,7 +292,7 @@ struct cpu_data {
|
|||
unsigned long long offset;
|
||||
unsigned long long size;
|
||||
unsigned long long timestamp;
|
||||
struct record *next;
|
||||
struct pevent_record *next;
|
||||
char *page;
|
||||
int cpu;
|
||||
int index;
|
||||
|
@ -367,9 +377,9 @@ static int calc_index(void *ptr, int cpu)
|
|||
return (unsigned long)ptr - (unsigned long)cpu_data[cpu].page;
|
||||
}
|
||||
|
||||
struct record *trace_peek_data(int cpu)
|
||||
struct pevent_record *trace_peek_data(int cpu)
|
||||
{
|
||||
struct record *data;
|
||||
struct pevent_record *data;
|
||||
void *page = cpu_data[cpu].page;
|
||||
int idx = cpu_data[cpu].index;
|
||||
void *ptr = page + idx;
|
||||
|
@ -389,15 +399,15 @@ struct record *trace_peek_data(int cpu)
|
|||
/* FIXME: handle header page */
|
||||
if (header_page_ts_size != 8)
|
||||
die("expected a long long type for timestamp");
|
||||
cpu_data[cpu].timestamp = data2host8(ptr);
|
||||
cpu_data[cpu].timestamp = data2host8(perf_pevent, ptr);
|
||||
ptr += 8;
|
||||
switch (header_page_size_size) {
|
||||
case 4:
|
||||
cpu_data[cpu].page_size = data2host4(ptr);
|
||||
cpu_data[cpu].page_size = data2host4(perf_pevent, ptr);
|
||||
ptr += 4;
|
||||
break;
|
||||
case 8:
|
||||
cpu_data[cpu].page_size = data2host8(ptr);
|
||||
cpu_data[cpu].page_size = data2host8(perf_pevent, ptr);
|
||||
ptr += 8;
|
||||
break;
|
||||
default:
|
||||
|
@ -414,7 +424,7 @@ read_again:
|
|||
return trace_peek_data(cpu);
|
||||
}
|
||||
|
||||
type_len_ts = data2host4(ptr);
|
||||
type_len_ts = data2host4(perf_pevent, ptr);
|
||||
ptr += 4;
|
||||
|
||||
type_len = type_len4host(type_len_ts);
|
||||
|
@ -424,14 +434,14 @@ read_again:
|
|||
case RINGBUF_TYPE_PADDING:
|
||||
if (!delta)
|
||||
die("error, hit unexpected end of page");
|
||||
length = data2host4(ptr);
|
||||
length = data2host4(perf_pevent, ptr);
|
||||
ptr += 4;
|
||||
length *= 4;
|
||||
ptr += length;
|
||||
goto read_again;
|
||||
|
||||
case RINGBUF_TYPE_TIME_EXTEND:
|
||||
extend = data2host4(ptr);
|
||||
extend = data2host4(perf_pevent, ptr);
|
||||
ptr += 4;
|
||||
extend <<= TS_SHIFT;
|
||||
extend += delta;
|
||||
|
@ -442,7 +452,7 @@ read_again:
|
|||
ptr += 12;
|
||||
break;
|
||||
case 0:
|
||||
length = data2host4(ptr);
|
||||
length = data2host4(perf_pevent, ptr);
|
||||
ptr += 4;
|
||||
die("here! length=%d", length);
|
||||
break;
|
||||
|
@ -467,9 +477,9 @@ read_again:
|
|||
return data;
|
||||
}
|
||||
|
||||
struct record *trace_read_data(int cpu)
|
||||
struct pevent_record *trace_read_data(int cpu)
|
||||
{
|
||||
struct record *data;
|
||||
struct pevent_record *data;
|
||||
|
||||
data = trace_peek_data(cpu);
|
||||
cpu_data[cpu].next = NULL;
|
||||
|
@ -509,6 +519,8 @@ ssize_t trace_report(int fd, bool __repipe)
|
|||
file_bigendian = buf[0];
|
||||
host_bigendian = bigendian();
|
||||
|
||||
read_trace_init(file_bigendian, host_bigendian);
|
||||
|
||||
read_or_die(buf, 1);
|
||||
long_size = buf[0];
|
||||
|
||||
|
@ -526,11 +538,11 @@ ssize_t trace_report(int fd, bool __repipe)
|
|||
repipe = false;
|
||||
|
||||
if (show_funcs) {
|
||||
print_funcs();
|
||||
pevent_print_funcs(perf_pevent);
|
||||
return size;
|
||||
}
|
||||
if (show_printk) {
|
||||
print_printk();
|
||||
pevent_print_printk(perf_pevent);
|
||||
return size;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,20 +1,21 @@
|
|||
#ifndef __PERF_TRACE_EVENTS_H
|
||||
#define __PERF_TRACE_EVENTS_H
|
||||
#ifndef _PERF_UTIL_TRACE_EVENT_H
|
||||
#define _PERF_UTIL_TRACE_EVENT_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "parse-events.h"
|
||||
#include "event-parse.h"
|
||||
#include "session.h"
|
||||
|
||||
struct machine;
|
||||
struct perf_sample;
|
||||
union perf_event;
|
||||
struct thread;
|
||||
|
||||
#define __unused __attribute__((unused))
|
||||
extern int header_page_size_size;
|
||||
extern int header_page_ts_size;
|
||||
extern int header_page_data_offset;
|
||||
|
||||
|
||||
#ifndef PAGE_MASK
|
||||
#define PAGE_MASK (page_size - 1)
|
||||
#endif
|
||||
extern bool latency_format;
|
||||
extern struct pevent *perf_pevent;
|
||||
|
||||
enum {
|
||||
RINGBUF_TYPE_PADDING = 29,
|
||||
|
@ -26,246 +27,37 @@ enum {
|
|||
#define TS_SHIFT 27
|
||||
#endif
|
||||
|
||||
#define NSECS_PER_SEC 1000000000ULL
|
||||
#define NSECS_PER_USEC 1000ULL
|
||||
int bigendian(void);
|
||||
|
||||
enum format_flags {
|
||||
FIELD_IS_ARRAY = 1,
|
||||
FIELD_IS_POINTER = 2,
|
||||
FIELD_IS_SIGNED = 4,
|
||||
FIELD_IS_STRING = 8,
|
||||
FIELD_IS_DYNAMIC = 16,
|
||||
FIELD_IS_FLAG = 32,
|
||||
FIELD_IS_SYMBOLIC = 64,
|
||||
};
|
||||
int read_trace_init(int file_bigendian, int host_bigendian);
|
||||
void print_trace_event(int cpu, void *data, int size);
|
||||
|
||||
struct format_field {
|
||||
struct format_field *next;
|
||||
char *type;
|
||||
char *name;
|
||||
int offset;
|
||||
int size;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
struct format {
|
||||
int nr_common;
|
||||
int nr_fields;
|
||||
struct format_field *common_fields;
|
||||
struct format_field *fields;
|
||||
};
|
||||
|
||||
struct print_arg_atom {
|
||||
char *atom;
|
||||
};
|
||||
|
||||
struct print_arg_string {
|
||||
char *string;
|
||||
int offset;
|
||||
};
|
||||
|
||||
struct print_arg_field {
|
||||
char *name;
|
||||
struct format_field *field;
|
||||
};
|
||||
|
||||
struct print_flag_sym {
|
||||
struct print_flag_sym *next;
|
||||
char *value;
|
||||
char *str;
|
||||
};
|
||||
|
||||
struct print_arg_typecast {
|
||||
char *type;
|
||||
struct print_arg *item;
|
||||
};
|
||||
|
||||
struct print_arg_flags {
|
||||
struct print_arg *field;
|
||||
char *delim;
|
||||
struct print_flag_sym *flags;
|
||||
};
|
||||
|
||||
struct print_arg_symbol {
|
||||
struct print_arg *field;
|
||||
struct print_flag_sym *symbols;
|
||||
};
|
||||
|
||||
struct print_arg;
|
||||
|
||||
struct print_arg_op {
|
||||
char *op;
|
||||
int prio;
|
||||
struct print_arg *left;
|
||||
struct print_arg *right;
|
||||
};
|
||||
|
||||
struct print_arg_func {
|
||||
char *name;
|
||||
struct print_arg *args;
|
||||
};
|
||||
|
||||
enum print_arg_type {
|
||||
PRINT_NULL,
|
||||
PRINT_ATOM,
|
||||
PRINT_FIELD,
|
||||
PRINT_FLAGS,
|
||||
PRINT_SYMBOL,
|
||||
PRINT_TYPE,
|
||||
PRINT_STRING,
|
||||
PRINT_OP,
|
||||
};
|
||||
|
||||
struct print_arg {
|
||||
struct print_arg *next;
|
||||
enum print_arg_type type;
|
||||
union {
|
||||
struct print_arg_atom atom;
|
||||
struct print_arg_field field;
|
||||
struct print_arg_typecast typecast;
|
||||
struct print_arg_flags flags;
|
||||
struct print_arg_symbol symbol;
|
||||
struct print_arg_func func;
|
||||
struct print_arg_string string;
|
||||
struct print_arg_op op;
|
||||
};
|
||||
};
|
||||
|
||||
struct print_fmt {
|
||||
char *format;
|
||||
struct print_arg *args;
|
||||
};
|
||||
|
||||
struct event {
|
||||
struct event *next;
|
||||
char *name;
|
||||
int id;
|
||||
int flags;
|
||||
struct format format;
|
||||
struct print_fmt print_fmt;
|
||||
char *system;
|
||||
};
|
||||
|
||||
enum {
|
||||
EVENT_FL_ISFTRACE = 0x01,
|
||||
EVENT_FL_ISPRINT = 0x02,
|
||||
EVENT_FL_ISBPRINT = 0x04,
|
||||
EVENT_FL_ISFUNC = 0x08,
|
||||
EVENT_FL_ISFUNCENT = 0x10,
|
||||
EVENT_FL_ISFUNCRET = 0x20,
|
||||
|
||||
EVENT_FL_FAILED = 0x80000000
|
||||
};
|
||||
|
||||
struct record {
|
||||
unsigned long long ts;
|
||||
int size;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct record *trace_peek_data(int cpu);
|
||||
struct record *trace_read_data(int cpu);
|
||||
|
||||
void parse_set_info(int nr_cpus, int long_sz);
|
||||
|
||||
ssize_t trace_report(int fd, bool repipe);
|
||||
|
||||
void *malloc_or_die(unsigned int size);
|
||||
|
||||
void parse_cmdlines(char *file, int size);
|
||||
void parse_proc_kallsyms(char *file, unsigned int size);
|
||||
void parse_ftrace_printk(char *file, unsigned int size);
|
||||
|
||||
void print_funcs(void);
|
||||
void print_printk(void);
|
||||
void print_event(int cpu, void *data, int size, unsigned long long nsecs,
|
||||
char *comm);
|
||||
|
||||
int parse_ftrace_file(char *buf, unsigned long size);
|
||||
int parse_event_file(char *buf, unsigned long size, char *sys);
|
||||
void print_trace_event(int cpu, void *data, int size);
|
||||
|
||||
extern int file_bigendian;
|
||||
extern int host_bigendian;
|
||||
struct pevent_record *trace_peek_data(int cpu);
|
||||
struct event_format *trace_find_event(int type);
|
||||
|
||||
int bigendian(void);
|
||||
unsigned long long
|
||||
raw_field_value(struct event_format *event, const char *name, void *data);
|
||||
void *raw_field_ptr(struct event_format *event, const char *name, void *data);
|
||||
|
||||
static inline unsigned short __data2host2(unsigned short data)
|
||||
{
|
||||
unsigned short swap;
|
||||
void parse_proc_kallsyms(char *file, unsigned int size __unused);
|
||||
void parse_ftrace_printk(char *file, unsigned int size __unused);
|
||||
|
||||
if (host_bigendian == file_bigendian)
|
||||
return data;
|
||||
|
||||
swap = ((data & 0xffULL) << 8) |
|
||||
((data & (0xffULL << 8)) >> 8);
|
||||
|
||||
return swap;
|
||||
}
|
||||
|
||||
static inline unsigned int __data2host4(unsigned int data)
|
||||
{
|
||||
unsigned int swap;
|
||||
|
||||
if (host_bigendian == file_bigendian)
|
||||
return data;
|
||||
|
||||
swap = ((data & 0xffULL) << 24) |
|
||||
((data & (0xffULL << 8)) << 8) |
|
||||
((data & (0xffULL << 16)) >> 8) |
|
||||
((data & (0xffULL << 24)) >> 24);
|
||||
|
||||
return swap;
|
||||
}
|
||||
|
||||
static inline unsigned long long __data2host8(unsigned long long data)
|
||||
{
|
||||
unsigned long long swap;
|
||||
|
||||
if (host_bigendian == 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;
|
||||
}
|
||||
|
||||
#define data2host2(ptr) __data2host2(*(unsigned short *)ptr)
|
||||
#define data2host4(ptr) __data2host4(*(unsigned int *)ptr)
|
||||
#define data2host8(ptr) ({ \
|
||||
unsigned long long __val; \
|
||||
\
|
||||
memcpy(&__val, (ptr), sizeof(unsigned long long)); \
|
||||
__data2host8(__val); \
|
||||
})
|
||||
|
||||
extern int header_page_ts_offset;
|
||||
extern int header_page_ts_size;
|
||||
extern int header_page_size_offset;
|
||||
extern int header_page_size_size;
|
||||
extern int header_page_data_offset;
|
||||
extern int header_page_data_size;
|
||||
|
||||
extern bool latency_format;
|
||||
ssize_t trace_report(int fd, bool repipe);
|
||||
|
||||
int trace_parse_common_type(void *data);
|
||||
int trace_parse_common_pid(void *data);
|
||||
int parse_common_pc(void *data);
|
||||
int parse_common_flags(void *data);
|
||||
int parse_common_lock_depth(void *data);
|
||||
struct event *trace_find_event(int id);
|
||||
struct event *trace_find_next_event(struct event *event);
|
||||
|
||||
struct event_format *trace_find_next_event(struct event_format *event);
|
||||
unsigned long long read_size(void *ptr, int size);
|
||||
unsigned long long
|
||||
raw_field_value(struct event *event, const char *name, void *data);
|
||||
void *raw_field_ptr(struct event *event, const char *name, void *data);
|
||||
unsigned long long eval_flag(const char *flag);
|
||||
|
||||
struct pevent_record *trace_read_data(int cpu);
|
||||
int read_tracing_data(int fd, struct list_head *pattrs);
|
||||
|
||||
struct tracing_data {
|
||||
|
@ -280,15 +72,6 @@ struct tracing_data *tracing_data_get(struct list_head *pattrs,
|
|||
void tracing_data_put(struct tracing_data *tdata);
|
||||
|
||||
|
||||
/* taken from kernel/trace/trace.h */
|
||||
enum trace_flag_type {
|
||||
TRACE_FLAG_IRQS_OFF = 0x01,
|
||||
TRACE_FLAG_IRQS_NOSUPPORT = 0x02,
|
||||
TRACE_FLAG_NEED_RESCHED = 0x04,
|
||||
TRACE_FLAG_HARDIRQ = 0x08,
|
||||
TRACE_FLAG_SOFTIRQ = 0x10,
|
||||
};
|
||||
|
||||
struct scripting_ops {
|
||||
const char *name;
|
||||
int (*start_script) (const char *script, int argc, const char **argv);
|
||||
|
@ -314,4 +97,4 @@ int common_pc(struct scripting_context *context);
|
|||
int common_flags(struct scripting_context *context);
|
||||
int common_lock_depth(struct scripting_context *context);
|
||||
|
||||
#endif /* __PERF_TRACE_EVENTS_H */
|
||||
#endif /* _PERF_UTIL_TRACE_EVENT_H */
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
ifeq ("$(origin O)", "command line")
|
||||
OUTPUT := $(O)/
|
||||
COMMAND_O := O=$(O)
|
||||
endif
|
||||
|
||||
ifneq ($(OUTPUT),)
|
||||
|
|
Loading…
Reference in a new issue