Check for data races when reading JIT/DEX entries.

Update the entries only when the list is modified by the runtime.

Check that the list wasn't concurrently modified when being read.

Bug: 124287208
Test: libunwindstack_test
Test: art/test.py -b --host -r -t 137-cfi
Change-Id: I87ba70322053a01b3d5be1fdf6310e1dc21bb084
diff --git a/libunwindstack/tests/DexFileTest.cpp b/libunwindstack/tests/DexFileTest.cpp
index 0149a42..df7b31d 100644
--- a/libunwindstack/tests/DexFileTest.cpp
+++ b/libunwindstack/tests/DexFileTest.cpp
@@ -177,11 +177,11 @@
 
   std::string method;
   uint64_t method_offset;
-  ASSERT_TRUE(dex_file->GetMethodInformation(0x102, &method, &method_offset));
+  ASSERT_TRUE(dex_file->GetFunctionName(0x4102, &method, &method_offset));
   EXPECT_EQ("Main.<init>", method);
   EXPECT_EQ(2U, method_offset);
 
-  ASSERT_TRUE(dex_file->GetMethodInformation(0x118, &method, &method_offset));
+  ASSERT_TRUE(dex_file->GetFunctionName(0x4118, &method, &method_offset));
   EXPECT_EQ("Main.main", method);
   EXPECT_EQ(0U, method_offset);
 }
@@ -195,9 +195,9 @@
 
   std::string method;
   uint64_t method_offset;
-  EXPECT_FALSE(dex_file->GetMethodInformation(0x100000, &method, &method_offset));
+  EXPECT_FALSE(dex_file->GetFunctionName(0x100000, &method, &method_offset));
 
-  EXPECT_FALSE(dex_file->GetMethodInformation(0x98, &method, &method_offset));
+  EXPECT_FALSE(dex_file->GetFunctionName(0x98, &method, &method_offset));
 }
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/DexFilesTest.cpp b/libunwindstack/tests/DexFilesTest.cpp
index 1ea9e5c..655dcc8 100644
--- a/libunwindstack/tests/DexFilesTest.cpp
+++ b/libunwindstack/tests/DexFilesTest.cpp
@@ -22,8 +22,8 @@
 
 #include <gtest/gtest.h>
 
-#include <unwindstack/DexFiles.h>
 #include <unwindstack/Elf.h>
+#include <unwindstack/JitDebug.h>
 #include <unwindstack/MapInfo.h>
 #include <unwindstack/Maps.h>
 #include <unwindstack/Memory.h>
@@ -32,6 +32,10 @@
 #include "ElfFake.h"
 #include "MemoryFake.h"
 
