Rewrite libbacktrace to be all C++.

This includes removing the map_info.c source and replacing it with the
BacktraceMap class to handle all map related code.

Change all callers of libbacktrace map functionality.

Also modify the corkscrew thread code so that it doesn't need to build
the map twice (once in the corkscrew format and once in the libbacktrace
format).

Change-Id: I32865a39f83a3dd6f958fc03c2759ba47d12382e
diff --git a/libbacktrace/Android.mk b/libbacktrace/Android.mk
index d2fd79e..d729c1c 100644
--- a/libbacktrace/Android.mk
+++ b/libbacktrace/Android.mk
@@ -2,8 +2,8 @@
 
 common_src := \
 	Backtrace.cpp \
+	BacktraceMap.cpp \
 	BacktraceThread.cpp \
-	map_info.c \
 	thread_utils.c \
 
 common_cflags := \
@@ -222,7 +222,7 @@
 
 else
 LOCAL_SRC_FILES += \
-	map_info.c \
+	BacktraceMap.cpp \
 
 endif
 
diff --git a/libbacktrace/Backtrace.cpp b/libbacktrace/Backtrace.cpp
index 20667e0..d7b40ab 100644
--- a/libbacktrace/Backtrace.cpp
+++ b/libbacktrace/Backtrace.cpp
@@ -27,46 +27,28 @@
 #include <string>
 
 #include <backtrace/Backtrace.h>
-#include <cutils/log.h>
+#include <backtrace/BacktraceMap.h>
 
 #include "Backtrace.h"
 #include "thread_utils.h"
 
 //-------------------------------------------------------------------------
-// BacktraceImpl functions.
-//-------------------------------------------------------------------------
-backtrace_t* BacktraceImpl::GetBacktraceData() {
-  return &backtrace_obj_->backtrace_;
-}
-
-//-------------------------------------------------------------------------
 // Backtrace functions.
 //-------------------------------------------------------------------------
