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. |
127 ptrace(PT_LWPINFO, lwp_id, linfo, sizeof(struct ptrace_lwpinfo)); |
127 ptrace(PT_LWPINFO, lwp_id, linfo, sizeof(struct ptrace_lwpinfo)); |
128 |
128 |
129 return (errno == 0)? true: false; |
129 return (errno == 0)? true: false; |
130 } |
130 } |
131 |
131 |
|
132 static bool ptrace_continue(pid_t pid, int signal) { |
|
133 // pass the signal to the process so we don't swallow it |
|
134 if (ptrace(PTRACE_CONT, pid, NULL, signal) < 0) { |
|
135 print_debug("ptrace(PTRACE_CONT, ..) failed for %d\n", pid); |
|
136 return false; |
|
137 } |
|
138 return true; |
|
139 } |
|
140 |
|
141 // waits until the ATTACH has stopped the process |
|
142 // by signal SIGSTOP |
|
143 static bool ptrace_waitpid(pid_t pid) { |
|
144 int ret; |
|
145 int status; |
|
146 do { |
|
147 // Wait for debuggee to stop. |
|
148 ret = waitpid(pid, &status, 0); |
|
149 if (ret >= 0) { |
|
150 if (WIFSTOPPED(status)) { |
|
151 // Any signal will stop the thread, make sure it is SIGSTOP. Otherwise SIGSTOP |
|
152 // will still be pending and delivered when the process is DETACHED and the process |
|
153 // will go to sleep. |
|
154 if (WSTOPSIG(status) == SIGSTOP) { |
|
155 // Debuggee stopped by SIGSTOP. |
|
156 return true; |
|
157 } |
|
158 if (!ptrace_continue(pid, WSTOPSIG(status))) { |
|
159 print_error("Failed to correctly attach to VM. VM might HANG! [PTRACE_CONT failed, stopped by %d]\n", WSTOPSIG(status)); |
|
160 return false; |
|
161 } |
|
162 } else { |
|
163 print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status); |
|
164 return false; |
|
165 } |
|
166 } else { |
|
167 switch (errno) { |
|
168 case EINTR: |
|
169 continue; |
|
170 break; |
|
171 case ECHILD: |
|
172 print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid); |
|
173 break; |
|
174 case EINVAL: |
|
175 print_debug("waitpid() failed. Invalid options argument.\n"); |
|
176 break; |
|
177 default: |
|
178 print_debug("waitpid() failed. Unexpected error %d\n",errno); |
|
179 } |
|
180 return false; |
|
181 } |
|
182 } while(true); |
|
183 } |
|
184 |
132 // attach to a process/thread specified by "pid" |
185 // attach to a process/thread specified by "pid" |
133 static bool ptrace_attach(pid_t pid) { |
186 static bool ptrace_attach(pid_t pid) { |
134 if (ptrace(PT_ATTACH, pid, NULL, 0) < 0) { |
187 if (ptrace(PT_ATTACH, pid, NULL, 0) < 0) { |
135 print_debug("ptrace(PTRACE_ATTACH, ..) failed for %d\n", pid); |
188 print_debug("ptrace(PTRACE_ATTACH, ..) failed for %d\n", pid); |
136 return false; |
189 return false; |
137 } else { |
190 } else { |
138 int ret; |
191 return ptrace_waitpid(pid); |
139 int status; |
|
140 do { |
|
141 // Wait for debuggee to stop. |
|
142 ret = waitpid(pid, &status, 0); |
|
143 if (ret >= 0) { |
|
144 if (WIFSTOPPED(status)) { |
|
145 // Debuggee stopped. |
|
146 return true; |
|
147 } else { |
|
148 print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status); |
|
149 return false; |
|
150 } |
|
151 } else { |
|
152 switch (errno) { |
|
153 case EINTR: |
|
154 continue; |
|
155 break; |
|
156 case ECHILD: |
|
157 print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid); |
|
158 break; |
|
159 case EINVAL: |
|
160 print_debug("waitpid() failed. Invalid options argument.\n"); |
|
161 break; |
|
162 default: |
|
163 print_debug("waitpid() failed. Unexpected error %d\n",errno); |
|
164 } |
|
165 return false; |
|
166 } |
|
167 } while(true); |
|
168 } |
192 } |
169 } |
193 } |
170 |
194 |
171 // ------------------------------------------------------- |
195 // ------------------------------------------------------- |
172 // functions for obtaining library information |
196 // functions for obtaining library information |