提交 81393214 编写于 作者: I Ingo Molnar

Merge tag 'perf-core-for-mingo' of...

Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core

Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:

  * Add an option in 'perf script' to print the source line number, from Adrian Hunter

  * Add --header/--header-only options to 'script' and 'report', the default is not
    tho show the header info, but as this has been the default for some time,
    leave a single line explaining how to obtain that information, from Jiri Olsa.

  * Fix symoff printing in callchains in 'perf script', from Adrian Hunter.

  * Assorted mmap_pages handling fixes, from Adrian Hunter.

  * Fix summary percentage when processing files in 'perf trace', from David Ahern.

  * Handle old kernels where the "raw_syscalls" tracepoints were called plan "syscalls",
    in 'perf trace', from David Ahern.

  * Several man pages typo fixes from Dongsheng Yang.

  * Add '-v' option to 'perf kvm', from Dongsheng Yang.

  * Make perf kvm diff support --guestmount, from Dongsheng Yang.

  * Get rid of several die() calls in libtraceevent, from Namhyung Kim.

  * Use basename() in a more robust way, to avoid problems related to different
    system library implementations for that function, from Stephane Eranian.

  * Remove open coded management of short_name_allocated member, from Adrian Hunter

  * Several cleanups in the "dso" methods, constifying some parameters and
    renaming some fields to clarify its purpose. (Arnaldo Carvalho de Melo.)

  * Add per-feature check flags, fixing libunwind related build problems on some
    architectures, from Jean Pihet.
