Merge "Fix code style, put unused in the end"
diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp
index b4c57cc..11e9af5 100644
--- a/debuggerd/tombstone.cpp
+++ b/debuggerd/tombstone.cpp
@@ -625,12 +625,9 @@
     dump_fault_addr(log, tid, signal);
   }
 
-  BacktraceMap* map = NULL;
-  UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, tid));
+  UniquePtr<BacktraceMap> map(BacktraceMap::Create(pid));
+  UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, tid, map.get()));
   if (backtrace->Unwind(0)) {
-    // Grab the map that was created and share it with the siblings.
-    map = backtrace->TakeMapOwnership();
-
     dump_abort_message(backtrace.get(), log, abort_msg_address);
     dump_thread(backtrace.get(), log, SCOPE_AT_FAULT, total_sleep_time_usec);
   }
@@ -641,12 +638,9 @@
 
   bool detach_failed = false;
   if (dump_sibling_threads) {
-    detach_failed = dump_sibling_thread_report(log, pid, tid, total_sleep_time_usec, map);
+    detach_failed = dump_sibling_thread_report(log, pid, tid, total_sleep_time_usec, map.get());
   }
 
-  // Destroy the BacktraceMap object.
-  delete map;
-
   if (want_logs) {
     dump_logs(log, pid, 0);
   }
diff --git a/include/backtrace/Backtrace.h b/include/backtrace/Backtrace.h
index f0fb0cd..bd4134c 100644
--- a/include/backtrace/Backtrace.h
+++ b/include/backtrace/Backtrace.h
@@ -64,10 +64,6 @@
   // Find the map associated with the given pc.
   virtual const backtrace_map_t* FindMap(uintptr_t pc);
 
-  // Take ownership of the BacktraceMap object associated with the backtrace.
-  // If this is called, the caller must handle deleting the object themselves.
-  virtual BacktraceMap* TakeMapOwnership();
-
   // Read the data at a specific address.
   virtual bool ReadWord(uintptr_t ptr, uint32_t* out_value) = 0;
 
diff --git a/include/backtrace/BacktraceMap.h b/include/backtrace/BacktraceMap.h
index a53293a..06da2f4 100644
--- a/include/backtrace/BacktraceMap.h
+++ b/include/backtrace/BacktraceMap.h
@@ -28,8 +28,8 @@
 #include <sys/mman.h>
 #endif
 
+#include <deque>
 #include <string>
-#include <vector>
 
 struct backtrace_map_t {
   uintptr_t start;
@@ -40,7 +40,8 @@
 
 class BacktraceMap {
 public:
-  BacktraceMap(pid_t pid);
+  static BacktraceMap* Create(pid_t pid);
+
   virtual ~BacktraceMap();
 
   // Get the map data structure for the given address.
@@ -60,20 +61,22 @@
   bool IsWritable(uintptr_t pc) { return GetFlags(pc) & PROT_WRITE; }
   bool IsExecutable(uintptr_t pc) { return GetFlags(pc) & PROT_EXEC; }
 
-  typedef std::vector<backtrace_map_t>::iterator iterator;
+  typedef std::deque<backtrace_map_t>::iterator iterator;
   iterator begin() { return maps_.begin(); }
   iterator end() { return maps_.end(); }
 
-  typedef std::vector<backtrace_map_t>::const_iterator const_iterator;
+  typedef std::deque<backtrace_map_t>::const_iterator const_iterator;
   const_iterator begin() const { return maps_.begin(); }
   const_iterator end() const { return maps_.end(); }
 
   virtual bool Build();
 
 protected:
+  BacktraceMap(pid_t pid);
+
   virtual bool ParseLine(const char* line, backtrace_map_t* map);
 
-  std::vector<backtrace_map_t> maps_;
+  std::deque<backtrace_map_t> maps_;
   pid_t pid_;
 };
 
diff --git a/libbacktrace/Android.mk b/libbacktrace/Android.mk
index f23eefd..0ae8839 100644
--- a/libbacktrace/Android.mk
+++ b/libbacktrace/Android.mk
@@ -1,7 +1,7 @@
 LOCAL_PATH:= $(call my-dir)
 
 common_src := \
-	Backtrace.cpp \
+	BacktraceImpl.cpp \
 	BacktraceMap.cpp \
 	BacktraceThread.cpp \
 	thread_utils.c \
@@ -23,7 +23,7 @@
 	liblog \
 
 # To enable using libunwind on each arch, add it to this list.
-libunwind_architectures := arm64
+libunwind_architectures := arm arm64
 
 ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),$(libunwind_architectures)))
 
