Projects
openEuler:24.03:SP1:Everything:64G
libtraceevent
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 2
View file
_service:tar_scm:libtraceevent.spec
Changed
@@ -1,6 +1,6 @@ Name: libtraceevent -Version: 1.2.1 -Release: 4 +Version: 1.8.2 +Release: 1 License: LGPLv2+ and GPLv2+ Summary: Library to parse raw trace event formats @@ -30,8 +30,8 @@ %build MANPAGE_DOCBOOK_XSL=`rpm -ql docbook-style-xsl | grep manpages/docbook.xsl` -%set_build_flags -%make_build prefix=%{_prefix} libdir=%{_libdir} MANPAGE_XSL=%{MANPAGE_DOCBOOK_XSL} all doc +# Parallel build does not work +make -O -j1 V=1 VERBOSE=1 CFLAGS="%{build_cflags}" LDFLAGS="%{build_ldflags}" prefix=%{_prefix} libdir=%{_libdir} MANPAGE_XSL=%{MANPAGE_DOCBOOK_XSL} all doc %install %make_install prefix=%{_prefix} libdir=%{_libdir} install doc-install @@ -43,9 +43,10 @@ %{_libdir}/traceevent/ %{_libdir}/libtraceevent.so.%{version} %{_libdir}/libtraceevent.so.1 -%{_mandir}/man3/tep_*.3.* -%{_mandir}/man3/libtraceevent.3.* -%{_mandir}/man3/trace_seq*.3.* +%{_mandir}/man3/tep_*.3* +%{_mandir}/man3/libtraceevent.3* +%{_mandir}/man3/trace_seq*.3* +%{_mandir}/man3/kbuffer_*.3* %{_docdir}/%{name}-doc %files devel @@ -54,6 +55,9 @@ %{_libdir}/pkgconfig/libtraceevent.pc %changelog +* Sun Jun 30 2024 shafeipaozi <sunbo.oerv@isrc.iscas.ac.cn> - 1.8.2-1 +- update to 1.8.2 + * Thu Jul 13 2023 liyanan <thistleslyn@163.com> - 1.2.1-4 - Delete confilt with perf when the kernel is greater than 6.2
View file
_service:tar_scm:0001-fix-missing-fstack-protector-strong.patch
Changed
@@ -1,8 +1,8 @@ diff --git a/Makefile b/Makefile -index 089b621..3665e0f 100644 +index 41ad866..20ae048 100644 --- a/Makefile +++ b/Makefile -@@ -113,7 +113,7 @@ INCLUDES = -I. -I $(srctree)/include $(CONFIG_INCLUDES) +@@ -127,7 +127,7 @@ export LIBTRACEEVENT_STATIC LIBTRACEEVENT_SHARED EP_HEADERS_DIR ifdef EXTRA_CFLAGS CFLAGS := $(EXTRA_CFLAGS) else @@ -10,12 +10,12 @@ + CFLAGS := -g -Wall -fstack-protector-strong endif - LIBS = -ldl + LIBS ?= -ldl diff --git a/plugins/Makefile b/plugins/Makefile -index b60352d..d5744a9 100644 +index 4c8cb17..56b5646 100644 --- a/plugins/Makefile +++ b/plugins/Makefile -@@ -75,7 +75,7 @@ INCLUDES = -I. -I.. -I../src -I $(srctree)/include $(CONFIG_INCLUDES) +@@ -68,7 +68,7 @@ INCLUDES = -I. -I.. -I../src -I $(srctree)/include -I $(EP_HEADERS_DIR) $(CONFIG ifdef EXTRA_CFLAGS CFLAGS := $(EXTRA_CFLAGS) else
View file
_service
Changed
@@ -2,7 +2,7 @@ <service name="tar_scm"> <param name="scm">git</param> <param name="url">git@gitee.com:src-openeuler/libtraceevent.git</param> - <param name="revision">openEuler-24.03-LTS-Next</param> + <param name="revision">openEuler-24.03-LTS-SP1</param> <param name="exclude">*</param> <param name="extract">*</param> </service>
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/build
Deleted
-(directory)
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/build/Build.include
Deleted
@@ -1,103 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -### -# build: Generic definitions -# -# Lots of this code have been borrowed or heavily inspired from parts -# of kbuild code, which is not credited, but mostly developed by: -# -# Copyright (C) Sam Ravnborg <sam@mars.ravnborg.org>, 2015 -# Copyright (C) Linus Torvalds <torvalds@linux-foundation.org>, 2015 -# - -### -# Convenient variables -comma := , -squote := ' -pound := \# - -### -# Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o -dot-target = $(dir $@).$(notdir $@) - -### -# filename of target with directory and extension stripped -basetarget = $(basename $(notdir $@)) - -### -# The temporary file to save gcc -MD generated dependencies must not -# contain a comma -depfile = $(subst $(comma),_,$(dot-target).d) - -### -# Check if both arguments has same arguments. Result is empty string if equal. -arg-check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \ - $(filter-out $(cmd_$@), $(cmd_$(1))) ) - -### -# Escape single quote for use in echo statements -escsq = $(subst $(squote),'\$(squote)',$1) - -# Echo command -# Short version is used, if $(quiet) equals `quiet_', otherwise full one. -echo-cmd = $(if $($(quiet)cmd_$(1)),\ - echo ' $(call escsq,$($(quiet)cmd_$(1)))';) - -### -# Replace >$< with >$$< to preserve $ when reloading the .cmd file -# (needed for make) -# Replace >#< with >$(pound)< to avoid starting a comment in the .cmd file -# (needed for make) -# Replace >'< with >'\''< to be able to enclose the whole string in '...' -# (needed for the shell) -make-cmd = $(call escsq,$(subst $(pound),$$(pound),$(subst $$,$$$$,$(cmd_$(1))))) - -### -# Find any prerequisites that is newer than target or that does not exist. -# PHONY targets skipped in both cases. -any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^) - -### -# Copy dependency data into .cmd file -# - gcc -M dependency info -# - command line to create object 'cmd_object :=' -dep-cmd = $(if $(wildcard $(fixdep)), \ - $(fixdep) $(depfile) $@ '$(make-cmd)' > $(dot-target).tmp; \ - rm -f $(depfile); \ - mv -f $(dot-target).tmp $(dot-target).cmd, \ - printf '$(pound) cannot find fixdep (%s)\n' $(fixdep) > $(dot-target).cmd; \ - printf '$(pound) using basic dep data\n\n' >> $(dot-target).cmd; \ - cat $(depfile) >> $(dot-target).cmd; \ - printf '\n%s\n' 'cmd_$@ := $(make-cmd)' >> $(dot-target).cmd) - -### -# if_changed_dep - execute command if any prerequisite is newer than -# target, or command line has changed and update -# dependencies in the cmd file -if_changed_dep = $(if $(strip $(any-prereq) $(arg-check)), \ - @set -e; \ - $(echo-cmd) $(cmd_$(1)); \ - $(dep-cmd)) - -# if_changed - execute command if any prerequisite is newer than -# target, or command line has changed -if_changed = $(if $(strip $(any-prereq) $(arg-check)), \ - @set -e; \ - $(echo-cmd) $(cmd_$(1)); \ - printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd) - -### -# C flags to be used in rule definitions, includes: -# - depfile generation -# - global $(CFLAGS) -# - per target C flags -# - per object C flags -# - BUILD_STR macro to allow '-D"$(variable)"' constructs -c_flags_1 = -Wp,-MD,$(depfile) -Wp,-MT,$@ $(CFLAGS) -D"BUILD_STR(s)=\#s" $(CFLAGS_$(basetarget).o) $(CFLAGS_$(obj)) -c_flags_2 = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(c_flags_1)) -c_flags = $(filter-out $(CFLAGS_REMOVE_$(obj)), $(c_flags_2)) -cxx_flags = -Wp,-MD,$(depfile) -Wp,-MT,$@ $(CXXFLAGS) -D"BUILD_STR(s)=\#s" $(CXXFLAGS_$(basetarget).o) $(CXXFLAGS_$(obj)) - -### -## HOSTCC C flags - -host_c_flags = -Wp,-MD,$(depfile) -Wp,-MT,$@ $(KBUILD_HOSTCFLAGS) -D"BUILD_STR(s)=\#s" $(HOSTCFLAGS_$(basetarget).o) $(HOSTCFLAGS_$(obj))
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/build/Makefile.build
Deleted
@@ -1,162 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -### -# Main build makefile. -# -# Lots of this code have been borrowed or heavily inspired from parts -# of kbuild code, which is not credited, but mostly developed by: -# -# Copyright (C) Sam Ravnborg <sam@mars.ravnborg.org>, 2015 -# Copyright (C) Linus Torvalds <torvalds@linux-foundation.org>, 2015 -# - -PHONY := __build -__build: - -ifeq ($(V),1) - quiet = - Q = -else - quiet=quiet_ - Q=@ -endif - -ifneq ($(findstring s,$(filter-out --%,$(MAKEFLAGS))),) - quiet=silent_ -endif - -build-dir := $(srctree)/build - -# Define $(fixdep) for dep-cmd function -ifeq ($(OUTPUT),) - fixdep := $(build-dir)/fixdep -else - fixdep := $(OUTPUT)/fixdep -endif - -# Generic definitions -include $(build-dir)/Build.include - -# do not force detected configuration --include $(OUTPUT).config-detected - -# Init all relevant variables used in build files so -# 1) they have correct type -# 2) they do not inherit any value from the environment -subdir-y := -obj-y := -subdir-y := -subdir-obj-y := - -# Build definitions -build-file := $(dir)/Build --include $(build-file) - -quiet_cmd_flex = FLEX $@ -quiet_cmd_bison = BISON $@ - -# Create directory unless it exists -quiet_cmd_mkdir = MKDIR $(dir $@) - cmd_mkdir = mkdir -p $(dir $@) - rule_mkdir = $(if $(wildcard $(dir $@)),,@$(call echo-cmd,mkdir) $(cmd_mkdir)) - -# Compile command -quiet_cmd_cc_o_c = CC $@ - cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< - -quiet_cmd_host_cc_o_c = HOSTCC $@ - cmd_host_cc_o_c = $(HOSTCC) $(host_c_flags) -c -o $@ $< - -quiet_cmd_cxx_o_c = CXX $@ - cmd_cxx_o_c = $(CXX) $(cxx_flags) -c -o $@ $< - -quiet_cmd_cpp_i_c = CPP $@ - cmd_cpp_i_c = $(CC) $(c_flags) -E -o $@ $< - -quiet_cmd_cc_s_c = AS $@ - cmd_cc_s_c = $(CC) $(c_flags) -S -o $@ $< - -quiet_cmd_gen = GEN $@ - -# Link agregate command -# If there's nothing to link, create empty $@ object. -quiet_cmd_ld_multi = LD $@ - cmd_ld_multi = $(if $(strip $(obj-y)),\ - $(LD) -r -o $@ $(filter $(obj-y),$^),rm -f $@; $(AR) rcs $@) - -quiet_cmd_host_ld_multi = HOSTLD $@ - cmd_host_ld_multi = $(if $(strip $(obj-y)),\ - $(HOSTLD) -r -o $@ $(filter $(obj-y),$^),rm -f $@; $(HOSTAR) rcs $@) - -ifneq ($(filter $(obj),$(hostprogs)),) - host = host_ -endif - -# Build rules -$(OUTPUT)%.o: %.c FORCE - $(call rule_mkdir) - $(call if_changed_dep,$(host)cc_o_c) - -$(OUTPUT)%.o: %.cpp FORCE - $(call rule_mkdir) - $(call if_changed_dep,cxx_o_c) - -$(OUTPUT)%.o: %.S FORCE - $(call rule_mkdir) - $(call if_changed_dep,$(host)cc_o_c) - -$(OUTPUT)%.i: %.c FORCE - $(call rule_mkdir) - $(call if_changed_dep,cpp_i_c) - -$(OUTPUT)%.s: %.S FORCE - $(call rule_mkdir) - $(call if_changed_dep,cpp_i_c) - -$(OUTPUT)%.s: %.c FORCE - $(call rule_mkdir) - $(call if_changed_dep,cc_s_c) - -# Gather build data: -# obj-y - list of build objects -# subdir-y - list of directories to nest -# subdir-obj-y - list of directories objects 'dir/$(obj)-in.o' -obj-y := $($(obj)-y) -subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y))) -obj-y := $(patsubst %/, %/$(obj)-in.o, $(obj-y)) -subdir-obj-y := $(filter %/$(obj)-in.o, $(obj-y)) - -# '$(OUTPUT)/dir' prefix to all objects -objprefix := $(subst ./,,$(OUTPUT)$(dir)/) -obj-y := $(addprefix $(objprefix),$(obj-y)) -subdir-obj-y := $(addprefix $(objprefix),$(subdir-obj-y)) - -# Final '$(obj)-in.o' object -in-target := $(objprefix)$(obj)-in.o - -PHONY += $(subdir-y) - -$(subdir-y): - $(Q)$(MAKE) -f $(build-dir)/Makefile.build dir=$(dir)/$@ obj=$(obj) - -$(sort $(subdir-obj-y)): $(subdir-y) ; - -$(in-target): $(obj-y) FORCE - $(call rule_mkdir) - $(call if_changed,$(host)ld_multi) - -__build: $(in-target) - @: - -PHONY += FORCE -FORCE: - -# Include all cmd files to get all the dependency rules -# for all objects included -targets := $(wildcard $(sort $(obj-y) $(in-target) $(MAKECMDGOALS))) -cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd)) - -ifneq ($(cmd_files),) - include $(cmd_files) -endif - -.PHONY: $(PHONY)
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/scripts/Makefile.include
Deleted
@@ -1,135 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -ifneq ($(O),) -ifeq ($(origin O), command line) - dummy := $(if $(shell cd $(PWD); test -d $(O) || echo $(O)),$(error O=$(O) does not exist),) - ABSOLUTE_O := $(shell cd $(PWD); cd $(O) ; pwd) - OUTPUT := $(ABSOLUTE_O)/$(if $(subdir),$(subdir)/) - COMMAND_O := O=$(ABSOLUTE_O) -ifeq ($(objtree),) - objtree := $(O) -endif -endif -endif - -# check that the output directory actually exists -ifneq ($(OUTPUT),) -OUTDIR := $(shell cd $(OUTPUT) && pwd) -$(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist)) -endif - -# -# Include saner warnings here, which can catch bugs: -# -EXTRA_WARNINGS := -Wbad-function-cast -EXTRA_WARNINGS += -Wdeclaration-after-statement -EXTRA_WARNINGS += -Wformat-security -EXTRA_WARNINGS += -Wformat-y2k -EXTRA_WARNINGS += -Winit-self -EXTRA_WARNINGS += -Wmissing-declarations -EXTRA_WARNINGS += -Wmissing-prototypes -EXTRA_WARNINGS += -Wnested-externs -EXTRA_WARNINGS += -Wno-system-headers -EXTRA_WARNINGS += -Wold-style-definition -EXTRA_WARNINGS += -Wpacked -EXTRA_WARNINGS += -Wredundant-decls -EXTRA_WARNINGS += -Wstrict-prototypes -EXTRA_WARNINGS += -Wswitch-default -EXTRA_WARNINGS += -Wswitch-enum -EXTRA_WARNINGS += -Wundef -EXTRA_WARNINGS += -Wwrite-strings -EXTRA_WARNINGS += -Wformat - -CC_NO_CLANG := $(shell $(CC) -dM -E -x c /dev/null | grep -Fq "__clang__"; echo $$?) - -# 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 various cross-compile vars or setting CROSS_COMPILE as a prefix. -$(call allow-override,CC,$(CROSS_COMPILE)gcc) -$(call allow-override,AR,$(CROSS_COMPILE)ar) -$(call allow-override,LD,$(CROSS_COMPILE)ld) -$(call allow-override,CXX,$(CROSS_COMPILE)g++) -$(call allow-override,STRIP,$(CROSS_COMPILE)strip) - -ifeq ($(CC_NO_CLANG), 1) -EXTRA_WARNINGS += -Wstrict-aliasing=3 -endif - -# Hack to avoid type-punned warnings on old systems such as RHEL5: -# We should be changing CFLAGS and checking gcc version, but this -# will do for now and keep the above -Wstrict-aliasing=3 in place -# in newer systems. -# Needed for the __raw_cmpxchg in tools/arch/x86/include/asm/cmpxchg.h -# -# See https://lkml.org/lkml/2006/11/28/253 and https://gcc.gnu.org/gcc-4.8/changes.html, -# that takes into account Linus's comments (search for Wshadow) for the reasoning about -# -Wshadow not being interesting before gcc 4.8. - -ifneq ($(filter 3.%,$(MAKE_VERSION)),) # make-3 -EXTRA_WARNINGS += -fno-strict-aliasing -EXTRA_WARNINGS += -Wno-shadow -else -EXTRA_WARNINGS += -Wshadow -endif - -ifneq ($(findstring $(MAKEFLAGS), w),w) -PRINT_DIR = --no-print-directory -else -NO_SUBDIR = : -endif - -ifneq ($(findstring s,$(filter-out --%,$(MAKEFLAGS))),) - silent=1 -endif - -# -# Define a callable command for descending to a new directory -# -# Call by doing: $(call descend,directory,target) -# -descend = \ - +mkdir -p $(OUTPUT)$(1) && \ - $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) $(2) - -QUIET_SUBDIR0 = +$(MAKE) $(COMMAND_O) -C # space to separate -C and subdir -QUIET_SUBDIR1 = - -ifneq ($(silent),1) - ifneq ($(V),1) - QUIET_CC = @echo ' CC '$@; - QUIET_CC_FPIC = @echo ' CC FPIC '$@; - QUIET_CLANG = @echo ' CLANG '$@; - QUIET_AR = @echo ' AR '$@; - QUIET_LINK = @echo ' LINK '$@; - QUIET_MKDIR = @echo ' MKDIR '$@; - PRINT_GEN = echo ' GEN '$@; - QUIET_GEN = @echo ' GEN '$@; - QUIET_SUBDIR0 = +@subdir= - QUIET_SUBDIR1 = ;$(NO_SUBDIR) \ - echo ' SUBDIR '$$subdir; \ - $(MAKE) $(PRINT_DIR) -C $$subdir - QUIET_FLEX = @echo ' FLEX '$@; - QUIET_BISON = @echo ' BISON '$@; - - descend = \ - +@echo ' DESCEND '$(1); \ - mkdir -p $(OUTPUT)$(1) && \ - $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) $(2) - - PRINT_INSTALL = printf ' INSTALL %s\n' $1; - PRINT_UNINST = printf ' UNINST %s\n' $1; - QUIET_CLEAN = @printf ' CLEAN %s\n' $1; - QUIET_INSTALL = @printf ' INSTALL %s\n' $1; - QUIET_UNINST = @printf ' UNINST %s\n' $1; - endif -endif - -pound := \#
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/src/event-parse.h
Deleted
@@ -1,752 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1 */ -/* - * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> - * - */ -#ifndef _PARSE_EVENTS_H -#define _PARSE_EVENTS_H - -#include <stdbool.h> -#include <stdarg.h> -#include <stdio.h> -#include <regex.h> -#include <string.h> - -#include "trace-seq.h" - -#ifndef __maybe_unused -#define __maybe_unused __attribute__((unused)) -#endif - -#ifndef DEBUG_RECORD -#define DEBUG_RECORD 0 -#endif - -struct tep_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 *priv; -#if DEBUG_RECORD - struct tep_record *prev; - struct tep_record *next; - long alloc_addr; -#endif -}; - -/* ----------------------- tep ----------------------- */ - -struct tep_handle; -struct tep_event; - -typedef int (*tep_event_handler_func)(struct trace_seq *s, - struct tep_record *record, - struct tep_event *event, - void *context); - -typedef int (*tep_plugin_load_func)(struct tep_handle *tep); -typedef int (*tep_plugin_unload_func)(struct tep_handle *tep); - -struct tep_plugin_option { - struct tep_plugin_option *next; - void *handle; - char *file; - char *name; - char *plugin_alias; - char *description; - const char *value; - void *priv; - int set; -}; - -/* - * Plugin hooks that can be called: - * - * TEP_PLUGIN_LOADER: (required) - * The function name to initialized the plugin. - * - * int TEP_PLUGIN_LOADER(struct tep_handle *tep) - * - * TEP_PLUGIN_UNLOADER: (optional) - * The function called just before unloading - * - * int TEP_PLUGIN_UNLOADER(struct tep_handle *tep) - * - * TEP_PLUGIN_OPTIONS: (optional) - * Plugin options that can be set before loading - * - * struct tep_plugin_option TEP_PLUGIN_OPTIONS = { - * { - * .name = "option-name", - * .plugin_alias = "override-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. - * - * If .value is not set, then it is considered a boolean and only - * .set will be processed. If .value is defined, then it is considered - * a string option and .set will be ignored. - * - * TEP_PLUGIN_ALIAS: (optional) - * The name to use for finding options (uses filename if not defined) - */ -#define TEP_PLUGIN_LOADER tep_plugin_loader -#define TEP_PLUGIN_UNLOADER tep_plugin_unloader -#define TEP_PLUGIN_OPTIONS tep_plugin_options -#define TEP_PLUGIN_ALIAS tep_plugin_alias -#define _MAKE_STR(x) #x -#define MAKE_STR(x) _MAKE_STR(x) -#define TEP_PLUGIN_LOADER_NAME MAKE_STR(TEP_PLUGIN_LOADER) -#define TEP_PLUGIN_UNLOADER_NAME MAKE_STR(TEP_PLUGIN_UNLOADER) -#define TEP_PLUGIN_OPTIONS_NAME MAKE_STR(TEP_PLUGIN_OPTIONS) -#define TEP_PLUGIN_ALIAS_NAME MAKE_STR(TEP_PLUGIN_ALIAS) - -enum tep_format_flags { - TEP_FIELD_IS_ARRAY = 1, - TEP_FIELD_IS_POINTER = 2, - TEP_FIELD_IS_SIGNED = 4, - TEP_FIELD_IS_STRING = 8, - TEP_FIELD_IS_DYNAMIC = 16, - TEP_FIELD_IS_LONG = 32, - TEP_FIELD_IS_FLAG = 64, - TEP_FIELD_IS_SYMBOLIC = 128, -}; - -struct tep_format_field { - struct tep_format_field *next; - struct tep_event *event; - char *type; - char *name; - char *alias; - int offset; - int size; - unsigned int arraylen; - unsigned int elementsize; - unsigned long flags; -}; - -struct tep_format { - int nr_common; - int nr_fields; - struct tep_format_field *common_fields; - struct tep_format_field *fields; -}; - -struct tep_print_arg_atom { - char *atom; -}; - -struct tep_print_arg_string { - char *string; - int offset; -}; - -struct tep_print_arg_bitmask { - char *bitmask; - int offset; -}; - -struct tep_print_arg_field { - char *name; - struct tep_format_field *field; -}; - -struct tep_print_flag_sym { - struct tep_print_flag_sym *next; - char *value; - char *str; -}; - -struct tep_print_arg_typecast { - char *type; - struct tep_print_arg *item; -}; - -struct tep_print_arg_flags { - struct tep_print_arg *field; - char *delim; - struct tep_print_flag_sym *flags; -}; - -struct tep_print_arg_symbol { - struct tep_print_arg *field; - struct tep_print_flag_sym *symbols; -}; - -struct tep_print_arg_hex { - struct tep_print_arg *field; - struct tep_print_arg *size; -}; - -struct tep_print_arg_int_array { - struct tep_print_arg *field; - struct tep_print_arg *count; - struct tep_print_arg *el_size; -}; - -struct tep_print_arg_dynarray { - struct tep_format_field *field; - struct tep_print_arg *index; -}; - -struct tep_print_arg; - -struct tep_print_arg_op { - char *op; - int prio; - struct tep_print_arg *left; - struct tep_print_arg *right; -}; - -struct tep_function_handler; - -struct tep_print_arg_func { - struct tep_function_handler *func; - struct tep_print_arg *args; -}; - -enum tep_print_arg_type { - TEP_PRINT_NULL, - TEP_PRINT_ATOM, - TEP_PRINT_FIELD, - TEP_PRINT_FLAGS, - TEP_PRINT_SYMBOL, - TEP_PRINT_HEX, - TEP_PRINT_INT_ARRAY, - TEP_PRINT_TYPE, - TEP_PRINT_STRING, - TEP_PRINT_BSTRING, - TEP_PRINT_DYNAMIC_ARRAY, - TEP_PRINT_OP, - TEP_PRINT_FUNC, - TEP_PRINT_BITMASK, - TEP_PRINT_DYNAMIC_ARRAY_LEN, - TEP_PRINT_HEX_STR, -}; - -struct tep_print_arg { - struct tep_print_arg *next; - enum tep_print_arg_type type; - union { - struct tep_print_arg_atom atom; - struct tep_print_arg_field field; - struct tep_print_arg_typecast typecast; - struct tep_print_arg_flags flags; - struct tep_print_arg_symbol symbol; - struct tep_print_arg_hex hex; - struct tep_print_arg_int_array int_array; - struct tep_print_arg_func func; - struct tep_print_arg_string string; - struct tep_print_arg_bitmask bitmask; - struct tep_print_arg_op op; - struct tep_print_arg_dynarray dynarray; - }; -}; - -struct tep_print_parse; - -struct tep_print_fmt { - char *format; - struct tep_print_arg *args; - struct tep_print_parse *print_cache; -}; - -struct tep_event { - struct tep_handle *tep; - char *name; - int id; - int flags; - struct tep_format format; - struct tep_print_fmt print_fmt; - char *system; - tep_event_handler_func handler; - void *context; -}; - -enum { - TEP_EVENT_FL_ISFTRACE = 0x01, - TEP_EVENT_FL_ISPRINT = 0x02, - TEP_EVENT_FL_ISBPRINT = 0x04, - TEP_EVENT_FL_ISFUNCENT = 0x10, - TEP_EVENT_FL_ISFUNCRET = 0x20, - TEP_EVENT_FL_NOHANDLE = 0x40, - TEP_EVENT_FL_PRINTRAW = 0x80, - - TEP_EVENT_FL_FAILED = 0x80000000 -}; - -enum tep_event_sort_type { - TEP_EVENT_SORT_ID, - TEP_EVENT_SORT_NAME, - TEP_EVENT_SORT_SYSTEM, -}; - -enum tep_event_type { - TEP_EVENT_ERROR, - TEP_EVENT_NONE, - TEP_EVENT_SPACE, - TEP_EVENT_NEWLINE, - TEP_EVENT_OP, - TEP_EVENT_DELIM, - TEP_EVENT_ITEM, - TEP_EVENT_DQUOTE, - TEP_EVENT_SQUOTE, -}; - -typedef unsigned long long (*tep_func_handler)(struct trace_seq *s, - unsigned long long *args); - -enum tep_func_arg_type { - TEP_FUNC_ARG_VOID, - TEP_FUNC_ARG_INT, - TEP_FUNC_ARG_LONG, - TEP_FUNC_ARG_STRING, - TEP_FUNC_ARG_PTR, - TEP_FUNC_ARG_MAX_TYPES -}; - -enum tep_flag { - TEP_NSEC_OUTPUT = 1, /* output in NSECS */ - TEP_DISABLE_SYS_PLUGINS = 1 << 1, - TEP_DISABLE_PLUGINS = 1 << 2, -}; - -#define TEP_ERRORS \ - _PE(MEM_ALLOC_FAILED, "failed to allocate memory"), \ - _PE(PARSE_EVENT_FAILED, "failed to parse event"), \ - _PE(READ_ID_FAILED, "failed to read event id"), \ - _PE(READ_FORMAT_FAILED, "failed to read event format"), \ - _PE(READ_PRINT_FAILED, "failed to read event print fmt"), \ - _PE(OLD_FTRACE_ARG_FAILED,"failed to allocate field name for ftrace"),\ - _PE(INVALID_ARG_TYPE, "invalid argument type"), \ - _PE(INVALID_EXP_TYPE, "invalid expression type"), \ - _PE(INVALID_OP_TYPE, "invalid operator type"), \ - _PE(INVALID_EVENT_NAME, "invalid event name"), \ - _PE(EVENT_NOT_FOUND, "no event found"), \ - _PE(SYNTAX_ERROR, "syntax error"), \ - _PE(ILLEGAL_RVALUE, "illegal rvalue"), \ - _PE(ILLEGAL_LVALUE, "illegal lvalue for string comparison"), \ - _PE(INVALID_REGEX, "regex did not compute"), \ - _PE(ILLEGAL_STRING_CMP, "illegal comparison for string"), \ - _PE(ILLEGAL_INTEGER_CMP,"illegal comparison for integer"), \ - _PE(REPARENT_NOT_OP, "cannot reparent other than OP"), \ - _PE(REPARENT_FAILED, "failed to reparent filter OP"), \ - _PE(BAD_FILTER_ARG, "bad arg in filter tree"), \ - _PE(UNEXPECTED_TYPE, "unexpected type (not a value)"), \ - _PE(ILLEGAL_TOKEN, "illegal token"), \ - _PE(INVALID_PAREN, "open parenthesis cannot come here"), \ - _PE(UNBALANCED_PAREN, "unbalanced number of parenthesis"), \ - _PE(UNKNOWN_TOKEN, "unknown token"), \ - _PE(FILTER_NOT_FOUND, "no filter found"), \ - _PE(NOT_A_NUMBER, "must have number field"), \ - _PE(NO_FILTER, "no filters exists"), \ - _PE(FILTER_MISS, "record does not match to filter") - -#undef _PE -#define _PE(__code, __str) TEP_ERRNO__ ## __code -enum tep_errno { - TEP_ERRNO__SUCCESS = 0, - TEP_ERRNO__FILTER_MATCH = TEP_ERRNO__SUCCESS, - - /* - * Choose an arbitrary negative big number not to clash with standard - * errno since SUS requires the errno has distinct positive values. - * See 'Issue 6' in the link below. - * - * https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html - */ - __TEP_ERRNO__START = -100000, - - TEP_ERRORS, - - __TEP_ERRNO__END, -}; -#undef _PE - -struct tep_plugin_list; - -#define INVALID_PLUGIN_LIST_OPTION ((char **)((unsigned long)-1)) - -enum tep_plugin_load_priority { - TEP_PLUGIN_FIRST, - TEP_PLUGIN_LAST, -}; - -int tep_add_plugin_path(struct tep_handle *tep, char *path, - enum tep_plugin_load_priority prio); -struct tep_plugin_list *tep_load_plugins(struct tep_handle *tep); -void tep_unload_plugins(struct tep_plugin_list *plugin_list, - struct tep_handle *tep); -void tep_load_plugins_hook(struct tep_handle *tep, const char *suffix, - void (*load_plugin)(struct tep_handle *tep, - const char *path, - const char *name, - void *data), - void *data); -char **tep_plugin_list_options(void); -void tep_plugin_free_options_list(char **list); -int tep_plugin_add_options(const char *name, - struct tep_plugin_option *options); -int tep_plugin_add_option(const char *name, const char *val); -void tep_plugin_remove_options(struct tep_plugin_option *options); -void tep_plugin_print_options(struct trace_seq *s); -void tep_print_plugins(struct trace_seq *s, - const char *prefix, const char *suffix, - const struct tep_plugin_list *list); - -/* tep_handle */ -typedef char *(tep_func_resolver_t)(void *priv, - unsigned long long *addrp, char **modp); -void tep_set_flag(struct tep_handle *tep, int flag); -void tep_clear_flag(struct tep_handle *tep, enum tep_flag flag); -bool tep_test_flag(struct tep_handle *tep, enum tep_flag flags); - -static inline int tep_is_bigendian(void) -{ - unsigned char str = { 0x1, 0x2, 0x3, 0x4 }; - unsigned int val; - - memcpy(&val, str, 4); - return val == 0x01020304; -} - -/* 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 tep_set_function_resolver(struct tep_handle *tep, - tep_func_resolver_t *func, void *priv); -void tep_reset_function_resolver(struct tep_handle *tep); -int tep_register_comm(struct tep_handle *tep, const char *comm, int pid); -int tep_override_comm(struct tep_handle *tep, const char *comm, int pid); -int tep_parse_saved_cmdlines(struct tep_handle *tep, const char *buf); -int tep_parse_kallsyms(struct tep_handle *tep, const char *kallsyms); -int tep_register_function(struct tep_handle *tep, char *name, - unsigned long long addr, char *mod); -int tep_parse_printk_formats(struct tep_handle *tep, const char *buf); -int tep_register_print_string(struct tep_handle *tep, const char *fmt, - unsigned long long addr); -bool tep_is_pid_registered(struct tep_handle *tep, int pid); - -struct tep_event *tep_get_event(struct tep_handle *tep, int index); - -#define TEP_PRINT_INFO "INFO" -#define TEP_PRINT_INFO_RAW "INFO_RAW" -#define TEP_PRINT_COMM "COMM" -#define TEP_PRINT_LATENCY "LATENCY" -#define TEP_PRINT_NAME "NAME" -#define TEP_PRINT_PID 1U -#define TEP_PRINT_TIME 2U -#define TEP_PRINT_CPU 3U - -void tep_print_event(struct tep_handle *tep, struct trace_seq *s, - struct tep_record *record, const char *fmt, ...) - __attribute__ ((format (printf, 4, 5))); - -int tep_parse_header_page(struct tep_handle *tep, char *buf, unsigned long size, - int long_size); - -enum tep_errno tep_parse_event(struct tep_handle *tep, const char *buf, - unsigned long size, const char *sys); -enum tep_errno tep_parse_format(struct tep_handle *tep, - struct tep_event **eventp, - const char *buf, - unsigned long size, const char *sys); - -void *tep_get_field_raw(struct trace_seq *s, struct tep_event *event, - const char *name, struct tep_record *record, - int *len, int err); - -int tep_get_field_val(struct trace_seq *s, struct tep_event *event, - const char *name, struct tep_record *record, - unsigned long long *val, int err); -int tep_get_common_field_val(struct trace_seq *s, struct tep_event *event, - const char *name, struct tep_record *record, - unsigned long long *val, int err); -int tep_get_any_field_val(struct trace_seq *s, struct tep_event *event, - const char *name, struct tep_record *record, - unsigned long long *val, int err); - -int tep_print_num_field(struct trace_seq *s, const char *fmt, - struct tep_event *event, const char *name, - struct tep_record *record, int err); - -int tep_print_func_field(struct trace_seq *s, const char *fmt, - struct tep_event *event, const char *name, - struct tep_record *record, int err); - -enum tep_reg_handler { - TEP_REGISTER_SUCCESS = 0, - TEP_REGISTER_SUCCESS_OVERWRITE, -}; - -int tep_register_event_handler(struct tep_handle *tep, int id, - const char *sys_name, const char *event_name, - tep_event_handler_func func, void *context); -int tep_unregister_event_handler(struct tep_handle *tep, int id, - const char *sys_name, const char *event_name, - tep_event_handler_func func, void *context); -int tep_register_print_function(struct tep_handle *tep, - tep_func_handler func, - enum tep_func_arg_type ret_type, - char *name, ...); -int tep_unregister_print_function(struct tep_handle *tep, - tep_func_handler func, char *name); - -struct tep_format_field *tep_find_common_field(struct tep_event *event, const char *name); -struct tep_format_field *tep_find_field(struct tep_event *event, const char *name); -struct tep_format_field *tep_find_any_field(struct tep_event *event, const char *name); - -const char *tep_find_function(struct tep_handle *tep, unsigned long long addr); -unsigned long long -tep_find_function_address(struct tep_handle *tep, unsigned long long addr); -unsigned long long tep_read_number(struct tep_handle *tep, const void *ptr, int size); -int tep_read_number_field(struct tep_format_field *field, const void *data, - unsigned long long *value); - -struct tep_event *tep_get_first_event(struct tep_handle *tep); -int tep_get_events_count(struct tep_handle *tep); -struct tep_event *tep_find_event(struct tep_handle *tep, int id); - -struct tep_event * -tep_find_event_by_name(struct tep_handle *tep, const char *sys, const char *name); -struct tep_event * -tep_find_event_by_record(struct tep_handle *tep, struct tep_record *record); - -int tep_data_type(struct tep_handle *tep, struct tep_record *rec); -int tep_data_pid(struct tep_handle *tep, struct tep_record *rec); -int tep_data_preempt_count(struct tep_handle *tep, struct tep_record *rec); -int tep_data_flags(struct tep_handle *tep, struct tep_record *rec); -const char *tep_data_comm_from_pid(struct tep_handle *tep, int pid); -struct tep_cmdline; -struct tep_cmdline *tep_data_pid_from_comm(struct tep_handle *tep, const char *comm, - struct tep_cmdline *next); -int tep_cmdline_pid(struct tep_handle *tep, struct tep_cmdline *cmdline); - -void tep_print_field(struct trace_seq *s, void *data, - struct tep_format_field *field); -void tep_print_fields(struct trace_seq *s, void *data, - int size __maybe_unused, struct tep_event *event); -int tep_strerror(struct tep_handle *tep, enum tep_errno errnum, - char *buf, size_t buflen); - -struct tep_event **tep_list_events(struct tep_handle *tep, enum tep_event_sort_type); -struct tep_event **tep_list_events_copy(struct tep_handle *tep, - enum tep_event_sort_type); -struct tep_format_field **tep_event_common_fields(struct tep_event *event); -struct tep_format_field **tep_event_fields(struct tep_event *event); - -enum tep_endian { - TEP_LITTLE_ENDIAN = 0, - TEP_BIG_ENDIAN -}; -int tep_get_cpus(struct tep_handle *tep); -void tep_set_cpus(struct tep_handle *tep, int cpus); -int tep_get_long_size(struct tep_handle *tep); -void tep_set_long_size(struct tep_handle *tep, int long_size); -int tep_get_page_size(struct tep_handle *tep); -void tep_set_page_size(struct tep_handle *tep, int _page_size); -bool tep_is_file_bigendian(struct tep_handle *tep); -void tep_set_file_bigendian(struct tep_handle *tep, enum tep_endian endian); -bool tep_is_local_bigendian(struct tep_handle *tep); -void tep_set_local_bigendian(struct tep_handle *tep, enum tep_endian endian); -int tep_get_header_page_size(struct tep_handle *tep); -int tep_get_header_timestamp_size(struct tep_handle *tep); -bool tep_is_old_format(struct tep_handle *tep); -void tep_set_test_filters(struct tep_handle *tep, int test_filters); - -struct tep_handle *tep_alloc(void); -void tep_free(struct tep_handle *tep); -void tep_ref(struct tep_handle *tep); -void tep_unref(struct tep_handle *tep); -int tep_get_ref(struct tep_handle *tep); - -/* for debugging */ -void tep_print_funcs(struct tep_handle *tep); -void tep_print_printk(struct tep_handle *tep); - -/* ----------------------- filtering ----------------------- */ - -enum tep_filter_boolean_type { - TEP_FILTER_FALSE, - TEP_FILTER_TRUE, -}; - -enum tep_filter_op_type { - TEP_FILTER_OP_AND = 1, - TEP_FILTER_OP_OR, - TEP_FILTER_OP_NOT, -}; - -enum tep_filter_cmp_type { - TEP_FILTER_CMP_NONE, - TEP_FILTER_CMP_EQ, - TEP_FILTER_CMP_NE, - TEP_FILTER_CMP_GT, - TEP_FILTER_CMP_LT, - TEP_FILTER_CMP_GE, - TEP_FILTER_CMP_LE, - TEP_FILTER_CMP_MATCH, - TEP_FILTER_CMP_NOT_MATCH, - TEP_FILTER_CMP_REGEX, - TEP_FILTER_CMP_NOT_REGEX, -}; - -enum tep_filter_exp_type { - TEP_FILTER_EXP_NONE, - TEP_FILTER_EXP_ADD, - TEP_FILTER_EXP_SUB, - TEP_FILTER_EXP_MUL, - TEP_FILTER_EXP_DIV, - TEP_FILTER_EXP_MOD, - TEP_FILTER_EXP_RSHIFT, - TEP_FILTER_EXP_LSHIFT, - TEP_FILTER_EXP_AND, - TEP_FILTER_EXP_OR, - TEP_FILTER_EXP_XOR, - TEP_FILTER_EXP_NOT, -}; - -enum tep_filter_arg_type { - TEP_FILTER_ARG_NONE, - TEP_FILTER_ARG_BOOLEAN, - TEP_FILTER_ARG_VALUE, - TEP_FILTER_ARG_FIELD, - TEP_FILTER_ARG_EXP, - TEP_FILTER_ARG_OP, - TEP_FILTER_ARG_NUM, - TEP_FILTER_ARG_STR, -}; - -enum tep_filter_value_type { - TEP_FILTER_NUMBER, - TEP_FILTER_STRING, - TEP_FILTER_CHAR -}; - -struct tep_filter_arg; - -struct tep_filter_arg_boolean { - enum tep_filter_boolean_type value; -}; - -struct tep_filter_arg_field { - struct tep_format_field *field; -}; - -struct tep_filter_arg_value { - enum tep_filter_value_type type; - union { - char *str; - unsigned long long val; - }; -}; - -struct tep_filter_arg_op { - enum tep_filter_op_type type; - struct tep_filter_arg *left; - struct tep_filter_arg *right; -}; - -struct tep_filter_arg_exp { - enum tep_filter_exp_type type; - struct tep_filter_arg *left; - struct tep_filter_arg *right; -}; - -struct tep_filter_arg_num { - enum tep_filter_cmp_type type; - struct tep_filter_arg *left; - struct tep_filter_arg *right; -}; - -struct tep_filter_arg_str { - enum tep_filter_cmp_type type; - struct tep_format_field *field; - char *val; - char *buffer; - regex_t reg; -}; - -struct tep_filter_arg { - enum tep_filter_arg_type type; - union { - struct tep_filter_arg_boolean boolean; - struct tep_filter_arg_field field; - struct tep_filter_arg_value value; - struct tep_filter_arg_op op; - struct tep_filter_arg_exp exp; - struct tep_filter_arg_num num; - struct tep_filter_arg_str str; - }; -}; - -struct tep_filter_type { - int event_id; - struct tep_event *event; - struct tep_filter_arg *filter; -}; - -#define TEP_FILTER_ERROR_BUFSZ 1024 - -struct tep_event_filter { - struct tep_handle *tep; - int filters; - struct tep_filter_type *event_filters; - char error_bufferTEP_FILTER_ERROR_BUFSZ; -}; - -struct tep_event_filter *tep_filter_alloc(struct tep_handle *tep); - -/* for backward compatibility */ -#define FILTER_NONE TEP_ERRNO__NO_FILTER -#define FILTER_NOEXIST TEP_ERRNO__FILTER_NOT_FOUND -#define FILTER_MISS TEP_ERRNO__FILTER_MISS -#define FILTER_MATCH TEP_ERRNO__FILTER_MATCH - -enum tep_errno tep_filter_add_filter_str(struct tep_event_filter *filter, - const char *filter_str); - -enum tep_errno tep_filter_match(struct tep_event_filter *filter, - struct tep_record *record); - -int tep_filter_strerror(struct tep_event_filter *filter, enum tep_errno err, - char *buf, size_t buflen); - -int tep_event_filtered(struct tep_event_filter *filter, - int event_id); - -void tep_filter_reset(struct tep_event_filter *filter); - -void tep_filter_free(struct tep_event_filter *filter); - -char *tep_filter_make_string(struct tep_event_filter *filter, int event_id); - -int tep_filter_remove_event(struct tep_event_filter *filter, - int event_id); - -int tep_filter_copy(struct tep_event_filter *dest, struct tep_event_filter *source); - -int tep_filter_compare(struct tep_event_filter *filter1, struct tep_event_filter *filter2); - -#endif /* _PARSE_EVENTS_H */
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/src/event-utils.h
Deleted
@@ -1,66 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1 */ -/* - * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> - * - */ -#ifndef __UTIL_H -#define __UTIL_H - -#include <ctype.h> -#include <stdarg.h> - -/* Can be overridden */ -void tep_warning(const char *fmt, ...); -int tep_vwarning(const char *name, const char *fmt, va_list ap); -void pr_stat(const char *fmt, ...); -void vpr_stat(const char *fmt, va_list ap); - -/* Always available */ -void __pr_stat(const char *fmt, ...); -void __vpr_stat(const char *fmt, ...); - -#define min(x, y) ({ \ - typeof(x) _min1 = (x); \ - typeof(y) _min2 = (y); \ - (void) (&_min1 == &_min2); \ - _min1 < _min2 ? _min1 : _min2; }) - -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--; - } - string1 = 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
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/src/kbuffer.h
Deleted
@@ -1,68 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1 */ -/* - * Copyright (C) 2012 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> - * - */ -#ifndef _KBUFFER_H -#define _KBUFFER_H - -#ifndef TS_SHIFT -#define TS_SHIFT 27 -#endif - -enum kbuffer_endian { - KBUFFER_ENDIAN_BIG, - KBUFFER_ENDIAN_LITTLE, -}; - -enum kbuffer_long_size { - KBUFFER_LSIZE_4, - KBUFFER_LSIZE_8, -}; - -enum { - KBUFFER_TYPE_PADDING = 29, - KBUFFER_TYPE_TIME_EXTEND = 30, - KBUFFER_TYPE_TIME_STAMP = 31, -}; - -struct kbuffer; - -struct kbuffer *kbuffer_alloc(enum kbuffer_long_size size, enum kbuffer_endian endian); -void kbuffer_free(struct kbuffer *kbuf); -int kbuffer_load_subbuffer(struct kbuffer *kbuf, void *subbuffer); -void *kbuffer_read_event(struct kbuffer *kbuf, unsigned long long *ts); -void *kbuffer_next_event(struct kbuffer *kbuf, unsigned long long *ts); -unsigned long long kbuffer_timestamp(struct kbuffer *kbuf); -unsigned long long kbuffer_subbuf_timestamp(struct kbuffer *kbuf, void *subbuf); -unsigned int kbuffer_ptr_delta(struct kbuffer *kbuf, void *ptr); - -void *kbuffer_translate_data(int swap, void *data, unsigned int *size); - -void *kbuffer_read_at_offset(struct kbuffer *kbuf, int offset, unsigned long long *ts); - -int kbuffer_curr_index(struct kbuffer *kbuf); - -int kbuffer_curr_offset(struct kbuffer *kbuf); -int kbuffer_curr_size(struct kbuffer *kbuf); -int kbuffer_event_size(struct kbuffer *kbuf); -int kbuffer_missed_events(struct kbuffer *kbuf); -int kbuffer_subbuffer_size(struct kbuffer *kbuf); - -void kbuffer_set_old_format(struct kbuffer *kbuf); -int kbuffer_start_of_data(struct kbuffer *kbuf); - -/* Debugging */ - -struct kbuffer_raw_info { - int type; - int length; - unsigned long long delta; - void *next; -}; - -/* Read raw data */ -struct kbuffer_raw_info *kbuffer_raw_get(struct kbuffer *kbuf, void *subbuf, - struct kbuffer_raw_info *info); - -#endif /* _K_BUFFER_H */
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/src/trace-seq.h
Deleted
@@ -1,55 +0,0 @@ -// 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
_service:tar_scm:libtraceevent-1.2.1.tar.gz/.gitignore -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/.gitignore
Changed
@@ -2,12 +2,17 @@ TRACEEVENT-CFLAGS libtraceevent-dynamic-list libtraceevent.so.* +.pc +patches *.o build_prefix build_uninstall *~ \#*\# +.#* *.cmd *.so .*.d ep_version.h +libtraceevent.pc +lib/
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/Makefile -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/Makefile
Changed
@@ -1,5 +1,5 @@ -include ../scripts/Makefile.include include ../scripts/utilities.mak +include ../scripts/utils.mk # This Makefile and manpage XSL files were taken from tools/perf/Documentation # and modified for libtraceevent. @@ -13,6 +13,8 @@ _MAN_HTML=$(patsubst %.txt,%.html,$(MAN_TXT)) _DOC_MAN3=$(patsubst %.txt,%.m,$(MAN3_TXT)) +OUTPUT := $(obj)/Documentation/ + MAN_XML=$(addprefix $(OUTPUT),$(_MAN_XML)) MAN_HTML=$(addprefix $(OUTPUT),$(_MAN_HTML)) DOC_MAN3=$(addprefix $(OUTPUT),$(_DOC_MAN3)) @@ -154,20 +156,16 @@ $(error "You need to install $(missing_tools) for man pages") endif -install-%.3: $(OUTPUT)%.3 - $(call QUIET_INSTALL, $<) \ - $(INSTALL) -d -m 755 $(DESTDIR)$(man3dir); \ - $(INSTALL) -m 644 $< $(DESTDIR)$(man3dir); +$(OUTPUT)install-%.3: $(OUTPUT)%.3 + $(Q)$(call do_install,$<,$(man3dir),644) -do-install-man: man $(addprefix install-,$(wildcard $(OUTPUT)*.3)) +do-install-man: man $(patsubst $(OUTPUT)%,$(OUTPUT)install-%,$(wildcard $(OUTPUT)*.3)) install-man: check-man-tools man $(Q)$(MAKE) -C . do-install-man install-%.txt: $(OUTPUT)%.html - $(call QUIET_INSTALL, $<) \ - $(INSTALL) -d -m 755 $(DESTDIR)$(htmldir); \ - $(INSTALL) -m 644 $< $(DESTDIR)$(htmldir); + $(Q)$(call do_install,$<,$(htmldir),644) do-install-html: html $(addprefix install-,$(wildcard *.txt)) @@ -192,7 +190,7 @@ CLEAN_FILES = \ $(MAN_XML) $(addsuffix +,$(MAN_XML)) \ $(MAN_HTML) $(addsuffix +,$(MAN_HTML)) \ - $(DOC_MAN3) *.3 *.m + $(DOC_MAN3) $(OUTPUT)*.3 $(OUTPUT)*.m clean: $(call QUIET_CLEAN, Documentation) $(RM) $(CLEAN_FILES)
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/install-docs.sh.in
Added
@@ -0,0 +1,20 @@ +#!/bin/bash +# SPDX-License-Identifier: LGPL-2.1 +# +# Copyright (c) 2023 Daniel Wagner, SUSE LLC + +for section in 1 3 5; do + while IFS= read -r -d '' man; do + ! -d "${DESTDIR}@MANDIR@/man${section}" && install -d "${DESTDIR}@MANDIR@/man${section}" + + echo Installing "${man}" to "${DESTDIR}@MANDIR@/man${section}" + install -m 0644 "${man}" "${DESTDIR}@MANDIR@/man${section}/" + done< <(find "@SRCDIR@" -name "*\.${section}" -type f -print0) +done + +while IFS= read -r -d '' html; do + ! -d "${DESTDIR}@HTMLDIR@" && install -d "${DESTDIR}@HTMLDIR@" + + echo Installing "${html}" to "${DESTDIR}@HTMLDIR@" + install -m 0644 "${html}" "${DESTDIR}@HTMLDIR@" +done< <(find "@SRCDIR@" -name "*\.html" -type f -print0)
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-commands.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-commands.txt
Changed
@@ -3,7 +3,7 @@ NAME ---- -tep_register_comm, tep_override_comm, tep_pid_is_registered, +tep_register_comm, tep_override_comm, tep_is_pid_registered, tep_data_comm_from_pid, tep_data_pid_from_comm, tep_cmdline_pid - Manage pid to process name mappings. @@ -28,27 +28,27 @@ of the process, instead of its pid. This information can be retrieved from tracefs/saved_cmdlines file. -The _tep_register_comm()_ function registers a _pid_ / process name mapping. +The *tep_register_comm()* function registers a _pid_ / process name mapping. If a command with the same _pid_ is already registered, an error is returned. The _pid_ argument is the process ID, the _comm_ argument is the process name, _tep_ is the event context. The _comm_ is duplicated internally. -The _tep_override_comm()_ function registers a _pid_ / process name mapping. +The *tep_override_comm()* function registers a _pid_ / process name mapping. If a process with the same pid is already registered, the process name string is udapted with the new one. The _pid_ argument is the process ID, the _comm_ argument is the process name, _tep_ is the event context. The _comm_ is duplicated internally. -The _tep_is_pid_registered()_ function checks if a pid has a process name +The *tep_is_pid_registered()* function checks if a pid has a process name mapping registered. The _pid_ argument is the process ID, _tep_ is the event context. -The _tep_data_comm_from_pid()_ function returns the process name for a given +The *tep_data_comm_from_pid()* function returns the process name for a given pid. The _pid_ argument is the process ID, _tep_ is the event context. The returned string should not be freed, but will be freed when the _tep_ handler is closed. -The _tep_data_pid_from_comm()_ function returns a pid for a given process name. +The *tep_data_pid_from_comm()* function returns a pid for a given process name. The _comm_ argument is the process name, _tep_ is the event context. The argument _next_ is the cmdline structure to search for the next pid. As there may be more than one pid for a given process, the result of this call @@ -56,31 +56,31 @@ the next pid. If _next_ is NULL, it will return the first pid associated with the _comm_. The function performs a linear search, so it may be slow. -The _tep_cmdline_pid()_ function returns the pid associated with a given +The *tep_cmdline_pid()* function returns the pid associated with a given _cmdline_. The _tep_ argument is the event context. RETURN VALUE ------------ -_tep_register_comm()_ function returns 0 on success. In case of an error -1 is +*tep_register_comm()* function returns 0 on success. In case of an error -1 is returned and errno is set to indicate the cause of the problem: ENOMEM, if there is not enough memory to duplicate the _comm_ or EEXIST if a mapping for this _pid_ is already registered. -_tep_override_comm()_ function returns 0 on success. In case of an error -1 is +*tep_override_comm()* function returns 0 on success. In case of an error -1 is returned and errno is set to indicate the cause of the problem: ENOMEM, if there is not enough memory to duplicate the _comm_. -_tep_is_pid_registered()_ function returns true if the _pid_ has a process name +*tep_is_pid_registered()* function returns true if the _pid_ has a process name mapped to it, false otherwise. -_tep_data_comm_from_pid()_ function returns the process name as string, or the +*tep_data_comm_from_pid()* function returns the process name as string, or the string "<...>" if there is no mapping for the given pid. -_tep_data_pid_from_comm()_ function returns a pointer to a struct cmdline, that +*tep_data_pid_from_comm()* function returns a pointer to a struct cmdline, that holds a pid for a given process, or NULL if none is found. This result can be passed back into a recurring call as the _next_ parameter of the function. -_tep_cmdline_pid()_ functions returns the pid for the give cmdline. If _cmdline_ +*tep_cmdline_pid()* functions returns the pid for the give cmdline. If _cmdline_ is NULL, then -1 is returned. EXAMPLE @@ -131,7 +131,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-cpus.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-cpus.txt
Changed
@@ -18,16 +18,16 @@ DESCRIPTION ----------- -The _tep_get_cpus()_ function gets the number of CPUs, which have a tracing +The *tep_get_cpus()* function gets the number of CPUs, which have a tracing buffer representing it. The _tep_ argument is trace event parser context. -The _tep_set_cpus()_ function sets the number of CPUs, which have a tracing +The *tep_set_cpus()* function sets the number of CPUs, which have a tracing buffer representing it. The _tep_ argument is trace event parser context. The _cpu_ argument is the number of CPUs with tracing data. RETURN VALUE ------------ -The _tep_get_cpus()_ functions returns the number of CPUs, which have tracing +The *tep_get_cpus()* functions returns the number of CPUs, which have tracing data recorded. EXAMPLE @@ -55,7 +55,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-debug.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-debug.txt
Changed
@@ -21,18 +21,18 @@ DESCRIPTION ----------- -The _tep_print_printk()_ function prints the printk string formats that were +The *tep_print_printk()* function prints the printk string formats that were stored for this tracing session. The _tep_ argument is trace event parser context. -The _tep_print_funcs()_ function prints the stored function name to address mapping +The *tep_print_funcs()* function prints the stored function name to address mapping for this tracing session. The _tep_ argument is trace event parser context. -The _tep_set_test_filters()_ function sets a flag to test a filter string. If this -flag is set, when _tep_filter_add_filter_str()_ API as called, it will print the filter +The *tep_set_test_filters()* function sets a flag to test a filter string. If this +flag is set, when *tep_filter_add_filter_str()* API as called, it will print the filter string instead of adding it. The _tep_ argument is trace event parser context. The _test_filters_ argument is the test flag that will be set. -The _tep_plugin_print_options()_ function writes a list of the registered plugin options +The *tep_plugin_print_options()* function writes a list of the registered plugin options into _s_. EXAMPLE @@ -73,7 +73,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-endian_read.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-endian_read.txt
Changed
@@ -16,14 +16,14 @@ DESCRIPTION ----------- -The _tep_read_number()_ function reads an integer from raw data, taking into +The *tep_read_number()* function reads an integer from raw data, taking into account the endianness of the raw data and the current host. The _tep_ argument is the trace event parser context. The _ptr_ is a pointer to the raw data, where the integer is, and the _size_ is the size of the integer. RETURN VALUE ------------ -The _tep_read_number()_ function returns the integer in the byte order of +The *tep_read_number()* function returns the integer in the byte order of the current host. In case of an error, 0 is returned. EXAMPLE @@ -56,7 +56,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-event_find.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-event_find.txt
Changed
@@ -3,7 +3,7 @@ NAME ---- -tep_find_event,tep_find_event_by_name,tep_find_event_by_record - +tep_find_event,tep_find_event_by_name,tep_find_event_by_record, tep_record_is_event - Find events by given key. SYNOPSIS @@ -15,6 +15,7 @@ struct tep_event pass:**tep_find_event*(struct tep_handle pass:*_tep_, int _id_); struct tep_event pass:**tep_find_event_by_name*(struct tep_handle pass:*_tep_, const char pass:*_sys_, const char pass:*_name_); struct tep_event pass:**tep_find_event_by_record*(struct tep_handle pass:*_tep_, struct tep_record pass:*_record_); +bool *tep_record_is_event*(struct tep_record pass:*record, struct tep_event pass:*event); -- DESCRIPTION @@ -23,20 +24,24 @@ criteria. All functions require a pointer to a _tep_, trace event parser context. -The _tep_find_event()_ function searches for an event by given event _id_. The +The *tep_find_event()* function searches for an event by given event _id_. The event ID is assigned dynamically and can be viewed in event's format file, "ID" field. -The tep_find_event_by_name()_ function searches for an event by given +The *tep_find_event_by_name()* function searches for an event by given event _name_, under the system _sys_. If the _sys_ is NULL (not specified), the first event with _name_ is returned. -The tep_find_event_by_record()_ function searches for an event from a given +The *tep_find_event_by_record()* function searches for an event from a given _record_. +The *tep_record_is_event()* function tests if the given _record_ is of the type +of the _event_. This is normally used to know if the _record_ being processed is +of an _event_ where further processing should be done. + RETURN VALUE ------------ -All these functions return a pointer to the found event, or NULL if there is no +All these functions except *tep_record_is_event()* return a pointer to the found event, or NULL if there is no such event. EXAMPLE @@ -81,7 +86,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-event_get.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-event_get.txt
Changed
@@ -18,27 +18,27 @@ DESCRIPTION ----------- -The _tep_get_event()_ function returns a pointer to event at the given _index_. +The *tep_get_event()* function returns a pointer to event at the given _index_. The _tep_ argument is trace event parser context, the _index_ is the index of the requested event. -The _tep_get_first_event()_ function returns a pointer to the first event. +The *tep_get_first_event()* function returns a pointer to the first event. As events are stored in an array, this function returns the pointer to the beginning of the array. The _tep_ argument is trace event parser context. -The _tep_get_events_count()_ function returns the number of the events +The *tep_get_events_count()* function returns the number of the events in the array. The _tep_ argument is trace event parser context. RETURN VALUE ------------ -The _tep_get_event()_ returns a pointer to the event located at _index_. +The *tep_get_event()* returns a pointer to the event located at _index_. NULL is returned in case of error, in case there are no events or _index_ is out of range. -The _tep_get_first_event()_ returns a pointer to the first event. NULL is +The *tep_get_first_event()* returns a pointer to the first event. NULL is returned in case of error, or in case there are no events. -The _tep_get_events_count()_ returns the number of the events. 0 is +The *tep_get_events_count()* returns the number of the events. 0 is returned in case of error, or in case there are no events. EXAMPLE @@ -77,7 +77,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-event_list.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-event_list.txt
Changed
@@ -24,7 +24,7 @@ DESCRIPTION ----------- -The _tep_list_events()_ function returns an array of pointers to the events, +The *tep_list_events()* function returns an array of pointers to the events, sorted by the _sort_type_ criteria. The last element of the array is NULL. The returned memory must not be freed, it is managed by the library. The function is not thread safe. The _tep_ argument is trace event parser @@ -36,18 +36,18 @@ _TEP_EVENT_SORT_SYSTEM_ - sort by the event (system, name, id) triplet. -- -The _tep_list_events_copy()_ is a thread safe version of _tep_list_events()_. +The *tep_list_events_copy()* is a thread safe version of _tep_list_events()_. It has the same behavior, but the returned array is allocated internally and must be freed by the caller. Note that the content of the array must not be freed (see the EXAMPLE below). RETURN VALUE ------------ -The _tep_list_events()_ function returns an array of pointers to events. +The *tep_list_events()* function returns an array of pointers to events. In case of an error, NULL is returned. The returned array must not be freed, it is managed by the library. -The _tep_list_events_copy()_ function returns an array of pointers to events. +The *tep_list_events_copy()* function returns an array of pointers to events. In case of an error, NULL is returned. The returned array must be freed by the caller. @@ -100,7 +100,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-event_print.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-event_print.txt
Changed
@@ -18,7 +18,7 @@ DESCRIPTION ----------- -The _tep_print_event()_ function parses the event information of the given +The *tep_print_event()* function parses the event information of the given _record_ and writes it into the trace sequence _s_, according to the format string _fmt_. The desired information is specified after the format string. The _fmt_ is printf-like format string, following arguments are supported: @@ -108,7 +108,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-field_find.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-field_find.txt
Changed
@@ -22,18 +22,18 @@ These functions search for a field with given name in an event. The field returned can be used to find the field content from within a data record. -The _tep_find_common_field()_ function searches for a common field with _name_ +The *tep_find_common_field()* function searches for a common field with _name_ in the _event_. -The _tep_find_field()_ function searches for an event specific field with +The *tep_find_field()* function searches for an event specific field with _name_ in the _event_. -The _tep_find_any_field()_ function searches for any field with _name_ in the +The *tep_find_any_field()* function searches for any field with _name_ in the _event_. RETURN VALUE ------------ -The _tep_find_common_field(), _tep_find_field()_ and _tep_find_any_field()_ +The _tep_find_common_field(), *tep_find_field()* and _tep_find_any_field()_ functions return a pointer to the found field, or NULL in case there is no field with the requested name. @@ -96,7 +96,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-field_get_val.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-field_get_val.txt
Changed
@@ -23,19 +23,19 @@ ----------- These functions can be used to find a field and retrieve its value. -The _tep_get_any_field_val()_ function searches in the _record_ for a field +The *tep_get_any_field_val()* function searches in the _record_ for a field with _name_, part of the _event_. If the field is found, its value is stored in _val_. If there is an error and _err_ is not zero, then an error string is written into _s_. -The _tep_get_common_field_val()_ function does the same as -_tep_get_any_field_val()_, but searches only in the common fields. This works +The *tep_get_common_field_val()* function does the same as +*tep_get_any_field_val()*, but searches only in the common fields. This works for any event as all events include the common fields. -The _tep_get_field_val()_ function does the same as _tep_get_any_field_val()_, +The *tep_get_field_val()* function does the same as *tep_get_any_field_val()*, but searches only in the event specific fields. -The _tep_get_field_raw()_ function searches in the _record_ for a field with +The *tep_get_field_raw()* function searches in the _record_ for a field with _name_, part of the _event_. If the field is found, a pointer to where the field exists in the record's raw data is returned. The size of the data is stored in _len_. If there is an error and _err_ is not zero, then an error string is @@ -43,10 +43,10 @@ RETURN VALUE ------------ -The _tep_get_any_field_val()_, _tep_get_common_field_val()_ and -_tep_get_field_val()_ functions return 0 on success, or -1 in case of an error. +The *tep_get_any_field_val()*, *tep_get_common_field_val()* and +*tep_get_field_val()* functions return 0 on success, or -1 in case of an error. -The _tep_get_field_raw()_ function returns a pointer to field's raw data, and +The *tep_get_field_raw()* function returns a pointer to field's raw data, and places the length of this data in _len_. In case of an error NULL is returned. EXAMPLE @@ -64,10 +64,10 @@ { int len; char *comm; - struct tep_event_format *event; + struct tep_event *event; unsigned long long val; - event = tep_find_event_by_record(pevent, record); + event = tep_find_event_by_record(tep, record); if (event != NULL) { if (tep_get_common_field_val(NULL, event, "common_type", record, &val, 0) == 0) { @@ -100,7 +100,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-field_print.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-field_print.txt
Changed
@@ -3,7 +3,7 @@ NAME ---- -tep_print_field, tep_print_fields, tep_print_num_field, tep_print_func_field - +tep_print_field_content, tep_print_fields, tep_print_num_field, tep_print_func_field, tep_record_print_fields, tep_record_print_selected_fields - Print the field content. SYNOPSIS @@ -13,35 +13,37 @@ *#include <event-parse.h>* *#include <trace-seq.h>* -void *tep_print_field*(struct trace_seq pass:*_s_, void pass:*_data_, struct tep_format_field pass:*_field_); +void *tep_print_field_content*(struct trace_seq pass:*_s_, void pass:*_data_, int size, struct tep_format_field pass:*_field_); void *tep_print_fields*(struct trace_seq pass:*_s_, void pass:*_data_, int _size_, struct tep_event pass:*_event_); int *tep_print_num_field*(struct trace_seq pass:*_s_, const char pass:*_fmt_, struct tep_event pass:*_event_, const char pass:*_name_, struct tep_record pass:*_record_, int _err_); int *tep_print_func_field*(struct trace_seq pass:*_s_, const char pass:*_fmt_, struct tep_event pass:*_event_, const char pass:*_name_, struct tep_record pass:*_record_, int _err_); +void *tep_record_print_fields*(struct trace_seq pass:*_s_, struct tep_record pass:*_record_, struct tep_event pass:*_event_); +void *tep_record_print_selected_fields*(struct trace_seq pass:*_s_, struct tep_record pass:*_record_, struct tep_event pass:*_event_, int _select_mask_); -- DESCRIPTION ----------- These functions print recorded field's data, according to the field's type. -The _tep_print_field()_ function extracts from the recorded raw _data_ value of +The *tep_print_field_content()* function extracts from the recorded raw _data_ value of the _field_ and prints it into _s_, according to the field type. -The _tep_print_fields()_ prints each field name followed by the record's field +The *tep_print_fields()* prints each field name followed by the record's field value according to the field's type: verse -- "field1_name=field1_value field2_name=field2_value ..." -- -It iterates all fields of the _event_, and calls _tep_print_field()_ for each of +It iterates all fields of the _event_, and calls *tep_print_field_content()* for each of them. -The _tep_print_num_field()_ function prints a numeric field with given format +The *tep_print_num_field()* function prints a numeric field with given format string. A search is performed in the _event_ for a field with _name_. If such field is found, its value is extracted from the _record_ and is printed in the _s_, according to the given format string _fmt_. If the argument _err_ is non-zero, and an error occures - it is printed in the _s_. -The _tep_print_func_field()_ function prints a function field with given format +The *tep_print_func_field()* function prints a function field with given format string. A search is performed in the _event_ for a field with _name_. If such field is found, its value is extracted from the _record_. The value is assumed to be a function address, and a search is perform to find the name of this @@ -49,9 +51,16 @@ according to the given format string _fmt_. If the argument _err_ is non-zero, and an error occures - it is printed in _s_. +The *tep_record_print_fields()* prints the field's name followed by its value +for all record's field. + +The *tep_record_print_selected_fields()* prints the field's name followed by +its value for selected subset of record field. The fields to be printed are +defined by the _select_mask_ bit mask. + RETURN VALUE ------------ -The _tep_print_num_field()_ and _tep_print_func_field()_ functions return 1 +The *tep_print_num_field()* and *tep_print_func_field()* functions return 1 on success, -1 in case of an error or 0 if the print buffer _s_ is full. EXAMPLE @@ -74,7 +83,7 @@ trace_seq_reset(&seq); /* Print the value of "common_pid" */ - tep_print_field(&seq, record->data, field_pid); + tep_print_field_content(&seq, record->data, record->size, field_pid); /* Print all fields of the "hrtimer_start" event */ tep_print_fields(&seq, record->data, record->size, event); @@ -104,7 +113,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-field_read.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-field_read.txt
Changed
@@ -16,14 +16,14 @@ DESCRIPTION ----------- -The _tep_read_number_field()_ function reads the value of the _field_ from the +The *tep_read_number_field()* function reads the value of the _field_ from the raw _data_ and stores it in the _value_. The function sets the _value_ according to the endianness of the raw data and the current machine and stores it in _value_. RETURN VALUE ------------ -The _tep_read_number_field()_ function retunrs 0 in case of success, or -1 in +The *tep_read_number_field()* function retunrs 0 in case of success, or -1 in case of an error. EXAMPLE @@ -59,7 +59,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-fields.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-fields.txt
Changed
@@ -17,17 +17,17 @@ DESCRIPTION ----------- -The _tep_event_common_fields()_ function returns an array of pointers to common +The *tep_event_common_fields()* function returns an array of pointers to common fields for the _event_. The array is allocated in the function and must be freed by free(). The last element of the array is NULL. -The _tep_event_fields()_ function returns an array of pointers to event specific +The *tep_event_fields()* function returns an array of pointers to event specific fields for the _event_. The array is allocated in the function and must be freed by free(). The last element of the array is NULL. RETURN VALUE ------------ -Both _tep_event_common_fields()_ and _tep_event_fields()_ functions return +Both *tep_event_common_fields()* and *tep_event_fields()* functions return an array of pointers to tep_format_field structures in case of success, or NULL in case of an error. @@ -83,7 +83,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-file_endian.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-file_endian.txt
Changed
@@ -23,11 +23,11 @@ -- DESCRIPTION ----------- -The _tep_is_file_bigendian()_ function gets the endianness of the raw data, +The *tep_is_file_bigendian()* function gets the endianness of the raw data, being accessed by the tep handler. The _tep_ argument is trace event parser context. -The _tep_set_file_bigendian()_ function sets the endianness of raw data being +The *tep_set_file_bigendian()* function sets the endianness of raw data being accessed by the tep handler. The _tep_ argument is trace event parser context. verse -- @@ -37,7 +37,7 @@ -- RETURN VALUE ------------ -The _tep_is_file_bigendian()_ function returns true if the data is in bigendian +The *tep_is_file_bigendian()* function returns true if the data is in bigendian format, false otherwise. EXAMPLE @@ -69,7 +69,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-filter.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-filter.txt
Changed
@@ -34,53 +34,53 @@ described in the event's format file. This set of functions can be used to create, delete, modify and attach event filters. -The _tep_filter_alloc()_ function creates a new event filter. The _tep_ argument +The *tep_filter_alloc()* function creates a new event filter. The _tep_ argument is the trace event parser context. -The _tep_filter_free()_ function frees an event filter and all resources that it +The *tep_filter_free()* function frees an event filter and all resources that it had used. -The _tep_filter_reset()_ function removes all rules from an event filter and +The *tep_filter_reset()* function removes all rules from an event filter and resets it. -The _tep_filter_add_filter_str()_ function adds a new rule to the _filter_. The +The *tep_filter_add_filter_str()* function adds a new rule to the _filter_. The _filter_str_ argument is the filter string, that contains the rule. -The _tep_event_filtered()_ function checks if the event with _event_id_ has +The *tep_event_filtered()* function checks if the event with _event_id_ has _filter_. -The _tep_filter_remove_event()_ function removes a _filter_ for an event with +The *tep_filter_remove_event()* function removes a _filter_ for an event with _event_id_. -The _tep_filter_match()_ function tests if a _record_ matches given _filter_. +The *tep_filter_match()* function tests if a _record_ matches given _filter_. -The _tep_filter_copy()_ function copies a _source_ filter into a _dest_ filter. +The *tep_filter_copy()* function copies a _source_ filter into a _dest_ filter. -The _tep_filter_compare()_ function compares two filers - _filter1_ and _filter2_. +The *tep_filter_compare()* function compares two filers - _filter1_ and _filter2_. -The _tep_filter_make_string()_ function constructs a string, displaying +The *tep_filter_make_string()* function constructs a string, displaying the _filter_ contents for given _event_id_. -The _tep_filter_strerror()_ function copies the _filter_ error buffer into the +The *tep_filter_strerror()* function copies the _filter_ error buffer into the given _buf_ with the size _buflen_. If the error buffer is empty, in the _buf_ is copied a string, describing the error _err_. RETURN VALUE ------------ -The _tep_filter_alloc()_ function returns a pointer to the newly created event +The *tep_filter_alloc()* function returns a pointer to the newly created event filter, or NULL in case of an error. -The _tep_filter_add_filter_str()_ function returns 0 if the rule was -successfully added or a negative error code. Use _tep_filter_strerror()_ to see +The *tep_filter_add_filter_str()* function returns 0 if the rule was +successfully added or a negative error code. Use *tep_filter_strerror()* to see actual error message in case of an error. -The _tep_event_filtered()_ function returns 1 if the filter is found for given +The *tep_event_filtered()* function returns 1 if the filter is found for given event, or 0 otherwise. -The _tep_filter_remove_event()_ function returns 1 if the vent was removed, or +The *tep_filter_remove_event()* function returns 1 if the vent was removed, or 0 if the event was not found. -The _tep_filter_match()_ function returns _tep_errno_, according to the result: +The *tep_filter_match()* function returns _tep_errno_, according to the result: verse -- _pass:TEP_ERRNO__FILTER_MATCH_ - filter found for event, the record matches. @@ -90,16 +90,16 @@ -- or any other _tep_errno_, if an error occurred during the test. -The _tep_filter_copy()_ function returns 0 on success or -1 if not all rules +The *tep_filter_copy()* function returns 0 on success or -1 if not all rules were copied. -The _tep_filter_compare()_ function returns 1 if the two filters hold the same +The *tep_filter_compare()* function returns 1 if the two filters hold the same content, or 0 if they do not. -The _tep_filter_make_string()_ function returns a string, which must be freed +The *tep_filter_make_string()* function returns a string, which must be freed with free(), or NULL in case of an error. -The _tep_filter_strerror()_ function returns 0 if message was filled +The *tep_filter_strerror()* function returns 0 if message was filled successfully, or -1 in case of an error. EXAMPLE @@ -187,7 +187,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-func_apis.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-func_apis.txt
Changed
@@ -3,9 +3,8 @@ NAME ---- -tep_find_function, tep_find_function_address, tep_set_function_resolver, -tep_reset_function_resolver, tep_register_function, tep_register_print_string - -function related tep APIs +tep_set_function_resolver, tep_reset_function_resolver, tep_register_function, tep_register_print_string, +tep_get_function_count - function related tep APIs SYNOPSIS -------- @@ -16,10 +15,9 @@ typedef char pass:*(*tep_func_resolver_t*)(void pass:*_priv_, unsigned long long pass:*_addrp_, char pass:**_modp_); int *tep_set_function_resolver*(struct tep_handle pass:*_tep_, tep_func_resolver_t pass:*_func_, void pass:*_priv_); void *tep_reset_function_resolver*(struct tep_handle pass:*_tep_); -const char pass:**tep_find_function*(struct tep_handle pass:*_tep_, unsigned long long _addr_); -unsigned long long *tep_find_function_address*(struct tep_handle pass:*_tep_, unsigned long long _addr_); int *tep_register_function*(struct tep_handle pass:*_tep_, char pass:*_name_, unsigned long long _addr_, char pass:*_mod_); int *tep_register_print_string*(struct tep_handle pass:*_tep_, const char pass:*_fmt_, unsigned long long _addr_); +int *tep_get_function_count*(struct tep_handle *_tep_) -- DESCRIPTION @@ -29,18 +27,18 @@ The _tep_func_resolver_t_ type is the prototype of the alternative kernel functions resolver. This function receives a pointer to its custom context -(set with the _tep_set_function_resolver()_ call ) and the address of a kernel +(set with the *tep_set_function_resolver()* call ) and the address of a kernel function, which has to be resolved. In case of success, it should return the name of the function and its module (if any) in _modp_. -The _tep_set_function_resolver()_ function registers _func_ as an alternative +The *tep_set_function_resolver()* function registers _func_ as an alternative kernel functions resolver. The _tep_ argument is trace event parser context. The _priv_ argument is a custom context of the _func_ function. The function -resolver is used by the APIs _tep_find_function()_, -_tep_find_function_address()_, and _tep_print_func_field()_ to resolve +resolver is used by the APIs *tep_find_function*(3), +*tep_find_function_address*(3), and *tep_print_func_field()* to resolve a function address to a function name. -The _tep_reset_function_resolver()_ function resets the kernel functions +The *tep_reset_function_resolver()* function resets the kernel functions resolver to the default function. The _tep_ argument is trace event parser context. @@ -49,15 +47,7 @@ address. The given address does not have to be exact, it will select the function that would contain it. -The _tep_find_function()_ function returns the function name, which contains the -given address _addr_. The _tep_ argument is the trace event parser context. - -The _tep_find_function_address()_ function returns the function start address, -by given address _addr_. The _addr_ does not have to be exact, it will select -the function that would contain it. The _tep_ argument is the trace event -parser context. - -The _tep_register_function()_ function registers a function name mapped to an +The *tep_register_function()* function registers a function name mapped to an address and (optional) module. This mapping is used in case the function tracer or events have "%pS" parameter in its format string. It is common to pass in the kallsyms function names with their corresponding addresses with this @@ -66,7 +56,7 @@ start address of the function. The _mod_ is the kernel module the function may be in (NULL for none). -The _tep_register_print_string()_ function registers a string by the address +The *tep_register_print_string()* function registers a string by the address it was stored in the kernel. Some strings internal to the kernel with static address are passed to certain events. The "%s" in the event's format field which has an address needs to know what string would be at that address. The @@ -75,22 +65,17 @@ context. The _fmt_ is the string to register, it is copied internally. The _addr_ is the address the string was located at. +*tep_get_function_count*() returns the number of registered functions in a tep handler. RETURN VALUE ------------ -The _tep_set_function_resolver()_ function returns 0 in case of success, or -1 +The *tep_set_function_resolver()* function returns 0 in case of success, or -1 in case of an error. -The _tep_find_function()_ function returns the function name, or NULL in case -it cannot be found. - -The _tep_find_function_address()_ function returns the function start address, -or 0 in case it cannot be found. - -The _tep_register_function()_ function returns 0 in case of success. In case of +The *tep_register_function()* function returns 0 in case of success. In case of an error -1 is returned, and errno is set to the appropriate error number. -The _tep_register_print_string()_ function returns 0 in case of success. In case +The *tep_register_print_string()* function returns 0 in case of success. In case of an error -1 is returned, and errno is set to the appropriate error number. EXAMPLE @@ -161,7 +146,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-func_find.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-func_find.txt
Changed
@@ -3,7 +3,7 @@ NAME ---- -tep_find_function,tep_find_function_address - Find function name / start address. +tep_find_function,tep_find_function_address,tep_find_function_info - Find function name / start address. SYNOPSIS -------- @@ -13,6 +13,8 @@ const char pass:**tep_find_function*(struct tep_handle pass:*_tep_, unsigned long long _addr_); unsigned long long *tep_find_function_address*(struct tep_handle pass:*_tep_, unsigned long long _addr_); +int *tep_find_function_info*(struct tep_handle pass:*_tep_, unsigned long long _addr_, const char pass:**_name_, + unsigned long long pass:*_start_, unsigned long pass:*_size_); -- DESCRIPTION @@ -21,21 +23,29 @@ address. The given address does not have to be exact, it will select the function that would contain it. -The _tep_find_function()_ function returns the function name, which contains the +The *tep_find_function()* function returns the function name, which contains the given address _addr_. The _tep_ argument is the trace event parser context. -The _tep_find_function_address()_ function returns the function start address, +The *tep_find_function_address()* function returns the function start address, by given address _addr_. The _addr_ does not have to be exact, it will select the function that would contain it. The _tep_ argument is the trace event parser context. +The *tep_find_function_info()* function retrieves the _name_, starting address (_start_), +and the function text _size_ of the function at _address_, if it is found. Note, +if the _tep_ handle has a function resolver (used by perf), then _size_ is set to +zero. + RETURN VALUE ------------ -The _tep_find_function()_ function returns the function name, or NULL in case +The *tep_find_function()* function returns the function name, or NULL in case it cannot be found. -The _tep_find_function_address()_ function returns the function start address, +The *tep_find_function_address()* function returns the function start address, or 0 in case it cannot be found. +The *tep_find_function_info()* function returns 1 if a function is found for the +given address, or 0 if it is not. + EXAMPLE ------- source,c @@ -44,12 +54,45 @@ ... struct tep_handle *tep = tep_alloc(); ... -void show_function( unsigned long long addr) +void show_function_name(unsigned long long addr) +{ + const char *fname = tep_find_function(tep, addr); + + if (fname) + printf("Found function %s at 0x%0llx\n", fname, addr); + else + printf("No function found at 0x%0llx\n", addr); +} + +void show_function_start_addr(unsigned long long addr) { const char *fname = tep_find_function(tep, addr); - unsigned long long fstart = tep_find_function_address(tep, addr); + unsigned long long fstart; + + if (!fname) { + printf("No function found at 0x%0llx\n", addr); + return; + } + + fstart = tep_find_function_address(tep, addr); + printf("Function %s at 0x%llx starts at 0x%0llx\n", + fname, addr, fstart); +} + +void show_function_info(unsigned long long addr) +{ + const char *fname; + unsigned long long fstart; + unsigned long size; + + ret = tep_find_function_info(tep, addr, &fname, &fstart, &size); + if (!ret) { + printf("No function found at 0x%0lx\n", addr); + return; + } - /* addr is in function named fname, starting at fstart address, at offset (addr - fstart) */ + printf("Function %s at 0x%lx starts at 0x%0lx and is %ld in size\n", + fname, addr, fstart, size); } ... -- @@ -66,7 +109,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-handle.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-handle.txt
Changed
@@ -3,7 +3,7 @@ NAME ---- -tep_alloc, tep_free,tep_ref, tep_unref,tep_get_ref - Create, destroy, manage +tep_alloc, tep_free,tep_ref, tep_unref,tep_get_ref, tep_kbuffer - Create, destroy, manage references of trace event parser context. SYNOPSIS @@ -17,6 +17,7 @@ void *tep_ref*(struct tep_handle pass:*_tep_); void *tep_unref*(struct tep_handle pass:*_tep_); int *tep_get_ref*(struct tep_handle pass:*_tep_); +struct kbuffer pass:**tep_kbuffer*(struct tep_handle pass:*_tep_); -- DESCRIPTION @@ -25,29 +26,36 @@ structure, representing the trace event parser context. This context is used as the input parameter of most library APIs. -The _tep_alloc()_ function allocates and initializes the tep context. +The *tep_alloc()* function allocates and initializes the tep context. -The _tep_free()_ function will decrement the reference of the _tep_ handler. +The *tep_free()* function will decrement the reference of the _tep_ handler. When there is no more references, then it will free the handler, as well as clean up all its resources that it had used. The argument _tep_ is the pointer to the trace event parser context. -The _tep_ref()_ function adds a reference to the _tep_ handler. +The *tep_ref()* function adds a reference to the _tep_ handler. -The _tep_unref()_ function removes a reference from the _tep_ handler. When +The *tep_unref()* function removes a reference from the _tep_ handler. When the last reference is removed, the _tep_ is destroyed, and all resources that it had used are cleaned up. -The _tep_ref_get()_ functions gets the current references of the _tep_ handler. +The *tep_ref_get()* functions gets the current references of the _tep_ handler. + +The *tep_kbuffer()* function allocates a kbuffer descriptor that can be used to +parse raw data that is represented by the _tep_ handle descriptor. It must be freed +with *kbuf_free(3)*. RETURN VALUE ------------ -_tep_alloc()_ returns a pointer to a newly created tep_handle structure. +*tep_alloc()* returns a pointer to a newly created tep_handle structure. NULL is returned in case there is not enough free memory to allocate it. -_tep_ref_get()_ returns the current references of _tep_. +*tep_ref_get()* returns the current references of _tep_. If _tep_ is NULL, 0 is returned. +*tep_kbuffer()* returns a kbuffer descriptor that can parse the raw data that +represents the tep handle. Must be freed with *kbuf_free(3)*. + EXAMPLE ------- source,c @@ -79,7 +87,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-header_page.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-header_page.txt
Changed
@@ -22,26 +22,26 @@ events/header_page. Old kernels do not have header page info, so default values from user space context are used. -The _tep_get_header_page_size()_ function returns the size of a long integer, +The *tep_get_header_page_size()* function returns the size of a long integer, in kernel context. The _tep_ argument is trace event parser context. This information is retrieved from tracefs events/header_page, "commit" field. -The _tep_get_header_timestamp_size()_ function returns the size of timestamps, +The *tep_get_header_timestamp_size()* function returns the size of timestamps, in kernel context. The _tep_ argument is trace event parser context. This information is retrieved from tracefs events/header_page, "timestamp" field. -The _tep_is_old_format()_ function returns true if the kernel predates +The *tep_is_old_format()* function returns true if the kernel predates the addition of events/header_page, otherwise it returns false. RETURN VALUE ------------ -The _tep_get_header_page_size()_ function returns the size of a long integer, +The *tep_get_header_page_size()* function returns the size of a long integer, in bytes. -The _tep_get_header_timestamp_size()_ function returns the size of timestamps, +The *tep_get_header_timestamp_size()* function returns the size of timestamps, in bytes. -The _tep_is_old_format()_ function returns true, if an old kernel is used to +The *tep_is_old_format()* function returns true, if an old kernel is used to generate the tracing data, which has no event/header_page. If the kernel is new, or _tep_ is NULL, false is returned. @@ -80,7 +80,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-host_endian.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-host_endian.txt
Changed
@@ -25,15 +25,15 @@ DESCRIPTION ----------- -The _tep_is_bigendian()_ gets the endianness of the machine, executing +The *tep_is_bigendian()* gets the endianness of the machine, executing the function. -The _tep_is_local_bigendian()_ function gets the endianness of the local +The *tep_is_local_bigendian()* function gets the endianness of the local machine, saved in the _tep_ handler. The _tep_ argument is the trace event -parser context. This API is a bit faster than _tep_is_bigendian()_, as it +parser context. This API is a bit faster than *tep_is_bigendian()*, as it returns cached endianness of the local machine instead of checking it each time. -The _tep_set_local_bigendian()_ function sets the endianness of the local +The *tep_set_local_bigendian()* function sets the endianness of the local machine in the _tep_ handler. The _tep_ argument is trace event parser context. The _endian_ argument is the endianness: verse @@ -44,10 +44,10 @@ RETURN VALUE ------------ -The _tep_is_bigendian()_ function returns non zero if the endianness of the +The *tep_is_bigendian()* function returns non zero if the endianness of the machine, executing the code, is big endian and zero otherwise. -The _tep_is_local_bigendian()_ function returns true, if the endianness of the +The *tep_is_local_bigendian()* function returns true, if the endianness of the local machine, saved in the _tep_ handler, is big endian, or false otherwise. EXAMPLE @@ -82,7 +82,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-kbuffer-create.txt
Added
@@ -0,0 +1,233 @@ +libtraceevent(3) +================ + +NAME +---- +kbuffer_alloc, kbuffer_dup, kbuffer_free, kbuffer_load_subbuffer, kbuffer_subbuffer, +kbuffer_refresh, kbuffer_subbuffer_size, kbuffer_start_of_data - Creating of kbuffer element to parse +the Linux kernel tracing ring buffer + +SYNOPSIS +-------- +verse +-- +*#include <kbuffer.h>* + +enum kbuffer_endian { + KBUFFER_ENDIAN_BIG, + KBUFFER_ENDIAN_LITTLE, + KBUFFER_ENDIAN_SAME_AS_HOST, +}; + +enum kbuffer_long_size { + KBUFFER_LSIZE_4, + KBUFFER_LSIZE_8, + KBUFFER_LSIZE_SAME_AS_HOST, +}; + +struct kbuffer; +struct tep_handle; + +struct kbuffer pass:**kbuffer_alloc*(enum kbuffer_long_size _size_, enum kbuffer_endian _endian_); +struct kbuffer pass:**kbuffer_dup*(struct kbuffer pass:*_kbuf_); +void *kbuffer_free*(struct kbuffer pass:*_kbuf_); +int *kbuffer_load_subbuffer*(struct kbuffer pass:*_kbuf_, void pass:*_subbuffer_); +int *kbuffer_subbuffer_size*(struct kbuffer pass:*_kbuf_); +int *kbuffer_refresh*(struct kbuffer pass:*_kbuf_); +int *kbuffer_start_of_data*(struct kbuffer pass:*_kbuf_); +void pass:**kbuffer_subbuffer*(struct kbuffer pass:*_kbuf); +-- + +DESCRIPTION +----------- +These functions create a _kbuffer_ handle that can be used to parse the raw sub buffers +of the Linux kernel tracing ring buffer. The ring buffer is found in the tracefs +directory, and can be retrieved by *tracefs_instance_get_file(3)* at +*per_cpu/cpuX/trace_pipe_raw* where *X* is replaced by the per CPU number of +the specified ring buffer. The ring buffer inside the kernel is split up per +CPU, such that the raw ring buffer must be retrieved per CPU as well. + +The *kbuffer_alloc()* will create a descriptor that can be used to manage a sub buffer +read by the ring buffer. The _size_ parameter denotes what the word size is +for the given buffer (note, this works from reading raw data from machines other +than the machine that is calling this function). The _endian_ denotes the endian +for the machine. + +If _endian_ is set to _KBUFFER_ENDIAN_SAME_AS_HOST_ the endian will be set to the same +as the host endianess, which is useful when the application is reading the +ring buffer data directly from the same machine it is running on. + +If _size_ is set to _KBUFFER_LSIZE_SAME_AS_HOST_, if the word size is 8, it will +set the kbuffer descriptor to long size of 8. But if the size is 4, then it +will then perform a *uname(2)* call, and if the _machine_ field has the string "64" +in it, it will be set to 8 byte long size and not 4 byte. This is because the +ring buffer long size is dependent on the kernel and not user space. + +The *kbuffer_dup()* function will duplicate an existing kbuffer structure with +an allocated new one. It will have all the properties of the passed in _kbuf_, +including pointing to the same subbuffer that was loaded in the _kbuf_. +It must be freed with *kbuffer_free()*. + +The *kbuffer_free()* function will free the resources created by *kbuffer_alloc()*. + +The *kbuffer_load_subbuffer()* will take a _subbuffer_ which is a raw data blob +from the tracefs *trace_pipe_raw* file. The Linux tracing ring buffer is broken up +into sub buffers. Each sub buffer is as stand alone data segment that has all the +information to split out the individual events and time stamps. This sub buffer +is what kbuffer uses to walk the events. + +The *kbuffer_subbuffer_size()* returns the location of the end of the last event +on the sub-buffer. It does not return the size of the sub-buffer itself. + +The *kbuffer_refresh()* is to be used if more writes were done on the loaded kbuffer +where the size of the kbuffer needs to be refreshed to be able to read the new +events that were written since the last *kbuffer_load_subbuffer()* was called on it. + +Note, no memory barriers are implemented with this function and any synchronization +with the writer is the responsibility of the application. + +The *kbuffer_start_of_data()* function returns the offset of where the actual +data load of the sub-buffer begins. + +The *kbuffer_subbuffer()* function returns the pointer to the currently loaded +subbuffer. That is, the last subbuffer that was loaded by *kbuffer_load_subbuffer()*. +If no subbuffer was loaded NULL is returned. + +RETURN VALUE +------------ +*kbuffer_alloc()* returns an allocated kbuffer descriptor or NULL on error. +The returned descriptor must be freed with *kbuffer_free()* + +*kbuffer_load_subbuffer()* returns 0 on success and -1 on error. + +*kbuffer_subbuffer_size()* returns the index on the subbuffer where the end +of the last event is located. + +*kbuffer_start_of_data()* returns the offset of where the data begins on the +sub-buffer loaded in _kbuf_. + +*kbuffer_subbuffer()* returns the last loaded subbuffer to _kbuf_ that was loaded +by *kbuffer_load_subbuffer()* or NULL if none was loaded. + +*kbuffer_refresh()* returns 0 on success and -1 if _kbuf_ is NULL or it does not +have a subbuffer loaded via *kbuffer_load_subbuffer()*. + +EXAMPLE +------- +source,c +-- +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/stat.h> + +#include <kbuffer.h> + +int main (int argc, char **argv) +{ + unsigned long long ts; + struct kbuffer *kbuf; + struct stat st; + char *buf; + void *event; + int ret; + int fd; + int i = 0; + + if (argc < 2) { + printf("usage: %s raw-subbuffer-page\n", argv0); + printf(" Try: dd count=1 bs=4096 if=/sys/kernel/tracing/per_cpu/cpu0/trace_pipe_raw of=/tmp/file\n"); + exit(0); + } + + if (stat(argv1, &st) < 0) { + perror("stat"); + exit(-1); + } + + buf = malloc(st.st_size); + if (!buf) { + perror("Allocating buffer"); + exit(-1); + } + + fd = open(argv1, O_RDONLY); + if (fd < 0) { + perror(argv1); + exit(-1); + } + + ret = read(fd, buf, st.st_size); + if (ret < 0) { + perror("Reading buffer"); + exit(-1); + } + close(fd); + + kbuf = kbuffer_alloc(KBUFFER_ENDIAN_SAME_AS_HOST, + KBUFFER_LSIZE_SAME_AS_HOST); + if (!kbuf) { + perror("Creating kbuffer"); + exit(-1); + } + ret = kbuffer_load_subbuffer(kbuf, buf); + if (ret < 0) { + perror("Loading sub bufer"); + exit(-1); + } + + if (kbuffer_subbuffer_size(kbuf) > st.st_size) { + fprintf(stderr, "kbuffer is bigger than raw size %d > %ld\n", + kbuffer_subbuffer_size(kbuf), st.st_size); + exit(-1); + } + + printf("Kbuffer data starts at %d\n", kbuffer_start_of_data(kbuf)); + do { + event = kbuffer_read_event(kbuf, &ts); + if (event) { + printf(" event %3d ts:%lld\n", i++, ts); + event = kbuffer_next_event(kbuf, NULL); + } + } while (event); + + if (!event) + printf("Finished sub buffer\n"); + + kbuffer_free(kbuf); + + return 0; +} +-- +FILES +----- +verse +-- +*event-parse.h* + Header file to include in order to have access to the library APIs. +*-ltraceevent* + Linker switch to add when building a program that uses the library. +-- + +SEE ALSO +-------- +*libtraceevent*(3), *trace-cmd*(1) + +AUTHOR +------ +verse +-- +*Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. +-- +REPORTING BUGS +-------------- +Report bugs to <linux-trace-devel@vger.kernel.org> + +LICENSE +------- +libtraceevent is Free Software licensed under the GNU LGPL 2.1 + +RESOURCES +--------- +https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-kbuffer-read.txt
Added
@@ -0,0 +1,263 @@ +libtraceevent(3) +================ + +NAME +---- +kbuffer_read_event, kbuffer_next_event, kbuffer_missed_events, kbuffer_event_size, kbuffer_curr_size, +kbuffer_curr_offset, kbuffer_curr_index, kbuffer_read_buffer - +Functions to read through the kbuffer sub buffer. + +SYNOPSIS +-------- +verse +-- +*#include <kbuffer.h>* + +void pass:**kbuffer_read_event*(struct kbuffer pass:*_kbuf_, unsigned long long pass:*_ts_); +void pass:**kbuffer_next_event*(struct kbuffer pass:*_kbuf_, unsigned long long pass:*_ts_); +void pass:**kbuffer_read_at_offset*(struct kbuffer pass:*_kbuf_, int _offset_, unsigned long long pass:*_ts_); +int *kbuffer_missed_events*(struct kbuffer pass:*_kbuf_); +int *kbuffer_event_size*(struct kbuffer pass:*_kbuf_); +int *kbuffer_curr_size*(struct kbuffer pass:*_kbuf_); +int *kbuffer_curr_offset*(struct kbuffer pass:*_kbuf_); +int *kbuffer_curr_index*(struct kbuffer pass:*_kbuf_); +int *kbuffer_read_buffer*(struct kbuffer pass:*_kbuf_, void pass:*_buffer_, int _len_); +-- + +DESCRIPTION +----------- +The function *kbuffer_read_event()* reads the next event in the _kbuf_ descriptor +and if _ts_ is non NULL, will place its timestamp into it. This does not modify the _kbuf_ +descriptor, and calling this function mulitple times will return the same result. + +The function *kbuffer_next_event()* will return the next event in the _kbuf_ descriptor. +It will also set the _ts_ to the timestamp of the returned event. NULL is returned +if there are no more events and _ts_ will be undefined. Note, if this is called directly +after a *kbuffer_load_subbuffer()* then it will likely give an unexpected result, as it +will return the second event and not the first event. Usually this function is only used +to move to the next event and to know if there's any more events to read, and +*kbuffer_read_event()* is always called first. + +The function *kbuffer_read_at_offset()* returns the event located at a given _offset_ from +the beginning of the sub-buffer. This offset can be retrieved by *kbuffer_curr_offset()*. +If _ts_ points to an unsigned long long, then it will be set to the event at the given +offset's timestamp. + +If the sub-buffer had missed events before it, then *kbuffer_missed_events()* will return +the non zero. If it returns -1, that means there were missed events, but the exact number +of missed events is unknown. If it returns a positive number, then the number of missed events +is the return value. + +The *kbuffer_event_size()* function returns the size of the data portion of the current event +(the one that would be returned by *kbuffer_read_event()*. + +The *kbuffer_curr_size()* function returns the entire record size of the current event +(the one that would be returned by *kbuffer_read_event()*. The difference here is that the +return value includes the size of the event record meta data that is not part of what +is returned by *kbuffer_read_event()*. + +The *kbuffer_curr_offset()* function returns the offset from the beginning of the sub-buffer +of where the current event's meta data for the record begins. The first event will +not be at offset zero. This offset can be used to retrieve the event with +*kbuffer_read_at_offset()*. + +The *kbuffer_curr_index()* function returns the index from the beginning of the data +portion of the sub-buffer where the current evnet's meta data is located. +The first event will likely be zero, but may not be if there's a timestamp attached to it. + +The *kbuffer_read_buffer()* function will fill the given _buffer_ from the _kbuf_ the same +way the kernel would do a read system call. That is, if the length _len_ is less than the +sub buffer size, or the kbuffer current index is non-zero, it will start copying from the +_kbuf_ current event and create _buffer_ as a new sub buffer (with a timestamp +and commit header) with that event that was found and including all events after that can +fit within _len_. The _len_ must include the size of the sub buffer header as well as the +events to include. That is, _len_ is the allocate size of _buffer_ that can be filled. +The return from this function is the index of the end of the last event that was added. +If there are no more events then zero is returned, and if the buffer can not +copy any events because _len_ was too small, then -1 is returned. + + +RETURN VALUE +------------ +*kbuffer_read_event()* returns the event that the _kbuf_ descriptor is currently at, +or NULL if the last event was passed (by *kbuffer_next_event()*). + +*kbuffer_next_event()* returns the next event after the current event or NULL if there +are no more events. + +*kbuffer_read_at_offset()* returns the event at a given _offset_ from the start of +the sub-buffer stored in _kbuf_, or NULL if there exists no event. Note, _offset_ +only needs to be an offset that lands on the record, or is at the start of it. It does +not need to be exactly at the beginning of the record. + +*kbuffer_missed_events()* returns 0 if there were no missed events before loaded sub-buffer. +Returns -1 if there were an unknown number of missed events, or if the number of missed events +is known, that number will be returned. + +*kbuffer_event_size()* returns the size of the data payload of the current event of _kbuf_. + +*kbuffer_curr_size()* returns the size of the entire record of the current event of _kbuf_. +This includes the size of the meta data for that record. + +*kbuf_curr_offset()* returns the offset of the current record from the beginning of the _kbuf_ +sub-buffer. + +*kbuf_curr_index()* returns the index of the current record from the beginning of the _kbuf_ +data section. + +*kbuf_read_buffer()* returns the index of the end of the last event that was filled in +_buffer_. If there are no more events to copy from _start_ then 0 is returned. If _len_ +is not big enough to hold any events, then -1 is returned. + +EXAMPLE +------- +source,c +-- +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/stat.h> + +#include <kbuffer.h> + +int main (int argc, char **argv) +{ + unsigned long long ts; + struct kbuffer *kbuf; + struct stat st; + char *buf; + void *event; + int save_offset = -1; + int record_size; + int offset; + int index; + int size; + int ret; + int fd; + int i = 0; + + if (argc < 2) { + printf("usage: %s raw-subbuffer-page\n", argv0); + printf(" Try: dd count=1 bs=4096 if=/sys/kernel/tracing/per_cpu/cpu0/trace_pipe_raw of=/tmp/file\n"); + exit(0); + } + + if (stat(argv1, &st) < 0) { + perror("stat"); + exit(-1); + } + + buf = malloc(st.st_size); + if (!buf) { + perror("Allocating buffer"); + exit(-1); + } + + fd = open(argv1, O_RDONLY); + if (fd < 0) { + perror(argv1); + exit(-1); + } + + ret = read(fd, buf, st.st_size); + if (ret < 0) { + perror("Reading buffer"); + exit(-1); + } + close(fd); + + kbuf = kbuffer_alloc(KBUFFER_ENDIAN_SAME_AS_HOST, + KBUFFER_LSIZE_SAME_AS_HOST); + if (!kbuf) { + perror("Creating kbuffer"); + exit(-1); + } + ret = kbuffer_load_subbuffer(kbuf, buf); + if (ret < 0) { + perror("Loading sub bufer"); + exit(-1); + } + + if (kbuffer_subbuffer_size(kbuf) > st.st_size) { + fprintf(stderr, "kbuffer is bigger than raw size %d > %ld\n", + kbuffer_subbuffer_size(kbuf), st.st_size); + exit(-1); + } + + ret = kbuffer_missed_events(kbuf); + if (ret) { + if (ret > 0) + printf("Missed %d events before this buffer\n", ret); + else + printf("Missed unknown number of events before this buffer\n"); + } + do { + event = kbuffer_read_event(kbuf, &ts); + if (event) { + record_size = kbuffer_curr_size(kbuf); + offset = kbuffer_curr_offset(kbuf); + index = kbuffer_curr_index(kbuf); + size = kbuffer_event_size(kbuf); + + if (i == 20) + save_offset = offset; + printf(" event %3d ts:%lld\trecord_size:%d size:%d\tindex:%d offset:%d\n", + i++, ts, record_size, size, index, offset); + event = kbuffer_next_event(kbuf, NULL); + } + } while (event); + + if (!event) + printf("Finished sub buffer\n"); + + if (save_offset > 0) { + event = kbuffer_read_at_offset(kbuf, save_offset, &ts); + if (!event) { + fprintf(stderr, "Funny, can't find event 20 at offset %d\n", save_offset); + exit(-1); + } + record_size = kbuffer_curr_size(kbuf); + offset = kbuffer_curr_offset(kbuf); + index = kbuffer_curr_index(kbuf); + size = kbuffer_event_size(kbuf); + + printf("\n saved event 20 ts:%lld\trecord_size:%d size:%d\tindex:%d offset:%d\n\n", + ts, record_size, size, index, offset); + } + kbuffer_free(kbuf); + + return 0; +} +-- +FILES +----- +verse +-- +*event-parse.h* + Header file to include in order to have access to the library APIs. +*-ltraceevent* + Linker switch to add when building a program that uses the library. +-- + +SEE ALSO +-------- +*libtraceevent*(3), *trace-cmd*(1) + +AUTHOR +------ +verse +-- +*Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. +-- +REPORTING BUGS +-------------- +Report bugs to <linux-trace-devel@vger.kernel.org> + +LICENSE +------- +libtraceevent is Free Software licensed under the GNU LGPL 2.1 + +RESOURCES +--------- +https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-kbuffer-timestamp.txt
Added
@@ -0,0 +1,208 @@ +libtraceevent(3) +================ + +NAME +---- +kbuffer_timestamp, kbuffer_subbuf_timestamp - +Functions that read various data of a kbuffer descriptor + +SYNOPSIS +-------- +verse +-- +*#include <kbuffer.h>* + +unsigned long long *kbuffer_timestamp*(struct kbuffer pass:*_kbuf_); +unsigned long long *kbuffer_subbuf_timestamp*(struct kbuffer pass:*_kbuf_, void pass:*_subbuf_); +-- + +DESCRIPTION +----------- +The function *kbuffer_timestamp()* returns the timestamp of the current event of _kbuf_. + +The function *kbuffer_subbuf_timestamp()* returns the timestamp for the sub-buffer +that was loaded in _kbuf_. This usually is (but not guaranteed to be) the timestamp +of the first event on the sub-buffer. + +The function *kbuffer_start_of_data()* returns the offset of where the delta + +RETURN VALUE +------------ +*kbuffer_read_event()* returns the event that the _kbuf_ descriptor is currently at, +or NULL if the last event was passed (by *kbuffer_next_event()*). + +*kbuffer_next_event()* returns the next event after the current event or NULL if there +are no more events. + +*kbuffer_read_at_offset()* returns the event at a given _offset_ from the start of +the sub-buffer stored in _kbuf_, or NULL if there exists no event. Note, _offset_ +only needs to be an offset that lands on the record, or is at the start of it. It does +not need to be exactly at the beginning of the record. + +*kbuffer_missed_events()* returns 0 if there were no missed events before loaded sub-buffer. +Returns -1 if there were an unknown number of missed events, or if the number of missed events +is known, that number will be returned. + +*kbuffer_event_size()* returns the size of the data payload of the current event of _kbuf_. + +*kbuffer_curr_size()* returns the size of the entire record of the current event of _kbuf_. +This includes the size of the meta data for that record. + +*kbuf_curr_offset()* returns the offset of the current record from the beginning of the _kbuf_ +sub-buffer. + +*kbuf_curr_index()* returns the index of the current record from the beginning of the _kbuf_ +data section. + +EXAMPLE +------- +source,c +-- +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/stat.h> + +#include <kbuffer.h> + +int main (int argc, char **argv) +{ + unsigned long long ts; + struct kbuffer *kbuf; + struct stat st; + char *buf; + void *event; + int save_offset = -1; + int record_size; + int offset; + int index; + int size; + int ret; + int fd; + int i = 0; + + if (argc < 2) { + printf("usage: %s raw-subbuffer-page\n", argv0); + printf(" Try: dd count=1 bs=4096 if=/sys/kernel/tracing/per_cpu/cpu0/trace_pipe_raw of=/tmp/file\n"); + exit(0); + } + + if (stat(argv1, &st) < 0) { + perror("stat"); + exit(-1); + } + + buf = malloc(st.st_size); + if (!buf) { + perror("Allocating buffer"); + exit(-1); + } + + fd = open(argv1, O_RDONLY); + if (fd < 0) { + perror(argv1); + exit(-1); + } + + ret = read(fd, buf, st.st_size); + if (ret < 0) { + perror("Reading buffer"); + exit(-1); + } + close(fd); + + kbuf = kbuffer_alloc(KBUFFER_ENDIAN_SAME_AS_HOST, + KBUFFER_LSIZE_SAME_AS_HOST); + if (!kbuf) { + perror("Creating kbuffer"); + exit(-1); + } + ret = kbuffer_load_subbuffer(kbuf, buf); + if (ret < 0) { + perror("Loading sub bufer"); + exit(-1); + } + + if (kbuffer_subbuffer_size(kbuf) > st.st_size) { + fprintf(stderr, "kbuffer is bigger than raw size %d > %ld\n", + kbuffer_subbuffer_size(kbuf), st.st_size); + exit(-1); + } + + ret = kbuffer_missed_events(kbuf); + if (ret) { + if (ret > 0) + printf("Missed %d events before this buffer\n", ret); + else + printf("Missed unknown number of events before this buffer\n"); + } + do { + event = kbuffer_read_event(kbuf, &ts); + if (event) { + record_size = kbuffer_curr_size(kbuf); + offset = kbuffer_curr_offset(kbuf); + index = kbuffer_curr_index(kbuf); + size = kbuffer_event_size(kbuf); + + if (i == 20) + save_offset = offset; + printf(" event %3d ts:%lld\trecord_size:%d size:%d\tindex:%d offset:%d\n", + i++, ts, record_size, size, index, offset); + event = kbuffer_next_event(kbuf, NULL); + } + } while (event); + + if (!event) + printf("Finished sub buffer\n"); + + if (save_offset > 0) { + event = kbuffer_read_at_offset(kbuf, save_offset, &ts); + if (!event) { + fprintf(stderr, "Funny, can't find event 20 at offset %d\n", save_offset); + exit(-1); + } + record_size = kbuffer_curr_size(kbuf); + offset = kbuffer_curr_offset(kbuf); + index = kbuffer_curr_index(kbuf); + size = kbuffer_event_size(kbuf); + + printf("\n saved event 20 ts:%lld\trecord_size:%d size:%d\tindex:%d offset:%d\n\n", + ts, record_size, size, index, offset); + } + kbuffer_free(kbuf); + + return 0; +} +-- +FILES +----- +verse +-- +*event-parse.h* + Header file to include in order to have access to the library APIs. +*-ltraceevent* + Linker switch to add when building a program that uses the library. +-- + +SEE ALSO +-------- +*libtraceevent*(3), *trace-cmd*(1) + +AUTHOR +------ +verse +-- +*Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. +-- +REPORTING BUGS +-------------- +Report bugs to <linux-trace-devel@vger.kernel.org> + +LICENSE +------- +libtraceevent is Free Software licensed under the GNU LGPL 2.1 + +RESOURCES +--------- +https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-kvm-plugin.txt
Added
@@ -0,0 +1,252 @@ +libtraceevent(3) +================ + +NAME +---- +tep_plugin_kvm_get_func, tep_plugin_kvm_put_func - Add function name for instruction pointer of kvm plugin + +SYNOPSIS +-------- +verse +-- +*#include <event-parse.h>* + +const char pass:**tep_plugin_kvm_get_func*(struct tep_event pass:*event, + struct tep_record pass:*record, + unsigned long long pass:*paddr); +void *tep_plugin_kvm_put_func*(const char pass:*func); +-- + +DESCRIPTION +----------- +The functions *tep_plugin_kvm_get_func()* and *tep_plugin_kvm_put_func()* +are not to be called by an application, but instead are to be defined by +an application. + +Certain events (like kvm_exit and kvm_entry) have the instruction pointer +of where in the guest the context changed from guest to host. As the host +only knows the instruction pointer and does not have information about what +function in the guest that instruction pointer belongs to, it can only print +the address. + +But the application may have more information about the guest, and know where +the guest was when the exit occurred, and also even know the function name +of that address. + +The KVM plugin for libtraceevent is called on these events, and then calls +*tep_plugin_kvm_get_func()* to see if that function can resolve the instruction +pointer address to a real function name. If the return is non NULL, it will +print the function in the output for that event. + +These functions are currently defined as weak functions within the plugin, as +to not require them to be defined elsewhere. For an application to override +the weak function, it will need to define the function in a file that gets +compiled with *-rdynamic*. That will tell the dynamic linker to examine that +object file and use function names to resolve weak functions in other shared +objects (in this case the KVM plugin shared object). + +If the application defines *tep_plugin_kvm_get_func()*, it must use the above +prototype. The _event_ will hold the KVM event that has the instruction pointer +field. The _record_ will be the instance of that event. The application's function +does not need to use these parameters, but they may be useful for finding the +function name for the address. The _paddr_ is a pointer to a 64 bit value (where +only 32 bits may be used on 32 bit machines). This value is the instruction +pointer to look up. If the application knows the start address of the function +as well, it can set _paddr_ to that address, and the KVM plugin will also +append a "+offset" to the function name where the offset is the original +value in _paddr_ minus the value in _paddr_ when it is called. Finally, +the application should return the function name as a nul terminated string +if one is found. + +If the returned string of *tep_plugin_kvm_get_func()* was allocated, the KVM plugin +will call *tep_plugin_kvm_put_func()* when it is through with it, passing the +value returned by *tep_plugin_kvm_get_func()* as _func_. This allows the application +to free it if necessary. + +RETURN VALUE +------------ +The *tep_plugin_kvm_get_func()* is not to be called by the application but instead +is to be defined by the application. It should return a nul terminated string representing +the function for the given instruction pointer passed to it by reference in _paddr_. It +can then optionally update the _paddr_ to a value that holds the start of the function. +The string returned may be freed by the *tep_plugin_kvm_put_func()* that the application +should define to clean up the string. + +The below example needs to be compiled with the *-rdynamic* flag so that the dynamic +linker can resolve the *tep_plugin_kvm_get_func()* and *tep_plugin_kvm_put_func()* functions. + +When run against a trace.dat file produced by *trace-cmd(1)* recording the kvm_exit and +kvm_entry events on a guest, and then the guest's /proc/kallsyms file is passed as the +second parameter, the output produced will look something like: + +source,c +-- +CPU 0/KVM-20407 83156.177626 000 kvm_exit reason APIC_ACCESS rip 0xffffffffb0056ee2 exit native_apic_mem_write+0x2 info 10b0 0 +CPU 0/KVM-20407 83156.177632 000 kvm_entry vcpu 0 rip 0xffffffffb0056ee8 enter native_apic_mem_write+0x8 +-- + +But without those callbacks, it would look like: + +source,c +-- +CPU 0/KVM-20407 83156.177626 000 kvm_exit reason APIC_ACCESS rip 0xffffffffb0056ee2 info 10b0 0 +CPU 0/KVM-20407 83156.177632 000 kvm_entry vcpu 0 rip 0xffffffffb0056ee8 +-- + +EXAMPLE +------- +source,c +-- +#include <stdio.h> +#include <stdlib.h> +#include <event-parse.h> +#include <trace-cmd.h> +#include <sys/stat.h> + +static struct tep_handle *tep; + +const char *tep_plugin_kvm_get_func(struct tep_event *event, struct tep_record *record, + unsigned long long *paddr) +{ + const char *func; + char *event_func; + char *ename; + + func = tep_find_function(tep, *paddr); + if (!func) + return NULL; + + if (strcmp(event->name, "kvm_exit") == 0) + ename = "exit"; + else + ename = "enter"; + + /* + * Normally, passing back func directly is sufficient and then + * tep_plugin_kvm_put_func() would not be required. But this example + * is showing how to handle allocation of the returned string. + */ + event_func = malloc(strlen(ename) + strlen(func) + 2); + if (!event_func) + return NULL; + sprintf(event_func, "%s %s", ename, func); + + *paddr = tep_find_function_address(tep, *paddr); + + return event_func; +} + +void tep_plugin_kvm_put_func(const char *func) +{ + char *f = (char *)func; + + free(f); +} + +static int show_event(struct tracecmd_input *handle, struct tep_event *event, + struct tep_record *record, int cpu, void *data) +{ + static struct trace_seq seq; + tep = data; + + if (!seq.buffer) + trace_seq_init(&seq); + + trace_seq_reset(&seq); + tep_print_event(tracecmd_get_tep(handle), &seq, record, + "%s-%d\t%6.1000d %03d %s\t%s\n", + TEP_PRINT_COMM, TEP_PRINT_PID, + TEP_PRINT_TIME, TEP_PRINT_CPU, + TEP_PRINT_NAME, TEP_PRINT_INFO); + trace_seq_terminate(&seq); + trace_seq_do_printf(&seq); + return 0; +} + +int main(int argc, char **argv) +{ + struct tracecmd_input *handle; + struct tep_handle *guest_tep; + struct stat st; + FILE *fp; + char *buf; + + if (argc < 3) { + printf("usage: trace.dat guest_kallsyms_file\n"); + exit(-1); + } + + handle = tracecmd_open(argv1, 0); + if (!handle) { + perror(argv1); + exit(-1); + } + + /* Just for kallsyms parsing */ + guest_tep = tep_alloc(); + if (!guest_tep) + exit(-1); + + if (stat(argv2, &st) < 0) { + perror(argv2); + exit(-1); + } + + buf = malloc(st.st_size + 1); + if (!buf) + exit(-1); + + fp = fopen(argv2, "r"); + if (!fp) { + perror(argv2); + exit(-1); + } + + if (fread(buf, st.st_size, 1, fp) < 0) { + perror(argv2); + exit(-1); + } + + bufst.st_size = '\0'; + + if (tep_parse_kallsyms(guest_tep, buf) < 0) { + printf("Failed to parse %s\n", argv2); + exit(-1); + } + free(buf); + + tracecmd_follow_event(handle, "kvm", "kvm_exit", show_event, guest_tep); + tracecmd_follow_event(handle, "kvm", "kvm_entry", show_event, guest_tep); + + tracecmd_iterate_events(handle, NULL, 0, NULL, NULL); + + tep_free(guest_tep); + tracecmd_close(handle); +} +-- + +FILES +----- +verse +-- +*event-parse.h* + Header file to include in order to have access to the library APIs. +*-ltraceevent* + Linker switch to add when building a program that uses the library. +-- + +SEE ALSO +-------- +*libtraceevent*(3), *trace-cmd*(1) + +REPORTING BUGS +-------------- +Report bugs to <linux-trace-devel@vger.kernel.org> + +LICENSE +------- +libtraceevent is Free Software licensed under the GNU LGPL 2.1 + +RESOURCES +--------- +https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-log.txt
Added
@@ -0,0 +1,90 @@ +libtraceevent(3) +================ + +NAME +---- +tep_set_loglevel - Set log level of the library + +SYNOPSIS +-------- +verse +-- +*#include <event-parse.h>* + +enum *tep_loglevel* { + TEP_LOG_NONE = 0, + TEP_LOG_CRITICAL, + TEP_LOG_ERROR, + TEP_LOG_WARNING, + TEP_LOG_INFO, + TEP_LOG_DEBUG, + TEP_LOG_ALL +}; + +int *tep_set_loglevel*(enum tep_loglevel _level_); + +-- +DESCRIPTION +----------- +The *tep_set_loglevel()* function sets the level of the library logs that will be printed +on the console. Library log levels are: +verse +-- + _TEP_LOG_NONE_ - Do not print any logs. + _TEP_LOG_CRITICAL_ - Print critical logs, problem that may cause a crash. + _TEP_LOG_ERROR_ - Print error logs, problem that could break the main logic of an API. + _TEP_LOG_WARNING_ - Print warnings, problem that could limit the result of an API. + _TEP_LOG_INFO_ - Print information about normal execution of an API. + _TEP_LOG_DEBUG_ - Print debug information. + _TEP_LOG_ALL_ - Print logs from all levels. +-- +Setting the log level to specific value means that logs from the previous levels will be printed +too. For example _TEP_LOG_WARNING_ will print any logs with severity _TEP_LOG_WARNING_, +_TEP_LOG_ERROR_ and _TEP_LOG_CRITICAL_. The default log level is _TEP_LOG_CRITICAL_. + + +EXAMPLE +------- +source,c +-- +#include <event-parse.h> + +tep_set_loglevel(TEP_LOG_ALL); +... +/* call libtraceevent APIs and observe any logs they produce */ +... +tep_set_loglevel(TEP_LOG_CRITICAL); +-- + +FILES +----- +verse +-- +*event-parse.h* + Header file to include in order to have access to the library APIs. +*-ltraceevent* + Linker switch to add when building a program that uses the library. +-- + +SEE ALSO +-------- +*libtraceevent*(3), *trace-cmd*(1) + +AUTHOR +------ +verse +-- +*Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. +*Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. +-- +REPORTING BUGS +-------------- +Report bugs to <linux-trace-devel@vger.kernel.org> + +LICENSE +------- +libtraceevent is Free Software licensed under the GNU LGPL 2.1 + +RESOURCES +--------- +https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-long_size.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-long_size.txt
Changed
@@ -18,16 +18,16 @@ DESCRIPTION ----------- -The _tep_get_long_size()_ function returns the size of a long integer on the machine, +The *tep_get_long_size()* function returns the size of a long integer on the machine, where the trace is generated. The _tep_ argument is trace event parser context. -The _tep_set_long_size()_ function sets the size of a long integer on the machine, +The *tep_set_long_size()* function sets the size of a long integer on the machine, where the trace is generated. The _tep_ argument is trace event parser context. The _long_size_ is the size of a long integer, in bytes. RETURN VALUE ------------ -The _tep_get_long_size()_ function returns the size of a long integer on the machine, +The *tep_get_long_size()* function returns the size of a long integer on the machine, where the trace is generated, in bytes. EXAMPLE @@ -56,7 +56,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-page_size.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-page_size.txt
Changed
@@ -3,7 +3,7 @@ NAME ---- -tep_get_page_size, tep_set_page_size - Get / set the size of a memory page on +tep_get_page_size, tep_set_page_size, tep_get_sub_buffer_data_size, tep_get_sub_buffer_size - Get / set the size of a memory page on the machine, where the trace is generated SYNOPSIS @@ -14,22 +14,43 @@ int *tep_get_page_size*(struct tep_handle pass:*_tep_); void *tep_set_page_size*(struct tep_handle pass:*_tep_, int _page_size_); +int *tep_get_sub_buffer_size*(struct tep_handle pass:*_tep_); +int *tep_get_sub_buffer_data_size*(struct tep_handle pass:*_tep_); +int *tep_get_sub_buffer_commit_offset*(struct tep_handle pass:*_tep_); -- DESCRIPTION ----------- -The _tep_get_page_size()_ function returns the size of a memory page on +The *tep_get_page_size()* function returns the size of a memory page on the machine, where the trace is generated. The _tep_ argument is trace event parser context. -The _tep_set_page_size()_ function stores in the _tep_ context the size of a +The *tep_set_page_size()* function stores in the _tep_ context the size of a memory page on the machine, where the trace is generated. The _tep_ argument is trace event parser context. The _page_size_ argument is the size of a memory page, in bytes. +The *tep_get_sub_buffer_size()* returns the size of each "sub buffer" of the +ring buffer. The Linux kernel ring buffer is broken up into sections called +sub buffers. This returns the size of those buffers. + +The *tep_get_sub_buffer_data_size()* returns the size of just the data portion +of the sub buffers. + +The *tep_get_sub_buffer_commit_offset()* returns the offset on the sub buffer +that holds the committed portion of data. This number contains the index from +the data portion of the sub buffer that is the end of the last element on the +sub buffer. + RETURN VALUE ------------ -The _tep_get_page_size()_ function returns size of the memory page, in bytes. +The *tep_get_page_size()* function returns size of the memory page, in bytes. + +The *tep_get_sub_buffer_size()* function returns the number of bytes each sub +buffer is made up of. + +The *tep_get_sub_buffer_commit_offset()* function returns the location on the +sub buffer that contains the index of the last element. EXAMPLE ------- @@ -60,7 +81,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-parse-files.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-parse-files.txt
Changed
@@ -19,14 +19,14 @@ DESCRIPTION ----------- -*tep_parse_saved_cmdlines* is a helper function to parse content in the tracefs +*tep_parse_saved_cmdlines()* is a helper function to parse content in the tracefs file system of the "saved_cmdlines" file (stored in a string buffer passed in by _buf_) and loads the mapping of the process IDs (pid) to the comm names in the _tep_ handler. The events store the pid and this is used to be able to show the process names associated to those process ids. It parses the string _buf_ that holds the content of saved_cmdlines and ends with a nul character ('\0'). -*tep_parse_printk_formats* is a helper function to parse content in the tracefs +*tep_parse_printk_formats()* is a helper function to parse content in the tracefs file system of the "printk_formats" file (stored in a string buffer passed in by _buf_) and loads the mapping of addresses of strings that may be referenced by events. Events only store the address of constant strings in the kernel, and the mapping @@ -34,7 +34,7 @@ file. It parses the string _buf_ that holds the content of printk_formats and ends with a nul character ('\0'). -*tep_parse_kallsyms* is a helper function to parse the Linux kernel /proc/kallsyms format +*tep_parse_kallsyms()* is a helper function to parse the Linux kernel /proc/kallsyms format (stored in a string buffer passed in by _buf_) and load the functions into the _tep_ handler such that function IP addresses can be mapped to their name when parsing events with %pS in the print format field. It parses the string _buf_ that @@ -126,8 +126,8 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_, _tep_register_comm(3)_, _tep_register_function(3)_, -_tep_register_print_string_(3) +*libtraceevent*(3), *trace-cmd*(1), *tep_register_comm*(3), *tep_register_function*(3), +*tep_register_print_string*(3) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-parse_event.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-parse_event.txt
Changed
@@ -17,7 +17,7 @@ DESCRIPTION ----------- -The _tep_parse_event()_ function parses the event format and creates an event +The *tep_parse_event()* function parses the event format and creates an event structure to quickly parse raw data for a given event. The _tep_ argument is the trace event parser context. The created event structure is stored in the _tep_ context. The _buf_ argument is a buffer with _size_, where the event @@ -25,13 +25,13 @@ tracefs/events/.../.../format files. The _sys_ argument is the system of the event. -The _tep_parse_format()_ function does the same as _tep_parse_event()_. The only +The *tep_parse_format()* function does the same as *tep_parse_event()*. The only difference is in the extra _eventp_ argument, where the newly created event structure is returned. RETURN VALUE ------------ -Both _tep_parse_event()_ and _tep_parse_format()_ functions return 0 on success, +Both *tep_parse_event()* and *tep_parse_format()* functions return 0 on success, or TEP_ERRNO__... in case of an error. EXAMPLE @@ -68,7 +68,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-parse_head.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-parse_head.txt
Changed
@@ -16,19 +16,19 @@ DESCRIPTION ----------- -The _tep_parse_header_page()_ function parses the header page data from _buf_, +The *tep_parse_header_page()* function parses the header page data from _buf_, and initializes the _tep_, trace event parser context, with it. The buffer _buf_ is with _size_, and is supposed to be copied from tracefs/events/header_page. Some old kernels do not have header page info, in this case the -_tep_parse_header_page()_ function can be called with _size_ equal to 0. The +*tep_parse_header_page()* function can be called with _size_ equal to 0. The _tep_ context is initialized with default values. The _long_size_ can be used in this use case, to set the size of a long integer to be used. RETURN VALUE ------------ -The _tep_parse_header_page()_ function returns 0 in case of success, or -1 +The *tep_parse_header_page()* function returns 0 in case of success, or -1 in case of an error. EXAMPLE @@ -60,7 +60,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-plugins.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-plugins.txt
Changed
@@ -3,7 +3,8 @@ NAME ---- -tep_load_plugins, tep_unload_plugins, tep_load_plugins_hook, tep_add_plugin_path - Load / unload traceevent plugins. +tep_load_plugins, tep_unload_plugins, tep_load_plugins_hook, tep_add_plugin_path, +tep_plugin_add_option - Load / unload traceevent plugins. SYNOPSIS -------- @@ -21,11 +22,12 @@ void pass:*_data_); int *tep_add_plugin_path*(struct tep_handle pass:*tep, char pass:*path, enum tep_plugin_load_priority prio); +int *tep_plugin_add_option*(const char pass:*_name_, const char pass:*_val_); -- DESCRIPTION ----------- -The _tep_load_plugins()_ function loads all plugins, located in the plugin +The *tep_load_plugins()* function loads all plugins, located in the plugin directories. The _tep_ argument is trace event parser context. The plugin directories are : verse @@ -39,29 +41,29 @@ - Directories, specified in _tep_->plugins_dir with priority TEP_PLUGIN_LAST -- Loading of plugins can be controlled by the _tep_flags_, using the -_tep_set_flag()_ API: +*tep_set_flag()* API: verse -- _TEP_DISABLE_SYS_PLUGINS_ - do not load plugins, located in the system's plugin directory. _TEP_DISABLE_PLUGINS_ - do not load any plugins. -- -The _tep_set_flag()_ API needs to be called before _tep_load_plugins()_, if +The *tep_set_flag()* API needs to be called before *tep_load_plugins()*, if loading of all plugins is not the desired case. -The _tep_unload_plugins()_ function unloads the plugins, previously loaded by -_tep_load_plugins()_. The _tep_ argument is trace event parser context. The +The *tep_unload_plugins()* function unloads the plugins, previously loaded by +*tep_load_plugins()*. The _tep_ argument is trace event parser context. The _plugin_list_ is the list of loaded plugins, returned by -the _tep_load_plugins()_ function. +the *tep_load_plugins()* function. -The _tep_load_plugins_hook()_ function walks through all directories with plugins -and calls user specified _load_plugin()_ hook for each plugin file. Only files +The *tep_load_plugins_hook()* function walks through all directories with plugins +and calls user specified *load_plugin()* hook for each plugin file. Only files with given _suffix_ are considered to be plugins. The _data_ is a user specified -context, passed to _load_plugin()_. Directories and the walk order are the same -as in _tep_load_plugins()_ API. +context, passed to *load_plugin()*. Directories and the walk order are the same +as in *tep_load_plugins()* API. -The _tep_add_plugin_path()_ functions adds additional directories with plugins in -the _tep_->plugins_dir list. It must be called before _tep_load_plugins()_ in order +The *tep_add_plugin_path()* functions adds additional directories with plugins in +the _tep_->plugins_dir list. It must be called before *tep_load_plugins()* in order for the plugins from the new directories to be loaded. The _tep_ argument is the trace event parser context. The _path_ is the full path to the new plugin directory. The _prio_ argument specifies the loading priority order for the @@ -76,11 +78,16 @@ Where the plugins in TEP_PLUGIN_LAST" will take precedence over the plugins in the other directories. +The *tep_plugin_add_option()* sets options defined by a plugin. The _name_ is the +name of the option to set to _val_. Plugins can add options to change its behavior +and *tep_plugin_add_option()* is used by the application to make those modifications. + + RETURN VALUE ------------ -The _tep_load_plugins()_ function returns a list of successfully loaded plugins, +The *tep_load_plugins()* function returns a list of successfully loaded plugins, or NULL in case no plugins are loaded. -The _tep_add_plugin_path()_ function returns -1 in case of an error, 0 otherwise. +The *tep_add_plugin_path()* function returns -1 in case of an error, 0 otherwise. EXAMPLE ------- @@ -121,7 +128,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_, _tep_set_flag(3)_ +*libtraceevent*(3), *trace-cmd*(1), *tep_set_flag*(3) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-record_parse.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-record_parse.txt
Changed
@@ -30,19 +30,19 @@ ----------- This set of functions can be used to extract common fields from a record. -The _tep_data_type()_ function gets the event id from the record _rec_. +The *tep_data_type()* function gets the event id from the record _rec_. It reads the "common_type" field. The _tep_ argument is the trace event parser context. -The _tep_data_pid()_ function gets the process id from the record _rec_. +The *tep_data_pid()* function gets the process id from the record _rec_. It reads the "common_pid" field. The _tep_ argument is the trace event parser context. -The _tep_data_preempt_count()_ function gets the preemption count from the +The *tep_data_preempt_count()* function gets the preemption count from the record _rec_. It reads the "common_preempt_count" field. The _tep_ argument is the trace event parser context. -The _tep_data_flags()_ function gets the latency flags from the record _rec_. +The *tep_data_flags()* function gets the latency flags from the record _rec_. It reads the "common_flags" field. The _tep_ argument is the trace event parser context. Supported latency flags are: verse @@ -56,14 +56,14 @@ RETURN VALUE ------------ -The _tep_data_type()_ function returns an integer, representing the event id. +The *tep_data_type()* function returns an integer, representing the event id. -The _tep_data_pid()_ function returns an integer, representing the process id +The *tep_data_pid()* function returns an integer, representing the process id -The _tep_data_preempt_count()_ function returns an integer, representing the +The *tep_data_preempt_count()* function returns an integer, representing the preemption count. -The _tep_data_flags()_ function returns an integer, representing the latency +The *tep_data_flags()* function returns an integer, representing the latency flags. Look at the _trace_flag_type_ enum for supported flags. All these functions in case of an error return a negative integer. @@ -115,7 +115,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-reg_event_handler.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-reg_event_handler.txt
Changed
@@ -25,7 +25,7 @@ DESCRIPTION ----------- -The _tep_register_event_handler()_ function registers a handler function, +The *tep_register_event_handler()* function registers a handler function, which is going to be called to parse the information for a given event. The _tep_ argument is the trace event parser context. The _id_ argument is the id of the event. The _sys_name_ argument is the name of the system, @@ -39,8 +39,8 @@ If for some reason the default print format is not sufficient, the developer can register a function for an event to be used to parse the data instead. -The _tep_unregister_event_handler()_ function unregisters the handler function, -previously registered with _tep_register_event_handler()_. The _tep_ argument +The *tep_unregister_event_handler()* function unregisters the handler function, +previously registered with *tep_register_event_handler()*. The _tep_ argument is the trace event parser context. The _id_, _sys_name_, _event_name_, _func_, and _context_ are the same arguments, as when the callback function _func_ was registered. @@ -53,13 +53,13 @@ RETURN VALUE ------------ -The _tep_register_event_handler()_ function returns _TEP_REGISTER_SUCCESS_ +The *tep_register_event_handler()* function returns _TEP_REGISTER_SUCCESS_ if the new handler is registered successfully or _TEP_REGISTER_SUCCESS_OVERWRITE_ if an existing handler is overwritten. If there is not enough memory to complete the registration, TEP_ERRNO__MEM_ALLOC_FAILED is returned. -The _tep_unregister_event_handler()_ function returns 0 if _func_ was removed +The *tep_unregister_event_handler()* function returns 0 if _func_ was removed successful or, -1 if the event was not found. The _tep_event_handler_func_ should return -1 in case of an error, @@ -134,7 +134,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-reg_print_func.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-reg_print_func.txt
Changed
@@ -33,7 +33,7 @@ This allows a plugin to dynamically create a way to process one of these functions. -The _tep_register_print_function()_ registers such helper function. The _tep_ +The *tep_register_print_function()* registers such helper function. The _tep_ argument is the trace event parser context. The _func_ argument is a pointer to the helper function. The _ret_type_ argument is the return type of the helper function, value from the _tep_func_arg_type_ enum. The _name_ is the name @@ -41,8 +41,8 @@ variable list of _tep_func_arg_type_ enums, the _func_ function arguments. This list must end with _TEP_FUNC_ARG_VOID_. See 'EXAMPLE' section. -The _tep_unregister_print_function()_ unregisters a helper function, previously -registered with _tep_register_print_function()_. The _tep_ argument is the +The *tep_unregister_print_function()* unregisters a helper function, previously +registered with *tep_register_print_function()*. The _tep_ argument is the trace event parser context. The _func_ and _name_ arguments are the same, used when the helper function was registered. @@ -53,10 +53,10 @@ RETURN VALUE ------------ -The _tep_register_print_function()_ function returns 0 in case of success. +The *tep_register_print_function()* function returns 0 in case of success. In case of an error, TEP_ERRNO_... code is returned. -The _tep_unregister_print_function()_ returns 0 in case of success, or -1 in +The *tep_unregister_print_function()* returns 0 in case of success, or -1 in case of an error. EXAMPLE @@ -71,7 +71,7 @@ REC->sr_cursor, REC->sr_fbc, yesno(REC->hpll), REC->hpll_plane, REC->hpll_cursor, REC->hpll_fbc, yesno(REC->fbc) -- -Notice the call to function _yesno()_ in the print arguments. In the kernel +Notice the call to function *yesno()* in the print arguments. In the kernel context, this function has the following implementation: source,c -- @@ -83,9 +83,9 @@ return x ? yes : no; } -- -The user space event parser has no idea how to handle this _yesno()_ function. -The _tep_register_print_function()_ API can be used to register a user space -helper function, mapped to the kernel's _yesno()_: +The user space event parser has no idea how to handle this *yesno()* function. +The *tep_register_print_function()* API can be used to register a user space +helper function, mapped to the kernel's *yesno()*: source,c -- #include <event-parse.h> @@ -133,7 +133,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-set_flag.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-set_flag.txt
Changed
@@ -37,17 +37,17 @@ - in directory, defined by the environment variable _TRACEEVENT_PLUGIN_DIR_ - in user's home directory, _~/.traceevent/plugins_ -- -Note: plugin related flags must me set before calling _tep_load_plugins()_ API. +Note: plugin related flags must me set before calling *tep_load_plugins()* API. -The _tep_set_flag()_ function sets _flag_ to _tep_ context. +The *tep_set_flag()* function sets _flag_ to _tep_ context. -The _tep_clear_flag()_ function clears _flag_ from _tep_ context. +The *tep_clear_flag()* function clears _flag_ from _tep_ context. -The _tep_test_flag()_ function tests if _flag_ is set to _tep_ context. +The *tep_test_flag()* function tests if _flag_ is set to _tep_ context. RETURN VALUE ------------ -_tep_test_flag()_ function returns true if _flag_ is set, false otherwise. +*tep_test_flag()* function returns true if _flag_ is set, false otherwise. EXAMPLE ------- @@ -82,7 +82,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-strerror.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-strerror.txt
Changed
@@ -16,7 +16,7 @@ -- DESCRIPTION ----------- -The _tep_strerror()_ function converts tep error number into a human +The *tep_strerror()* function converts tep error number into a human readable string. The _tep_ argument is trace event parser context. The _errnum_ is a regular errno, defined in errno.h, or a tep error number. The string, describing this @@ -24,13 +24,13 @@ the size of the _buf_. It as a thread safe wrapper around strerror_r(). The library function has two -different behaviors - POSIX and GNU specific. The _tep_strerror()_ API always +different behaviors - POSIX and GNU specific. The *tep_strerror()* API always behaves as the POSIX version - the error string is copied in the user supplied buffer. RETURN VALUE ------------ -The _tep_strerror()_ function returns 0, if a valid _errnum_ is passed and the +The *tep_strerror()* function returns 0, if a valid _errnum_ is passed and the string is copied into _buf_. If _errnum_ is not a valid error number, -1 is returned and _buf_ is not modified. @@ -63,7 +63,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent-tseq.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent-tseq.txt
Changed
@@ -32,45 +32,45 @@ Trace sequences are used to allow a function to call several other functions to create a string of data to use. -The _trace_seq_init()_ function initializes the trace sequence _s_. +The *trace_seq_init()* function initializes the trace sequence _s_. -The _trace_seq_destroy()_ function destroys the trace sequence _s_ and frees +The *trace_seq_destroy()* function destroys the trace sequence _s_ and frees all its resources that it had used. -The _trace_seq_reset()_ function re-initializes the trace sequence _s_. All +The *trace_seq_reset()* function re-initializes the trace sequence _s_. All characters already written in _s_ will be deleted. -The _trace_seq_terminate()_ function terminates the trace sequence _s_. It puts +The *trace_seq_terminate()* function terminates the trace sequence _s_. It puts the null character pass:'\0' at the end of the buffer. -The _trace_seq_putc()_ function puts a single character _c_ in the trace +The *trace_seq_putc()* function puts a single character _c_ in the trace sequence _s_. -The _trace_seq_puts()_ function puts a NULL terminated string _str_ in the +The *trace_seq_puts()* function puts a NULL terminated string _str_ in the trace sequence _s_. -The _trace_seq_printf()_ function puts a formated string _fmt _with +The *trace_seq_printf()* function puts a formated string _fmt _with variable arguments _..._ in the trace sequence _s_. -The _trace_seq_vprintf()_ function puts a formated string _fmt _with +The *trace_seq_vprintf()* function puts a formated string _fmt _with list of arguments _args_ in the trace sequence _s_. -The _trace_seq_do_printf()_ function prints the buffer of trace sequence _s_ to +The *trace_seq_do_printf()* function prints the buffer of trace sequence _s_ to the standard output stdout. -The _trace_seq_do_fprintf()_ function prints the buffer of trace sequence _s_ +The *trace_seq_do_fprintf()* function prints the buffer of trace sequence _s_ to the given file _fp_. RETURN VALUE ------------ -Both _trace_seq_putc()_ and _trace_seq_puts()_ functions return the number of +Both *trace_seq_putc()* and *trace_seq_puts()* functions return the number of characters put in the trace sequence, or 0 in case of an error -Both _trace_seq_printf()_ and _trace_seq_vprintf()_ functions return 0 if the +Both *trace_seq_printf()* and *trace_seq_vprintf()* functions return 0 if the trace oversizes the buffer's free space, the number of characters printed, or a negative value in case of an error. -Both _trace_seq_do_printf()_ and _trace_seq_do_fprintf()_ functions return the +Both *trace_seq_do_printf()* and *trace_seq_do_fprintf()* functions return the number of printed characters, or -1 in case of an error. EXAMPLE @@ -136,7 +136,7 @@ SEE ALSO -------- -_libtraceevent(3)_, _trace-cmd(1)_ +*libtraceevent*(3), *trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Documentation/libtraceevent.txt -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/libtraceevent.txt
Changed
@@ -26,10 +26,14 @@ void *tep_set_long_size*(struct tep_handle pass:*_tep_, int _long_size_); int *tep_get_page_size*(struct tep_handle pass:*_tep_); void *tep_set_page_size*(struct tep_handle pass:*_tep_, int _page_size_); + int *tep_get_sub_buffer_size*(struct tep_handle pass:*_tep_); + int *tep_get_sub_buffer_data_size*(struct tep_handle pass:*_tep_); + int *tep_get_sub_buffer_commit_offset*(struct tep_handle pass:*_tep_); int *tep_get_header_page_size*(struct tep_handle pass:*_tep_); int *tep_get_header_timestamp_size*(struct tep_handle pass:*_tep_); bool *tep_is_old_format*(struct tep_handle pass:*_tep_); int *tep_strerror*(struct tep_handle pass:*_tep_, enum tep_errno _errnum_, char pass:*_buf_, size_t _buflen_); + struct kbuffer pass:**tep_kbuffer*(struct tep_handle pass:*_tep_); Register / unregister APIs: int *tep_register_function*(struct tep_handle pass:*_tep_, char pass:*_name_, unsigned long long _addr_, char pass:*_mod_); @@ -38,6 +42,19 @@ int *tep_register_print_string*(struct tep_handle pass:*_tep_, const char pass:*_fmt_, unsigned long long _addr_); int *tep_register_print_function*(struct tep_handle pass:*_tep_, tep_func_handler _func_, enum tep_func_arg_type _ret_type_, char pass:*_name_, _..._); int *tep_unregister_print_function*(struct tep_handle pass:*_tep_, tep_func_handler _func_, char pass:*_name_); + int *tep_get_function_count*(struct tep_handle *_tep_); + +Trace printk parsing: + void *tep_print_printk*(struct tep_handle pass:*tep); + void *tep_print_funcs*(struct tep_handle pass:*tep); + void *tep_set_test_filters*(struct tep_handle pass:*tep, int test_filters); + void *tep_plugin_print_options*(struct trace_seq pass:*s); + int *tep_plugin_add_option*(const char pass:*_name_, const char pass:*_val_); + +Meta data parsing: + int *tep_parse_saved_cmdlines*(struct tep_handle pass:*_tep_, const char pass:*_buf_); + int *tep_parse_printk_formats*(struct tep_handle pass:*_tep_, const char pass:*_buf_); + int *tep_parse_kallsyms*(struct tep_handle pass:*_tep_, const char pass:*_buf_); Plugins management: struct tep_plugin_list pass:**tep_load_plugins*(struct tep_handle pass:*_tep_); @@ -47,6 +64,14 @@ int *tep_plugin_add_options*(const char pass:*_name_, struct tep_plugin_option pass:*_options_); void *tep_plugin_remove_options*(struct tep_plugin_option pass:*_options_); void *tep_print_plugins*(struct trace_seq pass:*_s_, const char pass:*_prefix_, const char pass:*_suffix_, const struct tep_plugin_list pass:*_list_); + void *tep_load_plugins_hook*(struct tep_handle pass:*_tep_, const char pass:*_suffix_, + void (pass:*_load_plugin_)(struct tep_handle pass:*tep, + const char pass:*path, + const char pass:*name, + void pass:*data), + void pass:*_data_); + int *tep_add_plugin_path*(struct tep_handle pass:*tep, char pass:*path, + enum tep_plugin_load_priority prio); Event related APIs: struct tep_event pass:**tep_get_event*(struct tep_handle pass:*_tep_, int _index_); @@ -60,6 +85,7 @@ struct tep_event pass:**tep_find_event*(struct tep_handle pass:*_tep_, int _id_); struct tep_event pass:**tep_find_event_by_name*(struct tep_handle pass:*_tep_, const char pass:*_sys_, const char pass:*_name_); struct tep_event pass:**tep_find_event_by_record*(struct tep_handle pass:*_tep_, struct tep_record pass:*_record_); + bool *tep_record_is_event*(struct tep_record pass:*record, struct tep_event pass:*event); Parsing of event files: int *tep_parse_header_page*(struct tep_handle pass:*_tep_, char pass:*_buf_, unsigned long _size_, int _long_size_); @@ -76,10 +102,12 @@ int *tep_read_number_field*(struct tep_format_field pass:*_field_, const void pass:*_data_, unsigned long long pass:*_value_); Event fields printing: - void *tep_print_field*(struct trace_seq pass:*_s_, void pass:*_data_, struct tep_format_field pass:*_field_); + void *tep_print_field_content*(struct trace_seq pass:*_s_, void pass:*_data_, int size, struct tep_format_field pass:*_field_); void *tep_print_fields*(struct trace_seq pass:*_s_, void pass:*_data_, int _size_, struct tep_event pass:*_event_); int *tep_print_num_field*(struct trace_seq pass:*_s_, const char pass:*_fmt_, struct tep_event pass:*_event_, const char pass:*_name_, struct tep_record pass:*_record_, int _err_); int *tep_print_func_field*(struct trace_seq pass:*_s_, const char pass:*_fmt_, struct tep_event pass:*_event_, const char pass:*_name_, struct tep_record pass:*_record_, int _err_); + void *tep_record_print_fields*(struct trace_seq pass:*_s_, struct tep_record pass:*_record_, struct tep_event pass:*_event_); + void *tep_record_print_selected_fields*(struct trace_seq pass:*_s_, struct tep_record pass:*_record_, struct tep_event pass:*_event_, int _select_mask_); Event fields finding: struct tep_format_field pass:**tep_find_common_field*(struct tep_event pass:*_event_, const char pass:*_name_); @@ -91,6 +119,8 @@ void *tep_reset_function_resolver*(struct tep_handle pass:*_tep_); const char pass:**tep_find_function*(struct tep_handle pass:*_tep_, unsigned long long _addr_); unsigned long long *tep_find_function_address*(struct tep_handle pass:*_tep_, unsigned long long _addr_); + int *tep_find_function_info*(struct tep_handle pass:*_tep_, unsigned long long _addr_, const char pass:**_name_, + unsigned long long pass:*_start_, unsigned long pass:*_size_); Filter management: struct tep_event_filter pass:**tep_filter_alloc*(struct tep_handle pass:*_tep_); @@ -127,6 +157,15 @@ bool *tep_is_local_bigendian*(struct tep_handle pass:*_tep_); void *tep_set_local_bigendian*(struct tep_handle pass:*_tep_, enum tep_endian _endian_); +Control library logs: + int *tep_set_loglevel*(enum tep_loglevel _level_); + +KVM plugin calllbacks: (Defined by the application and complied with -rdynamic) + const char pass:**tep_plugin_kvm_get_func*(struct tep_event pass:*event, + struct tep_record pass:*record, + unsigned long long pass:*paddr); + void *tep_plugin_kvm_put_func*(const char pass:*func); + Trace sequences: *#include <trace-seq.h>* void *trace_seq_init*(struct trace_seq pass:*_s_); @@ -139,6 +178,28 @@ void *trace_seq_terminate*(struct trace_seq pass:*_s_); int *trace_seq_do_fprintf*(struct trace_seq pass:*_s_, FILE pass:*_fp_); int *trace_seq_do_printf*(struct trace_seq pass:*_s_); + +kbuffer parsing: +#include <kbuffer.h> + struct kbuffer pass:**kbuffer_alloc*(enum kbuffer_long_size _size_, enum kbuffer_endian _endian_); + struct kbuffer pass:**kbuffer_dup*(struct kbuffer pass:*_kbuf_); + void *kbuffer_free*(struct kbuffer pass:*_kbuf_); + int *kbuffer_load_subbuffer*(struct kbuffer pass:*_kbuf_, void pass:*_subbuffer_); + int *kbuffer_subbuffer_size*(struct kbuffer pass:*_kbuf); + void pass:**kbuffer_subbuffer*(struct kbuffer pass:*_kbuf); + int *kbuffer_refresh*(struct kbuffer pass:*_kbuf_); + int *kbuffer_start_of_data*(struct kbuffer pass:*_kbuf_); + unsigned long long *kbuffer_timestamp*(struct kbuffer pass:*_kbuf_); + unsigned long long *kbuffer_subbuf_timestamp*(struct kbuffer pass:*_kbuf_, void pass:*_subbuf_); + void pass:**kbuffer_read_event*(struct kbuffer pass:*_kbuf_, unsigned long long pass:*_ts_); + void pass:**kbuffer_next_event*(struct kbuffer pass:*_kbuf_, unsigned long long pass:*_ts_); + void pass:**kbuffer_read_at_offset*(struct kbuffer pass:*_kbuf_, int _offset_, unsigned long long pass:*_ts_); + int *kbuffer_missed_events*(struct kbuffer pass:*_kbuf_); + int *kbuffer_event_size*(struct kbuffer pass:*_kbuf_); + int *kbuffer_curr_size*(struct kbuffer pass:*_kbuf_); + int *kbuffer_curr_offset*(struct kbuffer pass:*_kbuf_); + int *kbuffer_curr_index*(struct kbuffer pass:*_kbuf_); + int *kbuffer_read_buffer*(struct kbuffer pass:*_kbuf_, void pass:*_buffer_, int _start_, int _len_); -- DESCRIPTION @@ -170,7 +231,7 @@ SEE ALSO -------- -_trace-cmd(1)_ +*trace-cmd*(1) AUTHOR ------
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/Documentation/meson.build
Added
@@ -0,0 +1,196 @@ +# SPDX-License-Identifier: LGPL-2.1 +# +# Copyright (c) 2023 Daniel Wagner, SUSE LLC + +# input text file: man page section +sources = { + 'libtraceevent.txt': '3', + 'libtraceevent-func_apis.txt': '3', + 'libtraceevent-commands.txt': '3', + 'libtraceevent-cpus.txt': '3', + 'libtraceevent-debug.txt': '3', + 'libtraceevent-endian_read.txt': '3', + 'libtraceevent-event_find.txt': '3', + 'libtraceevent-event_get.txt': '3', + 'libtraceevent-event_list.txt': '3', + 'libtraceevent-event_print.txt': '3', + 'libtraceevent-field_find.txt': '3', + 'libtraceevent-field_get_val.txt': '3', + 'libtraceevent-field_print.txt': '3', + 'libtraceevent-field_read.txt': '3', + 'libtraceevent-fields.txt': '3', + 'libtraceevent-file_endian.txt': '3', + 'libtraceevent-filter.txt': '3', + 'libtraceevent-func_find.txt': '3', + 'libtraceevent-handle.txt': '3', + 'libtraceevent-header_page.txt': '3', + 'libtraceevent-host_endian.txt': '3', + 'libtraceevent-kbuffer-create.txt': '3', + 'libtraceevent-kbuffer-read.txt': '3', + 'libtraceevent-kbuffer-timestamp.txt': '3', + 'libtraceevent-kvm-plugin.txt': '3', + 'libtraceevent-log.txt': '3', + 'libtraceevent-long_size.txt': '3', + 'libtraceevent-page_size.txt': '3', + 'libtraceevent-parse_event.txt': '3', + 'libtraceevent-parse-files.txt': '3', + 'libtraceevent-parse_head.txt': '3', + 'libtraceevent-plugins.txt': '3', + 'libtraceevent-record_parse.txt': '3', + 'libtraceevent-reg_event_handler.txt': '3', + 'libtraceevent-reg_print_func.txt': '3', + 'libtraceevent-set_flag.txt': '3', + 'libtraceevent-strerror.txt': '3', + 'libtraceevent-tseq.txt': '3', +} + +conf_dir = meson.current_source_dir() + '/' +top_source_dir = meson.current_source_dir() + '/../' + +# +# For asciidoc ... +# -7.1.2, no extra settings are needed. +# 8.0-, set ASCIIDOC8. +# + +# +# For docbook-xsl ... +# -1.68.1, set ASCIIDOC_NO_ROFF? (based on changelog from 1.73.0) +# 1.69.0, no extra settings are needed? +# 1.69.1-1.71.0, set DOCBOOK_SUPPRESS_SP? +# 1.71.1, no extra settings are needed? +# 1.72.0, set DOCBOOK_XSL_172. +# 1.73.0-, set ASCIIDOC_NO_ROFF +# + +# +# If you had been using DOCBOOK_XSL_172 in an attempt to get rid +# of 'the ".ft C" problem' in your generated manpages, and you +# instead ended up with weird characters around callouts, try +# using ASCIIDOC_NO_ROFF instead (it works fine with ASCIIDOC8). +# + +if get_option('asciidoctor') + asciidoc = find_program('asciidoctor') + asciidoc_extra = '-a', 'compat-mode' + asciidoc_extra += '-I.' + asciidoc_extra += '-r', 'asciidoctor-extensions' + asciidoc_extra += '-a', 'mansource=libtraceevent' + asciidoc_extra += '-a', 'manmanual="libtraceevent Manual"' + asciidoc_html = 'xhtml5' +else + asciidoc = find_program('asciidoc') + asciidoc_extra = '--unsafe' + asciidoc_extra += '-f', conf_dir + 'asciidoc.conf' + asciidoc_html = 'xhtml11' + + r = run_command(asciidoc, '--version', check: true) + v = r.stdout().strip() + if v.version_compare('>=8.0') + asciidoc_extra += '-a', 'asciidoc7compatible' + endif +endif + +manpage_xsl = conf_dir + 'manpage-normal.xsl' + +if get_option('docbook-xls-172') + asciidoc_extra += '-a', 'libtraceevent-asciidoc-no-roff' + manpage_xsl = conf_dir + 'manpage-1.72.xsl' +elif get_option('asciidoc-no-roff') + # docbook-xsl after 1.72 needs the regular XSL, but will not + # pass-thru raw roff codes from asciidoc.conf, so turn them off. + asciidoc_extra += '-a', 'libtraceevent-asciidoc-no-roff' +endif + +xmlto = find_program('xmlto') +xmlto_extra = + +if get_option('man-bold-literal') + xmlto_extra += '-m ', conf_dir + 'manpage-bold-literal.xsl' +endif + +if get_option('docbook-suppress-sp') + xmlto_extra += '-m ', conf_dir + 'manpage-suppress-sp.xsl' +endif + +check_doc = custom_target( + 'check-doc', + output: 'dummy', + command : + top_source_dir + 'check-manpages.sh', + meson.current_source_dir()) + +gen = generator( + asciidoc, + output: '@BASENAME@.xml', + arguments: + '-b', 'docbook', + '-d', 'manpage', + '-a', 'libtraceevent_version=' + meson.project_version(), + '-o', '@OUTPUT@' + + asciidoc_extra + + '@INPUT@') + +man = +html = +foreach txt, section : sources + # build man page(s) + xml = gen.process(txt) + man += custom_target( + txt.underscorify() + '_man', + input: xml, + output: '@BASENAME@.' + section, + depends: check_doc, + command: + xmlto, + '-m', manpage_xsl, + 'man', + '-o', '@OUTPUT@' + + xmlto_extra + + '@INPUT@') + + # build html pages + html += custom_target( + txt.underscorify() + '_html', + input: txt, + output: '@BASENAME@.html', + depends: check_doc, + command: + asciidoc, + '-b', asciidoc_html, + '-d', 'manpage', + '-a', 'libtraceevent_version=' + meson.project_version(), + '-o', '@OUTPUT@' + + asciidoc_extra + + '@INPUT@') +endforeach + +# Install path workaround because: +# +# - xmlto might generate more than one file and we would to tell meson +# about those output files. We could figure out which files are generated +# (see sed match in check-manpages.sh). +# +# - The man page generation puts all the generated files under sub dirs +# and it's not obvious how to tell Meson it should not do this without +# causing the install step to fail (confusion where the generated files +# are stored) +# +# - The documentation build is not part of the 'build' target. The user +# has explicitly to trigger the doc build. Hence the documentation is +# not added to the 'install' target. +# +# Thus just use a plain old shell script to move the generated files to the +# right location. + +conf = configuration_data() +conf.set('SRCDIR', meson.current_build_dir()) +conf.set('MANDIR', mandir) +conf.set('HTMLDIR', htmldir) +configure_file( + input: 'install-docs.sh.in', + output: 'install-docs.sh', + configuration: conf) + +meson.add_install_script( + join_paths(meson.current_build_dir(), 'install-docs.sh'))
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/Makefile -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/Makefile
Changed
@@ -1,8 +1,9 @@ # SPDX-License-Identifier: GPL-2.0 # libtraceevent version EP_VERSION = 1 -EP_PATCHLEVEL = 2 -EP_EXTRAVERSION = 1 +EP_PATCHLEVEL = 8 +EP_EXTRAVERSION = 2 +EVENT_PARSE_VERSION = $(EP_VERSION).$(EP_PATCHLEVEL).$(EP_EXTRAVERSION) MAKEFLAGS += --no-print-directory @@ -45,8 +46,8 @@ libdir_relative ?= $(libdir_relative_temp) prefix ?= /usr/local -libdir = $(prefix)/$(libdir_relative) -man_dir = $(prefix)/share/man +libdir ?= $(prefix)/$(libdir_relative) +man_dir ?= $(prefix)/share/man man_dir_SQ = '$(subst ','\'',$(man_dir))' pkgconfig_dir ?= $(word 1,$(shell $(PKG_CONFIG) \ --variable pc_path pkg-config | tr ":" " ")) @@ -56,12 +57,7 @@ export man_dir man_dir_SQ INSTALL export DESTDIR DESTDIR_SQ -export EVENT_PARSE_VERSION - -include scripts/Makefile.include - -PKG_CONFIG_SOURCE_FILE = libtraceevent.pc -PKG_CONFIG_FILE := $(addprefix $(OUTPUT),$(PKG_CONFIG_SOURCE_FILE)) +export EP_VERSION EVENT_PARSE_VERSION # copy a bit from Linux kbuild @@ -72,12 +68,36 @@ VERBOSE = 0 endif -ifeq ($(srctree),) -srctree := $(CURDIR) -#$(info Determined 'srctree' to be $(srctree)) +SILENT := $(if $(findstring s,$(filter-out --%,$(MAKEFLAGS))),1) + +ifeq ("$(origin O)", "command line") + + saved-output := $(O) + BUILD_OUTPUT := $(shell cd $(O) && /bin/pwd) + $(if $(BUILD_OUTPUT),, \ + $(error output directory "$(saved-output)" does not exist)) + +else + BUILD_OUTPUT = $(CURDIR) endif -export prefix libdir +srctree := $(if $(BUILD_SRC),$(BUILD_SRC),$(CURDIR)) +objtree := $(BUILD_OUTPUT) +src := $(srctree) +obj := $(objtree) +bdir := $(obj)/lib + +export prefix src obj bdir + +PKG_CONFIG_SOURCE_FILE = libtraceevent.pc +PKG_CONFIG_FILE := $(addprefix $(obj)/,$(PKG_CONFIG_SOURCE_FILE)) + +export Q SILENT VERBOSE EXT + +# Include the utils +include scripts/utils.mk + +include $(src)/scripts/features.mk # Shell quotes libdir_SQ = $(subst ','\'',$(libdir)) @@ -94,20 +114,14 @@ OBJ = $@ N = -EVENT_PARSE_VERSION = $(EP_VERSION).$(EP_PATCHLEVEL).$(EP_EXTRAVERSION) - -bdir = lib - -export bdir - LIBTRACEEVENT_STATIC = $(bdir)/libtraceevent.a LIBTRACEEVENT_SHARED = $(bdir)/libtraceevent.so.$(EVENT_PARSE_VERSION) -LIB_TARGET = $(LIBTRACEEVENT_STATIC) $(bdir)/libtraceevent.so $(bdir)/libtraceevent.so.$(EP_VERSION) $(LIBTRACEEVENT_SHARED) -LIB_INSTALL = $(LIBTRACEEVENT_STATIC) $(bdir)/libtraceevent.so* -LIB_INSTALL := $(addprefix $(OUTPUT),$(LIB_INSTALL)) +EP_HEADERS_DIR = $(src)/include/traceevent -INCLUDES = -I. -I $(srctree)/include $(CONFIG_INCLUDES) +INCLUDES = -I. -I $(srctree)/include -I $(EP_HEADERS_DIR) $(CONFIG_INCLUDES) + +export LIBTRACEEVENT_STATIC LIBTRACEEVENT_SHARED EP_HEADERS_DIR # Set compile option CFLAGS ifdef EXTRA_CFLAGS @@ -116,11 +130,12 @@ CFLAGS := -g -Wall endif -LIBS = -ldl +LIBS ?= -ldl +export LIBS set_plugin_dir := 1 -# Set plugin_dir to preffered global plugin location +# Set plugin_dir to prefered global plugin location # If we install under $HOME directory we go under # $(HOME)/.local/lib/traceevent/plugins # @@ -149,6 +164,9 @@ override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ) override CFLAGS += $(udis86-flags) -D_GNU_SOURCE +# Make sure 32 bit stat() works on large file systems +override CFLAGS += -D_FILE_OFFSET_BITS=64 + ifeq ($(VERBOSE),1) Q = else @@ -160,11 +178,10 @@ # the same command line setup. MAKEOVERRIDES= -export srctree OUTPUT CC LD CFLAGS V +export srctree CC LD CFLAGS V build := -f $(srctree)/build/Makefile.build dir=. obj -TE_IN := $(OUTPUT)src/libtraceevent-in.o -LIB_TARGET := $(addprefix $(OUTPUT),$(LIB_TARGET)) +LIB_TARGET := libtraceevent.so libtraceevent.a CMD_TARGETS = $(LIB_TARGET) $(PKG_CONFIG_FILE) @@ -172,27 +189,33 @@ all: all_cmd plugins -all_cmd: $(CMD_TARGETS) +$(bdir): + $(Q)mkdir -p $(bdir) -$(TE_IN): force - $(Q)$(call descend,src,libtraceevent) +LIB_TARGET = libtraceevent.a libtraceevent.so +LIB_INSTALL = libtraceevent.a libtraceevent.so* +LIB_INSTALL := $(addprefix $(bdir)/,$(LIB_INSTALL)) -$(OUTPUT)$(LIBTRACEEVENT_SHARED): $(TE_IN) - $(Q)mkdir -p $(OUTPUT)$(bdir) - $(QUIET_LINK)$(CC) --shared $(LDFLAGS) $^ -Wl,-soname,libtraceevent.so.$(EP_VERSION) -o $@ $(LIBS) +LIBTRACEEVENT_SHARED_SO = $(bdir)/libtraceevent.so +LIBTRACEEVENT_SHARED_VERSION = $(bdir)/libtraceevent.so.$(EP_VERSION) -$(OUTPUT)$(bdir)/libtraceevent.so: $(OUTPUT)$(bdir)/libtraceevent.so.$(EP_VERSION) - @ln -sf $(<F) $@ +export LIBTRACEEVENT_SHARED_SO LIBTRACEEVENT_SHARED_VERSION -$(OUTPUT)$(bdir)/libtraceevent.so.$(EP_VERSION): $(OUTPUT)$(LIBTRACEEVENT_SHARED) - @ln -sf $(<F) $@ +all_cmd: $(CMD_TARGETS) + +libtraceevent.a: $(bdir) $(LIBTRACEEVENT_STATIC) +libtraceevent.so: $(bdir) $(LIBTRACEEVENT_SHARED) + +libs: libtraceevent.a libtraceevent.so -$(OUTPUT)$(LIBTRACEEVENT_STATIC): $(TE_IN) - $(Q)mkdir -p $(OUTPUT)$(bdir) - $(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^ +$(LIBTRACEEVENT_STATIC): force + $(Q)$(call descend,$(src)/src,$@) -$(OUTPUT)$(bdir)/%.so: $(OUTPUT)%-in.o - $(QUIET_LINK)$(CC) $(CFLAGS) -shared $(LDFLAGS) -nostartfiles -o $@ $^ $(LIBS) +$(LIBTRACEEVENT_SHARED): force + $(Q)$(call descend,$(src)/src,libtraceevent.so) + +$(bdir)/libtraceevent.so: $(bdir)/libtraceevent.so.$(EP_VERSION) + @ln -sf $(<F) $@ define make_version.h (echo '/* This file is automatically generated. Do not modify. */'; \ @@ -214,10 +237,10 @@ fi); endef -ep_version.h: force - $(Q)$(N)$(call update_version.h) +VERSION_FILE = $(obj)/ep_version.h -VERSION_FILES = ep_version.h +$(VERSION_FILE): force + $(Q)$(N)$(call update_version.h) define update_dir (echo $1 > $@.tmp; \ @@ -229,15 +252,27 @@ fi); endef -tags: force - $(RM) tags - find . -name '*.ch' | xargs ctags --extra=+f --c-kinds=+px \ - --regex-c++='/_PE\((^,)*).*/TEP_ERRNO__\1/' +UTEST_DIR = utest + +test: force $(LIBTRACEEVENT_STATIC) + $(Q)$(call descend,$(UTEST_DIR),test) + +VIM_TAGS = $(obj)/tags +EMACS_TAGS = $(obj)/TAGS + +$(VIM_TAGS): force + $(RM) $(VIM_TAGS) + find $(src) -name '*.ch' | (cd $(obj) && xargs ctags --extra=+f --c-kinds=+px \ + --regex-c++='/_PE\((^,)*).*/TEP_ERRNO__\1/') + +tags: $(VIM_TAGS) + +$(EMACS_TAGS): force + $(RM) $(EMACS_TAGS) + find $(src) -name '*.ch' | (cd $(obj) && xargs etags \ + --regex='/_PE(\(^,)*\).*/TEP_ERRNO__\1/') -TAGS: force - $(RM) TAGS - find . -name '*.ch' | xargs etags \ - --regex='/_PE(\(^,)*\).*/TEP_ERRNO__\1/' +TAGS: $(EMACS_TAGS) define build_prefix (echo $1 > $@.tmp; \ @@ -249,22 +284,11 @@ fi); endef -BUILD_PREFIX := $(OUTPUT)build_prefix +BUILD_PREFIX := $(obj)/build_prefix $(BUILD_PREFIX): force $(Q)$(call build_prefix,$(prefix)) -define do_install_mkdir - if ! -d '$(DESTDIR_SQ)$1' ; then \ - $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$1'; \ - fi -endef - -define do_install - $(call do_install_mkdir,$2); \ - $(INSTALL) $(if $3,-m $3,) $1 '$(DESTDIR_SQ)$2' -endef - define do_make_pkgconfig_file cp -f ${PKG_CONFIG_SOURCE_FILE}.template ${PKG_CONFIG_FILE}; \ sed -i "s|INSTALL_PREFIX|${1}|g" ${PKG_CONFIG_FILE}; \ @@ -273,8 +297,8 @@ sed -i "s|HEADER_DIR|$(includedir_relative)|g" ${PKG_CONFIG_FILE}; endef -$(PKG_CONFIG_FILE) : ${PKG_CONFIG_SOURCE_FILE}.template $(BUILD_PREFIX) $(VERSION_FILES) - $(QUIET_GEN) $(call do_make_pkgconfig_file,$(prefix)) +$(PKG_CONFIG_FILE) : ${PKG_CONFIG_SOURCE_FILE}.template $(BUILD_PREFIX) $(VERSION_FILE) + $(Q)$(print_gen)$(call do_make_pkgconfig_file,$(prefix)) define do_install_pkgconfig_file if -n "${pkgconfig_dir}" ; then \ @@ -292,14 +316,14 @@ define install_ld_config if $(LDCONFIG); then \ if ! grep -q "^$(libdir)$$" $(LD_SO_CONF_PATH)/* ; then \ - $(CC) -o $(OUTPUT)test $(srctree)/test.c -I $(includedir_SQ) \ - -L $(libdir_SQ) -ltraceevent &>/dev/null; \ - if ! $(OUTPUT)test &> /dev/null; then \ - $(call PRINT_INSTALL, trace.conf) \ + $(CC) -o $(objtree)/test $(srctree)/test.c -I $(includedir_SQ) \ + -L $(libdir_SQ) -ltraceevent &> /dev/null; \ + if ! $(objtree)/test &> /dev/null; then \ + $(call print_install, trace.conf, $(LD_SO_CONF_PATH)) \ echo $(libdir_SQ) >> $(LD_SO_CONF_PATH)/trace.conf; \ $(LDCONFIG); \ fi; \ - $(RM) $(OUTPUT)test; \ + $(RM) $(objtree)/test; \ fi; \ fi endef @@ -310,34 +334,30 @@ endef endif # DESTDIR = "" -install_lib: all_cmd install_plugins install_headers install_pkgconfig - $(call QUIET_INSTALL, $(LIB_TARGET)) \ - $(call do_install_mkdir,$(libdir_SQ)); \ - cp -fpR $(LIB_INSTALL) $(DESTDIR)$(libdir_SQ); \ - $(call install_ld_config) +install: install_libs install_plugins + +install_libs: libs install_headers install_pkgconfig + $(Q)$(call do_install,$(LIBTRACEEVENT_SHARED),$(libdir_SQ)); \ + cp -fpR $(LIB_INSTALL) $(DESTDIR)$(libdir_SQ) + $(Q)$(call install_ld_config) install_pkgconfig: $(PKG_CONFIG_FILE) - $(call QUIET_INSTALL, $(PKG_CONFIG_FILE)) \ - $(call do_install_pkgconfig_file,$(prefix)) + $(Q)$(call do_install_pkgconfig_file,$(prefix)) install_headers: - $(call QUIET_INSTALL, headers) \ - $(call do_install,src/event-parse.h,$(includedir_SQ),644); \ - $(call do_install,src/event-utils.h,$(includedir_SQ),644); \ - $(call do_install,src/trace-seq.h,$(includedir_SQ),644); \ - $(call do_install,src/kbuffer.h,$(includedir_SQ),644) + $(Q)$(call do_install,$(EP_HEADERS_DIR)/event-parse.h,$(includedir_SQ),644); + $(Q)$(call do_install,$(EP_HEADERS_DIR)/event-utils.h,$(includedir_SQ),644); + $(Q)$(call do_install,$(EP_HEADERS_DIR)/trace-seq.h,$(includedir_SQ),644); + $(Q)$(call do_install,$(EP_HEADERS_DIR)/kbuffer.h,$(includedir_SQ),644) -install: install_lib +install: install_libs clean: clean_plugins clean_src - $(call QUIET_CLEAN, libtraceevent) \ - $(RM) $(OUTPUT)*.o $(OUTPUT)*~ $(TARGETS) $(OUTPUT)*.a $(OUTPUT)*.so $(VERSION_FILES) $(OUTPUT).*.d $(OUTPUT).*.cmd; \ - $(RM) TRACEEVENT-CFLAGS $(OUTPUT)tags $(OUTPUT)TAGS; \ - $(RM) $(PKG_CONFIG_FILE) -ifneq ($(OUTPUT),) -else -BUILD_OUTPUT := $(shell pwd) -endif + $(Q)$(call do_clean,\ + $(VERSION_FILE) $(obj)/tags $(obj)/TAGS $(PKG_CONFIG_FILE) \ + $(LIBTRACEEVENT_STATIC) $(LIBTRACEEVENT_SHARED) \ + $(LIBTRACEEVENT_SHARED_SO) $(LIBTRACEEVENT_SHARED_VERSION) \ + $(BUILD_PREFIX)) define build_uninstall_script $(Q)mkdir $(BUILD_OUTPUT)/tmp_build @@ -361,20 +381,24 @@ @$(foreach file,$(shell cat $(BUILD_OUTPUT)/build_uninstall),$(call uninstall_file,$(file))) PHONY += doc -doc: - $(call descend,Documentation) +doc: check_doc + $(Q)$(call descend,$(src)/Documentation,) PHONY += doc-clean doc-clean: - $(call descend,Documentation,clean) + $(MAKE) -C $(src)/Documentation clean PHONY += doc-install doc-install: - $(call descend,Documentation,install) + $(Q)$(call descend,$(src)/Documentation,install) + +check_doc: force + $(Q)$(src)/check-manpages.sh $(src)/Documentation + PHONY += doc-uninstall doc-uninstall: - $(call descend,Documentation,uninstall) + $(MAKE) -C $(src)/Documentation uninstall PHONY += help help: @@ -395,19 +419,22 @@ PHONY += plugins plugins: - $(call descend,plugins) + $(Q)$(call descend,plugins,) PHONY += install_plugins -install_plugins: - $(call descend,plugins,install) +install_plugins: plugins + $(Q)$(call descend,plugins,install) + +samples: libtraceevent.a force + $(Q)$(call descend,$(src)/samples,all) PHONY += clean_plugins clean_plugins: - $(call descend,plugins,clean) + $(Q)$(call descend_clean,plugins) PHONY += clean_src clean_src: - $(call descend,src,clean) + $(Q)$(call descend_clean,src) force:
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/check-manpages.sh
Added
@@ -0,0 +1,78 @@ +#!/bin/bash +# SPDX-License-Identifier: LGPL-2.1 +# Copyright (C) 2022, Google Inc, Steven Rostedt <rostedt@goodmis.org> +# +# This checks if any function is listed in a man page that is not listed +# in the main man page. + +if $# -lt 1 ; then + echo "usage: check-manpages man-page-path" + exit 1 +fi + +cd $1 + +MAIN=libtraceevent +MAIN_FILE=${MAIN}.txt + +PROCESSED="" + +# Ignore man pages that do not contain functions +IGNORE="" + +for man in ${MAIN}-*.txt; do + + for a in `sed -ne '/^NAME/,/^SYNOP/{/^a-z/{s/, *$//;s/,/\n/g;s/ //g;s/-.*$/-/;/-/{s/-//p;q};p}}' $man`; do + if "${PROCESSED/:${a} /}" != "${PROCESSED}" ; then + P="${PROCESSED/:${a} */}" + echo "Found ${a} in ${man} and in ${P/* /}" + fi + PROCESSED="${man}:${a} ${PROCESSED}" + if "${IGNORE/$man/}" != "${IGNORE}" ; then + continue + fi + if ! grep -q '\*'${a}'\*' $MAIN_FILE; then + if "$last" == "" ; then + echo + fi + if "$last" != "$man" ; then + echo "Missing functions from $MAIN_FILE that are in $man" + last=$man + fi + echo " ${a}" + fi + done +done + +DEPRECATED="*tep_print_field*" + +# Should not be used by applications, only internal use by trace-cmd +IGNORE="*kbuffer_set_old_format* *kbuffer_raw_get* *kbuffer_ptr_delta* *kbuffer_translate_data*" + +HEADER=event-parse.h + +sed -ne 's/^a-z.* \*\(a-z_a-z_*\)(.*/\1/p' -e 's/^\(a-z_a-z_*\)(.*/\1/p' ../include/traceevent/{event-parse,trace-seq,kbuffer}.h | while read f; do + if ! grep -q '\*'${f}'\*' $MAIN_FILE; then + if "${DEPRECATED/\*$f\*/}" != "${DEPRECATED}" ; then + continue; + fi + if "${IGNORE/\*$f\*/}" != "${IGNORE}" ; then + continue; + fi + for head in event-parse.h trace-seq.h kbuffer.h; do + if grep -q $f ../include/traceevent/$head; then + if "$HEADER" != "$head" ; then + last="" + HEADER=$head + break + fi + fi + done + if "$last" == "" ; then + echo + echo "Missing functions from $MAIN_FILE that are in $HEADER" + last=$f + fi + echo " ${f}" + fi +done
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/include/asm/bug.h -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/include/asm/bug.h
Changed
@@ -5,7 +5,7 @@ #include <linux/compiler.h> #include <stdio.h> -#define __WARN_printf(arg...) do { fprintf(stderr, arg); } while (0) +#define __WARN_printf(arg...) do { fprintf(stderr, arg); fprintf(stderr, "\n");} while (0) #define WARN(condition, format...) ({ \ int __ret_warn_on = !!(condition); \
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/include/traceevent
Added
+(directory)
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/include/traceevent/event-parse.h
Added
@@ -0,0 +1,827 @@ +/* SPDX-License-Identifier: LGPL-2.1 */ +/* + * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> + * + */ +#ifndef __TEP_PARSE_EVENTS_H +#define __TEP_PARSE_EVENTS_H + +#include <stdbool.h> +#include <stdarg.h> +#include <stdio.h> +#include <regex.h> +#include <string.h> + +#include "trace-seq.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __maybe_unused +#define __maybe_unused __attribute__((unused)) +#endif + +#ifndef DEBUG_RECORD +#define DEBUG_RECORD 0 +#endif + +struct tep_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 *priv; +#if DEBUG_RECORD + struct tep_record *prev; + struct tep_record *next; + long alloc_addr; +#endif +}; + +/* ----------------------- tep ----------------------- */ + +struct tep_handle; +struct tep_event; + +typedef int (*tep_event_handler_func)(struct trace_seq *s, + struct tep_record *record, + struct tep_event *event, + void *context); + +typedef int (*tep_plugin_load_func)(struct tep_handle *tep); +typedef int (*tep_plugin_unload_func)(struct tep_handle *tep); + +struct tep_plugin_option { + struct tep_plugin_option *next; + void *handle; + char *file; + char *name; + char *plugin_alias; + char *description; + const char *value; + void *priv; + int set; +}; + +/* + * Plugin hooks that can be called: + * + * TEP_PLUGIN_LOADER: (required) + * The function name to initialized the plugin. + * + * int TEP_PLUGIN_LOADER(struct tep_handle *tep) + * + * TEP_PLUGIN_UNLOADER: (optional) + * The function called just before unloading + * + * int TEP_PLUGIN_UNLOADER(struct tep_handle *tep) + * + * TEP_PLUGIN_OPTIONS: (optional) + * Plugin options that can be set before loading + * + * struct tep_plugin_option TEP_PLUGIN_OPTIONS = { + * { + * .name = "option-name", + * .plugin_alias = "override-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. + * + * If .value is not set, then it is considered a boolean and only + * .set will be processed. If .value is defined, then it is considered + * a string option and .set will be ignored. + * + * TEP_PLUGIN_ALIAS: (optional) + * The name to use for finding options (uses filename if not defined) + */ +#define TEP_PLUGIN_LOADER tep_plugin_loader +#define TEP_PLUGIN_UNLOADER tep_plugin_unloader +#define TEP_PLUGIN_OPTIONS tep_plugin_options +#define TEP_PLUGIN_ALIAS tep_plugin_alias +#define _MAKE_STR(x) #x +#define MAKE_STR(x) _MAKE_STR(x) +#define TEP_PLUGIN_LOADER_NAME MAKE_STR(TEP_PLUGIN_LOADER) +#define TEP_PLUGIN_UNLOADER_NAME MAKE_STR(TEP_PLUGIN_UNLOADER) +#define TEP_PLUGIN_OPTIONS_NAME MAKE_STR(TEP_PLUGIN_OPTIONS) +#define TEP_PLUGIN_ALIAS_NAME MAKE_STR(TEP_PLUGIN_ALIAS) + +enum tep_format_flags { + TEP_FIELD_IS_ARRAY = 1, + TEP_FIELD_IS_POINTER = 2, + TEP_FIELD_IS_SIGNED = 4, + TEP_FIELD_IS_STRING = 8, + TEP_FIELD_IS_DYNAMIC = 16, + TEP_FIELD_IS_LONG = 32, + TEP_FIELD_IS_FLAG = 64, + TEP_FIELD_IS_SYMBOLIC = 128, + TEP_FIELD_IS_RELATIVE = 256, +}; + +struct tep_format_field { + struct tep_format_field *next; + struct tep_event *event; + char *type; + char *name; + char *alias; + int offset; + int size; + unsigned int arraylen; + unsigned int elementsize; + unsigned long flags; +}; + +struct tep_format { + int nr_common; + int nr_fields; + struct tep_format_field *common_fields; + struct tep_format_field *fields; +}; + +struct tep_print_arg_atom { + char *atom; +}; + +struct tep_print_arg_string { + char *string; + int offset; // for backward compatibility + struct tep_format_field *field; +}; + +struct tep_print_arg_bitmask { + char *bitmask; + int offset; // for backward compatibility + struct tep_format_field *field; +}; + +struct tep_print_arg_field { + char *name; + struct tep_format_field *field; +}; + +struct tep_print_flag_sym { + struct tep_print_flag_sym *next; + char *value; + char *str; +}; + +struct tep_print_arg_typecast { + char *type; + struct tep_print_arg *item; +}; + +struct tep_print_arg_flags { + struct tep_print_arg *field; + char *delim; + struct tep_print_flag_sym *flags; +}; + +struct tep_print_arg_symbol { + struct tep_print_arg *field; + struct tep_print_flag_sym *symbols; +}; + +struct tep_print_arg_hex { + struct tep_print_arg *field; + struct tep_print_arg *size; +}; + +struct tep_print_arg_int_array { + struct tep_print_arg *field; + struct tep_print_arg *count; + struct tep_print_arg *el_size; +}; + +struct tep_print_arg_dynarray { + struct tep_format_field *field; + struct tep_print_arg *index; +}; + +struct tep_print_arg; + +struct tep_print_arg_op { + char *op; + int prio; + struct tep_print_arg *left; + struct tep_print_arg *right; +}; + +struct tep_function_handler; + +struct tep_print_arg_func { + struct tep_function_handler *func; + struct tep_print_arg *args; +}; + +enum tep_print_arg_type { + TEP_PRINT_NULL, + TEP_PRINT_ATOM, + TEP_PRINT_FIELD, + TEP_PRINT_FLAGS, + TEP_PRINT_SYMBOL, + TEP_PRINT_HEX, + TEP_PRINT_INT_ARRAY, + TEP_PRINT_TYPE, + TEP_PRINT_STRING, + TEP_PRINT_BSTRING, + TEP_PRINT_DYNAMIC_ARRAY, + TEP_PRINT_OP, + TEP_PRINT_FUNC, + TEP_PRINT_BITMASK, + TEP_PRINT_DYNAMIC_ARRAY_LEN, + TEP_PRINT_HEX_STR, + TEP_PRINT_CPUMASK, +}; + +struct tep_print_arg { + struct tep_print_arg *next; + enum tep_print_arg_type type; + union { + struct tep_print_arg_atom atom; + struct tep_print_arg_field field; + struct tep_print_arg_typecast typecast; + struct tep_print_arg_flags flags; + struct tep_print_arg_symbol symbol; + struct tep_print_arg_hex hex; + struct tep_print_arg_int_array int_array; + struct tep_print_arg_func func; + struct tep_print_arg_string string; + struct tep_print_arg_bitmask bitmask; + struct tep_print_arg_op op; + struct tep_print_arg_dynarray dynarray; + }; +}; + +struct tep_print_parse; + +struct tep_print_fmt { + char *format; + struct tep_print_arg *args; + struct tep_print_parse *print_cache; +}; + +struct tep_event { + struct tep_handle *tep; + char *name; + int id; + int flags; + struct tep_format format; + struct tep_print_fmt print_fmt; + char *system; + tep_event_handler_func handler; + void *context; +}; + +enum { + TEP_EVENT_FL_ISFTRACE = 0x01, + TEP_EVENT_FL_ISPRINT = 0x02, + TEP_EVENT_FL_ISBPRINT = 0x04, + TEP_EVENT_FL_ISFUNCENT = 0x10, + TEP_EVENT_FL_ISFUNCRET = 0x20, + TEP_EVENT_FL_NOHANDLE = 0x40, + TEP_EVENT_FL_PRINTRAW = 0x80, + + TEP_EVENT_FL_FAILED = 0x80000000 +}; + +enum tep_event_sort_type { + TEP_EVENT_SORT_ID, + TEP_EVENT_SORT_NAME, + TEP_EVENT_SORT_SYSTEM, +}; + +enum tep_event_type { + TEP_EVENT_ERROR, + TEP_EVENT_NONE, + TEP_EVENT_SPACE, + TEP_EVENT_NEWLINE, + TEP_EVENT_OP, + TEP_EVENT_DELIM, + TEP_EVENT_ITEM, + TEP_EVENT_DQUOTE, + TEP_EVENT_SQUOTE, +}; + +typedef unsigned long long (*tep_func_handler)(struct trace_seq *s, + unsigned long long *args); + +enum tep_func_arg_type { + TEP_FUNC_ARG_VOID, + TEP_FUNC_ARG_INT, + TEP_FUNC_ARG_LONG, + TEP_FUNC_ARG_STRING, + TEP_FUNC_ARG_PTR, + TEP_FUNC_ARG_MAX_TYPES +}; + +enum tep_flag { + TEP_NSEC_OUTPUT = 1, /* output in NSECS */ + TEP_DISABLE_SYS_PLUGINS = 1 << 1, + TEP_DISABLE_PLUGINS = 1 << 2, +}; + +#define TEP_ERRORS \ + _PE(MEM_ALLOC_FAILED, "failed to allocate memory"), \ + _PE(PARSE_EVENT_FAILED, "failed to parse event"), \ + _PE(READ_ID_FAILED, "failed to read event id"), \ + _PE(READ_FORMAT_FAILED, "failed to read event format"), \ + _PE(READ_PRINT_FAILED, "failed to read event print fmt"), \ + _PE(OLD_FTRACE_ARG_FAILED,"failed to allocate field name for ftrace"),\ + _PE(INVALID_ARG_TYPE, "invalid argument type"), \ + _PE(INVALID_EXP_TYPE, "invalid expression type"), \ + _PE(INVALID_OP_TYPE, "invalid operator type"), \ + _PE(INVALID_EVENT_NAME, "invalid event name"), \ + _PE(EVENT_NOT_FOUND, "no event found"), \ + _PE(SYNTAX_ERROR, "syntax error"), \ + _PE(ILLEGAL_RVALUE, "illegal rvalue"), \ + _PE(ILLEGAL_LVALUE, "illegal lvalue for string comparison"), \ + _PE(INVALID_REGEX, "regex did not compute"), \ + _PE(ILLEGAL_STRING_CMP, "illegal comparison for string"), \ + _PE(ILLEGAL_INTEGER_CMP,"illegal comparison for integer"), \ + _PE(REPARENT_NOT_OP, "cannot reparent other than OP"), \ + _PE(REPARENT_FAILED, "failed to reparent filter OP"), \ + _PE(BAD_FILTER_ARG, "bad arg in filter tree"), \ + _PE(UNEXPECTED_TYPE, "unexpected type (not a value)"), \ + _PE(ILLEGAL_TOKEN, "illegal token"), \ + _PE(INVALID_PAREN, "open parenthesis cannot come here"), \ + _PE(UNBALANCED_PAREN, "unbalanced number of parenthesis"), \ + _PE(UNKNOWN_TOKEN, "unknown token"), \ + _PE(FILTER_NOT_FOUND, "no filter found"), \ + _PE(NOT_A_NUMBER, "must have number field"), \ + _PE(NO_FILTER, "no filters exists"), \ + _PE(FILTER_MISS, "record does not match to filter") + +#undef _PE +#define _PE(__code, __str) TEP_ERRNO__ ## __code +enum tep_errno { + TEP_ERRNO__SUCCESS = 0, + TEP_ERRNO__FILTER_MATCH = TEP_ERRNO__SUCCESS, + + /* + * Choose an arbitrary negative big number not to clash with standard + * errno since SUS requires the errno has distinct positive values. + * See 'Issue 6' in the link below. + * + * https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html + */ + __TEP_ERRNO__START = -100000, + + TEP_ERRORS, + + __TEP_ERRNO__END, +}; +#undef _PE + +struct tep_plugin_list; + +#define INVALID_PLUGIN_LIST_OPTION ((char **)((unsigned long)-1)) + +enum tep_plugin_load_priority { + TEP_PLUGIN_FIRST, + TEP_PLUGIN_LAST, +}; + +int tep_add_plugin_path(struct tep_handle *tep, char *path, + enum tep_plugin_load_priority prio); +struct tep_plugin_list *tep_load_plugins(struct tep_handle *tep); +void tep_unload_plugins(struct tep_plugin_list *plugin_list, + struct tep_handle *tep); +void tep_load_plugins_hook(struct tep_handle *tep, const char *suffix, + void (*load_plugin)(struct tep_handle *tep, + const char *path, + const char *name, + void *data), + void *data); +char **tep_plugin_list_options(void); +void tep_plugin_free_options_list(char **list); +int tep_plugin_add_options(const char *name, + struct tep_plugin_option *options); +int tep_plugin_add_option(const char *name, const char *val); +void tep_plugin_remove_options(struct tep_plugin_option *options); +void tep_plugin_print_options(struct trace_seq *s); +void tep_print_plugins(struct trace_seq *s, + const char *prefix, const char *suffix, + const struct tep_plugin_list *list); + +/* tep_handle */ +typedef char *(tep_func_resolver_t)(void *priv, + unsigned long long *addrp, char **modp); +void tep_set_flag(struct tep_handle *tep, int flag); +void tep_clear_flag(struct tep_handle *tep, enum tep_flag flag); +bool tep_test_flag(struct tep_handle *tep, enum tep_flag flags); + +static inline int tep_is_bigendian(void) +{ + unsigned char str = { 0x1, 0x2, 0x3, 0x4 }; + unsigned int val; + + memcpy(&val, str, 4); + return val == 0x01020304; +} + +/* 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 tep_set_function_resolver(struct tep_handle *tep, + tep_func_resolver_t *func, void *priv); +void tep_reset_function_resolver(struct tep_handle *tep); +int tep_register_comm(struct tep_handle *tep, const char *comm, int pid); +int tep_override_comm(struct tep_handle *tep, const char *comm, int pid); +int tep_parse_saved_cmdlines(struct tep_handle *tep, const char *buf); +int tep_parse_kallsyms(struct tep_handle *tep, const char *kallsyms); +int tep_register_function(struct tep_handle *tep, char *name, + unsigned long long addr, char *mod); +int tep_parse_printk_formats(struct tep_handle *tep, const char *buf); +int tep_register_print_string(struct tep_handle *tep, const char *fmt, + unsigned long long addr); +bool tep_is_pid_registered(struct tep_handle *tep, int pid); + +struct tep_event *tep_get_event(struct tep_handle *tep, int index); + +#define TEP_PRINT_INFO "INFO" +#define TEP_PRINT_INFO_RAW "INFO_RAW" +#define TEP_PRINT_COMM "COMM" +#define TEP_PRINT_LATENCY "LATENCY" +#define TEP_PRINT_NAME "NAME" +#define TEP_PRINT_PID 1U +#define TEP_PRINT_TIME 2U +#define TEP_PRINT_CPU 3U + +void tep_print_event(struct tep_handle *tep, struct trace_seq *s, + struct tep_record *record, const char *fmt, ...) + __attribute__ ((format (printf, 4, 5))); + +int tep_parse_header_page(struct tep_handle *tep, char *buf, unsigned long size, + int long_size); + +enum tep_errno tep_parse_event(struct tep_handle *tep, const char *buf, + unsigned long size, const char *sys); +enum tep_errno tep_parse_format(struct tep_handle *tep, + struct tep_event **eventp, + const char *buf, + unsigned long size, const char *sys); + +void *tep_get_field_raw(struct trace_seq *s, struct tep_event *event, + const char *name, struct tep_record *record, + int *len, int err); + +int tep_get_field_val(struct trace_seq *s, struct tep_event *event, + const char *name, struct tep_record *record, + unsigned long long *val, int err); +int tep_get_common_field_val(struct trace_seq *s, struct tep_event *event, + const char *name, struct tep_record *record, + unsigned long long *val, int err); +int tep_get_any_field_val(struct trace_seq *s, struct tep_event *event, + const char *name, struct tep_record *record, + unsigned long long *val, int err); + +int tep_print_num_field(struct trace_seq *s, const char *fmt, + struct tep_event *event, const char *name, + struct tep_record *record, int err); + +int tep_print_func_field(struct trace_seq *s, const char *fmt, + struct tep_event *event, const char *name, + struct tep_record *record, int err); + +enum tep_reg_handler { + TEP_REGISTER_SUCCESS = 0, + TEP_REGISTER_SUCCESS_OVERWRITE, +}; + +int tep_register_event_handler(struct tep_handle *tep, int id, + const char *sys_name, const char *event_name, + tep_event_handler_func func, void *context); +int tep_unregister_event_handler(struct tep_handle *tep, int id, + const char *sys_name, const char *event_name, + tep_event_handler_func func, void *context); +int tep_register_print_function(struct tep_handle *tep, + tep_func_handler func, + enum tep_func_arg_type ret_type, + char *name, ...); +int tep_unregister_print_function(struct tep_handle *tep, + tep_func_handler func, char *name); + +struct tep_format_field *tep_find_common_field(struct tep_event *event, const char *name); +struct tep_format_field *tep_find_field(struct tep_event *event, const char *name); +struct tep_format_field *tep_find_any_field(struct tep_event *event, const char *name); + +const char *tep_find_function(struct tep_handle *tep, unsigned long long addr); +unsigned long long +tep_find_function_address(struct tep_handle *tep, unsigned long long addr); +int tep_find_function_info(struct tep_handle *tep, unsigned long long addr, + const char **name, unsigned long long *start, + unsigned long *size); +unsigned long long tep_read_number(struct tep_handle *tep, const void *ptr, int size); +int tep_read_number_field(struct tep_format_field *field, const void *data, + unsigned long long *value); + +struct tep_event *tep_get_first_event(struct tep_handle *tep); +int tep_get_events_count(struct tep_handle *tep); +struct tep_event *tep_find_event(struct tep_handle *tep, int id); + +struct tep_event * +tep_find_event_by_name(struct tep_handle *tep, const char *sys, const char *name); +struct tep_event * +tep_find_event_by_record(struct tep_handle *tep, struct tep_record *record); + +int tep_data_type(struct tep_handle *tep, struct tep_record *rec); +int tep_data_pid(struct tep_handle *tep, struct tep_record *rec); +int tep_data_preempt_count(struct tep_handle *tep, struct tep_record *rec); +int tep_data_flags(struct tep_handle *tep, struct tep_record *rec); +const char *tep_data_comm_from_pid(struct tep_handle *tep, int pid); +struct tep_cmdline; +struct tep_cmdline *tep_data_pid_from_comm(struct tep_handle *tep, const char *comm, + struct tep_cmdline *next); +int tep_cmdline_pid(struct tep_handle *tep, struct tep_cmdline *cmdline); + +bool tep_record_is_event(struct tep_record *record, struct tep_event *event); + +void tep_print_field_content(struct trace_seq *s, void *data, int size, + struct tep_format_field *field); +void tep_record_print_fields(struct trace_seq *s, + struct tep_record *record, + struct tep_event *event); +void tep_record_print_selected_fields(struct trace_seq *s, + struct tep_record *record, + struct tep_event *event, + unsigned long long select_mask); +void tep_print_fields(struct trace_seq *s, void *data, + int size __maybe_unused, struct tep_event *event); +int tep_strerror(struct tep_handle *tep, enum tep_errno errnum, + char *buf, size_t buflen); + +struct tep_event **tep_list_events(struct tep_handle *tep, enum tep_event_sort_type); +struct tep_event **tep_list_events_copy(struct tep_handle *tep, + enum tep_event_sort_type); +struct tep_format_field **tep_event_common_fields(struct tep_event *event); +struct tep_format_field **tep_event_fields(struct tep_event *event); + +int tep_get_function_count(struct tep_handle *tep); + +enum tep_endian { + TEP_LITTLE_ENDIAN = 0, + TEP_BIG_ENDIAN +}; +int tep_get_cpus(struct tep_handle *tep); +void tep_set_cpus(struct tep_handle *tep, int cpus); +int tep_get_long_size(struct tep_handle *tep); +void tep_set_long_size(struct tep_handle *tep, int long_size); +int tep_get_page_size(struct tep_handle *tep); +int tep_get_sub_buffer_size(struct tep_handle *tep); +int tep_get_sub_buffer_data_size(struct tep_handle *tep); +int tep_get_sub_buffer_commit_offset(struct tep_handle *tep); +void tep_set_page_size(struct tep_handle *tep, int _page_size); +bool tep_is_file_bigendian(struct tep_handle *tep); +void tep_set_file_bigendian(struct tep_handle *tep, enum tep_endian endian); +bool tep_is_local_bigendian(struct tep_handle *tep); +void tep_set_local_bigendian(struct tep_handle *tep, enum tep_endian endian); +int tep_get_header_page_size(struct tep_handle *tep); +int tep_get_header_timestamp_size(struct tep_handle *tep); +bool tep_is_old_format(struct tep_handle *tep); +void tep_set_test_filters(struct tep_handle *tep, int test_filters); + +struct tep_handle *tep_alloc(void); +void tep_free(struct tep_handle *tep); +void tep_ref(struct tep_handle *tep); +void tep_unref(struct tep_handle *tep); +int tep_get_ref(struct tep_handle *tep); + +struct kbuffer *tep_kbuffer(struct tep_handle *tep); + +/* for debugging */ +void tep_print_funcs(struct tep_handle *tep); +void tep_print_printk(struct tep_handle *tep); + +/* ----------------------- filtering ----------------------- */ + +enum tep_filter_boolean_type { + TEP_FILTER_FALSE, + TEP_FILTER_TRUE, +}; + +enum tep_filter_op_type { + TEP_FILTER_OP_AND = 1, + TEP_FILTER_OP_OR, + TEP_FILTER_OP_NOT, +}; + +enum tep_filter_cmp_type { + TEP_FILTER_CMP_NONE, + TEP_FILTER_CMP_EQ, + TEP_FILTER_CMP_NE, + TEP_FILTER_CMP_GT, + TEP_FILTER_CMP_LT, + TEP_FILTER_CMP_GE, + TEP_FILTER_CMP_LE, + TEP_FILTER_CMP_MATCH, + TEP_FILTER_CMP_NOT_MATCH, + TEP_FILTER_CMP_REGEX, + TEP_FILTER_CMP_NOT_REGEX, +}; + +enum tep_filter_exp_type { + TEP_FILTER_EXP_NONE, + TEP_FILTER_EXP_ADD, + TEP_FILTER_EXP_SUB, + TEP_FILTER_EXP_MUL, + TEP_FILTER_EXP_DIV, + TEP_FILTER_EXP_MOD, + TEP_FILTER_EXP_RSHIFT, + TEP_FILTER_EXP_LSHIFT, + TEP_FILTER_EXP_AND, + TEP_FILTER_EXP_OR, + TEP_FILTER_EXP_XOR, + TEP_FILTER_EXP_NOT, +}; + +enum tep_filter_arg_type { + TEP_FILTER_ARG_NONE, + TEP_FILTER_ARG_BOOLEAN, + TEP_FILTER_ARG_VALUE, + TEP_FILTER_ARG_FIELD, + TEP_FILTER_ARG_EXP, + TEP_FILTER_ARG_OP, + TEP_FILTER_ARG_NUM, + TEP_FILTER_ARG_STR, +}; + +enum tep_filter_value_type { + TEP_FILTER_NUMBER, + TEP_FILTER_STRING, + TEP_FILTER_CHAR +}; + +struct tep_filter_arg; + +struct tep_filter_arg_boolean { + enum tep_filter_boolean_type value; +}; + +struct tep_filter_arg_field { + struct tep_format_field *field; +}; + +struct tep_filter_arg_value { + enum tep_filter_value_type type; + union { + char *str; + unsigned long long val; + }; +}; + +struct tep_filter_arg_op { + enum tep_filter_op_type type; + struct tep_filter_arg *left; + struct tep_filter_arg *right; +}; + +struct tep_filter_arg_exp { + enum tep_filter_exp_type type; + struct tep_filter_arg *left; + struct tep_filter_arg *right; +}; + +struct tep_filter_arg_num { + enum tep_filter_cmp_type type; + struct tep_filter_arg *left; + struct tep_filter_arg *right; +}; + +struct tep_filter_arg_str { + enum tep_filter_cmp_type type; + struct tep_format_field *field; + char *val; + char *buffer; + regex_t reg; +}; + +struct tep_filter_arg { + enum tep_filter_arg_type type; + union { + struct tep_filter_arg_boolean boolean; + struct tep_filter_arg_field field; + struct tep_filter_arg_value value; + struct tep_filter_arg_op op; + struct tep_filter_arg_exp exp; + struct tep_filter_arg_num num; + struct tep_filter_arg_str str; + }; +}; + +struct tep_filter_type { + int event_id; + struct tep_event *event; + struct tep_filter_arg *filter; +}; + +#define TEP_FILTER_ERROR_BUFSZ 1024 + +struct tep_event_filter { + struct tep_handle *tep; + int filters; + struct tep_filter_type *event_filters; + char error_bufferTEP_FILTER_ERROR_BUFSZ; +}; + +struct tep_event_filter *tep_filter_alloc(struct tep_handle *tep); + +/* for backward compatibility */ +#define FILTER_NONE TEP_ERRNO__NO_FILTER +#define FILTER_NOEXIST TEP_ERRNO__FILTER_NOT_FOUND +#define FILTER_MISS TEP_ERRNO__FILTER_MISS +#define FILTER_MATCH TEP_ERRNO__FILTER_MATCH + +enum tep_errno tep_filter_add_filter_str(struct tep_event_filter *filter, + const char *filter_str); + +enum tep_errno tep_filter_match(struct tep_event_filter *filter, + struct tep_record *record); + +int tep_filter_strerror(struct tep_event_filter *filter, enum tep_errno err, + char *buf, size_t buflen); + +int tep_event_filtered(struct tep_event_filter *filter, + int event_id); + +void tep_filter_reset(struct tep_event_filter *filter); + +void tep_filter_free(struct tep_event_filter *filter); + +char *tep_filter_make_string(struct tep_event_filter *filter, int event_id); + +int tep_filter_remove_event(struct tep_event_filter *filter, + int event_id); + +int tep_filter_copy(struct tep_event_filter *dest, struct tep_event_filter *source); + +int tep_filter_compare(struct tep_event_filter *filter1, struct tep_event_filter *filter2); + +/* Control library logs */ +enum tep_loglevel { + TEP_LOG_NONE = 0, + TEP_LOG_CRITICAL, + TEP_LOG_ERROR, + TEP_LOG_WARNING, + TEP_LOG_INFO, + TEP_LOG_DEBUG, + TEP_LOG_ALL +}; +void tep_set_loglevel(enum tep_loglevel level); + +/* + * Part of the KVM plugin. Will pass the current @event and @record + * as well as a pointer to the address to a guest kernel function. + * This is currently a weak function defined in the KVM plugin and + * should never be called. But a tool can override it, and this will + * be called when the kvm plugin has an address it needs the function + * name of. + * + * This function should return the function name for the given address + * and optionally, it can update @paddr to include the start of the function + * such that the kvm plugin can include an offset. + * + * For an application to be able to override the weak version in the + * plugin, it must be compiled with the gcc -rdynamic option that will + * allow the dynamic linker to use the application's function to + * override this callback. + */ +const char *tep_plugin_kvm_get_func(struct tep_event *event, + struct tep_record *record, + unsigned long long *paddr); + +/* + * tep_plugin_kvm_put_func() is another weak function that can be used + * to call back into the application if the function name returned by + * tep_plugin_kvm_get_func() needs to be freed. + */ +void tep_plugin_kvm_put_func(const char *func); + +/* DEPRECATED */ +void tep_print_field(struct trace_seq *s, void *data, + struct tep_format_field *field); + +#ifdef __cplusplus +} +#endif + +#endif /* _PARSE_EVENTS_H */
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/include/traceevent/event-utils.h
Added
@@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: LGPL-2.1 */ +/* + * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> + * + */ +#ifndef __TEP_EVENT_UTIL_H +#define __TEP_EVENT_UTIL_H + +#include <ctype.h> +#include <stdarg.h> +#include <stdbool.h> + +#include "event-parse.h" + +void tep_warning(const char *fmt, ...); +void tep_info(const char *fmt, ...); + +/* Can be overridden */ +int tep_vprint(const char *name, enum tep_loglevel level, + bool print_err, const char *fmt, va_list ap); + +/* The actual call of tep_vprint() for overrides to use */ +int __tep_vprint(const char *name, enum tep_loglevel level, + bool print_err, const char *fmt, va_list ap); + + +#define __deprecated(msg) __attribute__((deprecated("msg"))) + +/* For backward compatibilty, do not use */ +int tep_vwarning(const char *name, const char *fmt, va_list ap) __deprecated(Use tep_vprint instead); +void pr_stat(const char *fmt, ...) __deprecated(Use tep_info instead); +void vpr_stat(const char *fmt, va_list ap) __deprecated(Use tep_vprint instead); +void __pr_stat(const char *fmt, ...) __deprecated(Use tep_info instead);; +void __vpr_stat(const char *fmt, va_list ap) __deprecated(Use tep_vprint instead);; + +#define min(x, y) ({ \ + typeof(x) _min1 = (x); \ + typeof(y) _min2 = (y); \ + (void) (&_min1 == &_min2); \ + _min1 < _min2 ? _min1 : _min2; }) + +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--; + } + string1 = 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
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/include/traceevent/kbuffer.h
Added
@@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: LGPL-2.1 */ +/* + * Copyright (C) 2012 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> + * + */ +#ifndef _KBUFFER_H +#define _KBUFFER_H + +#ifndef TS_SHIFT +#define TS_SHIFT 27 +#endif + +enum kbuffer_endian { + KBUFFER_ENDIAN_BIG, + KBUFFER_ENDIAN_LITTLE, + KBUFFER_ENDIAN_SAME_AS_HOST, +}; + +enum kbuffer_long_size { + KBUFFER_LSIZE_4, + KBUFFER_LSIZE_8, + KBUFFER_LSIZE_SAME_AS_HOST, +}; + +enum { + KBUFFER_TYPE_PADDING = 29, + KBUFFER_TYPE_TIME_EXTEND = 30, + KBUFFER_TYPE_TIME_STAMP = 31, +}; + +struct kbuffer; + +struct kbuffer *kbuffer_alloc(enum kbuffer_long_size size, enum kbuffer_endian endian); +struct kbuffer *kbuffer_dup(struct kbuffer *kbuf); +void kbuffer_free(struct kbuffer *kbuf); +int kbuffer_load_subbuffer(struct kbuffer *kbuf, void *subbuffer); +int kbuffer_refresh(struct kbuffer *kbuf); +void *kbuffer_read_event(struct kbuffer *kbuf, unsigned long long *ts); +void *kbuffer_next_event(struct kbuffer *kbuf, unsigned long long *ts); +unsigned long long kbuffer_timestamp(struct kbuffer *kbuf); +unsigned long long kbuffer_subbuf_timestamp(struct kbuffer *kbuf, void *subbuf); +unsigned int kbuffer_ptr_delta(struct kbuffer *kbuf, void *ptr); + +void *kbuffer_translate_data(int swap, void *data, unsigned int *size); + +void *kbuffer_read_at_offset(struct kbuffer *kbuf, int offset, unsigned long long *ts); +int kbuffer_read_buffer(struct kbuffer *kbuf, void *buffer, int len); + +int kbuffer_curr_index(struct kbuffer *kbuf); + +int kbuffer_curr_offset(struct kbuffer *kbuf); +int kbuffer_curr_size(struct kbuffer *kbuf); +int kbuffer_event_size(struct kbuffer *kbuf); +int kbuffer_missed_events(struct kbuffer *kbuf); +int kbuffer_subbuffer_size(struct kbuffer *kbuf); +void *kbuffer_subbuffer(struct kbuffer *kbuf); + +void kbuffer_set_old_format(struct kbuffer *kbuf); +int kbuffer_start_of_data(struct kbuffer *kbuf); + +/* Debugging */ + +struct kbuffer_raw_info { + int type; + int length; + unsigned long long delta; + void *next; +}; + +/* Read raw data */ +struct kbuffer_raw_info *kbuffer_raw_get(struct kbuffer *kbuf, void *subbuf, + struct kbuffer_raw_info *info); + +#endif /* _K_BUFFER_H */
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/include/traceevent/meson.build
Added
@@ -0,0 +1,14 @@ +# SPDX-License-Identifier: LGPL-2.1 +# +# Copyright (c) 2023 Daniel Wagner, SUSE LLC + +headers = + 'event-parse.h', + 'event-utils.h', + 'kbuffer.h', + 'trace-seq.h', + + +foreach h : headers + install_headers(h, subdir : 'traceevent') +endforeach
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/include/traceevent/trace-seq.h
Added
@@ -0,0 +1,63 @@ +// 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> + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----------------------- 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); + +#ifdef __cplusplus +} +#endif + +#endif /* _TRACE_SEQ_H */
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/meson.build
Added
@@ -0,0 +1,57 @@ +# SPDX-License-Identifier: LGPL-2.1 +# +# Copyright (c) 2023 Daniel Wagner, SUSE LLC + +project( + 'libtraceevent', 'c', + meson_version: '>= 0.58.0', + license: 'LGPL-2.1', + version: '1.8.2', + default_options: + 'c_std=gnu99', + 'buildtype=debug', + 'default_library=both', + 'prefix=/usr/local', + 'warning_level=1', + ) + +library_version = meson.project_version() + +cunit_dep = dependency('cunit', required : false) + +prefixdir = get_option('prefix') +mandir = join_paths(prefixdir, get_option('mandir')) +htmldir = join_paths(prefixdir, get_option('htmldir')) +libdir = join_paths(prefixdir, get_option('libdir')) +plugindir = get_option('plugindir') +if plugindir == '' + plugindir = join_paths(libdir, 'libtraceevent/plugins') +endif + +add_project_arguments( + + '-D_GNU_SOURCE', + '-DPLUGIN_DIR="@0@"'.format(plugindir), + , + language : 'c', +) + +incdir = include_directories('include', 'include/traceevent') + +subdir('src') +subdir('include/traceevent') +subdir('plugins') +if cunit_dep.found() + subdir('utest') +endif +subdir('samples') + +if get_option('doc') +subdir('Documentation') + +custom_target( + 'docs', + output: 'docs', + depends: html, man, + command: 'echo') +endif
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/meson_options.txt
Added
@@ -0,0 +1,20 @@ +# SPDX-License-Identifier: LGPL-2.1 +# +# Copyright (c) 2023 Daniel Wagner, SUSE LLC + +option('plugindir', type : 'string', + description : 'set the plugin dir') +option('htmldir', type : 'string', value : 'share/doc/libtraceevent-doc', + description : 'directory for HTML documentation') +option('asciidoctor', type : 'boolean', value: false, + description : 'use asciidoctor instead of asciidoc') +option('docbook-xls-172', type : 'boolean', value : false, + description : 'enable docbook XLS 172 workaround') +option('asciidoc-no-roff', type : 'boolean', value : false, + description : 'enable no roff workaround') +option('man-bold-literal', type : 'boolean', value : false, + description : 'enable bold literals') +option('docbook-suppress-sp', type : 'boolean', value : false, + description : 'docbook suppress sp') +option('doc', type : 'boolean', value: true, + description : 'produce documentation')
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/plugins/Makefile -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/plugins/Makefile
Changed
@@ -41,7 +41,7 @@ prefix ?= /usr/local libdir = $(prefix)/$(libdir_relative) -include ../scripts/Makefile.include +include ../scripts/utils.mk # copy a bit from Linux kbuild @@ -52,13 +52,6 @@ VERBOSE = 0 endif -ifeq ($(srctree),) -srctree := $(patsubst %/,%,$(dir $(CURDIR))) -#$(info Determined 'srctree' to be $(srctree)) -endif - -export prefix libdir - # Shell quotes plugin_dir_SQ = $(subst ','\'',$(plugin_dir)) @@ -69,7 +62,7 @@ OBJ = $@ N = -INCLUDES = -I. -I.. -I../src -I $(srctree)/include $(CONFIG_INCLUDES) +INCLUDES = -I. -I.. -I../src -I $(srctree)/include -I $(EP_HEADERS_DIR) $(CONFIG_INCLUDES) # Set compile option CFLAGS ifdef EXTRA_CFLAGS @@ -89,16 +82,9 @@ Q = @ endif -# Disable command line variables (CFLAGS) override from top -# level Makefile (perf), otherwise build Makefile will get -# the same command line setup. -MAKEOVERRIDES= - export srctree OUTPUT CC LD CFLAGS V -build := -f $(srctree)/build/Makefile.build dir=. obj - -DYNAMIC_LIST_FILE := $(OUTPUT)libtraceevent-dynamic-list +DYNAMIC_LIST_FILE := $(bdir)/libtraceevent-dynamic-list PLUGINS = plugin_jbd2.so PLUGINS += plugin_hrtimer.so @@ -113,22 +99,16 @@ PLUGINS += plugin_cfg80211.so PLUGINS += plugin_tlb.so -PLUGINS := $(addprefix $(OUTPUT),$(PLUGINS)) -PLUGINS_IN := $(PLUGINS:.so=-in.o) +PLUGINS := $(PLUGINS:%.so=$(bdir)/%.so) +DEPS := $(PLUGINS:$(bdir)/%.so=$(bdir)/.%.d) plugins: $(PLUGINS) $(DYNAMIC_LIST_FILE) -__plugin_obj = $(notdir $@) - plugin_obj = $(__plugin_obj:-in.o=) - -$(PLUGINS_IN): force - $(Q)$(MAKE) $(build)=$(plugin_obj) +$(PLUGINS): | $(bdir) +$(DEPS): | $(bdir) -$(OUTPUT)libtraceevent-dynamic-list: $(PLUGINS) - $(QUIET_GEN)$(call do_generate_dynamic_list_file, $(PLUGINS), $@) - -$(OUTPUT)%.so: $(OUTPUT)%-in.o - $(QUIET_LINK)$(CC) $(CFLAGS) -shared $(LDFLAGS) -nostartfiles -o $@ $^ +$(bdir)/%.so: $(srctree)/plugins/%.c + $(Q)$(call do_plugin_build) define update_dir (echo $1 > $@.tmp; \ @@ -150,17 +130,6 @@ find . -name '*.ch' | xargs etags \ --regex='/_PE(\(^,)*\).*/TEP_ERRNO__\1/' -define do_install_mkdir - if ! -d '$(DESTDIR_SQ)$1' ; then \ - $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$1'; \ - fi -endef - -define do_install - $(call do_install_mkdir,$2); \ - $(INSTALL) $(if $3,-m $3,) $1 '$(DESTDIR_SQ)$2' -endef - define do_install_plugins for plugin in $1; do \ $(call do_install,$$plugin,$(plugin_dir_SQ)); \ @@ -180,18 +149,16 @@ fi endef +$(DYNAMIC_LIST_FILE): $(PLUGINS) + $(Q)($(print_gen)$(call do_generate_dynamic_list_file, $(PLUGINS), $@)) + install: $(PLUGINS) - $(call QUIET_INSTALL, trace_plugins) \ - $(call do_install_plugins, $(PLUGINS)) + $(Q)$(call do_install_plugins, $(PLUGINS)) clean: - $(call QUIET_CLEAN, trace_plugins) \ - $(RM) $(OUTPUT)*.o $(OUTPUT)*~ $(TARGETS) $(OUTPUT)*.a $(OUTPUT)*.so $(VERSION_FILES) .*.d .*.cmd; \ - $(RM) $(OUTPUT)libtraceevent-dynamic-list; \ - $(RM) $(PLUGINS); \ - $(RM) TRACEEVENT-CFLAGS tags TAGS; + $(Q)$(call do_clean, $(DYNAMIC_LIST_FILE) $(PLUGINS)) -PHONY += force plugins +PHONY += force plugins $(DYNAMIC_LIST_FILE) force: # Declare the contents of the .PHONY variable as phony. We keep that
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/plugins/dynamic_list.sh
Added
@@ -0,0 +1,11 @@ +#!/bin/sh +# SPDX-License-Identifier: LGPL-2.1 + +symbol_type=$(nm -u -D $@ | awk 'NF>1 {print $1}' | xargs echo "U w W" | + tr 'w ' 'W\n' | sort -u | xargs echo) + +if "$symbol_type" = "U W" ; then + echo '{' + nm -u -D $@ | awk 'NF>1 {sub("@.*", "", $2); print "\t"$2";"}' | sort -u + echo '};' +fi
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/plugins/meson.build
Added
@@ -0,0 +1,44 @@ +# SPDX-License-Identifier: LGPL-2.1 +# +# Copyright (c) 2023 Daniel Wagner, SUSE LLC + +plugins = + 'plugin_cfg80211.c', + 'plugin_function.c', + 'plugin_futex.c', + 'plugin_hrtimer.c', + 'plugin_jbd2.c', + 'plugin_kmem.c', + 'plugin_kvm.c', + 'plugin_mac80211.c', + 'plugin_sched_switch.c', + 'plugin_scsi.c', + 'plugin_tlb.c', + 'plugin_xen.c', + + +pdeps = +foreach plugin : plugins + pdeps += library( + plugin.replace('.c', ''), + plugin, + name_prefix: '', + version: library_version, + dependencies: libtraceevent_dep, + include_directories: incdir, + install: true, + install_dir: plugindir) +endforeach + +# perf needs the exported symbol list +dynamic_list_file = find_program('dynamic_list.sh') +custom_target( + 'dynamic_list', + depends: pdeps, + input: pdeps, + output: 'libtraceevent-dynamic-list', + command: dynamic_list_file, '@INPUT@', + capture: true, + build_by_default: true, + install: true, + install_dir: plugindir)
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/plugins/plugin_function.c -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/plugins/plugin_function.c
Changed
@@ -10,6 +10,11 @@ #include "event-utils.h" #include "trace-seq.h" +#define __weak __attribute__((weak)) + +/* Export this for applications to override it */ +__weak const char *tep_func_repeat_format = "%6.1000d"; + static struct func_stack { int size; char **stack; @@ -169,6 +174,36 @@ return 0; } +static int trace_func_repeat_handler(struct trace_seq *s, struct tep_record *record, + struct tep_event *event, void *context) +{ + struct tep_handle *tep = event->tep; + unsigned long long count, top_delta, bottom_delta; + struct tep_record dummy; + + function_handler(s, record, event, context); + + if (tep_get_field_val(s, event, "count", record, &count, 1)) + return trace_seq_putc(s, '!'); + + if (tep_get_field_val(s, event, "top_delta_ts", record, &top_delta, 1)) + return trace_seq_putc(s, '!'); + + if (tep_get_field_val(s, event, "bottom_delta_ts", record, &bottom_delta, 1)) + return trace_seq_putc(s, '!'); + + trace_seq_printf(s, " (count: %lld last_ts: ", count); + + memcpy(&dummy, record, sizeof(dummy)); + dummy.ts -= (top_delta << 32) | bottom_delta; + + tep_print_event(tep, s, &dummy, tep_func_repeat_format, TEP_PRINT_TIME); + + trace_seq_puts(s, ")"); + + return 0; +} + static int trace_stack_handler(struct trace_seq *s, struct tep_record *record, struct tep_event *event, void *context) @@ -198,9 +233,11 @@ break; func = tep_find_function(event->tep, addr); - if (func) - trace_seq_printf(s, "=> %s (%llx)\n", func, addr); - else + if (func) { + trace_seq_puts(s, "=> "); + show_function(s, event->tep, func, addr); + trace_seq_printf(s, " (%llx)\n", addr); + } else trace_seq_printf(s, "=> %llx\n", addr); } @@ -256,6 +293,9 @@ tep_register_event_handler(tep, -1, "ftrace", "raw_data", trace_raw_data_handler, NULL); + tep_register_event_handler(tep, -1, "ftrace", "func_repeats", + trace_func_repeat_handler, NULL); + tep_plugin_add_options("ftrace", plugin_options); return 0;
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/plugins/plugin_kvm.c -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/plugins/plugin_kvm.c
Changed
@@ -10,6 +10,8 @@ #include "event-parse.h" #include "trace-seq.h" +#define __weak __attribute__((weak)) + #ifdef HAVE_UDIS86 #include <udis86.h> @@ -273,15 +275,49 @@ return 0; } +__weak const char *tep_plugin_kvm_get_func(struct tep_event *event, + struct tep_record *record, + unsigned long long *val) +{ + return NULL; +} + +__weak void tep_plugin_kvm_put_func(const char *func) +{ +} + + +static void add_rip_function(struct trace_seq *s, struct tep_record *record, + struct tep_event *event, unsigned long long rip) +{ + unsigned long long ip = rip; + const char *func; + + func = tep_plugin_kvm_get_func(event, record, &ip); + if (func) { + trace_seq_printf(s, " %s", func); + /* The application may upate ip to the start of the function */ + if (ip != rip) + trace_seq_printf(s, "+0x%0llx", rip - ip); + tep_plugin_kvm_put_func(func); + } +} + static int kvm_exit_handler(struct trace_seq *s, struct tep_record *record, struct tep_event *event, void *context) { unsigned long long info1 = 0, info2 = 0; + unsigned long long rip; if (print_exit_reason(s, record, event, "exit_reason") < 0) return -1; - tep_print_num_field(s, " rip 0x%lx", event, "guest_rip", record, 1); + if (tep_get_field_val(s, event, "guest_rip", record, &rip, 1) < 0) + return -1; + + trace_seq_printf(s, " rip 0x%llx", rip); + + add_rip_function(s, record, event, rip); if (tep_get_field_val(s, event, "info1", record, &info1, 0) >= 0 && tep_get_field_val(s, event, "info2", record, &info2, 0) >= 0) @@ -290,6 +326,22 @@ return 0; } +static int kvm_entry_handler(struct trace_seq *s, struct tep_record *record, + struct tep_event *event, void *context) +{ + unsigned long long rip; + + tep_print_num_field(s, " vcpu %u", event, "vcpu_id", record, 1); + + if (tep_get_field_val(s, event, "rip", record, &rip, 1) < 0) + return -1; + + trace_seq_printf(s, " rip 0x%llx", rip); + add_rip_function(s, record, event, rip); + + return 0; +} + #define KVM_EMUL_INSN_F_CR0_PE (1 << 0) #define KVM_EMUL_INSN_F_EFL_VM (1 << 1) #define KVM_EMUL_INSN_F_CS_D (1 << 2) @@ -329,12 +381,12 @@ flags & KVM_EMUL_INSN_F_CS_D, flags & KVM_EMUL_INSN_F_CS_L); - trace_seq_printf(s, "%llx:%llx: %s%s", csbase, rip, disasm, - failed ? " FAIL" : ""); + trace_seq_printf(s, "%llx:%llx", csbase, rip); + add_rip_function(s, record, event, rip); + trace_seq_printf(s, ": %s%s", disasm, failed ? " FAIL" : ""); return 0; } - static int kvm_nested_vmexit_inject_handler(struct trace_seq *s, struct tep_record *record, struct tep_event *event, void *context) { @@ -352,7 +404,13 @@ static int kvm_nested_vmexit_handler(struct trace_seq *s, struct tep_record *record, struct tep_event *event, void *context) { - tep_print_num_field(s, "rip %llx ", event, "rip", record, 1); + unsigned long long rip; + + if (tep_get_field_val(s, event, "rip", record, &rip, 1) < 0) + return -1; + + trace_seq_printf(s, " rip %llx", rip); + add_rip_function(s, record, event, rip); return kvm_nested_vmexit_inject_handler(s, record, event, context); } @@ -456,6 +514,9 @@ tep_register_event_handler(tep, -1, "kvm", "kvm_exit", kvm_exit_handler, NULL); + tep_register_event_handler(tep, -1, "kvm", "kvm_entry", + kvm_entry_handler, NULL); + tep_register_event_handler(tep, -1, "kvm", "kvm_emulate_insn", kvm_emulate_insn_handler, NULL); @@ -496,6 +557,9 @@ tep_unregister_event_handler(tep, -1, "kvm", "kvm_exit", kvm_exit_handler, NULL); + tep_unregister_event_handler(tep, -1, "kvm", "kvm_entry", + kvm_entry_handler, NULL); + tep_unregister_event_handler(tep, -1, "kvm", "kvm_emulate_insn", kvm_emulate_insn_handler, NULL);
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/plugins/plugin_sched_switch.c -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/plugins/plugin_sched_switch.c
Changed
@@ -9,13 +9,143 @@ #include "event-parse.h" #include "trace-seq.h" -static void write_state(struct trace_seq *s, int val) +/* + * prev_state is of size long, which is 32 bits on 32 bit architectures. + * As it needs to have the same bits for both 32 bit and 64 bit architectures + * we can just assume that the flags we care about will all be within + * the 32 bits. + */ +#define MAX_STATE_BITS 32 + +static const char *convert_sym(struct tep_print_flag_sym *sym) +{ + static char save_statesMAX_STATE_BITS + 1; + + memset(save_states, 0, sizeof(save_states)); + + /* This is the flags for the prev_state_field, now make them into a string */ + for (; sym; sym = sym->next) { + long bitmask = strtoul(sym->value, NULL, 0); + int i; + + for (i = 0; !(bitmask & 1); i++) + bitmask >>= 1; + + if (i >= MAX_STATE_BITS) + continue; + + save_statesi = sym->str0; + } + + return save_states; +} + +static struct tep_print_arg_field * +find_arg_field(struct tep_format_field *prev_state_field, struct tep_print_arg *arg) +{ + struct tep_print_arg_field *field; + + if (!arg) + return NULL; + + if (arg->type == TEP_PRINT_FIELD) + return &arg->field; + + if (arg->type == TEP_PRINT_OP) { + field = find_arg_field(prev_state_field, arg->op.left); + if (field && field->field == prev_state_field) + return field; + field = find_arg_field(prev_state_field, arg->op.right); + if (field && field->field == prev_state_field) + return field; + } + return NULL; +} + +static struct tep_print_flag_sym * +test_flags(struct tep_format_field *prev_state_field, struct tep_print_arg *arg) +{ + struct tep_print_arg_field *field; + + field = find_arg_field(prev_state_field, arg->flags.field); + if (!field) + return NULL; + + return arg->flags.flags; +} + +static struct tep_print_flag_sym * +search_op(struct tep_format_field *prev_state_field, struct tep_print_arg *arg) +{ + struct tep_print_flag_sym *sym = NULL; + + if (!arg) + return NULL; + + if (arg->type == TEP_PRINT_OP) { + sym = search_op(prev_state_field, arg->op.left); + if (sym) + return sym; + + sym = search_op(prev_state_field, arg->op.right); + if (sym) + return sym; + } else if (arg->type == TEP_PRINT_FLAGS) { + sym = test_flags(prev_state_field, arg); + } + + return sym; +} + +static const char *get_states(struct tep_format_field *prev_state_field) +{ + struct tep_print_flag_sym *sym; + struct tep_print_arg *arg; + struct tep_event *event; + + event = prev_state_field->event; + + /* + * Look at the event format fields, and search for where + * the prev_state is parsed via the format flags. + */ + for (arg = event->print_fmt.args; arg; arg = arg->next) { + /* + * Currently, the __print_flags() for the prev_state + * is embedded in operations, so they too must be + * searched. + */ + sym = search_op(prev_state_field, arg); + if (sym) + return convert_sym(sym); + } + return NULL; +} + +static void write_state(struct trace_seq *s, struct tep_format_field *field, + struct tep_record *record) { - const char states = "SDTtZXxW"; + static struct tep_format_field *prev_state_field; + static const char *states; + unsigned long long val; int found = 0; + int len; int i; - for (i = 0; i < (sizeof(states) - 1); i++) { + if (!field) + return; + + if (!states || field != prev_state_field) { + states = get_states(field); + if (!states) + states = "SDTtXZPI"; + prev_state_field = field; + } + + tep_read_number_field(field, record->data, &val); + + len = strlen(states); + for (i = 0; i < len; i++) { if (!(val & (1 << i))) continue; @@ -67,10 +197,10 @@ } trace_seq_printf(s, "%lld", val); - if (tep_get_field_val(s, event, "prio", record, &val, 0) == 0) + if (tep_get_field_val(s, event, "prio", record, &val, 1) == 0) trace_seq_printf(s, " %lld", val); - if (tep_get_field_val(s, event, "success", record, &val, 1) == 0) + if (tep_get_field_val(s, event, "success", record, &val, 0) == 0) trace_seq_printf(s, " success=%lld", val); if (tep_get_field_val(s, event, "target_cpu", record, &val, 0) == 0) @@ -96,11 +226,11 @@ } trace_seq_printf(s, "%lld ", val); - if (tep_get_field_val(s, event, "prev_prio", record, &val, 0) == 0) + if (tep_get_field_val(s, event, "prev_prio", record, &val, 1) == 0) trace_seq_printf(s, "%d ", (int) val); - if (tep_get_field_val(s, event, "prev_state", record, &val, 0) == 0) - write_state(s, val); + field = tep_find_any_field(event, "prev_state"); + write_state(s, field, record); trace_seq_puts(s, " ==> "); @@ -114,7 +244,7 @@ } trace_seq_printf(s, "%lld", val); - if (tep_get_field_val(s, event, "next_prio", record, &val, 0) == 0) + if (tep_get_field_val(s, event, "next_prio", record, &val, 1) == 0) trace_seq_printf(s, " %d", (int) val); return 0;
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/samples
Added
+(directory)
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/samples/Makefile
Added
@@ -0,0 +1,26 @@ +# SPDX-License-Identifier: LGPL-2.1 + +include $(src)/scripts/utils.mk + +TARGETS := +TARGETS += test-event + +sdir := $(obj)/samples + +TARGETS := $(patsubst %,$(sdir)/%,$(TARGETS)) + +all: $(TARGETS) + +$(sdir): + @mkdir -p $(sdir) + +$(TARGETS): $(sdir) $(LIBTRACEEVENT_STATIC) + +$(sdir)/%: $(bdir)/%.o + $(call do_sample_build,$@,$<) + +$(bdir)/%.o: $(bdir)/%.c + $(Q)$(CC) -o $@ -c $< $(CFLAGS) $(INCLUDES) + +clean: + $(Q)$(call do_clean,$(sdir)/*)
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/samples/meson.build
Added
@@ -0,0 +1,9 @@ +# SPDX-License-Identifier: LGPL-2.1 +# +# Copyright (c) 2023 Daniel Wagner, SUSE LLC + +executable( + 'test-event', + 'test-event.c', + dependencies: libtraceevent_dep, + include_directories: incdir)
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/samples/test-event.c
Added
@@ -0,0 +1,154 @@ +// SPDX-License-Identifier: LGPL-2.1 +/* + * Copyright (C) 2022 Google Inc, Steven Rostedt <rostedt@goodmis.org> + */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include <getopt.h> +#include <event-parse.h> + +static char *argv0; + +static char *get_this_name(void) +{ + static char *this_name; + char *arg; + char *p; + + if (this_name) + return this_name; + + arg = argv0; + p = arg+strlen(arg); + + while (p >= arg && *p != '/') + p--; + p++; + + this_name = p; + return p; +} + +static void usage(void) +{ + char *p = get_this_name(); + + printf("usage: %s options\n" + " -h : this message\n" + " -s system : the system for the event\n" + " -e format : the event format file\n" + " -f file : file to read the event from\n" + " otherwise, reads from stdin\n" + "\n",p); + exit(-1); +} + +static void __vdie(const char *fmt, va_list ap, int err) +{ + int ret = errno; + char *p = get_this_name(); + + if (err && errno) + perror(p); + 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, 0); + va_end(ap); +} + +void pdie(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + __vdie(fmt, ap, 1); + va_end(ap); +} + +/* Must be a power of two */ +#define BUFALLOC 1024 +#define BUFMASK (~(BUFALLOC - 1)) + +int main(int argc, char **argv) +{ + struct tep_handle *tep; + struct tep_event *event; + FILE *file = stdin; + FILE *fp = NULL; + char *system = NULL; + char *event_buf = NULL; + int esize = 0; + int c; + + argv0 = argv0; + + while ((c = getopt(argc, argv, "hs:e:f:")) >= 0) { + switch (c) { + case 's': + system = optarg; + break; + case 'e': + event_buf = optarg; + file = NULL; + break; + case 'f': + fp = fopen(optarg, "r"); + if (!fp) + pdie("%s", optarg); + file = fp; + break; + case 'h': + usage(); + } + } + if (file) { + char *line = NULL; + size_t n = 0; + int len; + + while (getline(&line, &n, file) > 0) { + len = strlen(line) + 1; + + if (((esize - 1) & BUFMASK) < ((esize + len) & BUFMASK)) { + int a; + + a = (esize + len + BUFALLOC - 1) & BUFMASK; + event_buf = realloc(event_buf, a); + if (!event_buf) + pdie("allocating event"); + } + strcpy(event_buf + esize, line); + esize += len - 1; + } + free(line); + } + + tep = tep_alloc(); + if (!tep) + pdie("Allocating tep handle"); + + tep_set_loglevel(TEP_LOG_ALL); + + if (!system) + system = "test"; + + if (tep_parse_format(tep, &event, event_buf, esize, system)) + die("Failed to parse event"); + +}
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/scripts/features.mk
Added
@@ -0,0 +1,37 @@ +# SPDX-License-Identifier: GPL-2.0 + +# taken from perf which was based on Linux Kbuild +# try-cc +# Usage: option = $(call try-cc, source-to-build, cc-options) +try-cc = $(shell sh -c \ + 'TMP="$(BUILD_OUTPUT)$(TMPOUT).$$$$"; \ + echo "$(1)" | \ + $(CC) -x c - $(2) -o "$$TMP" > /dev/null 2>&1 && echo y; \ + rm -f "$$TMP"') + +define SOURCE_PTRACE +#include <stdio.h> +#include <sys/ptrace.h> + +int main (void) +{ + int ret; + ret = ptrace(PTRACE_ATTACH, 0, NULL, 0); + ptrace(PTRACE_TRACEME, 0, NULL, 0); + ptrace(PTRACE_GETSIGINFO, 0, NULL, NULL); + ptrace(PTRACE_GETEVENTMSG, 0, NULL, NULL); + ptrace(PTRACE_SETOPTIONS, NULL, NULL, + PTRACE_O_TRACEFORK | + PTRACE_O_TRACEVFORK | + PTRACE_O_TRACECLONE | + PTRACE_O_TRACEEXIT); + ptrace(PTRACE_CONT, NULL, NULL, 0); + ptrace(PTRACE_DETACH, 0, NULL, NULL); + ptrace(PTRACE_SETOPTIONS, 0, NULL, + PTRACE_O_TRACEFORK | + PTRACE_O_TRACEVFORK | + PTRACE_O_TRACECLONE | + PTRACE_O_TRACEEXIT); + return ret; +} +endef
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/scripts/utils.mk
Added
@@ -0,0 +1,182 @@ +# SPDX-License-Identifier: LGPL-2.1 + +# Utils + + PWD := $(shell /bin/pwd) + GOBJ = $(notdir $(strip $@)) + BASE1 = $(notdir $(strip $1)) + BASE2 = $(notdir $(strip $2)) + BASEPWD = $(notdir $(strip $(PWD))) + + +ifeq ($(VERBOSE),1) + Q = + S = +else + Q = @ + S = -s +endif + +# Use empty print_* macros if either SILENT or VERBOSE. +ifeq ($(findstring 1,$(SILENT)$(VERBOSE)),1) + print_compile = + print_app_build = + print_fpic_compile = + print_shared_lib_compile = + print_plugin_obj_compile = + print_plugin_build = + print_install = + print_uninstall = + print_gen = + print_update = + print_descend = + print_clean = +else + print_compile = echo ' COMPILE '$(GOBJ); + print_app_build = echo ' BUILD '$(GOBJ); + print_fpic_compile = echo ' COMPILE FPIC '$(GOBJ); + print_shared_lib_compile = echo ' COMPILE SHARED LIB '$(GOBJ); + print_plugin_obj_compile = echo ' COMPILE PLUGIN OBJ '$(GOBJ); + print_plugin_build = echo ' BUILD PLUGIN '$(GOBJ); + print_static_lib_build = echo ' BUILD STATIC LIB '$(GOBJ); + print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2'; + print_uninstall = echo ' UNINSTALL $(DESTDIR_SQ)$1'; + print_gen = echo ' GEN '$(GOBJ); + print_update = echo ' UPDATE '$(GOBJ); + print_descend = echo ' DESCEND '$(BASE1) $(BASE2); + print_clean = echo ' CLEAN '$(BASEPWD); +endif + +do_fpic_compile = \ + ($(print_fpic_compile) \ + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(EXT) -fPIC $< -o $@) + +do_compile = \ + ($(if $(GENERATE_PIC), $(do_fpic_compile), \ + $(print_compile) \ + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(EXT) $< -o $@)) + +do_app_build = \ + ($(print_app_build) \ + $(CC) $^ -rdynamic -o $@ $(LDFLAGS) $(CONFIG_LIBS) $(LIBS)) + +do_build_static_lib = \ + ($(print_static_lib_build) \ + if -f $@ ; then \ + mv $@ $@.rm; $(RM) $@.rm; \ + fi; \ + $(AR) rcs $@ $^) + +do_compile_shared_library = \ + ($(print_shared_lib_compile) \ + $(CC) --shared $^ '-Wl,-soname,$(1),-rpath=$$ORIGIN' -o $@ $(LDFLAGS) $(LIBS)) + +do_compile_plugin_obj = \ + ($(print_plugin_obj_compile) \ + $(CC) -c $(CPPFLAGS) $(CFLAGS) -fPIC -o $@ $<) + +do_plugin_build = \ + ($(print_plugin_build) \ + $(CC) $(CFLAGS) $(LDFLAGS) -shared -nostartfiles -o $@ $<) + +do_compile_python_plugin_obj = \ + ($(print_plugin_obj_compile) \ + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PYTHON_DIR_SQ) $(PYTHON_INCLUDES) -fPIC -o $@ $<) + +do_python_plugin_build = \ + ($(print_plugin_build) \ + $(CC) $< -shared $(LDFLAGS) $(PYTHON_LDFLAGS) -o $@) + +do_clean = \ + ($(print_clean) \ + $(RM) $1) + +do_sample_build = \ + $(Q)($(print_sample_build) \ + $(CC) -o $1 $2 $(CFLAGS) $(LIBTRACEEVENT_STATIC) -ldl) + +do_sample_obj = \ + $(Q)($(print_sample_obj) \ + $(CC) -g -Wall -c $(CFLAGS) -o $1 $2 -I../include/) + +# +# Define a callable command for descending to a new directory +# +# Call by doing: $(call descend,directory,target) +# +descend = \ + ($(print_descend) \ + mkdir -p $(obj)/$(BASE1); \ + $(MAKE) $(PRINT_DIR) bdir=$(obj)/$(BASE1) -C $(1) $(2)) + +descend_clean = \ + $(MAKE) $(PRINT_DIR) bdir=$(obj)/$(BASE1) -C $(1) clean + +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); \ + if -d $(src)/.git ; then \ + d=`git diff`; \ + x=""; \ + if ! -z "$$d" ; then x="+"; fi; \ + echo '#define VERSION_GIT "'$(shell \ + git log -1 --pretty=format:"%H" 2>/dev/null)$$x'"'; \ + else \ + echo '#define VERSION_GIT "not-a-git-repo"'; \ + fi \ + ) > $1 +endef + +define update_version.h + ($(call make_version.h, $@.tmp); \ + if -r $@ && cmp -s $@ $@.tmp; then \ + rm -f $@.tmp; \ + else \ + $(print_update) \ + mv -f $@.tmp $@; \ + fi); +endef + +define update_dir + (echo $1 > $@.tmp; \ + if -r $@ && cmp -s $@ $@.tmp; then \ + rm -f $@.tmp; \ + else \ + $(print_update) \ + mv -f $@.tmp $@; \ + fi); +endef + +define build_prefix + (echo $1 > $@.tmp; \ + if -r $@ && cmp -s $@ $@.tmp; then \ + rm -f $@.tmp; \ + else \ + $(print_update) \ + mv -f $@.tmp $@; \ + fi); +endef + +define do_install_mkdir + if ! -d '$(DESTDIR_SQ)$1' ; then \ + $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$1'; \ + fi +endef + +define do_install + $(print_install) \ + $(call do_install_mkdir,$2); \ + $(INSTALL) $(if $3,-m $3,) $1 '$(DESTDIR_SQ)$2' +endef + +define do_install_pkgconfig_file + if -n "${pkgconfig_dir}" ; then \ + $(call do_install,$(PKG_CONFIG_FILE),$(pkgconfig_dir),644); \ + else \ + (echo Failed to locate pkg-config directory) 1>&2; \ + fi +endef
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/src/Makefile -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/src/Makefile
Changed
@@ -1,12 +1,55 @@ # SPDX-License-Identifier: LGPL-2.1 -include ../scripts/Makefile.include +include $(src)/scripts/utils.mk -build := -f $(srctree)/build/Makefile.build dir=. obj +OBJS = +OBJS += event-parse-api.o +OBJS += event-parse.o +OBJS += event-plugin.o +OBJS += kbuffer-parse.o +OBJS += parse-filter.o +OBJS += parse-utils.o +OBJS += tep_strerror.o +OBJS += trace-seq.o + +OBJS := $(OBJS:%.o=$(bdir)/%.o) +DEPS := $(OBJS:$(bdir)/%.o=$(bdir)/.%.d) + +$(bdir)/%.o: %.c + $(Q)$(call do_fpic_compile) + +$(LIBTRACEEVENT_STATIC): $(OBJS) + $(Q)$(call do_build_static_lib) + +$(LIBTRACEEVENT_SHARED): $(OBJS) + $(Q)$(call do_compile_shared_library,$(notdir $(LIBTRACEEVENT_SHARED_VERSION))) + +$(LIBTRACEEVENT_SHARED_VERSION): $(LIBTRACEEVENT_SHARED) + @ln -sf $(<F) $@ + +$(LIBTRACEEVENT_SHARED_SO): $(LIBTRACEEVENT_SHARED_VERSION) + @ln -sf $(<F) $@ + +libtraceevent.so: $(LIBTRACEEVENT_SHARED_SO) libtraceevent: $(libtraceevent-y) $(Q)$(MAKE) $(build)=libtraceevent +$(DEPS): $(bdir)/.%.d: %.c + $(Q)$(CC) -M -MT $(bdir)/$*.o $(CPPFLAGS) $(CFLAGS) $< > $@ + +$(OBJS): $(bdir)/%.o : $(bdir)/.%.d + +$(OBJS): | $(bdir) +$(DEPS): | $(bdir) + clean: - $(call QUIET_CLEAN, trace_src) \ - $(RM) $(OUTPUT)*.o $(OUTPUT)*~ .*.d .*.cmd + $(Q)$(call do_clean,$(OBJS) $(DEPS)) + +dep_includes := $(wildcard $(DEPS)) + +ifneq ($(dep_includes),) + include $(dep_includes) +endif + +.PHONY: $(LIBTRACEEVENT_SHARED_SO) $(LIBTRACEEVENT_STATIC)
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/src/event-parse-api.c -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/src/event-parse-api.c
Changed
@@ -51,6 +51,20 @@ } /** + * 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_function_count(struct tep_handle *tep) +{ + if (tep) + return tep->func_count; + 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 @@ -249,6 +263,50 @@ } /** + * tep_get_sub_buffer_data_size - get the size of the data portion + * @tep: The handle to the tep to get the data size from + * + * Returns the size of the data portion of the sub buffer + */ +int tep_get_sub_buffer_data_size(struct tep_handle *tep) +{ + if (!tep) + return -1; + + return tep->header_page_data_size; +} + +/** + * tep_get_sub_buffer_size - get the size of a trace buffer page + * @tep: a handle to the tep_handle + * + * This returns the size of a trace buffer page on the traced machine. + * If @tep is NULL then -1 is returned. + */ +int tep_get_sub_buffer_size(struct tep_handle *tep) +{ + if (!tep) + return -1; + + return tep->header_page_data_size + tep->header_page_data_offset; +} + +/** + * tep_get_sub_buffer_commit_offset - return offset of the commit location + * @tep: the handle to the tep_handle + * + * Returns the offset of where to find the "commit" field of the offset. + * Use tep_get_header_page_size() to find the size of the commit field. + */ +int tep_get_sub_buffer_commit_offset(struct tep_handle *tep) +{ + if (!tep) + return -1; + + return tep->header_page_size_offset; +} + +/** * tep_is_file_bigendian - return the endian of the file * @tep: a handle to the tep_handle *
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/src/event-parse-local.h -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/src/event-parse-local.h
Changed
@@ -85,6 +85,10 @@ struct tep_event *last_event; struct tep_plugins_dir *plugins_dir; + + const char *input_buf; + unsigned long long input_buf_ptr; + unsigned long long input_buf_siz; }; enum tep_print_parse_type { @@ -113,11 +117,11 @@ unsigned long long data2host8(struct tep_handle *tep, unsigned long long data); /* access to the internal parser */ -int peek_char(void); -void init_input_buf(const char *buf, unsigned long long size); -unsigned long long get_input_buf_ptr(void); -const char *get_input_buf(void); -enum tep_event_type read_token(char **tok); +int peek_char(struct tep_handle *tep); +void init_input_buf(struct tep_handle *tep, const char *buf, unsigned long long size); +unsigned long long get_input_buf_ptr(struct tep_handle *tep); +const char *get_input_buf(struct tep_handle *tep); +enum tep_event_type read_token(struct tep_handle *tep, char **tok); void free_token(char *tok); #endif /* _PARSE_EVENTS_INT_H */
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/src/event-parse.c -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/src/event-parse.c
Changed
@@ -17,6 +17,7 @@ #include <ctype.h> #include <errno.h> #include <stdint.h> +#include <unistd.h> #include <limits.h> #include <linux/time64.h> @@ -27,10 +28,6 @@ #include "event-utils.h" #include "trace-seq.h" -static const char *input_buf; -static unsigned long long input_buf_ptr; -static unsigned long long input_buf_siz; - static int is_flag_field; static int is_symbolic_field; @@ -61,21 +58,22 @@ * * Initializes the internal buffer that tep_read_token() will parse. */ -__hidden void init_input_buf(const char *buf, unsigned long long size) +__hidden void init_input_buf(struct tep_handle *tep, const char *buf, + unsigned long long size) { - input_buf = buf; - input_buf_siz = size; - input_buf_ptr = 0; + tep->input_buf = buf; + tep->input_buf_siz = size; + tep->input_buf_ptr = 0; } -__hidden const char *get_input_buf(void) +__hidden const char *get_input_buf(struct tep_handle *tep) { - return input_buf; + return tep->input_buf; } -__hidden unsigned long long get_input_buf_ptr(void) +__hidden unsigned long long get_input_buf_ptr(struct tep_handle *tep) { - return input_buf_ptr; + return tep->input_buf_ptr; } struct event_handler { @@ -113,6 +111,22 @@ x++; } +static const char *get_event_type(enum tep_event_type type) +{ + switch (type) { + case TEP_EVENT_ERROR: return "ERROR"; + case TEP_EVENT_NONE: return "NONE"; + case TEP_EVENT_SPACE: return "SPACE"; + case TEP_EVENT_NEWLINE: return "NEWLINE"; + case TEP_EVENT_OP: return "OP"; + case TEP_EVENT_DELIM: return "DELIM"; + case TEP_EVENT_ITEM: return "ITEM"; + case TEP_EVENT_DQUOTE: return "DQUOTE"; + case TEP_EVENT_SQUOTE: return "SQUOTE"; + } + return "(UNKNOWN)"; +} + static struct tep_print_arg *alloc_arg(void) { return calloc(1, sizeof(struct tep_print_arg)); @@ -597,6 +611,43 @@ } /** + * tep_find_function_info - find a function by a given address + * @tep: a handle to the trace event parser context + * @addr: the address to find the function with + * @name: Return the name of the function (if found) + * @start: Return the start of the function (if found) + * @size: Return the size of the function (if found) + * + * Returns 1 if found, and 0 if it is not. + * If found then @name will point to the name of the function. + * @start: will contain the starting address of the function. + * @size: will contain the size of the function. + */ +int tep_find_function_info(struct tep_handle *tep, unsigned long long addr, + const char **name, unsigned long long *start, + unsigned long *size) +{ + struct func_map *map; + + map = find_func(tep, addr); + if (!map) + return 0; + + if (name) + *name = map->func; + if (start) + *start = map->addr; + if (size) { + if (!tep->func_resolver) + *size = map1.addr - map->addr; + else + *size = 0; + } + + return 1; +} + +/** * tep_find_function - find a function by a given address * @tep: a handle to the trace event parser context * @addr: the address to find the function with @@ -722,8 +773,11 @@ if (errno) goto out; - if (n != 2 || !func_end) + if (n != 2 || !func_end) { + tep_warning("Failed to parse kallsyms n=%d func_end=%d", + n, func_end); goto out; + } func = line + func_start; /* @@ -1063,6 +1117,7 @@ free(arg->string.string); break; case TEP_PRINT_BITMASK: + case TEP_PRINT_CPUMASK: free(arg->bitmask.bitmask); break; case TEP_PRINT_DYNAMIC_ARRAY: @@ -1110,12 +1165,12 @@ return TEP_EVENT_OP; } -static int __read_char(void) +static int __read_char(struct tep_handle *tep) { - if (input_buf_ptr >= input_buf_siz) + if (tep->input_buf_ptr >= tep->input_buf_siz) return -1; - return input_bufinput_buf_ptr++; + return tep->input_buftep->input_buf_ptr++; } /** @@ -1123,12 +1178,12 @@ * * Returns the next character read, or -1 if end of buffer. */ -__hidden int peek_char(void) +__hidden int peek_char(struct tep_handle *tep) { - if (input_buf_ptr >= input_buf_siz) + if (tep->input_buf_ptr >= tep->input_buf_siz) return -1; - return input_bufinput_buf_ptr; + return tep->input_buftep->input_buf_ptr; } static int extend_token(char **tok, char *buf, int size) @@ -1150,9 +1205,10 @@ return 0; } -static enum tep_event_type force_token(const char *str, char **tok); +static enum tep_event_type force_token(struct tep_handle *tep, const char *str, + char **tok); -static enum tep_event_type __read_token(char **tok) +static enum tep_event_type __read_token(struct tep_handle *tep, char **tok) { char bufBUFSIZ; int ch, last_ch, quote_ch, next_ch; @@ -1163,7 +1219,7 @@ *tok = NULL; - ch = __read_char(); + ch = __read_char(tep); if (ch < 0) return TEP_EVENT_NONE; @@ -1184,9 +1240,9 @@ case TEP_EVENT_OP: switch (ch) { case '-': - next_ch = peek_char(); + next_ch = peek_char(tep); if (next_ch == '>') { - bufi++ = __read_char(); + bufi++ = __read_char(tep); break; } /* fall through */ @@ -1196,10 +1252,10 @@ case '>': case '<': last_ch = ch; - ch = peek_char(); + ch = peek_char(tep); if (ch != last_ch) goto test_equal; - bufi++ = __read_char(); + bufi++ = __read_char(tep); switch (last_ch) { case '>': case '<': @@ -1219,9 +1275,9 @@ return type; test_equal: - ch = peek_char(); + ch = peek_char(tep); if (ch == '=') - bufi++ = __read_char(); + bufi++ = __read_char(tep); goto out; case TEP_EVENT_DQUOTE: @@ -1241,28 +1297,34 @@ i = 0; } last_ch = ch; - ch = __read_char(); + ch = __read_char(tep); bufi++ = ch; /* the '\' '\' will cancel itself */ if (ch == '\\' && last_ch == '\\') last_ch = 0; - } while (ch != quote_ch || last_ch == '\\'); + /* Break out if the file is corrupted and giving non print chars */ + if (ch <= 0) + break; + } while ((ch != quote_ch && isprint(ch)) || last_ch == '\\' || ch == '\n'); /* remove the last quote */ i--; + if (ch <= 0) + type = TEP_EVENT_NONE; + /* * For strings (double quotes) check the next token. * If it is another string, concatinate the two. */ if (type == TEP_EVENT_DQUOTE) { - unsigned long long save_input_buf_ptr = input_buf_ptr; + unsigned long long save_input_buf_ptr = tep->input_buf_ptr; do { - ch = __read_char(); + ch = __read_char(tep); } while (isspace(ch)); if (ch == '"') goto concat; - input_buf_ptr = save_input_buf_ptr; + tep->input_buf_ptr = save_input_buf_ptr; } goto out; @@ -1273,7 +1335,7 @@ break; } - while (get_type(peek_char()) == type) { + while (get_type(peek_char(tep)) == type) { if (i == (BUFSIZ - 1)) { bufi = 0; tok_size += BUFSIZ; @@ -1282,7 +1344,7 @@ return TEP_EVENT_NONE; i = 0; } - ch = __read_char(); + ch = __read_char(tep); bufi++ = ch; } @@ -1303,22 +1365,23 @@ if (strcmp(*tok, "LOCAL_PR_FMT") == 0) { free(*tok); *tok = NULL; - return force_token("\"%s\" ", tok); + return force_token(tep, "\"%s\" ", tok); } else if (strcmp(*tok, "STA_PR_FMT") == 0) { free(*tok); *tok = NULL; - return force_token("\" sta:%pM\" ", tok); + return force_token(tep, "\" sta:%pM\" ", tok); } else if (strcmp(*tok, "VIF_PR_FMT") == 0) { free(*tok); *tok = NULL; - return force_token("\" vif:%p(%d)\" ", tok); + return force_token(tep, "\" vif:%p(%d)\" ", tok); } } return type; } -static enum tep_event_type force_token(const char *str, char **tok) +static enum tep_event_type force_token(struct tep_handle *tep, const char *str, + char **tok) { const char *save_input_buf; unsigned long long save_input_buf_ptr; @@ -1326,18 +1389,18 @@ enum tep_event_type type; /* save off the current input pointers */ - save_input_buf = input_buf; - save_input_buf_ptr = input_buf_ptr; - save_input_buf_siz = input_buf_siz; + save_input_buf = tep->input_buf; + save_input_buf_ptr = tep->input_buf_ptr; + save_input_buf_siz = tep->input_buf_siz; - init_input_buf(str, strlen(str)); + init_input_buf(tep, str, strlen(str)); - type = __read_token(tok); + type = __read_token(tep, tok); /* reset back to original token */ - input_buf = save_input_buf; - input_buf_ptr = save_input_buf_ptr; - input_buf_siz = save_input_buf_siz; + tep->input_buf = save_input_buf; + tep->input_buf_ptr = save_input_buf_ptr; + tep->input_buf_siz = save_input_buf_siz; return type; } @@ -1361,12 +1424,12 @@ * * Returns the token type. */ -__hidden enum tep_event_type read_token(char **tok) +__hidden enum tep_event_type read_token(struct tep_handle *tep, char **tok) { enum tep_event_type type; for (;;) { - type = __read_token(tok); + type = __read_token(tep, tok); if (type != TEP_EVENT_SPACE) return type; @@ -1379,12 +1442,12 @@ } /* no newline */ -static enum tep_event_type read_token_item(char **tok) +static enum tep_event_type read_token_item(struct tep_handle *tep, char **tok) { enum tep_event_type type; for (;;) { - type = __read_token(tok); + type = __read_token(tep, tok); if (type != TEP_EVENT_SPACE && type != TEP_EVENT_NEWLINE) return type; free_token(*tok); @@ -1399,8 +1462,9 @@ static int test_type(enum tep_event_type type, enum tep_event_type expect) { if (type != expect) { - do_warning("Error: expected type %d but read %d", - expect, type); + do_warning("Error: expected type %d (%s) but read %d (%s)", + expect, get_event_type(expect), + type, get_event_type(type)); return -1; } return 0; @@ -1410,8 +1474,9 @@ enum tep_event_type expect, const char *expect_tok) { if (type != expect) { - do_warning("Error: expected type %d but read %d", - expect, type); + do_warning("Error: expected type %d (%s) but read %d (%s)", + expect, get_event_type(expect), + type, get_event_type(type)); return -1; } @@ -1423,33 +1488,35 @@ return 0; } -static int __read_expect_type(enum tep_event_type expect, char **tok, int newline_ok) +static int __read_expect_type(struct tep_handle *tep, enum tep_event_type expect, + char **tok, int newline_ok) { enum tep_event_type type; if (newline_ok) - type = read_token(tok); + type = read_token(tep, tok); else - type = read_token_item(tok); + type = read_token_item(tep, tok); return test_type(type, expect); } -static int read_expect_type(enum tep_event_type expect, char **tok) +static int read_expect_type(struct tep_handle *tep, enum tep_event_type expect, + char **tok) { - return __read_expect_type(expect, tok, 1); + return __read_expect_type(tep, expect, tok, 1); } -static int __read_expected(enum tep_event_type expect, const char *str, - int newline_ok) +static int __read_expected(struct tep_handle *tep, enum tep_event_type expect, + const char *str, int newline_ok) { enum tep_event_type type; char *token; int ret; if (newline_ok) - type = read_token(&token); + type = read_token(tep, &token); else - type = read_token_item(&token); + type = read_token_item(tep, &token); ret = test_type_token(type, token, expect, str); @@ -1458,27 +1525,29 @@ return ret; } -static int read_expected(enum tep_event_type expect, const char *str) +static int read_expected(struct tep_handle *tep, enum tep_event_type expect, + const char *str) { - return __read_expected(expect, str, 1); + return __read_expected(tep, expect, str, 1); } -static int read_expected_item(enum tep_event_type expect, const char *str) +static int read_expected_item(struct tep_handle *tep, enum tep_event_type expect, + const char *str) { - return __read_expected(expect, str, 0); + return __read_expected(tep, expect, str, 0); } -static char *event_read_name(void) +static char *event_read_name(struct tep_handle *tep) { char *token; - if (read_expected(TEP_EVENT_ITEM, "name") < 0) + if (read_expected(tep, TEP_EVENT_ITEM, "name") < 0) return NULL; - if (read_expected(TEP_EVENT_OP, ":") < 0) + if (read_expected(tep, TEP_EVENT_OP, ":") < 0) return NULL; - if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) + if (read_expect_type(tep, TEP_EVENT_ITEM, &token) < 0) goto fail; return token; @@ -1488,18 +1557,18 @@ return NULL; } -static int event_read_id(void) +static int event_read_id(struct tep_handle *tep) { char *token; int id; - if (read_expected_item(TEP_EVENT_ITEM, "ID") < 0) + if (read_expected_item(tep, TEP_EVENT_ITEM, "ID") < 0) return -1; - if (read_expected(TEP_EVENT_OP, ":") < 0) + if (read_expected(tep, TEP_EVENT_OP, ":") < 0) return -1; - if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) + if (read_expect_type(tep, TEP_EVENT_ITEM, &token) < 0) goto fail; id = strtoul(token, NULL, 0); @@ -1529,6 +1598,14 @@ return 0; } +static int field_is_relative_dynamic(struct tep_format_field *field) +{ + if (strncmp(field->type, "__rel_loc", 9) == 0) + return 1; + + return 0; +} + static int field_is_long(struct tep_format_field *field) { /* includes long long */ @@ -1579,7 +1656,8 @@ return 0; } -static int event_read_fields(struct tep_event *event, struct tep_format_field **fields) +static int event_read_fields(struct tep_handle *tep, struct tep_event *event, + struct tep_format_field **fields) { struct tep_format_field *field = NULL; enum tep_event_type type; @@ -1592,7 +1670,7 @@ do { unsigned int size_dynamic = 0; - type = read_token(&token); + type = read_token(tep, &token); if (type == TEP_EVENT_NEWLINE) { free_token(token); return count; @@ -1604,7 +1682,7 @@ goto fail; free_token(token); - type = read_token(&token); + type = read_token(tep, &token); /* * The ftrace fields may still use the "special" name. * Just ignore it. @@ -1612,14 +1690,14 @@ if (event->flags & TEP_EVENT_FL_ISFTRACE && type == TEP_EVENT_ITEM && strcmp(token, "special") == 0) { free_token(token); - type = read_token(&token); + type = read_token(tep, &token); } if (test_type_token(type, token, TEP_EVENT_OP, ":") < 0) goto fail; free_token(token); - if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) + if (read_expect_type(tep, TEP_EVENT_ITEM, &token) < 0) goto fail; last_token = token; @@ -1632,7 +1710,7 @@ /* read the rest of the type */ for (;;) { - type = read_token(&token); + type = read_token(tep, &token); if (type == TEP_EVENT_ITEM || (type == TEP_EVENT_OP && strcmp(token, "*") == 0) || /* @@ -1670,7 +1748,7 @@ goto fail; delim = " "; - while ((type = read_token(&token)) != TEP_EVENT_NONE) { + while ((type = read_token(tep, &token)) != TEP_EVENT_NONE) { if (type == TEP_EVENT_DELIM) { if (token0 == '(') depth++; @@ -1709,7 +1787,7 @@ field->flags |= TEP_FIELD_IS_ARRAY; - type = read_token(&token); + type = read_token(tep, &token); if (type == TEP_EVENT_ITEM) field->arraylen = strtoul(token, NULL, 0); @@ -1735,7 +1813,7 @@ /* We only care about the last token */ field->arraylen = strtoul(token, NULL, 0); free_token(token); - type = read_token(&token); + type = read_token(tep, &token); if (type == TEP_EVENT_NONE) { free(brackets); do_warning_event(event, "failed to find token"); @@ -1748,12 +1826,12 @@ ret = append(&brackets, "", ""); if (ret < 0) { free(brackets); - goto fail; + goto fail_expect; } /* add brackets to type */ - type = read_token(&token); + type = read_token(tep, &token); /* * If the next token is not an OP, then it is of * the format: type item; @@ -1769,7 +1847,7 @@ size_dynamic = type_size(field->name); free_token(field->name); field->name = field->alias = token; - type = read_token(&token); + type = read_token(tep, &token); } else { ret = append(&field->type, "", brackets); if (ret < 0) { @@ -1784,6 +1862,8 @@ field->flags |= TEP_FIELD_IS_STRING; if (field_is_dynamic(field)) field->flags |= TEP_FIELD_IS_DYNAMIC; + if (field_is_relative_dynamic(field)) + field->flags |= TEP_FIELD_IS_DYNAMIC | TEP_FIELD_IS_RELATIVE; if (field_is_long(field)) field->flags |= TEP_FIELD_IS_LONG; @@ -1791,35 +1871,45 @@ goto fail; free_token(token); - if (read_expected(TEP_EVENT_ITEM, "offset") < 0) + if (read_expected(tep, TEP_EVENT_ITEM, "offset") < 0) goto fail_expect; - if (read_expected(TEP_EVENT_OP, ":") < 0) + if (read_expected(tep, TEP_EVENT_OP, ":") < 0) goto fail_expect; - if (read_expect_type(TEP_EVENT_ITEM, &token)) + if (read_expect_type(tep, TEP_EVENT_ITEM, &token)) goto fail; field->offset = strtoul(token, NULL, 0); free_token(token); - if (read_expected(TEP_EVENT_OP, ";") < 0) + if (read_expected(tep, TEP_EVENT_OP, ";") < 0) goto fail_expect; - if (read_expected(TEP_EVENT_ITEM, "size") < 0) + if (read_expected(tep, TEP_EVENT_ITEM, "size") < 0) goto fail_expect; - if (read_expected(TEP_EVENT_OP, ":") < 0) + if (read_expected(tep, TEP_EVENT_OP, ":") < 0) goto fail_expect; - if (read_expect_type(TEP_EVENT_ITEM, &token)) + if (read_expect_type(tep, TEP_EVENT_ITEM, &token)) goto fail; field->size = strtoul(token, NULL, 0); free_token(token); - if (read_expected(TEP_EVENT_OP, ";") < 0) + /* + * The old data format before dynamic arrays had dynamic + * strings defined with just a 2 byte offset (the length + * is defined by the strlen() of the string. To process them + * correctly, check if the field is dynamic and has a size of + * 2 bytes. All current dynamic events have a size of 4. + */ + if ((field->flags & TEP_FIELD_IS_DYNAMIC) && field->size == 2) + field->flags |= TEP_FIELD_IS_STRING | TEP_FIELD_IS_ARRAY; + + if (read_expected(tep, TEP_EVENT_OP, ";") < 0) goto fail_expect; - type = read_token(&token); + type = read_token(tep, &token); if (type != TEP_EVENT_NEWLINE) { /* newer versions of the kernel have a "signed" type */ if (test_type_token(type, token, TEP_EVENT_ITEM, "signed")) @@ -1827,26 +1917,26 @@ free_token(token); - if (read_expected(TEP_EVENT_OP, ":") < 0) + if (read_expected(tep, TEP_EVENT_OP, ":") < 0) goto fail_expect; - if (read_expect_type(TEP_EVENT_ITEM, &token)) + if (read_expect_type(tep, TEP_EVENT_ITEM, &token)) goto fail; if (strtoul(token, NULL, 0)) field->flags |= TEP_FIELD_IS_SIGNED; free_token(token); - if (read_expected(TEP_EVENT_OP, ";") < 0) + if (read_expected(tep, TEP_EVENT_OP, ";") < 0) goto fail_expect; - if (read_expect_type(TEP_EVENT_NEWLINE, &token)) + if (read_expect_type(tep, TEP_EVENT_NEWLINE, &token)) goto fail; } free_token(token); - if (field->flags & TEP_FIELD_IS_ARRAY) { + if (field->flags & (TEP_FIELD_IS_ARRAY | TEP_FIELD_IS_DYNAMIC)) { if (field->arraylen) field->elementsize = field->size / field->arraylen; else if (field->flags & TEP_FIELD_IS_DYNAMIC) @@ -1862,6 +1952,7 @@ *fields = field; fields = &field->next; + field = NULL; } while (1); @@ -1883,22 +1974,22 @@ char *token; int ret; - if (read_expected_item(TEP_EVENT_ITEM, "format") < 0) + if (read_expected_item(event->tep, TEP_EVENT_ITEM, "format") < 0) return -1; - if (read_expected(TEP_EVENT_OP, ":") < 0) + if (read_expected(event->tep, TEP_EVENT_OP, ":") < 0) return -1; - if (read_expect_type(TEP_EVENT_NEWLINE, &token)) + if (read_expect_type(event->tep, TEP_EVENT_NEWLINE, &token)) goto fail; free_token(token); - ret = event_read_fields(event, &event->format.common_fields); + ret = event_read_fields(event->tep, event, &event->format.common_fields); if (ret < 0) return ret; event->format.nr_common = ret; - ret = event_read_fields(event, &event->format.fields); + ret = event_read_fields(event->tep, event, &event->format.fields); if (ret < 0) return ret; event->format.nr_fields = ret; @@ -1920,7 +2011,7 @@ enum tep_event_type type; char *token; - type = read_token(&token); + type = read_token(event->tep, &token); *tok = token; return process_arg_token(event, arg, tok, type); @@ -2026,7 +2117,7 @@ top->op.right = arg; free_token(token); - type = read_token_item(&token); + type = read_token_item(event->tep, &token); *tok = token; return type; @@ -2039,7 +2130,7 @@ static int get_op_prio(char *op) { - if (!op1) { + if (strlen(op) == 1) { switch (op0) { case '~': case '!': @@ -2104,6 +2195,120 @@ return arg->op.prio; } +static int consolidate_op_arg(struct tep_print_arg *arg) +{ + unsigned long long val, left, right; + int ret = 0; + + if (arg->type != TEP_PRINT_OP) + return 0; + + if (arg->op.left) + ret = consolidate_op_arg(arg->op.left); + if (ret < 0) + return ret; + + if (arg->op.right) + ret = consolidate_op_arg(arg->op.right); + if (ret < 0) + return ret; + + if (!arg->op.left || !arg->op.right) + return 0; + + if (arg->op.left->type != TEP_PRINT_ATOM || + arg->op.right->type != TEP_PRINT_ATOM) + return 0; + + /* Two atoms, we can do the operation now. */ + left = strtoull(arg->op.left->atom.atom, NULL, 0); + right = strtoull(arg->op.right->atom.atom, NULL, 0); + + switch (arg->op.op0) { + case '>': + switch (arg->op.op1) { + case '>': + val = left >> right; + break; + case '=': + val = left >= right; + break; + default: + val = left > right; + break; + } + break; + case '<': + switch (arg->op.op1) { + case '<': + val = left << right; + break; + case '=': + val = left <= right; + break; + default: + val = left < right; + break; + } + break; + case '&': + switch (arg->op.op1) { + case '&': + val = left && right; + break; + default: + val = left & right; + break; + } + break; + case '|': + switch (arg->op.op1) { + case '|': + val = left || right; + break; + default: + val = left | right; + break; + } + break; + case '-': + val = left - right; + break; + case '+': + val = left + right; + break; + case '*': + val = left * right; + break; + case '^': + val = left ^ right; + break; + case '/': + val = left / right; + break; + case '%': + val = left % right; + break; + case '=': + /* Only '==' is called here */ + val = left == right; + break; + case '!': + /* Only '!=' is called here. */ + val = left != right; + break; + default: + return 0; + } + + free_arg(arg->op.left); + free_arg(arg->op.right); + + arg->type = TEP_PRINT_ATOM; + free(arg->op.op); + return asprintf(&arg->atom.atom, "%lld", val) < 0 ? -1 : 0; +} + /* Note, *tok does not get freed, but will most likely be saved */ static enum tep_event_type process_op(struct tep_event *event, struct tep_print_arg *arg, char **tok) @@ -2117,10 +2322,6 @@ if (arg->type == TEP_PRINT_OP && !arg->op.left) { /* handle single op */ - if (token1) { - do_warning_event(event, "bad op token %s", token); - goto out_free; - } switch (token0) { case '~': case '!': @@ -2132,6 +2333,10 @@ goto out_free; } + if (token1) { + do_warning_event(event, "bad op token %s", token); + goto out_free; + } /* make an empty left */ left = alloc_arg(); @@ -2163,6 +2368,7 @@ arg->type = TEP_PRINT_OP; arg->op.op = token; arg->op.left = left; + arg->op.right = NULL; arg->op.prio = 0; /* it will set arg->op.right */ @@ -2206,7 +2412,7 @@ goto out_free; } - type = read_token_item(&token); + type = read_token_item(event->tep, &token); *tok = token; /* could just be a type pointer */ @@ -2268,6 +2474,7 @@ arg->type = TEP_PRINT_OP; arg->op.op = token; arg->op.left = left; + arg->op.right = NULL; arg->op.prio = 0; @@ -2311,34 +2518,46 @@ char *field; char *token; - if (read_expected(TEP_EVENT_OP, "->") < 0) - goto out_err; + type = read_token_item(event->tep, &token); + /* + * Check if REC happens to be surrounded by parenthesis, and + * return if that's the case, as "(REC)->" is valid. + * but return TEP_EVENT_ITEM. + */ + if (type == TEP_EVENT_DELIM && strcmp(token, ")") == 0) { + *tok = token; + return TEP_EVENT_ITEM; + } + + if (test_type_token(type, token, TEP_EVENT_OP, "->")) + goto out_free; + + free_token(token); - if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) + if (read_expect_type(event->tep, TEP_EVENT_ITEM, &token) < 0) goto out_free; field = token; arg->type = TEP_PRINT_FIELD; arg->field.name = field; + arg->field.field = tep_find_any_field(event, arg->field.name); + if (is_flag_field) { - arg->field.field = tep_find_any_field(event, arg->field.name); arg->field.field->flags |= TEP_FIELD_IS_FLAG; is_flag_field = 0; } else if (is_symbolic_field) { - arg->field.field = tep_find_any_field(event, arg->field.name); arg->field.field->flags |= TEP_FIELD_IS_SYMBOLIC; is_symbolic_field = 0; } - type = read_token(&token); + type = read_token(event->tep, &token); *tok = token; return type; out_free: free_token(token); - out_err: *tok = NULL; return TEP_EVENT_ERROR; } @@ -2360,19 +2579,31 @@ type = process_arg(event, field, &token); - if (test_type_token(type, token, TEP_EVENT_DELIM, next_token)) { - errno = EINVAL; - ret = -1; - free_arg(field); - goto out_free_token; + /* We do allow operators */ + if (type == TEP_EVENT_OP) { + type = process_op(event, field, &token); + + if (consolidate_op_arg(field) < 0) + type = TEP_EVENT_ERROR; + + if (type == TEP_EVENT_ERROR) + goto out_error; } + if (test_type_token(type, token, TEP_EVENT_DELIM, next_token)) + goto out_error; + *print_arg = field; out_free_token: free_token(token); return ret; +out_error: + errno = EINVAL; + ret = -1; + free_arg(field); + goto out_free_token; } static char *arg_eval (struct tep_print_arg *arg); @@ -2385,6 +2616,10 @@ int len; len = strlen(type); + if (len < 2) { + do_warning("invalid type: %s", type); + return val; + } if (pointer) { @@ -2640,6 +2875,7 @@ case TEP_PRINT_STRING: case TEP_PRINT_BSTRING: case TEP_PRINT_BITMASK: + case TEP_PRINT_CPUMASK: default: do_warning("invalid eval type %d", arg->type); ret = 0; @@ -2669,6 +2905,7 @@ case TEP_PRINT_STRING: case TEP_PRINT_BSTRING: case TEP_PRINT_BITMASK: + case TEP_PRINT_CPUMASK: default: do_warning("invalid eval type %d", arg->type); break; @@ -2688,7 +2925,7 @@ do { free_token(token); - type = read_token_item(&token); + type = read_token_item(event->tep, &token); if (test_type_token(type, token, TEP_EVENT_OP, "{")) break; @@ -2742,7 +2979,7 @@ list = &field->next; free_token(token); - type = read_token_item(&token); + type = read_token_item(event->tep, &token); } while (type == TEP_EVENT_DELIM && strcmp(token, ",") == 0); *tok = token; @@ -2786,10 +3023,10 @@ arg->flags.field = field; - type = read_token_item(&token); + type = read_token_item(event->tep, &token); if (event_item_type(type)) { arg->flags.delim = token; - type = read_token_item(&token); + type = read_token_item(event->tep, &token); } if (test_type_token(type, token, TEP_EVENT_DELIM, ",")) @@ -2800,7 +3037,7 @@ goto out_free; free_token(token); - type = read_token_item(tok); + type = read_token_item(event->tep, tok); return type; out_free_field: @@ -2839,7 +3076,7 @@ goto out_free; free_token(token); - type = read_token_item(tok); + type = read_token_item(event->tep, tok); return type; out_free_field: @@ -2863,7 +3100,7 @@ if (alloc_and_process_delim(event, ")", &arg->hex.size)) goto free_field; - return read_token_item(tok); + return read_token_item(event->tep, tok); free_field: free_arg(arg->hex.field); @@ -2901,7 +3138,7 @@ if (alloc_and_process_delim(event, ")", &arg->int_array.el_size)) goto free_size; - return read_token_item(tok); + return read_token_item(event->tep, tok); free_size: free_arg(arg->int_array.count); @@ -2928,7 +3165,7 @@ * The item within the parenthesis is another field that holds * the index into where the array starts. */ - type = read_token(&token); + type = read_token(event->tep, &token); *tok = token; if (type != TEP_EVENT_ITEM) goto out_free; @@ -2942,11 +3179,11 @@ arg->dynarray.field = field; arg->dynarray.index = 0; - if (read_expected(TEP_EVENT_DELIM, ")") < 0) + if (read_expected(event->tep, TEP_EVENT_DELIM, ")") < 0) goto out_free; free_token(token); - type = read_token_item(&token); + type = read_token_item(event->tep, &token); *tok = token; if (type != TEP_EVENT_OP || strcmp(token, "") != 0) return type; @@ -2967,7 +3204,7 @@ goto out_free_arg; free_token(token); - type = read_token_item(tok); + type = read_token_item(event->tep, tok); return type; out_free_arg: @@ -2986,7 +3223,7 @@ enum tep_event_type type; char *token; - if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) + if (read_expect_type(event->tep, TEP_EVENT_ITEM, &token) < 0) goto out_free; arg->type = TEP_PRINT_DYNAMIC_ARRAY_LEN; @@ -2999,11 +3236,11 @@ arg->dynarray.field = field; arg->dynarray.index = 0; - if (read_expected(TEP_EVENT_DELIM, ")") < 0) + if (read_expected(event->tep, TEP_EVENT_DELIM, ")") < 0) goto out_err; free_token(token); - type = read_token(&token); + type = read_token(event->tep, &token); *tok = token; return type; @@ -3033,11 +3270,22 @@ if (type == TEP_EVENT_ERROR) goto out_free; + /* + * If REC is surrounded by parenthesis, the process_arg() + * will return TEP_EVENT_ITEM with token == ")". In + * this case, we need to continue processing the item + * and return. + */ + if (type == TEP_EVENT_ITEM && strcmp(token, ")") == 0) { + free_token(token); + return process_entry(event, arg, tok); + } + if (test_type_token(type, token, TEP_EVENT_DELIM, ")")) goto out_free; free_token(token); - type = read_token_item(&token); + type = read_token_item(event->tep, &token); /* * If the next token is an item or another open paren, then @@ -3079,23 +3327,23 @@ static enum tep_event_type -process_str(struct tep_event *event __maybe_unused, struct tep_print_arg *arg, - char **tok) +process_str(struct tep_event *event, struct tep_print_arg *arg, char **tok) { enum tep_event_type type; char *token; - if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) + if (read_expect_type(event->tep, TEP_EVENT_ITEM, &token) < 0) goto out_free; arg->type = TEP_PRINT_STRING; arg->string.string = token; arg->string.offset = -1; + arg->string.field = NULL; - if (read_expected(TEP_EVENT_DELIM, ")") < 0) + if (read_expected(event->tep, TEP_EVENT_DELIM, ")") < 0) goto out_err; - type = read_token(&token); + type = read_token(event->tep, &token); *tok = token; return type; @@ -3108,23 +3356,23 @@ } static enum tep_event_type -process_bitmask(struct tep_event *event __maybe_unused, struct tep_print_arg *arg, - char **tok) +process_bitmask(struct tep_event *event, struct tep_print_arg *arg, char **tok) { enum tep_event_type type; char *token; - if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) + if (read_expect_type(event->tep, TEP_EVENT_ITEM, &token) < 0) goto out_free; arg->type = TEP_PRINT_BITMASK; arg->bitmask.bitmask = token; arg->bitmask.offset = -1; + arg->bitmask.field = NULL; - if (read_expected(TEP_EVENT_DELIM, ")") < 0) + if (read_expected(event->tep, TEP_EVENT_DELIM, ")") < 0) goto out_err; - type = read_token(&token); + type = read_token(event->tep, &token); *tok = token; return type; @@ -3136,6 +3384,17 @@ return TEP_EVENT_ERROR; } +static enum tep_event_type +process_cpumask(struct tep_event *event __maybe_unused, struct tep_print_arg *arg, + char **tok) +{ + enum tep_event_type type = process_bitmask(event, arg, tok); + if (type != TEP_EVENT_ERROR) + arg->type = TEP_PRINT_CPUMASK; + + return type; +} + static struct tep_function_handler * find_func_handler(struct tep_handle *tep, char *func_name) { @@ -3215,7 +3474,7 @@ free_token(token); } - type = read_token(&token); + type = read_token(event->tep, &token); *tok = token; return type; @@ -3241,14 +3500,14 @@ free_token(token); /* We don't care what the second parameter is of the __builtin_expect() */ - if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) + if (read_expect_type(event->tep, TEP_EVENT_ITEM, &token) < 0) goto out_free; - if (read_expected(TEP_EVENT_DELIM, ")") < 0) + if (read_expected(event->tep, TEP_EVENT_DELIM, ")") < 0) goto out_free; free_token(token); - type = read_token_item(tok); + type = read_token_item(event->tep, tok); return type; out_free: @@ -3258,6 +3517,97 @@ } static enum tep_event_type +process_sizeof(struct tep_event *event, struct tep_print_arg *arg, char **tok) +{ + struct tep_format_field *field; + enum tep_event_type type; + char *token = NULL; + bool token_has_paren = false; + int ret; + + type = read_token_item(event->tep, &token); + + arg->type = TEP_PRINT_ATOM; + + /* We handle some sizeof types */ + if (strcmp(token, "unsigned") == 0) { + free_token(token); + type = read_token_item(event->tep, &token); + + if (type == TEP_EVENT_ERROR) + goto error; + + /* If it's not an item (like "long") then do not process more */ + if (type != TEP_EVENT_ITEM) + token_has_paren = true; + } + + if (token_has_paren || strcmp(token, "int") == 0) { + arg->atom.atom = strdup("4"); + + } else if (strcmp(token, "long") == 0) { + free_token(token); + type = read_token_item(event->tep, &token); + + if (token && strcmp(token, "long") == 0) { + arg->atom.atom = strdup("8"); + } else { + switch (event->tep->long_size) { + case 4: + arg->atom.atom = strdup("4"); + break; + case 8: + arg->atom.atom = strdup("8"); + break; + default: + /* long size not defined yet, fail to parse it */ + goto error; + } + /* The token is the next token */ + token_has_paren = true; + } + } else if (strcmp(token, "REC") == 0) { + + free_token(token); + type = read_token_item(event->tep, &token); + + if (test_type_token(type, token, TEP_EVENT_OP, "->")) + goto error; + free_token(token); + + if (read_expect_type(event->tep, TEP_EVENT_ITEM, &token) < 0) + goto error; + + field = tep_find_any_field(event, token); + /* Can't handle arrays (yet) */ + if (!field || field->flags & TEP_FIELD_IS_ARRAY) + goto error; + + ret = asprintf(&arg->atom.atom, "%d", field->size); + if (ret < 0) + goto error; + + } else { + goto error; + } + + if (!token_has_paren) { + /* The token contains the last item before the parenthesis */ + free_token(token); + type = read_token_item(event->tep, &token); + } + if (test_type_token(type, token, TEP_EVENT_DELIM, ")")) + goto error; + + free_token(token); + return read_token_item(event->tep, tok); +error: + free_token(token); + *tok = NULL; + return TEP_EVENT_ERROR; +} + +static enum tep_event_type process_function(struct tep_event *event, struct tep_print_arg *arg, char *token, char **tok) { @@ -3285,19 +3635,30 @@ free_token(token); return process_int_array(event, arg, tok); } - if (strcmp(token, "__get_str") == 0) { + if (strcmp(token, "__get_str") == 0 || + strcmp(token, "__get_rel_str") == 0) { free_token(token); return process_str(event, arg, tok); } - if (strcmp(token, "__get_bitmask") == 0) { + if (strcmp(token, "__get_bitmask") == 0 || + strcmp(token, "__get_rel_bitmask") == 0) { free_token(token); return process_bitmask(event, arg, tok); } - if (strcmp(token, "__get_dynamic_array") == 0) { + if (strcmp(token, "__get_cpumask") == 0 || + strcmp(token, "__get_rel_cpumask") == 0) { + free_token(token); + return process_cpumask(event, arg, tok); + } + if (strcmp(token, "__get_dynamic_array") == 0 || + strcmp(token, "__get_rel_dynamic_array") == 0 || + strcmp(token, "__get_sockaddr") == 0 || + strcmp(token, "__get_sockaddr_rel") == 0) { free_token(token); return process_dynamic_array(event, arg, tok); } - if (strcmp(token, "__get_dynamic_array_len") == 0) { + if (strcmp(token, "__get_dynamic_array_len") == 0 || + strcmp(token, "__get_rel_dynamic_array_len") == 0) { free_token(token); return process_dynamic_array_len(event, arg, tok); } @@ -3305,6 +3666,10 @@ free_token(token); return process_builtin_expect(event, arg, tok); } + if (strcmp(token, "sizeof") == 0) { + free_token(token); + return process_sizeof(event, arg, tok); + } func = find_func_handler(event->tep, token); if (func) { @@ -3335,7 +3700,7 @@ } atom = token; /* test the next token */ - type = read_token_item(&token); + type = read_token_item(event->tep, &token); /* * If the next token is a parenthesis, then this @@ -3360,7 +3725,7 @@ return TEP_EVENT_ERROR; } free_token(token); - type = read_token_item(&token); + type = read_token_item(event->tep, &token); } arg->type = TEP_PRINT_ATOM; @@ -3371,7 +3736,7 @@ case TEP_EVENT_SQUOTE: arg->type = TEP_PRINT_ATOM; arg->atom.atom = token; - type = read_token_item(&token); + type = read_token_item(event->tep, &token); break; case TEP_EVENT_DELIM: if (strcmp(token, "(") == 0) { @@ -3412,7 +3777,7 @@ do { if (type == TEP_EVENT_NEWLINE) { - type = read_token_item(&token); + type = read_token_item(event->tep, &token); continue; } @@ -3437,6 +3802,10 @@ if (type == TEP_EVENT_OP) { type = process_op(event, arg, &token); free_token(token); + + if (consolidate_op_arg(arg) < 0) + type = TEP_EVENT_ERROR; + if (type == TEP_EVENT_ERROR) { *list = NULL; free_arg(arg); @@ -3467,16 +3836,16 @@ char *token; int ret; - if (read_expected_item(TEP_EVENT_ITEM, "print") < 0) + if (read_expected_item(event->tep, TEP_EVENT_ITEM, "print") < 0) return -1; - if (read_expected(TEP_EVENT_ITEM, "fmt") < 0) + if (read_expected(event->tep, TEP_EVENT_ITEM, "fmt") < 0) return -1; - if (read_expected(TEP_EVENT_OP, ":") < 0) + if (read_expected(event->tep, TEP_EVENT_OP, ":") < 0) return -1; - if (read_expect_type(TEP_EVENT_DQUOTE, &token) < 0) + if (read_expect_type(event->tep, TEP_EVENT_DQUOTE, &token) < 0) goto fail; concat: @@ -3484,7 +3853,7 @@ event->print_fmt.args = NULL; /* ok to have no arg */ - type = read_token_item(&token); + type = read_token_item(event->tep, &token); if (type == TEP_EVENT_NONE) return 0; @@ -3835,6 +4204,68 @@ return val; } +#define TEP_OFFSET_LEN_MASK 0xffff +#define TEP_LEN_SHIFT 16 + +static void dynamic_offset(struct tep_handle *tep, int size, void *data, + int data_size, unsigned int *offset, unsigned int *len) +{ + unsigned long long val; + unsigned int o, l; + + /* + * The total allocated length of the dynamic array is + * stored in the top half of the field and the offset + * is in the bottom half of the 32 bit field. + */ + val = tep_read_number(tep, data, size); + + /* Check for overflows */ + o = (unsigned int)(val & TEP_OFFSET_LEN_MASK); + + /* If there's no length, then just make the length the size of the data */ + if (size == 2) + l = data_size - o; + else + l = (unsigned int)((val >> TEP_LEN_SHIFT) & TEP_OFFSET_LEN_MASK); + + if (offset) + *offset = o > data_size ? 0 : o; + if (len) + *len = o + l > data_size ? 0 : l; +} + +static inline void dynamic_offset_field(struct tep_handle *tep, + struct tep_format_field *field, + void *data, int size, + unsigned int *offset, + unsigned int *len) +{ + /* Test for overflow */ + if (field->offset + field->size > size) { + if (offset) + *offset = 0; + if (len) + *len = 0; + return; + } + dynamic_offset(tep, field->size, data + field->offset, size, offset, len); + if (field->flags & TEP_FIELD_IS_RELATIVE) + *offset += field->offset + field->size; +} + +static bool check_data_offset_size(struct tep_event *event, const char *field_name, + int data_size, int field_offset, int field_size) +{ + /* Check to make sure the field is within the data */ + if (field_offset + field_size <= data_size) + return false; + + tep_warning("Event '%s' field '%s' goes beyond the size of the event (%d > %d)", + event->name, field_name, field_offset + field_size, data_size); + return true; +} + static unsigned long long eval_num_arg(void *data, int size, struct tep_event *event, struct tep_print_arg *arg) { @@ -3843,7 +4274,7 @@ unsigned long long left, right; struct tep_print_arg *typearg = NULL; struct tep_print_arg *larg; - unsigned long offset; + unsigned int offset; unsigned int field_size; switch (arg->type) { @@ -3860,7 +4291,12 @@ arg->field.field = tep_find_any_field(event, arg->field.name); if (!arg->field.field) goto out_warning_field; - + } + if (check_data_offset_size(event, arg->field.name, size, + arg->field.field->offset, + arg->field.field->size)) { + val = 0; + break; } /* must be a number */ val = tep_read_number(tep, data + arg->field.field->offset, @@ -3878,6 +4314,7 @@ case TEP_PRINT_STRING: case TEP_PRINT_BSTRING: case TEP_PRINT_BITMASK: + case TEP_PRINT_CPUMASK: return 0; case TEP_PRINT_FUNC: { struct trace_seq s; @@ -3907,18 +4344,11 @@ switch (larg->type) { case TEP_PRINT_DYNAMIC_ARRAY: - offset = tep_read_number(tep, - data + larg->dynarray.field->offset, - larg->dynarray.field->size); + dynamic_offset_field(tep, larg->dynarray.field, data, + size, &offset, NULL); + offset += right; if (larg->dynarray.field->elementsize) field_size = larg->dynarray.field->elementsize; - /* - * The actual length of the dynamic array is stored - * in the top half of the field, and the offset - * is in the bottom half of the 32 bit field. - */ - offset &= 0xffff; - offset += right; break; case TEP_PRINT_FIELD: if (!larg->field.field) { @@ -3936,6 +4366,11 @@ default: goto default_op; /* oops, all bets off */ } + if (check_data_offset_size(event, arg->field.name, size, + offset, field_size)) { + val = 0; + break; + } val = tep_read_number(tep, data + offset, field_size); if (typearg) @@ -4037,28 +4472,20 @@ } break; case TEP_PRINT_DYNAMIC_ARRAY_LEN: - offset = tep_read_number(tep, - data + arg->dynarray.field->offset, - arg->dynarray.field->size); - /* - * The total allocated length of the dynamic array is - * stored in the top half of the field, and the offset - * is in the bottom half of the 32 bit field. - */ - val = (unsigned long long)(offset >> 16); + dynamic_offset_field(tep, arg->dynarray.field, data, size, + NULL, &field_size); + val = field_size; break; case TEP_PRINT_DYNAMIC_ARRAY: /* Without , we pass the address to the dynamic data */ - offset = tep_read_number(tep, - data + arg->dynarray.field->offset, - arg->dynarray.field->size); - /* - * The total allocated length of the dynamic array is - * stored in the top half of the field, and the offset - * is in the bottom half of the 32 bit field. - */ - offset &= 0xffff; - val = (unsigned long long)((unsigned long)data + offset); + dynamic_offset_field(tep, arg->dynarray.field, data, size, + &offset, NULL); + if (check_data_offset_size(event, arg->field.name, size, + offset, 0)) { + val = (unsigned long)data; + break; + } + val = (unsigned long)data + offset; break; default: /* not sure what to do there */ return 0; @@ -4178,6 +4605,161 @@ free(str); } +#define log10(n) \ +( \ + n < 10UL ? 0 : \ + n < 100UL ? 1 : \ + n < 1000UL ? 2 : \ + n < 10000UL ? 3 : \ + n < 100000UL ? 4 : \ + n < 1000000UL ? 5 : \ + n < 10000000UL ? 6 : \ + n < 100000000UL ? 7 : \ + n < 1000000000UL ? 8 : \ + 9 \ +) + +/* ilog10(0) should be 1 but the 0 simplifies below math */ +#define ilog10(n) \ +( \ + n == 0 ? 0UL : \ + n == 1 ? 10UL : \ + n == 2 ? 100UL : \ + n == 3 ? 1000UL : \ + n == 4 ? 10000UL : \ + n == 5 ? 100000UL : \ + n == 6 ? 1000000UL : \ + n == 7 ? 10000000UL : \ + n == 8 ? 100000000UL : \ + 1000000000UL \ +) + +static unsigned int cpumask_worst_size(unsigned int nr_bits) +{ + /* + * Printing all the CPUs separated by a comma is a decent bound for the + * maximum memory required to print a cpumask (a slightly better bound + * is chunks of 2 bits set, i.e. 0-1,3-4,6-7...). + * + * e.g. for nr_bits=132: + * - 131 commas + * - 10 * 1 chars for CPUS 0, 9 + * - 90 * 2 chars for CPUS 10-99 + * - 32 * 3 chars for CPUS 100-131 + */ + unsigned int last_cpu = nr_bits - 1; + unsigned int nr_chars = nr_bits - 1; + int last_lvl = log10(last_cpu); + + /* All log10 levels before the last one have all values used */ + for (int lvl = 0; lvl < last_lvl; lvl++) { + int nr_values = ilog10(lvl + 1) - ilog10(lvl); + + nr_chars += nr_values * (lvl + 1); + } + /* Last level is incomplete */ + nr_chars += (nr_bits - ilog10(last_lvl)) * (last_lvl + 1); + + return nr_chars; +} + +static void print_cpumask_to_seq(struct tep_handle *tep, + struct trace_seq *s, const char *format, + int len_arg, const void *data, int size) +{ + int firstone = -1, firstzero = -1; + int nr_bits = size * 8; + bool first = true; + int str_size = 0; + char buf12; /* '-' + log10(2^32) + 1 digits + '\0' */ + char *str; + int index; + int i; + + str = malloc(cpumask_worst_size(nr_bits) + 1); + if (!str) { + do_warning("%s: not enough memory!", __func__); + return; + } + + for (i = 0; i < size; i++) { + unsigned char byte; + int fmtsize; + + if (tep->file_bigendian) + index = size - (i + 1); + else + index = i; + + /* Byte by byte scan, not the best... */ + byte = *(((unsigned char *)data) + index); +more: + /* First find a bit set to one...*/ + if (firstone < 0 && byte) { + /* + * Set all lower bits, so a later ffz on this same byte + * is guaranteed to find a later bit. + */ + firstone = ffs(byte) - 1; + byte |= (1 << firstone) - 1; + firstone += i * 8; + } + + if (firstone < 0) + continue; + + /* ...Then find a bit set to zero */ + if ((~byte) & 0xFF) { + /* + * Clear all lower bits, so a later ffs on this same + * byte is guaranteed to find a later bit. + */ + firstzero = ffs(~byte) - 1; + byte &= ~((1 << (firstzero)) - 1); + firstzero += i * 8; + } else if (i == size - 1) { /* ...Or reach the end of the mask */ + firstzero = nr_bits; + byte = 0; + } else { + continue; + } + + /* We've found a bit set to one, and a later bit set to zero. */ + if (!first) { + strstr_size = ','; + str_size++; + } + first = false; + + /* It takes {log10(number) + 1} chars to format a number */ + fmtsize = log10(firstone) + 1; + snprintf(buf, fmtsize + 1, "%d", firstone); + memcpy(str + str_size, buf, fmtsize); + str_size += fmtsize; + + if (firstzero > firstone + 1) { + fmtsize = log10(firstzero - 1) + 2; + snprintf(buf, fmtsize + 1, "-%d", firstzero - 1); + memcpy(str + str_size, buf, fmtsize); + str_size += fmtsize; + } + + firstzero = firstone = -1; + if (byte) + goto more; + } + + strstr_size = 0; + str_size++; + + if (len_arg >= 0) + trace_seq_printf(s, format, len_arg, str); + else + trace_seq_printf(s, format, str); + + free(str); +} + static void print_str_arg(struct trace_seq *s, void *data, int size, struct tep_event *event, const char *format, int len_arg, struct tep_print_arg *arg) @@ -4186,12 +4768,13 @@ struct tep_print_flag_sym *flag; struct tep_format_field *field; struct printk_map *printk; + unsigned int offset, len; long long val, fval; unsigned long long addr; char *str; unsigned char *hex; int print; - int i, len; + int i; switch (arg->type) { case TEP_PRINT_NULL: @@ -4295,11 +4878,9 @@ case TEP_PRINT_HEX: case TEP_PRINT_HEX_STR: if (arg->hex.field->type == TEP_PRINT_DYNAMIC_ARRAY) { - unsigned long offset; - offset = tep_read_number(tep, - data + arg->hex.field->dynarray.field->offset, - arg->hex.field->dynarray.field->size); - hex = data + (offset & 0xffff); + dynamic_offset_field(tep, arg->hex.field->dynarray.field, data, + size, &offset, NULL); + hex = data + offset; } else { field = arg->hex.field->field.field; if (!field) { @@ -4324,13 +4905,9 @@ int el_size; if (arg->int_array.field->type == TEP_PRINT_DYNAMIC_ARRAY) { - unsigned long offset; - struct tep_format_field *field = - arg->int_array.field->dynarray.field; - offset = tep_read_number(tep, - data + field->offset, - field->size); - num = data + (offset & 0xffff); + dynamic_offset_field(tep, arg->int_array.field->dynarray.field, data, + size, &offset, NULL); + num = data + offset; } else { field = arg->int_array.field->field.field; if (!field) { @@ -4370,37 +4947,44 @@ case TEP_PRINT_TYPE: break; case TEP_PRINT_STRING: { - int str_offset; - - if (arg->string.offset == -1) { - struct tep_format_field *f; - - f = tep_find_any_field(event, arg->string.string); - arg->string.offset = f->offset; + if (!arg->string.field) { + arg->string.field = tep_find_any_field(event, arg->string.string); + if (!arg->string.field) + break; + arg->string.offset = arg->string.field->offset; } - str_offset = data2host4(tep, *(unsigned int *)(data + arg->string.offset)); - str_offset &= 0xffff; - print_str_to_seq(s, format, len_arg, ((char *)data) + str_offset); + dynamic_offset_field(tep, arg->string.field, data, size, &offset, &len); + /* Do not attempt to save zero length dynamic strings */ + if (!len) + break; + print_str_to_seq(s, format, len_arg, ((char *)data) + offset); break; } case TEP_PRINT_BSTRING: print_str_to_seq(s, format, len_arg, arg->string.string); break; case TEP_PRINT_BITMASK: { - int bitmask_offset; - int bitmask_size; - - if (arg->bitmask.offset == -1) { - struct tep_format_field *f; - - f = tep_find_any_field(event, arg->bitmask.bitmask); - arg->bitmask.offset = f->offset; + if (!arg->bitmask.field) { + arg->bitmask.field = tep_find_any_field(event, arg->bitmask.bitmask); + if (!arg->bitmask.field) + break; + arg->bitmask.offset = arg->bitmask.field->offset; } - bitmask_offset = data2host4(tep, *(unsigned int *)(data + arg->bitmask.offset)); - bitmask_size = bitmask_offset >> 16; - bitmask_offset &= 0xffff; + dynamic_offset_field(tep, arg->bitmask.field, data, size, &offset, &len); print_bitmask_to_seq(tep, s, format, len_arg, - data + bitmask_offset, bitmask_size); + data + offset, len); + break; + } + case TEP_PRINT_CPUMASK: { + if (!arg->bitmask.field) { + arg->bitmask.field = tep_find_any_field(event, arg->bitmask.bitmask); + arg->bitmask.offset = arg->bitmask.field->offset; + } + if (!arg->bitmask.field) + break; + dynamic_offset_field(tep, arg->bitmask.field, data, size, &offset, &len); + print_cpumask_to_seq(tep, s, format, len_arg, + data + offset, len); break; } case TEP_PRINT_OP: @@ -4595,10 +5179,9 @@ ls = 2; goto process_again; case '0' ... '9': - goto process_again; case '.': - goto process_again; case '#': + case '+': goto process_again; case 'z': case 'Z': @@ -4701,8 +5284,10 @@ arg->next = NULL; arg->type = TEP_PRINT_BSTRING; arg->string.string = strdup(bptr); - if (!arg->string.string) + if (!arg->string.string) { + free(arg); goto out_free; + } bptr += strlen(bptr) + 1; *next = arg; next = &arg->next; @@ -4769,6 +5354,10 @@ return 0; } + /* evaluate if the arg has a type cast */ + while (arg->type == TEP_PRINT_TYPE) + arg = arg->typecast.item; + if (arg->type != TEP_PRINT_FIELD) { trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type); @@ -4977,6 +5566,10 @@ return ret; } + /* evaluate if the arg has a type cast */ + while (arg->type == TEP_PRINT_TYPE) + arg = arg->typecast.item; + if (arg->type != TEP_PRINT_FIELD) { trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type); return ret; @@ -5024,6 +5617,10 @@ return rc; } + /* evaluate if the arg has a type cast */ + while (arg->type == TEP_PRINT_TYPE) + arg = arg->typecast.item; + if (arg->type != TEP_PRINT_FIELD) { trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type); return rc; @@ -5062,6 +5659,8 @@ unsigned char *buf; struct sockaddr_storage *sa; bool reverse = false; + unsigned int offset; + unsigned int len; int rc = 0; int ret; @@ -5087,27 +5686,42 @@ return rc; } - if (arg->type != TEP_PRINT_FIELD) { - trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type); - return rc; - } + /* evaluate if the arg has a type cast */ + while (arg->type == TEP_PRINT_TYPE) + arg = arg->typecast.item; + + if (arg->type == TEP_PRINT_FIELD) { - if (!arg->field.field) { - arg->field.field = - tep_find_any_field(event, arg->field.name); if (!arg->field.field) { - do_warning("%s: field %s not found", - __func__, arg->field.name); - return rc; + arg->field.field = + tep_find_any_field(event, arg->field.name); + if (!arg->field.field) { + do_warning("%s: field %s not found", + __func__, arg->field.name); + return rc; + } } + + offset = arg->field.field->offset; + len = arg->field.field->size; + + } else if (arg->type == TEP_PRINT_DYNAMIC_ARRAY) { + + dynamic_offset_field(event->tep, arg->dynarray.field, data, + size, &offset, &len); + + } else { + trace_seq_printf(s, "ARG NOT FIELD NOR DYNAMIC ARRAY BUT TYPE %d", + arg->type); + return rc; } - sa = (struct sockaddr_storage *) (data + arg->field.field->offset); + sa = (struct sockaddr_storage *)(data + offset); if (sa->ss_family == AF_INET) { struct sockaddr_in *sa4 = (struct sockaddr_in *) sa; - if (arg->field.field->size < sizeof(struct sockaddr_in)) { + if (len < sizeof(struct sockaddr_in)) { trace_seq_printf(s, "INVALIDIPv4"); return rc; } @@ -5120,7 +5734,7 @@ } else if (sa->ss_family == AF_INET6) { struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) sa; - if (arg->field.field->size < sizeof(struct sockaddr_in6)) { + if (len < sizeof(struct sockaddr_in6)) { trace_seq_printf(s, "INVALIDIPv6"); return rc; } @@ -5202,6 +5816,10 @@ return ret; } + /* evaluate if the arg has a type cast */ + while (arg->type == TEP_PRINT_TYPE) + arg = arg->typecast.item; + if (arg->type != TEP_PRINT_FIELD) { trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type); return ret; @@ -5243,13 +5861,12 @@ void *data, int size, struct tep_event *event, struct tep_print_arg *arg, int print_len) { + unsigned int offset, arr_len; int plen = print_len; char *delim = " "; int ret = 0; char *buf; int i; - unsigned long offset; - int arr_len; switch (*(ptr + 1)) { case 'C': @@ -5276,11 +5893,9 @@ return ret; } - offset = tep_read_number(event->tep, - data + arg->dynarray.field->offset, - arg->dynarray.field->size); - arr_len = (unsigned long long)(offset >> 16); - buf = data + (offset & 0xffff); + dynamic_offset_field(event->tep, arg->dynarray.field, data, size, + &offset, &arr_len); + buf = data + offset; if (arr_len < plen) plen = arr_len; @@ -5305,21 +5920,19 @@ return 1; } -void tep_print_field(struct trace_seq *s, void *data, - struct tep_format_field *field) +static void print_field_raw(struct trace_seq *s, void *data, int size, + struct tep_format_field *field) { - unsigned long long val; - unsigned int offset, len, i; struct tep_handle *tep = field->event->tep; + unsigned int offset, len, i; + unsigned long long val; if (field->flags & TEP_FIELD_IS_ARRAY) { - offset = field->offset; - len = field->size; if (field->flags & TEP_FIELD_IS_DYNAMIC) { - val = tep_read_number(tep, data + offset, len); - offset = val; - len = offset >> 16; - offset &= 0xffff; + dynamic_offset_field(tep, field, data, size, &offset, &len); + } else { + offset = field->offset; + len = field->size; } if (field->flags & TEP_FIELD_IS_STRING && is_printable_array(data + offset, len)) { @@ -5368,21 +5981,158 @@ trace_seq_printf(s, "%llu", val); } } + trace_seq_terminate(s); } -void tep_print_fields(struct trace_seq *s, void *data, - int size __maybe_unused, struct tep_event *event) +static int print_parse_data(struct tep_print_parse *parse, struct trace_seq *s, + void *data, int size, struct tep_event *event); + +static inline void print_field(struct trace_seq *s, void *data, int size, + struct tep_format_field *field, + struct tep_print_parse **parse_ptr) +{ + struct tep_event *event = field->event; + struct tep_print_parse *start_parse; + struct tep_print_parse *parse; + struct tep_print_arg *arg; + bool has_0x = false; + + parse = parse_ptr ? *parse_ptr : event->print_fmt.print_cache; + + if (!parse || event->flags & TEP_EVENT_FL_FAILED) + goto out; + + if (field->flags & (TEP_FIELD_IS_ARRAY | TEP_FIELD_IS_STRING)) + goto out; + + start_parse = parse; + do { + if (parse->type == PRINT_FMT_STRING) { + int len = strlen(parse->format); + + if (len > 1 && + strcmp(parse->format + (len -2), "0x") == 0) + has_0x = true; + else + has_0x = false; + + goto next; + } + + arg = parse->arg; + + while (arg && arg->type == TEP_PRINT_TYPE) + arg = arg->typecast.item; + + if (!arg || arg->type != TEP_PRINT_FIELD || + arg->field.field != field) { + has_0x = false; + goto next; + } + + if (has_0x) + trace_seq_puts(s, "0x"); + + print_parse_data(parse, s, data, size, event); + + if (parse_ptr) + *parse_ptr = parse->next; + + return; + + next: + parse = parse->next ? parse->next : + event->print_fmt.print_cache; + } while (parse != start_parse); + + out: + /* Not found. */ + print_field_raw(s, data, size, field); +} + +/** + * tep_print_field_content - write out the raw content of a field + * @s: The trace_seq to write the content into + * @data: The payload to extract the field from. + * @size: The size of the payload. + * @field: The field to extract + * + * Use @field to find the field content from within @data and write it + * in human readable format into @s. + * + * It will not write anything on error (s->len will not move) + */ +void tep_print_field_content(struct trace_seq *s, void *data, int size, + struct tep_format_field *field) +{ + print_field(s, data, size, field, NULL); +} + +/** DEPRECATED **/ +void tep_print_field(struct trace_seq *s, void *data, + struct tep_format_field *field) { + /* unsafe to use, should pass in size */ + print_field(s, data, 4096, field, NULL); +} + +static inline void +print_selected_fields(struct trace_seq *s, void *data, int size, + struct tep_event *event, + unsigned long long ignore_mask) +{ + struct tep_print_parse *parse = event->print_fmt.print_cache; struct tep_format_field *field; + unsigned long long field_mask = 1; field = event->format.fields; - while (field) { + for(; field; field = field->next, field_mask <<= 1) { + if (field_mask & ignore_mask) + continue; + trace_seq_printf(s, " %s=", field->name); - tep_print_field(s, data, field); - field = field->next; + print_field(s, data, size, field, &parse); } } +void tep_print_fields(struct trace_seq *s, void *data, + int size, struct tep_event *event) +{ + print_selected_fields(s, data, size, event, 0); +} + +/** + * tep_record_print_fields - print the field name followed by the + * record's field value. + * @s: The seq to print to + * @record: The record to get the event from + * @event: The event that the field is for + */ +void tep_record_print_fields(struct trace_seq *s, + struct tep_record *record, + struct tep_event *event) +{ + print_selected_fields(s, record->data, record->size, event, 0); +} + +/** + * tep_record_print_selected_fields - print the field name followed by the + * record's field value for a selected subset of record fields. + * @s: The seq to print to + * @record: The record to get the event from + * @event: The event that the field is for + * @select_mask: Bit mask defining the fields to print + */ +void tep_record_print_selected_fields(struct trace_seq *s, + struct tep_record *record, + struct tep_event *event, + unsigned long long select_mask) +{ + unsigned long long ignore_mask = ~select_mask; + + print_selected_fields(s, record->data, record->size, event, ignore_mask); +} + static int print_function(struct trace_seq *s, const char *format, void *data, int size, struct tep_event *event, struct tep_print_arg *arg) @@ -5685,11 +6435,14 @@ case 'L': ls = 2; break; - case '.': case 'z': case 'Z': + ls = 1; + break; + case '.': case '0' ... '9': case '-': + case '+': break; case '*': /* The argument is the length. */ @@ -5733,6 +6486,7 @@ *arg = (*arg)->next; ret++; return ret; + case 'c': case 'd': case 'u': case 'i': @@ -5889,35 +6643,45 @@ return parse_ret; } -static void print_event_cache(struct tep_print_parse *parse, struct trace_seq *s, - void *data, int size, struct tep_event *event) +static int print_parse_data(struct tep_print_parse *parse, struct trace_seq *s, + void *data, int size, struct tep_event *event) { int len_arg; + if (parse->len_as_arg) + len_arg = eval_num_arg(data, size, event, parse->len_as_arg); + + switch (parse->type) { + case PRINT_FMT_ARG_DIGIT: + print_arg_number(s, parse->format, + parse->len_as_arg ? len_arg : -1, data, + size, parse->ls, event, parse->arg); + break; + case PRINT_FMT_ARG_POINTER: + print_arg_pointer(s, parse->format, + parse->len_as_arg ? len_arg : 1, + data, size, event, parse->arg); + break; + case PRINT_FMT_ARG_STRING: + print_arg_string(s, parse->format, + parse->len_as_arg ? len_arg : -1, + data, size, event, parse->arg); + break; + case PRINT_FMT_STRING: + default: + trace_seq_printf(s, "%s", parse->format); + /* Return 1 on non field. */ + return 1; + } + /* Return 0 on field being processed. */ + return 0; +} + +static void print_event_cache(struct tep_print_parse *parse, struct trace_seq *s, + void *data, int size, struct tep_event *event) +{ while (parse) { - if (parse->len_as_arg) - len_arg = eval_num_arg(data, size, event, parse->len_as_arg); - switch (parse->type) { - case PRINT_FMT_ARG_DIGIT: - print_arg_number(s, parse->format, - parse->len_as_arg ? len_arg : -1, data, - size, parse->ls, event, parse->arg); - break; - case PRINT_FMT_ARG_POINTER: - print_arg_pointer(s, parse->format, - parse->len_as_arg ? len_arg : 1, - data, size, event, parse->arg); - break; - case PRINT_FMT_ARG_STRING: - print_arg_string(s, parse->format, - parse->len_as_arg ? len_arg : -1, - data, size, event, parse->arg); - break; - case PRINT_FMT_STRING: - default: - trace_seq_printf(s, "%s", parse->format); - break; - } + print_parse_data(parse, s, data, size, event); parse = parse->next; } } @@ -6007,8 +6771,13 @@ (hardirq && softirq) ? 'H' : hardirq ? 'h' : softirq ? 's' : '.'); - if (pc) - trace_seq_printf(&sq, "%x", pc); + if (pc & 0xf) + trace_seq_printf(&sq, "%x", pc & 0xf); + else + trace_seq_printf(&sq, "."); + + if (pc & 0xf0) + trace_seq_printf(&sq, "%x", pc >> 4); else trace_seq_printf(&sq, "."); @@ -6103,6 +6872,21 @@ return comm; } +/** + * tep_record_is_event - return true if the given record is the given event + * @record: The record to see is the @event + * @event: The event to test against @record + * + * Returns true if the record is of the given event, false otherwise + */ +bool tep_record_is_event(struct tep_record *record, struct tep_event *event) +{ + int type; + + type = tep_data_type(event->tep, record); + return event->id == type; +} + static struct tep_cmdline * pid_from_cmdlist(struct tep_handle *tep, const char *comm, struct tep_cmdline *next) { @@ -6390,17 +7174,23 @@ struct tep_record *record, const char *fmt, ...) { struct print_event_type type; - char *format = strdup(fmt); - char *current = format; - char *str = format; + struct tep_event *event; + char *current; + char *format; + char *str; int offset; va_list args; - struct tep_event *event; + event = tep_find_event_by_record(tep, record); + if (!event) { + trace_seq_printf(s, "UNKNOWN EVENT"); + return; + } + + str = current = format = strdup(fmt); if (!format) return; - event = tep_find_event_by_record(tep, record); va_start(args, fmt); while (*current) { current = strchr(str, '%'); @@ -6728,6 +7518,9 @@ case TEP_PRINT_BITMASK: printf("__get_bitmask(%s)", args->bitmask.bitmask); break; + case TEP_PRINT_CPUMASK: + printf("__get_cpumask(%s)", args->bitmask.bitmask); + break; case TEP_PRINT_TYPE: printf("(%s)", args->typecast.type); print_args(args->typecast.item); @@ -6753,7 +7546,7 @@ } } -static void parse_header_field(const char *field, +static void parse_header_field(struct tep_handle *tep, const char *field, int *offset, int *size, int mandatory) { unsigned long long save_input_buf_ptr; @@ -6761,16 +7554,16 @@ char *token; int type; - save_input_buf_ptr = input_buf_ptr; - save_input_buf_siz = input_buf_siz; + save_input_buf_ptr = tep->input_buf_ptr; + save_input_buf_siz = tep->input_buf_siz; - if (read_expected(TEP_EVENT_ITEM, "field") < 0) + if (read_expected(tep, TEP_EVENT_ITEM, "field") < 0) return; - if (read_expected(TEP_EVENT_OP, ":") < 0) + if (read_expected(tep, TEP_EVENT_OP, ":") < 0) return; /* type */ - if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) + if (read_expect_type(tep, TEP_EVENT_ITEM, &token) < 0) goto fail; free_token(token); @@ -6778,39 +7571,39 @@ * If this is not a mandatory field, then test it first. */ if (mandatory) { - if (read_expected(TEP_EVENT_ITEM, field) < 0) + if (read_expected(tep, TEP_EVENT_ITEM, field) < 0) return; } else { - if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) + if (read_expect_type(tep, TEP_EVENT_ITEM, &token) < 0) goto fail; if (strcmp(token, field) != 0) goto discard; free_token(token); } - if (read_expected(TEP_EVENT_OP, ";") < 0) + if (read_expected(tep, TEP_EVENT_OP, ";") < 0) return; - if (read_expected(TEP_EVENT_ITEM, "offset") < 0) + if (read_expected(tep, TEP_EVENT_ITEM, "offset") < 0) return; - if (read_expected(TEP_EVENT_OP, ":") < 0) + if (read_expected(tep, TEP_EVENT_OP, ":") < 0) return; - if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) + if (read_expect_type(tep, TEP_EVENT_ITEM, &token) < 0) goto fail; *offset = atoi(token); free_token(token); - if (read_expected(TEP_EVENT_OP, ";") < 0) + if (read_expected(tep, TEP_EVENT_OP, ";") < 0) return; - if (read_expected(TEP_EVENT_ITEM, "size") < 0) + if (read_expected(tep, TEP_EVENT_ITEM, "size") < 0) return; - if (read_expected(TEP_EVENT_OP, ":") < 0) + if (read_expected(tep, TEP_EVENT_OP, ":") < 0) return; - if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) + if (read_expect_type(tep, TEP_EVENT_ITEM, &token) < 0) goto fail; *size = atoi(token); free_token(token); - if (read_expected(TEP_EVENT_OP, ";") < 0) + if (read_expected(tep, TEP_EVENT_OP, ";") < 0) return; - type = read_token(&token); + type = read_token(tep, &token); if (type != TEP_EVENT_NEWLINE) { /* newer versions of the kernel have a "signed" type */ if (type != TEP_EVENT_ITEM) @@ -6821,17 +7614,17 @@ free_token(token); - if (read_expected(TEP_EVENT_OP, ":") < 0) + if (read_expected(tep, TEP_EVENT_OP, ":") < 0) return; - if (read_expect_type(TEP_EVENT_ITEM, &token)) + if (read_expect_type(tep, TEP_EVENT_ITEM, &token)) goto fail; free_token(token); - if (read_expected(TEP_EVENT_OP, ";") < 0) + if (read_expected(tep, TEP_EVENT_OP, ";") < 0) return; - if (read_expect_type(TEP_EVENT_NEWLINE, &token)) + if (read_expect_type(tep, TEP_EVENT_NEWLINE, &token)) goto fail; } fail: @@ -6839,8 +7632,8 @@ return; discard: - input_buf_ptr = save_input_buf_ptr; - input_buf_siz = save_input_buf_siz; + tep->input_buf_ptr = save_input_buf_ptr; + tep->input_buf_siz = save_input_buf_siz; *offset = 0; *size = 0; free_token(token); @@ -6871,18 +7664,19 @@ tep->header_page_ts_size = sizeof(long long); tep->header_page_size_size = long_size; tep->header_page_data_offset = sizeof(long long) + long_size; + tep->header_page_data_size = getpagesize() - tep->header_page_data_offset; tep->old_format = 1; return -1; } - init_input_buf(buf, size); + init_input_buf(tep, buf, size); - parse_header_field("timestamp", &tep->header_page_ts_offset, + parse_header_field(tep, "timestamp", &tep->header_page_ts_offset, &tep->header_page_ts_size, 1); - parse_header_field("commit", &tep->header_page_size_offset, + parse_header_field(tep, "commit", &tep->header_page_size_offset, &tep->header_page_size_size, 1); - parse_header_field("overwrite", &tep->header_page_overwrite, + parse_header_field(tep, "overwrite", &tep->header_page_overwrite, &ignore, 0); - parse_header_field("data", &tep->header_page_data_offset, + parse_header_field(tep, "data", &tep->header_page_data_offset, &tep->header_page_data_size, 1); return 0; @@ -6927,8 +7721,8 @@ if (!(*next)) return 0; - pr_stat("overriding event (%d) %s:%s with new print handler", - event->id, event->system, event->name); + tep_info("overriding event (%d) %s:%s with new print handler", + event->id, event->system, event->name); event->handler = handle->func; event->context = handle->context; @@ -6959,13 +7753,13 @@ struct tep_event *event; int ret; - init_input_buf(buf, size); + init_input_buf(tep, buf, size); *eventp = event = alloc_event(); if (!event) return TEP_ERRNO__MEM_ALLOC_FAILED; - event->name = event_read_name(); + event->name = event_read_name(tep); if (!event->name) { /* Bad event? */ ret = TEP_ERRNO__MEM_ALLOC_FAILED; @@ -6979,7 +7773,7 @@ event->flags |= TEP_EVENT_FL_ISBPRINT; } - event->id = event_read_id(); + event->id = event_read_id(tep); if (event->id < 0) { ret = TEP_ERRNO__READ_ID_FAILED; /* @@ -7198,6 +7992,8 @@ data + offset, field->size); *len = offset >> 16; offset &= 0xffff; + if (field->flags & TEP_FIELD_IS_RELATIVE) + offset += field->offset + field->size; } else *len = field->size; @@ -7404,7 +8200,7 @@ * plugins updating the function. This overrides the * system defaults. */ - pr_stat("override of function helper '%s'", name); + tep_info("override of function helper '%s'", name); remove_func_handler(tep, name); } @@ -7542,8 +8338,8 @@ if (event == NULL) goto not_found; - pr_stat("overriding event (%d) %s:%s with new print handler", - event->id, event->system, event->name); + tep_info("overriding event (%d) %s:%s with new print handler", + event->id, event->system, event->name); event->handler = func; event->context = context; @@ -7628,8 +8424,8 @@ goto not_found; if (event->handler == func && event->context == context) { - pr_stat("removing override handler for event (%d) %s:%s. Going back to default handler.", - event->id, event->system, event->name); + tep_info("removing override handler for event (%d) %s:%s. Going back to default handler.", + event->id, event->system, event->name); event->handler = NULL; event->context = NULL;
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/src/event-plugin.c -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/src/event-plugin.c
Changed
@@ -497,7 +497,7 @@ list->name = plugin; *plugin_list = list; - pr_stat("registering plugin: %s", plugin); + tep_info("registering plugin: %s", plugin); func(tep); return;
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/src/kbuffer-parse.c -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/src/kbuffer-parse.c
Changed
@@ -6,6 +6,9 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <stdbool.h> + +#include <sys/utsname.h> #include "kbuffer.h" @@ -14,6 +17,9 @@ #define COMMIT_MASK ((1 << 27) - 1) +/* Absolute time stamps do not have the 5 MSB, take from the real time stamp */ +#define TS_MSB (0xf8ULL << 56) + enum { KBUFFER_FL_HOST_BIG_ENDIAN = (1<<0), KBUFFER_FL_BIG_ENDIAN = (1<<1), @@ -80,6 +86,42 @@ ENDIAN_MASK; } +static unsigned long long swap_8(unsigned long data) +{ + return ((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); +} + +static unsigned int swap_4(unsigned int data) +{ + return ((data & 0xffULL) << 24) | + ((data & (0xffULL << 8)) << 8) | + ((data & (0xffULL << 16)) >> 8) | + ((data & (0xffULL << 24)) >> 24); +} + +static void write_8(bool do_swap, void *ptr, unsigned long long data) +{ + if (do_swap) + *(unsigned long long *)ptr = swap_8(data); + else + *(unsigned long long *)ptr = data; +} + +static void write_4(bool do_swap, void *ptr, unsigned int data) +{ + if (do_swap) + *(unsigned int *)ptr = swap_4(data); + else + *(unsigned int *)ptr = data; +} + static unsigned long long __read_8(void *ptr) { unsigned long long data = *(unsigned long long *)ptr; @@ -90,18 +132,8 @@ static unsigned long long __read_8_sw(void *ptr) { unsigned long long data = *(unsigned long long *)ptr; - unsigned long long swap; - 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; + return swap_8(data); } static unsigned int __read_4(void *ptr) @@ -114,14 +146,8 @@ static unsigned int __read_4_sw(void *ptr) { unsigned int data = *(unsigned int *)ptr; - unsigned int swap; - - swap = ((data & 0xffULL) << 24) | - ((data & (0xffULL << 8)) << 8) | - ((data & (0xffULL << 16)) >> 8) | - ((data & (0xffULL << 24)) >> 24); - return swap; + return swap_4(data); } static unsigned long long read_8(struct kbuffer *kbuf, void *ptr) @@ -154,8 +180,27 @@ return (unsigned long)ptr - (unsigned long)kbuf->data; } +static int next_event(struct kbuffer *kbuf); static int __next_event(struct kbuffer *kbuf); +/* + * Just because sizeof(long) is 4 bytes, doesn't mean the OS isn't + * 64bits + */ +static bool host_is_32bit(void) +{ + struct utsname buf; + int ret; + + ret = uname(&buf); + if (ret < 0) { + /* Oh well, just assume it is 32 bit */ + return true; + } + /* If the uname machine value contains 64, assume the kernel is 64 bit */ + return strstr(buf.machine, "64") == NULL; +} + /** * kbuffer_alloc - allocat a new kbuffer * @size; enum to denote size of word @@ -172,6 +217,10 @@ switch (size) { case KBUFFER_LSIZE_4: break; + case KBUFFER_LSIZE_SAME_AS_HOST: + if (sizeof(long) != 8 && host_is_32bit()) + break; + /* fallthrough */ case KBUFFER_LSIZE_8: flags |= KBUFFER_FL_LONG_8; break; @@ -181,6 +230,7 @@ switch (endian) { case KBUFFER_ENDIAN_LITTLE: + case KBUFFER_ENDIAN_SAME_AS_HOST: break; case KBUFFER_ENDIAN_BIG: flags |= KBUFFER_FL_BIG_ENDIAN; @@ -195,8 +245,11 @@ kbuf->flags = flags; - if (host_is_bigendian()) + if (host_is_bigendian()) { + if (endian == KBUFFER_ENDIAN_SAME_AS_HOST) + flags |= KBUFFER_FL_BIG_ENDIAN; kbuf->flags |= KBUFFER_FL_HOST_BIG_ENDIAN; + } if (do_swap(kbuf)) { kbuf->read_8 = __read_8_sw; @@ -217,6 +270,26 @@ return kbuf; } +/** + * kbuffer_dup - duplicate a given kbuffer + * @kbuf_orig; The kbuffer to duplicate + * + * Allocates a new kbuffer based off of anothe kbuffer. + * Returns the duplicate on success or NULL on error. + */ +struct kbuffer *kbuffer_dup(struct kbuffer *kbuf_orig) +{ + struct kbuffer *kbuf; + + kbuf = malloc(sizeof(*kbuf)); + if (!kbuf) + return NULL; + + *kbuf = *kbuf_orig; + + return kbuf; +} + /** kbuffer_free - free an allocated kbuffer * @kbuf: The kbuffer to free * @@ -227,6 +300,33 @@ free(kbuf); } +/** + * kbuffer_refresh - update the meta data from the subbuffer + * @kbuf; The kbuffer to update + * + * If the loaded subbuffer changed its meta data (the commit) + * then update the pointers for it. + */ +int kbuffer_refresh(struct kbuffer *kbuf) +{ + unsigned long long flags; + unsigned int old_size; + + if (!kbuf || !kbuf->subbuffer) + return -1; + + old_size = kbuf->size; + + flags = read_long(kbuf, kbuf->subbuffer + 8); + kbuf->size = (unsigned int)flags & COMMIT_MASK; + + /* Update next to be the next element */ + if (kbuf->size != old_size && kbuf->curr == kbuf->next) + next_event(kbuf); + + return 0; +} + static unsigned int type4host(struct kbuffer *kbuf, unsigned int type_len_ts) { @@ -263,6 +363,13 @@ return type_len_ts >> 5; } +static void set_curr_to_end(struct kbuffer *kbuf) +{ + kbuf->curr = kbuf->size; + kbuf->next = kbuf->size; + kbuf->index = kbuf->size; +} + /* * Linux 2.6.30 and earlier (not much ealier) had a different * ring buffer format. It should be obsolete, but we handle it anyway. @@ -307,9 +414,7 @@ case OLD_RINGBUF_TYPE_TIME_STAMP: /* should never happen! */ - kbuf->curr = kbuf->size; - kbuf->next = kbuf->size; - kbuf->index = kbuf->size; + set_curr_to_end(kbuf); return -1; default: if (len) @@ -347,7 +452,7 @@ translate_data(struct kbuffer *kbuf, void *data, void **rptr, unsigned long long *delta, int *length) { - unsigned long long extend; + unsigned long long extend, msb = 0; unsigned int type_len_ts; unsigned int type_len; @@ -362,13 +467,15 @@ *length = read_4(kbuf, data); break; - case KBUFFER_TYPE_TIME_EXTEND: case KBUFFER_TYPE_TIME_STAMP: + msb = kbuf->timestamp & TS_MSB; + /* fall through */ + case KBUFFER_TYPE_TIME_EXTEND: extend = read_4(kbuf, data); data += 4; extend <<= TS_SHIFT; extend += *delta; - *delta = extend; + *delta = extend | msb; *length = 0; break; @@ -669,6 +776,17 @@ } /** + * kbuffer_subbuffer - the currently loaded subbuffer + * @kbuf: The kbuffer to read from + * + * Returns the currently loaded subbuffer. + */ +void *kbuffer_subbuffer(struct kbuffer *kbuf) +{ + return kbuf->subbuffer; +} + +/** * kbuffer_curr_index - Return the index of the record * @kbuf: The kbuffer to read from * @@ -812,3 +930,90 @@ return info; } + +/** + * kbuffer_read_buffer - read a buffer like the kernel would perform a read + * @kbuf: the kbuffer handle + * @buffer: where to write the data into + * @len; The length of @buffer + * + * This will read the saved sub buffer within @kbuf like the systemcall + * of read() to the trace_pipe_raw would do. That is, if either @len + * can not fit the entire buffer, or if the current index in @kbuf + * is non-zero, it will write to @buffer a new subbuffer that could be + * loaded into kbuffer_load_subbuffer(). That is, it will write into + * @buffer a legitimate sub-buffer with a header and all that has the + * proper timestamp and commit fields. + * + * Returns the index after the last element written. + * 0 if nothing was copied. + * -1 on error (which includes not having enough space in len to + * copy the subbuffer header or any of its content. In otherwords, + * do not try again! + * + * @kbuf current index will be set to the next element to read. + */ +int kbuffer_read_buffer(struct kbuffer *kbuf, void *buffer, int len) +{ + unsigned long long ts; + unsigned int type_len_ts; + bool do_swap = false; + int last_next; + int save_curr; + + /* Are we at the end of the buffer */ + if (kbuf->curr >= kbuf->size) + return 0; + + /* If we can not copy anyting, return -1 */ + if (len < kbuf->start) + return -1; + + /* Check if the first event can fit */ + if (len < (kbuf->next - kbuf->curr) + kbuf->start) + return -1; + + if (kbuf->read_8 == __read_8_sw) + do_swap = true; + + /* Have this subbuffer timestamp be the current timestamp */ + write_8(do_swap, buffer, kbuf->timestamp); + + len -= kbuf->start; + + save_curr = kbuf->curr; + + /* Due to timestamps, we must save the current next to use */ + last_next = kbuf->next; + + while (len >= kbuf->next - save_curr) { + last_next = kbuf->next; + if (!kbuffer_next_event(kbuf, &ts)) + break; + } + + len = last_next - save_curr; + /* No event was found? */ + if (!len) + return 0; + + memcpy(buffer + kbuf->start, kbuf->data + save_curr, len); + + /* Zero out the delta, as the sub-buffer has the timestamp */ + type_len_ts = read_4(kbuf, buffer + kbuf->start); + + if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN) + type_len_ts &= ~(((1 << 27) - 1)); + else + type_len_ts &= ((1 << 5) - 1); + + write_4(do_swap, buffer + kbuf->start, type_len_ts); + + /* Update the size */ + if (kbuf->read_long == __read_long_8) + write_8(do_swap, buffer + 8, len); + else + write_4(do_swap, buffer + 8, len); + + return last_next; +}
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/src/meson.build
Added
@@ -0,0 +1,39 @@ +# SPDX-License-Identifier: LGPL-2.1 +# +# Copyright (c) 2023 Daniel Wagner, SUSE LLC + +sources= + 'event-parse-api.c', + 'event-parse.c', + 'event-plugin.c', + 'kbuffer-parse.c', + 'parse-filter.c', + 'parse-utils.c', + 'tep_strerror.c', + 'trace-seq.c', + + +cc = meson.get_compiler('c') +dl_dep = cc.find_library('dl') + +libtraceevent = library( + 'traceevent', + sources, + version: library_version, + dependencies: dl_dep, + include_directories: incdir, + install: true) + +pkg = import('pkgconfig') +pkg.generate( + libtraceevent, + subdirs: 'traceevent', + filebase: meson.project_name(), + name: meson.project_name(), + version: meson.project_version(), + description: 'Manage trace event', + url: 'https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/') + +libtraceevent_dep = declare_dependency( + include_directories: '.', + link_with: libtraceevent)
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/src/parse-filter.c -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/src/parse-filter.c
Changed
@@ -30,7 +30,7 @@ struct tep_event *event; }; -static void show_error(char *error_buf, const char *fmt, ...) +static void show_error(struct tep_handle *tep, char *error_buf, const char *fmt, ...) { unsigned long long index; const char *input; @@ -38,8 +38,8 @@ int len; int i; - input = get_input_buf(); - index = get_input_buf_ptr(); + input = get_input_buf(tep); + index = get_input_buf_ptr(tep); len = input ? strlen(input) : 0; if (len) { @@ -57,20 +57,20 @@ va_end(ap); } -static enum tep_event_type filter_read_token(char **tok) +static enum tep_event_type filter_read_token(struct tep_handle *tep, char **tok) { enum tep_event_type type; char *token = NULL; do { free_token(token); - type = read_token(&token); + type = read_token(tep, &token); } while (type == TEP_EVENT_NEWLINE || type == TEP_EVENT_SPACE); /* If token is = or ! check to see if the next char is ~ */ if (token && (strcmp(token, "=") == 0 || strcmp(token, "!") == 0) && - peek_char() == '~') { + peek_char(tep) == '~') { /* append it */ *tok = malloc(3); if (*tok == NULL) { @@ -80,7 +80,7 @@ sprintf(*tok, "%c%c", *token, '~'); free_token(token); /* Now remove the '~' from the buffer */ - read_token(&token); + read_token(tep, &token); free_token(token); } else *tok = token; @@ -337,7 +337,7 @@ arg = allocate_arg(); if (arg == NULL) { - show_error(error_str, "failed to allocate filter arg"); + show_error(event->tep, error_str, "failed to allocate filter arg"); return TEP_ERRNO__MEM_ALLOC_FAILED; } @@ -351,7 +351,7 @@ arg->value.str = strdup(token); if (!arg->value.str) { free_arg(arg); - show_error(error_str, "failed to allocate string filter arg"); + show_error(event->tep, error_str, "failed to allocate string filter arg"); return TEP_ERRNO__MEM_ALLOC_FAILED; } break; @@ -383,7 +383,7 @@ break; default: free_arg(arg); - show_error(error_str, "expected a value but found %s", token); + show_error(event->tep, error_str, "expected a value but found %s", token); return TEP_ERRNO__UNEXPECTED_TYPE; } *parg = arg; @@ -437,7 +437,8 @@ } static enum tep_errno -add_right(struct tep_filter_arg *op, struct tep_filter_arg *arg, char *error_str) +add_right(struct tep_handle *tep, struct tep_filter_arg *op, + struct tep_filter_arg *arg, char *error_str) { struct tep_filter_arg *left; char *str; @@ -468,7 +469,7 @@ case TEP_FILTER_ARG_FIELD: break; default: - show_error(error_str, "Illegal rvalue"); + show_error(tep, error_str, "Illegal rvalue"); return TEP_ERRNO__ILLEGAL_RVALUE; } @@ -514,7 +515,7 @@ /* Left arg must be a field */ if (left->type != TEP_FILTER_ARG_FIELD) { - show_error(error_str, + show_error(tep, error_str, "Illegal lvalue for string comparison"); return TEP_ERRNO__ILLEGAL_LVALUE; } @@ -532,14 +533,14 @@ case TEP_FILTER_CMP_NOT_REGEX: ret = regcomp(&op->str.reg, str, REG_ICASE|REG_NOSUB); if (ret) { - show_error(error_str, + show_error(tep, error_str, "RegEx '%s' did not compute", str); return TEP_ERRNO__INVALID_REGEX; } break; default: - show_error(error_str, + show_error(tep, error_str, "Illegal comparison for string"); return TEP_ERRNO__ILLEGAL_STRING_CMP; } @@ -549,7 +550,7 @@ op->str.field = left->field.field; op->str.val = strdup(str); if (!op->str.val) { - show_error(error_str, "Failed to allocate string filter"); + show_error(tep, error_str, "Failed to allocate string filter"); return TEP_ERRNO__MEM_ALLOC_FAILED; } /* @@ -557,7 +558,7 @@ */ op->str.buffer = malloc(op->str.field->size + 1); if (!op->str.buffer) { - show_error(error_str, "Failed to allocate string filter"); + show_error(tep, error_str, "Failed to allocate string filter"); return TEP_ERRNO__MEM_ALLOC_FAILED; } /* Null terminate this buffer */ @@ -575,7 +576,7 @@ switch (op->num.type) { case TEP_FILTER_CMP_REGEX: case TEP_FILTER_CMP_NOT_REGEX: - show_error(error_str, + show_error(tep, error_str, "Op not allowed with integers"); return TEP_ERRNO__ILLEGAL_INTEGER_CMP; @@ -597,7 +598,7 @@ return 0; out_fail: - show_error(error_str, "Syntax error"); + show_error(tep, error_str, "Syntax error"); return TEP_ERRNO__SYNTAX_ERROR; } @@ -748,15 +749,16 @@ }; static enum tep_errno -reparent_op_arg(struct tep_filter_arg *parent, struct tep_filter_arg *old_child, - struct tep_filter_arg *arg, char *error_str) +reparent_op_arg(struct tep_handle *tep, struct tep_filter_arg *parent, + struct tep_filter_arg *old_child, struct tep_filter_arg *arg, + char *error_str) { struct tep_filter_arg *other_child; struct tep_filter_arg **ptr; if (parent->type != TEP_FILTER_ARG_OP && arg->type != TEP_FILTER_ARG_OP) { - show_error(error_str, "can not reparent other than OP"); + show_error(tep, error_str, "can not reparent other than OP"); return TEP_ERRNO__REPARENT_NOT_OP; } @@ -768,7 +770,7 @@ ptr = &old_child->op.left; other_child = old_child->op.right; } else { - show_error(error_str, "Error in reparent op, find other child"); + show_error(tep, error_str, "Error in reparent op, find other child"); return TEP_ERRNO__REPARENT_FAILED; } @@ -789,7 +791,7 @@ else if (parent->op.left == old_child) ptr = &parent->op.left; else { - show_error(error_str, "Error in reparent op"); + show_error(tep, error_str, "Error in reparent op"); return TEP_ERRNO__REPARENT_FAILED; } @@ -800,8 +802,8 @@ } /* Returns either filter_vals (success) or tep_errno (failfure) */ -static int test_arg(struct tep_filter_arg *parent, struct tep_filter_arg *arg, - char *error_str) +static int test_arg(struct tep_handle *tep, struct tep_filter_arg *parent, + struct tep_filter_arg *arg, char *error_str) { int lval, rval; @@ -818,47 +820,47 @@ return FILTER_VAL_NORM; case TEP_FILTER_ARG_EXP: - lval = test_arg(arg, arg->exp.left, error_str); + lval = test_arg(tep, arg, arg->exp.left, error_str); if (lval != FILTER_VAL_NORM) return lval; - rval = test_arg(arg, arg->exp.right, error_str); + rval = test_arg(tep, arg, arg->exp.right, error_str); if (rval != FILTER_VAL_NORM) return rval; return FILTER_VAL_NORM; case TEP_FILTER_ARG_NUM: - lval = test_arg(arg, arg->num.left, error_str); + lval = test_arg(tep, arg, arg->num.left, error_str); if (lval != FILTER_VAL_NORM) return lval; - rval = test_arg(arg, arg->num.right, error_str); + rval = test_arg(tep, arg, arg->num.right, error_str); if (rval != FILTER_VAL_NORM) return rval; return FILTER_VAL_NORM; case TEP_FILTER_ARG_OP: if (arg->op.type != TEP_FILTER_OP_NOT) { - lval = test_arg(arg, arg->op.left, error_str); + lval = test_arg(tep, arg, arg->op.left, error_str); switch (lval) { case FILTER_VAL_NORM: break; case FILTER_VAL_TRUE: if (arg->op.type == TEP_FILTER_OP_OR) return FILTER_VAL_TRUE; - rval = test_arg(arg, arg->op.right, error_str); + rval = test_arg(tep, arg, arg->op.right, error_str); if (rval != FILTER_VAL_NORM) return rval; - return reparent_op_arg(parent, arg, arg->op.right, + return reparent_op_arg(tep, parent, arg, arg->op.right, error_str); case FILTER_VAL_FALSE: if (arg->op.type == TEP_FILTER_OP_AND) return FILTER_VAL_FALSE; - rval = test_arg(arg, arg->op.right, error_str); + rval = test_arg(tep, arg, arg->op.right, error_str); if (rval != FILTER_VAL_NORM) return rval; - return reparent_op_arg(parent, arg, arg->op.right, + return reparent_op_arg(tep, parent, arg, arg->op.right, error_str); default: @@ -866,7 +868,7 @@ } } - rval = test_arg(arg, arg->op.right, error_str); + rval = test_arg(tep, arg, arg->op.right, error_str); switch (rval) { case FILTER_VAL_NORM: default: @@ -878,7 +880,7 @@ if (arg->op.type == TEP_FILTER_OP_NOT) return FILTER_VAL_FALSE; - return reparent_op_arg(parent, arg, arg->op.left, + return reparent_op_arg(tep, parent, arg, arg->op.left, error_str); case FILTER_VAL_FALSE: @@ -887,25 +889,25 @@ if (arg->op.type == TEP_FILTER_OP_NOT) return FILTER_VAL_TRUE; - return reparent_op_arg(parent, arg, arg->op.left, + return reparent_op_arg(tep, parent, arg, arg->op.left, error_str); } return rval; default: - show_error(error_str, "bad arg in filter tree"); + show_error(tep, error_str, "bad arg in filter tree"); return TEP_ERRNO__BAD_FILTER_ARG; } return FILTER_VAL_NORM; } /* Remove any unknown event fields */ -static int collapse_tree(struct tep_filter_arg *arg, +static int collapse_tree(struct tep_handle *tep, struct tep_filter_arg *arg, struct tep_filter_arg **arg_collapsed, char *error_str) { int ret; - ret = test_arg(arg, arg, error_str); + ret = test_arg(tep, arg, arg, error_str); switch (ret) { case FILTER_VAL_NORM: break; @@ -918,7 +920,7 @@ arg->type = TEP_FILTER_ARG_BOOLEAN; arg->boolean.value = ret == FILTER_VAL_TRUE; } else { - show_error(error_str, "Failed to allocate filter arg"); + show_error(tep, error_str, "Failed to allocate filter arg"); ret = TEP_ERRNO__MEM_ALLOC_FAILED; } break; @@ -954,7 +956,7 @@ do { free(token); - type = filter_read_token(&token); + type = filter_read_token(event->tep, &token); switch (type) { case TEP_EVENT_SQUOTE: case TEP_EVENT_DQUOTE: @@ -965,7 +967,7 @@ if (!left_item) left_item = arg; else if (current_exp) { - ret = add_right(current_exp, arg, error_str); + ret = add_right(event->tep, current_exp, arg, error_str); if (ret < 0) goto fail; left_item = NULL; @@ -985,20 +987,20 @@ case TEP_EVENT_DELIM: if (*token == ',') { - show_error(error_str, "Illegal token ','"); + show_error(event->tep, error_str, "Illegal token ','"); ret = TEP_ERRNO__ILLEGAL_TOKEN; goto fail; } if (*token == '(') { if (left_item) { - show_error(error_str, + show_error(event->tep, error_str, "Open paren can not come after item"); ret = TEP_ERRNO__INVALID_PAREN; goto fail; } if (current_exp) { - show_error(error_str, + show_error(event->tep, error_str, "Open paren can not come after expression"); ret = TEP_ERRNO__INVALID_PAREN; goto fail; @@ -1007,7 +1009,7 @@ ret = process_filter(event, &arg, error_str, 0); if (ret != TEP_ERRNO__UNBALANCED_PAREN) { if (ret == 0) { - show_error(error_str, + show_error(event->tep, error_str, "Unbalanced number of '('"); ret = TEP_ERRNO__UNBALANCED_PAREN; } @@ -1024,7 +1026,7 @@ } if (current_op) - ret = add_right(current_op, arg, error_str); + ret = add_right(event->tep, current_op, arg, error_str); else current_exp = arg; @@ -1071,7 +1073,7 @@ goto fail_syntax; break; case OP_NONE: - show_error(error_str, + show_error(event->tep, error_str, "Unknown op token %s", token); ret = TEP_ERRNO__UNKNOWN_TOKEN; goto fail; @@ -1096,14 +1098,14 @@ if (arg == NULL) goto fail_alloc; if (current_op) - ret = add_right(current_op, arg, error_str); + ret = add_right(event->tep, current_op, arg, error_str); if (ret < 0) goto fail; current_exp = arg; ret = process_filter(event, &arg, error_str, 1); if (ret < 0) goto fail; - ret = add_right(current_exp, arg, error_str); + ret = add_right(event->tep, current_exp, arg, error_str); if (ret < 0) goto fail; break; @@ -1118,7 +1120,7 @@ goto fail_alloc; if (current_op) - ret = add_right(current_op, arg, error_str); + ret = add_right(event->tep,current_op, arg, error_str); if (ret < 0) goto fail; ret = add_left(arg, left_item); @@ -1150,7 +1152,7 @@ if (!current_op) current_op = current_exp; - ret = collapse_tree(current_op, parg, error_str); + ret = collapse_tree(event->tep, current_op, parg, error_str); /* collapse_tree() may free current_op, and updates parg accordingly */ current_op = NULL; if (ret < 0) @@ -1160,11 +1162,11 @@ return 0; fail_alloc: - show_error(error_str, "failed to allocate filter arg"); + show_error(event->tep, error_str, "failed to allocate filter arg"); ret = TEP_ERRNO__MEM_ALLOC_FAILED; goto fail; fail_syntax: - show_error(error_str, "Syntax error"); + show_error(event->tep, error_str, "Syntax error"); ret = TEP_ERRNO__SYNTAX_ERROR; fail: free_arg(current_op); @@ -1180,7 +1182,7 @@ { int ret; - init_input_buf(filter_str, strlen(filter_str)); + init_input_buf(event->tep, filter_str, strlen(filter_str)); ret = process_filter(event, parg, error_str, 0); if (ret < 0) @@ -1238,7 +1240,7 @@ static void filter_init_error_buf(struct tep_event_filter *filter) { /* clear buffer to reset show error */ - init_input_buf("", 0); + init_input_buf(filter->tep, "", 0); filter->error_buffer0 = '\0'; } @@ -1712,8 +1714,11 @@ if (arg->str.field->flags & TEP_FIELD_IS_DYNAMIC) { addr = *(unsigned int *)val; - val = record->data + (addr & 0xffff); size = addr >> 16; + addr &= 0xffff; + if (arg->str.field->flags & TEP_FIELD_IS_RELATIVE) + addr += arg->str.field->offset + arg->str.field->size; + val = record->data + addr; } /*
View file
_service:tar_scm:libtraceevent-1.2.1.tar.gz/src/parse-utils.c -> _service:tar_scm:libtraceevent-1.8.2.tar.gz/src/parse-utils.c
Changed
@@ -9,56 +9,148 @@ #include <stdarg.h> #include <errno.h> +#include "event-utils.h" +#include "event-parse.h" +#include "kbuffer.h" + #define __weak __attribute__((weak)) -int __weak tep_vwarning(const char *name, const char *fmt, va_list ap) +static int log_level = TEP_LOG_CRITICAL; + +/** + * tep_set_loglevel - set log level of the library + * @level: desired level of the library messages + */ +void tep_set_loglevel(enum tep_loglevel level) { - int ret = errno; + log_level = level; +} + +/** + * tep_vprint - print library log messages + * @name: name of the library. + * @level: severity of the log message. This parameter is not used in this implementation, but as + * the function is weak and can be overridden, having the log level could be useful + * for other implementations. + * @print_err: whether to print the errno, if non zero. + * @fmt: printf format string of the message. + * @ap: list of printf parameters. + * + * This function is used to print all messages from traceevent, tracefs and trace-cmd libraries. + * It is defined as weak, so the application that uses those libraries can override it in order + * to implement its own logic for printing library logs. + * + * Return the value of errno at the function enter. + */ +int __weak tep_vprint(const char *name, enum tep_loglevel level, + bool print_err, const char *fmt, va_list ap) +{ + return __tep_vprint(name, level, print_err, fmt, ap); +} - if (errno) - perror(name); +/** + * __tep_vprint - print library log messages + * @name: name of the library. + * @level: severity of the log message. This parameter is not used in this implementation, but as + * the function is weak and can be overridden, having the log level could be useful + * for other implementations. + * @print_err: whether to print the errno, if non zero. + * @fmt: printf format string of the message. + * @ap: list of printf parameters. + * + * This function is used to print all messages from traceevent, tracefs and trace-cmd libraries. + * It is defined as weak, so the application that uses those libraries can override it in order + * to implement its own logic for printing library logs. + * + * Return the value of errno at the function enter. + */ +int __tep_vprint(const char *name, enum tep_loglevel level, + bool print_err, const char *fmt, va_list ap) +{ + int ret = errno; + FILE *fp = stdout; - fprintf(stderr, " "); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); + if (level <= TEP_LOG_WARNING) { + fp = stderr; + if (errno && print_err) { + perror(name); + fprintf(stderr, " "); + } + } + vfprintf(fp, fmt, ap); + fprintf(fp, "\n"); return ret; } -void __weak tep_warning(const char *fmt, ...) +void tep_warning(const char *fmt, ...) { va_list ap; + if (log_level < TEP_LOG_WARNING) + return; + va_start(ap, fmt); - tep_vwarning("libtraceevent", fmt, ap); + tep_vprint("libtraceevent", TEP_LOG_WARNING, true, 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, ...) +void tep_info(const char *fmt, ...) { va_list ap; + if (log_level < TEP_LOG_INFO) + return; + va_start(ap, fmt); - __vpr_stat(fmt, ap); + tep_vprint("libtraceevent", TEP_LOG_INFO, false, fmt, ap); va_end(ap); } -void __weak vpr_stat(const char *fmt, va_list ap) +/* The below is for backward compatibility */ +int __weak tep_vwarning(const char *name, const char *fmt, va_list ap) { - __vpr_stat(fmt, ap); + return tep_vprint(name, TEP_LOG_WARNING, true, fmt, ap); } -void __weak pr_stat(const char *fmt, ...) +void pr_stat(const char *fmt, ...) __attribute__((weak, alias("tep_info"))); +void __pr_stat(const char *fmt, ...) __attribute__((weak, alias("tep_info"))); + +void __weak __vpr_stat(const char *fmt, va_list ap) { - va_list ap; + tep_vprint("libtraceevent", TEP_LOG_INFO, false, fmt, ap); +} - va_start(ap, fmt); - __vpr_stat(fmt, ap); - va_end(ap); +void vpr_stat(const char *fmt, va_list ap) __attribute__((weak, alias("__vpr_stat"))); + +/** + * tep_kbuffer - return an allocated kbuffer that can be used for the tep handle + * @tep: the handle that will work with the kbuffer descriptor + * + * Allocates and returns a new kbuffer. + * The return must be freed by kbuffer_free(); + */ +struct kbuffer *tep_kbuffer(struct tep_handle *tep) +{ + enum kbuffer_endian endian; + int long_size; + + long_size = tep_get_long_size(tep); + + /* If the long_size is not set, then use the commit size */ + if (!long_size) + long_size = tep_get_header_page_size(tep); + + if (long_size == 8) + long_size = KBUFFER_LSIZE_8; + else + long_size = KBUFFER_LSIZE_4; + + if (tep_is_file_bigendian(tep)) + endian = KBUFFER_ENDIAN_BIG; + else + endian = KBUFFER_ENDIAN_LITTLE; + + return kbuffer_alloc(long_size, endian); }
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/utest
Added
+(directory)
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/utest/.gitignore
Added
@@ -0,0 +1,1 @@ +trace-utest
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/utest/Makefile
Added
@@ -0,0 +1,38 @@ +# SPDX-License-Identifier: LGPL-2.1 + +include $(src)/scripts/utils.mk + +TARGETS = $(bdir)/trace-utest + +OBJS = +OBJS += trace-utest.o +OBJS += traceevent-utest.o + +LIBS += -lcunit \ + -ldl \ + $(LIBTRACEEVENT_STATIC) + +OBJS := $(OBJS:%.o=$(bdir)/%.o) +DEPS := $(OBJS:$(bdir)/%.o=$(bdir)/.%.d) + +$(OBJS): | $(bdir) +$(DEPS): | $(bdir) + +$(bdir)/trace-utest: $(OBJS) $(LIBTRACEEVENT_STATIC) + $(Q)$(do_app_build) + +$(bdir)/%.o: %.c + $(Q)$(call do_fpic_compile) + +$(DEPS): $(bdir)/.%.d: %.c + $(Q)$(CC) -M $(CPPFLAGS) $(CFLAGS) $< > $@ + $(Q)$(CC) -M -MT $(bdir)/$*.o $(CPPFLAGS) $(CFLAGS) $< > $@ + +$(OBJS): $(bdir)/%.o : $(bdir)/.%.d + +dep_includes := $(wildcard $(DEPS)) + +test: $(TARGETS) + +clean: + $(Q)$(call do_clean,$(TARGETS) $(bdir)/*.o $(bdir)/.*.d)
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/utest/README
Added
@@ -0,0 +1,17 @@ + +Unit tests for libtraceevent library. The tests use CUnit framework: + + http://cunit.sourceforge.net/ + +which must be pre installed on the system, before building the unit tests. +The framework can be downloaded, compiled and installed manually, or +using a precompiled distro package: + + Fedora: + CUnit + CUnit-devel + + Ubuntu and Debian: + libcunit1 + libcunit1-doc + libcunit1-dev
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/utest/meson.build
Added
@@ -0,0 +1,16 @@ +# SPDX-License-Identifier: LGPL-2.1 +# +# Copyright (c) 2023 Daniel Wagner, SUSE LLC + +source = + 'trace-utest.c', + 'traceevent-utest.c', + + +e = executable( + 'trace-utest', + source, + include_directories: incdir, + dependencies: libtraceevent_dep, cunit_dep) + +test('trace-utest', e)
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/utest/trace-utest.c
Added
@@ -0,0 +1,86 @@ +// SPDX-License-Identifier: LGPL-2.1 +/* + * Copyright (C) 2020, VMware, Tzvetomir Stoyanov <tz.stoyanov@gmail.com> + * + * Modified from libtracefs to libtraceevent: + * Copyright (C) 2021, VMware, Steven Rostedt <rostedt@goodmis.org> + * + */ +#include <stdio.h> +#include <unistd.h> +#include <getopt.h> +#include <stdlib.h> + +#include <CUnit/CUnit.h> +#include <CUnit/Basic.h> + +#include "trace-utest.h" + +enum unit_tests { + RUN_NONE = 0, + RUN_TRACEEVENT = (1 << 0), + RUN_ALL = 0xFFFF +}; + +static void print_help(char **argv) +{ + printf("Usage: %s OPTIONS\n", basename(argv0)); + printf("\t-s, --silent\tPrint test summary\n"); + printf("\t-r, --run test\tRun specific test:\n"); + printf("\t\t traceevent run libtraceevent tests\n"); + printf("\t-h, --help\tPrint usage information\n"); + exit(0); +} + +int main(int argc, char **argv) +{ + CU_BasicRunMode verbose = CU_BRM_VERBOSE; + enum unit_tests tests = RUN_NONE; + + for (;;) { + int c; + int index = 0; + const char *opts = "+hsr:"; + static struct option long_options = { + {"silent", no_argument, NULL, 's'}, + {"run", required_argument, NULL, 'r'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + + c = getopt_long (argc, argv, opts, long_options, &index); + if (c == -1) + break; + switch (c) { + case 'r': + if (strcmp(optarg, "traceevent") == 0) + tests |= RUN_TRACEEVENT; + else + print_help(argv); + break; + case 's': + verbose = CU_BRM_SILENT; + break; + case 'h': + default: + print_help(argv); + break; + } + } + + if (tests == RUN_NONE) + tests = RUN_ALL; + + if (CU_initialize_registry() != CUE_SUCCESS) { + printf("Test registry cannot be initialized\n"); + return -1; + } + + if (tests & RUN_TRACEEVENT) + test_traceevent_lib(); + + CU_basic_set_mode(verbose); + CU_basic_run_tests(); + CU_cleanup_registry(); + return 0; +}
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/utest/trace-utest.h
Added
@@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: LGPL-2.1 */ +/* + * Copyright (C) 2020, VMware, Tzvetomir Stoyanov <tz.stoyanov@gmail.com> + * + * Modified from libtracefs to libtraceevent: + * Copyright (C) 2021, VMware, Steven Rostedt <rostedt@goodmis.org> + * + */ +#ifndef _TRACE_UTEST_H_ +#define _TRACE_UTEST_H_ + +void test_traceevent_lib(void); + +#endif /* _TRACE_UTEST_H_ */
View file
_service:tar_scm:libtraceevent-1.8.2.tar.gz/utest/traceevent-utest.c
Added
@@ -0,0 +1,429 @@ +// SPDX-License-Identifier: LGPL-2.1 +/* + * Copyright (C) 2020, VMware, Tzvetomir Stoyanov <tz.stoyanov@gmail.com> + * + * Modified from libtracefs to libtraceevent: + * Copyright (C) 2021, VMware, Steven Rostedt <rostedt@goodmis.org> + * + */ +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <time.h> +#include <dirent.h> +#include <ftw.h> + +#include <CUnit/CUnit.h> +#include <CUnit/Basic.h> + +#include "event-parse.h" +#include "trace-seq.h" + +#define TRACEEVENT_SUITE "traceevent library" + +#define DYN_STR_EVENT_SYSTEM "irq" +#define DYN_STR_FIELD "name" +#define DYN_STRING "hello" +#define DYN_STRING_FMT "irq=0 handler=hello" +static const char dyn_str_event = + "name: irq_handler_entry\n" + "ID: 1\n" + "format:\n" + "\tfield:unsigned short common_type;\toffset:0;\tsize:2;\tsigned:0;\n" + "\tfield:unsigned char common_flags;\toffset:2;\tsize:1;\tsigned:0;\n" + "\tfield:unsigned char common_preempt_count;\toffset:3;\tsize:1;\tsigned:0;\n" + "\tfield:int common_pid;\toffset:4;\tsize:4;\tsigned:1;\n" + "\n" + "\tfield:int irq;\toffset:8;\tsize:4;\tsigned:1;\n" + "\tfield:__data_loc char name;\toffset:12;\tsize:4;\tsigned:1;\n" + "\n" + "print fmt: \"irq=%d handler=%s\", REC->irq, __get_str(name)\n"; + +static char dyn_str_data = { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + /* common type */ 1, 0x00, +#else + /* common type */ 0x00, 1, +#endif + /* common flags */ 0x00, + /* common_preempt_count */ 0x00, + /* common_pid */ 0x00, 0x00, 0x00, 0x00, + /* irq */ 0x00, 0x00, 0x00, 0x00, + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + /* name : offset */ 16, 0x00, + /* name : length */ 6, 0x00, +#else + /* name : length */ 0x00, 6, + /* name : offset */ 0x00, 16, +#endif + /* name */ 'h', 'e', 'l', 'l', 'o', '\0', + /* padding */ 0x00, 0x00 +}; +static void *dyn_str_event_data = (void *)dyn_str_data; + +static const char dyn_str_old_event = + "name: irq_handler_entry\n" + "ID: 2\n" + "format:\n" + "\tfield:unsigned short common_type;\toffset:0;\tsize:2;\n" + "\tfield:unsigned char common_flags;\toffset:2;\tsize:1;\n" + "\tfield:unsigned char common_preempt_count;\toffset:3;\tsize:1;\n" + "\tfield:int common_pid;\toffset:4;\tsize:4;\n" + "\n" + "\tfield:int irq;\toffset:8;\tsize:4;\n" + "\tfield:__data_loc name;\toffset:12;\tsize:2;\n" + "\n" + "print fmt: \"irq=%d handler=%s\", REC->irq, __get_str(name)\n"; + +static char dyn_str_old_data = { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + /* common type */ 2, 0x00, +#else + /* common type */ 0x00, 2, +#endif + /* common flags */ 0x00, + /* common_preempt_count */ 0x00, + /* common_pid */ 0x00, 0x00, 0x00, 0x00, + /* irq */ 0x00, 0x00, 0x00, 0x00, + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + /* name : offset */ 16, 0x00, +#else + /* name : offset */ 0x00, 16, +#endif + /* padding */ 0x00, 0x00, + /* name */ 'h', 'e', 'l', 'l', 'o', '\0', + /* padding */ 0x00, 0x00, 0x00 +}; +static void *dyn_str_old_event_data = (void *)dyn_str_old_data; + +#define CPUMASK_EVENT_SYSTEM "ipi" +#define CPUMASK_EVENT_FIELD "cpumask" +static const char cpumask_event_format = + "name: ipi_send_cpumask\n" + "ID: 3\n" + "format:\n" + "\tfield:unsigned short common_type;\toffset:0;\tsize:2;\n" + "\tfield:unsigned char common_flags;\toffset:2;\tsize:1;\n" + "\tfield:unsigned char common_preempt_count;\toffset:3;\tsize:1;\n" + "\tfield:int common_pid;\toffset:4;\tsize:4;\n" + "\n" + "\tfield:__data_loc cpumask_t * cpumask;\toffset:8;\tsize:4;\tsigned:0;\n" + "\n" + "print fmt: \"cpumask=%s\", __get_cpumask(cpumask)\n"; + +/* Mind the endianness! */ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define DECL_CPUMASK_EVENT_DATA(name, args...) \ + static char cpumask_##name##_event_data = { \ + /* common type */ 3, 0x00, \ + /* common flags */ 0x00, \ + /* common_preempt_count */ 0x00, \ + /* common_pid */ 0x00, 0x00, 0x00, 0x00, \ + /* offset, size */ 16, 0x00, 8, 0x00, \ + /* padding */ 0x00, 0x00, 0x00, 0x00, \ + /* cpumask */ args, \ +} +#else +#define DECL_CPUMASK_EVENT_DATA(name, args...) \ +static char cpumask_##name##_event_data = { \ + /* common type */ 0x00, 3, \ + /* common flags */ 0x00, \ + /* common_preempt_count */ 0x00, \ + /* common_pid */ 0x00, 0x00, 0x00, 0x00, \ + /* offset, size */ 0x00, 8, 0x00, 16, \ + /* padding */ 0x00, 0x00, 0x00, 0x00, \ + /* cpumask */ args, \ +} +#endif + +#define SIZEOF_LONG0_FMT "FAILED TO PARSE s4=0 u4=0 s8=0 u8=0x0" +#define SIZEOF_LONG4_FMT "int=4 unsigned=4 unsigned int=4 long=4 unsigned long=4 long long=8 unsigned long long=8 s4=4 u4=4 s8=8 u8=8" +#define SIZEOF_LONG8_FMT "int=4 unsigned=4 unsigned int=4 long=8 unsigned long=8 long long=8 unsigned long long=8 s4=4 u4=4 s8=8 u8=8" + +static const char size_of_event = + "name: sizeof_event\n" + "ID: 23\n" + "format:\n" + "\tfield:unsigned short common_type;\toffset:0;\tsize:2;\tsigned:0;\n" + "\tfield:unsigned char common_flags;\toffset:2;\tsize:1;\tsigned:0;\n" + "\tfield:unsigned char common_preempt_count;\toffset:3;\tsize:1;\tsigned:0;\n" + "\tfield:int common_pid;\toffset:4;\tsize:4;\tsigned:1;\n" + "\n" + "\tfield:int s4;\toffset:8;\tsize:4;\tsigned:1;\n" + "\tfield:unsigned int u4;\toffset:12;\tsize:4;\tsigned:0;\n" + "\tfield:long long s8;\toffset:16;\tsize:8;\tsigned:1;\n" + "\tfield:unsigned long long u8;\toffset:24;\tsize:8;\tsigned:0;\n" + "\n" + "print fmt: \"int=%d unsigned=%d unsigned int=%d long=%d unsigned long=%d long long=%d unsigned long long=%d s4=%d u4=%d s8=%d u8=%d\", " + "sizeof(int), sizeof(unsigned), sizeof(unsigned int), sizeof(long), sizeof(unsigned long), " + "sizeof(long long), sizeof(unsigned long long), sizeof(REC->s4), " + "sizeof(REC->u4), sizeof(REC->s8), sizeof(REC->u8))\n"; +static char sizeof_data = { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + /* common type */ 23, 0x00, +#else + /* common type */ 0x00, 23, +#endif + /* common flags */ 0x00, + /* common_preempt_count */ 0x00, + /* common_pid */ 0x00, 0x00, 0x00, 0x00, + /* irq */ 0x00, 0x00, 0x00, 0x00, + + /* s4 */ 0x00, 0x00, 0x00, 0x00, + /* u4 */ 0x00, 0x00, 0x00, 0x00, + /* s8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* u8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; +static void *sizeof_event_data = (void *)sizeof_data; + +DECL_CPUMASK_EVENT_DATA(full, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff); +#define CPUMASK_FULL "ARRAYff, ff, ff, ff, ff, ff, ff, ff" +#define CPUMASK_FULL_FMT "cpumask=0-63" + +DECL_CPUMASK_EVENT_DATA(empty, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); +#define CPUMASK_EMPTY "ARRAY00, 00, 00, 00, 00, 00, 00, 00" +#define CPUMASK_EMPTY_FMT "cpumask=" + +DECL_CPUMASK_EVENT_DATA(half, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55); +#define CPUMASK_HALF "ARRAY55, 55, 55, 55, 55, 55, 55, 55" +#define CPUMASK_HALF_FMT "cpumask=0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62" + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +DECL_CPUMASK_EVENT_DATA(bytep1, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); +#define CPUMASK_BYTEP1 "ARRAY01, 80, 00, 00, 00, 00, 00, 00" +#define CPUMASK_BYTEP1_FMT "cpumask=0,15" + +DECL_CPUMASK_EVENT_DATA(bytep2, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00); +#define CPUMASK_BYTEP2 "ARRAY01, 00, 80, 00, 00, 00, 00, 00" +#define CPUMASK_BYTEP2_FMT "cpumask=0,23" + +DECL_CPUMASK_EVENT_DATA(bytepn, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80); +#define CPUMASK_BYTEPN "ARRAY01, 00, 00, 00, 00, 00, 00, 80" +#define CPUMASK_BYTEPN_FMT "cpumask=0,63" + +#else + +DECL_CPUMASK_EVENT_DATA(bytep1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01); +#define CPUMASK_BYTEP1 "ARRAY00, 00, 00, 00, 00, 00, 80, 01" +#define CPUMASK_BYTEP1_FMT "cpumask=0,15" + +DECL_CPUMASK_EVENT_DATA(bytep2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x01); +#define CPUMASK_BYTEP2 "ARRAY00, 00, 00, 00, 00, 80, 00, 01" +#define CPUMASK_BYTEP2_FMT "cpumask=0,23" + +DECL_CPUMASK_EVENT_DATA(bytepn, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01); +#define CPUMASK_BYTEPN "ARRAY80, 00, 00, 00, 00, 00, 80, 01" +#define CPUMASK_BYTEPN_FMT "cpumask=0,63" +#endif + +static struct tep_handle *test_tep; +static struct trace_seq *test_seq; +static struct trace_seq seq_storage; + +static void parse_dyn_str(const char *dyn_str, void *data, int size) +{ + struct tep_format_field *field; + struct tep_event *event; + struct tep_record record; + + record.data = data; + record.size = size; + + CU_TEST(tep_parse_format(test_tep, &event, + dyn_str, strlen(dyn_str), + DYN_STR_EVENT_SYSTEM) == TEP_ERRNO__SUCCESS); + + field = tep_find_any_field(event, DYN_STR_FIELD); + CU_TEST(field != NULL); + trace_seq_reset(test_seq); + tep_print_field_content(test_seq, data, size, field); + CU_TEST(strcmp(test_seq->buffer, DYN_STRING) == 0); + + trace_seq_reset(test_seq); + tep_print_event(test_tep, test_seq, &record, "%s", TEP_PRINT_INFO); + trace_seq_do_printf(test_seq); + CU_TEST(strcmp(test_seq->buffer, DYN_STRING_FMT) == 0); +} + +static void test_parse_dyn_str_event(void) +{ + parse_dyn_str(dyn_str_event, dyn_str_event_data, sizeof(dyn_str_data)); +} + +static void test_parse_dyn_str_old_event(void) +{ + parse_dyn_str(dyn_str_old_event, dyn_str_old_event_data, sizeof(dyn_str_old_data)); +} + +static void parse_cpumask(const char *format, void *data, int size, + const char* expected_raw, const char* expected) +{ + struct tep_format_field *field; + struct tep_event *event; + struct tep_record record; + + record.data = data; + record.size = size; + + CU_TEST(tep_parse_format(test_tep, &event, + format, strlen(format), + CPUMASK_EVENT_SYSTEM) == TEP_ERRNO__SUCCESS); + + field = tep_find_any_field(event, CPUMASK_EVENT_FIELD); + CU_TEST(field != NULL); + + trace_seq_reset(test_seq); + tep_print_field_content(test_seq, data, size, field); + CU_TEST(strcmp(test_seq->buffer, expected_raw) == 0); + + trace_seq_reset(test_seq); + tep_print_event(test_tep, test_seq, &record, "%s", TEP_PRINT_INFO); + trace_seq_do_printf(test_seq); + CU_TEST(strcmp(test_seq->buffer, expected) == 0); +} + +static void test_parse_cpumask_full(void) +{ + parse_cpumask(cpumask_event_format, + cpumask_full_event_data, sizeof(cpumask_full_event_data), + CPUMASK_FULL, CPUMASK_FULL_FMT); +} + +static void test_parse_cpumask_empty(void) +{ + parse_cpumask(cpumask_event_format, + cpumask_empty_event_data, sizeof(cpumask_empty_event_data), + CPUMASK_EMPTY, CPUMASK_EMPTY_FMT); +} + +static void test_parse_cpumask_half(void) +{ + parse_cpumask(cpumask_event_format, + cpumask_half_event_data, sizeof(cpumask_half_event_data), + CPUMASK_HALF, CPUMASK_HALF_FMT); +} + +static void test_parse_cpumask_bytep1(void) +{ + parse_cpumask(cpumask_event_format, + cpumask_bytep1_event_data, sizeof(cpumask_bytep1_event_data), + CPUMASK_BYTEP1, CPUMASK_BYTEP1_FMT); +} + +static void test_parse_cpumask_bytep2(void) +{ + parse_cpumask(cpumask_event_format, + cpumask_bytep2_event_data, sizeof(cpumask_bytep2_event_data), + CPUMASK_BYTEP2, CPUMASK_BYTEP2_FMT); +} + +static void test_parse_cpumask_bytepn(void) +{ + parse_cpumask(cpumask_event_format, + cpumask_bytepn_event_data, sizeof(cpumask_bytepn_event_data), + CPUMASK_BYTEPN, CPUMASK_BYTEPN_FMT); +} + +static void test_parse_sizeof(int long_size, int value, const char *system, + const char *test_str) +{ + struct tep_event *event; + struct tep_record record; + char *sizeof_event; + char *p; + + tep_set_long_size(test_tep, long_size); + + record.data = sizeof_event_data; + record.size = sizeof(sizeof_data); + + sizeof_event = strdup(size_of_event); + CU_TEST(sizeof_event != NULL); + + /* Set a new id */ + p = strstr(sizeof_event, "ID: 2"); + p5 = '0' + value; + + /* Handles endianess */ + *(unsigned short *)sizeof_data = 20 + value; + + CU_TEST(tep_parse_format(test_tep, &event, sizeof_event, + strlen(sizeof_event), + system) == TEP_ERRNO__SUCCESS); + + trace_seq_reset(test_seq); + tep_print_event(test_tep, test_seq, &record, "%s", TEP_PRINT_INFO); + trace_seq_do_printf(test_seq); + CU_TEST(strcmp(test_seq->buffer, test_str) == 0); + + free(sizeof_event); +} + +static void test_parse_sizeof8(void) +{ + test_parse_sizeof(8, 3, "sizeof8", SIZEOF_LONG8_FMT); +} + +static void test_parse_sizeof4(void) +{ + test_parse_sizeof(4, 4, "sizeof4", SIZEOF_LONG4_FMT); +} + +static void test_parse_sizeof_undef(void) +{ + test_parse_sizeof(0, 5, "sizeof_undef", SIZEOF_LONG0_FMT); +} + +static int test_suite_destroy(void) +{ + tep_free(test_tep); + trace_seq_destroy(test_seq); + return 0; +} + +static int test_suite_init(void) +{ + test_seq = &seq_storage; + trace_seq_init(test_seq); + test_tep = tep_alloc(); + if (!test_tep) + return 1; + return 0; +} + +void test_traceevent_lib(void) +{ + CU_pSuite suite = NULL; + + suite = CU_add_suite(TRACEEVENT_SUITE, test_suite_init, test_suite_destroy); + if (suite == NULL) { + fprintf(stderr, "Suite \"%s\" cannot be ceated\n", TRACEEVENT_SUITE); + return; + } + CU_add_test(suite, "parse dynamic string event", + test_parse_dyn_str_event); + CU_add_test(suite, "parse old dynamic string event", + test_parse_dyn_str_old_event); + CU_add_test(suite, "parse full cpumask", + test_parse_cpumask_full); + CU_add_test(suite, "parse empty cpumask", + test_parse_cpumask_empty); + CU_add_test(suite, "parse half-filled cpumask", + test_parse_cpumask_half); + CU_add_test(suite, "parse cpumask spanning 2 bytes", + test_parse_cpumask_bytep1); + CU_add_test(suite, "parse cpumask spanning 3 bytes", + test_parse_cpumask_bytep2); + CU_add_test(suite, "parse cpumask spanning all bytes", + test_parse_cpumask_bytepn); + CU_add_test(suite, "parse sizeof() 8byte values", + test_parse_sizeof8); + CU_add_test(suite, "parse sizeof() 4byte values", + test_parse_sizeof4); + CU_add_test(suite, "parse sizeof() no long size defined", + test_parse_sizeof_undef); +}
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2