+#if !defined(NO_LIBDEXFILE_SUPPORT)
+#include <DexFile.h>
+#endif
+
 namespace unwindstack {
 
 class DexFilesTest : public ::testing::Test {
@@ -48,8 +52,7 @@
   }
 
   void Init(ArchEnum arch) {
-    dex_files_.reset(new DexFiles(process_memory_));
-    dex_files_->SetArch(arch);
+    dex_files_ = JitDebug<DexFile>::Create(arch, process_memory_);
 
     maps_.reset(
         new BufferMaps("1000-4000 ---s 00000000 00:00 0 /fake/elf\n"
@@ -86,10 +89,11 @@
     Init(ARCH_ARM);
   }
 
-  void WriteDescriptor32(uint64_t addr, uint32_t head);
-  void WriteDescriptor64(uint64_t addr, uint64_t head);
-  void WriteEntry32(uint64_t entry_addr, uint32_t next, uint32_t prev, uint32_t dex_file);
-  void WriteEntry64(uint64_t entry_addr, uint64_t next, uint64_t prev, uint64_t dex_file);
+  void WriteDescriptor32(uint64_t addr, uint32_t entry);
+  void WriteDescriptor64(uint64_t addr, uint64_t entry);
+  void WriteEntry32Pack(uint64_t addr, uint32_t next, uint32_t prev, uint32_t dex);
+  void WriteEntry32Pad(uint64_t addr, uint32_t next, uint32_t prev, uint32_t dex);
+  void WriteEntry64(uint64_t addr, uint64_t next, uint64_t prev, uint64_t dex);
   void WriteDex(uint64_t dex_file);
 
   static constexpr size_t kMapGlobalNonReadable = 2;
@@ -101,40 +105,70 @@
 
   std::shared_ptr<Memory> process_memory_;
   MemoryFake* memory_;
-  std::unique_ptr<DexFiles> dex_files_;
+  std::unique_ptr<JitDebug<DexFile>> dex_files_;
   std::unique_ptr<BufferMaps> maps_;
 };
 
-void DexFilesTest::WriteDescriptor32(uint64_t addr, uint32_t head) {
-  //   void* first_entry_
-  memory_->SetData32(addr + 12, head);
+void DexFilesTest::WriteDescriptor32(uint64_t addr, uint32_t entry) {
+  // Format of the 32 bit JITDescriptor structure:
+  //   uint32_t version
+  memory_->SetData32(addr, 1);
+  //   uint32_t action_flag
+  memory_->SetData32(addr + 4, 0);
+  //   uint32_t relevant_entry
+  memory_->SetData32(addr + 8, 0);
+  //   uint32_t first_entry
+  memory_->SetData32(addr + 12, entry);
 }
 
-void DexFilesTest::WriteDescriptor64(uint64_t addr, uint64_t head) {
-  //   void* first_entry_
-  memory_->SetData64(addr + 16, head);
+void DexFilesTest::WriteDescriptor64(uint64_t addr, uint64_t entry) {
+  // Format of the 64 bit JITDescriptor structure:
+  //   uint32_t version
+  memory_->SetData32(addr, 1);
+  //   uint32_t action_flag
+  memory_->SetData32(addr + 4, 0);
+  //   uint64_t relevant_entry
+  memory_->SetData64(addr + 8, 0);
+  //   uint64_t first_entry
+  memory_->SetData64(addr + 16, entry);
 }
 
-void DexFilesTest::WriteEntry32(uint64_t entry_addr, uint32_t next, uint32_t prev,
-                                uint32_t dex_file) {
-  // Format of the 32 bit DEXFileEntry structure:
+void DexFilesTest::WriteEntry32Pack(uint64_t addr, uint32_t next, uint32_t prev, uint32_t dex) {
+  // Format of the 32 bit JITCodeEntry structure:
   //   uint32_t next
-  memory_->SetData32(entry_addr, next);
+  memory_->SetData32(addr, next);
   //   uint32_t prev
-  memory_->SetData32(entry_addr + 4, prev);
-  //   uint32_t dex_file
-  memory_->SetData32(entry_addr + 8, dex_file);
+  memory_->SetData32(addr + 4, prev);
+  //   uint32_t dex
+  memory_->SetData32(addr + 8, dex);
+  //   uint64_t symfile_size
+  memory_->SetData64(addr + 12, sizeof(kDexData) * sizeof(uint32_t));
 }
 
-void DexFilesTest::WriteEntry64(uint64_t entry_addr, uint64_t next, uint64_t prev,
-                                uint64_t dex_file) {
-  // Format of the 64 bit DEXFileEntry structure:
+void DexFilesTest::WriteEntry32Pad(uint64_t addr, uint32_t next, uint32_t prev, uint32_t dex) {
+  // Format of the 32 bit JITCodeEntry structure:
+  //   uint32_t next
+  memory_->SetData32(addr, next);
+  //   uint32_t prev
+  memory_->SetData32(addr + 4, prev);
+  //   uint32_t dex
+  memory_->SetData32(addr + 8, dex);
+  //   uint32_t pad
+  memory_->SetData32(addr + 12, 0);
+  //   uint64_t symfile_size
+  memory_->SetData64(addr + 16, sizeof(kDexData) * sizeof(uint32_t));
+}
+
+void DexFilesTest::WriteEntry64(uint64_t addr, uint64_t next, uint64_t prev, uint64_t dex) {
+  // Format of the 64 bit JITCodeEntry structure:
   //   uint64_t next
-  memory_->SetData64(entry_addr, next);
+  memory_->SetData64(addr, next);
   //   uint64_t prev
-  memory_->SetData64(entry_addr + 8, prev);
-  //   uint64_t dex_file
-  memory_->SetData64(entry_addr + 16, dex_file);
+  memory_->SetData64(addr + 8, prev);
+  //   uint64_t dex
+  memory_->SetData64(addr + 16, dex);
+  //   uint64_t symfile_size
+  memory_->SetData64(addr + 24, sizeof(kDexData) * sizeof(uint32_t));
 }
 
 void DexFilesTest::WriteDex(uint64_t dex_file) {
@@ -144,9 +178,8 @@
 TEST_F(DexFilesTest, get_method_information_invalid) {
   std::string method_name = "nothing";
   uint64_t method_offset = 0x124;
-  MapInfo* info = maps_->Get(kMapDexFileEntries);
 
-  dex_files_->GetMethodInformation(maps_.get(), info, 0, &method_name, &method_offset);
+  dex_files_->GetFunctionName(maps_.get(), 0, &method_name, &method_offset);
   EXPECT_EQ("nothing", method_name);
   EXPECT_EQ(0x124U, method_offset);
 }
@@ -154,13 +187,12 @@
 TEST_F(DexFilesTest, get_method_information_32) {
   std::string method_name = "nothing";
   uint64_t method_offset = 0x124;
-  MapInfo* info = maps_->Get(kMapDexFiles);
 
   WriteDescriptor32(0xf800, 0x200000);
-  WriteEntry32(0x200000, 0, 0, 0x300000);
+  WriteEntry32Pad(0x200000, 0, 0, 0x300000);
   WriteDex(0x300000);
 
-  dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
+  dex_files_->GetFunctionName(maps_.get(), 0x300100, &method_name, &method_offset);
   EXPECT_EQ("Main.<init>", method_name);
   EXPECT_EQ(0U, method_offset);
 }
@@ -170,13 +202,12 @@
 
   std::string method_name = "nothing";
   uint64_t method_offset = 0x124;
-  MapInfo* info = maps_->Get(kMapDexFiles);
 
   WriteDescriptor64(0xf800, 0x200000);
   WriteEntry64(0x200000, 0, 0, 0x301000);
   WriteDex(0x301000);
 
-  dex_files_->GetMethodInformation(maps_.get(), info, 0x301102, &method_name, &method_offset);
+  dex_files_->GetFunctionName(maps_.get(), 0x301102, &method_name, &method_offset);
   EXPECT_EQ("Main.<init>", method_name);
   EXPECT_EQ(2U, method_offset);
 }
@@ -184,14 +215,14 @@
 TEST_F(DexFilesTest, get_method_information_not_first_entry_32) {
   std::string method_name = "nothing";
   uint64_t method_offset = 0x124;
-  MapInfo* info = maps_->Get(kMapDexFiles);
 
   WriteDescriptor32(0xf800, 0x200000);
-  WriteEntry32(0x200000, 0x200100, 0, 0x100000);
-  WriteEntry32(0x200100, 0, 0x200000, 0x300000);
+  WriteEntry32Pad(0x200000, 0x200100, 0, 0x100000);
+  WriteDex(0x100000);
+  WriteEntry32Pad(0x200100, 0, 0x200000, 0x300000);
   WriteDex(0x300000);
 
-  dex_files_->GetMethodInformation(maps_.get(), info, 0x300104, &method_name, &method_offset);
+  dex_files_->GetFunctionName(maps_.get(), 0x300104, &method_name, &method_offset);
   EXPECT_EQ("Main.<init>", method_name);
   EXPECT_EQ(4U, method_offset);
 }
@@ -201,14 +232,14 @@
 
   std::string method_name = "nothing";
   uint64_t method_offset = 0x124;
-  MapInfo* info = maps_->Get(kMapDexFiles);
 
   WriteDescriptor64(0xf800, 0x200000);
   WriteEntry64(0x200000, 0x200100, 0, 0x100000);
+  WriteDex(0x100000);
   WriteEntry64(0x200100, 0, 0x200000, 0x300000);
   WriteDex(0x300000);
 
-  dex_files_->GetMethodInformation(maps_.get(), info, 0x300106, &method_name, &method_offset);
+  dex_files_->GetFunctionName(maps_.get(), 0x300106, &method_name, &method_offset);
   EXPECT_EQ("Main.<init>", method_name);
   EXPECT_EQ(6U, method_offset);
 }
@@ -216,19 +247,18 @@
 TEST_F(DexFilesTest, get_method_information_cached) {
   std::string method_name = "nothing";
   uint64_t method_offset = 0x124;
-  MapInfo* info = maps_->Get(kMapDexFiles);
 
   WriteDescriptor32(0xf800, 0x200000);
-  WriteEntry32(0x200000, 0, 0, 0x300000);
+  WriteEntry32Pad(0x200000, 0, 0, 0x300000);
   WriteDex(0x300000);
 
-  dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
+  dex_files_->GetFunctionName(maps_.get(), 0x300100, &method_name, &method_offset);
   EXPECT_EQ("Main.<init>", method_name);
   EXPECT_EQ(0U, method_offset);
 
   // Clear all memory and make sure that data is acquired from the cache.
   memory_->Clear();
-  dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
+  dex_files_->GetFunctionName(maps_.get(), 0x300100, &method_name, &method_offset);
   EXPECT_EQ("Main.<init>", method_name);
   EXPECT_EQ(0U, method_offset);
 }
@@ -236,26 +266,24 @@
 TEST_F(DexFilesTest, get_method_information_search_libs) {
   std::string method_name = "nothing";
   uint64_t method_offset = 0x124;
-  MapInfo* info = maps_->Get(kMapDexFiles);
 
   WriteDescriptor32(0xf800, 0x200000);
-  WriteEntry32(0x200000, 0x200100, 0, 0x100000);
-  WriteEntry32(0x200100, 0, 0x200000, 0x300000);
+  WriteEntry32Pad(0x200000, 0x200100, 0, 0x100000);
+  WriteDex(0x100000);
+  WriteEntry32Pad(0x200100, 0, 0x200000, 0x300000);
   WriteDex(0x300000);
 
   // Only search a given named list of libs.
   std::vector<std::string> libs{"libart.so"};
-  dex_files_.reset(new DexFiles(process_memory_, libs));
-  dex_files_->SetArch(ARCH_ARM);
+  dex_files_ = JitDebug<DexFile>::Create(ARCH_ARM, process_memory_, libs);
 
-  dex_files_->GetMethodInformation(maps_.get(), info, 0x300104, &method_name, &method_offset);
+  dex_files_->GetFunctionName(maps_.get(), 0x300104, &method_name, &method_offset);
   EXPECT_EQ("nothing", method_name);
   EXPECT_EQ(0x124U, method_offset);
 
   MapInfo* map_info = maps_->Get(kMapGlobal);
   map_info->name = "/system/lib/libart.so";
-  dex_files_.reset(new DexFiles(process_memory_, libs));
-  dex_files_->SetArch(ARCH_ARM);
+  dex_files_ = JitDebug<DexFile>::Create(ARCH_ARM, process_memory_, libs);
   // Set the rw map to the same name or this will not scan this entry.
   map_info = maps_->Get(kMapGlobalRw);
   map_info->name = "/system/lib/libart.so";
@@ -263,7 +291,7 @@
   // DexFiles object.
   libs.clear();
 
-  dex_files_->GetMethodInformation(maps_.get(), info, 0x300104, &method_name, &method_offset);
+  dex_files_->GetFunctionName(maps_.get(), 0x300104, &method_name, &method_offset);
   EXPECT_EQ("Main.<init>", method_name);
   EXPECT_EQ(4U, method_offset);
 }
@@ -271,26 +299,24 @@
 TEST_F(DexFilesTest, get_method_information_global_skip_zero_32) {
   std::string method_name = "nothing";
   uint64_t method_offset = 0x124;
-  MapInfo* info = maps_->Get(kMapDexFiles);
 
   // First global variable found, but value is zero.
   WriteDescriptor32(0xa800, 0);
 
   WriteDescriptor32(0xf800, 0x200000);
-  WriteEntry32(0x200000, 0, 0, 0x300000);
+  WriteEntry32Pad(0x200000, 0, 0, 0x300000);
   WriteDex(0x300000);
 
-  dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
+  dex_files_->GetFunctionName(maps_.get(), 0x300100, &method_name, &method_offset);
   EXPECT_EQ("Main.<init>", method_name);
   EXPECT_EQ(0U, method_offset);
 
   // Verify that second is ignored when first is set to non-zero
-  dex_files_.reset(new DexFiles(process_memory_));
-  dex_files_->SetArch(ARCH_ARM);
+  dex_files_ = JitDebug<DexFile>::Create(ARCH_ARM, process_memory_);
   method_name = "fail";
   method_offset = 0x123;
   WriteDescriptor32(0xa800, 0x100000);
-  dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
+  dex_files_->GetFunctionName(maps_.get(), 0x300100, &method_name, &method_offset);
   EXPECT_EQ("fail", method_name);
   EXPECT_EQ(0x123U, method_offset);
 }
@@ -300,7 +326,6 @@
 
   std::string method_name = "nothing";
   uint64_t method_offset = 0x124;
-  MapInfo* info = maps_->Get(kMapDexFiles);
 
   // First global variable found, but value is zero.
   WriteDescriptor64(0xa800, 0);
@@ -309,17 +334,16 @@
   WriteEntry64(0x200000, 0, 0, 0x300000);
   WriteDex(0x300000);
 
-  dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
+  dex_files_->GetFunctionName(maps_.get(), 0x300100, &method_name, &method_offset);
   EXPECT_EQ("Main.<init>", method_name);
   EXPECT_EQ(0U, method_offset);
 
   // Verify that second is ignored when first is set to non-zero
-  dex_files_.reset(new DexFiles(process_memory_));
-  dex_files_->SetArch(ARCH_ARM64);
+  dex_files_ = JitDebug<DexFile>::Create(ARCH_ARM64, process_memory_);
   method_name = "fail";
   method_offset = 0x123;
   WriteDescriptor64(0xa800, 0x100000);
-  dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
+  dex_files_->GetFunctionName(maps_.get(), 0x300100, &method_name, &method_offset);
   EXPECT_EQ("fail", method_name);
   EXPECT_EQ(0x123U, method_offset);
 }
diff --git a/libunwindstack/tests/JitDebugTest.cpp b/libunwindstack/tests/JitDebugTest.cpp
index b1ca111..438194a 100644
--- a/libunwindstack/tests/JitDebugTest.cpp
+++ b/libunwindstack/tests/JitDebugTest.cpp
@@ -46,8 +46,7 @@
   }
 
   void Init(ArchEnum arch) {
-    jit_debug_.reset(new JitDebug(process_memory_));
-    jit_debug_->SetArch(arch);
+    jit_debug_ = JitDebug<Elf>::Create(arch, process_memory_);
 
     maps_.reset(
         new BufferMaps("1000-4000 ---s 00000000 00:00 0 /fake/elf1\n"
@@ -62,6 +61,12 @@
                        "200000-210000 rw-p 0002000 00:00 0 /fake/elf4\n"));
     ASSERT_TRUE(maps_->Parse());
 
+    // Ensure all memory of the ELF file is initialized,
+    // otherwise reads within it may fail.
+    for (uint64_t addr = 0x4000; addr < 0x6000; addr += 8) {
+      memory_->SetData64(addr, 0);
+    }
+
     MapInfo* map_info = maps_->Get(3);
     ASSERT_TRUE(map_info != nullptr);
     CreateFakeElf(map_info);
@@ -94,7 +99,7 @@
     ehdr.e_shstrndx = 1;
     ehdr.e_shoff = sh_offset;
     ehdr.e_shentsize = sizeof(ShdrType);
-    ehdr.e_shnum = 3;
+    ehdr.e_shnum = 4;
     memory_->SetMemory(offset, &ehdr, sizeof(ehdr));
 
     ShdrType shdr;
@@ -110,6 +115,7 @@
     shdr.sh_size = 0x100;
     memory_->SetMemory(offset + sh_offset, &shdr, sizeof(shdr));
     memory_->SetMemory(offset + 0x500, ".debug_frame");
+    memory_->SetMemory(offset + 0x550, ".text");
 
     sh_offset += sizeof(shdr);
     memset(&shdr, 0, sizeof(shdr));
@@ -120,6 +126,15 @@
     shdr.sh_size = 0x200;
     memory_->SetMemory(offset + sh_offset, &shdr, sizeof(shdr));
 
+    sh_offset += sizeof(shdr);
+    memset(&shdr, 0, sizeof(shdr));
+    shdr.sh_type = SHT_NOBITS;
+    shdr.sh_name = 0x50;
+    shdr.sh_addr = pc;
+    shdr.sh_offset = 0;
+    shdr.sh_size = size;
+    memory_->SetMemory(offset + sh_offset, &shdr, sizeof(shdr));
+
     // Now add a single cie/fde.
     uint64_t dwarf_offset = offset + 0x600;
     if (class_type == ELFCLASS32) {
@@ -168,7 +183,7 @@
 
   std::shared_ptr<Memory> process_memory_;
   MemoryFake* memory_;
-  std::unique_ptr<JitDebug> jit_debug_;
+  std::unique_ptr<JitDebug<Elf>> jit_debug_;
   std::unique_ptr<BufferMaps> maps_;
 };
 
@@ -238,20 +253,20 @@
 }
 
 TEST_F(JitDebugTest, get_elf_invalid) {
-  Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
+  Elf* elf = jit_debug_->Get(maps_.get(), 0x1500);
   ASSERT_TRUE(elf == nullptr);
 }
 
 TEST_F(JitDebugTest, get_elf_no_global_variable) {
   maps_.reset(new BufferMaps(""));
-  Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
+  Elf* elf = jit_debug_->Get(maps_.get(), 0x1500);
   ASSERT_TRUE(elf == nullptr);
 }
 
 TEST_F(JitDebugTest, get_elf_no_valid_descriptor_in_memory) {
   CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
 
-  Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
+  Elf* elf = jit_debug_->Get(maps_.get(), 0x1500);
   ASSERT_TRUE(elf == nullptr);
 }
 
@@ -260,7 +275,7 @@
 
   WriteDescriptor32(0xf800, 0x200000);
 
-  Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
+  Elf* elf = jit_debug_->Get(maps_.get(), 0x1500);
   ASSERT_TRUE(elf == nullptr);
 }
 
@@ -269,7 +284,7 @@
 
   WriteDescriptor32(0xf800, 0);
 
-  Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
+  Elf* elf = jit_debug_->Get(maps_.get(), 0x1500);
   ASSERT_TRUE(elf == nullptr);
 }
 
@@ -280,7 +295,7 @@
   // Set the version to an invalid value.
   memory_->SetData32(0xf800, 2);
 
-  Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
+  Elf* elf = jit_debug_->Get(maps_.get(), 0x1500);
   ASSERT_TRUE(elf == nullptr);
 }
 
