Home | History | Annotate | Download | only in tests
      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 
     36 #include <unwindstack/Maps.h>
     37 #include <unwindstack/Memory.h>
     38 #include <unwindstack/Regs.h>
     39 #include <unwindstack/RegsGetLocal.h>
     40 #include <unwindstack/Unwinder.h>
     41 
     42 #include "TestUtils.h"
     43 
     44 namespace unwindstack {
     45 
     46 static std::atomic_bool g_ready;
     47 static volatile bool g_ready_for_remote;
     48 static volatile bool g_signal_ready_for_remote;
     49 static std::atomic_bool g_finish;
     50 static std::atomic_uintptr_t g_ucontext;
     51 
     52 static void ResetGlobals() {
     53   g_ready = false;
     54   g_ready_for_remote = false;
     55   g_signal_ready_for_remote = false;
     56   g_finish = false;
     57   g_ucontext = 0;
     58 }
     59 
     60 static std::vector<const char*> kFunctionOrder{"OuterFunction", "MiddleFunction", "InnerFunction"};
     61 
     62 static std::vector<const char*> kFunctionSignalOrder{"OuterFunction",        "MiddleFunction",
     63                                                      "InnerFunction",        "SignalOuterFunction",
     64                                                      "SignalMiddleFunction", "SignalInnerFunction"};
     65 
     66 static void SignalHandler(int, siginfo_t*, void* sigcontext) {
     67   g_ucontext = reinterpret_cast<uintptr_t>(sigcontext);
     68   while (!g_finish.load()) {
     69   }
     70 }
     71 
     72 extern "C" void SignalInnerFunction() {
     73   g_signal_ready_for_remote = true;
     74   while (!g_finish.load()) {
     75   }
     76 }
     77 
     78 extern "C" void SignalMiddleFunction() {
     79   SignalInnerFunction();
     80 }
     81 
     82 extern "C" void SignalOuterFunction() {
     83   SignalMiddleFunction();
     84 }
     85 
     86 static void SignalCallerHandler(int, siginfo_t*, void*) {
     87   SignalOuterFunction();
     88 }
     89 
     90 static std::string ErrorMsg(const std::vector<const char*>& function_names, Unwinder& unwinder) {
     91   std::string unwind;
     92   for (size_t i = 0; i < unwinder.NumFrames(); i++) {
     93     unwind += unwinder.FormatFrame(i) + '\n';
     94   }
     95 
     96   return std::string(
     97              "Unwind completed without finding all frames\n"
     98              "  Looking for function: ") +
     99          function_names.front() + "\n" + "Unwind data:\n" + unwind;
    100 }
    101 
    102 static void VerifyUnwind(pid_t pid, Maps* maps, Regs* regs,
    103                          std::vector<const char*> expected_function_names) {
    104   auto process_memory(Memory::CreateProcessMemory(pid));
    105 
    106   Unwinder unwinder(512, maps, regs, process_memory);
    107   unwinder.Unwind();
    108 
    109   std::string expected_function = expected_function_names.back();
    110   expected_function_names.pop_back();
    111   for (auto& frame : unwinder.frames()) {
    112     if (frame.function_name == expected_function) {
    113       if (expected_function_names.empty()) {
    114         break;
    115       }
    116       expected_function = expected_function_names.back();
    117       expected_function_names.pop_back();
    118     }
    119   }
    120 
    121   ASSERT_TRUE(expected_function_names.empty()) << ErrorMsg(expected_function_names, unwinder);
    122 }
    123 
    124 // This test assumes that this code is compiled with optimizations turned
    125 // off. If this doesn't happen, then all of the calls will be optimized
    126 // away.
    127 extern "C" void InnerFunction(bool local, bool trigger_invalid_call) {
    128   if (local) {
    129     LocalMaps maps;
    130     ASSERT_TRUE(maps.Parse());
    131     std::unique_ptr<Regs> regs(Regs::CreateFromLocal());
    132     RegsGetLocal(regs.get());
    133 
    134     VerifyUnwind(getpid(), &maps, regs.get(), kFunctionOrder);
    135   } else {
    136     g_ready_for_remote = true;
    137     g_ready = true;
    138     if (trigger_invalid_call) {
    139       void (*crash_func)() = nullptr;
    140       crash_func();
    141     }
    142     while (!g_finish.load()) {
    143     }
    144   }
    145 }
    146 
    147 extern "C" void MiddleFunction(bool local, bool trigger_invalid_call) {
    148   InnerFunction(local, trigger_invalid_call);
    149 }
    150 
    151 extern "C" void OuterFunction(bool local, bool trigger_invalid_call) {
    152   MiddleFunction(local, trigger_invalid_call);
    153 }
    154 
    155 class UnwindTest : public ::testing::Test {
    156  public:
    157   void SetUp() override { ResetGlobals(); }
    158 };
    159 
    160 TEST_F(UnwindTest, local) {
    161   OuterFunction(true, false);
    162 }
    163 
    164 void WaitForRemote(pid_t pid, uint64_t addr, bool leave_attached, bool* completed) {
    165   *completed = false;
    166   // Need to sleep before attempting first ptrace. Without this, on the
    167   // host it becomes impossible to attach and ptrace sets errno to EPERM.
    168   usleep(1000);
    169   for (size_t i = 0; i < 1000; i++) {
    170     if (ptrace(PTRACE_ATTACH, pid, 0, 0) == 0) {
    171       ASSERT_TRUE(TestQuiescePid(pid))
    172           << "Waiting for process to quiesce failed: " << strerror(errno);
    173 
    174       MemoryRemote memory(pid);
    175       // Read the remote value to see if we are ready.
    176       bool value;
    177       if (memory.ReadFully(addr, &value, sizeof(value)) && value) {
    178         *completed = true;
    179       }
    180       if (!*completed || !leave_attached) {
    181         ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0));
    182       }
    183       if (*completed) {
    184         break;
    185       }
    186     } else {
    187       ASSERT_EQ(ESRCH, errno) << "ptrace attach failed with unexpected error: " << strerror(errno);
    188     }
    189     usleep(5000);
    190   }
    191 }
    192 
    193 TEST_F(UnwindTest, remote) {
    194   pid_t pid;
    195   if ((pid = fork()) == 0) {
    196     OuterFunction(false, false);
    197     exit(0);
    198   }
    199   ASSERT_NE(-1, pid);
    200   TestScopedPidReaper reap(pid);
    201 
    202   bool completed;
    203   WaitForRemote(pid, reinterpret_cast<uint64_t>(&g_ready_for_remote), true, &completed);
    204   ASSERT_TRUE(completed) << "Timed out waiting for remote process to be ready.";
    205 
    206   RemoteMaps maps(pid);
    207   ASSERT_TRUE(maps.Parse());
    208   std::unique_ptr<Regs> regs(Regs::RemoteGet(pid));
    209   ASSERT_TRUE(regs.get() != nullptr);
    210 
    211   VerifyUnwind(pid, &maps, regs.get(), kFunctionOrder);
    212 
    213   ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0))
    214       << "ptrace detach failed with unexpected error: " << strerror(errno);
    215 }
    216 
    217 TEST_F(UnwindTest, from_context) {
    218   std::atomic_int tid(0);
    219   std::thread thread([&]() {
    220     tid = syscall(__NR_gettid);
    221     OuterFunction(false, false);
    222   });
    223 
    224   struct sigaction act, oldact;
    225   memset(&act, 0, sizeof(act));
    226   act.sa_sigaction = SignalHandler;
    227   act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
    228   ASSERT_EQ(0, sigaction(SIGUSR1, &act, &oldact));
    229   // Wait for the tid to get set.
    230   for (size_t i = 0; i < 100; i++) {
    231     if (tid.load() != 0) {
    232       break;
    233     }
    234     usleep(1000);
    235   }
    236   ASSERT_NE(0, tid.load());
    237   // Portable tgkill method.
    238   ASSERT_EQ(0, syscall(__NR_tgkill, getpid(), tid.load(), SIGUSR1)) << "Error: " << strerror(errno);
    239 
    240   // Wait for context data.
    241   void* ucontext;
    242   for (size_t i = 0; i < 2000; i++) {
    243     ucontext = reinterpret_cast<void*>(g_ucontext.load());
    244     if (ucontext != nullptr) {
    245       break;
    246     }
    247     usleep(1000);
    248   }
    249   ASSERT_TRUE(ucontext != nullptr) << "Timed out waiting for thread to respond to signal.";
    250 
    251   LocalMaps maps;
    252   ASSERT_TRUE(maps.Parse());
    253   std::unique_ptr<Regs> regs(Regs::CreateFromUcontext(Regs::CurrentArch(), ucontext));
    254 
    255   VerifyUnwind(getpid(), &maps, regs.get(), kFunctionOrder);
    256 
    257   ASSERT_EQ(0, sigaction(SIGUSR1, &oldact, nullptr));
    258 
    259   g_finish = true;
    260   thread.join();
    261 }
    262 
    263 static void RemoteThroughSignal(int signal, unsigned int sa_flags) {
    264   pid_t pid;
    265   if ((pid = fork()) == 0) {
    266     struct sigaction act, oldact;
    267     memset(&act, 0, sizeof(act));
    268     act.sa_sigaction = SignalCallerHandler;
    269     act.sa_flags = SA_RESTART | SA_ONSTACK | sa_flags;
    270     ASSERT_EQ(0, sigaction(signal, &act, &oldact));
    271 
    272     OuterFunction(false, signal == SIGSEGV);
    273     exit(0);
    274   }
    275   ASSERT_NE(-1, pid);
    276   TestScopedPidReaper reap(pid);
    277 
    278   bool completed;
    279   if (signal != SIGSEGV) {
    280     WaitForRemote(pid, reinterpret_cast<uint64_t>(&g_ready_for_remote), false, &completed);
    281     ASSERT_TRUE(completed) << "Timed out waiting for remote process to be ready.";
    282     ASSERT_EQ(0, kill(pid, SIGUSR1));
    283   }
    284   WaitForRemote(pid, reinterpret_cast<uint64_t>(&g_signal_ready_for_remote), true, &completed);
    285   ASSERT_TRUE(completed) << "Timed out waiting for remote process to be in signal handler.";
    286 
    287   RemoteMaps maps(pid);
    288   ASSERT_TRUE(maps.Parse());
    289   std::unique_ptr<Regs> regs(Regs::RemoteGet(pid));
    290   ASSERT_TRUE(regs.get() != nullptr);
    291 
    292   VerifyUnwind(pid, &maps, regs.get(), kFunctionSignalOrder);
    293 
    294   ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0))
    295       << "ptrace detach failed with unexpected error: " << strerror(errno);
    296 }
    297 
    298 TEST_F(UnwindTest, remote_through_signal) {
    299   RemoteThroughSignal(SIGUSR1, 0);
    300 }
    301 
    302 TEST_F(UnwindTest, remote_through_signal_sa_siginfo) {
    303   RemoteThroughSignal(SIGUSR1, SA_SIGINFO);
    304 }
    305 
    306 TEST_F(UnwindTest, remote_through_signal_with_invalid_func) {
    307   RemoteThroughSignal(SIGSEGV, 0);
    308 }
    309 
    310 TEST_F(UnwindTest, remote_through_signal_sa_siginfo_with_invalid_func) {
    311   RemoteThroughSignal(SIGSEGV, SA_SIGINFO);
    312 }
    313 
    314 // Verify that using the same map while unwinding multiple threads at the
    315 // same time doesn't cause problems.
    316 TEST_F(UnwindTest, multiple_threads_unwind_same_map) {
    317   static constexpr size_t kNumConcurrentThreads = 100;
    318 
    319   LocalMaps maps;
    320   ASSERT_TRUE(maps.Parse());
    321   auto process_memory(Memory::CreateProcessMemory(getpid()));
    322 
    323   std::vector<std::thread*> threads;
    324 
    325   std::atomic_bool wait;
    326   wait = true;
    327   size_t frames[kNumConcurrentThreads];
    328   for (size_t i = 0; i < kNumConcurrentThreads; i++) {
    329     std::thread* thread = new std::thread([i, &frames, &maps, &process_memory, &wait]() {
    330       while (wait)
    331         ;
    332       std::unique_ptr<Regs> regs(Regs::CreateFromLocal());
    333       RegsGetLocal(regs.get());
    334 
    335       Unwinder unwinder(512, &maps, regs.get(), process_memory);
    336       unwinder.Unwind();
    337       frames[i] = unwinder.NumFrames();
    338       ASSERT_LE(3U, frames[i]) << "Failed for thread " << i;
    339     });
    340     threads.push_back(thread);
    341   }
    342   wait = false;
    343   for (auto thread : threads) {
    344     thread->join();
    345     delete thread;
    346   }
    347 }
    348 
    349 }  // namespace unwindstack
    350