mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 07:42:04 +00:00
bug 595167 - Make Breakpad client libs work on Android. r=mwu a=blocking-fennec
This commit is contained in:
parent
a593182495
commit
cdd510c54b
@ -0,0 +1,4 @@
|
||||
#include <sys/exec_elf.h>
|
||||
#define ElfW(type) _ElfW (Elf, ELFSIZE, type)
|
||||
#define _ElfW(e,w,t) _ElfW_1 (e, w, _##t)
|
||||
#define _ElfW_1(e,w,t) e##w##t
|
@ -0,0 +1,46 @@
|
||||
#ifndef GOOGLE_BREAKPAD_CLIENT_LINUX_ANDROID_UCONTEXT_H_
|
||||
#define GOOGLE_BREAKPAD_CLIENT_LINUX_ANDROID_UCONTEXT_H_
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
// Adapted from platform-linux.cc in V8
|
||||
#if !defined(__GLIBC__) && (defined(__arm__) || defined(__thumb__))
|
||||
// Android runs a fairly new Linux kernel, so signal info is there,
|
||||
// but the C library doesn't have the structs defined.
|
||||
|
||||
struct sigcontext {
|
||||
uint32_t trap_no;
|
||||
uint32_t error_code;
|
||||
uint32_t oldmask;
|
||||
uint32_t arm_r0;
|
||||
uint32_t arm_r1;
|
||||
uint32_t arm_r2;
|
||||
uint32_t arm_r3;
|
||||
uint32_t arm_r4;
|
||||
uint32_t arm_r5;
|
||||
uint32_t arm_r6;
|
||||
uint32_t arm_r7;
|
||||
uint32_t arm_r8;
|
||||
uint32_t arm_r9;
|
||||
uint32_t arm_r10;
|
||||
uint32_t arm_fp;
|
||||
uint32_t arm_ip;
|
||||
uint32_t arm_sp;
|
||||
uint32_t arm_lr;
|
||||
uint32_t arm_pc;
|
||||
uint32_t arm_cpsr;
|
||||
uint32_t fault_address;
|
||||
};
|
||||
typedef uint32_t __sigset_t;
|
||||
typedef struct sigcontext mcontext_t;
|
||||
typedef struct ucontext {
|
||||
uint32_t uc_flags;
|
||||
struct ucontext* uc_link;
|
||||
stack_t uc_stack;
|
||||
mcontext_t uc_mcontext;
|
||||
__sigset_t uc_sigmask;
|
||||
} ucontext_t;
|
||||
|
||||
#endif
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_CLIENT_LINUX_ANDROID_UCONTEXT_H_
|
@ -73,12 +73,18 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/prctl.h>
|
||||
#if !defined(__ANDROID__)
|
||||
#include <sys/signal.h>
|
||||
#endif
|
||||
#include <sys/syscall.h>
|
||||
#if !defined(__ANDROID__)
|
||||
#include <sys/ucontext.h>
|
||||
#include <sys/user.h>
|
||||
#endif
|
||||
#include <sys/wait.h>
|
||||
#if !defined(__ANDROID__)
|
||||
#include <ucontext.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
|
||||
#include <algorithm>
|
||||
@ -186,7 +192,7 @@ bool ExceptionHandler::InstallHandlers() {
|
||||
stack.ss_sp = signal_stack;
|
||||
stack.ss_size = kSigStackSize;
|
||||
|
||||
if (sigaltstack(&stack, NULL) == -1)
|
||||
if (sys_sigaltstack(&stack, NULL) == -1)
|
||||
return false;
|
||||
|
||||
struct sigaction sa;
|
||||
@ -310,7 +316,7 @@ bool ExceptionHandler::HandleSignal(int sig, siginfo_t* info, void* uc) {
|
||||
return false;
|
||||
|
||||
// Allow ourselves to be dumped.
|
||||
prctl(PR_SET_DUMPABLE, 1);
|
||||
sys_prctl(PR_SET_DUMPABLE, 1);
|
||||
CrashContext context;
|
||||
memcpy(&context.siginfo, info, sizeof(siginfo_t));
|
||||
memcpy(&context.context, uc, sizeof(struct ucontext));
|
||||
|
@ -33,9 +33,11 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "client/linux/android_ucontext.h"
|
||||
#include "client/linux/crash_generation/crash_generation_client.h"
|
||||
#include "processor/scoped_ptr.h"
|
||||
|
||||
|
@ -45,7 +45,9 @@
|
||||
#include <elf.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#if !defined(__ANDROID__)
|
||||
#include <link.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ptrace.h>
|
||||
@ -117,11 +119,16 @@ inline bool IsMappedFileOpenUnsafe(
|
||||
bool GetThreadRegisters(ThreadInfo* info) {
|
||||
pid_t tid = info->tid;
|
||||
|
||||
if (sys_ptrace(PTRACE_GETREGS, tid, NULL, &info->regs) == -1 ||
|
||||
sys_ptrace(PTRACE_GETFPREGS, tid, NULL, &info->fpregs) == -1) {
|
||||
if (sys_ptrace(PTRACE_GETREGS, tid, NULL, &info->regs) == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !defined(__ANDROID__)
|
||||
if (sys_ptrace(PTRACE_GETFPREGS, tid, NULL, &info->fpregs) == -1) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__i386)
|
||||
if (sys_ptrace(PTRACE_GETFPXREGS, tid, NULL, &info->fpxregs) == -1)
|
||||
return false;
|
||||
@ -425,7 +432,7 @@ bool LinuxDumper::ThreadInfoGet(ThreadInfo* info) {
|
||||
#elif defined(__x86_64)
|
||||
memcpy(&stack_pointer, &info->regs.rsp, sizeof(info->regs.rsp));
|
||||
#elif defined(__ARM_EABI__)
|
||||
memcpy(&stack_pointer, &info->regs.uregs[R13], sizeof(info->regs.uregs[R13]));
|
||||
memcpy(&stack_pointer, &info->regs.ARM_sp, sizeof(info->regs.ARM_sp));
|
||||
#else
|
||||
#error "This code hasn't been ported to your platform yet."
|
||||
#endif
|
||||
|
@ -34,18 +34,38 @@
|
||||
#include <linux/limits.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#if !defined(__ANDROID__)
|
||||
#include <sys/user.h>
|
||||
#endif
|
||||
|
||||
#include "common/memory.h"
|
||||
#include "google_breakpad/common/minidump_format.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
#if defined(__i386) || defined(__x86_64)
|
||||
typedef typeof(((struct user*) 0)->u_debugreg[0]) debugreg_t;
|
||||
#endif
|
||||
|
||||
// Typedef for our parsing of the auxv variables in /proc/pid/auxv.
|
||||
#if defined(__i386) || defined(__ARM_EABI__)
|
||||
#if !defined(__ANDROID__)
|
||||
typedef Elf32_auxv_t elf_aux_entry;
|
||||
#else
|
||||
// Android is missing this structure definition
|
||||
typedef struct
|
||||
{
|
||||
uint32_t a_type; /* Entry type */
|
||||
union
|
||||
{
|
||||
uint32_t a_val; /* Integer value */
|
||||
} a_un;
|
||||
} elf_aux_entry;
|
||||
|
||||
#if !defined(AT_SYSINFO_EHDR)
|
||||
#define AT_SYSINFO_EHDR 33
|
||||
#endif
|
||||
#endif // __ANDROID__
|
||||
#elif defined(__x86_64__)
|
||||
typedef Elf64_auxv_t elf_aux_entry;
|
||||
#endif
|
||||
@ -77,8 +97,12 @@ struct ThreadInfo {
|
||||
|
||||
#elif defined(__ARM_EABI__)
|
||||
// Mimicking how strace does this(see syscall.c, search for GETREGS)
|
||||
#if defined(__ANDROID__)
|
||||
struct pt_regs regs;
|
||||
#else
|
||||
struct user_regs regs;
|
||||
struct user_fpregs fpregs;
|
||||
#endif // __ANDROID__
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -50,11 +50,17 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#if defined(__ANDROID__)
|
||||
#include "client/linux/android_link.h"
|
||||
#else
|
||||
#include <link.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#if !defined(__ANDROID__)
|
||||
#include <sys/ucontext.h>
|
||||
#include <sys/user.h>
|
||||
#endif
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include "client/minidump_file_writer.h"
|
||||
@ -62,6 +68,7 @@
|
||||
#include "google_breakpad/common/minidump_cpu_amd64.h"
|
||||
#include "google_breakpad/common/minidump_cpu_x86.h"
|
||||
|
||||
#include "client/linux/android_ucontext.h"
|
||||
#include "client/linux/handler/exception_handler.h"
|
||||
#include "client/linux/minidump_writer/line_reader.h"
|
||||
#include "client/linux/minidump_writer/linux_dumper.h"
|
||||
@ -337,11 +344,13 @@ static void CPUFillFromThreadInfo(MDRawContextARM *out,
|
||||
out->iregs[i] = info.regs.uregs[i];
|
||||
// No CPSR register in ThreadInfo(it's not accessible via ptrace)
|
||||
out->cpsr = 0;
|
||||
#if !defined(__ANDROID__)
|
||||
out->float_save.fpscr = info.fpregs.fpsr |
|
||||
(static_cast<u_int64_t>(info.fpregs.fpcr) << 32);
|
||||
//TODO: sort this out, actually collect floating point registers
|
||||
memset(&out->float_save.regs, 0, sizeof(out->float_save.regs));
|
||||
memset(&out->float_save.extra, 0, sizeof(out->float_save.extra));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void CPUFillFromUContext(MDRawContextARM *out, const ucontext *uc,
|
||||
@ -375,11 +384,11 @@ static void CPUFillFromUContext(MDRawContextARM *out, const ucontext *uc,
|
||||
}
|
||||
|
||||
static uintptr_t InstructionPointer(const ThreadInfo& info) {
|
||||
return info.regs.uregs[R12];
|
||||
return info.regs.ARM_ip;
|
||||
}
|
||||
|
||||
static uintptr_t StackPointer(const ThreadInfo& info) {
|
||||
return info.regs.uregs[R13];
|
||||
return info.regs.ARM_sp;
|
||||
}
|
||||
|
||||
static uintptr_t StackPointer(const ucontext* uc) {
|
||||
@ -457,7 +466,7 @@ class MinidumpWriter {
|
||||
// it to a MD_LINUX_DSO_DEBUG stream.
|
||||
struct r_debug* r_debug = NULL;
|
||||
uint32_t dynamic_length = 0;
|
||||
|
||||
#if !defined(__ANDROID__)
|
||||
for (int i = 0;;) {
|
||||
ElfW(Dyn) dyn;
|
||||
dynamic_length += sizeof(dyn);
|
||||
@ -468,6 +477,7 @@ class MinidumpWriter {
|
||||
} else if (dyn.d_tag == DT_NULL)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
// A minidump file contains a number of tagged streams. This is the number
|
||||
// of stream which we write.
|
||||
@ -949,6 +959,9 @@ class MinidumpWriter {
|
||||
|
||||
bool WriteDSODebugStream(MDRawDirectory* dirent, struct r_debug* r_debug,
|
||||
uint32_t dynamic_length) {
|
||||
#if defined(__ANDROID__)
|
||||
return false;
|
||||
#else
|
||||
// The caller provided us with a pointer to "struct r_debug". We can
|
||||
// look up the "r_map" field to get a linked list of all loaded DSOs.
|
||||
// Our list of DSOs potentially is different from the ones in the crashing
|
||||
@ -1022,6 +1035,7 @@ class MinidumpWriter {
|
||||
delete[] dso_debug_data;
|
||||
|
||||
return true;
|
||||
#endif // __ANDROID__
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -50,9 +50,12 @@ LOCAL_INCLUDES = -I$(srcdir)/../..
|
||||
CPPSRCS = \
|
||||
file_id.cc \
|
||||
guid_creator.cc \
|
||||
http_upload.cc \
|
||||
$(NULL)
|
||||
|
||||
ifneq (Android,$(OS_TARGET))
|
||||
CPPSRCS += http_upload.cc
|
||||
endif
|
||||
|
||||
HOST_CPPSRCS = \
|
||||
dump_symbols.cc \
|
||||
file_id.cc \
|
||||
|
@ -38,7 +38,11 @@
|
||||
#include <assert.h>
|
||||
#include <elf.h>
|
||||
#include <fcntl.h>
|
||||
#if defined(__ANDROID__)
|
||||
#include "client/linux/android_link.h"
|
||||
#else
|
||||
#include <link.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
@ -71,7 +75,7 @@ FileID::FileID(const char* path) {
|
||||
reinterpret_cast<const ElfW(Ehdr)*>(elf_base);
|
||||
if (my_strncmp(elf_base, ELFMAG, SELFMAG) != 0)
|
||||
return false;
|
||||
#if __ELF_NATIVE_CLASS == 32
|
||||
#if __ELF_NATIVE_CLASS == 32 || ELFSIZE == 32
|
||||
#define ELFCLASS ELFCLASS32
|
||||
#else
|
||||
#define ELFCLASS ELFCLASS64
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user