• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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