From f0b8d2671fa56e0e1dcb4cc09fd6f7edf70f8fa3 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Fri, 20 Mar 2009 11:54:15 -0400 Subject: PR6930: staprun: supports error message to syslog Add an interface (eprintf) to output error messages to syslogd, because staprun has no stderr after detaching from console. --- runtime/staprun/common.c | 21 +++++++++++++++++++++ runtime/staprun/mainloop.c | 2 +- runtime/staprun/staprun.h | 18 +++++++++++------- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/runtime/staprun/common.c b/runtime/staprun/common.c index fd16b4b8..b8860248 100644 --- a/runtime/staprun/common.c +++ b/runtime/staprun/common.c @@ -344,3 +344,24 @@ int send_request(int type, void *data, int len) if (rc < 0) return rc; return (rc != len+4); } + +#include + +static int use_syslog = 0; + +void eprintf(const char *fmt, ...) +{ + va_list va; + va_start(va, fmt); + if (use_syslog) + vsyslog(LOG_ERR, fmt, va); + else + vfprintf(stderr, fmt, va); + va_end(va); +} + +void switch_syslog(const char *name) +{ + openlog(name, LOG_PID, LOG_DAEMON); + use_syslog = 1; +} diff --git a/runtime/staprun/mainloop.c b/runtime/staprun/mainloop.c index db6ef6b7..e91e6302 100644 --- a/runtime/staprun/mainloop.c +++ b/runtime/staprun/mainloop.c @@ -468,7 +468,7 @@ int stp_main_loop(void) } #endif case STP_OOB_DATA: - fputs((char *)data, stderr); + eprintf("%s", (char *)data); break; case STP_EXIT: { diff --git a/runtime/staprun/staprun.h b/runtime/staprun/staprun.h index 84cf63fc..4c43e3ee 100644 --- a/runtime/staprun/staprun.h +++ b/runtime/staprun/staprun.h @@ -33,31 +33,35 @@ #include #include #include +#include /* Include config.h to pick up dependency for --prefix usage. */ #include "config.h" -#define dbug(level, args...) {if (verbose>=level) {fprintf(stderr,"%s:%s:%d ",__name__,__FUNCTION__, __LINE__); fprintf(stderr,args);}} +extern void eprintf(const char *fmt, ...); +extern void switch_syslog(const char *name); + +#define dbug(level, args...) do {if (verbose>=level) {eprintf("%s:%s:%d ",__name__,__FUNCTION__, __LINE__); eprintf(args);}} while (0) extern char *__name__; /* print to stderr */ -#define err(args...) fprintf(stderr,args) +#define err(args...) eprintf(args) /* better perror() */ #define perr(args...) do { \ int _errno = errno; \ - fputs("ERROR: ", stderr); \ - fprintf(stderr, args); \ - fprintf(stderr, ": %s\n", strerror(_errno)); \ + eprintf("ERROR: "); \ + eprintf(args); \ + eprintf(": %s\n", strerror(_errno)); \ } while (0) /* Error messages. Use these for serious errors, not informational messages to stderr. */ -#define _err(args...) do {fprintf(stderr,"%s:%s:%d: ERROR: ",__name__, __FUNCTION__, __LINE__); fprintf(stderr,args);} while(0) +#define _err(args...) do {eprintf("%s:%s:%d: ERROR: ",__name__, __FUNCTION__, __LINE__); eprintf(args);} while(0) #define _perr(args...) do { \ int _errno = errno; \ _err(args); \ - fprintf(stderr, ": %s\n", strerror(_errno)); \ + eprintf(": %s\n", strerror(_errno)); \ } while (0) #define overflow_error() _err("Internal buffer overflow. Please file a bug report.\n") -- cgit From 54892f28a2747079fae4aa35b80598cbb993a4c3 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Fri, 20 Mar 2009 11:59:06 -0400 Subject: PR6930: stapio: run in background as a daemon Add '-D'(daemon mode) option to staprun/stapio for daemon mode. In this mode, stapio shows just its pid and detachs from console. Since it has no stdio, this mode requires -o option. stapio will exit when it receives SIGTERM or detects some error. --- runtime/staprun/common.c | 52 ++++++++++++++++++++++++++++++++++++++++++---- runtime/staprun/mainloop.c | 35 +++++++++++++++++++++++++++++++ runtime/staprun/staprun.h | 1 + 3 files changed, 84 insertions(+), 4 deletions(-) diff --git a/runtime/staprun/common.c b/runtime/staprun/common.c index b8860248..a1b70d3b 100644 --- a/runtime/staprun/common.c +++ b/runtime/staprun/common.c @@ -27,6 +27,7 @@ int attach_mod; int delete_mod; int load_only; int need_uprobes; +int daemon_mode; /* module variables */ char *modname = NULL; @@ -35,6 +36,21 @@ char *modoptions[MAXMODOPTIONS]; int control_channel = -1; /* NB: fd==0 possible */ +static char path_buf[PATH_MAX]; +static char *get_abspath(char *path) +{ + int len; + if (path[0] == '/') + return path; + + len = strlen(getcwd(path_buf, PATH_MAX)); + if (len + 2 + strlen(path) >= PATH_MAX) + return NULL; + path_buf[len] = '/'; + strcpy(&path_buf[len + 1], path); + return path_buf; +} + void parse_args(int argc, char **argv) { int c; @@ -49,8 +65,9 @@ void parse_args(int argc, char **argv) delete_mod = 0; load_only = 0; need_uprobes = 0; + daemon_mode = 0; - while ((c = getopt(argc, argv, "ALuvb:t:dc:o:x:")) != EOF) { + while ((c = getopt(argc, argv, "ALuvb:t:dc:o:x:D")) != EOF) { switch (c) { case 'u': need_uprobes = 1; @@ -85,11 +102,20 @@ void parse_args(int argc, char **argv) case 'L': load_only = 1; break; + case 'D': + daemon_mode = 1; + break; default: usage(argv[0]); } } - + if (outfile_name) { + outfile_name = get_abspath(outfile_name); + if (outfile_name == NULL) { + err("File name is too long.\n"); + usage(argv[0]); + } + } if (attach_mod && load_only) { err("You can't specify the '-A' and '-L' options together.\n"); usage(argv[0]); @@ -118,12 +144,29 @@ void parse_args(int argc, char **argv) err("You can't specify the '-c' and '-x' options together.\n"); usage(argv[0]); } + + if (daemon_mode && load_only) { + err("You can't specify the '-D' and '-L' options together.\n"); + usage(argv[0]); + } + if (daemon_mode && delete_mod) { + err("You can't specify the '-D' and '-d' options together.\n"); + usage(argv[0]); + } + if (daemon_mode && target_cmd) { + err("You can't specify the '-D' and '-c' options together.\n"); + usage(argv[0]); + } + if (daemon_mode && outfile_name == NULL) { + err("You have to specify output FILE with '-D' option.\n"); + usage(argv[0]); + } } void usage(char *prog) { - err("\n%s [-v] [-c cmd ] [-x pid] [-u user]\n" - "\t[-A|-L] [-b bufsize] [-o FILE] MODULE [module-options]\n", prog); + err("\n%s [-v] [-c cmd ] [-x pid] [-u user] [-A|-L|-d]\n" + "\t[-b bufsize] [-o FILE [-D]] MODULE [module-options]\n", prog); err("-v Increase verbosity.\n"); err("-c cmd Command \'cmd\' will be run and staprun will\n"); err(" exit when it does. The '_stp_target' variable\n"); @@ -140,6 +183,7 @@ void usage(char *prog) err("-d Delete a module. Only detached or unused modules\n"); err(" the user has permission to access will be deleted. Use \"*\"\n"); err(" (quoted) to delete all unused modules.\n"); + err("-D Run in background. This requires '-o' option.\n"); err("MODULE can be either a module name or a module path. If a\n"); err("module name is used, it is looked for in the following\n"); err("directory: /lib/modules/`uname -r`/systemtap\n"); diff --git a/runtime/staprun/mainloop.c b/runtime/staprun/mainloop.c index e91e6302..b0d88073 100644 --- a/runtime/staprun/mainloop.c +++ b/runtime/staprun/mainloop.c @@ -318,6 +318,41 @@ int init_stapio(void) if (target_cmd) start_cmd(); + /* Run in background */ + if (daemon_mode) { + pid_t pid; + int ret; + dbug(2, "daemonizing stapio\n"); + + /* daemonize */ + ret = daemon(0, 1); /* don't close stdout at this time. */ + if (ret) { + err("Failed to daemonize stapio\n"); + return -1; + } + + /* change error messages to syslog. */ + switch_syslog("stapio"); + + /* show new pid */ + pid = getpid(); + fprintf(stdout, "%d\n", pid); + fflush(stdout); + + /* redirect all outputs to /dev/null */ + ret = open("/dev/null", O_RDWR); + if (ret < 0) { + err("Failed to open /dev/null\n"); + return -1; + } + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + dup2(ret, STDOUT_FILENO); + dup2(ret, STDERR_FILENO); + close(ret); + } + return 0; } diff --git a/runtime/staprun/staprun.h b/runtime/staprun/staprun.h index 4c43e3ee..b380cebd 100644 --- a/runtime/staprun/staprun.h +++ b/runtime/staprun/staprun.h @@ -157,6 +157,7 @@ extern int attach_mod; extern int delete_mod; extern int load_only; extern int need_uprobes; +extern int daemon_mode; /* getopt variables */ extern char *optarg; -- cgit From 52064a4bd37f8d81e1f488fe9d32fe6ccee63bd7 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Fri, 20 Mar 2009 11:40:04 -0400 Subject: Added functions to grab IP source and destination from a socket, and functions to grab TCP source and destination port from a socket. Also, used this function inside some TCP probe functions, as recvmsg, to provide a richer set of fields. --- tapset/ip.stp | 32 ++++++++++++++++++++++++++ tapset/tcp.stp | 34 ++++++++++++++++++++++++++++ testsuite/systemtap.examples/network/tcp.stp | 11 +++++++++ 3 files changed, 77 insertions(+) create mode 100644 tapset/ip.stp create mode 100644 testsuite/systemtap.examples/network/tcp.stp diff --git a/tapset/ip.stp b/tapset/ip.stp new file mode 100644 index 00000000..1e2e263c --- /dev/null +++ b/tapset/ip.stp @@ -0,0 +1,32 @@ +// IP tapset +// Copyright (C) 2009, IBM Inc. +// Author : Breno Leitao +// +// This file is free software. You can redistribute it and/or modify it under +// the terms of the GNU General Public License (GPL), version 2. +// +// Based on previous work done by Arnaldo Carvalho de Melo + +/** + * sfunction ip_ntop - returns a string representation from an integer IP number + * @addr: the ip represented as an integer + */ +function ip_ntop:string (addr:long) +%{ + __be32 ip; + + ip = THIS->addr; + snprintf(THIS->__retvalue, MAXSTRINGLEN, NIPQUAD_FMT, NIPQUAD(ip)); +%} + +/* return the source IP address for a given sock */ +function __ip_sock_saddr:long (sock:long) +{ + return @cast(sock, "inet_sock")->saddr +} + +/* return the destination IP address for a given sock */ +function __ip_sock_daddr:long (sock:long) +{ + return @cast(sock, "inet_sock")->daddr +} diff --git a/tapset/tcp.stp b/tapset/tcp.stp index 1375f115..bb96b0cb 100644 --- a/tapset/tcp.stp +++ b/tapset/tcp.stp @@ -73,6 +73,16 @@ function tcp_ts_get_info_state:long(sock:long) CATCH_DEREF_FAULT(); %} +/* return the TCP destination port for a given sock */ +function __tcp_sock_dport:long (sock:long){ + return @cast(sock, "inet_sock")->dport +} + +/* return the TCP source port for a given sock */ +function __tcp_sock_sport:long (sock:long){ + return @cast(sock, "inet_sock")->sport +} + global sockstate[13], sockstate_init_p function tcp_sockstate_str:string (state:long) { if (! sockstate_init_p) { @@ -182,6 +192,10 @@ probe tcp.sendmsg.return = kernel.function("tcp_sendmsg").return { * @name: Name of this probe * @sock: Network socket * @size: Number of bytes to be received + * @saddr: A string representing the source IP address + * @daddr: A string representing the destination IP address + * @sport: TCP source port + * @dport: TCP destination port * Context: * The process which receives a tcp message */ @@ -189,12 +203,20 @@ probe tcp.recvmsg = kernel.function("tcp_recvmsg") { name = "tcp.recvmsg" sock = $sk size = $len + saddr = ip_ntop(__ip_sock_saddr($sk)) + daddr = ip_ntop(__ip_sock_daddr($sk)) + sport = __tcp_sock_sport($sk) + dport = __tcp_sock_dport($sk) } /** * probe tcp.recvmsg.return - Receiving TCP message complete * @name: Name of this probe * @size: Number of bytes received or error code if an error occurred. + * @saddr: A string representing the source IP address + * @daddr: A string representing the destination IP address + * @sport: TCP source port + * @dport: TCP destination port * * Context: * The process which receives a tcp message @@ -202,6 +224,10 @@ probe tcp.recvmsg = kernel.function("tcp_recvmsg") { probe tcp.recvmsg.return = kernel.function("tcp_recvmsg").return { name = "tcp.recvmsg" size = $return + saddr = ip_ntop(__ip_sock_saddr($sk)) + daddr = ip_ntop(__ip_sock_daddr($sk)) + sport = __tcp_sock_sport($sk) + dport = __tcp_sock_dport($sk) } /** @@ -209,6 +235,10 @@ probe tcp.recvmsg.return = kernel.function("tcp_recvmsg").return { * @name: Name of this probe * @sock: Network socket * @flags: TCP flags (e.g. FIN, etc) + * @saddr: A string representing the source IP address + * @daddr: A string representing the destination IP address + * @sport: TCP source port + * @dport: TCP destination port * * Context: * The process which disconnects tcp @@ -217,6 +247,10 @@ probe tcp.disconnect = kernel.function("tcp_disconnect") { name = "tcp.disconnect" sock = $sk flags = $flags + saddr = ip_ntop(__ip_sock_saddr($sk)) + daddr = ip_ntop(__ip_sock_daddr($sk)) + sport = __tcp_sock_sport($sk) + dport = __tcp_sock_dport($sk) } /** diff --git a/testsuite/systemtap.examples/network/tcp.stp b/testsuite/systemtap.examples/network/tcp.stp new file mode 100644 index 00000000..ebe72a1c --- /dev/null +++ b/testsuite/systemtap.examples/network/tcp.stp @@ -0,0 +1,11 @@ +//A simple TCP tapset example + +probe begin { + printf("Expected IP 7.91.205.21 .... %s\n", ip_ntop(123456789)) + printf("Expected IP 58.222.104.177 .... %s\n", ip_ntop(987654321)) + printf("Expected IP 9.3.191.111 ... %s\n", ip_ntop(151240559)) +} + +probe tcp.recvmsg { + printf("received a message from %s on port %d from port %d\n", saddr, dport, sport) +} -- cgit From 7e402c4915c373e7818cf6218b0877a102fd7ff6 Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Fri, 20 Mar 2009 11:41:02 -0400 Subject: removed authorblock from tapset reference guide; added ip.stp to template --- doc/SystemTap_Tapset_Reference/tapsets.tmpl | 39 +++-------------------------- 1 file changed, 4 insertions(+), 35 deletions(-) diff --git a/doc/SystemTap_Tapset_Reference/tapsets.tmpl b/doc/SystemTap_Tapset_Reference/tapsets.tmpl index 892d30a9..21706ea2 100644 --- a/doc/SystemTap_Tapset_Reference/tapsets.tmpl +++ b/doc/SystemTap_Tapset_Reference/tapsets.tmpl @@ -5,23 +5,10 @@ SystemTap Tapset Reference Manual - - - - William - Cohen - - -
- wcohen@redhat.com -
-
-
-
- 2008, 2009 - Red Hat, Inc. + 2008-2009 + Red Hat, Inc. and others @@ -170,11 +157,12 @@ Networking Tapset This family of probe points is used to probe the activities of - the network device, TCP layer, and UDP layer. + the network device and protocol layers. !Itapset/networking.stp !Itapset/tcp.stp !Itapset/udp.stp +!Itapset/ip.stp @@ -185,25 +173,6 @@ !Itapset/socket.stp - Process Tapset -- cgit From acd56c22068963ad48f39890f5307600ff7d5278 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Fri, 20 Mar 2009 12:11:30 -0400 Subject: PR6930: stapio: support file switching Add file-switching option(-S size[,N]) to stapio. This option has two arguments, 'size' and 'N', and requires -o option. - When the size of output file exceeds specified 'size'MB, staprun switches output file to the next file. For this purpose, all output file has a serial number as a suffix only when user specifies this option. - Using this option in bulk mode, the output file name will be 'FILE_cpuX.SERIAL'. - When the number of files exceeds specified N, staprun removes the oldest file. This argument can be omitted. --- runtime/staprun/common.c | 30 ++++++++++++++- runtime/staprun/mainloop.c | 15 ++------ runtime/staprun/relay.c | 69 +++++++++++++++++++++++++++++++++- runtime/staprun/relay_old.c | 92 ++++++++++++++++++++++++++++++++++++++++++++- runtime/staprun/staprun.h | 6 ++- 5 files changed, 195 insertions(+), 17 deletions(-) diff --git a/runtime/staprun/common.c b/runtime/staprun/common.c index a1b70d3b..194488ef 100644 --- a/runtime/staprun/common.c +++ b/runtime/staprun/common.c @@ -28,6 +28,8 @@ int delete_mod; int load_only; int need_uprobes; int daemon_mode; +off_t fsize_max; +int fnum_max; /* module variables */ char *modname = NULL; @@ -54,6 +56,7 @@ static char *get_abspath(char *path) void parse_args(int argc, char **argv) { int c; + char *s; /* Initialize option variables. */ verbose = 0; @@ -66,8 +69,10 @@ void parse_args(int argc, char **argv) load_only = 0; need_uprobes = 0; daemon_mode = 0; + fsize_max = 0; + fnum_max = 0; - while ((c = getopt(argc, argv, "ALuvb:t:dc:o:x:D")) != EOF) { + while ((c = getopt(argc, argv, "ALuvb:t:dc:o:x:S:D")) != EOF) { switch (c) { case 'u': need_uprobes = 1; @@ -105,6 +110,16 @@ void parse_args(int argc, char **argv) case 'D': daemon_mode = 1; break; + case 'S': + fsize_max = strtoul(optarg, &s, 10); + fsize_max <<= 20; + if (s[0] == ',') + fnum_max = (int)strtoul(&s[1], &s, 10); + if (s[0] != '\0') { + err("Invalid file size option '%s'.\n", optarg); + usage(argv[0]); + } + break; default: usage(argv[0]); } @@ -161,12 +176,16 @@ void parse_args(int argc, char **argv) err("You have to specify output FILE with '-D' option.\n"); usage(argv[0]); } + if (outfile_name == NULL && fsize_max != 0) { + err("You have to specify output FILE with '-S' option.\n"); + usage(argv[0]); + } } void usage(char *prog) { err("\n%s [-v] [-c cmd ] [-x pid] [-u user] [-A|-L|-d]\n" - "\t[-b bufsize] [-o FILE [-D]] MODULE [module-options]\n", prog); + "\t[-b bufsize] [-o FILE [-D] [-S size[,N]]] MODULE [module-options]\n", prog); err("-v Increase verbosity.\n"); err("-c cmd Command \'cmd\' will be run and staprun will\n"); err(" exit when it does. The '_stp_target' variable\n"); @@ -184,6 +203,13 @@ void usage(char *prog) err(" the user has permission to access will be deleted. Use \"*\"\n"); err(" (quoted) to delete all unused modules.\n"); err("-D Run in background. This requires '-o' option.\n"); + err("-S size[,N] Switches output file to next file when the size\n"); + err(" of file reaches the specified size. The value\n"); + err(" should be an integer greater than 1 which is\n"); + err(" assumed to be the maximum file size in MB.\n"); + err(" When the number of output files reaches N, it\n"); + err(" switches to the first output file. You can omit\n"); + err(" the second argument.\n"); err("MODULE can be either a module name or a module path. If a\n"); err("module name is used, it is looked for in the following\n"); err("directory: /lib/modules/`uname -r`/systemtap\n"); diff --git a/runtime/staprun/mainloop.c b/runtime/staprun/mainloop.c index b0d88073..c80bbba4 100644 --- a/runtime/staprun/mainloop.c +++ b/runtime/staprun/mainloop.c @@ -489,18 +489,11 @@ int stp_main_loop(void) switch (type) { #ifdef STP_OLD_TRANSPORT case STP_REALTIME_DATA: - { - ssize_t bw = write(out_fd[0], data, nb); - if (bw >= 0 && bw != nb) { - nb = nb - bw; - bw = write(out_fd[0], data, nb); - } - if (bw != nb) { - _perr("write error (nb=%ld)", (long)nb); - cleanup_and_exit(0); - } - break; + if (write_realtime_data(data, nb)) { + _perr("write error (nb=%ld)", (long)nb); + cleanup_and_exit(0); } + break; #endif case STP_OOB_DATA: eprintf("%s", (char *)data); diff --git a/runtime/staprun/relay.c b/runtime/staprun/relay.c index 19621933..891913b0 100644 --- a/runtime/staprun/relay.c +++ b/runtime/staprun/relay.c @@ -44,6 +44,52 @@ static int ppoll(struct pollfd *fds, nfds_t nfds, } #endif +int make_outfile_name(char *buf, int max, int fnum, int cpu) +{ + if (bulkmode) { + /* special case: for testing we sometimes want to write to /dev/null */ + if (strcmp(outfile_name, "/dev/null") == 0) { + strcpy(buf, "/dev/null"); + } else { + if (snprintf_chk(buf, max, "%s_cpu%d.%d", + outfile_name, cpu, fnum)) + return -1; + } + } else { + /* stream mode */ + if (snprintf_chk(buf, max, "%s.%d", outfile_name, fnum)) + return -1; + } + return 0; +} + +static int open_outfile(int fnum, int cpu, int remove_file) +{ + char buf[PATH_MAX]; + if (!outfile_name) { + _err("-S is set without -o. Please file a bug report.\n"); + return -1; + } + + if (remove_file) { + /* remove oldest file */ + if (make_outfile_name(buf, PATH_MAX, fnum - fnum_max, cpu) < 0) + return -1; + remove(buf); /* don't care */ + } + + if (make_outfile_name(buf, PATH_MAX, fnum, cpu) < 0) + return -1; + out_fd[cpu] = open (buf, O_CREAT|O_TRUNC|O_WRONLY, 0666); + if (out_fd[cpu] < 0) { + perr("Couldn't open output file %s", buf); + return -1; + } + if (set_clexec(out_fd[cpu]) < 0) + return -1; + return 0; +} + /** * reader_thread - per-cpu channel buffer reader */ @@ -57,6 +103,9 @@ static void *reader_thread(void *data) struct timespec tim = {.tv_sec=0, .tv_nsec=200000000}, *timeout = &tim; sigset_t sigs; struct sigaction sa; + off_t wsize = 0; + int fnum = 0; + int remove_file = 0; sigemptyset(&sigs); sigaddset(&sigs,SIGUSR2); @@ -99,6 +148,19 @@ static void *reader_thread(void *data) } } while ((rc = read(relay_fd[cpu], buf, sizeof(buf))) > 0) { + wsize += rc; + /* Switching file */ + if (fsize_max && wsize > fsize_max) { + close(out_fd[cpu]); + fnum++; + if (fnum_max && fnum == fnum_max) + remove_file = 1; + if (open_outfile(fnum, cpu, remove_file) < 0) { + perr("Couldn't open file for cpu %d, exiting.", cpu); + return(NULL); + } + wsize = 0; + } if (write(out_fd[cpu], buf, rc) != rc) { perr("Couldn't write to output %d for cpu %d, exiting.", out_fd[cpu], cpu); return(NULL); @@ -163,7 +225,12 @@ int init_relayfs(void) return -1; } - if (bulkmode) { + if (fsize_max) { + /* switch file mode */ + for (i = 0; i < ncpus; i++) + if (open_outfile(0, i, 0) < 0) + return -1; + } else if (bulkmode) { for (i = 0; i < ncpus; i++) { if (outfile_name) { /* special case: for testing we sometimes want to write to /dev/null */ diff --git a/runtime/staprun/relay_old.c b/runtime/staprun/relay_old.c index bd746f19..25ba93bf 100644 --- a/runtime/staprun/relay_old.c +++ b/runtime/staprun/relay_old.c @@ -23,6 +23,14 @@ static int bulkmode = 0; unsigned subbuf_size = 0; unsigned n_subbufs = 0; +struct switchfile_ctrl_block { + off_t wsize; + int fnum; + int rmfile; +}; + +static struct switchfile_ctrl_block global_scb = {0, 0, 0}; + /* per-cpu buffer info */ static struct buf_status { @@ -70,6 +78,36 @@ void close_oldrelayfs(int detach) close_relayfs_files(i); } +static int open_oldoutfile(int fnum, int cpu, int remove_file) +{ + char buf[PATH_MAX]; + if (outfile_name) { + if (remove_file) { + /* remove oldest file */ + if (make_outfile_name(buf, PATH_MAX, fnum - fnum_max, + cpu) < 0) + return -1; + remove(buf); /* don't care */ + } + if (make_outfile_name(buf, PATH_MAX, fnum, cpu) < 0) + return -1; + } else if (bulkmode) { + if (sprintf_chk(buf, "stpd_cpu%d.%d", cpu, fnum)) + return -1; + } else { /* stream mode */ + out_fd[cpu] = STDOUT_FILENO; + return 0; + } + + out_fd[cpu] = open (buf, O_CREAT|O_TRUNC|O_WRONLY, 0666); + if (out_fd[cpu] < 0) { + perr("Couldn't open output file %s", buf); + return -1; + } + if (set_clexec(out_fd[cpu]) < 0) + return -1; + return 0; +} /** * open_relayfs_files - open and mmap buffer and open output file. * Returns -1 on unexpected failure, 0 if file not found, 1 on success. @@ -104,6 +142,11 @@ static int open_relayfs_files(int cpu, const char *relay_filebase, const char *p return -1; } + if (fsize_max) { + if (open_oldoutfile(0, cpu, 0) < 0) + goto err2; + goto opened; + } if (outfile_name) { /* special case: for testing we sometimes want to * write to /dev/null */ @@ -126,6 +169,7 @@ static int open_relayfs_files(int cpu, const char *relay_filebase, const char *p perr("Couldn't open output file %s", tmp); goto err2; } +opened: total_bufsize = subbuf_size * n_subbufs; relay_buffer[cpu] = mmap(NULL, total_bufsize, PROT_READ, @@ -155,7 +199,8 @@ err1: /** * process_subbufs - write ready subbufs to disk */ -static int process_subbufs(struct _stp_buf_info *info) +static int process_subbufs(struct _stp_buf_info *info, + struct switchfile_ctrl_block *scb) { unsigned subbufs_ready, start_subbuf, end_subbuf, subbuf_idx, i; int len, cpu = info->cpu; @@ -173,6 +218,18 @@ static int process_subbufs(struct _stp_buf_info *info) padding = *((unsigned *)subbuf_ptr); subbuf_ptr += sizeof(padding); len = (subbuf_size - sizeof(padding)) - padding; + scb->wsize += len; + if (fsize_max && scb->wsize > fsize_max) { + fclose(percpu_tmpfile[cpu]); + scb->fnum ++; + if (fnum_max && scb->fnum == fnum_max) + scb->rmfile = 1; + if (open_oldoutfile(scb->fnum, cpu, scb->rmfile) < 0) { + perr("Couldn't open file for cpu %d, exiting.", cpu); + exit(1); + } + scb->wsize = 0; + } if (len) { if (fwrite_unlocked (subbuf_ptr, len, 1, percpu_tmpfile[cpu]) != 1) { _perr("Couldn't write to output file for cpu %d, exiting:", cpu); @@ -196,6 +253,7 @@ static void *reader_thread(void *data) struct _stp_consumed_info consumed_info; unsigned subbufs_consumed; cpu_set_t cpu_mask; + struct switchfile_ctrl_block scb = {0, 0, 0}; CPU_ZERO(&cpu_mask); CPU_SET(cpu, &cpu_mask); @@ -217,7 +275,7 @@ static void *reader_thread(void *data) } rc = read(proc_fd[cpu], &status[cpu].info, sizeof(struct _stp_buf_info)); - subbufs_consumed = process_subbufs(&status[cpu].info); + subbufs_consumed = process_subbufs(&status[cpu].info, &scb); if (subbufs_consumed) { if (subbufs_consumed > status[cpu].max_backlog) status[cpu].max_backlog = subbufs_consumed; @@ -232,6 +290,33 @@ static void *reader_thread(void *data) } while (1); } +/** + * write_realtime_data - write realtime data packet to disk + */ +int write_realtime_data(void *data, ssize_t nb) +{ + ssize_t bw; + global_scb.wsize += nb; + if (fsize_max && global_scb.wsize > fsize_max) { + close(out_fd[0]); + global_scb.fnum++; + if (fnum_max && global_scb.fnum == fnum_max) + global_scb.rmfile = 1; + if (open_oldoutfile(global_scb.fnum, 0, + global_scb.rmfile) < 0) { + perr("Couldn't open file, exiting."); + return -1; + } + global_scb.wsize = 0; + } + bw = write(out_fd[0], data, nb); + if (bw >= 0 && bw != nb) { + nb = nb - bw; + bw = write(out_fd[0], data, nb); + } + return bw != nb; +} + /** * init_relayfs - create files and threads for relayfs processing * @@ -249,6 +334,9 @@ int init_oldrelayfs(void) bulkmode = 1; if (!bulkmode) { + if (fsize_max) + return open_oldoutfile(0, 0, 0); + if (outfile_name) { out_fd[0] = open (outfile_name, O_CREAT|O_TRUNC|O_WRONLY, 0666); if (out_fd[0] < 0 || set_clexec(out_fd[0]) < 0) { diff --git a/runtime/staprun/staprun.h b/runtime/staprun/staprun.h index b380cebd..6d0f9179 100644 --- a/runtime/staprun/staprun.h +++ b/runtime/staprun/staprun.h @@ -9,7 +9,7 @@ * * Copyright (C) 2005-2008 Red Hat Inc. */ - +#define _FILE_OFFSET_BITS 64 #include #include #include @@ -117,7 +117,9 @@ int init_relayfs(void); void close_relayfs(void); int init_oldrelayfs(void); void close_oldrelayfs(int); +int write_realtime_data(void *data, ssize_t nb); void setup_signals(void); +int make_outfile_name(char *buf, int max, int fnum, int cpu); /* staprun_funcs.c */ void setup_staprun_signals(void); const char *moderror(int err); @@ -158,6 +160,8 @@ extern int delete_mod; extern int load_only; extern int need_uprobes; extern int daemon_mode; +extern off_t fsize_max; +extern int fnum_max; /* getopt variables */ extern char *optarg; -- cgit From 701c41be909697d5ab36f7604a1f3620c7d04abc Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Fri, 20 Mar 2009 13:31:18 -0400 Subject: PR6930: stap: supports on-file flight recorder options Add on-file flight recorder options (the combination of -F and -o, and -S option) to stap command, and change manpages and NEWS. - Both of -F and -o is specified, stap passes -D option to staprun. - stap just passes -S option to staprun. --- NEWS | 17 +++++++++++++++++ buildrun.cxx | 5 ++++- main.cxx | 10 ++++++++-- session.h | 1 + stap.1.in | 16 +++++++++++++--- staprun.8.in | 15 ++++++++++++++- 6 files changed, 57 insertions(+), 7 deletions(-) diff --git a/NEWS b/NEWS index fff8afc9..d85ec2c0 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,22 @@ * What's new +- On-file flight recorder is supported. It allows stap to record huge + trace log on the disk and to run in background. + Passing -F option with -o option runs stap in background mode. In this + mode, staprun is detached from console, and stap itself shows staprun's + pid and exits. + Specifying the max size and the max number of log files are also available + by passing -S option. This option has one or two arguments seperated by + a comma. The first argument is the max size of a log file in MB. If the + size of a log file exceeds it, stap switches to the next log file + automatically. The second is how many files are kept on the disk. If the + number of log files exceeds it, the oldest log file is removed + automatically. The second argument can be omitted. + + For example, this will record output on log files each of them is smaller + than 1024MB and keep last 3 logs, in background. + % stap -F -o /tmp/staplog -S 1024,3 script.stp + - In guru mode (-g), the kernel probing blacklist is disabled, leaving only a subset - the kernel's own internal kprobe blacklist - to attempt to filter out areas unsafe to probe. The differences may be enough to diff --git a/buildrun.cxx b/buildrun.cxx index 0e9e0e17..e3634545 100644 --- a/buildrun.cxx +++ b/buildrun.cxx @@ -329,7 +329,10 @@ run_pass (systemtap_session& s) staprun_cmd += "-u "; if (s.load_only) - staprun_cmd += "-L "; + staprun_cmd += (s.output_file.empty() ? "-L " : "-D "); + + if (!s.size_option.empty()) + staprun_cmd += "-S " + s.size_option + " "; staprun_cmd += s.tmpdir + "/" + s.module_name + ".ko"; diff --git a/main.cxx b/main.cxx index 890f65bc..6f4064a5 100644 --- a/main.cxx +++ b/main.cxx @@ -111,7 +111,9 @@ usage (systemtap_session& s, int exitcode) << " -o FILE send script output to file, instead of stdout" << endl << " -c CMD start the probes, run CMD, and exit when it finishes" << endl << " -x PID sets target() to PID" << endl - << " -F load module and start probes, then detach" << endl + << " -F run as on-file flight recorder with -o." << endl + << " run as on-memory flight recorder without -o." << endl + << " -S size[,n] set maximum of the size and the number of files." << endl << " -d OBJECT add unwind/symbol data for OBJECT file"; if (s.unwindsym_modules.size() == 0) clog << endl; @@ -444,7 +446,7 @@ main (int argc, char * const argv []) { "vp", 1, &long_opt, LONG_OPT_VERBOSE_PASS }, { NULL, 0, NULL, 0 } }; - int grc = getopt_long (argc, argv, "hVMvtp:I:e:o:R:r:m:kgPc:x:D:bs:uqwl:d:L:F", + int grc = getopt_long (argc, argv, "hVMvtp:I:e:o:R:r:m:kgPc:x:D:bs:uqwl:d:L:FS:", long_options, NULL); if (grc < 0) break; @@ -628,6 +630,10 @@ main (int argc, char * const argv []) s.macros.push_back (string (optarg)); break; + case 'S': + s.size_option = string (optarg); + break; + case 'q': s.tapset_compile_coverage = true; break; diff --git a/session.h b/session.h index ec6c2e3e..820b819e 100644 --- a/session.h +++ b/session.h @@ -90,6 +90,7 @@ struct systemtap_session std::string module_name; std::string stapconf_name; std::string output_file; + std::string size_option; std::string cmd; int target_pid; int last_pass; diff --git a/stap.1.in b/stap.1.in index 5a2e35f9..f997b788 100644 --- a/stap.1.in +++ b/stap.1.in @@ -175,7 +175,7 @@ even if they do not have an explicit probe placed into them. .TP .BI \-o " FILE" Send standard output to named file. In bulk mode, percpu files will -start with FILE_ followed by the cpu number. +start with FILE_ (FILE_cpu with -F) followed by the cpu number. .TP .BI \-c " CMD" Start the probes, run CMD, and exit when CMD finishes. @@ -193,8 +193,18 @@ and aliases. Similar to "-l", but list probe points and script-level local variables. .TP .BI \-F -Load module and start probes, then detach from the module leaving the -probes running. +Without -o option, load module and start probes, then detach from the module +leaving the probes running. +With -o option, run staprun in background as a daemon and show it's pid. +.TP +.BI \-S " size[,N]" +Sets the maximum size of output file and the maximum number of output files. +If the size of output file will exceed +.B size +, systemtap switches output file to the next file. And if the number of +output files exceed +.B N +, systemtap removes the oldest output file. You can omit the second argument. .TP .B \-\-kelf For names and addresses of functions to probe, diff --git a/staprun.8.in b/staprun.8.in index c7e77dc4..68b5c947 100644 --- a/staprun.8.in +++ b/staprun.8.in @@ -52,7 +52,8 @@ The '_stp_target' variable will be set to PID. .TP .B \-o FILE Send output to FILE. If the module uses bulk mode, the output will -be in percpu files FILE_x where 'x' is the cpu number. +be in percpu files FILE_x(FILE_cpux in backgroud and bulk mode) +where 'x' is the cpu number. .TP .B \-b BUFFER_SIZE The systemtap module will specify a buffer size. @@ -73,6 +74,18 @@ Attach to loaded systemtap module. Delete a module. Only detached or unused modules the user has permission to access will be deleted. Use "*" (quoted) to delete all unused modules. +.TP +.BI \-D +Run staprun in background as a daemon and show it's pid. +.TP +.BI \-S " size[,N]" +Sets the maximum size of output file and the maximum number of output files. +If the size of output file will exceed +.B size +, systemtap switches output file to the next file. And if the number of +output files exceed +.B N +, systemtap removes the oldest output file. You can omit the second argument. .SH ARGUMENTS .B MODULE -- cgit From dc6e1d97c43aa173549ad00bb78d7ea86ec90c95 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Fri, 20 Mar 2009 13:33:34 -0400 Subject: PR6930: initscript: support on-file flight recorder Modify systemtap initscript to support on-file flight recoder options. --- initscript/README.initscript | 2 +- initscript/systemtap.in | 22 +++++++++++++--------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/initscript/README.initscript b/initscript/README.initscript index f566cf71..ee11f3be 100644 --- a/initscript/README.initscript +++ b/initscript/README.initscript @@ -1,5 +1,5 @@ Systemtap initscript -Version 0.2 +Version 0.2.1 Author: Masami Hiramatsu INDEX diff --git a/initscript/systemtap.in b/initscript/systemtap.in index eaa1d969..918455d6 100644 --- a/initscript/systemtap.in +++ b/initscript/systemtap.in @@ -287,7 +287,7 @@ stap_getopt () { # opts # TODO: support quoted options getopt -s bash -u \ -l 'kelf,kmap::,ignore-vmlinux,ignore-dwarf,vp:' \ - -o 'hVMvtp:I:e:o:R:r:m:kgPc:x:D:bs:uqwl:d:L:F' -- $@ + -o 'hVMvtp:I:e:o:R:r:m:kgPc:x:D:bs:uqwl:d:L:FS:' -- $@ ret=$? [ $ret -ne 0 ] && slog "Failed to parse parameters. ($@)" return $ret @@ -301,9 +301,9 @@ get_compile_opts () { # opts for o in $opts; do if [ $skip -ne 0 ]; then skip=0; continue; fi case $o in - -p|-m|-r|-c|-x|-e|-s|-o) + -p|-m|-r|-c|-x|-e|-s|-o|-S) skip=1 ;; - -h|-V|-k) + -h|-V|-k|-F) ;; *) echo -n $o" " ;; @@ -312,14 +312,16 @@ get_compile_opts () { # opts } get_run_opts () { # normalized_opts - local opts o show + local opts o show mode opts=`stap_getopt $*` [ $? -ne 0 ] && return 1 + mode='-L' show=0 for o in $opts; do case $o in - -c|-x|-s|-o) + -c|-x|-s|-o|-S) [ $o == '-s' ] && o='-b' + [ $o == '-o' ] && mode='-D' echo -n $o" " show=1 ;; @@ -331,6 +333,7 @@ get_run_opts () { # normalized_opts ;; esac done + echo -n $mode } prepare_cache_dir () { @@ -461,11 +464,12 @@ start_script () { # script return 1 fi pushd "$tmpdir" &> /dev/null - logex $STAPRUN -L $opts "$CACHE_PATH/$s.ko" + eval log \"Exec: $STAPRUN $opts $CACHE_PATH/$s.ko\" + $STAPRUN $opts "$CACHE_PATH/$s.ko" 2>> "$LOG_FILE" > ./pid ret=$? + [ x`cat ./pid` = x ] && echo 0 > ./pid if [ $ret -eq 0 ]; then - # TODO: store daemon pid after supporting on-file flight recorder - echo 0 > "$STAT_PATH/$s" + logex cp -f ./pid "$STAT_PATH/$s" fi popd &> /dev/null rm -rf "$tmpdir" @@ -524,7 +528,7 @@ stop_script () { # script p=`get_daemon_pid $1` if [ $p -ne 0 ]; then - logex killall -TERM $p + logex kill -TERM $p else logex $STAPRUN -d "$1" fi -- cgit From 04ae1b090781725631ba3477ff77721b012cdaba Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Fri, 20 Mar 2009 13:38:29 -0400 Subject: PR9821: staprun supports subset of strftime. Add strftime subset format support for output file name to systemtap. This format will be evaluated when opening a new output file. --- main.cxx | 4 +- runtime/staprun/common.c | 119 +++++++++++++++++++++++++++++++++++++++++++- runtime/staprun/relay.c | 89 +++++++++++++++++++++++++++------ runtime/staprun/relay_old.c | 50 +++++++++++++------ runtime/staprun/staprun.h | 6 ++- stap.1.in | 2 + staprun.8.in | 4 +- 7 files changed, 240 insertions(+), 34 deletions(-) diff --git a/main.cxx b/main.cxx index 6f4064a5..cdcae41a 100644 --- a/main.cxx +++ b/main.cxx @@ -108,7 +108,9 @@ usage (systemtap_session& s, int exitcode) << " " << s.kernel_build_tree << endl << " -m MODULE set probe module name, instead of " << endl << " " << s.module_name << endl - << " -o FILE send script output to file, instead of stdout" << endl + << " -o FILE send script output to file, instead of stdout. This supports" << endl + << " a subset of strftime(3) (%%,%C,%Y,%y,%m,%d,%e,%F,%H,%I,%j,%k," << endl + << " %l,%M,%S,%R,%T,%u,%w) for FILE." << endl << " -c CMD start the probes, run CMD, and exit when it finishes" << endl << " -x PID sets target() to PID" << endl << " -F run as on-file flight recorder with -o." << endl diff --git a/runtime/staprun/common.c b/runtime/staprun/common.c index 194488ef..8200ec9d 100644 --- a/runtime/staprun/common.c +++ b/runtime/staprun/common.c @@ -53,6 +53,113 @@ static char *get_abspath(char *path) return path_buf; } +int stap_strfloctime(char *buf, size_t max, const char *fmt, time_t t) +{ + char *c = buf; + const char *c2 = fmt, *end = buf + max; + int ret, num; + struct tm tm; + if (buf == NULL || fmt == NULL || max <= 1) + return -EINVAL; + localtime_r(&t, &tm); + + while (*c2 != '\0'){ + if (c + 1 >= end) + return -EINVAL; + if (*c2 != '%') { + *c++ = *c2++; + continue; + } + c2++; + switch (*c2++) { + case '%': + *c++ = '%'; + break; + case 'Y': + num = tm.tm_year + 1900; + goto numbering; + case 'y': + num = tm.tm_year % 100; + goto numbering02; + case 'C': + num = ((tm.tm_year + 1900 - 1) / 100) + 1; + goto numbering; + case 'm': + num = tm.tm_mon + 1; + goto numbering02; + case 'd': + num = tm.tm_mday; + goto numbering02; + case 'e': + num = tm.tm_mday; + goto numbering; + case 'F': + ret = snprintf(c, end - c, "%d-%02d-%02d", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); + if (ret < 0) return ret; + c += ret; + break; + case 'H': + num = tm.tm_hour; + goto numbering02; + case 'I': + num = tm.tm_hour % 12; + if (num == 0) num = 12; + goto numbering02; + case 'j': + ret = snprintf(c, end - c, "%03d", tm.tm_yday); + if (ret < 0) return ret; + c += ret; + break; + case 'k': + num = tm.tm_hour; + goto numbering; + case 'l': + num = tm.tm_hour % 12; + if (num == 0) num = 12; + goto numbering; + case 'M': + num = tm.tm_min; + goto numbering02; + case 'S': + num = tm.tm_sec; + goto numbering02; + case 'R': + ret = snprintf(c, end - c, "%02d:%02d", + tm.tm_hour, tm.tm_min); + if (ret < 0) return ret; + c += ret; + break; + case 'T': + ret = snprintf(c, end - c, "%02d:%02d:%02d", + tm.tm_hour, tm.tm_min, tm.tm_sec); + if (ret < 0) return ret; + c += ret; + break; + case 'u': + num = tm.tm_wday == 0 ? 7 : tm.tm_wday; + goto numbering; + case 'w': + num = tm.tm_wday; + goto numbering; + default: + return -EINVAL; + } + continue; +numbering: + ret = snprintf(c, end - c, "%d", num); + if (ret < 0) return ret; + c += ret; + continue; +numbering02: + ret = snprintf(c, end - c, "%02d", num); + if (ret < 0) return ret; + c += ret; + } + *c = '\0'; + return c - buf; +} + void parse_args(int argc, char **argv) { int c; @@ -125,11 +232,19 @@ void parse_args(int argc, char **argv) } } if (outfile_name) { + char tmp[PATH_MAX]; + int ret; outfile_name = get_abspath(outfile_name); if (outfile_name == NULL) { err("File name is too long.\n"); usage(argv[0]); } + ret = stap_strfloctime(tmp, PATH_MAX - 18, /* = _cpuNNN.SSSSSSSSSS */ + outfile_name, time(NULL)); + if (ret < 0) { + err("Filename format is invalid or too long.\n"); + usage(argv[0]); + } } if (attach_mod && load_only) { err("You can't specify the '-A' and '-L' options together.\n"); @@ -191,7 +306,9 @@ void usage(char *prog) err(" exit when it does. The '_stp_target' variable\n"); err(" will contain the pid for the command.\n"); err("-x pid Sets the '_stp_target' variable to pid.\n"); - err("-o FILE Send output to FILE.\n"); + err("-o FILE Send output to FILE. This supports a subset of\n"); + err(" strftime(3) (%%%%,%%C,%%Y,%%y,%%m,%%d,%%e,%%F,%%H,%%I\n"); + err(" %%j,%%k,%%l,%%M,%%S,%%R,%%T,%%u,%%w) for FILE.\n"); err("-b buffer size The systemtap module specifies a buffer size.\n"); err(" Setting one here will override that value. The\n"); err(" value should be an integer between 1 and 4095 \n"); diff --git a/runtime/staprun/relay.c b/runtime/staprun/relay.c index 891913b0..50f295b5 100644 --- a/runtime/staprun/relay.c +++ b/runtime/staprun/relay.c @@ -17,6 +17,9 @@ static pthread_t reader[NR_CPUS]; static int relay_fd[NR_CPUS]; static int bulkmode = 0; static volatile int stop_threads = 0; +static time_t *time_backlog[NR_CPUS]; +static int backlog_order=0; +#define BACKLOG_MASK ((1 << backlog_order) - 1) /* * ppoll exists in glibc >= 2.4 @@ -44,20 +47,52 @@ static int ppoll(struct pollfd *fds, nfds_t nfds, } #endif -int make_outfile_name(char *buf, int max, int fnum, int cpu) +int init_backlog(int cpu) { + int order = 0; + if (!fnum_max) + return 0; + while (fnum_max >> order) order++; + if (fnum_max == 1<<(order-1)) order--; + time_backlog[cpu] = (time_t *)calloc(1< Date: Fri, 20 Mar 2009 15:50:00 -0400 Subject: tweak NEWS blurb wording on --skip-badvars --- NEWS | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index d85ec2c0..7670f681 100644 --- a/NEWS +++ b/NEWS @@ -23,9 +23,9 @@ probe more interrupt handlers. - Variables unavailable in current context may be skipped by setting a - session level flag with command line option --skip-badvars now available. - This will simply substitute the otherwise error causing variable with a - literal 0 and print a warning message when the substitution has been made. + session level flag with command line option --skip-badvars now available. + This replaces any dwarf $variable expressions that could not be resolved + with literal numeric zeros, along with a warning message. * What's new in version 0.9 -- cgit From 9c73606142525f521a44c4907832b2d1e1f3c659 Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Fri, 20 Mar 2009 16:30:02 -0400 Subject: PR9967: don't count -DINTERRUPTIBLE=1 reentrancy against MAXSKIPPED * tapsets.cxx (common_probe_entryfn_prologue): Become conditional on !INTERRUPTIBLE. * translate.cxx (emit_module_exit): Still print skipped_count_reentrant with -t, even if skipped_count was zero. --- stap.1.in | 3 ++- tapsets.cxx | 4 +++- translate.cxx | 5 +++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/stap.1.in b/stap.1.in index 50c092ee..7efa9239 100644 --- a/stap.1.in +++ b/stap.1.in @@ -1056,7 +1056,8 @@ means that the first error will exit the script. MAXSKIPPED Maximum number of skipped probes before an exit is triggered, default 100. Running systemtap with \-t (timing) mode gives more details about skipped -probes. +probes. With the default \-DINTERRUPTIBLE=1 setting, probes skipped due to +reentrancy are not accumulated against this limit. .TP MINSTACKSPACE Minimum number of free kernel stack bytes required in order to diff --git a/tapsets.cxx b/tapsets.cxx index a8653d8a..bc567491 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -206,7 +206,9 @@ common_probe_entryfn_prologue (translator_output* o, string statestr, o->newline() << "c = per_cpu_ptr (contexts, smp_processor_id());"; o->newline() << "if (atomic_inc_return (& c->busy) != 1) {"; - o->newline(1) << "atomic_inc (& skipped_count);"; + o->newline(1) << "#if !INTERRUPTIBLE"; + o->newline() << "atomic_inc (& skipped_count);"; + o->newline() << "#endif"; o->newline() << "#ifdef STP_TIMING"; o->newline() << "atomic_inc (& skipped_count_reentrant);"; o->newline() << "#ifdef DEBUG_REENTRANCY"; diff --git a/translate.cxx b/translate.cxx index 377a11fb..e7c23672 100644 --- a/translate.cxx +++ b/translate.cxx @@ -1360,9 +1360,10 @@ c_unparser::emit_module_exit () o->newline() << "#endif"; } - // print final error/reentrancy counts if non-zero + // print final error/skipped counts if non-zero o->newline() << "if (atomic_read (& skipped_count) || " - << "atomic_read (& error_count)) {"; + << "atomic_read (& error_count) || " + << "atomic_read (& skipped_count_reentrant)) {"; // PR9967 o->newline(1) << "_stp_warn (\"Number of errors: %d, " << "skipped probes: %d\\n\", " << "(int) atomic_read (& error_count), " -- cgit From 422735b3ec857e812097566e28950aa3313892b4 Mon Sep 17 00:00:00 2001 From: Stan Cox Date: Fri, 20 Mar 2009 16:30:19 -0400 Subject: Define static user probe point using asm instead of c. * includes/sys/sdt.h (STAP_PROBE_DATA): New. Define the probe point using asm instead of c. (STAP_PROBEN): Use it. * testsuite/systemtap.base/sdt.exp: Continue if a compile fails. * testsuite/systemtap.base/static_uprobes.exp: Don't test setting probe without .probes section. --- includes/sys/sdt.h | 123 +++++++++++----------------- testsuite/systemtap.base/sdt.exp | 6 +- testsuite/systemtap.base/static_uprobes.exp | 12 ++- 3 files changed, 64 insertions(+), 77 deletions(-) diff --git a/includes/sys/sdt.h b/includes/sys/sdt.h index d6c90192..5b92eeb3 100644 --- a/includes/sys/sdt.h +++ b/includes/sys/sdt.h @@ -13,35 +13,23 @@ #include #include -#if _LP64 -#define STAP_PROBE_STRUCT_ARG(arg) \ - __uint64_t arg -#else -#define STAP_PROBE_STRUCT_ARG(arg) \ - long arg __attribute__ ((aligned(8))) -#endif - -#define STAP_SENTINEL 0x31425250 - -#define STAP_PROBE_STRUCT(probe,argc) \ -struct _probe_ ## probe \ -{ \ - int probe_type; \ - STAP_PROBE_STRUCT_ARG (probe_name); \ - STAP_PROBE_STRUCT_ARG (probe_arg); \ -}; \ -static char probe ## _ ## probe_name [] \ - __attribute__ ((section (".probes"))) \ - = #probe; \ -__extension__ static volatile struct _probe_ ## probe _probe_ ## probe __attribute__ ((section (".probes"))) = {STAP_SENTINEL,(size_t)& probe ## _ ## probe_name[0],argc}; - -/* The goto _probe_ prevents the label from "drifting" */ -#define STAP_LABEL_REF(probe, label) \ - if (__builtin_expect(_probe_ ## probe.probe_type < 0, 0)) \ - goto label; +#define STAP_PROBE_DATA_(probe,label) \ + __asm__ volatile (".section .probes\n" \ + "\t.align 4\n" \ + label "_name:\n\t.asciz " #probe "\n" \ + "\t.align 4\n" \ + "\t.int 0x31425250\n" \ + "\t.align 8\n" \ + "\t.quad " label "_name\n" \ + "\t.quad " label "\n" \ + "\t.previous\n") + +#define STAP_PROBE_DATA(probe,label) \ + STAP_PROBE_DATA_(#probe,label) /* These baroque macros are used to create a unique label */ #define STAP_CONCAT(a,b) a ## b +#define STAP_CONCATSTR(a,b) #a #b #define STAP_LABEL_PREFIX(p) _stapprobe1_ ## p /* __COUNTER__ is not present in gcc 4.1 */ #if __GNUC__ == 4 && __GNUC_MINOR__ >= 3 @@ -49,88 +37,80 @@ __extension__ static volatile struct _probe_ ## probe _probe_ ## probe __attribu #else #define STAP_COUNTER STAP_CONCAT(__,LINE__) #endif -#define STAP_LABEL(a,b) STAP_CONCAT(a,b) +#define STAP_LABEL(a,b) STAP_CONCATSTR(a,b) #define STAP_PROBE_(probe,label) \ do { \ - STAP_PROBE_STRUCT(probe,(size_t)&& label) \ - STAP_LABEL_REF(probe,label); \ -label: \ - __asm__ volatile ("nop"); \ + STAP_PROBE_DATA(probe,label); \ + __asm__ volatile (label ":\n" \ + "\tnop"); \ } while (0) -#define STAP_PROBE1_(probe,label,parm1) \ +#define STAP_PROBE1_(probe,label,parm1) \ do { \ - STAP_PROBE_STRUCT(probe,(size_t)&& label) \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ -label: \ - __asm__ volatile ("nop /* %0 */" :: "X"( arg1)); \ - STAP_LABEL_REF(probe,label); \ + STAP_PROBE_DATA(probe,label); \ + __asm__ volatile (label ":\n" \ + "\tnop /* %0 */" :: "X"(arg1)); \ } while (0) #define STAP_PROBE2_(probe,label,parm1,parm2) \ do { \ - STAP_PROBE_STRUCT(probe,(size_t)&& label) \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ -label: \ - __asm__ volatile ("nop /* %0 %1 */" :: "X"(arg1), "X"(arg2)); \ - STAP_LABEL_REF(probe,label); \ + STAP_PROBE_DATA(probe,label); \ + __asm__ volatile (label ":\n" \ + "\tnop /* %0 %1 */" :: "X"(arg1), "X"(arg2)); \ } while (0) #define STAP_PROBE3_(probe,label,parm1,parm2,parm3) \ do { \ - STAP_PROBE_STRUCT(probe,(size_t)&& label) \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ volatile __typeof__((parm3)) arg3 __attribute__ ((unused)) = parm3; \ -label: \ - __asm__ volatile ("nop /* %0 %1 %2 */" :: "X"(arg1), "X"(arg2), "X"(arg3)); \ - STAP_LABEL_REF(probe,label); \ + STAP_PROBE_DATA(probe,label); \ + __asm__ volatile (label ":\n" \ + "\tnop /* %0 %1 %2 */" :: "X"(arg1), "X"(arg2), "X"(arg3)); \ } while (0) #define STAP_PROBE4_(probe,label,parm1,parm2,parm3,parm4) \ do { \ - STAP_PROBE_STRUCT(probe,(size_t)&& label) \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ volatile __typeof__((parm3)) arg3 __attribute__ ((unused)) = parm3; \ volatile __typeof__((parm4)) arg4 __attribute__ ((unused)) = parm4; \ -label: \ - __asm__ volatile ("nop /* %0 %1 %2 %3 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4)); \ - STAP_LABEL_REF(probe,label); \ + STAP_PROBE_DATA(probe,label); \ + __asm__ volatile (label ":\n" \ + "\tnop /* %0 %1 %2 %3 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4)); \ } while (0) #define STAP_PROBE5_(probe,label,parm1,parm2,parm3,parm4,parm5) \ do { \ - STAP_PROBE_STRUCT(probe,(size_t)&& label) \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ volatile __typeof__((parm3)) arg3 __attribute__ ((unused)) = parm3; \ volatile __typeof__((parm4)) arg4 __attribute__ ((unused)) = parm4; \ volatile __typeof__((parm5)) arg5 __attribute__ ((unused)) = parm5; \ -label: \ - __asm__ volatile ("nop /* %0 %1 %2 %3 %4 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5)); \ - STAP_LABEL_REF(probe,label); \ + STAP_PROBE_DATA(probe,label); \ + __asm__ volatile (label ":\n" \ + "\tnop /* %0 %1 %2 %3 %4 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5)); \ } while (0) #define STAP_PROBE6_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6) \ do { \ - STAP_PROBE_STRUCT(probe,(size_t)&& label) \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ volatile __typeof__((parm3)) arg3 __attribute__ ((unused)) = parm3; \ volatile __typeof__((parm4)) arg4 __attribute__ ((unused)) = parm4; \ volatile __typeof__((parm5)) arg5 __attribute__ ((unused)) = parm5; \ volatile __typeof__((parm6)) arg6 __attribute__ ((unused)) = parm6; \ -label: \ - __asm__ volatile ("nop" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6)); \ - STAP_LABEL_REF(probe,label); \ + STAP_PROBE_DATA(probe,label); \ + __asm__ volatile (label ":\n" \ + "\tnop /* %0 %1 %2 %3 %4 %5 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6)); \ } while (0) -#define STAP_PROBE7_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7) \ +#define STAP_PROBE7_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7) \ do { \ - STAP_PROBE_STRUCT(probe,(size_t)&& label) \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ volatile __typeof__((parm3)) arg3 __attribute__ ((unused)) = parm3; \ @@ -138,14 +118,13 @@ do { \ volatile __typeof__((parm5)) arg5 __attribute__ ((unused)) = parm5; \ volatile __typeof__((parm6)) arg6 __attribute__ ((unused)) = parm6; \ volatile __typeof__((parm7)) arg7 __attribute__ ((unused)) = parm7; \ -label: \ - __asm__ volatile ("nop" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6), "X"(arg7)); \ - STAP_LABEL_REF(probe,label); \ + STAP_PROBE_DATA(probe,label); \ + __asm__ volatile (label ":\n" \ + "\tnop /* %0 %1 %2 %3 %4 %5 %6 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6), "X"(arg7)); \ } while (0) #define STAP_PROBE8_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8) \ do { \ - STAP_PROBE_STRUCT(probe,(size_t)&& label) \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ volatile __typeof__((parm3)) arg3 __attribute__ ((unused)) = parm3; \ @@ -154,14 +133,13 @@ do { \ volatile __typeof__((parm6)) arg6 __attribute__ ((unused)) = parm6; \ volatile __typeof__((parm7)) arg7 __attribute__ ((unused)) = parm7; \ volatile __typeof__((parm8)) arg8 __attribute__ ((unused)) = parm8; \ -label: \ - __asm__ volatile ("nop" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6), "X"(arg7), "X"(arg8)); \ - STAP_LABEL_REF(probe,label); \ + STAP_PROBE_DATA(probe,label); \ + __asm__ volatile (label ":\n" \ + "\tnop /* %0 %1 %2 %3 %4 %5 %6 %7 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6), "X"(arg7), "X"(arg8)); \ } while (0) #define STAP_PROBE9_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9) \ do { \ - STAP_PROBE_STRUCT(probe,(size_t)&& label) \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ volatile __typeof__((parm3)) arg3 __attribute__ ((unused)) = parm3; \ @@ -171,14 +149,13 @@ do { \ volatile __typeof__((parm7)) arg7 __attribute__ ((unused)) = parm7; \ volatile __typeof__((parm8)) arg8 __attribute__ ((unused)) = parm8; \ volatile __typeof__((parm9)) arg9 __attribute__ ((unused)) = parm9; \ -label: \ - __asm__ volatile ("nop" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6), "X"(arg7), "X"(arg8), "X"(arg9)); \ - STAP_LABEL_REF(probe,label); \ + STAP_PROBE_DATA(probe,label); \ + __asm__ volatile (label ":\n" \ + "\tnop /* %0 %1 %2 %3 %4 %5 %6 %7 %8 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6), "X"(arg7), "X"(arg8), "X"(arg9)); \ } while (0) #define STAP_PROBE10_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10) \ do { \ - STAP_PROBE_STRUCT(probe,(size_t)&& label) \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ volatile __typeof__((parm3)) arg3 __attribute__ ((unused)) = parm3; \ @@ -189,9 +166,9 @@ do { \ volatile __typeof__((parm8)) arg8 __attribute__ ((unused)) = parm8; \ volatile __typeof__((parm9)) arg9 __attribute__ ((unused)) = parm9; \ volatile __typeof__((parm10)) arg10 __attribute__ ((unused)) = parm10; \ -label: \ - __asm__ volatile ("nop" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6), "X"(arg7), "X"(arg8), "X"(arg9), "X"(arg10)); \ - STAP_LABEL_REF(probe,label); \ + STAP_PROBE_DATA(probe,label); \ + __asm__ volatile (label ":\n" \ + "\tnop /* %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6), "X"(arg7), "X"(arg8), "X"(arg9), "X"(arg10)); \ } while (0) #define STAP_PROBE(provider,probe) \ diff --git a/testsuite/systemtap.base/sdt.exp b/testsuite/systemtap.base/sdt.exp index 21b94810..a398d795 100644 --- a/testsuite/systemtap.base/sdt.exp +++ b/testsuite/systemtap.base/sdt.exp @@ -27,7 +27,8 @@ set res [target_compile $srcdir/$subdir/$test.c $test.prog executable "$test_fla if { $res != "" } { verbose "target_compile failed: $res" 2 fail "compiling $test.c $extra_flag" - return + untested "$test $extra_flag" + continue } else { pass "compiling $test.c $extra_flag" } @@ -49,7 +50,8 @@ set res [target_compile $srcdir/$subdir/$test.c $test.prog executable "$test_fla if { $res != "" } { verbose "target_compile failed: $res" 2 fail "compiling $test.c c++ $extra_flag" - return + untested "$test $extra_flag" + continue } else { pass "compiling $test.c c++ $extra_flag" } diff --git a/testsuite/systemtap.base/static_uprobes.exp b/testsuite/systemtap.base/static_uprobes.exp index b4214436..e407440e 100644 --- a/testsuite/systemtap.base/static_uprobes.exp +++ b/testsuite/systemtap.base/static_uprobes.exp @@ -103,7 +103,11 @@ if {[installtest_p]} { set sdtdir $srcdir/../includes } -set sup_flags "additional_flags=-I$sdtdir additional_flags=-g additional_flags=-O additional_flags=-I." +set sup_flags "additional_flags=-I$srcdir/../includes/sys" +set sup_flags "$sup_flags additional_flags=-I$sdtdir" +set sup_flags "$sup_flags additional_flags=-g" +set sup_flags "$sup_flags additional_flags=-O" +set sup_flags "$sup_flags additional_flags=-I." set res [target_compile $sup_srcpath $sup_exepath executable $sup_flags] if { $res != "" } { verbose "target_compile failed: $res" 2 @@ -177,6 +181,10 @@ expect { wait -if {$ok == 5} { pass "$test C++" } { fail "$test C++ ($ok)" } +# we now generate the probes via asm so there is no label debug info +if {$ok == 5} { pass "$test C++" } { xfail "$test C++ ($ok)" } +if { $verbose == 0 } { catch {exec rm -f $sup_srcpath $sup_exepath $supcplus_exepath $sup_dpath $sup_hpath $sup_stppath} +} + -- cgit From 11dc6a07aa2aa1c7da1738c20cbc5c19f878374b Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Fri, 20 Mar 2009 19:13:45 -0400 Subject: fix build regression w/o -t * translate.cxx (emit_common_header): Always emit atomic_t skipped_* counters. --- translate.cxx | 2 -- 1 file changed, 2 deletions(-) diff --git a/translate.cxx b/translate.cxx index e7c23672..40bb82c2 100644 --- a/translate.cxx +++ b/translate.cxx @@ -867,12 +867,10 @@ c_unparser::emit_common_header () o->newline() << "static atomic_t session_state = ATOMIC_INIT (STAP_SESSION_STARTING);"; o->newline() << "static atomic_t error_count = ATOMIC_INIT (0);"; o->newline() << "static atomic_t skipped_count = ATOMIC_INIT (0);"; - o->newline() << "#ifdef STP_TIMING"; o->newline() << "static atomic_t skipped_count_lowstack = ATOMIC_INIT (0);"; o->newline() << "static atomic_t skipped_count_reentrant = ATOMIC_INIT (0);"; o->newline() << "static atomic_t skipped_count_uprobe_reg = ATOMIC_INIT (0);"; o->newline() << "static atomic_t skipped_count_uprobe_unreg = ATOMIC_INIT (0);"; - o->newline() << "#endif"; o->newline(); o->newline() << "struct context {"; o->newline(1) << "atomic_t busy;"; -- cgit From a1c66a0f3d8795fbcf49ce936dee3c5645f0bfa6 Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Fri, 20 Mar 2009 19:26:58 -0400 Subject: support tracepoint extraction for kernel build trees built with O=/path * buildrun.cxx (make_tracequery): Also search source/include/trace/*.h. --- buildrun.cxx | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/buildrun.cxx b/buildrun.cxx index e3634545..6a266bd2 100644 --- a/buildrun.cxx +++ b/buildrun.cxx @@ -384,21 +384,25 @@ make_tracequery(systemtap_session& s, string& name) // dynamically pull in all tracepoint headers from include/trace/ glob_t trace_glob; - string glob_str(s.kernel_build_tree + "/include/trace/*.h"); - glob(glob_str.c_str(), 0, NULL, &trace_glob); - for (unsigned i = 0; i < trace_glob.gl_pathc; ++i) + string globs[2] = { "/include/trace/*.h", "/source/include/trace/*.h" }; + for (unsigned z=0; z<2; z++) { - string header(basename(trace_glob.gl_pathv[i])); - - // filter out a few known "internal-only" headers - if (header == "trace_events.h") - continue; - if (header.find("_event_types.h") != string::npos) - continue; - - osrc << "#include " << endl; + string glob_str(s.kernel_build_tree + globs[z]); + glob(glob_str.c_str(), 0, NULL, &trace_glob); + for (unsigned i = 0; i < trace_glob.gl_pathc; ++i) + { + string header(basename(trace_glob.gl_pathv[i])); + + // filter out a few known "internal-only" headers + if (header == "trace_events.h") + continue; + if (header.find("_event_types.h") != string::npos) + continue; + + osrc << "#include " << endl; + } + globfree(&trace_glob); } - globfree(&trace_glob); // finish up the module source osrc << "#endif /* CONFIG_TRACEPOINTS */" << endl; -- cgit From b278033a7e4632a414502b63ba51fcce36f44f94 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 20 Mar 2009 16:35:06 -0700 Subject: Cache the tracepoint query results To use tracepoints, we build a "tracequery" module that compiles debuginfo for all available tracepoints in the user's kernel. That's a bit of a cumbersome step to do during pass-2 though. This change adds tracequery caching so we only need to compile it once. --- hash.cxx | 18 ++++++++++++++++++ hash.h | 1 + session.h | 1 + tapsets.cxx | 34 +++++++++++++++++++++++++++++++++- 4 files changed, 53 insertions(+), 1 deletion(-) diff --git a/hash.cxx b/hash.cxx index 61caa356..b8d5a0e4 100644 --- a/hash.cxx +++ b/hash.cxx @@ -237,4 +237,22 @@ find_hash (systemtap_session& s, const string& script) find_script_hash(s, script, base); } + +void +find_tracequery_hash (systemtap_session& s) +{ + hash h; + get_base_hash(s, h); + + // The basic hash should be good enough for the tracepoint query module + + // Get the directory path to store our cached module + string result, hashdir; + h.result(result); + if (!create_hashdir(s, result, hashdir)) + return; + + s.tracequery_path = hashdir + "/tracequery_" + result + ".ko"; +} + /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ diff --git a/hash.h b/hash.h index d386ad03..0fe95e27 100644 --- a/hash.h +++ b/hash.h @@ -35,5 +35,6 @@ public: }; void find_hash (systemtap_session& s, const std::string& script); +void find_tracequery_hash (systemtap_session& s); /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ diff --git a/session.h b/session.h index 820b819e..cbbae6b2 100644 --- a/session.h +++ b/session.h @@ -117,6 +117,7 @@ struct systemtap_session std::string cache_path; std::string hash_path; std::string stapconf_path; + std::string tracequery_path; // dwarfless operation bool consult_symtab; diff --git a/tapsets.cxx b/tapsets.cxx index bc567491..e9ade595 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -18,6 +18,7 @@ #include "buildrun.h" #include "dwarf_wrappers.h" #include "auto_free.h" +#include "hash.h" #include #include @@ -9993,12 +9994,43 @@ tracepoint_builder::init_dw(systemtap_session& s) if (dw != NULL) return true; + if (s.use_cache) + { + // see if the cached module exists + find_tracequery_hash(s); + if (!s.tracequery_path.empty()) + { + int fd = open(s.tracequery_path.c_str(), O_RDONLY); + if (fd != -1) + { + if (s.verbose > 2) + clog << "Pass 2: using cached " << s.tracequery_path << endl; + + dw = new dwflpp(s); + dw->setup_user(s.tracequery_path); + close(fd); + return true; + } + } + } + + // no cached module, time to make it string tracequery_ko; int rc = make_tracequery(s, tracequery_ko); if (rc != 0) return false; - // TODO cache tracequery.ko + if (s.use_cache) + { + // try to save tracequery in the cache + if (s.verbose > 2) + clog << "Copying " << tracequery_ko + << " to " << s.tracequery_path << endl; + if (copy_file(tracequery_ko.c_str(), + s.tracequery_path.c_str()) != 0) + cerr << "Copy failed (\"" << tracequery_ko << "\" to \"" + << s.tracequery_path << "\"): " << strerror(errno) << endl; + } dw = new dwflpp(s); dw->setup_user(tracequery_ko); -- cgit From ccd65d4a6f99ded6bfc05deee39f9d20816ca8a6 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 20 Mar 2009 17:12:15 -0700 Subject: Document @cast module search paths --- NEWS | 5 +++++ stap.1.in | 10 ++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 7670f681..4a65bacb 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,10 @@ * What's new +- Typecasting with @cast now supports modules search paths, which is + useful in case there are multiple places where the type definition + may be found. For example: + @cast(sdev, "scsi_device", "kernel:scsi_mod")->sdev_state + - On-file flight recorder is supported. It allows stap to record huge trace log on the disk and to run in background. Passing -F option with -o option runs stap in background mode. In this diff --git a/stap.1.in b/stap.1.in index 7efa9239..c562c8b7 100644 --- a/stap.1.in +++ b/stap.1.in @@ -788,10 +788,12 @@ and dereference the .I member value. The optional .I module -tells the translator where to look for information about that type. If -the module is not specified, it will default either to the probe module -for dwarf probes, or to "kernel" for functions and all other probes -types. +tells the translator where to look for information about that type. +Multiple modules may be specified as a list with +.IR : +separators. If the module is not specified, it will default either to +the probe module for dwarf probes, or to "kernel" for functions and all +other probes types. .PP When in guru mode, the translator will also allow scripts to assign new values to members of typecasted pointers. -- cgit From b1a4288cb2293d59010e3c0183f582b65b7e163e Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 20 Mar 2009 17:49:32 -0700 Subject: Add a tracepoint NEWS blurb --- NEWS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/NEWS b/NEWS index 4a65bacb..7ae93675 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,12 @@ * What's new +- Kernel tracepoints are now supported for probing predefined kernel + events without any debuginfo. Tracepoints incur less overhead than + kprobes, and context parameters are available with full type + information. Any kernel 2.6.28 and later should have defined + tracepoints. Try the following to see what's available: + $ stap -L 'kernel.trace("*")' + - Typecasting with @cast now supports modules search paths, which is useful in case there are multiple places where the type definition may be found. For example: -- cgit From b08db79a21adfb5e2fb38b711269a7d0125d1d53 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 20 Mar 2009 17:51:47 -0700 Subject: Update a few new AUTHORS --- AUTHORS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/AUTHORS b/AUTHORS index 6a20ef72..0ed3ed04 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,6 +1,7 @@ Ananth N Mavinakayanahalli Anil Keshavamurthy Anithra Janakiraman +Breno Leitao Charles Spirakis Dan Horak Dave Brolley @@ -21,6 +22,8 @@ K.Prasad Kent Sebastian Kevin Stafford Li Guanglei +Lubomir Rintel +Mahesh J Salgaonkar Mark McLoughlin Mark Wielaard Martin Hunt -- cgit From a99eea4f68db917268b83ab75574c832b646bd65 Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Sat, 21 Mar 2009 08:39:57 -0400 Subject: sdt.exp: save intermediate sdt.h-client executables for analysis * testsuite/lib/stap_run2.exp (stap_run3): Put supplied stap extra arguments after the .stp script name, not before, so that @1/such arguments can be substituted within. --- testsuite/lib/stap_run2.exp | 2 +- testsuite/systemtap.base/sdt.exp | 14 +++++++++----- testsuite/systemtap.base/sdt.stp | 20 ++++++++++---------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/testsuite/lib/stap_run2.exp b/testsuite/lib/stap_run2.exp index b734a1e7..d1f02c83 100644 --- a/testsuite/lib/stap_run2.exp +++ b/testsuite/lib/stap_run2.exp @@ -29,7 +29,7 @@ proc stap_run2 { TEST_NAME args } { proc stap_run3 { TEST_NAME TEST_FILE args } { if {[info procs installtest_p] != "" && ![installtest_p]} { untested $TEST_NAME; return } - set cmd [concat stap $args $TEST_FILE] + set cmd [concat stap $TEST_FILE $args] send_log "executing: $cmd\n" catch {eval exec $cmd} res diff --git a/testsuite/systemtap.base/sdt.exp b/testsuite/systemtap.base/sdt.exp index a398d795..46fa5a28 100644 --- a/testsuite/systemtap.base/sdt.exp +++ b/testsuite/systemtap.base/sdt.exp @@ -15,6 +15,7 @@ set extra_flags {{""} {additional_flags=-std=gnu89} {additional_flags=-ansi} {ad # Iterate extra_flags, trying each with C and C++ for {set i 0} {$i < [llength $extra_flags]} {incr i} { set extra_flag [lindex $extra_flags $i] +set testprog "sdt.c.exe.$i" # C set test_flags "additional_flags=-g" @@ -23,7 +24,9 @@ set test_flags "$test_flags additional_flags=-Wall" set test_flags "$test_flags additional_flags=-Wextra" set test_flags "$test_flags additional_flags=-Werror" -set res [target_compile $srcdir/$subdir/$test.c $test.prog executable "$test_flags $extra_flag"] +set saveidx 0 + +set res [target_compile $srcdir/$subdir/$test.c $testprog executable "$test_flags $extra_flag"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "compiling $test.c $extra_flag" @@ -34,19 +37,21 @@ if { $res != "" } { } if {[installtest_p]} { - stap_run3 "$test $extra_flag" $srcdir/$subdir/$test.stp -c ./$test.prog + stap_run3 "$test $extra_flag" $srcdir/$subdir/$test.stp $testprog -c ./$testprog } else { untested "$test $extra_flag" } # C++ +set testprog "sdt.cxx.exe.$i" + set test_flags "additional_flags=-g" set test_flags "$test_flags additional_flags=-I$srcdir/../includes/sys" set test_flags "$test_flags additional_flags=-Wall" set test_flags "$test_flags additional_flags=-Werror" set test_flags "$test_flags additional_flags=-x additional_flags=c++" -set res [target_compile $srcdir/$subdir/$test.c $test.prog executable "$test_flags $extra_flag"] +set res [target_compile $srcdir/$subdir/$test.c $testprog executable "$test_flags $extra_flag"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "compiling $test.c c++ $extra_flag" @@ -57,10 +62,9 @@ if { $res != "" } { } if {[installtest_p]} { - stap_run3 "$test c++ $extra_flag" $srcdir/$subdir/$test.stp -c ./$test.prog + stap_run3 "$test c++ $extra_flag" $srcdir/$subdir/$test.stp $testprog -c ./$testprog } else { untested "$test c++ $extra_flag" } } -catch {exec rm -f $test.prog} diff --git a/testsuite/systemtap.base/sdt.stp b/testsuite/systemtap.base/sdt.stp index 1f075bca..5df1fdc9 100644 --- a/testsuite/systemtap.base/sdt.stp +++ b/testsuite/systemtap.base/sdt.stp @@ -1,49 +1,49 @@ -probe process("sdt.prog").mark("mark_a") +probe process(@1).mark("mark_a") { printf("%d\n", $arg1); } -probe process("sdt.prog").mark("mark_b") +probe process(@1).mark("mark_b") { printf("%d %d\n", $arg1, $arg2); } -probe process("sdt.prog").mark("mark_c") +probe process(@1).mark("mark_c") { printf("%d %d %d\n", $arg1, $arg2, $arg3); } -probe process("sdt.prog").mark("mark_d") +probe process(@1).mark("mark_d") { printf("%d %d %d %d\n", $arg1, $arg2, $arg3, $arg4); } -probe process("sdt.prog").mark("mark_e") +probe process(@1).mark("mark_e") { printf("%d %d %d %d %d\n", $arg1, $arg2, $arg3, $arg4, $arg5); } -probe process("sdt.prog").mark("mark_f") +probe process(@1).mark("mark_f") { printf("%d %d %d %d %d %d\n", $arg1, $arg2, $arg3, $arg4, $arg5, $arg6); } -probe process("sdt.prog").mark("mark_g") +probe process(@1).mark("mark_g") { printf("%d %d %d %d %d %d %d\n", $arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7); } -probe process("sdt.prog").mark("mark_h") +probe process(@1).mark("mark_h") { printf("%d %d %d %d %d %d %d %d\n", $arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7, $arg8); } -probe process("sdt.prog").mark("mark_i") +probe process(@1).mark("mark_i") { printf("%d %d %d %d %d %d %d %d %d\n", $arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7, $arg8, $arg9); } -probe process("sdt.prog").mark("mark_j") +probe process(@1).mark("mark_j") { printf("%d %d %d %d %d %d %d %d %d %d\n", $arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7, $arg8, $arg9, $arg10); } -- cgit From 1fa23e70a939c20664d7ae6ee5ef66b51835e0ee Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Sun, 22 Mar 2009 11:20:23 -0400 Subject: PR9974: adapt to utrace_connected_engine -> utrace_engine Adjusted all headers that #include to follow with: /* PR9974: Adapt to struct renaming. */ --- runtime/itrace.c | 6 ++++++ runtime/task_finder.c | 6 ++++++ runtime/uprobes2/uprobes.c | 6 ++++++ runtime/uprobes2/uprobes.h | 5 +++++ runtime/utrace_compatibility.h | 5 +++++ 5 files changed, 28 insertions(+) diff --git a/runtime/itrace.c b/runtime/itrace.c index 3d9ded2f..618cbff0 100644 --- a/runtime/itrace.c +++ b/runtime/itrace.c @@ -18,6 +18,12 @@ #include #include #include + +/* PR9974: Adapt to struct renaming. */ +#ifdef UTRACE_API_VERSION +#define utrace_attached_engine utrace_engine +#endif + #include #include "uprobes/uprobes.h" #include "utrace_compatibility.h" diff --git a/runtime/task_finder.c b/runtime/task_finder.c index 2b408763..3f4908cb 100644 --- a/runtime/task_finder.c +++ b/runtime/task_finder.c @@ -6,6 +6,12 @@ #endif #include + +/* PR9974: Adapt to struct renaming. */ +#ifdef UTRACE_API_VERSION +#define utrace_attached_engine utrace_engine +#endif + #include #include #include diff --git a/runtime/uprobes2/uprobes.c b/runtime/uprobes2/uprobes.c index af187fc9..a0e9f2fe 100644 --- a/runtime/uprobes2/uprobes.c +++ b/runtime/uprobes2/uprobes.c @@ -29,6 +29,12 @@ #include #include #define UPROBES_IMPLEMENTATION 1 + +/* PR9974: Adapt to struct renaming. */ +#ifdef UTRACE_API_VERSION +#define utrace_attached_engine utrace_engine +#endif + #include "uprobes.h" #include #include diff --git a/runtime/uprobes2/uprobes.h b/runtime/uprobes2/uprobes.h index 11d01f5c..112e29e2 100644 --- a/runtime/uprobes2/uprobes.h +++ b/runtime/uprobes2/uprobes.h @@ -23,6 +23,11 @@ #include #include +/* Adapt to struct renaming. */ +#ifdef UTRACE_API_VERSION +#define utrace_attached_engine utrace_engine +#endif + struct pt_regs; enum uprobe_type { diff --git a/runtime/utrace_compatibility.h b/runtime/utrace_compatibility.h index 4a70da42..5521a5c2 100644 --- a/runtime/utrace_compatibility.h +++ b/runtime/utrace_compatibility.h @@ -13,6 +13,11 @@ #include +/* PR9974: Adapt to struct renaming. */ +#ifdef UTRACE_API_VERSION +#define utrace_attached_engine utrace_engine +#endif + #ifdef UTRACE_ACTION_RESUME /* -- cgit From 407658581b73f4f4a99e002f085a06c4ebb0864b Mon Sep 17 00:00:00 2001 From: Stan Cox Date: Mon, 23 Mar 2009 10:10:03 -0400 Subject: Make .probes 32 bit aware and simplify label handling. * includes/sys/sdt.h (STAP_PROBE_DATA_): Use gas local labels which avoids a mysql problem when a function containing a probe is inlined. Make the data placement 32 bit aware. --- includes/sys/sdt.h | 118 +++++++++++++++++++++++++---------------------------- 1 file changed, 56 insertions(+), 62 deletions(-) diff --git a/includes/sys/sdt.h b/includes/sys/sdt.h index 5b92eeb3..3da4ff66 100644 --- a/includes/sys/sdt.h +++ b/includes/sys/sdt.h @@ -13,90 +13,84 @@ #include #include -#define STAP_PROBE_DATA_(probe,label) \ +#define STAP_PROBE_DATA_(probe,dataop) \ __asm__ volatile (".section .probes\n" \ - "\t.align 4\n" \ - label "_name:\n\t.asciz " #probe "\n" \ + "\t.align 8\n" \ + "1:\n\t.asciz " #probe "\n" \ "\t.align 4\n" \ "\t.int 0x31425250\n" \ - "\t.align 8\n" \ - "\t.quad " label "_name\n" \ - "\t.quad " label "\n" \ + "\t.align 8\n" \ + "\t" #dataop " 1b\n" \ + "\t.align 8\n" \ + "\t" #dataop " 2f\n" \ "\t.previous\n") -#define STAP_PROBE_DATA(probe,label) \ - STAP_PROBE_DATA_(#probe,label) - -/* These baroque macros are used to create a unique label */ -#define STAP_CONCAT(a,b) a ## b -#define STAP_CONCATSTR(a,b) #a #b -#define STAP_LABEL_PREFIX(p) _stapprobe1_ ## p -/* __COUNTER__ is not present in gcc 4.1 */ -#if __GNUC__ == 4 && __GNUC_MINOR__ >= 3 -#define STAP_COUNTER STAP_CONCAT(__,COUNTER__) +#if _LP64 +#define STAP_PROBE_DATA(probe) \ + STAP_PROBE_DATA_(#probe,.quad) #else -#define STAP_COUNTER STAP_CONCAT(__,LINE__) +#define STAP_PROBE_DATA(probe) \ + STAP_PROBE_DATA_(#probe,.long) #endif -#define STAP_LABEL(a,b) STAP_CONCATSTR(a,b) -#define STAP_PROBE_(probe,label) \ +#define STAP_PROBE_(probe) \ do { \ - STAP_PROBE_DATA(probe,label); \ - __asm__ volatile (label ":\n" \ + STAP_PROBE_DATA(probe); \ + __asm__ volatile ("2:\n" \ "\tnop"); \ } while (0) -#define STAP_PROBE1_(probe,label,parm1) \ +#define STAP_PROBE1_(probe,parm1) \ do { \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ - STAP_PROBE_DATA(probe,label); \ - __asm__ volatile (label ":\n" \ + STAP_PROBE_DATA(probe); \ + __asm__ volatile ("2:\n" \ "\tnop /* %0 */" :: "X"(arg1)); \ } while (0) -#define STAP_PROBE2_(probe,label,parm1,parm2) \ +#define STAP_PROBE2_(probe,parm1,parm2) \ do { \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ - STAP_PROBE_DATA(probe,label); \ - __asm__ volatile (label ":\n" \ + STAP_PROBE_DATA(probe); \ + __asm__ volatile ("2:\n" \ "\tnop /* %0 %1 */" :: "X"(arg1), "X"(arg2)); \ } while (0) -#define STAP_PROBE3_(probe,label,parm1,parm2,parm3) \ +#define STAP_PROBE3_(probe,parm1,parm2,parm3) \ do { \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ volatile __typeof__((parm3)) arg3 __attribute__ ((unused)) = parm3; \ - STAP_PROBE_DATA(probe,label); \ - __asm__ volatile (label ":\n" \ + STAP_PROBE_DATA(probe); \ + __asm__ volatile ("2:\n" \ "\tnop /* %0 %1 %2 */" :: "X"(arg1), "X"(arg2), "X"(arg3)); \ } while (0) -#define STAP_PROBE4_(probe,label,parm1,parm2,parm3,parm4) \ +#define STAP_PROBE4_(probe,parm1,parm2,parm3,parm4) \ do { \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ volatile __typeof__((parm3)) arg3 __attribute__ ((unused)) = parm3; \ volatile __typeof__((parm4)) arg4 __attribute__ ((unused)) = parm4; \ - STAP_PROBE_DATA(probe,label); \ - __asm__ volatile (label ":\n" \ + STAP_PROBE_DATA(probe); \ + __asm__ volatile ("2:\n" \ "\tnop /* %0 %1 %2 %3 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4)); \ } while (0) -#define STAP_PROBE5_(probe,label,parm1,parm2,parm3,parm4,parm5) \ +#define STAP_PROBE5_(probe,parm1,parm2,parm3,parm4,parm5) \ do { \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ volatile __typeof__((parm3)) arg3 __attribute__ ((unused)) = parm3; \ volatile __typeof__((parm4)) arg4 __attribute__ ((unused)) = parm4; \ volatile __typeof__((parm5)) arg5 __attribute__ ((unused)) = parm5; \ - STAP_PROBE_DATA(probe,label); \ - __asm__ volatile (label ":\n" \ + STAP_PROBE_DATA(probe); \ + __asm__ volatile ("2:\n" \ "\tnop /* %0 %1 %2 %3 %4 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5)); \ } while (0) -#define STAP_PROBE6_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6) \ +#define STAP_PROBE6_(probe,parm1,parm2,parm3,parm4,parm5,parm6) \ do { \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ @@ -104,12 +98,12 @@ do { \ volatile __typeof__((parm4)) arg4 __attribute__ ((unused)) = parm4; \ volatile __typeof__((parm5)) arg5 __attribute__ ((unused)) = parm5; \ volatile __typeof__((parm6)) arg6 __attribute__ ((unused)) = parm6; \ - STAP_PROBE_DATA(probe,label); \ - __asm__ volatile (label ":\n" \ + STAP_PROBE_DATA(probe); \ + __asm__ volatile ("2:\n" \ "\tnop /* %0 %1 %2 %3 %4 %5 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6)); \ } while (0) -#define STAP_PROBE7_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7) \ +#define STAP_PROBE7_(probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7) \ do { \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ @@ -118,12 +112,12 @@ do { \ volatile __typeof__((parm5)) arg5 __attribute__ ((unused)) = parm5; \ volatile __typeof__((parm6)) arg6 __attribute__ ((unused)) = parm6; \ volatile __typeof__((parm7)) arg7 __attribute__ ((unused)) = parm7; \ - STAP_PROBE_DATA(probe,label); \ - __asm__ volatile (label ":\n" \ + STAP_PROBE_DATA(probe); \ + __asm__ volatile ("2:\n" \ "\tnop /* %0 %1 %2 %3 %4 %5 %6 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6), "X"(arg7)); \ } while (0) -#define STAP_PROBE8_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8) \ +#define STAP_PROBE8_(probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8) \ do { \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ @@ -133,12 +127,12 @@ do { \ volatile __typeof__((parm6)) arg6 __attribute__ ((unused)) = parm6; \ volatile __typeof__((parm7)) arg7 __attribute__ ((unused)) = parm7; \ volatile __typeof__((parm8)) arg8 __attribute__ ((unused)) = parm8; \ - STAP_PROBE_DATA(probe,label); \ - __asm__ volatile (label ":\n" \ + STAP_PROBE_DATA(probe); \ + __asm__ volatile ("2:\n" \ "\tnop /* %0 %1 %2 %3 %4 %5 %6 %7 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6), "X"(arg7), "X"(arg8)); \ } while (0) -#define STAP_PROBE9_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9) \ +#define STAP_PROBE9_(probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9) \ do { \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ @@ -149,12 +143,12 @@ do { \ volatile __typeof__((parm7)) arg7 __attribute__ ((unused)) = parm7; \ volatile __typeof__((parm8)) arg8 __attribute__ ((unused)) = parm8; \ volatile __typeof__((parm9)) arg9 __attribute__ ((unused)) = parm9; \ - STAP_PROBE_DATA(probe,label); \ - __asm__ volatile (label ":\n" \ + STAP_PROBE_DATA(probe); \ + __asm__ volatile ("2:\n" \ "\tnop /* %0 %1 %2 %3 %4 %5 %6 %7 %8 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6), "X"(arg7), "X"(arg8), "X"(arg9)); \ } while (0) -#define STAP_PROBE10_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10) \ +#define STAP_PROBE10_(probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10) \ do { \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ @@ -166,33 +160,33 @@ do { \ volatile __typeof__((parm8)) arg8 __attribute__ ((unused)) = parm8; \ volatile __typeof__((parm9)) arg9 __attribute__ ((unused)) = parm9; \ volatile __typeof__((parm10)) arg10 __attribute__ ((unused)) = parm10; \ - STAP_PROBE_DATA(probe,label); \ - __asm__ volatile (label ":\n" \ + STAP_PROBE_DATA(probe); \ + __asm__ volatile ("2:\n" \ "\tnop /* %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6), "X"(arg7), "X"(arg8), "X"(arg9), "X"(arg10)); \ } while (0) #define STAP_PROBE(provider,probe) \ - STAP_PROBE_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER)) + STAP_PROBE_(probe) #define STAP_PROBE1(provider,probe,parm1) \ - STAP_PROBE1_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1)) + STAP_PROBE1_(probe,(parm1)) #define STAP_PROBE2(provider,probe,parm1,parm2) \ - STAP_PROBE2_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2)) + STAP_PROBE2_(probe,(parm1),(parm2)) #define STAP_PROBE3(provider,probe,parm1,parm2,parm3) \ - STAP_PROBE3_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2),(parm3)) + STAP_PROBE3_(probe,(parm1),(parm2),(parm3)) #define STAP_PROBE4(provider,probe,parm1,parm2,parm3,parm4) \ - STAP_PROBE4_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2),(parm3),(parm4)) + STAP_PROBE4_(probe,(parm1),(parm2),(parm3),(parm4)) #define STAP_PROBE5(provider,probe,parm1,parm2,parm3,parm4,parm5) \ - STAP_PROBE5_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2),(parm3),(parm4),(parm5)) + STAP_PROBE5_(probe,(parm1),(parm2),(parm3),(parm4),(parm5)) #define STAP_PROBE6(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6) \ - STAP_PROBE6_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2),(parm3),(parm4),(parm5),(parm6)) + STAP_PROBE6_(probe,(parm1),(parm2),(parm3),(parm4),(parm5),(parm6)) #define STAP_PROBE7(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7) \ - STAP_PROBE7_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2),(parm3),(parm4),(parm5),(parm6),(parm7)) + STAP_PROBE7_(probe,(parm1),(parm2),(parm3),(parm4),(parm5),(parm6),(parm7)) #define STAP_PROBE8(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8) \ - STAP_PROBE8_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2),(parm3),(parm4),(parm5),(parm6),(parm7),(parm8)) + STAP_PROBE8_(probe,(parm1),(parm2),(parm3),(parm4),(parm5),(parm6),(parm7),(parm8)) #define STAP_PROBE9(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9) \ - STAP_PROBE9_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2),(parm3),(parm4),(parm5),(parm6),(parm7),(parm8),(parm9)) + STAP_PROBE9_(probe,(parm1),(parm2),(parm3),(parm4),(parm5),(parm6),(parm7),(parm8),(parm9)) #define STAP_PROBE10(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10) \ - STAP_PROBE10_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2),(parm3),(parm4),(parm5),(parm6),(parm7),(parm8),(parm9),(parm10)) + STAP_PROBE10_(probe,(parm1),(parm2),(parm3),(parm4),(parm5),(parm6),(parm7),(parm8),(parm9),(parm10)) #define DTRACE_PROBE(provider,probe) \ STAP_PROBE(provider,probe) -- cgit From d4db5608dbc31868a2041f20ea3f473eef3e61fd Mon Sep 17 00:00:00 2001 From: William Cohen Date: Mon, 23 Mar 2009 11:16:13 -0400 Subject: Add missing escape in kernel-doc create_sparameterlist() matching. --- scripts/kernel-doc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 9947882d..92178910 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1774,7 +1774,7 @@ sub create_sparameterlist($$$) { my $param; foreach my $arg (split($splitter, $args)) { - if ($arg =~ m/s*([\w]+)\s*:?\s*([\w]*)/) { + if ($arg =~ m/\s*([\w]+)\s*:?\s*([\w]*)/) { $param = $1; $type = $2; push_parameter($param, $type, $file); -- cgit