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