@@ -35,6 +35,7 @@
 LOCAL_SRC_FILES:= \
 	$(common_src) \
 	UnwindCurrent.cpp \
+	UnwindMap.cpp \
 	UnwindPtrace.cpp \
 
 LOCAL_CFLAGS := \
diff --git a/libbacktrace/Backtrace.cpp b/libbacktrace/BacktraceImpl.cpp
similarity index 92%
rename from libbacktrace/Backtrace.cpp
rename to libbacktrace/BacktraceImpl.cpp
index d7b40ab..39296b4 100644
--- a/libbacktrace/Backtrace.cpp
+++ b/libbacktrace/BacktraceImpl.cpp
@@ -29,7 +29,7 @@
 #include <backtrace/Backtrace.h>
 #include <backtrace/BacktraceMap.h>
 
-#include "Backtrace.h"
+#include "BacktraceImpl.h"
 #include "thread_utils.h"
 
 //-------------------------------------------------------------------------
@@ -40,21 +40,21 @@
   impl_->SetParent(this);
 
   if (map_ == NULL) {
-    // The map will be created when needed.
+    map_ = BacktraceMap::Create(pid);
     map_shared_ = false;
   }
 }
 
 Backtrace::~Backtrace() {
-  if (map_ && !map_shared_) {
-    delete map_;
-    map_ = NULL;
-  }
-
   if (impl_) {
     delete impl_;
     impl_ = NULL;
   }
+
+  if (map_ && !map_shared_) {
+    delete map_;
+    map_ = NULL;
+  }
 }
 
 bool Backtrace::Unwind(size_t num_ignore_frames) {
@@ -129,30 +129,10 @@
   return buf;
 }
 
-bool Backtrace::BuildMap() {
-  map_ = impl_->CreateBacktraceMap(pid_);
-  if (!map_->Build()) {
-    BACK_LOGW("Failed to build map for process %d", pid_);
-    return false;
-  }
-  return true;
-}
-
 const backtrace_map_t* Backtrace::FindMap(uintptr_t pc) {
-  if (map_ == NULL) {
-    // Lazy eval, time to build the map.
-    if (!BuildMap()) {
-      return NULL;
-    }
-  }
   return map_->Find(pc);
 }
 
-BacktraceMap* Backtrace::TakeMapOwnership() {
-  map_shared_ = true;
-  return map_;
-}
-
 //-------------------------------------------------------------------------
 // BacktraceCurrent functions.
 //-------------------------------------------------------------------------
diff --git a/libbacktrace/Backtrace.h b/libbacktrace/BacktraceImpl.h
similarity index 78%
rename from libbacktrace/Backtrace.h
rename to libbacktrace/BacktraceImpl.h
index 31fcaf2..af014d5 100644
--- a/libbacktrace/Backtrace.h
+++ b/libbacktrace/BacktraceImpl.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef _LIBBACKTRACE_BACKTRACE_H
-#define _LIBBACKTRACE_BACKTRACE_H
+#ifndef _LIBBACKTRACE_BACKTRACE_IMPL_H
+#define _LIBBACKTRACE_BACKTRACE_IMPL_H
 
 #include <backtrace/Backtrace.h>
 #include <backtrace/BacktraceMap.h>
