Merge "Adapt to versioned_ndk_headers renaming."
diff --git a/libc/Android.bp b/libc/Android.bp
index 6e3b5cd..d3d162b 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1772,8 +1772,8 @@
     arch: {
         arm: {
             //TODO: This is to work around b/24465209. Remove after root cause is fixed
+            pack_relocations: false,
             ldflags: ["-Wl,--hash-style=both"],
-            use_clang_lld: false,
 
             // Don't re-export new/delete and friends, even if the compiler really wants to.
             version_script: "libc.arm.map",
@@ -1806,8 +1806,8 @@
         },
         x86: {
             //TODO: This is to work around b/24465209. Remove after root cause is fixed
+            pack_relocations: false,
             ldflags: ["-Wl,--hash-style=both"],
-            use_clang_lld: false,
 
             // Don't re-export new/delete and friends, even if the compiler really wants to.
             version_script: "libc.x86.map",
@@ -1838,8 +1838,8 @@
     //TODO (dimitry): This is to work around b/24465209. Remove after root cause is fixed
     arch: {
         arm: {
+            pack_relocations: false,
             ldflags: ["-Wl,--hash-style=both"],
-            use_clang_lld: false,
             version_script: "libstdc++.arm.map",
         },
         arm64: {
@@ -1852,8 +1852,8 @@
             version_script: "libstdc++.mips64.map",
         },
         x86: {
+            pack_relocations: false,
             ldflags: ["-Wl,--hash-style=both"],
-            use_clang_lld: false,
             version_script: "libstdc++.x86.map",
         },
         x86_64: {
diff --git a/libc/malloc_debug/Android.bp b/libc/malloc_debug/Android.bp
index 1a79802..a4ff5d4 100644
--- a/libc/malloc_debug/Android.bp
+++ b/libc/malloc_debug/Android.bp
@@ -14,6 +14,7 @@
     stl: "libc++_static",
 
     whole_static_libs: [
+        "libbase",
         "libasync_safe",
         "libdemangle",
     ],
@@ -49,6 +50,7 @@
         "malloc_debug.cpp",
         "PointerData.cpp",
         "RecordData.cpp",
+        "UnwindBacktrace.cpp",
     ],
 
     stl: "libc++_static",
@@ -69,9 +71,14 @@
     static_libs: [
         "libasync_safe",
         "libbase",
+        "libdemangle",
         "libc_malloc_debug_backtrace",
     ],
 
+    shared_libs: [
+        "libunwindstack",
+    ],
+
     multilib: {
         lib32: {
             version_script: "exported32.map",
@@ -112,15 +119,21 @@
         "tests/malloc_debug_unit_tests.cpp",
     ],
 
-    whole_static_libs: ["libc_malloc_debug"],
-
     local_include_dirs: ["tests"],
     include_dirs: [
         "bionic/libc",
         "bionic/libc/async_safe/include",
     ],
 
-    shared_libs: ["libbase"],
+    static_libs: [
+        "libc_malloc_debug",
+        "libdemangle",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libunwindstack",
+    ],
 
     cflags: [
         "-Wall",
diff --git a/libc/malloc_debug/Config.cpp b/libc/malloc_debug/Config.cpp
index 2c94fe8..96fc27f 100644
--- a/libc/malloc_debug/Config.cpp
+++ b/libc/malloc_debug/Config.cpp
@@ -93,6 +93,9 @@
     {
         "backtrace_dump_prefix", {0, &Config::SetBacktraceDumpPrefix},
     },
+    {
+        "backtrace_full", {BACKTRACE_FULL, &Config::VerifyValueEmpty},
+    },
 
     {
         "fill", {FILL_ON_ALLOC | FILL_ON_FREE, &Config::SetFill},
@@ -363,6 +366,11 @@
   error_log("    backtrace_dump_prefix.<PID>.final.txt.");
   error_log("    The default is false.");
   error_log("");
+  error_log("  backtrace_full");
+  error_log("    Any time a backtrace is acquired, use an unwinder that can");
+  error_log("    display Java stack frames. This unwinder can run slower than");
+  error_log("    normal unwinder.");
+  error_log("");
   error_log("  fill_on_alloc[=XX]");
   error_log("    On first allocation, fill with the value 0x%02x.", DEFAULT_FILL_ALLOC_VALUE);
   error_log("    If XX is set it will only fill up to XX bytes of the");
diff --git a/libc/malloc_debug/Config.h b/libc/malloc_debug/Config.h
index 3bcef0b..86d1ee4 100644
--- a/libc/malloc_debug/Config.h
+++ b/libc/malloc_debug/Config.h
@@ -43,6 +43,7 @@
 constexpr uint64_t TRACK_ALLOCS = 0x80;
 constexpr uint64_t LEAK_TRACK = 0x100;
 constexpr uint64_t RECORD_ALLOCS = 0x200;
+constexpr uint64_t BACKTRACE_FULL = 0x400;
 
 // In order to guarantee posix compliance, set the minimum alignment
 // to 8 bytes for 32 bit systems and 16 bytes for 64 bit systems.
diff --git a/libc/malloc_debug/GuardData.cpp b/libc/malloc_debug/GuardData.cpp
index f9a2dca..debc14e 100644
--- a/libc/malloc_debug/GuardData.cpp
+++ b/libc/malloc_debug/GuardData.cpp
@@ -62,10 +62,7 @@
   }
 
   error_log("Backtrace at time of failure:");
-  std::vector<uintptr_t> frames(64);
-  size_t frame_num = backtrace_get(frames.data(), frames.size());
-  frames.resize(frame_num);
-  backtrace_log(frames.data(), frames.size());
+  BacktraceAndLog();
   error_log(LOG_DIVIDER);
 }
 
diff --git a/libc/malloc_debug/PointerData.cpp b/libc/malloc_debug/PointerData.cpp
index 85139e6..b0e2fc8 100644
--- a/libc/malloc_debug/PointerData.cpp
+++ b/libc/malloc_debug/PointerData.cpp
@@ -43,6 +43,7 @@
 
 #include <android-base/stringprintf.h>
 #include <android-base/thread_annotations.h>
+#include <demangle.h>
 #include <private/bionic_macros.h>
 
 #include "Config.h"
@@ -51,6 +52,7 @@
 #include "backtrace.h"
 #include "debug_log.h"
 #include "malloc_debug.h"
+#include "UnwindBacktrace.h"
 
 std::atomic_uint8_t PointerData::backtrace_enabled_;
 std::atomic_bool PointerData::backtrace_dump_;
@@ -63,6 +65,7 @@
 std::unordered_map<FrameKeyType, size_t> PointerData::key_to_index_ GUARDED_BY(
     PointerData::frame_mutex_);
 std::unordered_map<size_t, FrameInfoType> PointerData::frames_ GUARDED_BY(PointerData::frame_mutex_);
+std::unordered_map<size_t, std::vector<unwindstack::LocalFrameData>> PointerData::backtraces_info_ GUARDED_BY(PointerData::frame_mutex_);
 constexpr size_t kBacktraceEmptyIndex = 1;
 size_t PointerData::cur_hash_index_ GUARDED_BY(PointerData::frame_mutex_);
 
@@ -127,10 +130,18 @@
 }
 
 size_t PointerData::AddBacktrace(size_t num_frames) {
-  std::vector<uintptr_t> frames(num_frames);
-  num_frames = backtrace_get(frames.data(), frames.size());
-  if (num_frames == 0) {
-    return kBacktraceEmptyIndex;
+  std::vector<uintptr_t> frames;
+  std::vector<unwindstack::LocalFrameData> frames_info;
+  if (g_debug->config().options() & BACKTRACE_FULL) {
+    if (!Unwind(&frames, &frames_info, num_frames)) {
+      return kBacktraceEmptyIndex;
+    }
+  } else {
+    frames.resize(num_frames);
+    num_frames = backtrace_get(frames.data(), frames.size());
+    if (num_frames == 0) {
+      return kBacktraceEmptyIndex;
+    }
   }
 
   FrameKeyType key{.num_frames = num_frames, .frames = frames.data()};
@@ -144,6 +155,9 @@
     key_to_index_.emplace(key, hash_index);
 
     frames_.emplace(hash_index, FrameInfoType{.references = 1, .frames = std::move(frames)});
+    if (g_debug->config().options() & BACKTRACE_FULL) {
+      backtraces_info_.emplace(hash_index, std::move(frames_info));
+    }
   } else {
     hash_index = entry->second;
     FrameInfoType* frame_info = &frames_[hash_index];
@@ -168,6 +182,9 @@
     FrameKeyType key{.num_frames = frame_info->frames.size(), .frames = frame_info->frames.data()};
     key_to_index_.erase(key);
     frames_.erase(hash_index);
+    if (g_debug->config().options() & BACKTRACE_FULL) {
+      backtraces_info_.erase(hash_index);
+    }
   }
 }
 
@@ -230,6 +247,25 @@
   return max_frames;
 }
 
+void PointerData::LogBacktrace(size_t hash_index) {
+  std::lock_guard<std::mutex> frame_guard(frame_mutex_);
+  if (g_debug->config().options() & BACKTRACE_FULL) {
+    auto backtrace_info_entry = backtraces_info_.find(hash_index);
+    if (backtrace_info_entry != backtraces_info_.end()) {
+      UnwindLog(backtrace_info_entry->second);
+      return;
+    }
+  } else {
+    auto frame_entry = frames_.find(hash_index);
+    if (frame_entry != frames_.end()) {
+      FrameInfoType* frame_info = &frame_entry->second;
+      backtrace_log(frame_info->frames.data(), frame_info->frames.size());
+      return;
+    }
+  }
+  error_log("  hash_index %zu does not have matching frame data.", hash_index);
+}
+
 void PointerData::LogFreeError(const FreePointerInfoType& info, size_t usable_size) {
   error_log(LOG_DIVIDER);
   uint8_t* memory = reinterpret_cast<uint8_t*>(info.pointer);
@@ -242,13 +278,8 @@
   }
 
   if (info.hash_index > kBacktraceEmptyIndex) {
-    std::lock_guard<std::mutex> frame_guard(frame_mutex_);
-    auto frame_entry = frames_.find(info.hash_index);
-    if (frame_entry != frames_.end()) {
-      FrameInfoType* frame_info = &frame_entry->second;
-      error_log("Backtrace at time of free:");
-      backtrace_log(frame_info->frames.data(), frame_info->frames.size());
-    }
+    error_log("Backtrace at time of free:");
+    LogBacktrace(info.hash_index);
   }
 
   error_log(LOG_DIVIDER);
@@ -328,15 +359,8 @@
     return;
   }
 
-  std::lock_guard<std::mutex> frame_guard(frame_mutex_);
-  auto frame_entry = frames_.find(hash_index);
-  if (frame_entry == frames_.end()) {
-    error_log("Freed pointer hash_index %zu does not have matching frame data.", hash_index);
-    return;
-  }
-  FrameInfoType* frame_info = &frame_entry->second;
   error_log("Backtrace of original free:");
-  backtrace_log(frame_info->frames.data(), frame_info->frames.size());
+  LogBacktrace(hash_index);
 }
 
 void PointerData::VerifyAllFreed() {
@@ -350,18 +374,28 @@
     REQUIRES(pointer_mutex_, frame_mutex_) {
   for (const auto& entry : pointers_) {
     FrameInfoType* frame_info = nullptr;
+    std::vector<unwindstack::LocalFrameData>* backtrace_info = nullptr;
     size_t hash_index = entry.second.hash_index;
     if (hash_index > kBacktraceEmptyIndex) {
-      frame_info = &frames_[hash_index];
-      if (frame_info->references == 0) {
+      auto frame_entry = frames_.find(hash_index);
+      if (frame_entry == frames_.end()) {
         // Somehow wound up with a pointer with a valid hash_index, but
         // no frame data. This should not be possible since adding a pointer
         // occurs after the hash_index and frame data have been added.
         // When removing a pointer, the pointer is deleted before the frame
         // data.
-        frames_.erase(hash_index);
         error_log("Pointer 0x%" PRIxPTR " hash_index %zu does not exist.", entry.first, hash_index);
-        frame_info = nullptr;
+      } else {
+        frame_info = &frame_entry->second;
+      }
+
+      if (g_debug->config().options() & BACKTRACE_FULL) {
+        auto backtrace_entry = backtraces_info_.find(hash_index);
+        if (backtrace_entry == backtraces_info_.end()) {
+          error_log("Pointer 0x%" PRIxPTR " hash_index %zu does not exist.", entry.first, hash_index);
+        } else {
+          backtrace_info = &backtrace_entry->second;
+        }
       }
     }
     if (hash_index == 0 && only_with_backtrace) {
@@ -369,7 +403,7 @@
     }
 
     list->emplace_back(ListInfoType{entry.first, 1, entry.second.RealSize(),
-                                    entry.second.ZygoteChildAlloc(), frame_info});
+                                    entry.second.ZygoteChildAlloc(), frame_info, backtrace_info});
   }
 
   // Sort by the size of the allocation.
@@ -440,7 +474,10 @@
   for (const auto& list_info : list) {
     error_log("+++ %s leaked block of size %zu at 0x%" PRIxPTR " (leak %zu of %zu)", getprogname(),
               list_info.size, list_info.pointer, ++track_count, list.size());
-    if (list_info.frame_info != nullptr) {
+    if (list_info.backtrace_info != nullptr) {
+      error_log("Backtrace at time of allocation:");
+      UnwindLog(*list_info.backtrace_info);
+    } else if (list_info.frame_info != nullptr) {
       error_log("Backtrace at time of allocation:");
       backtrace_log(list_info.frame_info->frames.data(), list_info.frame_info->frames.size());
     }
@@ -520,14 +557,28 @@
         if (frame_info->frames[i] == 0) {
           break;
         }
-#if defined(__LP64__)
-        fprintf(fp, " %016" PRIxPTR, frame_info->frames[i]);
-#else
-        fprintf(fp, " %08" PRIxPTR, frame_info->frames[i]);
-#endif
+        fprintf(fp, " %" PRIxPTR, frame_info->frames[i]);
       }
     }
     fprintf(fp, "\n");
+    if (info.backtrace_info != nullptr) {
+      fprintf(fp, "  bt_info");
+      for (const auto& frame : *info.backtrace_info) {
+        fprintf(fp, " {");
+        if (frame.map_info != nullptr && !frame.map_info->name.empty()) {
+          fprintf(fp, "\"%s\"", frame.map_info->name.c_str());
+        } else {
+          fprintf(fp, "\"\"");
+        }
+        fprintf(fp, " %" PRIx64, frame.rel_pc);
+        if (frame.function_name.empty()) {
+          fprintf(fp, " \"\" 0}");
+        } else {
+          fprintf(fp, " \"%s\" %" PRIx64 "}", demangle(frame.function_name.c_str()).c_str(), frame.function_offset);
+        }
+      }
+      fprintf(fp, "\n");
+    }
   }
 }
 
