Read maps data before using and do safe reads.

Rather than only updating the maps when a pc can't be found, always update
the maps before using them. This avoids issues where the maps change
and it could cause a crash reading from a map that has been modified.

This assumes that executed code never gets unloaded, or that the
code is unloaded so infrequently that it doesn't matter. This happens
because the pcs for the backtraces are gathered as the program runs
and those pcs are symbolized and made into relative pcs at a later time.

Also, add safe reading of the elf data when necessary to avoid any
crashes if maps are changing while this is running.

Since the MapEntry objects can be deleted, copy the values for
the current map in the backtrace code to detect when in our own code
instead of keeping a pointer.

Bug: 340988785

Test: malloc_debug unit/system tests pass.
Test: libmemunreachable tests pass.
Change-Id: Ica2ba50a5bcf9e19c7e4033e29a5a67a1847d1a6
diff --git a/libc/malloc_debug/backtrace.cpp b/libc/malloc_debug/backtrace.cpp
index ecb3a80..6a32fca 100644
--- a/libc/malloc_debug/backtrace.cpp
+++ b/libc/malloc_debug/backtrace.cpp
@@ -50,7 +50,7 @@
 typedef struct _Unwind_Context __unwind_context;
 
 static MapData g_map_data;
-static const MapEntry* g_current_code_map = nullptr;
+static MapEntry g_current_code_map;
 
 static _Unwind_Reason_Code find_current_map(__unwind_context* context, void*) {
   uintptr_t ip = _Unwind_GetIP(context);
@@ -58,11 +58,15 @@
   if (ip == 0) {
     return _URC_END_OF_STACK;
   }
-  g_current_code_map = g_map_data.find(ip);
+  auto map = g_map_data.find(ip);
+  if (map != nullptr) {
+    g_current_code_map = *map;
+  }
   return _URC_END_OF_STACK;
 }
 
 void backtrace_startup() {
+  g_map_data.ReadMaps();
   _Unwind_Backtrace(find_current_map, nullptr);
 }
 
@@ -98,7 +102,8 @@
   }
 
   // Do not record the frames that fall in our own shared library.
-  if (g_current_code_map && (ip >= g_current_code_map->start) && ip < g_current_code_map->end) {
+  if (g_current_code_map.start() != 0 && (ip >= g_current_code_map.start()) &&
+      ip < g_current_code_map.end()) {
     return _URC_NO_REASON;
   }
 
@@ -113,6 +118,10 @@
 }
 
 std::string backtrace_string(const uintptr_t* frames, size_t frame_count) {
+  if (g_map_data.NumMaps() == 0) {
+    g_map_data.ReadMaps();
+  }
+
   std::string str;
 
   for (size_t frame_num = 0; frame_num < frame_count; frame_num++) {
@@ -130,14 +139,15 @@
     uintptr_t rel_pc = offset;
     const MapEntry* entry = g_map_data.find(frames[frame_num], &rel_pc);
 
-    const char* soname = (entry != nullptr) ? entry->name.c_str() : info.dli_fname;
+    const char* soname = (entry != nullptr) ? entry->name().c_str() : info.dli_fname;
     if (soname == nullptr) {
       soname = "<unknown>";
     }
 
     char offset_buf[128];
-    if (entry != nullptr && entry->elf_start_offset != 0) {
-      snprintf(offset_buf, sizeof(offset_buf), " (offset 0x%" PRIxPTR ")", entry->elf_start_offset);
+    if (entry != nullptr && entry->elf_start_offset() != 0) {
+      snprintf(offset_buf, sizeof(offset_buf), " (offset 0x%" PRIxPTR ")",
+               entry->elf_start_offset());
     } else {
       offset_buf[0] = '\0';
     }
@@ -167,5 +177,6 @@
 }
 
 void backtrace_log(const uintptr_t* frames, size_t frame_count) {
+  g_map_data.ReadMaps();
   error_log_string(backtrace_string(frames, frame_count).c_str());
 }