1 /* Copyright (C) 2010 Free Software Foundation, Inc.
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 3 of the License, or
6 (at your option) any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
29 #ifndef STAP_SCRIPT_FILENAME
30 #error "STAP_SCRIPT_FILENAME is required"
33 #define STRINGIFY1(lit) #lit
34 #define STRINGIFY(lit) STRINGIFY1 (lit)
35 #define _(x) gettext (x)
37 static int opt_d, opt_f, opt_q, opt_p;
38 /* Verified we should run the -ff postprocessor. */
41 static size_t opt_o_len;
43 /* Script filename. */
44 static char *opt_Z = STRINGIFY (STAP_SCRIPT_FILENAME);
49 void *retval = malloc (size);
52 error (EXIT_FAILURE, errno, _("memory allocation of %zu bytes"), size);
57 /* warning: EOF is also an error. */
59 xread (int fd, void *buf, size_t count)
61 ssize_t retval = read (fd, buf, count);
64 error (EXIT_FAILURE, errno, _("Error reading data"));
69 /* warning: No events are also an error. */
71 xpoll (struct pollfd *fds, nfds_t nfds, int timeout)
73 if (poll (fds, nfds, timeout) != 1)
74 error (EXIT_FAILURE, errno, _("poll returned error"));
80 pid_t retval = fork ();
83 error (EXIT_FAILURE, errno, _("Error calling fork"));
89 xsnprintf (char *str, size_t size, const char *format, ...)
94 va_start (ap, format);
95 i = vsnprintf (str, size, format, ap);
97 if (i <= 0 || strlen (str) >= size - 1)
98 error (EXIT_FAILURE, errno, _("Error calling sprintf"));
102 xfflush (FILE *stream)
104 if (fflush (stream) != 0)
105 error (EXIT_FAILURE, errno, _("Error calling fflush"));
109 xdup2 (int oldfd, int newfd)
111 if (dup2 (oldfd, newfd) != newfd)
112 error (EXIT_FAILURE, errno, _("Error calling dup2 (%d, %d)"), oldfd,
120 error (EXIT_FAILURE, errno, _("Error calling close (%d)"), fd);
124 xpipe (int pipefd[2])
126 if (pipe (pipefd) != 0)
127 error (EXIT_FAILURE, errno, _("Error creating internal pipe"));
133 if (raise (sig) != 0)
134 error (EXIT_FAILURE, errno, _("Error calling raise (%d)"), sig);
138 xfcntl_setfl (int fd, int cmdarg)
140 if (fcntl (fd, F_SETFL, cmdarg) != 0)
141 error (EXIT_FAILURE, errno,
142 _("Error calling fcntl (%d, F_SETFL, 0%o)"), fd, cmdarg);
146 xwrite (int fd, const void *buf, size_t count)
151 if ((ssize_t) count < 0 || write (fd, buf, count) != (ssize_t) count)
152 error (EXIT_FAILURE, errno,
153 _("Error calling write (%d, ..., %zu)"), fd, count);
157 xopen (const char *pathname, int flags, mode_t mode)
159 int retval = open (pathname, flags, mode);
162 error (EXIT_FAILURE, errno,
163 _("Error %s file \"%s\" (flags 0x%x, mode 0%o)"),
164 flags & O_APPEND ? _("appending")
165 : (flags & O_CREAT ? _("creating")
167 pathname, flags, mode);
176 usage: staptrace [-dfq] [-o file] [-p pid] [command [arg ...]]\n\
177 [-Z <stap script>]\n\
186 dump_args (char **args)
190 for (argp = args; *argp; argp++)
194 fputs (*argp, stderr);
196 fputc ('\n', stderr);
200 ff_filter (int fd_read)
202 char buf[getpagesize ()];
204 /* Does the buf start on a line boundary? */
206 /* Initial fd if no `\n[' is seen at the start. */
207 int fd_write = STDOUT_FILENO;
209 xfcntl_setfl (fd_read, O_NONBLOCK);
213 struct pollfd pollfd;
216 pollfd.events = POLLIN;
218 xpoll (&pollfd, 1, -1);
220 if (pollfd.revents & ~(POLLIN | POLLHUP) || pollfd.revents == 0)
221 error (EXIT_FAILURE, errno, _("poll returned error revents 0x%x"),
224 if (pollfd.revents & POLLIN)
231 want = sizeof (buf) - buf_len - 1;
233 got = xread (fd_read, &buf[buf_len], want);
234 if (memchr (&buf[buf_len], 0, got) != NULL)
235 error (EXIT_FAILURE, 0,
236 _("Unexpected \\0 in the internal -ff stream"));
240 fprintf (stderr, "buf_len %zu + %zd = %zu, read: {%s}\n",
241 buf_len - got, got, buf_len, &buf[buf_len - got]);
245 /* Keep the last character for `c' or `n' line continuations. */
246 while (start + 1 < &buf[buf_len])
250 static char fname[FILENAME_MAX];
256 s = strchr (start, '\n');
259 len = strlen (start);
261 if (start[len - 1] == 'c' || start[len - 1] == 'n')
263 xwrite (fd_write, start, len);
269 if (start[len] == 'n')
271 xwrite (fd_write, start, len);
278 error (EXIT_FAILURE, 0,
279 _("'[' (at 0x%lx) expected in the internal -ff stream"),
280 (unsigned long) (start - buf));
283 /* We need more data. */
286 ul = strtoul (&start[1], &end, 10);
287 assert (end != NULL);
290 /* We need more data. */
293 if (end > start + 64 || *end != ']' || end == &start[1])
294 error (EXIT_FAILURE, 0,
295 _("Invalid TID in the internal -ff stream: %s"), start);
299 xsnprintf (fname, sizeof (fname), "%s.%lu", opt_o, ul);
300 if (fd_write != STDOUT_FILENO)
302 fd_write = xopen (fname, O_WRONLY | O_APPEND | O_CREAT, 0644);
307 want = &buf[buf_len] - start;
308 memmove (buf, start, want);
313 if (pollfd.revents & POLLHUP)
317 if (fd_write != STDOUT_FILENO)
322 main (int argc, char **argv)
326 args = xmalloc (sizeof (*args) * argc * 2 + 32);
334 i = getopt (argc, argv, "+dfqo:p:hZ:");
352 opt_o_len = strlen (opt_o);
363 usage (EXIT_SUCCESS);
365 usage (EXIT_FAILURE);
369 if ((optind == argc) == !opt_p)
370 usage (EXIT_FAILURE);
375 static char kill_s[256];
376 static char option_s[256];
383 execvp (argv[optind], &argv[optind]);
384 error (EXIT_FAILURE, errno, _("Error executing child command"));
387 /* FIXME: Call `kill -CONT' from the systamtap script. How? */
388 xsnprintf (kill_s, sizeof (kill_s),
390 "while [ -e /proc/%lu/root ]; do sleep 0.1; done",
391 (unsigned long) child, (unsigned long) child);
394 xsnprintf (option_s, sizeof (option_s), "opt_child=%lu",
395 (unsigned long) child);
401 xdup2 (STDERR_FILENO, STDOUT_FILENO);
422 *argp++ = "opt_ff=1";
427 /* -ff is the same like -f when no -o is specified. */
448 ff_filter (pipefd[0]);
453 xdup2 (pipefd[1], STDOUT_FILENO);
457 execvp ("stap", args);
461 error (EXIT_FAILURE, errno, _("Error executing stap"));