| .\" -*-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> |