@@ -39,13 +39,20 @@
 
   void SetParent(Backtrace* backtrace) { backtrace_obj_ = backtrace; }
 
-  virtual BacktraceMap* CreateBacktraceMap(pid_t pid) = 0;
+  inline pid_t Pid() { return backtrace_obj_->Pid(); }
+  inline pid_t Tid() { return backtrace_obj_->Tid(); }
+
+  inline const backtrace_map_t* FindMap(uintptr_t addr) {
+    return backtrace_obj_->FindMap(addr);
+  }
+  inline std::string GetFunctionName(uintptr_t pc, uintptr_t* offset) {
+    return backtrace_obj_->GetFunctionName(pc, offset);
+  }
+  inline BacktraceMap* GetMap() { return backtrace_obj_->GetMap(); }
 
 protected:
   inline std::vector<backtrace_frame_data_t>* GetFrames() { return &backtrace_obj_->frames_; }
 
-  inline bool BuildMap() { return backtrace_obj_->BuildMap(); }
-
   Backtrace* backtrace_obj_;
 };
 
@@ -69,4 +76,4 @@
 Backtrace* CreatePtraceObj(pid_t pid, pid_t tid, BacktraceMap* map);
 Backtrace* CreateThreadObj(pid_t tid, BacktraceMap* map);
 
-#endif // _LIBBACKTRACE_BACKTRACE_H
+#endif // _LIBBACKTRACE_BACKTRACE_IMPL_H
diff --git a/libbacktrace/BacktraceMap.cpp b/libbacktrace/BacktraceMap.cpp
index 78f5b6b..6320800 100644
--- a/libbacktrace/BacktraceMap.cpp
+++ b/libbacktrace/BacktraceMap.cpp
@@ -21,9 +21,13 @@
 #include <string>
 #include <vector>
 
+#include <backtrace/backtrace_constants.h>
 #include <backtrace/BacktraceMap.h>
 #include <log/log.h>
 
+#include "thread_utils.h"
+#include "BacktraceImpl.h"
+
 BacktraceMap::BacktraceMap(pid_t pid) : pid_(pid) {
   if (pid_ < 0) {
     pid_ = getpid();
@@ -128,3 +132,16 @@
 
   return true;
 }
+
+#if defined(__APPLE__)
+// Corkscrew and libunwind don't compile on the mac, so create a generic
+// map object.
+BacktraceMap* BacktraceMap::Create(pid_t pid) {
+  BacktraceMap* map = new BacktraceMap(pid);
+  if (!map->Build()) {
+    delete map;
+    return NULL;
+  }
+  return map;
+}
+#endif
diff --git a/libbacktrace/BacktraceThread.cpp b/libbacktrace/BacktraceThread.cpp
index 9953dc1..5ffe516 100644
--- a/libbacktrace/BacktraceThread.cpp
+++ b/libbacktrace/BacktraceThread.cpp
@@ -180,10 +180,6 @@
 }
 
 bool BacktraceThread::Unwind(size_t num_ignore_frames) {
-  if (!thread_intf_->Init()) {
-    return false;
-  }
-
   ThreadEntry* entry = ThreadEntry::AddThreadToUnwind(
       thread_intf_, Pid(), Tid(), num_ignore_frames);
   if (!entry) {
diff --git a/libbacktrace/BacktraceThread.h b/libbacktrace/BacktraceThread.h
index cae496a..3412d58 100644
--- a/libbacktrace/BacktraceThread.h
+++ b/libbacktrace/BacktraceThread.h
@@ -20,7 +20,7 @@
 #include <inttypes.h>
 #include <sys/types.h>
 
-#include "Backtrace.h"
+#include "BacktraceImpl.h"
 
 enum state_e {
   STATE_WAITING = 0,
@@ -58,8 +58,6 @@
 public:
   virtual ~BacktraceThreadInterface() { }
 
-  virtual bool Init() = 0;
-
   virtual void ThreadUnwind(
       siginfo_t* siginfo, void* sigcontext, size_t num_ignore_frames) = 0;
 };
diff --git a/libbacktrace/Corkscrew.cpp b/libbacktrace/Corkscrew.cpp
index fd31a26..efeee2e 100644
--- a/libbacktrace/Corkscrew.cpp
+++ b/libbacktrace/Corkscrew.cpp
@@ -65,7 +65,8 @@
     }
     map.name = cur_map->name;
 
-    maps_.push_back(map);
+    // The maps are in descending order, but we want them in ascending order.
+    maps_.push_front(map);
 
     cur_map = cur_map->next;
   }
