Merge "Add arch member into Unwinder object."
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index c52c6f7..5280121 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -597,8 +597,8 @@
   }
 
   // TODO: Use seccomp to lock ourselves down.
-  unwindstack::UnwinderFromPid unwinder(256, vm_pid);
-  if (!unwinder.Init(unwindstack::Regs::CurrentArch())) {
+  unwindstack::UnwinderFromPid unwinder(256, vm_pid, unwindstack::Regs::CurrentArch());
+  if (!unwinder.Init()) {
     LOG(FATAL) << "Failed to init unwinder object.";
   }
 
diff --git a/debuggerd/handler/debuggerd_fallback.cpp b/debuggerd/handler/debuggerd_fallback.cpp
index 9bcbdb3..abcb2c4 100644
--- a/debuggerd/handler/debuggerd_fallback.cpp
+++ b/debuggerd/handler/debuggerd_fallback.cpp
@@ -82,16 +82,12 @@
     thread.pid = getpid();
     thread.tid = gettid();
     thread.thread_name = get_thread_name(gettid());
-    unwindstack::ArchEnum arch = unwindstack::Regs::CurrentArch();
-    thread.registers.reset(unwindstack::Regs::CreateFromUcontext(arch, ucontext));
+    thread.registers.reset(
+        unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(), ucontext));
 
     // TODO: Create this once and store it in a global?
     unwindstack::UnwinderFromPid unwinder(kMaxFrames, getpid());
-    if (unwinder.Init(arch)) {
-      dump_backtrace_thread(output_fd, &unwinder, thread);
-    } else {
-      async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Unable to init unwinder.");
-    }
+    dump_backtrace_thread(output_fd, &unwinder, thread);
   }
   __linker_disable_fallback_allocator();
 }
diff --git a/debuggerd/libdebuggerd/backtrace.cpp b/debuggerd/libdebuggerd/backtrace.cpp
index f5a873c..c543a83 100644
--- a/debuggerd/libdebuggerd/backtrace.cpp
+++ b/debuggerd/libdebuggerd/backtrace.cpp
@@ -18,8 +18,9 @@
 
 #include "libdebuggerd/backtrace.h"
 
-#include <errno.h>
 #include <dirent.h>
+#include <errno.h>
+#include <inttypes.h>
 #include <limits.h>
 #include <stddef.h>
 #include <stdio.h>
@@ -65,7 +66,11 @@
   unwinder->SetRegs(thread.registers.get());
   unwinder->Unwind();
   if (unwinder->NumFrames() == 0) {
-    _LOG(&log, logtype::THREAD, "Unwind failed: tid = %d", thread.tid);
+    _LOG(&log, logtype::THREAD, "Unwind failed: tid = %d\n", thread.tid);
+    if (unwinder->LastErrorCode() != unwindstack::ERROR_NONE) {
+      _LOG(&log, logtype::THREAD, "  Error code: %s\n", unwinder->LastErrorCodeString());
+      _LOG(&log, logtype::THREAD, "  Error address: 0x%" PRIx64 "\n", unwinder->LastErrorAddress());
+    }
     return;
   }
 
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index e1fe82b..d88c5a9 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -407,7 +407,11 @@
   unwinder->SetRegs(regs_copy.get());
   unwinder->Unwind();
   if (unwinder->NumFrames() == 0) {
-    _LOG(log, logtype::THREAD, "Failed to unwind");
+    _LOG(log, logtype::THREAD, "Failed to unwind\n");
+    if (unwinder->LastErrorCode() != unwindstack::ERROR_NONE) {
+      _LOG(log, logtype::THREAD, "  Error code: %s\n", unwinder->LastErrorCodeString());
+      _LOG(log, logtype::THREAD, "  Error address: 0x%" PRIx64 "\n", unwinder->LastErrorAddress());
+    }
   } else {
     _LOG(log, logtype::BACKTRACE, "\nbacktrace:\n");
     log_backtrace(log, unwinder, "    ");
@@ -578,8 +582,8 @@
       .siginfo = siginfo,
   };
 
