strace/trace.cpp

175 lines
3.8 KiB
C++

// 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 <dlfcn.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string>
#include <sys/socket.h>
#define O_WRONLY 01
#define O_CREAT 0100
#define O_TRUNC 01000
// #include <fcntl.h> // 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;
}
}