ÜberWall

UWgrind

/* $Id: UWgrind.c,v 1.2 2013/11/30 01:58:55 khorben Exp $ */
/* TODO:
* - determine memory type on the fly (static from stack from mmap from heap...)
* - track errno on all system calls
* - track format string origin
* - track memory not free'd (hook exit)
*/
#define DEBUG
//#define DEBUG_MASK 0x0000000f /* all errors */
//#define DEBUG_MASK 0x00000400 /* statistics */
//#define DEBUG_MASK 0x0000040f /* statistics and errors */
//#define DEBUG_MASK 0x0000042f
//#define DEBUG_MASK 0xffffffff /* everything */
#define DEBUG_MASK 0x00001400
#define ABORT_MASK 0x00000000 /* no errors */
//#define ABORT_MASK 0x0000000f /* all errors */
#include <assert.h>
#include <sys/mman.h>
#include <sys/shm.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <signal.h>
#include <dlfcn.h>
/* macros */
/* debugging levels */
#define DL_EFD 0x0001
#define DL_EPTR 0x0002
#define DL_ESTR 0x0004
#define DL_FD 0x0010
#define DL_PTR 0x0020
#define DL_STR 0x0040
/* system */
#define DL_SYSCALL 0x0100
#define DL_WARNING 0x0200
#define DL_STATS 0x0400
/* headers */
#define DL_STDLIB_H 0x1000
#define DL_STRING_H 0x2000
#define DL_STRINGS_H 0x2000
#define DL_UNISTD_H 0x4000
#define DL_PEDANTIC 0xffffffff
#ifdef DEBUG
# define DPRINTF(level, x) { if((level & DEBUG_MASK) == level) _dprintf x; \
if((level & ABORT_MASK) == level) kill(getpid(), SIGSTOP); }
#else
# define DPRINTF(level, x)
#endif
/* functions */
static int _dprintf(const char * format, ...)
{
int ret;
va_list ap;
va_start(ap, format);
ret = vfprintf(stderr, format, ap);
va_end(ap);
return ret;
}
/* UWgrind */
/* private */
/* types */
typedef struct _FunctionWrapper
{
void ** ptr;
char * name;
char * symbol;
size_t count;
} FunctionWrapper;
typedef enum _FunctionName
{
FN_BZERO = 0,
FN_CALLOC,
FN_CHDIR,
FN_CLOSE,
FN_EXIT,
FN_FCHDIR,
FN_FREE,
FN_FSTAT,
FN_GETENV,
FN_GETOPT,
FN_LINK,
FN_LSEEK,
FN_LSTAT,
FN_MALLOC,
FN_MEMCMP,
FN_MEMCPY,
FN_MEMMOVE,
FN_MEMSET,
FN_MKDIR,
FN_MKTEMP,
FN_MMAP,
FN_MREMAP,
FN_MUNMAP,
FN_OPEN,
FN_READ,
FN_READLINK,
FN_REALLOC,
FN_RECV,
FN_RMDIR,
FN_SEND,
FN_SHMGET,
FN_SOCKET,
FN_STAT,
FN_STRCAT,
FN_STRCMP,
FN_STRCPY,
FN_STRDUP,
FN_STRLEN,
FN_STRNCPY,
FN_STRNDUP,
FN_SYMLINK,
FN_UNLINK,
FN_WRITE,
} FunctionName;
#define FN_LAST FN_WRITE
#define FN_COUNT (FN_LAST + 1)
typedef enum _PointerType { PT_HEAP = 0, PT_MMAP } PointerType;
#define PT_LAST PT_MMAP
#define PT_COUNT (PT_LAST + 1)
typedef struct _Pointer
{
void * ptr;
size_t size;
PointerType type;
} Pointer;
/* variables */
/* internal */
static int _norec = 0;
/* function pointers */
/* static int (*old_asprintf)(char ** ret, char * format, ...); */
static void (*old_bzero)(void * b, size_t len);
static void * (*old_calloc)(size_t number, size_t size);
static int (*old_chdir)(const char * path);
static int (*old_close)(int fd);
static void (*old_exit)(int status);
static int (*old_fchdir)(int fd);
static void (*old_free)(void * ptr);
static int (*old_fstat)(int fd, struct stat * st);
static char * (*old_getenv)(const char * name);
static int (*old_getopt)(int argc, char * const argv[], const char * optstring);
static int (*old_link)(const char * name1, const char * name2);
static off_t (*old_lseek)(int fd, off_t offset, int whence);
static int (*old_lstat)(const char * path, struct stat * st);
static void * (*old_malloc)(size_t size);
static int (*old_memcmp)(const void * b1, const void * b2, size_t len);
static void * (*old_memcpy)(void * dst, const void * src, size_t len);
static void * (*old_memmove)(void * dst, const void * src, size_t len);
static void * (*old_memset)(void * b, int c, size_t len);
static int (*old_mkdir)(const char * path, mode_t mode);
static char * (*old_mktemp)(char * template);
static void * (*old_mmap)(void * addr, size_t len, int prot, int flags, int fd,
off_t offset);
static void * (*old_mremap)(void * oldp, size_t oldsize, void * newp,
size_t newsize, int flags);
static int (*old_munmap)(void * addr, size_t len);
static int (*old_open)(const char * path, int flags, mode_t mode);
static ssize_t (*old_read)(int fd, void * buf, size_t nbytes);
static ssize_t (*old_readlink)(const char * path, char * buf, size_t size);
static void * (*old_realloc)(void * ptr, size_t size);
static ssize_t (*old_recv)(int fd, void * buf, size_t len, int flags);
static int (*old_rmdir)(const char * path);
static ssize_t (*old_send)(int fd, const void * buf, size_t len, int flags);
static int (*old_shmget)(key_t key, size_t size, int shmflg);
static int (*old_socket)(int domain, int type, int protocol);
static int (*old_stat)(const char * path, struct stat * st);
static char * (*old_strcat)(char * s, const char * append);
static int (*old_strcmp)(const char * s1, const char * s2);
static char * (*old_strcpy)(char * dst, const char * src);
static char * (*old_strdup)(const char * str);
static size_t (*old_strlen)(const char * str);
static char * (*old_strncpy)(char * dst, const char * src, size_t len);
static char * (*old_strndup)(const char * str, size_t len);
static int (*old_symlink)(const char * name1, const char * name2);
static int (*old_unlink)(const char * path);
static ssize_t (*old_write)(int fd, const void * buf, size_t nbytes);
#define FW(a) { (void*)&old_ ## a, # a, # a, 0 },
FunctionWrapper _fw[FN_COUNT] =
{
FW(bzero)
FW(calloc)
FW(chdir)
FW(close)
FW(exit)
FW(fchdir)
FW(free)
#ifdef __NetBSD__
{ (void*)&old_fstat, "fstat", "__fstat30", 0 },
#else
FW(fstat)
#endif
FW(getenv)
FW(getopt)
FW(link)
FW(lseek)
#ifdef __NetBSD__
{ (void*)&old_lstat, "lstat", "__lstat30", 0 },
#else
FW(lstat)
#endif
FW(malloc)
FW(memcmp)
FW(memcpy)
FW(memmove)
FW(memset)
FW(mkdir)
FW(mktemp)
FW(mmap)
FW(mremap)
FW(munmap)
FW(open)
FW(read)
FW(readlink)
FW(realloc)
FW(recv)
FW(rmdir)
FW(send)
FW(shmget)
#ifdef __NetBSD__
{ (void*)&old_socket, "socket", "__socket30", 0 },
#else
FW(socket)
#endif
#ifdef __NetBSD__
{ (void*)&old_stat, "stat", "__stat30", 0 },
#else
FW(stat)
#endif
FW(strcat)
FW(strcmp)
FW(strcpy)
FW(strdup)
FW(strlen)
FW(strncpy)
FW(strndup)
FW(symlink)
FW(unlink)
FW(write)
};
/* file descriptors */
static int * _fd = NULL;
static size_t _fd_cnt = 0;
/* pointers */
static const char * sPointerType[PT_COUNT] = { "heap", "mmapped" };
static Pointer * _ptr = NULL;
static size_t _ptr_cnt = 0;
static intptr_t _heap;
static intptr_t _stack;
/* functions */
/* prototypes */
static void _fd_check(int fd);
static void _fd_close(int fd);
static void _fd_open(int fd);
static void _ptr_alloc(void * ptr, size_t size, PointerType type);
static void _ptr_check(void * ptr);
static void _ptr_read(const void * ptr, size_t size);
static void _ptr_free(void * ptr);
static void _ptr_write(const void * ptr, size_t size);
/* UWgrind_enter */
static void _UWgrind_enter(FunctionName name)
{
static void * hdl = NULL;
#ifdef __Linux__
static char libc[] = "/lib/libc.so.6";
#else
static char libc[] = "/lib/libc.so";
#endif
int i;
assert(_norec == 0);
_norec = 1;
_fw[name].count++;
if(hdl != NULL)
return;
if((hdl = dlopen(libc, RTLD_LAZY)) == NULL)
old_exit(1);
for(i = 0; i < FN_COUNT; i++)
if((*(_fw[i].ptr) = dlsym(hdl, _fw[i].symbol)) == NULL)
old_exit(1);
dlclose(hdl);
/* file descriptors */
_fd_open(0);
_fd_open(1);
_fd_open(2);
/* pointers */
_heap = (intptr_t)old_malloc(1);
_stack = (intptr_t)(&i) | 0xffff;
DPRINTF(DL_PEDANTIC, ("INFO: heap is @%p, stack is @%p\n", _heap,
_stack));
}
/* UWgrind_stats */
static void _UWgrind_stats(void)
{
size_t i;
for(i = 0; i < FN_COUNT; i++)
{
if(_fw[i].count == 0)
continue;
DPRINTF(DL_STATS, ("%s called %zu time(s)\n", _fw[i].name,
_fw[i].count));
}
DPRINTF(DL_STATS, ("%zu block(s) are still allocated\n", _ptr_cnt));
}
/* UWgrind_leave */
static void _UWgrind_leave(void)
{
_norec = 0;
}
/* UWgrind_error */
void _UWgrind_error(const char * message)
{
fputs("UWgrind: ", stderr);
perror(message);
}
/* file descriptors */
static void _fd_check(int fd)
{
size_t i;
if(fd < 0)
{
DPRINTF(DL_EFD, ("ERROR: invalid fd %d\n", fd));
return;
}
for(i = 0; i < _fd_cnt; i++)
if(fd == _fd[i])
return;
DPRINTF(DL_EFD, ("ERROR: fd %d is not opened\n", fd));
}
static void _fd_close(int fd)
{
size_t i;
int * p;
if(fd < 0)
{
DPRINTF(DL_EFD, ("ERROR: invalid fd %d\n", fd));
return;
}
for(i = 0; i < _fd_cnt; i++)
if(_fd[i] == fd)
break;
if(i == _fd_cnt)
{
DPRINTF(DL_EFD, ("ERROR: fd %d is not opened\n", fd));
return;
}
_fd_cnt--;
old_memmove(&_fd[i], &_fd[i + 1], sizeof(*_fd) * (_fd_cnt - i));
if((p = old_realloc(_fd, sizeof(*_fd) * _fd_cnt)) == NULL)
_UWgrind_error("realloc");
else
_fd = p;
}
static void _fd_open(int fd)
{
size_t i;
int * p;
if(fd < 0)
{
DPRINTF(DL_EFD, ("ERROR: invalid fd %d\n", fd));
return;
}
for(i = 0; i < _fd_cnt; i++)
if(_fd[i] == fd)
{
DPRINTF(DL_EFD, ("ERROR: fd %d is already opened\n",
fd));
return;
}
if((p = old_realloc(_fd, sizeof(*_fd) * (_fd_cnt + 1))) == NULL)
{
_UWgrind_error("realloc");
return;
}
_fd = p;
_fd[_fd_cnt++] = fd;
}
/* pointers */
static void _ptr_alloc(void * ptr, size_t size, PointerType type)
{
size_t i;
Pointer * p;
if(ptr == NULL)
{
DPRINTF(DL_EPTR, ("%s%s%s", "ERROR: ", sPointerType[type],
" allocation returned NULL\n"));
return;
}
for(i = 0; i < _ptr_cnt; i++)
if(_ptr[i].ptr == ptr)
{
DPRINTF(DL_EPTR, ("ERROR: %s pointer %p is already"
" allocated\n",
sPointerType[type], ptr));
return;
}
if((p = old_realloc(_ptr, sizeof(*_ptr) * (_ptr_cnt + 1))) == NULL)
{
_UWgrind_error("realloc");
return;
}
_ptr = p;
_ptr[_ptr_cnt].ptr = ptr;
_ptr[_ptr_cnt].size = size;
_ptr[_ptr_cnt++].type = type;
}
static void _ptr_check(void * ptr)
{
size_t i;
for(i = 0; i < _ptr_cnt; i++)
if(ptr >= _ptr[i].ptr && ptr < _ptr[i].ptr + _ptr[i].size)
return;
DPRINTF(DL_EPTR, ("ERROR: pointer %p is not allocated\n", ptr));
}
static void _ptr_free(void * ptr)
{
size_t i;
Pointer * p;
if(ptr == NULL)
{
DPRINTF(DL_PEDANTIC, ("ERROR: pointer %p is not valid\n", ptr));
return;
}
for(i = 0; i < _ptr_cnt; i++)
if(_ptr[i].ptr == ptr)
break;
if(i == _ptr_cnt)
{
DPRINTF(DL_EPTR, ("ERROR: pointer %p is not allocated\n", ptr));
return;
}
_ptr_cnt--;
old_memmove(&_ptr[i], &_ptr[i + 1], sizeof(*_ptr) * (_ptr_cnt - i));
if((p = old_realloc(_ptr, sizeof(*_ptr) * _ptr_cnt)) == NULL)
_UWgrind_error("realloc");
else
_ptr = p;
}
void _ptr_read(const void * ptr, size_t size)
{
size_t i;
if(ptr < _stack && ptr > &i)
{
DPRINTF(DL_PTR, ("DEBUG: reading stack %zu@%p\n", size, ptr));
if(ptr + size <= &i)
DPRINTF(DL_EPTR, ("ERROR: stack read overflow %zu@%p"
" (@%p)\n", size, ptr, &i));
return;
}
for(i = 0; i < _ptr_cnt; i++)
if(_ptr[i].ptr <= ptr && _ptr[i].ptr + _ptr[i].size > ptr)
break;
if(i < _ptr_cnt)
{
DPRINTF(DL_PTR, ("DEBUG: reading %s %zu@%p\n",
sPointerType[_ptr[i].type], size, ptr));
if(ptr + size > _ptr[i].ptr + _ptr[i].size)
DPRINTF(DL_EPTR, ("ERROR: %s read overflow %zu@%p"
" (%zu@%p)\n",
sPointerType[_ptr[i].type],
size, ptr, _ptr[i].size,
_ptr[i].ptr));
return;
}
DPRINTF(DL_PTR, ("DEBUG: reading %zu@%p\n", size, ptr));
}
void _ptr_write(const void * ptr, size_t size)
{
size_t i;
if(ptr < _stack && ptr > &i)
{
DPRINTF(DL_PTR, ("DEBUG: writing stack %zu@%p\n", size, ptr));
if(ptr + size <= &i)
DPRINTF(DL_EPTR, ("ERROR: stack write overflow %zu@%p"
" (@%p)\n", size, ptr, &i));
return;
}
for(i = 0; i < _ptr_cnt; i++)
if(_ptr[i].ptr <= ptr && _ptr[i].ptr + _ptr[i].size > ptr)
/* FIXME detect offsets inside allocated memory,
* small offsets before, ... */
break;
if(i < _ptr_cnt)
{
DPRINTF(DL_PTR, ("DEBUG: writing %s %zu@%p\n",
sPointerType[_ptr[i].type], size, ptr));
if(ptr + size > _ptr[i].ptr + _ptr[i].size)
DPRINTF(DL_EPTR, ("ERROR: %s write overflow %zu@%p"
" (%zu@%p)\n",
sPointerType[_ptr[i].type],
size, ptr, _ptr[i].size,
_ptr[i].ptr));
return;
}
DPRINTF(DL_PTR, ("DEBUG: writing %zu@%p\n", size, ptr));
}
/* strings */
void _str_check(const char * str)
{
_ptr_read(str, old_strlen(str) + 1);
}
/* public */
/* TODO:
* - everything that manipulates pointers, buffers...
* *_r
* asprintf */
/* bzero */
void bzero(void * b, size_t len)
{
if(_norec)
return old_bzero(b, len);
_UWgrind_enter(FN_BZERO);
_ptr_write(b, len);
old_bzero(b, len);
DPRINTF(DL_STRINGS_H, ("CALL: bzero(%p, %zu)\n", b, len));
_UWgrind_leave();
}
/* calloc */
void * calloc(size_t number, size_t size)
{
void * ret;
if(_norec)
return old_calloc(number, size);
_UWgrind_enter(FN_CALLOC);
ret = old_calloc(number, size);
DPRINTF(DL_STDLIB_H, ("CALL: calloc(%zu, %zu) => %p\n", number, size,
ret));
_ptr_alloc(ret, number * size, PT_HEAP);
_UWgrind_leave();
return ret;
}
/* chdir */
int chdir(const char * path)
{
int ret;
if(_norec)
return old_chdir(path);
_UWgrind_enter(FN_CHDIR);
ret = old_chdir(path);
DPRINTF(DL_SYSCALL, ("CALL: chdir(\"%s\") => %d\n", path, ret));
_UWgrind_leave();
return ret;
}
/* close */
int close(int fd)
{
int ret;
if(_norec)
return old_close(fd);
_UWgrind_enter(FN_CLOSE);
_fd_close(fd);
ret = old_close(fd);
DPRINTF(DL_SYSCALL, ("CALL: close(%d) => %d\n", fd, ret));
_UWgrind_leave();
return ret;
}
/* exit */
void exit(int status)
{
if(_norec)
{
old_exit(status);
_exit(status);
}
_UWgrind_enter(FN_EXIT);
_UWgrind_stats();
DPRINTF(DL_SYSCALL, ("CALL: exit(%d)\n", status));
old_exit(status);
_UWgrind_leave();
}
/* fchdir */
int fchdir(int fd)
{
int ret;
if(_norec)
return old_fchdir(fd);
_UWgrind_enter(FN_FCHDIR);
_fd_check(fd);
ret = old_fchdir(fd);
DPRINTF(DL_SYSCALL, ("CALL: fchdir(%d) => %d\n", fd, ret));
_UWgrind_leave();
return ret;
}
/* fclose
* feof
* fgetpos
* fgets
* fileno
* fopen
* fprintf
* fread */
/* free */
void free(void * ptr)
{
if(_norec)
return old_free(ptr);
_UWgrind_enter(FN_FREE);
old_free(ptr);
DPRINTF(DL_STDLIB_H, ("CALL: free(%p)\n", ptr));
_ptr_free(ptr);
_UWgrind_leave();
}
/* freopen
* fseek
* fsetpos
* ftell
* fwrite */
/* fstat */
int fstat(int fd, struct stat * st)
{
int ret;
if(_norec)
return old_fstat(fd, st);
_UWgrind_enter(FN_FSTAT);
_fd_check(fd);
_ptr_write(st, sizeof(*st));
ret = old_fstat(fd, st);
DPRINTF(DL_SYSCALL, ("CALL: fstat(%d, %p) => %d\n", fd, st, ret));
_UWgrind_leave();
return ret;
}
/* getenv */
char * getenv(const char * name)
{
char * ret;
if(_norec)
return old_getenv(name);
_UWgrind_enter(FN_GETENV);
_str_check(name);
ret = old_getenv(name);
DPRINTF(DL_STDLIB_H, ("CALL: getenv(\"%s\") => %p\n", name, ret));
_UWgrind_leave();
return ret;
}
/* getopt */
int getopt(int argc, char * const argv[], const char * optstring)
{
int ret;
if(_norec)
return old_getopt(argc, argv, optstring);
_UWgrind_enter(FN_GETOPT);
ret = old_getopt(argc, argv, optstring);
DPRINTF(DL_UNISTD_H, ("CALL: getopt(%d, %p, \"%s\") => %d\n", argc,
argv, optstring, ret));
_UWgrind_leave();
return ret;
}
/* link */
int link(const char * name1, const char * name2)
{
int ret;
if(_norec)
return old_link(name1, name2);
_UWgrind_enter(FN_LINK);
_str_check(name1);
_str_check(name2);
ret = old_link(name1, name2);
DPRINTF(DL_SYSCALL, ("CALL: link(\"%s\", \"%s\") => %d\n", name1,
name2, ret));
_UWgrind_leave();
return ret;
}
/* lseek */
off_t lseek(int fd, off_t offset, int whence)
{
off_t ret;
if(_norec)
return old_lseek(fd, offset, whence);
_UWgrind_enter(FN_LSEEK);
_fd_check(fd);
ret = old_lseek(fd, offset, whence);
DPRINTF(DL_SYSCALL, ("CALL: lseek(%d, %zd, %d) => %zd\n", fd, offset,
whence, ret));
_UWgrind_leave();
return ret;
}
/* lstat */
int lstat(const char * path, struct stat * st)
{
int ret;
if(_norec)
return old_lstat(path, st);
_UWgrind_enter(FN_LSTAT);
_str_check(path);
_ptr_write(st, sizeof(*st));
ret = old_lstat(path, st);
DPRINTF(DL_SYSCALL, ("CALL: lstat(\"%s\", %p) => %d\n", path, st,
ret));
_UWgrind_leave();
return ret;
}
/* malloc */
void * malloc(size_t size)
{
void * ret;
if(_norec)
return old_malloc(size);
_UWgrind_enter(FN_MALLOC);
ret = old_malloc(size);
DPRINTF(DL_STDLIB_H, ("CALL: malloc(%zu) => %p\n", size, ret));
if(ret == NULL)
return ret;
_ptr_alloc(ret, size, PT_HEAP);
_UWgrind_leave();
return ret;
}
/* memcmp */
int memcmp(const void * b1, const void * b2, size_t len)
{
int ret;
if(_norec)
return old_memcmp(b1, b2, len);
_UWgrind_enter(FN_MEMCMP);
ret = old_memcmp(b1, b2, len);
_ptr_read(b2, len);
_ptr_read(b1, len);
DPRINTF(DL_STRING_H, ("CALL: memcmp(%p, %p, %zu) => %d\n", b1, b2, len,
ret));
_UWgrind_leave();
return ret;
}
/* memcpy */
void * memcpy(void * dst, const void * src, size_t len)
{
void * ret;
if(_norec)
return old_memcpy(dst, src, len);
_UWgrind_enter(FN_MEMCPY);
_ptr_read(src, len);
_ptr_write(dst, len);
if(src == dst || (dst < src && dst + len > src)
|| (src < dst && src + len > dst))
DPRINTF(DL_PTR, ("ERROR: potential memory corruption @%p\n",
dst));
ret = old_memcpy(dst, src, len);
DPRINTF(DL_STRING_H, ("CALL: memcpy(%p, %p, %zu) => %p\n", dst, src,
len, ret));
_UWgrind_leave();
return ret;
}
/* memmove */
void * memmove(void * dst, const void * src, size_t len)
{
void * ret;
if(_norec)
return old_memmove(dst, src, len);
_UWgrind_enter(FN_MEMMOVE);
_ptr_read(src, len);
_ptr_write(dst, len);
ret = old_memmove(dst, src, len);
DPRINTF(DL_STRING_H, ("CALL: memmove(%p, %p, %zu) => %p\n", dst, src,
len, ret));
_UWgrind_leave();
return ret;
}
/* memset */
void * memset(void * b, int c, size_t len)
{
void * ret;
if(_norec)
return old_memset(b, c, len);
_UWgrind_enter(FN_MEMSET);
if(len == 0)
DPRINTF(DL_WARNING, ("%s", "WARNING: zero-length memset\n"));
_ptr_write(b, len);
ret = old_memset(b, c, len);
DPRINTF(DL_STRING_H, ("CALL: memset(%p, %d, %zu) => %p\n", b, c, len,
ret));
_UWgrind_leave();
return ret;
}
/* mkdir */
int mkdir(const char * path, mode_t mode)
{
int ret;
if(_norec)
return old_mkdir(path, mode);
_UWgrind_enter(FN_MKDIR);
_str_check(path);
ret = old_mkdir(path, mode);
DPRINTF(DL_SYSCALL, ("CALL: mkdir(\"%s\", %o) => %d\n", path, mode,
ret));
_UWgrind_leave();
return ret;
}
/* mktemp */
char * mktemp(char * template)
{
char * ret;
if(_norec)
return old_mktemp(template);
_UWgrind_enter(FN_MKTEMP);
ret = old_mktemp(template);
DPRINTF(DL_STDLIB_H, ("CALL: mktemp(\"%s\") => \"%s\"\n", ret));
_UWgrind_leave();
return ret;
}
/* mmap */
void * mmap(void * addr, size_t len, int prot, int flags, int fd, off_t offset)
{
void * ret;
if(_norec)
return old_mmap(addr, len, prot, flags, fd, offset);
_UWgrind_enter(FN_MMAP);
if((flags & MAP_ANON) != MAP_ANON)
_fd_check(fd);
ret = old_mmap(addr, len, prot, flags, fd, offset);
DPRINTF(DL_SYSCALL, ("CALL: mmap(%p, %zu, %d, %d, %d, %zd) => %p\n",
addr, len, prot, flags, fd, offset));
if(ret != MAP_FAILED)
_ptr_alloc(ret, len, PT_MMAP);
_UWgrind_leave();
return ret;
}
/* mremap */
void * mremap(void * oldp, size_t oldsize, void * newp, size_t newsize,
int flags)
{
void * ret;
if(_norec)
return old_mremap(oldp, oldsize, newp, newsize, flags);
_UWgrind_enter(FN_MREMAP);
ret = old_mremap(oldp, oldsize, newp, newsize, flags);
DPRINTF(DL_SYSCALL, ("CALL: mremap(%p, %zu, %p, %zu, %d) => %p\n",
oldp, oldsize, newp, newsize, flags, ret));
if(ret != MAP_FAILED)
{
_ptr_free(oldp);
_ptr_alloc(ret, newsize, PT_MMAP);
}
_UWgrind_leave();
return ret;
}
/* munmap */
int munmap(void * addr, size_t len)
{
int ret;
if(_norec)
return old_munmap(addr, len);
_UWgrind_enter(FN_MUNMAP);
ret = old_munmap(addr, len);
DPRINTF(DL_SYSCALL, ("CALL: munmap(%p, %zu) => %d\n", addr, len, ret));
if(ret == 0)
_ptr_free(addr);
_UWgrind_leave();
return ret;
}
/* open */
int open(const char * path, int flags, mode_t mode)
{
int ret;
if(_norec)
return old_open(path, flags, mode);
_UWgrind_enter(FN_OPEN);
if((ret = old_open(path, flags, mode)) >= 0)
_fd_open(ret);
DPRINTF(DL_SYSCALL, ("CALL: open(\"%s\", %d, %o) => %d\n", path, flags,
mode, ret));
_UWgrind_leave();
return ret;
}
/* printf */
/* read */
ssize_t read(int fd, void * buf, size_t nbytes)
{
ssize_t ret;
if(_norec)
return old_read(fd, buf, nbytes);
_UWgrind_enter(FN_READ);
_fd_check(fd);
_ptr_write(buf, nbytes);
ret = old_read(fd, buf, nbytes);
DPRINTF(DL_SYSCALL, ("CALL: read(%d, %p, %zu) => %zd\n", fd, buf,
nbytes, ret));
_UWgrind_leave();
return ret;
}
/* readlink */
ssize_t readlink(const char * path, char * buf, size_t size)
{
ssize_t ret;
if(_norec)
return old_readlink(path, buf, size);
_UWgrind_enter(FN_READLINK);
_str_check(path);
_ptr_write(buf, size);
ret = old_readlink(path, buf, size);
DPRINTF(DL_SYSCALL, ("CALL: readlink(\"%s\", %p, %zu) => %zd\n",
path, buf, size, ret));
_UWgrind_leave();
return ret;
}
/* realloc */
void * realloc(void * ptr, size_t size)
{
void * ret;
if(_norec)
return old_realloc(ptr, size);
_UWgrind_enter(FN_REALLOC);
if(ptr != NULL)
_ptr_check(ptr);
if(size == 0)
DPRINTF(DL_WARNING, ("%s", "WARNING: zero-size realloc()\n"));
ret = old_realloc(ptr, size);
DPRINTF(DL_STDLIB_H, ("CALL: realloc(%p, %zu) => %p\n", ptr, size,
ret));
if(ret == NULL)
{
if(size == 0)
_ptr_free(ptr);
_UWgrind_leave();
return ret;
}
_ptr_free(ptr);
_ptr_alloc(ret, size, PT_HEAP);
_UWgrind_leave();
return ret;
}
/* recv */
ssize_t recv(int fd, void * buf, size_t len, int flags)
{
ssize_t ret;
if(_norec)
return old_recv(fd, buf, len, flags);
_UWgrind_enter(FN_RECV);
_fd_check(fd);
_ptr_write(buf, len);
ret = old_recv(fd, buf, len, flags);
DPRINTF(DL_SYSCALL, ("CALL: recv(%d, %p, %zu, %d) => %zd\n", fd, buf,
len, flags, ret));
_UWgrind_leave();
return ret;
}
/* rmdir */
int rmdir(const char * path)
{
int ret;
if(_norec)
return old_rmdir(path);
_UWgrind_enter(FN_RMDIR);
_str_check(path);
ret = old_rmdir(path);
DPRINTF(DL_SYSCALL, ("CALL: rmdir(%p \"%s\") => %d\n", path, path,
ret));
_UWgrind_leave();
return ret;
}
/* send */
ssize_t send(int fd, const void * buf, size_t len, int flags)
{
ssize_t ret;
if(_norec)
return old_send(fd, buf, len, flags);
_UWgrind_enter(FN_SEND);
_fd_check(fd);
_ptr_read(buf, len);
ret = old_send(fd, buf, len, flags);
DPRINTF(DL_SYSCALL, ("CALL: send(%d, %p, %zu, %d) => %zd\n", fd, buf,
len, flags, ret));
_UWgrind_leave();
return ret;
}
/* setenv */
/* shmget */
int shmget(key_t key, size_t size, int shmflg)
{
int ret;
if(_norec)
return old_shmget(key, size, shmflg);
_UWgrind_enter(FN_SHMGET);
ret = old_shmget(key, size, shmflg);
DPRINTF(DL_SYSCALL, ("CALL: shmget(%u, %zu, %d) => %d\n", key, size,
shmflg, ret));
_UWgrind_leave();
return ret;
}
/* snprintf */
/* socket */
int socket(int domain, int type, int protocol)
{
int ret;
if(_norec)
return old_socket(domain, type, protocol);
_UWgrind_enter(FN_SOCKET);
ret = old_socket(domain, type, protocol);
DPRINTF(DL_SYSCALL, ("CALL: socket(%d, %d, %d) => %d\n", domain, type,
protocol, ret));
if(ret != -1)
_fd_open(ret);
_UWgrind_leave();
return ret;
}
/* sprintf */
/* stat */
int stat(const char * path, struct stat * st)
{
int ret;
if(_norec)
return old_stat(path, st);
_UWgrind_enter(FN_STAT);
_str_check(path);
_ptr_write(st, sizeof(*st));
ret = old_stat(path, st);
DPRINTF(DL_SYSCALL, ("CALL: stat(%p \"%s\", %p) => %d\n", path, path,
st, ret));
_UWgrind_leave();
return ret;
}
/* swab */
/* strcat */
char * strcat(char * s, const char * append)
{
char * ret;
if(_norec)
return old_strcat(s, append);
_UWgrind_enter(FN_STRCAT);
_str_check(s);
_str_check(append);
ret = old_strcat(s, append);
DPRINTF(DL_STRING_H, ("CALL: strcat(%p \"%s\", %p \"%s\") => \"%s\"\n",
s, s, append, append, ret));
if(ret != NULL)
_str_check(ret);
_UWgrind_leave();
return ret;
}
/* strcmp */
int strcmp(const char * s1, const char * s2)
{
int ret;
if(_norec)
return old_strcmp(s1, s2);
_UWgrind_enter(FN_STRCMP);
_str_check(s1);
_str_check(s2);
ret = old_strcmp(s1, s2);
DPRINTF(DL_STRING_H, ("CALL: strcmp(%p \"%s\", %p \"%s\") => %d\n", s1,
s1, s2, s2, ret));
_UWgrind_leave();
return ret;
}
/* strcpy */
char * strcpy(char * dst, const char * src)
{
size_t len;
char * ret;
if(_norec)
return old_strcpy(dst, src);
_UWgrind_enter(FN_STRCPY);
len = old_strlen(src) + 1;
_ptr_read(src, len);
_ptr_write(dst, len);
ret = old_strcpy(dst, src);
DPRINTF(DL_STRING_H, ("CALL: strcpy(%p \"%s\", %p \"%s\") => %p\n",
dst, dst, src, src, ret));
_UWgrind_leave();
return ret;
}
/* strdup */
char * strdup(const char * str)
{
char * ret;
size_t len;
if(_norec)
return old_strdup(str);
_UWgrind_enter(FN_STRDUP);
len = old_strlen(str) + 1;
_ptr_read(str, len);
ret = old_strdup(str);
DPRINTF(DL_STRING_H, ("CALL: strdup(%p \"%s\") => %p\n", str, str,
ret));
if(ret != NULL)
_ptr_alloc(ret, len, PT_HEAP);
_UWgrind_leave();
return ret;
}
/* strlen */
size_t strlen(const char * str)
{
/* static int norec = 0; */
size_t ret;
if(_norec)
return old_strlen(str);
/* if(norec)
return old_strlen(str);
norec = 1; */
_UWgrind_enter(FN_STRLEN);
ret = old_strlen(str);
_ptr_read(str, ret + 1);
DPRINTF(DL_STRING_H, ("CALL: strlen(%p \"%s\") => %zu\n", str, str,
ret));
/* norec = 0; */
_UWgrind_leave();
return ret;
}
/* strncat
* strncmp */
/* strncpy */
char * strncpy(char * dst, const char * src, size_t len)
{
char * ret;
if(_norec)
return old_strncpy(dst, src, len);
_UWgrind_enter(FN_STRNCPY);
_ptr_read(src, len);
_ptr_write(dst, len);
ret = old_strncpy(dst, src, len);
DPRINTF(DL_STRING_H, ("CALL: strcpy(%p \"%s\", %p \"%s\", %zu)"
" => %p\n", dst, dst, src, src, len, ret));
_UWgrind_leave();
return ret;
}
/* strndup */
char * strndup(const char * str, size_t len)
{
char * ret;
if(_norec)
return old_strndup(str, len);
_UWgrind_enter(FN_STRNDUP);
_str_check(str); /* FIXME check with maximum length of len */
ret = old_strndup(str, len);
DPRINTF(DL_STRING_H, ("CALL: strndup(%p \"%s\", %zu) => %p\n", str,
str, len, ret));
_ptr_alloc(ret, len, PT_HEAP); /* FIXME check with maximum length of len */
_UWgrind_leave();
return ret;
}
/* symlink */
int symlink(const char * name1, const char * name2)
{
int ret;
if(_norec)
return old_symlink(name1, name2);
_UWgrind_enter(FN_SYMLINK);
_str_check(name1);
_str_check(name2);
ret = old_symlink(name1, name2);
DPRINTF(DL_SYSCALL, ("CALL: symlink(%p \"%s\", %p \"%s\") => %p\n",
name1, name1, name2, name2, ret));
_UWgrind_leave();
return ret;
}
/* unlink */
int unlink(const char * path)
{
int ret;
if(_norec)
return old_unlink(path);
_str_check(path);
_UWgrind_enter(FN_UNLINK);
ret = old_unlink(path);
DPRINTF(DL_SYSCALL, ("CALL: unlink(%p \"%s\") => %d\n", path, path,
ret));
_UWgrind_leave();
return ret;
}
/* vasprintf
* vfprintf
* vprintf
* vsnprintf
* vsprintf */
/* write */
ssize_t write(int fd, const void * buf, size_t nbytes)
{
ssize_t ret;
if(_norec)
return old_write(fd, buf, nbytes);
_UWgrind_enter(FN_WRITE);
_fd_check(fd);
_ptr_read(buf, nbytes);
ret = old_write(fd, buf, nbytes);
DPRINTF(DL_SYSCALL, ("CALL: write(%d, %p, %zu) => %zd\n", fd, buf,
nbytes, ret));
_UWgrind_leave();
return ret;
}