aboutsummaryrefslogtreecommitdiff
path: root/options.c
diff options
context:
space:
mode:
Diffstat (limited to 'options.c')
-rw-r--r--options.c374
1 files changed, 192 insertions, 182 deletions
diff --git a/options.c b/options.c
index 4f02a06..63f2ff3 100644
--- a/options.c
+++ b/options.c
@@ -2,6 +2,10 @@
#include "config.h"
#endif
+#ifndef PACKAGE_VERSION
+# define PACKAGE_VERSION "0.3.32"
+#endif
+
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
@@ -21,7 +25,7 @@
char *library[MAX_LIBRARY];
int library_num = 0;
static char *progname; /* Program name (`ltrace') */
-FILE *output;
+FILE * output;
int opt_a = DEFAULT_ACOLUMN; /* default alignment column for results */
int opt_c = 0; /* Count time, calls, and report a summary on program exit */
int opt_d = 0; /* debug */
@@ -30,7 +34,7 @@ int opt_s = DEFAULT_STRLEN; /* default maximum # of bytes printed in strings */
int opt_S = 0; /* display syscalls */
int opt_L = 1; /* display library calls */
int opt_f = 0; /* trace child processes as they are created */
-char *opt_u = NULL; /* username to run command as */
+char * opt_u = NULL; /* username to run command as */
int opt_r = 0; /* print relative timestamp */
int opt_t = 0; /* print absolute timestamp */
#ifdef USE_DEMANGLE
@@ -40,81 +44,91 @@ int opt_n = 0; /* indent trace output according to program flow */
int opt_T = 0; /* show the time spent inside each call */
/* List of pids given to option -p: */
-struct opt_p_t *opt_p = NULL; /* attach to process with a given pid */
+struct opt_p_t * opt_p = NULL; /* attach to process with a given pid */
/* List of function names given to option -e: */
-struct opt_e_t *opt_e = NULL;
-int opt_e_enable = 1;
+struct opt_e_t * opt_e = NULL;
+int opt_e_enable=1;
+
+/* List of global function names given to -x: */
+struct opt_e_t * opt_x = NULL;
+
+/* Set a break on the routine named here in order to re-initialize breakpoints
+ after all the PLTs have been initialzed */
+char * PLTs_initialized_by_here = PLTs_INIT_BY_HERE;
-static void usage(void)
-{
+static void
+usage(void) {
#if !(HAVE_GETOPT || HAVE_GETOPT_LONG)
fprintf(stdout, "Usage: %s [command [arg ...]]\n"
- "Trace library calls of a given program.\n\n", progname);
+"Trace library calls of a given program.\n\n", progname);
#else
fprintf(stdout, "Usage: %s [option ...] [command [arg ...]]\n"
- "Trace library calls of a given program.\n\n"
+"Trace library calls of a given program.\n\n"
+
# if HAVE_GETOPT_LONG
- " -a, --align=COLUMN align return values in a secific column.\n"
+" -a, --align=COLUMN align return values in a secific column.\n"
# else
- " -a COLUMN align return values in a secific column.\n"
+" -a COLUMN align return values in a secific column.\n"
# endif
- " -c count time and calls, and report a summary on exit.\n"
+" -c count time and calls, and report a summary on exit.\n"
# ifdef USE_DEMANGLE
# if HAVE_GETOPT_LONG
- " -C, --demangle decode low-level symbol names into user-level names.\n"
+" -C, --demangle decode low-level symbol names into user-level names.\n"
# else
- " -C decode low-level symbol names into user-level names.\n"
+" -C decode low-level symbol names into user-level names.\n"
# endif
# endif
# if HAVE_GETOPT_LONG
- " -d, --debug print debugging info.\n"
+" -d, --debug print debugging info.\n"
# else
- " -d print debugging info.\n"
+" -d print debugging info.\n"
# endif
- " -e expr modify which events to trace.\n"
- " -f follow forks.\n"
+" -e expr modify which events to trace.\n"
+" -f follow forks.\n"
# if HAVE_GETOPT_LONG
- " -h, --help display this help and exit.\n"
+" -h, --help display this help and exit.\n"
# else
- " -h display this help and exit.\n"
+" -h display this help and exit.\n"
# endif
- " -i print instruction pointer at time of library call.\n"
+" -i print instruction pointer at time of library call.\n"
# if HAVE_GETOPT_LONG
- " -l, --library=FILE print library calls from this library only.\n"
+" -l, --library=FILE print library calls from this library only.\n"
# else
- " -l FILE print library calls from this library only.\n"
+" -l FILE print library calls from this library only.\n"
# endif
- " -L do NOT display library calls.\n"
+" -L do NOT display library calls.\n"
# if HAVE_GETOPT_LONG
- " -n, --indent=NR indent output by NR spaces for each call level nesting.\n"
+" -n, --indent=NR indent output by NR spaces for each call level nesting.\n"
# else
- " -n NR indent output by NR spaces for each call level nesting.\n"
+" -n NR indent output by NR spaces for each call level nesting.\n"
# endif
# if HAVE_GETOPT_LONG
- " -o, --output=FILE write the trace output to that file.\n"
+" -o, --output=FILE write the trace output to that file.\n"
# else
- " -o FILE write the trace output to that file.\n"
+" -o FILE write the trace output to that file.\n"
# endif
- " -p PID attach to the process with the process ID pid.\n"
- " -r print relative timestamps.\n"
- " -s STRLEN specify the maximum string size to print.\n"
- " -S display system calls.\n"
- " -t, -tt, -ttt print absolute timestamps.\n"
- " -T show the time spent inside each call.\n"
- " -u USERNAME run command with the userid, groupid of username.\n"
+" -p PID attach to the process with the process ID pid.\n"
+" -r print relative timestamps.\n"
+" -s STRLEN specify the maximum string size to print.\n"
+" -S display system calls.\n"
+" -t, -tt, -ttt print absolute timestamps.\n"
+" -T show the time spent inside each call.\n"
+" -u USERNAME run command with the userid, groupid of username.\n"
# if HAVE_GETOPT_LONG
- " -V, --version output version information and exit.\n"
+" -V, --version output version information and exit.\n"
# else
- " -V output version information and exit.\n"
+" -V output version information and exit.\n"
# endif
- "\nReport bugs to Juan Cespedes <cespedes@debian.org>\n",
- progname);
+" -x NAME treat the global NAME like a library subroutine.\n"
+" -X NAME same as -x; and PLT's will be initialized by here.\n"
+"\nReport bugs to Juan Cespedes <cespedes@debian.org>\n"
+ , progname);
#endif
}
-static char *search_for_command(char *filename)
-{
+static char *
+search_for_command(char * filename) {
static char pathname[PATH_MAX];
char *path;
int m, n;
@@ -145,193 +159,189 @@ static char *search_for_command(char *filename)
return filename;
}
-char **process_options(int argc, char **argv)
-{
+char **
+process_options(int argc, char **argv) {
progname = argv[0];
output = stderr;
#if HAVE_GETOPT || HAVE_GETOPT_LONG
- while (1) {
+ while(1) {
int c;
#if HAVE_GETOPT_LONG
int option_index = 0;
static struct option long_options[] = {
- {"align", 1, 0, 'a'},
- {"debug", 0, 0, 'd'},
+ { "align", 1, 0, 'a'},
+ { "debug", 0, 0, 'd'},
# ifdef USE_DEMANGLE
- {"demangle", 0, 0, 'C'},
+ { "demangle", 0, 0, 'C'},
#endif
- {"indent", 1, 0, 'n'},
- {"help", 0, 0, 'h'},
- {"library", 1, 0, 'l'},
- {"output", 1, 0, 'o'},
- {"version", 0, 0, 'V'},
- {0, 0, 0, 0}
+ { "indent", 1, 0, 'n'},
+ { "help", 0, 0, 'h'},
+ { "library", 1, 0, 'l'},
+ { "output", 1, 0, 'o'},
+ { "version", 0, 0, 'V'},
+ { 0, 0, 0, 0}
};
c = getopt_long(argc, argv, "+cdfhiLrStTV"
# ifdef USE_DEMANGLE
- "C"
+ "C"
# endif
- "a:e:l:n:o:p:s:u:", long_options,
- &option_index);
+ "a:e:l:n:o:p:s:u:x:X:", long_options, &option_index);
#else
c = getopt(argc, argv, "+cdfhiLrStTV"
# ifdef USE_DEMANGLE
- "C"
+ "C"
# endif
- "a:e:l:n:o:p:s:u:");
+ "a:e:l:n:o:p:s:u:x:X:");
#endif
- if (c == -1) {
+ if (c==-1) {
break;
}
- switch (c) {
- case 'a':
- opt_a = atoi(optarg);
- break;
- case 'c':
- opt_c++;
- break;
+ switch(c) {
+ case 'a': opt_a = atoi(optarg);
+ break;
+ case 'c': opt_c++;
+ break;
#ifdef USE_DEMANGLE
- case 'C':
- opt_C++;
- break;
+ case 'C': opt_C++;
+ break;
#endif
- case 'd':
- opt_d++;
- break;
- case 'e':
- {
- char *str_e = strdup(optarg);
- if (!str_e) {
- perror("ltrace: strdup");
- exit(1);
- }
- if (str_e[0] == '!') {
- opt_e_enable = 0;
- str_e++;
- }
- while (*str_e) {
- struct opt_e_t *tmp;
- char *str2 = strchr(str_e, ',');
- if (str2) {
- *str2 = '\0';
+ case 'd': opt_d++;
+ break;
+ case 'e':
+ {
+ char * str_e = strdup(optarg);
+ if (!str_e) {
+ perror("ltrace: strdup");
+ exit(1);
+ }
+ if (str_e[0]=='!') {
+ opt_e_enable=0;
+ str_e++;
}
- tmp = malloc(sizeof(struct opt_e_t));
+ while(*str_e) {
+ struct opt_e_t * tmp;
+ char *str2 = strchr(str_e,',');
+ if (str2) {
+ *str2 = '\0';
+ }
+ tmp = malloc(sizeof(struct opt_e_t));
+ if (!tmp) {
+ perror("ltrace: malloc");
+ exit(1);
+ }
+ tmp->name = str_e;
+ tmp->next = opt_e;
+ opt_e = tmp;
+ if (str2) {
+ str_e = str2+1;
+ } else {
+ break;
+ }
+ }
+ break;
+ }
+ case 'f': opt_f = 1;
+ break;
+ case 'h': usage();
+ exit(0);
+ case 'i': opt_i++;
+ break;
+ case 'l': if (library_num == MAX_LIBRARY) {
+ fprintf(stderr, "Too many libraries. Maximum is %i.\n", MAX_LIBRARY);
+ exit(1);
+ }
+ library[library_num++] = optarg;
+ break;
+ case 'L': opt_L = 0;
+ break;
+ case 'n': opt_n = atoi(optarg);
+ break;
+ case 'o': output = fopen(optarg, "w");
+ if (!output) {
+ fprintf(stderr, "Can't open %s for output: %s\n", optarg, strerror(errno));
+ exit(1);
+ }
+ setvbuf(output, (char *)NULL, _IOLBF, 0);
+ fcntl(fileno(output), F_SETFD, FD_CLOEXEC);
+ break;
+ case 'p':
+ {
+ struct opt_p_t * tmp = malloc(sizeof(struct opt_p_t));
if (!tmp) {
perror("ltrace: malloc");
exit(1);
}
- tmp->name = str_e;
- tmp->next = opt_e;
- opt_e = tmp;
- if (str2) {
- str_e = str2 + 1;
- } else {
+ tmp->pid = atoi(optarg);
+ tmp->next = opt_p;
+ opt_p = tmp;
+ break;
+ }
+ case 'r': opt_r++;
break;
+ case 's': opt_s = atoi(optarg);
+ break;
+ case 'S': opt_S = 1;
+ break;
+ case 't': opt_t++;
+ break;
+ case 'T': opt_T++;
+ break;
+ case 'u': opt_u = optarg;
+ break;
+ case 'V': printf("ltrace version " PACKAGE_VERSION ".\n"
+"Copyright (C) 1997-2006 Juan Cespedes <cespedes@debian.org>.\n"
+"This is free software; see the GNU General Public Licence\n"
+"version 2 or later for copying conditions. There is NO warranty.\n");
+ exit(0);
+ case 'X': PLTs_initialized_by_here = optarg;
+ /* Fall Thru */
+
+ case 'x':
+ {
+ struct opt_e_t * p = opt_x;
+
+ /* First, check for duplicate. */
+ while (p && strcmp(p->name, optarg)) {
+ p = p->next;
}
+ if (p) { break; }
+
+ /* If not duplicate, add to list. */
+ p = malloc(sizeof(struct opt_e_t));
+ if (!p) {
+ perror("ltrace: malloc");
+ exit(1);
+ }
+ p->name = optarg;
+ p->next = opt_x;
+ opt_x = p;
+ break;
}
- break;
- }
- case 'f':
- opt_f = 1;
- break;
- case 'h':
- usage();
- exit(0);
- case 'i':
- opt_i++;
- break;
- case 'l':
- if (library_num == MAX_LIBRARY) {
- fprintf(stderr,
- "Too many libraries. Maximum is %i.\n",
- MAX_LIBRARY);
- exit(1);
- }
- library[library_num++] = optarg;
- break;
- case 'L':
- opt_L = 0;
- break;
- case 'n':
- opt_n = atoi(optarg);
- break;
- case 'o':
- output = fopen(optarg, "w");
- if (!output) {
- fprintf(stderr,
- "Can't open %s for output: %s\n",
- optarg, strerror(errno));
- exit(1);
- }
- setvbuf(output, (char *)NULL, _IOLBF, 0);
- fcntl(fileno(output), F_SETFD, FD_CLOEXEC);
- break;
- case 'p':
- {
- struct opt_p_t *tmp =
- malloc(sizeof(struct opt_p_t));
- if (!tmp) {
- perror("ltrace: malloc");
- exit(1);
- }
- tmp->pid = atoi(optarg);
- tmp->next = opt_p;
- opt_p = tmp;
- break;
- }
- case 'r':
- opt_r++;
- break;
- case 's':
- opt_s = atoi(optarg);
- break;
- case 'S':
- opt_S = 1;
- break;
- case 't':
- opt_t++;
- break;
- case 'T':
- opt_T++;
- break;
- case 'u':
- opt_u = optarg;
- break;
- case 'V':
- printf("ltrace version " PACKAGE_VERSION ".\n"
- "Copyright (C) 1997-2006 Juan Cespedes <cespedes@debian.org>.\n"
- "This is free software; see the GNU General Public Licence\n"
- "version 2 or later for copying conditions. There is NO warranty.\n");
- exit(0);
- default:
+
+ default:
#if HAVE_GETOPT_LONG
- fprintf(stderr,
- "Try `%s --help' for more information\n",
- progname);
+ fprintf(stderr, "Try `%s --help' for more information\n", progname);
#else
- fprintf(stderr, "Try `%s -h' for more information\n",
- progname);
+ fprintf(stderr, "Try `%s -h' for more information\n", progname);
#endif
- exit(1);
+ exit(1);
}
}
- argc -= optind;
- argv += optind;
+ argc -= optind; argv += optind;
#endif
- if (!opt_p && argc < 1) {
+ if (!opt_p && argc<1) {
fprintf(stderr, "%s: too few arguments\n", progname);
usage();
exit(1);
}
if (opt_r && opt_t) {
- fprintf(stderr, "%s: Incompatible options -r and -t\n",
- progname);
+ fprintf(stderr, "%s: Incompatible options -r and -t\n", progname);
exit(1);
}
- if (argc > 0) {
+ if (argc>0) {
command = search_for_command(argv[0]);
}
return &argv[0];