diff --git a/libc/malloc_debug/PointerData.h b/libc/malloc_debug/PointerData.h
index 7a0b3b8..62d4186 100644
--- a/libc/malloc_debug/PointerData.h
+++ b/libc/malloc_debug/PointerData.h
@@ -39,8 +39,10 @@
 #include <vector>
 
 #include <private/bionic_macros.h>
+#include <unwindstack/LocalUnwinder.h>
 
 #include "OptionData.h"
+#include "UnwindBacktrace.h"
 
 extern int* g_malloc_zygote_child;
 
@@ -105,6 +107,7 @@
   size_t size;
   bool zygote_child_alloc;
   FrameInfoType* frame_info;
+  std::vector<unwindstack::LocalFrameData>* backtrace_info;
 };
 
 class PointerData : public OptionData {
@@ -160,6 +163,7 @@
 
  private:
   static std::string GetHashString(uintptr_t* frames, size_t num_frames);
+  static void LogBacktrace(size_t hash_index);
 
   size_t alloc_offset_ = 0;
   std::vector<uint8_t> cmp_mem_;
@@ -174,6 +178,7 @@
   static std::mutex frame_mutex_;
   static std::unordered_map<FrameKeyType, size_t> key_to_index_;
   static std::unordered_map<size_t, FrameInfoType> frames_;
+  static std::unordered_map<size_t, std::vector<unwindstack::LocalFrameData>> backtraces_info_;
   static size_t cur_hash_index_;
 
   static std::mutex free_pointer_mutex_;
diff --git a/libc/malloc_debug/README.md b/libc/malloc_debug/README.md
index 51540f8..b50de40 100644
--- a/libc/malloc_debug/README.md
+++ b/libc/malloc_debug/README.md
@@ -150,8 +150,8 @@
 option.
 
 ### backtrace\_dump\_prefix
-As of P, when the backtrace options has been enabled, this sets the prefix
-used for dumping files when the signal SIGRTMAX - 17 is received or when
+As of P, when one of the backtrace options has been enabled, this sets the
+prefix used for dumping files when the signal SIGRTMAX - 17 is received or when
 the program exits and backtrace\_dump\_on\_exit is set.
 
 The default is /data/local/tmp/backtrace\_heap.
@@ -160,6 +160,11 @@
 on the signal will be backtrace\_dump\_prefix.**PID**.txt. The filename chosen
 when the program exits will be backtrace\_dump\_prefix.**PID**.exit.txt.
 
+### backtrace\_full
+As of P, any time that a backtrace is gathered, a different algorithm is used
+that is extra thorough and can unwind through Java frames. This will run
+slower than the normal backtracing function.
+
 ### fill\_on\_alloc[=MAX\_FILLED\_BYTES]
 Any allocation routine, other than calloc, will result in the allocation being
 filled with the value 0xeb. When doing a realloc to a larger size, the bytes
@@ -490,6 +495,45 @@
 The map data is simply the output of /proc/PID/maps. This data can be used to
 decode the frames in the backtraces.
 
+As of Android P, there is a new version of this file. The new header is:
+
+    Android Native Heap Dump v1.1
+
+The new version no longer 0 pads the backtrace addresses. In v1.0:
+
+    z 0  sz      400  num    1  bt 0000a230 0000b500
+
+While v1.1:
+
+    z 0  sz      400  num    1  bt a230 b500
+
+In addition, when the new option backtrace\_full is used, another line will
+be added to every backtrace line. The line will be:
+
+      bt_info {"MAP_NAME" RELATIVE_TO_MAP_PC "FUNCTION_NAME" FUNCTION_OFFSET} ...
+
+For each backtrace pc, there will be one element in braces.
+
+MAP\_NAME is the name of the map in which the backtrace pc exists. If there is
+no valid map name, this will be empty.
+RELATIVE\_TO\_MAP\_PC is the hexadecimal value of the relative pc to the map.
+FUNCTION\_NAME the name of the function for this pc. If there is no valid
+function name, then it will be empty.
+FUNCTION\_OFFSET the hexadecimal offset from the beginning of the function. If
+the FUNCTION\_NAME is empty, then this value will always be zero.
+
+An example of this new format:
+
+    z 0  sz      400  num    1  bt a2a0 b510
+      bt_info {"/system/libc.so" 2a0 "abort" 24} {"/system/libutils.so" 510 "" 0}
+
+In this example, the first backtrace frame has a pc of 0xa2a0 and is in the
+map named /system/libc.so which starts at 0xa000. The relative pc is 0x2a0,
+and it is in the function abort + 0x24.
+The second backtrace frame has a pc of 0xb510 and is in the map named
+/system/libutils.so which starts at 0xb000. The relative pc is 0x510 and
+it is in an unknown function.
+
 There is a tool to visualize this data, development/scripts/native\_heapdump\_viewer.py.
 
 Examples
diff --git a/libc/malloc_debug/UnwindBacktrace.cpp b/libc/malloc_debug/UnwindBacktrace.cpp
new file mode 100644
index 0000000..ddafc73
--- /dev/null
+++ b/libc/malloc_debug/UnwindBacktrace.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <inttypes.h>
+#include <pthread.h>
+#include <stdint.h>
+
+#include <algorithm>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <android-base/stringprintf.h>
+#include <demangle.h>
+#include <unwindstack/LocalUnwinder.h>
+#include <unwindstack/MapInfo.h>
+
+#include "UnwindBacktrace.h"
+#include "debug_log.h"
+
+#if defined(__LP64__)
+#define PAD_PTR "016" PRIx64
+#else
+#define PAD_PTR "08" PRIx64
+#endif
+
+static pthread_once_t g_setup_once = PTHREAD_ONCE_INIT;
+
+static unwindstack::LocalUnwinder* g_unwinder;
+
+static void Setup() {
+#if defined(__LP64__)
+  std::vector<std::string> skip_libraries{"/system/lib64/libunwindstack.so", "/system/lib64/libc_malloc_debug.so"};
+#else
+  std::vector<std::string> skip_libraries{"/system/lib/libunwindstack.so", "/system/lib/libc_malloc_debug.so"};
+#endif
+
+  g_unwinder = new unwindstack::LocalUnwinder(skip_libraries);
+  g_unwinder->Init();
+}
+
+bool Unwind(std::vector<uintptr_t>* frames, std::vector<unwindstack::LocalFrameData>* frame_info, size_t max_frames) {
+  pthread_once(&g_setup_once, Setup);
+
+  if (g_unwinder == nullptr) {
+    return false;
+  }
+
+  if (!g_unwinder->Unwind(frame_info, max_frames)) {
+    frames->clear();
+    frame_info->clear();
+    return false;
+  }
+
+  for (const auto& frame : *frame_info) {
+    frames->push_back(frame.pc);
+  }
+  return true;
+}
+
+void UnwindLog(const std::vector<unwindstack::LocalFrameData>& frame_info) {
+  for (size_t i = 0; i < frame_info.size(); i++) {
+    const unwindstack::LocalFrameData* info = &frame_info[i];
+    unwindstack::MapInfo* map_info = info->map_info;
+
+    std::string line = android::base::StringPrintf("          #%0zd  pc %" PAD_PTR "  ", i, info->rel_pc);
+    if (map_info->offset != 0) {
+      line += android::base::StringPrintf("(offset 0x%" PRIx64 ") ", map_info->offset);
+    }
+
+    if (map_info->name.empty()) {
+      line += android::base::StringPrintf("<anonymous:%" PRIx64 ">", map_info->start);
+    } else {
+      line += map_info->name;
+    }
+
+    if (!info->function_name.empty()) {
+      line += " (" + demangle(info->function_name.c_str());
+      if (info->function_offset != 0) {
+        line += "+" + std::to_string(info->function_offset);
+      }
+      line += ")";
+    }
+    error_log_string(line.c_str());
+  }
+}
diff --git a/libc/malloc_debug/UnwindBacktrace.h b/libc/malloc_debug/UnwindBacktrace.h
new file mode 100644
index 0000000..4c6c8d4
--- /dev/null
+++ b/libc/malloc_debug/UnwindBacktrace.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include <unwindstack/LocalUnwinder.h>
+#include <unwindstack/MapInfo.h>
+
+bool Unwind(std::vector<uintptr_t>* frames, std::vector<unwindstack::LocalFrameData>* info, size_t max_frames);
+
+void UnwindLog(const std::vector<unwindstack::LocalFrameData>& frame_info);
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index 6f841ca..836c33b 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -47,6 +47,7 @@
 #include "debug_disable.h"
 #include "debug_log.h"
 #include "malloc_debug.h"
+#include "UnwindBacktrace.h"
 
 // ------------------------------------------------------------------------
 // Global Data
@@ -118,6 +119,26 @@
   });
 }
 
