Merge "Fix support finding global variables."
am: 2da8e3c2ee

Change-Id: Ieec8f9ae7c542487a108c06f66b4292046e4ff4c
diff --git a/libunwindstack/Elf.cpp b/libunwindstack/Elf.cpp
index c141b2e..6627787 100644
--- a/libunwindstack/Elf.cpp
+++ b/libunwindstack/Elf.cpp
@@ -112,35 +112,33 @@
                      gnu_debugdata_interface_->GetFunctionName(addr, name, func_offset)));
 }
 
-bool Elf::GetGlobalVariable(const std::string& name, uint64_t* memory_address) {
+bool Elf::GetGlobalVariableOffset(const std::string& name, uint64_t* memory_offset) {
   if (!valid_) {
     return false;
   }
 
-  if (!interface_->GetGlobalVariable(name, memory_address) &&
+  uint64_t vaddr;
+  if (!interface_->GetGlobalVariable(name, &vaddr) &&
       (gnu_debugdata_interface_ == nullptr ||
-       !gnu_debugdata_interface_->GetGlobalVariable(name, memory_address))) {
+       !gnu_debugdata_interface_->GetGlobalVariable(name, &vaddr))) {
     return false;
   }
 
-  // Adjust by the load bias.
-  if (load_bias_ > 0 && *memory_address < static_cast<uint64_t>(load_bias_)) {
-    return false;
+  // Check the .data section.
+  uint64_t vaddr_start = interface_->data_vaddr_start();
+  if (vaddr >= vaddr_start && vaddr < interface_->data_vaddr_end()) {
+    *memory_offset = vaddr - vaddr_start + interface_->data_offset();
+    return true;
   }
 
-  *memory_address -= load_bias_;
-
-  // If this winds up in the dynamic section, then we might need to adjust
-  // the address.
-  uint64_t dynamic_end = interface_->dynamic_vaddr() + interface_->dynamic_size();
-  if (*memory_address >= interface_->dynamic_vaddr() && *memory_address < dynamic_end) {
-    if (interface_->dynamic_vaddr() > interface_->dynamic_offset()) {
-      *memory_address -= interface_->dynamic_vaddr() - interface_->dynamic_offset();
-    } else {
-      *memory_address += interface_->dynamic_offset() - interface_->dynamic_vaddr();
-    }
+  // Check the .dynamic section.
+  vaddr_start = interface_->dynamic_vaddr_start();
+  if (vaddr >= vaddr_start && vaddr < interface_->dynamic_vaddr_end()) {
+    *memory_offset = vaddr - vaddr_start + interface_->dynamic_offset();
+    return true;
   }
-  return true;
+
+  return false;
 }
 
 std::string Elf::GetBuildID() {
diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp
index 5f95fa8..7676289 100644
--- a/libunwindstack/ElfInterface.cpp
+++ b/libunwindstack/ElfInterface.cpp
@@ -236,8 +236,12 @@
 
     case PT_DYNAMIC:
       dynamic_offset_ = phdr.p_offset;
-      dynamic_vaddr_ = phdr.p_vaddr;
-      dynamic_size_ = phdr.p_memsz;
+      dynamic_vaddr_start_ = phdr.p_vaddr;
+      if (__builtin_add_overflow(dynamic_vaddr_start_, phdr.p_memsz, &dynamic_vaddr_end_)) {
+        dynamic_offset_ = 0;
+        dynamic_vaddr_start_ = 0;
+        dynamic_vaddr_end_ = 0;
+      }
       break;
 
     default:
@@ -360,6 +364,14 @@
             eh_frame_hdr_offset_ = shdr.sh_offset;
             eh_frame_hdr_section_bias_ = static_cast<uint64_t>(shdr.sh_addr) - shdr.sh_offset;
             eh_frame_hdr_size_ = shdr.sh_size;
+          } else if (name == ".data") {
+            data_offset_ = shdr.sh_offset;
+            data_vaddr_start_ = shdr.sh_addr;
+            if (__builtin_add_overflow(data_vaddr_start_, shdr.sh_size, &data_vaddr_end_)) {
+              data_offset_ = 0;
+              data_vaddr_start_ = 0;
+              data_vaddr_end_ = 0;
+            }
           }
         }
       }
@@ -398,7 +410,7 @@
   // Find the soname location from the dynamic headers section.
   DynType dyn;
   uint64_t offset = dynamic_offset_;
-  uint64_t max_offset = offset + dynamic_size_;
+  uint64_t max_offset = offset + dynamic_vaddr_end_ - dynamic_vaddr_start_;
   for (uint64_t offset = dynamic_offset_; offset < max_offset; offset += sizeof(DynType)) {
     if (!memory_->ReadFully(offset, &dyn, sizeof(dyn))) {
       last_error_.code = ERROR_MEMORY_INVALID;
diff --git a/libunwindstack/Global.cpp b/libunwindstack/Global.cpp
index a20be00..ec977e1 100644
--- a/libunwindstack/Global.cpp
+++ b/libunwindstack/Global.cpp
@@ -39,28 +39,22 @@
   }
 }
 
-uint64_t Global::GetVariableOffset(MapInfo* info, const std::string& variable) {
-  if (!search_libs_.empty()) {
-    bool found = false;
-    const char* lib = basename(info->name.c_str());
-    for (const std::string& name : search_libs_) {
-      if (name == lib) {
-        found = true;
-        break;
-      }
-    }
-    if (!found) {
-      return 0;
-    }
+bool Global::Searchable(const std::string& name) {
+  if (search_libs_.empty()) {
+    return true;
   }
 
-  Elf* elf = info->GetElf(memory_, arch());
-  uint64_t ptr;
-  // Find first non-empty list (libraries might be loaded multiple times).
-  if (elf->GetGlobalVariable(variable, &ptr) && ptr != 0) {
-    return ptr + info->start;
+  if (name.empty()) {
+    return false;
   }
-  return 0;
+
+  const char* base_name = basename(name.c_str());
+  for (const std::string& lib : search_libs_) {
+    if (base_name == lib) {
+      return true;
+    }
+  }
+  return false;
 }
 
 void Global::FindAndReadVariable(Maps* maps, const char* var_str) {
@@ -78,24 +72,27 @@
   //   f2000-f3000 2000 rw- /system/lib/libc.so
   MapInfo* map_start = nullptr;
   for (const auto& info : *maps) {
-    if (map_start != nullptr) {
-      if (map_start->name == info->name) {
-        if (info->offset != 0 &&
-            (info->flags & (PROT_READ | PROT_WRITE)) == (PROT_READ | PROT_WRITE)) {
-          uint64_t ptr = GetVariableOffset(map_start, variable);
-          if (ptr != 0 && ReadVariableData(ptr)) {
-            break;
-          } else {
-            // Failed to find the global variable, do not bother trying again.
-            map_start = nullptr;
+    if (map_start != nullptr && map_start->name == info->name) {
+      if (info->offset != 0 &&
+          (info->flags & (PROT_READ | PROT_WRITE)) == (PROT_READ | PROT_WRITE)) {
+        Elf* elf = map_start->GetElf(memory_, arch());
+        uint64_t ptr;
+        if (elf->GetGlobalVariableOffset(variable, &ptr) && ptr != 0) {
+          uint64_t offset_end = info->offset + info->end - info->start;
+          if (ptr >= info->offset && ptr < offset_end) {
+            ptr = info->start + ptr - info->offset;
+            if (ReadVariableData(ptr)) {
+              break;
+            }
           }
         }
-      } else {
         map_start = nullptr;
       }
+    } else {
+      map_start = nullptr;
     }
     if (map_start == nullptr && (info->flags & PROT_READ) && info->offset == 0 &&
-        !info->name.empty()) {
+        Searchable(info->name)) {
       map_start = info.get();
     }
   }
diff --git a/libunwindstack/include/unwindstack/Elf.h b/libunwindstack/include/unwindstack/Elf.h
index fc3f2a6..472ed92 100644
--- a/libunwindstack/include/unwindstack/Elf.h
+++ b/libunwindstack/include/unwindstack/Elf.h
@@ -63,7 +63,7 @@
 
   bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset);
 
-  bool GetGlobalVariable(const std::string& name, uint64_t* memory_address);
+  bool GetGlobalVariableOffset(const std::string& name, uint64_t* memory_offset);
 
   uint64_t GetRelPc(uint64_t pc, const MapInfo* map_info);
 
diff --git a/libunwindstack/include/unwindstack/ElfInterface.h b/libunwindstack/include/unwindstack/ElfInterface.h
index ae9bd9a..0c39b23 100644
--- a/libunwindstack/include/unwindstack/ElfInterface.h
+++ b/libunwindstack/include/unwindstack/ElfInterface.h
@@ -77,8 +77,11 @@
   void SetGnuDebugdataInterface(ElfInterface* interface) { gnu_debugdata_interface_ = interface; }
 
   uint64_t dynamic_offset() { return dynamic_offset_; }
-  uint64_t dynamic_vaddr() { return dynamic_vaddr_; }
-  uint64_t dynamic_size() { return dynamic_size_; }
+  uint64_t dynamic_vaddr_start() { return dynamic_vaddr_start_; }
+  uint64_t dynamic_vaddr_end() { return dynamic_vaddr_end_; }
+  uint64_t data_offset() { return data_offset_; }
+  uint64_t data_vaddr_start() { return data_vaddr_start_; }
+  uint64_t data_vaddr_end() { return data_vaddr_end_; }
   uint64_t eh_frame_hdr_offset() { return eh_frame_hdr_offset_; }
   int64_t eh_frame_hdr_section_bias() { return eh_frame_hdr_section_bias_; }
   uint64_t eh_frame_hdr_size() { return eh_frame_hdr_size_; }
@@ -141,8 +144,12 @@
 
   // Stored elf data.
   uint64_t dynamic_offset_ = 0;
-  uint64_t dynamic_vaddr_ = 0;
-  uint64_t dynamic_size_ = 0;
+  uint64_t dynamic_vaddr_start_ = 0;
+  uint64_t dynamic_vaddr_end_ = 0;
+
+  uint64_t data_offset_ = 0;
+  uint64_t data_vaddr_start_ = 0;
+  uint64_t data_vaddr_end_ = 0;
 
   uint64_t eh_frame_hdr_offset_ = 0;
   int64_t eh_frame_hdr_section_bias_ = 0;
diff --git a/libunwindstack/include/unwindstack/Global.h b/libunwindstack/include/unwindstack/Global.h
index a7e6c15..b9bb141 100644
--- a/libunwindstack/include/unwindstack/Global.h
+++ b/libunwindstack/include/unwindstack/Global.h
@@ -45,7 +45,7 @@
   ArchEnum arch() { return arch_; }
 
  protected:
-  uint64_t GetVariableOffset(MapInfo* info, const std::string& variable);
+  bool Searchable(const std::string& name);
   void FindAndReadVariable(Maps* maps, const char* variable);
 
   virtual bool ReadVariableData(uint64_t offset) = 0;
diff --git a/libunwindstack/tests/DexFilesTest.cpp b/libunwindstack/tests/DexFilesTest.cpp
index 1ea9e5c..0dd3af6 100644
--- a/libunwindstack/tests/DexFilesTest.cpp
+++ b/libunwindstack/tests/DexFilesTest.cpp
@@ -36,14 +36,18 @@
 
 class DexFilesTest : public ::testing::Test {
  protected:
-  void CreateFakeElf(MapInfo* map_info) {
+  void CreateFakeElf(MapInfo* map_info, uint64_t global_offset, uint64_t data_offset,
+                     uint64_t data_vaddr, uint64_t data_size) {
     MemoryFake* memory = new MemoryFake;
     ElfFake* elf = new ElfFake(memory);
     elf->FakeSetValid(true);
     ElfInterfaceFake* interface = new ElfInterfaceFake(memory);
     elf->FakeSetInterface(interface);
 
-    interface->FakeSetGlobalVariable("__dex_debug_descriptor", 0x800);
+    interface->FakeSetGlobalVariable("__dex_debug_descriptor", global_offset);
+    interface->FakeSetDataOffset(data_offset);
+    interface->FakeSetDataVaddrStart(data_vaddr);
+    interface->FakeSetDataVaddrEnd(data_vaddr + data_size);
     map_info->elf.reset(elf);
   }
 
@@ -54,11 +58,11 @@
     maps_.reset(
         new BufferMaps("1000-4000 ---s 00000000 00:00 0 /fake/elf\n"
                        "4000-6000 r--s 00000000 00:00 0 /fake/elf\n"
-                       "6000-8000 -wxs 00000000 00:00 0 /fake/elf\n"
+                       "6000-8000 -wxs 00002000 00:00 0 /fake/elf\n"
                        "a000-c000 r--p 00000000 00:00 0 /fake/elf2\n"
-                       "c000-f000 rw-p 00001000 00:00 0 /fake/elf2\n"
+                       "c000-f000 rw-p 00002000 00:00 0 /fake/elf2\n"
                        "f000-11000 r--p 00000000 00:00 0 /fake/elf3\n"
-                       "100000-110000 rw-p 0001000 00:00 0 /fake/elf3\n"
+                       "100000-110000 rw-p 00f1000 00:00 0 /fake/elf3\n"
                        "200000-210000 rw-p 0002000 00:00 0 /fake/elf3\n"
                        "300000-400000 rw-p 0003000 00:00 0 /fake/elf3\n"));
     ASSERT_TRUE(maps_->Parse());
@@ -66,17 +70,17 @@
     // Global variable in a section that is not readable.
     MapInfo* map_info = maps_->Get(kMapGlobalNonReadable);
     ASSERT_TRUE(map_info != nullptr);
-    CreateFakeElf(map_info);
+    CreateFakeElf(map_info, 0x2800, 0x2000, 0x2000, 0x3000);
 
     // Global variable not set by default.
     map_info = maps_->Get(kMapGlobalSetToZero);
     ASSERT_TRUE(map_info != nullptr);
-    CreateFakeElf(map_info);
+    CreateFakeElf(map_info, 0x2800, 0x2000, 0x2000, 0x3000);
 
     // Global variable set in this map.
     map_info = maps_->Get(kMapGlobal);
     ASSERT_TRUE(map_info != nullptr);
-    CreateFakeElf(map_info);
+    CreateFakeElf(map_info, 0xf1800, 0xf1000, 0xf1000, 0x10000);
   }
 
   void SetUp() override {
@@ -156,7 +160,7 @@
   uint64_t method_offset = 0x124;
   MapInfo* info = maps_->Get(kMapDexFiles);
 
-  WriteDescriptor32(0xf800, 0x200000);
+  WriteDescriptor32(0x100800, 0x200000);
   WriteEntry32(0x200000, 0, 0, 0x300000);
   WriteDex(0x300000);
 
@@ -172,7 +176,7 @@
   uint64_t method_offset = 0x124;
   MapInfo* info = maps_->Get(kMapDexFiles);
 
-  WriteDescriptor64(0xf800, 0x200000);
+  WriteDescriptor64(0x100800, 0x200000);
   WriteEntry64(0x200000, 0, 0, 0x301000);
   WriteDex(0x301000);
 
@@ -186,7 +190,7 @@
   uint64_t method_offset = 0x124;
   MapInfo* info = maps_->Get(kMapDexFiles);
 
-  WriteDescriptor32(0xf800, 0x200000);
+  WriteDescriptor32(0x100800, 0x200000);
   WriteEntry32(0x200000, 0x200100, 0, 0x100000);
   WriteEntry32(0x200100, 0, 0x200000, 0x300000);
   WriteDex(0x300000);
@@ -203,7 +207,7 @@
   uint64_t method_offset = 0x124;
   MapInfo* info = maps_->Get(kMapDexFiles);
 
-  WriteDescriptor64(0xf800, 0x200000);
+  WriteDescriptor64(0x100800, 0x200000);
   WriteEntry64(0x200000, 0x200100, 0, 0x100000);
   WriteEntry64(0x200100, 0, 0x200000, 0x300000);
   WriteDex(0x300000);
@@ -218,7 +222,7 @@
   uint64_t method_offset = 0x124;
   MapInfo* info = maps_->Get(kMapDexFiles);
 
-  WriteDescriptor32(0xf800, 0x200000);
+  WriteDescriptor32(0x100800, 0x200000);
   WriteEntry32(0x200000, 0, 0, 0x300000);
   WriteDex(0x300000);
 
@@ -238,7 +242,7 @@
   uint64_t method_offset = 0x124;
   MapInfo* info = maps_->Get(kMapDexFiles);
 
-  WriteDescriptor32(0xf800, 0x200000);
+  WriteDescriptor32(0x100800, 0x200000);
   WriteEntry32(0x200000, 0x200100, 0, 0x100000);
   WriteEntry32(0x200100, 0, 0x200000, 0x300000);
   WriteDex(0x300000);
@@ -274,9 +278,9 @@
   MapInfo* info = maps_->Get(kMapDexFiles);
 
   // First global variable found, but value is zero.
-  WriteDescriptor32(0xa800, 0);
+  WriteDescriptor32(0xc800, 0);
 
-  WriteDescriptor32(0xf800, 0x200000);
+  WriteDescriptor32(0x100800, 0x200000);
   WriteEntry32(0x200000, 0, 0, 0x300000);
   WriteDex(0x300000);
 
@@ -289,7 +293,7 @@
   dex_files_->SetArch(ARCH_ARM);
   method_name = "fail";
   method_offset = 0x123;
-  WriteDescriptor32(0xa800, 0x100000);
+  WriteDescriptor32(0xc800, 0x100000);
   dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
   EXPECT_EQ("fail", method_name);
   EXPECT_EQ(0x123U, method_offset);
@@ -303,9 +307,9 @@
   MapInfo* info = maps_->Get(kMapDexFiles);
 
   // First global variable found, but value is zero.
-  WriteDescriptor64(0xa800, 0);
+  WriteDescriptor64(0xc800, 0);
 
-  WriteDescriptor64(0xf800, 0x200000);
+  WriteDescriptor64(0x100800, 0x200000);
   WriteEntry64(0x200000, 0, 0, 0x300000);
   WriteDex(0x300000);
 
@@ -318,7 +322,7 @@
   dex_files_->SetArch(ARCH_ARM64);
   method_name = "fail";
   method_offset = 0x123;
-  WriteDescriptor64(0xa800, 0x100000);
+  WriteDescriptor64(0xc800, 0x100000);
   dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
   EXPECT_EQ("fail", method_name);
   EXPECT_EQ(0x123U, method_offset);
diff --git a/libunwindstack/tests/ElfFake.h b/libunwindstack/tests/ElfFake.h
index 832e64a..c33908d 100644
--- a/libunwindstack/tests/ElfFake.h
+++ b/libunwindstack/tests/ElfFake.h
@@ -97,6 +97,14 @@
 
   void FakeSetErrorAddress(uint64_t address) { last_error_.address = address; }
 
+  void FakeSetDataOffset(uint64_t offset) { data_offset_ = offset; }
+  void FakeSetDataVaddrStart(uint64_t vaddr) { data_vaddr_start_ = vaddr; }
+  void FakeSetDataVaddrEnd(uint64_t vaddr) { data_vaddr_end_ = vaddr; }
+
+  void FakeSetDynamicOffset(uint64_t offset) { dynamic_offset_ = offset; }
+  void FakeSetDynamicVaddrStart(uint64_t vaddr) { dynamic_vaddr_start_ = vaddr; }
+  void FakeSetDynamicVaddrEnd(uint64_t vaddr) { dynamic_vaddr_end_ = vaddr; }
+
  private:
   std::unordered_map<std::string, uint64_t> globals_;
   std::string fake_build_id_;
diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp
index e6728a0..d227b60 100644
--- a/libunwindstack/tests/ElfTest.cpp
+++ b/libunwindstack/tests/ElfTest.cpp
@@ -320,9 +320,13 @@
   MOCK_METHOD(bool, GetGlobalVariable, (const std::string&, uint64_t*), (override));
   MOCK_METHOD(bool, IsValidPc, (uint64_t), (override));
 
+  void MockSetDataOffset(uint64_t offset) { data_offset_ = offset; }
+  void MockSetDataVaddrStart(uint64_t vaddr) { data_vaddr_start_ = vaddr; }
+  void MockSetDataVaddrEnd(uint64_t vaddr) { data_vaddr_end_ = vaddr; }
+
   void MockSetDynamicOffset(uint64_t offset) { dynamic_offset_ = offset; }
-  void MockSetDynamicVaddr(uint64_t vaddr) { dynamic_vaddr_ = vaddr; }
-  void MockSetDynamicSize(uint64_t size) { dynamic_size_ = size; }
+  void MockSetDynamicVaddrStart(uint64_t vaddr) { dynamic_vaddr_start_ = vaddr; }
+  void MockSetDynamicVaddrEnd(uint64_t vaddr) { dynamic_vaddr_end_ = vaddr; }
 };
 
 TEST_F(ElfTest, step_in_interface) {
@@ -348,7 +352,7 @@
 
   std::string global("something");
   uint64_t offset;
-  ASSERT_FALSE(elf.GetGlobalVariable(global, &offset));
+  ASSERT_FALSE(elf.GetGlobalVariableOffset(global, &offset));
 }
 
 TEST_F(ElfTest, get_global_valid_not_in_interface) {
@@ -358,119 +362,69 @@
   ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
   elf.FakeSetInterface(interface);
 
-  uint64_t offset;
   std::string global("something");
-  EXPECT_CALL(*interface, GetGlobalVariable(global, &offset)).WillOnce(::testing::Return(false));
+  EXPECT_CALL(*interface, GetGlobalVariable(global, ::testing::_))
+      .WillOnce(::testing::Return(false));
 
-  ASSERT_FALSE(elf.GetGlobalVariable(global, &offset));
+  uint64_t offset;
+  ASSERT_FALSE(elf.GetGlobalVariableOffset(global, &offset));
 }
 
-TEST_F(ElfTest, get_global_valid_below_load_bias) {
+TEST_F(ElfTest, get_global_vaddr_in_no_sections) {
   ElfFake elf(memory_);
   elf.FakeSetValid(true);
-  elf.FakeSetLoadBias(0x1000);
 
   ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
   elf.FakeSetInterface(interface);
 
-  uint64_t offset;
   std::string global("something");
-  EXPECT_CALL(*interface, GetGlobalVariable(global, &offset))
+  EXPECT_CALL(*interface, GetGlobalVariable(global, ::testing::_))
       .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x300), ::testing::Return(true)));
 
-  ASSERT_FALSE(elf.GetGlobalVariable(global, &offset));
-}
-
-TEST_F(ElfTest, get_global_valid_dynamic_zero_non_zero_load_bias) {
-  ElfFake elf(memory_);
-  elf.FakeSetValid(true);
-  elf.FakeSetLoadBias(0x100);
-
-  ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
-  elf.FakeSetInterface(interface);
-
   uint64_t offset;
-  std::string global("something");
-  EXPECT_CALL(*interface, GetGlobalVariable(global, &offset))
-      .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x300), ::testing::Return(true)));
-
-  ASSERT_TRUE(elf.GetGlobalVariable(global, &offset));
-  EXPECT_EQ(0x200U, offset);
+  ASSERT_FALSE(elf.GetGlobalVariableOffset(global, &offset));
 }
 
-TEST_F(ElfTest, get_global_valid_dynamic_zero) {
+TEST_F(ElfTest, get_global_vaddr_in_data_section) {
   ElfFake elf(memory_);
   elf.FakeSetValid(true);
 
   ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
   elf.FakeSetInterface(interface);
+  interface->MockSetDataVaddrStart(0x500);
+  interface->MockSetDataVaddrEnd(0x600);
+  interface->MockSetDataOffset(0xa000);
 
-  ElfInterfaceMock* gnu_interface = new ElfInterfaceMock(memory_);
-  elf.FakeSetGnuDebugdataInterface(gnu_interface);
+  std::string global("something");
+  EXPECT_CALL(*interface, GetGlobalVariable(global, ::testing::_))
+      .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x580), ::testing::Return(true)));
 
   uint64_t offset;
-  std::string global("something");
-  EXPECT_CALL(*interface, GetGlobalVariable(global, &offset)).WillOnce(::testing::Return(false));
-
-  EXPECT_CALL(*gnu_interface, GetGlobalVariable(global, &offset))
-      .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x500), ::testing::Return(true)));
-
-  ASSERT_TRUE(elf.GetGlobalVariable(global, &offset));
-  EXPECT_EQ(0x500U, offset);
+  ASSERT_TRUE(elf.GetGlobalVariableOffset(global, &offset));
+  EXPECT_EQ(0xa080U, offset);
 }
 
