Imported Upstream version 0.7.2
[platform/upstream/ltrace.git] / TODO
1 -*-org-*-
2 * TODO
3 ** Automatic prototype discovery:
4 *** Use debuginfo if available
5     Alternatively, use debuginfo to generate configure file.
6 *** Demangled identifiers contain partial prototypes themselves
7 ** Automatically update list of syscalls?
8 ** Update /etc/ltrace.conf
9    In particular, we could use a config directory, where packages
10    would install their ltrace config scripts.  The config file could
11    be named after SONAME, and automatically read when corresponding
12    library is mapped.
13 ** More operating systems (solaris?)
14 ** Get rid of EVENT_ARCH_SYSCALL and EVENT_ARCH_SYSRET
15 ** Implement displaced tracing
16    A technique used in GDB (and in uprobes, I believe), whereby the
17    instruction under breakpoint is moved somewhere else, and followed
18    by a jump back to original place.  When the breakpoint hits, the IP
19    is moved to the displaced instruction, and the process is
20    continued.  We avoid all the fuss with singlestepping and
21    reenablement.
22 ** Create different ltrace processes to trace different children
23 ** Config file syntax
24 *** named arguments
25     This would be useful for replacing the arg1, emt2 etc.
26
27 *** parameter pack improvements
28     The above format tweaks require that packs that expand to no types
29     at all be supported.  If this works, then it should be relatively
30     painless to implement conditionals:
31
32     | void ptrace(REQ=enum(PTRACE_TRACEME=0,...),
33     |             if[REQ==0](pack(),pack(pid_t, void*, void *)))
34
35     This is of course dangerously close to a programming language, and
36     I think ltrace should be careful to stay as simple as possible.
37     (We can hook into Lua, or TinyScheme, or some such if we want more
38     general scripting capabilities.  Implementing something ad-hoc is
39     undesirable.)  But the above can be nicely expressed by pattern
40     matching:
41
42     | void ptrace(REQ=enum[int](...)):
43     |   [REQ==0] => ()
44     |   [REQ==1 or REQ==2] => (pid_t, void*)
45     |   [true] => (pid_t, void*, void*);
46
47     Or:
48
49     | int open(string, FLAGS=flags[int](O_RDONLY=00,...,O_CREAT=0100,...)):
50     |   [(FLAGS & 0100) != 0] => (flags[int](S_IRWXU,...))
51
52     This would still require pretty complete expression evaluation.
53     _Including_ pointer dereferences and such.  And e.g. in accept, we
54     need subtraction:
55
56     | int accept(int, +struct(short, +array(hex(char), X-2))*, (X=uint)*);
57
58     Perhaps we should hook to something after all.
59
60 *** errno tracking
61     Some calls result in setting errno.  Somehow mark those, and on
62     failure, show errno.
63
64 *** second conversions?
65     This definitely calls for some general scripting.  The goal is to
66     have seconds in adjtimex calls show as e.g. 10s, 1m15s or some
67     such.
68
69 *** format should take arguments like string does
70     Format should take value argument describing the value that should
71     be analyzed.  The following overwriting rules would then apply:
72
73     | format       | format(array(char, zero)*) |
74     | format(LENS) | X=LENS, format[X]          |
75
76     The latter expanded form would be canonical.
77
78     This depends on named arguments and parameter pack improvements
79     (we need to be able to construct parameter packs that expand to
80     nothing).
81
82 *** More fine-tuned control of right arguments
83     Combination of named arguments and some extensions could take care
84     of that:
85
86     | void func(X=hide(int*), long*, +pack(X)); |
87
88     This would show long* as input argument (i.e. the function could
89     mangle it), and later show the pre-fetched X.  The "pack" syntax is
90     utterly undeveloped as of now.  The general idea is to produce
91     arguments that expand to some mix of types and values.  But maybe
92     all we need is something like
93
94     | void func(out int*, long*); |
95
96     ltrace would know that out/inout/in arguments are given in the
97     right order, but left pass should display in and inout arguments
98     only, and right pass then out and inout.  + would be
99     backward-compatible syntactic sugar, expanded like so:
100
101     | void func(int*, int*, +long*, long*);              |
102     | void func(in int*, in int*, out long*, out long*); |
103
104     But sometimes we may want to see a different type on the way in and
105     on the way out.  E.g. in asprintf, what's interesting on the way in
106     is the address, but on the way out we want to see buffer contents.
107     Does something like the following make sense?
108
109     | void func(X=void*, long*, out string(X)); |
110
111 ** Support for functions that never return
112    This would be useful for __cxa_throw, presumably also for longjmp
113    (do we handle that at all?) and perhaps a handful of others.
114
115 ** Support flag fields
116    enum-like syntax, except disjunction of several values is assumed.
117 ** Support long long
118    We currently can't define time_t on 32bit machines.  That mean we
119    can't describe a range of time-related functions.
120
121 ** Support signed char, unsigned char, char
122    Also, don't format it as characted by default, string lens can do
123    it.  Perhaps introduce byte and ubyte and leave 'char' as alias of
124    one of those with string lens applied by default.
125
126 ** Support fixed-width types
127    Really we should keep everything as {u,}int{8,16,32,64} internally,
128    and have long, short and others be translated to one of those
129    according to architecture rules.  Maybe this could be achieved by a
130    per-arch config file with typedefs such as:
131
132    | typedef ulong = uint8_t |
133
134 ** Some more functions in vect might be made to take const*
135    Or even marked __attribute__((pure)).
136
137 * BUGS
138 ** After a clone(), syscalls may be seen as sysrets in s390 (see trace.c:syscall_p())