Home | History | Annotate | Download | only in 137-cfi
      1 /*
      2  * Copyright (C) 2015 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 #if __linux__
     18 #include <errno.h>
     19 #include <signal.h>
     20 #include <string.h>
     21 #include <sys/ptrace.h>
     22 #include <sys/wait.h>
     23 #include <unistd.h>
     24 #endif
     25 
     26 #include "jni.h"
     27 
     28 #include <android-base/logging.h>
     29 #include <android-base/stringprintf.h>
     30 #include <backtrace/Backtrace.h>
     31 
     32 #include "base/file_utils.h"
     33 #include "base/logging.h"
     34 #include "base/macros.h"
     35 #include "base/utils.h"
     36 #include "gc/heap.h"
     37 #include "gc/space/image_space.h"
     38 #include "oat_file.h"
     39 #include "runtime.h"
     40 
     41 namespace art {
     42 
     43 // For testing debuggerd. We do not have expected-death tests, so can't test this by default.
     44 // Code for this is copied from SignalTest.
     45 static constexpr bool kCauseSegfault = false;
     46 char* go_away_compiler_cfi = nullptr;
     47 
     48 static void CauseSegfault() {
     49 #if defined(__arm__) || defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
     50   // On supported architectures we cause a real SEGV.
     51   *go_away_compiler_cfi = 'a';
     52 #else
     53   // On other architectures we simulate SEGV.
     54   kill(getpid(), SIGSEGV);
     55 #endif
     56 }
     57 
     58 extern "C" JNIEXPORT jint JNICALL Java_Main_startSecondaryProcess(JNIEnv*, jclass) {
     59 #if __linux__
     60   // Get our command line so that we can use it to start identical process.
     61   std::string cmdline;  // null-separated and null-terminated arguments.
     62   ReadFileToString("/proc/self/cmdline", &cmdline);
     63   cmdline = cmdline + "--secondary" + '\0';  // Let the child know it is a helper.
     64 
     65   // Split the string into individual arguments suitable for execv.
     66   std::vector<char*> argv;
     67   for (size_t i = 0; i < cmdline.size(); i += strlen(&cmdline[i]) + 1) {
     68     argv.push_back(&cmdline[i]);
     69   }
     70   argv.push_back(nullptr);  // Terminate the list.
     71 
     72   pid_t pid = fork();
     73   if (pid < 0) {
     74     LOG(FATAL) << "Fork failed";
     75   } else if (pid == 0) {
     76     execv(argv[0], argv.data());
     77     exit(1);
     78   }
     79   return pid;
     80 #else
     81   return 0;
     82 #endif
     83 }
     84 
     85 extern "C" JNIEXPORT jboolean JNICALL Java_Main_sigstop(JNIEnv*, jclass) {
     86 #if __linux__
     87   raise(SIGSTOP);
     88 #endif
     89   return true;  // Prevent the compiler from tail-call optimizing this method away.
     90 }
     91 
     92 // Helper to look for a sequence in the stack trace.
     93 #if __linux__
     94 static bool CheckStack(Backtrace* bt, const std::vector<std::string>& seq) {
     95   size_t cur_search_index = 0;  // The currently active index in seq.
     96   CHECK_GT(seq.size(), 0U);
     97 
     98   for (Backtrace::const_iterator it = bt->begin(); it != bt->end(); ++it) {
     99     if (BacktraceMap::IsValid(it->map)) {
    100       LOG(INFO) << "Got " << it->func_name << ", looking for " << seq[cur_search_index];
    101       if (it->func_name.find(seq[cur_search_index]) != std::string::npos) {
    102         cur_search_index++;
    103         if (cur_search_index == seq.size()) {
    104           return true;
    105         }
    106       }
    107     }
    108   }
    109 
    110   printf("Cannot find %s in backtrace:\n", seq[cur_search_index].c_str());
    111   for (Backtrace::const_iterator it = bt->begin(); it != bt->end(); ++it) {
    112     if (BacktraceMap::IsValid(it->map)) {
    113       printf("  %s\n", Backtrace::FormatFrameData(&*it).c_str());
    114     }
    115   }
    116 
    117   return false;
    118 }
    119 
    120 static void MoreErrorInfo(pid_t pid, bool sig_quit_on_fail) {
    121   printf("Secondary pid is %d\n", pid);
    122 
    123   PrintFileToLog(android::base::StringPrintf("/proc/%d/maps", pid), ::android::base::ERROR);
    124 
    125   if (sig_quit_on_fail) {
    126     int res = kill(pid, SIGQUIT);
    127     if (res != 0) {
    128       PLOG(ERROR) << "Failed to send signal";
    129     }
    130   }
    131 }
    132 #endif
    133 
    134 extern "C" JNIEXPORT jboolean JNICALL Java_Main_unwindInProcess(JNIEnv*, jclass) {
    135 #if __linux__
    136   std::unique_ptr<Backtrace> bt(Backtrace::Create(BACKTRACE_CURRENT_PROCESS, GetTid()));
    137   if (!bt->Unwind(0, nullptr)) {
    138     printf("Cannot unwind in process.\n");
    139     return JNI_FALSE;
    140   } else if (bt->NumFrames() == 0) {
    141     printf("No frames for unwind in process.\n");
    142     return JNI_FALSE;
    143   }
    144 
    145   // We cannot really parse an exact stack, as the optimizing compiler may inline some functions.
    146   // This is also risky, as deduping might play a trick on us, so the test needs to make sure that
    147   // only unique functions are being expected.
    148   // "mini-debug-info" does not include parameters to save space.
    149   std::vector<std::string> seq = {
    150       "Java_Main_unwindInProcess",       // This function.
    151       "java.util.Arrays.binarySearch0",  // Framework method.
    152       "Base.$noinline$runTest",          // Method in other dex file.
    153       "Main.main"                        // The Java entry method.
    154   };
    155 
    156   bool result = CheckStack(bt.get(), seq);
    157   if (!kCauseSegfault) {
    158     return result ? JNI_TRUE : JNI_FALSE;
    159   } else {
    160     LOG(INFO) << "Result of check-stack: " << result;
    161   }
    162 #endif
    163 
    164   if (kCauseSegfault) {
    165     CauseSegfault();
    166   }
    167 
    168   return JNI_FALSE;
    169 }
    170 
    171 #if __linux__
    172 static constexpr int kSleepTimeMicroseconds = 50000;             // 0.05 seconds
    173 static constexpr int kMaxTotalSleepTimeMicroseconds = 10000000;  // 10 seconds
    174 
    175 // Wait for a sigstop. This code is copied from libbacktrace.
    176 int wait_for_sigstop(pid_t tid, int* total_sleep_time_usec, bool* detach_failed ATTRIBUTE_UNUSED) {
    177   for (;;) {
    178     int status;
    179     pid_t n = TEMP_FAILURE_RETRY(waitpid(tid, &status, __WALL | WNOHANG));
    180     if (n == -1) {
    181       PLOG(WARNING) << "waitpid failed: tid " << tid;
    182       break;
    183     } else if (n == tid) {
    184       if (WIFSTOPPED(status)) {
    185         return WSTOPSIG(status);
    186       } else {
    187         PLOG(ERROR) << "unexpected waitpid response: n=" << n << ", status=" << std::hex << status;
    188         break;
    189       }
    190     }
    191 
    192     if (*total_sleep_time_usec > kMaxTotalSleepTimeMicroseconds) {
    193       PLOG(WARNING) << "timed out waiting for stop signal: tid=" << tid;
    194       break;
    195     }
    196 
    197     usleep(kSleepTimeMicroseconds);
    198     *total_sleep_time_usec += kSleepTimeMicroseconds;
    199   }
    200 
    201   return -1;
    202 }
    203 #endif
    204 
    205 extern "C" JNIEXPORT jboolean JNICALL Java_Main_unwindOtherProcess(JNIEnv*, jclass, jint pid_int) {
    206 #if __linux__
    207   pid_t pid = static_cast<pid_t>(pid_int);
    208 
    209   // SEIZE is like ATTACH, but it does not stop the process (we let it stop itself).
    210   if (ptrace(PTRACE_SEIZE, pid, 0, 0)) {
    211     // Were not able to attach, bad.
    212     printf("Failed to attach to other process.\n");
    213     PLOG(ERROR) << "Failed to attach.";
    214     kill(pid, SIGKILL);
    215     return JNI_FALSE;
    216   }
    217 
    218   bool detach_failed = false;
    219   int total_sleep_time_usec = 0;
    220   int signal = wait_for_sigstop(pid, &total_sleep_time_usec, &detach_failed);
    221   if (signal != SIGSTOP) {
    222     LOG(WARNING) << "wait_for_sigstop failed.";
    223     return JNI_FALSE;
    224   }
    225 
    226   std::unique_ptr<Backtrace> bt(Backtrace::Create(pid, BACKTRACE_CURRENT_THREAD));
    227   bool result = true;
    228   if (!bt->Unwind(0, nullptr)) {
    229     printf("Cannot unwind other process.\n");
    230     result = false;
    231   } else if (bt->NumFrames() == 0) {
    232     printf("No frames for unwind of other process.\n");
    233     result = false;
    234   }
    235 
    236   if (result) {
    237     // See comment in unwindInProcess for non-exact stack matching.
    238     // "mini-debug-info" does not include parameters to save space.
    239     std::vector<std::string> seq = {
    240         "Java_Main_sigstop",                // The stop function in the other process.
    241         "java.util.Arrays.binarySearch0",   // Framework method.
    242         "Base.$noinline$runTest",           // Method in other dex file.
    243         "Main.main"                         // The Java entry method.
    244     };
    245 
    246     result = CheckStack(bt.get(), seq);
    247   }
    248 
    249   constexpr bool kSigQuitOnFail = true;
    250   if (!result) {
    251     MoreErrorInfo(pid, kSigQuitOnFail);
    252   }
    253 
    254   if (ptrace(PTRACE_DETACH, pid, 0, 0) != 0) {
    255     PLOG(ERROR) << "Detach failed";
    256   }
    257 
    258   // If we failed to unwind and induced an ANR dump, give the child some time (20s).
    259   if (!result && kSigQuitOnFail) {
    260     sleep(20);
    261   }
    262 
    263   // Kill the other process once we are done with it.
    264   kill(pid, SIGKILL);
    265 
    266   return result ? JNI_TRUE : JNI_FALSE;
    267 #else
    268   UNUSED(pid_int);
    269   return JNI_FALSE;
    270 #endif
    271 }
    272 
    273 }  // namespace art
    274