Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 71363a80 authored by Elliott Hughes's avatar Elliott Hughes
Browse files

Support libcorkscrew on x86 hosts in binaries using glibc.

Change-Id: I1f2b7f21cc7f8227dbe7d294fed88cb691a24d09
parent b7fa1fc1
Loading
Loading
Loading
Loading
+49 −8
Original line number Diff line number Diff line
@@ -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 \
@@ -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

@@ -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
+5 −35
Original line number Diff line number Diff line
@@ -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 {
@@ -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);
+26 −3
Original line number Diff line number Diff line
@@ -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;
@@ -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()) {
+10 −2
Original line number Diff line number Diff line
@@ -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;
@@ -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);

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);
}