Merge "Update the tests." am: 4614a7ae1b
am: 8547fb9003
Change-Id: I0ad4c3cd4cf548433f4d553d8685986f27977800
This commit is contained in:
commit
e69ff20c0f
9 changed files with 485 additions and 404 deletions
|
|
@ -243,6 +243,13 @@ cc_test {
|
|||
static_libs: ["libutils"],
|
||||
},
|
||||
},
|
||||
|
||||
data: [
|
||||
"testdata/arm/*",
|
||||
"testdata/arm64/*",
|
||||
"testdata/x86/*",
|
||||
"testdata/x86_64/*",
|
||||
],
|
||||
}
|
||||
|
||||
cc_benchmark {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/macros.h>
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <android-base/strings.h>
|
||||
#include <backtrace/Backtrace.h>
|
||||
|
|
@ -129,6 +130,10 @@ static void* OfflineThreadFunc(void* arg) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
std::string GetTestPath(std::string path) {
|
||||
return android::base::GetExecutableDirectory() + "/testdata/" + ABI_STRING + '/' + path;
|
||||
}
|
||||
|
||||
// This test is disable because it is for generating test data.
|
||||
TEST(libbacktrace, DISABLED_generate_offline_testdata) {
|
||||
// Create a thread to generate the needed stack and registers information.
|
||||
|
|
@ -206,20 +211,6 @@ static std::string FunctionNameForAddress(uintptr_t addr,
|
|||
return "";
|
||||
}
|
||||
|
||||
static std::string GetArch() {
|
||||
#if defined(__arm__)
|
||||
return "arm";
|
||||
#elif defined(__aarch64__)
|
||||
return "aarch64";
|
||||
#elif defined(__i386__)
|
||||
return "x86";
|
||||
#elif defined(__x86_64__)
|
||||
return "x86_64";
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
struct OfflineTestData {
|
||||
int pid;
|
||||
int tid;
|
||||
|
|
@ -280,20 +271,15 @@ bool ReadOfflineTestData(const std::string offline_testdata_path, OfflineTestDat
|
|||
return true;
|
||||
}
|
||||
|
||||
static void BacktraceOfflineTest(const std::string& testlib_name) {
|
||||
const std::string arch = GetArch();
|
||||
if (arch.empty()) {
|
||||
GTEST_LOG_(INFO) << "This test does nothing on current arch.";
|
||||
return;
|
||||
}
|
||||
const std::string testlib_path = "testdata/" + arch + "/" + testlib_name;
|
||||
struct stat st;
|
||||
if (stat(testlib_path.c_str(), &st) == -1) {
|
||||
GTEST_LOG_(INFO) << "This test is skipped as " << testlib_path << " doesn't exist.";
|
||||
static void BacktraceOfflineTest(const char* arch, const std::string& testlib_name) {
|
||||
// TODO: For now, we can only run this on the same arch as the library arch.
|
||||
if (std::string(ABI_STRING) != arch) {
|
||||
GTEST_LOG_(INFO) << "Ignoring arch " << arch << " for lib " << testlib_name;
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string offline_testdata_path = "testdata/" + arch + "/offline_testdata";
|
||||
const std::string testlib_path(GetTestPath(testlib_name));
|
||||
const std::string offline_testdata_path(GetTestPath("offline_testdata"));
|
||||
OfflineTestData testdata;
|
||||
ASSERT_TRUE(ReadOfflineTestData(offline_testdata_path, &testdata));
|
||||
|
||||
|
|
@ -339,35 +325,40 @@ static void BacktraceOfflineTest(const std::string& testlib_name) {
|
|||
testdata.symbols));
|
||||
}
|
||||
|
||||
// For now, these tests can only run on the given architectures.
|
||||
TEST(libbacktrace, offline_eh_frame) {
|
||||
BacktraceOfflineTest("libbacktrace_test_eh_frame.so");
|
||||
BacktraceOfflineTest("arm64", "libbacktrace_test_eh_frame.so");
|
||||
BacktraceOfflineTest("x86_64", "libbacktrace_test_eh_frame.so");
|
||||
}
|
||||
|
||||
TEST(libbacktrace, offline_debug_frame) {
|
||||
BacktraceOfflineTest("libbacktrace_test_debug_frame.so");
|
||||
BacktraceOfflineTest("arm", "libbacktrace_test_debug_frame.so");
|
||||
BacktraceOfflineTest("x86", "libbacktrace_test_debug_frame.so");
|
||||
}
|
||||
|
||||
TEST(libbacktrace, offline_gnu_debugdata) {
|
||||
BacktraceOfflineTest("libbacktrace_test_gnu_debugdata.so");
|
||||
BacktraceOfflineTest("arm", "libbacktrace_test_gnu_debugdata.so");
|
||||
BacktraceOfflineTest("x86", "libbacktrace_test_gnu_debugdata.so");
|
||||
}
|
||||
|
||||
TEST(libbacktrace, offline_arm_exidx) {
|
||||
BacktraceOfflineTest("libbacktrace_test_arm_exidx.so");
|
||||
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) {
|
||||
const std::string arch = GetArch();
|
||||
if (arch.empty() || arch != "arm") {
|
||||
GTEST_LOG_(INFO) << "This test does nothing on current arch.";
|
||||
// TODO: For now, only run on the given arch.
|
||||
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 = "testdata/" + arch + "/libart.so";
|
||||
const std::string testlib_path(GetTestPath("libart.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 = "testdata/" + arch + "/offline_testdata_for_libart";
|
||||
const std::string offline_testdata_path(GetTestPath("offline_testdata_for_libart"));
|
||||
OfflineTestData testdata;
|
||||
ASSERT_TRUE(ReadOfflineTestData(offline_testdata_path, &testdata));
|
||||
|
||||
|
|
|
|||
|
|
@ -304,8 +304,10 @@ TEST(libbacktrace, local_max_trace) {
|
|||
ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, VerifyMaxBacktrace, nullptr), 0);
|
||||
}
|
||||
|
||||
static void VerifyProcTest(pid_t pid, pid_t tid, bool share_map, bool (*ReadyFunc)(Backtrace*),
|
||||
void (*VerifyFunc)(Backtrace*)) {
|
||||
static void VerifyProcTest(pid_t pid, pid_t tid, bool (*ReadyFunc)(Backtrace*),
|
||||
void (*VerifyFunc)(Backtrace*),
|
||||
Backtrace* (*back_func)(pid_t, pid_t, BacktraceMap*),
|
||||
BacktraceMap* (*map_func)(pid_t, bool)) {
|
||||
pid_t ptrace_tid;
|
||||
if (tid < 0) {
|
||||
ptrace_tid = pid;
|
||||
|
|
@ -322,10 +324,8 @@ static void VerifyProcTest(pid_t pid, pid_t tid, bool share_map, bool (*ReadyFun
|
|||
WaitForStop(ptrace_tid);
|
||||
|
||||
std::unique_ptr<BacktraceMap> map;
|
||||
if (share_map) {
|
||||
map.reset(BacktraceMap::Create(pid));
|
||||
}
|
||||
std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid, map.get()));
|
||||
map.reset(map_func(pid, false));
|
||||
std::unique_ptr<Backtrace> backtrace(back_func(pid, tid, map.get()));
|
||||
ASSERT_TRUE(backtrace.get() != nullptr);
|
||||
ASSERT_TRUE(backtrace->Unwind(0));
|
||||
ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, backtrace->GetError());
|
||||
|
|
@ -349,21 +349,22 @@ TEST(libbacktrace, ptrace_trace) {
|
|||
ASSERT_NE(test_level_one(1, 2, 3, 4, nullptr, nullptr), 0);
|
||||
_exit(1);
|
||||
}
|
||||
VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, false, ReadyLevelBacktrace, VerifyLevelDump);
|
||||
VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, ReadyLevelBacktrace, VerifyLevelDump,
|
||||
Backtrace::Create, BacktraceMap::Create);
|
||||
|
||||
kill(pid, SIGKILL);
|
||||
int status;
|
||||
ASSERT_EQ(waitpid(pid, &status, 0), pid);
|
||||
}
|
||||
|
||||
TEST(libbacktrace, ptrace_trace_shared_map) {
|
||||
TEST(libbacktrace, ptrace_trace_new) {
|
||||
pid_t pid;
|
||||
if ((pid = fork()) == 0) {
|
||||
ASSERT_NE(test_level_one(1, 2, 3, 4, nullptr, nullptr), 0);
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, true, ReadyLevelBacktrace, VerifyLevelDump);
|
||||
VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, ReadyLevelBacktrace, VerifyLevelDump,
|
||||
Backtrace::CreateNew, BacktraceMap::CreateNew);
|
||||
|
||||
kill(pid, SIGKILL);
|
||||
int status;
|
||||
|
|
@ -376,7 +377,22 @@ TEST(libbacktrace, ptrace_max_trace) {
|
|||
ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, nullptr, nullptr), 0);
|
||||
_exit(1);
|
||||
}
|
||||
VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, false, ReadyMaxBacktrace, VerifyMaxDump);
|
||||
VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, ReadyMaxBacktrace, VerifyMaxDump, Backtrace::Create,
|
||||
BacktraceMap::Create);
|
||||
|
||||
kill(pid, SIGKILL);
|
||||
int status;
|
||||
ASSERT_EQ(waitpid(pid, &status, 0), pid);
|
||||
}
|
||||
|
||||
TEST(libbacktrace, ptrace_max_trace_new) {
|
||||
pid_t pid;
|
||||
if ((pid = fork()) == 0) {
|
||||
ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES + 10, nullptr, nullptr), 0);
|
||||
_exit(1);
|
||||
}
|
||||
VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, ReadyMaxBacktrace, VerifyMaxDump,
|
||||
Backtrace::CreateNew, BacktraceMap::CreateNew);
|
||||
|
||||
kill(pid, SIGKILL);
|
||||
int status;
|
||||
|
|
@ -403,7 +419,22 @@ TEST(libbacktrace, ptrace_ignore_frames) {
|
|||
ASSERT_NE(test_level_one(1, 2, 3, 4, nullptr, nullptr), 0);
|
||||
_exit(1);
|
||||
}
|
||||
VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, false, ReadyLevelBacktrace, VerifyProcessIgnoreFrames);
|
||||
VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, ReadyLevelBacktrace, VerifyProcessIgnoreFrames,
|
||||
Backtrace::Create, BacktraceMap::Create);
|
||||
|
||||
kill(pid, SIGKILL);
|
||||
int status;
|
||||
ASSERT_EQ(waitpid(pid, &status, 0), pid);
|
||||
}
|
||||
|
||||
TEST(libbacktrace, ptrace_ignore_frames_new) {
|
||||
pid_t pid;
|
||||
if ((pid = fork()) == 0) {
|
||||
ASSERT_NE(test_level_one(1, 2, 3, 4, nullptr, nullptr), 0);
|
||||
_exit(1);
|
||||
}
|
||||
VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, ReadyLevelBacktrace, VerifyProcessIgnoreFrames,
|
||||
Backtrace::CreateNew, BacktraceMap::CreateNew);
|
||||
|
||||
kill(pid, SIGKILL);
|
||||
int status;
|
||||
|
|
@ -466,7 +497,47 @@ TEST(libbacktrace, ptrace_threads) {
|
|||
if (pid == *it) {
|
||||
continue;
|
||||
}
|
||||
VerifyProcTest(pid, *it, false, ReadyLevelBacktrace, VerifyLevelDump);
|
||||
VerifyProcTest(pid, *it, ReadyLevelBacktrace, VerifyLevelDump, Backtrace::Create,
|
||||
BacktraceMap::Create);
|
||||
}
|
||||
|
||||
FinishRemoteProcess(pid);
|
||||
}
|
||||
|
||||
TEST(libbacktrace, ptrace_threads_new) {
|
||||
pid_t pid;
|
||||
if ((pid = fork()) == 0) {
|
||||
for (size_t i = 0; i < NUM_PTRACE_THREADS; i++) {
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
|
||||
pthread_t thread;
|
||||
ASSERT_TRUE(pthread_create(&thread, &attr, PtraceThreadLevelRun, nullptr) == 0);
|
||||
}
|
||||
ASSERT_NE(test_level_one(1, 2, 3, 4, nullptr, nullptr), 0);
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
// Check to see that all of the threads are running before unwinding.
|
||||
std::vector<pid_t> threads;
|
||||
uint64_t start = NanoTime();
|
||||
do {
|
||||
usleep(US_PER_MSEC);
|
||||
threads.clear();
|
||||
GetThreads(pid, &threads);
|
||||
} while ((threads.size() != NUM_PTRACE_THREADS + 1) && ((NanoTime() - start) <= 5 * NS_PER_SEC));
|
||||
ASSERT_EQ(threads.size(), static_cast<size_t>(NUM_PTRACE_THREADS + 1));
|
||||
|
||||
ASSERT_TRUE(ptrace(PTRACE_ATTACH, pid, 0, 0) == 0);
|
||||
WaitForStop(pid);
|
||||
for (std::vector<int>::const_iterator it = threads.begin(); it != threads.end(); ++it) {
|
||||
// Skip the current forked process, we only care about the threads.
|
||||
if (pid == *it) {
|
||||
continue;
|
||||
}
|
||||
VerifyProcTest(pid, *it, ReadyLevelBacktrace, VerifyLevelDump, Backtrace::CreateNew,
|
||||
BacktraceMap::CreateNew);
|
||||
}
|
||||
|
||||
FinishRemoteProcess(pid);
|
||||
|
|
@ -1579,7 +1650,7 @@ TEST(libbacktrace, unwind_disallow_device_map_local) {
|
|||
munmap(device_map, DEVICE_MAP_SIZE);
|
||||
}
|
||||
|
||||
TEST(libbacktrace, unwind_disallow_device_map_remote) {
|
||||
TEST(libbacktrace, unwind_disallow_device_map_remote_new) {
|
||||
void* device_map;
|
||||
SetupDeviceMap(&device_map);
|
||||
|
||||
|
|
@ -1588,13 +1659,11 @@ TEST(libbacktrace, unwind_disallow_device_map_remote) {
|
|||
CreateRemoteProcess(&pid);
|
||||
|
||||
// Now create an unwind object.
|
||||
std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, pid));
|
||||
std::unique_ptr<BacktraceMap> map(BacktraceMap::CreateNew(pid));
|
||||
ASSERT_TRUE(map.get() != nullptr);
|
||||
std::unique_ptr<Backtrace> backtrace(Backtrace::CreateNew(pid, pid, map.get()));
|
||||
|
||||
// TODO: Currently unwind from context doesn't work on remote
|
||||
// unwind. Keep this test because the new unwinder should support
|
||||
// this eventually, or we can delete this test.
|
||||
// properly with unwind from context.
|
||||
// UnwindFromDevice(backtrace.get(), device_map);
|
||||
UnwindFromDevice(backtrace.get(), device_map);
|
||||
|
||||
FinishRemoteProcess(pid);
|
||||
|
||||
|
|
@ -1633,7 +1702,9 @@ static void SetValueAndLoop(void* data) {
|
|||
;
|
||||
}
|
||||
|
||||
static void UnwindThroughSignal(bool use_action) {
|
||||
static void UnwindThroughSignal(bool use_action,
|
||||
Backtrace* (*back_func)(pid_t, pid_t, BacktraceMap*),
|
||||
BacktraceMap* (*map_func)(pid_t, bool)) {
|
||||
volatile int value = 0;
|
||||
pid_t pid;
|
||||
if ((pid = fork()) == 0) {
|
||||
|
|
@ -1659,7 +1730,8 @@ static void UnwindThroughSignal(bool use_action) {
|
|||
|
||||
WaitForStop(pid);
|
||||
|
||||
std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, pid));
|
||||
std::unique_ptr<BacktraceMap> map(map_func(pid, false));
|
||||
std::unique_ptr<Backtrace> backtrace(back_func(pid, pid, map.get()));
|
||||
|
||||
size_t bytes_read = backtrace->Read(reinterpret_cast<uintptr_t>(const_cast<int*>(&value)),
|
||||
reinterpret_cast<uint8_t*>(&read_value), sizeof(read_value));
|
||||
|
|
@ -1677,6 +1749,7 @@ static void UnwindThroughSignal(bool use_action) {
|
|||
// Wait for the process to get to the signal handler loop.
|
||||
Backtrace::const_iterator frame_iter;
|
||||
start = NanoTime();
|
||||
std::unique_ptr<BacktraceMap> map;
|
||||
std::unique_ptr<Backtrace> backtrace;
|
||||
while (true) {
|
||||
usleep(1000);
|
||||
|
|
@ -1685,7 +1758,9 @@ static void UnwindThroughSignal(bool use_action) {
|
|||
|
||||
WaitForStop(pid);
|
||||
|
||||
backtrace.reset(Backtrace::Create(pid, pid));
|
||||
map.reset(map_func(pid, false));
|
||||
ASSERT_TRUE(map.get() != nullptr);
|
||||
backtrace.reset(back_func(pid, pid, map.get()));
|
||||
ASSERT_TRUE(backtrace->Unwind(0));
|
||||
bool found = false;
|
||||
for (frame_iter = backtrace->begin(); frame_iter != backtrace->end(); ++frame_iter) {
|
||||
|
|
@ -1742,11 +1817,19 @@ static void UnwindThroughSignal(bool use_action) {
|
|||
}
|
||||
|
||||
TEST(libbacktrace, unwind_remote_through_signal_using_handler) {
|
||||
UnwindThroughSignal(false);
|
||||
UnwindThroughSignal(false, Backtrace::Create, BacktraceMap::Create);
|
||||
}
|
||||
|
||||
TEST(libbacktrace, unwind_remote_through_signal_using_handler_new) {
|
||||
UnwindThroughSignal(false, Backtrace::CreateNew, BacktraceMap::CreateNew);
|
||||
}
|
||||
|
||||
TEST(libbacktrace, unwind_remote_through_signal_using_action) {
|
||||
UnwindThroughSignal(true);
|
||||
UnwindThroughSignal(true, Backtrace::Create, BacktraceMap::Create);
|
||||
}
|
||||
|
||||
TEST(libbacktrace, unwind_remote_through_signal_using_action_new) {
|
||||
UnwindThroughSignal(true, Backtrace::CreateNew, BacktraceMap::CreateNew);
|
||||
}
|
||||
|
||||
#if defined(ENABLE_PSS_TESTS)
|
||||
|
|
|
|||
188
libbacktrace/testdata/arm/offline_testdata
vendored
188
libbacktrace/testdata/arm/offline_testdata
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
142
libbacktrace/testdata/x86/offline_testdata
vendored
142
libbacktrace/testdata/x86/offline_testdata
vendored
File diff suppressed because one or more lines are too long
164
libbacktrace/testdata/x86_64/offline_testdata
vendored
164
libbacktrace/testdata/x86_64/offline_testdata
vendored
File diff suppressed because one or more lines are too long
Loading…
Add table
Reference in a new issue