+void BacktraceAndLog() {
+  if (g_debug->config().options() & BACKTRACE_FULL) {
+    std::vector<uintptr_t> frames;
+    std::vector<unwindstack::LocalFrameData> frames_info;
+    if (!Unwind(&frames, &frames_info, 256)) {
+      error_log("  Backtrace failed to get any frames.");
+    } else {
+      UnwindLog(frames_info);
+    }
+  } else {
+    std::vector<uintptr_t> frames(256);
+    size_t num_frames = backtrace_get(frames.data(), frames.size());
+    if (num_frames == 0) {
+      error_log("  Backtrace failed to get any frames.");
+    } else {
+      backtrace_log(frames.data(), num_frames);
+    }
+  }
+}
+
 static void LogError(const void* pointer, const char* error_str) {
   error_log(LOG_DIVIDER);
   error_log("+++ ALLOCATION %p %s", pointer, error_str);
@@ -128,14 +149,8 @@
     PointerData::LogFreeBacktrace(pointer);
   }
 
-  std::vector<uintptr_t> frames(128);
-  size_t num_frames = backtrace_get(frames.data(), frames.size());
-  if (num_frames == 0) {
-    error_log("Backtrace failed to get any frames.");
-  } else {
-    error_log("Backtrace at time of failure:");
-    backtrace_log(frames.data(), num_frames);
-  }
+  error_log("Backtrace at time of failure:");
+  BacktraceAndLog();
   error_log(LOG_DIVIDER);
 }
 