-  unwindstack::UnwinderFromPid unwinder(kMaxFrames, pid);
-  if (!unwinder.Init(unwindstack::Regs::CurrentArch())) {
+  unwindstack::UnwinderFromPid unwinder(kMaxFrames, pid, unwindstack::Regs::CurrentArch());
+  if (!unwinder.Init()) {
     LOG(FATAL) << "Failed to init unwinder object.";
   }
 
diff --git a/libbacktrace/BacktraceCurrent.cpp b/libbacktrace/BacktraceCurrent.cpp
index 038b59e..a506575 100644
--- a/libbacktrace/BacktraceCurrent.cpp
+++ b/libbacktrace/BacktraceCurrent.cpp
@@ -37,6 +37,12 @@
 #include "ThreadEntry.h"
 
 bool BacktraceCurrent::ReadWord(uint64_t ptr, word_t* out_value) {
+#if defined(__aarch64__)
+  // Tagged pointer after Android R would lead top byte to have random values
+  // https://source.android.com/devices/tech/debug/tagged-pointers
+  ptr &= (1ULL << 56) - 1;
+#endif
+
   if (!VerifyReadWordArgs(ptr, out_value)) {
     return false;
   }
@@ -54,6 +60,12 @@
 }
 
 size_t BacktraceCurrent::Read(uint64_t addr, uint8_t* buffer, size_t bytes) {
+#if defined(__aarch64__)
+  // Tagged pointer after Android R would lead top byte to have random values
+  // https://source.android.com/devices/tech/debug/tagged-pointers
+  addr &= (1ULL << 56) - 1;
+#endif
+
   backtrace_map_t map;
   FillInMap(addr, &map);
   if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) {
diff --git a/libbacktrace/UnwindStack.cpp b/libbacktrace/UnwindStack.cpp
index 624711f..82ff21c 100644
--- a/libbacktrace/UnwindStack.cpp
+++ b/libbacktrace/UnwindStack.cpp
@@ -52,11 +52,11 @@
   unwinder.SetResolveNames(stack_map->ResolveNames());
   stack_map->SetArch(regs->Arch());
   if (stack_map->GetJitDebug() != nullptr) {
-    unwinder.SetJitDebug(stack_map->GetJitDebug(), regs->Arch());
+    unwinder.SetJitDebug(stack_map->GetJitDebug());
   }
 #if !defined(NO_LIBDEXFILE_SUPPORT)
   if (stack_map->GetDexFiles() != nullptr) {
-    unwinder.SetDexFiles(stack_map->GetDexFiles(), regs->Arch());
+    unwinder.SetDexFiles(stack_map->GetDexFiles());
   }
 #endif
   unwinder.Unwind(skip_names, &stack_map->GetSuffixesToIgnore());
@@ -180,5 +180,10 @@
 }
 
 size_t UnwindStackPtrace::Read(uint64_t addr, uint8_t* buffer, size_t bytes) {
+#if defined(__aarch64__)
+  // Tagged pointer after Android R would lead top byte to have random values
+  // https://source.android.com/devices/tech/debug/tagged-pointers
+  addr &= (1ULL << 56) - 1;
+#endif
   return memory_->Read(addr, buffer, bytes);
 }
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index 8cc780a..75a419c 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -131,7 +131,6 @@
         support_system_process: true,
     },
     defaults: ["libunwindstack_defaults"],
-
     srcs: ["DexFile.cpp"],
     cflags: ["-DDEXFILE_SUPPORT"],
     shared_libs: ["libdexfile_support"],