@@ -290,12 +305,18 @@
   WriteDescriptor32(0xf800, 0x200000);
   WriteEntry32Pad(0x200000, 0, 0, 0x4000, 0x1000);
 
-  Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
+  Elf* elf = jit_debug_->Get(maps_.get(), 0x1500);
   ASSERT_TRUE(elf != nullptr);
+  uint64_t text_addr;
+  uint64_t text_size;
+  ASSERT_TRUE(elf->GetTextRange(&text_addr, &text_size));
+  ASSERT_EQ(text_addr, 0x1500u);
+  ASSERT_EQ(text_size, 0x200u);
 
   // Clear the memory and verify all of the data is cached.
   memory_->Clear();
-  Elf* elf2 = jit_debug_->GetElf(maps_.get(), 0x1500);
+  WriteDescriptor32(0xf800, 0x200000);
+  Elf* elf2 = jit_debug_->Get(maps_.get(), 0x1500);
   ASSERT_TRUE(elf2 != nullptr);
   EXPECT_EQ(elf, elf2);
 }
@@ -309,16 +330,15 @@
   WriteDescriptor32(0x12800, 0x201000);
   WriteEntry32Pad(0x201000, 0, 0, 0x5000, 0x1000);
 
-  ASSERT_TRUE(jit_debug_->GetElf(maps_.get(), 0x1500) != nullptr);
-  ASSERT_TRUE(jit_debug_->GetElf(maps_.get(), 0x2000) == nullptr);
+  ASSERT_TRUE(jit_debug_->Get(maps_.get(), 0x1500) != nullptr);
+  ASSERT_TRUE(jit_debug_->Get(maps_.get(), 0x2000) == nullptr);
 
   // Now clear the descriptor entry for the first one.
   WriteDescriptor32(0xf800, 0);
