From a3da8e451321c31d88cebd12c234d0aac2a1cc35 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 6 Nov 2010 11:47:24 +0300 Subject: perf, ui: Eliminate stack-smashing protection compiler complaint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The gcc complains about small auto-var strings being allocated from stack space. Make them const to avoid this: | CC util/ui/util.o | cc1: warnings being treated as errors | util/ui/util.c: In function ‘ui__dialog_yesno’: | util/ui/util.c:108: error: not protecting function: no buffer at least 8 bytes long | make: *** [util/ui/util.o] Error 1 The real bug is in the newtWinChoice() ABI - but that's an externality we cannot fix here, so we use this workaround. Signed-off-by: Cyrill Gorcunov Acked-by: Frédéric Weisbecker Cc: Arnaldo Carvalho de Melo LKML-Reference: <20101106084724.GA5956@lenovo> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/ui/util.c b/tools/perf/util/ui/util.c index 9706d9d..056c695 100644 --- a/tools/perf/util/ui/util.c +++ b/tools/perf/util/ui/util.c @@ -104,9 +104,10 @@ out_destroy_form: return rc; } +static const char yes[] = "Yes", no[] = "No"; + bool ui__dialog_yesno(const char *msg) { /* newtWinChoice should really be accepting const char pointers... */ - char yes[] = "Yes", no[] = "No"; - return newtWinChoice(NULL, yes, no, (char *)msg) == 1; + return newtWinChoice(NULL, (char *)yes, (char *)no, (char *)msg) == 1; } -- cgit v0.10.2 From 01797c599816d39dfea47864c0f90cd50845811f Mon Sep 17 00:00:00 2001 From: Corey Ashford Date: Mon, 8 Nov 2010 18:20:45 -0800 Subject: perf: Fix usages of profile_cpu in builtin-top.c to use cpu_list profile_cpu was left over from an earlier implementation that supported running perf top on a single CPU. profile_cpu was no longer set by any switch and usages of it resulted in dead code. Instead, convert the code to use cpu_list, which is set by the -C option. Also improved the printing of nr_cpus and cpu_list by correcting the plurals. Signed-off-by: Corey Ashford Cc: a.p.zijlstra@chello.nl Cc: acme@redhat.com LKML-Reference: <1289269245-9388-1-git-send-email-cjashfor@linux.vnet.ibm.com> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index b513e40..dd62580 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -69,7 +69,6 @@ static int target_tid = -1; static pid_t *all_tids = NULL; static int thread_num = 0; static bool inherit = false; -static int profile_cpu = -1; static int nr_cpus = 0; static int realtime_prio = 0; static bool group = false; @@ -558,13 +557,13 @@ static void print_sym_table(void) else printf(" (all"); - if (profile_cpu != -1) - printf(", cpu: %d)\n", profile_cpu); + if (cpu_list) + printf(", CPU%s: %s)\n", nr_cpus > 1 ? "s" : "", cpu_list); else { if (target_tid != -1) printf(")\n"); else - printf(", %d CPUs)\n", nr_cpus); + printf(", %d CPU%s)\n", nr_cpus, nr_cpus > 1 ? "s" : ""); } printf("%-*.*s\n", win_width, win_width, graph_dotted_line); @@ -1187,11 +1186,10 @@ int group_fd; static void start_counter(int i, int counter) { struct perf_event_attr *attr; - int cpu; + int cpu = -1; int thread_index; - cpu = profile_cpu; - if (target_tid == -1 && profile_cpu == -1) + if (target_tid == -1) cpu = cpumap[i]; attr = attrs + counter; -- cgit v0.10.2 From e8719adf30c136319a77824d032b3a185148f8f9 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Wed, 10 Nov 2010 07:52:32 -0600 Subject: perf trace scripting: fix some small memory leaks and missing error checks Free the other two fields of script_desc which somehow got overlooked, free malloc'ed args in case exec fails, and add missing checks for failed mallocs. Signed-off-by: Tom Zanussi Acked-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 2f8df45..368e624 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -337,6 +337,8 @@ static struct script_desc *script_desc__new(const char *name) static void script_desc__delete(struct script_desc *s) { free(s->name); + free(s->half_liner); + free(s->args); free(s); } @@ -626,6 +628,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used) close(live_pipe[0]); __argv = malloc(6 * sizeof(const char *)); + if (!__argv) + die("malloc"); + __argv[0] = "/bin/sh"; __argv[1] = record_script_path; __argv[2] = "-q"; @@ -634,6 +639,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used) __argv[5] = NULL; execvp("/bin/sh", (char **)__argv); + free(__argv); exit(-1); } @@ -641,6 +647,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used) close(live_pipe[1]); __argv = malloc((argc + 3) * sizeof(const char *)); + if (!__argv) + die("malloc"); __argv[0] = "/bin/sh"; __argv[1] = report_script_path; for (i = 2; i < argc; i++) @@ -650,6 +658,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used) __argv[i++] = NULL; execvp("/bin/sh", (char **)__argv); + free(__argv); exit(-1); } @@ -661,6 +670,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used) } __argv = malloc((argc + 1) * sizeof(const char *)); + if (!__argv) + die("malloc"); __argv[0] = "/bin/sh"; __argv[1] = script_path; for (i = 3; i < argc; i++) @@ -668,6 +679,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used) __argv[argc - 1] = NULL; execvp("/bin/sh", (char **)__argv); + free(__argv); exit(-1); } -- cgit v0.10.2 From b0b6d914e2b7e0a736635515e87be718050c17c8 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Wed, 10 Nov 2010 08:08:20 -0600 Subject: perf trace scripting: remove system-wide param from shell scripts Including -a unconditionally when recording doesn't allow for the option of running scripts without it. Future patches will add add it back if needed at run-time. Signed-off-by: Tom Zanussi Acked-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/scripts/perl/bin/failed-syscalls-record b/tools/perf/scripts/perl/bin/failed-syscalls-record index eb5846b..8104895 100644 --- a/tools/perf/scripts/perl/bin/failed-syscalls-record +++ b/tools/perf/scripts/perl/bin/failed-syscalls-record @@ -1,2 +1,2 @@ #!/bin/bash -perf record -a -e raw_syscalls:sys_exit $@ +perf record -e raw_syscalls:sys_exit $@ diff --git a/tools/perf/scripts/perl/bin/rw-by-file-record b/tools/perf/scripts/perl/bin/rw-by-file-record index 5bfaae5..33efc86 100644 --- a/tools/perf/scripts/perl/bin/rw-by-file-record +++ b/tools/perf/scripts/perl/bin/rw-by-file-record @@ -1,3 +1,3 @@ #!/bin/bash -perf record -a -e syscalls:sys_enter_read -e syscalls:sys_enter_write $@ +perf record -e syscalls:sys_enter_read -e syscalls:sys_enter_write $@ diff --git a/tools/perf/scripts/perl/bin/rw-by-pid-record b/tools/perf/scripts/perl/bin/rw-by-pid-record index 6e0b2f7..7cb9db2 100644 --- a/tools/perf/scripts/perl/bin/rw-by-pid-record +++ b/tools/perf/scripts/perl/bin/rw-by-pid-record @@ -1,2 +1,2 @@ #!/bin/bash -perf record -a -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write $@ +perf record -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write $@ diff --git a/tools/perf/scripts/perl/bin/rwtop-record b/tools/perf/scripts/perl/bin/rwtop-record index 6e0b2f7..7cb9db2 100644 --- a/tools/perf/scripts/perl/bin/rwtop-record +++ b/tools/perf/scripts/perl/bin/rwtop-record @@ -1,2 +1,2 @@ #!/bin/bash -perf record -a -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write $@ +perf record -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write $@ diff --git a/tools/perf/scripts/perl/bin/wakeup-latency-record b/tools/perf/scripts/perl/bin/wakeup-latency-record index 9f2acaa..464251a 100644 --- a/tools/perf/scripts/perl/bin/wakeup-latency-record +++ b/tools/perf/scripts/perl/bin/wakeup-latency-record @@ -1,5 +1,5 @@ #!/bin/bash -perf record -a -e sched:sched_switch -e sched:sched_wakeup $@ +perf record -e sched:sched_switch -e sched:sched_wakeup $@ diff --git a/tools/perf/scripts/perl/bin/workqueue-stats-record b/tools/perf/scripts/perl/bin/workqueue-stats-record index 85301f2..8edda90 100644 --- a/tools/perf/scripts/perl/bin/workqueue-stats-record +++ b/tools/perf/scripts/perl/bin/workqueue-stats-record @@ -1,2 +1,2 @@ #!/bin/bash -perf record -a -e workqueue:workqueue_creation -e workqueue:workqueue_destruction -e workqueue:workqueue_execution -e workqueue:workqueue_insertion $@ +perf record -e workqueue:workqueue_creation -e workqueue:workqueue_destruction -e workqueue:workqueue_execution -e workqueue:workqueue_insertion $@ diff --git a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record index eb5846b..8104895 100644 --- a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record +++ b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record @@ -1,2 +1,2 @@ #!/bin/bash -perf record -a -e raw_syscalls:sys_exit $@ +perf record -e raw_syscalls:sys_exit $@ diff --git a/tools/perf/scripts/python/bin/futex-contention-record b/tools/perf/scripts/python/bin/futex-contention-record index 5ecbb43..b1495c9 100644 --- a/tools/perf/scripts/python/bin/futex-contention-record +++ b/tools/perf/scripts/python/bin/futex-contention-record @@ -1,2 +1,2 @@ #!/bin/bash -perf record -a -e syscalls:sys_enter_futex -e syscalls:sys_exit_futex $@ +perf record -e syscalls:sys_enter_futex -e syscalls:sys_exit_futex $@ diff --git a/tools/perf/scripts/python/bin/netdev-times-record b/tools/perf/scripts/python/bin/netdev-times-record index d931a82..558754b 100644 --- a/tools/perf/scripts/python/bin/netdev-times-record +++ b/tools/perf/scripts/python/bin/netdev-times-record @@ -1,5 +1,5 @@ #!/bin/bash -perf record -a -e net:net_dev_xmit -e net:net_dev_queue \ +perf record -e net:net_dev_xmit -e net:net_dev_queue \ -e net:netif_receive_skb -e net:netif_rx \ -e skb:consume_skb -e skb:kfree_skb \ -e skb:skb_copy_datagram_iovec -e napi:napi_poll \ diff --git a/tools/perf/scripts/python/bin/sched-migration-record b/tools/perf/scripts/python/bin/sched-migration-record index 17a3e9b..7493fdd 100644 --- a/tools/perf/scripts/python/bin/sched-migration-record +++ b/tools/perf/scripts/python/bin/sched-migration-record @@ -1,2 +1,2 @@ #!/bin/bash -perf record -m 16384 -a -e sched:sched_wakeup -e sched:sched_wakeup_new -e sched:sched_switch -e sched:sched_migrate_task $@ +perf record -m 16384 -e sched:sched_wakeup -e sched:sched_wakeup_new -e sched:sched_switch -e sched:sched_migrate_task $@ diff --git a/tools/perf/scripts/python/bin/sctop-record b/tools/perf/scripts/python/bin/sctop-record index 1fc5998..4efbfaa 100644 --- a/tools/perf/scripts/python/bin/sctop-record +++ b/tools/perf/scripts/python/bin/sctop-record @@ -1,2 +1,2 @@ #!/bin/bash -perf record -a -e raw_syscalls:sys_enter $@ +perf record -e raw_syscalls:sys_enter $@ diff --git a/tools/perf/scripts/python/bin/syscall-counts-by-pid-record b/tools/perf/scripts/python/bin/syscall-counts-by-pid-record index 1fc5998..4efbfaa 100644 --- a/tools/perf/scripts/python/bin/syscall-counts-by-pid-record +++ b/tools/perf/scripts/python/bin/syscall-counts-by-pid-record @@ -1,2 +1,2 @@ #!/bin/bash -perf record -a -e raw_syscalls:sys_enter $@ +perf record -e raw_syscalls:sys_enter $@ diff --git a/tools/perf/scripts/python/bin/syscall-counts-record b/tools/perf/scripts/python/bin/syscall-counts-record index 1fc5998..4efbfaa 100644 --- a/tools/perf/scripts/python/bin/syscall-counts-record +++ b/tools/perf/scripts/python/bin/syscall-counts-record @@ -1,2 +1,2 @@ #!/bin/bash -perf record -a -e raw_syscalls:sys_enter $@ +perf record -e raw_syscalls:sys_enter $@ -- cgit v0.10.2 From bca647aac5067fec8dfcbf8ddb79a4c0d5afdfdd Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Wed, 10 Nov 2010 08:11:30 -0600 Subject: perf record: make the record options available outside perf record Other perf commands that invoke perf record, such as perf trace, may want to reuse the options used by perf record. This makes them non-static and renames them to avoid clashes with other 'options' variables. Signed-off-by: Tom Zanussi Acked-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 4e75583..93bd2ff 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -790,7 +790,7 @@ static const char * const record_usage[] = { static bool force, append_file; -static const struct option options[] = { +const struct option record_options[] = { OPT_CALLBACK('e', "event", NULL, "event", "event selector. use 'perf list' to list available events", parse_events), @@ -839,16 +839,16 @@ int cmd_record(int argc, const char **argv, const char *prefix __used) { int i, j, err = -ENOMEM; - argc = parse_options(argc, argv, options, record_usage, + argc = parse_options(argc, argv, record_options, record_usage, PARSE_OPT_STOP_AT_NON_OPTION); if (!argc && target_pid == -1 && target_tid == -1 && !system_wide && !cpu_list) - usage_with_options(record_usage, options); + usage_with_options(record_usage, record_options); if (force && append_file) { fprintf(stderr, "Can't overwrite and append at the same time." " You need to choose between -f and -A"); - usage_with_options(record_usage, options); + usage_with_options(record_usage, record_options); } else if (append_file) { write_mode = WRITE_APPEND; } else { @@ -871,7 +871,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used) if (thread_num <= 0) { fprintf(stderr, "Can't find all threads of pid %d\n", target_pid); - usage_with_options(record_usage, options); + usage_with_options(record_usage, record_options); } } else { all_tids=malloc(sizeof(pid_t)); -- cgit v0.10.2 From 34c86ea97ed811bb40ee4db63f710eb522162c77 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Wed, 10 Nov 2010 08:15:43 -0600 Subject: perf trace record: handle commands correctly Because the perf-trace shell scripts hard-coded the use of the perf-record system-wide param, a perf trace record session was always system wide, even if it was given a command. If given a command, perf trace record now only records the events for the command, as users expect. If no command is given, or if the '-a' option is used, the recorded events are system-wide, as before. root@tropicana:~# perf trace record syscall-counts ls -al root@tropicana:~# perf trace ls-23152 [000] 39984.890387: sys_enter: NR 12 (0, 0, 0, 0, 0, 0) ls-23152 [000] 39984.890404: sys_enter: NR 9 (0, 0, 0, 0, 0, 0) root@tropicana:~# perf trace record syscall-counts -a ls -al root@tropicana:~# perf trace npviewer.bin-22297 [000] 39831.102709: sys_enter: NR 168 (0, 0, 0, 0, 0, 0) ls-23111 [000] 39831.107679: sys_enter: NR 59 (0, 0, 0, 0, 0, 0) Signed-off-by: Tom Zanussi Acked-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 368e624..0de7fcb 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -10,6 +10,7 @@ #include "util/symbol.h" #include "util/thread.h" #include "util/trace-event.h" +#include "util/parse-options.h" #include "util/util.h" static char const *script_name; @@ -17,6 +18,7 @@ static char const *generate_script_lang; static bool debug_mode; static u64 last_timestamp; static u64 nr_unordered; +extern const struct option record_options[]; static int default_start_script(const char *script __unused, int argc __unused, @@ -566,6 +568,20 @@ static const struct option options[] = { OPT_END() }; +static bool have_cmd(int argc, const char **argv) +{ + char **__argv = malloc(sizeof(const char *) * argc); + + if (!__argv) + die("malloc"); + memcpy(__argv, argv, sizeof(const char *) * argc); + argc = parse_options(argc, (const char **)__argv, record_options, + NULL, PARSE_OPT_STOP_AT_NON_OPTION); + free(__argv); + + return argc != 0; +} + int cmd_trace(int argc, const char **argv, const char *prefix __used) { struct perf_session *session; @@ -663,20 +679,28 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used) } if (suffix) { + bool system_wide = false; + int j = 0; + script_path = get_script_path(argv[2], suffix); if (!script_path) { fprintf(stderr, "script not found\n"); return -1; } + if (!strcmp(suffix, RECORD_SUFFIX)) + system_wide = !have_cmd(argc - 2, &argv[2]); + __argv = malloc((argc + 1) * sizeof(const char *)); if (!__argv) die("malloc"); - __argv[0] = "/bin/sh"; - __argv[1] = script_path; + __argv[j++] = "/bin/sh"; + __argv[j++] = script_path; + if (system_wide) + __argv[j++] = "-a"; for (i = 3; i < argc; i++) - __argv[i - 1] = argv[i]; - __argv[argc - 1] = NULL; + __argv[j++] = argv[i]; + __argv[j++] = NULL; execvp("/bin/sh", (char **)__argv); free(__argv); -- cgit v0.10.2 From b5b8731219ddd007c229feacbfe745d1be070e6a Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Wed, 10 Nov 2010 08:16:51 -0600 Subject: perf trace: live-mode command-line cleanup This patch attempts to make the perf trace command-line for live-mode commands more user-friendly and consistent with other perf commands. The main change it makes is to allow to be run as part of perf trace live-mode commands, as other perf commands do, instead of the system-wide traces they're currently hard-coded to by the shell scripts. With this patch, the following live-mode trace now works as expected: $ perf trace rw-by-pid ls -al The previous system-wide behavior for this command would still be available by explicitly specifying -a: $ perf trace rw-by-pid -a ls -al and if no is specified, the output is also system-wide: $ perf trace rw-by-pid Because live-mode requires both record and report steps to be invoked, it isn't always possible to know which args to send to the report and which to send to the record steps - mainly this is the case for report scripts with optional args - in those cases it would be necessary to use separate 'perf trace record' and 'perf trace report' steps. For example: $ perf trace syscall-counts ls Here we can't decide whether ls should be passed as a param to the syscall-counts script or whether we should invoke ls as a . In these cases, we just say that we'll ignore optional script params and always interpret the extra arguments as a . If the user instead wants the other interpretation, that can be accomplished by using separate record and report commands explicitly: $ perf trace record syscall-counts $ perf trace report syscall-counts ls So the rules that this patch implements, which seem to make the most intuitive sense for live-mode commands: - for commands with optional args and commands with no args, no args are sent to the report script, all are sent to the record step - for 'top' commands i.e. that end with 'top', can't be used - all extra args are send to the report script as params - for commands with required args, the n required args are taken to be the first n args after the script name and sent to the report script, and the rest are sent to the record step Signed-off-by: Tom Zanussi Acked-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 0de7fcb..0483e28 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -330,7 +330,7 @@ static struct script_desc *script_desc__new(const char *name) { struct script_desc *s = zalloc(sizeof(*s)); - if (s != NULL) + if (s != NULL && name) s->name = strdup(name); return s; @@ -541,6 +541,34 @@ static char *get_script_path(const char *script_root, const char *suffix) return path; } +static bool is_top_script(const char *script_path) +{ + return ends_with((char *)script_path, "top") == NULL ? false : true; +} + +static int has_required_arg(char *script_path) +{ + struct script_desc *desc; + int n_args = 0; + char *p; + + desc = script_desc__new(NULL); + + if (read_script_info(desc, script_path)) + goto out; + + if (!desc->args) + goto out; + + for (p = desc->args; *p; p++) + if (*p == '<') + n_args++; +out: + script_desc__delete(desc); + + return n_args; +} + static const char * const trace_usage[] = { "perf trace [] ", NULL @@ -584,48 +612,65 @@ static bool have_cmd(int argc, const char **argv) int cmd_trace(int argc, const char **argv, const char *prefix __used) { + char *rec_script_path = NULL; + char *rep_script_path = NULL; struct perf_session *session; - const char *suffix = NULL; + char *script_path = NULL; const char **__argv; - char *script_path; - int i, err; + bool system_wide; + int i, j, err; - if (argc >= 2 && strncmp(argv[1], "rec", strlen("rec")) == 0) { - if (argc < 3) { - fprintf(stderr, - "Please specify a record script\n"); - return -1; - } - suffix = RECORD_SUFFIX; + setup_scripting(); + + argc = parse_options(argc, argv, options, trace_usage, + PARSE_OPT_STOP_AT_NON_OPTION); + + if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) { + rec_script_path = get_script_path(argv[1], RECORD_SUFFIX); + if (!rec_script_path) + return cmd_record(argc, argv, NULL); } - if (argc >= 2 && strncmp(argv[1], "rep", strlen("rep")) == 0) { - if (argc < 3) { + if (argc > 1 && !strncmp(argv[0], "rep", strlen("rep"))) { + rep_script_path = get_script_path(argv[1], REPORT_SUFFIX); + if (!rep_script_path) { fprintf(stderr, - "Please specify a report script\n"); + "Please specify a valid report script" + "(see 'perf trace -l' for listing)\n"); return -1; } - suffix = REPORT_SUFFIX; } /* make sure PERF_EXEC_PATH is set for scripts */ perf_set_argv_exec_path(perf_exec_path()); - if (!suffix && argc >= 2 && strncmp(argv[1], "-", strlen("-")) != 0) { - char *record_script_path, *report_script_path; + if (argc && !script_name && !rec_script_path && !rep_script_path) { int live_pipe[2]; + int rep_args; pid_t pid; - record_script_path = get_script_path(argv[1], RECORD_SUFFIX); - if (!record_script_path) { - fprintf(stderr, "record script not found\n"); - return -1; + rec_script_path = get_script_path(argv[0], RECORD_SUFFIX); + rep_script_path = get_script_path(argv[0], REPORT_SUFFIX); + + if (!rec_script_path && !rep_script_path) { + fprintf(stderr, " Couldn't find script %s\n\n See perf" + " trace -l for available scripts.\n", argv[0]); + usage_with_options(trace_usage, options); } - report_script_path = get_script_path(argv[1], REPORT_SUFFIX); - if (!report_script_path) { - fprintf(stderr, "report script not found\n"); - return -1; + if (is_top_script(argv[0])) { + rep_args = argc - 1; + } else { + int rec_args; + + rep_args = has_required_arg(rep_script_path); + rec_args = (argc - 1) - rep_args; + if (rec_args < 0) { + fprintf(stderr, " %s script requires options." + "\n\n See perf trace -l for available " + "scripts and options.\n", argv[0]); + usage_with_options(trace_usage, options); + } } if (pipe(live_pipe) < 0) { @@ -640,19 +685,30 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used) } if (!pid) { + system_wide = true; + j = 0; + dup2(live_pipe[1], 1); close(live_pipe[0]); - __argv = malloc(6 * sizeof(const char *)); + if (!is_top_script(argv[0])) + system_wide = !have_cmd(argc - rep_args, + &argv[rep_args]); + + __argv = malloc((argc + 6) * sizeof(const char *)); if (!__argv) die("malloc"); - __argv[0] = "/bin/sh"; - __argv[1] = record_script_path; - __argv[2] = "-q"; - __argv[3] = "-o"; - __argv[4] = "-"; - __argv[5] = NULL; + __argv[j++] = "/bin/sh"; + __argv[j++] = rec_script_path; + if (system_wide) + __argv[j++] = "-a"; + __argv[j++] = "-q"; + __argv[j++] = "-o"; + __argv[j++] = "-"; + for (i = rep_args + 1; i < argc; i++) + __argv[j++] = argv[i]; + __argv[j++] = NULL; execvp("/bin/sh", (char **)__argv); free(__argv); @@ -662,43 +718,43 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used) dup2(live_pipe[0], 0); close(live_pipe[1]); - __argv = malloc((argc + 3) * sizeof(const char *)); + __argv = malloc((argc + 4) * sizeof(const char *)); if (!__argv) die("malloc"); - __argv[0] = "/bin/sh"; - __argv[1] = report_script_path; - for (i = 2; i < argc; i++) - __argv[i] = argv[i]; - __argv[i++] = "-i"; - __argv[i++] = "-"; - __argv[i++] = NULL; + j = 0; + __argv[j++] = "/bin/sh"; + __argv[j++] = rep_script_path; + for (i = 1; i < rep_args + 1; i++) + __argv[j++] = argv[i]; + __argv[j++] = "-i"; + __argv[j++] = "-"; + __argv[j++] = NULL; execvp("/bin/sh", (char **)__argv); free(__argv); exit(-1); } - if (suffix) { - bool system_wide = false; - int j = 0; + if (rec_script_path) + script_path = rec_script_path; + if (rep_script_path) + script_path = rep_script_path; - script_path = get_script_path(argv[2], suffix); - if (!script_path) { - fprintf(stderr, "script not found\n"); - return -1; - } + if (script_path) { + system_wide = false; + j = 0; - if (!strcmp(suffix, RECORD_SUFFIX)) - system_wide = !have_cmd(argc - 2, &argv[2]); + if (rec_script_path) + system_wide = !have_cmd(argc - 1, &argv[1]); - __argv = malloc((argc + 1) * sizeof(const char *)); + __argv = malloc((argc + 2) * sizeof(const char *)); if (!__argv) die("malloc"); __argv[j++] = "/bin/sh"; __argv[j++] = script_path; if (system_wide) __argv[j++] = "-a"; - for (i = 3; i < argc; i++) + for (i = 2; i < argc; i++) __argv[j++] = argv[i]; __argv[j++] = NULL; @@ -707,11 +763,6 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used) exit(-1); } - setup_scripting(); - - argc = parse_options(argc, argv, options, trace_usage, - PARSE_OPT_STOP_AT_NON_OPTION); - if (symbol__init() < 0) return -1; if (!script_name) -- cgit v0.10.2 From d3c4f798ac4b7337b417467f36f4b2e6dcb49240 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Wed, 10 Nov 2010 08:19:35 -0600 Subject: perf trace: update Documentation with new perf trace variants Add documentation describing new 'perf trace' command changes e.g. handling and live-mode/top variants. Signed-off-by: Tom Zanussi Acked-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt index 122ec9d..26aff6b 100644 --- a/tools/perf/Documentation/perf-trace.txt +++ b/tools/perf/Documentation/perf-trace.txt @@ -8,7 +8,11 @@ perf-trace - Read perf.data (created by perf record) and display trace output SYNOPSIS -------- [verse] -'perf trace' {record