-TEST_F(ElfTest, get_global_valid_in_gnu_debugdata_dynamic_zero) {
+TEST_F(ElfTest, get_global_vaddr_in_dynamic_section) {
   ElfFake elf(memory_);
   elf.FakeSetValid(true);
 
   ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
   elf.FakeSetInterface(interface);
+  interface->MockSetDataVaddrStart(0x500);
+  interface->MockSetDataVaddrEnd(0x600);
+  interface->MockSetDataOffset(0xa000);
+
+  interface->MockSetDynamicVaddrStart(0x800);
+  interface->MockSetDynamicVaddrEnd(0x900);
+  interface->MockSetDynamicOffset(0xc000);
+
+  std::string global("something");
+  EXPECT_CALL(*interface, GetGlobalVariable(global, ::testing::_))
+      .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x880), ::testing::Return(true)));
 
   uint64_t offset;
-  std::string global("something");
-  EXPECT_CALL(*interface, GetGlobalVariable(global, &offset))
-      .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x300), ::testing::Return(true)));
-
-  ASSERT_TRUE(elf.GetGlobalVariable(global, &offset));
-  EXPECT_EQ(0x300U, offset);
-}
-
-TEST_F(ElfTest, get_global_valid_dynamic_adjust_negative) {
-  ElfFake elf(memory_);
-  elf.FakeSetValid(true);
-
-  ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
-  interface->MockSetDynamicOffset(0x400);
-  interface->MockSetDynamicVaddr(0x800);
-  interface->MockSetDynamicSize(0x100);
-  elf.FakeSetInterface(interface);
-
-  uint64_t offset;
-  std::string global("something");
-  EXPECT_CALL(*interface, GetGlobalVariable(global, &offset))
-      .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x850), ::testing::Return(true)));
-
-  ASSERT_TRUE(elf.GetGlobalVariable(global, &offset));
-  EXPECT_EQ(0x450U, offset);
-}
-
-TEST_F(ElfTest, get_global_valid_dynamic_adjust_positive) {
-  ElfFake elf(memory_);
-  elf.FakeSetValid(true);
-
-  ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
-  interface->MockSetDynamicOffset(0x1000);
-  interface->MockSetDynamicVaddr(0x800);
-  interface->MockSetDynamicSize(0x100);
-  elf.FakeSetInterface(interface);
-
-  uint64_t offset;
-  std::string global("something");
-  EXPECT_CALL(*interface, GetGlobalVariable(global, &offset))
-      .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x850), ::testing::Return(true)));
-
-  ASSERT_TRUE(elf.GetGlobalVariable(global, &offset));
-  EXPECT_EQ(0x1050U, offset);
+  ASSERT_TRUE(elf.GetGlobalVariableOffset(global, &offset));
+  EXPECT_EQ(0xc080U, offset);
 }
 
 TEST_F(ElfTest, is_valid_pc_elf_invalid) {
diff --git a/libunwindstack/tests/JitDebugTest.cpp b/libunwindstack/tests/JitDebugTest.cpp
index b1ca111..9b32a3a 100644
--- a/libunwindstack/tests/JitDebugTest.cpp
+++ b/libunwindstack/tests/JitDebugTest.cpp
@@ -35,13 +35,17 @@
 
 class JitDebugTest : public ::testing::Test {
  protected:
-  void CreateFakeElf(MapInfo* map_info) {
+  void CreateFakeElf(MapInfo* map_info, uint64_t global_offset, uint64_t data_offset,
+                     uint64_t data_vaddr, uint64_t data_size) {
     MemoryFake* memory = new MemoryFake;
     ElfFake* elf = new ElfFake(memory);
     elf->FakeSetValid(true);
     ElfInterfaceFake* interface = new ElfInterfaceFake(memory);
     elf->FakeSetInterface(interface);
-    interface->FakeSetGlobalVariable("__jit_debug_descriptor", 0x800);
+    interface->FakeSetGlobalVariable("__jit_debug_descriptor", global_offset);
+    interface->FakeSetDataOffset(data_offset);
+    interface->FakeSetDataVaddrStart(data_vaddr);
+    interface->FakeSetDataVaddrEnd(data_vaddr + data_size);
     map_info->elf.reset(elf);
   }
 
@@ -52,27 +56,27 @@
     maps_.reset(
         new BufferMaps("1000-4000 ---s 00000000 00:00 0 /fake/elf1\n"
                        "4000-6000 r--s 00000000 00:00 0 /fake/elf1\n"
-                       "6000-8000 -wxs 00000000 00:00 0 /fake/elf1\n"
+                       "6000-8000 -wxs 00002000 00:00 0 /fake/elf1\n"
                        "a000-c000 --xp 00000000 00:00 0 /fake/elf2\n"
-                       "c000-f000 rw-p 00001000 00:00 0 /fake/elf2\n"
+                       "c000-f000 rw-p 00002000 00:00 0 /fake/elf2\n"
                        "f000-11000 r--p 00000000 00:00 0 /fake/elf3\n"
-                       "11000-12000 rw-p 00001000 00:00 0 /fake/elf3\n"
+                       "11000-12000 rw-p 00002000 00:00 0 /fake/elf3\n"
                        "12000-14000 r--p 00000000 00:00 0 /fake/elf4\n"
-                       "100000-110000 rw-p 0001000 00:00 0 /fake/elf4\n"
-                       "200000-210000 rw-p 0002000 00:00 0 /fake/elf4\n"));
+                       "100000-110000 rw-p 00ee000 00:00 0 /fake/elf4\n"
+                       "200000-210000 rw-p 01ee000 00:00 0 /fake/elf4\n"));
     ASSERT_TRUE(maps_->Parse());
 
     MapInfo* map_info = maps_->Get(3);
     ASSERT_TRUE(map_info != nullptr);
-    CreateFakeElf(map_info);
+    CreateFakeElf(map_info, 0x2800, 0x2000, 0x2000, 0x3000);
 
     map_info = maps_->Get(5);
     ASSERT_TRUE(map_info != nullptr);
-    CreateFakeElf(map_info);
+    CreateFakeElf(map_info, 0x2800, 0x2000, 0x2000, 0x3000);
 
     map_info = maps_->Get(7);
     ASSERT_TRUE(map_info != nullptr);
-    CreateFakeElf(map_info);
+    CreateFakeElf(map_info, 0xee800, 0xee000, 0xee000, 0x10000);
   }
 
   void SetUp() override {
@@ -258,7 +262,7 @@
 TEST_F(JitDebugTest, get_elf_no_valid_code_entry) {
   CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
 
-  WriteDescriptor32(0xf800, 0x200000);
+  WriteDescriptor32(0x11800, 0x200000);
 
   Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
   ASSERT_TRUE(elf == nullptr);
@@ -267,7 +271,7 @@
 TEST_F(JitDebugTest, get_elf_invalid_descriptor_first_entry) {
   CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
 
-  WriteDescriptor32(0xf800, 0);
+  WriteDescriptor32(0x11800, 0);
 
   Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
   ASSERT_TRUE(elf == nullptr);
@@ -276,9 +280,9 @@
 TEST_F(JitDebugTest, get_elf_invalid_descriptor_version) {
   CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
 
-  WriteDescriptor32(0xf800, 0x20000);
+  WriteDescriptor32(0x11800, 0x20000);
   // Set the version to an invalid value.
-  memory_->SetData32(0xf800, 2);
+  memory_->SetData32(0x11800, 2);
 
   Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
   ASSERT_TRUE(elf == nullptr);
@@ -287,7 +291,7 @@
 TEST_F(JitDebugTest, get_elf_32) {
   CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
 
-  WriteDescriptor32(0xf800, 0x200000);
+  WriteDescriptor32(0x11800, 0x200000);
   WriteEntry32Pad(0x200000, 0, 0, 0x4000, 0x1000);
 
   Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
@@ -304,16 +308,16 @@
   CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
   CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x5000, ELFCLASS32, EM_ARM, 0x2000, 0x300);
 
-  WriteDescriptor32(0xf800, 0x200000);
+  WriteDescriptor32(0x11800, 0x200000);
   WriteEntry32Pad(0x200000, 0, 0, 0x4000, 0x1000);
-  WriteDescriptor32(0x12800, 0x201000);
+  WriteDescriptor32(0x100800, 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);
 
   // Now clear the descriptor entry for the first one.
-  WriteDescriptor32(0xf800, 0);
+  WriteDescriptor32(0x11800, 0);
   jit_debug_.reset(new JitDebug(process_memory_));
   jit_debug_->SetArch(ARCH_ARM);
 
@@ -326,7 +330,7 @@
 
   CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
 
-  WriteDescriptor32(0xf800, 0x200000);
+  WriteDescriptor32(0x11800, 0x200000);
   WriteEntry32Pack(0x200000, 0, 0, 0x4000, 0x1000);
 
   jit_debug_->SetArch(ARCH_X86);
@@ -345,7 +349,7 @@
 
   CreateElf<Elf64_Ehdr, Elf64_Shdr>(0x4000, ELFCLASS64, EM_AARCH64, 0x1500, 0x200);
 
-  WriteDescriptor64(0xf800, 0x200000);
+  WriteDescriptor64(0x11800, 0x200000);
   WriteEntry64(0x200000, 0, 0, 0x4000, 0x1000);
 
   Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
@@ -362,7 +366,7 @@
   CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
   CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x5000, ELFCLASS32, EM_ARM, 0x2300, 0x400);
 
-  WriteDescriptor32(0xf800, 0x200000);
+  WriteDescriptor32(0x11800, 0x200000);
   WriteEntry32Pad(0x200000, 0, 0x200100, 0x4000, 0x1000);
   WriteEntry32Pad(0x200100, 0x200100, 0, 0x5000, 0x1000);
 
@@ -385,7 +389,7 @@
 TEST_F(JitDebugTest, get_elf_search_libs) {
   CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
 
-  WriteDescriptor32(0xf800, 0x200000);
+  WriteDescriptor32(0x11800, 0x200000);
   WriteEntry32Pad(0x200000, 0, 0, 0x4000, 0x1000);
 
   // Only search a given named list of libs.
diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/maps.txt b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/maps.txt
index 5657373..1ff12db 100644
--- a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/maps.txt
+++ b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/maps.txt
@@ -1,4 +1,4 @@
 d0250000-d2600000 r-xp 0 00:00 0 <anonymous:d0250000>
 e466e000-e4ae8000 r-xp 0 00:00 0 libart.so
-e4ae8000-e4ae9000 rw-p 1000 00:00 0 libart.so
+e4af1000-e4af2000 rw-p 482000 00:00 0 libart.so
 e7d91000-e7e31000 r-xp 0 00:00 0 libc.so
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt b/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt
index 4043122..3b87f2f 100644
--- a/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt
+++ b/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt
@@ -4,8 +4,8 @@
 e0447000-e0448000 r-xp 2000 00:00 0   137-cfi.odex
 e2796000-e4796000 r-xp 0 00:00 0   anonymous:e2796000
 e648e000-e690f000 r-xp 0 00:00 0  libart.so
-e690f000-e6910000 rw-p 1000 00:00 0  libart.so
+e6918000-e6919000 rw-p 489000 00:00 0  libart.so
 ed306000-ed801000 r-xp 0 00:00 0   libartd.so
-ed801000-ed802000 rw-p 1000 00:00 0   libartd.so
+ed80a000-ed80b000 rw-p 503000 00:00 0   libartd.so
 eda88000-edb23000 r-xp 0 00:00 0   libc.so
 ede4e000-ede50000 r-xp 0 00:00 0   anonymous:ede4e000
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/maps.txt b/libunwindstack/tests/files/offline/jit_debug_x86/maps.txt
index f255a44..c22b5de 100644
--- a/libunwindstack/tests/files/offline/jit_debug_x86/maps.txt
+++ b/libunwindstack/tests/files/offline/jit_debug_x86/maps.txt
@@ -4,5 +4,5 @@
 ec606000-ec607000 r-xp 2000 00:00 0   137-cfi.odex
 ee74c000-f074c000 r-xp 0 00:00 0   anonymous:ee74c000
 f6be1000-f732b000 r-xp 0 00:00 0   libartd.so
-f732b000-f732c000 rw-p 1000 00:00 0   libartd.so
+f7334000-f7335000 rw-p 752000 00:00 0   libartd.so
 f734b000-f74fc000 r-xp 0 00:00 0   libc.so