-  jit_debug_.reset(new JitDebug(process_memory_));
-  jit_debug_->SetArch(ARCH_ARM);
+  jit_debug_ = JitDebug<Elf>::Create(ARCH_ARM, process_memory_);
 
-  ASSERT_TRUE(jit_debug_->GetElf(maps_.get(), 0x1500) == nullptr);
-  ASSERT_TRUE(jit_debug_->GetElf(maps_.get(), 0x2000) != nullptr);
+  ASSERT_TRUE(jit_debug_->Get(maps_.get(), 0x1500) == nullptr);
+  ASSERT_TRUE(jit_debug_->Get(maps_.get(), 0x2000) != nullptr);
 }
 
 TEST_F(JitDebugTest, get_elf_x86) {
@@ -329,13 +349,14 @@
   WriteDescriptor32(0xf800, 0x200000);
   WriteEntry32Pack(0x200000, 0, 0, 0x4000, 0x1000);
 
-  jit_debug_->SetArch(ARCH_X86);
-  Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
+  jit_debug_ = JitDebug<Elf>::Create(ARCH_X86, process_memory_);
+  Elf* elf = jit_debug_->Get(maps_.get(), 0x1500);
   ASSERT_TRUE(elf != nullptr);
 
   // Clear the memory and verify all of the data is cached.
   memory_->Clear();
-  Elf* elf2 = jit_debug_->GetElf(maps_.get(), 0x1500);
+  WriteDescriptor32(0xf800, 0x200000);
+  Elf* elf2 = jit_debug_->Get(maps_.get(), 0x1500);
   ASSERT_TRUE(elf2 != nullptr);
   EXPECT_EQ(elf, elf2);
 }
