You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf updates from Arnaldo Carvalho de Melo: User visible changes: Improvements: * Support showing source code, asking for variables to be collected at probe time and other 'perf probe' operations that use DWARF information. This supports only binaries with debugging information at this time, detached debuginfo (aka debuginfo packages) support should come in later patches. (Masami Hiramatsu) * Add a perf.data file header window in the 'perf report' TUI, associated with the 'i' hotkey, providing a counterpart to the --header option in the stdio UI. (Namhyung Kim) * Guest related improvements to 'perf kvm', including allowing to specify a directory with guest specific /proc information. (Dongsheng Yang) * Print session information only if --stdio is given (Namhyung Kim) Developer stuff: Fixes: * Get rid of a duplicate va_end() in error reporting (Namhyung Kim) * If a hist entry doesn't have symbol information, compare it with its address. Affects upcoming new feature (--cumulate) (Namhyung Kim) Improvements: * Make libtraceevent install target quieter (Jiri Olsa) * Make tests/make output more compact (Jiri Olsa) * Ignore generated files in feature-checks (Chunwei Chen) New APIs: * Introduce pevent_filter_strerror() in libtraceevent, similar in purpose to libc's strerror() function. (Namhyung Kim) Refactorings: * Use perf_data_file methods to write output file in 'record' and 'inject' (Jiri Olsa) * Use pr_*() functions where applicable in 'report' (Namhyumg Kim) * Add 'machine' 'addr_location' struct to have full picture (machine, thread, map, symbol, addr) for a (partially) resolved address, reducing function signatures (Arnaldo Carvalho de Melo) * Reduce code duplication in the histogram entry creation/insertion. (Arnaldo Carvalho de Melo) * Auto allocate annotation histogram data structures, (Arnaldo Carvalho de Melo) * No need to test against NULL before calling free, also set freed memory in struct pointers to NULL, to help fixing use after free bugs. (Arnaldo Carvalho de Melo> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
@@ -67,6 +67,8 @@ PLUGIN_DIR = -DPLUGIN_DIR="$(DESTDIR)/$(plugin_dir)"
|
||||
PLUGIN_DIR_SQ = '$(subst ','\'',$(PLUGIN_DIR))'
|
||||
endif
|
||||
|
||||
include $(if $(BUILD_SRC),$(BUILD_SRC)/)../../scripts/Makefile.include
|
||||
|
||||
# copy a bit from Linux kbuild
|
||||
|
||||
ifeq ("$(origin V)", "command line")
|
||||
@@ -81,18 +83,13 @@ ifeq ("$(origin O)", "command line")
|
||||
endif
|
||||
|
||||
ifeq ($(BUILD_SRC),)
|
||||
ifneq ($(BUILD_OUTPUT),)
|
||||
ifneq ($(OUTPUT),)
|
||||
|
||||
define build_output
|
||||
$(if $(VERBOSE:1=),@)+$(MAKE) -C $(BUILD_OUTPUT) \
|
||||
BUILD_SRC=$(CURDIR) -f $(CURDIR)/Makefile $1
|
||||
$(if $(VERBOSE:1=),@)+$(MAKE) -C $(OUTPUT) \
|
||||
BUILD_SRC=$(CURDIR)/ -f $(CURDIR)/Makefile $1
|
||||
endef
|
||||
|
||||
saved-output := $(BUILD_OUTPUT)
|
||||
BUILD_OUTPUT := $(shell cd $(BUILD_OUTPUT) && /bin/pwd)
|
||||
$(if $(BUILD_OUTPUT),, \
|
||||
$(error output directory "$(saved-output)" does not exist))
|
||||
|
||||
all: sub-make
|
||||
|
||||
$(MAKECMDGOALS): sub-make
|
||||
@@ -104,7 +101,7 @@ sub-make: force
|
||||
# Leave processing to above invocation of make
|
||||
skip-makefile := 1
|
||||
|
||||
endif # BUILD_OUTPUT
|
||||
endif # OUTPUT
|
||||
endif # BUILD_SRC
|
||||
|
||||
# We process the rest of the Makefile if this is the final invocation of make
|
||||
@@ -150,41 +147,14 @@ override CFLAGS += $(udis86-flags) -D_GNU_SOURCE
|
||||
|
||||
ifeq ($(VERBOSE),1)
|
||||
Q =
|
||||
print_compile =
|
||||
print_app_build =
|
||||
print_fpic_compile =
|
||||
print_shared_lib_compile =
|
||||
print_plugin_obj_compile =
|
||||
print_plugin_build =
|
||||
print_install =
|
||||
else
|
||||
Q = @
|
||||
print_compile = echo ' CC '$(OBJ);
|
||||
print_app_build = echo ' BUILD '$(OBJ);
|
||||
print_fpic_compile = echo ' CC FPIC '$(OBJ);
|
||||
print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ);
|
||||
print_plugin_obj_compile = echo ' CC FPIC '$(OBJ);
|
||||
print_plugin_build = echo ' BUILD PLUGIN '$(OBJ);
|
||||
print_static_lib_build = echo ' BUILD STATIC LIB '$(OBJ);
|
||||
print_install = echo ' INSTALL '$1;
|
||||
endif
|
||||
|
||||
do_fpic_compile = \
|
||||
($(print_fpic_compile) \
|
||||
$(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@)
|
||||
|
||||
do_app_build = \
|
||||
($(print_app_build) \
|
||||
$(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS))
|
||||
|
||||
do_compile_shared_library = \
|
||||
($(print_shared_lib_compile) \
|
||||
$(CC) --shared $^ -o $@)
|
||||
|
||||
do_compile_plugin_obj = \
|
||||
($(print_plugin_obj_compile) \
|
||||
$(CC) -c $(CFLAGS) -fPIC -o $@ $<)
|
||||
|
||||
do_plugin_build = \
|
||||
($(print_plugin_build) \
|
||||
$(CC) $(CFLAGS) -shared -nostartfiles -o $@ $<)
|
||||
@@ -194,16 +164,13 @@ do_build_static_lib = \
|
||||
$(RM) $@; $(AR) rcs $@ $^)
|
||||
|
||||
|
||||
define do_compile
|
||||
$(print_compile) \
|
||||
$(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@;
|
||||
endef
|
||||
do_compile = $(QUIET_CC)$(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@;
|
||||
|
||||
$(obj)/%.o: $(src)/%.c
|
||||
$(Q)$(call do_compile)
|
||||
$(call do_compile)
|
||||
|
||||
%.o: $(src)/%.c
|
||||
$(Q)$(call do_compile)
|
||||
$(call do_compile)
|
||||
|
||||
PEVENT_LIB_OBJS = event-parse.o
|
||||
PEVENT_LIB_OBJS += event-plugin.o
|
||||
@@ -237,21 +204,21 @@ all: all_cmd
|
||||
all_cmd: $(CMD_TARGETS)
|
||||
|
||||
libtraceevent.so: $(PEVENT_LIB_OBJS)
|
||||
$(Q)$(do_compile_shared_library)
|
||||
$(QUIET_LINK)$(CC) --shared $^ -o $@
|
||||
|
||||
libtraceevent.a: $(PEVENT_LIB_OBJS)
|
||||
$(Q)$(do_build_static_lib)
|
||||
$(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^
|
||||
|
||||
plugins: $(PLUGINS)
|
||||
|
||||
$(PEVENT_LIB_OBJS): %.o: $(src)/%.c TRACEEVENT-CFLAGS
|
||||
$(Q)$(do_fpic_compile)
|
||||
$(QUIET_CC_FPIC)$(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@
|
||||
|
||||
$(PLUGIN_OBJS): %.o : $(src)/%.c
|
||||
$(Q)$(do_compile_plugin_obj)
|
||||
$(QUIET_CC_FPIC)$(CC) -c $(CFLAGS) -fPIC -o $@ $<
|
||||
|
||||
$(PLUGINS): %.so: %.o
|
||||
$(Q)$(do_plugin_build)
|
||||
$(QUIET_LINK)$(CC) $(CFLAGS) -shared -nostartfiles -o $@ $<
|
||||
|
||||
define make_version.h
|
||||
(echo '/* This file is automatically generated. Do not modify. */'; \
|
||||
@@ -333,28 +300,32 @@ TAGS: force
|
||||
--regex='/_PE(\([^,)]*\).*/PEVENT_ERRNO__\1/'
|
||||
|
||||
define do_install
|
||||
$(print_install) \
|
||||
if [ ! -d '$(DESTDIR_SQ)$2' ]; then \
|
||||
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \
|
||||
fi; \
|
||||
$(INSTALL) $1 '$(DESTDIR_SQ)$2'
|
||||
endef
|
||||
|
||||
define do_install_plugins
|
||||
for plugin in $1; do \
|
||||
$(call do_install,$$plugin,$(plugin_dir_SQ)); \
|
||||
done
|
||||
endef
|
||||
|
||||
install_lib: all_cmd install_plugins
|
||||
$(Q)$(call do_install,$(LIB_FILE),$(bindir_SQ))
|
||||
$(call QUIET_INSTALL, $(LIB_FILE)) \
|
||||
$(call do_install,$(LIB_FILE),$(bindir_SQ))
|
||||
|
||||
PLUGINS_INSTALL = $(subst .so,.install,$(PLUGINS))
|
||||
|
||||
$(PLUGINS_INSTALL): %.install : %.so force
|
||||
$(Q)$(call do_install,$<,$(plugin_dir_SQ))
|
||||
|
||||
install_plugins: $(PLUGINS_INSTALL)
|
||||
install_plugins: $(PLUGINS)
|
||||
$(call QUIET_INSTALL, trace_plugins) \
|
||||
$(call do_install_plugins, $(PLUGINS))
|
||||
|
||||
install: install_lib
|
||||
|
||||
clean:
|
||||
$(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d
|
||||
$(RM) TRACEEVENT-CFLAGS tags TAGS
|
||||
$(call QUIET_CLEAN, libtraceevent) \
|
||||
$(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d \
|
||||
$(RM) TRACEEVENT-CFLAGS tags TAGS
|
||||
|
||||
endif # skip-makefile
|
||||
|
||||
|
||||
@@ -5230,22 +5230,7 @@ int pevent_strerror(struct pevent *pevent __maybe_unused,
|
||||
|
||||
idx = errnum - __PEVENT_ERRNO__START - 1;
|
||||
msg = pevent_error_str[idx];
|
||||
|
||||
switch (errnum) {
|
||||
case PEVENT_ERRNO__MEM_ALLOC_FAILED:
|
||||
case PEVENT_ERRNO__PARSE_EVENT_FAILED:
|
||||
case PEVENT_ERRNO__READ_ID_FAILED:
|
||||
case PEVENT_ERRNO__READ_FORMAT_FAILED:
|
||||
case PEVENT_ERRNO__READ_PRINT_FAILED:
|
||||
case PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED:
|
||||
case PEVENT_ERRNO__INVALID_ARG_TYPE:
|
||||
snprintf(buf, buflen, "%s", msg);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* cannot reach here */
|
||||
break;
|
||||
}
|
||||
snprintf(buf, buflen, "%s", msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -851,10 +851,13 @@ struct filter_type {
|
||||
struct filter_arg *filter;
|
||||
};
|
||||
|
||||
#define PEVENT_FILTER_ERROR_BUFSZ 1024
|
||||
|
||||
struct event_filter {
|
||||
struct pevent *pevent;
|
||||
int filters;
|
||||
struct filter_type *event_filters;
|
||||
char error_buffer[PEVENT_FILTER_ERROR_BUFSZ];
|
||||
};
|
||||
|
||||
struct event_filter *pevent_filter_alloc(struct pevent *pevent);
|
||||
@@ -874,10 +877,12 @@ enum filter_trivial_type {
|
||||
enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter,
|
||||
const char *filter_str);
|
||||
|
||||
|
||||
enum pevent_errno pevent_filter_match(struct event_filter *filter,
|
||||
struct pevent_record *record);
|
||||
|
||||
int pevent_filter_strerror(struct event_filter *filter, enum pevent_errno err,
|
||||
char *buf, size_t buflen);
|
||||
|
||||
int pevent_event_filtered(struct event_filter *filter,
|
||||
int event_id);
|
||||
|
||||
|
||||
@@ -38,55 +38,31 @@ struct event_list {
|
||||
struct event_format *event;
|
||||
};
|
||||
|
||||
#define MAX_ERR_STR_SIZE 256
|
||||
|
||||
static void show_error(char **error_str, const char *fmt, ...)
|
||||
static void show_error(char *error_buf, const char *fmt, ...)
|
||||
{
|
||||
unsigned long long index;
|
||||
const char *input;
|
||||
char *error;
|
||||
va_list ap;
|
||||
int len;
|
||||
int i;
|
||||
|
||||
if (!error_str)
|
||||
return;
|
||||
|
||||
input = pevent_get_input_buf();
|
||||
index = pevent_get_input_buf_ptr();
|
||||
len = input ? strlen(input) : 0;
|
||||
|
||||
error = malloc(MAX_ERR_STR_SIZE + (len*2) + 3);
|
||||
if (error == NULL) {
|
||||
/*
|
||||
* Maybe it's due to len is too long.
|
||||
* Retry without the input buffer part.
|
||||
*/
|
||||
len = 0;
|
||||
|
||||
error = malloc(MAX_ERR_STR_SIZE);
|
||||
if (error == NULL) {
|
||||
/* no memory */
|
||||
*error_str = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (len) {
|
||||
strcpy(error, input);
|
||||
error[len] = '\n';
|
||||
strcpy(error_buf, input);
|
||||
error_buf[len] = '\n';
|
||||
for (i = 1; i < len && i < index; i++)
|
||||
error[len+i] = ' ';
|
||||
error[len + i] = '^';
|
||||
error[len + i + 1] = '\n';
|
||||
error_buf[len+i] = ' ';
|
||||
error_buf[len + i] = '^';
|
||||
error_buf[len + i + 1] = '\n';
|
||||
len += i+2;
|
||||
}
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(error + len, MAX_ERR_STR_SIZE, fmt, ap);
|
||||
vsnprintf(error_buf + len, PEVENT_FILTER_ERROR_BUFSZ - len, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
*error_str = error;
|
||||
}
|
||||
|
||||
static void free_token(char *token)
|
||||
@@ -370,7 +346,7 @@ static void free_events(struct event_list *events)
|
||||
|
||||
static enum pevent_errno
|
||||
create_arg_item(struct event_format *event, const char *token,
|
||||
enum event_type type, struct filter_arg **parg, char **error_str)
|
||||
enum event_type type, struct filter_arg **parg, char *error_str)
|
||||
{
|
||||
struct format_field *field;
|
||||
struct filter_arg *arg;
|
||||
@@ -474,7 +450,7 @@ create_arg_cmp(enum filter_exp_type etype)
|
||||
}
|
||||
|
||||
static enum pevent_errno
|
||||
add_right(struct filter_arg *op, struct filter_arg *arg, char **error_str)
|
||||
add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str)
|
||||
{
|
||||
struct filter_arg *left;
|
||||
char *str;
|
||||
@@ -786,7 +762,7 @@ enum filter_vals {
|
||||
|
||||
static enum pevent_errno
|
||||
reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
|
||||
struct filter_arg *arg, char **error_str)
|
||||
struct filter_arg *arg, char *error_str)
|
||||
{
|
||||
struct filter_arg *other_child;
|
||||
struct filter_arg **ptr;
|
||||
@@ -838,7 +814,7 @@ reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
|
||||
|
||||
/* Returns either filter_vals (success) or pevent_errno (failfure) */
|
||||
static int test_arg(struct filter_arg *parent, struct filter_arg *arg,
|
||||
char **error_str)
|
||||
char *error_str)
|
||||
{
|
||||
int lval, rval;
|
||||
|
||||
@@ -938,7 +914,7 @@ static int test_arg(struct filter_arg *parent, struct filter_arg *arg,
|
||||
|
||||
/* Remove any unknown event fields */
|
||||
static int collapse_tree(struct filter_arg *arg,
|
||||
struct filter_arg **arg_collapsed, char **error_str)
|
||||
struct filter_arg **arg_collapsed, char *error_str)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -973,7 +949,7 @@ static int collapse_tree(struct filter_arg *arg,
|
||||
|
||||
static enum pevent_errno
|
||||
process_filter(struct event_format *event, struct filter_arg **parg,
|
||||
char **error_str, int not)
|
||||
char *error_str, int not)
|
||||
{
|
||||
enum event_type type;
|
||||
char *token = NULL;
|
||||
@@ -1211,7 +1187,7 @@ process_filter(struct event_format *event, struct filter_arg **parg,
|
||||
|
||||
static enum pevent_errno
|
||||
process_event(struct event_format *event, const char *filter_str,
|
||||
struct filter_arg **parg, char **error_str)
|
||||
struct filter_arg **parg, char *error_str)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -1236,7 +1212,7 @@ process_event(struct event_format *event, const char *filter_str,
|
||||
|
||||
static enum pevent_errno
|
||||
filter_event(struct event_filter *filter, struct event_format *event,
|
||||
const char *filter_str, char **error_str)
|
||||
const char *filter_str, char *error_str)
|
||||
{
|
||||
struct filter_type *filter_type;
|
||||
struct filter_arg *arg;
|
||||
@@ -1268,13 +1244,21 @@ filter_event(struct event_filter *filter, struct event_format *event,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void filter_init_error_buf(struct event_filter *filter)
|
||||
{
|
||||
/* clear buffer to reset show error */
|
||||
pevent_buffer_init("", 0);
|
||||
filter->error_buffer[0] = '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
* pevent_filter_add_filter_str - add a new filter
|
||||
* @filter: the event filter to add to
|
||||
* @filter_str: the filter string that contains the filter
|
||||
*
|
||||
* Returns 0 if the filter was successfully added or a
|
||||
* negative error code.
|
||||
* negative error code. Use pevent_filter_strerror() to see
|
||||
* actual error message in case of error.
|
||||
*/
|
||||
enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter,
|
||||
const char *filter_str)
|
||||
@@ -1291,10 +1275,8 @@ enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter,
|
||||
enum pevent_errno rtn = 0; /* PEVENT_ERRNO__SUCCESS */
|
||||
int len;
|
||||
int ret;
|
||||
char *error_str = NULL;
|
||||
|
||||
/* clear buffer to reset show error */
|
||||
pevent_buffer_init("", 0);
|
||||
filter_init_error_buf(filter);
|
||||
|
||||
filter_start = strchr(filter_str, ':');
|
||||
if (filter_start)
|
||||
@@ -1353,7 +1335,7 @@ enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter,
|
||||
/* filter starts here */
|
||||
for (event = events; event; event = event->next) {
|
||||
ret = filter_event(filter, event->event, filter_start,
|
||||
&error_str);
|
||||
filter->error_buffer);
|
||||
/* Failures are returned if a parse error happened */
|
||||
if (ret < 0)
|
||||
rtn = ret;
|
||||
@@ -1381,6 +1363,32 @@ static void free_filter_type(struct filter_type *filter_type)
|
||||
free_arg(filter_type->filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* pevent_filter_strerror - fill error message in a buffer
|
||||
* @filter: the event filter contains error
|
||||
* @err: the error code
|
||||
* @buf: the buffer to be filled in
|
||||
* @buflen: the size of the buffer
|
||||
*
|
||||
* Returns 0 if message was filled successfully, -1 if error
|
||||
*/
|
||||
int pevent_filter_strerror(struct event_filter *filter, enum pevent_errno err,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
if (err <= __PEVENT_ERRNO__START || err >= __PEVENT_ERRNO__END)
|
||||
return -1;
|
||||
|
||||
if (strlen(filter->error_buffer) > 0) {
|
||||
size_t len = snprintf(buf, buflen, "%s", filter->error_buffer);
|
||||
|
||||
if (len > buflen)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pevent_strerror(filter->pevent, err, buf, buflen);
|
||||
}
|
||||
|
||||
/**
|
||||
* pevent_filter_remove_event - remove a filter for an event
|
||||
* @filter: the event filter to remove from
|
||||
@@ -2027,6 +2035,8 @@ enum pevent_errno pevent_filter_match(struct event_filter *filter,
|
||||
int ret;
|
||||
enum pevent_errno err = 0;
|
||||
|
||||
filter_init_error_buf(filter);
|
||||
|
||||
if (!filter->filters)
|
||||
return PEVENT_ERRNO__NO_FILTER;
|
||||
|
||||
|
||||
@@ -489,6 +489,7 @@ ifndef NO_SLANG
|
||||
LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
|
||||
LIB_OBJS += $(OUTPUT)ui/browsers/map.o
|
||||
LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o
|
||||
LIB_OBJS += $(OUTPUT)ui/browsers/header.o
|
||||
LIB_OBJS += $(OUTPUT)ui/tui/setup.o
|
||||
LIB_OBJS += $(OUTPUT)ui/tui/util.o
|
||||
LIB_OBJS += $(OUTPUT)ui/tui/helpline.o
|
||||
|
||||
@@ -154,8 +154,7 @@ static int perf_session_env__lookup_binutils_path(struct perf_session_env *env,
|
||||
}
|
||||
if (lookup_path(buf))
|
||||
goto out;
|
||||
free(buf);
|
||||
buf = NULL;
|
||||
zfree(&buf);
|
||||
}
|
||||
|
||||
if (!strcmp(arch, "arm"))
|
||||
|
||||
@@ -69,15 +69,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
|
||||
if (he == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = 0;
|
||||
if (he->ms.sym != NULL) {
|
||||
struct annotation *notes = symbol__annotation(he->ms.sym);
|
||||
if (notes->src == NULL && symbol__alloc_hist(he->ms.sym) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
|
||||
}
|
||||
|
||||
ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
|
||||
evsel->hists.stats.total_period += sample->period;
|
||||
hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
|
||||
return ret;
|
||||
@@ -188,8 +180,7 @@ find_next:
|
||||
* symbol, free he->ms.sym->src to signal we already
|
||||
* processed this symbol.
|
||||
*/
|
||||
free(notes->src);
|
||||
notes->src = NULL;
|
||||
zfree(¬es->src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -654,7 +654,7 @@ static void data__free(struct data__file *d)
|
||||
for (col = 0; col < PERF_HPP_DIFF__MAX_INDEX; col++) {
|
||||
struct diff_hpp_fmt *fmt = &d->fmt[col];
|
||||
|
||||
free(fmt->header);
|
||||
zfree(&fmt->header);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+27
-38
@@ -22,14 +22,13 @@
|
||||
#include <linux/list.h>
|
||||
|
||||
struct perf_inject {
|
||||
struct perf_tool tool;
|
||||
bool build_ids;
|
||||
bool sched_stat;
|
||||
const char *input_name;
|
||||
int pipe_output,
|
||||
output;
|
||||
u64 bytes_written;
|
||||
struct list_head samples;
|
||||
struct perf_tool tool;
|
||||
bool build_ids;
|
||||
bool sched_stat;
|
||||
const char *input_name;
|
||||
struct perf_data_file output;
|
||||
u64 bytes_written;
|
||||
struct list_head samples;
|
||||
};
|
||||
|
||||
struct event_entry {
|
||||
@@ -42,21 +41,14 @@ static int perf_event__repipe_synth(struct perf_tool *tool,
|
||||
union perf_event *event)
|
||||
{
|
||||
struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
|
||||
uint32_t size;
|
||||
void *buf = event;
|
||||
ssize_t size;
|
||||
|
||||
size = event->header.size;
|
||||
|
||||
while (size) {
|
||||
int ret = write(inject->output, buf, size);
|
||||
if (ret < 0)
|
||||
return -errno;
|
||||
|
||||
size -= ret;
|
||||
buf += ret;
|
||||
inject->bytes_written += ret;
|
||||
}
|
||||
size = perf_data_file__write(&inject->output, event,
|
||||
event->header.size);
|
||||
if (size < 0)
|
||||
return -errno;
|
||||
|
||||
inject->bytes_written += size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -80,7 +72,7 @@ static int perf_event__repipe_attr(struct perf_tool *tool,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!inject->pipe_output)
|
||||
if (&inject->output.is_pipe)
|
||||
return 0;
|
||||
|
||||
return perf_event__repipe_synth(tool, event);
|
||||
@@ -355,6 +347,7 @@ static int __cmd_inject(struct perf_inject *inject)
|
||||
.path = inject->input_name,
|
||||
.mode = PERF_DATA_MODE_READ,
|
||||
};
|
||||
struct perf_data_file *file_out = &inject->output;
|
||||
|
||||
signal(SIGINT, sig_handler);
|
||||
|
||||
@@ -391,14 +384,14 @@ static int __cmd_inject(struct perf_inject *inject)
|
||||
}
|
||||
}
|
||||
|
||||
if (!inject->pipe_output)
|
||||
lseek(inject->output, session->header.data_offset, SEEK_SET);
|
||||
if (!file_out->is_pipe)
|
||||
lseek(file_out->fd, session->header.data_offset, SEEK_SET);
|
||||
|
||||
ret = perf_session__process_events(session, &inject->tool);
|
||||
|
||||
if (!inject->pipe_output) {
|
||||
if (!file_out->is_pipe) {
|
||||
session->header.data_size = inject->bytes_written;
|
||||
perf_session__write_header(session, session->evlist, inject->output, true);
|
||||
perf_session__write_header(session, session->evlist, file_out->fd, true);
|
||||
}
|
||||
|
||||
perf_session__delete(session);
|
||||
@@ -427,14 +420,17 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||
},
|
||||
.input_name = "-",
|
||||
.samples = LIST_HEAD_INIT(inject.samples),
|
||||
.output = {
|
||||
.path = "-",
|
||||
.mode = PERF_DATA_MODE_WRITE,
|
||||
},
|
||||
};
|
||||
const char *output_name = "-";
|
||||
const struct option options[] = {
|
||||
OPT_BOOLEAN('b', "build-ids", &inject.build_ids,
|
||||
"Inject build-ids into the output stream"),
|
||||
OPT_STRING('i', "input", &inject.input_name, "file",
|
||||
"input file name"),
|
||||
OPT_STRING('o', "output", &output_name, "file",
|
||||
OPT_STRING('o', "output", &inject.output.path, "file",
|
||||
"output file name"),
|
||||
OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat,
|
||||
"Merge sched-stat and sched-switch for getting events "
|
||||
@@ -456,16 +452,9 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||
if (argc)
|
||||
usage_with_options(inject_usage, options);
|
||||
|
||||
if (!strcmp(output_name, "-")) {
|
||||
inject.pipe_output = 1;
|
||||
inject.output = STDOUT_FILENO;
|
||||
} else {
|
||||
inject.output = open(output_name, O_CREAT | O_WRONLY | O_TRUNC,
|
||||
S_IRUSR | S_IWUSR);
|
||||
if (inject.output < 0) {
|
||||
perror("failed to create output file");
|
||||
return -1;
|
||||
}
|
||||
if (perf_data_file__open(&inject.output)) {
|
||||
perror("failed to create output file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (symbol__init() < 0)
|
||||
|
||||
@@ -89,7 +89,7 @@ struct exit_reasons_table {
|
||||
|
||||
struct perf_kvm_stat {
|
||||
struct perf_tool tool;
|
||||
struct perf_record_opts opts;
|
||||
struct record_opts opts;
|
||||
struct perf_evlist *evlist;
|
||||
struct perf_session *session;
|
||||
|
||||
@@ -1158,9 +1158,7 @@ out:
|
||||
if (kvm->timerfd >= 0)
|
||||
close(kvm->timerfd);
|
||||
|
||||
if (pollfds)
|
||||
free(pollfds);
|
||||
|
||||
free(pollfds);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,6 @@ static int
|
||||
dump_raw_samples(struct perf_tool *tool,
|
||||
union perf_event *event,
|
||||
struct perf_sample *sample,
|
||||
struct perf_evsel *evsel __maybe_unused,
|
||||
struct machine *machine)
|
||||
{
|
||||
struct perf_mem *mem = container_of(tool, struct perf_mem, tool);
|
||||
@@ -112,10 +111,10 @@ dump_raw_samples(struct perf_tool *tool,
|
||||
static int process_sample_event(struct perf_tool *tool,
|
||||
union perf_event *event,
|
||||
struct perf_sample *sample,
|
||||
struct perf_evsel *evsel,
|
||||
struct perf_evsel *evsel __maybe_unused,
|
||||
struct machine *machine)
|
||||
{
|
||||
return dump_raw_samples(tool, event, sample, evsel, machine);
|
||||
return dump_raw_samples(tool, event, sample, machine);
|
||||
}
|
||||
|
||||
static int report_raw_events(struct perf_mem *mem)
|
||||
|
||||
@@ -169,6 +169,7 @@ static int opt_set_target(const struct option *opt, const char *str,
|
||||
int unset __maybe_unused)
|
||||
{
|
||||
int ret = -ENOENT;
|
||||
char *tmp;
|
||||
|
||||
if (str && !params.target) {
|
||||
if (!strcmp(opt->long_name, "exec"))
|
||||
@@ -180,7 +181,19 @@ static int opt_set_target(const struct option *opt, const char *str,
|
||||
else
|
||||
return ret;
|
||||
|
||||
params.target = str;
|
||||
/* Expand given path to absolute path, except for modulename */
|
||||
if (params.uprobes || strchr(str, '/')) {
|
||||
tmp = realpath(str, NULL);
|
||||
if (!tmp) {
|
||||
pr_warning("Failed to get the absolute path of %s: %m\n", str);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
tmp = strdup(str);
|
||||
if (!tmp)
|
||||
return -ENOMEM;
|
||||
}
|
||||
params.target = tmp;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
@@ -411,7 +424,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||
}
|
||||
|
||||
#ifdef HAVE_DWARF_SUPPORT
|
||||
if (params.show_lines && !params.uprobes) {
|
||||
if (params.show_lines) {
|
||||
if (params.mod_events) {
|
||||
pr_err(" Error: Don't use --line with"
|
||||
" --add/--del.\n");
|
||||
|
||||
+41
-53
@@ -62,9 +62,9 @@ static void __handle_on_exit_funcs(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
struct perf_record {
|
||||
struct record {
|
||||
struct perf_tool tool;
|
||||
struct perf_record_opts opts;
|
||||
struct record_opts opts;
|
||||
u64 bytes_written;
|
||||
struct perf_data_file file;
|
||||
struct perf_evlist *evlist;
|
||||
@@ -76,24 +76,14 @@ struct perf_record {
|
||||
long samples;
|
||||
};
|
||||
|
||||
static int perf_record__write(struct perf_record *rec, void *buf, size_t size)
|
||||
static int record__write(struct record *rec, void *bf, size_t size)
|
||||
{
|
||||
struct perf_data_file *file = &rec->file;
|
||||
|
||||
while (size) {
|
||||
ssize_t ret = write(file->fd, buf, size);
|
||||
|
||||
if (ret < 0) {
|
||||
pr_err("failed to write perf data, error: %m\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
size -= ret;
|
||||
buf += ret;
|
||||
|
||||
rec->bytes_written += ret;
|
||||
if (perf_data_file__write(rec->session->file, bf, size) < 0) {
|
||||
pr_err("failed to write perf data, error: %m\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rec->bytes_written += size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -102,12 +92,11 @@ static int process_synthesized_event(struct perf_tool *tool,
|
||||
struct perf_sample *sample __maybe_unused,
|
||||
struct machine *machine __maybe_unused)
|
||||
{
|
||||
struct perf_record *rec = container_of(tool, struct perf_record, tool);
|
||||
return perf_record__write(rec, event, event->header.size);
|
||||
struct record *rec = container_of(tool, struct record, tool);
|
||||
return record__write(rec, event, event->header.size);
|
||||
}
|
||||
|
||||
static int perf_record__mmap_read(struct perf_record *rec,
|
||||
struct perf_mmap *md)
|
||||
static int record__mmap_read(struct record *rec, struct perf_mmap *md)
|
||||
{
|
||||
unsigned int head = perf_mmap__read_head(md);
|
||||
unsigned int old = md->prev;
|
||||
@@ -128,7 +117,7 @@ static int perf_record__mmap_read(struct perf_record *rec,
|
||||
size = md->mask + 1 - (old & md->mask);
|
||||
old += size;
|
||||
|
||||
if (perf_record__write(rec, buf, size) < 0) {
|
||||
if (record__write(rec, buf, size) < 0) {
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
@@ -138,7 +127,7 @@ static int perf_record__mmap_read(struct perf_record *rec,
|
||||
size = head - old;
|
||||
old += size;
|
||||
|
||||
if (perf_record__write(rec, buf, size) < 0) {
|
||||
if (record__write(rec, buf, size) < 0) {
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
@@ -163,9 +152,9 @@ static void sig_handler(int sig)
|
||||
signr = sig;
|
||||
}
|
||||
|
||||
static void perf_record__sig_exit(int exit_status __maybe_unused, void *arg)
|
||||
static void record__sig_exit(int exit_status __maybe_unused, void *arg)
|
||||
{
|
||||
struct perf_record *rec = arg;
|
||||
struct record *rec = arg;
|
||||
int status;
|
||||
|
||||
if (rec->evlist->workload.pid > 0) {
|
||||
@@ -183,13 +172,13 @@ static void perf_record__sig_exit(int exit_status __maybe_unused, void *arg)
|
||||
signal(signr, SIG_DFL);
|
||||
}
|
||||
|
||||
static int perf_record__open(struct perf_record *rec)
|
||||
static int record__open(struct record *rec)
|
||||
{
|
||||
char msg[512];
|
||||
struct perf_evsel *pos;
|
||||
struct perf_evlist *evlist = rec->evlist;
|
||||
struct perf_session *session = rec->session;
|
||||
struct perf_record_opts *opts = &rec->opts;
|
||||
struct record_opts *opts = &rec->opts;
|
||||
int rc = 0;
|
||||
|
||||
perf_evlist__config(evlist, opts);
|
||||
@@ -239,7 +228,7 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int process_buildids(struct perf_record *rec)
|
||||
static int process_buildids(struct record *rec)
|
||||
{
|
||||
struct perf_data_file *file = &rec->file;
|
||||
struct perf_session *session = rec->session;
|
||||
@@ -254,9 +243,9 @@ static int process_buildids(struct perf_record *rec)
|
||||
size, &build_id__mark_dso_hit_ops);
|
||||
}
|
||||
|
||||
static void perf_record__exit(int status, void *arg)
|
||||
static void record__exit(int status, void *arg)
|
||||
{
|
||||
struct perf_record *rec = arg;
|
||||
struct record *rec = arg;
|
||||
struct perf_data_file *file = &rec->file;
|
||||
|
||||
if (status != 0)
|
||||
@@ -312,14 +301,14 @@ static struct perf_event_header finished_round_event = {
|
||||
.type = PERF_RECORD_FINISHED_ROUND,
|
||||
};
|
||||
|
||||
static int perf_record__mmap_read_all(struct perf_record *rec)
|
||||
static int record__mmap_read_all(struct record *rec)
|
||||
{
|
||||
int i;
|
||||
int rc = 0;
|
||||
|
||||
for (i = 0; i < rec->evlist->nr_mmaps; i++) {
|
||||
if (rec->evlist->mmap[i].base) {
|
||||
if (perf_record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) {
|
||||
if (record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) {
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
@@ -327,14 +316,13 @@ static int perf_record__mmap_read_all(struct perf_record *rec)
|
||||
}
|
||||
|
||||
if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA))
|
||||
rc = perf_record__write(rec, &finished_round_event,
|
||||
sizeof(finished_round_event));
|
||||
rc = record__write(rec, &finished_round_event, sizeof(finished_round_event));
|
||||
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void perf_record__init_features(struct perf_record *rec)
|
||||
static void record__init_features(struct record *rec)
|
||||
{
|
||||
struct perf_evlist *evsel_list = rec->evlist;
|
||||
struct perf_session *session = rec->session;
|
||||
@@ -353,14 +341,14 @@ static void perf_record__init_features(struct perf_record *rec)
|
||||
perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
|
||||
}
|
||||
|
||||
static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
|
||||
static int __cmd_record(struct record *rec, int argc, const char **argv)
|
||||
{
|
||||
int err;
|
||||
unsigned long waking = 0;
|
||||
const bool forks = argc > 0;
|
||||
struct machine *machine;
|
||||
struct perf_tool *tool = &rec->tool;
|
||||
struct perf_record_opts *opts = &rec->opts;
|
||||
struct record_opts *opts = &rec->opts;
|
||||
struct perf_evlist *evsel_list = rec->evlist;
|
||||
struct perf_data_file *file = &rec->file;
|
||||
struct perf_session *session;
|
||||
@@ -368,7 +356,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
|
||||
|
||||
rec->progname = argv[0];
|
||||
|
||||
on_exit(perf_record__sig_exit, rec);
|
||||
on_exit(record__sig_exit, rec);
|
||||
signal(SIGCHLD, sig_handler);
|
||||
signal(SIGINT, sig_handler);
|
||||
signal(SIGUSR1, sig_handler);
|
||||
@@ -382,7 +370,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
|
||||
|
||||
rec->session = session;
|
||||
|
||||
perf_record__init_features(rec);
|
||||
record__init_features(rec);
|
||||
|
||||
if (forks) {
|
||||
err = perf_evlist__prepare_workload(evsel_list, &opts->target,
|
||||
@@ -394,7 +382,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (perf_record__open(rec) != 0) {
|
||||
if (record__open(rec) != 0) {
|
||||
err = -1;
|
||||
goto out_delete_session;
|
||||
}
|
||||
@@ -403,9 +391,9 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
|
||||
perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
|
||||
|
||||
/*
|
||||
* perf_session__delete(session) will be called at perf_record__exit()
|
||||
* perf_session__delete(session) will be called at record__exit()
|
||||
*/
|
||||
on_exit(perf_record__exit, rec);
|
||||
on_exit(record__exit, rec);
|
||||
|
||||
if (file->is_pipe) {
|
||||
err = perf_header__write_pipe(file->fd);
|
||||
@@ -510,7 +498,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
|
||||
for (;;) {
|
||||
int hits = rec->samples;
|
||||
|
||||
if (perf_record__mmap_read_all(rec) < 0) {
|
||||
if (record__mmap_read_all(rec) < 0) {
|
||||
err = -1;
|
||||
goto out_delete_session;
|
||||
}
|
||||
@@ -669,7 +657,7 @@ static int get_stack_size(char *str, unsigned long *_size)
|
||||
}
|
||||
#endif /* HAVE_LIBUNWIND_SUPPORT */
|
||||
|
||||
int record_parse_callchain(const char *arg, struct perf_record_opts *opts)
|
||||
int record_parse_callchain(const char *arg, struct record_opts *opts)
|
||||
{
|
||||
char *tok, *name, *saveptr = NULL;
|
||||
char *buf;
|
||||
@@ -725,7 +713,7 @@ int record_parse_callchain(const char *arg, struct perf_record_opts *opts)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void callchain_debug(struct perf_record_opts *opts)
|
||||
static void callchain_debug(struct record_opts *opts)
|
||||
{
|
||||
pr_debug("callchain: type %d\n", opts->call_graph);
|
||||
|
||||
@@ -738,7 +726,7 @@ int record_parse_callchain_opt(const struct option *opt,
|
||||
const char *arg,
|
||||
int unset)
|
||||
{
|
||||
struct perf_record_opts *opts = opt->value;
|
||||
struct record_opts *opts = opt->value;
|
||||
int ret;
|
||||
|
||||
/* --no-call-graph */
|
||||
@@ -759,7 +747,7 @@ int record_callchain_opt(const struct option *opt,
|
||||
const char *arg __maybe_unused,
|
||||
int unset __maybe_unused)
|
||||
{
|
||||
struct perf_record_opts *opts = opt->value;
|
||||
struct record_opts *opts = opt->value;
|
||||
|
||||
if (opts->call_graph == CALLCHAIN_NONE)
|
||||
opts->call_graph = CALLCHAIN_FP;
|
||||
@@ -775,8 +763,8 @@ static const char * const record_usage[] = {
|
||||
};
|
||||
|
||||
/*
|
||||
* XXX Ideally would be local to cmd_record() and passed to a perf_record__new
|
||||
* because we need to have access to it in perf_record__exit, that is called
|
||||
* XXX Ideally would be local to cmd_record() and passed to a record__new
|
||||
* because we need to have access to it in record__exit, that is called
|
||||
* after cmd_record() exits, but since record_options need to be accessible to
|
||||
* builtin-script, leave it here.
|
||||
*
|
||||
@@ -784,7 +772,7 @@ static const char * const record_usage[] = {
|
||||
*
|
||||
* Just say no to tons of global variables, sigh.
|
||||
*/
|
||||
static struct perf_record record = {
|
||||
static struct record record = {
|
||||
.opts = {
|
||||
.mmap_pages = UINT_MAX,
|
||||
.user_freq = UINT_MAX,
|
||||
@@ -808,7 +796,7 @@ const char record_callchain_help[] = CALLCHAIN_HELP "fp";
|
||||
/*
|
||||
* XXX Will stay a global variable till we fix builtin-script.c to stop messing
|
||||
* with it and switch to use the library functions in perf_evlist that came
|
||||
* from builtin-record.c, i.e. use perf_record_opts,
|
||||
* from builtin-record.c, i.e. use record_opts,
|
||||
* perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
|
||||
* using pipes, etc.
|
||||
*/
|
||||
@@ -891,7 +879,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||
{
|
||||
int err = -ENOMEM;
|
||||
struct perf_evlist *evsel_list;
|
||||
struct perf_record *rec = &record;
|
||||
struct record *rec = &record;
|
||||
char errbuf[BUFSIZ];
|
||||
|
||||
evsel_list = perf_evlist__new();
|
||||
@@ -956,7 +944,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||
if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0)
|
||||
usage_with_options(record_usage, record_options);
|
||||
|
||||
if (perf_record_opts__config(&rec->opts)) {
|
||||
if (record_opts__config(&rec->opts)) {
|
||||
err = -EINVAL;
|
||||
goto out_free_fd;
|
||||
}
|
||||
|
||||
+88
-169
@@ -39,7 +39,7 @@
|
||||
#include <dlfcn.h>
|
||||
#include <linux/bitmap.h>
|
||||
|
||||
struct perf_report {
|
||||
struct report {
|
||||
struct perf_tool tool;
|
||||
struct perf_session *session;
|
||||
bool force, use_tui, use_gtk, use_stdio;
|
||||
@@ -60,14 +60,14 @@ struct perf_report {
|
||||
DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
|
||||
};
|
||||
|
||||
static int perf_report_config(const char *var, const char *value, void *cb)
|
||||
static int report__config(const char *var, const char *value, void *cb)
|
||||
{
|
||||
if (!strcmp(var, "report.group")) {
|
||||
symbol_conf.event_group = perf_config_bool(var, value);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(var, "report.percent-limit")) {
|
||||
struct perf_report *rep = cb;
|
||||
struct report *rep = cb;
|
||||
rep->min_percent = strtof(value, NULL);
|
||||
return 0;
|
||||
}
|
||||
@@ -75,31 +75,40 @@ static int perf_report_config(const char *var, const char *value, void *cb)
|
||||
return perf_default_config(var, value, cb);
|
||||
}
|
||||
|
||||
static int perf_report__add_mem_hist_entry(struct perf_tool *tool,
|
||||
struct addr_location *al,
|
||||
struct perf_sample *sample,
|
||||
struct perf_evsel *evsel,
|
||||
struct machine *machine,
|
||||
union perf_event *event)
|
||||
static int report__resolve_callchain(struct report *rep, struct symbol **parent,
|
||||
struct perf_evsel *evsel, struct addr_location *al,
|
||||
struct perf_sample *sample)
|
||||
{
|
||||
struct perf_report *rep = container_of(tool, struct perf_report, tool);
|
||||
if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) {
|
||||
return machine__resolve_callchain(al->machine, evsel, al->thread, sample,
|
||||
parent, al, rep->max_stack);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample)
|
||||
{
|
||||
if (!symbol_conf.use_callchain)
|
||||
return 0;
|
||||
return callchain_append(he->callchain, &callchain_cursor, sample->period);
|
||||
}
|
||||
|
||||
static int report__add_mem_hist_entry(struct perf_tool *tool, struct addr_location *al,
|
||||
struct perf_sample *sample, struct perf_evsel *evsel,
|
||||
union perf_event *event)
|
||||
{
|
||||
struct report *rep = container_of(tool, struct report, tool);
|
||||
struct symbol *parent = NULL;
|
||||
u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
|
||||
int err = 0;
|
||||
struct hist_entry *he;
|
||||
struct mem_info *mi, *mx;
|
||||
uint64_t cost;
|
||||
int err = report__resolve_callchain(rep, &parent, evsel, al, sample);
|
||||
|
||||
if ((sort__has_parent || symbol_conf.use_callchain) &&
|
||||
sample->callchain) {
|
||||
err = machine__resolve_callchain(machine, evsel, al->thread,
|
||||
sample, &parent, al,
|
||||
rep->max_stack);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mi = machine__resolve_mem(machine, al->thread, sample, cpumode);
|
||||
mi = machine__resolve_mem(al->machine, al->thread, sample, cpumode);
|
||||
if (!mi)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -122,77 +131,36 @@ static int perf_report__add_mem_hist_entry(struct perf_tool *tool,
|
||||
if (!he)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* In the TUI browser, we are doing integrated annotation,
|
||||
* so we don't allocate the extra space needed because the stdio
|
||||
* code will not use it.
|
||||
*/
|
||||
if (sort__has_sym && he->ms.sym && use_browser > 0) {
|
||||
struct annotation *notes = symbol__annotation(he->ms.sym);
|
||||
err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
assert(evsel != NULL);
|
||||
|
||||
if (notes->src == NULL && symbol__alloc_hist(he->ms.sym) < 0)
|
||||
goto out;
|
||||
|
||||
err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (sort__has_sym && he->mem_info->daddr.sym && use_browser > 0) {
|
||||
struct annotation *notes;
|
||||
|
||||
mx = he->mem_info;
|
||||
|
||||
notes = symbol__annotation(mx->daddr.sym);
|
||||
if (notes->src == NULL && symbol__alloc_hist(mx->daddr.sym) < 0)
|
||||
goto out;
|
||||
|
||||
err = symbol__inc_addr_samples(mx->daddr.sym,
|
||||
mx->daddr.map,
|
||||
evsel->idx,
|
||||
mx->daddr.al_addr);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
mx = he->mem_info;
|
||||
err = addr_map_symbol__inc_samples(&mx->daddr, evsel->idx);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
evsel->hists.stats.total_period += cost;
|
||||
hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
|
||||
err = 0;
|
||||
|
||||
if (symbol_conf.use_callchain) {
|
||||
err = callchain_append(he->callchain,
|
||||
&callchain_cursor,
|
||||
sample->period);
|
||||
}
|
||||
err = hist_entry__append_callchain(he, sample);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
|
||||
struct addr_location *al,
|
||||
struct perf_sample *sample,
|
||||
struct perf_evsel *evsel,
|
||||
struct machine *machine)
|
||||
static int report__add_branch_hist_entry(struct perf_tool *tool, struct addr_location *al,
|
||||
struct perf_sample *sample, struct perf_evsel *evsel)
|
||||
{
|
||||
struct perf_report *rep = container_of(tool, struct perf_report, tool);
|
||||
struct report *rep = container_of(tool, struct report, tool);
|
||||
struct symbol *parent = NULL;
|
||||
int err = 0;
|
||||
unsigned i;
|
||||
struct hist_entry *he;
|
||||
struct branch_info *bi, *bx;
|
||||
int err = report__resolve_callchain(rep, &parent, evsel, al, sample);
|
||||
|
||||
if ((sort__has_parent || symbol_conf.use_callchain)
|
||||
&& sample->callchain) {
|
||||
err = machine__resolve_callchain(machine, evsel, al->thread,
|
||||
sample, &parent, al,
|
||||
rep->max_stack);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
bi = machine__resolve_bstack(machine, al->thread,
|
||||
bi = machine__resolve_bstack(al->machine, al->thread,
|
||||
sample->branch_stack);
|
||||
if (!bi)
|
||||
return -ENOMEM;
|
||||
@@ -214,35 +182,15 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
|
||||
he = __hists__add_entry(&evsel->hists, al, parent, &bi[i], NULL,
|
||||
1, 1, 0);
|
||||
if (he) {
|
||||
struct annotation *notes;
|
||||
bx = he->branch_info;
|
||||
if (bx->from.sym && use_browser == 1 && sort__has_sym) {
|
||||
notes = symbol__annotation(bx->from.sym);
|
||||
if (!notes->src
|
||||
&& symbol__alloc_hist(bx->from.sym) < 0)
|
||||
goto out;
|
||||
err = addr_map_symbol__inc_samples(&bx->from, evsel->idx);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = symbol__inc_addr_samples(bx->from.sym,
|
||||
bx->from.map,
|
||||
evsel->idx,
|
||||
bx->from.al_addr);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
err = addr_map_symbol__inc_samples(&bx->to, evsel->idx);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
if (bx->to.sym && use_browser == 1 && sort__has_sym) {
|
||||
notes = symbol__annotation(bx->to.sym);
|
||||
if (!notes->src
|
||||
&& symbol__alloc_hist(bx->to.sym) < 0)
|
||||
goto out;
|
||||
|
||||
err = symbol__inc_addr_samples(bx->to.sym,
|
||||
bx->to.map,
|
||||
evsel->idx,
|
||||
bx->to.al_addr);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
evsel->hists.stats.total_period += 1;
|
||||
hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
|
||||
} else
|
||||
@@ -254,24 +202,16 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int perf_evsel__add_hist_entry(struct perf_tool *tool,
|
||||
struct perf_evsel *evsel,
|
||||
struct addr_location *al,
|
||||
struct perf_sample *sample,
|
||||
struct machine *machine)
|
||||
static int report__add_hist_entry(struct perf_tool *tool, struct perf_evsel *evsel,
|
||||
struct addr_location *al, struct perf_sample *sample)
|
||||
{
|
||||
struct perf_report *rep = container_of(tool, struct perf_report, tool);
|
||||
struct report *rep = container_of(tool, struct report, tool);
|
||||
struct symbol *parent = NULL;
|
||||
int err = 0;
|
||||
struct hist_entry *he;
|
||||
int err = report__resolve_callchain(rep, &parent, evsel, al, sample);
|
||||
|
||||
if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) {
|
||||
err = machine__resolve_callchain(machine, evsel, al->thread,
|
||||
sample, &parent, al,
|
||||
rep->max_stack);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
he = __hists__add_entry(&evsel->hists, al, parent, NULL, NULL,
|
||||
sample->period, sample->weight,
|
||||
@@ -279,30 +219,11 @@ static int perf_evsel__add_hist_entry(struct perf_tool *tool,
|
||||
if (he == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
if (symbol_conf.use_callchain) {
|
||||
err = callchain_append(he->callchain,
|
||||
&callchain_cursor,
|
||||
sample->period);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
/*
|
||||
* Only in the TUI browser we are doing integrated annotation,
|
||||
* so we don't allocated the extra space needed because the stdio
|
||||
* code will not use it.
|
||||
*/
|
||||
if (he->ms.sym != NULL && use_browser == 1 && sort__has_sym) {
|
||||
struct annotation *notes = symbol__annotation(he->ms.sym);
|
||||
|
||||
assert(evsel != NULL);
|
||||
|
||||
err = -ENOMEM;
|
||||
if (notes->src == NULL && symbol__alloc_hist(he->ms.sym) < 0)
|
||||
goto out;
|
||||
|
||||
err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
|
||||
}
|
||||
err = hist_entry__append_callchain(he, sample);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
|
||||
evsel->hists.stats.total_period += sample->period;
|
||||
hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
|
||||
out:
|
||||
@@ -316,13 +237,13 @@ static int process_sample_event(struct perf_tool *tool,
|
||||
struct perf_evsel *evsel,
|
||||
struct machine *machine)
|
||||
{
|
||||
struct perf_report *rep = container_of(tool, struct perf_report, tool);
|
||||
struct report *rep = container_of(tool, struct report, tool);
|
||||
struct addr_location al;
|
||||
int ret;
|
||||
|
||||
if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
|
||||
fprintf(stderr, "problem processing %d event, skipping it.\n",
|
||||
event->header.type);
|
||||
pr_debug("problem processing %d event, skipping it.\n",
|
||||
event->header.type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -333,21 +254,18 @@ static int process_sample_event(struct perf_tool *tool,
|
||||
return 0;
|
||||
|
||||
if (sort__mode == SORT_MODE__BRANCH) {
|
||||
ret = perf_report__add_branch_hist_entry(tool, &al, sample,
|
||||
evsel, machine);
|
||||
ret = report__add_branch_hist_entry(tool, &al, sample, evsel);
|
||||
if (ret < 0)
|
||||
pr_debug("problem adding lbr entry, skipping event\n");
|
||||
} else if (rep->mem_mode == 1) {
|
||||
ret = perf_report__add_mem_hist_entry(tool, &al, sample,
|
||||
evsel, machine, event);
|
||||
ret = report__add_mem_hist_entry(tool, &al, sample, evsel, event);
|
||||
if (ret < 0)
|
||||
pr_debug("problem adding mem entry, skipping event\n");
|
||||
} else {
|
||||
if (al.map != NULL)
|
||||
al.map->dso->hit = 1;
|
||||
|
||||
ret = perf_evsel__add_hist_entry(tool, evsel, &al, sample,
|
||||
machine);
|
||||
ret = report__add_hist_entry(tool, evsel, &al, sample);
|
||||
if (ret < 0)
|
||||
pr_debug("problem incrementing symbol period, skipping event\n");
|
||||
}
|
||||
@@ -360,7 +278,7 @@ static int process_read_event(struct perf_tool *tool,
|
||||
struct perf_evsel *evsel,
|
||||
struct machine *machine __maybe_unused)
|
||||
{
|
||||
struct perf_report *rep = container_of(tool, struct perf_report, tool);
|
||||
struct report *rep = container_of(tool, struct report, tool);
|
||||
|
||||
if (rep->show_threads) {
|
||||
const char *name = evsel ? perf_evsel__name(evsel) : "unknown";
|
||||
@@ -379,7 +297,7 @@ static int process_read_event(struct perf_tool *tool,
|
||||
}
|
||||
|
||||
/* For pipe mode, sample_type is not currently set */
|
||||
static int perf_report__setup_sample_type(struct perf_report *rep)
|
||||
static int report__setup_sample_type(struct report *rep)
|
||||
{
|
||||
struct perf_session *session = rep->session;
|
||||
u64 sample_type = perf_evlist__combined_sample_type(session->evlist);
|
||||
@@ -424,8 +342,7 @@ static void sig_handler(int sig __maybe_unused)
|
||||
session_done = 1;
|
||||
}
|
||||
|
||||
static size_t hists__fprintf_nr_sample_events(struct perf_report *rep,
|
||||
struct hists *hists,
|
||||
static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report *rep,
|
||||
const char *evname, FILE *fp)
|
||||
{
|
||||
size_t ret;
|
||||
@@ -462,7 +379,7 @@ static size_t hists__fprintf_nr_sample_events(struct perf_report *rep,
|
||||
}
|
||||
|
||||
static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
|
||||
struct perf_report *rep,
|
||||
struct report *rep,
|
||||
const char *help)
|
||||
{
|
||||
struct perf_evsel *pos;
|
||||
@@ -475,7 +392,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
|
||||
!perf_evsel__is_group_leader(pos))
|
||||
continue;
|
||||
|
||||
hists__fprintf_nr_sample_events(rep, hists, evname, stdout);
|
||||
hists__fprintf_nr_sample_events(hists, rep, evname, stdout);
|
||||
hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout);
|
||||
fprintf(stdout, "\n\n");
|
||||
}
|
||||
@@ -495,7 +412,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cmd_report(struct perf_report *rep)
|
||||
static int __cmd_report(struct report *rep)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
u64 nr_samples;
|
||||
@@ -519,7 +436,7 @@ static int __cmd_report(struct perf_report *rep)
|
||||
if (rep->show_threads)
|
||||
perf_read_values_init(&rep->show_threads_values);
|
||||
|
||||
ret = perf_report__setup_sample_type(rep);
|
||||
ret = report__setup_sample_type(rep);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -552,15 +469,17 @@ static int __cmd_report(struct perf_report *rep)
|
||||
desc);
|
||||
}
|
||||
|
||||
if (verbose > 3)
|
||||
perf_session__fprintf(session, stdout);
|
||||
if (use_browser == 0) {
|
||||
if (verbose > 3)
|
||||
perf_session__fprintf(session, stdout);
|
||||
|
||||
if (verbose > 2)
|
||||
perf_session__fprintf_dsos(session, stdout);
|
||||
if (verbose > 2)
|
||||
perf_session__fprintf_dsos(session, stdout);
|
||||
|
||||
if (dump_trace) {
|
||||
perf_session__fprintf_nr_events(session, stdout);
|
||||
return 0;
|
||||
if (dump_trace) {
|
||||
perf_session__fprintf_nr_events(session, stdout);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
nr_samples = 0;
|
||||
@@ -638,7 +557,7 @@ static int __cmd_report(struct perf_report *rep)
|
||||
static int
|
||||
parse_callchain_opt(const struct option *opt, const char *arg, int unset)
|
||||
{
|
||||
struct perf_report *rep = (struct perf_report *)opt->value;
|
||||
struct report *rep = (struct report *)opt->value;
|
||||
char *tok, *tok2;
|
||||
char *endptr;
|
||||
|
||||
@@ -720,7 +639,7 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset)
|
||||
return -1;
|
||||
setup:
|
||||
if (callchain_register_param(&callchain_param) < 0) {
|
||||
fprintf(stderr, "Can't register callchain params\n");
|
||||
pr_err("Can't register callchain params\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -758,7 +677,7 @@ static int
|
||||
parse_percent_limit(const struct option *opt, const char *str,
|
||||
int unset __maybe_unused)
|
||||
{
|
||||
struct perf_report *rep = opt->value;
|
||||
struct report *rep = opt->value;
|
||||
|
||||
rep->min_percent = strtof(str, NULL);
|
||||
return 0;
|
||||
@@ -776,7 +695,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||
"perf report [<options>]",
|
||||
NULL
|
||||
};
|
||||
struct perf_report report = {
|
||||
struct report report = {
|
||||
.tool = {
|
||||
.sample = process_sample_event,
|
||||
.mmap = perf_event__process_mmap,
|
||||
@@ -892,7 +811,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||
.mode = PERF_DATA_MODE_READ,
|
||||
};
|
||||
|
||||
perf_config(perf_report_config, &report);
|
||||
perf_config(report__config, &report);
|
||||
|
||||
argc = parse_options(argc, argv, options, report_usage, 0);
|
||||
|
||||
@@ -942,7 +861,7 @@ repeat:
|
||||
}
|
||||
if (report.mem_mode) {
|
||||
if (sort__mode == SORT_MODE__BRANCH) {
|
||||
fprintf(stderr, "branch and mem mode incompatible\n");
|
||||
pr_err("branch and mem mode incompatible\n");
|
||||
goto error;
|
||||
}
|
||||
sort__mode = SORT_MODE__MEMORY;
|
||||
|
||||
@@ -469,7 +469,7 @@ static void *thread_func(void *ctx)
|
||||
char comm2[22];
|
||||
int fd;
|
||||
|
||||
free(parms);
|
||||
zfree(&parms);
|
||||
|
||||
sprintf(comm2, ":%s", this_task->comm);
|
||||
prctl(PR_SET_NAME, comm2);
|
||||
|
||||
+10
-12
@@ -423,7 +423,6 @@ static void print_sample_addr(union perf_event *event,
|
||||
static void print_sample_bts(union perf_event *event,
|
||||
struct perf_sample *sample,
|
||||
struct perf_evsel *evsel,
|
||||
struct machine *machine,
|
||||
struct thread *thread,
|
||||
struct addr_location *al)
|
||||
{
|
||||
@@ -435,7 +434,7 @@ static void print_sample_bts(union perf_event *event,
|
||||
printf(" ");
|
||||
else
|
||||
printf("\n");
|
||||
perf_evsel__print_ip(evsel, sample, machine, al,
|
||||
perf_evsel__print_ip(evsel, sample, al,
|
||||
output[attr->type].print_ip_opts,
|
||||
PERF_MAX_STACK_DEPTH);
|
||||
}
|
||||
@@ -446,14 +445,13 @@ static void print_sample_bts(union perf_event *event,
|
||||
if (PRINT_FIELD(ADDR) ||
|
||||
((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
|
||||
!output[attr->type].user_set))
|
||||
print_sample_addr(event, sample, machine, thread, attr);
|
||||
print_sample_addr(event, sample, al->machine, thread, attr);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void process_event(union perf_event *event, struct perf_sample *sample,
|
||||
struct perf_evsel *evsel, struct machine *machine,
|
||||
struct thread *thread,
|
||||
struct perf_evsel *evsel, struct thread *thread,
|
||||
struct addr_location *al)
|
||||
{
|
||||
struct perf_event_attr *attr = &evsel->attr;
|
||||
@@ -469,7 +467,7 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
|
||||
}
|
||||
|
||||
if (is_bts_event(attr)) {
|
||||
print_sample_bts(event, sample, evsel, machine, thread, al);
|
||||
print_sample_bts(event, sample, evsel, thread, al);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -477,7 +475,7 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
|
||||
event_format__print(evsel->tp_format, sample->cpu,
|
||||
sample->raw_data, sample->raw_size);
|
||||
if (PRINT_FIELD(ADDR))
|
||||
print_sample_addr(event, sample, machine, thread, attr);
|
||||
print_sample_addr(event, sample, al->machine, thread, attr);
|
||||
|
||||
if (PRINT_FIELD(IP)) {
|
||||
if (!symbol_conf.use_callchain)
|
||||
@@ -485,7 +483,7 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
|
||||
else
|
||||
printf("\n");
|
||||
|
||||
perf_evsel__print_ip(evsel, sample, machine, al,
|
||||
perf_evsel__print_ip(evsel, sample, al,
|
||||
output[attr->type].print_ip_opts,
|
||||
PERF_MAX_STACK_DEPTH);
|
||||
}
|
||||
@@ -574,7 +572,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
|
||||
if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
|
||||
return 0;
|
||||
|
||||
scripting_ops->process_event(event, sample, evsel, machine, thread, &al);
|
||||
scripting_ops->process_event(event, sample, evsel, thread, &al);
|
||||
|
||||
evsel->hists.stats.total_period += sample->period;
|
||||
return 0;
|
||||
@@ -1104,9 +1102,9 @@ static struct script_desc *script_desc__new(const char *name)
|
||||
|
||||
static void script_desc__delete(struct script_desc *s)
|
||||
{
|
||||
free(s->name);
|
||||
free(s->half_liner);
|
||||
free(s->args);
|
||||
zfree(&s->name);
|
||||
zfree(&s->half_liner);
|
||||
zfree(&s->args);
|
||||
free(s);
|
||||
}
|
||||
|
||||
|
||||
@@ -185,8 +185,7 @@ static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
|
||||
|
||||
static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
|
||||
{
|
||||
free(evsel->priv);
|
||||
evsel->priv = NULL;
|
||||
zfree(&evsel->priv);
|
||||
}
|
||||
|
||||
static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel)
|
||||
@@ -208,8 +207,7 @@ static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel)
|
||||
|
||||
static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel)
|
||||
{
|
||||
free(evsel->prev_raw_counts);
|
||||
evsel->prev_raw_counts = NULL;
|
||||
zfree(&evsel->prev_raw_counts);
|
||||
}
|
||||
|
||||
static void perf_evlist__free_stats(struct perf_evlist *evlist)
|
||||
|
||||
@@ -488,8 +488,7 @@ static const char *cat_backtrace(union perf_event *event,
|
||||
* It seems the callchain is corrupted.
|
||||
* Discard all.
|
||||
*/
|
||||
free(p);
|
||||
p = NULL;
|
||||
zfree(&p);
|
||||
goto exit;
|
||||
}
|
||||
continue;
|
||||
|
||||
+10
-13
@@ -189,21 +189,18 @@ static void perf_top__record_precise_ip(struct perf_top *top,
|
||||
if (pthread_mutex_trylock(¬es->lock))
|
||||
return;
|
||||
|
||||
if (notes->src == NULL && symbol__alloc_hist(sym) < 0) {
|
||||
pthread_mutex_unlock(¬es->lock);
|
||||
pr_err("Not enough memory for annotating '%s' symbol!\n",
|
||||
sym->name);
|
||||
sleep(1);
|
||||
return;
|
||||
}
|
||||
|
||||
ip = he->ms.map->map_ip(he->ms.map, ip);
|
||||
err = symbol__inc_addr_samples(sym, he->ms.map, counter, ip);
|
||||
err = hist_entry__inc_addr_samples(he, counter, ip);
|
||||
|
||||
pthread_mutex_unlock(¬es->lock);
|
||||
|
||||
if (err == -ERANGE && !he->ms.map->erange_warned)
|
||||
ui__warn_map_erange(he->ms.map, sym, ip);
|
||||
else if (err == -ENOMEM) {
|
||||
pr_err("Not enough memory for annotating '%s' symbol!\n",
|
||||
sym->name);
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void perf_top__show_details(struct perf_top *top)
|
||||
@@ -857,7 +854,7 @@ static int perf_top__start_counters(struct perf_top *top)
|
||||
char msg[512];
|
||||
struct perf_evsel *counter;
|
||||
struct perf_evlist *evlist = top->evlist;
|
||||
struct perf_record_opts *opts = &top->record_opts;
|
||||
struct record_opts *opts = &top->record_opts;
|
||||
|
||||
perf_evlist__config(evlist, opts);
|
||||
|
||||
@@ -909,7 +906,7 @@ static int perf_top__setup_sample_type(struct perf_top *top __maybe_unused)
|
||||
|
||||
static int __cmd_top(struct perf_top *top)
|
||||
{
|
||||
struct perf_record_opts *opts = &top->record_opts;
|
||||
struct record_opts *opts = &top->record_opts;
|
||||
pthread_t thread;
|
||||
int ret;
|
||||
|
||||
@@ -1031,7 +1028,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||
.max_stack = PERF_MAX_STACK_DEPTH,
|
||||
.sym_pcnt_filter = 5,
|
||||
};
|
||||
struct perf_record_opts *opts = &top.record_opts;
|
||||
struct record_opts *opts = &top.record_opts;
|
||||
struct target *target = &opts->target;
|
||||
const struct option options[] = {
|
||||
OPT_CALLBACK('e', "event", &top.evlist, "event",
|
||||
@@ -1182,7 +1179,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||
if (top.delay_secs < 1)
|
||||
top.delay_secs = 1;
|
||||
|
||||
if (perf_record_opts__config(opts)) {
|
||||
if (record_opts__config(opts)) {
|
||||
status = -EINVAL;
|
||||
goto out_delete_maps;
|
||||
}
|
||||
|
||||
@@ -146,8 +146,7 @@ static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
|
||||
|
||||
static void perf_evsel__delete_priv(struct perf_evsel *evsel)
|
||||
{
|
||||
free(evsel->priv);
|
||||
evsel->priv = NULL;
|
||||
zfree(&evsel->priv);
|
||||
perf_evsel__delete(evsel);
|
||||
}
|
||||
|
||||
@@ -165,8 +164,7 @@ static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel, void *handler)
|
||||
return -ENOMEM;
|
||||
|
||||
out_delete:
|
||||
free(evsel->priv);
|
||||
evsel->priv = NULL;
|
||||
zfree(&evsel->priv);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
@@ -1159,7 +1157,7 @@ struct trace {
|
||||
int max;
|
||||
struct syscall *table;
|
||||
} syscalls;
|
||||
struct perf_record_opts opts;
|
||||
struct record_opts opts;
|
||||
struct machine *host;
|
||||
u64 base_time;
|
||||
bool full_time;
|
||||
@@ -1278,10 +1276,8 @@ static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
|
||||
size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
|
||||
struct thread_trace *ttrace = arg->thread->priv;
|
||||
|
||||
if (ttrace && fd >= 0 && fd <= ttrace->paths.max) {
|
||||
free(ttrace->paths.table[fd]);
|
||||
ttrace->paths.table[fd] = NULL;
|
||||
}
|
||||
if (ttrace && fd >= 0 && fd <= ttrace->paths.max)
|
||||
zfree(&ttrace->paths.table[fd]);
|
||||
|
||||
return printed;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user