@@ -93,8 +94,8 @@
     it->stack_size = cork_frames[i].stack_size;
     it->func_offset = 0;
 
-    it->map = backtrace_obj_->FindMap(it->pc);
-    it->func_name = backtrace_obj_->GetFunctionName(it->pc, &it->func_offset);
+    it->map = FindMap(it->pc);
+    it->func_name = GetFunctionName(it->pc, &it->func_offset);
   }
   return true;
 }
@@ -119,7 +120,7 @@
   *offset = 0;
 
   Dl_info info;
-  const backtrace_map_t* map = backtrace_obj_->FindMap(pc);
+  const backtrace_map_t* map = FindMap(pc);
   if (map) {
     if (dladdr((const void*)pc, &info)) {
       if (info.dli_sname) {
@@ -158,19 +159,10 @@
 CorkscrewThread::~CorkscrewThread() {
 }
 
-bool CorkscrewThread::Init() {
-  if (backtrace_obj_->GetMap() == NULL) {
-    // Trigger the map object creation, which will create the corkscrew
-    // map information.
-    return BuildMap();
-  }
-  return true;
-}
-
 void CorkscrewThread::ThreadUnwind(
     siginfo_t* siginfo, void* sigcontext, size_t num_ignore_frames) {
   backtrace_frame_t cork_frames[MAX_BACKTRACE_FRAMES];
-  CorkscrewMap* map = static_cast<CorkscrewMap*>(backtrace_obj_->GetMap());
+  CorkscrewMap* map = static_cast<CorkscrewMap*>(GetMap());
   ssize_t num_frames = unwind_backtrace_signal_arch(
       siginfo, sigcontext, map->GetMapInfo(), cork_frames,
       num_ignore_frames, MAX_BACKTRACE_FRAMES);
@@ -204,12 +196,11 @@
 }
 
 bool CorkscrewPtrace::Unwind(size_t num_ignore_frames) {
-  ptrace_context_ = load_ptrace_context(backtrace_obj_->Tid());
+  ptrace_context_ = load_ptrace_context(Tid());
 
   backtrace_frame_t frames[MAX_BACKTRACE_FRAMES];
   ssize_t num_frames = unwind_backtrace_ptrace(
-      backtrace_obj_->Tid(), ptrace_context_, frames, num_ignore_frames,
-      MAX_BACKTRACE_FRAMES);
+      Tid(), ptrace_context_, frames, num_ignore_frames, MAX_BACKTRACE_FRAMES);
 
   return GenerateFrameData(frames, num_frames);
 }
@@ -246,3 +237,15 @@
   CorkscrewThread* thread_obj = new CorkscrewThread();
   return new BacktraceThread(thread_obj, thread_obj, tid, map);
 }
+
+//-------------------------------------------------------------------------
+// BacktraceMap create function.
+//-------------------------------------------------------------------------
+BacktraceMap* BacktraceMap::Create(pid_t pid) {
+  BacktraceMap* map = new CorkscrewMap(pid);
+  if (!map->Build()) {
+    delete map;
+    return NULL;
+  }
+  return map;
+}
diff --git a/libbacktrace/Corkscrew.h b/libbacktrace/Corkscrew.h
index 229bb01..1633398 100644
--- a/libbacktrace/Corkscrew.h
+++ b/libbacktrace/Corkscrew.h
@@ -26,26 +26,9 @@
 
 #include <corkscrew/backtrace.h>
 
-#include "Backtrace.h"
+#include "BacktraceImpl.h"
 #include "BacktraceThread.h"
 
-class CorkscrewCommon : public BacktraceImpl {
-public:
-  bool GenerateFrameData(backtrace_frame_t* cork_frames, ssize_t num_frames);
-
-  virtual BacktraceMap* CreateBacktraceMap(pid_t pid) { return new BacktraceMap(pid); }
-};
-
-class CorkscrewCurrent : public CorkscrewCommon {
-public:
-  CorkscrewCurrent();
-  virtual ~CorkscrewCurrent();
-
-  virtual bool Unwind(size_t num_ignore_threads);
-
-  virtual std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset);
-};
-
 class CorkscrewMap : public BacktraceMap {
 public:
   CorkscrewMap(pid_t pid);
@@ -59,17 +42,28 @@
   map_info_t* map_info_;
 };
 