@@ -819,7 +834,7 @@
     return false;
   }
 
-  fprintf(fp, "Android Native Heap Dump v1.0\n\n");
+  fprintf(fp, "Android Native Heap Dump v1.1\n\n");
 
   PointerData::DumpLiveToFile(fp);
 
diff --git a/libc/malloc_debug/malloc_debug.h b/libc/malloc_debug/malloc_debug.h
index ac210e2..7280ea7 100644
--- a/libc/malloc_debug/malloc_debug.h
+++ b/libc/malloc_debug/malloc_debug.h
@@ -62,3 +62,5 @@
 constexpr size_t FREE_TRACK_MEM_BUFFER_SIZE = 4096;
 
 extern const MallocDispatch* g_dispatch;
+
+void BacktraceAndLog();
diff --git a/libc/malloc_debug/tests/backtrace_fake.cpp b/libc/malloc_debug/tests/backtrace_fake.cpp
index db542e5..ad16c02 100644
--- a/libc/malloc_debug/tests/backtrace_fake.cpp
+++ b/libc/malloc_debug/tests/backtrace_fake.cpp
@@ -20,6 +20,8 @@
 #include <vector>
 #include <utility>
 
+#include <unwindstack/LocalUnwinder.h>
+
 #include "backtrace.h"
 #include "backtrace_fake.h"
 #include "debug_log.h"
