Merge "init: create android::init:: namespace"
diff --git a/libsysutils/src/FrameworkListener.cpp b/libsysutils/src/FrameworkListener.cpp
index 1b6076f..6f76e76 100644
--- a/libsysutils/src/FrameworkListener.cpp
+++ b/libsysutils/src/FrameworkListener.cpp
@@ -68,7 +68,7 @@
         android_errorWriteLog(0x534e4554, "29831647");
         c->sendMsg(500, "Command too large for buffer", false);
         mSkipToNextNullByte = true;
-        return false;
+        return true;
     }
 
     int offset = 0;
diff --git a/libunwindstack/Elf.h b/libunwindstack/Elf.h
index 7bf45b8..f9db541 100644
--- a/libunwindstack/Elf.h
+++ b/libunwindstack/Elf.h
@@ -45,8 +45,8 @@
     return valid_ && interface_->GetSoname(name);
   }
 
-  bool GetFunctionName(uint64_t, std::string*, uint64_t*) {
-    return false;
+  bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) {
+    return valid_ && interface_->GetFunctionName(addr, name, func_offset);
   }
 
   bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory) {
diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp
index bfa7944..3a7f7cb 100644
--- a/libunwindstack/ElfInterface.cpp
+++ b/libunwindstack/ElfInterface.cpp
@@ -22,9 +22,18 @@
 
 #include "DwarfDebugFrame.h"
 #include "DwarfEhFrame.h"
+#include "DwarfSection.h"
 #include "ElfInterface.h"
+#include "Log.h"
 #include "Memory.h"
 #include "Regs.h"
+#include "Symbols.h"
+
+ElfInterface::~ElfInterface() {
+  for (auto symbol : symbols_) {
+    delete symbol;
+  }
+}
 
 template <typename AddressType>
 void ElfInterface::InitHeadersWithTemplate() {
@@ -57,7 +66,13 @@
   if (!ReadProgramHeaders<EhdrType, PhdrType>(ehdr)) {
     return false;
   }
-  return ReadSectionHeaders<EhdrType, ShdrType>(ehdr);
+
+  // We could still potentially unwind without the section header
+  // information, so ignore any errors.
+  if (!ReadSectionHeaders<EhdrType, ShdrType>(ehdr)) {
+    log(0, "Malformed section header found, ignoring...");
+  }
+  return true;
 }
 
 template <typename EhdrType, typename PhdrType>
@@ -147,12 +162,39 @@
   }
 
   // Skip the first header, it's always going to be NULL.
+  offset += ehdr.e_shentsize;
   for (size_t i = 1; i < ehdr.e_shnum; i++, offset += ehdr.e_shentsize) {
     if (!memory_->ReadField(offset, &shdr, &shdr.sh_type, sizeof(shdr.sh_type))) {
       return false;
     }
 
-    if (shdr.sh_type == SHT_PROGBITS) {
+    if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
+      if (!memory_->Read(offset, &shdr, sizeof(shdr))) {
+        return false;
+      }
+      // Need to go get the information about the section that contains
+      // the string terminated names.
+      ShdrType str_shdr;
+      if (shdr.sh_link >= ehdr.e_shnum) {
+        return false;
+      }
+      uint64_t str_offset = ehdr.e_shoff + shdr.sh_link * ehdr.e_shentsize;
+      if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_type, sizeof(str_shdr.sh_type))) {
+        return false;
+      }
+      if (str_shdr.sh_type != SHT_STRTAB) {
+        return false;
+      }
+      if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_offset,
+                              sizeof(str_shdr.sh_offset))) {
+        return false;
+      }
+      if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_size, sizeof(str_shdr.sh_size))) {
+        return false;
+      }
+      symbols_.push_back(new Symbols(shdr.sh_offset, shdr.sh_size, shdr.sh_entsize,
+                                     str_shdr.sh_offset, str_shdr.sh_size));
+    } else if (shdr.sh_type == SHT_PROGBITS && sec_size != 0) {
       // Look for the .debug_frame and .gnu_debugdata.
       if (!memory_->ReadField(offset, &shdr, &shdr.sh_name, sizeof(shdr.sh_name))) {
         return false;
@@ -160,18 +202,20 @@
       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") {
-            if (memory_->ReadField(offset, &shdr, &shdr.sh_offset, sizeof(shdr.sh_offset)) &&
-                memory_->ReadField(offset, &shdr, &shdr.sh_size, sizeof(shdr.sh_size))) {
-              debug_frame_offset_ = shdr.sh_offset;
-              debug_frame_size_ = shdr.sh_size;
-            }
+            offset_ptr = &debug_frame_offset_;
+            size_ptr = &debug_frame_size_;
           } else if (name == ".gnu_debugdata") {
-            if (memory_->ReadField(offset, &shdr, &shdr.sh_offset, sizeof(shdr.sh_offset)) &&
-                memory_->ReadField(offset, &shdr, &shdr.sh_size, sizeof(shdr.sh_size))) {
-              gnu_debugdata_offset_ = shdr.sh_offset;
-              gnu_debugdata_size_ = shdr.sh_size;
-            }
+            offset_ptr = &gnu_debugdata_offset_;
+            size_ptr = &gnu_debugdata_size_;
+          }
+          if (offset_ptr != nullptr &&
+              memory_->ReadField(offset, &shdr, &shdr.sh_offset, sizeof(shdr.sh_offset)) &&
+              memory_->ReadField(offset, &shdr, &shdr.sh_size, sizeof(shdr.sh_size))) {
+            *offset_ptr = shdr.sh_offset;
+            *size_ptr = shdr.sh_size;
           }
         }
       }