+class CorkscrewCommon : public BacktraceImpl {
+public:
+  bool GenerateFrameData(backtrace_frame_t* cork_frames, ssize_t num_frames);
+};
+
+class CorkscrewCurrent : public CorkscrewCommon {
+public:
+  CorkscrewCurrent();
+  virtual ~CorkscrewCurrent();
+
+  virtual bool Unwind(size_t num_ignore_threads);
+
+  virtual std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset);
+};
+
 class CorkscrewThread : public CorkscrewCurrent, public BacktraceThreadInterface {
 public:
   CorkscrewThread();
   virtual ~CorkscrewThread();
 
-  virtual bool Init();
-
   virtual void ThreadUnwind(
       siginfo_t* siginfo, void* sigcontext, size_t num_ignore_frames);
-
-  virtual BacktraceMap* CreateBacktraceMap(pid_t pid) { return new CorkscrewMap(pid); }
 };
 
 class CorkscrewPtrace : public CorkscrewCommon {
diff --git a/libbacktrace/UnwindCurrent.cpp b/libbacktrace/UnwindCurrent.cpp
index d1195ee..17b71b9 100644
--- a/libbacktrace/UnwindCurrent.cpp
+++ b/libbacktrace/UnwindCurrent.cpp
@@ -25,6 +25,7 @@
 #include <libunwind.h>
 
 #include "UnwindCurrent.h"
+#include "UnwindMap.h"
 
 // Define the ucontext_t structures needed for each supported arch.
 #if defined(__arm__)
@@ -119,8 +120,8 @@
       }
 
       if (resolve) {
-        frame->func_name = backtrace_obj_->GetFunctionName(frame->pc, &frame->func_offset);
-        frame->map = backtrace_obj_->FindMap(frame->pc);
+        frame->func_name = GetFunctionName(frame->pc, &frame->func_offset);
+        frame->map = FindMap(frame->pc);
       } else {
         frame->map = NULL;
         frame->func_offset = 0;
@@ -171,10 +172,6 @@
 UnwindThread::~UnwindThread() {
 }
 
-bool UnwindThread::Init() {
-  return true;
-}
-
 void UnwindThread::ThreadUnwind(
     siginfo_t* /*siginfo*/, void* sigcontext, size_t num_ignore_frames) {
   ExtractContext(sigcontext);
diff --git a/libbacktrace/UnwindCurrent.h b/libbacktrace/UnwindCurrent.h
index 8302c0b..acce110 100644
--- a/libbacktrace/UnwindCurrent.h
+++ b/libbacktrace/UnwindCurrent.h
@@ -19,7 +19,7 @@
 
 #include <string>
 
-#include "Backtrace.h"
+#include "BacktraceImpl.h"
 #include "BacktraceThread.h"
 
 #define UNW_LOCAL_ONLY
@@ -38,8 +38,6 @@
 
   void ExtractContext(void* sigcontext);
 
-  virtual BacktraceMap* CreateBacktraceMap(pid_t pid) { return new BacktraceMap(pid); }
-
 protected:
   unw_context_t context_;
 };
@@ -49,8 +47,6 @@
   UnwindThread();
   virtual ~UnwindThread();
 
-  virtual bool Init();
-
   virtual void ThreadUnwind(
       siginfo_t* siginfo, void* sigcontext, size_t num_ignore_frames);
 };
