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