TODO revision 61b4c490657af4a7af26e50fca5ea0c4a2960062
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*** typedef should be able to assign a lens to a name 25*** named arguments 26 This would be useful for replacing the arg1, emt2 etc. 27 28*** parameter pack improvements 29 The above format tweaks require that packs that expand to no types 30 at all be supported. If this works, then it should be relatively 31 painless to implement conditionals: 32 33 | void ptrace(REQ=enum(PTRACE_TRACEME=0,...), 34 | if[REQ==0](pack(),pack(pid_t, void*, void *))) 35 36 This is of course dangerously close to a programming language, and 37 I think ltrace should be careful to stay as simple as possible. 38 (We can hook into Lua, or TinyScheme, or some such if we want more 39 general scripting capabilities. Implementing something ad-hoc is 40 undesirable.) But the above can be nicely expressed by pattern 41 matching: 42 43 | void ptrace(REQ=enum[int](...)): 44 | [REQ==0] => () 45 | [REQ==1 or REQ==2] => (pid_t, void*) 46 | [true] => (pid_t, void*, void*); 47 48 Or: 49 50 | int open(string, FLAGS=flags[int](O_RDONLY=00,...,O_CREAT=0100,...)): 51 | [(FLAGS & 0100) != 0] => (flags[int](S_IRWXU,...)) 52 53 This would still require pretty complete expression evaluation. 54 _Including_ pointer dereferences and such. And e.g. in accept, we 55 need subtraction: 56 57 | int accept(int, +struct(short, +array(hex(char), X-2))*, (X=uint)*); 58 59 Perhaps we should hook to something after all. 60 61*** errno tracking 62 Some calls result in setting errno. Somehow mark those, and on 63 failure, show errno. 64 65*** second conversions? 66 This definitely calls for some general scripting. The goal is to 67 have seconds in adjtimex calls show as e.g. 10s, 1m15s or some 68 such. 69 70*** format should take arguments like string does 71 Format should take value argument describing the value that should 72 be analyzed. The following overwriting rules would then apply: 73 74 | format | format(array(char, zero)*) | 75 | format(LENS) | X=LENS, format[X] | 76 77 The latter expanded form would be canonical. 78 79 This depends on named arguments and parameter pack improvements 80 (we need to be able to construct parameter packs that expand to 81 nothing). 82 83*** More fine-tuned control of right arguments 84 Combination of named arguments and some extensions could take care 85 of that: 86 87 | void func(X=hide(int*), long*, +pack(X)); | 88 89 This would show long* as input argument (i.e. the function could 90 mangle it), and later show the pre-fetched X. The "pack" syntax is 91 utterly undeveloped as of now. The general idea is to produce 92 arguments that expand to some mix of types and values. But maybe 93 all we need is something like 94 95 | void func(out int*, long*); | 96 97 ltrace would know that out/inout/in arguments are given in the 98 right order, but left pass should display in and inout arguments 99 only, and right pass then out and inout. + would be 100 backward-compatible syntactic sugar, expanded like so: 101 102 | void func(int*, int*, +long*, long*); | 103 | void func(in int*, in int*, out long*, out long*); | 104 105 But sometimes we may want to see a different type on the way in and 106 on the way out. E.g. in asprintf, what's interesting on the way in 107 is the address, but on the way out we want to see buffer contents. 108 Does something like the following make sense? 109 110 | void func(X=void*, long*, out string(X)); | 111 112** Support for functions that never return 113 This would be useful for __cxa_throw, presumably also for longjmp 114 (do we handle that at all?) and perhaps a handful of others. 115 116** Support flag fields 117 enum-like syntax, except disjunction of several values is assumed. 118** Support long long 119 We currently can't define time_t on 32bit machines. That mean we 120 can't describe a range of time-related functions. 121 122** Support signed char, unsigned char, char 123 Also, don't format it as characted by default, string lens can do 124 it. Perhaps introduce byte and ubyte and leave 'char' as alias of 125 one of those with string lens applied by default. 126 127** Support fixed-width types 128 Really we should keep everything as {u,}int{8,16,32,64} internally, 129 and have long, short and others be translated to one of those 130 according to architecture rules. Maybe this could be achieved by a 131 per-arch config file with typedefs such as: 132 133 | typedef ulong = uint8_t | 134 135* BUGS 136** After a clone(), syscalls may be seen as sysrets in s390 (see trace.c:syscall_p()) 137