@@ -57,3 +59,31 @@
     error_log("  #%02zd pc %p", i, reinterpret_cast<void*>(frames[i]));
   }
 }
+
+static std::deque<std::vector<unwindstack::LocalFrameData>> g_fake_local_frame_data;
+
+void BacktraceUnwindFakeClearAll() {
+  g_fake_local_frame_data.clear();
+}
+
+void BacktraceUnwindFake(const std::vector<unwindstack::LocalFrameData>& frames) {
+  g_fake_local_frame_data.push_back(frames);
+}
+
+bool Unwind(std::vector<uintptr_t>* frames, std::vector<unwindstack::LocalFrameData>* info, size_t) {
+  if (g_fake_local_frame_data.empty()) {
+    return false;
+  }
+
+  *info = g_fake_local_frame_data.front();
+  g_fake_local_frame_data.pop_front();
+  frames->clear();
+  for (const auto& frame : *info) {
+    frames->push_back(frame.pc);
+  }
+
+  return true;
+}
+
+void UnwindLog(const std::vector<unwindstack::LocalFrameData>& /*frame_info*/) {
+}
diff --git a/libc/malloc_debug/tests/backtrace_fake.h b/libc/malloc_debug/tests/backtrace_fake.h
index f2aa7a0..a9ee97d 100644
--- a/libc/malloc_debug/tests/backtrace_fake.h
+++ b/libc/malloc_debug/tests/backtrace_fake.h
@@ -21,7 +21,12 @@
 
 #include <vector>
 
