Loading libbacktrace/BacktraceOffline.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -222,6 +222,7 @@ bool BacktraceOffline::Unwind(size_t num_ignore_frames, ucontext_t* context) { } else { num_ignore_frames--; } is_debug_frame_used_ = false; ret = unw_step(&cursor); } while (ret > 0 && num_frames < MAX_BACKTRACE_FRAMES); Loading Loading @@ -318,7 +319,8 @@ bool BacktraceOffline::FindProcInfo(unw_addr_space_t addr_space, uint64_t ip, } } } if (debug_frame->has_debug_frame || debug_frame->has_gnu_debugdata) { if (!is_debug_frame_used_ && (debug_frame->has_debug_frame || debug_frame->has_gnu_debugdata)) { is_debug_frame_used_ = true; unw_dyn_info_t di; unw_word_t segbase = map.start - debug_frame->min_vaddr; // TODO: http://b/32916571 Loading libbacktrace/BacktraceOffline.h +10 −1 Original line number Diff line number Diff line Loading @@ -48,7 +48,8 @@ class BacktraceOffline : public Backtrace { bool cache_file) : Backtrace(pid, tid, map), cache_file_(cache_file), context_(nullptr) { context_(nullptr), is_debug_frame_used_(false) { stack_space_.start = stack.start; stack_space_.end = stack.end; stack_space_.data = stack.data; Loading Loading @@ -78,6 +79,14 @@ class BacktraceOffline : public Backtrace { Space arm_extab_space_; Space arm_exidx_space_; Space stack_space_; // is_debug_frame_used_ is to make sure we can try both .debug_frame and .ARM.exidx in // FindProcInfo() on ARM. One example is EsxContext::Clear() in // vendor/lib/egl/libGLESv2_adreno.so. EsxContext::Clear() appears in both .debug_frame and // .ARM.exidx. However, libunwind fails to execute debug_frame instruction // "DW_CFA_offset_extended: r265 at cfa-48". So we need to try .ARM.exidx to unwind that // function. bool is_debug_frame_used_; }; #endif // _LIBBACKTRACE_BACKTRACE_OFFLINE_H libbacktrace/backtrace_offline_test.cpp +19 −49 Original line number Diff line number Diff line Loading @@ -357,26 +357,24 @@ TEST(libbacktrace, offline_arm_exidx) { BacktraceOfflineTest("arm", "libbacktrace_test_arm_exidx.so"); } // This test tests the situation that ranges of functions covered by .eh_frame and .ARM.exidx // overlap with each other, which appears in /system/lib/libart.so. TEST(libbacktrace, offline_unwind_mix_eh_frame_and_arm_exidx) { // TODO: For now, only run on the given arch. if (std::string(ABI_STRING) != "arm") { static void LibUnwindingTest(const std::string& arch, const std::string& testdata_name, const std::string& testlib_name) { if (std::string(ABI_STRING) != arch) { GTEST_LOG_(INFO) << "Skipping test since offline for arm on " << ABI_STRING << " isn't supported."; return; } const std::string testlib_path(GetTestPath("libart.so")); const std::string testlib_path(GetTestPath(testlib_name)); 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_libart")); const std::string offline_testdata_path(GetTestPath(testdata_name)); OfflineTestData testdata; ASSERT_TRUE(ReadOfflineTestData(offline_testdata_path, &testdata)); // Fix path of /system/lib/libart.so. // Fix path of the testlib. for (auto& map : testdata.maps) { if (map.name.find("libart.so") != std::string::npos) { if (map.name.find(testlib_name) != std::string::npos) { map.name = testlib_path; } } Loading @@ -392,9 +390,8 @@ TEST(libbacktrace, offline_unwind_mix_eh_frame_and_arm_exidx) { ucontext_t ucontext = GetUContextFromUnwContext(testdata.unw_context); ASSERT_TRUE(backtrace->Unwind(0, &ucontext)); // The last frame is outside of libart.so ASSERT_EQ(testdata.symbols.size() + 1, backtrace->NumFrames()); for (size_t i = 0; i + 1 < backtrace->NumFrames(); ++i) { 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); Loading @@ -402,43 +399,16 @@ TEST(libbacktrace, offline_unwind_mix_eh_frame_and_arm_exidx) { } } 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; // This test tests the situation that ranges of functions covered by .eh_frame and .ARM.exidx // overlap with each other, which appears in /system/lib/libart.so. TEST(libbacktrace, offline_unwind_mix_eh_frame_and_arm_exidx) { LibUnwindingTest("arm", "offline_testdata_for_libart", "libart.so"); } 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; } TEST(libbacktrace, offline_debug_frame_with_load_bias) { LibUnwindingTest("arm", "offline_testdata_for_libandroid_runtime", "libandroid_runtime.so"); } // 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); } TEST(libbacktrace, offline_try_armexidx_after_debug_frame) { LibUnwindingTest("arm", "offline_testdata_for_libGLESv2_adreno", "libGLESv2_adreno.so"); } libbacktrace/testdata/arm/libGLESv2_adreno.so 0 → 100644 +4.04 MiB File added.No diff preview for this file type. View file libbacktrace/testdata/arm/offline_testdata_for_libGLESv2_adreno 0 → 100644 +6 −0 Original line number Diff line number Diff line pid: 7288 tid: 31656 regs: pc: cc416235 sp: cc17f000 map: start: cc361000 end: cc758000 offset: 0 load_bias: 9000 flags: 5 name: /vendor/lib/egl/libGLESv2_adreno.so stack: start: cc17f254 end: cc17f258 size: 4 b36141cc function: start: be1f0 end: be304 name: EsxContext::Clear(unsigned int, unsigned int, unsigned int, EsxClearValues*) function: start: be058 end: be1f0 name: EsxContext::ClearBuffersForDebug() Loading
libbacktrace/BacktraceOffline.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -222,6 +222,7 @@ bool BacktraceOffline::Unwind(size_t num_ignore_frames, ucontext_t* context) { } else { num_ignore_frames--; } is_debug_frame_used_ = false; ret = unw_step(&cursor); } while (ret > 0 && num_frames < MAX_BACKTRACE_FRAMES); Loading Loading @@ -318,7 +319,8 @@ bool BacktraceOffline::FindProcInfo(unw_addr_space_t addr_space, uint64_t ip, } } } if (debug_frame->has_debug_frame || debug_frame->has_gnu_debugdata) { if (!is_debug_frame_used_ && (debug_frame->has_debug_frame || debug_frame->has_gnu_debugdata)) { is_debug_frame_used_ = true; unw_dyn_info_t di; unw_word_t segbase = map.start - debug_frame->min_vaddr; // TODO: http://b/32916571 Loading
libbacktrace/BacktraceOffline.h +10 −1 Original line number Diff line number Diff line Loading @@ -48,7 +48,8 @@ class BacktraceOffline : public Backtrace { bool cache_file) : Backtrace(pid, tid, map), cache_file_(cache_file), context_(nullptr) { context_(nullptr), is_debug_frame_used_(false) { stack_space_.start = stack.start; stack_space_.end = stack.end; stack_space_.data = stack.data; Loading Loading @@ -78,6 +79,14 @@ class BacktraceOffline : public Backtrace { Space arm_extab_space_; Space arm_exidx_space_; Space stack_space_; // is_debug_frame_used_ is to make sure we can try both .debug_frame and .ARM.exidx in // FindProcInfo() on ARM. One example is EsxContext::Clear() in // vendor/lib/egl/libGLESv2_adreno.so. EsxContext::Clear() appears in both .debug_frame and // .ARM.exidx. However, libunwind fails to execute debug_frame instruction // "DW_CFA_offset_extended: r265 at cfa-48". So we need to try .ARM.exidx to unwind that // function. bool is_debug_frame_used_; }; #endif // _LIBBACKTRACE_BACKTRACE_OFFLINE_H
libbacktrace/backtrace_offline_test.cpp +19 −49 Original line number Diff line number Diff line Loading @@ -357,26 +357,24 @@ TEST(libbacktrace, offline_arm_exidx) { BacktraceOfflineTest("arm", "libbacktrace_test_arm_exidx.so"); } // This test tests the situation that ranges of functions covered by .eh_frame and .ARM.exidx // overlap with each other, which appears in /system/lib/libart.so. TEST(libbacktrace, offline_unwind_mix_eh_frame_and_arm_exidx) { // TODO: For now, only run on the given arch. if (std::string(ABI_STRING) != "arm") { static void LibUnwindingTest(const std::string& arch, const std::string& testdata_name, const std::string& testlib_name) { if (std::string(ABI_STRING) != arch) { GTEST_LOG_(INFO) << "Skipping test since offline for arm on " << ABI_STRING << " isn't supported."; return; } const std::string testlib_path(GetTestPath("libart.so")); const std::string testlib_path(GetTestPath(testlib_name)); 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_libart")); const std::string offline_testdata_path(GetTestPath(testdata_name)); OfflineTestData testdata; ASSERT_TRUE(ReadOfflineTestData(offline_testdata_path, &testdata)); // Fix path of /system/lib/libart.so. // Fix path of the testlib. for (auto& map : testdata.maps) { if (map.name.find("libart.so") != std::string::npos) { if (map.name.find(testlib_name) != std::string::npos) { map.name = testlib_path; } } Loading @@ -392,9 +390,8 @@ TEST(libbacktrace, offline_unwind_mix_eh_frame_and_arm_exidx) { ucontext_t ucontext = GetUContextFromUnwContext(testdata.unw_context); ASSERT_TRUE(backtrace->Unwind(0, &ucontext)); // The last frame is outside of libart.so ASSERT_EQ(testdata.symbols.size() + 1, backtrace->NumFrames()); for (size_t i = 0; i + 1 < backtrace->NumFrames(); ++i) { 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); Loading @@ -402,43 +399,16 @@ TEST(libbacktrace, offline_unwind_mix_eh_frame_and_arm_exidx) { } } 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; // This test tests the situation that ranges of functions covered by .eh_frame and .ARM.exidx // overlap with each other, which appears in /system/lib/libart.so. TEST(libbacktrace, offline_unwind_mix_eh_frame_and_arm_exidx) { LibUnwindingTest("arm", "offline_testdata_for_libart", "libart.so"); } 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; } TEST(libbacktrace, offline_debug_frame_with_load_bias) { LibUnwindingTest("arm", "offline_testdata_for_libandroid_runtime", "libandroid_runtime.so"); } // 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); } TEST(libbacktrace, offline_try_armexidx_after_debug_frame) { LibUnwindingTest("arm", "offline_testdata_for_libGLESv2_adreno", "libGLESv2_adreno.so"); }
libbacktrace/testdata/arm/libGLESv2_adreno.so 0 → 100644 +4.04 MiB File added.No diff preview for this file type. View file
libbacktrace/testdata/arm/offline_testdata_for_libGLESv2_adreno 0 → 100644 +6 −0 Original line number Diff line number Diff line pid: 7288 tid: 31656 regs: pc: cc416235 sp: cc17f000 map: start: cc361000 end: cc758000 offset: 0 load_bias: 9000 flags: 5 name: /vendor/lib/egl/libGLESv2_adreno.so stack: start: cc17f254 end: cc17f258 size: 4 b36141cc function: start: be1f0 end: be304 name: EsxContext::Clear(unsigned int, unsigned int, unsigned int, EsxClearValues*) function: start: be058 end: be1f0 name: EsxContext::ClearBuffersForDebug()