OLD | NEW |
1 /* Copyright (C) 2009-2012 Free Software Foundation, Inc. | 1 /* Copyright (C) 2009-2013 Free Software Foundation, Inc. |
2 | 2 |
3 This file is part of GDB. | 3 This file is part of GDB. |
4 | 4 |
5 This program is free software; you can redistribute it and/or modify | 5 This program is free software; you can redistribute it and/or modify |
6 it under the terms of the GNU General Public License as published by | 6 it under the terms of the GNU General Public License as published by |
7 the Free Software Foundation; either version 3 of the License, or | 7 the Free Software Foundation; either version 3 of the License, or |
8 (at your option) any later version. | 8 (at your option) any later version. |
9 | 9 |
10 This program is distributed in the hope that it will be useful, | 10 This program is distributed in the hope that it will be useful, |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 GNU General Public License for more details. | 13 GNU General Public License for more details. |
14 | 14 |
15 You should have received a copy of the GNU General Public License | 15 You should have received a copy of the GNU General Public License |
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ | 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
17 | 17 |
18 #include "server.h" | 18 #include "server.h" |
19 #include "target.h" | 19 #include "target.h" |
20 #include "lynx-low.h" | 20 #include "lynx-low.h" |
21 | 21 |
22 #include <limits.h> | 22 #include <limits.h> |
23 #include <sys/ptrace.h> | 23 #include <sys/ptrace.h> |
24 #include <sys/piddef.h> /* Provides PIDGET, TIDGET, BUILDPID, etc. */ | 24 #include <sys/piddef.h> /* Provides PIDGET, TIDGET, BUILDPID, etc. */ |
25 #include <unistd.h> | 25 #include <unistd.h> |
26 #include <sys/ioctl.h> | 26 #include <sys/ioctl.h> |
27 #include <sys/types.h> | 27 #include <sys/types.h> |
28 #include <sys/wait.h> | 28 #include "gdb_wait.h" |
29 #include <signal.h> | 29 #include <signal.h> |
| 30 #include "filestuff.h" |
30 | 31 |
31 int using_threads = 1; | 32 int using_threads = 1; |
32 | 33 |
| 34 const struct target_desc *lynx_tdesc; |
| 35 |
| 36 /* Per-process private data. */ |
| 37 |
| 38 struct process_info_private |
| 39 { |
| 40 /* The PTID obtained from the last wait performed on this process. |
| 41 Initialized to null_ptid until the first wait is performed. */ |
| 42 ptid_t last_wait_event_ptid; |
| 43 }; |
| 44 |
33 /* Print a debug trace on standard output if debug_threads is set. */ | 45 /* Print a debug trace on standard output if debug_threads is set. */ |
34 | 46 |
35 static void | 47 static void |
36 lynx_debug (char *string, ...) | 48 lynx_debug (char *string, ...) |
37 { | 49 { |
38 va_list args; | 50 va_list args; |
39 | 51 |
40 if (!debug_threads) | 52 if (!debug_threads) |
41 return; | 53 return; |
42 | 54 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 lynx_ptrace_pid_from_ptid (ptid_t ptid) | 101 lynx_ptrace_pid_from_ptid (ptid_t ptid) |
90 { | 102 { |
91 return BUILDPID (lynx_ptid_get_pid (ptid), lynx_ptid_get_tid (ptid)); | 103 return BUILDPID (lynx_ptid_get_pid (ptid), lynx_ptid_get_tid (ptid)); |
92 } | 104 } |
93 | 105 |
94 /* Return a string image of the ptrace REQUEST number. */ | 106 /* Return a string image of the ptrace REQUEST number. */ |
95 | 107 |
96 static char * | 108 static char * |
97 ptrace_request_to_str (int request) | 109 ptrace_request_to_str (int request) |
98 { | 110 { |
| 111 #define CASE(X) case X: return #X |
99 switch (request) | 112 switch (request) |
100 { | 113 { |
101 case PTRACE_TRACEME: | 114 CASE(PTRACE_TRACEME); |
102 return "PTRACE_TRACEME"; | 115 CASE(PTRACE_PEEKTEXT); |
103 break; | 116 CASE(PTRACE_PEEKDATA); |
104 case PTRACE_PEEKTEXT: | 117 CASE(PTRACE_PEEKUSER); |
105 return "PTRACE_PEEKTEXT"; | 118 CASE(PTRACE_POKETEXT); |
106 break; | 119 CASE(PTRACE_POKEDATA); |
107 case PTRACE_PEEKDATA: | 120 CASE(PTRACE_POKEUSER); |
108 return "PTRACE_PEEKDATA"; | 121 CASE(PTRACE_CONT); |
109 break; | 122 CASE(PTRACE_KILL); |
110 case PTRACE_PEEKUSER: | 123 CASE(PTRACE_SINGLESTEP); |
111 return "PTRACE_PEEKUSER"; | 124 CASE(PTRACE_ATTACH); |
112 break; | 125 CASE(PTRACE_DETACH); |
113 case PTRACE_POKETEXT: | 126 CASE(PTRACE_GETREGS); |
114 return "PTRACE_POKETEXT"; | 127 CASE(PTRACE_SETREGS); |
115 break; | 128 CASE(PTRACE_GETFPREGS); |
116 case PTRACE_POKEDATA: | 129 CASE(PTRACE_SETFPREGS); |
117 return "PTRACE_POKEDATA"; | 130 CASE(PTRACE_READDATA); |
118 break; | 131 CASE(PTRACE_WRITEDATA); |
119 case PTRACE_POKEUSER: | 132 CASE(PTRACE_READTEXT); |
120 return "PTRACE_POKEUSER"; | 133 CASE(PTRACE_WRITETEXT); |
121 break; | 134 CASE(PTRACE_GETFPAREGS); |
122 case PTRACE_CONT: | 135 CASE(PTRACE_SETFPAREGS); |
123 return "PTRACE_CONT"; | 136 CASE(PTRACE_GETWINDOW); |
124 break; | 137 CASE(PTRACE_SETWINDOW); |
125 case PTRACE_KILL: | 138 CASE(PTRACE_SYSCALL); |
126 return "PTRACE_KILL"; | 139 CASE(PTRACE_DUMPCORE); |
127 break; | 140 CASE(PTRACE_SETWRBKPT); |
128 case PTRACE_SINGLESTEP: | 141 CASE(PTRACE_SETACBKPT); |
129 return "PTRACE_SINGLESTEP"; | 142 CASE(PTRACE_CLRBKPT); |
130 break; | 143 CASE(PTRACE_GET_UCODE); |
131 case PTRACE_ATTACH: | |
132 return "PTRACE_ATTACH"; | |
133 break; | |
134 case PTRACE_DETACH: | |
135 return "PTRACE_DETACH"; | |
136 break; | |
137 case PTRACE_GETREGS: | |
138 return "PTRACE_GETREGS"; | |
139 break; | |
140 case PTRACE_SETREGS: | |
141 return "PTRACE_SETREGS"; | |
142 break; | |
143 case PTRACE_GETFPREGS: | |
144 return "PTRACE_GETFPREGS"; | |
145 break; | |
146 case PTRACE_SETFPREGS: | |
147 return "PTRACE_SETFPREGS"; | |
148 break; | |
149 case PTRACE_READDATA: | |
150 return "PTRACE_READDATA"; | |
151 break; | |
152 case PTRACE_WRITEDATA: | |
153 return "PTRACE_WRITEDATA"; | |
154 break; | |
155 case PTRACE_READTEXT: | |
156 return "PTRACE_READTEXT"; | |
157 break; | |
158 case PTRACE_WRITETEXT: | |
159 return "PTRACE_WRITETEXT"; | |
160 break; | |
161 case PTRACE_GETFPAREGS: | |
162 return "PTRACE_GETFPAREGS"; | |
163 break; | |
164 case PTRACE_SETFPAREGS: | |
165 return "PTRACE_SETFPAREGS"; | |
166 break; | |
167 case PTRACE_GETWINDOW: | |
168 return "PTRACE_GETWINDOW"; | |
169 break; | |
170 case PTRACE_SETWINDOW: | |
171 return "PTRACE_SETWINDOW"; | |
172 break; | |
173 case PTRACE_SYSCALL: | |
174 return "PTRACE_SYSCALL"; | |
175 break; | |
176 case PTRACE_DUMPCORE: | |
177 return "PTRACE_DUMPCORE"; | |
178 break; | |
179 case PTRACE_SETWRBKPT: | |
180 return "PTRACE_SETWRBKPT"; | |
181 break; | |
182 case PTRACE_SETACBKPT: | |
183 return "PTRACE_SETACBKPT"; | |
184 break; | |
185 case PTRACE_CLRBKPT: | |
186 return "PTRACE_CLRBKPT"; | |
187 break; | |
188 case PTRACE_GET_UCODE: | |
189 return "PTRACE_GET_UCODE"; | |
190 break; | |
191 #ifdef PT_READ_GPR | 144 #ifdef PT_READ_GPR |
192 case PT_READ_GPR: | 145 CASE(PT_READ_GPR); |
193 return "PT_READ_GPR"; | |
194 break; | |
195 #endif | 146 #endif |
196 #ifdef PT_WRITE_GPR | 147 #ifdef PT_WRITE_GPR |
197 case PT_WRITE_GPR: | 148 CASE(PT_WRITE_GPR); |
198 return "PT_WRITE_GPR"; | |
199 break; | |
200 #endif | 149 #endif |
201 #ifdef PT_READ_FPR | 150 #ifdef PT_READ_FPR |
202 case PT_READ_FPR: | 151 CASE(PT_READ_FPR); |
203 return "PT_READ_FPR"; | |
204 break; | |
205 #endif | 152 #endif |
206 #ifdef PT_WRITE_FPR | 153 #ifdef PT_WRITE_FPR |
207 case PT_WRITE_FPR: | 154 CASE(PT_WRITE_FPR); |
208 return "PT_WRITE_FPR"; | |
209 break; | |
210 #endif | 155 #endif |
211 #ifdef PT_READ_VPR | 156 #ifdef PT_READ_VPR |
212 case PT_READ_VPR: | 157 CASE(PT_READ_VPR); |
213 return "PT_READ_VPR"; | |
214 break; | |
215 #endif | 158 #endif |
216 #ifdef PT_WRITE_VPR | 159 #ifdef PT_WRITE_VPR |
217 case PT_WRITE_VPR: | 160 CASE(PT_WRITE_VPR); |
218 return "PT_WRITE_VPR"; | |
219 break; | |
220 #endif | 161 #endif |
221 #ifdef PTRACE_PEEKUSP | 162 #ifdef PTRACE_PEEKUSP |
222 case PTRACE_PEEKUSP: | 163 CASE(PTRACE_PEEKUSP); |
223 return "PTRACE_PEEKUSP"; | |
224 break; | |
225 #endif | 164 #endif |
226 #ifdef PTRACE_POKEUSP | 165 #ifdef PTRACE_POKEUSP |
227 case PTRACE_POKEUSP: | 166 CASE(PTRACE_POKEUSP); |
228 return "PTRACE_POKEUSP"; | |
229 break; | |
230 #endif | 167 #endif |
231 case PTRACE_PEEKTHREAD: | 168 CASE(PTRACE_PEEKTHREAD); |
232 return "PTRACE_PEEKTHREAD"; | 169 CASE(PTRACE_THREADUSER); |
233 break; | 170 CASE(PTRACE_FPREAD); |
234 case PTRACE_THREADUSER: | 171 CASE(PTRACE_FPWRITE); |
235 return "PTRACE_THREADUSER"; | 172 CASE(PTRACE_SETSIG); |
236 break; | 173 CASE(PTRACE_CONT_ONE); |
237 case PTRACE_FPREAD: | 174 CASE(PTRACE_KILL_ONE); |
238 return "PTRACE_FPREAD"; | 175 CASE(PTRACE_SINGLESTEP_ONE); |
239 break; | 176 CASE(PTRACE_GETLOADINFO); |
240 case PTRACE_FPWRITE: | 177 CASE(PTRACE_GETTRACESIG); |
241 return "PTRACE_FPWRITE"; | 178 #ifdef PTRACE_GETTHREADLIST |
242 break; | 179 CASE(PTRACE_GETTHREADLIST); |
243 case PTRACE_SETSIG: | 180 #endif |
244 return "PTRACE_SETSIG"; | |
245 break; | |
246 case PTRACE_CONT_ONE: | |
247 return "PTRACE_CONT_ONE"; | |
248 break; | |
249 case PTRACE_KILL_ONE: | |
250 return "PTRACE_KILL_ONE"; | |
251 break; | |
252 case PTRACE_SINGLESTEP_ONE: | |
253 return "PTRACE_SINGLESTEP_ONE"; | |
254 break; | |
255 case PTRACE_GETLOADINFO: | |
256 return "PTRACE_GETLOADINFO"; | |
257 break; | |
258 case PTRACE_GETTHREADLIST: | |
259 return "PTRACE_GETTHREADLIST"; | |
260 break; | |
261 } | 181 } |
| 182 #undef CASE |
| 183 |
262 return "<unknown-request>"; | 184 return "<unknown-request>"; |
263 } | 185 } |
264 | 186 |
265 /* A wrapper around ptrace that allows us to print debug traces of | 187 /* A wrapper around ptrace that allows us to print debug traces of |
266 ptrace calls if debug traces are activated. */ | 188 ptrace calls if debug traces are activated. */ |
267 | 189 |
268 static int | 190 static int |
269 lynx_ptrace (int request, ptid_t ptid, int addr, int data, int addr2) | 191 lynx_ptrace (int request, ptid_t ptid, int addr, int data, int addr2) |
270 { | 192 { |
271 int result; | 193 int result; |
272 const int pid = lynx_ptrace_pid_from_ptid (ptid); | 194 const int pid = lynx_ptrace_pid_from_ptid (ptid); |
273 int saved_errno; | 195 int saved_errno; |
274 | 196 |
275 if (debug_threads) | 197 if (debug_threads) |
276 fprintf (stderr, "PTRACE (%s, pid=%d(pid=%d, tid=%d), addr=0x%x, " | 198 fprintf (stderr, "PTRACE (%s, pid=%d(pid=%d, tid=%d), addr=0x%x, " |
277 "data=0x%x, addr2=0x%x)", | 199 "data=0x%x, addr2=0x%x)", |
278 ptrace_request_to_str (request), pid, PIDGET (pid), TIDGET (pid), | 200 ptrace_request_to_str (request), pid, PIDGET (pid), TIDGET (pid), |
279 addr, data, addr2); | 201 addr, data, addr2); |
280 result = ptrace (request, pid, addr, data, addr2); | 202 result = ptrace (request, pid, addr, data, addr2); |
281 saved_errno = errno; | 203 saved_errno = errno; |
282 if (debug_threads) | 204 if (debug_threads) |
283 fprintf (stderr, " -> %d (=0x%x)\n", result, result); | 205 fprintf (stderr, " -> %d (=0x%x)\n", result, result); |
284 | 206 |
285 errno = saved_errno; | 207 errno = saved_errno; |
286 return result; | 208 return result; |
287 } | 209 } |
288 | 210 |
| 211 /* Call add_process with the given parameters, and initializes |
| 212 the process' private data. */ |
| 213 |
| 214 static struct process_info * |
| 215 lynx_add_process (int pid, int attached) |
| 216 { |
| 217 struct process_info *proc; |
| 218 |
| 219 proc = add_process (pid, attached); |
| 220 proc->tdesc = lynx_tdesc; |
| 221 proc->private = xcalloc (1, sizeof (*proc->private)); |
| 222 proc->private->last_wait_event_ptid = null_ptid; |
| 223 |
| 224 return proc; |
| 225 } |
| 226 |
289 /* Implement the create_inferior method of the target_ops vector. */ | 227 /* Implement the create_inferior method of the target_ops vector. */ |
290 | 228 |
291 static int | 229 static int |
292 lynx_create_inferior (char *program, char **allargs) | 230 lynx_create_inferior (char *program, char **allargs) |
293 { | 231 { |
294 struct process_info *new_process; | |
295 int pid; | 232 int pid; |
296 | 233 |
297 lynx_debug ("lynx_create_inferior ()"); | 234 lynx_debug ("lynx_create_inferior ()"); |
298 | 235 |
299 pid = fork (); | 236 pid = fork (); |
300 if (pid < 0) | 237 if (pid < 0) |
301 perror_with_name ("fork"); | 238 perror_with_name ("fork"); |
302 | 239 |
303 if (pid == 0) | 240 if (pid == 0) |
304 { | 241 { |
305 int pgrp; | 242 int pgrp; |
306 | 243 |
| 244 close_most_fds (); |
| 245 |
307 /* Switch child to its own process group so that signals won't | 246 /* Switch child to its own process group so that signals won't |
308 directly affect gdbserver. */ | 247 directly affect gdbserver. */ |
309 pgrp = getpid(); | 248 pgrp = getpid(); |
310 setpgid (0, pgrp); | 249 setpgid (0, pgrp); |
311 ioctl (0, TIOCSPGRP, &pgrp); | 250 ioctl (0, TIOCSPGRP, &pgrp); |
312 lynx_ptrace (PTRACE_TRACEME, null_ptid, 0, 0, 0); | 251 lynx_ptrace (PTRACE_TRACEME, null_ptid, 0, 0, 0); |
313 execv (program, allargs); | 252 execv (program, allargs); |
314 fprintf (stderr, "Cannot exec %s: %s.\n", program, strerror (errno)); | 253 fprintf (stderr, "Cannot exec %s: %s.\n", program, strerror (errno)); |
315 fflush (stderr); | 254 fflush (stderr); |
316 _exit (0177); | 255 _exit (0177); |
317 } | 256 } |
318 | 257 |
319 new_process = add_process (pid, 0); | 258 lynx_add_process (pid, 0); |
320 /* Do not add the process thread just yet, as we do not know its tid. | 259 /* Do not add the process thread just yet, as we do not know its tid. |
321 We will add it later, during the wait for the STOP event corresponding | 260 We will add it later, during the wait for the STOP event corresponding |
322 to the lynx_ptrace (PTRACE_TRACEME) call above. */ | 261 to the lynx_ptrace (PTRACE_TRACEME) call above. */ |
323 return pid; | 262 return pid; |
324 } | 263 } |
325 | 264 |
| 265 /* Assuming we've just attached to a running inferior whose pid is PID, |
| 266 add all threads running in that process. */ |
| 267 |
| 268 static void |
| 269 lynx_add_threads_after_attach (int pid) |
| 270 { |
| 271 /* Ugh! There appears to be no way to get the list of threads |
| 272 in the program we just attached to. So get the list by calling |
| 273 the "ps" command. This is only needed now, as we will then |
| 274 keep the thread list up to date thanks to thread creation and |
| 275 exit notifications. */ |
| 276 FILE *f; |
| 277 char buf[256]; |
| 278 int thread_pid, thread_tid; |
| 279 |
| 280 f = popen ("ps atx", "r"); |
| 281 if (f == NULL) |
| 282 perror_with_name ("Cannot get thread list"); |
| 283 |
| 284 while (fgets (buf, sizeof (buf), f) != NULL) |
| 285 if ((sscanf (buf, "%d %d", &thread_pid, &thread_tid) == 2 |
| 286 && thread_pid == pid)) |
| 287 { |
| 288 ptid_t thread_ptid = lynx_ptid_build (pid, thread_tid); |
| 289 |
| 290 if (!find_thread_ptid (thread_ptid)) |
| 291 { |
| 292 lynx_debug ("New thread: (pid = %d, tid = %d)", |
| 293 pid, thread_tid); |
| 294 add_thread (thread_ptid, NULL); |
| 295 } |
| 296 } |
| 297 |
| 298 pclose (f); |
| 299 } |
| 300 |
326 /* Implement the attach target_ops method. */ | 301 /* Implement the attach target_ops method. */ |
327 | 302 |
328 static int | 303 static int |
329 lynx_attach (unsigned long pid) | 304 lynx_attach (unsigned long pid) |
330 { | 305 { |
331 struct process_info *new_process; | |
332 ptid_t ptid = lynx_ptid_build (pid, 0); | 306 ptid_t ptid = lynx_ptid_build (pid, 0); |
333 | 307 |
334 if (lynx_ptrace (PTRACE_ATTACH, ptid, 0, 0, 0) != 0) | 308 if (lynx_ptrace (PTRACE_ATTACH, ptid, 0, 0, 0) != 0) |
335 error ("Cannot attach to process %lu: %s (%d)\n", pid, | 309 error ("Cannot attach to process %lu: %s (%d)\n", pid, |
336 strerror (errno), errno); | 310 strerror (errno), errno); |
337 | 311 |
338 new_process = add_process (pid, 1); | 312 lynx_add_process (pid, 1); |
339 add_thread (ptid, NULL); | 313 lynx_add_threads_after_attach (pid); |
340 | 314 |
341 return 0; | 315 return 0; |
342 } | 316 } |
343 | 317 |
344 /* Implement the resume target_ops method. */ | 318 /* Implement the resume target_ops method. */ |
345 | 319 |
346 static void | 320 static void |
347 lynx_resume (struct thread_resume *resume_info, size_t n) | 321 lynx_resume (struct thread_resume *resume_info, size_t n) |
348 { | 322 { |
349 ptid_t inferior_ptid = thread_to_gdb_id (current_inferior); | |
350 /* FIXME: Assume for now that n == 1. */ | 323 /* FIXME: Assume for now that n == 1. */ |
| 324 ptid_t ptid = resume_info[0].thread; |
351 const int request = (resume_info[0].kind == resume_step | 325 const int request = (resume_info[0].kind == resume_step |
352 ? PTRACE_SINGLESTEP : PTRACE_CONT); | 326 ? PTRACE_SINGLESTEP : PTRACE_CONT); |
353 const int signal = resume_info[0].sig; | 327 const int signal = resume_info[0].sig; |
354 int ret; | 328 |
| 329 /* If given a minus_one_ptid, then try using the current_process' |
| 330 private->last_wait_event_ptid. On most LynxOS versions, |
| 331 using any of the process' thread works well enough, but |
| 332 LynxOS 178 is a little more sensitive, and triggers some |
| 333 unexpected signals (Eg SIG61) when we resume the inferior |
| 334 using a different thread. */ |
| 335 if (ptid_equal (ptid, minus_one_ptid)) |
| 336 ptid = current_process()->private->last_wait_event_ptid; |
| 337 |
| 338 /* The ptid might still be minus_one_ptid; this can happen between |
| 339 the moment we create the inferior or attach to a process, and |
| 340 the moment we resume its execution for the first time. It is |
| 341 fine to use the current_inferior's ptid in those cases. */ |
| 342 if (ptid_equal (ptid, minus_one_ptid)) |
| 343 ptid = thread_to_gdb_id (current_inferior); |
355 | 344 |
356 regcache_invalidate (); | 345 regcache_invalidate (); |
357 ret = lynx_ptrace (request, inferior_ptid, 1, signal, 0); | 346 |
| 347 errno = 0; |
| 348 lynx_ptrace (request, ptid, 1, signal, 0); |
| 349 if (errno) |
| 350 perror_with_name ("ptrace"); |
358 } | 351 } |
359 | 352 |
360 /* Resume the execution of the given PTID. */ | 353 /* Resume the execution of the given PTID. */ |
361 | 354 |
362 static void | 355 static void |
363 lynx_continue (ptid_t ptid) | 356 lynx_continue (ptid_t ptid) |
364 { | 357 { |
365 struct thread_resume resume_info; | 358 struct thread_resume resume_info; |
366 | 359 |
367 resume_info.thread = ptid; | 360 resume_info.thread = ptid; |
368 resume_info.kind = resume_continue; | 361 resume_info.kind = resume_continue; |
369 resume_info.sig = 0; | 362 resume_info.sig = 0; |
370 | 363 |
371 lynx_resume (&resume_info, 1); | 364 lynx_resume (&resume_info, 1); |
372 } | 365 } |
373 | 366 |
374 /* Remove all inferiors and associated threads. */ | |
375 | |
376 static void | |
377 lynx_clear_inferiors (void) | |
378 { | |
379 /* We do not use private data, so nothing much to do except calling | |
380 clear_inferiors. */ | |
381 clear_inferiors (); | |
382 } | |
383 | |
384 /* A wrapper around waitpid that handles the various idiosyncrasies | 367 /* A wrapper around waitpid that handles the various idiosyncrasies |
385 of LynxOS' waitpid. */ | 368 of LynxOS' waitpid. */ |
386 | 369 |
387 static int | 370 static int |
388 lynx_waitpid (int pid, int *stat_loc) | 371 lynx_waitpid (int pid, int *stat_loc) |
389 { | 372 { |
390 int ret = 0; | 373 int ret = 0; |
391 | 374 |
392 while (1) | 375 while (1) |
393 { | 376 { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
431 | 414 |
432 if (ptid_equal (ptid, minus_one_ptid)) | 415 if (ptid_equal (ptid, minus_one_ptid)) |
433 pid = lynx_ptid_get_pid (thread_to_gdb_id (current_inferior)); | 416 pid = lynx_ptid_get_pid (thread_to_gdb_id (current_inferior)); |
434 else | 417 else |
435 pid = BUILDPID (lynx_ptid_get_pid (ptid), lynx_ptid_get_tid (ptid)); | 418 pid = BUILDPID (lynx_ptid_get_pid (ptid), lynx_ptid_get_tid (ptid)); |
436 | 419 |
437 retry: | 420 retry: |
438 | 421 |
439 ret = lynx_waitpid (pid, &wstat); | 422 ret = lynx_waitpid (pid, &wstat); |
440 new_ptid = lynx_ptid_build (ret, ((union wait *) &wstat)->w_tid); | 423 new_ptid = lynx_ptid_build (ret, ((union wait *) &wstat)->w_tid); |
| 424 find_process_pid (ret)->private->last_wait_event_ptid = new_ptid; |
441 | 425 |
442 /* If this is a new thread, then add it now. The reason why we do | 426 /* If this is a new thread, then add it now. The reason why we do |
443 this here instead of when handling new-thread events is because | 427 this here instead of when handling new-thread events is because |
444 we need to add the thread associated to the "main" thread - even | 428 we need to add the thread associated to the "main" thread - even |
445 for non-threaded applications where the new-thread events are not | 429 for non-threaded applications where the new-thread events are not |
446 generated. */ | 430 generated. */ |
447 if (!find_thread_ptid (new_ptid)) | 431 if (!find_thread_ptid (new_ptid)) |
448 add_thread (new_ptid, NULL); | 432 { |
| 433 lynx_debug ("New thread: (pid = %d, tid = %d)", |
| 434 » » lynx_ptid_get_pid (new_ptid), lynx_ptid_get_tid (new_ptid)); |
| 435 add_thread (new_ptid, NULL); |
| 436 } |
449 | 437 |
450 if (WIFSTOPPED (wstat)) | 438 if (WIFSTOPPED (wstat)) |
451 { | 439 { |
452 status->kind = TARGET_WAITKIND_STOPPED; | 440 status->kind = TARGET_WAITKIND_STOPPED; |
453 status->value.integer = gdb_signal_from_host (WSTOPSIG (wstat)); | 441 status->value.integer = gdb_signal_from_host (WSTOPSIG (wstat)); |
454 lynx_debug ("process stopped with signal: %d", | 442 lynx_debug ("process stopped with signal: %d", |
455 status->value.integer); | 443 status->value.integer); |
456 } | 444 } |
457 else if (WIFEXITED (wstat)) | 445 else if (WIFEXITED (wstat)) |
458 { | 446 { |
(...skipping 25 matching lines...) Expand all Loading... |
484 && status->value.integer == GDB_SIGNAL_TRAP) | 472 && status->value.integer == GDB_SIGNAL_TRAP) |
485 { | 473 { |
486 const int realsig = lynx_ptrace (PTRACE_GETTRACESIG, new_ptid, 0, 0, 0); | 474 const int realsig = lynx_ptrace (PTRACE_GETTRACESIG, new_ptid, 0, 0, 0); |
487 | 475 |
488 lynx_debug ("(realsig = %d)", realsig); | 476 lynx_debug ("(realsig = %d)", realsig); |
489 switch (realsig) | 477 switch (realsig) |
490 { | 478 { |
491 case SIGNEWTHREAD: | 479 case SIGNEWTHREAD: |
492 /* We just added the new thread above. No need to do anything | 480 /* We just added the new thread above. No need to do anything |
493 further. Just resume the execution again. */ | 481 further. Just resume the execution again. */ |
494 » lynx_continue (ptid); | 482 » lynx_continue (new_ptid); |
495 goto retry; | 483 goto retry; |
496 | 484 |
497 case SIGTHREADEXIT: | 485 case SIGTHREADEXIT: |
498 remove_thread (find_thread_ptid (new_ptid)); | 486 remove_thread (find_thread_ptid (new_ptid)); |
499 » lynx_continue (ptid); | 487 » lynx_continue (new_ptid); |
500 goto retry; | 488 goto retry; |
501 } | 489 } |
502 } | 490 } |
503 | 491 |
504 return new_ptid; | 492 return new_ptid; |
505 } | 493 } |
506 | 494 |
507 /* A wrapper around lynx_wait_1 that also prints debug traces when | 495 /* A wrapper around lynx_wait_1 that also prints debug traces when |
508 such debug traces have been activated. */ | 496 such debug traces have been activated. */ |
509 | 497 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
555 lynx_ptrace (PTRACE_DETACH, ptid, 0, 0, 0); | 543 lynx_ptrace (PTRACE_DETACH, ptid, 0, 0, 0); |
556 the_target->mourn (process); | 544 the_target->mourn (process); |
557 return 0; | 545 return 0; |
558 } | 546 } |
559 | 547 |
560 /* Implement the mourn target_ops method. */ | 548 /* Implement the mourn target_ops method. */ |
561 | 549 |
562 static void | 550 static void |
563 lynx_mourn (struct process_info *proc) | 551 lynx_mourn (struct process_info *proc) |
564 { | 552 { |
565 lynx_clear_inferiors (); | 553 /* Free our private data. */ |
| 554 free (proc->private); |
| 555 proc->private = NULL; |
| 556 |
| 557 clear_inferiors (); |
566 } | 558 } |
567 | 559 |
568 /* Implement the join target_ops method. */ | 560 /* Implement the join target_ops method. */ |
569 | 561 |
570 static void | 562 static void |
571 lynx_join (int pid) | 563 lynx_join (int pid) |
572 { | 564 { |
573 /* The PTRACE_DETACH is sufficient to detach from the process. | 565 /* The PTRACE_DETACH is sufficient to detach from the process. |
574 So no need to do anything extra. */ | 566 So no need to do anything extra. */ |
575 } | 567 } |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
761 NULL, /* handle_monitor_command */ | 753 NULL, /* handle_monitor_command */ |
762 }; | 754 }; |
763 | 755 |
764 void | 756 void |
765 initialize_low (void) | 757 initialize_low (void) |
766 { | 758 { |
767 set_target_ops (&lynx_target_ops); | 759 set_target_ops (&lynx_target_ops); |
768 the_low_target.arch_setup (); | 760 the_low_target.arch_setup (); |
769 } | 761 } |
770 | 762 |
OLD | NEW |