Loading libcorkscrew/Android.mk +49 −8 Original line number Diff line number Diff line Loading @@ -14,9 +14,7 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := \ generic_src_files := \ backtrace.c \ backtrace-helper.c \ demangle.c \ Loading @@ -24,16 +22,24 @@ LOCAL_SRC_FILES := \ ptrace.c \ symbol_table.c ifeq ($(TARGET_ARCH),arm) LOCAL_SRC_FILES += \ arm_src_files := \ arch-arm/backtrace-arm.c \ arch-arm/ptrace-arm.c x86_src_files := \ arch-x86/backtrace-x86.c \ arch-x86/ptrace-x86.c include $(CLEAR_VARS) LOCAL_SRC_FILES := $(generic_src_files) ifeq ($(TARGET_ARCH),arm) LOCAL_SRC_FILES += $(arm_src_files) LOCAL_CFLAGS += -DCORKSCREW_HAVE_ARCH endif ifeq ($(TARGET_ARCH),x86) LOCAL_SRC_FILES += \ arch-x86/backtrace-x86.c \ arch-x86/ptrace-x86.c LOCAL_SRC_FILES += $(x86_src_files) LOCAL_CFLAGS += -DCORKSCREW_HAVE_ARCH endif Loading @@ -44,3 +50,38 @@ LOCAL_MODULE := libcorkscrew LOCAL_MODULE_TAGS := optional include $(BUILD_SHARED_LIBRARY) # Build test. include $(CLEAR_VARS) LOCAL_SRC_FILES := test.c LOCAL_CFLAGS += -std=gnu99 -Werror -fno-inline-small-functions LOCAL_SHARED_LIBRARIES := libcorkscrew LOCAL_MODULE := libcorkscrew_test LOCAL_MODULE_TAGS := optional include $(BUILD_EXECUTABLE) ifeq ($(HOST_OS)-$(HOST_ARCH),linux-x86) # Build libcorkscrew. include $(CLEAR_VARS) LOCAL_SRC_FILES += $(generic_src_files) $(x86_src_files) LOCAL_CFLAGS += -DCORKSCREW_HAVE_ARCH LOCAL_SHARED_LIBRARIES += libgccdemangle LOCAL_STATIC_LIBRARIES += libcutils LOCAL_LDLIBS += -ldl -lrt LOCAL_CFLAGS += -std=gnu99 -Werror LOCAL_MODULE := libcorkscrew LOCAL_MODULE_TAGS := optional include $(BUILD_HOST_SHARED_LIBRARY) # Build test. include $(CLEAR_VARS) LOCAL_SRC_FILES := test.c LOCAL_CFLAGS += -std=gnu99 -Werror -fno-inline-small-functions LOCAL_SHARED_LIBRARIES := libcorkscrew LOCAL_MODULE := libcorkscrew_test LOCAL_MODULE_TAGS := optional include $(BUILD_HOST_EXECUTABLE) endif # linux-x86 libcorkscrew/arch-x86/backtrace-x86.c +5 −35 Original line number Diff line number Diff line Loading @@ -31,40 +31,10 @@ #include <limits.h> #include <errno.h> #include <sys/ptrace.h> #include <sys/exec_elf.h> #include <cutils/log.h> /* Machine context at the time a signal was raised. */ typedef struct ucontext { uint32_t uc_flags; struct ucontext* uc_link; stack_t uc_stack; struct sigcontext { uint32_t gs; uint32_t fs; uint32_t es; uint32_t ds; uint32_t edi; uint32_t esi; uint32_t ebp; uint32_t esp; uint32_t ebx; uint32_t edx; uint32_t ecx; uint32_t eax; uint32_t trapno; uint32_t err; uint32_t eip; uint32_t cs; uint32_t efl; uint32_t uesp; uint32_t ss; void* fpregs; uint32_t oldmask; uint32_t cr2; } uc_mcontext; uint32_t uc_sigmask; } ucontext_t; #define __USE_GNU // For REG_EBP, REG_ESP, and REG_EIP. #include <ucontext.h> /* Unwind state. */ typedef struct { Loading Loading @@ -114,9 +84,9 @@ ssize_t unwind_backtrace_signal_arch(siginfo_t* siginfo, void* sigcontext, const ucontext_t* uc = (const ucontext_t*)sigcontext; unwind_state_t state; state.ebp = uc->uc_mcontext.ebp; state.eip = uc->uc_mcontext.eip; state.esp = uc->uc_mcontext.esp; state.ebp = uc->uc_mcontext.gregs[REG_EBP]; state.esp = uc->uc_mcontext.gregs[REG_ESP]; state.eip = uc->uc_mcontext.gregs[REG_EIP]; memory_t memory; init_memory(&memory, map_info_list); Loading libcorkscrew/backtrace.c +26 −3 Original line number Diff line number Diff line Loading @@ -27,16 +27,41 @@ #include <unistd.h> #include <signal.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include <unwind.h> #include <sys/exec_elf.h> #include <cutils/log.h> #include <cutils/atomic.h> #include <elf.h> #if HAVE_DLADDR #define __USE_GNU // For dladdr(3) in glibc. #include <dlfcn.h> #endif #if defined(__BIONIC__) // Bionic implements and exports gettid but only implements tgkill. extern int tgkill(int tgid, int tid, int sig); #else // glibc doesn't implement or export either gettid or tgkill. #include <unistd.h> #include <sys/syscall.h> static pid_t gettid() { return syscall(__NR_gettid); } static int tgkill(int tgid, int tid, int sig) { return syscall(__NR_tgkill, tgid, tid, sig); } #endif typedef struct { backtrace_frame_t* backtrace; size_t ignore_depth; Loading Loading @@ -115,8 +140,6 @@ static void unwind_backtrace_thread_signal_handler(int n, siginfo_t* siginfo, vo } #endif extern int tgkill(int tgid, int tid, int sig); ssize_t unwind_backtrace_thread(pid_t tid, backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) { if (tid == gettid()) { Loading libcorkscrew/symbol_table.c +10 −2 Original line number Diff line number Diff line Loading @@ -19,14 +19,22 @@ #include <corkscrew/symbol_table.h> #include <stdbool.h> #include <stdlib.h> #include <elf.h> #include <fcntl.h> #include <string.h> #include <sys/stat.h> #include <sys/mman.h> #include <sys/exec_elf.h> #include <cutils/log.h> static bool is_elf(Elf32_Ehdr* e) { return (e->e_ident[EI_MAG0] == ELFMAG0 && e->e_ident[EI_MAG1] == ELFMAG1 && e->e_ident[EI_MAG2] == ELFMAG2 && e->e_ident[EI_MAG3] == ELFMAG3); } // Compare function for qsort static int qcompar(const void *a, const void *b) { const symbol_t* asym = (const symbol_t*)a; Loading Loading @@ -67,7 +75,7 @@ symbol_table_t* load_symbol_table(const char *filename) { // Parse the file header Elf32_Ehdr *hdr = (Elf32_Ehdr*)base; if (!IS_ELF(*hdr)) { if (!is_elf(hdr)) { goto out_close; } Elf32_Shdr *shdr = (Elf32_Shdr*)(base + hdr->e_shoff); Loading libcorkscrew/test.c 0 → 100644 +42 −0 Original line number Diff line number Diff line #include <corkscrew/backtrace.h> #include <stdio.h> #include <stdlib.h> void do_backtrace() { const size_t MAX_DEPTH = 32; backtrace_frame_t* frames = (backtrace_frame_t*) malloc(sizeof(backtrace_frame_t) * MAX_DEPTH); ssize_t frame_count = unwind_backtrace(frames, 0, MAX_DEPTH); fprintf(stderr, "frame_count=%d\n", (int) frame_count); backtrace_symbol_t* backtrace_symbols = (backtrace_symbol_t*) malloc(sizeof(backtrace_symbol_t) * frame_count); get_backtrace_symbols(frames, frame_count, backtrace_symbols); for (size_t i = 0; i < (size_t) frame_count; ++i) { char line[MAX_BACKTRACE_LINE_LENGTH]; format_backtrace_line(i, &frames[i], &backtrace_symbols[i], line, MAX_BACKTRACE_LINE_LENGTH); fprintf(stderr, " %s\n", line); } free_backtrace_symbols(backtrace_symbols, frame_count); free(backtrace_symbols); free(frames); } __attribute__ ((noinline)) void g() { fprintf(stderr, "g()\n"); do_backtrace(); } __attribute__ ((noinline)) int f(int i) { fprintf(stderr, "f(%i)\n", i); if (i == 0) { g(); return 0; } return f(i - 1); } int main() { return f(5); } Loading
libcorkscrew/Android.mk +49 −8 Original line number Diff line number Diff line Loading @@ -14,9 +14,7 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := \ generic_src_files := \ backtrace.c \ backtrace-helper.c \ demangle.c \ Loading @@ -24,16 +22,24 @@ LOCAL_SRC_FILES := \ ptrace.c \ symbol_table.c ifeq ($(TARGET_ARCH),arm) LOCAL_SRC_FILES += \ arm_src_files := \ arch-arm/backtrace-arm.c \ arch-arm/ptrace-arm.c x86_src_files := \ arch-x86/backtrace-x86.c \ arch-x86/ptrace-x86.c include $(CLEAR_VARS) LOCAL_SRC_FILES := $(generic_src_files) ifeq ($(TARGET_ARCH),arm) LOCAL_SRC_FILES += $(arm_src_files) LOCAL_CFLAGS += -DCORKSCREW_HAVE_ARCH endif ifeq ($(TARGET_ARCH),x86) LOCAL_SRC_FILES += \ arch-x86/backtrace-x86.c \ arch-x86/ptrace-x86.c LOCAL_SRC_FILES += $(x86_src_files) LOCAL_CFLAGS += -DCORKSCREW_HAVE_ARCH endif Loading @@ -44,3 +50,38 @@ LOCAL_MODULE := libcorkscrew LOCAL_MODULE_TAGS := optional include $(BUILD_SHARED_LIBRARY) # Build test. include $(CLEAR_VARS) LOCAL_SRC_FILES := test.c LOCAL_CFLAGS += -std=gnu99 -Werror -fno-inline-small-functions LOCAL_SHARED_LIBRARIES := libcorkscrew LOCAL_MODULE := libcorkscrew_test LOCAL_MODULE_TAGS := optional include $(BUILD_EXECUTABLE) ifeq ($(HOST_OS)-$(HOST_ARCH),linux-x86) # Build libcorkscrew. include $(CLEAR_VARS) LOCAL_SRC_FILES += $(generic_src_files) $(x86_src_files) LOCAL_CFLAGS += -DCORKSCREW_HAVE_ARCH LOCAL_SHARED_LIBRARIES += libgccdemangle LOCAL_STATIC_LIBRARIES += libcutils LOCAL_LDLIBS += -ldl -lrt LOCAL_CFLAGS += -std=gnu99 -Werror LOCAL_MODULE := libcorkscrew LOCAL_MODULE_TAGS := optional include $(BUILD_HOST_SHARED_LIBRARY) # Build test. include $(CLEAR_VARS) LOCAL_SRC_FILES := test.c LOCAL_CFLAGS += -std=gnu99 -Werror -fno-inline-small-functions LOCAL_SHARED_LIBRARIES := libcorkscrew LOCAL_MODULE := libcorkscrew_test LOCAL_MODULE_TAGS := optional include $(BUILD_HOST_EXECUTABLE) endif # linux-x86
libcorkscrew/arch-x86/backtrace-x86.c +5 −35 Original line number Diff line number Diff line Loading @@ -31,40 +31,10 @@ #include <limits.h> #include <errno.h> #include <sys/ptrace.h> #include <sys/exec_elf.h> #include <cutils/log.h> /* Machine context at the time a signal was raised. */ typedef struct ucontext { uint32_t uc_flags; struct ucontext* uc_link; stack_t uc_stack; struct sigcontext { uint32_t gs; uint32_t fs; uint32_t es; uint32_t ds; uint32_t edi; uint32_t esi; uint32_t ebp; uint32_t esp; uint32_t ebx; uint32_t edx; uint32_t ecx; uint32_t eax; uint32_t trapno; uint32_t err; uint32_t eip; uint32_t cs; uint32_t efl; uint32_t uesp; uint32_t ss; void* fpregs; uint32_t oldmask; uint32_t cr2; } uc_mcontext; uint32_t uc_sigmask; } ucontext_t; #define __USE_GNU // For REG_EBP, REG_ESP, and REG_EIP. #include <ucontext.h> /* Unwind state. */ typedef struct { Loading Loading @@ -114,9 +84,9 @@ ssize_t unwind_backtrace_signal_arch(siginfo_t* siginfo, void* sigcontext, const ucontext_t* uc = (const ucontext_t*)sigcontext; unwind_state_t state; state.ebp = uc->uc_mcontext.ebp; state.eip = uc->uc_mcontext.eip; state.esp = uc->uc_mcontext.esp; state.ebp = uc->uc_mcontext.gregs[REG_EBP]; state.esp = uc->uc_mcontext.gregs[REG_ESP]; state.eip = uc->uc_mcontext.gregs[REG_EIP]; memory_t memory; init_memory(&memory, map_info_list); Loading
libcorkscrew/backtrace.c +26 −3 Original line number Diff line number Diff line Loading @@ -27,16 +27,41 @@ #include <unistd.h> #include <signal.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include <unwind.h> #include <sys/exec_elf.h> #include <cutils/log.h> #include <cutils/atomic.h> #include <elf.h> #if HAVE_DLADDR #define __USE_GNU // For dladdr(3) in glibc. #include <dlfcn.h> #endif #if defined(__BIONIC__) // Bionic implements and exports gettid but only implements tgkill. extern int tgkill(int tgid, int tid, int sig); #else // glibc doesn't implement or export either gettid or tgkill. #include <unistd.h> #include <sys/syscall.h> static pid_t gettid() { return syscall(__NR_gettid); } static int tgkill(int tgid, int tid, int sig) { return syscall(__NR_tgkill, tgid, tid, sig); } #endif typedef struct { backtrace_frame_t* backtrace; size_t ignore_depth; Loading Loading @@ -115,8 +140,6 @@ static void unwind_backtrace_thread_signal_handler(int n, siginfo_t* siginfo, vo } #endif extern int tgkill(int tgid, int tid, int sig); ssize_t unwind_backtrace_thread(pid_t tid, backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) { if (tid == gettid()) { Loading
libcorkscrew/symbol_table.c +10 −2 Original line number Diff line number Diff line Loading @@ -19,14 +19,22 @@ #include <corkscrew/symbol_table.h> #include <stdbool.h> #include <stdlib.h> #include <elf.h> #include <fcntl.h> #include <string.h> #include <sys/stat.h> #include <sys/mman.h> #include <sys/exec_elf.h> #include <cutils/log.h> static bool is_elf(Elf32_Ehdr* e) { return (e->e_ident[EI_MAG0] == ELFMAG0 && e->e_ident[EI_MAG1] == ELFMAG1 && e->e_ident[EI_MAG2] == ELFMAG2 && e->e_ident[EI_MAG3] == ELFMAG3); } // Compare function for qsort static int qcompar(const void *a, const void *b) { const symbol_t* asym = (const symbol_t*)a; Loading Loading @@ -67,7 +75,7 @@ symbol_table_t* load_symbol_table(const char *filename) { // Parse the file header Elf32_Ehdr *hdr = (Elf32_Ehdr*)base; if (!IS_ELF(*hdr)) { if (!is_elf(hdr)) { goto out_close; } Elf32_Shdr *shdr = (Elf32_Shdr*)(base + hdr->e_shoff); Loading
libcorkscrew/test.c 0 → 100644 +42 −0 Original line number Diff line number Diff line #include <corkscrew/backtrace.h> #include <stdio.h> #include <stdlib.h> void do_backtrace() { const size_t MAX_DEPTH = 32; backtrace_frame_t* frames = (backtrace_frame_t*) malloc(sizeof(backtrace_frame_t) * MAX_DEPTH); ssize_t frame_count = unwind_backtrace(frames, 0, MAX_DEPTH); fprintf(stderr, "frame_count=%d\n", (int) frame_count); backtrace_symbol_t* backtrace_symbols = (backtrace_symbol_t*) malloc(sizeof(backtrace_symbol_t) * frame_count); get_backtrace_symbols(frames, frame_count, backtrace_symbols); for (size_t i = 0; i < (size_t) frame_count; ++i) { char line[MAX_BACKTRACE_LINE_LENGTH]; format_backtrace_line(i, &frames[i], &backtrace_symbols[i], line, MAX_BACKTRACE_LINE_LENGTH); fprintf(stderr, " %s\n", line); } free_backtrace_symbols(backtrace_symbols, frame_count); free(backtrace_symbols); free(frames); } __attribute__ ((noinline)) void g() { fprintf(stderr, "g()\n"); do_backtrace(); } __attribute__ ((noinline)) int f(int i) { fprintf(stderr, "f(%i)\n", i); if (i == 0) { g(); return 0; } return f(i - 1); } int main() { return f(5); }