diff --git a/libbacktrace/UnwindMap.cpp b/libbacktrace/UnwindMap.cpp
new file mode 100644
index 0000000..9c8193b
--- /dev/null
+++ b/libbacktrace/UnwindMap.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2014 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 LOG_TAG "libbacktrace"
+
+#include <pthread.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <backtrace/BacktraceMap.h>
+
+#include <libunwind.h>
+
+#include "UnwindMap.h"
+
+//-------------------------------------------------------------------------
+// libunwind has a single shared address space for the current process
+// aka local. If multiple maps are created for the current pid, then
+// only update the local address space once, and keep a reference count
+// of maps using the same map cursor.
+//-------------------------------------------------------------------------
+static pthread_mutex_t g_map_mutex = PTHREAD_MUTEX_INITIALIZER;
+static unw_map_cursor_t* g_map_cursor = NULL;
+static int g_map_references = 0;
+
+UnwindMap::UnwindMap(pid_t pid) : BacktraceMap(pid) {
+  map_cursor_.map_list = NULL;
+}
+
+UnwindMap::~UnwindMap() {
+  if (pid_ == getpid()) {
+    pthread_mutex_lock(&g_map_mutex);
+    if (--g_map_references == 0) {
+      // Clear the local address space map.
+      unw_map_set(unw_local_addr_space, NULL);
+      unw_map_cursor_destroy(&map_cursor_);
+    }
+    pthread_mutex_unlock(&g_map_mutex);
+  } else {
+    unw_map_cursor_destroy(&map_cursor_);
+  }
+}
+
+bool UnwindMap::Build() {
+  bool return_value = true;
+  if (pid_ == getpid()) {
+    pthread_mutex_lock(&g_map_mutex);
+    if (g_map_references == 0) {
+      return_value = (unw_map_cursor_create(&map_cursor_, pid_) == 0);
+      if (return_value) {
+        // Set the local address space to this cursor map.
+        unw_map_set(unw_local_addr_space, &map_cursor_);
+        g_map_references = 1;
+        g_map_cursor = &map_cursor_;
+      }
+    } else {
+      g_map_references++;
+      map_cursor_ = *g_map_cursor;
+    }
+    pthread_mutex_unlock(&g_map_mutex);
+  } else {
+    return_value = (unw_map_cursor_create(&map_cursor_, pid_) == 0);
+  }
+
+  if (!return_value)
+    return false;
+
+  // Use the map_cursor information to construct the BacktraceMap data
+  // rather than reparsing /proc/self/maps.
+  unw_map_cursor_reset(&map_cursor_);
+  unw_map_t unw_map;
+  while (unw_map_cursor_get(&map_cursor_, &unw_map)) {
+    backtrace_map_t map;
+
+    map.start = unw_map.start;
+    map.end = unw_map.end;
+    map.flags = unw_map.flags;
+    map.name = unw_map.path;
+
+    // The maps are in descending order, but we want them in ascending order.
+    maps_.push_front(map);
+  }
+
+  return true;
+}
+
+//-------------------------------------------------------------------------
+// BacktraceMap create function.
+//-------------------------------------------------------------------------
+BacktraceMap* BacktraceMap::Create(pid_t pid) {
+  BacktraceMap* map = new UnwindMap(pid);
+  if (!map->Build()) {
+    delete map;
+    return NULL;
+  }
+  return map;
+}
diff --git a/libbacktrace/UnwindMap.h b/libbacktrace/UnwindMap.h
new file mode 100644
index 0000000..5a874e8
--- /dev/null
+++ b/libbacktrace/UnwindMap.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2014 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_MAP_H
+#define _LIBBACKTRACE_UNWIND_MAP_H
+
+#include <backtrace/BacktraceMap.h>
+
+// The unw_map_cursor_t structure is different depending on whether it is
+// the local or remote version. In order to get the correct version, include
+// libunwind.h first then this header.
+
+class UnwindMap : public BacktraceMap {
+public:
+  UnwindMap(pid_t pid);
+  virtual ~UnwindMap();
+
+  virtual bool Build();
+
+  unw_map_cursor_t* GetMapCursor() { return &map_cursor_; }
+
+private:
+  unw_map_cursor_t map_cursor_;
+};
+
+#endif // _LIBBACKTRACE_UNWIND_MAP_H
diff --git a/libbacktrace/UnwindPtrace.cpp b/libbacktrace/UnwindPtrace.cpp
index e45c5f8..732dae8 100644
--- a/libbacktrace/UnwindPtrace.cpp
+++ b/libbacktrace/UnwindPtrace.cpp
@@ -25,6 +25,7 @@
 #include <libunwind.h>
 #include <libunwind-ptrace.h>
 
