Handle when bias is different in elf headers.

The original code assumed that the load bias in the program headers
would be exactly the same as in eh_frame/eh_frame_hdr/debug_frame.

This isn't guaranteed, so add a section bias for use when creating
a DwarfSection. In addtion, make the load bias and section bias
a signed value. There is no reason that this value needs to be positive,
so don't force it to be.

Add a new offline test that has a different load bias in eh_frame than
in the executable load.

Add additional unit tests to verify the load bias values are set properly.

Clean up the tests in ElfInterfaceTest, making all tests names follow the
same convention.

Bug: 141888859
Bug: 142094469

Test: New units and old unit tests pass on host and taimen.
Change-Id: Ib878123ab5545f0f315c749cfe0d27b012d873ee
diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp
index be1f092..e34273c 100644
--- a/libunwindstack/ElfInterface.cpp
+++ b/libunwindstack/ElfInterface.cpp
@@ -124,10 +124,10 @@
 }
 
 template <typename AddressType>
-void ElfInterface::InitHeadersWithTemplate(uint64_t load_bias) {
+void ElfInterface::InitHeadersWithTemplate() {
   if (eh_frame_hdr_offset_ != 0) {
     eh_frame_.reset(new DwarfEhFrameWithHdr<AddressType>(memory_));
-    if (!eh_frame_->Init(eh_frame_hdr_offset_, eh_frame_hdr_size_, load_bias)) {
+    if (!eh_frame_->Init(eh_frame_hdr_offset_, eh_frame_hdr_size_, eh_frame_hdr_section_bias_)) {
       eh_frame_.reset(nullptr);
     }
   }
@@ -136,21 +136,23 @@
     // If there is an eh_frame section without an eh_frame_hdr section,
     // or using the frame hdr object failed to init.
     eh_frame_.reset(new DwarfEhFrame<AddressType>(memory_));
-    if (!eh_frame_->Init(eh_frame_offset_, eh_frame_size_, load_bias)) {
+    if (!eh_frame_->Init(eh_frame_offset_, eh_frame_size_, eh_frame_section_bias_)) {
       eh_frame_.reset(nullptr);
     }
   }
 
   if (eh_frame_.get() == nullptr) {
     eh_frame_hdr_offset_ = 0;
+    eh_frame_hdr_section_bias_ = 0;
     eh_frame_hdr_size_ = static_cast<uint64_t>(-1);
     eh_frame_offset_ = 0;
+    eh_frame_section_bias_ = 0;
     eh_frame_size_ = static_cast<uint64_t>(-1);
   }
 
   if (debug_frame_offset_ != 0) {
     debug_frame_.reset(new DwarfDebugFrame<AddressType>(memory_));
-    if (!debug_frame_->Init(debug_frame_offset_, debug_frame_size_, load_bias)) {
+    if (!debug_frame_->Init(debug_frame_offset_, debug_frame_size_, debug_frame_section_bias_)) {
       debug_frame_.reset(nullptr);
       debug_frame_offset_ = 0;
       debug_frame_size_ = static_cast<uint64_t>(-1);
@@ -159,7 +161,7 @@
 }
 
 template <typename EhdrType, typename PhdrType, typename ShdrType>
-bool ElfInterface::ReadAllHeaders(uint64_t* load_bias) {
+bool ElfInterface::ReadAllHeaders(int64_t* load_bias) {
   EhdrType ehdr;
   if (!memory_->ReadFully(0, &ehdr, sizeof(ehdr))) {
     last_error_.code = ERROR_MEMORY_INVALID;
@@ -175,7 +177,7 @@
 }
 
 template <typename EhdrType, typename PhdrType>
-uint64_t ElfInterface::GetLoadBias(Memory* memory) {
+int64_t ElfInterface::GetLoadBias(Memory* memory) {
   EhdrType ehdr;
   if (!memory->ReadFully(0, &ehdr, sizeof(ehdr))) {
     return false;
@@ -190,17 +192,14 @@
 
     // Find the first executable load when looking for the load bias.
     if (phdr.p_type == PT_LOAD && (phdr.p_flags & PF_X)) {
-      if (phdr.p_vaddr > phdr.p_offset) {
-        return phdr.p_vaddr - phdr.p_offset;
-      }
-      break;
+      return static_cast<uint64_t>(phdr.p_vaddr) - phdr.p_offset;
     }
   }
   return 0;
 }
 
 template <typename EhdrType, typename PhdrType>
-void ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias) {
+void ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, int64_t* load_bias) {
   uint64_t offset = ehdr.e_phoff;
   bool first_exec_load_header = true;
   for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) {
@@ -219,8 +218,8 @@
       pt_loads_[phdr.p_offset] = LoadInfo{phdr.p_offset, phdr.p_vaddr,
                                           static_cast<size_t>(phdr.p_memsz)};
       // Only set the load bias from the first executable load header.
-      if (first_exec_load_header && phdr.p_vaddr > phdr.p_offset) {
-        *load_bias = phdr.p_vaddr - phdr.p_offset;
+      if (first_exec_load_header) {
+        *load_bias = static_cast<uint64_t>(phdr.p_vaddr) - phdr.p_offset;
       }
       first_exec_load_header = false;
       break;
@@ -229,6 +228,7 @@
     case PT_GNU_EH_FRAME:
       // This is really the pointer to the .eh_frame_hdr section.
       eh_frame_hdr_offset_ = phdr.p_offset;
+      eh_frame_hdr_section_bias_ = static_cast<uint64_t>(phdr.p_paddr) - phdr.p_offset;
       eh_frame_hdr_size_ = phdr.p_memsz;
       break;
 
@@ -343,24 +343,21 @@
       if (shdr.sh_name < sec_size) {
         std::string name;
         if (memory_->ReadString(sec_offset + shdr.sh_name, &name)) {
-          uint64_t* offset_ptr = nullptr;
-          uint64_t* size_ptr = nullptr;
           if (name == ".debug_frame") {
-            offset_ptr = &debug_frame_offset_;
-            size_ptr = &debug_frame_size_;
+            debug_frame_offset_ = shdr.sh_offset;
+            debug_frame_size_ = shdr.sh_size;
+            debug_frame_section_bias_ = static_cast<uint64_t>(shdr.sh_addr) - shdr.sh_offset;
           } else if (name == ".gnu_debugdata") {
-            offset_ptr = &gnu_debugdata_offset_;
-            size_ptr = &gnu_debugdata_size_;
+            gnu_debugdata_offset_ = shdr.sh_offset;
+            gnu_debugdata_size_ = shdr.sh_size;
           } else if (name == ".eh_frame") {
-            offset_ptr = &eh_frame_offset_;
-            size_ptr = &eh_frame_size_;
+            eh_frame_offset_ = shdr.sh_offset;
+            eh_frame_section_bias_ = static_cast<uint64_t>(shdr.sh_addr) - shdr.sh_offset;
+            eh_frame_size_ = shdr.sh_size;
           } else if (eh_frame_hdr_offset_ == 0 && name == ".eh_frame_hdr") {
-            offset_ptr = &eh_frame_hdr_offset_;
-            size_ptr = &eh_frame_hdr_size_;
-          }
-          if (offset_ptr != nullptr) {
-            *offset_ptr = shdr.sh_offset;
-            *size_ptr = shdr.sh_size;
+            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;
           }
         }
       }
@@ -642,16 +639,14 @@
 }
 
 // Instantiate all of the needed template functions.
-template void ElfInterface::InitHeadersWithTemplate<uint32_t>(uint64_t);
-template void ElfInterface::InitHeadersWithTemplate<uint64_t>(uint64_t);
+template void ElfInterface::InitHeadersWithTemplate<uint32_t>();
+template void ElfInterface::InitHeadersWithTemplate<uint64_t>();
 
-template bool ElfInterface::ReadAllHeaders<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(uint64_t*);
-template bool ElfInterface::ReadAllHeaders<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(uint64_t*);
+template bool ElfInterface::ReadAllHeaders<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(int64_t*);
+template bool ElfInterface::ReadAllHeaders<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(int64_t*);
 
-template void ElfInterface::ReadProgramHeaders<Elf32_Ehdr, Elf32_Phdr>(const Elf32_Ehdr&,
-                                                                       uint64_t*);
-template void ElfInterface::ReadProgramHeaders<Elf64_Ehdr, Elf64_Phdr>(const Elf64_Ehdr&,
-                                                                       uint64_t*);
+template void ElfInterface::ReadProgramHeaders<Elf32_Ehdr, Elf32_Phdr>(const Elf32_Ehdr&, int64_t*);
+template void ElfInterface::ReadProgramHeaders<Elf64_Ehdr, Elf64_Phdr>(const Elf64_Ehdr&, int64_t*);
 
 template void ElfInterface::ReadSectionHeaders<Elf32_Ehdr, Elf32_Shdr>(const Elf32_Ehdr&);
 template void ElfInterface::ReadSectionHeaders<Elf64_Ehdr, Elf64_Shdr>(const Elf64_Ehdr&);
@@ -673,8 +668,8 @@
 template void ElfInterface::GetMaxSizeWithTemplate<Elf32_Ehdr>(Memory*, uint64_t*);
 template void ElfInterface::GetMaxSizeWithTemplate<Elf64_Ehdr>(Memory*, uint64_t*);
 
-template uint64_t ElfInterface::GetLoadBias<Elf32_Ehdr, Elf32_Phdr>(Memory*);
-template uint64_t ElfInterface::GetLoadBias<Elf64_Ehdr, Elf64_Phdr>(Memory*);
+template int64_t ElfInterface::GetLoadBias<Elf32_Ehdr, Elf32_Phdr>(Memory*);
+template int64_t ElfInterface::GetLoadBias<Elf64_Ehdr, Elf64_Phdr>(Memory*);
 
 template std::string ElfInterface::ReadBuildIDFromMemory<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr>(
     Memory*);