initial
This commit is contained in:
commit
0601b95da3
|
@ -0,0 +1,3 @@
|
|||
*.so
|
||||
*.txt
|
||||
*.log
|
|
@ -0,0 +1,13 @@
|
|||
NAME = trace.so
|
||||
LDFLAGS = -ldl
|
||||
CFLAGS = -rdynamic -std=c++11 -shared -fpic
|
||||
|
||||
all: $(NAME)
|
||||
|
||||
$(NAME): trace.cpp getcaller.cpp
|
||||
g++ $(CFLAGS) -o $@ $< $(LDFLAGS)
|
||||
|
||||
clean:
|
||||
$(RM) -f trace.so
|
||||
|
||||
.PHONY: all
|
|
@ -0,0 +1,15 @@
|
|||
# strace
|
||||
|
||||
Custom strace, that logs the calling function but only logs syscalls that open or close a fd.
|
||||
|
||||
## Compile
|
||||
```
|
||||
make all
|
||||
```
|
||||
|
||||
## Use
|
||||
```bash
|
||||
TRACEOUT=trace.log LD_PRELOAD=./trace.so ./program-under-test --arg1 --arg2 ....
|
||||
```
|
||||
|
||||
This does not log event or epoll fds
|
|
@ -0,0 +1,60 @@
|
|||
// compile with: g++ -rdynamic -c -std=c++11 -o caller.o getcaller.cpp
|
||||
#include <string>
|
||||
|
||||
#include <execinfo.h>
|
||||
#define BT_BUF_SIZE 10
|
||||
|
||||
#include <memory.h>
|
||||
#include <stdlib.h>
|
||||
#include <sstream>
|
||||
|
||||
static int depth = 2;
|
||||
|
||||
std::string demangle(std::string& in) {
|
||||
if(in.size() < 5) return in;
|
||||
if(in.find("_Z") > 0) return in;
|
||||
|
||||
std::ostringstream out;
|
||||
std::istringstream is(in.substr(2));
|
||||
bool first = true;
|
||||
while(is) {
|
||||
char c = is.peek();
|
||||
while(c == 'N' || c == 'K') {
|
||||
is.get();
|
||||
c = is.peek();
|
||||
}
|
||||
unsigned int len = 0;
|
||||
is >> len;
|
||||
if(len == 0)
|
||||
break;
|
||||
if(!first)
|
||||
out << "::";
|
||||
first = false;
|
||||
|
||||
char* buf = new char[len+1];
|
||||
buf[len] = '\0';
|
||||
is.read(buf, len);
|
||||
out << buf;
|
||||
delete[] buf;
|
||||
}
|
||||
return out.str();
|
||||
}
|
||||
|
||||
std::string getCaller() {
|
||||
if(depth+1 > BT_BUF_SIZE) return "UNKNOWN";
|
||||
void* buffer[BT_BUF_SIZE];
|
||||
int nptrs = backtrace(buffer, BT_BUF_SIZE);
|
||||
|
||||
char** strings = backtrace_symbols(buffer, nptrs);
|
||||
if (!strings)
|
||||
return "UNKNOWN";
|
||||
std::string out(strings[depth]);
|
||||
free(strings);
|
||||
size_t startoffset = out.rfind('(')+1;
|
||||
size_t plusoffset = out.find('+', startoffset)-1;
|
||||
if(plusoffset == std::string::npos)
|
||||
return "UNKNOWN";
|
||||
|
||||
out = out.substr(startoffset, plusoffset-startoffset);
|
||||
return demangle(out);
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
// 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;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue