// compile with: g++ -rdynamic -std=c++11 -shared -o trace.so trace.cpp getgetCaller().c_str().cpp -fpic -ldl #define RTLD_NEXT ((void *) -1l) #include #include #include #include #include #include #include #include #define O_WRONLY 01 #define O_CREAT 0100 #define O_TRUNC 01000 // #include // conflicts with open() static int (*libc_open)(const char* path, int flags, mode_t mode) = NULL; static int (*libc_close)(int fd) = NULL; static int (*libc_socket)(int domain, int type, int protocol) = NULL; static int (*libc_accept)(int sockfd, struct sockaddr *addr, socklen_t *addrlen) = NULL; static int (*libc_accept4)(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) = NULL; static int (*libc_pipe)(int pipefd[2]) = NULL; static int (*libc_pipe2)(int pipefd[2], int flags) = NULL; static int (*libc_dup)(int oldfd) = NULL; static int (*libc_dup2)(int oldfd, int newfd) = NULL; static int (*libc_dup3)(int oldfd, int newfd, int flags) = NULL; static int writefd = -1; std::string getCaller(); #define SETCAST(N) libc_ ## N = ( decltype(libc_ ## N) ) dlsym(RTLD_NEXT, #N) void init() { if(!libc_open) { SETCAST(open); SETCAST(close); SETCAST(socket); SETCAST(accept); SETCAST(accept4); SETCAST(pipe); SETCAST(pipe2); SETCAST(dup); SETCAST(dup2); SETCAST(dup3); char* target = getenv("TRACEOUT"); if(!target) { writefd = STDOUT_FILENO; return; } writefd = libc_open(target, (int) O_WRONLY | O_CREAT | O_TRUNC, (mode_t) 0664); } } extern "C" { int open(const char* path, int flags, mode_t mode) { init(); errno = 0; int res = libc_open(path, flags, mode); dprintf(writefd, "%s -> open(\"%s\", %i, %o) = %i (e: %i)\n", getCaller().c_str(), path, flags, mode, res, errno); return res; } int close(int fd) { init(); errno = 0; int res = libc_close(fd); dprintf(writefd, "%s -> close(%i) = %i (e: %i)\n", getCaller().c_str(), fd, res, errno); return res; } int socket(int dom, int type, int prot) { init(); errno = 0; int res = libc_socket(dom, type, prot); dprintf(writefd, "%s -> socket(%i, %i, %i) = %i (e: %i)\n", getCaller().c_str(), dom, type, prot, res, errno); return res; } int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { init(); errno = 0; int res = libc_accept(sockfd, addr, addrlen); dprintf(writefd, "%s -> accept(%i, x, x) = %i (e: %i)\n", getCaller().c_str(), sockfd, res, errno); return res; } int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) { init(); errno = 0; int res = libc_accept4(sockfd, addr, addrlen, flags); dprintf(writefd, "%s -> accept4(%i, x, x, %i) = %i (e: %i)\n", getCaller().c_str(), sockfd, flags, res, errno); return res; } int pipe(int pipefd[2]) { init(); errno = 0; int res = libc_pipe(pipefd); dprintf(writefd, "%s -> pipe([%i, %i]) = %i (e: %i)\n", getCaller().c_str(), pipefd[0], pipefd[1], res, errno); return res; } int pipe2(int pipefd[2], int flags) { init(); errno = 0; int res = libc_pipe2(pipefd, flags); dprintf(writefd, "%s -> pipe2([%i, %i], %i) = %i (e: %i)\n", getCaller().c_str(), pipefd[0], pipefd[1], flags, res, errno); return res; } int dup(int oldfd) { init(); errno = 0; int res = libc_dup(oldfd); dprintf(writefd, "%s -> dup(%i) = %i (e: %i)\n", getCaller().c_str(), oldfd, res, errno); return res; } int dup2(int oldfd, int newfd) { init(); errno = 0; int res = libc_dup2(oldfd, newfd); dprintf(writefd, "%s -> dup2(%i, %i) = %i (e: %i)\n", getCaller().c_str(), oldfd, newfd, res, errno); return res; } int dup3(int oldfd, int newfd, int flags) { init(); errno = 0; int res = libc_dup3(oldfd, newfd, flags); dprintf(writefd, "%s -> dup3(%i, %i, %i) = %i (e: %i)\n", getCaller().c_str(), oldfd, newfd, flags, res, errno); return res; } }