Added
Link Here
|
1 |
/* Native-dependent code for FreeBSD. |
2 |
|
3 |
Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. |
4 |
|
5 |
This file is part of GDB. |
6 |
|
7 |
This program is free software; you can redistribute it and/or modify |
8 |
it under the terms of the GNU General Public License as published by |
9 |
the Free Software Foundation; either version 2 of the License, or |
10 |
(at your option) any later version. |
11 |
|
12 |
This program is distributed in the hope that it will be useful, |
13 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 |
GNU General Public License for more details. |
16 |
|
17 |
You should have received a copy of the GNU General Public License |
18 |
along with this program; if not, write to the Free Software |
19 |
Foundation, Inc., 51 Franklin Street, Fifth Floor, |
20 |
Boston, MA 02110-1301, USA. */ |
21 |
|
22 |
#include "defs.h" |
23 |
#include "inferior.h" |
24 |
#include "symfile.h" |
25 |
#include "gdbcore.h" |
26 |
#include "gdbthread.h" |
27 |
#include "gdb_assert.h" |
28 |
#include <sys/types.h> |
29 |
#include <sys/ptrace.h> |
30 |
#include <sys/wait.h> |
31 |
|
32 |
extern struct target_ops child_ops; |
33 |
void clear_step_resume_breakpoint (void); |
34 |
void clear_step_resume_breakpoint_thread (void); |
35 |
void (*reactivate_threads) (char*) = NULL; |
36 |
void (*disable_threads) (void) = NULL; |
37 |
|
38 |
static void (*mourn_inferior_beneath) (void); |
39 |
static void (*detach_beneath) (char *args, int from_tty); |
40 |
static ptid_t (*wait_beneath) (ptid_t ptid, |
41 |
struct target_waitstatus *ourstatus); |
42 |
int follow_event_pid = 0; |
43 |
|
44 |
/* Return a the name of file that can be opened to get the symbols for |
45 |
the child process identified by PID. */ |
46 |
|
47 |
char * |
48 |
fbsd_pid_to_exec_file (int pid) |
49 |
{ |
50 |
size_t len = MAXPATHLEN; |
51 |
char *buf = xcalloc (len, sizeof (char)); |
52 |
char *path; |
53 |
|
54 |
#ifdef KERN_PROC_PATHNAME |
55 |
int mib[4]; |
56 |
|
57 |
mib[0] = CTL_KERN; |
58 |
mib[1] = KERN_PROC; |
59 |
mib[2] = KERN_PROC_PATHNAME; |
60 |
mib[3] = pid; |
61 |
if (sysctl (mib, 4, buf, &len, NULL, 0) == 0) |
62 |
return buf; |
63 |
#endif |
64 |
|
65 |
path = xstrprintf ("/proc/%d/file", pid); |
66 |
if (readlink (path, buf, MAXPATHLEN) == -1) |
67 |
{ |
68 |
xfree (buf); |
69 |
buf = NULL; |
70 |
} |
71 |
|
72 |
xfree (path); |
73 |
return buf; |
74 |
} |
75 |
|
76 |
/* Wait for the child specified by PTID to do something. Return the |
77 |
process ID of the child, or MINUS_ONE_PTID in case of error; store |
78 |
the status in *OURSTATUS. */ |
79 |
|
80 |
static ptid_t |
81 |
inf_ptrace_wait (ptid_t ptid, struct target_waitstatus *ourstatus) |
82 |
{ |
83 |
pid_t pid; |
84 |
int status, save_errno; |
85 |
|
86 |
do |
87 |
{ |
88 |
set_sigint_trap (); |
89 |
set_sigio_trap (); |
90 |
do |
91 |
{ |
92 |
pid = waitpid (PIDGET (ptid), &status, 0); |
93 |
save_errno = errno; |
94 |
} |
95 |
while (pid == -1 && errno == EINTR); |
96 |
|
97 |
clear_sigio_trap (); |
98 |
clear_sigint_trap (); |
99 |
|
100 |
if (pid == -1) |
101 |
{ |
102 |
fprintf_unfiltered (gdb_stderr, |
103 |
_("Child process unexpectedly missing: %s.\n"), |
104 |
safe_strerror (save_errno)); |
105 |
|
106 |
/* Claim it exited with unknown signal. */ |
107 |
ourstatus->kind = TARGET_WAITKIND_SIGNALLED; |
108 |
ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN; |
109 |
return minus_one_ptid; |
110 |
} |
111 |
|
112 |
/* Ignore terminated detached child processes. */ |
113 |
if (!WIFSTOPPED (status) && pid != PIDGET (inferior_ptid)) |
114 |
pid = -1; |
115 |
} |
116 |
while (pid == -1); |
117 |
|
118 |
store_waitstatus (ourstatus, status); |
119 |
return pid_to_ptid (pid); |
120 |
} |
121 |
|
122 |
static ptid_t |
123 |
fbsd_wait (ptid_t ptid, struct target_waitstatus *ourstatus) |
124 |
{ |
125 |
long lwp; |
126 |
struct ptrace_lwpinfo lwpinfo; |
127 |
struct target_waitstatus stat; |
128 |
ptid_t ret; |
129 |
static ptid_t forking_child = {0,0,0}; |
130 |
|
131 |
ret = wait_beneath (ptid, ourstatus); |
132 |
|
133 |
if (PIDGET (ret) >= 0 && ourstatus->kind == TARGET_WAITKIND_STOPPED && |
134 |
(ourstatus->value.sig == TARGET_SIGNAL_TRAP || |
135 |
ourstatus->value.sig == TARGET_SIGNAL_STOP) && |
136 |
(ptrace(PT_LWPINFO, PIDGET (ret), (caddr_t)&lwpinfo, |
137 |
sizeof lwpinfo) == 0)) |
138 |
{ |
139 |
if (lwpinfo.pl_flags & PL_FLAG_CHILD) |
140 |
{ |
141 |
/* Leave the child in a stopped state until we get a fork event in |
142 |
the parent. That's when we decide which process to follow. */ |
143 |
ourstatus->kind = TARGET_WAITKIND_IGNORE; |
144 |
forking_child = ret; |
145 |
} |
146 |
else if (lwpinfo.pl_flags & PL_FLAG_FORKED) |
147 |
{ |
148 |
/* We'd better be in the middle of processing a fork() event. */ |
149 |
gdb_assert (!ptid_equal (forking_child, null_ptid)); |
150 |
ourstatus->kind = TARGET_WAITKIND_FORKED; |
151 |
ourstatus->value.related_pid = lwpinfo.pl_child_pid; |
152 |
forking_child = null_ptid; |
153 |
} |
154 |
else if (lwpinfo.pl_flags & PL_FLAG_EXEC && |
155 |
PIDGET (ret) == follow_event_pid) |
156 |
{ |
157 |
ourstatus->kind = TARGET_WAITKIND_EXECD; |
158 |
ourstatus->value.execd_pathname = |
159 |
xstrdup (fbsd_pid_to_exec_file (PIDGET (ret))); |
160 |
} |
161 |
} |
162 |
|
163 |
return ret; |
164 |
} |
165 |
|
166 |
static void |
167 |
fbsd_enable_event_reporting (int pid) |
168 |
{ |
169 |
#ifdef PT_FOLLOW_FORK |
170 |
follow_event_pid = pid; |
171 |
if (ptrace(PT_FOLLOW_FORK, pid, 0, 1) < 0) |
172 |
error (_("Cannot follow fork on this target.")); |
173 |
#endif |
174 |
} |
175 |
|
176 |
static void |
177 |
fbsd_post_attach (int pid) |
178 |
{ |
179 |
fbsd_enable_event_reporting (pid); |
180 |
} |
181 |
|
182 |
static void |
183 |
fbsd_post_startup_inferior (ptid_t ptid) |
184 |
{ |
185 |
fbsd_enable_event_reporting (PIDGET (ptid)); |
186 |
} |
187 |
|
188 |
int |
189 |
fbsd_follow_fork (struct target_ops *ops, int follow_child) |
190 |
{ |
191 |
ptid_t last_ptid, ret, child_ptid; |
192 |
struct target_waitstatus last_status; |
193 |
int parent_pid, child_pid; |
194 |
struct target_waitstatus ourstatus; |
195 |
|
196 |
get_last_target_status (&last_ptid, &last_status); |
197 |
parent_pid = PIDGET (last_ptid); |
198 |
child_pid = last_status.value.related_pid; |
199 |
|
200 |
if (follow_child) |
201 |
{ |
202 |
detach_breakpoints (child_pid); |
203 |
remove_breakpoints (); |
204 |
child_ptid = pid_to_ptid (child_pid); |
205 |
|
206 |
target_detach (NULL, 0); |
207 |
inferior_ptid = child_ptid; |
208 |
|
209 |
/* Reinstall ourselves, since we might have been removed in |
210 |
target_detach (which does other necessary cleanup). */ |
211 |
push_target (ops); |
212 |
|
213 |
/* Need to restore some of the actions done by the threaded detach */ |
214 |
if (reactivate_threads) |
215 |
{ |
216 |
reactivate_threads (fbsd_pid_to_exec_file (child_pid)); |
217 |
reactivate_threads = NULL; |
218 |
} |
219 |
|
220 |
/* Reset breakpoints in the child as appropriate. */ |
221 |
clear_step_resume_breakpoint_thread (); |
222 |
follow_inferior_reset_breakpoints (); |
223 |
|
224 |
/* Enable fork/exec event reporting for the child. */ |
225 |
fbsd_enable_event_reporting (child_pid); |
226 |
} |
227 |
else /* Follow parent */ |
228 |
{ |
229 |
/* Before detaching from the child, remove all breakpoints from |
230 |
it. (This won't actually modify the breakpoint list, but will |
231 |
physically remove the breakpoints from the child.) */ |
232 |
detach_breakpoints (child_pid); |
233 |
ptrace (PT_DETACH, child_pid, (caddr_t) 1, 0); |
234 |
} |
235 |
|
236 |
return 0; |
237 |
} |
238 |
|
239 |
/* EXECD_PATHNAME is assumed to be non-NULL. */ |
240 |
|
241 |
static void |
242 |
fbsd_follow_exec (int pid, char *execd_pathname) |
243 |
{ |
244 |
struct target_waitstatus status; |
245 |
ptid_t ret = inferior_ptid; |
246 |
|
247 |
/* This is an exec event that we actually wish to pay attention to. |
248 |
Refresh our symbol table to the newly exec'd program, remove any |
249 |
momentary bp's, etc. |
250 |
|
251 |
If there are breakpoints, they aren't really inserted now, |
252 |
since the exec() transformed our inferior into a fresh set |
253 |
of instructions. |
254 |
|
255 |
We want to preserve symbolic breakpoints on the list, since |
256 |
we have hopes that they can be reset after the new a.out's |
257 |
symbol table is read. |
258 |
|
259 |
However, any "raw" breakpoints must be removed from the list |
260 |
(e.g., the solib bp's), since their address is probably invalid |
261 |
now. |
262 |
|
263 |
And, we DON'T want to call delete_breakpoints() here, since |
264 |
that may write the bp's "shadow contents" (the instruction |
265 |
value that was overwritten witha TRAP instruction). Since |
266 |
we now have a new a.out, those shadow contents aren't valid. */ |
267 |
update_breakpoints_after_exec (); |
268 |
|
269 |
/* If there was one, it's gone now. We cannot truly step-to-next |
270 |
statement through an exec(). */ |
271 |
clear_step_resume_breakpoint (); |
272 |
step_range_start = 0; |
273 |
step_range_end = 0; |
274 |
|
275 |
/* What is this a.out's name? */ |
276 |
printf_unfiltered (_("Executing new program: %s\n"), execd_pathname); |
277 |
|
278 |
/* We've followed the inferior through an exec. Therefore, the |
279 |
inferior has essentially been killed & reborn. */ |
280 |
|
281 |
gdb_flush (gdb_stdout); |
282 |
|
283 |
/* Disable thread library */ |
284 |
if (disable_threads) |
285 |
{ |
286 |
disable_threads (); |
287 |
disable_threads = NULL; |
288 |
} |
289 |
|
290 |
generic_mourn_inferior (); |
291 |
inferior_ptid = ret; |
292 |
|
293 |
/* That a.out is now the one to use. */ |
294 |
exec_file_attach (execd_pathname, 0); |
295 |
|
296 |
/* And also is where symbols can be found. */ |
297 |
symbol_file_add_main (execd_pathname, 0); |
298 |
|
299 |
/* Reset the shared library package. This ensures that we get |
300 |
a shlib event when the child reaches "_start", at which point |
301 |
the dld will have had a chance to initialize the child. */ |
302 |
#if defined(SOLIB_RESTART) |
303 |
SOLIB_RESTART (); |
304 |
#endif |
305 |
#ifdef SOLIB_CREATE_INFERIOR_HOOK |
306 |
SOLIB_CREATE_INFERIOR_HOOK (PIDGET (inferior_ptid)); |
307 |
#else |
308 |
solib_create_inferior_hook (); |
309 |
#endif |
310 |
|
311 |
/* Reinsert all breakpoints. (Those which were symbolic have |
312 |
been reset to the proper address in the new a.out, thanks |
313 |
to symbol_file_command...) */ |
314 |
insert_breakpoints (); |
315 |
} |
316 |
|
317 |
static void fbsd_mourn_inferior (void) |
318 |
{ |
319 |
follow_event_pid = 0; |
320 |
mourn_inferior_beneath (); |
321 |
} |
322 |
|
323 |
static void fbsd_detach (char *args, int from_tty) |
324 |
{ |
325 |
follow_event_pid = 0; |
326 |
detach_beneath (args, from_tty); |
327 |
} |
328 |
|
329 |
void |
330 |
_initialize_fbsdnat (void) |
331 |
{ |
332 |
wait_beneath = inf_ptrace_wait; |
333 |
detach_beneath = child_ops.to_detach; |
334 |
mourn_inferior_beneath = child_ops.to_mourn_inferior; |
335 |
child_ops.to_wait = fbsd_wait; |
336 |
child_ops.to_detach = fbsd_detach; |
337 |
child_ops.to_mourn_inferior = fbsd_mourn_inferior; |
338 |
child_ops.to_post_attach = fbsd_post_attach; |
339 |
child_ops.to_post_startup_inferior = fbsd_post_startup_inferior; |
340 |
child_ops.to_follow_fork = fbsd_follow_fork; |
341 |
child_ops.to_follow_exec = fbsd_follow_exec; |
342 |
} |