]>
Commit | Line | Data |
---|---|---|
f412e1b4 PS |
1 | http://sourceware.org/ml/gdb-patches/2012-03/msg00170.html |
2 | Subject: [patch 2/3] attach-fail-reasons: Say more than ptrace: Operation not permitted. | |
3 | ||
4 | Hi, | |
5 | ||
6 | There is a common question on #gdb and also already described: | |
7 | ||
8 | http://sourceware.org/gdb/wiki/FAQ | |
9 | 16. Getting an internal error or other error while attaching to processes on | |
10 | GNU/Linux | |
11 | -> | |
12 | Try setenforce 0 (SELinux) or echo 0 >/proc/sys/kernel/yama/ptrace_scope | |
13 | (ptrace scope) to disable system security protections. | |
14 | ||
15 | and here is a patch to give some explanations. | |
16 | ||
17 | More reasons can be given later, this is a container for them and it contains | |
18 | some useful ones already. | |
19 | ||
20 | No regressions on {x86_64,x86_64-m32,i686}-fedora17-linux-gnu and with | |
21 | non-extended gdbserver. | |
22 | ||
23 | The testcase does not test gdbserver, somehow it is a bit difficult without | |
24 | having shell on target. | |
25 | ||
26 | Attaching to process 27480 | |
27 | ptrace: Operation not permitted. | |
28 | (gdb) _ | |
29 | -> | |
30 | Attaching to process 27480 | |
31 | warning: process 27480 is already traced by process 29011 | |
32 | ptrace: Operation not permitted. | |
33 | (gdb) _ | |
34 | ||
35 | ||
36 | Thanks, | |
37 | Jan | |
38 | ||
39 | ||
40 | gdb/ | |
41 | 2012-03-06 Jan Kratochvil <jan.kratochvil@redhat.com> | |
42 | ||
43 | * common/linux-procfs.c (linux_proc_get_int): New, from | |
44 | linux_proc_get_tgid. | |
45 | (linux_proc_get_tgid): Only call linux_proc_get_int. | |
46 | (linux_proc_get_tracerpid): New. | |
47 | (linux_proc_pid_has_state): New, from linux_proc_pid_is_zombie. | |
48 | (linux_proc_pid_is_stopped, linux_proc_pid_is_zombie): Only call | |
49 | linux_proc_pid_has_state. | |
50 | * common/linux-procfs.h (linux_proc_get_tracerpid): New declaration. | |
51 | * common/linux-ptrace.c: Include linux-procfs.h. | |
52 | (linux_ptrace_attach_warnings): New. | |
53 | * common/linux-ptrace.h (linux_ptrace_attach_warnings): New declaration. | |
54 | * linux-nat.c: Include exceptions.h and linux-ptrace.h. | |
55 | (linux_nat_attach): New variable ex. Wrap to_attach by TRY_CATCH and | |
56 | call linux_ptrace_attach_warnings. | |
57 | ||
58 | gdb/gdbserver/ | |
59 | 2012-03-06 Jan Kratochvil <jan.kratochvil@redhat.com> | |
60 | ||
61 | * linux-low.c (linux_attach_lwp_1): Call linux_ptrace_attach_warnings. | |
62 | ||
63 | gdb/testsuite/ | |
64 | 2012-03-06 Jan Kratochvil <jan.kratochvil@redhat.com> | |
65 | ||
66 | * gdb.base/attach-twice.c: New files. | |
67 | * gdb.base/attach-twice.exp: New files. | |
68 | ||
69 | Index: gdb-7.4.50.20120120/gdb/common/linux-procfs.c | |
70 | =================================================================== | |
71 | --- gdb-7.4.50.20120120.orig/gdb/common/linux-procfs.c 2012-03-06 07:34:00.000000000 +0100 | |
72 | +++ gdb-7.4.50.20120120/gdb/common/linux-procfs.c 2012-03-06 07:34:17.586816449 +0100 | |
73 | @@ -28,67 +28,54 @@ | |
74 | /* Return the TGID of LWPID from /proc/pid/status. Returns -1 if not | |
75 | found. */ | |
76 | ||
77 | -int | |
78 | -linux_proc_get_tgid (int lwpid) | |
79 | +static int | |
80 | +linux_proc_get_int (int lwpid, const char *field) | |
81 | { | |
82 | + size_t field_len = strlen (field); | |
83 | FILE *status_file; | |
84 | char buf[100]; | |
85 | - int tgid = -1; | |
86 | + int retval = -1; | |
87 | ||
88 | snprintf (buf, sizeof (buf), "/proc/%d/status", (int) lwpid); | |
89 | status_file = fopen (buf, "r"); | |
90 | - if (status_file != NULL) | |
91 | + if (status_file == NULL) | |
92 | { | |
93 | - while (fgets (buf, sizeof (buf), status_file)) | |
94 | - { | |
95 | - if (strncmp (buf, "Tgid:", 5) == 0) | |
96 | - { | |
97 | - tgid = strtoul (buf + strlen ("Tgid:"), NULL, 10); | |
98 | - break; | |
99 | - } | |
100 | - } | |
101 | - | |
102 | - fclose (status_file); | |
103 | + warning (_("unable to open /proc file '%s'"), buf); | |
104 | + return -1; | |
105 | } | |
106 | ||
107 | - return tgid; | |
108 | + while (fgets (buf, sizeof (buf), status_file)) | |
109 | + if (strncmp (buf, field, field_len) == 0 && buf[field_len] == ':') | |
110 | + { | |
111 | + retval = strtol (&buf[field_len + 1], NULL, 10); | |
112 | + break; | |
113 | + } | |
114 | + | |
115 | + fclose (status_file); | |
116 | + return retval; | |
117 | } | |
118 | ||
119 | -/* Detect `T (stopped)' in `/proc/PID/status'. | |
120 | - Other states including `T (tracing stop)' are reported as false. */ | |
121 | +/* Return the TGID of LWPID from /proc/pid/status. Returns -1 if not | |
122 | + found. */ | |
123 | ||
124 | int | |
125 | -linux_proc_pid_is_stopped (pid_t pid) | |
126 | +linux_proc_get_tgid (int lwpid) | |
127 | { | |
128 | - FILE *status_file; | |
129 | - char buf[100]; | |
130 | - int retval = 0; | |
131 | + return linux_proc_get_int (lwpid, "Tgid"); | |
132 | +} | |
133 | ||
134 | - snprintf (buf, sizeof (buf), "/proc/%d/status", (int) pid); | |
135 | - status_file = fopen (buf, "r"); | |
136 | - if (status_file != NULL) | |
137 | - { | |
138 | - int have_state = 0; | |
139 | +/* See linux-procfs.h. */ | |
140 | ||
141 | - while (fgets (buf, sizeof (buf), status_file)) | |
142 | - { | |
143 | - if (strncmp (buf, "State:", 6) == 0) | |
144 | - { | |
145 | - have_state = 1; | |
146 | - break; | |
147 | - } | |
148 | - } | |
149 | - if (have_state && strstr (buf, "T (stopped)") != NULL) | |
150 | - retval = 1; | |
151 | - fclose (status_file); | |
152 | - } | |
153 | - return retval; | |
154 | +pid_t | |
155 | +linux_proc_get_tracerpid (int lwpid) | |
156 | +{ | |
157 | + return linux_proc_get_int (lwpid, "TracerPid"); | |
158 | } | |
159 | ||
160 | -/* See linux-procfs.h declaration. */ | |
161 | +/* Return non-zero if 'State' of /proc/PID/status contains STATE. */ | |
162 | ||
163 | -int | |
164 | -linux_proc_pid_is_zombie (pid_t pid) | |
165 | +static int | |
166 | +linux_proc_pid_has_state (pid_t pid, const char *state) | |
167 | { | |
168 | char buffer[100]; | |
169 | FILE *procfile; | |
170 | @@ -110,8 +97,24 @@ linux_proc_pid_is_zombie (pid_t pid) | |
171 | have_state = 1; | |
172 | break; | |
173 | } | |
174 | - retval = (have_state | |
175 | - && strcmp (buffer, "State:\tZ (zombie)\n") == 0); | |
176 | + retval = (have_state && strstr (buffer, state) != NULL); | |
177 | fclose (procfile); | |
178 | return retval; | |
179 | } | |
180 | + | |
181 | +/* Detect `T (stopped)' in `/proc/PID/status'. | |
182 | + Other states including `T (tracing stop)' are reported as false. */ | |
183 | + | |
184 | +int | |
185 | +linux_proc_pid_is_stopped (pid_t pid) | |
186 | +{ | |
187 | + return linux_proc_pid_has_state (pid, "T (stopped)"); | |
188 | +} | |
189 | + | |
190 | +/* See linux-procfs.h declaration. */ | |
191 | + | |
192 | +int | |
193 | +linux_proc_pid_is_zombie (pid_t pid) | |
194 | +{ | |
195 | + return linux_proc_pid_has_state (pid, "Z (zombie)"); | |
196 | +} | |
197 | Index: gdb-7.4.50.20120120/gdb/common/linux-procfs.h | |
198 | =================================================================== | |
199 | --- gdb-7.4.50.20120120.orig/gdb/common/linux-procfs.h 2012-03-06 07:34:00.000000000 +0100 | |
200 | +++ gdb-7.4.50.20120120/gdb/common/linux-procfs.h 2012-03-06 07:34:17.586816449 +0100 | |
201 | @@ -26,6 +26,11 @@ | |
202 | ||
203 | extern int linux_proc_get_tgid (int lwpid); | |
204 | ||
205 | +/* Return the TracerPid of LWPID from /proc/pid/status. Returns -1 if not | |
206 | + found. */ | |
207 | + | |
208 | +extern pid_t linux_proc_get_tracerpid (int lwpid); | |
209 | + | |
210 | /* Detect `T (stopped)' in `/proc/PID/status'. | |
211 | Other states including `T (tracing stop)' are reported as false. */ | |
212 | ||
213 | Index: gdb-7.4.50.20120120/gdb/common/linux-ptrace.c | |
214 | =================================================================== | |
215 | --- gdb-7.4.50.20120120.orig/gdb/common/linux-ptrace.c 2012-03-06 07:34:00.000000000 +0100 | |
216 | +++ gdb-7.4.50.20120120/gdb/common/linux-ptrace.c 2012-03-06 07:34:17.586816449 +0100 | |
217 | @@ -24,3 +24,21 @@ | |
218 | #endif | |
219 | ||
220 | #include "linux-ptrace.h" | |
221 | +#include "linux-procfs.h" | |
222 | + | |
223 | +/* Print all possible reasons we could fail to attach PID. */ | |
224 | + | |
225 | +void | |
226 | +linux_ptrace_attach_warnings (pid_t pid) | |
227 | +{ | |
228 | + pid_t tracerpid; | |
229 | + | |
230 | + tracerpid = linux_proc_get_tracerpid (pid); | |
231 | + if (tracerpid > 0) | |
232 | + warning (_("process %d is already traced by process %d"), (int) pid, | |
233 | + (int) tracerpid); | |
234 | + | |
235 | + if (linux_proc_pid_is_zombie (pid)) | |
236 | + warning (_("process %d is a zombie - the process has already terminated"), | |
237 | + (int) pid); | |
238 | +} | |
239 | Index: gdb-7.4.50.20120120/gdb/common/linux-ptrace.h | |
240 | =================================================================== | |
241 | --- gdb-7.4.50.20120120.orig/gdb/common/linux-ptrace.h 2012-01-04 09:17:18.000000000 +0100 | |
242 | +++ gdb-7.4.50.20120120/gdb/common/linux-ptrace.h 2012-03-06 07:34:17.586816449 +0100 | |
243 | @@ -65,4 +65,6 @@ | |
244 | #define __WALL 0x40000000 /* Wait for any child. */ | |
245 | #endif | |
246 | ||
247 | +extern void linux_ptrace_attach_warnings (pid_t pid); | |
248 | + | |
249 | #endif /* COMMON_LINUX_PTRACE_H */ | |
250 | Index: gdb-7.4.50.20120120/gdb/gdbserver/linux-low.c | |
251 | =================================================================== | |
252 | --- gdb-7.4.50.20120120.orig/gdb/gdbserver/linux-low.c 2012-03-06 07:34:00.000000000 +0100 | |
253 | +++ gdb-7.4.50.20120120/gdb/gdbserver/linux-low.c 2012-03-06 07:34:17.587816446 +0100 | |
254 | @@ -632,6 +632,7 @@ linux_attach_lwp_1 (unsigned long lwpid, | |
255 | } | |
256 | ||
257 | /* If we fail to attach to a process, report an error. */ | |
258 | + linux_ptrace_attach_warnings (lwpid); | |
259 | error ("Cannot attach to lwp %ld: %s (%d)\n", lwpid, | |
260 | strerror (errno), errno); | |
261 | } | |
262 | Index: gdb-7.4.50.20120120/gdb/linux-nat.c | |
263 | =================================================================== | |
264 | --- gdb-7.4.50.20120120.orig/gdb/linux-nat.c 2012-03-06 07:34:00.000000000 +0100 | |
265 | +++ gdb-7.4.50.20120120/gdb/linux-nat.c 2012-03-06 07:34:29.860775803 +0100 | |
266 | @@ -59,6 +59,8 @@ | |
267 | #include "solib.h" | |
268 | #include "linux-osdata.h" | |
269 | #include "cli/cli-utils.h" | |
270 | +#include "exceptions.h" | |
271 | +#include "linux-ptrace.h" | |
272 | ||
273 | #ifndef SPUFS_MAGIC | |
274 | #define SPUFS_MAGIC 0x23c9b64e | |
275 | @@ -1613,11 +1615,22 @@ linux_nat_attach (struct target_ops *ops | |
276 | struct lwp_info *lp; | |
277 | int status; | |
278 | ptid_t ptid; | |
279 | + volatile struct gdb_exception ex; | |
280 | ||
281 | /* Make sure we report all signals during attach. */ | |
282 | linux_nat_pass_signals (0, NULL); | |
283 | ||
284 | - linux_ops->to_attach (ops, args, from_tty); | |
285 | + TRY_CATCH (ex, RETURN_MASK_ERROR) | |
286 | + { | |
287 | + linux_ops->to_attach (ops, args, from_tty); | |
288 | + } | |
289 | + if (ex.reason < 0) | |
290 | + { | |
291 | + pid_t pid = parse_pid_to_attach (args); | |
292 | + | |
293 | + linux_ptrace_attach_warnings (pid); | |
294 | + throw_exception (ex); | |
295 | + } | |
296 | ||
297 | /* The ptrace base target adds the main thread with (pid,0,0) | |
298 | format. Decorate it with lwp info. */ | |
299 | Index: gdb-7.4.50.20120120/gdb/testsuite/gdb.base/attach-twice.c | |
300 | =================================================================== | |
301 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
302 | +++ gdb-7.4.50.20120120/gdb/testsuite/gdb.base/attach-twice.c 2012-03-06 07:34:17.589816440 +0100 | |
303 | @@ -0,0 +1,42 @@ | |
304 | +/* This testcase is part of GDB, the GNU debugger. | |
305 | + | |
306 | + Copyright 2011-2012 Free Software Foundation, Inc. | |
307 | + | |
308 | + This program is free software; you can redistribute it and/or modify | |
309 | + it under the terms of the GNU General Public License as published by | |
310 | + the Free Software Foundation; either version 3 of the License, or | |
311 | + (at your option) any later version. | |
312 | + | |
313 | + This program is distributed in the hope that it will be useful, | |
314 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
315 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
316 | + GNU General Public License for more details. | |
317 | + | |
318 | + You should have received a copy of the GNU General Public License | |
319 | + along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
320 | + | |
321 | +#include <stdlib.h> | |
322 | +#include <unistd.h> | |
323 | +#include <sys/ptrace.h> | |
324 | +#include <errno.h> | |
325 | + | |
326 | +int | |
327 | +main (void) | |
328 | +{ | |
329 | + long l; | |
330 | + | |
331 | + switch (fork ()) | |
332 | + { | |
333 | + case -1: | |
334 | + perror ("fork"); | |
335 | + exit (1); | |
336 | + case 0: | |
337 | + errno = 0; | |
338 | + ptrace (PTRACE_ATTACH, getppid (), NULL, NULL); | |
339 | + if (errno != 0) | |
340 | + perror ("PTRACE_ATTACH"); | |
341 | + break; | |
342 | + } | |
343 | + sleep (600); | |
344 | + return 0; | |
345 | +} | |
346 | Index: gdb-7.4.50.20120120/gdb/testsuite/gdb.base/attach-twice.exp | |
347 | =================================================================== | |
348 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
349 | +++ gdb-7.4.50.20120120/gdb/testsuite/gdb.base/attach-twice.exp 2012-03-06 07:34:17.589816440 +0100 | |
350 | @@ -0,0 +1,52 @@ | |
351 | +# Copyright (C) 2012 Free Software Foundation, Inc. | |
352 | +# | |
353 | +# This program is free software; you can redistribute it and/or modify | |
354 | +# it under the terms of the GNU General Public License as published by | |
355 | +# the Free Software Foundation; either version 3 of the License, or | |
356 | +# (at your option) any later version. | |
357 | +# | |
358 | +# This program is distributed in the hope that it will be useful, | |
359 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
360 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
361 | +# GNU General Public License for more details. | |
362 | +# | |
363 | +# You should have received a copy of the GNU General Public License | |
364 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
365 | + | |
366 | +# Manipulation with PID on target is not supported. | |
367 | +if [is_remote target] then { | |
368 | + return 0 | |
369 | +} | |
370 | + | |
371 | +set testfile attach-twice | |
372 | +set executable ${testfile} | |
373 | +set binfile ${objdir}/${subdir}/${executable} | |
374 | + | |
375 | +if { [prepare_for_testing ${testfile}.exp $executable] } { | |
376 | + return -1 | |
377 | +} | |
378 | + | |
379 | +set testpid [eval exec $binfile &] | |
380 | +exec sleep 2 | |
381 | + | |
382 | +set parentpid 0 | |
383 | + | |
384 | +set test "attach" | |
385 | +gdb_test_multiple "attach $testpid" $test { | |
386 | + -re "Attaching to program: \[^\r\n\]*, process $testpid\r\n.*warning: process $testpid is already traced by process (\[0-9\]+)\r\n.*ptrace: Operation not permitted\\.\r\n$gdb_prompt $" { | |
387 | + set parentpid $expect_out(1,string) | |
388 | + pass $test | |
389 | + } | |
390 | + -re "Attaching to program: \[^\r\n\]*, process $testpid\r\n.*ptrace: Operation not permitted\\.\r\n$gdb_prompt $" { | |
391 | + fail $test | |
392 | + } | |
393 | + -re "\r\n$gdb_prompt $" { | |
394 | + xfail $test | |
395 | + } | |
396 | +} | |
397 | + | |
398 | +eval exec ps xfw | |
399 | +if {$parentpid != 0} { | |
400 | + eval exec kill -9 $parentpid | |
401 | +} | |
402 | +eval exec kill -9 $testpid |