1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <errno.h>
18 #include <signal.h>
19 #include <stdint.h>
20 #include <string.h>
21 #include <sys/ptrace.h>
22 #include <sys/syscall.h>
23 #include <unistd.h>
24
25 #include <gtest/gtest.h>
26
27 #include <atomic>
28 #include <memory>
29 #include <sstream>
30 #include <string>
31 #include <thread>
32 #include <vector>
33
34 #include <android-base/stringprintf.h>
35 #include <android-base/threads.h>
36
37 #include <unwindstack/Maps.h>
38 #include <unwindstack/Regs.h>
39 #include <unwindstack/RegsGetLocal.h>
40 #include <unwindstack/Unwinder.h>
41
42 #include "ForkTest.h"
43 #include "MemoryRemote.h"
44 #include "PidUtils.h"
45 #include "TestUtils.h"
46
47 namespace unwindstack {
48
49 enum TestTypeEnum : uint8_t {
50 TEST_TYPE_LOCAL_UNWINDER = 0,
51 TEST_TYPE_LOCAL_UNWINDER_FROM_PID,
52 TEST_TYPE_LOCAL_WAIT_FOR_FINISH,
53 TEST_TYPE_REMOTE,
54 TEST_TYPE_REMOTE_WITH_INVALID_CALL,
55 };
56
57 static volatile bool g_ready_for_remote;
58 static volatile bool g_signal_ready_for_remote;
59 // In order to avoid the compiler not emitting the unwind entries for
60 // the InnerFunction code that loops waiting for g_finish, always make
61 // g_finish a volatile instead of an atomic. This issue was only ever
62 // observerd on the arm architecture.
63 static volatile bool g_finish;
64 static std::atomic_uintptr_t g_ucontext;
65 static std::atomic_int g_waiters;
66
ResetGlobals()67 static void ResetGlobals() {
68 g_ready_for_remote = false;
69 g_signal_ready_for_remote = false;
70 g_finish = false;
71 g_ucontext = 0;
72 g_waiters = 0;
73 }
74
75 static std::vector<const char*> kFunctionOrder{"OuterFunction", "MiddleFunction", "InnerFunction"};
76
77 static std::vector<const char*> kFunctionSignalOrder{"OuterFunction", "MiddleFunction",
78 "InnerFunction", "SignalOuterFunction",
79 "SignalMiddleFunction", "SignalInnerFunction"};
80
SignalHandler(int,siginfo_t *,void * sigcontext)81 static void SignalHandler(int, siginfo_t*, void* sigcontext) {
82 g_ucontext = reinterpret_cast<uintptr_t>(sigcontext);
83 while (!g_finish) {
84 }
85 }
86
SignalInnerFunction()87 extern "C" void SignalInnerFunction() {
88 g_signal_ready_for_remote = true;
89 // Avoid any function calls because not every instruction will be
90 // unwindable.
91 // This method of looping is only used when testing a remote unwind.
92 while (true) {
93 }
94 }
95
SignalMiddleFunction()96 extern "C" void SignalMiddleFunction() {
97 SignalInnerFunction();
98 }
99
SignalOuterFunction()100 extern "C" void SignalOuterFunction() {
101 SignalMiddleFunction();
102 }
103
SignalCallerHandler(int,siginfo_t *,void *)104 static void SignalCallerHandler(int, siginfo_t*, void*) {
105 SignalOuterFunction();
106 }
107
ErrorMsg(const std::vector<const char * > & function_names,Unwinder * unwinder)108 static std::string ErrorMsg(const std::vector<const char*>& function_names, Unwinder* unwinder) {
109 std::string unwind;
110 for (size_t i = 0; i < unwinder->NumFrames(); i++) {
111 unwind += unwinder->FormatFrame(i) + '\n';
112 }
113
114 return std::string(
115 "Unwind completed without finding all frames\n"
116 " Unwinder error: ") +
117 unwinder->LastErrorCodeString() + "\n" +
118 " Looking for function: " + function_names.front() + "\n" + "Unwind data:\n" + unwind;
119 }
120
VerifyUnwindFrames(Unwinder * unwinder,std::vector<const char * > expected_function_names)121 static void VerifyUnwindFrames(Unwinder* unwinder,
122 std::vector<const char*> expected_function_names) {
123 for (auto& frame : unwinder->frames()) {
124 if (frame.function_name == expected_function_names.back()) {
125 expected_function_names.pop_back();
126 if (expected_function_names.empty()) {
127 break;
128 }
129 }
130 }
131
132 ASSERT_TRUE(expected_function_names.empty()) << ErrorMsg(expected_function_names, unwinder);
133
134 // Verify that the load bias of every map with a MapInfo is has been initialized.
135 for (auto& frame : unwinder->frames()) {
136 if (frame.map_info == nullptr) {
137 continue;
138 }
139 ASSERT_NE(UINT64_MAX, frame.map_info->GetLoadBias()) << "Frame " << frame.num << " failed";
140 }
141 }
142
VerifyUnwind(Unwinder * unwinder,std::vector<const char * > expected_function_names)143 static void VerifyUnwind(Unwinder* unwinder, std::vector<const char*> expected_function_names) {
144 unwinder->Unwind();
145
146 VerifyUnwindFrames(unwinder, expected_function_names);
147 }
148
VerifyUnwind(pid_t pid,Maps * maps,Regs * regs,std::vector<const char * > expected_function_names)149 static void VerifyUnwind(pid_t pid, Maps* maps, Regs* regs,
150 std::vector<const char*> expected_function_names) {
151 auto process_memory(Memory::CreateProcessMemory(pid));
152
153 Unwinder unwinder(512, maps, regs, process_memory);
154 VerifyUnwind(&unwinder, expected_function_names);
155 }
156
157 // This test assumes that this code is compiled with optimizations turned
158 // off. If this doesn't happen, then all of the calls will be optimized
159 // away.
InnerFunction(TestTypeEnum test_type)160 extern "C" void InnerFunction(TestTypeEnum test_type) {
161 // Use a switch statement to force the compiler to create unwinding information
162 // for each case.
163 switch (test_type) {
164 case TEST_TYPE_LOCAL_WAIT_FOR_FINISH: {
165 g_waiters++;
166 while (!g_finish) {
167 }
168 break;
169 }
170
171 case TEST_TYPE_REMOTE:
172 case TEST_TYPE_REMOTE_WITH_INVALID_CALL: {
173 g_ready_for_remote = true;
174 if (test_type == TEST_TYPE_REMOTE_WITH_INVALID_CALL) {
175 void (*crash_func)() = nullptr;
176 crash_func();
177 }
178 while (true) {
179 }
180 break;
181 }
182
183 default: {
184 std::unique_ptr<Unwinder> unwinder;
185 std::unique_ptr<Regs> regs(Regs::CreateFromLocal());
186 RegsGetLocal(regs.get());
187 std::unique_ptr<Maps> maps;
188
189 if (test_type == TEST_TYPE_LOCAL_UNWINDER) {
190 maps.reset(new LocalMaps());
191 ASSERT_TRUE(maps->Parse());
192 auto process_memory(Memory::CreateProcessMemory(getpid()));
193 unwinder.reset(new Unwinder(512, maps.get(), regs.get(), process_memory));
194 } else {
195 UnwinderFromPid* unwinder_from_pid = new UnwinderFromPid(512, getpid());
196 unwinder_from_pid->SetRegs(regs.get());
197 unwinder.reset(unwinder_from_pid);
198 }
199 VerifyUnwind(unwinder.get(), kFunctionOrder);
200 break;
201 }
202 }
203 }
204
MiddleFunction(TestTypeEnum test_type)205 extern "C" void MiddleFunction(TestTypeEnum test_type) {
206 InnerFunction(test_type);
207 }
208
OuterFunction(TestTypeEnum test_type)209 extern "C" void OuterFunction(TestTypeEnum test_type) {
210 MiddleFunction(test_type);
211 }
212
213 class UnwindTest : public ForkTest {
214 public:
SetUp()215 void SetUp() override { ResetGlobals(); }
216
RemoteValueTrue(volatile bool * addr)217 bool RemoteValueTrue(volatile bool* addr) {
218 MemoryRemote memory(pid_);
219
220 bool value;
221 if (memory.ReadFully(reinterpret_cast<uint64_t>(addr), &value, sizeof(value)) && value) {
222 return true;
223 }
224 return false;
225 }
226
WaitForRemote(volatile bool * addr)227 void WaitForRemote(volatile bool* addr) {
228 ForkAndWaitForPidState([this, addr]() {
229 if (RemoteValueTrue(addr)) {
230 return PID_RUN_PASS;
231 }
232 return PID_RUN_KEEP_GOING;
233 });
234 }
235
RemoteCheckForLeaks(void (* unwind_func)(void *))236 void RemoteCheckForLeaks(void (*unwind_func)(void*)) {
237 SetForkFunc([]() { OuterFunction(TEST_TYPE_REMOTE); });
238 ASSERT_NO_FATAL_FAILURE(WaitForRemote(&g_ready_for_remote));
239
240 pid_t pid = pid_;
241 TestCheckForLeaks(unwind_func, &pid);
242 }
243
RemoteThroughSignal(int signal,unsigned int sa_flags)244 void RemoteThroughSignal(int signal, unsigned int sa_flags) {
245 SetForkFunc([signal, sa_flags]() {
246 struct sigaction act = {};
247 act.sa_sigaction = SignalCallerHandler;
248 act.sa_flags = SA_RESTART | SA_ONSTACK | sa_flags;
249 ASSERT_EQ(0, sigaction(signal, &act, nullptr));
250
251 OuterFunction(signal != SIGSEGV ? TEST_TYPE_REMOTE : TEST_TYPE_REMOTE_WITH_INVALID_CALL);
252 });
253
254 if (signal != SIGSEGV) {
255 // Wait for the remote process to set g_ready_for_remote, then send the
256 // given signal. After that, wait for g_signal_ready_for_remote to be set.
257 bool signal_sent = false;
258 volatile bool* remote_ready_addr = &g_ready_for_remote;
259 volatile bool* signal_ready_addr = &g_signal_ready_for_remote;
260 ASSERT_NO_FATAL_FAILURE(ForkAndWaitForPidState(
261 [this, &signal_sent, signal, remote_ready_addr, signal_ready_addr]() {
262 if (!signal_sent) {
263 if (RemoteValueTrue(remote_ready_addr)) {
264 kill(pid_, signal);
265 signal_sent = true;
266 }
267 } else if (RemoteValueTrue(signal_ready_addr)) {
268 return PID_RUN_PASS;
269 }
270 return PID_RUN_KEEP_GOING;
271 }));
272 } else {
273 // The process should be SIGSEGV'ing, so wait for the remote process
274 // to be in the signal function.
275 ASSERT_NO_FATAL_FAILURE(WaitForRemote(&g_signal_ready_for_remote));
276 }
277
278 RemoteMaps maps(pid_);
279 ASSERT_TRUE(maps.Parse());
280 std::unique_ptr<Regs> regs(Regs::RemoteGet(pid_));
281 ASSERT_TRUE(regs.get() != nullptr);
282
283 VerifyUnwind(pid_, &maps, regs.get(), kFunctionSignalOrder);
284 }
285 };
286
TEST_F(UnwindTest,local)287 TEST_F(UnwindTest, local) {
288 OuterFunction(TEST_TYPE_LOCAL_UNWINDER);
289 }
290
TEST_F(UnwindTest,local_use_from_pid)291 TEST_F(UnwindTest, local_use_from_pid) {
292 OuterFunction(TEST_TYPE_LOCAL_UNWINDER_FROM_PID);
293 }
294
LocalUnwind(void * data)295 static void LocalUnwind(void* data) {
296 TestTypeEnum* test_type = reinterpret_cast<TestTypeEnum*>(data);
297 OuterFunction(*test_type);
298 }
299
TEST_F(UnwindTest,local_check_for_leak)300 TEST_F(UnwindTest, local_check_for_leak) {
301 #if !defined(__BIONIC__)
302 GTEST_SKIP() << "Leak checking depends on bionic.";
303 #endif
304
305 TestTypeEnum test_type = TEST_TYPE_LOCAL_UNWINDER;
306 TestCheckForLeaks(LocalUnwind, &test_type);
307 }
308
TEST_F(UnwindTest,local_use_from_pid_check_for_leak)309 TEST_F(UnwindTest, local_use_from_pid_check_for_leak) {
310 #if !defined(__BIONIC__)
311 GTEST_SKIP() << "Leak checking depends on bionic.";
312 #endif
313
314 TestTypeEnum test_type = TEST_TYPE_LOCAL_UNWINDER_FROM_PID;
315 TestCheckForLeaks(LocalUnwind, &test_type);
316 }
317
TEST_F(UnwindTest,remote)318 TEST_F(UnwindTest, remote) {
319 SetForkFunc([]() { OuterFunction(TEST_TYPE_REMOTE); });
320 ASSERT_NO_FATAL_FAILURE(WaitForRemote(&g_ready_for_remote));
321
322 RemoteMaps maps(pid_);
323 ASSERT_TRUE(maps.Parse());
324 std::unique_ptr<Regs> regs(Regs::RemoteGet(pid_));
325 ASSERT_TRUE(regs.get() != nullptr);
326
327 VerifyUnwind(pid_, &maps, regs.get(), kFunctionOrder);
328 }
329
TEST_F(UnwindTest,unwind_from_pid_remote)330 TEST_F(UnwindTest, unwind_from_pid_remote) {
331 SetForkFunc([]() { OuterFunction(TEST_TYPE_REMOTE); });
332 ASSERT_NO_FATAL_FAILURE(WaitForRemote(&g_ready_for_remote));
333
334 std::unique_ptr<Regs> regs(Regs::RemoteGet(pid_));
335 ASSERT_TRUE(regs.get() != nullptr);
336
337 UnwinderFromPid unwinder(512, pid_);
338 unwinder.SetRegs(regs.get());
339
340 VerifyUnwind(&unwinder, kFunctionOrder);
341 }
342
RemoteUnwind(void * data)343 static void RemoteUnwind(void* data) {
344 pid_t* pid = reinterpret_cast<pid_t*>(data);
345
346 RemoteMaps maps(*pid);
347 ASSERT_TRUE(maps.Parse());
348 std::unique_ptr<Regs> regs(Regs::RemoteGet(*pid));
349 ASSERT_TRUE(regs.get() != nullptr);
350
351 VerifyUnwind(*pid, &maps, regs.get(), kFunctionOrder);
352 }
353
TEST_F(UnwindTest,remote_check_for_leaks)354 TEST_F(UnwindTest, remote_check_for_leaks) {
355 #if !defined(__BIONIC__)
356 GTEST_SKIP() << "Leak checking depends on bionic.";
357 #endif
358
359 RemoteCheckForLeaks(RemoteUnwind);
360 }
361
RemoteUnwindFromPid(void * data)362 static void RemoteUnwindFromPid(void* data) {
363 pid_t* pid = reinterpret_cast<pid_t*>(data);
364
365 std::unique_ptr<Regs> regs(Regs::RemoteGet(*pid));
366 ASSERT_TRUE(regs.get() != nullptr);
367
368 UnwinderFromPid unwinder(512, *pid);
369 unwinder.SetRegs(regs.get());
370
371 VerifyUnwind(&unwinder, kFunctionOrder);
372 }
373
TEST_F(UnwindTest,remote_unwind_for_pid_check_for_leaks)374 TEST_F(UnwindTest, remote_unwind_for_pid_check_for_leaks) {
375 #if !defined(__BIONIC__)
376 GTEST_SKIP() << "Leak checking depends on bionic.";
377 #endif
378
379 RemoteCheckForLeaks(RemoteUnwindFromPid);
380 }
381
TEST_F(UnwindTest,from_context)382 TEST_F(UnwindTest, from_context) {
383 std::atomic_int tid(0);
384 std::thread thread([&]() {
385 tid = syscall(__NR_gettid);
386 OuterFunction(TEST_TYPE_LOCAL_WAIT_FOR_FINISH);
387 });
388
389 struct sigaction act = {};
390 act.sa_sigaction = SignalHandler;
391 act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
392 ASSERT_EQ(0, sigaction(SIGUSR1, &act, nullptr));
393
394 // Wait 20 seconds for the thread to get be running in the right function.
395 for (time_t start_time = time(nullptr); time(nullptr) - start_time < 20;) {
396 if (g_waiters.load() == 1) {
397 break;
398 }
399 usleep(1000);
400 }
401 ASSERT_NE(0, tid.load());
402 ASSERT_EQ(0, tgkill(getpid(), tid.load(), SIGUSR1)) << "Error: " << strerror(errno);
403
404 // Wait 20 seconds for context data.
405 void* ucontext;
406 for (time_t start_time = time(nullptr); time(nullptr) - start_time < 20;) {
407 ucontext = reinterpret_cast<void*>(g_ucontext.load());
408 if (ucontext != nullptr) {
409 break;
410 }
411 usleep(1000);
412 }
413 ASSERT_TRUE(ucontext != nullptr) << "Timed out waiting for thread to respond to signal.";
414
415 LocalMaps maps;
416 ASSERT_TRUE(maps.Parse());
417 std::unique_ptr<Regs> regs(Regs::CreateFromUcontext(Regs::CurrentArch(), ucontext));
418
419 VerifyUnwind(getpid(), &maps, regs.get(), kFunctionOrder);
420
421 g_finish = true;
422 thread.join();
423 }
424
TEST_F(UnwindTest,remote_through_signal)425 TEST_F(UnwindTest, remote_through_signal) {
426 RemoteThroughSignal(SIGUSR1, 0);
427 }
428
TEST_F(UnwindTest,remote_through_signal_sa_siginfo)429 TEST_F(UnwindTest, remote_through_signal_sa_siginfo) {
430 RemoteThroughSignal(SIGUSR1, SA_SIGINFO);
431 }
432
TEST_F(UnwindTest,remote_through_signal_with_invalid_func)433 TEST_F(UnwindTest, remote_through_signal_with_invalid_func) {
434 RemoteThroughSignal(SIGSEGV, 0);
435 }
436
TEST_F(UnwindTest,remote_through_signal_sa_siginfo_with_invalid_func)437 TEST_F(UnwindTest, remote_through_signal_sa_siginfo_with_invalid_func) {
438 RemoteThroughSignal(SIGSEGV, SA_SIGINFO);
439 }
440
441 // Verify that using the same map while unwinding multiple threads at the
442 // same time doesn't cause problems.
TEST_F(UnwindTest,multiple_threads_unwind_same_map)443 TEST_F(UnwindTest, multiple_threads_unwind_same_map) {
444 static constexpr size_t kNumConcurrentThreads = 100;
445
446 LocalMaps maps;
447 ASSERT_TRUE(maps.Parse());
448 auto process_memory(Memory::CreateProcessMemory(getpid()));
449
450 std::vector<std::thread*> threads;
451
452 std::atomic_bool wait;
453 wait = true;
454 size_t frames[kNumConcurrentThreads];
455 for (size_t i = 0; i < kNumConcurrentThreads; i++) {
456 std::thread* thread = new std::thread([i, &frames, &maps, &process_memory, &wait]() {
457 while (wait) {
458 }
459 std::unique_ptr<Regs> regs(Regs::CreateFromLocal());
460 RegsGetLocal(regs.get());
461
462 Unwinder unwinder(512, &maps, regs.get(), process_memory);
463 unwinder.Unwind();
464 frames[i] = unwinder.NumFrames();
465 ASSERT_LE(3U, frames[i]) << "Failed for thread " << i;
466 });
467 threads.push_back(thread);
468 }
469 wait = false;
470 for (auto thread : threads) {
471 thread->join();
472 delete thread;
473 }
474 }
475
TEST_F(UnwindTest,thread_unwind)476 TEST_F(UnwindTest, thread_unwind) {
477 std::atomic_int tid(0);
478 std::thread thread([&tid]() {
479 tid = android::base::GetThreadId();
480 OuterFunction(TEST_TYPE_LOCAL_WAIT_FOR_FINISH);
481 });
482
483 while (g_waiters.load() != 1) {
484 }
485
486 ThreadUnwinder unwinder(512);
487 ASSERT_TRUE(unwinder.Init());
488 unwinder.UnwindWithSignal(SIGRTMIN, tid);
489 VerifyUnwindFrames(&unwinder, kFunctionOrder);
490
491 g_finish = true;
492 thread.join();
493 }
494
TEST_F(UnwindTest,thread_unwind_copy_regs)495 TEST_F(UnwindTest, thread_unwind_copy_regs) {
496 std::atomic_int tid(0);
497 std::thread thread([&tid]() {
498 tid = android::base::GetThreadId();
499 OuterFunction(TEST_TYPE_LOCAL_WAIT_FOR_FINISH);
500 });
501
502 while (g_waiters.load() != 1) {
503 }
504
505 ThreadUnwinder unwinder(512);
506 ASSERT_TRUE(unwinder.Init());
507 std::unique_ptr<Regs> initial_regs;
508 unwinder.UnwindWithSignal(SIGRTMIN, tid, &initial_regs);
509 ASSERT_TRUE(initial_regs != nullptr);
510 // Verify the initial registers match the first frame pc/sp.
511 ASSERT_TRUE(unwinder.NumFrames() != 0);
512 auto initial_frame = unwinder.frames()[0];
513 ASSERT_EQ(initial_regs->pc(), initial_frame.pc);
514 ASSERT_EQ(initial_regs->sp(), initial_frame.sp);
515 VerifyUnwindFrames(&unwinder, kFunctionOrder);
516
517 g_finish = true;
518 thread.join();
519 }
520
TEST_F(UnwindTest,thread_unwind_with_external_maps)521 TEST_F(UnwindTest, thread_unwind_with_external_maps) {
522 std::atomic_int tid(0);
523 std::thread thread([&tid]() {
524 tid = android::base::GetThreadId();
525 OuterFunction(TEST_TYPE_LOCAL_WAIT_FOR_FINISH);
526 });
527
528 while (g_waiters.load() != 1) {
529 }
530
531 LocalMaps maps;
532 ASSERT_TRUE(maps.Parse());
533
534 ThreadUnwinder unwinder(512, &maps);
535 ASSERT_EQ(&maps, unwinder.GetMaps());
536 ASSERT_TRUE(unwinder.Init());
537 ASSERT_EQ(&maps, unwinder.GetMaps());
538 unwinder.UnwindWithSignal(SIGRTMIN, tid);
539 VerifyUnwindFrames(&unwinder, kFunctionOrder);
540 ASSERT_EQ(&maps, unwinder.GetMaps());
541
542 g_finish = true;
543 thread.join();
544 }
545
TEST_F(UnwindTest,thread_unwind_cur_pid)546 TEST_F(UnwindTest, thread_unwind_cur_pid) {
547 ThreadUnwinder unwinder(512);
548 ASSERT_TRUE(unwinder.Init());
549 unwinder.UnwindWithSignal(SIGRTMIN, getpid());
550 EXPECT_EQ(0U, unwinder.NumFrames());
551 EXPECT_EQ(ERROR_UNSUPPORTED, unwinder.LastErrorCode());
552 }
553
TEST_F(UnwindTest,thread_unwind_cur_thread)554 TEST_F(UnwindTest, thread_unwind_cur_thread) {
555 std::thread thread([]() {
556 ThreadUnwinder unwinder(512);
557 ASSERT_TRUE(unwinder.Init());
558 unwinder.UnwindWithSignal(SIGRTMIN, android::base::GetThreadId());
559 EXPECT_EQ(0U, unwinder.NumFrames());
560 EXPECT_EQ(ERROR_UNSUPPORTED, unwinder.LastErrorCode());
561 });
562 thread.join();
563 }
564
TEST_F(UnwindTest,thread_unwind_cur_pid_from_thread)565 TEST_F(UnwindTest, thread_unwind_cur_pid_from_thread) {
566 std::thread thread([]() {
567 ThreadUnwinder unwinder(512);
568 ASSERT_TRUE(unwinder.Init());
569 unwinder.UnwindWithSignal(SIGRTMIN, getpid());
570 EXPECT_NE(0U, unwinder.NumFrames());
571 EXPECT_NE(ERROR_UNSUPPORTED, unwinder.LastErrorCode());
572 });
573 thread.join();
574 }
575
CreateUnwindThread(std::atomic_int & tid,ThreadUnwinder & unwinder,std::atomic_bool & start_unwinding,std::atomic_int & unwinders)576 static std::thread* CreateUnwindThread(std::atomic_int& tid, ThreadUnwinder& unwinder,
577 std::atomic_bool& start_unwinding,
578 std::atomic_int& unwinders) {
579 return new std::thread([&tid, &unwinder, &start_unwinding, &unwinders]() {
580 while (!start_unwinding.load()) {
581 }
582
583 ThreadUnwinder thread_unwinder(512, &unwinder);
584 // Allow the unwind to timeout since this will be doing multiple
585 // unwinds at once.
586 for (size_t i = 0; i < 3; i++) {
587 thread_unwinder.UnwindWithSignal(SIGRTMIN, tid);
588 if (thread_unwinder.LastErrorCode() != ERROR_THREAD_TIMEOUT) {
589 break;
590 }
591 }
592 VerifyUnwindFrames(&thread_unwinder, kFunctionOrder);
593 ++unwinders;
594 });
595 }
596
TEST_F(UnwindTest,thread_unwind_same_thread_from_threads)597 TEST_F(UnwindTest, thread_unwind_same_thread_from_threads) {
598 static constexpr size_t kNumThreads = 300;
599
600 std::atomic_int tid(0);
601 std::thread thread([&tid]() {
602 tid = android::base::GetThreadId();
603 OuterFunction(TEST_TYPE_LOCAL_WAIT_FOR_FINISH);
604 });
605
606 while (g_waiters.load() != 1) {
607 }
608
609 ThreadUnwinder unwinder(512);
610 ASSERT_TRUE(unwinder.Init());
611
612 std::atomic_bool start_unwinding(false);
613 std::vector<std::thread*> threads;
614 std::atomic_int unwinders(0);
615 for (size_t i = 0; i < kNumThreads; i++) {
616 threads.push_back(CreateUnwindThread(tid, unwinder, start_unwinding, unwinders));
617 }
618
619 start_unwinding = true;
620 while (unwinders.load() != kNumThreads) {
621 }
622
623 for (auto* thread : threads) {
624 thread->join();
625 delete thread;
626 }
627
628 g_finish = true;
629 thread.join();
630 }
631
TEST_F(UnwindTest,thread_unwind_multiple_thread_from_threads)632 TEST_F(UnwindTest, thread_unwind_multiple_thread_from_threads) {
633 static constexpr size_t kNumThreads = 100;
634
635 std::atomic_int tids[kNumThreads] = {};
636 std::vector<std::thread*> threads;
637 for (size_t i = 0; i < kNumThreads; i++) {
638 std::thread* thread = new std::thread([&tids, i]() {
639 tids[i] = android::base::GetThreadId();
640 OuterFunction(TEST_TYPE_LOCAL_WAIT_FOR_FINISH);
641 });
642 threads.push_back(thread);
643 }
644
645 while (g_waiters.load() != kNumThreads) {
646 }
647
648 ThreadUnwinder unwinder(512);
649 ASSERT_TRUE(unwinder.Init());
650
651 std::atomic_bool start_unwinding(false);
652 std::vector<std::thread*> unwinder_threads;
653 std::atomic_int unwinders(0);
654 for (size_t i = 0; i < kNumThreads; i++) {
655 unwinder_threads.push_back(CreateUnwindThread(tids[i], unwinder, start_unwinding, unwinders));
656 }
657
658 start_unwinding = true;
659 while (unwinders.load() != kNumThreads) {
660 }
661
662 for (auto* thread : unwinder_threads) {
663 thread->join();
664 delete thread;
665 }
666
667 g_finish = true;
668
669 for (auto* thread : threads) {
670 thread->join();
671 delete thread;
672 }
673 }
674
TEST_F(UnwindTest,thread_unwind_multiple_thread_from_threads_updatable_maps)675 TEST_F(UnwindTest, thread_unwind_multiple_thread_from_threads_updatable_maps) {
676 static constexpr size_t kNumThreads = 100;
677
678 // Do this before the threads are started so that the maps needed to
679 // unwind are not created yet, and this verifies the dynamic nature
680 // of the LocalUpdatableMaps object.
681 LocalUpdatableMaps maps;
682 ASSERT_TRUE(maps.Parse());
683
684 std::atomic_int tids[kNumThreads] = {};
685 std::vector<std::thread*> threads;
686 for (size_t i = 0; i < kNumThreads; i++) {
687 std::thread* thread = new std::thread([&tids, i]() {
688 tids[i] = android::base::GetThreadId();
689 OuterFunction(TEST_TYPE_LOCAL_WAIT_FOR_FINISH);
690 });
691 threads.push_back(thread);
692 }
693
694 while (g_waiters.load() != kNumThreads) {
695 }
696
697 ThreadUnwinder unwinder(512, &maps);
698 ASSERT_TRUE(unwinder.Init());
699
700 std::atomic_bool start_unwinding(false);
701 std::vector<std::thread*> unwinder_threads;
702 std::atomic_int unwinders(0);
703 for (size_t i = 0; i < kNumThreads; i++) {
704 unwinder_threads.push_back(CreateUnwindThread(tids[i], unwinder, start_unwinding, unwinders));
705 }
706
707 start_unwinding = true;
708 while (unwinders.load() != kNumThreads) {
709 }
710
711 for (auto* thread : unwinder_threads) {
712 thread->join();
713 delete thread;
714 }
715
716 g_finish = true;
717
718 for (auto* thread : threads) {
719 thread->join();
720 delete thread;
721 }
722 }
723
724 } // namespace unwindstack
725