I think that the wrapper framework in valgrind is pretty nice. I am trying to track differences between different code paths (as to why one works and another does not). Instead of trying to look at a difference of an strace output (which will not give me all details I need because I want to trace lib and sys calls I decided to use wrappers around a handful of functions.
The one function that got me scratching my head is fcntl.
The fcntl manpage declares it as follows
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock *lock);
However as this is C and overloading does not come naturally to C, it is prototyped as follows in fcntl.h
extern int fcntl (int __fd, int __cmd, ...);
The end-user wrapping facility in valgrind supports N number of WORD arguments, but carries a warning about using the wrong number of args and I did not see a mention of any varargs.
A more classical varargs function like printf is typically implemented with a lower fixed args function vprintf which takes va_list as a single parameter. In such a case I would have wrapped vprintf rather than printf, but alas AFAIK fcntl does not have such an intermediate function.
My question is – what would a “safe” wrapper for fcntl look like?
For example, the following seems to work, but is it safe:
int I_WRAP_SONAME_FNNAME_ZU(libcZdsoZa,fcntl)(int fd, int cmd, ...)
{
int result;
OrigFn fn;
void* arg;
va_list argp;
va_start(argp, cmd);
arg=va_arg(argp, void*);
VALGRIND_GET_ORIG_FN(fn);
printf("@@fcntl wrapper: args fd=%d, cmd=%d, arg=%p ... ", fd, cmd, arg);
CALL_FN_W_WWW(result, fn, fd, cmd, arg);
printf("##fcntl wrapper: result %d\n", result);
return result;
}
Look syswrappers for sys_ioctl in valgrind sources in file coregrind/m_syswrap/syswrap-linux.c.
Look at http://valgrind.org/docs/manual/dist.readme-missing.html for details.
Maybe you will need to rebuild valgrind with your changes for syswrappers.