Snap for 8730993 from 1367a0bf332b096e9c303343e5d1eee99cb40936 to mainline-tzdata3-release

Change-Id: I3aa8420448c01cedabe1a39b4d9387bb7e5b9b54
diff --git a/libbacktrace/Android.bp b/libbacktrace/Android.bp
index af14cde..38645cc 100644
--- a/libbacktrace/Android.bp
+++ b/libbacktrace/Android.bp
@@ -56,6 +56,9 @@
         "//apex_available:anyapex",
     ],
     target: {
+        linux_glibc: {
+            enabled: true,
+        },
         linux_bionic: {
             enabled: true,
         },
@@ -116,19 +119,6 @@
         "//apex_available:platform",
         "//apex_available:anyapex",
     ],
-    // This library is being deprecated in favor of libunwindstack.
-    // Therefore, only allow the current set of users, and block anyone
-    // else.
-    visibility: [
-        "//art:__subpackages__",
-        "//bionic/libc/malloc_debug",
-        "//frameworks/native/opengl/libs",
-        "//packages/modules/vndk/apex",
-        "//packages/modules/Bluetooth/tools/rootcanal",
-        "//packages/modules/Bluetooth/system/gd",
-        "//system/core/init",
-        "//system/core/libutils",
-    ],
     min_sdk_version: "apex_inherit",
     vndk: {
         enabled: true,
@@ -162,7 +152,6 @@
 // Static library without DEX support to avoid dependencies on the ART APEX.
 cc_library_static {
     name: "libbacktrace_no_dex",
-    ramdisk_available: true,
     visibility: [
         "//system/core/debuggerd",
         "//system/core/init",
@@ -193,7 +182,7 @@
     ],
 
     target: {
-        host_linux: {
+        linux_glibc: {
             // This forces the creation of eh_frame with unwind information
             // for host.
             cflags: [
@@ -231,6 +220,8 @@
         "libunwindstack",
     ],
 
+    group_static_libs: true,
+
     target: {
         android: {
             // So that the dlopen can find the libbacktrace_test.so.
diff --git a/libbacktrace/BacktraceCurrent.cpp b/libbacktrace/BacktraceCurrent.cpp
index 84c7bc8..a506575 100644
--- a/libbacktrace/BacktraceCurrent.cpp
+++ b/libbacktrace/BacktraceCurrent.cpp
@@ -28,7 +28,6 @@
 
 #include <string>
 
-#include <android-base/file.h>
 #include <android-base/threads.h>
 #include <backtrace/Backtrace.h>
 #include <backtrace/BacktraceMap.h>
@@ -98,7 +97,7 @@
 
 bool BacktraceCurrent::DiscardFrame(const backtrace_frame_data_t& frame) {
   if (BacktraceMap::IsValid(frame.map)) {
-    const std::string library = android::base::Basename(frame.map.name);
+    const std::string library = basename(frame.map.name.c_str());
     if (library == "libunwind.so" || library == "libbacktrace.so") {
       return true;
     }
diff --git a/libbacktrace/UnwindStack.cpp b/libbacktrace/UnwindStack.cpp
index d2e65cb..0b3bb70 100644
--- a/libbacktrace/UnwindStack.cpp
+++ b/libbacktrace/UnwindStack.cpp
@@ -95,6 +95,10 @@
         error->error_code = BACKTRACE_UNWIND_ERROR_INVALID_ELF;
         break;
 
+      case unwindstack::ERROR_SYSTEM_CALL:
+        error->error_code = BACKTRACE_UNWIND_ERROR_INTERNAL;
+        break;
+
       case unwindstack::ERROR_THREAD_DOES_NOT_EXIST:
         error->error_code = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST;
         break;
@@ -102,13 +106,6 @@
       case unwindstack::ERROR_THREAD_TIMEOUT:
         error->error_code = BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT;
         break;
-
-      case unwindstack::ERROR_SYSTEM_CALL:
-      case unwindstack::ERROR_MAPS_PARSE:
-      case unwindstack::ERROR_BAD_ARCH:
-      case unwindstack::ERROR_INVALID_PARAMETER:
-        error->error_code = BACKTRACE_UNWIND_ERROR_INTERNAL;
-        break;
     }
   }
 
@@ -140,20 +137,12 @@
     }
     back_frame->func_offset = frame->function_offset;
 
-    if (frame->map_info != nullptr) {
-      back_frame->map.name = frame->map_info->name();
-      back_frame->map.start = frame->map_info->start();
-      back_frame->map.end = frame->map_info->end();
-      back_frame->map.offset = frame->map_info->elf_start_offset();
-      back_frame->map.load_bias = frame->map_info->load_bias();
-      back_frame->map.flags = frame->map_info->flags();
-    } else {
-      back_frame->map.start = 0;
-      back_frame->map.end = 0;
-      back_frame->map.offset = 0;
-      back_frame->map.load_bias = 0;
-      back_frame->map.flags = 0;
-    }
+    back_frame->map.name = frame->map_name;
+    back_frame->map.start = frame->map_start;
+    back_frame->map.end = frame->map_end;
+    back_frame->map.offset = frame->map_elf_start_offset;
+    back_frame->map.load_bias = frame->map_load_bias;
+    back_frame->map.flags = frame->map_flags;
   }
 
   return true;
diff --git a/libbacktrace/UnwindStackMap.cpp b/libbacktrace/UnwindStackMap.cpp
index b0508d9..7c15ed7 100644
--- a/libbacktrace/UnwindStackMap.cpp
+++ b/libbacktrace/UnwindStackMap.cpp
@@ -92,24 +92,19 @@
   }
 
   // Fill in the load_bias.
-  std::shared_ptr<unwindstack::MapInfo> map_info = stack_maps_->Find(addr);
+  unwindstack::MapInfo* map_info = stack_maps_->Find(addr);
   if (map_info == nullptr) {
     return;
   }
   map->load_bias = map_info->GetLoadBias(process_memory_);
 }
 
-std::string UnwindStackMap::GetBuildId(uint64_t addr) {
-  auto map_info = stack_maps_->Find(addr);
-  return map_info == nullptr ? std::string() : map_info->GetPrintableBuildID();
-}
-
 uint64_t UnwindStackMap::GetLoadBias(size_t index) {
   if (index >= stack_maps_->Total()) {
     return 0;
   }
 
-  std::shared_ptr<unwindstack::MapInfo> map_info = stack_maps_->Get(index);
+  unwindstack::MapInfo* map_info = stack_maps_->Get(index);
   if (map_info == nullptr) {
     return 0;
   }
@@ -121,7 +116,7 @@
   unwindstack::Maps* maps = stack_maps();
 
   // Get the map for this
-  auto map_info = maps->Find(pc);
+  unwindstack::MapInfo* map_info = maps->Find(pc);
   if (map_info == nullptr || map_info->flags() & PROT_DEVICE_MAP) {
     return "";
   }
@@ -140,7 +135,7 @@
 
   unwindstack::SharedString name;
   uint64_t func_offset;
-  if (!elf->GetFunctionName(elf->GetRelPc(pc, map_info.get()), &name, &func_offset)) {
+  if (!elf->GetFunctionName(elf->GetRelPc(pc, map_info), &name, &func_offset)) {
     return "";
   }
   *offset = func_offset;
diff --git a/libbacktrace/UnwindStackMap.h b/libbacktrace/UnwindStackMap.h
index 3c2591e..f0e7d8b 100644
--- a/libbacktrace/UnwindStackMap.h
+++ b/libbacktrace/UnwindStackMap.h
@@ -47,8 +47,6 @@
 
   void FillIn(uint64_t addr, backtrace_map_t* map) override;
 
-  std::string GetBuildId(uint64_t addr) override;
-
   virtual std::string GetFunctionName(uint64_t pc, uint64_t* offset) override;
   virtual std::shared_ptr<unwindstack::Memory> GetProcessMemory() override final;
 
diff --git a/libbacktrace/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp
index b978349..a9160d5 100644
--- a/libbacktrace/backtrace_test.cpp
+++ b/libbacktrace/backtrace_test.cpp
@@ -45,7 +45,6 @@
 #include <backtrace/Backtrace.h>
 #include <backtrace/BacktraceMap.h>
 
-#include <android-base/file.h>
 #include <android-base/macros.h>
 #include <android-base/stringprintf.h>
 #include <android-base/test_utils.h>
@@ -282,7 +281,7 @@
   // None of the frames should be in the backtrace libraries.
   for (const auto& frame : *backtrace ) {
     if (BacktraceMap::IsValid(frame.map)) {
-      const std::string name = android::base::Basename(frame.map.name);
+      const std::string name = basename(frame.map.name.c_str());
       for (const auto& lib : kBacktraceLibs) {
         ASSERT_TRUE(name != lib) << DumpFrames(backtrace.get());
       }
@@ -303,7 +302,7 @@
   size_t first_frame_non_backtrace_lib = 0;
   for (const auto& frame : *backtrace) {
     if (BacktraceMap::IsValid(frame.map)) {
-      const std::string name = android::base::Basename(frame.map.name);
+      const std::string name = basename(frame.map.name.c_str());
       bool found = false;
       for (const auto& lib : kBacktraceLibs) {
         if (name == lib) {
diff --git a/libbacktrace/include/backtrace/BacktraceMap.h b/libbacktrace/include/backtrace/BacktraceMap.h
index eab1328..e000a00 100644
--- a/libbacktrace/include/backtrace/BacktraceMap.h
+++ b/libbacktrace/include/backtrace/BacktraceMap.h
@@ -117,9 +117,6 @@
   // Fill in the map data structure for the given address.
   virtual void FillIn(uint64_t addr, backtrace_map_t* map);
 
-  // Get BuildId of ELF file at the given address, or empty string on failure.
-  virtual std::string GetBuildId(uint64_t /*pc*/) { return std::string(); }
-
   // Only supported with the new unwinder.
   virtual std::string GetFunctionName(uint64_t /*pc*/, uint64_t* /*offset*/) { return ""; }
   virtual std::shared_ptr<unwindstack::Memory> GetProcessMemory() { return nullptr; }
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index bed17e4..5443ce7 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -51,44 +51,42 @@
     },
 }
 
-libunwindstack_common_src_files = [
-    "AndroidUnwinder.cpp",
-    "ArmExidx.cpp",
-    "DexFiles.cpp",
-    "DwarfCfa.cpp",
-    "DwarfEhFrameWithHdr.cpp",
-    "DwarfMemory.cpp",
-    "DwarfOp.cpp",
-    "DwarfSection.cpp",
-    "Elf.cpp",
-    "ElfInterface.cpp",
-    "ElfInterfaceArm.cpp",
-    "Global.cpp",
-    "JitDebug.cpp",
-    "MapInfo.cpp",
-    "Maps.cpp",
-    "Memory.cpp",
-    "MemoryMte.cpp",
-    "MemoryXz.cpp",
-    "Regs.cpp",
-    "RegsArm.cpp",
-    "RegsArm64.cpp",
-    "RegsX86.cpp",
-    "RegsX86_64.cpp",
-    "RegsMips.cpp",
-    "RegsMips64.cpp",
-    "Symbols.cpp",
-    "ThreadEntry.cpp",
-    "ThreadUnwinder.cpp",
-    "Unwinder.cpp",
-]
-
 cc_defaults {
     name: "libunwindstack_defaults",
     defaults: ["libunwindstack_flags"],
     export_include_dirs: ["include"],
 
-    srcs: libunwindstack_common_src_files,
+    srcs: [
+        "ArmExidx.cpp",
+        "DexFiles.cpp",
+        "DwarfCfa.cpp",
+        "DwarfEhFrameWithHdr.cpp",
+        "DwarfMemory.cpp",
+        "DwarfOp.cpp",
+        "DwarfSection.cpp",
+        "Elf.cpp",
+        "ElfInterface.cpp",
+        "ElfInterfaceArm.cpp",
+        "Global.cpp",
+        "JitDebug.cpp",
+        "Log.cpp",
+        "MapInfo.cpp",
+        "Maps.cpp",
+        "Memory.cpp",
+        "MemoryMte.cpp",
+        "LocalUnwinder.cpp",
+        "Regs.cpp",
+        "RegsArm.cpp",
+        "RegsArm64.cpp",
+        "RegsX86.cpp",
+        "RegsX86_64.cpp",
+        "RegsMips.cpp",
+        "RegsMips64.cpp",
+        "Symbols.cpp",
+        "ThreadEntry.cpp",
+        "ThreadUnwinder.cpp",
+        "Unwinder.cpp",
+    ],
 
     cflags: [
         "-Wexit-time-destructors",
@@ -142,44 +140,35 @@
         support_system_process: true,
     },
     defaults: ["libunwindstack_defaults"],
-    srcs: [
-        "DexFile.cpp",
-        "LogAndroid.cpp",
-    ],
+    srcs: ["DexFile.cpp"],
     cflags: ["-DDEXFILE_SUPPORT"],
     static_libs: ["libdexfile_support"],
-    runtime_libs: ["libdexfile"], // libdexfile_support dependency
 
     target: {
         vendor: {
             cflags: ["-UDEXFILE_SUPPORT"],
             exclude_srcs: ["DexFile.cpp"],
             exclude_static_libs: ["libdexfile_support"],
-            exclude_runtime_libs: ["libdexfile"],
         },
         product: {
             cflags: ["-UDEXFILE_SUPPORT"],
             exclude_srcs: ["DexFile.cpp"],
             exclude_static_libs: ["libdexfile_support"],
-            exclude_runtime_libs: ["libdexfile"],
         },
         recovery: {
             cflags: ["-UDEXFILE_SUPPORT"],
             exclude_srcs: ["DexFile.cpp"],
             exclude_static_libs: ["libdexfile_support"],
-            exclude_runtime_libs: ["libdexfile"],
         },
         vendor_ramdisk: {
             cflags: ["-UDEXFILE_SUPPORT"],
             exclude_srcs: ["DexFile.cpp"],
             exclude_static_libs: ["libdexfile_support"],
-            exclude_runtime_libs: ["libdexfile"],
         },
         native_bridge: {
             cflags: ["-UDEXFILE_SUPPORT"],
             exclude_srcs: ["DexFile.cpp"],
             exclude_static_libs: ["libdexfile_support"],
-            exclude_runtime_libs: ["libdexfile"],
         },
     },
 
@@ -191,23 +180,12 @@
     min_sdk_version: "29",
 }
 
-// Make sure that the code can be compiled without Android Logging.
-cc_library {
-    name: "libunwindstack_stdout_log",
-    defaults: ["libunwindstack_defaults"],
-    srcs: [
-        "LogStdout.cpp",
-    ],
-}
-
 // Static library without DEX support to avoid dependencies on the ART APEX.
 cc_library_static {
     name: "libunwindstack_no_dex",
-    ramdisk_available: true,
     recovery_available: true,
     vendor_ramdisk_available: true,
     defaults: ["libunwindstack_defaults"],
-    srcs: ["LogAndroid.cpp"],
 
     visibility: [
         "//external/gwp_asan",
@@ -222,30 +200,6 @@
 }
 
 //-------------------------------------------------------------------------
-// Utils
-//-------------------------------------------------------------------------
-cc_library {
-    name: "libunwindstack_utils",
-    defaults: ["libunwindstack_flags"],
-    export_include_dirs: ["utils"],
-    shared_libs: [
-        "libbase",
-        "libunwindstack",
-        "libprocinfo",
-    ],
-    whole_static_libs: [
-        "libc++fs",
-        "libz",
-    ],
-    srcs: [
-        "utils/MemoryFake.cpp",
-        "utils/OfflineUnwindUtils.cpp",
-        "utils/PidUtils.cpp",
-        "utils/ProcessTracer.cpp",
-    ],
-}
-
-//-------------------------------------------------------------------------
 // Unit Tests
 //-------------------------------------------------------------------------
 cc_library_shared {
@@ -268,7 +222,6 @@
     defaults: ["libunwindstack_flags"],
 
     srcs: [
-        "tests/AndroidUnwinderTest.cpp",
         "tests/ArmExidxDecodeTest.cpp",
         "tests/ArmExidxExtractTest.cpp",
         "tests/DexFileTest.cpp",
@@ -290,9 +243,9 @@
         "tests/ElfTest.cpp",
         "tests/ElfTestUtils.cpp",
         "tests/GlobalDebugImplTest.cpp",
-        "tests/GlobalTest.cpp",
         "tests/IsolatedSettings.cpp",
         "tests/JitDebugTest.cpp",
+        "tests/LocalUnwinderTest.cpp",
         "tests/LocalUpdatableMapsTest.cpp",
         "tests/LogFake.cpp",
         "tests/MapInfoCreateMemoryTest.cpp",
@@ -303,6 +256,7 @@
         "tests/MapsTest.cpp",
         "tests/MemoryBufferTest.cpp",
         "tests/MemoryCacheTest.cpp",
+        "tests/MemoryFake.cpp",
         "tests/MemoryFileTest.cpp",
         "tests/MemoryLocalTest.cpp",
         "tests/MemoryOfflineBufferTest.cpp",
@@ -316,7 +270,6 @@
         "tests/MemoryXzTest.cpp",
         "tests/RegsInfoTest.cpp",
         "tests/RegsIterateTest.cpp",
-        "tests/RegsRemoteTest.cpp",
         "tests/RegsStepIfSignalHandlerTest.cpp",
         "tests/RegsTest.cpp",
         "tests/SymbolsTest.cpp",
@@ -325,7 +278,6 @@
         "tests/UnwindTest.cpp",
         "tests/UnwinderTest.cpp",
         "tests/VerifyBionicTerminationTest.cpp",
-        "utils/tests/ProcessTracerTest.cpp",
     ],
 
     cflags: [
@@ -343,8 +295,6 @@
     static_libs: [
         "libdexfile_support",
         "libgmock",
-        "libprocinfo",
-        "libunwindstack_utils",
     ],
 
     test_suites: ["device-tests"],
@@ -356,47 +306,30 @@
         "tests/files/boot_arm.oat.gnu_debugdata.xz.one-block",
         "tests/files/elf32.xz",
         "tests/files/elf64.xz",
-        "offline_files/common/*",
-        "offline_files/apk_rorx_arm64/*",
-        "offline_files/apk_rorx_unreadable_arm64/*",
-        "offline_files/apk_rx_arm64/*",
-        "offline_files/apk_rx_unreadable_arm64/*",
-        "offline_files/art_quick_osr_stub_arm/*",
-        "offline_files/bad_eh_frame_hdr_arm64/*",
-        "offline_files/debug_frame_first_x86/*",
-        "offline_files/debug_frame_load_bias_arm/*",
-        "offline_files/eh_frame_bias_x86/*",
-        "offline_files/eh_frame_hdr_begin_x86_64/*",
-        "offline_files/empty_arm64/*",
-        "offline_files/invalid_elf_offset_arm/*",
-        "offline_files/jit_debug_arm/*",
-        "offline_files/jit_map_arm/*",
-        "offline_files/gnu_debugdata_arm/*",
-        "offline_files/load_bias_different_section_bias_arm64/*",
-        "offline_files/load_bias_ro_rx_x86_64/*",
-        "offline_files/offset_arm/*",
-        "offline_files/pauth_pc_arm64/*",
-        "offline_files/shared_lib_in_apk_arm64/*",
-        "offline_files/shared_lib_in_apk_memory_only_arm64/*",
-        "offline_files/shared_lib_in_apk_single_map_arm64/*",
-        "offline_files/signal_load_bias_arm/*",
-        "offline_files/signal_fde_x86/*",
-        "offline_files/signal_fde_x86_64/*",
-        "offline_files/straddle_arm/*",
-        "offline_files/jit_debug_x86/*",
-        "offline_files/straddle_arm64/*",
-        "offline_files/bluetooth_arm64/pc_1/*",
-        "offline_files/bluetooth_arm64/pc_2/*",
-        "offline_files/bluetooth_arm64/pc_3/*",
-        "offline_files/bluetooth_arm64/pc_4/*",
-        "offline_files/photos_reset_arm64/*",
-        "offline_files/youtube_compiled_arm64/*",
-        "offline_files/yt_music_arm64/*",
-        "offline_files/maps_compiled_arm64/28613_main-thread/*",
-        "offline_files/maps_compiled_arm64/28644/*",
-        "offline_files/maps_compiled_arm64/28648/*",
-        "offline_files/maps_compiled_arm64/28656_oat_odex_jar/*",
-        "offline_files/maps_compiled_arm64/28667/*",
+        "tests/files/offline/art_quick_osr_stub_arm/*",
+        "tests/files/offline/bad_eh_frame_hdr_arm64/*",
+        "tests/files/offline/debug_frame_first_x86/*",
+        "tests/files/offline/debug_frame_load_bias_arm/*",
+        "tests/files/offline/eh_frame_bias_x86/*",
+        "tests/files/offline/eh_frame_hdr_begin_x86_64/*",
+        "tests/files/offline/empty_arm64/*",
+        "tests/files/offline/invalid_elf_offset_arm/*",
+        "tests/files/offline/jit_debug_arm/*",
+        "tests/files/offline/jit_debug_x86/*",
+        "tests/files/offline/jit_map_arm/*",
+        "tests/files/offline/gnu_debugdata_arm/*",
+        "tests/files/offline/load_bias_different_section_bias_arm64/*",
+        "tests/files/offline/load_bias_ro_rx_x86_64/*",
+        "tests/files/offline/offset_arm/*",
+        "tests/files/offline/pauth_pc_arm64/*",
+        "tests/files/offline/shared_lib_in_apk_arm64/*",
+        "tests/files/offline/shared_lib_in_apk_memory_only_arm64/*",
+        "tests/files/offline/shared_lib_in_apk_single_map_arm64/*",
+        "tests/files/offline/signal_load_bias_arm/*",
+        "tests/files/offline/signal_fde_x86/*",
+        "tests/files/offline/signal_fde_x86_64/*",
+        "tests/files/offline/straddle_arm/*",
+        "tests/files/offline/straddle_arm64/*",
     ],
 
     target: {
@@ -438,7 +371,6 @@
     ],
     static_libs: [
         "libdexfile_support",
-        "libunwindstack_utils",
     ],
 }
 
@@ -446,6 +378,7 @@
     name: "libunwindstack_fuzz_unwinder",
     defaults: ["libunwindstack_fuzz_defaults"],
     srcs: [
+        "tests/MemoryFake.cpp",
         "tests/ElfFake.cpp",
         "tests/fuzz/UnwinderComponentCreator.cpp",
         "tests/fuzz/UnwinderFuzz.cpp",
@@ -460,7 +393,7 @@
     defaults: ["libunwindstack_flags"],
 
     shared_libs: [
-        "libunwindstack_stdout_log",
+        "libunwindstack",
         "libbase",
         "liblzma",
     ],
@@ -505,10 +438,6 @@
 cc_binary {
     name: "unwind_for_offline",
     defaults: ["libunwindstack_tools"],
-    static_libs: [
-        "libunwindstack_utils",
-        "libc++fs",
-    ],
 
     srcs: [
         "tools/unwind_for_offline.cpp",
@@ -546,27 +475,10 @@
         "benchmarks/main.cpp",
         "benchmarks/remote_unwind_benchmarks.cpp",
         "benchmarks/thread_unwind_benchmarks.cpp",
-        "benchmarks/OfflineUnwindBenchmarks.cpp",
-        "benchmarks/EvalBenchmark.cpp",
     ],
 
     data: [
         "benchmarks/files/*",
-        "offline_files/common/*",
-        "offline_files/jit_debug_arm/*",
-        "offline_files/straddle_arm64/*",
-        "offline_files/bluetooth_arm64/pc_1/*",
-        "offline_files/bluetooth_arm64/pc_2/*",
-        "offline_files/bluetooth_arm64/pc_3/*",
-        "offline_files/bluetooth_arm64/pc_4/*",
-        "offline_files/photos_reset_arm64/*",
-        "offline_files/youtube_compiled_arm64/*",
-        "offline_files/yt_music_arm64/*",
-        "offline_files/maps_compiled_arm64/28613_main-thread/*",
-        "offline_files/maps_compiled_arm64/28644/*",
-        "offline_files/maps_compiled_arm64/28648/*",
-        "offline_files/maps_compiled_arm64/28656_oat_odex_jar/*",
-        "offline_files/maps_compiled_arm64/28667/*",
     ],
 
     shared_libs: [
@@ -574,15 +486,11 @@
         "libunwindstack",
     ],
 
-    static_libs: [
-        "libunwindstack_utils",
-        "libprocinfo",
-    ],
-
     target: {
         android: {
             static_libs: [
                 "libmeminfo",
+                "libprocinfo",
             ],
         },
     },
diff --git a/libunwindstack/AndroidUnwinder.cpp b/libunwindstack/AndroidUnwinder.cpp
deleted file mode 100644
index 24e991e..0000000
--- a/libunwindstack/AndroidUnwinder.cpp
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright (C) 2022 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 <inttypes.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <memory>
-#include <mutex>
-#include <string>
-#include <vector>
-
-#include <android-base/stringprintf.h>
-#include <android-base/threads.h>
-
-#include <unwindstack/AndroidUnwinder.h>
-#include <unwindstack/Arch.h>
-#include <unwindstack/DexFiles.h>
-#include <unwindstack/Error.h>
-#include <unwindstack/JitDebug.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/Regs.h>
-#include <unwindstack/RegsGetLocal.h>
-#include <unwindstack/Unwinder.h>
-
-#if defined(__BIONIC__)
-#include <bionic/reserved_signals.h>
-static constexpr int kThreadUnwindSignal = BIONIC_SIGNAL_BACKTRACE;
-#else
-#include <signal.h>
-static int kThreadUnwindSignal = SIGRTMIN;
-#endif
-
-// Use the demangler from libc++.
-extern "C" char* __cxa_demangle(const char*, char*, size_t*, int* status);
-
-namespace unwindstack {
-
-void AndroidUnwinderData::DemangleFunctionNames() {
-  for (auto& frame : frames) {
-    char* demangled_name = __cxa_demangle(frame.function_name.c_str(), nullptr, nullptr, nullptr);
-    if (demangled_name != nullptr) {
-      frame.function_name = demangled_name;
-      free(demangled_name);
-    }
-  }
-}
-
-std::string AndroidUnwinderData::GetErrorString() {
-  std::string error_msg(GetErrorCodeString(error.code));
-  if (error.address != 0) {
-    error_msg += android::base::StringPrintf(" at address 0x%" PRIx64, error.address);
-  }
-  return error_msg;
-}
-
-AndroidUnwinder* AndroidUnwinder::Create(pid_t pid) {
-  if (pid == getpid()) {
-    return new AndroidLocalUnwinder;
-  } else {
-    return new AndroidRemoteUnwinder(pid);
-  }
-}
-
-bool AndroidUnwinder::Initialize(ErrorData& error) {
-  // Android stores the jit and dex file location only in the library
-  // libart.so or libartd.so.
-  static std::vector<std::string> search_libs [[clang::no_destroy]] = {"libart.so", "libartd.so"};
-
-  bool initialize = true;
-  std::call_once(initialize_, [this, &initialize, &error]() {
-    initialize = InternalInitialize(error);
-    if (!initialize) {
-      return;
-    }
-
-    jit_debug_ = CreateJitDebug(arch_, process_memory_, search_libs);
-
-#if defined(DEXFILE_SUPPORT)
-    dex_files_ = CreateDexFiles(arch_, process_memory_, search_libs);
-#endif
-  });
-
-  return initialize;
-}
-
-std::string AndroidUnwinder::FormatFrame(const FrameData& frame) const {
-  if (arch_ == ARCH_UNKNOWN) {
-    return "";
-  }
-  return Unwinder::FormatFrame(arch_, frame);
-}
-
-bool AndroidLocalUnwinder::InternalInitialize(ErrorData& error) {
-  arch_ = Regs::CurrentArch();
-
-  maps_.reset(new LocalUpdatableMaps);
-  if (!maps_->Parse()) {
-    error.code = ERROR_MAPS_PARSE;
-    return false;
-  }
-
-  if (process_memory_ == nullptr) {
-    process_memory_ = Memory::CreateProcessMemoryThreadCached(getpid());
-  }
-
-  return true;
-}
-
-FrameData AndroidUnwinder::BuildFrameFromPcOnly(uint64_t pc) {
-  return Unwinder::BuildFrameFromPcOnly(pc, arch_, maps_.get(), jit_debug_.get(), process_memory_,
-                                        true);
-}
-
-bool AndroidUnwinder::Unwind(AndroidUnwinderData& data) {
-  return Unwind(std::nullopt, data);
-}
-
-bool AndroidUnwinder::Unwind(std::optional<pid_t> tid, AndroidUnwinderData& data) {
-  if (!Initialize(data.error)) {
-    return false;
-  }
-
-  return InternalUnwind(tid, data);
-}
-
-bool AndroidUnwinder::Unwind(void* ucontext, AndroidUnwinderData& data) {
-  if (ucontext == nullptr) {
-    data.error.code = ERROR_INVALID_PARAMETER;
-    return false;
-  }
-  std::unique_ptr<Regs> regs(Regs::CreateFromUcontext(arch_, ucontext));
-  return Unwind(regs.get(), data);
-}
-
-bool AndroidUnwinder::Unwind(Regs* initial_regs, AndroidUnwinderData& data) {
-  if (initial_regs == nullptr) {
-    data.error.code = ERROR_INVALID_PARAMETER;
-    return false;
-  }
-
-  if (!Initialize(data.error)) {
-    return false;
-  }
-
-  if (arch_ != initial_regs->Arch()) {
-    data.error.code = ERROR_BAD_ARCH;
-    return false;
-  }
-
-  std::unique_ptr<Regs> regs(initial_regs->Clone());
-  if (data.saved_initial_regs) {
-    (*data.saved_initial_regs).reset(initial_regs->Clone());
-  }
-  Unwinder unwinder(data.max_frames.value_or(max_frames_), maps_.get(), regs.get(),
-                    process_memory_);
-  unwinder.SetJitDebug(jit_debug_.get());
-  unwinder.SetDexFiles(dex_files_.get());
-  unwinder.Unwind(data.show_all_frames ? nullptr : &initial_map_names_to_skip_,
-                  &map_suffixes_to_ignore_);
-  data.frames = unwinder.ConsumeFrames();
-  data.error = unwinder.LastError();
-  return data.frames.size() != 0;
-}
-
-bool AndroidLocalUnwinder::InternalUnwind(std::optional<pid_t> tid, AndroidUnwinderData& data) {
-  if (!tid) {
-    *tid = android::base::GetThreadId();
-  }
-
-  if (static_cast<uint64_t>(*tid) == android::base::GetThreadId()) {
-    // Unwind current thread.
-    std::unique_ptr<Regs> regs(Regs::CreateFromLocal());
-    RegsGetLocal(regs.get());
-    return AndroidUnwinder::Unwind(regs.get(), data);
-  }
-
-  ThreadUnwinder unwinder(data.max_frames.value_or(max_frames_), maps_.get(), process_memory_);
-  unwinder.SetJitDebug(jit_debug_.get());
-  unwinder.SetDexFiles(dex_files_.get());
-  std::unique_ptr<Regs>* initial_regs = nullptr;
-  if (data.saved_initial_regs) {
-    initial_regs = &data.saved_initial_regs.value();
-  }
-  unwinder.UnwindWithSignal(kThreadUnwindSignal, *tid, initial_regs,
-                            data.show_all_frames ? nullptr : &initial_map_names_to_skip_,
-                            &map_suffixes_to_ignore_);
-  data.frames = unwinder.ConsumeFrames();
-  data.error = unwinder.LastError();
-  return data.frames.size() != 0;
-}
-
-bool AndroidRemoteUnwinder::InternalInitialize(ErrorData& error) {
-  if (arch_ == ARCH_UNKNOWN) {
-    arch_ = Regs::RemoteGetArch(pid_);
-  }
-  if (arch_ == ARCH_UNKNOWN) {
-    error.code = ERROR_BAD_ARCH;
-    return false;
-  }
-
-  maps_.reset(new RemoteMaps(pid_));
-  if (!maps_->Parse()) {
-    error.code = ERROR_MAPS_PARSE;
-    return false;
-  }
-
-  if (process_memory_ == nullptr) {
-    process_memory_ = Memory::CreateProcessMemoryCached(pid_);
-  }
-
-  return true;
-}
-
-bool AndroidRemoteUnwinder::InternalUnwind(std::optional<pid_t> tid, AndroidUnwinderData& data) {
-  if (!tid) {
-    *tid = pid_;
-  }
-
-  std::unique_ptr<Regs> regs(Regs::RemoteGet(*tid));
-  return AndroidUnwinder::Unwind(regs.get(), data);
-}
-
-}  // namespace unwindstack
diff --git a/libunwindstack/AndroidVersions.md b/libunwindstack/AndroidVersions.md
index ff46829..b4e29ca 100644
--- a/libunwindstack/AndroidVersions.md
+++ b/libunwindstack/AndroidVersions.md
@@ -114,19 +114,3 @@
   and uses pc relative FDEs, the unwind will be incorrect. This tends
   to truncate unwinds since the unwinder could not find the correct unwind
   information for a given pc.
-
-## Android 12 ("S", API level 31)
-* Fix bug where, if a shared library is dlopen'ed from within an apk file,
-  is not readable, and the shared library only produces a single read-
-  executable map for the elf data and executable data, the offset into the
-  apk will not be displayed. Previously the line would look like:
-
-    #01 pc 000000000222675c  GoogleCamera.apk
-
-  to:
-
-    #01 pc 000000000222675c  GoogleCamera.apk (offset 0x269f000)
-
-  If the apk file is readable, or dlopen'ing the shared library creates
-  a read-only map of the elf data, and a read-executable map of the
-  code, the offset will be displayed properly without this fix.
diff --git a/libunwindstack/ArmExidx.cpp b/libunwindstack/ArmExidx.cpp
index c737cef..818f5d1 100644
--- a/libunwindstack/ArmExidx.cpp
+++ b/libunwindstack/ArmExidx.cpp
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-#include <inttypes.h>
 #include <stdint.h>
 
 #include <deque>
@@ -39,7 +38,7 @@
   for (const uint8_t data : data_) {
     log_str += android::base::StringPrintf(" 0x%02x", data);
   }
-  Log::Info(log_indent_, "%s", log_str.c_str());
+  log(log_indent_, log_str.c_str());
 }
 
 bool ArmExidx::ExtractEntryData(uint32_t entry_offset) {
@@ -68,9 +67,9 @@
     status_ = ARM_STATUS_NO_UNWIND;
     if (log_type_ != ARM_LOG_NONE) {
       if (log_type_ == ARM_LOG_FULL) {
-        Log::Info(log_indent_, "Raw Data: 0x00 0x00 0x00 0x01");
+        log(log_indent_, "Raw Data: 0x00 0x00 0x00 0x01");
       }
-      Log::Info(log_indent_, "[cantunwind]");
+      log(log_indent_, "[cantunwind]");
     }
     return false;
   }
@@ -196,7 +195,7 @@
   if (registers == 0) {
     // 10000000 00000000: Refuse to unwind
     if (log_type_ != ARM_LOG_NONE) {
-      Log::Info(log_indent_, "Refuse to unwind");
+      log(log_indent_, "Refuse to unwind");
     }
     status_ = ARM_STATUS_NO_UNWIND;
     return false;
@@ -217,7 +216,7 @@
           add_comma = true;
         }
       }
-      Log::Info(log_indent_, "%s}", msg.c_str());
+      log(log_indent_, "%s}", msg.c_str());
     } else {
       uint32_t cfa_offset = __builtin_popcount(registers) * 4;
       log_cfa_offset_ += cfa_offset;
@@ -265,7 +264,7 @@
     // 10011101: Reserved as prefix for ARM register to register moves
     // 10011111: Reserved as prefix for Intel Wireless MMX register to register moves
     if (log_type_ != ARM_LOG_NONE) {
-      Log::Info(log_indent_, "[Reserved]");
+      log(log_indent_, "[Reserved]");
     }
     status_ = ARM_STATUS_RESERVED;
     return false;
@@ -273,7 +272,7 @@
   // 1001nnnn: Set vsp = r[nnnn] (nnnn != 13, 15)
   if (log_type_ != ARM_LOG_NONE) {
     if (log_type_ == ARM_LOG_FULL) {
-      Log::Info(log_indent_, "vsp = r%d", bits);
+      log(log_indent_, "vsp = r%d", bits);
     } else {
       log_regs_[LOG_CFA_REG] = bits;
     }
@@ -301,9 +300,9 @@
         msg += android::base::StringPrintf("-r%d", 4 + end_reg);
       }
       if (byte & 0x8) {
-        Log::Info(log_indent_, "%s, r14}", msg.c_str());
+        log(log_indent_, "%s, r14}", msg.c_str());
       } else {
-        Log::Info(log_indent_, "%s}", msg.c_str());
+        log(log_indent_, "%s}", msg.c_str());
       }
     } else {
       end_reg += 4;
@@ -351,7 +350,7 @@
   // 10110000: Finish
   if (log_type_ != ARM_LOG_NONE) {
     if (log_type_ == ARM_LOG_FULL) {
-      Log::Info(log_indent_, "finish");
+      log(log_indent_, "finish");
     }
 
     if (log_skip_execution_) {
@@ -372,7 +371,7 @@
   if (byte == 0) {
     // 10110001 00000000: Spare
     if (log_type_ != ARM_LOG_NONE) {
-      Log::Info(log_indent_, "Spare");
+      log(log_indent_, "Spare");
     }
     status_ = ARM_STATUS_SPARE;
     return false;
@@ -380,7 +379,7 @@
   if (byte >> 4) {
     // 10110001 xxxxyyyy: Spare (xxxx != 0000)
     if (log_type_ != ARM_LOG_NONE) {
-      Log::Info(log_indent_, "Spare");
+      log(log_indent_, "Spare");
     }
     status_ = ARM_STATUS_SPARE;
     return false;
@@ -400,7 +399,7 @@
           add_comma = true;
         }
       }
-      Log::Info(log_indent_, "%s}", msg.c_str());
+      log(log_indent_, "%s}", msg.c_str());
     } else {
       byte &= 0xf;
       uint32_t cfa_offset = __builtin_popcount(byte) * 4;
@@ -457,7 +456,7 @@
   if (log_type_ != ARM_LOG_NONE) {
     int32_t cfa_offset = 0x204 + result;
     if (log_type_ == ARM_LOG_FULL) {
-      Log::Info(log_indent_, "vsp = vsp + %d", cfa_offset);
+      log(log_indent_, "vsp = vsp + %d", cfa_offset);
     } else {
       log_cfa_offset_ += cfa_offset;
     }
@@ -487,9 +486,9 @@
       if (end_reg) {
         msg += android::base::StringPrintf("-d%d", end_reg);
       }
-      Log::Info(log_indent_, "%s}", msg.c_str());
+      log(log_indent_, "%s}", msg.c_str());
     } else {
-      Log::Info(log_indent_, "Unsupported DX register display");
+      log(log_indent_, "Unsupported DX register display");
     }
 
     if (log_skip_execution_) {
@@ -503,7 +502,7 @@
 inline bool ArmExidx::DecodePrefix_10_11_01nn() {
   // 101101nn: Spare
   if (log_type_ != ARM_LOG_NONE) {
-    Log::Info(log_indent_, "Spare");
+    log(log_indent_, "Spare");
   }
   status_ = ARM_STATUS_SPARE;
   return false;
@@ -520,9 +519,9 @@
       if (last_reg) {
         msg += android::base::StringPrintf("-d%d", last_reg + 8);
       }
-      Log::Info(log_indent_, "%s}", msg.c_str());
+      log(log_indent_, "%s}", msg.c_str());
     } else {
-      Log::Info(log_indent_, "Unsupported DX register display");
+      log(log_indent_, "Unsupported DX register display");
     }
 
     if (log_skip_execution_) {
@@ -582,9 +581,9 @@
         if (end_reg) {
           msg += android::base::StringPrintf("-wR%d", start_reg + end_reg);
         }
-        Log::Info(log_indent_, "%s}", msg.c_str());
+        log(log_indent_, "%s}", msg.c_str());
       } else {
-        Log::Info(log_indent_, "Unsupported wRX register display");
+        log(log_indent_, "Unsupported wRX register display");
       }
 
       if (log_skip_execution_) {
@@ -601,7 +600,7 @@
     if (byte == 0) {
       // 11000111 00000000: Spare
       if (log_type_ != ARM_LOG_NONE) {
-        Log::Info(log_indent_, "Spare");
+        log(log_indent_, "Spare");
       }
       status_ = ARM_STATUS_SPARE;
       return false;
@@ -620,9 +619,9 @@
               add_comma = true;
             }
           }
-          Log::Info(log_indent_, "%s}", msg.c_str());
+          log(log_indent_, "%s}", msg.c_str());
         } else {
-          Log::Info(log_indent_, "Unsupported wCGR register display");
+          log(log_indent_, "Unsupported wCGR register display");
         }
 
         if (log_skip_execution_) {
@@ -634,7 +633,7 @@
     } else {
       // 11000111 xxxxyyyy: Spare (xxxx != 0000)
       if (log_type_ != ARM_LOG_NONE) {
-        Log::Info(log_indent_, "Spare");
+        log(log_indent_, "Spare");
       }
       status_ = ARM_STATUS_SPARE;
       return false;
@@ -648,9 +647,9 @@
         if (nnn) {
           msg += android::base::StringPrintf("-wR%d", 10 + nnn);
         }
-        Log::Info(log_indent_, "%s}", msg.c_str());
+        log(log_indent_, "%s}", msg.c_str());
       } else {
-        Log::Info(log_indent_, "Unsupported wRX register display");
+        log(log_indent_, "Unsupported wRX register display");
       }
 
       if (log_skip_execution_) {
@@ -681,9 +680,9 @@
         if (end_reg) {
           msg += android::base::StringPrintf("-d%d", 16 + start_reg + end_reg);
         }
-        Log::Info(log_indent_, "%s}", msg.c_str());
+        log(log_indent_, "%s}", msg.c_str());
       } else {
-        Log::Info(log_indent_, "Unsupported DX register display");
+        log(log_indent_, "Unsupported DX register display");
       }
 
       if (log_skip_execution_) {
@@ -706,9 +705,9 @@
         if (end_reg) {
           msg += android::base::StringPrintf("-d%d", start_reg + end_reg);
         }
-        Log::Info(log_indent_, "%s}", msg.c_str());
+        log(log_indent_, "%s}", msg.c_str());
       } else {
-        Log::Info(log_indent_, "Unsupported DX register display");
+        log(log_indent_, "Unsupported DX register display");
       }
 
       if (log_skip_execution_) {
@@ -720,7 +719,7 @@
   } else {
     // 11001yyy: Spare (yyy != 000, 001)
     if (log_type_ != ARM_LOG_NONE) {
-      Log::Info(log_indent_, "Spare");
+      log(log_indent_, "Spare");
     }
     status_ = ARM_STATUS_SPARE;
     return false;
@@ -739,9 +738,9 @@
       if (end_reg) {
         msg += android::base::StringPrintf("-d%d", 8 + end_reg);
       }
-      Log::Info(log_indent_, "%s}", msg.c_str());
+      log(log_indent_, "%s}", msg.c_str());
     } else {
-      Log::Info(log_indent_, "Unsupported DX register display");
+      log(log_indent_, "Unsupported DX register display");
     }
 
     if (log_skip_execution_) {
@@ -765,7 +764,7 @@
   default:
     // 11xxxyyy: Spare (xxx != 000, 001, 010)
     if (log_type_ != ARM_LOG_NONE) {
-      Log::Info(log_indent_, "Spare");
+      log(log_indent_, "Spare");
     }
     status_ = ARM_STATUS_SPARE;
     return false;
@@ -785,7 +784,7 @@
     if (log_type_ != ARM_LOG_NONE) {
       int32_t cfa_offset = ((byte & 0x3f) << 2) + 4;
       if (log_type_ == ARM_LOG_FULL) {
-        Log::Info(log_indent_, "vsp = vsp + %d", cfa_offset);
+        log(log_indent_, "vsp = vsp + %d", cfa_offset);
       } else {
         log_cfa_offset_ += cfa_offset;
       }
@@ -802,7 +801,7 @@
     if (log_type_ != ARM_LOG_NONE) {
       uint32_t cfa_offset = ((byte & 0x3f) << 2) + 4;
       if (log_type_ == ARM_LOG_FULL) {
-        Log::Info(log_indent_, "vsp = vsp - %d", cfa_offset);
+        log(log_indent_, "vsp = vsp - %d", cfa_offset);
       } else {
         log_cfa_offset_ -= cfa_offset;
       }
@@ -842,9 +841,9 @@
 
   if (log_cfa_offset_ != 0) {
     char sign = (log_cfa_offset_ > 0) ? '+' : '-';
-    Log::Info(log_indent_, "cfa = r%" PRIu8 " %c %d", cfa_reg, sign, abs(log_cfa_offset_));
+    log(log_indent_, "cfa = r%zu %c %d", cfa_reg, sign, abs(log_cfa_offset_));
   } else {
-    Log::Info(log_indent_, "cfa = r%" PRIu8, cfa_reg);
+    log(log_indent_, "cfa = r%zu", cfa_reg);
   }
 
   for (const auto& entry : log_regs_) {
@@ -852,10 +851,10 @@
       break;
     }
     if (entry.second == 0) {
-      Log::Info(log_indent_, "r%" PRIu8 " = [cfa]", entry.first);
+      log(log_indent_, "r%zu = [cfa]", entry.first);
     } else {
       char sign = (entry.second > 0) ? '-' : '+';
-      Log::Info(log_indent_, "r%" PRIu8 " = [cfa %c %d]", entry.first, sign, abs(entry.second));
+      log(log_indent_, "r%zu = [cfa %c %d]", entry.first, sign, abs(entry.second));
     }
   }
 }
diff --git a/libunwindstack/ArmExidx.h b/libunwindstack/ArmExidx.h
index 847613a..d9fc371 100644
--- a/libunwindstack/ArmExidx.h
+++ b/libunwindstack/ArmExidx.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_ARM_EXIDX_H
+#define _LIBUNWINDSTACK_ARM_EXIDX_H
 
 #include <stdint.h>
 
@@ -121,3 +122,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_ARM_EXIDX_H
diff --git a/libunwindstack/Check.h b/libunwindstack/Check.h
index 102cbb1..9643d76 100644
--- a/libunwindstack/Check.h
+++ b/libunwindstack/Check.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_CHECK_H
+#define _LIBUNWINDSTACK_CHECK_H
 
 #include <stdlib.h>
 
@@ -22,10 +23,12 @@
 
 namespace unwindstack {
 
-#define CHECK(assertion)                                       \
-  if (__builtin_expect(!(assertion), false)) {                 \
-    Log::Error("%s:%d: %s\n", __FILE__, __LINE__, #assertion); \
-    abort();                                                   \
+#define CHECK(assertion)                                   \
+  if (__builtin_expect(!(assertion), false)) {             \
+    log(0, "%s:%d: %s\n", __FILE__, __LINE__, #assertion); \
+    abort();                                               \
   }
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_CHECK_H
diff --git a/libunwindstack/DexFile.cpp b/libunwindstack/DexFile.cpp
index 220ee82..e576354 100644
--- a/libunwindstack/DexFile.cpp
+++ b/libunwindstack/DexFile.cpp
@@ -22,10 +22,12 @@
 
 #include <memory>
 
+#define LOG_TAG "unwind"
+#include <log/log.h>
+
 #include <android-base/unique_fd.h>
 #include <art_api/dex_file_support.h>
 
-#include <unwindstack/Log.h>
 #include <unwindstack/MapInfo.h>
 #include <unwindstack/Memory.h>
 
@@ -39,7 +41,7 @@
 
 static bool CheckDexSupport() {
   if (std::string err_msg; !art_api::dex::TryLoadLibdexfile(&err_msg)) {
-    Log::Error("Failed to initialize DEX file support: %s", err_msg.c_str());
+    ALOGW("Failed to initialize DEX file support: %s", err_msg.c_str());
     return false;
   }
   return true;
diff --git a/libunwindstack/DexFile.h b/libunwindstack/DexFile.h
index 3bb65da..6775530 100644
--- a/libunwindstack/DexFile.h
+++ b/libunwindstack/DexFile.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_DEX_FILE_H
+#define _LIBUNWINDSTACK_DEX_FILE_H
 
 #include <stdint.h>
 
@@ -79,3 +80,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_DEX_FILE_H
diff --git a/libunwindstack/DexFiles.cpp b/libunwindstack/DexFiles.cpp
index 981f158..bc99012 100644
--- a/libunwindstack/DexFiles.cpp
+++ b/libunwindstack/DexFiles.cpp
@@ -29,7 +29,7 @@
 template <>
 bool GlobalDebugInterface<DexFile>::Load(Maps* maps, std::shared_ptr<Memory>& memory, uint64_t addr,
                                          uint64_t size, /*out*/ std::shared_ptr<DexFile>& dex) {
-  dex = DexFile::Create(addr, size, memory.get(), maps->Find(addr).get());
+  dex = DexFile::Create(addr, size, memory.get(), maps->Find(addr));
   return dex.get() != nullptr;
 }
 
diff --git a/libunwindstack/DwarfCfa.cpp b/libunwindstack/DwarfCfa.cpp
index c167cd4..884acf5 100644
--- a/libunwindstack/DwarfCfa.cpp
+++ b/libunwindstack/DwarfCfa.cpp
@@ -93,7 +93,7 @@
       }
       case 3: {
         if (cie_loc_regs_ == nullptr) {
-          Log::Error("Invalid: restore while processing cie.");
+          log(0, "restore while processing cie");
           last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
           return false;
         }
@@ -197,8 +197,8 @@
     }
     raw_data += android::base::StringPrintf(" 0x%02x", value);
   }
-  Log::Info(indent, "DW_CFA_offset register(%d) %" PRId64, reg, offset);
-  Log::Info(indent, "%s", raw_data.c_str());
+  log(indent, "DW_CFA_offset register(%d) %" PRId64, reg, offset);
+  log(indent, "%s", raw_data.c_str());
   return true;
 }
 
@@ -208,11 +208,11 @@
   const auto* cfa = &DwarfCfaInfo::kTable[op];
   if (cfa->name[0] == '\0' || (arch_ != ARCH_ARM64 && op == 0x2d)) {
     if (op == 0x2d) {
-      Log::Info(indent, "Illegal (Only valid on aarch64)");
+      log(indent, "Illegal (Only valid on aarch64)");
     } else {
-      Log::Info(indent, "Illegal");
+      log(indent, "Illegal");
     }
-    Log::Info(indent, "Raw Data: 0x%02x", op);
+    log(indent, "Raw Data: 0x%02x", op);
     return true;
   }
 
@@ -239,7 +239,7 @@
       log_string += GetOperandString(cfa->display_operands[i], value, cur_pc);
     }
   }
-  Log::Info(indent, "%s", log_string.c_str());
+  log(indent, "%s", log_string.c_str());
 
   // Get the raw bytes of the data.
   uint64_t end_offset = memory_->cur_offset();
@@ -253,7 +253,7 @@
 
     // Only show 10 raw bytes per line.
     if ((i % 10) == 0 && i != 0) {
-      Log::Info(indent, "%s", raw_data.c_str());
+      log(indent, "%s", raw_data.c_str());
       raw_data.clear();
     }
     if (raw_data.empty()) {
@@ -262,12 +262,12 @@
     raw_data += android::base::StringPrintf(" 0x%02x", value);
   }
   if (!raw_data.empty()) {
-    Log::Info(indent, "%s", raw_data.c_str());
+    log(indent, "%s", raw_data.c_str());
   }
 
   // Log any of the expression data.
   for (const auto& line : expression_lines) {
-    Log::Info(indent + 1, "%s", line.c_str());
+    log(indent + 1, "%s", line.c_str());
   }
   return true;
 }
@@ -295,8 +295,8 @@
         }
         break;
       case 1:
-        Log::Info(indent, "DW_CFA_advance_loc %d", cfa_low);
-        Log::Info(indent, "Raw Data: 0x%02x", cfa_value);
+        log(indent, "DW_CFA_advance_loc %d", cfa_low);
+        log(indent, "Raw Data: 0x%02x", cfa_value);
         cur_pc += cfa_low * fde_->cie->code_alignment_factor;
         break;
       case 2:
@@ -305,14 +305,13 @@
         }
         break;
       case 3:
-        Log::Info(indent, "DW_CFA_restore register(%d)", cfa_low);
-        Log::Info(indent, "Raw Data: 0x%02x", cfa_value);
+        log(indent, "DW_CFA_restore register(%d)", cfa_low);
+        log(indent, "Raw Data: 0x%02x", cfa_value);
         break;
     }
     if (cur_pc != old_pc) {
-      // This forces a newline or empty log line.
-      Log::Info("");
-      Log::Info(indent, "PC 0x%" PRIx64, cur_pc);
+      log(0, "");
+      log(indent, "PC 0x%" PRIx64, cur_pc);
     }
     old_pc = cur_pc;
   }
@@ -325,23 +324,16 @@
   return true;
 }
 
-template <>
-bool DwarfCfa<uint32_t>::cfa_set_loc(DwarfLocations*) {
-  uint32_t cur_pc = cur_pc_;
-  uint32_t new_pc = operands_[0];
+template <typename AddressType>
+bool DwarfCfa<AddressType>::cfa_set_loc(DwarfLocations*) {
+  AddressType cur_pc = cur_pc_;
+  AddressType new_pc = operands_[0];
   if (new_pc < cur_pc) {
-    Log::Info("Warning: PC is moving backwards: old 0x%" PRIx32 " new 0x%" PRIx32, cur_pc, new_pc);
-  }
-  cur_pc_ = new_pc;
-  return true;
-}
-
-template <>
-bool DwarfCfa<uint64_t>::cfa_set_loc(DwarfLocations*) {
-  uint64_t cur_pc = cur_pc_;
-  uint64_t new_pc = operands_[0];
-  if (new_pc < cur_pc) {
-    Log::Info("Warning: PC is moving backwards: old 0x%" PRIx64 " new 0x%" PRIx64, cur_pc, new_pc);
+    if (std::is_same<AddressType, uint32_t>::value) {
+      log(0, "Warning: PC is moving backwards: old 0x%" PRIx32 " new 0x%" PRIx32, cur_pc, new_pc);
+    } else {
+      log(0, "Warning: PC is moving backwards: old 0x%" PRIx64 " new 0x%" PRIx64, cur_pc, new_pc);
+    }
   }
   cur_pc_ = new_pc;
   return true;
@@ -364,7 +356,7 @@
 bool DwarfCfa<AddressType>::cfa_restore(DwarfLocations* loc_regs) {
   AddressType reg = operands_[0];
   if (cie_loc_regs_ == nullptr) {
-    Log::Error("Invalid: restore while processing cie.");
+    log(0, "restore while processing cie");
     last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
     return false;
   }
@@ -408,7 +400,7 @@
 template <typename AddressType>
 bool DwarfCfa<AddressType>::cfa_restore_state(DwarfLocations* loc_regs) {
   if (loc_reg_state_.size() == 0) {
-    Log::Info("Warning: Attempt to restore without remember.");
+    log(0, "Warning: Attempt to restore without remember.");
     return true;
   }
   *loc_regs = loc_reg_state_.top();
@@ -426,7 +418,7 @@
 bool DwarfCfa<AddressType>::cfa_def_cfa_register(DwarfLocations* loc_regs) {
   auto cfa_location = loc_regs->find(CFA_REG);
   if (cfa_location == loc_regs->end() || cfa_location->second.type != DWARF_LOCATION_REGISTER) {
-    Log::Error("Attempt to set new register, but cfa is not already set to a register.");
+    log(0, "Attempt to set new register, but cfa is not already set to a register.");
     last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
     return false;
   }
@@ -440,7 +432,7 @@
   // Changing the offset if this is not a register is illegal.
   auto cfa_location = loc_regs->find(CFA_REG);
   if (cfa_location == loc_regs->end() || cfa_location->second.type != DWARF_LOCATION_REGISTER) {
-    Log::Error("Attempt to set offset, but cfa is not set to a register.");
+    log(0, "Attempt to set offset, but cfa is not set to a register.");
     last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
     return false;
   }
@@ -487,7 +479,7 @@
   // Changing the offset if this is not a register is illegal.
   auto cfa_location = loc_regs->find(CFA_REG);
   if (cfa_location == loc_regs->end() || cfa_location->second.type != DWARF_LOCATION_REGISTER) {
-    Log::Error("Attempt to set offset, but cfa is not set to a register.");
+    log(0, "Attempt to set offset, but cfa is not set to a register.");
     last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
     return false;
   }
diff --git a/libunwindstack/DwarfCfa.h b/libunwindstack/DwarfCfa.h
index e9656e5..c4425bd 100644
--- a/libunwindstack/DwarfCfa.h
+++ b/libunwindstack/DwarfCfa.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_DWARF_CFA_H
+#define _LIBUNWINDSTACK_DWARF_CFA_H
 
 #include <stdint.h>
 
@@ -269,3 +270,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_DWARF_CFA_H
diff --git a/libunwindstack/DwarfDebugFrame.h b/libunwindstack/DwarfDebugFrame.h
index 017568d..635cefd 100644
--- a/libunwindstack/DwarfDebugFrame.h
+++ b/libunwindstack/DwarfDebugFrame.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_DWARF_DEBUG_FRAME_H
+#define _LIBUNWINDSTACK_DWARF_DEBUG_FRAME_H
 
 #include <stdint.h>
 
@@ -45,3 +46,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_DWARF_DEBUG_FRAME_H
diff --git a/libunwindstack/DwarfEhFrame.h b/libunwindstack/DwarfEhFrame.h
index 93befd4..7a41e45 100644
--- a/libunwindstack/DwarfEhFrame.h
+++ b/libunwindstack/DwarfEhFrame.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_DWARF_EH_FRAME_H
+#define _LIBUNWINDSTACK_DWARF_EH_FRAME_H
 
 #include <stdint.h>
 
@@ -44,3 +45,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_DWARF_EH_FRAME_H
diff --git a/libunwindstack/DwarfEhFrameWithHdr.h b/libunwindstack/DwarfEhFrameWithHdr.h
index d074b7b..f7c010c 100644
--- a/libunwindstack/DwarfEhFrameWithHdr.h
+++ b/libunwindstack/DwarfEhFrameWithHdr.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_DWARF_EH_FRAME_WITH_HDR_H
+#define _LIBUNWINDSTACK_DWARF_EH_FRAME_WITH_HDR_H
 
 #include <stdint.h>
 
@@ -81,3 +82,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_DWARF_EH_FRAME_WITH_HDR_H
diff --git a/libunwindstack/DwarfEncoding.h b/libunwindstack/DwarfEncoding.h
index c9fbf24..20db222 100644
--- a/libunwindstack/DwarfEncoding.h
+++ b/libunwindstack/DwarfEncoding.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_DWARF_ENCODING_H
+#define _LIBUNWINDSTACK_DWARF_ENCODING_H
 
 #include <stdint.h>
 
@@ -46,3 +47,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_DWARF_ENCODING_H
diff --git a/libunwindstack/DwarfOp.h b/libunwindstack/DwarfOp.h
index 2f33465..ac9fd2d 100644
--- a/libunwindstack/DwarfOp.h
+++ b/libunwindstack/DwarfOp.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_DWARF_OP_H
+#define _LIBUNWINDSTACK_DWARF_OP_H
 
 #include <stdint.h>
 
@@ -139,3 +140,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_DWARF_OP_H
diff --git a/libunwindstack/DwarfSection.cpp b/libunwindstack/DwarfSection.cpp
index 34d37b0..8a2997e 100644
--- a/libunwindstack/DwarfSection.cpp
+++ b/libunwindstack/DwarfSection.cpp
@@ -102,8 +102,7 @@
     }
 
     cie->cfa_instructions_end = memory_.cur_offset() + length64;
-    // TODO(b/192012848): This is wrong. We need to propagate pointer size here.
-    cie->fde_address_encoding = DW_EH_PE_udata8;
+    cie->fde_address_encoding = DW_EH_PE_sdata8;
 
     uint64_t cie_id;
     if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) {
@@ -119,8 +118,7 @@
   } else {
     // 32 bit Cie
     cie->cfa_instructions_end = memory_.cur_offset() + length32;
-    // TODO(b/192012848): This is wrong. We need to propagate pointer size here.
-    cie->fde_address_encoding = DW_EH_PE_udata4;
+    cie->fde_address_encoding = DW_EH_PE_sdata4;
 
     uint32_t cie_id;
     if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) {
@@ -163,13 +161,8 @@
   } while (aug_value != '\0');
 
   if (cie->version == 4 || cie->version == 5) {
-    char address_size;
-    if (!memory_.ReadBytes(&address_size, 1)) {
-      last_error_.code = DWARF_ERROR_MEMORY_INVALID;
-      last_error_.address = memory_.cur_offset();
-      return false;
-    }
-    cie->fde_address_encoding = address_size == 8 ? DW_EH_PE_udata8 : DW_EH_PE_udata4;
+    // Skip the Address Size field since we only use it for validation.
+    memory_.set_cur_offset(memory_.cur_offset() + 1);
 
     // Segment Size
     if (!memory_.ReadBytes(&cie->segment_size, 1)) {
@@ -674,7 +667,7 @@
 
     if (value64 == cie64_value_) {
       entry_is_cie = true;
-      cie_fde_encoding = DW_EH_PE_udata8;
+      cie_fde_encoding = DW_EH_PE_sdata8;
     } else {
       cie_offset = GetCieOffsetFromFde64(value64);
     }
@@ -690,7 +683,7 @@
 
     if (value32 == cie32_value_) {
       entry_is_cie = true;
-      cie_fde_encoding = DW_EH_PE_udata4;
+      cie_fde_encoding = DW_EH_PE_sdata4;
     } else {
       cie_offset = GetCieOffsetFromFde32(value32);
     }
diff --git a/libunwindstack/Elf.cpp b/libunwindstack/Elf.cpp
index 44db356..7f4142b 100644
--- a/libunwindstack/Elf.cpp
+++ b/libunwindstack/Elf.cpp
@@ -15,26 +15,21 @@
  */
 
 #include <elf.h>
-#include <inttypes.h>
 #include <string.h>
-#include <sys/mman.h>
 
 #include <memory>
 #include <mutex>
 #include <string>
 #include <utility>
 
-#include <android-base/stringprintf.h>
+#define LOG_TAG "unwind"
+#include <log/log.h>
 
 #include <unwindstack/Elf.h>
 #include <unwindstack/ElfInterface.h>
-#include <unwindstack/Log.h>
 #include <unwindstack/MapInfo.h>
 #include <unwindstack/Memory.h>
 #include <unwindstack/Regs.h>
-#include <unwindstack/SharedString.h>
-
-#include <android-base/stringprintf.h>
 
 #include "ElfInterfaceArm.h"
 #include "Symbols.h"
@@ -42,7 +37,7 @@
 namespace unwindstack {
 
 bool Elf::cache_enabled_;
-std::unordered_map<std::string, std::unordered_map<uint64_t, std::shared_ptr<Elf>>>* Elf::cache_;
+std::unordered_map<std::string, std::pair<std::shared_ptr<Elf>, bool>>* Elf::cache_;
 std::mutex* Elf::cache_lock_;
 
 bool Elf::Init() {
@@ -307,6 +302,7 @@
       interface.reset(new ElfInterface32(memory));
     } else {
       // Unsupported.
+      ALOGI("32 bit elf that is neither arm nor x86 nor mips: e_machine = %d\n", e_machine);
       return nullptr;
     }
   } else if (class_type_ == ELFCLASS64) {
@@ -324,6 +320,8 @@
       arch_ = ARCH_MIPS64;
     } else {
       // Unsupported.
+      ALOGI("64 bit elf that is neither aarch64 nor x86_64 nor mips64: e_machine = %d\n",
+            e_machine);
       return nullptr;
     }
     interface.reset(new ElfInterface64(memory));
@@ -353,8 +351,7 @@
 void Elf::SetCachingEnabled(bool enable) {
   if (!cache_enabled_ && enable) {
     cache_enabled_ = true;
-    cache_ =
-        new std::unordered_map<std::string, std::unordered_map<uint64_t, std::shared_ptr<Elf>>>;
+    cache_ = new std::unordered_map<std::string, std::pair<std::shared_ptr<Elf>, bool>>;
     cache_lock_ = new std::mutex;
   } else if (cache_enabled_ && !enable) {
     cache_enabled_ = false;
@@ -372,49 +369,58 @@
 }
 
 void Elf::CacheAdd(MapInfo* info) {
-  if (!info->elf()->valid()) {
-    return;
+  // If elf_offset != 0, then cache both name:offset and name.
+  // The cached name is used to do lookups if multiple maps for the same
+  // named elf file exist.
+  // For example, if there are two maps boot.odex:1000 and boot.odex:2000
+  // where each reference the entire boot.odex, the cache will properly
+  // use the same cached elf object.
+
+  if (info->offset() == 0 || info->elf_offset() != 0) {
+    (*cache_)[info->name()] = std::make_pair(info->elf(), true);
   }
-  (*cache_)[std::string(info->name())].emplace(info->elf_start_offset(), info->elf());
+
+  if (info->offset() != 0) {
+    // The second element in the pair indicates whether elf_offset should
+    // be set to offset when getting out of the cache.
+    std::string key = std::string(info->name()) + ':' + std::to_string(info->offset());
+    (*cache_)[key] = std::make_pair(info->elf(), info->elf_offset() != 0);
+  }
+}
+
+bool Elf::CacheAfterCreateMemory(MapInfo* info) {
+  if (info->name().empty() || info->offset() == 0 || info->elf_offset() == 0) {
+    return false;
+  }
+
+  auto entry = cache_->find(info->name());
+  if (entry == cache_->end()) {
+    return false;
+  }
+
+  // In this case, the whole file is the elf, and the name has already
+  // been cached. Add an entry at name:offset to get this directly out
+  // of the cache next time.
+  info->set_elf(entry->second.first);
+  std::string key = std::string(info->name()) + ':' + std::to_string(info->offset());
+  (*cache_)[key] = std::make_pair(info->elf(), true);
+  return true;
 }
 
 bool Elf::CacheGet(MapInfo* info) {
-  auto name_entry = cache_->find(std::string(info->name()));
-  if (name_entry == cache_->end()) {
-    return false;
+  std::string name(info->name());
+  if (info->offset() != 0) {
+    name += ':' + std::to_string(info->offset());
   }
-  // First look to see if there is a zero offset entry, this indicates
-  // the whole elf is the file.
-  auto& offset_cache = name_entry->second;
-  uint64_t elf_start_offset = 0;
-  auto entry = offset_cache.find(elf_start_offset);
-  if (entry == offset_cache.end()) {
-    // Try and find using the current offset.
-    elf_start_offset = info->offset();
-    entry = offset_cache.find(elf_start_offset);
-    if (entry == offset_cache.end()) {
-      // If this is an execute map, then see if the previous read-only
-      // map is the start of the elf.
-      if (!(info->flags() & PROT_EXEC)) {
-        return false;
-      }
-      auto prev_map = info->GetPrevRealMap();
-      if (prev_map == nullptr || info->offset() <= prev_map->offset() ||
-          (prev_map->flags() != PROT_READ)) {
-        return false;
-      }
-      elf_start_offset = prev_map->offset();
-      entry = offset_cache.find(elf_start_offset);
-      if (entry == offset_cache.end()) {
-        return false;
-      }
+  auto entry = cache_->find(name);
+  if (entry != cache_->end()) {
+    info->set_elf(entry->second.first);
+    if (entry->second.second) {
+      info->set_elf_offset(info->offset());
     }
+    return true;
   }
-
-  info->set_elf(entry->second);
-  info->set_elf_start_offset(elf_start_offset);
-  info->set_elf_offset(info->offset() - elf_start_offset);
-  return true;
+  return false;
 }
 
 std::string Elf::GetBuildID(Memory* memory) {
@@ -435,21 +441,4 @@
   return "";
 }
 
-std::string Elf::GetPrintableBuildID(std::string& build_id) {
-  if (build_id.empty()) {
-    return "";
-  }
-  std::string printable_build_id;
-  for (const char& c : build_id) {
-    // Use %hhx to avoid sign extension on abis that have signed chars.
-    printable_build_id += android::base::StringPrintf("%02hhx", c);
-  }
-  return printable_build_id;
-}
-
-std::string Elf::GetPrintableBuildID() {
-  std::string build_id = GetBuildID();
-  return Elf::GetPrintableBuildID(build_id);
-}
-
 }  // namespace unwindstack
diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp
index 0389198..8268ed7 100644
--- a/libunwindstack/ElfInterface.cpp
+++ b/libunwindstack/ElfInterface.cpp
@@ -21,6 +21,10 @@
 #include <string>
 #include <utility>
 
+#include <7zCrc.h>
+#include <Xz.h>
+#include <XzCrc64.h>
+
 #include <unwindstack/DwarfError.h>
 #include <unwindstack/DwarfSection.h>
 #include <unwindstack/ElfInterface.h>
diff --git a/libunwindstack/ElfInterfaceArm.h b/libunwindstack/ElfInterfaceArm.h
index 6ee6dc9..9bfad0b 100644
--- a/libunwindstack/ElfInterfaceArm.h
+++ b/libunwindstack/ElfInterfaceArm.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_ELF_INTERFACE_ARM_H
+#define _LIBUNWINDSTACK_ELF_INTERFACE_ARM_H
 
 #include <elf.h>
 #include <stdint.h>
@@ -93,3 +94,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_ELF_INTERFACE_ARM_H
diff --git a/libunwindstack/Global.cpp b/libunwindstack/Global.cpp
index 0183bd3..b8adc5c 100644
--- a/libunwindstack/Global.cpp
+++ b/libunwindstack/Global.cpp
@@ -21,8 +21,6 @@
 #include <string>
 #include <vector>
 
-#include <android-base/file.h>
-
 #include <unwindstack/Global.h>
 #include <unwindstack/MapInfo.h>
 #include <unwindstack/Maps.h>
@@ -50,7 +48,7 @@
     return false;
   }
 
-  std::string base_name = android::base::Basename(name);
+  const char* base_name = basename(name.c_str());
   for (const std::string& lib : search_libs_) {
     if (base_name == lib) {
       return true;
@@ -79,7 +77,8 @@
   //   f3000-f4000 2000 rw- /system/lib/libc.so
   MapInfo* map_zero = nullptr;
   for (const auto& info : *maps) {
-    if ((info->flags() & (PROT_READ | PROT_WRITE)) == (PROT_READ | PROT_WRITE) &&
+    if (info->offset() != 0 &&
+        (info->flags() & (PROT_READ | PROT_WRITE)) == (PROT_READ | PROT_WRITE) &&
         map_zero != nullptr && Searchable(info->name()) && info->name() == map_zero->name()) {
       Elf* elf = map_zero->GetElf(memory_, arch());
       uint64_t ptr;
diff --git a/libunwindstack/GlobalDebugImpl.h b/libunwindstack/GlobalDebugImpl.h
index dcea0ef..db8068d 100644
--- a/libunwindstack/GlobalDebugImpl.h
+++ b/libunwindstack/GlobalDebugImpl.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_GLOBAL_DEBUG_IMPL_H
+#define _LIBUNWINDSTACK_GLOBAL_DEBUG_IMPL_H
 
 #include <stdint.h>
 #include <string.h>
@@ -434,3 +435,5 @@
 }
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_GLOBAL_DEBUG_IMPL_H
diff --git a/libunwindstack/LocalUnwinder.cpp b/libunwindstack/LocalUnwinder.cpp
new file mode 100644
index 0000000..466dd68
--- /dev/null
+++ b/libunwindstack/LocalUnwinder.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#include <pthread.h>
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <unwindstack/Elf.h>
+#include <unwindstack/LocalUnwinder.h>
+#include <unwindstack/MapInfo.h>
+#include <unwindstack/Maps.h>
+#include <unwindstack/Memory.h>
+#include <unwindstack/Regs.h>
+#include <unwindstack/RegsGetLocal.h>
+
+namespace unwindstack {
+
+bool LocalUnwinder::Init() {
+  pthread_rwlock_init(&maps_rwlock_, nullptr);
+
+  // Create the maps.
+  maps_.reset(new unwindstack::LocalUpdatableMaps());
+  if (!maps_->Parse()) {
+    maps_.reset();
+    return false;
+  }
+
+  process_memory_ = unwindstack::Memory::CreateProcessMemoryThreadCached(getpid());
+
+  return true;
+}
+
+bool LocalUnwinder::ShouldSkipLibrary(const std::string& map_name) {
+  for (const std::string& skip_library : skip_libraries_) {
+    if (skip_library == map_name) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool LocalUnwinder::Unwind(std::vector<LocalFrameData>* frame_info, size_t max_frames) {
+  std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::CreateFromLocal());
+  unwindstack::RegsGetLocal(regs.get());
+  ArchEnum arch = regs->Arch();
+
+  // Clear any cached data from previous unwinds.
+  process_memory_->Clear();
+
+  size_t num_frames = 0;
+  bool adjust_pc = false;
+  while (true) {
+    uint64_t cur_pc = regs->pc();
+    uint64_t cur_sp = regs->sp();
+
+    MapInfo* map_info = maps_->Find(cur_pc);
+    if (map_info == nullptr) {
+      break;
+    }
+
+    Elf* elf = map_info->GetElf(process_memory_, arch);
+    uint64_t rel_pc = elf->GetRelPc(cur_pc, map_info);
+    uint64_t step_pc = rel_pc;
+    uint64_t pc_adjustment;
+    if (adjust_pc) {
+      pc_adjustment = GetPcAdjustment(rel_pc, elf, arch);
+    } else {
+      pc_adjustment = 0;
+    }
+    step_pc -= pc_adjustment;
+
+    bool finished = false;
+    bool is_signal_frame = false;
+    if (elf->StepIfSignalHandler(rel_pc, regs.get(), process_memory_.get())) {
+      step_pc = rel_pc;
+    } else if (!elf->Step(step_pc, regs.get(), process_memory_.get(), &finished,
+                          &is_signal_frame)) {
+      finished = true;
+    }
+
+    // Skip any locations that are within this library.
+    if (num_frames != 0 || !ShouldSkipLibrary(map_info->name())) {
+      // Add frame information.
+      SharedString func_name;
+      uint64_t func_offset;
+      if (elf->GetFunctionName(rel_pc, &func_name, &func_offset)) {
+        frame_info->emplace_back(map_info, cur_pc - pc_adjustment, rel_pc - pc_adjustment,
+                                 func_name, func_offset);
+      } else {
+        frame_info->emplace_back(map_info, cur_pc - pc_adjustment, rel_pc - pc_adjustment, "", 0);
+      }
+      num_frames++;
+    }
+
+    if (finished || frame_info->size() == max_frames ||
+        (cur_pc == regs->pc() && cur_sp == regs->sp())) {
+      break;
+    }
+    adjust_pc = true;
+  }
+  return num_frames != 0;
+}
+
+}  // namespace unwindstack
diff --git a/libunwindstack/LogAndroid.cpp b/libunwindstack/Log.cpp
similarity index 66%
rename from libunwindstack/LogAndroid.cpp
rename to libunwindstack/Log.cpp
index a2bfc39..3bf73e1 100644
--- a/libunwindstack/LogAndroid.cpp
+++ b/libunwindstack/Log.cpp
@@ -32,51 +32,45 @@
 
 namespace unwindstack {
 
-namespace Log {
+static bool g_print_to_stdout = false;
+
+void log_to_stdout(bool enable) {
+  g_print_to_stdout = enable;
+}
 
 // Send the data to the log.
-static void LogWithPriority(int priority, uint8_t indent, const char* format, va_list args) {
+void log(uint8_t indent, const char* format, ...) {
   std::string real_format;
   if (indent > 0) {
     real_format = android::base::StringPrintf("%*s%s", 2 * indent, " ", format);
   } else {
     real_format = format;
   }
-  LOG_PRI_VA(priority, LOG_TAG, real_format.c_str(), args);
-}
-
-void Info(const char* format, ...) {
   va_list args;
   va_start(args, format);
-  LogWithPriority(ANDROID_LOG_INFO, 0, format, args);
-  va_end(args);
-}
-
-void Info(uint8_t indent, const char* format, ...) {
-  va_list args;
-  va_start(args, format);
-  LogWithPriority(ANDROID_LOG_INFO, indent, format, args);
-  va_end(args);
-}
-
-void Error(const char* format, ...) {
-  va_list args;
-  va_start(args, format);
-  LogWithPriority(ANDROID_LOG_ERROR, 0, format, args);
+  if (g_print_to_stdout) {
+    real_format += '\n';
+    vprintf(real_format.c_str(), args);
+  } else {
+    LOG_PRI_VA(ANDROID_LOG_INFO, LOG_TAG, real_format.c_str(), args);
+  }
   va_end(args);
 }
 
 #if defined(__BIONIC__)
-void AsyncSafe(const char* format, ...) {
+void log_async_safe(const char* format, ...) {
+  if (g_print_to_stdout) {
+    // Printing to stdout is never async safe, so throw the message away.
+    return;
+  }
+
   va_list args;
   va_start(args, format);
   async_safe_format_log_va_list(ANDROID_LOG_ERROR, "libunwindstack", format, args);
   va_end(args);
 }
 #else
-void AsyncSafe(const char*, ...) {}
+void log_async_safe(const char*, ...) {}
 #endif
 
-}  // namespace Log
-
 }  // namespace unwindstack
diff --git a/libunwindstack/LogStdout.cpp b/libunwindstack/LogStdout.cpp
deleted file mode 100644
index 6ce06f8..0000000
--- a/libunwindstack/LogStdout.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2021 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 <stdarg.h>
-#include <stdint.h>
-#include <stdio.h>
-
-#include <string>
-
-#include <android-base/stringprintf.h>
-
-#include <unwindstack/Log.h>
-
-namespace unwindstack {
-
-namespace Log {
-
-static void PrintToStdout(uint8_t indent, const char* format, va_list args) {
-  std::string real_format;
-  if (indent > 0) {
-    real_format = android::base::StringPrintf("%*s%s", 2 * indent, " ", format);
-  } else {
-    real_format = format;
-  }
-  real_format += '\n';
-
-  vprintf(real_format.c_str(), args);
-}
-
-void Info(const char* format, ...) {
-  va_list args;
-  va_start(args, format);
-  PrintToStdout(0, format, args);
-  va_end(args);
-}
-
-void Info(uint8_t indent, const char* format, ...) {
-  va_list args;
-  va_start(args, format);
-  PrintToStdout(indent, format, args);
-  va_end(args);
-}
-
-void Error(const char* format, ...) {
-  va_list args;
-  va_start(args, format);
-  PrintToStdout(0, format, args);
-  va_end(args);
-}
-
-// Do nothing for async safe.
-void AsyncSafe(const char*, ...) {}
-
-}  // namespace Log
-
-}  // namespace unwindstack
diff --git a/libunwindstack/MapInfo.cpp b/libunwindstack/MapInfo.cpp
index 6db1183..8fb6f7e 100644
--- a/libunwindstack/MapInfo.cpp
+++ b/libunwindstack/MapInfo.cpp
@@ -23,7 +23,7 @@
 #include <mutex>
 #include <string>
 
-#include <android-base/strings.h>
+#include <android-base/stringprintf.h>
 
 #include <unwindstack/Elf.h>
 #include <unwindstack/MapInfo.h>
@@ -34,55 +34,15 @@
 
 namespace unwindstack {
 
-bool MapInfo::ElfFileNotReadable() {
-  const std::string& map_name = name();
-  return memory_backed_elf() && !map_name.empty() && map_name[0] != '[' &&
-         !android::base::StartsWith(map_name, "/memfd:");
-}
-
-std::shared_ptr<MapInfo> MapInfo::GetPrevRealMap() {
-  if (name().empty()) {
-    return nullptr;
-  }
-
-  for (auto prev = prev_map(); prev != nullptr; prev = prev->prev_map()) {
-    if (!prev->IsBlank()) {
-      if (prev->name() == name()) {
-        return prev;
-      }
-      return nullptr;
-    }
-  }
-  return nullptr;
-}
-
-std::shared_ptr<MapInfo> MapInfo::GetNextRealMap() {
-  if (name().empty()) {
-    return nullptr;
-  }
-
-  for (auto next = next_map(); next != nullptr; next = next->next_map()) {
-    if (!next->IsBlank()) {
-      if (next->name() == name()) {
-        return next;
-      }
-      return nullptr;
-    }
-  }
-  return nullptr;
-}
-
 bool MapInfo::InitFileMemoryFromPreviousReadOnlyMap(MemoryFileAtOffset* memory) {
   // One last attempt, see if the previous map is read-only with the
   // same name and stretches across this map.
-  auto prev_real_map = GetPrevRealMap();
-  if (prev_real_map == nullptr || prev_real_map->flags() != PROT_READ ||
-      prev_real_map->offset() >= offset()) {
+  if (prev_real_map() == nullptr || prev_real_map()->flags() != PROT_READ) {
     return false;
   }
 
-  uint64_t map_size = end() - prev_real_map->end();
-  if (!memory->Init(name(), prev_real_map->offset(), map_size)) {
+  uint64_t map_size = end() - prev_real_map()->end();
+  if (!memory->Init(name(), prev_real_map()->offset(), map_size)) {
     return false;
   }
 
@@ -91,21 +51,16 @@
     return false;
   }
 
-  if (!memory->Init(name(), prev_real_map->offset(), max_size)) {
+  if (!memory->Init(name(), prev_real_map()->offset(), max_size)) {
     return false;
   }
 
-  set_elf_offset(offset() - prev_real_map->offset());
-  set_elf_start_offset(prev_real_map->offset());
+  set_elf_offset(offset() - prev_real_map()->offset());
+  set_elf_start_offset(prev_real_map()->offset());
   return true;
 }
 
 Memory* MapInfo::GetFileMemory() {
-  // Fail on device maps.
-  if (flags() & MAPS_FLAGS_DEVICE_MAP) {
-    return nullptr;
-  }
-
   std::unique_ptr<MemoryFileAtOffset> memory(new MemoryFileAtOffset);
   if (offset() == 0) {
     if (memory->Init(name(), 0)) {
@@ -128,11 +83,7 @@
   // and reinit to that size. This is needed because the dynamic linker
   // only maps in a portion of the original elf, and never the symbol
   // file data.
-  //
-  // For maps with MAPS_FLAGS_JIT_SYMFILE_MAP, the map range is for a JIT function,
-  // which can be smaller than elf header size. So make sure map_size is large enough
-  // to read elf header.
-  uint64_t map_size = std::max<uint64_t>(end() - start(), sizeof(ElfTypes64::Ehdr));
+  uint64_t map_size = end() - start();
   if (!memory->Init(name(), offset(), map_size)) {
     return nullptr;
   }
@@ -158,6 +109,13 @@
   // No elf at offset, try to init as if the whole file is an elf.
   if (memory->Init(name(), 0) && Elf::IsValidElf(memory.get())) {
     set_elf_offset(offset());
+    // Need to check how to set the elf start offset. If this map is not
+    // the r-x map of a r-- map, then use the real offset value. Otherwise,
+    // use 0.
+    if (prev_real_map() == nullptr || prev_real_map()->offset() != 0 ||
+        prev_real_map()->flags() != PROT_READ || prev_real_map()->name() != name()) {
+      set_elf_start_offset(offset());
+    }
     return memory.release();
   }
 
@@ -208,13 +166,10 @@
   // option is used.
   std::unique_ptr<MemoryRange> memory(new MemoryRange(process_memory, start(), end() - start(), 0));
   if (Elf::IsValidElf(memory.get())) {
-    set_elf_start_offset(offset());
-
-    auto next_real_map = GetNextRealMap();
-
     // Might need to peek at the next map to create a memory object that
     // includes that map too.
-    if (offset() != 0 || next_real_map == nullptr || offset() >= next_real_map->offset()) {
+    if (offset() != 0 || name().empty() || next_real_map() == nullptr ||
+        offset() >= next_real_map()->offset() || next_real_map()->name() != name()) {
       return memory.release();
     }
 
@@ -224,103 +179,95 @@
     // be discarded.
     MemoryRanges* ranges = new MemoryRanges;
     ranges->Insert(new MemoryRange(process_memory, start(), end() - start(), 0));
-    ranges->Insert(new MemoryRange(process_memory, next_real_map->start(),
-                                   next_real_map->end() - next_real_map->start(),
-                                   next_real_map->offset() - offset()));
+    ranges->Insert(new MemoryRange(process_memory, next_real_map()->start(),
+                                   next_real_map()->end() - next_real_map()->start(),
+                                   next_real_map()->offset() - offset()));
 
     return ranges;
   }
 
-  auto prev_real_map = GetPrevRealMap();
-
   // Find the read-only map by looking at the previous map. The linker
   // doesn't guarantee that this invariant will always be true. However,
   // if that changes, there is likely something else that will change and
   // break something.
-  if (offset() == 0 || prev_real_map == nullptr || prev_real_map->offset() >= offset()) {
+  if (offset() == 0 || name().empty() || prev_real_map() == nullptr ||
+      prev_real_map()->name() != name() || prev_real_map()->offset() >= offset()) {
     set_memory_backed_elf(false);
     return nullptr;
   }
 
   // Make sure that relative pc values are corrected properly.
-  set_elf_offset(offset() - prev_real_map->offset());
+  set_elf_offset(offset() - prev_real_map()->offset());
   // Use this as the elf start offset, otherwise, you always get offsets into
   // the r-x section, which is not quite the right information.
-  set_elf_start_offset(prev_real_map->offset());
+  set_elf_start_offset(prev_real_map()->offset());
 
-  std::unique_ptr<MemoryRanges> ranges(new MemoryRanges);
-  if (!ranges->Insert(new MemoryRange(process_memory, prev_real_map->start(),
-                                      prev_real_map->end() - prev_real_map->start(), 0))) {
-    return nullptr;
-  }
-  if (!ranges->Insert(new MemoryRange(process_memory, start(), end() - start(), elf_offset()))) {
-    return nullptr;
-  }
-  return ranges.release();
+  MemoryRanges* ranges = new MemoryRanges;
+  ranges->Insert(new MemoryRange(process_memory, prev_real_map()->start(),
+                                 prev_real_map()->end() - prev_real_map()->start(), 0));
+  ranges->Insert(new MemoryRange(process_memory, start(), end() - start(), elf_offset()));
+
+  return ranges;
 }
 
-class ScopedElfCacheLock {
- public:
-  ScopedElfCacheLock() {
-    if (Elf::CachingEnabled()) Elf::CacheLock();
-  }
-  ~ScopedElfCacheLock() {
-    if (Elf::CachingEnabled()) Elf::CacheUnlock();
-  }
-};
-
 Elf* MapInfo::GetElf(const std::shared_ptr<Memory>& process_memory, ArchEnum expected_arch) {
-  // Make sure no other thread is trying to add the elf to this map.
-  std::lock_guard<std::mutex> guard(elf_mutex());
+  {
+    // Make sure no other thread is trying to add the elf to this map.
+    std::lock_guard<std::mutex> guard(elf_mutex());
 
-  if (elf().get() != nullptr) {
-    return elf().get();
-  }
-
-  ScopedElfCacheLock elf_cache_lock;
-  if (Elf::CachingEnabled() && !name().empty()) {
-    if (Elf::CacheGet(this)) {
+    if (elf().get() != nullptr) {
       return elf().get();
     }
-  }
 
-  elf().reset(new Elf(CreateMemory(process_memory)));
-  // If the init fails, keep the elf around as an invalid object so we
-  // don't try to reinit the object.
-  elf()->Init();
-  if (elf()->valid() && expected_arch != elf()->arch()) {
-    // Make the elf invalid, mismatch between arch and expected arch.
-    elf()->Invalidate();
+    bool locked = false;
+    if (Elf::CachingEnabled() && !name().empty()) {
+      Elf::CacheLock();
+      locked = true;
+      if (Elf::CacheGet(this)) {
+        Elf::CacheUnlock();
+        return elf().get();
+      }
+    }
+
+    Memory* memory = CreateMemory(process_memory);
+    if (locked) {
+      if (Elf::CacheAfterCreateMemory(this)) {
+        delete memory;
+        Elf::CacheUnlock();
+        return elf().get();
+      }
+    }
+    elf().reset(new Elf(memory));
+    // If the init fails, keep the elf around as an invalid object so we
+    // don't try to reinit the object.
+    elf()->Init();
+    if (elf()->valid() && expected_arch != elf()->arch()) {
+      // Make the elf invalid, mismatch between arch and expected arch.
+      elf()->Invalidate();
+    }
+
+    if (locked) {
+      Elf::CacheAdd(this);
+      Elf::CacheUnlock();
+    }
   }
 
   if (!elf()->valid()) {
     set_elf_start_offset(offset());
-  } else if (auto prev_real_map = GetPrevRealMap(); prev_real_map != nullptr &&
-                                                    prev_real_map->flags() == PROT_READ &&
-                                                    prev_real_map->offset() < offset()) {
+  } else if (prev_real_map() != nullptr && elf_start_offset() != offset() &&
+             prev_real_map()->offset() == elf_start_offset() && prev_real_map()->name() == name()) {
     // If there is a read-only map then a read-execute map that represents the
     // same elf object, make sure the previous map is using the same elf
-    // object if it hasn't already been set. Locking this should not result
-    // in a deadlock as long as the invariant that the code only ever tries
-    // to lock the previous real map holds true.
-    std::lock_guard<std::mutex> guard(prev_real_map->elf_mutex());
-    if (prev_real_map->elf() == nullptr) {
-      // Need to verify if the map is the previous read-only map.
-      prev_real_map->set_elf(elf());
-      prev_real_map->set_memory_backed_elf(memory_backed_elf());
-      prev_real_map->set_elf_start_offset(elf_start_offset());
-      prev_real_map->set_elf_offset(prev_real_map->offset() - elf_start_offset());
-    } else if (prev_real_map->elf_start_offset() == elf_start_offset()) {
+    // object if it hasn't already been set.
+    std::lock_guard<std::mutex> guard(prev_real_map()->elf_mutex());
+    if (prev_real_map()->elf().get() == nullptr) {
+      prev_real_map()->set_elf(elf());
+      prev_real_map()->set_memory_backed_elf(memory_backed_elf());
+    } else {
       // Discard this elf, and use the elf from the previous map instead.
-      set_elf(prev_real_map->elf());
+      set_elf(prev_real_map()->elf());
     }
   }
-
-  // Cache the elf only after all of the above checks since we might
-  // discard the original elf we created.
-  if (Elf::CachingEnabled()) {
-    Elf::CacheAdd(this);
-  }
   return elf().get();
 }
 
@@ -337,33 +284,27 @@
   return elf()->GetFunctionName(addr, name, func_offset);
 }
 
-uint64_t MapInfo::GetLoadBias() {
-  uint64_t cur_load_bias = load_bias().load();
-  if (cur_load_bias != UINT64_MAX) {
-    return cur_load_bias;
-  }
-
-  Elf* elf_obj = GetElfObj();
-  if (elf_obj == nullptr) {
-    return UINT64_MAX;
-  }
-
-  if (elf_obj->valid()) {
-    cur_load_bias = elf_obj->GetLoadBias();
-    set_load_bias(cur_load_bias);
-    return cur_load_bias;
-  }
-
-  set_load_bias(0);
-  return 0;
-}
-
 uint64_t MapInfo::GetLoadBias(const std::shared_ptr<Memory>& process_memory) {
-  uint64_t cur_load_bias = GetLoadBias();
-  if (cur_load_bias != UINT64_MAX) {
+  int64_t cur_load_bias = load_bias().load();
+  if (cur_load_bias != INT64_MAX) {
     return cur_load_bias;
   }
 
+  {
+    // Make sure no other thread is trying to add the elf to this map.
+    std::lock_guard<std::mutex> guard(elf_mutex());
+    if (elf() != nullptr) {
+      if (elf()->valid()) {
+        cur_load_bias = elf()->GetLoadBias();
+        set_load_bias(cur_load_bias);
+        return cur_load_bias;
+      } else {
+        set_load_bias(0);
+        return 0;
+      }
+    }
+  }
+
   // Call lightweight static function that will only read enough of the
   // elf data to get the load bias.
   std::unique_ptr<Memory> memory(CreateMemory(process_memory));
@@ -380,23 +321,6 @@
   }
 }
 
-std::string MapInfo::GetFullName() {
-  Elf* elf_obj = GetElfObj();
-  if (elf_obj == nullptr || elf_start_offset() == 0 || name().empty()) {
-    return name();
-  }
-
-  std::string soname = elf_obj->GetSoname();
-  if (soname.empty()) {
-    return name();
-  }
-
-  std::string full_name(name());
-  full_name += '!';
-  full_name += soname;
-  return full_name;
-}
-
 SharedString MapInfo::GetBuildID() {
   SharedString* id = build_id().load();
   if (id != nullptr) {
@@ -407,8 +331,12 @@
   // time it should be detected and only one thread should win and
   // save the data.
 
+  // Now need to see if the elf object exists.
+  // Make sure no other thread is trying to add the elf to this map.
+  elf_mutex().lock();
+  Elf* elf_obj = elf().get();
+  elf_mutex().unlock();
   std::string result;
-  Elf* elf_obj = GetElfObj();
   if (elf_obj != nullptr) {
     result = elf_obj->GetBuildID();
   } else {
@@ -454,7 +382,15 @@
 
 std::string MapInfo::GetPrintableBuildID() {
   std::string raw_build_id = GetBuildID();
-  return Elf::GetPrintableBuildID(raw_build_id);
+  if (raw_build_id.empty()) {
+    return "";
+  }
+  std::string printable_build_id;
+  for (const char& c : raw_build_id) {
+    // Use %hhx to avoid sign extension on abis that have signed chars.
+    printable_build_id += android::base::StringPrintf("%02hhx", c);
+  }
+  return printable_build_id;
 }
 
 }  // namespace unwindstack
diff --git a/libunwindstack/Maps.cpp b/libunwindstack/Maps.cpp
index 9527176..7a9e2e9 100644
--- a/libunwindstack/Maps.cpp
+++ b/libunwindstack/Maps.cpp
@@ -39,7 +39,7 @@
 
 namespace unwindstack {
 
-std::shared_ptr<MapInfo> Maps::Find(uint64_t pc) {
+MapInfo* Maps::Find(uint64_t pc) {
   if (maps_.empty()) {
     return nullptr;
   }
@@ -49,7 +49,7 @@
     size_t index = (first + last) / 2;
     const auto& cur = maps_[index];
     if (pc >= cur->start() && pc < cur->end()) {
-      return cur;
+      return cur.get();
     } else if (pc < cur->start()) {
       last = index;
     } else {
@@ -60,7 +60,8 @@
 }
 
 bool Maps::Parse() {
-  std::shared_ptr<MapInfo> prev_map;
+  MapInfo* prev_map = nullptr;
+  MapInfo* prev_real_map = nullptr;
   return android::procinfo::ReadMapFile(GetMapsFile(),
                       [&](const android::procinfo::MapInfo& mapinfo) {
     // Mark a device map in /dev/ and not in /dev/ashmem/ specially.
@@ -69,53 +70,52 @@
         strncmp(mapinfo.name.c_str() + 5, "ashmem/", 7) != 0) {
       flags |= unwindstack::MAPS_FLAGS_DEVICE_MAP;
     }
-    maps_.emplace_back(
-        MapInfo::Create(prev_map, mapinfo.start, mapinfo.end, mapinfo.pgoff, flags, mapinfo.name));
-    prev_map = maps_.back();
+    maps_.emplace_back(new MapInfo(prev_map, prev_real_map, mapinfo.start, mapinfo.end,
+                                   mapinfo.pgoff, flags, mapinfo.name));
+    prev_map = maps_.back().get();
+    if (!prev_map->IsBlank()) {
+      prev_real_map = prev_map;
+    }
   });
 }
 
 void Maps::Add(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
-               const std::string& name) {
-  std::shared_ptr<MapInfo> prev_map(maps_.empty() ? nullptr : maps_.back());
-  auto map_info = MapInfo::Create(prev_map, start, end, offset, flags, name);
-  maps_.emplace_back(std::move(map_info));
-}
-
-void Maps::Add(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
                const std::string& name, uint64_t load_bias) {
-  std::shared_ptr<MapInfo> prev_map(maps_.empty() ? nullptr : maps_.back());
-  auto map_info = MapInfo::Create(prev_map, start, end, offset, flags, name);
+  MapInfo* prev_map = maps_.empty() ? nullptr : maps_.back().get();
+  MapInfo* prev_real_map = prev_map;
+  while (prev_real_map != nullptr && prev_real_map->IsBlank()) {
+    prev_real_map = prev_real_map->prev_map();
+  }
+
+  auto map_info =
+      std::make_unique<MapInfo>(prev_map, prev_real_map, start, end, offset, flags, name);
   map_info->set_load_bias(load_bias);
   maps_.emplace_back(std::move(map_info));
 }
 
 void Maps::Sort() {
-  if (maps_.empty()) {
-    return;
-  }
-
   std::sort(maps_.begin(), maps_.end(),
-            [](const std::shared_ptr<MapInfo>& a, const std::shared_ptr<MapInfo>& b) {
+            [](const std::unique_ptr<MapInfo>& a, const std::unique_ptr<MapInfo>& b) {
               return a->start() < b->start();
             });
 
-  // Set prev_map and next_map on the info objects.
-  std::shared_ptr<MapInfo> prev_map;
-  // Set the last next_map to nullptr.
-  maps_.back()->set_next_map(prev_map);
-  for (auto& map_info : maps_) {
+  // Set the prev_map values on the info objects.
+  MapInfo* prev_map = nullptr;
+  MapInfo* prev_real_map = nullptr;
+  for (const auto& map_info : maps_) {
     map_info->set_prev_map(prev_map);
-    if (prev_map) {
-      prev_map->set_next_map(map_info);
+    map_info->set_prev_real_map(prev_real_map);
+    prev_map = map_info.get();
+    if (!prev_map->IsBlank()) {
+      prev_real_map = prev_map;
     }
-    prev_map = map_info;
   }
 }
 
 bool BufferMaps::Parse() {
   std::string content(buffer_);
-  std::shared_ptr<MapInfo> prev_map;
+  MapInfo* prev_map = nullptr;
+  MapInfo* prev_real_map = nullptr;
   return android::procinfo::ReadMapFileContent(
       &content[0], [&](const android::procinfo::MapInfo& mapinfo) {
         // Mark a device map in /dev/ and not in /dev/ashmem/ specially.
@@ -124,9 +124,12 @@
             strncmp(mapinfo.name.c_str() + 5, "ashmem/", 7) != 0) {
           flags |= unwindstack::MAPS_FLAGS_DEVICE_MAP;
         }
-        maps_.emplace_back(MapInfo::Create(prev_map, mapinfo.start, mapinfo.end, mapinfo.pgoff,
-                                           flags, mapinfo.name));
-        prev_map = maps_.back();
+        maps_.emplace_back(new MapInfo(prev_map, prev_real_map, mapinfo.start, mapinfo.end,
+                                       mapinfo.pgoff, flags, mapinfo.name));
+        prev_map = maps_.back().get();
+        if (!prev_map->IsBlank()) {
+          prev_real_map = prev_map;
+        }
       });
 }
 
@@ -142,9 +145,9 @@
   pthread_rwlock_init(&maps_rwlock_, nullptr);
 }
 
-std::shared_ptr<MapInfo> LocalUpdatableMaps::Find(uint64_t pc) {
+MapInfo* LocalUpdatableMaps::Find(uint64_t pc) {
   pthread_rwlock_rdlock(&maps_rwlock_);
-  std::shared_ptr<MapInfo> map_info = Maps::Find(pc);
+  MapInfo* map_info = Maps::Find(pc);
   pthread_rwlock_unlock(&maps_rwlock_);
 
   if (map_info == nullptr) {
@@ -188,22 +191,13 @@
       auto& info = maps_[old_map_idx];
       if (start == info->start() && end == info->end() && flags == info->flags() &&
           name == info->name()) {
+        // No need to check
         search_map_idx = old_map_idx + 1;
-        // Since we are throwing away a map from the new list, need to
-        // adjust the next/prev pointers in the old map entry.
-        auto prev = new_map_info->prev_map();
-        auto next = new_map_info->next_map();
-        info->set_prev_map(prev);
-        info->set_next_map(next);
-
-        // Fix up the pointers in the prev and next entries.
-        if (prev != nullptr) {
-          prev->set_next_map(info);
+        if (new_map_idx + 1 < maps_.size()) {
+          maps_[new_map_idx + 1]->set_prev_map(info.get());
+          maps_[new_map_idx + 1]->set_prev_real_map(info->IsBlank() ? info->prev_real_map()
+                                                                    : info.get());
         }
-        if (next != nullptr) {
-          next->set_prev_map(info);
-        }
-
         maps_[new_map_idx] = nullptr;
         num_deleted_new_entries++;
         break;
@@ -216,9 +210,7 @@
       // Never delete these maps, they may be in use. The assumption is
       // that there will only every be a handful of these so waiting
       // to destroy them is not too expensive.
-      // Since these are all shared_ptrs, we can just remove the references.
-      // Any code still holding on to the pointer, will still have a
-      // valid pointer after this.
+      saved_maps_.emplace_back(std::move(info));
       search_map_idx = old_map_idx + 1;
       maps_[old_map_idx] = nullptr;
       num_deleted_old_entries++;
@@ -228,7 +220,9 @@
     }
   }
 
+  // Now move out any of the maps that never were found.
   for (size_t i = search_map_idx; i < last_map_idx; i++) {
+    saved_maps_.emplace_back(std::move(maps_[i]));
     maps_[i] = nullptr;
     num_deleted_old_entries++;
   }
diff --git a/libunwindstack/Memory.cpp b/libunwindstack/Memory.cpp
index 5cfe2f0..e1fe0e1 100644
--- a/libunwindstack/Memory.cpp
+++ b/libunwindstack/Memory.cpp
@@ -25,17 +25,21 @@
 #include <sys/uio.h>
 #include <unistd.h>
 
+#include <7zCrc.h>
+#include <Xz.h>
+#include <XzCrc64.h>
+
 #include <algorithm>
 #include <memory>
 #include <mutex>
 #include <optional>
-#include <string>
 
 #include <android-base/unique_fd.h>
 
 #include <unwindstack/Log.h>
 #include <unwindstack/Memory.h>
 
+#include "Check.h"
 #include "MemoryBuffer.h"
 #include "MemoryCache.h"
 #include "MemoryFileAtOffset.h"
@@ -44,9 +48,16 @@
 #include "MemoryOfflineBuffer.h"
 #include "MemoryRange.h"
 #include "MemoryRemote.h"
+#include "MemoryXz.h"
 
 namespace unwindstack {
 
+// Statistics (used only for optional debug log messages).
+static constexpr bool kLogMemoryXzUsage = false;
+std::atomic_size_t MemoryXz::total_used_ = 0;
+std::atomic_size_t MemoryXz::total_size_ = 0;
+std::atomic_size_t MemoryXz::total_open_ = 0;
+
 static size_t ProcessVmRead(pid_t pid, uint64_t remote_src, void* dst, size_t len) {
 
   // Split up the remote read across page boundaries.
@@ -369,7 +380,7 @@
   return memory_->Read(read_addr, dst, read_length);
 }
 
-bool MemoryRanges::Insert(MemoryRange* memory) {
+void MemoryRanges::Insert(MemoryRange* memory) {
   uint64_t last_addr;
   if (__builtin_add_overflow(memory->offset(), memory->length(), &last_addr)) {
     // This should never happen in the real world. However, it is possible
@@ -378,12 +389,7 @@
     // value.
     last_addr = UINT64_MAX;
   }
-  auto entry = maps_.try_emplace(last_addr, memory);
-  if (entry.second) {
-    return true;
-  }
-  delete memory;
-  return false;
+  maps_.emplace(last_addr, memory);
 }
 
 size_t MemoryRanges::Read(uint64_t addr, void* dst, size_t size) {
@@ -415,16 +421,6 @@
   return true;
 }
 
-bool MemoryOffline::Init(const std::string& file, uint64_t offset, uint64_t start, uint64_t size) {
-  auto memory_file = std::make_shared<MemoryFileAtOffset>();
-  if (!memory_file->Init(file, offset)) {
-    return false;
-  }
-
-  memory_ = std::make_unique<MemoryRange>(memory_file, 0, size, start);
-  return true;
-}
-
 size_t MemoryOffline::Read(uint64_t addr, void* dst, size_t size) {
   if (!memory_) {
     return 0;
@@ -535,7 +531,7 @@
         CacheDataType* cache = reinterpret_cast<CacheDataType*>(memory);
         delete cache;
       }) != 0) {
-    Log::AsyncSafe("Failed to create pthread key.");
+    log_async_safe("Failed to create pthread key.");
     thread_cache_.reset();
   }
 }
@@ -563,10 +559,6 @@
 }
 
 void MemoryThreadCache::Clear() {
-  if (!thread_cache_) {
-    return;
-  }
-
   CacheDataType* cache = reinterpret_cast<CacheDataType*>(pthread_getspecific(*thread_cache_));
   if (cache != nullptr) {
     delete cache;
@@ -574,4 +566,229 @@
   }
 }
 
+MemoryXz::MemoryXz(Memory* memory, uint64_t addr, uint64_t size, const std::string& name)
+    : compressed_memory_(memory), compressed_addr_(addr), compressed_size_(size), name_(name) {
+  total_open_ += 1;
+}
+
+bool MemoryXz::Init() {
+  static std::once_flag crc_initialized;
+  std::call_once(crc_initialized, []() {
+    CrcGenerateTable();
+    Crc64GenerateTable();
+  });
+  if (compressed_size_ >= kMaxCompressedSize) {
+    return false;
+  }
+  if (!ReadBlocks()) {
+    return false;
+  }
+
+  // All blocks (except the last one) must have the same power-of-2 size.
+  if (blocks_.size() > 1) {
+    size_t block_size_log2 = __builtin_ctz(blocks_.front().decompressed_size);
+    auto correct_size = [=](XzBlock& b) { return b.decompressed_size == (1 << block_size_log2); };
+    if (std::all_of(blocks_.begin(), std::prev(blocks_.end()), correct_size) &&
+        blocks_.back().decompressed_size <= (1 << block_size_log2)) {
+      block_size_log2_ = block_size_log2;
+    } else {
+      // Inconsistent block-sizes.  Decompress and merge everything now.
+      std::unique_ptr<uint8_t[]> data(new uint8_t[size_]);
+      size_t offset = 0;
+      for (XzBlock& block : blocks_) {
+        if (!Decompress(&block)) {
+          return false;
+        }
+        memcpy(data.get() + offset, block.decompressed_data.get(), block.decompressed_size);
+        offset += block.decompressed_size;
+      }
+      blocks_.clear();
+      blocks_.push_back(XzBlock{
+          .decompressed_data = std::move(data),
+          .decompressed_size = size_,
+      });
+      block_size_log2_ = 31;  // Because 32 bits is too big (shift right by 32 is not allowed).
+    }
+  }
+
+  return true;
+}
+
+MemoryXz::~MemoryXz() {
+  total_used_ -= used_;
+  total_size_ -= size_;
+  total_open_ -= 1;
+}
+
+size_t MemoryXz::Read(uint64_t addr, void* buffer, size_t size) {
+  if (addr >= size_) {
+    return 0;  // Read past the end.
+  }
+  uint8_t* dst = reinterpret_cast<uint8_t*>(buffer);  // Position in the output buffer.
+  for (size_t i = addr >> block_size_log2_; i < blocks_.size(); i++) {
+    XzBlock* block = &blocks_[i];
+    if (block->decompressed_data == nullptr) {
+      if (!Decompress(block)) {
+        break;
+      }
+    }
+    size_t offset = (addr - (i << block_size_log2_));  // Start inside the block.
+    size_t copy_bytes = std::min<size_t>(size, block->decompressed_size - offset);
+    memcpy(dst, block->decompressed_data.get() + offset, copy_bytes);
+    dst += copy_bytes;
+    addr += copy_bytes;
+    size -= copy_bytes;
+    if (size == 0) {
+      break;
+    }
+  }
+  return dst - reinterpret_cast<uint8_t*>(buffer);
+}
+
+bool MemoryXz::ReadBlocks() {
+  static ISzAlloc alloc;
+  alloc.Alloc = [](ISzAllocPtr, size_t size) { return malloc(size); };
+  alloc.Free = [](ISzAllocPtr, void* ptr) { return free(ptr); };
+
+  // Read the compressed data, so we can quickly scan through the headers.
+  std::unique_ptr<uint8_t[]> compressed_data(new (std::nothrow) uint8_t[compressed_size_]);
+  if (compressed_data.get() == nullptr) {
+    return false;
+  }
+  if (!compressed_memory_->ReadFully(compressed_addr_, compressed_data.get(), compressed_size_)) {
+    return false;
+  }
+
+  // Implement the required interface for communication
+  // (written in C so we can not use virtual methods or member functions).
+  struct XzLookInStream : public ILookInStream, public ICompressProgress {
+    static SRes LookImpl(const ILookInStream* p, const void** buf, size_t* size) {
+      auto* ctx = reinterpret_cast<const XzLookInStream*>(p);
+      *buf = ctx->data + ctx->offset;
+      *size = std::min(*size, ctx->size - ctx->offset);
+      return SZ_OK;
+    }
+    static SRes SkipImpl(const ILookInStream* p, size_t len) {
+      auto* ctx = reinterpret_cast<XzLookInStream*>(const_cast<ILookInStream*>(p));
+      ctx->offset += len;
+      return SZ_OK;
+    }
+    static SRes ReadImpl(const ILookInStream* p, void* buf, size_t* size) {
+      auto* ctx = reinterpret_cast<const XzLookInStream*>(p);
+      *size = std::min(*size, ctx->size - ctx->offset);
+      memcpy(buf, ctx->data + ctx->offset, *size);
+      return SZ_OK;
+    }
+    static SRes SeekImpl(const ILookInStream* p, Int64* pos, ESzSeek origin) {
+      auto* ctx = reinterpret_cast<XzLookInStream*>(const_cast<ILookInStream*>(p));
+      switch (origin) {
+        case SZ_SEEK_SET:
+          ctx->offset = *pos;
+          break;
+        case SZ_SEEK_CUR:
+          ctx->offset += *pos;
+          break;
+        case SZ_SEEK_END:
+          ctx->offset = ctx->size + *pos;
+          break;
+      }
+      *pos = ctx->offset;
+      return SZ_OK;
+    }
+    static SRes ProgressImpl(const ICompressProgress*, UInt64, UInt64) { return SZ_OK; }
+    size_t offset;
+    uint8_t* data;
+    size_t size;
+  };
+  XzLookInStream callbacks;
+  callbacks.Look = &XzLookInStream::LookImpl;
+  callbacks.Skip = &XzLookInStream::SkipImpl;
+  callbacks.Read = &XzLookInStream::ReadImpl;
+  callbacks.Seek = &XzLookInStream::SeekImpl;
+  callbacks.Progress = &XzLookInStream::ProgressImpl;
+  callbacks.offset = 0;
+  callbacks.data = compressed_data.get();
+  callbacks.size = compressed_size_;
+
+  // Iterate over the internal XZ blocks without decompressing them.
+  CXzs xzs;
+  Xzs_Construct(&xzs);
+  Int64 end_offset = compressed_size_;
+  if (Xzs_ReadBackward(&xzs, &callbacks, &end_offset, &callbacks, &alloc) == SZ_OK) {
+    blocks_.reserve(Xzs_GetNumBlocks(&xzs));
+    size_t dst_offset = 0;
+    for (int s = xzs.num - 1; s >= 0; s--) {
+      const CXzStream& stream = xzs.streams[s];
+      size_t src_offset = stream.startOffset + XZ_STREAM_HEADER_SIZE;
+      for (size_t b = 0; b < stream.numBlocks; b++) {
+        const CXzBlockSizes& block = stream.blocks[b];
+        blocks_.push_back(XzBlock{
+            .decompressed_data = nullptr,  // Lazy allocation and decompression.
+            .decompressed_size = static_cast<uint32_t>(block.unpackSize),
+            .compressed_offset = static_cast<uint32_t>(src_offset),
+            .compressed_size = static_cast<uint32_t>((block.totalSize + 3) & ~3u),
+            .stream_flags = stream.flags,
+        });
+        dst_offset += blocks_.back().decompressed_size;
+        src_offset += blocks_.back().compressed_size;
+      }
+    }
+    size_ = dst_offset;
+    total_size_ += dst_offset;
+  }
+  Xzs_Free(&xzs, &alloc);
+  return !blocks_.empty();
+}
+
+bool MemoryXz::Decompress(XzBlock* block) {
+  static ISzAlloc alloc;
+  alloc.Alloc = [](ISzAllocPtr, size_t size) { return malloc(size); };
+  alloc.Free = [](ISzAllocPtr, void* ptr) { return free(ptr); };
+
+  // Read the compressed data for this block.
+  std::unique_ptr<uint8_t[]> compressed_data(new (std::nothrow) uint8_t[block->compressed_size]);
+  if (compressed_data.get() == nullptr) {
+    return false;
+  }
+  if (!compressed_memory_->ReadFully(compressed_addr_ + block->compressed_offset,
+                                     compressed_data.get(), block->compressed_size)) {
+    return false;
+  }
+
+  // Allocate decompressed memory.
+  std::unique_ptr<uint8_t[]> decompressed_data(new uint8_t[block->decompressed_size]);
+  if (decompressed_data == nullptr) {
+    return false;
+  }
+
+  // Decompress.
+  CXzUnpacker state{};
+  XzUnpacker_Construct(&state, &alloc);
+  state.streamFlags = block->stream_flags;
+  XzUnpacker_PrepareToRandomBlockDecoding(&state);
+  size_t decompressed_size = block->decompressed_size;
+  size_t compressed_size = block->compressed_size;
+  ECoderStatus status;
+  XzUnpacker_SetOutBuf(&state, decompressed_data.get(), decompressed_size);
+  int return_val =
+      XzUnpacker_Code(&state, /*decompressed_data=*/nullptr, &decompressed_size,
+                      compressed_data.get(), &compressed_size, true, CODER_FINISH_END, &status);
+  XzUnpacker_Free(&state);
+  if (return_val != SZ_OK || status != CODER_STATUS_FINISHED_WITH_MARK) {
+    log(0, "Can not decompress \"%s\"", name_.c_str());
+    return false;
+  }
+
+  used_ += block->decompressed_size;
+  total_used_ += block->decompressed_size;
+  if (kLogMemoryXzUsage) {
+    log(0, "decompressed memory: %zi%% of %ziKB (%zi files), %i%% of %iKB (%s)",
+        100 * total_used_ / total_size_, total_size_ / 1024, total_open_.load(),
+        100 * used_ / size_, size_ / 1024, name_.c_str());
+  }
+
+  block->decompressed_data = std::move(decompressed_data);
+  return true;
+}
+
 }  // namespace unwindstack
diff --git a/libunwindstack/MemoryBuffer.h b/libunwindstack/MemoryBuffer.h
index a5b5743..24609f4 100644
--- a/libunwindstack/MemoryBuffer.h
+++ b/libunwindstack/MemoryBuffer.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_MEMORY_BUFFER_H
+#define _LIBUNWINDSTACK_MEMORY_BUFFER_H
 
 #include <stdint.h>
 
@@ -55,3 +56,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_MEMORY_BUFFER_H
diff --git a/libunwindstack/MemoryCache.h b/libunwindstack/MemoryCache.h
index de5e9a0..523a4a1 100644
--- a/libunwindstack/MemoryCache.h
+++ b/libunwindstack/MemoryCache.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_MEMORY_CACHE_H
+#define _LIBUNWINDSTACK_MEMORY_CACHE_H
 
 #include <pthread.h>
 #include <stdint.h>
@@ -90,3 +91,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_MEMORY_CACHE_H
diff --git a/libunwindstack/MemoryFileAtOffset.h b/libunwindstack/MemoryFileAtOffset.h
index 90cf00b..9949f26 100644
--- a/libunwindstack/MemoryFileAtOffset.h
+++ b/libunwindstack/MemoryFileAtOffset.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_MEMORY_FILE_AT_OFFSET_H
+#define _LIBUNWINDSTACK_MEMORY_FILE_AT_OFFSET_H
 
 #include <stdint.h>
 
@@ -44,3 +45,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_MEMORY_FILE_AT_OFFSET_H
diff --git a/libunwindstack/MemoryLocal.h b/libunwindstack/MemoryLocal.h
index f98c9cb..a5c7a48 100644
--- a/libunwindstack/MemoryLocal.h
+++ b/libunwindstack/MemoryLocal.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_MEMORY_LOCAL_H
+#define _LIBUNWINDSTACK_MEMORY_LOCAL_H
 
 #include <stdint.h>
 
@@ -32,3 +33,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_MEMORY_LOCAL_H
diff --git a/libunwindstack/MemoryMte.cpp b/libunwindstack/MemoryMte.cpp
index 3841744..679f413 100644
--- a/libunwindstack/MemoryMte.cpp
+++ b/libunwindstack/MemoryMte.cpp
@@ -17,10 +17,8 @@
 #include <sys/ptrace.h>
 #include <sys/uio.h>
 
-#if defined(__BIONIC__)
+#ifdef __BIONIC__
 #include <bionic/mte.h>
-#else
-#define mte_supported() false
 #endif
 
 #include "MemoryLocal.h"
@@ -29,7 +27,7 @@
 namespace unwindstack {
 
 long MemoryRemote::ReadTag(uint64_t addr) {
-#if defined(PTRACE_PEEKMTETAGS) || defined(PT_PEEKMTETAGS)
+#if defined(__aarch64__)
   char tag;
   iovec iov = {&tag, 1};
   if (ptrace(PTRACE_PEEKMTETAGS, pid_, reinterpret_cast<void*>(addr), &iov) != 0 ||
diff --git a/libunwindstack/MemoryOffline.h b/libunwindstack/MemoryOffline.h
index 024e111..789f1a2 100644
--- a/libunwindstack/MemoryOffline.h
+++ b/libunwindstack/MemoryOffline.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_MEMORY_OFFLINE_H
+#define _LIBUNWINDSTACK_MEMORY_OFFLINE_H
 
 #include <stdint.h>
 
@@ -35,8 +36,6 @@
 
   bool Init(const std::string& file, uint64_t offset);
 
-  bool Init(const std::string& file, uint64_t offset, uint64_t start, uint64_t size);
-
   size_t Read(uint64_t addr, void* dst, size_t size) override;
 
  private:
@@ -57,3 +56,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_MEMORY_OFFLINE_H
diff --git a/libunwindstack/MemoryOfflineBuffer.h b/libunwindstack/MemoryOfflineBuffer.h
index d77008e..64c49a1 100644
--- a/libunwindstack/MemoryOfflineBuffer.h
+++ b/libunwindstack/MemoryOfflineBuffer.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_MEMORY_OFFLINE_BUFFER_H
+#define _LIBUNWINDSTACK_MEMORY_OFFLINE_BUFFER_H
 
 #include <stdint.h>
 
@@ -38,3 +39,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_MEMORY_OFFLINE_BUFFER_H
diff --git a/libunwindstack/MemoryRange.h b/libunwindstack/MemoryRange.h
index b789ee3..3b4ab5c 100644
--- a/libunwindstack/MemoryRange.h
+++ b/libunwindstack/MemoryRange.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_MEMORY_RANGE_H
+#define _LIBUNWINDSTACK_MEMORY_RANGE_H
 
 #include <stdint.h>
 
@@ -52,7 +53,7 @@
   MemoryRanges() = default;
   virtual ~MemoryRanges() = default;
 
-  bool Insert(MemoryRange* memory);
+  void Insert(MemoryRange* memory);
 
   size_t Read(uint64_t addr, void* dst, size_t size) override;
 
@@ -61,3 +62,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_MEMORY_RANGE_H
diff --git a/libunwindstack/MemoryRemote.h b/libunwindstack/MemoryRemote.h
index 563e5b7..dd09c88 100644
--- a/libunwindstack/MemoryRemote.h
+++ b/libunwindstack/MemoryRemote.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_MEMORY_REMOTE_H
+#define _LIBUNWINDSTACK_MEMORY_REMOTE_H
 
 #include <stdint.h>
 #include <sys/types.h>
@@ -41,3 +42,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_MEMORY_REMOTE_H
diff --git a/libunwindstack/MemoryXz.cpp b/libunwindstack/MemoryXz.cpp
deleted file mode 100644
index 9e91a07..0000000
--- a/libunwindstack/MemoryXz.cpp
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Copyright (C) 2021 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 <stdlib.h>
-#include <string.h>
-
-#include <algorithm>
-#include <atomic>
-#include <memory>
-#include <mutex>
-#include <string>
-#include <utility>
-
-#include <7zCrc.h>
-#include <Xz.h>
-#include <XzCrc64.h>
-
-#include <unwindstack/Log.h>
-
-#include "MemoryXz.h"
-
-namespace unwindstack {
-
-// Statistics (used only for optional debug log messages).
-static constexpr bool kLogMemoryXzUsage = false;
-std::atomic_size_t MemoryXz::total_used_ = 0;
-std::atomic_size_t MemoryXz::total_size_ = 0;
-std::atomic_size_t MemoryXz::total_open_ = 0;
-
-MemoryXz::MemoryXz(Memory* memory, uint64_t addr, uint64_t size, const std::string& name)
-    : compressed_memory_(memory), compressed_addr_(addr), compressed_size_(size), name_(name) {
-  total_open_ += 1;
-}
-
-bool MemoryXz::Init() {
-  static std::once_flag crc_initialized;
-  std::call_once(crc_initialized, []() {
-    CrcGenerateTable();
-    Crc64GenerateTable();
-  });
-  if (compressed_size_ >= kMaxCompressedSize) {
-    return false;
-  }
-  if (!ReadBlocks()) {
-    return false;
-  }
-
-  // All blocks (except the last one) must have the same power-of-2 size.
-  if (blocks_.size() > 1) {
-    size_t block_size_log2 = __builtin_ctz(blocks_.front().decompressed_size);
-    auto correct_size = [=](XzBlock& b) { return b.decompressed_size == (1 << block_size_log2); };
-    if (std::all_of(blocks_.begin(), std::prev(blocks_.end()), correct_size) &&
-        blocks_.back().decompressed_size <= (1 << block_size_log2)) {
-      block_size_log2_ = block_size_log2;
-    } else {
-      // Inconsistent block-sizes.  Decompress and merge everything now.
-      std::unique_ptr<uint8_t[]> data(new uint8_t[size_]);
-      size_t offset = 0;
-      for (XzBlock& block : blocks_) {
-        if (!Decompress(&block)) {
-          return false;
-        }
-        memcpy(data.get() + offset, block.decompressed_data.get(), block.decompressed_size);
-        offset += block.decompressed_size;
-      }
-      blocks_.clear();
-      blocks_.push_back(XzBlock{
-          .decompressed_data = std::move(data),
-          .decompressed_size = size_,
-      });
-      block_size_log2_ = 31;  // Because 32 bits is too big (shift right by 32 is not allowed).
-    }
-  }
-
-  return true;
-}
-
-MemoryXz::~MemoryXz() {
-  total_used_ -= used_;
-  total_size_ -= size_;
-  total_open_ -= 1;
-}
-
-size_t MemoryXz::Read(uint64_t addr, void* buffer, size_t size) {
-  if (addr >= size_) {
-    return 0;  // Read past the end.
-  }
-  uint8_t* dst = reinterpret_cast<uint8_t*>(buffer);  // Position in the output buffer.
-  for (size_t i = addr >> block_size_log2_; i < blocks_.size(); i++) {
-    XzBlock* block = &blocks_[i];
-    if (block->decompressed_data == nullptr) {
-      if (!Decompress(block)) {
-        break;
-      }
-    }
-    size_t offset = (addr - (i << block_size_log2_));  // Start inside the block.
-    size_t copy_bytes = std::min<size_t>(size, block->decompressed_size - offset);
-    memcpy(dst, block->decompressed_data.get() + offset, copy_bytes);
-    dst += copy_bytes;
-    addr += copy_bytes;
-    size -= copy_bytes;
-    if (size == 0) {
-      break;
-    }
-  }
-  return dst - reinterpret_cast<uint8_t*>(buffer);
-}
-
-bool MemoryXz::ReadBlocks() {
-  static ISzAlloc alloc;
-  alloc.Alloc = [](ISzAllocPtr, size_t size) { return malloc(size); };
-  alloc.Free = [](ISzAllocPtr, void* ptr) { return free(ptr); };
-
-  // Read the compressed data, so we can quickly scan through the headers.
-  std::unique_ptr<uint8_t[]> compressed_data(new (std::nothrow) uint8_t[compressed_size_]);
-  if (compressed_data.get() == nullptr) {
-    return false;
-  }
-  if (!compressed_memory_->ReadFully(compressed_addr_, compressed_data.get(), compressed_size_)) {
-    return false;
-  }
-
-  // Implement the required interface for communication
-  // (written in C so we can not use virtual methods or member functions).
-  struct XzLookInStream : public ILookInStream, public ICompressProgress {
-    static SRes LookImpl(const ILookInStream* p, const void** buf, size_t* size) {
-      auto* ctx = reinterpret_cast<const XzLookInStream*>(p);
-      *buf = ctx->data + ctx->offset;
-      *size = std::min(*size, ctx->size - ctx->offset);
-      return SZ_OK;
-    }
-    static SRes SkipImpl(const ILookInStream* p, size_t len) {
-      auto* ctx = reinterpret_cast<XzLookInStream*>(const_cast<ILookInStream*>(p));
-      ctx->offset += len;
-      return SZ_OK;
-    }
-    static SRes ReadImpl(const ILookInStream* p, void* buf, size_t* size) {
-      auto* ctx = reinterpret_cast<const XzLookInStream*>(p);
-      *size = std::min(*size, ctx->size - ctx->offset);
-      memcpy(buf, ctx->data + ctx->offset, *size);
-      return SZ_OK;
-    }
-    static SRes SeekImpl(const ILookInStream* p, Int64* pos, ESzSeek origin) {
-      auto* ctx = reinterpret_cast<XzLookInStream*>(const_cast<ILookInStream*>(p));
-      switch (origin) {
-        case SZ_SEEK_SET:
-          ctx->offset = *pos;
-          break;
-        case SZ_SEEK_CUR:
-          ctx->offset += *pos;
-          break;
-        case SZ_SEEK_END:
-          ctx->offset = ctx->size + *pos;
-          break;
-      }
-      *pos = ctx->offset;
-      return SZ_OK;
-    }
-    static SRes ProgressImpl(const ICompressProgress*, UInt64, UInt64) { return SZ_OK; }
-    size_t offset;
-    uint8_t* data;
-    size_t size;
-  };
-  XzLookInStream callbacks;
-  callbacks.Look = &XzLookInStream::LookImpl;
-  callbacks.Skip = &XzLookInStream::SkipImpl;
-  callbacks.Read = &XzLookInStream::ReadImpl;
-  callbacks.Seek = &XzLookInStream::SeekImpl;
-  callbacks.Progress = &XzLookInStream::ProgressImpl;
-  callbacks.offset = 0;
-  callbacks.data = compressed_data.get();
-  callbacks.size = compressed_size_;
-
-  // Iterate over the internal XZ blocks without decompressing them.
-  CXzs xzs;
-  Xzs_Construct(&xzs);
-  Int64 end_offset = compressed_size_;
-  if (Xzs_ReadBackward(&xzs, &callbacks, &end_offset, &callbacks, &alloc) == SZ_OK) {
-    blocks_.reserve(Xzs_GetNumBlocks(&xzs));
-    size_t dst_offset = 0;
-    for (int s = xzs.num - 1; s >= 0; s--) {
-      const CXzStream& stream = xzs.streams[s];
-      size_t src_offset = stream.startOffset + XZ_STREAM_HEADER_SIZE;
-      for (size_t b = 0; b < stream.numBlocks; b++) {
-        const CXzBlockSizes& block = stream.blocks[b];
-        blocks_.push_back(XzBlock{
-            .decompressed_data = nullptr,  // Lazy allocation and decompression.
-            .decompressed_size = static_cast<uint32_t>(block.unpackSize),
-            .compressed_offset = static_cast<uint32_t>(src_offset),
-            .compressed_size = static_cast<uint32_t>((block.totalSize + 3) & ~3u),
-            .stream_flags = stream.flags,
-        });
-        dst_offset += blocks_.back().decompressed_size;
-        src_offset += blocks_.back().compressed_size;
-      }
-    }
-    size_ = dst_offset;
-    total_size_ += dst_offset;
-  }
-  Xzs_Free(&xzs, &alloc);
-  return !blocks_.empty();
-}
-
-bool MemoryXz::Decompress(XzBlock* block) {
-  static ISzAlloc alloc;
-  alloc.Alloc = [](ISzAllocPtr, size_t size) { return malloc(size); };
-  alloc.Free = [](ISzAllocPtr, void* ptr) { return free(ptr); };
-
-  // Read the compressed data for this block.
-  std::unique_ptr<uint8_t[]> compressed_data(new (std::nothrow) uint8_t[block->compressed_size]);
-  if (compressed_data.get() == nullptr) {
-    return false;
-  }
-  if (!compressed_memory_->ReadFully(compressed_addr_ + block->compressed_offset,
-                                     compressed_data.get(), block->compressed_size)) {
-    return false;
-  }
-
-  // Allocate decompressed memory.
-  std::unique_ptr<uint8_t[]> decompressed_data(new uint8_t[block->decompressed_size]);
-  if (decompressed_data == nullptr) {
-    return false;
-  }
-
-  // Decompress.
-  CXzUnpacker state{};
-  XzUnpacker_Construct(&state, &alloc);
-  state.streamFlags = block->stream_flags;
-  XzUnpacker_PrepareToRandomBlockDecoding(&state);
-  size_t decompressed_size = block->decompressed_size;
-  size_t compressed_size = block->compressed_size;
-  ECoderStatus status;
-  XzUnpacker_SetOutBuf(&state, decompressed_data.get(), decompressed_size);
-  int return_val =
-      XzUnpacker_Code(&state, /*decompressed_data=*/nullptr, &decompressed_size,
-                      compressed_data.get(), &compressed_size, true, CODER_FINISH_END, &status);
-  XzUnpacker_Free(&state);
-  if (return_val != SZ_OK || status != CODER_STATUS_FINISHED_WITH_MARK) {
-    Log::Error("Cannot decompress \"%s\"", name_.c_str());
-    return false;
-  }
-
-  used_ += block->decompressed_size;
-  total_used_ += block->decompressed_size;
-  if (kLogMemoryXzUsage) {
-    Log::Info("decompressed memory: %zi%% of %ziKB (%zi files), %i%% of %iKB (%s)",
-              100 * total_used_ / total_size_, total_size_ / 1024, total_open_.load(),
-              100 * used_ / size_, size_ / 1024, name_.c_str());
-  }
-
-  block->decompressed_data = std::move(decompressed_data);
-  return true;
-}
-
-}  // namespace unwindstack
diff --git a/libunwindstack/MemoryXz.h b/libunwindstack/MemoryXz.h
index 57bf6c5..c72ba88 100644
--- a/libunwindstack/MemoryXz.h
+++ b/libunwindstack/MemoryXz.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_MEMORY_XZ_H
+#define _LIBUNWINDSTACK_MEMORY_XZ_H
 
 #include <atomic>
 #include <memory>
@@ -70,3 +71,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_MEMORY_XZ_H
diff --git a/libunwindstack/Regs.cpp b/libunwindstack/Regs.cpp
index 08a35ea..03aa6c2 100644
--- a/libunwindstack/Regs.cpp
+++ b/libunwindstack/Regs.cpp
@@ -18,7 +18,6 @@
 #include <sys/ptrace.h>
 #include <sys/uio.h>
 
-#include <algorithm>
 #include <vector>
 
 #include <unwindstack/Elf.h>
@@ -26,26 +25,27 @@
 #include <unwindstack/Regs.h>
 #include <unwindstack/RegsArm.h>
 #include <unwindstack/RegsArm64.h>
+#include <unwindstack/RegsMips.h>
+#include <unwindstack/RegsMips64.h>
 #include <unwindstack/RegsX86.h>
 #include <unwindstack/RegsX86_64.h>
 #include <unwindstack/UserArm.h>
 #include <unwindstack/UserArm64.h>
+#include <unwindstack/UserMips.h>
+#include <unwindstack/UserMips64.h>
 #include <unwindstack/UserX86.h>
 #include <unwindstack/UserX86_64.h>
 
 namespace unwindstack {
 
 // The largest user structure.
-// constexpr size_t MAX_USER_REGS_SIZE = sizeof(mips64_user_regs) + 10;
-static constexpr size_t kMaxUserRegsSize = std::max(
-    sizeof(arm_user_regs),
-    std::max(sizeof(arm64_user_regs), std::max(sizeof(x86_user_regs), sizeof(x86_64_user_regs))));
+constexpr size_t MAX_USER_REGS_SIZE = sizeof(mips64_user_regs) + 10;
 
 // This function assumes that reg_data is already aligned to a 64 bit value.
 // If not this could crash with an unaligned access.
 Regs* Regs::RemoteGet(pid_t pid) {
   // Make the buffer large enough to contain the largest registers type.
-  std::vector<uint64_t> buffer(kMaxUserRegsSize / sizeof(uint64_t));
+  std::vector<uint64_t> buffer(MAX_USER_REGS_SIZE / sizeof(uint64_t));
   struct iovec io;
   io.iov_base = buffer.data();
   io.iov_len = buffer.size() * sizeof(uint64_t);
@@ -54,7 +54,6 @@
     return nullptr;
   }
 
-  // Infer the process architecture from the size of its register structure.
   switch (io.iov_len) {
   case sizeof(x86_user_regs):
     return RegsX86::Read(buffer.data());
@@ -64,35 +63,14 @@
     return RegsArm::Read(buffer.data());
   case sizeof(arm64_user_regs):
     return RegsArm64::Read(buffer.data());
+  case sizeof(mips_user_regs):
+    return RegsMips::Read(buffer.data());
+  case sizeof(mips64_user_regs):
+    return RegsMips64::Read(buffer.data());
   }
   return nullptr;
 }
 
-ArchEnum Regs::RemoteGetArch(pid_t pid) {
-  // Make the buffer large enough to contain the largest registers type.
-  std::vector<uint64_t> buffer(kMaxUserRegsSize / sizeof(uint64_t));
-  struct iovec io;
-  io.iov_base = buffer.data();
-  io.iov_len = buffer.size() * sizeof(uint64_t);
-
-  if (ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, reinterpret_cast<void*>(&io)) == -1) {
-    return ARCH_UNKNOWN;
-  }
-
-  // Infer the process architecture from the size of its register structure.
-  switch (io.iov_len) {
-    case sizeof(x86_user_regs):
-      return ARCH_X86;
-    case sizeof(x86_64_user_regs):
-      return ARCH_X86_64;
-    case sizeof(arm_user_regs):
-      return ARCH_ARM;
-    case sizeof(arm64_user_regs):
-      return ARCH_ARM64;
-  }
-  return ARCH_UNKNOWN;
-}
-
 Regs* Regs::CreateFromUcontext(ArchEnum arch, void* ucontext) {
   switch (arch) {
     case ARCH_X86:
@@ -103,6 +81,11 @@
       return RegsArm::CreateFromUcontext(ucontext);
     case ARCH_ARM64:
       return RegsArm64::CreateFromUcontext(ucontext);
+    case ARCH_MIPS:
+      return RegsMips::CreateFromUcontext(ucontext);
+    case ARCH_MIPS64:
+      return RegsMips64::CreateFromUcontext(ucontext);
+    case ARCH_UNKNOWN:
     default:
       return nullptr;
   }
diff --git a/libunwindstack/RegsInfo.h b/libunwindstack/RegsInfo.h
index 28b297e..e445a91 100644
--- a/libunwindstack/RegsInfo.h
+++ b/libunwindstack/RegsInfo.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_REGS_INFO_H
+#define _LIBUNWINDSTACK_REGS_INFO_H
 
 #include <stdint.h>
 
@@ -63,3 +64,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_REGS_INFO_H
diff --git a/libunwindstack/Symbols.h b/libunwindstack/Symbols.h
index 0b46751..c1967b0 100644
--- a/libunwindstack/Symbols.h
+++ b/libunwindstack/Symbols.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_SYMBOLS_H
+#define _LIBUNWINDSTACK_SYMBOLS_H
 
 #include <stdint.h>
 
@@ -74,3 +75,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_SYMBOLS_H
diff --git a/libunwindstack/TEST_MAPPING b/libunwindstack/TEST_MAPPING
index 2ebaeac..0c73ff9 100644
--- a/libunwindstack/TEST_MAPPING
+++ b/libunwindstack/TEST_MAPPING
@@ -12,11 +12,5 @@
     {
       "name": "CtsPerfettoTestCases"
     }
-  ],
-
-  "hwasan-postsubmit": [
-    {
-      "name": "libunwindstack_unit_test"
-    }
   ]
 }
diff --git a/libunwindstack/ThreadEntry.cpp b/libunwindstack/ThreadEntry.cpp
index db34df0..86912a2 100644
--- a/libunwindstack/ThreadEntry.cpp
+++ b/libunwindstack/ThreadEntry.cpp
@@ -75,12 +75,12 @@
 }
 
 bool ThreadEntry::Wait(WaitType type) {
-  static const std::chrono::duration wait_time(std::chrono::seconds(10));
+  static const std::chrono::duration wait_time(std::chrono::seconds(5));
   std::unique_lock<std::mutex> lock(wait_mutex_);
   if (wait_cond_.wait_for(lock, wait_time, [this, type] { return wait_value_ == type; })) {
     return true;
   } else {
-    Log::AsyncSafe("pthread_cond_timedwait for value %d failed", type);
+    log_async_safe("pthread_cond_timedwait for value %d failed", type);
     return false;
   }
 }
diff --git a/libunwindstack/ThreadEntry.h b/libunwindstack/ThreadEntry.h
index 2f8e88d..1caba83 100644
--- a/libunwindstack/ThreadEntry.h
+++ b/libunwindstack/ThreadEntry.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_THREAD_ENTRY_H
+#define _LIBUNWINDSTACK_THREAD_ENTRY_H
 
 #include <pthread.h>
 #include <sys/types.h>
@@ -73,3 +74,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_THREAD_ENTRY_H
diff --git a/libunwindstack/ThreadUnwinder.cpp b/libunwindstack/ThreadUnwinder.cpp
index 7b45261..a04a997 100644
--- a/libunwindstack/ThreadUnwinder.cpp
+++ b/libunwindstack/ThreadUnwinder.cpp
@@ -39,7 +39,7 @@
 static void SignalLogOnly(int, siginfo_t*, void*) {
   android::base::ErrnoRestorer restore;
 
-  Log::AsyncSafe("pid %d, tid %d: Received a spurious thread signal\n", getpid(),
+  log_async_safe("pid %d, tid %d: Received a spurious thread signal\n", getpid(),
                  static_cast<int>(android::base::GetThreadId()));
 }
 
@@ -65,17 +65,13 @@
     entry->Wake();
   } else {
     // At this point, it is possible that entry has been freed, so just exit.
-    Log::AsyncSafe("Timed out waiting for unwind thread to indicate it completed.");
+    log_async_safe("Timed out waiting for unwind thread to indicate it completed.");
   }
 }
 
 ThreadUnwinder::ThreadUnwinder(size_t max_frames, Maps* maps)
     : UnwinderFromPid(max_frames, getpid(), Regs::CurrentArch(), maps) {}
 
-ThreadUnwinder::ThreadUnwinder(size_t max_frames, Maps* maps,
-                               std::shared_ptr<Memory>& process_memory)
-    : UnwinderFromPid(max_frames, getpid(), Regs::CurrentArch(), maps, process_memory) {}
-
 ThreadUnwinder::ThreadUnwinder(size_t max_frames, const ThreadUnwinder* unwinder)
     : UnwinderFromPid(max_frames, getpid(), Regs::CurrentArch()) {
   process_memory_ = unwinder->process_memory_;
@@ -96,7 +92,7 @@
   struct sigaction old_action = {};
   sigemptyset(&new_action.sa_mask);
   if (sigaction(signal, &new_action, &old_action) != 0) {
-    Log::AsyncSafe("sigaction failed: %s", strerror(errno));
+    log_async_safe("sigaction failed: %s", strerror(errno));
     ThreadEntry::Remove(entry);
     last_error_.code = ERROR_SYSTEM_CALL;
     return nullptr;
@@ -141,7 +137,7 @@
     last_error_.code = ERROR_THREAD_DOES_NOT_EXIST;
   } else {
     last_error_.code = ERROR_THREAD_TIMEOUT;
-    Log::AsyncSafe("Timed out waiting for signal handler to get ucontext data.");
+    log_async_safe("Timed out waiting for signal handler to get ucontext data.");
   }
 
   ThreadEntry::Remove(entry);
@@ -149,11 +145,11 @@
   return nullptr;
 }
 
-void ThreadUnwinder::UnwindWithSignal(int signal, pid_t tid, std::unique_ptr<Regs>* initial_regs,
+void ThreadUnwinder::UnwindWithSignal(int signal, pid_t tid,
                                       const std::vector<std::string>* initial_map_names_to_skip,
                                       const std::vector<std::string>* map_suffixes_to_ignore) {
   ClearErrors();
-  if (tid == static_cast<pid_t>(android::base::GetThreadId())) {
+  if (tid == pid_) {
     last_error_.code = ERROR_UNSUPPORTED;
     return;
   }
@@ -168,9 +164,6 @@
   }
 
   std::unique_ptr<Regs> regs(Regs::CreateFromUcontext(Regs::CurrentArch(), entry->GetUcontext()));
-  if (initial_regs != nullptr) {
-    initial_regs->reset(regs->Clone());
-  }
   SetRegs(regs.get());
   UnwinderFromPid::Unwind(initial_map_names_to_skip, map_suffixes_to_ignore);
 
@@ -180,7 +173,7 @@
   // Wait for the thread to indicate it is done with the ThreadEntry.
   if (!entry->Wait(WAIT_FOR_THREAD_TO_RESTART)) {
     // Send a warning, but do not mark as a failure to unwind.
-    Log::AsyncSafe("Timed out waiting for signal handler to indicate it finished.");
+    log_async_safe("Timed out waiting for signal handler to indicate it finished.");
   }
 
   ThreadEntry::Remove(entry);
diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp
index facff86..bd34465 100644
--- a/libunwindstack/Unwinder.cpp
+++ b/libunwindstack/Unwinder.cpp
@@ -24,10 +24,9 @@
 #include <unistd.h>
 
 #include <algorithm>
-#include <memory>
 
-#include <android-base/file.h>
 #include <android-base/stringprintf.h>
+#include <android-base/strings.h>
 
 #include <unwindstack/DexFiles.h>
 #include <unwindstack/Elf.h>
@@ -61,12 +60,21 @@
   frame->pc = dex_pc;
   frame->sp = regs_->sp();
 
-  frame->map_info = maps_->Find(dex_pc);
-  if (frame->map_info != nullptr) {
-    frame->rel_pc = dex_pc - frame->map_info->start();
-    // Initialize the load bias for this map so subsequent calls
-    // to GetLoadBias() will always return data.
-    frame->map_info->set_load_bias(0);
+  MapInfo* info = maps_->Find(dex_pc);
+  if (info != nullptr) {
+    frame->map_start = info->start();
+    frame->map_end = info->end();
+    // Since this is a dex file frame, the elf_start_offset is not set
+    // by any of the normal code paths. Use the offset of the map since
+    // that matches the actual offset.
+    frame->map_elf_start_offset = info->offset();
+    frame->map_exact_offset = info->offset();
+    frame->map_load_bias = info->load_bias();
+    frame->map_flags = info->flags();
+    if (resolve_names_) {
+      frame->map_name = info->name();
+    }
+    frame->rel_pc = dex_pc - info->start();
   } else {
     frame->rel_pc = dex_pc;
     warnings_ |= WARNING_DEX_PC_NOT_IN_MAP;
@@ -86,7 +94,7 @@
 #endif
 }
 
-FrameData* Unwinder::FillInFrame(std::shared_ptr<MapInfo>& map_info, Elf* /*elf*/, uint64_t rel_pc,
+FrameData* Unwinder::FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc,
                                  uint64_t pc_adjustment) {
   size_t frame_num = frames_.size();
   frames_.resize(frame_num + 1);
@@ -101,8 +109,25 @@
     return nullptr;
   }
 
-  frame->map_info = map_info;
-
+  if (resolve_names_) {
+    frame->map_name = map_info->name();
+    if (embedded_soname_ && map_info->elf_start_offset() != 0 && !frame->map_name.empty()) {
+      std::string soname = elf->GetSoname();
+      if (!soname.empty()) {
+        std::string map_with_soname;
+        map_with_soname += frame->map_name;
+        map_with_soname += '!';
+        map_with_soname += soname;
+        frame->map_name = SharedString(std::move(map_with_soname));
+      }
+    }
+  }
+  frame->map_elf_start_offset = map_info->elf_start_offset();
+  frame->map_exact_offset = map_info->offset();
+  frame->map_start = map_info->start();
+  frame->map_end = map_info->end();
+  frame->map_flags = map_info->flags();
+  frame->map_load_bias = elf->GetLoadBias();
   return frame;
 }
 
@@ -126,6 +151,7 @@
   ClearErrors();
 
   frames_.clear();
+  elf_from_memory_not_file_ = false;
 
   // Clear any cached data from previous unwinds.
   process_memory_->Clear();
@@ -140,32 +166,30 @@
     uint64_t cur_pc = regs_->pc();
     uint64_t cur_sp = regs_->sp();
 
-    std::shared_ptr<MapInfo> map_info = maps_->Find(regs_->pc());
+    MapInfo* map_info = maps_->Find(regs_->pc());
     uint64_t pc_adjustment = 0;
     uint64_t step_pc;
     uint64_t rel_pc;
     Elf* elf;
-    bool ignore_frame = false;
     if (map_info == nullptr) {
       step_pc = regs_->pc();
       rel_pc = step_pc;
-      // If we get invalid map via return_address_attempt, don't hide error for the previous frame.
-      if (!return_address_attempt || last_error_.code == ERROR_NONE) {
-        last_error_.code = ERROR_INVALID_MAP;
-        last_error_.address = step_pc;
-      }
+      last_error_.code = ERROR_INVALID_MAP;
       elf = nullptr;
     } else {
-      ignore_frame =
-          initial_map_names_to_skip != nullptr &&
-          std::find(initial_map_names_to_skip->begin(), initial_map_names_to_skip->end(),
-                    android::base::Basename(map_info->name())) != initial_map_names_to_skip->end();
-      if (!ignore_frame && ShouldStop(map_suffixes_to_ignore, map_info->name())) {
+      if (ShouldStop(map_suffixes_to_ignore, map_info->name())) {
         break;
       }
       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.
+      const std::string& map_name = map_info->name();
+      if (!elf_from_memory_not_file_ && map_info->memory_backed_elf() && !map_name.empty() &&
+          map_name[0] != '[' && !android::base::StartsWith(map_name, "/memfd:")) {
+        elf_from_memory_not_file_ = true;
+      }
       step_pc = regs_->pc();
-      rel_pc = elf->GetRelPc(step_pc, map_info.get());
+      rel_pc = elf->GetRelPc(step_pc, map_info);
       // Everyone except elf data in gdb jit debug maps uses the relative pc.
       if (!(map_info->flags() & MAPS_FLAGS_JIT_SYMFILE_MAP)) {
         step_pc = rel_pc;
@@ -191,7 +215,9 @@
     }
 
     FrameData* frame = nullptr;
-    if (!ignore_frame) {
+    if (map_info == nullptr || initial_map_names_to_skip == nullptr ||
+        std::find(initial_map_names_to_skip->begin(), initial_map_names_to_skip->end(),
+                  basename(map_info->name().c_str())) == initial_map_names_to_skip->end()) {
       if (regs_->dex_pc() != 0) {
         // Add a frame to represent the dex file.
         FillInDexFrame();
@@ -222,7 +248,7 @@
         // some of the speculative frames.
         in_device_map = true;
       } else {
-        auto sp_info = maps_->Find(regs_->sp());
+        MapInfo* sp_info = maps_->Find(regs_->sp());
         if (sp_info != nullptr && sp_info->flags() & MAPS_FLAGS_DEVICE_MAP) {
           // Do not stop here, fall through in case we are
           // in the speculative unwind path and need to remove
@@ -299,30 +325,25 @@
 }
 
 std::string Unwinder::FormatFrame(const FrameData& frame) const {
-  return FormatFrame(arch_, frame, display_build_id_);
-}
-
-std::string Unwinder::FormatFrame(ArchEnum arch, const FrameData& frame, bool display_build_id) {
   std::string data;
-  if (ArchIs32Bit(arch)) {
+  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);
   }
 
-  auto map_info = frame.map_info;
-  if (map_info == nullptr) {
+  if (frame.map_start == frame.map_end) {
     // No valid map associated with this frame.
     data += "  <unknown>";
-  } else if (!map_info->name().empty()) {
+  } else if (!frame.map_name.empty()) {
     data += "  ";
-    data += map_info->GetFullName();
+    data += frame.map_name;
   } else {
-    data += android::base::StringPrintf("  <anonymous:%" PRIx64 ">", map_info->start());
+    data += android::base::StringPrintf("  <anonymous:%" PRIx64 ">", frame.map_start);
   }
 
-  if (map_info != nullptr && map_info->elf_start_offset() != 0) {
-    data += android::base::StringPrintf(" (offset 0x%" PRIx64 ")", map_info->elf_start_offset());
+  if (frame.map_elf_start_offset != 0) {
+    data += android::base::StringPrintf(" (offset 0x%" PRIx64 ")", frame.map_elf_start_offset);
   }
 
   if (!frame.function_name.empty()) {
@@ -341,7 +362,8 @@
     data += ')';
   }
 
-  if (map_info != nullptr && display_build_id) {
+  MapInfo* map_info = maps_->Find(frame.map_start);
+  if (map_info != nullptr && display_build_id_) {
     std::string build_id = map_info->GetPrintableBuildID();
     if (!build_id.empty()) {
       data += " (BuildId: " + build_id + ')';
@@ -354,7 +376,7 @@
   if (frame_num >= frames_.size()) {
     return "";
   }
-  return FormatFrame(arch_, frames_[frame_num], display_build_id_);
+  return FormatFrame(frames_[frame_num]);
 }
 
 void Unwinder::SetJitDebug(JitDebug* jit_debug) {
@@ -424,7 +446,7 @@
                                          bool resolve_names) {
   FrameData frame;
 
-  std::shared_ptr<MapInfo> map_info = maps->Find(pc);
+  MapInfo* map_info = maps->Find(pc);
   if (map_info == nullptr || arch == ARCH_UNKNOWN) {
     frame.pc = pc;
     frame.rel_pc = pc;
@@ -433,7 +455,7 @@
 
   Elf* elf = map_info->GetElf(process_memory, arch);
 
-  uint64_t relative_pc = elf->GetRelPc(pc, map_info.get());
+  uint64_t relative_pc = elf->GetRelPc(pc, map_info);
 
   uint64_t pc_adjustment = GetPcAdjustment(relative_pc, elf, arch);
   relative_pc -= pc_adjustment;
@@ -453,7 +475,13 @@
   // Copy all the things we need into the frame for symbolization.
   frame.rel_pc = relative_pc;
   frame.pc = pc - pc_adjustment;
-  frame.map_info = map_info;
+  frame.map_name = map_info->name();
+  frame.map_elf_start_offset = map_info->elf_start_offset();
+  frame.map_exact_offset = map_info->offset();
+  frame.map_start = map_info->start();
+  frame.map_end = map_info->end();
+  frame.map_flags = map_info->flags();
+  frame.map_load_bias = elf->GetLoadBias();
 
   if (!resolve_names ||
       !elf->GetFunctionName(debug_pc, &frame.function_name, &frame.function_offset)) {
diff --git a/libunwindstack/benchmarks/ElfBenchmark.cpp b/libunwindstack/benchmarks/ElfBenchmark.cpp
index 7bfd9db..3e1e21f 100644
--- a/libunwindstack/benchmarks/ElfBenchmark.cpp
+++ b/libunwindstack/benchmarks/ElfBenchmark.cpp
@@ -47,7 +47,7 @@
 
     unwindstack::Elf elf(file_memory.release());
     if (!elf.Init() || !elf.valid()) {
-      errx(1, "Internal Error: Cannot open elf: %s", elf_file.c_str());
+      errx(1, "Internal Error: Cannot open elf.");
     }
 
     state.PauseTiming();
@@ -73,15 +73,10 @@
 }
 BENCHMARK(BM_elf_create);
 
-void BM_elf_create_large_compressed(benchmark::State& state) {
-  BenchmarkElfCreate(state, GetLargeCompressedFrameElfFile());
+void BM_elf_create_compressed(benchmark::State& state) {
+  BenchmarkElfCreate(state, GetCompressedElfFile());
 }
-BENCHMARK(BM_elf_create_large_compressed);
-
-void BM_elf_create_large_eh_frame(benchmark::State& state) {
-  BenchmarkElfCreate(state, GetLargeEhFrameElfFile());
-}
-BENCHMARK(BM_elf_create_large_eh_frame);
+BENCHMARK(BM_elf_create_compressed);
 
 static void InitializeBuildId(benchmark::State& state, unwindstack::Maps& maps,
                               unwindstack::MapInfo** build_id_map_info) {
diff --git a/libunwindstack/benchmarks/EvalBenchmark.cpp b/libunwindstack/benchmarks/EvalBenchmark.cpp
deleted file mode 100644
index 9b3d1d8..0000000
--- a/libunwindstack/benchmarks/EvalBenchmark.cpp
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (C) 2021 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 <cstdint>
-#include <ios>
-#include <sstream>
-
-#include <benchmark/benchmark.h>
-
-#include <unwindstack/DwarfLocation.h>
-#include <unwindstack/DwarfSection.h>
-
-#include "Utils.h"
-#include "utils/DwarfSectionImplFake.h"
-#include "utils/MemoryFake.h"
-#include "utils/RegsFake.h"
-
-namespace unwindstack {
-namespace {
-
-// This collection of benchmarks exercises the DwarfSectionImpl::Eval function with a set of
-// artificial unwind data. The number of registers and register evaluation method are varied
-// for each individual benchmark.
-
-constexpr int kReturnAddressReg = 5;
-
-template <typename AddresssType>
-class EvalBenchmark : public benchmark::Fixture {
- public:
-  EvalBenchmark() {
-    memory_.Clear();
-    section_ = std::make_unique<DwarfSectionImplFake<AddresssType>>(&memory_);
-  }
-
-  void TearDown(benchmark::State& state) override { mem_tracker_.SetBenchmarkCounters(state); }
-
-  // Benchmarks DwarfSectionImpl::Eval given the DwarfLocation object, loc_regs, initialized in each
-  // individual benchmark macro/function.
-  //
-  // This method initializes the fake register object and the DwarfCie object the same regardless
-  // of the benchmark. So the initialization of loc_regs is carefully crafted in each benchmark
-  // macro so that the evaluated PC and SP match the expected values after each call to Eval in the
-  // benchmarking loop.
-  //
-  // In addition to the Eval call, register value assertion is included in the benchmarking loop
-  // to ensure that we always capture the actual register evaluation
-  // (DwarfSectionImpl::EvalRegister). For example, if Eval is modified to lazily evaluate register
-  // values, we will still capture the register evaluation for the PC and SP (common case) in the
-  // register value assertion.
-  void RunBenchmark(benchmark::State& state, DwarfLocations& loc_regs) {
-    DwarfCie cie{.return_address_register = kReturnAddressReg};
-    bool finished;
-    RegsImplFake<AddresssType> regs(64);
-    regs.set_pc(0x1000);
-    regs.set_sp(0x3500);
-    regs[0] = 0x10000000;
-    mem_tracker_.StartTrackingAllocations();
-    for (auto _ : state) {
-      std::stringstream err_stream;
-      if (!section_->Eval(&cie, &memory_, loc_regs, &regs, &finished)) {
-        err_stream << "Eval() failed at address " << section_->LastErrorAddress();
-        state.SkipWithError(err_stream.str().c_str());
-        return;
-      }
-      if (finished || regs.pc() != 0x60000000U || regs.sp() != 0x10000000U) {
-        err_stream
-            << "Eval() finished successfully but registers were not evaluated correctly."
-            << "\nExpected: finished == false, regs.pc() == 0x60000000, regs.sp() == 0x10000000."
-            << "\nActual: finished == " << std::boolalpha << finished << std::hex
-            << ", regs.pc() == 0x" << regs.pc() << ", regs.sp() == 0x" << regs.sp();
-        state.SkipWithError(err_stream.str().c_str());
-        return;
-      }
-    }
-    mem_tracker_.StopTrackingAllocations();
-  }
-
- protected:
-  MemoryFake memory_;
-  std::unique_ptr<DwarfSectionImplFake<AddresssType>> section_;
-  MemoryTracker mem_tracker_;
-};
-
-// Benchmarks exercising Eval with the DWARF_LOCATION_REGISTER evaluation method.
-BENCHMARK_TEMPLATE_F(EvalBenchmark, BM_eval_register_few_regs, uint64_t)(benchmark::State& state) {
-  DwarfLocations loc_regs;
-  loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {0, 0}};
-  loc_regs[kReturnAddressReg] = DwarfLocation{DWARF_LOCATION_REGISTER, {0, 0x50000000}};
-  RunBenchmark(state, loc_regs);
-}
-
-BENCHMARK_TEMPLATE_F(EvalBenchmark, BM_eval_register_many_regs, uint64_t)(benchmark::State& state) {
-  DwarfLocations loc_regs;
-  loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {0, 0}};
-  for (uint64_t i = 0; i < 64; i++) {
-    loc_regs[i] = DwarfLocation{DWARF_LOCATION_REGISTER, {0, i * 0x10000000}};
-  }
-  RunBenchmark(state, loc_regs);
-}
-
-// Benchmarks exercising Eval with the DWARF_LOCATION_VAL_OFFSET evaluation method.
-BENCHMARK_TEMPLATE_F(EvalBenchmark, BM_eval_val_offset_few_regs, uint64_t)
-(benchmark::State& state) {
-  DwarfLocations loc_regs;
-  loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {0, 0}};
-  loc_regs[kReturnAddressReg] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0x50000000, 0}};
-  RunBenchmark(state, loc_regs);
-}
-
-BENCHMARK_TEMPLATE_F(EvalBenchmark, BM_eval_val_offset_many_regs, uint64_t)
-(benchmark::State& state) {
-  DwarfLocations loc_regs;
-  loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {0, 0}};
-  for (uint64_t i = 0; i < 64; i++) {
-    loc_regs[i] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {i * 0x10000000, 0}};
-  }
-  RunBenchmark(state, loc_regs);
-}
-
-// Benchmarks exercising Eval with the DWARF_LOCATION_OFFSET evaluation method.
-BENCHMARK_TEMPLATE_F(EvalBenchmark, BM_eval_offset_few_regs, uint64_t)
-(benchmark::State& state) {
-  memory_.SetData64(0x20000000, 0x60000000);
-  DwarfLocations loc_regs;
-  loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {0, 0}};
-  loc_regs[kReturnAddressReg] = DwarfLocation{DWARF_LOCATION_OFFSET, {0x10000000, 0}};
-  RunBenchmark(state, loc_regs);
-}
-
-BENCHMARK_TEMPLATE_F(EvalBenchmark, BM_eval_offset_many_regs, uint64_t)
-(benchmark::State& state) {
-  memory_.SetData64(0x20000000, 0x60000000);
-  memory_.SetData64(0x30000000, 0x10000000);
-  DwarfLocations loc_regs;
-  loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {0, 0}};
-  for (uint64_t i = 1; i < 64; i++) {
-    loc_regs[i] = DwarfLocation{DWARF_LOCATION_OFFSET, {0x10000000, 0}};
-  }
-  // Read from different place in memory for reg 0 so reg 0 maintains value of 0x10000000
-  // across multiple calls to Eval.
-  loc_regs[0] = DwarfLocation{DWARF_LOCATION_OFFSET, {0x20000000, 0}};
-  RunBenchmark(state, loc_regs);
-}
-
-// Benchmarks exercising Eval with the DWARF_LOCATION_EXPRESSION evaluation method.
-// The dwarf op-code used for the expression benchmarks are OP_const4u (see DwarfOp::Eval).
-BENCHMARK_TEMPLATE_F(EvalBenchmark, BM_eval_expression_few_regs, uint64_t)
-(benchmark::State& state) {
-  memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
-  uint64_t pc_value = 0x60000000;
-  memory_.SetMemory(0x80000000, &pc_value, sizeof(pc_value));
-  DwarfLocations loc_regs;
-  loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {0, 0}};
-  loc_regs[kReturnAddressReg] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5004}};
-  RunBenchmark(state, loc_regs);
-}
-
-BENCHMARK_TEMPLATE_F(EvalBenchmark, BM_eval_expression_many_regs, uint64_t)
-(benchmark::State& state) {
-  memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
-  uint64_t pc_value = 0x60000000;
-  memory_.SetMemory(0x80000000, &pc_value, sizeof(pc_value));
-
-  memory_.SetMemory(0x6000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x90});
-  uint64_t sp_value = 0x10000000;
-  memory_.SetMemory(0x90000000, &sp_value, sizeof(sp_value));
-
-  DwarfLocations loc_regs;
-  loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {0, 0}};
-  for (uint64_t i = 1; i < 64; i++) {
-    loc_regs[i] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5004}};
-  }
-  // Read from different place in memory for reg 0 so reg 0 maintains value of 0x10000000
-  // across multiple calls to Eval.
-  loc_regs[0] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x6004}};
-  RunBenchmark(state, loc_regs);
-}
-
-// Benchmarks exercising Eval with the DWARF_LOCATION_VAL_EXPRESSION evaluation method.
-// The dwarf op-code used for the value expression benchmarks are OP_const4u (see DwarfOp::Eval).
-BENCHMARK_TEMPLATE_F(EvalBenchmark, BM_eval_val_expression_few_regs, uint64_t)
-(benchmark::State& state) {
-  memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x60});
-  DwarfLocations loc_regs;
-  loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {0, 0}};
-  loc_regs[kReturnAddressReg] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5004}};
-  RunBenchmark(state, loc_regs);
-}
-
-BENCHMARK_TEMPLATE_F(EvalBenchmark, BM_eval_val_expression_many_regs, uint64_t)
-(benchmark::State& state) {
-  memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x60});
-  memory_.SetMemory(0x6000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x10});
-  DwarfLocations loc_regs;
-  loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {0, 0}};
-  for (uint64_t i = 1; i < 64; i++) {
-    loc_regs[i] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5004}};
-  }
-  // Read from different place in memory for reg 0 so reg 0 maintains value of 0x10000000
-  // across multiple calls to Eval.
-  loc_regs[0] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x6004}};
-  RunBenchmark(state, loc_regs);
-}
-
-}  // namespace
-}  // namespace unwindstack
diff --git a/libunwindstack/benchmarks/MemoryLocalUnsafe.h b/libunwindstack/benchmarks/MemoryLocalUnsafe.h
deleted file mode 100644
index 8edf473..0000000
--- a/libunwindstack/benchmarks/MemoryLocalUnsafe.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2021 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 <cstddef>
-#include <cstring>
-
-#include <unwindstack/Memory.h>
-
-namespace unwindstack {
-
-// MemoryLocalUnsafe is a prototype class to compare the performance of MemoryLocal::Read
-// to an "unsafe" read that assumes the local memory address provided is valid (i.e. memory is
-// not corrupted and address range lies within the stack).
-class MemoryLocalUnsafe : public Memory {
- public:
-  MemoryLocalUnsafe() = default;
-  virtual ~MemoryLocalUnsafe() = default;
-
-  size_t Read(uint64_t addr, void* dst, size_t size) override {
-    memcpy(dst, reinterpret_cast<void*>(addr), size);
-    return size;
-  }
-};
-
-}  // namespace unwindstack
diff --git a/libunwindstack/benchmarks/OfflineUnwindBenchmarks.cpp b/libunwindstack/benchmarks/OfflineUnwindBenchmarks.cpp
deleted file mode 100644
index bcb0bec..0000000
--- a/libunwindstack/benchmarks/OfflineUnwindBenchmarks.cpp
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * Copyright (C) 2021 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 <cstddef>
-#include <cstdint>
-#include <filesystem>
-#include <memory>
-#include <sstream>
-#include <unordered_map>
-#include <vector>
-
-#include <benchmark/benchmark.h>
-
-#include <unwindstack/Arch.h>
-#include <unwindstack/Unwinder.h>
-
-#include "Utils.h"
-#include "utils/OfflineUnwindUtils.h"
-
-// This collection of benchmarks exercises Unwinder::Unwind for offline unwinds.
-//
-// See `libunwindstack/utils/OfflineUnwindUtils.h` for more info on offline unwinds
-// and b/192012600 for additional information regarding these benchmarks.
-namespace unwindstack {
-namespace {
-
-static constexpr char kStartup[] = "startup_case";
-static constexpr char kSteadyState[] = "steady_state_case";
-
-class OfflineUnwindBenchmark : public benchmark::Fixture {
- public:
-  void SetUp(benchmark::State& state) override {
-    // Ensure each benchmarks has a fresh ELF cache at the start.
-    unwind_case_ = state.range(0) ? kSteadyState : kStartup;
-    resolve_names_ = state.range(1);
-    Elf::SetCachingEnabled(false);
-  }
-
-  void TearDown(benchmark::State& state) override {
-    offline_utils_.ReturnToCurrentWorkingDirectory();
-    mem_tracker_.SetBenchmarkCounters(state);
-  }
-
-  void SingleUnwindBenchmark(benchmark::State& state, const UnwindSampleInfo& sample_info) {
-    std::string error_msg;
-    if (!offline_utils_.Init(sample_info, &error_msg)) {
-      state.SkipWithError(error_msg.c_str());
-      return;
-    }
-    BenchmarkOfflineUnwindMultipleSamples(state, std::vector<UnwindSampleInfo>{sample_info});
-  }
-
-  void ConsecutiveUnwindBenchmark(benchmark::State& state,
-                                  const std::vector<UnwindSampleInfo>& sample_infos) {
-    std::string error_msg;
-    if (!offline_utils_.Init(sample_infos, &error_msg)) {
-      state.SkipWithError(error_msg.c_str());
-      return;
-    }
-    BenchmarkOfflineUnwindMultipleSamples(state, sample_infos);
-  }
-
- private:
-  void BenchmarkOfflineUnwindMultipleSamples(benchmark::State& state,
-                                             const std::vector<UnwindSampleInfo>& sample_infos) {
-    std::string error_msg;
-    auto offline_unwind_multiple_samples = [&](bool benchmarking_unwind) {
-      // The benchmark should only measure the time / memory usage for the creation of
-      // each Unwinder object and the corresponding unwind as close as possible.
-      if (benchmarking_unwind) state.PauseTiming();
-
-      std::unordered_map<std::string_view, std::unique_ptr<Regs>> regs_copies;
-      for (const auto& sample_info : sample_infos) {
-        const std::string& sample_name = sample_info.offline_files_dir;
-
-        // Need to init unwinder with new copy of regs each iteration because unwinding changes
-        // the attributes of the regs object.
-        regs_copies.emplace(sample_name,
-                            std::unique_ptr<Regs>(offline_utils_.GetRegs(sample_name)->Clone()));
-
-        // The Maps object will still hold the parsed maps from the previous unwinds. So reset them
-        // unless we want to assume all Maps are cached.
-        if (!sample_info.create_maps) {
-          if (!offline_utils_.CreateMaps(&error_msg, sample_name)) {
-            state.SkipWithError(error_msg.c_str());
-            return;
-          }
-
-          // Since this maps object will be cached, need to make sure that
-          // all of the names are fully qualified paths. This allows the
-          // caching mechanism to properly cache elf files that are
-          // actually the same.
-          if (!offline_utils_.ChangeToSampleDirectory(&error_msg, sample_name)) {
-            state.SkipWithError(error_msg.c_str());
-            return;
-          }
-          for (auto& map_info : *offline_utils_.GetMaps(sample_name)) {
-            auto& name = map_info->name();
-            if (!name.empty()) {
-              std::filesystem::path path;
-              if (std::filesystem::is_symlink(name.c_str())) {
-                path = std::filesystem::read_symlink(name.c_str());
-              } else {
-                path = std::filesystem::current_path();
-                path /= name.c_str();
-              }
-              name = path.lexically_normal().c_str();
-            }
-          }
-        }
-      }
-
-      if (benchmarking_unwind) mem_tracker_.StartTrackingAllocations();
-      for (const auto& sample_info : sample_infos) {
-        const std::string& sample_name = sample_info.offline_files_dir;
-        // Need to change to sample directory for Unwinder to properly init ELF objects.
-        // See more info at OfflineUnwindUtils::ChangeToSampleDirectory.
-        if (!offline_utils_.ChangeToSampleDirectory(&error_msg, sample_name)) {
-          state.SkipWithError(error_msg.c_str());
-          return;
-        }
-        if (benchmarking_unwind) state.ResumeTiming();
-
-        Unwinder unwinder(128, offline_utils_.GetMaps(sample_name),
-                          regs_copies.at(sample_name).get(),
-                          offline_utils_.GetProcessMemory(sample_name));
-        if (sample_info.memory_flag == ProcessMemoryFlag::kIncludeJitMemory) {
-          unwinder.SetJitDebug(offline_utils_.GetJitDebug(sample_name));
-        }
-        unwinder.SetResolveNames(resolve_names_);
-        unwinder.Unwind();
-
-        if (benchmarking_unwind) state.PauseTiming();
-        size_t expected_num_frames;
-        if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg, sample_name)) {
-          state.SkipWithError(error_msg.c_str());
-          return;
-        }
-        if (unwinder.NumFrames() != expected_num_frames) {
-          std::stringstream err_stream;
-          err_stream << "Failed to unwind sample " << sample_name << " properly.Expected "
-                     << expected_num_frames << " frames, but unwinder contained "
-                     << unwinder.NumFrames() << " frames. Unwind:\n"
-                     << DumpFrames(unwinder);
-          state.SkipWithError(err_stream.str().c_str());
-          return;
-        }
-      }
-      if (benchmarking_unwind) mem_tracker_.StopTrackingAllocations();
-    };
-
-    if (unwind_case_ == kSteadyState) {
-      WarmUpUnwindCaches(offline_unwind_multiple_samples);
-    }
-
-    for (auto _ : state) {
-      offline_unwind_multiple_samples(/*benchmarking_unwind=*/true);
-    }
-  }
-
-  // This functions main purpose is to enable ELF caching for the steady state unwind case
-  // and then perform one unwind to warm up the cache for subsequent unwinds.
-  //
-  // Another reason for pulling this functionality out of the main benchmarking function is
-  // to add an additional call stack frame in between the cache warm-up unwinds and
-  // BenchmarkOfflineUnwindMultipleSamples so that it is easy to filter this set of unwinds out
-  // when profiling.
-  void WarmUpUnwindCaches(const std::function<void(bool)>& offline_unwind_multiple_samples) {
-    Elf::SetCachingEnabled(true);
-    offline_unwind_multiple_samples(/*benchmarking_unwind=*/false);
-  }
-
-  std::string unwind_case_;
-  bool resolve_names_;
-  MemoryTracker mem_tracker_;
-  OfflineUnwindUtils offline_utils_;
-};
-
-BENCHMARK_DEFINE_F(OfflineUnwindBenchmark, BM_offline_straddle_arm64)(benchmark::State& state) {
-  SingleUnwindBenchmark(
-      state, {.offline_files_dir = "straddle_arm64/", .arch = ARCH_ARM64, .create_maps = false});
-}
-BENCHMARK_REGISTER_F(OfflineUnwindBenchmark, BM_offline_straddle_arm64)
-    ->ArgNames({"is_steady_state_case", "resolve_names"})
-    ->Ranges({{false, true}, {false, true}});
-
-BENCHMARK_DEFINE_F(OfflineUnwindBenchmark, BM_offline_straddle_arm64_cached_maps)
-(benchmark::State& state) {
-  SingleUnwindBenchmark(state, {.offline_files_dir = "straddle_arm64/", .arch = ARCH_ARM64});
-}
-BENCHMARK_REGISTER_F(OfflineUnwindBenchmark, BM_offline_straddle_arm64_cached_maps)
-    ->ArgNames({"is_steady_state_case", "resolve_names"})
-    ->Ranges({{false, true}, {false, true}});
-
-BENCHMARK_DEFINE_F(OfflineUnwindBenchmark, BM_offline_jit_debug_arm)(benchmark::State& state) {
-  SingleUnwindBenchmark(state, {.offline_files_dir = "jit_debug_arm/",
-                                .arch = ARCH_ARM,
-                                .memory_flag = ProcessMemoryFlag::kIncludeJitMemory,
-                                .create_maps = false});
-}
-BENCHMARK_REGISTER_F(OfflineUnwindBenchmark, BM_offline_jit_debug_arm)
-    ->ArgNames({"is_steady_state_case", "resolve_names"})
-    ->Ranges({{false, true}, {false, true}});
-
-BENCHMARK_DEFINE_F(OfflineUnwindBenchmark, BM_offline_profiler_like_multi_process)
-(benchmark::State& state) {
-  ConsecutiveUnwindBenchmark(
-      state,
-      std::vector<UnwindSampleInfo>{
-          {.offline_files_dir = "bluetooth_arm64/pc_1/", .arch = ARCH_ARM64, .create_maps = false},
-          {.offline_files_dir = "jit_debug_arm/",
-           .arch = ARCH_ARM,
-           .memory_flag = ProcessMemoryFlag::kIncludeJitMemory,
-           .create_maps = false},
-          {.offline_files_dir = "photos_reset_arm64/", .arch = ARCH_ARM64, .create_maps = false},
-          {.offline_files_dir = "youtube_compiled_arm64/",
-           .arch = ARCH_ARM64,
-           .create_maps = false},
-          {.offline_files_dir = "yt_music_arm64/", .arch = ARCH_ARM64, .create_maps = false},
-          {.offline_files_dir = "maps_compiled_arm64/28656_oat_odex_jar/",
-           .arch = ARCH_ARM64,
-           .create_maps = false}});
-}
-BENCHMARK_REGISTER_F(OfflineUnwindBenchmark, BM_offline_profiler_like_multi_process)
-    ->ArgNames({"is_steady_state_case", "resolve_names"})
-    ->Ranges({{false, true}, {false, true}});
-
-BENCHMARK_DEFINE_F(OfflineUnwindBenchmark, BM_offline_profiler_like_single_process_multi_thread)
-(benchmark::State& state) {
-  ConsecutiveUnwindBenchmark(
-      state,
-      std::vector<UnwindSampleInfo>{{.offline_files_dir = "maps_compiled_arm64/28656_oat_odex_jar/",
-                                     .arch = ARCH_ARM64,
-                                     .create_maps = false},
-                                    {.offline_files_dir = "maps_compiled_arm64/28613_main-thread/",
-                                     .arch = ARCH_ARM64,
-                                     .create_maps = false},
-                                    {.offline_files_dir = "maps_compiled_arm64/28644/",
-                                     .arch = ARCH_ARM64,
-                                     .create_maps = false},
-                                    {.offline_files_dir = "maps_compiled_arm64/28648/",
-                                     .arch = ARCH_ARM64,
-                                     .create_maps = false},
-                                    {.offline_files_dir = "maps_compiled_arm64/28667/",
-                                     .arch = ARCH_ARM64,
-                                     .create_maps = false}});
-}
-BENCHMARK_REGISTER_F(OfflineUnwindBenchmark, BM_offline_profiler_like_single_process_multi_thread)
-    ->ArgNames({"is_steady_state_case", "resolve_names"})
-    ->Ranges({{false, true}, {false, true}});
-
-BENCHMARK_DEFINE_F(OfflineUnwindBenchmark, BM_offline_profiler_like_single_thread_diverse_pcs)
-(benchmark::State& state) {
-  ConsecutiveUnwindBenchmark(
-      state,
-      std::vector<UnwindSampleInfo>{
-          {.offline_files_dir = "bluetooth_arm64/pc_1/", .arch = ARCH_ARM64, .create_maps = false},
-          {.offline_files_dir = "bluetooth_arm64/pc_2/", .arch = ARCH_ARM64, .create_maps = false},
-          {.offline_files_dir = "bluetooth_arm64/pc_3/", .arch = ARCH_ARM64, .create_maps = false},
-          {.offline_files_dir = "bluetooth_arm64/pc_4/",
-           .arch = ARCH_ARM64,
-           .create_maps = false}});
-}
-BENCHMARK_REGISTER_F(OfflineUnwindBenchmark, BM_offline_profiler_like_single_thread_diverse_pcs)
-    ->ArgNames({"is_steady_state_case", "resolve_names"})
-    ->Ranges({{false, true}, {false, true}});
-
-}  // namespace
-}  // namespace unwindstack
diff --git a/libunwindstack/benchmarks/SymbolBenchmark.cpp b/libunwindstack/benchmarks/SymbolBenchmark.cpp
index f181b57..8b65b15 100644
--- a/libunwindstack/benchmarks/SymbolBenchmark.cpp
+++ b/libunwindstack/benchmarks/SymbolBenchmark.cpp
@@ -47,7 +47,7 @@
 
     unwindstack::Elf elf(unwindstack::Memory::CreateFileMemory(elf_file, 0).release());
     if (!elf.Init() || !elf.valid()) {
-      errx(1, "Internal Error: Cannot open elf: %s", elf_file.c_str());
+      errx(1, "Internal Error: Cannot open elf.");
     }
 
     unwindstack::SharedString name;
@@ -129,25 +129,3 @@
                         GetSymbolSortedElfFile(), true);
 }
 BENCHMARK(BM_elf_and_symbol_find_multiple_from_sorted);
-
-void BM_elf_and_symbol_not_present_from_large_compressed_frame(benchmark::State& state) {
-  BenchmarkSymbolLookup(state, 0, GetLargeCompressedFrameElfFile(), false);
-}
-BENCHMARK(BM_elf_and_symbol_not_present_from_large_compressed_frame);
-
-void BM_elf_and_symbol_find_single_from_large_compressed_frame(benchmark::State& state) {
-  BenchmarkSymbolLookup(state, 0x202aec, GetLargeCompressedFrameElfFile(), true);
-}
-BENCHMARK(BM_elf_and_symbol_find_single_from_large_compressed_frame);
-
-void BM_elf_and_symbol_find_single_many_times_from_large_compressed_frame(benchmark::State& state) {
-  BenchmarkSymbolLookup(state, 0x202aec, GetLargeCompressedFrameElfFile(), true, 4096);
-}
-BENCHMARK(BM_elf_and_symbol_find_single_many_times_from_large_compressed_frame);
-
-void BM_elf_and_symbol_find_multiple_from_large_compressed_frame(benchmark::State& state) {
-  BenchmarkSymbolLookup(state,
-                        std::vector<uint64_t>{0x202aec, 0x23e74c, 0xd000c, 0x201b10, 0x183060},
-                        GetLargeCompressedFrameElfFile(), true);
-}
-BENCHMARK(BM_elf_and_symbol_find_multiple_from_large_compressed_frame);
diff --git a/libunwindstack/benchmarks/Utils.cpp b/libunwindstack/benchmarks/Utils.cpp
index 3750168..c92f109 100644
--- a/libunwindstack/benchmarks/Utils.cpp
+++ b/libunwindstack/benchmarks/Utils.cpp
@@ -17,9 +17,6 @@
 #include <err.h>
 #include <stdint.h>
 
-#include <benchmark/benchmark.h>
-#include <malloc.h>
-
 #include <string>
 #include <vector>
 
@@ -30,30 +27,17 @@
 #include <unwindstack/Elf.h>
 #include <unwindstack/Memory.h>
 
-#include "utils/OfflineUnwindUtils.h"
-
-#include "Utils.h"
-
-std::string GetBenchmarkFilesDirectory() {
-  std::string path = android::base::GetExecutableDirectory() + "/benchmarks/files/";
-  unwindstack::DecompressFiles(path);
-  return path;
-}
-
 std::string GetElfFile() {
-  return GetBenchmarkFilesDirectory() + "libart_arm.so";
+  return android::base::GetExecutableDirectory() + "/benchmarks/files/libart_arm.so";
 }
 
 std::string GetSymbolSortedElfFile() {
-  return GetBenchmarkFilesDirectory() + "boot_arm.oat";
+  return android::base::GetExecutableDirectory() + "/benchmarks/files/boot_arm.oat";
 }
 
-std::string GetLargeCompressedFrameElfFile() {
-  return GetBenchmarkFilesDirectory() + "libpac.so";
-}
-
-std::string GetLargeEhFrameElfFile() {
-  return GetBenchmarkFilesDirectory() + "libLLVM_android.so";
+std::string GetCompressedElfFile() {
+  // Both are the same right now.
+  return GetSymbolSortedElfFile();
 }
 
 #if defined(__BIONIC__)
@@ -76,42 +60,3 @@
   }
 }
 #endif
-
-void MemoryTracker::SetBenchmarkCounters(benchmark::State& state) {
-  total_iterations_ += state.iterations();
-#if defined(__BIONIC__)
-  state.counters["MEAN_RSS_BYTES"] = total_rss_bytes_ / static_cast<double>(total_iterations_);
-  state.counters["MAX_RSS_BYTES"] = max_rss_bytes_;
-  state.counters["MIN_RSS_BYTES"] = min_rss_bytes_;
-#endif
-  state.counters["MEAN_ALLOCATED_BYTES"] =
-      total_alloc_bytes_ / static_cast<double>(total_iterations_);
-  state.counters["MAX_ALLOCATED_BYTES"] = max_alloc_bytes_;
-  state.counters["MIN_ALLOCATED_BYTES"] = min_alloc_bytes_;
-}
-
-void MemoryTracker::StartTrackingAllocations() {
-#if defined(__BIONIC__)
-  mallopt(M_PURGE, 0);
-  rss_bytes_before_ = 0;
-  GatherRss(&rss_bytes_before_);
-#endif
-  alloc_bytes_before_ = mallinfo().uordblks;
-}
-
-void MemoryTracker::StopTrackingAllocations() {
-#if defined(__BIONIC__)
-  mallopt(M_PURGE, 0);
-#endif
-  uint64_t bytes_alloced = mallinfo().uordblks - alloc_bytes_before_;
-  total_alloc_bytes_ += bytes_alloced;
-  if (bytes_alloced > max_alloc_bytes_) max_alloc_bytes_ = bytes_alloced;
-  if (bytes_alloced < min_alloc_bytes_) min_alloc_bytes_ = bytes_alloced;
-#if defined(__BIONIC__)
-  uint64_t rss_bytes = 0;
-  GatherRss(&rss_bytes);
-  total_rss_bytes_ += rss_bytes - rss_bytes_before_;
-  if (rss_bytes > max_rss_bytes_) max_rss_bytes_ = rss_bytes;
-  if (rss_bytes < min_rss_bytes_) min_rss_bytes_ = rss_bytes;
-#endif
-}
diff --git a/libunwindstack/benchmarks/Utils.h b/libunwindstack/benchmarks/Utils.h
index 2d05af9..bee6efc 100644
--- a/libunwindstack/benchmarks/Utils.h
+++ b/libunwindstack/benchmarks/Utils.h
@@ -14,25 +14,18 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_UTILS_H
+#define _LIBUNWINDSTACK_UTILS_H
 
-#include <benchmark/benchmark.h>
 #include <stdint.h>
 
 #include <string>
 
-std::string GetBenchmarkFilesDirectory();
-
 std::string GetElfFile();
 
 std::string GetSymbolSortedElfFile();
 
-// GetLargeCompressedFrameElfFile and GetLargeEhFrameElfFile were added to provide larger
-// ELF files for more representative benchmarks. Theses ELF files will enable validation
-// of optimizations to the unwindstack::Elf.
-std::string GetLargeCompressedFrameElfFile();
-
-std::string GetLargeEhFrameElfFile();
+std::string GetCompressedElfFile();
 
 #if defined(__BIONIC__)
 
@@ -43,25 +36,4 @@
 
 #endif
 
-class MemoryTracker {
- public:
-  void StartTrackingAllocations();
-  void StopTrackingAllocations();
-  void SetBenchmarkCounters(benchmark::State& state);
-
- private:
-#if defined(__BIONIC__)
-  uint64_t total_rss_bytes_ = 0;
-  uint64_t min_rss_bytes_ = 0;
-  uint64_t max_rss_bytes_ = 0;
-  uint64_t rss_bytes_before_;
-#endif
-  uint64_t total_alloc_bytes_ = 0;
-  uint64_t min_alloc_bytes_ = std::numeric_limits<uint64_t>::max();
-  uint64_t max_alloc_bytes_ = 0;
-  uint64_t alloc_bytes_before_;
-  // Benchmarks may run multiple times (the whole benchmark not just what is in the ranged based
-  // for loop) but this instance is not destructed and re-constructed each time. So this holds the
-  // total number of iterations of the ranged for loop across all runs of a single benchmark.
-  size_t total_iterations_ = 0;
-};
+#endif  // _LIBUNWINDSTACK_UTILS_h
diff --git a/libunwindstack/benchmarks/files/boot_arm.oat b/libunwindstack/benchmarks/files/boot_arm.oat
new file mode 100644
index 0000000..51188eb
--- /dev/null
+++ b/libunwindstack/benchmarks/files/boot_arm.oat
Binary files differ
diff --git a/libunwindstack/benchmarks/files/boot_arm.oat.gz b/libunwindstack/benchmarks/files/boot_arm.oat.gz
deleted file mode 100644
index 4b236b8..0000000
--- a/libunwindstack/benchmarks/files/boot_arm.oat.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/benchmarks/files/libLLVM_android.so.gz b/libunwindstack/benchmarks/files/libLLVM_android.so.gz
deleted file mode 100644
index 5edc266..0000000
--- a/libunwindstack/benchmarks/files/libLLVM_android.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/benchmarks/files/libart_arm.so b/libunwindstack/benchmarks/files/libart_arm.so
new file mode 100644
index 0000000..2201faf
--- /dev/null
+++ b/libunwindstack/benchmarks/files/libart_arm.so
Binary files differ
diff --git a/libunwindstack/benchmarks/files/libart_arm.so.gz b/libunwindstack/benchmarks/files/libart_arm.so.gz
deleted file mode 100644
index 963f453..0000000
--- a/libunwindstack/benchmarks/files/libart_arm.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/benchmarks/files/libpac.so.gz b/libunwindstack/benchmarks/files/libpac.so.gz
deleted file mode 100644
index a5df2be..0000000
--- a/libunwindstack/benchmarks/files/libpac.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/benchmarks/local_unwind_benchmarks.cpp b/libunwindstack/benchmarks/local_unwind_benchmarks.cpp
index 78c8c13..69c6091 100644
--- a/libunwindstack/benchmarks/local_unwind_benchmarks.cpp
+++ b/libunwindstack/benchmarks/local_unwind_benchmarks.cpp
@@ -22,13 +22,12 @@
 
 #include <android-base/strings.h>
 
-#include <unwindstack/AndroidUnwinder.h>
+#include <unwindstack/LocalUnwinder.h>
 #include <unwindstack/Maps.h>
 #include <unwindstack/Memory.h>
 #include <unwindstack/Regs.h>
 #include <unwindstack/RegsGetLocal.h>
 #include <unwindstack/Unwinder.h>
-#include "MemoryLocalUnsafe.h"
 
 constexpr size_t kMaxFrames = 32;
 
@@ -76,6 +75,13 @@
   return unwinder.NumFrames();
 }
 
+static size_t LocalUnwind(void* unwind_ptr) {
+  unwindstack::LocalUnwinder* unwinder = reinterpret_cast<unwindstack::LocalUnwinder*>(unwind_ptr);
+  std::vector<unwindstack::LocalFrameData> frame_info;
+  unwinder->Unwind(&frame_info, kMaxFrames);
+  return frame_info.size();
+}
+
 static void BM_local_unwind_uncached_process_memory(benchmark::State& state) {
   auto process_memory = unwindstack::Memory::CreateProcessMemory(getpid());
   unwindstack::LocalMaps maps;
@@ -100,54 +106,6 @@
 }
 BENCHMARK(BM_local_unwind_cached_process_memory);
 
-static void BM_local_android_unwind_uncached_process_memory(benchmark::State& state) {
-  auto process_memory = unwindstack::Memory::CreateProcessMemory(getpid());
-  unwindstack::AndroidLocalUnwinder unwinder(process_memory);
-  unwindstack::ErrorData error;
-  if (!unwinder.Initialize(error)) {
-    state.SkipWithError("Failed to initialize.");
-  }
-
-  for (auto _ : state) {
-    if (LocalCall1(
-            [](void* u) -> size_t {
-              unwindstack::AndroidLocalUnwinder* unwinder =
-                  reinterpret_cast<unwindstack::AndroidLocalUnwinder*>(u);
-              unwindstack::AndroidUnwinderData data;
-              unwinder->Unwind(data);
-              return data.frames.size();
-            },
-            &unwinder) < 5) {
-      state.SkipWithError("Failed to unwind.");
-    }
-  }
-}
-BENCHMARK(BM_local_android_unwind_uncached_process_memory);
-
-static void BM_local_android_unwind_cached_process_memory(benchmark::State& state) {
-  auto process_memory = unwindstack::Memory::CreateProcessMemoryCached(getpid());
-  unwindstack::AndroidLocalUnwinder unwinder(process_memory);
-  unwindstack::ErrorData error;
-  if (!unwinder.Initialize(error)) {
-    state.SkipWithError("Failed to initialize.");
-  }
-
-  for (auto _ : state) {
-    if (LocalCall1(
-            [](void* u) -> size_t {
-              unwindstack::AndroidLocalUnwinder* unwinder =
-                  reinterpret_cast<unwindstack::AndroidLocalUnwinder*>(u);
-              unwindstack::AndroidUnwinderData data;
-              unwinder->Unwind(data);
-              return data.frames.size();
-            },
-            &unwinder) < 5) {
-      state.SkipWithError("Failed to unwind.");
-    }
-  }
-}
-BENCHMARK(BM_local_android_unwind_cached_process_memory);
-
 static void BM_local_unwind_local_updatable_maps_uncached(benchmark::State& state) {
   auto process_memory = unwindstack::Memory::CreateProcessMemory(getpid());
   unwindstack::LocalUpdatableMaps maps;
@@ -184,6 +142,16 @@
 }
 BENCHMARK(BM_local_unwind_local_updatable_maps_thread_cached);
 
+static void BM_local_unwind_local_unwinder(benchmark::State& state) {
+  unwindstack::LocalUnwinder unwinder;
+  if (!unwinder.Init()) {
+    state.SkipWithError("Failed to init local unwinder.");
+  }
+
+  Run(state, LocalUnwind, &unwinder);
+}
+BENCHMARK(BM_local_unwind_local_unwinder);
+
 static void BM_local_unwind_uncached_process_memory_no_func_names(benchmark::State& state) {
   auto process_memory = unwindstack::Memory::CreateProcessMemory(getpid());
   unwindstack::LocalMaps maps;
@@ -231,15 +199,3 @@
   Run(state, Unwind, &data);
 }
 BENCHMARK(BM_local_unwind_local_updatable_maps_cached_no_func_names);
-
-static void BM_local_unwind_uncached_process_memory_unsafe_reads(benchmark::State& state) {
-  std::shared_ptr<unwindstack::Memory> process_memory(new unwindstack::MemoryLocalUnsafe());
-  unwindstack::LocalMaps maps;
-  if (!maps.Parse()) {
-    state.SkipWithError("Failed to parse local maps.");
-  }
-
-  UnwindData data = {.process_memory = process_memory, .maps = &maps, .resolve_names = true};
-  Run(state, Unwind, &data);
-}
-BENCHMARK(BM_local_unwind_uncached_process_memory_unsafe_reads);
diff --git a/libunwindstack/benchmarks/main.cpp b/libunwindstack/benchmarks/main.cpp
index 3fc1db9..02b2fdf 100644
--- a/libunwindstack/benchmarks/main.cpp
+++ b/libunwindstack/benchmarks/main.cpp
@@ -16,80 +16,4 @@
 
 #include <benchmark/benchmark.h>
 
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <android-base/strings.h>
-
-#include <string>
-#include <vector>
-
-#if defined(__APPLE__)
-
-// Darwin doesn't support this, so do nothing.
-bool LockToCPU(int) {
-  return false;
-}
-
-#else
-
-#include <errno.h>
-#include <sched.h>
-
-bool LockToCPU(int lock_cpu) {
-  cpu_set_t cpuset;
-
-  CPU_ZERO(&cpuset);
-  CPU_SET(lock_cpu, &cpuset);
-  if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0) {
-    if (errno == EINVAL) {
-      printf("Invalid cpu %d\n", lock_cpu);
-    } else {
-      perror("sched_setaffinity failed");
-    }
-    return false;
-  }
-
-  printf("Locked to cpu %d\n", lock_cpu);
-  return true;
-}
-
-#endif
-
-int main(int argc, char** argv) {
-#if defined(__BIONIC__)
-  // Enable decay time option to allow frees to run faster at the cost of slightly increasing RSS.
-  // All applications on Android run with this option enabled.
-  mallopt(M_DECAY_TIME, 1);
-#endif
-  std::vector<char*> new_argv;
-  // The first argument is not an option, so add it as is.
-  new_argv.push_back(argv[0]);
-
-  // Look for the special option --benchmark_lock_cpu.
-  int lock_cpu = -1;
-  for (int i = 1; i < argc; i++) {
-    if (android::base::StartsWith(argv[i], "--benchmark_cpu=")) {
-      char* endptr;
-      long cpu = strtol(&argv[i][16], &endptr, 10);
-      if (endptr == nullptr || *endptr != '\0' || cpu > INT_MAX || cpu < 0) {
-        printf("Malformed value for --benchmark_cpu, requires a valid positive number.\n");
-        return 1;
-      }
-      lock_cpu = cpu;
-    } else {
-      new_argv.push_back(argv[i]);
-    }
-  }
-  new_argv.push_back(nullptr);
-
-  if (lock_cpu != -1 && !LockToCPU(lock_cpu)) {
-    return 1;
-  }
-
-  int new_argc = new_argv.size() - 1;
-  ::benchmark::Initialize(&new_argc, new_argv.data());
-  if (::benchmark::ReportUnrecognizedArguments(new_argc, new_argv.data())) return 1;
-  ::benchmark::RunSpecifiedBenchmarks();
-}
+BENCHMARK_MAIN();
diff --git a/libunwindstack/benchmarks/remote_unwind_benchmarks.cpp b/libunwindstack/benchmarks/remote_unwind_benchmarks.cpp
index 29c416d..ef07e39 100644
--- a/libunwindstack/benchmarks/remote_unwind_benchmarks.cpp
+++ b/libunwindstack/benchmarks/remote_unwind_benchmarks.cpp
@@ -24,26 +24,35 @@
 
 #include <benchmark/benchmark.h>
 
-#include <unwindstack/AndroidUnwinder.h>
 #include <unwindstack/Maps.h>
 #include <unwindstack/Memory.h>
 #include <unwindstack/Regs.h>
 #include <unwindstack/Unwinder.h>
 
 #include "MemoryRemote.h"
-#include "PidUtils.h"
 #include "tests/TestUtils.h"
 
 static bool WaitForRemote(pid_t pid, volatile bool* ready_ptr) {
-  return unwindstack::RunWhenQuiesced(pid, true, [pid, ready_ptr]() {
-    unwindstack::MemoryRemote memory(pid);
-    bool ready;
-    uint64_t ready_addr = reinterpret_cast<uint64_t>(ready_ptr);
-    if (memory.ReadFully(ready_addr, &ready, sizeof(ready)) && ready) {
-      return unwindstack::PID_RUN_PASS;
+  usleep(1000);
+  for (size_t i = 0; i < 1000; i++) {
+    if (ptrace(PTRACE_ATTACH, pid, 0, 0) == 0) {
+      unwindstack::TestQuiescePid(pid);
+
+      unwindstack::MemoryRemote memory(pid);
+      bool ready;
+      uint64_t ready_addr = reinterpret_cast<uint64_t>(ready_ptr);
+      if (memory.ReadFully(ready_addr, &ready, sizeof(ready)) && ready) {
+        return true;
+      }
+    } else if (errno != ESRCH) {
+      // Attach failed with unknown error.
+      perror("Ptrace failed:");
+      return false;
     }
-    return unwindstack::PID_RUN_KEEP_GOING;
-  });
+    usleep(5000);
+  }
+  printf("Pid %d did not quiesce in a timely fashion.\n", pid);
+  return false;
 }
 
 size_t RemoteCall6(volatile bool* ready) {
@@ -132,42 +141,3 @@
   RemoteUnwind(state, true);
 }
 BENCHMARK(BM_remote_unwind_cached);
-
-static void RemoteAndroidUnwind(benchmark::State& state, bool cached) {
-  pid_t pid = StartRemoteRun();
-  if (pid == -1) {
-    state.SkipWithError("Failed to start remote process.");
-  }
-  unwindstack::TestScopedPidReaper reap(pid);
-
-  std::shared_ptr<unwindstack::Memory> process_memory;
-  if (cached) {
-    process_memory = unwindstack::Memory::CreateProcessMemoryCached(pid);
-  } else {
-    process_memory = unwindstack::Memory::CreateProcessMemory(pid);
-  }
-  unwindstack::AndroidRemoteUnwinder unwinder(pid, process_memory);
-  unwindstack::ErrorData error;
-  if (!unwinder.Initialize(error)) {
-    state.SkipWithError("Failed to initialize unwinder.");
-  }
-
-  for (auto _ : state) {
-    unwindstack::AndroidUnwinderData data;
-    if (!unwinder.Unwind(data) || data.frames.size() < 5) {
-      state.SkipWithError("Failed to unwind properly.");
-    }
-  }
-
-  ptrace(PTRACE_DETACH, pid, 0, 0);
-}
-
-static void BM_remote_android_unwind_uncached(benchmark::State& state) {
-  RemoteAndroidUnwind(state, true);
-}
-BENCHMARK(BM_remote_android_unwind_uncached);
-
-static void BM_remote_android_unwind_cached(benchmark::State& state) {
-  RemoteAndroidUnwind(state, true);
-}
-BENCHMARK(BM_remote_android_unwind_cached);
diff --git a/libunwindstack/include/GlobalDebugInterface.h b/libunwindstack/include/GlobalDebugInterface.h
index b1e9106..45eec63 100644
--- a/libunwindstack/include/GlobalDebugInterface.h
+++ b/libunwindstack/include/GlobalDebugInterface.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_GLOBAL_DEBUG_INTERFACE_H
+#define _LIBUNWINDSTACK_GLOBAL_DEBUG_INTERFACE_H
 
 #include <stdint.h>
 #include <memory>
@@ -40,3 +41,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_GLOBAL_DEBUG_INTERFACE_H
diff --git a/libunwindstack/include/unwindstack/AndroidUnwinder.h b/libunwindstack/include/unwindstack/AndroidUnwinder.h
deleted file mode 100644
index de5579d..0000000
--- a/libunwindstack/include/unwindstack/AndroidUnwinder.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (C) 2022 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 <sys/types.h>
-#include <unistd.h>
-
-#include <memory>
-#include <mutex>
-#include <optional>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include <unwindstack/Arch.h>
-#include <unwindstack/DexFiles.h>
-#include <unwindstack/Error.h>
-#include <unwindstack/JitDebug.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/Regs.h>
-#include <unwindstack/SharedString.h>
-#include <unwindstack/Unwinder.h>
-
-namespace unwindstack {
-
-struct AndroidUnwinderData {
-  AndroidUnwinderData() = default;
-  explicit AndroidUnwinderData(const size_t max_frames) : max_frames(max_frames) {}
-  explicit AndroidUnwinderData(const bool show_all_frames) : show_all_frames(show_all_frames) {}
-
-  void DemangleFunctionNames();
-
-  std::string GetErrorString();
-
-  std::vector<FrameData> frames;
-  ErrorData error;
-  std::optional<std::unique_ptr<Regs>> saved_initial_regs;
-  const std::optional<size_t> max_frames;
-  const bool show_all_frames = false;
-};
-
-class AndroidUnwinder {
- public:
-  AndroidUnwinder(pid_t pid) : pid_(pid) {}
-  AndroidUnwinder(pid_t pid, std::shared_ptr<Memory>& memory)
-      : pid_(pid), process_memory_(memory) {}
-  AndroidUnwinder(pid_t pid, ArchEnum arch) : pid_(pid), arch_(arch) {}
-  AndroidUnwinder(pid_t pid, const std::vector<std::string> initial_map_names_to_skip)
-      : pid_(pid), initial_map_names_to_skip_(std::move(initial_map_names_to_skip)) {}
-  AndroidUnwinder(pid_t pid, const std::vector<std::string> initial_map_names_to_skip,
-                  const std::vector<std::string> map_suffixes_to_ignore)
-      : pid_(pid),
-        initial_map_names_to_skip_(std::move(initial_map_names_to_skip)),
-        map_suffixes_to_ignore_(std::move(map_suffixes_to_ignore)) {}
-  virtual ~AndroidUnwinder() = default;
-
-  bool Initialize(ErrorData& error);
-
-  std::shared_ptr<Memory>& GetProcessMemory() { return process_memory_; }
-  unwindstack::Maps* GetMaps() { return maps_.get(); }
-
-  const JitDebug& GetJitDebug() { return *jit_debug_.get(); }
-  const DexFiles& GetDexFiles() { return *dex_files_.get(); }
-
-  std::string FormatFrame(const FrameData& frame) const;
-
-  bool Unwind(AndroidUnwinderData& data);
-  bool Unwind(std::optional<pid_t> tid, AndroidUnwinderData& data);
-  bool Unwind(void* ucontext, AndroidUnwinderData& data);
-  bool Unwind(Regs* initial_regs, AndroidUnwinderData& data);
-
-  FrameData BuildFrameFromPcOnly(uint64_t pc);
-
-  static AndroidUnwinder* Create(pid_t pid);
-
- protected:
-  virtual bool InternalInitialize(ErrorData& error) = 0;
-
-  virtual bool InternalUnwind(std::optional<pid_t> tid, AndroidUnwinderData& data) = 0;
-
-  pid_t pid_;
-
-  size_t max_frames_ = kMaxNumFrames;
-  std::vector<std::string> initial_map_names_to_skip_;
-  std::vector<std::string> map_suffixes_to_ignore_;
-  std::once_flag initialize_;
-
-  ArchEnum arch_ = ARCH_UNKNOWN;
-
-  std::shared_ptr<Maps> maps_;
-  std::shared_ptr<Memory> process_memory_;
-  std::unique_ptr<JitDebug> jit_debug_;
-  std::unique_ptr<DexFiles> dex_files_;
-
-  static constexpr size_t kMaxNumFrames = 512;
-};
-
-class AndroidLocalUnwinder : public AndroidUnwinder {
- public:
-  AndroidLocalUnwinder() : AndroidUnwinder(getpid()) {
-    initial_map_names_to_skip_.emplace_back(kUnwindstackLib);
-  }
-  AndroidLocalUnwinder(std::shared_ptr<Memory>& process_memory)
-      : AndroidUnwinder(getpid(), process_memory) {
-    initial_map_names_to_skip_.emplace_back(kUnwindstackLib);
-  }
-  AndroidLocalUnwinder(const std::vector<std::string>& initial_map_names_to_skip)
-      : AndroidUnwinder(getpid(), initial_map_names_to_skip) {
-    initial_map_names_to_skip_.emplace_back(kUnwindstackLib);
-  }
-  AndroidLocalUnwinder(const std::vector<std::string>& initial_map_names_to_skip,
-                       const std::vector<std::string>& map_suffixes_to_ignore)
-      : AndroidUnwinder(getpid(), initial_map_names_to_skip, map_suffixes_to_ignore) {
-    initial_map_names_to_skip_.emplace_back(kUnwindstackLib);
-  }
-  virtual ~AndroidLocalUnwinder() = default;
-
- protected:
-  static constexpr const char* kUnwindstackLib = "libunwindstack.so";
-
-  bool InternalInitialize(ErrorData& error) override;
-
-  bool InternalUnwind(std::optional<pid_t> tid, AndroidUnwinderData& data) override;
-};
-
-class AndroidRemoteUnwinder : public AndroidUnwinder {
- public:
-  AndroidRemoteUnwinder(pid_t pid) : AndroidUnwinder(pid) {}
-  AndroidRemoteUnwinder(pid_t pid, std::shared_ptr<Memory>& process_memory)
-      : AndroidUnwinder(pid, process_memory) {}
-  AndroidRemoteUnwinder(pid_t pid, ArchEnum arch) : AndroidUnwinder(pid, arch) {}
-  AndroidRemoteUnwinder(pid_t pid, const std::vector<std::string> initial_map_names_to_skip)
-      : AndroidUnwinder(pid, initial_map_names_to_skip) {}
-  AndroidRemoteUnwinder(pid_t pid, const std::vector<std::string> initial_map_names_to_skip,
-                        const std::vector<std::string> map_suffixes_to_ignore)
-      : AndroidUnwinder(pid, initial_map_names_to_skip, map_suffixes_to_ignore) {}
-  virtual ~AndroidRemoteUnwinder() = default;
-
- protected:
-  bool InternalInitialize(ErrorData& error) override;
-
-  bool InternalUnwind(std::optional<pid_t> tid, AndroidUnwinderData& data) override;
-};
-
-}  // namespace unwindstack
diff --git a/libunwindstack/include/unwindstack/Arch.h b/libunwindstack/include/unwindstack/Arch.h
index 42180b4..7060004 100644
--- a/libunwindstack/include/unwindstack/Arch.h
+++ b/libunwindstack/include/unwindstack/Arch.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_ARCH_H
+#define _LIBUNWINDSTACK_ARCH_H
 
 #include <stddef.h>
 
@@ -42,3 +43,5 @@
 }
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_ARCH_H
diff --git a/libunwindstack/include/unwindstack/DexFiles.h b/libunwindstack/include/unwindstack/DexFiles.h
index 101d772..2a1b770 100644
--- a/libunwindstack/include/unwindstack/DexFiles.h
+++ b/libunwindstack/include/unwindstack/DexFiles.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_DEX_FILES_H
+#define _LIBUNWINDSTACK_DEX_FILES_H
 
 #include <stdint.h>
 
@@ -35,3 +36,5 @@
                                          std::vector<std::string> search_libs = {});
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_DEX_FILES_H
diff --git a/libunwindstack/include/unwindstack/DwarfError.h b/libunwindstack/include/unwindstack/DwarfError.h
index 6143523..763e2cb 100644
--- a/libunwindstack/include/unwindstack/DwarfError.h
+++ b/libunwindstack/include/unwindstack/DwarfError.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_DWARF_ERROR_H
+#define _LIBUNWINDSTACK_DWARF_ERROR_H
 
 #include <stdint.h>
 
@@ -39,3 +40,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_DWARF_ERROR_H
diff --git a/libunwindstack/include/unwindstack/DwarfLocation.h b/libunwindstack/include/unwindstack/DwarfLocation.h
index 9726f15..22ed47a 100644
--- a/libunwindstack/include/unwindstack/DwarfLocation.h
+++ b/libunwindstack/include/unwindstack/DwarfLocation.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_DWARF_LOCATION_H
+#define _LIBUNWINDSTACK_DWARF_LOCATION_H
 
 #include <stdint.h>
 
@@ -48,3 +49,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_DWARF_LOCATION_H
diff --git a/libunwindstack/include/unwindstack/DwarfMemory.h b/libunwindstack/include/unwindstack/DwarfMemory.h
index 2ef3b30..c45699a 100644
--- a/libunwindstack/include/unwindstack/DwarfMemory.h
+++ b/libunwindstack/include/unwindstack/DwarfMemory.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_DWARF_MEMORY_H
+#define _LIBUNWINDSTACK_DWARF_MEMORY_H
 
 #include <stdint.h>
 
@@ -71,3 +72,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_DWARF_MEMORY_H
diff --git a/libunwindstack/include/unwindstack/DwarfSection.h b/libunwindstack/include/unwindstack/DwarfSection.h
index 33435b2..71ca62e 100644
--- a/libunwindstack/include/unwindstack/DwarfSection.h
+++ b/libunwindstack/include/unwindstack/DwarfSection.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_DWARF_SECTION_H
+#define _LIBUNWINDSTACK_DWARF_SECTION_H
 
 #include <stdint.h>
 
@@ -178,3 +179,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_DWARF_SECTION_H
diff --git a/libunwindstack/include/unwindstack/DwarfStructs.h b/libunwindstack/include/unwindstack/DwarfStructs.h
index 4c05360..3d8c2db 100644
--- a/libunwindstack/include/unwindstack/DwarfStructs.h
+++ b/libunwindstack/include/unwindstack/DwarfStructs.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_DWARF_STRUCTS_H
+#define _LIBUNWINDSTACK_DWARF_STRUCTS_H
 
 #include <stdint.h>
 
@@ -50,3 +51,5 @@
 constexpr uint16_t CFA_REG = static_cast<uint16_t>(-1);
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_DWARF_STRUCTS_H
diff --git a/libunwindstack/include/unwindstack/Elf.h b/libunwindstack/include/unwindstack/Elf.h
index 0985042..01d9af9 100644
--- a/libunwindstack/include/unwindstack/Elf.h
+++ b/libunwindstack/include/unwindstack/Elf.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_ELF_H
+#define _LIBUNWINDSTACK_ELF_H
 
 #include <stddef.h>
 
@@ -67,8 +68,6 @@
 
   std::string GetBuildID();
 
-  std::string GetPrintableBuildID();
-
   int64_t GetLoadBias() { return load_bias_; }
 
   bool IsValidPc(uint64_t pc);
@@ -101,20 +100,14 @@
 
   static std::string GetBuildID(Memory* memory);
 
-  // Caching cannot be enabled/disabled while unwinding. It is assumed
-  // that once enabled, it remains enabled while all unwinds are running.
-  // If the state of the caching changes while unwinding is occurring,
-  // it could cause crashes.
   static void SetCachingEnabled(bool enable);
-
   static bool CachingEnabled() { return cache_enabled_; }
 
   static void CacheLock();
   static void CacheUnlock();
   static void CacheAdd(MapInfo* info);
   static bool CacheGet(MapInfo* info);
-
-  static std::string GetPrintableBuildID(std::string& build_id);
+  static bool CacheAfterCreateMemory(MapInfo* info);
 
  protected:
   bool valid_ = false;
@@ -131,9 +124,10 @@
   std::unique_ptr<ElfInterface> gnu_debugdata_interface_;
 
   static bool cache_enabled_;
-  static std::unordered_map<std::string, std::unordered_map<uint64_t, std::shared_ptr<Elf>>>*
-      cache_;
+  static std::unordered_map<std::string, std::pair<std::shared_ptr<Elf>, bool>>* cache_;
   static std::mutex* cache_lock_;
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_ELF_H
diff --git a/libunwindstack/include/unwindstack/ElfInterface.h b/libunwindstack/include/unwindstack/ElfInterface.h
index a192450..23b7256 100644
--- a/libunwindstack/include/unwindstack/ElfInterface.h
+++ b/libunwindstack/include/unwindstack/ElfInterface.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_ELF_INTERFACE_H
+#define _LIBUNWINDSTACK_ELF_INTERFACE_H
 
 #include <elf.h>
 #include <stdint.h>
@@ -224,3 +225,5 @@
 using ElfInterface64 = ElfInterfaceImpl<ElfTypes64>;
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_ELF_INTERFACE_H
diff --git a/libunwindstack/include/unwindstack/Error.h b/libunwindstack/include/unwindstack/Error.h
index 3a3c646..1610d55 100644
--- a/libunwindstack/include/unwindstack/Error.h
+++ b/libunwindstack/include/unwindstack/Error.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_ERROR_H
+#define _LIBUNWINDSTACK_ERROR_H
 
 #include <stdint.h>
 
@@ -40,10 +41,7 @@
                                 // not exist.
   ERROR_THREAD_TIMEOUT,         // Timeout trying to unwind a local thread.
   ERROR_SYSTEM_CALL,            // System call failed while unwinding.
-  ERROR_BAD_ARCH,               // Arch invalid (none, or mismatched).
-  ERROR_MAPS_PARSE,             // Failed to parse maps data.
-  ERROR_INVALID_PARAMETER,      // Invalid parameter passed to function.
-  ERROR_MAX = ERROR_INVALID_PARAMETER,
+  ERROR_MAX = ERROR_SYSTEM_CALL,
 };
 
 static inline const char* GetErrorCodeString(ErrorCode error) {
@@ -70,12 +68,6 @@
       return "Thread Timeout";
     case ERROR_SYSTEM_CALL:
       return "System Call Failed";
-    case ERROR_BAD_ARCH:
-      return "Invalid arch detected";
-    case ERROR_MAPS_PARSE:
-      return "Failed to parse maps";
-    case ERROR_INVALID_PARAMETER:
-      return "Invalid parameter";
   }
 }
 
@@ -86,3 +78,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_ERROR_H
diff --git a/libunwindstack/include/unwindstack/Global.h b/libunwindstack/include/unwindstack/Global.h
index d12ecb1..b790832 100644
--- a/libunwindstack/include/unwindstack/Global.h
+++ b/libunwindstack/include/unwindstack/Global.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_GLOBAL_H
+#define _LIBUNWINDSTACK_GLOBAL_H
 
 #include <stdint.h>
 
@@ -58,3 +59,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_GLOBAL_H
diff --git a/libunwindstack/include/unwindstack/JitDebug.h b/libunwindstack/include/unwindstack/JitDebug.h
index 8653f94..cfa8f7e 100644
--- a/libunwindstack/include/unwindstack/JitDebug.h
+++ b/libunwindstack/include/unwindstack/JitDebug.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_JIT_DEBUG_H
+#define _LIBUNWINDSTACK_JIT_DEBUG_H
 
 #include <stdint.h>
 
@@ -35,3 +36,5 @@
                                          std::vector<std::string> search_libs = {});
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_JIT_DEBUG_H
diff --git a/libunwindstack/include/unwindstack/LocalUnwinder.h b/libunwindstack/include/unwindstack/LocalUnwinder.h
new file mode 100644
index 0000000..b9123b3
--- /dev/null
+++ b/libunwindstack/include/unwindstack/LocalUnwinder.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2018 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_LOCAL_UNWINDER_H
+#define _LIBUNWINDSTACK_LOCAL_UNWINDER_H
+
+#include <pthread.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <unwindstack/Error.h>
+#include <unwindstack/Maps.h>
+#include <unwindstack/Memory.h>
+
+namespace unwindstack {
+
+// Forward declarations.
+class Elf;
+class MapInfo;
+
+struct LocalFrameData {
+  LocalFrameData(MapInfo* map_info, uint64_t pc, uint64_t rel_pc, const std::string& function_name,
+                 uint64_t function_offset)
+      : map_info(map_info),
+        pc(pc),
+        rel_pc(rel_pc),
+        function_name(function_name),
+        function_offset(function_offset) {}
+
+  MapInfo* map_info;
+  uint64_t pc;
+  uint64_t rel_pc;
+  std::string function_name;
+  uint64_t function_offset;
+};
+
+// This is a specialized class that should only be used for doing local unwinds.
+// The Unwind call can be made as multiple times on the same object, and it can
+// be called by multiple threads at the same time.
+// It is designed to be used in debugging circumstances to get a stack trace
+// as fast as possible.
+class LocalUnwinder {
+ public:
+  LocalUnwinder() = default;
+  LocalUnwinder(const std::vector<std::string>& skip_libraries) : skip_libraries_(skip_libraries) {}
+  ~LocalUnwinder() = default;
+
+  bool Init();
+
+  bool Unwind(std::vector<LocalFrameData>* frame_info, size_t max_frames);
+
+  bool ShouldSkipLibrary(const std::string& map_name);
+
+  MapInfo* GetMapInfo(uint64_t pc);
+
+  ErrorCode LastErrorCode() { return last_error_.code; }
+  uint64_t LastErrorAddress() { return last_error_.address; }
+
+ private:
+  pthread_rwlock_t maps_rwlock_;
+  std::unique_ptr<LocalUpdatableMaps> maps_ = nullptr;
+  std::shared_ptr<Memory> process_memory_;
+  std::vector<std::string> skip_libraries_;
+  ErrorData last_error_;
+};
+
+}  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_LOCAL_UNWINDER_H
diff --git a/libunwindstack/include/unwindstack/Log.h b/libunwindstack/include/unwindstack/Log.h
index 34eb218..a4f763d 100644
--- a/libunwindstack/include/unwindstack/Log.h
+++ b/libunwindstack/include/unwindstack/Log.h
@@ -14,24 +14,17 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_LOG_H
+#define _LIBUNWINDSTACK_LOG_H
 
-#include <stdarg.h>
 #include <stdint.h>
 
-#if !defined(__printflike)
-#define __printflike(x, y) __attribute__((__format__(printf, x, y)))
-#endif
-
 namespace unwindstack {
 
-namespace Log {
-
-void Error(const char* format, ...) __printflike(1, 2);
-void Info(const char* format, ...) __printflike(1, 2);
-void Info(uint8_t indent, const char* format, ...) __printflike(2, 3);
-void AsyncSafe(const char* format, ...) __printflike(1, 2);
-
-}  // namespace Log
+void log_to_stdout(bool enable);
+void log(uint8_t indent, const char* format, ...);
+void log_async_safe(const char* format, ...);
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_LOG_H
diff --git a/libunwindstack/include/unwindstack/MachineArm.h b/libunwindstack/include/unwindstack/MachineArm.h
index 6b8198e..3f902b1 100644
--- a/libunwindstack/include/unwindstack/MachineArm.h
+++ b/libunwindstack/include/unwindstack/MachineArm.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_MACHINE_ARM_H
+#define _LIBUNWINDSTACK_MACHINE_ARM_H
 
 #include <stdint.h>
 
@@ -45,3 +46,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_MACHINE_ARM_H
diff --git a/libunwindstack/include/unwindstack/MachineArm64.h b/libunwindstack/include/unwindstack/MachineArm64.h
index f1b7c1d..358e3d9 100644
--- a/libunwindstack/include/unwindstack/MachineArm64.h
+++ b/libunwindstack/include/unwindstack/MachineArm64.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_MACHINE_ARM64_H
+#define _LIBUNWINDSTACK_MACHINE_ARM64_H
 
 #include <stdint.h>
 
@@ -69,3 +70,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_MACHINE_ARM64_H
diff --git a/libunwindstack/include/unwindstack/MachineMips.h b/libunwindstack/include/unwindstack/MachineMips.h
index 6a96536..2dfb1e9 100644
--- a/libunwindstack/include/unwindstack/MachineMips.h
+++ b/libunwindstack/include/unwindstack/MachineMips.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_MACHINE_MIPS_H
+#define _LIBUNWINDSTACK_MACHINE_MIPS_H
 
 #include <stdint.h>
 
@@ -61,3 +62,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_MACHINE_MIPS_H
\ No newline at end of file
diff --git a/libunwindstack/include/unwindstack/MachineMips64.h b/libunwindstack/include/unwindstack/MachineMips64.h
index e148efc..34addf2 100644
--- a/libunwindstack/include/unwindstack/MachineMips64.h
+++ b/libunwindstack/include/unwindstack/MachineMips64.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_MACHINE_MIPS64_H
+#define _LIBUNWINDSTACK_MACHINE_MIPS64_H
 
 #include <stdint.h>
 
@@ -61,3 +62,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_MACHINE_MIPS64_H
\ No newline at end of file
diff --git a/libunwindstack/include/unwindstack/MachineX86.h b/libunwindstack/include/unwindstack/MachineX86.h
index ff4fd4b..02adb98 100644
--- a/libunwindstack/include/unwindstack/MachineX86.h
+++ b/libunwindstack/include/unwindstack/MachineX86.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_MACHINE_X86_H
+#define _LIBUNWINDSTACK_MACHINE_X86_H
 
 #include <stdint.h>
 
@@ -46,3 +47,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_MACHINE_X86_H
diff --git a/libunwindstack/include/unwindstack/MachineX86_64.h b/libunwindstack/include/unwindstack/MachineX86_64.h
index 66670e3..af33fea 100644
--- a/libunwindstack/include/unwindstack/MachineX86_64.h
+++ b/libunwindstack/include/unwindstack/MachineX86_64.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_MACHINE_X86_64_H
+#define _LIBUNWINDSTACK_MACHINE_X86_64_H
 
 #include <stdint.h>
 
@@ -47,3 +48,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_MACHINE_X86_64_H
diff --git a/libunwindstack/include/unwindstack/MapInfo.h b/libunwindstack/include/unwindstack/MapInfo.h
index 12711f5..727dc68 100644
--- a/libunwindstack/include/unwindstack/MapInfo.h
+++ b/libunwindstack/include/unwindstack/MapInfo.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_MAP_INFO_H
+#define _LIBUNWINDSTACK_MAP_INFO_H
 
 #include <stdint.h>
 
@@ -37,7 +38,7 @@
 // (for example, 400 process * 400 maps * 128 bytes = 20 MB + string data).
 class MapInfo {
  public:
-  MapInfo(std::shared_ptr<MapInfo>& prev_map, uint64_t start, uint64_t end, uint64_t offset,
+  MapInfo(MapInfo* prev_map, MapInfo* prev_real_map, uint64_t start, uint64_t end, uint64_t offset,
           uint64_t flags, SharedString name)
       : start_(start),
         end_(end),
@@ -45,35 +46,16 @@
         flags_(flags),
         name_(name),
         elf_fields_(nullptr),
-        prev_map_(prev_map) {}
-  MapInfo(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags, SharedString name)
-      : start_(start),
-        end_(end),
-        offset_(offset),
-        flags_(flags),
-        name_(name),
-        elf_fields_(nullptr) {}
-
-  static inline std::shared_ptr<MapInfo> Create(std::shared_ptr<MapInfo>& prev_map,
-                                                uint64_t start, uint64_t end, uint64_t offset,
-                                                uint64_t flags, SharedString name) {
-    auto map_info = std::make_shared<MapInfo>(prev_map, start, end, offset, flags, name);
-    if (prev_map) {
-      prev_map->next_map_ = map_info;
-    }
-    return map_info;
+        prev_map_(prev_map),
+        prev_real_map_(prev_real_map) {
+    if (prev_real_map != nullptr) prev_real_map->next_real_map_ = this;
   }
-  static inline std::shared_ptr<MapInfo> Create(uint64_t start, uint64_t end, uint64_t offset,
-                                                uint64_t flags, SharedString name) {
-    return std::make_shared<MapInfo>(start, end, offset, flags, name);
-  }
-
   ~MapInfo();
 
   // Cached data for mapped ELF files.
   // We allocate this structure lazily since there are much fewer ELFs than maps.
   struct ElfFields {
-    ElfFields() : load_bias_(UINT64_MAX), build_id_(0) {}
+    ElfFields() : load_bias_(INT64_MAX), build_id_(0) {}
 
     std::shared_ptr<Elf> elf_;
     // The offset of the beginning of this mapping to the beginning of the
@@ -87,7 +69,7 @@
     // shared libraries into a read-only and read-execute map.
     uint64_t elf_start_offset_ = 0;
 
-    std::atomic_uint64_t load_bias_;
+    std::atomic_int64_t load_bias_;
 
     // This is a pointer to a new'd std::string.
     // Using an atomic value means that we don't need to lock and will
@@ -101,38 +83,6 @@
     std::mutex elf_mutex_;
   };
 
-  // True if the file named by this map is not actually readable and the
-  // elf is using the data in memory.
-  bool ElfFileNotReadable();
-
-  // This is the previous map with the same name that is not empty and with
-  // a 0 offset. For example, this set of maps:
-  //  1000-2000  r--p 000000 00:00 0 libc.so
-  //  2000-3000  ---p 000000 00:00 0
-  //  3000-4000  r-xp 003000 00:00 0 libc.so
-  // The last map's prev_map would point to the 2000-3000 map, while
-  // GetPrevRealMap() would point to the 1000-2000 map.
-  // NOTE: If a map is encountered that has a non-zero offset, or has a
-  //       a name different from the current map, then GetPrevRealMap()
-  //       returns nullptr.
-  std::shared_ptr<MapInfo> GetPrevRealMap();
-  // This is the next map with the same name that is not empty and with
-  // a 0 offset. For the example above, the first map's GetNextRealMap()
-  // would be the 3000-4000 map.
-  // NOTE: If a map is encountered that has a non-zero offset, or has a
-  //       a name different from the current map, then GetNextRealMap()
-  //       returns nullptr.
-  std::shared_ptr<MapInfo> GetNextRealMap();
-
-  // This is guaranteed to give out the Elf object associated with the
-  // object. The invariant is that once the Elf object is set under the
-  // lock in a MapInfo object it never changes and is not freed until
-  // the MapInfo object is destructed.
-  inline Elf* GetElfObj() {
-    std::lock_guard<std::mutex> guard(elf_mutex());
-    return elf().get();
-  }
-
   inline uint64_t start() const { return start_; }
   inline void set_start(uint64_t value) { start_ = value; }
 
@@ -159,8 +109,8 @@
   inline uint64_t elf_start_offset() { return GetElfFields().elf_start_offset_; }
   inline void set_elf_start_offset(uint64_t value) { GetElfFields().elf_start_offset_ = value; }
 
-  inline std::atomic_uint64_t& load_bias() { return GetElfFields().load_bias_; }
-  inline void set_load_bias(uint64_t value) { GetElfFields().load_bias_ = value; }
+  inline std::atomic_int64_t& load_bias() { return GetElfFields().load_bias_; }
+  inline void set_load_bias(int64_t value) { GetElfFields().load_bias_ = value; }
 
   inline std::atomic<SharedString*>& build_id() { return GetElfFields().build_id_; }
   inline void set_build_id(SharedString* value) { GetElfFields().build_id_ = value; }
@@ -168,28 +118,20 @@
   inline bool memory_backed_elf() { return GetElfFields().memory_backed_elf_; }
   inline void set_memory_backed_elf(bool value) { GetElfFields().memory_backed_elf_ = value; }
 
-  inline std::shared_ptr<MapInfo> prev_map() const { return prev_map_.lock(); }
-  inline void set_prev_map(std::shared_ptr<MapInfo>& value) { prev_map_ = value; }
+  inline MapInfo* prev_map() const { return prev_map_; }
+  inline void set_prev_map(MapInfo* value) { prev_map_ = value; }
 
-  inline std::shared_ptr<MapInfo> next_map() const { return next_map_.lock(); }
-  inline void set_next_map(std::shared_ptr<MapInfo>& value) { next_map_ = value; }
+  inline MapInfo* prev_real_map() const { return prev_real_map_; }
+  inline void set_prev_real_map(MapInfo* value) { prev_real_map_ = value; }
+
+  inline MapInfo* next_real_map() const { return next_real_map_; }
+  inline void set_next_real_map(MapInfo* value) { next_real_map_ = value; }
 
   // This function guarantees it will never return nullptr.
   Elf* GetElf(const std::shared_ptr<Memory>& process_memory, ArchEnum expected_arch);
 
-  // Guaranteed to return the proper value if GetElf() has been called.
-  uint64_t GetLoadBias();
-
-  // Will get the proper value even if GetElf() hasn't been called.
   uint64_t GetLoadBias(const std::shared_ptr<Memory>& process_memory);
 
-  // This returns the name of the map plus the soname if this particular
-  // map represents an elf file that is contained inside of another file.
-  // The format of this soname embedded name is:
-  //   file.apk!libutils.so
-  // Otherwise, this function only returns the name of the map.
-  std::string GetFullName();
-
   Memory* CreateMemory(const std::shared_ptr<Memory>& process_memory);
 
   bool GetFunctionName(uint64_t addr, SharedString* name, uint64_t* func_offset);
@@ -226,8 +168,20 @@
 
   std::atomic<ElfFields*> elf_fields_;
 
-  std::weak_ptr<MapInfo> prev_map_;
-  std::weak_ptr<MapInfo> next_map_;
+  MapInfo* prev_map_ = nullptr;
+  // This is the previous map that is not empty with a 0 offset. For
+  // example, this set of maps:
+  //  1000-2000  r--p 000000 00:00 0 libc.so
+  //  2000-3000  ---p 000000 00:00 0 libc.so
+  //  3000-4000  r-xp 003000 00:00 0 libc.so
+  // The last map's prev_map would point to the 2000-3000 map, while the
+  // prev_real_map would point to the 1000-2000 map.
+  MapInfo* prev_real_map_ = nullptr;
+
+  // Same as above but set to point to the next map.
+  MapInfo* next_real_map_ = nullptr;
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_MAP_INFO_H
diff --git a/libunwindstack/include/unwindstack/Maps.h b/libunwindstack/include/unwindstack/Maps.h
index d9e1383..be013a4 100644
--- a/libunwindstack/include/unwindstack/Maps.h
+++ b/libunwindstack/include/unwindstack/Maps.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_MAPS_H
+#define _LIBUNWINDSTACK_MAPS_H
 
 #include <pthread.h>
 #include <sys/types.h>
@@ -49,35 +50,34 @@
   Maps(Maps&&) = default;
   Maps& operator=(Maps&&) = default;
 
-  virtual std::shared_ptr<MapInfo> Find(uint64_t pc);
+  virtual MapInfo* Find(uint64_t pc);
 
   virtual bool Parse();
 
   virtual const std::string GetMapsFile() const { return ""; }
 
-  void Add(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags, const std::string& name);
   void Add(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags, const std::string& name,
            uint64_t load_bias);
 
   void Sort();
 
-  typedef std::vector<std::shared_ptr<MapInfo>>::iterator iterator;
+  typedef std::vector<std::unique_ptr<MapInfo>>::iterator iterator;
   iterator begin() { return maps_.begin(); }
   iterator end() { return maps_.end(); }
 
-  typedef std::vector<std::shared_ptr<MapInfo>>::const_iterator const_iterator;
+  typedef std::vector<std::unique_ptr<MapInfo>>::const_iterator const_iterator;
   const_iterator begin() const { return maps_.begin(); }
   const_iterator end() const { return maps_.end(); }
 
   size_t Total() { return maps_.size(); }
 
-  std::shared_ptr<MapInfo> Get(size_t index) {
+  MapInfo* Get(size_t index) {
     if (index >= maps_.size()) return nullptr;
-    return maps_[index];
+    return maps_[index].get();
   }
 
  protected:
-  std::vector<std::shared_ptr<MapInfo>> maps_;
+  std::vector<std::unique_ptr<MapInfo>> maps_;
 };
 
 class RemoteMaps : public Maps {
@@ -102,7 +102,7 @@
   LocalUpdatableMaps();
   virtual ~LocalUpdatableMaps() = default;
 
-  std::shared_ptr<MapInfo> Find(uint64_t pc) override;
+  MapInfo* Find(uint64_t pc) override;
 
   bool Parse() override;
 
@@ -110,7 +110,9 @@
 
   bool Reparse(/*out*/ bool* any_changed = nullptr);
 
- private:
+ protected:
+  std::vector<std::unique_ptr<MapInfo>> saved_maps_;
+
   pthread_rwlock_t maps_rwlock_;
 };
 
@@ -137,3 +139,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_MAPS_H
diff --git a/libunwindstack/include/unwindstack/Memory.h b/libunwindstack/include/unwindstack/Memory.h
index d6ca29e..b7bede6 100644
--- a/libunwindstack/include/unwindstack/Memory.h
+++ b/libunwindstack/include/unwindstack/Memory.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_MEMORY_H
+#define _LIBUNWINDSTACK_MEMORY_H
 
 #include <stdint.h>
 #include <sys/types.h>
@@ -64,3 +65,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_MEMORY_H
diff --git a/libunwindstack/include/unwindstack/Regs.h b/libunwindstack/include/unwindstack/Regs.h
index e49370d..45e96df 100644
--- a/libunwindstack/include/unwindstack/Regs.h
+++ b/libunwindstack/include/unwindstack/Regs.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_REGS_H
+#define _LIBUNWINDSTACK_REGS_H
 
 #include <stdint.h>
 #include <unistd.h>
@@ -81,7 +82,6 @@
   virtual Regs* Clone() = 0;
 
   static ArchEnum CurrentArch();
-  static ArchEnum RemoteGetArch(pid_t pid);
   static Regs* RemoteGet(pid_t pid);
   static Regs* CreateFromUcontext(ArchEnum arch, void* ucontext);
   static Regs* CreateFromLocal();
@@ -116,3 +116,5 @@
 uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf, ArchEnum arch);
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_REGS_H
diff --git a/libunwindstack/include/unwindstack/RegsArm.h b/libunwindstack/include/unwindstack/RegsArm.h
index 5596605..fbb34e7 100644
--- a/libunwindstack/include/unwindstack/RegsArm.h
+++ b/libunwindstack/include/unwindstack/RegsArm.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_REGS_ARM_H
+#define _LIBUNWINDSTACK_REGS_ARM_H
 
 #include <stdint.h>
 
@@ -55,3 +56,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_REGS_ARM_H
diff --git a/libunwindstack/include/unwindstack/RegsArm64.h b/libunwindstack/include/unwindstack/RegsArm64.h
index d12a043..508366e 100644
--- a/libunwindstack/include/unwindstack/RegsArm64.h
+++ b/libunwindstack/include/unwindstack/RegsArm64.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_REGS_ARM64_H
+#define _LIBUNWINDSTACK_REGS_ARM64_H
 
 #include <stdint.h>
 
@@ -72,3 +73,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_REGS_ARM64_H
diff --git a/libunwindstack/include/unwindstack/RegsGetLocal.h b/libunwindstack/include/unwindstack/RegsGetLocal.h
index bf3f767..ac171b9 100644
--- a/libunwindstack/include/unwindstack/RegsGetLocal.h
+++ b/libunwindstack/include/unwindstack/RegsGetLocal.h
@@ -26,7 +26,8 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_REGS_GET_LOCAL_H
+#define _LIBUNWINDSTACK_REGS_GET_LOCAL_H
 
 namespace unwindstack {
 
@@ -90,4 +91,7 @@
   AsmGetRegs(regs->RawData());
 }
 
+
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_REGS_GET_LOCAL_H
diff --git a/libunwindstack/include/unwindstack/RegsMips.h b/libunwindstack/include/unwindstack/RegsMips.h
index 61e4dbf..dc09b83 100644
--- a/libunwindstack/include/unwindstack/RegsMips.h
+++ b/libunwindstack/include/unwindstack/RegsMips.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_REGS_MIPS_H
+#define _LIBUNWINDSTACK_REGS_MIPS_H
 
 #include <stdint.h>
 
@@ -55,3 +56,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_REGS_MIPS_H
diff --git a/libunwindstack/include/unwindstack/RegsMips64.h b/libunwindstack/include/unwindstack/RegsMips64.h
index 012a8f0..64a80dc 100644
--- a/libunwindstack/include/unwindstack/RegsMips64.h
+++ b/libunwindstack/include/unwindstack/RegsMips64.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_REGS_MIPS64_H
+#define _LIBUNWINDSTACK_REGS_MIPS64_H
 
 #include <stdint.h>
 
@@ -55,3 +56,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_REGS_MIPS64_H
diff --git a/libunwindstack/include/unwindstack/RegsX86.h b/libunwindstack/include/unwindstack/RegsX86.h
index d8245ee..cfbdda6 100644
--- a/libunwindstack/include/unwindstack/RegsX86.h
+++ b/libunwindstack/include/unwindstack/RegsX86.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_REGS_X86_H
+#define _LIBUNWINDSTACK_REGS_X86_H
 
 #include <stdint.h>
 
@@ -58,3 +59,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_REGS_X86_H
diff --git a/libunwindstack/include/unwindstack/RegsX86_64.h b/libunwindstack/include/unwindstack/RegsX86_64.h
index 90fee93..a11aef0 100644
--- a/libunwindstack/include/unwindstack/RegsX86_64.h
+++ b/libunwindstack/include/unwindstack/RegsX86_64.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_REGS_X86_64_H
+#define _LIBUNWINDSTACK_REGS_X86_64_H
 
 #include <stdint.h>
 
@@ -58,3 +59,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_REGS_X86_64_H
diff --git a/libunwindstack/include/unwindstack/SharedString.h b/libunwindstack/include/unwindstack/SharedString.h
index 1eb4e21..a82c4fe 100644
--- a/libunwindstack/include/unwindstack/SharedString.h
+++ b/libunwindstack/include/unwindstack/SharedString.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_SHAREDSTRING_H
+#define _LIBUNWINDSTACK_SHAREDSTRING_H
 
 #include <memory>
 #include <string>
@@ -72,3 +73,4 @@
 }
 
 }  // namespace unwindstack
+#endif  // _LIBUNWINDSTACK_SHAREDSTRING_H
diff --git a/libunwindstack/include/unwindstack/UcontextArm.h b/libunwindstack/include/unwindstack/UcontextArm.h
index 0d7f90d..7d1ec3b 100644
--- a/libunwindstack/include/unwindstack/UcontextArm.h
+++ b/libunwindstack/include/unwindstack/UcontextArm.h
@@ -26,7 +26,8 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_UCONTEXT_ARM_H
+#define _LIBUNWINDSTACK_UCONTEXT_ARM_H
 
 #include <stdint.h>
 
@@ -58,3 +59,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_UCONTEXT_ARM_H
diff --git a/libunwindstack/include/unwindstack/UcontextArm64.h b/libunwindstack/include/unwindstack/UcontextArm64.h
index 49278b3..a68be3b 100644
--- a/libunwindstack/include/unwindstack/UcontextArm64.h
+++ b/libunwindstack/include/unwindstack/UcontextArm64.h
@@ -26,7 +26,8 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_UCONTEXT_ARM64_H
+#define _LIBUNWINDSTACK_UCONTEXT_ARM64_H
 
 #include <stdint.h>
 
@@ -64,3 +65,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_UCONTEXT_ARM64_H
diff --git a/libunwindstack/include/unwindstack/UcontextMips.h b/libunwindstack/include/unwindstack/UcontextMips.h
index c75e469..02e33b6 100644
--- a/libunwindstack/include/unwindstack/UcontextMips.h
+++ b/libunwindstack/include/unwindstack/UcontextMips.h
@@ -26,7 +26,8 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_UCONTEXT_MIPS_H
+#define _LIBUNWINDSTACK_UCONTEXT_MIPS_H
 
 #include <stdint.h>
 
@@ -57,3 +58,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_UCONTEXT_MIPS_H
diff --git a/libunwindstack/include/unwindstack/UcontextMips64.h b/libunwindstack/include/unwindstack/UcontextMips64.h
index c63218f..5b92a55 100644
--- a/libunwindstack/include/unwindstack/UcontextMips64.h
+++ b/libunwindstack/include/unwindstack/UcontextMips64.h
@@ -26,7 +26,8 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_UCONTEXT_MIPS64_H
+#define _LIBUNWINDSTACK_UCONTEXT_MIPS64_H
 
 #include <stdint.h>
 
@@ -64,3 +65,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_UCONTEXT_MIPS64_H
diff --git a/libunwindstack/include/unwindstack/UcontextX86.h b/libunwindstack/include/unwindstack/UcontextX86.h
index 9dfdf2a..c96ebb7 100644
--- a/libunwindstack/include/unwindstack/UcontextX86.h
+++ b/libunwindstack/include/unwindstack/UcontextX86.h
@@ -26,7 +26,8 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_UCONTEXT_X86_H
+#define _LIBUNWINDSTACK_UCONTEXT_X86_H
 
 #include <stdint.h>
 
@@ -72,3 +73,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_UCONTEXT_X86_H
diff --git a/libunwindstack/include/unwindstack/UcontextX86_64.h b/libunwindstack/include/unwindstack/UcontextX86_64.h
index 2801217..4e163e5 100644
--- a/libunwindstack/include/unwindstack/UcontextX86_64.h
+++ b/libunwindstack/include/unwindstack/UcontextX86_64.h
@@ -26,7 +26,8 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_UCONTEXT_X86_64_H
+#define _LIBUNWINDSTACK_UCONTEXT_X86_64_H
 
 #include <stdint.h>
 
@@ -77,3 +78,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_UCONTEXT_X86_64_H
diff --git a/libunwindstack/include/unwindstack/Unwinder.h b/libunwindstack/include/unwindstack/Unwinder.h
index d78da5c..bcd0d42 100644
--- a/libunwindstack/include/unwindstack/Unwinder.h
+++ b/libunwindstack/include/unwindstack/Unwinder.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_UNWINDER_H
+#define _LIBUNWINDSTACK_UNWINDER_H
 
 #include <stdint.h>
 #include <sys/types.h>
@@ -48,7 +49,18 @@
   SharedString function_name;
   uint64_t function_offset = 0;
 
-  std::shared_ptr<MapInfo> map_info;
+  SharedString map_name;
+  // The offset from the first map representing the frame. When there are
+  // two maps (read-only and read-execute) this will be the offset from
+  // the read-only map. When there is only one map, this will be the
+  // same as the actual offset of the map and match map_exact_offset.
+  uint64_t map_elf_start_offset = 0;
+  // The actual offset from the map where the pc lies.
+  uint64_t map_exact_offset = 0;
+  uint64_t map_start = 0;
+  uint64_t map_end = 0;
+  uint64_t map_load_bias = 0;
+  int map_flags = 0;
 };
 
 class Unwinder {
@@ -82,9 +94,6 @@
   std::string FormatFrame(size_t frame_num) const;
   std::string FormatFrame(const FrameData& frame) const;
 
-  static std::string FormatFrame(ArchEnum arch, const FrameData& frame,
-                                 bool display_build_id = true);
-
   void SetArch(ArchEnum arch) { arch_ = arch; };
 
   void SetJitDebug(JitDebug* jit_debug);
@@ -100,11 +109,17 @@
   // set to an empty string and the function offset being set to zero.
   void SetResolveNames(bool resolve) { resolve_names_ = resolve; }
 
+  // Enable/disable soname printing the soname for a map name if the elf is
+  // embedded in a file. This is enabled by default.
+  // NOTE: This does nothing unless resolving names is enabled.
+  void SetEmbeddedSoname(bool embedded_soname) { embedded_soname_ = embedded_soname; }
+
   void SetDisplayBuildID(bool display_build_id) { display_build_id_ = display_build_id; }
 
   void SetDexFiles(DexFiles* dex_files);
 
-  const ErrorData& LastError() { return last_error_; }
+  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; }
@@ -123,8 +138,6 @@
   Unwinder(size_t max_frames, Maps* maps = nullptr) : max_frames_(max_frames), maps_(maps) {}
   Unwinder(size_t max_frames, ArchEnum arch, Maps* maps = nullptr)
       : max_frames_(max_frames), maps_(maps), arch_(arch) {}
-  Unwinder(size_t max_frames, ArchEnum arch, Maps* maps, std::shared_ptr<Memory>& process_memory)
-      : max_frames_(max_frames), maps_(maps), process_memory_(process_memory), arch_(arch) {}
 
   void ClearErrors() {
     warnings_ = WARNING_NONE;
@@ -133,18 +146,21 @@
   }
 
   void FillInDexFrame();
-  FrameData* FillInFrame(std::shared_ptr<MapInfo>& map_info, Elf* elf, uint64_t rel_pc,
-                         uint64_t pc_adjustment);
+  FrameData* FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, uint64_t pc_adjustment);
 
   size_t max_frames_;
-  Maps* maps_ = nullptr;
+  Maps* maps_;
   Regs* regs_;
   std::vector<FrameData> frames_;
   std::shared_ptr<Memory> process_memory_;
   JitDebug* jit_debug_ = nullptr;
   DexFiles* dex_files_ = nullptr;
   bool resolve_names_ = true;
+  bool embedded_soname_ = true;
   bool display_build_id_ = false;
+  // True if at least one elf file is coming from memory and not the related
+  // file. This is only true if there is an actual file backing up the elf.
+  bool elf_from_memory_not_file_ = false;
   ErrorData last_error_;
   uint64_t warnings_;
   ArchEnum arch_ = ARCH_UNKNOWN;
@@ -154,15 +170,14 @@
  public:
   UnwinderFromPid(size_t max_frames, pid_t pid, Maps* maps = nullptr)
       : Unwinder(max_frames, maps), pid_(pid) {}
-  UnwinderFromPid(size_t max_frames, pid_t pid, std::shared_ptr<Memory>& process_memory)
-      : Unwinder(max_frames, nullptr, process_memory), pid_(pid) {}
   UnwinderFromPid(size_t max_frames, pid_t pid, ArchEnum arch, Maps* maps = nullptr)
       : Unwinder(max_frames, arch, maps), pid_(pid) {}
-  UnwinderFromPid(size_t max_frames, pid_t pid, ArchEnum arch, Maps* maps,
-                  std::shared_ptr<Memory>& process_memory)
-      : Unwinder(max_frames, arch, maps, process_memory), pid_(pid) {}
   virtual ~UnwinderFromPid() = default;
 
+  void SetProcessMemory(std::shared_ptr<Memory>& process_memory) {
+    process_memory_ = process_memory;
+  }
+
   bool Init();
 
   void Unwind(const std::vector<std::string>* initial_map_names_to_skip = nullptr,
@@ -179,7 +194,6 @@
 class ThreadUnwinder : public UnwinderFromPid {
  public:
   ThreadUnwinder(size_t max_frames, Maps* maps = nullptr);
-  ThreadUnwinder(size_t max_frames, Maps* maps, std::shared_ptr<Memory>& process_memory);
   ThreadUnwinder(size_t max_frames, const ThreadUnwinder* unwinder);
   virtual ~ThreadUnwinder() = default;
 
@@ -187,7 +201,7 @@
 
   void Unwind(const std::vector<std::string>*, const std::vector<std::string>*) override {}
 
-  void UnwindWithSignal(int signal, pid_t tid, std::unique_ptr<Regs>* initial_regs = nullptr,
+  void UnwindWithSignal(int signal, pid_t tid,
                         const std::vector<std::string>* initial_map_names_to_skip = nullptr,
                         const std::vector<std::string>* map_suffixes_to_ignore = nullptr);
 
@@ -196,3 +210,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_UNWINDER_H
diff --git a/libunwindstack/include/unwindstack/UserArm.h b/libunwindstack/include/unwindstack/UserArm.h
index 725a35b..7388c03 100644
--- a/libunwindstack/include/unwindstack/UserArm.h
+++ b/libunwindstack/include/unwindstack/UserArm.h
@@ -26,7 +26,8 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_USER_ARM_H
+#define _LIBUNWINDSTACK_USER_ARM_H
 
 namespace unwindstack {
 
@@ -35,3 +36,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_USER_ARM_H
diff --git a/libunwindstack/include/unwindstack/UserArm64.h b/libunwindstack/include/unwindstack/UserArm64.h
index 0e16cd6..d74983f 100644
--- a/libunwindstack/include/unwindstack/UserArm64.h
+++ b/libunwindstack/include/unwindstack/UserArm64.h
@@ -26,7 +26,8 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_USER_ARM64_H
+#define _LIBUNWINDSTACK_USER_ARM64_H
 
 namespace unwindstack {
 
@@ -38,3 +39,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_USER_ARM64_H
diff --git a/libunwindstack/include/unwindstack/UserMips.h b/libunwindstack/include/unwindstack/UserMips.h
index 148ef93..184be4f 100644
--- a/libunwindstack/include/unwindstack/UserMips.h
+++ b/libunwindstack/include/unwindstack/UserMips.h
@@ -26,7 +26,8 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_USER_MIPS_H
+#define _LIBUNWINDSTACK_USER_MIPS_H
 
 namespace unwindstack {
 
@@ -40,3 +41,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_USER_MIPS_H
diff --git a/libunwindstack/include/unwindstack/UserMips64.h b/libunwindstack/include/unwindstack/UserMips64.h
index 9844307..c46befd 100644
--- a/libunwindstack/include/unwindstack/UserMips64.h
+++ b/libunwindstack/include/unwindstack/UserMips64.h
@@ -26,7 +26,8 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_USER_MIPS64_H
+#define _LIBUNWINDSTACK_USER_MIPS64_H
 
 namespace unwindstack {
 
@@ -40,3 +41,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_USER_MIPS64_H
diff --git a/libunwindstack/include/unwindstack/UserX86.h b/libunwindstack/include/unwindstack/UserX86.h
index 9508010..a040560 100644
--- a/libunwindstack/include/unwindstack/UserX86.h
+++ b/libunwindstack/include/unwindstack/UserX86.h
@@ -26,7 +26,8 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_USER_X86_H
+#define _LIBUNWINDSTACK_USER_X86_H
 
 namespace unwindstack {
 
@@ -51,3 +52,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_USER_X86_H
diff --git a/libunwindstack/include/unwindstack/UserX86_64.h b/libunwindstack/include/unwindstack/UserX86_64.h
index d7ff2e2..b80d201 100644
--- a/libunwindstack/include/unwindstack/UserX86_64.h
+++ b/libunwindstack/include/unwindstack/UserX86_64.h
@@ -26,7 +26,8 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_USER_X86_64_H
+#define _LIBUNWINDSTACK_USER_X86_64_H
 
 namespace unwindstack {
 
@@ -61,3 +62,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_USER_X86_64_H
diff --git a/libunwindstack/offline_files/apk_rorx_arm64/fake.apk b/libunwindstack/offline_files/apk_rorx_arm64/fake.apk
deleted file mode 100644
index 9bd1f85..0000000
--- a/libunwindstack/offline_files/apk_rorx_arm64/fake.apk
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/apk_rorx_arm64/links.txt b/libunwindstack/offline_files/apk_rorx_arm64/links.txt
deleted file mode 100644
index 42da529..0000000
--- a/libunwindstack/offline_files/apk_rorx_arm64/links.txt
+++ /dev/null
@@ -1 +0,0 @@
-../common/libc.so_3106fb6eab1b2dc6704157e908a50eba libc.so
diff --git a/libunwindstack/offline_files/apk_rorx_arm64/maps.txt b/libunwindstack/offline_files/apk_rorx_arm64/maps.txt
deleted file mode 100644
index 863c13e..0000000
--- a/libunwindstack/offline_files/apk_rorx_arm64/maps.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-603b0c4000-603b0c5000 r--p 0 00:00 0   run
-603b0c5000-603b0c6000 r-xp 1000 00:00 0   run
-7426d2d000-7426d2e000 r--p 4000 00:00 0   fake.apk
-7426d2e000-7426d2f000 r-xp 5000 00:00 0   fake.apk
-76b6da8000-76b6de4000 r--p 0 00:00 0   libc.so
-76b6de4000-76b6e65000 r-xp 3c000 00:00 0   libc.so
diff --git a/libunwindstack/offline_files/apk_rorx_arm64/output.txt b/libunwindstack/offline_files/apk_rorx_arm64/output.txt
deleted file mode 100644
index 0636f7f..0000000
--- a/libunwindstack/offline_files/apk_rorx_arm64/output.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-  #00 pc 0000000000001030  fake.apk!libunwindstack_local.so (offset 0x4000) (TestlibLevel4+28)
-  #01 pc 000000000000108c  fake.apk!libunwindstack_local.so (offset 0x4000) (TestlibLevel3+28)
-  #02 pc 00000000000010b8  fake.apk!libunwindstack_local.so (offset 0x4000) (TestlibLevel2+28)
-  #03 pc 00000000000010e4  fake.apk!libunwindstack_local.so (offset 0x4000) (TestlibLevel1+28)
-  #04 pc 0000000000001154  run (main+256)
-  #05 pc 0000000000048b10  libc.so (__libc_init+96)
diff --git a/libunwindstack/offline_files/apk_rorx_arm64/regs.txt b/libunwindstack/offline_files/apk_rorx_arm64/regs.txt
deleted file mode 100644
index da2ceb5..0000000
--- a/libunwindstack/offline_files/apk_rorx_arm64/regs.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-x0: 0
-x1: 0
-x2: 76bc49ee88
-x3: 11b030000
-x4: 800000
-x5: 5462727542000000
-x6: 804275726254
-x7: 5678727440ff306b
-x8: 0
-x9: e41
-x10: e41
-x11: 10
-x12: 76bc385f80
-x13: f66dca96235a549b
-x14: a83626c39758e9a
-x15: fabaf3feaa5334a
-x16: 7426d2f1e0
-x17: 7426d2e014
-x18: 76bb4bc000
-x19: 7fe740cd61
-x20: 3
-x21: 7fe740ce28
-x22: 76bb091000
-x23: 0
-x24: 0
-x25: 0
-x26: 0
-x27: 0
-x28: 0
-x29: 7fe740ccc0
-lr: 7426d2e090
-sp: 7fe740cc90
-pc: 7426d2e030
-pst: 80001000
diff --git a/libunwindstack/offline_files/apk_rorx_arm64/run b/libunwindstack/offline_files/apk_rorx_arm64/run
deleted file mode 100644
index b984d44..0000000
--- a/libunwindstack/offline_files/apk_rorx_arm64/run
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/apk_rorx_arm64/stack.data b/libunwindstack/offline_files/apk_rorx_arm64/stack.data
deleted file mode 100644
index 5a609c7..0000000
--- a/libunwindstack/offline_files/apk_rorx_arm64/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/apk_rorx_unreadable_arm64/fake.apk b/libunwindstack/offline_files/apk_rorx_unreadable_arm64/fake.apk
deleted file mode 100644
index 9bd1f85..0000000
--- a/libunwindstack/offline_files/apk_rorx_unreadable_arm64/fake.apk
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/apk_rorx_unreadable_arm64/links.txt b/libunwindstack/offline_files/apk_rorx_unreadable_arm64/links.txt
deleted file mode 100644
index 42da529..0000000
--- a/libunwindstack/offline_files/apk_rorx_unreadable_arm64/links.txt
+++ /dev/null
@@ -1 +0,0 @@
-../common/libc.so_3106fb6eab1b2dc6704157e908a50eba libc.so
diff --git a/libunwindstack/offline_files/apk_rorx_unreadable_arm64/maps.txt b/libunwindstack/offline_files/apk_rorx_unreadable_arm64/maps.txt
deleted file mode 100644
index d0fd187..0000000
--- a/libunwindstack/offline_files/apk_rorx_unreadable_arm64/maps.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-603b0c4000-603b0c5000 r--p 0 00:00 0   run
-603b0c5000-603b0c6000 r-xp 1000 00:00 0   run
-7426d2d000-7426d2e000 r--p 4000 00:00 0   unreadable.apk
-7426d2e000-7426d2f000 r-xp 5000 00:00 0   unreadable.apk
-76b6da8000-76b6de4000 r--p 0 00:00 0   libc.so
-76b6de4000-76b6e65000 r-xp 3c000 00:00 0   libc.so
diff --git a/libunwindstack/offline_files/apk_rorx_unreadable_arm64/output.txt b/libunwindstack/offline_files/apk_rorx_unreadable_arm64/output.txt
deleted file mode 100644
index dddf4da..0000000
--- a/libunwindstack/offline_files/apk_rorx_unreadable_arm64/output.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-  #00 pc 0000000000001030  unreadable.apk (offset 0x4000)
-  #01 pc 000000000000108c  unreadable.apk (offset 0x4000)
-  #02 pc 00000000000010b8  unreadable.apk (offset 0x4000)
-  #03 pc 00000000000010e4  unreadable.apk (offset 0x4000)
-  #04 pc 0000000000001154  run (main+256)
-  #05 pc 0000000000048b10  libc.so (__libc_init+96)
diff --git a/libunwindstack/offline_files/apk_rorx_unreadable_arm64/regs.txt b/libunwindstack/offline_files/apk_rorx_unreadable_arm64/regs.txt
deleted file mode 100644
index da2ceb5..0000000
--- a/libunwindstack/offline_files/apk_rorx_unreadable_arm64/regs.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-x0: 0
-x1: 0
-x2: 76bc49ee88
-x3: 11b030000
-x4: 800000
-x5: 5462727542000000
-x6: 804275726254
-x7: 5678727440ff306b
-x8: 0
-x9: e41
-x10: e41
-x11: 10
-x12: 76bc385f80
-x13: f66dca96235a549b
-x14: a83626c39758e9a
-x15: fabaf3feaa5334a
-x16: 7426d2f1e0
-x17: 7426d2e014
-x18: 76bb4bc000
-x19: 7fe740cd61
-x20: 3
-x21: 7fe740ce28
-x22: 76bb091000
-x23: 0
-x24: 0
-x25: 0
-x26: 0
-x27: 0
-x28: 0
-x29: 7fe740ccc0
-lr: 7426d2e090
-sp: 7fe740cc90
-pc: 7426d2e030
-pst: 80001000
diff --git a/libunwindstack/offline_files/apk_rorx_unreadable_arm64/run b/libunwindstack/offline_files/apk_rorx_unreadable_arm64/run
deleted file mode 100644
index b984d44..0000000
--- a/libunwindstack/offline_files/apk_rorx_unreadable_arm64/run
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/apk_rorx_unreadable_arm64/stack.data b/libunwindstack/offline_files/apk_rorx_unreadable_arm64/stack.data
deleted file mode 100644
index 5a609c7..0000000
--- a/libunwindstack/offline_files/apk_rorx_unreadable_arm64/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/apk_rx_arm64/links.txt b/libunwindstack/offline_files/apk_rx_arm64/links.txt
deleted file mode 100644
index 42da529..0000000
--- a/libunwindstack/offline_files/apk_rx_arm64/links.txt
+++ /dev/null
@@ -1 +0,0 @@
-../common/libc.so_3106fb6eab1b2dc6704157e908a50eba libc.so
diff --git a/libunwindstack/offline_files/apk_rx_arm64/maps.txt b/libunwindstack/offline_files/apk_rx_arm64/maps.txt
deleted file mode 100644
index 7e23cb0..0000000
--- a/libunwindstack/offline_files/apk_rx_arm64/maps.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-5e004ef000-5e004f0000 r--p 0 00:00 0   run
-5e004f0000-5e004f1000 r-xp 1000 00:00 0   run
-7cb0e62000-7cb0e63000 r-xp 4000 00:00 0   fake.apk
-7f410dc000-7f41118000 r--p 0 00:00 0   libc.so
-7f41118000-7f41199000 r-xp 3c000 00:00 0   libc.so
diff --git a/libunwindstack/offline_files/apk_rx_arm64/output.txt b/libunwindstack/offline_files/apk_rx_arm64/output.txt
deleted file mode 100644
index c033076..0000000
--- a/libunwindstack/offline_files/apk_rx_arm64/output.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-  #00 pc 000000000000066c  fake.apk!libunwindstack_local.so (offset 0x4000) (TestlibLevel4+36)
-  #01 pc 00000000000006c0  fake.apk!libunwindstack_local.so (offset 0x4000) (TestlibLevel3+28)
-  #02 pc 00000000000006ec  fake.apk!libunwindstack_local.so (offset 0x4000) (TestlibLevel2+28)
-  #03 pc 0000000000000718  fake.apk!libunwindstack_local.so (offset 0x4000) (TestlibLevel1+28)
-  #04 pc 0000000000001154  run (main+256)
-  #05 pc 0000000000048b10  libc.so (__libc_init+96)
diff --git a/libunwindstack/offline_files/apk_rx_arm64/regs.txt b/libunwindstack/offline_files/apk_rx_arm64/regs.txt
deleted file mode 100644
index 1f6e4c6..0000000
--- a/libunwindstack/offline_files/apk_rx_arm64/regs.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-x0: 0
-x1: 0
-x2: 7f42f67e88
-x3: 11b030000
-x4: 800000
-x5: 5462727542000000
-x6: 804275726254
-x7: 5678727440ff306b
-x8: 0
-x9: 1014
-x10: 1014
-x11: 10
-x12: 7f42e4ef80
-x13: 2f75fd4dd1b37121
-x14: 7
-x15: fabaf3feaa5334a
-x16: 7cb0e631e0
-x17: 7cb0e62648
-x18: 7f426ea000
-x19: 7fe563bf61
-x20: 3
-x21: 7fe563c028
-x22: 7f41b5a000
-x23: 0
-x24: 0
-x25: 0
-x26: 0
-x27: 0
-x28: 0
-x29: 7fe563bec0
-lr: 7cb0e626c4
-sp: 7fe563be90
-pc: 7cb0e6266c
-pst: 80001000
diff --git a/libunwindstack/offline_files/apk_rx_arm64/run b/libunwindstack/offline_files/apk_rx_arm64/run
deleted file mode 100644
index b984d44..0000000
--- a/libunwindstack/offline_files/apk_rx_arm64/run
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/apk_rx_arm64/stack.data b/libunwindstack/offline_files/apk_rx_arm64/stack.data
deleted file mode 100644
index 5ce83d4..0000000
--- a/libunwindstack/offline_files/apk_rx_arm64/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/apk_rx_unreadable_arm64/fake.apk b/libunwindstack/offline_files/apk_rx_unreadable_arm64/fake.apk
deleted file mode 100644
index 1f45187..0000000
--- a/libunwindstack/offline_files/apk_rx_unreadable_arm64/fake.apk
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/apk_rx_unreadable_arm64/links.txt b/libunwindstack/offline_files/apk_rx_unreadable_arm64/links.txt
deleted file mode 100644
index 42da529..0000000
--- a/libunwindstack/offline_files/apk_rx_unreadable_arm64/links.txt
+++ /dev/null
@@ -1 +0,0 @@
-../common/libc.so_3106fb6eab1b2dc6704157e908a50eba libc.so
diff --git a/libunwindstack/offline_files/apk_rx_unreadable_arm64/maps.txt b/libunwindstack/offline_files/apk_rx_unreadable_arm64/maps.txt
deleted file mode 100644
index 696c397..0000000
--- a/libunwindstack/offline_files/apk_rx_unreadable_arm64/maps.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-5e004ef000-5e004f0000 r--p 0 00:00 0   run
-5e004f0000-5e004f1000 r-xp 1000 00:00 0   run
-7cb0e62000-7cb0e63000 r-xp 4000 00:00 0   unreadable.apk
-7f410dc000-7f41118000 r--p 0 00:00 0   libc.so
-7f41118000-7f41199000 r-xp 3c000 00:00 0   libc.so
diff --git a/libunwindstack/offline_files/apk_rx_unreadable_arm64/output.txt b/libunwindstack/offline_files/apk_rx_unreadable_arm64/output.txt
deleted file mode 100644
index c984b58..0000000
--- a/libunwindstack/offline_files/apk_rx_unreadable_arm64/output.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-  #00 pc 000000000000066c  unreadable.apk (offset 0x4000)
-  #01 pc 00000000000006c0  unreadable.apk (offset 0x4000)
-  #02 pc 00000000000006ec  unreadable.apk (offset 0x4000)
-  #03 pc 0000000000000718  unreadable.apk (offset 0x4000)
-  #04 pc 0000000000001154  run (main+256)
-  #05 pc 0000000000048b10  libc.so (__libc_init+96)
diff --git a/libunwindstack/offline_files/apk_rx_unreadable_arm64/regs.txt b/libunwindstack/offline_files/apk_rx_unreadable_arm64/regs.txt
deleted file mode 100644
index 1f6e4c6..0000000
--- a/libunwindstack/offline_files/apk_rx_unreadable_arm64/regs.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-x0: 0
-x1: 0
-x2: 7f42f67e88
-x3: 11b030000
-x4: 800000
-x5: 5462727542000000
-x6: 804275726254
-x7: 5678727440ff306b
-x8: 0
-x9: 1014
-x10: 1014
-x11: 10
-x12: 7f42e4ef80
-x13: 2f75fd4dd1b37121
-x14: 7
-x15: fabaf3feaa5334a
-x16: 7cb0e631e0
-x17: 7cb0e62648
-x18: 7f426ea000
-x19: 7fe563bf61
-x20: 3
-x21: 7fe563c028
-x22: 7f41b5a000
-x23: 0
-x24: 0
-x25: 0
-x26: 0
-x27: 0
-x28: 0
-x29: 7fe563bec0
-lr: 7cb0e626c4
-sp: 7fe563be90
-pc: 7cb0e6266c
-pst: 80001000
diff --git a/libunwindstack/offline_files/apk_rx_unreadable_arm64/run b/libunwindstack/offline_files/apk_rx_unreadable_arm64/run
deleted file mode 100644
index b984d44..0000000
--- a/libunwindstack/offline_files/apk_rx_unreadable_arm64/run
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/apk_rx_unreadable_arm64/stack.data b/libunwindstack/offline_files/apk_rx_unreadable_arm64/stack.data
deleted file mode 100644
index 5ce83d4..0000000
--- a/libunwindstack/offline_files/apk_rx_unreadable_arm64/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/art_quick_osr_stub_arm/libart.so.gz b/libunwindstack/offline_files/art_quick_osr_stub_arm/libart.so.gz
deleted file mode 100644
index f0d1e92..0000000
--- a/libunwindstack/offline_files/art_quick_osr_stub_arm/libart.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/art_quick_osr_stub_arm/libc.so.gz b/libunwindstack/offline_files/art_quick_osr_stub_arm/libc.so.gz
deleted file mode 100644
index a7e4170..0000000
--- a/libunwindstack/offline_files/art_quick_osr_stub_arm/libc.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/art_quick_osr_stub_arm/output.txt b/libunwindstack/offline_files/art_quick_osr_stub_arm/output.txt
deleted file mode 100644
index 76b288f..0000000
--- a/libunwindstack/offline_files/art_quick_osr_stub_arm/output.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-  #00 pc 0000c788  <anonymous:d0250000> (com.example.simpleperf.simpleperfexamplewithnative.MixActivity.access$000)
-  #01 pc 0000cdd5  <anonymous:d0250000> (com.example.simpleperf.simpleperfexamplewithnative.MixActivity$1.run+60)
-  #02 pc 004135bb  libart.so (art_quick_osr_stub+42)
-  #03 pc 002657a5  libart.so (art::jit::Jit::MaybeDoOnStackReplacement(art::Thread*, art::ArtMethod*, unsigned int, int, art::JValue*)+876)
-  #04 pc 004021a7  libart.so (MterpMaybeDoOnStackReplacement+86)
-  #05 pc 00412474  libart.so (ExecuteMterpImpl+66164)
-  #06 pc cd8365b0  <unknown>
-  #07 pc 001d7f1b  libart.so (art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool)+374)
-  #08 pc 001dc593  libart.so (art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*, art::JValue*)+154)
-  #09 pc 001f4d01  libart.so (bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+732)
-  #10 pc 003fe427  libart.so (MterpInvokeInterface+1354)
-  #11 pc 00405b94  libart.so (ExecuteMterpImpl+14740)
-  #12 pc 7004873e  <unknown>
-  #13 pc 001d7f1b  libart.so (art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool)+374)
-  #14 pc 001dc4d5  libart.so (art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*)+92)
-  #15 pc 003f25ab  libart.so (artQuickToInterpreterBridge+970)
-  #16 pc 00417aff  libart.so (art_quick_to_interpreter_bridge+30)
-  #17 pc 00413575  libart.so (art_quick_invoke_stub_internal+68)
-  #18 pc 00418531  libart.so (art_quick_invoke_stub+236)
-  #19 pc 000b468d  libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+136)
-  #20 pc 00362f49  libart.so (art::(anonymous namespace)::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, art::(anonymous namespace)::ArgArray*, art::JValue*, char const*)+52)
-  #21 pc 00363cd9  libart.so (art::InvokeVirtualOrInterfaceWithJValues(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, jvalue*)+332)
-  #22 pc 003851dd  libart.so (art::Thread::CreateCallback(void*)+868)
-  #23 pc 00062925  libc.so (__pthread_start(void*)+22)
-  #24 pc 0001de39  libc.so (__start_thread+24)
diff --git a/libunwindstack/offline_files/bad_eh_frame_hdr_arm64/libc.so.gz b/libunwindstack/offline_files/bad_eh_frame_hdr_arm64/libc.so.gz
deleted file mode 100644
index d9c3705..0000000
--- a/libunwindstack/offline_files/bad_eh_frame_hdr_arm64/libc.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/bad_eh_frame_hdr_arm64/output.txt b/libunwindstack/offline_files/bad_eh_frame_hdr_arm64/output.txt
deleted file mode 100644
index cdec0e4..0000000
--- a/libunwindstack/offline_files/bad_eh_frame_hdr_arm64/output.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-  #00 pc 0000000000000550  waiter64
-  #01 pc 0000000000000568  waiter64
-  #02 pc 000000000000057c  waiter64
-  #03 pc 0000000000000590  waiter64
-  #04 pc 00000000000a8e98  libc.so (__libc_init+88)
diff --git a/libunwindstack/offline_files/bad_eh_frame_hdr_arm64/waiter64.gz b/libunwindstack/offline_files/bad_eh_frame_hdr_arm64/waiter64.gz
deleted file mode 100644
index 7039b60..0000000
--- a/libunwindstack/offline_files/bad_eh_frame_hdr_arm64/waiter64.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/bluetooth_arm64/pc_1/links.txt b/libunwindstack/offline_files/bluetooth_arm64/pc_1/links.txt
deleted file mode 100644
index 29aa2e4..0000000
--- a/libunwindstack/offline_files/bluetooth_arm64/pc_1/links.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-../../common/libbluetooth.so_41de80f38623dac3c221b849566fb858 libbluetooth.so
-../../common/libc.so_f3791c53da47e6e72151dcc8088b9048 libc.so
diff --git a/libunwindstack/offline_files/bluetooth_arm64/pc_1/maps.txt b/libunwindstack/offline_files/bluetooth_arm64/pc_1/maps.txt
deleted file mode 100644
index 60ce7c7..0000000
--- a/libunwindstack/offline_files/bluetooth_arm64/pc_1/maps.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-7b5e40e000-7b5e5d5000 r--p 0 00:00 0   libbluetooth.so
-7b5e5d5000-7b5ec43000 r-xp 1c7000 00:00 0   libbluetooth.so
-7e86814000-7e86850000 r--p 0 00:00 0   libc.so
-7e86850000-7e868d1000 r-xp 3c000 00:00 0   libc.so
diff --git a/libunwindstack/offline_files/bluetooth_arm64/pc_1/output.txt b/libunwindstack/offline_files/bluetooth_arm64/pc_1/output.txt
deleted file mode 100644
index 50852d6..0000000
--- a/libunwindstack/offline_files/bluetooth_arm64/pc_1/output.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-  #00 pc 00000000007cbbdc  libbluetooth.so (bluetooth::packet::Iterator<true>::operator*() const+368)
-  #01 pc 0000000000756ab0  libbluetooth.so (bluetooth::hci::LeExtendedAdvertisingReport::Parse(bluetooth::hci::LeExtendedAdvertisingReport*, bluetooth::packet::Iterator<true>)+1228)
-  #02 pc 0000000000756344  libbluetooth.so (bluetooth::hci::LeExtendedAdvertisingReportView::GetAdvertisingReports()+872)
-  #03 pc 0000000000750ec8  libbluetooth.so (bluetooth::hci::LeScanningManager::impl::handle_extended_advertising_report(bluetooth::hci::LeExtendedAdvertisingReportView)+116)
-  #04 pc 000000000074f48c  libbluetooth.so (bluetooth::hci::LeScanningManager::impl::handle_scan_results(bluetooth::hci::LeMetaEventView)+760)
-  #05 pc 0000000000750284  libbluetooth.so (base::internal::Invoker<base::internal::BindState<void (bluetooth::hci::LeScanningManager::impl::*)(bluetooth::hci::LeMetaEventView), base::internal::UnretainedWrapper<bluetooth::hci::LeScanningManager::impl> >, void (bluetooth::hci::LeMetaEventView)>::Run(base::internal::BindStateBase*, bluetooth::hci::LeMetaEventView&&)+312)
-  #06 pc 00000000006f9908  libbluetooth.so (void base::internal::FunctorTraits<base::RepeatingCallback<void (bluetooth::hci::LeMetaEventView)>, void>::Invoke<base::RepeatingCallback<void (bluetooth::hci::LeMetaEventView)>, bluetooth::hci::LeMetaEventView>(base::RepeatingCallback<void (bluetooth::hci::LeMetaEventView)>&&, bluetooth::hci::LeMetaEventView&&)+296)
-  #07 pc 000000000081ac88  libbluetooth.so (bluetooth::os::Handler::handle_next_event()+244)
-  #08 pc 000000000081b580  libbluetooth.so (bluetooth::os::Reactor::Run()+608)
-  #09 pc 000000000081bec0  libbluetooth.so (bluetooth::os::Thread::run(bluetooth::os::Thread::Priority)+172)
-  #10 pc 000000000081c028  libbluetooth.so (void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (bluetooth::os::Thread::*)(bluetooth::os::Thread::Priority), bluetooth::os::Thread*, bluetooth::os::Thread::Priority> >(void*)+64)
-  #11 pc 00000000000b1920  libc.so (__pthread_start(void*)+264)
-  #12 pc 00000000000513f0  libc.so (__start_thread+64)
diff --git a/libunwindstack/offline_files/bluetooth_arm64/pc_1/regs.txt b/libunwindstack/offline_files/bluetooth_arm64/pc_1/regs.txt
deleted file mode 100644
index 31d33d6..0000000
--- a/libunwindstack/offline_files/bluetooth_arm64/pc_1/regs.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-x0: 1
-x1: d
-x2: 7c0f6d5110
-x3: 7b5ae05f58
-x4: 4
-x5: 33
-x6: 4025000fe2c160c
-x7: eb0a02e0114040c1
-x8: 87fc4d8789a28136
-x9: 87fc4d8789a28136
-x10: a
-x11: 0
-x12: 8
-x13: 106b9c07
-x14: 0
-x15: 0
-x16: 7e831617d0
-x17: 7e86850b40
-x18: 7b59516000
-x19: 7b5ae06138
-x20: 7b5ae06160
-x21: 7b5ae06210
-x22: 2f
-x23: 0
-x24: 0
-x25: 7b5ae07000
-x26: 7b5ec4ad78
-x27: 7b5ae05f88
-x28: 7b5ec4ad98
-x29: 7b5ae05fb0
-lr: 7b5ebd9b2c
-sp: 7b5ae05f70
-pc: 7b5ebd9bdc
-pst: 60000000
diff --git a/libunwindstack/offline_files/bluetooth_arm64/pc_1/stack.data b/libunwindstack/offline_files/bluetooth_arm64/pc_1/stack.data
deleted file mode 100644
index 7395be3..0000000
--- a/libunwindstack/offline_files/bluetooth_arm64/pc_1/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/bluetooth_arm64/pc_2/links.txt b/libunwindstack/offline_files/bluetooth_arm64/pc_2/links.txt
deleted file mode 100644
index 29aa2e4..0000000
--- a/libunwindstack/offline_files/bluetooth_arm64/pc_2/links.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-../../common/libbluetooth.so_41de80f38623dac3c221b849566fb858 libbluetooth.so
-../../common/libc.so_f3791c53da47e6e72151dcc8088b9048 libc.so
diff --git a/libunwindstack/offline_files/bluetooth_arm64/pc_2/maps.txt b/libunwindstack/offline_files/bluetooth_arm64/pc_2/maps.txt
deleted file mode 100644
index 88dffe8..0000000
--- a/libunwindstack/offline_files/bluetooth_arm64/pc_2/maps.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-7b6021f000-7b603e6000 r--p 0 00:00 0   libbluetooth.so
-7b603e6000-7b60a54000 r-xp 1c7000 00:00 0   libbluetooth.so
-7e86814000-7e86850000 r--p 0 00:00 0   libc.so
-7e86850000-7e868d1000 r-xp 3c000 00:00 0   libc.so
diff --git a/libunwindstack/offline_files/bluetooth_arm64/pc_2/output.txt b/libunwindstack/offline_files/bluetooth_arm64/pc_2/output.txt
deleted file mode 100644
index 76f4825..0000000
--- a/libunwindstack/offline_files/bluetooth_arm64/pc_2/output.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-  #00 pc 0000000000832188  libbluetooth.so
-  #01 pc 000000000081aca4  libbluetooth.so (bluetooth::os::Handler::handle_next_event()+272)
-  #02 pc 000000000081b580  libbluetooth.so (bluetooth::os::Reactor::Run()+608)
-  #03 pc 000000000081bec0  libbluetooth.so (bluetooth::os::Thread::run(bluetooth::os::Thread::Priority)+172)
-  #04 pc 000000000081c028  libbluetooth.so (void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (bluetooth::os::Thread::*)(bluetooth::os::Thread::Priority), bluetooth::os::Thread*, bluetooth::os::Thread::Priority> >(void*)+64)
-  #05 pc 00000000000b1920  libc.so (__pthread_start(void*)+264)
-  #06 pc 00000000000513f0  libc.so (__start_thread+64)
diff --git a/libunwindstack/offline_files/bluetooth_arm64/pc_2/regs.txt b/libunwindstack/offline_files/bluetooth_arm64/pc_2/regs.txt
deleted file mode 100644
index 364f927..0000000
--- a/libunwindstack/offline_files/bluetooth_arm64/pc_2/regs.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-x0: 7b5cb42718
-x1: 7e868e244c
-x2: 7c2f7039d0
-x3: 7b5cb426d8
-x4: 48
-x5: b
-x6: 7cbf6a4290
-x7: 7b5cb41ff9
-x8: 0
-x9: 0
-x10: 7c2f69d000
-x11: 60
-x12: 11
-x13: 106b9c07
-x14: 70742a85
-x15: 20d43150fc510e
-x16: 7b60a8a000
-x17: 7b63298604
-x18: 7b5c1d6000
-x19: 7c2f6aaf58
-x20: 7c0f6cd810
-x21: 7b5cb43000
-x22: 1
-x23: 0
-x24: ffffffff
-x25: 7c2f6ab4d0
-x26: 7c2f6ab4ec
-x27: 1
-x28: 7c7f6d7a60
-x29: 7b5cb42730
-lr: 7b60a39ca8
-sp: 7b5cb42710
-pc: 7b60a51188
-pst: 60000000
diff --git a/libunwindstack/offline_files/bluetooth_arm64/pc_2/stack.data b/libunwindstack/offline_files/bluetooth_arm64/pc_2/stack.data
deleted file mode 100644
index 9bea330..0000000
--- a/libunwindstack/offline_files/bluetooth_arm64/pc_2/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/bluetooth_arm64/pc_3/links.txt b/libunwindstack/offline_files/bluetooth_arm64/pc_3/links.txt
deleted file mode 100644
index 29aa2e4..0000000
--- a/libunwindstack/offline_files/bluetooth_arm64/pc_3/links.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-../../common/libbluetooth.so_41de80f38623dac3c221b849566fb858 libbluetooth.so
-../../common/libc.so_f3791c53da47e6e72151dcc8088b9048 libc.so
diff --git a/libunwindstack/offline_files/bluetooth_arm64/pc_3/maps.txt b/libunwindstack/offline_files/bluetooth_arm64/pc_3/maps.txt
deleted file mode 100644
index 3acc483..0000000
--- a/libunwindstack/offline_files/bluetooth_arm64/pc_3/maps.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-7b56f20000-7b570e7000 r--p 0 00:00 0   libbluetooth.so
-7b570e7000-7b57755000 r-xp 1c7000 00:00 0   libbluetooth.so
-7e86814000-7e86850000 r--p 0 00:00 0   libc.so
-7e86850000-7e868d1000 r-xp 3c000 00:00 0   libc.so
diff --git a/libunwindstack/offline_files/bluetooth_arm64/pc_3/output.txt b/libunwindstack/offline_files/bluetooth_arm64/pc_3/output.txt
deleted file mode 100644
index e9d42c9..0000000
--- a/libunwindstack/offline_files/bluetooth_arm64/pc_3/output.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-  #00 pc 00000000003f0698  libbluetooth.so (allocation_tracker_notify_free(unsigned char, void*)+592)
-  #01 pc 00000000003f0d40  libbluetooth.so (osi_free(void*)+16)
-  #02 pc 00000000003f4598  libbluetooth.so (list_free_node_(list_t*, list_node_t*)+84)
-  #03 pc 00000000003f44e4  libbluetooth.so (list_remove(list_t*, void*)+356)
-  #04 pc 00000000003ef738  libbluetooth.so (callback_dispatch(void*)+188)
-  #05 pc 00000000003f6a70  libbluetooth.so (work_queue_read_cb(void*)+92)
-  #06 pc 00000000003f4cc4  libbluetooth.so (run_reactor(reactor_t*, int)+380)
-  #07 pc 00000000003f4b1c  libbluetooth.so (reactor_start(reactor_t*)+84)
-  #08 pc 00000000003f65dc  libbluetooth.so (run_thread(void*)+196)
-  #09 pc 00000000000b1920  libc.so (__pthread_start(void*)+264)
-  #10 pc 00000000000513f0  libc.so (__start_thread+64)
diff --git a/libunwindstack/offline_files/bluetooth_arm64/pc_3/regs.txt b/libunwindstack/offline_files/bluetooth_arm64/pc_3/regs.txt
deleted file mode 100644
index e8b9437..0000000
--- a/libunwindstack/offline_files/bluetooth_arm64/pc_3/regs.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-x0: 0
-x1: 7bff6daf18
-x2: 15f199c2
-x3: 0
-x4: 7db0c8a
-x5: 0
-x6: 0
-x7: 7f7f7f7f7f7f7f7f
-x8: 10
-x9: 124d6
-x10: 20
-x11: 7b577e6000
-x12: 1
-x13: 7bff6daf18
-x14: 341555ac
-x15: 18
-x16: 7e83161730
-x17: 7e868c6698
-x18: 7b415a2000
-x19: 7bff6daf18
-x20: 7bff6d8ae0
-x21: 7bff6daf10
-x22: 7b56fc8897
-x23: 7b56f8dcc7
-x24: 7b56f7870a
-x25: 7bff6daf28
-x26: 766310a6006816c5
-x27: 7b577e6758
-x28: 0
-x29: 7b41ab2f90
-lr: 7b57310488
-sp: 7b41ab2e50
-pc: 7b57310698
-pst: 20000000
diff --git a/libunwindstack/offline_files/bluetooth_arm64/pc_3/stack.data b/libunwindstack/offline_files/bluetooth_arm64/pc_3/stack.data
deleted file mode 100644
index cfc8a86..0000000
--- a/libunwindstack/offline_files/bluetooth_arm64/pc_3/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/bluetooth_arm64/pc_4/links.txt b/libunwindstack/offline_files/bluetooth_arm64/pc_4/links.txt
deleted file mode 100644
index 29aa2e4..0000000
--- a/libunwindstack/offline_files/bluetooth_arm64/pc_4/links.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-../../common/libbluetooth.so_41de80f38623dac3c221b849566fb858 libbluetooth.so
-../../common/libc.so_f3791c53da47e6e72151dcc8088b9048 libc.so
diff --git a/libunwindstack/offline_files/bluetooth_arm64/pc_4/maps.txt b/libunwindstack/offline_files/bluetooth_arm64/pc_4/maps.txt
deleted file mode 100644
index 3acc483..0000000
--- a/libunwindstack/offline_files/bluetooth_arm64/pc_4/maps.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-7b56f20000-7b570e7000 r--p 0 00:00 0   libbluetooth.so
-7b570e7000-7b57755000 r-xp 1c7000 00:00 0   libbluetooth.so
-7e86814000-7e86850000 r--p 0 00:00 0   libc.so
-7e86850000-7e868d1000 r-xp 3c000 00:00 0   libc.so
diff --git a/libunwindstack/offline_files/bluetooth_arm64/pc_4/output.txt b/libunwindstack/offline_files/bluetooth_arm64/pc_4/output.txt
deleted file mode 100644
index 9dc4dd9..0000000
--- a/libunwindstack/offline_files/bluetooth_arm64/pc_4/output.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-  #00 pc 00000000003f5b24  libbluetooth.so (semaphore_post(semaphore_t*))
-  #01 pc 000000000005c3b8  libc.so (__timer_thread_start(void*)+136)
-  #02 pc 00000000000b1920  libc.so (__pthread_start(void*)+264)
-  #03 pc 00000000000513f0  libc.so (__start_thread+64)
diff --git a/libunwindstack/offline_files/bluetooth_arm64/pc_4/regs.txt b/libunwindstack/offline_files/bluetooth_arm64/pc_4/regs.txt
deleted file mode 100644
index 1d080e6..0000000
--- a/libunwindstack/offline_files/bluetooth_arm64/pc_4/regs.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-x0: 7bff6f4a78
-x1: 7b43cafba0
-x2: 0
-x3: 8
-x4: ffffffff
-x5: 0
-x6: 36313031
-x7: 33363130
-x8: 7b577e6000
-x9: 87fc4d8789a28136
-x10: 0
-x11: 0
-x12: 1
-x13: 100000000
-x14: 0
-x15: 30
-x16: 7e868d3f28
-x17: 7e86863adc
-x18: 7b4330e000
-x19: 7c0f6c0750
-x20: 7b43cb0000
-x21: 7b43cafcb0
-x22: 2777
-x23: 2794
-x24: 7b43cafcb0
-x25: 7b43cafcb0
-x26: 7b43cafff8
-x27: fc000
-x28: 7b43bb7000
-x29: 7b43cafc30
-lr: 7e868703bc
-sp: 7b43cafba0
-pc: 7b57315b24
-pst: 60000000
diff --git a/libunwindstack/offline_files/bluetooth_arm64/pc_4/stack.data b/libunwindstack/offline_files/bluetooth_arm64/pc_4/stack.data
deleted file mode 100644
index 96d17cc..0000000
--- a/libunwindstack/offline_files/bluetooth_arm64/pc_4/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/common/base.odex_maps_compiled_arm64.gz b/libunwindstack/offline_files/common/base.odex_maps_compiled_arm64.gz
deleted file mode 100644
index e06cbbe..0000000
--- a/libunwindstack/offline_files/common/base.odex_maps_compiled_arm64.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/common/boot-core-libart.oat_8368d55c916dc1224e76017186edfceee88a9955.gz b/libunwindstack/offline_files/common/boot-core-libart.oat_8368d55c916dc1224e76017186edfceee88a9955.gz
deleted file mode 100644
index be140f3..0000000
--- a/libunwindstack/offline_files/common/boot-core-libart.oat_8368d55c916dc1224e76017186edfceee88a9955.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/common/boot-framework.oat_6da45a084bf1f153be922249096389b66d69b6e6.gz b/libunwindstack/offline_files/common/boot-framework.oat_6da45a084bf1f153be922249096389b66d69b6e6.gz
deleted file mode 100644
index 0348933..0000000
--- a/libunwindstack/offline_files/common/boot-framework.oat_6da45a084bf1f153be922249096389b66d69b6e6.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/common/boot.oat_c3e0e6503935c4103ec839d45f3a2183bd910e3c.gz b/libunwindstack/offline_files/common/boot.oat_c3e0e6503935c4103ec839d45f3a2183bd910e3c.gz
deleted file mode 100644
index 1afbe4a..0000000
--- a/libunwindstack/offline_files/common/boot.oat_c3e0e6503935c4103ec839d45f3a2183bd910e3c.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/common/libandroid_runtime.so_7d88088666db374aecde2fbe51bff2f4.gz b/libunwindstack/offline_files/common/libandroid_runtime.so_7d88088666db374aecde2fbe51bff2f4.gz
deleted file mode 100644
index 63d2c2d..0000000
--- a/libunwindstack/offline_files/common/libandroid_runtime.so_7d88088666db374aecde2fbe51bff2f4.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/common/libart.so_82c0556f4b66528e4a608c100a63b712.gz b/libunwindstack/offline_files/common/libart.so_82c0556f4b66528e4a608c100a63b712.gz
deleted file mode 100644
index 8936a9c..0000000
--- a/libunwindstack/offline_files/common/libart.so_82c0556f4b66528e4a608c100a63b712.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/common/libbluetooth.so_41de80f38623dac3c221b849566fb858.gz b/libunwindstack/offline_files/common/libbluetooth.so_41de80f38623dac3c221b849566fb858.gz
deleted file mode 100644
index 2c5cc32..0000000
--- a/libunwindstack/offline_files/common/libbluetooth.so_41de80f38623dac3c221b849566fb858.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/common/libc.so_3106fb6eab1b2dc6704157e908a50eba.gz b/libunwindstack/offline_files/common/libc.so_3106fb6eab1b2dc6704157e908a50eba.gz
deleted file mode 100644
index abb334f..0000000
--- a/libunwindstack/offline_files/common/libc.so_3106fb6eab1b2dc6704157e908a50eba.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/common/libc.so_f3791c53da47e6e72151dcc8088b9048.gz b/libunwindstack/offline_files/common/libc.so_f3791c53da47e6e72151dcc8088b9048.gz
deleted file mode 100644
index c1ce2cc..0000000
--- a/libunwindstack/offline_files/common/libc.so_f3791c53da47e6e72151dcc8088b9048.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/common/libjavacore.so_1cda9a31939d0b05577a62e79f44fc40.gz b/libunwindstack/offline_files/common/libjavacore.so_1cda9a31939d0b05577a62e79f44fc40.gz
deleted file mode 100644
index 6749740..0000000
--- a/libunwindstack/offline_files/common/libjavacore.so_1cda9a31939d0b05577a62e79f44fc40.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/common/libutils.so_b8aa8db7e6895d0ba92398ca5d3ed2d4.gz b/libunwindstack/offline_files/common/libutils.so_b8aa8db7e6895d0ba92398ca5d3ed2d4.gz
deleted file mode 100644
index 5154821..0000000
--- a/libunwindstack/offline_files/common/libutils.so_b8aa8db7e6895d0ba92398ca5d3ed2d4.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/debug_frame_first_x86/libc.so.gz b/libunwindstack/offline_files/debug_frame_first_x86/libc.so.gz
deleted file mode 100644
index 33e085f..0000000
--- a/libunwindstack/offline_files/debug_frame_first_x86/libc.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/debug_frame_first_x86/output.txt b/libunwindstack/offline_files/debug_frame_first_x86/output.txt
deleted file mode 100644
index 887e908..0000000
--- a/libunwindstack/offline_files/debug_frame_first_x86/output.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-  #00 pc 00000685  waiter (call_level3+53)
-  #01 pc 000006b7  waiter (call_level2+23)
-  #02 pc 000006d7  waiter (call_level1+23)
-  #03 pc 000006f7  waiter (main+23)
-  #04 pc 00018275  libc.so
diff --git a/libunwindstack/offline_files/debug_frame_first_x86/waiter.gz b/libunwindstack/offline_files/debug_frame_first_x86/waiter.gz
deleted file mode 100644
index 4b84cd9..0000000
--- a/libunwindstack/offline_files/debug_frame_first_x86/waiter.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/debug_frame_load_bias_arm/libbinder.so.gz b/libunwindstack/offline_files/debug_frame_load_bias_arm/libbinder.so.gz
deleted file mode 100644
index c9469fa..0000000
--- a/libunwindstack/offline_files/debug_frame_load_bias_arm/libbinder.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/debug_frame_load_bias_arm/libc.so.gz b/libunwindstack/offline_files/debug_frame_load_bias_arm/libc.so.gz
deleted file mode 100644
index 9063e51..0000000
--- a/libunwindstack/offline_files/debug_frame_load_bias_arm/libc.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/debug_frame_load_bias_arm/mediaserver.gz b/libunwindstack/offline_files/debug_frame_load_bias_arm/mediaserver.gz
deleted file mode 100644
index 719fea0..0000000
--- a/libunwindstack/offline_files/debug_frame_load_bias_arm/mediaserver.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/debug_frame_load_bias_arm/output.txt b/libunwindstack/offline_files/debug_frame_load_bias_arm/output.txt
deleted file mode 100644
index 0860ec9..0000000
--- a/libunwindstack/offline_files/debug_frame_load_bias_arm/output.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-  #00 pc 0005138c  libc.so (__ioctl+8)
-  #01 pc 0002140f  libc.so (ioctl+30)
-  #02 pc 00039535  libbinder.so (android::IPCThreadState::talkWithDriver(bool)+204)
-  #03 pc 00039633  libbinder.so (android::IPCThreadState::getAndExecuteCommand()+10)
-  #04 pc 00039b57  libbinder.so (android::IPCThreadState::joinThreadPool(bool)+38)
-  #05 pc 00000c21  mediaserver (main+104)
-  #06 pc 00084b89  libc.so (__libc_init+48)
-  #07 pc 00000b77  mediaserver (_start_main+38)
diff --git a/libunwindstack/offline_files/eh_frame_bias_x86/libc.so.gz b/libunwindstack/offline_files/eh_frame_bias_x86/libc.so.gz
deleted file mode 100644
index f26eb69..0000000
--- a/libunwindstack/offline_files/eh_frame_bias_x86/libc.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/eh_frame_bias_x86/output.txt b/libunwindstack/offline_files/eh_frame_bias_x86/output.txt
deleted file mode 100644
index e073809..0000000
--- a/libunwindstack/offline_files/eh_frame_bias_x86/output.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-  #00 pc ffffe430  vdso.so (__kernel_vsyscall+16)
-  #01 pc 00082a4b  libc.so (__epoll_pwait+43)
-  #02 pc 000303a3  libc.so (epoll_pwait+115)
-  #03 pc 000303ed  libc.so (epoll_wait+45)
-  #04 pc 00010ea2  tombstoned (epoll_dispatch+226)
-  #05 pc 0000c5e7  tombstoned (event_base_loop+1095)
-  #06 pc 0000c193  tombstoned (event_base_dispatch+35)
-  #07 pc 00005c77  tombstoned (main+884)
-  #08 pc 00015f66  libc.so (__libc_init+102)
-  #09 pc 0000360e  tombstoned (_start+98)
-  #10 pc 00000001  <unknown>
diff --git a/libunwindstack/offline_files/eh_frame_bias_x86/tombstoned.gz b/libunwindstack/offline_files/eh_frame_bias_x86/tombstoned.gz
deleted file mode 100644
index 35d6b39..0000000
--- a/libunwindstack/offline_files/eh_frame_bias_x86/tombstoned.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/eh_frame_bias_x86/vdso.so.gz b/libunwindstack/offline_files/eh_frame_bias_x86/vdso.so.gz
deleted file mode 100644
index 93490de..0000000
--- a/libunwindstack/offline_files/eh_frame_bias_x86/vdso.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/eh_frame_hdr_begin_x86_64/libc.so.gz b/libunwindstack/offline_files/eh_frame_hdr_begin_x86_64/libc.so.gz
deleted file mode 100644
index e64a160..0000000
--- a/libunwindstack/offline_files/eh_frame_hdr_begin_x86_64/libc.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/eh_frame_hdr_begin_x86_64/output.txt b/libunwindstack/offline_files/eh_frame_hdr_begin_x86_64/output.txt
deleted file mode 100644
index ea75136..0000000
--- a/libunwindstack/offline_files/eh_frame_hdr_begin_x86_64/output.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-  #00 pc 0000000000000a80  unwind_test64 (calling3)
-  #01 pc 0000000000000dd9  unwind_test64 (calling2+633)
-  #02 pc 000000000000121e  unwind_test64 (calling1+638)
-  #03 pc 00000000000013ed  unwind_test64 (main+13)
-  #04 pc 00000000000202b0  libc.so
diff --git a/libunwindstack/offline_files/eh_frame_hdr_begin_x86_64/unwind_test64.gz b/libunwindstack/offline_files/eh_frame_hdr_begin_x86_64/unwind_test64.gz
deleted file mode 100644
index 5f8f954..0000000
--- a/libunwindstack/offline_files/eh_frame_hdr_begin_x86_64/unwind_test64.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/empty_arm64/libbinder.so.gz b/libunwindstack/offline_files/empty_arm64/libbinder.so.gz
deleted file mode 100644
index e752f7d..0000000
--- a/libunwindstack/offline_files/empty_arm64/libbinder.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/empty_arm64/libc.so.gz b/libunwindstack/offline_files/empty_arm64/libc.so.gz
deleted file mode 100644
index 8bd14b5..0000000
--- a/libunwindstack/offline_files/empty_arm64/libc.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/empty_arm64/netd.gz b/libunwindstack/offline_files/empty_arm64/netd.gz
deleted file mode 100644
index ba6efa1..0000000
--- a/libunwindstack/offline_files/empty_arm64/netd.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/empty_arm64/output.txt b/libunwindstack/offline_files/empty_arm64/output.txt
deleted file mode 100644
index 486508a..0000000
--- a/libunwindstack/offline_files/empty_arm64/output.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-  #00 pc 00000000000963a4  libc.so (__ioctl+4)
-  #01 pc 000000000005344c  libc.so (ioctl+140)
-  #02 pc 0000000000050ce4  libbinder.so (android::IPCThreadState::talkWithDriver(bool)+308)
-  #03 pc 0000000000050e98  libbinder.so (android::IPCThreadState::getAndExecuteCommand()+24)
-  #04 pc 00000000000516ac  libbinder.so (android::IPCThreadState::joinThreadPool(bool)+60)
-  #05 pc 00000000000443b0  netd (main+1056)
-  #06 pc 0000000000045594  libc.so (__libc_init+108)
diff --git a/libunwindstack/offline_files/gnu_debugdata_arm/libandroid_runtime.so.gz b/libunwindstack/offline_files/gnu_debugdata_arm/libandroid_runtime.so.gz
deleted file mode 100644
index 199c4b2..0000000
--- a/libunwindstack/offline_files/gnu_debugdata_arm/libandroid_runtime.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/gnu_debugdata_arm/output.txt b/libunwindstack/offline_files/gnu_debugdata_arm/output.txt
deleted file mode 100644
index 3b6fe65..0000000
--- a/libunwindstack/offline_files/gnu_debugdata_arm/output.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-  #00 pc 0006dc49  libandroid_runtime.so (android::AndroidRuntime::javaThreadShell(void*)+80)
-  #01 pc 0006dce5  libandroid_runtime.so (android::AndroidRuntime::javaCreateThreadEtc(int (*)(void*), void*, char const*, int, unsigned int, void**))
diff --git a/libunwindstack/offline_files/invalid_elf_offset_arm/output.txt b/libunwindstack/offline_files/invalid_elf_offset_arm/output.txt
deleted file mode 100644
index fe7e485..0000000
--- a/libunwindstack/offline_files/invalid_elf_offset_arm/output.txt
+++ /dev/null
@@ -1 +0,0 @@
-  #00 pc 00aa7508  invalid.apk (offset 0x12e4000)
diff --git a/libunwindstack/offline_files/jit_debug_arm/137-cfi.odex.gz b/libunwindstack/offline_files/jit_debug_arm/137-cfi.odex.gz
deleted file mode 100644
index 7150613..0000000
--- a/libunwindstack/offline_files/jit_debug_arm/137-cfi.odex.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_arm/dalvikvm32.gz b/libunwindstack/offline_files/jit_debug_arm/dalvikvm32.gz
deleted file mode 100644
index 868440f..0000000
--- a/libunwindstack/offline_files/jit_debug_arm/dalvikvm32.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_arm/libart.so.gz b/libunwindstack/offline_files/jit_debug_arm/libart.so.gz
deleted file mode 100644
index f23b6fd..0000000
--- a/libunwindstack/offline_files/jit_debug_arm/libart.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_arm/libartd.so.gz b/libunwindstack/offline_files/jit_debug_arm/libartd.so.gz
deleted file mode 100644
index 4f9d860..0000000
--- a/libunwindstack/offline_files/jit_debug_arm/libartd.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_arm/libarttestd.so.gz b/libunwindstack/offline_files/jit_debug_arm/libarttestd.so.gz
deleted file mode 100644
index 49c9933..0000000
--- a/libunwindstack/offline_files/jit_debug_arm/libarttestd.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_arm/libc.so.gz b/libunwindstack/offline_files/jit_debug_arm/libc.so.gz
deleted file mode 100644
index 65f3cf2..0000000
--- a/libunwindstack/offline_files/jit_debug_arm/libc.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_arm/output.txt b/libunwindstack/offline_files/jit_debug_arm/output.txt
deleted file mode 100644
index 094168c..0000000
--- a/libunwindstack/offline_files/jit_debug_arm/output.txt
+++ /dev/null
@@ -1,76 +0,0 @@
-  #00 pc 00018a5e  libarttestd.so (Java_Main_unwindInProcess+866)
-  #01 pc 0000212d  137-cfi.odex (boolean Main.unwindInProcess(boolean, int, boolean)+92)
-  #02 pc 00011cb1  anonymous:e2796000 (boolean Main.bar(boolean)+72)
-  #03 pc 00462175  libartd.so (art_quick_invoke_stub_internal+68)
-  #04 pc 00467129  libartd.so (art_quick_invoke_stub+228)
-  #05 pc 000bf7a9  libartd.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+864)
-  #06 pc 00247833  libartd.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+382)
-  #07 pc 0022e935  libartd.so (art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool)+244)
-  #08 pc 0022f71d  libartd.so (art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*)+128)
-  #09 pc 00442865  libartd.so (artQuickToInterpreterBridge+796)
-  #10 pc 004666ff  libartd.so (art_quick_to_interpreter_bridge+30)
-  #11 pc 00011c31  anonymous:e2796000 (int Main.compare(Main, Main)+64)
-  #12 pc 00462175  libartd.so (art_quick_invoke_stub_internal+68)
-  #13 pc 00467129  libartd.so (art_quick_invoke_stub+228)
-  #14 pc 000bf7a9  libartd.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+864)
-  #15 pc 00247833  libartd.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+382)
-  #16 pc 0022e935  libartd.so (art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool)+244)
-  #17 pc 0022f71d  libartd.so (art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*)+128)
-  #18 pc 00442865  libartd.so (artQuickToInterpreterBridge+796)
-  #19 pc 004666ff  libartd.so (art_quick_to_interpreter_bridge+30)
-  #20 pc 00011b77  anonymous:e2796000 (int Main.compare(java.lang.Object, java.lang.Object)+118)
-  #21 pc 00462175  libartd.so (art_quick_invoke_stub_internal+68)
-  #22 pc 00467129  libartd.so (art_quick_invoke_stub+228)
-  #23 pc 000bf7a9  libartd.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+864)
-  #24 pc 00247833  libartd.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+382)
-  #25 pc 0022e935  libartd.so (art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool)+244)
-  #26 pc 0022f71d  libartd.so (art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*)+128)
-  #27 pc 00442865  libartd.so (artQuickToInterpreterBridge+796)
-  #28 pc 004666ff  libartd.so (art_quick_to_interpreter_bridge+30)
-  #29 pc 00011a29  anonymous:e2796000 (int java.util.Arrays.binarySearch0(java.lang.Object[], int, int, java.lang.Object, java.util.Comparator)+304)
-  #30 pc 00462175  libartd.so (art_quick_invoke_stub_internal+68)
-  #31 pc 0046722f  libartd.so (art_quick_invoke_static_stub+226)
-  #32 pc 000bf7bb  libartd.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+882)
-  #33 pc 00247833  libartd.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+382)
-  #34 pc 0022e935  libartd.so (art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool)+244)
-  #35 pc 0022f71d  libartd.so (art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*)+128)
-  #36 pc 00442865  libartd.so (artQuickToInterpreterBridge+796)
-  #37 pc 004666ff  libartd.so (art_quick_to_interpreter_bridge+30)
-  #38 pc 0001139b  anonymous:e2796000 (boolean Main.foo()+178)
-  #39 pc 00462175  libartd.so (art_quick_invoke_stub_internal+68)
-  #40 pc 00467129  libartd.so (art_quick_invoke_stub+228)
-  #41 pc 000bf7a9  libartd.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+864)
-  #42 pc 00247833  libartd.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+382)
-  #43 pc 0022e935  libartd.so (art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool)+244)
-  #44 pc 0022f71d  libartd.so (art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*)+128)
-  #45 pc 00442865  libartd.so (artQuickToInterpreterBridge+796)
-  #46 pc 004666ff  libartd.so (art_quick_to_interpreter_bridge+30)
-  #47 pc 00010aa7  anonymous:e2796000 (void Main.runPrimary()+70)
-  #48 pc 00462175  libartd.so (art_quick_invoke_stub_internal+68)
-  #49 pc 00467129  libartd.so (art_quick_invoke_stub+228)
-  #50 pc 000bf7a9  libartd.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+864)
-  #51 pc 00247833  libartd.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+382)
-  #52 pc 0022e935  libartd.so (art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool)+244)
-  #53 pc 0022f71d  libartd.so (art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*)+128)
-  #54 pc 00442865  libartd.so (artQuickToInterpreterBridge+796)
-  #55 pc 004666ff  libartd.so (art_quick_to_interpreter_bridge+30)
-  #56 pc 0000ba99  anonymous:e2796000 (void Main.main(java.lang.String[])+144)
-  #57 pc 00462175  libartd.so (art_quick_invoke_stub_internal+68)
-  #58 pc 0046722f  libartd.so (art_quick_invoke_static_stub+226)
-  #59 pc 000bf7bb  libartd.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+882)
-  #60 pc 00247833  libartd.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+382)
-  #61 pc 0022e935  libartd.so (art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool)+244)
-  #62 pc 0022f71d  libartd.so (art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*)+128)
-  #63 pc 00442865  libartd.so (artQuickToInterpreterBridge+796)
-  #64 pc 004666ff  libartd.so (art_quick_to_interpreter_bridge+30)
-  #65 pc 00462175  libartd.so (art_quick_invoke_stub_internal+68)
-  #66 pc 0046722f  libartd.so (art_quick_invoke_static_stub+226)
-  #67 pc 000bf7bb  libartd.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+882)
-  #68 pc 003b292d  libartd.so (art::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, art::ArgArray*, art::JValue*, char const*)+52)
-  #69 pc 003b26c3  libartd.so (art::InvokeWithVarArgs(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, std::__va_list)+210)
-  #70 pc 00308411  libartd.so (art::JNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, std::__va_list)+76)
-  #71 pc 000e6a9f  libartd.so (art::CheckJNI::CallMethodV(char const*, _JNIEnv*, _jobject*, _jclass*, _jmethodID*, std::__va_list, art::Primitive::Type, art::InvokeType)+1486)
-  #72 pc 000e19b9  libartd.so (art::CheckJNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, std::__va_list)+40)
-  #73 pc 0000159f  dalvikvm32 (_JNIEnv::CallStaticVoidMethod(_jclass*, _jmethodID*, ...)+30)
-  #74 pc 00001349  dalvikvm32 (main+896)
-  #75 pc 000850c9  libc.so
diff --git a/libunwindstack/offline_files/jit_debug_x86/137-cfi.odex.gz b/libunwindstack/offline_files/jit_debug_x86/137-cfi.odex.gz
deleted file mode 100644
index 6b7a055..0000000
--- a/libunwindstack/offline_files/jit_debug_x86/137-cfi.odex.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_x86/dalvikvm32.gz b/libunwindstack/offline_files/jit_debug_x86/dalvikvm32.gz
deleted file mode 100644
index e9306c6..0000000
--- a/libunwindstack/offline_files/jit_debug_x86/dalvikvm32.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_x86/libartd.so.gz b/libunwindstack/offline_files/jit_debug_x86/libartd.so.gz
deleted file mode 100644
index 83716b1..0000000
--- a/libunwindstack/offline_files/jit_debug_x86/libartd.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_x86/libarttestd.so.gz b/libunwindstack/offline_files/jit_debug_x86/libarttestd.so.gz
deleted file mode 100644
index 097eeb0..0000000
--- a/libunwindstack/offline_files/jit_debug_x86/libarttestd.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_x86/libc.so.gz b/libunwindstack/offline_files/jit_debug_x86/libc.so.gz
deleted file mode 100644
index 30230f7..0000000
--- a/libunwindstack/offline_files/jit_debug_x86/libc.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_x86/output.txt b/libunwindstack/offline_files/jit_debug_x86/output.txt
deleted file mode 100644
index 08b2401..0000000
--- a/libunwindstack/offline_files/jit_debug_x86/output.txt
+++ /dev/null
@@ -1,69 +0,0 @@
-  #00 pc 00068fb8  libarttestd.so (art::CauseSegfault()+72)
-  #01 pc 00067f00  libarttestd.so (Java_Main_unwindInProcess+10032)
-  #02 pc 000021a8  137-cfi.odex (boolean Main.unwindInProcess(boolean, int, boolean)+136)
-  #03 pc 0000fe80  anonymous:ee74c000 (boolean Main.bar(boolean)+64)
-  #04 pc 006ad4d2  libartd.so (art_quick_invoke_stub+338)
-  #05 pc 00146ab5  libartd.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+885)
-  #06 pc 0039cf0d  libartd.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+653)
-  #07 pc 00392552  libartd.so (art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool)+354)
-  #08 pc 0039399a  libartd.so (art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*)+234)
-  #09 pc 00684362  libartd.so (artQuickToInterpreterBridge+1058)
-  #10 pc 006b35bd  libartd.so (art_quick_to_interpreter_bridge+77)
-  #11 pc 0000fe03  anonymous:ee74c000 (int Main.compare(Main, Main)+51)
-  #12 pc 006ad4d2  libartd.so (art_quick_invoke_stub+338)
-  #13 pc 00146ab5  libartd.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+885)
-  #14 pc 0039cf0d  libartd.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+653)
-  #15 pc 00392552  libartd.so (art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool)+354)
-  #16 pc 0039399a  libartd.so (art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*)+234)
-  #17 pc 00684362  libartd.so (artQuickToInterpreterBridge+1058)
-  #18 pc 006b35bd  libartd.so (art_quick_to_interpreter_bridge+77)
-  #19 pc 0000fd3b  anonymous:ee74c000 (int Main.compare(java.lang.Object, java.lang.Object)+107)
-  #20 pc 006ad4d2  libartd.so (art_quick_invoke_stub+338)
-  #21 pc 00146ab5  libartd.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+885)
-  #22 pc 0039cf0d  libartd.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+653)
-  #23 pc 00392552  libartd.so (art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool)+354)
-  #24 pc 0039399a  libartd.so (art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*)+234)
-  #25 pc 00684362  libartd.so (artQuickToInterpreterBridge+1058)
-  #26 pc 006b35bd  libartd.so (art_quick_to_interpreter_bridge+77)
-  #27 pc 0000fbdb  anonymous:ee74c000 (int java.util.Arrays.binarySearch0(java.lang.Object[], int, int, java.lang.Object, java.util.Comparator)+331)
-  #28 pc 006ad6a2  libartd.so (art_quick_invoke_static_stub+418)
-  #29 pc 00146acb  libartd.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+907)
-  #30 pc 0039cf0d  libartd.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+653)
-  #31 pc 00392552  libartd.so (art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool)+354)
-  #32 pc 0039399a  libartd.so (art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*)+234)
-  #33 pc 00684362  libartd.so (artQuickToInterpreterBridge+1058)
-  #34 pc 006b35bd  libartd.so (art_quick_to_interpreter_bridge+77)
-  #35 pc 0000f624  anonymous:ee74c000 (boolean Main.foo()+164)
-  #36 pc 006ad4d2  libartd.so (art_quick_invoke_stub+338)
-  #37 pc 00146ab5  libartd.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+885)
-  #38 pc 0039cf0d  libartd.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+653)
-  #39 pc 00392552  libartd.so (art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool)+354)
-  #40 pc 0039399a  libartd.so (art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*)+234)
-  #41 pc 00684362  libartd.so (artQuickToInterpreterBridge+1058)
-  #42 pc 006b35bd  libartd.so (art_quick_to_interpreter_bridge+77)
-  #43 pc 0000eedb  anonymous:ee74c000 (void Main.runPrimary()+59)
-  #44 pc 006ad4d2  libartd.so (art_quick_invoke_stub+338)
-  #45 pc 00146ab5  libartd.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+885)
-  #46 pc 0039cf0d  libartd.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+653)
-  #47 pc 00392552  libartd.so (art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool)+354)
-  #48 pc 0039399a  libartd.so (art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*)+234)
-  #49 pc 00684362  libartd.so (artQuickToInterpreterBridge+1058)
-  #50 pc 006b35bd  libartd.so (art_quick_to_interpreter_bridge+77)
-  #51 pc 0000ac21  anonymous:ee74c000 (void Main.main(java.lang.String[])+97)
-  #52 pc 006ad6a2  libartd.so (art_quick_invoke_static_stub+418)
-  #53 pc 00146acb  libartd.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+907)
-  #54 pc 0039cf0d  libartd.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+653)
-  #55 pc 00392552  libartd.so (art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame&, art::JValue, bool)+354)
-  #56 pc 0039399a  libartd.so (art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor const&, art::ShadowFrame*)+234)
-  #57 pc 00684362  libartd.so (artQuickToInterpreterBridge+1058)
-  #58 pc 006b35bd  libartd.so (art_quick_to_interpreter_bridge+77)
-  #59 pc 006ad6a2  libartd.so (art_quick_invoke_static_stub+418)
-  #60 pc 00146acb  libartd.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+907)
-  #61 pc 005aac95  libartd.so (art::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, art::ArgArray*, art::JValue*, char const*)+85)
-  #62 pc 005aab5a  libartd.so (art::InvokeWithVarArgs(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, char*)+362)
-  #63 pc 0048a3dd  libartd.so (art::JNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, char*)+125)
-  #64 pc 0018448c  libartd.so (art::CheckJNI::CallMethodV(char const*, _JNIEnv*, _jobject*, _jclass*, _jmethodID*, char*, art::Primitive::Type, art::InvokeType)+1964)
-  #65 pc 0017cf06  libartd.so (art::CheckJNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, char*)+70)
-  #66 pc 00001d8c  dalvikvm32 (_JNIEnv::CallStaticVoidMethod(_jclass*, _jmethodID*, ...)+60)
-  #67 pc 00001a80  dalvikvm32 (main+1312)
-  #68 pc 00018275  libc.so
diff --git a/libunwindstack/offline_files/jit_map_arm/jit_map0.so.gz b/libunwindstack/offline_files/jit_map_arm/jit_map0.so.gz
deleted file mode 100644
index 2a332c9..0000000
--- a/libunwindstack/offline_files/jit_map_arm/jit_map0.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/jit_map_arm/jit_map1.so.gz b/libunwindstack/offline_files/jit_map_arm/jit_map1.so.gz
deleted file mode 100644
index c1341db..0000000
--- a/libunwindstack/offline_files/jit_map_arm/jit_map1.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/jit_map_arm/libart.so.gz b/libunwindstack/offline_files/jit_map_arm/libart.so.gz
deleted file mode 100644
index bacf50b..0000000
--- a/libunwindstack/offline_files/jit_map_arm/libart.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/jit_map_arm/libc.so.gz b/libunwindstack/offline_files/jit_map_arm/libc.so.gz
deleted file mode 100644
index a33f276..0000000
--- a/libunwindstack/offline_files/jit_map_arm/libc.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/jit_map_arm/output.txt b/libunwindstack/offline_files/jit_map_arm/output.txt
deleted file mode 100644
index f9eb2ef..0000000
--- a/libunwindstack/offline_files/jit_map_arm/output.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-  #00 pc 00000000  jit_map0.so (com.example.simpleperf.simpleperfexamplewithnative.MixActivity.access$000)
-  #01 pc 0000003d  jit_map1.so (com.example.simpleperf.simpleperfexamplewithnative.MixActivity$1.run+60)
-  #02 pc 004135bb  libart.so (art_quick_osr_stub+42)
-  #03 pc 003851dd  libart.so (art::Thread::CreateCallback(void*)+868)
-  #04 pc 00062925  libc.so (__pthread_start(void*)+22)
-  #05 pc 0001de39  libc.so (__start_thread+24)
diff --git a/libunwindstack/offline_files/load_bias_different_section_bias_arm64/libc.so.gz b/libunwindstack/offline_files/load_bias_different_section_bias_arm64/libc.so.gz
deleted file mode 100644
index ad5f4e5..0000000
--- a/libunwindstack/offline_files/load_bias_different_section_bias_arm64/libc.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/load_bias_different_section_bias_arm64/linker64.gz b/libunwindstack/offline_files/load_bias_different_section_bias_arm64/linker64.gz
deleted file mode 100644
index 0224762..0000000
--- a/libunwindstack/offline_files/load_bias_different_section_bias_arm64/linker64.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/load_bias_different_section_bias_arm64/output.txt b/libunwindstack/offline_files/load_bias_different_section_bias_arm64/output.txt
deleted file mode 100644
index d34c97e..0000000
--- a/libunwindstack/offline_files/load_bias_different_section_bias_arm64/output.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-  #00 pc 00000000000d59bc  linker64 (__dl_syscall+28)
-  #01 pc 00000000000554e8  linker64 (__dl__ZL24debuggerd_signal_handleriP7siginfoPv+1148)
-  #02 pc 00000000000008c0  vdso (__kernel_rt_sigreturn)
-  #03 pc 000000000007f3e8  libc.so (abort+168)
-  #04 pc 00000000000459fc  test (std::__ndk1::__throw_bad_cast()+4)
-  #05 pc 0000000000056d80  test (testing::Test::Run()+88)
-  #06 pc 000000000005724c  test (testing::TestInfo::Run()+112)
-  #07 pc 0000000000057558  test (testing::TestSuite::Run()+116)
-  #08 pc 000000000005bffc  test (testing::internal::UnitTestImpl::RunAllTests()+464)
-  #09 pc 000000000005bd9c  test (testing::UnitTest::Run()+116)
-  #10 pc 00000000000464e4  test (main+144)
-  #11 pc 000000000007aa34  libc.so (__libc_init+108)
diff --git a/libunwindstack/offline_files/load_bias_different_section_bias_arm64/test.gz b/libunwindstack/offline_files/load_bias_different_section_bias_arm64/test.gz
deleted file mode 100644
index 5a49557..0000000
--- a/libunwindstack/offline_files/load_bias_different_section_bias_arm64/test.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/load_bias_different_section_bias_arm64/vdso.gz b/libunwindstack/offline_files/load_bias_different_section_bias_arm64/vdso.gz
deleted file mode 100644
index 99a8b7f..0000000
--- a/libunwindstack/offline_files/load_bias_different_section_bias_arm64/vdso.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/load_bias_ro_rx_x86_64/libc.so.gz b/libunwindstack/offline_files/load_bias_ro_rx_x86_64/libc.so.gz
deleted file mode 100644
index b63a853..0000000
--- a/libunwindstack/offline_files/load_bias_ro_rx_x86_64/libc.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/load_bias_ro_rx_x86_64/output.txt b/libunwindstack/offline_files/load_bias_ro_rx_x86_64/output.txt
deleted file mode 100644
index 592fb89..0000000
--- a/libunwindstack/offline_files/load_bias_ro_rx_x86_64/output.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-  #00 pc 00000000000e9dd4  libc.so (__write+20)
-  #01 pc 000000000007ab9c  libc.so (_IO_file_write+44)
-  #02 pc 0000000000079f3e  libc.so
-  #03 pc 000000000007bce8  libc.so (_IO_do_write+24)
-  #04 pc 000000000007b26e  libc.so (_IO_file_xsputn+270)
-  #05 pc 000000000004f7f9  libc.so (_IO_vfprintf+1945)
-  #06 pc 0000000000057cb5  libc.so (_IO_printf+165)
-  #07 pc 0000000000ed1796  perfetto_unittests (testing::internal::PrettyUnitTestResultPrinter::OnTestIterationStart(testing::UnitTest const&, int)+374)
-  #08 pc 0000000000ed30fd  perfetto_unittests (testing::internal::TestEventRepeater::OnTestIterationStart(testing::UnitTest const&, int)+125)
-  #09 pc 0000000000ed5e25  perfetto_unittests (testing::internal::UnitTestImpl::RunAllTests()+581)
-  #10 pc 0000000000ef63f3  perfetto_unittests (bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)+131)
-  #11 pc 0000000000ee2a21  perfetto_unittests (bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*)+113)
-  #12 pc 0000000000ed5bb9  perfetto_unittests (testing::UnitTest::Run()+185)
-  #13 pc 0000000000e900f0  perfetto_unittests (RUN_ALL_TESTS()+16)
-  #14 pc 0000000000e900d8  perfetto_unittests (main+56)
-  #15 pc 000000000002352a  libc.so (__libc_start_main+234)
-  #16 pc 0000000000919029  perfetto_unittests (_start+41)
diff --git a/libunwindstack/offline_files/load_bias_ro_rx_x86_64/perfetto_unittests.gz b/libunwindstack/offline_files/load_bias_ro_rx_x86_64/perfetto_unittests.gz
deleted file mode 100644
index 1172e25..0000000
--- a/libunwindstack/offline_files/load_bias_ro_rx_x86_64/perfetto_unittests.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/maps_compiled_arm64/28613_main-thread/app_process64.gz b/libunwindstack/offline_files/maps_compiled_arm64/28613_main-thread/app_process64.gz
deleted file mode 100644
index a2dc750..0000000
--- a/libunwindstack/offline_files/maps_compiled_arm64/28613_main-thread/app_process64.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/maps_compiled_arm64/28613_main-thread/links.txt b/libunwindstack/offline_files/maps_compiled_arm64/28613_main-thread/links.txt
deleted file mode 100644
index 27beb3e..0000000
--- a/libunwindstack/offline_files/maps_compiled_arm64/28613_main-thread/links.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-../../common/base.odex_maps_compiled_arm64 base.odex_maps_compiled_arm64
-../../common/boot-framework.oat_6da45a084bf1f153be922249096389b66d69b6e6 boot-framework.oat
-../../common/boot.oat_c3e0e6503935c4103ec839d45f3a2183bd910e3c boot.oat
-../../common/libandroid_runtime.so_7d88088666db374aecde2fbe51bff2f4 libandroid_runtime.so
-../../common/libart.so_82c0556f4b66528e4a608c100a63b712 libart.so
-../../common/libc.so_f3791c53da47e6e72151dcc8088b9048 libc.so
diff --git a/libunwindstack/offline_files/maps_compiled_arm64/28613_main-thread/maps.txt b/libunwindstack/offline_files/maps_compiled_arm64/28613_main-thread/maps.txt
deleted file mode 100644
index 7bcd383..0000000
--- a/libunwindstack/offline_files/maps_compiled_arm64/28613_main-thread/maps.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-6fcf3000-6fd9e000 r--p 0 00:00 0   boot.oat
-6fd9e000-700fe000 r-xp ab000 00:00 0   boot.oat
-71227000-713aa000 r--p 0 00:00 0   boot-framework.oat
-713aa000-71ab4000 r-xp 183000 00:00 0   boot-framework.oat
-6193c7e000-6193c80000 r--p 0 00:00 0   app_process64
-6193c80000-6193c81000 r-xp 2000 00:00 0   app_process64
-7b590f4000-7b5a2aa000 r--p 0 00:00 0   base.odex_maps_compiled_arm64
-7b5a2aa000-7b6061c000 r-xp 11b6000 00:00 0   base.odex_maps_compiled_arm64
-7bdd800000-7bdda00000 r--p 0 00:00 0   libart.so
-7bdda00000-7bddf4a000 r-xp 200000 00:00 0   libart.so
-7e7c400000-7e7c4af000 r--p 0 00:00 0   libandroid_runtime.so
-7e7c4af000-7e7c5df000 r-xp af000 00:00 0   libandroid_runtime.so
-7e86814000-7e86850000 r--p 0 00:00 0   libc.so
-7e86850000-7e868d1000 r-xp 3c000 00:00 0   libc.so
diff --git a/libunwindstack/offline_files/maps_compiled_arm64/28613_main-thread/output.txt b/libunwindstack/offline_files/maps_compiled_arm64/28613_main-thread/output.txt
deleted file mode 100644
index 97e939a..0000000
--- a/libunwindstack/offline_files/maps_compiled_arm64/28613_main-thread/output.txt
+++ /dev/null
@@ -1,50 +0,0 @@
-  #00 pc 000000000023b1e0  libart.so (art::ThreadList::RunCheckpoint(art::Closure*, art::Closure*)+2980)
-  #01 pc 0000000000244698  libart.so (art::ClassLinker::InitializeClass(art::Thread*, art::Handle<art::mirror::Class>, bool, bool)+2348)
-  #02 pc 0000000000243fd0  libart.so (art::ClassLinker::InitializeClass(art::Thread*, art::Handle<art::mirror::Class>, bool, bool)+612)
-  #03 pc 0000000000359730  libart.so (artAllocObjectFromCodeResolvedRegionTLAB+668)
-  #04 pc 000000000029ba88  libart.so (art_quick_alloc_object_resolved_region_tlab+104)
-  #05 pc 0000000005b4ba38  base.odex_maps_compiled_arm64 (ffs.h+4600)
-  #06 pc 0000000005b8a620  base.odex_maps_compiled_arm64 (ffs.a+528)
-  #07 pc 0000000005a1fb18  base.odex_maps_compiled_arm64 (ebhk.a+184)
-  #08 pc 00000000023600d4  base.odex_maps_compiled_arm64 (bdvg.<init>+6356)
-  #09 pc 000000000236678c  base.odex_maps_compiled_arm64 (bdvh.a+2652)
-  #10 pc 0000000002a59b00  base.odex_maps_compiled_arm64 (bdux.O+816)
-  #11 pc 0000000005afc2a4  base.odex_maps_compiled_arm64 (er.tO+244)
-  #12 pc 00000000058a6444  base.odex_maps_compiled_arm64 (gi.c+1396)
-  #13 pc 00000000058a8104  base.odex_maps_compiled_arm64 (gi.e+4708)
-  #14 pc 0000000005893ce0  base.odex_maps_compiled_arm64 (fy.aB+5952)
-  #15 pc 0000000005894e4c  base.odex_maps_compiled_arm64 (fy.aD+492)
-  #16 pc 000000000589dde0  base.odex_maps_compiled_arm64 (fy.at+544)
-  #17 pc 0000000005f09288  base.odex_maps_compiled_arm64 (hfn.F+2040)
-  #18 pc 0000000005f0a550  base.odex_maps_compiled_arm64 (hfn.K+480)
-  #19 pc 0000000005f09d3c  base.odex_maps_compiled_arm64 (hfn.J+364)
-  #20 pc 0000000005f09b48  base.odex_maps_compiled_arm64 (hfn.H+56)
-  #21 pc 00000000028b9e98  base.odex_maps_compiled_arm64 (bdtd.o+3528)
-  #22 pc 0000000003367630  base.odex_maps_compiled_arm64 (bqyr.q+4368)
-  #23 pc 0000000003354ad8  base.odex_maps_compiled_arm64 (bqye.b+3144)
-  #24 pc 00000000033828fc  base.odex_maps_compiled_arm64 (brna.e+332)
-  #25 pc 0000000003382a80  base.odex_maps_compiled_arm64 (brna.b+96)
-  #26 pc 000000000338f35c  base.odex_maps_compiled_arm64 (brsh.e+236)
-  #27 pc 000000000338f214  base.odex_maps_compiled_arm64 (brsh.d+212)
-  #28 pc 000000000338dafc  base.odex_maps_compiled_arm64 (brsf.a+76)
-  #29 pc 000000000339173c  base.odex_maps_compiled_arm64 (brsp.d+316)
-  #30 pc 000000000338f560  base.odex_maps_compiled_arm64 (brsj.xI+224)
-  #31 pc 0000000002eb4f64  base.odex_maps_compiled_arm64 (buzf.b+1380)
-  #32 pc 0000000004ce2d98  base.odex_maps_compiled_arm64 (dgvq.run+440)
-  #33 pc 00000000004eef60  boot-framework.oat (android.os.Handler.dispatchMessage+80)
-  #34 pc 00000000004f1dfc  boot-framework.oat (android.os.Looper.loopOnce+1036)
-  #35 pc 00000000004f1954  boot-framework.oat (android.os.Looper.loop+516)
-  #36 pc 00000000002ce21c  boot-framework.oat (android.app.ActivityThread.main+732)
-  #37 pc 00000000002937e8  libart.so (art_quick_invoke_static_stub+568)
-  #38 pc 00000000003026c0  libart.so (_jobject* art::InvokeMethod<(art::PointerSize)8>(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jobject*, _jobject*, unsigned long)+608)
-  #39 pc 0000000000302438  libart.so (art::Method_invoke(_JNIEnv*, _jobject*, _jobject*, _jobjectArray*)+52)
-  #40 pc 00000000000b2f74  boot.oat (art_jni_trampoline+132)
-  #41 pc 000000000081aadc  boot-framework.oat (com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run+140)
-  #42 pc 0000000000822e18  boot-framework.oat (com.android.internal.os.ZygoteInit.main+2472)
-  #43 pc 00000000002937e8  libart.so (art_quick_invoke_static_stub+568)
-  #44 pc 00000000003dff34  libart.so (art::JValue art::InvokeWithVarArgs<_jmethodID*>(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, std::__va_list)+464)
-  #45 pc 00000000005c43f0  libart.so (art::JNI<true>::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, std::__va_list)+268)
-  #46 pc 00000000000b0ac4  libandroid_runtime.so (_JNIEnv::CallStaticVoidMethod(_jclass*, _jmethodID*, ...)+120)
-  #47 pc 00000000000bc078  libandroid_runtime.so (android::AndroidRuntime::start(char const*, android::Vector<android::String8> const&, bool)+836)
-  #48 pc 000000000000258c  app_process64 (main+1336)
-  #49 pc 00000000000488d8  libc.so (__libc_init+96)
diff --git a/libunwindstack/offline_files/maps_compiled_arm64/28613_main-thread/regs.txt b/libunwindstack/offline_files/maps_compiled_arm64/28613_main-thread/regs.txt
deleted file mode 100644
index 44b1c3d..0000000
--- a/libunwindstack/offline_files/maps_compiled_arm64/28613_main-thread/regs.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-x0: 7e868e244c
-x1: 7e868e244c
-x2: 7bff757440
-x3: 7fe2362a48
-x4: 20
-x5: 7c1f7185a0
-x6: 7d4f6ba140
-x7: 7d4f6a6f50
-x8: 7c1f7185c0
-x9: 0
-x10: 7bff69b000
-x11: 30
-x12: f
-x13: 7d4f6cb760
-x14: 1
-x15: 16b54cbc
-x16: 7e77ab57d0
-x17: 7e86850b40
-x18: 7e8a6b6000
-x19: 7d4f6a1be0
-x20: 7c6f6de2d0
-x21: 8
-x22: 7c1f7185b8
-x23: 7d4f6d26a0
-x24: 7bff6e28c0
-x25: 1
-x26: 7bde215000
-x27: 7c1f718580
-x28: 7d5f69d220
-x29: 7fe2362b00
-lr: 7bdda3b300
-sp: 7fe2362a80
-pc: 7bdda3b1e0
-pst: 80000000
diff --git a/libunwindstack/offline_files/maps_compiled_arm64/28613_main-thread/stack.data b/libunwindstack/offline_files/maps_compiled_arm64/28613_main-thread/stack.data
deleted file mode 100644
index 45170f3..0000000
--- a/libunwindstack/offline_files/maps_compiled_arm64/28613_main-thread/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/maps_compiled_arm64/28644/links.txt b/libunwindstack/offline_files/maps_compiled_arm64/28644/links.txt
deleted file mode 100644
index 03ba1a5..0000000
--- a/libunwindstack/offline_files/maps_compiled_arm64/28644/links.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-../../common/base.odex_maps_compiled_arm64 base.odex_maps_compiled_arm64
-../../common/boot.oat_c3e0e6503935c4103ec839d45f3a2183bd910e3c boot.oat
-../../common/libart.so_82c0556f4b66528e4a608c100a63b712 libart.so
-../../common/libc.so_f3791c53da47e6e72151dcc8088b9048 libc.so
diff --git a/libunwindstack/offline_files/maps_compiled_arm64/28644/maps.txt b/libunwindstack/offline_files/maps_compiled_arm64/28644/maps.txt
deleted file mode 100644
index b624632..0000000
--- a/libunwindstack/offline_files/maps_compiled_arm64/28644/maps.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-6fcf3000-6fd9e000 r--p 0 00:00 0   boot.oat
-6fd9e000-700fe000 r-xp ab000 00:00 0   boot.oat
-7b590f4000-7b5a2aa000 r--p 0 00:00 0   base.odex_maps_compiled_arm64
-7b5a2aa000-7b6061c000 r-xp 11b6000 00:00 0   base.odex_maps_compiled_arm64
-7bdd800000-7bdda00000 r--p 0 00:00 0   libart.so
-7bdda00000-7bddf4a000 r-xp 200000 00:00 0   libart.so
-7e86814000-7e86850000 r--p 0 00:00 0   libc.so
-7e86850000-7e868d1000 r-xp 3c000 00:00 0   libc.so
diff --git a/libunwindstack/offline_files/maps_compiled_arm64/28644/output.txt b/libunwindstack/offline_files/maps_compiled_arm64/28644/output.txt
deleted file mode 100644
index cd61268..0000000
--- a/libunwindstack/offline_files/maps_compiled_arm64/28644/output.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-  #00 pc 000000000004c35c  libc.so (syscall+28)
-  #01 pc 0000000000411604  libart.so (art::Thread::Park(bool, long)+2300)
-  #02 pc 0000000000410790  libart.so (art::Unsafe_park(_JNIEnv*, _jobject*, unsigned char, long)+280)
-  #03 pc 00000000000adf4c  boot.oat (art_jni_trampoline+108)
-  #04 pc 00000000002f9ccc  boot.oat (java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedNanos+1228)
-  #05 pc 00000000001235b0  boot.oat (java.util.concurrent.CountDownLatch.await+480)
-  #06 pc 0000000003e2e390  base.odex_maps_compiled_arm64 (cqqp.e+448)
-  #07 pc 0000000003ac39a4  base.odex_maps_compiled_arm64 (clys.e+1060)
-  #08 pc 0000000003ac3e4c  base.odex_maps_compiled_arm64 (clys.c+44)
-  #09 pc 0000000002b8ebb0  base.odex_maps_compiled_arm64 (bmob.call+64)
-  #10 pc 00000000054c72d8  base.odex_maps_compiled_arm64 (dgxq.a+72)
-  #11 pc 0000000004ce4d54  base.odex_maps_compiled_arm64 (dgwi.run+148)
-  #12 pc 0000000005672604  base.odex_maps_compiled_arm64 (dgxr.run+68)
-  #13 pc 0000000002f064d4  base.odex_maps_compiled_arm64 (bwkg.run+148)
-  #14 pc 000000000037b75c  boot.oat (java.util.concurrent.ThreadPoolExecutor.runWorker+988)
-  #15 pc 0000000000374f84  boot.oat (java.util.concurrent.ThreadPoolExecutor$Worker.run+68)
-  #16 pc 0000000002f041f4  base.odex_maps_compiled_arm64 (bwjw.run+564)
-  #17 pc 00000000001bf0bc  boot.oat (java.lang.Thread.run+76)
-  #18 pc 0000000000293564  libart.so (art_quick_invoke_stub+548)
-  #19 pc 00000000002c6558  libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+156)
-  #20 pc 0000000000367ea8  libart.so (art::JValue art::InvokeVirtualOrInterfaceWithJValues<art::ArtMethod*>(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, art::ArtMethod*, jvalue const*)+380)
-  #21 pc 00000000003e9b6c  libart.so (art::Thread::CreateCallback(void*)+1004)
-  #22 pc 00000000000b1920  libc.so (__pthread_start(void*)+264)
-  #23 pc 00000000000513f0  libc.so (__start_thread+64)
diff --git a/libunwindstack/offline_files/maps_compiled_arm64/28644/regs.txt b/libunwindstack/offline_files/maps_compiled_arm64/28644/regs.txt
deleted file mode 100644
index 6ed344d..0000000
--- a/libunwindstack/offline_files/maps_compiled_arm64/28644/regs.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-x0: 7d4f6e9068
-x1: 80
-x2: 2
-x3: 7b58af6368
-x4: 0
-x5: 0
-x6: 0
-x7: 20
-x8: 62
-x9: 3b9ac0a4
-x10: 3b
-x11: 87fc4d8789a28136
-x12: 18
-x13: 9271d475358
-x14: bb1f91d69b7d5
-x15: 15f199c2
-x16: 7bde011728
-x17: 7e86860340
-x18: 7b4d7ea000
-x19: 7d4f6e9068
-x20: 7d4f6e9030
-x21: df8474ea4
-x22: 0
-x23: 44
-x24: 7bde215000
-x25: 1
-x26: 0
-x27: 7bde217000
-x28: 7b58af7000
-x29: 7b58af6390
-lr: 7bddc11608
-sp: 7b58af6360
-pc: 7e8686035c
-pst: 40000000
diff --git a/libunwindstack/offline_files/maps_compiled_arm64/28644/stack.data b/libunwindstack/offline_files/maps_compiled_arm64/28644/stack.data
deleted file mode 100644
index 4662d5f..0000000
--- a/libunwindstack/offline_files/maps_compiled_arm64/28644/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/maps_compiled_arm64/28648/links.txt b/libunwindstack/offline_files/maps_compiled_arm64/28648/links.txt
deleted file mode 100644
index 03ba1a5..0000000
--- a/libunwindstack/offline_files/maps_compiled_arm64/28648/links.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-../../common/base.odex_maps_compiled_arm64 base.odex_maps_compiled_arm64
-../../common/boot.oat_c3e0e6503935c4103ec839d45f3a2183bd910e3c boot.oat
-../../common/libart.so_82c0556f4b66528e4a608c100a63b712 libart.so
-../../common/libc.so_f3791c53da47e6e72151dcc8088b9048 libc.so
diff --git a/libunwindstack/offline_files/maps_compiled_arm64/28648/maps.txt b/libunwindstack/offline_files/maps_compiled_arm64/28648/maps.txt
deleted file mode 100644
index b624632..0000000
--- a/libunwindstack/offline_files/maps_compiled_arm64/28648/maps.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-6fcf3000-6fd9e000 r--p 0 00:00 0   boot.oat
-6fd9e000-700fe000 r-xp ab000 00:00 0   boot.oat
-7b590f4000-7b5a2aa000 r--p 0 00:00 0   base.odex_maps_compiled_arm64
-7b5a2aa000-7b6061c000 r-xp 11b6000 00:00 0   base.odex_maps_compiled_arm64
-7bdd800000-7bdda00000 r--p 0 00:00 0   libart.so
-7bdda00000-7bddf4a000 r-xp 200000 00:00 0   libart.so
-7e86814000-7e86850000 r--p 0 00:00 0   libc.so
-7e86850000-7e868d1000 r-xp 3c000 00:00 0   libc.so
diff --git a/libunwindstack/offline_files/maps_compiled_arm64/28648/output.txt b/libunwindstack/offline_files/maps_compiled_arm64/28648/output.txt
deleted file mode 100644
index e0fff1f..0000000
--- a/libunwindstack/offline_files/maps_compiled_arm64/28648/output.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-  #00 pc 000000000004c35c  libc.so (syscall+28)
-  #01 pc 0000000000411148  libart.so (art::Thread::Park(bool, long)+1088)
-  #02 pc 0000000000410790  libart.so (art::Unsafe_park(_JNIEnv*, _jobject*, unsigned char, long)+280)
-  #03 pc 00000000000adf4c  boot.oat (art_jni_trampoline+108)
-  #04 pc 000000000023c924  boot.oat (java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await+756)
-  #05 pc 00000000003d966c  boot.oat (java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take+524)
-  #06 pc 0000000000394ab8  boot.oat ([DEDUPED]+40)
-  #07 pc 0000000000377574  boot.oat (java.util.concurrent.ThreadPoolExecutor.getTask+484)
-  #08 pc 000000000037b46c  boot.oat (java.util.concurrent.ThreadPoolExecutor.runWorker+236)
-  #09 pc 0000000000374f84  boot.oat (java.util.concurrent.ThreadPoolExecutor$Worker.run+68)
-  #10 pc 00000000049a8668  base.odex_maps_compiled_arm64 (czkj.run+120)
-  #11 pc 00000000001bf0bc  boot.oat (java.lang.Thread.run+76)
-  #12 pc 0000000000293564  libart.so (art_quick_invoke_stub+548)
-  #13 pc 00000000002c6558  libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+156)
-  #14 pc 0000000000367ea8  libart.so (art::JValue art::InvokeVirtualOrInterfaceWithJValues<art::ArtMethod*>(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, art::ArtMethod*, jvalue const*)+380)
-  #15 pc 00000000003e9b6c  libart.so (art::Thread::CreateCallback(void*)+1004)
-  #16 pc 00000000000b1920  libc.so (__pthread_start(void*)+264)
-  #17 pc 00000000000513f0  libc.so (__start_thread+64)
diff --git a/libunwindstack/offline_files/maps_compiled_arm64/28648/regs.txt b/libunwindstack/offline_files/maps_compiled_arm64/28648/regs.txt
deleted file mode 100644
index 19fdcdb..0000000
--- a/libunwindstack/offline_files/maps_compiled_arm64/28648/regs.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-x0: 7d4f6effa8
-x1: 80
-x2: 2
-x3: 0
-x4: 0
-x5: 0
-x6: 0
-x7: 20
-x8: 62
-x9: 7bff6b7e40
-x10: 430000
-x11: 10
-x12: 13758080
-x13: 10
-x14: 0
-x15: 177d30dc
-x16: 7bde011728
-x17: 7e86860340
-x18: 7b4bc6a000
-x19: 7d4f6effa8
-x20: 7d4f6eff70
-x21: 47
-x22: 0
-x23: 7bde215000
-x24: 0
-x25: 1
-x26: 0
-x27: 7bde217000
-x28: 7b586cf000
-x29: 7b586ce500
-lr: 7bddc1114c
-sp: 7b586ce4d0
-pc: 7e8686035c
-pst: 40000000
diff --git a/libunwindstack/offline_files/maps_compiled_arm64/28648/stack.data b/libunwindstack/offline_files/maps_compiled_arm64/28648/stack.data
deleted file mode 100644
index dbf4731..0000000
--- a/libunwindstack/offline_files/maps_compiled_arm64/28648/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/maps_compiled_arm64/28656_oat_odex_jar/links.txt b/libunwindstack/offline_files/maps_compiled_arm64/28656_oat_odex_jar/links.txt
deleted file mode 100644
index 03ba1a5..0000000
--- a/libunwindstack/offline_files/maps_compiled_arm64/28656_oat_odex_jar/links.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-../../common/base.odex_maps_compiled_arm64 base.odex_maps_compiled_arm64
-../../common/boot.oat_c3e0e6503935c4103ec839d45f3a2183bd910e3c boot.oat
-../../common/libart.so_82c0556f4b66528e4a608c100a63b712 libart.so
-../../common/libc.so_f3791c53da47e6e72151dcc8088b9048 libc.so
diff --git a/libunwindstack/offline_files/maps_compiled_arm64/28656_oat_odex_jar/maps.txt b/libunwindstack/offline_files/maps_compiled_arm64/28656_oat_odex_jar/maps.txt
deleted file mode 100644
index c3ff7aa..0000000
--- a/libunwindstack/offline_files/maps_compiled_arm64/28656_oat_odex_jar/maps.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-6fcf3000-6fd9e000 r--p 0 00:00 0   boot.oat
-6fd9e000-700fe000 r-xp ab000 00:00 0   boot.oat
-7b590f4000-7b5a2aa000 r--p 0 00:00 0   base.odex_maps_compiled_arm64
-7b5a2aa000-7b6061c000 r-xp 11b6000 00:00 0   base.odex_maps_compiled_arm64
-7bdd326000-7bdd800000 r--p 0 00:00 0   core-oj.jar
-7bdd800000-7bdda00000 r--p 0 00:00 0   libart.so
-7bdda00000-7bddf4a000 r-xp 200000 00:00 0   libart.so
-7e86814000-7e86850000 r--p 0 00:00 0   libc.so
-7e86850000-7e868d1000 r-xp 3c000 00:00 0   libc.so
diff --git a/libunwindstack/offline_files/maps_compiled_arm64/28656_oat_odex_jar/output.txt b/libunwindstack/offline_files/maps_compiled_arm64/28656_oat_odex_jar/output.txt
deleted file mode 100644
index 3ca316f..0000000
--- a/libunwindstack/offline_files/maps_compiled_arm64/28656_oat_odex_jar/output.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-  #00 pc 000000000004c35c  libc.so (syscall+28)
-  #01 pc 0000000000411148  libart.so (art::Thread::Park(bool, long)+1088)
-  #02 pc 0000000000410790  libart.so (art::Unsafe_park(_JNIEnv*, _jobject*, unsigned char, long)+280)
-  #03 pc 00000000000adf4c  boot.oat (art_jni_trampoline+108)
-  #04 pc 000000000023c924  boot.oat (java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await+756)
-  #05 pc 000000000020aec4  libart.so (nterp_helper+7636)
-  #06 pc 00000000001faf02  core-oj.jar
-  #07 pc 000000000020a044  libart.so (nterp_helper+3924)
-  #08 pc 00000000001fab38  core-oj.jar
-  #09 pc 0000000000377574  boot.oat (java.util.concurrent.ThreadPoolExecutor.getTask+484)
-  #10 pc 000000000037b46c  boot.oat (java.util.concurrent.ThreadPoolExecutor.runWorker+236)
-  #11 pc 0000000000374f84  boot.oat (java.util.concurrent.ThreadPoolExecutor$Worker.run+68)
-  #12 pc 0000000002f041f4  base.odex_maps_compiled_arm64 (bwjw.run+564)
-  #13 pc 00000000001bf0bc  boot.oat (java.lang.Thread.run+76)
-  #14 pc 0000000000293564  libart.so (art_quick_invoke_stub+548)
-  #15 pc 00000000002c6558  libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+156)
-  #16 pc 0000000000367ea8  libart.so (art::JValue art::InvokeVirtualOrInterfaceWithJValues<art::ArtMethod*>(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, art::ArtMethod*, jvalue const*)+380)
-  #17 pc 00000000003e9b6c  libart.so (art::Thread::CreateCallback(void*)+1004)
-  #18 pc 00000000000b1920  libc.so (__pthread_start(void*)+264)
-  #19 pc 00000000000513f0  libc.so (__start_thread+64)
diff --git a/libunwindstack/offline_files/maps_compiled_arm64/28656_oat_odex_jar/regs.txt b/libunwindstack/offline_files/maps_compiled_arm64/28656_oat_odex_jar/regs.txt
deleted file mode 100644
index 6428f11..0000000
--- a/libunwindstack/offline_files/maps_compiled_arm64/28656_oat_odex_jar/regs.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-x0: 7d4f6f8ab8
-x1: 80
-x2: 2
-x3: 0
-x4: 0
-x5: 0
-x6: 0
-x7: 20
-x8: 62
-x9: 7bff6b7e40
-x10: 430000
-x11: 10
-x12: 4
-x13: 1ac8703d
-x14: 7b57dcf610
-x15: 177d143c
-x16: 7bde011728
-x17: 7e86860340
-x18: 7b44f5e000
-x19: 7d4f6f8ab8
-x20: 7d4f6f8a80
-x21: 47
-x22: 0
-x23: 7bde215000
-x24: 0
-x25: 1
-x26: 0
-x27: 7bde217000
-x28: 7b57dd0000
-x29: 7b57dcf3c0
-lr: 7bddc1114c
-sp: 7b57dcf390
-pc: 7e8686035c
-pst: 40000000
diff --git a/libunwindstack/offline_files/maps_compiled_arm64/28656_oat_odex_jar/stack.data b/libunwindstack/offline_files/maps_compiled_arm64/28656_oat_odex_jar/stack.data
deleted file mode 100644
index a44fcdd..0000000
--- a/libunwindstack/offline_files/maps_compiled_arm64/28656_oat_odex_jar/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/maps_compiled_arm64/28667/links.txt b/libunwindstack/offline_files/maps_compiled_arm64/28667/links.txt
deleted file mode 100644
index 3f9febc..0000000
--- a/libunwindstack/offline_files/maps_compiled_arm64/28667/links.txt
+++ /dev/null
@@ -1 +0,0 @@
-../../common/libc.so_f3791c53da47e6e72151dcc8088b9048 libc.so
diff --git a/libunwindstack/offline_files/maps_compiled_arm64/28667/maps.txt b/libunwindstack/offline_files/maps_compiled_arm64/28667/maps.txt
deleted file mode 100644
index b9a4bb8..0000000
--- a/libunwindstack/offline_files/maps_compiled_arm64/28667/maps.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-7b38a95000-7b38ef0000 r-xp 1000 00:00 0   CronetDynamite.apk
-7e86814000-7e86850000 r--p 0 00:00 0   libc.so
-7e86850000-7e868d1000 r-xp 3c000 00:00 0   libc.so
diff --git a/libunwindstack/offline_files/maps_compiled_arm64/28667/output.txt b/libunwindstack/offline_files/maps_compiled_arm64/28667/output.txt
deleted file mode 100644
index 7a65fc6..0000000
--- a/libunwindstack/offline_files/maps_compiled_arm64/28667/output.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-  #00 pc 000000000004c35c  libc.so (syscall+28)
-  #01 pc 0000000000050980  libc.so (__futex_wait_ex(void volatile*, bool, int, bool, timespec const*)+144)
-  #02 pc 00000000000b0c64  libc.so (pthread_cond_timedwait+140)
-  #03 pc 000000000027550c  CronetDynamite.apk (offset 0x1000)
diff --git a/libunwindstack/offline_files/maps_compiled_arm64/28667/regs.txt b/libunwindstack/offline_files/maps_compiled_arm64/28667/regs.txt
deleted file mode 100644
index 9416bb2..0000000
--- a/libunwindstack/offline_files/maps_compiled_arm64/28667/regs.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-x0: 7b35894a10
-x1: 89
-x2: 2
-x3: 7b358948e0
-x4: 0
-x5: ffffffff
-x6: ffffffff
-x7: 2e65746163696669
-x8: 62
-x9: 89
-x10: 9
-x11: 0
-x12: 0
-x13: 92708000f58
-x14: 23ef2f8bd6c2ce
-x15: 15f199c2
-x16: 7e868d40a8
-x17: 7e86860340
-x18: 7b34300000
-x19: 2
-x20: 7b358948e0
-x21: 7b35894a10
-x22: 89
-x23: 7b35894fb0
-x24: 7b35895000
-x25: 4b
-x26: 7c2f6b0000
-x27: 7b38b4a5b0
-x28: 1
-x29: 7b35894840
-lr: 7e86864984
-sp: 7b35894820
-pc: 7e8686035c
-pst: 40000000
diff --git a/libunwindstack/offline_files/maps_compiled_arm64/28667/stack.data b/libunwindstack/offline_files/maps_compiled_arm64/28667/stack.data
deleted file mode 100644
index 5f8f82c..0000000
--- a/libunwindstack/offline_files/maps_compiled_arm64/28667/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/offset_arm/libc.so.gz b/libunwindstack/offline_files/offset_arm/libc.so.gz
deleted file mode 100644
index e592dfb..0000000
--- a/libunwindstack/offline_files/offset_arm/libc.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/offset_arm/libunwindstack_test.gz b/libunwindstack/offline_files/offset_arm/libunwindstack_test.gz
deleted file mode 100644
index c27ce1a..0000000
--- a/libunwindstack/offline_files/offset_arm/libunwindstack_test.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/offset_arm/output.txt b/libunwindstack/offline_files/offset_arm/output.txt
deleted file mode 100644
index 36bd388..0000000
--- a/libunwindstack/offline_files/offset_arm/output.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-  #00 pc 0032bfa0  libunwindstack_test (SignalInnerFunction+40)
-  #01 pc 0032bfeb  libunwindstack_test (SignalMiddleFunction+2)
-  #02 pc 0032bff3  libunwindstack_test (SignalOuterFunction+2)
-  #03 pc 0032fed3  libunwindstack_test (unwindstack::SignalCallerHandler(int, siginfo*, void*)+26)
-  #04 pc 0002652c  libc.so (__restore)
-  #05 pc 00000000  <unknown>
-  #06 pc 0032c2d9  libunwindstack_test (InnerFunction+736)
-  #07 pc 0032cc4f  libunwindstack_test (MiddleFunction+42)
-  #08 pc 0032cc81  libunwindstack_test (OuterFunction+42)
-  #09 pc 0032e547  libunwindstack_test (unwindstack::RemoteThroughSignal(int, unsigned int)+270)
-  #10 pc 0032ed99  libunwindstack_test (unwindstack::UnwindTest_remote_through_signal_with_invalid_func_Test::TestBody()+16)
-  #11 pc 00354453  libunwindstack_test (testing::Test::Run()+154)
-  #12 pc 00354de7  libunwindstack_test (testing::TestInfo::Run()+194)
-  #13 pc 00355105  libunwindstack_test (testing::TestCase::Run()+180)
-  #14 pc 0035a215  libunwindstack_test (testing::internal::UnitTestImpl::RunAllTests()+664)
-  #15 pc 00359f4f  libunwindstack_test (testing::UnitTest::Run()+110)
-  #16 pc 0034d3db  libunwindstack_test (main+38)
-  #17 pc 00092c0d  libc.so (__libc_init+48)
-  #18 pc 0004202f  libunwindstack_test (_start_main+38)
diff --git a/libunwindstack/offline_files/pauth_pc_arm64/libc.so.gz b/libunwindstack/offline_files/pauth_pc_arm64/libc.so.gz
deleted file mode 100644
index 48397a0..0000000
--- a/libunwindstack/offline_files/pauth_pc_arm64/libc.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/pauth_pc_arm64/output.txt b/libunwindstack/offline_files/pauth_pc_arm64/output.txt
deleted file mode 100644
index a41d36a..0000000
--- a/libunwindstack/offline_files/pauth_pc_arm64/output.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-  #00 pc 00000000000404a8  toybox (do_print+28)
-  #01 pc 0000000000040270  toybox (do_find+5072)
-  #02 pc 000000000002c640  toybox (dirtree_handle_callback+40)
-  #03 pc 000000000002c588  toybox (dirtree_recurse+200)
-  #04 pc 000000000002c6a8  toybox (dirtree_handle_callback+144)
-  #05 pc 000000000002c588  toybox (dirtree_recurse+200)
-  #06 pc 000000000002c6a8  toybox (dirtree_handle_callback+144)
-  #07 pc 000000000002c588  toybox (dirtree_recurse+200)
-  #08 pc 000000000002c6a8  toybox (dirtree_handle_callback+144)
-  #09 pc 000000000002c588  toybox (dirtree_recurse+200)
-  #10 pc 000000000002c6a8  toybox (dirtree_handle_callback+144)
-  #11 pc 000000000002c588  toybox (dirtree_recurse+200)
-  #12 pc 000000000002c6a8  toybox (dirtree_handle_callback+144)
-  #13 pc 000000000002c588  toybox (dirtree_recurse+200)
-  #14 pc 000000000002c6a8  toybox (dirtree_handle_callback+144)
-  #15 pc 000000000002c588  toybox (dirtree_recurse+200)
-  #16 pc 000000000002c6a8  toybox (dirtree_handle_callback+144)
-  #17 pc 000000000002c588  toybox (dirtree_recurse+200)
-  #18 pc 000000000002c6a8  toybox (dirtree_handle_callback+144)
-  #19 pc 000000000002c588  toybox (dirtree_recurse+200)
-  #20 pc 000000000002c6a8  toybox (dirtree_handle_callback+144)
-  #21 pc 000000000003ee54  toybox (find_main+272)
-  #22 pc 0000000000034834  toybox (toy_exec_which+88)
-  #23 pc 00000000000342cc  toybox (toybox_main+148)
-  #24 pc 00000000000348b4  toybox (main+120)
-  #25 pc 00000000000499d8  libc.so (__libc_init+112)
diff --git a/libunwindstack/offline_files/pauth_pc_arm64/toybox.gz b/libunwindstack/offline_files/pauth_pc_arm64/toybox.gz
deleted file mode 100644
index a8edec9..0000000
--- a/libunwindstack/offline_files/pauth_pc_arm64/toybox.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/photos_reset_arm64/links.txt b/libunwindstack/offline_files/photos_reset_arm64/links.txt
deleted file mode 100644
index aadfa08..0000000
--- a/libunwindstack/offline_files/photos_reset_arm64/links.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-../common/boot.oat_c3e0e6503935c4103ec839d45f3a2183bd910e3c boot.oat
-../common/libart.so_82c0556f4b66528e4a608c100a63b712 libart.so
-../common/libc.so_f3791c53da47e6e72151dcc8088b9048 libc.so
diff --git a/libunwindstack/offline_files/photos_reset_arm64/maps.txt b/libunwindstack/offline_files/photos_reset_arm64/maps.txt
deleted file mode 100644
index 49237cc..0000000
--- a/libunwindstack/offline_files/photos_reset_arm64/maps.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-6fcf3000-6fd9e000 r--p 0 00:00 0   boot.oat
-6fd9e000-700fe000 r-xp ab000 00:00 0   boot.oat
-7b64f9d000-7b65286000 r--p 0 00:00 0   base.apk!classes4.dex
-7b65c00000-7b66307000 r--p 0 00:00 0   base.apk!classes2.dex
-7bdd800000-7bdda00000 r--p 0 00:00 0   libart.so
-7bdda00000-7bddf4a000 r-xp 200000 00:00 0   libart.so
-7e86814000-7e86850000 r--p 0 00:00 0   libc.so
-7e86850000-7e868d1000 r-xp 3c000 00:00 0   libc.so
diff --git a/libunwindstack/offline_files/photos_reset_arm64/output.txt b/libunwindstack/offline_files/photos_reset_arm64/output.txt
deleted file mode 100644
index d046c00..0000000
--- a/libunwindstack/offline_files/photos_reset_arm64/output.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-  #00 pc 000000000004c35c  libc.so (syscall+28)
-  #01 pc 0000000000353010  libart.so (art::ConditionVariable::WaitHoldingLocks(art::Thread*)+148)
-  #02 pc 000000000031d7dc  libart.so (art::Monitor::Wait(art::Thread*, long, int, bool, art::ThreadState)+1228)
-  #03 pc 000000000031ce90  libart.so (art::Monitor::Wait(art::Thread*, art::ObjPtr<art::mirror::Object>, long, int, bool, art::ThreadState)+524)
-  #04 pc 00000000000ab35c  boot.oat (art_jni_trampoline+108)
-  #05 pc 00000000000cc278  boot.oat (java.lang.ref.ReferenceQueue.remove+360)
-  #06 pc 00000000000cc0ec  boot.oat (java.lang.ref.ReferenceQueue.remove+44)
-  #07 pc 000000000020a0a0  libart.so (nterp_helper+4016)
-  #08 pc 0000000000404264  base.apk!classes2.dex
-  #09 pc 000000000037b75c  boot.oat (java.util.concurrent.ThreadPoolExecutor.runWorker+988)
-  #10 pc 0000000000374f84  boot.oat (java.util.concurrent.ThreadPoolExecutor$Worker.run+68)
-  #11 pc 000000000020aec4  libart.so (nterp_helper+7636)
-  #12 pc 00000000000f2a24  base.apk!classes4.dex
-  #13 pc 00000000001bf0bc  boot.oat (java.lang.Thread.run+76)
-  #14 pc 0000000000293564  libart.so (art_quick_invoke_stub+548)
-  #15 pc 00000000002c6558  libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+156)
-  #16 pc 0000000000367ea8  libart.so (art::JValue art::InvokeVirtualOrInterfaceWithJValues<art::ArtMethod*>(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, art::ArtMethod*, jvalue const*)+380)
-  #17 pc 00000000003e9b6c  libart.so (art::Thread::CreateCallback(void*)+1004)
-  #18 pc 00000000000b1920  libc.so (__pthread_start(void*)+264)
-  #19 pc 00000000000513f0  libc.so (__start_thread+64)
diff --git a/libunwindstack/offline_files/photos_reset_arm64/regs.txt b/libunwindstack/offline_files/photos_reset_arm64/regs.txt
deleted file mode 100644
index 77c2e78..0000000
--- a/libunwindstack/offline_files/photos_reset_arm64/regs.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-x0: 7bff6e4bb0
-x1: 80
-x2: 0
-x3: 0
-x4: 0
-x5: 0
-x6: 0
-x7: 3030303030303034
-x8: 62
-x9: 87fc4d8789a28136
-x10: 0
-x11: ff6fd6f8
-x12: ffff00000eff
-x13: 106b9c07
-x14: 7b5d33e730
-x15: 0
-x16: 7bde011728
-x17: 7e86860340
-x18: 7b5ce14000
-x19: 7bff6e4ba0
-x20: 7d4f6eac00
-x21: 0
-x22: 7bff6e4bb0
-x23: 0
-x24: 7c0f6ccb50
-x25: 7b5d33f000
-x26: 1
-x27: 7d2f6b2f30
-x28: 7d2f6b2f18
-x29: 7b5d33e090
-lr: 7bddb53014
-sp: 7b5d33e080
-pc: 7e8686035c
-pst: 60000000
diff --git a/libunwindstack/offline_files/photos_reset_arm64/stack.data b/libunwindstack/offline_files/photos_reset_arm64/stack.data
deleted file mode 100644
index 0f576e3..0000000
--- a/libunwindstack/offline_files/photos_reset_arm64/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/shared_lib_in_apk_arm64/libc.so.gz b/libunwindstack/offline_files/shared_lib_in_apk_arm64/libc.so.gz
deleted file mode 100644
index 259534f..0000000
--- a/libunwindstack/offline_files/shared_lib_in_apk_arm64/libc.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/shared_lib_in_apk_arm64/linker64.gz b/libunwindstack/offline_files/shared_lib_in_apk_arm64/linker64.gz
deleted file mode 100644
index abcaa33..0000000
--- a/libunwindstack/offline_files/shared_lib_in_apk_arm64/linker64.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/shared_lib_in_apk_arm64/output.txt b/libunwindstack/offline_files/shared_lib_in_apk_arm64/output.txt
deleted file mode 100644
index d7bbf39..0000000
--- a/libunwindstack/offline_files/shared_lib_in_apk_arm64/output.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-  #00 pc 000000000014ccbc  linker64 (__dl_syscall+28)
-  #01 pc 000000000005426c  linker64 (__dl__ZL24debuggerd_signal_handleriP7siginfoPv+1128)
-  #02 pc 00000000000008c0  vdso.so (__kernel_rt_sigreturn)
-  #03 pc 00000000000846f4  libc.so (abort+172)
-  #04 pc 0000000000084ad4  libc.so (__assert2+36)
-  #05 pc 000000000003d5b4  ANGLEPrebuilt.apk!libfeature_support_angle.so (offset 0x4000) (ANGLEGetUtilityAPI+56)
-  #06 pc 000000000007fe68  libc.so (__libc_init)
diff --git a/libunwindstack/offline_files/shared_lib_in_apk_arm64/vdso.so.gz b/libunwindstack/offline_files/shared_lib_in_apk_arm64/vdso.so.gz
deleted file mode 100644
index e08b7cc..0000000
--- a/libunwindstack/offline_files/shared_lib_in_apk_arm64/vdso.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/shared_lib_in_apk_memory_only_arm64/libc.so.gz b/libunwindstack/offline_files/shared_lib_in_apk_memory_only_arm64/libc.so.gz
deleted file mode 100644
index 31e71ca..0000000
--- a/libunwindstack/offline_files/shared_lib_in_apk_memory_only_arm64/libc.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/shared_lib_in_apk_memory_only_arm64/linker64.gz b/libunwindstack/offline_files/shared_lib_in_apk_memory_only_arm64/linker64.gz
deleted file mode 100644
index 0f1424e..0000000
--- a/libunwindstack/offline_files/shared_lib_in_apk_memory_only_arm64/linker64.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/shared_lib_in_apk_memory_only_arm64/output.txt b/libunwindstack/offline_files/shared_lib_in_apk_memory_only_arm64/output.txt
deleted file mode 100644
index c733893..0000000
--- a/libunwindstack/offline_files/shared_lib_in_apk_memory_only_arm64/output.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-  #00 pc 000000000014ccbc  linker64 (__dl_syscall+28)
-  #01 pc 000000000005426c  linker64 (__dl__ZL24debuggerd_signal_handleriP7siginfoPv+1128)
-  #02 pc 00000000000008c0  vdso.so (__kernel_rt_sigreturn)
-  #03 pc 00000000000846f4  libc.so (abort+172)
-  #04 pc 0000000000084ad4  libc.so (__assert2+36)
-  #05 pc 000000000003d5b4  ANGLEPrebuilt.apk (offset 0x21d5000)
-  #06 pc 000000000007fe68  libc.so (__libc_init)
diff --git a/libunwindstack/offline_files/shared_lib_in_apk_memory_only_arm64/vdso.so.gz b/libunwindstack/offline_files/shared_lib_in_apk_memory_only_arm64/vdso.so.gz
deleted file mode 100644
index bf06ecf..0000000
--- a/libunwindstack/offline_files/shared_lib_in_apk_memory_only_arm64/vdso.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/shared_lib_in_apk_single_map_arm64/libc.so.gz b/libunwindstack/offline_files/shared_lib_in_apk_single_map_arm64/libc.so.gz
deleted file mode 100644
index cac2635..0000000
--- a/libunwindstack/offline_files/shared_lib_in_apk_single_map_arm64/libc.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/shared_lib_in_apk_single_map_arm64/output.txt b/libunwindstack/offline_files/shared_lib_in_apk_single_map_arm64/output.txt
deleted file mode 100644
index cb1978b..0000000
--- a/libunwindstack/offline_files/shared_lib_in_apk_single_map_arm64/output.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-  #00 pc 00000000000814bc  libc.so (syscall+28)
-  #01 pc 00000000008cdf5c  test.apk (offset 0x5000)
-  #02 pc 00000000008cde9c  test.apk (offset 0x5000)
-  #03 pc 00000000008cdd70  test.apk (offset 0x5000)
-  #04 pc 00000000008ce408  test.apk (offset 0x5000)
-  #05 pc 00000000008ce8d8  test.apk (offset 0x5000)
-  #06 pc 00000000008ce814  test.apk (offset 0x5000)
-  #07 pc 00000000008bcf60  test.apk (offset 0x5000)
-  #08 pc 0000000000133024  test.apk (offset 0x5000)
-  #09 pc 0000000000134ad0  test.apk (offset 0x5000)
-  #10 pc 0000000000134b64  test.apk (offset 0x5000)
-  #11 pc 00000000000e406c  libc.so (__pthread_start(void*)+36)
-  #12 pc 0000000000085e18  libc.so (__start_thread+64)
diff --git a/libunwindstack/offline_files/signal_fde_x86/libc.so.gz b/libunwindstack/offline_files/signal_fde_x86/libc.so.gz
deleted file mode 100644
index af44763..0000000
--- a/libunwindstack/offline_files/signal_fde_x86/libc.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/signal_fde_x86/libunwindstack_test.gz b/libunwindstack/offline_files/signal_fde_x86/libunwindstack_test.gz
deleted file mode 100644
index 92e59ea..0000000
--- a/libunwindstack/offline_files/signal_fde_x86/libunwindstack_test.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/signal_fde_x86/output.txt b/libunwindstack/offline_files/signal_fde_x86/output.txt
deleted file mode 100644
index eb1a0ec..0000000
--- a/libunwindstack/offline_files/signal_fde_x86/output.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-  #00 pc 007914d9  libunwindstack_test (SignalInnerFunction+25)
-  #01 pc 007914fc  libunwindstack_test (SignalMiddleFunction+28)
-  #02 pc 0079152c  libunwindstack_test (SignalOuterFunction+28)
-  #03 pc 0079af62  libunwindstack_test (unwindstack::SignalCallerHandler(int, siginfo*, void*)+50)
-  #04 pc 00058fb0  libc.so (__restore)
-  #05 pc 00000000  <unknown>
-  #06 pc 0079161a  libunwindstack_test (InnerFunction+218)
-  #07 pc 007923aa  libunwindstack_test (MiddleFunction+42)
-  #08 pc 007923ea  libunwindstack_test (OuterFunction+42)
-  #09 pc 00797444  libunwindstack_test (unwindstack::RemoteThroughSignal(int, unsigned int)+868)
-  #10 pc 007985b8  libunwindstack_test (unwindstack::UnwindTest_remote_through_signal_with_invalid_func_Test::TestBody()+56)
-  #11 pc 00817a19  libunwindstack_test
-  #12 pc 008178c5  libunwindstack_test (testing::Test::Run()+277)
-  #13 pc 00818d3e  libunwindstack_test (testing::TestInfo::Run()+318)
-  #14 pc 008198b4  libunwindstack_test (testing::TestSuite::Run()+436)
-  #15 pc 00828cb0  libunwindstack_test (testing::internal::UnitTestImpl::RunAllTests()+1216)
-  #16 pc 0082870f  libunwindstack_test (testing::UnitTest::Run()+367)
-  #17 pc 0084031e  libunwindstack_test (IsolateMain+2334)
-  #18 pc 0083f9e9  libunwindstack_test (main+41)
-  #19 pc 00050646  libc.so (__libc_init+118)
diff --git a/libunwindstack/offline_files/signal_fde_x86_64/libc.so.gz b/libunwindstack/offline_files/signal_fde_x86_64/libc.so.gz
deleted file mode 100644
index 048cb54..0000000
--- a/libunwindstack/offline_files/signal_fde_x86_64/libc.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/signal_fde_x86_64/libunwindstack_test.gz b/libunwindstack/offline_files/signal_fde_x86_64/libunwindstack_test.gz
deleted file mode 100644
index e60eb34..0000000
--- a/libunwindstack/offline_files/signal_fde_x86_64/libunwindstack_test.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/signal_fde_x86_64/output.txt b/libunwindstack/offline_files/signal_fde_x86_64/output.txt
deleted file mode 100644
index 6ac6e3a..0000000
--- a/libunwindstack/offline_files/signal_fde_x86_64/output.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-  #00 pc 000000000058415b  libunwindstack_test (SignalInnerFunction+11)
-  #01 pc 0000000000584168  libunwindstack_test (SignalMiddleFunction+8)
-  #02 pc 0000000000584178  libunwindstack_test (SignalOuterFunction+8)
-  #03 pc 000000000058ac77  libunwindstack_test (unwindstack::SignalCallerHandler(int, siginfo*, void*)+23)
-  #04 pc 0000000000057d10  libc.so (__restore_rt)
-  #05 pc 0000000000000000  <unknown>
-  #06 pc 0000000000584244  libunwindstack_test (InnerFunction+196)
-  #07 pc 0000000000584b44  libunwindstack_test (MiddleFunction+20)
-  #08 pc 0000000000584b64  libunwindstack_test (OuterFunction+20)
-  #09 pc 0000000000588457  libunwindstack_test (unwindstack::RemoteThroughSignal(int, unsigned int)+583)
-  #10 pc 0000000000588f67  libunwindstack_test (unwindstack::UnwindTest_remote_through_signal_with_invalid_func_Test::TestBody()+23)
-  #11 pc 00000000005d9c38  libunwindstack_test (testing::Test::Run()+216)
-  #12 pc 00000000005daf9a  libunwindstack_test (testing::TestInfo::Run()+266)
-  #13 pc 00000000005dba46  libunwindstack_test (testing::TestSuite::Run()+390)
-  #14 pc 00000000005ea4c6  libunwindstack_test (testing::internal::UnitTestImpl::RunAllTests()+1190)
-  #15 pc 00000000005e9f61  libunwindstack_test (testing::UnitTest::Run()+337)
-  #16 pc 0000000000600155  libunwindstack_test (IsolateMain+2037)
-  #17 pc 000000000004e405  libc.so (__libc_init+101)
diff --git a/libunwindstack/offline_files/signal_load_bias_arm/libc.so.gz b/libunwindstack/offline_files/signal_load_bias_arm/libc.so.gz
deleted file mode 100644
index 8b9d517..0000000
--- a/libunwindstack/offline_files/signal_load_bias_arm/libc.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/signal_load_bias_arm/libunwindstack_unit_test.gz b/libunwindstack/offline_files/signal_load_bias_arm/libunwindstack_unit_test.gz
deleted file mode 100644
index bd28d05..0000000
--- a/libunwindstack/offline_files/signal_load_bias_arm/libunwindstack_unit_test.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/signal_load_bias_arm/output.txt b/libunwindstack/offline_files/signal_load_bias_arm/output.txt
deleted file mode 100644
index a4e2d6c..0000000
--- a/libunwindstack/offline_files/signal_load_bias_arm/output.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-  #00 pc 0029ef9e  libunwindstack_unit_test (SignalInnerFunction+10)
-  #01 pc 0029efa7  libunwindstack_unit_test (SignalMiddleFunction+2)
-  #02 pc 0029efaf  libunwindstack_unit_test (SignalOuterFunction+2)
-  #03 pc 002a280b  libunwindstack_unit_test (unwindstack::SignalCallerHandler(int, siginfo*, void*)+10)
-  #04 pc 00058bd4  libc.so (__restore)
-  #05 pc 0029f01e  libunwindstack_unit_test (InnerFunction+106)
-  #06 pc 0029f633  libunwindstack_unit_test (MiddleFunction+16)
-  #07 pc 0029f64b  libunwindstack_unit_test (OuterFunction+16)
-  #08 pc 002a1711  libunwindstack_unit_test (unwindstack::RemoteThroughSignal(int, unsigned int)+260)
-  #09 pc 002a1603  libunwindstack_unit_test (unwindstack::UnwindTest_remote_through_signal_Test::TestBody()+10)
-  #10 pc 002c8fe3  libunwindstack_unit_test (testing::Test::Run()+130)
-  #11 pc 002c9b25  libunwindstack_unit_test (testing::TestInfo::Run()+184)
-  #12 pc 002c9e27  libunwindstack_unit_test (testing::TestSuite::Run()+202)
-  #13 pc 002d193d  libunwindstack_unit_test (testing::internal::UnitTestImpl::RunAllTests()+660)
-  #14 pc 002d160b  libunwindstack_unit_test (testing::UnitTest::Run()+134)
-  #15 pc 002de035  libunwindstack_unit_test (IsolateMain+680)
-  #16 pc 00058155  libc.so (__libc_init+68)
diff --git a/libunwindstack/offline_files/straddle_arm/libbase.so.gz b/libunwindstack/offline_files/straddle_arm/libbase.so.gz
deleted file mode 100644
index 94093a5..0000000
--- a/libunwindstack/offline_files/straddle_arm/libbase.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/straddle_arm/libc.so.gz b/libunwindstack/offline_files/straddle_arm/libc.so.gz
deleted file mode 100644
index 415e83f..0000000
--- a/libunwindstack/offline_files/straddle_arm/libc.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/straddle_arm/output.txt b/libunwindstack/offline_files/straddle_arm/output.txt
deleted file mode 100644
index 1a26405..0000000
--- a/libunwindstack/offline_files/straddle_arm/output.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-  #00 pc 0001a9f8  libc.so (abort+64)
-  #01 pc 00006a1b  libbase.so (android::base::DefaultAborter(char const*)+6)
-  #02 pc 00007441  libbase.so (android::base::LogMessage::~LogMessage()+748)
-  #03 pc 00015147  /does/not/exist/libhidlbase.so
diff --git a/libunwindstack/offline_files/straddle_arm64/libunwindstack_test.gz b/libunwindstack/offline_files/straddle_arm64/libunwindstack_test.gz
deleted file mode 100644
index 82460c8..0000000
--- a/libunwindstack/offline_files/straddle_arm64/libunwindstack_test.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/straddle_arm64/output.txt b/libunwindstack/offline_files/straddle_arm64/output.txt
deleted file mode 100644
index c54daec..0000000
--- a/libunwindstack/offline_files/straddle_arm64/output.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-  #00 pc 0000000000429fd8  libunwindstack_test (SignalInnerFunction+24)
-  #01 pc 000000000042a078  libunwindstack_test (SignalMiddleFunction+8)
-  #02 pc 000000000042a08c  libunwindstack_test (SignalOuterFunction+8)
-  #03 pc 000000000042d8fc  libunwindstack_test (unwindstack::RemoteThroughSignal(int, unsigned int)+20)
-  #04 pc 000000000042d8d8  libunwindstack_test (unwindstack::UnwindTest_remote_through_signal_Test::TestBody()+32)
-  #05 pc 0000000000455d70  libunwindstack_test (testing::Test::Run()+392)
diff --git a/libunwindstack/offline_files/youtube_compiled_arm64/libbinder.so.gz b/libunwindstack/offline_files/youtube_compiled_arm64/libbinder.so.gz
deleted file mode 100644
index 0e52d42..0000000
--- a/libunwindstack/offline_files/youtube_compiled_arm64/libbinder.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/youtube_compiled_arm64/libcodec2_client.so.gz b/libunwindstack/offline_files/youtube_compiled_arm64/libcodec2_client.so.gz
deleted file mode 100644
index 19a563e..0000000
--- a/libunwindstack/offline_files/youtube_compiled_arm64/libcodec2_client.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/youtube_compiled_arm64/libgui.so.gz b/libunwindstack/offline_files/youtube_compiled_arm64/libgui.so.gz
deleted file mode 100644
index 45b4068..0000000
--- a/libunwindstack/offline_files/youtube_compiled_arm64/libgui.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/youtube_compiled_arm64/libsfplugin_ccodec.so.gz b/libunwindstack/offline_files/youtube_compiled_arm64/libsfplugin_ccodec.so.gz
deleted file mode 100644
index 3db0b38..0000000
--- a/libunwindstack/offline_files/youtube_compiled_arm64/libsfplugin_ccodec.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/youtube_compiled_arm64/libstagefright.so.gz b/libunwindstack/offline_files/youtube_compiled_arm64/libstagefright.so.gz
deleted file mode 100644
index 34398ad..0000000
--- a/libunwindstack/offline_files/youtube_compiled_arm64/libstagefright.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/youtube_compiled_arm64/libstagefright_foundation.so.gz b/libunwindstack/offline_files/youtube_compiled_arm64/libstagefright_foundation.so.gz
deleted file mode 100644
index 770de8a..0000000
--- a/libunwindstack/offline_files/youtube_compiled_arm64/libstagefright_foundation.so.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/youtube_compiled_arm64/links.txt b/libunwindstack/offline_files/youtube_compiled_arm64/links.txt
deleted file mode 100644
index 72892f4..0000000
--- a/libunwindstack/offline_files/youtube_compiled_arm64/links.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-../common/libandroid_runtime.so_7d88088666db374aecde2fbe51bff2f4 libandroid_runtime.so
-../common/libc.so_f3791c53da47e6e72151dcc8088b9048 libc.so
-../common/libutils.so_b8aa8db7e6895d0ba92398ca5d3ed2d4 libutils.so
diff --git a/libunwindstack/offline_files/youtube_compiled_arm64/maps.txt b/libunwindstack/offline_files/youtube_compiled_arm64/maps.txt
deleted file mode 100644
index 0d595c3..0000000
--- a/libunwindstack/offline_files/youtube_compiled_arm64/maps.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-7e6f820000-7e6f82d000 r--p 0 00:00 0   libutils.so
-7e6f82d000-7e6f839000 r-xp d000 00:00 0   libutils.so
-7e6f881000-7e6f895000 r--p 0 00:00 0   libstagefright_foundation.so
-7e6f895000-7e6f8b4000 r-xp 14000 00:00 0   libstagefright_foundation.so
-7e71cab000-7e71d2f000 r--p 0 00:00 0   libgui.so
-7e71d2f000-7e71dce000 r-xp 84000 00:00 0   libgui.so
-7e72942000-7e7299b000 r--p 0 00:00 0   libbinder.so
-7e7299b000-7e729ec000 r-xp 59000 00:00 0   libbinder.so
-7e77b5e000-7e77b86000 r--p 0 00:00 0   libsfplugin_ccodec.so
-7e77b86000-7e77bf6000 r-xp 28000 00:00 0   libsfplugin_ccodec.so
-7e7a40c000-7e7a48a000 r--p 0 00:00 0   libstagefright.so
-7e7a48a000-7e7a5b8000 r-xp 7e000 00:00 0   libstagefright.so
-7e7c400000-7e7c4af000 r--p 0 00:00 0   libandroid_runtime.so
-7e7c4af000-7e7c5df000 r-xp af000 00:00 0   libandroid_runtime.so
-7e84114000-7e84121000 r--p 0 00:00 0   libcodec2_client.so
-7e84121000-7e8413c000 r-xp d000 00:00 0   libcodec2_client.so
-7e86814000-7e86850000 r--p 0 00:00 0   libc.so
-7e86850000-7e868d1000 r-xp 3c000 00:00 0   libc.so
diff --git a/libunwindstack/offline_files/youtube_compiled_arm64/output.txt b/libunwindstack/offline_files/youtube_compiled_arm64/output.txt
deleted file mode 100644
index d832383..0000000
--- a/libunwindstack/offline_files/youtube_compiled_arm64/output.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-  #00 pc 000000000009d5e4  libc.so (__ioctl+4)
-  #01 pc 00000000000593e8  libc.so (ioctl+152)
-  #02 pc 000000000005ddac  libbinder.so (android::IPCThreadState::transact(int, unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+920)
-  #03 pc 000000000005d7d8  libbinder.so (android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+176)
-  #04 pc 00000000000aa0e4  libgui.so (android::BpSurfaceComposer::setTransactionState(android::FrameTimelineInfo const&, android::Vector<android::ComposerState> const&, android::Vector<android::DisplayState> const&, unsigned int, android::sp<android::IBinder> const&, android::InputWindowCommands const&, long, bool, android::client_cache_t const&, bool, std::__1::vector<android::ListenerCallbacks, std::__1::allocator<android::ListenerCallbacks> > const&, unsigned long)+872)
-  #05 pc 00000000000a0ed8  libgui.so (android::SurfaceComposerClient::Transaction::apply(bool)+556)
-  #06 pc 00000000000947ac  libgui.so (android::BLASTBufferQueue::processNextBufferLocked(bool)+9748)
-  #07 pc 00000000000ae488  libgui.so (android::BLASTBufferQueue::onFrameAvailable(android::BufferItem const&)+136)
-  #08 pc 00000000000888d8  libgui.so (android::ConsumerBase::onFrameAvailable(android::BufferItem const&)+172)
-  #09 pc 0000000000084448  libgui.so (android::BufferQueue::ProxyConsumerListener::onFrameAvailable(android::BufferItem const&)+92)
-  #10 pc 00000000000c7b8c  libgui.so (android::BufferQueueProducer::queueBuffer(int, android::IGraphicBufferProducer::QueueBufferInput const&, android::IGraphicBufferProducer::QueueBufferOutput*)+2232)
-  #11 pc 00000000000258f4  libcodec2_client.so (android::hardware::media::c2::OutputBufferQueue::outputBuffer(C2ConstGraphicBlock const&, android::IGraphicBufferProducer::QueueBufferInput const&, android::IGraphicBufferProducer::QueueBufferOutput*)+1104)
-  #12 pc 000000000004a038  libsfplugin_ccodec.so (android::CCodecBufferChannel::renderOutputBuffer(android::sp<android::MediaCodecBuffer> const&, long)+2572)
-  #13 pc 000000000012036c  libstagefright.so (android::MediaCodec::onReleaseOutputBuffer(android::sp<android::AMessage> const&)+1184)
-  #14 pc 0000000000110158  libstagefright.so (android::MediaCodec::onMessageReceived(android::sp<android::AMessage> const&)+376)
-  #15 pc 00000000000188c0  libstagefright_foundation.so (android::AHandler::deliverMessage(android::sp<android::AMessage> const&)+84)
-  #16 pc 000000000001e68c  libstagefright_foundation.so (android::AMessage::deliver()+188)
-  #17 pc 0000000000019c08  libstagefright_foundation.so (android::ALooper::loop()+592)
-  #18 pc 0000000000012138  libutils.so (android::Thread::_threadLoop(void*)+460)
-  #19 pc 00000000000bc3ec  libandroid_runtime.so (android::AndroidRuntime::javaThreadShell(void*)+144)
-  #20 pc 0000000000011928  libutils.so (thread_data_t::trampoline(thread_data_t const*)+404)
-  #21 pc 00000000000b1920  libc.so (__pthread_start(void*)+264)
-  #22 pc 00000000000513f0  libc.so (__start_thread+64)
diff --git a/libunwindstack/offline_files/youtube_compiled_arm64/regs.txt b/libunwindstack/offline_files/youtube_compiled_arm64/regs.txt
deleted file mode 100644
index 110362b..0000000
--- a/libunwindstack/offline_files/youtube_compiled_arm64/regs.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-x0: 36
-x1: c0306201
-x2: 7b34407370
-x3: 7b344075a0
-x4: 7b344073b0
-x5: 7c8f6ffe54
-x6: 2c
-x7: 0
-x8: 1d
-x9: 7b34407310
-x10: 7b34407310
-x11: 7b344072e0
-x12: ffffff80ffffffd0
-x13: 7c1f790fd0
-x14: 1
-x15: 26
-x16: 7e729f9448
-x17: 7e8686d350
-x18: 7acb076000
-x19: 7b34409000
-x20: 7cbf755480
-x21: 7b34407520
-x22: 7cbf755408
-x23: 7cbf7553e0
-x24: 7cbf7553b8
-x25: 74
-x26: 80407203
-x27: 7b34409000
-x28: 7204
-x29: 7b34407340
-lr: 7e8686d3ec
-sp: 7b34407260
-pc: 7e868b15e4
-pst: 80000000
diff --git a/libunwindstack/offline_files/youtube_compiled_arm64/stack.data b/libunwindstack/offline_files/youtube_compiled_arm64/stack.data
deleted file mode 100644
index e238489..0000000
--- a/libunwindstack/offline_files/youtube_compiled_arm64/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/yt_music_arm64/base.odex.gz b/libunwindstack/offline_files/yt_music_arm64/base.odex.gz
deleted file mode 100644
index a19d1ed..0000000
--- a/libunwindstack/offline_files/yt_music_arm64/base.odex.gz
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/offline_files/yt_music_arm64/links.txt b/libunwindstack/offline_files/yt_music_arm64/links.txt
deleted file mode 100644
index aadfa08..0000000
--- a/libunwindstack/offline_files/yt_music_arm64/links.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-../common/boot.oat_c3e0e6503935c4103ec839d45f3a2183bd910e3c boot.oat
-../common/libart.so_82c0556f4b66528e4a608c100a63b712 libart.so
-../common/libc.so_f3791c53da47e6e72151dcc8088b9048 libc.so
diff --git a/libunwindstack/offline_files/yt_music_arm64/maps.txt b/libunwindstack/offline_files/yt_music_arm64/maps.txt
deleted file mode 100644
index f54f627..0000000
--- a/libunwindstack/offline_files/yt_music_arm64/maps.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-6fcf3000-6fd9e000 r--p 0 00:00 0   boot.oat
-6fd9e000-700fe000 r-xp ab000 00:00 0   boot.oat
-7b620b5000-7b6221b000 r--p 0 00:00 0   base.odex
-7b6221b000-7b6279f000 r-xp 166000 00:00 0   base.odex
-7bdd800000-7bdda00000 r--p 0 00:00 0   libart.so
-7bdda00000-7bddf4a000 r-xp 200000 00:00 0   libart.so
-7e86814000-7e86850000 r--p 0 00:00 0   libc.so
-7e86850000-7e868d1000 r-xp 3c000 00:00 0   libc.so
diff --git a/libunwindstack/offline_files/yt_music_arm64/output.txt b/libunwindstack/offline_files/yt_music_arm64/output.txt
deleted file mode 100644
index 0cba24a..0000000
--- a/libunwindstack/offline_files/yt_music_arm64/output.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-  #00 pc 000000000004c35c  libc.so (syscall+28)
-  #01 pc 0000000000411148  libart.so (art::Thread::Park(bool, long)+1088)
-  #02 pc 0000000000410790  libart.so (art::Unsafe_park(_JNIEnv*, _jobject*, unsigned char, long)+280)
-  #03 pc 00000000000adf4c  boot.oat (art_jni_trampoline+108)
-  #04 pc 000000000023c924  boot.oat (java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await+756)
-  #05 pc 00000000003d966c  boot.oat (java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take+524)
-  #06 pc 0000000000394ab8  boot.oat ([DEDUPED]+40)
-  #07 pc 0000000000377574  boot.oat (java.util.concurrent.ThreadPoolExecutor.getTask+484)
-  #08 pc 000000000037b46c  boot.oat (java.util.concurrent.ThreadPoolExecutor.runWorker+236)
-  #09 pc 0000000000374f84  boot.oat (java.util.concurrent.ThreadPoolExecutor$Worker.run+68)
-  #10 pc 000000000059ec1c  base.odex (lwo.run+92)
-  #11 pc 00000000001bf0bc  boot.oat (java.lang.Thread.run+76)
-  #12 pc 0000000000293564  libart.so (art_quick_invoke_stub+548)
-  #13 pc 00000000002c6558  libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+156)
-  #14 pc 0000000000367ea8  libart.so (art::JValue art::InvokeVirtualOrInterfaceWithJValues<art::ArtMethod*>(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, art::ArtMethod*, jvalue const*)+380)
-  #15 pc 00000000003e9b6c  libart.so (art::Thread::CreateCallback(void*)+1004)
-  #16 pc 00000000000b1920  libc.so (__pthread_start(void*)+264)
-  #17 pc 00000000000513f0  libc.so (__start_thread+64)
diff --git a/libunwindstack/offline_files/yt_music_arm64/regs.txt b/libunwindstack/offline_files/yt_music_arm64/regs.txt
deleted file mode 100644
index 9bbe3ce..0000000
--- a/libunwindstack/offline_files/yt_music_arm64/regs.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-x0: 7d4f6e3cf8
-x1: 80
-x2: 2
-x3: 0
-x4: 0
-x5: 0
-x6: 0
-x7: 20
-x8: 62
-x9: 7bff6b7e40
-x10: 430000
-x11: 40
-x12: 341555ac
-x13: 18
-x14: f5c2b97f58
-x15: 12dd106c
-x16: 7bde011728
-x17: 7e86860340
-x18: 7b5e54e000
-x19: 7d4f6e3cf8
-x20: 7d4f6e3cc0
-x21: 47
-x22: 0
-x23: 7bde215000
-x24: 0
-x25: 1
-x26: 0
-x27: 7bde217000
-x28: 7b5e85c000
-x29: 7b5e85b500
-lr: 7bddc1114c
-sp: 7b5e85b4d0
-pc: 7e8686035c
-pst: 40000000
diff --git a/libunwindstack/offline_files/yt_music_arm64/stack.data b/libunwindstack/offline_files/yt_music_arm64/stack.data
deleted file mode 100644
index 06345b7..0000000
--- a/libunwindstack/offline_files/yt_music_arm64/stack.data
+++ /dev/null
Binary files differ
diff --git a/libunwindstack/tests/AndroidUnwinderTest.cpp b/libunwindstack/tests/AndroidUnwinderTest.cpp
deleted file mode 100644
index 1794acc..0000000
--- a/libunwindstack/tests/AndroidUnwinderTest.cpp
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
- * Copyright (C) 2022 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 <dlfcn.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/types.h>
-#include <time.h>
-#include <unistd.h>
-
-#include <gtest/gtest.h>
-
-#include <atomic>
-#include <string>
-#include <thread>
-#include <vector>
-
-#include <android-base/strings.h>
-#include <android-base/threads.h>
-
-#include <unwindstack/AndroidUnwinder.h>
-#include <unwindstack/Error.h>
-#include <unwindstack/Regs.h>
-#include <unwindstack/RegsArm.h>
-#include <unwindstack/RegsArm64.h>
-#include <unwindstack/RegsGetLocal.h>
-#include <unwindstack/RegsX86.h>
-#include <unwindstack/RegsX86_64.h>
-#include <unwindstack/UcontextArm.h>
-#include <unwindstack/UcontextArm64.h>
-#include <unwindstack/UcontextX86.h>
-#include <unwindstack/UcontextX86_64.h>
-#include <unwindstack/Unwinder.h>
-
-#include "PidUtils.h"
-#include "TestUtils.h"
-
-namespace unwindstack {
-
-static std::string GetBacktrace(AndroidUnwinder& unwinder, std::vector<FrameData>& frames) {
-  std::string backtrace_str;
-  for (auto& frame : frames) {
-    backtrace_str += unwinder.FormatFrame(frame) + '\n';
-  }
-  return backtrace_str;
-}
-
-static pid_t ForkWaitForever() {
-  pid_t pid;
-  if ((pid = fork()) == 0) {
-    // Do a loop that guarantees the terminating leaf frame will be in
-    // the test executable and not any other library function.
-    bool run = true;
-    while (run) {
-      DoNotOptimize(run = true);
-    }
-    exit(1);
-  }
-  return pid;
-}
-
-TEST(AndroidUnwinderDataTest, demangle_function_names) {
-  AndroidUnwinderData data;
-
-  // Add a few frames with and without demangled function names.
-  data.frames.resize(4);
-  data.frames[0].function_name = "no_demangle()";
-  data.frames[1].function_name = "_Z4fakeb";
-  data.frames[3].function_name = "_Z8demanglei";
-
-  data.DemangleFunctionNames();
-  EXPECT_EQ("no_demangle()", data.frames[0].function_name);
-  EXPECT_EQ("fake(bool)", data.frames[1].function_name);
-  EXPECT_EQ("", data.frames[2].function_name);
-  EXPECT_EQ("demangle(int)", data.frames[3].function_name);
-
-  // Make sure that this action is idempotent.
-  data.DemangleFunctionNames();
-  EXPECT_EQ("no_demangle()", data.frames[0].function_name);
-  EXPECT_EQ("fake(bool)", data.frames[1].function_name);
-  EXPECT_EQ("", data.frames[2].function_name);
-  EXPECT_EQ("demangle(int)", data.frames[3].function_name);
-}
-
-TEST(AndroidUnwinderDataTest, get_error_string) {
-  AndroidUnwinderData data;
-
-  EXPECT_EQ("None", data.GetErrorString());
-  data.error.code = ERROR_INVALID_ELF;
-  EXPECT_EQ("Invalid Elf", data.GetErrorString());
-  data.error.code = ERROR_MEMORY_INVALID;
-  EXPECT_EQ("Memory Invalid", data.GetErrorString());
-  data.error.address = 0x1000;
-  EXPECT_EQ("Memory Invalid at address 0x1000", data.GetErrorString());
-}
-
-TEST(AndroidUnwinderTest, unwind_errors) {
-  AndroidLocalUnwinder unwinder;
-
-  AndroidUnwinderData data;
-  void* ucontext = nullptr;
-  EXPECT_FALSE(unwinder.Unwind(ucontext, data));
-  EXPECT_EQ(ERROR_INVALID_PARAMETER, data.error.code);
-  std::unique_ptr<Regs> regs;
-  EXPECT_FALSE(unwinder.Unwind(regs.get(), data));
-  EXPECT_EQ(ERROR_INVALID_PARAMETER, data.error.code);
-  // Make sure that we are using a different arch from the
-  // current arch.
-  if (Regs::CurrentArch() == ARCH_ARM) {
-    regs.reset(new RegsArm64);
-  } else {
-    regs.reset(new RegsArm);
-  }
-  EXPECT_FALSE(unwinder.Unwind(regs.get(), data));
-  EXPECT_EQ(ERROR_BAD_ARCH, data.error.code);
-}
-
-TEST(AndroidUnwinderTest, create) {
-  // Verify the local unwinder object is created.
-  std::unique_ptr<AndroidUnwinder> unwinder(AndroidUnwinder::Create(getpid()));
-  AndroidUnwinderData data;
-  ASSERT_TRUE(unwinder->Unwind(data));
-
-  pid_t pid = ForkWaitForever();
-  ASSERT_NE(-1, pid);
-  TestScopedPidReaper reap(pid);
-
-  ASSERT_TRUE(RunWhenQuiesced(pid, false, [pid, &unwinder]() {
-    // Verify the remote unwinder object is created.
-    unwinder.reset(AndroidUnwinder::Create(pid));
-    AndroidUnwinderData data;
-    if (!unwinder->Unwind(data)) {
-      printf("Failed to unwind %s\n", data.GetErrorString().c_str());
-      return PID_RUN_FAIL;
-    }
-    return PID_RUN_PASS;
-  }));
-}
-
-TEST(AndroidLocalUnwinderTest, initialize_before) {
-  AndroidLocalUnwinder unwinder;
-  ErrorData error;
-  ASSERT_TRUE(unwinder.Initialize(error));
-
-  AndroidUnwinderData data;
-  ASSERT_TRUE(unwinder.Unwind(data));
-}
-
-TEST(AndroidLocalUnwinderTest, suffix_ignore) {
-  AndroidLocalUnwinder unwinder(std::vector<std::string>{}, std::vector<std::string>{"so"});
-  AndroidUnwinderData data;
-  // This should work as long as the first frame is in the test executable.
-  ASSERT_TRUE(unwinder.Unwind(data));
-  // Make sure the unwind doesn't include any .so frames.
-  for (const auto& frame : data.frames) {
-    ASSERT_TRUE(frame.map_info == nullptr ||
-                !android::base::EndsWith(frame.map_info->name(), ".so"))
-        << GetBacktrace(unwinder, data.frames);
-  }
-}
-
-TEST(AndroidUnwinderTest, verify_all_unwind_functions) {
-  AndroidLocalUnwinder unwinder;
-  AndroidUnwinderData data;
-  ASSERT_TRUE(unwinder.Unwind(data));
-  ASSERT_TRUE(unwinder.Unwind(std::nullopt, data));
-  ASSERT_TRUE(unwinder.Unwind(getpid(), data));
-  std::unique_ptr<Regs> regs(Regs::CreateFromLocal());
-  RegsGetLocal(regs.get());
-
-  void* ucontext;
-  switch (regs->Arch()) {
-    case ARCH_ARM: {
-      arm_ucontext_t* arm_ucontext =
-          reinterpret_cast<arm_ucontext_t*>(malloc(sizeof(arm_ucontext_t)));
-      ucontext = arm_ucontext;
-      memcpy(&arm_ucontext->uc_mcontext.regs[0], regs->RawData(), ARM_REG_LAST * sizeof(uint32_t));
-    } break;
-    case ARCH_ARM64: {
-      arm64_ucontext_t* arm64_ucontext =
-          reinterpret_cast<arm64_ucontext_t*>(malloc(sizeof(arm64_ucontext_t)));
-      ucontext = arm64_ucontext;
-      memcpy(&arm64_ucontext->uc_mcontext.regs[0], regs->RawData(),
-             ARM64_REG_LAST * sizeof(uint64_t));
-    } break;
-    case ARCH_X86: {
-      x86_ucontext_t* x86_ucontext =
-          reinterpret_cast<x86_ucontext_t*>(malloc(sizeof(x86_ucontext_t)));
-      ucontext = x86_ucontext;
-      RegsX86* regs_x86 = static_cast<RegsX86*>(regs.get());
-
-      x86_ucontext->uc_mcontext.edi = (*regs_x86)[X86_REG_EDI];
-      x86_ucontext->uc_mcontext.esi = (*regs_x86)[X86_REG_ESI];
-      x86_ucontext->uc_mcontext.ebp = (*regs_x86)[X86_REG_EBP];
-      x86_ucontext->uc_mcontext.esp = (*regs_x86)[X86_REG_ESP];
-      x86_ucontext->uc_mcontext.ebx = (*regs_x86)[X86_REG_EBX];
-      x86_ucontext->uc_mcontext.edx = (*regs_x86)[X86_REG_EDX];
-      x86_ucontext->uc_mcontext.ecx = (*regs_x86)[X86_REG_ECX];
-      x86_ucontext->uc_mcontext.eax = (*regs_x86)[X86_REG_EAX];
-      x86_ucontext->uc_mcontext.eip = (*regs_x86)[X86_REG_EIP];
-    } break;
-    case ARCH_X86_64: {
-      x86_64_ucontext_t* x86_64_ucontext =
-          reinterpret_cast<x86_64_ucontext_t*>(malloc(sizeof(x86_64_ucontext_t)));
-      ucontext = x86_64_ucontext;
-      RegsX86_64* regs_x86_64 = static_cast<RegsX86_64*>(regs.get());
-
-      memcpy(&x86_64_ucontext->uc_mcontext.r8, &(*regs_x86_64)[X86_64_REG_R8],
-             8 * sizeof(uint64_t));
-
-      x86_64_ucontext->uc_mcontext.rdi = (*regs_x86_64)[X86_64_REG_RDI];
-      x86_64_ucontext->uc_mcontext.rsi = (*regs_x86_64)[X86_64_REG_RSI];
-      x86_64_ucontext->uc_mcontext.rbp = (*regs_x86_64)[X86_64_REG_RBP];
-      x86_64_ucontext->uc_mcontext.rbx = (*regs_x86_64)[X86_64_REG_RBX];
-      x86_64_ucontext->uc_mcontext.rdx = (*regs_x86_64)[X86_64_REG_RDX];
-      x86_64_ucontext->uc_mcontext.rax = (*regs_x86_64)[X86_64_REG_RAX];
-      x86_64_ucontext->uc_mcontext.rcx = (*regs_x86_64)[X86_64_REG_RCX];
-      x86_64_ucontext->uc_mcontext.rsp = (*regs_x86_64)[X86_64_REG_RSP];
-      x86_64_ucontext->uc_mcontext.rip = (*regs_x86_64)[X86_64_REG_RIP];
-    } break;
-    default:
-      ucontext = nullptr;
-      break;
-  }
-  ASSERT_TRUE(ucontext != nullptr);
-  ASSERT_TRUE(unwinder.Unwind(ucontext, data));
-  free(ucontext);
-  AndroidUnwinderData reg_data;
-  ASSERT_TRUE(unwinder.Unwind(regs.get(), reg_data));
-  ASSERT_EQ(data.frames.size(), reg_data.frames.size());
-  // Make sure all of the frame data is exactly the same.
-  for (size_t i = 0; i < data.frames.size(); i++) {
-    SCOPED_TRACE("\nMismatch at Frame " + std::to_string(i) + "\nucontext trace:\n" +
-                 GetBacktrace(unwinder, data.frames) + "\nregs trace:\n" +
-                 GetBacktrace(unwinder, reg_data.frames));
-    const auto& frame_context = data.frames[i];
-    const auto& frame_reg = reg_data.frames[i];
-    ASSERT_EQ(frame_context.num, frame_reg.num);
-    ASSERT_EQ(frame_context.rel_pc, frame_reg.rel_pc);
-    ASSERT_EQ(frame_context.pc, frame_reg.pc);
-    ASSERT_EQ(frame_context.sp, frame_reg.sp);
-    ASSERT_STREQ(frame_context.function_name.c_str(), frame_reg.function_name.c_str());
-    ASSERT_EQ(frame_context.function_offset, frame_reg.function_offset);
-    ASSERT_EQ(frame_context.map_info.get(), frame_reg.map_info.get());
-  }
-}
-
-TEST(AndroidLocalUnwinderTest, unwind_current_thread) {
-  AndroidLocalUnwinder unwinder;
-  AndroidUnwinderData data;
-  ASSERT_TRUE(unwinder.Unwind(data));
-  // Verify that the libunwindstack.so does not appear in the first frame.
-  ASSERT_TRUE(data.frames[0].map_info == nullptr ||
-              !android::base::EndsWith(data.frames[0].map_info->name(), "/libunwindstack.so"))
-      << "libunwindstack.so not removed properly\n"
-      << GetBacktrace(unwinder, data.frames);
-}
-
-TEST(AndroidLocalUnwinderTest, unwind_current_thread_show_all_frames) {
-  AndroidLocalUnwinder unwinder;
-  AndroidUnwinderData data(true);
-  ASSERT_TRUE(unwinder.Unwind(data));
-  // Verify that the libunwindstack.so does appear in the first frame.
-  ASSERT_TRUE(data.frames[0].map_info != nullptr &&
-              android::base::EndsWith(data.frames[0].map_info->name(), "/libunwindstack.so"))
-      << "libunwindstack.so was removed improperly\n"
-      << GetBacktrace(unwinder, data.frames);
-}
-
-TEST(AndroidLocalUnwinderTest, unwind_different_thread) {
-  std::atomic<pid_t> tid;
-  std::atomic_bool keep_running = true;
-  std::thread thread([&tid, &keep_running] {
-    tid = android::base::GetThreadId();
-    while (keep_running) {
-    }
-    return nullptr;
-  });
-
-  while (tid == 0) {
-  }
-
-  {
-    AndroidLocalUnwinder unwinder;
-    AndroidUnwinderData data;
-    ASSERT_TRUE(unwinder.Unwind(data));
-    // Verify that the libunwindstack.so does not appear in the first frame.
-    ASSERT_TRUE(data.frames[0].map_info == nullptr ||
-                !android::base::EndsWith(data.frames[0].map_info->name(), "/libunwindstack.so"))
-        << "libunwindstack.so not removed properly\n"
-        << GetBacktrace(unwinder, data.frames);
-  }
-
-  {
-    AndroidLocalUnwinder unwinder;
-    AndroidUnwinderData data(true);
-    ASSERT_TRUE(unwinder.Unwind(data));
-    // Verify that the libunwindstack.so does appear in the first frame.
-    ASSERT_TRUE(data.frames[0].map_info != nullptr &&
-                android::base::EndsWith(data.frames[0].map_info->name(), "/libunwindstack.so"))
-        << "libunwindstack.so was removed improperly\n"
-        << GetBacktrace(unwinder, data.frames);
-  }
-
-  // Allow the thread to terminate normally.
-  keep_running = false;
-  thread.join();
-}
-
-TEST(AndroidRemoteUnwinderTest, initialize_before) {
-  pid_t pid = ForkWaitForever();
-  ASSERT_NE(-1, pid);
-  TestScopedPidReaper reap(pid);
-
-  ASSERT_TRUE(Attach(pid));
-
-  AndroidRemoteUnwinder unwinder(pid);
-  ErrorData error;
-  ASSERT_TRUE(unwinder.Initialize(error));
-
-  AndroidUnwinderData data;
-  ASSERT_TRUE(unwinder.Unwind(data));
-
-  ASSERT_TRUE(Detach(pid));
-}
-
-static bool Verify(pid_t pid, std::function<PidRunEnum(const FrameData& frame)> fn) {
-  return RunWhenQuiesced(pid, false, [pid, &fn]() {
-    AndroidRemoteUnwinder unwinder(pid);
-    AndroidUnwinderData data;
-    if (!unwinder.Unwind(data)) {
-      printf("Failed to unwind %s\n", data.GetErrorString().c_str());
-      return PID_RUN_FAIL;
-    }
-    const auto& frame = data.frames[0];
-    return fn(frame);
-  });
-}
-
-TEST(AndroidRemoteUnwinderTest, skip_libraries) {
-  void* test_lib = GetTestLibHandle();
-  ASSERT_TRUE(test_lib != nullptr);
-  int (*wait_func)() = reinterpret_cast<int (*)()>(dlsym(test_lib, "WaitForever"));
-  ASSERT_TRUE(wait_func != nullptr);
-
-  pid_t pid;
-  if ((pid = fork()) == 0) {
-    DoNotOptimize(wait_func());
-    exit(0);
-  }
-  ASSERT_NE(-1, pid);
-  TestScopedPidReaper reap(pid);
-
-  ASSERT_TRUE(Verify(pid, [pid](const FrameData& frame) {
-    // Make sure that the frame is in the dlopen'd library before proceeding.
-    if (frame.map_info == nullptr ||
-        !android::base::EndsWith(frame.map_info->name(), "/libunwindstack_local.so")) {
-      return PID_RUN_KEEP_GOING;
-    }
-
-    // Do an unwind removing the libunwindstack_local.so library.
-    AndroidRemoteUnwinder unwinder(pid, std::vector<std::string>{"libunwindstack_local.so"});
-    AndroidUnwinderData data;
-    if (!unwinder.Unwind(data)) {
-      printf("Failed to unwind %s\n", data.GetErrorString().c_str());
-      return PID_RUN_FAIL;
-    }
-
-    // Verify that library is properly ignored.
-    if (android::base::EndsWith(data.frames[0].map_info->name(), "/libunwindstack_local.so")) {
-      printf("Failed to strip libunwindstack_local.so\n%s\n",
-             GetBacktrace(unwinder, data.frames).c_str());
-      return PID_RUN_FAIL;
-    }
-    return PID_RUN_PASS;
-  }));
-}
-
-TEST(AndroidRemoteUnwinderTest, suffix_ignore) {
-  pid_t pid = ForkWaitForever();
-  ASSERT_NE(-1, pid);
-  TestScopedPidReaper reap(pid);
-
-  ASSERT_TRUE(Verify(pid, [pid](const FrameData& frame) {
-    // Wait until the forked process is no longer in libc.so.
-    if (frame.map_info != nullptr && android::base::EndsWith(frame.map_info->name(), ".so")) {
-      return PID_RUN_KEEP_GOING;
-    }
-
-    AndroidRemoteUnwinder unwinder(pid, std::vector<std::string>{}, std::vector<std::string>{"so"});
-    AndroidUnwinderData data;
-    if (!unwinder.Unwind(data)) {
-      printf("Failed to unwind %s\n", data.GetErrorString().c_str());
-
-      AndroidRemoteUnwinder normal_unwinder(pid);
-      if (normal_unwinder.Unwind(data)) {
-        printf("Full unwind %s\n", GetBacktrace(normal_unwinder, data.frames).c_str());
-      }
-      return PID_RUN_FAIL;
-    }
-
-    // Make sure the unwind doesn't include any .so frames.
-    for (const auto& frame : data.frames) {
-      if (frame.map_info != nullptr && android::base::EndsWith(frame.map_info->name(), ".so")) {
-        printf("Found unexpected .so frame\n%s\n", GetBacktrace(unwinder, data.frames).c_str());
-        return PID_RUN_FAIL;
-      }
-    }
-    return PID_RUN_PASS;
-  }));
-}
-
-}  // namespace unwindstack
diff --git a/libunwindstack/tests/ArmExidxDecodeTest.cpp b/libunwindstack/tests/ArmExidxDecodeTest.cpp
index ea0dc0e..69a7816 100644
--- a/libunwindstack/tests/ArmExidxDecodeTest.cpp
+++ b/libunwindstack/tests/ArmExidxDecodeTest.cpp
@@ -29,7 +29,7 @@
 #include "ArmExidx.h"
 
 #include "LogFake.h"
-#include "utils/MemoryFake.h"
+#include "MemoryFake.h"
 
 namespace unwindstack {
 
diff --git a/libunwindstack/tests/ArmExidxExtractTest.cpp b/libunwindstack/tests/ArmExidxExtractTest.cpp
index cfd5b7e..79c799c 100644
--- a/libunwindstack/tests/ArmExidxExtractTest.cpp
+++ b/libunwindstack/tests/ArmExidxExtractTest.cpp
@@ -26,7 +26,7 @@
 #include "ArmExidx.h"
 
 #include "LogFake.h"
-#include "utils/MemoryFake.h"
+#include "MemoryFake.h"
 
 namespace unwindstack {
 
diff --git a/libunwindstack/tests/DexFileData.h b/libunwindstack/tests/DexFileData.h
index d4408d9..6975c68 100644
--- a/libunwindstack/tests/DexFileData.h
+++ b/libunwindstack/tests/DexFileData.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_DEXFILESDATA_H
+#define _LIBUNWINDSTACK_DEXFILESDATA_H
 
 namespace unwindstack {
 
@@ -40,3 +41,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_DEXFILESDATA_H
diff --git a/libunwindstack/tests/DexFileTest.cpp b/libunwindstack/tests/DexFileTest.cpp
index 96d99e3..05b368b 100644
--- a/libunwindstack/tests/DexFileTest.cpp
+++ b/libunwindstack/tests/DexFileTest.cpp
@@ -19,7 +19,6 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <memory>
 #include <unordered_map>
 
 #include <MemoryLocal.h>
@@ -30,12 +29,12 @@
 
 #include "DexFile.h"
 #include "DexFileData.h"
-#include "utils/MemoryFake.h"
+#include "MemoryFake.h"
 
 namespace unwindstack {
 
 static constexpr size_t kNumLeakLoops = 5000;
-static constexpr size_t kMaxAllowedLeakBytes = 4 * 1024;
+static constexpr size_t kMaxAllowedLeakBytes = 1024;
 
 static void CheckForLeak(size_t loop, size_t* first_allocated_bytes, size_t* last_allocated_bytes) {
   size_t allocated_bytes = mallinfo().uordblks;
@@ -61,8 +60,8 @@
   size_t last_allocated_bytes = 0;
   for (size_t i = 0; i < kNumLeakLoops; i++) {
     MemoryFake memory;
-    auto info = MapInfo::Create(0, 0x10000, 0, 0x5, tf.path);
-    EXPECT_TRUE(DexFile::Create(0, sizeof(kDexData), &memory, info.get()) != nullptr);
+    MapInfo info(nullptr, nullptr, 0, 0x10000, 0, 0x5, tf.path);
+    EXPECT_TRUE(DexFile::Create(0, sizeof(kDexData), &memory, &info) != nullptr);
     ASSERT_NO_FATAL_FAILURE(CheckForLeak(i, &first_allocated_bytes, &last_allocated_bytes));
   }
 }
@@ -89,8 +88,8 @@
             static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
 
   MemoryFake memory;
-  auto info = MapInfo::Create(0, 0x10000, 0, 0x5, tf.path);
-  EXPECT_TRUE(DexFile::Create(0x500, sizeof(kDexData), &memory, info.get()) != nullptr);
+  MapInfo info(nullptr, nullptr, 0, 0x10000, 0, 0x5, tf.path);
+  EXPECT_TRUE(DexFile::Create(0x500, sizeof(kDexData), &memory, &info) != nullptr);
 }
 
 TEST(DexFileTest, create_using_file_non_zero_start) {
@@ -102,8 +101,8 @@
             static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
 
   MemoryFake memory;
-  auto info = MapInfo::Create(0x100, 0x10000, 0, 0x5, tf.path);
-  EXPECT_TRUE(DexFile::Create(0x600, sizeof(kDexData), &memory, info.get()) != nullptr);
+  MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0, 0x5, tf.path);
+  EXPECT_TRUE(DexFile::Create(0x600, sizeof(kDexData), &memory, &info) != nullptr);
 }
 
 TEST(DexFileTest, create_using_file_non_zero_offset) {
@@ -115,22 +114,22 @@
             static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
 
   MemoryFake memory;
-  auto info = MapInfo::Create(0x100, 0x10000, 0x200, 0x5, tf.path);
-  EXPECT_TRUE(DexFile::Create(0x400, sizeof(kDexData), &memory, info.get()) != nullptr);
+  MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, tf.path);
+  EXPECT_TRUE(DexFile::Create(0x400, sizeof(kDexData), &memory, &info) != nullptr);
 }
 
 TEST(DexFileTest, create_using_memory_empty_file) {
   MemoryFake memory;
   memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
-  auto info = MapInfo::Create(0x100, 0x10000, 0x200, 0x5, "");
-  EXPECT_TRUE(DexFile::Create(0x4000, sizeof(kDexData), &memory, info.get()) != nullptr);
+  MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, "");
+  EXPECT_TRUE(DexFile::Create(0x4000, sizeof(kDexData), &memory, &info) != nullptr);
 }
 
 TEST(DexFileTest, create_using_memory_file_does_not_exist) {
   MemoryFake memory;
   memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
-  auto info = MapInfo::Create(0x100, 0x10000, 0x200, 0x5, "/does/not/exist");
-  EXPECT_TRUE(DexFile::Create(0x4000, sizeof(kDexData), &memory, info.get()) != nullptr);
+  MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, "/does/not/exist");
+  EXPECT_TRUE(DexFile::Create(0x4000, sizeof(kDexData), &memory, &info) != nullptr);
 }
 
 TEST(DexFileTest, create_using_memory_file_is_malformed) {
@@ -142,14 +141,13 @@
 
   MemoryFake memory;
   memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
-  auto info = MapInfo::Create(0x4000, 0x10000, 0x200, 0x5, "/does/not/exist");
-  std::shared_ptr<DexFile> dex_file =
-      DexFile::Create(0x4000, sizeof(kDexData), &memory, info.get());
+  MapInfo info(nullptr, nullptr, 0x4000, 0x10000, 0x200, 0x5, "/does/not/exist");
+  std::shared_ptr<DexFile> dex_file = DexFile::Create(0x4000, sizeof(kDexData), &memory, &info);
   ASSERT_TRUE(dex_file != nullptr);
 
   // Check it came from memory by clearing memory and verifying it fails.
   memory.Clear();
-  dex_file = DexFile::Create(0x4000, sizeof(kDexData), &memory, info.get());
+  dex_file = DexFile::Create(0x4000, sizeof(kDexData), &memory, &info);
   EXPECT_TRUE(dex_file == nullptr);
 }
 
@@ -170,8 +168,8 @@
 TEST(DexFileTest, get_method) {
   MemoryFake memory;
   memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
-  auto info = MapInfo::Create(0x100, 0x10000, 0x200, 0x5, "");
-  std::shared_ptr<DexFile> dex_file(DexFile::Create(0x4000, sizeof(kDexData), &memory, info.get()));
+  MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, "");
+  std::shared_ptr<DexFile> dex_file(DexFile::Create(0x4000, sizeof(kDexData), &memory, &info));
   ASSERT_TRUE(dex_file != nullptr);
 
   SharedString method;
@@ -188,8 +186,8 @@
 TEST(DexFileTest, get_method_empty) {
   MemoryFake memory;
   memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
-  auto info = MapInfo::Create(0x100, 0x10000, 0x200, 0x5, "");
-  std::shared_ptr<DexFile> dex_file(DexFile::Create(0x4000, sizeof(kDexData), &memory, info.get()));
+  MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, "");
+  std::shared_ptr<DexFile> dex_file(DexFile::Create(0x4000, sizeof(kDexData), &memory, &info));
   ASSERT_TRUE(dex_file != nullptr);
 
   SharedString method;
@@ -207,9 +205,8 @@
             static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
 
   MemoryFake memory;
-  auto info = MapInfo::Create(0x4000, 0x10000, 0, 0x5, tf.path);
-  std::shared_ptr<DexFile> dex_file =
-      DexFile::Create(0x4000, sizeof(kDexData), &memory, info.get());
+  MapInfo info(nullptr, nullptr, 0x4000, 0x10000, 0, 0x5, tf.path);
+  std::shared_ptr<DexFile> dex_file = DexFile::Create(0x4000, sizeof(kDexData), &memory, &info);
   EXPECT_TRUE(dex_file != nullptr);
 
   SharedString method;
diff --git a/libunwindstack/tests/DexFilesTest.cpp b/libunwindstack/tests/DexFilesTest.cpp
index 9250d6d..c18a437 100644
--- a/libunwindstack/tests/DexFilesTest.cpp
+++ b/libunwindstack/tests/DexFilesTest.cpp
@@ -31,7 +31,7 @@
 #include "DexFile.h"
 #include "DexFileData.h"
 #include "ElfFake.h"
-#include "utils/MemoryFake.h"
+#include "MemoryFake.h"
 
 namespace unwindstack {
 
@@ -72,22 +72,22 @@
     ASSERT_TRUE(maps_->Parse());
 
     // Global variable in a section that is not readable.
-    MapInfo* map_info = maps_->Get(kMapGlobalNonReadable).get();
+    MapInfo* map_info = maps_->Get(kMapGlobalNonReadable);
     ASSERT_TRUE(map_info != nullptr);
     CreateFakeElf(map_info, 0x2800, 0x2000, 0x2000, 0x3000);
 
     // Global variable not set by default.
-    map_info = maps_->Get(kMapGlobalSetToZero).get();
+    map_info = maps_->Get(kMapGlobalSetToZero);
     ASSERT_TRUE(map_info != nullptr);
     CreateFakeElf(map_info, 0x2800, 0x2000, 0x2000, 0x3000);
 
     // Global variable set in this map.
-    map_info = maps_->Get(kMapGlobal).get();
+    map_info = maps_->Get(kMapGlobal);
     ASSERT_TRUE(map_info != nullptr);
     CreateFakeElf(map_info, 0xf1800, 0xf1000, 0xf1000, 0x10000);
 
     // Global variable set in this map, but there is an empty map before rw map.
-    map_info = maps_->Get(kMapGlobalAfterEmpty).get();
+    map_info = maps_->Get(kMapGlobalAfterEmpty);
     ASSERT_TRUE(map_info != nullptr);
     CreateFakeElf(map_info, 0x3800, 0x3000, 0x3000, 0xd000);
   }
@@ -278,7 +278,7 @@
   EXPECT_EQ("nothing", method_name);
   EXPECT_EQ(0x124U, method_offset);
 
-  auto map_info = maps_->Get(kMapGlobal);
+  MapInfo* map_info = maps_->Get(kMapGlobal);
   map_info->set_name("/system/lib/libart.so");
   dex_files_ = CreateDexFiles(ARCH_ARM, process_memory_, libs);
   // Set the rw map to the same name or this will not scan this entry.
diff --git a/libunwindstack/tests/DwarfCfaLogTest.cpp b/libunwindstack/tests/DwarfCfaLogTest.cpp
index 876f951..7cb51ef 100644
--- a/libunwindstack/tests/DwarfCfaLogTest.cpp
+++ b/libunwindstack/tests/DwarfCfaLogTest.cpp
@@ -32,7 +32,7 @@
 #include "DwarfCfa.h"
 
 #include "LogFake.h"
-#include "utils/MemoryFake.h"
+#include "MemoryFake.h"
 
 namespace unwindstack {
 
diff --git a/libunwindstack/tests/DwarfCfaTest.cpp b/libunwindstack/tests/DwarfCfaTest.cpp
index 45728fb..5ed428d 100644
--- a/libunwindstack/tests/DwarfCfaTest.cpp
+++ b/libunwindstack/tests/DwarfCfaTest.cpp
@@ -32,7 +32,7 @@
 #include "DwarfCfa.h"
 
 #include "LogFake.h"
-#include "utils/MemoryFake.h"
+#include "MemoryFake.h"
 
 namespace unwindstack {
 
@@ -204,7 +204,7 @@
   ASSERT_EQ(0x2001U, this->dmem_->cur_offset());
   ASSERT_EQ(0U, loc_regs.size());
 
-  ASSERT_EQ("6 unwind Invalid: restore while processing cie.\n", GetFakeLogPrint());
+  ASSERT_EQ("4 unwind restore while processing cie\n", GetFakeLogPrint());
   ASSERT_EQ("", GetFakeLogBuf());
 
   ResetLogs();
@@ -233,7 +233,7 @@
   ASSERT_EQ(0x4002U, this->dmem_->cur_offset());
   ASSERT_EQ(0U, loc_regs.size());
 
-  ASSERT_EQ("6 unwind Invalid: restore while processing cie.\n", GetFakeLogPrint());
+  ASSERT_EQ("4 unwind restore while processing cie\n", GetFakeLogPrint());
   ASSERT_EQ("", GetFakeLogBuf());
 
   ResetLogs();
@@ -598,7 +598,7 @@
   ASSERT_EQ(0U, loc_regs.size());
   ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode());
 
-  ASSERT_EQ("6 unwind Attempt to set new register, but cfa is not already set to a register.\n",
+  ASSERT_EQ("4 unwind Attempt to set new register, but cfa is not already set to a register.\n",
             GetFakeLogPrint());
   ASSERT_EQ("", GetFakeLogBuf());
 
@@ -641,7 +641,7 @@
   ASSERT_EQ(0U, loc_regs.size());
   ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode());
 
-  ASSERT_EQ("6 unwind Attempt to set offset, but cfa is not set to a register.\n",
+  ASSERT_EQ("4 unwind Attempt to set offset, but cfa is not set to a register.\n",
             GetFakeLogPrint());
   ASSERT_EQ("", GetFakeLogBuf());
 
@@ -683,7 +683,7 @@
   ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs));
   ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode());
 
-  ASSERT_EQ("6 unwind Attempt to set offset, but cfa is not set to a register.\n",
+  ASSERT_EQ("4 unwind Attempt to set offset, but cfa is not set to a register.\n",
             GetFakeLogPrint());
   ASSERT_EQ("", GetFakeLogBuf());
 
diff --git a/libunwindstack/tests/DwarfDebugFrameTest.cpp b/libunwindstack/tests/DwarfDebugFrameTest.cpp
index 47a00b4..235151b 100644
--- a/libunwindstack/tests/DwarfDebugFrameTest.cpp
+++ b/libunwindstack/tests/DwarfDebugFrameTest.cpp
@@ -26,7 +26,7 @@
 #include "DwarfEncoding.h"
 
 #include "LogFake.h"
-#include "utils/MemoryFake.h"
+#include "MemoryFake.h"
 
 namespace unwindstack {
 
@@ -195,25 +195,6 @@
   ASSERT_EQ(3U, fdes.size());
 }
 
-TYPED_TEST_P(DwarfDebugFrameTest, GetFdes32_big_function_address) {
-  SetCie32(&this->memory_, 0x5000, 0xfc, std::vector<uint8_t>{1, '\0', 0, 0, 1});
-  SetFde32(&this->memory_, 0x5100, 0xfc, 0, 0xe9ad9b1f, 0x200);
-  ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x200, 0));
-
-  std::vector<const DwarfFde*> fdes;
-  this->debug_frame_->GetFdes(&fdes);
-
-  ASSERT_EQ(1U, fdes.size());
-
-  EXPECT_EQ(0x5000U, fdes[0]->cie_offset);
-  EXPECT_EQ(0x5110U, fdes[0]->cfa_instructions_offset);
-  EXPECT_EQ(0x5200U, fdes[0]->cfa_instructions_end);
-  EXPECT_EQ(0xe9ad9b1fU, fdes[0]->pc_start);
-  EXPECT_EQ(0xe9ad9d1fU, fdes[0]->pc_end);
-  EXPECT_EQ(0U, fdes[0]->lsda_address);
-  EXPECT_TRUE(fdes[0]->cie != nullptr);
-}
-
 TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromPc32) {
   SetFourFdes32(&this->memory_);
   ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0));
@@ -433,7 +414,7 @@
 
   ASSERT_TRUE(fde->cie != nullptr);
   EXPECT_EQ(1U, fde->cie->version);
-  EXPECT_EQ(DW_EH_PE_udata4, fde->cie->fde_address_encoding);
+  EXPECT_EQ(DW_EH_PE_sdata4, fde->cie->fde_address_encoding);
   EXPECT_EQ(DW_EH_PE_omit, fde->cie->lsda_encoding);
   EXPECT_EQ(0U, fde->cie->segment_size);
   EXPECT_EQ(1U, fde->cie->augmentation_string.size());
@@ -461,7 +442,7 @@
 
   ASSERT_TRUE(fde->cie != nullptr);
   EXPECT_EQ(1U, fde->cie->version);
-  EXPECT_EQ(DW_EH_PE_udata8, fde->cie->fde_address_encoding);
+  EXPECT_EQ(DW_EH_PE_sdata8, fde->cie->fde_address_encoding);
   EXPECT_EQ(DW_EH_PE_omit, fde->cie->lsda_encoding);
   EXPECT_EQ(0U, fde->cie->segment_size);
   EXPECT_EQ(1U, fde->cie->augmentation_string.size());
@@ -496,14 +477,14 @@
   const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
   EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
   ASSERT_TRUE(cie != nullptr);
-  VerifyCieVersion(cie, 1, 0, DW_EH_PE_udata4, 0x20, 0xd, 0x104);
+  VerifyCieVersion(cie, 1, 0, DW_EH_PE_sdata4, 0x20, 0xd, 0x104);
 
   std::vector<uint8_t> zero(0x100, 0);
   this->memory_.SetMemory(0x5000, zero);
   cie = this->debug_frame_->GetCieFromOffset(0x5000);
   EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
   ASSERT_TRUE(cie != nullptr);
-  VerifyCieVersion(cie, 1, 0, DW_EH_PE_udata4, 0x20, 0xd, 0x104);
+  VerifyCieVersion(cie, 1, 0, DW_EH_PE_sdata4, 0x20, 0xd, 0x104);
 }
 
 TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset64_cie_cached) {
@@ -511,14 +492,14 @@
   const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
   EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
   ASSERT_TRUE(cie != nullptr);
-  VerifyCieVersion(cie, 1, 0, DW_EH_PE_udata8, 0x20, 0x19, 0x10c);
+  VerifyCieVersion(cie, 1, 0, DW_EH_PE_sdata8, 0x20, 0x19, 0x10c);
 
   std::vector<uint8_t> zero(0x100, 0);
   this->memory_.SetMemory(0x5000, zero);
   cie = this->debug_frame_->GetCieFromOffset(0x5000);
   EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
   ASSERT_TRUE(cie != nullptr);
-  VerifyCieVersion(cie, 1, 0, DW_EH_PE_udata8, 0x20, 0x19, 0x10c);
+  VerifyCieVersion(cie, 1, 0, DW_EH_PE_sdata8, 0x20, 0x19, 0x10c);
 }
 
 TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset32_version1) {
@@ -526,7 +507,7 @@
   const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
   EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
   ASSERT_TRUE(cie != nullptr);
-  VerifyCieVersion(cie, 1, 0, DW_EH_PE_udata4, 0x20, 0xd, 0x104);
+  VerifyCieVersion(cie, 1, 0, DW_EH_PE_sdata4, 0x20, 0xd, 0x104);
 }
 
 TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset64_version1) {
@@ -534,7 +515,7 @@
   const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
   EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
   ASSERT_TRUE(cie != nullptr);
-  VerifyCieVersion(cie, 1, 0, DW_EH_PE_udata8, 0x20, 0x19, 0x10c);
+  VerifyCieVersion(cie, 1, 0, DW_EH_PE_sdata8, 0x20, 0x19, 0x10c);
 }
 
 TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset32_version3) {
@@ -542,7 +523,7 @@
   const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
   EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
   ASSERT_TRUE(cie != nullptr);
-  VerifyCieVersion(cie, 3, 0, DW_EH_PE_udata4, 0x181, 0xe, 0x104);
+  VerifyCieVersion(cie, 3, 0, DW_EH_PE_sdata4, 0x181, 0xe, 0x104);
 }
 
 TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset64_version3) {
@@ -550,55 +531,39 @@
   const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
   EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
   ASSERT_TRUE(cie != nullptr);
-  VerifyCieVersion(cie, 3, 0, DW_EH_PE_udata8, 0x181, 0x1a, 0x10c);
+  VerifyCieVersion(cie, 3, 0, DW_EH_PE_sdata8, 0x181, 0x1a, 0x10c);
 }
 
-TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset32_version4_32bit_address) {
-  SetCie32(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{4, '\0', 4, 10, 4, 8, 0x81, 3});
+TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset32_version4) {
+  SetCie32(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{4, '\0', 0, 10, 4, 8, 0x81, 3});
   const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
   EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
   ASSERT_TRUE(cie != nullptr);
-  VerifyCieVersion(cie, 4, 10, DW_EH_PE_udata4, 0x181, 0x10, 0x104);
+  VerifyCieVersion(cie, 4, 10, DW_EH_PE_sdata4, 0x181, 0x10, 0x104);
 }
 
-TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset32_version4_64bit_address) {
-  SetCie32(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{4, '\0', 8, 10, 4, 8, 0x81, 3});
+TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset64_version4) {
+  SetCie64(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{4, '\0', 0, 10, 4, 8, 0x81, 3});
   const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
   EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
   ASSERT_TRUE(cie != nullptr);
-  VerifyCieVersion(cie, 4, 10, DW_EH_PE_udata8, 0x181, 0x10, 0x104);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset64_version4_32bit_address) {
-  SetCie64(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{4, '\0', 4, 10, 4, 8, 0x81, 3});
-  const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
-  EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
-  ASSERT_TRUE(cie != nullptr);
-  VerifyCieVersion(cie, 4, 10, DW_EH_PE_udata4, 0x181, 0x1c, 0x10c);
-}
-
-TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset64_version4_64bit_address) {
-  SetCie64(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{4, '\0', 8, 10, 4, 8, 0x81, 3});
-  const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
-  EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
-  ASSERT_TRUE(cie != nullptr);
-  VerifyCieVersion(cie, 4, 10, DW_EH_PE_udata8, 0x181, 0x1c, 0x10c);
+  VerifyCieVersion(cie, 4, 10, DW_EH_PE_sdata8, 0x181, 0x1c, 0x10c);
 }
 
 TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset32_version5) {
-  SetCie32(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{5, '\0', 4, 10, 4, 8, 0x81, 3});
+  SetCie32(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{5, '\0', 0, 10, 4, 8, 0x81, 3});
   const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
   EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
   ASSERT_TRUE(cie != nullptr);
-  VerifyCieVersion(cie, 5, 10, DW_EH_PE_udata4, 0x181, 0x10, 0x104);
+  VerifyCieVersion(cie, 5, 10, DW_EH_PE_sdata4, 0x181, 0x10, 0x104);
 }
 
 TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset64_version5) {
-  SetCie64(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{5, '\0', 8, 10, 4, 8, 0x81, 3});
+  SetCie64(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{5, '\0', 0, 10, 4, 8, 0x81, 3});
   const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
   EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
   ASSERT_TRUE(cie != nullptr);
-  VerifyCieVersion(cie, 5, 10, DW_EH_PE_udata8, 0x181, 0x1c, 0x10c);
+  VerifyCieVersion(cie, 5, 10, DW_EH_PE_sdata8, 0x181, 0x1c, 0x10c);
 }
 
 TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset_version_invalid) {
@@ -674,7 +639,7 @@
   SetCie32(&this->memory_, 0x5000, 0xfc,
            std::vector<uint8_t>{/* version */ 4,
                                 /* augment string */ 'z', '\0',
-                                /* address size */ 4,
+                                /* address size */ 8,
                                 /* segment size */ 0x10,
                                 /* code alignment factor */ 16,
                                 /* data alignment factor */ 32,
@@ -907,18 +872,15 @@
 
 REGISTER_TYPED_TEST_SUITE_P(
     DwarfDebugFrameTest, GetFdes32, GetFdes32_after_GetFdeFromPc, GetFdes32_not_in_section,
-    GetFdes32_big_function_address, GetFdeFromPc32, GetFdeFromPc32_reverse,
-    GetFdeFromPc32_not_in_section, GetFdes64, GetFdes64_after_GetFdeFromPc,
-    GetFdes64_not_in_section, GetFdeFromPc64, GetFdeFromPc64_reverse, GetFdeFromPc64_not_in_section,
-    GetCieFde32, GetCieFde64, GetCieFromOffset32_cie_cached, GetCieFromOffset64_cie_cached,
-    GetCieFromOffset32_version1, GetCieFromOffset64_version1, GetCieFromOffset32_version3,
-    GetCieFromOffset64_version3, GetCieFromOffset32_version4_32bit_address,
-    GetCieFromOffset32_version4_64bit_address, GetCieFromOffset64_version4_32bit_address,
-    GetCieFromOffset64_version4_64bit_address, GetCieFromOffset32_version5,
-    GetCieFromOffset64_version5, GetCieFromOffset_version_invalid, GetCieFromOffset32_augment,
-    GetCieFromOffset64_augment, GetFdeFromOffset32_augment, GetFdeFromOffset64_augment,
-    GetFdeFromOffset32_lsda_address, GetFdeFromOffset64_lsda_address, GetFdeFromPc_interleaved,
-    GetFdeFromPc_overlap);
+    GetFdeFromPc32, GetFdeFromPc32_reverse, GetFdeFromPc32_not_in_section, GetFdes64,
+    GetFdes64_after_GetFdeFromPc, GetFdes64_not_in_section, GetFdeFromPc64, GetFdeFromPc64_reverse,
+    GetFdeFromPc64_not_in_section, GetCieFde32, GetCieFde64, GetCieFromOffset32_cie_cached,
+    GetCieFromOffset64_cie_cached, GetCieFromOffset32_version1, GetCieFromOffset64_version1,
+    GetCieFromOffset32_version3, GetCieFromOffset64_version3, GetCieFromOffset32_version4,
+    GetCieFromOffset64_version4, GetCieFromOffset32_version5, GetCieFromOffset64_version5,
+    GetCieFromOffset_version_invalid, GetCieFromOffset32_augment, GetCieFromOffset64_augment,
+    GetFdeFromOffset32_augment, GetFdeFromOffset64_augment, GetFdeFromOffset32_lsda_address,
+    GetFdeFromOffset64_lsda_address, GetFdeFromPc_interleaved, GetFdeFromPc_overlap);
 
 typedef ::testing::Types<uint32_t, uint64_t> DwarfDebugFrameTestTypes;
 INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfDebugFrameTest, DwarfDebugFrameTestTypes);
diff --git a/libunwindstack/tests/DwarfEhFrameTest.cpp b/libunwindstack/tests/DwarfEhFrameTest.cpp
index ea2e397..46a25a4 100644
--- a/libunwindstack/tests/DwarfEhFrameTest.cpp
+++ b/libunwindstack/tests/DwarfEhFrameTest.cpp
@@ -24,7 +24,7 @@
 #include "DwarfEncoding.h"
 
 #include "LogFake.h"
-#include "utils/MemoryFake.h"
+#include "MemoryFake.h"
 
 namespace unwindstack {
 
@@ -74,7 +74,7 @@
   const DwarfCie* cie = fde->cie;
   ASSERT_TRUE(cie != nullptr);
   EXPECT_EQ(1U, cie->version);
-  EXPECT_EQ(DW_EH_PE_udata4, cie->fde_address_encoding);
+  EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
   EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
   EXPECT_EQ(0U, cie->segment_size);
   EXPECT_EQ('\0', cie->augmentation_string[0]);
@@ -113,7 +113,7 @@
   const DwarfCie* cie = fde->cie;
   ASSERT_TRUE(cie != nullptr);
   EXPECT_EQ(1U, cie->version);
-  EXPECT_EQ(DW_EH_PE_udata8, cie->fde_address_encoding);
+  EXPECT_EQ(DW_EH_PE_sdata8, cie->fde_address_encoding);
   EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
   EXPECT_EQ(0U, cie->segment_size);
   EXPECT_EQ('\0', cie->augmentation_string[0]);
diff --git a/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp b/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp
index 87b477a..6aa3867 100644
--- a/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp
+++ b/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp
@@ -25,7 +25,7 @@
 #include "DwarfEncoding.h"
 
 #include "LogFake.h"
-#include "utils/MemoryFake.h"
+#include "MemoryFake.h"
 
 namespace unwindstack {
 
@@ -479,7 +479,7 @@
 
   ASSERT_TRUE(fde->cie != nullptr);
   EXPECT_EQ(1U, fde->cie->version);
-  EXPECT_EQ(DW_EH_PE_udata4, fde->cie->fde_address_encoding);
+  EXPECT_EQ(DW_EH_PE_sdata4, fde->cie->fde_address_encoding);
   EXPECT_EQ(DW_EH_PE_omit, fde->cie->lsda_encoding);
   EXPECT_EQ(0U, fde->cie->segment_size);
   EXPECT_EQ(1U, fde->cie->augmentation_string.size());
@@ -517,7 +517,7 @@
 
   ASSERT_TRUE(fde->cie != nullptr);
   EXPECT_EQ(1U, fde->cie->version);
-  EXPECT_EQ(DW_EH_PE_udata8, fde->cie->fde_address_encoding);
+  EXPECT_EQ(DW_EH_PE_sdata8, fde->cie->fde_address_encoding);
   EXPECT_EQ(DW_EH_PE_omit, fde->cie->lsda_encoding);
   EXPECT_EQ(0U, fde->cie->segment_size);
   EXPECT_EQ(1U, fde->cie->augmentation_string.size());
diff --git a/libunwindstack/tests/DwarfMemoryTest.cpp b/libunwindstack/tests/DwarfMemoryTest.cpp
index b3d04c4..650e965 100644
--- a/libunwindstack/tests/DwarfMemoryTest.cpp
+++ b/libunwindstack/tests/DwarfMemoryTest.cpp
@@ -23,7 +23,7 @@
 
 #include <unwindstack/DwarfMemory.h>
 
-#include "utils/MemoryFake.h"
+#include "MemoryFake.h"
 
 namespace unwindstack {
 
diff --git a/libunwindstack/tests/DwarfOpLogTest.cpp b/libunwindstack/tests/DwarfOpLogTest.cpp
index f4dbf8d..8dbf6e8 100644
--- a/libunwindstack/tests/DwarfOpLogTest.cpp
+++ b/libunwindstack/tests/DwarfOpLogTest.cpp
@@ -28,7 +28,7 @@
 
 #include "DwarfOp.h"
 
-#include "utils/MemoryFake.h"
+#include "MemoryFake.h"
 
 namespace unwindstack {
 
diff --git a/libunwindstack/tests/DwarfOpTest.cpp b/libunwindstack/tests/DwarfOpTest.cpp
index eda9a58..942d074 100644
--- a/libunwindstack/tests/DwarfOpTest.cpp
+++ b/libunwindstack/tests/DwarfOpTest.cpp
@@ -27,8 +27,8 @@
 
 #include "DwarfOp.h"
 
+#include "MemoryFake.h"
 #include "RegsFake.h"
-#include "utils/MemoryFake.h"
 
 namespace unwindstack {
 
diff --git a/libunwindstack/tests/DwarfSectionImplTest.cpp b/libunwindstack/tests/DwarfSectionImplTest.cpp
index a487bc0..9d047f2 100644
--- a/libunwindstack/tests/DwarfSectionImplTest.cpp
+++ b/libunwindstack/tests/DwarfSectionImplTest.cpp
@@ -25,25 +25,49 @@
 #include "DwarfEncoding.h"
 
 #include "LogFake.h"
-#include "utils/DwarfSectionImplFake.h"
-#include "utils/MemoryFake.h"
-#include "utils/RegsFake.h"
+#include "MemoryFake.h"
+#include "RegsFake.h"
 
 namespace unwindstack {
 
 template <typename TypeParam>
+class TestDwarfSectionImpl : public DwarfSectionImpl<TypeParam> {
+ public:
+  TestDwarfSectionImpl(Memory* memory) : DwarfSectionImpl<TypeParam>(memory) {}
+  virtual ~TestDwarfSectionImpl() = default;
+
+  bool Init(uint64_t, uint64_t, int64_t) override { return false; }
+
+  void GetFdes(std::vector<const DwarfFde*>*) override {}
+
+  const DwarfFde* GetFdeFromPc(uint64_t) override { return nullptr; }
+
+  uint64_t GetCieOffsetFromFde32(uint32_t) { return 0; }
+
+  uint64_t GetCieOffsetFromFde64(uint64_t) { return 0; }
+
+  uint64_t AdjustPcFromFde(uint64_t) override { return 0; }
+
+  void TestSetCachedCieLocRegs(uint64_t offset, const DwarfLocations& loc_regs) {
+    this->cie_loc_regs_[offset] = loc_regs;
+  }
+  void TestClearCachedCieLocRegs() { this->cie_loc_regs_.clear(); }
+  void TestClearError() { this->last_error_.code = DWARF_ERROR_NONE; }
+};
+
+template <typename TypeParam>
 class DwarfSectionImplTest : public ::testing::Test {
  protected:
   void SetUp() override {
     memory_.Clear();
-    section_ = new DwarfSectionImplFake<TypeParam>(&memory_);
+    section_ = new TestDwarfSectionImpl<TypeParam>(&memory_);
     ResetLogs();
   }
 
   void TearDown() override { delete section_; }
 
   MemoryFake memory_;
-  DwarfSectionImplFake<TypeParam>* section_ = nullptr;
+  TestDwarfSectionImpl<TypeParam>* section_ = nullptr;
 };
 TYPED_TEST_SUITE_P(DwarfSectionImplTest);
 
@@ -54,7 +78,7 @@
   EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
   EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
 
-  this->section_->FakeClearError();
+  this->section_->TestClearError();
   ASSERT_TRUE(this->section_->GetCieFromOffset(0x4000) == nullptr);
   EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
   EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
@@ -65,7 +89,7 @@
   EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
   EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
 
-  this->section_->FakeClearError();
+  this->section_->TestClearError();
   ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
   EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
   EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
@@ -185,19 +209,19 @@
   ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
   EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
 
-  this->section_->FakeClearError();
+  this->section_->TestClearError();
   loc_regs.erase(CFA_REG);
   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_INVALID, {0, 0}};
   ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
   EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
 
-  this->section_->FakeClearError();
+  this->section_->TestClearError();
   loc_regs.erase(CFA_REG);
   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_OFFSET, {0, 0}};
   ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
   EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
 
-  this->section_->FakeClearError();
+  this->section_->TestClearError();
   loc_regs.erase(CFA_REG);
   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0, 0}};
   ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
@@ -542,7 +566,7 @@
 
   DwarfLocations cie_loc_regs;
   cie_loc_regs[6] = DwarfLocation{DWARF_LOCATION_REGISTER, {4, 0}};
-  this->section_->FakeSetCachedCieLocRegs(0x8000, cie_loc_regs);
+  this->section_->TestSetCachedCieLocRegs(0x8000, cie_loc_regs);
   this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0x09, 0x04, 0x03});
 
   DwarfLocations loc_regs;
diff --git a/libunwindstack/tests/DwarfSectionTest.cpp b/libunwindstack/tests/DwarfSectionTest.cpp
index 55f1d3a..e1ed885 100644
--- a/libunwindstack/tests/DwarfSectionTest.cpp
+++ b/libunwindstack/tests/DwarfSectionTest.cpp
@@ -22,8 +22,8 @@
 #include <unwindstack/DwarfSection.h>
 #include <unwindstack/Elf.h>
 
+#include "MemoryFake.h"
 #include "RegsFake.h"
-#include "utils/MemoryFake.h"
 
 namespace unwindstack {
 
diff --git a/libunwindstack/tests/ElfCacheTest.cpp b/libunwindstack/tests/ElfCacheTest.cpp
index 1687a4c..65eef20 100644
--- a/libunwindstack/tests/ElfCacheTest.cpp
+++ b/libunwindstack/tests/ElfCacheTest.cpp
@@ -15,24 +15,17 @@
  */
 
 #include <elf.h>
-#include <sys/mman.h>
 #include <unistd.h>
 
-#include <memory>
-
 #include <android-base/file.h>
 
 #include <gtest/gtest.h>
 
 #include <unwindstack/Elf.h>
 #include <unwindstack/MapInfo.h>
-#include <unwindstack/Maps.h>
 
-#include "ElfFake.h"
 #include "ElfTestUtils.h"
-#include "utils/MemoryFake.h"
-
-#include <inttypes.h>
+#include "MemoryFake.h"
 
 namespace unwindstack {
 
@@ -40,337 +33,231 @@
  protected:
   static void SetUpTestSuite() { memory_.reset(new MemoryFake); }
 
-  void SetUp() override {
-    Elf::SetCachingEnabled(true);
+  void SetUp() override { Elf::SetCachingEnabled(true); }
 
-    // Create maps for testing.
-    maps_.reset(
-        new BufferMaps("1000-2000 r-xs 00000000 00:00 0 elf_one.so\n"
-                       "2000-3000 r-xs 00000000 00:00 0 elf_two.so\n"
-                       "3000-4000 ---s 00000000 00:00 0\n"
-                       "4000-5000 r--s 00000000 00:00 0 elf_three.so\n"
-                       "5000-6000 r-xs 00001000 00:00 0 elf_three.so\n"
-                       "6000-7000 ---s 00000000 00:00 0\n"
-                       "7000-8000 r--s 00001000 00:00 0 app_one.apk\n"
-                       "8000-9000 r-xs 00005000 00:00 0 app_one.apk\n"
-                       "9000-a000 r--s 00004000 00:00 0 app_two.apk\n"
-                       "a000-b000 r-xs 00005000 00:00 0 app_two.apk\n"
-                       "b000-c000 r--s 00008000 00:00 0 app_two.apk\n"
-                       "c000-d000 r-xs 00009000 00:00 0 app_two.apk\n"
-                       "d000-e000 ---s 00000000 00:00 0\n"
-                       "e000-f000 r-xs 00000000 00:00 0 invalid\n"
-                       "f000-10000 r-xs 00000000 00:00 0 invalid\n"
-                       "10000-11000 r-xs 00000000 00:00 0 elf_two.so\n"
-                       "11000-12000 r-xs 00000000 00:00 0 elf_one.so\n"
-                       "12000-13000 r--s 00000000 00:00 0 elf_three.so\n"
-                       "13000-14000 r-xs 00001000 00:00 0 elf_three.so\n"
-                       "14000-15000 ---s 00000000 00:00 0\n"
-                       "15000-16000 r--s 00001000 00:00 0 app_one.apk\n"
-                       "16000-17000 r-xs 00005000 00:00 0 app_one.apk\n"
-                       "17000-18000 r--s 00004000 00:00 0 app_two.apk\n"
-                       "18000-19000 r-xs 00005000 00:00 0 app_two.apk\n"
-                       "19000-1a000 r--s 00008000 00:00 0 app_two.apk\n"
-                       "1a000-1b000 r-xs 00009000 00:00 0 app_two.apk\n"));
-    ASSERT_TRUE(maps_->Parse());
-
-    std::unordered_map<std::string, std::string> renames;
-
-    temps_.emplace_back(new TemporaryFile);
-    renames["elf_one.so"] = temps_.back()->path;
-    WriteElfFile(0, temps_.back().get());
-
-    temps_.emplace_back(new TemporaryFile);
-    renames["elf_two.so"] = temps_.back()->path;
-    WriteElfFile(0, temps_.back().get());
-
-    temps_.emplace_back(new TemporaryFile);
-    renames["elf_three.so"] = temps_.back()->path;
-    WriteElfFile(0, temps_.back().get());
-
-    temps_.emplace_back(new TemporaryFile);
-    renames["app_one.apk"] = temps_.back()->path;
-    WriteElfFile(0x1000, temps_.back().get());
-    WriteElfFile(0x5000, temps_.back().get());
-
-    temps_.emplace_back(new TemporaryFile);
-    renames["app_two.apk"] = temps_.back()->path;
-    WriteElfFile(0x4000, temps_.back().get());
-    WriteElfFile(0x8000, temps_.back().get());
-
-    for (auto& map_info : *maps_) {
-      if (!map_info->name().empty()) {
-        if (renames.count(map_info->name()) != 0) {
-          // Replace the name with the temporary file name.
-          map_info->name() = renames.at(map_info->name());
-        }
-      }
-    }
-  }
-
-  // Make sure the cache is cleared between runs.
   void TearDown() override { Elf::SetCachingEnabled(false); }
 
-  void WriteElfFile(uint64_t offset, TemporaryFile* tf) {
-    Elf32_Ehdr ehdr;
-    TestInitEhdr(&ehdr, ELFCLASS32, EM_ARM);
-    Elf32_Shdr shdr = {};
-    shdr.sh_type = SHT_NULL;
-
-    ehdr.e_shnum = 1;
-    ehdr.e_shoff = 0x2000;
-    ehdr.e_shentsize = sizeof(shdr);
+  void WriteElfFile(uint64_t offset, TemporaryFile* tf, uint32_t type) {
+    ASSERT_TRUE(type == EM_ARM || type == EM_386 || type == EM_X86_64);
+    size_t ehdr_size;
+    Elf32_Ehdr ehdr32;
+    Elf64_Ehdr ehdr64;
+    void* ptr;
+    if (type == EM_ARM || type == EM_386) {
+      ehdr_size = sizeof(ehdr32);
+      ptr = &ehdr32;
+      TestInitEhdr(&ehdr32, ELFCLASS32, type);
+    } else {
+      ehdr_size = sizeof(ehdr64);
+      ptr = &ehdr64;
+      TestInitEhdr(&ehdr64, ELFCLASS64, type);
+    }
 
     ASSERT_EQ(offset, static_cast<uint64_t>(lseek(tf->fd, offset, SEEK_SET)));
-    ASSERT_TRUE(android::base::WriteFully(tf->fd, &ehdr, sizeof(ehdr)));
-    ASSERT_EQ(offset + 0x2000, static_cast<uint64_t>(lseek(tf->fd, offset + 0x2000, SEEK_SET)));
-    ASSERT_TRUE(android::base::WriteFully(tf->fd, &shdr, sizeof(shdr)));
+    ASSERT_TRUE(android::base::WriteFully(tf->fd, ptr, ehdr_size));
   }
 
-  std::vector<std::unique_ptr<TemporaryFile>> temps_;
-  std::unique_ptr<Maps> maps_;
+  void VerifyWithinSameMap(bool cache_enabled);
+  void VerifySameMap(bool cache_enabled);
+  void VerifyWithinSameMapNeverReadAtZero(bool cache_enabled);
+
   static std::shared_ptr<Memory> memory_;
 };
 
 std::shared_ptr<Memory> ElfCacheTest::memory_;
 
-TEST_F(ElfCacheTest, verify_elf_caching) {
-  Elf* elf_one = maps_->Find(0x1000)->GetElf(memory_, ARCH_ARM);
-  ASSERT_TRUE(elf_one->valid());
-  Elf* elf_two = maps_->Find(0x2000)->GetElf(memory_, ARCH_ARM);
-  EXPECT_TRUE(elf_two->valid());
-  Elf* elf_three = maps_->Find(0x4000)->GetElf(memory_, ARCH_ARM);
-  ASSERT_TRUE(elf_three->valid());
+void ElfCacheTest::VerifySameMap(bool cache_enabled) {
+  if (!cache_enabled) {
+    Elf::SetCachingEnabled(false);
+  }
 
-  // Check that the caching is working for elf files.
-  EXPECT_EQ(maps_->Find(0x5000)->GetElf(memory_, ARCH_ARM), elf_three);
-  EXPECT_EQ(0U, maps_->Find(0x5000)->elf_start_offset());
-  EXPECT_EQ(0x1000U, maps_->Find(0x5000)->elf_offset());
-  EXPECT_EQ(0x1000U, maps_->Find(0x5000)->offset());
+  TemporaryFile tf;
+  ASSERT_TRUE(tf.fd != -1);
+  WriteElfFile(0, &tf, EM_ARM);
+  close(tf.fd);
 
-  EXPECT_EQ(maps_->Find(0x10000)->GetElf(memory_, ARCH_ARM), elf_two);
-  EXPECT_EQ(0U, maps_->Find(0x10000)->elf_start_offset());
-  EXPECT_EQ(0U, maps_->Find(0x10000)->elf_offset());
-  EXPECT_EQ(0U, maps_->Find(0x10000)->offset());
+  uint64_t start = 0x1000;
+  uint64_t end = 0x20000;
+  MapInfo info1(nullptr, nullptr, start, end, 0, 0x5, tf.path);
+  MapInfo info2(nullptr, nullptr, start, end, 0, 0x5, tf.path);
 
-  EXPECT_EQ(maps_->Find(0x11000)->GetElf(memory_, ARCH_ARM), elf_one);
-  EXPECT_EQ(0U, maps_->Find(0x11000)->elf_start_offset());
-  EXPECT_EQ(0U, maps_->Find(0x11000)->elf_offset());
-  EXPECT_EQ(0U, maps_->Find(0x11000)->offset());
+  Elf* elf1 = info1.GetElf(memory_, ARCH_ARM);
+  ASSERT_TRUE(elf1->valid());
+  Elf* elf2 = info2.GetElf(memory_, ARCH_ARM);
+  ASSERT_TRUE(elf2->valid());
 
-  EXPECT_EQ(maps_->Find(0x12000)->GetElf(memory_, ARCH_ARM), elf_three);
-  EXPECT_EQ(0U, maps_->Find(0x12000)->elf_start_offset());
-  EXPECT_EQ(0U, maps_->Find(0x12000)->elf_offset());
-  EXPECT_EQ(0U, maps_->Find(0x12000)->offset());
-
-  EXPECT_EQ(maps_->Find(0x13000)->GetElf(memory_, ARCH_ARM), elf_three);
-  EXPECT_EQ(0U, maps_->Find(0x13000)->elf_start_offset());
-  EXPECT_EQ(0x1000U, maps_->Find(0x13000)->elf_offset());
-  EXPECT_EQ(0x1000U, maps_->Find(0x13000)->offset());
+  if (cache_enabled) {
+    EXPECT_EQ(elf1, elf2);
+  } else {
+    EXPECT_NE(elf1, elf2);
+  }
 }
 
-TEST_F(ElfCacheTest, verify_elf_caching_ro_first_ro_second) {
-  Elf* elf_three = maps_->Find(0x4000)->GetElf(memory_, ARCH_ARM);
-  ASSERT_TRUE(elf_three->valid());
-
-  EXPECT_EQ(maps_->Find(0x12000)->GetElf(memory_, ARCH_ARM), elf_three);
-  EXPECT_EQ(0U, maps_->Find(0x12000)->elf_start_offset());
-  EXPECT_EQ(0U, maps_->Find(0x12000)->elf_offset());
-  EXPECT_EQ(0U, maps_->Find(0x12000)->offset());
+TEST_F(ElfCacheTest, no_caching) {
+  VerifySameMap(false);
 }
 
-TEST_F(ElfCacheTest, verify_elf_caching_ro_first_rx_second) {
-  Elf* elf_three = maps_->Find(0x4000)->GetElf(memory_, ARCH_ARM);
-  ASSERT_TRUE(elf_three->valid());
-
-  EXPECT_EQ(maps_->Find(0x13000)->GetElf(memory_, ARCH_ARM), elf_three);
-  EXPECT_EQ(0U, maps_->Find(0x13000)->elf_start_offset());
-  EXPECT_EQ(0x1000U, maps_->Find(0x13000)->elf_offset());
-  EXPECT_EQ(0x1000U, maps_->Find(0x13000)->offset());
+TEST_F(ElfCacheTest, caching_invalid_elf) {
+  VerifySameMap(true);
 }
 
-TEST_F(ElfCacheTest, verify_elf_caching_rx_first_ro_second) {
-  Elf* elf_three = maps_->Find(0x5000)->GetElf(memory_, ARCH_ARM);
-  ASSERT_TRUE(elf_three->valid());
+void ElfCacheTest::VerifyWithinSameMap(bool cache_enabled) {
+  if (!cache_enabled) {
+    Elf::SetCachingEnabled(false);
+  }
 
-  EXPECT_EQ(maps_->Find(0x12000)->GetElf(memory_, ARCH_ARM), elf_three);
-  EXPECT_EQ(0U, maps_->Find(0x12000)->elf_start_offset());
-  EXPECT_EQ(0U, maps_->Find(0x12000)->elf_offset());
-  EXPECT_EQ(0U, maps_->Find(0x12000)->offset());
+  TemporaryFile tf;
+  ASSERT_TRUE(tf.fd != -1);
+  WriteElfFile(0, &tf, EM_ARM);
+  WriteElfFile(0x100, &tf, EM_386);
+  WriteElfFile(0x200, &tf, EM_X86_64);
+  lseek(tf.fd, 0x500, SEEK_SET);
+  uint8_t value = 0;
+  write(tf.fd, &value, 1);
+  close(tf.fd);
+
+  uint64_t start = 0x1000;
+  uint64_t end = 0x20000;
+  // Will have an elf at offset 0 in file.
+  MapInfo info0_1(nullptr, nullptr, start, end, 0, 0x5, tf.path);
+  MapInfo info0_2(nullptr, nullptr, start, end, 0, 0x5, tf.path);
+  // Will have an elf at offset 0x100 in file.
+  MapInfo info100_1(nullptr, nullptr, start, end, 0x100, 0x5, tf.path);
+  MapInfo info100_2(nullptr, nullptr, start, end, 0x100, 0x5, tf.path);
+  // Will have an elf at offset 0x200 in file.
+  MapInfo info200_1(nullptr, nullptr, start, end, 0x200, 0x5, tf.path);
+  MapInfo info200_2(nullptr, nullptr, start, end, 0x200, 0x5, tf.path);
+  // Will have an elf at offset 0 in file.
+  MapInfo info300_1(nullptr, nullptr, start, end, 0x300, 0x5, tf.path);
+  MapInfo info300_2(nullptr, nullptr, start, end, 0x300, 0x5, tf.path);
+
+  Elf* elf0_1 = info0_1.GetElf(memory_, ARCH_ARM);
+  ASSERT_TRUE(elf0_1->valid());
+  EXPECT_EQ(ARCH_ARM, elf0_1->arch());
+  Elf* elf0_2 = info0_2.GetElf(memory_, ARCH_ARM);
+  ASSERT_TRUE(elf0_2->valid());
+  EXPECT_EQ(ARCH_ARM, elf0_2->arch());
+  EXPECT_EQ(0U, info0_1.elf_offset());
+  EXPECT_EQ(0U, info0_2.elf_offset());
+  if (cache_enabled) {
+    EXPECT_EQ(elf0_1, elf0_2);
+  } else {
+    EXPECT_NE(elf0_1, elf0_2);
+  }
+
+  Elf* elf100_1 = info100_1.GetElf(memory_, ARCH_X86);
+  ASSERT_TRUE(elf100_1->valid());
+  EXPECT_EQ(ARCH_X86, elf100_1->arch());
+  Elf* elf100_2 = info100_2.GetElf(memory_, ARCH_X86);
+  ASSERT_TRUE(elf100_2->valid());
+  EXPECT_EQ(ARCH_X86, elf100_2->arch());
+  EXPECT_EQ(0U, info100_1.elf_offset());
+  EXPECT_EQ(0U, info100_2.elf_offset());
+  if (cache_enabled) {
+    EXPECT_EQ(elf100_1, elf100_2);
+  } else {
+    EXPECT_NE(elf100_1, elf100_2);
+  }
+
+  Elf* elf200_1 = info200_1.GetElf(memory_, ARCH_X86_64);
+  ASSERT_TRUE(elf200_1->valid());
+  EXPECT_EQ(ARCH_X86_64, elf200_1->arch());
+  Elf* elf200_2 = info200_2.GetElf(memory_, ARCH_X86_64);
+  ASSERT_TRUE(elf200_2->valid());
+  EXPECT_EQ(ARCH_X86_64, elf200_2->arch());
+  EXPECT_EQ(0U, info200_1.elf_offset());
+  EXPECT_EQ(0U, info200_2.elf_offset());
+  if (cache_enabled) {
+    EXPECT_EQ(elf200_1, elf200_2);
+  } else {
+    EXPECT_NE(elf200_1, elf200_2);
+  }
+
+  Elf* elf300_1 = info300_1.GetElf(memory_, ARCH_ARM);
+  ASSERT_TRUE(elf300_1->valid());
+  EXPECT_EQ(ARCH_ARM, elf300_1->arch());
+  Elf* elf300_2 = info300_2.GetElf(memory_, ARCH_ARM);
+  ASSERT_TRUE(elf300_2->valid());
+  EXPECT_EQ(ARCH_ARM, elf300_2->arch());
+  EXPECT_EQ(0x300U, info300_1.elf_offset());
+  EXPECT_EQ(0x300U, info300_2.elf_offset());
+  if (cache_enabled) {
+    EXPECT_EQ(elf300_1, elf300_2);
+    EXPECT_EQ(elf0_1, elf300_1);
+  } else {
+    EXPECT_NE(elf300_1, elf300_2);
+    EXPECT_NE(elf0_1, elf300_1);
+  }
 }
 
-TEST_F(ElfCacheTest, verify_elf_caching_rx_first_rx_second) {
-  Elf* elf_three = maps_->Find(0x5000)->GetElf(memory_, ARCH_ARM);
-  ASSERT_TRUE(elf_three->valid());
-
-  EXPECT_EQ(maps_->Find(0x13000)->GetElf(memory_, ARCH_ARM), elf_three);
-  EXPECT_EQ(0U, maps_->Find(0x13000)->elf_start_offset());
-  EXPECT_EQ(0x1000U, maps_->Find(0x13000)->elf_offset());
-  EXPECT_EQ(0x1000U, maps_->Find(0x13000)->offset());
+TEST_F(ElfCacheTest, no_caching_valid_elf_offset_non_zero) {
+  VerifyWithinSameMap(false);
 }
 
-TEST_F(ElfCacheTest, verify_elf_apk_caching) {
-  Elf* app_one_elf1 = maps_->Find(0x7000)->GetElf(memory_, ARCH_ARM);
-  ASSERT_TRUE(app_one_elf1->valid());
-  Elf* app_one_elf2 = maps_->Find(0x8000)->GetElf(memory_, ARCH_ARM);
-  ASSERT_TRUE(app_one_elf2->valid());
-  Elf* app_two_elf1 = maps_->Find(0x9000)->GetElf(memory_, ARCH_ARM);
-  ASSERT_TRUE(app_two_elf1->valid());
-  Elf* app_two_elf2 = maps_->Find(0xb000)->GetElf(memory_, ARCH_ARM);
-  ASSERT_TRUE(app_two_elf2->valid());
-
-  // Check that the caching is working for elf files in apks.
-  EXPECT_EQ(maps_->Find(0xa000)->GetElf(memory_, ARCH_ARM), app_two_elf1);
-  EXPECT_EQ(0x4000U, maps_->Find(0xa000)->elf_start_offset());
-  EXPECT_EQ(0x1000U, maps_->Find(0xa000)->elf_offset());
-  EXPECT_EQ(0x5000U, maps_->Find(0xa000)->offset());
-
-  EXPECT_EQ(maps_->Find(0xc000)->GetElf(memory_, ARCH_ARM), app_two_elf2);
-  EXPECT_EQ(0x8000U, maps_->Find(0xc000)->elf_start_offset());
-  EXPECT_EQ(0x1000U, maps_->Find(0xc000)->elf_offset());
-  EXPECT_EQ(0x9000U, maps_->Find(0xc000)->offset());
-
-  EXPECT_EQ(maps_->Find(0x15000)->GetElf(memory_, ARCH_ARM), app_one_elf1);
-  EXPECT_EQ(0x1000U, maps_->Find(0x15000)->elf_start_offset());
-  EXPECT_EQ(0U, maps_->Find(0x15000)->elf_offset());
-  EXPECT_EQ(0x1000U, maps_->Find(0x15000)->offset());
-
-  EXPECT_EQ(maps_->Find(0x16000)->GetElf(memory_, ARCH_ARM), app_one_elf2);
-  EXPECT_EQ(0x1000U, maps_->Find(0x16000)->elf_start_offset());
-  EXPECT_EQ(0x4000U, maps_->Find(0x16000)->elf_offset());
-  EXPECT_EQ(0x5000U, maps_->Find(0x16000)->offset());
-
-  EXPECT_EQ(maps_->Find(0x17000)->GetElf(memory_, ARCH_ARM), app_two_elf1);
-  EXPECT_EQ(0x4000U, maps_->Find(0x17000)->elf_start_offset());
-  EXPECT_EQ(0U, maps_->Find(0x17000)->elf_offset());
-  EXPECT_EQ(0x4000U, maps_->Find(0x17000)->offset());
-
-  EXPECT_EQ(maps_->Find(0x18000)->GetElf(memory_, ARCH_ARM), app_two_elf1);
-  EXPECT_EQ(0x4000U, maps_->Find(0x18000)->elf_start_offset());
-  EXPECT_EQ(0x1000U, maps_->Find(0x18000)->elf_offset());
-  EXPECT_EQ(0x5000U, maps_->Find(0x18000)->offset());
-
-  EXPECT_EQ(maps_->Find(0x19000)->GetElf(memory_, ARCH_ARM), app_two_elf2);
-  EXPECT_EQ(0x8000U, maps_->Find(0x19000)->elf_start_offset());
-  EXPECT_EQ(0U, maps_->Find(0x19000)->elf_offset());
-  EXPECT_EQ(0x8000U, maps_->Find(0x19000)->offset());
-
-  EXPECT_EQ(maps_->Find(0x1a000)->GetElf(memory_, ARCH_ARM), app_two_elf2);
-  EXPECT_EQ(0x8000U, maps_->Find(0x1a000)->elf_start_offset());
-  EXPECT_EQ(0x1000U, maps_->Find(0x1a000)->elf_offset());
-  EXPECT_EQ(0x9000U, maps_->Find(0x1a000)->offset());
+TEST_F(ElfCacheTest, caching_valid_elf_offset_non_zero) {
+  VerifyWithinSameMap(true);
 }
 
-TEST_F(ElfCacheTest, verify_elf_apk_caching_ro_first_ro_second) {
-  Elf* app_two_elf1 = maps_->Find(0x9000)->GetElf(memory_, ARCH_ARM);
-  ASSERT_TRUE(app_two_elf1->valid());
-  Elf* app_two_elf2 = maps_->Find(0xb000)->GetElf(memory_, ARCH_ARM);
-  ASSERT_TRUE(app_two_elf2->valid());
+// Verify that when reading from multiple non-zero offsets in the same map
+// that when cached, all of the elf objects are the same.
+void ElfCacheTest::VerifyWithinSameMapNeverReadAtZero(bool cache_enabled) {
+  if (!cache_enabled) {
+    Elf::SetCachingEnabled(false);
+  }
 
-  EXPECT_EQ(maps_->Find(0x17000)->GetElf(memory_, ARCH_ARM), app_two_elf1);
-  EXPECT_EQ(0x4000U, maps_->Find(0x17000)->elf_start_offset());
-  EXPECT_EQ(0U, maps_->Find(0x17000)->elf_offset());
-  EXPECT_EQ(0x4000U, maps_->Find(0x17000)->offset());
+  TemporaryFile tf;
+  ASSERT_TRUE(tf.fd != -1);
+  WriteElfFile(0, &tf, EM_ARM);
+  lseek(tf.fd, 0x500, SEEK_SET);
+  uint8_t value = 0;
+  write(tf.fd, &value, 1);
+  close(tf.fd);
 
-  EXPECT_EQ(maps_->Find(0x19000)->GetElf(memory_, ARCH_ARM), app_two_elf2);
-  EXPECT_EQ(0x8000U, maps_->Find(0x19000)->elf_start_offset());
-  EXPECT_EQ(0U, maps_->Find(0x19000)->elf_offset());
-  EXPECT_EQ(0x8000U, maps_->Find(0x19000)->offset());
+  uint64_t start = 0x1000;
+  uint64_t end = 0x20000;
+  // Multiple info sections at different offsets will have non-zero elf offsets.
+  MapInfo info300_1(nullptr, nullptr, start, end, 0x300, 0x5, tf.path);
+  MapInfo info300_2(nullptr, nullptr, start, end, 0x300, 0x5, tf.path);
+  MapInfo info400_1(nullptr, nullptr, start, end, 0x400, 0x5, tf.path);
+  MapInfo info400_2(nullptr, nullptr, start, end, 0x400, 0x5, tf.path);
+
+  Elf* elf300_1 = info300_1.GetElf(memory_, ARCH_ARM);
+  ASSERT_TRUE(elf300_1->valid());
+  EXPECT_EQ(ARCH_ARM, elf300_1->arch());
+  Elf* elf300_2 = info300_2.GetElf(memory_, ARCH_ARM);
+  ASSERT_TRUE(elf300_2->valid());
+  EXPECT_EQ(ARCH_ARM, elf300_2->arch());
+  EXPECT_EQ(0x300U, info300_1.elf_offset());
+  EXPECT_EQ(0x300U, info300_2.elf_offset());
+  if (cache_enabled) {
+    EXPECT_EQ(elf300_1, elf300_2);
+  } else {
+    EXPECT_NE(elf300_1, elf300_2);
+  }
+
+  Elf* elf400_1 = info400_1.GetElf(memory_, ARCH_ARM);
+  ASSERT_TRUE(elf400_1->valid());
+  EXPECT_EQ(ARCH_ARM, elf400_1->arch());
+  Elf* elf400_2 = info400_2.GetElf(memory_, ARCH_ARM);
+  ASSERT_TRUE(elf400_2->valid());
+  EXPECT_EQ(ARCH_ARM, elf400_2->arch());
+  EXPECT_EQ(0x400U, info400_1.elf_offset());
+  EXPECT_EQ(0x400U, info400_2.elf_offset());
+  if (cache_enabled) {
+    EXPECT_EQ(elf400_1, elf400_2);
+    EXPECT_EQ(elf300_1, elf400_1);
+  } else {
+    EXPECT_NE(elf400_1, elf400_2);
+    EXPECT_NE(elf300_1, elf400_1);
+  }
 }
 
-TEST_F(ElfCacheTest, verify_elf_apk_caching_ro_first_rx_second) {
-  Elf* app_two_elf1 = maps_->Find(0x9000)->GetElf(memory_, ARCH_ARM);
-  ASSERT_TRUE(app_two_elf1->valid());
-  Elf* app_two_elf2 = maps_->Find(0xb000)->GetElf(memory_, ARCH_ARM);
-  ASSERT_TRUE(app_two_elf2->valid());
-
-  EXPECT_EQ(maps_->Find(0x18000)->GetElf(memory_, ARCH_ARM), app_two_elf1);
-  EXPECT_EQ(0x4000U, maps_->Find(0x18000)->elf_start_offset());
-  EXPECT_EQ(0x1000U, maps_->Find(0x18000)->elf_offset());
-  EXPECT_EQ(0x5000U, maps_->Find(0x18000)->offset());
-
-  EXPECT_EQ(maps_->Find(0x1a000)->GetElf(memory_, ARCH_ARM), app_two_elf2);
-  EXPECT_EQ(0x8000U, maps_->Find(0x1a000)->elf_start_offset());
-  EXPECT_EQ(0x1000U, maps_->Find(0x1a000)->elf_offset());
-  EXPECT_EQ(0x9000U, maps_->Find(0x1a000)->offset());
+TEST_F(ElfCacheTest, no_caching_valid_elf_offset_non_zero_never_read_at_zero) {
+  VerifyWithinSameMapNeverReadAtZero(false);
 }
 
-TEST_F(ElfCacheTest, verify_elf_apk_caching_rx_first_ro_second) {
-  Elf* app_two_elf1 = maps_->Find(0xa000)->GetElf(memory_, ARCH_ARM);
-  ASSERT_TRUE(app_two_elf1->valid());
-  Elf* app_two_elf2 = maps_->Find(0xc000)->GetElf(memory_, ARCH_ARM);
-  ASSERT_TRUE(app_two_elf2->valid());
-
-  EXPECT_EQ(maps_->Find(0x17000)->GetElf(memory_, ARCH_ARM), app_two_elf1);
-  EXPECT_EQ(0x4000U, maps_->Find(0x17000)->elf_start_offset());
-  EXPECT_EQ(0U, maps_->Find(0x17000)->elf_offset());
-  EXPECT_EQ(0x4000U, maps_->Find(0x17000)->offset());
-
-  EXPECT_EQ(maps_->Find(0x19000)->GetElf(memory_, ARCH_ARM), app_two_elf2);
-  EXPECT_EQ(0x8000U, maps_->Find(0x19000)->elf_start_offset());
-  EXPECT_EQ(0U, maps_->Find(0x19000)->elf_offset());
-  EXPECT_EQ(0x8000U, maps_->Find(0x19000)->offset());
-}
-
-TEST_F(ElfCacheTest, verify_elf_apk_caching_rx_first_rx_second) {
-  Elf* app_two_elf1 = maps_->Find(0x9000)->GetElf(memory_, ARCH_ARM);
-  ASSERT_TRUE(app_two_elf1->valid());
-  Elf* app_two_elf2 = maps_->Find(0xb000)->GetElf(memory_, ARCH_ARM);
-  ASSERT_TRUE(app_two_elf2->valid());
-
-  EXPECT_EQ(maps_->Find(0x17000)->GetElf(memory_, ARCH_ARM), app_two_elf1);
-  EXPECT_EQ(0x4000U, maps_->Find(0x17000)->elf_start_offset());
-  EXPECT_EQ(0U, maps_->Find(0x17000)->elf_offset());
-  EXPECT_EQ(0x4000U, maps_->Find(0x17000)->offset());
-
-  EXPECT_EQ(maps_->Find(0x19000)->GetElf(memory_, ARCH_ARM), app_two_elf2);
-  EXPECT_EQ(0x8000U, maps_->Find(0x19000)->elf_start_offset());
-  EXPECT_EQ(0U, maps_->Find(0x19000)->elf_offset());
-  EXPECT_EQ(0x8000U, maps_->Find(0x19000)->offset());
-}
-
-// Verify that with elf caching disabled, we aren't caching improperly.
-TEST_F(ElfCacheTest, verify_disable_elf_caching) {
-  Elf::SetCachingEnabled(false);
-
-  Elf* elf_one = maps_->Find(0x1000)->GetElf(memory_, ARCH_ARM);
-  ASSERT_TRUE(elf_one->valid());
-  Elf* elf_two = maps_->Find(0x2000)->GetElf(memory_, ARCH_ARM);
-  EXPECT_TRUE(elf_two->valid());
-  Elf* elf_three = maps_->Find(0x4000)->GetElf(memory_, ARCH_ARM);
-  ASSERT_TRUE(elf_three->valid());
-  EXPECT_EQ(maps_->Find(0x5000)->GetElf(memory_, ARCH_ARM), elf_three);
-
-  EXPECT_NE(maps_->Find(0x10000)->GetElf(memory_, ARCH_ARM), elf_two);
-  EXPECT_NE(maps_->Find(0x11000)->GetElf(memory_, ARCH_ARM), elf_one);
-  EXPECT_NE(maps_->Find(0x12000)->GetElf(memory_, ARCH_ARM), elf_three);
-  EXPECT_NE(maps_->Find(0x13000)->GetElf(memory_, ARCH_ARM), elf_three);
-
-  Elf* app_one_elf1 = maps_->Find(0x7000)->GetElf(memory_, ARCH_ARM);
-  ASSERT_TRUE(app_one_elf1->valid());
-  Elf* app_one_elf2 = maps_->Find(0x8000)->GetElf(memory_, ARCH_ARM);
-  ASSERT_TRUE(app_one_elf2->valid());
-  Elf* app_two_elf1 = maps_->Find(0x9000)->GetElf(memory_, ARCH_ARM);
-  ASSERT_TRUE(app_two_elf1->valid());
-  EXPECT_EQ(maps_->Find(0xa000)->GetElf(memory_, ARCH_ARM), app_two_elf1);
-  Elf* app_two_elf2 = maps_->Find(0xb000)->GetElf(memory_, ARCH_ARM);
-  ASSERT_TRUE(app_two_elf2->valid());
-  EXPECT_EQ(maps_->Find(0xc000)->GetElf(memory_, ARCH_ARM), app_two_elf2);
-
-  EXPECT_NE(maps_->Find(0x15000)->GetElf(memory_, ARCH_ARM), app_one_elf1);
-  EXPECT_NE(maps_->Find(0x16000)->GetElf(memory_, ARCH_ARM), app_one_elf2);
-  EXPECT_NE(maps_->Find(0x17000)->GetElf(memory_, ARCH_ARM), app_two_elf1);
-  EXPECT_NE(maps_->Find(0x18000)->GetElf(memory_, ARCH_ARM), app_two_elf1);
-  EXPECT_NE(maps_->Find(0x19000)->GetElf(memory_, ARCH_ARM), app_two_elf2);
-  EXPECT_NE(maps_->Find(0x1a000)->GetElf(memory_, ARCH_ARM), app_two_elf2);
-}
-
-// Verify that invalid elf objects are not cached.
-TEST_F(ElfCacheTest, verify_invalid_not_cached) {
-  Elf* invalid_elf1 = maps_->Find(0xe000)->GetElf(memory_, ARCH_ARM);
-  ASSERT_FALSE(invalid_elf1->valid());
-  Elf* invalid_elf2 = maps_->Find(0xf000)->GetElf(memory_, ARCH_ARM);
-  ASSERT_FALSE(invalid_elf2->valid());
-  ASSERT_NE(invalid_elf1, invalid_elf2);
+TEST_F(ElfCacheTest, caching_valid_elf_offset_non_zero_never_read_at_zero) {
+  VerifyWithinSameMapNeverReadAtZero(true);
 }
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/ElfFake.cpp b/libunwindstack/tests/ElfFake.cpp
index 3da673e..80c3e31 100644
--- a/libunwindstack/tests/ElfFake.cpp
+++ b/libunwindstack/tests/ElfFake.cpp
@@ -26,7 +26,7 @@
 #include <unwindstack/SharedString.h>
 
 #include "ElfFake.h"
-#include "utils/RegsFake.h"
+#include "RegsFake.h"
 
 namespace unwindstack {
 
diff --git a/libunwindstack/tests/ElfFake.h b/libunwindstack/tests/ElfFake.h
index 97d6dcc..8c5b9ef 100644
--- a/libunwindstack/tests/ElfFake.h
+++ b/libunwindstack/tests/ElfFake.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_TESTS_ELF_FAKE_H
+#define _LIBUNWINDSTACK_TESTS_ELF_FAKE_H
 
 #include <stdint.h>
 
@@ -151,3 +152,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_TESTS_ELF_FAKE_H
diff --git a/libunwindstack/tests/ElfInterfaceArmTest.cpp b/libunwindstack/tests/ElfInterfaceArmTest.cpp
index ee70cc0..43c6a97 100644
--- a/libunwindstack/tests/ElfInterfaceArmTest.cpp
+++ b/libunwindstack/tests/ElfInterfaceArmTest.cpp
@@ -26,7 +26,7 @@
 #include "ElfInterfaceArm.h"
 
 #include "ElfFake.h"
-#include "utils/MemoryFake.h"
+#include "MemoryFake.h"
 
 namespace unwindstack {
 
diff --git a/libunwindstack/tests/ElfInterfaceTest.cpp b/libunwindstack/tests/ElfInterfaceTest.cpp
index 47ae3d0..d250d0a 100644
--- a/libunwindstack/tests/ElfInterfaceTest.cpp
+++ b/libunwindstack/tests/ElfInterfaceTest.cpp
@@ -26,7 +26,7 @@
 #include "ElfInterfaceArm.h"
 
 #include "ElfFake.h"
-#include "utils/MemoryFake.h"
+#include "MemoryFake.h"
 
 #if !defined(PT_ARM_EXIDX)
 #define PT_ARM_EXIDX 0x70000001
diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp
index f16c6e5..c641f52 100644
--- a/libunwindstack/tests/ElfTest.cpp
+++ b/libunwindstack/tests/ElfTest.cpp
@@ -31,7 +31,7 @@
 #include "ElfFake.h"
 #include "ElfTestUtils.h"
 #include "LogFake.h"
-#include "utils/MemoryFake.h"
+#include "MemoryFake.h"
 
 #if !defined(PT_ARM_EXIDX)
 #define PT_ARM_EXIDX 0x70000001
@@ -172,7 +172,8 @@
   ASSERT_FALSE(elf.Init());
 
   ASSERT_EQ("", GetFakeLogBuf());
-  ASSERT_EQ("", GetFakeLogPrint());
+  ASSERT_EQ("4 unwind 32 bit elf that is neither arm nor x86 nor mips: e_machine = 20\n\n",
+            GetFakeLogPrint());
 }
 
 TEST_F(ElfTest, elf64_invalid_machine) {
@@ -184,7 +185,8 @@
   ASSERT_FALSE(elf.Init());
 
   ASSERT_EQ("", GetFakeLogBuf());
-  ASSERT_EQ("", GetFakeLogPrint());
+  ASSERT_EQ("4 unwind 64 bit elf that is neither aarch64 nor x86_64 nor mips64: e_machine = 21\n\n",
+            GetFakeLogPrint());
 }
 
 TEST_F(ElfTest, elf_arm) {
@@ -294,12 +296,12 @@
   elf.FakeSetInterface(interface);
 
   elf.FakeSetValid(true);
-  auto map_info = MapInfo::Create(0x1000, 0x2000, 0, 0, "");
+  MapInfo map_info(nullptr, nullptr, 0x1000, 0x2000, 0, 0, "");
 
-  ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, map_info.get()));
+  ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, &map_info));
 
   elf.FakeSetValid(false);
-  ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, map_info.get()));
+  ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, &map_info));
 }
 
 void ElfTest::VerifyStepIfSignalHandler(uint64_t load_bias) {
@@ -551,14 +553,4 @@
   EXPECT_EQ(0x1000U, elf.GetLastErrorAddress());
 }
 
-TEST(ElfBuildIdTest, get_printable_build_id_empty) {
-  std::string empty;
-  ASSERT_EQ("", Elf::GetPrintableBuildID(empty));
-}
-
-TEST(ElfBuildIdTest, get_printable_build_id_check) {
-  std::string empty = {'\xff', '\x45', '\x40', '\x0f'};
-  ASSERT_EQ("ff45400f", Elf::GetPrintableBuildID(empty));
-}
-
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/ElfTestUtils.h b/libunwindstack/tests/ElfTestUtils.h
index 25f0052..62cd59a 100644
--- a/libunwindstack/tests/ElfTestUtils.h
+++ b/libunwindstack/tests/ElfTestUtils.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_TESTS_ELF_TEST_UTILS_H
+#define _LIBUNWINDSTACK_TESTS_ELF_TEST_UTILS_H
 
 #include <functional>
 #include <string>
@@ -33,3 +34,5 @@
 std::string TestGetFileDirectory();
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_TESTS_ELF_TEST_UTILS_H
diff --git a/libunwindstack/tests/GlobalTest.cpp b/libunwindstack/tests/GlobalTest.cpp
deleted file mode 100644
index b6893ba..0000000
--- a/libunwindstack/tests/GlobalTest.cpp
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2021 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 <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <unwindstack/Elf.h>
-#include <unwindstack/Global.h>
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Maps.h>
-
-#include "ElfFake.h"
-
-using ::testing::_;
-using ::testing::DoAll;
-using ::testing::Return;
-using ::testing::SetArgPointee;
-
-namespace unwindstack {
-
-class GlobalMock : public Global {
- public:
-  explicit GlobalMock(std::shared_ptr<Memory>& memory) : Global(memory) {}
-  GlobalMock(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs)
-      : Global(memory, search_libs) {}
-
-  MOCK_METHOD(bool, ReadVariableData, (uint64_t), (override));
-
-  MOCK_METHOD(void, ProcessArch, (), (override));
-
-  void TestFindAndReadVariable(Maps* maps, const char* var_str) {
-    FindAndReadVariable(maps, var_str);
-  }
-};
-
-class GlobalTest : public ::testing::Test {
- protected:
-  void SetUp() override {
-    maps_.reset(
-        new BufferMaps("10000-11000 r--p 0000 00:00 0 first.so\n"
-                       "11000-12000 r-xp 1000 00:00 0 first.so\n"
-                       "12000-13000 rw-p 2000 00:00 0 first.so\n"
-
-                       "20000-22000 r--p 0000 00:00 0 second.so\n"
-                       "22000-23000 rw-p 2000 00:00 0 second.so\n"
-
-                       "30000-31000 r--p 0000 00:00 0 third.so\n"
-                       "31000-32000 ---p 0000 00:00 0\n"
-                       "32000-33000 r-xp 1000 00:00 0 third.so\n"
-                       "33000-34000 rw-p 2000 00:00 0 third.so\n"
-
-                       "40000-42000 r--p 0000 00:00 0 fourth.so\n"
-                       "42000-43000 rw-p 0000 00:00 0 fourth.so\n"));
-    ASSERT_TRUE(maps_->Parse());
-    ASSERT_EQ(11U, maps_->Total());
-
-    elf_fakes_.push_back(new ElfInterfaceFake(nullptr));
-    elf_fakes_.push_back(new ElfInterfaceFake(nullptr));
-    elf_fakes_.push_back(new ElfInterfaceFake(nullptr));
-    elf_fakes_.push_back(new ElfInterfaceFake(nullptr));
-
-    ElfFake* elf_fake = new ElfFake(nullptr);
-    elf_fake->FakeSetValid(true);
-    elf_fake->FakeSetInterface(elf_fakes_[0]);
-    elf_fakes_[0]->FakeSetDataVaddrStart(0x2000);
-    elf_fakes_[0]->FakeSetDataVaddrEnd(0x3000);
-    elf_fakes_[0]->FakeSetDataOffset(0x2000);
-    auto map_info = maps_->Find(0x10000);
-    map_info->GetElfFields().elf_.reset(elf_fake);
-
-    elf_fake = new ElfFake(nullptr);
-    elf_fake->FakeSetValid(true);
-    elf_fake->FakeSetInterface(elf_fakes_[1]);
-    elf_fakes_[1]->FakeSetDataVaddrStart(0x2000);
-    elf_fakes_[1]->FakeSetDataVaddrEnd(0x3000);
-    elf_fakes_[1]->FakeSetDataOffset(0x2000);
-    map_info = maps_->Find(0x20000);
-    map_info->GetElfFields().elf_.reset(elf_fake);
-
-    elf_fake = new ElfFake(nullptr);
-    elf_fake->FakeSetValid(true);
-    elf_fake->FakeSetInterface(elf_fakes_[2]);
-    elf_fakes_[2]->FakeSetDataVaddrStart(0x2000);
-    elf_fakes_[2]->FakeSetDataVaddrEnd(0x3000);
-    elf_fakes_[2]->FakeSetDataOffset(0x2000);
-    map_info = maps_->Find(0x30000);
-    map_info->GetElfFields().elf_.reset(elf_fake);
-
-    elf_fake = new ElfFake(nullptr);
-    elf_fake->FakeSetValid(true);
-    elf_fake->FakeSetInterface(elf_fakes_[3]);
-    elf_fakes_[3]->FakeSetDataVaddrStart(00);
-    elf_fakes_[3]->FakeSetDataVaddrEnd(0x1000);
-    elf_fakes_[3]->FakeSetDataOffset(0);
-    map_info = maps_->Find(0x40000);
-    map_info->GetElfFields().elf_.reset(elf_fake);
-
-    global_.reset(new GlobalMock(empty_));
-  }
-
-  std::shared_ptr<Memory> empty_;
-  std::unique_ptr<BufferMaps> maps_;
-  std::unique_ptr<GlobalMock> global_;
-  std::vector<ElfInterfaceFake*> elf_fakes_;
-};
-
-TEST_F(GlobalTest, ro_rx_rw) {
-  std::string global_var("fake_global");
-  elf_fakes_[0]->FakeSetGlobalVariable(global_var, 0x2010);
-  EXPECT_CALL(*global_, ReadVariableData(0x12010)).WillOnce(Return(true));
-
-  global_->TestFindAndReadVariable(maps_.get(), global_var.c_str());
-}
-
-TEST_F(GlobalTest, ro_rx_rw_searchable) {
-  std::vector<std::string> search_libs = {"first.so"};
-  global_.reset(new GlobalMock(empty_, search_libs));
-
-  std::string global_var("fake_global");
-  elf_fakes_[0]->FakeSetGlobalVariable(global_var, 0x2010);
-  EXPECT_CALL(*global_, ReadVariableData(0x12010)).WillOnce(Return(true));
-
-  global_->TestFindAndReadVariable(maps_.get(), global_var.c_str());
-}
-
-TEST_F(GlobalTest, ro_rx_rw_not_searchable) {
-  std::vector<std::string> search_libs = {"second.so"};
-  global_.reset(new GlobalMock(empty_, search_libs));
-
-  std::string global_var("fake_global");
-  elf_fakes_[0]->FakeSetGlobalVariable(global_var, 0x2010);
-
-  global_->TestFindAndReadVariable(maps_.get(), global_var.c_str());
-}
-
-TEST_F(GlobalTest, ro_rw) {
-  std::string global_var("fake_global");
-  elf_fakes_[1]->FakeSetGlobalVariable(global_var, 0x2010);
-  EXPECT_CALL(*global_, ReadVariableData(0x22010)).WillOnce(Return(true));
-
-  global_->TestFindAndReadVariable(maps_.get(), global_var.c_str());
-}
-
-TEST_F(GlobalTest, ro_blank_rx_rw) {
-  std::string global_var("fake_global");
-  elf_fakes_[2]->FakeSetGlobalVariable(global_var, 0x2010);
-  EXPECT_CALL(*global_, ReadVariableData(0x33010)).WillOnce(Return(true));
-
-  global_->TestFindAndReadVariable(maps_.get(), global_var.c_str());
-}
-
-TEST_F(GlobalTest, ro_rw_with_zero_offset) {
-  std::string global_var("fake_global");
-  elf_fakes_[3]->FakeSetGlobalVariable(global_var, 0x10);
-  EXPECT_CALL(*global_, ReadVariableData(0x42010)).WillOnce(Return(true));
-
-  global_->TestFindAndReadVariable(maps_.get(), global_var.c_str());
-}
-
-}  // namespace unwindstack
diff --git a/libunwindstack/tests/JitDebugTest.cpp b/libunwindstack/tests/JitDebugTest.cpp
index 66e220c..44378a8 100644
--- a/libunwindstack/tests/JitDebugTest.cpp
+++ b/libunwindstack/tests/JitDebugTest.cpp
@@ -29,7 +29,7 @@
 #include <unwindstack/Memory.h>
 
 #include "ElfFake.h"
-#include "utils/MemoryFake.h"
+#include "MemoryFake.h"
 
 namespace unwindstack {
 
@@ -65,15 +65,15 @@
                        "200000-210000 rw-p 01ee000 00:00 0 /fake/elf4\n"));
     ASSERT_TRUE(maps_->Parse());
 
-    MapInfo* map_info = maps_->Get(3).get();
+    MapInfo* map_info = maps_->Get(3);
     ASSERT_TRUE(map_info != nullptr);
     CreateFakeElf(map_info, 0x2800, 0x2000, 0x2000, 0x3000);
 
-    map_info = maps_->Get(5).get();
+    map_info = maps_->Get(5);
     ASSERT_TRUE(map_info != nullptr);
     CreateFakeElf(map_info, 0x2800, 0x2000, 0x2000, 0x3000);
 
-    map_info = maps_->Get(7).get();
+    map_info = maps_->Get(7);
     ASSERT_TRUE(map_info != nullptr);
     CreateFakeElf(map_info, 0xee800, 0xee000, 0xee000, 0x10000);
   }
@@ -414,7 +414,7 @@
   EXPECT_TRUE(jit_debug_->Find(maps_.get(), 0x1500) == nullptr);
 
   // Change the name of the map that includes the value and verify this works.
-  auto map_info = maps_->Get(5);
+  MapInfo* map_info = maps_->Get(5);
   map_info->set_name("/system/lib/libart.so");
   map_info = maps_->Get(6);
   map_info->set_name("/system/lib/libart.so");
diff --git a/libunwindstack/tests/LocalUnwinderTest.cpp b/libunwindstack/tests/LocalUnwinderTest.cpp
new file mode 100644
index 0000000..5658aa3
--- /dev/null
+++ b/libunwindstack/tests/LocalUnwinderTest.cpp
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2018 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 <dlfcn.h>
+#include <inttypes.h>
+#include <signal.h>
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include <android-base/stringprintf.h>
+
+#include <unwindstack/LocalUnwinder.h>
+
+namespace unwindstack {
+
+static std::vector<LocalFrameData>* g_frame_info;
+static LocalUnwinder* g_unwinder;
+
+extern "C" void SignalLocalInnerFunction() {
+  g_unwinder->Unwind(g_frame_info, 256);
+}
+
+extern "C" void SignalLocalMiddleFunction() {
+  SignalLocalInnerFunction();
+}
+
+extern "C" void SignalLocalOuterFunction() {
+  SignalLocalMiddleFunction();
+}
+
+static void SignalLocalCallerHandler(int, siginfo_t*, void*) {
+  SignalLocalOuterFunction();
+}
+
+static std::string ErrorMsg(const std::vector<const char*>& function_names,
+                            const std::vector<LocalFrameData>& frame_info) {
+  std::string unwind;
+  size_t i = 0;
+  for (const auto& frame : frame_info) {
+    unwind += android::base::StringPrintf("#%02zu pc 0x%" PRIx64 " rel_pc 0x%" PRIx64, i++,
+                                          frame.pc, frame.rel_pc);
+    if (frame.map_info != nullptr) {
+      if (!frame.map_info->name().empty()) {
+        unwind += " ";
+        unwind += frame.map_info->name();
+      } else {
+        unwind += android::base::StringPrintf(" 0x%" PRIx64 "-0x%" PRIx64, frame.map_info->start(),
+                                              frame.map_info->end());
+      }
+      if (frame.map_info->offset() != 0) {
+        unwind += android::base::StringPrintf(" offset 0x%" PRIx64, frame.map_info->offset());
+      }
+    }
+    if (!frame.function_name.empty()) {
+      unwind += " " + frame.function_name;
+      if (frame.function_offset != 0) {
+        unwind += android::base::StringPrintf("+%" PRId64, frame.function_offset);
+      }
+    }
+    unwind += '\n';
+  }
+
+  return std::string(
+             "Unwind completed without finding all frames\n"
+             "  Looking for function: ") +
+         function_names.front() + "\n" + "Unwind data:\n" + unwind;
+}
+
+// This test assumes that this code is compiled with optimizations turned
+// off. If this doesn't happen, then all of the calls will be optimized
+// away.
+extern "C" void LocalInnerFunction(LocalUnwinder* unwinder, bool unwind_through_signal) {
+  std::vector<LocalFrameData> frame_info;
+  g_frame_info = &frame_info;
+  g_unwinder = unwinder;
+  std::vector<const char*> expected_function_names;
+
+  if (unwind_through_signal) {
+    struct sigaction act, oldact;
+    memset(&act, 0, sizeof(act));
+    act.sa_sigaction = SignalLocalCallerHandler;
+    act.sa_flags = SA_RESTART | SA_ONSTACK;
+    ASSERT_EQ(0, sigaction(SIGUSR1, &act, &oldact));
+
+    raise(SIGUSR1);
+
+    ASSERT_EQ(0, sigaction(SIGUSR1, &oldact, nullptr));
+
+    expected_function_names = {"LocalOuterFunction",        "LocalMiddleFunction",
+                               "LocalInnerFunction",        "SignalLocalOuterFunction",
+                               "SignalLocalMiddleFunction", "SignalLocalInnerFunction"};
+  } else {
+    ASSERT_TRUE(unwinder->Unwind(&frame_info, 256));
+
+    expected_function_names = {"LocalOuterFunction", "LocalMiddleFunction", "LocalInnerFunction"};
+  }
+
+  for (auto& frame : frame_info) {
+    if (frame.function_name == expected_function_names.back()) {
+      expected_function_names.pop_back();
+      if (expected_function_names.empty()) {
+        break;
+      }
+    }
+  }
+
+  ASSERT_TRUE(expected_function_names.empty()) << ErrorMsg(expected_function_names, frame_info);
+}
+
+extern "C" void LocalMiddleFunction(LocalUnwinder* unwinder, bool unwind_through_signal) {
+  LocalInnerFunction(unwinder, unwind_through_signal);
+}
+
+extern "C" void LocalOuterFunction(LocalUnwinder* unwinder, bool unwind_through_signal) {
+  LocalMiddleFunction(unwinder, unwind_through_signal);
+}
+
+class LocalUnwinderTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    unwinder_.reset(new LocalUnwinder);
+    ASSERT_TRUE(unwinder_->Init());
+  }
+
+  std::unique_ptr<LocalUnwinder> unwinder_;
+};
+
+TEST_F(LocalUnwinderTest, local) {
+  LocalOuterFunction(unwinder_.get(), false);
+}
+
+TEST_F(LocalUnwinderTest, local_signal) {
+  LocalOuterFunction(unwinder_.get(), true);
+}
+
+TEST_F(LocalUnwinderTest, local_multiple) {
+  ASSERT_NO_FATAL_FAILURE(LocalOuterFunction(unwinder_.get(), false));
+
+  ASSERT_NO_FATAL_FAILURE(LocalOuterFunction(unwinder_.get(), true));
+
+  ASSERT_NO_FATAL_FAILURE(LocalOuterFunction(unwinder_.get(), false));
+
+  ASSERT_NO_FATAL_FAILURE(LocalOuterFunction(unwinder_.get(), true));
+}
+
+// This test verifies that doing an unwind before and after a dlopen
+// works. It's verifying that the maps read during the first unwind
+// do not cause a problem when doing the unwind using the code in
+// the dlopen'd code.
+TEST_F(LocalUnwinderTest, unwind_after_dlopen) {
+  // Prime the maps data.
+  ASSERT_NO_FATAL_FAILURE(LocalOuterFunction(unwinder_.get(), false));
+
+  std::string testlib(testing::internal::GetArgvs()[0]);
+  auto const value = testlib.find_last_of('/');
+  if (value != std::string::npos) {
+    testlib = testlib.substr(0, value + 1);
+  } else {
+    testlib = "";
+  }
+  testlib += "libunwindstack_local.so";
+
+  void* handle = dlopen(testlib.c_str(), RTLD_NOW);
+  ASSERT_TRUE(handle != nullptr);
+
+  void (*unwind_function)(void*, void*) =
+      reinterpret_cast<void (*)(void*, void*)>(dlsym(handle, "TestlibLevel1"));
+  ASSERT_TRUE(unwind_function != nullptr);
+
+  std::vector<LocalFrameData> frame_info;
+  unwind_function(unwinder_.get(), &frame_info);
+
+  ASSERT_EQ(0, dlclose(handle));
+
+  std::vector<const char*> expected_function_names{"TestlibLevel1", "TestlibLevel2",
+                                                   "TestlibLevel3", "TestlibLevel4"};
+
+  for (auto& frame : frame_info) {
+    if (frame.function_name == expected_function_names.back()) {
+      expected_function_names.pop_back();
+      if (expected_function_names.empty()) {
+        break;
+      }
+    }
+  }
+
+  ASSERT_TRUE(expected_function_names.empty()) << ErrorMsg(expected_function_names, frame_info);
+}
+
+}  // namespace unwindstack
diff --git a/libunwindstack/tests/LocalUpdatableMapsTest.cpp b/libunwindstack/tests/LocalUpdatableMapsTest.cpp
index 0dbabcd..0632a44 100644
--- a/libunwindstack/tests/LocalUpdatableMapsTest.cpp
+++ b/libunwindstack/tests/LocalUpdatableMapsTest.cpp
@@ -36,6 +36,8 @@
 
   void TestSetMapsFile(const std::string& maps_file) { maps_file_ = maps_file; }
 
+  const std::vector<std::unique_ptr<MapInfo>>& TestGetSavedMaps() { return saved_maps_; }
+
  private:
   std::string maps_file_;
 };
@@ -54,7 +56,7 @@
     ASSERT_TRUE(maps_.Parse());
     ASSERT_EQ(2U, maps_.Total());
 
-    auto map_info = maps_.Get(0);
+    MapInfo* map_info = maps_.Get(0);
     ASSERT_TRUE(map_info != nullptr);
     EXPECT_EQ(0x3000U, map_info->start());
     EXPECT_EQ(0x4000U, map_info->end());
@@ -81,16 +83,15 @@
   maps_.TestSetMapsFile(tf.path);
   ASSERT_TRUE(maps_.Reparse());
   ASSERT_EQ(2U, maps_.Total());
+  EXPECT_EQ(0U, maps_.TestGetSavedMaps().size());
 
-  auto map_info = maps_.Get(0);
+  MapInfo* map_info = maps_.Get(0);
   ASSERT_TRUE(map_info != nullptr);
   EXPECT_EQ(0x3000U, map_info->start());
   EXPECT_EQ(0x4000U, map_info->end());
   EXPECT_EQ(0U, map_info->offset());
   EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
   EXPECT_TRUE(map_info->name().empty());
-  EXPECT_EQ(nullptr, map_info->prev_map());
-  EXPECT_EQ(maps_.Get(1), map_info->next_map());
 
   map_info = maps_.Get(1);
   ASSERT_TRUE(map_info != nullptr);
@@ -99,8 +100,6 @@
   EXPECT_EQ(0U, map_info->offset());
   EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
   EXPECT_TRUE(map_info->name().empty());
-  EXPECT_EQ(maps_.Get(0), map_info->prev_map());
-  EXPECT_EQ(nullptr, map_info->next_map());
 }
 
 TEST_F(LocalUpdatableMapsTest, same_map_new_perms) {
@@ -114,15 +113,13 @@
   ASSERT_TRUE(maps_.Reparse());
   ASSERT_EQ(2U, maps_.Total());
 
-  auto map_info = maps_.Get(0);
+  MapInfo* map_info = maps_.Get(0);
   ASSERT_TRUE(map_info != nullptr);
   EXPECT_EQ(0x3000U, map_info->start());
   EXPECT_EQ(0x4000U, map_info->end());
   EXPECT_EQ(0U, map_info->offset());
   EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, map_info->flags());
   EXPECT_TRUE(map_info->name().empty());
-  EXPECT_EQ(nullptr, map_info->prev_map());
-  EXPECT_EQ(maps_.Get(1), map_info->next_map());
 
   map_info = maps_.Get(1);
   ASSERT_TRUE(map_info != nullptr);
@@ -131,8 +128,16 @@
   EXPECT_EQ(0U, map_info->offset());
   EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
   EXPECT_TRUE(map_info->name().empty());
-  EXPECT_EQ(maps_.Get(0), map_info->prev_map());
-  EXPECT_EQ(nullptr, map_info->next_map());
+
+  auto& saved_maps = maps_.TestGetSavedMaps();
+  ASSERT_EQ(1U, saved_maps.size());
+  map_info = saved_maps[0].get();
+  ASSERT_TRUE(map_info != nullptr);
+  EXPECT_EQ(0x3000U, map_info->start());
+  EXPECT_EQ(0x4000U, map_info->end());
+  EXPECT_EQ(0U, map_info->offset());
+  EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
+  EXPECT_TRUE(map_info->name().empty());
 }
 
 TEST_F(LocalUpdatableMapsTest, same_map_new_name) {
@@ -146,15 +151,13 @@
   ASSERT_TRUE(maps_.Reparse());
   ASSERT_EQ(2U, maps_.Total());
 
-  auto map_info = maps_.Get(0);
+  MapInfo* map_info = maps_.Get(0);
   ASSERT_TRUE(map_info != nullptr);
   EXPECT_EQ(0x3000U, map_info->start());
   EXPECT_EQ(0x4000U, map_info->end());
   EXPECT_EQ(0U, map_info->offset());
   EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
   EXPECT_EQ("/fake/lib.so", map_info->name());
-  EXPECT_EQ(nullptr, map_info->prev_map());
-  EXPECT_EQ(maps_.Get(1), map_info->next_map());
 
   map_info = maps_.Get(1);
   ASSERT_TRUE(map_info != nullptr);
@@ -163,8 +166,16 @@
   EXPECT_EQ(0U, map_info->offset());
   EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
   EXPECT_TRUE(map_info->name().empty());
-  EXPECT_EQ(maps_.Get(0), map_info->prev_map());
-  EXPECT_EQ(nullptr, map_info->next_map());
+
+  auto& saved_maps = maps_.TestGetSavedMaps();
+  ASSERT_EQ(1U, saved_maps.size());
+  map_info = saved_maps[0].get();
+  ASSERT_TRUE(map_info != nullptr);
+  EXPECT_EQ(0x3000U, map_info->start());
+  EXPECT_EQ(0x4000U, map_info->end());
+  EXPECT_EQ(0U, map_info->offset());
+  EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
+  EXPECT_TRUE(map_info->name().empty());
 }
 
 TEST_F(LocalUpdatableMapsTest, only_add_maps) {
@@ -179,16 +190,15 @@
   maps_.TestSetMapsFile(tf.path);
   ASSERT_TRUE(maps_.Reparse());
   ASSERT_EQ(4U, maps_.Total());
+  EXPECT_EQ(0U, maps_.TestGetSavedMaps().size());
 
-  auto map_info = maps_.Get(0);
+  MapInfo* map_info = maps_.Get(0);
   ASSERT_TRUE(map_info != nullptr);
   EXPECT_EQ(0x1000U, map_info->start());
   EXPECT_EQ(0x2000U, map_info->end());
   EXPECT_EQ(0U, map_info->offset());
   EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
   EXPECT_TRUE(map_info->name().empty());
-  EXPECT_EQ(nullptr, map_info->prev_map());
-  EXPECT_EQ(maps_.Get(1), map_info->next_map());
 
   map_info = maps_.Get(1);
   ASSERT_TRUE(map_info != nullptr);
@@ -197,8 +207,6 @@
   EXPECT_EQ(0U, map_info->offset());
   EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
   EXPECT_TRUE(map_info->name().empty());
-  EXPECT_EQ(maps_.Get(0), map_info->prev_map());
-  EXPECT_EQ(maps_.Get(2), map_info->next_map());
 
   map_info = maps_.Get(2);
   ASSERT_TRUE(map_info != nullptr);
@@ -207,8 +215,6 @@
   EXPECT_EQ(0U, map_info->offset());
   EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
   EXPECT_TRUE(map_info->name().empty());
-  EXPECT_EQ(maps_.Get(1), map_info->prev_map());
-  EXPECT_EQ(maps_.Get(3), map_info->next_map());
 
   map_info = maps_.Get(3);
   ASSERT_TRUE(map_info != nullptr);
@@ -217,8 +223,6 @@
   EXPECT_EQ(0U, map_info->offset());
   EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
   EXPECT_TRUE(map_info->name().empty());
-  EXPECT_EQ(maps_.Get(2), map_info->prev_map());
-  EXPECT_EQ(nullptr, map_info->next_map());
 }
 
 TEST_F(LocalUpdatableMapsTest, all_new_maps) {
@@ -232,15 +236,13 @@
   ASSERT_TRUE(maps_.Reparse());
   ASSERT_EQ(2U, maps_.Total());
 
-  auto map_info = maps_.Get(0);
+  MapInfo* map_info = maps_.Get(0);
   ASSERT_TRUE(map_info != nullptr);
   EXPECT_EQ(0x1000U, map_info->start());
   EXPECT_EQ(0x2000U, map_info->end());
   EXPECT_EQ(0U, map_info->offset());
   EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
   EXPECT_TRUE(map_info->name().empty());
-  EXPECT_EQ(nullptr, map_info->prev_map());
-  EXPECT_EQ(maps_.Get(1), map_info->next_map());
 
   map_info = maps_.Get(1);
   ASSERT_TRUE(map_info != nullptr);
@@ -249,8 +251,24 @@
   EXPECT_EQ(0U, map_info->offset());
   EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
   EXPECT_TRUE(map_info->name().empty());
-  EXPECT_EQ(maps_.Get(0), map_info->prev_map());
-  EXPECT_EQ(nullptr, map_info->next_map());
+
+  auto& saved_maps = maps_.TestGetSavedMaps();
+  ASSERT_EQ(2U, saved_maps.size());
+  map_info = saved_maps[0].get();
+  ASSERT_TRUE(map_info != nullptr);
+  EXPECT_EQ(0x3000U, map_info->start());
+  EXPECT_EQ(0x4000U, map_info->end());
+  EXPECT_EQ(0U, map_info->offset());
+  EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
+  EXPECT_TRUE(map_info->name().empty());
+
+  map_info = saved_maps[1].get();
+  ASSERT_TRUE(map_info != nullptr);
+  EXPECT_EQ(0x8000U, map_info->start());
+  EXPECT_EQ(0x9000U, map_info->end());
+  EXPECT_EQ(0U, map_info->offset());
+  EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
+  EXPECT_TRUE(map_info->name().empty());
 }
 
 TEST_F(LocalUpdatableMapsTest, add_map_prev_name_updated) {
@@ -265,21 +283,14 @@
   ASSERT_TRUE(maps_.Reparse());
   ASSERT_EQ(3U, maps_.Total());
 
-  auto map_info = maps_.Get(2);
+  MapInfo* map_info = maps_.Get(2);
   ASSERT_TRUE(map_info != nullptr);
   EXPECT_EQ(0x9000U, map_info->start());
   EXPECT_EQ(0xA000U, map_info->end());
   EXPECT_EQ(0U, map_info->offset());
   EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
   EXPECT_TRUE(map_info->name().empty());
-
-  // Check all of the prev and next pointers.
-  EXPECT_EQ(nullptr, maps_.Get(0)->prev_map());
-  EXPECT_EQ(maps_.Get(1), maps_.Get(0)->next_map());
-  EXPECT_EQ(maps_.Get(0), maps_.Get(1)->prev_map());
-  EXPECT_EQ(maps_.Get(2), maps_.Get(1)->next_map());
-  EXPECT_EQ(maps_.Get(1), maps_.Get(2)->prev_map());
-  EXPECT_EQ(nullptr, maps_.Get(2)->next_map());
+  EXPECT_EQ(maps_.Get(1), map_info->prev_map());
 }
 
 TEST_F(LocalUpdatableMapsTest, add_map_prev_real_name_updated) {
@@ -287,7 +298,7 @@
   ASSERT_TRUE(
       android::base::WriteStringToFile("3000-4000 r-xp 00000 00:00 0 /fake/lib.so\n"
                                        "4000-5000 ---p 00000 00:00 0\n"
-                                       "7000-8000 r-xp 00000 00:00 0 /fake/lib.so\n"
+                                       "7000-8000 r-xp 00000 00:00 0 /fake/lib1.so\n"
                                        "8000-9000 ---p 00000 00:00 0\n",
                                        tf.path));
 
@@ -302,16 +313,15 @@
   ASSERT_EQ(4U, maps_.Total());
   ASSERT_FALSE(any_changed);
 
-  auto map_info = maps_.Get(2);
+  MapInfo* map_info = maps_.Get(2);
   ASSERT_TRUE(map_info != nullptr);
   EXPECT_EQ(0x7000U, map_info->start());
   EXPECT_EQ(0x8000U, map_info->end());
   EXPECT_EQ(0U, map_info->offset());
   EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
-  EXPECT_EQ(maps_.Get(0), map_info->GetPrevRealMap());
+  EXPECT_EQ(maps_.Get(0), map_info->prev_real_map());
   EXPECT_EQ(maps_.Get(1), map_info->prev_map());
-  EXPECT_EQ(maps_.Get(3), map_info->next_map());
-  EXPECT_EQ("/fake/lib.so", map_info->name());
+  EXPECT_EQ("/fake/lib1.so", map_info->name());
 
   map_info = maps_.Get(3);
   ASSERT_TRUE(map_info != nullptr);
@@ -319,15 +329,14 @@
   EXPECT_EQ(0x9000U, map_info->end());
   EXPECT_EQ(0U, map_info->offset());
   EXPECT_TRUE(map_info->IsBlank());
-  EXPECT_EQ(nullptr, map_info->GetPrevRealMap());
+  EXPECT_EQ(maps_.Get(2), map_info->prev_real_map());
   EXPECT_EQ(maps_.Get(2), map_info->prev_map());
-  EXPECT_EQ(maps_.Get(4), map_info->next_map());
   EXPECT_TRUE(map_info->name().empty());
 
   ASSERT_TRUE(
       android::base::WriteStringToFile("3000-4000 r-xp 00000 00:00 0 /fake/lib.so\n"
                                        "4000-5000 ---p 00000 00:00 0\n"
-                                       "7000-8000 r-xp 00000 00:00 0 /fake/lib.so\n"
+                                       "7000-8000 r-xp 00000 00:00 0 /fake/lib1.so\n"
                                        "8000-9000 ---p 00000 00:00 0\n"
                                        "9000-a000 r-xp 00000 00:00 0 /fake/lib2.so\n"
                                        "a000-b000 r-xp 00000 00:00 0 /fake/lib3.so\n",
@@ -349,10 +358,9 @@
   EXPECT_EQ(0x8000U, map_info->end());
   EXPECT_EQ(0U, map_info->offset());
   EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
-  EXPECT_EQ("/fake/lib.so", map_info->name());
+  EXPECT_EQ("/fake/lib1.so", map_info->name());
   EXPECT_EQ(maps_.Get(1), map_info->prev_map());
-  EXPECT_EQ(maps_.Get(0), map_info->GetPrevRealMap());
-  EXPECT_EQ(maps_.Get(3), map_info->next_map());
+  EXPECT_EQ(maps_.Get(0), map_info->prev_real_map());
 
   map_info = maps_.Get(4);
   ASSERT_TRUE(map_info != nullptr);
@@ -362,8 +370,7 @@
   EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
   EXPECT_EQ("/fake/lib2.so", map_info->name());
   EXPECT_EQ(maps_.Get(3), map_info->prev_map());
-  EXPECT_EQ(nullptr, map_info->GetPrevRealMap());
-  EXPECT_EQ(maps_.Get(5), map_info->next_map());
+  EXPECT_EQ(maps_.Get(2), map_info->prev_real_map());
 
   map_info = maps_.Get(5);
   ASSERT_TRUE(map_info != nullptr);
@@ -373,8 +380,7 @@
   EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
   EXPECT_EQ("/fake/lib3.so", map_info->name());
   EXPECT_EQ(maps_.Get(4), map_info->prev_map());
-  EXPECT_EQ(nullptr, map_info->GetPrevRealMap());
-  EXPECT_EQ(nullptr, map_info->next_map());
+  EXPECT_EQ(maps_.Get(4), map_info->prev_real_map());
 }
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/LogFake.h b/libunwindstack/tests/LogFake.h
index 11f47b1..e1dc50d 100644
--- a/libunwindstack/tests/LogFake.h
+++ b/libunwindstack/tests/LogFake.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_TESTS_LOG_FAKE_H
+#define _LIBUNWINDSTACK_TESTS_LOG_FAKE_H
 
 #include <string>
 
@@ -25,3 +26,5 @@
 std::string GetFakeLogPrint();
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_TESTS_LOG_FAKE_H
diff --git a/libunwindstack/tests/MapInfoCreateMemoryTest.cpp b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
index 08e0d2b..d5e04a1 100644
--- a/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
+++ b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
@@ -35,7 +35,7 @@
 #include <unwindstack/Memory.h>
 
 #include "ElfTestUtils.h"
-#include "utils/MemoryFake.h"
+#include "MemoryFake.h"
 
 namespace unwindstack {
 
@@ -89,32 +89,32 @@
 };
 
 TEST_F(MapInfoCreateMemoryTest, end_le_start) {
-  auto info = MapInfo::Create(0x100, 0x100, 0, 0, elf_.path);
+  MapInfo info(nullptr, nullptr, 0x100, 0x100, 0, 0, elf_.path);
 
-  std::unique_ptr<Memory> memory(info->CreateMemory(process_memory_));
+  std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
   ASSERT_TRUE(memory.get() == nullptr);
 
-  info->set_end(0xff);
-  memory.reset(info->CreateMemory(process_memory_));
+  info.set_end(0xff);
+  memory.reset(info.CreateMemory(process_memory_));
   ASSERT_TRUE(memory.get() == nullptr);
 
   // Make sure this test is valid.
-  info->set_end(0x101);
-  memory.reset(info->CreateMemory(process_memory_));
+  info.set_end(0x101);
+  memory.reset(info.CreateMemory(process_memory_));
   ASSERT_TRUE(memory.get() != nullptr);
-  EXPECT_FALSE(info->memory_backed_elf());
+  EXPECT_FALSE(info.memory_backed_elf());
 }
 
 // Verify that if the offset is non-zero but there is no elf at the offset,
 // that the full file is used.
 TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_full_file) {
-  auto info = MapInfo::Create(0x100, 0x200, 0x100, 0, elf_.path);
+  MapInfo info(nullptr, nullptr, 0x100, 0x200, 0x100, 0, elf_.path);
 
-  std::unique_ptr<Memory> memory(info->CreateMemory(process_memory_));
+  std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
   ASSERT_TRUE(memory.get() != nullptr);
-  EXPECT_FALSE(info->memory_backed_elf());
-  ASSERT_EQ(0x100U, info->elf_offset());
-  EXPECT_EQ(0U, info->elf_start_offset());
+  EXPECT_FALSE(info.memory_backed_elf());
+  ASSERT_EQ(0x100U, info.elf_offset());
+  EXPECT_EQ(0x100U, info.elf_start_offset());
 
   // Read the entire file.
   std::vector<uint8_t> buffer(1024);
@@ -129,61 +129,62 @@
 
   // Now verify the elf start offset is set correctly based on the previous
   // info.
-  auto prev_info = MapInfo::Create(0, 0x100, 0x10, 0, "");
-  info->set_prev_map(prev_info);
+  MapInfo prev_info(nullptr, nullptr, 0, 0x100, 0x10, 0, "");
+  info.set_prev_map(&prev_info);
+  info.set_prev_real_map(&prev_info);
 
   // No preconditions met, change each one until it should set the elf start
   // offset to zero.
-  info->set_elf_offset(0);
-  info->set_elf_start_offset(0);
-  info->set_memory_backed_elf(false);
-  memory.reset(info->CreateMemory(process_memory_));
+  info.set_elf_offset(0);
+  info.set_elf_start_offset(0);
+  info.set_memory_backed_elf(false);
+  memory.reset(info.CreateMemory(process_memory_));
   ASSERT_TRUE(memory.get() != nullptr);
-  EXPECT_FALSE(info->memory_backed_elf());
-  ASSERT_EQ(0x100U, info->elf_offset());
-  EXPECT_EQ(0U, info->elf_start_offset());
+  EXPECT_FALSE(info.memory_backed_elf());
+  ASSERT_EQ(0x100U, info.elf_offset());
+  EXPECT_EQ(0x100U, info.elf_start_offset());
 
-  prev_info->set_offset(0);
-  info->set_elf_offset(0);
-  info->set_elf_start_offset(0);
-  info->set_memory_backed_elf(false);
-  memory.reset(info->CreateMemory(process_memory_));
+  prev_info.set_offset(0);
+  info.set_elf_offset(0);
+  info.set_elf_start_offset(0);
+  info.set_memory_backed_elf(false);
+  memory.reset(info.CreateMemory(process_memory_));
   ASSERT_TRUE(memory.get() != nullptr);
-  EXPECT_FALSE(info->memory_backed_elf());
-  ASSERT_EQ(0x100U, info->elf_offset());
-  EXPECT_EQ(0U, info->elf_start_offset());
+  EXPECT_FALSE(info.memory_backed_elf());
+  ASSERT_EQ(0x100U, info.elf_offset());
+  EXPECT_EQ(0x100U, info.elf_start_offset());
 
-  prev_info->set_flags(PROT_READ);
-  info->set_elf_offset(0);
-  info->set_elf_start_offset(0);
-  info->set_memory_backed_elf(false);
-  memory.reset(info->CreateMemory(process_memory_));
+  prev_info.set_flags(PROT_READ);
+  info.set_elf_offset(0);
+  info.set_elf_start_offset(0);
+  info.set_memory_backed_elf(false);
+  memory.reset(info.CreateMemory(process_memory_));
   ASSERT_TRUE(memory.get() != nullptr);
-  EXPECT_FALSE(info->memory_backed_elf());
-  ASSERT_EQ(0x100U, info->elf_offset());
-  EXPECT_EQ(0U, info->elf_start_offset());
+  EXPECT_FALSE(info.memory_backed_elf());
+  ASSERT_EQ(0x100U, info.elf_offset());
+  EXPECT_EQ(0x100U, info.elf_start_offset());
 
-  prev_info->set_name(info->name());
-  info->set_elf_offset(0);
-  info->set_elf_start_offset(0);
-  info->set_memory_backed_elf(false);
-  memory.reset(info->CreateMemory(process_memory_));
+  prev_info.set_name(info.name());
+  info.set_elf_offset(0);
+  info.set_elf_start_offset(0);
+  info.set_memory_backed_elf(false);
+  memory.reset(info.CreateMemory(process_memory_));
   ASSERT_TRUE(memory.get() != nullptr);
-  EXPECT_FALSE(info->memory_backed_elf());
-  ASSERT_EQ(0x100U, info->elf_offset());
-  EXPECT_EQ(0U, info->elf_start_offset());
+  EXPECT_FALSE(info.memory_backed_elf());
+  ASSERT_EQ(0x100U, info.elf_offset());
+  EXPECT_EQ(0U, info.elf_start_offset());
 }
 
 // Verify that if the offset is non-zero and there is an elf at that
 // offset, that only part of the file is used.
 TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file) {
-  auto info = MapInfo::Create(0x100, 0x200, 0x1000, 0, elf_at_1000_.path);
+  MapInfo info(nullptr, nullptr, 0x100, 0x200, 0x1000, 0, elf_at_1000_.path);
 
-  std::unique_ptr<Memory> memory(info->CreateMemory(process_memory_));
+  std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
   ASSERT_TRUE(memory.get() != nullptr);
-  EXPECT_FALSE(info->memory_backed_elf());
-  ASSERT_EQ(0U, info->elf_offset());
-  EXPECT_EQ(0x1000U, info->elf_start_offset());
+  EXPECT_FALSE(info.memory_backed_elf());
+  ASSERT_EQ(0U, info.elf_offset());
+  EXPECT_EQ(0x1000U, info.elf_start_offset());
 
   // Read the valid part of the file.
   std::vector<uint8_t> buffer(0x100);
@@ -202,13 +203,13 @@
 // embedded elf is bigger than the initial map, the new object is larger
 // than the original map size. Do this for a 32 bit elf and a 64 bit elf.
 TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file_whole_elf32) {
-  auto info = MapInfo::Create(0x5000, 0x6000, 0x1000, 0, elf32_at_map_.path);
+  MapInfo info(nullptr, nullptr, 0x5000, 0x6000, 0x1000, 0, elf32_at_map_.path);
 
-  std::unique_ptr<Memory> memory(info->CreateMemory(process_memory_));
+  std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
   ASSERT_TRUE(memory.get() != nullptr);
-  EXPECT_FALSE(info->memory_backed_elf());
-  ASSERT_EQ(0U, info->elf_offset());
-  EXPECT_EQ(0x1000U, info->elf_start_offset());
+  EXPECT_FALSE(info.memory_backed_elf());
+  ASSERT_EQ(0U, info.elf_offset());
+  EXPECT_EQ(0x1000U, info.elf_start_offset());
 
   // Verify the memory is a valid elf.
   uint8_t e_ident[SELFMAG + 1];
@@ -220,13 +221,13 @@
 }
 
 TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file_whole_elf64) {
-  auto info = MapInfo::Create(0x7000, 0x8000, 0x2000, 0, elf64_at_map_.path);
+  MapInfo info(nullptr, nullptr, 0x7000, 0x8000, 0x2000, 0, elf64_at_map_.path);
 
-  std::unique_ptr<Memory> memory(info->CreateMemory(process_memory_));
+  std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
   ASSERT_TRUE(memory.get() != nullptr);
-  EXPECT_FALSE(info->memory_backed_elf());
-  ASSERT_EQ(0U, info->elf_offset());
-  EXPECT_EQ(0x2000U, info->elf_start_offset());
+  EXPECT_FALSE(info.memory_backed_elf());
+  ASSERT_EQ(0U, info.elf_offset());
+  EXPECT_EQ(0x2000U, info.elf_start_offset());
 
   // Verify the memory is a valid elf.
   uint8_t e_ident[SELFMAG + 1];
@@ -243,14 +244,14 @@
   // be returned if the file mapping fails, but the device check is incorrect.
   std::vector<uint8_t> buffer(1024);
   uint64_t start = reinterpret_cast<uint64_t>(buffer.data());
-  auto info = MapInfo::Create(start, start + buffer.size(), 0, 0x8000, "/dev/something");
+  MapInfo info(nullptr, nullptr, start, start + buffer.size(), 0, 0x8000, "/dev/something");
 
-  std::unique_ptr<Memory> memory(info->CreateMemory(process_memory_));
+  std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
   ASSERT_TRUE(memory.get() == nullptr);
 }
 
 TEST_F(MapInfoCreateMemoryTest, process_memory) {
-  auto info = MapInfo::Create(0x2000, 0x3000, 0, PROT_READ, "");
+  MapInfo info(nullptr, nullptr, 0x2000, 0x3000, 0, PROT_READ, "");
 
   Elf32_Ehdr ehdr = {};
   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
@@ -262,11 +263,11 @@
   for (size_t i = sizeof(ehdr); i < buffer.size(); i++) {
     buffer[i] = i % 256;
   }
-  memory_->SetMemory(info->start(), buffer.data(), buffer.size());
+  memory_->SetMemory(info.start(), buffer.data(), buffer.size());
 
-  std::unique_ptr<Memory> memory(info->CreateMemory(process_memory_));
+  std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
   ASSERT_TRUE(memory.get() != nullptr);
-  EXPECT_TRUE(info->memory_backed_elf());
+  EXPECT_TRUE(info.memory_backed_elf());
 
   memset(buffer.data(), 0, buffer.size());
   ASSERT_TRUE(memory->ReadFully(0, buffer.data(), buffer.size()));
@@ -293,7 +294,7 @@
   // Set the memory in the r-x map.
   memory_->SetMemoryBlock(0x3000, 0x2000, 0x5d);
 
-  auto map_info = maps.Find(0x3000).get();
+  MapInfo* map_info = maps.Find(0x3000);
   ASSERT_TRUE(map_info != nullptr);
 
   std::unique_ptr<Memory> mem(map_info->CreateMemory(process_memory_));
@@ -340,7 +341,7 @@
   memory_->SetMemoryBlock(0x3000 + sizeof(ehdr), 0x4000 - sizeof(ehdr), 0x34);
   memory_->SetMemoryBlock(0x4000, 0x1000, 0x43);
 
-  auto map_info = maps.Find(0x4000).get();
+  MapInfo* map_info = maps.Find(0x4000);
   ASSERT_TRUE(map_info != nullptr);
 
   std::unique_ptr<Memory> mem(map_info->CreateMemory(process_memory_));
@@ -366,44 +367,13 @@
   }
 }
 
-TEST_F(MapInfoCreateMemoryTest, valid_single_rx_non_zero_offset) {
-  Maps maps;
-  maps.Add(0x3000, 0x5000, 0xa000, PROT_READ | PROT_EXEC, "/only/in/memory.apk", 0);
-
-  Elf32_Ehdr ehdr = {};
-  TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
-
-  // Setup an elf at offset 0x3000 in memory..
-  memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr));
-  memory_->SetMemoryBlock(0x3000 + sizeof(ehdr), 0x5000 - sizeof(ehdr), 0x34);
-
-  auto map_info = maps.Find(0x3000);
-  ASSERT_TRUE(map_info != nullptr);
-
-  std::unique_ptr<Memory> mem(map_info->CreateMemory(process_memory_));
-  ASSERT_TRUE(mem.get() != nullptr);
-  EXPECT_TRUE(map_info->memory_backed_elf());
-  EXPECT_EQ(0UL, map_info->elf_offset());
-  EXPECT_EQ(0xa000UL, map_info->offset());
-  EXPECT_EQ(0xa000UL, map_info->elf_start_offset());
-
-  // Verify that reading values from this memory works properly.
-  std::vector<uint8_t> buffer(0x3000);
-  size_t bytes = mem->Read(0, buffer.data(), buffer.size());
-  ASSERT_EQ(0x2000UL, bytes);
-  ASSERT_EQ(0, memcmp(&ehdr, buffer.data(), sizeof(ehdr)));
-  for (size_t i = sizeof(ehdr); i < bytes; i++) {
-    ASSERT_EQ(0x34, buffer[i]) << "Failed at byte " << i;
-  }
-}
-
 TEST_F(MapInfoCreateMemoryTest, rosegment_from_file) {
   Maps maps;
   maps.Add(0x500, 0x600, 0, PROT_READ, "something_else", 0);
   maps.Add(0x1000, 0x2000, 0x1000, PROT_READ, elf_at_1000_.path, 0);
   maps.Add(0x2000, 0x3000, 0x2000, PROT_READ | PROT_EXEC, elf_at_1000_.path, 0);
 
-  auto map_info = maps.Find(0x2000).get();
+  MapInfo* map_info = maps.Find(0x2000);
   ASSERT_TRUE(map_info != nullptr);
 
   // Set up the size
@@ -455,7 +425,7 @@
   // Set the memory in the r-x map.
   memory_->SetMemoryBlock(0x3000, 0x2000, 0x5d);
 
-  auto map_info = maps.Find(0x3000).get();
+  MapInfo* map_info = maps.Find(0x3000);
   ASSERT_TRUE(map_info != nullptr);
 
   std::unique_ptr<Memory> mem(map_info->CreateMemory(process_memory_));
diff --git a/libunwindstack/tests/MapInfoGetBuildIDTest.cpp b/libunwindstack/tests/MapInfoGetBuildIDTest.cpp
index 4877c68..e123d0e 100644
--- a/libunwindstack/tests/MapInfoGetBuildIDTest.cpp
+++ b/libunwindstack/tests/MapInfoGetBuildIDTest.cpp
@@ -36,8 +36,7 @@
 
 #include "ElfFake.h"
 #include "ElfTestUtils.h"
-#include "utils/MemoryFake.h"
-#include "utils/OfflineUnwindUtils.h"
+#include "MemoryFake.h"
 
 namespace unwindstack {
 
@@ -51,7 +50,8 @@
     elf_interface_ = new ElfInterfaceFake(memory_);
     elf_->FakeSetInterface(elf_interface_);
     elf_container_.reset(elf_);
-    map_info_ = MapInfo::Create(0x1000, 0x20000, 0, PROT_READ | PROT_WRITE, tf_->path);
+    map_info_.reset(
+        new MapInfo(nullptr, nullptr, 0x1000, 0x20000, 0, PROT_READ | PROT_WRITE, tf_->path));
   }
 
   void TearDown() override { delete memory_; }
@@ -62,15 +62,15 @@
   ElfFake* elf_;
   ElfInterfaceFake* elf_interface_;
   std::unique_ptr<ElfFake> elf_container_;
-  std::shared_ptr<MapInfo> map_info_;
+  std::unique_ptr<MapInfo> map_info_;
   std::unique_ptr<TemporaryFile> tf_;
 };
 
 TEST_F(MapInfoGetBuildIDTest, no_elf_and_no_valid_elf_in_memory) {
-  auto info = MapInfo::Create(0x1000, 0x2000, 0, PROT_READ, "");
+  MapInfo info(nullptr, nullptr, 0x1000, 0x2000, 0, PROT_READ, "");
 
-  EXPECT_EQ("", info->GetBuildID());
-  EXPECT_EQ("", info->GetPrintableBuildID());
+  EXPECT_EQ("", info.GetBuildID());
+  EXPECT_EQ("", info.GetPrintableBuildID());
 }
 
 TEST_F(MapInfoGetBuildIDTest, from_elf) {
@@ -197,16 +197,9 @@
 }
 
 TEST_F(MapInfoGetBuildIDTest, real_elf) {
-  auto map_info = MapInfo::Create(0x1000, 0x20000, 0, PROT_READ | PROT_WRITE,
-                                  GetOfflineFilesDirectory() + "empty_arm64/libc.so");
-  EXPECT_EQ("6df0590c4920f4c7b9f34fe833f37d54", map_info->GetPrintableBuildID());
-}
-
-TEST_F(MapInfoGetBuildIDTest, in_device_map) {
-  auto map_info =
-      MapInfo::Create(0x1000, 0x20000, 0, PROT_READ | PROT_WRITE | MAPS_FLAGS_DEVICE_MAP,
-                      GetOfflineFilesDirectory() + "empty_arm64/libc.so");
-  EXPECT_EQ("", map_info->GetPrintableBuildID());
+  MapInfo map_info(nullptr, nullptr, 0x1000, 0x20000, 0, PROT_READ | PROT_WRITE,
+                   TestGetFileDirectory() + "offline/empty_arm64/libc.so");
+  EXPECT_EQ("6df0590c4920f4c7b9f34fe833f37d54", map_info.GetPrintableBuildID());
 }
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/MapInfoGetElfTest.cpp b/libunwindstack/tests/MapInfoGetElfTest.cpp
index 79f470f..944f894 100644
--- a/libunwindstack/tests/MapInfoGetElfTest.cpp
+++ b/libunwindstack/tests/MapInfoGetElfTest.cpp
@@ -37,7 +37,7 @@
 #include <unwindstack/Memory.h>
 
 #include "ElfTestUtils.h"
-#include "utils/MemoryFake.h"
+#include "MemoryFake.h"
 
 namespace unwindstack {
 
@@ -59,7 +59,7 @@
     ehdr->e_shnum = 4;
   }
 
-  void InitMapInfo(std::vector<std::shared_ptr<MapInfo>>& maps, bool in_memory);
+  void InitMapInfo(std::vector<std::unique_ptr<MapInfo>>& maps, bool in_memory);
 
   const size_t kMapSize = 4096;
 
@@ -70,40 +70,42 @@
 };
 
 TEST_F(MapInfoGetElfTest, invalid) {
-  auto info = MapInfo::Create(0x1000, 0x2000, 0, PROT_READ, "");
+  MapInfo info(nullptr, nullptr, 0x1000, 0x2000, 0, PROT_READ, "");
 
   // The map is empty, but this should still create an invalid elf object.
-  Elf* elf = info->GetElf(process_memory_, ARCH_ARM);
+  Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
   ASSERT_TRUE(elf != nullptr);
   ASSERT_FALSE(elf->valid());
 }
 
 TEST_F(MapInfoGetElfTest, valid32) {
+  MapInfo info(nullptr, nullptr, 0x3000, 0x4000, 0, PROT_READ, "");
+
   Elf32_Ehdr ehdr;
   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
   memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr));
 
-  auto info = MapInfo::Create(0x3000, 0x4000, 0, PROT_READ, "");
-  Elf* elf = info->GetElf(process_memory_, ARCH_ARM);
+  Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
   ASSERT_TRUE(elf != nullptr);
   ASSERT_TRUE(elf->valid());
   EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
   EXPECT_EQ(ELFCLASS32, elf->class_type());
 
   // Now verify that an empty process memory returns an invalid elf object.
-  info->set_elf(nullptr);
-  elf = info->GetElf(std::shared_ptr<Memory>(), ARCH_ARM);
+  info.set_elf(nullptr);
+  elf = info.GetElf(std::shared_ptr<Memory>(), ARCH_ARM);
   ASSERT_TRUE(elf != nullptr);
   ASSERT_FALSE(elf->valid());
 }
 
 TEST_F(MapInfoGetElfTest, valid64) {
+  MapInfo info(nullptr, nullptr, 0x8000, 0x9000, 0, PROT_READ, "");
+
   Elf64_Ehdr ehdr;
   TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
   memory_->SetMemory(0x8000, &ehdr, sizeof(ehdr));
 
-  auto info = MapInfo::Create(0x8000, 0x9000, 0, PROT_READ, "");
-  Elf* elf = info->GetElf(process_memory_, ARCH_ARM64);
+  Elf* elf = info.GetElf(process_memory_, ARCH_ARM64);
   ASSERT_TRUE(elf != nullptr);
   ASSERT_TRUE(elf->valid());
   EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
@@ -111,24 +113,26 @@
 }
 
 TEST_F(MapInfoGetElfTest, invalid_arch_mismatch) {
+  MapInfo info(nullptr, nullptr, 0x3000, 0x4000, 0, PROT_READ, "");
+
   Elf32_Ehdr ehdr;
   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
   memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr));
 
-  auto info = MapInfo::Create(0x3000, 0x4000, 0, PROT_READ, "");
-  Elf* elf = info->GetElf(process_memory_, ARCH_X86);
+  Elf* elf = info.GetElf(process_memory_, ARCH_X86);
   ASSERT_TRUE(elf != nullptr);
   ASSERT_FALSE(elf->valid());
 }
 
 TEST_F(MapInfoGetElfTest, gnu_debugdata_init32) {
+  MapInfo info(nullptr, nullptr, 0x2000, 0x3000, 0, PROT_READ, "");
+
   TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, true,
                                                [&](uint64_t offset, const void* ptr, size_t size) {
                                                  memory_->SetMemory(0x2000 + offset, ptr, size);
                                                });
 
-  auto info = MapInfo::Create(0x2000, 0x3000, 0, PROT_READ, "");
-  Elf* elf = info->GetElf(process_memory_, ARCH_ARM);
+  Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
   ASSERT_TRUE(elf != nullptr);
   ASSERT_TRUE(elf->valid());
   EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
@@ -137,13 +141,14 @@
 }
 
 TEST_F(MapInfoGetElfTest, gnu_debugdata_init64) {
+  MapInfo info(nullptr, nullptr, 0x5000, 0x8000, 0, PROT_READ, "");
+
   TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, true,
                                                [&](uint64_t offset, const void* ptr, size_t size) {
                                                  memory_->SetMemory(0x5000 + offset, ptr, size);
                                                });
 
-  auto info = MapInfo::Create(0x5000, 0x8000, 0, PROT_READ, "");
-  Elf* elf = info->GetElf(process_memory_, ARCH_ARM64);
+  Elf* elf = info.GetElf(process_memory_, ARCH_ARM64);
   ASSERT_TRUE(elf != nullptr);
   ASSERT_TRUE(elf->valid());
   EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
@@ -152,25 +157,26 @@
 }
 
 TEST_F(MapInfoGetElfTest, end_le_start) {
+  MapInfo info(nullptr, nullptr, 0x1000, 0x1000, 0, PROT_READ, elf_.path);
+
   Elf32_Ehdr ehdr;
   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
   ASSERT_TRUE(android::base::WriteFully(elf_.fd, &ehdr, sizeof(ehdr)));
 
-  auto info = MapInfo::Create(0x1000, 0x1000, 0, PROT_READ, elf_.path);
-  Elf* elf = info->GetElf(process_memory_, ARCH_ARM);
+  Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
   ASSERT_TRUE(elf != nullptr);
   ASSERT_FALSE(elf->valid());
 
-  info->set_elf(nullptr);
-  info->set_end(0xfff);
-  elf = info->GetElf(process_memory_, ARCH_ARM);
+  info.set_elf(nullptr);
+  info.set_end(0xfff);
+  elf = info.GetElf(process_memory_, ARCH_ARM);
   ASSERT_TRUE(elf != nullptr);
   ASSERT_FALSE(elf->valid());
 
   // Make sure this test is valid.
-  info->set_elf(nullptr);
-  info->set_end(0x2000);
-  elf = info->GetElf(process_memory_, ARCH_ARM);
+  info.set_elf(nullptr);
+  info.set_end(0x2000);
+  elf = info.GetElf(process_memory_, ARCH_ARM);
   ASSERT_TRUE(elf != nullptr);
   ASSERT_TRUE(elf->valid());
 }
@@ -178,6 +184,8 @@
 // Verify that if the offset is non-zero but there is no elf at the offset,
 // that the full file is used.
 TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_full_file) {
+  MapInfo info(nullptr, nullptr, 0x1000, 0x2000, 0x100, PROT_READ, elf_.path);
+
   std::vector<uint8_t> buffer(0x1000);
   memset(buffer.data(), 0, buffer.size());
   Elf32_Ehdr ehdr;
@@ -185,12 +193,11 @@
   memcpy(buffer.data(), &ehdr, sizeof(ehdr));
   ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
 
-  auto info = MapInfo::Create(0x1000, 0x2000, 0x100, PROT_READ, elf_.path);
-  Elf* elf = info->GetElf(process_memory_, ARCH_ARM);
+  Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
   ASSERT_TRUE(elf != nullptr);
   ASSERT_TRUE(elf->valid());
   ASSERT_TRUE(elf->memory() != nullptr);
-  ASSERT_EQ(0x100U, info->elf_offset());
+  ASSERT_EQ(0x100U, info.elf_offset());
 
   // Read the entire file.
   memset(buffer.data(), 0, buffer.size());
@@ -206,20 +213,20 @@
 // Verify that if the offset is non-zero and there is an elf at that
 // offset, that only part of the file is used.
 TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file) {
-  auto info = MapInfo::Create(0x1000, 0x2000, 0x2000, PROT_READ, elf_.path);
+  MapInfo info(nullptr, nullptr, 0x1000, 0x2000, 0x2000, PROT_READ, elf_.path);
 
   std::vector<uint8_t> buffer(0x4000);
   memset(buffer.data(), 0, buffer.size());
   Elf32_Ehdr ehdr;
   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
-  memcpy(&buffer[info->offset()], &ehdr, sizeof(ehdr));
+  memcpy(&buffer[info.offset()], &ehdr, sizeof(ehdr));
   ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
 
-  Elf* elf = info->GetElf(process_memory_, ARCH_ARM);
+  Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
   ASSERT_TRUE(elf != nullptr);
   ASSERT_TRUE(elf->valid());
   ASSERT_TRUE(elf->memory() != nullptr);
-  ASSERT_EQ(0U, info->elf_offset());
+  ASSERT_EQ(0U, info.elf_offset());
 
   // Read the valid part of the file.
   ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), 0x1000));
@@ -236,7 +243,7 @@
 // embedded elf is bigger than the initial map, the new object is larger
 // than the original map size. Do this for a 32 bit elf and a 64 bit elf.
 TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf32) {
-  auto info = MapInfo::Create(0x5000, 0x6000, 0x1000, PROT_READ, elf_.path);
+  MapInfo info(nullptr, nullptr, 0x5000, 0x6000, 0x1000, PROT_READ, elf_.path);
 
   std::vector<uint8_t> buffer(0x4000);
   memset(buffer.data(), 0, buffer.size());
@@ -245,14 +252,14 @@
   ehdr.e_shoff = 0x2000;
   ehdr.e_shentsize = sizeof(Elf32_Shdr) + 100;
   ehdr.e_shnum = 4;
-  memcpy(&buffer[info->offset()], &ehdr, sizeof(ehdr));
+  memcpy(&buffer[info.offset()], &ehdr, sizeof(ehdr));
   ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
 
-  Elf* elf = info->GetElf(process_memory_, ARCH_ARM);
+  Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
   ASSERT_TRUE(elf != nullptr);
   ASSERT_TRUE(elf->valid());
   ASSERT_TRUE(elf->memory() != nullptr);
-  ASSERT_EQ(0U, info->elf_offset());
+  ASSERT_EQ(0U, info.elf_offset());
 
   // Verify the memory is a valid elf.
   memset(buffer.data(), 0, buffer.size());
@@ -264,7 +271,7 @@
 }
 
 TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf64) {
-  auto info = MapInfo::Create(0x7000, 0x8000, 0x1000, PROT_READ, elf_.path);
+  MapInfo info(nullptr, nullptr, 0x7000, 0x8000, 0x1000, PROT_READ, elf_.path);
 
   std::vector<uint8_t> buffer(0x4000);
   memset(buffer.data(), 0, buffer.size());
@@ -273,45 +280,14 @@
   ehdr.e_shoff = 0x2000;
   ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
   ehdr.e_shnum = 4;
-  memcpy(&buffer[info->offset()], &ehdr, sizeof(ehdr));
+  memcpy(&buffer[info.offset()], &ehdr, sizeof(ehdr));
   ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
 
-  Elf* elf = info->GetElf(process_memory_, ARCH_ARM64);
+  Elf* elf = info.GetElf(process_memory_, ARCH_ARM64);
   ASSERT_TRUE(elf != nullptr);
   ASSERT_TRUE(elf->valid());
   ASSERT_TRUE(elf->memory() != nullptr);
-  ASSERT_EQ(0U, info->elf_offset());
-
-  // Verify the memory is a valid elf.
-  memset(buffer.data(), 0, buffer.size());
-  ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), 0x1000));
-  ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
-
-  // Read past the end of what would normally be the size of the map.
-  ASSERT_TRUE(elf->memory()->ReadFully(0x1000, buffer.data(), 1));
-}
-
-// Verify that if the offset is non-zero and there is an elf at that
-// offset, that only part of the file is used. Further verify that if the
-// the initial map is smaller than elf header size, we can still read the elf.
-TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf64_small_map_range) {
-  auto info = MapInfo::Create(0x7000, 0x7004, 0x1000, PROT_READ, elf_.path);
-
-  std::vector<uint8_t> buffer(0x4000);
-  memset(buffer.data(), 0, buffer.size());
-  Elf64_Ehdr ehdr;
-  TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
-  ehdr.e_shoff = 0x2000;
-  ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
-  ehdr.e_shnum = 4;
-  memcpy(&buffer[info->offset()], &ehdr, sizeof(ehdr));
-  ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
-
-  Elf* elf = info->GetElf(process_memory_, ARCH_ARM64);
-  ASSERT_TRUE(elf != nullptr);
-  ASSERT_TRUE(elf->valid());
-  ASSERT_TRUE(elf->memory() != nullptr);
-  ASSERT_EQ(0U, info->elf_offset());
+  ASSERT_EQ(0U, info.elf_offset());
 
   // Verify the memory is a valid elf.
   memset(buffer.data(), 0, buffer.size());
@@ -323,6 +299,9 @@
 }
 
 TEST_F(MapInfoGetElfTest, check_device_maps) {
+  MapInfo info(nullptr, nullptr, 0x7000, 0x8000, 0x1000, PROT_READ | MAPS_FLAGS_DEVICE_MAP,
+               "/dev/something");
+
   // Create valid elf data in process memory for this to verify that only
   // the name is causing invalid elf data.
   Elf64_Ehdr ehdr;
@@ -332,22 +311,20 @@
   ehdr.e_shnum = 0;
   memory_->SetMemory(0x7000, &ehdr, sizeof(ehdr));
 
-  auto info =
-      MapInfo::Create(0x7000, 0x8000, 0x1000, PROT_READ | MAPS_FLAGS_DEVICE_MAP, "/dev/something");
-  Elf* elf = info->GetElf(process_memory_, ARCH_X86_64);
+  Elf* elf = info.GetElf(process_memory_, ARCH_X86_64);
   ASSERT_TRUE(elf != nullptr);
   ASSERT_FALSE(elf->valid());
 
   // Set the name to nothing to verify that it still fails.
-  info->set_elf(nullptr);
-  info->set_name("");
-  elf = info->GetElf(process_memory_, ARCH_X86_64);
+  info.set_elf(nullptr);
+  info.set_name("");
+  elf = info.GetElf(process_memory_, ARCH_X86_64);
   ASSERT_FALSE(elf->valid());
 
   // Change the flags and verify the elf is valid now.
-  info->set_elf(nullptr);
-  info->set_flags(PROT_READ);
-  elf = info->GetElf(process_memory_, ARCH_X86_64);
+  info.set_elf(nullptr);
+  info.set_flags(PROT_READ);
+  elf = info.GetElf(process_memory_, ARCH_X86_64);
   ASSERT_TRUE(elf->valid());
 }
 
@@ -368,17 +345,17 @@
   wait = true;
   // Create all of the threads and have them do the GetElf at the same time
   // to make it likely that a race will occur.
-  auto info = MapInfo::Create(0x7000, 0x8000, 0x1000, PROT_READ, "");
+  MapInfo info(nullptr, nullptr, 0x7000, 0x8000, 0x1000, PROT_READ, "");
   for (size_t i = 0; i < kNumConcurrentThreads; i++) {
     std::thread* thread = new std::thread([i, this, &wait, &info, &elf_in_threads]() {
       while (wait)
         ;
-      Elf* elf = info->GetElf(process_memory_, ARCH_X86_64);
+      Elf* elf = info.GetElf(process_memory_, ARCH_X86_64);
       elf_in_threads[i] = elf;
     });
     threads.push_back(thread);
   }
-  ASSERT_TRUE(info->elf() == nullptr);
+  ASSERT_TRUE(info.elf() == nullptr);
 
   // Set them all going and wait for the threads to finish.
   wait = false;
@@ -388,7 +365,7 @@
   }
 
   // Now verify that all of the elf files are exactly the same and valid.
-  Elf* elf = info->elf().get();
+  Elf* elf = info.elf().get();
   ASSERT_TRUE(elf != nullptr);
   EXPECT_TRUE(elf->valid());
   for (size_t i = 0; i < kNumConcurrentThreads; i++) {
@@ -398,23 +375,24 @@
 
 // Verify that previous maps don't automatically get the same elf object.
 TEST_F(MapInfoGetElfTest, prev_map_elf_not_set) {
-  auto info1 = MapInfo::Create(0x1000, 0x2000, 0, PROT_READ, "/not/present");
-  auto info2 = MapInfo::Create(info1, 0x2000, 0x3000, 0, PROT_READ, elf_.path);
+  MapInfo info1(nullptr, nullptr, 0x1000, 0x2000, 0, PROT_READ, "/not/present");
+  MapInfo info2(&info1, &info1, 0x2000, 0x3000, 0, PROT_READ, elf_.path);
 
   Elf32_Ehdr ehdr;
   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
   memory_->SetMemory(0x2000, &ehdr, sizeof(ehdr));
-  Elf* elf = info2->GetElf(process_memory_, ARCH_ARM);
+  Elf* elf = info2.GetElf(process_memory_, ARCH_ARM);
   ASSERT_TRUE(elf != nullptr);
   ASSERT_TRUE(elf->valid());
 
-  ASSERT_NE(elf, info1->GetElf(process_memory_, ARCH_ARM));
+  ASSERT_NE(elf, info1.GetElf(process_memory_, ARCH_ARM));
 }
 
-void MapInfoGetElfTest::InitMapInfo(std::vector<std::shared_ptr<MapInfo>>& maps, bool in_memory) {
+void MapInfoGetElfTest::InitMapInfo(std::vector<std::unique_ptr<MapInfo>>& maps, bool in_memory) {
   maps.resize(2);
-  maps[0] = MapInfo::Create(0x1000, 0x2000, 0, PROT_READ, elf_.path);
-  maps[1] = MapInfo::Create(maps[0], 0x2000, 0x3000, 0x1000, PROT_READ | PROT_EXEC, elf_.path);
+  maps[0].reset(new MapInfo(nullptr, nullptr, 0x1000, 0x2000, 0, PROT_READ, elf_.path));
+  maps[1].reset(new MapInfo(maps[0].get(), maps[0].get(), 0x2000, 0x3000, 0x1000,
+                            PROT_READ | PROT_EXEC, elf_.path));
 
   Elf32_Ehdr ehdr;
   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
@@ -428,7 +406,7 @@
 // Verify that a read-only map followed by a read-execute map will result
 // in the same elf object in both maps.
 TEST_F(MapInfoGetElfTest, read_only_followed_by_read_exec_share_elf_exec_first) {
-  std::vector<std::shared_ptr<MapInfo>> maps;
+  std::vector<std::unique_ptr<MapInfo>> maps;
 
   // First use in memory maps.
   InitMapInfo(maps, true);
@@ -461,7 +439,7 @@
 // Verify that a read-only map followed by a read-execute map will result
 // in the same elf object in both maps.
 TEST_F(MapInfoGetElfTest, read_only_followed_by_read_exec_share_elf_read_only_first) {
-  std::vector<std::shared_ptr<MapInfo>> maps;
+  std::vector<std::unique_ptr<MapInfo>> maps;
 
   // First use in memory maps.
   InitMapInfo(maps, true);
@@ -494,18 +472,18 @@
 // Verify that a read-only map followed by an empty map, then followed by
 // a read-execute map will result in the same elf object in both maps.
 TEST_F(MapInfoGetElfTest, read_only_followed_by_empty_then_read_exec_share_elf) {
-  auto r_info = MapInfo::Create(0x1000, 0x2000, 0, PROT_READ, elf_.path);
-  auto empty = MapInfo::Create(r_info, 0x2000, 0x3000, 0, 0, "");
-  auto rw_info = MapInfo::Create(empty, 0x3000, 0x4000, 0x2000, PROT_READ | PROT_EXEC, elf_.path);
+  MapInfo r_info(nullptr, nullptr, 0x1000, 0x2000, 0, PROT_READ, elf_.path);
+  MapInfo empty(&r_info, &r_info, 0x2000, 0x3000, 0, 0, "");
+  MapInfo rw_info(&empty, &r_info, 0x3000, 0x4000, 0x2000, PROT_READ | PROT_EXEC, elf_.path);
 
   Elf32_Ehdr ehdr;
   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
   memory_->SetMemory(0x1000, &ehdr, sizeof(ehdr));
-  Elf* elf = rw_info->GetElf(process_memory_, ARCH_ARM);
+  Elf* elf = rw_info.GetElf(process_memory_, ARCH_ARM);
   ASSERT_TRUE(elf != nullptr);
   ASSERT_TRUE(elf->valid());
 
-  ASSERT_EQ(elf, r_info->GetElf(process_memory_, ARCH_ARM));
+  ASSERT_EQ(elf, r_info.GetElf(process_memory_, ARCH_ARM));
 }
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp b/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp
index a0aca4f..5ddf1de 100644
--- a/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp
+++ b/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp
@@ -39,7 +39,7 @@
 
 #include "ElfFake.h"
 #include "ElfTestUtils.h"
-#include "utils/MemoryFake.h"
+#include "MemoryFake.h"
 
 namespace unwindstack {
 
@@ -50,7 +50,7 @@
     process_memory_.reset(memory_);
     elf_ = new ElfFake(new MemoryFake);
     elf_container_.reset(elf_);
-    map_info_ = MapInfo::Create(0x1000, 0x20000, 0, PROT_READ | PROT_WRITE, "");
+    map_info_.reset(new MapInfo(nullptr, nullptr, 0x1000, 0x20000, 0, PROT_READ | PROT_WRITE, ""));
   }
 
   void MultipleThreadTest(uint64_t expected_load_bias);
@@ -59,13 +59,13 @@
   MemoryFake* memory_;
   ElfFake* elf_;
   std::unique_ptr<ElfFake> elf_container_;
-  std::shared_ptr<MapInfo> map_info_;
+  std::unique_ptr<MapInfo> map_info_;
 };
 
 TEST_F(MapInfoGetLoadBiasTest, no_elf_and_no_valid_elf_in_memory) {
-  auto info = MapInfo::Create(0x1000, 0x2000, 0, PROT_READ, "");
+  MapInfo info(nullptr, nullptr, 0x1000, 0x2000, 0, PROT_READ, "");
 
-  EXPECT_EQ(0U, info->GetLoadBias(process_memory_));
+  EXPECT_EQ(0U, info.GetLoadBias(process_memory_));
 }
 
 TEST_F(MapInfoGetLoadBiasTest, load_bias_cached_from_elf) {
@@ -84,7 +84,7 @@
   elf_->FakeSetLoadBias(0);
   EXPECT_EQ(0U, map_info_->GetLoadBias(process_memory_));
 
-  map_info_->set_load_bias(UINT64_MAX);
+  map_info_->set_load_bias(INT64_MAX);
   elf_->FakeSetLoadBias(0x1000);
   EXPECT_EQ(0x1000U, map_info_->GetLoadBias(process_memory_));
 }
diff --git a/libunwindstack/tests/MapInfoTest.cpp b/libunwindstack/tests/MapInfoTest.cpp
index 9cfbb44..7ba9471 100644
--- a/libunwindstack/tests/MapInfoTest.cpp
+++ b/libunwindstack/tests/MapInfoTest.cpp
@@ -15,7 +15,6 @@
  */
 
 #include <stdint.h>
-#include <sys/mman.h>
 
 #include <thread>
 
@@ -29,98 +28,34 @@
 namespace unwindstack {
 
 TEST(MapInfoTest, maps_constructor_const_char) {
-  auto prev_map = MapInfo::Create(0, 0, 0, 0, "");
-  auto map_info = MapInfo::Create(prev_map, 1, 2, 3, 4, "map");
+  MapInfo prev_map(nullptr, nullptr, 0, 0, 0, 0, "");
+  MapInfo map_info(&prev_map, &prev_map, 1, 2, 3, 4, "map");
 
-  EXPECT_EQ(prev_map.get(), map_info->prev_map().get());
-  EXPECT_EQ(1UL, map_info->start());
-  EXPECT_EQ(2UL, map_info->end());
-  EXPECT_EQ(3UL, map_info->offset());
-  EXPECT_EQ(4UL, map_info->flags());
-  EXPECT_EQ("map", map_info->name());
-  EXPECT_EQ(UINT64_MAX, map_info->load_bias());
-  EXPECT_EQ(0UL, map_info->elf_offset());
-  EXPECT_TRUE(map_info->elf().get() == nullptr);
+  EXPECT_EQ(&prev_map, map_info.prev_map());
+  EXPECT_EQ(1UL, map_info.start());
+  EXPECT_EQ(2UL, map_info.end());
+  EXPECT_EQ(3UL, map_info.offset());
+  EXPECT_EQ(4UL, map_info.flags());
+  EXPECT_EQ("map", map_info.name());
+  EXPECT_EQ(INT64_MAX, map_info.load_bias());
+  EXPECT_EQ(0UL, map_info.elf_offset());
+  EXPECT_TRUE(map_info.elf().get() == nullptr);
 }
 
 TEST(MapInfoTest, maps_constructor_string) {
   std::string name("string_map");
-  auto prev_map = MapInfo::Create(0, 0, 0, 0, "");
-  auto map_info = MapInfo::Create(prev_map, 1, 2, 3, 4, name);
+  MapInfo prev_map(nullptr, nullptr, 0, 0, 0, 0, "");
+  MapInfo map_info(&prev_map, &prev_map, 1, 2, 3, 4, name);
 
-  EXPECT_EQ(prev_map, map_info->prev_map());
-  EXPECT_EQ(1UL, map_info->start());
-  EXPECT_EQ(2UL, map_info->end());
-  EXPECT_EQ(3UL, map_info->offset());
-  EXPECT_EQ(4UL, map_info->flags());
-  EXPECT_EQ("string_map", map_info->name());
-  EXPECT_EQ(UINT64_MAX, map_info->load_bias());
-  EXPECT_EQ(0UL, map_info->elf_offset());
-  EXPECT_TRUE(map_info->elf().get() == nullptr);
-}
-
-TEST(MapInfoTest, real_map_check) {
-  auto map1 = MapInfo::Create(0, 0x1000, 0, PROT_READ, "fake.so");
-  auto map2 = MapInfo::Create(map1, 0, 0, 0, 0, "");
-  auto map3 = MapInfo::Create(map2, 0x1000, 0x2000, 0x1000, PROT_READ | PROT_EXEC, "fake.so");
-
-  EXPECT_EQ(nullptr, map1->prev_map());
-  EXPECT_EQ(nullptr, map1->GetPrevRealMap());
-  EXPECT_EQ(map2, map1->next_map());
-  EXPECT_EQ(map3, map1->GetNextRealMap());
-
-  EXPECT_EQ(map1, map2->prev_map());
-  EXPECT_EQ(nullptr, map2->GetPrevRealMap());
-  EXPECT_EQ(map3, map2->next_map());
-  EXPECT_EQ(nullptr, map2->GetNextRealMap());
-
-  EXPECT_EQ(map2, map3->prev_map());
-  EXPECT_EQ(map1, map3->GetPrevRealMap());
-  EXPECT_EQ(nullptr, map3->next_map());
-  EXPECT_EQ(nullptr, map3->GetNextRealMap());
-
-  // Verify that if the middle map is not blank, then the Get{Next,Prev}RealMap
-  // functions return nullptrs.
-  map2->set_offset(1);
-  EXPECT_EQ(nullptr, map1->GetPrevRealMap());
-  EXPECT_EQ(nullptr, map1->GetNextRealMap());
-  EXPECT_EQ(nullptr, map3->GetPrevRealMap());
-  EXPECT_EQ(nullptr, map3->GetNextRealMap());
-  map2->set_offset(0);
-  EXPECT_EQ(map3, map1->GetNextRealMap());
-
-  map2->set_flags(1);
-  EXPECT_EQ(nullptr, map1->GetPrevRealMap());
-  EXPECT_EQ(nullptr, map1->GetNextRealMap());
-  EXPECT_EQ(nullptr, map3->GetPrevRealMap());
-  EXPECT_EQ(nullptr, map3->GetNextRealMap());
-  map2->set_flags(0);
-  EXPECT_EQ(map3, map1->GetNextRealMap());
-
-  map2->set_name("something");
-  EXPECT_EQ(nullptr, map1->GetPrevRealMap());
-  EXPECT_EQ(nullptr, map1->GetNextRealMap());
-  EXPECT_EQ(nullptr, map3->GetPrevRealMap());
-  EXPECT_EQ(nullptr, map3->GetNextRealMap());
-  map2->set_name("");
-  EXPECT_EQ(map3, map1->GetNextRealMap());
-
-  // Verify that if the Get{Next,Prev}RealMap names must match.
-  map1->set_name("another");
-  EXPECT_EQ(nullptr, map1->GetPrevRealMap());
-  EXPECT_EQ(nullptr, map1->GetNextRealMap());
-  EXPECT_EQ(nullptr, map3->GetPrevRealMap());
-  EXPECT_EQ(nullptr, map3->GetNextRealMap());
-  map1->set_name("fake.so");
-  EXPECT_EQ(map3, map1->GetNextRealMap());
-
-  map3->set_name("another");
-  EXPECT_EQ(nullptr, map1->GetPrevRealMap());
-  EXPECT_EQ(nullptr, map1->GetNextRealMap());
-  EXPECT_EQ(nullptr, map3->GetPrevRealMap());
-  EXPECT_EQ(nullptr, map3->GetNextRealMap());
-  map3->set_name("fake.so");
-  EXPECT_EQ(map3, map1->GetNextRealMap());
+  EXPECT_EQ(&prev_map, map_info.prev_map());
+  EXPECT_EQ(1UL, map_info.start());
+  EXPECT_EQ(2UL, map_info.end());
+  EXPECT_EQ(3UL, map_info.offset());
+  EXPECT_EQ(4UL, map_info.flags());
+  EXPECT_EQ("string_map", map_info.name());
+  EXPECT_EQ(INT64_MAX, map_info.load_bias());
+  EXPECT_EQ(0UL, map_info.elf_offset());
+  EXPECT_TRUE(map_info.elf().get() == nullptr);
 }
 
 TEST(MapInfoTest, get_function_name) {
@@ -129,18 +64,18 @@
   elf->FakeSetInterface(interface);
   interface->FakePushFunctionData(FunctionData("function", 1000));
 
-  auto map_info = MapInfo::Create(1, 2, 3, 4, "");
-  map_info->set_elf(elf);
+  MapInfo map_info(nullptr, nullptr, 1, 2, 3, 4, "");
+  map_info.set_elf(elf);
 
   SharedString name;
   uint64_t offset;
-  ASSERT_TRUE(map_info->GetFunctionName(1000, &name, &offset));
+  ASSERT_TRUE(map_info.GetFunctionName(1000, &name, &offset));
   EXPECT_EQ("function", name);
   EXPECT_EQ(1000UL, offset);
 }
 
 TEST(MapInfoTest, multiple_thread_get_elf_fields) {
-  auto map_info = MapInfo::Create(0, 0, 0, 0, "");
+  MapInfo map_info(nullptr, nullptr, 0, 0, 0, 0, "");
 
   static constexpr size_t kNumConcurrentThreads = 100;
   MapInfo::ElfFields* elf_fields[kNumConcurrentThreads];
@@ -154,7 +89,7 @@
     std::thread* thread = new std::thread([i, &wait, &map_info, &elf_fields]() {
       while (wait)
         ;
-      elf_fields[i] = &map_info->GetElfFields();
+      elf_fields[i] = &map_info.GetElfFields();
     });
     threads.push_back(thread);
   }
@@ -167,29 +102,11 @@
   }
 
   // Now verify that all of elf fields are exactly the same and valid.
-  MapInfo::ElfFields* expected_elf_fields = &map_info->GetElfFields();
+  MapInfo::ElfFields* expected_elf_fields = &map_info.GetElfFields();
   ASSERT_TRUE(expected_elf_fields != nullptr);
   for (size_t i = 0; i < kNumConcurrentThreads; i++) {
     EXPECT_EQ(expected_elf_fields, elf_fields[i]) << "Thread " << i << " mismatched.";
   }
 }
 
-TEST(MapInfoTest, elf_file_not_readable) {
-  auto map_info_readable = MapInfo::Create(0, 0x1000, 0, PROT_READ, "fake.so");
-  map_info_readable->set_memory_backed_elf(true);
-  ASSERT_TRUE(map_info_readable->ElfFileNotReadable());
-
-  auto map_info_no_name = MapInfo::Create(0, 0x1000, 0, PROT_READ, "");
-  map_info_no_name->set_memory_backed_elf(true);
-  ASSERT_FALSE(map_info_no_name->ElfFileNotReadable());
-
-  auto map_info_bracket = MapInfo::Create(0, 0x2000, 0, PROT_READ, "[vdso]");
-  map_info_bracket->set_memory_backed_elf(true);
-  ASSERT_FALSE(map_info_bracket->ElfFileNotReadable());
-
-  auto map_info_memfd = MapInfo::Create(0, 0x3000, 0, PROT_READ, "/memfd:jit-cache");
-  map_info_memfd->set_memory_backed_elf(true);
-  ASSERT_FALSE(map_info_memfd->ElfFileNotReadable());
-}
-
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/MapsTest.cpp b/libunwindstack/tests/MapsTest.cpp
index 8226b11..309bdc2 100644
--- a/libunwindstack/tests/MapsTest.cpp
+++ b/libunwindstack/tests/MapsTest.cpp
@@ -32,7 +32,7 @@
     ASSERT_FALSE(maps.Parse()) << "Failed on: " + line;
   } else {
     ASSERT_TRUE(maps.Parse()) << "Failed on: " + line;
-    MapInfo* element = maps.Get(0).get();
+    MapInfo* element = maps.Get(0);
     ASSERT_TRUE(element != nullptr) << "Failed on: " + line;
     info->set_start(element->start());
     info->set_end(element->end());
@@ -47,36 +47,18 @@
   Maps maps;
 
   maps.Add(0x1000, 0x2000, 0, PROT_READ, "fake_map", 0);
-  maps.Add(0x3000, 0x4000, 0, 0, "", 0x1234);
-  maps.Add(0x5000, 0x6000, 1, 2, "fake_map", static_cast<uint64_t>(-1));
+  maps.Add(0x3000, 0x4000, 0x10, 0, "", 0x1234);
+  maps.Add(0x5000, 0x6000, 1, 2, "fake_map2", static_cast<uint64_t>(-1));
 
   ASSERT_EQ(3U, maps.Total());
-  auto info1 = maps.Get(0);
-  auto info2 = maps.Get(1);
-  auto info3 = maps.Get(2);
-
-  EXPECT_EQ(nullptr, info1->prev_map());
-  EXPECT_EQ(nullptr, info1->GetPrevRealMap());
-  EXPECT_EQ(info2, info1->next_map());
-  EXPECT_EQ(info3, info1->GetNextRealMap());
-
-  EXPECT_EQ(info1, info2->prev_map());
-  EXPECT_EQ(nullptr, info2->GetPrevRealMap());
-  EXPECT_EQ(info3, info2->next_map());
-  EXPECT_EQ(nullptr, info2->GetNextRealMap());
-
-  EXPECT_EQ(info2, info3->prev_map());
-  EXPECT_EQ(info1, info3->GetPrevRealMap());
-  EXPECT_EQ(nullptr, info3->next_map());
-  EXPECT_EQ(nullptr, info3->GetNextRealMap());
-
-  ASSERT_EQ(0x1000U, info1->start());
-  ASSERT_EQ(0x2000U, info1->end());
-  ASSERT_EQ(0U, info1->offset());
-  ASSERT_EQ(PROT_READ, info1->flags());
-  ASSERT_EQ("fake_map", info1->name());
-  ASSERT_EQ(0U, info1->elf_offset());
-  ASSERT_EQ(0U, info1->load_bias().load());
+  MapInfo* info = maps.Get(0);
+  ASSERT_EQ(0x1000U, info->start());
+  ASSERT_EQ(0x2000U, info->end());
+  ASSERT_EQ(0U, info->offset());
+  ASSERT_EQ(PROT_READ, info->flags());
+  ASSERT_EQ("fake_map", info->name());
+  ASSERT_EQ(0U, info->elf_offset());
+  ASSERT_EQ(0U, info->load_bias().load());
 }
 
 TEST(MapsTest, map_move) {
@@ -89,7 +71,7 @@
   Maps maps2 = std::move(maps);
 
   ASSERT_EQ(3U, maps2.Total());
-  auto info = maps2.Get(0);
+  MapInfo* info = maps2.Get(0);
   ASSERT_EQ(0x1000U, info->start());
   ASSERT_EQ(0x2000U, info->end());
   ASSERT_EQ(0U, info->offset());
@@ -100,28 +82,28 @@
 }
 
 TEST(MapsTest, verify_parse_line) {
-  auto info = MapInfo::Create(0, 0, 0, 0, "");
+  MapInfo info(nullptr, nullptr, 0, 0, 0, 0, "");
 
-  VerifyLine("01-02 rwxp 03 04:05 06\n", info.get());
-  EXPECT_EQ(1U, info->start());
-  EXPECT_EQ(2U, info->end());
-  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info->flags());
-  EXPECT_EQ(3U, info->offset());
-  EXPECT_EQ("", info->name());
+  VerifyLine("01-02 rwxp 03 04:05 06\n", &info);
+  EXPECT_EQ(1U, info.start());
+  EXPECT_EQ(2U, info.end());
+  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info.flags());
+  EXPECT_EQ(3U, info.offset());
+  EXPECT_EQ("", info.name());
 
-  VerifyLine("0a-0b ---s 0c 0d:0e 06 /fake/name\n", info.get());
-  EXPECT_EQ(0xaU, info->start());
-  EXPECT_EQ(0xbU, info->end());
-  EXPECT_EQ(0U, info->flags());
-  EXPECT_EQ(0xcU, info->offset());
-  EXPECT_EQ("/fake/name", info->name());
+  VerifyLine("0a-0b ---s 0c 0d:0e 06 /fake/name\n", &info);
+  EXPECT_EQ(0xaU, info.start());
+  EXPECT_EQ(0xbU, info.end());
+  EXPECT_EQ(0U, info.flags());
+  EXPECT_EQ(0xcU, info.offset());
+  EXPECT_EQ("/fake/name", info.name());
 
-  VerifyLine("01-02   rwxp   03    04:05    06    /fake/name/again\n", info.get());
-  EXPECT_EQ(1U, info->start());
-  EXPECT_EQ(2U, info->end());
-  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info->flags());
-  EXPECT_EQ(3U, info->offset());
-  EXPECT_EQ("/fake/name/again", info->name());
+  VerifyLine("01-02   rwxp   03    04:05    06    /fake/name/again\n", &info);
+  EXPECT_EQ(1U, info.start());
+  EXPECT_EQ(2U, info.end());
+  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info.flags());
+  EXPECT_EQ(3U, info.offset());
+  EXPECT_EQ("/fake/name/again", info.name());
 
   VerifyLine("-00 rwxp 00 00:00 0\n", nullptr);
   VerifyLine("00- rwxp 00 00:00 0\n", nullptr);
@@ -173,19 +155,19 @@
 }
 
 TEST(MapsTest, verify_large_values) {
-  auto info = MapInfo::Create(0, 0, 0, 0, "");
+  MapInfo info(nullptr, nullptr, 0, 0, 0, 0, "");
 #if defined(__LP64__)
-  VerifyLine("fabcdef012345678-f12345678abcdef8 rwxp f0b0d0f010305070 00:00 0\n", info.get());
-  EXPECT_EQ(0xfabcdef012345678UL, info->start());
-  EXPECT_EQ(0xf12345678abcdef8UL, info->end());
-  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info->flags());
-  EXPECT_EQ(0xf0b0d0f010305070UL, info->offset());
+  VerifyLine("fabcdef012345678-f12345678abcdef8 rwxp f0b0d0f010305070 00:00 0\n", &info);
+  EXPECT_EQ(0xfabcdef012345678UL, info.start());
+  EXPECT_EQ(0xf12345678abcdef8UL, info.end());
+  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info.flags());
+  EXPECT_EQ(0xf0b0d0f010305070UL, info.offset());
 #else
-  VerifyLine("f2345678-fabcdef8 rwxp f0305070 00:00 0\n", info.get());
-  EXPECT_EQ(0xf2345678UL, info->start());
-  EXPECT_EQ(0xfabcdef8UL, info->end());
-  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info->flags());
-  EXPECT_EQ(0xf0305070UL, info->offset());
+  VerifyLine("f2345678-fabcdef8 rwxp f0305070 00:00 0\n", &info);
+  EXPECT_EQ(0xf2345678UL, info.start());
+  EXPECT_EQ(0xfabcdef8UL, info.end());
+  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info.flags());
+  EXPECT_EQ(0xf0305070UL, info.offset());
 #endif
 }
 
@@ -200,7 +182,7 @@
   ASSERT_TRUE(maps.Parse());
   ASSERT_EQ(5U, maps.Total());
 
-  auto info = maps.Get(0);
+  MapInfo* info = maps.Get(0);
   ASSERT_TRUE(info != nullptr);
   EXPECT_EQ(PROT_NONE, info->flags());
   EXPECT_EQ(0x1000U, info->start());
@@ -252,7 +234,7 @@
   ASSERT_TRUE(maps.Parse());
   ASSERT_EQ(3U, maps.Total());
 
-  auto info = maps.Get(0);
+  MapInfo* info = maps.Get(0);
   ASSERT_TRUE(info != nullptr);
   EXPECT_EQ("", info->name());
   EXPECT_EQ(0x7b29b000U, info->start());
@@ -287,7 +269,7 @@
   ASSERT_TRUE(maps.Parse());
   ASSERT_EQ(2U, maps.Total());
 
-  auto info = maps.Get(0);
+  MapInfo* info = maps.Get(0);
   ASSERT_TRUE(info != nullptr);
   EXPECT_EQ(0U, info->offset());
   EXPECT_EQ(0xa000U, info->start());
@@ -352,7 +334,7 @@
   ASSERT_TRUE(maps.Parse());
   ASSERT_EQ(4U, maps.Total());
 
-  auto info = maps.Get(0);
+  MapInfo* info = maps.Get(0);
   ASSERT_TRUE(info != nullptr);
   EXPECT_TRUE(info->flags() & 0x8000);
   EXPECT_EQ("/dev/", info->name());
@@ -385,7 +367,7 @@
   ASSERT_TRUE(maps.Parse());
   ASSERT_EQ(3U, maps.Total());
 
-  auto info = maps.Get(0);
+  MapInfo* info = maps.Get(0);
   ASSERT_TRUE(info != nullptr);
   EXPECT_EQ(0x7b29b000U, info->start());
   EXPECT_EQ(0x7b29e000U, info->end());
@@ -427,7 +409,7 @@
   ASSERT_TRUE(maps.Parse());
   ASSERT_EQ(3U, maps.Total());
 
-  auto info = maps.Get(0);
+  MapInfo* info = maps.Get(0);
   ASSERT_TRUE(info != nullptr);
   EXPECT_EQ(0x7b29b000U, info->start());
   EXPECT_EQ(0x7b29e000U, info->end());
@@ -519,7 +501,7 @@
   EXPECT_EQ(index, maps.Total());
   // Verify all of the maps.
   for (size_t i = 0; i < index; i++) {
-    auto info = maps.Get(i);
+    MapInfo* info = maps.Get(i);
     ASSERT_TRUE(info != nullptr) << "Failed verifying index " + std::to_string(i);
     EXPECT_EQ(i * 4096, info->start()) << "Failed verifying index " + std::to_string(i);
     EXPECT_EQ((i + 1) * 4096, info->end()) << "Failed verifying index " + std::to_string(i);
@@ -569,7 +551,7 @@
   ASSERT_TRUE(maps.Parse());
   ASSERT_EQ(5000U, maps.Total());
   for (size_t i = 0; i < 5000; i++) {
-    auto info = maps.Get(i);
+    MapInfo* info = maps.Get(i);
     EXPECT_EQ(start + i * 4096, info->start()) << "Failed at map " + std::to_string(i);
     EXPECT_EQ(start + (i + 1) * 4096, info->end()) << "Failed at map " + std::to_string(i);
     std::string name = "/fake" + std::to_string(i) + ".so";
@@ -594,7 +576,7 @@
   EXPECT_TRUE(maps.Find(0xf000) == nullptr);
   EXPECT_TRUE(maps.Find(0xf010) == nullptr);
 
-  auto info = maps.Find(0x1000);
+  MapInfo* info = maps.Find(0x1000);
   ASSERT_TRUE(info != nullptr);
   EXPECT_EQ(0x1000U, info->start());
   EXPECT_EQ(0x2000U, info->end());
@@ -635,75 +617,4 @@
   EXPECT_EQ("/system/lib/fake5.so", info->name());
 }
 
-TEST(MapsTest, sort) {
-  Maps maps;
-
-  maps.Add(0x8000, 0x9000, 0, 0, "", 0);
-  maps.Add(0x7000, 0x8000, 0, 0, "lib.so", 0);
-  maps.Add(0x6000, 0x7000, 0, 0, "", 0);
-  maps.Add(0x5000, 0x6000, 0, 0, "lib.so", 0);
-  maps.Add(0x4000, 0x5000, 0, 0, "", 0);
-  maps.Add(0x3000, 0x4000, 0, 0, "", 0);
-  maps.Add(0x2000, 0x3000, 0, 0, "lib.so", 0);
-  maps.Add(0x1000, 0x2000, 0, 0, "", 0);
-
-  maps.Sort();
-
-  EXPECT_EQ(0x1000UL, maps.Get(0)->start());
-  EXPECT_EQ(nullptr, maps.Get(0)->prev_map());
-  EXPECT_EQ(maps.Get(1), maps.Get(0)->next_map());
-  EXPECT_EQ(nullptr, maps.Get(0)->GetPrevRealMap());
-  EXPECT_EQ(nullptr, maps.Get(0)->GetNextRealMap());
-
-  EXPECT_EQ(0x2000UL, maps.Get(1)->start());
-  EXPECT_EQ(maps.Get(0), maps.Get(1)->prev_map());
-  EXPECT_EQ(maps.Get(2), maps.Get(1)->next_map());
-  EXPECT_EQ(nullptr, maps.Get(1)->GetPrevRealMap());
-  EXPECT_EQ(maps.Get(4), maps.Get(1)->GetNextRealMap());
-
-  EXPECT_EQ(0x3000UL, maps.Get(2)->start());
-  EXPECT_EQ(maps.Get(1), maps.Get(2)->prev_map());
-  EXPECT_EQ(maps.Get(3), maps.Get(2)->next_map());
-  EXPECT_EQ(nullptr, maps.Get(2)->GetPrevRealMap());
-  EXPECT_EQ(nullptr, maps.Get(2)->GetNextRealMap());
-
-  EXPECT_EQ(0x4000UL, maps.Get(3)->start());
-  EXPECT_EQ(maps.Get(2), maps.Get(3)->prev_map());
-  EXPECT_EQ(maps.Get(4), maps.Get(3)->next_map());
-  EXPECT_EQ(nullptr, maps.Get(3)->GetPrevRealMap());
-  EXPECT_EQ(nullptr, maps.Get(3)->GetNextRealMap());
-
-  EXPECT_EQ(0x5000UL, maps.Get(4)->start());
-  EXPECT_EQ(maps.Get(3), maps.Get(4)->prev_map());
-  EXPECT_EQ(maps.Get(5), maps.Get(4)->next_map());
-  EXPECT_EQ(maps.Get(1), maps.Get(4)->GetPrevRealMap());
-  EXPECT_EQ(maps.Get(6), maps.Get(4)->GetNextRealMap());
-
-  EXPECT_EQ(0x6000UL, maps.Get(5)->start());
-  EXPECT_EQ(maps.Get(4), maps.Get(5)->prev_map());
-  EXPECT_EQ(maps.Get(6), maps.Get(5)->next_map());
-  EXPECT_EQ(nullptr, maps.Get(5)->GetPrevRealMap());
-  EXPECT_EQ(nullptr, maps.Get(5)->GetNextRealMap());
-
-  EXPECT_EQ(0x7000UL, maps.Get(6)->start());
-  EXPECT_EQ(maps.Get(5), maps.Get(6)->prev_map());
-  EXPECT_EQ(maps.Get(7), maps.Get(6)->next_map());
-  EXPECT_EQ(maps.Get(4), maps.Get(6)->GetPrevRealMap());
-  EXPECT_EQ(nullptr, maps.Get(6)->GetNextRealMap());
-
-  EXPECT_EQ(0x8000UL, maps.Get(7)->start());
-  EXPECT_EQ(maps.Get(6), maps.Get(7)->prev_map());
-  EXPECT_EQ(nullptr, maps.Get(7)->next_map());
-  EXPECT_EQ(nullptr, maps.Get(7)->GetPrevRealMap());
-  EXPECT_EQ(nullptr, maps.Get(7)->GetNextRealMap());
-}
-
-TEST(MapsTest, sort_empty) {
-  Maps maps;
-
-  maps.Sort();
-
-  EXPECT_EQ(0ULL, maps.Total());
-}
-
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/MemoryBufferTest.cpp b/libunwindstack/tests/MemoryBufferTest.cpp
index 91b20dd..ffd6817 100644
--- a/libunwindstack/tests/MemoryBufferTest.cpp
+++ b/libunwindstack/tests/MemoryBufferTest.cpp
@@ -103,14 +103,7 @@
   ASSERT_TRUE(memory_->Resize(256));
 
   ASSERT_TRUE(memory_->Resize(1024));
-}
 
-extern "C" void __hwasan_init() __attribute__((weak));
-
-TEST_F(MemoryBufferTest, Resize_too_large) {
-  if (&__hwasan_init != 0) {
-    GTEST_SKIP() << "Tests fails hwasan allocation size too large check.";
-  }
   ASSERT_FALSE(memory_->Resize(SIZE_MAX));
 }
 
diff --git a/libunwindstack/tests/MemoryCacheTest.cpp b/libunwindstack/tests/MemoryCacheTest.cpp
index ae0c61b..3bd3e4d 100644
--- a/libunwindstack/tests/MemoryCacheTest.cpp
+++ b/libunwindstack/tests/MemoryCacheTest.cpp
@@ -21,7 +21,7 @@
 #include <gtest/gtest.h>
 
 #include "MemoryCache.h"
-#include "utils/MemoryFake.h"
+#include "MemoryFake.h"
 
 namespace unwindstack {
 
diff --git a/libunwindstack/utils/MemoryFake.cpp b/libunwindstack/tests/MemoryFake.cpp
similarity index 97%
rename from libunwindstack/utils/MemoryFake.cpp
rename to libunwindstack/tests/MemoryFake.cpp
index 573285b..5695dfc 100644
--- a/libunwindstack/utils/MemoryFake.cpp
+++ b/libunwindstack/tests/MemoryFake.cpp
@@ -41,7 +41,7 @@
     if (value != data_.end()) {
       value->second = src[i];
     } else {
-      data_.insert({addr, src[i]});
+      data_.insert({ addr, src[i] });
     }
   }
 }
@@ -58,4 +58,4 @@
   return size;
 }
 
-}  // namespace unwindstack
\ No newline at end of file
+}  // namespace unwindstack
diff --git a/libunwindstack/utils/MemoryFake.h b/libunwindstack/tests/MemoryFake.h
similarity index 76%
rename from libunwindstack/utils/MemoryFake.h
rename to libunwindstack/tests/MemoryFake.h
index b7adfd9..20610a5 100644
--- a/libunwindstack/utils/MemoryFake.h
+++ b/libunwindstack/tests/MemoryFake.h
@@ -14,13 +14,14 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_TESTS_MEMORY_FAKE_H
+#define _LIBUNWINDSTACK_TESTS_MEMORY_FAKE_H
 
 #include <stdint.h>
 
 #include <string>
-#include <unordered_map>
 #include <vector>
+#include <unordered_map>
 
 #include <unwindstack/Memory.h>
 
@@ -37,13 +38,21 @@
 
   void SetMemoryBlock(uint64_t addr, size_t length, uint8_t value);
 
-  void SetData8(uint64_t addr, uint8_t value) { SetMemory(addr, &value, sizeof(value)); }
+  void SetData8(uint64_t addr, uint8_t value) {
+    SetMemory(addr, &value, sizeof(value));
+  }
 
-  void SetData16(uint64_t addr, uint16_t value) { SetMemory(addr, &value, sizeof(value)); }
+  void SetData16(uint64_t addr, uint16_t value) {
+    SetMemory(addr, &value, sizeof(value));
+  }
 
-  void SetData32(uint64_t addr, uint32_t value) { SetMemory(addr, &value, sizeof(value)); }
+  void SetData32(uint64_t addr, uint32_t value) {
+    SetMemory(addr, &value, sizeof(value));
+  }
 
-  void SetData64(uint64_t addr, uint64_t value) { SetMemory(addr, &value, sizeof(value)); }
+  void SetData64(uint64_t addr, uint64_t value) {
+    SetMemory(addr, &value, sizeof(value));
+  }
 
   void SetMemory(uint64_t addr, std::vector<uint8_t> values) {
     SetMemory(addr, values.data(), values.size());
@@ -71,3 +80,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_TESTS_MEMORY_FAKE_H
diff --git a/libunwindstack/tests/MemoryMteTest.cpp b/libunwindstack/tests/MemoryMteTest.cpp
index 8129394..9aab0c0 100644
--- a/libunwindstack/tests/MemoryMteTest.cpp
+++ b/libunwindstack/tests/MemoryMteTest.cpp
@@ -25,7 +25,6 @@
 
 #include "MemoryLocal.h"
 #include "MemoryRemote.h"
-#include "PidUtils.h"
 #include "TestUtils.h"
 
 namespace unwindstack {
@@ -69,14 +68,14 @@
   ASSERT_LT(0, pid);
   TestScopedPidReaper reap(pid);
 
-  ASSERT_TRUE(Attach(pid));
+  ASSERT_TRUE(TestAttach(pid));
 
   MemoryRemote remote(pid);
 
   EXPECT_EQ(1, remote.ReadTag(mapping));
   EXPECT_EQ(0, remote.ReadTag(mapping + 16));
 
-  ASSERT_TRUE(Detach(pid));
+  ASSERT_TRUE(TestDetach(pid));
 }
 
 TEST(MemoryMteTest, local_read_tag) {
diff --git a/libunwindstack/tests/MemoryRangeTest.cpp b/libunwindstack/tests/MemoryRangeTest.cpp
index 7a374eb..2d4f141 100644
--- a/libunwindstack/tests/MemoryRangeTest.cpp
+++ b/libunwindstack/tests/MemoryRangeTest.cpp
@@ -21,8 +21,8 @@
 
 #include <gtest/gtest.h>
 
+#include "MemoryFake.h"
 #include "MemoryRange.h"
-#include "utils/MemoryFake.h"
 
 namespace unwindstack {
 
diff --git a/libunwindstack/tests/MemoryRangesTest.cpp b/libunwindstack/tests/MemoryRangesTest.cpp
index cf3250a..e4e9fc4 100644
--- a/libunwindstack/tests/MemoryRangesTest.cpp
+++ b/libunwindstack/tests/MemoryRangesTest.cpp
@@ -20,8 +20,8 @@
 
 #include <gtest/gtest.h>
 
+#include "MemoryFake.h"
 #include "MemoryRange.h"
-#include "utils/MemoryFake.h"
 
 namespace unwindstack {
 
@@ -86,10 +86,4 @@
   }
 }
 
-TEST_F(MemoryRangesTest, duplicate_last_addr) {
-  MemoryRanges ranges;
-  ASSERT_TRUE(ranges.Insert(new MemoryRange(nullptr, 0x1000, 0x2000, 0x1000)));
-  ASSERT_FALSE(ranges.Insert(new MemoryRange(nullptr, 0x2000, 0x1000, 0x2000)));
-}
-
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/MemoryRemoteTest.cpp b/libunwindstack/tests/MemoryRemoteTest.cpp
index ed58eb9..621893b 100644
--- a/libunwindstack/tests/MemoryRemoteTest.cpp
+++ b/libunwindstack/tests/MemoryRemoteTest.cpp
@@ -32,9 +32,8 @@
 
 #include "MemoryRemote.h"
 
-#include "PidUtils.h"
+#include "MemoryFake.h"
 #include "TestUtils.h"
-#include "utils/MemoryFake.h"
 
 namespace unwindstack {
 
@@ -50,7 +49,7 @@
   ASSERT_LT(0, pid);
   TestScopedPidReaper reap(pid);
 
-  ASSERT_TRUE(Attach(pid));
+  ASSERT_TRUE(TestAttach(pid));
 
   MemoryRemote remote(pid);
 
@@ -60,7 +59,7 @@
     ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
   }
 
-  ASSERT_TRUE(Detach(pid));
+  ASSERT_TRUE(TestDetach(pid));
 }
 
 TEST(MemoryRemoteTest, read_large) {
@@ -79,7 +78,7 @@
   ASSERT_LT(0, pid);
   TestScopedPidReaper reap(pid);
 
-  ASSERT_TRUE(Attach(pid));
+  ASSERT_TRUE(TestAttach(pid));
 
   MemoryRemote remote(pid);
 
@@ -89,7 +88,7 @@
     ASSERT_EQ(i / getpagesize(), dst[i]) << "Failed at byte " << i;
   }
 
-  ASSERT_TRUE(Detach(pid));
+  ASSERT_TRUE(TestDetach(pid));
 }
 
 TEST(MemoryRemoteTest, read_partial) {
@@ -112,7 +111,7 @@
   // Unmap from our process.
   ASSERT_EQ(0, munmap(mapping, 3 * getpagesize()));
 
-  ASSERT_TRUE(Attach(pid));
+  ASSERT_TRUE(TestAttach(pid));
 
   MemoryRemote remote(pid);
 
@@ -133,7 +132,7 @@
     ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
   }
 
-  ASSERT_TRUE(Detach(pid));
+  ASSERT_TRUE(TestDetach(pid));
 }
 
 TEST(MemoryRemoteTest, read_fail) {
@@ -153,7 +152,7 @@
   ASSERT_LT(0, pid);
   TestScopedPidReaper reap(pid);
 
-  ASSERT_TRUE(Attach(pid));
+  ASSERT_TRUE(TestAttach(pid));
 
   MemoryRemote remote(pid);
 
@@ -172,7 +171,7 @@
 
   ASSERT_EQ(0, munmap(src, pagesize));
 
-  ASSERT_TRUE(Detach(pid));
+  ASSERT_TRUE(TestDetach(pid));
 }
 
 TEST(MemoryRemoteTest, read_overflow) {
@@ -185,7 +184,7 @@
   ASSERT_LT(0, pid);
   TestScopedPidReaper reap(pid);
 
-  ASSERT_TRUE(Attach(pid));
+  ASSERT_TRUE(TestAttach(pid));
 
   MemoryRemote remote(pid);
 
@@ -193,7 +192,7 @@
   std::vector<uint8_t> dst(200);
   ASSERT_FALSE(remote.ReadFully(UINT64_MAX - 100, dst.data(), 200));
 
-  ASSERT_TRUE(Detach(pid));
+  ASSERT_TRUE(TestDetach(pid));
 }
 
 TEST(MemoryRemoteTest, read_illegal) {
@@ -205,7 +204,7 @@
   ASSERT_LT(0, pid);
   TestScopedPidReaper reap(pid);
 
-  ASSERT_TRUE(Attach(pid));
+  ASSERT_TRUE(TestAttach(pid));
 
   MemoryRemote remote(pid);
 
@@ -213,7 +212,7 @@
   ASSERT_FALSE(remote.ReadFully(0, dst.data(), 1));
   ASSERT_FALSE(remote.ReadFully(0, dst.data(), 100));
 
-  ASSERT_TRUE(Detach(pid));
+  ASSERT_TRUE(TestDetach(pid));
 }
 
 TEST(MemoryRemoteTest, read_mprotect_hole) {
@@ -234,7 +233,7 @@
 
   ASSERT_EQ(0, munmap(mapping, 3 * page_size));
 
-  ASSERT_TRUE(Attach(pid));
+  ASSERT_TRUE(TestAttach(pid));
 
   MemoryRemote remote(pid);
   std::vector<uint8_t> dst(getpagesize() * 4, 0xCC);
@@ -248,7 +247,7 @@
     ASSERT_EQ(0xCC, dst[i]);
   }
 
-  ASSERT_TRUE(Detach(pid));
+  ASSERT_TRUE(TestDetach(pid));
 }
 
 TEST(MemoryRemoteTest, read_munmap_hole) {
@@ -271,7 +270,7 @@
   ASSERT_EQ(0, munmap(mapping, page_size));
   ASSERT_EQ(0, munmap(static_cast<char*>(mapping) + 2 * page_size, page_size));
 
-  ASSERT_TRUE(Attach(pid));
+  ASSERT_TRUE(TestAttach(pid));
 
   MemoryRemote remote(pid);
   std::vector<uint8_t> dst(getpagesize() * 4, 0xCC);
@@ -284,7 +283,7 @@
     ASSERT_EQ(0xCC, dst[i]);
   }
 
-  ASSERT_TRUE(Detach(pid));
+  ASSERT_TRUE(TestDetach(pid));
 }
 
 // Verify that the memory remote object chooses a memory read function
@@ -308,7 +307,7 @@
 
   ASSERT_EQ(0, munmap(mapping, 2 * page_size));
 
-  ASSERT_TRUE(Attach(pid));
+  ASSERT_TRUE(TestAttach(pid));
 
   // We know that process_vm_readv of a mprotect'd PROT_NONE region will fail.
   // Read from the PROT_NONE area first to force the choice of ptrace.
@@ -337,7 +336,7 @@
   ASSERT_EQ(sizeof(value), bytes);
   ASSERT_EQ(0xfcfcfcfcU, value);
 
-  ASSERT_TRUE(Detach(pid));
+  ASSERT_TRUE(TestDetach(pid));
 }
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/MemoryTest.cpp b/libunwindstack/tests/MemoryTest.cpp
index 268e536..8a8eb24 100644
--- a/libunwindstack/tests/MemoryTest.cpp
+++ b/libunwindstack/tests/MemoryTest.cpp
@@ -24,7 +24,7 @@
 
 #include <unwindstack/Memory.h>
 
-#include "utils/MemoryFake.h"
+#include "MemoryFake.h"
 
 namespace unwindstack {
 
diff --git a/libunwindstack/tests/MemoryThreadCacheTest.cpp b/libunwindstack/tests/MemoryThreadCacheTest.cpp
index 0ecfba9..2c499bf 100644
--- a/libunwindstack/tests/MemoryThreadCacheTest.cpp
+++ b/libunwindstack/tests/MemoryThreadCacheTest.cpp
@@ -22,7 +22,7 @@
 #include <gtest/gtest.h>
 
 #include "MemoryCache.h"
-#include "utils/MemoryFake.h"
+#include "MemoryFake.h"
 
 namespace unwindstack {
 
@@ -164,23 +164,17 @@
   }
 }
 
-static void ExhaustPthreadKeys(std::vector<pthread_key_t>* keys) {
+TEST_F(MemoryThreadCacheTest, read_uncached_due_to_error) {
   // Use up all of the keys to force the next attempt to create one to fail.
   static constexpr size_t kMaxKeysToCreate = 10000;
-  keys->resize(kMaxKeysToCreate);
+  std::vector<pthread_key_t> keys(kMaxKeysToCreate);
   for (size_t i = 0; i < kMaxKeysToCreate; i++) {
-    if (pthread_key_create(&(*keys)[i], nullptr) != 0) {
-      keys->resize(i);
+    if (pthread_key_create(&keys[i], nullptr) != 0) {
+      keys.resize(i);
       break;
     }
   }
-  ASSERT_NE(0U, keys->size()) << "No keys created.";
-  ASSERT_LT(keys->size(), kMaxKeysToCreate) << "Cannot use up pthread keys.";
-}
-
-TEST_F(MemoryThreadCacheTest, read_uncached_due_to_error) {
-  std::vector<pthread_key_t> keys;
-  ASSERT_NO_FATAL_FAILURE(ExhaustPthreadKeys(&keys));
+  ASSERT_NE(kMaxKeysToCreate, keys.size()) << "Cannot exist pthread keys.";
 
   MemoryFake* fake = new MemoryFake;
   MemoryThreadCache memory(fake);
@@ -205,17 +199,4 @@
   }
 }
 
-TEST_F(MemoryThreadCacheTest, clear_cache_when_no_cache) {
-  std::vector<pthread_key_t> keys;
-  ASSERT_NO_FATAL_FAILURE(ExhaustPthreadKeys(&keys));
-
-  MemoryFake* fake = new MemoryFake;
-  MemoryThreadCache memory(fake);
-  memory.Clear();
-
-  for (pthread_key_t& key : keys) {
-    pthread_key_delete(key);
-  }
-}
-
 }  // namespace unwindstack
diff --git a/libunwindstack/utils/RegsFake.h b/libunwindstack/tests/RegsFake.h
similarity index 96%
rename from libunwindstack/utils/RegsFake.h
rename to libunwindstack/tests/RegsFake.h
index 4bb4181..f67d7dc 100644
--- a/libunwindstack/utils/RegsFake.h
+++ b/libunwindstack/tests/RegsFake.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_TESTS_REGS_FAKE_H
+#define _LIBUNWINDSTACK_TESTS_REGS_FAKE_H
 
 #include <stdint.h>
 
@@ -112,3 +113,5 @@
 };
 
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_TESTS_REGS_FAKE_H
diff --git a/libunwindstack/tests/RegsRemoteTest.cpp b/libunwindstack/tests/RegsRemoteTest.cpp
deleted file mode 100644
index 2427501..0000000
--- a/libunwindstack/tests/RegsRemoteTest.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2022 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 <signal.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <memory>
-
-#include <gtest/gtest.h>
-
-#include <unwindstack/Regs.h>
-
-#include "PidUtils.h"
-
-namespace unwindstack {
-
-class RegsRemoteTest : public ::testing::Test {
- protected:
-  void SetUp() override {
-    if ((pid_ = fork()) == 0) {
-      volatile bool run = true;
-      while (!run) {
-      }
-      exit(1);
-    }
-    ASSERT_TRUE(pid_ != -1);
-    ASSERT_TRUE(Attach(pid_));
-  }
-
-  void TearDown() override {
-    if (pid_ == -1) {
-      return;
-    }
-    EXPECT_TRUE(Detach(pid_));
-    kill(pid_, SIGKILL);
-    waitpid(pid_, nullptr, 0);
-  }
-
-  pid_t pid_ = -1;
-};
-
-TEST_F(RegsRemoteTest, remote_get) {
-  std::unique_ptr<Regs> regs(Regs::RemoteGet(pid_));
-#if defined(__arm__)
-  ASSERT_EQ(ARCH_ARM, regs->Arch());
-#elif defined(__aarch64__)
-  ASSERT_EQ(ARCH_ARM64, regs->Arch());
-#elif defined(__i386__)
-  ASSERT_EQ(ARCH_X86, regs->Arch());
-#elif defined(__x86_64__)
-  ASSERT_EQ(ARCH_X86_64, regs->Arch());
-#else
-  ASSERT_EQ(nullptr, regs.get());
-#endif
-}
-
-TEST_F(RegsRemoteTest, remote_get_arch) {
-#if defined(__arm__)
-  ASSERT_EQ(ARCH_ARM, Regs::RemoteGetArch(pid_));
-#elif defined(__aarch64__)
-  ASSERT_EQ(ARCH_ARM64, Regs::RemoteGetArch(pid_));
-#elif defined(__i386__)
-  ASSERT_EQ(ARCH_X86, Regs::RemoteGetArch(pid_));
-#elif defined(__x86_64__)
-  ASSERT_EQ(ARCH_X86_64, Regs::RemoteGetArch(pid_));
-#else
-  ASSERT_EQ(ARCH_NONE, Regs::RemoteGetArch(pid_));
-#endif
-}
-
-}  // namespace unwindstack
diff --git a/libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp b/libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp
index 77e930f..eac12ca 100644
--- a/libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp
+++ b/libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp
@@ -32,7 +32,7 @@
 #include <unwindstack/RegsX86.h>
 #include <unwindstack/RegsX86_64.h>
 
-#include "utils/MemoryFake.h"
+#include "MemoryFake.h"
 
 namespace unwindstack {
 
diff --git a/libunwindstack/tests/RegsTest.cpp b/libunwindstack/tests/RegsTest.cpp
index 7c10d9e..716a847 100644
--- a/libunwindstack/tests/RegsTest.cpp
+++ b/libunwindstack/tests/RegsTest.cpp
@@ -16,8 +16,6 @@
 
 #include <stdint.h>
 
-#include <memory>
-
 #include <gtest/gtest.h>
 
 #include <unwindstack/Elf.h>
@@ -31,8 +29,8 @@
 #include <unwindstack/RegsMips64.h>
 
 #include "ElfFake.h"
+#include "MemoryFake.h"
 #include "RegsFake.h"
-#include "utils/MemoryFake.h"
 
 namespace unwindstack {
 
@@ -171,27 +169,27 @@
 }
 
 TEST_F(RegsTest, elf_invalid) {
-  auto map_info = MapInfo::Create(0x1000, 0x2000, 0, 0, "");
+  MapInfo map_info(nullptr, nullptr, 0x1000, 0x2000, 0, 0, "");
   Elf* invalid_elf = new Elf(nullptr);
-  map_info->set_elf(invalid_elf);
+  map_info.set_elf(invalid_elf);
 
-  EXPECT_EQ(0x500U, invalid_elf->GetRelPc(0x1500, map_info.get()));
+  EXPECT_EQ(0x500U, invalid_elf->GetRelPc(0x1500, &map_info));
   EXPECT_EQ(2U, GetPcAdjustment(0x500U, invalid_elf, ARCH_ARM));
   EXPECT_EQ(2U, GetPcAdjustment(0x511U, invalid_elf, ARCH_ARM));
 
-  EXPECT_EQ(0x600U, invalid_elf->GetRelPc(0x1600, map_info.get()));
+  EXPECT_EQ(0x600U, invalid_elf->GetRelPc(0x1600, &map_info));
   EXPECT_EQ(4U, GetPcAdjustment(0x600U, invalid_elf, ARCH_ARM64));
 
-  EXPECT_EQ(0x700U, invalid_elf->GetRelPc(0x1700, map_info.get()));
+  EXPECT_EQ(0x700U, invalid_elf->GetRelPc(0x1700, &map_info));
   EXPECT_EQ(1U, GetPcAdjustment(0x700U, invalid_elf, ARCH_X86));
 
-  EXPECT_EQ(0x800U, invalid_elf->GetRelPc(0x1800, map_info.get()));
+  EXPECT_EQ(0x800U, invalid_elf->GetRelPc(0x1800, &map_info));
   EXPECT_EQ(1U, GetPcAdjustment(0x800U, invalid_elf, ARCH_X86_64));
 
-  EXPECT_EQ(0x900U, invalid_elf->GetRelPc(0x1900, map_info.get()));
+  EXPECT_EQ(0x900U, invalid_elf->GetRelPc(0x1900, &map_info));
   EXPECT_EQ(8U, GetPcAdjustment(0x900U, invalid_elf, ARCH_MIPS));
 
-  EXPECT_EQ(0xa00U, invalid_elf->GetRelPc(0x1a00, map_info.get()));
+  EXPECT_EQ(0xa00U, invalid_elf->GetRelPc(0x1a00, &map_info));
   EXPECT_EQ(8U, GetPcAdjustment(0xa00U, invalid_elf, ARCH_MIPS64));
 }
 
diff --git a/libunwindstack/tests/SymbolsTest.cpp b/libunwindstack/tests/SymbolsTest.cpp
index c4f6f9b..89147a2 100644
--- a/libunwindstack/tests/SymbolsTest.cpp
+++ b/libunwindstack/tests/SymbolsTest.cpp
@@ -34,8 +34,8 @@
 
 #include <unwindstack/Memory.h>
 
+#include "MemoryFake.h"
 #include "Symbols.h"
-#include "utils/MemoryFake.h"
 
 namespace unwindstack {
 
diff --git a/libunwindstack/tests/TestLocal.cpp b/libunwindstack/tests/TestLocal.cpp
index 25bd42f..fa0baff 100644
--- a/libunwindstack/tests/TestLocal.cpp
+++ b/libunwindstack/tests/TestLocal.cpp
@@ -14,30 +14,26 @@
  * limitations under the License.
  */
 
-#include <stdint.h>
-#include <stdlib.h>
+#include <unwindstack/LocalUnwinder.h>
 
-#include "TestUtils.h"
+#include <vector>
 
-// The loop in this function is only guaranteed to not be optimized away by the compiler
-// if optimizations are turned off. This is partially because the compiler doesn't have
-// any idea about the function since it is retrieved using dlsym.
-//
-// In an effort to defend against the compiler:
-//  1. The loop iteration variable is volatile.
-//  2. A call to this function should be wrapped in TestUtils::DoNotOptimize().
-extern "C" int BusyWait() {
-  for (size_t i = 0; i < 1000000;) {
-    unwindstack::DoNotOptimize(i++);
-  }
-  return 0;
+extern "C" void TestlibLevel4(void* unwinder_data, void* frame_data) {
+  unwindstack::LocalUnwinder* unwinder =
+      reinterpret_cast<unwindstack::LocalUnwinder*>(unwinder_data);
+  std::vector<unwindstack::LocalFrameData>* frame_info =
+      reinterpret_cast<std::vector<unwindstack::LocalFrameData>*>(frame_data);
+  unwinder->Unwind(frame_info, 256);
 }
 
-// Do a loop that guarantees the terminating leaf frame will be in
-// the this library and not a function from a different library.
-extern "C" void WaitForever() {
-  bool run = true;
-  while (run) {
-    unwindstack::DoNotOptimize(run = true);
-  }
+extern "C" void TestlibLevel3(void* unwinder_data, void* frame_data) {
+  TestlibLevel4(unwinder_data, frame_data);
+}
+
+extern "C" void TestlibLevel2(void* unwinder_data, void* frame_data) {
+  TestlibLevel3(unwinder_data, frame_data);
+}
+
+extern "C" void TestlibLevel1(void* unwinder_data, void* frame_data) {
+  TestlibLevel2(unwinder_data, frame_data);
 }
diff --git a/libunwindstack/tests/TestUtils.cpp b/libunwindstack/tests/TestUtils.cpp
index 1f748ba..ecc2d45 100644
--- a/libunwindstack/tests/TestUtils.cpp
+++ b/libunwindstack/tests/TestUtils.cpp
@@ -14,16 +14,11 @@
  * limitations under the License.
  */
 
-#include <dlfcn.h>
 #include <malloc.h>
 #include <stdint.h>
 
-#include <string>
-
 #include <gtest/gtest.h>
 
-#include "TestUtils.h"
-
 namespace unwindstack {
 
 void TestCheckForLeaks(void (*unwind_func)(void*), void* data) {
@@ -47,17 +42,4 @@
   }
 }
 
-void* GetTestLibHandle() {
-  std::string testlib(testing::internal::GetArgvs()[0]);
-  auto const value = testlib.find_last_of('/');
-  if (value != std::string::npos) {
-    testlib = testlib.substr(0, value + 1);
-  } else {
-    testlib = "";
-  }
-  testlib += "libunwindstack_local.so";
-
-  return dlopen(testlib.c_str(), RTLD_NOW);
-}
-
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/TestUtils.h b/libunwindstack/tests/TestUtils.h
index 19cd693..0685006 100644
--- a/libunwindstack/tests/TestUtils.h
+++ b/libunwindstack/tests/TestUtils.h
@@ -14,12 +14,14 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_TESTS_TEST_UTILS_H
+#define _LIBUNWINDSTACK_TESTS_TEST_UTILS_H
 
 #include <signal.h>
-#include <stdint.h>
+#include <sys/ptrace.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <unistd.h>
 
 namespace unwindstack {
 
@@ -35,15 +37,34 @@
   pid_t pid_;
 };
 
-void TestCheckForLeaks(void (*unwind_func)(void*), void* data);
-
-void* GetTestLibHandle();
-
-// TODO(b/148307629): Once we incorporate google benchmark library into
-// GoogleTest, we can call benchmark::DoNotOptimize here instead.
-template <class Tp>
-static inline void DoNotOptimize(Tp const& value) {
-  asm volatile("" : : "r,m"(value) : "memory");
+inline bool TestQuiescePid(pid_t pid) {
+  siginfo_t si;
+  bool ready = false;
+  // Wait for up to 5 seconds.
+  for (size_t i = 0; i < 5000; i++) {
+    if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
+      ready = true;
+      break;
+    }
+    usleep(1000);
+  }
+  return ready;
 }
 
+inline bool TestAttach(pid_t pid) {
+  if (ptrace(PTRACE_ATTACH, pid, 0, 0) == -1) {
+    return false;
+  }
+
+  return TestQuiescePid(pid);
+}
+
+inline bool TestDetach(pid_t pid) {
+  return ptrace(PTRACE_DETACH, pid, 0, 0) == 0;
+}
+
+void TestCheckForLeaks(void (*unwind_func)(void*), void* data);
+
 }  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_TESTS_TEST_UTILS_H
diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp
index 0d6fa1d..c834d0d 100644
--- a/libunwindstack/tests/UnwindOfflineTest.cpp
+++ b/libunwindstack/tests/UnwindOfflineTest.cpp
@@ -14,108 +14,218 @@
  * limitations under the License.
  */
 
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include <sys/mman.h>
+#include <unistd.h>
 
 #include <gtest/gtest.h>
 
-#include <cstddef>
-#include <fstream>
-#include <memory>
-#include <sstream>
 #include <string>
+#include <unordered_map>
+#include <vector>
 
-#include <unwindstack/Arch.h>
-#include <unwindstack/Memory.h>
+#include <android-base/file.h>
+
+#include <unwindstack/JitDebug.h>
+#include <unwindstack/MachineArm.h>
+#include <unwindstack/MachineArm64.h>
+#include <unwindstack/MachineX86.h>
+#include <unwindstack/MachineX86_64.h>
+#include <unwindstack/Maps.h>
+#include <unwindstack/RegsArm.h>
 #include <unwindstack/RegsArm64.h>
+#include <unwindstack/RegsX86.h>
+#include <unwindstack/RegsX86_64.h>
 #include <unwindstack/Unwinder.h>
 
+#include "ElfTestUtils.h"
+#include "MemoryFake.h"
+#include "MemoryOffline.h"
 #include "TestUtils.h"
-#include "utils/MemoryFake.h"
-#include "utils/OfflineUnwindUtils.h"
 
-// This collection of tests exercises Unwinder::Unwind for offline unwinds.
-//
-// See `libunwindstack/utils/OfflineUnwindUtils.h` for more info on offline unwinds
-// and b/192012600 for additional information regarding offline unwind benchmarks.
 namespace unwindstack {
-namespace {
+
+static void AddMemory(std::string file_name, MemoryOfflineParts* parts) {
+  MemoryOffline* memory = new MemoryOffline;
+  ASSERT_TRUE(memory->Init(file_name.c_str(), 0));
+  parts->Add(memory);
+}
 
 class UnwindOfflineTest : public ::testing::Test {
- public:
-  bool GetExpectedSamplesFrameInfo(
-      std::string* expected_frame_info, std::string* error_msg,
-      const std::string& sample_name = OfflineUnwindUtils::kSingleSample) {
-    const std::string* a_frame_info_path = offline_utils_.GetFrameInfoFilepath(sample_name);
-    if (a_frame_info_path == nullptr) {
-      std::stringstream err_stream;
-      err_stream << "Unable to get frame info filepath for invalid sample name " << sample_name
-                 << ".\n";
-      *error_msg = err_stream.str();
-      return false;
-    }
-
-    std::ifstream in(*a_frame_info_path);
-    std::stringstream buffer;
-    buffer << in.rdbuf();
-    *expected_frame_info = buffer.str();
-    return true;
-  }
-
-  void ConsecutiveUnwindTest(const std::vector<UnwindSampleInfo>& sample_infos) {
-    std::string error_msg;
-    if (!offline_utils_.Init(sample_infos, &error_msg)) FAIL() << error_msg;
-
-    for (const auto& sample_info : sample_infos) {
-      const std::string& sample_name = sample_info.offline_files_dir;
-      // Need to change to sample directory for Unwinder to properly init ELF objects.
-      // See more info at OfflineUnwindUtils::ChangeToSampleDirectory.
-      if (!offline_utils_.ChangeToSampleDirectory(&error_msg, sample_name)) FAIL() << error_msg;
-
-      Unwinder unwinder =
-          Unwinder(128, offline_utils_.GetMaps(sample_name), offline_utils_.GetRegs(sample_name),
-                   offline_utils_.GetProcessMemory(sample_name));
-      if (sample_info.memory_flag == ProcessMemoryFlag::kIncludeJitMemory) {
-        unwinder.SetJitDebug(offline_utils_.GetJitDebug(sample_name));
-      }
-      unwinder.Unwind();
-
-      size_t expected_num_frames;
-      if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg, sample_name))
-        FAIL() << error_msg;
-      std::string expected_frame_info;
-      if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg, sample_name))
-        FAIL() << error_msg;
-
-      std::string actual_frame_info = DumpFrames(unwinder);
-      ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << actual_frame_info;
-      EXPECT_EQ(expected_frame_info, actual_frame_info);
-    }
-  }
-
  protected:
-  void TearDown() override { offline_utils_.ReturnToCurrentWorkingDirectory(); }
+  void TearDown() override {
+    if (cwd_ != nullptr) {
+      ASSERT_EQ(0, chdir(cwd_));
+    }
+    free(cwd_);
+  }
 
-  OfflineUnwindUtils offline_utils_;
+  void Init(const char* file_dir, ArchEnum arch, bool add_stack = true) {
+    dir_ = TestGetFileDirectory() + "offline/" + file_dir;
+
+    std::string data;
+    ASSERT_TRUE(android::base::ReadFileToString((dir_ + "maps.txt"), &data));
+
+    maps_.reset(new BufferMaps(data.c_str()));
+    ASSERT_TRUE(maps_->Parse());
+
+    if (add_stack) {
+      std::string stack_name(dir_ + "stack.data");
+      struct stat st;
+      if (stat(stack_name.c_str(), &st) == 0 && S_ISREG(st.st_mode)) {
+        std::unique_ptr<MemoryOffline> stack_memory(new MemoryOffline);
+        ASSERT_TRUE(stack_memory->Init((dir_ + "stack.data").c_str(), 0));
+        process_memory_.reset(stack_memory.release());
+      } else {
+        std::unique_ptr<MemoryOfflineParts> stack_memory(new MemoryOfflineParts);
+        for (size_t i = 0;; i++) {
+          stack_name = dir_ + "stack" + std::to_string(i) + ".data";
+          if (stat(stack_name.c_str(), &st) == -1 || !S_ISREG(st.st_mode)) {
+            ASSERT_TRUE(i != 0) << "No stack data files found.";
+            break;
+          }
+          AddMemory(stack_name, stack_memory.get());
+        }
+        process_memory_.reset(stack_memory.release());
+      }
+    }
+
+    switch (arch) {
+      case ARCH_ARM: {
+        RegsArm* regs = new RegsArm;
+        regs_.reset(regs);
+        ReadRegs<uint32_t>(regs, arm_regs_);
+        break;
+      }
+      case ARCH_ARM64: {
+        RegsArm64* regs = new RegsArm64;
+        regs_.reset(regs);
+        ReadRegs<uint64_t>(regs, arm64_regs_);
+        break;
+      }
+      case ARCH_X86: {
+        RegsX86* regs = new RegsX86;
+        regs_.reset(regs);
+        ReadRegs<uint32_t>(regs, x86_regs_);
+        break;
+      }
+      case ARCH_X86_64: {
+        RegsX86_64* regs = new RegsX86_64;
+        regs_.reset(regs);
+        ReadRegs<uint64_t>(regs, x86_64_regs_);
+        break;
+      }
+      default:
+        ASSERT_TRUE(false) << "Unknown arch " << std::to_string(arch);
+    }
+    cwd_ = getcwd(nullptr, 0);
+    // Make dir_ an absolute directory.
+    if (dir_.empty() || dir_[0] != '/') {
+      dir_ = std::string(cwd_) + '/' + dir_;
+    }
+    ASSERT_EQ(0, chdir(dir_.c_str()));
+
+    if (process_memory_ == nullptr) {
+      process_memory_.reset(new MemoryFake);
+    }
+  }
+
+  template <typename AddressType>
+  void ReadRegs(RegsImpl<AddressType>* regs,
+                const std::unordered_map<std::string, uint32_t>& name_to_reg) {
+    FILE* fp = fopen((dir_ + "regs.txt").c_str(), "r");
+    ASSERT_TRUE(fp != nullptr);
+    while (!feof(fp)) {
+      uint64_t value;
+      char reg_name[100];
+      ASSERT_EQ(2, fscanf(fp, "%s %" SCNx64 "\n", reg_name, &value));
+      std::string name(reg_name);
+      if (!name.empty()) {
+        // Remove the : from the end.
+        name.resize(name.size() - 1);
+      }
+      auto entry = name_to_reg.find(name);
+      ASSERT_TRUE(entry != name_to_reg.end()) << "Unknown register named " << name;
+      (*regs)[entry->second] = value;
+    }
+    fclose(fp);
+  }
+
+  static std::unordered_map<std::string, uint32_t> arm_regs_;
+  static std::unordered_map<std::string, uint32_t> arm64_regs_;
+  static std::unordered_map<std::string, uint32_t> x86_regs_;
+  static std::unordered_map<std::string, uint32_t> x86_64_regs_;
+
+  char* cwd_ = nullptr;
+  std::string dir_;
+  std::unique_ptr<Regs> regs_;
+  std::unique_ptr<Maps> maps_;
+  std::shared_ptr<Memory> process_memory_;
 };
 
-TEST_F(UnwindOfflineTest, pc_straddle_arm) {
-  std::string error_msg;
-  if (!offline_utils_.Init({.offline_files_dir = "straddle_arm/", .arch = ARCH_ARM}, &error_msg))
-    FAIL() << error_msg;
+std::unordered_map<std::string, uint32_t> UnwindOfflineTest::arm_regs_ = {
+    {"r0", ARM_REG_R0},  {"r1", ARM_REG_R1}, {"r2", ARM_REG_R2},   {"r3", ARM_REG_R3},
+    {"r4", ARM_REG_R4},  {"r5", ARM_REG_R5}, {"r6", ARM_REG_R6},   {"r7", ARM_REG_R7},
+    {"r8", ARM_REG_R8},  {"r9", ARM_REG_R9}, {"r10", ARM_REG_R10}, {"r11", ARM_REG_R11},
+    {"ip", ARM_REG_R12}, {"sp", ARM_REG_SP}, {"lr", ARM_REG_LR},   {"pc", ARM_REG_PC},
+};
 
-  Regs* regs = offline_utils_.GetRegs();
-  std::unique_ptr<Regs> regs_copy(regs->Clone());
-  Unwinder unwinder(128, offline_utils_.GetMaps(), regs, offline_utils_.GetProcessMemory());
+std::unordered_map<std::string, uint32_t> UnwindOfflineTest::arm64_regs_ = {
+    {"x0", ARM64_REG_R0},      {"x1", ARM64_REG_R1},   {"x2", ARM64_REG_R2},
+    {"x3", ARM64_REG_R3},      {"x4", ARM64_REG_R4},   {"x5", ARM64_REG_R5},
+    {"x6", ARM64_REG_R6},      {"x7", ARM64_REG_R7},   {"x8", ARM64_REG_R8},
+    {"x9", ARM64_REG_R9},      {"x10", ARM64_REG_R10}, {"x11", ARM64_REG_R11},
+    {"x12", ARM64_REG_R12},    {"x13", ARM64_REG_R13}, {"x14", ARM64_REG_R14},
+    {"x15", ARM64_REG_R15},    {"x16", ARM64_REG_R16}, {"x17", ARM64_REG_R17},
+    {"x18", ARM64_REG_R18},    {"x19", ARM64_REG_R19}, {"x20", ARM64_REG_R20},
+    {"x21", ARM64_REG_R21},    {"x22", ARM64_REG_R22}, {"x23", ARM64_REG_R23},
+    {"x24", ARM64_REG_R24},    {"x25", ARM64_REG_R25}, {"x26", ARM64_REG_R26},
+    {"x27", ARM64_REG_R27},    {"x28", ARM64_REG_R28}, {"x29", ARM64_REG_R29},
+    {"sp", ARM64_REG_SP},      {"lr", ARM64_REG_LR},   {"pc", ARM64_REG_PC},
+    {"pst", ARM64_REG_PSTATE},
+};
+
+std::unordered_map<std::string, uint32_t> UnwindOfflineTest::x86_regs_ = {
+    {"eax", X86_REG_EAX}, {"ebx", X86_REG_EBX}, {"ecx", X86_REG_ECX},
+    {"edx", X86_REG_EDX}, {"ebp", X86_REG_EBP}, {"edi", X86_REG_EDI},
+    {"esi", X86_REG_ESI}, {"esp", X86_REG_ESP}, {"eip", X86_REG_EIP},
+};
+
+std::unordered_map<std::string, uint32_t> UnwindOfflineTest::x86_64_regs_ = {
+    {"rax", X86_64_REG_RAX}, {"rbx", X86_64_REG_RBX}, {"rcx", X86_64_REG_RCX},
+    {"rdx", X86_64_REG_RDX}, {"r8", X86_64_REG_R8},   {"r9", X86_64_REG_R9},
+    {"r10", X86_64_REG_R10}, {"r11", X86_64_REG_R11}, {"r12", X86_64_REG_R12},
+    {"r13", X86_64_REG_R13}, {"r14", X86_64_REG_R14}, {"r15", X86_64_REG_R15},
+    {"rdi", X86_64_REG_RDI}, {"rsi", X86_64_REG_RSI}, {"rbp", X86_64_REG_RBP},
+    {"rsp", X86_64_REG_RSP}, {"rip", X86_64_REG_RIP},
+};
+
+static std::string DumpFrames(Unwinder& unwinder) {
+  std::string str;
+  for (size_t i = 0; i < unwinder.NumFrames(); i++) {
+    str += unwinder.FormatFrame(i) + "\n";
+  }
+  return str;
+}
+
+TEST_F(UnwindOfflineTest, pc_straddle_arm) {
+  ASSERT_NO_FATAL_FAILURE(Init("straddle_arm/", ARCH_ARM));
+
+  std::unique_ptr<Regs> regs_copy(regs_->Clone());
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
   unwinder.Unwind();
 
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  std::string expected_frame_info;
-  if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg;
-
   std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
-  EXPECT_EQ(expected_frame_info, frame_info);
+  ASSERT_EQ(4U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc 0001a9f8  libc.so (abort+64)\n"
+      "  #01 pc 00006a1b  libbase.so (android::base::DefaultAborter(char const*)+6)\n"
+      "  #02 pc 00007441  libbase.so (android::base::LogMessage::~LogMessage()+748)\n"
+      "  #03 pc 00015147  /does/not/exist/libhidlbase.so\n",
+      frame_info);
   EXPECT_EQ(0xf31ea9f8U, unwinder.frames()[0].pc);
   EXPECT_EQ(0xe9c866f8U, unwinder.frames()[0].sp);
   EXPECT_EQ(0xf2da0a1bU, unwinder.frames()[1].pc);
@@ -131,7 +241,7 @@
   unwinder.Unwind();
 
   frame_info = DumpFrames(unwinder);
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  ASSERT_EQ(4U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
   EXPECT_EQ(
       "  #00 pc 0001a9f8  libc.so (abort+64) (BuildId: 2dd0d4ba881322a0edabeed94808048c)\n"
       "  #01 pc 00006a1b  libbase.so (android::base::DefaultAborter(char const*)+6) (BuildId: "
@@ -143,23 +253,20 @@
 }
 
 TEST_F(UnwindOfflineTest, pc_in_gnu_debugdata_arm) {
-  std::string error_msg;
-  if (!offline_utils_.Init({.offline_files_dir = "gnu_debugdata_arm/", .arch = ARCH_ARM},
-                           &error_msg))
-    FAIL() << error_msg;
+  ASSERT_NO_FATAL_FAILURE(Init("gnu_debugdata_arm/", ARCH_ARM));
 
-  Unwinder unwinder(128, offline_utils_.GetMaps(), offline_utils_.GetRegs(),
-                    offline_utils_.GetProcessMemory());
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
   unwinder.Unwind();
 
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  std::string expected_frame_info;
-  if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg;
-
   std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
-  EXPECT_EQ(expected_frame_info, frame_info);
+  ASSERT_EQ(2U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc 0006dc49  libandroid_runtime.so "
+      "(android::AndroidRuntime::javaThreadShell(void*)+80)\n"
+      "  #01 pc 0006dce5  libandroid_runtime.so "
+      "(android::AndroidRuntime::javaCreateThreadEtc(int (*)(void*), void*, char const*, int, "
+      "unsigned int, void**))\n",
+      frame_info);
   EXPECT_EQ(0xf1f6dc49U, unwinder.frames()[0].pc);
   EXPECT_EQ(0xd8fe6930U, unwinder.frames()[0].sp);
   EXPECT_EQ(0xf1f6dce5U, unwinder.frames()[1].pc);
@@ -167,23 +274,23 @@
 }
 
 TEST_F(UnwindOfflineTest, pc_straddle_arm64) {
-  std::string error_msg;
-  if (!offline_utils_.Init({.offline_files_dir = "straddle_arm64/", .arch = ARCH_ARM64},
-                           &error_msg))
-    FAIL() << error_msg;
+  ASSERT_NO_FATAL_FAILURE(Init("straddle_arm64/", ARCH_ARM64));
 
-  Unwinder unwinder(128, offline_utils_.GetMaps(), offline_utils_.GetRegs(),
-                    offline_utils_.GetProcessMemory());
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
   unwinder.Unwind();
 
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  std::string expected_frame_info;
-  if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg;
-
   std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
-  EXPECT_EQ(expected_frame_info, frame_info);
+  ASSERT_EQ(6U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc 0000000000429fd8  libunwindstack_test (SignalInnerFunction+24)\n"
+      "  #01 pc 000000000042a078  libunwindstack_test (SignalMiddleFunction+8)\n"
+      "  #02 pc 000000000042a08c  libunwindstack_test (SignalOuterFunction+8)\n"
+      "  #03 pc 000000000042d8fc  libunwindstack_test "
+      "(unwindstack::RemoteThroughSignal(int, unsigned int)+20)\n"
+      "  #04 pc 000000000042d8d8  libunwindstack_test "
+      "(unwindstack::UnwindTest_remote_through_signal_Test::TestBody()+32)\n"
+      "  #05 pc 0000000000455d70  libunwindstack_test (testing::Test::Run()+392)\n",
+      frame_info);
   EXPECT_EQ(0x64d09d4fd8U, unwinder.frames()[0].pc);
   EXPECT_EQ(0x7fe0d84040U, unwinder.frames()[0].sp);
   EXPECT_EQ(0x64d09d5078U, unwinder.frames()[1].pc);
@@ -199,26 +306,166 @@
 }
 
 TEST_F(UnwindOfflineTest, jit_debug_x86) {
-  std::string error_msg;
-  if (!offline_utils_.Init({.offline_files_dir = "jit_debug_x86/",
-                            .arch = ARCH_X86,
-                            .memory_flag = ProcessMemoryFlag::kIncludeJitMemory},
-                           &error_msg))
-    FAIL() << error_msg;
+  ASSERT_NO_FATAL_FAILURE(Init("jit_debug_x86/", ARCH_X86));
 
-  Unwinder unwinder(128, offline_utils_.GetMaps(), offline_utils_.GetRegs(),
-                    offline_utils_.GetProcessMemory());
-  unwinder.SetJitDebug(offline_utils_.GetJitDebug());
+  MemoryOfflineParts* memory = new MemoryOfflineParts;
+  AddMemory(dir_ + "descriptor.data", memory);
+  AddMemory(dir_ + "stack.data", memory);
+  for (size_t i = 0; i < 7; i++) {
+    AddMemory(dir_ + "entry" + std::to_string(i) + ".data", memory);
+    AddMemory(dir_ + "jit" + std::to_string(i) + ".data", memory);
+  }
+  process_memory_.reset(memory);
+
+  std::unique_ptr<JitDebug> jit_debug = CreateJitDebug(regs_->Arch(), process_memory_);
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
+  unwinder.SetJitDebug(jit_debug.get());
   unwinder.Unwind();
 
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  std::string expected_frame_info;
-  if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg;
-
   std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
-  EXPECT_EQ(expected_frame_info, frame_info);
+  ASSERT_EQ(69U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc 00068fb8  libarttestd.so (art::CauseSegfault()+72)\n"
+      "  #01 pc 00067f00  libarttestd.so (Java_Main_unwindInProcess+10032)\n"
+      "  #02 pc 000021a8  137-cfi.odex (boolean Main.unwindInProcess(boolean, int, "
+      "boolean)+136)\n"
+      "  #03 pc 0000fe80  anonymous:ee74c000 (boolean Main.bar(boolean)+64)\n"
+      "  #04 pc 006ad4d2  libartd.so (art_quick_invoke_stub+338)\n"
+      "  #05 pc 00146ab5  libartd.so "
+      "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+      "const*)+885)\n"
+      "  #06 pc 0039cf0d  libartd.so "
+      "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+      "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
+      "  #07 pc 00392552  libartd.so "
+      "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+      "art::ShadowFrame&, art::JValue, bool)+354)\n"
+      "  #08 pc 0039399a  libartd.so "
+      "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+      "const&, art::ShadowFrame*)+234)\n"
+      "  #09 pc 00684362  libartd.so (artQuickToInterpreterBridge+1058)\n"
+      "  #10 pc 006b35bd  libartd.so (art_quick_to_interpreter_bridge+77)\n"
+      "  #11 pc 0000fe03  anonymous:ee74c000 (int Main.compare(Main, Main)+51)\n"
+      "  #12 pc 006ad4d2  libartd.so (art_quick_invoke_stub+338)\n"
+      "  #13 pc 00146ab5  libartd.so "
+      "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+      "const*)+885)\n"
+      "  #14 pc 0039cf0d  libartd.so "
+      "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+      "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
+      "  #15 pc 00392552  libartd.so "
+      "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+      "art::ShadowFrame&, art::JValue, bool)+354)\n"
+      "  #16 pc 0039399a  libartd.so "
+      "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+      "const&, art::ShadowFrame*)+234)\n"
+      "  #17 pc 00684362  libartd.so (artQuickToInterpreterBridge+1058)\n"
+      "  #18 pc 006b35bd  libartd.so (art_quick_to_interpreter_bridge+77)\n"
+      "  #19 pc 0000fd3b  anonymous:ee74c000 (int Main.compare(java.lang.Object, "
+      "java.lang.Object)+107)\n"
+      "  #20 pc 006ad4d2  libartd.so (art_quick_invoke_stub+338)\n"
+      "  #21 pc 00146ab5  libartd.so "
+      "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+      "const*)+885)\n"
+      "  #22 pc 0039cf0d  libartd.so "
+      "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+      "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
+      "  #23 pc 00392552  libartd.so "
+      "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+      "art::ShadowFrame&, art::JValue, bool)+354)\n"
+      "  #24 pc 0039399a  libartd.so "
+      "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+      "const&, art::ShadowFrame*)+234)\n"
+      "  #25 pc 00684362  libartd.so (artQuickToInterpreterBridge+1058)\n"
+      "  #26 pc 006b35bd  libartd.so (art_quick_to_interpreter_bridge+77)\n"
+      "  #27 pc 0000fbdb  anonymous:ee74c000 (int "
+      "java.util.Arrays.binarySearch0(java.lang.Object[], int, int, java.lang.Object, "
+      "java.util.Comparator)+331)\n"
+      "  #28 pc 006ad6a2  libartd.so (art_quick_invoke_static_stub+418)\n"
+      "  #29 pc 00146acb  libartd.so "
+      "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+      "const*)+907)\n"
+      "  #30 pc 0039cf0d  libartd.so "
+      "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+      "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
+      "  #31 pc 00392552  libartd.so "
+      "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+      "art::ShadowFrame&, art::JValue, bool)+354)\n"
+      "  #32 pc 0039399a  libartd.so "
+      "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+      "const&, art::ShadowFrame*)+234)\n"
+      "  #33 pc 00684362  libartd.so (artQuickToInterpreterBridge+1058)\n"
+      "  #34 pc 006b35bd  libartd.so (art_quick_to_interpreter_bridge+77)\n"
+      "  #35 pc 0000f624  anonymous:ee74c000 (boolean Main.foo()+164)\n"
+      "  #36 pc 006ad4d2  libartd.so (art_quick_invoke_stub+338)\n"
+      "  #37 pc 00146ab5  libartd.so "
+      "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+      "const*)+885)\n"
+      "  #38 pc 0039cf0d  libartd.so "
+      "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+      "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
+      "  #39 pc 00392552  libartd.so "
+      "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+      "art::ShadowFrame&, art::JValue, bool)+354)\n"
+      "  #40 pc 0039399a  libartd.so "
+      "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+      "const&, art::ShadowFrame*)+234)\n"
+      "  #41 pc 00684362  libartd.so (artQuickToInterpreterBridge+1058)\n"
+      "  #42 pc 006b35bd  libartd.so (art_quick_to_interpreter_bridge+77)\n"
+      "  #43 pc 0000eedb  anonymous:ee74c000 (void Main.runPrimary()+59)\n"
+      "  #44 pc 006ad4d2  libartd.so (art_quick_invoke_stub+338)\n"
+      "  #45 pc 00146ab5  libartd.so "
+      "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+      "const*)+885)\n"
+      "  #46 pc 0039cf0d  libartd.so "
+      "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+      "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
+      "  #47 pc 00392552  libartd.so "
+      "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+      "art::ShadowFrame&, art::JValue, bool)+354)\n"
+      "  #48 pc 0039399a  libartd.so "
+      "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+      "const&, art::ShadowFrame*)+234)\n"
+      "  #49 pc 00684362  libartd.so (artQuickToInterpreterBridge+1058)\n"
+      "  #50 pc 006b35bd  libartd.so (art_quick_to_interpreter_bridge+77)\n"
+      "  #51 pc 0000ac21  anonymous:ee74c000 (void Main.main(java.lang.String[])+97)\n"
+      "  #52 pc 006ad6a2  libartd.so (art_quick_invoke_static_stub+418)\n"
+      "  #53 pc 00146acb  libartd.so "
+      "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+      "const*)+907)\n"
+      "  #54 pc 0039cf0d  libartd.so "
+      "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+      "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
+      "  #55 pc 00392552  libartd.so "
+      "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+      "art::ShadowFrame&, art::JValue, bool)+354)\n"
+      "  #56 pc 0039399a  libartd.so "
+      "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+      "const&, art::ShadowFrame*)+234)\n"
+      "  #57 pc 00684362  libartd.so (artQuickToInterpreterBridge+1058)\n"
+      "  #58 pc 006b35bd  libartd.so (art_quick_to_interpreter_bridge+77)\n"
+      "  #59 pc 006ad6a2  libartd.so (art_quick_invoke_static_stub+418)\n"
+      "  #60 pc 00146acb  libartd.so "
+      "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+      "const*)+907)\n"
+      "  #61 pc 005aac95  libartd.so "
+      "(art::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, "
+      "art::ArgArray*, art::JValue*, char const*)+85)\n"
+      "  #62 pc 005aab5a  libartd.so "
+      "(art::InvokeWithVarArgs(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, "
+      "_jmethodID*, char*)+362)\n"
+      "  #63 pc 0048a3dd  libartd.so "
+      "(art::JNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, char*)+125)\n"
+      "  #64 pc 0018448c  libartd.so "
+      "(art::CheckJNI::CallMethodV(char const*, _JNIEnv*, _jobject*, _jclass*, _jmethodID*, char*, "
+      "art::Primitive::Type, art::InvokeType)+1964)\n"
+      "  #65 pc 0017cf06  libartd.so "
+      "(art::CheckJNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, char*)+70)\n"
+      "  #66 pc 00001d8c  dalvikvm32 "
+      "(_JNIEnv::CallStaticVoidMethod(_jclass*, _jmethodID*, ...)+60)\n"
+      "  #67 pc 00001a80  dalvikvm32 (main+1312)\n"
+      "  #68 pc 00018275  libc.so\n",
+      frame_info);
   EXPECT_EQ(0xeb89bfb8U, unwinder.frames()[0].pc);
   EXPECT_EQ(0xffeb5280U, unwinder.frames()[0].sp);
   EXPECT_EQ(0xeb89af00U, unwinder.frames()[1].pc);
@@ -360,26 +607,174 @@
 }
 
 TEST_F(UnwindOfflineTest, jit_debug_arm) {
-  std::string error_msg;
-  if (!offline_utils_.Init({.offline_files_dir = "jit_debug_arm/",
-                            .arch = ARCH_ARM,
-                            .memory_flag = ProcessMemoryFlag::kIncludeJitMemory},
-                           &error_msg))
-    FAIL() << error_msg;
+  ASSERT_NO_FATAL_FAILURE(Init("jit_debug_arm/", ARCH_ARM));
 
-  Unwinder unwinder(128, offline_utils_.GetMaps(), offline_utils_.GetRegs(),
-                    offline_utils_.GetProcessMemory());
-  unwinder.SetJitDebug(offline_utils_.GetJitDebug());
+  MemoryOfflineParts* memory = new MemoryOfflineParts;
+  AddMemory(dir_ + "descriptor.data", memory);
+  AddMemory(dir_ + "descriptor1.data", memory);
+  AddMemory(dir_ + "stack.data", memory);
+  for (size_t i = 0; i < 7; i++) {
+    AddMemory(dir_ + "entry" + std::to_string(i) + ".data", memory);
+    AddMemory(dir_ + "jit" + std::to_string(i) + ".data", memory);
+  }
+  process_memory_.reset(memory);
+
+  std::unique_ptr<JitDebug> jit_debug = CreateJitDebug(regs_->Arch(), process_memory_);
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
+  unwinder.SetJitDebug(jit_debug.get());
   unwinder.Unwind();
 
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  std::string expected_frame_info;
-  if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg;
-
   std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
-  EXPECT_EQ(expected_frame_info, frame_info);
+  ASSERT_EQ(76U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc 00018a5e  libarttestd.so (Java_Main_unwindInProcess+866)\n"
+      "  #01 pc 0000212d  137-cfi.odex (boolean Main.unwindInProcess(boolean, int, "
+      "boolean)+92)\n"
+      "  #02 pc 00011cb1  anonymous:e2796000 (boolean Main.bar(boolean)+72)\n"
+      "  #03 pc 00462175  libartd.so (art_quick_invoke_stub_internal+68)\n"
+      "  #04 pc 00467129  libartd.so (art_quick_invoke_stub+228)\n"
+      "  #05 pc 000bf7a9  libartd.so "
+      "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+      "const*)+864)\n"
+      "  #06 pc 00247833  libartd.so "
+      "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+      "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
+      "  #07 pc 0022e935  libartd.so "
+      "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+      "art::ShadowFrame&, art::JValue, bool)+244)\n"
+      "  #08 pc 0022f71d  libartd.so "
+      "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+      "const&, art::ShadowFrame*)+128)\n"
+      "  #09 pc 00442865  libartd.so (artQuickToInterpreterBridge+796)\n"
+      "  #10 pc 004666ff  libartd.so (art_quick_to_interpreter_bridge+30)\n"
+      "  #11 pc 00011c31  anonymous:e2796000 (int Main.compare(Main, Main)+64)\n"
+      "  #12 pc 00462175  libartd.so (art_quick_invoke_stub_internal+68)\n"
+      "  #13 pc 00467129  libartd.so (art_quick_invoke_stub+228)\n"
+      "  #14 pc 000bf7a9  libartd.so "
+      "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+      "const*)+864)\n"
+      "  #15 pc 00247833  libartd.so "
+      "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+      "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
+      "  #16 pc 0022e935  libartd.so "
+      "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+      "art::ShadowFrame&, art::JValue, bool)+244)\n"
+      "  #17 pc 0022f71d  libartd.so "
+      "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+      "const&, art::ShadowFrame*)+128)\n"
+      "  #18 pc 00442865  libartd.so (artQuickToInterpreterBridge+796)\n"
+      "  #19 pc 004666ff  libartd.so (art_quick_to_interpreter_bridge+30)\n"
+      "  #20 pc 00011b77  anonymous:e2796000 (int Main.compare(java.lang.Object, "
+      "java.lang.Object)+118)\n"
+      "  #21 pc 00462175  libartd.so (art_quick_invoke_stub_internal+68)\n"
+      "  #22 pc 00467129  libartd.so (art_quick_invoke_stub+228)\n"
+      "  #23 pc 000bf7a9  libartd.so "
+      "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+      "const*)+864)\n"
+      "  #24 pc 00247833  libartd.so "
+      "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+      "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
+      "  #25 pc 0022e935  libartd.so "
+      "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+      "art::ShadowFrame&, art::JValue, bool)+244)\n"
+      "  #26 pc 0022f71d  libartd.so "
+      "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+      "const&, art::ShadowFrame*)+128)\n"
+      "  #27 pc 00442865  libartd.so (artQuickToInterpreterBridge+796)\n"
+      "  #28 pc 004666ff  libartd.so (art_quick_to_interpreter_bridge+30)\n"
+      "  #29 pc 00011a29  anonymous:e2796000 (int "
+      "java.util.Arrays.binarySearch0(java.lang.Object[], int, int, java.lang.Object, "
+      "java.util.Comparator)+304)\n"
+      "  #30 pc 00462175  libartd.so (art_quick_invoke_stub_internal+68)\n"
+      "  #31 pc 0046722f  libartd.so (art_quick_invoke_static_stub+226)\n"
+      "  #32 pc 000bf7bb  libartd.so "
+      "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+      "const*)+882)\n"
+      "  #33 pc 00247833  libartd.so "
+      "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+      "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
+      "  #34 pc 0022e935  libartd.so "
+      "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+      "art::ShadowFrame&, art::JValue, bool)+244)\n"
+      "  #35 pc 0022f71d  libartd.so "
+      "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+      "const&, art::ShadowFrame*)+128)\n"
+      "  #36 pc 00442865  libartd.so (artQuickToInterpreterBridge+796)\n"
+      "  #37 pc 004666ff  libartd.so (art_quick_to_interpreter_bridge+30)\n"
+      "  #38 pc 0001139b  anonymous:e2796000 (boolean Main.foo()+178)\n"
+      "  #39 pc 00462175  libartd.so (art_quick_invoke_stub_internal+68)\n"
+      "  #40 pc 00467129  libartd.so (art_quick_invoke_stub+228)\n"
+      "  #41 pc 000bf7a9  libartd.so "
+      "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+      "const*)+864)\n"
+      "  #42 pc 00247833  libartd.so "
+      "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+      "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
+      "  #43 pc 0022e935  libartd.so "
+      "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+      "art::ShadowFrame&, art::JValue, bool)+244)\n"
+      "  #44 pc 0022f71d  libartd.so "
+      "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+      "const&, art::ShadowFrame*)+128)\n"
+      "  #45 pc 00442865  libartd.so (artQuickToInterpreterBridge+796)\n"
+      "  #46 pc 004666ff  libartd.so (art_quick_to_interpreter_bridge+30)\n"
+      "  #47 pc 00010aa7  anonymous:e2796000 (void Main.runPrimary()+70)\n"
+      "  #48 pc 00462175  libartd.so (art_quick_invoke_stub_internal+68)\n"
+      "  #49 pc 00467129  libartd.so (art_quick_invoke_stub+228)\n"
+      "  #50 pc 000bf7a9  libartd.so "
+      "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+      "const*)+864)\n"
+      "  #51 pc 00247833  libartd.so "
+      "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+      "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
+      "  #52 pc 0022e935  libartd.so "
+      "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+      "art::ShadowFrame&, art::JValue, bool)+244)\n"
+      "  #53 pc 0022f71d  libartd.so "
+      "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+      "const&, art::ShadowFrame*)+128)\n"
+      "  #54 pc 00442865  libartd.so (artQuickToInterpreterBridge+796)\n"
+      "  #55 pc 004666ff  libartd.so (art_quick_to_interpreter_bridge+30)\n"
+      "  #56 pc 0000ba99  anonymous:e2796000 (void Main.main(java.lang.String[])+144)\n"
+      "  #57 pc 00462175  libartd.so (art_quick_invoke_stub_internal+68)\n"
+      "  #58 pc 0046722f  libartd.so (art_quick_invoke_static_stub+226)\n"
+      "  #59 pc 000bf7bb  libartd.so "
+      "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+      "const*)+882)\n"
+      "  #60 pc 00247833  libartd.so "
+      "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+      "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
+      "  #61 pc 0022e935  libartd.so "
+      "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+      "art::ShadowFrame&, art::JValue, bool)+244)\n"
+      "  #62 pc 0022f71d  libartd.so "
+      "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+      "const&, art::ShadowFrame*)+128)\n"
+      "  #63 pc 00442865  libartd.so (artQuickToInterpreterBridge+796)\n"
+      "  #64 pc 004666ff  libartd.so (art_quick_to_interpreter_bridge+30)\n"
+      "  #65 pc 00462175  libartd.so (art_quick_invoke_stub_internal+68)\n"
+      "  #66 pc 0046722f  libartd.so (art_quick_invoke_static_stub+226)\n"
+      "  #67 pc 000bf7bb  libartd.so "
+      "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+      "const*)+882)\n"
+      "  #68 pc 003b292d  libartd.so "
+      "(art::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, "
+      "art::ArgArray*, art::JValue*, char const*)+52)\n"
+      "  #69 pc 003b26c3  libartd.so "
+      "(art::InvokeWithVarArgs(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, "
+      "_jmethodID*, std::__va_list)+210)\n"
+      "  #70 pc 00308411  libartd.so "
+      "(art::JNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, std::__va_list)+76)\n"
+      "  #71 pc 000e6a9f  libartd.so "
+      "(art::CheckJNI::CallMethodV(char const*, _JNIEnv*, _jobject*, _jclass*, _jmethodID*, "
+      "std::__va_list, art::Primitive::Type, art::InvokeType)+1486)\n"
+      "  #72 pc 000e19b9  libartd.so "
+      "(art::CheckJNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, std::__va_list)+40)\n"
+      "  #73 pc 0000159f  dalvikvm32 "
+      "(_JNIEnv::CallStaticVoidMethod(_jclass*, _jmethodID*, ...)+30)\n"
+      "  #74 pc 00001349  dalvikvm32 (main+896)\n"
+      "  #75 pc 000850c9  libc.so\n",
+      frame_info);
   EXPECT_EQ(0xdfe66a5eU, unwinder.frames()[0].pc);
   EXPECT_EQ(0xff85d180U, unwinder.frames()[0].sp);
   EXPECT_EQ(0xe044712dU, unwinder.frames()[1].pc);
@@ -535,17 +930,12 @@
 }
 
 struct LeakType {
-  LeakType(Maps* maps, Regs* regs, std::shared_ptr<Memory>& process_memory,
-           size_t expected_num_frames)
-      : maps(maps),
-        regs(regs),
-        process_memory(process_memory),
-        expected_num_frames(expected_num_frames) {}
+  LeakType(Maps* maps, Regs* regs, std::shared_ptr<Memory>& process_memory)
+      : maps(maps), regs(regs), process_memory(process_memory) {}
 
   Maps* maps;
   Regs* regs;
   std::shared_ptr<Memory>& process_memory;
-  size_t expected_num_frames;
 };
 
 static void OfflineUnwind(void* data) {
@@ -557,23 +947,23 @@
   Unwinder unwinder(128, leak_data->maps, regs_copy.get(), leak_data->process_memory);
   unwinder.SetJitDebug(jit_debug.get());
   unwinder.Unwind();
-  ASSERT_EQ(leak_data->expected_num_frames, unwinder.NumFrames());
+  ASSERT_EQ(76U, unwinder.NumFrames());
 }
 
 TEST_F(UnwindOfflineTest, unwind_offline_check_for_leaks) {
-  std::string error_msg;
-  if (!offline_utils_.Init({.offline_files_dir = "jit_debug_arm/",
-                            .arch = ARCH_ARM,
-                            .memory_flag = ProcessMemoryFlag::kIncludeJitMemory},
-                           &error_msg))
-    FAIL() << error_msg;
+  ASSERT_NO_FATAL_FAILURE(Init("jit_debug_arm/", ARCH_ARM));
 
-  std::shared_ptr<Memory> process_memory = offline_utils_.GetProcessMemory();
+  MemoryOfflineParts* memory = new MemoryOfflineParts;
+  AddMemory(dir_ + "descriptor.data", memory);
+  AddMemory(dir_ + "descriptor1.data", memory);
+  AddMemory(dir_ + "stack.data", memory);
+  for (size_t i = 0; i < 7; i++) {
+    AddMemory(dir_ + "entry" + std::to_string(i) + ".data", memory);
+    AddMemory(dir_ + "jit" + std::to_string(i) + ".data", memory);
+  }
+  process_memory_.reset(memory);
 
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  LeakType data(offline_utils_.GetMaps(), offline_utils_.GetRegs(), process_memory,
-                expected_num_frames);
+  LeakType data(maps_.get(), regs_.get(), process_memory_);
   TestCheckForLeaks(OfflineUnwind, &data);
 }
 
@@ -581,23 +971,20 @@
 // fallback to iterating over the cies/fdes and ignore the eh_frame_hdr.
 // No .gnu_debugdata section in the elf file, so no symbols.
 TEST_F(UnwindOfflineTest, bad_eh_frame_hdr_arm64) {
-  std::string error_msg;
-  if (!offline_utils_.Init({.offline_files_dir = "bad_eh_frame_hdr_arm64/", .arch = ARCH_ARM64},
-                           &error_msg))
-    FAIL() << error_msg;
+  ASSERT_NO_FATAL_FAILURE(Init("bad_eh_frame_hdr_arm64/", ARCH_ARM64));
 
-  Unwinder unwinder(128, offline_utils_.GetMaps(), offline_utils_.GetRegs(),
-                    offline_utils_.GetProcessMemory());
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
   unwinder.Unwind();
 
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  std::string expected_frame_info;
-  if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg;
-
   std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
-  EXPECT_EQ(expected_frame_info, frame_info);
+  ASSERT_EQ(5U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc 0000000000000550  waiter64\n"
+      "  #01 pc 0000000000000568  waiter64\n"
+      "  #02 pc 000000000000057c  waiter64\n"
+      "  #03 pc 0000000000000590  waiter64\n"
+      "  #04 pc 00000000000a8e98  libc.so (__libc_init+88)\n",
+      frame_info);
   EXPECT_EQ(0x60a9fdf550U, unwinder.frames()[0].pc);
   EXPECT_EQ(0x7fdd141990U, unwinder.frames()[0].sp);
   EXPECT_EQ(0x60a9fdf568U, unwinder.frames()[1].pc);
@@ -613,23 +1000,20 @@
 // The elf has bad eh_frame unwind information for the pcs. If eh_frame
 // is used first, the unwind will not match the expected output.
 TEST_F(UnwindOfflineTest, debug_frame_first_x86) {
-  std::string error_msg;
-  if (!offline_utils_.Init({.offline_files_dir = "debug_frame_first_x86/", .arch = ARCH_X86},
-                           &error_msg))
-    FAIL() << error_msg;
+  ASSERT_NO_FATAL_FAILURE(Init("debug_frame_first_x86/", ARCH_X86));
 
-  Unwinder unwinder(128, offline_utils_.GetMaps(), offline_utils_.GetRegs(),
-                    offline_utils_.GetProcessMemory());
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
   unwinder.Unwind();
 
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  std::string expected_frame_info;
-  if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg;
-
   std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
-  EXPECT_EQ(expected_frame_info, frame_info);
+  ASSERT_EQ(5U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc 00000685  waiter (call_level3+53)\n"
+      "  #01 pc 000006b7  waiter (call_level2+23)\n"
+      "  #02 pc 000006d7  waiter (call_level1+23)\n"
+      "  #03 pc 000006f7  waiter (main+23)\n"
+      "  #04 pc 00018275  libc.so\n",
+      frame_info);
   EXPECT_EQ(0x56598685U, unwinder.frames()[0].pc);
   EXPECT_EQ(0xffcf9e38U, unwinder.frames()[0].sp);
   EXPECT_EQ(0x565986b7U, unwinder.frames()[1].pc);
@@ -644,23 +1028,20 @@
 
 // Make sure that a pc that is at the beginning of an fde unwinds correctly.
 TEST_F(UnwindOfflineTest, eh_frame_hdr_begin_x86_64) {
-  std::string error_msg;
-  if (!offline_utils_.Init({.offline_files_dir = "eh_frame_hdr_begin_x86_64/", .arch = ARCH_X86_64},
-                           &error_msg))
-    FAIL() << error_msg;
+  ASSERT_NO_FATAL_FAILURE(Init("eh_frame_hdr_begin_x86_64/", ARCH_X86_64));
 
-  Unwinder unwinder(128, offline_utils_.GetMaps(), offline_utils_.GetRegs(),
-                    offline_utils_.GetProcessMemory());
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
   unwinder.Unwind();
 
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  std::string expected_frame_info;
-  if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg;
-
   std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
-  EXPECT_EQ(expected_frame_info, frame_info);
+  ASSERT_EQ(5U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc 0000000000000a80  unwind_test64 (calling3)\n"
+      "  #01 pc 0000000000000dd9  unwind_test64 (calling2+633)\n"
+      "  #02 pc 000000000000121e  unwind_test64 (calling1+638)\n"
+      "  #03 pc 00000000000013ed  unwind_test64 (main+13)\n"
+      "  #04 pc 00000000000202b0  libc.so\n",
+      frame_info);
   EXPECT_EQ(0x561550b17a80U, unwinder.frames()[0].pc);
   EXPECT_EQ(0x7ffcc8596ce8U, unwinder.frames()[0].sp);
   EXPECT_EQ(0x561550b17dd9U, unwinder.frames()[1].pc);
@@ -674,26 +1055,71 @@
 }
 
 TEST_F(UnwindOfflineTest, art_quick_osr_stub_arm) {
-  std::string error_msg;
-  if (!offline_utils_.Init({.offline_files_dir = "art_quick_osr_stub_arm/",
-                            .arch = ARCH_ARM,
-                            .memory_flag = ProcessMemoryFlag::kIncludeJitMemory},
-                           &error_msg))
-    FAIL() << error_msg;
+  ASSERT_NO_FATAL_FAILURE(Init("art_quick_osr_stub_arm/", ARCH_ARM));
 
-  Unwinder unwinder(128, offline_utils_.GetMaps(), offline_utils_.GetRegs(),
-                    offline_utils_.GetProcessMemory());
-  unwinder.SetJitDebug(offline_utils_.GetJitDebug());
+  MemoryOfflineParts* memory = new MemoryOfflineParts;
+  AddMemory(dir_ + "descriptor.data", memory);
+  AddMemory(dir_ + "stack.data", memory);
+  for (size_t i = 0; i < 2; i++) {
+    AddMemory(dir_ + "entry" + std::to_string(i) + ".data", memory);
+    AddMemory(dir_ + "jit" + std::to_string(i) + ".data", memory);
+  }
+  process_memory_.reset(memory);
+
+  std::unique_ptr<JitDebug> jit_debug = CreateJitDebug(regs_->Arch(), process_memory_);
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
+  unwinder.SetJitDebug(jit_debug.get());
   unwinder.Unwind();
 
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  std::string expected_frame_info;
-  if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg;
-
   std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
-  EXPECT_EQ(expected_frame_info, frame_info);
+  ASSERT_EQ(25U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc 0000c788  <anonymous:d0250000> "
+      "(com.example.simpleperf.simpleperfexamplewithnative.MixActivity.access$000)\n"
+      "  #01 pc 0000cdd5  <anonymous:d0250000> "
+      "(com.example.simpleperf.simpleperfexamplewithnative.MixActivity$1.run+60)\n"
+      "  #02 pc 004135bb  libart.so (art_quick_osr_stub+42)\n"
+      "  #03 pc 002657a5  libart.so "
+      "(art::jit::Jit::MaybeDoOnStackReplacement(art::Thread*, art::ArtMethod*, unsigned int, int, "
+      "art::JValue*)+876)\n"
+      "  #04 pc 004021a7  libart.so (MterpMaybeDoOnStackReplacement+86)\n"
+      "  #05 pc 00412474  libart.so (ExecuteMterpImpl+66164)\n"
+      "  #06 pc cd8365b0  <unknown>\n"  // symbol in dex file
+      "  #07 pc 001d7f1b  libart.so "
+      "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+      "art::ShadowFrame&, art::JValue, bool)+374)\n"
+      "  #08 pc 001dc593  libart.so "
+      "(art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, "
+      "art::CodeItemDataAccessor const&, art::ShadowFrame*, art::JValue*)+154)\n"
+      "  #09 pc 001f4d01  libart.so "
+      "(bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, "
+      "art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+732)\n"
+      "  #10 pc 003fe427  libart.so (MterpInvokeInterface+1354)\n"
+      "  #11 pc 00405b94  libart.so (ExecuteMterpImpl+14740)\n"
+      "  #12 pc 7004873e  <unknown>\n"  // symbol in dex file
+      "  #13 pc 001d7f1b  libart.so "
+      "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+      "art::ShadowFrame&, art::JValue, bool)+374)\n"
+      "  #14 pc 001dc4d5  libart.so "
+      "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+      "const&, art::ShadowFrame*)+92)\n"
+      "  #15 pc 003f25ab  libart.so (artQuickToInterpreterBridge+970)\n"
+      "  #16 pc 00417aff  libart.so (art_quick_to_interpreter_bridge+30)\n"
+      "  #17 pc 00413575  libart.so (art_quick_invoke_stub_internal+68)\n"
+      "  #18 pc 00418531  libart.so (art_quick_invoke_stub+236)\n"
+      "  #19 pc 000b468d  libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned "
+      "int, art::JValue*, char const*)+136)\n"
+      "  #20 pc 00362f49  libart.so "
+      "(art::(anonymous namespace)::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable "
+      "const&, art::ArtMethod*, art::(anonymous namespace)::ArgArray*, art::JValue*, char "
+      "const*)+52)\n"
+      "  #21 pc 00363cd9  libart.so "
+      "(art::InvokeVirtualOrInterfaceWithJValues(art::ScopedObjectAccessAlreadyRunnable const&, "
+      "_jobject*, _jmethodID*, jvalue*)+332)\n"
+      "  #22 pc 003851dd  libart.so (art::Thread::CreateCallback(void*)+868)\n"
+      "  #23 pc 00062925  libc.so (__pthread_start(void*)+22)\n"
+      "  #24 pc 0001de39  libc.so (__start_thread+24)\n",
+      frame_info);
   EXPECT_EQ(0xd025c788U, unwinder.frames()[0].pc);
   EXPECT_EQ(0xcd4ff140U, unwinder.frames()[0].sp);
   EXPECT_EQ(0xd025cdd5U, unwinder.frames()[1].pc);
@@ -747,28 +1173,31 @@
 }
 
 TEST_F(UnwindOfflineTest, jit_map_arm) {
-  std::string error_msg;
-  if (!offline_utils_.Init({.offline_files_dir = "jit_map_arm/", .arch = ARCH_ARM}, &error_msg))
-    FAIL() << error_msg;
+  ASSERT_NO_FATAL_FAILURE(Init("jit_map_arm/", ARCH_ARM));
 
-  Maps* maps = offline_utils_.GetMaps();
-  maps->Add(0xd025c788, 0xd025c9f0, 0, PROT_READ | PROT_EXEC | MAPS_FLAGS_JIT_SYMFILE_MAP,
-            "jit_map0.so", 0);
-  maps->Add(0xd025cd98, 0xd025cff4, 0, PROT_READ | PROT_EXEC | MAPS_FLAGS_JIT_SYMFILE_MAP,
-            "jit_map1.so", 0);
-  maps->Sort();
+  maps_->Add(0xd025c788, 0xd025c9f0, 0, PROT_READ | PROT_EXEC | MAPS_FLAGS_JIT_SYMFILE_MAP,
+             "jit_map0.so", 0);
+  maps_->Add(0xd025cd98, 0xd025cff4, 0, PROT_READ | PROT_EXEC | MAPS_FLAGS_JIT_SYMFILE_MAP,
+             "jit_map1.so", 0);
+  maps_->Sort();
 
-  Unwinder unwinder(128, maps, offline_utils_.GetRegs(), offline_utils_.GetProcessMemory());
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
   unwinder.Unwind();
 
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  std::string expected_frame_info;
-  if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg;
-
   std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
-  EXPECT_EQ(expected_frame_info, frame_info);
+  ASSERT_EQ(6U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc 00000000  jit_map0.so "
+      "(com.example.simpleperf.simpleperfexamplewithnative.MixActivity.access$000)\n"
+      "  #01 pc 0000003d  jit_map1.so "
+      "(com.example.simpleperf.simpleperfexamplewithnative.MixActivity$1.run+60)\n"
+      "  #02 pc 004135bb  libart.so (art_quick_osr_stub+42)\n"
+
+      "  #03 pc 003851dd  libart.so (art::Thread::CreateCallback(void*)+868)\n"
+      "  #04 pc 00062925  libc.so (__pthread_start(void*)+22)\n"
+      "  #05 pc 0001de39  libc.so (__start_thread+24)\n",
+      frame_info);
+
   EXPECT_EQ(0xd025c788U, unwinder.frames()[0].pc);
   EXPECT_EQ(0xcd4ff140U, unwinder.frames()[0].sp);
   EXPECT_EQ(0xd025cdd5U, unwinder.frames()[1].pc);
@@ -784,22 +1213,39 @@
 }
 
 TEST_F(UnwindOfflineTest, offset_arm) {
-  std::string error_msg;
-  if (!offline_utils_.Init({.offline_files_dir = "offset_arm/", .arch = ARCH_ARM}, &error_msg))
-    FAIL() << error_msg;
+  ASSERT_NO_FATAL_FAILURE(Init("offset_arm/", ARCH_ARM));
 
-  Unwinder unwinder(128, offline_utils_.GetMaps(), offline_utils_.GetRegs(),
-                    offline_utils_.GetProcessMemory());
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
   unwinder.Unwind();
 
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  std::string expected_frame_info;
-  if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg;
-
   std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
-  EXPECT_EQ(expected_frame_info, frame_info);
+  ASSERT_EQ(19U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc 0032bfa0  libunwindstack_test (SignalInnerFunction+40)\n"
+      "  #01 pc 0032bfeb  libunwindstack_test (SignalMiddleFunction+2)\n"
+      "  #02 pc 0032bff3  libunwindstack_test (SignalOuterFunction+2)\n"
+      "  #03 pc 0032fed3  libunwindstack_test "
+      "(unwindstack::SignalCallerHandler(int, siginfo*, void*)+26)\n"
+      "  #04 pc 0002652c  libc.so (__restore)\n"
+      "  #05 pc 00000000  <unknown>\n"
+      "  #06 pc 0032c2d9  libunwindstack_test (InnerFunction+736)\n"
+      "  #07 pc 0032cc4f  libunwindstack_test (MiddleFunction+42)\n"
+      "  #08 pc 0032cc81  libunwindstack_test (OuterFunction+42)\n"
+      "  #09 pc 0032e547  libunwindstack_test "
+      "(unwindstack::RemoteThroughSignal(int, unsigned int)+270)\n"
+      "  #10 pc 0032ed99  libunwindstack_test "
+      "(unwindstack::UnwindTest_remote_through_signal_with_invalid_func_Test::TestBody()+16)\n"
+      "  #11 pc 00354453  libunwindstack_test (testing::Test::Run()+154)\n"
+      "  #12 pc 00354de7  libunwindstack_test (testing::TestInfo::Run()+194)\n"
+      "  #13 pc 00355105  libunwindstack_test (testing::TestCase::Run()+180)\n"
+      "  #14 pc 0035a215  libunwindstack_test "
+      "(testing::internal::UnitTestImpl::RunAllTests()+664)\n"
+      "  #15 pc 00359f4f  libunwindstack_test (testing::UnitTest::Run()+110)\n"
+      "  #16 pc 0034d3db  libunwindstack_test (main+38)\n"
+      "  #17 pc 00092c0d  libc.so (__libc_init+48)\n"
+      "  #18 pc 0004202f  libunwindstack_test (_start_main+38)\n",
+      frame_info);
+
   EXPECT_EQ(0x2e55fa0U, unwinder.frames()[0].pc);
   EXPECT_EQ(0xf43d2cccU, unwinder.frames()[0].sp);
   EXPECT_EQ(0x2e55febU, unwinder.frames()[1].pc);
@@ -843,23 +1289,24 @@
 // Test using a non-zero load bias library that has the fde entries
 // encoded as 0xb, which is not set as pc relative.
 TEST_F(UnwindOfflineTest, debug_frame_load_bias_arm) {
-  std::string error_msg;
-  if (!offline_utils_.Init({.offline_files_dir = "debug_frame_load_bias_arm/", .arch = ARCH_ARM},
-                           &error_msg))
-    FAIL() << error_msg;
+  ASSERT_NO_FATAL_FAILURE(Init("debug_frame_load_bias_arm/", ARCH_ARM));
 
-  Unwinder unwinder(128, offline_utils_.GetMaps(), offline_utils_.GetRegs(),
-                    offline_utils_.GetProcessMemory());
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
   unwinder.Unwind();
 
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  std::string expected_frame_info;
-  if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg;
-
   std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
-  EXPECT_EQ(expected_frame_info, frame_info);
+  ASSERT_EQ(8U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc 0005138c  libc.so (__ioctl+8)\n"
+      "  #01 pc 0002140f  libc.so (ioctl+30)\n"
+      "  #02 pc 00039535  libbinder.so (android::IPCThreadState::talkWithDriver(bool)+204)\n"
+      "  #03 pc 00039633  libbinder.so (android::IPCThreadState::getAndExecuteCommand()+10)\n"
+      "  #04 pc 00039b57  libbinder.so (android::IPCThreadState::joinThreadPool(bool)+38)\n"
+      "  #05 pc 00000c21  mediaserver (main+104)\n"
+      "  #06 pc 00084b89  libc.so (__libc_init+48)\n"
+      "  #07 pc 00000b77  mediaserver (_start_main+38)\n",
+      frame_info);
+
   EXPECT_EQ(0xf0be238cU, unwinder.frames()[0].pc);
   EXPECT_EQ(0xffd4a638U, unwinder.frames()[0].sp);
   EXPECT_EQ(0xf0bb240fU, unwinder.frames()[1].pc);
@@ -879,23 +1326,25 @@
 }
 
 TEST_F(UnwindOfflineTest, shared_lib_in_apk_arm64) {
-  std::string error_msg;
-  if (!offline_utils_.Init({.offline_files_dir = "shared_lib_in_apk_arm64/", .arch = ARCH_ARM64},
-                           &error_msg))
-    FAIL() << error_msg;
+  ASSERT_NO_FATAL_FAILURE(Init("shared_lib_in_apk_arm64/", ARCH_ARM64));
 
-  Unwinder unwinder(128, offline_utils_.GetMaps(), offline_utils_.GetRegs(),
-                    offline_utils_.GetProcessMemory());
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
   unwinder.Unwind();
 
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  std::string expected_frame_info;
-  if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg;
-
   std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
-  EXPECT_EQ(expected_frame_info, frame_info);
+  ASSERT_EQ(7U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc 000000000014ccbc  linker64 (__dl_syscall+28)\n"
+      "  #01 pc 000000000005426c  linker64 "
+      "(__dl__ZL24debuggerd_signal_handleriP7siginfoPv+1128)\n"
+      "  #02 pc 00000000000008c0  vdso.so (__kernel_rt_sigreturn)\n"
+      "  #03 pc 00000000000846f4  libc.so (abort+172)\n"
+      "  #04 pc 0000000000084ad4  libc.so (__assert2+36)\n"
+      "  #05 pc 000000000003d5b4  ANGLEPrebuilt.apk!libfeature_support_angle.so (offset 0x4000) "
+      "(ANGLEGetUtilityAPI+56)\n"
+      "  #06 pc 000000000007fe68  libc.so (__libc_init)\n",
+      frame_info);
+
   EXPECT_EQ(0x7e82c4fcbcULL, unwinder.frames()[0].pc);
   EXPECT_EQ(0x7df8ca3bf0ULL, unwinder.frames()[0].sp);
   EXPECT_EQ(0x7e82b5726cULL, unwinder.frames()[1].pc);
@@ -914,31 +1363,27 @@
 }
 
 TEST_F(UnwindOfflineTest, shared_lib_in_apk_memory_only_arm64) {
-  std::string error_msg;
-  if (!offline_utils_.Init(
-          {.offline_files_dir = "shared_lib_in_apk_memory_only_arm64/", .arch = ARCH_ARM64},
-          &error_msg))
-    FAIL() << error_msg;
+  ASSERT_NO_FATAL_FAILURE(Init("shared_lib_in_apk_memory_only_arm64/", ARCH_ARM64));
   // Add the memory that represents the shared library.
+  MemoryOfflineParts* memory = reinterpret_cast<MemoryOfflineParts*>(process_memory_.get());
+  AddMemory(dir_ + "lib_mem.data", memory);
 
-  std::shared_ptr<Memory> process_memory = offline_utils_.GetProcessMemory();
-  MemoryOfflineParts* memory = reinterpret_cast<MemoryOfflineParts*>(process_memory.get());
-  const std::string* offline_files_path = offline_utils_.GetOfflineFilesPath();
-  if (offline_files_path == nullptr) FAIL() << "GetOfflineFilesPath() failed.";
-
-  if (!AddMemory(*offline_files_path + "lib_mem.data", memory, &error_msg)) FAIL() << error_msg;
-
-  Unwinder unwinder(128, offline_utils_.GetMaps(), offline_utils_.GetRegs(), process_memory);
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
   unwinder.Unwind();
 
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  std::string expected_frame_info;
-  if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg;
-
   std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
-  EXPECT_EQ(expected_frame_info, frame_info);
+  ASSERT_EQ(7U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc 000000000014ccbc  linker64 (__dl_syscall+28)\n"
+      "  #01 pc 000000000005426c  linker64 "
+      "(__dl__ZL24debuggerd_signal_handleriP7siginfoPv+1128)\n"
+      "  #02 pc 00000000000008c0  vdso.so (__kernel_rt_sigreturn)\n"
+      "  #03 pc 00000000000846f4  libc.so (abort+172)\n"
+      "  #04 pc 0000000000084ad4  libc.so (__assert2+36)\n"
+      "  #05 pc 000000000003d5b4  ANGLEPrebuilt.apk (offset 0x21d5000)\n"
+      "  #06 pc 000000000007fe68  libc.so (__libc_init)\n",
+      frame_info);
+
   EXPECT_EQ(0x7e82c4fcbcULL, unwinder.frames()[0].pc);
   EXPECT_EQ(0x7df8ca3bf0ULL, unwinder.frames()[0].sp);
   EXPECT_EQ(0x7e82b5726cULL, unwinder.frames()[1].pc);
@@ -957,24 +1402,29 @@
 }
 
 TEST_F(UnwindOfflineTest, shared_lib_in_apk_single_map_arm64) {
-  std::string error_msg;
-  if (!offline_utils_.Init(
-          {.offline_files_dir = "shared_lib_in_apk_single_map_arm64/", .arch = ARCH_ARM64},
-          &error_msg))
-    FAIL() << error_msg;
+  ASSERT_NO_FATAL_FAILURE(Init("shared_lib_in_apk_single_map_arm64/", ARCH_ARM64));
 
-  Unwinder unwinder(128, offline_utils_.GetMaps(), offline_utils_.GetRegs(),
-                    offline_utils_.GetProcessMemory());
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
   unwinder.Unwind();
 
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  std::string expected_frame_info;
-  if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg;
-
   std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
-  EXPECT_EQ(expected_frame_info, frame_info);
+  ASSERT_EQ(13U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc 00000000000814bc  libc.so (syscall+28)\n"
+      "  #01 pc 00000000008cdf5c  test.apk (offset 0x5000)\n"
+      "  #02 pc 00000000008cde9c  test.apk (offset 0x5000)\n"
+      "  #03 pc 00000000008cdd70  test.apk (offset 0x5000)\n"
+      "  #04 pc 00000000008ce408  test.apk (offset 0x5000)\n"
+      "  #05 pc 00000000008ce8d8  test.apk (offset 0x5000)\n"
+      "  #06 pc 00000000008ce814  test.apk (offset 0x5000)\n"
+      "  #07 pc 00000000008bcf60  test.apk (offset 0x5000)\n"
+      "  #08 pc 0000000000133024  test.apk (offset 0x5000)\n"
+      "  #09 pc 0000000000134ad0  test.apk (offset 0x5000)\n"
+      "  #10 pc 0000000000134b64  test.apk (offset 0x5000)\n"
+      "  #11 pc 00000000000e406c  libc.so (__pthread_start(void*)+36)\n"
+      "  #12 pc 0000000000085e18  libc.so (__start_thread+64)\n",
+      frame_info);
+
   EXPECT_EQ(0x7cbe0b14bcULL, unwinder.frames()[0].pc);
   EXPECT_EQ(0x7be4f077d0ULL, unwinder.frames()[0].sp);
   EXPECT_EQ(0x7be6715f5cULL, unwinder.frames()[1].pc);
@@ -1004,42 +1454,26 @@
 }
 
 TEST_F(UnwindOfflineTest, invalid_elf_offset_arm) {
-  std::string error_msg;
-  if (!offline_utils_.Init({.offline_files_dir = "invalid_elf_offset_arm/",
-                            .arch = ARCH_ARM,
-                            .memory_flag = ProcessMemoryFlag::kNoMemory},
-                           &error_msg))
-    FAIL() << error_msg;
+  ASSERT_NO_FATAL_FAILURE(Init("invalid_elf_offset_arm/", ARCH_ARM, false));
 
-  Unwinder unwinder(128, offline_utils_.GetMaps(), offline_utils_.GetRegs(),
-                    offline_utils_.GetProcessMemory());
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
   unwinder.Unwind();
 
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-
   std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  ASSERT_EQ(1U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
   EXPECT_EQ("  #00 pc 00aa7508  invalid.apk (offset 0x12e4000)\n", frame_info);
   EXPECT_EQ(0xc898f508, unwinder.frames()[0].pc);
   EXPECT_EQ(0xc2044218, unwinder.frames()[0].sp);
 }
 
 TEST_F(UnwindOfflineTest, load_bias_ro_rx_x86_64) {
-  std::string error_msg;
-  if (!offline_utils_.Init({.offline_files_dir = "load_bias_ro_rx_x86_64/", .arch = ARCH_X86_64},
-                           &error_msg))
-    FAIL() << error_msg;
+  ASSERT_NO_FATAL_FAILURE(Init("load_bias_ro_rx_x86_64/", ARCH_X86_64));
 
-  Unwinder unwinder(128, offline_utils_.GetMaps(), offline_utils_.GetRegs(),
-                    offline_utils_.GetProcessMemory());
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
   unwinder.Unwind();
 
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-
   std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  ASSERT_EQ(17U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
   EXPECT_EQ(
       "  #00 pc 00000000000e9dd4  libc.so (__write+20)\n"
       "  #01 pc 000000000007ab9c  libc.so (_IO_file_write+44)\n"
@@ -1110,24 +1544,28 @@
 }
 
 TEST_F(UnwindOfflineTest, load_bias_different_section_bias_arm64) {
-  std::string error_msg;
-  if (!offline_utils_.Init(
-          {.offline_files_dir = "load_bias_different_section_bias_arm64/", .arch = ARCH_ARM64},
-          &error_msg))
-    FAIL() << error_msg;
+  ASSERT_NO_FATAL_FAILURE(Init("load_bias_different_section_bias_arm64/", ARCH_ARM64));
 
-  Unwinder unwinder(128, offline_utils_.GetMaps(), offline_utils_.GetRegs(),
-                    offline_utils_.GetProcessMemory());
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
   unwinder.Unwind();
 
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  std::string expected_frame_info;
-  if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg;
-
   std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
-  EXPECT_EQ(expected_frame_info, frame_info);
+  ASSERT_EQ(12U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc 00000000000d59bc  linker64 (__dl_syscall+28)\n"
+      "  #01 pc 00000000000554e8  linker64 (__dl__ZL24debuggerd_signal_handleriP7siginfoPv+1148)\n"
+      "  #02 pc 00000000000008c0  vdso (__kernel_rt_sigreturn)\n"
+      "  #03 pc 000000000007f3e8  libc.so (abort+168)\n"
+      "  #04 pc 00000000000459fc  test (std::__ndk1::__throw_bad_cast()+4)\n"
+      "  #05 pc 0000000000056d80  test (testing::Test::Run()+88)\n"
+      "  #06 pc 000000000005724c  test (testing::TestInfo::Run()+112)\n"
+      "  #07 pc 0000000000057558  test (testing::TestSuite::Run()+116)\n"
+      "  #08 pc 000000000005bffc  test (testing::internal::UnitTestImpl::RunAllTests()+464)\n"
+      "  #09 pc 000000000005bd9c  test (testing::UnitTest::Run()+116)\n"
+      "  #10 pc 00000000000464e4  test (main+144)\n"
+      "  #11 pc 000000000007aa34  libc.so (__libc_init+108)\n",
+      frame_info);
+
   EXPECT_EQ(0x7112cb99bcULL, unwinder.frames()[0].pc);
   EXPECT_EQ(0x7112bdbbf0ULL, unwinder.frames()[0].sp);
   EXPECT_EQ(0x7112c394e8ULL, unwinder.frames()[1].pc);
@@ -1155,23 +1593,27 @@
 }
 
 TEST_F(UnwindOfflineTest, eh_frame_bias_x86) {
-  std::string error_msg;
-  if (!offline_utils_.Init({.offline_files_dir = "eh_frame_bias_x86/", .arch = ARCH_X86},
-                           &error_msg))
-    FAIL() << error_msg;
+  ASSERT_NO_FATAL_FAILURE(Init("eh_frame_bias_x86/", ARCH_X86));
 
-  Unwinder unwinder(128, offline_utils_.GetMaps(), offline_utils_.GetRegs(),
-                    offline_utils_.GetProcessMemory());
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
   unwinder.Unwind();
 
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  std::string expected_frame_info;
-  if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg;
-
   std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
-  EXPECT_EQ(expected_frame_info, frame_info);
+  ASSERT_EQ(11U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc ffffe430  vdso.so (__kernel_vsyscall+16)\n"
+      "  #01 pc 00082a4b  libc.so (__epoll_pwait+43)\n"
+      "  #02 pc 000303a3  libc.so (epoll_pwait+115)\n"
+      "  #03 pc 000303ed  libc.so (epoll_wait+45)\n"
+      "  #04 pc 00010ea2  tombstoned (epoll_dispatch+226)\n"
+      "  #05 pc 0000c5e7  tombstoned (event_base_loop+1095)\n"
+      "  #06 pc 0000c193  tombstoned (event_base_dispatch+35)\n"
+      "  #07 pc 00005c77  tombstoned (main+884)\n"
+      "  #08 pc 00015f66  libc.so (__libc_init+102)\n"
+      "  #09 pc 0000360e  tombstoned (_start+98)\n"
+      "  #10 pc 00000001  <unknown>\n",
+      frame_info);
+
   EXPECT_EQ(0xffffe430ULL, unwinder.frames()[0].pc);
   EXPECT_EQ(0xfffe1a30ULL, unwinder.frames()[0].sp);
   EXPECT_EQ(0xeb585a4bULL, unwinder.frames()[1].pc);
@@ -1197,23 +1639,37 @@
 }
 
 TEST_F(UnwindOfflineTest, signal_load_bias_arm) {
-  std::string error_msg;
-  if (!offline_utils_.Init({.offline_files_dir = "signal_load_bias_arm/", .arch = ARCH_ARM},
-                           &error_msg))
-    FAIL() << error_msg;
+  ASSERT_NO_FATAL_FAILURE(Init("signal_load_bias_arm/", ARCH_ARM));
 
-  Unwinder unwinder(128, offline_utils_.GetMaps(), offline_utils_.GetRegs(),
-                    offline_utils_.GetProcessMemory());
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
   unwinder.Unwind();
 
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  std::string expected_frame_info;
-  if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg;
-
   std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
-  EXPECT_EQ(expected_frame_info, frame_info);
+  ASSERT_EQ(17U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc 0029ef9e  libunwindstack_unit_test (SignalInnerFunction+10)\n"
+      "  #01 pc 0029efa7  libunwindstack_unit_test (SignalMiddleFunction+2)\n"
+      "  #02 pc 0029efaf  libunwindstack_unit_test (SignalOuterFunction+2)\n"
+      "  #03 pc 002a280b  libunwindstack_unit_test (unwindstack::SignalCallerHandler(int, "
+      "siginfo*, void*)+10)\n"
+      "  #04 pc 00058bd4  libc.so (__restore)\n"
+      "  #05 pc 0029f01e  libunwindstack_unit_test (InnerFunction+106)\n"
+      "  #06 pc 0029f633  libunwindstack_unit_test (MiddleFunction+16)\n"
+      "  #07 pc 0029f64b  libunwindstack_unit_test (OuterFunction+16)\n"
+      "  #08 pc 002a1711  libunwindstack_unit_test (unwindstack::RemoteThroughSignal(int, unsigned "
+      "int)+260)\n"
+      "  #09 pc 002a1603  libunwindstack_unit_test "
+      "(unwindstack::UnwindTest_remote_through_signal_Test::TestBody()+10)\n"
+      "  #10 pc 002c8fe3  libunwindstack_unit_test (testing::Test::Run()+130)\n"
+      "  #11 pc 002c9b25  libunwindstack_unit_test (testing::TestInfo::Run()+184)\n"
+      "  #12 pc 002c9e27  libunwindstack_unit_test (testing::TestSuite::Run()+202)\n"
+      "  #13 pc 002d193d  libunwindstack_unit_test "
+      "(testing::internal::UnitTestImpl::RunAllTests()+660)\n"
+      "  #14 pc 002d160b  libunwindstack_unit_test (testing::UnitTest::Run()+134)\n"
+      "  #15 pc 002de035  libunwindstack_unit_test (IsolateMain+680)\n"
+      "  #16 pc 00058155  libc.so (__libc_init+68)\n",
+      frame_info);
+
   EXPECT_EQ(0xb6955f9eULL, unwinder.frames()[0].pc);
   EXPECT_EQ(0xf2790ce8ULL, unwinder.frames()[0].sp);
   EXPECT_EQ(0xb6955fa7ULL, unwinder.frames()[1].pc);
@@ -1251,22 +1707,25 @@
 }
 
 TEST_F(UnwindOfflineTest, empty_arm64) {
-  std::string error_msg;
-  if (!offline_utils_.Init({.offline_files_dir = "empty_arm64/", .arch = ARCH_ARM64}, &error_msg))
-    FAIL() << error_msg;
+  ASSERT_NO_FATAL_FAILURE(Init("empty_arm64/", ARCH_ARM64));
 
-  Unwinder unwinder(128, offline_utils_.GetMaps(), offline_utils_.GetRegs(),
-                    offline_utils_.GetProcessMemory());
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
   unwinder.Unwind();
 
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  std::string expected_frame_info;
-  if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg;
-
   std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
-  EXPECT_EQ(expected_frame_info, frame_info);
+  ASSERT_EQ(7U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc 00000000000963a4  libc.so (__ioctl+4)\n"
+      "  #01 pc 000000000005344c  libc.so (ioctl+140)\n"
+      "  #02 pc 0000000000050ce4  libbinder.so "
+      "(android::IPCThreadState::talkWithDriver(bool)+308)\n"
+      "  #03 pc 0000000000050e98  libbinder.so "
+      "(android::IPCThreadState::getAndExecuteCommand()+24)\n"
+      "  #04 pc 00000000000516ac  libbinder.so (android::IPCThreadState::joinThreadPool(bool)+60)\n"
+      "  #05 pc 00000000000443b0  netd (main+1056)\n"
+      "  #06 pc 0000000000045594  libc.so (__libc_init+108)\n",
+      frame_info);
+
   EXPECT_EQ(0x72a02203a4U, unwinder.frames()[0].pc);
   EXPECT_EQ(0x7ffb6c0b50U, unwinder.frames()[0].sp);
   EXPECT_EQ(0x72a01dd44cU, unwinder.frames()[1].pc);
@@ -1287,22 +1746,40 @@
 // that the signal handler match does not occur and it uses the
 // fde to do the unwind.
 TEST_F(UnwindOfflineTest, signal_fde_x86) {
-  std::string error_msg;
-  if (!offline_utils_.Init({.offline_files_dir = "signal_fde_x86/", .arch = ARCH_X86}, &error_msg))
-    FAIL() << error_msg;
+  ASSERT_NO_FATAL_FAILURE(Init("signal_fde_x86/", ARCH_X86));
 
-  Unwinder unwinder(128, offline_utils_.GetMaps(), offline_utils_.GetRegs(),
-                    offline_utils_.GetProcessMemory());
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
   unwinder.Unwind();
 
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  std::string expected_frame_info;
-  if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg;
-
   std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
-  EXPECT_EQ(expected_frame_info, frame_info);
+  ASSERT_EQ(20U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc 007914d9  libunwindstack_test (SignalInnerFunction+25)\n"
+      "  #01 pc 007914fc  libunwindstack_test (SignalMiddleFunction+28)\n"
+      "  #02 pc 0079152c  libunwindstack_test (SignalOuterFunction+28)\n"
+      "  #03 pc 0079af62  libunwindstack_test (unwindstack::SignalCallerHandler(int, siginfo*, "
+      "void*)+50)\n"
+      "  #04 pc 00058fb0  libc.so (__restore)\n"
+      "  #05 pc 00000000  <unknown>\n"
+      "  #06 pc 0079161a  libunwindstack_test (InnerFunction+218)\n"
+      "  #07 pc 007923aa  libunwindstack_test (MiddleFunction+42)\n"
+      "  #08 pc 007923ea  libunwindstack_test (OuterFunction+42)\n"
+      "  #09 pc 00797444  libunwindstack_test (unwindstack::RemoteThroughSignal(int, unsigned "
+      "int)+868)\n"
+      "  #10 pc 007985b8  libunwindstack_test "
+      "(unwindstack::UnwindTest_remote_through_signal_with_invalid_func_Test::TestBody()+56)\n"
+      "  #11 pc 00817a19  libunwindstack_test\n"
+      "  #12 pc 008178c5  libunwindstack_test (testing::Test::Run()+277)\n"
+      "  #13 pc 00818d3e  libunwindstack_test (testing::TestInfo::Run()+318)\n"
+      "  #14 pc 008198b4  libunwindstack_test (testing::TestSuite::Run()+436)\n"
+      "  #15 pc 00828cb0  libunwindstack_test "
+      "(testing::internal::UnitTestImpl::RunAllTests()+1216)\n"
+      "  #16 pc 0082870f  libunwindstack_test (testing::UnitTest::Run()+367)\n"
+      "  #17 pc 0084031e  libunwindstack_test (IsolateMain+2334)\n"
+      "  #18 pc 0083f9e9  libunwindstack_test (main+41)\n"
+      "  #19 pc 00050646  libc.so (__libc_init+118)\n",
+      frame_info);
+
   EXPECT_EQ(0x5ae0d4d9U, unwinder.frames()[0].pc);
   EXPECT_EQ(0xecb37188U, unwinder.frames()[0].sp);
   EXPECT_EQ(0x5ae0d4fcU, unwinder.frames()[1].pc);
@@ -1349,23 +1826,38 @@
 // that the signal handler match does not occur and it uses the
 // fde to do the unwind.
 TEST_F(UnwindOfflineTest, signal_fde_x86_64) {
-  std::string error_msg;
-  if (!offline_utils_.Init({.offline_files_dir = "signal_fde_x86_64/", .arch = ARCH_X86_64},
-                           &error_msg))
-    FAIL() << error_msg;
+  ASSERT_NO_FATAL_FAILURE(Init("signal_fde_x86_64/", ARCH_X86_64));
 
-  Unwinder unwinder(128, offline_utils_.GetMaps(), offline_utils_.GetRegs(),
-                    offline_utils_.GetProcessMemory());
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
   unwinder.Unwind();
 
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  std::string expected_frame_info;
-  if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg;
-
   std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
-  EXPECT_EQ(expected_frame_info, frame_info);
+  ASSERT_EQ(18U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc 000000000058415b  libunwindstack_test (SignalInnerFunction+11)\n"
+      "  #01 pc 0000000000584168  libunwindstack_test (SignalMiddleFunction+8)\n"
+      "  #02 pc 0000000000584178  libunwindstack_test (SignalOuterFunction+8)\n"
+      "  #03 pc 000000000058ac77  libunwindstack_test (unwindstack::SignalCallerHandler(int, "
+      "siginfo*, void*)+23)\n"
+      "  #04 pc 0000000000057d10  libc.so (__restore_rt)\n"
+      "  #05 pc 0000000000000000  <unknown>\n"
+      "  #06 pc 0000000000584244  libunwindstack_test (InnerFunction+196)\n"
+      "  #07 pc 0000000000584b44  libunwindstack_test (MiddleFunction+20)\n"
+      "  #08 pc 0000000000584b64  libunwindstack_test (OuterFunction+20)\n"
+      "  #09 pc 0000000000588457  libunwindstack_test (unwindstack::RemoteThroughSignal(int, "
+      "unsigned int)+583)\n"
+      "  #10 pc 0000000000588f67  libunwindstack_test "
+      "(unwindstack::UnwindTest_remote_through_signal_with_invalid_func_Test::TestBody()+23)\n"
+      "  #11 pc 00000000005d9c38  libunwindstack_test (testing::Test::Run()+216)\n"
+      "  #12 pc 00000000005daf9a  libunwindstack_test (testing::TestInfo::Run()+266)\n"
+      "  #13 pc 00000000005dba46  libunwindstack_test (testing::TestSuite::Run()+390)\n"
+      "  #14 pc 00000000005ea4c6  libunwindstack_test "
+      "(testing::internal::UnitTestImpl::RunAllTests()+1190)\n"
+      "  #15 pc 00000000005e9f61  libunwindstack_test (testing::UnitTest::Run()+337)\n"
+      "  #16 pc 0000000000600155  libunwindstack_test (IsolateMain+2037)\n"
+      "  #17 pc 000000000004e405  libc.so (__libc_init+101)\n",
+      frame_info);
+
   EXPECT_EQ(0x5bb41271e15bU, unwinder.frames()[0].pc);
   EXPECT_EQ(0x707eb5aa8320U, unwinder.frames()[0].sp);
   EXPECT_EQ(0x5bb41271e168U, unwinder.frames()[1].pc);
@@ -1405,25 +1897,45 @@
 }
 
 TEST_F(UnwindOfflineTest, pauth_pc_arm64) {
-  std::string error_msg;
-  if (!offline_utils_.Init({.offline_files_dir = "pauth_pc_arm64/", .arch = ARCH_ARM64},
-                           &error_msg))
-    FAIL() << error_msg;
+  ASSERT_NO_FATAL_FAILURE(Init("pauth_pc_arm64/", ARCH_ARM64));
 
-  static_cast<RegsArm64*>(offline_utils_.GetRegs())->SetPACMask(0x007fff8000000000ULL);
+  static_cast<RegsArm64*>(regs_.get())->SetPACMask(0x007fff8000000000ULL);
 
-  Unwinder unwinder(128, offline_utils_.GetMaps(), offline_utils_.GetRegs(),
-                    offline_utils_.GetProcessMemory());
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
   unwinder.Unwind();
 
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  std::string expected_frame_info;
-  if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg;
-
   std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
-  EXPECT_EQ(expected_frame_info, frame_info);
+  ASSERT_EQ(26U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc 00000000000404a8  toybox (do_print+28)\n"
+      "  #01 pc 0000000000040270  toybox (do_find+5072)\n"
+      "  #02 pc 000000000002c640  toybox (dirtree_handle_callback+40)\n"
+      "  #03 pc 000000000002c588  toybox (dirtree_recurse+200)\n"
+      "  #04 pc 000000000002c6a8  toybox (dirtree_handle_callback+144)\n"
+      "  #05 pc 000000000002c588  toybox (dirtree_recurse+200)\n"
+      "  #06 pc 000000000002c6a8  toybox (dirtree_handle_callback+144)\n"
+      "  #07 pc 000000000002c588  toybox (dirtree_recurse+200)\n"
+      "  #08 pc 000000000002c6a8  toybox (dirtree_handle_callback+144)\n"
+      "  #09 pc 000000000002c588  toybox (dirtree_recurse+200)\n"
+      "  #10 pc 000000000002c6a8  toybox (dirtree_handle_callback+144)\n"
+      "  #11 pc 000000000002c588  toybox (dirtree_recurse+200)\n"
+      "  #12 pc 000000000002c6a8  toybox (dirtree_handle_callback+144)\n"
+      "  #13 pc 000000000002c588  toybox (dirtree_recurse+200)\n"
+      "  #14 pc 000000000002c6a8  toybox (dirtree_handle_callback+144)\n"
+      "  #15 pc 000000000002c588  toybox (dirtree_recurse+200)\n"
+      "  #16 pc 000000000002c6a8  toybox (dirtree_handle_callback+144)\n"
+      "  #17 pc 000000000002c588  toybox (dirtree_recurse+200)\n"
+      "  #18 pc 000000000002c6a8  toybox (dirtree_handle_callback+144)\n"
+      "  #19 pc 000000000002c588  toybox (dirtree_recurse+200)\n"
+      "  #20 pc 000000000002c6a8  toybox (dirtree_handle_callback+144)\n"
+      "  #21 pc 000000000003ee54  toybox (find_main+272)\n"
+      "  #22 pc 0000000000034834  toybox (toy_exec_which+88)\n"
+      "  #23 pc 00000000000342cc  toybox (toybox_main+148)\n"
+      "  #24 pc 00000000000348b4  toybox (main+120)\n"
+      "  #25 pc 00000000000499d8  libc.so "
+      "(__libc_init+112)\n",
+      frame_info);
+
   EXPECT_EQ(0x5c390884a8U, unwinder.frames()[0].pc);
   EXPECT_EQ(0x7ff3511750U, unwinder.frames()[0].sp);
   EXPECT_EQ(0x5c39088270U, unwinder.frames()[1].pc);
@@ -1478,185 +1990,4 @@
   EXPECT_EQ(0x7ff3511e70U, unwinder.frames()[25].sp);
 }
 
-TEST_F(UnwindOfflineTest, profiler_like_multi_process) {
-  ConsecutiveUnwindTest(std::vector<UnwindSampleInfo>{
-      {.offline_files_dir = "bluetooth_arm64/pc_1/", .arch = ARCH_ARM64},
-      {.offline_files_dir = "jit_debug_arm/",
-       .arch = ARCH_ARM,
-       .memory_flag = ProcessMemoryFlag::kIncludeJitMemory},
-      {.offline_files_dir = "photos_reset_arm64/", .arch = ARCH_ARM64},
-      {.offline_files_dir = "youtube_compiled_arm64/", .arch = ARCH_ARM64},
-      {.offline_files_dir = "yt_music_arm64/", .arch = ARCH_ARM64},
-      {.offline_files_dir = "maps_compiled_arm64/28656_oat_odex_jar/", .arch = ARCH_ARM64}});
-}
-
-TEST_F(UnwindOfflineTest, profiler_like_single_process_multi_thread) {
-  ConsecutiveUnwindTest(std::vector<UnwindSampleInfo>{
-      {.offline_files_dir = "maps_compiled_arm64/28656_oat_odex_jar/", .arch = ARCH_ARM64},
-      {.offline_files_dir = "maps_compiled_arm64/28613_main-thread/", .arch = ARCH_ARM64},
-      {.offline_files_dir = "maps_compiled_arm64/28644/", .arch = ARCH_ARM64},
-      {.offline_files_dir = "maps_compiled_arm64/28648/", .arch = ARCH_ARM64},
-      {.offline_files_dir = "maps_compiled_arm64/28667/", .arch = ARCH_ARM64}});
-}
-
-TEST_F(UnwindOfflineTest, profiler_like_single_thread_diverse_pcs) {
-  ConsecutiveUnwindTest(std::vector<UnwindSampleInfo>{
-      {.offline_files_dir = "bluetooth_arm64/pc_1/", .arch = ARCH_ARM64},
-      {.offline_files_dir = "bluetooth_arm64/pc_2/", .arch = ARCH_ARM64},
-      {.offline_files_dir = "bluetooth_arm64/pc_3/", .arch = ARCH_ARM64},
-      {.offline_files_dir = "bluetooth_arm64/pc_4/", .arch = ARCH_ARM64}});
-}
-
-static void VerifyApkRORX(Unwinder& unwinder) {
-  EXPECT_EQ(0x7426d2e030U, unwinder.frames()[0].pc);
-  EXPECT_EQ(0x7fe740cc90U, unwinder.frames()[0].sp);
-  EXPECT_EQ(0x7426d2e08cU, unwinder.frames()[1].pc);
-  EXPECT_EQ(0x7fe740ccd0U, unwinder.frames()[1].sp);
-  EXPECT_EQ(0x7426d2e0b8U, unwinder.frames()[2].pc);
-  EXPECT_EQ(0x7fe740ccf0U, unwinder.frames()[2].sp);
-  EXPECT_EQ(0x7426d2e0e4U, unwinder.frames()[3].pc);
-  EXPECT_EQ(0x7fe740cd10U, unwinder.frames()[3].sp);
-  EXPECT_EQ(0x603b0c5154U, unwinder.frames()[4].pc);
-  EXPECT_EQ(0x7fe740cd30U, unwinder.frames()[4].sp);
-  EXPECT_EQ(0x76b6df0b10U, unwinder.frames()[5].pc);
-  EXPECT_EQ(0x7fe740cdb0U, unwinder.frames()[5].sp);
-}
-
-TEST_F(UnwindOfflineTest, apk_rorx_arm64) {
-  std::string error_msg;
-  if (!offline_utils_.Init({.offline_files_dir = "apk_rorx_arm64/", .arch = ARCH_ARM64},
-                           &error_msg))
-    FAIL() << error_msg;
-
-  Unwinder unwinder(128, offline_utils_.GetMaps(), offline_utils_.GetRegs(),
-                    offline_utils_.GetProcessMemory());
-  unwinder.Unwind();
-
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  std::string expected_frame_info;
-  if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg;
-
-  std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
-  EXPECT_EQ(expected_frame_info, frame_info);
-
-  VerifyApkRORX(unwinder);
-}
-
-TEST_F(UnwindOfflineTest, apk_rorx_unreadable_arm64) {
-  std::string error_msg;
-  if (!offline_utils_.Init({.offline_files_dir = "apk_rorx_unreadable_arm64/", .arch = ARCH_ARM64},
-                           &error_msg))
-    FAIL() << error_msg;
-
-  // Create a process memory object that holds the apk data in memory
-  // along with the stack data.
-  MemoryOffline* stack_memory = new MemoryOffline;
-  ASSERT_TRUE(stack_memory->Init("stack.data", 0));
-
-  MemoryOffline* apk_memory = new MemoryOffline;
-  auto info1 = offline_utils_.GetMaps()->Find(0x7426d2d000);
-  ASSERT_TRUE(info1 != nullptr);
-  auto info2 = offline_utils_.GetMaps()->Find(0x7426d2e000);
-  ASSERT_TRUE(info2 != nullptr);
-  ASSERT_TRUE(
-      apk_memory->Init("fake.apk", info1->offset(), info1->start(), info2->end() - info1->start()));
-
-  std::unique_ptr<MemoryOfflineParts> parts(new MemoryOfflineParts);
-  parts->Add(stack_memory);
-  parts->Add(apk_memory);
-
-  std::shared_ptr<Memory> process_memory(parts.release());
-
-  Unwinder unwinder(128, offline_utils_.GetMaps(), offline_utils_.GetRegs(), process_memory);
-  unwinder.Unwind();
-
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  std::string expected_frame_info;
-  if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg;
-
-  std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
-  EXPECT_EQ(expected_frame_info, frame_info);
-
-  VerifyApkRORX(unwinder);
-}
-
-static void VerifyApkRX(Unwinder& unwinder) {
-  EXPECT_EQ(0x7cb0e6266cU, unwinder.frames()[0].pc);
-  EXPECT_EQ(0x7fe563be90U, unwinder.frames()[0].sp);
-  EXPECT_EQ(0x7cb0e626c0U, unwinder.frames()[1].pc);
-  EXPECT_EQ(0x7fe563bed0U, unwinder.frames()[1].sp);
-  EXPECT_EQ(0x7cb0e626ecU, unwinder.frames()[2].pc);
-  EXPECT_EQ(0x7fe563bef0U, unwinder.frames()[2].sp);
-  EXPECT_EQ(0x7cb0e62718U, unwinder.frames()[3].pc);
-  EXPECT_EQ(0x7fe563bf10U, unwinder.frames()[3].sp);
-  EXPECT_EQ(0x5e004f0154U, unwinder.frames()[4].pc);
-  EXPECT_EQ(0x7fe563bf30U, unwinder.frames()[4].sp);
-  EXPECT_EQ(0x7f41124b10U, unwinder.frames()[5].pc);
-  EXPECT_EQ(0x7fe563bfb0U, unwinder.frames()[5].sp);
-}
-
-TEST_F(UnwindOfflineTest, apk_rx_arm64) {
-  std::string error_msg;
-  if (!offline_utils_.Init({.offline_files_dir = "apk_rx_arm64/", .arch = ARCH_ARM64}, &error_msg))
-    FAIL() << error_msg;
-
-  Unwinder unwinder(128, offline_utils_.GetMaps(), offline_utils_.GetRegs(),
-                    offline_utils_.GetProcessMemory());
-  unwinder.Unwind();
-
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  std::string expected_frame_info;
-  if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg;
-
-  std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
-  EXPECT_EQ(expected_frame_info, frame_info);
-
-  VerifyApkRX(unwinder);
-}
-
-TEST_F(UnwindOfflineTest, apk_rx_unreadable_arm64) {
-  std::string error_msg;
-  if (!offline_utils_.Init({.offline_files_dir = "apk_rx_unreadable_arm64/", .arch = ARCH_ARM64},
-                           &error_msg))
-    FAIL() << error_msg;
-
-  // Create a process memory object that holds the apk data in memory
-  // along with the stack data.
-  MemoryOffline* stack_memory = new MemoryOffline;
-  ASSERT_TRUE(stack_memory->Init("stack.data", 0));
-
-  MemoryOffline* apk_memory = new MemoryOffline;
-  auto info = offline_utils_.GetMaps()->Find(0x7cb0e62000);
-  ASSERT_TRUE(info != nullptr);
-  ASSERT_TRUE(
-      apk_memory->Init("fake.apk", info->offset(), info->start(), info->end() - info->start()));
-
-  std::unique_ptr<MemoryOfflineParts> parts(new MemoryOfflineParts);
-  parts->Add(stack_memory);
-  parts->Add(apk_memory);
-
-  std::shared_ptr<Memory> process_memory(parts.release());
-
-  Unwinder unwinder(128, offline_utils_.GetMaps(), offline_utils_.GetRegs(), process_memory);
-  unwinder.Unwind();
-
-  size_t expected_num_frames;
-  if (!offline_utils_.GetExpectedNumFrames(&expected_num_frames, &error_msg)) FAIL() << error_msg;
-  std::string expected_frame_info;
-  if (!GetExpectedSamplesFrameInfo(&expected_frame_info, &error_msg)) FAIL() << error_msg;
-
-  std::string frame_info(DumpFrames(unwinder));
-  ASSERT_EQ(expected_num_frames, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
-  EXPECT_EQ(expected_frame_info, frame_info);
-
-  VerifyApkRX(unwinder);
-}
-
-}  // namespace
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/UnwindTest.cpp b/libunwindstack/tests/UnwindTest.cpp
index 9a5a96f..e42125d 100644
--- a/libunwindstack/tests/UnwindTest.cpp
+++ b/libunwindstack/tests/UnwindTest.cpp
@@ -40,7 +40,6 @@
 #include <unwindstack/Unwinder.h>
 
 #include "MemoryRemote.h"
-#include "PidUtils.h"
 #include "TestUtils.h"
 
 namespace unwindstack {
@@ -53,17 +52,15 @@
   TEST_TYPE_REMOTE_WITH_INVALID_CALL,
 };
 
+static std::atomic_bool g_ready;
 static volatile bool g_ready_for_remote;
 static volatile bool g_signal_ready_for_remote;
-// In order to avoid the compiler not emitting the unwind entries for
-// the InnerFunction code that loops waiting for g_finish, always make
-// g_finish a volatile instead of an atomic. This issue was only ever
-// observerd on the arm architecture.
-static volatile bool g_finish;
+static std::atomic_bool g_finish;
 static std::atomic_uintptr_t g_ucontext;
 static std::atomic_int g_waiters;
 
 static void ResetGlobals() {
+  g_ready = false;
   g_ready_for_remote = false;
   g_signal_ready_for_remote = false;
   g_finish = false;
@@ -79,7 +76,7 @@
 
 static void SignalHandler(int, siginfo_t*, void* sigcontext) {
   g_ucontext = reinterpret_cast<uintptr_t>(sigcontext);
-  while (!g_finish) {
+  while (!g_finish.load()) {
   }
 }
 
@@ -112,9 +109,8 @@
 
   return std::string(
              "Unwind completed without finding all frames\n"
-             "  Unwinder error: ") +
-         unwinder->LastErrorCodeString() + "\n" +
-         "  Looking for function: " + function_names.front() + "\n" + "Unwind data:\n" + unwind;
+             "  Looking for function: ") +
+         function_names.front() + "\n" + "Unwind data:\n" + unwind;
 }
 
 static void VerifyUnwindFrames(Unwinder* unwinder,
@@ -129,14 +125,6 @@
   }
 
   ASSERT_TRUE(expected_function_names.empty()) << ErrorMsg(expected_function_names, unwinder);
-
-  // Verify that the load bias of every map with a MapInfo is has been initialized.
-  for (auto& frame : unwinder->frames()) {
-    if (frame.map_info == nullptr) {
-      continue;
-    }
-    ASSERT_NE(UINT64_MAX, frame.map_info->GetLoadBias()) << "Frame " << frame.num << " failed";
-  }
 }
 
 static void VerifyUnwind(Unwinder* unwinder, std::vector<const char*> expected_function_names) {
@@ -162,7 +150,7 @@
   switch (test_type) {
     case TEST_TYPE_LOCAL_WAIT_FOR_FINISH: {
       g_waiters++;
-      while (!g_finish) {
+      while (!g_finish.load()) {
       }
       break;
     }
@@ -170,6 +158,7 @@
     case TEST_TYPE_REMOTE:
     case TEST_TYPE_REMOTE_WITH_INVALID_CALL: {
       g_ready_for_remote = true;
+      g_ready = true;
       if (test_type == TEST_TYPE_REMOTE_WITH_INVALID_CALL) {
         void (*crash_func)() = nullptr;
         crash_func();
@@ -237,15 +226,33 @@
   TestCheckForLeaks(LocalUnwind, &test_type);
 }
 
-static bool WaitForRemote(pid_t pid, bool leave_attached, uint64_t addr) {
-  MemoryRemote memory(pid);
-  return RunWhenQuiesced(pid, leave_attached, [addr, &memory]() {
-    bool value;
-    if (memory.ReadFully(addr, &value, sizeof(value)) && value) {
-      return PID_RUN_PASS;
+void WaitForRemote(pid_t pid, uint64_t addr, bool leave_attached, bool* completed) {
+  *completed = false;
+  // Need to sleep before attempting first ptrace. Without this, on the
+  // host it becomes impossible to attach and ptrace sets errno to EPERM.
+  usleep(1000);
+  for (size_t i = 0; i < 1000; i++) {
+    if (ptrace(PTRACE_ATTACH, pid, 0, 0) == 0) {
+      ASSERT_TRUE(TestQuiescePid(pid))
+          << "Waiting for process to quiesce failed: " << strerror(errno);
+
+      MemoryRemote memory(pid);
+      // Read the remote value to see if we are ready.
+      bool value;
+      if (memory.ReadFully(addr, &value, sizeof(value)) && value) {
+        *completed = true;
+      }
+      if (!*completed || !leave_attached) {
+        ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0));
+      }
+      if (*completed) {
+        break;
+      }
+    } else {
+      ASSERT_EQ(ESRCH, errno) << "ptrace attach failed with unexpected error: " << strerror(errno);
     }
-    return PID_RUN_KEEP_GOING;
-  });
+    usleep(5000);
+  }
 }
 
 TEST_F(UnwindTest, remote) {
@@ -257,7 +264,9 @@
   ASSERT_NE(-1, pid);
   TestScopedPidReaper reap(pid);
 
-  ASSERT_TRUE(WaitForRemote(pid, true, reinterpret_cast<uint64_t>(&g_ready_for_remote)));
+  bool completed;
+  WaitForRemote(pid, reinterpret_cast<uint64_t>(&g_ready_for_remote), true, &completed);
+  ASSERT_TRUE(completed) << "Timed out waiting for remote process to be ready.";
 
   RemoteMaps maps(pid);
   ASSERT_TRUE(maps.Parse());
@@ -266,7 +275,8 @@
 
   VerifyUnwind(pid, &maps, regs.get(), kFunctionOrder);
 
-  ASSERT_TRUE(Detach(pid));
+  ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0))
+      << "ptrace detach failed with unexpected error: " << strerror(errno);
 }
 
 TEST_F(UnwindTest, unwind_from_pid_remote) {
@@ -278,7 +288,9 @@
   ASSERT_NE(-1, pid);
   TestScopedPidReaper reap(pid);
 
-  ASSERT_TRUE(WaitForRemote(pid, true, reinterpret_cast<uint64_t>(&g_ready_for_remote)));
+  bool completed;
+  WaitForRemote(pid, reinterpret_cast<uint64_t>(&g_ready_for_remote), true, &completed);
+  ASSERT_TRUE(completed) << "Timed out waiting for remote process to be ready.";
 
   std::unique_ptr<Regs> regs(Regs::RemoteGet(pid));
   ASSERT_TRUE(regs.get() != nullptr);
@@ -288,7 +300,10 @@
 
   VerifyUnwind(&unwinder, kFunctionOrder);
 
-  ASSERT_TRUE(Detach(pid));
+  // Verify that calling the same object works again.
+
+  ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0))
+      << "ptrace detach failed with unexpected error: " << strerror(errno);
 }
 
 static void RemoteCheckForLeaks(void (*unwind_func)(void*)) {
@@ -300,11 +315,14 @@
   ASSERT_NE(-1, pid);
   TestScopedPidReaper reap(pid);
 
-  ASSERT_TRUE(WaitForRemote(pid, true, reinterpret_cast<uint64_t>(&g_ready_for_remote)));
+  bool completed;
+  WaitForRemote(pid, reinterpret_cast<uint64_t>(&g_ready_for_remote), true, &completed);
+  ASSERT_TRUE(completed) << "Timed out waiting for remote process to be ready.";
 
   TestCheckForLeaks(unwind_func, &pid);
 
-  ASSERT_TRUE(Detach(pid));
+  ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0))
+      << "ptrace detach failed with unexpected error: " << strerror(errno);
 }
 
 static void RemoteUnwind(void* data) {
@@ -350,8 +368,8 @@
   act.sa_sigaction = SignalHandler;
   act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
   ASSERT_EQ(0, sigaction(SIGUSR1, &act, &oldact));
-  // Wait 20 seconds for the tid to get set.
-  for (time_t start_time = time(nullptr); time(nullptr) - start_time < 20;) {
+  // Wait for the tid to get set.
+  for (size_t i = 0; i < 100; i++) {
     if (tid.load() != 0) {
       break;
     }
@@ -360,9 +378,9 @@
   ASSERT_NE(0, tid.load());
   ASSERT_EQ(0, tgkill(getpid(), tid.load(), SIGUSR1)) << "Error: " << strerror(errno);
 
-  // Wait 20 seconds for context data.
+  // Wait for context data.
   void* ucontext;
-  for (time_t start_time = time(nullptr); time(nullptr) - start_time < 20;) {
+  for (size_t i = 0; i < 2000; i++) {
     ucontext = reinterpret_cast<void*>(g_ucontext.load());
     if (ucontext != nullptr) {
       break;
@@ -398,11 +416,14 @@
   ASSERT_NE(-1, pid);
   TestScopedPidReaper reap(pid);
 
+  bool completed;
   if (signal != SIGSEGV) {
-    ASSERT_TRUE(WaitForRemote(pid, false, reinterpret_cast<uint64_t>(&g_ready_for_remote)));
+    WaitForRemote(pid, reinterpret_cast<uint64_t>(&g_ready_for_remote), false, &completed);
+    ASSERT_TRUE(completed) << "Timed out waiting for remote process to be ready.";
     ASSERT_EQ(0, kill(pid, SIGUSR1));
   }
-  ASSERT_TRUE(WaitForRemote(pid, true, reinterpret_cast<uint64_t>(&g_signal_ready_for_remote)));
+  WaitForRemote(pid, reinterpret_cast<uint64_t>(&g_signal_ready_for_remote), true, &completed);
+  ASSERT_TRUE(completed) << "Timed out waiting for remote process to be in signal handler.";
 
   RemoteMaps maps(pid);
   ASSERT_TRUE(maps.Parse());
@@ -411,7 +432,8 @@
 
   VerifyUnwind(pid, &maps, regs.get(), kFunctionSignalOrder);
 
-  ASSERT_TRUE(Detach(pid));
+  ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0))
+      << "ptrace detach failed with unexpected error: " << strerror(errno);
 }
 
 TEST_F(UnwindTest, remote_through_signal) {
@@ -446,8 +468,8 @@
   size_t frames[kNumConcurrentThreads];
   for (size_t i = 0; i < kNumConcurrentThreads; i++) {
     std::thread* thread = new std::thread([i, &frames, &maps, &process_memory, &wait]() {
-      while (wait) {
-      }
+      while (wait)
+        ;
       std::unique_ptr<Regs> regs(Regs::CreateFromLocal());
       RegsGetLocal(regs.get());
 
@@ -474,8 +496,8 @@
     OuterFunction(TEST_TYPE_LOCAL_WAIT_FOR_FINISH);
   });
 
-  while (tid.load() == 0) {
-  }
+  while (tid.load() == 0)
+    ;
 
   ThreadUnwinder unwinder(512);
   ASSERT_TRUE(unwinder.Init());
@@ -486,34 +508,6 @@
   thread.join();
 }
 
-TEST_F(UnwindTest, thread_unwind_copy_regs) {
-  ResetGlobals();
-
-  std::atomic_int tid(0);
-  std::thread thread([&tid]() {
-    tid = android::base::GetThreadId();
-    OuterFunction(TEST_TYPE_LOCAL_WAIT_FOR_FINISH);
-  });
-
-  while (tid.load() == 0) {
-  }
-
-  ThreadUnwinder unwinder(512);
-  ASSERT_TRUE(unwinder.Init());
-  std::unique_ptr<Regs> initial_regs;
-  unwinder.UnwindWithSignal(SIGRTMIN, tid, &initial_regs);
-  ASSERT_TRUE(initial_regs != nullptr);
-  // Verify the initial registers match the first frame pc/sp.
-  ASSERT_TRUE(unwinder.NumFrames() != 0);
-  auto initial_frame = unwinder.frames()[0];
-  ASSERT_EQ(initial_regs->pc(), initial_frame.pc);
-  ASSERT_EQ(initial_regs->sp(), initial_frame.sp);
-  VerifyUnwindFrames(&unwinder, kFunctionOrder);
-
-  g_finish = true;
-  thread.join();
-}
-
 TEST_F(UnwindTest, thread_unwind_with_external_maps) {
   ResetGlobals();
 
@@ -523,8 +517,8 @@
     OuterFunction(TEST_TYPE_LOCAL_WAIT_FOR_FINISH);
   });
 
-  while (tid.load() == 0) {
-  }
+  while (tid.load() == 0)
+    ;
 
   LocalMaps maps;
   ASSERT_TRUE(maps.Parse());
@@ -549,44 +543,28 @@
   EXPECT_EQ(ERROR_UNSUPPORTED, unwinder.LastErrorCode());
 }
 
-TEST_F(UnwindTest, thread_unwind_cur_thread) {
-  std::thread thread([]() {
-    ThreadUnwinder unwinder(512);
-    ASSERT_TRUE(unwinder.Init());
-    unwinder.UnwindWithSignal(SIGRTMIN, android::base::GetThreadId());
-    EXPECT_EQ(0U, unwinder.NumFrames());
-    EXPECT_EQ(ERROR_UNSUPPORTED, unwinder.LastErrorCode());
-  });
-  thread.join();
-}
-
-TEST_F(UnwindTest, thread_unwind_cur_pid_from_thread) {
-  std::thread thread([]() {
-    ThreadUnwinder unwinder(512);
-    ASSERT_TRUE(unwinder.Init());
-    unwinder.UnwindWithSignal(SIGRTMIN, getpid());
-    EXPECT_NE(0U, unwinder.NumFrames());
-    EXPECT_NE(ERROR_UNSUPPORTED, unwinder.LastErrorCode());
-  });
-  thread.join();
-}
-
 static std::thread* CreateUnwindThread(std::atomic_int& tid, ThreadUnwinder& unwinder,
                                        std::atomic_bool& start_unwinding,
                                        std::atomic_int& unwinders) {
   return new std::thread([&tid, &unwinder, &start_unwinding, &unwinders]() {
-    while (!start_unwinding.load()) {
-    }
+    while (!start_unwinding.load())
+      ;
 
     ThreadUnwinder thread_unwinder(512, &unwinder);
-    // Allow the unwind to timeout since this will be doing multiple
-    // unwinds at once.
-    for (size_t i = 0; i < 3; i++) {
-      thread_unwinder.UnwindWithSignal(SIGRTMIN, tid);
-      if (thread_unwinder.LastErrorCode() != ERROR_THREAD_TIMEOUT) {
+    thread_unwinder.UnwindWithSignal(SIGRTMIN, tid);
+#if defined(__arm__)
+    // On arm, there is a chance of winding up in case that doesn't unwind.
+    // Identify that case and allow unwinding in that case.
+    for (size_t i = 0; i < 10; i++) {
+      auto frames = thread_unwinder.frames();
+      if (frames.size() > 1 && frames[frames.size() - 1].pc < 1000 &&
+          frames[frames.size() - 2].function_name == "InnerFunction") {
+        thread_unwinder.UnwindWithSignal(SIGRTMIN, tid);
+      } else {
         break;
       }
     }
+#endif
     VerifyUnwindFrames(&thread_unwinder, kFunctionOrder);
     ++unwinders;
   });
@@ -602,8 +580,8 @@
     OuterFunction(TEST_TYPE_LOCAL_WAIT_FOR_FINISH);
   });
 
-  while (g_waiters.load() != 1) {
-  }
+  while (g_waiters.load() != 1)
+    ;
 
   ThreadUnwinder unwinder(512);
   ASSERT_TRUE(unwinder.Init());
@@ -616,8 +594,8 @@
   }
 
   start_unwinding = true;
-  while (unwinders.load() != kNumThreads) {
-  }
+  while (unwinders.load() != kNumThreads)
+    ;
 
   for (auto* thread : threads) {
     thread->join();
@@ -642,8 +620,8 @@
     threads.push_back(thread);
   }
 
-  while (g_waiters.load() != kNumThreads) {
-  }
+  while (g_waiters.load() != kNumThreads)
+    ;
 
   ThreadUnwinder unwinder(512);
   ASSERT_TRUE(unwinder.Init());
@@ -656,8 +634,8 @@
   }
 
   start_unwinding = true;
-  while (unwinders.load() != kNumThreads) {
-  }
+  while (unwinders.load() != kNumThreads)
+    ;
 
   for (auto* thread : unwinder_threads) {
     thread->join();
@@ -692,8 +670,8 @@
     threads.push_back(thread);
   }
 
-  while (g_waiters.load() != kNumThreads) {
-  }
+  while (g_waiters.load() != kNumThreads)
+    ;
 
   ThreadUnwinder unwinder(512, &maps);
   ASSERT_TRUE(unwinder.Init());
@@ -706,8 +684,8 @@
   }
 
   start_unwinding = true;
-  while (unwinders.load() != kNumThreads) {
-  }
+  while (unwinders.load() != kNumThreads)
+    ;
 
   for (auto* thread : unwinder_threads) {
     thread->join();
diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp
index 2da3ee1..2884a40 100644
--- a/libunwindstack/tests/UnwinderTest.cpp
+++ b/libunwindstack/tests/UnwinderTest.cpp
@@ -39,8 +39,8 @@
 
 #include "ElfFake.h"
 #include "ElfTestUtils.h"
-#include "utils/MemoryFake.h"
-#include "utils/RegsFake.h"
+#include "MemoryFake.h"
+#include "RegsFake.h"
 
 namespace unwindstack {
 
@@ -49,8 +49,8 @@
   static MapInfo* AddMapInfo(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
                              const char* name, Elf* elf = nullptr) {
     std::string str_name(name);
-    maps_->Add(start, end, offset, flags, name);
-    MapInfo* map_info = maps_->Find(start).get();
+    maps_->Add(start, end, offset, flags, name, static_cast<uint64_t>(-1));
+    MapInfo* map_info = maps_->Find(start);
     if (elf != nullptr) {
       map_info->set_elf(elf);
     }
@@ -99,7 +99,9 @@
 
     AddMapInfo(0x53000, 0x54000, 0, PROT_READ | PROT_WRITE, "/fake/fake.oat");
 
-    AddMapInfo(0xa3000, 0xa4000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/fake.vdex");
+    map_info =
+        AddMapInfo(0xa3000, 0xa4000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/fake.vdex");
+    map_info->set_load_bias(0);
 
     elf = new ElfFake(new MemoryFake);
     elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
@@ -137,7 +139,7 @@
 
     map_info =
         AddMapInfo(0xd0000, 0xd1000, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/fake.apk");
-    map_info->set_elf_start_offset(0x1000);
+    map_info->set_load_bias(0);
 
     elf = new ElfFake(new MemoryFake);
     interface = new ElfInterfaceFake(nullptr);
@@ -206,6 +208,7 @@
   unwinder.Unwind();
   EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(3U, unwinder.NumFrames());
 
@@ -216,15 +219,13 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("Frame0", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->name());
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0x1000U, frame->map_info->start());
-  EXPECT_EQ(0x8000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("/system/fake/libc.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x1000U, frame->map_start);
+  EXPECT_EQ(0x8000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 
   frame = &unwinder.frames()[1];
   EXPECT_EQ(1U, frame->num);
@@ -233,15 +234,13 @@
   EXPECT_EQ(0x10010U, frame->sp);
   EXPECT_EQ("Frame1", frame->function_name);
   EXPECT_EQ(1U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->name());
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0x1000U, frame->map_info->start());
-  EXPECT_EQ(0x8000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("/system/fake/libc.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x1000U, frame->map_start);
+  EXPECT_EQ(0x8000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 
   frame = &unwinder.frames()[2];
   EXPECT_EQ(2U, frame->num);
@@ -250,15 +249,13 @@
   EXPECT_EQ(0x10020U, frame->sp);
   EXPECT_EQ("Frame2", frame->function_name);
   EXPECT_EQ(2U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->name());
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0x1000U, frame->map_info->start());
-  EXPECT_EQ(0x8000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("/system/fake/libc.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x1000U, frame->map_start);
+  EXPECT_EQ(0x8000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 }
 
 TEST_F(UnwinderTest, multiple_frames_dont_resolve_names) {
@@ -277,6 +274,7 @@
   unwinder.Unwind();
   EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(3U, unwinder.NumFrames());
 
@@ -287,15 +285,13 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->name());
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0x1000U, frame->map_info->start());
-  EXPECT_EQ(0x8000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x1000U, frame->map_start);
+  EXPECT_EQ(0x8000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 
   frame = &unwinder.frames()[1];
   EXPECT_EQ(1U, frame->num);
@@ -304,15 +300,13 @@
   EXPECT_EQ(0x10010U, frame->sp);
   EXPECT_EQ("", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->name());
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0x1000U, frame->map_info->start());
-  EXPECT_EQ(0x8000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x1000U, frame->map_start);
+  EXPECT_EQ(0x8000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 
   frame = &unwinder.frames()[2];
   EXPECT_EQ(2U, frame->num);
@@ -321,15 +315,13 @@
   EXPECT_EQ(0x10020U, frame->sp);
   EXPECT_EQ("", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->name());
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0x1000U, frame->map_info->start());
-  EXPECT_EQ(0x8000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x1000U, frame->map_start);
+  EXPECT_EQ(0x8000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 }
 
 TEST_F(UnwinderTest, non_zero_load_bias) {
@@ -343,6 +335,7 @@
   unwinder.Unwind();
   EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(1U, unwinder.NumFrames());
 
@@ -353,15 +346,13 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("Frame0", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/fake/fake_load_bias.so", frame->map_info->name());
-  EXPECT_EQ("/fake/fake_load_bias.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0xa5000U, frame->map_info->start());
-  EXPECT_EQ(0xa6000U, frame->map_info->end());
-  EXPECT_EQ(0x5000U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_info->flags());
+  EXPECT_EQ("/fake/fake_load_bias.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0xa5000U, frame->map_start);
+  EXPECT_EQ(0xa6000U, frame->map_end);
+  EXPECT_EQ(0x5000U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
 }
 
 TEST_F(UnwinderTest, non_zero_elf_offset) {
@@ -375,6 +366,7 @@
   unwinder.Unwind();
   EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(1U, unwinder.NumFrames());
 
@@ -385,15 +377,13 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("Frame0", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/fake/fake_offset.oat", frame->map_info->name());
-  EXPECT_EQ("/fake/fake_offset.oat", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0xa7000U, frame->map_info->start());
-  EXPECT_EQ(0xa8000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_info->flags());
+  EXPECT_EQ("/fake/fake_offset.oat", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0xa7000U, frame->map_start);
+  EXPECT_EQ(0xa8000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
 }
 
 TEST_F(UnwinderTest, non_zero_map_offset) {
@@ -407,6 +397,7 @@
   unwinder.Unwind();
   EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(1U, unwinder.NumFrames());
 
@@ -417,15 +408,45 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("Frame0", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/fake/fake.apk", frame->map_info->name());
-  EXPECT_EQ("/fake/fake.apk!lib_fake.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0x1d000U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0x1d000U, frame->map_info->offset());
-  EXPECT_EQ(0x43000U, frame->map_info->start());
-  EXPECT_EQ(0x44000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("/fake/fake.apk!lib_fake.so", frame->map_name);
+  EXPECT_EQ(0x1d000U, frame->map_elf_start_offset);
+  EXPECT_EQ(0x1d000U, frame->map_exact_offset);
+  EXPECT_EQ(0x43000U, frame->map_start);
+  EXPECT_EQ(0x44000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
+}
+
+TEST_F(UnwinderTest, disable_embedded_soname) {
+  ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
+
+  regs_.set_pc(0x43000);
+  regs_.set_sp(0x10000);
+  ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
+
+  Unwinder unwinder(64, maps_.get(), &regs_, process_memory_);
+  unwinder.SetEmbeddedSoname(false);
+  unwinder.Unwind();
+  EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+  EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
+
+  ASSERT_EQ(1U, unwinder.NumFrames());
+
+  auto* frame = &unwinder.frames()[0];
+  EXPECT_EQ(0U, frame->num);
+  EXPECT_EQ(0U, frame->rel_pc);
+  EXPECT_EQ(0x43000U, frame->pc);
+  EXPECT_EQ(0x10000U, frame->sp);
+  EXPECT_EQ("Frame0", frame->function_name);
+  EXPECT_EQ(0U, frame->function_offset);
+  EXPECT_EQ("/fake/fake.apk", frame->map_name);
+  EXPECT_EQ(0x1d000U, frame->map_elf_start_offset);
+  EXPECT_EQ(0x1d000U, frame->map_exact_offset);
+  EXPECT_EQ(0x43000U, frame->map_start);
+  EXPECT_EQ(0x44000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 }
 
 // Verify that no attempt to continue after the step indicates it is done.
@@ -446,6 +467,7 @@
   unwinder.Unwind();
   EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(1U, unwinder.NumFrames());
 
@@ -456,15 +478,13 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("Frame0", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->name());
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0x1000U, frame->map_info->start());
-  EXPECT_EQ(0x8000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("/system/fake/libc.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x1000U, frame->map_start);
+  EXPECT_EQ(0x8000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 }
 
 // Verify the maximum frames to save.
@@ -481,27 +501,25 @@
   unwinder.Unwind();
   EXPECT_EQ(ERROR_MAX_FRAMES_EXCEEDED, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(20U, unwinder.NumFrames());
 
   for (size_t i = 0; i < 20; i++) {
     auto* frame = &unwinder.frames()[i];
     EXPECT_EQ(i, frame->num);
-    SCOPED_TRACE(testing::Message() << "Failed at frame " << i);
-    EXPECT_EQ(i * 0x100, frame->rel_pc);
-    EXPECT_EQ(0x1000 + i * 0x100, frame->pc);
-    EXPECT_EQ(0x10000 + 0x10 * i, frame->sp);
-    EXPECT_EQ("Frame" + std::to_string(i), frame->function_name);
-    EXPECT_EQ(i, frame->function_offset);
-    ASSERT_TRUE(frame->map_info != nullptr);
-    EXPECT_EQ("/system/fake/libc.so", frame->map_info->name());
-    EXPECT_EQ("/system/fake/libc.so", frame->map_info->GetFullName());
-    EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-    EXPECT_EQ(0U, frame->map_info->offset());
-    EXPECT_EQ(0x1000U, frame->map_info->start());
-    EXPECT_EQ(0x8000U, frame->map_info->end());
-    EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-    EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+    EXPECT_EQ(i * 0x100, frame->rel_pc) << "Failed at frame " << i;
+    EXPECT_EQ(0x1000 + i * 0x100, frame->pc) << "Failed at frame " << i;
+    EXPECT_EQ(0x10000 + 0x10 * i, frame->sp) << "Failed at frame " << i;
+    EXPECT_EQ("Frame" + std::to_string(i), frame->function_name) << "Failed at frame " << i;
+    EXPECT_EQ(i, frame->function_offset) << "Failed at frame " << i;
+    EXPECT_EQ("/system/fake/libc.so", frame->map_name) << "Failed at frame " << i;
+    EXPECT_EQ(0U, frame->map_elf_start_offset) << "Failed at frame " << i;
+    EXPECT_EQ(0U, frame->map_exact_offset) << "Failed at frame " << i;
+    EXPECT_EQ(0x1000U, frame->map_start) << "Failed at frame " << i;
+    EXPECT_EQ(0x8000U, frame->map_end) << "Failed at frame " << i;
+    EXPECT_EQ(0U, frame->map_load_bias) << "Failed at frame " << i;
+    EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags) << "Failed at frame " << i;
   }
 }
 
@@ -527,6 +545,7 @@
   unwinder.Unwind(&skip_libs);
   EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(3U, unwinder.NumFrames());
 
@@ -537,15 +556,13 @@
   EXPECT_EQ(0x10050U, frame->sp);
   EXPECT_EQ("Frame0", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->name());
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0x1000U, frame->map_info->start());
-  EXPECT_EQ(0x8000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("/system/fake/libc.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x1000U, frame->map_start);
+  EXPECT_EQ(0x8000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 
   frame = &unwinder.frames()[1];
   EXPECT_EQ(1U, frame->num);
@@ -554,15 +571,13 @@
   EXPECT_EQ(0x10060U, frame->sp);
   EXPECT_EQ("Frame1", frame->function_name);
   EXPECT_EQ(1U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/system/fake/libunwind.so", frame->map_info->name());
-  EXPECT_EQ("/system/fake/libunwind.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0x20000U, frame->map_info->start());
-  EXPECT_EQ(0x22000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("/system/fake/libunwind.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x20000U, frame->map_start);
+  EXPECT_EQ(0x22000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 
   frame = &unwinder.frames()[2];
   EXPECT_EQ(2U, frame->num);
@@ -571,14 +586,12 @@
   EXPECT_EQ(0x10070U, frame->sp);
   EXPECT_EQ("Frame2", frame->function_name);
   EXPECT_EQ(2U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/fake/libanother.so", frame->map_info->name());
-  EXPECT_EQ("/fake/libanother.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0x23000U, frame->map_info->start());
-  EXPECT_EQ(0x24000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("/fake/libanother.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x23000U, frame->map_start);
+  EXPECT_EQ(0x24000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 }
 
 // Verify SP in a non-existant map is okay.
@@ -595,6 +608,7 @@
   unwinder.Unwind();
   EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(2U, unwinder.NumFrames());
 
@@ -605,14 +619,12 @@
   EXPECT_EQ(0x63000U, frame->sp);
   EXPECT_EQ("Frame0", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->name());
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0x1000U, frame->map_info->start());
-  EXPECT_EQ(0x8000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("/system/fake/libc.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x1000U, frame->map_start);
+  EXPECT_EQ(0x8000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 
   frame = &unwinder.frames()[1];
   EXPECT_EQ(1U, frame->num);
@@ -621,14 +633,12 @@
   EXPECT_EQ(0x50020U, frame->sp);
   EXPECT_EQ("Frame1", frame->function_name);
   EXPECT_EQ(1U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/system/fake/libunwind.so", frame->map_info->name());
-  EXPECT_EQ("/system/fake/libunwind.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0x20000U, frame->map_info->start());
-  EXPECT_EQ(0x22000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("/system/fake/libunwind.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x20000U, frame->map_start);
+  EXPECT_EQ(0x22000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 }
 
 // Verify PC in a device stops the unwind.
@@ -647,6 +657,7 @@
   unwinder.Unwind();
   EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(1U, unwinder.NumFrames());
 }
@@ -667,6 +678,7 @@
   unwinder.Unwind();
   EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(1U, unwinder.NumFrames());
 }
@@ -682,6 +694,7 @@
   unwinder.Unwind();
   EXPECT_EQ(ERROR_INVALID_MAP, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(1U, unwinder.NumFrames());
 
@@ -692,7 +705,13 @@
   EXPECT_EQ(0x13000U, frame->sp);
   EXPECT_EQ("", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info == nullptr);
+  EXPECT_EQ("", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0U, frame->map_start);
+  EXPECT_EQ(0U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(0, frame->map_flags);
 }
 
 // Verify that a speculative frame is added.
@@ -713,6 +732,7 @@
   unwinder.Unwind();
   EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(3U, unwinder.NumFrames());
 
@@ -723,7 +743,13 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info == nullptr);
+  EXPECT_EQ("", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0U, frame->map_start);
+  EXPECT_EQ(0U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(0, frame->map_flags);
 
   frame = &unwinder.frames()[1];
   EXPECT_EQ(1U, frame->num);
@@ -732,15 +758,13 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("Frame0", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->name());
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0x1000U, frame->map_info->start());
-  EXPECT_EQ(0x8000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("/system/fake/libc.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x1000U, frame->map_start);
+  EXPECT_EQ(0x8000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 
   frame = &unwinder.frames()[2];
   EXPECT_EQ(2U, frame->num);
@@ -749,15 +773,13 @@
   EXPECT_EQ(0x10020U, frame->sp);
   EXPECT_EQ("Frame1", frame->function_name);
   EXPECT_EQ(1U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/fake/libanother.so", frame->map_info->name());
-  EXPECT_EQ("/fake/libanother.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0x23000U, frame->map_info->start());
-  EXPECT_EQ(0x24000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("/fake/libanother.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x23000U, frame->map_start);
+  EXPECT_EQ(0x24000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 }
 
 // Verify that a speculative frame is added then removed because no other
@@ -777,6 +799,7 @@
   unwinder.Unwind();
   EXPECT_EQ(ERROR_INVALID_MAP, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(2U, unwinder.NumFrames());
 
@@ -787,15 +810,13 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("Frame0", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/system/fake/libunwind.so", frame->map_info->name());
-  EXPECT_EQ("/system/fake/libunwind.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0x20000U, frame->map_info->start());
-  EXPECT_EQ(0x22000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("/system/fake/libunwind.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x20000U, frame->map_start);
+  EXPECT_EQ(0x22000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 
   frame = &unwinder.frames()[1];
   EXPECT_EQ(1U, frame->num);
@@ -804,7 +825,13 @@
   EXPECT_EQ(0x10010U, frame->sp);
   EXPECT_EQ("", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info == nullptr);
+  EXPECT_EQ("", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0U, frame->map_start);
+  EXPECT_EQ(0U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(0, frame->map_flags);
 }
 
 // Verify that a speculative frame is added and left if there are only
@@ -823,6 +850,7 @@
   unwinder.Unwind();
   EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(2U, unwinder.NumFrames());
 
@@ -833,7 +861,13 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info == nullptr);
+  EXPECT_EQ("", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0U, frame->map_start);
+  EXPECT_EQ(0U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(0, frame->map_flags);
 
   frame = &unwinder.frames()[1];
   EXPECT_EQ(1U, frame->num);
@@ -842,15 +876,13 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("Frame0", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->name());
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0x1000U, frame->map_info->start());
-  EXPECT_EQ(0x8000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("/system/fake/libc.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x1000U, frame->map_start);
+  EXPECT_EQ(0x8000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 }
 
 // Verify that a speculative frame does not cause a crash when it wasn't
@@ -867,35 +899,11 @@
   unwinder.Unwind(&skip_names);
   EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(0U, unwinder.NumFrames());
 }
 
-// Verify that a speculative frame mapping to invalid map doesn't hide error
-// for the previous frame.
-TEST_F(UnwinderTest, speculative_frame_to_invalid_map_not_hide_prev_error) {
-  regs_.set_pc(0x100000);
-  regs_.set_sp(0x10000);
-  regs_.FakeSetReturnAddress(0x4);
-  regs_.FakeSetReturnAddressValid(true);
-
-  Unwinder unwinder(64, maps_.get(), &regs_, process_memory_);
-  unwinder.Unwind();
-  EXPECT_EQ(ERROR_INVALID_ELF, unwinder.LastErrorCode());
-  EXPECT_EQ(WARNING_NONE, unwinder.warnings());
-
-  ASSERT_EQ(1U, unwinder.NumFrames());
-
-  auto* frame = &unwinder.frames()[0];
-  EXPECT_EQ(0U, frame->num);
-  EXPECT_EQ(0x300U, frame->rel_pc);
-  EXPECT_EQ(0x100000U, frame->pc);
-  EXPECT_EQ(0x10000U, frame->sp);
-  EXPECT_EQ("", frame->function_name);
-  EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-}
-
 // Verify that an unwind stops when a frame is in given suffix.
 TEST_F(UnwinderTest, map_ignore_suffixes) {
   ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
@@ -915,10 +923,11 @@
   unwinder.Unwind(nullptr, &suffixes);
   EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(2U, unwinder.NumFrames());
   // Make sure the elf was not initialized.
-  MapInfo* map_info = maps_->Find(0x53000).get();
+  MapInfo* map_info = maps_->Find(0x53000);
   ASSERT_TRUE(map_info != nullptr);
   EXPECT_TRUE(map_info->elf() == nullptr);
 
@@ -929,15 +938,13 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("Frame0", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->name());
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0x1000U, frame->map_info->start());
-  EXPECT_EQ(0x8000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("/system/fake/libc.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x1000U, frame->map_start);
+  EXPECT_EQ(0x8000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 
   frame = &unwinder.frames()[1];
   EXPECT_EQ(1U, frame->num);
@@ -946,15 +953,13 @@
   EXPECT_EQ(0x10010U, frame->sp);
   EXPECT_EQ("Frame1", frame->function_name);
   EXPECT_EQ(1U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/fake/fake.apk", frame->map_info->name());
-  EXPECT_EQ("/fake/fake.apk!lib_fake.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0x1d000U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0x1d000U, frame->map_info->offset());
-  EXPECT_EQ(0x43000U, frame->map_info->start());
-  EXPECT_EQ(0x44000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("/fake/fake.apk!lib_fake.so", frame->map_name);
+  EXPECT_EQ(0x1d000U, frame->map_elf_start_offset);
+  EXPECT_EQ(0x1d000U, frame->map_exact_offset);
+  EXPECT_EQ(0x43000U, frame->map_start);
+  EXPECT_EQ(0x44000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 }
 
 // Verify that an unwind stops when the sp and pc don't change.
@@ -978,6 +983,7 @@
   unwinder.Unwind();
   EXPECT_EQ(ERROR_REPEATED_FRAME, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(3U, unwinder.NumFrames());
 
@@ -988,15 +994,13 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("Frame0", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->name());
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0x1000U, frame->map_info->start());
-  EXPECT_EQ(0x8000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("/system/fake/libc.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x1000U, frame->map_start);
+  EXPECT_EQ(0x8000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 
   frame = &unwinder.frames()[1];
   EXPECT_EQ(1U, frame->num);
@@ -1005,15 +1009,13 @@
   EXPECT_EQ(0x10010U, frame->sp);
   EXPECT_EQ("Frame1", frame->function_name);
   EXPECT_EQ(1U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/fake/compressed.so", frame->map_info->name());
-  EXPECT_EQ("/fake/compressed.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0x33000U, frame->map_info->start());
-  EXPECT_EQ(0x34000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("/fake/compressed.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x33000U, frame->map_start);
+  EXPECT_EQ(0x34000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 
   frame = &unwinder.frames()[2];
   EXPECT_EQ(2U, frame->num);
@@ -1022,15 +1024,13 @@
   EXPECT_EQ(0x10020U, frame->sp);
   EXPECT_EQ("Frame2", frame->function_name);
   EXPECT_EQ(2U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/fake/compressed.so", frame->map_info->name());
-  EXPECT_EQ("/fake/compressed.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0x33000U, frame->map_info->start());
-  EXPECT_EQ(0x34000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("/fake/compressed.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x33000U, frame->map_start);
+  EXPECT_EQ(0x34000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 }
 
 TEST_F(UnwinderTest, dex_pc_in_map) {
@@ -1043,6 +1043,7 @@
   unwinder.Unwind();
   EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(2U, unwinder.NumFrames());
 
@@ -1053,15 +1054,13 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/fake/fake.vdex", frame->map_info->name());
-  EXPECT_EQ("/fake/fake.vdex", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0xa3000U, frame->map_info->start());
-  EXPECT_EQ(0xa4000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_info->flags());
+  EXPECT_EQ("/fake/fake.vdex", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0xa3000U, frame->map_start);
+  EXPECT_EQ(0xa4000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
 
   frame = &unwinder.frames()[1];
   EXPECT_EQ(1U, frame->num);
@@ -1070,15 +1069,13 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("Frame0", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->name());
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0x1000U, frame->map_info->start());
-  EXPECT_EQ(0x8000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("/system/fake/libc.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x1000U, frame->map_start);
+  EXPECT_EQ(0x8000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 }
 
 TEST_F(UnwinderTest, dex_pc_in_map_non_zero_offset) {
@@ -1091,6 +1088,7 @@
   unwinder.Unwind();
   EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(2U, unwinder.NumFrames());
 
@@ -1101,15 +1099,13 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/fake/fake.apk", frame->map_info->name());
-  EXPECT_EQ("/fake/fake.apk", frame->map_info->GetFullName());
-  EXPECT_EQ(0x1000U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0x1000U, frame->map_info->offset());
-  EXPECT_EQ(0xd0000U, frame->map_info->start());
-  EXPECT_EQ(0xd1000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_info->flags());
+  EXPECT_EQ("/fake/fake.apk", frame->map_name);
+  EXPECT_EQ(0x1000U, frame->map_elf_start_offset);
+  EXPECT_EQ(0x1000U, frame->map_exact_offset);
+  EXPECT_EQ(0xd0000U, frame->map_start);
+  EXPECT_EQ(0xd1000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
 
   frame = &unwinder.frames()[1];
   EXPECT_EQ(1U, frame->num);
@@ -1118,15 +1114,13 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("Frame0", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->name());
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0x1000U, frame->map_info->start());
-  EXPECT_EQ(0x8000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("/system/fake/libc.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x1000U, frame->map_start);
+  EXPECT_EQ(0x8000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 }
 
 TEST_F(UnwinderTest, dex_pc_not_in_map) {
@@ -1139,6 +1133,7 @@
   unwinder.Unwind();
   EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_DEX_PC_NOT_IN_MAP, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(2U, unwinder.NumFrames());
 
@@ -1149,7 +1144,13 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info == nullptr);
+  EXPECT_EQ("", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0U, frame->map_start);
+  EXPECT_EQ(0U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(0, frame->map_flags);
 
   frame = &unwinder.frames()[1];
   EXPECT_EQ(1U, frame->num);
@@ -1158,15 +1159,13 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("Frame0", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->name());
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0x1000U, frame->map_info->start());
-  EXPECT_EQ(0x8000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("/system/fake/libc.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x1000U, frame->map_start);
+  EXPECT_EQ(0x8000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 }
 
 TEST_F(UnwinderTest, dex_pc_not_in_map_valid_dex_files) {
@@ -1181,6 +1180,7 @@
   unwinder.Unwind();
   EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_DEX_PC_NOT_IN_MAP, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(2U, unwinder.NumFrames());
 
@@ -1191,7 +1191,13 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info == nullptr);
+  EXPECT_EQ("", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0U, frame->map_start);
+  EXPECT_EQ(0U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(0, frame->map_flags);
 
   frame = &unwinder.frames()[1];
   EXPECT_EQ(1U, frame->num);
@@ -1200,15 +1206,13 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("Frame0", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->name());
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0x1000U, frame->map_info->start());
-  EXPECT_EQ(0x8000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("/system/fake/libc.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x1000U, frame->map_start);
+  EXPECT_EQ(0x8000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 }
 
 TEST_F(UnwinderTest, dex_pc_multiple_frames) {
@@ -1224,6 +1228,7 @@
   unwinder.Unwind();
   EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(3U, unwinder.NumFrames());
 
@@ -1234,14 +1239,13 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/fake/fake.vdex", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0xa3000U, frame->map_info->start());
-  EXPECT_EQ(0xa4000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_info->flags());
+  EXPECT_EQ("/fake/fake.vdex", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0xa3000U, frame->map_start);
+  EXPECT_EQ(0xa4000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
 
   frame = &unwinder.frames()[1];
   EXPECT_EQ(1U, frame->num);
@@ -1250,15 +1254,13 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("Frame0", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->name());
-  EXPECT_EQ("/system/fake/libc.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0x1000U, frame->map_info->start());
-  EXPECT_EQ(0x8000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("/system/fake/libc.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x1000U, frame->map_start);
+  EXPECT_EQ(0x8000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 
   frame = &unwinder.frames()[2];
   EXPECT_EQ(2U, frame->num);
@@ -1267,15 +1269,13 @@
   EXPECT_EQ(0x10010U, frame->sp);
   EXPECT_EQ("Frame1", frame->function_name);
   EXPECT_EQ(1U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/fake/compressed.so", frame->map_info->name());
-  EXPECT_EQ("/fake/compressed.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0x33000U, frame->map_info->start());
-  EXPECT_EQ(0x34000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_info->flags());
+  EXPECT_EQ("/fake/compressed.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x33000U, frame->map_start);
+  EXPECT_EQ(0x34000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 }
 
 TEST_F(UnwinderTest, dex_pc_max_frames) {
@@ -1288,6 +1288,7 @@
   unwinder.Unwind();
   EXPECT_EQ(ERROR_MAX_FRAMES_EXCEEDED, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(1U, unwinder.NumFrames());
 
@@ -1298,18 +1299,16 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/fake/fake.vdex", frame->map_info->name());
-  EXPECT_EQ("/fake/fake.vdex", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0xa3000U, frame->map_info->start());
-  EXPECT_EQ(0xa4000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_info->flags());
+  EXPECT_EQ("/fake/fake.vdex", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0xa3000U, frame->map_start);
+  EXPECT_EQ(0xa4000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
 }
 
-TEST_F(UnwinderTest, elf_file_not_readable) {
+TEST_F(UnwinderTest, elf_from_memory_not_file) {
   ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
 
   regs_.set_pc(0xc0050);
@@ -1320,6 +1319,7 @@
   unwinder.Unwind();
   EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_TRUE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(1U, unwinder.NumFrames());
 
@@ -1330,16 +1330,13 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("Frame0", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_TRUE(frame->map_info->ElfFileNotReadable());
-  EXPECT_EQ("/fake/unreadable.so", frame->map_info->name());
-  EXPECT_EQ("/fake/unreadable.so", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0xc0000U, frame->map_info->start());
-  EXPECT_EQ(0xc1000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_info->flags());
+  EXPECT_EQ("/fake/unreadable.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0xc0000U, frame->map_start);
+  EXPECT_EQ(0xc1000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
 }
 
 TEST_F(UnwinderTest, elf_from_memory_but_no_valid_file_with_bracket) {
@@ -1353,6 +1350,7 @@
   unwinder.Unwind();
   EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(1U, unwinder.NumFrames());
 
@@ -1363,15 +1361,13 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("Frame0", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("[vdso]", frame->map_info->name());
-  EXPECT_EQ("[vdso]", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0xc1000U, frame->map_info->start());
-  EXPECT_EQ(0xc2000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_info->flags());
+  EXPECT_EQ("[vdso]", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0xc1000U, frame->map_start);
+  EXPECT_EQ(0xc2000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
 }
 
 TEST_F(UnwinderTest, elf_from_memory_but_empty_filename) {
@@ -1385,6 +1381,7 @@
   unwinder.Unwind();
   EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(1U, unwinder.NumFrames());
 
@@ -1395,15 +1392,13 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("Frame0", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("", frame->map_info->name());
-  EXPECT_EQ("", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0xc2000U, frame->map_info->start());
-  EXPECT_EQ(0xc3000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_info->flags());
+  EXPECT_EQ("", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0xc2000U, frame->map_start);
+  EXPECT_EQ(0xc3000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
 }
 
 TEST_F(UnwinderTest, elf_from_memory_but_from_memfd) {
@@ -1417,6 +1412,7 @@
   unwinder.Unwind();
   EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
   EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
 
   ASSERT_EQ(1U, unwinder.NumFrames());
 
@@ -1427,15 +1423,13 @@
   EXPECT_EQ(0x10000U, frame->sp);
   EXPECT_EQ("Frame0", frame->function_name);
   EXPECT_EQ(0U, frame->function_offset);
-  ASSERT_TRUE(frame->map_info != nullptr);
-  EXPECT_EQ("/memfd:/jit-cache", frame->map_info->name());
-  EXPECT_EQ("/memfd:/jit-cache", frame->map_info->GetFullName());
-  EXPECT_EQ(0U, frame->map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame->map_info->offset());
-  EXPECT_EQ(0xc3000U, frame->map_info->start());
-  EXPECT_EQ(0xc4000U, frame->map_info->end());
-  EXPECT_EQ(0U, frame->map_info->GetLoadBias());
-  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_info->flags());
+  EXPECT_EQ("/memfd:/jit-cache", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0xc3000U, frame->map_start);
+  EXPECT_EQ(0xc4000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
 }
 
 // Verify format frame code.
@@ -1455,16 +1449,18 @@
   frame.sp = 0x1000;
   frame.function_name = "function";
   frame.function_offset = 100;
-  auto map_info = MapInfo::Create(0x3000, 0x6000, 0, PROT_READ, "/fake/libfake.so");
-  map_info->set_elf_start_offset(0x2000);
-  frame.map_info = map_info;
+  frame.map_name = "/fake/libfake.so";
+  frame.map_elf_start_offset = 0x2000;
+  frame.map_start = 0x3000;
+  frame.map_end = 0x6000;
+  frame.map_flags = PROT_READ;
 
   EXPECT_EQ("  #01 pc 0000000000001000  /fake/libfake.so (offset 0x2000) (function+100)",
             unwinder64.FormatFrame(frame));
   EXPECT_EQ("  #01 pc 00001000  /fake/libfake.so (offset 0x2000) (function+100)",
             unwinder32.FormatFrame(frame));
 
-  map_info->set_elf_start_offset(0);
+  frame.map_elf_start_offset = 0;
   EXPECT_EQ("  #01 pc 0000000000001000  /fake/libfake.so (function+100)",
             unwinder64.FormatFrame(frame));
   EXPECT_EQ("  #01 pc 00001000  /fake/libfake.so (function+100)", unwinder32.FormatFrame(frame));
@@ -1483,11 +1479,12 @@
   EXPECT_EQ("  #01 pc 0000000000001000  /fake/libfake.so", unwinder64.FormatFrame(frame));
   EXPECT_EQ("  #01 pc 00001000  /fake/libfake.so", unwinder32.FormatFrame(frame));
 
-  map_info->name() = "";
+  frame.map_name = "";
   EXPECT_EQ("  #01 pc 0000000000001000  <anonymous:3000>", unwinder64.FormatFrame(frame));
   EXPECT_EQ("  #01 pc 00001000  <anonymous:3000>", unwinder32.FormatFrame(frame));
 
-  frame.map_info = nullptr;
+  frame.map_start = 0;
+  frame.map_end = 0;
   EXPECT_EQ("  #01 pc 0000000000001000  <unknown>", unwinder64.FormatFrame(frame));
   EXPECT_EQ("  #01 pc 00001000  <unknown>", unwinder32.FormatFrame(frame));
 }
@@ -1504,9 +1501,11 @@
   frame.sp = 0x1000;
   frame.function_name = "function";
   frame.function_offset = 100;
-  frame.map_info = MapInfo::Create(0x3000, 0x6000, 0, PROT_READ, "/fake/libfake.so");
-  SharedString* build_id = new SharedString(std::string{0x46, 0x41, 0x4b, 0x45});
-  frame.map_info->set_build_id(build_id);
+  frame.map_name = "/fake/libfake.so";
+  frame.map_elf_start_offset = 0;
+  frame.map_start = 0x3000;
+  frame.map_end = 0x6000;
+  frame.map_flags = PROT_READ;
 
   EXPECT_EQ("  #01 pc 00001000  /fake/libfake.so (function+100)", unwinder.FormatFrame(frame));
   unwinder.SetDisplayBuildID(true);
@@ -1612,15 +1611,13 @@
   frame = unwinder.BuildFrameFromPcOnly(0x100310);
   EXPECT_EQ(0x10030eU, frame.pc);
   EXPECT_EQ(0x60eU, frame.rel_pc);
-  ASSERT_TRUE(frame.map_info != nullptr);
-  EXPECT_EQ("/fake/jit.so", frame.map_info->name());
-  EXPECT_EQ("/fake/jit.so", frame.map_info->GetFullName());
-  EXPECT_EQ(0x100U, frame.map_info->elf_start_offset());
-  EXPECT_EQ(0x200U, frame.map_info->offset());
-  EXPECT_EQ(0x100000U, frame.map_info->start());
-  EXPECT_EQ(0x101000U, frame.map_info->end());
-  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame.map_info->flags());
-  EXPECT_EQ(0U, frame.map_info->GetLoadBias());
+  EXPECT_EQ("/fake/jit.so", frame.map_name);
+  EXPECT_EQ(0x100U, frame.map_elf_start_offset);
+  EXPECT_EQ(0x200U, frame.map_exact_offset);
+  EXPECT_EQ(0x100000U, frame.map_start);
+  EXPECT_EQ(0x101000U, frame.map_end);
+  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame.map_flags);
+  EXPECT_EQ(0x300U, frame.map_load_bias);
   EXPECT_EQ("", frame.function_name);
   EXPECT_EQ(0U, frame.function_offset);
 }
@@ -1636,15 +1633,13 @@
   frame = unwinder.BuildFrameFromPcOnly(0x1010);
   EXPECT_EQ(0x100cU, frame.pc);
   EXPECT_EQ(0xcU, frame.rel_pc);
-  ASSERT_TRUE(frame.map_info != nullptr);
-  EXPECT_EQ("/system/fake/libc.so", frame.map_info->name());
-  EXPECT_EQ("/system/fake/libc.so", frame.map_info->GetFullName());
-  EXPECT_EQ(0U, frame.map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame.map_info->offset());
-  EXPECT_EQ(0x1000U, frame.map_info->start());
-  EXPECT_EQ(0x8000U, frame.map_info->end());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame.map_info->flags());
-  EXPECT_EQ(0U, frame.map_info->GetLoadBias());
+  EXPECT_EQ("/system/fake/libc.so", frame.map_name);
+  EXPECT_EQ(0U, frame.map_elf_start_offset);
+  EXPECT_EQ(0U, frame.map_exact_offset);
+  EXPECT_EQ(0x1000U, frame.map_start);
+  EXPECT_EQ(0x8000U, frame.map_end);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame.map_flags);
+  EXPECT_EQ(0U, frame.map_load_bias);
   EXPECT_EQ("", frame.function_name);
   EXPECT_EQ(0U, frame.function_offset);
 
@@ -1655,15 +1650,13 @@
   frame = unwinder.BuildFrameFromPcOnly(0x1010);
   EXPECT_EQ(0x100cU, frame.pc);
   EXPECT_EQ(0xcU, frame.rel_pc);
-  ASSERT_TRUE(frame.map_info != nullptr);
-  EXPECT_EQ("/system/fake/libc.so", frame.map_info->name());
-  EXPECT_EQ("/system/fake/libc.so", frame.map_info->GetFullName());
-  EXPECT_EQ(0U, frame.map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame.map_info->offset());
-  EXPECT_EQ(0x1000U, frame.map_info->start());
-  EXPECT_EQ(0x8000U, frame.map_info->end());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame.map_info->flags());
-  EXPECT_EQ(0U, frame.map_info->GetLoadBias());
+  EXPECT_EQ("/system/fake/libc.so", frame.map_name);
+  EXPECT_EQ(0U, frame.map_elf_start_offset);
+  EXPECT_EQ(0U, frame.map_exact_offset);
+  EXPECT_EQ(0x1000U, frame.map_start);
+  EXPECT_EQ(0x8000U, frame.map_end);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame.map_flags);
+  EXPECT_EQ(0U, frame.map_load_bias);
   EXPECT_EQ("", frame.function_name);
   EXPECT_EQ(0U, frame.function_offset);
 
@@ -1673,15 +1666,13 @@
   frame = unwinder.BuildFrameFromPcOnly(0x1010);
   EXPECT_EQ(0x100cU, frame.pc);
   EXPECT_EQ(0xcU, frame.rel_pc);
-  ASSERT_TRUE(frame.map_info != nullptr);
-  EXPECT_EQ("/system/fake/libc.so", frame.map_info->name());
-  EXPECT_EQ("/system/fake/libc.so", frame.map_info->GetFullName());
-  EXPECT_EQ(0U, frame.map_info->elf_start_offset());
-  EXPECT_EQ(0U, frame.map_info->offset());
-  EXPECT_EQ(0x1000U, frame.map_info->start());
-  EXPECT_EQ(0x8000U, frame.map_info->end());
-  EXPECT_EQ(PROT_READ | PROT_WRITE, frame.map_info->flags());
-  EXPECT_EQ(0U, frame.map_info->GetLoadBias());
+  EXPECT_EQ("/system/fake/libc.so", frame.map_name);
+  EXPECT_EQ(0U, frame.map_elf_start_offset);
+  EXPECT_EQ(0U, frame.map_exact_offset);
+  EXPECT_EQ(0x1000U, frame.map_start);
+  EXPECT_EQ(0x8000U, frame.map_end);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame.map_flags);
+  EXPECT_EQ(0U, frame.map_load_bias);
   EXPECT_EQ("Frame0", frame.function_name);
   EXPECT_EQ(10U, frame.function_offset);
 }
@@ -1746,22 +1737,21 @@
   FrameData frame = unwinder.BuildFrameFromPcOnly(0x100310);
   EXPECT_EQ(0x10030eU, frame.pc);
   EXPECT_EQ(0x60eU, frame.rel_pc);
-  ASSERT_TRUE(frame.map_info != nullptr);
-  EXPECT_EQ("/fake/jit.so", frame.map_info->name());
-  EXPECT_EQ("/fake/jit.so", frame.map_info->GetFullName());
-  EXPECT_EQ(0x100U, frame.map_info->elf_start_offset());
-  EXPECT_EQ(0x200U, frame.map_info->offset());
-  EXPECT_EQ(0x100000U, frame.map_info->start());
-  EXPECT_EQ(0x101000U, frame.map_info->end());
-  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame.map_info->flags());
-  EXPECT_EQ(0U, frame.map_info->GetLoadBias());
+  EXPECT_EQ("/fake/jit.so", frame.map_name);
+  EXPECT_EQ(0x100U, frame.map_elf_start_offset);
+  EXPECT_EQ(0x200U, frame.map_exact_offset);
+  EXPECT_EQ(0x100000U, frame.map_start);
+  EXPECT_EQ(0x101000U, frame.map_end);
+  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame.map_flags);
+  EXPECT_EQ(0U, frame.map_load_bias);
   EXPECT_EQ("FakeJitFunction", frame.function_name);
   EXPECT_EQ(0xeU, frame.function_offset);
 }
 
 TEST_F(UnwinderTest, unwinder_from_pid_set_process_memory) {
   auto process_memory = Memory::CreateProcessMemoryCached(getpid());
-  UnwinderFromPid unwinder(10, getpid(), process_memory);
+  UnwinderFromPid unwinder(10, getpid());
+  unwinder.SetProcessMemory(process_memory);
   unwinder.SetArch(unwindstack::Regs::CurrentArch());
   ASSERT_TRUE(unwinder.Init());
   ASSERT_EQ(process_memory.get(), unwinder.GetProcessMemory().get());
@@ -1781,22 +1771,6 @@
   ASSERT_DEATH(CreateJitDebug(ARCH_UNKNOWN, process_memory), "");
 }
 
-TEST_F(UnwinderTest, unwinder_from_pid_with_external_maps) {
-  LocalMaps map;
-  ASSERT_TRUE(map.Parse());
-
-  UnwinderFromPid unwinder1(10, getpid(), &map);
-  unwinder1.SetArch(Regs::CurrentArch());
-  ASSERT_EQ(&map, unwinder1.GetMaps());
-  ASSERT_TRUE(unwinder1.Init());
-  ASSERT_EQ(&map, unwinder1.GetMaps());
-
-  UnwinderFromPid unwinder2(10, getpid(), Regs::CurrentArch(), &map);
-  ASSERT_EQ(&map, unwinder2.GetMaps());
-  ASSERT_TRUE(unwinder2.Init());
-  ASSERT_EQ(&map, unwinder2.GetMaps());
-}
-
 TEST_F(UnwinderDeathTest, set_dex_files_error) {
   Maps maps;
   std::shared_ptr<Memory> process_memory(new MemoryFake);
diff --git a/libunwindstack/tests/VerifyBionicTerminationTest.cpp b/libunwindstack/tests/VerifyBionicTerminationTest.cpp
index ff105c4..37fd89b 100644
--- a/libunwindstack/tests/VerifyBionicTerminationTest.cpp
+++ b/libunwindstack/tests/VerifyBionicTerminationTest.cpp
@@ -69,10 +69,9 @@
 static void VerifyReturnAddress(const FrameData& frame) {
   // Now go and find information about the register data and verify that the relative pc results in
   // an undefined register.
-  Elf elf(Memory::CreateFileMemory(frame.map_info->name(), 0).release());
-  ASSERT_TRUE(frame.map_info != nullptr);
-  ASSERT_TRUE(elf.Init()) << "Failed to init elf object from " << frame.map_info->name().c_str();
-  ASSERT_TRUE(elf.valid()) << "Elf " << frame.map_info->name().c_str() << " is not valid.";
+  Elf elf(Memory::CreateFileMemory(frame.map_name, 0).release());
+  ASSERT_TRUE(elf.Init()) << "Failed to init elf object from " << frame.map_name.c_str();
+  ASSERT_TRUE(elf.valid()) << "Elf " << frame.map_name.c_str() << " is not valid.";
   ElfInterface* interface = elf.interface();
 
   // Only check the eh_frame and the debug_frame since the undefined register
@@ -109,9 +108,8 @@
   const std::vector<FrameData>& frames = unwinder.frames();
   for (size_t i = 0; i < unwinder.NumFrames(); i++) {
     const FrameData& frame = frames[i];
-    if (frame.function_name == "__libc_init" && frame.map_info != nullptr &&
-        !frame.map_info->name().empty() &&
-        std::string("libc.so") == basename(frame.map_info->name().c_str())) {
+    if (frame.function_name == "__libc_init" && !frame.map_name.empty() &&
+        std::string("libc.so") == basename(frame.map_name.c_str())) {
       ASSERT_EQ(unwinder.NumFrames(), i + 1) << "__libc_init is not last frame.";
       ASSERT_NO_FATAL_FAILURE(VerifyReturnAddress(frame));
       found = true;
diff --git a/libunwindstack/offline_files/art_quick_osr_stub_arm/descriptor.data b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/descriptor.data
similarity index 100%
rename from libunwindstack/offline_files/art_quick_osr_stub_arm/descriptor.data
rename to libunwindstack/tests/files/offline/art_quick_osr_stub_arm/descriptor.data
Binary files differ
diff --git a/libunwindstack/offline_files/art_quick_osr_stub_arm/entry0.data b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/entry0.data
similarity index 100%
rename from libunwindstack/offline_files/art_quick_osr_stub_arm/entry0.data
rename to libunwindstack/tests/files/offline/art_quick_osr_stub_arm/entry0.data
Binary files differ
diff --git a/libunwindstack/offline_files/art_quick_osr_stub_arm/entry1.data b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/entry1.data
similarity index 100%
rename from libunwindstack/offline_files/art_quick_osr_stub_arm/entry1.data
rename to libunwindstack/tests/files/offline/art_quick_osr_stub_arm/entry1.data
Binary files differ
diff --git a/libunwindstack/offline_files/art_quick_osr_stub_arm/jit0.data b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/jit0.data
similarity index 100%
rename from libunwindstack/offline_files/art_quick_osr_stub_arm/jit0.data
rename to libunwindstack/tests/files/offline/art_quick_osr_stub_arm/jit0.data
Binary files differ
diff --git a/libunwindstack/offline_files/art_quick_osr_stub_arm/jit1.data b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/jit1.data
similarity index 100%
rename from libunwindstack/offline_files/art_quick_osr_stub_arm/jit1.data
rename to libunwindstack/tests/files/offline/art_quick_osr_stub_arm/jit1.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libart.so b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libart.so
new file mode 100644
index 0000000..09ba495
--- /dev/null
+++ b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libart.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libc.so b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libc.so
new file mode 100644
index 0000000..39c9025
--- /dev/null
+++ b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libc.so
Binary files differ
diff --git a/libunwindstack/offline_files/art_quick_osr_stub_arm/maps.txt b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/maps.txt
similarity index 100%
rename from libunwindstack/offline_files/art_quick_osr_stub_arm/maps.txt
rename to libunwindstack/tests/files/offline/art_quick_osr_stub_arm/maps.txt
diff --git a/libunwindstack/offline_files/art_quick_osr_stub_arm/regs.txt b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/regs.txt
similarity index 100%
rename from libunwindstack/offline_files/art_quick_osr_stub_arm/regs.txt
rename to libunwindstack/tests/files/offline/art_quick_osr_stub_arm/regs.txt
diff --git a/libunwindstack/offline_files/art_quick_osr_stub_arm/stack.data b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/stack.data
similarity index 100%
rename from libunwindstack/offline_files/art_quick_osr_stub_arm/stack.data
rename to libunwindstack/tests/files/offline/art_quick_osr_stub_arm/stack.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/libc.so b/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/libc.so
new file mode 100644
index 0000000..78449bf
--- /dev/null
+++ b/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/libc.so
Binary files differ
diff --git a/libunwindstack/offline_files/bad_eh_frame_hdr_arm64/maps.txt b/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/maps.txt
similarity index 100%
rename from libunwindstack/offline_files/bad_eh_frame_hdr_arm64/maps.txt
rename to libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/maps.txt
diff --git a/libunwindstack/offline_files/bad_eh_frame_hdr_arm64/regs.txt b/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/regs.txt
similarity index 100%
rename from libunwindstack/offline_files/bad_eh_frame_hdr_arm64/regs.txt
rename to libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/regs.txt
diff --git a/libunwindstack/offline_files/bad_eh_frame_hdr_arm64/stack.data b/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/stack.data
similarity index 100%
rename from libunwindstack/offline_files/bad_eh_frame_hdr_arm64/stack.data
rename to libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/stack.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/waiter64 b/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/waiter64
new file mode 100644
index 0000000..81bda1d
--- /dev/null
+++ b/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/waiter64
Binary files differ
diff --git a/libunwindstack/tests/files/offline/debug_frame_first_x86/libc.so b/libunwindstack/tests/files/offline/debug_frame_first_x86/libc.so
new file mode 100644
index 0000000..9c78790
--- /dev/null
+++ b/libunwindstack/tests/files/offline/debug_frame_first_x86/libc.so
Binary files differ
diff --git a/libunwindstack/offline_files/debug_frame_first_x86/maps.txt b/libunwindstack/tests/files/offline/debug_frame_first_x86/maps.txt
similarity index 100%
rename from libunwindstack/offline_files/debug_frame_first_x86/maps.txt
rename to libunwindstack/tests/files/offline/debug_frame_first_x86/maps.txt
diff --git a/libunwindstack/offline_files/debug_frame_first_x86/regs.txt b/libunwindstack/tests/files/offline/debug_frame_first_x86/regs.txt
similarity index 100%
rename from libunwindstack/offline_files/debug_frame_first_x86/regs.txt
rename to libunwindstack/tests/files/offline/debug_frame_first_x86/regs.txt
diff --git a/libunwindstack/offline_files/debug_frame_first_x86/stack.data b/libunwindstack/tests/files/offline/debug_frame_first_x86/stack.data
similarity index 100%
rename from libunwindstack/offline_files/debug_frame_first_x86/stack.data
rename to libunwindstack/tests/files/offline/debug_frame_first_x86/stack.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/debug_frame_first_x86/waiter b/libunwindstack/tests/files/offline/debug_frame_first_x86/waiter
new file mode 100644
index 0000000..b1fc024
--- /dev/null
+++ b/libunwindstack/tests/files/offline/debug_frame_first_x86/waiter
Binary files differ
diff --git a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/libbinder.so b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/libbinder.so
new file mode 100644
index 0000000..4b7bf44
--- /dev/null
+++ b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/libbinder.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/libc.so b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/libc.so
new file mode 100644
index 0000000..013858e
--- /dev/null
+++ b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/libc.so
Binary files differ
diff --git a/libunwindstack/offline_files/debug_frame_load_bias_arm/maps.txt b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/maps.txt
similarity index 100%
rename from libunwindstack/offline_files/debug_frame_load_bias_arm/maps.txt
rename to libunwindstack/tests/files/offline/debug_frame_load_bias_arm/maps.txt
diff --git a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/mediaserver b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/mediaserver
new file mode 100644
index 0000000..9e4a83f
--- /dev/null
+++ b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/mediaserver
Binary files differ
diff --git a/libunwindstack/offline_files/debug_frame_load_bias_arm/regs.txt b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/regs.txt
similarity index 100%
rename from libunwindstack/offline_files/debug_frame_load_bias_arm/regs.txt
rename to libunwindstack/tests/files/offline/debug_frame_load_bias_arm/regs.txt
diff --git a/libunwindstack/offline_files/debug_frame_load_bias_arm/stack.data b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/stack.data
similarity index 100%
rename from libunwindstack/offline_files/debug_frame_load_bias_arm/stack.data
rename to libunwindstack/tests/files/offline/debug_frame_load_bias_arm/stack.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/libc.so b/libunwindstack/tests/files/offline/eh_frame_bias_x86/libc.so
new file mode 100644
index 0000000..f3eb615
--- /dev/null
+++ b/libunwindstack/tests/files/offline/eh_frame_bias_x86/libc.so
Binary files differ
diff --git a/libunwindstack/offline_files/eh_frame_bias_x86/maps.txt b/libunwindstack/tests/files/offline/eh_frame_bias_x86/maps.txt
similarity index 100%
rename from libunwindstack/offline_files/eh_frame_bias_x86/maps.txt
rename to libunwindstack/tests/files/offline/eh_frame_bias_x86/maps.txt
diff --git a/libunwindstack/offline_files/eh_frame_bias_x86/regs.txt b/libunwindstack/tests/files/offline/eh_frame_bias_x86/regs.txt
similarity index 100%
rename from libunwindstack/offline_files/eh_frame_bias_x86/regs.txt
rename to libunwindstack/tests/files/offline/eh_frame_bias_x86/regs.txt
diff --git a/libunwindstack/offline_files/eh_frame_bias_x86/stack.data b/libunwindstack/tests/files/offline/eh_frame_bias_x86/stack.data
similarity index 100%
rename from libunwindstack/offline_files/eh_frame_bias_x86/stack.data
rename to libunwindstack/tests/files/offline/eh_frame_bias_x86/stack.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/tombstoned b/libunwindstack/tests/files/offline/eh_frame_bias_x86/tombstoned
new file mode 100644
index 0000000..aefdb6b
--- /dev/null
+++ b/libunwindstack/tests/files/offline/eh_frame_bias_x86/tombstoned
Binary files differ
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/vdso.so b/libunwindstack/tests/files/offline/eh_frame_bias_x86/vdso.so
new file mode 100644
index 0000000..c71dcfb
--- /dev/null
+++ b/libunwindstack/tests/files/offline/eh_frame_bias_x86/vdso.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/libc.so b/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/libc.so
new file mode 100644
index 0000000..46b6f45
--- /dev/null
+++ b/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/libc.so
Binary files differ
diff --git a/libunwindstack/offline_files/eh_frame_hdr_begin_x86_64/maps.txt b/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/maps.txt
similarity index 100%
rename from libunwindstack/offline_files/eh_frame_hdr_begin_x86_64/maps.txt
rename to libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/maps.txt
diff --git a/libunwindstack/offline_files/eh_frame_hdr_begin_x86_64/regs.txt b/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/regs.txt
similarity index 100%
rename from libunwindstack/offline_files/eh_frame_hdr_begin_x86_64/regs.txt
rename to libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/regs.txt
diff --git a/libunwindstack/offline_files/eh_frame_hdr_begin_x86_64/stack.data b/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/stack.data
similarity index 100%
rename from libunwindstack/offline_files/eh_frame_hdr_begin_x86_64/stack.data
rename to libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/stack.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/unwind_test64 b/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/unwind_test64
new file mode 100644
index 0000000..ab0ef8f
--- /dev/null
+++ b/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/unwind_test64
Binary files differ
diff --git a/libunwindstack/tests/files/offline/empty_arm64/libbinder.so b/libunwindstack/tests/files/offline/empty_arm64/libbinder.so
new file mode 100644
index 0000000..f30384c
--- /dev/null
+++ b/libunwindstack/tests/files/offline/empty_arm64/libbinder.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/empty_arm64/libc.so b/libunwindstack/tests/files/offline/empty_arm64/libc.so
new file mode 100644
index 0000000..b05dcaf
--- /dev/null
+++ b/libunwindstack/tests/files/offline/empty_arm64/libc.so
Binary files differ
diff --git a/libunwindstack/offline_files/empty_arm64/maps.txt b/libunwindstack/tests/files/offline/empty_arm64/maps.txt
similarity index 100%
rename from libunwindstack/offline_files/empty_arm64/maps.txt
rename to libunwindstack/tests/files/offline/empty_arm64/maps.txt
diff --git a/libunwindstack/tests/files/offline/empty_arm64/netd b/libunwindstack/tests/files/offline/empty_arm64/netd
new file mode 100644
index 0000000..8a72e94
--- /dev/null
+++ b/libunwindstack/tests/files/offline/empty_arm64/netd
Binary files differ
diff --git a/libunwindstack/offline_files/empty_arm64/regs.txt b/libunwindstack/tests/files/offline/empty_arm64/regs.txt
similarity index 100%
rename from libunwindstack/offline_files/empty_arm64/regs.txt
rename to libunwindstack/tests/files/offline/empty_arm64/regs.txt
diff --git a/libunwindstack/offline_files/empty_arm64/stack.data b/libunwindstack/tests/files/offline/empty_arm64/stack.data
similarity index 100%
rename from libunwindstack/offline_files/empty_arm64/stack.data
rename to libunwindstack/tests/files/offline/empty_arm64/stack.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/gnu_debugdata_arm/libandroid_runtime.so b/libunwindstack/tests/files/offline/gnu_debugdata_arm/libandroid_runtime.so
new file mode 100644
index 0000000..e4283e6
--- /dev/null
+++ b/libunwindstack/tests/files/offline/gnu_debugdata_arm/libandroid_runtime.so
Binary files differ
diff --git a/libunwindstack/offline_files/gnu_debugdata_arm/maps.txt b/libunwindstack/tests/files/offline/gnu_debugdata_arm/maps.txt
similarity index 100%
rename from libunwindstack/offline_files/gnu_debugdata_arm/maps.txt
rename to libunwindstack/tests/files/offline/gnu_debugdata_arm/maps.txt
diff --git a/libunwindstack/offline_files/gnu_debugdata_arm/regs.txt b/libunwindstack/tests/files/offline/gnu_debugdata_arm/regs.txt
similarity index 100%
rename from libunwindstack/offline_files/gnu_debugdata_arm/regs.txt
rename to libunwindstack/tests/files/offline/gnu_debugdata_arm/regs.txt
diff --git a/libunwindstack/offline_files/gnu_debugdata_arm/stack.data b/libunwindstack/tests/files/offline/gnu_debugdata_arm/stack.data
similarity index 100%
rename from libunwindstack/offline_files/gnu_debugdata_arm/stack.data
rename to libunwindstack/tests/files/offline/gnu_debugdata_arm/stack.data
Binary files differ
diff --git a/libunwindstack/offline_files/invalid_elf_offset_arm/maps.txt b/libunwindstack/tests/files/offline/invalid_elf_offset_arm/maps.txt
similarity index 100%
rename from libunwindstack/offline_files/invalid_elf_offset_arm/maps.txt
rename to libunwindstack/tests/files/offline/invalid_elf_offset_arm/maps.txt
diff --git a/libunwindstack/offline_files/invalid_elf_offset_arm/regs.txt b/libunwindstack/tests/files/offline/invalid_elf_offset_arm/regs.txt
similarity index 100%
rename from libunwindstack/offline_files/invalid_elf_offset_arm/regs.txt
rename to libunwindstack/tests/files/offline/invalid_elf_offset_arm/regs.txt
diff --git a/libunwindstack/offline_files/apk_rx_arm64/fake.apk b/libunwindstack/tests/files/offline/jit_debug_arm/137-cfi.odex
similarity index 78%
rename from libunwindstack/offline_files/apk_rx_arm64/fake.apk
rename to libunwindstack/tests/files/offline/jit_debug_arm/137-cfi.odex
index 1f45187..35a6bc5 100644
--- a/libunwindstack/offline_files/apk_rx_arm64/fake.apk
+++ b/libunwindstack/tests/files/offline/jit_debug_arm/137-cfi.odex
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/dalvikvm32 b/libunwindstack/tests/files/offline/jit_debug_arm/dalvikvm32
new file mode 100644
index 0000000..def299e
--- /dev/null
+++ b/libunwindstack/tests/files/offline/jit_debug_arm/dalvikvm32
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_arm/descriptor.data b/libunwindstack/tests/files/offline/jit_debug_arm/descriptor.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_arm/descriptor.data
rename to libunwindstack/tests/files/offline/jit_debug_arm/descriptor.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_arm/descriptor1.data b/libunwindstack/tests/files/offline/jit_debug_arm/descriptor1.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_arm/descriptor1.data
rename to libunwindstack/tests/files/offline/jit_debug_arm/descriptor1.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_arm/entry0.data b/libunwindstack/tests/files/offline/jit_debug_arm/entry0.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_arm/entry0.data
rename to libunwindstack/tests/files/offline/jit_debug_arm/entry0.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_arm/entry1.data b/libunwindstack/tests/files/offline/jit_debug_arm/entry1.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_arm/entry1.data
rename to libunwindstack/tests/files/offline/jit_debug_arm/entry1.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_arm/entry2.data b/libunwindstack/tests/files/offline/jit_debug_arm/entry2.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_arm/entry2.data
rename to libunwindstack/tests/files/offline/jit_debug_arm/entry2.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_arm/entry3.data b/libunwindstack/tests/files/offline/jit_debug_arm/entry3.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_arm/entry3.data
rename to libunwindstack/tests/files/offline/jit_debug_arm/entry3.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_arm/entry4.data b/libunwindstack/tests/files/offline/jit_debug_arm/entry4.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_arm/entry4.data
rename to libunwindstack/tests/files/offline/jit_debug_arm/entry4.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_arm/entry5.data b/libunwindstack/tests/files/offline/jit_debug_arm/entry5.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_arm/entry5.data
rename to libunwindstack/tests/files/offline/jit_debug_arm/entry5.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_arm/entry6.data b/libunwindstack/tests/files/offline/jit_debug_arm/entry6.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_arm/entry6.data
rename to libunwindstack/tests/files/offline/jit_debug_arm/entry6.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_arm/jit0.data b/libunwindstack/tests/files/offline/jit_debug_arm/jit0.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_arm/jit0.data
rename to libunwindstack/tests/files/offline/jit_debug_arm/jit0.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_arm/jit1.data b/libunwindstack/tests/files/offline/jit_debug_arm/jit1.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_arm/jit1.data
rename to libunwindstack/tests/files/offline/jit_debug_arm/jit1.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_arm/jit2.data b/libunwindstack/tests/files/offline/jit_debug_arm/jit2.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_arm/jit2.data
rename to libunwindstack/tests/files/offline/jit_debug_arm/jit2.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_arm/jit3.data b/libunwindstack/tests/files/offline/jit_debug_arm/jit3.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_arm/jit3.data
rename to libunwindstack/tests/files/offline/jit_debug_arm/jit3.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_arm/jit4.data b/libunwindstack/tests/files/offline/jit_debug_arm/jit4.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_arm/jit4.data
rename to libunwindstack/tests/files/offline/jit_debug_arm/jit4.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_arm/jit5.data b/libunwindstack/tests/files/offline/jit_debug_arm/jit5.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_arm/jit5.data
rename to libunwindstack/tests/files/offline/jit_debug_arm/jit5.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_arm/jit6.data b/libunwindstack/tests/files/offline/jit_debug_arm/jit6.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_arm/jit6.data
rename to libunwindstack/tests/files/offline/jit_debug_arm/jit6.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/libart.so b/libunwindstack/tests/files/offline/jit_debug_arm/libart.so
new file mode 100644
index 0000000..0527893
--- /dev/null
+++ b/libunwindstack/tests/files/offline/jit_debug_arm/libart.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/libartd.so b/libunwindstack/tests/files/offline/jit_debug_arm/libartd.so
new file mode 100644
index 0000000..8559056
--- /dev/null
+++ b/libunwindstack/tests/files/offline/jit_debug_arm/libartd.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/libarttestd.so b/libunwindstack/tests/files/offline/jit_debug_arm/libarttestd.so
new file mode 100644
index 0000000..06dbf10
--- /dev/null
+++ b/libunwindstack/tests/files/offline/jit_debug_arm/libarttestd.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/libc.so b/libunwindstack/tests/files/offline/jit_debug_arm/libc.so
new file mode 100644
index 0000000..9894e66
--- /dev/null
+++ b/libunwindstack/tests/files/offline/jit_debug_arm/libc.so
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_arm/maps.txt b/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_arm/maps.txt
rename to libunwindstack/tests/files/offline/jit_debug_arm/maps.txt
diff --git a/libunwindstack/offline_files/jit_debug_arm/regs.txt b/libunwindstack/tests/files/offline/jit_debug_arm/regs.txt
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_arm/regs.txt
rename to libunwindstack/tests/files/offline/jit_debug_arm/regs.txt
diff --git a/libunwindstack/offline_files/jit_debug_arm/stack.data b/libunwindstack/tests/files/offline/jit_debug_arm/stack.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_arm/stack.data
rename to libunwindstack/tests/files/offline/jit_debug_arm/stack.data
Binary files differ
diff --git a/libunwindstack/offline_files/apk_rx_arm64/fake.apk b/libunwindstack/tests/files/offline/jit_debug_x86/137-cfi.odex
similarity index 75%
copy from libunwindstack/offline_files/apk_rx_arm64/fake.apk
copy to libunwindstack/tests/files/offline/jit_debug_x86/137-cfi.odex
index 1f45187..870ac0a 100644
--- a/libunwindstack/offline_files/apk_rx_arm64/fake.apk
+++ b/libunwindstack/tests/files/offline/jit_debug_x86/137-cfi.odex
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/dalvikvm32 b/libunwindstack/tests/files/offline/jit_debug_x86/dalvikvm32
new file mode 100644
index 0000000..76ffad9
--- /dev/null
+++ b/libunwindstack/tests/files/offline/jit_debug_x86/dalvikvm32
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_x86/descriptor.data b/libunwindstack/tests/files/offline/jit_debug_x86/descriptor.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_x86/descriptor.data
rename to libunwindstack/tests/files/offline/jit_debug_x86/descriptor.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_x86/entry0.data b/libunwindstack/tests/files/offline/jit_debug_x86/entry0.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_x86/entry0.data
rename to libunwindstack/tests/files/offline/jit_debug_x86/entry0.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_x86/entry1.data b/libunwindstack/tests/files/offline/jit_debug_x86/entry1.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_x86/entry1.data
rename to libunwindstack/tests/files/offline/jit_debug_x86/entry1.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_x86/entry2.data b/libunwindstack/tests/files/offline/jit_debug_x86/entry2.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_x86/entry2.data
rename to libunwindstack/tests/files/offline/jit_debug_x86/entry2.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_x86/entry3.data b/libunwindstack/tests/files/offline/jit_debug_x86/entry3.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_x86/entry3.data
rename to libunwindstack/tests/files/offline/jit_debug_x86/entry3.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_x86/entry4.data b/libunwindstack/tests/files/offline/jit_debug_x86/entry4.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_x86/entry4.data
rename to libunwindstack/tests/files/offline/jit_debug_x86/entry4.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_x86/entry5.data b/libunwindstack/tests/files/offline/jit_debug_x86/entry5.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_x86/entry5.data
rename to libunwindstack/tests/files/offline/jit_debug_x86/entry5.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_x86/entry6.data b/libunwindstack/tests/files/offline/jit_debug_x86/entry6.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_x86/entry6.data
rename to libunwindstack/tests/files/offline/jit_debug_x86/entry6.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_x86/jit0.data b/libunwindstack/tests/files/offline/jit_debug_x86/jit0.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_x86/jit0.data
rename to libunwindstack/tests/files/offline/jit_debug_x86/jit0.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_x86/jit1.data b/libunwindstack/tests/files/offline/jit_debug_x86/jit1.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_x86/jit1.data
rename to libunwindstack/tests/files/offline/jit_debug_x86/jit1.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_x86/jit2.data b/libunwindstack/tests/files/offline/jit_debug_x86/jit2.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_x86/jit2.data
rename to libunwindstack/tests/files/offline/jit_debug_x86/jit2.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_x86/jit3.data b/libunwindstack/tests/files/offline/jit_debug_x86/jit3.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_x86/jit3.data
rename to libunwindstack/tests/files/offline/jit_debug_x86/jit3.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_x86/jit4.data b/libunwindstack/tests/files/offline/jit_debug_x86/jit4.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_x86/jit4.data
rename to libunwindstack/tests/files/offline/jit_debug_x86/jit4.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_x86/jit5.data b/libunwindstack/tests/files/offline/jit_debug_x86/jit5.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_x86/jit5.data
rename to libunwindstack/tests/files/offline/jit_debug_x86/jit5.data
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_x86/jit6.data b/libunwindstack/tests/files/offline/jit_debug_x86/jit6.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_x86/jit6.data
rename to libunwindstack/tests/files/offline/jit_debug_x86/jit6.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/libartd.so b/libunwindstack/tests/files/offline/jit_debug_x86/libartd.so
new file mode 100644
index 0000000..92ed991
--- /dev/null
+++ b/libunwindstack/tests/files/offline/jit_debug_x86/libartd.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/libarttestd.so b/libunwindstack/tests/files/offline/jit_debug_x86/libarttestd.so
new file mode 100644
index 0000000..5efae02
--- /dev/null
+++ b/libunwindstack/tests/files/offline/jit_debug_x86/libarttestd.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/libc.so b/libunwindstack/tests/files/offline/jit_debug_x86/libc.so
new file mode 100644
index 0000000..9c78790
--- /dev/null
+++ b/libunwindstack/tests/files/offline/jit_debug_x86/libc.so
Binary files differ
diff --git a/libunwindstack/offline_files/jit_debug_x86/maps.txt b/libunwindstack/tests/files/offline/jit_debug_x86/maps.txt
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_x86/maps.txt
rename to libunwindstack/tests/files/offline/jit_debug_x86/maps.txt
diff --git a/libunwindstack/offline_files/jit_debug_x86/regs.txt b/libunwindstack/tests/files/offline/jit_debug_x86/regs.txt
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_x86/regs.txt
rename to libunwindstack/tests/files/offline/jit_debug_x86/regs.txt
diff --git a/libunwindstack/offline_files/jit_debug_x86/stack.data b/libunwindstack/tests/files/offline/jit_debug_x86/stack.data
similarity index 100%
rename from libunwindstack/offline_files/jit_debug_x86/stack.data
rename to libunwindstack/tests/files/offline/jit_debug_x86/stack.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_map_arm/jit_map0.so b/libunwindstack/tests/files/offline/jit_map_arm/jit_map0.so
new file mode 100644
index 0000000..e667883
--- /dev/null
+++ b/libunwindstack/tests/files/offline/jit_map_arm/jit_map0.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_map_arm/jit_map1.so b/libunwindstack/tests/files/offline/jit_map_arm/jit_map1.so
new file mode 100644
index 0000000..9a1d714
--- /dev/null
+++ b/libunwindstack/tests/files/offline/jit_map_arm/jit_map1.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_map_arm/libart.so b/libunwindstack/tests/files/offline/jit_map_arm/libart.so
new file mode 100644
index 0000000..09ba495
--- /dev/null
+++ b/libunwindstack/tests/files/offline/jit_map_arm/libart.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_map_arm/libc.so b/libunwindstack/tests/files/offline/jit_map_arm/libc.so
new file mode 100644
index 0000000..39c9025
--- /dev/null
+++ b/libunwindstack/tests/files/offline/jit_map_arm/libc.so
Binary files differ
diff --git a/libunwindstack/offline_files/jit_map_arm/maps.txt b/libunwindstack/tests/files/offline/jit_map_arm/maps.txt
similarity index 100%
rename from libunwindstack/offline_files/jit_map_arm/maps.txt
rename to libunwindstack/tests/files/offline/jit_map_arm/maps.txt
diff --git a/libunwindstack/offline_files/jit_map_arm/regs.txt b/libunwindstack/tests/files/offline/jit_map_arm/regs.txt
similarity index 100%
rename from libunwindstack/offline_files/jit_map_arm/regs.txt
rename to libunwindstack/tests/files/offline/jit_map_arm/regs.txt
diff --git a/libunwindstack/offline_files/jit_map_arm/stack.data b/libunwindstack/tests/files/offline/jit_map_arm/stack.data
similarity index 100%
rename from libunwindstack/offline_files/jit_map_arm/stack.data
rename to libunwindstack/tests/files/offline/jit_map_arm/stack.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/libc.so b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/libc.so
new file mode 100644
index 0000000..7bb7156
--- /dev/null
+++ b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/libc.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/linker64 b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/linker64
new file mode 100644
index 0000000..00a3896
--- /dev/null
+++ b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/linker64
Binary files differ
diff --git a/libunwindstack/offline_files/load_bias_different_section_bias_arm64/maps.txt b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/maps.txt
similarity index 100%
rename from libunwindstack/offline_files/load_bias_different_section_bias_arm64/maps.txt
rename to libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/maps.txt
diff --git a/libunwindstack/offline_files/load_bias_different_section_bias_arm64/regs.txt b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/regs.txt
similarity index 100%
rename from libunwindstack/offline_files/load_bias_different_section_bias_arm64/regs.txt
rename to libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/regs.txt
diff --git a/libunwindstack/offline_files/load_bias_different_section_bias_arm64/stack0.data b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack0.data
similarity index 100%
rename from libunwindstack/offline_files/load_bias_different_section_bias_arm64/stack0.data
rename to libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack0.data
Binary files differ
diff --git a/libunwindstack/offline_files/load_bias_different_section_bias_arm64/stack1.data b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack1.data
similarity index 100%
rename from libunwindstack/offline_files/load_bias_different_section_bias_arm64/stack1.data
rename to libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack1.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/test b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/test
new file mode 100644
index 0000000..3a75b8f
--- /dev/null
+++ b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/test
Binary files differ
diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/vdso b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/vdso
new file mode 100644
index 0000000..4940916
--- /dev/null
+++ b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/vdso
Binary files differ
diff --git a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/libc.so b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/libc.so
new file mode 100644
index 0000000..63383d0
--- /dev/null
+++ b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/libc.so
Binary files differ
diff --git a/libunwindstack/offline_files/load_bias_ro_rx_x86_64/maps.txt b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/maps.txt
similarity index 100%
rename from libunwindstack/offline_files/load_bias_ro_rx_x86_64/maps.txt
rename to libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/maps.txt
diff --git a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/perfetto_unittests b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/perfetto_unittests
new file mode 100644
index 0000000..a30e599
--- /dev/null
+++ b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/perfetto_unittests
Binary files differ
diff --git a/libunwindstack/offline_files/load_bias_ro_rx_x86_64/regs.txt b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/regs.txt
similarity index 100%
rename from libunwindstack/offline_files/load_bias_ro_rx_x86_64/regs.txt
rename to libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/regs.txt
diff --git a/libunwindstack/offline_files/load_bias_ro_rx_x86_64/stack.data b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/stack.data
similarity index 100%
rename from libunwindstack/offline_files/load_bias_ro_rx_x86_64/stack.data
rename to libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/stack.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/offset_arm/libc.so b/libunwindstack/tests/files/offline/offset_arm/libc.so
new file mode 100644
index 0000000..9f5c8ca
--- /dev/null
+++ b/libunwindstack/tests/files/offline/offset_arm/libc.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/offset_arm/libunwindstack_test b/libunwindstack/tests/files/offline/offset_arm/libunwindstack_test
new file mode 100644
index 0000000..7a30bfa
--- /dev/null
+++ b/libunwindstack/tests/files/offline/offset_arm/libunwindstack_test
Binary files differ
diff --git a/libunwindstack/offline_files/offset_arm/maps.txt b/libunwindstack/tests/files/offline/offset_arm/maps.txt
similarity index 100%
rename from libunwindstack/offline_files/offset_arm/maps.txt
rename to libunwindstack/tests/files/offline/offset_arm/maps.txt
diff --git a/libunwindstack/offline_files/offset_arm/regs.txt b/libunwindstack/tests/files/offline/offset_arm/regs.txt
similarity index 100%
rename from libunwindstack/offline_files/offset_arm/regs.txt
rename to libunwindstack/tests/files/offline/offset_arm/regs.txt
diff --git a/libunwindstack/offline_files/offset_arm/stack0.data b/libunwindstack/tests/files/offline/offset_arm/stack0.data
similarity index 100%
rename from libunwindstack/offline_files/offset_arm/stack0.data
rename to libunwindstack/tests/files/offline/offset_arm/stack0.data
Binary files differ
diff --git a/libunwindstack/offline_files/offset_arm/stack1.data b/libunwindstack/tests/files/offline/offset_arm/stack1.data
similarity index 100%
rename from libunwindstack/offline_files/offset_arm/stack1.data
rename to libunwindstack/tests/files/offline/offset_arm/stack1.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/pauth_pc_arm64/libc.so b/libunwindstack/tests/files/offline/pauth_pc_arm64/libc.so
new file mode 100644
index 0000000..def2b02
--- /dev/null
+++ b/libunwindstack/tests/files/offline/pauth_pc_arm64/libc.so
Binary files differ
diff --git a/libunwindstack/offline_files/pauth_pc_arm64/maps.txt b/libunwindstack/tests/files/offline/pauth_pc_arm64/maps.txt
similarity index 100%
rename from libunwindstack/offline_files/pauth_pc_arm64/maps.txt
rename to libunwindstack/tests/files/offline/pauth_pc_arm64/maps.txt
diff --git a/libunwindstack/offline_files/pauth_pc_arm64/regs.txt b/libunwindstack/tests/files/offline/pauth_pc_arm64/regs.txt
similarity index 100%
rename from libunwindstack/offline_files/pauth_pc_arm64/regs.txt
rename to libunwindstack/tests/files/offline/pauth_pc_arm64/regs.txt
diff --git a/libunwindstack/offline_files/pauth_pc_arm64/stack.data b/libunwindstack/tests/files/offline/pauth_pc_arm64/stack.data
similarity index 100%
rename from libunwindstack/offline_files/pauth_pc_arm64/stack.data
rename to libunwindstack/tests/files/offline/pauth_pc_arm64/stack.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/pauth_pc_arm64/toybox b/libunwindstack/tests/files/offline/pauth_pc_arm64/toybox
new file mode 100644
index 0000000..1d33935
--- /dev/null
+++ b/libunwindstack/tests/files/offline/pauth_pc_arm64/toybox
Binary files differ
diff --git a/libunwindstack/offline_files/shared_lib_in_apk_arm64/ANGLEPrebuilt.apk b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/ANGLEPrebuilt.apk
similarity index 100%
rename from libunwindstack/offline_files/shared_lib_in_apk_arm64/ANGLEPrebuilt.apk
rename to libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/ANGLEPrebuilt.apk
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/libc.so b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/libc.so
new file mode 100644
index 0000000..20008fd
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/libc.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/linker64 b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/linker64
new file mode 100644
index 0000000..b90933b
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/linker64
Binary files differ
diff --git a/libunwindstack/offline_files/shared_lib_in_apk_arm64/maps.txt b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/maps.txt
similarity index 100%
rename from libunwindstack/offline_files/shared_lib_in_apk_arm64/maps.txt
rename to libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/maps.txt
diff --git a/libunwindstack/offline_files/shared_lib_in_apk_arm64/regs.txt b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/regs.txt
similarity index 100%
rename from libunwindstack/offline_files/shared_lib_in_apk_arm64/regs.txt
rename to libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/regs.txt
diff --git a/libunwindstack/offline_files/shared_lib_in_apk_arm64/stack0.data b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/stack0.data
similarity index 100%
rename from libunwindstack/offline_files/shared_lib_in_apk_arm64/stack0.data
rename to libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/stack0.data
Binary files differ
diff --git a/libunwindstack/offline_files/shared_lib_in_apk_arm64/stack1.data b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/stack1.data
similarity index 100%
rename from libunwindstack/offline_files/shared_lib_in_apk_arm64/stack1.data
rename to libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/stack1.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/vdso.so b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/vdso.so
new file mode 100644
index 0000000..205ebd4
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/vdso.so
Binary files differ
diff --git a/libunwindstack/offline_files/shared_lib_in_apk_memory_only_arm64/lib_mem.data b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/lib_mem.data
similarity index 100%
rename from libunwindstack/offline_files/shared_lib_in_apk_memory_only_arm64/lib_mem.data
rename to libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/lib_mem.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/libc.so b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/libc.so
new file mode 100644
index 0000000..20008fd
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/libc.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/linker64 b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/linker64
new file mode 100644
index 0000000..b90933b
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/linker64
Binary files differ
diff --git a/libunwindstack/offline_files/shared_lib_in_apk_memory_only_arm64/maps.txt b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/maps.txt
similarity index 100%
rename from libunwindstack/offline_files/shared_lib_in_apk_memory_only_arm64/maps.txt
rename to libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/maps.txt
diff --git a/libunwindstack/offline_files/shared_lib_in_apk_memory_only_arm64/regs.txt b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/regs.txt
similarity index 100%
rename from libunwindstack/offline_files/shared_lib_in_apk_memory_only_arm64/regs.txt
rename to libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/regs.txt
diff --git a/libunwindstack/offline_files/shared_lib_in_apk_memory_only_arm64/stack0.data b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/stack0.data
similarity index 100%
rename from libunwindstack/offline_files/shared_lib_in_apk_memory_only_arm64/stack0.data
rename to libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/stack0.data
Binary files differ
diff --git a/libunwindstack/offline_files/shared_lib_in_apk_memory_only_arm64/stack1.data b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/stack1.data
similarity index 100%
rename from libunwindstack/offline_files/shared_lib_in_apk_memory_only_arm64/stack1.data
rename to libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/stack1.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/vdso.so b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/vdso.so
new file mode 100644
index 0000000..205ebd4
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/vdso.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/libc.so b/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/libc.so
new file mode 100644
index 0000000..cac1dd9
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/libc.so
Binary files differ
diff --git a/libunwindstack/offline_files/shared_lib_in_apk_single_map_arm64/maps.txt b/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/maps.txt
similarity index 100%
rename from libunwindstack/offline_files/shared_lib_in_apk_single_map_arm64/maps.txt
rename to libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/maps.txt
diff --git a/libunwindstack/offline_files/shared_lib_in_apk_single_map_arm64/regs.txt b/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/regs.txt
similarity index 100%
rename from libunwindstack/offline_files/shared_lib_in_apk_single_map_arm64/regs.txt
rename to libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/regs.txt
diff --git a/libunwindstack/offline_files/shared_lib_in_apk_single_map_arm64/stack.data b/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/stack.data
similarity index 100%
rename from libunwindstack/offline_files/shared_lib_in_apk_single_map_arm64/stack.data
rename to libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/stack.data
Binary files differ
diff --git a/libunwindstack/offline_files/shared_lib_in_apk_single_map_arm64/test.apk b/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/test.apk
similarity index 100%
rename from libunwindstack/offline_files/shared_lib_in_apk_single_map_arm64/test.apk
rename to libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/test.apk
Binary files differ
diff --git a/libunwindstack/tests/files/offline/signal_fde_x86/libc.so b/libunwindstack/tests/files/offline/signal_fde_x86/libc.so
new file mode 100644
index 0000000..5c882e4
--- /dev/null
+++ b/libunwindstack/tests/files/offline/signal_fde_x86/libc.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/signal_fde_x86/libunwindstack_test b/libunwindstack/tests/files/offline/signal_fde_x86/libunwindstack_test
new file mode 100644
index 0000000..8dcff67
--- /dev/null
+++ b/libunwindstack/tests/files/offline/signal_fde_x86/libunwindstack_test
Binary files differ
diff --git a/libunwindstack/offline_files/signal_fde_x86/maps.txt b/libunwindstack/tests/files/offline/signal_fde_x86/maps.txt
similarity index 100%
rename from libunwindstack/offline_files/signal_fde_x86/maps.txt
rename to libunwindstack/tests/files/offline/signal_fde_x86/maps.txt
diff --git a/libunwindstack/offline_files/signal_fde_x86/regs.txt b/libunwindstack/tests/files/offline/signal_fde_x86/regs.txt
similarity index 100%
rename from libunwindstack/offline_files/signal_fde_x86/regs.txt
rename to libunwindstack/tests/files/offline/signal_fde_x86/regs.txt
diff --git a/libunwindstack/offline_files/signal_fde_x86/stack0.data b/libunwindstack/tests/files/offline/signal_fde_x86/stack0.data
similarity index 100%
rename from libunwindstack/offline_files/signal_fde_x86/stack0.data
rename to libunwindstack/tests/files/offline/signal_fde_x86/stack0.data
Binary files differ
diff --git a/libunwindstack/offline_files/signal_fde_x86/stack1.data b/libunwindstack/tests/files/offline/signal_fde_x86/stack1.data
similarity index 100%
rename from libunwindstack/offline_files/signal_fde_x86/stack1.data
rename to libunwindstack/tests/files/offline/signal_fde_x86/stack1.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/signal_fde_x86_64/libc.so b/libunwindstack/tests/files/offline/signal_fde_x86_64/libc.so
new file mode 100644
index 0000000..cea7336
--- /dev/null
+++ b/libunwindstack/tests/files/offline/signal_fde_x86_64/libc.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/signal_fde_x86_64/libunwindstack_test b/libunwindstack/tests/files/offline/signal_fde_x86_64/libunwindstack_test
new file mode 100644
index 0000000..c48e84e
--- /dev/null
+++ b/libunwindstack/tests/files/offline/signal_fde_x86_64/libunwindstack_test
Binary files differ
diff --git a/libunwindstack/offline_files/signal_fde_x86_64/maps.txt b/libunwindstack/tests/files/offline/signal_fde_x86_64/maps.txt
similarity index 100%
rename from libunwindstack/offline_files/signal_fde_x86_64/maps.txt
rename to libunwindstack/tests/files/offline/signal_fde_x86_64/maps.txt
diff --git a/libunwindstack/offline_files/signal_fde_x86_64/regs.txt b/libunwindstack/tests/files/offline/signal_fde_x86_64/regs.txt
similarity index 100%
rename from libunwindstack/offline_files/signal_fde_x86_64/regs.txt
rename to libunwindstack/tests/files/offline/signal_fde_x86_64/regs.txt
diff --git a/libunwindstack/offline_files/signal_fde_x86_64/stack0.data b/libunwindstack/tests/files/offline/signal_fde_x86_64/stack0.data
similarity index 100%
rename from libunwindstack/offline_files/signal_fde_x86_64/stack0.data
rename to libunwindstack/tests/files/offline/signal_fde_x86_64/stack0.data
Binary files differ
diff --git a/libunwindstack/offline_files/signal_fde_x86_64/stack1.data b/libunwindstack/tests/files/offline/signal_fde_x86_64/stack1.data
similarity index 100%
rename from libunwindstack/offline_files/signal_fde_x86_64/stack1.data
rename to libunwindstack/tests/files/offline/signal_fde_x86_64/stack1.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/signal_load_bias_arm/libc.so b/libunwindstack/tests/files/offline/signal_load_bias_arm/libc.so
new file mode 100644
index 0000000..f046624
--- /dev/null
+++ b/libunwindstack/tests/files/offline/signal_load_bias_arm/libc.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/signal_load_bias_arm/libunwindstack_unit_test b/libunwindstack/tests/files/offline/signal_load_bias_arm/libunwindstack_unit_test
new file mode 100644
index 0000000..f460dd6
--- /dev/null
+++ b/libunwindstack/tests/files/offline/signal_load_bias_arm/libunwindstack_unit_test
Binary files differ
diff --git a/libunwindstack/offline_files/signal_load_bias_arm/maps.txt b/libunwindstack/tests/files/offline/signal_load_bias_arm/maps.txt
similarity index 100%
rename from libunwindstack/offline_files/signal_load_bias_arm/maps.txt
rename to libunwindstack/tests/files/offline/signal_load_bias_arm/maps.txt
diff --git a/libunwindstack/offline_files/signal_load_bias_arm/regs.txt b/libunwindstack/tests/files/offline/signal_load_bias_arm/regs.txt
similarity index 100%
rename from libunwindstack/offline_files/signal_load_bias_arm/regs.txt
rename to libunwindstack/tests/files/offline/signal_load_bias_arm/regs.txt
diff --git a/libunwindstack/offline_files/signal_load_bias_arm/stack0.data b/libunwindstack/tests/files/offline/signal_load_bias_arm/stack0.data
similarity index 100%
rename from libunwindstack/offline_files/signal_load_bias_arm/stack0.data
rename to libunwindstack/tests/files/offline/signal_load_bias_arm/stack0.data
Binary files differ
diff --git a/libunwindstack/offline_files/signal_load_bias_arm/stack1.data b/libunwindstack/tests/files/offline/signal_load_bias_arm/stack1.data
similarity index 100%
rename from libunwindstack/offline_files/signal_load_bias_arm/stack1.data
rename to libunwindstack/tests/files/offline/signal_load_bias_arm/stack1.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/straddle_arm/libbase.so b/libunwindstack/tests/files/offline/straddle_arm/libbase.so
new file mode 100644
index 0000000..d1f16ee
--- /dev/null
+++ b/libunwindstack/tests/files/offline/straddle_arm/libbase.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/straddle_arm/libc.so b/libunwindstack/tests/files/offline/straddle_arm/libc.so
new file mode 100644
index 0000000..4dc19ca
--- /dev/null
+++ b/libunwindstack/tests/files/offline/straddle_arm/libc.so
Binary files differ
diff --git a/libunwindstack/offline_files/straddle_arm/maps.txt b/libunwindstack/tests/files/offline/straddle_arm/maps.txt
similarity index 100%
rename from libunwindstack/offline_files/straddle_arm/maps.txt
rename to libunwindstack/tests/files/offline/straddle_arm/maps.txt
diff --git a/libunwindstack/offline_files/straddle_arm/regs.txt b/libunwindstack/tests/files/offline/straddle_arm/regs.txt
similarity index 100%
rename from libunwindstack/offline_files/straddle_arm/regs.txt
rename to libunwindstack/tests/files/offline/straddle_arm/regs.txt
diff --git a/libunwindstack/offline_files/straddle_arm/stack.data b/libunwindstack/tests/files/offline/straddle_arm/stack.data
similarity index 100%
rename from libunwindstack/offline_files/straddle_arm/stack.data
rename to libunwindstack/tests/files/offline/straddle_arm/stack.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/straddle_arm64/libunwindstack_test b/libunwindstack/tests/files/offline/straddle_arm64/libunwindstack_test
new file mode 100644
index 0000000..092fc3a
--- /dev/null
+++ b/libunwindstack/tests/files/offline/straddle_arm64/libunwindstack_test
Binary files differ
diff --git a/libunwindstack/offline_files/straddle_arm64/maps.txt b/libunwindstack/tests/files/offline/straddle_arm64/maps.txt
similarity index 100%
rename from libunwindstack/offline_files/straddle_arm64/maps.txt
rename to libunwindstack/tests/files/offline/straddle_arm64/maps.txt
diff --git a/libunwindstack/offline_files/straddle_arm64/regs.txt b/libunwindstack/tests/files/offline/straddle_arm64/regs.txt
similarity index 100%
rename from libunwindstack/offline_files/straddle_arm64/regs.txt
rename to libunwindstack/tests/files/offline/straddle_arm64/regs.txt
diff --git a/libunwindstack/offline_files/straddle_arm64/stack.data b/libunwindstack/tests/files/offline/straddle_arm64/stack.data
similarity index 100%
rename from libunwindstack/offline_files/straddle_arm64/stack.data
rename to libunwindstack/tests/files/offline/straddle_arm64/stack.data
Binary files differ
diff --git a/libunwindstack/tests/fuzz/UnwinderComponentCreator.h b/libunwindstack/tests/fuzz/UnwinderComponentCreator.h
index 8486418..fd3499a 100644
--- a/libunwindstack/tests/fuzz/UnwinderComponentCreator.h
+++ b/libunwindstack/tests/fuzz/UnwinderComponentCreator.h
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#pragma once
+#ifndef _LIBUNWINDSTACK_UNWINDERCOMPONENTCREATOR_H
+#define _LIBUNWINDSTACK_UNWINDERCOMPONENTCREATOR_H
 
 #include <elf.h>
 #include <sys/mman.h>
@@ -35,7 +36,7 @@
 #include <unwindstack/RegsX86_64.h>
 
 #include "../ElfFake.h"
-#include "utils/MemoryFake.h"
+#include "../MemoryFake.h"
 
 #include "fuzzer/FuzzedDataProvider.h"
 
@@ -80,3 +81,4 @@
                                                    std::shared_ptr<unwindstack::Memory> memory,
                                                    uint max_libraries, uint max_library_length,
                                                    unwindstack::ArchEnum arch);
+#endif  // _LIBUNWINDSTACK_UNWINDERCOMPONENTCREATOR_H
diff --git a/libunwindstack/tests/fuzz/UnwinderFuzz.cpp b/libunwindstack/tests/fuzz/UnwinderFuzz.cpp
index 41913f1..f926ce7 100644
--- a/libunwindstack/tests/fuzz/UnwinderFuzz.cpp
+++ b/libunwindstack/tests/fuzz/UnwinderFuzz.cpp
@@ -23,9 +23,9 @@
 #include <unwindstack/Memory.h>
 #include <unwindstack/Unwinder.h>
 
+#include "../MemoryFake.h"
 #include "UnwinderComponentCreator.h"
 #include "fuzzer/FuzzedDataProvider.h"
-#include "utils/MemoryFake.h"
 
 namespace unwindstack {
 
diff --git a/libunwindstack/tools/share_common_elfs.sh b/libunwindstack/tools/share_common_elfs.sh
deleted file mode 100755
index d6e79a1..0000000
--- a/libunwindstack/tools/share_common_elfs.sh
+++ /dev/null
@@ -1,119 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2021 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.
-
-### Usage: shares_common_elfs.sh [-m] [-a] <path/to/dump/directory/or/elf>
-###
-### This script is used to eliminate copies of the same ELF file(s) across
-### subdirectories of 'offline_files/' by placing common ELF(s) in
-### 'offline_files/common'. The build id is appended to each ELF name to allow
-### for different versions of the same shared library. Unless -a is used, the
-### path must be a valid ELF file.
-###
-### Options:
-### -m
-###    If the ELF(s) does not currently reside in the 'common' directory, move
-###     the elf to 'common' and rename it.
-### -a
-###    Eliminate copies for all ELFs in a directory. The path specified point
-###    to a directory and NOT an individual ELF file.
-
-usage() {
-  grep '^###' $0 | sed -e 's/^###//'
-  exit 1
-}
-
-update_elf() {
-  local elf_path="$1"
-  local move_if_not_in_common="$2"
-
-  local basename=$(basename "$elf_path")
-  local maps_path=$(dirname "$elf_path")"/maps.txt"
-  local build_id=$(readelf -n "$elf_path" | grep -oP 'Build ID: \K([\w\d]+)')
-  local new_elf_name="${basename}_${build_id}"
-  local common_dir="${ANDROID_BUILD_TOP}/system/unwinding/libunwindstack/offline_files/common/"
-
-  if [[ -f "${common_dir}${new_elf_name}" ]]; then
-    # If the ELF is already found in the common directory, delete the local copy.
-    git rm "$elf_path"
-  elif [[ $move_if_not_in_common == true ]]; then
-    # If the ELF is not found in the common directory and the `move_if_not_common`
-    # flag was set, move the local ELF to the common directory.
-    git mv "$elf_path" "${common_dir}${new_elf_name}"
-  else
-    # The ELF was not found in the common directory so exit this function.
-    return 0
-  fi
-
-  # Replace the name of the elf we just deleted/moved to the relative
-  # path to that ELF in the common directory.
-  local elf_dir_path=$(dirname "$elf_path")
-  local rel_path_to_common=$(realpath --relative-to="$elf_dir_path" "$common_dir")
-  sed -i -e "s/${basename}/${rel_path_to_common}\/${new_elf_name}/g" "$maps_path"
-}
-
-is_an_elf() {
-  if [[ $(head -c 4 $1 | cut -c2-) == "ELF" ]]; then
-    echo true
-  else
-    echo false
-  fi
-}
-
-main () {
-  set -e # abort the script if some error occurs.
-  local move_if_not_in_common=false
-  local update_all_elfs=false
-  while getopts ":hma" arg; do
-    case $arg in
-      m)
-        move_if_not_in_common=true
-        ;;
-      a)
-        update_all_elfs=true
-        ;;
-      h | *)
-        usage
-        ;;
-    esac
-  done
-  path=${@:$OPTIND:1}
-  if [[ -z $path ]]; then
-    usage
-  fi
-
-  if [[ $update_all_elfs == true ]]; then
-    if [[ ! -d $path || "${path: -1}" != "/" ]]; then
-      echo "$path is not a valid path to a directory." >&2
-      usage
-    fi
-    for elf_path in "${path}"*; do
-      if [[ $(is_an_elf $elf_path) == true ]]; then
-        update_elf $elf_path $move_if_not_in_common
-      fi
-    done
-  else
-    if [[ ! -f $path ]]; then
-      echo "$path is not a valid path to a file." >&2
-      usage
-    elif [[ $(is_an_elf $path) == false ]]; then
-      echo "$path is not a valid ELF file." >&2
-    else
-      update_elf $path $move_if_not_in_common
-    fi
-  fi
-}
-
-main "$@"
\ No newline at end of file
diff --git a/libunwindstack/tools/strip.py b/libunwindstack/tools/strip.py
deleted file mode 100755
index bb47de7..0000000
--- a/libunwindstack/tools/strip.py
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2021 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.
-#
-
-import argparse, subprocess, re, os, glob, array, gzip
-
-DESCRIPTION = "This tool reduces ELF size using stripping and compression"
-
-STRIP_SECTIONS = [".text", ".rodata"]
-
-READELF_FORMAT = """
-  \s+(?P<index>[0-9\[\] ]+)
-  \s+(?P<name>[a-z_.]+)
-  \s+(?P<type>[A-Z_]+)
-  \s+(?P<address>[0-9a-f]+)
-  \s+(?P<offset>[0-9a-f]+)
-  \s+(?P<size>[0-9a-f]+)
-"""
-
-def strip(path):
-  proc = subprocess.run(["readelf", "--file-header", "--sections", path],
-                        stdout=subprocess.PIPE, universal_newlines=True)
-  assert(proc.returncode == 0)  # readelf command failed
-  sections = {m["name"] : m for m in re.finditer(READELF_FORMAT, proc.stdout, re.VERBOSE)}
-  for name in STRIP_SECTIONS:
-    if name == ".text" and os.path.basename(path) in ["vdso", "vdso.so", "libc.so"]:
-      continue  # Stripping these libraries breaks signal handler unwinding.
-    section = sections.get(name)
-    if not section:
-      print("Warning: {} not found in {}".format(name, path))
-    if section and section["type"] != "NOBITS":
-      offset, size = int(section["offset"], 16), int(section["size"], 16) & ~1
-      with open(path, "r+b") as f:
-        f.seek(offset)
-        data = array.array('H')  # 16-bit unsigned integer array.
-        data.frombytes(f.read(size))
-        # Preserve top bits for thumb so that we can still determine instruction size.
-        is_thumb = (name == ".text" and re.search("Machine:\s+ARM", proc.stdout))
-        for i in range(len(data)):
-          data[i] = 0xffff if is_thumb and (data[i] & 0xe000) == 0xe000 else 0
-        f.seek(offset)
-        f.write(data.tobytes())
-
-  # gzip-compress the file to take advantage of the zeroed sections.
-  with open(path, 'rb') as src, gzip.open(path + ".gz", 'wb') as dst:
-    dst.write(src.read())
-  os.remove(path)
-
-def main():
-  parser = argparse.ArgumentParser(description=DESCRIPTION)
-  parser.add_argument('target', nargs='+', help="ELF file or whole directory to strip")
-  args = parser.parse_args()
-
-  for path in args.target:
-    if os.path.isdir(path):
-      for path in glob.glob(os.path.join(path, "**/*"), recursive=True):
-        if os.path.isfile(path) and open(path, "rb").read(4) == b"\x7FELF":
-          strip(path)
-    else:
-      strip(path)
-
-if __name__ == '__main__':
-  main()
diff --git a/libunwindstack/tools/unwind_for_offline.cpp b/libunwindstack/tools/unwind_for_offline.cpp
index 4a2bf65..4d3a5f4 100644
--- a/libunwindstack/tools/unwind_for_offline.cpp
+++ b/libunwindstack/tools/unwind_for_offline.cpp
@@ -14,14 +14,20 @@
  * limitations under the License.
  */
 
-#include <cstdio>
 #define _GNU_SOURCE 1
+#include <errno.h>
 #include <inttypes.h>
+#include <signal.h>
+#include <stdint.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include <sys/mman.h>
+#include <sys/ptrace.h>
+#include <sys/types.h>
+#include <unistd.h>
 
-#include <cstdlib>
-#include <filesystem>
+#include <algorithm>
 #include <memory>
 #include <string>
 #include <unordered_map>
@@ -30,21 +36,13 @@
 
 #include <unwindstack/Elf.h>
 #include <unwindstack/JitDebug.h>
-#include <unwindstack/MapInfo.h>
 #include <unwindstack/Maps.h>
 #include <unwindstack/Memory.h>
 #include <unwindstack/Regs.h>
 #include <unwindstack/Unwinder.h>
-#include "utils/ProcessTracer.h"
 
-#include <android-base/file.h>
-#include <android-base/parseint.h>
 #include <android-base/stringprintf.h>
 
-namespace {
-constexpr pid_t kMinPid = 1;
-constexpr int kAllCmdOptionsParsed = -1;
-
 struct map_info_t {
   uint64_t start;
   uint64_t end;
@@ -53,46 +51,26 @@
   std::string name;
 };
 
-int usage(int exit_code) {
-  fprintf(stderr, "USAGE: unwind_for_offline [-t] [-e FILE] [-f[FILE]] <PID>\n\n");
-  fprintf(stderr, "OPTIONS:\n");
-  fprintf(stderr, "-t\n");
-  fprintf(stderr, "       Dump offline snapshot for all threads of <PID>.\n");
-  fprintf(stderr, "-e FILE\n");
-  fprintf(stderr, "       If FILE is a valid ELF file included in /proc/<PID>/maps,\n");
-  fprintf(stderr, "       unwind_for_offline will wait until the current frame (PC)\n");
-  fprintf(stderr, "       lies within the .so file given by FILE. FILE should be\n");
-  fprintf(stderr, "       base name of the path (the component following the final\n");
-  fprintf(stderr, "       '/') rather than the fully qualified path.\n");
-  fprintf(stderr, "-f [FILE]\n");
-  fprintf(stderr, "       Write info (e.g. frames and stack range) logs to a file\n");
-  fprintf(stderr, "       rather than to the stdout/stderr. If FILE is not\n");
-  fprintf(stderr, "       specified, the output file will be named 'output.txt'.\n");
-  return exit_code;
-}
-
-bool EnsureProcInDesiredElf(const std::string& elf_name, unwindstack::ProcessTracer& proc) {
-  if (proc.UsesSharedLibrary(proc.pid(), elf_name)) {
-    printf("Confirmed pid %d does use %s. Waiting for PC to lie within %s...\n", proc.pid(),
-           elf_name.c_str(), elf_name.c_str());
-    if (!proc.StopInDesiredElf(elf_name)) return false;
-  } else {
-    fprintf(stderr, "Process %d does not use library %s.\n", proc.pid(), elf_name.c_str());
+static bool Attach(pid_t pid) {
+  if (ptrace(PTRACE_SEIZE, pid, 0, 0) == -1) {
     return false;
   }
-  return true;
-}
 
-bool CreateAndChangeDumpDir(std::filesystem::path thread_dir, pid_t tid, bool is_main_thread) {
-  std::string dir_name = std::to_string(tid);
-  if (is_main_thread) dir_name += "_main-thread";
-  thread_dir /= dir_name;
-  if (!std::filesystem::create_directory(thread_dir)) {
-    fprintf(stderr, "Failed to create directory for tid %d\n", tid);
+  if (ptrace(PTRACE_INTERRUPT, pid, 0, 0) == -1) {
+    ptrace(PTRACE_DETACH, pid, 0, 0);
     return false;
   }
-  std::filesystem::current_path(thread_dir);
-  return true;
+
+  // Allow at least 1 second to attach properly.
+  for (size_t i = 0; i < 1000; i++) {
+    siginfo_t si;
+    if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
+      return true;
+    }
+    usleep(1000);
+  }
+  printf("%d: Failed to stop.\n", pid);
+  return false;
 }
 
 bool SaveRegs(unwindstack::Regs* regs) {
@@ -108,8 +86,7 @@
   return true;
 }
 
-bool SaveStack(pid_t pid, const std::vector<std::pair<uint64_t, uint64_t>>& stacks,
-               FILE* output_fp) {
+bool SaveStack(pid_t pid, const std::vector<std::pair<uint64_t, uint64_t>>& stacks) {
   for (size_t i = 0; i < stacks.size(); i++) {
     std::string file_name;
     if (stacks.size() != 1) {
@@ -124,11 +101,11 @@
     std::vector<uint8_t> buffer(sp_end - sp_start);
     auto process_memory = unwindstack::Memory::CreateProcessMemory(pid);
     if (!process_memory->Read(sp_start, buffer.data(), buffer.size())) {
-      fprintf(stderr, "Unable to read stack data.\n");
+      printf("Unable to read stack data.\n");
       return false;
     }
 
-    fprintf(output_fp, "\nSaving the stack 0x%" PRIx64 "-0x%" PRIx64 "\n", sp_start, sp_end);
+    printf("Saving the stack 0x%" PRIx64 "-0x%" PRIx64 "\n", sp_start, sp_end);
 
     std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(file_name.c_str(), "w+"), &fclose);
     if (fp == nullptr) {
@@ -138,15 +115,14 @@
 
     size_t bytes = fwrite(&sp_start, 1, sizeof(sp_start), fp.get());
     if (bytes != sizeof(sp_start)) {
-      fprintf(stderr, "Failed to write sp_start data: sizeof(sp_start) %zu, written %zu\n",
-              sizeof(sp_start), bytes);
+      printf("Failed to write sp_start data: sizeof(sp_start) %zu, written %zu\n", sizeof(sp_start),
+             bytes);
       return false;
     }
 
     bytes = fwrite(buffer.data(), 1, buffer.size(), fp.get());
     if (bytes != buffer.size()) {
-      fprintf(stderr, "Failed to write all stack data: stack size %zu, written %zu\n",
-              buffer.size(), bytes);
+      printf("Failed to write all stack data: stack size %zu, written %zu\n", buffer.size(), bytes);
       return false;
     }
   }
@@ -159,8 +135,7 @@
   if (info->name.empty()) {
     cur_name = android::base::StringPrintf("anonymous_%" PRIx64, info->start);
   } else {
-    cur_name = android::base::StringPrintf(
-        "%s_%" PRIx64, android::base::Basename(info->name).c_str(), info->start);
+    cur_name = android::base::StringPrintf("%s_%" PRIx64, basename(info->name.c_str()), info->start);
   }
 
   std::vector<uint8_t> buffer(info->end - info->start);
@@ -168,8 +143,7 @@
   // map, so read all that is readable.
   size_t bytes = memory->Read(info->start, buffer.data(), buffer.size());
   if (bytes == 0) {
-    fprintf(stderr, "Cannot read data from address %" PRIx64 " length %zu\n", info->start,
-            buffer.size());
+    printf("Cannot read data from address %" PRIx64 " length %zu\n", info->start, buffer.size());
     return false;
   }
 
@@ -181,8 +155,7 @@
 
   size_t bytes_written = fwrite(buffer.data(), 1, bytes, output.get());
   if (bytes_written != bytes) {
-    fprintf(stderr, "Failed to write all data to file: bytes read %zu, written %zu\n", bytes,
-            bytes_written);
+    printf("Failed to write all data to file: bytes read %zu, written %zu\n", bytes, bytes_written);
     return false;
   }
 
@@ -193,7 +166,7 @@
 }
 
 bool CopyElfFromFile(map_info_t* info, bool* file_copied) {
-  std::string cur_name = android::base::Basename(info->name);
+  std::string cur_name = basename(info->name.c_str());
   if (*file_copied) {
     info->name = cur_name;
     return true;
@@ -215,8 +188,8 @@
   while ((bytes = fread(buffer.data(), 1, buffer.size(), fp.get())) > 0) {
     size_t bytes_written = fwrite(buffer.data(), 1, bytes, output.get());
     if (bytes_written != bytes) {
-      fprintf(stderr, "Bytes written doesn't match bytes read: read %zu, written %zu\n", bytes,
-              bytes_written);
+      printf("Bytes written doesn't match bytes read: read %zu, written %zu\n", bytes,
+             bytes_written);
       return false;
     }
   }
@@ -252,33 +225,29 @@
     return;
   }
 
-  fprintf(stderr, "Cannot save memory or file for map ");
+  printf("Cannot save memory or file for map ");
   if (!info->name.empty()) {
-    fprintf(stderr, "%s\n", info->name.c_str());
+    printf("%s\n", info->name.c_str());
   } else {
-    fprintf(stderr, "anonymous:%" PRIx64 "\n", info->start);
+    printf("anonymous:%" PRIx64 "\n", info->start);
   }
 }
 
-bool SaveData(pid_t tid, const std::filesystem::path& cwd, bool is_main_thread, FILE* output_fp) {
-  fprintf(output_fp, "-------------------- tid = %d %s--------------------\n", tid,
-          is_main_thread ? "(main thread) " : "--------------");
-  unwindstack::Regs* regs = unwindstack::Regs::RemoteGet(tid);
+int SaveData(pid_t pid) {
+  unwindstack::Regs* regs = unwindstack::Regs::RemoteGet(pid);
   if (regs == nullptr) {
-    fprintf(stderr, "Unable to get remote reg data.\n");
-    return false;
+    printf("Unable to get remote reg data.\n");
+    return 1;
   }
 
-  if (!CreateAndChangeDumpDir(cwd, tid, is_main_thread)) return false;
-
   // Save the current state of the registers.
   if (!SaveRegs(regs)) {
-    return false;
+    return 1;
   }
 
   // Do an unwind so we know how much of the stack to save, and what
   // elf files are involved.
-  unwindstack::UnwinderFromPid unwinder(1024, tid);
+  unwindstack::UnwinderFromPid unwinder(1024, pid);
   unwinder.SetRegs(regs);
   uint64_t sp = regs->sp();
   unwinder.Unwind();
@@ -287,7 +256,7 @@
   std::vector<std::pair<uint64_t, uint64_t>> stacks;
   unwindstack::Maps* maps = unwinder.GetMaps();
   uint64_t sp_map_start = 0;
-  auto map_info = maps->Find(sp);
+  unwindstack::MapInfo* map_info = maps->Find(sp);
   if (map_info != nullptr) {
     stacks.emplace_back(std::make_pair(sp, map_info->end()));
     sp_map_start = map_info->start();
@@ -300,34 +269,35 @@
       sp_map_start = map_info->start();
     }
 
-    if (maps_by_start.count(frame.map_info->start()) == 0) {
+    if (maps_by_start.count(frame.map_start) == 0) {
+      map_info = maps->Find(frame.map_start);
       if (map_info == nullptr) {
         continue;
       }
 
-      auto info = FillInAndGetMapInfo(maps_by_start, map_info.get());
+      auto info = FillInAndGetMapInfo(maps_by_start, map_info);
       bool file_copied = false;
       SaveMapInformation(unwinder.GetProcessMemory(), info, &file_copied);
 
       // If you are using a a linker that creates two maps (one read-only, one
       // read-executable), it's necessary to capture the previous map
       // information if needed.
-      auto prev_map = map_info->prev_map();
+      unwindstack::MapInfo* prev_map = map_info->prev_map();
       if (prev_map != nullptr && map_info->offset() != 0 && prev_map->offset() == 0 &&
           prev_map->flags() == PROT_READ && map_info->name() == prev_map->name() &&
           maps_by_start.count(prev_map->start()) == 0) {
-        info = FillInAndGetMapInfo(maps_by_start, prev_map.get());
+        info = FillInAndGetMapInfo(maps_by_start, prev_map);
         SaveMapInformation(unwinder.GetProcessMemory(), info, &file_copied);
       }
     }
   }
 
   for (size_t i = 0; i < unwinder.NumFrames(); i++) {
-    fprintf(output_fp, "%s\n", unwinder.FormatFrame(i).c_str());
+    printf("%s\n", unwinder.FormatFrame(i).c_str());
   }
 
-  if (!SaveStack(tid, stacks, output_fp)) {
-    return false;
+  if (!SaveStack(pid, stacks)) {
+    return 1;
   }
 
   std::vector<std::pair<uint64_t, map_info_t>> sorted_maps(maps_by_start.begin(),
@@ -335,8 +305,8 @@
   std::sort(sorted_maps.begin(), sorted_maps.end(),
             [](auto& a, auto& b) { return a.first < b.first; });
 
-  std::unique_ptr<FILE, decltype(&fclose)> map_fp(fopen("maps.txt", "w+"), &fclose);
-  if (map_fp == nullptr) {
+  std::unique_ptr<FILE, decltype(&fclose)> fp(fopen("maps.txt", "w+"), &fclose);
+  if (fp == nullptr) {
     perror("Failed to create maps.txt");
     return false;
   }
@@ -353,89 +323,32 @@
     if (map.flags & PROT_EXEC) {
       perms[2] = 'x';
     }
-    fprintf(map_fp.get(), "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " 00:00 0", map.start, map.end,
-            perms, map.offset);
+    fprintf(fp.get(), "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " 00:00 0", map.start, map.end, perms,
+            map.offset);
     if (!map.name.empty()) {
-      fprintf(map_fp.get(), "   %s", map.name.c_str());
+      fprintf(fp.get(), "   %s", map.name.c_str());
     }
-    fprintf(map_fp.get(), "\n");
+    fprintf(fp.get(), "\n");
   }
 
-  fprintf(output_fp, "------------------------------------------------------------------\n");
-  return true;
+  return 0;
 }
-}  // namespace
 
 int main(int argc, char** argv) {
-  if (argc < 2) return usage(EXIT_FAILURE);
-
-  bool dump_threads = false;
-  std::string elf_name;
-  std::unique_ptr<FILE, decltype(&fclose)> output_fp(nullptr, &fclose);
-  int opt;
-  while ((opt = getopt(argc, argv, ":te:f::")) != kAllCmdOptionsParsed) {
-    switch (opt) {
-      case 't': {
-        dump_threads = true;
-        break;
-      }
-      case 'e': {
-        elf_name = optarg;
-        if (elf_name == "-f") {
-          fprintf(stderr, "Missing argument for option e.\n");
-          return usage(EXIT_FAILURE);
-        }
-        break;
-      }
-      case 'f': {
-        const std::string& output_filename = optarg != nullptr ? optarg : "output.txt";
-        if (optind == argc - 2) {
-          fprintf(stderr, "Ensure there is no space between '-f' and the filename provided.\n");
-          return usage(EXIT_FAILURE);
-        }
-        output_fp.reset(fopen(output_filename.c_str(), "a"));
-        break;
-      }
-      case '?': {
-        if (isprint(optopt))
-          fprintf(stderr, "Unknown option `-%c'.\n", optopt);
-        else
-          fprintf(stderr, "Unknown option character `\\x%x'.\n", optopt);
-        return usage(EXIT_FAILURE);
-      }
-      case ':': {
-        fprintf(stderr, "Missing arg for option %c.\n", optopt);
-        return usage(EXIT_FAILURE);
-      }
-      default: {
-        return usage(EXIT_FAILURE);
-      }
-    }
-  }
-  if (optind != argc - 1) return usage(EXIT_FAILURE);
-
-  pid_t pid;
-  if (!android::base::ParseInt(argv[optind], &pid, kMinPid, std::numeric_limits<pid_t>::max()))
-    return usage(EXIT_FAILURE);
-
-  unwindstack::ProcessTracer proc(pid, dump_threads);
-  if (!proc.Stop()) return EXIT_FAILURE;
-  if (!elf_name.empty()) {
-    if (!EnsureProcInDesiredElf(elf_name, proc)) return EXIT_FAILURE;
-  }
-  if (!output_fp) output_fp.reset(stdout);
-  std::filesystem::path cwd = std::filesystem::current_path();
-
-  if (!proc.Attach(proc.pid())) return EXIT_FAILURE;
-  if (!SaveData(proc.pid(), cwd, /*is_main_thread=*/proc.IsTracingThreads(), output_fp.get()))
-    return EXIT_FAILURE;
-  if (!proc.Detach(proc.pid())) return EXIT_FAILURE;
-  for (const pid_t& tid : proc.tids()) {
-    if (!proc.Attach(tid)) return EXIT_FAILURE;
-    if (!SaveData(tid, cwd, /*is_main_thread=*/false, output_fp.get())) return EXIT_FAILURE;
-    if (!proc.Detach(tid)) return EXIT_FAILURE;
+  if (argc != 2) {
+    printf("Usage: unwind_for_offline <PID>\n");
+    return 1;
   }
 
-  printf("\nSuccess!\n");
-  return EXIT_SUCCESS;
+  pid_t pid = atoi(argv[1]);
+  if (!Attach(pid)) {
+    printf("Failed to attach to pid %d: %s\n", pid, strerror(errno));
+    return 1;
+  }
+
+  int return_code = SaveData(pid);
+
+  ptrace(PTRACE_DETACH, pid, 0, 0);
+
+  return return_code;
 }
diff --git a/libunwindstack/tools/unwind_info.cpp b/libunwindstack/tools/unwind_info.cpp
index adc93b4..65b65aa 100644
--- a/libunwindstack/tools/unwind_info.cpp
+++ b/libunwindstack/tools/unwind_info.cpp
@@ -103,6 +103,9 @@
 }
 
 int GetElfInfo(const char* file, uint64_t offset) {
+  // Send all log messages to stdout.
+  log_to_stdout(true);
+
   Elf elf(Memory::CreateFileMemory(file, offset).release());
   if (!elf.Init() || !elf.valid()) {
     printf("%s is not a valid elf file.\n", file);
diff --git a/libunwindstack/tools/unwind_reg_info.cpp b/libunwindstack/tools/unwind_reg_info.cpp
index da34dc8..3675f96 100644
--- a/libunwindstack/tools/unwind_reg_info.cpp
+++ b/libunwindstack/tools/unwind_reg_info.cpp
@@ -154,6 +154,7 @@
 
   ArmExidx arm(nullptr, interface->memory(), nullptr);
 
+  log_to_stdout(true);
   arm.set_log(ARM_LOG_BY_REG);
   arm.set_log_skip_execution(true);
   arm.set_log_indent(1);
diff --git a/libunwindstack/tools/unwind_symbols.cpp b/libunwindstack/tools/unwind_symbols.cpp
index a56ed5f..2506fc1 100644
--- a/libunwindstack/tools/unwind_symbols.cpp
+++ b/libunwindstack/tools/unwind_symbols.cpp
@@ -56,6 +56,9 @@
     }
   }
 
+  // Send all log messages to stdout.
+  unwindstack::log_to_stdout(true);
+
   unwindstack::Elf elf(unwindstack::Memory::CreateFileMemory(argv[1], 0).release());
   if (!elf.Init() || !elf.valid()) {
     printf("%s is not a valid elf file.\n", argv[1]);
diff --git a/libunwindstack/utils/DwarfSectionImplFake.h b/libunwindstack/utils/DwarfSectionImplFake.h
deleted file mode 100644
index 54ed995..0000000
--- a/libunwindstack/utils/DwarfSectionImplFake.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2021 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 <unwindstack/DwarfSection.h>
-#include <unwindstack/Memory.h>
-
-namespace unwindstack {
-
-template <typename TypeParam>
-class DwarfSectionImplFake : public DwarfSectionImpl<TypeParam> {
- public:
-  DwarfSectionImplFake(Memory* memory) : DwarfSectionImpl<TypeParam>(memory) {}
-  virtual ~DwarfSectionImplFake() = default;
-
-  bool Init(uint64_t, uint64_t, int64_t) override { return false; }
-
-  void GetFdes(std::vector<const DwarfFde*>*) override {}
-
-  const DwarfFde* GetFdeFromPc(uint64_t) override { return nullptr; }
-
-  uint64_t GetCieOffsetFromFde32(uint32_t) { return 0; }
-
-  uint64_t GetCieOffsetFromFde64(uint64_t) { return 0; }
-
-  uint64_t AdjustPcFromFde(uint64_t) override { return 0; }
-
-  void FakeSetCachedCieLocRegs(uint64_t offset, const DwarfLocations& loc_regs) {
-    this->cie_loc_regs_[offset] = loc_regs;
-  }
-  void FakeClearError() { this->last_error_.code = DWARF_ERROR_NONE; }
-};
-
-}  // namespace unwindstack
diff --git a/libunwindstack/utils/OfflineUnwindUtils.cpp b/libunwindstack/utils/OfflineUnwindUtils.cpp
deleted file mode 100644
index 8cc544d..0000000
--- a/libunwindstack/utils/OfflineUnwindUtils.cpp
+++ /dev/null
@@ -1,511 +0,0 @@
-/*
- * Copyright (C) 2021 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 <err.h>
-#include <errno.h>
-#include <inttypes.h>
-#include <string.h>
-
-#include <cstddef>
-#include <filesystem>
-#include <fstream>
-#include <iostream>
-#include <memory>
-#include <regex>
-#include <sstream>
-#include <string>
-#include <tuple>
-#include <utility>
-#include <vector>
-
-#include <android-base/file.h>
-#include <android-base/strings.h>
-#include <zlib.h>
-
-#include <unwindstack/Arch.h>
-#include <unwindstack/JitDebug.h>
-#include <unwindstack/MachineArm.h>
-#include <unwindstack/MachineArm64.h>
-#include <unwindstack/MachineX86.h>
-#include <unwindstack/MachineX86_64.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Regs.h>
-#include <unwindstack/RegsArm.h>
-#include <unwindstack/RegsArm64.h>
-#include <unwindstack/RegsX86.h>
-#include <unwindstack/RegsX86_64.h>
-#include <unwindstack/Unwinder.h>
-
-#include "Check.h"
-#include "MemoryOffline.h"
-#include "utils/MemoryFake.h"
-
-#include "OfflineUnwindUtils.h"
-
-namespace unwindstack {
-
-void DecompressFiles(const std::string& directory) {
-  namespace fs = std::filesystem;
-  for (const auto& file : fs::recursive_directory_iterator(directory)) {
-    fs::path src_path = file.path();
-    if (src_path.extension() == ".gz") {
-      fs::path dst_path = fs::path(src_path).replace_extension();  // Remove .gz extension.
-      if (!fs::exists(dst_path) || fs::last_write_time(src_path) > fs::last_write_time(dst_path)) {
-        gzFile src = gzopen(src_path.c_str(), "rb");
-        CHECK(src != nullptr);
-        fs::path tmp_path = fs::path(src_path).replace_extension("." + std::to_string(getpid()));
-        std::ofstream tmp(tmp_path);  // Temporary file to avoid races between unit tests.
-        char buffer[1024];
-        int size;
-        while ((size = gzread(src, buffer, sizeof(buffer))) > 0) {
-          tmp.write(buffer, size);
-        }
-        tmp.close();
-        gzclose(src);
-        fs::rename(tmp_path, dst_path);
-      }
-    }
-  }
-}
-
-void CreateLinks(const std::string& directory) {
-  namespace fs = std::filesystem;
-  for (const auto& file : fs::recursive_directory_iterator(directory)) {
-    fs::path src_path = file.path();
-    if (fs::is_regular_file(src_path) && src_path.filename() == "links.txt") {
-      std::string contents;
-      if (!android::base::ReadFileToString(src_path.c_str(), &contents)) {
-        errx(1, "Unable to read file: %s", src_path.c_str());
-      }
-      fs::path parent_path = src_path.parent_path();
-      std::vector<std::string> lines(android::base::Split(contents, "\n"));
-      for (auto line : lines) {
-        std::string trimmed_line(android::base::Trim(line));
-        if (trimmed_line.empty()) {
-          continue;
-        }
-
-        std::vector<std::string> values(android::base::Split(trimmed_line, " "));
-        if (values.size() != 2) {
-          errx(1, "Invalid line in %s: line %s", src_path.c_str(), line.c_str());
-        }
-
-        // Create the symlink if it doesn't already exist.
-        fs::path target(parent_path);
-        target /= fs::path(values[0]);
-        fs::path source(parent_path);
-        source /= fs::path(values[1]);
-        if (!fs::exists(source)) {
-          // Ignore any errors, if this is running at the same time
-          // in multiple processes, then this might fail.
-          std::error_code ec;
-          fs::create_symlink(target, source, ec);
-        }
-      }
-    }
-  }
-}
-
-std::string GetOfflineFilesDirectory() {
-  std::string path = android::base::GetExecutableDirectory() + "/offline_files/";
-  DecompressFiles(path);
-  CreateLinks(path);
-  return path;
-}
-
-std::string DumpFrames(const Unwinder& unwinder) {
-  std::string str;
-  for (size_t i = 0; i < unwinder.NumFrames(); i++) {
-    str += unwinder.FormatFrame(i) + "\n";
-  }
-  return str;
-}
-
-bool AddMemory(std::string file_name, MemoryOfflineParts* parts, std::string* error_msg) {
-  MemoryOffline* memory = new MemoryOffline;
-  if (!memory->Init(file_name.c_str(), 0)) {
-    std::stringstream err_stream;
-    err_stream << "Failed to add stack '" << file_name << "' to stack memory.";
-    *error_msg = err_stream.str();
-    return false;
-  }
-  parts->Add(memory);
-
-  return true;
-}
-
-Regs* OfflineUnwindUtils::GetRegs(const std::string& initial_sample_name) const {
-  const std::string& sample_name = GetAdjustedSampleName(initial_sample_name);
-  std::string error_msg;
-  if (!IsValidUnwindSample(sample_name, &error_msg)) {
-    std::cerr << error_msg;
-    return nullptr;
-  }
-  return samples_.at(sample_name).regs.get();
-}
-
-Maps* OfflineUnwindUtils::GetMaps(const std::string& initial_sample_name) const {
-  const std::string& sample_name = GetAdjustedSampleName(initial_sample_name);
-  std::string error_msg;
-  if (!IsValidUnwindSample(sample_name, &error_msg)) {
-    std::cerr << error_msg;
-    return nullptr;
-  }
-  return samples_.at(sample_name).maps.get();
-}
-
-std::shared_ptr<Memory> OfflineUnwindUtils::GetProcessMemory(
-    const std::string& initial_sample_name) const {
-  const std::string& sample_name = GetAdjustedSampleName(initial_sample_name);
-  std::string error_msg;
-  if (!IsValidUnwindSample(sample_name, &error_msg)) {
-    std::cerr << error_msg;
-    return nullptr;
-  }
-  return samples_.at(sample_name).process_memory;
-}
-
-JitDebug* OfflineUnwindUtils::GetJitDebug(const std::string& initial_sample_name) const {
-  const std::string& sample_name = GetAdjustedSampleName(initial_sample_name);
-  std::string error_msg;
-  if (!IsValidUnwindSample(sample_name, &error_msg)) {
-    std::cerr << error_msg;
-    return nullptr;
-  }
-  return samples_.at(sample_name).jit_debug.get();
-}
-
-const std::string* OfflineUnwindUtils::GetOfflineFilesPath(
-    const std::string& initial_sample_name) const {
-  const std::string& sample_name = GetAdjustedSampleName(initial_sample_name);
-  std::string error_msg;
-  if (!IsValidUnwindSample(sample_name, &error_msg)) {
-    std::cerr << error_msg;
-    return nullptr;
-  }
-  return &samples_.at(sample_name).offline_files_path;
-}
-
-const std::string* OfflineUnwindUtils::GetFrameInfoFilepath(
-    const std::string& initial_sample_name) const {
-  const std::string& sample_name = GetAdjustedSampleName(initial_sample_name);
-  std::string error_msg;
-  if (!IsValidUnwindSample(sample_name, &error_msg)) {
-    std::cerr << error_msg;
-    return nullptr;
-  }
-  return &samples_.at(sample_name).frame_info_filepath;
-}
-
-bool OfflineUnwindUtils::Init(const std::vector<UnwindSampleInfo>& sample_infos,
-                              std::string* error_msg) {
-  // Save the current path so the caller can switch back to it later.
-  cwd_ = std::filesystem::current_path();
-
-  // Fill in the unwind samples.
-  std::stringstream err_stream;
-  for (const auto& sample_info : sample_infos) {
-    std::string offline_files_full_path =
-        GetOfflineFilesDirectory() + sample_info.offline_files_dir;
-    if (!std::filesystem::exists(offline_files_full_path)) {
-      err_stream << "Offline files directory '" << offline_files_full_path << "' does not exist.";
-      *error_msg = err_stream.str();
-      return false;
-    }
-    std::string frame_info_filepath = offline_files_full_path + sample_info.frame_info_filename;
-
-    std::string map_buffer;
-    if (!android::base::ReadFileToString((offline_files_full_path + "maps.txt"), &map_buffer)) {
-      err_stream << "Failed to read from '" << offline_files_full_path << "maps.txt' into memory.";
-      *error_msg = err_stream.str();
-      return false;
-    }
-
-    // CreateMaps, CreatRegs, and Create*Memory may need to be called later by the client. So we
-    // need to create the sample now in case the flags are set to call these methods in Init.
-    const std::string& sample_name = sample_info.offline_files_dir;
-    samples_.emplace(sample_name, (UnwindSample){
-                                      std::move(offline_files_full_path),
-                                      std::move(frame_info_filepath), std::move(map_buffer),
-                                      nullptr,                         // regs
-                                      nullptr,                         // maps
-                                      std::make_shared<MemoryFake>(),  // process_memory
-                                      nullptr,                         // jit_debug
-                                  });
-    UnwindSample& sample = samples_.at(sample_name);
-
-    if (sample_info.create_maps) {
-      if (!CreateMaps(error_msg, sample_name)) return false;
-    }
-    if (!CreateRegs(sample_info.arch, error_msg, sample_name)) return false;
-
-    switch (sample_info.memory_flag) {
-      case ProcessMemoryFlag::kNone: {
-        if (!CreateProcessMemory(error_msg, sample_name)) return false;
-        break;
-      }
-      case ProcessMemoryFlag::kIncludeJitMemory: {
-        if (!CreateProcessMemory(error_msg, sample_name)) return false;
-        sample.jit_debug = CreateJitDebug(sample.regs->Arch(), sample.process_memory);
-        break;
-      }
-      case ProcessMemoryFlag::kNoMemory: {
-        break;
-      }
-      default: {
-        std::stringstream err_stream;
-        err_stream << "Unknown memory type for sample '" << sample_name << "'.";
-        *error_msg = err_stream.str();
-        return false;
-      }
-    }
-  }
-  initted_ = true;
-  return true;
-}
-
-bool OfflineUnwindUtils::Init(const UnwindSampleInfo& sample_info, std::string* error_msg) {
-  if (Init(std::vector<UnwindSampleInfo>{sample_info}, error_msg)) {
-    if (!ChangeToSampleDirectory(error_msg)) return false;
-    return true;
-  }
-  return false;
-}
-
-bool OfflineUnwindUtils::ChangeToSampleDirectory(std::string* error_msg,
-                                                 const std::string& initial_sample_name) const {
-  if (!initted_) {
-    *error_msg =
-        "Cannot change to sample directory because OfflineUnwindUtils::Init has not been called.";
-    return false;
-  }
-  const std::string& sample_name = GetAdjustedSampleName(initial_sample_name);
-  if (!IsValidUnwindSample(sample_name, error_msg)) return false;
-
-  std::filesystem::current_path(std::filesystem::path(samples_.at(sample_name).offline_files_path));
-  return true;
-}
-
-bool OfflineUnwindUtils::GetExpectedNumFrames(size_t* expected_num_frames, std::string* error_msg,
-                                              const std::string& initial_sample_name) const {
-  if (!initted_) {
-    *error_msg =
-        "Cannot get expected number of frames of a sample because OfflineUnwindUtils::Init has not "
-        "been called.";
-    return false;
-  }
-  const std::string& sample_name = GetAdjustedSampleName(initial_sample_name);
-  if (!IsValidUnwindSample(sample_name, error_msg)) return false;
-
-  const std::string& sample_frames_path = samples_.at(sample_name).frame_info_filepath;
-  if (!std::filesystem::exists(sample_frames_path)) {
-    std::stringstream err_stream;
-    err_stream << "Offline files directory '" << sample_frames_path << "' does not exist.";
-    *error_msg = err_stream.str();
-    return false;
-  }
-
-  std::ifstream in(sample_frames_path);
-  in.unsetf(std::ios_base::skipws);  // Ensure that we do not skip newlines.
-  *expected_num_frames =
-      std::count(std::istream_iterator<char>(in), std::istream_iterator<char>(), '\n');
-
-  return true;
-}
-
-bool OfflineUnwindUtils::CreateMaps(std::string* error_msg,
-                                    const std::string& initial_sample_name) {
-  const std::string& sample_name = GetAdjustedSampleName(initial_sample_name);
-  if (!IsValidUnwindSample(sample_name, error_msg)) return false;
-  UnwindSample& sample = samples_.at(sample_name);
-
-  sample.maps.reset(new BufferMaps(sample.map_buffer.c_str()));
-  if (!sample.maps->Parse()) {
-    *error_msg = "Failed to parse offline maps.";
-    return false;
-  }
-  return true;
-}
-
-bool OfflineUnwindUtils::CreateProcessMemory(std::string* error_msg,
-                                             const std::string& initial_sample_name) {
-  const std::string& sample_name = GetAdjustedSampleName(initial_sample_name);
-  if (!IsValidUnwindSample(sample_name, error_msg)) return false;
-  UnwindSample& sample = samples_.at(sample_name);
-
-  // Construct process memory from all descriptor, stack, entry, and jit files
-  auto memory = std::make_unique<MemoryOfflineParts>();
-  bool data_files_found = false;
-  for (const auto& file : std::filesystem::directory_iterator(sample.offline_files_path)) {
-    std::string filename = file.path().string();
-    if (std::regex_match(filename,
-                         std::regex("^(.+)\\/(descriptor|stack|entry|jit)(\\d*)\\.data$"))) {
-      data_files_found = true;
-      if (!AddMemory(filename, memory.get(), error_msg)) return false;
-    }
-  }
-  if (!data_files_found) {
-    *error_msg = "No memory (stack, JIT, etc.) data files found.";
-    return false;
-  }
-
-  sample.process_memory.reset(memory.release());
-  return true;
-}
-
-namespace {
-template <typename AddressType>
-bool ReadRegs(RegsImpl<AddressType>* regs,
-              const std::unordered_map<std::string, uint32_t>& name_to_reg, std::string* error_msg,
-              const std::string& offline_files_path) {
-  std::stringstream err_stream;
-  FILE* fp = fopen((offline_files_path + "regs.txt").c_str(), "r");
-  if (fp == nullptr) {
-    err_stream << "Error opening file '" << offline_files_path << "regs.txt': " << strerror(errno);
-    *error_msg = err_stream.str();
-    return false;
-  }
-
-  while (!feof(fp)) {
-    uint64_t value;
-    char reg_name[100];
-    if (fscanf(fp, "%s %" SCNx64 "\n", reg_name, &value) != 2) {
-      err_stream << "Failed to read in register name/values from '" << offline_files_path
-                 << "regs.txt'.";
-      *error_msg = err_stream.str();
-      return false;
-    }
-    std::string name(reg_name);
-    if (!name.empty()) {
-      // Remove the : from the end.
-      name.resize(name.size() - 1);
-    }
-    auto entry = name_to_reg.find(name);
-    if (entry == name_to_reg.end()) {
-      err_stream << "Unknown register named " << reg_name;
-      *error_msg = err_stream.str();
-      return false;
-    }
-    (*regs)[entry->second] = value;
-  }
-  fclose(fp);
-  return true;
-}
-}  // namespace
-
-bool OfflineUnwindUtils::CreateRegs(ArchEnum arch, std::string* error_msg,
-                                    const std::string& initial_sample_name) {
-  const std::string& sample_name = GetAdjustedSampleName(initial_sample_name);
-  if (!IsValidUnwindSample(sample_name, error_msg)) return false;
-  auto& regs = samples_.at(sample_name).regs;
-  const auto& offline_files_path = samples_.at(sample_name).offline_files_path;
-
-  switch (arch) {
-    case ARCH_ARM: {
-      RegsArm* regs_impl = new RegsArm;
-      regs.reset(regs_impl);
-      if (!ReadRegs<uint32_t>(regs_impl, arm_regs_, error_msg, offline_files_path)) return false;
-      break;
-    }
-    case ARCH_ARM64: {
-      RegsArm64* regs_impl = new RegsArm64;
-      regs.reset(regs_impl);
-      if (!ReadRegs<uint64_t>(regs_impl, arm64_regs_, error_msg, offline_files_path)) return false;
-      break;
-    }
-    case ARCH_X86: {
-      RegsX86* regs_impl = new RegsX86;
-      regs.reset(regs_impl);
-      if (!ReadRegs<uint32_t>(regs_impl, x86_regs_, error_msg, offline_files_path)) return false;
-      break;
-    }
-    case ARCH_X86_64: {
-      RegsX86_64* regs_impl = new RegsX86_64;
-      regs.reset(regs_impl);
-      if (!ReadRegs<uint64_t>(regs_impl, x86_64_regs_, error_msg, offline_files_path)) return false;
-      break;
-    }
-    default:
-      *error_msg = "Unknown architechture " + std::to_string(arch);
-      return false;
-  }
-
-  return true;
-}
-
-const std::string& OfflineUnwindUtils::GetAdjustedSampleName(
-    const std::string& initial_sample_name) const {
-  // Only return the first entry in the sample map if this is the single unwind use case.
-  // Otherwise return the inputted sample name so we can check if that is a valid sample name.
-  if (initial_sample_name == kSingleSample && samples_.size() == 1) {
-    return samples_.begin()->first;
-  }
-  return initial_sample_name;
-}
-
-bool OfflineUnwindUtils::IsValidUnwindSample(const std::string& sample_name,
-                                             std::string* error_msg) const {
-  if (samples_.find(sample_name) == samples_.end()) {
-    std::stringstream err_stream;
-    err_stream << "Invalid sample name (offline file directory) '" << sample_name << "'.";
-    if (sample_name == kSingleSample) {
-      err_stream << " An explicit sample name must be provided for the multiple unwind use case "
-                    "of OfflineUnwindUtils (i.e. should not use the default sample name).";
-    }
-    *error_msg = err_stream.str();
-    return false;
-  }
-  return true;
-}
-
-std::unordered_map<std::string, uint32_t> OfflineUnwindUtils::arm_regs_ = {
-    {"r0", ARM_REG_R0},  {"r1", ARM_REG_R1}, {"r2", ARM_REG_R2},   {"r3", ARM_REG_R3},
-    {"r4", ARM_REG_R4},  {"r5", ARM_REG_R5}, {"r6", ARM_REG_R6},   {"r7", ARM_REG_R7},
-    {"r8", ARM_REG_R8},  {"r9", ARM_REG_R9}, {"r10", ARM_REG_R10}, {"r11", ARM_REG_R11},
-    {"ip", ARM_REG_R12}, {"sp", ARM_REG_SP}, {"lr", ARM_REG_LR},   {"pc", ARM_REG_PC},
-};
-
-std::unordered_map<std::string, uint32_t> OfflineUnwindUtils::arm64_regs_ = {
-    {"x0", ARM64_REG_R0},      {"x1", ARM64_REG_R1},   {"x2", ARM64_REG_R2},
-    {"x3", ARM64_REG_R3},      {"x4", ARM64_REG_R4},   {"x5", ARM64_REG_R5},
-    {"x6", ARM64_REG_R6},      {"x7", ARM64_REG_R7},   {"x8", ARM64_REG_R8},
-    {"x9", ARM64_REG_R9},      {"x10", ARM64_REG_R10}, {"x11", ARM64_REG_R11},
-    {"x12", ARM64_REG_R12},    {"x13", ARM64_REG_R13}, {"x14", ARM64_REG_R14},
-    {"x15", ARM64_REG_R15},    {"x16", ARM64_REG_R16}, {"x17", ARM64_REG_R17},
-    {"x18", ARM64_REG_R18},    {"x19", ARM64_REG_R19}, {"x20", ARM64_REG_R20},
-    {"x21", ARM64_REG_R21},    {"x22", ARM64_REG_R22}, {"x23", ARM64_REG_R23},
-    {"x24", ARM64_REG_R24},    {"x25", ARM64_REG_R25}, {"x26", ARM64_REG_R26},
-    {"x27", ARM64_REG_R27},    {"x28", ARM64_REG_R28}, {"x29", ARM64_REG_R29},
-    {"sp", ARM64_REG_SP},      {"lr", ARM64_REG_LR},   {"pc", ARM64_REG_PC},
-    {"pst", ARM64_REG_PSTATE},
-};
-
-std::unordered_map<std::string, uint32_t> OfflineUnwindUtils::x86_regs_ = {
-    {"eax", X86_REG_EAX}, {"ebx", X86_REG_EBX}, {"ecx", X86_REG_ECX},
-    {"edx", X86_REG_EDX}, {"ebp", X86_REG_EBP}, {"edi", X86_REG_EDI},
-    {"esi", X86_REG_ESI}, {"esp", X86_REG_ESP}, {"eip", X86_REG_EIP},
-};
-
-std::unordered_map<std::string, uint32_t> OfflineUnwindUtils::x86_64_regs_ = {
-    {"rax", X86_64_REG_RAX}, {"rbx", X86_64_REG_RBX}, {"rcx", X86_64_REG_RCX},
-    {"rdx", X86_64_REG_RDX}, {"r8", X86_64_REG_R8},   {"r9", X86_64_REG_R9},
-    {"r10", X86_64_REG_R10}, {"r11", X86_64_REG_R11}, {"r12", X86_64_REG_R12},
-    {"r13", X86_64_REG_R13}, {"r14", X86_64_REG_R14}, {"r15", X86_64_REG_R15},
-    {"rdi", X86_64_REG_RDI}, {"rsi", X86_64_REG_RSI}, {"rbp", X86_64_REG_RBP},
-    {"rsp", X86_64_REG_RSP}, {"rip", X86_64_REG_RIP},
-};
-
-}  // namespace unwindstack
diff --git a/libunwindstack/utils/OfflineUnwindUtils.h b/libunwindstack/utils/OfflineUnwindUtils.h
deleted file mode 100644
index df89c68..0000000
--- a/libunwindstack/utils/OfflineUnwindUtils.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2021 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 <cstddef>
-#include <filesystem>
-#include <memory>
-#include <string>
-#include <unordered_map>
-#include <vector>
-
-#include <unwindstack/Arch.h>
-#include <unwindstack/JitDebug.h>
-#include <unwindstack/Memory.h>
-#include <unwindstack/Regs.h>
-#include <unwindstack/Unwinder.h>
-
-#include "MemoryOffline.h"
-
-// These utils facilitate performing offline unwinds. Offline unwinds are similar to local
-// unwinds, however, instead of pausing the process to gather the current execution state
-// (stack, registers, Elf / maps), a snapshot of the process is taken. This snapshot data
-// is used at a later time (when the process is no longer running) to unwind the process
-// at the point the snapshot was taken.
-//
-// Offline unwinds simulate one of the most common use cases of the Unwinder. These types of
-// unwinds are performed by two of the largest clients of libunwindstack: Perfetto and Simpleperf.
-//
-// Offline unwind snapshots were obtained using the following approach:
-// 1. (Optional) Flash a virtual or physical device with the internal Android build rather than
-//    an AOSP build to have additional and more complex apps to unwind.
-// 2. Determine the pid of the app/process you want to unwind. View all of the running
-//    processes with `adb shell ps -A`  or `adb shell ps -A | grep name.of.process` if you know
-//    the (package) name of the process.
-// 3. (Optional) If you want to ensure that an application is compiled or that the compiled code is
-//    erased (e.g. want interpreter / JIT frames in the unwind), run `adb shell cmd package compile`
-//    based on the options provided here
-//    (https://source.android.com/devices/tech/dalvik/jit-compiler).
-// 4. Ensure the process is running and in a "desired state" when you execute
-//    `adb shell /bin/unwind_for_offline [options] pid`. For example:
-//   a. If you are unwinding the bluetooth process and want the unwind to contain the bluetooth
-//      ELF (libbluetooth.so), try to pair with a device over bluetooth. Make sure you use the
-//      `-t` and `-e` flags.
-//   b. You will likely see more variation in the thread snapshots (especially if you are trying
-//      to capture JIT/interpreter frames) if you ensure the app is not-idle when you run
-//      `unwind_for_offline`. E.g. immediately run unwind_for_offline after searching for a
-//      landmark in Google Maps.
-// 5. Grab the desired snapshot directories with `adb pull ...`
-// 6. (Optional) Reduce the size of copied ELFs:
-//   a. Use tools/share_common_elfs.sh to eliminate copies of the same ELF files that are already
-//      used by other 'libunwindstack/offline_files/' subdirectories.
-//   b. Strip ELFs of all sections that are not needed for unwinding and/or symbolization.
-//   c. Compress/Zip the entire snapshot directory.
-// 7. Use the path to the snapshot directory(ies) for the `offline_files_dirs` parameter to
-//    `OfflineUnwindUtils::Init`.
-//
-// See b/192012600 for additional information regarding Offline Unwind Benchmarks.
-namespace unwindstack {
-
-void DecompressFiles(const std::string& directory);
-
-std::string GetOfflineFilesDirectory();
-
-std::string DumpFrames(const Unwinder& unwinder);
-
-bool AddMemory(std::string file_name, MemoryOfflineParts* parts, std::string* error_msg);
-
-// Enum that indicates how `UnwindSample::process_memory` of `OfflineUnwindUtils::samples_`
-// should be initialized.
-enum class ProcessMemoryFlag {
-  kNone = 0,
-  kIncludeJitMemory,
-  kNoMemory,
-};
-
-// A `UnwindSampleInfo` object contains the information necessary for OfflineUnwindUtils
-// to initialize a single offline unwind sample.
-struct UnwindSampleInfo {
-  std::string offline_files_dir;
-  ArchEnum arch;
-  std::string frame_info_filename = "output.txt";
-  ProcessMemoryFlag memory_flag = ProcessMemoryFlag::kNone;
-  bool create_maps = true;
-};
-
-// The `OfflineUnwindUtils` class helps perform offline unwinds by handling the creation of the
-// `Regs`, `Maps`, and `Memory` objects needed for unwinding.
-//
-// `OfflineUnwindUtils` assists in two unwind use cases:
-// 1. Single unwinds: unwind from a single sample/snapshot (one set of offline unwind files).
-// 2. Consecutive/Multiple unwinds: unwind from a multiple samples/snapshots.
-//
-// `Init` contains two overloads for these two unwind cases. Other than `Init` and
-// `ReturnToCurrentWorkingDirectory`, the remainder of the public API includes a `sample_name`
-// parameter to indicate which sample/snapshot we are referencing. Specifying this value is
-// REQUIRED for the multiple unwind use case. However, in the single use case, the caller has
-// the choice of either providing the sample name or using the default value.
-class OfflineUnwindUtils {
- public:
-  // If the sample name passed to Get* is an invalid sample, nullptr is returned.
-  Regs* GetRegs(const std::string& sample_name = kSingleSample) const;
-
-  Maps* GetMaps(const std::string& sample_name = kSingleSample) const;
-
-  std::shared_ptr<Memory> GetProcessMemory(const std::string& sample_name = kSingleSample) const;
-
-  JitDebug* GetJitDebug(const std::string& sample_name = kSingleSample) const;
-
-  const std::string* GetOfflineFilesPath(const std::string& sample_name = kSingleSample) const;
-
-  const std::string* GetFrameInfoFilepath(const std::string& sample_name = kSingleSample) const;
-
-  // Note: If the caller sets elements of `set_maps` to false or `memory_types` to
-  //  kNoMemory, they are responsible for calling `CreateMaps` or `CreateProcessMemory` before
-  //  expecting `GetMaps` or `GetProcessMemory` to return anything but nullptr.
-  bool Init(const std::vector<UnwindSampleInfo>& sample_infos, std::string* error_msg);
-
-  bool Init(const UnwindSampleInfo& sample_info, std::string* error_msg);
-
-  // This must be called explicitly for the multiple unwind use case sometime before
-  // Unwinder::Unwind is called. This is required because the Unwinder must init each
-  // ELF object with a MemoryFileAtOffset memory object. Because the maps.txt provides a relative
-  // path to the ELF files, we must be in the directory of the maps.txt when unwinding.
-  //
-  // Note: Init performs the check that this sample directory exists. If Init fails,
-  // `initted_` is not set to true and this function will return false.
-  bool ChangeToSampleDirectory(std::string* error_msg,
-                               const std::string& initial_sample_name = kSingleSample) const;
-
-  void ReturnToCurrentWorkingDirectory() {
-    if (!cwd_.empty()) std::filesystem::current_path(cwd_);
-  }
-
-  bool GetExpectedNumFrames(size_t* expected_num_frames, std::string* error_msg,
-                            const std::string& sample_name = kSingleSample) const;
-
-  bool CreateMaps(std::string* error_msg, const std::string& sample_name = kSingleSample);
-
-  bool CreateProcessMemory(std::string* error_msg, const std::string& sample_name = kSingleSample);
-
-  static constexpr char kSingleSample[] = "";
-
- private:
-  // An `UnwindSample` encapsulates the information necessary to perform an offline unwind for a
-  // single offline sample/snapshot.
-  struct UnwindSample {
-    std::string offline_files_path;
-    std::string frame_info_filepath;
-    std::string map_buffer;
-    std::unique_ptr<Regs> regs;
-    std::unique_ptr<Maps> maps;
-    std::shared_ptr<Memory> process_memory;
-    std::unique_ptr<JitDebug> jit_debug;
-  };
-
-  bool CreateRegs(ArchEnum arch, std::string* error_msg,
-                  const std::string& sample_name = kSingleSample);
-
-  // Needed to support using the default value `kSingleSample` for the single unwind use case.
-  const std::string& GetAdjustedSampleName(const std::string& sample_name) const;
-
-  bool IsValidUnwindSample(const std::string& sample_name, std::string* error_msg) const;
-
-  static std::unordered_map<std::string, uint32_t> arm_regs_;
-  static std::unordered_map<std::string, uint32_t> arm64_regs_;
-  static std::unordered_map<std::string, uint32_t> x86_regs_;
-  static std::unordered_map<std::string, uint32_t> x86_64_regs_;
-
-  std::string cwd_;
-  std::unordered_map<std::string, UnwindSample> samples_;
-  bool initted_ = false;
-};
-
-}  // namespace unwindstack
diff --git a/libunwindstack/utils/PidUtils.cpp b/libunwindstack/utils/PidUtils.cpp
deleted file mode 100644
index 4268225..0000000
--- a/libunwindstack/utils/PidUtils.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2022 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 <errno.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <sys/ptrace.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "PidUtils.h"
-
-namespace unwindstack {
-
-static bool Exited(pid_t pid) {
-  int status;
-  pid_t wait_pid = waitpid(pid, &status, WNOHANG);
-  if (wait_pid != pid) {
-    return false;
-  }
-
-  if (WIFEXITED(status)) {
-    fprintf(stderr, "%d died: Process exited with code %d\n", pid, WEXITSTATUS(status));
-  } else if (WIFSIGNALED(status)) {
-    fprintf(stderr, "%d died: Process exited due to signal %d\n", pid, WTERMSIG(status));
-  } else {
-    fprintf(stderr, "%d died: Process finished for unknown reason\n", pid);
-  }
-  return true;
-}
-
-bool Quiesce(pid_t pid) {
-  siginfo_t si;
-  // Wait for up to 10 seconds.
-  for (time_t start_time = time(nullptr); time(nullptr) - start_time < 10;) {
-    if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
-      return true;
-    }
-    if (errno != ESRCH) {
-      if (errno == EINVAL) {
-        // The process is in group-stop state, so try and kick the
-        // process out of that state.
-        if (ptrace(PTRACE_LISTEN, pid, 0, 0) == -1) {
-          // Cannot recover from this, so just pretend it worked and see
-          // if we can unwind.
-          return true;
-        }
-      } else {
-        perror("ptrace getsiginfo failed");
-        return false;
-      }
-    }
-    usleep(5000);
-  }
-  fprintf(stderr, "Did not quiesce in 10 seconds\n");
-  return false;
-}
-
-bool Attach(pid_t pid) {
-  // Wait up to 45 seconds to attach.
-  for (time_t start_time = time(nullptr); time(nullptr) - start_time < 45;) {
-    if (ptrace(PTRACE_ATTACH, pid, 0, 0) == 0) {
-      break;
-    }
-    if (errno != ESRCH) {
-      perror("Failed to attach");
-      return false;
-    }
-    usleep(5000);
-  }
-
-  if (Quiesce(pid)) {
-    return true;
-  }
-
-  if (ptrace(PTRACE_DETACH, pid, 0, 0) == -1) {
-    perror("Failed to detach");
-  }
-  return false;
-}
-
-bool Detach(pid_t pid) {
-  if (ptrace(PTRACE_DETACH, pid, 0, 0) == -1) {
-    perror("ptrace detach failed");
-    return false;
-  }
-  return true;
-}
-
-bool RunWhenQuiesced(pid_t pid, bool leave_attached, std::function<PidRunEnum()> fn) {
-  // Wait up to 120 seconds to run the fn.
-  PidRunEnum status = PID_RUN_KEEP_GOING;
-  for (time_t start_time = time(nullptr);
-       time(nullptr) - start_time < 120 && status == PID_RUN_KEEP_GOING;) {
-    if (Attach(pid)) {
-      status = fn();
-      if (status == PID_RUN_PASS && leave_attached) {
-        return true;
-      }
-
-      if (!Detach(pid)) {
-        return false;
-      }
-    } else if (Exited(pid)) {
-      return false;
-    }
-    usleep(5000);
-  }
-  if (status == PID_RUN_KEEP_GOING) {
-    fprintf(stderr, "Timed out waiting for pid %d to be ready\n", pid);
-  }
-  return status == PID_RUN_PASS;
-}
-
-}  // namespace unwindstack
diff --git a/libunwindstack/utils/PidUtils.h b/libunwindstack/utils/PidUtils.h
deleted file mode 100644
index 5f67204..0000000
--- a/libunwindstack/utils/PidUtils.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2022 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 <sys/types.h>
-
-#include <functional>
-
-namespace unwindstack {
-
-enum PidRunEnum : uint8_t {
-  PID_RUN_KEEP_GOING,
-  PID_RUN_PASS,
-  PID_RUN_FAIL,
-};
-
-bool Quiesce(pid_t pid);
-
-bool Attach(pid_t pid);
-
-bool Detach(pid_t pid);
-
-bool RunWhenQuiesced(pid_t pid, bool leave_attached, std::function<PidRunEnum()> fn);
-
-}  // namespace unwindstack
diff --git a/libunwindstack/utils/ProcessTracer.cpp b/libunwindstack/utils/ProcessTracer.cpp
deleted file mode 100644
index 7f60ca0..0000000
--- a/libunwindstack/utils/ProcessTracer.cpp
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (C) 2021 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 <errno.h>
-#include <fcntl.h>
-#include <sys/ptrace.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <algorithm>
-#include <array>
-#include <atomic>
-#include <csignal>
-#include <cstddef>
-#include <cstdio>
-#include <cstring>
-#include <memory>
-#include <regex>
-#include <string>
-#include <unordered_set>
-#include <vector>
-
-#include <unwindstack/MapInfo.h>
-#include <unwindstack/Maps.h>
-#include <unwindstack/Regs.h>
-#include <unwindstack/Unwinder.h>
-
-#include <android-base/file.h>
-#include <android-base/stringprintf.h>
-#include <procinfo/process.h>
-
-#include "ProcessTracer.h"
-
-namespace unwindstack {
-
-ProcessTracer::ProcessTracer(pid_t pid, bool is_tracing_threads)
-    : pid_(pid), is_tracing_threads_(is_tracing_threads) {
-  if (is_tracing_threads_) is_tracing_threads_ = InitProcessTids();
-}
-
-bool ProcessTracer::InitProcessTids() {
-  std::string error_msg;
-  if (!android::procinfo::GetProcessTids(pid_, &tids_, &error_msg)) {
-    fprintf(stderr,
-            "Failed to get process tids: %s. Reverting to tracing the "
-            "main thread only.\n",
-            error_msg.c_str());
-    return false;
-  }
-  if (tids_.erase(pid_) != 1) {
-    fprintf(stderr,
-            "Failed to erase the main thread from the thread id set. "
-            "Reverting to tracing the main thread only.\n");
-    return false;
-  }
-  return true;
-}
-
-ProcessTracer::~ProcessTracer() {
-  if (cur_attached_tid_ != kNoThreadAttached) Detach(cur_attached_tid_);
-  if (!is_running_) Resume();
-}
-
-bool ProcessTracer::Stop() {
-  if (kill(pid_, SIGSTOP) == kKillFailed) {
-    fprintf(stderr, "Failed to send stop signal to pid %d: %s\n", pid_, strerror(errno));
-    return false;
-  }
-  usleep(1000);  // 1 ms. Without this sleep, any attempt to resume right away may fail.
-
-  is_running_ = false;
-  return true;
-}
-
-bool ProcessTracer::Resume() {
-  if (kill(pid_, SIGCONT) == kKillFailed) {
-    fprintf(stderr, "Failed to send continue signal to pid %d: %s\n", pid_, strerror(errno));
-    return false;
-  }
-  usleep(1000);  // 1 ms. Without this sleep, any attempt to stop right away may fail.
-
-  is_running_ = true;
-  return true;
-}
-
-bool ProcessTracer::Detach(pid_t tid) {
-  if (tid != pid_ && tids_.find(tid) == tids_.end()) {
-    fprintf(stderr, "Tid %d does not belong to proc %d.\n", tid, pid_);
-    return false;
-  }
-
-  if (cur_attached_tid_ == kNoThreadAttached) {
-    fprintf(stderr, "Cannot detach because no thread is currently attached.\n");
-    return false;
-  }
-  if (is_running_ && !Stop()) return false;
-
-  if (ptrace(PTRACE_DETACH, tid, nullptr, nullptr) == kPtraceFailed) {
-    fprintf(stderr, "Failed to detach from tid %d: %s\n", tid, strerror(errno));
-    return false;
-  }
-
-  cur_attached_tid_ = kNoThreadAttached;
-  return true;
-}
-
-bool ProcessTracer::Attach(pid_t tid) {
-  if (tid != pid_ && tids_.find(tid) == tids_.end()) {
-    fprintf(stderr, "Tid %d does not belong to proc %d.\n", tid, pid_);
-    return false;
-  }
-
-  if (is_running_) Stop();
-  if (cur_attached_tid_ != kNoThreadAttached) {
-    fprintf(stderr, "Cannot attatch to tid %d. Already attached to tid %d.\n", tid,
-            cur_attached_tid_);
-    return false;
-  }
-
-  if (ptrace(PTRACE_ATTACH, tid, nullptr, nullptr) == kPtraceFailed) {
-    fprintf(stderr, "Failed to attached to tid %d: %s\n", tid, strerror(errno));
-    return false;
-  }
-  int status;
-  if (waitpid(tid, &status, 0) == kWaitpidFailed) {
-    fprintf(stderr, "Failed to stop tid %d: %s\n", tid, strerror(errno));
-    return false;
-  }
-
-  cur_attached_tid_ = tid;
-  return true;
-}
-
-bool ProcessTracer::StopInDesiredElf(const std::string& elf_name) {
-  signal(SIGINT, [](int) { keepWaitingForPcInElf = false; });
-  bool pc_in_desired_elf = true;
-  do {
-    if (!Attach(pid_)) return false;
-    pc_in_desired_elf = ProcIsInDesiredElf(pid_, elf_name);
-    if (!Detach(pid_)) return false;
-
-    if (!pc_in_desired_elf) {
-      for (pid_t tid : tids_) {
-        if (!Attach(tid)) return false;
-        pc_in_desired_elf = ProcIsInDesiredElf(tid, elf_name);
-        if (!Detach(tid)) return false;
-        if (pc_in_desired_elf) break;
-      }
-    }
-
-    // If the process is not in the desired ELF, resume it for a short time, then check again.
-    if (!pc_in_desired_elf) {
-      Resume();
-      usleep(1000);  // 1 ms
-      Stop();
-    }
-  } while (!pc_in_desired_elf && keepWaitingForPcInElf);
-
-  if (!pc_in_desired_elf) {
-    fprintf(stderr, "\nExited while waiting for pid %d to enter %s.\n", pid_, elf_name.c_str());
-    return false;
-  }
-  return true;
-}
-
-bool ProcessTracer::UsesSharedLibrary(pid_t pid, const std::string& desired_elf_name) {
-  std::unique_ptr<Maps> maps = std::make_unique<RemoteMaps>(pid);
-  if (!maps->Parse()) {
-    fprintf(stderr, "Could not parse maps for pid %d.\n", pid);
-    return false;
-  }
-  for (const auto& map : *maps) {
-    if (android::base::Basename(map->name()).c_str() == desired_elf_name) return true;
-  }
-  return false;
-}
-
-bool ProcessTracer::ProcIsInDesiredElf(pid_t pid, const std::string& desired_elf_name) {
-  std::unique_ptr<Regs> regs(Regs::RemoteGet(pid));
-  if (regs == nullptr) {
-    fprintf(stderr, "Unable to get remote reg data.\n");
-    return false;
-  }
-  UnwinderFromPid unwinder(1024, pid);
-  unwinder.SetRegs(regs.get());
-  if (!unwinder.Init()) {
-    fprintf(stderr, "Unable to intitialize unwinder.\n");
-    return false;
-  }
-  Maps* maps = unwinder.GetMaps();
-  auto map_info = maps->Find(regs->pc());
-  if (map_info == nullptr) {
-    regs->fallback_pc();
-    map_info = maps->Find(regs->pc());
-    if (map_info == nullptr) {
-      return false;
-    }
-  }
-
-  const std::string& current_elf_name = android::base::Basename(map_info->name()).c_str();
-  bool in_desired_elf = current_elf_name == desired_elf_name;
-  if (in_desired_elf) printf("pid %d is in %s! Unwinding...\n\n", pid, desired_elf_name.c_str());
-  return in_desired_elf;
-}
-}  // namespace unwindstack
diff --git a/libunwindstack/utils/ProcessTracer.h b/libunwindstack/utils/ProcessTracer.h
deleted file mode 100644
index 1809cb2..0000000
--- a/libunwindstack/utils/ProcessTracer.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2021 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 <sys/types.h>
-
-#include <set>
-#include <string>
-#include <unordered_set>
-
-namespace unwindstack {
-
-// ProcessTracer objects abstract operations for tracing a process and its threads with ptrace(2).
-class ProcessTracer final {
- public:
-  ProcessTracer(pid_t pid, bool is_tracing_threads);
-
-  ~ProcessTracer();
-
-  // ProcessTracer instances are moveable but not copyable because they manage the
-  // state of a process.
-  ProcessTracer(const ProcessTracer&) = delete;
-  ProcessTracer& operator=(const ProcessTracer&) = delete;
-  ProcessTracer(ProcessTracer&&) = default;
-  ProcessTracer& operator=(ProcessTracer&&) = default;
-
-  pid_t pid() const { return pid_; }
-
-  const std::set<pid_t>& tids() const { return tids_; }
-
-  bool IsTracingThreads() const { return is_tracing_threads_; }
-
-  bool Stop();
-
-  bool Resume();
-
-  // Like ptrace, it is required to call ProcessTracer::Detach before calling ProcessTracer::Attach
-  // on a different thread of the same process.
-  bool Detach(pid_t tid);
-
-  bool Attach(pid_t tid);
-
-  // This method for determining whether a thread is currently executing instructions from a
-  // desired ELF is not the most time efficient solution. In the interest of simplicity and
-  // limiting memory usage, the UnwinderFromPid, Regs, and Maps instances constructed for
-  // in each check (loop iteration) are thrown away.
-  //
-  // A SIGINT signal handler is set up to allow the user to gracefully exit with CTRL-C if they
-  // decide that they no longer want to wait for the process to enter the desired ELF.
-  bool StopInDesiredElf(const std::string& elf_name);
-
-  // `desired_elf_name` should match the filename of the path (the component following the final
-  // '/') corresponding to the shared library as indicated in /proc/pid/maps.
-  static bool UsesSharedLibrary(pid_t pid, const std::string& desired_elf_name);
-
- private:
-  static bool ProcIsInDesiredElf(pid_t tid, const std::string& desired_elf_name);
-
-  // Initialize tids_ such that the main thread is the first element and
-  // the remaining tids are in order from least to greatest.
-  bool InitProcessTids();
-
-  static constexpr pid_t kNoThreadAttached = -2;
-  static constexpr pid_t kKillFailed = -1;
-  static constexpr pid_t kPtraceFailed = -1;
-  static constexpr pid_t kWaitpidFailed = -1;
-  static inline std::atomic_bool keepWaitingForPcInElf = true;
-  const pid_t pid_;
-  bool is_tracing_threads_ = false;
-  std::set<pid_t> tids_;
-  bool is_running_ = true;
-  pid_t cur_attached_tid_ = kNoThreadAttached;
-};
-}  // namespace unwindstack
diff --git a/libunwindstack/utils/tests/ProcessTracerTest.cpp b/libunwindstack/utils/tests/ProcessTracerTest.cpp
deleted file mode 100644
index eae55bb..0000000
--- a/libunwindstack/utils/tests/ProcessTracerTest.cpp
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright (C) 2021 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 <dlfcn.h>
-#include <gtest/gtest.h>
-#include <sys/ptrace.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <algorithm>
-#include <array>
-#include <atomic>
-#include <cerrno>
-#include <csignal>
-#include <cstddef>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <filesystem>
-#include <memory>
-#include <string>
-#include <system_error>
-#include <thread>
-
-#include <android-base/file.h>
-#include <procinfo/process.h>
-
-#include "OfflineUnwindUtils.h"
-#include "ProcessTracer.h"
-#include "tests/TestUtils.h"
-
-namespace unwindstack {
-namespace {
-
-class ProcessTracerTest : public ::testing::TestWithParam<bool> {
- protected:
-  enum class BoolOrTimeout {
-    kSuccess = 0,
-    kFail,
-    kTimeout,
-  };
-
-  // Setup a child process that has a few threads that simply busy wait.
-  void SetUp() override {
-    // Setup signal handlers for child to let parent know that it is ready and for parent
-    // to kill the child.
-    child_is_ready_ = false;
-    ASSERT_NE(SIG_ERR, signal(kChildIsReadySignal, [](int) { child_is_ready_ = true; }))
-        << "Failed to set up signal handler for kChildIsReadySignal: " << strerror(errno);
-    child_keep_running_ = true;
-    ASSERT_NE(SIG_ERR, signal(kStopChildSignal, [](int) { child_keep_running_ = false; }))
-        << "Failed to set up signal handler for kStopChildSignal: " << strerror(errno);
-
-    pid_t parent_pid = getpid();
-    child_pid_ = fork();
-    if (child_pid_ == static_cast<pid_t>(-1)) FAIL() << "SetUp: fork() failed: " << strerror(errno);
-    if (child_pid_ == 0) {
-      ASSERT_NO_FATAL_FAILURE(ChildProcSpin(parent_pid));
-    }
-
-    // Make sure the child process has set up its threads before running the test.
-    sigset_t signal_mask, old_mask;
-    sigemptyset(&signal_mask);
-    sigaddset(&signal_mask, kChildIsReadySignal);
-    sigprocmask(SIG_BLOCK, &signal_mask, &old_mask);
-    while (!child_is_ready_) sigsuspend(&old_mask);
-    sigprocmask(SIG_UNBLOCK, &signal_mask, NULL);
-  }
-
-  void TearDown() override {
-    // Send signal to join threads and exit.
-    if (-1 == kill(child_pid_, kStopChildSignal)) {
-      std::cerr << "TearDown: kill sending kStopChildSignal failed: " << strerror(errno) << ".\n";
-      kill(child_pid_, SIGKILL);
-    }
-  }
-
-  void ChildProcSpin(pid_t parent_pid) {
-    // Busy wait in a dlopened local library so we can reliably test (across different
-    // architecture) if a process is within a desired ELF.
-    std::unique_ptr<void, decltype(&dlclose)> test_lib_handle(GetTestLibHandle(), &dlclose);
-    ASSERT_TRUE(test_lib_handle);
-    int (*busy_wait_func)() = reinterpret_cast<int (*)()>(dlsym(test_lib_handle.get(), "BusyWait"));
-    ASSERT_NE(nullptr, busy_wait_func);
-
-    std::array<std::thread, kNumThreads> threads;
-    std::array<std::atomic_bool, kNumThreads> threads_are_ready{false, false, false, false, false};
-    for (size_t i = 0; i < kNumThreads; ++i) {
-      threads.at(i) = std::thread([&threads_are_ready, i, &busy_wait_func]() {
-        while (child_keep_running_) {
-          DoNotOptimize(busy_wait_func());
-          threads_are_ready.at(i) = true;
-        }
-      });
-    }
-    // Wait until all threads have entered the loop before informing parent child is
-    // ready to avoid a race.
-    while (!std::all_of(threads_are_ready.begin(), threads_are_ready.end(),
-                        [&](const std::atomic_bool& el) { return el == true; })) {
-      usleep(100);
-    }
-    ASSERT_NE(-1, kill(parent_pid, kChildIsReadySignal) == -1)
-        << "TearDown: kill sending kChildIsReady failed: " << strerror(errno) << ".\n";
-    for (size_t i = 0; i < kNumThreads; ++i) {
-      threads.at(i).join();
-    }
-    exit(EXIT_SUCCESS);
-  }
-
-  BoolOrTimeout StopInDesiredElfTimeout(ProcessTracer& proc, const std::string& elf_name,
-                                        size_t timeout_sec = 2) {
-    static BoolOrTimeout result = BoolOrTimeout::kSuccess;
-    if (SIG_ERR == signal(SIGALRM, [](int) {
-          result = BoolOrTimeout::kTimeout;
-          // StopInDesiredElf contains signal handler for SIGINT mainly so that we could stop the
-          // search easily when running unwind_for_offline and we can use it here too.
-          kill(getpid(), SIGINT);
-        })) {
-      std::cerr << "Failed to set up signal handler for SIGALRM: " << strerror(errno) << ".\n";
-      exit(EXIT_FAILURE);
-    }
-    alarm(timeout_sec);
-    if (proc.StopInDesiredElf(elf_name)) {
-      result = BoolOrTimeout::kSuccess;
-    } else if (result != BoolOrTimeout::kTimeout) {
-      result = BoolOrTimeout::kFail;
-    }
-    alarm(0);
-    return result;
-  }
-
-  static constexpr size_t kNumThreads = 5;
-  static constexpr int kChildIsReadySignal = SIGUSR1;
-  static constexpr int kStopChildSignal = SIGUSR2;
-  static inline std::atomic_bool child_is_ready_ = false;
-  static inline std::atomic_bool child_keep_running_ = true;
-  pid_t child_pid_;
-};
-
-static void VerifyState(pid_t tid, bool running) {
-  while (true) {
-    android::procinfo::ProcessInfo proc_info;
-    ASSERT_TRUE(GetProcessInfo(tid, &proc_info));
-    if (running) {
-      if (proc_info.state == android::procinfo::kProcessStateRunning ||
-          proc_info.state == android::procinfo::kProcessStateSleeping) {
-        break;
-      }
-    } else if (proc_info.state == android::procinfo::kProcessStateStopped) {
-      break;
-    }
-    usleep(1000);
-  }
-}
-
-static void VerifyState(ProcessTracer& proc, bool running) {
-  // Verify that the main thread and all threads are in the expected state.
-  VerifyState(proc.pid(), running);
-  if (::testing::Test::HasFatalFailure()) return;
-  for (const pid_t& tid : proc.tids()) {
-    VerifyState(tid, running);
-    if (::testing::Test::HasFatalFailure()) return;
-  }
-}
-
-TEST_P(ProcessTracerTest, stop_and_resume) {
-  ProcessTracer proc(child_pid_, /*is_tracing_threads*/ GetParam());
-
-  ASSERT_TRUE(proc.Stop());
-  VerifyState(proc, /*running*/ false);
-  if (::testing::Test::HasFatalFailure()) return;
-
-  ASSERT_TRUE(proc.Resume());
-  VerifyState(proc, /*running*/ true);
-  if (::testing::Test::HasFatalFailure()) return;
-}
-
-TEST_P(ProcessTracerTest, attach_and_detach) {
-  ProcessTracer proc(child_pid_, /*is_tracing_threads*/ GetParam());
-
-  ASSERT_TRUE(proc.Attach(child_pid_));
-  // Attaching to the same pid should result in failure and errno indicating that we cannot trace
-  // the priocess because it is already being traced after the call to Attach().
-  ASSERT_EQ(-1, ptrace(PTRACE_ATTACH, child_pid_, nullptr, nullptr));
-  ASSERT_EQ(EPERM, errno);
-  ASSERT_TRUE(proc.Detach(child_pid_));
-  for (const pid_t& tid : proc.tids()) {
-    ASSERT_TRUE(proc.Attach(tid));
-    ASSERT_EQ(-1, ptrace(PTRACE_ATTACH, tid, nullptr, nullptr));
-    ASSERT_EQ(EPERM, errno);
-    ASSERT_TRUE(proc.Detach(tid));
-  }
-}
-
-TEST_P(ProcessTracerTest, consecutive_attach_fail) {
-  if (!GetParam()) GTEST_SKIP();
-  ProcessTracer proc(child_pid_, /*is_tracing_threads*/ GetParam());
-
-  bool is_first_thread = true;
-  for (const pid_t& tid : proc.tids()) {
-    if (is_first_thread) {
-      ASSERT_TRUE(proc.Attach(tid));
-      is_first_thread = false;
-    } else {
-      ASSERT_FALSE(proc.Attach(tid));
-    }
-  }
-}
-
-TEST_P(ProcessTracerTest, trace_invalid_tid) {
-  if (GetParam()) GTEST_SKIP();
-  ProcessTracer proc(child_pid_, /*is_tracing_threads*/ GetParam());
-  ASSERT_FALSE(proc.Attach(getpid()));
-  ASSERT_FALSE(proc.Detach(getpid()));
-}
-
-TEST_P(ProcessTracerTest, detach_with_no_attached) {
-  if (GetParam()) GTEST_SKIP();
-  ProcessTracer proc(child_pid_, /*is_tracing_threads*/ GetParam());
-  ASSERT_FALSE(proc.Detach(child_pid_));
-}
-
-TEST_P(ProcessTracerTest, uses_shared_library) {
-  ProcessTracer proc(child_pid_, /*is_tracing_threads*/ GetParam());
-
-  std::string elf_name = "libunwindstack_local.so";
-  ASSERT_TRUE(proc.UsesSharedLibrary(child_pid_, elf_name));
-  for (const pid_t& tid : proc.tids()) {
-    ASSERT_TRUE(proc.UsesSharedLibrary(tid, elf_name));
-  }
-}
-
-TEST_P(ProcessTracerTest, does_not_use_shared_library) {
-  ProcessTracer proc(child_pid_, /*is_tracing_threads*/ GetParam());
-
-  std::string elf_name = "libfake.so";
-  ASSERT_FALSE(proc.UsesSharedLibrary(child_pid_, elf_name));
-  for (const pid_t& tid : proc.tids()) {
-    ASSERT_FALSE(proc.UsesSharedLibrary(tid, elf_name));
-  }
-}
-
-TEST_P(ProcessTracerTest, stop_in_elf_we_use) {
-  // Skip the run with is_tracing_threads=false because main thread only uses
-  // the threading library.
-  if (!GetParam()) GTEST_SKIP();
-  ProcessTracer proc(child_pid_, /*is_tracing_threads*/ GetParam());
-  std::string elf_name = "libunwindstack_local.so";
-
-  EXPECT_EQ(BoolOrTimeout::kSuccess, StopInDesiredElfTimeout(proc, elf_name));
-}
-
-TEST_P(ProcessTracerTest, timeout_when_try_to_stop_in_elf_we_do_not_use) {
-  ProcessTracer proc(child_pid_, /*is_tracing_threads*/ GetParam());
-  std::string elf_name = "libfake.so";
-
-  EXPECT_EQ(BoolOrTimeout::kTimeout, StopInDesiredElfTimeout(proc, elf_name));
-}
-
-INSTANTIATE_TEST_CASE_P(IsTracingThreads, ProcessTracerTest, testing::Values(false, true));
-
-}  // namespace
-}  // namespace unwindstack