summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Ferris <cferris@google.com>2022-02-18 02:46:02 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2022-02-18 02:46:02 +0000
commit95e2cfb8457ddc2d7effd63a1e81e09a879400e3 (patch)
tree7b74d3c42065befea88a997e23e37b941d974ff3
parentc254fd7fb7269b04c5f500df142d4dbcf3203344 (diff)
parent0086510198e06b873ca9f5ab890ba94680c63ca0 (diff)
downloadunwinding-95e2cfb8457ddc2d7effd63a1e81e09a879400e3.tar.gz
Add get initial regs to ThreadUnwinder. am: 875fd55938 am: 0086510198
Original change: https://android-review.googlesource.com/c/platform/system/unwinding/+/1981166 Change-Id: I651e6299e6d3968d9f358cce95fb198165e828f1
-rw-r--r--libunwindstack/ThreadUnwinder.cpp5
-rw-r--r--libunwindstack/include/unwindstack/Unwinder.h2
-rw-r--r--libunwindstack/tests/UnwindTest.cpp68
3 files changed, 53 insertions, 22 deletions
diff --git a/libunwindstack/ThreadUnwinder.cpp b/libunwindstack/ThreadUnwinder.cpp
index b649491..9a8a0a6 100644
--- a/libunwindstack/ThreadUnwinder.cpp
+++ b/libunwindstack/ThreadUnwinder.cpp
@@ -145,7 +145,7 @@ ThreadEntry* ThreadUnwinder::SendSignalToThread(int signal, pid_t tid) {
return nullptr;
}
-void ThreadUnwinder::UnwindWithSignal(int signal, pid_t tid,
+void ThreadUnwinder::UnwindWithSignal(int signal, pid_t tid, std::unique_ptr<Regs>* initial_regs,
const std::vector<std::string>* initial_map_names_to_skip,
const std::vector<std::string>* map_suffixes_to_ignore) {
ClearErrors();
@@ -164,6 +164,9 @@ void ThreadUnwinder::UnwindWithSignal(int signal, pid_t tid,
}
std::unique_ptr<Regs> regs(Regs::CreateFromUcontext(Regs::CurrentArch(), entry->GetUcontext()));
+ if (initial_regs != nullptr) {
+ initial_regs->reset(regs->Clone());
+ }
SetRegs(regs.get());
UnwinderFromPid::Unwind(initial_map_names_to_skip, map_suffixes_to_ignore);
diff --git a/libunwindstack/include/unwindstack/Unwinder.h b/libunwindstack/include/unwindstack/Unwinder.h
index d87e55c..e21e91d 100644
--- a/libunwindstack/include/unwindstack/Unwinder.h
+++ b/libunwindstack/include/unwindstack/Unwinder.h
@@ -185,7 +185,7 @@ class ThreadUnwinder : public UnwinderFromPid {
void Unwind(const std::vector<std::string>*, const std::vector<std::string>*) override {}
- void UnwindWithSignal(int signal, pid_t tid,
+ void UnwindWithSignal(int signal, pid_t tid, std::unique_ptr<Regs>* initial_regs = nullptr,
const std::vector<std::string>* initial_map_names_to_skip = nullptr,
const std::vector<std::string>* map_suffixes_to_ignore = nullptr);
diff --git a/libunwindstack/tests/UnwindTest.cpp b/libunwindstack/tests/UnwindTest.cpp
index 1996992..80f931b 100644
--- a/libunwindstack/tests/UnwindTest.cpp
+++ b/libunwindstack/tests/UnwindTest.cpp
@@ -467,8 +467,8 @@ TEST_F(UnwindTest, multiple_threads_unwind_same_map) {
size_t frames[kNumConcurrentThreads];
for (size_t i = 0; i < kNumConcurrentThreads; i++) {
std::thread* thread = new std::thread([i, &frames, &maps, &process_memory, &wait]() {
- while (wait)
- ;
+ while (wait) {
+ }
std::unique_ptr<Regs> regs(Regs::CreateFromLocal());
RegsGetLocal(regs.get());
@@ -495,8 +495,8 @@ TEST_F(UnwindTest, thread_unwind) {
OuterFunction(TEST_TYPE_LOCAL_WAIT_FOR_FINISH);
});
- while (tid.load() == 0)
- ;
+ while (tid.load() == 0) {
+ }
ThreadUnwinder unwinder(512);
ASSERT_TRUE(unwinder.Init());
@@ -507,6 +507,34 @@ TEST_F(UnwindTest, thread_unwind) {
thread.join();
}
+TEST_F(UnwindTest, thread_unwind_copy_regs) {
+ ResetGlobals();
+
+ std::atomic_int tid(0);
+ std::thread thread([&tid]() {
+ tid = android::base::GetThreadId();
+ OuterFunction(TEST_TYPE_LOCAL_WAIT_FOR_FINISH);
+ });
+
+ while (tid.load() == 0) {
+ }
+
+ ThreadUnwinder unwinder(512);
+ ASSERT_TRUE(unwinder.Init());
+ std::unique_ptr<Regs> initial_regs;
+ unwinder.UnwindWithSignal(SIGRTMIN, tid, &initial_regs);
+ ASSERT_TRUE(initial_regs != nullptr);
+ // Verify the initial registers match the first frame pc/sp.
+ ASSERT_TRUE(unwinder.NumFrames() != 0);
+ auto initial_frame = unwinder.frames()[0];
+ ASSERT_EQ(initial_regs->pc(), initial_frame.pc);
+ ASSERT_EQ(initial_regs->sp(), initial_frame.sp);
+ VerifyUnwindFrames(&unwinder, kFunctionOrder);
+
+ g_finish = true;
+ thread.join();
+}
+
TEST_F(UnwindTest, thread_unwind_with_external_maps) {
ResetGlobals();
@@ -516,8 +544,8 @@ TEST_F(UnwindTest, thread_unwind_with_external_maps) {
OuterFunction(TEST_TYPE_LOCAL_WAIT_FOR_FINISH);
});
- while (tid.load() == 0)
- ;
+ while (tid.load() == 0) {
+ }
LocalMaps maps;
ASSERT_TRUE(maps.Parse());
@@ -546,8 +574,8 @@ static std::thread* CreateUnwindThread(std::atomic_int& tid, ThreadUnwinder& unw
std::atomic_bool& start_unwinding,
std::atomic_int& unwinders) {
return new std::thread([&tid, &unwinder, &start_unwinding, &unwinders]() {
- while (!start_unwinding.load())
- ;
+ while (!start_unwinding.load()) {
+ }
ThreadUnwinder thread_unwinder(512, &unwinder);
// Allow the unwind to timeout since this will be doing multiple
@@ -573,8 +601,8 @@ TEST_F(UnwindTest, thread_unwind_same_thread_from_threads) {
OuterFunction(TEST_TYPE_LOCAL_WAIT_FOR_FINISH);
});
- while (g_waiters.load() != 1)
- ;
+ while (g_waiters.load() != 1) {
+ }
ThreadUnwinder unwinder(512);
ASSERT_TRUE(unwinder.Init());
@@ -587,8 +615,8 @@ TEST_F(UnwindTest, thread_unwind_same_thread_from_threads) {
}
start_unwinding = true;
- while (unwinders.load() != kNumThreads)
- ;
+ while (unwinders.load() != kNumThreads) {
+ }
for (auto* thread : threads) {
thread->join();
@@ -613,8 +641,8 @@ TEST_F(UnwindTest, thread_unwind_multiple_thread_from_threads) {
threads.push_back(thread);
}
- while (g_waiters.load() != kNumThreads)
- ;
+ while (g_waiters.load() != kNumThreads) {
+ }
ThreadUnwinder unwinder(512);
ASSERT_TRUE(unwinder.Init());
@@ -627,8 +655,8 @@ TEST_F(UnwindTest, thread_unwind_multiple_thread_from_threads) {
}
start_unwinding = true;
- while (unwinders.load() != kNumThreads)
- ;
+ while (unwinders.load() != kNumThreads) {
+ }
for (auto* thread : unwinder_threads) {
thread->join();
@@ -663,8 +691,8 @@ TEST_F(UnwindTest, thread_unwind_multiple_thread_from_threads_updatable_maps) {
threads.push_back(thread);
}
- while (g_waiters.load() != kNumThreads)
- ;
+ while (g_waiters.load() != kNumThreads) {
+ }
ThreadUnwinder unwinder(512, &maps);
ASSERT_TRUE(unwinder.Init());
@@ -677,8 +705,8 @@ TEST_F(UnwindTest, thread_unwind_multiple_thread_from_threads_updatable_maps) {
}
start_unwinding = true;
- while (unwinders.load() != kNumThreads)
- ;
+ while (unwinders.load() != kNumThreads) {
+ }
for (auto* thread : unwinder_threads) {
thread->join();