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