diff options
Diffstat (limited to 'tools/lib/traceevent')
24 files changed, 755 insertions, 335 deletions
diff --git a/tools/lib/traceevent/Build b/tools/lib/traceevent/Build index ba54bfce0b0b..f9a5d79578f5 100644 --- a/tools/lib/traceevent/Build +++ b/tools/lib/traceevent/Build @@ -6,14 +6,3 @@ libtraceevent-y += parse-utils.o  libtraceevent-y += kbuffer-parse.o  libtraceevent-y += tep_strerror.o  libtraceevent-y += event-parse-api.o - -plugin_jbd2-y         += plugin_jbd2.o -plugin_hrtimer-y      += plugin_hrtimer.o -plugin_kmem-y         += plugin_kmem.o -plugin_kvm-y          += plugin_kvm.o -plugin_mac80211-y     += plugin_mac80211.o -plugin_sched_switch-y += plugin_sched_switch.o -plugin_function-y     += plugin_function.o -plugin_xen-y          += plugin_xen.o -plugin_scsi-y         += plugin_scsi.o -plugin_cfg80211-y     += plugin_cfg80211.o diff --git a/tools/lib/traceevent/Documentation/libtraceevent-event_print.txt b/tools/lib/traceevent/Documentation/libtraceevent-event_print.txt new file mode 100644 index 000000000000..2c6a61811118 --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-event_print.txt @@ -0,0 +1,130 @@ +libtraceevent(3) +================ + +NAME +---- +tep_print_event - Writes event information into a trace sequence. + +SYNOPSIS +-------- +[verse] +-- +*#include <event-parse.h>* +*#include <trace-seq.h>* + +void *tep_print_event*(struct tep_handle pass:[*]_tep_, struct trace_seqpass:[*]_s_, struct tep_record pass:[*]_record_, const char pass:[*]_fmt_, _..._) +-- + +DESCRIPTION +----------- + +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: +[verse] +-- +	TEP_PRINT_PID, "%d"  - PID of the event. +	TEP_PRINT_CPU, "%d"  - Event CPU. +	TEP_PRINT_COMM, "%s" - Event command string. +	TEP_PRINT_NAME, "%s" - Event name. +	TEP_PRINT_LATENCY, "%s" - Latency of the event. It prints 4 or more +			fields - interrupt state, scheduling state, +			current context, and preemption count. +			Field 1 is the interrupt enabled state: +				d : Interrupts are disabled +				. : Interrupts are enabled +				X : The architecture does not support this +				    information +			Field 2 is the "need resched" state. +				N : The task is set to call the scheduler when +				    possible, as another higher priority task +				    may need to be scheduled in. +				. : The task is not set to call the scheduler. +			Field 3 is the context state. +				. : Normal context +				s : Soft interrupt context +				h : Hard interrupt context +				H : Hard interrupt context which triggered +				    during soft interrupt context. +				z : NMI context +				Z : NMI context which triggered during hard +				    interrupt context +			Field 4 is the preemption count. +				. : The preempt count is zero. +			On preemptible kernels (where the task can be scheduled +			out in arbitrary locations while in kernel context), the +			preempt count, when non zero, will prevent the kernel +			from scheduling out the current task. The preempt count +			number is displayed when it is not zero. +			Depending on the kernel, it may show other fields +			(lock depth, or migration disabled, which are unique to +			specialized kernels). +	TEP_PRINT_TIME, %d - event time stamp. A divisor and precision can be +			specified as part of this format string: +			"%precision.divisord". Example: +			"%3.1000d" - divide the time by 1000 and print the first +			3 digits before the dot. Thus, the time stamp +			"123456000" will be printed as "123.456" +	TEP_PRINT_INFO, "%s" - event information. +	TEP_PRINT_INFO_RAW, "%s" - event information, in raw format. + +-- +EXAMPLE +------- +[source,c] +-- +#include <event-parse.h> +#include <trace-seq.h> +... +struct trace_seq seq; +trace_seq_init(&seq); +struct tep_handle *tep = tep_alloc(); +... +void print_my_event(struct tep_record *record) +{ +	trace_seq_reset(&seq); +	tep_print_event(tep, s, record, "%16s-%-5d [%03d] %s %6.1000d %s %s", +			TEP_PRINT_COMM, TEP_PRINT_PID, TEP_PRINT_CPU, +			TEP_PRINT_LATENCY, TEP_PRINT_TIME, TEP_PRINT_NAME, +			TEP_PRINT_INFO); +} +... +-- + +FILES +----- +[verse] +-- +*event-parse.h* +	Header file to include in order to have access to the library APIs. +*trace-seq.h* +	Header file to include in order to have access to trace sequences related APIs. +	Trace sequences are used to allow a function to call several other functions +	to create a string of data to use. +*-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/linux/kernel/git/torvalds/linux.git diff --git a/tools/lib/traceevent/Documentation/libtraceevent-func_apis.txt b/tools/lib/traceevent/Documentation/libtraceevent-func_apis.txt index 38bfea30a5f6..f6aca0df2151 100644 --- a/tools/lib/traceevent/Documentation/libtraceevent-func_apis.txt +++ b/tools/lib/traceevent/Documentation/libtraceevent-func_apis.txt @@ -59,12 +59,12 @@ parser context.  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 "%pF" or "%pS" parameter in its format string. It is common to -pass in the kallsyms function names with their corresponding addresses with this +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  function. The _tep_ argument is the trace event parser context. The _name_ is -the name of the function, the string is copied internally. The _addr_ is -the start address of the function. The _mod_ is the kernel module -the function may be in (NULL for none). +the name of the function, the string is copied internally. The _addr_ is the +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  it was stored in the kernel. Some strings internal to the kernel with static diff --git a/tools/lib/traceevent/Documentation/libtraceevent-handle.txt b/tools/lib/traceevent/Documentation/libtraceevent-handle.txt index 8d568316847d..45b20172e262 100644 --- a/tools/lib/traceevent/Documentation/libtraceevent-handle.txt +++ b/tools/lib/traceevent/Documentation/libtraceevent-handle.txt @@ -3,7 +3,7 @@ libtraceevent(3)  NAME  ---- -tep_alloc, tep_free,tep_ref, tep_unref,tep_ref_get - Create, destroy, manage +tep_alloc, tep_free,tep_ref, tep_unref,tep_get_ref - Create, destroy, manage  references of trace event parser context.  SYNOPSIS @@ -16,7 +16,7 @@ struct tep_handle pass:[*]*tep_alloc*(void);  void *tep_free*(struct tep_handle pass:[*]_tep_);  void *tep_ref*(struct tep_handle pass:[*]_tep_);  void *tep_unref*(struct tep_handle pass:[*]_tep_); -int *tep_ref_get*(struct tep_handle pass:[*]_tep_); +int *tep_get_ref*(struct tep_handle pass:[*]_tep_);  --  DESCRIPTION @@ -57,9 +57,9 @@ EXAMPLE  ...  struct tep_handle *tep = tep_alloc();  ... -int ref = tep_ref_get(tep); +int ref = tep_get_ref(tep);  tep_ref(tep); -if ( (ref+1) != tep_ref_get(tep)) { +if ( (ref+1) != tep_get_ref(tep)) {  	/* Something wrong happened, the counter is not incremented by 1 */  }  tep_unref(tep); diff --git a/tools/lib/traceevent/Documentation/libtraceevent-plugins.txt b/tools/lib/traceevent/Documentation/libtraceevent-plugins.txt new file mode 100644 index 000000000000..596032ade31f --- /dev/null +++ b/tools/lib/traceevent/Documentation/libtraceevent-plugins.txt @@ -0,0 +1,99 @@ +libtraceevent(3) +================ + +NAME +---- +tep_load_plugins, tep_unload_plugins - Load / unload traceevent plugins. + +SYNOPSIS +-------- +[verse] +-- +*#include <event-parse.h>* + +struct tep_plugin_list pass:[*]*tep_load_plugins*(struct tep_handle pass:[*]_tep_); +void *tep_unload_plugins*(struct tep_plugin_list pass:[*]_plugin_list_, struct tep_handle pass:[*]_tep_); +-- + +DESCRIPTION +----------- +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] +-- +	- System's plugin directory, defined at the library compile time. It +	  depends on the library installation prefix and usually is +	  _(install_preffix)/lib/traceevent/plugins_ +	- Directory, defined by the environment variable _TRACEEVENT_PLUGIN_DIR_ +	- User's plugin directory, located at _~/.local/lib/traceevent/plugins_ +-- +Loading of plugins can be controlled by the _tep_flags_, using the +_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 +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 +_plugin_list_ is the list of loaded plugins, returned by +the _tep_load_plugins()_ function. + +RETURN VALUE +------------ +The _tep_load_plugins()_ function returns a list of successfully loaded plugins, +or NULL in case no plugins are loaded. + +EXAMPLE +------- +[source,c] +-- +#include <event-parse.h> +... +struct tep_handle *tep = tep_alloc(); +... +struct tep_plugin_list *plugins = tep_load_plugins(tep); +if (plugins == NULL) { +	/* no plugins are loaded */ +} +... +tep_unload_plugins(plugins, tep); +-- + +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)_, _tep_set_flag(3)_ + +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/linux/kernel/git/torvalds/linux.git diff --git a/tools/lib/traceevent/Documentation/libtraceevent.txt b/tools/lib/traceevent/Documentation/libtraceevent.txt index fbd977b47de1..d530a7ce8fb2 100644 --- a/tools/lib/traceevent/Documentation/libtraceevent.txt +++ b/tools/lib/traceevent/Documentation/libtraceevent.txt @@ -16,7 +16,7 @@ Management of tep handler data structure and access of its members:  	void *tep_free*(struct tep_handle pass:[*]_tep_);  	void *tep_ref*(struct tep_handle pass:[*]_tep_);  	void *tep_unref*(struct tep_handle pass:[*]_tep_); -	int *tep_ref_get*(struct tep_handle pass:[*]_tep_); +	int *tep_get_ref*(struct tep_handle pass:[*]_tep_);  	void *tep_set_flag*(struct tep_handle pass:[*]_tep_, enum tep_flag _flag_);  	void *tep_clear_flag*(struct tep_handle pass:[*]_tep_, enum tep_flag _flag_);  	bool *tep_test_flag*(struct tep_handle pass:[*]_tep_, enum tep_flag _flags_); @@ -26,15 +26,12 @@ Management of tep handler data structure and access of its members:  	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_); -	bool *tep_is_latency_format*(struct tep_handle pass:[*]_tep_); -	void *tep_set_latency_format*(struct tep_handle pass:[*]_tep_, int _lat_);  	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_);  Register / unregister APIs: -	int *tep_register_trace_clock*(struct tep_handle pass:[*]_tep_, const char pass:[*]_trace_clock_);  	int *tep_register_function*(struct tep_handle pass:[*]_tep_, char pass:[*]_name_, unsigned long long _addr_, char pass:[*]_mod_);  	int *tep_register_event_handler*(struct tep_handle pass:[*]_tep_, int _id_, const char pass:[*]_sys_name_, const char pass:[*]_event_name_, tep_event_handler_func _func_, void pass:[*]_context_);  	int *tep_unregister_event_handler*(struct tep_handle pass:[*]tep, int id, const char pass:[*]sys_name, const char pass:[*]event_name, tep_event_handler_func func, void pass:[*]_context_); @@ -57,14 +54,7 @@ Event related APIs:  	int *tep_get_events_count*(struct tep_handle pass:[*]_tep_);  	struct tep_event pass:[*]pass:[*]*tep_list_events*(struct tep_handle pass:[*]_tep_, enum tep_event_sort_type _sort_type_);  	struct tep_event pass:[*]pass:[*]*tep_list_events_copy*(struct tep_handle pass:[*]_tep_, enum tep_event_sort_type _sort_type_); - -Event printing: -	void *tep_print_event*(struct tep_handle pass:[*]_tep_, struct trace_seq pass:[*]_s_, struct tep_record pass:[*]_record_, bool _use_trace_clock_); -	void *tep_print_event_data*(struct tep_handle pass:[*]_tep_, struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, struct tep_record pass:[*]_record_); -	void *tep_event_info*(struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, struct tep_record pass:[*]_record_); -	void *tep_print_event_task*(struct tep_handle pass:[*]_tep_, struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, struct tep_record pass:[*]_record_); -	void *tep_print_event_time*(struct tep_handle pass:[*]_tep_, struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, struct tep_record pass:[*]record, bool _use_trace_clock_); -	void *tep_set_print_raw*(struct tep_handle pass:[*]_tep_, int _print_raw_); +	void *tep_print_event*(struct tep_handle pass:[*]_tep_, struct trace_seq pass:[*]_s_, struct tep_record pass:[*]_record_, const char pass:[*]_fmt_, _..._);  Event finding:  	struct tep_event pass:[*]*tep_find_event*(struct tep_handle pass:[*]_tep_, int _id_); @@ -116,7 +106,6 @@ Filter management:  	int *tep_filter_compare*(struct tep_event_filter pass:[*]_filter1_, struct tep_event_filter pass:[*]_filter2_);  Parsing various data from the records: -	void *tep_data_latency_format*(struct tep_handle pass:[*]_tep_, struct trace_seq pass:[*]_s_, struct tep_record pass:[*]_record_);  	int *tep_data_type*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_rec_);  	int *tep_data_pid*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_rec_);  	int *tep_data_preempt_count*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_rec_); diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 3292c290654f..5315f3787f8d 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -58,30 +58,6 @@ export man_dir man_dir_SQ INSTALL  export DESTDIR DESTDIR_SQ  export EVENT_PARSE_VERSION -set_plugin_dir := 1 - -# Set plugin_dir to preffered global plugin location -# If we install under $HOME directory we go under -# $(HOME)/.traceevent/plugins -# -# We dont set PLUGIN_DIR in case we install under $HOME -# directory, because by default the code looks under: -# $(HOME)/.traceevent/plugins by default. -# -ifeq ($(plugin_dir),) -ifeq ($(prefix),$(HOME)) -override plugin_dir = $(HOME)/.traceevent/plugins -set_plugin_dir := 0 -else -override plugin_dir = $(libdir)/traceevent/plugins -endif -endif - -ifeq ($(set_plugin_dir),1) -PLUGIN_DIR = -DPLUGIN_DIR="$(plugin_dir)" -PLUGIN_DIR_SQ = '$(subst ','\'',$(PLUGIN_DIR))' -endif -  include ../../scripts/Makefile.include  # copy a bit from Linux kbuild @@ -105,7 +81,6 @@ export prefix libdir src obj  # Shell quotes  libdir_SQ = $(subst ','\'',$(libdir))  libdir_relative_SQ = $(subst ','\'',$(libdir_relative)) -plugin_dir_SQ = $(subst ','\'',$(plugin_dir))  CONFIG_INCLUDES =   CONFIG_LIBS	= @@ -151,29 +126,14 @@ MAKEOVERRIDES=  export srctree OUTPUT CC LD CFLAGS V  build := -f $(srctree)/tools/build/Makefile.build dir=. obj -PLUGINS  = plugin_jbd2.so -PLUGINS += plugin_hrtimer.so -PLUGINS += plugin_kmem.so -PLUGINS += plugin_kvm.so -PLUGINS += plugin_mac80211.so -PLUGINS += plugin_sched_switch.so -PLUGINS += plugin_function.so -PLUGINS += plugin_xen.so -PLUGINS += plugin_scsi.so -PLUGINS += plugin_cfg80211.so - -PLUGINS    := $(addprefix $(OUTPUT),$(PLUGINS)) -PLUGINS_IN := $(PLUGINS:.so=-in.o) -  TE_IN      := $(OUTPUT)libtraceevent-in.o  LIB_TARGET := $(addprefix $(OUTPUT),$(LIB_TARGET)) -DYNAMIC_LIST_FILE := $(OUTPUT)libtraceevent-dynamic-list -CMD_TARGETS = $(LIB_TARGET) $(PLUGINS) $(DYNAMIC_LIST_FILE) +CMD_TARGETS = $(LIB_TARGET)  TARGETS = $(CMD_TARGETS) -all: all_cmd +all: all_cmd plugins  all_cmd: $(CMD_TARGETS) @@ -188,17 +148,6 @@ $(OUTPUT)libtraceevent.so.$(EVENT_PARSE_VERSION): $(TE_IN)  $(OUTPUT)libtraceevent.a: $(TE_IN)  	$(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^ -$(OUTPUT)libtraceevent-dynamic-list: $(PLUGINS) -	$(QUIET_GEN)$(call do_generate_dynamic_list_file, $(PLUGINS), $@) - -plugins: $(PLUGINS) - -__plugin_obj = $(notdir $@) -  plugin_obj = $(__plugin_obj:-in.o=) - -$(PLUGINS_IN): force -	$(Q)$(MAKE) $(build)=$(plugin_obj) -  $(OUTPUT)%.so: $(OUTPUT)%-in.o  	$(QUIET_LINK)$(CC) $(CFLAGS) -shared $(LDFLAGS) -nostartfiles -o $@ $^ @@ -258,25 +207,6 @@ define do_install  	$(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));	\ -	done -endef - -define do_generate_dynamic_list_file -	symbol_type=`$(NM) -u -D $1 | awk 'NF>1 {print $$1}' | \ -	xargs echo "U W w" | tr ' ' '\n' | sort -u | xargs echo`;\ -	if [ "$$symbol_type" = "U W w" ];then				\ -		(echo '{';						\ -		$(NM) -u -D $1 | awk 'NF>1 {print "\t"$$2";"}' | sort -u;\ -		echo '};';						\ -		) > $2;							\ -	else								\ -		(echo Either missing one of [$1] or bad version of $(NM)) 1>&2;\ -	fi -endef -  PKG_CONFIG_FILE = libtraceevent.pc  define do_install_pkgconfig_file  	if [ -n "${pkgconfig_dir}" ]; then 					\ @@ -296,10 +226,6 @@ install_lib: all_cmd install_plugins install_headers install_pkgconfig  		$(call do_install_mkdir,$(libdir_SQ)); \  		cp -fpR $(LIB_INSTALL) $(DESTDIR)$(libdir_SQ) -install_plugins: $(PLUGINS) -	$(call QUIET_INSTALL, trace_plugins) \ -		$(call do_install_plugins, $(PLUGINS)) -  install_pkgconfig:  	$(call QUIET_INSTALL, $(PKG_CONFIG_FILE)) \  		$(call do_install_pkgconfig_file,$(prefix)) @@ -313,7 +239,7 @@ install_headers:  install: install_lib -clean: +clean: clean_plugins  	$(call QUIET_CLEAN, libtraceevent) \  		$(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d .*.cmd; \  		$(RM) TRACEEVENT-CFLAGS tags TAGS; \ @@ -351,7 +277,19 @@ help:  	@echo '  doc-install         - install the man pages'  	@echo '  doc-uninstall       - uninstall the man pages'  	@echo'' -PHONY += force plugins + +PHONY += plugins +plugins: +	$(call descend,plugins) + +PHONY += install_plugins +install_plugins: +	$(call descend,plugins,install) + +PHONY += clean_plugins +clean_plugins: +	$(call descend,plugins,clean) +  force:  # Declare the contents of the .PHONY variable as phony.  We keep that diff --git a/tools/lib/traceevent/event-parse-api.c b/tools/lib/traceevent/event-parse-api.c index 988587840c80..4faf52a65791 100644 --- a/tools/lib/traceevent/event-parse-api.c +++ b/tools/lib/traceevent/event-parse-api.c @@ -303,33 +303,6 @@ void tep_set_local_bigendian(struct tep_handle *tep, enum tep_endian endian)  }  /** - * tep_is_latency_format - get if the latency output format is configured - * @tep: a handle to the tep_handle - * - * This returns true if the latency output format is configured - * If @tep is NULL, false is returned. - */ -bool tep_is_latency_format(struct tep_handle *tep) -{ -	if (tep) -		return (tep->latency_format); -	return false; -} - -/** - * tep_set_latency_format - set the latency output format - * @tep: a handle to the tep_handle - * @lat: non zero for latency output format - * - * This sets the latency output format -  */ -void tep_set_latency_format(struct tep_handle *tep, int lat) -{ -	if (tep) -		tep->latency_format = lat; -} - -/**   * tep_is_old_format - get if an old kernel is used   * @tep: a handle to the tep_handle   * @@ -345,19 +318,6 @@ bool tep_is_old_format(struct tep_handle *tep)  }  /** - * tep_set_print_raw - set a flag to force print in raw format - * @tep: a handle to the tep_handle - * @print_raw: the new value of the print_raw flag - * - * This sets a flag to force print in raw format - */ -void tep_set_print_raw(struct tep_handle *tep, int print_raw) -{ -	if (tep) -		tep->print_raw = print_raw; -} - -/**   * tep_set_test_filters - set a flag to test a filter string   * @tep: a handle to the tep_handle   * @test_filters: the new value of the test_filters flag diff --git a/tools/lib/traceevent/event-parse-local.h b/tools/lib/traceevent/event-parse-local.h index 09aa142f7fdd..cee469803a34 100644 --- a/tools/lib/traceevent/event-parse-local.h +++ b/tools/lib/traceevent/event-parse-local.h @@ -28,8 +28,6 @@ struct tep_handle {  	enum tep_endian file_bigendian;  	enum tep_endian host_bigendian; -	int latency_format; -  	int old_format;  	int cpus; @@ -70,8 +68,6 @@ struct tep_handle {  	int ld_offset;  	int ld_size; -	int print_raw; -  	int test_filters;  	int flags; @@ -85,8 +81,6 @@ struct tep_handle {  	/* cache */  	struct tep_event *last_event; - -	char *trace_clock;  };  void tep_free_event(struct tep_event *event); diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index b36b536a9fcb..d948475585ce 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -142,6 +142,25 @@ static int cmdline_cmp(const void *a, const void *b)  	return 0;  } +/* Looking for where to place the key */ +static int cmdline_slot_cmp(const void *a, const void *b) +{ +	const struct tep_cmdline *ca = a; +	const struct tep_cmdline *cb = b; +	const struct tep_cmdline *cb1 = cb + 1; + +	if (ca->pid < cb->pid) +		return -1; + +	if (ca->pid > cb->pid) { +		if (ca->pid <= cb1->pid) +			return 0; +		return 1; +	} + +	return 0; +} +  struct cmdline_list {  	struct cmdline_list	*next;  	char			*comm; @@ -239,6 +258,7 @@ static int add_new_comm(struct tep_handle *tep,  	struct tep_cmdline *cmdline;  	struct tep_cmdline key;  	char *new_comm; +	int cnt;  	if (!pid)  		return 0; @@ -269,21 +289,43 @@ static int add_new_comm(struct tep_handle *tep,  		errno = ENOMEM;  		return -1;  	} +	tep->cmdlines = cmdlines; -	cmdlines[tep->cmdline_count].comm = strdup(comm); -	if (!cmdlines[tep->cmdline_count].comm) { -		free(cmdlines); +	key.comm = strdup(comm); +	if (!key.comm) {  		errno = ENOMEM;  		return -1;  	} -	cmdlines[tep->cmdline_count].pid = pid; -		 -	if (cmdlines[tep->cmdline_count].comm) +	if (!tep->cmdline_count) { +		/* no entries yet */ +		tep->cmdlines[0] = key;  		tep->cmdline_count++; +		return 0; +	} -	qsort(cmdlines, tep->cmdline_count, sizeof(*cmdlines), cmdline_cmp); -	tep->cmdlines = cmdlines; +	/* Now find where we want to store the new cmdline */ +	cmdline = bsearch(&key, tep->cmdlines, tep->cmdline_count - 1, +			  sizeof(*tep->cmdlines), cmdline_slot_cmp); + +	cnt = tep->cmdline_count; +	if (cmdline) { +		/* cmdline points to the one before the spot we want */ +		cmdline++; +		cnt -= cmdline - tep->cmdlines; + +	} else { +		/* The new entry is either before or after the list */ +		if (key.pid > tep->cmdlines[tep->cmdline_count - 1].pid) { +			tep->cmdlines[tep->cmdline_count++] = key; +			return 0; +		} +		cmdline = &tep->cmdlines[0]; +	} +	memmove(cmdline + 1, cmdline, (cnt * sizeof(*cmdline))); +	*cmdline = key; + +	tep->cmdline_count++;  	return 0;  } @@ -351,16 +393,6 @@ int tep_override_comm(struct tep_handle *tep, const char *comm, int pid)  	return _tep_register_comm(tep, comm, pid, true);  } -int tep_register_trace_clock(struct tep_handle *tep, const char *trace_clock) -{ -	tep->trace_clock = strdup(trace_clock); -	if (!tep->trace_clock) { -		errno = ENOMEM; -		return -1; -	} -	return 0; -} -  struct func_map {  	unsigned long long		addr;  	char				*func; @@ -4335,10 +4367,20 @@ static struct tep_print_arg *make_bprint_args(char *fmt, void *data, int size, s  					switch (*ptr) {  					case 's':  					case 'S': -					case 'f': -					case 'F':  					case 'x':  						break; +					case 'f': +					case 'F': +						/* +						 * Pre-5.5 kernels use %pf and +						 * %pF for printing symbols +						 * while kernels since 5.5 use +						 * %pfw for fwnodes. So check +						 * %p[fF] isn't followed by 'w'. +						 */ +						if (ptr[1] != 'w') +							break; +						/* fall through */  					default:  						/*  						 * Older kernels do not process @@ -4455,12 +4497,12 @@ get_bprint_format(void *data, int size __maybe_unused,  	printk = find_printk(tep, addr);  	if (!printk) { -		if (asprintf(&format, "%%pf: (NO FORMAT FOUND at %llx)\n", addr) < 0) +		if (asprintf(&format, "%%ps: (NO FORMAT FOUND at %llx)\n", addr) < 0)  			return NULL;  		return format;  	} -	if (asprintf(&format, "%s: %s", "%pf", printk->printk) < 0) +	if (asprintf(&format, "%s: %s", "%ps", printk->printk) < 0)  		return NULL;  	return format; @@ -5170,24 +5212,20 @@ out_failed:  	}  } -/** - * tep_data_latency_format - parse the data for the latency format - * @tep: a handle to the trace event parser context - * @s: the trace_seq to write to - * @record: the record to read from - * +/*   * This parses out the Latency format (interrupts disabled,   * need rescheduling, in hard/soft interrupt, preempt count   * and lock depth) and places it into the trace_seq.   */ -void tep_data_latency_format(struct tep_handle *tep, -			     struct trace_seq *s, struct tep_record *record) +static void data_latency_format(struct tep_handle *tep, struct trace_seq *s, +				char *format, struct tep_record *record)  {  	static int check_lock_depth = 1;  	static int check_migrate_disable = 1;  	static int lock_depth_exists;  	static int migrate_disable_exists;  	unsigned int lat_flags; +	struct trace_seq sq;  	unsigned int pc;  	int lock_depth = 0;  	int migrate_disable = 0; @@ -5195,6 +5233,7 @@ void tep_data_latency_format(struct tep_handle *tep,  	int softirq;  	void *data = record->data; +	trace_seq_init(&sq);  	lat_flags = parse_common_flags(tep, data);  	pc = parse_common_pc(tep, data);  	/* lock_depth may not always exist */ @@ -5222,7 +5261,7 @@ void tep_data_latency_format(struct tep_handle *tep,  	hardirq = lat_flags & TRACE_FLAG_HARDIRQ;  	softirq = lat_flags & TRACE_FLAG_SOFTIRQ; -	trace_seq_printf(s, "%c%c%c", +	trace_seq_printf(&sq, "%c%c%c",  	       (lat_flags & TRACE_FLAG_IRQS_OFF) ? 'd' :  	       (lat_flags & TRACE_FLAG_IRQS_NOSUPPORT) ?  	       'X' : '.', @@ -5232,24 +5271,32 @@ void tep_data_latency_format(struct tep_handle *tep,  	       hardirq ? 'h' : softirq ? 's' : '.');  	if (pc) -		trace_seq_printf(s, "%x", pc); +		trace_seq_printf(&sq, "%x", pc);  	else -		trace_seq_putc(s, '.'); +		trace_seq_printf(&sq, ".");  	if (migrate_disable_exists) {  		if (migrate_disable < 0) -			trace_seq_putc(s, '.'); +			trace_seq_printf(&sq, ".");  		else -			trace_seq_printf(s, "%d", migrate_disable); +			trace_seq_printf(&sq, "%d", migrate_disable);  	}  	if (lock_depth_exists) {  		if (lock_depth < 0) -			trace_seq_putc(s, '.'); +			trace_seq_printf(&sq, ".");  		else -			trace_seq_printf(s, "%d", lock_depth); +			trace_seq_printf(&sq, "%d", lock_depth); +	} + +	if (sq.state == TRACE_SEQ__MEM_ALLOC_FAILED) { +		s->state = TRACE_SEQ__MEM_ALLOC_FAILED; +		return;  	} +	trace_seq_terminate(&sq); +	trace_seq_puts(s, sq.buffer); +	trace_seq_destroy(&sq);  	trace_seq_terminate(s);  } @@ -5410,21 +5457,16 @@ int tep_cmdline_pid(struct tep_handle *tep, struct tep_cmdline *cmdline)  	return cmdline->pid;  } -/** - * tep_event_info - parse the data into the print format - * @s: the trace_seq to write to - * @event: the handle to the event - * @record: the record to read from - * +/*   * This parses the raw @data using the given @event information and   * writes the print format into the trace_seq.   */ -void tep_event_info(struct trace_seq *s, struct tep_event *event, -		    struct tep_record *record) +static void print_event_info(struct trace_seq *s, char *format, bool raw, +			     struct tep_event *event, struct tep_record *record)  {  	int print_pretty = 1; -	if (event->tep->print_raw || (event->flags & TEP_EVENT_FL_PRINTRAW)) +	if (raw || (event->flags & TEP_EVENT_FL_PRINTRAW))  		tep_print_fields(s, record->data, record->size, event);  	else { @@ -5439,20 +5481,6 @@ void tep_event_info(struct trace_seq *s, struct tep_event *event,  	trace_seq_terminate(s);  } -static bool is_timestamp_in_us(char *trace_clock, bool use_trace_clock) -{ -	if (!trace_clock || !use_trace_clock) -		return true; - -	if (!strcmp(trace_clock, "local") || !strcmp(trace_clock, "global") -	    || !strcmp(trace_clock, "uptime") || !strcmp(trace_clock, "perf") -	    || !strncmp(trace_clock, "mono", 4)) -		return true; - -	/* trace_clock is setting in tsc or counter mode */ -	return false; -} -  /**   * tep_find_event_by_record - return the event from a given record   * @tep: a handle to the trace event parser context @@ -5476,129 +5504,197 @@ tep_find_event_by_record(struct tep_handle *tep, struct tep_record *record)  	return tep_find_event(tep, type);  } -/** - * tep_print_event_task - Write the event task comm, pid and CPU - * @tep: a handle to the trace event parser context - * @s: the trace_seq to write to - * @event: the handle to the record's event - * @record: The record to get the event from - * - * Writes the tasks comm, pid and CPU to @s. +/* + * Writes the timestamp of the record into @s. Time divisor and precision can be + * specified as part of printf @format string. Example: + *	"%3.1000d" - divide the time by 1000 and print the first 3 digits + *	before the dot. Thus, the timestamp "123456000" will be printed as + *	"123.456"   */ -void tep_print_event_task(struct tep_handle *tep, struct trace_seq *s, -			  struct tep_event *event, -			  struct tep_record *record) +static void print_event_time(struct tep_handle *tep, struct trace_seq *s, +				 char *format, struct tep_event *event, +				 struct tep_record *record) +{ +	unsigned long long time; +	char *divstr; +	int prec = 0, pr; +	int div = 0; +	int p10 = 1; + +	if (isdigit(*(format + 1))) +		prec = atoi(format + 1); +	divstr = strchr(format, '.'); +	if (divstr && isdigit(*(divstr + 1))) +		div = atoi(divstr + 1); +	time = record->ts; +	if (div) { +		time += div / 2; +		time /= div; +	} +	pr = prec; +	while (pr--) +		p10 *= 10; + +	if (p10 > 1 && p10 < time) +		trace_seq_printf(s, "%5llu.%0*llu", time / p10, prec, time % p10); +	else +		trace_seq_printf(s, "%12llu\n", time); +} + +struct print_event_type { +	enum { +		EVENT_TYPE_INT = 1, +		EVENT_TYPE_STRING, +		EVENT_TYPE_UNKNOWN, +	} type; +	char format[32]; +}; + +static void print_string(struct tep_handle *tep, struct trace_seq *s, +			 struct tep_record *record, struct tep_event *event, +			 const char *arg, struct print_event_type *type)  { -	void *data = record->data;  	const char *comm;  	int pid; -	pid = parse_common_pid(tep, data); -	comm = find_cmdline(tep, pid); +	if (strncmp(arg, TEP_PRINT_LATENCY, strlen(TEP_PRINT_LATENCY)) == 0) { +		data_latency_format(tep, s, type->format, record); +	} else if (strncmp(arg, TEP_PRINT_COMM, strlen(TEP_PRINT_COMM)) == 0) { +		pid = parse_common_pid(tep, record->data); +		comm = find_cmdline(tep, pid); +		trace_seq_printf(s, type->format, comm); +	} else if (strncmp(arg, TEP_PRINT_INFO_RAW, strlen(TEP_PRINT_INFO_RAW)) == 0) { +		print_event_info(s, type->format, true, event, record); +	} else if (strncmp(arg, TEP_PRINT_INFO, strlen(TEP_PRINT_INFO)) == 0) { +		print_event_info(s, type->format, false, event, record); +	} else if  (strncmp(arg, TEP_PRINT_NAME, strlen(TEP_PRINT_NAME)) == 0) { +		trace_seq_printf(s, type->format, event->name); +	} else { +		trace_seq_printf(s, "[UNKNOWN TEP TYPE %s]", arg); +	} -	if (tep->latency_format) -		trace_seq_printf(s, "%8.8s-%-5d %3d", comm, pid, record->cpu); -	else -		trace_seq_printf(s, "%16s-%-5d [%03d]", comm, pid, record->cpu);  } -/** - * tep_print_event_time - Write the event timestamp - * @tep: a handle to the trace event parser context - * @s: the trace_seq to write to - * @event: the handle to the record's event - * @record: The record to get the event from - * @use_trace_clock: Set to parse according to the @tep->trace_clock - * - * Writes the timestamp of the record into @s. - */ -void tep_print_event_time(struct tep_handle *tep, struct trace_seq *s, -			  struct tep_event *event, -			  struct tep_record *record, -			  bool use_trace_clock) +static void print_int(struct tep_handle *tep, struct trace_seq *s, +		      struct tep_record *record, struct tep_event *event, +		      int arg, struct print_event_type *type)  { -	unsigned long secs; -	unsigned long usecs; -	unsigned long nsecs; -	int p; -	bool use_usec_format; +	int param; -	use_usec_format = is_timestamp_in_us(tep->trace_clock, use_trace_clock); -	if (use_usec_format) { -		secs = record->ts / NSEC_PER_SEC; -		nsecs = record->ts - secs * NSEC_PER_SEC; +	switch (arg) { +	case TEP_PRINT_CPU: +		param = record->cpu; +		break; +	case TEP_PRINT_PID: +		param = parse_common_pid(tep, record->data); +		break; +	case TEP_PRINT_TIME: +		return print_event_time(tep, s, type->format, event, record); +	default: +		return;  	} +	trace_seq_printf(s, type->format, param); +} -	if (tep->latency_format) { -		tep_data_latency_format(tep, s, record); -	} +static int tep_print_event_param_type(char *format, +				      struct print_event_type *type) +{ +	char *str = format + 1; +	int i = 1; -	if (use_usec_format) { -		if (tep->flags & TEP_NSEC_OUTPUT) { -			usecs = nsecs; -			p = 9; -		} else { -			usecs = (nsecs + 500) / NSEC_PER_USEC; -			/* To avoid usecs larger than 1 sec */ -			if (usecs >= USEC_PER_SEC) { -				usecs -= USEC_PER_SEC; -				secs++; -			} -			p = 6; +	type->type = EVENT_TYPE_UNKNOWN; +	while (*str) { +		switch (*str) { +		case 'd': +		case 'u': +		case 'i': +		case 'x': +		case 'X': +		case 'o': +			type->type = EVENT_TYPE_INT; +			break; +		case 's': +			type->type = EVENT_TYPE_STRING; +			break;  		} - -		trace_seq_printf(s, " %5lu.%0*lu:", secs, p, usecs); -	} else -		trace_seq_printf(s, " %12llu:", record->ts); +		str++; +		i++; +		if (type->type != EVENT_TYPE_UNKNOWN) +			break; +	} +	memset(type->format, 0, 32); +	memcpy(type->format, format, i < 32 ? i : 31); +	return i;  }  /** - * tep_print_event_data - Write the event data section + * tep_print_event - Write various event information   * @tep: a handle to the trace event parser context   * @s: the trace_seq to write to - * @event: the handle to the record's event   * @record: The record to get the event from - * - * Writes the parsing of the record's data to @s. + * @format: a printf format string. Supported event fileds: + *	TEP_PRINT_PID, "%d" - event PID + *	TEP_PRINT_CPU, "%d" - event CPU + *	TEP_PRINT_COMM, "%s" - event command string + *	TEP_PRINT_NAME, "%s" - event name + *	TEP_PRINT_LATENCY, "%s" - event latency + *	TEP_PRINT_TIME, %d - event time stamp. A divisor and precision + *			can be specified as part of this format string: + *			"%precision.divisord". Example: + *			"%3.1000d" - divide the time by 1000 and print the first + *			3 digits before the dot. Thus, the time stamp + *			"123456000" will be printed as "123.456" + *	TEP_PRINT_INFO, "%s" - event information. If any width is specified in + *			the format string, the event information will be printed + *			in raw format. + * Writes the specified event information into @s.   */ -void tep_print_event_data(struct tep_handle *tep, struct trace_seq *s, -			  struct tep_event *event, -			  struct tep_record *record) -{ -	static const char *spaces = "                    "; /* 20 spaces */ -	int len; - -	trace_seq_printf(s, " %s: ", event->name); - -	/* Space out the event names evenly. */ -	len = strlen(event->name); -	if (len < 20) -		trace_seq_printf(s, "%.*s", 20 - len, spaces); - -	tep_event_info(s, event, record); -} -  void tep_print_event(struct tep_handle *tep, struct trace_seq *s, -		     struct tep_record *record, bool use_trace_clock) -{ +		     struct tep_record *record, const char *fmt, ...) +{ +	struct print_event_type type; +	char *format = strdup(fmt); +	char *current = format; +	char *str = format; +	int offset; +	va_list args;  	struct tep_event *event; -	event = tep_find_event_by_record(tep, record); -	if (!event) { -		int i; -		int type = trace_parse_common_type(tep, record->data); - -		do_warning("ug! no event found for type %d", type); -		trace_seq_printf(s, "[UNKNOWN TYPE %d]", type); -		for (i = 0; i < record->size; i++) -			trace_seq_printf(s, " %02x", -					 ((unsigned char *)record->data)[i]); +	if (!format)  		return; -	} -	tep_print_event_task(tep, s, event, record); -	tep_print_event_time(tep, s, event, record, use_trace_clock); -	tep_print_event_data(tep, s, event, record); +	event = tep_find_event_by_record(tep, record); +	va_start(args, fmt); +	while (*current) { +		current = strchr(str, '%'); +		if (!current) { +			trace_seq_puts(s, str); +			break; +		} +		memset(&type, 0, sizeof(type)); +		offset = tep_print_event_param_type(current, &type); +		*current = '\0'; +		trace_seq_puts(s, str); +		current += offset; +		switch (type.type) { +		case EVENT_TYPE_STRING: +			print_string(tep, s, record, event, +				     va_arg(args, char*), &type); +			break; +		case EVENT_TYPE_INT: +			print_int(tep, s, record, event, +				  va_arg(args, int), &type); +			break; +		case EVENT_TYPE_UNKNOWN: +		default: +			trace_seq_printf(s, "[UNKNOWN TYPE]"); +			break; +		} +		str = current; + +	} +	va_end(args); +	free(format);  }  static int events_id_cmp(const void *a, const void *b) @@ -6963,7 +7059,6 @@ void tep_free(struct tep_handle *tep)  		free_handler(handle);  	} -	free(tep->trace_clock);  	free(tep->events);  	free(tep->sort_events);  	free(tep->func_resolver); diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 642f68ab5fb2..b77837f75a0d 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -435,25 +435,26 @@ int tep_set_function_resolver(struct tep_handle *tep,  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_register_trace_clock(struct tep_handle *tep, const char *trace_clock);  int tep_register_function(struct tep_handle *tep, char *name,  			  unsigned long long addr, char *mod);  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); -void tep_print_event_task(struct tep_handle *tep, struct trace_seq *s, -			  struct tep_event *event, -			  struct tep_record *record); -void tep_print_event_time(struct tep_handle *tep, struct trace_seq *s, -			  struct tep_event *event, -			  struct tep_record *record, -			  bool use_trace_clock); -void tep_print_event_data(struct tep_handle *tep, struct trace_seq *s, -			  struct tep_event *event, -			  struct tep_record *record); +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, bool use_trace_clock); +		     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); @@ -525,8 +526,6 @@ 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); -void tep_data_latency_format(struct tep_handle *tep, -			     struct trace_seq *s, 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); @@ -541,8 +540,6 @@ 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); -void tep_event_info(struct trace_seq *s, struct tep_event *event, -		    struct tep_record *record);  int tep_strerror(struct tep_handle *tep, enum tep_errno errnum,  		 char *buf, size_t buflen); @@ -566,12 +563,9 @@ 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); -bool tep_is_latency_format(struct tep_handle *tep); -void tep_set_latency_format(struct tep_handle *tep, int lat);  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_print_raw(struct tep_handle *tep, int print_raw);  void tep_set_test_filters(struct tep_handle *tep, int test_filters);  struct tep_handle *tep_alloc(void); diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c index 8ca28de9337a..e1f7ddd5a6cf 100644 --- a/tools/lib/traceevent/event-plugin.c +++ b/tools/lib/traceevent/event-plugin.c @@ -18,7 +18,7 @@  #include "event-utils.h"  #include "trace-seq.h" -#define LOCAL_PLUGIN_DIR ".traceevent/plugins" +#define LOCAL_PLUGIN_DIR ".local/lib/traceevent/plugins/"  static struct registered_plugin_options {  	struct registered_plugin_options	*next; diff --git a/tools/lib/traceevent/plugins/Build b/tools/lib/traceevent/plugins/Build new file mode 100644 index 000000000000..210d26910613 --- /dev/null +++ b/tools/lib/traceevent/plugins/Build @@ -0,0 +1,10 @@ +plugin_jbd2-y         += plugin_jbd2.o +plugin_hrtimer-y      += plugin_hrtimer.o +plugin_kmem-y         += plugin_kmem.o +plugin_kvm-y          += plugin_kvm.o +plugin_mac80211-y     += plugin_mac80211.o +plugin_sched_switch-y += plugin_sched_switch.o +plugin_function-y     += plugin_function.o +plugin_xen-y          += plugin_xen.o +plugin_scsi-y         += plugin_scsi.o +plugin_cfg80211-y     += plugin_cfg80211.o diff --git a/tools/lib/traceevent/plugins/Makefile b/tools/lib/traceevent/plugins/Makefile new file mode 100644 index 000000000000..f440989fa55e --- /dev/null +++ b/tools/lib/traceevent/plugins/Makefile @@ -0,0 +1,222 @@ +# SPDX-License-Identifier: GPL-2.0 + +#MAKEFLAGS += --no-print-directory + + +# Makefiles suck: This macro sets a default value of $(2) for the +# variable named by $(1), unless the variable has been set by +# environment or command line. This is necessary for CC and AR +# because make sets default values, so the simpler ?= approach +# won't work as expected. +define allow-override +  $(if $(or $(findstring environment,$(origin $(1))),\ +            $(findstring command line,$(origin $(1)))),,\ +    $(eval $(1) = $(2))) +endef + +# Allow setting CC and AR, or setting CROSS_COMPILE as a prefix. +$(call allow-override,CC,$(CROSS_COMPILE)gcc) +$(call allow-override,AR,$(CROSS_COMPILE)ar) +$(call allow-override,NM,$(CROSS_COMPILE)nm) +$(call allow-override,PKG_CONFIG,pkg-config) + +EXT = -std=gnu99 +INSTALL = install + +# Use DESTDIR for installing into a different root directory. +# This is useful for building a package. The program will be +# installed in this directory as if it was the root directory. +# Then the build tool can move it later. +DESTDIR ?= +DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))' + +LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1) +ifeq ($(LP64), 1) +  libdir_relative = lib64 +else +  libdir_relative = lib +endif + +prefix ?= /usr/local +libdir = $(prefix)/$(libdir_relative) + +set_plugin_dir := 1 + +# Set plugin_dir to preffered global plugin location +# If we install under $HOME directory we go under +# $(HOME)/.local/lib/traceevent/plugins +# +# We dont set PLUGIN_DIR in case we install under $HOME +# directory, because by default the code looks under: +# $(HOME)/.local/lib/traceevent/plugins by default. +# +ifeq ($(plugin_dir),) +ifeq ($(prefix),$(HOME)) +override plugin_dir = $(HOME)/.local/lib/traceevent/plugins +set_plugin_dir := 0 +else +override plugin_dir = $(libdir)/traceevent/plugins +endif +endif + +ifeq ($(set_plugin_dir),1) +PLUGIN_DIR = -DPLUGIN_DIR="$(plugin_dir)" +PLUGIN_DIR_SQ = '$(subst ','\'',$(PLUGIN_DIR))' +endif + +include ../../../scripts/Makefile.include + +# copy a bit from Linux kbuild + +ifeq ("$(origin V)", "command line") +  VERBOSE = $(V) +endif +ifndef VERBOSE +  VERBOSE = 0 +endif + +ifeq ($(srctree),) +srctree := $(patsubst %/,%,$(dir $(CURDIR))) +srctree := $(patsubst %/,%,$(dir $(srctree))) +srctree := $(patsubst %/,%,$(dir $(srctree))) +srctree := $(patsubst %/,%,$(dir $(srctree))) +#$(info Determined 'srctree' to be $(srctree)) +endif + +export prefix libdir src obj + +# Shell quotes +plugin_dir_SQ = $(subst ','\'',$(plugin_dir)) + +CONFIG_INCLUDES = +CONFIG_LIBS    = +CONFIG_FLAGS   = + +OBJ            = $@ +N              = + +INCLUDES = -I. -I.. -I $(srctree)/tools/include $(CONFIG_INCLUDES) + +# Set compile option CFLAGS +ifdef EXTRA_CFLAGS +  CFLAGS := $(EXTRA_CFLAGS) +else +  CFLAGS := -g -Wall +endif + +# Append required CFLAGS +override CFLAGS += -fPIC +override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ) +override CFLAGS += $(udis86-flags) -D_GNU_SOURCE + +ifeq ($(VERBOSE),1) +  Q = +else +  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)/tools/build/Makefile.build dir=. obj + +DYNAMIC_LIST_FILE := $(OUTPUT)libtraceevent-dynamic-list + +PLUGINS  = plugin_jbd2.so +PLUGINS += plugin_hrtimer.so +PLUGINS += plugin_kmem.so +PLUGINS += plugin_kvm.so +PLUGINS += plugin_mac80211.so +PLUGINS += plugin_sched_switch.so +PLUGINS += plugin_function.so +PLUGINS += plugin_xen.so +PLUGINS += plugin_scsi.so +PLUGINS += plugin_cfg80211.so + +PLUGINS    := $(addprefix $(OUTPUT),$(PLUGINS)) +PLUGINS_IN := $(PLUGINS:.so=-in.o) + +plugins: $(PLUGINS) $(DYNAMIC_LIST_FILE) + +__plugin_obj = $(notdir $@) +  plugin_obj = $(__plugin_obj:-in.o=) + +$(PLUGINS_IN): force +	$(Q)$(MAKE) $(build)=$(plugin_obj) + +$(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 $@ $^ + +define update_dir +  (echo $1 > $@.tmp;                           \ +   if [ -r $@ ] && cmp -s $@ $@.tmp; then      \ +     rm -f $@.tmp;                             \ +   else                                                \ +     echo '  UPDATE                 $@';       \ +     mv -f $@.tmp $@;                          \ +   fi); +endef + +tags:	force +	$(RM) tags +	find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \ +	--regex-c++='/_PE\(([^,)]*).*/TEP_ERRNO__\1/' + +TAGS:	force +	$(RM) TAGS +	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)); \ +       done +endef + +define do_generate_dynamic_list_file +	symbol_type=`$(NM) -u -D $1 | 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 $1 | awk 'NF>1 {print "\t"$$2";"}' | sort -u;\ +		echo '};';                                              \ +		) > $2;                                                 \ +	else                                                            \ +		(echo Either missing one of [$1] or bad version of $(NM)) 1>&2;\ +		fi +endef + +install: $(PLUGINS) +	$(call QUIET_INSTALL, trace_plugins) \ +	$(call do_install_plugins, $(PLUGINS)) + +clean: +	$(call QUIET_CLEAN, trace_plugins) \ +		$(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d .*.cmd; \ +		$(RM) $(OUTPUT)libtraceevent-dynamic-list \ +		$(RM) TRACEEVENT-CFLAGS tags TAGS; + +PHONY += force plugins +force: + +# Declare the contents of the .PHONY variable as phony.  We keep that +# information in a variable so we can use it in if_changed and friends. +.PHONY: $(PHONY) diff --git a/tools/lib/traceevent/plugin_cfg80211.c b/tools/lib/traceevent/plugins/plugin_cfg80211.c index 3d43b56a6c98..3d43b56a6c98 100644 --- a/tools/lib/traceevent/plugin_cfg80211.c +++ b/tools/lib/traceevent/plugins/plugin_cfg80211.c diff --git a/tools/lib/traceevent/plugin_function.c b/tools/lib/traceevent/plugins/plugin_function.c index 7770fcb78e0f..7770fcb78e0f 100644 --- a/tools/lib/traceevent/plugin_function.c +++ b/tools/lib/traceevent/plugins/plugin_function.c diff --git a/tools/lib/traceevent/plugin_hrtimer.c b/tools/lib/traceevent/plugins/plugin_hrtimer.c index bb434e0ed03a..bb434e0ed03a 100644 --- a/tools/lib/traceevent/plugin_hrtimer.c +++ b/tools/lib/traceevent/plugins/plugin_hrtimer.c diff --git a/tools/lib/traceevent/plugin_jbd2.c b/tools/lib/traceevent/plugins/plugin_jbd2.c index 04fc125f38cb..04fc125f38cb 100644 --- a/tools/lib/traceevent/plugin_jbd2.c +++ b/tools/lib/traceevent/plugins/plugin_jbd2.c diff --git a/tools/lib/traceevent/plugin_kmem.c b/tools/lib/traceevent/plugins/plugin_kmem.c index edaec5d962c3..edaec5d962c3 100644 --- a/tools/lib/traceevent/plugin_kmem.c +++ b/tools/lib/traceevent/plugins/plugin_kmem.c diff --git a/tools/lib/traceevent/plugin_kvm.c b/tools/lib/traceevent/plugins/plugin_kvm.c index c8e623065a7e..c8e623065a7e 100644 --- a/tools/lib/traceevent/plugin_kvm.c +++ b/tools/lib/traceevent/plugins/plugin_kvm.c diff --git a/tools/lib/traceevent/plugin_mac80211.c b/tools/lib/traceevent/plugins/plugin_mac80211.c index 884303c26b5c..884303c26b5c 100644 --- a/tools/lib/traceevent/plugin_mac80211.c +++ b/tools/lib/traceevent/plugins/plugin_mac80211.c diff --git a/tools/lib/traceevent/plugin_sched_switch.c b/tools/lib/traceevent/plugins/plugin_sched_switch.c index 957389a0ff7a..957389a0ff7a 100644 --- a/tools/lib/traceevent/plugin_sched_switch.c +++ b/tools/lib/traceevent/plugins/plugin_sched_switch.c diff --git a/tools/lib/traceevent/plugin_scsi.c b/tools/lib/traceevent/plugins/plugin_scsi.c index 5d0387a4b65a..5d0387a4b65a 100644 --- a/tools/lib/traceevent/plugin_scsi.c +++ b/tools/lib/traceevent/plugins/plugin_scsi.c diff --git a/tools/lib/traceevent/plugin_xen.c b/tools/lib/traceevent/plugins/plugin_xen.c index 993b208d0323..993b208d0323 100644 --- a/tools/lib/traceevent/plugin_xen.c +++ b/tools/lib/traceevent/plugins/plugin_xen.c  | 

