aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Machata <pmachata@redhat.com>2012-09-27 23:43:25 +0200
committerPetr Machata <pmachata@redhat.com>2012-10-01 14:18:53 +0200
commit51e74aca71ff7e8be91c074afd4f2264f46294e9 (patch)
tree9d55d829ceef7262f86e0e733eeb3a0fd4d4eaba
parent74e57dd396818b1a9414c44e397ac82f692f5582 (diff)
downloadltrace-51e74aca71ff7e8be91c074afd4f2264f46294e9.tar.gz
Add parsing of -l option
-rw-r--r--ChangeLog15
-rw-r--r--ltrace.118
-rw-r--r--options.c53
-rw-r--r--options.h5
-rw-r--r--testsuite/ltrace.main/main-threaded.exp2
-rw-r--r--testsuite/ltrace.main/main-vfork.exp2
-rw-r--r--testsuite/ltrace.main/main.exp2
-rw-r--r--testsuite/ltrace.main/parameters-lib.c5
-rw-r--r--testsuite/ltrace.main/parameters.c11
-rw-r--r--testsuite/ltrace.main/parameters.conf2
-rw-r--r--testsuite/ltrace.main/parameters.exp12
11 files changed, 86 insertions, 41 deletions
diff --git a/ChangeLog b/ChangeLog
index b33fd02..997d317 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,20 @@
2012-09-27 Petr Machata <pmachata@redhat.com>
+ * options.h (struct options_t.export_filter): New field.
+ * options.c (parse_filter): Take argument OPERATORS.
+ (recursive_parse_chain): Likewise.
+ (slist_chase_end): New function.
+ (process_options): Handle 'l' option, initialize export_filter.
+ * ltrace.1: Explain -l.
+ * testsuite/ltrace.main/main-vfork.exp: Update use of -l.
+ * testsuite/ltrace.main/main.exp: Likewise.
+ * testsuite/ltrace.main/parameters-lib.c (func_printf): New function.
+ * testsuite/ltrace.main/parameters.c: Call it instead of printf.
+ * testsuite/ltrace.main/parameters.conf: Declare it.
+ * testsuite/ltrace.main/parameters.exp: Update expectations and -l.
+
+2012-09-27 Petr Machata <pmachata@redhat.com>
+
* library.h (library_symbol_named_cb): New function.
* library.c (library_symbol_named_cb): Implemented here.
diff --git a/ltrace.1 b/ltrace.1
index fb64289..16cb03b 100644
--- a/ltrace.1
+++ b/ltrace.1
@@ -7,7 +7,7 @@ ltrace \- A library call tracer
.SH SYNOPSIS
.B ltrace
-.I "[-bCfghiLrStttV] [-a column] [-A maxelts] [-D level] [-e expr] [-l filename] [-n nr] [-o filename] [-p pid] ... [-s strsize] [-u username] [-w count] [-x extern] ... [--align=column] [--debug=level] [--demangle] [--help] [--indent=nr] [--library=filename] [--no-signals] [--output=filename] [--version] [--where=NR] [command [arg ...]]"
+.I "[-bCfghiLrStttV] [-a column] [-A maxelts] [-D level] [-e expr] [-l library_pattern] [-n nr] [-o filename] [-p pid] ... [-s strsize] [-u username] [-w count] [-x extern] ... [--align=column] [--debug=level] [--demangle] [--help] [--indent=nr] [--library=library_pattern] [--no-signals] [--output=filename] [--version] [--where=NR] [command [arg ...]]"
.SH DESCRIPTION
.B ltrace
@@ -95,16 +95,16 @@ Show a summary of the options to ltrace and exit.
.I \-i
Print the instruction pointer at the time of the library call.
.TP
-.I \-l, \-\-library filename
-Display only the symbols included in the library
-.I filename.
-Up to 30 library names can be specified with several instances
-of this option.
+.I \-l, \-\-library library_pattern
+Display only the symbols implemented by libraries that match
+.I library_pattern.
+Multiple library patters can be specified with several instances of
+this option. Syntax of library_pattern is described in section
+\fBFILTER EXPRESSIONS\fR.
.TP
.I \-L
-DON'T display library calls (use it with the
-.I \-S
-option).
+When no -e option is given, don't assume the default action of
+\fB@MAIN\fR.
.TP
.I \-n, \-\-indent nr
Indent trace output by
diff --git a/options.c b/options.c
index 8b73233..40bac34 100644
--- a/options.c
+++ b/options.c
@@ -74,7 +74,7 @@ usage(void) {
" -F, --config=FILE load alternate configuration file (may be repeated).\n"
" -h, --help display this help and exit.\n"
" -i print instruction pointer at time of library call.\n"
- " -l, --library=FILE print library calls from this library only.\n"
+ " -l, --library=FILE only trace symbols implemented by this library.\n"
" -L do NOT display library calls.\n"
" -n, --indent=NR indent output by NR spaces for each call level nesting.\n"
" -o, --output=FILE write the trace output to that file.\n"
@@ -257,7 +257,7 @@ grok_libname_pattern(char **libnamep, char **libendp)
}
static int
-parse_filter(struct filter *filt, char *expr)
+parse_filter(struct filter *filt, char *expr, int operators)
{
/* Filter is a chain of sym@lib rules separated by '-' or '+'.
* If the filter expression starts with '-', the missing
@@ -266,7 +266,7 @@ parse_filter(struct filter *filt, char *expr)
enum filter_rule_type type = FR_ADD;
while (*expr != 0) {
- size_t s = strcspn(expr, "@-+");
+ size_t s = strcspn(expr, "-+@" + (operators ? 0 : 2));
char *symname = expr;
char *libname;
char *next = expr + s + 1;
@@ -285,7 +285,7 @@ parse_filter(struct filter *filt, char *expr)
} else {
assert(expr[s] == '@');
expr[s] = 0;
- s = strcspn(next, "-+");
+ s = strcspn(next, "-+" + (operators ? 0 : 2));
if (s == 0) {
libname = "*";
expr = next;
@@ -357,7 +357,7 @@ parse_filter(struct filter *filt, char *expr)
}
static struct filter *
-recursive_parse_chain(char *expr)
+recursive_parse_chain(char *expr, int operators)
{
struct filter *filt = malloc(sizeof(*filt));
if (filt == NULL) {
@@ -367,7 +367,7 @@ recursive_parse_chain(char *expr)
}
filter_init(filt);
- if (parse_filter(filt, expr) < 0) {
+ if (parse_filter(filt, expr, operators) < 0) {
fprintf(stderr, "Filter '%s' will be ignored.\n", expr);
free(filt);
filt = NULL;
@@ -376,6 +376,14 @@ recursive_parse_chain(char *expr)
return filt;
}
+static struct filter **
+slist_chase_end(struct filter **begin)
+{
+ for (; *begin != NULL; begin = &(*begin)->next)
+ ;
+ return begin;
+}
+
static void
parse_filter_chain(const char *expr, struct filter **retp)
{
@@ -389,10 +397,7 @@ parse_filter_chain(const char *expr, struct filter **retp)
if (str[0] == '!')
str[0] = '-';
- struct filter **tailp;
- for (tailp = retp; *tailp != NULL; tailp = &(*tailp)->next)
- ;
- *tailp = recursive_parse_chain(str);
+ *slist_chase_end(retp) = recursive_parse_chain(str, 1);
}
char **
@@ -499,10 +504,16 @@ process_options(int argc, char **argv)
case 'i':
opt_i++;
break;
- case 'l':
- // XXX TODO
- fprintf(stderr, "-l support not yet implemented\n");
+
+ case 'l': {
+ size_t patlen = strlen(optarg);
+ char buf[patlen + 2];
+ sprintf(buf, "@%s", optarg);
+ *slist_chase_end(&options.export_filter)
+ = recursive_parse_chain(buf, 0);
break;
+ }
+
case 'L':
libcalls = 0;
break;
@@ -607,13 +618,21 @@ process_options(int argc, char **argv)
opt_F = egg;
}
- /* Set default filter. Use @MAIN for now, as that's what
- * ltrace used to have in the past. XXX Maybe we should make
- * this "*" instead. */
- if (options.plt_filter == NULL && libcalls) {
+ /* If neither -e, nor -l, nor -L are used, set default -e.
+ * Use @MAIN for now, as that's what ltrace used to have in
+ * the past. XXX Maybe we should make this "*" instead. */
+ if (libcalls
+ && options.plt_filter == NULL
+ && options.export_filter == NULL) {
parse_filter_chain("@MAIN", &options.plt_filter);
options.hide_caller = 1;
}
+ if (!libcalls && options.plt_filter != NULL) {
+ fprintf(stderr,
+ "%s: Option -L can't be used with -e or -l.\n",
+ progname);
+ err_usage();
+ }
if (!opt_p && argc < 1) {
fprintf(stderr, "%s: too few arguments\n", progname);
diff --git a/options.h b/options.h
index 0806928..176ce90 100644
--- a/options.h
+++ b/options.h
@@ -21,6 +21,11 @@ struct options_t {
#endif /* defined(HAVE_LIBUNWIND) */
struct filter *plt_filter;
struct filter *static_filter;
+
+ /* A filter matching library names of libraries, whose
+ * exported symbols we wish to trace. */
+ struct filter *export_filter;
+
int hide_caller; /* Whether caller library should be hidden. */
};
extern struct options_t options;
diff --git a/testsuite/ltrace.main/main-threaded.exp b/testsuite/ltrace.main/main-threaded.exp
index 5539805..4f6c25d 100644
--- a/testsuite/ltrace.main/main-threaded.exp
+++ b/testsuite/ltrace.main/main-threaded.exp
@@ -19,7 +19,7 @@ if { [ltrace_compile_shlib $libsrc $lib_sl debug ] != ""
}
# set options for ltrace.
-ltrace_options "-l" "$lib_sl" "-f"
+ltrace_options "-l" "lib$testfile.so" "-f"
# Run PUT for ltarce.
set exec_output [ltrace_runtest $objdir/$subdir $objdir/$subdir/$binfile]
diff --git a/testsuite/ltrace.main/main-vfork.exp b/testsuite/ltrace.main/main-vfork.exp
index 299c5e0..989012d 100644
--- a/testsuite/ltrace.main/main-vfork.exp
+++ b/testsuite/ltrace.main/main-vfork.exp
@@ -19,7 +19,7 @@ if { [ltrace_compile_shlib $libsrc $lib_sl debug ] != ""
}
# set options for ltrace.
-ltrace_options "-l" "$lib_sl" "-f"
+ltrace_options "-l" "lib$testfile.so" "-f" "-evfork"
# Run PUT for ltarce.
set exec_output [ltrace_runtest $objdir/$subdir $objdir/$subdir/$binfile]
diff --git a/testsuite/ltrace.main/main.exp b/testsuite/ltrace.main/main.exp
index 9e126bc..50c5353 100644
--- a/testsuite/ltrace.main/main.exp
+++ b/testsuite/ltrace.main/main.exp
@@ -19,7 +19,7 @@ if { [ltrace_compile_shlib $libsrc $lib_sl debug ] != ""
}
# set options for ltrace.
-ltrace_options "-l" "$objdir/$subdir/libmain.so"
+ltrace_options "-l" "libmain.so"
# Run PUT for ltarce.
set exec_output [ltrace_runtest $objdir/$subdir $objdir/$subdir/$binfile]
diff --git a/testsuite/ltrace.main/parameters-lib.c b/testsuite/ltrace.main/parameters-lib.c
index 750075e..04effaf 100644
--- a/testsuite/ltrace.main/parameters-lib.c
+++ b/testsuite/ltrace.main/parameters-lib.c
@@ -456,3 +456,8 @@ func_hfa_d12(struct struct_hfa_d12 e)
{
return e;
}
+
+void
+func_printf(char *format, ...)
+{
+}
diff --git a/testsuite/ltrace.main/parameters.c b/testsuite/ltrace.main/parameters.c
index 44d54b2..ae8e17b 100644
--- a/testsuite/ltrace.main/parameters.c
+++ b/testsuite/ltrace.main/parameters.c
@@ -182,10 +182,11 @@ main ()
15, 16, 'B', 18.0, 19.0, 20.0,
21, 22.0, 23.0, 24.0, 25.0);
- printf("sotnuh %d %ld %g %c\n", 5, 6L, 1.5, 'X');
- printf("sotnuh1 %d %ld %hd\n", 5, 6L, (short)7);
- printf("sotnuh2 %s %10s %10s\n", "a string", "a trimmed string", "short");
- printf("many_args"
+ void func_printf(char *format, ...);
+ func_printf("sotnuh %d %ld %g %c\n", 5, 6L, 1.5, 'X');
+ func_printf("sotnuh1 %d %ld %hd\n", 5, 6L, (short)7);
+ func_printf("sotnuh2 %s %10s %10s\n", "a string", "a trimmed string", "short");
+ func_printf("many_args"
"%d %d %ld %g %c %d %g "
"%c %d %g %d %g %c %d "
"%hd %d %c %g %g %g "
@@ -195,7 +196,7 @@ main ()
(short)15, 16, 'B', 18.0, 19.0, 20.0,
21L, 22.0, 23.0, 24.0, 25.0);
- printf("sotnuh3 %*s\n", 4, "a trimmed string");
+ func_printf("sotnuh3 %*s\n", 4, "a trimmed string");
void func_lens(int, long, short, long);
func_lens(22, 23, 24, 25);
diff --git a/testsuite/ltrace.main/parameters.conf b/testsuite/ltrace.main/parameters.conf
index 0531a6a..743237f 100644
--- a/testsuite/ltrace.main/parameters.conf
+++ b/testsuite/ltrace.main/parameters.conf
@@ -22,7 +22,7 @@ struct(long,long,long,long) func_struct_large(struct(long,long,long,long), struc
struct(char,char,long,long) func_struct_large2(struct(char,char,long,long), struct(char,char,long,long));
struct(long,long,char,char) func_struct_large3(struct(long,long,char,char), struct(long,long,char,char));
void func_many_args(int, int, long, double, char, int, float, char, int, double, int, double, char, int, short, int, char, float, float, double, long, float, float, float, float);
-int printf(format);
+void func_printf(format);
void func_lens(octal, octal(long), hex(short), hex(long));
bool(int) func_bool(int, bool(int));
void func_hide(int, hide(int), hide(int), int, hide(int), int);
diff --git a/testsuite/ltrace.main/parameters.exp b/testsuite/ltrace.main/parameters.exp
index badbe6b..367214f 100644
--- a/testsuite/ltrace.main/parameters.exp
+++ b/testsuite/ltrace.main/parameters.exp
@@ -20,7 +20,7 @@ if { [ltrace_compile_shlib $libsrc $lib_sl debug ] != ""
}
# set options for ltrace.
-ltrace_options "-l" "$objdir/$subdir/libparameters.so" "-F" "$srcdir/$subdir/parameters.conf"
+ltrace_options "-l" "libparameters.so" "-F" "$srcdir/$subdir/parameters.conf"
# Run PUT for ltarce.
set exec_output [ltrace_runtest $objdir/$subdir $objdir/$subdir/$binfile]
@@ -100,19 +100,19 @@ ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1
set pattern "func_many_args(1, 2, 3, 4.00*, '5', 6, 7.00*, '8', 9, 10.00*, 11, 12.00*, 'A', 14, 15, 16, 'B', 18.00*, 19.00*, 20.00*, 21, 22.00*, 23.00*, 24.00*, 25.00*)"
ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1
-set pattern "printf(\\\"sotnuh %d %ld %g %c.n\\\", 5, 6, 1.500*, 'X')"
+set pattern "func_printf(\\\"sotnuh %d %ld %g %c.n\\\", 5, 6, 1.500*, 'X')"
ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1
-set pattern "printf(\\\"sotnuh1 %d %ld %hd.n\\\", 5, 6, 7)"
+set pattern "func_printf(\\\"sotnuh1 %d %ld %hd.n\\\", 5, 6, 7)"
ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1
-set pattern "printf(\\\"sotnuh2 %s %10s %10s.n\\\", \\\"a string\\\", \\\"a trimmed \\\", \\\"short\\\")"
+set pattern "func_printf(\\\"sotnuh2 %s %10s %10s.n\\\", \\\"a string\\\", \\\"a trimmed \\\", \\\"short\\\")"
ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1
-set pattern "printf(\\\"sotnuh3 %.s.n\\\", 4, \\\"a tr\\\")"
+set pattern "func_printf(\\\"sotnuh3 %.s.n\\\", 4, \\\"a tr\\\")"
ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1
-set pattern "printf(\\\"many_args%d %d %ld %g %c %d %g .*, 1, 2, 3, 4.00*, '5', 6, 7.00*, '8', 9, 10.00*, 11, 12.00*, 'A', 14, 15, 16, 'B', 18.00*, 19.00*, 20.00*, 21, 22.00*, 23.00*, 24.00*, 25.00*)"
+set pattern "func_printf(\\\"many_args%d %d %ld %g %c %d %g .*, 1, 2, 3, 4.00*, '5', 6, 7.00*, '8', 9, 10.00*, 11, 12.00*, 'A', 14, 15, 16, 'B', 18.00*, 19.00*, 20.00*, 21, 22.00*, 23.00*, 24.00*, 25.00*)"
ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1
set pattern "func_lens(026, 027, 0x18, 0x19)"