+#include <unwindstack/LocalUnwinder.h>
+
 void backtrace_fake_clear_all();
 void backtrace_fake_add(const std::vector<uintptr_t>& ips);
 
+void BacktraceUnwindFakeClearAll();
+void BacktraceUnwindFake(const std::vector<unwindstack::LocalFrameData>& frames);
+
 #endif // MALLOC_DEBUG_TESTS_BACKTRACE_FAKE_H
diff --git a/libc/malloc_debug/tests/log_fake.cpp b/libc/malloc_debug/tests/log_fake.cpp
index fb64e3e..9a23ac7 100644
--- a/libc/malloc_debug/tests/log_fake.cpp
+++ b/libc/malloc_debug/tests/log_fake.cpp
@@ -45,9 +45,7 @@
 }
 
 extern "C" int async_safe_format_log(int priority, const char* tag, const char* format, ...) {
-  g_fake_log_print += std::to_string(priority) + ' ';
-  g_fake_log_print += tag;
-  g_fake_log_print += ' ';
+  g_fake_log_print += std::to_string(priority) + ' ' + tag + ' ';
 
   va_list ap;
   va_start(ap, format);
@@ -59,6 +57,12 @@
   return 0;
 }
 
+extern "C" int async_safe_write_log(int priority, const char* tag, const char* msg) {
+  g_fake_log_print += std::to_string(priority) + ' ' + tag + ' ' + msg + '\n';
+
+  return 0;
+}
+
 extern "C" int __android_log_buf_write(int bufId, int prio, const char* tag, const char* msg) {
   g_fake_log_buf += std::to_string(bufId) + ' ' + std::to_string(prio) + ' ';
   g_fake_log_buf += tag;
diff --git a/libc/malloc_debug/tests/malloc_debug_config_tests.cpp b/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
index 4603535..2a6e399 100644
--- a/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_config_tests.cpp
@@ -83,6 +83,11 @@
   "6 malloc_debug     backtrace_dump_prefix.<PID>.final.txt.\n"
   "6 malloc_debug     The default is false.\n"
   "6 malloc_debug \n"
+  "6 malloc_debug   backtrace_full\n"
+  "6 malloc_debug     Any time a backtrace is acquired, use an unwinder that can\n"
+  "6 malloc_debug     display Java stack frames. This unwinder can run slower than\n"
+  "6 malloc_debug     normal unwinder.\n"
+  "6 malloc_debug \n"
   "6 malloc_debug   fill_on_alloc[=XX]\n"
   "6 malloc_debug     On first allocation, fill with the value 0xeb.\n"
   "6 malloc_debug     If XX is set it will only fill up to XX bytes of the\n"
@@ -413,6 +418,24 @@
   ASSERT_STREQ("", getFakeLogPrint().c_str());
 }
 
