Use new unwinder for offline in libbacktrace.

libbbacktrace changes:
- Completely rewrite the BacktraceOffline class to use the new unwinder.
- Modify the test data to save ucontext_t data instead of unw_context data.
- Convert the previous tests from unw_context data to ucontext_t data.

Bug: 65682279

Test: New unit tests pass in libunwindstack.
Test: All offline tests continue to pass.
Change-Id: I540345c304b20199d46deeb0349a0638a0f3ab2f
diff --git a/libbacktrace/UnwindStack.cpp b/libbacktrace/UnwindStack.cpp
index c5d498c..158467e 100644
--- a/libbacktrace/UnwindStack.cpp
+++ b/libbacktrace/UnwindStack.cpp
@@ -18,7 +18,6 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
-#include <ucontext.h>
 
 #include <memory>
 #include <set>
@@ -103,7 +102,7 @@
 
 bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map,
                        std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames,
-                       std::vector<std::string>* skip_names) {
+                       std::vector<std::string>* skip_names, BacktraceUnwindError* error) {
   UnwindStackMap* stack_map = reinterpret_cast<UnwindStackMap*>(back_map);
   auto process_memory = stack_map->process_memory();
   unwindstack::Unwinder unwinder(MAX_BACKTRACE_FRAMES + num_ignore_frames, stack_map->stack_maps(),
@@ -112,6 +111,38 @@
     unwinder.SetJitDebug(stack_map->GetJitDebug(), regs->Arch());
   }
   unwinder.Unwind(skip_names, &stack_map->GetSuffixesToIgnore());
+  if (error != nullptr) {
+    switch (unwinder.LastErrorCode()) {
+      case unwindstack::ERROR_NONE:
+        error->error_code = BACKTRACE_UNWIND_NO_ERROR;
+        break;
+
+      case unwindstack::ERROR_MEMORY_INVALID:
+        error->error_code = BACKTRACE_UNWIND_ERROR_ACCESS_MEM_FAILED;
+        error->error_info.addr = unwinder.LastErrorAddress();
+        break;
+
+      case unwindstack::ERROR_UNWIND_INFO:
+        error->error_code = BACKTRACE_UNWIND_ERROR_UNWIND_INFO;
+        break;
+
+      case unwindstack::ERROR_UNSUPPORTED:
+        error->error_code = BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION;
+        break;
+
+      case unwindstack::ERROR_INVALID_MAP:
+        error->error_code = BACKTRACE_UNWIND_ERROR_MAP_MISSING;
+        break;
+
+      case unwindstack::ERROR_MAX_FRAMES_EXCEEDED:
+        error->error_code = BACKTRACE_UNWIND_ERROR_EXCEED_MAX_FRAMES_LIMIT;
+        break;
+
+      case unwindstack::ERROR_REPEATED_FRAME:
+        error->error_code = BACKTRACE_UNWIND_ERROR_REPEATED_FRAME;
+        break;
+    }
+  }
 
   if (num_ignore_frames >= unwinder.NumFrames()) {
     frames->resize(0);
@@ -178,7 +209,7 @@
   return GetMap()->GetFunctionName(pc, offset);
 }
 
-bool UnwindStackCurrent::UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucontext) {
+bool UnwindStackCurrent::UnwindFromContext(size_t num_ignore_frames, void* ucontext) {
   std::unique_ptr<unwindstack::Regs> regs;
   if (ucontext == nullptr) {
     regs.reset(unwindstack::Regs::CreateFromLocal());
@@ -189,9 +220,8 @@
     regs.reset(unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(), ucontext));
   }
 
-  error_.error_code = BACKTRACE_UNWIND_NO_ERROR;
   std::vector<std::string> skip_names{"libunwindstack.so", "libbacktrace.so"};
-  return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames, &skip_names);
+  return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames, &skip_names, &error_);
 }
 
 UnwindStackPtrace::UnwindStackPtrace(pid_t pid, pid_t tid, BacktraceMap* map)
@@ -201,7 +231,7 @@
   return GetMap()->GetFunctionName(pc, offset);
 }
 
-bool UnwindStackPtrace::Unwind(size_t num_ignore_frames, ucontext_t* context) {
+bool UnwindStackPtrace::Unwind(size_t num_ignore_frames, void* context) {
   std::unique_ptr<unwindstack::Regs> regs;
   if (context == nullptr) {
     regs.reset(unwindstack::Regs::RemoteGet(Tid()));
@@ -209,10 +239,77 @@
     regs.reset(unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(), context));
   }
 
-  error_.error_code = BACKTRACE_UNWIND_NO_ERROR;
-  return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames, nullptr);
+  return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames, nullptr, &error_);
 }
 
 size_t UnwindStackPtrace::Read(uint64_t addr, uint8_t* buffer, size_t bytes) {
   return memory_.Read(addr, buffer, bytes);
 }
+
+UnwindStackOffline::UnwindStackOffline(ArchEnum arch, pid_t pid, pid_t tid, BacktraceMap* map,
+                                       bool map_shared)
+    : Backtrace(pid, tid, map), arch_(arch) {
+  map_shared_ = map_shared;
+}
+
+bool UnwindStackOffline::Unwind(size_t num_ignore_frames, void* ucontext) {
+  if (ucontext == nullptr) {
+    return false;
+  }
+
+  unwindstack::ArchEnum arch;
+  switch (arch_) {
+    case ARCH_ARM:
+      arch = unwindstack::ARCH_ARM;
+      break;
+    case ARCH_ARM64:
+      arch = unwindstack::ARCH_ARM64;
+      break;
+    case ARCH_X86:
+      arch = unwindstack::ARCH_X86;
+      break;
+    case ARCH_X86_64:
+      arch = unwindstack::ARCH_X86_64;
+      break;
+    default:
+      return false;
+  }
+
+  std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::CreateFromUcontext(arch, ucontext));
+
+  return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames, nullptr, &error_);
+}
+
+std::string UnwindStackOffline::GetFunctionNameRaw(uint64_t, uint64_t*) {
+  return "";
+}
+
+size_t UnwindStackOffline::Read(uint64_t, uint8_t*, size_t) {
+  return 0;
+}
+
+bool UnwindStackOffline::ReadWord(uint64_t, word_t*) {
+  return false;
+}
+
+Backtrace* Backtrace::CreateOffline(ArchEnum arch, pid_t pid, pid_t tid,
+                                    const std::vector<backtrace_map_t>& maps,
+                                    const backtrace_stackinfo_t& stack) {
+  BacktraceMap* map = BacktraceMap::CreateOffline(pid, maps, stack);
+  if (map == nullptr) {
+    return nullptr;
+  }
+
+  return new UnwindStackOffline(arch, pid, tid, map, false);
+}
+
+Backtrace* Backtrace::CreateOffline(ArchEnum arch, pid_t pid, pid_t tid, BacktraceMap* map) {
+  if (map == nullptr) {
+    return nullptr;
+  }
+  return new UnwindStackOffline(arch, pid, tid, map, true);
+}
+
+void Backtrace::SetGlobalElfCache(bool enable) {
+  unwindstack::Elf::SetCachingEnabled(enable);
+}