Description: Revert "Remove mips support."
 This reverts commit c0fa0c327e58eda604b2fd00b81f1c12817542d3.
Forwarded: not-needed
--- a/system/unwinding/libunwindstack/Android.bp
+++ b/system/unwinding/libunwindstack/Android.bp
@@ -80,6 +80,8 @@ libunwindstack_common_src_files = [
     "RegsX86.cpp",
     "RegsX86_64.cpp",
     "RegsRiscv64.cpp",
+    "RegsMips.cpp",
+    "RegsMips64.cpp",
     "Symbols.cpp",
     "ThreadEntry.cpp",
     "ThreadUnwinder.cpp",
--- a/system/unwinding/libunwindstack/Elf.cpp
+++ b/system/unwinding/libunwindstack/Elf.cpp
@@ -302,6 +302,9 @@ ElfInterface* Elf::CreateInterfaceFromMemory(Memory* memory) {
     } else if (e_machine == EM_386) {
       arch_ = ARCH_X86;
       interface.reset(new ElfInterface32(memory));
+    } else if (e_machine == EM_MIPS) {
+      arch_ = ARCH_MIPS;
+      interface.reset(new ElfInterface32(memory));
     } else {
       // Unsupported.
       return nullptr;
@@ -317,6 +320,8 @@ ElfInterface* Elf::CreateInterfaceFromMemory(Memory* memory) {
       arch_ = ARCH_ARM64;
     } else if (e_machine == EM_X86_64) {
       arch_ = ARCH_X86_64;
+    } else if (e_machine == EM_MIPS) {
+      arch_ = ARCH_MIPS64;
     } else if (e_machine == EM_RISCV) {
       arch_ = ARCH_RISCV64;
     } else {
--- a/system/unwinding/libunwindstack/GlobalDebugImpl.h
+++ b/system/unwinding/libunwindstack/GlobalDebugImpl.h
@@ -409,7 +409,8 @@ std::unique_ptr<GlobalDebugInterface<Symfile>> CreateGlobalDebugImpl(
       static_assert(sizeof(typename Impl::JITDescriptor) == 48, "layout");
       return std::make_unique<Impl>(arch, jit_memory, search_libs, global_variable_name);
     }
-    case ARCH_ARM: {
+    case ARCH_ARM:
+    case ARCH_MIPS: {
       using Impl = GlobalDebugImpl<Symfile, uint32_t, Uint64_A>;
       static_assert(offsetof(typename Impl::JITCodeEntry, symfile_size) == 16, "layout");
       static_assert(offsetof(typename Impl::JITCodeEntry, seqlock) == 32, "layout");
@@ -419,6 +420,7 @@ std::unique_ptr<GlobalDebugInterface<Symfile>> CreateGlobalDebugImpl(
     }
     case ARCH_ARM64:
     case ARCH_X86_64:
+    case ARCH_MIPS64:
     case ARCH_RISCV64: {
       using Impl = GlobalDebugImpl<Symfile, uint64_t, Uint64_A>;
       static_assert(offsetof(typename Impl::JITCodeEntry, symfile_size) == 24, "layout");
--- a/system/unwinding/libunwindstack/Regs.cpp
+++ b/system/unwinding/libunwindstack/Regs.cpp
@@ -211,6 +211,14 @@ uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf, ArchEnum arch) {
       }
       return 4;
     }
+  case ARCH_MIPS:
+  case ARCH_MIPS64: {
+    if (rel_pc < 8) {
+      return 0;
+    }
+    // For now, just assume no compact branches
+    return 8;
+  }
   case ARCH_X86:
   case ARCH_X86_64: {
     if (rel_pc == 0) {
--- /dev/null
+++ b/system/unwinding/libunwindstack/RegsMips.cpp
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <string.h>
+
+#include <functional>
+
+#include <unwindstack/Elf.h>
+#include <unwindstack/MachineMips.h>
+#include <unwindstack/MapInfo.h>
+#include <unwindstack/Memory.h>
+#include <unwindstack/RegsMips.h>
+#include <unwindstack/UcontextMips.h>
+#include <unwindstack/UserMips.h>
+
+namespace unwindstack {
+
+RegsMips::RegsMips()
+    : RegsImpl<uint32_t>(MIPS_REG_LAST, Location(LOCATION_REGISTER, MIPS_REG_RA)) {}
+
+ArchEnum RegsMips::Arch() {
+  return ARCH_MIPS;
+}
+
+uint64_t RegsMips::pc() {
+  return regs_[MIPS_REG_PC];
+}
+
+uint64_t RegsMips::sp() {
+  return regs_[MIPS_REG_SP];
+}
+
+void RegsMips::set_pc(uint64_t pc) {
+  regs_[MIPS_REG_PC] = static_cast<uint32_t>(pc);
+}
+
+void RegsMips::set_sp(uint64_t sp) {
+  regs_[MIPS_REG_SP] = static_cast<uint32_t>(sp);
+}
+
+bool RegsMips::SetPcFromReturnAddress(Memory*) {
+  uint32_t ra = regs_[MIPS_REG_RA];
+  if (regs_[MIPS_REG_PC] == ra) {
+    return false;
+  }
+
+  regs_[MIPS_REG_PC] = ra;
+  return true;
+}
+
+void RegsMips::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
+  fn("r0", regs_[MIPS_REG_R0]);
+  fn("r1", regs_[MIPS_REG_R1]);
+  fn("r2", regs_[MIPS_REG_R2]);
+  fn("r3", regs_[MIPS_REG_R3]);
+  fn("r4", regs_[MIPS_REG_R4]);
+  fn("r5", regs_[MIPS_REG_R5]);
+  fn("r6", regs_[MIPS_REG_R6]);
+  fn("r7", regs_[MIPS_REG_R7]);
+  fn("r8", regs_[MIPS_REG_R8]);
+  fn("r9", regs_[MIPS_REG_R9]);
+  fn("r10", regs_[MIPS_REG_R10]);
+  fn("r11", regs_[MIPS_REG_R11]);
+  fn("r12", regs_[MIPS_REG_R12]);
+  fn("r13", regs_[MIPS_REG_R13]);
+  fn("r14", regs_[MIPS_REG_R14]);
+  fn("r15", regs_[MIPS_REG_R15]);
+  fn("r16", regs_[MIPS_REG_R16]);
+  fn("r17", regs_[MIPS_REG_R17]);
+  fn("r18", regs_[MIPS_REG_R18]);
+  fn("r19", regs_[MIPS_REG_R19]);
+  fn("r20", regs_[MIPS_REG_R20]);
+  fn("r21", regs_[MIPS_REG_R21]);
+  fn("r22", regs_[MIPS_REG_R22]);
+  fn("r23", regs_[MIPS_REG_R23]);
+  fn("r24", regs_[MIPS_REG_R24]);
+  fn("r25", regs_[MIPS_REG_R25]);
+  fn("r26", regs_[MIPS_REG_R26]);
+  fn("r27", regs_[MIPS_REG_R27]);
+  fn("r28", regs_[MIPS_REG_R28]);
+  fn("sp", regs_[MIPS_REG_SP]);
+  fn("r30", regs_[MIPS_REG_R30]);
+  fn("ra", regs_[MIPS_REG_RA]);
+  fn("pc", regs_[MIPS_REG_PC]);
+}
+
+Regs* RegsMips::Read(void* remote_data) {
+  mips_user_regs* user = reinterpret_cast<mips_user_regs*>(remote_data);
+  RegsMips* regs = new RegsMips();
+  uint32_t* reg_data = reinterpret_cast<uint32_t*>(regs->RawData());
+
+  memcpy(regs->RawData(), &user->regs[MIPS32_EF_R0], (MIPS_REG_R31 + 1) * sizeof(uint32_t));
+
+  reg_data[MIPS_REG_PC] = user->regs[MIPS32_EF_CP0_EPC];
+  return regs;
+}
+
+Regs* RegsMips::CreateFromUcontext(void* ucontext) {
+  mips_ucontext_t* mips_ucontext = reinterpret_cast<mips_ucontext_t*>(ucontext);
+
+  RegsMips* regs = new RegsMips();
+  // Copy 64 bit sc_regs over to 32 bit regs
+  for (int i = 0; i < 32; i++) {
+      (*regs)[MIPS_REG_R0 + i] = mips_ucontext->uc_mcontext.sc_regs[i];
+  }
+  (*regs)[MIPS_REG_PC] = mips_ucontext->uc_mcontext.sc_pc;
+  return regs;
+}
+
+bool RegsMips::StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) {
+  uint64_t data;
+  uint64_t offset = 0;
+  Memory* elf_memory = elf->memory();
+  // Read from elf memory since it is usually more expensive to read from
+  // process memory.
+  if (!elf_memory->ReadFully(elf_offset, &data, sizeof(data))) {
+    return false;
+  }
+
+  // Look for the kernel sigreturn functions.
+  // __vdso_rt_sigreturn:
+  // 0x24021061     li  v0, 0x1061
+  // 0x0000000c     syscall
+  // __vdso_sigreturn:
+  // 0x24021017     li  v0, 0x1017
+  // 0x0000000c     syscall
+  if (data == 0x0000000c24021061ULL) {
+    // vdso_rt_sigreturn => read rt_sigframe
+    // offset = siginfo offset + sizeof(siginfo) + uc_mcontext offset + sc_pc offset
+    offset = 24 + 128 + 24 + 8;
+  } else if (data == 0x0000000c24021017LL) {
+    // vdso_sigreturn => read sigframe
+    // offset = sigcontext offset + sc_pc offset
+    offset = 24 + 8;
+  } else {
+    return false;
+  }
+
+  // read sc_pc and sc_regs[32] from stack
+  uint64_t values[MIPS_REG_LAST];
+  if (!process_memory->ReadFully(regs_[MIPS_REG_SP] + offset, values, sizeof(values))) {
+    return false;
+  }
+
+  // Copy 64 bit sc_pc over to 32 bit regs_[MIPS_REG_PC]
+  regs_[MIPS_REG_PC] = values[0];
+
+  // Copy 64 bit sc_regs over to 32 bit regs
+  for (int i = 0; i < 32; i++) {
+      regs_[MIPS_REG_R0 + i] = values[1 + i];
+  }
+  return true;
+}
+
+Regs* RegsMips::Clone() {
+  return new RegsMips(*this);
+}
+
+}  // namespace unwindstack
--- /dev/null
+++ b/system/unwinding/libunwindstack/RegsMips64.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <string.h>
+
+#include <functional>
+
+#include <unwindstack/Elf.h>
+#include <unwindstack/MachineMips64.h>
+#include <unwindstack/MapInfo.h>
+#include <unwindstack/Memory.h>
+#include <unwindstack/RegsMips64.h>
+#include <unwindstack/UcontextMips64.h>
+#include <unwindstack/UserMips64.h>
+
+namespace unwindstack {
+
+RegsMips64::RegsMips64()
+    : RegsImpl<uint64_t>(MIPS64_REG_LAST, Location(LOCATION_REGISTER, MIPS64_REG_RA)) {}
+
+ArchEnum RegsMips64::Arch() {
+  return ARCH_MIPS64;
+}
+
+uint64_t RegsMips64::pc() {
+  return regs_[MIPS64_REG_PC];
+}
+
+uint64_t RegsMips64::sp() {
+  return regs_[MIPS64_REG_SP];
+}
+
+void RegsMips64::set_pc(uint64_t pc) {
+  regs_[MIPS64_REG_PC] = pc;
+}
+
+void RegsMips64::set_sp(uint64_t sp) {
+  regs_[MIPS64_REG_SP] = sp;
+}
+
+bool RegsMips64::SetPcFromReturnAddress(Memory*) {
+  uint64_t ra = regs_[MIPS64_REG_RA];
+  if (regs_[MIPS64_REG_PC] == ra) {
+    return false;
+  }
+
+  regs_[MIPS64_REG_PC] = ra;
+  return true;
+}
+
+void RegsMips64::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
+  fn("r0", regs_[MIPS64_REG_R0]);
+  fn("r1", regs_[MIPS64_REG_R1]);
+  fn("r2", regs_[MIPS64_REG_R2]);
+  fn("r3", regs_[MIPS64_REG_R3]);
+  fn("r4", regs_[MIPS64_REG_R4]);
+  fn("r5", regs_[MIPS64_REG_R5]);
+  fn("r6", regs_[MIPS64_REG_R6]);
+  fn("r7", regs_[MIPS64_REG_R7]);
+  fn("r8", regs_[MIPS64_REG_R8]);
+  fn("r9", regs_[MIPS64_REG_R9]);
+  fn("r10", regs_[MIPS64_REG_R10]);
+  fn("r11", regs_[MIPS64_REG_R11]);
+  fn("r12", regs_[MIPS64_REG_R12]);
+  fn("r13", regs_[MIPS64_REG_R13]);
+  fn("r14", regs_[MIPS64_REG_R14]);
+  fn("r15", regs_[MIPS64_REG_R15]);
+  fn("r16", regs_[MIPS64_REG_R16]);
+  fn("r17", regs_[MIPS64_REG_R17]);
+  fn("r18", regs_[MIPS64_REG_R18]);
+  fn("r19", regs_[MIPS64_REG_R19]);
+  fn("r20", regs_[MIPS64_REG_R20]);
+  fn("r21", regs_[MIPS64_REG_R21]);
+  fn("r22", regs_[MIPS64_REG_R22]);
+  fn("r23", regs_[MIPS64_REG_R23]);
+  fn("r24", regs_[MIPS64_REG_R24]);
+  fn("r25", regs_[MIPS64_REG_R25]);
+  fn("r26", regs_[MIPS64_REG_R26]);
+  fn("r27", regs_[MIPS64_REG_R27]);
+  fn("r28", regs_[MIPS64_REG_R28]);
+  fn("sp", regs_[MIPS64_REG_SP]);
+  fn("r30", regs_[MIPS64_REG_R30]);
+  fn("ra", regs_[MIPS64_REG_RA]);
+  fn("pc", regs_[MIPS64_REG_PC]);
+}
+
+Regs* RegsMips64::Read(void* remote_data) {
+  mips64_user_regs* user = reinterpret_cast<mips64_user_regs*>(remote_data);
+  RegsMips64* regs = new RegsMips64();
+  uint64_t* reg_data = reinterpret_cast<uint64_t*>(regs->RawData());
+
+  memcpy(regs->RawData(), &user->regs[MIPS64_EF_R0], (MIPS64_REG_R31 + 1) * sizeof(uint64_t));
+
+  reg_data[MIPS64_REG_PC] = user->regs[MIPS64_EF_CP0_EPC];
+  return regs;
+}
+
+Regs* RegsMips64::CreateFromUcontext(void* ucontext) {
+  mips64_ucontext_t* mips64_ucontext = reinterpret_cast<mips64_ucontext_t*>(ucontext);
+
+  RegsMips64* regs = new RegsMips64();
+  // Copy 64 bit sc_regs over to 64 bit regs
+  memcpy(regs->RawData(), &mips64_ucontext->uc_mcontext.sc_regs[0], 32 * sizeof(uint64_t));
+  (*regs)[MIPS64_REG_PC] = mips64_ucontext->uc_mcontext.sc_pc;
+  return regs;
+}
+
+bool RegsMips64::StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) {
+  uint64_t data;
+  Memory* elf_memory = elf->memory();
+  // Read from elf memory since it is usually more expensive to read from
+  // process memory.
+  if (!elf_memory->Read(elf_offset, &data, sizeof(data))) {
+    return false;
+  }
+
+  // Look for the kernel sigreturn function.
+  // __vdso_rt_sigreturn:
+  // 0x2402145b     li  v0, 0x145b
+  // 0x0000000c     syscall
+  if (data != 0x0000000c2402145bULL) {
+    return false;
+  }
+
+  // vdso_rt_sigreturn => read rt_sigframe
+  // offset = siginfo offset + sizeof(siginfo) + uc_mcontext offset
+  // read 64 bit sc_regs[32] from stack into 64 bit regs_
+  uint64_t sp = regs_[MIPS64_REG_SP];
+  if (!process_memory->Read(sp + 24 + 128 + 40, regs_.data(),
+                            sizeof(uint64_t) * (MIPS64_REG_LAST - 1))) {
+    return false;
+  }
+
+  // offset = siginfo offset + sizeof(siginfo) + uc_mcontext offset + sc_pc offset
+  // read 64 bit sc_pc from stack into 64 bit regs_[MIPS64_REG_PC]
+  if (!process_memory->Read(sp + 24 + 128 + 40 + 576, &regs_[MIPS64_REG_PC], sizeof(uint64_t))) {
+    return false;
+  }
+  return true;
+}
+
+Regs* RegsMips64::Clone() {
+  return new RegsMips64(*this);
+}
+
+}  // namespace unwindstack
--- a/system/unwinding/libunwindstack/include/unwindstack/Arch.h
+++ b/system/unwinding/libunwindstack/include/unwindstack/Arch.h
@@ -26,6 +26,8 @@ enum ArchEnum : uint8_t {
   ARCH_ARM64,
   ARCH_X86,
   ARCH_X86_64,
+  ARCH_MIPS,
+  ARCH_MIPS64,
   ARCH_RISCV64,
 };
 
@@ -33,6 +35,7 @@ static inline bool ArchIs32Bit(ArchEnum arch) {
   switch (arch) {
     case ARCH_ARM:
     case ARCH_X86:
+    case ARCH_MIPS:
       return true;
     default:
       return false;
--- /dev/null
+++ b/system/unwinding/libunwindstack/include/unwindstack/MachineMips.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+namespace unwindstack {
+
+enum MipsReg : uint16_t {
+  MIPS_REG_R0 = 0,
+  MIPS_REG_R1,
+  MIPS_REG_R2,
+  MIPS_REG_R3,
+  MIPS_REG_R4,
+  MIPS_REG_R5,
+  MIPS_REG_R6,
+  MIPS_REG_R7,
+  MIPS_REG_R8,
+  MIPS_REG_R9,
+  MIPS_REG_R10,
+  MIPS_REG_R11,
+  MIPS_REG_R12,
+  MIPS_REG_R13,
+  MIPS_REG_R14,
+  MIPS_REG_R15,
+  MIPS_REG_R16,
+  MIPS_REG_R17,
+  MIPS_REG_R18,
+  MIPS_REG_R19,
+  MIPS_REG_R20,
+  MIPS_REG_R21,
+  MIPS_REG_R22,
+  MIPS_REG_R23,
+  MIPS_REG_R24,
+  MIPS_REG_R25,
+  MIPS_REG_R26,
+  MIPS_REG_R27,
+  MIPS_REG_R28,
+  MIPS_REG_R29,
+  MIPS_REG_R30,
+  MIPS_REG_R31,
+  MIPS_REG_PC,
+  MIPS_REG_LAST,
+
+  MIPS_REG_SP = MIPS_REG_R29,
+  MIPS_REG_RA = MIPS_REG_R31,
+};
+
+}  // namespace unwindstack
--- /dev/null
+++ b/system/unwinding/libunwindstack/include/unwindstack/MachineMips64.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+namespace unwindstack {
+
+enum Mips64Reg : uint16_t {
+  MIPS64_REG_R0 = 0,
+  MIPS64_REG_R1,
+  MIPS64_REG_R2,
+  MIPS64_REG_R3,
+  MIPS64_REG_R4,
+  MIPS64_REG_R5,
+  MIPS64_REG_R6,
+  MIPS64_REG_R7,
+  MIPS64_REG_R8,
+  MIPS64_REG_R9,
+  MIPS64_REG_R10,
+  MIPS64_REG_R11,
+  MIPS64_REG_R12,
+  MIPS64_REG_R13,
+  MIPS64_REG_R14,
+  MIPS64_REG_R15,
+  MIPS64_REG_R16,
+  MIPS64_REG_R17,
+  MIPS64_REG_R18,
+  MIPS64_REG_R19,
+  MIPS64_REG_R20,
+  MIPS64_REG_R21,
+  MIPS64_REG_R22,
+  MIPS64_REG_R23,
+  MIPS64_REG_R24,
+  MIPS64_REG_R25,
+  MIPS64_REG_R26,
+  MIPS64_REG_R27,
+  MIPS64_REG_R28,
+  MIPS64_REG_R29,
+  MIPS64_REG_R30,
+  MIPS64_REG_R31,
+  MIPS64_REG_PC,
+  MIPS64_REG_LAST,
+
+  MIPS64_REG_SP = MIPS64_REG_R29,
+  MIPS64_REG_RA = MIPS64_REG_R31,
+};
+
+}  // namespace unwindstack
--- /dev/null
+++ b/system/unwinding/libunwindstack/include/unwindstack/RegsMips.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#include <functional>
+
+#include <unwindstack/Elf.h>
+#include <unwindstack/Regs.h>
+
+namespace unwindstack {
+
+// Forward declarations.
+class Memory;
+
+class RegsMips : public RegsImpl<uint32_t> {
+ public:
+  RegsMips();
+  virtual ~RegsMips() = default;
+
+  ArchEnum Arch() override final;
+
+  bool SetPcFromReturnAddress(Memory* process_memory) override;
+
+  bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override;
+
+  void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
+
+  uint64_t pc() override;
+  uint64_t sp() override;
+
+  void set_pc(uint64_t pc) override;
+  void set_sp(uint64_t sp) override;
+
+  Regs* Clone() override final;
+
+  static Regs* Read(void* data);
+
+  static Regs* CreateFromUcontext(void* ucontext);
+};
+
+}  // namespace unwindstack
--- /dev/null
+++ b/system/unwinding/libunwindstack/include/unwindstack/RegsMips64.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#include <functional>
+
+#include <unwindstack/Elf.h>
+#include <unwindstack/Regs.h>
+
+namespace unwindstack {
+
+// Forward declarations.
+class Memory;
+
+class RegsMips64 : public RegsImpl<uint64_t> {
+ public:
+  RegsMips64();
+  virtual ~RegsMips64() = default;
+
+  ArchEnum Arch() override final;
+
+  bool SetPcFromReturnAddress(Memory* process_memory) override;
+
+  bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override;
+
+  void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
+
+  uint64_t pc() override;
+  uint64_t sp() override;
+
+  void set_pc(uint64_t pc) override;
+  void set_sp(uint64_t sp) override;
+
+  Regs* Clone() override final;
+
+  static Regs* Read(void* data);
+
+  static Regs* CreateFromUcontext(void* ucontext);
+};
+
+}  // namespace unwindstack
--- /dev/null
+++ b/system/unwinding/libunwindstack/include/unwindstack/UcontextMips.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#include <unwindstack/MachineMips.h>
+
+namespace unwindstack {
+
+struct mips_stack_t {
+  uint32_t ss_sp;    // void __user*
+  uint32_t ss_size;  // size_t
+  int32_t ss_flags;  // int
+};
+
+struct mips_mcontext_t {
+  uint32_t sc_regmask;
+  uint32_t sc_status;
+  uint64_t sc_pc;
+  uint64_t sc_regs[32];
+  // Nothing else is used, so don't define it.
+};
+
+struct mips_ucontext_t {
+  uint32_t uc_flags;  // unsigned long
+  uint32_t uc_link;   // struct ucontext*
+  mips_stack_t uc_stack;
+  mips_mcontext_t uc_mcontext;
+  // Nothing else is used, so don't define it.
+};
+
+}  // namespace unwindstack
--- /dev/null
+++ b/system/unwinding/libunwindstack/include/unwindstack/UcontextMips64.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#include <unwindstack/MachineMips64.h>
+
+namespace unwindstack {
+
+struct mips64_stack_t {
+  uint64_t ss_sp;    // void __user*
+  uint64_t ss_size;  // size_t
+  int32_t ss_flags;  // int
+};
+
+struct mips64_mcontext_t {
+  uint64_t sc_regs[32];
+  uint64_t sc_fpregs[32];
+  uint64_t sc_mdhi;
+  uint64_t sc_hi1;
+  uint64_t sc_hi2;
+  uint64_t sc_hi3;
+  uint64_t sc_mdlo;
+  uint64_t sc_lo1;
+  uint64_t sc_lo2;
+  uint64_t sc_lo3;
+  uint64_t sc_pc;
+  // Nothing else is used, so don't define it.
+};
+
+struct mips64_ucontext_t {
+  uint64_t uc_flags;  // unsigned long
+  uint64_t uc_link;   // struct ucontext*
+  mips64_stack_t uc_stack;
+  mips64_mcontext_t uc_mcontext;
+  // Nothing else is used, so don't define it.
+};
+
+}  // namespace unwindstack
--- /dev/null
+++ b/system/unwinding/libunwindstack/include/unwindstack/UserMips.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+namespace unwindstack {
+
+enum Mips32UserReg : uint16_t {
+  MIPS32_EF_R0 = 6,
+  MIPS32_EF_CP0_EPC = 40,
+};
+
+struct mips_user_regs {
+  uint32_t regs[45];
+};
+
+}  // namespace unwindstack
--- /dev/null
+++ b/system/unwinding/libunwindstack/include/unwindstack/UserMips64.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+namespace unwindstack {
+
+enum Mips64UserReg : uint16_t {
+  MIPS64_EF_R0 = 0,
+  MIPS64_EF_CP0_EPC = 34,
+};
+
+struct mips64_user_regs {
+  uint64_t regs[45];
+};
+
+}  // namespace unwindstack
--- a/system/unwinding/libunwindstack/tools/unwind.cpp
+++ b/system/unwinding/libunwindstack/tools/unwind.cpp
@@ -77,6 +77,12 @@ void DoUnwind(pid_t pid) {
     case unwindstack::ARCH_X86_64:
       printf("x86_64");
       break;
+    case unwindstack::ARCH_MIPS:
+      printf("mips");
+      break;
+    case unwindstack::ARCH_MIPS64:
+      printf("mips64");
+      break;
     case unwindstack::ARCH_RISCV64:
       printf("riscv64");
       break;
--- a/system/unwinding/libunwindstack/utils/RegsFake.h
+++ b/system/unwinding/libunwindstack/utils/RegsFake.h
@@ -50,7 +50,7 @@ class RegsFake : public Regs {
 
   bool Is32Bit() {
     CHECK(fake_arch_ != ARCH_UNKNOWN);
-    return fake_arch_ == ARCH_ARM || fake_arch_ == ARCH_X86;
+    return fake_arch_ == ARCH_ARM || fake_arch_ == ARCH_X86 || fake_arch_ == ARCH_MIPS;
   }
 
   bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; }