@@ -228,7 +272,40 @@
   return true;
 }
 
-bool ElfInterface::Step(uint64_t, Regs*, Memory*) {
+template <typename SymType>
+bool ElfInterface::GetFunctionNameWithTemplate(uint64_t addr, std::string* name,
+                                               uint64_t* func_offset) {
+  if (symbols_.empty()) {
+    return false;
+  }
+
+  for (const auto symbol : symbols_) {
+    if (symbol->GetName<SymType>(addr, load_bias_, memory_, name, func_offset)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool ElfInterface::Step(uint64_t pc, Regs* regs, Memory* process_memory) {
+  // Need to subtract off the load_bias to get the correct pc.
+  if (pc < load_bias_) {
+    return false;
+  }
+  pc -= load_bias_;
+
+  // Try the eh_frame first.
+  DwarfSection* eh_frame = eh_frame_.get();
+  if (eh_frame != nullptr && eh_frame->Step(pc, regs, process_memory)) {
+    return true;
+  }
+
+  // Try the debug_frame next.
+  DwarfSection* debug_frame = debug_frame_.get();
+  if (debug_frame != nullptr && debug_frame->Step(pc, regs, process_memory)) {
+    return true;
+  }
+
   return false;
 }
 
@@ -247,3 +324,8 @@
 
 template bool ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(std::string*);
 template bool ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(std::string*);
+
+template bool ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(uint64_t, std::string*,
+                                                                   uint64_t*);
+template bool ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(uint64_t, std::string*,
+                                                                   uint64_t*);
diff --git a/libunwindstack/ElfInterface.h b/libunwindstack/ElfInterface.h
index 1cc8aa0..d0d0d28 100644
--- a/libunwindstack/ElfInterface.h
+++ b/libunwindstack/ElfInterface.h
@@ -30,6 +30,7 @@
 // Forward declarations.
 class Memory;
 class Regs;
+class Symbols;
 
 struct LoadInfo {
   uint64_t offset;
@@ -46,7 +47,7 @@
 class ElfInterface {
  public:
   ElfInterface(Memory* memory) : memory_(memory) {}
-  virtual ~ElfInterface() = default;
+  virtual ~ElfInterface();
 
   virtual bool Init() = 0;
 
@@ -94,6 +95,9 @@
   template <typename DynType>
   bool GetSonameWithTemplate(std::string* soname);
 
+  template <typename SymType>
+  bool GetFunctionNameWithTemplate(uint64_t addr, std::string* name, uint64_t* func_offset);
+
   virtual bool HandleType(uint64_t, uint32_t) { return false; }
 
   Memory* memory_;
@@ -118,6 +122,8 @@
 
   std::unique_ptr<DwarfSection> eh_frame_;
   std::unique_ptr<DwarfSection> debug_frame_;
+
+  std::vector<Symbols*> symbols_;
 };
 
 class ElfInterface32 : public ElfInterface {
@@ -135,8 +141,8 @@
     return ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(soname);
   }
 
-  bool GetFunctionName(uint64_t, std::string*, uint64_t*) override {
-    return false;
+  bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) override {
+    return ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(addr, name, func_offset);
   }
 };
 
@@ -155,8 +161,8 @@
     return ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(soname);
   }
 
-  bool GetFunctionName(uint64_t, std::string*, uint64_t*) override {
-    return false;
+  bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) override {
+    return ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(addr, name, func_offset);
   }
 };
 
diff --git a/libunwindstack/tests/ElfInterfaceTest.cpp b/libunwindstack/tests/ElfInterfaceTest.cpp
index 81cdaf5..0f56ba8 100644
--- a/libunwindstack/tests/ElfInterfaceTest.cpp
+++ b/libunwindstack/tests/ElfInterfaceTest.cpp
@@ -79,9 +79,37 @@
   template <typename ElfType>
   void InitHeadersDebugFrameFail();
 
+  template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
+  void InitSectionHeadersMalformed();
+
+  template <typename Ehdr, typename Shdr, typename Sym, typename ElfInterfaceType>
+  void InitSectionHeaders(uint64_t entry_size);
+
+  template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
+  void InitSectionHeadersOffsets();
+
+  template <typename Sym>
+  void InitSym(uint64_t offset, uint32_t value, uint32_t size, uint32_t name_offset,
+               uint64_t sym_offset, const char* name);
+
   MemoryFake memory_;
 };
 
+template <typename Sym>
+void ElfInterfaceTest::InitSym(uint64_t offset, uint32_t value, uint32_t size, uint32_t name_offset,
+                               uint64_t sym_offset, const char* name) {
+  Sym sym;
+  memset(&sym, 0, sizeof(sym));
+  sym.st_info = STT_FUNC;
+  sym.st_value = value;
+  sym.st_size = size;
+  sym.st_name = name_offset;
+  sym.st_shndx = SHN_COMMON;
+
+  memory_.SetMemory(offset, &sym, sizeof(sym));
+  memory_.SetMemory(sym_offset + name_offset, name, strlen(name) + 1);
+}
+
 template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType>
 void ElfInterfaceTest::SinglePtLoad() {
   std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));