+#include "UnwindMap.h"
 #include "UnwindPtrace.h"
 
 UnwindPtrace::UnwindPtrace() : addr_space_(NULL), upt_info_(NULL) {
@@ -36,6 +37,10 @@
     upt_info_ = NULL;
   }
   if (addr_space_) {
+    // Remove the map from the address space before destroying it.
+    // It will be freed in the UnwindMap destructor.
+    unw_map_set(addr_space_, NULL);
+
     unw_destroy_addr_space(addr_space_);
     addr_space_ = NULL;
   }
@@ -48,7 +53,10 @@
     return false;
   }
 
-  upt_info_ = reinterpret_cast<struct UPT_info*>(_UPT_create(backtrace_obj_->Tid()));
+  UnwindMap* map = static_cast<UnwindMap*>(GetMap());
+  unw_map_set(addr_space_, map->GetMapCursor());
+
+  upt_info_ = reinterpret_cast<struct UPT_info*>(_UPT_create(Tid()));
   if (!upt_info_) {
     BACK_LOGW("Failed to create upt info.");
     return false;
@@ -91,9 +99,9 @@
         prev->stack_size = frame->sp - prev->sp;
       }
 
-      frame->func_name = backtrace_obj_->GetFunctionName(frame->pc, &frame->func_offset);
+      frame->func_name = GetFunctionName(frame->pc, &frame->func_offset);
 
-      frame->map = backtrace_obj_->FindMap(frame->pc);
+      frame->map = FindMap(frame->pc);
 
       num_frames++;
     } else {
diff --git a/libbacktrace/UnwindPtrace.h b/libbacktrace/UnwindPtrace.h
index 05375dd..1e82117 100644
--- a/libbacktrace/UnwindPtrace.h
+++ b/libbacktrace/UnwindPtrace.h
@@ -19,7 +19,7 @@
 
 #include <string>
 
-#include "Backtrace.h"
+#include "BacktraceImpl.h"
 
 #include <libunwind.h>
 
@@ -32,8 +32,6 @@
 
   virtual std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset);
 
-  virtual BacktraceMap* CreateBacktraceMap(pid_t pid) { return new BacktraceMap(pid); }
-
 private:
   unw_addr_space_t addr_space_;
   struct UPT_info* upt_info_;
diff --git a/libbacktrace/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp
index 0ff7897..23eaf92 100644
--- a/libbacktrace/backtrace_test.cpp
+++ b/libbacktrace/backtrace_test.cpp
@@ -247,7 +247,7 @@
   ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, VerifyMaxBacktrace, NULL), 0);
 }
 