Signed-off-by: NArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: NIngo Molnar <mingo@kernel.org>
......@@ -2710,7 +2710,6 @@ process_func_handler(struct event_format *event, struct pevent_function_handler
struct print_arg *farg;
enum event_type type;
char *token;
const char *test;
int i;
arg->type = PRINT_FUNC;
......@@ -2727,15 +2726,19 @@ process_func_handler(struct event_format *event, struct pevent_function_handler
}
type = process_arg(event, farg, &token);
if (i < (func->nr_args - 1))
test = ",";
else
test = ")";
if (test_type_token(type, token, EVENT_DELIM, test)) {
free_arg(farg);
free_token(token);
return EVENT_ERROR;
if (i < (func->nr_args - 1)) {
if (type != EVENT_DELIM || strcmp(token, ",") != 0) {
warning("Error: function '%s()' expects %d arguments but event %s only uses %d",
func->name, func->nr_args,
event->name, i + 1);
goto err;
}
} else {
if (type != EVENT_DELIM || strcmp(token, ")") != 0) {
warning("Error: function '%s()' only expects %d arguments but event %s has more",
func->name, func->nr_args, event->name);
goto err;
}
}
*next_arg = farg;
......@@ -2747,6 +2750,11 @@ process_func_handler(struct event_format *event, struct pevent_function_handler
*tok = token;
return type;
err:
free_arg(farg);
free_token(token);
return EVENT_ERROR;
}
static enum event_type
......
......@@ -860,7 +860,7 @@ int pevent_event_filtered(struct event_filter *filter,
void pevent_filter_reset(struct event_filter *filter);
void pevent_filter_clear_trivial(struct event_filter *filter,
int pevent_filter_clear_trivial(struct event_filter *filter,
enum filter_trivial_type type);
void pevent_filter_free(struct event_filter *filter);
......
......@@ -182,7 +182,10 @@ struct event_filter *pevent_filter_alloc(struct pevent *pevent)
{
struct event_filter *filter;
filter = malloc_or_die(sizeof(*filter));
filter = malloc(sizeof(*filter));
if (filter == NULL)
return NULL;
memset(filter, 0, sizeof(*filter));
filter->pevent = pevent;
pevent_ref(pevent);
......@@ -242,15 +245,19 @@ static void free_arg(struct filter_arg *arg)
free(arg);
}
static void add_event(struct event_list **events,
static int add_event(struct event_list **events,
struct event_format *event)
{
struct event_list *list;
list = malloc_or_die(sizeof(*list));
list = malloc(sizeof(*list));
if (list == NULL)
return -1;
list->next = *events;
*events = list;
list->event = event;
return 0;
}
static int event_match(struct event_format *event,
......@@ -273,6 +280,7 @@ find_event(struct pevent *pevent, struct event_list **events,
regex_t ereg;
regex_t sreg;
int match = 0;
int fail = 0;
char *reg;
int ret;
int i;
......@@ -307,7 +315,10 @@ find_event(struct pevent *pevent, struct event_list **events,
event = pevent->events[i];
if (event_match(event, sys_name ? &sreg : NULL, &ereg)) {
match = 1;
add_event(events, event);
if (add_event(events, event) < 0) {
fail = 1;
break;
}
}
}
......@@ -317,6 +328,8 @@ find_event(struct pevent *pevent, struct event_list **events,
if (!match)
return -1;
if (fail)
return -2;
return 0;
}
......@@ -349,8 +362,11 @@ create_arg_item(struct event_format *event, const char *token,
arg->value.type =
type == EVENT_DQUOTE ? FILTER_STRING : FILTER_CHAR;
arg->value.str = strdup(token);
if (!arg->value.str)
die("malloc string");
if (!arg->value.str) {
free_arg(arg);
show_error(error_str, "failed to allocate string filter arg");
return NULL;
}
break;
case EVENT_ITEM:
/* if it is a number, then convert it */
......@@ -1210,7 +1226,13 @@ int pevent_filter_add_filter_str(struct event_filter *filter,
else
len = strlen(filter_str);
this_event = malloc_or_die(len + 1);
this_event = malloc(len + 1);
if (this_event == NULL) {
show_error(error_str, "Memory allocation failure");
/* This can only happen when events is NULL, but still */
free_events(events);
return -1;
}
memcpy(this_event, filter_str, len);
this_event[len] = 0;
......@@ -1482,8 +1504,10 @@ int pevent_update_trivial(struct event_filter *dest, struct event_filter *source
* @type: remove only true, false, or both
*
* Removes filters that only contain a TRUE or FALES boolean arg.
*
* Returns 0 on success and -1 if there was a problem.
*/
void pevent_filter_clear_trivial(struct event_filter *filter,
int pevent_filter_clear_trivial(struct event_filter *filter,
enum filter_trivial_type type)
{
struct filter_type *filter_type;
......@@ -1492,13 +1516,15 @@ void pevent_filter_clear_trivial(struct event_filter *filter,
int i;
if (!filter->filters)
return;
return 0;
/*
* Two steps, first get all ids with trivial filters.
* then remove those ids.
*/
for (i = 0; i < filter->filters; i++) {
int *new_ids;
filter_type = &filter->event_filters[i];
if (filter_type->filter->type != FILTER_ARG_BOOLEAN)
continue;
......@@ -1513,19 +1539,24 @@ void pevent_filter_clear_trivial(struct event_filter *filter,
break;
}
ids = realloc(ids, sizeof(*ids) * (count + 1));
if (!ids)
die("Can't allocate ids");
new_ids = realloc(ids, sizeof(*ids) * (count + 1));
if (!new_ids) {
free(ids);
return -1;
}
ids = new_ids;
ids[count++] = filter_type->event_id;
}
if (!count)
return;
return 0;
for (i = 0; i < count; i++)
pevent_filter_remove_event(filter, ids[i]);
free(ids);
return 0;
}
/**
......
......@@ -12,9 +12,9 @@ SYNOPSIS
DESCRIPTION
-----------
This command runs runs perf-buildid-list --with-hits, and collects the files
with the buildids found so that analysis of perf.data contents can be possible
on another machine.
This command runs perf-buildid-list --with-hits, and collects the files with the
buildids found so that analysis of perf.data contents can be possible on another
machine.
SEE ALSO
......
......@@ -10,9 +10,9 @@ SYNOPSIS
[verse]
'perf kvm' [--host] [--guest] [--guestmount=<path>
[--guestkallsyms=<path> --guestmodules=<path> | --guestvmlinux=<path>]]
{top|record|report|diff|buildid-list}
{top|record|report|diff|buildid-list} [<options>]
'perf kvm' [--host] [--guest] [--guestkallsyms=<path> --guestmodules=<path>
| --guestvmlinux=<path>] {top|record|report|diff|buildid-list|stat}
| --guestvmlinux=<path>] {top|record|report|diff|buildid-list|stat} [<options>]
'perf kvm stat [record|report|live] [<options>]
DESCRIPTION
......@@ -93,6 +93,9 @@ OPTIONS
kernel module information. Users copy it out from guest os.
--guestvmlinux=<path>::
Guest os kernel vmlinux.
-v::
--verbose::
Be more verbose (show counter open errors, etc).
STAT REPORT OPTIONS
-------------------
......
......@@ -237,6 +237,15 @@ OPTIONS
Do not show entries which have an overhead under that percent.
(Default: 0).
--header::
Show header information in the perf.data file. This includes
various information like hostname, OS and perf version, cpu/mem
info, perf command line, event list and so on. Currently only
--stdio output supports this feature.
--header-only::
Show only perf.data header (forces --stdio).
SEE ALSO
--------
linkperf:perf-stat[1], linkperf:perf-annotate[1]
......@@ -115,7 +115,7 @@ OPTIONS
-f::
--fields::
Comma separated list of fields to print. Options are:
comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff.
comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, srcline.
Field list can be prepended with the type, trace, sw or hw,
to indicate to which event type the field list applies.
e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace
......@@ -209,6 +209,12 @@ OPTIONS
--show-mmap-events
Display mmap related events (e.g. MMAP, MMAP2).
--header
Show perf.data header.
--header-only
Show only perf.data header.
SEE ALSO
--------
linkperf:perf-record[1], linkperf:perf-script-perl[1],
......
......@@ -373,7 +373,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
if (argc) {
/*
* Special case: if there's an argument left then assume tha
* Special case: if there's an argument left then assume that
* it's a symbol filter:
*/
if (argc > 1)
......
......@@ -1000,8 +1000,7 @@ static int data_init(int argc, const char **argv)
data__files_cnt = argc;
use_default = false;
}
} else if (symbol_conf.default_guest_vmlinux_name ||
symbol_conf.default_guest_kallsyms) {
} else if (perf_guest) {
defaults[0] = "perf.data.host";
defaults[1] = "perf.data.guest";
}
......
......@@ -1232,7 +1232,7 @@ static int read_events(struct perf_kvm_stat *kvm)
.ordered_samples = true,
};
struct perf_data_file file = {
.path = input_name,
.path = kvm->file_name,
.mode = PERF_DATA_MODE_READ,
};
......@@ -1690,6 +1690,8 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
"file", "file saving guest os /proc/kallsyms"),
OPT_STRING(0, "guestmodules", &symbol_conf.default_guest_modules,
"file", "file saving guest os /proc/modules"),
OPT_INCR('v', "verbose", &verbose,
"be more verbose (show counter open errors, etc)"),
OPT_END()
};
......@@ -1711,12 +1713,7 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
perf_guest = 1;
if (!file_name) {
if (perf_host && !perf_guest)
file_name = strdup("perf.data.host");
else if (!perf_host && perf_guest)
file_name = strdup("perf.data.guest");
else
file_name = strdup("perf.data.kvm");
file_name = get_filename_for_perf_kvm();
if (!file_name) {
pr_err("Failed to allocate memory for filename\n");
......
......@@ -224,7 +224,7 @@ static int perf_record__open(struct perf_record *rec)
"Consider increasing "
"/proc/sys/kernel/perf_event_mlock_kb,\n"
"or try again with a smaller value of -m/--mmap_pages.\n"
"(current value: %d)\n", opts->mmap_pages);
"(current value: %u)\n", opts->mmap_pages);
rc = -errno;
} else {
pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno));
......
......@@ -49,6 +49,8 @@ struct perf_report {
bool show_threads;
bool inverted_callchain;
bool mem_mode;
bool header;
bool header_only;
int max_stack;
struct perf_read_values show_threads_values;
const char *pretty_printing_style;
......@@ -514,9 +516,6 @@ static int __cmd_report(struct perf_report *rep)
return ret;
}
if (use_browser <= 0)
perf_session__fprintf_info(session, stdout, rep->show_full_info);
if (rep->show_threads)
perf_read_values_init(&rep->show_threads_values);
......@@ -820,6 +819,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
OPT_BOOLEAN(0, "gtk", &report.use_gtk, "Use the GTK2 interface"),
OPT_BOOLEAN(0, "stdio", &report.use_stdio,
"Use the stdio interface"),
OPT_BOOLEAN(0, "header", &report.header, "Show data header."),
OPT_BOOLEAN(0, "header-only", &report.header_only,
"Show only data header."),
OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
"sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline,"
" dso_to, dso_from, symbol_to, symbol_from, mispredict,"
......@@ -963,6 +965,10 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
goto error;
}
/* Force tty output for header output. */
if (report.header || report.header_only)
use_browser = 0;
if (strcmp(input_name, "-") != 0)
setup_browser(true);
else {
......@@ -970,6 +976,16 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
perf_hpp__init();
}
if (report.header || report.header_only) {
perf_session__fprintf_info(session, stdout,
report.show_full_info);
if (report.header_only)
return 0;
} else if (use_browser == 0) {
fputs("# To display the perf.data header info, please use --header/--header-only options.\n#\n",
stdout);
}
/*
* Only in the TUI browser we are doing integrated annotation,
* so don't allocate extra space that won't be used in the stdio
......
......@@ -43,6 +43,7 @@ enum perf_output_field {
PERF_OUTPUT_DSO = 1U << 9,
PERF_OUTPUT_ADDR = 1U << 10,
PERF_OUTPUT_SYMOFFSET = 1U << 11,
PERF_OUTPUT_SRCLINE = 1U << 12,
};
struct output_option {
......@@ -61,6 +62,7 @@ struct output_option {
{.str = "dso", .field = PERF_OUTPUT_DSO},
{.str = "addr", .field = PERF_OUTPUT_ADDR},
{.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET},
{.str = "srcline", .field = PERF_OUTPUT_SRCLINE},
};
/* default set to maintain compatibility with current format */
......@@ -210,6 +212,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
"to DSO.\n");
return -EINVAL;
}
if (PRINT_FIELD(SRCLINE) && !PRINT_FIELD(IP)) {
pr_err("Display of source line number requested but sample IP is not\n"
"selected. Hence, no address to lookup the source line number.\n");
return -EINVAL;
}
if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID",
......@@ -245,6 +252,9 @@ static void set_print_ip_opts(struct perf_event_attr *attr)
if (PRINT_FIELD(SYMOFFSET))
output[type].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET;
if (PRINT_FIELD(SRCLINE))
output[type].print_ip_opts |= PRINT_IP_OPT_SRCLINE;
}
/*
......@@ -1484,6 +1494,8 @@ static int have_cmd(int argc, const char **argv)
int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
{
bool show_full_info = false;
bool header = false;
bool header_only = false;
char *rec_script_path = NULL;
char *rep_script_path = NULL;
struct perf_session *session;
......@@ -1522,6 +1534,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
OPT_STRING('i', "input", &input_name, "file", "input file name"),
OPT_BOOLEAN('d', "debug-mode", &debug_mode,
"do various checks like samples ordering and lost events"),
OPT_BOOLEAN(0, "header", &header, "Show data header."),
OPT_BOOLEAN(0, "header-only", &header_only, "Show only data header."),
OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
"file", "vmlinux pathname"),
OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
......@@ -1738,6 +1752,12 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
if (session == NULL)
return -ENOMEM;
if (header || header_only) {
perf_session__fprintf_info(session, stdout, show_full_info);
if (header_only)
return 0;
}
script.session = session;
if (cpu_list) {
......@@ -1745,9 +1765,6 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
return -1;
}
if (!script_name && !generate_script_lang)
perf_session__fprintf_info(session, stdout, show_full_info);
if (!no_callchain)
symbol_conf.use_callchain = true;
else
......
......@@ -12,6 +12,7 @@
#include "util/thread_map.h"
#include "util/stat.h"
#include "trace-event.h"
#include "util/parse-events.h"
#include <libaudit.h>
#include <stdlib.h>
......@@ -173,6 +174,10 @@ static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void
{
struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);
/* older kernel (e.g., RHEL6) use syscalls:{enter,exit} */
if (evsel == NULL)
evsel = perf_evsel__newtp("syscalls", direction);
if (evsel) {
if (perf_evsel__init_syscall_tp(evsel, handler))
goto out_delete;
......@@ -1765,8 +1770,10 @@ static int trace__process_sample(struct perf_tool *tool,
if (!trace->full_time && trace->base_time == 0)
trace->base_time = sample->time;
if (handler)
if (handler) {
++trace->nr_events;
handler(trace, evsel, sample);
}
return err;
}
......@@ -1801,10 +1808,11 @@ static int trace__record(int argc, const char **argv)
"-R",
"-m", "1024",
"-c", "1",
"-e", "raw_syscalls:sys_enter,raw_syscalls:sys_exit",
"-e",
};
rec_argc = ARRAY_SIZE(record_args) + argc;
/* +1 is for the event string below */
rec_argc = ARRAY_SIZE(record_args) + 1 + argc;
rec_argv = calloc(rec_argc + 1, sizeof(char *));
if (rec_argv == NULL)
......@@ -1813,6 +1821,17 @@ static int trace__record(int argc, const char **argv)
for (i = 0; i < ARRAY_SIZE(record_args); i++)
rec_argv[i] = record_args[i];
/* event string may be different for older kernels - e.g., RHEL6 */
if (is_valid_tracepoint("raw_syscalls:sys_enter"))
rec_argv[i] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit";
else if (is_valid_tracepoint("syscalls:sys_enter"))
rec_argv[i] = "syscalls:sys_enter,syscalls:sys_exit";
else {
pr_err("Neither raw_syscalls nor syscalls events exist.\n");
return -1;
}
i++;
for (j = 0; j < (unsigned int)argc; j++, i++)
rec_argv[i] = argv[j];
......@@ -2048,6 +2067,10 @@ static int trace__replay(struct trace *trace)
evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
"raw_syscalls:sys_enter");
/* older kernels have syscalls tp versus raw_syscalls */
if (evsel == NULL)
evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
"syscalls:sys_enter");
if (evsel == NULL) {
pr_err("Data file does not have raw_syscalls:sys_enter event\n");
goto out;
......@@ -2061,6 +2084,9 @@ static int trace__replay(struct trace *trace)
evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
"raw_syscalls:sys_exit");
if (evsel == NULL)
evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
"syscalls:sys_exit");
if (evsel == NULL) {
pr_err("Data file does not have raw_syscalls:sys_exit event\n");
goto out;
......
......@@ -36,6 +36,30 @@ ifeq ($(ARCH),arm)
LIBUNWIND_LIBS = -lunwind -lunwind-arm
endif
ifeq ($(LIBUNWIND_LIBS),)
NO_LIBUNWIND := 1
else
#
# For linking with debug library, run like:
#
# make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/
#
ifdef LIBUNWIND_DIR
LIBUNWIND_CFLAGS = -I$(LIBUNWIND_DIR)/include
LIBUNWIND_LDFLAGS = -L$(LIBUNWIND_DIR)/lib
endif
LIBUNWIND_LDFLAGS += $(LIBUNWIND_LIBS)
# Set per-feature check compilation flags
FEATURE_CHECK_CFLAGS-libunwind = $(LIBUNWIND_CFLAGS)
FEATURE_CHECK_LDFLAGS-libunwind = $(LIBUNWIND_LDFLAGS)
FEATURE_CHECK_CFLAGS-libunwind-debug-frame = $(LIBUNWIND_CFLAGS)
FEATURE_CHECK_LDFLAGS-libunwind-debug-frame = $(LIBUNWIND_LDFLAGS)
# and the flags for the test-all case
FEATURE_CHECK_CFLAGS-all += $(LIBUNWIND_CFLAGS)
FEATURE_CHECK_LDFLAGS-all += $(LIBUNWIND_LDFLAGS)
endif
ifeq ($(NO_PERF_REGS),0)
CFLAGS += -DHAVE_PERF_REGS_SUPPORT
endif
......@@ -102,7 +126,7 @@ endif
feature_check = $(eval $(feature_check_code))
define feature_check_code
feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS="$(LDFLAGS)" LIBUNWIND_LIBS="$(LIBUNWIND_LIBS)" -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 >/dev/null 2>/dev/null && echo 1 || echo 0)
endef
feature_set = $(eval $(feature_set_code))
......@@ -305,21 +329,7 @@ ifndef NO_LIBELF
endif # NO_DWARF
endif # NO_LIBELF
ifeq ($(LIBUNWIND_LIBS),)
NO_LIBUNWIND := 1
endif
ifndef NO_LIBUNWIND
#
# For linking with debug library, run like:
#
# make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/
#
ifdef LIBUNWIND_DIR
LIBUNWIND_CFLAGS := -I$(LIBUNWIND_DIR)/include
LIBUNWIND_LDFLAGS := -L$(LIBUNWIND_DIR)/lib
endif
ifneq ($(feature-libunwind), 1)
msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 1.1);
NO_LIBUNWIND := 1
......@@ -334,14 +344,12 @@ ifndef NO_LIBUNWIND
# non-ARM has no dwarf_find_debug_frame() function:
CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME
endif
endif
endif
ifndef NO_LIBUNWIND
CFLAGS += -DHAVE_LIBUNWIND_SUPPORT
EXTLIBS += $(LIBUNWIND_LIBS)
CFLAGS += $(LIBUNWIND_CFLAGS)
LDFLAGS += $(LIBUNWIND_LDFLAGS)
CFLAGS += -DHAVE_LIBUNWIND_SUPPORT
EXTLIBS += $(LIBUNWIND_LIBS)
CFLAGS += $(LIBUNWIND_CFLAGS)
LDFLAGS += $(LIBUNWIND_LDFLAGS)
endif # ifneq ($(feature-libunwind), 1)
endif
ifndef NO_LIBAUDIT
......
......@@ -32,12 +32,12 @@ CC := $(CC) -MD
all: $(FILES)
BUILD = $(CC) $(CFLAGS) $(LDFLAGS) -o $(OUTPUT)$@ $@.c
BUILD = $(CC) $(CFLAGS) -o $(OUTPUT)$@ $@.c $(LDFLAGS)
###############################
test-all:
$(BUILD) -Werror -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma $(LIBUNWIND_LIBS) -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
$(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:
$(BUILD)
......@@ -70,10 +70,10 @@ test-libnuma:
$(BUILD) -lnuma
test-libunwind:
$(BUILD) $(LIBUNWIND_LIBS) -lelf
$(BUILD) -lelf
test-libunwind-debug-frame:
$(BUILD) $(LIBUNWIND_LIBS) -lelf
$(BUILD) -lelf
test-libaudit:
$(BUILD) -laudit
......
......@@ -900,7 +900,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
* cache, or is just a kallsyms file, well, lets hope that this
* DSO is the same as when 'perf record' ran.
*/
filename = dso->long_name;
filename = (char *)dso->long_name;
snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
symbol_conf.symfs, filename);
free_filename = false;
......
......@@ -89,7 +89,7 @@ int build_id__sprintf(const u8 *build_id, int len, char *bf)
return raw - build_id;
}
char *dso__build_id_filename(struct dso *dso, char *bf, size_t size)
char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
{
char build_id_hex[BUILD_ID_SIZE * 2 + 1];
......
......@@ -10,7 +10,7 @@ extern struct perf_tool build_id__mark_dso_hit_ops;
struct dso;
int build_id__sprintf(const u8 *build_id, int len, char *bf);
char *dso__build_id_filename(struct dso *dso, char *bf, size_t size);
char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size);
int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event,
struct perf_sample *sample, struct perf_evsel *evsel,
......
......@@ -28,8 +28,8 @@ char dso__symtab_origin(const struct dso *dso)
return origin[dso->symtab_type];
}
int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
char *root_dir, char *file, size_t size)
int dso__binary_type_file(const struct dso *dso, enum dso_binary_type type,
char *root_dir, char *filename, size_t size)
{
char build_id_hex[BUILD_ID_SIZE * 2 + 1];
int ret = 0;
......@@ -38,36 +38,36 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
case DSO_BINARY_TYPE__DEBUGLINK: {
char *debuglink;
strncpy(file, dso->long_name, size);
debuglink = file + dso->long_name_len;
while (debuglink != file && *debuglink != '/')
strncpy(filename, dso->long_name, size);
debuglink = filename + dso->long_name_len;
while (debuglink != filename && *debuglink != '/')
debuglink--;
if (*debuglink == '/')
debuglink++;
filename__read_debuglink(dso->long_name, debuglink,
size - (debuglink - file));
size - (debuglink - filename));
}
break;
case DSO_BINARY_TYPE__BUILD_ID_CACHE:
/* skip the locally configured cache if a symfs is given */
if (symbol_conf.symfs[0] ||
(dso__build_id_filename(dso, file, size) == NULL))
(dso__build_id_filename(dso, filename, size) == NULL))
ret = -1;
break;
case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
snprintf(file, size, "%s/usr/lib/debug%s.debug",
snprintf(filename, size, "%s/usr/lib/debug%s.debug",
symbol_conf.symfs, dso->long_name);
break;
case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
snprintf(file, size, "%s/usr/lib/debug%s",
snprintf(filename, size, "%s/usr/lib/debug%s",
symbol_conf.symfs, dso->long_name);
break;
case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
{
char *last_slash;
const char *last_slash;
size_t len;
size_t dir_size;
......@@ -75,14 +75,14 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
while (last_slash != dso->long_name && *last_slash != '/')
last_slash--;
len = scnprintf(file, size, "%s", symbol_conf.symfs);
len = scnprintf(filename, size, "%s", symbol_conf.symfs);
dir_size = last_slash - dso->long_name + 2;
if (dir_size > (size - len)) {
ret = -1;
break;
}
len += scnprintf(file + len, dir_size, "%s", dso->long_name);
len += scnprintf(file + len , size - len, ".debug%s",
len += scnprintf(filename + len, dir_size, "%s", dso->long_name);
len += scnprintf(filename + len , size - len, ".debug%s",
last_slash);
break;
}
......@@ -96,7 +96,7 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
build_id__sprintf(dso->build_id,
sizeof(dso->build_id),
build_id_hex);
snprintf(file, size,
snprintf(filename, size,
"%s/usr/lib/debug/.build-id/%.2s/%s.debug",
symbol_conf.symfs, build_id_hex, build_id_hex + 2);
break;
......@@ -104,23 +104,23 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
case DSO_BINARY_TYPE__VMLINUX:
case DSO_BINARY_TYPE__GUEST_VMLINUX:
case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
snprintf(file, size, "%s%s",
snprintf(filename, size, "%s%s",
symbol_conf.symfs, dso->long_name);
break;
case DSO_BINARY_TYPE__GUEST_KMODULE:
snprintf(file, size, "%s%s%s", symbol_conf.symfs,
snprintf(filename, size, "%s%s%s", symbol_conf.symfs,
root_dir, dso->long_name);
break;
case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
snprintf(file, size, "%s%s", symbol_conf.symfs,
snprintf(filename, size, "%s%s", symbol_conf.symfs,
dso->long_name);
break;
case DSO_BINARY_TYPE__KCORE:
case DSO_BINARY_TYPE__GUEST_KCORE:
snprintf(file, size, "%s", dso->long_name);
snprintf(filename, size, "%s", dso->long_name);
break;
default:
......@@ -200,11 +200,10 @@ dso_cache__free(struct rb_root *root)
}
}
static struct dso_cache*
dso_cache__find(struct rb_root *root, u64 offset)
static struct dso_cache *dso_cache__find(const struct rb_root *root, u64 offset)
{
struct rb_node **p = &root->rb_node;
struct rb_node *parent = NULL;
struct rb_node * const *p = &root->rb_node;
const struct rb_node *parent = NULL;
struct dso_cache *cache;
while (*p != NULL) {
......@@ -379,32 +378,63 @@ struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
* processing we had no idea this was the kernel dso.
*/
if (dso != NULL) {
dso__set_short_name(dso, short_name);
dso__set_short_name(dso, short_name, false);
dso->kernel = dso_type;
}
return dso;
}
void dso__set_long_name(struct dso *dso, char *name)
void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated)
{
if (name == NULL)
return;
dso->long_name = name;
dso->long_name_len = strlen(name);
if (dso->long_name_allocated)
free((char *)dso->long_name);
dso->long_name = name;
dso->long_name_len = strlen(name);
dso->long_name_allocated = name_allocated;
}
void dso__set_short_name(struct dso *dso, const char *name)
void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated)
{
if (name == NULL)
return;
dso->short_name = name;
dso->short_name_len = strlen(name);
if (dso->short_name_allocated)
free((char *)dso->short_name);
dso->short_name = name;
dso->short_name_len = strlen(name);
dso->short_name_allocated = name_allocated;
}
static void dso__set_basename(struct dso *dso)
{
dso__set_short_name(dso, basename(dso->long_name));
/*
* basename() may modify path buffer, so we must pass
* a copy.
*/
char *base, *lname = strdup(dso->long_name);
if (!lname)
return;
/*
* basename() may return a pointer to internal
* storage which is reused in subsequent calls
* so copy the result.
*/
base = strdup(basename(lname));
free(lname);
if (!base)
return;
dso__set_short_name(dso, base, true);
}
int dso__name_len(const struct dso *dso)
......@@ -439,8 +469,8 @@ struct dso *dso__new(const char *name)
if (dso != NULL) {
int i;
strcpy(dso->name, name);
dso__set_long_name(dso, dso->name);
dso__set_short_name(dso, dso->name);
dso__set_long_name(dso, dso->name, false);
dso__set_short_name(dso, dso->name, false);
for (i = 0; i < MAP__NR_TYPES; ++i)
dso->symbols[i] = dso->symbol_names[i] = RB_ROOT;
dso->cache = RB_ROOT;
......@@ -465,13 +495,23 @@ void dso__delete(struct dso *dso)
int i;
for (i = 0; i < MAP__NR_TYPES; ++i)
symbols__delete(&dso->symbols[i]);
if (dso->sname_alloc)
if (dso->short_name_allocated) {
free((char *)dso->short_name);
if (dso->lname_alloc)
free(dso->long_name);
dso->short_name = NULL;
dso->short_name_allocated = false;
}
if (dso->long_name_allocated) {
free((char *)dso->long_name);
dso->long_name = NULL;
dso->long_name_allocated = false;
}
dso_cache__free(&dso->cache);
dso__free_a2l(dso);
free(dso->symsrc_filename);
dso->symsrc_filename = NULL;
free(dso);
}
......@@ -546,7 +586,7 @@ void dsos__add(struct list_head *head, struct dso *dso)
list_add_tail(&dso->node, head);
}
struct dso *dsos__find(struct list_head *head, const char *name, bool cmp_short)
struct dso *dsos__find(const struct list_head *head, const char *name, bool cmp_short)
{
struct dso *pos;
......
......@@ -89,14 +89,14 @@ struct dso {
u8 has_srcline:1;
u8 hit:1;
u8 annotate_warned:1;
u8 sname_alloc:1;
u8 lname_alloc:1;
u8 short_name_allocated:1;
u8 long_name_allocated:1;
u8 sorted_by_name;
u8 loaded;
u8 rel;
u8 build_id[BUILD_ID_SIZE];
const char *short_name;
char *long_name;
const char *long_name;
u16 long_name_len;
u16 short_name_len;
char name[0];
......@@ -110,8 +110,8 @@ static inline void dso__set_loaded(struct dso *dso, enum map_type type)
struct dso *dso__new(const char *name);
void dso__delete(struct dso *dso);
void dso__set_short_name(struct dso *dso, const char *name);
void dso__set_long_name(struct dso *dso, char *name);
void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated);
void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated);
int dso__name_len(const struct dso *dso);
......@@ -128,8 +128,8 @@ void dso__read_running_kernel_build_id(struct dso *dso,
int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir);
char dso__symtab_origin(const struct dso *dso);
int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
char *root_dir, char *file, size_t size);
int dso__binary_type_file(const struct dso *dso, enum dso_binary_type type,
char *root_dir, char *filename, size_t size);
int dso__data_fd(struct dso *dso, struct machine *machine);
ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
......@@ -143,7 +143,7 @@ struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
const char *short_name, int dso_type);
void dsos__add(struct list_head *head, struct dso *dso);
struct dso *dsos__find(struct list_head *head, const char *name,
struct dso *dsos__find(const struct list_head *head, const char *name,
bool cmp_short);
struct dso *__dsos__findnew(struct list_head *head, const char *name);
bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
......
......@@ -732,11 +732,13 @@ static long parse_pages_arg(const char *str, unsigned long min,
return -EINVAL;
}
if ((pages == 0) && (min == 0)) {
if (pages == 0 && min == 0) {
/* leave number of pages at 0 */
} else if (pages < (1UL << 31) && !is_power_of_2(pages)) {
} else if (!is_power_of_2(pages)) {
/* round pages up to next power of 2 */
pages = next_pow2(pages);
pages = next_pow2_l(pages);
if (!pages)
return -EINVAL;
pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n",
pages * page_size, pages);
}
......@@ -754,7 +756,7 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str,
unsigned long max = UINT_MAX;
long pages;
if (max < SIZE_MAX / page_size)
if (max > SIZE_MAX / page_size)
max = SIZE_MAX / page_size;
pages = parse_pages_arg(str, 1, max);
......
......@@ -177,7 +177,7 @@ perf_header__set_cmdline(int argc, const char **argv)
continue; \
else
static int write_buildid(char *name, size_t name_len, u8 *build_id,
static int write_buildid(const char *name, size_t name_len, u8 *build_id,
pid_t pid, u16 misc, int fd)
{
int err;
......@@ -209,7 +209,7 @@ static int __dsos__write_buildid_table(struct list_head *head,
dsos__for_each_with_build_id(pos, head) {
int err;
char *name;
const char *name;
size_t name_len;
if (!pos->hit)
......@@ -387,7 +387,7 @@ static int dso__cache_build_id(struct dso *dso, struct machine *machine,
{
bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
bool is_vdso = is_vdso_map(dso->short_name);
char *name = dso->long_name;
const char *name = dso->long_name;
char nm[PATH_MAX];
if (dso__is_kcore(dso)) {
......
......@@ -763,8 +763,7 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,
ret = -1;
goto out;
}
dso__set_long_name(map->dso, long_name);
map->dso->lname_alloc = 1;
dso__set_long_name(map->dso, long_name, true);
dso__kernel_module_get_build_id(map->dso, "");
}
}
......@@ -935,8 +934,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
if (name == NULL)
goto out_problem;
map->dso->short_name = name;
map->dso->sname_alloc = 1;
dso__set_short_name(map->dso, name, true);
map->end = map->start + event->mmap.len;
} else if (is_kernel_mmap) {
const char *symbol_name = (event->mmap.filename +
......
......@@ -11,6 +11,7 @@
#include "strlist.h"
#include "vdso.h"
#include "build-id.h"
#include "util.h"
#include <linux/string.h>
const char *map_type__name[MAP__NR_TYPES] = {
......@@ -252,6 +253,22 @@ size_t map__fprintf_dsoname(struct map *map, FILE *fp)
return fprintf(fp, "%s", dsoname);
}
int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
FILE *fp)
{
char *srcline;
int ret = 0;
if (map && map->dso) {
srcline = get_srcline(map->dso,
map__rip_2objdump(map, addr));
if (srcline != SRCLINE_UNKNOWN)
ret = fprintf(fp, "%s%s", prefix, srcline);
free_srcline(srcline);
}
return ret;
}
/**
* map__rip_2objdump - convert symbol start address to objdump address.
* @map: memory map
......
......@@ -103,6 +103,8 @@ struct map *map__clone(struct map *map);
int map__overlap(struct map *l, struct map *r);
size_t map__fprintf(struct map *map, FILE *fp);
size_t map__fprintf_dsoname(struct map *map, FILE *fp);
int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
FILE *fp);
int map__load(struct map *map, symbol_filter_t filter);
struct symbol *map__find_symbol(struct map *map,
......
......@@ -154,7 +154,7 @@ static struct dso *kernel_get_module_dso(const char *module)
vmlinux_name = symbol_conf.vmlinux_name;
if (vmlinux_name) {
if (dso__load_vmlinux(dso, map, vmlinux_name, NULL) <= 0)
if (dso__load_vmlinux(dso, map, vmlinux_name, false, NULL) <= 0)
return NULL;
} else {
if (dso__load_vmlinux_path(dso, map, NULL) <= 0) {
......
......@@ -1497,6 +1497,7 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
int print_dso = print_opts & PRINT_IP_OPT_DSO;
int print_symoffset = print_opts & PRINT_IP_OPT_SYMOFFSET;
int print_oneline = print_opts & PRINT_IP_OPT_ONELINE;
int print_srcline = print_opts & PRINT_IP_OPT_SRCLINE;
char s = print_oneline ? ' ' : '\t';
if (symbol_conf.use_callchain && sample->callchain) {
......@@ -1515,6 +1516,8 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
node_al = *al;
while (stack_depth) {
u64 addr = 0;
node = callchain_cursor_current(&callchain_cursor);
if (!node)
break;
......@@ -1525,10 +1528,13 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
if (print_ip)
printf("%c%16" PRIx64, s, node->ip);
if (node->map)
addr = node->map->map_ip(node->map, node->ip);
if (print_sym) {
printf(" ");
if (print_symoffset) {
node_al.addr = node->ip;
node_al.addr = addr;
node_al.map = node->map;
symbol__fprintf_symname_offs(node->sym, &node_al, stdout);
} else
......@@ -1541,6 +1547,10 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
printf(")");
}
if (print_srcline)
map__fprintf_srcline(node->map, addr, "\n ",
stdout);
if (!print_oneline)
printf("\n");
......@@ -1570,6 +1580,9 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
map__fprintf_dsoname(al->map, stdout);
printf(")");
}
if (print_srcline)
map__fprintf_srcline(al->map, al->addr, "\n ", stdout);
}
}
......
......@@ -45,6 +45,7 @@ struct perf_session {
#define PRINT_IP_OPT_DSO (1<<2)
#define PRINT_IP_OPT_SYMOFFSET (1<<3)
#define PRINT_IP_OPT_ONELINE (1<<4)
#define PRINT_IP_OPT_SRCLINE (1<<5)
struct perf_tool;
......
......@@ -255,7 +255,7 @@ char *get_srcline(struct dso *dso, unsigned long addr)
char *file = NULL;
unsigned line = 0;
char *srcline;
char *dso_name;
const char *dso_name;
if (!dso->has_srcline)
return SRCLINE_UNKNOWN;
......
......@@ -1159,7 +1159,7 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
dso->data_type = DSO_BINARY_TYPE__GUEST_KCORE;
else
dso->data_type = DSO_BINARY_TYPE__KCORE;
dso__set_long_name(dso, strdup(kcore_filename));
dso__set_long_name(dso, strdup(kcore_filename), true);
close(fd);
......@@ -1408,7 +1408,8 @@ struct map *map_groups__find_by_name(struct map_groups *mg,
}
int dso__load_vmlinux(struct dso *dso, struct map *map,
const char *vmlinux, symbol_filter_t filter)
const char *vmlinux, bool vmlinux_allocated,
symbol_filter_t filter)
{
int err = -1;
struct symsrc ss;
......@@ -1437,7 +1438,7 @@ int dso__load_vmlinux(struct dso *dso, struct map *map,
dso->data_type = DSO_BINARY_TYPE__GUEST_VMLINUX;
else
dso->data_type = DSO_BINARY_TYPE__VMLINUX;
dso__set_long_name(dso, (char *)vmlinux);
dso__set_long_name(dso, vmlinux, vmlinux_allocated);
dso__set_loaded(dso, map->type);
pr_debug("Using %s for symbols\n", symfs_vmlinux);
}
......@@ -1456,21 +1457,16 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,
filename = dso__build_id_filename(dso, NULL, 0);
if (filename != NULL) {
err = dso__load_vmlinux(dso, map, filename, filter);
if (err > 0) {
dso->lname_alloc = 1;
err = dso__load_vmlinux(dso, map, filename, true, filter);
if (err > 0)
goto out;
}
free(filename);
}
for (i = 0; i < vmlinux_path__nr_entries; ++i) {
err = dso__load_vmlinux(dso, map, vmlinux_path[i], filter);
if (err > 0) {
dso__set_long_name(dso, strdup(vmlinux_path[i]));
dso->lname_alloc = 1;
err = dso__load_vmlinux(dso, map, vmlinux_path[i], false, filter);
if (err > 0)
break;
}
}
out:
return err;
......@@ -1607,15 +1603,8 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
}
if (!symbol_conf.ignore_vmlinux && symbol_conf.vmlinux_name != NULL) {
err = dso__load_vmlinux(dso, map,
symbol_conf.vmlinux_name, filter);
if (err > 0) {
dso__set_long_name(dso,
strdup(symbol_conf.vmlinux_name));
dso->lname_alloc = 1;
return err;
}
return err;
return dso__load_vmlinux(dso, map, symbol_conf.vmlinux_name,
false, filter);
}
if (!symbol_conf.ignore_vmlinux && vmlinux_path != NULL) {
......@@ -1641,7 +1630,7 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
free(kallsyms_allocated_filename);
if (err > 0 && !dso__is_kcore(dso)) {
dso__set_long_name(dso, strdup("[kernel.kallsyms]"));
dso__set_long_name(dso, "[kernel.kallsyms]", false);
map__fixup_start(map);
map__fixup_end(map);
}
......@@ -1671,7 +1660,8 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
*/
if (symbol_conf.default_guest_vmlinux_name != NULL) {
err = dso__load_vmlinux(dso, map,
symbol_conf.default_guest_vmlinux_name, filter);
symbol_conf.default_guest_vmlinux_name,
false, filter);
return err;
}
......@@ -1688,7 +1678,7 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
pr_debug("Using %s for symbols\n", kallsyms_filename);
if (err > 0 && !dso__is_kcore(dso)) {
machine__mmap_name(machine, path, sizeof(path));
dso__set_long_name(dso, strdup(path));
dso__set_long_name(dso, strdup(path), true);
map__fixup_start(map);
map__fixup_end(map);
}
......
......@@ -206,7 +206,8 @@ bool symsrc__possibly_runtime(struct symsrc *ss);
int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter);
int dso__load_vmlinux(struct dso *dso, struct map *map,
const char *vmlinux, symbol_filter_t filter);
const char *vmlinux, bool vmlinux_allocated,
symbol_filter_t filter);
int dso__load_vmlinux_path(struct dso *dso, struct map *map,
symbol_filter_t filter);
int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map,
......
......@@ -482,3 +482,17 @@ int filename__read_str(const char *filename, char **buf, size_t *sizep)
close(fd);
return err;
}
const char *get_filename_for_perf_kvm(void)
{
const char *filename;
if (perf_host && !perf_guest)
filename = strdup("perf.data.host");
else if (!perf_host && perf_guest)
filename = strdup("perf.data.guest");
else
filename = strdup("perf.data.kvm");
return filename;
}
......@@ -73,6 +73,7 @@
#include <sys/ttydefaults.h>
#include <lk/debugfs.h>
#include <termios.h>
#include <linux/bitops.h>
extern const char *graph_line;
extern const char *graph_dotted_line;
......@@ -281,6 +282,17 @@ static inline unsigned next_pow2(unsigned x)
return 1ULL << (32 - __builtin_clz(x - 1));
}
static inline unsigned long next_pow2_l(unsigned long x)
{
#if BITS_PER_LONG == 64
if (x <= (1UL << 31))
return next_pow2(x);
return (unsigned long)next_pow2(x >> 32) << 32;
#else
return next_pow2(x);
#endif
}
size_t hex_width(u64 v);
int hex2u64(const char *ptr, u64 *val);
......@@ -309,4 +321,6 @@ void free_srcline(char *srcline);
int filename__read_int(const char *filename, int *value);
int filename__read_str(const char *filename, char **buf, size_t *sizep);
const char *get_filename_for_perf_kvm(void);
#endif /* GIT_COMPAT_UTIL_H */
......@@ -103,7 +103,7 @@ struct dso *vdso__dso_findnew(struct list_head *head)
dso = dso__new(VDSO__MAP_NAME);
if (dso != NULL) {
dsos__add(head, dso);
dso__set_long_name(dso, file);
dso__set_long_name(dso, file, false);
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册