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>
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
index 0d9cbb4..ca4ab78 100644
--- a/tools/lib/traceevent/Makefile
+++ b/tools/lib/traceevent/Makefile
@@ -67,6 +67,8 @@
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 @@
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 @@
# 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 @@
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 @@
$(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_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 @@
--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
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 22566c2..2ce565a 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -5230,22 +5230,7 @@
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;
}
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index 3ad784f..cf5db90 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -851,10 +851,13 @@
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 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);
diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c
index e2842b9..b502344 100644
--- a/tools/lib/traceevent/parse-filter.c
+++ b/tools/lib/traceevent/parse-filter.c
@@ -38,55 +38,31 @@
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 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 @@
}
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 @@
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 @@
/* 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 @@
/* 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 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 @@
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 @@
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 @@
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 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 @@
/* 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;
@@ -1382,6 +1364,32 @@
}
/**
+ * 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
* @event_id: the event to remove a filter for
@@ -2027,6 +2035,8 @@
int ret;
enum pevent_errno err = 0;
+ filter_init_error_buf(filter);
+
if (!filter->filters)
return PEVENT_ERRNO__NO_FILTER;
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 97a2145..3638b0b 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -489,6 +489,7 @@
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
diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c
index aacef07..42faf36 100644
--- a/tools/perf/arch/common.c
+++ b/tools/perf/arch/common.c
@@ -154,8 +154,7 @@
}
if (lookup_path(buf))
goto out;
- free(buf);
- buf = NULL;
+ zfree(&buf);
}
if (!strcmp(arch, "arm"))
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 6fd52c8..ab65057 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -69,15 +69,7 @@
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 @@
* symbol, free he->ms.sym->src to signal we already
* processed this symbol.
*/
- free(notes->src);
- notes->src = NULL;
+ zfree(¬es->src);
}
}
}
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 2a85cc9..e6a0844 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -654,7 +654,7 @@
for (col = 0; col < PERF_HPP_DIFF__MAX_INDEX; col++) {
struct diff_hpp_fmt *fmt = &d->fmt[col];
- free(fmt->header);
+ zfree(&fmt->header);
}
}
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 6a25085..c9f6d74 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -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 @@
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;
+ size = perf_data_file__write(&inject->output, event,
+ event->header.size);
+ if (size < 0)
+ return -errno;
- while (size) {
- int ret = write(inject->output, buf, size);
- if (ret < 0)
- return -errno;
-
- size -= ret;
- buf += ret;
- inject->bytes_written += ret;
- }
-
+ inject->bytes_written += size;
return 0;
}
@@ -80,7 +72,7 @@
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 @@
.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 @@
}
}
- 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 @@
},
.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 @@
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)
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 154b397..a6ec105 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -89,7 +89,7 @@
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 @@
if (kvm->timerfd >= 0)
close(kvm->timerfd);
- if (pollfds)
- free(pollfds);
-
+ free(pollfds);
return err;
}
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 31c00f1..2e3ade69 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -62,7 +62,6 @@
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 @@
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)
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index c98ccb5..43ff33d 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -169,6 +169,7 @@
int unset __maybe_unused)
{
int ret = -ENOENT;
+ char *tmp;
if (str && !params.target) {
if (!strcmp(opt->long_name, "exec"))
@@ -180,7 +181,19 @@
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 @@
}
#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");
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index c1c1200..6ec0cbc 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -62,9 +62,9 @@
}
#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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
.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 @@
}
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 @@
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 @@
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 @@
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 @@
}
}
- if (perf_record__open(rec) != 0) {
+ if (record__open(rec) != 0) {
err = -1;
goto out_delete_session;
}
@@ -403,9 +391,9 @@
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 @@
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 @@
}
#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 @@
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 @@
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 @@
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 @@
};
/*
- * 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 @@
*
* 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 @@
/*
* 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 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 @@
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;
}
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 3a14dbe..bf8dd2e 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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);
+ err = hist_entry__append_callchain(he, sample);
+ if (err)
+ goto out;
- 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__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 @@
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 @@
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 @@
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 @@
}
/* 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 @@
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 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 @@
!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 @@
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 @@
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 @@
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
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 @@
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 @@
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 @@
"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 @@
.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 @@
}
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;
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 0f3c6551..6a76a07 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -469,7 +469,7 @@
char comm2[22];
int fd;
- free(parms);
+ zfree(&parms);
sprintf(comm2, ":%s", this_task->comm);
prctl(PR_SET_NAME, comm2);
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index f8ab125..6040000 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -423,7 +423,6 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 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);
}
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index dab98b5..106a5e5 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -185,8 +185,7 @@
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 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)
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 20d4212..652af0b 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -488,8 +488,7 @@
* It seems the callchain is corrupted.
* Discard all.
*/
- free(p);
- p = NULL;
+ zfree(&p);
goto exit;
}
continue;
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 03d37a7..172e91a 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -189,21 +189,18 @@
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 @@
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 __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 @@
.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 @@
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;
}
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 56bbca5..c5b4bc5 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -146,8 +146,7 @@
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 @@
return -ENOMEM;
out_delete:
- free(evsel->priv);
- evsel->priv = NULL;
+ zfree(&evsel->priv);
return -ENOENT;
}
@@ -1159,7 +1157,7 @@
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 @@
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;
}
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 5a1f4df..14faeeb 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -126,7 +126,7 @@
feature_check = $(eval $(feature_check_code))
define feature_check_code
- feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C config/feature-checks test-$1 >/dev/null 2>/dev/null && echo 1 || echo 0)
+ feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C config/feature-checks test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0)
endef
feature_set = $(eval $(feature_set_code))
@@ -173,7 +173,7 @@
# to skip the print-out of the long features list if the file
# existed before and after it was built:
#
-ifeq ($(wildcard $(OUTPUT)config/feature-checks/test-all),)
+ifeq ($(wildcard $(OUTPUT)config/feature-checks/test-all.bin),)
test-all-failed := 1
else
test-all-failed := 0
@@ -203,7 +203,7 @@
#
$(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_set,$(feat)))
else
- $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS=$(LDFLAGS) -i -j -C config/feature-checks $(CORE_FEATURE_TESTS) >/dev/null 2>&1)
+ $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS=$(LDFLAGS) -i -j -C config/feature-checks $(addsuffix .bin,$(CORE_FEATURE_TESTS)) >/dev/null 2>&1)
$(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_check,$(feat)))
endif
diff --git a/tools/perf/config/feature-checks/.gitignore b/tools/perf/config/feature-checks/.gitignore
new file mode 100644
index 0000000..80f3da0
--- /dev/null
+++ b/tools/perf/config/feature-checks/.gitignore
@@ -0,0 +1,2 @@
+*.d
+*.bin
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
index bc86462..7cf6fcd 100644
--- a/tools/perf/config/feature-checks/Makefile
+++ b/tools/perf/config/feature-checks/Makefile
@@ -1,90 +1,90 @@
FILES= \
- test-all \
- test-backtrace \
- test-bionic \
- test-dwarf \
- test-fortify-source \
- test-glibc \
- test-gtk2 \
- test-gtk2-infobar \
- test-hello \
- test-libaudit \
- test-libbfd \
- test-liberty \
- test-liberty-z \
- test-cplus-demangle \
- test-libelf \
- test-libelf-getphdrnum \
- test-libelf-mmap \
- test-libnuma \
- test-libperl \
- test-libpython \
- test-libpython-version \
- test-libslang \
- test-libunwind \
- test-libunwind-debug-frame \
- test-on-exit \
- test-stackprotector-all \
- test-timerfd
+ test-all.bin \
+ test-backtrace.bin \
+ test-bionic.bin \
+ test-dwarf.bin \
+ test-fortify-source.bin \
+ test-glibc.bin \
+ test-gtk2.bin \
+ test-gtk2-infobar.bin \
+ test-hello.bin \
+ test-libaudit.bin \
+ test-libbfd.bin \
+ test-liberty.bin \
+ test-liberty-z.bin \
+ test-cplus-demangle.bin \
+ test-libelf.bin \
+ test-libelf-getphdrnum.bin \
+ test-libelf-mmap.bin \
+ test-libnuma.bin \
+ test-libperl.bin \
+ test-libpython.bin \
+ test-libpython-version.bin \
+ test-libslang.bin \
+ test-libunwind.bin \
+ test-libunwind-debug-frame.bin \
+ test-on-exit.bin \
+ test-stackprotector-all.bin \
+ test-timerfd.bin
CC := $(CC) -MD
all: $(FILES)
-BUILD = $(CC) $(CFLAGS) -o $(OUTPUT)$@ $@.c $(LDFLAGS)
+BUILD = $(CC) $(CFLAGS) -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) $(LDFLAGS)
###############################
-test-all:
+test-all.bin:
$(BUILD) -Werror -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl
-test-hello:
+test-hello.bin:
$(BUILD)
-test-stackprotector-all:
+test-stackprotector-all.bin:
$(BUILD) -Werror -fstack-protector-all
-test-fortify-source:
+test-fortify-source.bin:
$(BUILD) -O2 -Werror -D_FORTIFY_SOURCE=2
-test-bionic:
+test-bionic.bin:
$(BUILD)
-test-libelf:
+test-libelf.bin:
$(BUILD) -lelf
-test-glibc:
+test-glibc.bin:
$(BUILD)
-test-dwarf:
+test-dwarf.bin:
$(BUILD) -ldw
-test-libelf-mmap:
+test-libelf-mmap.bin:
$(BUILD) -lelf
-test-libelf-getphdrnum:
+test-libelf-getphdrnum.bin:
$(BUILD) -lelf
-test-libnuma:
+test-libnuma.bin:
$(BUILD) -lnuma
-test-libunwind:
+test-libunwind.bin:
$(BUILD) -lelf
-test-libunwind-debug-frame:
+test-libunwind-debug-frame.bin:
$(BUILD) -lelf
-test-libaudit:
+test-libaudit.bin:
$(BUILD) -laudit
-test-libslang:
+test-libslang.bin:
$(BUILD) -I/usr/include/slang -lslang
-test-gtk2:
+test-gtk2.bin:
$(BUILD) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null)
-test-gtk2-infobar:
+test-gtk2-infobar.bin:
$(BUILD) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null)
grep-libs = $(filter -l%,$(1))
@@ -96,7 +96,7 @@
PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null`
FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
-test-libperl:
+test-libperl.bin:
$(BUILD) $(FLAGS_PERL_EMBED)
override PYTHON := python
@@ -113,31 +113,31 @@
PYTHON_EMBED_CCOPTS = $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
FLAGS_PYTHON_EMBED = $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
-test-libpython:
+test-libpython.bin:
$(BUILD) $(FLAGS_PYTHON_EMBED)
-test-libpython-version:
+test-libpython-version.bin:
$(BUILD) $(FLAGS_PYTHON_EMBED)
-test-libbfd:
+test-libbfd.bin:
$(BUILD) -DPACKAGE='"perf"' -lbfd -ldl
-test-liberty:
+test-liberty.bin:
$(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty
-test-liberty-z:
+test-liberty-z.bin:
$(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty -lz
-test-cplus-demangle:
+test-cplus-demangle.bin:
$(BUILD) -liberty
-test-on-exit:
+test-on-exit.bin:
$(BUILD)
-test-backtrace:
+test-backtrace.bin:
$(BUILD)
-test-timerfd:
+test-timerfd.bin:
$(BUILD)
-include *.d
diff --git a/tools/perf/config/utilities.mak b/tools/perf/config/utilities.mak
index f168deb..4d985e0 100644
--- a/tools/perf/config/utilities.mak
+++ b/tools/perf/config/utilities.mak
@@ -178,10 +178,3 @@
_ge_attempt = $(if $(get-executable),$(get-executable),$(_gea_warn)$(call _gea_err,$(2)))
_gea_warn = $(warning The path '$(1)' is not executable.)
_gea_err = $(if $(1),$(error Please set '$(1)' appropriately))
-
-ifneq ($(findstring $(MAKEFLAGS),s),s)
- ifneq ($(V),1)
- QUIET_CLEAN = @printf ' CLEAN %s\n' $1;
- QUIET_INSTALL = @printf ' INSTALL %s\n' $1;
- endif
-endif
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index b23fed5..b1cc84b 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -247,7 +247,7 @@
CALLCHAIN_DWARF
};
-struct perf_record_opts {
+struct record_opts {
struct target target;
int call_graph;
bool group;
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 85d4919..4248d1e 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -391,7 +391,7 @@
struct machines machines;
struct machine *machine;
struct thread *thread;
- struct perf_record_opts opts = {
+ struct record_opts opts = {
.mmap_pages = UINT_MAX,
.user_freq = UINT_MAX,
.user_interval = ULLONG_MAX,
diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c
index 376c356..27eb751 100644
--- a/tools/perf/tests/keep-tracking.c
+++ b/tools/perf/tests/keep-tracking.c
@@ -51,7 +51,7 @@
*/
int test__keep_tracking(void)
{
- struct perf_record_opts opts = {
+ struct record_opts opts = {
.mmap_pages = UINT_MAX,
.user_freq = UINT_MAX,
.user_interval = ULLONG_MAX,
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index 2ca0abf..f641c35 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -106,10 +106,36 @@
test_make_perf_o := test -f $(PERF)/perf.o
test_make_util_map_o := test -f $(PERF)/util/map.o
-test_make_install := test -x $$TMP_DEST/bin/perf
-test_make_install_O := $(test_make_install)
-test_make_install_bin := $(test_make_install)
-test_make_install_bin_O := $(test_make_install)
+define test_dest_files
+ for file in $(1); do \
+ if [ ! -x $$TMP_DEST/$$file ]; then \
+ echo " failed to find: $$file"; \
+ fi \
+ done
+endef
+
+installed_files_bin := bin/perf
+installed_files_bin += etc/bash_completion.d/perf
+installed_files_bin += libexec/perf-core/perf-archive
+
+installed_files_plugins := lib64/traceevent/plugins/plugin_cfg80211.so
+installed_files_plugins += lib64/traceevent/plugins/plugin_scsi.so
+installed_files_plugins += lib64/traceevent/plugins/plugin_xen.so
+installed_files_plugins += lib64/traceevent/plugins/plugin_function.so
+installed_files_plugins += lib64/traceevent/plugins/plugin_sched_switch.so
+installed_files_plugins += lib64/traceevent/plugins/plugin_mac80211.so
+installed_files_plugins += lib64/traceevent/plugins/plugin_kvm.so
+installed_files_plugins += lib64/traceevent/plugins/plugin_kmem.so
+installed_files_plugins += lib64/traceevent/plugins/plugin_hrtimer.so
+installed_files_plugins += lib64/traceevent/plugins/plugin_jbd2.so
+
+installed_files_all := $(installed_files_bin)
+installed_files_all += $(installed_files_plugins)
+
+test_make_install := $(call test_dest_files,$(installed_files_all))
+test_make_install_O := $(call test_dest_files,$(installed_files_all))
+test_make_install_bin := $(call test_dest_files,$(installed_files_bin))
+test_make_install_bin_O := $(call test_dest_files,$(installed_files_bin))
# FIXME nothing gets installed
test_make_install_man := test -f $$TMP_DEST/share/man/man1/perf.1
@@ -162,7 +188,7 @@
cmd="cd $(PERF) && make -f $(MK) DESTDIR=$$TMP_DEST $($@)"; \
echo "- $@: $$cmd" && echo $$cmd > $@ && \
( eval $$cmd ) >> $@ 2>&1; \
- echo " test: $(call test,$@)"; \
+ echo " test: $(call test,$@)" >> $@ 2>&1; \
$(call test,$@) && \
rm -f $@ \
rm -rf $$TMP_DEST
@@ -174,7 +200,7 @@
cmd="cd $(PERF) && make -f $(MK) O=$$TMP_O DESTDIR=$$TMP_DEST $($(patsubst %_O,%,$@))"; \
echo "- $@: $$cmd" && echo $$cmd > $@ && \
( eval $$cmd ) >> $@ 2>&1 && \
- echo " test: $(call test_O,$@)"; \
+ echo " test: $(call test_O,$@)" >> $@ 2>&1; \
$(call test_O,$@) && \
rm -f $@ && \
rm -rf $$TMP_O \
diff --git a/tools/perf/tests/open-syscall-tp-fields.c b/tools/perf/tests/open-syscall-tp-fields.c
index 41cc0ba..774620a 100644
--- a/tools/perf/tests/open-syscall-tp-fields.c
+++ b/tools/perf/tests/open-syscall-tp-fields.c
@@ -6,7 +6,7 @@
int test__syscall_open_tp_fields(void)
{
- struct perf_record_opts opts = {
+ struct record_opts opts = {
.target = {
.uid = UINT_MAX,
.uses_mmap = true,
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index 93a62b0..eeba562 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -34,7 +34,7 @@
int test__PERF_RECORD(void)
{
- struct perf_record_opts opts = {
+ struct record_opts opts = {
.target = {
.uid = UINT_MAX,
.uses_mmap = true,
diff --git a/tools/perf/tests/perf-time-to-tsc.c b/tools/perf/tests/perf-time-to-tsc.c
index 4ca1b93..c6398b9 100644
--- a/tools/perf/tests/perf-time-to-tsc.c
+++ b/tools/perf/tests/perf-time-to-tsc.c
@@ -46,7 +46,7 @@
*/
int test__perf_time_to_tsc(void)
{
- struct perf_record_opts opts = {
+ struct record_opts opts = {
.mmap_pages = UINT_MAX,
.user_freq = UINT_MAX,
.user_interval = ULLONG_MAX,
diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c
index cbaa7af..d11541d 100644
--- a/tools/perf/ui/browser.c
+++ b/tools/perf/ui/browser.c
@@ -256,8 +256,7 @@
__ui_browser__show_title(browser, title);
browser->title = title;
- free(browser->helpline);
- browser->helpline = NULL;
+ zfree(&browser->helpline);
va_start(ap, helpline);
err = vasprintf(&browser->helpline, helpline, ap);
@@ -268,12 +267,11 @@
return err ? 0 : -1;
}
-void ui_browser__hide(struct ui_browser *browser __maybe_unused)
+void ui_browser__hide(struct ui_browser *browser)
{
pthread_mutex_lock(&ui__lock);
ui_helpline__pop();
- free(browser->helpline);
- browser->helpline = NULL;
+ zfree(&browser->helpline);
pthread_mutex_unlock(&ui__lock);
}
diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h
index 7d45d2f..118cca2 100644
--- a/tools/perf/ui/browser.h
+++ b/tools/perf/ui/browser.h
@@ -59,6 +59,8 @@
bool ui_browser__dialog_yesno(struct ui_browser *browser, const char *text);
int ui_browser__input_window(const char *title, const char *text, char *input,
const char *exit_msg, int delay_sec);
+struct perf_session_env;
+int tui__header_window(struct perf_session_env *env);
void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence);
unsigned int ui_browser__argv_refresh(struct ui_browser *browser);
diff --git a/tools/perf/ui/browsers/header.c b/tools/perf/ui/browsers/header.c
new file mode 100644
index 0000000..89c16b9
--- /dev/null
+++ b/tools/perf/ui/browsers/header.c
@@ -0,0 +1,127 @@
+#include "util/cache.h"
+#include "util/debug.h"
+#include "ui/browser.h"
+#include "ui/ui.h"
+#include "ui/util.h"
+#include "ui/libslang.h"
+#include "util/header.h"
+#include "util/session.h"
+
+static void ui_browser__argv_write(struct ui_browser *browser,
+ void *entry, int row)
+{
+ char **arg = entry;
+ char *str = *arg;
+ char empty[] = " ";
+ bool current_entry = ui_browser__is_current_entry(browser, row);
+ unsigned long offset = (unsigned long)browser->priv;
+
+ if (offset >= strlen(str))
+ str = empty;
+ else
+ str = str + offset;
+
+ ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
+ HE_COLORSET_NORMAL);
+
+ slsmg_write_nstring(str, browser->width);
+}
+
+static int list_menu__run(struct ui_browser *menu)
+{
+ int key;
+ unsigned long offset;
+ const char help[] =
+ "h/?/F1 Show this window\n"
+ "UP/DOWN/PGUP\n"
+ "PGDN/SPACE\n"
+ "LEFT/RIGHT Navigate\n"
+ "q/ESC/CTRL+C Exit browser";
+
+ if (ui_browser__show(menu, "Header information", "Press 'q' to exit") < 0)
+ return -1;
+
+ while (1) {
+ key = ui_browser__run(menu, 0);
+
+ switch (key) {
+ case K_RIGHT:
+ offset = (unsigned long)menu->priv;
+ offset += 10;
+ menu->priv = (void *)offset;
+ continue;
+ case K_LEFT:
+ offset = (unsigned long)menu->priv;
+ if (offset >= 10)
+ offset -= 10;
+ menu->priv = (void *)offset;
+ continue;
+ case K_F1:
+ case 'h':
+ case '?':
+ ui_browser__help_window(menu, help);
+ continue;
+ case K_ESC:
+ case 'q':
+ case CTRL('c'):
+ key = -1;
+ break;
+ default:
+ continue;
+ }
+
+ break;
+ }
+
+ ui_browser__hide(menu);
+ return key;
+}
+
+static int ui__list_menu(int argc, char * const argv[])
+{
+ struct ui_browser menu = {
+ .entries = (void *)argv,
+ .refresh = ui_browser__argv_refresh,
+ .seek = ui_browser__argv_seek,
+ .write = ui_browser__argv_write,
+ .nr_entries = argc,
+ };
+
+ return list_menu__run(&menu);
+}
+
+int tui__header_window(struct perf_session_env *env)
+{
+ int i, argc = 0;
+ char **argv;
+ struct perf_session *session;
+ char *ptr, *pos;
+ size_t size;
+ FILE *fp = open_memstream(&ptr, &size);
+
+ session = container_of(env, struct perf_session, header.env);
+ perf_header__fprintf_info(session, fp, true);
+ fclose(fp);
+
+ for (pos = ptr, argc = 0; (pos = strchr(pos, '\n')) != NULL; pos++)
+ argc++;
+
+ argv = calloc(argc + 1, sizeof(*argv));
+ if (argv == NULL)
+ goto out;
+
+ argv[0] = pos = ptr;
+ for (i = 1; (pos = strchr(pos, '\n')) != NULL; i++) {
+ *pos++ = '\0';
+ argv[i] = pos;
+ }
+
+ BUG_ON(i != argc + 1);
+
+ ui__list_menu(argc, argv);
+
+out:
+ free(argv);
+ free(ptr);
+ return 0;
+}
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index a440e03..a7045ea 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1267,10 +1267,8 @@
{
int i;
- for (i = 0; i < n; ++i) {
- free(options[i]);
- options[i] = NULL;
- }
+ for (i = 0; i < n; ++i)
+ zfree(&options[i]);
}
/* Check whether the browser is for 'top' or 'report' */
@@ -1329,7 +1327,7 @@
abs_path[nr_options] = strdup(path);
if (!abs_path[nr_options]) {
- free(options[nr_options]);
+ zfree(&options[nr_options]);
ui__warning("Can't search all data files due to memory shortage.\n");
fclose(file);
break;
@@ -1400,6 +1398,36 @@
char script_opt[64];
int delay_secs = hbt ? hbt->refresh : 0;
+#define HIST_BROWSER_HELP_COMMON \
+ "h/?/F1 Show this window\n" \
+ "UP/DOWN/PGUP\n" \
+ "PGDN/SPACE Navigate\n" \
+ "q/ESC/CTRL+C Exit browser\n\n" \
+ "For multiple event sessions:\n\n" \
+ "TAB/UNTAB Switch events\n\n" \
+ "For symbolic views (--sort has sym):\n\n" \
+ "-> Zoom into DSO/Threads & Annotate current symbol\n" \
+ "<- Zoom out\n" \
+ "a Annotate current symbol\n" \
+ "C Collapse all callchains\n" \
+ "d Zoom into current DSO\n" \
+ "E Expand all callchains\n" \
+
+ /* help messages are sorted by lexical order of the hotkey */
+ const char report_help[] = HIST_BROWSER_HELP_COMMON
+ "i Show header information\n"
+ "P Print histograms to perf.hist.N\n"
+ "r Run available scripts\n"
+ "s Switch to another data file in PWD\n"
+ "t Zoom into current Thread\n"
+ "V Verbose (DSO names in callchains, etc)\n"
+ "/ Filter symbol by name";
+ const char top_help[] = HIST_BROWSER_HELP_COMMON
+ "P Print histograms to perf.hist.N\n"
+ "t Zoom into current Thread\n"
+ "V Verbose (DSO names in callchains, etc)\n"
+ "/ Filter symbol by name";
+
if (browser == NULL)
return -1;
@@ -1484,29 +1512,16 @@
if (is_report_browser(hbt))
goto do_data_switch;
continue;
+ case 'i':
+ /* env->arch is NULL for live-mode (i.e. perf top) */
+ if (env->arch)
+ tui__header_window(env);
+ continue;
case K_F1:
case 'h':
case '?':
ui_browser__help_window(&browser->b,
- "h/?/F1 Show this window\n"
- "UP/DOWN/PGUP\n"
- "PGDN/SPACE Navigate\n"
- "q/ESC/CTRL+C Exit browser\n\n"
- "For multiple event sessions:\n\n"
- "TAB/UNTAB Switch events\n\n"
- "For symbolic views (--sort has sym):\n\n"
- "-> Zoom into DSO/Threads & Annotate current symbol\n"
- "<- Zoom out\n"
- "a Annotate current symbol\n"
- "C Collapse all callchains\n"
- "E Expand all callchains\n"
- "d Zoom into current DSO\n"
- "t Zoom into current Thread\n"
- "r Run available scripts('perf report' only)\n"
- "s Switch to another data file in PWD ('perf report' only)\n"
- "P Print histograms to perf.hist.N\n"
- "V Verbose (DSO names in callchains, etc)\n"
- "/ Filter symbol by name");
+ is_report_browser(hbt) ? report_help : top_help);
continue;
case K_ENTER:
case K_RIGHT:
diff --git a/tools/perf/ui/browsers/scripts.c b/tools/perf/ui/browsers/scripts.c
index d63c68e..402d2bd 100644
--- a/tools/perf/ui/browsers/scripts.c
+++ b/tools/perf/ui/browsers/scripts.c
@@ -173,8 +173,7 @@
if (script.b.width > AVERAGE_LINE_LEN)
script.b.width = AVERAGE_LINE_LEN;
- if (line)
- free(line);
+ free(line);
pclose(fp);
script.nr_lines = nr_entries;
diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c
index 696c1fb..52e7fc4 100644
--- a/tools/perf/ui/gtk/util.c
+++ b/tools/perf/ui/gtk/util.c
@@ -23,8 +23,7 @@
if (!perf_gtk__is_active_context(*ctx))
return -1;
- free(*ctx);
- *ctx = NULL;
+ zfree(ctx);
return 0;
}
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index c244cb5..831fbb7 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -510,7 +510,7 @@
free(line);
out:
- free(rem_sq_bracket);
+ zfree(&rem_sq_bracket);
return ret;
}
diff --git a/tools/perf/ui/tui/util.c b/tools/perf/ui/tui/util.c
index 092902e..bf890f7 100644
--- a/tools/perf/ui/tui/util.c
+++ b/tools/perf/ui/tui/util.c
@@ -92,6 +92,8 @@
t = sep + 1;
}
+ pthread_mutex_lock(&ui__lock);
+
max_len += 2;
nr_lines += 8;
y = SLtt_Screen_Rows / 2 - nr_lines / 2;
@@ -120,13 +122,19 @@
SLsmg_write_nstring((char *)exit_msg, max_len);
SLsmg_refresh();
+ pthread_mutex_unlock(&ui__lock);
+
x += 2;
len = 0;
key = ui__getch(delay_secs);
while (key != K_TIMER && key != K_ENTER && key != K_ESC) {
+ pthread_mutex_lock(&ui__lock);
+
if (key == K_BKSPC) {
- if (len == 0)
+ if (len == 0) {
+ pthread_mutex_unlock(&ui__lock);
goto next_key;
+ }
SLsmg_gotorc(y, x + --len);
SLsmg_write_char(' ');
} else {
@@ -136,6 +144,8 @@
}
SLsmg_refresh();
+ pthread_mutex_unlock(&ui__lock);
+
/* XXX more graceful overflow handling needed */
if (len == sizeof(buf) - 1) {
ui_helpline__push("maximum size of symbol name reached!");
@@ -174,6 +184,8 @@
t = sep + 1;
}
+ pthread_mutex_lock(&ui__lock);
+
max_len += 2;
nr_lines += 4;
y = SLtt_Screen_Rows / 2 - nr_lines / 2,
@@ -195,6 +207,9 @@
SLsmg_gotorc(y + nr_lines - 1, x);
SLsmg_write_nstring((char *)exit_msg, max_len);
SLsmg_refresh();
+
+ pthread_mutex_unlock(&ui__lock);
+
return ui__getch(delay_secs);
}
@@ -215,9 +230,7 @@
if (vasprintf(&s, format, args) > 0) {
int key;
- pthread_mutex_lock(&ui__lock);
key = ui__question_window(title, s, "Press any key...", 0);
- pthread_mutex_unlock(&ui__lock);
free(s);
return key;
}
diff --git a/tools/perf/util/alias.c b/tools/perf/util/alias.c
index e6d1347..c0b43ee 100644
--- a/tools/perf/util/alias.c
+++ b/tools/perf/util/alias.c
@@ -55,8 +55,7 @@
src++;
c = cmdline[src];
if (!c) {
- free(*argv);
- *argv = NULL;
+ zfree(argv);
return error("cmdline ends with \\");
}
}
@@ -68,8 +67,7 @@
cmdline[dst] = 0;
if (quoted) {
- free(*argv);
- *argv = NULL;
+ zfree(argv);
return error("unclosed quote");
}
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 0fcd81e..469eb67 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -26,10 +26,10 @@
static void ins__delete(struct ins_operands *ops)
{
- free(ops->source.raw);
- free(ops->source.name);
- free(ops->target.raw);
- free(ops->target.name);
+ zfree(&ops->source.raw);
+ zfree(&ops->source.name);
+ zfree(&ops->target.raw);
+ zfree(&ops->target.name);
}
static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size,
@@ -185,8 +185,7 @@
return 0;
out_free_ops:
- free(ops->locked.ops);
- ops->locked.ops = NULL;
+ zfree(&ops->locked.ops);
return 0;
}
@@ -205,9 +204,9 @@
static void lock__delete(struct ins_operands *ops)
{
- free(ops->locked.ops);
- free(ops->target.raw);
- free(ops->target.name);
+ zfree(&ops->locked.ops);
+ zfree(&ops->target.raw);
+ zfree(&ops->target.name);
}
static struct ins_ops lock_ops = {
@@ -256,8 +255,7 @@
return 0;
out_free_source:
- free(ops->source.raw);
- ops->source.raw = NULL;
+ zfree(&ops->source.raw);
return -1;
}
@@ -464,17 +462,12 @@
pthread_mutex_unlock(¬es->lock);
}
-int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
- int evidx, u64 addr)
+static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
+ struct annotation *notes, int evidx, u64 addr)
{
unsigned offset;
- struct annotation *notes;
struct sym_hist *h;
- notes = symbol__annotation(sym);
- if (notes->src == NULL)
- return -ENOMEM;
-
pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
if (addr < sym->start || addr > sym->end)
@@ -491,6 +484,33 @@
return 0;
}
+static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
+ int evidx, u64 addr)
+{
+ struct annotation *notes;
+
+ if (sym == NULL || use_browser != 1 || !sort__has_sym)
+ return 0;
+
+ notes = symbol__annotation(sym);
+ if (notes->src == NULL) {
+ if (symbol__alloc_hist(sym) < 0)
+ return -ENOMEM;
+ }
+
+ return __symbol__inc_addr_samples(sym, map, notes, evidx, addr);
+}
+
+int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx)
+{
+ return symbol__inc_addr_samples(ams->sym, ams->map, evidx, ams->al_addr);
+}
+
+int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip)
+{
+ return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip);
+}
+
static void disasm_line__init_ins(struct disasm_line *dl)
{
dl->ins = ins__find(dl->name);
@@ -538,8 +558,7 @@
return 0;
out_free_name:
- free(*namep);
- *namep = NULL;
+ zfree(namep);
return -1;
}
@@ -564,7 +583,7 @@
return dl;
out_free_line:
- free(dl->line);
+ zfree(&dl->line);
out_delete:
free(dl);
return NULL;
@@ -572,8 +591,8 @@
void disasm_line__free(struct disasm_line *dl)
{
- free(dl->line);
- free(dl->name);
+ zfree(&dl->line);
+ zfree(&dl->name);
if (dl->ins && dl->ins->ops->free)
dl->ins->ops->free(&dl->ops);
else
@@ -1091,8 +1110,7 @@
src_line = (void *)src_line + sizeof_src_line;
}
- free(notes->src->lines);
- notes->src->lines = NULL;
+ zfree(¬es->src->lines);
}
/* Get the filename:line for the colored entries */
@@ -1376,3 +1394,8 @@
return 0;
}
+
+int hist_entry__annotate(struct hist_entry *he, size_t privsize)
+{
+ return symbol__annotate(he->ms.sym, he->ms.map, privsize);
+}
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 834b7b5..b2aef59 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -132,12 +132,17 @@
return &a->annotation;
}
-int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
- int evidx, u64 addr);
+int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx);
+
+int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr);
+
int symbol__alloc_hist(struct symbol *sym);
void symbol__annotate_zero_histograms(struct symbol *sym);
int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize);
+
+int hist_entry__annotate(struct hist_entry *he, size_t privsize);
+
int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym);
int symbol__annotate_printf(struct symbol *sym, struct map *map,
struct perf_evsel *evsel, bool full_paths,
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 4f7f989..08b25af 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -146,7 +146,7 @@
struct option;
-int record_parse_callchain(const char *arg, struct perf_record_opts *opts);
+int record_parse_callchain(const char *arg, struct record_opts *opts);
int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset);
int record_callchain_opt(const struct option *opt, const char *arg, int unset);
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
index 96bbda1..0922aa4 100644
--- a/tools/perf/util/cgroup.c
+++ b/tools/perf/util/cgroup.c
@@ -133,7 +133,7 @@
/* XXX: not reentrant */
if (--cgrp->refcnt == 0) {
close(cgrp->fd);
- free(cgrp->name);
+ zfree(&cgrp->name);
free(cgrp);
}
}
diff --git a/tools/perf/util/comm.c b/tools/perf/util/comm.c
index ee0df0e..67d1e40 100644
--- a/tools/perf/util/comm.c
+++ b/tools/perf/util/comm.c
@@ -21,7 +21,7 @@
{
if (!--cs->ref) {
rb_erase(&cs->rb_node, &comm_str_root);
- free(cs->str);
+ zfree(&cs->str);
free(cs);
}
}
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 8640a91..299b555 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -25,7 +25,6 @@
ui_helpline__vshow(fmt, args);
else
ret = vfprintf(stderr, fmt, args);
- va_end(args);
}
return ret;
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 4ddeecb..4045d08 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -497,21 +497,18 @@
symbols__delete(&dso->symbols[i]);
if (dso->short_name_allocated) {
- free((char *)dso->short_name);
- dso->short_name = NULL;
+ zfree((char **)&dso->short_name);
dso->short_name_allocated = false;
}
if (dso->long_name_allocated) {
- free((char *)dso->long_name);
- dso->long_name = NULL;
+ zfree((char **)&dso->long_name);
dso->long_name_allocated = false;
}
dso_cache__free(&dso->cache);
dso__free_a2l(dso);
- free(dso->symsrc_filename);
- dso->symsrc_filename = NULL;
+ zfree(&dso->symsrc_filename);
free(dso);
}
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 6948768..45a76c6 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -106,8 +106,12 @@
memset(&event->comm, 0, sizeof(event->comm));
- tgid = perf_event__get_comm_tgid(pid, event->comm.comm,
- sizeof(event->comm.comm));
+ if (machine__is_host(machine))
+ tgid = perf_event__get_comm_tgid(pid, event->comm.comm,
+ sizeof(event->comm.comm));
+ else
+ tgid = machine->pid;
+
if (tgid < 0)
goto out;
@@ -129,7 +133,11 @@
goto out;
}
- snprintf(filename, sizeof(filename), "/proc/%d/task", pid);
+ if (machine__is_default_guest(machine))
+ return 0;
+
+ snprintf(filename, sizeof(filename), "%s/proc/%d/task",
+ machine->root_dir, pid);
tasks = opendir(filename);
if (tasks == NULL) {
@@ -178,7 +186,11 @@
FILE *fp;
int rc = 0;
- snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);
+ if (machine__is_default_guest(machine))
+ return 0;
+
+ snprintf(filename, sizeof(filename), "%s/proc/%d/maps",
+ machine->root_dir, pid);
fp = fopen(filename, "r");
if (fp == NULL) {
@@ -218,7 +230,10 @@
/*
* Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
*/
- event->header.misc = PERF_RECORD_MISC_USER;
+ if (machine__is_host(machine))
+ event->header.misc = PERF_RECORD_MISC_USER;
+ else
+ event->header.misc = PERF_RECORD_MISC_GUEST_USER;
if (prot[2] != 'x') {
if (!mmap_data || prot[0] != 'r')
@@ -387,6 +402,7 @@
struct machine *machine, bool mmap_data)
{
DIR *proc;
+ char proc_path[PATH_MAX];
struct dirent dirent, *next;
union perf_event *comm_event, *mmap_event;
int err = -1;
@@ -399,7 +415,12 @@
if (mmap_event == NULL)
goto out_free_comm;
- proc = opendir("/proc");
+ if (machine__is_default_guest(machine))
+ return 0;
+
+ snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir);
+ proc = opendir(proc_path);
+
if (proc == NULL)
goto out_free_mmap;
@@ -638,6 +659,7 @@
struct map_groups *mg = &thread->mg;
bool load_map = false;
+ al->machine = machine;
al->thread = thread;
al->addr = addr;
al->cpumode = cpumode;
@@ -658,15 +680,10 @@
al->level = 'g';
mg = &machine->kmaps;
load_map = true;
+ } else if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) {
+ al->level = 'u';
} else {
- /*
- * 'u' means guest os user space.
- * TODO: We don't support guest user space. Might support late.
- */
- if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest)
- al->level = 'u';
- else
- al->level = 'H';
+ al->level = 'H';
al->map = NULL;
if ((cpumode == PERF_RECORD_MISC_GUEST_USER ||
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index da31829..b08a7ec 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -101,10 +101,8 @@
void perf_evlist__exit(struct perf_evlist *evlist)
{
- free(evlist->mmap);
- free(evlist->pollfd);
- evlist->mmap = NULL;
- evlist->pollfd = NULL;
+ zfree(&evlist->mmap);
+ zfree(&evlist->pollfd);
}
void perf_evlist__delete(struct perf_evlist *evlist)
@@ -587,8 +585,7 @@
for (i = 0; i < evlist->nr_mmaps; i++)
__perf_evlist__munmap(evlist, i);
- free(evlist->mmap);
- evlist->mmap = NULL;
+ zfree(&evlist->mmap);
}
static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 9f64ede..2fe5195 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -12,7 +12,7 @@
struct pollfd;
struct thread_map;
struct cpu_map;
-struct perf_record_opts;
+struct record_opts;
#define PERF_EVLIST__HLIST_BITS 8
#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS)
@@ -97,9 +97,8 @@
void perf_evlist__set_id_pos(struct perf_evlist *evlist);
bool perf_can_sample_identifier(void);
-void perf_evlist__config(struct perf_evlist *evlist,
- struct perf_record_opts *opts);
-int perf_record_opts__config(struct perf_record_opts *opts);
+void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts);
+int record_opts__config(struct record_opts *opts);
int perf_evlist__prepare_workload(struct perf_evlist *evlist,
struct target *target,
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 01ff4cf..ade8d9c 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -208,7 +208,7 @@
return evsel;
out_free:
- free(evsel->name);
+ zfree(&evsel->name);
free(evsel);
return NULL;
}
@@ -528,8 +528,7 @@
* enable/disable events specifically, as there's no
* initial traced exec call.
*/
-void perf_evsel__config(struct perf_evsel *evsel,
- struct perf_record_opts *opts)
+void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
{
struct perf_evsel *leader = evsel->leader;
struct perf_event_attr *attr = &evsel->attr;
@@ -751,8 +750,7 @@
{
xyarray__delete(evsel->sample_id);
evsel->sample_id = NULL;
- free(evsel->id);
- evsel->id = NULL;
+ zfree(&evsel->id);
}
void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
@@ -768,7 +766,7 @@
void perf_evsel__free_counts(struct perf_evsel *evsel)
{
- free(evsel->counts);
+ zfree(&evsel->counts);
}
void perf_evsel__exit(struct perf_evsel *evsel)
@@ -782,10 +780,10 @@
{
perf_evsel__exit(evsel);
close_cgroup(evsel->cgrp);
- free(evsel->group_name);
+ zfree(&evsel->group_name);
if (evsel->tp_format)
pevent_free_format(evsel->tp_format);
- free(evsel->name);
+ zfree(&evsel->name);
free(evsel);
}
@@ -1961,8 +1959,7 @@
evsel->attr.type = PERF_TYPE_SOFTWARE;
evsel->attr.config = PERF_COUNT_SW_CPU_CLOCK;
- free(evsel->name);
- evsel->name = NULL;
+ zfree(&evsel->name);
return true;
}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 8120eeb..f1b3256 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -96,7 +96,7 @@
struct cpu_map;
struct thread_map;
struct perf_evlist;
-struct perf_record_opts;
+struct record_opts;
struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx);
@@ -120,7 +120,7 @@
void perf_evsel__delete(struct perf_evsel *evsel);
void perf_evsel__config(struct perf_evsel *evsel,
- struct perf_record_opts *opts);
+ struct record_opts *opts);
int __perf_evsel__sample_size(u64 sample_type);
void perf_evsel__calc_id_pos(struct perf_evsel *evsel);
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 61c5421..a4a60b7 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -800,10 +800,10 @@
return;
for (i = 0 ; i < tp->core_sib; i++)
- free(tp->core_siblings[i]);
+ zfree(&tp->core_siblings[i]);
for (i = 0 ; i < tp->thread_sib; i++)
- free(tp->thread_siblings[i]);
+ zfree(&tp->thread_siblings[i]);
free(tp);
}
@@ -1232,10 +1232,8 @@
return;
for (evsel = events; evsel->attr.size; evsel++) {
- if (evsel->name)
- free(evsel->name);
- if (evsel->id)
- free(evsel->id);
+ zfree(&evsel->name);
+ zfree(&evsel->id);
}
free(events);
@@ -1326,8 +1324,7 @@
}
}
out:
- if (buf)
- free(buf);
+ free(buf);
return events;
error:
if (events)
@@ -2108,7 +2105,7 @@
ret = 0;
out_free:
for (i = 0; i < nr_groups; i++)
- free(desc[i].name);
+ zfree(&desc[i].name);
free(desc);
return ret;
diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c
index 8b1f6e8..86c37c4 100644
--- a/tools/perf/util/help.c
+++ b/tools/perf/util/help.c
@@ -22,8 +22,8 @@
unsigned int i;
for (i = 0; i < cmds->cnt; ++i)
- free(cmds->names[i]);
- free(cmds->names);
+ zfree(&cmds->names[i]);
+ zfree(&cmds->names);
cmds->cnt = 0;
cmds->alloc = 0;
}
@@ -263,9 +263,8 @@
for (i = 0; i < old->cnt; i++)
cmds->names[cmds->cnt++] = old->names[i];
- free(old->names);
+ zfree(&old->names);
old->cnt = 0;
- old->names = NULL;
}
const char *help_unknown_cmd(const char *cmd)
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 822903e..4ed3e88 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1,4 +1,3 @@
-#include "annotate.h"
#include "util.h"
#include "build-id.h"
#include "hist.h"
@@ -342,15 +341,15 @@
}
static struct hist_entry *add_hist_entry(struct hists *hists,
- struct hist_entry *entry,
- struct addr_location *al,
- u64 period,
- u64 weight)
+ struct hist_entry *entry,
+ struct addr_location *al)
{
struct rb_node **p;
struct rb_node *parent = NULL;
struct hist_entry *he;
int64_t cmp;
+ u64 period = entry->stat.period;
+ u64 weight = entry->stat.weight;
p = &hists->entries_in->rb_node;
@@ -373,7 +372,7 @@
* This mem info was allocated from machine__resolve_mem
* and will not be used anymore.
*/
- free(entry->mem_info);
+ zfree(&entry->mem_info);
/* If the map of an existing hist_entry has
* become out-of-date due to an exec() or
@@ -437,7 +436,7 @@
.transaction = transaction,
};
- return add_hist_entry(hists, &entry, al, period, weight);
+ return add_hist_entry(hists, &entry, al);
}
int64_t
@@ -476,8 +475,8 @@
void hist_entry__free(struct hist_entry *he)
{
- free(he->branch_info);
- free(he->mem_info);
+ zfree(&he->branch_info);
+ zfree(&he->mem_info);
free_srcline(he->srcline);
free(he);
}
@@ -807,16 +806,6 @@
}
}
-int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip)
-{
- return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip);
-}
-
-int hist_entry__annotate(struct hist_entry *he, size_t privsize)
-{
- return symbol__annotate(he->ms.sym, he->ms.map, privsize);
-}
-
void events_stats__inc(struct events_stats *stats, u32 type)
{
++stats->nr_events[0];
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index b621347a..a59743f 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -111,9 +111,6 @@
size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
int max_cols, float min_pcnt, FILE *fp);
-int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr);
-int hist_entry__annotate(struct hist_entry *he, size_t privsize);
-
void hists__filter_by_dso(struct hists *hists);
void hists__filter_by_thread(struct hists *hists);
void hists__filter_by_symbol(struct hists *hists);
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index c78cc84..a98538d 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -102,8 +102,7 @@
map_groups__exit(&machine->kmaps);
dsos__delete(&machine->user_dsos);
dsos__delete(&machine->kernel_dsos);
- free(machine->root_dir);
- machine->root_dir = NULL;
+ zfree(&machine->root_dir);
}
void machine__delete(struct machine *machine)
@@ -562,11 +561,10 @@
* on one of them.
*/
if (type == MAP__FUNCTION) {
- free((char *)kmap->ref_reloc_sym->name);
- kmap->ref_reloc_sym->name = NULL;
- free(kmap->ref_reloc_sym);
- }
- kmap->ref_reloc_sym = NULL;
+ zfree((char **)&kmap->ref_reloc_sym->name);
+ zfree(&kmap->ref_reloc_sym);
+ } else
+ kmap->ref_reloc_sym = NULL;
}
map__delete(machine->vmlinux_maps[type]);
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 094c28b..0153435 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -204,7 +204,7 @@
}
path->name = malloc(MAX_EVENT_LENGTH);
if (!path->name) {
- free(path->system);
+ zfree(&path->system);
free(path);
return NULL;
}
@@ -236,8 +236,8 @@
path->name = strdup(str+1);
if (path->system == NULL || path->name == NULL) {
- free(path->system);
- free(path->name);
+ zfree(&path->system);
+ zfree(&path->name);
free(path);
path = NULL;
}
@@ -917,7 +917,7 @@
ret = parse_events__scanner(str, &data, PE_START_TERMS);
if (!ret) {
list_splice(data.terms, terms);
- free(data.terms);
+ zfree(&data.terms);
return 0;
}
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 56fc10a..0934d64 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -755,7 +755,7 @@
continue;
}
printf(" %-50s [Kernel PMU event]\n", aliases[j]);
- free(aliases[j]);
+ zfree(&aliases[j]);
printed++;
}
if (printed)
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 544ac18..86ed858 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -172,6 +172,52 @@
return (dso) ? dso->long_name : NULL;
}
+/* Copied from unwind.c */
+static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
+ GElf_Shdr *shp, const char *name)
+{
+ Elf_Scn *sec = NULL;
+
+ while ((sec = elf_nextscn(elf, sec)) != NULL) {
+ char *str;
+
+ gelf_getshdr(sec, shp);
+ str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
+ if (!strcmp(name, str))
+ break;
+ }
+
+ return sec;
+}
+
+static int get_text_start_address(const char *exec, unsigned long *address)
+{
+ Elf *elf;
+ GElf_Ehdr ehdr;
+ GElf_Shdr shdr;
+ int fd, ret = -ENOENT;
+
+ fd = open(exec, O_RDONLY);
+ if (fd < 0)
+ return -errno;
+
+ elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
+ if (elf == NULL)
+ return -EINVAL;
+
+ if (gelf_getehdr(elf, &ehdr) == NULL)
+ goto out;
+
+ if (!elf_section_by_name(elf, &ehdr, &shdr, ".text"))
+ goto out;
+
+ *address = shdr.sh_addr - shdr.sh_offset;
+ ret = 0;
+out:
+ elf_end(elf);
+ return ret;
+}
+
static int init_user_exec(void)
{
int ret = 0;
@@ -186,6 +232,37 @@
return ret;
}
+static int convert_exec_to_group(const char *exec, char **result)
+{
+ char *ptr1, *ptr2, *exec_copy;
+ char buf[64];
+ int ret;
+
+ exec_copy = strdup(exec);
+ if (!exec_copy)
+ return -ENOMEM;
+
+ ptr1 = basename(exec_copy);
+ if (!ptr1) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ptr2 = strpbrk(ptr1, "-._");
+ if (ptr2)
+ *ptr2 = '\0';
+ ret = e_snprintf(buf, 64, "%s_%s", PERFPROBE_GROUP, ptr1);
+ if (ret < 0)
+ goto out;
+
+ *result = strdup(buf);
+ ret = *result ? 0 : -ENOMEM;
+
+out:
+ free(exec_copy);
+ return ret;
+}
+
static int convert_to_perf_probe_point(struct probe_trace_point *tp,
struct perf_probe_point *pp)
{
@@ -261,6 +338,40 @@
return 0;
}
+static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
+ int ntevs, const char *exec)
+{
+ int i, ret = 0;
+ unsigned long offset, stext = 0;
+ char buf[32];
+
+ if (!exec)
+ return 0;
+
+ ret = get_text_start_address(exec, &stext);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < ntevs && ret >= 0; i++) {
+ offset = tevs[i].point.address - stext;
+ offset += tevs[i].point.offset;
+ tevs[i].point.offset = 0;
+ zfree(&tevs[i].point.symbol);
+ ret = e_snprintf(buf, 32, "0x%lx", offset);
+ if (ret < 0)
+ break;
+ tevs[i].point.module = strdup(exec);
+ tevs[i].point.symbol = strdup(buf);
+ if (!tevs[i].point.symbol || !tevs[i].point.module) {
+ ret = -ENOMEM;
+ break;
+ }
+ tevs[i].uprobes = true;
+ }
+
+ return ret;
+}
+
static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
int ntevs, const char *module)
{
@@ -290,9 +401,7 @@
}
}
- if (tmp)
- free(tmp);
-
+ free(tmp);
return ret;
}
@@ -305,15 +414,6 @@
struct debuginfo *dinfo;
int ntevs, ret = 0;
- if (pev->uprobes) {
- if (need_dwarf) {
- pr_warning("Debuginfo-analysis is not yet supported"
- " with -x/--exec option.\n");
- return -ENOSYS;
- }
- return convert_name_to_addr(pev, target);
- }
-
dinfo = open_debuginfo(target);
if (!dinfo) {
@@ -332,9 +432,14 @@
if (ntevs > 0) { /* Succeeded to find trace events */
pr_debug("find %d probe_trace_events.\n", ntevs);
- if (target)
- ret = add_module_to_probe_trace_events(*tevs, ntevs,
- target);
+ if (target) {
+ if (pev->uprobes)
+ ret = add_exec_to_probe_trace_events(*tevs,
+ ntevs, target);
+ else
+ ret = add_module_to_probe_trace_events(*tevs,
+ ntevs, target);
+ }
return ret < 0 ? ret : ntevs;
}
@@ -401,15 +506,13 @@
case EFAULT:
raw_path = strchr(++raw_path, '/');
if (!raw_path) {
- free(*new_path);
- *new_path = NULL;
+ zfree(new_path);
return -ENOENT;
}
continue;
default:
- free(*new_path);
- *new_path = NULL;
+ zfree(new_path);
return -errno;
}
}
@@ -580,7 +683,7 @@
*/
fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol,
vl->point.offset);
- free(vl->point.symbol);
+ zfree(&vl->point.symbol);
nvars = 0;
if (vl->vars) {
strlist__for_each(node, vl->vars) {
@@ -654,9 +757,6 @@
return -ENOSYS;
}
- if (pev->uprobes)
- return convert_name_to_addr(pev, target);
-
return 0;
}
@@ -1278,8 +1378,7 @@
error:
pr_debug("Failed to synthesize perf probe point: %s\n",
strerror(-ret));
- if (buf)
- free(buf);
+ free(buf);
return NULL;
}
@@ -1480,34 +1579,25 @@
struct perf_probe_arg_field *field, *next;
int i;
- if (pev->event)
- free(pev->event);
- if (pev->group)
- free(pev->group);
- if (pp->file)
- free(pp->file);
- if (pp->function)
- free(pp->function);
- if (pp->lazy_line)
- free(pp->lazy_line);
+ free(pev->event);
+ free(pev->group);
+ free(pp->file);
+ free(pp->function);
+ free(pp->lazy_line);
+
for (i = 0; i < pev->nargs; i++) {
- if (pev->args[i].name)
- free(pev->args[i].name);
- if (pev->args[i].var)
- free(pev->args[i].var);
- if (pev->args[i].type)
- free(pev->args[i].type);
+ free(pev->args[i].name);
+ free(pev->args[i].var);
+ free(pev->args[i].type);
field = pev->args[i].field;
while (field) {
next = field->next;
- if (field->name)
- free(field->name);
+ zfree(&field->name);
free(field);
field = next;
}
}
- if (pev->args)
- free(pev->args);
+ free(pev->args);
memset(pev, 0, sizeof(*pev));
}
@@ -1516,21 +1606,14 @@
struct probe_trace_arg_ref *ref, *next;
int i;
- if (tev->event)
- free(tev->event);
- if (tev->group)
- free(tev->group);
- if (tev->point.symbol)
- free(tev->point.symbol);
- if (tev->point.module)
- free(tev->point.module);
+ free(tev->event);
+ free(tev->group);
+ free(tev->point.symbol);
+ free(tev->point.module);
for (i = 0; i < tev->nargs; i++) {
- if (tev->args[i].name)
- free(tev->args[i].name);
- if (tev->args[i].value)
- free(tev->args[i].value);
- if (tev->args[i].type)
- free(tev->args[i].type);
+ free(tev->args[i].name);
+ free(tev->args[i].value);
+ free(tev->args[i].type);
ref = tev->args[i].ref;
while (ref) {
next = ref->next;
@@ -1538,8 +1621,7 @@
ref = next;
}
}
- if (tev->args)
- free(tev->args);
+ free(tev->args);
memset(tev, 0, sizeof(*tev));
}
@@ -1913,14 +1995,29 @@
int max_tevs, const char *target)
{
struct symbol *sym;
- int ret = 0, i;
+ int ret, i;
struct probe_trace_event *tev;
+ if (pev->uprobes && !pev->group) {
+ /* Replace group name if not given */
+ ret = convert_exec_to_group(target, &pev->group);
+ if (ret != 0) {
+ pr_warning("Failed to make a group name.\n");
+ return ret;
+ }
+ }
+
/* Convert perf_probe_event with debuginfo */
ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, target);
if (ret != 0)
return ret; /* Found in debuginfo or got an error */
+ if (pev->uprobes) {
+ ret = convert_name_to_addr(pev, target);
+ if (ret < 0)
+ return ret;
+ }
+
/* Allocate trace event buffer */
tev = *tevs = zalloc(sizeof(struct probe_trace_event));
if (tev == NULL)
@@ -2056,7 +2153,7 @@
for (i = 0; i < npevs; i++) {
for (j = 0; j < pkgs[i].ntevs; j++)
clear_probe_trace_event(&pkgs[i].tevs[j]);
- free(pkgs[i].tevs);
+ zfree(&pkgs[i].tevs);
}
free(pkgs);
@@ -2281,7 +2378,7 @@
struct perf_probe_point *pp = &pev->point;
struct symbol *sym;
struct map *map = NULL;
- char *function = NULL, *name = NULL;
+ char *function = NULL;
int ret = -EINVAL;
unsigned long long vaddr = 0;
@@ -2297,12 +2394,7 @@
goto out;
}
- name = realpath(exec, NULL);
- if (!name) {
- pr_warning("Cannot find realpath for %s.\n", exec);
- goto out;
- }
- map = dso__new_map(name);
+ map = dso__new_map(exec);
if (!map) {
pr_warning("Cannot find appropriate DSO for %s.\n", exec);
goto out;
@@ -2367,7 +2459,5 @@
}
if (function)
free(function);
- if (name)
- free(name);
return ret;
}
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index f9f3de8..d481c46 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -12,6 +12,7 @@
char *symbol; /* Base symbol */
char *module; /* Module name */
unsigned long offset; /* Offset from symbol */
+ unsigned long address; /* Actual address of the trace point */
bool retprobe; /* Return probe flag */
};
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index ffb657f..061edb1 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -226,10 +226,8 @@
if (!dbg)
return NULL;
- if (debuginfo__init_offline_dwarf(dbg, path) < 0) {
- free(dbg);
- dbg = NULL;
- }
+ if (debuginfo__init_offline_dwarf(dbg, path) < 0)
+ zfree(&dbg);
return dbg;
}
@@ -241,10 +239,8 @@
if (!dbg)
return NULL;
- if (debuginfo__init_online_kernel_dwarf(dbg, (Dwarf_Addr)addr) < 0) {
- free(dbg);
- dbg = NULL;
- }
+ if (debuginfo__init_online_kernel_dwarf(dbg, (Dwarf_Addr)addr) < 0)
+ zfree(&dbg);
return dbg;
}
@@ -729,6 +725,7 @@
return -ENOENT;
}
tp->offset = (unsigned long)(paddr - sym.st_value);
+ tp->address = (unsigned long)paddr;
tp->symbol = strdup(symbol);
if (!tp->symbol)
return -ENOMEM;
@@ -1301,8 +1298,7 @@
ret = debuginfo__find_probes(dbg, &tf.pf);
if (ret < 0) {
- free(*tevs);
- *tevs = NULL;
+ zfree(tevs);
return ret;
}
@@ -1413,13 +1409,10 @@
if (ret < 0) {
/* Free vlist for error */
while (af.nvls--) {
- if (af.vls[af.nvls].point.symbol)
- free(af.vls[af.nvls].point.symbol);
- if (af.vls[af.nvls].vars)
- strlist__delete(af.vls[af.nvls].vars);
+ zfree(&af.vls[af.nvls].point.symbol);
+ strlist__delete(af.vls[af.nvls].vars);
}
- free(af.vls);
- *vls = NULL;
+ zfree(vls);
return ret;
}
@@ -1523,10 +1516,7 @@
if (fname) {
ppt->file = strdup(fname);
if (ppt->file == NULL) {
- if (ppt->function) {
- free(ppt->function);
- ppt->function = NULL;
- }
+ zfree(&ppt->function);
ret = -ENOMEM;
goto end;
}
@@ -1580,8 +1570,7 @@
else
ret = 0; /* Lines are not found */
else {
- free(lf->lr->path);
- lf->lr->path = NULL;
+ zfree(&lf->lr->path);
}
return ret;
}
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index e510453..104a475 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -74,8 +74,7 @@
return perf_probe_api(perf_probe_sample_identifier);
}
-void perf_evlist__config(struct perf_evlist *evlist,
- struct perf_record_opts *opts)
+void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts)
{
struct perf_evsel *evsel;
bool use_sample_identifier = false;
@@ -123,7 +122,7 @@
return filename__read_int(path, (int *) rate);
}
-static int perf_record_opts__config_freq(struct perf_record_opts *opts)
+static int record_opts__config_freq(struct record_opts *opts)
{
bool user_freq = opts->user_freq != UINT_MAX;
unsigned int max_rate;
@@ -173,9 +172,9 @@
return 0;
}
-int perf_record_opts__config(struct perf_record_opts *opts)
+int record_opts__config(struct record_opts *opts)
{
- return perf_record_opts__config_freq(opts);
+ return record_opts__config_freq(opts);
}
bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index d5e5969..e108207 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -194,8 +194,7 @@
zero_flag_atom = 0;
break;
case PRINT_FIELD:
- if (cur_field_name)
- free(cur_field_name);
+ free(cur_field_name);
cur_field_name = strdup(args->field.name);
break;
case PRINT_FLAGS:
@@ -257,12 +256,9 @@
return event;
}
-static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused,
- struct perf_sample *sample,
+static void perl_process_tracepoint(struct perf_sample *sample,
struct perf_evsel *evsel,
- struct machine *machine __maybe_unused,
- struct thread *thread,
- struct addr_location *al)
+ struct thread *thread)
{
struct format_field *field;
static char handler[256];
@@ -349,10 +345,7 @@
static void perl_process_event_generic(union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel,
- struct machine *machine __maybe_unused,
- struct thread *thread __maybe_unused,
- struct addr_location *al __maybe_unused)
+ struct perf_evsel *evsel)
{
dSP;
@@ -377,12 +370,11 @@
static void perl_process_event(union perf_event *event,
struct perf_sample *sample,
struct perf_evsel *evsel,
- struct machine *machine,
struct thread *thread,
- struct addr_location *al)
+ struct addr_location *al __maybe_unused)
{
- perl_process_tracepoint(event, sample, evsel, machine, thread, al);
- perl_process_event_generic(event, sample, evsel, machine, thread, al);
+ perl_process_tracepoint(sample, evsel, thread);
+ perl_process_event_generic(event, sample, evsel);
}
static void run_start_sub(void)
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 53c20e7..cd9774d 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -161,8 +161,7 @@
zero_flag_atom = 0;
break;
case PRINT_FIELD:
- if (cur_field_name)
- free(cur_field_name);
+ free(cur_field_name);
cur_field_name = strdup(args->field.name);
break;
case PRINT_FLAGS:
@@ -231,13 +230,10 @@
return event;
}
-static void python_process_tracepoint(union perf_event *perf_event
- __maybe_unused,
- struct perf_sample *sample,
- struct perf_evsel *evsel,
- struct machine *machine __maybe_unused,
- struct thread *thread,
- struct addr_location *al)
+static void python_process_tracepoint(struct perf_sample *sample,
+ struct perf_evsel *evsel,
+ struct thread *thread,
+ struct addr_location *al)
{
PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;
static char handler_name[256];
@@ -351,11 +347,8 @@
Py_DECREF(t);
}
-static void python_process_general_event(union perf_event *perf_event
- __maybe_unused,
- struct perf_sample *sample,
+static void python_process_general_event(struct perf_sample *sample,
struct perf_evsel *evsel,
- struct machine *machine __maybe_unused,
struct thread *thread,
struct addr_location *al)
{
@@ -411,22 +404,19 @@
Py_DECREF(t);
}
-static void python_process_event(union perf_event *perf_event,
+static void python_process_event(union perf_event *event __maybe_unused,
struct perf_sample *sample,
struct perf_evsel *evsel,
- struct machine *machine,
struct thread *thread,
struct addr_location *al)
{
switch (evsel->attr.type) {
case PERF_TYPE_TRACEPOINT:
- python_process_tracepoint(perf_event, sample, evsel,
- machine, thread, al);
+ python_process_tracepoint(sample, evsel, thread, al);
break;
/* Reserve for future process_hw/sw/raw APIs */
default:
- python_process_general_event(perf_event, sample, evsel,
- machine, thread, al);
+ python_process_general_event(sample, evsel, thread, al);
}
}
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 989b2e3..8ffe29c 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -132,18 +132,18 @@
static void perf_session_env__delete(struct perf_session_env *env)
{
- free(env->hostname);
- free(env->os_release);
- free(env->version);
- free(env->arch);
- free(env->cpu_desc);
- free(env->cpuid);
+ zfree(&env->hostname);
+ zfree(&env->os_release);
+ zfree(&env->version);
+ zfree(&env->arch);
+ zfree(&env->cpu_desc);
+ zfree(&env->cpuid);
- free(env->cmdline);
- free(env->sibling_cores);
- free(env->sibling_threads);
- free(env->numa_nodes);
- free(env->pmu_mappings);
+ zfree(&env->cmdline);
+ zfree(&env->sibling_cores);
+ zfree(&env->sibling_threads);
+ zfree(&env->numa_nodes);
+ zfree(&env->pmu_mappings);
}
void perf_session__delete(struct perf_session *session)
@@ -830,6 +830,7 @@
struct perf_sample *sample)
{
const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
+ struct machine *machine;
if (perf_guest &&
((cpumode == PERF_RECORD_MISC_GUEST_KERNEL) ||
@@ -842,7 +843,11 @@
else
pid = sample->pid;
- return perf_session__findnew_machine(session, pid);
+ machine = perf_session__find_machine(session, pid);
+ if (!machine)
+ machine = perf_session__findnew_machine(session,
+ DEFAULT_GUEST_KERNEL_ID);
+ return machine;
}
return &session->machines.host;
@@ -1467,7 +1472,7 @@
}
void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
- struct machine *machine, struct addr_location *al,
+ struct addr_location *al,
unsigned int print_opts, unsigned int stack_depth)
{
struct callchain_cursor_node *node;
@@ -1482,7 +1487,7 @@
if (symbol_conf.use_callchain && sample->callchain) {
struct addr_location node_al;
- if (machine__resolve_callchain(machine, evsel, al->thread,
+ if (machine__resolve_callchain(al->machine, evsel, al->thread,
sample, NULL, NULL,
PERF_MAX_STACK_DEPTH) != 0) {
if (verbose)
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 9c25d49..3140f8a 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -106,7 +106,7 @@
unsigned int type);
void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
- struct machine *machine, struct addr_location *al,
+ struct addr_location *al,
unsigned int print_opts, unsigned int stack_depth);
int perf_session__cpu_bitmap(struct perf_session *session,
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 8b0bb1f..635cd8f 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -13,6 +13,7 @@
int sort__need_collapse = 0;
int sort__has_parent = 0;
int sort__has_sym = 0;
+int sort__has_dso = 0;
enum sort_mode sort__mode = SORT_MODE__NORMAL;
enum sort_type sort__first_dimension;
@@ -161,6 +162,11 @@
/* --sort symbol */
+static int64_t _sort__addr_cmp(u64 left_ip, u64 right_ip)
+{
+ return (int64_t)(right_ip - left_ip);
+}
+
static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r)
{
u64 ip_l, ip_r;
@@ -183,15 +189,17 @@
int64_t ret;
if (!left->ms.sym && !right->ms.sym)
- return right->level - left->level;
+ return _sort__addr_cmp(left->ip, right->ip);
/*
* comparing symbol address alone is not enough since it's a
* relative address within a dso.
*/
- ret = sort__dso_cmp(left, right);
- if (ret != 0)
- return ret;
+ if (!sort__has_dso) {
+ ret = sort__dso_cmp(left, right);
+ if (ret != 0)
+ return ret;
+ }
return _sort__sym_cmp(left->ms.sym, right->ms.sym);
}
@@ -372,7 +380,7 @@
struct addr_map_symbol *from_r = &right->branch_info->from;
if (!from_l->sym && !from_r->sym)
- return right->level - left->level;
+ return _sort__addr_cmp(from_l->addr, from_r->addr);
return _sort__sym_cmp(from_l->sym, from_r->sym);
}
@@ -384,7 +392,7 @@
struct addr_map_symbol *to_r = &right->branch_info->to;
if (!to_l->sym && !to_r->sym)
- return right->level - left->level;
+ return _sort__addr_cmp(to_l->addr, to_r->addr);
return _sort__sym_cmp(to_l->sym, to_r->sym);
}
@@ -1056,6 +1064,8 @@
sort__has_parent = 1;
} else if (sd->entry == &sort_sym) {
sort__has_sym = 1;
+ } else if (sd->entry == &sort_dso) {
+ sort__has_dso = 1;
}
__sort_dimension__add(sd, i);
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
index 58b2bd8..7e67879 100644
--- a/tools/perf/util/srcline.c
+++ b/tools/perf/util/srcline.c
@@ -129,7 +129,7 @@
out:
if (a2l) {
- free((void *)a2l->input);
+ zfree((void **)&a2l->input);
free(a2l);
}
bfd_close(abfd);
@@ -140,8 +140,8 @@
{
if (a2l->abfd)
bfd_close(a2l->abfd);
- free((void *)a2l->input);
- free(a2l->syms);
+ zfree((void **)&a2l->input);
+ zfree(&a2l->syms);
free(a2l);
}
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c
index cfa9068..4abe235 100644
--- a/tools/perf/util/strbuf.c
+++ b/tools/perf/util/strbuf.c
@@ -28,7 +28,7 @@
void strbuf_release(struct strbuf *sb)
{
if (sb->alloc) {
- free(sb->buf);
+ zfree(&sb->buf);
strbuf_init(sb, 0);
}
}
diff --git a/tools/perf/util/strfilter.c b/tools/perf/util/strfilter.c
index 3edd053..79a757a 100644
--- a/tools/perf/util/strfilter.c
+++ b/tools/perf/util/strfilter.c
@@ -14,7 +14,7 @@
{
if (node) {
if (node->p && !is_operator(*node->p))
- free((char *)node->p);
+ zfree((char **)&node->p);
strfilter_node__delete(node->l);
strfilter_node__delete(node->r);
free(node);
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index f0b0c00..2553e5b 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -128,7 +128,7 @@
{
char **p;
for (p = argv; *p; p++)
- free(*p);
+ zfree(p);
free(argv);
}
diff --git a/tools/perf/util/strlist.c b/tools/perf/util/strlist.c
index eabdce0..61a90bf 100644
--- a/tools/perf/util/strlist.c
+++ b/tools/perf/util/strlist.c
@@ -5,6 +5,7 @@
*/
#include "strlist.h"
+#include "util.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@@ -38,7 +39,7 @@
static void str_node__delete(struct str_node *snode, bool dupstr)
{
if (dupstr)
- free((void *)snode->s);
+ zfree((void **)&snode->s);
free(snode);
}
diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c
index 56a84f2..43262b8 100644
--- a/tools/perf/util/svghelper.c
+++ b/tools/perf/util/svghelper.c
@@ -21,6 +21,7 @@
#include "perf.h"
#include "svghelper.h"
+#include "util.h"
#include "cpumap.h"
static u64 first_time, last_time;
@@ -708,8 +709,8 @@
return 0;
exit:
- free(t.sib_core);
- free(t.sib_thr);
+ zfree(&t.sib_core);
+ zfree(&t.sib_thr);
return -1;
}
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index bf0ce29..4b0a127 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -554,7 +554,7 @@
void symsrc__destroy(struct symsrc *ss)
{
- free(ss->name);
+ zfree(&ss->name);
elf_end(ss->elf);
close(ss->fd);
}
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index ac7070a..bd15f49 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -1,4 +1,5 @@
#include "symbol.h"
+#include "util.h"
#include <stdio.h>
#include <fcntl.h>
@@ -275,7 +276,7 @@
void symsrc__destroy(struct symsrc *ss)
{
- free(ss->name);
+ zfree(&ss->name);
close(ss->fd);
}
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 923d000..39ce9ad 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -796,7 +796,7 @@
mi = rb_entry(next, struct module_info, rb_node);
next = rb_next(&mi->rb_node);
rb_erase(&mi->rb_node, modules);
- free(mi->name);
+ zfree(&mi->name);
free(mi);
}
}
@@ -1621,13 +1621,10 @@
static void vmlinux_path__exit(void)
{
- while (--vmlinux_path__nr_entries >= 0) {
- free(vmlinux_path[vmlinux_path__nr_entries]);
- vmlinux_path[vmlinux_path__nr_entries] = NULL;
- }
+ while (--vmlinux_path__nr_entries >= 0)
+ zfree(&vmlinux_path[vmlinux_path__nr_entries]);
- free(vmlinux_path);
- vmlinux_path = NULL;
+ zfree(&vmlinux_path);
}
static int vmlinux_path__init(void)
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 8a9d910..cbd6803 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -164,6 +164,7 @@
};
struct addr_location {
+ struct machine *machine;
struct thread *thread;
struct map *map;
struct symbol *sym;
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index 9b5f856..5d32159 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -9,6 +9,7 @@
#include "strlist.h"
#include <string.h>
#include "thread_map.h"
+#include "util.h"
/* Skip "." and ".." directories */
static int filter(const struct dirent *dir)
@@ -40,7 +41,7 @@
}
for (i=0; i<items; i++)
- free(namelist[i]);
+ zfree(&namelist[i]);
free(namelist);
return threads;
@@ -117,7 +118,7 @@
threads->map[threads->nr + i] = atoi(namelist[i]->d_name);
for (i = 0; i < items; i++)
- free(namelist[i]);
+ zfree(&namelist[i]);
free(namelist);
threads->nr += items;
@@ -134,12 +135,11 @@
out_free_namelist:
for (i = 0; i < items; i++)
- free(namelist[i]);
+ zfree(&namelist[i]);
free(namelist);
out_free_closedir:
- free(threads);
- threads = NULL;
+ zfree(&threads);
goto out_closedir;
}
@@ -194,7 +194,7 @@
for (i = 0; i < items; i++) {
threads->map[j++] = atoi(namelist[i]->d_name);
- free(namelist[i]);
+ zfree(&namelist[i]);
}
threads->nr = total_tasks;
free(namelist);
@@ -206,12 +206,11 @@
out_free_namelist:
for (i = 0; i < items; i++)
- free(namelist[i]);
+ zfree(&namelist[i]);
free(namelist);
out_free_threads:
- free(threads);
- threads = NULL;
+ zfree(&threads);
goto out;
}
@@ -262,8 +261,7 @@
return threads;
out_free_threads:
- free(threads);
- threads = NULL;
+ zfree(&threads);
goto out;
}
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c
index ce793c7..8e517de 100644
--- a/tools/perf/util/top.c
+++ b/tools/perf/util/top.c
@@ -26,7 +26,7 @@
float samples_per_sec;
float ksamples_per_sec;
float esamples_percent;
- struct perf_record_opts *opts = &top->record_opts;
+ struct record_opts *opts = &top->record_opts;
struct target *target = &opts->target;
size_t ret = 0;
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index 88cfeaf..dab14d0 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -14,7 +14,7 @@
struct perf_top {
struct perf_tool tool;
struct perf_evlist *evlist;
- struct perf_record_opts record_opts;
+ struct record_opts record_opts;
/*
* Symbols will be added here in perf_event__process_sample and will
* get out after decayed.
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index c354b95..7e6fcfe 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -397,8 +397,8 @@
struct tracepoint_path *t = tps;
tps = tps->next;
- free(t->name);
- free(t->system);
+ zfree(&t->name);
+ zfree(&t->system);
free(t);
}
}
@@ -562,10 +562,8 @@
output_fd = fd;
}
- if (err) {
- free(tdata);
- tdata = NULL;
- }
+ if (err)
+ zfree(&tdata);
put_tracepoints_path(tps);
return tdata;
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index 95199e4..57aaccc 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -38,9 +38,8 @@
static void process_event_unsupported(union perf_event *event __maybe_unused,
struct perf_sample *sample __maybe_unused,
struct perf_evsel *evsel __maybe_unused,
- struct machine *machine __maybe_unused,
struct thread *thread __maybe_unused,
- struct addr_location *al __maybe_unused)
+ struct addr_location *al __maybe_unused)
{
}
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 3a01618..7b6d686 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -68,7 +68,6 @@
void (*process_event) (union perf_event *event,
struct perf_sample *sample,
struct perf_evsel *evsel,
- struct machine *machine,
struct thread *thread,
struct addr_location *al);
int (*generate_script) (struct pevent *pevent, const char *outfile);
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 9a2c268..6995d66 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -186,6 +186,8 @@
return calloc(1, size);
}
+#define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
+
static inline int has_extension(const char *filename, const char *ext)
{
size_t len = strlen(filename);
diff --git a/tools/perf/util/values.c b/tools/perf/util/values.c
index 697c8b4..0fb3c1f 100644
--- a/tools/perf/util/values.c
+++ b/tools/perf/util/values.c
@@ -31,14 +31,14 @@
return;
for (i = 0; i < values->threads; i++)
- free(values->value[i]);
- free(values->value);
- free(values->pid);
- free(values->tid);
- free(values->counterrawid);
+ zfree(&values->value[i]);
+ zfree(&values->value);
+ zfree(&values->pid);
+ zfree(&values->tid);
+ zfree(&values->counterrawid);
for (i = 0; i < values->counters; i++)
- free(values->countername[i]);
- free(values->countername);
+ zfree(&values->countername[i]);
+ zfree(&values->countername);
}
static void perf_read_values__enlarge_threads(struct perf_read_values *values)
diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
index ee76544..8abbef1 100644
--- a/tools/scripts/Makefile.include
+++ b/tools/scripts/Makefile.include
@@ -61,6 +61,7 @@
ifneq ($(findstring $(MAKEFLAGS),s),s)
ifneq ($(V),1)
QUIET_CC = @echo ' CC '$@;
+ QUIET_CC_FPIC = @echo ' CC FPIC '$@;
QUIET_AR = @echo ' AR '$@;
QUIET_LINK = @echo ' LINK '$@;
QUIET_MKDIR = @echo ' MKDIR '$@;
@@ -76,5 +77,8 @@
+@echo ' DESCEND '$(1); \
mkdir -p $(OUTPUT)$(1) && \
$(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) $(2)
+
+ QUIET_CLEAN = @printf ' CLEAN %s\n' $1;
+ QUIET_INSTALL = @printf ' INSTALL %s\n' $1;
endif
endif