146283Sdfr/* Low level Unix child interface to ttrace, for GDB when running under HP-UX.
298944Sobrien   Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998,
3130803Smarcel   1999, 2000, 2001, 2003
446283Sdfr   Free Software Foundation, Inc.
546283Sdfr
698944Sobrien   This file is part of GDB.
746283Sdfr
898944Sobrien   This program is free software; you can redistribute it and/or modify
998944Sobrien   it under the terms of the GNU General Public License as published by
1098944Sobrien   the Free Software Foundation; either version 2 of the License, or
1198944Sobrien   (at your option) any later version.
1246283Sdfr
1398944Sobrien   This program is distributed in the hope that it will be useful,
1498944Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1598944Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1698944Sobrien   GNU General Public License for more details.
1746283Sdfr
1898944Sobrien   You should have received a copy of the GNU General Public License
1998944Sobrien   along with this program; if not, write to the Free Software
2098944Sobrien   Foundation, Inc., 59 Temple Place - Suite 330,
2198944Sobrien   Boston, MA 02111-1307, USA.  */
2246283Sdfr
2346283Sdfr#include "defs.h"
2446283Sdfr#include "frame.h"
2546283Sdfr#include "inferior.h"
2646283Sdfr#include "target.h"
2746283Sdfr#include "gdb_string.h"
2898944Sobrien#include "gdb_wait.h"
2946283Sdfr#include "command.h"
30130803Smarcel#include "gdbthread.h"
3146283Sdfr
3298944Sobrien/* We need pstat functionality so that we can get the exec file
3398944Sobrien   for a process we attach to.
3498944Sobrien
3598944Sobrien   According to HP, we should use the 64bit interfaces, so we
3698944Sobrien   define _PSTAT64 to achieve this.  */
3798944Sobrien#define _PSTAT64
3898944Sobrien#include <sys/pstat.h>
3998944Sobrien
4046283Sdfr/* Some hackery to work around a use of the #define name NO_FLAGS
4146283Sdfr * in both gdb and HPUX (bfd.h and /usr/include/machine/vmparam.h).
4246283Sdfr */
4346283Sdfr#ifdef  NO_FLAGS
4446283Sdfr#define INFTTRACE_TEMP_HACK NO_FLAGS
4546283Sdfr#undef  NO_FLAGS
4646283Sdfr#endif
4746283Sdfr
4846283Sdfr#ifdef USG
4946283Sdfr#include <sys/types.h>
5046283Sdfr#endif
5146283Sdfr
5246283Sdfr#include <sys/param.h>
5346283Sdfr#include <sys/dir.h>
5446283Sdfr#include <signal.h>
5546283Sdfr#include <sys/ioctl.h>
5646283Sdfr
5746283Sdfr#include <sys/ttrace.h>
5846283Sdfr#include <sys/mman.h>
5946283Sdfr
6046283Sdfr#ifndef NO_PTRACE_H
6146283Sdfr#ifdef PTRACE_IN_WRONG_PLACE
6246283Sdfr#include <ptrace.h>
6346283Sdfr#else
6446283Sdfr#include <sys/ptrace.h>
6546283Sdfr#endif
6646283Sdfr#endif /* NO_PTRACE_H */
6746283Sdfr
6846283Sdfr/* Second half of the hackery above.  Non-ANSI C, so
6946283Sdfr * we can't use "#error", alas.
7046283Sdfr */
7146283Sdfr#ifdef NO_FLAGS
7246283Sdfr#if (NO_FLAGS != INFTTRACE_TEMP_HACK )
7346283Sdfr  /* #error "Hackery to remove warning didn't work right" */
7446283Sdfr#else
7546283Sdfr  /* Ok, new def'n of NO_FLAGS is same as old one; no action needed. */
7646283Sdfr#endif
7746283Sdfr#else
7846283Sdfr  /* #error "Didn't get expected re-definition of NO_FLAGS" */
7946283Sdfr#define NO_FLAGS INFTTRACE_TEMP_HACK
8046283Sdfr#endif
8146283Sdfr
8246283Sdfr#if !defined (PT_SETTRC)
8346283Sdfr#define PT_SETTRC	0	/* Make process traceable by parent */
8446283Sdfr#endif
8546283Sdfr#if !defined (PT_READ_I)
8646283Sdfr#define PT_READ_I	1	/* Read word from text space */
8746283Sdfr#endif
8846283Sdfr#if !defined (PT_READ_D)
8946283Sdfr#define	PT_READ_D	2	/* Read word from data space */
9046283Sdfr#endif
9146283Sdfr#if !defined (PT_READ_U)
9246283Sdfr#define PT_READ_U	3	/* Read word from kernel user struct */
9346283Sdfr#endif
9446283Sdfr#if !defined (PT_WRITE_I)
9546283Sdfr#define PT_WRITE_I	4	/* Write word to text space */
9646283Sdfr#endif
9746283Sdfr#if !defined (PT_WRITE_D)
9846283Sdfr#define PT_WRITE_D	5	/* Write word to data space */
9946283Sdfr#endif
10046283Sdfr#if !defined (PT_WRITE_U)
10146283Sdfr#define PT_WRITE_U	6	/* Write word to kernel user struct */
10246283Sdfr#endif
10346283Sdfr#if !defined (PT_CONTINUE)
10446283Sdfr#define PT_CONTINUE	7	/* Continue after signal */
10546283Sdfr#endif
10646283Sdfr#if !defined (PT_STEP)
10746283Sdfr#define PT_STEP		9	/* Set flag for single stepping */
10846283Sdfr#endif
10946283Sdfr#if !defined (PT_KILL)
11046283Sdfr#define PT_KILL		8	/* Send child a SIGKILL signal */
11146283Sdfr#endif
11246283Sdfr
11346283Sdfr#ifndef PT_ATTACH
11446283Sdfr#define PT_ATTACH PTRACE_ATTACH
11546283Sdfr#endif
11646283Sdfr#ifndef PT_DETACH
11746283Sdfr#define PT_DETACH PTRACE_DETACH
11846283Sdfr#endif
11946283Sdfr
12046283Sdfr#include "gdbcore.h"
12146283Sdfr#ifndef	NO_SYS_FILE
12246283Sdfr#include <sys/file.h>
12346283Sdfr#endif
12446283Sdfr
12546283Sdfr/* This semaphore is used to coordinate the child and parent processes
12646283Sdfr   after a fork(), and before an exec() by the child.  See parent_attach_all
12746283Sdfr   for details.
12898944Sobrien */
12998944Sobrientypedef struct
13098944Sobrien  {
13198944Sobrien    int parent_channel[2];	/* Parent "talks" to [1], child "listens" to [0] */
13298944Sobrien    int child_channel[2];	/* Child "talks" to [1], parent "listens" to [0] */
13398944Sobrien  }
13498944Sobrienstartup_semaphore_t;
13546283Sdfr
13646283Sdfr#define SEM_TALK (1)
13746283Sdfr#define SEM_LISTEN (0)
13846283Sdfr
13998944Sobrienstatic startup_semaphore_t startup_semaphore;
14046283Sdfr
14146283Sdfr/* See can_touch_threads_of_process for details. */
14298944Sobrienstatic int vforking_child_pid = 0;
14398944Sobrienstatic int vfork_in_flight = 0;
14446283Sdfr
14546283Sdfr/* 1 if ok as results of a ttrace or ttrace_wait call, 0 otherwise.
14646283Sdfr */
14746283Sdfr#define TT_OK( _status, _errno ) \
14846283Sdfr    (((_status) == 1) && ((_errno) == 0))
14946283Sdfr
15046283Sdfr#define TTRACE_ARG_TYPE uint64_t
15146283Sdfr
15246283Sdfr/* When supplied as the "addr" operand, ttrace interprets this
15346283Sdfr   to mean, "from the current address".
15498944Sobrien */
15546283Sdfr#define TT_USE_CURRENT_PC ((TTRACE_ARG_TYPE) TT_NOPC)
15646283Sdfr
15746283Sdfr/* When supplied as the "addr", "data" or "addr2" operand for most
15846283Sdfr   requests, ttrace interprets this to mean, "pay no heed to this
15946283Sdfr   argument".
16098944Sobrien */
16146283Sdfr#define TT_NIL ((TTRACE_ARG_TYPE) TT_NULLARG)
16246283Sdfr
16346283Sdfr/* This is capable of holding the value of a 32-bit register.  The
16446283Sdfr   value is always left-aligned in the buffer; i.e., [0] contains
16546283Sdfr   the most-significant byte of the register's value, and [sizeof(reg)]
16646283Sdfr   contains the least-significant value.
16746283Sdfr
16846283Sdfr   ??rehrauer: Yes, this assumes that an int is 32-bits on HP-UX, and
16946283Sdfr   that registers are 32-bits on HP-UX.  The latter assumption changes
17046283Sdfr   with PA2.0.
17198944Sobrien */
17298944Sobrientypedef int register_value_t;
17346283Sdfr
17446283Sdfr/********************************************************************
17546283Sdfr
17646283Sdfr                 How this works:
17746283Sdfr
17846283Sdfr   1.  Thread numbers
17946283Sdfr
18046283Sdfr   The rest of GDB sees threads as being things with different
18146283Sdfr   "pid" (process id) values.  See "thread.c" for details.  The
18246283Sdfr   separate threads will be seen and reacted to if infttrace passes
18346283Sdfr   back different pid values (for _events_).  See wait_for_inferior
18446283Sdfr   in inftarg.c.
18546283Sdfr
18646283Sdfr   So infttrace is going to use thread ids externally, pretending
18746283Sdfr   they are process ids, and keep track internally so that it can
18846283Sdfr   use the real process id (and thread id) when calling ttrace.
18946283Sdfr
19046283Sdfr   The data structure that supports this is a linked list of the
19146283Sdfr   current threads.  Since at some date infttrace will have to
19246283Sdfr   deal with multiple processes, each list element records its
19346283Sdfr   corresponding pid, rather than having a single global.
19446283Sdfr
19546283Sdfr   Note that the list is only approximately current; that's ok, as
19646283Sdfr   it's up to date when we need it (we hope!).  Also, it can contain
19746283Sdfr   dead threads, as there's no harm if it does.
19846283Sdfr
19946283Sdfr   The approach taken here is to bury the translation from external
20046283Sdfr   to internal inside "call_ttrace" and a few other places.
20146283Sdfr
20246283Sdfr   There are some wrinkles:
20346283Sdfr
20446283Sdfr   o  When GDB forks itself to create the debug target process,
20546283Sdfr      there's only a pid of 0 around in the child, so the
20646283Sdfr      TT_PROC_SETTRC operation uses a more direct call to ttrace;
20746283Sdfr      Similiarly, the initial setting of the event mask happens
20846283Sdfr      early as  well, and so is also special-cased, and an attach
20946283Sdfr      uses a real pid;
21046283Sdfr
21146283Sdfr   o  We define an unthreaded application as having a "pseudo"
21246283Sdfr      thread;
21346283Sdfr
21446283Sdfr   o  To keep from confusing the rest of GDB, we don't switch
21546283Sdfr      the PID for the pseudo thread to a TID.  A table will help:
21646283Sdfr
21746283Sdfr      Rest of GDB sees these PIDs:     pid   tid1  tid2  tid3 ...
21846283Sdfr
21946283Sdfr      Our thread list stores:          pid   pid   pid   pid  ...
22046283Sdfr                                       tid0  tid1  tid2  tid3
22146283Sdfr
22246283Sdfr      Ttrace sees these TIDS:          tid0  tid1  tid2  tid3 ...
22346283Sdfr
22446283Sdfr      Both pid and tid0 will map to tid0, as there are infttrace.c-internal
22546283Sdfr      calls to ttrace using tid0.
22646283Sdfr
22746283Sdfr   2. Step and Continue
22846283Sdfr
22946283Sdfr   Since we're implementing the "stop the world" model, sub-model
23046283Sdfr   "other threads run during step", we have some stuff to do:
23146283Sdfr
23246283Sdfr   o  User steps require continuing all threads other than the
23346283Sdfr      one the user is stepping;
23446283Sdfr
23546283Sdfr   o  Internal debugger steps (such as over a breakpoint or watchpoint,
23646283Sdfr      but not out of a library load thunk) require stepping only
23746283Sdfr      the selected thread; this means that we have to report the
23846283Sdfr      step finish on that thread, which can lead to complications;
23946283Sdfr
24046283Sdfr   o  When a thread is created, it is created running, rather
24146283Sdfr      than stopped--so we have to stop it.
24246283Sdfr
24346283Sdfr   The OS doesn't guarantee the stopped thread list will be stable,
24446283Sdfr   no does it guarantee where on the stopped thread list a thread
24546283Sdfr   that is single-stepped will wind up: it's possible that it will
24646283Sdfr   be off the list for a while, it's possible the step will complete
24746283Sdfr   and it will be re-posted to the end...
24846283Sdfr
24946283Sdfr   This means we have to scan the stopped thread list, build up
25046283Sdfr   a work-list, and then run down the work list; we can't do the
25146283Sdfr   step/continue during the scan.
25246283Sdfr
25346283Sdfr   3. Buffering events
25446283Sdfr
25546283Sdfr   Then there's the issue of waiting for an event.  We do this by
25646283Sdfr   noticing how many events are reported at the end of each wait.
25746283Sdfr   From then on, we "fake" all resumes and steps, returning instantly,
25846283Sdfr   and don't do another wait.  Once all pending events are reported,
25946283Sdfr   we can really resume again.
26046283Sdfr
26146283Sdfr   To keep this hidden, all the routines which know about tids and
26246283Sdfr   pids or real events and simulated ones are static (file-local).
26346283Sdfr
26446283Sdfr   This code can make lots of calls to ttrace, in particular it
26546283Sdfr   can spin down the list of thread states more than once.  If this
26646283Sdfr   becomes a performance hit, the spin could be done once and the
26746283Sdfr   various "tsp" blocks saved, keeping all later spins in this
26846283Sdfr   process.
26946283Sdfr
27046283Sdfr   The O/S doesn't promise to keep the list straight, and so we must
27146283Sdfr   re-scan a lot.  By observation, it looks like a single-step/wait
27246283Sdfr   puts the stepped thread at the end of the list but doesn't change
27346283Sdfr   it otherwise.
27446283Sdfr
27546283Sdfr****************************************************************
27646283Sdfr*/
27746283Sdfr
27846283Sdfr/* Uncomment these to turn on various debugging output */
27946283Sdfr/* #define THREAD_DEBUG */
28046283Sdfr/* #define WAIT_BUFFER_DEBUG */
28146283Sdfr/* #define PARANOIA */
28246283Sdfr
28346283Sdfr
28446283Sdfr#define INFTTRACE_ALL_THREADS (-1)
28546283Sdfr#define INFTTRACE_STEP        (1)
28646283Sdfr#define INFTTRACE_CONTINUE    (0)
28746283Sdfr
28846283Sdfr/* FIX: this is used in inftarg.c/child_wait, in a hack.
28946283Sdfr */
29046283Sdfrextern int not_same_real_pid;
29146283Sdfr
29246283Sdfr/* This is used to count buffered events.
29346283Sdfr */
29446283Sdfrstatic unsigned int more_events_left = 0;
29546283Sdfr
29646283Sdfr/* Process state.
29746283Sdfr */
29898944Sobrientypedef enum process_state_enum
29998944Sobrien  {
30046283Sdfr    STOPPED,
30146283Sdfr    FAKE_STEPPING,
30298944Sobrien    FAKE_CONTINUE,		/* For later use */
30346283Sdfr    RUNNING,
30446283Sdfr    FORKING,
30546283Sdfr    VFORKING
30698944Sobrien  }
30798944Sobrienprocess_state_t;
30846283Sdfr
30946283Sdfrstatic process_state_t process_state = STOPPED;
31046283Sdfr
31146283Sdfr/* User-specified stepping modality.
31246283Sdfr */
31398944Sobrientypedef enum stepping_mode_enum
31498944Sobrien  {
31598944Sobrien    DO_DEFAULT,			/* ...which is a continue! */
31646283Sdfr    DO_STEP,
31746283Sdfr    DO_CONTINUE
31898944Sobrien  }
31998944Sobrienstepping_mode_t;
32098944Sobrien
32146283Sdfr/* Action to take on an attach, depends on
32246283Sdfr * what kind (user command, fork, vfork).
32346283Sdfr *
32446283Sdfr * At the moment, this is either:
32546283Sdfr *
32646283Sdfr * o  continue with a SIGTRAP signal, or
32746283Sdfr *
32846283Sdfr * o  leave stopped.
32946283Sdfr */
33098944Sobrientypedef enum attach_continue_enum
33198944Sobrien  {
33298944Sobrien    DO_ATTACH_CONTINUE,
33398944Sobrien    DONT_ATTACH_CONTINUE
33498944Sobrien  }
33598944Sobrienattach_continue_t;
33646283Sdfr
33746283Sdfr/* This flag is true if we are doing a step-over-bpt
33846283Sdfr * with buffered events.  We will have to be sure to
33946283Sdfr * report the right thread, as otherwise the spaghetti
34046283Sdfr * code in "infrun.c/wait_for_inferior" will get
34146283Sdfr * confused.
34246283Sdfr */
34398944Sobrienstatic int doing_fake_step = 0;
34498944Sobrienstatic lwpid_t fake_step_tid = 0;
34598944Sobrien
34646283Sdfr
34746283Sdfr/****************************************************
34846283Sdfr * Thread information structure routines and types. *
34946283Sdfr ****************************************************
35046283Sdfr */
35198944Sobrientypedef
35246283Sdfrstruct thread_info_struct
35398944Sobrien  {
35498944Sobrien    int am_pseudo;		/* This is a pseudo-thread for the process. */
35598944Sobrien    int pid;			/* Process ID */
35698944Sobrien    lwpid_t tid;		/* Thread  ID */
35798944Sobrien    int handled;		/* 1 if a buffered event was handled. */
35898944Sobrien    int seen;			/* 1 if this thread was seen on a traverse. */
35998944Sobrien    int terminated;		/* 1 if thread has terminated. */
36098944Sobrien    int have_signal;		/* 1 if signal to be sent */
36198944Sobrien    enum target_signal signal_value;	/* Signal to send */
36298944Sobrien    int have_start;		/* 1 if alternate starting address */
36398944Sobrien    stepping_mode_t stepping_mode;	/* Whether to step or continue */
36498944Sobrien    CORE_ADDR start;		/* Where to start */
36598944Sobrien    int have_state;		/* 1 if the event state has been set */
36698944Sobrien    ttstate_t last_stop_state;	/* The most recently-waited event for this thread. */
36746283Sdfr    struct thread_info_struct
36898944Sobrien     *next;			/* All threads are linked via this field. */
36946283Sdfr    struct thread_info_struct
37098944Sobrien     *next_pseudo;		/* All pseudo-threads are linked via this field. */
37198944Sobrien  }
37298944Sobrienthread_info;
37346283Sdfr
37446283Sdfrtypedef
37546283Sdfrstruct thread_info_header_struct
37698944Sobrien  {
37798944Sobrien    int count;
37846283Sdfr    thread_info *head;
37946283Sdfr    thread_info *head_pseudo;
38046283Sdfr
38198944Sobrien  }
38298944Sobrienthread_info_header;
38346283Sdfr
38498944Sobrienstatic thread_info_header thread_head =
38598944Sobrien{0, NULL, NULL};
38698944Sobrienstatic thread_info_header deleted_threads =
38798944Sobrien{0, NULL, NULL};
38846283Sdfr
38998944Sobrienstatic ptid_t saved_real_ptid;
39046283Sdfr
39198944Sobrien
39246283Sdfr/*************************************************
39346283Sdfr *          Debugging support functions          *
39446283Sdfr *************************************************
39546283Sdfr */
39646283SdfrCORE_ADDR
39798944Sobrienget_raw_pc (lwpid_t ttid)
39846283Sdfr{
39998944Sobrien  unsigned long pc_val;
40098944Sobrien  int offset;
40198944Sobrien  int res;
40298944Sobrien
40398944Sobrien  offset = register_addr (PC_REGNUM, U_REGS_OFFSET);
40498944Sobrien  res = read_from_register_save_state (
40598944Sobrien					ttid,
40698944Sobrien					(TTRACE_ARG_TYPE) offset,
40798944Sobrien					(char *) &pc_val,
40898944Sobrien					sizeof (pc_val));
40998944Sobrien  if (res <= 0)
41098944Sobrien    {
41198944Sobrien      return (CORE_ADDR) pc_val;
41246283Sdfr    }
41398944Sobrien  else
41498944Sobrien    {
41598944Sobrien      return (CORE_ADDR) 0;
41646283Sdfr    }
41798944Sobrien}
41846283Sdfr
41946283Sdfrstatic char *
42098944Sobrienget_printable_name_of_stepping_mode (stepping_mode_t mode)
42146283Sdfr{
42298944Sobrien  switch (mode)
42398944Sobrien    {
42498944Sobrien    case DO_DEFAULT:
42598944Sobrien      return "DO_DEFAULT";
42698944Sobrien    case DO_STEP:
42798944Sobrien      return "DO_STEP";
42898944Sobrien    case DO_CONTINUE:
42998944Sobrien      return "DO_CONTINUE";
43098944Sobrien    default:
43198944Sobrien      return "?unknown mode?";
43298944Sobrien    }
43346283Sdfr}
43446283Sdfr
43546283Sdfr/* This function returns a pointer to a string describing the
43646283Sdfr * ttrace event being reported.
43746283Sdfr */
43846283Sdfrchar *
43998944Sobrienget_printable_name_of_ttrace_event (ttevents_t event)
44046283Sdfr{
44146283Sdfr  /* This enumeration is "gappy", so don't use a table. */
44298944Sobrien  switch (event)
44398944Sobrien    {
44446283Sdfr
44546283Sdfr    case TTEVT_NONE:
44698944Sobrien      return "TTEVT_NONE";
44746283Sdfr    case TTEVT_SIGNAL:
44898944Sobrien      return "TTEVT_SIGNAL";
44946283Sdfr    case TTEVT_FORK:
45098944Sobrien      return "TTEVT_FORK";
45146283Sdfr    case TTEVT_EXEC:
45298944Sobrien      return "TTEVT_EXEC";
45346283Sdfr    case TTEVT_EXIT:
45498944Sobrien      return "TTEVT_EXIT";
45546283Sdfr    case TTEVT_VFORK:
45698944Sobrien      return "TTEVT_VFORK";
45746283Sdfr    case TTEVT_SYSCALL_RETURN:
45898944Sobrien      return "TTEVT_SYSCALL_RETURN";
45946283Sdfr    case TTEVT_LWP_CREATE:
46098944Sobrien      return "TTEVT_LWP_CREATE";
46146283Sdfr    case TTEVT_LWP_TERMINATE:
46298944Sobrien      return "TTEVT_LWP_TERMINATE";
46346283Sdfr    case TTEVT_LWP_EXIT:
46498944Sobrien      return "TTEVT_LWP_EXIT";
46546283Sdfr    case TTEVT_LWP_ABORT_SYSCALL:
46698944Sobrien      return "TTEVT_LWP_ABORT_SYSCALL";
46746283Sdfr    case TTEVT_SYSCALL_ENTRY:
46898944Sobrien      return "TTEVT_SYSCALL_ENTRY";
46998944Sobrien    case TTEVT_SYSCALL_RESTART:
47098944Sobrien      return "TTEVT_SYSCALL_RESTART";
47198944Sobrien    default:
47246283Sdfr      return "?new event?";
47398944Sobrien    }
47446283Sdfr}
47598944Sobrien
47646283Sdfr
47746283Sdfr/* This function translates the ttrace request enumeration into
47846283Sdfr * a character string that is its printable (aka "human readable")
47946283Sdfr * name.
48046283Sdfr */
48146283Sdfrchar *
48298944Sobrienget_printable_name_of_ttrace_request (ttreq_t request)
48346283Sdfr{
48446283Sdfr  if (!IS_TTRACE_REQ (request))
48546283Sdfr    return "?bad req?";
48646283Sdfr
48746283Sdfr  /* This enumeration is "gappy", so don't use a table. */
48898944Sobrien  switch (request)
48998944Sobrien    {
49098944Sobrien    case TT_PROC_SETTRC:
49146283Sdfr      return "TT_PROC_SETTRC";
49298944Sobrien    case TT_PROC_ATTACH:
49346283Sdfr      return "TT_PROC_ATTACH";
49498944Sobrien    case TT_PROC_DETACH:
49546283Sdfr      return "TT_PROC_DETACH";
49698944Sobrien    case TT_PROC_RDTEXT:
49746283Sdfr      return "TT_PROC_RDTEXT";
49898944Sobrien    case TT_PROC_WRTEXT:
49946283Sdfr      return "TT_PROC_WRTEXT";
50098944Sobrien    case TT_PROC_RDDATA:
50146283Sdfr      return "TT_PROC_RDDATA";
50298944Sobrien    case TT_PROC_WRDATA:
50346283Sdfr      return "TT_PROC_WRDATA";
50498944Sobrien    case TT_PROC_STOP:
50546283Sdfr      return "TT_PROC_STOP";
50698944Sobrien    case TT_PROC_CONTINUE:
50746283Sdfr      return "TT_PROC_CONTINUE";
50898944Sobrien    case TT_PROC_GET_PATHNAME:
50946283Sdfr      return "TT_PROC_GET_PATHNAME";
51098944Sobrien    case TT_PROC_GET_EVENT_MASK:
51146283Sdfr      return "TT_PROC_GET_EVENT_MASK";
51298944Sobrien    case TT_PROC_SET_EVENT_MASK:
51346283Sdfr      return "TT_PROC_SET_EVENT_MASK";
51498944Sobrien    case TT_PROC_GET_FIRST_LWP_STATE:
51546283Sdfr      return "TT_PROC_GET_FIRST_LWP_STATE";
51698944Sobrien    case TT_PROC_GET_NEXT_LWP_STATE:
51746283Sdfr      return "TT_PROC_GET_NEXT_LWP_STATE";
51898944Sobrien    case TT_PROC_EXIT:
51946283Sdfr      return "TT_PROC_EXIT";
52098944Sobrien    case TT_PROC_GET_MPROTECT:
52146283Sdfr      return "TT_PROC_GET_MPROTECT";
52298944Sobrien    case TT_PROC_SET_MPROTECT:
52346283Sdfr      return "TT_PROC_SET_MPROTECT";
52498944Sobrien    case TT_PROC_SET_SCBM:
52546283Sdfr      return "TT_PROC_SET_SCBM";
52698944Sobrien    case TT_LWP_STOP:
52746283Sdfr      return "TT_LWP_STOP";
52898944Sobrien    case TT_LWP_CONTINUE:
52946283Sdfr      return "TT_LWP_CONTINUE";
53098944Sobrien    case TT_LWP_SINGLE:
53146283Sdfr      return "TT_LWP_SINGLE";
53298944Sobrien    case TT_LWP_RUREGS:
53346283Sdfr      return "TT_LWP_RUREGS";
53498944Sobrien    case TT_LWP_WUREGS:
53546283Sdfr      return "TT_LWP_WUREGS";
53698944Sobrien    case TT_LWP_GET_EVENT_MASK:
53746283Sdfr      return "TT_LWP_GET_EVENT_MASK";
53898944Sobrien    case TT_LWP_SET_EVENT_MASK:
53946283Sdfr      return "TT_LWP_SET_EVENT_MASK";
54098944Sobrien    case TT_LWP_GET_STATE:
54146283Sdfr      return "TT_LWP_GET_STATE";
54298944Sobrien    default:
54346283Sdfr      return "?new req?";
54498944Sobrien    }
54546283Sdfr}
54698944Sobrien
54746283Sdfr
54846283Sdfr/* This function translates the process state enumeration into
54946283Sdfr * a character string that is its printable (aka "human readable")
55046283Sdfr * name.
55146283Sdfr */
55246283Sdfrstatic char *
55398944Sobrienget_printable_name_of_process_state (process_state_t process_state)
55446283Sdfr{
55598944Sobrien  switch (process_state)
55698944Sobrien    {
55746283Sdfr    case STOPPED:
55846283Sdfr      return "STOPPED";
55946283Sdfr    case FAKE_STEPPING:
56046283Sdfr      return "FAKE_STEPPING";
56146283Sdfr    case RUNNING:
56246283Sdfr      return "RUNNING";
56346283Sdfr    case FORKING:
56446283Sdfr      return "FORKING";
56546283Sdfr    case VFORKING:
56646283Sdfr      return "VFORKING";
56746283Sdfr    default:
56846283Sdfr      return "?some unknown state?";
56998944Sobrien    }
57046283Sdfr}
57146283Sdfr
57246283Sdfr/* Set a ttrace thread state to a safe, initial state.
57346283Sdfr */
57446283Sdfrstatic void
57598944Sobrienclear_ttstate_t (ttstate_t *tts)
57646283Sdfr{
57798944Sobrien  tts->tts_pid = 0;
57898944Sobrien  tts->tts_lwpid = 0;
57998944Sobrien  tts->tts_user_tid = 0;
58098944Sobrien  tts->tts_event = TTEVT_NONE;
58146283Sdfr}
58246283Sdfr
58346283Sdfr/* Copy ttrace thread state TTS_FROM into TTS_TO.
58446283Sdfr */
58546283Sdfrstatic void
58698944Sobriencopy_ttstate_t (ttstate_t *tts_to, ttstate_t *tts_from)
58746283Sdfr{
58898944Sobrien  memcpy ((char *) tts_to, (char *) tts_from, sizeof (*tts_to));
58946283Sdfr}
59046283Sdfr
59146283Sdfr/* Are there any live threads we know about?
59246283Sdfr */
59398944Sobrienstatic int
59498944Sobrienany_thread_records (void)
59546283Sdfr{
59698944Sobrien  return (thread_head.count > 0);
59746283Sdfr}
59846283Sdfr
59946283Sdfr/* Create, fill in and link in a thread descriptor.
60046283Sdfr */
60146283Sdfrstatic thread_info *
60298944Sobriencreate_thread_info (int pid, lwpid_t tid)
60346283Sdfr{
60498944Sobrien  thread_info *new_p;
60598944Sobrien  thread_info *p;
60698944Sobrien  int thread_count_of_pid;
60746283Sdfr
60898944Sobrien  new_p = xmalloc (sizeof (thread_info));
60998944Sobrien  new_p->pid = pid;
61098944Sobrien  new_p->tid = tid;
61198944Sobrien  new_p->have_signal = 0;
61298944Sobrien  new_p->have_start = 0;
61398944Sobrien  new_p->have_state = 0;
61498944Sobrien  clear_ttstate_t (&new_p->last_stop_state);
61598944Sobrien  new_p->am_pseudo = 0;
61698944Sobrien  new_p->handled = 0;
61798944Sobrien  new_p->seen = 0;
61898944Sobrien  new_p->terminated = 0;
61998944Sobrien  new_p->next = NULL;
62098944Sobrien  new_p->next_pseudo = NULL;
62198944Sobrien  new_p->stepping_mode = DO_DEFAULT;
62246283Sdfr
62398944Sobrien  if (0 == thread_head.count)
62498944Sobrien    {
62546283Sdfr#ifdef THREAD_DEBUG
62698944Sobrien      if (debug_on)
62798944Sobrien	printf ("First thread, pid %d tid %d!\n", pid, tid);
62846283Sdfr#endif
62998944Sobrien      saved_real_ptid = inferior_ptid;
63046283Sdfr    }
63198944Sobrien  else
63298944Sobrien    {
63346283Sdfr#ifdef THREAD_DEBUG
63498944Sobrien      if (debug_on)
63598944Sobrien	printf ("Subsequent thread, pid %d tid %d\n", pid, tid);
63646283Sdfr#endif
63746283Sdfr    }
63846283Sdfr
63998944Sobrien  /* Another day, another thread...
64098944Sobrien   */
64198944Sobrien  thread_head.count++;
64246283Sdfr
64398944Sobrien  /* The new thread always goes at the head of the list.
64498944Sobrien   */
64598944Sobrien  new_p->next = thread_head.head;
64698944Sobrien  thread_head.head = new_p;
64746283Sdfr
64898944Sobrien  /* Is this the "pseudo" thread of a process?  It is if there's
64998944Sobrien   * no other thread for this process on the list.  (Note that this
65098944Sobrien   * accomodates multiple processes, such as we see even for simple
65198944Sobrien   * cases like forking "non-threaded" programs.)
65298944Sobrien   */
65398944Sobrien  p = thread_head.head;
65498944Sobrien  thread_count_of_pid = 0;
65598944Sobrien  while (p)
65698944Sobrien    {
65798944Sobrien      if (p->pid == new_p->pid)
65898944Sobrien	thread_count_of_pid++;
65998944Sobrien      p = p->next;
66098944Sobrien    }
66146283Sdfr
66298944Sobrien  /* Did we see any other threads for this pid?  (Recall that we just
66398944Sobrien   * added this thread to the list...)
66498944Sobrien   */
66598944Sobrien  if (thread_count_of_pid == 1)
66698944Sobrien    {
66798944Sobrien      new_p->am_pseudo = 1;
66898944Sobrien      new_p->next_pseudo = thread_head.head_pseudo;
66998944Sobrien      thread_head.head_pseudo = new_p;
67098944Sobrien    }
67198944Sobrien
67298944Sobrien  return new_p;
67346283Sdfr}
67446283Sdfr
67546283Sdfr/* Get rid of our thread info.
67646283Sdfr */
67746283Sdfrstatic void
67898944Sobrienclear_thread_info (void)
67946283Sdfr{
68098944Sobrien  thread_info *p;
68198944Sobrien  thread_info *q;
68246283Sdfr
68346283Sdfr#ifdef THREAD_DEBUG
68498944Sobrien  if (debug_on)
68598944Sobrien    printf ("Clearing all thread info\n");
68646283Sdfr#endif
68746283Sdfr
68898944Sobrien  p = thread_head.head;
68998944Sobrien  while (p)
69098944Sobrien    {
69198944Sobrien      q = p;
69298944Sobrien      p = p->next;
69398944Sobrien      xfree (q);
69446283Sdfr    }
69546283Sdfr
69698944Sobrien  thread_head.head = NULL;
69798944Sobrien  thread_head.head_pseudo = NULL;
69898944Sobrien  thread_head.count = 0;
69946283Sdfr
70098944Sobrien  p = deleted_threads.head;
70198944Sobrien  while (p)
70298944Sobrien    {
70398944Sobrien      q = p;
70498944Sobrien      p = p->next;
70598944Sobrien      xfree (q);
70646283Sdfr    }
70746283Sdfr
70898944Sobrien  deleted_threads.head = NULL;
70998944Sobrien  deleted_threads.head_pseudo = NULL;
71098944Sobrien  deleted_threads.count = 0;
71146283Sdfr
71298944Sobrien  /* No threads, so can't have pending events.
71398944Sobrien   */
71498944Sobrien  more_events_left = 0;
71546283Sdfr}
71646283Sdfr
71746283Sdfr/* Given a tid, find the thread block for it.
71846283Sdfr */
71946283Sdfrstatic thread_info *
72098944Sobrienfind_thread_info (lwpid_t tid)
72146283Sdfr{
72298944Sobrien  thread_info *p;
72346283Sdfr
72498944Sobrien  for (p = thread_head.head; p; p = p->next)
72598944Sobrien    {
72698944Sobrien      if (p->tid == tid)
72798944Sobrien	{
72898944Sobrien	  return p;
72998944Sobrien	}
73046283Sdfr    }
73146283Sdfr
73298944Sobrien  for (p = deleted_threads.head; p; p = p->next)
73398944Sobrien    {
73498944Sobrien      if (p->tid == tid)
73598944Sobrien	{
73698944Sobrien	  return p;
73798944Sobrien	}
73846283Sdfr    }
73998944Sobrien
74098944Sobrien  return NULL;
74146283Sdfr}
74246283Sdfr
74346283Sdfr/* For any but the pseudo thread, this maps to the
74446283Sdfr * thread ID.  For the pseudo thread, if you pass either
74546283Sdfr * the thread id or the PID, you get the pseudo thread ID.
74646283Sdfr *
74746283Sdfr * We have to be prepared for core gdb to ask about
74846283Sdfr * deleted threads.  We do the map, but we don't like it.
74946283Sdfr */
75046283Sdfrstatic lwpid_t
75198944Sobrienmap_from_gdb_tid (lwpid_t gdb_tid)
75246283Sdfr{
75398944Sobrien  thread_info *p;
75446283Sdfr
75598944Sobrien  /* First assume gdb_tid really is a tid, and try to find a
75698944Sobrien   * matching entry on the threads list.
75798944Sobrien   */
75898944Sobrien  for (p = thread_head.head; p; p = p->next)
75998944Sobrien    {
76098944Sobrien      if (p->tid == gdb_tid)
76198944Sobrien	return gdb_tid;
76246283Sdfr    }
76346283Sdfr
76498944Sobrien  /* It doesn't appear to be a tid; perhaps it's really a pid?
76598944Sobrien   * Try to find a "pseudo" thread entry on the threads list.
76698944Sobrien   */
76798944Sobrien  for (p = thread_head.head_pseudo; p != NULL; p = p->next_pseudo)
76898944Sobrien    {
76998944Sobrien      if (p->pid == gdb_tid)
77098944Sobrien	return p->tid;
77198944Sobrien    }
77246283Sdfr
77398944Sobrien  /* Perhaps it's the tid of a deleted thread we may still
77498944Sobrien   * have some knowledge of?
77598944Sobrien   */
77698944Sobrien  for (p = deleted_threads.head; p; p = p->next)
77798944Sobrien    {
77898944Sobrien      if (p->tid == gdb_tid)
77998944Sobrien	return gdb_tid;
78046283Sdfr    }
78146283Sdfr
78298944Sobrien  /* Or perhaps it's the pid of a deleted process we may still
78398944Sobrien   * have knowledge of?
78498944Sobrien   */
78598944Sobrien  for (p = deleted_threads.head_pseudo; p != NULL; p = p->next_pseudo)
78698944Sobrien    {
78798944Sobrien      if (p->pid == gdb_tid)
78898944Sobrien	return p->tid;
78998944Sobrien    }
79046283Sdfr
79198944Sobrien  return 0;			/* Error? */
79246283Sdfr}
79346283Sdfr
79446283Sdfr/* Map the other way: from a real tid to the
79546283Sdfr * "pid" known by core gdb.  This tid may be
79646283Sdfr * for a thread that just got deleted, so we
79746283Sdfr * also need to consider deleted threads.
79846283Sdfr */
79946283Sdfrstatic lwpid_t
80098944Sobrienmap_to_gdb_tid (lwpid_t real_tid)
80146283Sdfr{
80298944Sobrien  thread_info *p;
80346283Sdfr
80498944Sobrien  for (p = thread_head.head; p; p = p->next)
80598944Sobrien    {
80698944Sobrien      if (p->tid == real_tid)
80798944Sobrien	{
80898944Sobrien	  if (p->am_pseudo)
80998944Sobrien	    return p->pid;
81098944Sobrien	  else
81198944Sobrien	    return real_tid;
81298944Sobrien	}
81346283Sdfr    }
81446283Sdfr
81598944Sobrien  for (p = deleted_threads.head; p; p = p->next)
81698944Sobrien    {
81798944Sobrien      if (p->tid == real_tid)
81898944Sobrien	if (p->am_pseudo)
81998944Sobrien	  return p->pid;	/* Error? */
82098944Sobrien	else
82198944Sobrien	  return real_tid;
82246283Sdfr    }
82346283Sdfr
82498944Sobrien  return 0;			/* Error?  Never heard of this thread! */
82546283Sdfr}
82646283Sdfr
82746283Sdfr/* Do any threads have saved signals?
82846283Sdfr */
82998944Sobrienstatic int
83098944Sobriensaved_signals_exist (void)
83146283Sdfr{
83298944Sobrien  thread_info *p;
83398944Sobrien
83498944Sobrien  for (p = thread_head.head; p; p = p->next)
83598944Sobrien    {
83698944Sobrien      if (p->have_signal)
83798944Sobrien	{
83898944Sobrien	  return 1;
83998944Sobrien	}
84046283Sdfr    }
84146283Sdfr
84298944Sobrien  return 0;
84346283Sdfr}
84446283Sdfr
84546283Sdfr/* Is this the tid for the zero-th thread?
84646283Sdfr */
84798944Sobrienstatic int
84898944Sobrienis_pseudo_thread (lwpid_t tid)
84946283Sdfr{
85098944Sobrien  thread_info *p = find_thread_info (tid);
85198944Sobrien  if (NULL == p || p->terminated)
85298944Sobrien    return 0;
85398944Sobrien  else
85498944Sobrien    return p->am_pseudo;
85546283Sdfr}
85646283Sdfr
85746283Sdfr/* Is this thread terminated?
85846283Sdfr */
85998944Sobrienstatic int
86098944Sobrienis_terminated (lwpid_t tid)
86146283Sdfr{
86298944Sobrien  thread_info *p = find_thread_info (tid);
86346283Sdfr
86498944Sobrien  if (NULL != p)
86598944Sobrien    return p->terminated;
86646283Sdfr
86798944Sobrien  return 0;
86846283Sdfr}
86946283Sdfr
87046283Sdfr/* Is this pid a real PID or a TID?
87146283Sdfr */
87298944Sobrienstatic int
87398944Sobrienis_process_id (int pid)
87446283Sdfr{
87598944Sobrien  lwpid_t tid;
87698944Sobrien  thread_info *tinfo;
87798944Sobrien  pid_t this_pid;
87898944Sobrien  int this_pid_count;
87946283Sdfr
88046283Sdfr  /* What does PID really represent?
88146283Sdfr   */
88246283Sdfr  tid = map_from_gdb_tid (pid);
88346283Sdfr  if (tid <= 0)
88498944Sobrien    return 0;			/* Actually, is probably an error... */
88546283Sdfr
88646283Sdfr  tinfo = find_thread_info (tid);
88746283Sdfr
88846283Sdfr  /* Does it appear to be a true thread?
88946283Sdfr   */
89098944Sobrien  if (!tinfo->am_pseudo)
89146283Sdfr    return 0;
89246283Sdfr
89346283Sdfr  /* Else, it looks like it may be a process.  See if there's any other
89446283Sdfr   * threads with the same process ID, though.  If there are, then TID
89546283Sdfr   * just happens to be the first thread of several for this process.
89646283Sdfr   */
89746283Sdfr  this_pid = tinfo->pid;
89846283Sdfr  this_pid_count = 0;
89946283Sdfr  for (tinfo = thread_head.head; tinfo; tinfo = tinfo->next)
90046283Sdfr    {
90146283Sdfr      if (tinfo->pid == this_pid)
90298944Sobrien	this_pid_count++;
90346283Sdfr    }
90446283Sdfr
90546283Sdfr  return (this_pid_count == 1);
90646283Sdfr}
90746283Sdfr
90846283Sdfr
90946283Sdfr/* Add a thread to our info.  Prevent duplicate entries.
91046283Sdfr */
91146283Sdfrstatic thread_info *
91298944Sobrienadd_tthread (int pid, lwpid_t tid)
91346283Sdfr{
91498944Sobrien  thread_info *p;
91546283Sdfr
91698944Sobrien  p = find_thread_info (tid);
91798944Sobrien  if (NULL == p)
91898944Sobrien    p = create_thread_info (pid, tid);
91946283Sdfr
92098944Sobrien  return p;
92146283Sdfr}
92246283Sdfr
92346283Sdfr/* Notice that a thread was deleted.
92446283Sdfr */
92546283Sdfrstatic void
92698944Sobriendel_tthread (lwpid_t tid)
92746283Sdfr{
92898944Sobrien  thread_info *p;
92998944Sobrien  thread_info *chase;
93046283Sdfr
93198944Sobrien  if (thread_head.count <= 0)
93298944Sobrien    {
93398944Sobrien      error ("Internal error in thread database.");
93498944Sobrien      return;
93546283Sdfr    }
93646283Sdfr
93798944Sobrien  chase = NULL;
93898944Sobrien  for (p = thread_head.head; p; p = p->next)
93998944Sobrien    {
94098944Sobrien      if (p->tid == tid)
94198944Sobrien	{
94246283Sdfr
94346283Sdfr#ifdef THREAD_DEBUG
94498944Sobrien	  if (debug_on)
94598944Sobrien	    printf ("Delete here: %d \n", tid);
94646283Sdfr#endif
94746283Sdfr
94898944Sobrien	  if (p->am_pseudo)
94998944Sobrien	    {
95098944Sobrien	      /*
95198944Sobrien	       * Deleting a main thread is ok if we're doing
95298944Sobrien	       * a parent-follow on a child; this is odd but
95398944Sobrien	       * not wrong.  It apparently _doesn't_ happen
95498944Sobrien	       * on the child-follow, as we don't just delete
95598944Sobrien	       * the pseudo while keeping the rest of the
95698944Sobrien	       * threads around--instead, we clear out the whole
95798944Sobrien	       * thread list at once.
95898944Sobrien	       */
95998944Sobrien	      thread_info *q;
96098944Sobrien	      thread_info *q_chase;
96146283Sdfr
96298944Sobrien	      q_chase = NULL;
96398944Sobrien	      for (q = thread_head.head_pseudo; q; q = q->next)
96498944Sobrien		{
96598944Sobrien		  if (q == p)
96698944Sobrien		    {
96798944Sobrien		      /* Remove from pseudo list.
96898944Sobrien		       */
96998944Sobrien		      if (q_chase == NULL)
97098944Sobrien			thread_head.head_pseudo = p->next_pseudo;
97198944Sobrien		      else
97298944Sobrien			q_chase->next = p->next_pseudo;
97398944Sobrien		    }
97498944Sobrien		  else
97598944Sobrien		    q_chase = q;
97698944Sobrien		}
97798944Sobrien	    }
97846283Sdfr
97998944Sobrien	  /* Remove from live list.
98098944Sobrien	   */
98198944Sobrien	  thread_head.count--;
98246283Sdfr
98398944Sobrien	  if (NULL == chase)
98498944Sobrien	    thread_head.head = p->next;
98598944Sobrien	  else
98698944Sobrien	    chase->next = p->next;
98798944Sobrien
98898944Sobrien	  /* Add to deleted thread list.
98998944Sobrien	   */
99098944Sobrien	  p->next = deleted_threads.head;
99198944Sobrien	  deleted_threads.head = p;
99298944Sobrien	  deleted_threads.count++;
99398944Sobrien	  if (p->am_pseudo)
99498944Sobrien	    {
99598944Sobrien	      p->next_pseudo = deleted_threads.head_pseudo;
99698944Sobrien	      deleted_threads.head_pseudo = p;
99798944Sobrien	    }
99898944Sobrien	  p->terminated = 1;
99998944Sobrien
100098944Sobrien	  return;
100198944Sobrien	}
100298944Sobrien
100398944Sobrien      else
100498944Sobrien	chase = p;
100546283Sdfr    }
100646283Sdfr}
100746283Sdfr
100846283Sdfr/* Get the pid for this tid. (Has to be a real TID!).
100946283Sdfr */
101046283Sdfrstatic int
101198944Sobrienget_pid_for (lwpid_t tid)
101246283Sdfr{
101398944Sobrien  thread_info *p;
101446283Sdfr
101598944Sobrien  for (p = thread_head.head; p; p = p->next)
101698944Sobrien    {
101798944Sobrien      if (p->tid == tid)
101898944Sobrien	{
101998944Sobrien	  return p->pid;
102098944Sobrien	}
102146283Sdfr    }
102246283Sdfr
102398944Sobrien  for (p = deleted_threads.head; p; p = p->next)
102498944Sobrien    {
102598944Sobrien      if (p->tid == tid)
102698944Sobrien	{
102798944Sobrien	  return p->pid;
102898944Sobrien	}
102946283Sdfr    }
103098944Sobrien
103198944Sobrien  return 0;
103246283Sdfr}
103346283Sdfr
103446283Sdfr/* Note that this thread's current event has been handled.
103546283Sdfr */
103646283Sdfrstatic void
103798944Sobrienset_handled (int pid, lwpid_t tid)
103846283Sdfr{
103998944Sobrien  thread_info *p;
104046283Sdfr
104198944Sobrien  p = find_thread_info (tid);
104298944Sobrien  if (NULL == p)
104398944Sobrien    p = add_tthread (pid, tid);
104498944Sobrien
104598944Sobrien  p->handled = 1;
104646283Sdfr}
104746283Sdfr
104846283Sdfr/* Was this thread's current event handled?
104946283Sdfr */
105098944Sobrienstatic int
105198944Sobrienwas_handled (lwpid_t tid)
105246283Sdfr{
105398944Sobrien  thread_info *p;
105446283Sdfr
105598944Sobrien  p = find_thread_info (tid);
105698944Sobrien  if (NULL != p)
105798944Sobrien    return p->handled;
105898944Sobrien
105998944Sobrien  return 0;			/* New threads have not been handled */
106046283Sdfr}
106146283Sdfr
106246283Sdfr/* Set this thread to unhandled.
106346283Sdfr */
106446283Sdfrstatic void
106598944Sobrienclear_handled (lwpid_t tid)
106646283Sdfr{
106798944Sobrien  thread_info *p;
106898944Sobrien
106946283Sdfr#ifdef WAIT_BUFFER_DEBUG
107098944Sobrien  if (debug_on)
107198944Sobrien    printf ("clear_handled %d\n", (int) tid);
107246283Sdfr#endif
107346283Sdfr
107446283Sdfr  p = find_thread_info (tid);
107546283Sdfr  if (p == NULL)
107646283Sdfr    error ("Internal error: No thread state to clear?");
107746283Sdfr
107846283Sdfr  p->handled = 0;
107946283Sdfr}
108046283Sdfr
108146283Sdfr/* Set all threads to unhandled.
108246283Sdfr */
108346283Sdfrstatic void
108498944Sobrienclear_all_handled (void)
108546283Sdfr{
108698944Sobrien  thread_info *p;
108746283Sdfr
108846283Sdfr#ifdef WAIT_BUFFER_DEBUG
108998944Sobrien  if (debug_on)
109098944Sobrien    printf ("clear_all_handled\n");
109146283Sdfr#endif
109246283Sdfr
109398944Sobrien  for (p = thread_head.head; p; p = p->next)
109498944Sobrien    {
109598944Sobrien      p->handled = 0;
109646283Sdfr    }
109746283Sdfr
109898944Sobrien  for (p = deleted_threads.head; p; p = p->next)
109998944Sobrien    {
110098944Sobrien      p->handled = 0;
110146283Sdfr    }
110246283Sdfr}
110346283Sdfr
110446283Sdfr/* Set this thread to default stepping mode.
110546283Sdfr */
110646283Sdfrstatic void
110798944Sobrienclear_stepping_mode (lwpid_t tid)
110846283Sdfr{
110998944Sobrien  thread_info *p;
111098944Sobrien
111146283Sdfr#ifdef WAIT_BUFFER_DEBUG
111298944Sobrien  if (debug_on)
111398944Sobrien    printf ("clear_stepping_mode %d\n", (int) tid);
111446283Sdfr#endif
111546283Sdfr
111646283Sdfr  p = find_thread_info (tid);
111746283Sdfr  if (p == NULL)
111846283Sdfr    error ("Internal error: No thread state to clear?");
111946283Sdfr
112046283Sdfr  p->stepping_mode = DO_DEFAULT;
112146283Sdfr}
112246283Sdfr
112346283Sdfr/* Set all threads to do default continue on resume.
112446283Sdfr */
112546283Sdfrstatic void
112698944Sobrienclear_all_stepping_mode (void)
112746283Sdfr{
112898944Sobrien  thread_info *p;
112946283Sdfr
113046283Sdfr#ifdef WAIT_BUFFER_DEBUG
113198944Sobrien  if (debug_on)
113298944Sobrien    printf ("clear_all_stepping_mode\n");
113346283Sdfr#endif
113446283Sdfr
113598944Sobrien  for (p = thread_head.head; p; p = p->next)
113698944Sobrien    {
113798944Sobrien      p->stepping_mode = DO_DEFAULT;
113846283Sdfr    }
113946283Sdfr
114098944Sobrien  for (p = deleted_threads.head; p; p = p->next)
114198944Sobrien    {
114298944Sobrien      p->stepping_mode = DO_DEFAULT;
114346283Sdfr    }
114446283Sdfr}
114546283Sdfr
114646283Sdfr/* Set all threads to unseen on this pass.
114798944Sobrien */
114846283Sdfrstatic void
114998944Sobrienset_all_unseen (void)
115046283Sdfr{
115198944Sobrien  thread_info *p;
115246283Sdfr
115398944Sobrien  for (p = thread_head.head; p; p = p->next)
115498944Sobrien    {
115598944Sobrien      p->seen = 0;
115646283Sdfr    }
115746283Sdfr}
115846283Sdfr
115946283Sdfr#if (defined( THREAD_DEBUG ) || defined( PARANOIA ))
116046283Sdfr/* debugging routine.
116146283Sdfr */
116246283Sdfrstatic void
116398944Sobrienprint_tthread (thread_info *p)
116446283Sdfr{
116598944Sobrien  printf (" Thread pid %d, tid %d", p->pid, p->tid);
116698944Sobrien  if (p->have_state)
116798944Sobrien    printf (", event is %s",
116898944Sobrien	 get_printable_name_of_ttrace_event (p->last_stop_state.tts_event));
116946283Sdfr
117098944Sobrien  if (p->am_pseudo)
117198944Sobrien    printf (", pseudo thread");
117298944Sobrien
117398944Sobrien  if (p->have_signal)
117498944Sobrien    printf (", have signal 0x%x", p->signal_value);
117598944Sobrien
117698944Sobrien  if (p->have_start)
117798944Sobrien    printf (", have start at 0x%x", p->start);
117898944Sobrien
117998944Sobrien  printf (", step is %s", get_printable_name_of_stepping_mode (p->stepping_mode));
118098944Sobrien
118198944Sobrien  if (p->handled)
118298944Sobrien    printf (", handled");
118398944Sobrien  else
118498944Sobrien    printf (", not handled");
118598944Sobrien
118698944Sobrien  if (p->seen)
118798944Sobrien    printf (", seen");
118898944Sobrien  else
118998944Sobrien    printf (", not seen");
119098944Sobrien
119198944Sobrien  printf ("\n");
119246283Sdfr}
119346283Sdfr
119446283Sdfrstatic void
119598944Sobrienprint_tthreads (void)
119646283Sdfr{
119798944Sobrien  thread_info *p;
119846283Sdfr
119998944Sobrien  if (thread_head.count == 0)
120098944Sobrien    printf ("Thread list is empty\n");
120198944Sobrien  else
120298944Sobrien    {
120398944Sobrien      printf ("Thread list has ");
120498944Sobrien      if (thread_head.count == 1)
120598944Sobrien	printf ("1 entry:\n");
120698944Sobrien      else
120798944Sobrien	printf ("%d entries:\n", thread_head.count);
120898944Sobrien      for (p = thread_head.head; p; p = p->next)
120998944Sobrien	{
121098944Sobrien	  print_tthread (p);
121198944Sobrien	}
121246283Sdfr    }
121346283Sdfr
121498944Sobrien  if (deleted_threads.count == 0)
121598944Sobrien    printf ("Deleted thread list is empty\n");
121698944Sobrien  else
121798944Sobrien    {
121898944Sobrien      printf ("Deleted thread list has ");
121998944Sobrien      if (deleted_threads.count == 1)
122098944Sobrien	printf ("1 entry:\n");
122198944Sobrien      else
122298944Sobrien	printf ("%d entries:\n", deleted_threads.count);
122346283Sdfr
122498944Sobrien      for (p = deleted_threads.head; p; p = p->next)
122598944Sobrien	{
122698944Sobrien	  print_tthread (p);
122798944Sobrien	}
122846283Sdfr    }
122946283Sdfr}
123046283Sdfr#endif
123146283Sdfr
123246283Sdfr/* Update the thread list based on the "seen" bits.
123346283Sdfr */
123446283Sdfrstatic void
123598944Sobrienupdate_thread_list (void)
123646283Sdfr{
123798944Sobrien  thread_info *p;
123898944Sobrien  thread_info *chase;
123946283Sdfr
124098944Sobrien  chase = NULL;
124198944Sobrien  for (p = thread_head.head; p; p = p->next)
124298944Sobrien    {
124346283Sdfr      /* Is this an "unseen" thread which really happens to be a process?
124498944Sobrien         If so, is it inferior_ptid and is a vfork in flight?  If yes to
124546283Sdfr         all, then DON'T REMOVE IT!  We're in the midst of moving a vfork
124646283Sdfr         operation, which is a multiple step thing, to the point where we
124746283Sdfr         can touch the parent again.  We've most likely stopped to examine
124846283Sdfr         the child at a late stage in the vfork, and if we're not following
124946283Sdfr         the child, we'd best not treat the parent as a dead "thread"...
125098944Sobrien       */
125198944Sobrien      if ((!p->seen) && p->am_pseudo && vfork_in_flight
125298944Sobrien	  && (p->pid != vforking_child_pid))
125398944Sobrien	p->seen = 1;
125446283Sdfr
125598944Sobrien      if (!p->seen)
125698944Sobrien	{
125798944Sobrien	  /* Remove this one
125898944Sobrien	   */
125946283Sdfr
126046283Sdfr#ifdef THREAD_DEBUG
126198944Sobrien	  if (debug_on)
126298944Sobrien	    printf ("Delete unseen thread: %d \n", p->tid);
126346283Sdfr#endif
126498944Sobrien	  del_tthread (p->tid);
126598944Sobrien	}
126646283Sdfr    }
126746283Sdfr}
126898944Sobrien
126946283Sdfr
127098944Sobrien
127146283Sdfr/************************************************
127246283Sdfr *            O/S call wrappers                 *
127346283Sdfr ************************************************
127446283Sdfr */
127546283Sdfr
127646283Sdfr/* This function simply calls ttrace with the given arguments.
127746283Sdfr * It exists so that all calls to ttrace are isolated.  All
127846283Sdfr * parameters should be as specified by "man 2 ttrace".
127946283Sdfr *
128046283Sdfr * No other "raw" calls to ttrace should exist in this module.
128146283Sdfr */
128246283Sdfrstatic int
128398944Sobriencall_real_ttrace (ttreq_t request, pid_t pid, lwpid_t tid, TTRACE_ARG_TYPE addr,
128498944Sobrien		  TTRACE_ARG_TYPE data, TTRACE_ARG_TYPE addr2)
128546283Sdfr{
128698944Sobrien  int tt_status;
128746283Sdfr
128846283Sdfr  errno = 0;
128998944Sobrien  tt_status = ttrace (request, pid, tid, addr, data, addr2);
129046283Sdfr
129146283Sdfr#ifdef THREAD_DEBUG
129298944Sobrien  if (errno)
129398944Sobrien    {
129498944Sobrien      /* Don't bother for a known benign error: if you ask for the
129598944Sobrien       * first thread state, but there is only one thread and it's
129698944Sobrien       * not stopped, ttrace complains.
129798944Sobrien       *
129898944Sobrien       * We have this inside the #ifdef because our caller will do
129998944Sobrien       * this check for real.
130098944Sobrien       */
130198944Sobrien      if (request != TT_PROC_GET_FIRST_LWP_STATE
130298944Sobrien	  || errno != EPROTO)
130398944Sobrien	{
130498944Sobrien	  if (debug_on)
130598944Sobrien	    printf ("TT fail for %s, with pid %d, tid %d, status %d \n",
130698944Sobrien		    get_printable_name_of_ttrace_request (request),
130798944Sobrien		    pid, tid, tt_status);
130898944Sobrien	}
130946283Sdfr    }
131046283Sdfr#endif
131146283Sdfr
131246283Sdfr#if 0
131346283Sdfr  /* ??rehrauer: It would probably be most robust to catch and report
131446283Sdfr   * failed requests here.  However, some clients of this interface
131546283Sdfr   * seem to expect to catch & deal with them, so we'd best not.
131646283Sdfr   */
131798944Sobrien  if (errno)
131898944Sobrien    {
131998944Sobrien      strcpy (reason_for_failure, "ttrace (");
132098944Sobrien      strcat (reason_for_failure, get_printable_name_of_ttrace_request (request));
132198944Sobrien      strcat (reason_for_failure, ")");
132298944Sobrien      printf ("ttrace error, errno = %d\n", errno);
132398944Sobrien      perror_with_name (reason_for_failure);
132498944Sobrien    }
132546283Sdfr#endif
132646283Sdfr
132746283Sdfr  return tt_status;
132846283Sdfr}
132998944Sobrien
133046283Sdfr
133146283Sdfr/* This function simply calls ttrace_wait with the given arguments.
133246283Sdfr * It exists so that all calls to ttrace_wait are isolated.
133346283Sdfr *
133446283Sdfr * No "raw" calls to ttrace_wait should exist elsewhere.
133546283Sdfr */
133646283Sdfrstatic int
133798944Sobriencall_real_ttrace_wait (int pid, lwpid_t tid, ttwopt_t option, ttstate_t *tsp,
133898944Sobrien		       size_t tsp_size)
133946283Sdfr{
134098944Sobrien  int ttw_status;
134198944Sobrien  thread_info *tinfo = NULL;
134246283Sdfr
134346283Sdfr  errno = 0;
134446283Sdfr  ttw_status = ttrace_wait (pid, tid, option, tsp, tsp_size);
134598944Sobrien
134698944Sobrien  if (errno)
134798944Sobrien    {
134846283Sdfr#ifdef THREAD_DEBUG
134998944Sobrien      if (debug_on)
135098944Sobrien	printf ("TW fail with pid %d, tid %d \n", pid, tid);
135146283Sdfr#endif
135246283Sdfr
135346283Sdfr      perror_with_name ("ttrace wait");
135498944Sobrien    }
135546283Sdfr
135646283Sdfr  return ttw_status;
135746283Sdfr}
135898944Sobrien
135946283Sdfr
136046283Sdfr/* A process may have one or more kernel threads, of which all or
136146283Sdfr   none may be stopped.  This function returns the ID of the first
136246283Sdfr   kernel thread in a stopped state, or 0 if none are stopped.
136346283Sdfr
136446283Sdfr   This function can be used with get_process_next_stopped_thread_id
136546283Sdfr   to iterate over the IDs of all stopped threads of this process.
136646283Sdfr */
136746283Sdfrstatic lwpid_t
136898944Sobrienget_process_first_stopped_thread_id (int pid, ttstate_t *thread_state)
136946283Sdfr{
137098944Sobrien  int tt_status;
137146283Sdfr
137298944Sobrien  tt_status = call_real_ttrace (TT_PROC_GET_FIRST_LWP_STATE,
137398944Sobrien				(pid_t) pid,
137498944Sobrien				(lwpid_t) TT_NIL,
137598944Sobrien				(TTRACE_ARG_TYPE) thread_state,
137698944Sobrien				(TTRACE_ARG_TYPE) sizeof (*thread_state),
137798944Sobrien				TT_NIL);
137898944Sobrien
137998944Sobrien  if (errno)
138098944Sobrien    {
138198944Sobrien      if (errno == EPROTO)
138298944Sobrien	{
138398944Sobrien	  /* This is an error we can handle: there isn't any stopped
138498944Sobrien	   * thread.  This happens when we're re-starting the application
138598944Sobrien	   * and it has only one thread.  GET_NEXT handles the case of
138698944Sobrien	   * no more stopped threads well; GET_FIRST doesn't.  (A ttrace
138798944Sobrien	   * "feature".)
138898944Sobrien	   */
138998944Sobrien	  tt_status = 1;
139098944Sobrien	  errno = 0;
139198944Sobrien	  return 0;
139298944Sobrien	}
139398944Sobrien      else
139498944Sobrien	perror_with_name ("ttrace");
139546283Sdfr    }
139698944Sobrien
139798944Sobrien  if (tt_status < 0)
139846283Sdfr    /* Failed somehow.
139946283Sdfr     */
140046283Sdfr    return 0;
140146283Sdfr
140246283Sdfr  return thread_state->tts_lwpid;
140346283Sdfr}
140498944Sobrien
140546283Sdfr
140646283Sdfr/* This function returns the ID of the "next" kernel thread in a
140746283Sdfr   stopped state, or 0 if there are none.  "Next" refers to the
140846283Sdfr   thread following that of the last successful call to this
140946283Sdfr   function or to get_process_first_stopped_thread_id, using
141046283Sdfr   the value of thread_state returned by that call.
141146283Sdfr
141246283Sdfr   This function can be used with get_process_first_stopped_thread_id
141346283Sdfr   to iterate over the IDs of all stopped threads of this process.
141446283Sdfr */
141546283Sdfrstatic lwpid_t
141698944Sobrienget_process_next_stopped_thread_id (int pid, ttstate_t *thread_state)
141746283Sdfr{
141898944Sobrien  int tt_status;
141946283Sdfr
142046283Sdfr  tt_status = call_real_ttrace (
142198944Sobrien				 TT_PROC_GET_NEXT_LWP_STATE,
142298944Sobrien				 (pid_t) pid,
142398944Sobrien				 (lwpid_t) TT_NIL,
142498944Sobrien				 (TTRACE_ARG_TYPE) thread_state,
142598944Sobrien				 (TTRACE_ARG_TYPE) sizeof (*thread_state),
142698944Sobrien				 TT_NIL);
142746283Sdfr  if (errno)
142846283Sdfr    perror_with_name ("ttrace");
142946283Sdfr
143046283Sdfr  if (tt_status < 0)
143146283Sdfr    /* Failed
143246283Sdfr     */
143346283Sdfr    return 0;
143446283Sdfr
143598944Sobrien  else if (tt_status == 0)
143698944Sobrien    {
143798944Sobrien      /* End of list, no next state.  Don't return the
143898944Sobrien       * tts_lwpid, as it's a meaningless "240".
143998944Sobrien       *
144098944Sobrien       * This is an HPUX "feature".
144198944Sobrien       */
144298944Sobrien      return 0;
144398944Sobrien    }
144498944Sobrien
144546283Sdfr  return thread_state->tts_lwpid;
144646283Sdfr}
144746283Sdfr
144846283Sdfr/* ??rehrauer: Eventually this function perhaps should be calling
144946283Sdfr   pid_to_thread_id.  However, that function currently does nothing
145046283Sdfr   for HP-UX.  Even then, I'm not clear whether that function
145146283Sdfr   will return a "kernel" thread ID, or a "user" thread ID.  If
145246283Sdfr   the former, we can just call it here.  If the latter, we must
145346283Sdfr   map from the "user" tid to a "kernel" tid.
145446283Sdfr
145546283Sdfr   NOTE: currently not called.
145646283Sdfr */
145746283Sdfrstatic lwpid_t
145898944Sobrienget_active_tid_of_pid (int pid)
145946283Sdfr{
146098944Sobrien  ttstate_t thread_state;
146146283Sdfr
146246283Sdfr  return get_process_first_stopped_thread_id (pid, &thread_state);
146346283Sdfr}
146446283Sdfr
146546283Sdfr/* This function returns 1 if tt_request is a ttrace request that
146646283Sdfr * operates upon all threads of a (i.e., the entire) process.
146746283Sdfr */
146846283Sdfrint
146998944Sobrienis_process_ttrace_request (ttreq_t tt_request)
147046283Sdfr{
147146283Sdfr  return IS_TTRACE_PROCREQ (tt_request);
147246283Sdfr}
147398944Sobrien
147446283Sdfr
147546283Sdfr/* This function translates a thread ttrace request into
147646283Sdfr * the equivalent process request for a one-thread process.
147746283Sdfr */
147846283Sdfrstatic ttreq_t
147998944Sobrienmake_process_version (ttreq_t request)
148046283Sdfr{
148198944Sobrien  if (!IS_TTRACE_REQ (request))
148298944Sobrien    {
148398944Sobrien      error ("Internal error, bad ttrace request made\n");
148498944Sobrien      return -1;
148598944Sobrien    }
148646283Sdfr
148798944Sobrien  switch (request)
148898944Sobrien    {
148998944Sobrien    case TT_LWP_STOP:
149046283Sdfr      return TT_PROC_STOP;
149146283Sdfr
149298944Sobrien    case TT_LWP_CONTINUE:
149346283Sdfr      return TT_PROC_CONTINUE;
149446283Sdfr
149598944Sobrien    case TT_LWP_GET_EVENT_MASK:
149646283Sdfr      return TT_PROC_GET_EVENT_MASK;
149746283Sdfr
149898944Sobrien    case TT_LWP_SET_EVENT_MASK:
149946283Sdfr      return TT_PROC_SET_EVENT_MASK;
150046283Sdfr
150198944Sobrien    case TT_LWP_SINGLE:
150298944Sobrien    case TT_LWP_RUREGS:
150398944Sobrien    case TT_LWP_WUREGS:
150498944Sobrien    case TT_LWP_GET_STATE:
150598944Sobrien      return -1;		/* No equivalent */
150646283Sdfr
150798944Sobrien    default:
150846283Sdfr      return request;
150998944Sobrien    }
151046283Sdfr}
151198944Sobrien
151246283Sdfr
151346283Sdfr/* This function translates the "pid" used by the rest of
151446283Sdfr * gdb to a real pid and a tid.  It then calls "call_real_ttrace"
151546283Sdfr * with the given arguments.
151646283Sdfr *
151746283Sdfr * In general, other parts of this module should call this
151846283Sdfr * function when they are dealing with external users, who only
151946283Sdfr * have tids to pass (but they call it "pid" for historical
152046283Sdfr * reasons).
152146283Sdfr */
152246283Sdfrstatic int
152398944Sobriencall_ttrace (ttreq_t request, int gdb_tid, TTRACE_ARG_TYPE addr,
152498944Sobrien	     TTRACE_ARG_TYPE data, TTRACE_ARG_TYPE addr2)
152546283Sdfr{
152698944Sobrien  lwpid_t real_tid;
152798944Sobrien  int real_pid;
152898944Sobrien  ttreq_t new_request;
152998944Sobrien  int tt_status;
153098944Sobrien  char reason_for_failure[100];	/* Arbitrary size, should be big enough. */
153198944Sobrien
153246283Sdfr#ifdef THREAD_DEBUG
153398944Sobrien  int is_interesting = 0;
153446283Sdfr
153598944Sobrien  if (TT_LWP_RUREGS == request)
153698944Sobrien    {
153798944Sobrien      is_interesting = 1;	/* Adjust code here as desired */
153898944Sobrien    }
153998944Sobrien
154098944Sobrien  if (is_interesting && 0 && debug_on)
154198944Sobrien    {
154298944Sobrien      if (!is_process_ttrace_request (request))
154398944Sobrien	{
154498944Sobrien	  printf ("TT: Thread request, tid is %d", gdb_tid);
154598944Sobrien	  printf ("== SINGLE at %x", addr);
154698944Sobrien	}
154798944Sobrien      else
154898944Sobrien	{
154998944Sobrien	  printf ("TT: Process request, tid is %d\n", gdb_tid);
155098944Sobrien	  printf ("==! SINGLE at %x", addr);
155198944Sobrien	}
155298944Sobrien    }
155346283Sdfr#endif
155446283Sdfr
155546283Sdfr  /* The initial SETTRC and SET_EVENT_MASK calls (and all others
155646283Sdfr   * which happen before any threads get set up) should go
155746283Sdfr   * directly to "call_real_ttrace", so they don't happen here.
155846283Sdfr   *
155946283Sdfr   * But hardware watchpoints do a SET_EVENT_MASK, so we can't
156046283Sdfr   * rule them out....
156146283Sdfr   */
156246283Sdfr#ifdef THREAD_DEBUG
156398944Sobrien  if (request == TT_PROC_SETTRC && debug_on)
156498944Sobrien    printf ("Unexpected call for TT_PROC_SETTRC\n");
156546283Sdfr#endif
156646283Sdfr
156746283Sdfr  /* Sometimes we get called with a bogus tid (e.g., if a
156846283Sdfr   * thread has terminated, we return 0; inftarg later asks
156946283Sdfr   * whether the thread has exited/forked/vforked).
157046283Sdfr   */
157198944Sobrien  if (gdb_tid == 0)
157246283Sdfr    {
157398944Sobrien      errno = ESRCH;		/* ttrace's response would probably be "No such process". */
157446283Sdfr      return -1;
157546283Sdfr    }
157646283Sdfr
157746283Sdfr  /* All other cases should be able to expect that there are
157846283Sdfr   * thread records.
157946283Sdfr   */
158098944Sobrien  if (!any_thread_records ())
158198944Sobrien    {
158246283Sdfr#ifdef THREAD_DEBUG
158398944Sobrien      if (debug_on)
158498944Sobrien	warning ("No thread records for ttrace call");
158546283Sdfr#endif
158698944Sobrien      errno = ESRCH;		/* ttrace's response would be "No such process". */
158746283Sdfr      return -1;
158898944Sobrien    }
158946283Sdfr
159046283Sdfr  /* OK, now the task is to translate the incoming tid into
159146283Sdfr   * a pid/tid pair.
159246283Sdfr   */
159398944Sobrien  real_tid = map_from_gdb_tid (gdb_tid);
159498944Sobrien  real_pid = get_pid_for (real_tid);
159546283Sdfr
159646283Sdfr  /* Now check the result.  "Real_pid" is NULL if our list
159746283Sdfr   * didn't find it.  We have some tricks we can play to fix
159846283Sdfr   * this, however.
159946283Sdfr   */
160098944Sobrien  if (0 == real_pid)
160198944Sobrien    {
160298944Sobrien      ttstate_t thread_state;
160346283Sdfr
160446283Sdfr#ifdef THREAD_DEBUG
160598944Sobrien      if (debug_on)
160698944Sobrien	printf ("No saved pid for tid %d\n", gdb_tid);
160746283Sdfr#endif
160846283Sdfr
160998944Sobrien      if (is_process_ttrace_request (request))
161098944Sobrien	{
161198944Sobrien
161298944Sobrien	  /* Ok, we couldn't get a tid.  Try to translate to
161398944Sobrien	   * the equivalent process operation.  We expect this
161498944Sobrien	   * NOT to happen, so this is a desparation-type
161598944Sobrien	   * move.  It can happen if there is an internal
161698944Sobrien	   * error and so no "wait()" call is ever done.
161798944Sobrien	   */
161898944Sobrien	  new_request = make_process_version (request);
161998944Sobrien	  if (new_request == -1)
162098944Sobrien	    {
162198944Sobrien
162246283Sdfr#ifdef THREAD_DEBUG
162398944Sobrien	      if (debug_on)
162498944Sobrien		printf ("...and couldn't make process version of thread operation\n");
162546283Sdfr#endif
162646283Sdfr
162798944Sobrien	      /* Use hacky saved pid, which won't always be correct
162898944Sobrien	       * in the multi-process future.  Use tid as thread,
162998944Sobrien	       * probably dooming this to failure.  FIX!
163098944Sobrien	       */
163198944Sobrien	      if (! ptid_equal (saved_real_ptid, null_ptid))
163298944Sobrien		{
163346283Sdfr#ifdef THREAD_DEBUG
163498944Sobrien		  if (debug_on)
163598944Sobrien		    printf ("...using saved pid %d\n",
163698944Sobrien		            PIDGET (saved_real_ptid));
163746283Sdfr#endif
163846283Sdfr
163998944Sobrien		  real_pid = PIDGET (saved_real_ptid);
164098944Sobrien		  real_tid = gdb_tid;
164198944Sobrien		}
164246283Sdfr
164398944Sobrien	      else
164498944Sobrien		error ("Unable to perform thread operation");
164598944Sobrien	    }
164646283Sdfr
164798944Sobrien	  else
164898944Sobrien	    {
164998944Sobrien	      /* Sucessfully translated this to a process request,
165098944Sobrien	       * which needs no thread value.
165198944Sobrien	       */
165298944Sobrien	      real_pid = gdb_tid;
165398944Sobrien	      real_tid = 0;
165498944Sobrien	      request = new_request;
165546283Sdfr
165646283Sdfr#ifdef THREAD_DEBUG
165798944Sobrien	      if (debug_on)
165898944Sobrien		{
165998944Sobrien		  printf ("Translated thread request to process request\n");
166098944Sobrien		  if (ptid_equal (saved_real_ptid, null_ptid))
166198944Sobrien		    printf ("...but there's no saved pid\n");
166298944Sobrien
166398944Sobrien		  else
166498944Sobrien		    {
166598944Sobrien		      if (gdb_tid != PIDGET (saved_real_ptid))
166698944Sobrien			printf ("...but have the wrong pid (%d rather than %d)\n",
166798944Sobrien				gdb_tid, PIDGET (saved_real_ptid));
166898944Sobrien		    }
166998944Sobrien		}
167046283Sdfr#endif
167198944Sobrien	    }			/* Translated to a process request */
167298944Sobrien	}			/* Is a process request */
167346283Sdfr
167498944Sobrien      else
167598944Sobrien	{
167698944Sobrien	  /* We have to have a thread.  Ooops.
167798944Sobrien	   */
167898944Sobrien	  error ("Thread request with no threads (%s)",
167998944Sobrien		 get_printable_name_of_ttrace_request (request));
168098944Sobrien	}
168146283Sdfr    }
168246283Sdfr
168346283Sdfr  /* Ttrace doesn't like to see tid values on process requests,
168446283Sdfr   * even if we have the right one.
168546283Sdfr   */
168698944Sobrien  if (is_process_ttrace_request (request))
168798944Sobrien    {
168846283Sdfr      real_tid = 0;
168998944Sobrien    }
169098944Sobrien
169146283Sdfr#ifdef THREAD_DEBUG
169298944Sobrien  if (is_interesting && 0 && debug_on)
169398944Sobrien    {
169498944Sobrien      printf ("    now tid %d, pid %d\n", real_tid, real_pid);
169598944Sobrien      printf ("    request is %s\n", get_printable_name_of_ttrace_request (request));
169698944Sobrien    }
169746283Sdfr#endif
169846283Sdfr
169946283Sdfr  /* Finally, the (almost) real call.
170046283Sdfr   */
170146283Sdfr  tt_status = call_real_ttrace (request, real_pid, real_tid, addr, data, addr2);
170246283Sdfr
170346283Sdfr#ifdef THREAD_DEBUG
170498944Sobrien  if (is_interesting && debug_on)
170598944Sobrien    {
170698944Sobrien      if (!TT_OK (tt_status, errno)
170798944Sobrien	  && !(tt_status == 0 & errno == 0))
170898944Sobrien	printf (" got error (errno==%d, status==%d)\n", errno, tt_status);
170998944Sobrien    }
171046283Sdfr#endif
171146283Sdfr
171246283Sdfr  return tt_status;
171346283Sdfr}
171446283Sdfr
171546283Sdfr
171646283Sdfr/* Stop all the threads of a process.
171798944Sobrien
171846283Sdfr * NOTE: use of TT_PROC_STOP can cause a thread with a real event
171946283Sdfr *       to get a TTEVT_NONE event, discarding the old event.  Be
172046283Sdfr *       very careful, and only call TT_PROC_STOP when you mean it!
172146283Sdfr */
172246283Sdfrstatic void
172398944Sobrienstop_all_threads_of_process (pid_t real_pid)
172446283Sdfr{
172598944Sobrien  int ttw_status;
172646283Sdfr
172746283Sdfr  ttw_status = call_real_ttrace (TT_PROC_STOP,
172898944Sobrien				 (pid_t) real_pid,
172998944Sobrien				 (lwpid_t) TT_NIL,
173098944Sobrien				 (TTRACE_ARG_TYPE) TT_NIL,
173198944Sobrien				 (TTRACE_ARG_TYPE) TT_NIL,
173298944Sobrien				 TT_NIL);
173346283Sdfr  if (errno)
173446283Sdfr    perror_with_name ("ttrace stop of other threads");
173546283Sdfr}
173646283Sdfr
173746283Sdfr
173846283Sdfr/* Under some circumstances, it's unsafe to attempt to stop, or even
173946283Sdfr   query the state of, a process' threads.
174046283Sdfr
174146283Sdfr   In ttrace-based HP-UX, an example is a vforking child process.  The
174246283Sdfr   vforking parent and child are somewhat fragile, w/r/t what we can do
174346283Sdfr   what we can do to them with ttrace, until after the child exits or
174446283Sdfr   execs, or until the parent's vfork event is delivered.  Until that
174546283Sdfr   time, we must not try to stop the process' threads, or inquire how
174646283Sdfr   many there are, or even alter its data segments, or it typically dies
174746283Sdfr   with a SIGILL.  Sigh.
174846283Sdfr
174946283Sdfr   This function returns 1 if this stopped process, and the event that
175046283Sdfr   we're told was responsible for its current stopped state, cannot safely
175146283Sdfr   have its threads examined.
175298944Sobrien */
175346283Sdfr#define CHILD_VFORKED(evt,pid) \
175498944Sobrien  (((evt) == TTEVT_VFORK) && ((pid) != PIDGET (inferior_ptid)))
175546283Sdfr#define CHILD_URPED(evt,pid) \
175646283Sdfr  ((((evt) == TTEVT_EXEC) || ((evt) == TTEVT_EXIT)) && ((pid) != vforking_child_pid))
175746283Sdfr#define PARENT_VFORKED(evt,pid) \
175898944Sobrien  (((evt) == TTEVT_VFORK) && ((pid) == PIDGET (inferior_ptid)))
175946283Sdfr
176046283Sdfrstatic int
176198944Sobriencan_touch_threads_of_process (int pid, ttevents_t stopping_event)
176246283Sdfr{
176346283Sdfr  if (CHILD_VFORKED (stopping_event, pid))
176446283Sdfr    {
176546283Sdfr      vforking_child_pid = pid;
176646283Sdfr      vfork_in_flight = 1;
176746283Sdfr    }
176846283Sdfr
176946283Sdfr  else if (vfork_in_flight &&
177098944Sobrien	   (PARENT_VFORKED (stopping_event, pid) ||
177198944Sobrien	    CHILD_URPED (stopping_event, pid)))
177246283Sdfr    {
177346283Sdfr      vfork_in_flight = 0;
177446283Sdfr      vforking_child_pid = 0;
177546283Sdfr    }
177646283Sdfr
177798944Sobrien  return !vfork_in_flight;
177846283Sdfr}
177946283Sdfr
178046283Sdfr
178146283Sdfr/* If we can find an as-yet-unhandled thread state of a
178246283Sdfr * stopped thread of this process return 1 and set "tsp".
178346283Sdfr * Return 0 if we can't.
178446283Sdfr *
178546283Sdfr * If this function is used when the threads of PIS haven't
178646283Sdfr * been stopped, undefined behaviour is guaranteed!
178746283Sdfr */
178898944Sobrienstatic int
178998944Sobrienselect_stopped_thread_of_process (int pid, ttstate_t *tsp)
179046283Sdfr{
179198944Sobrien  lwpid_t candidate_tid, tid;
179298944Sobrien  ttstate_t candidate_tstate, tstate;
179346283Sdfr
179446283Sdfr  /* If we're not allowed to touch the process now, then just
179546283Sdfr   * return the current value of *TSP.
179646283Sdfr   *
179746283Sdfr   * This supports "vfork".  It's ok, really, to double the
179846283Sdfr   * current event (the child EXEC, we hope!).
179946283Sdfr   */
180098944Sobrien  if (!can_touch_threads_of_process (pid, tsp->tts_event))
180146283Sdfr    return 1;
180246283Sdfr
180346283Sdfr  /* Decide which of (possibly more than one) events to
180446283Sdfr   * return as the first one.  We scan them all so that
180546283Sdfr   * we always return the result of a fake-step first.
180646283Sdfr   */
180746283Sdfr  candidate_tid = 0;
180846283Sdfr  for (tid = get_process_first_stopped_thread_id (pid, &tstate);
180946283Sdfr       tid != 0;
181046283Sdfr       tid = get_process_next_stopped_thread_id (pid, &tstate))
181146283Sdfr    {
181246283Sdfr      /* TTEVT_NONE events are uninteresting to our clients.  They're
181346283Sdfr       * an artifact of our "stop the world" model--the thread is
181446283Sdfr       * stopped because we stopped it.
181546283Sdfr       */
181698944Sobrien      if (tstate.tts_event == TTEVT_NONE)
181798944Sobrien	{
181898944Sobrien	  set_handled (pid, tstate.tts_lwpid);
181998944Sobrien	}
182046283Sdfr
182146283Sdfr      /* Did we just single-step a single thread, without letting any
182246283Sdfr       * of the others run?  Is this an event for that thread?
182346283Sdfr       *
182446283Sdfr       * If so, we believe our client would prefer to see this event
182546283Sdfr       * over any others.  (Typically the client wants to just push
182646283Sdfr       * one thread a little farther forward, and then go around
182746283Sdfr       * checking for what all threads are doing.)
182846283Sdfr       */
182946283Sdfr      else if (doing_fake_step && (tstate.tts_lwpid == fake_step_tid))
183098944Sobrien	{
183146283Sdfr#ifdef WAIT_BUFFER_DEBUG
183298944Sobrien	  /* It's possible here to see either a SIGTRAP (due to
183398944Sobrien	   * successful completion of a step) or a SYSCALL_ENTRY
183498944Sobrien	   * (due to a step completion with active hardware
183598944Sobrien	   * watchpoints).
183698944Sobrien	   */
183798944Sobrien	  if (debug_on)
183898944Sobrien	    printf ("Ending fake step with tid %d, state %s\n",
183998944Sobrien		    tstate.tts_lwpid,
184098944Sobrien		    get_printable_name_of_ttrace_event (tstate.tts_event));
184198944Sobrien#endif
184246283Sdfr
184398944Sobrien	  /* Remember this one, and throw away any previous
184498944Sobrien	   * candidate.
184598944Sobrien	   */
184698944Sobrien	  candidate_tid = tstate.tts_lwpid;
184798944Sobrien	  candidate_tstate = tstate;
184898944Sobrien	}
184946283Sdfr
185046283Sdfr#ifdef FORGET_DELETED_BPTS
185146283Sdfr
185246283Sdfr      /* We can't just do this, as if we do, and then wind
185346283Sdfr       * up the loop with no unhandled events, we need to
185446283Sdfr       * handle that case--the appropriate reaction is to
185546283Sdfr       * just continue, but there's no easy way to do that.
185646283Sdfr       *
185746283Sdfr       * Better to put this in the ttrace_wait call--if, when
185846283Sdfr       * we fake a wait, we update our events based on the
185946283Sdfr       * breakpoint_here_pc call and find there are no more events,
186046283Sdfr       * then we better continue and so on.
186146283Sdfr       *
186246283Sdfr       * Or we could put it in the next/continue fake.
186346283Sdfr       * But it has to go in the buffering code, not in the
186446283Sdfr       * real go/wait code.
186546283Sdfr       */
186698944Sobrien      else if ((TTEVT_SIGNAL == tstate.tts_event)
186798944Sobrien	       && (5 == tstate.tts_u.tts_signal.tts_signo)
186898944Sobrien	       && (0 != get_raw_pc (tstate.tts_lwpid))
186998944Sobrien	       && !breakpoint_here_p (get_raw_pc (tstate.tts_lwpid)))
187098944Sobrien	{
187198944Sobrien	  /*
187298944Sobrien	   * If the user deleted a breakpoint while this
187398944Sobrien	   * breakpoint-hit event was buffered, we can forget
187498944Sobrien	   * it now.
187598944Sobrien	   */
187646283Sdfr#ifdef WAIT_BUFFER_DEBUG
187798944Sobrien	  if (debug_on)
187898944Sobrien	    printf ("Forgetting deleted bp hit for thread %d\n",
187998944Sobrien		    tstate.tts_lwpid);
188098944Sobrien#endif
188146283Sdfr
188298944Sobrien	  set_handled (pid, tstate.tts_lwpid);
188398944Sobrien	}
188446283Sdfr#endif
188546283Sdfr
188646283Sdfr      /* Else, is this the first "unhandled" event?  If so,
188746283Sdfr       * we believe our client wants to see it (if we don't
188846283Sdfr       * see a fake-step later on in the scan).
188946283Sdfr       */
189098944Sobrien      else if (!was_handled (tstate.tts_lwpid) && candidate_tid == 0)
189198944Sobrien	{
189298944Sobrien	  candidate_tid = tstate.tts_lwpid;
189398944Sobrien	  candidate_tstate = tstate;
189498944Sobrien	}
189546283Sdfr
189646283Sdfr      /* This is either an event that has already been "handled",
189746283Sdfr       * and thus we believe is uninteresting to our client, or we
189846283Sdfr       * already have a candidate event.  Ignore it...
189946283Sdfr       */
190046283Sdfr    }
190146283Sdfr
190246283Sdfr  /* What do we report?
190346283Sdfr   */
190498944Sobrien  if (doing_fake_step)
190598944Sobrien    {
190698944Sobrien      if (candidate_tid == fake_step_tid)
190798944Sobrien	{
190898944Sobrien	  /* Fake step.
190998944Sobrien	   */
191098944Sobrien	  tstate = candidate_tstate;
191198944Sobrien	}
191298944Sobrien      else
191398944Sobrien	{
191498944Sobrien	  warning ("Internal error: fake-step failed to complete.");
191598944Sobrien	  return 0;
191698944Sobrien	}
191798944Sobrien    }
191898944Sobrien  else if (candidate_tid != 0)
191998944Sobrien    {
192046283Sdfr      /* Found a candidate unhandled event.
192146283Sdfr       */
192246283Sdfr      tstate = candidate_tstate;
192398944Sobrien    }
192498944Sobrien  else if (tid != 0)
192598944Sobrien    {
192698944Sobrien      warning ("Internal error in call of ttrace_wait.");
192746283Sdfr      return 0;
192898944Sobrien    }
192998944Sobrien  else
193098944Sobrien    {
193146283Sdfr      warning ("Internal error: no unhandled thread event to select");
193246283Sdfr      return 0;
193398944Sobrien    }
193446283Sdfr
193546283Sdfr  copy_ttstate_t (tsp, &tstate);
193646283Sdfr  return 1;
193798944Sobrien}				/* End of select_stopped_thread_of_process */
193846283Sdfr
193946283Sdfr#ifdef PARANOIA
194046283Sdfr/* Check our internal thread data against the real thing.
194146283Sdfr */
194246283Sdfrstatic void
194398944Sobriencheck_thread_consistency (pid_t real_pid)
194446283Sdfr{
194598944Sobrien  int tid;			/* really lwpid_t */
194698944Sobrien  ttstate_t tstate;
194798944Sobrien  thread_info *p;
194846283Sdfr
194998944Sobrien  /* Spin down the O/S list of threads, checking that they
195098944Sobrien   * match what we've got.
195198944Sobrien   */
195298944Sobrien  for (tid = get_process_first_stopped_thread_id (real_pid, &tstate);
195398944Sobrien       tid != 0;
195498944Sobrien       tid = get_process_next_stopped_thread_id (real_pid, &tstate))
195598944Sobrien    {
195646283Sdfr
195798944Sobrien      p = find_thread_info (tid);
195846283Sdfr
195998944Sobrien      if (NULL == p)
196098944Sobrien	{
196198944Sobrien	  warning ("No internal thread data for thread %d.", tid);
196298944Sobrien	  continue;
196398944Sobrien	}
196446283Sdfr
196598944Sobrien      if (!p->seen)
196698944Sobrien	{
196798944Sobrien	  warning ("Inconsistent internal thread data for thread %d.", tid);
196898944Sobrien	}
196946283Sdfr
197098944Sobrien      if (p->terminated)
197198944Sobrien	{
197298944Sobrien	  warning ("Thread %d is not terminated, internal error.", tid);
197398944Sobrien	  continue;
197498944Sobrien	}
197598944Sobrien
197698944Sobrien
197746283Sdfr#define TT_COMPARE( fld ) \
197846283Sdfr            tstate.fld != p->last_stop_state.fld
197998944Sobrien
198098944Sobrien      if (p->have_state)
198198944Sobrien	{
198298944Sobrien	  if (TT_COMPARE (tts_pid)
198398944Sobrien	      || TT_COMPARE (tts_lwpid)
198498944Sobrien	      || TT_COMPARE (tts_user_tid)
198598944Sobrien	      || TT_COMPARE (tts_event)
198698944Sobrien	      || TT_COMPARE (tts_flags)
198798944Sobrien	      || TT_COMPARE (tts_scno)
198898944Sobrien	      || TT_COMPARE (tts_scnargs))
198998944Sobrien	    {
199098944Sobrien	      warning ("Internal thread data for thread %d is wrong.", tid);
199198944Sobrien	      continue;
199298944Sobrien	    }
199398944Sobrien	}
199446283Sdfr    }
199546283Sdfr}
199698944Sobrien#endif /* PARANOIA */
199798944Sobrien
199846283Sdfr
199946283Sdfr/* This function wraps calls to "call_real_ttrace_wait" so
200046283Sdfr * that a actual wait is only done when all pending events
200146283Sdfr * have been reported.
200246283Sdfr *
200346283Sdfr * Note that typically it is called with a pid of "0", i.e.
200446283Sdfr * the "don't care" value.
200546283Sdfr *
200646283Sdfr * Return value is the status of the pseudo wait.
200746283Sdfr */
200846283Sdfrstatic int
200998944Sobriencall_ttrace_wait (int pid, ttwopt_t option, ttstate_t *tsp, size_t tsp_size)
201046283Sdfr{
201146283Sdfr  /* This holds the actual, for-real, true process ID.
201246283Sdfr   */
201346283Sdfr  static int real_pid;
201446283Sdfr
201546283Sdfr  /* As an argument to ttrace_wait, zero pid
201646283Sdfr   * means "Any process", and zero tid means
201746283Sdfr   * "Any thread of the specified process".
201846283Sdfr   */
201998944Sobrien  int wait_pid = 0;
202098944Sobrien  lwpid_t wait_tid = 0;
202198944Sobrien  lwpid_t real_tid;
202246283Sdfr
202398944Sobrien  int ttw_status = 0;		/* To be returned */
202446283Sdfr
202598944Sobrien  thread_info *tinfo = NULL;
202646283Sdfr
202798944Sobrien  if (pid != 0)
202898944Sobrien    {
202946283Sdfr      /* Unexpected case.
203046283Sdfr       */
203146283Sdfr#ifdef THREAD_DEBUG
203298944Sobrien      if (debug_on)
203398944Sobrien	printf ("TW: Pid to wait on is %d\n", pid);
203446283Sdfr#endif
203546283Sdfr
203698944Sobrien      if (!any_thread_records ())
203798944Sobrien	error ("No thread records for ttrace call w. specific pid");
203846283Sdfr
203946283Sdfr      /* OK, now the task is to translate the incoming tid into
204046283Sdfr       * a pid/tid pair.
204146283Sdfr       */
204298944Sobrien      real_tid = map_from_gdb_tid (pid);
204398944Sobrien      real_pid = get_pid_for (real_tid);
204446283Sdfr#ifdef THREAD_DEBUG
204598944Sobrien      if (debug_on)
204698944Sobrien	printf ("==TW: real pid %d, real tid %d\n", real_pid, real_tid);
204746283Sdfr#endif
204898944Sobrien    }
204946283Sdfr
205046283Sdfr
205146283Sdfr  /* Sanity checks and set-up.
205246283Sdfr   *                             Process State
205346283Sdfr   *
205446283Sdfr   *                        Stopped   Running    Fake-step  (v)Fork
205546283Sdfr   *                      \________________________________________
205646283Sdfr   *                      |
205746283Sdfr   *  No buffered events  |  error     wait       wait      wait
205846283Sdfr   *                      |
205946283Sdfr   *  Buffered events     |  debuffer  error      wait      debuffer (?)
206046283Sdfr   *
206146283Sdfr   */
206298944Sobrien  if (more_events_left == 0)
206398944Sobrien    {
206446283Sdfr
206598944Sobrien      if (process_state == RUNNING)
206698944Sobrien	{
206798944Sobrien	  /* OK--normal call of ttrace_wait with no buffered events.
206898944Sobrien	   */
206998944Sobrien	  ;
207098944Sobrien	}
207198944Sobrien      else if (process_state == FAKE_STEPPING)
207298944Sobrien	{
207398944Sobrien	  /* Ok--call of ttrace_wait to support
207498944Sobrien	   * fake stepping with no buffered events.
207598944Sobrien	   *
207698944Sobrien	   * But we better be fake-stepping!
207798944Sobrien	   */
207898944Sobrien	  if (!doing_fake_step)
207998944Sobrien	    {
208098944Sobrien	      warning ("Inconsistent thread state.");
208198944Sobrien	    }
208298944Sobrien	}
208398944Sobrien      else if ((process_state == FORKING)
208498944Sobrien	       || (process_state == VFORKING))
208598944Sobrien	{
208698944Sobrien	  /* Ok--there are two processes, so waiting
208798944Sobrien	   * for the second while the first is stopped
208898944Sobrien	   * is ok.  Handled bits stay as they were.
208998944Sobrien	   */
209098944Sobrien	  ;
209198944Sobrien	}
209298944Sobrien      else if (process_state == STOPPED)
209398944Sobrien	{
209498944Sobrien	  warning ("Process not running at wait call.");
209598944Sobrien	}
209646283Sdfr      else
209798944Sobrien	/* No known state.
209898944Sobrien	 */
209998944Sobrien	warning ("Inconsistent process state.");
210098944Sobrien    }
210198944Sobrien
210298944Sobrien  else
210398944Sobrien    {
210446283Sdfr      /* More events left
210546283Sdfr       */
210698944Sobrien      if (process_state == STOPPED)
210798944Sobrien	{
210898944Sobrien	  /* OK--buffered events being unbuffered.
210998944Sobrien	   */
211098944Sobrien	  ;
211198944Sobrien	}
211298944Sobrien      else if (process_state == RUNNING)
211398944Sobrien	{
211498944Sobrien	  /* An error--shouldn't have buffered events
211598944Sobrien	   * when running.
211698944Sobrien	   */
211798944Sobrien	  warning ("Trying to continue with buffered events:");
211898944Sobrien	}
211998944Sobrien      else if (process_state == FAKE_STEPPING)
212098944Sobrien	{
212198944Sobrien	  /*
212298944Sobrien	   * Better be fake-stepping!
212398944Sobrien	   */
212498944Sobrien	  if (!doing_fake_step)
212598944Sobrien	    {
212698944Sobrien	      warning ("Losing buffered thread events!\n");
212798944Sobrien	    }
212898944Sobrien	}
212998944Sobrien      else if ((process_state == FORKING)
213098944Sobrien	       || (process_state == VFORKING))
213198944Sobrien	{
213298944Sobrien	  /* Ok--there are two processes, so waiting
213398944Sobrien	   * for the second while the first is stopped
213498944Sobrien	   * is ok.  Handled bits stay as they were.
213598944Sobrien	   */
213698944Sobrien	  ;
213798944Sobrien	}
213846283Sdfr      else
213998944Sobrien	warning ("Process in unknown state with buffered events.");
214098944Sobrien    }
214146283Sdfr
214246283Sdfr  /* Sometimes we have to wait for a particular thread
214346283Sdfr   * (if we're stepping over a bpt).  In that case, we
214446283Sdfr   * _know_ it's going to complete the single-step we
214546283Sdfr   * asked for (because we're only doing the step under
214646283Sdfr   * certain very well-understood circumstances), so it
214746283Sdfr   * can't block.
214846283Sdfr   */
214998944Sobrien  if (doing_fake_step)
215098944Sobrien    {
215146283Sdfr      wait_tid = fake_step_tid;
215298944Sobrien      wait_pid = get_pid_for (fake_step_tid);
215346283Sdfr
215446283Sdfr#ifdef WAIT_BUFFER_DEBUG
215598944Sobrien      if (debug_on)
215698944Sobrien	printf ("Doing a wait after a fake-step for %d, pid %d\n",
215798944Sobrien		wait_tid, wait_pid);
215846283Sdfr#endif
215998944Sobrien    }
216046283Sdfr
216198944Sobrien  if (more_events_left == 0	/* No buffered events, need real ones. */
216298944Sobrien      || process_state != STOPPED)
216398944Sobrien    {
216446283Sdfr      /* If there are no buffered events, and so we need
216546283Sdfr       * real ones, or if we are FORKING, VFORKING,
216646283Sdfr       * FAKE_STEPPING or RUNNING, and thus have to do
216746283Sdfr       * a real wait, then do a real wait.
216846283Sdfr       */
216946283Sdfr
217046283Sdfr#ifdef WAIT_BUFFER_DEBUG
217146283Sdfr      /* Normal case... */
217298944Sobrien      if (debug_on)
217398944Sobrien	printf ("TW: do it for real; pid %d, tid %d\n", wait_pid, wait_tid);
217446283Sdfr#endif
217546283Sdfr
217646283Sdfr      /* The actual wait call.
217746283Sdfr       */
217898944Sobrien      ttw_status = call_real_ttrace_wait (wait_pid, wait_tid, option, tsp, tsp_size);
217946283Sdfr
218046283Sdfr      /* Note that the routines we'll call will be using "call_real_ttrace",
218146283Sdfr       * not "call_ttrace", and thus need the real pid rather than the pseudo-tid
218246283Sdfr       * the rest of the world uses (which is actually the tid).
218346283Sdfr       */
218446283Sdfr      real_pid = tsp->tts_pid;
218546283Sdfr
218646283Sdfr      /* For most events: Stop the world!
218798944Sobrien
218846283Sdfr       * It's sometimes not safe to stop all threads of a process.
218946283Sdfr       * Sometimes it's not even safe to ask for the thread state
219046283Sdfr       * of a process!
219146283Sdfr       */
219246283Sdfr      if (can_touch_threads_of_process (real_pid, tsp->tts_event))
219398944Sobrien	{
219498944Sobrien	  /* If we're really only stepping a single thread, then don't
219598944Sobrien	   * try to stop all the others -- we only do this single-stepping
219698944Sobrien	   * business when all others were already stopped...and the stop
219798944Sobrien	   * would mess up other threads' events.
219898944Sobrien	   *
219998944Sobrien	   * Similiarly, if there are other threads with events,
220098944Sobrien	   * don't do the stop.
220198944Sobrien	   */
220298944Sobrien	  if (!doing_fake_step)
220398944Sobrien	    {
220498944Sobrien	      if (more_events_left > 0)
220598944Sobrien		warning ("Internal error in stopping process");
220646283Sdfr
220798944Sobrien	      stop_all_threads_of_process (real_pid);
220898944Sobrien
220998944Sobrien	      /* At this point, we could scan and update_thread_list(),
221098944Sobrien	       * and only use the local list for the rest of the
221198944Sobrien	       * module! We'd get rid of the scans in the various
221298944Sobrien	       * continue routines (adding one in attach).  It'd
221398944Sobrien	       * be great--UPGRADE ME!
221498944Sobrien	       */
221598944Sobrien	    }
221698944Sobrien	}
221798944Sobrien
221846283Sdfr#ifdef PARANOIA
221998944Sobrien      else if (debug_on)
222098944Sobrien	{
222198944Sobrien	  if (more_events_left > 0)
222298944Sobrien	    printf ("== Can't stop process; more events!\n");
222398944Sobrien	  else
222498944Sobrien	    printf ("== Can't stop process!\n");
222598944Sobrien	}
222646283Sdfr#endif
222746283Sdfr
222898944Sobrien      process_state = STOPPED;
222946283Sdfr
223046283Sdfr#ifdef WAIT_BUFFER_DEBUG
223198944Sobrien      if (debug_on)
223298944Sobrien	printf ("Process set to STOPPED\n");
223346283Sdfr#endif
223498944Sobrien    }
223598944Sobrien
223698944Sobrien  else
223798944Sobrien    {
223846283Sdfr      /* Fake a call to ttrace_wait.  The process must be
223946283Sdfr       * STOPPED, as we aren't going to do any wait.
224046283Sdfr       */
224146283Sdfr#ifdef WAIT_BUFFER_DEBUG
224298944Sobrien      if (debug_on)
224398944Sobrien	printf ("TW: fake it\n");
224446283Sdfr#endif
224546283Sdfr
224698944Sobrien      if (process_state != STOPPED)
224798944Sobrien	{
224898944Sobrien	  warning ("Process not stopped at wait call, in state '%s'.\n",
224998944Sobrien		   get_printable_name_of_process_state (process_state));
225098944Sobrien	}
225146283Sdfr
225298944Sobrien      if (doing_fake_step)
225398944Sobrien	error ("Internal error in stepping over breakpoint");
225446283Sdfr
225598944Sobrien      ttw_status = 0;		/* Faking it is always successful! */
225698944Sobrien    }				/* End of fake or not? if */
225798944Sobrien
225846283Sdfr  /* Pick an event to pass to our caller.  Be paranoid.
225946283Sdfr   */
226098944Sobrien  if (!select_stopped_thread_of_process (real_pid, tsp))
226198944Sobrien    warning ("Can't find event, using previous event.");
226246283Sdfr
226398944Sobrien  else if (tsp->tts_event == TTEVT_NONE)
226498944Sobrien    warning ("Internal error: no thread has a real event.");
226546283Sdfr
226698944Sobrien  else if (doing_fake_step)
226798944Sobrien    {
226898944Sobrien      if (fake_step_tid != tsp->tts_lwpid)
226998944Sobrien	warning ("Internal error in stepping over breakpoint.");
227098944Sobrien
227146283Sdfr      /* This wait clears the (current) fake-step if there was one.
227246283Sdfr       */
227346283Sdfr      doing_fake_step = 0;
227498944Sobrien      fake_step_tid = 0;
227598944Sobrien    }
227646283Sdfr
227746283Sdfr  /* We now have a correct tsp and ttw_status for the thread
227846283Sdfr   * which we want to report.  So it's "handled"!  This call
227946283Sdfr   * will add it to our list if it's not there already.
228046283Sdfr   */
228198944Sobrien  set_handled (real_pid, tsp->tts_lwpid);
228246283Sdfr
228346283Sdfr  /* Save a copy of the ttrace state of this thread, in our local
228446283Sdfr     thread descriptor.
228546283Sdfr
228646283Sdfr     This caches the state.  The implementation of queries like
2287130803Smarcel     hpux_has_execd can then use this cached state, rather than
228846283Sdfr     be forced to make an explicit ttrace call to get it.
228946283Sdfr
229046283Sdfr     (Guard against the condition that this is the first time we've
229146283Sdfr     waited on, i.e., seen this thread, and so haven't yet entered
229246283Sdfr     it into our list of threads.)
229346283Sdfr   */
229446283Sdfr  tinfo = find_thread_info (tsp->tts_lwpid);
229598944Sobrien  if (tinfo != NULL)
229698944Sobrien    {
229798944Sobrien      copy_ttstate_t (&tinfo->last_stop_state, tsp);
229898944Sobrien      tinfo->have_state = 1;
229998944Sobrien    }
230098944Sobrien
230146283Sdfr  return ttw_status;
230298944Sobrien}				/* call_ttrace_wait */
230346283Sdfr
230446283Sdfr#if defined(CHILD_REPORTED_EXEC_EVENTS_PER_EXEC_CALL)
230546283Sdfrint
230698944Sobrienchild_reported_exec_events_per_exec_call (void)
230746283Sdfr{
230898944Sobrien  return 1;			/* ttrace reports the event once per call. */
230946283Sdfr}
231046283Sdfr#endif
231198944Sobrien
231246283Sdfr
231346283Sdfr
231446283Sdfr/* Our implementation of hardware watchpoints involves making memory
231546283Sdfr   pages write-protected.  We must remember a page's original permissions,
231646283Sdfr   and we must also know when it is appropriate to restore a page's
231746283Sdfr   permissions to its original state.
231846283Sdfr
231946283Sdfr   We use a "dictionary" of hardware-watched pages to do this.  Each
232046283Sdfr   hardware-watched page is recorded in the dictionary.  Each page's
232146283Sdfr   dictionary entry contains the original permissions and a reference
232246283Sdfr   count.  Pages are hashed into the dictionary by their start address.
232346283Sdfr
232446283Sdfr   When hardware watchpoint is set on page X for the first time, page X
232546283Sdfr   is added to the dictionary with a reference count of 1.  If other
232646283Sdfr   hardware watchpoints are subsequently set on page X, its reference
232746283Sdfr   count is incremented.  When hardware watchpoints are removed from
232846283Sdfr   page X, its reference count is decremented.  If a page's reference
232946283Sdfr   count drops to 0, it's permissions are restored and the page's entry
233046283Sdfr   is thrown out of the dictionary.
233198944Sobrien */
233298944Sobrientypedef struct memory_page
233398944Sobrien{
233498944Sobrien  CORE_ADDR page_start;
233598944Sobrien  int reference_count;
233698944Sobrien  int original_permissions;
233798944Sobrien  struct memory_page *next;
233898944Sobrien  struct memory_page *previous;
233998944Sobrien}
234098944Sobrienmemory_page_t;
234146283Sdfr
234246283Sdfr#define MEMORY_PAGE_DICTIONARY_BUCKET_COUNT  128
234346283Sdfr
234498944Sobrienstatic struct
234598944Sobrien  {
234698944Sobrien    LONGEST page_count;
234798944Sobrien    int page_size;
234898944Sobrien    int page_protections_allowed;
234998944Sobrien    /* These are just the heads of chains of actual page descriptors. */
235098944Sobrien    memory_page_t buckets[MEMORY_PAGE_DICTIONARY_BUCKET_COUNT];
235198944Sobrien  }
235298944Sobrienmemory_page_dictionary;
235346283Sdfr
235446283Sdfr
235546283Sdfrstatic void
235698944Sobrienrequire_memory_page_dictionary (void)
235746283Sdfr{
235898944Sobrien  int i;
235946283Sdfr
236046283Sdfr  /* Is the memory page dictionary ready for use?  If so, we're done. */
236146283Sdfr  if (memory_page_dictionary.page_count >= (LONGEST) 0)
236246283Sdfr    return;
236346283Sdfr
236446283Sdfr  /* Else, initialize it. */
236546283Sdfr  memory_page_dictionary.page_count = (LONGEST) 0;
236646283Sdfr
236798944Sobrien  for (i = 0; i < MEMORY_PAGE_DICTIONARY_BUCKET_COUNT; i++)
236846283Sdfr    {
236946283Sdfr      memory_page_dictionary.buckets[i].page_start = (CORE_ADDR) 0;
237046283Sdfr      memory_page_dictionary.buckets[i].reference_count = 0;
237146283Sdfr      memory_page_dictionary.buckets[i].next = NULL;
237246283Sdfr      memory_page_dictionary.buckets[i].previous = NULL;
237346283Sdfr    }
237446283Sdfr}
237546283Sdfr
237646283Sdfr
237746283Sdfrstatic void
237898944Sobrienretire_memory_page_dictionary (void)
237946283Sdfr{
238098944Sobrien  memory_page_dictionary.page_count = (LONGEST) - 1;
238146283Sdfr}
238246283Sdfr
238346283Sdfr
238446283Sdfr/* Write-protect the memory page that starts at this address.
238546283Sdfr
238646283Sdfr   Returns the original permissions of the page.
238746283Sdfr */
238846283Sdfrstatic int
238998944Sobrienwrite_protect_page (int pid, CORE_ADDR page_start)
239046283Sdfr{
239198944Sobrien  int tt_status;
239298944Sobrien  int original_permissions;
239398944Sobrien  int new_permissions;
239446283Sdfr
239546283Sdfr  tt_status = call_ttrace (TT_PROC_GET_MPROTECT,
239698944Sobrien			   pid,
239798944Sobrien			   (TTRACE_ARG_TYPE) page_start,
239898944Sobrien			   TT_NIL,
239998944Sobrien			   (TTRACE_ARG_TYPE) & original_permissions);
240046283Sdfr  if (errno || (tt_status < 0))
240146283Sdfr    {
240298944Sobrien      return 0;			/* What else can we do? */
240346283Sdfr    }
240446283Sdfr
240546283Sdfr  /* We'll also write-protect the page now, if that's allowed. */
240646283Sdfr  if (memory_page_dictionary.page_protections_allowed)
240746283Sdfr    {
240846283Sdfr      new_permissions = original_permissions & ~PROT_WRITE;
240946283Sdfr      tt_status = call_ttrace (TT_PROC_SET_MPROTECT,
241098944Sobrien			       pid,
241198944Sobrien			       (TTRACE_ARG_TYPE) page_start,
241298944Sobrien			 (TTRACE_ARG_TYPE) memory_page_dictionary.page_size,
241398944Sobrien			       (TTRACE_ARG_TYPE) new_permissions);
241446283Sdfr      if (errno || (tt_status < 0))
241598944Sobrien	{
241698944Sobrien	  return 0;		/* What else can we do? */
241798944Sobrien	}
241846283Sdfr    }
241946283Sdfr
242046283Sdfr  return original_permissions;
242146283Sdfr}
242246283Sdfr
242346283Sdfr
242446283Sdfr/* Unwrite-protect the memory page that starts at this address, restoring
242546283Sdfr   (what we must assume are) its original permissions.
242698944Sobrien */
242746283Sdfrstatic void
242898944Sobrienunwrite_protect_page (int pid, CORE_ADDR page_start, int original_permissions)
242946283Sdfr{
243098944Sobrien  int tt_status;
243146283Sdfr
243246283Sdfr  tt_status = call_ttrace (TT_PROC_SET_MPROTECT,
243398944Sobrien			   pid,
243498944Sobrien			   (TTRACE_ARG_TYPE) page_start,
243598944Sobrien			 (TTRACE_ARG_TYPE) memory_page_dictionary.page_size,
243698944Sobrien			   (TTRACE_ARG_TYPE) original_permissions);
243746283Sdfr  if (errno || (tt_status < 0))
243846283Sdfr    {
243998944Sobrien      return;			/* What else can we do? */
244046283Sdfr    }
244146283Sdfr}
244246283Sdfr
244346283Sdfr
244446283Sdfr/* Memory page-protections are used to implement "hardware" watchpoints
244546283Sdfr   on HP-UX.
244646283Sdfr
244746283Sdfr   For every memory page that is currently being watched (i.e., that
244846283Sdfr   presently should be write-protected), write-protect it.
244998944Sobrien */
245046283Sdfrvoid
245198944Sobrienhppa_enable_page_protection_events (int pid)
245246283Sdfr{
245398944Sobrien  int bucket;
245446283Sdfr
245546283Sdfr  memory_page_dictionary.page_protections_allowed = 1;
245646283Sdfr
245798944Sobrien  for (bucket = 0; bucket < MEMORY_PAGE_DICTIONARY_BUCKET_COUNT; bucket++)
245846283Sdfr    {
245998944Sobrien      memory_page_t *page;
246046283Sdfr
246146283Sdfr      page = memory_page_dictionary.buckets[bucket].next;
246246283Sdfr      while (page != NULL)
246398944Sobrien	{
246498944Sobrien	  page->original_permissions = write_protect_page (pid, page->page_start);
246598944Sobrien	  page = page->next;
246698944Sobrien	}
246746283Sdfr    }
246846283Sdfr}
246946283Sdfr
247046283Sdfr
247146283Sdfr/* Memory page-protections are used to implement "hardware" watchpoints
247246283Sdfr   on HP-UX.
247346283Sdfr
247446283Sdfr   For every memory page that is currently being watched (i.e., that
247546283Sdfr   presently is or should be write-protected), un-write-protect it.
247698944Sobrien */
247746283Sdfrvoid
247898944Sobrienhppa_disable_page_protection_events (int pid)
247946283Sdfr{
248098944Sobrien  int bucket;
248146283Sdfr
248298944Sobrien  for (bucket = 0; bucket < MEMORY_PAGE_DICTIONARY_BUCKET_COUNT; bucket++)
248346283Sdfr    {
248498944Sobrien      memory_page_t *page;
248546283Sdfr
248646283Sdfr      page = memory_page_dictionary.buckets[bucket].next;
248746283Sdfr      while (page != NULL)
248898944Sobrien	{
248998944Sobrien	  unwrite_protect_page (pid, page->page_start, page->original_permissions);
249098944Sobrien	  page = page->next;
249198944Sobrien	}
249246283Sdfr    }
249346283Sdfr
249446283Sdfr  memory_page_dictionary.page_protections_allowed = 0;
249546283Sdfr}
249646283Sdfr
249746283Sdfr/* Count the number of outstanding events.  At this
249846283Sdfr * point, we have selected one thread and its event
249946283Sdfr * as the one to be "reported" upwards to core gdb.
250046283Sdfr * That thread is already marked as "handled".
250146283Sdfr *
250246283Sdfr * Note: we could just scan our own thread list.  FIXME!
250346283Sdfr */
250446283Sdfrstatic int
250598944Sobriencount_unhandled_events (int real_pid, lwpid_t real_tid)
250646283Sdfr{
250798944Sobrien  ttstate_t tstate;
250898944Sobrien  lwpid_t ttid;
250998944Sobrien  int events_left;
251098944Sobrien
251146283Sdfr  /* Ok, find out how many threads have real events to report.
251246283Sdfr   */
251346283Sdfr  events_left = 0;
251498944Sobrien  ttid = get_process_first_stopped_thread_id (real_pid, &tstate);
251546283Sdfr
251646283Sdfr#ifdef THREAD_DEBUG
251798944Sobrien  if (debug_on)
251898944Sobrien    {
251998944Sobrien      if (ttid == 0)
252098944Sobrien	printf ("Process %d has no threads\n", real_pid);
252146283Sdfr      else
252298944Sobrien	printf ("Process %d has these threads:\n", real_pid);
252398944Sobrien    }
252446283Sdfr#endif
252546283Sdfr
252698944Sobrien  while (ttid > 0)
252798944Sobrien    {
252898944Sobrien      if (tstate.tts_event != TTEVT_NONE
252998944Sobrien	  && !was_handled (ttid))
253098944Sobrien	{
253198944Sobrien	  /* TTEVT_NONE implies we just stopped it ourselves
253298944Sobrien	   * because we're the stop-the-world guys, so it's
253398944Sobrien	   * not an event from our point of view.
253498944Sobrien	   *
253598944Sobrien	   * If "was_handled" is true, this is an event we
253698944Sobrien	   * already handled, so don't count it.
253798944Sobrien	   *
253898944Sobrien	   * Note that we don't count the thread with the
253998944Sobrien	   * currently-reported event, as it's already marked
254098944Sobrien	   * as handled.
254198944Sobrien	   */
254298944Sobrien	  events_left++;
254398944Sobrien	}
254498944Sobrien
254546283Sdfr#if defined( THREAD_DEBUG ) || defined( WAIT_BUFFER_DEBUG )
254698944Sobrien      if (debug_on)
254798944Sobrien	{
254898944Sobrien	  if (ttid == real_tid)
254998944Sobrien	    printf ("*");	/* Thread we're reporting */
255098944Sobrien	  else
255198944Sobrien	    printf (" ");
255246283Sdfr
255398944Sobrien	  if (tstate.tts_event != TTEVT_NONE)
255498944Sobrien	    printf ("+");	/* Thread with a real event */
255598944Sobrien	  else
255698944Sobrien	    printf (" ");
255746283Sdfr
255898944Sobrien	  if (was_handled (ttid))
255998944Sobrien	    printf ("h");	/* Thread has been handled */
256098944Sobrien	  else
256198944Sobrien	    printf (" ");
256246283Sdfr
256398944Sobrien	  printf (" %d, with event %s", ttid,
256498944Sobrien		  get_printable_name_of_ttrace_event (tstate.tts_event));
256598944Sobrien
256698944Sobrien	  if (tstate.tts_event == TTEVT_SIGNAL
256798944Sobrien	      && 5 == tstate.tts_u.tts_signal.tts_signo)
256898944Sobrien	    {
256998944Sobrien	      CORE_ADDR pc_val;
257098944Sobrien
257198944Sobrien	      pc_val = get_raw_pc (ttid);
257298944Sobrien
257398944Sobrien	      if (pc_val > 0)
257498944Sobrien		printf (" breakpoint at 0x%x\n", pc_val);
257598944Sobrien	      else
257698944Sobrien		printf (" bpt, can't fetch pc.\n");
257798944Sobrien	    }
257898944Sobrien	  else
257998944Sobrien	    printf ("\n");
258098944Sobrien	}
258146283Sdfr#endif
258246283Sdfr
258346283Sdfr      ttid = get_process_next_stopped_thread_id (real_pid, &tstate);
258498944Sobrien    }
258546283Sdfr
258646283Sdfr#if defined( THREAD_DEBUG ) || defined( WAIT_BUFFER_DEBUG )
258798944Sobrien  if (debug_on)
258898944Sobrien    if (events_left > 0)
258998944Sobrien      printf ("There are thus %d pending events\n", events_left);
259046283Sdfr#endif
259146283Sdfr
259246283Sdfr  return events_left;
259346283Sdfr}
259446283Sdfr
259546283Sdfr/* This function is provided as a sop to clients that are calling
259646283Sdfr * ptrace_wait to wait for a process to stop.  (see the
259746283Sdfr * implementation of child_wait.)  Return value is the pid for
259846283Sdfr * the event that ended the wait.
259946283Sdfr *
260046283Sdfr * Note: used by core gdb and so uses the pseudo-pid (really tid).
260146283Sdfr */
260246283Sdfrint
260398944Sobrienptrace_wait (ptid_t ptid, int *status)
260446283Sdfr{
260598944Sobrien  ttstate_t tsp;
260698944Sobrien  int ttwait_return;
260798944Sobrien  int real_pid;
260898944Sobrien  ttstate_t state;
260998944Sobrien  lwpid_t real_tid;
261098944Sobrien  int return_pid;
261146283Sdfr
261246283Sdfr  /* The ptrace implementation of this also ignores pid.
261346283Sdfr   */
261446283Sdfr  *status = 0;
261546283Sdfr
261698944Sobrien  ttwait_return = call_ttrace_wait (0, TTRACE_WAITOK, &tsp, sizeof (tsp));
261746283Sdfr  if (ttwait_return < 0)
261846283Sdfr    {
261946283Sdfr      /* ??rehrauer: It appears that if our inferior exits and we
262046283Sdfr         haven't asked for exit events, that we're not getting any
262146283Sdfr         indication save a negative return from ttrace_wait and an
262246283Sdfr         errno set to ESRCH?
262398944Sobrien       */
262446283Sdfr      if (errno == ESRCH)
262598944Sobrien	{
262698944Sobrien	  *status = 0;		/* WIFEXITED */
262798944Sobrien	  return PIDGET (inferior_ptid);
262898944Sobrien	}
262946283Sdfr
263098944Sobrien      warning ("Call of ttrace_wait returned with errno %d.",
263198944Sobrien	       errno);
263246283Sdfr      *status = ttwait_return;
263398944Sobrien      return PIDGET (inferior_ptid);
263446283Sdfr    }
263546283Sdfr
263646283Sdfr  real_pid = tsp.tts_pid;
263746283Sdfr  real_tid = tsp.tts_lwpid;
263846283Sdfr
263946283Sdfr  /* One complication is that the "tts_event" structure has
264046283Sdfr   * a set of flags, and more than one can be set.  So we
264146283Sdfr   * either have to force an order (as we do here), or handle
264246283Sdfr   * more than one flag at a time.
264346283Sdfr   */
264498944Sobrien  if (tsp.tts_event & TTEVT_LWP_CREATE)
264598944Sobrien    {
264646283Sdfr
264798944Sobrien      /* Unlike what you might expect, this event is reported in
264898944Sobrien       * the _creating_ thread, and the _created_ thread (whose tid
264998944Sobrien       * we have) is still running.  So we have to stop it.  This
265098944Sobrien       * has already been done in "call_ttrace_wait", but should we
265198944Sobrien       * ever abandon the "stop-the-world" model, here's the command
265298944Sobrien       * to use:
265398944Sobrien       *
265498944Sobrien       *    call_ttrace( TT_LWP_STOP, real_tid, TT_NIL, TT_NIL, TT_NIL );
265598944Sobrien       *
265698944Sobrien       * Note that this would depend on being called _after_ "add_tthread"
265798944Sobrien       * below for the tid-to-pid translation to be done in "call_ttrace".
265898944Sobrien       */
265946283Sdfr
266046283Sdfr#ifdef THREAD_DEBUG
266198944Sobrien      if (debug_on)
266298944Sobrien	printf ("New thread: pid %d, tid %d, creator tid %d\n",
266398944Sobrien		real_pid, tsp.tts_u.tts_thread.tts_target_lwpid,
266498944Sobrien		real_tid);
266546283Sdfr#endif
266646283Sdfr
266798944Sobrien      /* Now we have to return the tid of the created thread, not
266898944Sobrien       * the creating thread, or "wait_for_inferior" won't know we
266998944Sobrien       * have a new "process" (thread).  Plus we should record it
267098944Sobrien       * right, too.
267198944Sobrien       */
267246283Sdfr      real_tid = tsp.tts_u.tts_thread.tts_target_lwpid;
267346283Sdfr
267498944Sobrien      add_tthread (real_pid, real_tid);
267598944Sobrien    }
267646283Sdfr
267798944Sobrien  else if ((tsp.tts_event & TTEVT_LWP_TERMINATE)
267898944Sobrien	   || (tsp.tts_event & TTEVT_LWP_EXIT))
267998944Sobrien    {
268046283Sdfr
268146283Sdfr#ifdef THREAD_DEBUG
268298944Sobrien      if (debug_on)
268398944Sobrien	printf ("Thread dies: %d\n", real_tid);
268446283Sdfr#endif
268546283Sdfr
268698944Sobrien      del_tthread (real_tid);
268798944Sobrien    }
268846283Sdfr
268998944Sobrien  else if (tsp.tts_event & TTEVT_EXEC)
269098944Sobrien    {
269146283Sdfr
269298944Sobrien#ifdef THREAD_DEBUG
269398944Sobrien      if (debug_on)
269498944Sobrien	printf ("Pid %d has zero'th thread %d; inferior pid is %d\n",
269598944Sobrien		real_pid, real_tid, PIDGET (inferior_ptid));
269646283Sdfr#endif
269746283Sdfr
269898944Sobrien      add_tthread (real_pid, real_tid);
269998944Sobrien    }
270046283Sdfr
270146283Sdfr#ifdef THREAD_DEBUG
270298944Sobrien  else if (debug_on)
270398944Sobrien    {
270498944Sobrien      printf ("Process-level event %s, using tid %d\n",
270598944Sobrien	      get_printable_name_of_ttrace_event (tsp.tts_event),
270698944Sobrien	      real_tid);
270746283Sdfr
270898944Sobrien      /* OK to do this, as "add_tthread" won't add
270998944Sobrien       * duplicate entries.  Also OK not to do it,
271098944Sobrien       * as this event isn't one which can change the
271198944Sobrien       * thread state.
271298944Sobrien       */
271398944Sobrien      add_tthread (real_pid, real_tid);
271498944Sobrien    }
271546283Sdfr#endif
271646283Sdfr
271746283Sdfr
271846283Sdfr  /* How many events are left to report later?
271946283Sdfr   * In a non-stop-the-world model, this isn't needed.
272046283Sdfr   *
272146283Sdfr   * Note that it's not always safe to query the thread state of a process,
272246283Sdfr   * which is what count_unhandled_events does.  (If unsafe, we're left with
272346283Sdfr   * no other resort than to assume that no more events remain...)
272446283Sdfr   */
272546283Sdfr  if (can_touch_threads_of_process (real_pid, tsp.tts_event))
272698944Sobrien    more_events_left = count_unhandled_events (real_pid, real_tid);
272798944Sobrien
272898944Sobrien  else
272998944Sobrien    {
273098944Sobrien      if (more_events_left > 0)
273198944Sobrien	warning ("Vfork or fork causing loss of %d buffered events.",
273298944Sobrien		 more_events_left);
273398944Sobrien
273446283Sdfr      more_events_left = 0;
273598944Sobrien    }
273646283Sdfr
273746283Sdfr  /* Attempt to translate the ttrace_wait-returned status into the
273846283Sdfr     ptrace equivalent.
273946283Sdfr
274046283Sdfr     ??rehrauer: This is somewhat fragile.  We really ought to rewrite
274146283Sdfr     clients that expect to pick apart a ptrace wait status, to use
274246283Sdfr     something a little more abstract.
274398944Sobrien   */
274498944Sobrien  if ((tsp.tts_event & TTEVT_EXEC)
274546283Sdfr      || (tsp.tts_event & TTEVT_FORK)
274646283Sdfr      || (tsp.tts_event & TTEVT_VFORK))
274746283Sdfr    {
274846283Sdfr      /* Forks come in pairs (parent and child), so core gdb
274946283Sdfr       * will do two waits.  Be ready to notice this.
275046283Sdfr       */
275146283Sdfr      if (tsp.tts_event & TTEVT_FORK)
275298944Sobrien	{
275398944Sobrien	  process_state = FORKING;
275498944Sobrien
275546283Sdfr#ifdef WAIT_BUFFER_DEBUG
275698944Sobrien	  if (debug_on)
275798944Sobrien	    printf ("Process set to FORKING\n");
275846283Sdfr#endif
275998944Sobrien	}
276046283Sdfr      else if (tsp.tts_event & TTEVT_VFORK)
276198944Sobrien	{
276298944Sobrien	  process_state = VFORKING;
276398944Sobrien
276446283Sdfr#ifdef WAIT_BUFFER_DEBUG
276598944Sobrien	  if (debug_on)
276698944Sobrien	    printf ("Process set to VFORKING\n");
276746283Sdfr#endif
276898944Sobrien	}
276946283Sdfr
277046283Sdfr      /* Make an exec or fork look like a breakpoint.  Definitely a hack,
277146283Sdfr         but I don't think non HP-UX-specific clients really carefully
277246283Sdfr         inspect the first events they get after inferior startup, so
277346283Sdfr         it probably almost doesn't matter what we claim this is.
277498944Sobrien       */
277546283Sdfr
277646283Sdfr#ifdef THREAD_DEBUG
277798944Sobrien      if (debug_on)
277898944Sobrien	printf ("..a process 'event'\n");
277946283Sdfr#endif
278046283Sdfr
278146283Sdfr      /* Also make fork and exec events look like bpts, so they can be caught.
278298944Sobrien       */
278346283Sdfr      *status = 0177 | (_SIGTRAP << 8);
278446283Sdfr    }
278546283Sdfr
278646283Sdfr  /* Special-cases: We ask for syscall entry and exit events to implement
278746283Sdfr     "fast" (aka "hardware") watchpoints.
278846283Sdfr
278946283Sdfr     When we get a syscall entry, we want to disable page-protections,
279046283Sdfr     and resume the inferior; this isn't an event we wish for
279146283Sdfr     wait_for_inferior to see.  Note that we must resume ONLY the
279246283Sdfr     thread that reported the syscall entry; we don't want to allow
279346283Sdfr     other threads to run with the page protections off, as they might
279446283Sdfr     then be able to write to watch memory without it being caught.
279546283Sdfr
279646283Sdfr     When we get a syscall exit, we want to reenable page-protections,
279746283Sdfr     but we don't want to resume the inferior; this is an event we wish
279846283Sdfr     wait_for_inferior to see.  Make it look like the signal we normally
279946283Sdfr     get for a single-step completion.  This should cause wait_for_inferior
280046283Sdfr     to evaluate whether any watchpoint triggered.
280146283Sdfr
280246283Sdfr     Or rather, that's what we'd LIKE to do for syscall exit; we can't,
280346283Sdfr     due to some HP-UX "features".  Some syscalls have problems with
280446283Sdfr     write-protections on some pages, and some syscalls seem to have
280546283Sdfr     pending writes to those pages at the time we're getting the return
280646283Sdfr     event.  So, we'll single-step the inferior to get out of the syscall,
280746283Sdfr     and then reenable protections.
280846283Sdfr
280946283Sdfr     Note that we're intentionally allowing the syscall exit case to
281046283Sdfr     fall through into the succeeding cases, as sometimes we single-
281146283Sdfr     step out of one syscall only to immediately enter another...
281246283Sdfr   */
281346283Sdfr  else if ((tsp.tts_event & TTEVT_SYSCALL_ENTRY)
281498944Sobrien	   || (tsp.tts_event & TTEVT_SYSCALL_RETURN))
281546283Sdfr    {
281646283Sdfr      /* Make a syscall event look like a breakpoint.  Same comments
281746283Sdfr         as for exec & fork events.
281898944Sobrien       */
281946283Sdfr#ifdef THREAD_DEBUG
282098944Sobrien      if (debug_on)
282198944Sobrien	printf ("..a syscall 'event'\n");
282246283Sdfr#endif
282346283Sdfr
282446283Sdfr      /* Also make syscall events look like bpts, so they can be caught.
282598944Sobrien       */
282646283Sdfr      *status = 0177 | (_SIGTRAP << 8);
282746283Sdfr    }
282846283Sdfr
282946283Sdfr  else if ((tsp.tts_event & TTEVT_LWP_CREATE)
283098944Sobrien	   || (tsp.tts_event & TTEVT_LWP_TERMINATE)
283198944Sobrien	   || (tsp.tts_event & TTEVT_LWP_EXIT))
283246283Sdfr    {
283346283Sdfr      /* Make a thread event look like a breakpoint.  Same comments
283446283Sdfr       * as for exec & fork events.
283546283Sdfr       */
283646283Sdfr#ifdef THREAD_DEBUG
283798944Sobrien      if (debug_on)
283898944Sobrien	printf ("..a thread 'event'\n");
283946283Sdfr#endif
284046283Sdfr
284146283Sdfr      /* Also make thread events look like bpts, so they can be caught.
284298944Sobrien       */
284346283Sdfr      *status = 0177 | (_SIGTRAP << 8);
284446283Sdfr    }
284598944Sobrien
284646283Sdfr  else if ((tsp.tts_event & TTEVT_EXIT))
284798944Sobrien    {				/* WIFEXITED */
284898944Sobrien
284946283Sdfr#ifdef THREAD_DEBUG
285098944Sobrien      if (debug_on)
285198944Sobrien	printf ("..an exit\n");
285246283Sdfr#endif
285346283Sdfr
285446283Sdfr      /* Prevent rest of gdb from thinking this is
285546283Sdfr       * a new thread if for some reason it's never
285646283Sdfr       * seen the main thread before.
285746283Sdfr       */
285898944Sobrien      inferior_ptid = pid_to_ptid (map_to_gdb_tid (real_tid));	/* HACK, FIX */
285998944Sobrien
286046283Sdfr      *status = 0 | (tsp.tts_u.tts_exit.tts_exitcode);
286146283Sdfr    }
286298944Sobrien
286346283Sdfr  else if (tsp.tts_event & TTEVT_SIGNAL)
286498944Sobrien    {				/* WIFSTOPPED */
286546283Sdfr#ifdef THREAD_DEBUG
286698944Sobrien      if (debug_on)
286798944Sobrien	printf ("..a signal, %d\n", tsp.tts_u.tts_signal.tts_signo);
286846283Sdfr#endif
286946283Sdfr
287046283Sdfr      *status = 0177 | (tsp.tts_u.tts_signal.tts_signo << 8);
287146283Sdfr    }
287246283Sdfr
287346283Sdfr  else
287498944Sobrien    {				/* !WIFSTOPPED */
287546283Sdfr
287646283Sdfr      /* This means the process or thread terminated.  But we should've
287746283Sdfr         caught an explicit exit/termination above.  So warn (this is
287846283Sdfr         really an internal error) and claim the process or thread
287946283Sdfr         terminated with a SIGTRAP.
288046283Sdfr       */
288146283Sdfr
288246283Sdfr      warning ("process_wait: unknown process state");
288346283Sdfr
288446283Sdfr#ifdef THREAD_DEBUG
288598944Sobrien      if (debug_on)
288698944Sobrien	printf ("Process-level event %s, using tid %d\n",
288798944Sobrien		get_printable_name_of_ttrace_event (tsp.tts_event),
288898944Sobrien		real_tid);
288946283Sdfr#endif
289046283Sdfr
289146283Sdfr      *status = _SIGTRAP;
289246283Sdfr    }
289346283Sdfr
289498944Sobrien  target_post_wait (pid_to_ptid (tsp.tts_pid), *status);
289546283Sdfr
289646283Sdfr
289746283Sdfr#ifdef THREAD_DEBUG
289898944Sobrien  if (debug_on)
289998944Sobrien    printf ("Done waiting, pid is %d, tid %d\n", real_pid, real_tid);
290046283Sdfr#endif
290146283Sdfr
290246283Sdfr  /* All code external to this module uses the tid, but calls
290346283Sdfr   * it "pid".  There's some tweaking so that the outside sees
290446283Sdfr   * the first thread as having the same number as the starting
290546283Sdfr   * pid.
290646283Sdfr   */
290798944Sobrien  return_pid = map_to_gdb_tid (real_tid);
290846283Sdfr
290998944Sobrien  if (real_tid == 0 || return_pid == 0)
291098944Sobrien    {
291198944Sobrien      warning ("Internal error: process-wait failed.");
291298944Sobrien    }
291398944Sobrien
291446283Sdfr  return return_pid;
291546283Sdfr}
291698944Sobrien
291746283Sdfr
291846283Sdfr/* This function causes the caller's process to be traced by its
291946283Sdfr   parent.  This is intended to be called after GDB forks itself,
292046283Sdfr   and before the child execs the target.  Despite the name, it
292146283Sdfr   is called by the child.
292246283Sdfr
292346283Sdfr   Note that HP-UX ttrace is rather funky in how this is done.
292446283Sdfr   If the parent wants to get the initial exec event of a child,
292546283Sdfr   it must set the ttrace event mask of the child to include execs.
292646283Sdfr   (The child cannot do this itself.)  This must be done after the
292746283Sdfr   child is forked, but before it execs.
292846283Sdfr
292946283Sdfr   To coordinate the parent and child, we implement a semaphore using
293046283Sdfr   pipes.  After SETTRC'ing itself, the child tells the parent that
293146283Sdfr   it is now traceable by the parent, and waits for the parent's
293246283Sdfr   acknowledgement.  The parent can then set the child's event mask,
293346283Sdfr   and notify the child that it can now exec.
293446283Sdfr
293546283Sdfr   (The acknowledgement by parent happens as a result of a call to
293646283Sdfr   child_acknowledge_created_inferior.)
293746283Sdfr */
293846283Sdfrint
2939130803Smarcelparent_attach_all (int p1, PTRACE_ARG3_TYPE p2, int p3)
294046283Sdfr{
294198944Sobrien  int tt_status;
294246283Sdfr
294346283Sdfr  /* We need a memory home for a constant, to pass it to ttrace.
294446283Sdfr     The value of the constant is arbitrary, so long as both
294546283Sdfr     parent and child use the same value.  Might as well use the
294646283Sdfr     "magic" constant provided by ttrace...
294746283Sdfr   */
294898944Sobrien  uint64_t tc_magic_child = TT_VERSION;
294998944Sobrien  uint64_t tc_magic_parent = 0;
295046283Sdfr
295146283Sdfr  tt_status = call_real_ttrace (
295298944Sobrien				 TT_PROC_SETTRC,
295398944Sobrien				 (int) TT_NIL,
295498944Sobrien				 (lwpid_t) TT_NIL,
295598944Sobrien				 TT_NIL,
295698944Sobrien				 (TTRACE_ARG_TYPE) TT_VERSION,
295798944Sobrien				 TT_NIL);
295846283Sdfr
295946283Sdfr  if (tt_status < 0)
296046283Sdfr    return tt_status;
296146283Sdfr
296246283Sdfr  /* Notify the parent that we're potentially ready to exec(). */
296346283Sdfr  write (startup_semaphore.child_channel[SEM_TALK],
296498944Sobrien	 &tc_magic_child,
296598944Sobrien	 sizeof (tc_magic_child));
296646283Sdfr
296746283Sdfr  /* Wait for acknowledgement from the parent. */
296846283Sdfr  read (startup_semaphore.parent_channel[SEM_LISTEN],
296998944Sobrien	&tc_magic_parent,
297098944Sobrien	sizeof (tc_magic_parent));
297198944Sobrien
297246283Sdfr  if (tc_magic_child != tc_magic_parent)
297346283Sdfr    warning ("mismatched semaphore magic");
297446283Sdfr
297546283Sdfr  /* Discard our copy of the semaphore. */
297646283Sdfr  (void) close (startup_semaphore.parent_channel[SEM_LISTEN]);
297746283Sdfr  (void) close (startup_semaphore.parent_channel[SEM_TALK]);
297846283Sdfr  (void) close (startup_semaphore.child_channel[SEM_LISTEN]);
297946283Sdfr  (void) close (startup_semaphore.child_channel[SEM_TALK]);
298098944Sobrien
298146283Sdfr  return tt_status;
298246283Sdfr}
298346283Sdfr
298446283Sdfr/* Despite being file-local, this routine is dealing with
298546283Sdfr * actual process IDs, not thread ids.  That's because it's
298646283Sdfr * called before the first "wait" call, and there's no map
298746283Sdfr * yet from tids to pids.
298846283Sdfr *
298946283Sdfr * When it is called, a forked child is running, but waiting on
299046283Sdfr * the semaphore.  If you stop the child and re-start it,
299146283Sdfr * things get confused, so don't do that!  An attached child is
299246283Sdfr * stopped.
299346283Sdfr *
299446283Sdfr * Since this is called after either attach or run, we
299546283Sdfr * have to be the common part of both.
299646283Sdfr */
299746283Sdfrstatic void
299898944Sobrienrequire_notification_of_events (int real_pid)
299946283Sdfr{
300098944Sobrien  int tt_status;
300198944Sobrien  ttevent_t notifiable_events;
300246283Sdfr
300398944Sobrien  lwpid_t tid;
300498944Sobrien  ttstate_t thread_state;
300546283Sdfr
300646283Sdfr#ifdef THREAD_DEBUG
300798944Sobrien  if (debug_on)
300898944Sobrien    printf ("Require notif, pid is %d\n", real_pid);
300946283Sdfr#endif
301046283Sdfr
301146283Sdfr  /* Temporary HACK: tell inftarg.c/child_wait to not
301246283Sdfr   * loop until pids are the same.
301346283Sdfr   */
301446283Sdfr  not_same_real_pid = 0;
301546283Sdfr
301646283Sdfr  sigemptyset (&notifiable_events.tte_signals);
301746283Sdfr  notifiable_events.tte_opts = TTEO_NONE;
301846283Sdfr
301946283Sdfr  /* This ensures that forked children inherit their parent's
302046283Sdfr   * event mask, which we're setting here.
302146283Sdfr   *
302246283Sdfr   * NOTE: if you debug gdb with itself, then the ultimate
302346283Sdfr   *       debuggee gets flags set by the outermost gdb, as
302446283Sdfr   *       a child of a child will still inherit.
302546283Sdfr   */
302646283Sdfr  notifiable_events.tte_opts |= TTEO_PROC_INHERIT;
302746283Sdfr
302898944Sobrien  notifiable_events.tte_events = TTEVT_DEFAULT;
302946283Sdfr  notifiable_events.tte_events |= TTEVT_SIGNAL;
303046283Sdfr  notifiable_events.tte_events |= TTEVT_EXEC;
303146283Sdfr  notifiable_events.tte_events |= TTEVT_EXIT;
303246283Sdfr  notifiable_events.tte_events |= TTEVT_FORK;
303346283Sdfr  notifiable_events.tte_events |= TTEVT_VFORK;
303446283Sdfr  notifiable_events.tte_events |= TTEVT_LWP_CREATE;
303546283Sdfr  notifiable_events.tte_events |= TTEVT_LWP_EXIT;
303646283Sdfr  notifiable_events.tte_events |= TTEVT_LWP_TERMINATE;
303746283Sdfr
303846283Sdfr  tt_status = call_real_ttrace (
303998944Sobrien				 TT_PROC_SET_EVENT_MASK,
304098944Sobrien				 real_pid,
304198944Sobrien				 (lwpid_t) TT_NIL,
304298944Sobrien				 (TTRACE_ARG_TYPE) & notifiable_events,
304398944Sobrien			       (TTRACE_ARG_TYPE) sizeof (notifiable_events),
304498944Sobrien				 TT_NIL);
304546283Sdfr}
304646283Sdfr
304746283Sdfrstatic void
304898944Sobrienrequire_notification_of_exec_events (int real_pid)
304946283Sdfr{
305098944Sobrien  int tt_status;
305198944Sobrien  ttevent_t notifiable_events;
305246283Sdfr
305398944Sobrien  lwpid_t tid;
305498944Sobrien  ttstate_t thread_state;
305546283Sdfr
305646283Sdfr#ifdef THREAD_DEBUG
305798944Sobrien  if (debug_on)
305898944Sobrien    printf ("Require notif, pid is %d\n", real_pid);
305946283Sdfr#endif
306046283Sdfr
306146283Sdfr  /* Temporary HACK: tell inftarg.c/child_wait to not
306246283Sdfr   * loop until pids are the same.
306346283Sdfr   */
306446283Sdfr  not_same_real_pid = 0;
306546283Sdfr
306646283Sdfr  sigemptyset (&notifiable_events.tte_signals);
306746283Sdfr  notifiable_events.tte_opts = TTEO_NOSTRCCHLD;
306846283Sdfr
306946283Sdfr  /* This ensures that forked children don't inherit their parent's
307046283Sdfr   * event mask, which we're setting here.
307146283Sdfr   */
307246283Sdfr  notifiable_events.tte_opts &= ~TTEO_PROC_INHERIT;
307346283Sdfr
307498944Sobrien  notifiable_events.tte_events = TTEVT_DEFAULT;
307546283Sdfr  notifiable_events.tte_events |= TTEVT_EXEC;
307646283Sdfr  notifiable_events.tte_events |= TTEVT_EXIT;
307746283Sdfr
307846283Sdfr  tt_status = call_real_ttrace (
307998944Sobrien				 TT_PROC_SET_EVENT_MASK,
308098944Sobrien				 real_pid,
308198944Sobrien				 (lwpid_t) TT_NIL,
308298944Sobrien				 (TTRACE_ARG_TYPE) & notifiable_events,
308398944Sobrien			       (TTRACE_ARG_TYPE) sizeof (notifiable_events),
308498944Sobrien				 TT_NIL);
308546283Sdfr}
308698944Sobrien
308746283Sdfr
308846283Sdfr/* This function is called by the parent process, with pid being the
308946283Sdfr * ID of the child process, after the debugger has forked.
309046283Sdfr */
309146283Sdfrvoid
309298944Sobrienchild_acknowledge_created_inferior (int pid)
309346283Sdfr{
309446283Sdfr  /* We need a memory home for a constant, to pass it to ttrace.
309546283Sdfr     The value of the constant is arbitrary, so long as both
309646283Sdfr     parent and child use the same value.  Might as well use the
309746283Sdfr     "magic" constant provided by ttrace...
309898944Sobrien   */
309998944Sobrien  uint64_t tc_magic_parent = TT_VERSION;
310098944Sobrien  uint64_t tc_magic_child = 0;
310146283Sdfr
310246283Sdfr  /* Wait for the child to tell us that it has forked. */
310346283Sdfr  read (startup_semaphore.child_channel[SEM_LISTEN],
310498944Sobrien	&tc_magic_child,
310598944Sobrien	sizeof (tc_magic_child));
310646283Sdfr
310746283Sdfr  /* Clear thread info now.  We'd like to do this in
310846283Sdfr   * "require...", but that messes up attach.
310946283Sdfr   */
311098944Sobrien  clear_thread_info ();
311146283Sdfr
311246283Sdfr  /* Tell the "rest of gdb" that the initial thread exists.
311346283Sdfr   * This isn't really a hack.  Other thread-based versions
311446283Sdfr   * of gdb (e.g. gnu-nat.c) seem to do the same thing.
311546283Sdfr   *
311646283Sdfr   * Q: Why don't we also add this thread to the local
311746283Sdfr   *    list via "add_tthread"?
311846283Sdfr   *
311946283Sdfr   * A: Because we don't know the tid, and can't stop the
312046283Sdfr   *    the process safely to ask what it is.  Anyway, we'll
312146283Sdfr   *    add it when it gets the EXEC event.
312246283Sdfr   */
312398944Sobrien  add_thread (pid_to_ptid (pid));		/* in thread.c */
312446283Sdfr
312546283Sdfr  /* We can now set the child's ttrace event mask.
312646283Sdfr   */
312746283Sdfr  require_notification_of_exec_events (pid);
312846283Sdfr
312946283Sdfr  /* Tell ourselves that the process is running.
313046283Sdfr   */
313146283Sdfr  process_state = RUNNING;
313246283Sdfr
313346283Sdfr  /* Notify the child that it can exec. */
313446283Sdfr  write (startup_semaphore.parent_channel[SEM_TALK],
313598944Sobrien	 &tc_magic_parent,
313698944Sobrien	 sizeof (tc_magic_parent));
313746283Sdfr
313846283Sdfr  /* Discard our copy of the semaphore. */
313946283Sdfr  (void) close (startup_semaphore.parent_channel[SEM_LISTEN]);
314046283Sdfr  (void) close (startup_semaphore.parent_channel[SEM_TALK]);
314146283Sdfr  (void) close (startup_semaphore.child_channel[SEM_LISTEN]);
314246283Sdfr  (void) close (startup_semaphore.child_channel[SEM_TALK]);
314346283Sdfr}
314446283Sdfr
314546283Sdfr
314646283Sdfr/*
314746283Sdfr * arrange for notification of all events by
314846283Sdfr * calling require_notification_of_events.
314946283Sdfr */
315046283Sdfrvoid
315198944Sobrienchild_post_startup_inferior (ptid_t ptid)
315246283Sdfr{
315398944Sobrien  require_notification_of_events (PIDGET (ptid));
315446283Sdfr}
315546283Sdfr
315646283Sdfr/* From here on, we should expect tids rather than pids.
315746283Sdfr */
315846283Sdfrstatic void
315998944Sobrienhppa_enable_catch_fork (int tid)
316046283Sdfr{
316198944Sobrien  int tt_status;
316298944Sobrien  ttevent_t ttrace_events;
316346283Sdfr
316446283Sdfr  /* Get the set of events that are currently enabled.
316546283Sdfr   */
316646283Sdfr  tt_status = call_ttrace (TT_PROC_GET_EVENT_MASK,
316798944Sobrien			   tid,
316898944Sobrien			   (TTRACE_ARG_TYPE) & ttrace_events,
316998944Sobrien			   (TTRACE_ARG_TYPE) sizeof (ttrace_events),
317098944Sobrien			   TT_NIL);
317146283Sdfr  if (errno)
317246283Sdfr    perror_with_name ("ttrace");
317346283Sdfr
317446283Sdfr  /* Add forks to that set. */
317546283Sdfr  ttrace_events.tte_events |= TTEVT_FORK;
317646283Sdfr
317746283Sdfr#ifdef THREAD_DEBUG
317898944Sobrien  if (debug_on)
317998944Sobrien    printf ("enable fork, tid is %d\n", tid);
318046283Sdfr#endif
318146283Sdfr
318246283Sdfr  tt_status = call_ttrace (TT_PROC_SET_EVENT_MASK,
318398944Sobrien			   tid,
318498944Sobrien			   (TTRACE_ARG_TYPE) & ttrace_events,
318598944Sobrien			   (TTRACE_ARG_TYPE) sizeof (ttrace_events),
318698944Sobrien			   TT_NIL);
318746283Sdfr  if (errno)
318846283Sdfr    perror_with_name ("ttrace");
318946283Sdfr}
319046283Sdfr
319146283Sdfr
319246283Sdfrstatic void
319398944Sobrienhppa_disable_catch_fork (int tid)
319446283Sdfr{
319598944Sobrien  int tt_status;
319698944Sobrien  ttevent_t ttrace_events;
319746283Sdfr
319846283Sdfr  /* Get the set of events that are currently enabled.
319946283Sdfr   */
320046283Sdfr  tt_status = call_ttrace (TT_PROC_GET_EVENT_MASK,
320198944Sobrien			   tid,
320298944Sobrien			   (TTRACE_ARG_TYPE) & ttrace_events,
320398944Sobrien			   (TTRACE_ARG_TYPE) sizeof (ttrace_events),
320498944Sobrien			   TT_NIL);
320546283Sdfr
320646283Sdfr  if (errno)
320746283Sdfr    perror_with_name ("ttrace");
320846283Sdfr
320946283Sdfr  /* Remove forks from that set. */
321046283Sdfr  ttrace_events.tte_events &= ~TTEVT_FORK;
321146283Sdfr
321246283Sdfr#ifdef THREAD_DEBUG
321398944Sobrien  if (debug_on)
321498944Sobrien    printf ("disable fork, tid is %d\n", tid);
321546283Sdfr#endif
321646283Sdfr
321746283Sdfr  tt_status = call_ttrace (TT_PROC_SET_EVENT_MASK,
321898944Sobrien			   tid,
321998944Sobrien			   (TTRACE_ARG_TYPE) & ttrace_events,
322098944Sobrien			   (TTRACE_ARG_TYPE) sizeof (ttrace_events),
322198944Sobrien			   TT_NIL);
322246283Sdfr
322346283Sdfr  if (errno)
322446283Sdfr    perror_with_name ("ttrace");
322546283Sdfr}
322646283Sdfr
322746283Sdfr
322846283Sdfr#if defined(CHILD_INSERT_FORK_CATCHPOINT)
322946283Sdfrint
323098944Sobrienchild_insert_fork_catchpoint (int tid)
323146283Sdfr{
323246283Sdfr  /* Enable reporting of fork events from the kernel. */
323346283Sdfr  /* ??rehrauer: For the moment, we're always enabling these events,
323446283Sdfr     and just ignoring them if there's no catchpoint to catch them.
323598944Sobrien   */
323646283Sdfr  return 0;
323746283Sdfr}
323846283Sdfr#endif
323946283Sdfr
324046283Sdfr
324146283Sdfr#if defined(CHILD_REMOVE_FORK_CATCHPOINT)
324246283Sdfrint
324398944Sobrienchild_remove_fork_catchpoint (int tid)
324446283Sdfr{
324546283Sdfr  /* Disable reporting of fork events from the kernel. */
324646283Sdfr  /* ??rehrauer: For the moment, we're always enabling these events,
324746283Sdfr     and just ignoring them if there's no catchpoint to catch them.
324898944Sobrien   */
324946283Sdfr  return 0;
325046283Sdfr}
325146283Sdfr#endif
325246283Sdfr
325346283Sdfr
325446283Sdfrstatic void
325598944Sobrienhppa_enable_catch_vfork (int tid)
325646283Sdfr{
325798944Sobrien  int tt_status;
325898944Sobrien  ttevent_t ttrace_events;
325946283Sdfr
326046283Sdfr  /* Get the set of events that are currently enabled.
326146283Sdfr   */
326246283Sdfr  tt_status = call_ttrace (TT_PROC_GET_EVENT_MASK,
326398944Sobrien			   tid,
326498944Sobrien			   (TTRACE_ARG_TYPE) & ttrace_events,
326598944Sobrien			   (TTRACE_ARG_TYPE) sizeof (ttrace_events),
326698944Sobrien			   TT_NIL);
326746283Sdfr
326846283Sdfr  if (errno)
326946283Sdfr    perror_with_name ("ttrace");
327046283Sdfr
327146283Sdfr  /* Add vforks to that set. */
327246283Sdfr  ttrace_events.tte_events |= TTEVT_VFORK;
327346283Sdfr
327446283Sdfr#ifdef THREAD_DEBUG
327598944Sobrien  if (debug_on)
327698944Sobrien    printf ("enable vfork, tid is %d\n", tid);
327746283Sdfr#endif
327846283Sdfr
327946283Sdfr  tt_status = call_ttrace (TT_PROC_SET_EVENT_MASK,
328098944Sobrien			   tid,
328198944Sobrien			   (TTRACE_ARG_TYPE) & ttrace_events,
328298944Sobrien			   (TTRACE_ARG_TYPE) sizeof (ttrace_events),
328398944Sobrien			   TT_NIL);
328446283Sdfr
328546283Sdfr  if (errno)
328646283Sdfr    perror_with_name ("ttrace");
328746283Sdfr}
328846283Sdfr
328946283Sdfr
329046283Sdfrstatic void
329198944Sobrienhppa_disable_catch_vfork (int tid)
329246283Sdfr{
329398944Sobrien  int tt_status;
329498944Sobrien  ttevent_t ttrace_events;
329546283Sdfr
329646283Sdfr  /* Get the set of events that are currently enabled. */
329746283Sdfr  tt_status = call_ttrace (TT_PROC_GET_EVENT_MASK,
329898944Sobrien			   tid,
329998944Sobrien			   (TTRACE_ARG_TYPE) & ttrace_events,
330098944Sobrien			   (TTRACE_ARG_TYPE) sizeof (ttrace_events),
330198944Sobrien			   TT_NIL);
330246283Sdfr
330346283Sdfr  if (errno)
330446283Sdfr    perror_with_name ("ttrace");
330546283Sdfr
330646283Sdfr  /* Remove vforks from that set. */
330746283Sdfr  ttrace_events.tte_events &= ~TTEVT_VFORK;
330846283Sdfr
330946283Sdfr#ifdef THREAD_DEBUG
331098944Sobrien  if (debug_on)
331198944Sobrien    printf ("disable vfork, tid is %d\n", tid);
331246283Sdfr#endif
331346283Sdfr  tt_status = call_ttrace (TT_PROC_SET_EVENT_MASK,
331498944Sobrien			   tid,
331598944Sobrien			   (TTRACE_ARG_TYPE) & ttrace_events,
331698944Sobrien			   (TTRACE_ARG_TYPE) sizeof (ttrace_events),
331798944Sobrien			   TT_NIL);
331846283Sdfr
331946283Sdfr  if (errno)
332046283Sdfr    perror_with_name ("ttrace");
332146283Sdfr}
332246283Sdfr
332346283Sdfr
332446283Sdfr#if defined(CHILD_INSERT_VFORK_CATCHPOINT)
332546283Sdfrint
332698944Sobrienchild_insert_vfork_catchpoint (int tid)
332746283Sdfr{
332846283Sdfr  /* Enable reporting of vfork events from the kernel. */
332946283Sdfr  /* ??rehrauer: For the moment, we're always enabling these events,
333046283Sdfr     and just ignoring them if there's no catchpoint to catch them.
333198944Sobrien   */
333246283Sdfr  return 0;
333346283Sdfr}
333446283Sdfr#endif
333546283Sdfr
333646283Sdfr
333746283Sdfr#if defined(CHILD_REMOVE_VFORK_CATCHPOINT)
333846283Sdfrint
333998944Sobrienchild_remove_vfork_catchpoint (int tid)
334046283Sdfr{
334146283Sdfr  /* Disable reporting of vfork events from the kernel. */
334246283Sdfr  /* ??rehrauer: For the moment, we're always enabling these events,
334346283Sdfr     and just ignoring them if there's no catchpoint to catch them.
334498944Sobrien   */
334546283Sdfr  return 0;
334646283Sdfr}
334746283Sdfr#endif
334846283Sdfr
334946283Sdfr/* Q: Do we need to map the returned process ID to a thread ID?
335098944Sobrien
335146283Sdfr * A: I don't think so--here we want a _real_ pid.  Any later
335246283Sdfr *    operations will call "require_notification_of_events" and
335346283Sdfr *    start the mapping.
335446283Sdfr */
335546283Sdfrint
3356130803Smarcelhpux_has_forked (int tid, int *childpid)
335746283Sdfr{
335898944Sobrien  int tt_status;
335998944Sobrien  ttstate_t ttrace_state;
336098944Sobrien  thread_info *tinfo;
336146283Sdfr
336246283Sdfr  /* Do we have cached thread state that we can consult?  If so, use it. */
336346283Sdfr  tinfo = find_thread_info (map_from_gdb_tid (tid));
336498944Sobrien  if (tinfo != NULL)
336598944Sobrien    {
336698944Sobrien      copy_ttstate_t (&ttrace_state, &tinfo->last_stop_state);
336798944Sobrien    }
336846283Sdfr
336946283Sdfr  /* Nope, must read the thread's current state */
337046283Sdfr  else
337146283Sdfr    {
337246283Sdfr      tt_status = call_ttrace (TT_LWP_GET_STATE,
337398944Sobrien			       tid,
337498944Sobrien			       (TTRACE_ARG_TYPE) & ttrace_state,
337598944Sobrien			       (TTRACE_ARG_TYPE) sizeof (ttrace_state),
337698944Sobrien			       TT_NIL);
337746283Sdfr
337846283Sdfr      if (errno)
337998944Sobrien	perror_with_name ("ttrace");
338098944Sobrien
338146283Sdfr      if (tt_status < 0)
338298944Sobrien	return 0;
338346283Sdfr    }
338446283Sdfr
338546283Sdfr  if (ttrace_state.tts_event & TTEVT_FORK)
338646283Sdfr    {
338746283Sdfr      *childpid = ttrace_state.tts_u.tts_fork.tts_fpid;
338846283Sdfr      return 1;
338946283Sdfr    }
339046283Sdfr
339146283Sdfr  return 0;
339246283Sdfr}
339346283Sdfr
3394130803Smarcel/* See hpux_has_forked for pid discussion.
339546283Sdfr */
339646283Sdfrint
3397130803Smarcelhpux_has_vforked (int tid, int *childpid)
339846283Sdfr{
339998944Sobrien  int tt_status;
340098944Sobrien  ttstate_t ttrace_state;
340198944Sobrien  thread_info *tinfo;
340246283Sdfr
340346283Sdfr  /* Do we have cached thread state that we can consult?  If so, use it. */
340446283Sdfr  tinfo = find_thread_info (map_from_gdb_tid (tid));
340546283Sdfr  if (tinfo != NULL)
340646283Sdfr    copy_ttstate_t (&ttrace_state, &tinfo->last_stop_state);
340746283Sdfr
340846283Sdfr  /* Nope, must read the thread's current state */
340946283Sdfr  else
341046283Sdfr    {
341146283Sdfr      tt_status = call_ttrace (TT_LWP_GET_STATE,
341298944Sobrien			       tid,
341398944Sobrien			       (TTRACE_ARG_TYPE) & ttrace_state,
341498944Sobrien			       (TTRACE_ARG_TYPE) sizeof (ttrace_state),
341598944Sobrien			       TT_NIL);
341646283Sdfr
341746283Sdfr      if (errno)
341898944Sobrien	perror_with_name ("ttrace");
341998944Sobrien
342046283Sdfr      if (tt_status < 0)
342198944Sobrien	return 0;
342246283Sdfr    }
342346283Sdfr
342446283Sdfr  if (ttrace_state.tts_event & TTEVT_VFORK)
342546283Sdfr    {
342646283Sdfr      *childpid = ttrace_state.tts_u.tts_fork.tts_fpid;
342746283Sdfr      return 1;
342846283Sdfr    }
342946283Sdfr
343046283Sdfr  return 0;
343146283Sdfr}
343246283Sdfr
343346283Sdfr
343446283Sdfr#if defined(CHILD_INSERT_EXEC_CATCHPOINT)
343546283Sdfrint
343698944Sobrienchild_insert_exec_catchpoint (int tid)
343746283Sdfr{
343846283Sdfr  /* Enable reporting of exec events from the kernel. */
343946283Sdfr  /* ??rehrauer: For the moment, we're always enabling these events,
344046283Sdfr     and just ignoring them if there's no catchpoint to catch them.
344198944Sobrien   */
344246283Sdfr  return 0;
344346283Sdfr}
344446283Sdfr#endif
344546283Sdfr
344646283Sdfr
344746283Sdfr#if defined(CHILD_REMOVE_EXEC_CATCHPOINT)
344846283Sdfrint
344998944Sobrienchild_remove_exec_catchpoint (int tid)
345046283Sdfr{
345146283Sdfr  /* Disable reporting of execevents from the kernel. */
345246283Sdfr  /* ??rehrauer: For the moment, we're always enabling these events,
345346283Sdfr     and just ignoring them if there's no catchpoint to catch them.
345498944Sobrien   */
345546283Sdfr  return 0;
345646283Sdfr}
345746283Sdfr#endif
345846283Sdfr
345946283Sdfr
346046283Sdfrint
3461130803Smarcelhpux_has_execd (int tid, char **execd_pathname)
346246283Sdfr{
346398944Sobrien  int tt_status;
346498944Sobrien  ttstate_t ttrace_state;
346598944Sobrien  thread_info *tinfo;
346646283Sdfr
346746283Sdfr  /* Do we have cached thread state that we can consult?  If so, use it. */
346846283Sdfr  tinfo = find_thread_info (map_from_gdb_tid (tid));
346946283Sdfr  if (tinfo != NULL)
347046283Sdfr    copy_ttstate_t (&ttrace_state, &tinfo->last_stop_state);
347146283Sdfr
347246283Sdfr  /* Nope, must read the thread's current state */
347346283Sdfr  else
347446283Sdfr    {
347546283Sdfr      tt_status = call_ttrace (TT_LWP_GET_STATE,
347698944Sobrien			       tid,
347798944Sobrien			       (TTRACE_ARG_TYPE) & ttrace_state,
347898944Sobrien			       (TTRACE_ARG_TYPE) sizeof (ttrace_state),
347998944Sobrien			       TT_NIL);
348046283Sdfr
348146283Sdfr      if (errno)
348298944Sobrien	perror_with_name ("ttrace");
348398944Sobrien
348446283Sdfr      if (tt_status < 0)
348598944Sobrien	return 0;
348646283Sdfr    }
348746283Sdfr
348846283Sdfr  if (ttrace_state.tts_event & TTEVT_EXEC)
348946283Sdfr    {
349046283Sdfr      /* See child_pid_to_exec_file in this file: this is a macro.
349146283Sdfr       */
349298944Sobrien      char *exec_file = target_pid_to_exec_file (tid);
349398944Sobrien
349446283Sdfr      *execd_pathname = savestring (exec_file, strlen (exec_file));
349546283Sdfr      return 1;
349646283Sdfr    }
349746283Sdfr
349846283Sdfr  return 0;
349946283Sdfr}
350046283Sdfr
350146283Sdfr
350246283Sdfrint
3503130803Smarcelhpux_has_syscall_event (int pid, enum target_waitkind *kind, int *syscall_id)
350446283Sdfr{
350598944Sobrien  int tt_status;
350698944Sobrien  ttstate_t ttrace_state;
350798944Sobrien  thread_info *tinfo;
350846283Sdfr
350946283Sdfr  /* Do we have cached thread state that we can consult?  If so, use it. */
351046283Sdfr  tinfo = find_thread_info (map_from_gdb_tid (pid));
351146283Sdfr  if (tinfo != NULL)
351246283Sdfr    copy_ttstate_t (&ttrace_state, &tinfo->last_stop_state);
351346283Sdfr
351446283Sdfr  /* Nope, must read the thread's current state */
351546283Sdfr  else
351646283Sdfr    {
351798944Sobrien      tt_status = call_ttrace (TT_LWP_GET_STATE,
351898944Sobrien			       pid,
351998944Sobrien			       (TTRACE_ARG_TYPE) & ttrace_state,
352098944Sobrien			       (TTRACE_ARG_TYPE) sizeof (ttrace_state),
352198944Sobrien			       TT_NIL);
352246283Sdfr
352346283Sdfr      if (errno)
352498944Sobrien	perror_with_name ("ttrace");
352598944Sobrien
352646283Sdfr      if (tt_status < 0)
352798944Sobrien	return 0;
352846283Sdfr    }
352946283Sdfr
353098944Sobrien  *kind = TARGET_WAITKIND_SPURIOUS;	/* Until proven otherwise... */
353146283Sdfr  *syscall_id = -1;
353246283Sdfr
353346283Sdfr  if (ttrace_state.tts_event & TTEVT_SYSCALL_ENTRY)
353446283Sdfr    *kind = TARGET_WAITKIND_SYSCALL_ENTRY;
353546283Sdfr  else if (ttrace_state.tts_event & TTEVT_SYSCALL_RETURN)
353646283Sdfr    *kind = TARGET_WAITKIND_SYSCALL_RETURN;
353746283Sdfr  else
353846283Sdfr    return 0;
353946283Sdfr
354046283Sdfr  *syscall_id = ttrace_state.tts_scno;
354146283Sdfr  return 1;
354246283Sdfr}
354398944Sobrien
354446283Sdfr
354546283Sdfr
354646283Sdfr#if defined(CHILD_THREAD_ALIVE)
354746283Sdfr
354846283Sdfr/* Check to see if the given thread is alive.
354998944Sobrien
355046283Sdfr * We'll trust the thread list, as the more correct
355146283Sdfr * approach of stopping the process and spinning down
355246283Sdfr * the OS's thread list is _very_ expensive.
355346283Sdfr *
355446283Sdfr * May need a FIXME for that reason.
355546283Sdfr */
355646283Sdfrint
355798944Sobrienchild_thread_alive (ptid_t ptid)
355846283Sdfr{
355998944Sobrien  lwpid_t gdb_tid = PIDGET (ptid);
356098944Sobrien  lwpid_t tid;
356146283Sdfr
356298944Sobrien  /* This spins down the lists twice.
356398944Sobrien   * Possible peformance improvement here!
356498944Sobrien   */
356598944Sobrien  tid = map_from_gdb_tid (gdb_tid);
356698944Sobrien  return !is_terminated (tid);
356746283Sdfr}
356846283Sdfr
356946283Sdfr#endif
357098944Sobrien
357146283Sdfr
357246283Sdfr
357346283Sdfr/* This function attempts to read the specified number of bytes from the
357446283Sdfr   save_state_t that is our view into the hardware registers, starting at
357546283Sdfr   ss_offset, and ending at ss_offset + sizeof_buf - 1
357646283Sdfr
357746283Sdfr   If this function succeeds, it deposits the fetched bytes into buf,
357846283Sdfr   and returns 0.
357946283Sdfr
358046283Sdfr   If it fails, it returns a negative result.  The contents of buf are
358146283Sdfr   undefined it this function fails.
358298944Sobrien */
358346283Sdfrint
358498944Sobrienread_from_register_save_state (int tid, TTRACE_ARG_TYPE ss_offset, char *buf,
358598944Sobrien			       int sizeof_buf)
358646283Sdfr{
358798944Sobrien  int tt_status;
358898944Sobrien  register_value_t register_value = 0;
358946283Sdfr
359046283Sdfr  tt_status = call_ttrace (TT_LWP_RUREGS,
359198944Sobrien			   tid,
359298944Sobrien			   ss_offset,
359398944Sobrien			   (TTRACE_ARG_TYPE) sizeof_buf,
359498944Sobrien			   (TTRACE_ARG_TYPE) buf);
359546283Sdfr
359698944Sobrien  if (tt_status == 1)
359798944Sobrien    /* Map ttrace's version of success to our version.
359898944Sobrien     * Sometime ttrace returns 0, but that's ok here.
359998944Sobrien     */
360098944Sobrien    return 0;
360198944Sobrien
360246283Sdfr  return tt_status;
360346283Sdfr}
360498944Sobrien
360546283Sdfr
360646283Sdfr/* This function attempts to write the specified number of bytes to the
360746283Sdfr   save_state_t that is our view into the hardware registers, starting at
360846283Sdfr   ss_offset, and ending at ss_offset + sizeof_buf - 1
360946283Sdfr
361046283Sdfr   If this function succeeds, it deposits the bytes in buf, and returns 0.
361146283Sdfr
361246283Sdfr   If it fails, it returns a negative result.  The contents of the save_state_t
361346283Sdfr   are undefined it this function fails.
361498944Sobrien */
361546283Sdfrint
361698944Sobrienwrite_to_register_save_state (int tid, TTRACE_ARG_TYPE ss_offset, char *buf,
361798944Sobrien			      int sizeof_buf)
361846283Sdfr{
361998944Sobrien  int tt_status;
362098944Sobrien  register_value_t register_value = 0;
362146283Sdfr
362246283Sdfr  tt_status = call_ttrace (TT_LWP_WUREGS,
362398944Sobrien			   tid,
362498944Sobrien			   ss_offset,
362598944Sobrien			   (TTRACE_ARG_TYPE) sizeof_buf,
362698944Sobrien			   (TTRACE_ARG_TYPE) buf);
362746283Sdfr  return tt_status;
362846283Sdfr}
362998944Sobrien
363046283Sdfr
363146283Sdfr/* This function is a sop to the largeish number of direct calls
363246283Sdfr   to call_ptrace that exist in other files.  Rather than create
363346283Sdfr   functions whose name abstracts away from ptrace, and change all
363446283Sdfr   the present callers of call_ptrace, we'll do the expedient (and
363546283Sdfr   perhaps only practical) thing.
363646283Sdfr
363746283Sdfr   Note HP-UX explicitly disallows a mix of ptrace & ttrace on a traced
363846283Sdfr   process.  Thus, we must translate all ptrace requests into their
363946283Sdfr   process-specific, ttrace equivalents.
364098944Sobrien */
364146283Sdfrint
364298944Sobriencall_ptrace (int pt_request, int gdb_tid, PTRACE_ARG3_TYPE addr, int data)
364346283Sdfr{
364498944Sobrien  ttreq_t tt_request;
364598944Sobrien  TTRACE_ARG_TYPE tt_addr = (TTRACE_ARG_TYPE) addr;
364698944Sobrien  TTRACE_ARG_TYPE tt_data = (TTRACE_ARG_TYPE) data;
364798944Sobrien  TTRACE_ARG_TYPE tt_addr2 = TT_NIL;
364898944Sobrien  int tt_status;
364998944Sobrien  register_value_t register_value;
365098944Sobrien  int read_buf;
365146283Sdfr
365246283Sdfr  /* Perform the necessary argument translation.  Note that some
365346283Sdfr     cases are funky enough in the ttrace realm that we handle them
365446283Sdfr     very specially.
365546283Sdfr   */
365698944Sobrien  switch (pt_request)
365798944Sobrien    {
365846283Sdfr      /* The following cases cannot conveniently be handled conveniently
365946283Sdfr         by merely adjusting the ptrace arguments and feeding into the
366046283Sdfr         generic call to ttrace at the bottom of this function.
366146283Sdfr
366246283Sdfr         Note that because all branches of this switch end in "return",
366346283Sdfr         there's no need for any "break" statements.
366498944Sobrien       */
366598944Sobrien    case PT_SETTRC:
3666130803Smarcel      return parent_attach_all (0, 0, 0);
366746283Sdfr
366898944Sobrien    case PT_RUREGS:
366998944Sobrien      tt_status = read_from_register_save_state (gdb_tid,
367098944Sobrien						 tt_addr,
367198944Sobrien						 &register_value,
367298944Sobrien						 sizeof (register_value));
367398944Sobrien      if (tt_status < 0)
367498944Sobrien	return tt_status;
367598944Sobrien      return register_value;
367646283Sdfr
367798944Sobrien    case PT_WUREGS:
367898944Sobrien      register_value = (int) tt_data;
367998944Sobrien      tt_status = write_to_register_save_state (gdb_tid,
368098944Sobrien						tt_addr,
368198944Sobrien						&register_value,
368298944Sobrien						sizeof (register_value));
368398944Sobrien      return tt_status;
368498944Sobrien      break;
368546283Sdfr
368698944Sobrien    case PT_READ_I:
368798944Sobrien      tt_status = call_ttrace (TT_PROC_RDTEXT,	/* Implicit 4-byte xfer becomes block-xfer. */
368898944Sobrien			       gdb_tid,
368998944Sobrien			       tt_addr,
369098944Sobrien			       (TTRACE_ARG_TYPE) 4,
369198944Sobrien			       (TTRACE_ARG_TYPE) & read_buf);
369298944Sobrien      if (tt_status < 0)
369398944Sobrien	return tt_status;
369498944Sobrien      return read_buf;
369546283Sdfr
369698944Sobrien    case PT_READ_D:
369798944Sobrien      tt_status = call_ttrace (TT_PROC_RDDATA,	/* Implicit 4-byte xfer becomes block-xfer. */
369898944Sobrien			       gdb_tid,
369998944Sobrien			       tt_addr,
370098944Sobrien			       (TTRACE_ARG_TYPE) 4,
370198944Sobrien			       (TTRACE_ARG_TYPE) & read_buf);
370298944Sobrien      if (tt_status < 0)
370398944Sobrien	return tt_status;
370498944Sobrien      return read_buf;
370546283Sdfr
370698944Sobrien    case PT_ATTACH:
370798944Sobrien      tt_status = call_real_ttrace (TT_PROC_ATTACH,
370898944Sobrien				    map_from_gdb_tid (gdb_tid),
370998944Sobrien				    (lwpid_t) TT_NIL,
371098944Sobrien				    tt_addr,
371198944Sobrien				    (TTRACE_ARG_TYPE) TT_VERSION,
371298944Sobrien				    tt_addr2);
371398944Sobrien      if (tt_status < 0)
371498944Sobrien	return tt_status;
371598944Sobrien      return tt_status;
371698944Sobrien
371746283Sdfr      /* The following cases are handled by merely adjusting the ptrace
371846283Sdfr         arguments and feeding into the generic call to ttrace.
371998944Sobrien       */
372098944Sobrien    case PT_DETACH:
372198944Sobrien      tt_request = TT_PROC_DETACH;
372298944Sobrien      break;
372346283Sdfr
372498944Sobrien    case PT_WRITE_I:
372598944Sobrien      tt_request = TT_PROC_WRTEXT;	/* Translates 4-byte xfer to block-xfer. */
372698944Sobrien      tt_data = 4;		/* This many bytes. */
372798944Sobrien      tt_addr2 = (TTRACE_ARG_TYPE) & data;	/* Address of xfer source. */
372898944Sobrien      break;
372946283Sdfr
373098944Sobrien    case PT_WRITE_D:
373198944Sobrien      tt_request = TT_PROC_WRDATA;	/* Translates 4-byte xfer to block-xfer. */
373298944Sobrien      tt_data = 4;		/* This many bytes. */
373398944Sobrien      tt_addr2 = (TTRACE_ARG_TYPE) & data;	/* Address of xfer source. */
373498944Sobrien      break;
373546283Sdfr
373698944Sobrien    case PT_RDTEXT:
373798944Sobrien      tt_request = TT_PROC_RDTEXT;
373898944Sobrien      break;
373946283Sdfr
374098944Sobrien    case PT_RDDATA:
374198944Sobrien      tt_request = TT_PROC_RDDATA;
374298944Sobrien      break;
374346283Sdfr
374498944Sobrien    case PT_WRTEXT:
374598944Sobrien      tt_request = TT_PROC_WRTEXT;
374698944Sobrien      break;
374746283Sdfr
374898944Sobrien    case PT_WRDATA:
374998944Sobrien      tt_request = TT_PROC_WRDATA;
375098944Sobrien      break;
375146283Sdfr
375298944Sobrien    case PT_CONTINUE:
375398944Sobrien      tt_request = TT_PROC_CONTINUE;
375498944Sobrien      break;
375546283Sdfr
375698944Sobrien    case PT_STEP:
375798944Sobrien      tt_request = TT_LWP_SINGLE;	/* Should not be making this request? */
375898944Sobrien      break;
375946283Sdfr
376098944Sobrien    case PT_KILL:
376198944Sobrien      tt_request = TT_PROC_EXIT;
376298944Sobrien      break;
376346283Sdfr
376498944Sobrien    case PT_GET_PROCESS_PATHNAME:
376598944Sobrien      tt_request = TT_PROC_GET_PATHNAME;
376698944Sobrien      break;
376746283Sdfr
376898944Sobrien    default:
376998944Sobrien      tt_request = pt_request;	/* Let ttrace be the one to complain. */
377098944Sobrien      break;
377198944Sobrien    }
377246283Sdfr
377346283Sdfr  return call_ttrace (tt_request,
377498944Sobrien		      gdb_tid,
377598944Sobrien		      tt_addr,
377698944Sobrien		      tt_data,
377798944Sobrien		      tt_addr2);
377846283Sdfr}
377946283Sdfr
378046283Sdfr/* Kill that pesky process!
378146283Sdfr */
378246283Sdfrvoid
378398944Sobrienkill_inferior (void)
378446283Sdfr{
378598944Sobrien  int tid;
378698944Sobrien  int wait_status;
378798944Sobrien  thread_info *t;
378846283Sdfr  thread_info **paranoia;
378998944Sobrien  int para_count, i;
379046283Sdfr
379198944Sobrien  if (PIDGET (inferior_ptid) == 0)
379246283Sdfr    return;
379346283Sdfr
379446283Sdfr  /* Walk the list of "threads", some of which are "pseudo threads",
379598944Sobrien     aka "processes".  For each that is NOT inferior_ptid, stop it,
379646283Sdfr     and detach it.
379746283Sdfr
379846283Sdfr     You see, we may not have just a single process to kill.  If we're
379946283Sdfr     restarting or quitting or detaching just after the inferior has
380046283Sdfr     forked, then we've actually two processes to clean up.
380146283Sdfr
380246283Sdfr     But we can't just call target_mourn_inferior() for each, since that
380346283Sdfr     zaps the target vector.
380498944Sobrien   */
380546283Sdfr
380698944Sobrien  paranoia = (thread_info **) xmalloc (thread_head.count *
380798944Sobrien				       sizeof (thread_info *));
380846283Sdfr  para_count = 0;
380998944Sobrien
381046283Sdfr  t = thread_head.head;
381198944Sobrien  while (t)
381298944Sobrien    {
381398944Sobrien
381498944Sobrien      paranoia[para_count] = t;
381598944Sobrien      for (i = 0; i < para_count; i++)
381698944Sobrien	{
381798944Sobrien	  if (t->next == paranoia[i])
381898944Sobrien	    {
381998944Sobrien	      warning ("Bad data in gdb's thread data; repairing.");
382098944Sobrien	      t->next = 0;
382198944Sobrien	    }
382298944Sobrien	}
382398944Sobrien      para_count++;
382498944Sobrien
382598944Sobrien      if (t->am_pseudo && (t->pid != PIDGET (inferior_ptid)))
382698944Sobrien	{
382798944Sobrien	  call_ttrace (TT_PROC_EXIT,
382898944Sobrien		       t->pid,
382998944Sobrien		       TT_NIL,
383098944Sobrien		       TT_NIL,
383198944Sobrien		       TT_NIL);
383298944Sobrien	}
383398944Sobrien      t = t->next;
383446283Sdfr    }
383546283Sdfr
383698944Sobrien  xfree (paranoia);
383746283Sdfr
383898944Sobrien  call_ttrace (TT_PROC_EXIT,
383998944Sobrien	       PIDGET (inferior_ptid),
384098944Sobrien	       TT_NIL,
384198944Sobrien	       TT_NIL,
384298944Sobrien	       TT_NIL);
384346283Sdfr  target_mourn_inferior ();
384498944Sobrien  clear_thread_info ();
384546283Sdfr}
384646283Sdfr
384746283Sdfr
384846283Sdfr#ifndef CHILD_RESUME
384946283Sdfr
385046283Sdfr/* Sanity check a thread about to be continued.
385146283Sdfr */
385246283Sdfrstatic void
385398944Sobrienthread_dropping_event_check (thread_info *p)
385446283Sdfr{
385598944Sobrien  if (!p->handled)
385698944Sobrien    {
385798944Sobrien      /*
385898944Sobrien       * This seems to happen when we "next" over a
385998944Sobrien       * "fork()" while following the parent.  If it's
386098944Sobrien       * the FORK event, that's ok.  If it's a SIGNAL
386198944Sobrien       * in the unfollowed child, that's ok to--but
386298944Sobrien       * how can we know that's what's going on?
386398944Sobrien       *
386498944Sobrien       * FIXME!
386598944Sobrien       */
386698944Sobrien      if (p->have_state)
386798944Sobrien	{
386898944Sobrien	  if (p->last_stop_state.tts_event == TTEVT_FORK)
386998944Sobrien	    {
387098944Sobrien	      /* Ok */
387198944Sobrien	      ;
387298944Sobrien	    }
387398944Sobrien	  else if (p->last_stop_state.tts_event == TTEVT_SIGNAL)
387498944Sobrien	    {
387598944Sobrien	      /* Ok, close eyes and let it happen.
387698944Sobrien	       */
387798944Sobrien	      ;
387898944Sobrien	    }
387998944Sobrien	  else
388098944Sobrien	    {
388198944Sobrien	      /* This shouldn't happen--we're dropping a
388298944Sobrien	       * real event.
388398944Sobrien	       */
388498944Sobrien	      warning ("About to continue process %d, thread %d with unhandled event %s.",
388598944Sobrien		       p->pid, p->tid,
388698944Sobrien		       get_printable_name_of_ttrace_event (
388798944Sobrien					     p->last_stop_state.tts_event));
388846283Sdfr
388946283Sdfr#ifdef PARANOIA
389098944Sobrien	      if (debug_on)
389198944Sobrien		print_tthread (p);
389246283Sdfr#endif
389398944Sobrien	    }
389498944Sobrien	}
389598944Sobrien      else
389698944Sobrien	{
389798944Sobrien	  /* No saved state, have to assume it failed.
389898944Sobrien	   */
389998944Sobrien	  warning ("About to continue process %d, thread %d with unhandled event.",
390098944Sobrien		   p->pid, p->tid);
390146283Sdfr#ifdef PARANOIA
390298944Sobrien	  if (debug_on)
390398944Sobrien	    print_tthread (p);
390446283Sdfr#endif
390598944Sobrien	}
390646283Sdfr    }
390746283Sdfr
390898944Sobrien}				/* thread_dropping_event_check */
390998944Sobrien
391046283Sdfr/* Use a loop over the threads to continue all the threads but
391146283Sdfr * the one specified, which is to be stepped.
391246283Sdfr */
391346283Sdfrstatic void
391498944Sobrienthreads_continue_all_but_one (lwpid_t gdb_tid, int signal)
391546283Sdfr{
391698944Sobrien  thread_info *p;
391798944Sobrien  int thread_signal;
391898944Sobrien  lwpid_t real_tid;
391998944Sobrien  lwpid_t scan_tid;
392098944Sobrien  ttstate_t state;
392198944Sobrien  int real_pid;
392298944Sobrien
392346283Sdfr#ifdef THREAD_DEBUG
392498944Sobrien  if (debug_on)
392598944Sobrien    printf ("Using loop over threads to step/resume with signals\n");
392646283Sdfr#endif
392746283Sdfr
392898944Sobrien  /* First update the thread list.
392998944Sobrien   */
393098944Sobrien  set_all_unseen ();
393198944Sobrien  real_tid = map_from_gdb_tid (gdb_tid);
393298944Sobrien  real_pid = get_pid_for (real_tid);
393398944Sobrien
393498944Sobrien  scan_tid = get_process_first_stopped_thread_id (real_pid, &state);
393598944Sobrien  while (0 != scan_tid)
393698944Sobrien    {
393798944Sobrien
393846283Sdfr#ifdef THREAD_DEBUG
393998944Sobrien      /* FIX: later should check state is stopped;
394098944Sobrien       * state.tts_flags & TTS_STATEMASK == TTS_WASSUSPENDED
394198944Sobrien       */
394298944Sobrien      if (debug_on)
3943130803Smarcel 	if ((state.tts_flags & TTS_STATEMASK) != TTS_WASSUSPENDED)
394498944Sobrien	  printf ("About to continue non-stopped thread %d\n", scan_tid);
394546283Sdfr#endif
394646283Sdfr
394798944Sobrien      p = find_thread_info (scan_tid);
394898944Sobrien      if (NULL == p)
394998944Sobrien	{
395098944Sobrien	  add_tthread (real_pid, scan_tid);
395198944Sobrien	  p = find_thread_info (scan_tid);
395246283Sdfr
395398944Sobrien	  /* This is either a newly-created thread or the
395498944Sobrien	   * result of a fork; in either case there's no
395598944Sobrien	   * actual event to worry about.
395698944Sobrien	   */
395798944Sobrien	  p->handled = 1;
395846283Sdfr
395998944Sobrien	  if (state.tts_event != TTEVT_NONE)
396098944Sobrien	    {
396198944Sobrien	      /* Oops, do need to worry!
396298944Sobrien	       */
396398944Sobrien	      warning ("Unexpected thread with \"%s\" event.",
396498944Sobrien		       get_printable_name_of_ttrace_event (state.tts_event));
396598944Sobrien	    }
396698944Sobrien	}
396798944Sobrien      else if (scan_tid != p->tid)
396898944Sobrien	error ("Bad data in thread database.");
396946283Sdfr
397046283Sdfr#ifdef THREAD_DEBUG
397198944Sobrien      if (debug_on)
397298944Sobrien	if (p->terminated)
397398944Sobrien	  printf ("Why are we continuing a dead thread?\n");
397446283Sdfr#endif
397546283Sdfr
397698944Sobrien      p->seen = 1;
397798944Sobrien
397898944Sobrien      scan_tid = get_process_next_stopped_thread_id (real_pid, &state);
397946283Sdfr    }
398046283Sdfr
398198944Sobrien  /* Remove unseen threads.
398298944Sobrien   */
398398944Sobrien  update_thread_list ();
398446283Sdfr
398598944Sobrien  /* Now run down the thread list and continue or step.
398698944Sobrien   */
398798944Sobrien  for (p = thread_head.head; p; p = p->next)
398898944Sobrien    {
398946283Sdfr
399098944Sobrien      /* Sanity check.
399198944Sobrien       */
399298944Sobrien      thread_dropping_event_check (p);
399346283Sdfr
399498944Sobrien      /* Pass the correct signals along.
399598944Sobrien       */
399698944Sobrien      if (p->have_signal)
399798944Sobrien	{
399898944Sobrien	  thread_signal = p->signal_value;
399998944Sobrien	  p->have_signal = 0;
400098944Sobrien	}
400198944Sobrien      else
400298944Sobrien	thread_signal = 0;
400346283Sdfr
400498944Sobrien      if (p->tid != real_tid)
400598944Sobrien	{
400698944Sobrien	  /*
400798944Sobrien	   * Not the thread of interest, so continue it
400898944Sobrien	   * as the user expects.
400998944Sobrien	   */
401098944Sobrien	  if (p->stepping_mode == DO_STEP)
401198944Sobrien	    {
401298944Sobrien	      /* Just step this thread.
401398944Sobrien	       */
401498944Sobrien	      call_ttrace (
401598944Sobrien			    TT_LWP_SINGLE,
401698944Sobrien			    p->tid,
401798944Sobrien			    TT_USE_CURRENT_PC,
401898944Sobrien			    (TTRACE_ARG_TYPE) target_signal_to_host (signal),
401998944Sobrien			    TT_NIL);
402098944Sobrien	    }
402198944Sobrien	  else
402298944Sobrien	    {
402398944Sobrien	      /* Regular continue (default case).
402498944Sobrien	       */
402598944Sobrien	      call_ttrace (
402698944Sobrien			    TT_LWP_CONTINUE,
402798944Sobrien			    p->tid,
402898944Sobrien			    TT_USE_CURRENT_PC,
402998944Sobrien		    (TTRACE_ARG_TYPE) target_signal_to_host (thread_signal),
403098944Sobrien			    TT_NIL);
403198944Sobrien	    }
403298944Sobrien	}
403398944Sobrien      else
403498944Sobrien	{
403598944Sobrien	  /* Step the thread of interest.
403698944Sobrien	   */
403798944Sobrien	  call_ttrace (
403898944Sobrien			TT_LWP_SINGLE,
403998944Sobrien			real_tid,
404098944Sobrien			TT_USE_CURRENT_PC,
404198944Sobrien			(TTRACE_ARG_TYPE) target_signal_to_host (signal),
404298944Sobrien			TT_NIL);
404398944Sobrien	}
404498944Sobrien    }				/* Loop over threads */
404598944Sobrien}				/* End threads_continue_all_but_one */
404698944Sobrien
404746283Sdfr/* Use a loop over the threads to continue all the threads.
404846283Sdfr * This is done when a signal must be sent to any of the threads.
404946283Sdfr */
405046283Sdfrstatic void
405198944Sobrienthreads_continue_all_with_signals (lwpid_t gdb_tid, int signal)
405246283Sdfr{
405398944Sobrien  thread_info *p;
405498944Sobrien  int thread_signal;
405598944Sobrien  lwpid_t real_tid;
405698944Sobrien  lwpid_t scan_tid;
405798944Sobrien  ttstate_t state;
405898944Sobrien  int real_pid;
405946283Sdfr
406046283Sdfr#ifdef THREAD_DEBUG
406198944Sobrien  if (debug_on)
406298944Sobrien    printf ("Using loop over threads to resume with signals\n");
406346283Sdfr#endif
406446283Sdfr
406598944Sobrien  /* Scan and update thread list.
406698944Sobrien   */
406798944Sobrien  set_all_unseen ();
406898944Sobrien  real_tid = map_from_gdb_tid (gdb_tid);
406998944Sobrien  real_pid = get_pid_for (real_tid);
407046283Sdfr
407198944Sobrien  scan_tid = get_process_first_stopped_thread_id (real_pid, &state);
407298944Sobrien  while (0 != scan_tid)
407398944Sobrien    {
407498944Sobrien
407546283Sdfr#ifdef THREAD_DEBUG
407698944Sobrien      if (debug_on)
4077130803Smarcel	if ((state.tts_flags & TTS_STATEMASK) != TTS_WASSUSPENDED)
407898944Sobrien	  warning ("About to continue non-stopped thread %d\n", scan_tid);
407946283Sdfr#endif
408046283Sdfr
408198944Sobrien      p = find_thread_info (scan_tid);
408298944Sobrien      if (NULL == p)
408398944Sobrien	{
408498944Sobrien	  add_tthread (real_pid, scan_tid);
408598944Sobrien	  p = find_thread_info (scan_tid);
408646283Sdfr
408798944Sobrien	  /* This is either a newly-created thread or the
408898944Sobrien	   * result of a fork; in either case there's no
408998944Sobrien	   * actual event to worry about.
409098944Sobrien	   */
409198944Sobrien	  p->handled = 1;
409246283Sdfr
409398944Sobrien	  if (state.tts_event != TTEVT_NONE)
409498944Sobrien	    {
409598944Sobrien	      /* Oops, do need to worry!
409698944Sobrien	       */
409798944Sobrien	      warning ("Unexpected thread with \"%s\" event.",
409898944Sobrien		       get_printable_name_of_ttrace_event (state.tts_event));
409998944Sobrien	    }
410098944Sobrien	}
410146283Sdfr
410246283Sdfr#ifdef THREAD_DEBUG
410398944Sobrien      if (debug_on)
410498944Sobrien	if (p->terminated)
410598944Sobrien	  printf ("Why are we continuing a dead thread? (1)\n");
410646283Sdfr#endif
410746283Sdfr
410898944Sobrien      p->seen = 1;
410946283Sdfr
411098944Sobrien      scan_tid = get_process_next_stopped_thread_id (real_pid, &state);
411146283Sdfr    }
411246283Sdfr
411398944Sobrien  /* Remove unseen threads from our list.
411498944Sobrien   */
411598944Sobrien  update_thread_list ();
411646283Sdfr
411798944Sobrien  /* Continue the threads.
411898944Sobrien   */
411998944Sobrien  for (p = thread_head.head; p; p = p->next)
412098944Sobrien    {
412146283Sdfr
412298944Sobrien      /* Sanity check.
412398944Sobrien       */
412498944Sobrien      thread_dropping_event_check (p);
412546283Sdfr
412698944Sobrien      /* Pass the correct signals along.
412798944Sobrien       */
412898944Sobrien      if (p->tid == real_tid)
412998944Sobrien	{
413098944Sobrien	  thread_signal = signal;
413198944Sobrien	  p->have_signal = 0;
413298944Sobrien	}
413398944Sobrien      else if (p->have_signal)
413498944Sobrien	{
413598944Sobrien	  thread_signal = p->signal_value;
413698944Sobrien	  p->have_signal = 0;
413798944Sobrien	}
413898944Sobrien      else
413998944Sobrien	thread_signal = 0;
414046283Sdfr
414198944Sobrien      if (p->stepping_mode == DO_STEP)
414298944Sobrien	{
414398944Sobrien	  call_ttrace (
414498944Sobrien			TT_LWP_SINGLE,
414598944Sobrien			p->tid,
414698944Sobrien			TT_USE_CURRENT_PC,
414798944Sobrien			(TTRACE_ARG_TYPE) target_signal_to_host (signal),
414898944Sobrien			TT_NIL);
414998944Sobrien	}
415098944Sobrien      else
415198944Sobrien	{
415298944Sobrien	  /* Continue this thread (default case).
415398944Sobrien	   */
415498944Sobrien	  call_ttrace (
415598944Sobrien			TT_LWP_CONTINUE,
415698944Sobrien			p->tid,
415798944Sobrien			TT_USE_CURRENT_PC,
415898944Sobrien		    (TTRACE_ARG_TYPE) target_signal_to_host (thread_signal),
415998944Sobrien			TT_NIL);
416098944Sobrien	}
416146283Sdfr    }
416298944Sobrien}				/* End threads_continue_all_with_signals */
416346283Sdfr
416446283Sdfr/* Step one thread only.
416546283Sdfr */
416646283Sdfrstatic void
416798944Sobrienthread_fake_step (lwpid_t tid, enum target_signal signal)
416846283Sdfr{
416998944Sobrien  thread_info *p;
417046283Sdfr
417146283Sdfr#ifdef THREAD_DEBUG
417298944Sobrien  if (debug_on)
417398944Sobrien    {
417498944Sobrien      printf ("Doing a fake-step over a bpt, etc. for %d\n", tid);
417546283Sdfr
417698944Sobrien      if (is_terminated (tid))
417798944Sobrien	printf ("Why are we continuing a dead thread? (4)\n");
417846283Sdfr    }
417946283Sdfr#endif
418046283Sdfr
418198944Sobrien  if (doing_fake_step)
418298944Sobrien    warning ("Step while step already in progress.");
418398944Sobrien
418498944Sobrien  /* See if there's a saved signal value for this
418598944Sobrien   * thread to be passed on, but no current signal.
418698944Sobrien   */
418798944Sobrien  p = find_thread_info (tid);
418898944Sobrien  if (p != NULL)
418998944Sobrien    {
419098944Sobrien      if (p->have_signal && signal == TARGET_SIGNAL_0)
419198944Sobrien	{
419298944Sobrien	  /* Pass on a saved signal.
419398944Sobrien	   */
419498944Sobrien	  signal = p->signal_value;
419598944Sobrien	}
419698944Sobrien
419798944Sobrien      p->have_signal = 0;
419846283Sdfr    }
419946283Sdfr
420098944Sobrien  if (!p->handled)
420198944Sobrien    warning ("Internal error: continuing unhandled thread.");
420246283Sdfr
420398944Sobrien  call_ttrace (TT_LWP_SINGLE,
420498944Sobrien	       tid,
420598944Sobrien	       TT_USE_CURRENT_PC,
420698944Sobrien	       (TTRACE_ARG_TYPE) target_signal_to_host (signal),
420798944Sobrien	       TT_NIL);
420846283Sdfr
420998944Sobrien  /* Do bookkeeping so "call_ttrace_wait" knows it has to wait
421098944Sobrien   * for this thread only, and clear any saved signal info.
421198944Sobrien   */
421298944Sobrien  doing_fake_step = 1;
421398944Sobrien  fake_step_tid = tid;
421446283Sdfr
421598944Sobrien}				/* End thread_fake_step */
421698944Sobrien
421746283Sdfr/* Continue one thread when a signal must be sent to it.
421846283Sdfr */
421946283Sdfrstatic void
422098944Sobrienthreads_continue_one_with_signal (lwpid_t gdb_tid, int signal)
422146283Sdfr{
422298944Sobrien  thread_info *p;
422398944Sobrien  lwpid_t real_tid;
422498944Sobrien  int real_pid;
422598944Sobrien
422646283Sdfr#ifdef THREAD_DEBUG
422798944Sobrien  if (debug_on)
422898944Sobrien    printf ("Continuing one thread with a signal\n");
422946283Sdfr#endif
423046283Sdfr
423198944Sobrien  real_tid = map_from_gdb_tid (gdb_tid);
423298944Sobrien  real_pid = get_pid_for (real_tid);
423346283Sdfr
423498944Sobrien  p = find_thread_info (real_tid);
423598944Sobrien  if (NULL == p)
423698944Sobrien    {
423798944Sobrien      add_tthread (real_pid, real_tid);
423846283Sdfr    }
423946283Sdfr
424046283Sdfr#ifdef THREAD_DEBUG
424198944Sobrien  if (debug_on)
424298944Sobrien    if (p->terminated)
424398944Sobrien      printf ("Why are we continuing a dead thread? (2)\n");
424446283Sdfr#endif
424546283Sdfr
424698944Sobrien  if (!p->handled)
424798944Sobrien    warning ("Internal error: continuing unhandled thread.");
424898944Sobrien
424998944Sobrien  p->have_signal = 0;
425098944Sobrien
425198944Sobrien  call_ttrace (TT_LWP_CONTINUE,
425298944Sobrien	       gdb_tid,
425398944Sobrien	       TT_USE_CURRENT_PC,
425498944Sobrien	       (TTRACE_ARG_TYPE) target_signal_to_host (signal),
425598944Sobrien	       TT_NIL);
425646283Sdfr}
425746283Sdfr#endif
425846283Sdfr
425946283Sdfr#ifndef CHILD_RESUME
426046283Sdfr
426146283Sdfr/* Resume execution of the inferior process.
426298944Sobrien
426346283Sdfr * This routine is in charge of setting the "handled" bits.
426446283Sdfr *
426546283Sdfr *   If STEP is zero,      continue it.
426646283Sdfr *   If STEP is nonzero,   single-step it.
426746283Sdfr *
426846283Sdfr *   If SIGNAL is nonzero, give it that signal.
426946283Sdfr *
427046283Sdfr *   If TID is -1,         apply to all threads.
427146283Sdfr *   If TID is not -1,     apply to specified thread.
427246283Sdfr *
427346283Sdfr *           STEP
427446283Sdfr *      \      !0                        0
427546283Sdfr *  TID  \________________________________________________
427646283Sdfr *       |
427746283Sdfr *   -1  |   Step current            Continue all threads
427846283Sdfr *       |   thread and              (but which gets any
427946283Sdfr *       |   continue others         signal?--We look at
428098944Sobrien *       |                           "inferior_ptid")
428146283Sdfr *       |
428246283Sdfr *    N  |   Step _this_ thread      Continue _this_ thread
428346283Sdfr *       |   and leave others        and leave others
428446283Sdfr *       |   stopped; internally     stopped; used only for
428546283Sdfr *       |   used by gdb, never      hardware watchpoints
428646283Sdfr *       |   a user command.         and attach, never a
428746283Sdfr *       |                           user command.
428846283Sdfr */
428946283Sdfrvoid
429098944Sobrienchild_resume (ptid_t ptid, int step, enum target_signal signal)
429146283Sdfr{
429298944Sobrien  int resume_all_threads;
429346283Sdfr  lwpid_t tid;
429498944Sobrien  process_state_t new_process_state;
429598944Sobrien  lwpid_t gdb_tid = PIDGET (ptid);
429646283Sdfr
429746283Sdfr  resume_all_threads =
429846283Sdfr    (gdb_tid == INFTTRACE_ALL_THREADS) ||
429946283Sdfr    (vfork_in_flight);
430046283Sdfr
430198944Sobrien  if (resume_all_threads)
430298944Sobrien    {
430398944Sobrien      /* Resume all threads, but first pick a tid value
430498944Sobrien       * so we can get the pid when in call_ttrace doing
430598944Sobrien       * the map.
430698944Sobrien       */
430798944Sobrien      if (vfork_in_flight)
430898944Sobrien	tid = vforking_child_pid;
430998944Sobrien      else
431098944Sobrien	tid = map_from_gdb_tid (PIDGET (inferior_ptid));
431198944Sobrien    }
431246283Sdfr  else
431398944Sobrien    tid = map_from_gdb_tid (gdb_tid);
431446283Sdfr
431546283Sdfr#ifdef THREAD_DEBUG
431698944Sobrien  if (debug_on)
431798944Sobrien    {
431898944Sobrien      if (more_events_left)
431998944Sobrien	printf ("More events; ");
432046283Sdfr
432198944Sobrien      if (signal != 0)
432298944Sobrien	printf ("Sending signal %d; ", signal);
432346283Sdfr
432498944Sobrien      if (resume_all_threads)
432598944Sobrien	{
432698944Sobrien	  if (step == 0)
432798944Sobrien	    printf ("Continue process %d\n", tid);
432898944Sobrien	  else
432998944Sobrien	    printf ("Step/continue thread %d\n", tid);
433098944Sobrien	}
433198944Sobrien      else
433298944Sobrien	{
433398944Sobrien	  if (step == 0)
433498944Sobrien	    printf ("Continue thread %d\n", tid);
433598944Sobrien	  else
433698944Sobrien	    printf ("Step just thread %d\n", tid);
433798944Sobrien	}
433898944Sobrien
433998944Sobrien      if (vfork_in_flight)
434098944Sobrien	printf ("Vfork in flight\n");
434198944Sobrien    }
434246283Sdfr#endif
434346283Sdfr
434498944Sobrien  if (process_state == RUNNING)
434598944Sobrien    warning ("Internal error in resume logic; doing resume or step anyway.");
434646283Sdfr
434798944Sobrien  if (!step			/* Asked to continue...       */
434898944Sobrien      && resume_all_threads	/* whole process..            */
434998944Sobrien      && signal != 0		/* with a signal...           */
435098944Sobrien      && more_events_left > 0)
435198944Sobrien    {				/* but we can't yet--save it! */
435298944Sobrien
435346283Sdfr      /* Continue with signal means we have to set the pending
435446283Sdfr       * signal value for this thread.
435546283Sdfr       */
435646283Sdfr      thread_info *k;
435798944Sobrien
435846283Sdfr#ifdef THREAD_DEBUG
435998944Sobrien      if (debug_on)
436098944Sobrien	printf ("Saving signal %d for thread %d\n", signal, tid);
436146283Sdfr#endif
436246283Sdfr
436398944Sobrien      k = find_thread_info (tid);
436498944Sobrien      if (k != NULL)
436598944Sobrien	{
436698944Sobrien	  k->have_signal = 1;
436798944Sobrien	  k->signal_value = signal;
436846283Sdfr
436946283Sdfr#ifdef THREAD_DEBUG
437098944Sobrien	  if (debug_on)
437198944Sobrien	    if (k->terminated)
437298944Sobrien	      printf ("Why are we continuing a dead thread? (3)\n");
437346283Sdfr#endif
437446283Sdfr
437598944Sobrien	}
437646283Sdfr
437746283Sdfr#ifdef THREAD_DEBUG
437898944Sobrien      else if (debug_on)
437998944Sobrien	{
438098944Sobrien	  printf ("No thread info for tid %d\n", tid);
438198944Sobrien	}
438246283Sdfr#endif
438398944Sobrien    }
438446283Sdfr
438546283Sdfr  /* Are we faking this "continue" or "step"?
438698944Sobrien
438746283Sdfr   * We used to do steps by continuing all the threads for
438846283Sdfr   * which the events had been handled already.  While
438946283Sdfr   * conceptually nicer (hides it all in a lower level), this
439046283Sdfr   * can lead to starvation and a hang (e.g. all but one thread
439146283Sdfr   * are unhandled at a breakpoint just before a "join" operation,
439246283Sdfr   * and one thread is in the join, and the user wants to step that
439346283Sdfr   * thread).
439446283Sdfr   */
439598944Sobrien  if (resume_all_threads	/* Whole process, therefore user command */
439698944Sobrien      && more_events_left > 0)
439798944Sobrien    {				/* But we can't do this yet--fake it! */
439846283Sdfr      thread_info *p;
439998944Sobrien
440098944Sobrien      if (!step)
440198944Sobrien	{
440298944Sobrien	  /* No need to do any notes on a per-thread
440398944Sobrien	   * basis--we're done!
440498944Sobrien	   */
440546283Sdfr#ifdef WAIT_BUFFER_DEBUG
440698944Sobrien	  if (debug_on)
440798944Sobrien	    printf ("Faking a process resume.\n");
440846283Sdfr#endif
440946283Sdfr
441098944Sobrien	  return;
441198944Sobrien	}
441298944Sobrien      else
441398944Sobrien	{
441446283Sdfr
441546283Sdfr#ifdef WAIT_BUFFER_DEBUG
441698944Sobrien	  if (debug_on)
441798944Sobrien	    printf ("Faking a process step.\n");
441846283Sdfr#endif
441946283Sdfr
442098944Sobrien	}
442146283Sdfr
442298944Sobrien      p = find_thread_info (tid);
442398944Sobrien      if (p == NULL)
442498944Sobrien	{
442598944Sobrien	  warning ("No thread information for tid %d, 'next' command ignored.\n", tid);
442698944Sobrien	  return;
442798944Sobrien	}
442898944Sobrien      else
442998944Sobrien	{
443098944Sobrien
443146283Sdfr#ifdef THREAD_DEBUG
443298944Sobrien	  if (debug_on)
443398944Sobrien	    if (p->terminated)
443498944Sobrien	      printf ("Why are we continuing a dead thread? (3.5)\n");
443546283Sdfr#endif
443646283Sdfr
443798944Sobrien	  if (p->stepping_mode != DO_DEFAULT)
443898944Sobrien	    {
443998944Sobrien	      warning ("Step or continue command applied to thread which is already stepping or continuing; command ignored.");
444046283Sdfr
444198944Sobrien	      return;
444298944Sobrien	    }
444346283Sdfr
444498944Sobrien	  if (step)
444598944Sobrien	    p->stepping_mode = DO_STEP;
444698944Sobrien	  else
444798944Sobrien	    p->stepping_mode = DO_CONTINUE;
444846283Sdfr
444998944Sobrien	  return;
445098944Sobrien	}			/* Have thread info */
445198944Sobrien    }				/* Must fake step or go */
445246283Sdfr
445346283Sdfr  /* Execept for fake-steps, from here on we know we are
445446283Sdfr   * going to wind up with a running process which will
445546283Sdfr   * need a real wait.
445646283Sdfr   */
445746283Sdfr  new_process_state = RUNNING;
445846283Sdfr
445946283Sdfr  /* An address of TT_USE_CURRENT_PC tells ttrace to continue from where
446046283Sdfr   * it was.  (If GDB wanted it to start some other way, we have already
446146283Sdfr   * written a new PC value to the child.)
446246283Sdfr   *
446346283Sdfr   * If this system does not support PT_STEP, a higher level function will
446446283Sdfr   * have called single_step() to transmute the step request into a
446546283Sdfr   * continue request (by setting breakpoints on all possible successor
446646283Sdfr   * instructions), so we don't have to worry about that here.
446746283Sdfr   */
446898944Sobrien  if (step)
446998944Sobrien    {
447098944Sobrien      if (resume_all_threads)
447198944Sobrien	{
447298944Sobrien	  /*
447398944Sobrien	   * Regular user step: other threads get a "continue".
447498944Sobrien	   */
447598944Sobrien	  threads_continue_all_but_one (tid, signal);
447698944Sobrien	  clear_all_handled ();
447798944Sobrien	  clear_all_stepping_mode ();
447898944Sobrien	}
447946283Sdfr
448098944Sobrien      else
448198944Sobrien	{
448298944Sobrien	  /* "Fake step": gdb is stepping one thread over a
448398944Sobrien	   * breakpoint, watchpoint, or out of a library load
448498944Sobrien	   * event, etc.  The rest just stay where they are.
448598944Sobrien	   *
448698944Sobrien	   * Also used when there are pending events: we really
448798944Sobrien	   * step the current thread, but leave the rest stopped.
448898944Sobrien	   * Users can't request this, but "wait_for_inferior"
448998944Sobrien	   * does--a lot!
449098944Sobrien	   */
449198944Sobrien	  thread_fake_step (tid, signal);
449246283Sdfr
449398944Sobrien	  /* Clear the "handled" state of this thread, because
449498944Sobrien	   * we'll soon get a new event for it.  Other events
449598944Sobrien	   * stay as they were.
449698944Sobrien	   */
449798944Sobrien	  clear_handled (tid);
449898944Sobrien	  clear_stepping_mode (tid);
449998944Sobrien	  new_process_state = FAKE_STEPPING;
450098944Sobrien	}
450198944Sobrien    }
450298944Sobrien
450398944Sobrien  else
450498944Sobrien    {
4505130803Smarcel      /* TT_LWP_CONTINUE can pass signals to threads, TT_PROC_CONTINUE can't.
4506130803Smarcel	 Therefore, we really can't use TT_PROC_CONTINUE here.
4507130803Smarcel
4508130803Smarcel	 Consider a process which stopped due to signal which gdb decides
4509130803Smarcel	 to handle and not pass on to the inferior.  In that case we must
4510130803Smarcel	 clear the pending signal by restarting the inferior using
4511130803Smarcel	 TT_LWP_CONTINUE and pass zero as the signal number.  Else the
4512130803Smarcel	 pending signal will be passed to the inferior.  interrupt.exp
4513130803Smarcel	 in the testsuite does this precise thing and fails due to the
4514130803Smarcel	 unwanted signal delivery to the inferior.  */
4515130803Smarcel      /* drow/2002-12-05: However, note that we must use TT_PROC_CONTINUE
4516130803Smarcel	 if we are tracing a vfork.  */
4517130803Smarcel      if (vfork_in_flight)
451898944Sobrien	{
4519130803Smarcel	  call_ttrace (TT_PROC_CONTINUE, tid, TT_NIL, TT_NIL, TT_NIL);
4520130803Smarcel	  clear_all_handled ();
4521130803Smarcel	  clear_all_stepping_mode ();
4522130803Smarcel	}
4523130803Smarcel      else if (resume_all_threads)
4524130803Smarcel	{
452546283Sdfr#ifdef THREAD_DEBUG
4526130803Smarcel	  if (debug_on)
4527130803Smarcel	    printf ("Doing a continue by loop of all threads\n");
452846283Sdfr#endif
452946283Sdfr
4530130803Smarcel	  threads_continue_all_with_signals (tid, signal);
453146283Sdfr
4532130803Smarcel	  clear_all_handled ();
4533130803Smarcel	  clear_all_stepping_mode ();
453498944Sobrien	}
453598944Sobrien      else
453698944Sobrien	{
453746283Sdfr#ifdef THREAD_DEBUG
4538130803Smarcel	  printf ("Doing a continue w/signal of just thread %d\n", tid);
453946283Sdfr#endif
454046283Sdfr
4541130803Smarcel	  threads_continue_one_with_signal (tid, signal);
454246283Sdfr
4543130803Smarcel	  /* Clear the "handled" state of this thread, because we
4544130803Smarcel	     will soon get a new event for it.  Other events can
4545130803Smarcel	     stay as they were.  */
4546130803Smarcel	  clear_handled (tid);
4547130803Smarcel	  clear_stepping_mode (tid);
454898944Sobrien	}
454998944Sobrien    }
455046283Sdfr
455146283Sdfr  process_state = new_process_state;
455246283Sdfr
455346283Sdfr#ifdef WAIT_BUFFER_DEBUG
455498944Sobrien  if (debug_on)
455598944Sobrien    printf ("Process set to %s\n",
455698944Sobrien	    get_printable_name_of_process_state (process_state));
455746283Sdfr#endif
455846283Sdfr
455946283Sdfr}
456046283Sdfr#endif /* CHILD_RESUME */
456198944Sobrien
456246283Sdfr
456346283Sdfr#ifdef ATTACH_DETACH
456446283Sdfr/*
456546283Sdfr * Like it says.
456646283Sdfr *
456798944Sobrien * One worry is that we may not be attaching to "inferior_ptid"
456846283Sdfr * and thus may not want to clear out our data.  FIXME?
456946283Sdfr *
457046283Sdfr */
457146283Sdfrstatic void
457298944Sobrienupdate_thread_state_after_attach (int pid, attach_continue_t kind_of_go)
457346283Sdfr{
457498944Sobrien  int tt_status;
457598944Sobrien  ttstate_t thread_state;
457698944Sobrien  lwpid_t a_thread;
457798944Sobrien  lwpid_t tid;
457846283Sdfr
457946283Sdfr  /* The process better be stopped.
458046283Sdfr   */
458198944Sobrien  if (process_state != STOPPED
458298944Sobrien      && process_state != VFORKING)
458398944Sobrien    warning ("Internal error attaching.");
458446283Sdfr
458546283Sdfr  /* Clear out old tthread info and start over.  This has the
458646283Sdfr   * side effect of ensuring that the TRAP is reported as being
458746283Sdfr   * in the right thread (re-mapped from tid to pid).
458846283Sdfr   *
458946283Sdfr   * It's because we need to add the tthread _now_ that we
459046283Sdfr   * need to call "clear_thread_info" _now_, and that's why
459146283Sdfr   * "require_notification_of_events" doesn't clear the thread
459246283Sdfr   * info (it's called later than this routine).
459346283Sdfr   */
459498944Sobrien  clear_thread_info ();
459546283Sdfr  a_thread = 0;
459646283Sdfr
459746283Sdfr  for (tid = get_process_first_stopped_thread_id (pid, &thread_state);
459846283Sdfr       tid != 0;
459946283Sdfr       tid = get_process_next_stopped_thread_id (pid, &thread_state))
460046283Sdfr    {
460146283Sdfr      thread_info *p;
460298944Sobrien
460346283Sdfr      if (a_thread == 0)
460498944Sobrien	{
460598944Sobrien	  a_thread = tid;
460646283Sdfr#ifdef THREAD_DEBUG
460798944Sobrien	  if (debug_on)
460898944Sobrien	    printf ("Attaching to process %d, thread %d\n",
460998944Sobrien		    pid, a_thread);
461046283Sdfr#endif
461198944Sobrien	}
461246283Sdfr
461346283Sdfr      /* Tell ourselves and the "rest of gdb" that this thread
461446283Sdfr       * exists.
461546283Sdfr       *
461646283Sdfr       * This isn't really a hack.  Other thread-based versions
461746283Sdfr       * of gdb (e.g. gnu-nat.c) seem to do the same thing.
461846283Sdfr       *
461946283Sdfr       * We don't need to do mapping here, as we know this
462046283Sdfr       * is the first thread and thus gets the real pid
462198944Sobrien       * (and is "inferior_ptid").
462246283Sdfr       *
462346283Sdfr       * NOTE: it probably isn't the originating thread,
462446283Sdfr       *       but that doesn't matter (we hope!).
462546283Sdfr       */
462698944Sobrien      add_tthread (pid, tid);
462798944Sobrien      p = find_thread_info (tid);
462898944Sobrien      if (NULL == p)		/* ?We just added it! */
462998944Sobrien	error ("Internal error adding a thread on attach.");
463098944Sobrien
463198944Sobrien      copy_ttstate_t (&p->last_stop_state, &thread_state);
463246283Sdfr      p->have_state = 1;
463346283Sdfr
463498944Sobrien      if (DO_ATTACH_CONTINUE == kind_of_go)
463598944Sobrien	{
463698944Sobrien	  /*
463798944Sobrien	   * If we are going to CONTINUE afterwards,
463898944Sobrien	   * raising a SIGTRAP, don't bother trying to
463998944Sobrien	   * handle this event.  But check first!
464098944Sobrien	   */
464198944Sobrien	  switch (p->last_stop_state.tts_event)
464298944Sobrien	    {
464346283Sdfr
464498944Sobrien	    case TTEVT_NONE:
464598944Sobrien	      /* Ok to set this handled.
464698944Sobrien	       */
464798944Sobrien	      break;
464846283Sdfr
464998944Sobrien	    default:
465098944Sobrien	      warning ("Internal error; skipping event %s on process %d, thread %d.",
465198944Sobrien		       get_printable_name_of_ttrace_event (
465298944Sobrien					      p->last_stop_state.tts_event),
465398944Sobrien		       p->pid, p->tid);
465498944Sobrien	    }
465546283Sdfr
465698944Sobrien	  set_handled (pid, tid);
465746283Sdfr
465898944Sobrien	}
465998944Sobrien      else
466098944Sobrien	{
466198944Sobrien	  /* There will be no "continue" opertion, so the
466298944Sobrien	   * process remains stopped.  Don't set any events
466398944Sobrien	   * handled except the "gimmies".
466498944Sobrien	   */
466598944Sobrien	  switch (p->last_stop_state.tts_event)
466698944Sobrien	    {
466746283Sdfr
466898944Sobrien	    case TTEVT_NONE:
466998944Sobrien	      /* Ok to ignore this.
467098944Sobrien	       */
467198944Sobrien	      set_handled (pid, tid);
467298944Sobrien	      break;
467346283Sdfr
467498944Sobrien	    case TTEVT_EXEC:
467598944Sobrien	    case TTEVT_FORK:
467698944Sobrien	      /* Expected "other" FORK or EXEC event from a
467798944Sobrien	       * fork or vfork.
467898944Sobrien	       */
467998944Sobrien	      break;
468098944Sobrien
468198944Sobrien	    default:
468298944Sobrien	      printf ("Internal error: failed to handle event %s on process %d, thread %d.",
468398944Sobrien		      get_printable_name_of_ttrace_event (
468498944Sobrien					      p->last_stop_state.tts_event),
468598944Sobrien		      p->pid, p->tid);
468698944Sobrien	    }
468798944Sobrien	}
468898944Sobrien
468998944Sobrien      add_thread (pid_to_ptid (pid));		/* in thread.c */
469046283Sdfr    }
469198944Sobrien
469246283Sdfr#ifdef PARANOIA
469398944Sobrien  if (debug_on)
469498944Sobrien    print_tthreads ();
469546283Sdfr#endif
469646283Sdfr
469746283Sdfr  /* One mustn't call ttrace_wait() after attaching via ttrace,
469846283Sdfr     'cause the process is stopped already.
469998944Sobrien
470046283Sdfr     However, the upper layers of gdb's execution control will
470146283Sdfr     want to wait after attaching (but not after forks, in
470246283Sdfr     which case they will be doing a "target_resume", anticipating
470346283Sdfr     a later TTEVT_EXEC or TTEVT_FORK event).
470446283Sdfr
470546283Sdfr     To make this attach() implementation more compatible with
470646283Sdfr     others, we'll make the attached-to process raise a SIGTRAP.
470746283Sdfr
470846283Sdfr     Issue: this continues only one thread.  That could be
470946283Sdfr     dangerous if the thread is blocked--the process won't run
471046283Sdfr     and no trap will be raised.  FIX! (check state.tts_flags?
471146283Sdfr     need one that's either TTS_WASRUNNING--but we've stopped
471246283Sdfr     it and made it TTS_WASSUSPENDED.  Hum...FIXME!)
471346283Sdfr   */
471498944Sobrien  if (DO_ATTACH_CONTINUE == kind_of_go)
471598944Sobrien    {
471698944Sobrien      tt_status = call_real_ttrace (
471798944Sobrien				     TT_LWP_CONTINUE,
471898944Sobrien				     pid,
471998944Sobrien				     a_thread,
472098944Sobrien				     TT_USE_CURRENT_PC,
472198944Sobrien	       (TTRACE_ARG_TYPE) target_signal_to_host (TARGET_SIGNAL_TRAP),
472298944Sobrien				     TT_NIL);
472346283Sdfr      if (errno)
472498944Sobrien	perror_with_name ("ttrace");
472546283Sdfr
472698944Sobrien      clear_handled (a_thread);	/* So TRAP will be reported. */
472746283Sdfr
472846283Sdfr      /* Now running.
472946283Sdfr       */
473046283Sdfr      process_state = RUNNING;
473198944Sobrien    }
473246283Sdfr
473346283Sdfr  attach_flag = 1;
473446283Sdfr}
473546283Sdfr#endif /* ATTACH_DETACH */
473698944Sobrien
473746283Sdfr
473846283Sdfr#ifdef ATTACH_DETACH
473946283Sdfr/* Start debugging the process whose number is PID.
474046283Sdfr * (A _real_ pid).
474146283Sdfr */
474246283Sdfrint
474398944Sobrienattach (int pid)
474446283Sdfr{
474598944Sobrien  int tt_status;
474698944Sobrien
474746283Sdfr  tt_status = call_real_ttrace (
474898944Sobrien				 TT_PROC_ATTACH,
474998944Sobrien				 pid,
475098944Sobrien				 (lwpid_t) TT_NIL,
475198944Sobrien				 TT_NIL,
475298944Sobrien				 (TTRACE_ARG_TYPE) TT_VERSION,
475398944Sobrien				 TT_NIL);
475446283Sdfr  if (errno)
475546283Sdfr    perror_with_name ("ttrace attach");
475646283Sdfr
475746283Sdfr  /* If successful, the process is now stopped.
475846283Sdfr   */
475946283Sdfr  process_state = STOPPED;
476046283Sdfr
476146283Sdfr  /* Our caller ("attach_command" in "infcmd.c")
476246283Sdfr   * expects to do a "wait_for_inferior" after
476346283Sdfr   * the attach, so make sure the inferior is
476446283Sdfr   * running when we're done.
476546283Sdfr   */
476698944Sobrien  update_thread_state_after_attach (pid, DO_ATTACH_CONTINUE);
476746283Sdfr
476846283Sdfr  return pid;
476946283Sdfr}
477046283Sdfr
477146283Sdfr
477246283Sdfr#if defined(CHILD_POST_ATTACH)
477346283Sdfrvoid
477498944Sobrienchild_post_attach (int pid)
477546283Sdfr{
477646283Sdfr#ifdef THREAD_DEBUG
477798944Sobrien  if (debug_on)
477898944Sobrien    printf ("child-post-attach call\n");
477946283Sdfr#endif
478046283Sdfr
478146283Sdfr  require_notification_of_events (pid);
478246283Sdfr}
478346283Sdfr#endif
478446283Sdfr
478546283Sdfr
478646283Sdfr/* Stop debugging the process whose number is PID
478746283Sdfr   and continue it with signal number SIGNAL.
478846283Sdfr   SIGNAL = 0 means just continue it.
478946283Sdfr */
479046283Sdfrvoid
479198944Sobriendetach (int signal)
479246283Sdfr{
479346283Sdfr  errno = 0;
479446283Sdfr  call_ttrace (TT_PROC_DETACH,
479598944Sobrien	       PIDGET (inferior_ptid),
479698944Sobrien	       TT_NIL,
479798944Sobrien	       (TTRACE_ARG_TYPE) signal,
479898944Sobrien	       TT_NIL);
479946283Sdfr  attach_flag = 0;
480046283Sdfr
480198944Sobrien  clear_thread_info ();
480246283Sdfr
480346283Sdfr  /* Process-state? */
480446283Sdfr}
480546283Sdfr#endif /* ATTACH_DETACH */
480698944Sobrien
480746283Sdfr
480846283Sdfr/* Default the type of the ttrace transfer to int.  */
480946283Sdfr#ifndef TTRACE_XFER_TYPE
481046283Sdfr#define TTRACE_XFER_TYPE int
481146283Sdfr#endif
481246283Sdfr
481346283Sdfrvoid
481498944Sobrien_initialize_kernel_u_addr (void)
481546283Sdfr{
481646283Sdfr}
481746283Sdfr
481846283Sdfr#if !defined (CHILD_XFER_MEMORY)
481946283Sdfr/* NOTE! I tried using TTRACE_READDATA, etc., to read and write memory
482046283Sdfr   in the NEW_SUN_TTRACE case.
482146283Sdfr   It ought to be straightforward.  But it appears that writing did
482246283Sdfr   not write the data that I specified.  I cannot understand where
482346283Sdfr   it got the data that it actually did write.  */
482446283Sdfr
482546283Sdfr/* Copy LEN bytes to or from inferior's memory starting at MEMADDR
482646283Sdfr   to debugger memory starting at MYADDR.   Copy to inferior if
482798944Sobrien   WRITE is nonzero.  TARGET is ignored.
482898944Sobrien
482946283Sdfr   Returns the length copied, which is either the LEN argument or zero.
483046283Sdfr   This xfer function does not do partial moves, since child_ops
483146283Sdfr   doesn't allow memory operations to cross below us in the target stack
483246283Sdfr   anyway.  */
483346283Sdfr
483446283Sdfrint
483598944Sobrienchild_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
483698944Sobrien		   struct mem_attrib *attrib,
483798944Sobrien		   struct target_ops *target)
483846283Sdfr{
4839130803Smarcel  int i;
484046283Sdfr  /* Round starting address down to longword boundary.  */
4841130803Smarcel  CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (TTRACE_XFER_TYPE);
484246283Sdfr  /* Round ending address up; get number of longwords that makes.  */
4843130803Smarcel  int count
484498944Sobrien  = (((memaddr + len) - addr) + sizeof (TTRACE_XFER_TYPE) - 1)
484598944Sobrien  / sizeof (TTRACE_XFER_TYPE);
484646283Sdfr  /* Allocate buffer of that many longwords.  */
484798944Sobrien  /* FIXME (alloca): This code, cloned from infptrace.c, is unsafe
484898944Sobrien     because it uses alloca to allocate a buffer of arbitrary size.
484998944Sobrien     For very large xfers, this could crash GDB's stack.  */
4850130803Smarcel  TTRACE_XFER_TYPE *buffer
485146283Sdfr    = (TTRACE_XFER_TYPE *) alloca (count * sizeof (TTRACE_XFER_TYPE));
485246283Sdfr
485346283Sdfr  if (write)
485446283Sdfr    {
485546283Sdfr      /* Fill start and end extra bytes of buffer with existing memory data.  */
485646283Sdfr
485798944Sobrien      if (addr != memaddr || len < (int) sizeof (TTRACE_XFER_TYPE))
485898944Sobrien	{
485998944Sobrien	  /* Need part of initial word -- fetch it.  */
486098944Sobrien	  buffer[0] = call_ttrace (TT_LWP_RDTEXT,
486198944Sobrien				   PIDGET (inferior_ptid),
486298944Sobrien				   (TTRACE_ARG_TYPE) addr,
486398944Sobrien				   TT_NIL,
486498944Sobrien				   TT_NIL);
486598944Sobrien	}
486646283Sdfr
486746283Sdfr      if (count > 1)		/* FIXME, avoid if even boundary */
486846283Sdfr	{
486946283Sdfr	  buffer[count - 1] = call_ttrace (TT_LWP_RDTEXT,
487098944Sobrien					   PIDGET (inferior_ptid),
487198944Sobrien					   ((TTRACE_ARG_TYPE)
487298944Sobrien			  (addr + (count - 1) * sizeof (TTRACE_XFER_TYPE))),
487398944Sobrien					   TT_NIL,
487498944Sobrien					   TT_NIL);
487546283Sdfr	}
487646283Sdfr
487746283Sdfr      /* Copy data to be written over corresponding part of buffer */
487846283Sdfr
487946283Sdfr      memcpy ((char *) buffer + (memaddr & (sizeof (TTRACE_XFER_TYPE) - 1)),
488046283Sdfr	      myaddr,
488146283Sdfr	      len);
488246283Sdfr
488346283Sdfr      /* Write the entire buffer.  */
488446283Sdfr
488546283Sdfr      for (i = 0; i < count; i++, addr += sizeof (TTRACE_XFER_TYPE))
488646283Sdfr	{
488746283Sdfr	  errno = 0;
488846283Sdfr	  call_ttrace (TT_LWP_WRDATA,
488998944Sobrien		       PIDGET (inferior_ptid),
489098944Sobrien		       (TTRACE_ARG_TYPE) addr,
489198944Sobrien		       (TTRACE_ARG_TYPE) buffer[i],
489298944Sobrien		       TT_NIL);
489346283Sdfr	  if (errno)
489446283Sdfr	    {
489546283Sdfr	      /* Using the appropriate one (I or D) is necessary for
489698944Sobrien	         Gould NP1, at least.  */
489746283Sdfr	      errno = 0;
489846283Sdfr	      call_ttrace (TT_LWP_WRTEXT,
489998944Sobrien			   PIDGET (inferior_ptid),
490098944Sobrien			   (TTRACE_ARG_TYPE) addr,
490198944Sobrien			   (TTRACE_ARG_TYPE) buffer[i],
490298944Sobrien			   TT_NIL);
490346283Sdfr	    }
490446283Sdfr	  if (errno)
490546283Sdfr	    return 0;
490646283Sdfr	}
490746283Sdfr    }
490846283Sdfr  else
490946283Sdfr    {
491046283Sdfr      /* Read all the longwords */
491146283Sdfr      for (i = 0; i < count; i++, addr += sizeof (TTRACE_XFER_TYPE))
491246283Sdfr	{
491346283Sdfr	  errno = 0;
491446283Sdfr	  buffer[i] = call_ttrace (TT_LWP_RDTEXT,
491598944Sobrien				   PIDGET (inferior_ptid),
491698944Sobrien				   (TTRACE_ARG_TYPE) addr,
491798944Sobrien				   TT_NIL,
491898944Sobrien				   TT_NIL);
491946283Sdfr	  if (errno)
492046283Sdfr	    return 0;
492146283Sdfr	  QUIT;
492246283Sdfr	}
492346283Sdfr
492446283Sdfr      /* Copy appropriate bytes out of the buffer.  */
492546283Sdfr      memcpy (myaddr,
492646283Sdfr	      (char *) buffer + (memaddr & (sizeof (TTRACE_XFER_TYPE) - 1)),
492746283Sdfr	      len);
492846283Sdfr    }
492946283Sdfr  return len;
493046283Sdfr}
493198944Sobrien
493246283Sdfr
493346283Sdfrstatic void
493498944Sobrienudot_info (void)
493546283Sdfr{
493698944Sobrien  int udot_off;			/* Offset into user struct */
493798944Sobrien  int udot_val;			/* Value from user struct at udot_off */
493898944Sobrien  char mess[128];		/* For messages */
493946283Sdfr
494098944Sobrien  if (!target_has_execution)
494198944Sobrien    {
494298944Sobrien      error ("The program is not being run.");
494398944Sobrien    }
494446283Sdfr
494546283Sdfr#if !defined (KERNEL_U_SIZE)
494646283Sdfr
494746283Sdfr  /* Adding support for this command is easy.  Typically you just add a
494846283Sdfr     routine, called "kernel_u_size" that returns the size of the user
494946283Sdfr     struct, to the appropriate *-nat.c file and then add to the native
495046283Sdfr     config file "#define KERNEL_U_SIZE kernel_u_size()" */
495146283Sdfr  error ("Don't know how large ``struct user'' is in this version of gdb.");
495246283Sdfr
495346283Sdfr#else
495446283Sdfr
495546283Sdfr  for (udot_off = 0; udot_off < KERNEL_U_SIZE; udot_off += sizeof (udot_val))
495646283Sdfr    {
495746283Sdfr      if ((udot_off % 24) == 0)
495846283Sdfr	{
495946283Sdfr	  if (udot_off > 0)
496046283Sdfr	    {
496146283Sdfr	      printf_filtered ("\n");
496246283Sdfr	    }
496346283Sdfr	  printf_filtered ("%04x:", udot_off);
496446283Sdfr	}
496546283Sdfr      udot_val = call_ttrace (TT_LWP_RUREGS,
496698944Sobrien			      PIDGET (inferior_ptid),
496798944Sobrien			      (TTRACE_ARG_TYPE) udot_off,
496898944Sobrien			      TT_NIL,
496998944Sobrien			      TT_NIL);
497046283Sdfr      if (errno != 0)
497146283Sdfr	{
497246283Sdfr	  sprintf (mess, "\nreading user struct at offset 0x%x", udot_off);
497346283Sdfr	  perror_with_name (mess);
497446283Sdfr	}
497546283Sdfr      /* Avoid using nonportable (?) "*" in print specs */
497646283Sdfr      printf_filtered (sizeof (int) == 4 ? " 0x%08x" : " 0x%16x", udot_val);
497746283Sdfr    }
497846283Sdfr  printf_filtered ("\n");
497946283Sdfr
498046283Sdfr#endif
498146283Sdfr}
498246283Sdfr#endif /* !defined (CHILD_XFER_MEMORY).  */
498346283Sdfr
498498944Sobrien
498546283Sdfr/* TTrace version of "target_pid_to_exec_file"
498646283Sdfr */
498746283Sdfrchar *
498898944Sobrienchild_pid_to_exec_file (int tid)
498946283Sdfr{
499098944Sobrien  int tt_status;
499198944Sobrien  static char exec_file_buffer[1024];
499298944Sobrien  pid_t pid;
499398944Sobrien  static struct pst_status buf;
499498944Sobrien
499598944Sobrien  /* On various versions of hpux11, this may fail due to a supposed
499698944Sobrien     kernel bug.  We have alternate methods to get this information
499798944Sobrien     (ie pstat).  */
499846283Sdfr  tt_status = call_ttrace (TT_PROC_GET_PATHNAME,
499998944Sobrien			   tid,
500098944Sobrien			   (uint64_t) exec_file_buffer,
500198944Sobrien			   sizeof (exec_file_buffer) - 1,
500298944Sobrien			   0);
500346283Sdfr  if (tt_status >= 0)
500446283Sdfr    return exec_file_buffer;
500546283Sdfr
500698944Sobrien  /* Try to get process information via pstat and extract the filename
500798944Sobrien     from the pst_cmd field within the pst_status structure.  */
500898944Sobrien  if (pstat_getproc (&buf, sizeof (struct pst_status), 0, tid) != -1)
500998944Sobrien    {
501098944Sobrien      char *p = buf.pst_cmd;
501146283Sdfr
501298944Sobrien      while (*p && *p != ' ')
501398944Sobrien	p++;
501498944Sobrien      *p = 0;
501546283Sdfr
501698944Sobrien      return (buf.pst_cmd);
501746283Sdfr    }
501846283Sdfr
501998944Sobrien  return (NULL);
502046283Sdfr}
502146283Sdfr
502246283Sdfrvoid
502398944Sobrienpre_fork_inferior (void)
502446283Sdfr{
502598944Sobrien  int status;
502646283Sdfr
502746283Sdfr  status = pipe (startup_semaphore.parent_channel);
502898944Sobrien  if (status < 0)
502998944Sobrien    {
503046283Sdfr      warning ("error getting parent pipe for startup semaphore");
503146283Sdfr      return;
503298944Sobrien    }
503346283Sdfr
503446283Sdfr  status = pipe (startup_semaphore.child_channel);
503598944Sobrien  if (status < 0)
503698944Sobrien    {
503746283Sdfr      warning ("error getting child pipe for startup semaphore");
503846283Sdfr      return;
503998944Sobrien    }
504046283Sdfr}
504146283Sdfr
5042130803Smarcel/* Called from child_follow_fork in hppah-nat.c.
504346283Sdfr *
504446283Sdfr * This seems to be intended to attach after a fork or
504546283Sdfr * vfork, while "attach" is used to attach to a pid
504646283Sdfr * given by the user.  The check for an existing attach
504746283Sdfr * seems odd--it always fails in our test system.
504846283Sdfr */
504946283Sdfrint
505098944Sobrienhppa_require_attach (int pid)
505146283Sdfr{
505298944Sobrien  int tt_status;
505398944Sobrien  CORE_ADDR pc;
505498944Sobrien  CORE_ADDR pc_addr;
505598944Sobrien  unsigned int regs_offset;
505646283Sdfr  process_state_t old_process_state = process_state;
505798944Sobrien
505846283Sdfr  /* Are we already attached?  There appears to be no explicit
505946283Sdfr   * way to answer this via ttrace, so we try something which
506046283Sdfr   * should be innocuous if we are attached.  If that fails,
506146283Sdfr   * then we assume we're not attached, and so attempt to make
506246283Sdfr   * it so.
506346283Sdfr   */
506446283Sdfr  errno = 0;
506546283Sdfr  tt_status = call_real_ttrace (TT_PROC_STOP,
506698944Sobrien				pid,
506798944Sobrien				(lwpid_t) TT_NIL,
506898944Sobrien				(TTRACE_ARG_TYPE) TT_NIL,
506998944Sobrien				(TTRACE_ARG_TYPE) TT_NIL,
507098944Sobrien				TT_NIL);
507198944Sobrien
507246283Sdfr  if (errno)
507346283Sdfr    {
507446283Sdfr      /* No change to process-state!
507546283Sdfr       */
507646283Sdfr      errno = 0;
507798944Sobrien      pid = attach (pid);
507846283Sdfr    }
507946283Sdfr  else
508046283Sdfr    {
508198944Sobrien      /* If successful, the process is now stopped.  But if
508298944Sobrien       * we're VFORKING, the parent is still running, so don't
508398944Sobrien       * change the process state.
508498944Sobrien       */
508598944Sobrien      if (process_state != VFORKING)
508698944Sobrien	process_state = STOPPED;
508746283Sdfr
508898944Sobrien      /* If we were already attached, you'd think that we
508998944Sobrien       * would need to start going again--but you'd be wrong,
509098944Sobrien       * as the fork-following code is actually in the middle
509198944Sobrien       * of the "resume" routine in in "infrun.c" and so
509298944Sobrien       * will (almost) immediately do a resume.
509398944Sobrien       *
509498944Sobrien       * On the other hand, if we are VFORKING, which means
509598944Sobrien       * that the child and the parent share a process for a
509698944Sobrien       * while, we know that "resume" won't be resuming
509798944Sobrien       * until the child EXEC event is seen.  But we still
509898944Sobrien       * don't want to continue, as the event is already
509998944Sobrien       * there waiting.
510098944Sobrien       */
510198944Sobrien      update_thread_state_after_attach (pid, DONT_ATTACH_CONTINUE);
510298944Sobrien    }				/* STOP succeeded */
510398944Sobrien
510446283Sdfr  return pid;
510546283Sdfr}
510646283Sdfr
510746283Sdfrint
510898944Sobrienhppa_require_detach (int pid, int signal)
510946283Sdfr{
511098944Sobrien  int tt_status;
511146283Sdfr
511246283Sdfr  /* If signal is non-zero, we must pass the signal on to the active
511346283Sdfr     thread prior to detaching.  We do this by continuing the threads
511446283Sdfr     with the signal.
511546283Sdfr   */
511646283Sdfr  if (signal != 0)
511746283Sdfr    {
511846283Sdfr      errno = 0;
511998944Sobrien      threads_continue_all_with_signals (pid, signal);
512046283Sdfr    }
512146283Sdfr
512246283Sdfr  errno = 0;
512346283Sdfr  tt_status = call_ttrace (TT_PROC_DETACH,
512498944Sobrien			   pid,
512598944Sobrien			   TT_NIL,
512698944Sobrien			   TT_NIL,
512798944Sobrien			   TT_NIL);
512846283Sdfr
512998944Sobrien  errno = 0;			/* Ignore any errors. */
513046283Sdfr
513146283Sdfr  /* process_state? */
513298944Sobrien
513346283Sdfr  return pid;
513446283Sdfr}
513546283Sdfr
513646283Sdfr/* Given the starting address of a memory page, hash it to a bucket in
513746283Sdfr   the memory page dictionary.
513898944Sobrien */
513946283Sdfrstatic int
514098944Sobrienget_dictionary_bucket_of_page (CORE_ADDR page_start)
514146283Sdfr{
514298944Sobrien  int hash;
514346283Sdfr
514446283Sdfr  hash = (page_start / memory_page_dictionary.page_size);
514546283Sdfr  hash = hash % MEMORY_PAGE_DICTIONARY_BUCKET_COUNT;
514646283Sdfr
514746283Sdfr  return hash;
514846283Sdfr}
514946283Sdfr
515046283Sdfr
515146283Sdfr/* Given a memory page's starting address, get (i.e., find an existing
515246283Sdfr   or create a new) dictionary entry for the page.  The page will be
515346283Sdfr   write-protected when this function returns, but may have a reference
515446283Sdfr   count of 0 (if the page was newly-added to the dictionary).
515598944Sobrien */
515646283Sdfrstatic memory_page_t *
515798944Sobrienget_dictionary_entry_of_page (int pid, CORE_ADDR page_start)
515846283Sdfr{
515998944Sobrien  int bucket;
516098944Sobrien  memory_page_t *page = NULL;
516198944Sobrien  memory_page_t *previous_page = NULL;
516246283Sdfr
516346283Sdfr  /* We're going to be using the dictionary now, than-kew. */
516498944Sobrien  require_memory_page_dictionary ();
516546283Sdfr
516646283Sdfr  /* Try to find an existing dictionary entry for this page.  Hash
516746283Sdfr     on the page's starting address.
516898944Sobrien   */
516946283Sdfr  bucket = get_dictionary_bucket_of_page (page_start);
517046283Sdfr  page = &memory_page_dictionary.buckets[bucket];
517146283Sdfr  while (page != NULL)
517246283Sdfr    {
517346283Sdfr      if (page->page_start == page_start)
517498944Sobrien	break;
517546283Sdfr      previous_page = page;
517646283Sdfr      page = page->next;
517746283Sdfr    }
517846283Sdfr
517946283Sdfr  /* Did we find a dictionary entry for this page?  If not, then
518046283Sdfr     add it to the dictionary now.
518198944Sobrien   */
518246283Sdfr  if (page == NULL)
518346283Sdfr    {
518446283Sdfr      /* Create a new entry. */
518546283Sdfr      page = (memory_page_t *) xmalloc (sizeof (memory_page_t));
518646283Sdfr      page->page_start = page_start;
518746283Sdfr      page->reference_count = 0;
518846283Sdfr      page->next = NULL;
518946283Sdfr      page->previous = NULL;
519046283Sdfr
519146283Sdfr      /* We'll write-protect the page now, if that's allowed. */
519246283Sdfr      page->original_permissions = write_protect_page (pid, page_start);
519346283Sdfr
519446283Sdfr      /* Add the new entry to the dictionary. */
519546283Sdfr      page->previous = previous_page;
519646283Sdfr      previous_page->next = page;
519746283Sdfr
519846283Sdfr      memory_page_dictionary.page_count++;
519946283Sdfr    }
520046283Sdfr
520146283Sdfr  return page;
520246283Sdfr}
520346283Sdfr
520446283Sdfr
520546283Sdfrstatic void
520698944Sobrienremove_dictionary_entry_of_page (int pid, memory_page_t *page)
520746283Sdfr{
520846283Sdfr  /* Restore the page's original permissions. */
520946283Sdfr  unwrite_protect_page (pid, page->page_start, page->original_permissions);
521046283Sdfr
521146283Sdfr  /* Kick the page out of the dictionary. */
521246283Sdfr  if (page->previous != NULL)
521346283Sdfr    page->previous->next = page->next;
521446283Sdfr  if (page->next != NULL)
521546283Sdfr    page->next->previous = page->previous;
521646283Sdfr
521746283Sdfr  /* Just in case someone retains a handle to this after it's freed. */
521846283Sdfr  page->page_start = (CORE_ADDR) 0;
521946283Sdfr
522046283Sdfr  memory_page_dictionary.page_count--;
522146283Sdfr
522298944Sobrien  xfree (page);
522346283Sdfr}
522446283Sdfr
522546283Sdfr
522646283Sdfrstatic void
522798944Sobrienhppa_enable_syscall_events (int pid)
522846283Sdfr{
522998944Sobrien  int tt_status;
523098944Sobrien  ttevent_t ttrace_events;
523146283Sdfr
523246283Sdfr  /* Get the set of events that are currently enabled. */
523346283Sdfr  tt_status = call_ttrace (TT_PROC_GET_EVENT_MASK,
523498944Sobrien			   pid,
523598944Sobrien			   (TTRACE_ARG_TYPE) & ttrace_events,
523698944Sobrien			   (TTRACE_ARG_TYPE) sizeof (ttrace_events),
523798944Sobrien			   TT_NIL);
523846283Sdfr  if (errno)
523946283Sdfr    perror_with_name ("ttrace");
524046283Sdfr
524146283Sdfr  /* Add syscall events to that set. */
524246283Sdfr  ttrace_events.tte_events |= TTEVT_SYSCALL_ENTRY;
524346283Sdfr  ttrace_events.tte_events |= TTEVT_SYSCALL_RETURN;
524446283Sdfr
524546283Sdfr  tt_status = call_ttrace (TT_PROC_SET_EVENT_MASK,
524698944Sobrien			   pid,
524798944Sobrien			   (TTRACE_ARG_TYPE) & ttrace_events,
524898944Sobrien			   (TTRACE_ARG_TYPE) sizeof (ttrace_events),
524998944Sobrien			   TT_NIL);
525046283Sdfr  if (errno)
525146283Sdfr    perror_with_name ("ttrace");
525246283Sdfr}
525346283Sdfr
525446283Sdfr
525546283Sdfrstatic void
525698944Sobrienhppa_disable_syscall_events (int pid)
525746283Sdfr{
525898944Sobrien  int tt_status;
525998944Sobrien  ttevent_t ttrace_events;
526046283Sdfr
526146283Sdfr  /* Get the set of events that are currently enabled. */
526246283Sdfr  tt_status = call_ttrace (TT_PROC_GET_EVENT_MASK,
526398944Sobrien			   pid,
526498944Sobrien			   (TTRACE_ARG_TYPE) & ttrace_events,
526598944Sobrien			   (TTRACE_ARG_TYPE) sizeof (ttrace_events),
526698944Sobrien			   TT_NIL);
526746283Sdfr  if (errno)
526846283Sdfr    perror_with_name ("ttrace");
526946283Sdfr
527046283Sdfr  /* Remove syscall events from that set. */
527146283Sdfr  ttrace_events.tte_events &= ~TTEVT_SYSCALL_ENTRY;
527246283Sdfr  ttrace_events.tte_events &= ~TTEVT_SYSCALL_RETURN;
527346283Sdfr
527446283Sdfr  tt_status = call_ttrace (TT_PROC_SET_EVENT_MASK,
527598944Sobrien			   pid,
527698944Sobrien			   (TTRACE_ARG_TYPE) & ttrace_events,
527798944Sobrien			   (TTRACE_ARG_TYPE) sizeof (ttrace_events),
527898944Sobrien			   TT_NIL);
527946283Sdfr  if (errno)
528046283Sdfr    perror_with_name ("ttrace");
528146283Sdfr}
528246283Sdfr
528346283Sdfr
528446283Sdfr/* The address range beginning with START and ending with START+LEN-1
528546283Sdfr   (inclusive) is to be watched via page-protection by a new watchpoint.
528646283Sdfr   Set protection for all pages that overlap that range.
528746283Sdfr
528846283Sdfr   Note that our caller sets TYPE to:
528998944Sobrien   0 for a bp_hardware_watchpoint,
529098944Sobrien   1 for a bp_read_watchpoint,
529198944Sobrien   2 for a bp_access_watchpoint
529246283Sdfr
529346283Sdfr   (Yes, this is intentionally (though lord only knows why) different
529446283Sdfr   from the TYPE that is passed to hppa_remove_hw_watchpoint.)
529598944Sobrien */
529646283Sdfrint
529798944Sobrienhppa_insert_hw_watchpoint (int pid, CORE_ADDR start, LONGEST len, int type)
529846283Sdfr{
529998944Sobrien  CORE_ADDR page_start;
530098944Sobrien  int dictionary_was_empty;
530198944Sobrien  int page_size;
530298944Sobrien  int page_id;
530398944Sobrien  LONGEST range_size_in_pages;
530446283Sdfr
530546283Sdfr  if (type != 0)
530646283Sdfr    error ("read or access hardware watchpoints not supported on HP-UX");
530746283Sdfr
530846283Sdfr  /* Examine all pages in the address range. */
530946283Sdfr  require_memory_page_dictionary ();
531046283Sdfr
531146283Sdfr  dictionary_was_empty = (memory_page_dictionary.page_count == (LONGEST) 0);
531246283Sdfr
531346283Sdfr  page_size = memory_page_dictionary.page_size;
531446283Sdfr  page_start = (start / page_size) * page_size;
531546283Sdfr  range_size_in_pages = ((LONGEST) len + (LONGEST) page_size - 1) / (LONGEST) page_size;
531646283Sdfr
531798944Sobrien  for (page_id = 0; page_id < range_size_in_pages; page_id++, page_start += page_size)
531846283Sdfr    {
531998944Sobrien      memory_page_t *page;
532046283Sdfr
532146283Sdfr      /* This gets the page entered into the dictionary if it was
532246283Sdfr         not already entered.
532398944Sobrien       */
532446283Sdfr      page = get_dictionary_entry_of_page (pid, page_start);
532546283Sdfr      page->reference_count++;
532646283Sdfr    }
532746283Sdfr
532846283Sdfr  /* Our implementation depends on seeing calls to kernel code, for the
532946283Sdfr     following reason.  Here we ask to be notified of syscalls.
533046283Sdfr
533146283Sdfr     When a protected page is accessed by user code, HP-UX raises a SIGBUS.
533246283Sdfr     Fine.
533346283Sdfr
533446283Sdfr     But when kernel code accesses the page, it doesn't give a SIGBUS.
533546283Sdfr     Rather, the system call that touched the page fails, with errno=EFAULT.
533646283Sdfr     Not good for us.
533746283Sdfr
533846283Sdfr     We could accomodate this "feature" by asking to be notified of syscall
533946283Sdfr     entries & exits; upon getting an entry event, disabling page-protections;
534046283Sdfr     upon getting an exit event, reenabling page-protections and then checking
534146283Sdfr     if any watchpoints triggered.
534246283Sdfr
534346283Sdfr     However, this turns out to be a real performance loser.  syscalls are
534446283Sdfr     usually a frequent occurrence.  Having to unprotect-reprotect all watched
534546283Sdfr     pages, and also to then read all watched memory locations and compare for
534646283Sdfr     triggers, can be quite expensive.
534746283Sdfr
534846283Sdfr     Instead, we'll only ask to be notified of syscall exits.  When we get
534946283Sdfr     one, we'll check whether errno is set.  If not, or if it's not EFAULT,
535046283Sdfr     we can just continue the inferior.
535146283Sdfr
535246283Sdfr     If errno is set upon syscall exit to EFAULT, we must perform some fairly
535346283Sdfr     hackish stuff to determine whether the failure really was due to a
535446283Sdfr     page-protect trap on a watched location.
535598944Sobrien   */
535646283Sdfr  if (dictionary_was_empty)
535746283Sdfr    hppa_enable_syscall_events (pid);
535846283Sdfr
535946283Sdfr  return 1;
536046283Sdfr}
536146283Sdfr
536246283Sdfr
536346283Sdfr/* The address range beginning with START and ending with START+LEN-1
536446283Sdfr   (inclusive) was being watched via page-protection by a watchpoint
536546283Sdfr   which has been removed.  Remove protection for all pages that
536646283Sdfr   overlap that range, which are not also being watched by other
536746283Sdfr   watchpoints.
536898944Sobrien */
536946283Sdfrint
5370130803Smarcelhppa_remove_hw_watchpoint (int pid, CORE_ADDR start, LONGEST len, int type)
537146283Sdfr{
537298944Sobrien  CORE_ADDR page_start;
537398944Sobrien  int dictionary_is_empty;
537498944Sobrien  int page_size;
537598944Sobrien  int page_id;
537698944Sobrien  LONGEST range_size_in_pages;
537746283Sdfr
537846283Sdfr  if (type != 0)
537946283Sdfr    error ("read or access hardware watchpoints not supported on HP-UX");
538046283Sdfr
538146283Sdfr  /* Examine all pages in the address range. */
538246283Sdfr  require_memory_page_dictionary ();
538346283Sdfr
538446283Sdfr  page_size = memory_page_dictionary.page_size;
538546283Sdfr  page_start = (start / page_size) * page_size;
538646283Sdfr  range_size_in_pages = ((LONGEST) len + (LONGEST) page_size - 1) / (LONGEST) page_size;
538746283Sdfr
538898944Sobrien  for (page_id = 0; page_id < range_size_in_pages; page_id++, page_start += page_size)
538946283Sdfr    {
539098944Sobrien      memory_page_t *page;
539146283Sdfr
539246283Sdfr      page = get_dictionary_entry_of_page (pid, page_start);
539346283Sdfr      page->reference_count--;
539446283Sdfr
539546283Sdfr      /* Was this the last reference of this page?  If so, then we
539646283Sdfr         must scrub the entry from the dictionary, and also restore
539746283Sdfr         the page's original permissions.
539898944Sobrien       */
539946283Sdfr      if (page->reference_count == 0)
540098944Sobrien	remove_dictionary_entry_of_page (pid, page);
540146283Sdfr    }
540246283Sdfr
540346283Sdfr  dictionary_is_empty = (memory_page_dictionary.page_count == (LONGEST) 0);
540446283Sdfr
540546283Sdfr  /* If write protections are currently disallowed, then that implies that
540646283Sdfr     wait_for_inferior believes that the inferior is within a system call.
540746283Sdfr     Since we want to see both syscall entry and return, it's clearly not
540846283Sdfr     good to disable syscall events in this state!
540946283Sdfr
541046283Sdfr     ??rehrauer: Yeah, it'd be better if we had a specific flag that said,
541146283Sdfr     "inferior is between syscall events now".  Oh well.
541298944Sobrien   */
541346283Sdfr  if (dictionary_is_empty && memory_page_dictionary.page_protections_allowed)
541446283Sdfr    hppa_disable_syscall_events (pid);
541546283Sdfr
541646283Sdfr  return 1;
541746283Sdfr}
541846283Sdfr
541946283Sdfr
542046283Sdfr/* Could we implement a watchpoint of this type via our available
542146283Sdfr   hardware support?
542246283Sdfr
542346283Sdfr   This query does not consider whether a particular address range
542446283Sdfr   could be so watched, but just whether support is generally available
542546283Sdfr   for such things.  See hppa_range_profitable_for_hw_watchpoint for a
542646283Sdfr   query that answers whether a particular range should be watched via
542746283Sdfr   hardware support.
542898944Sobrien */
542946283Sdfrint
5430130803Smarcelhppa_can_use_hw_watchpoint (int type, int cnt, int ot)
543146283Sdfr{
543246283Sdfr  return (type == bp_hardware_watchpoint);
543346283Sdfr}
543446283Sdfr
543546283Sdfr
543646283Sdfr/* Assuming we could set a hardware watchpoint on this address, do
543746283Sdfr   we think it would be profitable ("a good idea") to do so?  If not,
543846283Sdfr   we can always set a regular (aka single-step & test) watchpoint
543946283Sdfr   on the address...
544098944Sobrien */
544146283Sdfrint
544298944Sobrienhppa_range_profitable_for_hw_watchpoint (int pid, CORE_ADDR start, LONGEST len)
544346283Sdfr{
544498944Sobrien  int range_is_stack_based;
544598944Sobrien  int range_is_accessible;
544698944Sobrien  CORE_ADDR page_start;
544798944Sobrien  int page_size;
544898944Sobrien  int page;
544998944Sobrien  LONGEST range_size_in_pages;
545046283Sdfr
545146283Sdfr  /* ??rehrauer: For now, say that all addresses are potentially
545246283Sdfr     profitable.  Possibly later we'll want to test the address
545346283Sdfr     for "stackness"?
545498944Sobrien   */
545546283Sdfr  range_is_stack_based = 0;
545646283Sdfr
545746283Sdfr  /* If any page in the range is inaccessible, then we cannot
545846283Sdfr     really use hardware watchpointing, even though our client
545946283Sdfr     thinks we can.  In that case, it's actually an error to
546046283Sdfr     attempt to use hw watchpoints, so we'll tell our client
546146283Sdfr     that the range is "unprofitable", and hope that they listen...
546298944Sobrien   */
546398944Sobrien  range_is_accessible = 1;	/* Until proven otherwise. */
546446283Sdfr
546546283Sdfr  /* Examine all pages in the address range. */
546646283Sdfr  errno = 0;
546746283Sdfr  page_size = sysconf (_SC_PAGE_SIZE);
546846283Sdfr
546946283Sdfr  /* If we can't determine page size, we're hosed.  Tell our
547046283Sdfr     client it's unprofitable to use hw watchpoints for this
547146283Sdfr     range.
547298944Sobrien   */
547346283Sdfr  if (errno || (page_size <= 0))
547446283Sdfr    {
547546283Sdfr      errno = 0;
547646283Sdfr      return 0;
547746283Sdfr    }
547846283Sdfr
547946283Sdfr  page_start = (start / page_size) * page_size;
548098944Sobrien  range_size_in_pages = len / (LONGEST) page_size;
548146283Sdfr
548298944Sobrien  for (page = 0; page < range_size_in_pages; page++, page_start += page_size)
548346283Sdfr    {
548498944Sobrien      int tt_status;
548598944Sobrien      int page_permissions;
548646283Sdfr
548746283Sdfr      /* Is this page accessible? */
548846283Sdfr      errno = 0;
548946283Sdfr      tt_status = call_ttrace (TT_PROC_GET_MPROTECT,
549098944Sobrien			       pid,
549198944Sobrien			       (TTRACE_ARG_TYPE) page_start,
549298944Sobrien			       TT_NIL,
549398944Sobrien			       (TTRACE_ARG_TYPE) & page_permissions);
549446283Sdfr      if (errno || (tt_status < 0))
549598944Sobrien	{
549698944Sobrien	  errno = 0;
549798944Sobrien	  range_is_accessible = 0;
549898944Sobrien	  break;
549998944Sobrien	}
550046283Sdfr
550146283Sdfr      /* Yes, go for another... */
550246283Sdfr    }
550346283Sdfr
550498944Sobrien  return (!range_is_stack_based && range_is_accessible);
550546283Sdfr}
550646283Sdfr
550746283Sdfr
550846283Sdfrchar *
550998944Sobrienhppa_pid_or_tid_to_str (ptid_t ptid)
551046283Sdfr{
551198944Sobrien  static char buf[100];		/* Static because address returned. */
551298944Sobrien  pid_t id = PIDGET (ptid);
551346283Sdfr
551446283Sdfr  /* Does this appear to be a process?  If so, print it that way. */
551546283Sdfr  if (is_process_id (id))
551698944Sobrien    return child_pid_to_str (ptid);
551746283Sdfr
551846283Sdfr  /* Else, print both the GDB thread number and the system thread id. */
551998944Sobrien  sprintf (buf, "thread %d (", pid_to_thread_id (ptid));
552098944Sobrien  strcat (buf, hppa_tid_to_str (ptid));
552146283Sdfr  strcat (buf, ")\0");
552246283Sdfr
552346283Sdfr  return buf;
552446283Sdfr}
552598944Sobrien
552646283Sdfr
552746283Sdfrvoid
552898944Sobrienhppa_ensure_vforking_parent_remains_stopped (int pid)
552946283Sdfr{
553046283Sdfr  /* Nothing to do when using ttrace.  Only the ptrace-based implementation
553146283Sdfr     must do real work.
553246283Sdfr   */
553346283Sdfr}
553446283Sdfr
553546283Sdfr
553646283Sdfrint
553798944Sobrienhppa_resume_execd_vforking_child_to_get_parent_vfork (void)
553846283Sdfr{
553998944Sobrien  return 0;			/* No, the parent vfork is available now. */
554046283Sdfr}
554198944Sobrien
554246283Sdfr
554398944Sobrien/* Write a register as a 64bit value.  This may be necessary if the
554498944Sobrien   native OS is too braindamaged to allow some (or all) registers to
554598944Sobrien   be written in 32bit hunks such as hpux11 and the PC queue registers.
554646283Sdfr
554798944Sobrien   This is horribly gross and disgusting.  */
554898944Sobrien
554998944Sobrienint
555098944Sobrienttrace_write_reg_64 (int gdb_tid, CORE_ADDR dest_addr, CORE_ADDR src_addr)
555198944Sobrien{
555298944Sobrien  pid_t 	pid;
555398944Sobrien  lwpid_t 	tid;
555498944Sobrien  int  		tt_status;
555598944Sobrien
555698944Sobrien  tid = map_from_gdb_tid (gdb_tid);
555798944Sobrien  pid = get_pid_for (tid);
555898944Sobrien
555998944Sobrien  errno = 0;
556098944Sobrien  tt_status = ttrace (TT_LWP_WUREGS,
556198944Sobrien		      pid,
556298944Sobrien		      tid,
556398944Sobrien		      (TTRACE_ARG_TYPE) dest_addr,
556498944Sobrien		      8,
556598944Sobrien		      (TTRACE_ARG_TYPE) src_addr );
556698944Sobrien
556798944Sobrien#ifdef THREAD_DEBUG
556898944Sobrien  if (errno)
556998944Sobrien    {
557098944Sobrien      /* Don't bother for a known benign error: if you ask for the
557198944Sobrien         first thread state, but there is only one thread and it's
557298944Sobrien         not stopped, ttrace complains.
557398944Sobrien
557498944Sobrien         We have this inside the #ifdef because our caller will do
557598944Sobrien         this check for real.  */
557698944Sobrien      if( request != TT_PROC_GET_FIRST_LWP_STATE
557798944Sobrien          ||  errno   != EPROTO )
557898944Sobrien        {
557998944Sobrien          if( debug_on )
558098944Sobrien            printf( "TT fail for %s, with pid %d, tid %d, status %d \n",
558198944Sobrien                    get_printable_name_of_ttrace_request (TT_LWP_WUREGS),
558298944Sobrien                    pid, tid, tt_status );
558398944Sobrien        }
558498944Sobrien    }
558598944Sobrien#endif
558698944Sobrien
558798944Sobrien  return tt_status;
558898944Sobrien}
558998944Sobrien
559046283Sdfrvoid
559198944Sobrien_initialize_infttrace (void)
559246283Sdfr{
559346283Sdfr  /* Initialize the ttrace-based hardware watchpoint implementation. */
559498944Sobrien  memory_page_dictionary.page_count = (LONGEST) - 1;
559546283Sdfr  memory_page_dictionary.page_protections_allowed = 1;
559646283Sdfr
559746283Sdfr  errno = 0;
559846283Sdfr  memory_page_dictionary.page_size = sysconf (_SC_PAGE_SIZE);
559946283Sdfr
560098944Sobrien  /* We do a lot of casts from pointers to TTRACE_ARG_TYPE; make sure
560198944Sobrien     this is okay.  */
560298944Sobrien  if (sizeof (TTRACE_ARG_TYPE) < sizeof (void *))
560398944Sobrien    internal_error (__FILE__, __LINE__, "failed internal consistency check");
560498944Sobrien
560546283Sdfr  if (errno || (memory_page_dictionary.page_size <= 0))
560646283Sdfr    perror_with_name ("sysconf");
560746283Sdfr}
5608