• 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/Memory.h>
39 #include <unwindstack/Regs.h>
40 #include <unwindstack/RegsGetLocal.h>
41 #include <unwindstack/Unwinder.h>
42 
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 
ResetGlobals()61 static void ResetGlobals() {
62   g_ready = false;
63   g_ready_for_remote = false;
64   g_signal_ready_for_remote = false;
65   g_finish = false;
66   g_ucontext = 0;
67 }
68 
69 static std::vector<const char*> kFunctionOrder{"OuterFunction", "MiddleFunction", "InnerFunction"};
70 
71 static std::vector<const char*> kFunctionSignalOrder{"OuterFunction",        "MiddleFunction",
72                                                      "InnerFunction",        "SignalOuterFunction",
73                                                      "SignalMiddleFunction", "SignalInnerFunction"};
74 
SignalHandler(int,siginfo_t *,void * sigcontext)75 static void SignalHandler(int, siginfo_t*, void* sigcontext) {
76   g_ucontext = reinterpret_cast<uintptr_t>(sigcontext);
77   while (!g_finish.load()) {
78   }
79 }
80 
SignalInnerFunction()81 extern "C" void SignalInnerFunction() {
82   g_signal_ready_for_remote = true;
83   // Avoid any function calls because not every instruction will be
84   // unwindable.
85   // This method of looping is only used when testing a remote unwind.
86   while (true) {
87   }
88 }
89 
SignalMiddleFunction()90 extern "C" void SignalMiddleFunction() {
91   SignalInnerFunction();
92 }
93 
SignalOuterFunction()94 extern "C" void SignalOuterFunction() {
95   SignalMiddleFunction();
96 }
97 
SignalCallerHandler(int,siginfo_t *,void *)98 static void SignalCallerHandler(int, siginfo_t*, void*) {
99   SignalOuterFunction();
100 }
101 
ErrorMsg(const std::vector<const char * > & function_names,Unwinder * unwinder)102 static std::string ErrorMsg(const std::vector<const char*>& function_names, Unwinder* unwinder) {
103   std::string unwind;
104   for (size_t i = 0; i < unwinder->NumFrames(); i++) {
105     unwind += unwinder->FormatFrame(i) + '\n';
106   }
107 
108   return std::string(
109              "Unwind completed without finding all frames\n"
110              "  Looking for function: ") +
111          function_names.front() + "\n" + "Unwind data:\n" + unwind;
112 }
113 
VerifyUnwind(Unwinder * unwinder,std::vector<const char * > expected_function_names)114 static void VerifyUnwind(Unwinder* unwinder, std::vector<const char*> expected_function_names) {
115   unwinder->Unwind();
116 
117   for (auto& frame : unwinder->frames()) {
118     if (frame.function_name == expected_function_names.back()) {
119       expected_function_names.pop_back();
120       if (expected_function_names.empty()) {
121         break;
122       }
123     }
124   }
125 
126   ASSERT_TRUE(expected_function_names.empty()) << ErrorMsg(expected_function_names, unwinder);
127 }
128 
VerifyUnwind(pid_t pid,Maps * maps,Regs * regs,std::vector<const char * > expected_function_names)129 static void VerifyUnwind(pid_t pid, Maps* maps, Regs* regs,
130                          std::vector<const char*> expected_function_names) {
131   auto process_memory(Memory::CreateProcessMemory(pid));
132 
133   Unwinder unwinder(512, maps, regs, process_memory);
134   VerifyUnwind(&unwinder, expected_function_names);
135 }
136 
137 // This test assumes that this code is compiled with optimizations turned
138 // off. If this doesn't happen, then all of the calls will be optimized
139 // away.
InnerFunction(TestTypeEnum test_type)140 extern "C" void InnerFunction(TestTypeEnum test_type) {
141   if (test_type == TEST_TYPE_LOCAL_WAIT_FOR_FINISH) {
142     while (!g_finish.load()) {
143     }
144     return;
145   }
146   if (test_type == TEST_TYPE_REMOTE || test_type == TEST_TYPE_REMOTE_WITH_INVALID_CALL) {
147     g_ready_for_remote = true;
148     g_ready = true;
149     if (test_type == TEST_TYPE_REMOTE_WITH_INVALID_CALL) {
150       void (*crash_func)() = nullptr;
151       crash_func();
152     }
153     // Avoid any function calls because not every instruction will be
154     // unwindable.
155     // This method of looping is only used when testing a remote unwind.
156     while (true) {
157     }
158     return;
159   }
160 
161   std::unique_ptr<Unwinder> unwinder;
162   std::unique_ptr<Regs> regs(Regs::CreateFromLocal());
163   RegsGetLocal(regs.get());
164   std::unique_ptr<Maps> maps;
165 
166   if (test_type == TEST_TYPE_LOCAL_UNWINDER) {
167     maps.reset(new LocalMaps());
168     ASSERT_TRUE(maps->Parse());
169     auto process_memory(Memory::CreateProcessMemory(getpid()));
170     unwinder.reset(new Unwinder(512, maps.get(), regs.get(), process_memory));
171   } else {
172     UnwinderFromPid* unwinder_from_pid = new UnwinderFromPid(512, getpid());
173     ASSERT_TRUE(unwinder_from_pid->Init(regs->Arch()));
174     unwinder_from_pid->SetRegs(regs.get());
175     unwinder.reset(unwinder_from_pid);
176   }
177   VerifyUnwind(unwinder.get(), kFunctionOrder);
178 }
179 
MiddleFunction(TestTypeEnum test_type)180 extern "C" void MiddleFunction(TestTypeEnum test_type) {
181   InnerFunction(test_type);
182 }
183 
OuterFunction(TestTypeEnum test_type)184 extern "C" void OuterFunction(TestTypeEnum test_type) {
185   MiddleFunction(test_type);
186 }
187 
188 class UnwindTest : public ::testing::Test {
189  public:
SetUp()190   void SetUp() override { ResetGlobals(); }
191 };
192 
TEST_F(UnwindTest,local)193 TEST_F(UnwindTest, local) {
194   OuterFunction(TEST_TYPE_LOCAL_UNWINDER);
195 }
196 
TEST_F(UnwindTest,local_use_from_pid)197 TEST_F(UnwindTest, local_use_from_pid) {
198   OuterFunction(TEST_TYPE_LOCAL_UNWINDER_FROM_PID);
199 }
200 
LocalUnwind(void * data)201 static void LocalUnwind(void* data) {
202   TestTypeEnum* test_type = reinterpret_cast<TestTypeEnum*>(data);
203   OuterFunction(*test_type);
204 }
205 
TEST_F(UnwindTest,local_check_for_leak)206 TEST_F(UnwindTest, local_check_for_leak) {
207   TestTypeEnum test_type = TEST_TYPE_LOCAL_UNWINDER;
208   TestCheckForLeaks(LocalUnwind, &test_type);
209 }
210 
TEST_F(UnwindTest,local_use_from_pid_check_for_leak)211 TEST_F(UnwindTest, local_use_from_pid_check_for_leak) {
212   TestTypeEnum test_type = TEST_TYPE_LOCAL_UNWINDER_FROM_PID;
213   TestCheckForLeaks(LocalUnwind, &test_type);
214 }
215 
WaitForRemote(pid_t pid,uint64_t addr,bool leave_attached,bool * completed)216 void WaitForRemote(pid_t pid, uint64_t addr, bool leave_attached, bool* completed) {
217   *completed = false;
218   // Need to sleep before attempting first ptrace. Without this, on the
219   // host it becomes impossible to attach and ptrace sets errno to EPERM.
220   usleep(1000);
221   for (size_t i = 0; i < 1000; i++) {
222     if (ptrace(PTRACE_ATTACH, pid, 0, 0) == 0) {
223       ASSERT_TRUE(TestQuiescePid(pid))
224           << "Waiting for process to quiesce failed: " << strerror(errno);
225 
226       MemoryRemote memory(pid);
227       // Read the remote value to see if we are ready.
228       bool value;
229       if (memory.ReadFully(addr, &value, sizeof(value)) && value) {
230         *completed = true;
231       }
232       if (!*completed || !leave_attached) {
233         ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0));
234       }
235       if (*completed) {
236         break;
237       }
238     } else {
239       ASSERT_EQ(ESRCH, errno) << "ptrace attach failed with unexpected error: " << strerror(errno);
240     }
241     usleep(5000);
242   }
243 }
244 
TEST_F(UnwindTest,remote)245 TEST_F(UnwindTest, remote) {
246   pid_t pid;
247   if ((pid = fork()) == 0) {
248     OuterFunction(TEST_TYPE_REMOTE);
249     exit(0);
250   }
251   ASSERT_NE(-1, pid);
252   TestScopedPidReaper reap(pid);
253 
254   bool completed;
255   WaitForRemote(pid, reinterpret_cast<uint64_t>(&g_ready_for_remote), true, &completed);
256   ASSERT_TRUE(completed) << "Timed out waiting for remote process to be ready.";
257 
258   RemoteMaps maps(pid);
259   ASSERT_TRUE(maps.Parse());
260   std::unique_ptr<Regs> regs(Regs::RemoteGet(pid));
261   ASSERT_TRUE(regs.get() != nullptr);
262 
263   VerifyUnwind(pid, &maps, regs.get(), kFunctionOrder);
264 
265   ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0))
266       << "ptrace detach failed with unexpected error: " << strerror(errno);
267 }
268 
TEST_F(UnwindTest,unwind_from_pid_remote)269 TEST_F(UnwindTest, unwind_from_pid_remote) {
270   pid_t pid;
271   if ((pid = fork()) == 0) {
272     OuterFunction(TEST_TYPE_REMOTE);
273     exit(0);
274   }
275   ASSERT_NE(-1, pid);
276   TestScopedPidReaper reap(pid);
277 
278   bool completed;
279   WaitForRemote(pid, reinterpret_cast<uint64_t>(&g_ready_for_remote), true, &completed);
280   ASSERT_TRUE(completed) << "Timed out waiting for remote process to be ready.";
281 
282   std::unique_ptr<Regs> regs(Regs::RemoteGet(pid));
283   ASSERT_TRUE(regs.get() != nullptr);
284 
285   UnwinderFromPid unwinder(512, pid);
286   ASSERT_TRUE(unwinder.Init(regs->Arch()));
287   unwinder.SetRegs(regs.get());
288 
289   VerifyUnwind(&unwinder, kFunctionOrder);
290 
291   // Verify that calling the same object works again.
292 
293   ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0))
294       << "ptrace detach failed with unexpected error: " << strerror(errno);
295 }
296 
RemoteCheckForLeaks(void (* unwind_func)(void *))297 static void RemoteCheckForLeaks(void (*unwind_func)(void*)) {
298   pid_t pid;
299   if ((pid = fork()) == 0) {
300     OuterFunction(TEST_TYPE_REMOTE);
301     exit(0);
302   }
303   ASSERT_NE(-1, pid);
304   TestScopedPidReaper reap(pid);
305 
306   bool completed;
307   WaitForRemote(pid, reinterpret_cast<uint64_t>(&g_ready_for_remote), true, &completed);
308   ASSERT_TRUE(completed) << "Timed out waiting for remote process to be ready.";
309 
310   TestCheckForLeaks(unwind_func, &pid);
311 
312   ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0))
313       << "ptrace detach failed with unexpected error: " << strerror(errno);
314 }
315 
RemoteUnwind(void * data)316 static void RemoteUnwind(void* data) {
317   pid_t* pid = reinterpret_cast<pid_t*>(data);
318 
319   RemoteMaps maps(*pid);
320   ASSERT_TRUE(maps.Parse());
321   std::unique_ptr<Regs> regs(Regs::RemoteGet(*pid));
322   ASSERT_TRUE(regs.get() != nullptr);
323 
324   VerifyUnwind(*pid, &maps, regs.get(), kFunctionOrder);
325 }
326 
TEST_F(UnwindTest,remote_check_for_leaks)327 TEST_F(UnwindTest, remote_check_for_leaks) {
328   RemoteCheckForLeaks(RemoteUnwind);
329 }
330 
RemoteUnwindFromPid(void * data)331 static void RemoteUnwindFromPid(void* data) {
332   pid_t* pid = reinterpret_cast<pid_t*>(data);
333 
334   std::unique_ptr<Regs> regs(Regs::RemoteGet(*pid));
335   ASSERT_TRUE(regs.get() != nullptr);
336 
337   UnwinderFromPid unwinder(512, *pid);
338   ASSERT_TRUE(unwinder.Init(regs->Arch()));
339   unwinder.SetRegs(regs.get());
340 
341   VerifyUnwind(&unwinder, kFunctionOrder);
342 }
343 
TEST_F(UnwindTest,remote_unwind_for_pid_check_for_leaks)344 TEST_F(UnwindTest, remote_unwind_for_pid_check_for_leaks) {
345   RemoteCheckForLeaks(RemoteUnwindFromPid);
346 }
347 
TEST_F(UnwindTest,from_context)348 TEST_F(UnwindTest, from_context) {
349   std::atomic_int tid(0);
350   std::thread thread([&]() {
351     tid = syscall(__NR_gettid);
352     OuterFunction(TEST_TYPE_LOCAL_WAIT_FOR_FINISH);
353   });
354 
355   struct sigaction act, oldact;
356   memset(&act, 0, sizeof(act));
357   act.sa_sigaction = SignalHandler;
358   act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
359   ASSERT_EQ(0, sigaction(SIGUSR1, &act, &oldact));
360   // Wait for the tid to get set.
361   for (size_t i = 0; i < 100; i++) {
362     if (tid.load() != 0) {
363       break;
364     }
365     usleep(1000);
366   }
367   ASSERT_NE(0, tid.load());
368   ASSERT_EQ(0, tgkill(getpid(), tid.load(), SIGUSR1)) << "Error: " << strerror(errno);
369 
370   // Wait for context data.
371   void* ucontext;
372   for (size_t i = 0; i < 2000; i++) {
373     ucontext = reinterpret_cast<void*>(g_ucontext.load());
374     if (ucontext != nullptr) {
375       break;
376     }
377     usleep(1000);
378   }
379   ASSERT_TRUE(ucontext != nullptr) << "Timed out waiting for thread to respond to signal.";
380 
381   LocalMaps maps;
382   ASSERT_TRUE(maps.Parse());
383   std::unique_ptr<Regs> regs(Regs::CreateFromUcontext(Regs::CurrentArch(), ucontext));
384 
385   VerifyUnwind(getpid(), &maps, regs.get(), kFunctionOrder);
386 
387   ASSERT_EQ(0, sigaction(SIGUSR1, &oldact, nullptr));
388 
389   g_finish = true;
390   thread.join();
391 }
392 
RemoteThroughSignal(int signal,unsigned int sa_flags)393 static void RemoteThroughSignal(int signal, unsigned int sa_flags) {
394   pid_t pid;
395   if ((pid = fork()) == 0) {
396     struct sigaction act, oldact;
397     memset(&act, 0, sizeof(act));
398     act.sa_sigaction = SignalCallerHandler;
399     act.sa_flags = SA_RESTART | SA_ONSTACK | sa_flags;
400     ASSERT_EQ(0, sigaction(signal, &act, &oldact));
401 
402     OuterFunction(signal != SIGSEGV ? TEST_TYPE_REMOTE : TEST_TYPE_REMOTE_WITH_INVALID_CALL);
403     exit(0);
404   }
405   ASSERT_NE(-1, pid);
406   TestScopedPidReaper reap(pid);
407 
408   bool completed;
409   if (signal != SIGSEGV) {
410     WaitForRemote(pid, reinterpret_cast<uint64_t>(&g_ready_for_remote), false, &completed);
411     ASSERT_TRUE(completed) << "Timed out waiting for remote process to be ready.";
412     ASSERT_EQ(0, kill(pid, SIGUSR1));
413   }
414   WaitForRemote(pid, reinterpret_cast<uint64_t>(&g_signal_ready_for_remote), true, &completed);
415   ASSERT_TRUE(completed) << "Timed out waiting for remote process to be in signal handler.";
416 
417   RemoteMaps maps(pid);
418   ASSERT_TRUE(maps.Parse());
419   std::unique_ptr<Regs> regs(Regs::RemoteGet(pid));
420   ASSERT_TRUE(regs.get() != nullptr);
421 
422   VerifyUnwind(pid, &maps, regs.get(), kFunctionSignalOrder);
423 
424   ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0))
425       << "ptrace detach failed with unexpected error: " << strerror(errno);
426 }
427 
TEST_F(UnwindTest,remote_through_signal)428 TEST_F(UnwindTest, remote_through_signal) {
429   RemoteThroughSignal(SIGUSR1, 0);
430 }
431 
TEST_F(UnwindTest,remote_through_signal_sa_siginfo)432 TEST_F(UnwindTest, remote_through_signal_sa_siginfo) {
433   RemoteThroughSignal(SIGUSR1, SA_SIGINFO);
434 }
435 
TEST_F(UnwindTest,remote_through_signal_with_invalid_func)436 TEST_F(UnwindTest, remote_through_signal_with_invalid_func) {
437   RemoteThroughSignal(SIGSEGV, 0);
438 }
439 
TEST_F(UnwindTest,remote_through_signal_sa_siginfo_with_invalid_func)440 TEST_F(UnwindTest, remote_through_signal_sa_siginfo_with_invalid_func) {
441   RemoteThroughSignal(SIGSEGV, SA_SIGINFO);
442 }
443 
444 // Verify that using the same map while unwinding multiple threads at the
445 // same time doesn't cause problems.
TEST_F(UnwindTest,multiple_threads_unwind_same_map)446 TEST_F(UnwindTest, multiple_threads_unwind_same_map) {
447   static constexpr size_t kNumConcurrentThreads = 100;
448 
449   LocalMaps maps;
450   ASSERT_TRUE(maps.Parse());
451   auto process_memory(Memory::CreateProcessMemory(getpid()));
452 
453   std::vector<std::thread*> threads;
454 
455   std::atomic_bool wait;
456   wait = true;
457   size_t frames[kNumConcurrentThreads];
458   for (size_t i = 0; i < kNumConcurrentThreads; i++) {
459     std::thread* thread = new std::thread([i, &frames, &maps, &process_memory, &wait]() {
460       while (wait)
461         ;
462       std::unique_ptr<Regs> regs(Regs::CreateFromLocal());
463       RegsGetLocal(regs.get());
464 
465       Unwinder unwinder(512, &maps, regs.get(), process_memory);
466       unwinder.Unwind();
467       frames[i] = unwinder.NumFrames();
468       ASSERT_LE(3U, frames[i]) << "Failed for thread " << i;
469     });
470     threads.push_back(thread);
471   }
472   wait = false;
473   for (auto thread : threads) {
474     thread->join();
475     delete thread;
476   }
477 }
478 
479 }  // namespace unwindstack
480