1 /* |
1 /* |
2 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. |
7 * published by the Free Software Foundation. |
140 return false; |
141 return false; |
141 #endif |
142 #endif |
142 |
143 |
143 } |
144 } |
144 |
145 |
|
146 static bool ptrace_continue(pid_t pid, int signal) { |
|
147 // pass the signal to the process so we don't swallow it |
|
148 if (ptrace(PTRACE_CONT, pid, NULL, signal) < 0) { |
|
149 print_debug("ptrace(PTRACE_CONT, ..) failed for %d\n", pid); |
|
150 return false; |
|
151 } |
|
152 return true; |
|
153 } |
|
154 |
|
155 // waits until the ATTACH has stopped the process |
|
156 // by signal SIGSTOP |
|
157 static bool ptrace_waitpid(pid_t pid) { |
|
158 int ret; |
|
159 int status; |
|
160 while (true) { |
|
161 // Wait for debuggee to stop. |
|
162 ret = waitpid(pid, &status, 0); |
|
163 if (ret == -1 && errno == ECHILD) { |
|
164 // try cloned process. |
|
165 ret = waitpid(pid, &status, __WALL); |
|
166 } |
|
167 if (ret >= 0) { |
|
168 if (WIFSTOPPED(status)) { |
|
169 // Any signal will stop the thread, make sure it is SIGSTOP. Otherwise SIGSTOP |
|
170 // will still be pending and delivered when the process is DETACHED and the process |
|
171 // will go to sleep. |
|
172 if (WSTOPSIG(status) == SIGSTOP) { |
|
173 // Debuggee stopped by SIGSTOP. |
|
174 return true; |
|
175 } |
|
176 if (!ptrace_continue(pid, WSTOPSIG(status))) { |
|
177 print_error("Failed to correctly attach to VM. VM might HANG! [PTRACE_CONT failed, stopped by %d]\n", WSTOPSIG(status)); |
|
178 return false; |
|
179 } |
|
180 } else { |
|
181 print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status); |
|
182 return false; |
|
183 } |
|
184 } else { |
|
185 switch (errno) { |
|
186 case EINTR: |
|
187 continue; |
|
188 break; |
|
189 case ECHILD: |
|
190 print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid); |
|
191 break; |
|
192 case EINVAL: |
|
193 print_debug("waitpid() failed. Invalid options argument.\n"); |
|
194 break; |
|
195 default: |
|
196 print_debug("waitpid() failed. Unexpected error %d\n",errno); |
|
197 break; |
|
198 } |
|
199 return false; |
|
200 } |
|
201 } |
|
202 } |
|
203 |
145 // attach to a process/thread specified by "pid" |
204 // attach to a process/thread specified by "pid" |
146 static bool ptrace_attach(pid_t pid) { |
205 static bool ptrace_attach(pid_t pid) { |
147 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) { |
206 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) { |
148 print_debug("ptrace(PTRACE_ATTACH, ..) failed for %d\n", pid); |
207 print_debug("ptrace(PTRACE_ATTACH, ..) failed for %d\n", pid); |
149 return false; |
208 return false; |
150 } else { |
209 } else { |
151 int ret; |
210 return ptrace_waitpid(pid); |
152 int status; |
|
153 do { |
|
154 // Wait for debuggee to stop. |
|
155 ret = waitpid(pid, &status, 0); |
|
156 if (ret == -1 && errno == ECHILD) { |
|
157 // try cloned process. |
|
158 ret = waitpid(pid, &status, __WALL); |
|
159 } |
|
160 if (ret >= 0) { |
|
161 if (WIFSTOPPED(status)) { |
|
162 // Debuggee stopped. |
|
163 return true; |
|
164 } else { |
|
165 print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status); |
|
166 return false; |
|
167 } |
|
168 } else { |
|
169 switch (errno) { |
|
170 case EINTR: |
|
171 continue; |
|
172 break; |
|
173 case ECHILD: |
|
174 print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid); |
|
175 break; |
|
176 case EINVAL: |
|
177 print_debug("waitpid() failed. Invalid options argument.\n"); |
|
178 break; |
|
179 default: |
|
180 print_debug("waitpid() failed. Unexpected error %d\n",errno); |
|
181 } |
|
182 return false; |
|
183 } |
|
184 } while(true); |
|
185 } |
211 } |
186 } |
212 } |
187 |
213 |
188 // ------------------------------------------------------- |
214 // ------------------------------------------------------- |
189 // functions for obtaining library information |
215 // functions for obtaining library information |