Add support for the new unwind method.

Also add a comment to the GetElf function to indicate that it never returns
nullptr.

Also needed to add this library to the a million and one places that the vndk
has hard-coded this data.

Bug: 23762183

Test: Built, nothing uses the new code.
Test: However, I did run backtrace_test using this code, and all tests pass.
Change-Id: Ib270665dcb7a7607075e36d88be76dbde6e2faa8
(cherry picked from commit dc4104b720c7fd2014ccfa9fa621d02df58a43c4)
diff --git a/libbacktrace/Android.bp b/libbacktrace/Android.bp
index e02aaf2..c58d777 100644
--- a/libbacktrace/Android.bp
+++ b/libbacktrace/Android.bp
@@ -53,6 +53,8 @@
     "UnwindCurrent.cpp",
     "UnwindMap.cpp",
     "UnwindPtrace.cpp",
+    "UnwindStack.cpp",
+    "UnwindStackMap.cpp",
 ]
 
 cc_library_headers {
@@ -84,6 +86,7 @@
                 "libbase",
                 "liblog",
                 "libunwind",
+                "libunwindstack",
             ],
 
             static_libs: ["libcutils"],
@@ -97,6 +100,7 @@
                 "libbase",
                 "liblog",
                 "libunwind",
+                "libunwindstack",
             ],
 
             static_libs: ["libcutils"],
@@ -108,6 +112,7 @@
                 "libbase",
                 "liblog",
                 "libunwind",
+                "libunwindstack",
             ],
 
             static_libs: ["libasync_safe", "libcutils"],
@@ -130,11 +135,13 @@
         linux: {
             shared_libs: [
                 "libunwind",
+                "libunwindstack",
             ],
         },
         android: {
             shared_libs: [
                 "libunwind",
+                "libunwindstack",
             ],
         },
     }
@@ -161,6 +168,7 @@
     shared_libs = [
         "libbase",
         "libunwind",
+        "libunwindstack",
         "libziparchive",
     ],
 }
@@ -192,6 +200,7 @@
         "libcutils",
         "liblog",
         "libunwind",
+        "libunwindstack",
     ],
 
     group_static_libs: true,