+TEST_F(MallocDebugConfigTest, backtrace_full) {
+  ASSERT_TRUE(InitConfig("backtrace_full")) << getFakeLogPrint();
+  ASSERT_EQ(BACKTRACE_FULL, config->options());
+
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  ASSERT_STREQ("", getFakeLogPrint().c_str());
+}
+
+TEST_F(MallocDebugConfigTest, backtrace_full_fail) {
+  ASSERT_FALSE(InitConfig("backtrace_full=200")) << getFakeLogPrint();
+
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  std::string log_msg(
+      "6 malloc_debug malloc_testing: value set for option 'backtrace_full' "
+      "which does not take a value\n");
+  ASSERT_STREQ((log_msg + usage_string).c_str(), getFakeLogPrint().c_str());
+}
+
 TEST_F(MallocDebugConfigTest, fill_on_alloc) {
   ASSERT_TRUE(InitConfig("fill_on_alloc=64")) << getFakeLogPrint();
   ASSERT_EQ(FILL_ON_ALLOC, config->options());
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index 1504d06..0663f6a 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -19,6 +19,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/cdefs.h>
+#include <sys/mman.h>
 #include <sys/param.h>
 #include <sys/types.h>
 #include <unistd.h>
@@ -1311,30 +1312,23 @@
   std::string sanitized(SanitizeHeapData(actual));
 
   std::string expected =
-      "Android Native Heap Dump v1.0\n"
-      "\n"
-      "Total memory: 405\n"
-      "Allocation records: 6\n"
-      "Backtrace size: 4\n"
-      "\n"
-#if defined(__LP64__)
-      "z 0  sz       50  num    1  bt 000000000000a100 000000000000b200\n"
-      "z 0  sz       10  num    1  bt 000000000000a000 000000000000b000\n"
-      "z 0  sz        5  num    1  bt 000000000000a300 000000000000b300\n"
-      "z 1  sz      200  num    1  bt 0000000000000500 0000000000000600\n"
-      "z 1  sz      100  num    1  bt 0000000000000100 0000000000000200\n"
-      "z 1  sz       40  num    1  bt 0000000000000300 0000000000000400\n"
-#else
-      "z 0  sz       50  num    1  bt 0000a100 0000b200\n"
-      "z 0  sz       10  num    1  bt 0000a000 0000b000\n"
-      "z 0  sz        5  num    1  bt 0000a300 0000b300\n"
-      "z 1  sz      200  num    1  bt 00000500 00000600\n"
-      "z 1  sz      100  num    1  bt 00000100 00000200\n"
-      "z 1  sz       40  num    1  bt 00000300 00000400\n"
-#endif
-      "MAPS\n"
-      "MAP_DATA\n"
-      "END\n\n";
+R"(Android Native Heap Dump v1.1
+
+Total memory: 405
+Allocation records: 6
+Backtrace size: 4
+
+z 0  sz       50  num    1  bt a100 b200
+z 0  sz       10  num    1  bt a000 b000
+z 0  sz        5  num    1  bt a300 b300
+z 1  sz      200  num    1  bt 500 600
+z 1  sz      100  num    1  bt 100 200
+z 1  sz       40  num    1  bt 300 400
+MAPS
+MAP_DATA
+END
+
+)";
   ASSERT_STREQ(expected.c_str(), sanitized.c_str()) << "Actual data: \n" << actual;
 
   ASSERT_STREQ("", getFakeLogBuf().c_str());
@@ -1383,24 +1377,20 @@
   std::string sanitized(SanitizeHeapData(actual));
 
   std::string expected =
-      "Android Native Heap Dump v1.0\n"
-      "\n"
-      "Total memory: 1200\n"
-      "Allocation records: 3\n"
-      "Backtrace size: 4\n"
-      "\n"
-#if defined(__LP64__)
-      "z 0  sz      500  num    1  bt 000000000000a000 000000000000b000 000000000000c000\n"
-      "z 0  sz      400  num    1  bt 000000000000a000 000000000000b000\n"
-      "z 0  sz      300  num    1  bt 0000000000000100 0000000000000200\n"
-#else
-      "z 0  sz      500  num    1  bt 0000a000 0000b000 0000c000\n"
-      "z 0  sz      400  num    1  bt 0000a000 0000b000\n"
-      "z 0  sz      300  num    1  bt 00000100 00000200\n"
-#endif
-      "MAPS\n"
-      "MAP_DATA\n"
-      "END\n\n";
+R"(Android Native Heap Dump v1.1
+
+Total memory: 1200
+Allocation records: 3
+Backtrace size: 4
+
+z 0  sz      500  num    1  bt a000 b000 c000
+z 0  sz      400  num    1  bt a000 b000
+z 0  sz      300  num    1  bt 100 200
+MAPS
+MAP_DATA
+END
+
+)";
   ASSERT_STREQ(expected.c_str(), sanitized.c_str()) << "Actual data: \n" << actual;
 
   ASSERT_STREQ("", getFakeLogBuf().c_str());
@@ -1436,28 +1426,84 @@
   std::string sanitized(SanitizeHeapData(actual));
 
   std::string expected =
-      "Android Native Heap Dump v1.0\n"
-      "\n"
-      "Total memory: 1000\n"
-      "Allocation records: 2\n"
-      "Backtrace size: 4\n"
-      "\n"
-#if defined(__LP64__)
-      "z 0  sz      400  num    1  bt 000000000000a000 000000000000b000 000000000000c000\n"
-      "z 0  sz      300  num    2  bt 0000000000000100 0000000000000200\n"
-#else
-      "z 0  sz      400  num    1  bt 0000a000 0000b000 0000c000\n"
-      "z 0  sz      300  num    2  bt 00000100 00000200\n"
-#endif
-      "MAPS\n"
-      "MAP_DATA\n"
-      "END\n\n";
+R"(Android Native Heap Dump v1.1
+
+Total memory: 1000
+Allocation records: 2
+Backtrace size: 4
+
+z 0  sz      400  num    1  bt a000 b000 c000
+z 0  sz      300  num    2  bt 100 200
+MAPS
+MAP_DATA
+END
+
+)";
   ASSERT_STREQ(expected.c_str(), sanitized.c_str()) << "Actual data: \n" << actual;
 
   ASSERT_STREQ("", getFakeLogBuf().c_str());
   ASSERT_STREQ("", getFakeLogPrint().c_str());
 }
 
