Hello everybody,

ltrace does not trace calls made to dynamically loaded objects,
and this made my testing of ncpfs Perl wrapper very hard, as
I was not able to confirm what's going inside without adding
debugging prints into either ncpfs or into generated wrapper...

I found this unacceptable, and so I cooked this code. You can
use it to create wrapper around any library you want, it just
must be dynamic library, not a static one.

Usage is simple:

NCP_TRACE_FILE=demo.trc LD_PRELOAD=./tracencp.so demo.pl

and enjoy demo.trc file.

I hope that in future I'll be able to persuade SWIG to create
trace_in_* and trace_out_* wrappers for me automatically - but
of course you can do it yourself meanwhile.

trace_in_XXX function has same arguments as XXX function, with 
two parameters added in front of the list - const char* functionName 
and void* caller. trace_out_XXX function has also arguments of
wrapped function - with added int returnValue and void* caller. 
So for example for NWDSFreeContext() you have:

NWDSCCODE NWDSFreeContext(NWDSContextHandle ctx);
void trace_in_NWDSFreeContext(const char* name, void* addr, NWDSContextHandle ctx);
void trace_out_NWDSFreeContext(NWDSCCODE err, void* addr, NWDSContextHandle ctx);

You should not modify arguments passed to you - depending on
optimization level your changes may be visible to function you
are wrapping and/or to caller. And you should use logprintf()
in trace_in_* and resprintf() in trace_out_*. These functions
take a care of automatic indenting and printing address of caller.

And of course, currently there are several limitations:
- only i386 version exists... Write your own assembly code, and send me it
  if you want this on your architecture.
- you cannot create C wrappers around functions which return 64bit
  quantities (if you'll cook wrapper in assembly, you'll find upper
  32bits in %edx register).
- on callchain deeper than 256 levels it dies.
- versioned symbols are not properly wrapped with version, they
  are wrapped without version information.
- maybe more... Use of weak symbols is intentional feature and not a bug.

Example (this example also shows that context handle is automatically
destroyed when it is no longer referenced from Perl - this is why
I wrote this tracer...):

$ NCP_TRACE_FILE=demo.trc LD_PRELOAD=./tracencp.so demo.pl
NWDSCreateContext() = ok, ctx=ncpfs::NWDSContextHandle=SCALAR(0x80f6408)
NWDSDuplicateContext(ctx) = ok, nctx=ncpfs::NWDSContextHandle=SCALAR(0x80f6444)
$ cat demo.trc
402B593D: NWDSCreateContext() = ...
401E3787:   NWDSCreateContextHandle() = ...
401E3242:     NWDSInitRequester() = ...
401E22B2:       my_iconv() = 0
401E22C0:       my_iconv_close() = 0
(cont'd.)     ... = 0
401E3377:     NWDSSetContext() = ...
401E39B3:       my_iconv_open() = 135390952
401E39D6:       my_iconv_open() = 135305312
(cont'd.)     ... = 0
401E33CA:     NWDSSetTransport() = 0
(cont'd.)   ... = 0
(cont'd.) ... = 137280664
402B5BB0: NWDSDuplicateContext() = ...
401E37BE:   NWDSDuplicateContextHandle() = ...
401E3508:     NWDSSetContext() = ...
401E39B3:       my_iconv_open() = 135292056
401E39D6:       my_iconv_open() = 135291776
(cont'd.)     ... = 0
401E360E:     NWDSSetContext() = ...
401E39B3:       my_iconv_open() = 135404088
401E39D6:       my_iconv_open() = 135733664
401E3A05:       my_iconv_close() = 0
401E3A22:       my_iconv_close() = 0
(cont'd.)     ... = 0
(cont'd.)   ... = 0
(cont'd.) ... = 136991752
40255E93: NWDSFreeContext() = ...
401E36A1:   my_iconv_close() = 0
401E36B5:   my_iconv_close() = 0
(cont'd.) ... = 0
40255E93: NWDSFreeContext() = ...
401E36A1:   my_iconv_close() = 0
401E36B5:   my_iconv_close() = 0
(cont'd.) ... = 0
$

					Enjoy,
						Petr Vandrovec
						vandrove@vc.cvut.cz
