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