@@ -348,12 +369,13 @@
   WriteDescriptor64(0xf800, 0x200000);
   WriteEntry64(0x200000, 0, 0, 0x4000, 0x1000);
 
-  Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
+  Elf* elf = jit_debug_->Get(maps_.get(), 0x1500);
   ASSERT_TRUE(elf != nullptr);
 
   // Clear the memory and verify all of the data is cached.
   memory_->Clear();
-  Elf* elf2 = jit_debug_->GetElf(maps_.get(), 0x1500);
+  WriteDescriptor64(0xf800, 0x200000);
+  Elf* elf2 = jit_debug_->Get(maps_.get(), 0x1500);
   ASSERT_TRUE(elf2 != nullptr);
   EXPECT_EQ(elf, elf2);
 }
@@ -366,20 +388,21 @@
   WriteEntry32Pad(0x200000, 0, 0x200100, 0x4000, 0x1000);
   WriteEntry32Pad(0x200100, 0x200100, 0, 0x5000, 0x1000);
 
-  Elf* elf_2 = jit_debug_->GetElf(maps_.get(), 0x2400);
+  Elf* elf_2 = jit_debug_->Get(maps_.get(), 0x2400);
   ASSERT_TRUE(elf_2 != nullptr);
 
-  Elf* elf_1 = jit_debug_->GetElf(maps_.get(), 0x1600);
+  Elf* elf_1 = jit_debug_->Get(maps_.get(), 0x1600);
   ASSERT_TRUE(elf_1 != nullptr);
 
   // Clear the memory and verify all of the data is cached.
   memory_->Clear();