@@ -718,3 +746,178 @@
 TEST_F(ElfInterfaceTest, init_headers_debug_frame64_fail) {
   InitHeadersDebugFrameFail<MockElfInterface64>();
 }
+
+template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
+void ElfInterfaceTest::InitSectionHeadersMalformed() {
+  std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
+
+  Ehdr ehdr;
+  memset(&ehdr, 0, sizeof(ehdr));
+  ehdr.e_shoff = 0x1000;
+  ehdr.e_shnum = 10;
+  ehdr.e_shentsize = sizeof(Shdr);
+  memory_.SetMemory(0, &ehdr, sizeof(ehdr));
+
+  ASSERT_TRUE(elf->Init());
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_malformed32) {
+  InitSectionHeadersMalformed<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>();
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_malformed64) {
+  InitSectionHeadersMalformed<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>();
+}
+
+template <typename Ehdr, typename Shdr, typename Sym, typename ElfInterfaceType>
+void ElfInterfaceTest::InitSectionHeaders(uint64_t entry_size) {
+  std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
+
+  uint64_t offset = 0x1000;
+
+  Ehdr ehdr;
+  memset(&ehdr, 0, sizeof(ehdr));
+  ehdr.e_shoff = offset;
+  ehdr.e_shnum = 10;
+  ehdr.e_shentsize = entry_size;
+  memory_.SetMemory(0, &ehdr, sizeof(ehdr));
+
+  offset += ehdr.e_shentsize;
+
+  Shdr shdr;
+  memset(&shdr, 0, sizeof(shdr));
+  shdr.sh_type = SHT_SYMTAB;
+  shdr.sh_link = 4;
+  shdr.sh_addr = 0x5000;
+  shdr.sh_offset = 0x5000;
+  shdr.sh_entsize = sizeof(Sym);
+  shdr.sh_size = shdr.sh_entsize * 10;
+  memory_.SetMemory(offset, &shdr, sizeof(shdr));
+  offset += ehdr.e_shentsize;
+
+  memset(&shdr, 0, sizeof(shdr));
+  shdr.sh_type = SHT_DYNSYM;
+  shdr.sh_link = 4;
+  shdr.sh_addr = 0x6000;
+  shdr.sh_offset = 0x6000;
+  shdr.sh_entsize = sizeof(Sym);
+  shdr.sh_size = shdr.sh_entsize * 10;
+  memory_.SetMemory(offset, &shdr, sizeof(shdr));
+  offset += ehdr.e_shentsize;
+
+  memset(&shdr, 0, sizeof(shdr));
+  shdr.sh_type = SHT_PROGBITS;
+  shdr.sh_name = 0xa000;
+  memory_.SetMemory(offset, &shdr, sizeof(shdr));
+  offset += ehdr.e_shentsize;
+
+  // The string data for the entries.
+  memset(&shdr, 0, sizeof(shdr));
+  shdr.sh_type = SHT_STRTAB;
+  shdr.sh_name = 0x20000;
+  shdr.sh_offset = 0xf000;
+  shdr.sh_size = 0x1000;
+  memory_.SetMemory(offset, &shdr, sizeof(shdr));
+  offset += ehdr.e_shentsize;
+
+  InitSym<Sym>(0x5000, 0x90000, 0x1000, 0x100, 0xf000, "function_one");
+  InitSym<Sym>(0x6000, 0xd0000, 0x1000, 0x300, 0xf000, "function_two");
+
+  ASSERT_TRUE(elf->Init());
+  EXPECT_EQ(0U, elf->debug_frame_offset());
+  EXPECT_EQ(0U, elf->debug_frame_size());
+  EXPECT_EQ(0U, elf->gnu_debugdata_offset());
+  EXPECT_EQ(0U, elf->gnu_debugdata_size());
+
+  // Look in the first symbol table.
+  std::string name;
+  uint64_t name_offset;
+  ASSERT_TRUE(elf->GetFunctionName(0x90010, &name, &name_offset));
+  EXPECT_EQ("function_one", name);
+  EXPECT_EQ(16U, name_offset);
+  ASSERT_TRUE(elf->GetFunctionName(0xd0020, &name, &name_offset));
+  EXPECT_EQ("function_two", name);
+  EXPECT_EQ(32U, name_offset);
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers32) {
+  InitSectionHeaders<Elf32_Ehdr, Elf32_Shdr, Elf32_Sym, ElfInterface32>(sizeof(Elf32_Shdr));
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers64) {
+  InitSectionHeaders<Elf64_Ehdr, Elf64_Shdr, Elf64_Sym, ElfInterface64>(sizeof(Elf64_Shdr));
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_non_std_entry_size32) {
+  InitSectionHeaders<Elf32_Ehdr, Elf32_Shdr, Elf32_Sym, ElfInterface32>(0x100);
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_non_std_entry_size64) {
+  InitSectionHeaders<Elf64_Ehdr, Elf64_Shdr, Elf64_Sym, ElfInterface64>(0x100);
+}
+
+template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
+void ElfInterfaceTest::InitSectionHeadersOffsets() {
+  std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
+
+  uint64_t offset = 0x2000;
+
+  Ehdr ehdr;
+  memset(&ehdr, 0, sizeof(ehdr));
+  ehdr.e_shoff = offset;
+  ehdr.e_shnum = 10;
+  ehdr.e_shentsize = sizeof(Shdr);
+  ehdr.e_shstrndx = 2;
+  memory_.SetMemory(0, &ehdr, sizeof(ehdr));
+
+  offset += ehdr.e_shentsize;
+
+  Shdr shdr;
+  memset(&shdr, 0, sizeof(shdr));
+  shdr.sh_type = SHT_PROGBITS;
+  shdr.sh_link = 2;
+  shdr.sh_name = 0x200;
+  shdr.sh_addr = 0x5000;
+  shdr.sh_offset = 0x5000;
+  shdr.sh_entsize = 0x100;
+  shdr.sh_size = 0x800;
+  memory_.SetMemory(offset, &shdr, sizeof(shdr));
+  offset += ehdr.e_shentsize;
+
+  // The string data for section header names.
+  memset(&shdr, 0, sizeof(shdr));
+  shdr.sh_type = SHT_STRTAB;
+  shdr.sh_name = 0x20000;
+  shdr.sh_offset = 0xf000;
+  shdr.sh_size = 0x1000;
+  memory_.SetMemory(offset, &shdr, sizeof(shdr));
+  offset += ehdr.e_shentsize;
+
+  memset(&shdr, 0, sizeof(shdr));
+  shdr.sh_type = SHT_PROGBITS;
+  shdr.sh_link = 2;
+  shdr.sh_name = 0x100;
+  shdr.sh_addr = 0x6000;
+  shdr.sh_offset = 0x6000;
+  shdr.sh_entsize = 0x100;
+  shdr.sh_size = 0x500;
+  memory_.SetMemory(offset, &shdr, sizeof(shdr));
+  offset += ehdr.e_shentsize;
+
+  memory_.SetMemory(0xf100, ".debug_frame", sizeof(".debug_frame"));
+  memory_.SetMemory(0xf200, ".gnu_debugdata", sizeof(".gnu_debugdata"));
+
+  ASSERT_TRUE(elf->Init());
+  EXPECT_EQ(0x6000U, elf->debug_frame_offset());
+  EXPECT_EQ(0x500U, elf->debug_frame_size());
+  EXPECT_EQ(0x5000U, elf->gnu_debugdata_offset());
+  EXPECT_EQ(0x800U, elf->gnu_debugdata_size());
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_offsets32) {
+  InitSectionHeadersOffsets<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>();
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_offsets64) {
+  InitSectionHeadersOffsets<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>();
+}