libBacktraceOffline: fix using debug frame with load bias.

Bug: http://b/69383534
Test: run backtrace_test.
Change-Id: I295d9dc8f3e5b628f179b2eaeac21fa93de130b0
diff --git a/libbacktrace/BacktraceOffline.cpp b/libbacktrace/BacktraceOffline.cpp
index 0a2f5a3..3041492 100644
--- a/libbacktrace/BacktraceOffline.cpp
+++ b/libbacktrace/BacktraceOffline.cpp
@@ -320,7 +320,7 @@
   }
   if (debug_frame->has_debug_frame || debug_frame->has_gnu_debugdata) {
     unw_dyn_info_t di;
-    unw_word_t segbase = map.start - map.offset;
+    unw_word_t segbase = map.start - debug_frame->min_vaddr;
     // TODO: http://b/32916571
     // TODO: Do it ourselves is more efficient than calling libunwind functions.
     int found = dwarf_find_debug_frame(0, &di, ip, segbase, filename.c_str(), map.start, map.end);
diff --git a/libbacktrace/backtrace_offline_test.cpp b/libbacktrace/backtrace_offline_test.cpp
index 0a1f33d..bf4cf2a 100644
--- a/libbacktrace/backtrace_offline_test.cpp
+++ b/libbacktrace/backtrace_offline_test.cpp
@@ -27,6 +27,7 @@
 #include <vector>
 
 #include <android-base/file.h>
+#include <android-base/logging.h>
 #include <android-base/macros.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
@@ -249,12 +250,21 @@
         return false;
       }
       HexStringToRawData(&line[pos], &testdata->unw_context, size);
+#if defined(__arm__)
+    } else if (android::base::StartsWith(line, "regs:")) {
+      uint64_t pc;
+      uint64_t sp;
+      sscanf(line.c_str(), "regs: pc: %" SCNx64 " sp: %" SCNx64, &pc, &sp);
+      testdata->unw_context.regs[13] = sp;
+      testdata->unw_context.regs[15] = pc;
+#endif
     } else if (android::base::StartsWith(line, "stack:")) {
       size_t size;
       int pos;
       sscanf(line.c_str(),
              "stack: start: %" SCNx64 " end: %" SCNx64 " size: %zu %n",
              &testdata->stack_info.start, &testdata->stack_info.end, &size, &pos);
+      CHECK_EQ(testdata->stack_info.end - testdata->stack_info.start, size);
       testdata->stack.resize(size);
       HexStringToRawData(&line[pos], &testdata->stack[0], size);
       testdata->stack_info.data = testdata->stack.data();
@@ -389,3 +399,44 @@
     ASSERT_EQ(name, testdata.symbols[i].name);
   }
 }
+
+TEST(libbacktrace, offline_debug_frame_with_load_bias) {
+  if (std::string(ABI_STRING) != "arm") {
+    GTEST_LOG_(INFO) << "Skipping test since offline for arm on " << ABI_STRING
+                     << " isn't supported.";
+    return;
+  }
+  const std::string testlib_path(GetTestPath("libandroid_runtime.so"));
+  struct stat st;
+  ASSERT_EQ(0, stat(testlib_path.c_str(), &st)) << "can't find testlib " << testlib_path;
+
+  const std::string offline_testdata_path(GetTestPath("offline_testdata_for_libandroid_runtime"));
+  OfflineTestData testdata;
+  ASSERT_TRUE(ReadOfflineTestData(offline_testdata_path, &testdata));
+
+  // Fix path of /system/lib/libandroid_runtime.so.
+  for (auto& map : testdata.maps) {
+    if (map.name.find("libandroid_runtime.so") != std::string::npos) {
+      map.name = testlib_path;
+    }
+  }
+
+  // Do offline backtrace.
+  std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(testdata.pid, testdata.maps));
+  ASSERT_TRUE(map != nullptr);
+
+  std::unique_ptr<Backtrace> backtrace(
+      Backtrace::CreateOffline(testdata.pid, testdata.tid, map.get(), testdata.stack_info));
+  ASSERT_TRUE(backtrace != nullptr);
+
+  ucontext_t ucontext = GetUContextFromUnwContext(testdata.unw_context);
+  ASSERT_TRUE(backtrace->Unwind(0, &ucontext));
+
+  ASSERT_EQ(testdata.symbols.size(), backtrace->NumFrames());
+  for (size_t i = 0; i < backtrace->NumFrames(); ++i) {
+    uintptr_t vaddr_in_file =
+        backtrace->GetFrame(i)->pc - testdata.maps[0].start + testdata.maps[0].load_bias;
+    std::string name = FunctionNameForAddress(vaddr_in_file, testdata.symbols);
+    ASSERT_EQ(name, testdata.symbols[i].name);
+  }
+}
diff --git a/libbacktrace/testdata/arm/libandroid_runtime.so b/libbacktrace/testdata/arm/libandroid_runtime.so
new file mode 100644
index 0000000..e4283e6
--- /dev/null
+++ b/libbacktrace/testdata/arm/libandroid_runtime.so
Binary files differ
diff --git a/libbacktrace/testdata/arm/offline_testdata_for_libandroid_runtime b/libbacktrace/testdata/arm/offline_testdata_for_libandroid_runtime
new file mode 100644
index 0000000..a12bc3c
--- /dev/null
+++ b/libbacktrace/testdata/arm/offline_testdata_for_libandroid_runtime
@@ -0,0 +1,6 @@
+pid: 7288 tid: 31656
+regs: pc: f1f6dc49 sp: d8fe6930
+map: start: f1f10000 end: f2049000 offset: 0 load_bias: 10000 flags: 5 name: /system/lib/libandroid_runtime.so
+stack: start: d8fe6954 end: d8fe6958 size: 4 e7dcf6f1
+function: start: 6dbf9 end: 6dce5 name: android::AndroidRuntime::javaThreadShell
+function: start: 6dce5 end: 6dd79 name: android::AndroidRuntime::javaCreateThreadEtc