-  EXPECT_EQ(elf_1, jit_debug_->GetElf(maps_.get(), 0x1500));
-  EXPECT_EQ(elf_1, jit_debug_->GetElf(maps_.get(), 0x16ff));
-  EXPECT_EQ(elf_2, jit_debug_->GetElf(maps_.get(), 0x2300));
-  EXPECT_EQ(elf_2, jit_debug_->GetElf(maps_.get(), 0x26ff));
-  EXPECT_EQ(nullptr, jit_debug_->GetElf(maps_.get(), 0x1700));
-  EXPECT_EQ(nullptr, jit_debug_->GetElf(maps_.get(), 0x2700));
+  WriteDescriptor32(0xf800, 0x200000);
+  EXPECT_EQ(elf_1, jit_debug_->Get(maps_.get(), 0x1500));
+  EXPECT_EQ(elf_1, jit_debug_->Get(maps_.get(), 0x16ff));
+  EXPECT_EQ(elf_2, jit_debug_->Get(maps_.get(), 0x2300));
+  EXPECT_EQ(elf_2, jit_debug_->Get(maps_.get(), 0x26ff));
+  EXPECT_EQ(nullptr, jit_debug_->Get(maps_.get(), 0x1700));
+  EXPECT_EQ(nullptr, jit_debug_->Get(maps_.get(), 0x2700));
 }
 
 TEST_F(JitDebugTest, get_elf_search_libs) {
@@ -390,21 +413,19 @@
 
   // Only search a given named list of libs.
   std::vector<std::string> libs{"libart.so"};
-  jit_debug_.reset(new JitDebug(process_memory_, libs));
-  jit_debug_->SetArch(ARCH_ARM);
-  EXPECT_TRUE(jit_debug_->GetElf(maps_.get(), 0x1500) == nullptr);
+  jit_debug_ = JitDebug<Elf>::Create(ARCH_ARM, process_memory_, libs);
+  EXPECT_TRUE(jit_debug_->Get(maps_.get(), 0x1500) == nullptr);
 
   // Change the name of the map that includes the value and verify this works.
   MapInfo* map_info = maps_->Get(5);
   map_info->name = "/system/lib/libart.so";
   map_info = maps_->Get(6);
   map_info->name = "/system/lib/libart.so";
-  jit_debug_.reset(new JitDebug(process_memory_, libs));
+  jit_debug_ = JitDebug<Elf>::Create(ARCH_ARM, process_memory_);
   // Make sure that clearing our copy of the libs doesn't affect the
   // JitDebug object.
   libs.clear();
-  jit_debug_->SetArch(ARCH_ARM);
-  EXPECT_TRUE(jit_debug_->GetElf(maps_.get(), 0x1500) != nullptr);
+  EXPECT_TRUE(jit_debug_->Get(maps_.get(), 0x1500) != nullptr);
 }
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp
index 655579e..0867561 100644
--- a/libunwindstack/tests/UnwindOfflineTest.cpp
+++ b/libunwindstack/tests/UnwindOfflineTest.cpp
@@ -290,9 +290,7 @@
   }
   process_memory_.reset(memory);
 
