diff --git a/Makefile b/Makefile index 06cb83b..6f20816 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,7 @@ CFLAGS = -Wall PROG = helloworld HPTEST = hptest USTACK = userstack +SPID = stack-pid UDIR = $(PWD)/source/uapi MDIR := $(PWD)/source @@ -18,7 +19,7 @@ OUTPUT_DIR = $(PWD)/build # obj-m := kernel/$(KMOD).o # $(KMOD)-objs := kernel/monitor_kernel.o -all: $(PROG) $(HPTEST) $(USTACK) module +all: $(PROG) $(HPTEST) $(USTACK) $(SPID) module $(PROG): $(TDIR)/helloworld.c mkdir -p $(OUTPUT_DIR) @@ -30,7 +31,11 @@ $(HPTEST): $(TDIR)/hptest.c $(USTACK): $(TDIR)/userstack.c mkdir -p $(OUTPUT_DIR) - $(CC) $(CFLAGS) -o $(OUTPUT_DIR)/$(USTACK) $(TDIR)/userstack.c + $(CC) -g $(CFLAGS) -o $(OUTPUT_DIR)/$(USTACK) $(TDIR)/userstack.c -lunwind -lunwind-x86_64 + +$(SPID): $(TDIR)/stack-pid.c + mkdir -p $(OUTPUT_DIR) + $(CC) $(CFLAGS) -o $(OUTPUT_DIR)/$(SPID) $(TDIR)/stack-pid.c -lunwind -lunwind-x86_64 -lunwind-ptrace module: make -C $(KDIR) M=$(MDIR) modules diff --git a/testcase/backtrace.c b/testcase/backtrace.c new file mode 100644 index 0000000..dc07ec2 --- /dev/null +++ b/testcase/backtrace.c @@ -0,0 +1,52 @@ + +#include +#include +#include +#include +#include + +#define MAX_STACK_FRAMES 64 +static void *stack_traces[MAX_STACK_FRAMES]; + +void print_trace() { + int stack_depth = backtrace(stack_traces, MAX_STACK_FRAMES); + Dwfl_Callbacks callbacks = { + .find_elf = dwfl_linux_proc_find_elf, + .find_debuginfo = dwfl_standard_find_debuginfo, + .debuginfo_path = NULL + }; + + Dwfl *dwfl = dwfl_begin(&callbacks); + dwfl_linux_proc_report(dwfl, getpid()); + dwfl_report_end(dwfl, NULL, NULL); + + for (int i = 0; i < stack_depth; ++i) { + const char *modname; + const char *symname; + GElf_Off offset; + Dwfl_Module *mod = dwfl_addrmodule(dwfl, (uintptr_t)stack_traces[i]); + Dwfl_Line *line = dwfl_module_getsrc(mod, (uintptr_t)stack_traces[i]); + const char *src; + int lineno, colno; + + if (line) { + src = dwfl_lineinfo(mod, line, &lineno, &colno, &modname, &symname); + printf("%s (%d) %s\n", src, lineno, symname); + } + } + + dwfl_end(dwfl); +} + +void foo() { + print_trace(); +} + +void bar() { + foo(); +} + +int main(int argc, char **argv) { + bar(); + return 0; +} \ No newline at end of file diff --git a/testcase/stack-pid.c b/testcase/stack-pid.c new file mode 100644 index 0000000..8a03d4d --- /dev/null +++ b/testcase/stack-pid.c @@ -0,0 +1,54 @@ +#include +#include +#include + +#include + +#include + +void die(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + exit(1); +} + + +int main(int argc, char **argv) +{ + if (argc != 2) + die("USAGE: unwind-pid \n"); + + unw_addr_space_t as = unw_create_addr_space(&_UPT_accessors, 0); + + pid_t pid = atoi(argv[1]); + if (ptrace(PTRACE_ATTACH, pid, 0, 0) != 0) + die("ERROR: cannot attach to %d\n", pid); + + void *context = _UPT_create(pid); + unw_cursor_t cursor; + if (unw_init_remote(&cursor, as, context) != 0) + die("ERROR: cannot initialize cursor for remote unwinding\n"); + + do { + unw_word_t offset, pc; + char sym[4096]; + if (unw_get_reg(&cursor, UNW_REG_IP, &pc)) + die("ERROR: cannot read program counter\n"); + + printf("0x%lx: ", pc); + + if (unw_get_proc_name(&cursor, sym, sizeof(sym), &offset) == 0) + printf("(%s+0x%lx)\n", sym, offset); + else + printf("-- no symbol name found\n"); + } while (unw_step(&cursor) > 0); + + _UPT_destroy(context); + (void) ptrace(PTRACE_DETACH, pid, 0, 0); + + return 0; +} diff --git a/testcase/userstack.c b/testcase/userstack.c index ad6d4ba..591177c 100644 --- a/testcase/userstack.c +++ b/testcase/userstack.c @@ -1,15 +1,46 @@ #include +#include #include void customFunction1(int n); void customFunction2(int n); void customFunction3(int n); +// Call this function to get a backtrace. +void backtrace() { + unw_cursor_t cursor; + unw_context_t context; + + // Initialize cursor to current frame for local unwinding. + unw_getcontext(&context); + unw_init_local(&cursor, &context); + + // Unwind frames one by one, going up the frame stack. + while (unw_step(&cursor) > 0) { + unw_word_t offset, pc; + unw_get_reg(&cursor, UNW_REG_IP, &pc); + if (pc == 0) { + break; + } + printf("0x%lx:", pc); + + char sym[256]; + if (unw_get_proc_name(&cursor, sym, sizeof(sym), &offset) == 0) { + printf(" (%s+0x%lx)\n", sym, offset); + } else { + printf(" -- error: unable to obtain symbol name for this frame\n"); + } + } +} + void customFunction1(int n) { if(n <= 0) { printf("End of recursion\n"); + // output backtrace + printf("pid: %d\n", getpid()); + backtrace(); while (1) { - // sleep(1); + sleep(1); } // never return, keep stack return; } else {