From d88401cca9ff7640387a0d88d75de1e7d8fff294 Mon Sep 17 00:00:00 2001 From: "mark@chromium.org" Date: Wed, 15 Apr 2015 19:28:11 +0000 Subject: [PATCH] MIPS64: Initial MIPS64 related change. With this change Breakpad can be compiled for MIPS64, but it is not yet functional. Patch by Gordana Cmiljanovic Review URL: https://breakpad.appspot.com/6824002/ git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1446 4c0a9323-5329-0410-9bdc-e9ce6186880e --- .../linux/dump_writer_common/thread_info.cc | 2 + .../dump_writer_common/ucontext_reader.cc | 2 + .../handler/exception_handler_unittest.cc | 4 + .../linux/minidump_writer/linux_dumper.h | 6 +- .../linux/minidump_writer/minidump_writer.cc | 10 +- src/common/android/breakpad_getcontext.S | 119 ++++++++++++++++-- src/common/android/include/link.h | 3 +- src/common/android/testing/include/wchar.h | 4 + src/common/android/ucontext_constants.h | 8 ++ src/common/linux/memory_mapped_file.cc | 9 +- src/common/memory.h | 3 +- src/third_party/curl/curl.h | 2 +- src/third_party/curl/curlbuild.h | 2 +- src/tools/linux/md2core/minidump-2-core.cc | 2 + 14 files changed, 156 insertions(+), 20 deletions(-) diff --git a/src/client/linux/dump_writer_common/thread_info.cc b/src/client/linux/dump_writer_common/thread_info.cc index 9fe253c6..a3072b6c 100644 --- a/src/client/linux/dump_writer_common/thread_info.cc +++ b/src/client/linux/dump_writer_common/thread_info.cc @@ -257,7 +257,9 @@ void ThreadInfo::FillCPUContext(RawContextCPU* out) const { out->float_save.regs[i] = fpregs.regs[i]; out->float_save.fpcsr = fpregs.fpcsr; +#if _MIPS_SIM == _ABIO32 out->float_save.fir = fpregs.fir; +#endif } #endif diff --git a/src/client/linux/dump_writer_common/ucontext_reader.cc b/src/client/linux/dump_writer_common/ucontext_reader.cc index b20a68bf..d37fdeb0 100644 --- a/src/client/linux/dump_writer_common/ucontext_reader.cc +++ b/src/client/linux/dump_writer_common/ucontext_reader.cc @@ -244,7 +244,9 @@ void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext *uc) { out->float_save.regs[i] = uc->uc_mcontext.fpregs.fp_r.fp_dregs[i]; out->float_save.fpcsr = uc->uc_mcontext.fpc_csr; +#if _MIPS_SIM == _ABIO32 out->float_save.fir = uc->uc_mcontext.fpc_eir; // Unused. +#endif } #endif diff --git a/src/client/linux/handler/exception_handler_unittest.cc b/src/client/linux/handler/exception_handler_unittest.cc index 6deea55b..289c9cd1 100644 --- a/src/client/linux/handler/exception_handler_unittest.cc +++ b/src/client/linux/handler/exception_handler_unittest.cc @@ -80,7 +80,11 @@ void FlushInstructionCache(const char* memory, uint32_t memory_size) { // Provided by Android's long begin = reinterpret_cast(memory); long end = begin + static_cast(memory_size); +#if _MIPS_SIM == _ABIO32 cacheflush(begin, end, 0); +#else + syscall(__NR_cacheflush, begin, end, ICACHE); +#endif # elif defined(__linux__) // See http://www.linux-mips.org/wiki/Cacheflush_Syscall. cacheflush(const_cast(memory), memory_size, ICACHE); diff --git a/src/client/linux/minidump_writer/linux_dumper.h b/src/client/linux/minidump_writer/linux_dumper.h index 2fc88486..87dfadb4 100644 --- a/src/client/linux/minidump_writer/linux_dumper.h +++ b/src/client/linux/minidump_writer/linux_dumper.h @@ -52,9 +52,11 @@ namespace google_breakpad { // Typedef for our parsing of the auxv variables in /proc/pid/auxv. -#if defined(__i386) || defined(__ARM_EABI__) || defined(__mips__) +#if defined(__i386) || defined(__ARM_EABI__) || \ + (defined(__mips__) && _MIPS_SIM == _ABIO32) typedef Elf32_auxv_t elf_aux_entry; -#elif defined(__x86_64) || defined(__aarch64__) +#elif defined(__x86_64) || defined(__aarch64__) || \ + (defined(__mips__) && _MIPS_SIM != _ABIO32) typedef Elf64_auxv_t elf_aux_entry; #endif diff --git a/src/client/linux/minidump_writer/minidump_writer.cc b/src/client/linux/minidump_writer/minidump_writer.cc index edc7e47d..0414bb72 100644 --- a/src/client/linux/minidump_writer/minidump_writer.cc +++ b/src/client/linux/minidump_writer/minidump_writer.cc @@ -689,10 +689,18 @@ class MinidumpWriter { return false; } +#ifdef __mips__ + if (dyn.d_tag == DT_MIPS_RLD_MAP) { + r_debug = reinterpret_cast(dyn.d_un.d_ptr); + continue; + } +#else if (dyn.d_tag == DT_DEBUG) { r_debug = reinterpret_cast(dyn.d_un.d_ptr); continue; - } else if (dyn.d_tag == DT_NULL) { + } +#endif + else if (dyn.d_tag == DT_NULL) { break; } } diff --git a/src/common/android/breakpad_getcontext.S b/src/common/android/breakpad_getcontext.S index 79fe88df..fd6326ad 100644 --- a/src/common/android/breakpad_getcontext.S +++ b/src/common/android/breakpad_getcontext.S @@ -229,14 +229,27 @@ breakpad_getcontext: #elif defined(__mips__) -#if _MIPS_SIM != _ABIO32 -#error "Unsupported mips ISA. Only mips o32 is supported." -#endif - // This implementation is inspired by implementation of getcontext in glibc. +#if _MIPS_SIM == _ABIO32 #include #include #include +#else +#include +#include +#endif + +// from asm/asm.h +#if _MIPS_SIM == _ABIO32 +#define ALSZ 7 +#define ALMASK ~7 +#define SZREG 4 +#else // _MIPS_SIM != _ABIO32 +#define ALSZ 15 +#define ALMASK ~15 +#define SZREG 8 +#endif + #include // for __NR_rt_sigprocmask #define _NSIG8 128 / 8 @@ -244,12 +257,14 @@ breakpad_getcontext: .text -LOCALS_NUM = 2 // save gp and ra on stack +LOCALS_NUM = 1 // save gp on stack FRAME_SIZE = ((LOCALS_NUM * SZREG) + ALSZ) & ALMASK -RA_FRAME_OFFSET = FRAME_SIZE - (1 * SZREG) -GP_FRAME_OFFSET = FRAME_SIZE - (2 * SZREG) + +GP_FRAME_OFFSET = FRAME_SIZE - (1 * SZREG) MCONTEXT_REG_SIZE = 8 +#if _MIPS_SIM == _ABIO32 + NESTED (breakpad_getcontext, FRAME_SIZE, ra) .mask 0x00000000, 0 .fmask 0x00000000, 0 @@ -262,8 +277,7 @@ NESTED (breakpad_getcontext, FRAME_SIZE, ra) #define _SP a2 addiu sp, -FRAME_SIZE - sw ra, RA_FRAME_OFFSET(sp) - sw gp, GP_FRAME_OFFSET(sp) + .cprestore GP_FRAME_OFFSET sw s0, (16 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0) sw s1, (17 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0) @@ -298,12 +312,95 @@ NESTED (breakpad_getcontext, FRAME_SIZE, ra) li v0, __NR_rt_sigprocmask syscall - lw ra, RA_FRAME_OFFSET(sp) - lw gp, GP_FRAME_OFFSET(sp) addiu sp, FRAME_SIZE jr ra END (breakpad_getcontext) +#else + +#ifndef NESTED +/* + * NESTED - declare nested routine entry point + */ +#define NESTED(symbol, framesize, rpc) \ + .globl symbol; \ + .align 2; \ + .type symbol,@function; \ + .ent symbol,0; \ +symbol: .frame sp, framesize, rpc; +#endif + +/* + * END - mark end of function + */ +#ifndef END +# define END(function) \ + .end function; \ + .size function,.-function +#endif + +/* int getcontext (ucontext_t *ucp) */ + +NESTED (breakpad_getcontext, FRAME_SIZE, ra) + .mask 0x10000000, 0 + .fmask 0x00000000, 0 + + move a2, sp +#define _SP a2 + move a3, gp +#define _GP a3 + + daddiu sp, -FRAME_SIZE + .cpsetup $25, GP_FRAME_OFFSET, breakpad_getcontext + + /* Store a magic flag. */ + li v1, 1 + sd v1, (0 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0) /* zero */ + + sd s0, (16 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0) + sd s1, (17 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0) + sd s2, (18 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0) + sd s3, (19 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0) + sd s4, (20 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0) + sd s5, (21 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0) + sd s6, (22 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0) + sd s7, (23 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0) + sd _GP, (28 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0) + sd _SP, (29 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0) + sd s8, (30 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0) + sd ra, (31 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0) + sd ra, MCONTEXT_PC_OFFSET(a0) + +#ifdef __mips_hard_float + s.d $f24, (24 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0) + s.d $f25, (25 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0) + s.d $f26, (26 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0) + s.d $f27, (27 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0) + s.d $f28, (28 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0) + s.d $f29, (29 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0) + s.d $f30, (30 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0) + s.d $f31, (31 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0) + + cfc1 v1, $31 + sw v1, MCONTEXT_FPC_CSR(a0) +#endif /* __mips_hard_float */ + +/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */ + li a3, _NSIG8 + daddu a2, a0, UCONTEXT_SIGMASK_OFFSET + move a1, zero + li a0, SIG_BLOCK + + li v0, __NR_rt_sigprocmask + syscall + + .cpreturn + daddiu sp, FRAME_SIZE + move v0, zero + jr ra + +END (breakpad_getcontext) +#endif // _MIPS_SIM == _ABIO32 #elif defined(__x86_64__) /* The x64 implementation of breakpad_getcontext was derived in part diff --git a/src/common/android/include/link.h b/src/common/android/include/link.h index 0f5010c0..e7ff8e2d 100644 --- a/src/common/android/include/link.h +++ b/src/common/android/include/link.h @@ -36,7 +36,8 @@ // TODO(rmcilroy): Remove this file once the ndk is updated for other // architectures - crbug.com/358831 -#if !defined(__aarch64__) && !defined(__x86_64__) +#if !defined(__aarch64__) && !defined(__x86_64__) && \ + !(defined(__mips__) && _MIPS_SIM == _ABI64) #ifdef __cplusplus extern "C" { diff --git a/src/common/android/testing/include/wchar.h b/src/common/android/testing/include/wchar.h index 9649cab6..85373fd2 100644 --- a/src/common/android/testing/include/wchar.h +++ b/src/common/android/testing/include/wchar.h @@ -38,6 +38,9 @@ #include_next +#if !defined(__aarch64__) && !defined(__x86_64__) && \ + !(defined(__mips__) && _MIPS_SIM == _ABI64) + // This needs to be in an extern "C" namespace, or Googletest will not // compile against it. #ifdef __cplusplus @@ -68,5 +71,6 @@ static int inline wcscasecmp(const wchar_t* s1, const wchar_t* s2) { #ifdef __cplusplus } // extern "C" #endif // __cplusplus +#endif #endif // GOOGLEBREAKPAD_COMMON_ANDROID_INCLUDE_WCHAR_H diff --git a/src/common/android/ucontext_constants.h b/src/common/android/ucontext_constants.h index e39f0234..1932d573 100644 --- a/src/common/android/ucontext_constants.h +++ b/src/common/android/ucontext_constants.h @@ -97,11 +97,19 @@ #elif defined(__mips__) +#if _MIPS_SIM == _ABIO32 #define MCONTEXT_PC_OFFSET 32 #define MCONTEXT_GREGS_OFFSET 40 #define MCONTEXT_FPREGS_OFFSET 296 #define MCONTEXT_FPC_CSR 556 #define UCONTEXT_SIGMASK_OFFSET 616 +#else +#define MCONTEXT_GREGS_OFFSET 40 +#define MCONTEXT_FPREGS_OFFSET 296 +#define MCONTEXT_PC_OFFSET 616 +#define MCONTEXT_FPC_CSR 624 +#define UCONTEXT_SIGMASK_OFFSET 640 +#endif #elif defined(__x86_64__) diff --git a/src/common/linux/memory_mapped_file.cc b/src/common/linux/memory_mapped_file.cc index 064326bb..592b66c8 100644 --- a/src/common/linux/memory_mapped_file.cc +++ b/src/common/linux/memory_mapped_file.cc @@ -54,6 +54,8 @@ MemoryMappedFile::~MemoryMappedFile() { Unmap(); } +#include + bool MemoryMappedFile::Map(const char* path, size_t offset) { Unmap(); @@ -62,7 +64,9 @@ bool MemoryMappedFile::Map(const char* path, size_t offset) { return false; } -#if defined(__x86_64__) || defined(__aarch64__) +#if defined(__x86_64__) || defined(__aarch64__) || \ + (defined(__mips__) && _MIPS_SIM == _ABI64) + struct kernel_stat st; if (sys_fstat(fd, &st) == -1 || st.st_size < 0) { #else @@ -83,7 +87,8 @@ bool MemoryMappedFile::Map(const char* path, size_t offset) { return true; } -#if defined(__x86_64__) || defined(__aarch64__) +#if defined(__x86_64__) || defined(__aarch64__) || \ + (defined(__mips__) && _MIPS_SIM == _ABI64) void* data = sys_mmap(NULL, file_len, PROT_READ, MAP_PRIVATE, fd, offset); #else if ((offset & 4095) != 0) { diff --git a/src/common/memory.h b/src/common/memory.h index 03228f07..d6aa137d 100644 --- a/src/common/memory.h +++ b/src/common/memory.h @@ -114,7 +114,8 @@ class PageAllocator { private: uint8_t *GetNPages(size_t num_pages) { -#if defined(__x86_64__) || defined(__aarch64__) +#if defined(__x86_64__) || defined(__aarch64__) || defined(__aarch64__) || \ + ((defined(__mips__) && _MIPS_SIM == _ABI64)) void *a = sys_mmap(NULL, page_size_ * num_pages, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); #else diff --git a/src/third_party/curl/curl.h b/src/third_party/curl/curl.h index 160cd98a..0d80936f 100644 --- a/src/third_party/curl/curl.h +++ b/src/third_party/curl/curl.h @@ -74,7 +74,7 @@ require it! */ #if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \ defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \ - defined(ANDROID) + defined(__ANDROID__) #include #endif diff --git a/src/third_party/curl/curlbuild.h b/src/third_party/curl/curlbuild.h index 87d0c7bb..b0a53e6c 100644 --- a/src/third_party/curl/curlbuild.h +++ b/src/third_party/curl/curlbuild.h @@ -155,7 +155,7 @@ /* The size of `long', as computed by sizeof. */ #if defined(_M_X64) || (defined(__x86_64__) && !defined(__ILP32__)) || \ - defined(__aarch64__) + defined(__aarch64__) || (defined(__mips__) && _MIPS_SIM == _ABI64) #define CURL_SIZEOF_LONG 8 #else #define CURL_SIZEOF_LONG 4 diff --git a/src/tools/linux/md2core/minidump-2-core.cc b/src/tools/linux/md2core/minidump-2-core.cc index 82007604..bcb0076e 100644 --- a/src/tools/linux/md2core/minidump-2-core.cc +++ b/src/tools/linux/md2core/minidump-2-core.cc @@ -384,7 +384,9 @@ ParseThreadRegisters(CrashedProcess::Thread* thread, thread->fpregs.regs[i] = rawregs->float_save.regs[i]; thread->fpregs.fpcsr = rawregs->float_save.fpcsr; +#if _MIPS_SIM == _ABIO32 thread->fpregs.fir = rawregs->float_save.fir; +#endif } #else #error "This code has not been ported to your platform yet"