diff --git a/libbacktrace/UnwindStack.cpp b/libbacktrace/UnwindStack.cpp
new file mode 100644
index 0000000..baf0ada
--- /dev/null
+++ b/libbacktrace/UnwindStack.cpp
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#define _GNU_SOURCE 1
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ucontext.h>
+
+#include <memory>
+#include <string>
+
+#if !defined(__ANDROID__)
+#include <cutils/threads.h>
+#endif
+
+#include <backtrace/Backtrace.h>
+#include <unwindstack/Elf.h>
+#include <unwindstack/MapInfo.h>
+#include <unwindstack/Maps.h>
+#include <unwindstack/Memory.h>
+#include <unwindstack/Regs.h>
+#include <unwindstack/RegsGetLocal.h>
+
+#include "BacktraceLog.h"
+#include "UnwindStack.h"
+#include "UnwindStackMap.h"
+
+static std::string GetFunctionName(pid_t pid, BacktraceMap* back_map, uintptr_t pc,
+                                   uintptr_t* offset) {
+  *offset = 0;
+  unwindstack::Maps* maps = reinterpret_cast<UnwindStackMap*>(back_map)->stack_maps();
+
+  // Get the map for this
+  unwindstack::MapInfo* map_info = maps->Find(pc);
+  if (map_info == nullptr || map_info->flags & PROT_DEVICE_MAP) {
+    return "";
+  }
+
+  unwindstack::Elf* elf = map_info->GetElf(pid, true);
+
+  std::string name;
+  uint64_t func_offset;
+  if (!elf->GetFunctionName(elf->GetRelPc(pc, map_info), &name, &func_offset)) {
+    return "";
+  }
+  *offset = func_offset;
+  return name;
+}
+
+static bool IsUnwindLibrary(const std::string& map_name) {
+  const std::string library(basename(map_name.c_str()));
+  return library == "libunwindstack.so" || library == "libbacktrace.so";
+}
+
+static bool Unwind(pid_t pid, unwindstack::Memory* memory, unwindstack::Regs* regs,
+                   BacktraceMap* back_map, std::vector<backtrace_frame_data_t>* frames,
+                   size_t num_ignore_frames) {
+  unwindstack::Maps* maps = reinterpret_cast<UnwindStackMap*>(back_map)->stack_maps();
+  bool adjust_rel_pc = false;
+  size_t num_frames = 0;
+  frames->clear();
+  while (num_frames < MAX_BACKTRACE_FRAMES) {
+    if (regs->pc() == 0) {
+      break;
+    }
+    unwindstack::MapInfo* map_info = maps->Find(regs->pc());
+    if (map_info == nullptr) {
+      break;
+    }
+
+    unwindstack::Elf* elf = map_info->GetElf(pid, true);
+    uint64_t rel_pc = regs->pc();
+    if (map_info != nullptr) {
+      rel_pc = elf->GetRelPc(regs->pc(), map_info);
+    }
+
+    bool skip_frame = num_frames == 0 && IsUnwindLibrary(map_info->name);
+    if (num_ignore_frames == 0 && !skip_frame) {
+      uint64_t adjusted_rel_pc = rel_pc;
+      if (map_info != nullptr && adjust_rel_pc) {
+        adjusted_rel_pc = regs->GetAdjustedPc(rel_pc, elf);
+      }
+      frames->resize(num_frames + 1);
+      backtrace_frame_data_t* frame = &frames->at(num_frames);
+      frame->num = num_frames;
+      if (map_info != nullptr) {
+        // This will point to the adjusted absolute pc. regs->pc() is
+        // unaltered.
+        frame->pc = map_info->start + adjusted_rel_pc;
+      } else {
+        frame->pc = rel_pc;
+      }
+      frame->sp = regs->sp();
+      frame->rel_pc = adjusted_rel_pc;
+      frame->stack_size = 0;
+
+      frame->map.start = map_info->start;
+      frame->map.end = map_info->end;
+      frame->map.offset = map_info->offset;
+      frame->map.load_bias = elf->GetLoadBias();
+      frame->map.flags = map_info->flags;
+      frame->map.name = map_info->name;
+
+      uint64_t func_offset = 0;
+      if (!elf->GetFunctionName(adjusted_rel_pc, &frame->func_name, &func_offset)) {
+        frame->func_name = "";
+      }
+      frame->func_offset = func_offset;
+      if (num_frames > 0) {
+        // Set the stack size for the previous frame.
+        backtrace_frame_data_t* prev = &frames->at(num_frames - 1);
+        prev->stack_size = frame->sp - prev->sp;
+      }
+      num_frames++;
+    } else if (!skip_frame && num_ignore_frames > 0) {
+      num_ignore_frames--;
+    }
+    adjust_rel_pc = true;
+
+    // Do not unwind through a device map.
+    if (map_info->flags & PROT_DEVICE_MAP) {
+      break;
+    }
+    unwindstack::MapInfo* sp_info = maps->Find(regs->sp());
+    if (sp_info->flags & PROT_DEVICE_MAP) {
+      break;
+    }
+
+    if (!elf->Step(rel_pc + map_info->elf_offset, regs, memory)) {
+      break;
+    }
+  }
+
+  return true;
+}
+
+UnwindStackCurrent::UnwindStackCurrent(pid_t pid, pid_t tid, BacktraceMap* map)
+    : BacktraceCurrent(pid, tid, map), memory_(new unwindstack::MemoryLocal) {}
+
+std::string UnwindStackCurrent::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) {
+  return ::GetFunctionName(Pid(), GetMap(), pc, offset);
+}
+
+bool UnwindStackCurrent::UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucontext) {
+  std::unique_ptr<unwindstack::Regs> regs;
+  if (ucontext == nullptr) {
+    regs.reset(unwindstack::Regs::CreateFromLocal());
+    // Fill in the registers from this function. Do it here to avoid
+    // one extra function call appearing in the unwind.
+    unwindstack::RegsGetLocal(regs.get());
+  } else {
+    regs.reset(unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::GetMachineType(), ucontext));
+  }
+
+  error_ = BACKTRACE_UNWIND_NO_ERROR;
+  return ::Unwind(getpid(), memory_.get(), regs.get(), GetMap(), &frames_, num_ignore_frames);
+}
+
+UnwindStackPtrace::UnwindStackPtrace(pid_t pid, pid_t tid, BacktraceMap* map)
+    : BacktracePtrace(pid, tid, map), memory_(new unwindstack::MemoryRemote(pid)) {}
+
+std::string UnwindStackPtrace::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) {
+  return ::GetFunctionName(Pid(), GetMap(), pc, offset);
+}
+
+bool UnwindStackPtrace::Unwind(size_t num_ignore_frames, ucontext_t* context) {
+  std::unique_ptr<unwindstack::Regs> regs;
+  if (context == nullptr) {
+    uint32_t machine_type;
+    regs.reset(unwindstack::Regs::RemoteGet(Tid(), &machine_type));
+  } else {
+    regs.reset(unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::GetMachineType(), context));
+  }
+
+  error_ = BACKTRACE_UNWIND_NO_ERROR;
+  return ::Unwind(Pid(), memory_.get(), regs.get(), GetMap(), &frames_, num_ignore_frames);
+}
+
+Backtrace* Backtrace::CreateNew(pid_t pid, pid_t tid, BacktraceMap* map) {
+  if (pid == BACKTRACE_CURRENT_PROCESS) {
+    pid = getpid();
+    if (tid == BACKTRACE_CURRENT_THREAD) {
+      tid = gettid();
+    }
+  } else if (tid == BACKTRACE_CURRENT_THREAD) {
+    tid = pid;
+  }
+
+  if (map == nullptr) {
+// This would cause the wrong type of map object to be created, so disallow.
+#if defined(__ANDROID__)
+    __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__,
+              "Backtrace::CreateNew() must be called with a real map pointer.");
+#else
+    BACK_LOGE("Backtrace::CreateNew() must be called with a real map pointer.");
+    abort();
+#endif
+  }
+
+  if (pid == getpid()) {
+    return new UnwindStackCurrent(pid, tid, map);
+  } else {
+    return new UnwindStackPtrace(pid, tid, map);
+  }
+}
diff --git a/libbacktrace/UnwindStack.h b/libbacktrace/UnwindStack.h
new file mode 100644
index 0000000..32d1f51
--- /dev/null
+++ b/libbacktrace/UnwindStack.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2017 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 _LIBBACKTRACE_UNWIND_STACK_H
+#define _LIBBACKTRACE_UNWIND_STACK_H
+
+#include <stdint.h>
+
+#include <string>
+
+#include <backtrace/BacktraceMap.h>
+#include <unwindstack/Memory.h>
+
+#include "BacktraceCurrent.h"
+#include "BacktracePtrace.h"
+
+class UnwindStackCurrent : public BacktraceCurrent {
+ public:
+  UnwindStackCurrent(pid_t pid, pid_t tid, BacktraceMap* map);
+  virtual ~UnwindStackCurrent() = default;
+
+  std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) override;
+
+  bool UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucontext) override;
+
+ private:
+  std::unique_ptr<unwindstack::Memory> memory_;
+};
+
+class UnwindStackPtrace : public BacktracePtrace {
+ public:
+  UnwindStackPtrace(pid_t pid, pid_t tid, BacktraceMap* map);
+  virtual ~UnwindStackPtrace() = default;
+
+  bool Unwind(size_t num_ignore_frames, ucontext_t* context) override;
+
+  std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset);
+
+ private:
+  std::unique_ptr<unwindstack::Memory> memory_;
+};
+
+#endif  // _LIBBACKTRACE_UNWIND_STACK_H
diff --git a/libbacktrace/UnwindStackMap.cpp b/libbacktrace/UnwindStackMap.cpp
new file mode 100644
index 0000000..ba9fd87
--- /dev/null
+++ b/libbacktrace/UnwindStackMap.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2017 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 <sys/types.h>
+
+#include <backtrace/BacktraceMap.h>
+#include <unwindstack/Elf.h>
+#include <unwindstack/MapInfo.h>
+#include <unwindstack/Maps.h>
+
+#include "UnwindStackMap.h"
+
+//-------------------------------------------------------------------------
+UnwindStackMap::UnwindStackMap(pid_t pid) : BacktraceMap(pid) {}
+
+bool UnwindStackMap::Build() {
+  if (pid_ == 0) {
+    pid_ = getpid();
+    stack_maps_.reset(new unwindstack::LocalMaps);
+  } else {
+    stack_maps_.reset(new unwindstack::RemoteMaps(pid_));
+  }
+
+  if (!stack_maps_->Parse()) {
+    return false;
+  }
+
+  // Iterate through the maps and fill in the backtrace_map_t structure.
+  for (auto& map_info : *stack_maps_) {
+    backtrace_map_t map;
+    map.start = map_info.start;
+    map.end = map_info.end;
+    map.offset = map_info.offset;
+    // Set to -1 so that it is demand loaded.
+    map.load_bias = static_cast<uintptr_t>(-1);
+    map.flags = map_info.flags;
+    map.name = map_info.name;
+
+    maps_.push_back(map);
+  }
+
+  return true;
+}
+
+void UnwindStackMap::FillIn(uintptr_t addr, backtrace_map_t* map) {
+  BacktraceMap::FillIn(addr, map);
+  if (map->load_bias != static_cast<uintptr_t>(-1)) {
+    return;
+  }
+
+  // Fill in the load_bias.
+  unwindstack::MapInfo* map_info = stack_maps_->Find(addr);
+  if (map_info == nullptr) {
+    return;
+  }
+  unwindstack::Elf* elf = map_info->GetElf(pid_, true);
+  map->load_bias = elf->GetLoadBias();
+}
+
+//-------------------------------------------------------------------------
+// BacktraceMap create function.
+//-------------------------------------------------------------------------
+BacktraceMap* BacktraceMap::CreateNew(pid_t pid, bool uncached) {
+  BacktraceMap* map;
+
+  if (uncached) {
+    // Force use of the base class to parse the maps when this call is made.
+    map = new BacktraceMap(pid);
+  } else if (pid == getpid()) {
+    map = new UnwindStackMap(0);
+  } else {
+    map = new UnwindStackMap(pid);
+  }
+  if (!map->Build()) {
+    delete map;
+    return nullptr;
+  }
+  return map;
+}
diff --git a/libbacktrace/UnwindStackMap.h b/libbacktrace/UnwindStackMap.h
new file mode 100644
index 0000000..7885b74
--- /dev/null
+++ b/libbacktrace/UnwindStackMap.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2017 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 _LIBBACKTRACE_UNWINDSTACK_MAP_H
+#define _LIBBACKTRACE_UNWINDSTACK_MAP_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <backtrace/BacktraceMap.h>
+#include <unwindstack/Maps.h>
+
+class UnwindStackMap : public BacktraceMap {
+ public:
+  explicit UnwindStackMap(pid_t pid);
+  ~UnwindStackMap() = default;
+
+  bool Build() override;
+
+  void FillIn(uintptr_t addr, backtrace_map_t* map) override;
+
+  unwindstack::Maps* stack_maps() { return stack_maps_.get(); }
+
+ protected:
+  std::unique_ptr<unwindstack::Maps> stack_maps_;
+};
+
+#endif  // _LIBBACKTRACE_UNWINDSTACK_MAP_H
diff --git a/libbacktrace/include/backtrace/Backtrace.h b/libbacktrace/include/backtrace/Backtrace.h
index b919e81..d67ea50 100644
--- a/libbacktrace/include/backtrace/Backtrace.h
+++ b/libbacktrace/include/backtrace/Backtrace.h
@@ -90,6 +90,8 @@
   // If map is NULL, then create the map and manage it internally.
   // If map is not NULL, the map is still owned by the caller.
   static Backtrace* Create(pid_t pid, pid_t tid, BacktraceMap* map = NULL);
