diff options
author | Steven Rostedt <srostedt@redhat.com> | 2010-05-21 19:49:57 +0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2010-05-21 19:49:57 +0400 |
commit | ff5f149b6aec8edbfa3698721667acd043009a33 (patch) | |
tree | d052553eb296dfee3f01b1cb2b717cb7ccf3127a /tools/perf | |
parent | f0218b3e9974f06014b61be8987159f4a20e011e (diff) | |
parent | 580d607cd666dfabfc1c7b0fb08c8ac690c7c87f (diff) | |
download | linux-ff5f149b6aec8edbfa3698721667acd043009a33.tar.xz |
Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip into trace/tip/tracing/core-7
Conflicts:
include/linux/ftrace_event.h
include/trace/ftrace.h
kernel/trace/trace_event_perf.c
kernel/trace/trace_kprobe.c
kernel/trace/trace_syscalls.c
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'tools/perf')
54 files changed, 479 insertions, 2176 deletions
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt index 2cab8e8c33d0..909fa766fa1c 100644 --- a/tools/perf/Documentation/perf-stat.txt +++ b/tools/perf/Documentation/perf-stat.txt @@ -43,6 +43,9 @@ OPTIONS -c:: scale counter values +-B:: + print large numbers with thousands' separators according to locale + EXAMPLES -------- diff --git a/tools/perf/Makefile b/tools/perf/Makefile index a9281cca4114..3d8f31ed771d 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -558,15 +558,19 @@ else endif # PERF_HAVE_DWARF_REGS endif # NO_DWARF +ifdef NO_NEWT + BASIC_CFLAGS += -DNO_NEWT_SUPPORT +else ifneq ($(shell sh -c "(echo '\#include <newt.h>'; echo 'int main(void) { newtInit(); newtCls(); return newtFinished(); }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -lnewt -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) msg := $(warning newt not found, disables TUI support. Please install newt-devel or libnewt-dev); BASIC_CFLAGS += -DNO_NEWT_SUPPORT else # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h BASIC_CFLAGS += -I/usr/include/slang - EXTLIBS += -lnewt + EXTLIBS += -lnewt -lslang LIB_OBJS += $(OUTPUT)util/newt.o endif +endif # NO_NEWT ifndef NO_LIBPERL PERL_EMBED_LDOPTS = `perl -MExtUtils::Embed -e ldopts 2>/dev/null` diff --git a/tools/perf/bench/sched-messaging.c b/tools/perf/bench/sched-messaging.c index da1b2e9f01ff..d1d1b30f99c1 100644 --- a/tools/perf/bench/sched-messaging.c +++ b/tools/perf/bench/sched-messaging.c @@ -256,10 +256,8 @@ static const struct option options[] = { "Use pipe() instead of socketpair()"), OPT_BOOLEAN('t', "thread", &thread_mode, "Be multi thread instead of multi process"), - OPT_INTEGER('g', "group", &num_groups, - "Specify number of groups"), - OPT_INTEGER('l', "loop", &loops, - "Specify number of loops"), + OPT_UINTEGER('g', "group", &num_groups, "Specify number of groups"), + OPT_UINTEGER('l', "loop", &loops, "Specify number of loops"), OPT_END() }; diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c index 46996774e559..fcb96269852a 100644 --- a/tools/perf/builtin-bench.c +++ b/tools/perf/builtin-bench.c @@ -95,7 +95,7 @@ static void dump_suites(int subsys_index) return; } -static char *bench_format_str; +static const char *bench_format_str; int bench_format = BENCH_FORMAT_DEFAULT; static const struct option bench_options[] = { @@ -126,7 +126,7 @@ static void print_usage(void) printf("\n"); } -static int bench_str2int(char *str) +static int bench_str2int(const char *str) { if (!str) return BENCH_FORMAT_DEFAULT; diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c index 81e3ecc40fc7..6d5a8a7faf48 100644 --- a/tools/perf/builtin-help.c +++ b/tools/perf/builtin-help.c @@ -33,10 +33,10 @@ static bool show_all = false; static enum help_format help_format = HELP_FORMAT_MAN; static struct option builtin_help_options[] = { OPT_BOOLEAN('a', "all", &show_all, "print all available commands"), - OPT_SET_INT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN), - OPT_SET_INT('w', "web", &help_format, "show manual in web browser", + OPT_SET_UINT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN), + OPT_SET_UINT('w', "web", &help_format, "show manual in web browser", HELP_FORMAT_WEB), - OPT_SET_INT('i', "info", &help_format, "show info page", + OPT_SET_UINT('i', "info", &help_format, "show info page", HELP_FORMAT_INFO), OPT_END(), }; diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index a4c7cae45024..34d1e853829d 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -19,11 +19,11 @@ #include <pthread.h> #include <math.h> -static char *file_name; +static const char *file_name; static char name_buffer[256]; -int perf_host = 1; -int perf_guest; +bool perf_host = 1; +bool perf_guest; static const char * const kvm_usage[] = { "perf kvm [<options>] {top|record|report|diff|buildid-list}", diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index e18dfdc2948a..821c1586a22b 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -792,8 +792,7 @@ static void print_result(void) print_bad_events(bad, total); } -static int info_threads; -static int info_map; +static bool info_threads, info_map; static void dump_threads(void) { diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 61c6d70732c9..e4a4da32a568 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -65,8 +65,10 @@ static int parse_probe_event(const char *str) int ret; pr_debug("probe-definition(%d): %s\n", params.nevents, str); - if (++params.nevents == MAX_PROBES) - die("Too many probes (> %d) are specified.", MAX_PROBES); + if (++params.nevents == MAX_PROBES) { + pr_err("Too many probes (> %d) were specified.", MAX_PROBES); + return -1; + } /* Parse a perf-probe command into event */ ret = parse_perf_probe_command(str, pev); @@ -84,7 +86,9 @@ static int parse_probe_event_argv(int argc, const char **argv) len = 0; for (i = 0; i < argc; i++) len += strlen(argv[i]) + 1; - buf = xzalloc(len + 1); + buf = zalloc(len + 1); + if (buf == NULL) + return -ENOMEM; len = 0; for (i = 0; i < argc; i++) len += sprintf(&buf[len], "%s ", argv[i]); diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 0f467cf7aa72..9bc89050e6f8 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -25,6 +25,7 @@ #include <unistd.h> #include <sched.h> +#include <sys/mman.h> enum write_mode_t { WRITE_FORCE, @@ -33,8 +34,8 @@ enum write_mode_t { static int *fd[MAX_NR_CPUS][MAX_COUNTERS]; -static unsigned int user_interval = UINT_MAX; -static long default_interval = 0; +static u64 user_interval = ULLONG_MAX; +static u64 default_interval = 0; static int nr_cpus = 0; static unsigned int page_size; @@ -45,7 +46,7 @@ static int output; static int pipe_output = 0; static const char *output_name = "perf.data"; static int group = 0; -static unsigned int realtime_prio = 0; +static int realtime_prio = 0; static bool raw_samples = false; static bool system_wide = false; static int profile_cpu = -1; @@ -60,13 +61,8 @@ static bool call_graph = false; static bool inherit_stat = false; static bool no_samples = false; static bool sample_address = false; -static bool multiplex = false; -static int multiplex_fd = -1; static long samples = 0; -static struct timeval last_read; -static struct timeval this_read; - static u64 bytes_written = 0; static struct pollfd *event_array; @@ -86,7 +82,7 @@ struct mmap_data { unsigned int prev; }; -static struct mmap_data *mmap_array[MAX_NR_CPUS][MAX_COUNTERS]; +static struct mmap_data mmap_array[MAX_NR_CPUS]; static unsigned long mmap_read_head(struct mmap_data *md) { @@ -146,8 +142,6 @@ static void mmap_read(struct mmap_data *md) void *buf; int diff; - gettimeofday(&this_read, NULL); - /* * If we're further behind than half the buffer, there's a chance * the writer will bite our tail and mess up the samples under us. @@ -158,23 +152,13 @@ static void mmap_read(struct mmap_data *md) */ diff = head - old; if (diff < 0) { - struct timeval iv; - unsigned long msecs; - - timersub(&this_read, &last_read, &iv); - msecs = iv.tv_sec*1000 + iv.tv_usec/1000; - - fprintf(stderr, "WARNING: failed to keep up with mmap data." - " Last read %lu msecs ago.\n", msecs); - + fprintf(stderr, "WARNING: failed to keep up with mmap data\n"); /* * head points to a known good entry, start there. */ old = head; } - last_read = this_read; - if (old != head) samples++; @@ -268,7 +252,7 @@ static void create_counter(int counter, int cpu) * it a weak assumption overridable by the user. */ if (!attr->sample_period || (user_freq != UINT_MAX && - user_interval != UINT_MAX)) { + user_interval != ULLONG_MAX)) { if (freq) { attr->sample_type |= PERF_SAMPLE_PERIOD; attr->freq = 1; @@ -380,27 +364,30 @@ try_again: */ if (group && group_fd == -1) group_fd = fd[nr_cpu][counter][thread_index]; - if (multiplex && multiplex_fd == -1) - multiplex_fd = fd[nr_cpu][counter][thread_index]; - if (multiplex && fd[nr_cpu][counter][thread_index] != multiplex_fd) { - - ret = ioctl(fd[nr_cpu][counter][thread_index], PERF_EVENT_IOC_SET_OUTPUT, multiplex_fd); - assert(ret != -1); + if (counter || thread_index) { + ret = ioctl(fd[nr_cpu][counter][thread_index], + PERF_EVENT_IOC_SET_OUTPUT, + fd[nr_cpu][0][0]); + if (ret) { + error("failed to set output: %d (%s)\n", errno, + strerror(errno)); + exit(-1); + } } else { - event_array[nr_poll].fd = fd[nr_cpu][counter][thread_index]; - event_array[nr_poll].events = POLLIN; - nr_poll++; - - mmap_array[nr_cpu][counter][thread_index].counter = counter; - mmap_array[nr_cpu][counter][thread_index].prev = 0; - mmap_array[nr_cpu][counter][thread_index].mask = mmap_pages*page_size - 1; - mmap_array[nr_cpu][counter][thread_index].base = mmap(NULL, (mmap_pages+1)*page_size, + mmap_array[nr_cpu].counter = counter; + mmap_array[nr_cpu].prev = 0; + mmap_array[nr_cpu].mask = mmap_pages*page_size - 1; + mmap_array[nr_cpu].base = mmap(NULL, (mmap_pages+1)*page_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd[nr_cpu][counter][thread_index], 0); - if (mmap_array[nr_cpu][counter][thread_index].base == MAP_FAILED) { + if (mmap_array[nr_cpu].base == MAP_FAILED) { error("failed to mmap with %d (%s)\n", errno, strerror(errno)); exit(-1); } + + event_array[nr_poll].fd = fd[nr_cpu][counter][thread_index]; + event_array[nr_poll].events = POLLIN; + nr_poll++; } if (filter != NULL) { @@ -501,16 +488,11 @@ static struct perf_event_header finished_round_event = { static void mmap_read_all(void) { - int i, counter, thread; + int i; for (i = 0; i < nr_cpu; i++) { - for (counter = 0; counter < nr_counters; counter++) { - for (thread = 0; thread < thread_num; thread++) { - if (mmap_array[i][counter][thread].base) - mmap_read(&mmap_array[i][counter][thread]); - } - - } + if (mmap_array[i].base) + mmap_read(&mmap_array[i]); } if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO)) @@ -817,16 +799,13 @@ static const struct option options[] = { "CPU to profile on"), OPT_BOOLEAN('f', "force", &force, "overwrite existing data file (deprecated)"), - OPT_LONG('c', "count", &user_interval, - "event period to sample"), + OPT_U64('c', "count", &user_interval, "event period to sample"), OPT_STRING('o', "output", &output_name, "file", "output file name"), OPT_BOOLEAN('i', "no-inherit", &no_inherit, "child tasks do not inherit counters"), - OPT_INTEGER('F', "freq", &user_freq, - "profile at this frequency"), - OPT_INTEGER('m', "mmap-pages", &mmap_pages, - "number of mmap data pages"), + OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"), + OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"), OPT_BOOLEAN('g', "call-graph", &call_graph, "do call-graph (stack chain/backtrace) recording"), OPT_INCR('v', "verbose", &verbose, @@ -837,8 +816,6 @@ static const struct option options[] = { "Sample addresses"), OPT_BOOLEAN('n', "no-samples", &no_samples, "don't sample"), - OPT_BOOLEAN('M', "multiplex", &multiplex, - "multiplex counter output in a single channel"), OPT_END() }; @@ -890,9 +867,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used) for (i = 0; i < MAX_NR_CPUS; i++) { for (j = 0; j < MAX_COUNTERS; j++) { fd[i][j] = malloc(sizeof(int)*thread_num); - mmap_array[i][j] = zalloc( - sizeof(struct mmap_data)*thread_num); - if (!fd[i][j] || !mmap_array[i][j]) + if (!fd[i][j]) return -ENOMEM; } } @@ -901,7 +876,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used) if (!event_array) return -ENOMEM; - if (user_interval != UINT_MAX) + if (user_interval != ULLONG_MAX) default_interval = user_interval; if (user_freq != UINT_MAX) freq = user_freq; diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 68265120ee07..a7b8760e401c 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -39,8 +39,8 @@ static bool dont_use_callchains; static bool show_threads; static struct perf_read_values show_threads_values; -static char default_pretty_printing_style[] = "normal"; -static char *pretty_printing_style = default_pretty_printing_style; +static const char default_pretty_printing_style[] = "normal"; +static const char *pretty_printing_style = default_pretty_printing_style; static char callchain_default_opt[] = "fractal,0.5"; @@ -116,7 +116,7 @@ static int perf_session__add_hist_entry(struct perf_session *self, * so we don't allocated the extra space needed because the stdio * code will not use it. */ - if (use_browser) + if (use_browser > 0) err = hist_entry__inc_addr_samples(he, al->addr); out_free_syms: free(syms); @@ -330,7 +330,7 @@ static int __cmd_report(void) hists = rb_entry(next, struct hists, rb_node); hists__collapse_resort(hists); hists__output_resort(hists); - if (use_browser) + if (use_browser > 0) hists__browse(hists, help, input_name); else { const char *evname = NULL; @@ -347,7 +347,7 @@ static int __cmd_report(void) next = rb_next(&hists->rb_node); } - if (!use_browser && sort_order == default_sort_order && + if (use_browser <= 0 && sort_order == default_sort_order && parent_pattern == default_parent_pattern) { fprintf(stdout, "#\n# (%s)\n#\n", help); @@ -491,7 +491,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __used) * so don't allocate extra space that won't be used in the stdio * implementation. */ - if (use_browser) + if (use_browser > 0) symbol_conf.priv_size = sizeof(struct sym_priv); if (symbol__init() < 0) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index be7bc9264710..f67bce2a83b4 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -22,7 +22,7 @@ static char const *input_name = "perf.data"; static char default_sort_order[] = "avg, max, switch, runtime"; -static char *sort_order = default_sort_order; +static const char *sort_order = default_sort_order; static int profile_cpu = -1; @@ -105,7 +105,7 @@ static u64 sum_runtime; static u64 sum_fluct; static u64 run_avg; -static unsigned long replay_repeat = 10; +static unsigned int replay_repeat = 10; static unsigned long nr_timestamps; static unsigned long nr_unordered_timestamps; static unsigned long nr_state_machine_bugs; @@ -1816,8 +1816,8 @@ static const char * const replay_usage[] = { }; static const struct option replay_options[] = { - OPT_INTEGER('r', "repeat", &replay_repeat, - "repeat the workload replay N times (-1: infinite)"), + OPT_UINTEGER('r', "repeat", &replay_repeat, + "repeat the workload replay N times (-1: infinite)"), OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"), OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index ff8c413b7e73..9a39ca3c3ac4 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -50,6 +50,7 @@ #include <sys/prctl.h> #include <math.h> +#include <locale.h> static struct perf_event_attr default_attrs[] = { @@ -80,6 +81,8 @@ static pid_t *all_tids = NULL; static int thread_num = 0; static pid_t child_pid = -1; static bool null_run = false; +static bool big_num = false; + static int *fd[MAX_NR_CPUS][MAX_COUNTERS]; @@ -377,7 +380,7 @@ static void nsec_printout(int counter, double avg) { double msecs = avg / 1e6; - fprintf(stderr, " %14.6f %-24s", msecs, event_name(counter)); + fprintf(stderr, " %18.6f %-24s", msecs, event_name(counter)); if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) { fprintf(stderr, " # %10.3f CPUs ", @@ -389,7 +392,10 @@ static void abs_printout(int counter, double avg) { double total, ratio = 0.0; - fprintf(stderr, " %14.0f %-24s", avg, event_name(counter)); + if (big_num) + fprintf(stderr, " %'18.0f %-24s", avg, event_name(counter)); + else + fprintf(stderr, " %18.0f %-24s", avg, event_name(counter)); if (MATCH_EVENT(HARDWARE, HW_INSTRUCTIONS, counter)) { total = avg_stats(&runtime_cycles_stats); @@ -426,7 +432,7 @@ static void print_counter(int counter) int scaled = event_scaled[counter]; if (scaled == -1) { - fprintf(stderr, " %14s %-24s\n", + fprintf(stderr, " %18s %-24s\n", "<not counted>", event_name(counter)); return; } @@ -477,7 +483,7 @@ static void print_stat(int argc, const char **argv) print_counter(counter); fprintf(stderr, "\n"); - fprintf(stderr, " %14.9f seconds time elapsed", + fprintf(stderr, " %18.9f seconds time elapsed", avg_stats(&walltime_nsecs_stats)/1e9); if (run_count > 1) { fprintf(stderr, " ( +- %7.3f%% )", @@ -534,6 +540,8 @@ static const struct option options[] = { "repeat command and print average + stddev (max: 100)"), OPT_BOOLEAN('n', "null", &null_run, "null run - dont start any counters"), + OPT_BOOLEAN('B', "big-num", &big_num, + "print large numbers with thousands\' separators"), OPT_END() }; @@ -542,6 +550,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used) int status; int i,j; + setlocale(LC_ALL, ""); + argc = parse_options(argc, argv, options, stat_usage, PARSE_OPT_STOP_AT_NON_OPTION); if (!argc && target_pid == -1 && target_tid == -1) diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index 0339612e7385..035b9fa063a9 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c @@ -257,7 +257,7 @@ static const char * const test_usage[] = { }; static const struct option test_options[] = { - OPT_BOOLEAN('v', "verbose", &verbose, + OPT_INTEGER('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"), OPT_END() }; diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index ed9b5b6905fa..397290a0a76e 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -71,7 +71,7 @@ static int thread_num = 0; static bool inherit = false; static int profile_cpu = -1; static int nr_cpus = 0; -static unsigned int realtime_prio = 0; +static int realtime_prio = 0; static bool group = false; static unsigned int page_size; static unsigned int mmap_pages = 16; @@ -96,7 +96,7 @@ struct source_line { struct source_line *next; }; -static char *sym_filter = NULL; +static const char *sym_filter = NULL; struct sym_entry *sym_filter_entry = NULL; struct sym_entry *sym_filter_entry_sched = NULL; static int sym_pcnt_filter = 5; @@ -1357,8 +1357,7 @@ static const struct option options[] = { "file", "vmlinux pathname"), OPT_BOOLEAN('K', "hide_kernel_symbols", &hide_kernel_symbols, "hide kernel symbols"), - OPT_INTEGER('m', "mmap-pages", &mmap_pages, - "number of mmap data pages"), + OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"), OPT_INTEGER('r', "realtime", &realtime_prio, "collect data with this RT SCHED_FIFO priority"), OPT_INTEGER('d', "delay", &delay_secs, diff --git a/tools/perf/perf.c b/tools/perf/perf.c index 08e0e5d2b50e..6e4871191138 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c @@ -15,15 +15,15 @@ #include "util/parse-events.h" #include "util/debugfs.h" -bool use_browser; - const char perf_usage_string[] = "perf [--version] [--help] COMMAND [ARGS]"; const char perf_more_info_string[] = "See 'perf help COMMAND' for more information on a specific command."; +int use_browser = -1; static int use_pager = -1; + struct pager_config { const char *cmd; int val; @@ -49,6 +49,24 @@ int check_pager_config(const char *cmd) return c.val; } +static int tui_command_config(const char *var, const char *value, void *data) +{ + struct pager_config *c = data; + if (!prefixcmp(var, "tui.") && !strcmp(var + 4, c->cmd)) + c->val = perf_config_bool(var, value); + return 0; +} + +/* returns 0 for "no tui", 1 for "use tui", and -1 for "not specified" */ +static int check_tui_config(const char *cmd) +{ + struct pager_config c; + c.cmd = cmd; + c.val = -1; + perf_config(tui_command_config, &c); + return c.val; +} + static void commit_pager_choice(void) { switch (use_pager) { @@ -255,6 +273,9 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) if (p->option & RUN_SETUP) prefix = NULL; /* setup_perf_directory(); */ + if (use_browser == -1) + use_browser = check_tui_config(p->cmd); + if (use_pager == -1 && p->option & RUN_SETUP) use_pager = check_pager_config(p->cmd); if (use_pager == -1 && p->option & USE_PAGER) diff --git a/tools/perf/perf.h b/tools/perf/perf.h index 02821febb704..ef7aa0a0c526 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -80,6 +80,7 @@ void get_term_dimensions(struct winsize *ws); #include "../../include/linux/perf_event.h" #include "util/types.h" +#include <stdbool.h> /* * prctl(PR_TASK_PERF_EVENTS_DISABLE) will (cheaply) disable all @@ -131,6 +132,6 @@ struct ip_callchain { u64 ips[0]; }; -extern int perf_host, perf_guest; +extern bool perf_host, perf_guest; #endif diff --git a/tools/perf/util/abspath.c b/tools/perf/util/abspath.c index a791dd467261..0e76affe9c36 100644 --- a/tools/perf/util/abspath.c +++ b/tools/perf/util/abspath.c @@ -1,86 +1,5 @@ #include "cache.h" -/* - * Do not use this for inspecting *tracked* content. When path is a - * symlink to a directory, we do not want to say it is a directory when - * dealing with tracked content in the working tree. - */ -static int is_directory(const char *path) -{ - struct stat st; - return (!stat(path, &st) && S_ISDIR(st.st_mode)); -} - -/* We allow "recursive" symbolic links. Only within reason, though. */ -#define MAXDEPTH 5 - -const char *make_absolute_path(const char *path) -{ - static char bufs[2][PATH_MAX + 1], *buf = bufs[0], *next_buf = bufs[1]; - char cwd[1024] = ""; - int buf_index = 1, len; - - int depth = MAXDEPTH; - char *last_elem = NULL; - struct stat st; - - if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX) - die ("Too long path: %.*s", 60, path); - - while (depth--) { - if (!is_directory(buf)) { - char *last_slash = strrchr(buf, '/'); - if (last_slash) { - *last_slash = '\0'; - last_elem = xstrdup(last_slash + 1); - } else { - last_elem = xstrdup(buf); - *buf = '\0'; - } - } - - if (*buf) { - if (!*cwd && !getcwd(cwd, sizeof(cwd))) - die ("Could not get current working directory"); - - if (chdir(buf)) - die ("Could not switch to '%s'", buf); - } - if (!getcwd(buf, PATH_MAX)) - die ("Could not get current working directory"); - - if (last_elem) { - len = strlen(buf); - - if (len + strlen(last_elem) + 2 > PATH_MAX) - die ("Too long path name: '%s/%s'", - buf, last_elem); - buf[len] = '/'; - strcpy(buf + len + 1, last_elem); - free(last_elem); - last_elem = NULL; - } - - if (!lstat(buf, &st) && S_ISLNK(st.st_mode)) { - len = readlink(buf, next_buf, PATH_MAX); - if (len < 0) - die ("Invalid symlink: %s", buf); - if (PATH_MAX <= len) - die("symbolic link too long: %s", buf); - next_buf[len] = '\0'; - buf = next_buf; - buf_index = 1 - buf_index; - next_buf = bufs[buf_index]; - } else - break; - } - - if (*cwd && chdir(cwd)) - die ("Could not change back to '%s'", cwd); - - return buf; -} - static const char *get_pwd_cwd(void) { static char cwd[PATH_MAX + 1]; diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index 0f60a3906808..70c5cf87d020 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c @@ -6,6 +6,8 @@ * Copyright (C) 2009, 2010 Red Hat Inc. * Copyright (C) 2009, 2010 Arnaldo Carvalho de Melo <acme@redhat.com> */ +#include "util.h" +#include <stdio.h> #include "build-id.h" #include "event.h" #include "symbol.h" @@ -37,3 +39,23 @@ struct perf_event_ops build_id__mark_dso_hit_ops = { .mmap = event__process_mmap, .fork = event__process_task, }; + +char *dso__build_id_filename(struct dso *self, char *bf, size_t size) +{ + char build_id_hex[BUILD_ID_SIZE * 2 + 1]; + const char *home; + + if (!self->has_build_id) + return NULL; + + build_id__sprintf(self->build_id, sizeof(self->build_id), build_id_hex); + home = getenv("HOME"); + if (bf == NULL) { + if (asprintf(&bf, "%s/%s/.build-id/%.2s/%s", home, + DEBUG_CACHE_DIR, build_id_hex, build_id_hex + 2) < 0) + return NULL; + } else + snprintf(bf, size, "%s/%s/.build-id/%.2s/%s", home, + DEBUG_CACHE_DIR, build_id_hex, build_id_hex + 2); + return bf; +} diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h index 1d981d63cf9a..5dafb00eaa06 100644 --- a/tools/perf/util/build-id.h +++ b/tools/perf/util/build-id.h @@ -5,4 +5,6 @@ extern struct perf_event_ops build_id__mark_dso_hit_ops; +char *dso__build_id_filename(struct dso *self, char *bf, size_t size); + #endif diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h index 4b9aab7f0405..65fe664fddf6 100644 --- a/tools/perf/util/cache.h +++ b/tools/perf/util/cache.h @@ -13,56 +13,16 @@ #define PERF_DIR_ENVIRONMENT "PERF_DIR" #define PERF_WORK_TREE_ENVIRONMENT "PERF_WORK_TREE" -#define DEFAULT_PERF_DIR_ENVIRONMENT ".perf" -#define DB_ENVIRONMENT "PERF_OBJECT_DIRECTORY" -#define INDEX_ENVIRONMENT "PERF_INDEX_FILE" -#define GRAFT_ENVIRONMENT "PERF_GRAFT_FILE" -#define TEMPLATE_DIR_ENVIRONMENT "PERF_TEMPLATE_DIR" -#define CONFIG_ENVIRONMENT "PERF_CONFIG" #define EXEC_PATH_ENVIRONMENT "PERF_EXEC_PATH" -#define CEILING_DIRECTORIES_ENVIRONMENT "PERF_CEILING_DIRECTORIES" -#define PERFATTRIBUTES_FILE ".perfattributes" -#define INFOATTRIBUTES_FILE "info/attributes" -#define ATTRIBUTE_MACRO_PREFIX "[attr]" +#define DEFAULT_PERF_DIR_ENVIRONMENT ".perf" #define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR" typedef int (*config_fn_t)(const char *, const char *, void *); extern int perf_default_config(const char *, const char *, void *); -extern int perf_config_from_file(config_fn_t fn, const char *, void *); extern int perf_config(config_fn_t fn, void *); -extern int perf_parse_ulong(const char *, unsigned long *); extern int perf_config_int(const char *, const char *); -extern unsigned long perf_config_ulong(const char *, const char *); -extern int perf_config_bool_or_int(const char *, const char *, int *); extern int perf_config_bool(const char *, const char *); -extern int perf_config_string(const char **, const char *, const char *); -extern int perf_config_set(const char *, const char *); -extern int perf_config_set_multivar(const char *, const char *, const char *, int); -extern int perf_config_rename_section(const char *, const char *); -extern const char *perf_etc_perfconfig(void); -extern int check_repository_format_version(const char *var, const char *value, void *cb); -extern int perf_config_system(void); -extern int perf_config_global(void); extern int config_error_nonbool(const char *); -extern const char *config_exclusive_filename; - -#define MAX_PERFNAME (1000) -extern char perf_default_email[MAX_PERFNAME]; -extern char perf_default_name[MAX_PERFNAME]; -extern int user_ident_explicitly_given; - -extern const char *perf_log_output_encoding; -extern const char *perf_mailmap_file; - -/* IO helper functions */ -extern void maybe_flush_or_die(FILE *, const char *); -extern int copy_fd(int ifd, int ofd); -extern int copy_file(const char *dst, const char *src, int mode); -extern ssize_t write_in_full(int fd, const void *buf, size_t count); -extern void write_or_die(int fd, const void *buf, size_t count); -extern int write_or_whine(int fd, const void *buf, size_t count, const char *msg); -extern int write_or_whine_pipe(int fd, const void *buf, size_t count, const char *msg); -extern void fsync_or_die(int fd, const char *); /* pager.c */ extern void setup_pager(void); @@ -70,7 +30,7 @@ extern const char *pager_program; extern int pager_in_use(void); extern int pager_use_color; -extern bool use_browser; +extern int use_browser; #ifdef NO_NEWT_SUPPORT static inline void setup_browser(void) @@ -83,9 +43,6 @@ void setup_browser(void); void exit_browser(bool wait_for_ok); #endif -extern const char *editor_program; -extern const char *excludes_file; - char *alias_lookup(const char *alias); int split_cmdline(char *cmdline, const char ***argv); @@ -115,22 +72,12 @@ static inline int is_absolute_path(const char *path) return path[0] == '/'; } -const char *make_absolute_path(const char *path); const char *make_nonrelative_path(const char *path); -const char *make_relative_path(const char *abs, const char *base); -int normalize_path_copy(char *dst, const char *src); -int longest_ancestor_length(const char *path, const char *prefix_list); char *strip_path_suffix(const char *path, const char *suffix); extern char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2))); extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2))); -/* perf_mkstemp() - create tmp file honoring TMPDIR variable */ -extern int perf_mkstemp(char *path, size_t len, const char *template); -extern char *mksnpath(char *buf, size_t n, const char *fmt, ...) - __attribute__((format (printf, 3, 4))); -extern char *perf_snpath(char *buf, size_t n, const char *fmt, ...) - __attribute__((format (printf, 3, 4))); extern char *perf_pathdup(const char *fmt, ...) __attribute__((format (printf, 1, 2))); diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 21a52e0a4435..62b69ad4aa73 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -15,6 +15,7 @@ #include <errno.h> #include <math.h> +#include "util.h" #include "callchain.h" bool ip_callchain__valid(struct ip_callchain *chain, event_t *event) diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 1cba1f5504e7..1ca73e4a2723 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -5,7 +5,6 @@ #include <linux/list.h> #include <linux/rbtree.h> #include "event.h" -#include "util.h" #include "symbol.h" enum chain_mode { diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index 8784649109ce..dabe892d0e53 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c @@ -16,7 +16,7 @@ static const char *config_file_name; static int config_linenr; static int config_file_eof; -const char *config_exclusive_filename = NULL; +static const char *config_exclusive_filename; static int get_next_char(void) { @@ -291,19 +291,6 @@ static int perf_parse_long(const char *value, long *ret) return 0; } -int perf_parse_ulong(const char *value, unsigned long *ret) -{ - if (value && *value) { - char *end; - unsigned long val = strtoul(value, &end, 0); - if (!parse_unit_factor(end, &val)) - return 0; - *ret = val; - return 1; - } - return 0; -} - static void die_bad_config(const char *name) { if (config_file_name) @@ -319,15 +306,7 @@ int perf_config_int(const char *name, const char *value) return ret; } -unsigned long perf_config_ulong(const char *name, const char *value) -{ - unsigned long ret; - if (!perf_parse_ulong(value, &ret)) - die_bad_config(name); - return ret; -} - -int perf_config_bool_or_int(const char *name, const char *value, int *is_bool) +static int perf_config_bool_or_int(const char *name, const char *value, int *is_bool) { *is_bool = 1; if (!value) @@ -348,14 +327,6 @@ int perf_config_bool(const char *name, const char *value) return !!perf_config_bool_or_int(name, value, &discard); } -int perf_config_string(const char **dest, const char *var, const char *value) -{ - if (!value) - return config_error_nonbool(var); - *dest = strdup(value); - return 0; -} - static int perf_default_core_config(const char *var __used, const char *value __used) { /* Add other config variables here and to Documentation/config.txt. */ @@ -371,7 +342,7 @@ int perf_default_config(const char *var, const char *value, void *dummy __used) return 0; } -int perf_config_from_file(config_fn_t fn, const char *filename, void *data) +static int perf_config_from_file(config_fn_t fn, const char *filename, void *data) { int ret; FILE *f = fopen(filename, "r"); @@ -389,7 +360,7 @@ int perf_config_from_file(config_fn_t fn, const char *filename, void *data) return ret; } -const char *perf_etc_perfconfig(void) +static const char *perf_etc_perfconfig(void) { static const char *system_wide; if (!system_wide) @@ -403,12 +374,12 @@ static int perf_env_bool(const char *k, int def) return v ? perf_config_bool(k, v) : def; } -int perf_config_system(void) +static int perf_config_system(void) { return !perf_env_bool("PERF_CONFIG_NOSYSTEM", 0); } -int perf_config_global(void) +static int perf_config_global(void) { return !perf_env_bool("PERF_CONFIG_NOGLOBAL", 0); } @@ -450,426 +421,6 @@ int perf_config(config_fn_t fn, void *data) } /* - * Find all the stuff for perf_config_set() below. - */ - -#define MAX_MATCHES 512 - -static struct { - int baselen; - char* key; - int do_not_match; - regex_t* value_regex; - int multi_replace; - size_t offset[MAX_MATCHES]; - enum { START, SECTION_SEEN, SECTION_END_SEEN, KEY_SEEN } state; - int seen; -} store; - -static int matches(const char* key, const char* value) -{ - return !strcmp(key, store.key) && - (store.value_regex == NULL || - (store.do_not_match ^ - !regexec(store.value_regex, value, 0, NULL, 0))); -} - -static int store_aux(const char* key, const char* value, void *cb __used) -{ - int section_len; - const char *ep; - - switch (store.state) { - case KEY_SEEN: - if (matches(key, value)) { - if (store.seen == 1 && store.multi_replace == 0) { - warning("%s has multiple values", key); - } else if (store.seen >= MAX_MATCHES) { - error("too many matches for %s", key); - return 1; - } - - store.offset[store.seen] = ftell(config_file); - store.seen++; - } - break; - case SECTION_SEEN: - /* - * What we are looking for is in store.key (both - * section and var), and its section part is baselen - * long. We found key (again, both section and var). - * We would want to know if this key is in the same - * section as what we are looking for. We already - * know we are in the same section as what should - * hold store.key. - */ - ep = strrchr(key, '.'); - section_len = ep - key; - - if ((section_len != store.baselen) || - memcmp(key, store.key, section_len+1)) { - store.state = SECTION_END_SEEN; - break; - } - - /* - * Do not increment matches: this is no match, but we - * just made sure we are in the desired section. - */ - store.offset[store.seen] = ftell(config_file); - /* fallthru */ - case SECTION_END_SEEN: - case START: - if (matches(key, value)) { - store.offset[store.seen] = ftell(config_file); - store.state = KEY_SEEN; - store.seen++; - } else { - if (strrchr(key, '.') - key == store.baselen && - !strncmp(key, store.key, store.baselen)) { - store.state = SECTION_SEEN; - store.offset[store.seen] = ftell(config_file); - } - } - default: - break; - } - return 0; -} - -static int store_write_section(int fd, const char* key) -{ - const char *dot; - int i, success; - struct strbuf sb = STRBUF_INIT; - - dot = memchr(key, '.', store.baselen); - if (dot) { - strbuf_addf(&sb, "[%.*s \"", (int)(dot - key), key); - for (i = dot - key + 1; i < store.baselen; i++) { - if (key[i] == '"' || key[i] == '\\') - strbuf_addch(&sb, '\\'); - strbuf_addch(&sb, key[i]); - } - strbuf_addstr(&sb, "\"]\n"); - } else { - strbuf_addf(&sb, "[%.*s]\n", store.baselen, key); - } - - success = (write_in_full(fd, sb.buf, sb.len) == (ssize_t)sb.len); - strbuf_release(&sb); - - return success; -} - -static int store_write_pair(int fd, const char* key, const char* value) -{ - int i, success; - int length = strlen(key + store.baselen + 1); - const char *quote = ""; - struct strbuf sb = STRBUF_INIT; - - /* - * Check to see if the value needs to be surrounded with a dq pair. - * Note that problematic characters are always backslash-quoted; this - * check is about not losing leading or trailing SP and strings that - * follow beginning-of-comment characters (i.e. ';' and '#') by the - * configuration parser. - */ - if (value[0] == ' ') - quote = "\""; - for (i = 0; value[i]; i++) - if (value[i] == ';' || value[i] == '#') - quote = "\""; - if (i && value[i - 1] == ' ') - quote = "\""; - - strbuf_addf(&sb, "\t%.*s = %s", - length, key + store.baselen + 1, quote); - - for (i = 0; value[i]; i++) - switch (value[i]) { - case '\n': - strbuf_addstr(&sb, "\\n"); - break; - case '\t': - strbuf_addstr(&sb, "\\t"); - break; - case '"': - case '\\': - strbuf_addch(&sb, '\\'); - default: - strbuf_addch(&sb, value[i]); - break; - } - strbuf_addf(&sb, "%s\n", quote); - - success = (write_in_full(fd, sb.buf, sb.len) == (ssize_t)sb.len); - strbuf_release(&sb); - - return success; -} - -static ssize_t find_beginning_of_line(const char* contents, size_t size, - size_t offset_, int* found_bracket) -{ - size_t equal_offset = size, bracket_offset = size; - ssize_t offset; - -contline: - for (offset = offset_-2; offset > 0 - && contents[offset] != '\n'; offset--) - switch (contents[offset]) { - case '=': equal_offset = offset; break; - case ']': bracket_offset = offset; break; - default: break; - } - if (offset > 0 && contents[offset-1] == '\\') { - offset_ = offset; - goto contline; - } - if (bracket_offset < equal_offset) { - *found_bracket = 1; - offset = bracket_offset+1; - } else - offset++; - - return offset; -} - -int perf_config_set(const char* key, const char* value) -{ - return perf_config_set_multivar(key, value, NULL, 0); -} - -/* - * If value==NULL, unset in (remove from) config, - * if value_regex!=NULL, disregard key/value pairs where value does not match. - * if multi_replace==0, nothing, or only one matching key/value is replaced, - * else all matching key/values (regardless how many) are removed, - * before the new pair is written. - * - * Returns 0 on success. - * - * This function does this: - * - * - it locks the config file by creating ".perf/config.lock" - * - * - it then parses the config using store_aux() as validator to find - * the position on the key/value pair to replace. If it is to be unset, - * it must be found exactly once. - * - * - the config file is mmap()ed and the part before the match (if any) is - * written to the lock file, then the changed part and the rest. - * - * - the config file is removed and the lock file rename()d to it. - * - */ -int perf_config_set_multivar(const char* key, const char* value, - const char* value_regex, int multi_replace) -{ - int i, dot; - int fd = -1, in_fd; - int ret = 0; - char* config_filename; - const char* last_dot = strrchr(key, '.'); - - if (config_exclusive_filename) - config_filename = strdup(config_exclusive_filename); - else - config_filename = perf_pathdup("config"); - - /* - * Since "key" actually contains the section name and the real - * key name separated by a dot, we have to know where the dot is. - */ - - if (last_dot == NULL) { - error("key does not contain a section: %s", key); - ret = 2; - goto out_free; - } - store.baselen = last_dot - key; - - store.multi_replace = multi_replace; - - /* - * Validate the key and while at it, lower case it for matching. - */ - store.key = malloc(strlen(key) + 1); - dot = 0; - for (i = 0; key[i]; i++) { - unsigned char c = key[i]; - if (c == '.') - dot = 1; - /* Leave the extended basename untouched.. */ - if (!dot || i > store.baselen) { - if (!iskeychar(c) || (i == store.baselen+1 && !isalpha(c))) { - error("invalid key: %s", key); - free(store.key); - ret = 1; - goto out_free; - } - c = tolower(c); - } else if (c == '\n') { - error("invalid key (newline): %s", key); - free(store.key); - ret = 1; - goto out_free; - } - store.key[i] = c; - } - store.key[i] = 0; - - /* - * If .perf/config does not exist yet, write a minimal version. - */ - in_fd = open(config_filename, O_RDONLY); - if ( in_fd < 0 ) { - free(store.key); - - if ( ENOENT != errno ) { - error("opening %s: %s", config_filename, - strerror(errno)); - ret = 3; /* same as "invalid config file" */ - goto out_free; - } - /* if nothing to unset, error out */ - if (value == NULL) { - ret = 5; - goto out_free; - } - - store.key = (char*)key; - if (!store_write_section(fd, key) || - !store_write_pair(fd, key, value)) - goto write_err_out; - } else { - struct stat st; - char *contents; - ssize_t contents_sz, copy_begin, copy_end; - int new_line = 0; - - if (value_regex == NULL) - store.value_regex = NULL; - else { - if (value_regex[0] == '!') { - store.do_not_match = 1; - value_regex++; - } else - store.do_not_match = 0; - - store.value_regex = (regex_t*)malloc(sizeof(regex_t)); - if (regcomp(store.value_regex, value_regex, - REG_EXTENDED)) { - error("invalid pattern: %s", value_regex); - free(store.value_regex); - ret = 6; - goto out_free; - } - } - - store.offset[0] = 0; - store.state = START; - store.seen = 0; - - /* - * After this, store.offset will contain the *end* offset - * of the last match, or remain at 0 if no match was found. - * As a side effect, we make sure to transform only a valid - * existing config file. - */ - if (perf_config_from_file(store_aux, config_filename, NULL)) { - error("invalid config file %s", config_filename); - free(store.key); - if (store.value_regex != NULL) { - regfree(store.value_regex); - free(store.value_regex); - } - ret = 3; - goto out_free; - } - - free(store.key); - if (store.value_regex != NULL) { - regfree(store.value_regex); - free(store.value_regex); - } - - /* if nothing to unset, or too many matches, error out */ - if ((store.seen == 0 && value == NULL) || - (store.seen > 1 && multi_replace == 0)) { - ret = 5; - goto out_free; - } - - fstat(in_fd, &st); - contents_sz = xsize_t(st.st_size); - contents = mmap(NULL, contents_sz, PROT_READ, - MAP_PRIVATE, in_fd, 0); - close(in_fd); - - if (store.seen == 0) - store.seen = 1; - - for (i = 0, copy_begin = 0; i < store.seen; i++) { - if (store.offset[i] == 0) { - store.offset[i] = copy_end = contents_sz; - } else if (store.state != KEY_SEEN) { - copy_end = store.offset[i]; - } else - copy_end = find_beginning_of_line( - contents, contents_sz, - store.offset[i]-2, &new_line); - - if (copy_end > 0 && contents[copy_end-1] != '\n') - new_line = 1; - - /* write the first part of the config */ - if (copy_end > copy_begin) { - if (write_in_full(fd, contents + copy_begin, - copy_end - copy_begin) < - copy_end - copy_begin) - goto write_err_out; - if (new_line && - write_in_full(fd, "\n", 1) != 1) - goto write_err_out; - } - copy_begin = store.offset[i]; - } - - /* write the pair (value == NULL means unset) */ - if (value != NULL) { - if (store.state == START) { - if (!store_write_section(fd, key)) - goto write_err_out; - } - if (!store_write_pair(fd, key, value)) - goto write_err_out; - } - - /* write the rest of the config */ - if (copy_begin < contents_sz) - if (write_in_full(fd, contents + copy_begin, - contents_sz - copy_begin) < - contents_sz - copy_begin) - goto write_err_out; - - munmap(contents, contents_sz); - } - - ret = 0; - -out_free: - free(config_filename); - return ret; - -write_err_out: - goto out_free; - -} - -/* * Call this to report error for your variable that should not * get a boolean value (i.e. "[my] var" means "true"). */ diff --git a/tools/perf/util/exec_cmd.c b/tools/perf/util/exec_cmd.c index 2745605dba11..67eeff571568 100644 --- a/tools/perf/util/exec_cmd.c +++ b/tools/perf/util/exec_cmd.c @@ -53,8 +53,8 @@ const char *perf_extract_argv0_path(const char *argv0) slash--; if (slash >= argv0) { - argv0_path = xstrndup(argv0, slash - argv0); - return slash + 1; + argv0_path = strndup(argv0, slash - argv0); + return argv0_path ? slash + 1 : NULL; } return argv0; @@ -116,7 +116,7 @@ void setup_path(void) strbuf_release(&new_path); } -const char **prepare_perf_cmd(const char **argv) +static const char **prepare_perf_cmd(const char **argv) { int argc; const char **nargv; diff --git a/tools/perf/util/exec_cmd.h b/tools/perf/util/exec_cmd.h index 31647ac92ed1..bc4b915963f5 100644 --- a/tools/perf/util/exec_cmd.h +++ b/tools/perf/util/exec_cmd.h @@ -5,7 +5,6 @@ extern void perf_set_argv_exec_path(const char *exec_path); extern const char *perf_extract_argv0_path(const char *path); extern const char *perf_exec_path(void); extern void setup_path(void); -extern const char **prepare_perf_cmd(const char **argv); extern int execv_perf_cmd(const char **argv); /* NULL terminated */ extern int execl_perf_cmd(const char *cmd, ...); extern const char *system_path(const char *path); diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 8847bec64c54..1f62435f96c2 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -221,29 +221,38 @@ static int __dsos__write_buildid_table(struct list_head *head, pid_t pid, return 0; } +static int machine__write_buildid_table(struct machine *self, int fd) +{ + int err; + u16 kmisc = PERF_RECORD_MISC_KERNEL, + umisc = PERF_RECORD_MISC_USER; + + if (!machine__is_host(self)) { + kmisc = PERF_RECORD_MISC_GUEST_KERNEL; + umisc = PERF_RECORD_MISC_GUEST_USER; + } + + err = __dsos__write_buildid_table(&self->kernel_dsos, self->pid, + kmisc, fd); + if (err == 0) + err = __dsos__write_buildid_table(&self->user_dsos, + self->pid, umisc, fd); + return err; +} + static int dsos__write_buildid_table(struct perf_header *header, int fd) { struct perf_session *session = container_of(header, struct perf_session, header); struct rb_node *nd; - int err = 0; - u16 kmisc, umisc; + int err = machine__write_buildid_table(&session->host_machine, fd); + + if (err) + return err; for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) { struct machine *pos = rb_entry(nd, struct machine, rb_node); - if (machine__is_host(pos)) { - kmisc = PERF_RECORD_MISC_KERNEL; - umisc = PERF_RECORD_MISC_USER; - } else { - kmisc = PERF_RECORD_MISC_GUEST_KERNEL; - umisc = PERF_RECORD_MISC_GUEST_USER; - } - - err = __dsos__write_buildid_table(&pos->kernel_dsos, pos->pid, - kmisc, fd); - if (err == 0) - err = __dsos__write_buildid_table(&pos->user_dsos, - pos->pid, umisc, fd); + err = machine__write_buildid_table(pos, fd); if (err) break; } @@ -363,12 +372,17 @@ static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir) return err; } -static int dsos__cache_build_ids(struct perf_header *self) +static int machine__cache_build_ids(struct machine *self, const char *debugdir) +{ + int ret = __dsos__cache_build_ids(&self->kernel_dsos, debugdir); + ret |= __dsos__cache_build_ids(&self->user_dsos, debugdir); + return ret; +} + +static int perf_session__cache_build_ids(struct perf_session *self) { - struct perf_session *session = container_of(self, - struct perf_session, header); struct rb_node *nd; - int ret = 0; + int ret; char debugdir[PATH_MAX]; snprintf(debugdir, sizeof(debugdir), "%s/%s", getenv("HOME"), @@ -377,25 +391,30 @@ static int dsos__cache_build_ids(struct perf_header *self) if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) return -1; - for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) { + ret = machine__cache_build_ids(&self->host_machine, debugdir); + + for (nd = rb_first(&self->machines); nd; nd = rb_next(nd)) { struct machine *pos = rb_entry(nd, struct machine, rb_node); - ret |= __dsos__cache_build_ids(&pos->kernel_dsos, debugdir); - ret |= __dsos__cache_build_ids(&pos->user_dsos, debugdir); + ret |= machine__cache_build_ids(pos, debugdir); } return ret ? -1 : 0; } -static bool dsos__read_build_ids(struct perf_header *self, bool with_hits) +static bool machine__read_build_ids(struct machine *self, bool with_hits) +{ + bool ret = __dsos__read_build_ids(&self->kernel_dsos, with_hits); + ret |= __dsos__read_build_ids(&self->user_dsos, with_hits); + return ret; +} + +static bool perf_session__read_build_ids(struct perf_session *self, bool with_hits) { - bool ret = false; - struct perf_session *session = container_of(self, - struct perf_session, header); struct rb_node *nd; + bool ret = machine__read_build_ids(&self->host_machine, with_hits); - for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) { + for (nd = rb_first(&self->machines); nd; nd = rb_next(nd)) { struct machine *pos = rb_entry(nd, struct machine, rb_node); - ret |= __dsos__read_build_ids(&pos->kernel_dsos, with_hits); - ret |= __dsos__read_build_ids(&pos->user_dsos, with_hits); + ret |= machine__read_build_ids(pos, with_hits); } return ret; @@ -404,12 +423,14 @@ static bool dsos__read_build_ids(struct perf_header *self, bool with_hits) static int perf_header__adds_write(struct perf_header *self, int fd) { int nr_sections; + struct perf_session *session; struct perf_file_section *feat_sec; int sec_size; u64 sec_start; int idx = 0, err; - if (dsos__read_build_ids(self, true)) + session = container_of(self, struct perf_session, header); + if (perf_session__read_build_ids(session, true)) perf_header__set_feat(self, HEADER_BUILD_ID); nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); @@ -450,7 +471,7 @@ static int perf_header__adds_write(struct perf_header *self, int fd) } buildid_sec->size = lseek(fd, 0, SEEK_CUR) - buildid_sec->offset; - dsos__cache_build_ids(self); + perf_session__cache_build_ids(session); } lseek(fd, sec_start, SEEK_SET); @@ -490,7 +511,6 @@ int perf_header__write(struct perf_header *self, int fd, bool at_exit) lseek(fd, sizeof(f_header), SEEK_SET); - for (i = 0; i < self->attrs; i++) { attr = self->attr[i]; diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c index fbb00978b2e2..6f2975a00358 100644 --- a/tools/perf/util/help.c +++ b/tools/perf/util/help.c @@ -4,28 +4,6 @@ #include "levenshtein.h" #include "help.h" -/* most GUI terminals set COLUMNS (although some don't export it) */ -static int term_columns(void) -{ - char *col_string = getenv("COLUMNS"); - int n_cols; - - if (col_string && (n_cols = atoi(col_string)) > 0) - return n_cols; - -#ifdef TIOCGWINSZ - { - struct winsize ws; - if (!ioctl(1, TIOCGWINSZ, &ws)) { - if (ws.ws_col) - return ws.ws_col; - } - } -#endif - - return 80; -} - void add_cmdname(struct cmdnames *cmds, const char *name, size_t len) { struct cmdname *ent = malloc(sizeof(*ent) + len + 1); @@ -96,9 +74,13 @@ static void pretty_print_string_list(struct cmdnames *cmds, int longest) { int cols = 1, rows; int space = longest + 1; /* min 1 SP between words */ - int max_cols = term_columns() - 1; /* don't print *on* the edge */ + struct winsize win; + int max_cols; int i, j; + get_term_dimensions(&win); + max_cols = win.ws_col - 1; /* don't print *on* the edge */ + if (space < max_cols) cols = max_cols / space; rows = (cmds->cnt + cols - 1) / cols; @@ -324,7 +306,7 @@ const char *help_unknown_cmd(const char *cmd) main_cmds.names[0] = NULL; clean_cmdnames(&main_cmds); - fprintf(stderr, "WARNING: You called a Git program named '%s', " + fprintf(stderr, "WARNING: You called a perf program named '%s', " "which does not exist.\n" "Continuing under the assumption that you meant '%s'\n", cmd, assumed); diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index f75c5f62401c..739c39fd0ade 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -1,3 +1,4 @@ +#include "build-id.h" #include "util.h" #include "hist.h" #include "session.h" @@ -662,7 +663,7 @@ size_t hists__fprintf(struct hists *self, struct hists *pair, long displacement = 0; unsigned int width; const char *sep = symbol_conf.field_sep; - char *col_width = symbol_conf.col_width_list_str; + const char *col_width = symbol_conf.col_width_list_str; init_rem_hits(); @@ -988,22 +989,35 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head) struct symbol *sym = self->ms.sym; struct map *map = self->ms.map; struct dso *dso = map->dso; - const char *filename = dso->long_name; + char *filename = dso__build_id_filename(dso, NULL, 0); char command[PATH_MAX * 2]; FILE *file; + int err = -1; u64 len; - if (!filename) - return -1; + if (filename == NULL) { + if (dso->has_build_id) { + pr_err("Can't annotate %s: not enough memory\n", + sym->name); + return -1; + } + /* + * If we don't have build-ids, well, lets hope that this + * DSO is the same as when 'perf record' ran. + */ + filename = dso->long_name; + } if (dso->origin == DSO__ORIG_KERNEL) { - if (dso->annotate_warned) - return 0; + if (dso->annotate_warned) { + err = 0; + goto out_free_filename; + } dso->annotate_warned = 1; pr_err("Can't annotate %s: No vmlinux file was found in the " "path:\n", sym->name); vmlinux_path__fprintf(stderr); - return -1; + goto out_free_filename; } pr_debug("%s: filename=%s, sym=%s, start=%#Lx, end=%#Lx\n", __func__, @@ -1025,14 +1039,18 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head) file = popen(command, "r"); if (!file) - return -1; + goto out_free_filename; while (!feof(file)) if (hist_entry__parse_objdump_line(self, file, head) < 0) break; pclose(file); - return 0; + err = 0; +out_free_filename: + if (dso->has_build_id) + free(filename); + return err; } void hists__inc_nr_events(struct hists *self, u32 type) diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h index 388ab1bfd114..1eb804fd3fbf 100644 --- a/tools/perf/util/include/linux/kernel.h +++ b/tools/perf/util/include/linux/kernel.h @@ -28,6 +28,8 @@ (type *)((char *)__mptr - offsetof(type, member)); }) #endif +#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); })) + #ifndef max #define max(x, y) ({ \ typeof(x) _max1 = (x); \ diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index 6974431d212f..0b45658f7497 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -1,7 +1,15 @@ #define _GNU_SOURCE #include <stdio.h> #undef _GNU_SOURCE - +/* + * slang versions <= 2.0.6 have a "#if HAVE_LONG_LONG" that breaks + * the build if it isn't defined. Use the equivalent one that glibc + * has on features.h. + */ +#include <features.h> +#ifndef HAVE_LONG_LONG +#define HAVE_LONG_LONG __GLIBC_HAVE_LONG_LONG +#endif #include <slang.h> #include <stdlib.h> #include <newt.h> @@ -14,6 +22,17 @@ #include "sort.h" #include "symbol.h" +#if SLANG_VERSION < 20104 +#define slsmg_printf(msg, args...) SLsmg_printf((char *)msg, ##args) +#define slsmg_write_nstring(msg, len) SLsmg_write_nstring((char *)msg, len) +#define sltt_set_color(obj, name, fg, bg) SLtt_set_color(obj,(char *)name,\ + (char *)fg, (char *)bg) +#else +#define slsmg_printf SLsmg_printf +#define slsmg_write_nstring SLsmg_write_nstring +#define sltt_set_color SLtt_set_color +#endif + struct ui_progress { newtComponent form, scale; }; @@ -118,6 +137,7 @@ int browser__show_help(const char *format, va_list ap) static void newt_form__set_exit_keys(newtComponent self) { + newtFormAddHotKey(self, NEWT_KEY_LEFT); newtFormAddHotKey(self, NEWT_KEY_ESCAPE); newtFormAddHotKey(self, 'Q'); newtFormAddHotKey(self, 'q'); @@ -166,6 +186,48 @@ out_destroy_form: return rc; } +static int ui__help_window(const char *text) +{ + struct newtExitStruct es; + newtComponent tb, form = newt_form__new(); + int rc = -1; + int max_len = 0, nr_lines = 0; + const char *t; + + if (form == NULL) + return -1; + + t = text; + while (1) { + const char *sep = strchr(t, '\n'); + int len; + + if (sep == NULL) + sep = strchr(t, '\0'); + len = sep - t; + if (max_len < len) + max_len = len; + ++nr_lines; + if (*sep == '\0') + break; + t = sep + 1; + } + + tb = newtTextbox(0, 0, max_len, nr_lines, 0); + if (tb == NULL) + goto out_destroy_form; + + newtTextboxSetText(tb, text); + newtFormAddComponent(form, tb); + newtCenteredWindow(max_len, nr_lines, NULL); + newtFormRun(form, &es); + newtPopWindow(); + rc = 0; +out_destroy_form: + newtFormDestroy(form); + return rc; +} + static bool dialog_yesno(const char *msg) { /* newtWinChoice should really be accepting const char pointers... */ @@ -249,21 +311,21 @@ static int objdump_line__show(struct objdump_line *self, struct list_head *head, color = ui_browser__percent_color(percent, current_entry); SLsmg_set_color(color); - SLsmg_printf(" %7.2f ", percent); + slsmg_printf(" %7.2f ", percent); if (!current_entry) SLsmg_set_color(HE_COLORSET_CODE); } else { int color = ui_browser__percent_color(0, current_entry); SLsmg_set_color(color); - SLsmg_write_nstring(" ", 9); + slsmg_write_nstring(" ", 9); } SLsmg_write_char(':'); - SLsmg_write_nstring(" ", 8); + slsmg_write_nstring(" ", 8); if (!*self->line) - SLsmg_write_nstring(" ", width - 18); + slsmg_write_nstring(" ", width - 18); else - SLsmg_write_nstring(self->line, width - 18); + slsmg_write_nstring(self->line, width - 18); return 0; } @@ -321,9 +383,9 @@ static int ui_browser__run(struct ui_browser *self, const char *title, newtFormAddHotKey(self->form, NEWT_KEY_DOWN); newtFormAddHotKey(self->form, NEWT_KEY_PGUP); newtFormAddHotKey(self->form, NEWT_KEY_PGDN); + newtFormAddHotKey(self->form, ' '); newtFormAddHotKey(self->form, NEWT_KEY_HOME); newtFormAddHotKey(self->form, NEWT_KEY_END); - newtFormAddHotKey(self->form, NEWT_KEY_LEFT); if (ui_browser__refresh_entries(self) < 0) return -1; @@ -358,6 +420,7 @@ static int ui_browser__run(struct ui_browser *self, const char *title, } break; case NEWT_KEY_PGDN: + case ' ': if (self->first_visible_entry_idx + self->height > self->nr_entries - 1) break; @@ -756,8 +819,11 @@ static int hist_browser__populate(struct hist_browser *self, struct hists *hists newtFormAddHotKey(self->form, 'd'); newtFormAddHotKey(self->form, 'T'); newtFormAddHotKey(self->form, 't'); + newtFormAddHotKey(self->form, '?'); + newtFormAddHotKey(self->form, 'H'); + newtFormAddHotKey(self->form, 'h'); + newtFormAddHotKey(self->form, NEWT_KEY_F1); newtFormAddHotKey(self->form, NEWT_KEY_RIGHT); - newtFormAddHotKey(self->form, NEWT_KEY_LEFT); newtFormAddComponents(self->form, self->tree, NULL); self->selection = newt__symbol_tree_get_current(self->tree); @@ -843,6 +909,9 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na dso = browser->selection->map ? browser->selection->map->dso : NULL; if (es.reason == NEWT_EXIT_HOTKEY) { + if (es.u.key == NEWT_KEY_F1) + goto do_help; + switch (toupper(es.u.key)) { case 'A': goto do_annotate; @@ -850,6 +919,17 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na goto zoom_dso; case 'T': goto zoom_thread; + case 'H': + case '?': +do_help: + ui__help_window("-> Zoom into DSO/Threads & Annotate current symbol\n" + "<- Zoom out\n" + "a Annotate current symbol\n" + "h/?/F1 Show this window\n" + "d Zoom into current DSO\n" + "t Zoom into current Thread\n" + "q/CTRL+C Exit browser"); + continue; default:; } if (toupper(es.u.key) == 'Q' || @@ -988,23 +1068,26 @@ static struct newtPercentTreeColors { void setup_browser(void) { struct newtPercentTreeColors *c = &defaultPercentTreeColors; - if (!isatty(1)) + + if (!isatty(1) || !use_browser) { + setup_pager(); return; + } - use_browser = true; + use_browser = 1; newtInit(); newtCls(); ui_helpline__puts(" "); - SLtt_set_color(HE_COLORSET_TOP, NULL, c->topColorFg, c->topColorBg); - SLtt_set_color(HE_COLORSET_MEDIUM, NULL, c->mediumColorFg, c->mediumColorBg); - SLtt_set_color(HE_COLORSET_NORMAL, NULL, c->normalColorFg, c->normalColorBg); - SLtt_set_color(HE_COLORSET_SELECTED, NULL, c->selColorFg, c->selColorBg); - SLtt_set_color(HE_COLORSET_CODE, NULL, c->codeColorFg, c->codeColorBg); + sltt_set_color(HE_COLORSET_TOP, NULL, c->topColorFg, c->topColorBg); + sltt_set_color(HE_COLORSET_MEDIUM, NULL, c->mediumColorFg, c->mediumColorBg); + sltt_set_color(HE_COLORSET_NORMAL, NULL, c->normalColorFg, c->normalColorBg); + sltt_set_color(HE_COLORSET_SELECTED, NULL, c->selColorFg, c->selColorBg); + sltt_set_color(HE_COLORSET_CODE, NULL, c->codeColorFg, c->codeColorBg); } void exit_browser(bool wait_for_ok) { - if (use_browser) { + if (use_browser > 0) { if (wait_for_ok) { char title[] = "Fatal Error", ok[] = "Ok"; newtWinMessage(title, ok, browser__last_msg); diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c index ed887642460c..99d02aa57dbf 100644 --- a/tools/perf/util/parse-options.c +++ b/tools/perf/util/parse-options.c @@ -51,7 +51,7 @@ static int get_value(struct parse_opt_ctx_t *p, case OPTION_BOOLEAN: case OPTION_INCR: case OPTION_BIT: - case OPTION_SET_INT: + case OPTION_SET_UINT: case OPTION_SET_PTR: return opterror(opt, "takes no value", flags); case OPTION_END: @@ -59,7 +59,9 @@ static int get_value(struct parse_opt_ctx_t *p, case OPTION_GROUP: case OPTION_STRING: case OPTION_INTEGER: + case OPTION_UINTEGER: case OPTION_LONG: + case OPTION_U64: default: break; } @@ -81,8 +83,8 @@ static int get_value(struct parse_opt_ctx_t *p, *(int *)opt->value = unset ? 0 : *(int *)opt->value + 1; return 0; - case OPTION_SET_INT: - *(int *)opt->value = unset ? 0 : opt->defval; + case OPTION_SET_UINT: + *(unsigned int *)opt->value = unset ? 0 : opt->defval; return 0; case OPTION_SET_PTR: @@ -125,6 +127,22 @@ static int get_value(struct parse_opt_ctx_t *p, return opterror(opt, "expects a numerical value", flags); return 0; + case OPTION_UINTEGER: + if (unset) { + *(unsigned int *)opt->value = 0; + return 0; + } + if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { + *(unsigned int *)opt->value = opt->defval; + return 0; + } + if (get_arg(p, opt, flags, &arg)) + return -1; + *(unsigned int *)opt->value = strtol(arg, (char **)&s, 10); + if (*s) + return opterror(opt, "expects a numerical value", flags); + return 0; + case OPTION_LONG: if (unset) { *(long *)opt->value = 0; @@ -141,6 +159,22 @@ static int get_value(struct parse_opt_ctx_t *p, return opterror(opt, "expects a numerical value", flags); return 0; + case OPTION_U64: + if (unset) { + *(u64 *)opt->value = 0; + return 0; + } + if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { + *(u64 *)opt->value = opt->defval; + return 0; + } + if (get_arg(p, opt, flags, &arg)) + return -1; + *(u64 *)opt->value = strtoull(arg, (char **)&s, 10); + if (*s) + return opterror(opt, "expects a numerical value", flags); + return 0; + case OPTION_END: case OPTION_ARGUMENT: case OPTION_GROUP: @@ -446,7 +480,10 @@ int usage_with_options_internal(const char * const *usagestr, switch (opts->type) { case OPTION_ARGUMENT: break; + case OPTION_LONG: + case OPTION_U64: case OPTION_INTEGER: + case OPTION_UINTEGER: if (opts->flags & PARSE_OPT_OPTARG) if (opts->long_name) pos += fprintf(stderr, "[=<n>]"); @@ -478,15 +515,14 @@ int usage_with_options_internal(const char * const *usagestr, pos += fprintf(stderr, " ..."); } break; - default: /* OPTION_{BIT,BOOLEAN,SET_INT,SET_PTR} */ + default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */ case OPTION_END: case OPTION_GROUP: case OPTION_BIT: case OPTION_BOOLEAN: case OPTION_INCR: - case OPTION_SET_INT: + case OPTION_SET_UINT: case OPTION_SET_PTR: - case OPTION_LONG: break; } diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h index b2da725f102a..c7d72dce54b2 100644 --- a/tools/perf/util/parse-options.h +++ b/tools/perf/util/parse-options.h @@ -1,6 +1,9 @@ #ifndef __PERF_PARSE_OPTIONS_H #define __PERF_PARSE_OPTIONS_H +#include <linux/kernel.h> +#include <stdbool.h> + enum parse_opt_type { /* special types */ OPTION_END, @@ -10,13 +13,15 @@ enum parse_opt_type { OPTION_BIT, OPTION_BOOLEAN, OPTION_INCR, - OPTION_SET_INT, + OPTION_SET_UINT, OPTION_SET_PTR, /* options with arguments (usually) */ OPTION_STRING, OPTION_INTEGER, OPTION_LONG, OPTION_CALLBACK, + OPTION_U64, + OPTION_UINTEGER, }; enum parse_opt_flags { @@ -74,7 +79,7 @@ typedef int parse_opt_cb(const struct option *, const char *arg, int unset); * * `defval`:: * default value to fill (*->value) with for PARSE_OPT_OPTARG. - * OPTION_{BIT,SET_INT,SET_PTR} store the {mask,integer,pointer} to put in + * OPTION_{BIT,SET_UINT,SET_PTR} store the {mask,integer,pointer} to put in * the value when met. * CALLBACKS can use it like they want. */ @@ -91,17 +96,21 @@ struct option { intptr_t defval; }; +#define check_vtype(v, type) ( BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v ) + #define OPT_END() { .type = OPTION_END } #define OPT_ARGUMENT(l, h) { .type = OPTION_ARGUMENT, .long_name = (l), .help = (h) } #define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) } -#define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (b) } -#define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } -#define OPT_INCR(s, l, v, h) { .type = OPTION_INCR, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } -#define OPT_SET_INT(s, l, v, h, i) { .type = OPTION_SET_INT, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (i) } +#define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h), .defval = (b) } +#define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h) } +#define OPT_INCR(s, l, v, h) { .type = OPTION_INCR, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) } +#define OPT_SET_UINT(s, l, v, h, i) { .type = OPTION_SET_UINT, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h), .defval = (i) } #define OPT_SET_PTR(s, l, v, h, p) { .type = OPTION_SET_PTR, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (p) } -#define OPT_INTEGER(s, l, v, h) { .type = OPTION_INTEGER, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } -#define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } -#define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h) } +#define OPT_INTEGER(s, l, v, h) { .type = OPTION_INTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) } +#define OPT_UINTEGER(s, l, v, h) { .type = OPTION_UINTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h) } +#define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) } +#define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) } +#define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h) } #define OPT_DATE(s, l, v, h) \ { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb } #define OPT_CALLBACK(s, l, v, a, h, f) \ diff --git a/tools/perf/util/path.c b/tools/perf/util/path.c index fd1f2faaade4..58a470d036dd 100644 --- a/tools/perf/util/path.c +++ b/tools/perf/util/path.c @@ -54,21 +54,6 @@ static char *cleanup_path(char *path) return path; } -char *mksnpath(char *buf, size_t n, const char *fmt, ...) -{ - va_list args; - unsigned len; - - va_start(args, fmt); - len = vsnprintf(buf, n, fmt, args); - va_end(args); - if (len >= n) { - strlcpy(buf, bad_path, n); - return buf; - } - return cleanup_path(buf); -} - static char *perf_vsnpath(char *buf, size_t n, const char *fmt, va_list args) { const char *perf_dir = get_perf_dir(); @@ -89,15 +74,6 @@ bad: return buf; } -char *perf_snpath(char *buf, size_t n, const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - (void)perf_vsnpath(buf, n, fmt, args); - va_end(args); - return buf; -} - char *perf_pathdup(const char *fmt, ...) { char path[PATH_MAX]; @@ -143,184 +119,6 @@ char *perf_path(const char *fmt, ...) return cleanup_path(pathname); } - -/* perf_mkstemp() - create tmp file honoring TMPDIR variable */ -int perf_mkstemp(char *path, size_t len, const char *template) -{ - const char *tmp; - size_t n; - - tmp = getenv("TMPDIR"); - if (!tmp) - tmp = "/tmp"; - n = snprintf(path, len, "%s/%s", tmp, template); - if (len <= n) { - errno = ENAMETOOLONG; - return -1; - } - return mkstemp(path); -} - - -const char *make_relative_path(const char *abs_path, const char *base) -{ - static char buf[PATH_MAX + 1]; - int baselen; - - if (!base) - return abs_path; - - baselen = strlen(base); - if (prefixcmp(abs_path, base)) - return abs_path; - if (abs_path[baselen] == '/') - baselen++; - else if (base[baselen - 1] != '/') - return abs_path; - - strcpy(buf, abs_path + baselen); - - return buf; -} - -/* - * It is okay if dst == src, but they should not overlap otherwise. - * - * Performs the following normalizations on src, storing the result in dst: - * - Ensures that components are separated by '/' (Windows only) - * - Squashes sequences of '/'. - * - Removes "." components. - * - Removes ".." components, and the components the precede them. - * Returns failure (non-zero) if a ".." component appears as first path - * component anytime during the normalization. Otherwise, returns success (0). - * - * Note that this function is purely textual. It does not follow symlinks, - * verify the existence of the path, or make any system calls. - */ -int normalize_path_copy(char *dst, const char *src) -{ - char *dst0; - - if (has_dos_drive_prefix(src)) { - *dst++ = *src++; - *dst++ = *src++; - } - dst0 = dst; - - if (is_dir_sep(*src)) { - *dst++ = '/'; - while (is_dir_sep(*src)) - src++; - } - - for (;;) { - char c = *src; - - /* - * A path component that begins with . could be - * special: - * (1) "." and ends -- ignore and terminate. - * (2) "./" -- ignore them, eat slash and continue. - * (3) ".." and ends -- strip one and terminate. - * (4) "../" -- strip one, eat slash and continue. - */ - if (c == '.') { - if (!src[1]) { - /* (1) */ - src++; - } else if (is_dir_sep(src[1])) { - /* (2) */ - src += 2; - while (is_dir_sep(*src)) - src++; - continue; - } else if (src[1] == '.') { - if (!src[2]) { - /* (3) */ - src += 2; - goto up_one; - } else if (is_dir_sep(src[2])) { - /* (4) */ - src += 3; - while (is_dir_sep(*src)) - src++; - goto up_one; - } - } - } - - /* copy up to the next '/', and eat all '/' */ - while ((c = *src++) != '\0' && !is_dir_sep(c)) - *dst++ = c; - if (is_dir_sep(c)) { - *dst++ = '/'; - while (is_dir_sep(c)) - c = *src++; - src--; - } else if (!c) - break; - continue; - - up_one: - /* - * dst0..dst is prefix portion, and dst[-1] is '/'; - * go up one level. - */ - dst--; /* go to trailing '/' */ - if (dst <= dst0) - return -1; - /* Windows: dst[-1] cannot be backslash anymore */ - while (dst0 < dst && dst[-1] != '/') - dst--; - } - *dst = '\0'; - return 0; -} - -/* - * path = Canonical absolute path - * prefix_list = Colon-separated list of absolute paths - * - * Determines, for each path in prefix_list, whether the "prefix" really - * is an ancestor directory of path. Returns the length of the longest - * ancestor directory, excluding any trailing slashes, or -1 if no prefix - * is an ancestor. (Note that this means 0 is returned if prefix_list is - * "/".) "/foo" is not considered an ancestor of "/foobar". Directories - * are not considered to be their own ancestors. path must be in a - * canonical form: empty components, or "." or ".." components are not - * allowed. prefix_list may be null, which is like "". - */ -int longest_ancestor_length(const char *path, const char *prefix_list) -{ - char buf[PATH_MAX+1]; - const char *ceil, *colon; - int len, max_len = -1; - - if (prefix_list == NULL || !strcmp(path, "/")) - return -1; - - for (colon = ceil = prefix_list; *colon; ceil = colon+1) { - for (colon = ceil; *colon && *colon != PATH_SEP; colon++); - len = colon - ceil; - if (len == 0 || len > PATH_MAX || !is_absolute_path(ceil)) - continue; - strlcpy(buf, ceil, len+1); - if (normalize_path_copy(buf, buf) < 0) - continue; - len = strlen(buf); - if (len > 0 && buf[len-1] == '/') - buf[--len] = '\0'; - - if (!strncmp(path, buf, len) && - path[len] == '/' && - len > max_len) { - max_len = len; - } - } - - return max_len; -} - /* strip arbitrary amount of directory separators at end of path */ static inline int chomp_trailing_dir_sep(const char *path, int len) { @@ -354,5 +152,5 @@ char *strip_path_suffix(const char *path, const char *suffix) if (path_len && !is_dir_sep(path[path_len - 1])) return NULL; - return xstrndup(path, chomp_trailing_dir_sep(path, path_len)); + return strndup(path, chomp_trailing_dir_sep(path, path_len)); } diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 562b1443e785..d964cb199c67 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -668,6 +668,7 @@ static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1); if (ret <= 0 || nops == 0) { pf->fb_ops = NULL; +#if _ELFUTILS_PREREQ(0, 142) } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa && pf->cfi != NULL) { Dwarf_Frame *frame; @@ -677,6 +678,7 @@ static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) (uintmax_t)pf->addr); return -ENOENT; } +#endif } /* Find each argument */ @@ -741,32 +743,36 @@ static int find_lazy_match_lines(struct list_head *head, const char *fname, const char *pat) { char *fbuf, *p1, *p2; - int fd, ret, line, nlines = 0; + int fd, line, nlines = -1; struct stat st; fd = open(fname, O_RDONLY); if (fd < 0) { pr_warning("Failed to open %s: %s\n", fname, strerror(-fd)); - return fd; + return -errno; } - ret = fstat(fd, &st); - if (ret < 0) { + if (fstat(fd, &st) < 0) { pr_warning("Failed to get the size of %s: %s\n", fname, strerror(errno)); - return ret; + nlines = -errno; + goto out_close; } - fbuf = xmalloc(st.st_size + 2); - ret = read(fd, fbuf, st.st_size); - if (ret < 0) { + + nlines = -ENOMEM; + fbuf = malloc(st.st_size + 2); + if (fbuf == NULL) + goto out_close; + if (read(fd, fbuf, st.st_size) < 0) { pr_warning("Failed to read %s: %s\n", fname, strerror(errno)); - return ret; + nlines = -errno; + goto out_free_fbuf; } - close(fd); fbuf[st.st_size] = '\n'; /* Dummy line */ fbuf[st.st_size + 1] = '\0'; p1 = fbuf; line = 1; + nlines = 0; while ((p2 = strchr(p1, '\n')) != NULL) { *p2 = '\0'; if (strlazymatch(p1, pat)) { @@ -776,7 +782,10 @@ static int find_lazy_match_lines(struct list_head *head, line++; p1 = p2 + 1; } +out_free_fbuf: free(fbuf); +out_close: + close(fd); return nlines; } @@ -953,11 +962,15 @@ int find_kprobe_trace_events(int fd, struct perf_probe_event *pev, if (!dbg) { pr_warning("No dwarf info found in the vmlinux - " "please rebuild with CONFIG_DEBUG_INFO=y.\n"); + free(pf.tevs); + *tevs = NULL; return -EBADF; } +#if _ELFUTILS_PREREQ(0, 142) /* Get the call frame information from this dwarf */ pf.cfi = dwarf_getcfi(dbg); +#endif off = 0; line_list__init(&pf.lcache); diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h index 66f1980e3855..e1f61dcd18ff 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h @@ -29,6 +29,7 @@ extern int find_line_range(int fd, struct line_range *lr); #include <dwarf.h> #include <libdw.h> +#include <version.h> struct probe_finder { struct perf_probe_event *pev; /* Target probe event */ @@ -44,7 +45,9 @@ struct probe_finder { struct list_head lcache; /* Line cache for lazy match */ /* For variable searching */ +#if _ELFUTILS_PREREQ(0, 142) Dwarf_CFI *cfi; /* Call Frame Information */ +#endif Dwarf_Op *fb_ops; /* Frame base attribute */ struct perf_probe_arg *pvar; /* Current target variable */ struct kprobe_trace_arg *tvar; /* Current result variable */ diff --git a/tools/perf/util/quote.c b/tools/perf/util/quote.c index 2726fe40eb5d..01f03242b86a 100644 --- a/tools/perf/util/quote.c +++ b/tools/perf/util/quote.c @@ -1,8 +1,6 @@ #include "cache.h" #include "quote.h" -int quote_path_fully = 1; - /* Help to copy the thing properly quoted for the shell safety. * any single quote is replaced with '\'', any exclamation point * is replaced with '\!', and the whole thing is enclosed in a @@ -19,7 +17,7 @@ static inline int need_bs_quote(char c) return (c == '\'' || c == '!'); } -void sq_quote_buf(struct strbuf *dst, const char *src) +static void sq_quote_buf(struct strbuf *dst, const char *src) { char *to_free = NULL; @@ -41,23 +39,6 @@ void sq_quote_buf(struct strbuf *dst, const char *src) free(to_free); } -void sq_quote_print(FILE *stream, const char *src) -{ - char c; - - fputc('\'', stream); - while ((c = *src++)) { - if (need_bs_quote(c)) { - fputs("'\\", stream); - fputc(c, stream); - fputc('\'', stream); - } else { - fputc(c, stream); - } - } - fputc('\'', stream); -} - void sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen) { int i; @@ -71,415 +52,3 @@ void sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen) die("Too many or long arguments"); } } - -char *sq_dequote_step(char *arg, char **next) -{ - char *dst = arg; - char *src = arg; - char c; - - if (*src != '\'') - return NULL; - for (;;) { - c = *++src; - if (!c) - return NULL; - if (c != '\'') { - *dst++ = c; - continue; - } - /* We stepped out of sq */ - switch (*++src) { - case '\0': - *dst = 0; - if (next) - *next = NULL; - return arg; - case '\\': - c = *++src; - if (need_bs_quote(c) && *++src == '\'') { - *dst++ = c; - continue; - } - /* Fallthrough */ - default: - if (!next || !isspace(*src)) - return NULL; - do { - c = *++src; - } while (isspace(c)); - *dst = 0; - *next = src; - return arg; - } - } -} - -char *sq_dequote(char *arg) -{ - return sq_dequote_step(arg, NULL); -} - -int sq_dequote_to_argv(char *arg, const char ***argv, int *nr, int *alloc) -{ - char *next = arg; - - if (!*arg) - return 0; - do { - char *dequoted = sq_dequote_step(next, &next); - if (!dequoted) - return -1; - ALLOC_GROW(*argv, *nr + 1, *alloc); - (*argv)[(*nr)++] = dequoted; - } while (next); - - return 0; -} - -/* 1 means: quote as octal - * 0 means: quote as octal if (quote_path_fully) - * -1 means: never quote - * c: quote as "\\c" - */ -#define X8(x) x, x, x, x, x, x, x, x -#define X16(x) X8(x), X8(x) -static signed char const sq_lookup[256] = { - /* 0 1 2 3 4 5 6 7 */ - /* 0x00 */ 1, 1, 1, 1, 1, 1, 1, 'a', - /* 0x08 */ 'b', 't', 'n', 'v', 'f', 'r', 1, 1, - /* 0x10 */ X16(1), - /* 0x20 */ -1, -1, '"', -1, -1, -1, -1, -1, - /* 0x28 */ X16(-1), X16(-1), X16(-1), - /* 0x58 */ -1, -1, -1, -1,'\\', -1, -1, -1, - /* 0x60 */ X16(-1), X8(-1), - /* 0x78 */ -1, -1, -1, -1, -1, -1, -1, 1, - /* 0x80 */ /* set to 0 */ -}; - -static inline int sq_must_quote(char c) -{ - return sq_lookup[(unsigned char)c] + quote_path_fully > 0; -} - -/* - * Returns the longest prefix not needing a quote up to maxlen if - * positive. - * This stops at the first \0 because it's marked as a character - * needing an escape. - */ -static ssize_t next_quote_pos(const char *s, ssize_t maxlen) -{ - ssize_t len; - - if (maxlen < 0) { - for (len = 0; !sq_must_quote(s[len]); len++); - } else { - for (len = 0; len < maxlen && !sq_must_quote(s[len]); len++); - } - return len; -} - -/* - * C-style name quoting. - * - * (1) if sb and fp are both NULL, inspect the input name and counts the - * number of bytes that are needed to hold c_style quoted version of name, - * counting the double quotes around it but not terminating NUL, and - * returns it. - * However, if name does not need c_style quoting, it returns 0. - * - * (2) if sb or fp are not NULL, it emits the c_style quoted version - * of name, enclosed with double quotes if asked and needed only. - * Return value is the same as in (1). - */ -static size_t quote_c_style_counted(const char *name, ssize_t maxlen, - struct strbuf *sb, FILE *fp, int no_dq) -{ -#define EMIT(c) \ - do { \ - if (sb) strbuf_addch(sb, (c)); \ - if (fp) fputc((c), fp); \ - count++; \ - } while (0) - -#define EMITBUF(s, l) \ - do { \ - int __ret; \ - if (sb) strbuf_add(sb, (s), (l)); \ - if (fp) __ret = fwrite((s), (l), 1, fp); \ - count += (l); \ - } while (0) - - ssize_t len, count = 0; - const char *p = name; - - for (;;) { - int ch; - - len = next_quote_pos(p, maxlen); - if (len == maxlen || !p[len]) - break; - - if (!no_dq && p == name) - EMIT('"'); - - EMITBUF(p, len); - EMIT('\\'); - p += len; - ch = (unsigned char)*p++; - if (sq_lookup[ch] >= ' ') { - EMIT(sq_lookup[ch]); - } else { - EMIT(((ch >> 6) & 03) + '0'); - EMIT(((ch >> 3) & 07) + '0'); - EMIT(((ch >> 0) & 07) + '0'); - } - } - - EMITBUF(p, len); - if (p == name) /* no ending quote needed */ - return 0; - - if (!no_dq) - EMIT('"'); - return count; -} - -size_t quote_c_style(const char *name, struct strbuf *sb, FILE *fp, int nodq) -{ - return quote_c_style_counted(name, -1, sb, fp, nodq); -} - -void quote_two_c_style(struct strbuf *sb, const char *prefix, const char *path, int nodq) -{ - if (quote_c_style(prefix, NULL, NULL, 0) || - quote_c_style(path, NULL, NULL, 0)) { - if (!nodq) - strbuf_addch(sb, '"'); - quote_c_style(prefix, sb, NULL, 1); - quote_c_style(path, sb, NULL, 1); - if (!nodq) - strbuf_addch(sb, '"'); - } else { - strbuf_addstr(sb, prefix); - strbuf_addstr(sb, path); - } -} - -void write_name_quoted(const char *name, FILE *fp, int terminator) -{ - if (terminator) { - quote_c_style(name, NULL, fp, 0); - } else { - fputs(name, fp); - } - fputc(terminator, fp); -} - -void write_name_quotedpfx(const char *pfx, ssize_t pfxlen, - const char *name, FILE *fp, int terminator) -{ - int needquote = 0; - - if (terminator) { - needquote = next_quote_pos(pfx, pfxlen) < pfxlen - || name[next_quote_pos(name, -1)]; - } - if (needquote) { - fputc('"', fp); - quote_c_style_counted(pfx, pfxlen, NULL, fp, 1); - quote_c_style(name, NULL, fp, 1); - fputc('"', fp); - } else { - int ret; - - ret = fwrite(pfx, pfxlen, 1, fp); - fputs(name, fp); - } - fputc(terminator, fp); -} - -/* quote path as relative to the given prefix */ -char *quote_path_relative(const char *in, int len, - struct strbuf *out, const char *prefix) -{ - int needquote; - - if (len < 0) - len = strlen(in); - - /* "../" prefix itself does not need quoting, but "in" might. */ - needquote = (next_quote_pos(in, len) < len); - strbuf_setlen(out, 0); - strbuf_grow(out, len); - - if (needquote) - strbuf_addch(out, '"'); - if (prefix) { - int off = 0; - while (off < len && prefix[off] && prefix[off] == in[off]) - if (prefix[off] == '/') { - prefix += off + 1; - in += off + 1; - len -= off + 1; - off = 0; - } else - off++; - - for (; *prefix; prefix++) - if (*prefix == '/') - strbuf_addstr(out, "../"); - } - - quote_c_style_counted (in, len, out, NULL, 1); - - if (needquote) - strbuf_addch(out, '"'); - if (!out->len) - strbuf_addstr(out, "./"); - - return out->buf; -} - -/* - * C-style name unquoting. - * - * Quoted should point at the opening double quote. - * + Returns 0 if it was able to unquote the string properly, and appends the - * result in the strbuf `sb'. - * + Returns -1 in case of error, and doesn't touch the strbuf. Though note - * that this function will allocate memory in the strbuf, so calling - * strbuf_release is mandatory whichever result unquote_c_style returns. - * - * Updates endp pointer to point at one past the ending double quote if given. - */ -int unquote_c_style(struct strbuf *sb, const char *quoted, const char **endp) -{ - size_t oldlen = sb->len, len; - int ch, ac; - - if (*quoted++ != '"') - return -1; - - for (;;) { - len = strcspn(quoted, "\"\\"); - strbuf_add(sb, quoted, len); - quoted += len; - - switch (*quoted++) { - case '"': - if (endp) - *endp = quoted; - return 0; - case '\\': - break; - default: - goto error; - } - - switch ((ch = *quoted++)) { - case 'a': ch = '\a'; break; - case 'b': ch = '\b'; break; - case 'f': ch = '\f'; break; - case 'n': ch = '\n'; break; - case 'r': ch = '\r'; break; - case 't': ch = '\t'; break; - case 'v': ch = '\v'; break; - - case '\\': case '"': - break; /* verbatim */ - - /* octal values with first digit over 4 overflow */ - case '0': case '1': case '2': case '3': - ac = ((ch - '0') << 6); - if ((ch = *quoted++) < '0' || '7' < ch) - goto error; - ac |= ((ch - '0') << 3); - if ((ch = *quoted++) < '0' || '7' < ch) - goto error; - ac |= (ch - '0'); - ch = ac; - break; - default: - goto error; - } - strbuf_addch(sb, ch); - } - - error: - strbuf_setlen(sb, oldlen); - return -1; -} - -/* quoting as a string literal for other languages */ - -void perl_quote_print(FILE *stream, const char *src) -{ - const char sq = '\''; - const char bq = '\\'; - char c; - - fputc(sq, stream); - while ((c = *src++)) { - if (c == sq || c == bq) - fputc(bq, stream); - fputc(c, stream); - } - fputc(sq, stream); -} - -void python_quote_print(FILE *stream, const char *src) -{ - const char sq = '\''; - const char bq = '\\'; - const char nl = '\n'; - char c; - - fputc(sq, stream); - while ((c = *src++)) { - if (c == nl) { - fputc(bq, stream); - fputc('n', stream); - continue; - } - if (c == sq || c == bq) - fputc(bq, stream); - fputc(c, stream); - } - fputc(sq, stream); -} - -void tcl_quote_print(FILE *stream, const char *src) -{ - char c; - - fputc('"', stream); - while ((c = *src++)) { - switch (c) { - case '[': case ']': - case '{': case '}': - case '$': case '\\': case '"': - fputc('\\', stream); - default: - fputc(c, stream); - break; - case '\f': - fputs("\\f", stream); - break; - case '\r': - fputs("\\r", stream); - break; - case '\n': - fputs("\\n", stream); - break; - case '\t': - fputs("\\t", stream); - break; - case '\v': - fputs("\\v", stream); - break; - } - } - fputc('"', stream); -} diff --git a/tools/perf/util/quote.h b/tools/perf/util/quote.h index b6a019733919..172889ea234f 100644 --- a/tools/perf/util/quote.h +++ b/tools/perf/util/quote.h @@ -22,47 +22,8 @@ * * Note that the above examples leak memory! Remember to free result from * sq_quote() in a real application. - * - * sq_quote_buf() writes to an existing buffer of specified size; it - * will return the number of characters that would have been written - * excluding the final null regardless of the buffer size. */ -extern void sq_quote_print(FILE *stream, const char *src); - -extern void sq_quote_buf(struct strbuf *, const char *src); extern void sq_quote_argv(struct strbuf *, const char **argv, size_t maxlen); -/* This unwraps what sq_quote() produces in place, but returns - * NULL if the input does not look like what sq_quote would have - * produced. - */ -extern char *sq_dequote(char *); - -/* - * Same as the above, but can be used to unwrap many arguments in the - * same string separated by space. "next" is changed to point to the - * next argument that should be passed as first parameter. When there - * is no more argument to be dequoted, "next" is updated to point to NULL. - */ -extern char *sq_dequote_step(char *arg, char **next); -extern int sq_dequote_to_argv(char *arg, const char ***argv, int *nr, int *alloc); - -extern int unquote_c_style(struct strbuf *, const char *quoted, const char **endp); -extern size_t quote_c_style(const char *name, struct strbuf *, FILE *, int no_dq); -extern void quote_two_c_style(struct strbuf *, const char *, const char *, int); - -extern void write_name_quoted(const char *name, FILE *, int terminator); -extern void write_name_quotedpfx(const char *pfx, ssize_t pfxlen, - const char *name, FILE *, int terminator); - -/* quote path as relative to the given prefix */ -char *quote_path_relative(const char *in, int len, - struct strbuf *out, const char *prefix); - -/* quoting as a string literal for other languages */ -extern void perl_quote_print(FILE *stream, const char *src); -extern void python_quote_print(FILE *stream, const char *src); -extern void tcl_quote_print(FILE *stream, const char *src); - #endif /* __PERF_QUOTE_H */ diff --git a/tools/perf/util/run-command.c b/tools/perf/util/run-command.c index 2b615acf94d7..da8e9b285f51 100644 --- a/tools/perf/util/run-command.c +++ b/tools/perf/util/run-command.c @@ -212,93 +212,3 @@ int run_command_v_opt(const char **argv, int opt) prepare_run_command_v_opt(&cmd, argv, opt); return run_command(&cmd); } - -int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const char *const *env) -{ - struct child_process cmd; - prepare_run_command_v_opt(&cmd, argv, opt); - cmd.dir = dir; - cmd.env = env; - return run_command(&cmd); -} - -int start_async(struct async *async) -{ - int pipe_out[2]; - - if (pipe(pipe_out) < 0) - return error("cannot create pipe: %s", strerror(errno)); - async->out = pipe_out[0]; - - /* Flush stdio before fork() to avoid cloning buffers */ - fflush(NULL); - - async->pid = fork(); - if (async->pid < 0) { - error("fork (async) failed: %s", strerror(errno)); - close_pair(pipe_out); - return -1; - } - if (!async->pid) { - close(pipe_out[0]); - exit(!!async->proc(pipe_out[1], async->data)); - } - close(pipe_out[1]); - - return 0; -} - -int finish_async(struct async *async) -{ - int ret = 0; - - if (wait_or_whine(async->pid)) - ret = error("waitpid (async) failed"); - - return ret; -} - -int run_hook(const char *index_file, const char *name, ...) -{ - struct child_process hook; - const char **argv = NULL, *env[2]; - char idx[PATH_MAX]; - va_list args; - int ret; - size_t i = 0, alloc = 0; - - if (access(perf_path("hooks/%s", name), X_OK) < 0) - return 0; - - va_start(args, name); - ALLOC_GROW(argv, i + 1, alloc); - argv[i++] = perf_path("hooks/%s", name); - while (argv[i-1]) { - ALLOC_GROW(argv, i + 1, alloc); - argv[i++] = va_arg(args, const char *); - } - va_end(args); - - memset(&hook, 0, sizeof(hook)); - hook.argv = argv; - hook.no_stdin = 1; - hook.stdout_to_stderr = 1; - if (index_file) { - snprintf(idx, sizeof(idx), "PERF_INDEX_FILE=%s", index_file); - env[0] = idx; - env[1] = NULL; - hook.env = env; - } - - ret = start_command(&hook); - free(argv); - if (ret) { - warning("Could not spawn %s", argv[0]); - return ret; - } - ret = finish_command(&hook); - if (ret == -ERR_RUN_COMMAND_WAITPID_SIGNAL) - warning("%s exited due to uncaught signal", argv[0]); - - return ret; -} diff --git a/tools/perf/util/run-command.h b/tools/perf/util/run-command.h index d79028727ce2..1ef264d5069c 100644 --- a/tools/perf/util/run-command.h +++ b/tools/perf/util/run-command.h @@ -50,39 +50,9 @@ int start_command(struct child_process *); int finish_command(struct child_process *); int run_command(struct child_process *); -extern int run_hook(const char *index_file, const char *name, ...); - #define RUN_COMMAND_NO_STDIN 1 #define RUN_PERF_CMD 2 /*If this is to be perf sub-command */ #define RUN_COMMAND_STDOUT_TO_STDERR 4 int run_command_v_opt(const char **argv, int opt); -/* - * env (the environment) is to be formatted like environ: "VAR=VALUE". - * To unset an environment variable use just "VAR". - */ -int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const char *const *env); - -/* - * The purpose of the following functions is to feed a pipe by running - * a function asynchronously and providing output that the caller reads. - * - * It is expected that no synchronization and mutual exclusion between - * the caller and the feed function is necessary so that the function - * can run in a thread without interfering with the caller. - */ -struct async { - /* - * proc writes to fd and closes it; - * returns 0 on success, non-zero on failure - */ - int (*proc)(int fd, void *data); - void *data; - int out; /* caller reads from here and closes it */ - pid_t pid; -}; - -int start_async(struct async *async); -int finish_async(struct async *async); - #endif /* __PERF_RUN_COMMAND_H */ diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 25bfca4f10f0..8f83a1835766 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -5,6 +5,7 @@ #include <byteswap.h> #include <unistd.h> #include <sys/types.h> +#include <sys/mman.h> #include "session.h" #include "sort.h" @@ -894,3 +895,10 @@ size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp) __dsos__fprintf(&self->host_machine.user_dsos, fp) + machines__fprintf_dsos(&self->machines, fp); } + +size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp, + bool with_hits) +{ + size_t ret = machine__fprintf_dsos_buildid(&self->host_machine, fp, with_hits); + return ret + machines__fprintf_dsos_buildid(&self->machines, fp, with_hits); +} diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index e7fce486ebe2..55c6881b218d 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -132,12 +132,8 @@ void perf_session__process_machines(struct perf_session *self, size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp); -static inline -size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp, - bool with_hits) -{ - return machines__fprintf_dsos_buildid(&self->machines, fp, with_hits); -} +size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, + FILE *fp, bool with_hits); static inline size_t perf_session__fprintf_nr_events(struct perf_session *self, FILE *fp) diff --git a/tools/perf/util/sigchain.c b/tools/perf/util/sigchain.c index 1118b99e57d3..ba785e9b1841 100644 --- a/tools/perf/util/sigchain.c +++ b/tools/perf/util/sigchain.c @@ -16,7 +16,7 @@ static void check_signum(int sig) die("BUG: signal out of range: %d", sig); } -int sigchain_push(int sig, sigchain_fun f) +static int sigchain_push(int sig, sigchain_fun f) { struct sigchain_signal *s = signals + sig; check_signum(sig); diff --git a/tools/perf/util/sigchain.h b/tools/perf/util/sigchain.h index 1a53c11265fd..959d64eb5557 100644 --- a/tools/perf/util/sigchain.h +++ b/tools/perf/util/sigchain.h @@ -3,7 +3,6 @@ typedef void (*sigchain_fun)(int); -int sigchain_push(int sig, sigchain_fun f); int sigchain_pop(int sig); void sigchain_push_common(sigchain_fun f); diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index da30b305fba0..2316cb5a4116 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -1,10 +1,10 @@ #include "sort.h" regex_t parent_regex; -char default_parent_pattern[] = "^sys_|^do_page_fault"; -char *parent_pattern = default_parent_pattern; -char default_sort_order[] = "comm,dso,symbol"; -char *sort_order = default_sort_order; +const char default_parent_pattern[] = "^sys_|^do_page_fault"; +const char *parent_pattern = default_parent_pattern; +const char default_sort_order[] = "comm,dso,symbol"; +const char *sort_order = default_sort_order; int sort__need_collapse = 0; int sort__has_parent = 0; diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index eab2e0b3b74e..0d61c4082f43 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -25,10 +25,10 @@ #include "sort.h" extern regex_t parent_regex; -extern char *sort_order; -extern char default_parent_pattern[]; -extern char *parent_pattern; -extern char default_sort_order[]; +extern const char *sort_order; +extern const char default_parent_pattern[]; +extern const char *parent_pattern; +extern const char default_sort_order[]; extern int sort__need_collapse; extern int sort__has_parent; extern char *field_sep; diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c index 5249d5a1b0c2..92e068517c1a 100644 --- a/tools/perf/util/strbuf.c +++ b/tools/perf/util/strbuf.c @@ -41,16 +41,6 @@ char *strbuf_detach(struct strbuf *sb, size_t *sz) return res; } -void strbuf_attach(struct strbuf *sb, void *buf, size_t len, size_t alloc) -{ - strbuf_release(sb); - sb->buf = buf; - sb->len = len; - sb->alloc = alloc; - strbuf_grow(sb, 0); - sb->buf[sb->len] = '\0'; -} - void strbuf_grow(struct strbuf *sb, size_t extra) { if (sb->len + extra + 1 <= sb->len) @@ -60,94 +50,7 @@ void strbuf_grow(struct strbuf *sb, size_t extra) ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc); } -void strbuf_trim(struct strbuf *sb) -{ - char *b = sb->buf; - while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1])) - sb->len--; - while (sb->len > 0 && isspace(*b)) { - b++; - sb->len--; - } - memmove(sb->buf, b, sb->len); - sb->buf[sb->len] = '\0'; -} -void strbuf_rtrim(struct strbuf *sb) -{ - while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1])) - sb->len--; - sb->buf[sb->len] = '\0'; -} - -void strbuf_ltrim(struct strbuf *sb) -{ - char *b = sb->buf; - while (sb->len > 0 && isspace(*b)) { - b++; - sb->len--; - } - memmove(sb->buf, b, sb->len); - sb->buf[sb->len] = '\0'; -} - -void strbuf_tolower(struct strbuf *sb) -{ - unsigned int i; - - for (i = 0; i < sb->len; i++) - sb->buf[i] = tolower(sb->buf[i]); -} - -struct strbuf **strbuf_split(const struct strbuf *sb, int delim) -{ - int alloc = 2, pos = 0; - char *n, *p; - struct strbuf **ret; - struct strbuf *t; - - ret = calloc(alloc, sizeof(struct strbuf *)); - p = n = sb->buf; - while (n < sb->buf + sb->len) { - int len; - n = memchr(n, delim, sb->len - (n - sb->buf)); - if (pos + 1 >= alloc) { - alloc = alloc * 2; - ret = realloc(ret, sizeof(struct strbuf *) * alloc); - } - if (!n) - n = sb->buf + sb->len - 1; - len = n - p + 1; - t = malloc(sizeof(struct strbuf)); - strbuf_init(t, len); - strbuf_add(t, p, len); - ret[pos] = t; - ret[++pos] = NULL; - p = ++n; - } - return ret; -} - -void strbuf_list_free(struct strbuf **sbs) -{ - struct strbuf **s = sbs; - - while (*s) { - strbuf_release(*s); - free(*s++); - } - free(sbs); -} - -int strbuf_cmp(const struct strbuf *a, const struct strbuf *b) -{ - int len = a->len < b->len ? a->len: b->len; - int cmp = memcmp(a->buf, b->buf, len); - if (cmp) - return cmp; - return a->len < b->len ? -1: a->len != b->len; -} - -void strbuf_splice(struct strbuf *sb, size_t pos, size_t len, +static void strbuf_splice(struct strbuf *sb, size_t pos, size_t len, const void *data, size_t dlen) { if (pos + len < pos) @@ -166,11 +69,6 @@ void strbuf_splice(struct strbuf *sb, size_t pos, size_t len, strbuf_setlen(sb, sb->len + dlen - len); } -void strbuf_insert(struct strbuf *sb, size_t pos, const void *data, size_t len) -{ - strbuf_splice(sb, pos, 0, data, len); -} - void strbuf_remove(struct strbuf *sb, size_t pos, size_t len) { strbuf_splice(sb, pos, len, NULL, 0); @@ -183,13 +81,6 @@ void strbuf_add(struct strbuf *sb, const void *data, size_t len) strbuf_setlen(sb, sb->len + len); } -void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len) -{ - strbuf_grow(sb, len); - memcpy(sb->buf + sb->len, sb->buf + pos, len); - strbuf_setlen(sb, sb->len + len); -} - void strbuf_addf(struct strbuf *sb, const char *fmt, ...) { int len; @@ -214,57 +105,6 @@ void strbuf_addf(struct strbuf *sb, const char *fmt, ...) strbuf_setlen(sb, sb->len + len); } -void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn, - void *context) -{ - for (;;) { - const char *percent; - size_t consumed; - - percent = strchrnul(format, '%'); - strbuf_add(sb, format, percent - format); - if (!*percent) - break; - format = percent + 1; - - consumed = fn(sb, format, context); - if (consumed) - format += consumed; - else - strbuf_addch(sb, '%'); - } -} - -size_t strbuf_expand_dict_cb(struct strbuf *sb, const char *placeholder, - void *context) -{ - struct strbuf_expand_dict_entry *e = context; - size_t len; - - for (; e->placeholder && (len = strlen(e->placeholder)); e++) { - if (!strncmp(placeholder, e->placeholder, len)) { - if (e->value) - strbuf_addstr(sb, e->value); - return len; - } - } - return 0; -} - -size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f) -{ - size_t res; - size_t oldalloc = sb->alloc; - - strbuf_grow(sb, size); - res = fread(sb->buf + sb->len, 1, size, f); - if (res > 0) - strbuf_setlen(sb, sb->len + res); - else if (oldalloc == 0) - strbuf_release(sb); - return res; -} - ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint) { size_t oldlen = sb->len; @@ -291,70 +131,3 @@ ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint) sb->buf[sb->len] = '\0'; return sb->len - oldlen; } - -#define STRBUF_MAXLINK (2*PATH_MAX) - -int strbuf_readlink(struct strbuf *sb, const char *path, ssize_t hint) -{ - size_t oldalloc = sb->alloc; - - if (hint < 32) - hint = 32; - - while (hint < STRBUF_MAXLINK) { - ssize_t len; - - strbuf_grow(sb, hint); - len = readlink(path, sb->buf, hint); - if (len < 0) { - if (errno != ERANGE) - break; - } else if (len < hint) { - strbuf_setlen(sb, len); - return 0; - } - - /* .. the buffer was too small - try again */ - hint *= 2; - } - if (oldalloc == 0) - strbuf_release(sb); - return -1; -} - -int strbuf_getline(struct strbuf *sb, FILE *fp, int term) -{ - int ch; - - strbuf_grow(sb, 0); - if (feof(fp)) - return EOF; - - strbuf_reset(sb); - while ((ch = fgetc(fp)) != EOF) { - if (ch == term) - break; - strbuf_grow(sb, 1); - sb->buf[sb->len++] = ch; - } - if (ch == EOF && sb->len == 0) - return EOF; - - sb->buf[sb->len] = '\0'; - return 0; -} - -int strbuf_read_file(struct strbuf *sb, const char *path, ssize_t hint) -{ - int fd, len; - - fd = open(path, O_RDONLY); - if (fd < 0) - return -1; - len = strbuf_read(sb, fd, hint); - close(fd); - if (len < 0) - return -1; - - return len; -} diff --git a/tools/perf/util/strbuf.h b/tools/perf/util/strbuf.h index a3d121d6c83e..436ac319f6c7 100644 --- a/tools/perf/util/strbuf.h +++ b/tools/perf/util/strbuf.h @@ -53,12 +53,6 @@ struct strbuf { extern void strbuf_init(struct strbuf *buf, ssize_t hint); extern void strbuf_release(struct strbuf *); extern char *strbuf_detach(struct strbuf *, size_t *); -extern void strbuf_attach(struct strbuf *, void *, size_t, size_t); -static inline void strbuf_swap(struct strbuf *a, struct strbuf *b) { - struct strbuf tmp = *a; - *a = *b; - *b = tmp; -} /*----- strbuf size related -----*/ static inline ssize_t strbuf_avail(const struct strbuf *sb) { @@ -74,17 +68,6 @@ static inline void strbuf_setlen(struct strbuf *sb, size_t len) { sb->len = len; sb->buf[len] = '\0'; } -#define strbuf_reset(sb) strbuf_setlen(sb, 0) - -/*----- content related -----*/ -extern void strbuf_trim(struct strbuf *); -extern void strbuf_rtrim(struct strbuf *); -extern void strbuf_ltrim(struct strbuf *); -extern int strbuf_cmp(const struct strbuf *, const struct strbuf *); -extern void strbuf_tolower(struct strbuf *); - -extern struct strbuf **strbuf_split(const struct strbuf *, int delim); -extern void strbuf_list_free(struct strbuf **); /*----- add data in your buffer -----*/ static inline void strbuf_addch(struct strbuf *sb, int c) { @@ -93,45 +76,17 @@ static inline void strbuf_addch(struct strbuf *sb, int c) { sb->buf[sb->len] = '\0'; } -extern void strbuf_insert(struct strbuf *, size_t pos, const void *, size_t); extern void strbuf_remove(struct strbuf *, size_t pos, size_t len); -/* splice pos..pos+len with given data */ -extern void strbuf_splice(struct strbuf *, size_t pos, size_t len, - const void *, size_t); - extern void strbuf_add(struct strbuf *, const void *, size_t); static inline void strbuf_addstr(struct strbuf *sb, const char *s) { strbuf_add(sb, s, strlen(s)); } -static inline void strbuf_addbuf(struct strbuf *sb, const struct strbuf *sb2) { - strbuf_add(sb, sb2->buf, sb2->len); -} -extern void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len); - -typedef size_t (*expand_fn_t) (struct strbuf *sb, const char *placeholder, void *context); -extern void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn, void *context); -struct strbuf_expand_dict_entry { - const char *placeholder; - const char *value; -}; -extern size_t strbuf_expand_dict_cb(struct strbuf *sb, const char *placeholder, void *context); __attribute__((format(printf,2,3))) extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...); -extern size_t strbuf_fread(struct strbuf *, size_t, FILE *); /* XXX: if read fails, any partial read is undone */ extern ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint); -extern int strbuf_read_file(struct strbuf *sb, const char *path, ssize_t hint); -extern int strbuf_readlink(struct strbuf *sb, const char *path, ssize_t hint); - -extern int strbuf_getline(struct strbuf *, FILE *, int); - -extern void stripspace(struct strbuf *buf, int skip_comments); -extern int launch_editor(const char *path, struct strbuf *buffer, const char *const *env); - -extern int strbuf_branchname(struct strbuf *sb, const char *name); -extern int strbuf_check_branch_ref(struct strbuf *sb, const char *name); #endif /* __PERF_STRBUF_H */ diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index ecccc8df128e..aaa51ba147df 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -11,6 +11,7 @@ #include <sys/param.h> #include <fcntl.h> #include <unistd.h> +#include "build-id.h" #include "symbol.h" #include "strlist.h" @@ -525,7 +526,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, curr_map = map_groups__find_by_name(kmaps, map->type, module); if (curr_map == NULL) { - pr_err("%s/proc/{kallsyms,modules} " + pr_debug("%s/proc/{kallsyms,modules} " "inconsistency while looking " "for \"%s\" module!\n", machine->root_dir, module); @@ -1131,6 +1132,10 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits) list_for_each_entry(pos, head, node) { if (with_hits && !pos->hit) continue; + if (pos->has_build_id) { + have_build_id = true; + continue; + } if (filename__read_build_id(pos->long_name, pos->build_id, sizeof(pos->build_id)) > 0) { have_build_id = true; @@ -1289,7 +1294,6 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) int size = PATH_MAX; char *name; u8 build_id[BUILD_ID_SIZE]; - char build_id_hex[BUILD_ID_SIZE * 2 + 1]; int ret = -1; int fd; struct machine *machine; @@ -1321,15 +1325,8 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) } self->origin = DSO__ORIG_BUILD_ID_CACHE; - - if (self->has_build_id) { - build_id__sprintf(self->build_id, sizeof(self->build_id), - build_id_hex); - snprintf(name, size, "%s/%s/.build-id/%.2s/%s", - getenv("HOME"), DEBUG_CACHE_DIR, - build_id_hex, build_id_hex + 2); + if (dso__build_id_filename(self, name, size) != NULL) goto open_file; - } more: do { self->origin++; @@ -1345,6 +1342,7 @@ more: case DSO__ORIG_BUILDID: if (filename__read_build_id(self->long_name, build_id, sizeof(build_id))) { + char build_id_hex[BUILD_ID_SIZE * 2 + 1]; build_id__sprintf(build_id, sizeof(build_id), build_id_hex); snprintf(name, size, @@ -1933,6 +1931,12 @@ static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, return ret; } +size_t machine__fprintf_dsos_buildid(struct machine *self, FILE *fp, bool with_hits) +{ + return __dsos__fprintf_buildid(&self->kernel_dsos, fp, with_hits) + + __dsos__fprintf_buildid(&self->user_dsos, fp, with_hits); +} + size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_hits) { struct rb_node *nd; @@ -1940,8 +1944,7 @@ size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_ for (nd = rb_first(self); nd; nd = rb_next(nd)) { struct machine *pos = rb_entry(nd, struct machine, rb_node); - ret += __dsos__fprintf_buildid(&pos->kernel_dsos, fp, with_hits); - ret += __dsos__fprintf_buildid(&pos->user_dsos, fp, with_hits); + ret += machine__fprintf_dsos_buildid(pos, fp, with_hits); } return ret; } diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 6389d1acaf81..5d25b5eb1456 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -78,7 +78,7 @@ struct symbol_conf { *default_guest_kallsyms, *default_guest_modules; const char *guestmount; - char *dso_list_str, + const char *dso_list_str, *comm_list_str, *sym_list_str, *col_width_list_str; @@ -170,6 +170,7 @@ int machine__load_vmlinux_path(struct machine *self, enum map_type type, size_t __dsos__fprintf(struct list_head *head, FILE *fp); +size_t machine__fprintf_dsos_buildid(struct machine *self, FILE *fp, bool with_hits); size_t machines__fprintf_dsos(struct rb_root *self, FILE *fp); size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_hits); diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 069f261b225c..73a02223c629 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -1937,7 +1937,7 @@ void *raw_field_ptr(struct event *event, const char *name, void *data) if (!field) return NULL; - if (field->flags & FIELD_IS_STRING) { + if (field->flags & FIELD_IS_DYNAMIC) { int offset; offset = *(int *)(data + field->offset); diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c index cb54cd002f49..f55cc3a765a1 100644 --- a/tools/perf/util/trace-event-read.c +++ b/tools/perf/util/trace-event-read.c @@ -53,12 +53,6 @@ static unsigned long page_size; static ssize_t calc_data_size; static bool repipe; -/* If it fails, the next read will report it */ -static void skip(int size) -{ - lseek(input_fd, size, SEEK_CUR); -} - static int do_read(int fd, void *buf, int size) { int rsize = size; @@ -98,6 +92,19 @@ static int read_or_die(void *data, int size) return r; } +/* If it fails, the next read will report it */ +static void skip(int size) +{ + char buf[BUFSIZ]; + int r; + + while (size) { + r = size > BUFSIZ ? BUFSIZ : size; + read_or_die(buf, r); + size -= r; + }; +} + static unsigned int read4(void) { unsigned int data; diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index 406d452956db..b3e86b1e4444 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h @@ -233,7 +233,12 @@ static inline unsigned long long __data2host8(unsigned long long data) #define data2host2(ptr) __data2host2(*(unsigned short *)ptr) #define data2host4(ptr) __data2host4(*(unsigned int *)ptr) -#define data2host8(ptr) __data2host8(*(unsigned long long *)ptr) +#define data2host8(ptr) ({ \ + unsigned long long __val; \ + \ + memcpy(&__val, (ptr), sizeof(unsigned long long)); \ + __data2host8(__val); \ +}) extern int header_page_ts_offset; extern int header_page_ts_size; diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 0795bf304b19..45b9655f3a5c 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -152,7 +152,6 @@ extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2))) extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN); extern int prefixcmp(const char *str, const char *prefix); -extern time_t tm_to_time_t(const struct tm *tm); static inline const char *skip_prefix(const char *str, const char *prefix) { @@ -160,119 +159,6 @@ static inline const char *skip_prefix(const char *str, const char *prefix) return strncmp(str, prefix, len) ? NULL : str + len; } -#if defined(NO_MMAP) || defined(USE_WIN32_MMAP) - -#ifndef PROT_READ -#define PROT_READ 1 -#define PROT_WRITE 2 -#define MAP_PRIVATE 1 -#define MAP_FAILED ((void*)-1) -#endif - -#define mmap git_mmap -#define munmap git_munmap -extern void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset); -extern int git_munmap(void *start, size_t length); - -#else /* NO_MMAP || USE_WIN32_MMAP */ - -#include <sys/mman.h> - -#endif /* NO_MMAP || USE_WIN32_MMAP */ - -#ifdef NO_MMAP - -/* This value must be multiple of (pagesize * 2) */ -#define DEFAULT_PACKED_GIT_WINDOW_SIZE (1 * 1024 * 1024) - -#else /* NO_MMAP */ - -/* This value must be multiple of (pagesize * 2) */ -#define DEFAULT_PACKED_GIT_WINDOW_SIZE \ - (sizeof(void*) >= 8 \ - ? 1 * 1024 * 1024 * 1024 \ - : 32 * 1024 * 1024) - -#endif /* NO_MMAP */ - -#ifdef NO_ST_BLOCKS_IN_STRUCT_STAT -#define on_disk_bytes(st) ((st).st_size) -#else -#define on_disk_bytes(st) ((st).st_blocks * 512) -#endif - -#define DEFAULT_PACKED_GIT_LIMIT \ - ((1024L * 1024L) * (sizeof(void*) >= 8 ? 8192 : 256)) - -#ifdef NO_PREAD -#define pread git_pread -extern ssize_t git_pread(int fd, void *buf, size_t count, off_t offset); -#endif -/* - * Forward decl that will remind us if its twin in cache.h changes. - * This function is used in compat/pread.c. But we can't include - * cache.h there. - */ -extern ssize_t read_in_full(int fd, void *buf, size_t count); - -#ifdef NO_SETENV -#define setenv gitsetenv -extern int gitsetenv(const char *, const char *, int); -#endif - -#ifdef NO_MKDTEMP -#define mkdtemp gitmkdtemp -extern char *gitmkdtemp(char *); -#endif - -#ifdef NO_UNSETENV -#define unsetenv gitunsetenv -extern void gitunsetenv(const char *); -#endif - -#ifdef NO_STRCASESTR -#define strcasestr gitstrcasestr -extern char *gitstrcasestr(const char *haystack, const char *needle); -#endif - -#ifdef NO_STRLCPY -#define strlcpy gitstrlcpy -extern size_t gitstrlcpy(char *, const char *, size_t); -#endif - -#ifdef NO_STRTOUMAX -#define strtoumax gitstrtoumax -extern uintmax_t gitstrtoumax(const char *, char **, int); -#endif - -#ifdef NO_HSTRERROR -#define hstrerror githstrerror -extern const char *githstrerror(int herror); -#endif - -#ifdef NO_MEMMEM -#define memmem gitmemmem -void *gitmemmem(const void *haystack, size_t haystacklen, - const void *needle, size_t needlelen); -#endif - -#ifdef FREAD_READS_DIRECTORIES -#ifdef fopen -#undef fopen -#endif -#define fopen(a,b) git_fopen(a,b) -extern FILE *git_fopen(const char*, const char*); -#endif - -#ifdef SNPRINTF_RETURNS_BOGUS -#define snprintf git_snprintf -extern int git_snprintf(char *str, size_t maxsize, - const char *format, ...); -#define vsnprintf git_vsnprintf -extern int git_vsnprintf(char *str, size_t maxsize, - const char *format, va_list ap); -#endif - #ifdef __GLIBC_PREREQ #if __GLIBC_PREREQ(2, 1) #define HAVE_STRCHRNUL @@ -293,28 +179,14 @@ static inline char *gitstrchrnul(const char *s, int c) * Wrappers: */ extern char *xstrdup(const char *str); -extern void *xmalloc(size_t size) __attribute__((weak)); -extern void *xmemdupz(const void *data, size_t len); -extern char *xstrndup(const char *str, size_t len); extern void *xrealloc(void *ptr, size_t size) __attribute__((weak)); -static inline void *xzalloc(size_t size) -{ - void *buf = xmalloc(size); - - return memset(buf, 0, size); -} static inline void *zalloc(size_t size) { return calloc(1, size); } -static inline size_t xsize_t(off_t len) -{ - return (size_t)len; -} - static inline int has_extension(const char *filename, const char *ext) { size_t len = strlen(filename); @@ -351,8 +223,6 @@ extern unsigned char sane_ctype[256]; #define isalpha(x) sane_istest(x,GIT_ALPHA) #define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT) #define isprint(x) sane_istest(x,GIT_PRINT) -#define is_glob_special(x) sane_istest(x,GIT_GLOB_SPECIAL) -#define is_regex_special(x) sane_istest(x,GIT_GLOB_SPECIAL | GIT_REGEX_SPECIAL) #define tolower(x) sane_case((unsigned char)(x), 0x20) #define toupper(x) sane_case((unsigned char)(x), 0) @@ -363,38 +233,6 @@ static inline int sane_case(int x, int high) return x; } -static inline int strtoul_ui(char const *s, int base, unsigned int *result) -{ - unsigned long ul; - char *p; - - errno = 0; - ul = strtoul(s, &p, base); - if (errno || *p || p == s || (unsigned int) ul != ul) - return -1; - *result = ul; - return 0; -} - -static inline int strtol_i(char const *s, int base, int *result) -{ - long ul; - char *p; - - errno = 0; - ul = strtol(s, &p, base); - if (errno || *p || p == s || (int) ul != ul) - return -1; - *result = ul; - return 0; -} - -#ifdef INTERNAL_QSORT -void git_qsort(void *base, size_t nmemb, size_t size, - int(*compar)(const void *, const void *)); -#define qsort git_qsort -#endif - #ifndef DIR_HAS_BSD_GROUP_SEMANTICS # define FORCE_DIR_SET_GID S_ISGID #else diff --git a/tools/perf/util/wrapper.c b/tools/perf/util/wrapper.c index bf44ca85d23b..73e900edb5a2 100644 --- a/tools/perf/util/wrapper.c +++ b/tools/perf/util/wrapper.c @@ -23,46 +23,6 @@ char *xstrdup(const char *str) return ret; } -void *xmalloc(size_t size) -{ - void *ret = malloc(size); - if (!ret && !size) - ret = malloc(1); - if (!ret) { - release_pack_memory(size, -1); - ret = malloc(size); - if (!ret && !size) - ret = malloc(1); - if (!ret) - die("Out of memory, malloc failed"); - } -#ifdef XMALLOC_POISON - memset(ret, 0xA5, size); -#endif - return ret; -} - -/* - * xmemdupz() allocates (len + 1) bytes of memory, duplicates "len" bytes of - * "data" to the allocated memory, zero terminates the allocated memory, - * and returns a pointer to the allocated memory. If the allocation fails, - * the program dies. - */ -void *xmemdupz(const void *data, size_t len) -{ - char *p = xmalloc(len + 1); - memcpy(p, data, len); - p[len] = '\0'; - return p; -} - -char *xstrndup(const char *str, size_t len) -{ - char *p = memchr(str, '\0', len); - - return xmemdupz(str, p ? (size_t)(p - str) : len); -} - void *xrealloc(void *ptr, size_t size) { void *ret = realloc(ptr, size); @@ -78,73 +38,3 @@ void *xrealloc(void *ptr, size_t size) } return ret; } - -/* - * xread() is the same a read(), but it automatically restarts read() - * operations with a recoverable error (EAGAIN and EINTR). xread() - * DOES NOT GUARANTEE that "len" bytes is read even if the data is available. - */ -static ssize_t xread(int fd, void *buf, size_t len) -{ - ssize_t nr; - while (1) { - nr = read(fd, buf, len); - if ((nr < 0) && (errno == EAGAIN || errno == EINTR)) - continue; - return nr; - } -} - -/* - * xwrite() is the same a write(), but it automatically restarts write() - * operations with a recoverable error (EAGAIN and EINTR). xwrite() DOES NOT - * GUARANTEE that "len" bytes is written even if the operation is successful. - */ -static ssize_t xwrite(int fd, const void *buf, size_t len) -{ - ssize_t nr; - while (1) { - nr = write(fd, buf, len); - if ((nr < 0) && (errno == EAGAIN || errno == EINTR)) - continue; - return nr; - } -} - -ssize_t read_in_full(int fd, void *buf, size_t count) -{ - char *p = buf; - ssize_t total = 0; - - while (count > 0) { - ssize_t loaded = xread(fd, p, count); - if (loaded <= 0) - return total ? total : loaded; - count -= loaded; - p += loaded; - total += loaded; - } - - return total; -} - -ssize_t write_in_full(int fd, const void *buf, size_t count) -{ - const char *p = buf; - ssize_t total = 0; - - while (count > 0) { - ssize_t written = xwrite(fd, p, count); - if (written < 0) - return -1; - if (!written) { - errno = ENOSPC; - return -1; - } - count -= written; - p += written; - total += written; - } - - return total; -} |