]> git.pld-linux.org Git - packages/gdb.git/blob - gdb-threads.patch
- updated for 6.1.1
[packages/gdb.git] / gdb-threads.patch
1 1999-08-13  Jim Kingdon  <http://developer.redhat.com/>
2
3         Threads code from gdb 4.18-codefusion-990706:
4         * infrun.c (signal_stop_update, signal_print_update,
5         signal_pass_update): new functions.
6         * inferior.h: new prototypes for above functions.
7         * target.h (enum strata): add thread stratum.
8         * linuxthreads.c: new file.  Support for debugging linux threads.
9         * config/i386/nm-linux.h: several new prototypes for above.
10         * config/i386/linux.mh: add linuxthreads.o to NATDEPFILES.
11
12         More threads code from the same place:
13         * config/i386/tm-linux.h (REALTIME_LO, REALTIME_HI): Add
14         definitions.
15         * target.h (enum target_signal): Add TARGET_SIGNAL_REALTIME_32.
16         * target.c (signals, target_signal_from_host,
17         target_signal_to_host): Add clauses for
18         TARGET_SIGNAL_REALTIME_32.
19
20         * various files: various minor changes to make the above work
21         with GDB 4.18.
22
23 diff -Ncr /home/kingdon/work/gdb/gdb/config/i386/linux.mh ./gdb/config/i386/linux.mh
24 *** /home/kingdon/work/gdb/gdb/config/i386/linux.mh     Thu Apr 15 21:34:19 1999
25 --- ./gdb/config/i386/linux.mh  Fri Aug 13 00:51:14 1999
26 ***************
27 *** 4,7 ****
28   XDEPFILES= ser-tcp.o
29   
30   NAT_FILE= nm-linux.h
31 ! NATDEPFILES= infptrace.o solib.o inftarg.o fork-child.o corelow.o core-aout.o core-regset.o i386v-nat.o i386v4-nat.o
32 --- 4,7 ----
33   XDEPFILES= ser-tcp.o
34   
35   NAT_FILE= nm-linux.h
36 ! NATDEPFILES= infptrace.o solib.o inftarg.o fork-child.o corelow.o core-aout.o core-regset.o i386v-nat.o i386v4-nat.o linuxthreads.o
37 diff -Ncr /home/kingdon/work/gdb/gdb/config/i386/nm-linux.h ./gdb/config/i386/nm-linux.h
38 *** /home/kingdon/work/gdb/gdb/config/i386/nm-linux.h   Thu Jul  8 16:09:02 1999
39 --- ./gdb/config/i386/nm-linux.h        Fri Aug 13 00:49:54 1999
40 ***************
41 *** 71,74 ****
42 --- 71,92 ----
43   extern int
44   i386_remove_watchpoint PARAMS ((int pid, CORE_ADDR addr, int len));
45   
46 + /* Support for the glibc linuxthreads package. */
47
48 + #ifdef __STDC__
49 + struct objfile;
50 + #endif
51
52 + extern void
53 + linuxthreads_new_objfile PARAMS ((struct objfile *objfile));
54 + #define target_new_objfile(OBJFILE) linuxthreads_new_objfile (OBJFILE)
55
56 + extern char *
57 + linuxthreads_pid_to_str PARAMS ((int pid));
58 + #define target_pid_to_str(PID) linuxthreads_pid_to_str (PID)
59
60 + extern int
61 + linuxthreads_prepare_to_proceed PARAMS ((int step));
62 + #define PREPARE_TO_PROCEED() linuxthreads_prepare_to_proceed (1)
63
64   #endif /* #ifndef NM_LINUX_H */
65 diff -Ncr /home/kingdon/work/gdb/gdb/config/i386/tm-linux.h ./gdb/config/i386/tm-linux.h
66 *** /home/kingdon/work/gdb/gdb/config/i386/tm-linux.h   Tue Aug  3 16:40:28 1999
67 --- ./gdb/config/i386/tm-linux.h        Sat Aug 14 19:15:35 1999
68 ***************
69 *** 104,107 ****
70 --- 104,121 ----
71   
72   extern CORE_ADDR i386_linux_sigtramp_saved_sp PARAMS ((struct frame_info *));
73   
74
75 + /* Some versions of Linux have real-time signal support in the C library, and
76 +    some don't.  We have to include this file to find out.  */
77 + #include <signal.h>
78
79 + #ifdef __SIGRTMIN
80 + #define REALTIME_LO __SIGRTMIN
81 + #define REALTIME_HI (__SIGRTMAX + 1)
82 + #else
83 + #define REALTIME_LO 32
84 + #define REALTIME_HI 64
85 + #endif
86
87
88   #endif  /* #ifndef TM_LINUX_H */
89 diff -Ncr /home/kingdon/work/gdb/gdb/inferior.h ./gdb/inferior.h
90 *** /home/kingdon/work/gdb/gdb/inferior.h       Thu Jul  8 16:02:22 1999
91 --- ./gdb/inferior.h    Fri Aug 13 00:43:51 1999
92 ***************
93 *** 260,265 ****
94 --- 260,271 ----
95   
96   extern int signal_pass_state PARAMS ((int));
97   
98 + extern int signal_stop_update PARAMS ((int, int));
99
100 + extern int signal_print_update PARAMS ((int, int));
101
102 + extern int signal_pass_update PARAMS ((int, int));
103
104   /* From infcmd.c */
105   
106   extern void tty_command PARAMS ((char *, int));
107 diff -Ncr /home/kingdon/work/gdb/gdb/infrun.c ./gdb/infrun.c
108 *** /home/kingdon/work/gdb/gdb/infrun.c Thu Aug 12 11:13:29 1999
109 --- ./gdb/infrun.c      Fri Aug 13 00:33:34 1999
110 ***************
111 *** 3291,3296 ****
112 --- 3291,3323 ----
113     return signal_program[signo];
114   }
115   
116 + int signal_stop_update (signo, state)
117 +      int signo;
118 +      int state;
119 + {
120 +   int ret = signal_stop[signo];
121 +   signal_stop[signo] = state;
122 +   return ret;
123 + }
124
125 + int signal_print_update (signo, state)
126 +      int signo;
127 +      int state;
128 + {
129 +   int ret = signal_print[signo];
130 +   signal_print[signo] = state;
131 +   return ret;
132 + }
133
134 + int signal_pass_update (signo, state)
135 +      int signo;
136 +      int state;
137 + {
138 +   int ret = signal_program[signo];
139 +   signal_program[signo] = state;
140 +   return ret;
141 + }
142
143   static void
144   sig_print_header (void)
145   {
146 diff -Ncr /home/kingdon/work/gdb/gdb/linuxthreads.c ./gdb/linuxthreads.c
147 *** /home/kingdon/work/gdb/gdb/linuxthreads.c   Wed Dec 31 19:00:00 1969
148 --- ./gdb/linuxthreads.c        Fri Aug 13 00:46:01 1999
149 ***************
150 *** 0 ****
151 --- 1,1631 ----
152 + /* Low level interface for debugging GNU/Linux threads for GDB,
153 +    the GNU debugger.
154 +    Copyright 1998, 1999 Free Software Foundation, Inc.
155
156 + This file is part of GDB.
157
158 + This program is free software; you can redistribute it and/or modify
159 + it under the terms of the GNU General Public License as published by
160 + the Free Software Foundation; either version 2 of the License, or
161 + (at your option) any later version.
162
163 + This program is distributed in the hope that it will be useful,
164 + but WITHOUT ANY WARRANTY; without even the implied warranty of
165 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
166 + GNU General Public License for more details.
167
168 + You should have received a copy of the GNU General Public License
169 + along with this program; if not, write to the Free Software
170 + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
171
172 + /* This module implements the debugging interface of the linuxthreads package
173 +    of the glibc. This package implements a simple clone()-based implementation
174 +    of Posix threads for Linux. To use this module, be sure that you have at
175 +    least the version of the linuxthreads package that holds the support of
176 +    GDB (currently 0.8 included in the glibc-2.0.7).
177
178 +    Right now, the linuxthreads package does not care of priority scheduling,
179 +    so, neither this module does; In particular, the threads are resumed
180 +    in any order, which could lead to different scheduling than the one
181 +    happening when GDB does not control the execution.
182
183 +    The latest point is that ptrace(PT_ATTACH, ...) is intrusive in Linux:
184 +    When a process is attached, then the attaching process becomes the current
185 +    parent of the attached process, and the old parent has lost this child.
186 +    If the old parent does a wait[...](), then this child is no longer
187 +    considered by the kernel as a child of the old parent, thus leading to
188 +    results of the call different when the child is attached and when it's not.
189
190 +    A fix has been submitted to the Linux community to solve this problem,
191 +    which consequences are not visible to the application itself, but on the
192 +    process which may wait() for the completion of the application (mostly,
193 +    it may consider that the application no longer exists (errno == ECHILD),
194 +    although it does, and thus being unable to get the exit status and resource
195 +    usage of the child. If by chance, it is able to wait() for the application
196 +    after it has died (by receiving first a SIGCHILD, and then doing a wait(),
197 +    then the exit status and resource usage may be wrong, because the
198 +    linuxthreads package heavily relies on wait() synchronization to keep
199 +    them correct.  */
200
201 + #include <sys/types.h> /* for pid_t */
202 + #include <sys/ptrace.h> /* for PT_* flags */
203 + #include <sys/wait.h> /* for WUNTRACED and __WCLONE flags */
204 + #include <signal.h> /* for struct sigaction and NSIG */
205 + #include <sys/utsname.h>
206
207 + #include "defs.h"
208 + #include "target.h"
209 + #include "inferior.h"
210 + #include "gdbcore.h"
211 + #include "gdbthread.h"
212 + #include "wait.h"
213 + #include "gdbcmd.h"
214 + #include "breakpoint.h"
215
216 + #ifndef PT_ATTACH
217 + #define PT_ATTACH     PTRACE_ATTACH
218 + #endif
219 + #ifndef PT_KILL
220 + #define PT_KILL               PTRACE_KILL
221 + #endif
222 + #ifndef PT_READ_U
223 + #define PT_READ_U     PTRACE_PEEKUSR
224 + #endif
225
226 + #ifdef NSIG
227 + #define LINUXTHREAD_NSIG NSIG
228 + #else
229 + #ifdef _NSIG
230 + #define LINUXTHREAD_NSIG _NSIG
231 + #endif
232 + #endif
233
234 + extern int child_suppress_run;                /* make inftarg.c non-runnable */
235 + struct target_ops linuxthreads_ops;   /* Forward declaration */
236 + extern struct target_ops child_ops;   /* target vector for inftarg.c */
237
238 + static CORE_ADDR linuxthreads_handles;        /* array of linuxthreads handles */
239 + static CORE_ADDR linuxthreads_manager;        /* pid of linuxthreads manager thread */
240 + static CORE_ADDR linuxthreads_initial;        /* pid of linuxthreads initial thread */
241 + static CORE_ADDR linuxthreads_debug;  /* linuxthreads internal debug flag */
242 + static CORE_ADDR linuxthreads_num;    /* number of valid handle entries */
243
244 + static int linuxthreads_max;          /* Maximum number of linuxthreads.
245 +                                          Zero if this executable doesn't use
246 +                                          threads, or wasn't linked with a
247 +                                          debugger-friendly version of the
248 +                                          linuxthreads library.  */
249
250 + static int linuxthreads_sizeof_handle;        /* size of a linuxthreads handle */
251 + static int linuxthreads_offset_descr; /* h_descr offset of the linuxthreads
252 +                                          handle */
253 + static int linuxthreads_offset_pid;   /* p_pid offset of the linuxthreads
254 +                                          descr */
255
256 + static int linuxthreads_manager_pid;  /* manager pid */
257 + static int linuxthreads_initial_pid;  /* initial pid */
258
259 + /* These variables form a bag of threads with interesting status.  If
260 +    wait_thread (PID) finds that PID stopped for some interesting
261 +    reason (i.e. anything other than stopped with SIGSTOP), then it
262 +    records its status in this queue.  linuxthreads_wait and
263 +    linuxthreads_find_trap extract processes from here.  */
264 + static int *linuxthreads_wait_pid;    /* wait array of pid */
265 + static int *linuxthreads_wait_status; /* wait array of status */
266 + static int linuxthreads_wait_last;    /* index of last valid elt in
267 +                                          linuxthreads_wait_{pid,status} */
268
269 + static sigset_t linuxthreads_wait_mask;       /* sigset with SIGCHLD */
270
271 + static int linuxthreads_step_pid;     /* current stepped pid */
272 + static int linuxthreads_step_signo;   /* current stepped target signal */
273 + static int linuxthreads_exit_status;  /* exit status of initial thread */
274
275 + static int linuxthreads_inferior_pid; /* temporary internal inferior pid */
276 + static int linuxthreads_breakpoint_pid;       /* last pid that hit a breakpoint */
277 + static int linuxthreads_attach_pending;       /* attach command without wait */
278
279 + static int linuxthreads_breakpoints_inserted; /* any breakpoints inserted */
280
281 + /* LinuxThreads uses certain signals for communication between
282 +    processes; we need to tell GDB to pass them through silently to the
283 +    inferior.  The LinuxThreads library has global variables we can
284 +    read containing the relevant signal numbers, but since the signal
285 +    numbers are chosen at run-time, those variables aren't initialized
286 +    until the shared library's constructors have had a chance to run.  */
287
288 + struct linuxthreads_signal {
289
290 +   /* The name of the LinuxThreads library variable that contains
291 +      the signal number.  */
292 +   char *var;
293
294 +   /* True if this variable must exist for us to debug properly.  */
295 +   int required;
296 +   
297 +   /* The variable's address in the inferior, or zero if the
298 +      LinuxThreads library hasn't been loaded into this inferior yet.  */
299 +   CORE_ADDR addr;
300
301 +   /* The signal number, or zero if we don't know yet (either because
302 +      we haven't found the variable, or it hasn't been initialized).
303 +      This is an actual target signal number that you could pass to
304 +      `kill', not a GDB signal number.  */
305 +   int signal;
306
307 +   /* GDB's original settings for `stop' and `print' for this signal.
308 +      We restore them when the user selects a different executable.
309 +      Invariant: if sig->signal != 0, then sig->{stop,print} contain
310 +      the original settings.  */
311 +   int stop, print;
312 + };
313
314 + struct linuxthreads_signal linuxthreads_sig_restart = {
315 +   "__pthread_sig_restart", 1, 0, 0, 0
316 + };
317 + struct linuxthreads_signal linuxthreads_sig_cancel = {
318 +   "__pthread_sig_cancel", 1, 0, 0, 0
319 + };
320 + struct linuxthreads_signal linuxthreads_sig_debug = {
321 +   "__pthread_sig_debug", 0, 0, 0, 0
322 + };
323
324 + /* A table of breakpoint locations, one per PID.  */
325 + static struct linuxthreads_breakpoint {
326 +     CORE_ADDR pc;     /* PC of breakpoint */
327 +     int               pid;    /* pid of breakpoint */
328 +     int               step;   /* whether the pc has been reached after sstep */
329 + } *linuxthreads_breakpoint_zombie;            /* Zombie breakpoints array */
330 + static int linuxthreads_breakpoint_last;      /* Last zombie breakpoint */
331
332 + /* linuxthreads_{insert,remove}_breakpoint pass the breakpoint address
333 +    to {insert,remove}_breakpoint via this variable, since
334 +    iterate_active_threads doesn't provide any way to pass values
335 +    through to the worker function.  */
336 + static CORE_ADDR linuxthreads_breakpoint_addr;
337
338 + #define       REMOVE_BREAKPOINT_ZOMBIE(_i) \
339 + { \
340 +   if ((_i) < linuxthreads_breakpoint_last) \
341 +     linuxthreads_breakpoint_zombie[(_i)] = \
342 +       linuxthreads_breakpoint_zombie[linuxthreads_breakpoint_last]; \
343 +   linuxthreads_breakpoint_last--; \
344 + }
345
346
347\f
348 + #ifndef PTRACE_XFER_TYPE
349 + #define PTRACE_XFER_TYPE int
350 + #endif
351 + /* Check to see if the given thread is alive.  */
352 + static int
353 + linuxthreads_thread_alive (pid)
354 +      int pid;
355 + {
356 +     errno = 0;
357 +     return ptrace (PT_READ_U, pid, (PTRACE_ARG3_TYPE)0, 0) >= 0 || errno == 0;
358 + }
359
360 + /* On detach(), find a SIGTRAP status.  If stop is non-zero, find a
361 +    SIGSTOP one, too.
362
363 +    Make sure PID is ready to run, and free of interference from our
364 +    efforts to debug it (e.g., pending SIGSTOP or SIGTRAP signals).  If
365 +    STOP is zero, just look for a SIGTRAP.  If STOP is non-zero, look
366 +    for a SIGSTOP, too.  Return non-zero if PID is alive and ready to
367 +    run; return zero if PID is dead.
368
369 +    PID may or may not be stopped at the moment, and we may or may not
370 +    have waited for it already.  We check the linuxthreads_wait bag in
371 +    case we've already got a status for it.  We may possibly wait for
372 +    it ourselves.
373
374 +    PID may have signals waiting to be delivered.  If they're caused by
375 +    our efforts to debug it, accept them with wait, but don't pass them
376 +    through to PID.  Do pass all other signals through.  */   
377 + static int
378 + linuxthreads_find_trap (pid, stop)
379 +     int pid;
380 +     int stop;
381 + {
382 +   int i;
383 +   int rpid;
384 +   int status;
385 +   int found_stop = 0;
386 +   int found_trap = 0;
387
388 +   /* PID may have any number of signals pending.  The kernel will
389 +      report each of them to us via wait, and then it's up to us to
390 +      pass them along to the process via ptrace, if we so choose.
391
392 +      We need to paw through the whole set until we've found a SIGTRAP
393 +      (or a SIGSTOP, if `stop' is set).  We don't pass the SIGTRAP (or
394 +      SIGSTOP) through, but we do re-send all the others, so PID will
395 +      receive them when we resume it.  */
396 +   int *wstatus = alloca (LINUXTHREAD_NSIG * sizeof (int));
397 +   int last = 0;
398
399 +   /* Look at the pending status */
400 +   for (i = linuxthreads_wait_last; i >= 0; i--)
401 +     if (linuxthreads_wait_pid[i] == pid)
402 +       {
403 +       status = linuxthreads_wait_status[i];
404
405 +       /* Delete the i'th member of the table.  Since the table is
406 +          unordered, we can do this simply by copying the table's
407 +          last element to the i'th position, and shrinking the table
408 +          by one element.  */
409 +       if (i < linuxthreads_wait_last)
410 +         {
411 +           linuxthreads_wait_status[i] =
412 +             linuxthreads_wait_status[linuxthreads_wait_last];
413 +           linuxthreads_wait_pid[i] =
414 +             linuxthreads_wait_pid[linuxthreads_wait_last];
415 +         }
416 +       linuxthreads_wait_last--;
417
418 +       if (!WIFSTOPPED(status)) /* Thread has died */
419 +         return 0;
420
421 +       if (WSTOPSIG(status) == SIGTRAP)
422 +         {
423 +           if (stop)
424 +             found_trap = 1;
425 +           else
426 +             return 1;
427 +         }
428 +       else if (WSTOPSIG(status) == SIGSTOP)
429 +         {
430 +           if (stop)
431 +             found_stop = 1;
432 +         }
433 +       else
434 +         {
435 +           wstatus[0] = status;
436 +           last = 1;
437 +         }
438
439 +       break;
440 +       }
441
442 +   if (stop)
443 +     {
444 +       /* Make sure that we'll find what we're looking for.  */
445 +       if (!found_trap)
446 +       kill (pid, SIGTRAP);
447 +       if (!found_stop)
448 +       kill (pid, SIGSTOP);
449 +     }
450 +                     
451 +   /* Catch all status until SIGTRAP and optionally SIGSTOP show up.  */
452 +   for (;;)
453 +     {
454 +       child_resume (pid, 1, TARGET_SIGNAL_0);
455
456 +       for (;;)
457 +       {
458 +         rpid = waitpid (pid, &status, __WCLONE);
459 +         if (rpid > 0)
460 +           break;
461 +         if (errno == EINTR)
462 +           continue;
463
464 +         /* There are a few reasons the wait call above may have
465 +            failed.  If the thread manager dies, its children get
466 +            reparented, and this interferes with GDB waiting for
467 +            them, in some cases.  Another possibility is that the
468 +            initial thread was not cloned, so calling wait with
469 +            __WCLONE won't find it.  I think neither of these should
470 +            occur in modern Linux kernels --- they don't seem to in
471 +            2.0.36.  */
472 +         rpid = waitpid (pid, &status, 0);
473 +         if (rpid > 0)
474 +           break;
475 +         if (errno != EINTR)
476 +           perror_with_name ("waitpid");
477 +       }
478
479 +       if (!WIFSTOPPED(status)) /* Thread has died */
480 +       return 0;
481
482 +       if (WSTOPSIG(status) == SIGTRAP)
483 +       if (!stop || found_stop)
484 +         break;
485 +       else
486 +         found_trap = 1;
487 +       else if (WSTOPSIG(status) != SIGSTOP)
488 +       wstatus[last++] = status;
489 +       else if (stop)
490 +       if (found_trap)
491 +         break;
492 +       else
493 +         found_stop = 1;
494 +     }
495
496 +   /* Resend any other signals we noticed to the thread, to be received
497 +      when we continue it.  */
498 +   while (--last >= 0)
499 +     kill (pid, WSTOPSIG(wstatus[last]));
500
501 +   return 1;
502 + }
503
504 + /* Cleanup stub for save_inferior_pid.  */
505 + static void
506 + restore_inferior_pid (arg)
507 +     void *arg;
508 + {
509 +   int pid = (int) arg;
510 +   inferior_pid = pid;
511 + }
512
513 + /* Register a cleanup to restore the value of inferior_pid.  */
514 + static struct cleanup *
515 + save_inferior_pid ()
516 + {
517 +   return make_cleanup (restore_inferior_pid, (void *) inferior_pid);
518 + }
519
520 + static void
521 + sigchld_handler(signo)
522 +     int signo;
523 + {
524 +     /* This handler is used to get an EINTR while doing waitpid()
525 +        when an event is received */
526 + }
527
528 + /* Have we already collected a wait status for PID in the
529 +    linuxthreads_wait bag?  */
530 + static int
531 + linuxthreads_pending_status (pid)
532 +     int pid;
533 + {
534 +   int i;
535 +   for (i = linuxthreads_wait_last; i >= 0; i--)
536 +     if (linuxthreads_wait_pid[i] == pid)
537 +       return 1;
538 +   return 0;
539 + }
540
541\f
542 + /* Internal linuxthreads signal management */
543
544 + /* Check in OBJFILE for the variable that holds the number for signal SIG.
545 +    We assume that we've already found other LinuxThreads-ish variables
546 +    in OBJFILE, so we complain if it's required, but not there.
547 +    Return true iff things are okay.  */
548 + static int
549 + find_signal_var (struct linuxthreads_signal *sig,
550 +                struct objfile *objfile)
551 + {
552 +   struct minimal_symbol *ms = lookup_minimal_symbol (sig->var, NULL, objfile);
553
554 +   if (! ms)
555 +     {
556 +       if (sig->required)
557 +       {
558 +         fprintf_unfiltered (gdb_stderr,
559 +                             "Unable to find linuxthreads symbol \"%s\"\n",
560 +                             sig->var);
561 +         return 0;
562 +       }
563 +       else
564 +       {
565 +         sig->addr = 0;
566 +         return 1;
567 +       }
568 +     }
569
570 +   sig->addr = SYMBOL_VALUE_ADDRESS (ms);
571
572 +   return 1;
573 + }
574
575 + static int
576 + find_all_signal_vars (struct objfile *objfile)
577 + {
578 +   return (   find_signal_var (&linuxthreads_sig_restart, objfile)
579 +         && find_signal_var (&linuxthreads_sig_cancel,  objfile)
580 +         && find_signal_var (&linuxthreads_sig_debug,   objfile));
581 + }
582
583 + /* A struct complaint isn't appropriate here.  */
584 + static int complained_cannot_determine_thread_signal_number = 0;
585
586 + /* Check to see if the variable holding the signal number for SIG has
587 +    been initialized yet.  If it has, tell GDB to pass that signal
588 +    through to the inferior silently.  */
589 + static void
590 + check_signal_number (struct linuxthreads_signal *sig)
591 + {
592 +   int num;
593
594 +   if (sig->signal)
595 +     /* We already know this signal number.  */
596 +     return;
597
598 +   if (! sig->addr)
599 +     /* We don't know the variable's address yet.  */
600 +     return;
601
602 +   if (target_read_memory (sig->addr, (char *)&num, sizeof (num))
603 +       != 0)
604 +     {
605 +       /* If this happens once, it'll probably happen for all the
606 +        signals, so only complain once.  */
607 +       if (! complained_cannot_determine_thread_signal_number)
608 +       warning ("Cannot determine thread signal number; "
609 +                "GDB may report spurious signals.");
610 +       complained_cannot_determine_thread_signal_number = 1;
611 +       return;
612 +     }
613 +   
614 +   if (num == 0)
615 +     /* It hasn't been initialized yet.  */
616 +     return;
617
618 +   /* We know sig->signal was zero, and is becoming non-zero, so it's
619 +      okay to sample GDB's original settings.  */
620 +   sig->signal = num;
621 +   sig->stop  = signal_stop_update  (target_signal_from_host (num), 0);
622 +   sig->print = signal_print_update (target_signal_from_host (num), 0);
623 + }
624
625
626 + static void
627 + check_all_signal_numbers (void)
628 + {
629 +   /* If this isn't a LinuxThreads program, quit early.  */
630 +   if (! linuxthreads_max)
631 +     return;
632
633 +   check_signal_number (&linuxthreads_sig_restart);
634 +   check_signal_number (&linuxthreads_sig_cancel);
635 +   check_signal_number (&linuxthreads_sig_debug);
636
637 +   /* handle linuxthread exit */
638 +   if (linuxthreads_sig_debug.signal
639 +       || linuxthreads_sig_restart.signal)
640 +     {
641 +       struct sigaction sact;
642
643 +       sact.sa_handler = sigchld_handler;
644 +       sigemptyset(&sact.sa_mask);
645 +       sact.sa_flags = 0;
646 +       if (linuxthreads_sig_debug.signal > 0)
647 +       sigaction(linuxthreads_sig_cancel.signal, &sact, NULL);
648 +       else
649 +       sigaction(linuxthreads_sig_restart.signal, &sact, NULL);
650 +     }
651 + }
652
653
654 + /* Restore GDB's original settings for SIG.
655 +    This should only be called when we're no longer sure if we're
656 +    talking to an executable that uses LinuxThreads, so we clear the
657 +    signal number and variable address too.  */
658 + static void
659 + restore_signal (struct linuxthreads_signal *sig)
660 + {
661 +   if (! sig->signal)
662 +     return;
663
664 +   /* We know sig->signal was non-zero, and is becoming zero, so it's
665 +      okay to restore GDB's original settings.  */
666 +   signal_stop_update  (target_signal_from_host (sig->signal), sig->stop);
667 +   signal_print_update (target_signal_from_host (sig->signal), sig->print);
668
669 +   sig->signal = 0;
670 +   sig->addr = 0;
671 + }
672
673
674 + /* Restore GDB's original settings for all LinuxThreads signals.
675 +    This should only be called when we're no longer sure if we're
676 +    talking to an executable that uses LinuxThreads, so we clear the
677 +    signal number and variable address too.  */
678 + static void
679 + restore_all_signals (void)
680 + {
681 +   restore_signal (&linuxthreads_sig_restart);
682 +   restore_signal (&linuxthreads_sig_cancel);
683 +   restore_signal (&linuxthreads_sig_debug);
684
685 +   /* If it happens again, we should complain again.  */
686 +   complained_cannot_determine_thread_signal_number = 0;
687 + }
688
689
690\f
691
692 + /* Apply FUNC to the pid of each active thread.  This consults the
693 +    inferior's handle table to find active threads.
694
695 +    If ALL is non-zero, process all threads.
696 +    If ALL is zero, skip threads with pending status.  */
697 + static void
698 + iterate_active_threads (func, all)
699 +     void (*func)(int);
700 +     int all;
701 + {
702 +   CORE_ADDR descr;
703 +   int pid;
704 +   int i;
705 +   int num;
706
707 +   read_memory (linuxthreads_num, (char *)&num, sizeof (int));
708
709 +   for (i = 0; i < linuxthreads_max && num > 0; i++)
710 +     {
711 +       read_memory (linuxthreads_handles +
712 +                  linuxthreads_sizeof_handle * i + linuxthreads_offset_descr,
713 +                  (char *)&descr, sizeof (void *));
714 +       if (descr)
715 +       {
716 +         num--;
717 +         read_memory (descr + linuxthreads_offset_pid,
718 +                      (char *)&pid, sizeof (pid_t));
719 +         if (pid > 0 && pid != linuxthreads_manager_pid
720 +             && (all || (!linuxthreads_pending_status (pid))))
721 +           (*func)(pid);
722 +       }
723 +     }
724
725 + }
726
727 + /* Insert a thread breakpoint at linuxthreads_breakpoint_addr.
728 +    This is the worker function for linuxthreads_insert_breakpoint,
729 +    which passes it to iterate_active_threads.  */
730 + static void
731 + insert_breakpoint (pid)
732 +     int pid;
733 + {
734 +   int j;
735
736 +   /* Remove (if any) the positive zombie breakpoint.  */
737 +   for (j = linuxthreads_breakpoint_last; j >= 0; j--)
738 +     if (linuxthreads_breakpoint_zombie[j].pid == pid)
739 +       {
740 +       if ((linuxthreads_breakpoint_zombie[j].pc - DECR_PC_AFTER_BREAK
741 +            == linuxthreads_breakpoint_addr)
742 +           && !linuxthreads_breakpoint_zombie[j].step)
743 +         REMOVE_BREAKPOINT_ZOMBIE(j);
744 +       break;
745 +       }
746 + }
747
748 + /* Note that we're about to remove a thread breakpoint at
749 +    linuxthreads_breakpoint_addr.
750
751 +    This is the worker function for linuxthreads_remove_breakpoint,
752 +    which passes it to iterate_active_threads.  The actual work of
753 +    overwriting the breakpoint instruction is done by
754 +    child_ops.to_remove_breakpoint; here, we simply create a zombie
755 +    breakpoint if the thread's PC is pointing at the breakpoint being
756 +    removed.  */
757 + static void
758 + remove_breakpoint (pid)
759 +     int pid;
760 + {
761 +   int j;
762
763 +   /* Insert a positive zombie breakpoint (if needed).  */
764 +   for (j = 0; j <= linuxthreads_breakpoint_last; j++)
765 +     if (linuxthreads_breakpoint_zombie[j].pid == pid)
766 +       break;
767
768 +   if (in_thread_list (pid) && linuxthreads_thread_alive (pid))
769 +     {
770 +       CORE_ADDR pc = read_pc_pid (pid);
771 +       if (linuxthreads_breakpoint_addr == pc - DECR_PC_AFTER_BREAK
772 +         && j > linuxthreads_breakpoint_last)
773 +       {
774 +         linuxthreads_breakpoint_zombie[j].pid = pid;
775 +         linuxthreads_breakpoint_zombie[j].pc = pc;
776 +         linuxthreads_breakpoint_zombie[j].step = 0;
777 +         linuxthreads_breakpoint_last++;
778 +       }
779 +     }
780 + }
781
782 + /* Kill a thread */
783 + static void
784 + kill_thread (pid)
785 +     int pid;
786 + {
787 +   if (in_thread_list (pid))
788 +     ptrace (PT_KILL, pid, (PTRACE_ARG3_TYPE) 0, 0);
789 +   else
790 +     kill (pid, SIGKILL);
791 + }
792
793 + /* Resume a thread */
794 + static void
795 + resume_thread (pid)
796 +     int pid;
797 + {
798 +   if (pid != inferior_pid
799 +       && in_thread_list (pid)
800 +       && linuxthreads_thread_alive (pid))
801 +     if (pid == linuxthreads_step_pid)
802 +       child_resume (pid, 1, linuxthreads_step_signo);
803 +     else
804 +       child_resume (pid, 0, TARGET_SIGNAL_0);
805 + }
806
807 + /* Detach a thread */
808 + static void
809 + detach_thread (pid)
810 +     int pid;
811 + {
812 +   if (in_thread_list (pid) && linuxthreads_thread_alive (pid))
813 +     {
814 +       /* Remove pending SIGTRAP and SIGSTOP */
815 +       linuxthreads_find_trap (pid, 1);
816
817 +       inferior_pid = pid;
818 +       detach (TARGET_SIGNAL_0);
819 +       inferior_pid = linuxthreads_manager_pid;
820 +     }
821 + }
822
823 + /* Stop a thread */
824 + static void
825 + stop_thread (pid)
826 +     int pid;
827 + {
828 +   if (pid != inferior_pid)
829 +     if (in_thread_list (pid))
830 +       kill (pid, SIGSTOP);
831 +     else if (ptrace (PT_ATTACH, pid, (PTRACE_ARG3_TYPE) 0, 0) == 0)
832 +       {
833 +       if (!linuxthreads_attach_pending)
834 +         printf_unfiltered ("[New %s]\n", target_pid_to_str (pid));
835 +       add_thread (pid);
836 +       if (linuxthreads_sig_debug.signal)
837 +         /* After a new thread in glibc 2.1 signals gdb its existence,
838 +            it suspends itself and wait for linuxthreads_sig_restart,
839 +            now we can wake up it. */
840 +         kill (pid, linuxthreads_sig_restart.signal);
841 +       }
842 +     else
843 +       perror_with_name ("ptrace in stop_thread");
844 + }
845
846 + /* Wait for a thread */
847 + static void
848 + wait_thread (pid)
849 +     int pid;
850 + {
851 +   int status;
852 +   int rpid;
853
854 +   if (pid != inferior_pid && in_thread_list (pid))
855 +     {
856 +       for (;;)
857 +       {
858 +         /* Get first pid status.  */
859 +         rpid = waitpid(pid, &status, __WCLONE);
860 +         if (rpid > 0)
861 +           break;
862 +         if (errno == EINTR)
863 +           continue;
864
865 +         /* There are two reasons this might have failed:
866
867 +            1) PID is the initial thread, which wasn't cloned, so
868 +            passing the __WCLONE flag to waitpid prevented us from
869 +            finding it.
870
871 +            2) The manager thread is the parent of all but the
872 +            initial thread; if it dies, the children will all be
873 +            reparented to init, which will wait for them.  This means
874 +            our call to waitpid won't find them.
875
876 +            Actually, based on a casual look at the 2.0.36 kernel
877 +            code, I don't think either of these cases happen.  But I
878 +            don't have things set up for remotely debugging the
879 +            kernel, so I'm not sure.  And perhaps older kernels
880 +            didn't work.  */
881 +         rpid = waitpid(pid, &status, 0);
882 +         if (rpid > 0)
883 +           break;
884 +         if (errno != EINTR && linuxthreads_thread_alive (pid))
885 +           perror_with_name ("waitpid");
886
887 +         /* the thread is dead.  */
888 +         return;
889 +       }
890 +       if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP)
891 +       {
892 +         linuxthreads_wait_pid[++linuxthreads_wait_last] = pid;
893 +         linuxthreads_wait_status[linuxthreads_wait_last] = status;
894 +       }
895 +     }
896 + }
897
898 + /* Walk through the linuxthreads handles in order to detect all
899 +    threads and stop them */
900 + static void
901 + update_stop_threads (test_pid)
902 +     int test_pid;
903 + {
904 +   struct cleanup *old_chain = NULL;
905
906 +   check_all_signal_numbers ();
907
908 +   if (linuxthreads_manager_pid == 0)
909 +     {
910 +       if (linuxthreads_manager)
911 +       {
912 +         if (test_pid > 0 && test_pid != inferior_pid)
913 +           {
914 +             old_chain = save_inferior_pid ();
915 +             inferior_pid = test_pid;
916 +           }
917 +         read_memory (linuxthreads_manager,
918 +                      (char *)&linuxthreads_manager_pid, sizeof (pid_t));
919 +       }
920 +       if (linuxthreads_initial)
921 +       {
922 +         if (test_pid > 0 && test_pid != inferior_pid)
923 +           {
924 +             old_chain = save_inferior_pid ();
925 +             inferior_pid = test_pid;
926 +           }
927 +         read_memory(linuxthreads_initial,
928 +                     (char *)&linuxthreads_initial_pid, sizeof (pid_t));
929 +       }
930 +     }
931
932 +   if (linuxthreads_manager_pid != 0)
933 +     {
934 +       if (old_chain == NULL && test_pid > 0 &&
935 +         test_pid != inferior_pid && linuxthreads_thread_alive (test_pid))
936 +       {
937 +         old_chain = save_inferior_pid ();
938 +         inferior_pid = test_pid;
939 +       }
940
941 +       if (linuxthreads_thread_alive (inferior_pid))
942 +       {
943 +         if (test_pid > 0)
944 +           {
945 +             if (test_pid != linuxthreads_manager_pid
946 +                 && !linuxthreads_pending_status (linuxthreads_manager_pid))
947 +               {
948 +                 stop_thread (linuxthreads_manager_pid);
949 +                 wait_thread (linuxthreads_manager_pid);
950 +               }
951 +             if (!in_thread_list (test_pid))
952 +               {
953 +                 if (!linuxthreads_attach_pending)
954 +                   printf_unfiltered ("[New %s]\n",
955 +                                      target_pid_to_str (test_pid));
956 +                 add_thread (test_pid);
957 +                 if (linuxthreads_sig_debug.signal
958 +                     && inferior_pid == test_pid)
959 +                   /* After a new thread in glibc 2.1 signals gdb its
960 +                      existence, it suspends itself and wait for
961 +                      linuxthreads_sig_restart, now we can wake up
962 +                      it. */
963 +                   kill (test_pid, linuxthreads_sig_restart.signal);
964 +               }
965 +           }
966 +         iterate_active_threads (stop_thread, 0);
967 +         iterate_active_threads (wait_thread, 0);
968 +       }
969 +     }
970
971 +   if (old_chain != NULL)
972 +     do_cleanups (old_chain);
973 + }
974
975 + /* This routine is called whenever a new symbol table is read in, or when all
976 +    symbol tables are removed.  libpthread can only be initialized when it
977 +    finds the right variables in libpthread.so.  Since it's a shared library,
978 +    those variables don't show up until the library gets mapped and the symbol
979 +    table is read in.  */
980
981 + void
982 + linuxthreads_new_objfile (objfile)
983 +     struct objfile *objfile;
984 + {
985 +   struct minimal_symbol *ms;
986
987 +   if (!objfile)
988 +     {
989 +       /* We're starting an entirely new executable, so we can no
990 +        longer be sure that it uses LinuxThreads.  Restore the signal
991 +        flags to their original states.  */
992 +       restore_all_signals ();
993
994 +       /* Indicate that we don't know anything's address any more.  */
995 +       linuxthreads_max = 0;
996
997 +       return;
998 +     }
999
1000 +   /* If we've already found our variables in another objfile, don't
1001 +      bother looking for them again.  */
1002 +   if (linuxthreads_max)
1003 +     return;
1004
1005 +   if (! lookup_minimal_symbol ("__pthread_initial_thread", NULL, objfile))
1006 +     /* This object file isn't the pthreads library.  */
1007 +     return;
1008
1009 +   if ((ms = lookup_minimal_symbol ("__pthread_threads_debug",
1010 +                                  NULL, objfile)) == NULL)
1011 +     {
1012 +       /* The debugging-aware libpthreads is not present in this objfile */
1013 +       warning ("\
1014 + This program seems to use POSIX threads, but the thread library used\n\
1015 + does not support debugging.  This may make using GDB difficult.  Don't\n\
1016 + set breakpoints or single-step through code that might be executed by\n\
1017 + any thread other than the main thread.");
1018 +       return;
1019 +     }
1020 +   linuxthreads_debug = SYMBOL_VALUE_ADDRESS (ms);
1021
1022 +   /* Read internal structures configuration */
1023 +   if ((ms = lookup_minimal_symbol ("__pthread_sizeof_handle",
1024 +                                  NULL, objfile)) == NULL
1025 +       || target_read_memory (SYMBOL_VALUE_ADDRESS (ms),
1026 +                            (char *)&linuxthreads_sizeof_handle,
1027 +                            sizeof (linuxthreads_sizeof_handle)) != 0)
1028 +     {
1029 +       fprintf_unfiltered (gdb_stderr,
1030 +                         "Unable to find linuxthreads symbol \"%s\"\n",
1031 +                         "__pthread_sizeof_handle");
1032 +       return;
1033 +     }
1034
1035 +   if ((ms = lookup_minimal_symbol ("__pthread_offsetof_descr",
1036 +                                  NULL, objfile)) == NULL
1037 +       || target_read_memory (SYMBOL_VALUE_ADDRESS (ms),
1038 +                            (char *)&linuxthreads_offset_descr,
1039 +                            sizeof (linuxthreads_offset_descr)) != 0)
1040 +     {
1041 +       fprintf_unfiltered (gdb_stderr,
1042 +                         "Unable to find linuxthreads symbol \"%s\"\n",
1043 +                         "__pthread_offsetof_descr");
1044 +       return;
1045 +     }
1046 +        
1047 +   if ((ms = lookup_minimal_symbol ("__pthread_offsetof_pid",
1048 +                                  NULL, objfile)) == NULL
1049 +       || target_read_memory (SYMBOL_VALUE_ADDRESS (ms),
1050 +                            (char *)&linuxthreads_offset_pid,
1051 +                            sizeof (linuxthreads_offset_pid)) != 0)
1052 +     {
1053 +       fprintf_unfiltered (gdb_stderr,
1054 +                         "Unable to find linuxthreads symbol \"%s\"\n",
1055 +                         "__pthread_offsetof_pid");
1056 +       return;
1057 +     }
1058
1059 +   if (! find_all_signal_vars (objfile))
1060 +     return;
1061
1062 +   /* Read adresses of internal structures to access */
1063 +   if ((ms = lookup_minimal_symbol ("__pthread_handles",
1064 +                                  NULL, objfile)) == NULL)
1065 +     {
1066 +       fprintf_unfiltered (gdb_stderr,
1067 +                         "Unable to find linuxthreads symbol \"%s\"\n",
1068 +                         "__pthread_handles");
1069 +       return;
1070 +     }
1071 +   linuxthreads_handles = SYMBOL_VALUE_ADDRESS (ms);
1072
1073 +   if ((ms = lookup_minimal_symbol ("__pthread_handles_num",
1074 +                                  NULL, objfile)) == NULL)
1075 +     {
1076 +       fprintf_unfiltered (gdb_stderr,
1077 +                         "Unable to find linuxthreads symbol \"%s\"\n",
1078 +                         "__pthread_handles_num");
1079 +       return;
1080 +     }
1081 +   linuxthreads_num = SYMBOL_VALUE_ADDRESS (ms);
1082
1083 +   if ((ms = lookup_minimal_symbol ("__pthread_manager_thread",
1084 +                                  NULL, objfile)) == NULL)
1085 +     {
1086 +       fprintf_unfiltered (gdb_stderr,
1087 +                         "Unable to find linuxthreads symbol \"%s\"\n",
1088 +                         "__pthread_manager_thread");
1089 +       return;
1090 +     }
1091 +   linuxthreads_manager = SYMBOL_VALUE_ADDRESS (ms) + linuxthreads_offset_pid;
1092
1093 +   if ((ms = lookup_minimal_symbol ("__pthread_initial_thread",
1094 +                                  NULL, objfile)) == NULL)
1095 +     {
1096 +       fprintf_unfiltered (gdb_stderr,
1097 +                         "Unable to find linuxthreads symbol \"%s\"\n",
1098 +                         "__pthread_initial_thread");
1099 +       return;
1100 +     }
1101 +   linuxthreads_initial = SYMBOL_VALUE_ADDRESS (ms) + linuxthreads_offset_pid;
1102
1103 +   /* Search for this last, so it won't be set to a non-zero value unless
1104 +      we successfully found all the symbols above.  */
1105 +   if ((ms = lookup_minimal_symbol ("__pthread_threads_max",
1106 +                                  NULL, objfile)) == NULL
1107 +       || target_read_memory (SYMBOL_VALUE_ADDRESS (ms),
1108 +                            (char *)&linuxthreads_max,
1109 +                            sizeof (linuxthreads_max)) != 0)
1110 +     {
1111 +       fprintf_unfiltered (gdb_stderr,
1112 +                         "Unable to find linuxthreads symbol \"%s\"\n",
1113 +                         "__pthread_threads_max");
1114 +       return;
1115 +     }
1116
1117 +   /* Allocate gdb internal structures */
1118 +   linuxthreads_wait_pid = 
1119 +     (int *)xmalloc (sizeof (int) * (linuxthreads_max + 1));
1120 +   linuxthreads_wait_status =
1121 +     (int *)xmalloc (sizeof (int) * (linuxthreads_max + 1));
1122 +   linuxthreads_breakpoint_zombie = (struct linuxthreads_breakpoint *)
1123 +     xmalloc (sizeof (struct linuxthreads_breakpoint) * (linuxthreads_max + 1));
1124
1125 +   if (inferior_pid && !linuxthreads_attach_pending)
1126 +     {
1127 +       int on = 1;
1128 +       target_write_memory (linuxthreads_debug, (char *)&on, sizeof (on));
1129 +       linuxthreads_attach_pending = 1;
1130 +       update_stop_threads (inferior_pid);
1131 +       linuxthreads_attach_pending = 0;
1132 +     }
1133 + }
1134
1135 + /* If we have switched threads from a one that stopped at breakpoint,
1136 +    return 1 otherwise 0.  */
1137
1138 + int
1139 + linuxthreads_prepare_to_proceed (step)
1140 +     int step;
1141 + {
1142 +   if (!linuxthreads_max
1143 +       || !linuxthreads_manager_pid
1144 +       || !linuxthreads_breakpoint_pid
1145 +       || !breakpoint_here_p (read_pc_pid (linuxthreads_breakpoint_pid)))
1146 +     return 0;
1147
1148 +   if (step)
1149 +     {
1150 +       /* Mark the current inferior as single stepping process.  */
1151 +       linuxthreads_step_pid = inferior_pid;
1152 +     }
1153
1154 +   linuxthreads_inferior_pid = linuxthreads_breakpoint_pid;
1155 +   return linuxthreads_breakpoint_pid;
1156 + }
1157
1158 + /* Convert a pid to printable form. */
1159
1160 + char *
1161 + linuxthreads_pid_to_str (pid)
1162 +     int pid;
1163 + {
1164 +   static char buf[100];
1165
1166 +   sprintf (buf, "%s %d%s", linuxthreads_max ? "Thread" : "Pid", pid,
1167 +          (pid == linuxthreads_manager_pid) ? " (manager thread)"
1168 +          : (pid == linuxthreads_initial_pid) ? " (initial thread)"
1169 +          : "");
1170
1171 +   return buf;
1172 + }
1173
1174 + /* Attach to process PID, then initialize for debugging it
1175 +    and wait for the trace-trap that results from attaching.  */
1176
1177 + static void
1178 + linuxthreads_attach (args, from_tty)
1179 +     char *args;
1180 +     int from_tty;
1181 + {
1182 +   if (!args)
1183 +     error_no_arg ("process-id to attach");
1184
1185 +   push_target (&linuxthreads_ops);
1186 +   linuxthreads_breakpoints_inserted = 1;
1187 +   linuxthreads_breakpoint_last = -1;
1188 +   linuxthreads_wait_last = -1;
1189 +   linuxthreads_exit_status = __W_STOPCODE(0);
1190
1191 +   child_ops.to_attach (args, from_tty);
1192
1193 +   if (linuxthreads_max)
1194 +     linuxthreads_attach_pending = 1;
1195 + }
1196
1197 + /* Take a program previously attached to and detaches it.
1198 +    The program resumes execution and will no longer stop
1199 +    on signals, etc.  We'd better not have left any breakpoints
1200 +    in the program or it'll die when it hits one.  For this
1201 +    to work, it may be necessary for the process to have been
1202 +    previously attached.  It *might* work if the program was
1203 +    started via the normal ptrace (PTRACE_TRACEME).  */
1204
1205 + static void
1206 + linuxthreads_detach (args, from_tty)
1207 +     char *args;
1208 +     int from_tty;
1209 + {
1210 +   if (linuxthreads_max)
1211 +     {
1212 +       int i;
1213 +       int pid;
1214 +       int off = 0;
1215 +       target_write_memory (linuxthreads_debug, (char *)&off, sizeof (off));
1216
1217 +       /* Walk through linuxthreads array in order to detach known threads.  */
1218 +       if (linuxthreads_manager_pid != 0)
1219 +       {
1220 +         /* Get rid of all positive zombie breakpoints.  */
1221 +         for (i = 0; i <= linuxthreads_breakpoint_last; i++)
1222 +           {
1223 +             if (linuxthreads_breakpoint_zombie[i].step)
1224 +               continue;
1225
1226 +             pid = linuxthreads_breakpoint_zombie[i].pid;
1227 +             if (!linuxthreads_thread_alive (pid))
1228 +               continue;
1229
1230 +             if (linuxthreads_breakpoint_zombie[i].pc != read_pc_pid (pid))
1231 +               continue;
1232
1233 +             /* Continue in STEP mode until the thread pc has moved or
1234 +                until SIGTRAP is found on the same PC.  */
1235 +             if (linuxthreads_find_trap (pid, 0)
1236 +                 && linuxthreads_breakpoint_zombie[i].pc == read_pc_pid (pid))
1237 +               write_pc_pid (linuxthreads_breakpoint_zombie[i].pc
1238 +                             - DECR_PC_AFTER_BREAK, pid);
1239 +           }
1240
1241 +         /* Detach thread after thread.  */
1242 +         inferior_pid = linuxthreads_manager_pid;
1243 +         iterate_active_threads (detach_thread, 1);
1244
1245 +         /* Remove pending SIGTRAP and SIGSTOP */
1246 +         linuxthreads_find_trap (inferior_pid, 1);
1247
1248 +         linuxthreads_wait_last = -1;
1249 +         linuxthreads_exit_status = __W_STOPCODE(0);
1250 +       }
1251
1252 +       linuxthreads_inferior_pid = 0;
1253 +       linuxthreads_breakpoint_pid = 0;
1254 +       linuxthreads_step_pid = 0;
1255 +       linuxthreads_step_signo = TARGET_SIGNAL_0;
1256 +       linuxthreads_manager_pid = 0;
1257 +       linuxthreads_initial_pid = 0;
1258 +       linuxthreads_attach_pending = 0;
1259 +       init_thread_list ();           /* Destroy thread info */
1260 +     }
1261
1262 +   child_ops.to_detach (args, from_tty);
1263
1264 +   unpush_target (&linuxthreads_ops);
1265 + }
1266
1267 + /* Resume execution of process PID.  If STEP is nozero, then
1268 +    just single step it.  If SIGNAL is nonzero, restart it with that
1269 +    signal activated.  */
1270
1271 + static void
1272 + linuxthreads_resume (pid, step, signo)
1273 +     int pid;
1274 +     int step;
1275 +     enum target_signal signo;
1276 + {
1277 +   if (!linuxthreads_max || stop_soon_quietly || linuxthreads_manager_pid == 0)
1278 +     child_ops.to_resume (pid, step, signo);
1279 +   else
1280 +     {
1281 +       int rpid;
1282 +       if (linuxthreads_inferior_pid)
1283 +       {
1284 +         /* Prepare resume of the last thread that hit a breakpoint */
1285 +         linuxthreads_breakpoints_inserted = 0;
1286 +         rpid = linuxthreads_inferior_pid;
1287 +         linuxthreads_step_signo = signo;
1288 +       }
1289 +       else
1290 +         {
1291 +         struct cleanup *old_chain = NULL;
1292 +         int i;
1293
1294 +         if (pid < 0)
1295 +           {
1296 +             linuxthreads_step_pid = step ? inferior_pid : 0;
1297 +             linuxthreads_step_signo = signo;
1298 +             rpid = inferior_pid;
1299 +           }
1300 +         else
1301 +           rpid = pid;
1302
1303 +         if (pid < 0 || !step)
1304 +           {
1305 +             linuxthreads_breakpoints_inserted = 1;
1306
1307 +             /* Walk through linuxthreads array in order to resume threads */
1308 +             if (pid >= 0 && inferior_pid != pid)
1309 +               {
1310 +                 old_chain = save_inferior_pid ();
1311 +                 inferior_pid = pid;
1312 +               }
1313
1314 +             iterate_active_threads (resume_thread, 0);
1315 +             if (linuxthreads_manager_pid != inferior_pid
1316 +                 && !linuxthreads_pending_status (linuxthreads_manager_pid))
1317 +               resume_thread (linuxthreads_manager_pid);
1318 +           }
1319 +         else
1320 +           linuxthreads_breakpoints_inserted = 0;
1321
1322 +         /* Deal with zombie breakpoint */
1323 +         for (i = 0; i <= linuxthreads_breakpoint_last; i++)
1324 +           if (linuxthreads_breakpoint_zombie[i].pid == rpid)
1325 +             {
1326 +               if (linuxthreads_breakpoint_zombie[i].pc != read_pc_pid (rpid))
1327 +                 {
1328 +                   /* The current pc is out of zombie breakpoint.  */
1329 +                   REMOVE_BREAKPOINT_ZOMBIE(i);
1330 +                 }
1331 +               break;
1332 +             }
1333
1334 +         if (old_chain != NULL)
1335 +           do_cleanups (old_chain);
1336 +       }
1337
1338 +       /* Resume initial thread. */
1339 +       if (!linuxthreads_pending_status (rpid))
1340 +       child_ops.to_resume (rpid, step, signo);
1341 +     }
1342 + }
1343
1344 + /* Wait for any threads to stop.  We may have to convert PID from a thread id
1345 +    to a LWP id, and vice versa on the way out.  */
1346
1347 + static int
1348 + linuxthreads_wait (int pid, struct target_waitstatus *ourstatus)
1349 + {
1350 +   int status;
1351 +   int rpid;
1352 +   int i;
1353 +   int last;
1354 +   int *wstatus;
1355
1356 +   if (linuxthreads_max && !linuxthreads_breakpoints_inserted)
1357 +     wstatus = alloca (LINUXTHREAD_NSIG * sizeof (int));
1358
1359 +   /* See if the inferior has chosen values for its signals yet.  By
1360 +      checking for them here, we can be sure we've updated GDB's signal
1361 +      handling table before the inferior ever gets one of them.  (Well,
1362 +      before we notice, anyway.)  */
1363 +   check_all_signal_numbers ();
1364
1365 +   for (;;)
1366 +     {
1367 +       if (!linuxthreads_max)
1368 +         rpid = 0;
1369 +       else if (!linuxthreads_breakpoints_inserted)
1370 +       {
1371 +         if (linuxthreads_inferior_pid)
1372 +           pid = linuxthreads_inferior_pid;
1373 +         else if (pid < 0)
1374 +           pid = inferior_pid;
1375 +         last = rpid = 0;
1376 +       }
1377 +       else if (pid < 0 && linuxthreads_wait_last >= 0)
1378 +       {
1379 +         status = linuxthreads_wait_status[linuxthreads_wait_last];
1380 +         rpid = linuxthreads_wait_pid[linuxthreads_wait_last--];
1381 +         }
1382 +       else if (pid > 0 && linuxthreads_pending_status (pid))
1383 +       {
1384 +         for (i = linuxthreads_wait_last; i >= 0; i--)
1385 +           if (linuxthreads_wait_pid[i] == pid)
1386 +               break;
1387 +         if (i < 0)
1388 +           rpid = 0;
1389 +         else
1390 +           {
1391 +             status = linuxthreads_wait_status[i];
1392 +             rpid = pid;
1393 +             if (i < linuxthreads_wait_last)
1394 +               {
1395 +                 linuxthreads_wait_status[i] =
1396 +                   linuxthreads_wait_status[linuxthreads_wait_last];
1397 +                 linuxthreads_wait_pid[i] =
1398 +                   linuxthreads_wait_pid[linuxthreads_wait_last];
1399 +               }
1400 +             linuxthreads_wait_last--;
1401 +           }
1402 +       }
1403 +       else
1404 +         rpid = 0;
1405
1406 +       if (rpid == 0)
1407 +       {
1408 +         int save_errno;
1409 +         sigset_t omask;
1410
1411 +         set_sigint_trap();    /* Causes SIGINT to be passed on to the
1412 +                                  attached process. */
1413 +         set_sigio_trap ();
1414
1415 +         sigprocmask(SIG_BLOCK, &linuxthreads_wait_mask, &omask);
1416 +         for (;;)
1417 +           {
1418 +             rpid = waitpid (pid, &status, __WCLONE | WNOHANG);
1419 +             if (rpid > 0)
1420 +               break;
1421 +             if (rpid == 0)
1422 +               save_errno = 0;
1423 +             else if (errno != EINTR)
1424 +               save_errno = errno;
1425 +             else
1426 +               continue;
1427
1428 +             rpid = waitpid (pid, &status, WNOHANG);
1429 +             if (rpid > 0)
1430 +               break;
1431 +             if (rpid < 0)
1432 +               if (errno == EINTR)
1433 +                 continue;
1434 +               else if (save_errno != 0)
1435 +                 break;
1436
1437 +             sigsuspend(&omask);
1438 +           }
1439 +         sigprocmask(SIG_SETMASK, &omask, NULL);
1440
1441 +         save_errno = errno;
1442 +         clear_sigio_trap ();
1443
1444 +         clear_sigint_trap();
1445
1446 +         if (rpid == -1)
1447 +           {
1448 +             if (WIFEXITED(linuxthreads_exit_status))
1449 +               {
1450 +                 store_waitstatus (ourstatus, linuxthreads_exit_status);
1451 +                 return inferior_pid;
1452 +               }
1453 +             else
1454 +               {
1455 +                 fprintf_unfiltered
1456 +                     (gdb_stderr, "Child process unexpectedly missing: %s.\n",
1457 +                      safe_strerror (save_errno));
1458 +                 /* Claim it exited with unknown signal.  */
1459 +                 ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
1460 +                 ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
1461 +                 return -1;
1462 +               }
1463 +           }
1464
1465 +         /* Signals arrive in any order.  So get all signals until SIGTRAP
1466 +            and resend previous ones to be held after.  */
1467 +         if (linuxthreads_max
1468 +             && !linuxthreads_breakpoints_inserted
1469 +             && WIFSTOPPED(status))
1470 +           if (WSTOPSIG(status) == SIGTRAP)
1471 +             {
1472 +               while (--last >= 0)
1473 +                 kill (rpid, WSTOPSIG(wstatus[last]));
1474
1475 +               /* insert negative zombie breakpoint */
1476 +               for (i = 0; i <= linuxthreads_breakpoint_last; i++)
1477 +                 if (linuxthreads_breakpoint_zombie[i].pid == rpid)
1478 +                     break;
1479 +               if (i > linuxthreads_breakpoint_last)
1480 +                 {
1481 +                   linuxthreads_breakpoint_zombie[i].pid = rpid;
1482 +                   linuxthreads_breakpoint_last++;
1483 +                 }
1484 +               linuxthreads_breakpoint_zombie[i].pc = read_pc_pid (rpid);
1485 +               linuxthreads_breakpoint_zombie[i].step = 1;
1486 +             }
1487 +           else
1488 +             {
1489 +               if (WSTOPSIG(status) != SIGSTOP)
1490 +                 {
1491 +                   for (i = 0; i < last; i++)
1492 +                     if (wstatus[i] == status)
1493 +                       break;
1494 +                   if (i >= last)
1495 +                     wstatus[last++] = status;
1496 +                 }
1497 +               child_resume (rpid, 1, TARGET_SIGNAL_0);
1498 +               continue;
1499 +             }
1500 +         if (linuxthreads_inferior_pid)
1501 +           linuxthreads_inferior_pid = 0;
1502 +       }
1503
1504 +       if (linuxthreads_max && !stop_soon_quietly)
1505 +       {
1506 +         if (linuxthreads_max
1507 +             && WIFSTOPPED(status)
1508 +             && WSTOPSIG(status) == SIGSTOP)
1509 +           {
1510 +             /* Skip SIGSTOP signals.  */
1511 +             if (!linuxthreads_pending_status (rpid))
1512 +               if (linuxthreads_step_pid == rpid)
1513 +                 child_resume (rpid, 1, linuxthreads_step_signo);
1514 +               else
1515 +                 child_resume (rpid, 0, TARGET_SIGNAL_0);
1516 +             continue;
1517 +           }
1518
1519 +         /* Do no report exit status of cloned threads.  */
1520 +         if (WIFEXITED(status))
1521 +           {
1522 +             if (rpid == linuxthreads_initial_pid)
1523 +               linuxthreads_exit_status = status;
1524
1525 +             /* Remove any zombie breakpoint.  */
1526 +             for (i = 0; i <= linuxthreads_breakpoint_last; i++)
1527 +               if (linuxthreads_breakpoint_zombie[i].pid == rpid)
1528 +                 {
1529 +                   REMOVE_BREAKPOINT_ZOMBIE(i);
1530 +                   break;
1531 +                 }
1532 +             if (pid > 0)
1533 +               pid = -1;
1534 +             continue;
1535 +           }
1536
1537 +         /* Deal with zombie breakpoint */
1538 +         for (i = 0; i <= linuxthreads_breakpoint_last; i++)
1539 +           if (linuxthreads_breakpoint_zombie[i].pid == rpid)
1540 +             break;
1541
1542 +         if (i <= linuxthreads_breakpoint_last)
1543 +           {
1544 +             /* There is a potential zombie breakpoint */
1545 +             if (WIFEXITED(status)
1546 +                 || linuxthreads_breakpoint_zombie[i].pc != read_pc_pid (rpid))
1547 +               {
1548 +                 /* The current pc is out of zombie breakpoint.  */
1549 +                 REMOVE_BREAKPOINT_ZOMBIE(i);
1550 +               }
1551 +             else if (!linuxthreads_breakpoint_zombie[i].step
1552 +                      && WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP)
1553 +               {
1554 +                 /* This is a real one ==> decrement PC and restart.  */
1555 +                 write_pc_pid (linuxthreads_breakpoint_zombie[i].pc
1556 +                               - DECR_PC_AFTER_BREAK, rpid);
1557 +                 if (linuxthreads_step_pid == rpid)
1558 +                   child_resume (rpid, 1, linuxthreads_step_signo);
1559 +                 else
1560 +                   child_resume (rpid, 0, TARGET_SIGNAL_0);
1561 +                 continue;
1562 +               }
1563 +           }
1564
1565 +         /* Walk through linuxthreads array in order to stop them */
1566 +         if (linuxthreads_breakpoints_inserted)
1567 +           update_stop_threads (rpid);
1568
1569 +       }
1570 +       else if (rpid != inferior_pid)
1571 +       continue;
1572
1573 +       store_waitstatus (ourstatus, status);
1574
1575 +       if (linuxthreads_attach_pending && !stop_soon_quietly)
1576 +         {
1577 +         int on = 1;
1578 +         target_write_memory (linuxthreads_debug, (char *)&on, sizeof (on));
1579 +         update_stop_threads (rpid);
1580 +         linuxthreads_attach_pending = 0;
1581 +         }
1582
1583 +       if (linuxthreads_breakpoints_inserted
1584 +         && WIFSTOPPED(status)
1585 +         && WSTOPSIG(status) == SIGTRAP)
1586 +       linuxthreads_breakpoint_pid = rpid;
1587 +       else if (linuxthreads_breakpoint_pid)
1588 +       linuxthreads_breakpoint_pid = 0;
1589
1590 +       return rpid;
1591 +     }
1592 + }
1593
1594 + /* Fork an inferior process, and start debugging it with ptrace.  */
1595
1596 + static void
1597 + linuxthreads_create_inferior (exec_file, allargs, env)
1598 +     char *exec_file;
1599 +     char *allargs;
1600 +     char **env;
1601 + {
1602 +   if (!exec_file && !exec_bfd)
1603 +     {
1604 +       error ("No executable file specified.\n\
1605 + Use the \"file\" or \"exec-file\" command.");
1606 +       return;
1607 +     }
1608
1609 +   push_target (&linuxthreads_ops);
1610 +   linuxthreads_breakpoints_inserted = 1;
1611 +   linuxthreads_breakpoint_last = -1;
1612 +   linuxthreads_wait_last = -1;
1613 +   linuxthreads_exit_status = __W_STOPCODE(0);
1614 +   
1615 +   if (linuxthreads_max)
1616 +     linuxthreads_attach_pending = 1;
1617
1618 +   child_ops.to_create_inferior (exec_file, allargs, env);
1619 + }
1620
1621 + /* Clean up after the inferior dies.  */
1622
1623 + static void
1624 + linuxthreads_mourn_inferior ()
1625 + {
1626 +   if (linuxthreads_max)
1627 +     {
1628 +       int off = 0;
1629 +       target_write_memory (linuxthreads_debug, (char *)&off, sizeof (off));
1630
1631 +       linuxthreads_inferior_pid = 0;
1632 +       linuxthreads_breakpoint_pid = 0;
1633 +       linuxthreads_step_pid = 0;
1634 +       linuxthreads_step_signo = TARGET_SIGNAL_0;
1635 +       linuxthreads_manager_pid = 0;
1636 +       linuxthreads_initial_pid = 0;
1637 +       linuxthreads_attach_pending = 0;
1638 +       init_thread_list();           /* Destroy thread info */
1639 +     }
1640
1641 +   child_ops.to_mourn_inferior ();
1642
1643 +   unpush_target (&linuxthreads_ops);
1644 + }
1645
1646 + /* Kill the inferior process */
1647
1648 + static void
1649 + linuxthreads_kill ()
1650 + {
1651 +   int rpid;
1652 +   int status;
1653
1654 +   if (inferior_pid == 0)
1655 +     return;
1656
1657 +   if (linuxthreads_max && linuxthreads_manager_pid != 0)
1658 +     {
1659 +       /* Remove all threads status.  */
1660 +       inferior_pid = linuxthreads_manager_pid;
1661 +       iterate_active_threads (kill_thread, 1);
1662 +     }
1663
1664 +   kill_thread (inferior_pid);
1665
1666 + #if 0
1667 +   /* doing_quit_force solves a real problem, but I think a properly
1668 +      placed call to catch_errors would do the trick much more cleanly.  */
1669 +   if (doing_quit_force >= 0)
1670 +     {
1671 +       if (linuxthreads_max && linuxthreads_manager_pid != 0)
1672 +       {
1673 +         /* Wait for thread to complete */
1674 +         while ((rpid = waitpid (-1, &status, __WCLONE)) > 0)
1675 +           if (!WIFEXITED(status))
1676 +             kill_thread (rpid);
1677
1678 +         while ((rpid = waitpid (-1, &status, 0)) > 0)
1679 +           if (!WIFEXITED(status))
1680 +             kill_thread (rpid);
1681 +       }
1682 +       else
1683 +       while ((rpid = waitpid (inferior_pid, &status, 0)) > 0)
1684 +         if (!WIFEXITED(status))
1685 +           ptrace (PT_KILL, inferior_pid, (PTRACE_ARG3_TYPE) 0, 0);
1686 +     }
1687 + #endif
1688
1689 +   /* Wait for all threads. */
1690 +   do
1691 +     rpid = waitpid (-1, &status, __WCLONE | WNOHANG);
1692 +   while (rpid > 0 || errno == EINTR);
1693
1694 +   do
1695 +     rpid = waitpid (-1, &status, WNOHANG);
1696 +   while (rpid > 0 || errno == EINTR);
1697
1698 +   linuxthreads_mourn_inferior ();
1699 + }
1700
1701 + /* Insert a breakpoint */
1702
1703 + static int
1704 + linuxthreads_insert_breakpoint (addr, contents_cache)
1705 +     CORE_ADDR addr;
1706 +     char *contents_cache;
1707 + {
1708 +   if (linuxthreads_max && linuxthreads_manager_pid != 0)
1709 +     {
1710 +       linuxthreads_breakpoint_addr = addr;
1711 +       iterate_active_threads (insert_breakpoint, 1);
1712 +       insert_breakpoint (linuxthreads_manager_pid);
1713 +     }
1714
1715 +   return child_ops.to_insert_breakpoint (addr, contents_cache);
1716 + }
1717
1718 + /* Remove a breakpoint */
1719
1720 + static int
1721 + linuxthreads_remove_breakpoint (addr, contents_cache)
1722 +     CORE_ADDR addr;
1723 +     char *contents_cache;
1724 + {
1725 +   if (linuxthreads_max && linuxthreads_manager_pid != 0)
1726 +     {
1727 +       linuxthreads_breakpoint_addr = addr;
1728 +       iterate_active_threads (remove_breakpoint, 1);
1729 +       remove_breakpoint (linuxthreads_manager_pid);
1730 +     }
1731
1732 +   return child_ops.to_remove_breakpoint (addr, contents_cache);
1733 + }
1734
1735 + /* Mark our target-struct as eligible for stray "run" and "attach" commands.  */
1736
1737 + static int
1738 + linuxthreads_can_run ()
1739 + {
1740 +   return child_suppress_run;
1741 + }
1742\f
1743 + static void
1744 + init_linuxthreads_ops ()
1745 + {
1746 +   linuxthreads_ops.to_shortname = "linuxthreads";
1747 +   linuxthreads_ops.to_longname  = "LINUX threads and pthread.";
1748 +   linuxthreads_ops.to_doc       = "LINUX threads and pthread support.";
1749 +   linuxthreads_ops.to_attach    = linuxthreads_attach;
1750 +   linuxthreads_ops.to_detach    = linuxthreads_detach;
1751 +   linuxthreads_ops.to_resume    = linuxthreads_resume;
1752 +   linuxthreads_ops.to_wait      = linuxthreads_wait;
1753 +   linuxthreads_ops.to_kill      = linuxthreads_kill;
1754 +   linuxthreads_ops.to_can_run   = linuxthreads_can_run;
1755 +   linuxthreads_ops.to_stratum   = thread_stratum;
1756 +   linuxthreads_ops.to_insert_breakpoint = linuxthreads_insert_breakpoint;
1757 +   linuxthreads_ops.to_remove_breakpoint = linuxthreads_remove_breakpoint;
1758 +   linuxthreads_ops.to_create_inferior   = linuxthreads_create_inferior;
1759 +   linuxthreads_ops.to_mourn_inferior    = linuxthreads_mourn_inferior;
1760 +   linuxthreads_ops.to_thread_alive      = linuxthreads_thread_alive;
1761 +   linuxthreads_ops.to_magic             = OPS_MAGIC;
1762 + }
1763
1764 + void
1765 + _initialize_linuxthreads ()
1766 + {
1767 +   struct sigaction sact;
1768
1769 +   init_linuxthreads_ops ();
1770 +   add_target (&linuxthreads_ops);
1771 +   child_suppress_run = 1;
1772
1773 +   /* Attach SIGCHLD handler */
1774 +   sact.sa_handler = sigchld_handler;
1775 +   sigemptyset (&sact.sa_mask);
1776 +   sact.sa_flags = 0;
1777 +   sigaction (SIGCHLD, &sact, NULL);
1778
1779 +   /* initialize SIGCHLD mask */
1780 +   sigemptyset (&linuxthreads_wait_mask);
1781 +   sigaddset (&linuxthreads_wait_mask, SIGCHLD);
1782 + }
1783 diff -Ncr /home/kingdon/work/gdb/gdb/target.c ./gdb/target.c
1784 *** /home/kingdon/work/gdb/gdb/target.c Thu Aug 12 11:13:38 1999
1785 --- ./gdb/target.c      Sat Aug 14 19:49:45 1999
1786 ***************
1787 *** 1238,1243 ****
1788 --- 1238,1244 ----
1789     {"SIG61", "Real-time event 61"},
1790     {"SIG62", "Real-time event 62"},
1791     {"SIG63", "Real-time event 63"},
1792 +   {"SIG32", "Real-time event 32"},
1793   
1794   #if defined(MACH) || defined(__MACH__)
1795     /* Mach exceptions */
1796 ***************
1797 *** 1571,1578 ****
1798   
1799   #if defined (REALTIME_LO)
1800     if (hostsig >= REALTIME_LO && hostsig < REALTIME_HI)
1801 !     return (enum target_signal)
1802 !       (hostsig - 33 + (int) TARGET_SIGNAL_REALTIME_33);
1803   #endif
1804     return TARGET_SIGNAL_UNKNOWN;
1805   }
1806 --- 1572,1587 ----
1807   
1808   #if defined (REALTIME_LO)
1809     if (hostsig >= REALTIME_LO && hostsig < REALTIME_HI)
1810 !     {
1811 !       /* This block of TARGET_SIGNAL_REALTIME value is in order.  */
1812 !       if (33 <= hostsig && hostsig <= 63)
1813 !       return (enum target_signal)
1814 !         (hostsig - 33 + (int) TARGET_SIGNAL_REALTIME_33);
1815 !       else if (hostsig == 32)
1816 !       return TARGET_SIGNAL_REALTIME_32;
1817 !       else
1818 !       error ("GDB bug: target.c (target_signal_from_host): unrecognized real-time signal");
1819 !     }
1820   #endif
1821     return TARGET_SIGNAL_UNKNOWN;
1822   }
1823 ***************
1824 *** 1619,1624 ****
1825 --- 1628,1635 ----
1826       case TARGET_SIGNAL_PRIO:
1827         return SIGPRIO;
1828   #endif
1829
1830 +     case TARGET_SIGNAL_REALTIME_32: return 32; /* by definition */ 
1831   
1832         /* Mach exceptions.  Assumes that the values for EXC_ are positive! */
1833   #if defined (EXC_BAD_ACCESS) && defined (_NSIG)
1834 diff -Ncr /home/kingdon/work/gdb/gdb/target.h ./gdb/target.h
1835 *** /home/kingdon/work/gdb/gdb/target.h Thu Aug 12 11:13:38 1999
1836 --- ./gdb/target.h      Sat Aug 14 19:07:48 1999
1837 ***************
1838 *** 48,54 ****
1839         file_stratum,           /* Executable files, etc */
1840         core_stratum,           /* Core dump files */
1841         download_stratum,       /* Downloading of remote targets */
1842 !       process_stratum         /* Executing processes */
1843   };
1844   
1845   enum thread_control_capabilities {
1846 --- 48,55 ----
1847         file_stratum,           /* Executable files, etc */
1848         core_stratum,           /* Core dump files */
1849         download_stratum,       /* Downloading of remote targets */
1850 !       process_stratum,        /* Executing processes */
1851 !       thread_stratum          /* Executing threads */
1852   };
1853   
1854   enum thread_control_capabilities {
1855 ***************
1856 *** 214,219 ****
1857 --- 215,227 ----
1858     TARGET_EXC_SOFTWARE = 80,
1859     TARGET_EXC_BREAKPOINT = 81,
1860   #endif
1861
1862 +   /* Yes, this pains me, too.  But LynxOS didn't have SIG32, and now
1863 +      Linux does, and we can't disturb the numbering, since it's part
1864 +      of the protocol.  Note that in some GDB's TARGET_SIGNAL_REALTIME_32
1865 +      is number 76.  */
1866 +   TARGET_SIGNAL_REALTIME_32,
1867
1868     /* Some signal we don't know about.  */
1869     TARGET_SIGNAL_UNKNOWN,
1870   
This page took 0.161375 seconds and 3 git commands to generate.