-void VerifyProcTest(pid_t pid, pid_t tid,
+void VerifyProcTest(pid_t pid, pid_t tid, bool share_map,
                     bool (*ReadyFunc)(Backtrace*),
                     void (*VerifyFunc)(Backtrace*)) {
   pid_t ptrace_tid;
@@ -264,7 +264,11 @@
       // Wait for the process to get to a stopping point.
       WaitForStop(ptrace_tid);
 
-      UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, tid));
+      UniquePtr<BacktraceMap> map;
+      if (share_map) {
+        map.reset(BacktraceMap::Create(pid));
+      }
+      UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, tid, map.get()));
       ASSERT_TRUE(backtrace->Unwind(0));
       ASSERT_TRUE(backtrace.get() != NULL);
       if (ReadyFunc(backtrace.get())) {
@@ -285,7 +289,21 @@
     ASSERT_NE(test_level_one(1, 2, 3, 4, NULL, NULL), 0);
     exit(1);
   }
-  VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, ReadyLevelBacktrace, VerifyLevelDump);
+  VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, false, ReadyLevelBacktrace, VerifyLevelDump);
+
+  kill(pid, SIGKILL);
+  int status;
+  ASSERT_EQ(waitpid(pid, &status, 0), pid);
+}
+
+TEST(libbacktrace, ptrace_trace_shared_map) {
+  pid_t pid;
+  if ((pid = fork()) == 0) {
+    ASSERT_NE(test_level_one(1, 2, 3, 4, NULL, NULL), 0);
+    exit(1);
+  }
+
+  VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, true, ReadyLevelBacktrace, VerifyLevelDump);
 
   kill(pid, SIGKILL);
   int status;
@@ -298,7 +316,7 @@
     ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, NULL, NULL), 0);
     exit(1);
   }
-  VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, ReadyMaxBacktrace, VerifyMaxDump);
+  VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, false, ReadyMaxBacktrace, VerifyMaxDump);
 
   kill(pid, SIGKILL);
   int status;
@@ -323,7 +341,7 @@
     ASSERT_NE(test_level_one(1, 2, 3, 4, NULL, NULL), 0);
     exit(1);
   }
-  VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, ReadyLevelBacktrace, VerifyProcessIgnoreFrames);
+  VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, false, ReadyLevelBacktrace, VerifyProcessIgnoreFrames);
 
   kill(pid, SIGKILL);
   int status;
@@ -387,7 +405,7 @@
     if (pid == *it) {
       continue;
     }
-    VerifyProcTest(pid, *it, ReadyLevelBacktrace, VerifyLevelDump);
+    VerifyProcTest(pid, *it, false, ReadyLevelBacktrace, VerifyLevelDump);
   }
   ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0);
 
@@ -586,6 +604,29 @@
   }
 }
 
+// This test is for UnwindMaps that should share the same map cursor when
+// multiple maps are created for the current process at the same time.
+TEST(libbacktrace, simultaneous_maps) {
+  BacktraceMap* map1 = BacktraceMap::Create(getpid());
+  BacktraceMap* map2 = BacktraceMap::Create(getpid());
+  BacktraceMap* map3 = BacktraceMap::Create(getpid());
+
+  Backtrace* back1 = Backtrace::Create(getpid(), BACKTRACE_CURRENT_THREAD, map1);
+  EXPECT_TRUE(back1->Unwind(0));
+  delete back1;
+  delete map1;
+
+  Backtrace* back2 = Backtrace::Create(getpid(), BACKTRACE_CURRENT_THREAD, map2);
+  EXPECT_TRUE(back2->Unwind(0));
+  delete back2;
+  delete map2;
+
+  Backtrace* back3 = Backtrace::Create(getpid(), BACKTRACE_CURRENT_THREAD, map3);
+  EXPECT_TRUE(back3->Unwind(0));
+  delete back3;
+  delete map3;
+}
+
 TEST(libbacktrace, format_test) {
   UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), BACKTRACE_CURRENT_THREAD));
   ASSERT_TRUE(backtrace.get() != NULL);