Add get initial regs to ThreadUnwinder. am: 875fd55938
Original change: https://android-review.googlesource.com/c/platform/system/unwinding/+/1981166
Change-Id: Ic47772da5559dacd67874608ae95bcc3fd2fd350
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
start_unwinding = true;
- while (unwinders.load() != kNumThreads)
- ;
+ while (unwinders.load() != kNumThreads) {
+ }
for (auto* thread : threads) {
thread->join();
@@ -613,8 +641,8 @@
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 @@
}
start_unwinding = true;
- while (unwinders.load() != kNumThreads)
- ;
+ while (unwinders.load() != kNumThreads) {
+ }
for (auto* thread : unwinder_threads) {
thread->join();
@@ -663,8 +691,8 @@
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 @@
}
start_unwinding = true;
- while (unwinders.load() != kNumThreads)
- ;
+ while (unwinders.load() != kNumThreads) {
+ }
for (auto* thread : unwinder_threads) {
thread->join();