-  JitDebug jit_debug(process_memory_);
   Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
-  unwinder.SetJitDebug(&jit_debug, regs_->Arch());
   unwinder.Unwind();
 
   std::string frame_info(DumpFrames(unwinder));
@@ -592,9 +590,7 @@
   }
   process_memory_.reset(memory);
 
-  JitDebug jit_debug(process_memory_);
   Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
-  unwinder.SetJitDebug(&jit_debug, regs_->Arch());
   unwinder.Unwind();
 
   std::string frame_info(DumpFrames(unwinder));
@@ -915,9 +911,7 @@
   LeakType* leak_data = reinterpret_cast<LeakType*>(data);
 
   std::unique_ptr<Regs> regs_copy(leak_data->regs->Clone());
-  JitDebug jit_debug(leak_data->process_memory);
   Unwinder unwinder(128, leak_data->maps, regs_copy.get(), leak_data->process_memory);
-  unwinder.SetJitDebug(&jit_debug, regs_copy->Arch());
   unwinder.Unwind();
   ASSERT_EQ(76U, unwinder.NumFrames());
 }
@@ -1038,9 +1032,7 @@
   }
   process_memory_.reset(memory);
 
-  JitDebug jit_debug(process_memory_);
   Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
-  unwinder.SetJitDebug(&jit_debug, regs_->Arch());
   unwinder.Unwind();
 
   std::string frame_info(DumpFrames(unwinder));