@@ -168,6 +167,7 @@
     defaults: ["libunwindstack_defaults"],
 
     visibility: [
+        "//external/gwp_asan",
         "//system/core/debuggerd",
         "//system/core/init",
         "//system/core/libbacktrace",
diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp
index 57806c1..bcdbde8 100644
--- a/libunwindstack/Unwinder.cpp
+++ b/libunwindstack/Unwinder.cpp
@@ -27,6 +27,7 @@
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 
+#include <unwindstack/DexFiles.h>
 #include <unwindstack/Elf.h>
 #include <unwindstack/JitDebug.h>
 #include <unwindstack/MapInfo.h>
@@ -34,7 +35,7 @@
 #include <unwindstack/Memory.h>
 #include <unwindstack/Unwinder.h>
 
-#include <unwindstack/DexFiles.h>
+#include "Check.h"
 
 // Use the demangler from libc++.
 extern "C" char* __cxa_demangle(const char*, char*, size_t*, int* status);
@@ -142,13 +143,11 @@
 
 void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip,
                       const std::vector<std::string>* map_suffixes_to_ignore) {
-  frames_.clear();
-  warnings_ = WARNING_NONE;
-  last_error_.code = ERROR_NONE;
-  last_error_.address = 0;
-  elf_from_memory_not_file_ = false;
+  CHECK(arch_ != ARCH_UNKNOWN);
+  ClearErrors();
 
-  ArchEnum arch = regs_->Arch();
+  frames_.clear();
+  elf_from_memory_not_file_ = false;
 
   bool return_address_attempt = false;
   bool adjust_pc = false;
@@ -169,7 +168,7 @@
       if (ShouldStop(map_suffixes_to_ignore, map_info->name)) {
         break;
       }
-      elf = map_info->GetElf(process_memory_, arch);
+      elf = map_info->GetElf(process_memory_, arch_);
       // If this elf is memory backed, and there is a valid file, then set
       // an indicator that we couldn't open the file.
       if (!elf_from_memory_not_file_ && map_info->memory_backed_elf && !map_info->name.empty() &&
@@ -183,7 +182,7 @@
         step_pc = rel_pc;
       }
       if (adjust_pc) {
-        pc_adjustment = GetPcAdjustment(rel_pc, elf, arch);
+        pc_adjustment = GetPcAdjustment(rel_pc, elf, arch_);
       } else {
         pc_adjustment = 0;
       }
@@ -311,7 +310,7 @@
 
 std::string Unwinder::FormatFrame(const FrameData& frame) const {
   std::string data;
-  if (regs_->Is32Bit()) {
+  if (ArchIs32Bit(arch_)) {
     data += android::base::StringPrintf("  #%02zu pc %08" PRIx64, frame.num, frame.rel_pc);
   } else {
     data += android::base::StringPrintf("  #%02zu pc %016" PRIx64, frame.num, frame.rel_pc);
@@ -362,23 +361,33 @@
   return FormatFrame(frames_[frame_num]);
 }
 
-void Unwinder::SetJitDebug(JitDebug* jit_debug, ArchEnum arch) {
-  jit_debug->SetArch(arch);
+void Unwinder::SetJitDebug(JitDebug* jit_debug) {
+  CHECK(arch_ != ARCH_UNKNOWN);
+  jit_debug->SetArch(arch_);
   jit_debug_ = jit_debug;
 }
 
-void Unwinder::SetDexFiles(DexFiles* dex_files, ArchEnum arch) {
-  dex_files->SetArch(arch);
+void Unwinder::SetDexFiles(DexFiles* dex_files) {
+  CHECK(arch_ != ARCH_UNKNOWN);
+  dex_files->SetArch(arch_);
   dex_files_ = dex_files;
 }
 
-bool UnwinderFromPid::Init(ArchEnum arch) {
+bool UnwinderFromPid::Init() {
+  CHECK(arch_ != ARCH_UNKNOWN);
+  if (initted_) {
+    return true;
+  }
+  initted_ = true;
+
   if (pid_ == getpid()) {
     maps_ptr_.reset(new LocalMaps());
   } else {
     maps_ptr_.reset(new RemoteMaps(pid_));
   }
   if (!maps_ptr_->Parse()) {
+    ClearErrors();
+    last_error_.code = ERROR_INVALID_MAP;
     return false;
   }
   maps_ = maps_ptr_.get();
@@ -387,16 +396,24 @@
 
   jit_debug_ptr_.reset(new JitDebug(process_memory_));
   jit_debug_ = jit_debug_ptr_.get();
-  SetJitDebug(jit_debug_, arch);
+  SetJitDebug(jit_debug_);
 #if defined(DEXFILE_SUPPORT)
   dex_files_ptr_.reset(new DexFiles(process_memory_));
   dex_files_ = dex_files_ptr_.get();
-  SetDexFiles(dex_files_, arch);
+  SetDexFiles(dex_files_);
 #endif
 
   return true;
 }
 
+void UnwinderFromPid::Unwind(const std::vector<std::string>* initial_map_names_to_skip,
+                             const std::vector<std::string>* map_suffixes_to_ignore) {
+  if (!Init()) {
+    return;
+  }
+  Unwinder::Unwind(initial_map_names_to_skip, map_suffixes_to_ignore);
+}
+
 FrameData Unwinder::BuildFrameFromPcOnly(uint64_t pc, ArchEnum arch, Maps* maps,
                                          JitDebug* jit_debug,
                                          std::shared_ptr<Memory> process_memory,
@@ -449,8 +466,7 @@
 }
 
 FrameData Unwinder::BuildFrameFromPcOnly(uint64_t pc) {
-  return BuildFrameFromPcOnly(pc, regs_ ? regs_->Arch() : ARCH_UNKNOWN, maps_, jit_debug_,
-                              process_memory_, resolve_names_);
+  return BuildFrameFromPcOnly(pc, arch_, maps_, jit_debug_, process_memory_, resolve_names_);
 }
 
 }  // namespace unwindstack
diff --git a/libunwindstack/include/unwindstack/Arch.h b/libunwindstack/include/unwindstack/Arch.h
new file mode 100644
index 0000000..7060004
--- /dev/null
+++ b/libunwindstack/include/unwindstack/Arch.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#ifndef _LIBUNWINDSTACK_ARCH_H
+#define _LIBUNWINDSTACK_ARCH_H
+
+#include <stddef.h>
+
+namespace unwindstack {
+
+enum ArchEnum : uint8_t {
+  ARCH_UNKNOWN = 0,
+  ARCH_ARM,
+  ARCH_ARM64,
+  ARCH_X86,
+  ARCH_X86_64,
+  ARCH_MIPS,
+  ARCH_MIPS64,
+};
+
+static inline bool ArchIs32Bit(ArchEnum arch) {
+  switch (arch) {
+    case ARCH_ARM:
+    case ARCH_X86:
+    case ARCH_MIPS:
+      return true;
+    default:
+      return false;
+  }
+}
+
+}  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_ARCH_H
diff --git a/libunwindstack/include/unwindstack/Elf.h b/libunwindstack/include/unwindstack/Elf.h
index 472ed92..97614b1 100644
--- a/libunwindstack/include/unwindstack/Elf.h
+++ b/libunwindstack/include/unwindstack/Elf.h
@@ -25,6 +25,7 @@
 #include <unordered_map>
 #include <utility>
 
+#include <unwindstack/Arch.h>
 #include <unwindstack/ElfInterface.h>
 #include <unwindstack/Memory.h>
 
@@ -38,16 +39,6 @@
 struct MapInfo;
 class Regs;
 
-enum ArchEnum : uint8_t {
-  ARCH_UNKNOWN = 0,
-  ARCH_ARM,
-  ARCH_ARM64,
-  ARCH_X86,
-  ARCH_X86_64,
-  ARCH_MIPS,
-  ARCH_MIPS64,
-};
-
 class Elf {
  public:
   Elf(Memory* memory) : memory_(memory) {}
diff --git a/libunwindstack/include/unwindstack/Error.h b/libunwindstack/include/unwindstack/Error.h
index 66fefe7..0be4572 100644
--- a/libunwindstack/include/unwindstack/Error.h
+++ b/libunwindstack/include/unwindstack/Error.h
@@ -39,6 +39,27 @@
   ERROR_INVALID_ELF,          // Unwind in an invalid elf.
 };
 
+static inline const char* GetErrorCodeString(ErrorCode error) {
+  switch (error) {
+    case ERROR_NONE:
+      return "None";
+    case ERROR_MEMORY_INVALID:
+      return "Memory Invalid";
+    case ERROR_UNWIND_INFO:
+      return "Unwind Info";
+    case ERROR_UNSUPPORTED:
+      return "Unsupported";
+    case ERROR_INVALID_MAP:
+      return "Invalid Map";
+    case ERROR_MAX_FRAMES_EXCEEDED:
+      return "Maximum Frames Exceeded";
+    case ERROR_REPEATED_FRAME:
+      return "Repeated Frame";
+    case ERROR_INVALID_ELF:
+      return "Invalid Elf";
+  }
+}
+
 struct ErrorData {
   ErrorCode code;
   uint64_t address;  // Only valid when code is ERROR_MEMORY_INVALID.
diff --git a/libunwindstack/include/unwindstack/Regs.h b/libunwindstack/include/unwindstack/Regs.h
index 5f42565..1a2a704 100644
--- a/libunwindstack/include/unwindstack/Regs.h
+++ b/libunwindstack/include/unwindstack/Regs.h
@@ -24,11 +24,12 @@
 #include <string>
 #include <vector>
 
+#include <unwindstack/Arch.h>
+
 namespace unwindstack {
 
 // Forward declarations.
 class Elf;
-enum ArchEnum : uint8_t;
 class Memory;
 
 class Regs {
@@ -52,7 +53,7 @@
 
   virtual ArchEnum Arch() = 0;
 
-  virtual bool Is32Bit() = 0;
+  bool Is32Bit() { return ArchIs32Bit(Arch()); }
 
   virtual void* RawData() = 0;
   virtual uint64_t pc() = 0;
@@ -96,8 +97,6 @@
       : Regs(total_regs, return_loc), regs_(total_regs) {}
   virtual ~RegsImpl() = default;
 
-  bool Is32Bit() override { return sizeof(AddressType) == sizeof(uint32_t); }
-
   inline AddressType& operator[](size_t reg) { return regs_[reg]; }
 
   void* RawData() override { return regs_.data(); }
diff --git a/libunwindstack/include/unwindstack/Unwinder.h b/libunwindstack/include/unwindstack/Unwinder.h
index 3df8aad..b274c4c 100644
--- a/libunwindstack/include/unwindstack/Unwinder.h
+++ b/libunwindstack/include/unwindstack/Unwinder.h
@@ -24,6 +24,7 @@
 #include <string>
 #include <vector>
 
+#include <unwindstack/Arch.h>
 #include <unwindstack/DexFiles.h>
 #include <unwindstack/Error.h>
 #include <unwindstack/JitDebug.h>
@@ -35,7 +36,6 @@
 
 // Forward declarations.
 class Elf;
-enum ArchEnum : uint8_t;
 
 struct FrameData {
   size_t num;
@@ -64,7 +64,11 @@
 class Unwinder {
  public:
   Unwinder(size_t max_frames, Maps* maps, Regs* regs, std::shared_ptr<Memory> process_memory)
-      : max_frames_(max_frames), maps_(maps), regs_(regs), process_memory_(process_memory) {
+      : max_frames_(max_frames),
+        maps_(maps),
+        regs_(regs),
+        process_memory_(process_memory),
+        arch_(regs->Arch()) {
     frames_.reserve(max_frames);
   }
   Unwinder(size_t max_frames, Maps* maps, std::shared_ptr<Memory> process_memory)
@@ -74,8 +78,8 @@
 
   virtual ~Unwinder() = default;
 
-  void Unwind(const std::vector<std::string>* initial_map_names_to_skip = nullptr,
-              const std::vector<std::string>* map_suffixes_to_ignore = nullptr);
+  virtual void Unwind(const std::vector<std::string>* initial_map_names_to_skip = nullptr,
+                      const std::vector<std::string>* map_suffixes_to_ignore = nullptr);
 
   size_t NumFrames() const { return frames_.size(); }
 
@@ -90,9 +94,14 @@
   std::string FormatFrame(size_t frame_num) const;
   std::string FormatFrame(const FrameData& frame) const;
 
-  void SetJitDebug(JitDebug* jit_debug, ArchEnum arch);
+  void SetArch(ArchEnum arch) { arch_ = arch; };
 
-  void SetRegs(Regs* regs) { regs_ = regs; }
+  void SetJitDebug(JitDebug* jit_debug);
+
+  void SetRegs(Regs* regs) {
+    regs_ = regs;
+    arch_ = regs_ != nullptr ? regs->Arch() : ARCH_UNKNOWN;
+  }
   Maps* GetMaps() { return maps_; }
   std::shared_ptr<Memory>& GetProcessMemory() { return process_memory_; }
 
@@ -107,11 +116,12 @@
 
   void SetDisplayBuildID(bool display_build_id) { display_build_id_ = display_build_id; }
 
-  void SetDexFiles(DexFiles* dex_files, ArchEnum arch);
+  void SetDexFiles(DexFiles* dex_files);
 
   bool elf_from_memory_not_file() { return elf_from_memory_not_file_; }
 
   ErrorCode LastErrorCode() { return last_error_.code; }
+  const char* LastErrorCodeString() { return GetErrorCodeString(last_error_.code); }
   uint64_t LastErrorAddress() { return last_error_.address; }
   uint64_t warnings() { return warnings_; }
 
@@ -126,6 +136,15 @@
 
  protected:
   Unwinder(size_t max_frames) : max_frames_(max_frames) { frames_.reserve(max_frames); }
+  Unwinder(size_t max_frames, ArchEnum arch) : max_frames_(max_frames), arch_(arch) {
+    frames_.reserve(max_frames);
+  }
+
+  void ClearErrors() {
+    warnings_ = WARNING_NONE;
+    last_error_.code = ERROR_NONE;
+    last_error_.address = 0;
+  }
 
   void FillInDexFrame();
   FrameData* FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, uint64_t pc_adjustment);
@@ -145,20 +164,27 @@
   bool elf_from_memory_not_file_ = false;
   ErrorData last_error_;
   uint64_t warnings_;
+  ArchEnum arch_ = ARCH_UNKNOWN;
 };
 
 class UnwinderFromPid : public Unwinder {
  public:
   UnwinderFromPid(size_t max_frames, pid_t pid) : Unwinder(max_frames), pid_(pid) {}
+  UnwinderFromPid(size_t max_frames, pid_t pid, ArchEnum arch)
+      : Unwinder(max_frames, arch), pid_(pid) {}
   virtual ~UnwinderFromPid() = default;
 
-  bool Init(ArchEnum arch);
+  bool Init();
+
+  void Unwind(const std::vector<std::string>* initial_map_names_to_skip = nullptr,
+              const std::vector<std::string>* map_suffixes_to_ignore = nullptr) override;
 
  private:
   pid_t pid_;
   std::unique_ptr<Maps> maps_ptr_;
   std::unique_ptr<JitDebug> jit_debug_ptr_;
   std::unique_ptr<DexFiles> dex_files_ptr_;
+  bool initted_ = false;
 };
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp
index c2bd836..0c6f9f8 100644
--- a/libunwindstack/tests/UnwindOfflineTest.cpp
+++ b/libunwindstack/tests/UnwindOfflineTest.cpp
@@ -314,7 +314,7 @@
 
   JitDebug jit_debug(process_memory_);
   Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
-  unwinder.SetJitDebug(&jit_debug, regs_->Arch());
+  unwinder.SetJitDebug(&jit_debug);
   unwinder.Unwind();
 
   std::string frame_info(DumpFrames(unwinder));
@@ -616,7 +616,7 @@
 
   JitDebug jit_debug(process_memory_);
   Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
-  unwinder.SetJitDebug(&jit_debug, regs_->Arch());
+  unwinder.SetJitDebug(&jit_debug);
   unwinder.Unwind();
 
   std::string frame_info(DumpFrames(unwinder));
@@ -939,7 +939,7 @@
   std::unique_ptr<Regs> regs_copy(leak_data->regs->Clone());
   JitDebug jit_debug(leak_data->process_memory);
   Unwinder unwinder(128, leak_data->maps, regs_copy.get(), leak_data->process_memory);
-  unwinder.SetJitDebug(&jit_debug, regs_copy->Arch());
+  unwinder.SetJitDebug(&jit_debug);
   unwinder.Unwind();
   ASSERT_EQ(76U, unwinder.NumFrames());
 }
@@ -1062,7 +1062,7 @@
 
   JitDebug jit_debug(process_memory_);
   Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
-  unwinder.SetJitDebug(&jit_debug, regs_->Arch());
+  unwinder.SetJitDebug(&jit_debug);
   unwinder.Unwind();
 
   std::string frame_info(DumpFrames(unwinder));
diff --git a/libunwindstack/tests/UnwindTest.cpp b/libunwindstack/tests/UnwindTest.cpp
index f76a101..b11d213 100644
--- a/libunwindstack/tests/UnwindTest.cpp
+++ b/libunwindstack/tests/UnwindTest.cpp
@@ -170,7 +170,6 @@
     unwinder.reset(new Unwinder(512, maps.get(), regs.get(), process_memory));
   } else {
     UnwinderFromPid* unwinder_from_pid = new UnwinderFromPid(512, getpid());
-    ASSERT_TRUE(unwinder_from_pid->Init(regs->Arch()));
     unwinder_from_pid->SetRegs(regs.get());
     unwinder.reset(unwinder_from_pid);
   }
@@ -283,7 +282,6 @@
   ASSERT_TRUE(regs.get() != nullptr);
 
   UnwinderFromPid unwinder(512, pid);
-  ASSERT_TRUE(unwinder.Init(regs->Arch()));
   unwinder.SetRegs(regs.get());
 
   VerifyUnwind(&unwinder, kFunctionOrder);
@@ -335,7 +333,6 @@
   ASSERT_TRUE(regs.get() != nullptr);
 
   UnwinderFromPid unwinder(512, *pid);
-  ASSERT_TRUE(unwinder.Init(regs->Arch()));
   unwinder.SetRegs(regs.get());
 
   VerifyUnwind(&unwinder, kFunctionOrder);
diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp
index 915f248..8bae242 100644
--- a/libunwindstack/tests/UnwinderTest.cpp
+++ b/libunwindstack/tests/UnwinderTest.cpp
@@ -1182,7 +1182,7 @@
 
   DexFiles dex_files(process_memory_);
   Unwinder unwinder(64, maps_.get(), &regs_, process_memory_);
-  unwinder.SetDexFiles(&dex_files, ARCH_ARM);
+  unwinder.SetDexFiles(&dex_files);
   unwinder.Unwind();
   EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_DEX_PC_NOT_IN_MAP, unwinder.warnings());
@@ -1735,7 +1735,7 @@
   regs.FakeSetArch(ARCH_ARM);
   JitDebug jit_debug(process_memory_);
   Unwinder unwinder(10, maps_.get(), &regs, process_memory_);
-  unwinder.SetJitDebug(&jit_debug, ARCH_ARM);
+  unwinder.SetJitDebug(&jit_debug);
 
   FrameData frame = unwinder.BuildFrameFromPcOnly(0x100310);
   EXPECT_EQ(0x10030eU, frame.pc);
@@ -1751,4 +1751,21 @@
   EXPECT_EQ(0xeU, frame.function_offset);
 }
 
+TEST_F(UnwinderTest, unwinder_from_pid_init_error) {
+  UnwinderFromPid unwinder(10, getpid());
+  ASSERT_DEATH(unwinder.Init(), "");
+}
+
+TEST_F(UnwinderTest, set_jit_debug_error) {
+  Unwinder unwinder(10, maps_.get(), process_memory_);
+  JitDebug jit_debug(process_memory_);
+  ASSERT_DEATH(unwinder.SetJitDebug(&jit_debug), "");
+}
+
+TEST_F(UnwinderTest, set_dex_files_error) {
+  Unwinder unwinder(10, maps_.get(), process_memory_);
+  DexFiles dex_files(process_memory_);
+  ASSERT_DEATH(unwinder.SetDexFiles(&dex_files), "");
+}
+
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/VerifyBionicTerminationTest.cpp b/libunwindstack/tests/VerifyBionicTerminationTest.cpp
index eb2b01d..3e67dc9 100644
--- a/libunwindstack/tests/VerifyBionicTerminationTest.cpp
+++ b/libunwindstack/tests/VerifyBionicTerminationTest.cpp
@@ -94,7 +94,6 @@
   std::unique_ptr<Regs> regs(Regs::CreateFromLocal());
 
   UnwinderFromPid unwinder(512, getpid());
-  ASSERT_TRUE(unwinder.Init(regs->Arch()));
   unwinder.SetRegs(regs.get());
 
   RegsGetLocal(regs.get());
diff --git a/libunwindstack/tests/fuzz/UnwinderFuzz.cpp b/libunwindstack/tests/fuzz/UnwinderFuzz.cpp
index 2f4986a..1600547 100644
--- a/libunwindstack/tests/fuzz/UnwinderFuzz.cpp
+++ b/libunwindstack/tests/fuzz/UnwinderFuzz.cpp
@@ -85,7 +85,7 @@
 
   // Create instance
   Unwinder unwinder(max_frames, maps.get(), regs.get(), memory);
-  unwinder.SetJitDebug(jit_debug_ptr.get(), arch);
+  unwinder.SetJitDebug(jit_debug_ptr.get());
   unwinder.SetResolveNames(data_provider.ConsumeBool());
   // Call unwind
   PerformUnwind(&data_provider, &unwinder);
diff --git a/libunwindstack/tools/unwind.cpp b/libunwindstack/tools/unwind.cpp
index 1812e50..ae45f06 100644
--- a/libunwindstack/tools/unwind.cpp
+++ b/libunwindstack/tools/unwind.cpp
@@ -90,11 +90,6 @@
   printf("\n");
 
   unwindstack::UnwinderFromPid unwinder(1024, pid);
-  if (!unwinder.Init(regs->Arch())) {
-    printf("Failed to init unwinder object.\n");
-    return;
-  }
-
   unwinder.SetRegs(regs);
   unwinder.Unwind();
 
diff --git a/libunwindstack/tools/unwind_for_offline.cpp b/libunwindstack/tools/unwind_for_offline.cpp
index 64b58a8..c44a121 100644
--- a/libunwindstack/tools/unwind_for_offline.cpp
+++ b/libunwindstack/tools/unwind_for_offline.cpp
@@ -248,10 +248,6 @@
   // Do an unwind so we know how much of the stack to save, and what
   // elf files are involved.
   unwindstack::UnwinderFromPid unwinder(1024, pid);
-  if (!unwinder.Init(regs->Arch())) {
-    printf("Unable to init unwinder object.\n");
-    return 1;
-  }
   unwinder.SetRegs(regs);
   uint64_t sp = regs->sp();
   unwinder.Unwind();