some try to get a hold on it...
however, it seems as if ld_preload changes offsets, need to find a way around this - so I can get usefull backtraces :-(
/* * gcc -Wall -nostartfiles -fpic -shared -olibbacktrace.so backtrace_open.c */ #define _GNU_SOURCE #define _FILE_OFFSET_BITS 64 #define _LARGEFILE_SOURCE
#include <dlfcn.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <assert.h> #include <sys/mman.h> #include <fcntl.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <errno.h> #include <time.h> #include <execinfo.h> /* XXX: do parallel support for open AND open64 by #undef open etc .. */ #define RESOLVE(x) if (!o_##x && !(o_##x = dlsym(RTLD_NEXT, #x))) { fprintf(stderr, #x"() not found!\n"); exit(-1); } #define min(x,y) ( (x)<(y)?(x):(y) ) #define max(x,y) ( (x)>(y)?(x):(y) ) #define N_FRAMES 16 /* XXX: need to handle this differently .. linked list? */ #define HIGHEST_FD 256 #define FEAT_RANGE_SUPPORT 1 static int (*o_open64)(const char *, int, ...); static int (*o_close)(int); static FILE *(*o_fopen64)(const char *, const char *); static int (*o_fclose)(FILE *); static int (*o_socket)(int domain, int type, int protocol); static int (*o_connect)(int sockfd, const struct sockaddr *addr, socklen_t addrlen); FILE *myfd = NULL; void _init(void) { RESOLVE(fopen64); /* CRASH! if you load us uninitialized, your process deserves to die! */ myfd = o_fopen64(getenv("DEBUG_FILENAME"), "w+"); fprintf(myfd, "%d: my filedescriptor.\n", fileno(myfd)); } void oneline_backtrace(const char* CallName, const char *str1, long nFD) { const long sizeofstr = N_FRAMES *3 + // 0x, sizeof(void*) * N_FRAMES * 4 + // hex number 256; void *stack_frames[N_FRAMES]; char addresslist[sizeofstr]; size_t size, i; long offset = 0; offset = sprintf(addresslist, "\n%ld: [%s][", nFD, CallName); size = backtrace(stack_frames, sizeof(stack_frames) / sizeof(void*)); if (size > 0) { if (N_FRAMES > size) size = N_FRAMES; for (i = 1; i < size; i++) { offset += sprintf(addresslist + offset, "%p;", stack_frames[i]); } } offset += snprintf(addresslist + offset, sizeof(addresslist) - offset, "]\n\t%s", str1); fwrite(addresslist, 1, offset, myfd); } #define NUMBUFSIZE 60 static char numbuf[NUMBUFSIZE]; char *str_off_t(__off64_t t) { char *p=numbuf+sizeof(numbuf)-1; int isneg=0; if (t < 0) { t= -t; isneg=1; } *p=0; do { *--p= '0' + (t % 10); t=t / 10; } while(t); if (isneg) *--p='-'; return p; } int open64(const char *pathname, int flag, ...) { int ret; RESOLVE(open64); ret = o_open64(pathname, flag); oneline_backtrace (__FUNCTION__, pathname, ret); return ret; } FILE *fopen64(const char *pathname, const char *mode) { FILE *Ret; RESOLVE(fopen64); Ret = o_fopen64(pathname, mode); oneline_backtrace (__FUNCTION__, pathname, fileno(Ret)); return Ret; } int socket(int domain, int type, int protocol) { int ret; char buf[128]; RESOLVE(socket); ret = o_socket(domain, type, protocol); snprintf(buf, sizeof(buf), "t: %d p:%d %s", type, protocol, strerror(errno)); oneline_backtrace (__FUNCTION__, buf, ret); return ret; } int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { const char *what; int ret; RESOLVE(connect); if (addrlen == sizeof(struct sockaddr_in6)) { what = " IPv6 "; } else if (addrlen == sizeof(struct sockaddr_in)) { what = " IPv4 "; } else { what = " WTF? "; } ret = o_connect(sockfd, addr, addrlen); oneline_backtrace (__FUNCTION__, what, sockfd); return ret; } int close(int fd) { oneline_backtrace (__FUNCTION__, "", fd); RESOLVE(close); return o_close(fd); } int fclose(FILE *stream) { int fd; int ret; fd = fileno(stream); RESOLVE(fclose); ret = o_fclose(stream); oneline_backtrace (__FUNCTION__, strerror(errno), fd); return ret; }