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