+  // Same as above, but uses a different underlying unwinder.
+  static Backtrace* CreateNew(pid_t pid, pid_t tid, BacktraceMap* map = NULL);
 
   // Create an offline Backtrace object that can be used to do an unwind without a process
   // that is still running. If cache_file is set to true, then elf information will be cached
diff --git a/libbacktrace/include/backtrace/BacktraceMap.h b/libbacktrace/include/backtrace/BacktraceMap.h
index 02a50f7..963c34b 100644
--- a/libbacktrace/include/backtrace/BacktraceMap.h
+++ b/libbacktrace/include/backtrace/BacktraceMap.h
@@ -52,6 +52,8 @@
   // Passing a map created with uncached set to true to Backtrace::Create()
   // is unsupported.
   static BacktraceMap* Create(pid_t pid, bool uncached = false);
+  // Same as above, but is compatible with the new unwinder.
+  static BacktraceMap* CreateNew(pid_t pid, bool uncached = false);
 
   static BacktraceMap* Create(pid_t pid, const std::vector<backtrace_map_t>& maps);
 
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index 78ae409..b971a9e 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -34,6 +34,7 @@
 
 cc_library {
     name: "libunwindstack",
+    vendor_available: true,
     defaults: ["libunwindstack_flags"],
     export_include_dirs: ["include"],
 
diff --git a/libunwindstack/include/unwindstack/MapInfo.h b/libunwindstack/include/unwindstack/MapInfo.h
index 2a97dde..1854767 100644
--- a/libunwindstack/include/unwindstack/MapInfo.h
+++ b/libunwindstack/include/unwindstack/MapInfo.h
@@ -41,6 +41,7 @@
   uint64_t elf_offset;
 
   Memory* CreateMemory(pid_t pid);
+  // This function guarantees it will never return nullptr.
   Elf* GetElf(pid_t pid, bool init_gnu_debugdata = false);
 };