+TEST_F(MallocDebugTest, backtrace_full_dump_on_exit) {
+  pid_t pid;
+  if ((pid = fork()) == 0) {
+    Init("backtrace=4 backtrace_full backtrace_dump_on_exit");
+    BacktraceUnwindFake(
+      std::vector<unwindstack::LocalFrameData>{{nullptr, 0x1100, 0x100, "fake1", 10},
+                                               {nullptr, 0x1200, 0x200, "fake2", 20}});
+    unwindstack::MapInfo map_info{0x10000, 0x20000, 0, PROT_READ | PROT_EXEC, "/data/fake.so"};
+    BacktraceUnwindFake(
+      std::vector<unwindstack::LocalFrameData>{{&map_info, 0x1a000, 0xa000, "level1", 0},
+                                               {&map_info, 0x1b000, 0xb000, "level2", 10}});
+    BacktraceUnwindFake(
+      std::vector<unwindstack::LocalFrameData>{{nullptr, 0x1a000, 0xa000, "func1", 0},
+                                               {nullptr, 0x1b000, 0xb000, "func2", 10},
+                                               {nullptr, 0x1c000, 0xc000, "", 30}});
+
+    std::vector<void*> pointers;
+    pointers.push_back(debug_malloc(300));
+    pointers.push_back(debug_malloc(400));
+    pointers.push_back(debug_malloc(500));
+
+    // Call the exit function manually.
+    debug_finalize();
+    exit(0);
+  }
+  ASSERT_NE(-1, pid);
+  ASSERT_EQ(pid, TEMP_FAILURE_RETRY(waitpid(pid, nullptr, 0)));
+
+  // Read all of the contents.
+  std::string actual;
+  std::string name = android::base::StringPrintf("%s.%d.exit.txt", BACKTRACE_DUMP_PREFIX, pid);
+  ASSERT_TRUE(android::base::ReadFileToString(name, &actual));
+  ASSERT_EQ(0, unlink(name.c_str()));
+
+  std::string sanitized(SanitizeHeapData(actual));
+
+  std::string expected =
+R"(Android Native Heap Dump v1.1
+
+Total memory: 1200
+Allocation records: 3
+Backtrace size: 4
+
+z 0  sz      500  num    1  bt 1a000 1b000 1c000
+  bt_info {"" a000 "func1" 0} {"" b000 "func2" a} {"" c000 "" 0}
+z 0  sz      400  num    1  bt 1a000 1b000
+  bt_info {"/data/fake.so" a000 "level1" 0} {"/data/fake.so" b000 "level2" a}
+z 0  sz      300  num    1  bt 1100 1200
+  bt_info {"" 100 "fake1" a} {"" 200 "fake2" 14}
+MAPS
+MAP_DATA
+END
+
+)";
+  ASSERT_STREQ(expected.c_str(), sanitized.c_str()) << "Actual data: \n" << actual;
+
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  ASSERT_STREQ("", getFakeLogPrint().c_str());
+}
 
 TEST_F(MallocDebugTest, realloc_usable_size) {
   Init("front_guard");
@@ -2286,7 +2332,8 @@
   std::string realloc_pointer_str(
       android::base::StringPrintf("6 malloc_debug +++ ALLOCATION %p UNKNOWN POINTER (realloc)\n",
                                   pointer));
-  std::string backtrace_str("6 malloc_debug Backtrace failed to get any frames.\n");
+  std::string backtrace_str("6 malloc_debug Backtrace at time of failure:\n");
+  backtrace_str += "6 malloc_debug   Backtrace failed to get any frames.\n";
 
   std::string expected_log(DIVIDER + free_pointer_str + backtrace_str + DIVIDER);
   expected_log += DIVIDER + usable_pointer_str + backtrace_str + DIVIDER;
diff --git a/libdl/Android.bp b/libdl/Android.bp
index 9d97957..d5f8e70 100644
--- a/libdl/Android.bp
+++ b/libdl/Android.bp
@@ -49,8 +49,8 @@
     arch: {
         arm: {
             version_script: "libdl.arm.map",
+            pack_relocations: false,
             ldflags: ["-Wl,--hash-style=both"],
-            use_clang_lld: false,
         },
         arm64: {
             version_script: "libdl.arm64.map",
@@ -62,11 +62,11 @@
             version_script: "libdl.mips64.map",
         },
         x86: {
+            pack_relocations: false,
             ldflags: [
                 "-Wl,--exclude-libs=libgcc_eh.a",
                 "-Wl,--hash-style=both",
             ],
-            use_clang_lld: false,
             version_script: "libdl.x86.map",
         },
         x86_64: {
diff --git a/libm/Android.bp b/libm/Android.bp
index 76bbca3..9566d5f 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -293,8 +293,8 @@
                 ],
             },
             instruction_set: "arm",
+            pack_relocations: false,
             ldflags: ["-Wl,--hash-style=both"],
-            use_clang_lld: false,
             version_script: "libm.arm.map",
         },
 
@@ -421,8 +421,8 @@
                 ],
             },
             local_include_dirs: ["i387"],
+            pack_relocations: false,
             ldflags: ["-Wl,--hash-style=both"],
-            use_clang_lld: false,
             version_script: "libm.x86.map",
         },
 
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 7d9abf9..6d68497 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -1432,10 +1432,13 @@
 }
 
 // Duplicate these definitions here because they are android specific
-// note that we cannot include <elf.h> because #defines conflict with
-// enum names provided by LLVM.
-#define DT_ANDROID_REL (llvm::ELF::DT_LOOS + 2)
-#define DT_ANDROID_RELA (llvm::ELF::DT_LOOS + 4)
+//  - note that we cannot include <elf.h> because #defines conflict with
+//    enum names provided by LLVM.
+//  - we also don't use llvm::ELF::DT_LOOS because its value is 0x60000000
+//    rather than the 0x6000000d we expect
+#define DT_LOOS 0x6000000d
+#define DT_ANDROID_REL (DT_LOOS + 2)
+#define DT_ANDROID_RELA (DT_LOOS + 4)
 
 template<typename ELFT>
 void validate_compatibility_of_native_library(const std::string& soname,