diff --git a/libunwindstack/tests/UnwindTest.cpp b/libunwindstack/tests/UnwindTest.cpp
index 4e38015..5e7e6bf 100644
--- a/libunwindstack/tests/UnwindTest.cpp
+++ b/libunwindstack/tests/UnwindTest.cpp
@@ -170,7 +170,7 @@
     unwinder.reset(new Unwinder(512, maps.get(), regs.get(), process_memory));
   } else {
     UnwinderFromPid* unwinder_from_pid = new UnwinderFromPid(512, getpid());
-    ASSERT_TRUE(unwinder_from_pid->Init(regs->Arch()));
+    ASSERT_TRUE(unwinder_from_pid->Init());
     unwinder_from_pid->SetRegs(regs.get());
     unwinder.reset(unwinder_from_pid);
   }
@@ -283,7 +283,7 @@
   ASSERT_TRUE(regs.get() != nullptr);
 
   UnwinderFromPid unwinder(512, pid);
-  ASSERT_TRUE(unwinder.Init(regs->Arch()));
+  ASSERT_TRUE(unwinder.Init());
   unwinder.SetRegs(regs.get());
 
   VerifyUnwind(&unwinder, kFunctionOrder);
@@ -335,7 +335,7 @@
   ASSERT_TRUE(regs.get() != nullptr);
 
   UnwinderFromPid unwinder(512, *pid);
-  ASSERT_TRUE(unwinder.Init(regs->Arch()));
+  ASSERT_TRUE(unwinder.Init());
   unwinder.SetRegs(regs.get());
 
   VerifyUnwind(&unwinder, kFunctionOrder);