From 719b97add040eb4d60e8a6b87d1e2f35ab73e6a0 Mon Sep 17 00:00:00 2001 From: Christopher Ferris Date: Tue, 31 Jan 2023 17:50:22 -0800 Subject: Display offset in backtraces if necessary. When moving to a proto tombstone, backtraces no longer contain an offset when a frame is in a shared library from an apk. Add the offset display again if needed, and add a test to verify this behavior. Bug: 267341682 Test: All unit tests pass. Test: Dumped a process running through an apk to verify the offset Test: is present. Change-Id: Ib720ccb5bfcc8531d1e407f3d01817e8a0b9128c (cherry picked from commit 22035ccb01693da3e0ec94776c86988c7d5c617e) --- debuggerd/debuggerd_test.cpp | 60 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) (limited to 'debuggerd/debuggerd_test.cpp') diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp index e11330819..9163ca0ab 100644 --- a/debuggerd/debuggerd_test.cpp +++ b/debuggerd/debuggerd_test.cpp @@ -36,6 +36,7 @@ #include #include +#include #include #include #include @@ -1842,7 +1843,7 @@ TEST_F(CrasherTest, stack_overflow) { ASSERT_MATCH(result, R"(Cause: stack pointer[^\n]*stack overflow.\n)"); } -static bool CopySharedLibrary(const char* tmp_dir, std::string* tmp_so_name) { +static std::string GetTestLibraryPath() { std::string test_lib(testing::internal::GetArgvs()[0]); auto const value = test_lib.find_last_of('/'); if (value == std::string::npos) { @@ -1850,7 +1851,62 @@ static bool CopySharedLibrary(const char* tmp_dir, std::string* tmp_so_name) { } else { test_lib = test_lib.substr(0, value + 1) + "./"; } - test_lib += "libcrash_test.so"; + return test_lib + "libcrash_test.so"; +} + +static void CreateEmbeddedLibrary(int out_fd) { + std::string test_lib(GetTestLibraryPath()); + android::base::unique_fd fd(open(test_lib.c_str(), O_RDONLY | O_CLOEXEC)); + ASSERT_NE(fd.get(), -1); + off_t file_size = lseek(fd, 0, SEEK_END); + ASSERT_EQ(lseek(fd, 0, SEEK_SET), 0); + std::vector contents(file_size); + ASSERT_TRUE(android::base::ReadFully(fd, contents.data(), contents.size())); + + // Put the shared library data at a pagesize() offset. + ASSERT_EQ(lseek(out_fd, 4 * getpagesize(), SEEK_CUR), 4 * getpagesize()); + ASSERT_EQ(static_cast(write(out_fd, contents.data(), contents.size())), contents.size()); +} + +TEST_F(CrasherTest, non_zero_offset_in_library) { + int intercept_result; + unique_fd output_fd; + TemporaryFile tf; + CreateEmbeddedLibrary(tf.fd); + StartProcess([&tf]() { + android_dlextinfo extinfo{}; + extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET; + extinfo.library_fd = tf.fd; + extinfo.library_fd_offset = 4 * getpagesize(); + void* handle = android_dlopen_ext(tf.path, RTLD_NOW, &extinfo); + if (handle == nullptr) { + _exit(1); + } + void (*crash_func)() = reinterpret_cast(dlsym(handle, "crash")); + if (crash_func == nullptr) { + _exit(1); + } + crash_func(); + }); + + StartIntercept(&output_fd); + FinishCrasher(); + AssertDeath(SIGSEGV); + FinishIntercept(&intercept_result); + + ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; + + std::string result; + ConsumeFd(std::move(output_fd), &result); + + // Verify the crash includes an offset value in the backtrace. + std::string match_str = android::base::StringPrintf("%s\\!libcrash_test.so \\(offset 0x%x\\)", + tf.path, 4 * getpagesize()); + ASSERT_MATCH(result, match_str); +} + +static bool CopySharedLibrary(const char* tmp_dir, std::string* tmp_so_name) { + std::string test_lib(GetTestLibraryPath()); *tmp_so_name = std::string(tmp_dir) + "/libcrash_test.so"; std::string cp_cmd = android::base::StringPrintf("cp %s %s", test_lib.c_str(), tmp_dir); -- cgit v1.2.3