-Backtrace::Backtrace(BacktraceImpl* impl, pid_t pid, backtrace_map_info_t* map_info)
-    : impl_(impl), map_info_(map_info), map_info_requires_delete_(false) {
+Backtrace::Backtrace(BacktraceImpl* impl, pid_t pid, BacktraceMap* map)
+    : pid_(pid), tid_(-1), map_(map), map_shared_(true), impl_(impl) {
   impl_->SetParent(this);
-  backtrace_.num_frames = 0;
-  backtrace_.pid = pid;
-  backtrace_.tid = -1;
 
-  if (map_info_ == NULL) {
-    // Create the map and manage it internally.
-    map_info_ = backtrace_create_map_info_list(pid);
-    map_info_requires_delete_ = true;
+  if (map_ == NULL) {
+    // The map will be created when needed.
+    map_shared_ = false;
   }
 }
 
 Backtrace::~Backtrace() {
-  for (size_t i = 0; i < NumFrames(); i++) {
-    if (backtrace_.frames[i].func_name) {
-      free(backtrace_.frames[i].func_name);
-      backtrace_.frames[i].func_name = NULL;
-    }
-  }
-
-  if (map_info_ && map_info_requires_delete_) {
-    backtrace_destroy_map_info_list(map_info_);
-    map_info_ = NULL;
+  if (map_ && !map_shared_) {
+    delete map_;
+    map_ = NULL;
   }
 
   if (impl_) {
@@ -109,47 +91,36 @@
   return true;
 }
 
-const char* Backtrace::GetMapName(uintptr_t pc, uintptr_t* map_start) {
-  const backtrace_map_info_t* map_info = FindMapInfo(pc);
-  if (map_info) {
-    if (map_start) {
-      *map_start = map_info->start;
-    }
-    return map_info->name;
-  }
-  return NULL;
-}
-
-const backtrace_map_info_t* Backtrace::FindMapInfo(uintptr_t ptr) {
-  return backtrace_find_map_info(map_info_, ptr);
-}
-
 std::string Backtrace::FormatFrameData(size_t frame_num) {
-  return FormatFrameData(&backtrace_.frames[frame_num]);
+  if (frame_num >= frames_.size()) {
+    return "";
+  }
+  return FormatFrameData(&frames_[frame_num]);
 }
 
 std::string Backtrace::FormatFrameData(const backtrace_frame_data_t* frame) {
   const char* map_name;
-  if (frame->map_name) {
-    map_name = frame->map_name;
+  if (frame->map && !frame->map->name.empty()) {
+    map_name = frame->map->name.c_str();
   } else {
     map_name = "<unknown>";
   }
+
   uintptr_t relative_pc;
-  if (frame->map_offset) {
-    relative_pc = frame->map_offset;
+  if (frame->map) {
+    relative_pc = frame->pc - frame->map->start;
   } else {
     relative_pc = frame->pc;
   }
 
   char buf[512];
-  if (frame->func_name && frame->func_offset) {
+  if (!frame->func_name.empty() && frame->func_offset) {
     snprintf(buf, sizeof(buf), "#%02zu pc %0*" PRIxPTR "  %s (%s+%" PRIuPTR ")",
              frame->num, (int)sizeof(uintptr_t)*2, relative_pc, map_name,
-             frame->func_name, frame->func_offset);
-  } else if (frame->func_name) {
+             frame->func_name.c_str(), frame->func_offset);
+  } else if (!frame->func_name.empty()) {
     snprintf(buf, sizeof(buf), "#%02zu pc %0*" PRIxPTR "  %s (%s)", frame->num,
-             (int)sizeof(uintptr_t)*2, relative_pc, map_name, frame->func_name);
+             (int)sizeof(uintptr_t)*2, relative_pc, map_name, frame->func_name.c_str());
   } else {
     snprintf(buf, sizeof(buf), "#%02zu pc %0*" PRIxPTR "  %s", frame->num,
              (int)sizeof(uintptr_t)*2, relative_pc, map_name);
@@ -158,13 +129,35 @@
   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.
 //-------------------------------------------------------------------------
 BacktraceCurrent::BacktraceCurrent(
-    BacktraceImpl* impl, backtrace_map_info_t *map_info) : Backtrace(impl, getpid(), map_info) {
-
-  backtrace_.pid = getpid();
+    BacktraceImpl* impl, BacktraceMap* map) : Backtrace(impl, getpid(), map) {
 }
 
 BacktraceCurrent::~BacktraceCurrent() {
@@ -175,8 +168,8 @@
     return false;
   }
 
-  const backtrace_map_info_t* map_info = FindMapInfo(ptr);
-  if (map_info && map_info->is_readable) {
+  const backtrace_map_t* map = FindMap(ptr);
+  if (map && map->flags & PROT_READ) {
     *out_value = *reinterpret_cast<uint32_t*>(ptr);
     return true;
   } else {
@@ -190,9 +183,9 @@
 // BacktracePtrace functions.
 //-------------------------------------------------------------------------
 BacktracePtrace::BacktracePtrace(
-    BacktraceImpl* impl, pid_t pid, pid_t tid, backtrace_map_info_t* map_info)
-    : Backtrace(impl, pid, map_info) {
-  backtrace_.tid = tid;
+    BacktraceImpl* impl, pid_t pid, pid_t tid, BacktraceMap* map)
+    : Backtrace(impl, pid, map) {
+  tid_ = tid;
 }
 
 BacktracePtrace::~BacktracePtrace() {
@@ -220,103 +213,16 @@
 #endif
 }
 
-Backtrace* Backtrace::Create(pid_t pid, pid_t tid, backtrace_map_info_t* map_info) {
+Backtrace* Backtrace::Create(pid_t pid, pid_t tid, BacktraceMap* map) {
   if (pid == BACKTRACE_CURRENT_PROCESS || pid == getpid()) {
     if (tid == BACKTRACE_CURRENT_THREAD || tid == gettid()) {
-      return CreateCurrentObj(map_info);
+      return CreateCurrentObj(map);
     } else {
-      return CreateThreadObj(tid, map_info);
+      return CreateThreadObj(tid, map);
     }
   } else if (tid == BACKTRACE_CURRENT_THREAD) {
-    return CreatePtraceObj(pid, pid, map_info);
+    return CreatePtraceObj(pid, pid, map);
   } else {
-    return CreatePtraceObj(pid, tid, map_info);
-  }
-}
-
-//-------------------------------------------------------------------------
-// Common interface functions.
-//-------------------------------------------------------------------------
-bool backtrace_create_context_with_map(
-    backtrace_context_t* context, pid_t pid, pid_t tid, size_t num_ignore_frames,
-    backtrace_map_info_t* map_info) {
-  Backtrace* backtrace = Backtrace::Create(pid, tid, map_info);
-  if (!backtrace) {
-    return false;
-  }
-  if (!backtrace->Unwind(num_ignore_frames)) {
-    delete backtrace;
-    return false;
-  }
-
-  context->data = backtrace;
-  context->backtrace = backtrace->GetBacktrace();
-  return true;
-}
-
-bool backtrace_create_context(
-    backtrace_context_t* context, pid_t pid, pid_t tid, size_t num_ignore_frames) {
-  return backtrace_create_context_with_map(context, pid, tid, num_ignore_frames, NULL);
-}
-
-
-void backtrace_destroy_context(backtrace_context_t* context) {
-  if (context->data) {
-    Backtrace* backtrace = reinterpret_cast<Backtrace*>(context->data);
-    delete backtrace;
-    context->data = NULL;
-  }
-  context->backtrace = NULL;
-}
-
-const backtrace_t* backtrace_get_data(backtrace_context_t* context) {
-  if (context && context->data) {
-    Backtrace* backtrace = reinterpret_cast<Backtrace*>(context->data);
-    return backtrace->GetBacktrace();
-  }
-  return NULL;
-}
-
-bool backtrace_read_word(const backtrace_context_t* context, uintptr_t ptr, uint32_t* value) {
-  if (context->data) {
-    Backtrace* backtrace = reinterpret_cast<Backtrace*>(context->data);
-    return backtrace->ReadWord(ptr, value);
-  }
-  return true;
-}
-
-const char* backtrace_get_map_name(const backtrace_context_t* context, uintptr_t pc, uintptr_t* map_start) {
-  if (context->data) {
-    Backtrace* backtrace = reinterpret_cast<Backtrace*>(context->data);
-    return backtrace->GetMapName(pc, map_start);
-  }
-  return NULL;
-}
-
-char* backtrace_get_func_name(const backtrace_context_t* context, uintptr_t pc, uintptr_t* func_offset) {
-  if (context->data) {
-    Backtrace* backtrace = reinterpret_cast<Backtrace*>(context->data);
-    std::string func_name = backtrace->GetFunctionName(pc, func_offset);
-    if (!func_name.empty()) {
-      return strdup(func_name.c_str());
-    }
-  }
-  return NULL;
-}
-
-void backtrace_format_frame_data(
-    const backtrace_context_t* context, size_t frame_num, char* buf,
-    size_t buf_size) {
-  if (buf_size == 0 || buf == NULL) {
-    BACK_LOGW("bad call buf %p buf_size %zu", buf, buf_size);
-  } else if (context->data) {
-    Backtrace* backtrace = reinterpret_cast<Backtrace*>(context->data);
-    std::string line = backtrace->FormatFrameData(frame_num);
-    if (line.size() > buf_size) {
-      memcpy(buf, line.c_str(), buf_size-1);
-      buf[buf_size] = '\0';
-    } else {
-      memcpy(buf, line.c_str(), line.size()+1);
-    }
+    return CreatePtraceObj(pid, tid, map);
   }
 }
diff --git a/libbacktrace/Backtrace.h b/libbacktrace/Backtrace.h
index d741ef1..31fcaf2 100644
--- a/libbacktrace/Backtrace.h
+++ b/libbacktrace/Backtrace.h
@@ -18,8 +18,10 @@
 #define _LIBBACKTRACE_BACKTRACE_H
 
 #include <backtrace/Backtrace.h>
+#include <backtrace/BacktraceMap.h>
 
 #include <sys/types.h>
+#include <log/log.h>
 
 // Macro to log the function name along with the warning message.
 #define BACK_LOGW(format, ...) \
@@ -37,15 +39,19 @@
 
   void SetParent(Backtrace* backtrace) { backtrace_obj_ = backtrace; }
 
+  virtual BacktraceMap* CreateBacktraceMap(pid_t pid) = 0;
+
 protected:
-  backtrace_t* GetBacktraceData();
+  inline std::vector<backtrace_frame_data_t>* GetFrames() { return &backtrace_obj_->frames_; }
+
+  inline bool BuildMap() { return backtrace_obj_->BuildMap(); }
 
   Backtrace* backtrace_obj_;
 };
 
 class BacktraceCurrent : public Backtrace {
 public:
-  BacktraceCurrent(BacktraceImpl* impl, backtrace_map_info_t* map_info);
+  BacktraceCurrent(BacktraceImpl* impl, BacktraceMap* map);
   virtual ~BacktraceCurrent();
 
   bool ReadWord(uintptr_t ptr, uint32_t* out_value);
@@ -53,14 +59,14 @@
 
 class BacktracePtrace : public Backtrace {
 public:
-  BacktracePtrace(BacktraceImpl* impl, pid_t pid, pid_t tid, backtrace_map_info_t* map_info);
+  BacktracePtrace(BacktraceImpl* impl, pid_t pid, pid_t tid, BacktraceMap* map);
   virtual ~BacktracePtrace();
 
   bool ReadWord(uintptr_t ptr, uint32_t* out_value);
 };
 
-Backtrace* CreateCurrentObj(backtrace_map_info_t* map_info);
-Backtrace* CreatePtraceObj(pid_t pid, pid_t tid, backtrace_map_info_t* map_info);
-Backtrace* CreateThreadObj(pid_t tid, backtrace_map_info_t* map_info);
+Backtrace* CreateCurrentObj(BacktraceMap* map);
+Backtrace* CreatePtraceObj(pid_t pid, pid_t tid, BacktraceMap* map);
+Backtrace* CreateThreadObj(pid_t tid, BacktraceMap* map);
 
 #endif // _LIBBACKTRACE_BACKTRACE_H
diff --git a/libbacktrace/BacktraceMap.cpp b/libbacktrace/BacktraceMap.cpp
new file mode 100644
index 0000000..b3b4300
--- /dev/null
+++ b/libbacktrace/BacktraceMap.cpp
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ */
+
+#include <ctype.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <string>
+#include <vector>
+
+#include <backtrace/BacktraceMap.h>
+#include <log/log.h>
+
+BacktraceMap::BacktraceMap(pid_t pid) : pid_(pid) {
+  if (pid_ < 0) {
+    pid_ = getpid();
+  }
+}
+
+BacktraceMap::~BacktraceMap() {
+}
+
+const backtrace_map_t* BacktraceMap::Find(uintptr_t addr) {
+  for (BacktraceMap::const_iterator it = begin();
+       it != end(); ++it) {
+    if (addr >= it->start && addr < it->end) {
+      return &*it;
+    }
+  }
+  return NULL;
+}
+
+bool BacktraceMap::ParseLine(const char* line, backtrace_map_t* map) {
+  unsigned long int start;
+  unsigned long int end;
+  char permissions[5];
+  int name_pos;
+
+#if defined(__APPLE__)
+// Mac OS vmmap(1) output:
+// __TEXT                 0009f000-000a1000 [    8K     8K] r-x/rwx SM=COW  /Volumes/android/dalvik-dev/out/host/darwin-x86/bin/libcorkscrew_test\n
+// 012345678901234567890123456789012345678901234567890123456789
+// 0         1         2         3         4         5
+  if (sscanf(line, "%*21c %lx-%lx [%*13c] %3c/%*3c SM=%*3c  %n",
+             &start, &end, permissions, &name_pos) != 3) {
+#else
+// Linux /proc/<pid>/maps lines:
+// 6f000000-6f01e000 rwxp 00000000 00:0c 16389419   /system/lib/libcomposer.so\n
+// 012345678901234567890123456789012345678901234567890123456789
+// 0         1         2         3         4         5
+  if (sscanf(line, "%lx-%lx %4s %*x %*x:%*x %*d%n",
+             &start, &end, permissions, &name_pos) != 3) {
+#endif
+    return false;
+  }
+
+  map->start = start;
+  map->end = end;
+  map->flags = PROT_NONE;
+  if (permissions[0] == 'r') {
+    map->flags |= PROT_READ;
+  }
+  if (permissions[1] == 'w') {
+    map->flags |= PROT_WRITE;
+  }
+  if (permissions[2] == 'x') {
+    map->flags |= PROT_EXEC;
+  }
+
+  while (isspace(line[name_pos])) {
+    name_pos += 1;
+  }
+  map->name = line+name_pos;
+  if (!map->name.empty() && map->name[map->name.length()-1] == '\n') {
+    map->name.erase(map->name.length()-1);
+  }
+
+  ALOGV("Parsed map: start=%p, end=%p, flags=%x, name=%s",
+        map->start, map->end, map->flags, map->name.c_str());
+  return true;
+}
+
+bool BacktraceMap::Build() {
+#if defined(__APPLE__)
+  char cmd[sizeof(pid_t)*3 + sizeof("vmmap -w -resident -submap -allSplitLibs -interleaved ") + 1];
+#else
+  char path[sizeof(pid_t)*3 + sizeof("/proc//maps") + 1];
+#endif
+  char line[1024];
+
+#if defined(__APPLE__)
+  // cmd is guaranteed to always be big enough to hold this string.
+  sprintf(cmd, "vmmap -w -resident -submap -allSplitLibs -interleaved %d", pid);
+  FILE* fp = popen(cmd, "r");
+#else
+  // path is guaranteed to always be big enough to hold this string.
+  sprintf(path, "/proc/%d/maps", pid_);
+  FILE* fp = fopen(path, "r");
+#endif
+  if (fp == NULL) {
+    return false;
+  }
+
+  while(fgets(line, sizeof(line), fp)) {
+    backtrace_map_t map;
+    if (ParseLine(line, &map)) {
+      maps_.push_back(map);
+    }
+  }
+#if defined(__APPLE__)
+  pclose(fp);
+#else
+  fclose(fp);
+#endif
+
+  return true;
+}
diff --git a/libbacktrace/BacktraceThread.cpp b/libbacktrace/BacktraceThread.cpp
index 70616b0..9953dc1 100644
--- a/libbacktrace/BacktraceThread.cpp
+++ b/libbacktrace/BacktraceThread.cpp
@@ -22,7 +22,6 @@
 #include <sys/types.h>
 
 #include <cutils/atomic.h>
-#include <cutils/log.h>
 
 #include "BacktraceThread.h"
 #include "thread_utils.h"
@@ -115,30 +114,21 @@
 
 BacktraceThread::BacktraceThread(
     BacktraceImpl* impl, BacktraceThreadInterface* thread_intf, pid_t tid,
-    backtrace_map_info_t* map_info)
-    : BacktraceCurrent(impl, map_info), thread_intf_(thread_intf) {
-  backtrace_.tid = tid;
+    BacktraceMap* map)
+    : BacktraceCurrent(impl, map), thread_intf_(thread_intf) {
+  tid_ = tid;
 }
 
 BacktraceThread::~BacktraceThread() {
 }
 
 void BacktraceThread::FinishUnwind() {
-  for (size_t i = 0; i < NumFrames(); i++) {
-    backtrace_frame_data_t* frame = &backtrace_.frames[i];
+  for (std::vector<backtrace_frame_data_t>::iterator it = frames_.begin();
+       it != frames_.end(); ++it) {
+    it->map = FindMap(it->pc);
 
-    frame->map_offset = 0;
-    uintptr_t map_start;
-    frame->map_name = GetMapName(frame->pc, &map_start);
-    if (frame->map_name) {
-      frame->map_offset = frame->pc - map_start;
-    }
-
-    frame->func_offset = 0;
-    std::string func_name = GetFunctionName(frame->pc, &frame->func_offset);
-    if (!func_name.empty()) {
-      frame->func_name = strdup(func_name.c_str());
-    }
+    it->func_offset = 0;
+    it->func_name = GetFunctionName(it->pc, &it->func_offset);
   }
 }
 
diff --git a/libbacktrace/BacktraceThread.h b/libbacktrace/BacktraceThread.h
index a4b6ecb..cae496a 100644
--- a/libbacktrace/BacktraceThread.h
+++ b/libbacktrace/BacktraceThread.h
@@ -22,12 +22,12 @@
 
 #include "Backtrace.h"
 
-typedef enum {
+enum state_e {
   STATE_WAITING = 0,
   STATE_DUMPING,
   STATE_DONE,
   STATE_CANCEL,
-} state_e;
+};
 
 class BacktraceThreadInterface;
 
@@ -71,7 +71,7 @@
   // subclass both.
   BacktraceThread(
       BacktraceImpl* impl, BacktraceThreadInterface* thread_intf, pid_t tid,
-      backtrace_map_info_t* map_info);
+      BacktraceMap* map);
   virtual ~BacktraceThread();
 
   virtual bool Unwind(size_t num_ignore_frames);
diff --git a/libbacktrace/Corkscrew.cpp b/libbacktrace/Corkscrew.cpp
index 63b8c7c..fd31a26 100644
--- a/libbacktrace/Corkscrew.cpp
+++ b/libbacktrace/Corkscrew.cpp
@@ -16,12 +16,11 @@
 
 #define LOG_TAG "libbacktrace"
 
-#include <backtrace/backtrace.h>
+#include <backtrace/Backtrace.h>
 
 #include <string.h>
 
 #include <backtrace-arch.h>
-#include <cutils/log.h>
 #include <corkscrew/backtrace.h>
 
 #ifndef __USE_GNU
@@ -32,6 +31,48 @@
 #include "Corkscrew.h"
 
 //-------------------------------------------------------------------------
+// CorkscrewMap functions.
+//-------------------------------------------------------------------------
+CorkscrewMap::CorkscrewMap(pid_t pid) : BacktraceMap(pid), map_info_(NULL) {
+}
+
+CorkscrewMap::~CorkscrewMap() {
+  if (map_info_) {
+    free_map_info_list(map_info_);
+    map_info_ = NULL;
+  }
+}
+
+bool CorkscrewMap::Build() {
+  map_info_ = load_map_info_list(pid_);
+
+  // Use the information in map_info_ to construct the BacktraceMap data
+  // rather than reparsing /proc/self/maps.
+  map_info_t* cur_map = map_info_;
+  while (cur_map) {
+    backtrace_map_t map;
+    map.start = cur_map->start;
+    map.end = cur_map->end;
+    map.flags = 0;
+    if (cur_map->is_readable) {
+      map.flags |= PROT_READ;
+    }
+    if (cur_map->is_writable) {
+      map.flags |= PROT_WRITE;
+    }
+    if (cur_map->is_executable) {
+      map.flags |= PROT_EXEC;
+    }
+    map.name = cur_map->name;
+
+    maps_.push_back(map);
+
+    cur_map = cur_map->next;
+  }
+  return map_info_ != NULL;
+}
+
+//-------------------------------------------------------------------------
 // CorkscrewCommon functions.
 //-------------------------------------------------------------------------
 bool CorkscrewCommon::GenerateFrameData(
@@ -41,29 +82,19 @@
     return false;
   }
 
-  backtrace_t* data = GetBacktraceData();
-  data->num_frames = num_frames;
-  for (size_t i = 0; i < data->num_frames; i++) {
-    backtrace_frame_data_t* frame = &data->frames[i];
-    frame->num = i;
-    frame->pc = cork_frames[i].absolute_pc;
-    frame->sp = cork_frames[i].stack_top;
-    frame->stack_size = cork_frames[i].stack_size;
-    frame->map_name = NULL;
-    frame->map_offset = 0;
-    frame->func_name = NULL;
-    frame->func_offset = 0;
+  std::vector<backtrace_frame_data_t>* frames = GetFrames();
+  frames->resize(num_frames);
+  size_t i = 0;
+  for (std::vector<backtrace_frame_data_t>::iterator it = frames->begin();
+       it != frames->end(); ++it, ++i) {
+    it->num = i;
+    it->pc = cork_frames[i].absolute_pc;
+    it->sp = cork_frames[i].stack_top;
+    it->stack_size = cork_frames[i].stack_size;
+    it->func_offset = 0;
 
-    uintptr_t map_start;
-    frame->map_name = backtrace_obj_->GetMapName(frame->pc, &map_start);
-    if (frame->map_name) {
-      frame->map_offset = frame->pc - map_start;
-    }
-
-    std::string func_name = backtrace_obj_->GetFunctionName(frame->pc, &frame->func_offset);
-    if (!func_name.empty()) {
-      frame->func_name = strdup(func_name.c_str());
-    }
+    it->map = backtrace_obj_->FindMap(it->pc);
+    it->func_name = backtrace_obj_->GetFunctionName(it->pc, &it->func_offset);
   }
   return true;
 }
@@ -88,23 +119,23 @@
   *offset = 0;
 
   Dl_info info;
-  const backtrace_map_info_t* map_info = backtrace_obj_->FindMapInfo(pc);
-  if (map_info) {
+  const backtrace_map_t* map = backtrace_obj_->FindMap(pc);
+  if (map) {
     if (dladdr((const void*)pc, &info)) {
       if (info.dli_sname) {
-        *offset = pc - map_info->start - (uintptr_t)info.dli_saddr + (uintptr_t)info.dli_fbase;
+        *offset = pc - map->start - (uintptr_t)info.dli_saddr + (uintptr_t)info.dli_fbase;
         return info.dli_sname;
       }
     } else {
       // dladdr(3) didn't find a symbol; maybe it's static? Look in the ELF file...
-      symbol_table_t* symbol_table = load_symbol_table(map_info->name);
+      symbol_table_t* symbol_table = load_symbol_table(map->name.c_str());
       if (symbol_table) {
         // First check if we can find the symbol using a relative pc.
         std::string name;
-        const symbol_t* elf_symbol = find_symbol(symbol_table, pc - map_info->start);
+        const symbol_t* elf_symbol = find_symbol(symbol_table, pc - map->start);
         if (elf_symbol) {
           name = elf_symbol->name;
-          *offset = pc - map_info->start - elf_symbol->start;
+          *offset = pc - map->start - elf_symbol->start;
         } else if ((elf_symbol = find_symbol(symbol_table, pc)) != NULL) {
           // Found the symbol using the absolute pc.
           name = elf_symbol->name;
@@ -125,39 +156,36 @@
 }
 
 CorkscrewThread::~CorkscrewThread() {
-  if (corkscrew_map_info_) {
-    free_map_info_list(corkscrew_map_info_);
-    corkscrew_map_info_ = NULL;
-  }
 }
 
 bool CorkscrewThread::Init() {
-  corkscrew_map_info_ = load_map_info_list(backtrace_obj_->Pid());
-  return corkscrew_map_info_ != NULL;
+  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 frames[MAX_BACKTRACE_FRAMES];
+  backtrace_frame_t cork_frames[MAX_BACKTRACE_FRAMES];
+  CorkscrewMap* map = static_cast<CorkscrewMap*>(backtrace_obj_->GetMap());
   ssize_t num_frames = unwind_backtrace_signal_arch(
-      siginfo, sigcontext, corkscrew_map_info_, frames, num_ignore_frames,
-      MAX_BACKTRACE_FRAMES);
+      siginfo, sigcontext, map->GetMapInfo(), cork_frames,
+      num_ignore_frames, MAX_BACKTRACE_FRAMES);
   if (num_frames > 0) {
-    backtrace_t* data = GetBacktraceData();
-    data->num_frames = num_frames;
-    for (size_t i = 0; i < data->num_frames; i++) {
-      backtrace_frame_data_t* frame = &data->frames[i];
-      frame->num = i;
-      frame->pc = frames[i].absolute_pc;
-      frame->sp = frames[i].stack_top;
-      frame->stack_size = frames[i].stack_size;
-
-      frame->map_offset = 0;
-      frame->map_name = NULL;
-      frame->map_offset = 0;
-
-      frame->func_offset = 0;
-      frame->func_name = NULL;
+    std::vector<backtrace_frame_data_t>* frames = GetFrames();
+    frames->resize(num_frames);
+    size_t i = 0;
+    for (std::vector<backtrace_frame_data_t>::iterator it = frames->begin();
+         it != frames->end(); ++it, ++i) {
+      it->num = i;
+      it->pc = cork_frames[i].absolute_pc;
+      it->sp = cork_frames[i].stack_top;
+      it->stack_size = cork_frames[i].stack_size;
+      it->map = NULL;
+      it->func_offset = 0;
     }
   }
 }
@@ -206,15 +234,15 @@
 //-------------------------------------------------------------------------
 // C++ object creation functions.
 //-------------------------------------------------------------------------
-Backtrace* CreateCurrentObj(backtrace_map_info_t* map_info) {
-  return new BacktraceCurrent(new CorkscrewCurrent(), map_info);
+Backtrace* CreateCurrentObj(BacktraceMap* map) {
+  return new BacktraceCurrent(new CorkscrewCurrent(), map);
 }
 
-Backtrace* CreatePtraceObj(pid_t pid, pid_t tid, backtrace_map_info_t* map_info) {
-  return new BacktracePtrace(new CorkscrewPtrace(), pid, tid, map_info);
+Backtrace* CreatePtraceObj(pid_t pid, pid_t tid, BacktraceMap* map) {
+  return new BacktracePtrace(new CorkscrewPtrace(), pid, tid, map);
 }
 
-Backtrace* CreateThreadObj(pid_t tid, backtrace_map_info_t* map_info) {
+Backtrace* CreateThreadObj(pid_t tid, BacktraceMap* map) {
   CorkscrewThread* thread_obj = new CorkscrewThread();
-  return new BacktraceThread(thread_obj, thread_obj, tid, map_info);
+  return new BacktraceThread(thread_obj, thread_obj, tid, map);
 }
diff --git a/libbacktrace/Corkscrew.h b/libbacktrace/Corkscrew.h
index 7cb125c..229bb01 100644
--- a/libbacktrace/Corkscrew.h
+++ b/libbacktrace/Corkscrew.h
@@ -21,8 +21,8 @@
 
 #include <string>
 
-#include <backtrace/backtrace.h>
 #include <backtrace/Backtrace.h>
+#include <backtrace/BacktraceMap.h>
 
 #include <corkscrew/backtrace.h>
 
@@ -32,6 +32,8 @@
 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 {
@@ -44,6 +46,19 @@
   virtual std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset);
 };
 
+class CorkscrewMap : public BacktraceMap {
+public:
+  CorkscrewMap(pid_t pid);
+  virtual ~CorkscrewMap();
+
+  virtual bool Build();
+
+  map_info_t* GetMapInfo() { return map_info_; }
+
+private:
+  map_info_t* map_info_;
+};
+
 class CorkscrewThread : public CorkscrewCurrent, public BacktraceThreadInterface {
 public:
   CorkscrewThread();
@@ -54,8 +69,7 @@
   virtual void ThreadUnwind(
       siginfo_t* siginfo, void* sigcontext, size_t num_ignore_frames);
 
-private:
-  map_info_t* corkscrew_map_info_;
+  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 6cdbc42..747eb21 100644
--- a/libbacktrace/UnwindCurrent.cpp
+++ b/libbacktrace/UnwindCurrent.cpp
@@ -18,9 +18,8 @@
 
 #include <sys/types.h>
 
-#include <cutils/log.h>
-
-#include <backtrace/backtrace.h>
+#include <backtrace/Backtrace.h>
+#include <backtrace/BacktraceMap.h>
 
 #define UNW_LOCAL_ONLY
 #include <libunwind.h>
@@ -79,9 +78,6 @@
 }
 
 bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, bool resolve) {
-  backtrace_t* backtrace = GetBacktraceData();
-  backtrace->num_frames = 0;
-
   // The cursor structure is pretty large, do not put it on the stack.
   unw_cursor_t* cursor = new unw_cursor_t;
   int ret = unw_init_local(cursor, &context_);
@@ -91,6 +87,9 @@
     return false;
   }
 
+  std::vector<backtrace_frame_data_t>* frames = GetFrames();
+  frames->reserve(MAX_BACKTRACE_FRAMES);
+  size_t num_frames = 0;
   do {
     unw_word_t pc;
     ret = unw_get_reg(cursor, UNW_REG_IP, &pc);
@@ -106,42 +105,32 @@
     }
 
     if (num_ignore_frames == 0) {
-      size_t num_frames = backtrace->num_frames;
-      backtrace_frame_data_t* frame = &backtrace->frames[num_frames];
+      frames->resize(num_frames+1);
+      backtrace_frame_data_t* frame = &frames->at(num_frames);
       frame->num = num_frames;
       frame->pc = static_cast<uintptr_t>(pc);
       frame->sp = static_cast<uintptr_t>(sp);
       frame->stack_size = 0;
-      frame->map_name = NULL;
-      frame->map_offset = 0;
-      frame->func_name = NULL;
-      frame->func_offset = 0;
 
       if (num_frames > 0) {
         // Set the stack size for the previous frame.
-        backtrace_frame_data_t* prev = &backtrace->frames[num_frames-1];
+        backtrace_frame_data_t* prev = &frames->at(num_frames-1);
         prev->stack_size = frame->sp - prev->sp;
       }
 
       if (resolve) {
-        std::string func_name = backtrace_obj_->GetFunctionName(frame->pc, &frame->func_offset);
-        if (!func_name.empty()) {
-          frame->func_name = strdup(func_name.c_str());
-        }
-
-        uintptr_t map_start;
-        frame->map_name = backtrace_obj_->GetMapName(frame->pc, &map_start);
-        if (frame->map_name) {
-          frame->map_offset = frame->pc - map_start;
-        }
+        frame->func_name = backtrace_obj_->GetFunctionName(frame->pc, &frame->func_offset);
+        frame->map = backtrace_obj_->FindMap(frame->pc);
+      } else {
+        frame->map = NULL;
+        frame->func_offset = 0;
       }
-
-      backtrace->num_frames++;
+      num_frames++;
     } else {
       num_ignore_frames--;
     }
     ret = unw_step (cursor);
-  } while (ret > 0 && backtrace->num_frames < MAX_BACKTRACE_FRAMES);
+  } while (ret > 0 && num_frames < MAX_BACKTRACE_FRAMES);
 
   delete cursor;
   return true;
@@ -195,11 +184,11 @@
 //-------------------------------------------------------------------------
 // C++ object creation function.
 //-------------------------------------------------------------------------
-Backtrace* CreateCurrentObj(backtrace_map_info_t* map_info) {
-  return new BacktraceCurrent(new UnwindCurrent(), map_info);
+Backtrace* CreateCurrentObj(BacktraceMap* map) {
+  return new BacktraceCurrent(new UnwindCurrent(), map);
 }
 
-Backtrace* CreateThreadObj(pid_t tid, backtrace_map_info_t* map_info) {
+Backtrace* CreateThreadObj(pid_t tid, BacktraceMap* map) {
   UnwindThread* thread_obj = new UnwindThread();
-  return new BacktraceThread(thread_obj, thread_obj, tid, map_info);
+  return new BacktraceThread(thread_obj, thread_obj, tid, map);
 }
diff --git a/libbacktrace/UnwindCurrent.h b/libbacktrace/UnwindCurrent.h
index 7dc977d..8302c0b 100644
--- a/libbacktrace/UnwindCurrent.h
+++ b/libbacktrace/UnwindCurrent.h
@@ -38,6 +38,8 @@
 
   void ExtractContext(void* sigcontext);
 
+  virtual BacktraceMap* CreateBacktraceMap(pid_t pid) { return new BacktraceMap(pid); }
+
 protected:
   unw_context_t context_;
 };
diff --git a/libbacktrace/UnwindPtrace.cpp b/libbacktrace/UnwindPtrace.cpp
index 6fecb76..e45c5f8 100644
--- a/libbacktrace/UnwindPtrace.cpp
+++ b/libbacktrace/UnwindPtrace.cpp
@@ -16,13 +16,12 @@
 
 #define LOG_TAG "libbacktrace"
 
-#include <backtrace/backtrace.h>
+#include <backtrace/Backtrace.h>
+#include <backtrace/BacktraceMap.h>
 
 #include <sys/types.h>
 #include <string.h>
 
-#include <cutils/log.h>
-
 #include <libunwind.h>
 #include <libunwind-ptrace.h>
 
@@ -55,9 +54,6 @@
     return false;
   }
 
-  backtrace_t* backtrace = GetBacktraceData();
-  backtrace->num_frames = 0;
-
   unw_cursor_t cursor;
   int ret = unw_init_remote(&cursor, addr_space_, upt_info_);
   if (ret < 0) {
@@ -65,6 +61,9 @@
     return false;
   }
 
+  std::vector<backtrace_frame_data_t>* frames = GetFrames();
+  frames->reserve(MAX_BACKTRACE_FRAMES);
+  size_t num_frames = 0;
   do {
     unw_word_t pc;
     ret = unw_get_reg(&cursor, UNW_REG_IP, &pc);
@@ -80,39 +79,28 @@
     }
 
     if (num_ignore_frames == 0) {
-      size_t num_frames = backtrace->num_frames;
-      backtrace_frame_data_t* frame = &backtrace->frames[num_frames];
+      frames->resize(num_frames+1);
+      backtrace_frame_data_t* frame = &frames->at(num_frames);
       frame->num = num_frames;
       frame->pc = static_cast<uintptr_t>(pc);
       frame->sp = static_cast<uintptr_t>(sp);
       frame->stack_size = 0;
-      frame->map_name = NULL;
-      frame->map_offset = 0;
-      frame->func_name = NULL;
-      frame->func_offset = 0;
 
       if (num_frames > 0) {
-        backtrace_frame_data_t* prev = &backtrace->frames[num_frames-1];
+        backtrace_frame_data_t* prev = &frames->at(num_frames-1);
         prev->stack_size = frame->sp - prev->sp;
       }
 
-      std::string func_name = backtrace_obj_->GetFunctionName(frame->pc, &frame->func_offset);
-      if (!func_name.empty()) {
-        frame->func_name = strdup(func_name.c_str());
-      }
+      frame->func_name = backtrace_obj_->GetFunctionName(frame->pc, &frame->func_offset);
 
-      uintptr_t map_start;
-      frame->map_name = backtrace_obj_->GetMapName(frame->pc, &map_start);
-      if (frame->map_name) {
-        frame->map_offset = frame->pc - map_start;
-      }
+      frame->map = backtrace_obj_->FindMap(frame->pc);
 
-      backtrace->num_frames++;
+      num_frames++;
     } else {
       num_ignore_frames--;
     }
     ret = unw_step (&cursor);
-  } while (ret > 0 && backtrace->num_frames < MAX_BACKTRACE_FRAMES);
+  } while (ret > 0 && num_frames < MAX_BACKTRACE_FRAMES);
 
   return true;
 }
@@ -132,6 +120,6 @@
 //-------------------------------------------------------------------------
 // C++ object creation function.
 //-------------------------------------------------------------------------
-Backtrace* CreatePtraceObj(pid_t pid, pid_t tid, backtrace_map_info_t* map_info) {
-  return new BacktracePtrace(new UnwindPtrace(), pid, tid, map_info);
+Backtrace* CreatePtraceObj(pid_t pid, pid_t tid, BacktraceMap* map) {
+  return new BacktracePtrace(new UnwindPtrace(), pid, tid, map);
 }
diff --git a/libbacktrace/UnwindPtrace.h b/libbacktrace/UnwindPtrace.h
index 781405b..05375dd 100644
--- a/libbacktrace/UnwindPtrace.h
+++ b/libbacktrace/UnwindPtrace.h
@@ -32,6 +32,8 @@
 
   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 2fed993..0ff7897 100644
--- a/libbacktrace/backtrace_test.cpp
+++ b/libbacktrace/backtrace_test.cpp
@@ -29,6 +29,7 @@
 #include <unistd.h>
 
 #include <backtrace/Backtrace.h>
+#include <backtrace/BacktraceMap.h>
 #include <UniquePtr.h>
 
 #include <cutils/atomic.h>
@@ -50,18 +51,18 @@
 // Number of simultaneous threads running in our forked process.
 #define NUM_PTRACE_THREADS 5
 
-typedef struct {
+struct thread_t {
   pid_t tid;
   int32_t state;
   pthread_t threadId;
-} thread_t;
+};
 
-typedef struct {
+struct dump_thread_t {
   thread_t thread;
   Backtrace* backtrace;
   int32_t* now;
   int32_t done;
-} dump_thread_t;
+};
 
 extern "C" {
 // Prototypes for functions in the test library.
@@ -103,9 +104,8 @@
 bool ReadyLevelBacktrace(Backtrace* backtrace) {
   // See if test_level_four is in the backtrace.
   bool found = false;
-  for (size_t i = 0; i < backtrace->NumFrames(); i++) {
-    const backtrace_frame_data_t* frame = backtrace->GetFrame(i);
-    if (frame->func_name != NULL && strcmp(frame->func_name, "test_level_four") == 0) {
+  for (Backtrace::const_iterator it = backtrace->begin(); it != backtrace->end(); ++it) {
+    if (it->func_name == "test_level_four") {
       found = true;
       break;
     }
@@ -122,8 +122,7 @@
   // frame we want.
   size_t frame_num = 0;
   for (size_t i = backtrace->NumFrames()-1; i > 2; i--) {
-    if (backtrace->GetFrame(i)->func_name != NULL &&
-        strcmp(backtrace->GetFrame(i)->func_name, "test_level_one") == 0) {
+    if (backtrace->GetFrame(i)->func_name == "test_level_one") {
       frame_num = i;
       break;
     }
@@ -131,14 +130,10 @@
   ASSERT_LT(static_cast<size_t>(0), frame_num);
   ASSERT_LE(static_cast<size_t>(3), frame_num);
 
-  ASSERT_TRUE(NULL != backtrace->GetFrame(frame_num)->func_name);
-  ASSERT_STREQ(backtrace->GetFrame(frame_num)->func_name, "test_level_one");
-  ASSERT_TRUE(NULL != backtrace->GetFrame(frame_num-1)->func_name);
-  ASSERT_STREQ(backtrace->GetFrame(frame_num-1)->func_name, "test_level_two");
-  ASSERT_TRUE(NULL != backtrace->GetFrame(frame_num-2)->func_name);
-  ASSERT_STREQ(backtrace->GetFrame(frame_num-2)->func_name, "test_level_three");
-  ASSERT_TRUE(NULL != backtrace->GetFrame(frame_num-3)->func_name);
-  ASSERT_STREQ(backtrace->GetFrame(frame_num-3)->func_name, "test_level_four");
+  ASSERT_EQ(backtrace->GetFrame(frame_num)->func_name, "test_level_one");
+  ASSERT_EQ(backtrace->GetFrame(frame_num-1)->func_name, "test_level_two");
+  ASSERT_EQ(backtrace->GetFrame(frame_num-2)->func_name, "test_level_three");
+  ASSERT_EQ(backtrace->GetFrame(frame_num-3)->func_name, "test_level_four");
 }
 
 void VerifyLevelBacktrace(void*) {
@@ -157,9 +152,8 @@
 void VerifyMaxDump(Backtrace* backtrace) {
   ASSERT_EQ(backtrace->NumFrames(), static_cast<size_t>(MAX_BACKTRACE_FRAMES));
   // Verify that the last frame is our recursive call.
-  ASSERT_TRUE(NULL != backtrace->GetFrame(MAX_BACKTRACE_FRAMES-1)->func_name);
-  ASSERT_STREQ(backtrace->GetFrame(MAX_BACKTRACE_FRAMES-1)->func_name,
-               "test_recursive_call");
+  ASSERT_EQ(backtrace->GetFrame(MAX_BACKTRACE_FRAMES-1)->func_name,
+            "test_recursive_call");
 }
 
 void VerifyMaxBacktrace(void*) {
@@ -220,8 +214,7 @@
       EXPECT_EQ(bt_ign2->GetFrame(i)->sp, bt_all->GetFrame(i+2)->sp);
       EXPECT_EQ(bt_ign2->GetFrame(i)->stack_size, bt_all->GetFrame(i+2)->stack_size);
     }
-    if (!check && bt_ign2->GetFrame(i)->func_name &&
-        strcmp(bt_ign2->GetFrame(i)->func_name, cur_proc) == 0) {
+    if (!check && bt_ign2->GetFrame(i)->func_name == cur_proc) {
       check = true;
     }
   }
@@ -598,38 +591,64 @@
   ASSERT_TRUE(backtrace.get() != NULL);
 
   backtrace_frame_data_t frame;
-  memset(&frame, 0, sizeof(backtrace_frame_data_t));
+  frame.num = 1;
+  frame.pc = 2;
+  frame.sp = 0;
+  frame.stack_size = 0;
+  frame.map = NULL;
+  frame.func_offset = 0;
 
+  backtrace_map_t map;
+  map.start = 0;
+  map.end = 0;
+
+  // Check no map set.
   frame.num = 1;
 #if defined(__LP64__)
-  EXPECT_STREQ("#01 pc 0000000000000000  <unknown>",
+  EXPECT_EQ("#01 pc 0000000000000002  <unknown>",
 #else
-  EXPECT_STREQ("#01 pc 00000000  <unknown>",
+  EXPECT_EQ("#01 pc 00000002  <unknown>",
 #endif
-               backtrace->FormatFrameData(&frame).c_str());
+            backtrace->FormatFrameData(&frame));
 
-  frame.pc = 0x12345678;
-  frame.map_name = "MapFake";
+  // Check map name empty, but exists.
+  frame.map = &map;
+  map.start = 1;
 #if defined(__LP64__)
-  EXPECT_STREQ("#01 pc 0000000012345678  MapFake",
+  EXPECT_EQ("#01 pc 0000000000000001  <unknown>",
 #else
-  EXPECT_STREQ("#01 pc 12345678  MapFake",
+  EXPECT_EQ("#01 pc 00000001  <unknown>",
 #endif
-               backtrace->FormatFrameData(&frame).c_str());
+            backtrace->FormatFrameData(&frame));
 
-  frame.func_name = const_cast<char*>("ProcFake");
+
+  // Check relative pc is set and map name is set.
+  frame.pc = 0x12345679;
+  frame.map = &map;
+  map.name = "MapFake";
+  map.start =  1;
 #if defined(__LP64__)
-  EXPECT_STREQ("#01 pc 0000000012345678  MapFake (ProcFake)",
+  EXPECT_EQ("#01 pc 0000000012345678  MapFake",
 #else
-  EXPECT_STREQ("#01 pc 12345678  MapFake (ProcFake)",
+  EXPECT_EQ("#01 pc 12345678  MapFake",
 #endif
-               backtrace->FormatFrameData(&frame).c_str());
+            backtrace->FormatFrameData(&frame));
 
+  // Check func_name is set, but no func offset.
+  frame.func_name = "ProcFake";
+#if defined(__LP64__)
+  EXPECT_EQ("#01 pc 0000000012345678  MapFake (ProcFake)",
+#else
+  EXPECT_EQ("#01 pc 12345678  MapFake (ProcFake)",
+#endif
+            backtrace->FormatFrameData(&frame));
+
+  // Check func_name is set, and func offset is non-zero.
   frame.func_offset = 645;
 #if defined(__LP64__)
-  EXPECT_STREQ("#01 pc 0000000012345678  MapFake (ProcFake+645)",
+  EXPECT_EQ("#01 pc 0000000012345678  MapFake (ProcFake+645)",
 #else
-  EXPECT_STREQ("#01 pc 12345678  MapFake (ProcFake+645)",
+  EXPECT_EQ("#01 pc 12345678  MapFake (ProcFake+645)",
 #endif
-               backtrace->FormatFrameData(&frame).c_str());
+            backtrace->FormatFrameData(&frame));
 }
diff --git a/libbacktrace/map_info.c b/libbacktrace/map_info.c
deleted file mode 100644
index 9cc6e01..0000000
--- a/libbacktrace/map_info.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (C) 2013 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 <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-#include <pthread.h>
-#include <unistd.h>
-#include <cutils/log.h>
-#include <sys/time.h>
-
-#include <backtrace/backtrace.h>
-
-#if defined(__APPLE__)
-
-// Mac OS vmmap(1) output:
-// __TEXT                 0009f000-000a1000 [    8K     8K] r-x/rwx SM=COW  /Volumes/android/dalvik-dev/out/host/darwin-x86/bin/libcorkscrew_test\n
-// 012345678901234567890123456789012345678901234567890123456789
-// 0         1         2         3         4         5
-static backtrace_map_info_t* parse_vmmap_line(const char* line) {
-  unsigned long int start;
-  unsigned long int end;
-  char permissions[4];
-  int name_pos;
-  if (sscanf(line, "%*21c %lx-%lx [%*13c] %3c/%*3c SM=%*3c  %n",
-             &start, &end, permissions, &name_pos) != 3) {
-    return NULL;
-  }
-
-  const char* name = line + name_pos;
-  size_t name_len = strlen(name);
-
-  backtrace_map_info_t* mi = calloc(1, sizeof(backtrace_map_info_t) + name_len);
-  if (mi != NULL) {
-    mi->start = start;
-    mi->end = end;
-    mi->is_readable = permissions[0] == 'r';
-    mi->is_writable = permissions[1] == 'w';
-    mi->is_executable = permissions[2] == 'x';
-    memcpy(mi->name, name, name_len);
-    mi->name[name_len - 1] = '\0';
-    ALOGV("Parsed map: start=0x%08x, end=0x%08x, "
-          "is_readable=%d, is_writable=%d is_executable=%d, name=%s",
-          mi->start, mi->end,
-          mi->is_readable, mi->is_writable, mi->is_executable, mi->name);
-  }
-  return mi;
-}
-
-backtrace_map_info_t* backtrace_create_map_info_list(pid_t pid) {
-  char cmd[1024];
-  if (pid < 0) {
-    pid = getpid();
-  }
-  snprintf(cmd, sizeof(cmd), "vmmap -w -resident -submap -allSplitLibs -interleaved %d", pid);
-  FILE* fp = popen(cmd, "r");
-  if (fp == NULL) {
-    return NULL;
-  }
-
-  char line[1024];
-  backtrace_map_info_t* milist = NULL;
-  while (fgets(line, sizeof(line), fp) != NULL) {
-    backtrace_map_info_t* mi = parse_vmmap_line(line);
-    if (mi != NULL) {
-      mi->next = milist;
-      milist = mi;
-    }
-  }
-  pclose(fp);
-  return milist;
-}
-
-#else
-
-// Linux /proc/<pid>/maps lines:
-// 6f000000-6f01e000 rwxp 00000000 00:0c 16389419   /system/lib/libcomposer.so\n
-// 012345678901234567890123456789012345678901234567890123456789
-// 0         1         2         3         4         5
-static backtrace_map_info_t* parse_maps_line(const char* line)
-{
-  unsigned long int start;
-  unsigned long int end;
-  char permissions[5];
-  int name_pos;
-  if (sscanf(line, "%lx-%lx %4s %*x %*x:%*x %*d%n", &start, &end,
-             permissions, &name_pos) != 3) {
-    return NULL;
-  }
-
-  while (isspace(line[name_pos])) {
-    name_pos += 1;
-  }
-  const char* name = line + name_pos;
-  size_t name_len = strlen(name);
-  if (name_len && name[name_len - 1] == '\n') {
-    name_len -= 1;
-  }
-
-  backtrace_map_info_t* mi = calloc(1, sizeof(backtrace_map_info_t) + name_len + 1);
-  if (mi) {
-    mi->start = start;
-    mi->end = end;
-    mi->is_readable = strlen(permissions) == 4 && permissions[0] == 'r';
-    mi->is_writable = strlen(permissions) == 4 && permissions[1] == 'w';
-    mi->is_executable = strlen(permissions) == 4 && permissions[2] == 'x';
-    memcpy(mi->name, name, name_len);
-    mi->name[name_len] = '\0';
-    ALOGV("Parsed map: start=0x%08x, end=0x%08x, "
-          "is_readable=%d, is_writable=%d, is_executable=%d, name=%s",
-          mi->start, mi->end,
-          mi->is_readable, mi->is_writable, mi->is_executable, mi->name);
-  }
-  return mi;
-}
-
-backtrace_map_info_t* backtrace_create_map_info_list(pid_t tid) {
-  char path[PATH_MAX];
-  char line[1024];
-  FILE* fp;
-  backtrace_map_info_t* milist = NULL;
-
-  if (tid < 0) {
-    tid = getpid();
-  }
-  snprintf(path, PATH_MAX, "/proc/%d/maps", tid);
-  fp = fopen(path, "r");
-  if (fp) {
-    while(fgets(line, sizeof(line), fp)) {
-      backtrace_map_info_t* mi = parse_maps_line(line);
-      if (mi) {
-        mi->next = milist;
-        milist = mi;
-      }
-    }
-    fclose(fp);
-  }
-  return milist;
-}
-
-#endif
-
-void backtrace_destroy_map_info_list(backtrace_map_info_t* milist) {
-  while (milist) {
-    backtrace_map_info_t* next = milist->next;
-    free(milist);
-    milist = next;
-  }
-}
-
-const backtrace_map_info_t* backtrace_find_map_info(
-    const backtrace_map_info_t* milist, uintptr_t addr) {
-  const backtrace_map_info_t* mi = milist;
-  while (mi && !(addr >= mi->start && addr < mi->end)) {
-    mi = mi->next;
-  }
-  return mi;
-}