412 lines
13 KiB
Groff
412 lines
13 KiB
Groff
.\" -*-nroff-*-
|
|
.\" Copyright (c) 2012, 2013 Petr Machata, Red Hat Inc.
|
|
.\" Copyright (c) 1997-2005 Juan Cespedes <cespedes@debian.org>
|
|
.\"
|
|
.\" This program is free software; you can redistribute it and/or
|
|
.\" modify it under the terms of the GNU General Public License as
|
|
.\" published by the Free Software Foundation; either version 2 of the
|
|
.\" License, or (at your option) any later version.
|
|
.\"
|
|
.\" This program is distributed in the hope that it will be useful, but
|
|
.\" WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
.\" General Public License for more details.
|
|
.\"
|
|
.\" You should have received a copy of the GNU General Public License
|
|
.\" along with this program; if not, write to the Free Software
|
|
.\" Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
|
.\" 02110-1301 USA
|
|
.\"
|
|
.TH ltrace.conf "5" "October 2012" "" "ltrace configuration file"
|
|
.SH "NAME"
|
|
.LP
|
|
\fBltrace.conf\fR \- Configuration file for \fBltrace(1)\fR.
|
|
|
|
.SH DESCRIPTION
|
|
|
|
This manual page describes \fBltrace.conf\fR, a file that describes
|
|
prototypes of functions in binaries for \fBltrace(1)\fR to use.
|
|
Ltrace needs this information to display function call arguments.
|
|
|
|
Each line of a configuration file describes at most a single item.
|
|
Lines composed entirely of white space are ignored, as are lines
|
|
starting with semicolon or hash characters (comment lines). Described
|
|
items can be either function prototypes, or definitions of type
|
|
aliases.
|
|
|
|
.SH PROTOTYPES
|
|
|
|
A prototype describes return type and parameter types of a single
|
|
function. The syntax is as follows:
|
|
|
|
.RS
|
|
\fILENS\fR \fINAME\fR \fB(\fR[\fILENS\fR{,\fILENS\fR}]\fB);\fR
|
|
.RE
|
|
|
|
\fINAME\fR is the (mangled) name of a symbol. In the elementary case,
|
|
\fILENS\fR is simply a type. Both lenses and types are described
|
|
below. For example, a simple function prototype might look like this:
|
|
|
|
.RS
|
|
.B int\fR kill\fB(int,int);
|
|
.RE
|
|
|
|
Despite the apparent similarity with C, \fBltrace.conf\fR is really
|
|
its own language that's only somewhat inspired by C.
|
|
|
|
.SH TYPES
|
|
|
|
Ltrace understands a range of primitive types. Those are interpreted
|
|
according to C convention native on a given architecture.
|
|
E.g. \fBulong\fR is interpreted as 4-byte unsigned integer on 32-bit
|
|
GNU/Linux machine, but 8-byte unsigned integer on 64-bit GNU/Linux
|
|
machine.
|
|
|
|
.TP
|
|
.B void
|
|
Denotes that a function does not return anything. Can be also used to
|
|
construct a generic pointer, i.e. pointer-sized number formatted in
|
|
hexadecimal format.
|
|
.TP
|
|
.B char
|
|
8-bit quantity rendered as a character
|
|
.TP
|
|
.B ushort,short
|
|
Denotes unsigned or signed short integer.
|
|
.TP
|
|
.B uint,int
|
|
Denotes unsigned or signed integer.
|
|
.TP
|
|
.B ulong,long
|
|
Denotes unsigned or signed long integer.
|
|
.TP
|
|
.B float
|
|
Denotes floating point number with single precision.
|
|
.TP
|
|
.B double
|
|
Denotes floating point number with double precision.
|
|
.PP
|
|
|
|
Besides primitive types, the following composed types are possible:
|
|
|
|
.TP
|
|
.B struct(\fR[\fILENS\fR{,\fILENS\fR}]\fB)\fR
|
|
Describes a structure with given types as fields,
|
|
e.g. \fBstruct(int,int,float)\fR.
|
|
|
|
Alignment is computed as customary on the architecture. Custom
|
|
alignment (e.g. packed structs) and bit-fields are not supported.
|
|
It's also not possible to differentiate between structs and non-POD
|
|
C++ classes, for arches where it makes a difference.
|
|
|
|
.TP
|
|
.B array(\fR\fILENS\fR\fB,\fIEXPR\fR\fB)
|
|
Describes array of length \fIEXPR\fR, which is composed of types
|
|
described by \fILENS\fR, e.g. \fBarray(int, \fR6\fB)\fR.
|
|
|
|
Note that in C, arrays in role of function argument decay into
|
|
pointers. Ltrace currently handles this automatically, but for full
|
|
formal correctness, any such arguments should be described as pointers
|
|
to arrays.
|
|
|
|
.TP
|
|
.I LENS\fR\fB*
|
|
Describes a pointer to a given type, e.g. \fBchar*\fR or \fBint***\fR.
|
|
Note that the former example actually describes a pointer to a
|
|
character, not a string. See below for \fBstring\fR lens, which is
|
|
applicable to these cases.
|
|
|
|
.SH LENSES
|
|
|
|
Lenses change the way that types are described. In the simplest case,
|
|
a lens is directly a type. Otherwise a type is decorated by the lens.
|
|
Ltrace understands the following lenses:
|
|
|
|
.TP
|
|
.B oct(\fITYPE\fB)
|
|
The argument, which should be an integer type, is formatted in base-8.
|
|
|
|
.TP
|
|
.B hex(\fITYPE\fB)
|
|
The argument, which should be an integer or floating point type, is
|
|
formatted in base-16. Floating point arguments are converted to
|
|
double and then displayed using the \fB%a\fR fprintf modifier.
|
|
|
|
.TP
|
|
.B hide(\fITYPE\fB)
|
|
The argument is not shown in argument list.
|
|
|
|
.TP
|
|
.B bool(\fITYPE\fB)
|
|
Arguments with zero value are shown as "false", others are shown as
|
|
"true".
|
|
|
|
.TP
|
|
.B bitvec(\fITYPE\fB)
|
|
Underlying argument is interpreted as a bit vector and a summary of
|
|
bits set in the vector is displayed. For example if bits 3,4,5 and 7
|
|
of the bit vector are set, ltrace shows <3-5,7>. Empty bit vector is
|
|
displayed as <>. If there are more bits set than unset, inverse is
|
|
shown instead: e.g. ~<0> when a number 0xfffffffe is displayed. Full
|
|
set is thus displayed ~<>.
|
|
|
|
If the underlying type is integral, then bits are shown in their
|
|
natural big-endian order, with LSB being bit 0.
|
|
E.g. \fBbitvec(ushort)\fR with value 0x0102 would be displayed as
|
|
<1,8>, irrespective of underlying byte order.
|
|
|
|
For other data types (notably structures and arrays), the underlying
|
|
data is interpreted byte after byte. Bit 0 of first byte has number
|
|
0, bit 0 of second byte number 8, and so on. Thus
|
|
\fBbitvec(struct(int))\fR is endian sensitive, and will show bytes
|
|
comprising the integer in their memory order. Pointers are first
|
|
dereferenced, thus \fBbitvec(array(char, \fR32\fB)*)\fR is actually a
|
|
pointer to 256-bit bit vector.
|
|
|
|
.PP
|
|
.B string(\fITYPE\fB)
|
|
.br
|
|
.B string[\fIEXPR\fB]
|
|
.br
|
|
.B string
|
|
.RS
|
|
The first form of the argument is canonical, the latter two are
|
|
syntactic sugar. In the canonical form, the function argument is
|
|
formatted as string. The \fITYPE\fR can have either of the following
|
|
forms: \fIX\fB*\fR, or \fBarray(\fIX\fB,\fIEXPR\fB)\fR, or
|
|
\fBarray(\fIX\fB,\fIEXPR\fB)*\fR. \fIX\fR is either \fBchar\fR for
|
|
normal strings, or an integer type for wide-character strings.
|
|
|
|
If an array is given, the length will typically be a \fBzero\fR
|
|
expression (but doesn't have to be). Using argument that is plain
|
|
array (i.e. not a pointer to array) makes sense e.g. in C structs, in
|
|
cases like \fBstruct(string(array(char, \fR6\fB)))\fR, which describes
|
|
the C type \fBstruct {char \fRs\fB[\fR6\fB];}\fR.
|
|
|
|
Because simple C-like strings are pretty common, there are two
|
|
shorthand forms. The first shorthand form (with brackets) means the
|
|
same as \fBstring(array(char, \fIEXPR\fB)*)\fR. Plain \fBstring\fR
|
|
without an argument is then taken to mean the same as
|
|
\fBstring[zero]\fR.
|
|
|
|
Note that \fBchar*\fR by itself describes a pointer to a char. Ltrace
|
|
will dereference the pointer, and read and display the single
|
|
character that it points to.
|
|
.RE
|
|
|
|
.B enum(\fINAME\fR[\fB=\fIVALUE\fR]{,\fINAME\fR[\fB=\fIVALUE\fR]}\fB)
|
|
.br
|
|
.B enum[\fITYPE\fB]\fB(\fINAME\fR[\fB=\fIVALUE\fR]{,\fINAME\fR[\fB=\fIVALUE\fR]}\fB)
|
|
.RS
|
|
This describes an enumeration lens. If an argument has any of the
|
|
given values, it is instead shown as the corresponding \fINAME\fR. If
|
|
a \fIVALUE\fR is omitted, the next consecutive value following after
|
|
the previous \fIVALUE\fR is taken instead. If the first \fIVALUE\fR
|
|
is omitted, it's \fB0\fR by default.
|
|
|
|
\fITYPE\fR, if given, is the underlying type. It is thus possible to
|
|
create enums over shorts or longs\(emarguments that are themselves
|
|
plain, non-enum types in C, but whose values can be meaningfully
|
|
described as enumerations. If omitted, \fITYPE\fR is taken to be
|
|
\fBint\fR.
|
|
.RE
|
|
|
|
.SH TYPE ALIASES
|
|
|
|
A line in config file can, instead of describing a prototype, create a
|
|
type alias. Instead of writing the same enum or struct on many places
|
|
(and possibly updating when it changes), one can introduce a name for
|
|
such type, and later just use that name:
|
|
|
|
.RS
|
|
\fBtypedef \fINAME\fB = \fILENS\fB;\fR
|
|
.RE
|
|
|
|
.SH RECURSIVE STRUCTURES
|
|
|
|
Ltrace allows you to express recursive structures. Such structures
|
|
are expanded to the depth described by the parameter \-A. To declare a
|
|
recursive type, you first have to introduce the type to ltrace by
|
|
using forward declaration. Then you can use the type in other type
|
|
definitions in the usual way:
|
|
|
|
.RS
|
|
.B typedef \fINAME\fB = struct;
|
|
.br
|
|
.B typedef \fINAME\fB = struct(\fINAME\fR can be used here\fB)
|
|
.RE
|
|
|
|
For example, consider the following singy-linked structure and a
|
|
function that takes such list as an argument:
|
|
|
|
.RS
|
|
.B typedef\fR int_list \fB= struct;
|
|
.br
|
|
.B typedef\fR int_list \fB= struct(int,\fR int_list\fB*);
|
|
.br
|
|
.B void\fR ll\fB(\fRint_list\fB*);
|
|
.RE
|
|
|
|
Such declarations might lead to an output like the following:
|
|
|
|
.RS
|
|
ll({ 9, { 8, { 7, { 6, ... } } } }) = <void>
|
|
.RE
|
|
|
|
Ltrace detects recursion and will not expand already-expanded
|
|
structures. Thus a doubly-linked list would look like the following:
|
|
|
|
.RS
|
|
.B typedef\fR int_list \fB= struct;
|
|
.br
|
|
.B typedef\fR int_list \fB= struct(int,\fR int_list\fB*,\fR int_list\fB*);
|
|
.RE
|
|
|
|
With output e.g. like:
|
|
|
|
.RS
|
|
ll({ 9, { 8, { 7, { 6, ..., ... }, recurse^ }, recurse^ }, nil })
|
|
.RE
|
|
|
|
The "recurse^" tokens mean that given pointer points to a structure
|
|
that was expanded in the previous layer. Simple "recurse" would mean
|
|
that it points back to this object. E.g. "recurse^^^" means it points
|
|
to a structure three layers up. For doubly-linked list, the pointer
|
|
to the previous element is of course the one that has been just
|
|
expanded in the previous round, and therefore all of them are either
|
|
recurse^, or nil. If the next and previous pointers are swapped, the
|
|
output adjusts correspondingly:
|
|
|
|
.RS
|
|
ll({ 9, nil, { 8, recurse^, { 7, recurse^, { 6, ..., ... } } } })
|
|
.RE
|
|
|
|
|
|
.SH EXPRESSIONS
|
|
|
|
Ltrace has support for some elementary expressions. Each expression
|
|
can be either of the following:
|
|
|
|
.TP
|
|
.I NUM
|
|
An integer number.
|
|
|
|
.TP
|
|
.B arg\fINUM
|
|
Value of \fINUM\fR-th argument. The expression has the same value as
|
|
the corresponding argument. \fBarg1\fR refers to the first argument,
|
|
\fBarg0\fR to the return value of the given function.
|
|
|
|
.TP
|
|
.B retval
|
|
Return value of function, same as \fBarg0\fR.
|
|
|
|
.TP
|
|
.B elt\fINUM
|
|
Value of \fINUM\fR-th element of the surrounding structure type. E.g.
|
|
\fBstruct(ulong,array(int,elt1))\fR describes a structure whose first
|
|
element is a length, and second element an array of ints of that
|
|
length.
|
|
|
|
.PP
|
|
.B zero
|
|
.br
|
|
.B zero(\fIEXPR\fB)
|
|
.RS
|
|
Describes array which extends until the first element, whose each byte
|
|
is 0. If an expression is given, that is the maximum length of the
|
|
array. If NUL terminator is not found earlier, that's where the array
|
|
ends.
|
|
.RE
|
|
|
|
.SH PARAMETER PACKS
|
|
|
|
Sometimes the actual function prototype varies slightly depending on
|
|
the exact parameters given. For example, the number and types of
|
|
printf parameters are not known in advance, but ltrace might be able
|
|
to determine them in runtime. This feature has wider applicability,
|
|
but currently the only parameter pack that ltrace supports is
|
|
printf-style format string itself:
|
|
|
|
.TP
|
|
.B format
|
|
When \fBformat\fR is seen in the parameter list, the underlying string
|
|
argument is parsed, and GNU-style format specifiers are used to
|
|
determine what the following actual arguments are. E.g. if the format
|
|
string is "%s %d\\n", it's as if the \fBformat\fR was replaced by
|
|
\fBstring, string, int\fR.
|
|
|
|
.SH RETURN ARGUMENTS
|
|
|
|
C functions often use one or more arguments for returning values back
|
|
to the caller. The caller provides a pointer to storage, which the
|
|
called function initializes. Ltrace has some support for this idiom.
|
|
|
|
When a traced binary hits a function call, ltrace first fetches all
|
|
arguments. It then displays \fIleft\fR portion of the argument list.
|
|
Only when the function returns does ltrace display \fIright\fR portion
|
|
as well. Typically, left portion takes up all the arguments, and
|
|
right portion only contains return value. But ltrace allows you to
|
|
configure where exactly to put the dividing line by means of a \fB+\fR
|
|
operator placed in front of an argument:
|
|
|
|
.RS
|
|
.B int\fR asprintf\fB(+string*, format);
|
|
.RE
|
|
|
|
Here, the first argument to asprintf is denoted as return argument,
|
|
which means that displaying the whole argument list is delayed until
|
|
the function returns:
|
|
|
|
.RS
|
|
a.out->asprintf( <unfinished ...>
|
|
.br
|
|
libc.so.6->malloc(100) = 0x245b010
|
|
.br
|
|
[... more calls here ...]
|
|
.br
|
|
<... asprintf resumed> "X=1", "X=%d", 1) = 5
|
|
.RE
|
|
|
|
It is currently not possible to have an "inout" argument that passes
|
|
information in both directions.
|
|
|
|
.SH EXAMPLES
|
|
|
|
In the following, the first is the C prototype, and following that is
|
|
ltrace configuration line.
|
|
|
|
.TP
|
|
.B void\fR func_charp_string\fB(char\fR str\fB[]);
|
|
.B void\fR func_charp_string\fB(string);
|
|
|
|
.PP
|
|
.B enum\fR e_foo \fB{\fRRED\fB, \fRGREEN\fB, \fRBLUE\fB};
|
|
.br
|
|
.B void\fR func_enum\fB(enum\fR e_foo bar\fB);\fR
|
|
.RS
|
|
.B void\fR func_enum\fB(enum(\fRRED\fB,\fRGREEN\fB,\fRBLUE\fB));\fR
|
|
.RS
|
|
- or -
|
|
.RE
|
|
.B typedef\fR e_foo \fB= enum(\fRRED\fB,\fRGREEN\fB,\fRBLUE\fB);\fR
|
|
.br
|
|
.B void\fR func_enum\fB(\fRe_foo\fB);\fR
|
|
.RE
|
|
|
|
.TP
|
|
.B void\fR func_arrayi\fB(int\fR arr\fB[],\fR int len\fB);
|
|
.B void\fR func_arrayi\fB(array(int,arg2)*,int);
|
|
|
|
.PP
|
|
.B struct\fR S1 \fB{float\fR f\fB; char\fR a\fB; char \fRb\fB;};
|
|
.br
|
|
.B struct\fR S2 \fB{char\fR str\fB[\fR6\fB]; float\fR f\fB;};
|
|
.br
|
|
.B struct\fR S1 func_struct\fB(int \fRa\fB, struct \fRS2\fB, double \fRd\fB);
|
|
.RS
|
|
.B struct(float,char,char)\fR func_struct\fB(int, struct(string(array(char, \fR6\fB)),float), double);
|
|
.RE
|
|
|
|
.SH AUTHOR
|
|
Petr Machata <pmachata@redhat.com>
|