infttrace.c revision 98944
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,
398944Sobrien   1999, 2000, 2001
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"
3046283Sdfr
3198944Sobrien/* We need pstat functionality so that we can get the exec file
3298944Sobrien   for a process we attach to.
3398944Sobrien
3498944Sobrien   According to HP, we should use the 64bit interfaces, so we
3598944Sobrien   define _PSTAT64 to achieve this.  */
3698944Sobrien#define _PSTAT64
3798944Sobrien#include <sys/pstat.h>
3898944Sobrien
3946283Sdfr/* Some hackery to work around a use of the #define name NO_FLAGS
4046283Sdfr * in both gdb and HPUX (bfd.h and /usr/include/machine/vmparam.h).
4146283Sdfr */
4246283Sdfr#ifdef  NO_FLAGS
4346283Sdfr#define INFTTRACE_TEMP_HACK NO_FLAGS
4446283Sdfr#undef  NO_FLAGS
4546283Sdfr#endif
4646283Sdfr
4746283Sdfr#ifdef USG
4846283Sdfr#include <sys/types.h>
4946283Sdfr#endif
5046283Sdfr
5146283Sdfr#include <sys/param.h>
5246283Sdfr#include <sys/dir.h>
5346283Sdfr#include <signal.h>
5446283Sdfr#include <sys/ioctl.h>
5546283Sdfr
5646283Sdfr#include <sys/ttrace.h>
5746283Sdfr#include <sys/mman.h>
5846283Sdfr
5946283Sdfr#ifndef NO_PTRACE_H
6046283Sdfr#ifdef PTRACE_IN_WRONG_PLACE
6146283Sdfr#include <ptrace.h>
6246283Sdfr#else
6346283Sdfr#include <sys/ptrace.h>
6446283Sdfr#endif
6546283Sdfr#endif /* NO_PTRACE_H */
6646283Sdfr
6746283Sdfr/* Second half of the hackery above.  Non-ANSI C, so
6846283Sdfr * we can't use "#error", alas.
6946283Sdfr */
7046283Sdfr#ifdef NO_FLAGS
7146283Sdfr#if (NO_FLAGS != INFTTRACE_TEMP_HACK )
7246283Sdfr  /* #error "Hackery to remove warning didn't work right" */
7346283Sdfr#else
7446283Sdfr  /* Ok, new def'n of NO_FLAGS is same as old one; no action needed. */
7546283Sdfr#endif
7646283Sdfr#else
7746283Sdfr  /* #error "Didn't get expected re-definition of NO_FLAGS" */
7846283Sdfr#define NO_FLAGS INFTTRACE_TEMP_HACK
7946283Sdfr#endif
8046283Sdfr
8146283Sdfr#if !defined (PT_SETTRC)
8246283Sdfr#define PT_SETTRC	0	/* Make process traceable by parent */
8346283Sdfr#endif
8446283Sdfr#if !defined (PT_READ_I)
8546283Sdfr#define PT_READ_I	1	/* Read word from text space */
8646283Sdfr#endif
8746283Sdfr#if !defined (PT_READ_D)
8846283Sdfr#define	PT_READ_D	2	/* Read word from data space */
8946283Sdfr#endif
9046283Sdfr#if !defined (PT_READ_U)
9146283Sdfr#define PT_READ_U	3	/* Read word from kernel user struct */
9246283Sdfr#endif
9346283Sdfr#if !defined (PT_WRITE_I)
9446283Sdfr#define PT_WRITE_I	4	/* Write word to text space */
9546283Sdfr#endif
9646283Sdfr#if !defined (PT_WRITE_D)
9746283Sdfr#define PT_WRITE_D	5	/* Write word to data space */
9846283Sdfr#endif
9946283Sdfr#if !defined (PT_WRITE_U)
10046283Sdfr#define PT_WRITE_U	6	/* Write word to kernel user struct */
10146283Sdfr#endif
10246283Sdfr#if !defined (PT_CONTINUE)
10346283Sdfr#define PT_CONTINUE	7	/* Continue after signal */
10446283Sdfr#endif
10546283Sdfr#if !defined (PT_STEP)
10646283Sdfr#define PT_STEP		9	/* Set flag for single stepping */
10746283Sdfr#endif
10846283Sdfr#if !defined (PT_KILL)
10946283Sdfr#define PT_KILL		8	/* Send child a SIGKILL signal */
11046283Sdfr#endif
11146283Sdfr
11246283Sdfr#ifndef PT_ATTACH
11346283Sdfr#define PT_ATTACH PTRACE_ATTACH
11446283Sdfr#endif
11546283Sdfr#ifndef PT_DETACH
11646283Sdfr#define PT_DETACH PTRACE_DETACH
11746283Sdfr#endif
11846283Sdfr
11946283Sdfr#include "gdbcore.h"
12046283Sdfr#ifndef	NO_SYS_FILE
12146283Sdfr#include <sys/file.h>
12246283Sdfr#endif
12346283Sdfr
12446283Sdfr/* This semaphore is used to coordinate the child and parent processes
12546283Sdfr   after a fork(), and before an exec() by the child.  See parent_attach_all
12646283Sdfr   for details.
12798944Sobrien */
12898944Sobrientypedef struct
12998944Sobrien  {
13098944Sobrien    int parent_channel[2];	/* Parent "talks" to [1], child "listens" to [0] */
13198944Sobrien    int child_channel[2];	/* Child "talks" to [1], parent "listens" to [0] */
13298944Sobrien  }
13398944Sobrienstartup_semaphore_t;
13446283Sdfr
13546283Sdfr#define SEM_TALK (1)
13646283Sdfr#define SEM_LISTEN (0)
13746283Sdfr
13898944Sobrienstatic startup_semaphore_t startup_semaphore;
13946283Sdfr
14046283Sdfr/* See can_touch_threads_of_process for details. */
14198944Sobrienstatic int vforking_child_pid = 0;
14298944Sobrienstatic int vfork_in_flight = 0;
14346283Sdfr
14446283Sdfr/* To support PREPARE_TO_PROCEED (hppa_prepare_to_proceed).
14546283Sdfr */
14698944Sobrienstatic pid_t old_gdb_pid = 0;
14746283Sdfrstatic pid_t reported_pid = 0;
14846283Sdfrstatic int reported_bpt = 0;
14946283Sdfr
15046283Sdfr/* 1 if ok as results of a ttrace or ttrace_wait call, 0 otherwise.
15146283Sdfr */
15246283Sdfr#define TT_OK( _status, _errno ) \
15346283Sdfr    (((_status) == 1) && ((_errno) == 0))
15446283Sdfr
15546283Sdfr#define TTRACE_ARG_TYPE uint64_t
15646283Sdfr
15746283Sdfr/* When supplied as the "addr" operand, ttrace interprets this
15846283Sdfr   to mean, "from the current address".
15998944Sobrien */
16046283Sdfr#define TT_USE_CURRENT_PC ((TTRACE_ARG_TYPE) TT_NOPC)
16146283Sdfr
16246283Sdfr/* When supplied as the "addr", "data" or "addr2" operand for most
16346283Sdfr   requests, ttrace interprets this to mean, "pay no heed to this
16446283Sdfr   argument".
16598944Sobrien */
16646283Sdfr#define TT_NIL ((TTRACE_ARG_TYPE) TT_NULLARG)
16746283Sdfr
16846283Sdfr/* This is capable of holding the value of a 32-bit register.  The
16946283Sdfr   value is always left-aligned in the buffer; i.e., [0] contains
17046283Sdfr   the most-significant byte of the register's value, and [sizeof(reg)]
17146283Sdfr   contains the least-significant value.
17246283Sdfr
17346283Sdfr   ??rehrauer: Yes, this assumes that an int is 32-bits on HP-UX, and
17446283Sdfr   that registers are 32-bits on HP-UX.  The latter assumption changes
17546283Sdfr   with PA2.0.
17698944Sobrien */
17798944Sobrientypedef int register_value_t;
17846283Sdfr
17946283Sdfr/********************************************************************
18046283Sdfr
18146283Sdfr                 How this works:
18246283Sdfr
18346283Sdfr   1.  Thread numbers
18446283Sdfr
18546283Sdfr   The rest of GDB sees threads as being things with different
18646283Sdfr   "pid" (process id) values.  See "thread.c" for details.  The
18746283Sdfr   separate threads will be seen and reacted to if infttrace passes
18846283Sdfr   back different pid values (for _events_).  See wait_for_inferior
18946283Sdfr   in inftarg.c.
19046283Sdfr
19146283Sdfr   So infttrace is going to use thread ids externally, pretending
19246283Sdfr   they are process ids, and keep track internally so that it can
19346283Sdfr   use the real process id (and thread id) when calling ttrace.
19446283Sdfr
19546283Sdfr   The data structure that supports this is a linked list of the
19646283Sdfr   current threads.  Since at some date infttrace will have to
19746283Sdfr   deal with multiple processes, each list element records its
19846283Sdfr   corresponding pid, rather than having a single global.
19946283Sdfr
20046283Sdfr   Note that the list is only approximately current; that's ok, as
20146283Sdfr   it's up to date when we need it (we hope!).  Also, it can contain
20246283Sdfr   dead threads, as there's no harm if it does.
20346283Sdfr
20446283Sdfr   The approach taken here is to bury the translation from external
20546283Sdfr   to internal inside "call_ttrace" and a few other places.
20646283Sdfr
20746283Sdfr   There are some wrinkles:
20846283Sdfr
20946283Sdfr   o  When GDB forks itself to create the debug target process,
21046283Sdfr      there's only a pid of 0 around in the child, so the
21146283Sdfr      TT_PROC_SETTRC operation uses a more direct call to ttrace;
21246283Sdfr      Similiarly, the initial setting of the event mask happens
21346283Sdfr      early as  well, and so is also special-cased, and an attach
21446283Sdfr      uses a real pid;
21546283Sdfr
21646283Sdfr   o  We define an unthreaded application as having a "pseudo"
21746283Sdfr      thread;
21846283Sdfr
21946283Sdfr   o  To keep from confusing the rest of GDB, we don't switch
22046283Sdfr      the PID for the pseudo thread to a TID.  A table will help:
22146283Sdfr
22246283Sdfr      Rest of GDB sees these PIDs:     pid   tid1  tid2  tid3 ...
22346283Sdfr
22446283Sdfr      Our thread list stores:          pid   pid   pid   pid  ...
22546283Sdfr                                       tid0  tid1  tid2  tid3
22646283Sdfr
22746283Sdfr      Ttrace sees these TIDS:          tid0  tid1  tid2  tid3 ...
22846283Sdfr
22946283Sdfr      Both pid and tid0 will map to tid0, as there are infttrace.c-internal
23046283Sdfr      calls to ttrace using tid0.
23146283Sdfr
23246283Sdfr   2. Step and Continue
23346283Sdfr
23446283Sdfr   Since we're implementing the "stop the world" model, sub-model
23546283Sdfr   "other threads run during step", we have some stuff to do:
23646283Sdfr
23746283Sdfr   o  User steps require continuing all threads other than the
23846283Sdfr      one the user is stepping;
23946283Sdfr
24046283Sdfr   o  Internal debugger steps (such as over a breakpoint or watchpoint,
24146283Sdfr      but not out of a library load thunk) require stepping only
24246283Sdfr      the selected thread; this means that we have to report the
24346283Sdfr      step finish on that thread, which can lead to complications;
24446283Sdfr
24546283Sdfr   o  When a thread is created, it is created running, rather
24646283Sdfr      than stopped--so we have to stop it.
24746283Sdfr
24846283Sdfr   The OS doesn't guarantee the stopped thread list will be stable,
24946283Sdfr   no does it guarantee where on the stopped thread list a thread
25046283Sdfr   that is single-stepped will wind up: it's possible that it will
25146283Sdfr   be off the list for a while, it's possible the step will complete
25246283Sdfr   and it will be re-posted to the end...
25346283Sdfr
25446283Sdfr   This means we have to scan the stopped thread list, build up
25546283Sdfr   a work-list, and then run down the work list; we can't do the
25646283Sdfr   step/continue during the scan.
25746283Sdfr
25846283Sdfr   3. Buffering events
25946283Sdfr
26046283Sdfr   Then there's the issue of waiting for an event.  We do this by
26146283Sdfr   noticing how many events are reported at the end of each wait.
26246283Sdfr   From then on, we "fake" all resumes and steps, returning instantly,
26346283Sdfr   and don't do another wait.  Once all pending events are reported,
26446283Sdfr   we can really resume again.
26546283Sdfr
26646283Sdfr   To keep this hidden, all the routines which know about tids and
26746283Sdfr   pids or real events and simulated ones are static (file-local).
26846283Sdfr
26946283Sdfr   This code can make lots of calls to ttrace, in particular it
27046283Sdfr   can spin down the list of thread states more than once.  If this
27146283Sdfr   becomes a performance hit, the spin could be done once and the
27246283Sdfr   various "tsp" blocks saved, keeping all later spins in this
27346283Sdfr   process.
27446283Sdfr
27546283Sdfr   The O/S doesn't promise to keep the list straight, and so we must
27646283Sdfr   re-scan a lot.  By observation, it looks like a single-step/wait
27746283Sdfr   puts the stepped thread at the end of the list but doesn't change
27846283Sdfr   it otherwise.
27946283Sdfr
28046283Sdfr****************************************************************
28146283Sdfr*/
28246283Sdfr
28346283Sdfr/* Uncomment these to turn on various debugging output */
28446283Sdfr/* #define THREAD_DEBUG */
28546283Sdfr/* #define WAIT_BUFFER_DEBUG */
28646283Sdfr/* #define PARANOIA */
28746283Sdfr
28846283Sdfr
28946283Sdfr#define INFTTRACE_ALL_THREADS (-1)
29046283Sdfr#define INFTTRACE_STEP        (1)
29146283Sdfr#define INFTTRACE_CONTINUE    (0)
29246283Sdfr
29346283Sdfr/* FIX: this is used in inftarg.c/child_wait, in a hack.
29446283Sdfr */
29546283Sdfrextern int not_same_real_pid;
29646283Sdfr
29746283Sdfr/* This is used to count buffered events.
29846283Sdfr */
29946283Sdfrstatic unsigned int more_events_left = 0;
30046283Sdfr
30146283Sdfr/* Process state.
30246283Sdfr */
30398944Sobrientypedef enum process_state_enum
30498944Sobrien  {
30546283Sdfr    STOPPED,
30646283Sdfr    FAKE_STEPPING,
30798944Sobrien    FAKE_CONTINUE,		/* For later use */
30846283Sdfr    RUNNING,
30946283Sdfr    FORKING,
31046283Sdfr    VFORKING
31198944Sobrien  }
31298944Sobrienprocess_state_t;
31346283Sdfr
31446283Sdfrstatic process_state_t process_state = STOPPED;
31546283Sdfr
31646283Sdfr/* User-specified stepping modality.
31746283Sdfr */
31898944Sobrientypedef enum stepping_mode_enum
31998944Sobrien  {
32098944Sobrien    DO_DEFAULT,			/* ...which is a continue! */
32146283Sdfr    DO_STEP,
32246283Sdfr    DO_CONTINUE
32398944Sobrien  }
32498944Sobrienstepping_mode_t;
32598944Sobrien
32646283Sdfr/* Action to take on an attach, depends on
32746283Sdfr * what kind (user command, fork, vfork).
32846283Sdfr *
32946283Sdfr * At the moment, this is either:
33046283Sdfr *
33146283Sdfr * o  continue with a SIGTRAP signal, or
33246283Sdfr *
33346283Sdfr * o  leave stopped.
33446283Sdfr */
33598944Sobrientypedef enum attach_continue_enum
33698944Sobrien  {
33798944Sobrien    DO_ATTACH_CONTINUE,
33898944Sobrien    DONT_ATTACH_CONTINUE
33998944Sobrien  }
34098944Sobrienattach_continue_t;
34146283Sdfr
34246283Sdfr/* This flag is true if we are doing a step-over-bpt
34346283Sdfr * with buffered events.  We will have to be sure to
34446283Sdfr * report the right thread, as otherwise the spaghetti
34546283Sdfr * code in "infrun.c/wait_for_inferior" will get
34646283Sdfr * confused.
34746283Sdfr */
34898944Sobrienstatic int doing_fake_step = 0;
34998944Sobrienstatic lwpid_t fake_step_tid = 0;
35098944Sobrien
35146283Sdfr
35246283Sdfr/****************************************************
35346283Sdfr * Thread information structure routines and types. *
35446283Sdfr ****************************************************
35546283Sdfr */
35698944Sobrientypedef
35746283Sdfrstruct thread_info_struct
35898944Sobrien  {
35998944Sobrien    int am_pseudo;		/* This is a pseudo-thread for the process. */
36098944Sobrien    int pid;			/* Process ID */
36198944Sobrien    lwpid_t tid;		/* Thread  ID */
36298944Sobrien    int handled;		/* 1 if a buffered event was handled. */
36398944Sobrien    int seen;			/* 1 if this thread was seen on a traverse. */
36498944Sobrien    int terminated;		/* 1 if thread has terminated. */
36598944Sobrien    int have_signal;		/* 1 if signal to be sent */
36698944Sobrien    enum target_signal signal_value;	/* Signal to send */
36798944Sobrien    int have_start;		/* 1 if alternate starting address */
36898944Sobrien    stepping_mode_t stepping_mode;	/* Whether to step or continue */
36998944Sobrien    CORE_ADDR start;		/* Where to start */
37098944Sobrien    int have_state;		/* 1 if the event state has been set */
37198944Sobrien    ttstate_t last_stop_state;	/* The most recently-waited event for this thread. */
37246283Sdfr    struct thread_info_struct
37398944Sobrien     *next;			/* All threads are linked via this field. */
37446283Sdfr    struct thread_info_struct
37598944Sobrien     *next_pseudo;		/* All pseudo-threads are linked via this field. */
37698944Sobrien  }
37798944Sobrienthread_info;
37846283Sdfr
37946283Sdfrtypedef
38046283Sdfrstruct thread_info_header_struct
38198944Sobrien  {
38298944Sobrien    int count;
38346283Sdfr    thread_info *head;
38446283Sdfr    thread_info *head_pseudo;
38546283Sdfr
38698944Sobrien  }
38798944Sobrienthread_info_header;
38846283Sdfr
38998944Sobrienstatic thread_info_header thread_head =
39098944Sobrien{0, NULL, NULL};
39198944Sobrienstatic thread_info_header deleted_threads =
39298944Sobrien{0, NULL, NULL};
39346283Sdfr
39498944Sobrienstatic ptid_t saved_real_ptid;
39546283Sdfr
39698944Sobrien
39746283Sdfr/*************************************************
39846283Sdfr *          Debugging support functions          *
39946283Sdfr *************************************************
40046283Sdfr */
40146283SdfrCORE_ADDR
40298944Sobrienget_raw_pc (lwpid_t ttid)
40346283Sdfr{
40498944Sobrien  unsigned long pc_val;
40598944Sobrien  int offset;
40698944Sobrien  int res;
40798944Sobrien
40898944Sobrien  offset = register_addr (PC_REGNUM, U_REGS_OFFSET);
40998944Sobrien  res = read_from_register_save_state (
41098944Sobrien					ttid,
41198944Sobrien					(TTRACE_ARG_TYPE) offset,
41298944Sobrien					(char *) &pc_val,
41398944Sobrien					sizeof (pc_val));
41498944Sobrien  if (res <= 0)
41598944Sobrien    {
41698944Sobrien      return (CORE_ADDR) pc_val;
41746283Sdfr    }
41898944Sobrien  else
41998944Sobrien    {
42098944Sobrien      return (CORE_ADDR) 0;
42146283Sdfr    }
42298944Sobrien}
42346283Sdfr
42446283Sdfrstatic char *
42598944Sobrienget_printable_name_of_stepping_mode (stepping_mode_t mode)
42646283Sdfr{
42798944Sobrien  switch (mode)
42898944Sobrien    {
42998944Sobrien    case DO_DEFAULT:
43098944Sobrien      return "DO_DEFAULT";
43198944Sobrien    case DO_STEP:
43298944Sobrien      return "DO_STEP";
43398944Sobrien    case DO_CONTINUE:
43498944Sobrien      return "DO_CONTINUE";
43598944Sobrien    default:
43698944Sobrien      return "?unknown mode?";
43798944Sobrien    }
43846283Sdfr}
43946283Sdfr
44046283Sdfr/* This function returns a pointer to a string describing the
44146283Sdfr * ttrace event being reported.
44246283Sdfr */
44346283Sdfrchar *
44498944Sobrienget_printable_name_of_ttrace_event (ttevents_t event)
44546283Sdfr{
44646283Sdfr  /* This enumeration is "gappy", so don't use a table. */
44798944Sobrien  switch (event)
44898944Sobrien    {
44946283Sdfr
45046283Sdfr    case TTEVT_NONE:
45198944Sobrien      return "TTEVT_NONE";
45246283Sdfr    case TTEVT_SIGNAL:
45398944Sobrien      return "TTEVT_SIGNAL";
45446283Sdfr    case TTEVT_FORK:
45598944Sobrien      return "TTEVT_FORK";
45646283Sdfr    case TTEVT_EXEC:
45798944Sobrien      return "TTEVT_EXEC";
45846283Sdfr    case TTEVT_EXIT:
45998944Sobrien      return "TTEVT_EXIT";
46046283Sdfr    case TTEVT_VFORK:
46198944Sobrien      return "TTEVT_VFORK";
46246283Sdfr    case TTEVT_SYSCALL_RETURN:
46398944Sobrien      return "TTEVT_SYSCALL_RETURN";
46446283Sdfr    case TTEVT_LWP_CREATE:
46598944Sobrien      return "TTEVT_LWP_CREATE";
46646283Sdfr    case TTEVT_LWP_TERMINATE:
46798944Sobrien      return "TTEVT_LWP_TERMINATE";
46846283Sdfr    case TTEVT_LWP_EXIT:
46998944Sobrien      return "TTEVT_LWP_EXIT";
47046283Sdfr    case TTEVT_LWP_ABORT_SYSCALL:
47198944Sobrien      return "TTEVT_LWP_ABORT_SYSCALL";
47246283Sdfr    case TTEVT_SYSCALL_ENTRY:
47398944Sobrien      return "TTEVT_SYSCALL_ENTRY";
47498944Sobrien    case TTEVT_SYSCALL_RESTART:
47598944Sobrien      return "TTEVT_SYSCALL_RESTART";
47698944Sobrien    default:
47746283Sdfr      return "?new event?";
47898944Sobrien    }
47946283Sdfr}
48098944Sobrien
48146283Sdfr
48246283Sdfr/* This function translates the ttrace request enumeration into
48346283Sdfr * a character string that is its printable (aka "human readable")
48446283Sdfr * name.
48546283Sdfr */
48646283Sdfrchar *
48798944Sobrienget_printable_name_of_ttrace_request (ttreq_t request)
48846283Sdfr{
48946283Sdfr  if (!IS_TTRACE_REQ (request))
49046283Sdfr    return "?bad req?";
49146283Sdfr
49246283Sdfr  /* This enumeration is "gappy", so don't use a table. */
49398944Sobrien  switch (request)
49498944Sobrien    {
49598944Sobrien    case TT_PROC_SETTRC:
49646283Sdfr      return "TT_PROC_SETTRC";
49798944Sobrien    case TT_PROC_ATTACH:
49846283Sdfr      return "TT_PROC_ATTACH";
49998944Sobrien    case TT_PROC_DETACH:
50046283Sdfr      return "TT_PROC_DETACH";
50198944Sobrien    case TT_PROC_RDTEXT:
50246283Sdfr      return "TT_PROC_RDTEXT";
50398944Sobrien    case TT_PROC_WRTEXT:
50446283Sdfr      return "TT_PROC_WRTEXT";
50598944Sobrien    case TT_PROC_RDDATA:
50646283Sdfr      return "TT_PROC_RDDATA";
50798944Sobrien    case TT_PROC_WRDATA:
50846283Sdfr      return "TT_PROC_WRDATA";
50998944Sobrien    case TT_PROC_STOP:
51046283Sdfr      return "TT_PROC_STOP";
51198944Sobrien    case TT_PROC_CONTINUE:
51246283Sdfr      return "TT_PROC_CONTINUE";
51398944Sobrien    case TT_PROC_GET_PATHNAME:
51446283Sdfr      return "TT_PROC_GET_PATHNAME";
51598944Sobrien    case TT_PROC_GET_EVENT_MASK:
51646283Sdfr      return "TT_PROC_GET_EVENT_MASK";
51798944Sobrien    case TT_PROC_SET_EVENT_MASK:
51846283Sdfr      return "TT_PROC_SET_EVENT_MASK";
51998944Sobrien    case TT_PROC_GET_FIRST_LWP_STATE:
52046283Sdfr      return "TT_PROC_GET_FIRST_LWP_STATE";
52198944Sobrien    case TT_PROC_GET_NEXT_LWP_STATE:
52246283Sdfr      return "TT_PROC_GET_NEXT_LWP_STATE";
52398944Sobrien    case TT_PROC_EXIT:
52446283Sdfr      return "TT_PROC_EXIT";
52598944Sobrien    case TT_PROC_GET_MPROTECT:
52646283Sdfr      return "TT_PROC_GET_MPROTECT";
52798944Sobrien    case TT_PROC_SET_MPROTECT:
52846283Sdfr      return "TT_PROC_SET_MPROTECT";
52998944Sobrien    case TT_PROC_SET_SCBM:
53046283Sdfr      return "TT_PROC_SET_SCBM";
53198944Sobrien    case TT_LWP_STOP:
53246283Sdfr      return "TT_LWP_STOP";
53398944Sobrien    case TT_LWP_CONTINUE:
53446283Sdfr      return "TT_LWP_CONTINUE";
53598944Sobrien    case TT_LWP_SINGLE:
53646283Sdfr      return "TT_LWP_SINGLE";
53798944Sobrien    case TT_LWP_RUREGS:
53846283Sdfr      return "TT_LWP_RUREGS";
53998944Sobrien    case TT_LWP_WUREGS:
54046283Sdfr      return "TT_LWP_WUREGS";
54198944Sobrien    case TT_LWP_GET_EVENT_MASK:
54246283Sdfr      return "TT_LWP_GET_EVENT_MASK";
54398944Sobrien    case TT_LWP_SET_EVENT_MASK:
54446283Sdfr      return "TT_LWP_SET_EVENT_MASK";
54598944Sobrien    case TT_LWP_GET_STATE:
54646283Sdfr      return "TT_LWP_GET_STATE";
54798944Sobrien    default:
54846283Sdfr      return "?new req?";
54998944Sobrien    }
55046283Sdfr}
55198944Sobrien
55246283Sdfr
55346283Sdfr/* This function translates the process state enumeration into
55446283Sdfr * a character string that is its printable (aka "human readable")
55546283Sdfr * name.
55646283Sdfr */
55746283Sdfrstatic char *
55898944Sobrienget_printable_name_of_process_state (process_state_t process_state)
55946283Sdfr{
56098944Sobrien  switch (process_state)
56198944Sobrien    {
56246283Sdfr    case STOPPED:
56346283Sdfr      return "STOPPED";
56446283Sdfr    case FAKE_STEPPING:
56546283Sdfr      return "FAKE_STEPPING";
56646283Sdfr    case RUNNING:
56746283Sdfr      return "RUNNING";
56846283Sdfr    case FORKING:
56946283Sdfr      return "FORKING";
57046283Sdfr    case VFORKING:
57146283Sdfr      return "VFORKING";
57246283Sdfr    default:
57346283Sdfr      return "?some unknown state?";
57498944Sobrien    }
57546283Sdfr}
57646283Sdfr
57746283Sdfr/* Set a ttrace thread state to a safe, initial state.
57846283Sdfr */
57946283Sdfrstatic void
58098944Sobrienclear_ttstate_t (ttstate_t *tts)
58146283Sdfr{
58298944Sobrien  tts->tts_pid = 0;
58398944Sobrien  tts->tts_lwpid = 0;
58498944Sobrien  tts->tts_user_tid = 0;
58598944Sobrien  tts->tts_event = TTEVT_NONE;
58646283Sdfr}
58746283Sdfr
58846283Sdfr/* Copy ttrace thread state TTS_FROM into TTS_TO.
58946283Sdfr */
59046283Sdfrstatic void
59198944Sobriencopy_ttstate_t (ttstate_t *tts_to, ttstate_t *tts_from)
59246283Sdfr{
59398944Sobrien  memcpy ((char *) tts_to, (char *) tts_from, sizeof (*tts_to));
59446283Sdfr}
59546283Sdfr
59646283Sdfr/* Are there any live threads we know about?
59746283Sdfr */
59898944Sobrienstatic int
59998944Sobrienany_thread_records (void)
60046283Sdfr{
60198944Sobrien  return (thread_head.count > 0);
60246283Sdfr}
60346283Sdfr
60446283Sdfr/* Create, fill in and link in a thread descriptor.
60546283Sdfr */
60646283Sdfrstatic thread_info *
60798944Sobriencreate_thread_info (int pid, lwpid_t tid)
60846283Sdfr{
60998944Sobrien  thread_info *new_p;
61098944Sobrien  thread_info *p;
61198944Sobrien  int thread_count_of_pid;
61246283Sdfr
61398944Sobrien  new_p = xmalloc (sizeof (thread_info));
61498944Sobrien  new_p->pid = pid;
61598944Sobrien  new_p->tid = tid;
61698944Sobrien  new_p->have_signal = 0;
61798944Sobrien  new_p->have_start = 0;
61898944Sobrien  new_p->have_state = 0;
61998944Sobrien  clear_ttstate_t (&new_p->last_stop_state);
62098944Sobrien  new_p->am_pseudo = 0;
62198944Sobrien  new_p->handled = 0;
62298944Sobrien  new_p->seen = 0;
62398944Sobrien  new_p->terminated = 0;
62498944Sobrien  new_p->next = NULL;
62598944Sobrien  new_p->next_pseudo = NULL;
62698944Sobrien  new_p->stepping_mode = DO_DEFAULT;
62746283Sdfr
62898944Sobrien  if (0 == thread_head.count)
62998944Sobrien    {
63046283Sdfr#ifdef THREAD_DEBUG
63198944Sobrien      if (debug_on)
63298944Sobrien	printf ("First thread, pid %d tid %d!\n", pid, tid);
63346283Sdfr#endif
63498944Sobrien      saved_real_ptid = inferior_ptid;
63546283Sdfr    }
63698944Sobrien  else
63798944Sobrien    {
63846283Sdfr#ifdef THREAD_DEBUG
63998944Sobrien      if (debug_on)
64098944Sobrien	printf ("Subsequent thread, pid %d tid %d\n", pid, tid);
64146283Sdfr#endif
64246283Sdfr    }
64346283Sdfr
64498944Sobrien  /* Another day, another thread...
64598944Sobrien   */
64698944Sobrien  thread_head.count++;
64746283Sdfr
64898944Sobrien  /* The new thread always goes at the head of the list.
64998944Sobrien   */
65098944Sobrien  new_p->next = thread_head.head;
65198944Sobrien  thread_head.head = new_p;
65246283Sdfr
65398944Sobrien  /* Is this the "pseudo" thread of a process?  It is if there's
65498944Sobrien   * no other thread for this process on the list.  (Note that this
65598944Sobrien   * accomodates multiple processes, such as we see even for simple
65698944Sobrien   * cases like forking "non-threaded" programs.)
65798944Sobrien   */
65898944Sobrien  p = thread_head.head;
65998944Sobrien  thread_count_of_pid = 0;
66098944Sobrien  while (p)
66198944Sobrien    {
66298944Sobrien      if (p->pid == new_p->pid)
66398944Sobrien	thread_count_of_pid++;
66498944Sobrien      p = p->next;
66598944Sobrien    }
66646283Sdfr
66798944Sobrien  /* Did we see any other threads for this pid?  (Recall that we just
66898944Sobrien   * added this thread to the list...)
66998944Sobrien   */
67098944Sobrien  if (thread_count_of_pid == 1)
67198944Sobrien    {
67298944Sobrien      new_p->am_pseudo = 1;
67398944Sobrien      new_p->next_pseudo = thread_head.head_pseudo;
67498944Sobrien      thread_head.head_pseudo = new_p;
67598944Sobrien    }
67698944Sobrien
67798944Sobrien  return new_p;
67846283Sdfr}
67946283Sdfr
68046283Sdfr/* Get rid of our thread info.
68146283Sdfr */
68246283Sdfrstatic void
68398944Sobrienclear_thread_info (void)
68446283Sdfr{
68598944Sobrien  thread_info *p;
68698944Sobrien  thread_info *q;
68746283Sdfr
68846283Sdfr#ifdef THREAD_DEBUG
68998944Sobrien  if (debug_on)
69098944Sobrien    printf ("Clearing all thread info\n");
69146283Sdfr#endif
69246283Sdfr
69398944Sobrien  p = thread_head.head;
69498944Sobrien  while (p)
69598944Sobrien    {
69698944Sobrien      q = p;
69798944Sobrien      p = p->next;
69898944Sobrien      xfree (q);
69946283Sdfr    }
70046283Sdfr
70198944Sobrien  thread_head.head = NULL;
70298944Sobrien  thread_head.head_pseudo = NULL;
70398944Sobrien  thread_head.count = 0;
70446283Sdfr
70598944Sobrien  p = deleted_threads.head;
70698944Sobrien  while (p)
70798944Sobrien    {
70898944Sobrien      q = p;
70998944Sobrien      p = p->next;
71098944Sobrien      xfree (q);
71146283Sdfr    }
71246283Sdfr
71398944Sobrien  deleted_threads.head = NULL;
71498944Sobrien  deleted_threads.head_pseudo = NULL;
71598944Sobrien  deleted_threads.count = 0;
71646283Sdfr
71798944Sobrien  /* No threads, so can't have pending events.
71898944Sobrien   */
71998944Sobrien  more_events_left = 0;
72046283Sdfr}
72146283Sdfr
72246283Sdfr/* Given a tid, find the thread block for it.
72346283Sdfr */
72446283Sdfrstatic thread_info *
72598944Sobrienfind_thread_info (lwpid_t tid)
72646283Sdfr{
72798944Sobrien  thread_info *p;
72846283Sdfr
72998944Sobrien  for (p = thread_head.head; p; p = p->next)
73098944Sobrien    {
73198944Sobrien      if (p->tid == tid)
73298944Sobrien	{
73398944Sobrien	  return p;
73498944Sobrien	}
73546283Sdfr    }
73646283Sdfr
73798944Sobrien  for (p = deleted_threads.head; p; p = p->next)
73898944Sobrien    {
73998944Sobrien      if (p->tid == tid)
74098944Sobrien	{
74198944Sobrien	  return p;
74298944Sobrien	}
74346283Sdfr    }
74498944Sobrien
74598944Sobrien  return NULL;
74646283Sdfr}
74746283Sdfr
74846283Sdfr/* For any but the pseudo thread, this maps to the
74946283Sdfr * thread ID.  For the pseudo thread, if you pass either
75046283Sdfr * the thread id or the PID, you get the pseudo thread ID.
75146283Sdfr *
75246283Sdfr * We have to be prepared for core gdb to ask about
75346283Sdfr * deleted threads.  We do the map, but we don't like it.
75446283Sdfr */
75546283Sdfrstatic lwpid_t
75698944Sobrienmap_from_gdb_tid (lwpid_t gdb_tid)
75746283Sdfr{
75898944Sobrien  thread_info *p;
75946283Sdfr
76098944Sobrien  /* First assume gdb_tid really is a tid, and try to find a
76198944Sobrien   * matching entry on the threads list.
76298944Sobrien   */
76398944Sobrien  for (p = thread_head.head; p; p = p->next)
76498944Sobrien    {
76598944Sobrien      if (p->tid == gdb_tid)
76698944Sobrien	return gdb_tid;
76746283Sdfr    }
76846283Sdfr
76998944Sobrien  /* It doesn't appear to be a tid; perhaps it's really a pid?
77098944Sobrien   * Try to find a "pseudo" thread entry on the threads list.
77198944Sobrien   */
77298944Sobrien  for (p = thread_head.head_pseudo; p != NULL; p = p->next_pseudo)
77398944Sobrien    {
77498944Sobrien      if (p->pid == gdb_tid)
77598944Sobrien	return p->tid;
77698944Sobrien    }
77746283Sdfr
77898944Sobrien  /* Perhaps it's the tid of a deleted thread we may still
77998944Sobrien   * have some knowledge of?
78098944Sobrien   */
78198944Sobrien  for (p = deleted_threads.head; p; p = p->next)
78298944Sobrien    {
78398944Sobrien      if (p->tid == gdb_tid)
78498944Sobrien	return gdb_tid;
78546283Sdfr    }
78646283Sdfr
78798944Sobrien  /* Or perhaps it's the pid of a deleted process we may still
78898944Sobrien   * have knowledge of?
78998944Sobrien   */
79098944Sobrien  for (p = deleted_threads.head_pseudo; p != NULL; p = p->next_pseudo)
79198944Sobrien    {
79298944Sobrien      if (p->pid == gdb_tid)
79398944Sobrien	return p->tid;
79498944Sobrien    }
79546283Sdfr
79698944Sobrien  return 0;			/* Error? */
79746283Sdfr}
79846283Sdfr
79946283Sdfr/* Map the other way: from a real tid to the
80046283Sdfr * "pid" known by core gdb.  This tid may be
80146283Sdfr * for a thread that just got deleted, so we
80246283Sdfr * also need to consider deleted threads.
80346283Sdfr */
80446283Sdfrstatic lwpid_t
80598944Sobrienmap_to_gdb_tid (lwpid_t real_tid)
80646283Sdfr{
80798944Sobrien  thread_info *p;
80846283Sdfr
80998944Sobrien  for (p = thread_head.head; p; p = p->next)
81098944Sobrien    {
81198944Sobrien      if (p->tid == real_tid)
81298944Sobrien	{
81398944Sobrien	  if (p->am_pseudo)
81498944Sobrien	    return p->pid;
81598944Sobrien	  else
81698944Sobrien	    return real_tid;
81798944Sobrien	}
81846283Sdfr    }
81946283Sdfr
82098944Sobrien  for (p = deleted_threads.head; p; p = p->next)
82198944Sobrien    {
82298944Sobrien      if (p->tid == real_tid)
82398944Sobrien	if (p->am_pseudo)
82498944Sobrien	  return p->pid;	/* Error? */
82598944Sobrien	else
82698944Sobrien	  return real_tid;
82746283Sdfr    }
82846283Sdfr
82998944Sobrien  return 0;			/* Error?  Never heard of this thread! */
83046283Sdfr}
83146283Sdfr
83246283Sdfr/* Do any threads have saved signals?
83346283Sdfr */
83498944Sobrienstatic int
83598944Sobriensaved_signals_exist (void)
83646283Sdfr{
83798944Sobrien  thread_info *p;
83898944Sobrien
83998944Sobrien  for (p = thread_head.head; p; p = p->next)
84098944Sobrien    {
84198944Sobrien      if (p->have_signal)
84298944Sobrien	{
84398944Sobrien	  return 1;
84498944Sobrien	}
84546283Sdfr    }
84646283Sdfr
84798944Sobrien  return 0;
84846283Sdfr}
84946283Sdfr
85046283Sdfr/* Is this the tid for the zero-th thread?
85146283Sdfr */
85298944Sobrienstatic int
85398944Sobrienis_pseudo_thread (lwpid_t tid)
85446283Sdfr{
85598944Sobrien  thread_info *p = find_thread_info (tid);
85698944Sobrien  if (NULL == p || p->terminated)
85798944Sobrien    return 0;
85898944Sobrien  else
85998944Sobrien    return p->am_pseudo;
86046283Sdfr}
86146283Sdfr
86246283Sdfr/* Is this thread terminated?
86346283Sdfr */
86498944Sobrienstatic int
86598944Sobrienis_terminated (lwpid_t tid)
86646283Sdfr{
86798944Sobrien  thread_info *p = find_thread_info (tid);
86846283Sdfr
86998944Sobrien  if (NULL != p)
87098944Sobrien    return p->terminated;
87146283Sdfr
87298944Sobrien  return 0;
87346283Sdfr}
87446283Sdfr
87546283Sdfr/* Is this pid a real PID or a TID?
87646283Sdfr */
87798944Sobrienstatic int
87898944Sobrienis_process_id (int pid)
87946283Sdfr{
88098944Sobrien  lwpid_t tid;
88198944Sobrien  thread_info *tinfo;
88298944Sobrien  pid_t this_pid;
88398944Sobrien  int this_pid_count;
88446283Sdfr
88546283Sdfr  /* What does PID really represent?
88646283Sdfr   */
88746283Sdfr  tid = map_from_gdb_tid (pid);
88846283Sdfr  if (tid <= 0)
88998944Sobrien    return 0;			/* Actually, is probably an error... */
89046283Sdfr
89146283Sdfr  tinfo = find_thread_info (tid);
89246283Sdfr
89346283Sdfr  /* Does it appear to be a true thread?
89446283Sdfr   */
89598944Sobrien  if (!tinfo->am_pseudo)
89646283Sdfr    return 0;
89746283Sdfr
89846283Sdfr  /* Else, it looks like it may be a process.  See if there's any other
89946283Sdfr   * threads with the same process ID, though.  If there are, then TID
90046283Sdfr   * just happens to be the first thread of several for this process.
90146283Sdfr   */
90246283Sdfr  this_pid = tinfo->pid;
90346283Sdfr  this_pid_count = 0;
90446283Sdfr  for (tinfo = thread_head.head; tinfo; tinfo = tinfo->next)
90546283Sdfr    {
90646283Sdfr      if (tinfo->pid == this_pid)
90798944Sobrien	this_pid_count++;
90846283Sdfr    }
90946283Sdfr
91046283Sdfr  return (this_pid_count == 1);
91146283Sdfr}
91246283Sdfr
91346283Sdfr
91446283Sdfr/* Add a thread to our info.  Prevent duplicate entries.
91546283Sdfr */
91646283Sdfrstatic thread_info *
91798944Sobrienadd_tthread (int pid, lwpid_t tid)
91846283Sdfr{
91998944Sobrien  thread_info *p;
92046283Sdfr
92198944Sobrien  p = find_thread_info (tid);
92298944Sobrien  if (NULL == p)
92398944Sobrien    p = create_thread_info (pid, tid);
92446283Sdfr
92598944Sobrien  return p;
92646283Sdfr}
92746283Sdfr
92846283Sdfr/* Notice that a thread was deleted.
92946283Sdfr */
93046283Sdfrstatic void
93198944Sobriendel_tthread (lwpid_t tid)
93246283Sdfr{
93398944Sobrien  thread_info *p;
93498944Sobrien  thread_info *chase;
93546283Sdfr
93698944Sobrien  if (thread_head.count <= 0)
93798944Sobrien    {
93898944Sobrien      error ("Internal error in thread database.");
93998944Sobrien      return;
94046283Sdfr    }
94146283Sdfr
94298944Sobrien  chase = NULL;
94398944Sobrien  for (p = thread_head.head; p; p = p->next)
94498944Sobrien    {
94598944Sobrien      if (p->tid == tid)
94698944Sobrien	{
94746283Sdfr
94846283Sdfr#ifdef THREAD_DEBUG
94998944Sobrien	  if (debug_on)
95098944Sobrien	    printf ("Delete here: %d \n", tid);
95146283Sdfr#endif
95246283Sdfr
95398944Sobrien	  if (p->am_pseudo)
95498944Sobrien	    {
95598944Sobrien	      /*
95698944Sobrien	       * Deleting a main thread is ok if we're doing
95798944Sobrien	       * a parent-follow on a child; this is odd but
95898944Sobrien	       * not wrong.  It apparently _doesn't_ happen
95998944Sobrien	       * on the child-follow, as we don't just delete
96098944Sobrien	       * the pseudo while keeping the rest of the
96198944Sobrien	       * threads around--instead, we clear out the whole
96298944Sobrien	       * thread list at once.
96398944Sobrien	       */
96498944Sobrien	      thread_info *q;
96598944Sobrien	      thread_info *q_chase;
96646283Sdfr
96798944Sobrien	      q_chase = NULL;
96898944Sobrien	      for (q = thread_head.head_pseudo; q; q = q->next)
96998944Sobrien		{
97098944Sobrien		  if (q == p)
97198944Sobrien		    {
97298944Sobrien		      /* Remove from pseudo list.
97398944Sobrien		       */
97498944Sobrien		      if (q_chase == NULL)
97598944Sobrien			thread_head.head_pseudo = p->next_pseudo;
97698944Sobrien		      else
97798944Sobrien			q_chase->next = p->next_pseudo;
97898944Sobrien		    }
97998944Sobrien		  else
98098944Sobrien		    q_chase = q;
98198944Sobrien		}
98298944Sobrien	    }
98346283Sdfr
98498944Sobrien	  /* Remove from live list.
98598944Sobrien	   */
98698944Sobrien	  thread_head.count--;
98746283Sdfr
98898944Sobrien	  if (NULL == chase)
98998944Sobrien	    thread_head.head = p->next;
99098944Sobrien	  else
99198944Sobrien	    chase->next = p->next;
99298944Sobrien
99398944Sobrien	  /* Add to deleted thread list.
99498944Sobrien	   */
99598944Sobrien	  p->next = deleted_threads.head;
99698944Sobrien	  deleted_threads.head = p;
99798944Sobrien	  deleted_threads.count++;
99898944Sobrien	  if (p->am_pseudo)
99998944Sobrien	    {
100098944Sobrien	      p->next_pseudo = deleted_threads.head_pseudo;
100198944Sobrien	      deleted_threads.head_pseudo = p;
100298944Sobrien	    }
100398944Sobrien	  p->terminated = 1;
100498944Sobrien
100598944Sobrien	  return;
100698944Sobrien	}
100798944Sobrien
100898944Sobrien      else
100998944Sobrien	chase = p;
101046283Sdfr    }
101146283Sdfr}
101246283Sdfr
101346283Sdfr/* Get the pid for this tid. (Has to be a real TID!).
101446283Sdfr */
101546283Sdfrstatic int
101698944Sobrienget_pid_for (lwpid_t tid)
101746283Sdfr{
101898944Sobrien  thread_info *p;
101946283Sdfr
102098944Sobrien  for (p = thread_head.head; p; p = p->next)
102198944Sobrien    {
102298944Sobrien      if (p->tid == tid)
102398944Sobrien	{
102498944Sobrien	  return p->pid;
102598944Sobrien	}
102646283Sdfr    }
102746283Sdfr
102898944Sobrien  for (p = deleted_threads.head; p; p = p->next)
102998944Sobrien    {
103098944Sobrien      if (p->tid == tid)
103198944Sobrien	{
103298944Sobrien	  return p->pid;
103398944Sobrien	}
103446283Sdfr    }
103598944Sobrien
103698944Sobrien  return 0;
103746283Sdfr}
103846283Sdfr
103946283Sdfr/* Note that this thread's current event has been handled.
104046283Sdfr */
104146283Sdfrstatic void
104298944Sobrienset_handled (int pid, lwpid_t tid)
104346283Sdfr{
104498944Sobrien  thread_info *p;
104546283Sdfr
104698944Sobrien  p = find_thread_info (tid);
104798944Sobrien  if (NULL == p)
104898944Sobrien    p = add_tthread (pid, tid);
104998944Sobrien
105098944Sobrien  p->handled = 1;
105146283Sdfr}
105246283Sdfr
105346283Sdfr/* Was this thread's current event handled?
105446283Sdfr */
105598944Sobrienstatic int
105698944Sobrienwas_handled (lwpid_t tid)
105746283Sdfr{
105898944Sobrien  thread_info *p;
105946283Sdfr
106098944Sobrien  p = find_thread_info (tid);
106198944Sobrien  if (NULL != p)
106298944Sobrien    return p->handled;
106398944Sobrien
106498944Sobrien  return 0;			/* New threads have not been handled */
106546283Sdfr}
106646283Sdfr
106746283Sdfr/* Set this thread to unhandled.
106846283Sdfr */
106946283Sdfrstatic void
107098944Sobrienclear_handled (lwpid_t tid)
107146283Sdfr{
107298944Sobrien  thread_info *p;
107398944Sobrien
107446283Sdfr#ifdef WAIT_BUFFER_DEBUG
107598944Sobrien  if (debug_on)
107698944Sobrien    printf ("clear_handled %d\n", (int) tid);
107746283Sdfr#endif
107846283Sdfr
107946283Sdfr  p = find_thread_info (tid);
108046283Sdfr  if (p == NULL)
108146283Sdfr    error ("Internal error: No thread state to clear?");
108246283Sdfr
108346283Sdfr  p->handled = 0;
108446283Sdfr}
108546283Sdfr
108646283Sdfr/* Set all threads to unhandled.
108746283Sdfr */
108846283Sdfrstatic void
108998944Sobrienclear_all_handled (void)
109046283Sdfr{
109198944Sobrien  thread_info *p;
109246283Sdfr
109346283Sdfr#ifdef WAIT_BUFFER_DEBUG
109498944Sobrien  if (debug_on)
109598944Sobrien    printf ("clear_all_handled\n");
109646283Sdfr#endif
109746283Sdfr
109898944Sobrien  for (p = thread_head.head; p; p = p->next)
109998944Sobrien    {
110098944Sobrien      p->handled = 0;
110146283Sdfr    }
110246283Sdfr
110398944Sobrien  for (p = deleted_threads.head; p; p = p->next)
110498944Sobrien    {
110598944Sobrien      p->handled = 0;
110646283Sdfr    }
110746283Sdfr}
110846283Sdfr
110946283Sdfr/* Set this thread to default stepping mode.
111046283Sdfr */
111146283Sdfrstatic void
111298944Sobrienclear_stepping_mode (lwpid_t tid)
111346283Sdfr{
111498944Sobrien  thread_info *p;
111598944Sobrien
111646283Sdfr#ifdef WAIT_BUFFER_DEBUG
111798944Sobrien  if (debug_on)
111898944Sobrien    printf ("clear_stepping_mode %d\n", (int) tid);
111946283Sdfr#endif
112046283Sdfr
112146283Sdfr  p = find_thread_info (tid);
112246283Sdfr  if (p == NULL)
112346283Sdfr    error ("Internal error: No thread state to clear?");
112446283Sdfr
112546283Sdfr  p->stepping_mode = DO_DEFAULT;
112646283Sdfr}
112746283Sdfr
112846283Sdfr/* Set all threads to do default continue on resume.
112946283Sdfr */
113046283Sdfrstatic void
113198944Sobrienclear_all_stepping_mode (void)
113246283Sdfr{
113398944Sobrien  thread_info *p;
113446283Sdfr
113546283Sdfr#ifdef WAIT_BUFFER_DEBUG
113698944Sobrien  if (debug_on)
113798944Sobrien    printf ("clear_all_stepping_mode\n");
113846283Sdfr#endif
113946283Sdfr
114098944Sobrien  for (p = thread_head.head; p; p = p->next)
114198944Sobrien    {
114298944Sobrien      p->stepping_mode = DO_DEFAULT;
114346283Sdfr    }
114446283Sdfr
114598944Sobrien  for (p = deleted_threads.head; p; p = p->next)
114698944Sobrien    {
114798944Sobrien      p->stepping_mode = DO_DEFAULT;
114846283Sdfr    }
114946283Sdfr}
115046283Sdfr
115146283Sdfr/* Set all threads to unseen on this pass.
115298944Sobrien */
115346283Sdfrstatic void
115498944Sobrienset_all_unseen (void)
115546283Sdfr{
115698944Sobrien  thread_info *p;
115746283Sdfr
115898944Sobrien  for (p = thread_head.head; p; p = p->next)
115998944Sobrien    {
116098944Sobrien      p->seen = 0;
116146283Sdfr    }
116246283Sdfr}
116346283Sdfr
116446283Sdfr#if (defined( THREAD_DEBUG ) || defined( PARANOIA ))
116546283Sdfr/* debugging routine.
116646283Sdfr */
116746283Sdfrstatic void
116898944Sobrienprint_tthread (thread_info *p)
116946283Sdfr{
117098944Sobrien  printf (" Thread pid %d, tid %d", p->pid, p->tid);
117198944Sobrien  if (p->have_state)
117298944Sobrien    printf (", event is %s",
117398944Sobrien	 get_printable_name_of_ttrace_event (p->last_stop_state.tts_event));
117446283Sdfr
117598944Sobrien  if (p->am_pseudo)
117698944Sobrien    printf (", pseudo thread");
117798944Sobrien
117898944Sobrien  if (p->have_signal)
117998944Sobrien    printf (", have signal 0x%x", p->signal_value);
118098944Sobrien
118198944Sobrien  if (p->have_start)
118298944Sobrien    printf (", have start at 0x%x", p->start);
118398944Sobrien
118498944Sobrien  printf (", step is %s", get_printable_name_of_stepping_mode (p->stepping_mode));
118598944Sobrien
118698944Sobrien  if (p->handled)
118798944Sobrien    printf (", handled");
118898944Sobrien  else
118998944Sobrien    printf (", not handled");
119098944Sobrien
119198944Sobrien  if (p->seen)
119298944Sobrien    printf (", seen");
119398944Sobrien  else
119498944Sobrien    printf (", not seen");
119598944Sobrien
119698944Sobrien  printf ("\n");
119746283Sdfr}
119846283Sdfr
119946283Sdfrstatic void
120098944Sobrienprint_tthreads (void)
120146283Sdfr{
120298944Sobrien  thread_info *p;
120346283Sdfr
120498944Sobrien  if (thread_head.count == 0)
120598944Sobrien    printf ("Thread list is empty\n");
120698944Sobrien  else
120798944Sobrien    {
120898944Sobrien      printf ("Thread list has ");
120998944Sobrien      if (thread_head.count == 1)
121098944Sobrien	printf ("1 entry:\n");
121198944Sobrien      else
121298944Sobrien	printf ("%d entries:\n", thread_head.count);
121398944Sobrien      for (p = thread_head.head; p; p = p->next)
121498944Sobrien	{
121598944Sobrien	  print_tthread (p);
121698944Sobrien	}
121746283Sdfr    }
121846283Sdfr
121998944Sobrien  if (deleted_threads.count == 0)
122098944Sobrien    printf ("Deleted thread list is empty\n");
122198944Sobrien  else
122298944Sobrien    {
122398944Sobrien      printf ("Deleted thread list has ");
122498944Sobrien      if (deleted_threads.count == 1)
122598944Sobrien	printf ("1 entry:\n");
122698944Sobrien      else
122798944Sobrien	printf ("%d entries:\n", deleted_threads.count);
122846283Sdfr
122998944Sobrien      for (p = deleted_threads.head; p; p = p->next)
123098944Sobrien	{
123198944Sobrien	  print_tthread (p);
123298944Sobrien	}
123346283Sdfr    }
123446283Sdfr}
123546283Sdfr#endif
123646283Sdfr
123746283Sdfr/* Update the thread list based on the "seen" bits.
123846283Sdfr */
123946283Sdfrstatic void
124098944Sobrienupdate_thread_list (void)
124146283Sdfr{
124298944Sobrien  thread_info *p;
124398944Sobrien  thread_info *chase;
124446283Sdfr
124598944Sobrien  chase = NULL;
124698944Sobrien  for (p = thread_head.head; p; p = p->next)
124798944Sobrien    {
124846283Sdfr      /* Is this an "unseen" thread which really happens to be a process?
124998944Sobrien         If so, is it inferior_ptid and is a vfork in flight?  If yes to
125046283Sdfr         all, then DON'T REMOVE IT!  We're in the midst of moving a vfork
125146283Sdfr         operation, which is a multiple step thing, to the point where we
125246283Sdfr         can touch the parent again.  We've most likely stopped to examine
125346283Sdfr         the child at a late stage in the vfork, and if we're not following
125446283Sdfr         the child, we'd best not treat the parent as a dead "thread"...
125598944Sobrien       */
125698944Sobrien      if ((!p->seen) && p->am_pseudo && vfork_in_flight
125798944Sobrien	  && (p->pid != vforking_child_pid))
125898944Sobrien	p->seen = 1;
125946283Sdfr
126098944Sobrien      if (!p->seen)
126198944Sobrien	{
126298944Sobrien	  /* Remove this one
126398944Sobrien	   */
126446283Sdfr
126546283Sdfr#ifdef THREAD_DEBUG
126698944Sobrien	  if (debug_on)
126798944Sobrien	    printf ("Delete unseen thread: %d \n", p->tid);
126846283Sdfr#endif
126998944Sobrien	  del_tthread (p->tid);
127098944Sobrien	}
127146283Sdfr    }
127246283Sdfr}
127398944Sobrien
127446283Sdfr
127598944Sobrien
127646283Sdfr/************************************************
127746283Sdfr *            O/S call wrappers                 *
127846283Sdfr ************************************************
127946283Sdfr */
128046283Sdfr
128146283Sdfr/* This function simply calls ttrace with the given arguments.
128246283Sdfr * It exists so that all calls to ttrace are isolated.  All
128346283Sdfr * parameters should be as specified by "man 2 ttrace".
128446283Sdfr *
128546283Sdfr * No other "raw" calls to ttrace should exist in this module.
128646283Sdfr */
128746283Sdfrstatic int
128898944Sobriencall_real_ttrace (ttreq_t request, pid_t pid, lwpid_t tid, TTRACE_ARG_TYPE addr,
128998944Sobrien		  TTRACE_ARG_TYPE data, TTRACE_ARG_TYPE addr2)
129046283Sdfr{
129198944Sobrien  int tt_status;
129246283Sdfr
129346283Sdfr  errno = 0;
129498944Sobrien  tt_status = ttrace (request, pid, tid, addr, data, addr2);
129546283Sdfr
129646283Sdfr#ifdef THREAD_DEBUG
129798944Sobrien  if (errno)
129898944Sobrien    {
129998944Sobrien      /* Don't bother for a known benign error: if you ask for the
130098944Sobrien       * first thread state, but there is only one thread and it's
130198944Sobrien       * not stopped, ttrace complains.
130298944Sobrien       *
130398944Sobrien       * We have this inside the #ifdef because our caller will do
130498944Sobrien       * this check for real.
130598944Sobrien       */
130698944Sobrien      if (request != TT_PROC_GET_FIRST_LWP_STATE
130798944Sobrien	  || errno != EPROTO)
130898944Sobrien	{
130998944Sobrien	  if (debug_on)
131098944Sobrien	    printf ("TT fail for %s, with pid %d, tid %d, status %d \n",
131198944Sobrien		    get_printable_name_of_ttrace_request (request),
131298944Sobrien		    pid, tid, tt_status);
131398944Sobrien	}
131446283Sdfr    }
131546283Sdfr#endif
131646283Sdfr
131746283Sdfr#if 0
131846283Sdfr  /* ??rehrauer: It would probably be most robust to catch and report
131946283Sdfr   * failed requests here.  However, some clients of this interface
132046283Sdfr   * seem to expect to catch & deal with them, so we'd best not.
132146283Sdfr   */
132298944Sobrien  if (errno)
132398944Sobrien    {
132498944Sobrien      strcpy (reason_for_failure, "ttrace (");
132598944Sobrien      strcat (reason_for_failure, get_printable_name_of_ttrace_request (request));
132698944Sobrien      strcat (reason_for_failure, ")");
132798944Sobrien      printf ("ttrace error, errno = %d\n", errno);
132898944Sobrien      perror_with_name (reason_for_failure);
132998944Sobrien    }
133046283Sdfr#endif
133146283Sdfr
133246283Sdfr  return tt_status;
133346283Sdfr}
133498944Sobrien
133546283Sdfr
133646283Sdfr/* This function simply calls ttrace_wait with the given arguments.
133746283Sdfr * It exists so that all calls to ttrace_wait are isolated.
133846283Sdfr *
133946283Sdfr * No "raw" calls to ttrace_wait should exist elsewhere.
134046283Sdfr */
134146283Sdfrstatic int
134298944Sobriencall_real_ttrace_wait (int pid, lwpid_t tid, ttwopt_t option, ttstate_t *tsp,
134398944Sobrien		       size_t tsp_size)
134446283Sdfr{
134598944Sobrien  int ttw_status;
134698944Sobrien  thread_info *tinfo = NULL;
134746283Sdfr
134846283Sdfr  errno = 0;
134946283Sdfr  ttw_status = ttrace_wait (pid, tid, option, tsp, tsp_size);
135098944Sobrien
135198944Sobrien  if (errno)
135298944Sobrien    {
135346283Sdfr#ifdef THREAD_DEBUG
135498944Sobrien      if (debug_on)
135598944Sobrien	printf ("TW fail with pid %d, tid %d \n", pid, tid);
135646283Sdfr#endif
135746283Sdfr
135846283Sdfr      perror_with_name ("ttrace wait");
135998944Sobrien    }
136046283Sdfr
136146283Sdfr  return ttw_status;
136246283Sdfr}
136398944Sobrien
136446283Sdfr
136546283Sdfr/* A process may have one or more kernel threads, of which all or
136646283Sdfr   none may be stopped.  This function returns the ID of the first
136746283Sdfr   kernel thread in a stopped state, or 0 if none are stopped.
136846283Sdfr
136946283Sdfr   This function can be used with get_process_next_stopped_thread_id
137046283Sdfr   to iterate over the IDs of all stopped threads of this process.
137146283Sdfr */
137246283Sdfrstatic lwpid_t
137398944Sobrienget_process_first_stopped_thread_id (int pid, ttstate_t *thread_state)
137446283Sdfr{
137598944Sobrien  int tt_status;
137646283Sdfr
137798944Sobrien  tt_status = call_real_ttrace (TT_PROC_GET_FIRST_LWP_STATE,
137898944Sobrien				(pid_t) pid,
137998944Sobrien				(lwpid_t) TT_NIL,
138098944Sobrien				(TTRACE_ARG_TYPE) thread_state,
138198944Sobrien				(TTRACE_ARG_TYPE) sizeof (*thread_state),
138298944Sobrien				TT_NIL);
138398944Sobrien
138498944Sobrien  if (errno)
138598944Sobrien    {
138698944Sobrien      if (errno == EPROTO)
138798944Sobrien	{
138898944Sobrien	  /* This is an error we can handle: there isn't any stopped
138998944Sobrien	   * thread.  This happens when we're re-starting the application
139098944Sobrien	   * and it has only one thread.  GET_NEXT handles the case of
139198944Sobrien	   * no more stopped threads well; GET_FIRST doesn't.  (A ttrace
139298944Sobrien	   * "feature".)
139398944Sobrien	   */
139498944Sobrien	  tt_status = 1;
139598944Sobrien	  errno = 0;
139698944Sobrien	  return 0;
139798944Sobrien	}
139898944Sobrien      else
139998944Sobrien	perror_with_name ("ttrace");
140046283Sdfr    }
140198944Sobrien
140298944Sobrien  if (tt_status < 0)
140346283Sdfr    /* Failed somehow.
140446283Sdfr     */
140546283Sdfr    return 0;
140646283Sdfr
140746283Sdfr  return thread_state->tts_lwpid;
140846283Sdfr}
140998944Sobrien
141046283Sdfr
141146283Sdfr/* This function returns the ID of the "next" kernel thread in a
141246283Sdfr   stopped state, or 0 if there are none.  "Next" refers to the
141346283Sdfr   thread following that of the last successful call to this
141446283Sdfr   function or to get_process_first_stopped_thread_id, using
141546283Sdfr   the value of thread_state returned by that call.
141646283Sdfr
141746283Sdfr   This function can be used with get_process_first_stopped_thread_id
141846283Sdfr   to iterate over the IDs of all stopped threads of this process.
141946283Sdfr */
142046283Sdfrstatic lwpid_t
142198944Sobrienget_process_next_stopped_thread_id (int pid, ttstate_t *thread_state)
142246283Sdfr{
142398944Sobrien  int tt_status;
142446283Sdfr
142546283Sdfr  tt_status = call_real_ttrace (
142698944Sobrien				 TT_PROC_GET_NEXT_LWP_STATE,
142798944Sobrien				 (pid_t) pid,
142898944Sobrien				 (lwpid_t) TT_NIL,
142998944Sobrien				 (TTRACE_ARG_TYPE) thread_state,
143098944Sobrien				 (TTRACE_ARG_TYPE) sizeof (*thread_state),
143198944Sobrien				 TT_NIL);
143246283Sdfr  if (errno)
143346283Sdfr    perror_with_name ("ttrace");
143446283Sdfr
143546283Sdfr  if (tt_status < 0)
143646283Sdfr    /* Failed
143746283Sdfr     */
143846283Sdfr    return 0;
143946283Sdfr
144098944Sobrien  else if (tt_status == 0)
144198944Sobrien    {
144298944Sobrien      /* End of list, no next state.  Don't return the
144398944Sobrien       * tts_lwpid, as it's a meaningless "240".
144498944Sobrien       *
144598944Sobrien       * This is an HPUX "feature".
144698944Sobrien       */
144798944Sobrien      return 0;
144898944Sobrien    }
144998944Sobrien
145046283Sdfr  return thread_state->tts_lwpid;
145146283Sdfr}
145246283Sdfr
145346283Sdfr/* ??rehrauer: Eventually this function perhaps should be calling
145446283Sdfr   pid_to_thread_id.  However, that function currently does nothing
145546283Sdfr   for HP-UX.  Even then, I'm not clear whether that function
145646283Sdfr   will return a "kernel" thread ID, or a "user" thread ID.  If
145746283Sdfr   the former, we can just call it here.  If the latter, we must
145846283Sdfr   map from the "user" tid to a "kernel" tid.
145946283Sdfr
146046283Sdfr   NOTE: currently not called.
146146283Sdfr */
146246283Sdfrstatic lwpid_t
146398944Sobrienget_active_tid_of_pid (int pid)
146446283Sdfr{
146598944Sobrien  ttstate_t thread_state;
146646283Sdfr
146746283Sdfr  return get_process_first_stopped_thread_id (pid, &thread_state);
146846283Sdfr}
146946283Sdfr
147046283Sdfr/* This function returns 1 if tt_request is a ttrace request that
147146283Sdfr * operates upon all threads of a (i.e., the entire) process.
147246283Sdfr */
147346283Sdfrint
147498944Sobrienis_process_ttrace_request (ttreq_t tt_request)
147546283Sdfr{
147646283Sdfr  return IS_TTRACE_PROCREQ (tt_request);
147746283Sdfr}
147898944Sobrien
147946283Sdfr
148046283Sdfr/* This function translates a thread ttrace request into
148146283Sdfr * the equivalent process request for a one-thread process.
148246283Sdfr */
148346283Sdfrstatic ttreq_t
148498944Sobrienmake_process_version (ttreq_t request)
148546283Sdfr{
148698944Sobrien  if (!IS_TTRACE_REQ (request))
148798944Sobrien    {
148898944Sobrien      error ("Internal error, bad ttrace request made\n");
148998944Sobrien      return -1;
149098944Sobrien    }
149146283Sdfr
149298944Sobrien  switch (request)
149398944Sobrien    {
149498944Sobrien    case TT_LWP_STOP:
149546283Sdfr      return TT_PROC_STOP;
149646283Sdfr
149798944Sobrien    case TT_LWP_CONTINUE:
149846283Sdfr      return TT_PROC_CONTINUE;
149946283Sdfr
150098944Sobrien    case TT_LWP_GET_EVENT_MASK:
150146283Sdfr      return TT_PROC_GET_EVENT_MASK;
150246283Sdfr
150398944Sobrien    case TT_LWP_SET_EVENT_MASK:
150446283Sdfr      return TT_PROC_SET_EVENT_MASK;
150546283Sdfr
150698944Sobrien    case TT_LWP_SINGLE:
150798944Sobrien    case TT_LWP_RUREGS:
150898944Sobrien    case TT_LWP_WUREGS:
150998944Sobrien    case TT_LWP_GET_STATE:
151098944Sobrien      return -1;		/* No equivalent */
151146283Sdfr
151298944Sobrien    default:
151346283Sdfr      return request;
151498944Sobrien    }
151546283Sdfr}
151698944Sobrien
151746283Sdfr
151846283Sdfr/* This function translates the "pid" used by the rest of
151946283Sdfr * gdb to a real pid and a tid.  It then calls "call_real_ttrace"
152046283Sdfr * with the given arguments.
152146283Sdfr *
152246283Sdfr * In general, other parts of this module should call this
152346283Sdfr * function when they are dealing with external users, who only
152446283Sdfr * have tids to pass (but they call it "pid" for historical
152546283Sdfr * reasons).
152646283Sdfr */
152746283Sdfrstatic int
152898944Sobriencall_ttrace (ttreq_t request, int gdb_tid, TTRACE_ARG_TYPE addr,
152998944Sobrien	     TTRACE_ARG_TYPE data, TTRACE_ARG_TYPE addr2)
153046283Sdfr{
153198944Sobrien  lwpid_t real_tid;
153298944Sobrien  int real_pid;
153398944Sobrien  ttreq_t new_request;
153498944Sobrien  int tt_status;
153598944Sobrien  char reason_for_failure[100];	/* Arbitrary size, should be big enough. */
153698944Sobrien
153746283Sdfr#ifdef THREAD_DEBUG
153898944Sobrien  int is_interesting = 0;
153946283Sdfr
154098944Sobrien  if (TT_LWP_RUREGS == request)
154198944Sobrien    {
154298944Sobrien      is_interesting = 1;	/* Adjust code here as desired */
154398944Sobrien    }
154498944Sobrien
154598944Sobrien  if (is_interesting && 0 && debug_on)
154698944Sobrien    {
154798944Sobrien      if (!is_process_ttrace_request (request))
154898944Sobrien	{
154998944Sobrien	  printf ("TT: Thread request, tid is %d", gdb_tid);
155098944Sobrien	  printf ("== SINGLE at %x", addr);
155198944Sobrien	}
155298944Sobrien      else
155398944Sobrien	{
155498944Sobrien	  printf ("TT: Process request, tid is %d\n", gdb_tid);
155598944Sobrien	  printf ("==! SINGLE at %x", addr);
155698944Sobrien	}
155798944Sobrien    }
155846283Sdfr#endif
155946283Sdfr
156046283Sdfr  /* The initial SETTRC and SET_EVENT_MASK calls (and all others
156146283Sdfr   * which happen before any threads get set up) should go
156246283Sdfr   * directly to "call_real_ttrace", so they don't happen here.
156346283Sdfr   *
156446283Sdfr   * But hardware watchpoints do a SET_EVENT_MASK, so we can't
156546283Sdfr   * rule them out....
156646283Sdfr   */
156746283Sdfr#ifdef THREAD_DEBUG
156898944Sobrien  if (request == TT_PROC_SETTRC && debug_on)
156998944Sobrien    printf ("Unexpected call for TT_PROC_SETTRC\n");
157046283Sdfr#endif
157146283Sdfr
157246283Sdfr  /* Sometimes we get called with a bogus tid (e.g., if a
157346283Sdfr   * thread has terminated, we return 0; inftarg later asks
157446283Sdfr   * whether the thread has exited/forked/vforked).
157546283Sdfr   */
157698944Sobrien  if (gdb_tid == 0)
157746283Sdfr    {
157898944Sobrien      errno = ESRCH;		/* ttrace's response would probably be "No such process". */
157946283Sdfr      return -1;
158046283Sdfr    }
158146283Sdfr
158246283Sdfr  /* All other cases should be able to expect that there are
158346283Sdfr   * thread records.
158446283Sdfr   */
158598944Sobrien  if (!any_thread_records ())
158698944Sobrien    {
158746283Sdfr#ifdef THREAD_DEBUG
158898944Sobrien      if (debug_on)
158998944Sobrien	warning ("No thread records for ttrace call");
159046283Sdfr#endif
159198944Sobrien      errno = ESRCH;		/* ttrace's response would be "No such process". */
159246283Sdfr      return -1;
159398944Sobrien    }
159446283Sdfr
159546283Sdfr  /* OK, now the task is to translate the incoming tid into
159646283Sdfr   * a pid/tid pair.
159746283Sdfr   */
159898944Sobrien  real_tid = map_from_gdb_tid (gdb_tid);
159998944Sobrien  real_pid = get_pid_for (real_tid);
160046283Sdfr
160146283Sdfr  /* Now check the result.  "Real_pid" is NULL if our list
160246283Sdfr   * didn't find it.  We have some tricks we can play to fix
160346283Sdfr   * this, however.
160446283Sdfr   */
160598944Sobrien  if (0 == real_pid)
160698944Sobrien    {
160798944Sobrien      ttstate_t thread_state;
160846283Sdfr
160946283Sdfr#ifdef THREAD_DEBUG
161098944Sobrien      if (debug_on)
161198944Sobrien	printf ("No saved pid for tid %d\n", gdb_tid);
161246283Sdfr#endif
161346283Sdfr
161498944Sobrien      if (is_process_ttrace_request (request))
161598944Sobrien	{
161698944Sobrien
161798944Sobrien	  /* Ok, we couldn't get a tid.  Try to translate to
161898944Sobrien	   * the equivalent process operation.  We expect this
161998944Sobrien	   * NOT to happen, so this is a desparation-type
162098944Sobrien	   * move.  It can happen if there is an internal
162198944Sobrien	   * error and so no "wait()" call is ever done.
162298944Sobrien	   */
162398944Sobrien	  new_request = make_process_version (request);
162498944Sobrien	  if (new_request == -1)
162598944Sobrien	    {
162698944Sobrien
162746283Sdfr#ifdef THREAD_DEBUG
162898944Sobrien	      if (debug_on)
162998944Sobrien		printf ("...and couldn't make process version of thread operation\n");
163046283Sdfr#endif
163146283Sdfr
163298944Sobrien	      /* Use hacky saved pid, which won't always be correct
163398944Sobrien	       * in the multi-process future.  Use tid as thread,
163498944Sobrien	       * probably dooming this to failure.  FIX!
163598944Sobrien	       */
163698944Sobrien	      if (! ptid_equal (saved_real_ptid, null_ptid))
163798944Sobrien		{
163846283Sdfr#ifdef THREAD_DEBUG
163998944Sobrien		  if (debug_on)
164098944Sobrien		    printf ("...using saved pid %d\n",
164198944Sobrien		            PIDGET (saved_real_ptid));
164246283Sdfr#endif
164346283Sdfr
164498944Sobrien		  real_pid = PIDGET (saved_real_ptid);
164598944Sobrien		  real_tid = gdb_tid;
164698944Sobrien		}
164746283Sdfr
164898944Sobrien	      else
164998944Sobrien		error ("Unable to perform thread operation");
165098944Sobrien	    }
165146283Sdfr
165298944Sobrien	  else
165398944Sobrien	    {
165498944Sobrien	      /* Sucessfully translated this to a process request,
165598944Sobrien	       * which needs no thread value.
165698944Sobrien	       */
165798944Sobrien	      real_pid = gdb_tid;
165898944Sobrien	      real_tid = 0;
165998944Sobrien	      request = new_request;
166046283Sdfr
166146283Sdfr#ifdef THREAD_DEBUG
166298944Sobrien	      if (debug_on)
166398944Sobrien		{
166498944Sobrien		  printf ("Translated thread request to process request\n");
166598944Sobrien		  if (ptid_equal (saved_real_ptid, null_ptid))
166698944Sobrien		    printf ("...but there's no saved pid\n");
166798944Sobrien
166898944Sobrien		  else
166998944Sobrien		    {
167098944Sobrien		      if (gdb_tid != PIDGET (saved_real_ptid))
167198944Sobrien			printf ("...but have the wrong pid (%d rather than %d)\n",
167298944Sobrien				gdb_tid, PIDGET (saved_real_ptid));
167398944Sobrien		    }
167498944Sobrien		}
167546283Sdfr#endif
167698944Sobrien	    }			/* Translated to a process request */
167798944Sobrien	}			/* Is a process request */
167846283Sdfr
167998944Sobrien      else
168098944Sobrien	{
168198944Sobrien	  /* We have to have a thread.  Ooops.
168298944Sobrien	   */
168398944Sobrien	  error ("Thread request with no threads (%s)",
168498944Sobrien		 get_printable_name_of_ttrace_request (request));
168598944Sobrien	}
168646283Sdfr    }
168746283Sdfr
168846283Sdfr  /* Ttrace doesn't like to see tid values on process requests,
168946283Sdfr   * even if we have the right one.
169046283Sdfr   */
169198944Sobrien  if (is_process_ttrace_request (request))
169298944Sobrien    {
169346283Sdfr      real_tid = 0;
169498944Sobrien    }
169598944Sobrien
169646283Sdfr#ifdef THREAD_DEBUG
169798944Sobrien  if (is_interesting && 0 && debug_on)
169898944Sobrien    {
169998944Sobrien      printf ("    now tid %d, pid %d\n", real_tid, real_pid);
170098944Sobrien      printf ("    request is %s\n", get_printable_name_of_ttrace_request (request));
170198944Sobrien    }
170246283Sdfr#endif
170346283Sdfr
170446283Sdfr  /* Finally, the (almost) real call.
170546283Sdfr   */
170646283Sdfr  tt_status = call_real_ttrace (request, real_pid, real_tid, addr, data, addr2);
170746283Sdfr
170846283Sdfr#ifdef THREAD_DEBUG
170998944Sobrien  if (is_interesting && debug_on)
171098944Sobrien    {
171198944Sobrien      if (!TT_OK (tt_status, errno)
171298944Sobrien	  && !(tt_status == 0 & errno == 0))
171398944Sobrien	printf (" got error (errno==%d, status==%d)\n", errno, tt_status);
171498944Sobrien    }
171546283Sdfr#endif
171646283Sdfr
171746283Sdfr  return tt_status;
171846283Sdfr}
171946283Sdfr
172046283Sdfr
172146283Sdfr/* Stop all the threads of a process.
172298944Sobrien
172346283Sdfr * NOTE: use of TT_PROC_STOP can cause a thread with a real event
172446283Sdfr *       to get a TTEVT_NONE event, discarding the old event.  Be
172546283Sdfr *       very careful, and only call TT_PROC_STOP when you mean it!
172646283Sdfr */
172746283Sdfrstatic void
172898944Sobrienstop_all_threads_of_process (pid_t real_pid)
172946283Sdfr{
173098944Sobrien  int ttw_status;
173146283Sdfr
173246283Sdfr  ttw_status = call_real_ttrace (TT_PROC_STOP,
173398944Sobrien				 (pid_t) real_pid,
173498944Sobrien				 (lwpid_t) TT_NIL,
173598944Sobrien				 (TTRACE_ARG_TYPE) TT_NIL,
173698944Sobrien				 (TTRACE_ARG_TYPE) TT_NIL,
173798944Sobrien				 TT_NIL);
173846283Sdfr  if (errno)
173946283Sdfr    perror_with_name ("ttrace stop of other threads");
174046283Sdfr}
174146283Sdfr
174246283Sdfr
174346283Sdfr/* Under some circumstances, it's unsafe to attempt to stop, or even
174446283Sdfr   query the state of, a process' threads.
174546283Sdfr
174646283Sdfr   In ttrace-based HP-UX, an example is a vforking child process.  The
174746283Sdfr   vforking parent and child are somewhat fragile, w/r/t what we can do
174846283Sdfr   what we can do to them with ttrace, until after the child exits or
174946283Sdfr   execs, or until the parent's vfork event is delivered.  Until that
175046283Sdfr   time, we must not try to stop the process' threads, or inquire how
175146283Sdfr   many there are, or even alter its data segments, or it typically dies
175246283Sdfr   with a SIGILL.  Sigh.
175346283Sdfr
175446283Sdfr   This function returns 1 if this stopped process, and the event that
175546283Sdfr   we're told was responsible for its current stopped state, cannot safely
175646283Sdfr   have its threads examined.
175798944Sobrien */
175846283Sdfr#define CHILD_VFORKED(evt,pid) \
175998944Sobrien  (((evt) == TTEVT_VFORK) && ((pid) != PIDGET (inferior_ptid)))
176046283Sdfr#define CHILD_URPED(evt,pid) \
176146283Sdfr  ((((evt) == TTEVT_EXEC) || ((evt) == TTEVT_EXIT)) && ((pid) != vforking_child_pid))
176246283Sdfr#define PARENT_VFORKED(evt,pid) \
176398944Sobrien  (((evt) == TTEVT_VFORK) && ((pid) == PIDGET (inferior_ptid)))
176446283Sdfr
176546283Sdfrstatic int
176698944Sobriencan_touch_threads_of_process (int pid, ttevents_t stopping_event)
176746283Sdfr{
176846283Sdfr  if (CHILD_VFORKED (stopping_event, pid))
176946283Sdfr    {
177046283Sdfr      vforking_child_pid = pid;
177146283Sdfr      vfork_in_flight = 1;
177246283Sdfr    }
177346283Sdfr
177446283Sdfr  else if (vfork_in_flight &&
177598944Sobrien	   (PARENT_VFORKED (stopping_event, pid) ||
177698944Sobrien	    CHILD_URPED (stopping_event, pid)))
177746283Sdfr    {
177846283Sdfr      vfork_in_flight = 0;
177946283Sdfr      vforking_child_pid = 0;
178046283Sdfr    }
178146283Sdfr
178298944Sobrien  return !vfork_in_flight;
178346283Sdfr}
178446283Sdfr
178546283Sdfr
178646283Sdfr/* If we can find an as-yet-unhandled thread state of a
178746283Sdfr * stopped thread of this process return 1 and set "tsp".
178846283Sdfr * Return 0 if we can't.
178946283Sdfr *
179046283Sdfr * If this function is used when the threads of PIS haven't
179146283Sdfr * been stopped, undefined behaviour is guaranteed!
179246283Sdfr */
179398944Sobrienstatic int
179498944Sobrienselect_stopped_thread_of_process (int pid, ttstate_t *tsp)
179546283Sdfr{
179698944Sobrien  lwpid_t candidate_tid, tid;
179798944Sobrien  ttstate_t candidate_tstate, tstate;
179846283Sdfr
179946283Sdfr  /* If we're not allowed to touch the process now, then just
180046283Sdfr   * return the current value of *TSP.
180146283Sdfr   *
180246283Sdfr   * This supports "vfork".  It's ok, really, to double the
180346283Sdfr   * current event (the child EXEC, we hope!).
180446283Sdfr   */
180598944Sobrien  if (!can_touch_threads_of_process (pid, tsp->tts_event))
180646283Sdfr    return 1;
180746283Sdfr
180846283Sdfr  /* Decide which of (possibly more than one) events to
180946283Sdfr   * return as the first one.  We scan them all so that
181046283Sdfr   * we always return the result of a fake-step first.
181146283Sdfr   */
181246283Sdfr  candidate_tid = 0;
181346283Sdfr  for (tid = get_process_first_stopped_thread_id (pid, &tstate);
181446283Sdfr       tid != 0;
181546283Sdfr       tid = get_process_next_stopped_thread_id (pid, &tstate))
181646283Sdfr    {
181746283Sdfr      /* TTEVT_NONE events are uninteresting to our clients.  They're
181846283Sdfr       * an artifact of our "stop the world" model--the thread is
181946283Sdfr       * stopped because we stopped it.
182046283Sdfr       */
182198944Sobrien      if (tstate.tts_event == TTEVT_NONE)
182298944Sobrien	{
182398944Sobrien	  set_handled (pid, tstate.tts_lwpid);
182498944Sobrien	}
182546283Sdfr
182646283Sdfr      /* Did we just single-step a single thread, without letting any
182746283Sdfr       * of the others run?  Is this an event for that thread?
182846283Sdfr       *
182946283Sdfr       * If so, we believe our client would prefer to see this event
183046283Sdfr       * over any others.  (Typically the client wants to just push
183146283Sdfr       * one thread a little farther forward, and then go around
183246283Sdfr       * checking for what all threads are doing.)
183346283Sdfr       */
183446283Sdfr      else if (doing_fake_step && (tstate.tts_lwpid == fake_step_tid))
183598944Sobrien	{
183646283Sdfr#ifdef WAIT_BUFFER_DEBUG
183798944Sobrien	  /* It's possible here to see either a SIGTRAP (due to
183898944Sobrien	   * successful completion of a step) or a SYSCALL_ENTRY
183998944Sobrien	   * (due to a step completion with active hardware
184098944Sobrien	   * watchpoints).
184198944Sobrien	   */
184298944Sobrien	  if (debug_on)
184398944Sobrien	    printf ("Ending fake step with tid %d, state %s\n",
184498944Sobrien		    tstate.tts_lwpid,
184598944Sobrien		    get_printable_name_of_ttrace_event (tstate.tts_event));
184698944Sobrien#endif
184746283Sdfr
184898944Sobrien	  /* Remember this one, and throw away any previous
184998944Sobrien	   * candidate.
185098944Sobrien	   */
185198944Sobrien	  candidate_tid = tstate.tts_lwpid;
185298944Sobrien	  candidate_tstate = tstate;
185398944Sobrien	}
185446283Sdfr
185546283Sdfr#ifdef FORGET_DELETED_BPTS
185646283Sdfr
185746283Sdfr      /* We can't just do this, as if we do, and then wind
185846283Sdfr       * up the loop with no unhandled events, we need to
185946283Sdfr       * handle that case--the appropriate reaction is to
186046283Sdfr       * just continue, but there's no easy way to do that.
186146283Sdfr       *
186246283Sdfr       * Better to put this in the ttrace_wait call--if, when
186346283Sdfr       * we fake a wait, we update our events based on the
186446283Sdfr       * breakpoint_here_pc call and find there are no more events,
186546283Sdfr       * then we better continue and so on.
186646283Sdfr       *
186746283Sdfr       * Or we could put it in the next/continue fake.
186846283Sdfr       * But it has to go in the buffering code, not in the
186946283Sdfr       * real go/wait code.
187046283Sdfr       */
187198944Sobrien      else if ((TTEVT_SIGNAL == tstate.tts_event)
187298944Sobrien	       && (5 == tstate.tts_u.tts_signal.tts_signo)
187398944Sobrien	       && (0 != get_raw_pc (tstate.tts_lwpid))
187498944Sobrien	       && !breakpoint_here_p (get_raw_pc (tstate.tts_lwpid)))
187598944Sobrien	{
187698944Sobrien	  /*
187798944Sobrien	   * If the user deleted a breakpoint while this
187898944Sobrien	   * breakpoint-hit event was buffered, we can forget
187998944Sobrien	   * it now.
188098944Sobrien	   */
188146283Sdfr#ifdef WAIT_BUFFER_DEBUG
188298944Sobrien	  if (debug_on)
188398944Sobrien	    printf ("Forgetting deleted bp hit for thread %d\n",
188498944Sobrien		    tstate.tts_lwpid);
188598944Sobrien#endif
188646283Sdfr
188798944Sobrien	  set_handled (pid, tstate.tts_lwpid);
188898944Sobrien	}
188946283Sdfr#endif
189046283Sdfr
189146283Sdfr      /* Else, is this the first "unhandled" event?  If so,
189246283Sdfr       * we believe our client wants to see it (if we don't
189346283Sdfr       * see a fake-step later on in the scan).
189446283Sdfr       */
189598944Sobrien      else if (!was_handled (tstate.tts_lwpid) && candidate_tid == 0)
189698944Sobrien	{
189798944Sobrien	  candidate_tid = tstate.tts_lwpid;
189898944Sobrien	  candidate_tstate = tstate;
189998944Sobrien	}
190046283Sdfr
190146283Sdfr      /* This is either an event that has already been "handled",
190246283Sdfr       * and thus we believe is uninteresting to our client, or we
190346283Sdfr       * already have a candidate event.  Ignore it...
190446283Sdfr       */
190546283Sdfr    }
190646283Sdfr
190746283Sdfr  /* What do we report?
190846283Sdfr   */
190998944Sobrien  if (doing_fake_step)
191098944Sobrien    {
191198944Sobrien      if (candidate_tid == fake_step_tid)
191298944Sobrien	{
191398944Sobrien	  /* Fake step.
191498944Sobrien	   */
191598944Sobrien	  tstate = candidate_tstate;
191698944Sobrien	}
191798944Sobrien      else
191898944Sobrien	{
191998944Sobrien	  warning ("Internal error: fake-step failed to complete.");
192098944Sobrien	  return 0;
192198944Sobrien	}
192298944Sobrien    }
192398944Sobrien  else if (candidate_tid != 0)
192498944Sobrien    {
192546283Sdfr      /* Found a candidate unhandled event.
192646283Sdfr       */
192746283Sdfr      tstate = candidate_tstate;
192898944Sobrien    }
192998944Sobrien  else if (tid != 0)
193098944Sobrien    {
193198944Sobrien      warning ("Internal error in call of ttrace_wait.");
193246283Sdfr      return 0;
193398944Sobrien    }
193498944Sobrien  else
193598944Sobrien    {
193646283Sdfr      warning ("Internal error: no unhandled thread event to select");
193746283Sdfr      return 0;
193898944Sobrien    }
193946283Sdfr
194046283Sdfr  copy_ttstate_t (tsp, &tstate);
194146283Sdfr  return 1;
194298944Sobrien}				/* End of select_stopped_thread_of_process */
194346283Sdfr
194446283Sdfr#ifdef PARANOIA
194546283Sdfr/* Check our internal thread data against the real thing.
194646283Sdfr */
194746283Sdfrstatic void
194898944Sobriencheck_thread_consistency (pid_t real_pid)
194946283Sdfr{
195098944Sobrien  int tid;			/* really lwpid_t */
195198944Sobrien  ttstate_t tstate;
195298944Sobrien  thread_info *p;
195346283Sdfr
195498944Sobrien  /* Spin down the O/S list of threads, checking that they
195598944Sobrien   * match what we've got.
195698944Sobrien   */
195798944Sobrien  for (tid = get_process_first_stopped_thread_id (real_pid, &tstate);
195898944Sobrien       tid != 0;
195998944Sobrien       tid = get_process_next_stopped_thread_id (real_pid, &tstate))
196098944Sobrien    {
196146283Sdfr
196298944Sobrien      p = find_thread_info (tid);
196346283Sdfr
196498944Sobrien      if (NULL == p)
196598944Sobrien	{
196698944Sobrien	  warning ("No internal thread data for thread %d.", tid);
196798944Sobrien	  continue;
196898944Sobrien	}
196946283Sdfr
197098944Sobrien      if (!p->seen)
197198944Sobrien	{
197298944Sobrien	  warning ("Inconsistent internal thread data for thread %d.", tid);
197398944Sobrien	}
197446283Sdfr
197598944Sobrien      if (p->terminated)
197698944Sobrien	{
197798944Sobrien	  warning ("Thread %d is not terminated, internal error.", tid);
197898944Sobrien	  continue;
197998944Sobrien	}
198098944Sobrien
198198944Sobrien
198246283Sdfr#define TT_COMPARE( fld ) \
198346283Sdfr            tstate.fld != p->last_stop_state.fld
198498944Sobrien
198598944Sobrien      if (p->have_state)
198698944Sobrien	{
198798944Sobrien	  if (TT_COMPARE (tts_pid)
198898944Sobrien	      || TT_COMPARE (tts_lwpid)
198998944Sobrien	      || TT_COMPARE (tts_user_tid)
199098944Sobrien	      || TT_COMPARE (tts_event)
199198944Sobrien	      || TT_COMPARE (tts_flags)
199298944Sobrien	      || TT_COMPARE (tts_scno)
199398944Sobrien	      || TT_COMPARE (tts_scnargs))
199498944Sobrien	    {
199598944Sobrien	      warning ("Internal thread data for thread %d is wrong.", tid);
199698944Sobrien	      continue;
199798944Sobrien	    }
199898944Sobrien	}
199946283Sdfr    }
200046283Sdfr}
200198944Sobrien#endif /* PARANOIA */
200298944Sobrien
200346283Sdfr
200446283Sdfr/* This function wraps calls to "call_real_ttrace_wait" so
200546283Sdfr * that a actual wait is only done when all pending events
200646283Sdfr * have been reported.
200746283Sdfr *
200846283Sdfr * Note that typically it is called with a pid of "0", i.e.
200946283Sdfr * the "don't care" value.
201046283Sdfr *
201146283Sdfr * Return value is the status of the pseudo wait.
201246283Sdfr */
201346283Sdfrstatic int
201498944Sobriencall_ttrace_wait (int pid, ttwopt_t option, ttstate_t *tsp, size_t tsp_size)
201546283Sdfr{
201646283Sdfr  /* This holds the actual, for-real, true process ID.
201746283Sdfr   */
201846283Sdfr  static int real_pid;
201946283Sdfr
202046283Sdfr  /* As an argument to ttrace_wait, zero pid
202146283Sdfr   * means "Any process", and zero tid means
202246283Sdfr   * "Any thread of the specified process".
202346283Sdfr   */
202498944Sobrien  int wait_pid = 0;
202598944Sobrien  lwpid_t wait_tid = 0;
202698944Sobrien  lwpid_t real_tid;
202746283Sdfr
202898944Sobrien  int ttw_status = 0;		/* To be returned */
202946283Sdfr
203098944Sobrien  thread_info *tinfo = NULL;
203146283Sdfr
203298944Sobrien  if (pid != 0)
203398944Sobrien    {
203446283Sdfr      /* Unexpected case.
203546283Sdfr       */
203646283Sdfr#ifdef THREAD_DEBUG
203798944Sobrien      if (debug_on)
203898944Sobrien	printf ("TW: Pid to wait on is %d\n", pid);
203946283Sdfr#endif
204046283Sdfr
204198944Sobrien      if (!any_thread_records ())
204298944Sobrien	error ("No thread records for ttrace call w. specific pid");
204346283Sdfr
204446283Sdfr      /* OK, now the task is to translate the incoming tid into
204546283Sdfr       * a pid/tid pair.
204646283Sdfr       */
204798944Sobrien      real_tid = map_from_gdb_tid (pid);
204898944Sobrien      real_pid = get_pid_for (real_tid);
204946283Sdfr#ifdef THREAD_DEBUG
205098944Sobrien      if (debug_on)
205198944Sobrien	printf ("==TW: real pid %d, real tid %d\n", real_pid, real_tid);
205246283Sdfr#endif
205398944Sobrien    }
205446283Sdfr
205546283Sdfr
205646283Sdfr  /* Sanity checks and set-up.
205746283Sdfr   *                             Process State
205846283Sdfr   *
205946283Sdfr   *                        Stopped   Running    Fake-step  (v)Fork
206046283Sdfr   *                      \________________________________________
206146283Sdfr   *                      |
206246283Sdfr   *  No buffered events  |  error     wait       wait      wait
206346283Sdfr   *                      |
206446283Sdfr   *  Buffered events     |  debuffer  error      wait      debuffer (?)
206546283Sdfr   *
206646283Sdfr   */
206798944Sobrien  if (more_events_left == 0)
206898944Sobrien    {
206946283Sdfr
207098944Sobrien      if (process_state == RUNNING)
207198944Sobrien	{
207298944Sobrien	  /* OK--normal call of ttrace_wait with no buffered events.
207398944Sobrien	   */
207498944Sobrien	  ;
207598944Sobrien	}
207698944Sobrien      else if (process_state == FAKE_STEPPING)
207798944Sobrien	{
207898944Sobrien	  /* Ok--call of ttrace_wait to support
207998944Sobrien	   * fake stepping with no buffered events.
208098944Sobrien	   *
208198944Sobrien	   * But we better be fake-stepping!
208298944Sobrien	   */
208398944Sobrien	  if (!doing_fake_step)
208498944Sobrien	    {
208598944Sobrien	      warning ("Inconsistent thread state.");
208698944Sobrien	    }
208798944Sobrien	}
208898944Sobrien      else if ((process_state == FORKING)
208998944Sobrien	       || (process_state == VFORKING))
209098944Sobrien	{
209198944Sobrien	  /* Ok--there are two processes, so waiting
209298944Sobrien	   * for the second while the first is stopped
209398944Sobrien	   * is ok.  Handled bits stay as they were.
209498944Sobrien	   */
209598944Sobrien	  ;
209698944Sobrien	}
209798944Sobrien      else if (process_state == STOPPED)
209898944Sobrien	{
209998944Sobrien	  warning ("Process not running at wait call.");
210098944Sobrien	}
210146283Sdfr      else
210298944Sobrien	/* No known state.
210398944Sobrien	 */
210498944Sobrien	warning ("Inconsistent process state.");
210598944Sobrien    }
210698944Sobrien
210798944Sobrien  else
210898944Sobrien    {
210946283Sdfr      /* More events left
211046283Sdfr       */
211198944Sobrien      if (process_state == STOPPED)
211298944Sobrien	{
211398944Sobrien	  /* OK--buffered events being unbuffered.
211498944Sobrien	   */
211598944Sobrien	  ;
211698944Sobrien	}
211798944Sobrien      else if (process_state == RUNNING)
211898944Sobrien	{
211998944Sobrien	  /* An error--shouldn't have buffered events
212098944Sobrien	   * when running.
212198944Sobrien	   */
212298944Sobrien	  warning ("Trying to continue with buffered events:");
212398944Sobrien	}
212498944Sobrien      else if (process_state == FAKE_STEPPING)
212598944Sobrien	{
212698944Sobrien	  /*
212798944Sobrien	   * Better be fake-stepping!
212898944Sobrien	   */
212998944Sobrien	  if (!doing_fake_step)
213098944Sobrien	    {
213198944Sobrien	      warning ("Losing buffered thread events!\n");
213298944Sobrien	    }
213398944Sobrien	}
213498944Sobrien      else if ((process_state == FORKING)
213598944Sobrien	       || (process_state == VFORKING))
213698944Sobrien	{
213798944Sobrien	  /* Ok--there are two processes, so waiting
213898944Sobrien	   * for the second while the first is stopped
213998944Sobrien	   * is ok.  Handled bits stay as they were.
214098944Sobrien	   */
214198944Sobrien	  ;
214298944Sobrien	}
214346283Sdfr      else
214498944Sobrien	warning ("Process in unknown state with buffered events.");
214598944Sobrien    }
214646283Sdfr
214746283Sdfr  /* Sometimes we have to wait for a particular thread
214846283Sdfr   * (if we're stepping over a bpt).  In that case, we
214946283Sdfr   * _know_ it's going to complete the single-step we
215046283Sdfr   * asked for (because we're only doing the step under
215146283Sdfr   * certain very well-understood circumstances), so it
215246283Sdfr   * can't block.
215346283Sdfr   */
215498944Sobrien  if (doing_fake_step)
215598944Sobrien    {
215646283Sdfr      wait_tid = fake_step_tid;
215798944Sobrien      wait_pid = get_pid_for (fake_step_tid);
215846283Sdfr
215946283Sdfr#ifdef WAIT_BUFFER_DEBUG
216098944Sobrien      if (debug_on)
216198944Sobrien	printf ("Doing a wait after a fake-step for %d, pid %d\n",
216298944Sobrien		wait_tid, wait_pid);
216346283Sdfr#endif
216498944Sobrien    }
216546283Sdfr
216698944Sobrien  if (more_events_left == 0	/* No buffered events, need real ones. */
216798944Sobrien      || process_state != STOPPED)
216898944Sobrien    {
216946283Sdfr      /* If there are no buffered events, and so we need
217046283Sdfr       * real ones, or if we are FORKING, VFORKING,
217146283Sdfr       * FAKE_STEPPING or RUNNING, and thus have to do
217246283Sdfr       * a real wait, then do a real wait.
217346283Sdfr       */
217446283Sdfr
217546283Sdfr#ifdef WAIT_BUFFER_DEBUG
217646283Sdfr      /* Normal case... */
217798944Sobrien      if (debug_on)
217898944Sobrien	printf ("TW: do it for real; pid %d, tid %d\n", wait_pid, wait_tid);
217946283Sdfr#endif
218046283Sdfr
218146283Sdfr      /* The actual wait call.
218246283Sdfr       */
218398944Sobrien      ttw_status = call_real_ttrace_wait (wait_pid, wait_tid, option, tsp, tsp_size);
218446283Sdfr
218546283Sdfr      /* Note that the routines we'll call will be using "call_real_ttrace",
218646283Sdfr       * not "call_ttrace", and thus need the real pid rather than the pseudo-tid
218746283Sdfr       * the rest of the world uses (which is actually the tid).
218846283Sdfr       */
218946283Sdfr      real_pid = tsp->tts_pid;
219046283Sdfr
219146283Sdfr      /* For most events: Stop the world!
219298944Sobrien
219346283Sdfr       * It's sometimes not safe to stop all threads of a process.
219446283Sdfr       * Sometimes it's not even safe to ask for the thread state
219546283Sdfr       * of a process!
219646283Sdfr       */
219746283Sdfr      if (can_touch_threads_of_process (real_pid, tsp->tts_event))
219898944Sobrien	{
219998944Sobrien	  /* If we're really only stepping a single thread, then don't
220098944Sobrien	   * try to stop all the others -- we only do this single-stepping
220198944Sobrien	   * business when all others were already stopped...and the stop
220298944Sobrien	   * would mess up other threads' events.
220398944Sobrien	   *
220498944Sobrien	   * Similiarly, if there are other threads with events,
220598944Sobrien	   * don't do the stop.
220698944Sobrien	   */
220798944Sobrien	  if (!doing_fake_step)
220898944Sobrien	    {
220998944Sobrien	      if (more_events_left > 0)
221098944Sobrien		warning ("Internal error in stopping process");
221146283Sdfr
221298944Sobrien	      stop_all_threads_of_process (real_pid);
221398944Sobrien
221498944Sobrien	      /* At this point, we could scan and update_thread_list(),
221598944Sobrien	       * and only use the local list for the rest of the
221698944Sobrien	       * module! We'd get rid of the scans in the various
221798944Sobrien	       * continue routines (adding one in attach).  It'd
221898944Sobrien	       * be great--UPGRADE ME!
221998944Sobrien	       */
222098944Sobrien	    }
222198944Sobrien	}
222298944Sobrien
222346283Sdfr#ifdef PARANOIA
222498944Sobrien      else if (debug_on)
222598944Sobrien	{
222698944Sobrien	  if (more_events_left > 0)
222798944Sobrien	    printf ("== Can't stop process; more events!\n");
222898944Sobrien	  else
222998944Sobrien	    printf ("== Can't stop process!\n");
223098944Sobrien	}
223146283Sdfr#endif
223246283Sdfr
223398944Sobrien      process_state = STOPPED;
223446283Sdfr
223546283Sdfr#ifdef WAIT_BUFFER_DEBUG
223698944Sobrien      if (debug_on)
223798944Sobrien	printf ("Process set to STOPPED\n");
223846283Sdfr#endif
223998944Sobrien    }
224098944Sobrien
224198944Sobrien  else
224298944Sobrien    {
224346283Sdfr      /* Fake a call to ttrace_wait.  The process must be
224446283Sdfr       * STOPPED, as we aren't going to do any wait.
224546283Sdfr       */
224646283Sdfr#ifdef WAIT_BUFFER_DEBUG
224798944Sobrien      if (debug_on)
224898944Sobrien	printf ("TW: fake it\n");
224946283Sdfr#endif
225046283Sdfr
225198944Sobrien      if (process_state != STOPPED)
225298944Sobrien	{
225398944Sobrien	  warning ("Process not stopped at wait call, in state '%s'.\n",
225498944Sobrien		   get_printable_name_of_process_state (process_state));
225598944Sobrien	}
225646283Sdfr
225798944Sobrien      if (doing_fake_step)
225898944Sobrien	error ("Internal error in stepping over breakpoint");
225946283Sdfr
226098944Sobrien      ttw_status = 0;		/* Faking it is always successful! */
226198944Sobrien    }				/* End of fake or not? if */
226298944Sobrien
226346283Sdfr  /* Pick an event to pass to our caller.  Be paranoid.
226446283Sdfr   */
226598944Sobrien  if (!select_stopped_thread_of_process (real_pid, tsp))
226698944Sobrien    warning ("Can't find event, using previous event.");
226746283Sdfr
226898944Sobrien  else if (tsp->tts_event == TTEVT_NONE)
226998944Sobrien    warning ("Internal error: no thread has a real event.");
227046283Sdfr
227198944Sobrien  else if (doing_fake_step)
227298944Sobrien    {
227398944Sobrien      if (fake_step_tid != tsp->tts_lwpid)
227498944Sobrien	warning ("Internal error in stepping over breakpoint.");
227598944Sobrien
227646283Sdfr      /* This wait clears the (current) fake-step if there was one.
227746283Sdfr       */
227846283Sdfr      doing_fake_step = 0;
227998944Sobrien      fake_step_tid = 0;
228098944Sobrien    }
228146283Sdfr
228246283Sdfr  /* We now have a correct tsp and ttw_status for the thread
228346283Sdfr   * which we want to report.  So it's "handled"!  This call
228446283Sdfr   * will add it to our list if it's not there already.
228546283Sdfr   */
228698944Sobrien  set_handled (real_pid, tsp->tts_lwpid);
228746283Sdfr
228846283Sdfr  /* Save a copy of the ttrace state of this thread, in our local
228946283Sdfr     thread descriptor.
229046283Sdfr
229146283Sdfr     This caches the state.  The implementation of queries like
229246283Sdfr     target_has_execd can then use this cached state, rather than
229346283Sdfr     be forced to make an explicit ttrace call to get it.
229446283Sdfr
229546283Sdfr     (Guard against the condition that this is the first time we've
229646283Sdfr     waited on, i.e., seen this thread, and so haven't yet entered
229746283Sdfr     it into our list of threads.)
229846283Sdfr   */
229946283Sdfr  tinfo = find_thread_info (tsp->tts_lwpid);
230098944Sobrien  if (tinfo != NULL)
230198944Sobrien    {
230298944Sobrien      copy_ttstate_t (&tinfo->last_stop_state, tsp);
230398944Sobrien      tinfo->have_state = 1;
230498944Sobrien    }
230598944Sobrien
230646283Sdfr  return ttw_status;
230798944Sobrien}				/* call_ttrace_wait */
230846283Sdfr
230946283Sdfr#if defined(CHILD_REPORTED_EXEC_EVENTS_PER_EXEC_CALL)
231046283Sdfrint
231198944Sobrienchild_reported_exec_events_per_exec_call (void)
231246283Sdfr{
231398944Sobrien  return 1;			/* ttrace reports the event once per call. */
231446283Sdfr}
231546283Sdfr#endif
231698944Sobrien
231746283Sdfr
231846283Sdfr
231946283Sdfr/* Our implementation of hardware watchpoints involves making memory
232046283Sdfr   pages write-protected.  We must remember a page's original permissions,
232146283Sdfr   and we must also know when it is appropriate to restore a page's
232246283Sdfr   permissions to its original state.
232346283Sdfr
232446283Sdfr   We use a "dictionary" of hardware-watched pages to do this.  Each
232546283Sdfr   hardware-watched page is recorded in the dictionary.  Each page's
232646283Sdfr   dictionary entry contains the original permissions and a reference
232746283Sdfr   count.  Pages are hashed into the dictionary by their start address.
232846283Sdfr
232946283Sdfr   When hardware watchpoint is set on page X for the first time, page X
233046283Sdfr   is added to the dictionary with a reference count of 1.  If other
233146283Sdfr   hardware watchpoints are subsequently set on page X, its reference
233246283Sdfr   count is incremented.  When hardware watchpoints are removed from
233346283Sdfr   page X, its reference count is decremented.  If a page's reference
233446283Sdfr   count drops to 0, it's permissions are restored and the page's entry
233546283Sdfr   is thrown out of the dictionary.
233698944Sobrien */
233798944Sobrientypedef struct memory_page
233898944Sobrien{
233998944Sobrien  CORE_ADDR page_start;
234098944Sobrien  int reference_count;
234198944Sobrien  int original_permissions;
234298944Sobrien  struct memory_page *next;
234398944Sobrien  struct memory_page *previous;
234498944Sobrien}
234598944Sobrienmemory_page_t;
234646283Sdfr
234746283Sdfr#define MEMORY_PAGE_DICTIONARY_BUCKET_COUNT  128
234846283Sdfr
234998944Sobrienstatic struct
235098944Sobrien  {
235198944Sobrien    LONGEST page_count;
235298944Sobrien    int page_size;
235398944Sobrien    int page_protections_allowed;
235498944Sobrien    /* These are just the heads of chains of actual page descriptors. */
235598944Sobrien    memory_page_t buckets[MEMORY_PAGE_DICTIONARY_BUCKET_COUNT];
235698944Sobrien  }
235798944Sobrienmemory_page_dictionary;
235846283Sdfr
235946283Sdfr
236046283Sdfrstatic void
236198944Sobrienrequire_memory_page_dictionary (void)
236246283Sdfr{
236398944Sobrien  int i;
236446283Sdfr
236546283Sdfr  /* Is the memory page dictionary ready for use?  If so, we're done. */
236646283Sdfr  if (memory_page_dictionary.page_count >= (LONGEST) 0)
236746283Sdfr    return;
236846283Sdfr
236946283Sdfr  /* Else, initialize it. */
237046283Sdfr  memory_page_dictionary.page_count = (LONGEST) 0;
237146283Sdfr
237298944Sobrien  for (i = 0; i < MEMORY_PAGE_DICTIONARY_BUCKET_COUNT; i++)
237346283Sdfr    {
237446283Sdfr      memory_page_dictionary.buckets[i].page_start = (CORE_ADDR) 0;
237546283Sdfr      memory_page_dictionary.buckets[i].reference_count = 0;
237646283Sdfr      memory_page_dictionary.buckets[i].next = NULL;
237746283Sdfr      memory_page_dictionary.buckets[i].previous = NULL;
237846283Sdfr    }
237946283Sdfr}
238046283Sdfr
238146283Sdfr
238246283Sdfrstatic void
238398944Sobrienretire_memory_page_dictionary (void)
238446283Sdfr{
238598944Sobrien  memory_page_dictionary.page_count = (LONGEST) - 1;
238646283Sdfr}
238746283Sdfr
238846283Sdfr
238946283Sdfr/* Write-protect the memory page that starts at this address.
239046283Sdfr
239146283Sdfr   Returns the original permissions of the page.
239246283Sdfr */
239346283Sdfrstatic int
239498944Sobrienwrite_protect_page (int pid, CORE_ADDR page_start)
239546283Sdfr{
239698944Sobrien  int tt_status;
239798944Sobrien  int original_permissions;
239898944Sobrien  int new_permissions;
239946283Sdfr
240046283Sdfr  tt_status = call_ttrace (TT_PROC_GET_MPROTECT,
240198944Sobrien			   pid,
240298944Sobrien			   (TTRACE_ARG_TYPE) page_start,
240398944Sobrien			   TT_NIL,
240498944Sobrien			   (TTRACE_ARG_TYPE) & original_permissions);
240546283Sdfr  if (errno || (tt_status < 0))
240646283Sdfr    {
240798944Sobrien      return 0;			/* What else can we do? */
240846283Sdfr    }
240946283Sdfr
241046283Sdfr  /* We'll also write-protect the page now, if that's allowed. */
241146283Sdfr  if (memory_page_dictionary.page_protections_allowed)
241246283Sdfr    {
241346283Sdfr      new_permissions = original_permissions & ~PROT_WRITE;
241446283Sdfr      tt_status = call_ttrace (TT_PROC_SET_MPROTECT,
241598944Sobrien			       pid,
241698944Sobrien			       (TTRACE_ARG_TYPE) page_start,
241798944Sobrien			 (TTRACE_ARG_TYPE) memory_page_dictionary.page_size,
241898944Sobrien			       (TTRACE_ARG_TYPE) new_permissions);
241946283Sdfr      if (errno || (tt_status < 0))
242098944Sobrien	{
242198944Sobrien	  return 0;		/* What else can we do? */
242298944Sobrien	}
242346283Sdfr    }
242446283Sdfr
242546283Sdfr  return original_permissions;
242646283Sdfr}
242746283Sdfr
242846283Sdfr
242946283Sdfr/* Unwrite-protect the memory page that starts at this address, restoring
243046283Sdfr   (what we must assume are) its original permissions.
243198944Sobrien */
243246283Sdfrstatic void
243398944Sobrienunwrite_protect_page (int pid, CORE_ADDR page_start, int original_permissions)
243446283Sdfr{
243598944Sobrien  int tt_status;
243646283Sdfr
243746283Sdfr  tt_status = call_ttrace (TT_PROC_SET_MPROTECT,
243898944Sobrien			   pid,
243998944Sobrien			   (TTRACE_ARG_TYPE) page_start,
244098944Sobrien			 (TTRACE_ARG_TYPE) memory_page_dictionary.page_size,
244198944Sobrien			   (TTRACE_ARG_TYPE) original_permissions);
244246283Sdfr  if (errno || (tt_status < 0))
244346283Sdfr    {
244498944Sobrien      return;			/* What else can we do? */
244546283Sdfr    }
244646283Sdfr}
244746283Sdfr
244846283Sdfr
244946283Sdfr/* Memory page-protections are used to implement "hardware" watchpoints
245046283Sdfr   on HP-UX.
245146283Sdfr
245246283Sdfr   For every memory page that is currently being watched (i.e., that
245346283Sdfr   presently should be write-protected), write-protect it.
245498944Sobrien */
245546283Sdfrvoid
245698944Sobrienhppa_enable_page_protection_events (int pid)
245746283Sdfr{
245898944Sobrien  int bucket;
245946283Sdfr
246046283Sdfr  memory_page_dictionary.page_protections_allowed = 1;
246146283Sdfr
246298944Sobrien  for (bucket = 0; bucket < MEMORY_PAGE_DICTIONARY_BUCKET_COUNT; bucket++)
246346283Sdfr    {
246498944Sobrien      memory_page_t *page;
246546283Sdfr
246646283Sdfr      page = memory_page_dictionary.buckets[bucket].next;
246746283Sdfr      while (page != NULL)
246898944Sobrien	{
246998944Sobrien	  page->original_permissions = write_protect_page (pid, page->page_start);
247098944Sobrien	  page = page->next;
247198944Sobrien	}
247246283Sdfr    }
247346283Sdfr}
247446283Sdfr
247546283Sdfr
247646283Sdfr/* Memory page-protections are used to implement "hardware" watchpoints
247746283Sdfr   on HP-UX.
247846283Sdfr
247946283Sdfr   For every memory page that is currently being watched (i.e., that
248046283Sdfr   presently is or should be write-protected), un-write-protect it.
248198944Sobrien */
248246283Sdfrvoid
248398944Sobrienhppa_disable_page_protection_events (int pid)
248446283Sdfr{
248598944Sobrien  int bucket;
248646283Sdfr
248798944Sobrien  for (bucket = 0; bucket < MEMORY_PAGE_DICTIONARY_BUCKET_COUNT; bucket++)
248846283Sdfr    {
248998944Sobrien      memory_page_t *page;
249046283Sdfr
249146283Sdfr      page = memory_page_dictionary.buckets[bucket].next;
249246283Sdfr      while (page != NULL)
249398944Sobrien	{
249498944Sobrien	  unwrite_protect_page (pid, page->page_start, page->original_permissions);
249598944Sobrien	  page = page->next;
249698944Sobrien	}
249746283Sdfr    }
249846283Sdfr
249946283Sdfr  memory_page_dictionary.page_protections_allowed = 0;
250046283Sdfr}
250146283Sdfr
250246283Sdfr/* Count the number of outstanding events.  At this
250346283Sdfr * point, we have selected one thread and its event
250446283Sdfr * as the one to be "reported" upwards to core gdb.
250546283Sdfr * That thread is already marked as "handled".
250646283Sdfr *
250746283Sdfr * Note: we could just scan our own thread list.  FIXME!
250846283Sdfr */
250946283Sdfrstatic int
251098944Sobriencount_unhandled_events (int real_pid, lwpid_t real_tid)
251146283Sdfr{
251298944Sobrien  ttstate_t tstate;
251398944Sobrien  lwpid_t ttid;
251498944Sobrien  int events_left;
251598944Sobrien
251646283Sdfr  /* Ok, find out how many threads have real events to report.
251746283Sdfr   */
251846283Sdfr  events_left = 0;
251998944Sobrien  ttid = get_process_first_stopped_thread_id (real_pid, &tstate);
252046283Sdfr
252146283Sdfr#ifdef THREAD_DEBUG
252298944Sobrien  if (debug_on)
252398944Sobrien    {
252498944Sobrien      if (ttid == 0)
252598944Sobrien	printf ("Process %d has no threads\n", real_pid);
252646283Sdfr      else
252798944Sobrien	printf ("Process %d has these threads:\n", real_pid);
252898944Sobrien    }
252946283Sdfr#endif
253046283Sdfr
253198944Sobrien  while (ttid > 0)
253298944Sobrien    {
253398944Sobrien      if (tstate.tts_event != TTEVT_NONE
253498944Sobrien	  && !was_handled (ttid))
253598944Sobrien	{
253698944Sobrien	  /* TTEVT_NONE implies we just stopped it ourselves
253798944Sobrien	   * because we're the stop-the-world guys, so it's
253898944Sobrien	   * not an event from our point of view.
253998944Sobrien	   *
254098944Sobrien	   * If "was_handled" is true, this is an event we
254198944Sobrien	   * already handled, so don't count it.
254298944Sobrien	   *
254398944Sobrien	   * Note that we don't count the thread with the
254498944Sobrien	   * currently-reported event, as it's already marked
254598944Sobrien	   * as handled.
254698944Sobrien	   */
254798944Sobrien	  events_left++;
254898944Sobrien	}
254998944Sobrien
255046283Sdfr#if defined( THREAD_DEBUG ) || defined( WAIT_BUFFER_DEBUG )
255198944Sobrien      if (debug_on)
255298944Sobrien	{
255398944Sobrien	  if (ttid == real_tid)
255498944Sobrien	    printf ("*");	/* Thread we're reporting */
255598944Sobrien	  else
255698944Sobrien	    printf (" ");
255746283Sdfr
255898944Sobrien	  if (tstate.tts_event != TTEVT_NONE)
255998944Sobrien	    printf ("+");	/* Thread with a real event */
256098944Sobrien	  else
256198944Sobrien	    printf (" ");
256246283Sdfr
256398944Sobrien	  if (was_handled (ttid))
256498944Sobrien	    printf ("h");	/* Thread has been handled */
256598944Sobrien	  else
256698944Sobrien	    printf (" ");
256746283Sdfr
256898944Sobrien	  printf (" %d, with event %s", ttid,
256998944Sobrien		  get_printable_name_of_ttrace_event (tstate.tts_event));
257098944Sobrien
257198944Sobrien	  if (tstate.tts_event == TTEVT_SIGNAL
257298944Sobrien	      && 5 == tstate.tts_u.tts_signal.tts_signo)
257398944Sobrien	    {
257498944Sobrien	      CORE_ADDR pc_val;
257598944Sobrien
257698944Sobrien	      pc_val = get_raw_pc (ttid);
257798944Sobrien
257898944Sobrien	      if (pc_val > 0)
257998944Sobrien		printf (" breakpoint at 0x%x\n", pc_val);
258098944Sobrien	      else
258198944Sobrien		printf (" bpt, can't fetch pc.\n");
258298944Sobrien	    }
258398944Sobrien	  else
258498944Sobrien	    printf ("\n");
258598944Sobrien	}
258646283Sdfr#endif
258746283Sdfr
258846283Sdfr      ttid = get_process_next_stopped_thread_id (real_pid, &tstate);
258998944Sobrien    }
259046283Sdfr
259146283Sdfr#if defined( THREAD_DEBUG ) || defined( WAIT_BUFFER_DEBUG )
259298944Sobrien  if (debug_on)
259398944Sobrien    if (events_left > 0)
259498944Sobrien      printf ("There are thus %d pending events\n", events_left);
259546283Sdfr#endif
259646283Sdfr
259746283Sdfr  return events_left;
259846283Sdfr}
259946283Sdfr
260046283Sdfr/* This function is provided as a sop to clients that are calling
260146283Sdfr * ptrace_wait to wait for a process to stop.  (see the
260246283Sdfr * implementation of child_wait.)  Return value is the pid for
260346283Sdfr * the event that ended the wait.
260446283Sdfr *
260546283Sdfr * Note: used by core gdb and so uses the pseudo-pid (really tid).
260646283Sdfr */
260746283Sdfrint
260898944Sobrienptrace_wait (ptid_t ptid, int *status)
260946283Sdfr{
261098944Sobrien  ttstate_t tsp;
261198944Sobrien  int ttwait_return;
261298944Sobrien  int real_pid;
261398944Sobrien  ttstate_t state;
261498944Sobrien  lwpid_t real_tid;
261598944Sobrien  int return_pid;
261646283Sdfr
261746283Sdfr  /* The ptrace implementation of this also ignores pid.
261846283Sdfr   */
261946283Sdfr  *status = 0;
262046283Sdfr
262198944Sobrien  ttwait_return = call_ttrace_wait (0, TTRACE_WAITOK, &tsp, sizeof (tsp));
262246283Sdfr  if (ttwait_return < 0)
262346283Sdfr    {
262446283Sdfr      /* ??rehrauer: It appears that if our inferior exits and we
262546283Sdfr         haven't asked for exit events, that we're not getting any
262646283Sdfr         indication save a negative return from ttrace_wait and an
262746283Sdfr         errno set to ESRCH?
262898944Sobrien       */
262946283Sdfr      if (errno == ESRCH)
263098944Sobrien	{
263198944Sobrien	  *status = 0;		/* WIFEXITED */
263298944Sobrien	  return PIDGET (inferior_ptid);
263398944Sobrien	}
263446283Sdfr
263598944Sobrien      warning ("Call of ttrace_wait returned with errno %d.",
263698944Sobrien	       errno);
263746283Sdfr      *status = ttwait_return;
263898944Sobrien      return PIDGET (inferior_ptid);
263946283Sdfr    }
264046283Sdfr
264146283Sdfr  real_pid = tsp.tts_pid;
264246283Sdfr  real_tid = tsp.tts_lwpid;
264346283Sdfr
264446283Sdfr  /* One complication is that the "tts_event" structure has
264546283Sdfr   * a set of flags, and more than one can be set.  So we
264646283Sdfr   * either have to force an order (as we do here), or handle
264746283Sdfr   * more than one flag at a time.
264846283Sdfr   */
264998944Sobrien  if (tsp.tts_event & TTEVT_LWP_CREATE)
265098944Sobrien    {
265146283Sdfr
265298944Sobrien      /* Unlike what you might expect, this event is reported in
265398944Sobrien       * the _creating_ thread, and the _created_ thread (whose tid
265498944Sobrien       * we have) is still running.  So we have to stop it.  This
265598944Sobrien       * has already been done in "call_ttrace_wait", but should we
265698944Sobrien       * ever abandon the "stop-the-world" model, here's the command
265798944Sobrien       * to use:
265898944Sobrien       *
265998944Sobrien       *    call_ttrace( TT_LWP_STOP, real_tid, TT_NIL, TT_NIL, TT_NIL );
266098944Sobrien       *
266198944Sobrien       * Note that this would depend on being called _after_ "add_tthread"
266298944Sobrien       * below for the tid-to-pid translation to be done in "call_ttrace".
266398944Sobrien       */
266446283Sdfr
266546283Sdfr#ifdef THREAD_DEBUG
266698944Sobrien      if (debug_on)
266798944Sobrien	printf ("New thread: pid %d, tid %d, creator tid %d\n",
266898944Sobrien		real_pid, tsp.tts_u.tts_thread.tts_target_lwpid,
266998944Sobrien		real_tid);
267046283Sdfr#endif
267146283Sdfr
267298944Sobrien      /* Now we have to return the tid of the created thread, not
267398944Sobrien       * the creating thread, or "wait_for_inferior" won't know we
267498944Sobrien       * have a new "process" (thread).  Plus we should record it
267598944Sobrien       * right, too.
267698944Sobrien       */
267746283Sdfr      real_tid = tsp.tts_u.tts_thread.tts_target_lwpid;
267846283Sdfr
267998944Sobrien      add_tthread (real_pid, real_tid);
268098944Sobrien    }
268146283Sdfr
268298944Sobrien  else if ((tsp.tts_event & TTEVT_LWP_TERMINATE)
268398944Sobrien	   || (tsp.tts_event & TTEVT_LWP_EXIT))
268498944Sobrien    {
268546283Sdfr
268646283Sdfr#ifdef THREAD_DEBUG
268798944Sobrien      if (debug_on)
268898944Sobrien	printf ("Thread dies: %d\n", real_tid);
268946283Sdfr#endif
269046283Sdfr
269198944Sobrien      del_tthread (real_tid);
269298944Sobrien    }
269346283Sdfr
269498944Sobrien  else if (tsp.tts_event & TTEVT_EXEC)
269598944Sobrien    {
269646283Sdfr
269798944Sobrien#ifdef THREAD_DEBUG
269898944Sobrien      if (debug_on)
269998944Sobrien	printf ("Pid %d has zero'th thread %d; inferior pid is %d\n",
270098944Sobrien		real_pid, real_tid, PIDGET (inferior_ptid));
270146283Sdfr#endif
270246283Sdfr
270398944Sobrien      add_tthread (real_pid, real_tid);
270498944Sobrien    }
270546283Sdfr
270646283Sdfr#ifdef THREAD_DEBUG
270798944Sobrien  else if (debug_on)
270898944Sobrien    {
270998944Sobrien      printf ("Process-level event %s, using tid %d\n",
271098944Sobrien	      get_printable_name_of_ttrace_event (tsp.tts_event),
271198944Sobrien	      real_tid);
271246283Sdfr
271398944Sobrien      /* OK to do this, as "add_tthread" won't add
271498944Sobrien       * duplicate entries.  Also OK not to do it,
271598944Sobrien       * as this event isn't one which can change the
271698944Sobrien       * thread state.
271798944Sobrien       */
271898944Sobrien      add_tthread (real_pid, real_tid);
271998944Sobrien    }
272046283Sdfr#endif
272146283Sdfr
272246283Sdfr
272346283Sdfr  /* How many events are left to report later?
272446283Sdfr   * In a non-stop-the-world model, this isn't needed.
272546283Sdfr   *
272646283Sdfr   * Note that it's not always safe to query the thread state of a process,
272746283Sdfr   * which is what count_unhandled_events does.  (If unsafe, we're left with
272846283Sdfr   * no other resort than to assume that no more events remain...)
272946283Sdfr   */
273046283Sdfr  if (can_touch_threads_of_process (real_pid, tsp.tts_event))
273198944Sobrien    more_events_left = count_unhandled_events (real_pid, real_tid);
273298944Sobrien
273398944Sobrien  else
273498944Sobrien    {
273598944Sobrien      if (more_events_left > 0)
273698944Sobrien	warning ("Vfork or fork causing loss of %d buffered events.",
273798944Sobrien		 more_events_left);
273898944Sobrien
273946283Sdfr      more_events_left = 0;
274098944Sobrien    }
274146283Sdfr
274246283Sdfr  /* Attempt to translate the ttrace_wait-returned status into the
274346283Sdfr     ptrace equivalent.
274446283Sdfr
274546283Sdfr     ??rehrauer: This is somewhat fragile.  We really ought to rewrite
274646283Sdfr     clients that expect to pick apart a ptrace wait status, to use
274746283Sdfr     something a little more abstract.
274898944Sobrien   */
274998944Sobrien  if ((tsp.tts_event & TTEVT_EXEC)
275046283Sdfr      || (tsp.tts_event & TTEVT_FORK)
275146283Sdfr      || (tsp.tts_event & TTEVT_VFORK))
275246283Sdfr    {
275346283Sdfr      /* Forks come in pairs (parent and child), so core gdb
275446283Sdfr       * will do two waits.  Be ready to notice this.
275546283Sdfr       */
275646283Sdfr      if (tsp.tts_event & TTEVT_FORK)
275798944Sobrien	{
275898944Sobrien	  process_state = FORKING;
275998944Sobrien
276046283Sdfr#ifdef WAIT_BUFFER_DEBUG
276198944Sobrien	  if (debug_on)
276298944Sobrien	    printf ("Process set to FORKING\n");
276346283Sdfr#endif
276498944Sobrien	}
276546283Sdfr      else if (tsp.tts_event & TTEVT_VFORK)
276698944Sobrien	{
276798944Sobrien	  process_state = VFORKING;
276898944Sobrien
276946283Sdfr#ifdef WAIT_BUFFER_DEBUG
277098944Sobrien	  if (debug_on)
277198944Sobrien	    printf ("Process set to VFORKING\n");
277246283Sdfr#endif
277398944Sobrien	}
277446283Sdfr
277546283Sdfr      /* Make an exec or fork look like a breakpoint.  Definitely a hack,
277646283Sdfr         but I don't think non HP-UX-specific clients really carefully
277746283Sdfr         inspect the first events they get after inferior startup, so
277846283Sdfr         it probably almost doesn't matter what we claim this is.
277998944Sobrien       */
278046283Sdfr
278146283Sdfr#ifdef THREAD_DEBUG
278298944Sobrien      if (debug_on)
278398944Sobrien	printf ("..a process 'event'\n");
278446283Sdfr#endif
278546283Sdfr
278646283Sdfr      /* Also make fork and exec events look like bpts, so they can be caught.
278798944Sobrien       */
278846283Sdfr      *status = 0177 | (_SIGTRAP << 8);
278946283Sdfr    }
279046283Sdfr
279146283Sdfr  /* Special-cases: We ask for syscall entry and exit events to implement
279246283Sdfr     "fast" (aka "hardware") watchpoints.
279346283Sdfr
279446283Sdfr     When we get a syscall entry, we want to disable page-protections,
279546283Sdfr     and resume the inferior; this isn't an event we wish for
279646283Sdfr     wait_for_inferior to see.  Note that we must resume ONLY the
279746283Sdfr     thread that reported the syscall entry; we don't want to allow
279846283Sdfr     other threads to run with the page protections off, as they might
279946283Sdfr     then be able to write to watch memory without it being caught.
280046283Sdfr
280146283Sdfr     When we get a syscall exit, we want to reenable page-protections,
280246283Sdfr     but we don't want to resume the inferior; this is an event we wish
280346283Sdfr     wait_for_inferior to see.  Make it look like the signal we normally
280446283Sdfr     get for a single-step completion.  This should cause wait_for_inferior
280546283Sdfr     to evaluate whether any watchpoint triggered.
280646283Sdfr
280746283Sdfr     Or rather, that's what we'd LIKE to do for syscall exit; we can't,
280846283Sdfr     due to some HP-UX "features".  Some syscalls have problems with
280946283Sdfr     write-protections on some pages, and some syscalls seem to have
281046283Sdfr     pending writes to those pages at the time we're getting the return
281146283Sdfr     event.  So, we'll single-step the inferior to get out of the syscall,
281246283Sdfr     and then reenable protections.
281346283Sdfr
281446283Sdfr     Note that we're intentionally allowing the syscall exit case to
281546283Sdfr     fall through into the succeeding cases, as sometimes we single-
281646283Sdfr     step out of one syscall only to immediately enter another...
281746283Sdfr   */
281846283Sdfr  else if ((tsp.tts_event & TTEVT_SYSCALL_ENTRY)
281998944Sobrien	   || (tsp.tts_event & TTEVT_SYSCALL_RETURN))
282046283Sdfr    {
282146283Sdfr      /* Make a syscall event look like a breakpoint.  Same comments
282246283Sdfr         as for exec & fork events.
282398944Sobrien       */
282446283Sdfr#ifdef THREAD_DEBUG
282598944Sobrien      if (debug_on)
282698944Sobrien	printf ("..a syscall 'event'\n");
282746283Sdfr#endif
282846283Sdfr
282946283Sdfr      /* Also make syscall events look like bpts, so they can be caught.
283098944Sobrien       */
283146283Sdfr      *status = 0177 | (_SIGTRAP << 8);
283246283Sdfr    }
283346283Sdfr
283446283Sdfr  else if ((tsp.tts_event & TTEVT_LWP_CREATE)
283598944Sobrien	   || (tsp.tts_event & TTEVT_LWP_TERMINATE)
283698944Sobrien	   || (tsp.tts_event & TTEVT_LWP_EXIT))
283746283Sdfr    {
283846283Sdfr      /* Make a thread event look like a breakpoint.  Same comments
283946283Sdfr       * as for exec & fork events.
284046283Sdfr       */
284146283Sdfr#ifdef THREAD_DEBUG
284298944Sobrien      if (debug_on)
284398944Sobrien	printf ("..a thread 'event'\n");
284446283Sdfr#endif
284546283Sdfr
284646283Sdfr      /* Also make thread events look like bpts, so they can be caught.
284798944Sobrien       */
284846283Sdfr      *status = 0177 | (_SIGTRAP << 8);
284946283Sdfr    }
285098944Sobrien
285146283Sdfr  else if ((tsp.tts_event & TTEVT_EXIT))
285298944Sobrien    {				/* WIFEXITED */
285398944Sobrien
285446283Sdfr#ifdef THREAD_DEBUG
285598944Sobrien      if (debug_on)
285698944Sobrien	printf ("..an exit\n");
285746283Sdfr#endif
285846283Sdfr
285946283Sdfr      /* Prevent rest of gdb from thinking this is
286046283Sdfr       * a new thread if for some reason it's never
286146283Sdfr       * seen the main thread before.
286246283Sdfr       */
286398944Sobrien      inferior_ptid = pid_to_ptid (map_to_gdb_tid (real_tid));	/* HACK, FIX */
286498944Sobrien
286546283Sdfr      *status = 0 | (tsp.tts_u.tts_exit.tts_exitcode);
286646283Sdfr    }
286798944Sobrien
286846283Sdfr  else if (tsp.tts_event & TTEVT_SIGNAL)
286998944Sobrien    {				/* WIFSTOPPED */
287046283Sdfr#ifdef THREAD_DEBUG
287198944Sobrien      if (debug_on)
287298944Sobrien	printf ("..a signal, %d\n", tsp.tts_u.tts_signal.tts_signo);
287346283Sdfr#endif
287446283Sdfr
287546283Sdfr      *status = 0177 | (tsp.tts_u.tts_signal.tts_signo << 8);
287646283Sdfr    }
287746283Sdfr
287846283Sdfr  else
287998944Sobrien    {				/* !WIFSTOPPED */
288046283Sdfr
288146283Sdfr      /* This means the process or thread terminated.  But we should've
288246283Sdfr         caught an explicit exit/termination above.  So warn (this is
288346283Sdfr         really an internal error) and claim the process or thread
288446283Sdfr         terminated with a SIGTRAP.
288546283Sdfr       */
288646283Sdfr
288746283Sdfr      warning ("process_wait: unknown process state");
288846283Sdfr
288946283Sdfr#ifdef THREAD_DEBUG
289098944Sobrien      if (debug_on)
289198944Sobrien	printf ("Process-level event %s, using tid %d\n",
289298944Sobrien		get_printable_name_of_ttrace_event (tsp.tts_event),
289398944Sobrien		real_tid);
289446283Sdfr#endif
289546283Sdfr
289646283Sdfr      *status = _SIGTRAP;
289746283Sdfr    }
289846283Sdfr
289998944Sobrien  target_post_wait (pid_to_ptid (tsp.tts_pid), *status);
290046283Sdfr
290146283Sdfr
290246283Sdfr#ifdef THREAD_DEBUG
290398944Sobrien  if (debug_on)
290498944Sobrien    printf ("Done waiting, pid is %d, tid %d\n", real_pid, real_tid);
290546283Sdfr#endif
290646283Sdfr
290746283Sdfr  /* All code external to this module uses the tid, but calls
290846283Sdfr   * it "pid".  There's some tweaking so that the outside sees
290946283Sdfr   * the first thread as having the same number as the starting
291046283Sdfr   * pid.
291146283Sdfr   */
291298944Sobrien  return_pid = map_to_gdb_tid (real_tid);
291346283Sdfr
291446283Sdfr  /* Remember this for later use in "hppa_prepare_to_proceed".
291546283Sdfr   */
291698944Sobrien  old_gdb_pid = PIDGET (inferior_ptid);
291746283Sdfr  reported_pid = return_pid;
291846283Sdfr  reported_bpt = ((tsp.tts_event & TTEVT_SIGNAL) && (5 == tsp.tts_u.tts_signal.tts_signo));
291946283Sdfr
292098944Sobrien  if (real_tid == 0 || return_pid == 0)
292198944Sobrien    {
292298944Sobrien      warning ("Internal error: process-wait failed.");
292398944Sobrien    }
292498944Sobrien
292546283Sdfr  return return_pid;
292646283Sdfr}
292798944Sobrien
292846283Sdfr
292946283Sdfr/* This function causes the caller's process to be traced by its
293046283Sdfr   parent.  This is intended to be called after GDB forks itself,
293146283Sdfr   and before the child execs the target.  Despite the name, it
293246283Sdfr   is called by the child.
293346283Sdfr
293446283Sdfr   Note that HP-UX ttrace is rather funky in how this is done.
293546283Sdfr   If the parent wants to get the initial exec event of a child,
293646283Sdfr   it must set the ttrace event mask of the child to include execs.
293746283Sdfr   (The child cannot do this itself.)  This must be done after the
293846283Sdfr   child is forked, but before it execs.
293946283Sdfr
294046283Sdfr   To coordinate the parent and child, we implement a semaphore using
294146283Sdfr   pipes.  After SETTRC'ing itself, the child tells the parent that
294246283Sdfr   it is now traceable by the parent, and waits for the parent's
294346283Sdfr   acknowledgement.  The parent can then set the child's event mask,
294446283Sdfr   and notify the child that it can now exec.
294546283Sdfr
294646283Sdfr   (The acknowledgement by parent happens as a result of a call to
294746283Sdfr   child_acknowledge_created_inferior.)
294846283Sdfr */
294946283Sdfrint
295098944Sobrienparent_attach_all (void)
295146283Sdfr{
295298944Sobrien  int tt_status;
295346283Sdfr
295446283Sdfr  /* We need a memory home for a constant, to pass it to ttrace.
295546283Sdfr     The value of the constant is arbitrary, so long as both
295646283Sdfr     parent and child use the same value.  Might as well use the
295746283Sdfr     "magic" constant provided by ttrace...
295846283Sdfr   */
295998944Sobrien  uint64_t tc_magic_child = TT_VERSION;
296098944Sobrien  uint64_t tc_magic_parent = 0;
296146283Sdfr
296246283Sdfr  tt_status = call_real_ttrace (
296398944Sobrien				 TT_PROC_SETTRC,
296498944Sobrien				 (int) TT_NIL,
296598944Sobrien				 (lwpid_t) TT_NIL,
296698944Sobrien				 TT_NIL,
296798944Sobrien				 (TTRACE_ARG_TYPE) TT_VERSION,
296898944Sobrien				 TT_NIL);
296946283Sdfr
297046283Sdfr  if (tt_status < 0)
297146283Sdfr    return tt_status;
297246283Sdfr
297346283Sdfr  /* Notify the parent that we're potentially ready to exec(). */
297446283Sdfr  write (startup_semaphore.child_channel[SEM_TALK],
297598944Sobrien	 &tc_magic_child,
297698944Sobrien	 sizeof (tc_magic_child));
297746283Sdfr
297846283Sdfr  /* Wait for acknowledgement from the parent. */
297946283Sdfr  read (startup_semaphore.parent_channel[SEM_LISTEN],
298098944Sobrien	&tc_magic_parent,
298198944Sobrien	sizeof (tc_magic_parent));
298298944Sobrien
298346283Sdfr  if (tc_magic_child != tc_magic_parent)
298446283Sdfr    warning ("mismatched semaphore magic");
298546283Sdfr
298646283Sdfr  /* Discard our copy of the semaphore. */
298746283Sdfr  (void) close (startup_semaphore.parent_channel[SEM_LISTEN]);
298846283Sdfr  (void) close (startup_semaphore.parent_channel[SEM_TALK]);
298946283Sdfr  (void) close (startup_semaphore.child_channel[SEM_LISTEN]);
299046283Sdfr  (void) close (startup_semaphore.child_channel[SEM_TALK]);
299198944Sobrien
299246283Sdfr  return tt_status;
299346283Sdfr}
299446283Sdfr
299546283Sdfr/* Despite being file-local, this routine is dealing with
299646283Sdfr * actual process IDs, not thread ids.  That's because it's
299746283Sdfr * called before the first "wait" call, and there's no map
299846283Sdfr * yet from tids to pids.
299946283Sdfr *
300046283Sdfr * When it is called, a forked child is running, but waiting on
300146283Sdfr * the semaphore.  If you stop the child and re-start it,
300246283Sdfr * things get confused, so don't do that!  An attached child is
300346283Sdfr * stopped.
300446283Sdfr *
300546283Sdfr * Since this is called after either attach or run, we
300646283Sdfr * have to be the common part of both.
300746283Sdfr */
300846283Sdfrstatic void
300998944Sobrienrequire_notification_of_events (int real_pid)
301046283Sdfr{
301198944Sobrien  int tt_status;
301298944Sobrien  ttevent_t notifiable_events;
301346283Sdfr
301498944Sobrien  lwpid_t tid;
301598944Sobrien  ttstate_t thread_state;
301646283Sdfr
301746283Sdfr#ifdef THREAD_DEBUG
301898944Sobrien  if (debug_on)
301998944Sobrien    printf ("Require notif, pid is %d\n", real_pid);
302046283Sdfr#endif
302146283Sdfr
302246283Sdfr  /* Temporary HACK: tell inftarg.c/child_wait to not
302346283Sdfr   * loop until pids are the same.
302446283Sdfr   */
302546283Sdfr  not_same_real_pid = 0;
302646283Sdfr
302746283Sdfr  sigemptyset (&notifiable_events.tte_signals);
302846283Sdfr  notifiable_events.tte_opts = TTEO_NONE;
302946283Sdfr
303046283Sdfr  /* This ensures that forked children inherit their parent's
303146283Sdfr   * event mask, which we're setting here.
303246283Sdfr   *
303346283Sdfr   * NOTE: if you debug gdb with itself, then the ultimate
303446283Sdfr   *       debuggee gets flags set by the outermost gdb, as
303546283Sdfr   *       a child of a child will still inherit.
303646283Sdfr   */
303746283Sdfr  notifiable_events.tte_opts |= TTEO_PROC_INHERIT;
303846283Sdfr
303998944Sobrien  notifiable_events.tte_events = TTEVT_DEFAULT;
304046283Sdfr  notifiable_events.tte_events |= TTEVT_SIGNAL;
304146283Sdfr  notifiable_events.tte_events |= TTEVT_EXEC;
304246283Sdfr  notifiable_events.tte_events |= TTEVT_EXIT;
304346283Sdfr  notifiable_events.tte_events |= TTEVT_FORK;
304446283Sdfr  notifiable_events.tte_events |= TTEVT_VFORK;
304546283Sdfr  notifiable_events.tte_events |= TTEVT_LWP_CREATE;
304646283Sdfr  notifiable_events.tte_events |= TTEVT_LWP_EXIT;
304746283Sdfr  notifiable_events.tte_events |= TTEVT_LWP_TERMINATE;
304846283Sdfr
304946283Sdfr  tt_status = call_real_ttrace (
305098944Sobrien				 TT_PROC_SET_EVENT_MASK,
305198944Sobrien				 real_pid,
305298944Sobrien				 (lwpid_t) TT_NIL,
305398944Sobrien				 (TTRACE_ARG_TYPE) & notifiable_events,
305498944Sobrien			       (TTRACE_ARG_TYPE) sizeof (notifiable_events),
305598944Sobrien				 TT_NIL);
305646283Sdfr}
305746283Sdfr
305846283Sdfrstatic void
305998944Sobrienrequire_notification_of_exec_events (int real_pid)
306046283Sdfr{
306198944Sobrien  int tt_status;
306298944Sobrien  ttevent_t notifiable_events;
306346283Sdfr
306498944Sobrien  lwpid_t tid;
306598944Sobrien  ttstate_t thread_state;
306646283Sdfr
306746283Sdfr#ifdef THREAD_DEBUG
306898944Sobrien  if (debug_on)
306998944Sobrien    printf ("Require notif, pid is %d\n", real_pid);
307046283Sdfr#endif
307146283Sdfr
307246283Sdfr  /* Temporary HACK: tell inftarg.c/child_wait to not
307346283Sdfr   * loop until pids are the same.
307446283Sdfr   */
307546283Sdfr  not_same_real_pid = 0;
307646283Sdfr
307746283Sdfr  sigemptyset (&notifiable_events.tte_signals);
307846283Sdfr  notifiable_events.tte_opts = TTEO_NOSTRCCHLD;
307946283Sdfr
308046283Sdfr  /* This ensures that forked children don't inherit their parent's
308146283Sdfr   * event mask, which we're setting here.
308246283Sdfr   */
308346283Sdfr  notifiable_events.tte_opts &= ~TTEO_PROC_INHERIT;
308446283Sdfr
308598944Sobrien  notifiable_events.tte_events = TTEVT_DEFAULT;
308646283Sdfr  notifiable_events.tte_events |= TTEVT_EXEC;
308746283Sdfr  notifiable_events.tte_events |= TTEVT_EXIT;
308846283Sdfr
308946283Sdfr  tt_status = call_real_ttrace (
309098944Sobrien				 TT_PROC_SET_EVENT_MASK,
309198944Sobrien				 real_pid,
309298944Sobrien				 (lwpid_t) TT_NIL,
309398944Sobrien				 (TTRACE_ARG_TYPE) & notifiable_events,
309498944Sobrien			       (TTRACE_ARG_TYPE) sizeof (notifiable_events),
309598944Sobrien				 TT_NIL);
309646283Sdfr}
309798944Sobrien
309846283Sdfr
309946283Sdfr/* This function is called by the parent process, with pid being the
310046283Sdfr * ID of the child process, after the debugger has forked.
310146283Sdfr */
310246283Sdfrvoid
310398944Sobrienchild_acknowledge_created_inferior (int pid)
310446283Sdfr{
310546283Sdfr  /* We need a memory home for a constant, to pass it to ttrace.
310646283Sdfr     The value of the constant is arbitrary, so long as both
310746283Sdfr     parent and child use the same value.  Might as well use the
310846283Sdfr     "magic" constant provided by ttrace...
310998944Sobrien   */
311098944Sobrien  uint64_t tc_magic_parent = TT_VERSION;
311198944Sobrien  uint64_t tc_magic_child = 0;
311246283Sdfr
311346283Sdfr  /* Wait for the child to tell us that it has forked. */
311446283Sdfr  read (startup_semaphore.child_channel[SEM_LISTEN],
311598944Sobrien	&tc_magic_child,
311698944Sobrien	sizeof (tc_magic_child));
311746283Sdfr
311846283Sdfr  /* Clear thread info now.  We'd like to do this in
311946283Sdfr   * "require...", but that messes up attach.
312046283Sdfr   */
312198944Sobrien  clear_thread_info ();
312246283Sdfr
312346283Sdfr  /* Tell the "rest of gdb" that the initial thread exists.
312446283Sdfr   * This isn't really a hack.  Other thread-based versions
312546283Sdfr   * of gdb (e.g. gnu-nat.c) seem to do the same thing.
312646283Sdfr   *
312746283Sdfr   * Q: Why don't we also add this thread to the local
312846283Sdfr   *    list via "add_tthread"?
312946283Sdfr   *
313046283Sdfr   * A: Because we don't know the tid, and can't stop the
313146283Sdfr   *    the process safely to ask what it is.  Anyway, we'll
313246283Sdfr   *    add it when it gets the EXEC event.
313346283Sdfr   */
313498944Sobrien  add_thread (pid_to_ptid (pid));		/* in thread.c */
313546283Sdfr
313646283Sdfr  /* We can now set the child's ttrace event mask.
313746283Sdfr   */
313846283Sdfr  require_notification_of_exec_events (pid);
313946283Sdfr
314046283Sdfr  /* Tell ourselves that the process is running.
314146283Sdfr   */
314246283Sdfr  process_state = RUNNING;
314346283Sdfr
314446283Sdfr  /* Notify the child that it can exec. */
314546283Sdfr  write (startup_semaphore.parent_channel[SEM_TALK],
314698944Sobrien	 &tc_magic_parent,
314798944Sobrien	 sizeof (tc_magic_parent));
314846283Sdfr
314946283Sdfr  /* Discard our copy of the semaphore. */
315046283Sdfr  (void) close (startup_semaphore.parent_channel[SEM_LISTEN]);
315146283Sdfr  (void) close (startup_semaphore.parent_channel[SEM_TALK]);
315246283Sdfr  (void) close (startup_semaphore.child_channel[SEM_LISTEN]);
315346283Sdfr  (void) close (startup_semaphore.child_channel[SEM_TALK]);
315446283Sdfr}
315546283Sdfr
315646283Sdfr
315746283Sdfr/*
315846283Sdfr * arrange for notification of all events by
315946283Sdfr * calling require_notification_of_events.
316046283Sdfr */
316146283Sdfrvoid
316298944Sobrienchild_post_startup_inferior (ptid_t ptid)
316346283Sdfr{
316498944Sobrien  require_notification_of_events (PIDGET (ptid));
316546283Sdfr}
316646283Sdfr
316746283Sdfr/* From here on, we should expect tids rather than pids.
316846283Sdfr */
316946283Sdfrstatic void
317098944Sobrienhppa_enable_catch_fork (int tid)
317146283Sdfr{
317298944Sobrien  int tt_status;
317398944Sobrien  ttevent_t ttrace_events;
317446283Sdfr
317546283Sdfr  /* Get the set of events that are currently enabled.
317646283Sdfr   */
317746283Sdfr  tt_status = call_ttrace (TT_PROC_GET_EVENT_MASK,
317898944Sobrien			   tid,
317998944Sobrien			   (TTRACE_ARG_TYPE) & ttrace_events,
318098944Sobrien			   (TTRACE_ARG_TYPE) sizeof (ttrace_events),
318198944Sobrien			   TT_NIL);
318246283Sdfr  if (errno)
318346283Sdfr    perror_with_name ("ttrace");
318446283Sdfr
318546283Sdfr  /* Add forks to that set. */
318646283Sdfr  ttrace_events.tte_events |= TTEVT_FORK;
318746283Sdfr
318846283Sdfr#ifdef THREAD_DEBUG
318998944Sobrien  if (debug_on)
319098944Sobrien    printf ("enable fork, tid is %d\n", tid);
319146283Sdfr#endif
319246283Sdfr
319346283Sdfr  tt_status = call_ttrace (TT_PROC_SET_EVENT_MASK,
319498944Sobrien			   tid,
319598944Sobrien			   (TTRACE_ARG_TYPE) & ttrace_events,
319698944Sobrien			   (TTRACE_ARG_TYPE) sizeof (ttrace_events),
319798944Sobrien			   TT_NIL);
319846283Sdfr  if (errno)
319946283Sdfr    perror_with_name ("ttrace");
320046283Sdfr}
320146283Sdfr
320246283Sdfr
320346283Sdfrstatic void
320498944Sobrienhppa_disable_catch_fork (int tid)
320546283Sdfr{
320698944Sobrien  int tt_status;
320798944Sobrien  ttevent_t ttrace_events;
320846283Sdfr
320946283Sdfr  /* Get the set of events that are currently enabled.
321046283Sdfr   */
321146283Sdfr  tt_status = call_ttrace (TT_PROC_GET_EVENT_MASK,
321298944Sobrien			   tid,
321398944Sobrien			   (TTRACE_ARG_TYPE) & ttrace_events,
321498944Sobrien			   (TTRACE_ARG_TYPE) sizeof (ttrace_events),
321598944Sobrien			   TT_NIL);
321646283Sdfr
321746283Sdfr  if (errno)
321846283Sdfr    perror_with_name ("ttrace");
321946283Sdfr
322046283Sdfr  /* Remove forks from that set. */
322146283Sdfr  ttrace_events.tte_events &= ~TTEVT_FORK;
322246283Sdfr
322346283Sdfr#ifdef THREAD_DEBUG
322498944Sobrien  if (debug_on)
322598944Sobrien    printf ("disable fork, tid is %d\n", tid);
322646283Sdfr#endif
322746283Sdfr
322846283Sdfr  tt_status = call_ttrace (TT_PROC_SET_EVENT_MASK,
322998944Sobrien			   tid,
323098944Sobrien			   (TTRACE_ARG_TYPE) & ttrace_events,
323198944Sobrien			   (TTRACE_ARG_TYPE) sizeof (ttrace_events),
323298944Sobrien			   TT_NIL);
323346283Sdfr
323446283Sdfr  if (errno)
323546283Sdfr    perror_with_name ("ttrace");
323646283Sdfr}
323746283Sdfr
323846283Sdfr
323946283Sdfr#if defined(CHILD_INSERT_FORK_CATCHPOINT)
324046283Sdfrint
324198944Sobrienchild_insert_fork_catchpoint (int tid)
324246283Sdfr{
324346283Sdfr  /* Enable reporting of fork events from the kernel. */
324446283Sdfr  /* ??rehrauer: For the moment, we're always enabling these events,
324546283Sdfr     and just ignoring them if there's no catchpoint to catch them.
324698944Sobrien   */
324746283Sdfr  return 0;
324846283Sdfr}
324946283Sdfr#endif
325046283Sdfr
325146283Sdfr
325246283Sdfr#if defined(CHILD_REMOVE_FORK_CATCHPOINT)
325346283Sdfrint
325498944Sobrienchild_remove_fork_catchpoint (int tid)
325546283Sdfr{
325646283Sdfr  /* Disable reporting of fork events from the kernel. */
325746283Sdfr  /* ??rehrauer: For the moment, we're always enabling these events,
325846283Sdfr     and just ignoring them if there's no catchpoint to catch them.
325998944Sobrien   */
326046283Sdfr  return 0;
326146283Sdfr}
326246283Sdfr#endif
326346283Sdfr
326446283Sdfr
326546283Sdfrstatic void
326698944Sobrienhppa_enable_catch_vfork (int tid)
326746283Sdfr{
326898944Sobrien  int tt_status;
326998944Sobrien  ttevent_t ttrace_events;
327046283Sdfr
327146283Sdfr  /* Get the set of events that are currently enabled.
327246283Sdfr   */
327346283Sdfr  tt_status = call_ttrace (TT_PROC_GET_EVENT_MASK,
327498944Sobrien			   tid,
327598944Sobrien			   (TTRACE_ARG_TYPE) & ttrace_events,
327698944Sobrien			   (TTRACE_ARG_TYPE) sizeof (ttrace_events),
327798944Sobrien			   TT_NIL);
327846283Sdfr
327946283Sdfr  if (errno)
328046283Sdfr    perror_with_name ("ttrace");
328146283Sdfr
328246283Sdfr  /* Add vforks to that set. */
328346283Sdfr  ttrace_events.tte_events |= TTEVT_VFORK;
328446283Sdfr
328546283Sdfr#ifdef THREAD_DEBUG
328698944Sobrien  if (debug_on)
328798944Sobrien    printf ("enable vfork, tid is %d\n", tid);
328846283Sdfr#endif
328946283Sdfr
329046283Sdfr  tt_status = call_ttrace (TT_PROC_SET_EVENT_MASK,
329198944Sobrien			   tid,
329298944Sobrien			   (TTRACE_ARG_TYPE) & ttrace_events,
329398944Sobrien			   (TTRACE_ARG_TYPE) sizeof (ttrace_events),
329498944Sobrien			   TT_NIL);
329546283Sdfr
329646283Sdfr  if (errno)
329746283Sdfr    perror_with_name ("ttrace");
329846283Sdfr}
329946283Sdfr
330046283Sdfr
330146283Sdfrstatic void
330298944Sobrienhppa_disable_catch_vfork (int tid)
330346283Sdfr{
330498944Sobrien  int tt_status;
330598944Sobrien  ttevent_t ttrace_events;
330646283Sdfr
330746283Sdfr  /* Get the set of events that are currently enabled. */
330846283Sdfr  tt_status = call_ttrace (TT_PROC_GET_EVENT_MASK,
330998944Sobrien			   tid,
331098944Sobrien			   (TTRACE_ARG_TYPE) & ttrace_events,
331198944Sobrien			   (TTRACE_ARG_TYPE) sizeof (ttrace_events),
331298944Sobrien			   TT_NIL);
331346283Sdfr
331446283Sdfr  if (errno)
331546283Sdfr    perror_with_name ("ttrace");
331646283Sdfr
331746283Sdfr  /* Remove vforks from that set. */
331846283Sdfr  ttrace_events.tte_events &= ~TTEVT_VFORK;
331946283Sdfr
332046283Sdfr#ifdef THREAD_DEBUG
332198944Sobrien  if (debug_on)
332298944Sobrien    printf ("disable vfork, tid is %d\n", tid);
332346283Sdfr#endif
332446283Sdfr  tt_status = call_ttrace (TT_PROC_SET_EVENT_MASK,
332598944Sobrien			   tid,
332698944Sobrien			   (TTRACE_ARG_TYPE) & ttrace_events,
332798944Sobrien			   (TTRACE_ARG_TYPE) sizeof (ttrace_events),
332898944Sobrien			   TT_NIL);
332946283Sdfr
333046283Sdfr  if (errno)
333146283Sdfr    perror_with_name ("ttrace");
333246283Sdfr}
333346283Sdfr
333446283Sdfr
333546283Sdfr#if defined(CHILD_INSERT_VFORK_CATCHPOINT)
333646283Sdfrint
333798944Sobrienchild_insert_vfork_catchpoint (int tid)
333846283Sdfr{
333946283Sdfr  /* Enable reporting of vfork events from the kernel. */
334046283Sdfr  /* ??rehrauer: For the moment, we're always enabling these events,
334146283Sdfr     and just ignoring them if there's no catchpoint to catch them.
334298944Sobrien   */
334346283Sdfr  return 0;
334446283Sdfr}
334546283Sdfr#endif
334646283Sdfr
334746283Sdfr
334846283Sdfr#if defined(CHILD_REMOVE_VFORK_CATCHPOINT)
334946283Sdfrint
335098944Sobrienchild_remove_vfork_catchpoint (int tid)
335146283Sdfr{
335246283Sdfr  /* Disable reporting of vfork events from the kernel. */
335346283Sdfr  /* ??rehrauer: For the moment, we're always enabling these events,
335446283Sdfr     and just ignoring them if there's no catchpoint to catch them.
335598944Sobrien   */
335646283Sdfr  return 0;
335746283Sdfr}
335846283Sdfr#endif
335946283Sdfr
336046283Sdfr#if defined(CHILD_HAS_FORKED)
336146283Sdfr
336246283Sdfr/* Q: Do we need to map the returned process ID to a thread ID?
336398944Sobrien
336446283Sdfr * A: I don't think so--here we want a _real_ pid.  Any later
336546283Sdfr *    operations will call "require_notification_of_events" and
336646283Sdfr *    start the mapping.
336746283Sdfr */
336846283Sdfrint
336998944Sobrienchild_has_forked (int tid, int *childpid)
337046283Sdfr{
337198944Sobrien  int tt_status;
337298944Sobrien  ttstate_t ttrace_state;
337398944Sobrien  thread_info *tinfo;
337446283Sdfr
337546283Sdfr  /* Do we have cached thread state that we can consult?  If so, use it. */
337646283Sdfr  tinfo = find_thread_info (map_from_gdb_tid (tid));
337798944Sobrien  if (tinfo != NULL)
337898944Sobrien    {
337998944Sobrien      copy_ttstate_t (&ttrace_state, &tinfo->last_stop_state);
338098944Sobrien    }
338146283Sdfr
338246283Sdfr  /* Nope, must read the thread's current state */
338346283Sdfr  else
338446283Sdfr    {
338546283Sdfr      tt_status = call_ttrace (TT_LWP_GET_STATE,
338698944Sobrien			       tid,
338798944Sobrien			       (TTRACE_ARG_TYPE) & ttrace_state,
338898944Sobrien			       (TTRACE_ARG_TYPE) sizeof (ttrace_state),
338998944Sobrien			       TT_NIL);
339046283Sdfr
339146283Sdfr      if (errno)
339298944Sobrien	perror_with_name ("ttrace");
339398944Sobrien
339446283Sdfr      if (tt_status < 0)
339598944Sobrien	return 0;
339646283Sdfr    }
339746283Sdfr
339846283Sdfr  if (ttrace_state.tts_event & TTEVT_FORK)
339946283Sdfr    {
340046283Sdfr      *childpid = ttrace_state.tts_u.tts_fork.tts_fpid;
340146283Sdfr      return 1;
340246283Sdfr    }
340346283Sdfr
340446283Sdfr  return 0;
340546283Sdfr}
340646283Sdfr#endif
340746283Sdfr
340846283Sdfr
340946283Sdfr#if defined(CHILD_HAS_VFORKED)
341046283Sdfr
341146283Sdfr/* See child_has_forked for pid discussion.
341246283Sdfr */
341346283Sdfrint
341498944Sobrienchild_has_vforked (int tid, int *childpid)
341546283Sdfr{
341698944Sobrien  int tt_status;
341798944Sobrien  ttstate_t ttrace_state;
341898944Sobrien  thread_info *tinfo;
341946283Sdfr
342046283Sdfr  /* Do we have cached thread state that we can consult?  If so, use it. */
342146283Sdfr  tinfo = find_thread_info (map_from_gdb_tid (tid));
342246283Sdfr  if (tinfo != NULL)
342346283Sdfr    copy_ttstate_t (&ttrace_state, &tinfo->last_stop_state);
342446283Sdfr
342546283Sdfr  /* Nope, must read the thread's current state */
342646283Sdfr  else
342746283Sdfr    {
342846283Sdfr      tt_status = call_ttrace (TT_LWP_GET_STATE,
342998944Sobrien			       tid,
343098944Sobrien			       (TTRACE_ARG_TYPE) & ttrace_state,
343198944Sobrien			       (TTRACE_ARG_TYPE) sizeof (ttrace_state),
343298944Sobrien			       TT_NIL);
343346283Sdfr
343446283Sdfr      if (errno)
343598944Sobrien	perror_with_name ("ttrace");
343698944Sobrien
343746283Sdfr      if (tt_status < 0)
343898944Sobrien	return 0;
343946283Sdfr    }
344046283Sdfr
344146283Sdfr  if (ttrace_state.tts_event & TTEVT_VFORK)
344246283Sdfr    {
344346283Sdfr      *childpid = ttrace_state.tts_u.tts_fork.tts_fpid;
344446283Sdfr      return 1;
344546283Sdfr    }
344646283Sdfr
344746283Sdfr  return 0;
344846283Sdfr}
344946283Sdfr#endif
345046283Sdfr
345146283Sdfr
345246283Sdfr#if defined(CHILD_CAN_FOLLOW_VFORK_PRIOR_TO_EXEC)
345346283Sdfrint
345498944Sobrienchild_can_follow_vfork_prior_to_exec (void)
345546283Sdfr{
345646283Sdfr  /* ttrace does allow this.
345746283Sdfr
345846283Sdfr     ??rehrauer: However, I had major-league problems trying to
345946283Sdfr     convince wait_for_inferior to handle that case.  Perhaps when
346046283Sdfr     it is rewritten to grok multiple processes in an explicit way...
346198944Sobrien   */
346246283Sdfr  return 0;
346346283Sdfr}
346446283Sdfr#endif
346546283Sdfr
346646283Sdfr
346746283Sdfr#if defined(CHILD_INSERT_EXEC_CATCHPOINT)
346846283Sdfrint
346998944Sobrienchild_insert_exec_catchpoint (int tid)
347046283Sdfr{
347146283Sdfr  /* Enable reporting of exec events from the kernel. */
347246283Sdfr  /* ??rehrauer: For the moment, we're always enabling these events,
347346283Sdfr     and just ignoring them if there's no catchpoint to catch them.
347498944Sobrien   */
347546283Sdfr  return 0;
347646283Sdfr}
347746283Sdfr#endif
347846283Sdfr
347946283Sdfr
348046283Sdfr#if defined(CHILD_REMOVE_EXEC_CATCHPOINT)
348146283Sdfrint
348298944Sobrienchild_remove_exec_catchpoint (int tid)
348346283Sdfr{
348446283Sdfr  /* Disable reporting of execevents from the kernel. */
348546283Sdfr  /* ??rehrauer: For the moment, we're always enabling these events,
348646283Sdfr     and just ignoring them if there's no catchpoint to catch them.
348798944Sobrien   */
348846283Sdfr  return 0;
348946283Sdfr}
349046283Sdfr#endif
349146283Sdfr
349246283Sdfr
349346283Sdfr#if defined(CHILD_HAS_EXECD)
349446283Sdfrint
349598944Sobrienchild_has_execd (int tid, char **execd_pathname)
349646283Sdfr{
349798944Sobrien  int tt_status;
349898944Sobrien  ttstate_t ttrace_state;
349998944Sobrien  thread_info *tinfo;
350046283Sdfr
350146283Sdfr  /* Do we have cached thread state that we can consult?  If so, use it. */
350246283Sdfr  tinfo = find_thread_info (map_from_gdb_tid (tid));
350346283Sdfr  if (tinfo != NULL)
350446283Sdfr    copy_ttstate_t (&ttrace_state, &tinfo->last_stop_state);
350546283Sdfr
350646283Sdfr  /* Nope, must read the thread's current state */
350746283Sdfr  else
350846283Sdfr    {
350946283Sdfr      tt_status = call_ttrace (TT_LWP_GET_STATE,
351098944Sobrien			       tid,
351198944Sobrien			       (TTRACE_ARG_TYPE) & ttrace_state,
351298944Sobrien			       (TTRACE_ARG_TYPE) sizeof (ttrace_state),
351398944Sobrien			       TT_NIL);
351446283Sdfr
351546283Sdfr      if (errno)
351698944Sobrien	perror_with_name ("ttrace");
351798944Sobrien
351846283Sdfr      if (tt_status < 0)
351998944Sobrien	return 0;
352046283Sdfr    }
352146283Sdfr
352246283Sdfr  if (ttrace_state.tts_event & TTEVT_EXEC)
352346283Sdfr    {
352446283Sdfr      /* See child_pid_to_exec_file in this file: this is a macro.
352546283Sdfr       */
352698944Sobrien      char *exec_file = target_pid_to_exec_file (tid);
352798944Sobrien
352846283Sdfr      *execd_pathname = savestring (exec_file, strlen (exec_file));
352946283Sdfr      return 1;
353046283Sdfr    }
353146283Sdfr
353246283Sdfr  return 0;
353346283Sdfr}
353446283Sdfr#endif
353546283Sdfr
353646283Sdfr
353746283Sdfr#if defined(CHILD_HAS_SYSCALL_EVENT)
353846283Sdfrint
353998944Sobrienchild_has_syscall_event (int pid, enum target_waitkind *kind, int *syscall_id)
354046283Sdfr{
354198944Sobrien  int tt_status;
354298944Sobrien  ttstate_t ttrace_state;
354398944Sobrien  thread_info *tinfo;
354446283Sdfr
354546283Sdfr  /* Do we have cached thread state that we can consult?  If so, use it. */
354646283Sdfr  tinfo = find_thread_info (map_from_gdb_tid (pid));
354746283Sdfr  if (tinfo != NULL)
354846283Sdfr    copy_ttstate_t (&ttrace_state, &tinfo->last_stop_state);
354946283Sdfr
355046283Sdfr  /* Nope, must read the thread's current state */
355146283Sdfr  else
355246283Sdfr    {
355398944Sobrien      tt_status = call_ttrace (TT_LWP_GET_STATE,
355498944Sobrien			       pid,
355598944Sobrien			       (TTRACE_ARG_TYPE) & ttrace_state,
355698944Sobrien			       (TTRACE_ARG_TYPE) sizeof (ttrace_state),
355798944Sobrien			       TT_NIL);
355846283Sdfr
355946283Sdfr      if (errno)
356098944Sobrien	perror_with_name ("ttrace");
356198944Sobrien
356246283Sdfr      if (tt_status < 0)
356398944Sobrien	return 0;
356446283Sdfr    }
356546283Sdfr
356698944Sobrien  *kind = TARGET_WAITKIND_SPURIOUS;	/* Until proven otherwise... */
356746283Sdfr  *syscall_id = -1;
356846283Sdfr
356946283Sdfr  if (ttrace_state.tts_event & TTEVT_SYSCALL_ENTRY)
357046283Sdfr    *kind = TARGET_WAITKIND_SYSCALL_ENTRY;
357146283Sdfr  else if (ttrace_state.tts_event & TTEVT_SYSCALL_RETURN)
357246283Sdfr    *kind = TARGET_WAITKIND_SYSCALL_RETURN;
357346283Sdfr  else
357446283Sdfr    return 0;
357546283Sdfr
357646283Sdfr  *syscall_id = ttrace_state.tts_scno;
357746283Sdfr  return 1;
357846283Sdfr}
357946283Sdfr#endif
358098944Sobrien
358146283Sdfr
358246283Sdfr
358346283Sdfr#if defined(CHILD_THREAD_ALIVE)
358446283Sdfr
358546283Sdfr/* Check to see if the given thread is alive.
358698944Sobrien
358746283Sdfr * We'll trust the thread list, as the more correct
358846283Sdfr * approach of stopping the process and spinning down
358946283Sdfr * the OS's thread list is _very_ expensive.
359046283Sdfr *
359146283Sdfr * May need a FIXME for that reason.
359246283Sdfr */
359346283Sdfrint
359498944Sobrienchild_thread_alive (ptid_t ptid)
359546283Sdfr{
359698944Sobrien  lwpid_t gdb_tid = PIDGET (ptid);
359798944Sobrien  lwpid_t tid;
359846283Sdfr
359998944Sobrien  /* This spins down the lists twice.
360098944Sobrien   * Possible peformance improvement here!
360198944Sobrien   */
360298944Sobrien  tid = map_from_gdb_tid (gdb_tid);
360398944Sobrien  return !is_terminated (tid);
360446283Sdfr}
360546283Sdfr
360646283Sdfr#endif
360798944Sobrien
360846283Sdfr
360946283Sdfr
361046283Sdfr/* This function attempts to read the specified number of bytes from the
361146283Sdfr   save_state_t that is our view into the hardware registers, starting at
361246283Sdfr   ss_offset, and ending at ss_offset + sizeof_buf - 1
361346283Sdfr
361446283Sdfr   If this function succeeds, it deposits the fetched bytes into buf,
361546283Sdfr   and returns 0.
361646283Sdfr
361746283Sdfr   If it fails, it returns a negative result.  The contents of buf are
361846283Sdfr   undefined it this function fails.
361998944Sobrien */
362046283Sdfrint
362198944Sobrienread_from_register_save_state (int tid, TTRACE_ARG_TYPE ss_offset, char *buf,
362298944Sobrien			       int sizeof_buf)
362346283Sdfr{
362498944Sobrien  int tt_status;
362598944Sobrien  register_value_t register_value = 0;
362646283Sdfr
362746283Sdfr  tt_status = call_ttrace (TT_LWP_RUREGS,
362898944Sobrien			   tid,
362998944Sobrien			   ss_offset,
363098944Sobrien			   (TTRACE_ARG_TYPE) sizeof_buf,
363198944Sobrien			   (TTRACE_ARG_TYPE) buf);
363246283Sdfr
363398944Sobrien  if (tt_status == 1)
363498944Sobrien    /* Map ttrace's version of success to our version.
363598944Sobrien     * Sometime ttrace returns 0, but that's ok here.
363698944Sobrien     */
363798944Sobrien    return 0;
363898944Sobrien
363946283Sdfr  return tt_status;
364046283Sdfr}
364198944Sobrien
364246283Sdfr
364346283Sdfr/* This function attempts to write the specified number of bytes to the
364446283Sdfr   save_state_t that is our view into the hardware registers, starting at
364546283Sdfr   ss_offset, and ending at ss_offset + sizeof_buf - 1
364646283Sdfr
364746283Sdfr   If this function succeeds, it deposits the bytes in buf, and returns 0.
364846283Sdfr
364946283Sdfr   If it fails, it returns a negative result.  The contents of the save_state_t
365046283Sdfr   are undefined it this function fails.
365198944Sobrien */
365246283Sdfrint
365398944Sobrienwrite_to_register_save_state (int tid, TTRACE_ARG_TYPE ss_offset, char *buf,
365498944Sobrien			      int sizeof_buf)
365546283Sdfr{
365698944Sobrien  int tt_status;
365798944Sobrien  register_value_t register_value = 0;
365846283Sdfr
365946283Sdfr  tt_status = call_ttrace (TT_LWP_WUREGS,
366098944Sobrien			   tid,
366198944Sobrien			   ss_offset,
366298944Sobrien			   (TTRACE_ARG_TYPE) sizeof_buf,
366398944Sobrien			   (TTRACE_ARG_TYPE) buf);
366446283Sdfr  return tt_status;
366546283Sdfr}
366698944Sobrien
366746283Sdfr
366846283Sdfr/* This function is a sop to the largeish number of direct calls
366946283Sdfr   to call_ptrace that exist in other files.  Rather than create
367046283Sdfr   functions whose name abstracts away from ptrace, and change all
367146283Sdfr   the present callers of call_ptrace, we'll do the expedient (and
367246283Sdfr   perhaps only practical) thing.
367346283Sdfr
367446283Sdfr   Note HP-UX explicitly disallows a mix of ptrace & ttrace on a traced
367546283Sdfr   process.  Thus, we must translate all ptrace requests into their
367646283Sdfr   process-specific, ttrace equivalents.
367798944Sobrien */
367846283Sdfrint
367998944Sobriencall_ptrace (int pt_request, int gdb_tid, PTRACE_ARG3_TYPE addr, int data)
368046283Sdfr{
368198944Sobrien  ttreq_t tt_request;
368298944Sobrien  TTRACE_ARG_TYPE tt_addr = (TTRACE_ARG_TYPE) addr;
368398944Sobrien  TTRACE_ARG_TYPE tt_data = (TTRACE_ARG_TYPE) data;
368498944Sobrien  TTRACE_ARG_TYPE tt_addr2 = TT_NIL;
368598944Sobrien  int tt_status;
368698944Sobrien  register_value_t register_value;
368798944Sobrien  int read_buf;
368846283Sdfr
368946283Sdfr  /* Perform the necessary argument translation.  Note that some
369046283Sdfr     cases are funky enough in the ttrace realm that we handle them
369146283Sdfr     very specially.
369246283Sdfr   */
369398944Sobrien  switch (pt_request)
369498944Sobrien    {
369546283Sdfr      /* The following cases cannot conveniently be handled conveniently
369646283Sdfr         by merely adjusting the ptrace arguments and feeding into the
369746283Sdfr         generic call to ttrace at the bottom of this function.
369846283Sdfr
369946283Sdfr         Note that because all branches of this switch end in "return",
370046283Sdfr         there's no need for any "break" statements.
370198944Sobrien       */
370298944Sobrien    case PT_SETTRC:
370398944Sobrien      return parent_attach_all ();
370446283Sdfr
370598944Sobrien    case PT_RUREGS:
370698944Sobrien      tt_status = read_from_register_save_state (gdb_tid,
370798944Sobrien						 tt_addr,
370898944Sobrien						 &register_value,
370998944Sobrien						 sizeof (register_value));
371098944Sobrien      if (tt_status < 0)
371198944Sobrien	return tt_status;
371298944Sobrien      return register_value;
371346283Sdfr
371498944Sobrien    case PT_WUREGS:
371598944Sobrien      register_value = (int) tt_data;
371698944Sobrien      tt_status = write_to_register_save_state (gdb_tid,
371798944Sobrien						tt_addr,
371898944Sobrien						&register_value,
371998944Sobrien						sizeof (register_value));
372098944Sobrien      return tt_status;
372198944Sobrien      break;
372246283Sdfr
372398944Sobrien    case PT_READ_I:
372498944Sobrien      tt_status = call_ttrace (TT_PROC_RDTEXT,	/* Implicit 4-byte xfer becomes block-xfer. */
372598944Sobrien			       gdb_tid,
372698944Sobrien			       tt_addr,
372798944Sobrien			       (TTRACE_ARG_TYPE) 4,
372898944Sobrien			       (TTRACE_ARG_TYPE) & read_buf);
372998944Sobrien      if (tt_status < 0)
373098944Sobrien	return tt_status;
373198944Sobrien      return read_buf;
373246283Sdfr
373398944Sobrien    case PT_READ_D:
373498944Sobrien      tt_status = call_ttrace (TT_PROC_RDDATA,	/* Implicit 4-byte xfer becomes block-xfer. */
373598944Sobrien			       gdb_tid,
373698944Sobrien			       tt_addr,
373798944Sobrien			       (TTRACE_ARG_TYPE) 4,
373898944Sobrien			       (TTRACE_ARG_TYPE) & read_buf);
373998944Sobrien      if (tt_status < 0)
374098944Sobrien	return tt_status;
374198944Sobrien      return read_buf;
374246283Sdfr
374398944Sobrien    case PT_ATTACH:
374498944Sobrien      tt_status = call_real_ttrace (TT_PROC_ATTACH,
374598944Sobrien				    map_from_gdb_tid (gdb_tid),
374698944Sobrien				    (lwpid_t) TT_NIL,
374798944Sobrien				    tt_addr,
374898944Sobrien				    (TTRACE_ARG_TYPE) TT_VERSION,
374998944Sobrien				    tt_addr2);
375098944Sobrien      if (tt_status < 0)
375198944Sobrien	return tt_status;
375298944Sobrien      return tt_status;
375398944Sobrien
375446283Sdfr      /* The following cases are handled by merely adjusting the ptrace
375546283Sdfr         arguments and feeding into the generic call to ttrace.
375698944Sobrien       */
375798944Sobrien    case PT_DETACH:
375898944Sobrien      tt_request = TT_PROC_DETACH;
375998944Sobrien      break;
376046283Sdfr
376198944Sobrien    case PT_WRITE_I:
376298944Sobrien      tt_request = TT_PROC_WRTEXT;	/* Translates 4-byte xfer to block-xfer. */
376398944Sobrien      tt_data = 4;		/* This many bytes. */
376498944Sobrien      tt_addr2 = (TTRACE_ARG_TYPE) & data;	/* Address of xfer source. */
376598944Sobrien      break;
376646283Sdfr
376798944Sobrien    case PT_WRITE_D:
376898944Sobrien      tt_request = TT_PROC_WRDATA;	/* Translates 4-byte xfer to block-xfer. */
376998944Sobrien      tt_data = 4;		/* This many bytes. */
377098944Sobrien      tt_addr2 = (TTRACE_ARG_TYPE) & data;	/* Address of xfer source. */
377198944Sobrien      break;
377246283Sdfr
377398944Sobrien    case PT_RDTEXT:
377498944Sobrien      tt_request = TT_PROC_RDTEXT;
377598944Sobrien      break;
377646283Sdfr
377798944Sobrien    case PT_RDDATA:
377898944Sobrien      tt_request = TT_PROC_RDDATA;
377998944Sobrien      break;
378046283Sdfr
378198944Sobrien    case PT_WRTEXT:
378298944Sobrien      tt_request = TT_PROC_WRTEXT;
378398944Sobrien      break;
378446283Sdfr
378598944Sobrien    case PT_WRDATA:
378698944Sobrien      tt_request = TT_PROC_WRDATA;
378798944Sobrien      break;
378846283Sdfr
378998944Sobrien    case PT_CONTINUE:
379098944Sobrien      tt_request = TT_PROC_CONTINUE;
379198944Sobrien      break;
379246283Sdfr
379398944Sobrien    case PT_STEP:
379498944Sobrien      tt_request = TT_LWP_SINGLE;	/* Should not be making this request? */
379598944Sobrien      break;
379646283Sdfr
379798944Sobrien    case PT_KILL:
379898944Sobrien      tt_request = TT_PROC_EXIT;
379998944Sobrien      break;
380046283Sdfr
380198944Sobrien    case PT_GET_PROCESS_PATHNAME:
380298944Sobrien      tt_request = TT_PROC_GET_PATHNAME;
380398944Sobrien      break;
380446283Sdfr
380598944Sobrien    default:
380698944Sobrien      tt_request = pt_request;	/* Let ttrace be the one to complain. */
380798944Sobrien      break;
380898944Sobrien    }
380946283Sdfr
381046283Sdfr  return call_ttrace (tt_request,
381198944Sobrien		      gdb_tid,
381298944Sobrien		      tt_addr,
381398944Sobrien		      tt_data,
381498944Sobrien		      tt_addr2);
381546283Sdfr}
381646283Sdfr
381746283Sdfr/* Kill that pesky process!
381846283Sdfr */
381946283Sdfrvoid
382098944Sobrienkill_inferior (void)
382146283Sdfr{
382298944Sobrien  int tid;
382398944Sobrien  int wait_status;
382498944Sobrien  thread_info *t;
382546283Sdfr  thread_info **paranoia;
382698944Sobrien  int para_count, i;
382746283Sdfr
382898944Sobrien  if (PIDGET (inferior_ptid) == 0)
382946283Sdfr    return;
383046283Sdfr
383146283Sdfr  /* Walk the list of "threads", some of which are "pseudo threads",
383298944Sobrien     aka "processes".  For each that is NOT inferior_ptid, stop it,
383346283Sdfr     and detach it.
383446283Sdfr
383546283Sdfr     You see, we may not have just a single process to kill.  If we're
383646283Sdfr     restarting or quitting or detaching just after the inferior has
383746283Sdfr     forked, then we've actually two processes to clean up.
383846283Sdfr
383946283Sdfr     But we can't just call target_mourn_inferior() for each, since that
384046283Sdfr     zaps the target vector.
384198944Sobrien   */
384246283Sdfr
384398944Sobrien  paranoia = (thread_info **) xmalloc (thread_head.count *
384498944Sobrien				       sizeof (thread_info *));
384546283Sdfr  para_count = 0;
384698944Sobrien
384746283Sdfr  t = thread_head.head;
384898944Sobrien  while (t)
384998944Sobrien    {
385098944Sobrien
385198944Sobrien      paranoia[para_count] = t;
385298944Sobrien      for (i = 0; i < para_count; i++)
385398944Sobrien	{
385498944Sobrien	  if (t->next == paranoia[i])
385598944Sobrien	    {
385698944Sobrien	      warning ("Bad data in gdb's thread data; repairing.");
385798944Sobrien	      t->next = 0;
385898944Sobrien	    }
385998944Sobrien	}
386098944Sobrien      para_count++;
386198944Sobrien
386298944Sobrien      if (t->am_pseudo && (t->pid != PIDGET (inferior_ptid)))
386398944Sobrien	{
386498944Sobrien	  call_ttrace (TT_PROC_EXIT,
386598944Sobrien		       t->pid,
386698944Sobrien		       TT_NIL,
386798944Sobrien		       TT_NIL,
386898944Sobrien		       TT_NIL);
386998944Sobrien	}
387098944Sobrien      t = t->next;
387146283Sdfr    }
387246283Sdfr
387398944Sobrien  xfree (paranoia);
387446283Sdfr
387598944Sobrien  call_ttrace (TT_PROC_EXIT,
387698944Sobrien	       PIDGET (inferior_ptid),
387798944Sobrien	       TT_NIL,
387898944Sobrien	       TT_NIL,
387998944Sobrien	       TT_NIL);
388046283Sdfr  target_mourn_inferior ();
388198944Sobrien  clear_thread_info ();
388246283Sdfr}
388346283Sdfr
388446283Sdfr
388546283Sdfr#ifndef CHILD_RESUME
388646283Sdfr
388746283Sdfr/* Sanity check a thread about to be continued.
388846283Sdfr */
388946283Sdfrstatic void
389098944Sobrienthread_dropping_event_check (thread_info *p)
389146283Sdfr{
389298944Sobrien  if (!p->handled)
389398944Sobrien    {
389498944Sobrien      /*
389598944Sobrien       * This seems to happen when we "next" over a
389698944Sobrien       * "fork()" while following the parent.  If it's
389798944Sobrien       * the FORK event, that's ok.  If it's a SIGNAL
389898944Sobrien       * in the unfollowed child, that's ok to--but
389998944Sobrien       * how can we know that's what's going on?
390098944Sobrien       *
390198944Sobrien       * FIXME!
390298944Sobrien       */
390398944Sobrien      if (p->have_state)
390498944Sobrien	{
390598944Sobrien	  if (p->last_stop_state.tts_event == TTEVT_FORK)
390698944Sobrien	    {
390798944Sobrien	      /* Ok */
390898944Sobrien	      ;
390998944Sobrien	    }
391098944Sobrien	  else if (p->last_stop_state.tts_event == TTEVT_SIGNAL)
391198944Sobrien	    {
391298944Sobrien	      /* Ok, close eyes and let it happen.
391398944Sobrien	       */
391498944Sobrien	      ;
391598944Sobrien	    }
391698944Sobrien	  else
391798944Sobrien	    {
391898944Sobrien	      /* This shouldn't happen--we're dropping a
391998944Sobrien	       * real event.
392098944Sobrien	       */
392198944Sobrien	      warning ("About to continue process %d, thread %d with unhandled event %s.",
392298944Sobrien		       p->pid, p->tid,
392398944Sobrien		       get_printable_name_of_ttrace_event (
392498944Sobrien					     p->last_stop_state.tts_event));
392546283Sdfr
392646283Sdfr#ifdef PARANOIA
392798944Sobrien	      if (debug_on)
392898944Sobrien		print_tthread (p);
392946283Sdfr#endif
393098944Sobrien	    }
393198944Sobrien	}
393298944Sobrien      else
393398944Sobrien	{
393498944Sobrien	  /* No saved state, have to assume it failed.
393598944Sobrien	   */
393698944Sobrien	  warning ("About to continue process %d, thread %d with unhandled event.",
393798944Sobrien		   p->pid, p->tid);
393846283Sdfr#ifdef PARANOIA
393998944Sobrien	  if (debug_on)
394098944Sobrien	    print_tthread (p);
394146283Sdfr#endif
394298944Sobrien	}
394346283Sdfr    }
394446283Sdfr
394598944Sobrien}				/* thread_dropping_event_check */
394698944Sobrien
394746283Sdfr/* Use a loop over the threads to continue all the threads but
394846283Sdfr * the one specified, which is to be stepped.
394946283Sdfr */
395046283Sdfrstatic void
395198944Sobrienthreads_continue_all_but_one (lwpid_t gdb_tid, int signal)
395246283Sdfr{
395398944Sobrien  thread_info *p;
395498944Sobrien  int thread_signal;
395598944Sobrien  lwpid_t real_tid;
395698944Sobrien  lwpid_t scan_tid;
395798944Sobrien  ttstate_t state;
395898944Sobrien  int real_pid;
395998944Sobrien
396046283Sdfr#ifdef THREAD_DEBUG
396198944Sobrien  if (debug_on)
396298944Sobrien    printf ("Using loop over threads to step/resume with signals\n");
396346283Sdfr#endif
396446283Sdfr
396598944Sobrien  /* First update the thread list.
396698944Sobrien   */
396798944Sobrien  set_all_unseen ();
396898944Sobrien  real_tid = map_from_gdb_tid (gdb_tid);
396998944Sobrien  real_pid = get_pid_for (real_tid);
397098944Sobrien
397198944Sobrien  scan_tid = get_process_first_stopped_thread_id (real_pid, &state);
397298944Sobrien  while (0 != scan_tid)
397398944Sobrien    {
397498944Sobrien
397546283Sdfr#ifdef THREAD_DEBUG
397698944Sobrien      /* FIX: later should check state is stopped;
397798944Sobrien       * state.tts_flags & TTS_STATEMASK == TTS_WASSUSPENDED
397898944Sobrien       */
397998944Sobrien      if (debug_on)
398098944Sobrien	if (state.tts_flags & TTS_STATEMASK != TTS_WASSUSPENDED)
398198944Sobrien	  printf ("About to continue non-stopped thread %d\n", scan_tid);
398246283Sdfr#endif
398346283Sdfr
398498944Sobrien      p = find_thread_info (scan_tid);
398598944Sobrien      if (NULL == p)
398698944Sobrien	{
398798944Sobrien	  add_tthread (real_pid, scan_tid);
398898944Sobrien	  p = find_thread_info (scan_tid);
398946283Sdfr
399098944Sobrien	  /* This is either a newly-created thread or the
399198944Sobrien	   * result of a fork; in either case there's no
399298944Sobrien	   * actual event to worry about.
399398944Sobrien	   */
399498944Sobrien	  p->handled = 1;
399546283Sdfr
399698944Sobrien	  if (state.tts_event != TTEVT_NONE)
399798944Sobrien	    {
399898944Sobrien	      /* Oops, do need to worry!
399998944Sobrien	       */
400098944Sobrien	      warning ("Unexpected thread with \"%s\" event.",
400198944Sobrien		       get_printable_name_of_ttrace_event (state.tts_event));
400298944Sobrien	    }
400398944Sobrien	}
400498944Sobrien      else if (scan_tid != p->tid)
400598944Sobrien	error ("Bad data in thread database.");
400646283Sdfr
400746283Sdfr#ifdef THREAD_DEBUG
400898944Sobrien      if (debug_on)
400998944Sobrien	if (p->terminated)
401098944Sobrien	  printf ("Why are we continuing a dead thread?\n");
401146283Sdfr#endif
401246283Sdfr
401398944Sobrien      p->seen = 1;
401498944Sobrien
401598944Sobrien      scan_tid = get_process_next_stopped_thread_id (real_pid, &state);
401646283Sdfr    }
401746283Sdfr
401898944Sobrien  /* Remove unseen threads.
401998944Sobrien   */
402098944Sobrien  update_thread_list ();
402146283Sdfr
402298944Sobrien  /* Now run down the thread list and continue or step.
402398944Sobrien   */
402498944Sobrien  for (p = thread_head.head; p; p = p->next)
402598944Sobrien    {
402646283Sdfr
402798944Sobrien      /* Sanity check.
402898944Sobrien       */
402998944Sobrien      thread_dropping_event_check (p);
403046283Sdfr
403198944Sobrien      /* Pass the correct signals along.
403298944Sobrien       */
403398944Sobrien      if (p->have_signal)
403498944Sobrien	{
403598944Sobrien	  thread_signal = p->signal_value;
403698944Sobrien	  p->have_signal = 0;
403798944Sobrien	}
403898944Sobrien      else
403998944Sobrien	thread_signal = 0;
404046283Sdfr
404198944Sobrien      if (p->tid != real_tid)
404298944Sobrien	{
404398944Sobrien	  /*
404498944Sobrien	   * Not the thread of interest, so continue it
404598944Sobrien	   * as the user expects.
404698944Sobrien	   */
404798944Sobrien	  if (p->stepping_mode == DO_STEP)
404898944Sobrien	    {
404998944Sobrien	      /* Just step this thread.
405098944Sobrien	       */
405198944Sobrien	      call_ttrace (
405298944Sobrien			    TT_LWP_SINGLE,
405398944Sobrien			    p->tid,
405498944Sobrien			    TT_USE_CURRENT_PC,
405598944Sobrien			    (TTRACE_ARG_TYPE) target_signal_to_host (signal),
405698944Sobrien			    TT_NIL);
405798944Sobrien	    }
405898944Sobrien	  else
405998944Sobrien	    {
406098944Sobrien	      /* Regular continue (default case).
406198944Sobrien	       */
406298944Sobrien	      call_ttrace (
406398944Sobrien			    TT_LWP_CONTINUE,
406498944Sobrien			    p->tid,
406598944Sobrien			    TT_USE_CURRENT_PC,
406698944Sobrien		    (TTRACE_ARG_TYPE) target_signal_to_host (thread_signal),
406798944Sobrien			    TT_NIL);
406898944Sobrien	    }
406998944Sobrien	}
407098944Sobrien      else
407198944Sobrien	{
407298944Sobrien	  /* Step the thread of interest.
407398944Sobrien	   */
407498944Sobrien	  call_ttrace (
407598944Sobrien			TT_LWP_SINGLE,
407698944Sobrien			real_tid,
407798944Sobrien			TT_USE_CURRENT_PC,
407898944Sobrien			(TTRACE_ARG_TYPE) target_signal_to_host (signal),
407998944Sobrien			TT_NIL);
408098944Sobrien	}
408198944Sobrien    }				/* Loop over threads */
408298944Sobrien}				/* End threads_continue_all_but_one */
408398944Sobrien
408446283Sdfr/* Use a loop over the threads to continue all the threads.
408546283Sdfr * This is done when a signal must be sent to any of the threads.
408646283Sdfr */
408746283Sdfrstatic void
408898944Sobrienthreads_continue_all_with_signals (lwpid_t gdb_tid, int signal)
408946283Sdfr{
409098944Sobrien  thread_info *p;
409198944Sobrien  int thread_signal;
409298944Sobrien  lwpid_t real_tid;
409398944Sobrien  lwpid_t scan_tid;
409498944Sobrien  ttstate_t state;
409598944Sobrien  int real_pid;
409646283Sdfr
409746283Sdfr#ifdef THREAD_DEBUG
409898944Sobrien  if (debug_on)
409998944Sobrien    printf ("Using loop over threads to resume with signals\n");
410046283Sdfr#endif
410146283Sdfr
410298944Sobrien  /* Scan and update thread list.
410398944Sobrien   */
410498944Sobrien  set_all_unseen ();
410598944Sobrien  real_tid = map_from_gdb_tid (gdb_tid);
410698944Sobrien  real_pid = get_pid_for (real_tid);
410746283Sdfr
410898944Sobrien  scan_tid = get_process_first_stopped_thread_id (real_pid, &state);
410998944Sobrien  while (0 != scan_tid)
411098944Sobrien    {
411198944Sobrien
411246283Sdfr#ifdef THREAD_DEBUG
411398944Sobrien      if (debug_on)
411498944Sobrien	if (state.tts_flags & TTS_STATEMASK != TTS_WASSUSPENDED)
411598944Sobrien	  warning ("About to continue non-stopped thread %d\n", scan_tid);
411646283Sdfr#endif
411746283Sdfr
411898944Sobrien      p = find_thread_info (scan_tid);
411998944Sobrien      if (NULL == p)
412098944Sobrien	{
412198944Sobrien	  add_tthread (real_pid, scan_tid);
412298944Sobrien	  p = find_thread_info (scan_tid);
412346283Sdfr
412498944Sobrien	  /* This is either a newly-created thread or the
412598944Sobrien	   * result of a fork; in either case there's no
412698944Sobrien	   * actual event to worry about.
412798944Sobrien	   */
412898944Sobrien	  p->handled = 1;
412946283Sdfr
413098944Sobrien	  if (state.tts_event != TTEVT_NONE)
413198944Sobrien	    {
413298944Sobrien	      /* Oops, do need to worry!
413398944Sobrien	       */
413498944Sobrien	      warning ("Unexpected thread with \"%s\" event.",
413598944Sobrien		       get_printable_name_of_ttrace_event (state.tts_event));
413698944Sobrien	    }
413798944Sobrien	}
413846283Sdfr
413946283Sdfr#ifdef THREAD_DEBUG
414098944Sobrien      if (debug_on)
414198944Sobrien	if (p->terminated)
414298944Sobrien	  printf ("Why are we continuing a dead thread? (1)\n");
414346283Sdfr#endif
414446283Sdfr
414598944Sobrien      p->seen = 1;
414646283Sdfr
414798944Sobrien      scan_tid = get_process_next_stopped_thread_id (real_pid, &state);
414846283Sdfr    }
414946283Sdfr
415098944Sobrien  /* Remove unseen threads from our list.
415198944Sobrien   */
415298944Sobrien  update_thread_list ();
415346283Sdfr
415498944Sobrien  /* Continue the threads.
415598944Sobrien   */
415698944Sobrien  for (p = thread_head.head; p; p = p->next)
415798944Sobrien    {
415846283Sdfr
415998944Sobrien      /* Sanity check.
416098944Sobrien       */
416198944Sobrien      thread_dropping_event_check (p);
416246283Sdfr
416398944Sobrien      /* Pass the correct signals along.
416498944Sobrien       */
416598944Sobrien      if (p->tid == real_tid)
416698944Sobrien	{
416798944Sobrien	  thread_signal = signal;
416898944Sobrien	  p->have_signal = 0;
416998944Sobrien	}
417098944Sobrien      else if (p->have_signal)
417198944Sobrien	{
417298944Sobrien	  thread_signal = p->signal_value;
417398944Sobrien	  p->have_signal = 0;
417498944Sobrien	}
417598944Sobrien      else
417698944Sobrien	thread_signal = 0;
417746283Sdfr
417898944Sobrien      if (p->stepping_mode == DO_STEP)
417998944Sobrien	{
418098944Sobrien	  call_ttrace (
418198944Sobrien			TT_LWP_SINGLE,
418298944Sobrien			p->tid,
418398944Sobrien			TT_USE_CURRENT_PC,
418498944Sobrien			(TTRACE_ARG_TYPE) target_signal_to_host (signal),
418598944Sobrien			TT_NIL);
418698944Sobrien	}
418798944Sobrien      else
418898944Sobrien	{
418998944Sobrien	  /* Continue this thread (default case).
419098944Sobrien	   */
419198944Sobrien	  call_ttrace (
419298944Sobrien			TT_LWP_CONTINUE,
419398944Sobrien			p->tid,
419498944Sobrien			TT_USE_CURRENT_PC,
419598944Sobrien		    (TTRACE_ARG_TYPE) target_signal_to_host (thread_signal),
419698944Sobrien			TT_NIL);
419798944Sobrien	}
419846283Sdfr    }
419998944Sobrien}				/* End threads_continue_all_with_signals */
420046283Sdfr
420146283Sdfr/* Step one thread only.
420246283Sdfr */
420346283Sdfrstatic void
420498944Sobrienthread_fake_step (lwpid_t tid, enum target_signal signal)
420546283Sdfr{
420698944Sobrien  thread_info *p;
420746283Sdfr
420846283Sdfr#ifdef THREAD_DEBUG
420998944Sobrien  if (debug_on)
421098944Sobrien    {
421198944Sobrien      printf ("Doing a fake-step over a bpt, etc. for %d\n", tid);
421246283Sdfr
421398944Sobrien      if (is_terminated (tid))
421498944Sobrien	printf ("Why are we continuing a dead thread? (4)\n");
421546283Sdfr    }
421646283Sdfr#endif
421746283Sdfr
421898944Sobrien  if (doing_fake_step)
421998944Sobrien    warning ("Step while step already in progress.");
422098944Sobrien
422198944Sobrien  /* See if there's a saved signal value for this
422298944Sobrien   * thread to be passed on, but no current signal.
422398944Sobrien   */
422498944Sobrien  p = find_thread_info (tid);
422598944Sobrien  if (p != NULL)
422698944Sobrien    {
422798944Sobrien      if (p->have_signal && signal == TARGET_SIGNAL_0)
422898944Sobrien	{
422998944Sobrien	  /* Pass on a saved signal.
423098944Sobrien	   */
423198944Sobrien	  signal = p->signal_value;
423298944Sobrien	}
423398944Sobrien
423498944Sobrien      p->have_signal = 0;
423546283Sdfr    }
423646283Sdfr
423798944Sobrien  if (!p->handled)
423898944Sobrien    warning ("Internal error: continuing unhandled thread.");
423946283Sdfr
424098944Sobrien  call_ttrace (TT_LWP_SINGLE,
424198944Sobrien	       tid,
424298944Sobrien	       TT_USE_CURRENT_PC,
424398944Sobrien	       (TTRACE_ARG_TYPE) target_signal_to_host (signal),
424498944Sobrien	       TT_NIL);
424546283Sdfr
424698944Sobrien  /* Do bookkeeping so "call_ttrace_wait" knows it has to wait
424798944Sobrien   * for this thread only, and clear any saved signal info.
424898944Sobrien   */
424998944Sobrien  doing_fake_step = 1;
425098944Sobrien  fake_step_tid = tid;
425146283Sdfr
425298944Sobrien}				/* End thread_fake_step */
425398944Sobrien
425446283Sdfr/* Continue one thread when a signal must be sent to it.
425546283Sdfr */
425646283Sdfrstatic void
425798944Sobrienthreads_continue_one_with_signal (lwpid_t gdb_tid, int signal)
425846283Sdfr{
425998944Sobrien  thread_info *p;
426098944Sobrien  lwpid_t real_tid;
426198944Sobrien  int real_pid;
426298944Sobrien
426346283Sdfr#ifdef THREAD_DEBUG
426498944Sobrien  if (debug_on)
426598944Sobrien    printf ("Continuing one thread with a signal\n");
426646283Sdfr#endif
426746283Sdfr
426898944Sobrien  real_tid = map_from_gdb_tid (gdb_tid);
426998944Sobrien  real_pid = get_pid_for (real_tid);
427046283Sdfr
427198944Sobrien  p = find_thread_info (real_tid);
427298944Sobrien  if (NULL == p)
427398944Sobrien    {
427498944Sobrien      add_tthread (real_pid, real_tid);
427546283Sdfr    }
427646283Sdfr
427746283Sdfr#ifdef THREAD_DEBUG
427898944Sobrien  if (debug_on)
427998944Sobrien    if (p->terminated)
428098944Sobrien      printf ("Why are we continuing a dead thread? (2)\n");
428146283Sdfr#endif
428246283Sdfr
428398944Sobrien  if (!p->handled)
428498944Sobrien    warning ("Internal error: continuing unhandled thread.");
428598944Sobrien
428698944Sobrien  p->have_signal = 0;
428798944Sobrien
428898944Sobrien  call_ttrace (TT_LWP_CONTINUE,
428998944Sobrien	       gdb_tid,
429098944Sobrien	       TT_USE_CURRENT_PC,
429198944Sobrien	       (TTRACE_ARG_TYPE) target_signal_to_host (signal),
429298944Sobrien	       TT_NIL);
429346283Sdfr}
429446283Sdfr#endif
429546283Sdfr
429646283Sdfr#ifndef CHILD_RESUME
429746283Sdfr
429846283Sdfr/* Resume execution of the inferior process.
429998944Sobrien
430046283Sdfr * This routine is in charge of setting the "handled" bits.
430146283Sdfr *
430246283Sdfr *   If STEP is zero,      continue it.
430346283Sdfr *   If STEP is nonzero,   single-step it.
430446283Sdfr *
430546283Sdfr *   If SIGNAL is nonzero, give it that signal.
430646283Sdfr *
430746283Sdfr *   If TID is -1,         apply to all threads.
430846283Sdfr *   If TID is not -1,     apply to specified thread.
430946283Sdfr *
431046283Sdfr *           STEP
431146283Sdfr *      \      !0                        0
431246283Sdfr *  TID  \________________________________________________
431346283Sdfr *       |
431446283Sdfr *   -1  |   Step current            Continue all threads
431546283Sdfr *       |   thread and              (but which gets any
431646283Sdfr *       |   continue others         signal?--We look at
431798944Sobrien *       |                           "inferior_ptid")
431846283Sdfr *       |
431946283Sdfr *    N  |   Step _this_ thread      Continue _this_ thread
432046283Sdfr *       |   and leave others        and leave others
432146283Sdfr *       |   stopped; internally     stopped; used only for
432246283Sdfr *       |   used by gdb, never      hardware watchpoints
432346283Sdfr *       |   a user command.         and attach, never a
432446283Sdfr *       |                           user command.
432546283Sdfr */
432646283Sdfrvoid
432798944Sobrienchild_resume (ptid_t ptid, int step, enum target_signal signal)
432846283Sdfr{
432998944Sobrien  int resume_all_threads;
433046283Sdfr  lwpid_t tid;
433198944Sobrien  process_state_t new_process_state;
433298944Sobrien  lwpid_t gdb_tid = PIDGET (ptid);
433346283Sdfr
433446283Sdfr  resume_all_threads =
433546283Sdfr    (gdb_tid == INFTTRACE_ALL_THREADS) ||
433646283Sdfr    (vfork_in_flight);
433746283Sdfr
433898944Sobrien  if (resume_all_threads)
433998944Sobrien    {
434098944Sobrien      /* Resume all threads, but first pick a tid value
434198944Sobrien       * so we can get the pid when in call_ttrace doing
434298944Sobrien       * the map.
434398944Sobrien       */
434498944Sobrien      if (vfork_in_flight)
434598944Sobrien	tid = vforking_child_pid;
434698944Sobrien      else
434798944Sobrien	tid = map_from_gdb_tid (PIDGET (inferior_ptid));
434898944Sobrien    }
434946283Sdfr  else
435098944Sobrien    tid = map_from_gdb_tid (gdb_tid);
435146283Sdfr
435246283Sdfr#ifdef THREAD_DEBUG
435398944Sobrien  if (debug_on)
435498944Sobrien    {
435598944Sobrien      if (more_events_left)
435698944Sobrien	printf ("More events; ");
435746283Sdfr
435898944Sobrien      if (signal != 0)
435998944Sobrien	printf ("Sending signal %d; ", signal);
436046283Sdfr
436198944Sobrien      if (resume_all_threads)
436298944Sobrien	{
436398944Sobrien	  if (step == 0)
436498944Sobrien	    printf ("Continue process %d\n", tid);
436598944Sobrien	  else
436698944Sobrien	    printf ("Step/continue thread %d\n", tid);
436798944Sobrien	}
436898944Sobrien      else
436998944Sobrien	{
437098944Sobrien	  if (step == 0)
437198944Sobrien	    printf ("Continue thread %d\n", tid);
437298944Sobrien	  else
437398944Sobrien	    printf ("Step just thread %d\n", tid);
437498944Sobrien	}
437598944Sobrien
437698944Sobrien      if (vfork_in_flight)
437798944Sobrien	printf ("Vfork in flight\n");
437898944Sobrien    }
437946283Sdfr#endif
438046283Sdfr
438198944Sobrien  if (process_state == RUNNING)
438298944Sobrien    warning ("Internal error in resume logic; doing resume or step anyway.");
438346283Sdfr
438498944Sobrien  if (!step			/* Asked to continue...       */
438598944Sobrien      && resume_all_threads	/* whole process..            */
438698944Sobrien      && signal != 0		/* with a signal...           */
438798944Sobrien      && more_events_left > 0)
438898944Sobrien    {				/* but we can't yet--save it! */
438998944Sobrien
439046283Sdfr      /* Continue with signal means we have to set the pending
439146283Sdfr       * signal value for this thread.
439246283Sdfr       */
439346283Sdfr      thread_info *k;
439498944Sobrien
439546283Sdfr#ifdef THREAD_DEBUG
439698944Sobrien      if (debug_on)
439798944Sobrien	printf ("Saving signal %d for thread %d\n", signal, tid);
439846283Sdfr#endif
439946283Sdfr
440098944Sobrien      k = find_thread_info (tid);
440198944Sobrien      if (k != NULL)
440298944Sobrien	{
440398944Sobrien	  k->have_signal = 1;
440498944Sobrien	  k->signal_value = signal;
440546283Sdfr
440646283Sdfr#ifdef THREAD_DEBUG
440798944Sobrien	  if (debug_on)
440898944Sobrien	    if (k->terminated)
440998944Sobrien	      printf ("Why are we continuing a dead thread? (3)\n");
441046283Sdfr#endif
441146283Sdfr
441298944Sobrien	}
441346283Sdfr
441446283Sdfr#ifdef THREAD_DEBUG
441598944Sobrien      else if (debug_on)
441698944Sobrien	{
441798944Sobrien	  printf ("No thread info for tid %d\n", tid);
441898944Sobrien	}
441946283Sdfr#endif
442098944Sobrien    }
442146283Sdfr
442246283Sdfr  /* Are we faking this "continue" or "step"?
442398944Sobrien
442446283Sdfr   * We used to do steps by continuing all the threads for
442546283Sdfr   * which the events had been handled already.  While
442646283Sdfr   * conceptually nicer (hides it all in a lower level), this
442746283Sdfr   * can lead to starvation and a hang (e.g. all but one thread
442846283Sdfr   * are unhandled at a breakpoint just before a "join" operation,
442946283Sdfr   * and one thread is in the join, and the user wants to step that
443046283Sdfr   * thread).
443146283Sdfr   */
443298944Sobrien  if (resume_all_threads	/* Whole process, therefore user command */
443398944Sobrien      && more_events_left > 0)
443498944Sobrien    {				/* But we can't do this yet--fake it! */
443546283Sdfr      thread_info *p;
443698944Sobrien
443798944Sobrien      if (!step)
443898944Sobrien	{
443998944Sobrien	  /* No need to do any notes on a per-thread
444098944Sobrien	   * basis--we're done!
444198944Sobrien	   */
444246283Sdfr#ifdef WAIT_BUFFER_DEBUG
444398944Sobrien	  if (debug_on)
444498944Sobrien	    printf ("Faking a process resume.\n");
444546283Sdfr#endif
444646283Sdfr
444798944Sobrien	  return;
444898944Sobrien	}
444998944Sobrien      else
445098944Sobrien	{
445146283Sdfr
445246283Sdfr#ifdef WAIT_BUFFER_DEBUG
445398944Sobrien	  if (debug_on)
445498944Sobrien	    printf ("Faking a process step.\n");
445546283Sdfr#endif
445646283Sdfr
445798944Sobrien	}
445846283Sdfr
445998944Sobrien      p = find_thread_info (tid);
446098944Sobrien      if (p == NULL)
446198944Sobrien	{
446298944Sobrien	  warning ("No thread information for tid %d, 'next' command ignored.\n", tid);
446398944Sobrien	  return;
446498944Sobrien	}
446598944Sobrien      else
446698944Sobrien	{
446798944Sobrien
446846283Sdfr#ifdef THREAD_DEBUG
446998944Sobrien	  if (debug_on)
447098944Sobrien	    if (p->terminated)
447198944Sobrien	      printf ("Why are we continuing a dead thread? (3.5)\n");
447246283Sdfr#endif
447346283Sdfr
447498944Sobrien	  if (p->stepping_mode != DO_DEFAULT)
447598944Sobrien	    {
447698944Sobrien	      warning ("Step or continue command applied to thread which is already stepping or continuing; command ignored.");
447746283Sdfr
447898944Sobrien	      return;
447998944Sobrien	    }
448046283Sdfr
448198944Sobrien	  if (step)
448298944Sobrien	    p->stepping_mode = DO_STEP;
448398944Sobrien	  else
448498944Sobrien	    p->stepping_mode = DO_CONTINUE;
448546283Sdfr
448698944Sobrien	  return;
448798944Sobrien	}			/* Have thread info */
448898944Sobrien    }				/* Must fake step or go */
448946283Sdfr
449046283Sdfr  /* Execept for fake-steps, from here on we know we are
449146283Sdfr   * going to wind up with a running process which will
449246283Sdfr   * need a real wait.
449346283Sdfr   */
449446283Sdfr  new_process_state = RUNNING;
449546283Sdfr
449646283Sdfr  /* An address of TT_USE_CURRENT_PC tells ttrace to continue from where
449746283Sdfr   * it was.  (If GDB wanted it to start some other way, we have already
449846283Sdfr   * written a new PC value to the child.)
449946283Sdfr   *
450046283Sdfr   * If this system does not support PT_STEP, a higher level function will
450146283Sdfr   * have called single_step() to transmute the step request into a
450246283Sdfr   * continue request (by setting breakpoints on all possible successor
450346283Sdfr   * instructions), so we don't have to worry about that here.
450446283Sdfr   */
450598944Sobrien  if (step)
450698944Sobrien    {
450798944Sobrien      if (resume_all_threads)
450898944Sobrien	{
450998944Sobrien	  /*
451098944Sobrien	   * Regular user step: other threads get a "continue".
451198944Sobrien	   */
451298944Sobrien	  threads_continue_all_but_one (tid, signal);
451398944Sobrien	  clear_all_handled ();
451498944Sobrien	  clear_all_stepping_mode ();
451598944Sobrien	}
451646283Sdfr
451798944Sobrien      else
451898944Sobrien	{
451998944Sobrien	  /* "Fake step": gdb is stepping one thread over a
452098944Sobrien	   * breakpoint, watchpoint, or out of a library load
452198944Sobrien	   * event, etc.  The rest just stay where they are.
452298944Sobrien	   *
452398944Sobrien	   * Also used when there are pending events: we really
452498944Sobrien	   * step the current thread, but leave the rest stopped.
452598944Sobrien	   * Users can't request this, but "wait_for_inferior"
452698944Sobrien	   * does--a lot!
452798944Sobrien	   */
452898944Sobrien	  thread_fake_step (tid, signal);
452946283Sdfr
453098944Sobrien	  /* Clear the "handled" state of this thread, because
453198944Sobrien	   * we'll soon get a new event for it.  Other events
453298944Sobrien	   * stay as they were.
453398944Sobrien	   */
453498944Sobrien	  clear_handled (tid);
453598944Sobrien	  clear_stepping_mode (tid);
453698944Sobrien	  new_process_state = FAKE_STEPPING;
453798944Sobrien	}
453898944Sobrien    }
453998944Sobrien
454098944Sobrien  else
454198944Sobrien    {
454246283Sdfr      /* TT_LWP_CONTINUE can pass signals to threads,
454346283Sdfr       * TT_PROC_CONTINUE can't.  So if there are any
454446283Sdfr       * signals to pass, we have to use the (slower)
454546283Sdfr       * loop over the stopped threads.
454646283Sdfr       *
454746283Sdfr       * Equally, if we have to not continue some threads,
454846283Sdfr       * due to saved events, we have to use the loop.
454946283Sdfr       */
455098944Sobrien      if ((signal != 0) || saved_signals_exist ())
455198944Sobrien	{
455298944Sobrien	  if (resume_all_threads)
455398944Sobrien	    {
455446283Sdfr
455546283Sdfr#ifdef THREAD_DEBUG
455698944Sobrien	      if (debug_on)
455798944Sobrien		printf ("Doing a continue by loop of all threads\n");
455846283Sdfr#endif
455946283Sdfr
456098944Sobrien	      threads_continue_all_with_signals (tid, signal);
456146283Sdfr
456298944Sobrien	      clear_all_handled ();
456398944Sobrien	      clear_all_stepping_mode ();
456498944Sobrien	    }
456546283Sdfr
456698944Sobrien	  else
456798944Sobrien	    {
456846283Sdfr#ifdef THREAD_DEBUG
456998944Sobrien	      printf ("Doing a continue w/signal of just thread %d\n", tid);
457046283Sdfr#endif
457146283Sdfr
457298944Sobrien	      threads_continue_one_with_signal (tid, signal);
457346283Sdfr
457498944Sobrien	      /* Clear the "handled" state of this thread, because
457598944Sobrien	       * we'll soon get a new event for it.  Other events
457698944Sobrien	       * can stay as they were.
457798944Sobrien	       */
457898944Sobrien	      clear_handled (tid);
457998944Sobrien	      clear_stepping_mode (tid);
458098944Sobrien	    }
458198944Sobrien	}
458246283Sdfr
458398944Sobrien      else
458498944Sobrien	{
458598944Sobrien	  /* No signals to send.
458698944Sobrien	   */
458798944Sobrien	  if (resume_all_threads)
458898944Sobrien	    {
458946283Sdfr#ifdef THREAD_DEBUG
459098944Sobrien	      if (debug_on)
459198944Sobrien		printf ("Doing a continue by process of process %d\n", tid);
459246283Sdfr#endif
459346283Sdfr
459498944Sobrien	      if (more_events_left > 0)
459598944Sobrien		{
459698944Sobrien		  warning ("Losing buffered events on continue.");
459798944Sobrien		  more_events_left = 0;
459898944Sobrien		}
459946283Sdfr
460098944Sobrien	      call_ttrace (TT_PROC_CONTINUE,
460198944Sobrien			   tid,
460298944Sobrien			   TT_NIL,
460398944Sobrien			   TT_NIL,
460498944Sobrien			   TT_NIL);
460546283Sdfr
460698944Sobrien	      clear_all_handled ();
460798944Sobrien	      clear_all_stepping_mode ();
460898944Sobrien	    }
460946283Sdfr
461098944Sobrien	  else
461198944Sobrien	    {
461246283Sdfr#ifdef THREAD_DEBUG
461398944Sobrien	      if (debug_on)
461498944Sobrien		{
461598944Sobrien		  printf ("Doing a continue of just thread %d\n", tid);
461698944Sobrien		  if (is_terminated (tid))
461798944Sobrien		    printf ("Why are we continuing a dead thread? (5)\n");
461898944Sobrien		}
461946283Sdfr#endif
462046283Sdfr
462198944Sobrien	      call_ttrace (TT_LWP_CONTINUE,
462298944Sobrien			   tid,
462398944Sobrien			   TT_NIL,
462498944Sobrien			   TT_NIL,
462598944Sobrien			   TT_NIL);
462646283Sdfr
462798944Sobrien	      /* Clear the "handled" state of this thread, because
462898944Sobrien	       * we'll soon get a new event for it.  Other events
462998944Sobrien	       * can stay as they were.
463098944Sobrien	       */
463198944Sobrien	      clear_handled (tid);
463298944Sobrien	      clear_stepping_mode (tid);
463398944Sobrien	    }
463498944Sobrien	}
463598944Sobrien    }
463646283Sdfr
463746283Sdfr  process_state = new_process_state;
463846283Sdfr
463946283Sdfr#ifdef WAIT_BUFFER_DEBUG
464098944Sobrien  if (debug_on)
464198944Sobrien    printf ("Process set to %s\n",
464298944Sobrien	    get_printable_name_of_process_state (process_state));
464346283Sdfr#endif
464446283Sdfr
464546283Sdfr}
464646283Sdfr#endif /* CHILD_RESUME */
464798944Sobrien
464846283Sdfr
464946283Sdfr#ifdef ATTACH_DETACH
465046283Sdfr/*
465146283Sdfr * Like it says.
465246283Sdfr *
465398944Sobrien * One worry is that we may not be attaching to "inferior_ptid"
465446283Sdfr * and thus may not want to clear out our data.  FIXME?
465546283Sdfr *
465646283Sdfr */
465746283Sdfrstatic void
465898944Sobrienupdate_thread_state_after_attach (int pid, attach_continue_t kind_of_go)
465946283Sdfr{
466098944Sobrien  int tt_status;
466198944Sobrien  ttstate_t thread_state;
466298944Sobrien  lwpid_t a_thread;
466398944Sobrien  lwpid_t tid;
466446283Sdfr
466546283Sdfr  /* The process better be stopped.
466646283Sdfr   */
466798944Sobrien  if (process_state != STOPPED
466898944Sobrien      && process_state != VFORKING)
466998944Sobrien    warning ("Internal error attaching.");
467046283Sdfr
467146283Sdfr  /* Clear out old tthread info and start over.  This has the
467246283Sdfr   * side effect of ensuring that the TRAP is reported as being
467346283Sdfr   * in the right thread (re-mapped from tid to pid).
467446283Sdfr   *
467546283Sdfr   * It's because we need to add the tthread _now_ that we
467646283Sdfr   * need to call "clear_thread_info" _now_, and that's why
467746283Sdfr   * "require_notification_of_events" doesn't clear the thread
467846283Sdfr   * info (it's called later than this routine).
467946283Sdfr   */
468098944Sobrien  clear_thread_info ();
468146283Sdfr  a_thread = 0;
468246283Sdfr
468346283Sdfr  for (tid = get_process_first_stopped_thread_id (pid, &thread_state);
468446283Sdfr       tid != 0;
468546283Sdfr       tid = get_process_next_stopped_thread_id (pid, &thread_state))
468646283Sdfr    {
468746283Sdfr      thread_info *p;
468898944Sobrien
468946283Sdfr      if (a_thread == 0)
469098944Sobrien	{
469198944Sobrien	  a_thread = tid;
469246283Sdfr#ifdef THREAD_DEBUG
469398944Sobrien	  if (debug_on)
469498944Sobrien	    printf ("Attaching to process %d, thread %d\n",
469598944Sobrien		    pid, a_thread);
469646283Sdfr#endif
469798944Sobrien	}
469846283Sdfr
469946283Sdfr      /* Tell ourselves and the "rest of gdb" that this thread
470046283Sdfr       * exists.
470146283Sdfr       *
470246283Sdfr       * This isn't really a hack.  Other thread-based versions
470346283Sdfr       * of gdb (e.g. gnu-nat.c) seem to do the same thing.
470446283Sdfr       *
470546283Sdfr       * We don't need to do mapping here, as we know this
470646283Sdfr       * is the first thread and thus gets the real pid
470798944Sobrien       * (and is "inferior_ptid").
470846283Sdfr       *
470946283Sdfr       * NOTE: it probably isn't the originating thread,
471046283Sdfr       *       but that doesn't matter (we hope!).
471146283Sdfr       */
471298944Sobrien      add_tthread (pid, tid);
471398944Sobrien      p = find_thread_info (tid);
471498944Sobrien      if (NULL == p)		/* ?We just added it! */
471598944Sobrien	error ("Internal error adding a thread on attach.");
471698944Sobrien
471798944Sobrien      copy_ttstate_t (&p->last_stop_state, &thread_state);
471846283Sdfr      p->have_state = 1;
471946283Sdfr
472098944Sobrien      if (DO_ATTACH_CONTINUE == kind_of_go)
472198944Sobrien	{
472298944Sobrien	  /*
472398944Sobrien	   * If we are going to CONTINUE afterwards,
472498944Sobrien	   * raising a SIGTRAP, don't bother trying to
472598944Sobrien	   * handle this event.  But check first!
472698944Sobrien	   */
472798944Sobrien	  switch (p->last_stop_state.tts_event)
472898944Sobrien	    {
472946283Sdfr
473098944Sobrien	    case TTEVT_NONE:
473198944Sobrien	      /* Ok to set this handled.
473298944Sobrien	       */
473398944Sobrien	      break;
473446283Sdfr
473598944Sobrien	    default:
473698944Sobrien	      warning ("Internal error; skipping event %s on process %d, thread %d.",
473798944Sobrien		       get_printable_name_of_ttrace_event (
473898944Sobrien					      p->last_stop_state.tts_event),
473998944Sobrien		       p->pid, p->tid);
474098944Sobrien	    }
474146283Sdfr
474298944Sobrien	  set_handled (pid, tid);
474346283Sdfr
474498944Sobrien	}
474598944Sobrien      else
474698944Sobrien	{
474798944Sobrien	  /* There will be no "continue" opertion, so the
474898944Sobrien	   * process remains stopped.  Don't set any events
474998944Sobrien	   * handled except the "gimmies".
475098944Sobrien	   */
475198944Sobrien	  switch (p->last_stop_state.tts_event)
475298944Sobrien	    {
475346283Sdfr
475498944Sobrien	    case TTEVT_NONE:
475598944Sobrien	      /* Ok to ignore this.
475698944Sobrien	       */
475798944Sobrien	      set_handled (pid, tid);
475898944Sobrien	      break;
475946283Sdfr
476098944Sobrien	    case TTEVT_EXEC:
476198944Sobrien	    case TTEVT_FORK:
476298944Sobrien	      /* Expected "other" FORK or EXEC event from a
476398944Sobrien	       * fork or vfork.
476498944Sobrien	       */
476598944Sobrien	      break;
476698944Sobrien
476798944Sobrien	    default:
476898944Sobrien	      printf ("Internal error: failed to handle event %s on process %d, thread %d.",
476998944Sobrien		      get_printable_name_of_ttrace_event (
477098944Sobrien					      p->last_stop_state.tts_event),
477198944Sobrien		      p->pid, p->tid);
477298944Sobrien	    }
477398944Sobrien	}
477498944Sobrien
477598944Sobrien      add_thread (pid_to_ptid (pid));		/* in thread.c */
477646283Sdfr    }
477798944Sobrien
477846283Sdfr#ifdef PARANOIA
477998944Sobrien  if (debug_on)
478098944Sobrien    print_tthreads ();
478146283Sdfr#endif
478246283Sdfr
478346283Sdfr  /* One mustn't call ttrace_wait() after attaching via ttrace,
478446283Sdfr     'cause the process is stopped already.
478598944Sobrien
478646283Sdfr     However, the upper layers of gdb's execution control will
478746283Sdfr     want to wait after attaching (but not after forks, in
478846283Sdfr     which case they will be doing a "target_resume", anticipating
478946283Sdfr     a later TTEVT_EXEC or TTEVT_FORK event).
479046283Sdfr
479146283Sdfr     To make this attach() implementation more compatible with
479246283Sdfr     others, we'll make the attached-to process raise a SIGTRAP.
479346283Sdfr
479446283Sdfr     Issue: this continues only one thread.  That could be
479546283Sdfr     dangerous if the thread is blocked--the process won't run
479646283Sdfr     and no trap will be raised.  FIX! (check state.tts_flags?
479746283Sdfr     need one that's either TTS_WASRUNNING--but we've stopped
479846283Sdfr     it and made it TTS_WASSUSPENDED.  Hum...FIXME!)
479946283Sdfr   */
480098944Sobrien  if (DO_ATTACH_CONTINUE == kind_of_go)
480198944Sobrien    {
480298944Sobrien      tt_status = call_real_ttrace (
480398944Sobrien				     TT_LWP_CONTINUE,
480498944Sobrien				     pid,
480598944Sobrien				     a_thread,
480698944Sobrien				     TT_USE_CURRENT_PC,
480798944Sobrien	       (TTRACE_ARG_TYPE) target_signal_to_host (TARGET_SIGNAL_TRAP),
480898944Sobrien				     TT_NIL);
480946283Sdfr      if (errno)
481098944Sobrien	perror_with_name ("ttrace");
481146283Sdfr
481298944Sobrien      clear_handled (a_thread);	/* So TRAP will be reported. */
481346283Sdfr
481446283Sdfr      /* Now running.
481546283Sdfr       */
481646283Sdfr      process_state = RUNNING;
481798944Sobrien    }
481846283Sdfr
481946283Sdfr  attach_flag = 1;
482046283Sdfr}
482146283Sdfr#endif /* ATTACH_DETACH */
482298944Sobrien
482346283Sdfr
482446283Sdfr#ifdef ATTACH_DETACH
482546283Sdfr/* Start debugging the process whose number is PID.
482646283Sdfr * (A _real_ pid).
482746283Sdfr */
482846283Sdfrint
482998944Sobrienattach (int pid)
483046283Sdfr{
483198944Sobrien  int tt_status;
483298944Sobrien
483346283Sdfr  tt_status = call_real_ttrace (
483498944Sobrien				 TT_PROC_ATTACH,
483598944Sobrien				 pid,
483698944Sobrien				 (lwpid_t) TT_NIL,
483798944Sobrien				 TT_NIL,
483898944Sobrien				 (TTRACE_ARG_TYPE) TT_VERSION,
483998944Sobrien				 TT_NIL);
484046283Sdfr  if (errno)
484146283Sdfr    perror_with_name ("ttrace attach");
484246283Sdfr
484346283Sdfr  /* If successful, the process is now stopped.
484446283Sdfr   */
484546283Sdfr  process_state = STOPPED;
484646283Sdfr
484746283Sdfr  /* Our caller ("attach_command" in "infcmd.c")
484846283Sdfr   * expects to do a "wait_for_inferior" after
484946283Sdfr   * the attach, so make sure the inferior is
485046283Sdfr   * running when we're done.
485146283Sdfr   */
485298944Sobrien  update_thread_state_after_attach (pid, DO_ATTACH_CONTINUE);
485346283Sdfr
485446283Sdfr  return pid;
485546283Sdfr}
485646283Sdfr
485746283Sdfr
485846283Sdfr#if defined(CHILD_POST_ATTACH)
485946283Sdfrvoid
486098944Sobrienchild_post_attach (int pid)
486146283Sdfr{
486246283Sdfr#ifdef THREAD_DEBUG
486398944Sobrien  if (debug_on)
486498944Sobrien    printf ("child-post-attach call\n");
486546283Sdfr#endif
486646283Sdfr
486746283Sdfr  require_notification_of_events (pid);
486846283Sdfr}
486946283Sdfr#endif
487046283Sdfr
487146283Sdfr
487246283Sdfr/* Stop debugging the process whose number is PID
487346283Sdfr   and continue it with signal number SIGNAL.
487446283Sdfr   SIGNAL = 0 means just continue it.
487546283Sdfr */
487646283Sdfrvoid
487798944Sobriendetach (int signal)
487846283Sdfr{
487946283Sdfr  errno = 0;
488046283Sdfr  call_ttrace (TT_PROC_DETACH,
488198944Sobrien	       PIDGET (inferior_ptid),
488298944Sobrien	       TT_NIL,
488398944Sobrien	       (TTRACE_ARG_TYPE) signal,
488498944Sobrien	       TT_NIL);
488546283Sdfr  attach_flag = 0;
488646283Sdfr
488798944Sobrien  clear_thread_info ();
488846283Sdfr
488946283Sdfr  /* Process-state? */
489046283Sdfr}
489146283Sdfr#endif /* ATTACH_DETACH */
489298944Sobrien
489346283Sdfr
489446283Sdfr/* Default the type of the ttrace transfer to int.  */
489546283Sdfr#ifndef TTRACE_XFER_TYPE
489646283Sdfr#define TTRACE_XFER_TYPE int
489746283Sdfr#endif
489846283Sdfr
489946283Sdfrvoid
490098944Sobrien_initialize_kernel_u_addr (void)
490146283Sdfr{
490246283Sdfr}
490346283Sdfr
490446283Sdfr#if !defined (CHILD_XFER_MEMORY)
490546283Sdfr/* NOTE! I tried using TTRACE_READDATA, etc., to read and write memory
490646283Sdfr   in the NEW_SUN_TTRACE case.
490746283Sdfr   It ought to be straightforward.  But it appears that writing did
490846283Sdfr   not write the data that I specified.  I cannot understand where
490946283Sdfr   it got the data that it actually did write.  */
491046283Sdfr
491146283Sdfr/* Copy LEN bytes to or from inferior's memory starting at MEMADDR
491246283Sdfr   to debugger memory starting at MYADDR.   Copy to inferior if
491398944Sobrien   WRITE is nonzero.  TARGET is ignored.
491498944Sobrien
491546283Sdfr   Returns the length copied, which is either the LEN argument or zero.
491646283Sdfr   This xfer function does not do partial moves, since child_ops
491746283Sdfr   doesn't allow memory operations to cross below us in the target stack
491846283Sdfr   anyway.  */
491946283Sdfr
492046283Sdfrint
492198944Sobrienchild_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
492298944Sobrien		   struct mem_attrib *attrib,
492398944Sobrien		   struct target_ops *target)
492446283Sdfr{
492546283Sdfr  register int i;
492646283Sdfr  /* Round starting address down to longword boundary.  */
492798944Sobrien  register CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (TTRACE_XFER_TYPE);
492846283Sdfr  /* Round ending address up; get number of longwords that makes.  */
492946283Sdfr  register int count
493098944Sobrien  = (((memaddr + len) - addr) + sizeof (TTRACE_XFER_TYPE) - 1)
493198944Sobrien  / sizeof (TTRACE_XFER_TYPE);
493246283Sdfr  /* Allocate buffer of that many longwords.  */
493398944Sobrien  /* FIXME (alloca): This code, cloned from infptrace.c, is unsafe
493498944Sobrien     because it uses alloca to allocate a buffer of arbitrary size.
493598944Sobrien     For very large xfers, this could crash GDB's stack.  */
493646283Sdfr  register TTRACE_XFER_TYPE *buffer
493746283Sdfr    = (TTRACE_XFER_TYPE *) alloca (count * sizeof (TTRACE_XFER_TYPE));
493846283Sdfr
493946283Sdfr  if (write)
494046283Sdfr    {
494146283Sdfr      /* Fill start and end extra bytes of buffer with existing memory data.  */
494246283Sdfr
494398944Sobrien      if (addr != memaddr || len < (int) sizeof (TTRACE_XFER_TYPE))
494498944Sobrien	{
494598944Sobrien	  /* Need part of initial word -- fetch it.  */
494698944Sobrien	  buffer[0] = call_ttrace (TT_LWP_RDTEXT,
494798944Sobrien				   PIDGET (inferior_ptid),
494898944Sobrien				   (TTRACE_ARG_TYPE) addr,
494998944Sobrien				   TT_NIL,
495098944Sobrien				   TT_NIL);
495198944Sobrien	}
495246283Sdfr
495346283Sdfr      if (count > 1)		/* FIXME, avoid if even boundary */
495446283Sdfr	{
495546283Sdfr	  buffer[count - 1] = call_ttrace (TT_LWP_RDTEXT,
495698944Sobrien					   PIDGET (inferior_ptid),
495798944Sobrien					   ((TTRACE_ARG_TYPE)
495898944Sobrien			  (addr + (count - 1) * sizeof (TTRACE_XFER_TYPE))),
495998944Sobrien					   TT_NIL,
496098944Sobrien					   TT_NIL);
496146283Sdfr	}
496246283Sdfr
496346283Sdfr      /* Copy data to be written over corresponding part of buffer */
496446283Sdfr
496546283Sdfr      memcpy ((char *) buffer + (memaddr & (sizeof (TTRACE_XFER_TYPE) - 1)),
496646283Sdfr	      myaddr,
496746283Sdfr	      len);
496846283Sdfr
496946283Sdfr      /* Write the entire buffer.  */
497046283Sdfr
497146283Sdfr      for (i = 0; i < count; i++, addr += sizeof (TTRACE_XFER_TYPE))
497246283Sdfr	{
497346283Sdfr	  errno = 0;
497446283Sdfr	  call_ttrace (TT_LWP_WRDATA,
497598944Sobrien		       PIDGET (inferior_ptid),
497698944Sobrien		       (TTRACE_ARG_TYPE) addr,
497798944Sobrien		       (TTRACE_ARG_TYPE) buffer[i],
497898944Sobrien		       TT_NIL);
497946283Sdfr	  if (errno)
498046283Sdfr	    {
498146283Sdfr	      /* Using the appropriate one (I or D) is necessary for
498298944Sobrien	         Gould NP1, at least.  */
498346283Sdfr	      errno = 0;
498446283Sdfr	      call_ttrace (TT_LWP_WRTEXT,
498598944Sobrien			   PIDGET (inferior_ptid),
498698944Sobrien			   (TTRACE_ARG_TYPE) addr,
498798944Sobrien			   (TTRACE_ARG_TYPE) buffer[i],
498898944Sobrien			   TT_NIL);
498946283Sdfr	    }
499046283Sdfr	  if (errno)
499146283Sdfr	    return 0;
499246283Sdfr	}
499346283Sdfr    }
499446283Sdfr  else
499546283Sdfr    {
499646283Sdfr      /* Read all the longwords */
499746283Sdfr      for (i = 0; i < count; i++, addr += sizeof (TTRACE_XFER_TYPE))
499846283Sdfr	{
499946283Sdfr	  errno = 0;
500046283Sdfr	  buffer[i] = call_ttrace (TT_LWP_RDTEXT,
500198944Sobrien				   PIDGET (inferior_ptid),
500298944Sobrien				   (TTRACE_ARG_TYPE) addr,
500398944Sobrien				   TT_NIL,
500498944Sobrien				   TT_NIL);
500546283Sdfr	  if (errno)
500646283Sdfr	    return 0;
500746283Sdfr	  QUIT;
500846283Sdfr	}
500946283Sdfr
501046283Sdfr      /* Copy appropriate bytes out of the buffer.  */
501146283Sdfr      memcpy (myaddr,
501246283Sdfr	      (char *) buffer + (memaddr & (sizeof (TTRACE_XFER_TYPE) - 1)),
501346283Sdfr	      len);
501446283Sdfr    }
501546283Sdfr  return len;
501646283Sdfr}
501798944Sobrien
501846283Sdfr
501946283Sdfrstatic void
502098944Sobrienudot_info (void)
502146283Sdfr{
502298944Sobrien  int udot_off;			/* Offset into user struct */
502398944Sobrien  int udot_val;			/* Value from user struct at udot_off */
502498944Sobrien  char mess[128];		/* For messages */
502546283Sdfr
502698944Sobrien  if (!target_has_execution)
502798944Sobrien    {
502898944Sobrien      error ("The program is not being run.");
502998944Sobrien    }
503046283Sdfr
503146283Sdfr#if !defined (KERNEL_U_SIZE)
503246283Sdfr
503346283Sdfr  /* Adding support for this command is easy.  Typically you just add a
503446283Sdfr     routine, called "kernel_u_size" that returns the size of the user
503546283Sdfr     struct, to the appropriate *-nat.c file and then add to the native
503646283Sdfr     config file "#define KERNEL_U_SIZE kernel_u_size()" */
503746283Sdfr  error ("Don't know how large ``struct user'' is in this version of gdb.");
503846283Sdfr
503946283Sdfr#else
504046283Sdfr
504146283Sdfr  for (udot_off = 0; udot_off < KERNEL_U_SIZE; udot_off += sizeof (udot_val))
504246283Sdfr    {
504346283Sdfr      if ((udot_off % 24) == 0)
504446283Sdfr	{
504546283Sdfr	  if (udot_off > 0)
504646283Sdfr	    {
504746283Sdfr	      printf_filtered ("\n");
504846283Sdfr	    }
504946283Sdfr	  printf_filtered ("%04x:", udot_off);
505046283Sdfr	}
505146283Sdfr      udot_val = call_ttrace (TT_LWP_RUREGS,
505298944Sobrien			      PIDGET (inferior_ptid),
505398944Sobrien			      (TTRACE_ARG_TYPE) udot_off,
505498944Sobrien			      TT_NIL,
505598944Sobrien			      TT_NIL);
505646283Sdfr      if (errno != 0)
505746283Sdfr	{
505846283Sdfr	  sprintf (mess, "\nreading user struct at offset 0x%x", udot_off);
505946283Sdfr	  perror_with_name (mess);
506046283Sdfr	}
506146283Sdfr      /* Avoid using nonportable (?) "*" in print specs */
506246283Sdfr      printf_filtered (sizeof (int) == 4 ? " 0x%08x" : " 0x%16x", udot_val);
506346283Sdfr    }
506446283Sdfr  printf_filtered ("\n");
506546283Sdfr
506646283Sdfr#endif
506746283Sdfr}
506846283Sdfr#endif /* !defined (CHILD_XFER_MEMORY).  */
506946283Sdfr
507098944Sobrien
507146283Sdfr/* TTrace version of "target_pid_to_exec_file"
507246283Sdfr */
507346283Sdfrchar *
507498944Sobrienchild_pid_to_exec_file (int tid)
507546283Sdfr{
507698944Sobrien  int tt_status;
507798944Sobrien  static char exec_file_buffer[1024];
507898944Sobrien  pid_t pid;
507998944Sobrien  static struct pst_status buf;
508098944Sobrien
508198944Sobrien  /* On various versions of hpux11, this may fail due to a supposed
508298944Sobrien     kernel bug.  We have alternate methods to get this information
508398944Sobrien     (ie pstat).  */
508446283Sdfr  tt_status = call_ttrace (TT_PROC_GET_PATHNAME,
508598944Sobrien			   tid,
508698944Sobrien			   (uint64_t) exec_file_buffer,
508798944Sobrien			   sizeof (exec_file_buffer) - 1,
508898944Sobrien			   0);
508946283Sdfr  if (tt_status >= 0)
509046283Sdfr    return exec_file_buffer;
509146283Sdfr
509298944Sobrien  /* Try to get process information via pstat and extract the filename
509398944Sobrien     from the pst_cmd field within the pst_status structure.  */
509498944Sobrien  if (pstat_getproc (&buf, sizeof (struct pst_status), 0, tid) != -1)
509598944Sobrien    {
509698944Sobrien      char *p = buf.pst_cmd;
509746283Sdfr
509898944Sobrien      while (*p && *p != ' ')
509998944Sobrien	p++;
510098944Sobrien      *p = 0;
510146283Sdfr
510298944Sobrien      return (buf.pst_cmd);
510346283Sdfr    }
510446283Sdfr
510598944Sobrien  return (NULL);
510646283Sdfr}
510746283Sdfr
510846283Sdfrvoid
510998944Sobrienpre_fork_inferior (void)
511046283Sdfr{
511198944Sobrien  int status;
511246283Sdfr
511346283Sdfr  status = pipe (startup_semaphore.parent_channel);
511498944Sobrien  if (status < 0)
511598944Sobrien    {
511646283Sdfr      warning ("error getting parent pipe for startup semaphore");
511746283Sdfr      return;
511898944Sobrien    }
511946283Sdfr
512046283Sdfr  status = pipe (startup_semaphore.child_channel);
512198944Sobrien  if (status < 0)
512298944Sobrien    {
512346283Sdfr      warning ("error getting child pipe for startup semaphore");
512446283Sdfr      return;
512598944Sobrien    }
512646283Sdfr}
512746283Sdfr
512846283Sdfr/* Called via #define REQUIRE_ATTACH from inftarg.c,
512946283Sdfr * ultimately from "follow_inferior_fork" in infrun.c,
513046283Sdfr * itself called from "resume".
513146283Sdfr *
513246283Sdfr * This seems to be intended to attach after a fork or
513346283Sdfr * vfork, while "attach" is used to attach to a pid
513446283Sdfr * given by the user.  The check for an existing attach
513546283Sdfr * seems odd--it always fails in our test system.
513646283Sdfr */
513746283Sdfrint
513898944Sobrienhppa_require_attach (int pid)
513946283Sdfr{
514098944Sobrien  int tt_status;
514198944Sobrien  CORE_ADDR pc;
514298944Sobrien  CORE_ADDR pc_addr;
514398944Sobrien  unsigned int regs_offset;
514446283Sdfr  process_state_t old_process_state = process_state;
514598944Sobrien
514646283Sdfr  /* Are we already attached?  There appears to be no explicit
514746283Sdfr   * way to answer this via ttrace, so we try something which
514846283Sdfr   * should be innocuous if we are attached.  If that fails,
514946283Sdfr   * then we assume we're not attached, and so attempt to make
515046283Sdfr   * it so.
515146283Sdfr   */
515246283Sdfr  errno = 0;
515346283Sdfr  tt_status = call_real_ttrace (TT_PROC_STOP,
515498944Sobrien				pid,
515598944Sobrien				(lwpid_t) TT_NIL,
515698944Sobrien				(TTRACE_ARG_TYPE) TT_NIL,
515798944Sobrien				(TTRACE_ARG_TYPE) TT_NIL,
515898944Sobrien				TT_NIL);
515998944Sobrien
516046283Sdfr  if (errno)
516146283Sdfr    {
516246283Sdfr      /* No change to process-state!
516346283Sdfr       */
516446283Sdfr      errno = 0;
516598944Sobrien      pid = attach (pid);
516646283Sdfr    }
516746283Sdfr  else
516846283Sdfr    {
516998944Sobrien      /* If successful, the process is now stopped.  But if
517098944Sobrien       * we're VFORKING, the parent is still running, so don't
517198944Sobrien       * change the process state.
517298944Sobrien       */
517398944Sobrien      if (process_state != VFORKING)
517498944Sobrien	process_state = STOPPED;
517546283Sdfr
517698944Sobrien      /* If we were already attached, you'd think that we
517798944Sobrien       * would need to start going again--but you'd be wrong,
517898944Sobrien       * as the fork-following code is actually in the middle
517998944Sobrien       * of the "resume" routine in in "infrun.c" and so
518098944Sobrien       * will (almost) immediately do a resume.
518198944Sobrien       *
518298944Sobrien       * On the other hand, if we are VFORKING, which means
518398944Sobrien       * that the child and the parent share a process for a
518498944Sobrien       * while, we know that "resume" won't be resuming
518598944Sobrien       * until the child EXEC event is seen.  But we still
518698944Sobrien       * don't want to continue, as the event is already
518798944Sobrien       * there waiting.
518898944Sobrien       */
518998944Sobrien      update_thread_state_after_attach (pid, DONT_ATTACH_CONTINUE);
519098944Sobrien    }				/* STOP succeeded */
519198944Sobrien
519246283Sdfr  return pid;
519346283Sdfr}
519446283Sdfr
519546283Sdfrint
519698944Sobrienhppa_require_detach (int pid, int signal)
519746283Sdfr{
519898944Sobrien  int tt_status;
519946283Sdfr
520046283Sdfr  /* If signal is non-zero, we must pass the signal on to the active
520146283Sdfr     thread prior to detaching.  We do this by continuing the threads
520246283Sdfr     with the signal.
520346283Sdfr   */
520446283Sdfr  if (signal != 0)
520546283Sdfr    {
520646283Sdfr      errno = 0;
520798944Sobrien      threads_continue_all_with_signals (pid, signal);
520846283Sdfr    }
520946283Sdfr
521046283Sdfr  errno = 0;
521146283Sdfr  tt_status = call_ttrace (TT_PROC_DETACH,
521298944Sobrien			   pid,
521398944Sobrien			   TT_NIL,
521498944Sobrien			   TT_NIL,
521598944Sobrien			   TT_NIL);
521646283Sdfr
521798944Sobrien  errno = 0;			/* Ignore any errors. */
521846283Sdfr
521946283Sdfr  /* process_state? */
522098944Sobrien
522146283Sdfr  return pid;
522246283Sdfr}
522346283Sdfr
522446283Sdfr/* Given the starting address of a memory page, hash it to a bucket in
522546283Sdfr   the memory page dictionary.
522698944Sobrien */
522746283Sdfrstatic int
522898944Sobrienget_dictionary_bucket_of_page (CORE_ADDR page_start)
522946283Sdfr{
523098944Sobrien  int hash;
523146283Sdfr
523246283Sdfr  hash = (page_start / memory_page_dictionary.page_size);
523346283Sdfr  hash = hash % MEMORY_PAGE_DICTIONARY_BUCKET_COUNT;
523446283Sdfr
523546283Sdfr  return hash;
523646283Sdfr}
523746283Sdfr
523846283Sdfr
523946283Sdfr/* Given a memory page's starting address, get (i.e., find an existing
524046283Sdfr   or create a new) dictionary entry for the page.  The page will be
524146283Sdfr   write-protected when this function returns, but may have a reference
524246283Sdfr   count of 0 (if the page was newly-added to the dictionary).
524398944Sobrien */
524446283Sdfrstatic memory_page_t *
524598944Sobrienget_dictionary_entry_of_page (int pid, CORE_ADDR page_start)
524646283Sdfr{
524798944Sobrien  int bucket;
524898944Sobrien  memory_page_t *page = NULL;
524998944Sobrien  memory_page_t *previous_page = NULL;
525046283Sdfr
525146283Sdfr  /* We're going to be using the dictionary now, than-kew. */
525298944Sobrien  require_memory_page_dictionary ();
525346283Sdfr
525446283Sdfr  /* Try to find an existing dictionary entry for this page.  Hash
525546283Sdfr     on the page's starting address.
525698944Sobrien   */
525746283Sdfr  bucket = get_dictionary_bucket_of_page (page_start);
525846283Sdfr  page = &memory_page_dictionary.buckets[bucket];
525946283Sdfr  while (page != NULL)
526046283Sdfr    {
526146283Sdfr      if (page->page_start == page_start)
526298944Sobrien	break;
526346283Sdfr      previous_page = page;
526446283Sdfr      page = page->next;
526546283Sdfr    }
526646283Sdfr
526746283Sdfr  /* Did we find a dictionary entry for this page?  If not, then
526846283Sdfr     add it to the dictionary now.
526998944Sobrien   */
527046283Sdfr  if (page == NULL)
527146283Sdfr    {
527246283Sdfr      /* Create a new entry. */
527346283Sdfr      page = (memory_page_t *) xmalloc (sizeof (memory_page_t));
527446283Sdfr      page->page_start = page_start;
527546283Sdfr      page->reference_count = 0;
527646283Sdfr      page->next = NULL;
527746283Sdfr      page->previous = NULL;
527846283Sdfr
527946283Sdfr      /* We'll write-protect the page now, if that's allowed. */
528046283Sdfr      page->original_permissions = write_protect_page (pid, page_start);
528146283Sdfr
528246283Sdfr      /* Add the new entry to the dictionary. */
528346283Sdfr      page->previous = previous_page;
528446283Sdfr      previous_page->next = page;
528546283Sdfr
528646283Sdfr      memory_page_dictionary.page_count++;
528746283Sdfr    }
528846283Sdfr
528946283Sdfr  return page;
529046283Sdfr}
529146283Sdfr
529246283Sdfr
529346283Sdfrstatic void
529498944Sobrienremove_dictionary_entry_of_page (int pid, memory_page_t *page)
529546283Sdfr{
529646283Sdfr  /* Restore the page's original permissions. */
529746283Sdfr  unwrite_protect_page (pid, page->page_start, page->original_permissions);
529846283Sdfr
529946283Sdfr  /* Kick the page out of the dictionary. */
530046283Sdfr  if (page->previous != NULL)
530146283Sdfr    page->previous->next = page->next;
530246283Sdfr  if (page->next != NULL)
530346283Sdfr    page->next->previous = page->previous;
530446283Sdfr
530546283Sdfr  /* Just in case someone retains a handle to this after it's freed. */
530646283Sdfr  page->page_start = (CORE_ADDR) 0;
530746283Sdfr
530846283Sdfr  memory_page_dictionary.page_count--;
530946283Sdfr
531098944Sobrien  xfree (page);
531146283Sdfr}
531246283Sdfr
531346283Sdfr
531446283Sdfrstatic void
531598944Sobrienhppa_enable_syscall_events (int pid)
531646283Sdfr{
531798944Sobrien  int tt_status;
531898944Sobrien  ttevent_t ttrace_events;
531946283Sdfr
532046283Sdfr  /* Get the set of events that are currently enabled. */
532146283Sdfr  tt_status = call_ttrace (TT_PROC_GET_EVENT_MASK,
532298944Sobrien			   pid,
532398944Sobrien			   (TTRACE_ARG_TYPE) & ttrace_events,
532498944Sobrien			   (TTRACE_ARG_TYPE) sizeof (ttrace_events),
532598944Sobrien			   TT_NIL);
532646283Sdfr  if (errno)
532746283Sdfr    perror_with_name ("ttrace");
532846283Sdfr
532946283Sdfr  /* Add syscall events to that set. */
533046283Sdfr  ttrace_events.tte_events |= TTEVT_SYSCALL_ENTRY;
533146283Sdfr  ttrace_events.tte_events |= TTEVT_SYSCALL_RETURN;
533246283Sdfr
533346283Sdfr  tt_status = call_ttrace (TT_PROC_SET_EVENT_MASK,
533498944Sobrien			   pid,
533598944Sobrien			   (TTRACE_ARG_TYPE) & ttrace_events,
533698944Sobrien			   (TTRACE_ARG_TYPE) sizeof (ttrace_events),
533798944Sobrien			   TT_NIL);
533846283Sdfr  if (errno)
533946283Sdfr    perror_with_name ("ttrace");
534046283Sdfr}
534146283Sdfr
534246283Sdfr
534346283Sdfrstatic void
534498944Sobrienhppa_disable_syscall_events (int pid)
534546283Sdfr{
534698944Sobrien  int tt_status;
534798944Sobrien  ttevent_t ttrace_events;
534846283Sdfr
534946283Sdfr  /* Get the set of events that are currently enabled. */
535046283Sdfr  tt_status = call_ttrace (TT_PROC_GET_EVENT_MASK,
535198944Sobrien			   pid,
535298944Sobrien			   (TTRACE_ARG_TYPE) & ttrace_events,
535398944Sobrien			   (TTRACE_ARG_TYPE) sizeof (ttrace_events),
535498944Sobrien			   TT_NIL);
535546283Sdfr  if (errno)
535646283Sdfr    perror_with_name ("ttrace");
535746283Sdfr
535846283Sdfr  /* Remove syscall events from that set. */
535946283Sdfr  ttrace_events.tte_events &= ~TTEVT_SYSCALL_ENTRY;
536046283Sdfr  ttrace_events.tte_events &= ~TTEVT_SYSCALL_RETURN;
536146283Sdfr
536246283Sdfr  tt_status = call_ttrace (TT_PROC_SET_EVENT_MASK,
536398944Sobrien			   pid,
536498944Sobrien			   (TTRACE_ARG_TYPE) & ttrace_events,
536598944Sobrien			   (TTRACE_ARG_TYPE) sizeof (ttrace_events),
536698944Sobrien			   TT_NIL);
536746283Sdfr  if (errno)
536846283Sdfr    perror_with_name ("ttrace");
536946283Sdfr}
537046283Sdfr
537146283Sdfr
537246283Sdfr/* The address range beginning with START and ending with START+LEN-1
537346283Sdfr   (inclusive) is to be watched via page-protection by a new watchpoint.
537446283Sdfr   Set protection for all pages that overlap that range.
537546283Sdfr
537646283Sdfr   Note that our caller sets TYPE to:
537798944Sobrien   0 for a bp_hardware_watchpoint,
537898944Sobrien   1 for a bp_read_watchpoint,
537998944Sobrien   2 for a bp_access_watchpoint
538046283Sdfr
538146283Sdfr   (Yes, this is intentionally (though lord only knows why) different
538246283Sdfr   from the TYPE that is passed to hppa_remove_hw_watchpoint.)
538398944Sobrien */
538446283Sdfrint
538598944Sobrienhppa_insert_hw_watchpoint (int pid, CORE_ADDR start, LONGEST len, int type)
538646283Sdfr{
538798944Sobrien  CORE_ADDR page_start;
538898944Sobrien  int dictionary_was_empty;
538998944Sobrien  int page_size;
539098944Sobrien  int page_id;
539198944Sobrien  LONGEST range_size_in_pages;
539246283Sdfr
539346283Sdfr  if (type != 0)
539446283Sdfr    error ("read or access hardware watchpoints not supported on HP-UX");
539546283Sdfr
539646283Sdfr  /* Examine all pages in the address range. */
539746283Sdfr  require_memory_page_dictionary ();
539846283Sdfr
539946283Sdfr  dictionary_was_empty = (memory_page_dictionary.page_count == (LONGEST) 0);
540046283Sdfr
540146283Sdfr  page_size = memory_page_dictionary.page_size;
540246283Sdfr  page_start = (start / page_size) * page_size;
540346283Sdfr  range_size_in_pages = ((LONGEST) len + (LONGEST) page_size - 1) / (LONGEST) page_size;
540446283Sdfr
540598944Sobrien  for (page_id = 0; page_id < range_size_in_pages; page_id++, page_start += page_size)
540646283Sdfr    {
540798944Sobrien      memory_page_t *page;
540846283Sdfr
540946283Sdfr      /* This gets the page entered into the dictionary if it was
541046283Sdfr         not already entered.
541198944Sobrien       */
541246283Sdfr      page = get_dictionary_entry_of_page (pid, page_start);
541346283Sdfr      page->reference_count++;
541446283Sdfr    }
541546283Sdfr
541646283Sdfr  /* Our implementation depends on seeing calls to kernel code, for the
541746283Sdfr     following reason.  Here we ask to be notified of syscalls.
541846283Sdfr
541946283Sdfr     When a protected page is accessed by user code, HP-UX raises a SIGBUS.
542046283Sdfr     Fine.
542146283Sdfr
542246283Sdfr     But when kernel code accesses the page, it doesn't give a SIGBUS.
542346283Sdfr     Rather, the system call that touched the page fails, with errno=EFAULT.
542446283Sdfr     Not good for us.
542546283Sdfr
542646283Sdfr     We could accomodate this "feature" by asking to be notified of syscall
542746283Sdfr     entries & exits; upon getting an entry event, disabling page-protections;
542846283Sdfr     upon getting an exit event, reenabling page-protections and then checking
542946283Sdfr     if any watchpoints triggered.
543046283Sdfr
543146283Sdfr     However, this turns out to be a real performance loser.  syscalls are
543246283Sdfr     usually a frequent occurrence.  Having to unprotect-reprotect all watched
543346283Sdfr     pages, and also to then read all watched memory locations and compare for
543446283Sdfr     triggers, can be quite expensive.
543546283Sdfr
543646283Sdfr     Instead, we'll only ask to be notified of syscall exits.  When we get
543746283Sdfr     one, we'll check whether errno is set.  If not, or if it's not EFAULT,
543846283Sdfr     we can just continue the inferior.
543946283Sdfr
544046283Sdfr     If errno is set upon syscall exit to EFAULT, we must perform some fairly
544146283Sdfr     hackish stuff to determine whether the failure really was due to a
544246283Sdfr     page-protect trap on a watched location.
544398944Sobrien   */
544446283Sdfr  if (dictionary_was_empty)
544546283Sdfr    hppa_enable_syscall_events (pid);
544646283Sdfr
544746283Sdfr  return 1;
544846283Sdfr}
544946283Sdfr
545046283Sdfr
545146283Sdfr/* The address range beginning with START and ending with START+LEN-1
545246283Sdfr   (inclusive) was being watched via page-protection by a watchpoint
545346283Sdfr   which has been removed.  Remove protection for all pages that
545446283Sdfr   overlap that range, which are not also being watched by other
545546283Sdfr   watchpoints.
545698944Sobrien */
545746283Sdfrint
545898944Sobrienhppa_remove_hw_watchpoint (int pid, CORE_ADDR start, LONGEST len,
545998944Sobrien			   enum bptype type)
546046283Sdfr{
546198944Sobrien  CORE_ADDR page_start;
546298944Sobrien  int dictionary_is_empty;
546398944Sobrien  int page_size;
546498944Sobrien  int page_id;
546598944Sobrien  LONGEST range_size_in_pages;
546646283Sdfr
546746283Sdfr  if (type != 0)
546846283Sdfr    error ("read or access hardware watchpoints not supported on HP-UX");
546946283Sdfr
547046283Sdfr  /* Examine all pages in the address range. */
547146283Sdfr  require_memory_page_dictionary ();
547246283Sdfr
547346283Sdfr  page_size = memory_page_dictionary.page_size;
547446283Sdfr  page_start = (start / page_size) * page_size;
547546283Sdfr  range_size_in_pages = ((LONGEST) len + (LONGEST) page_size - 1) / (LONGEST) page_size;
547646283Sdfr
547798944Sobrien  for (page_id = 0; page_id < range_size_in_pages; page_id++, page_start += page_size)
547846283Sdfr    {
547998944Sobrien      memory_page_t *page;
548046283Sdfr
548146283Sdfr      page = get_dictionary_entry_of_page (pid, page_start);
548246283Sdfr      page->reference_count--;
548346283Sdfr
548446283Sdfr      /* Was this the last reference of this page?  If so, then we
548546283Sdfr         must scrub the entry from the dictionary, and also restore
548646283Sdfr         the page's original permissions.
548798944Sobrien       */
548846283Sdfr      if (page->reference_count == 0)
548998944Sobrien	remove_dictionary_entry_of_page (pid, page);
549046283Sdfr    }
549146283Sdfr
549246283Sdfr  dictionary_is_empty = (memory_page_dictionary.page_count == (LONGEST) 0);
549346283Sdfr
549446283Sdfr  /* If write protections are currently disallowed, then that implies that
549546283Sdfr     wait_for_inferior believes that the inferior is within a system call.
549646283Sdfr     Since we want to see both syscall entry and return, it's clearly not
549746283Sdfr     good to disable syscall events in this state!
549846283Sdfr
549946283Sdfr     ??rehrauer: Yeah, it'd be better if we had a specific flag that said,
550046283Sdfr     "inferior is between syscall events now".  Oh well.
550198944Sobrien   */
550246283Sdfr  if (dictionary_is_empty && memory_page_dictionary.page_protections_allowed)
550346283Sdfr    hppa_disable_syscall_events (pid);
550446283Sdfr
550546283Sdfr  return 1;
550646283Sdfr}
550746283Sdfr
550846283Sdfr
550946283Sdfr/* Could we implement a watchpoint of this type via our available
551046283Sdfr   hardware support?
551146283Sdfr
551246283Sdfr   This query does not consider whether a particular address range
551346283Sdfr   could be so watched, but just whether support is generally available
551446283Sdfr   for such things.  See hppa_range_profitable_for_hw_watchpoint for a
551546283Sdfr   query that answers whether a particular range should be watched via
551646283Sdfr   hardware support.
551798944Sobrien */
551846283Sdfrint
551998944Sobrienhppa_can_use_hw_watchpoint (enum bptype type, int cnt, enum bptype ot)
552046283Sdfr{
552146283Sdfr  return (type == bp_hardware_watchpoint);
552246283Sdfr}
552346283Sdfr
552446283Sdfr
552546283Sdfr/* Assuming we could set a hardware watchpoint on this address, do
552646283Sdfr   we think it would be profitable ("a good idea") to do so?  If not,
552746283Sdfr   we can always set a regular (aka single-step & test) watchpoint
552846283Sdfr   on the address...
552998944Sobrien */
553046283Sdfrint
553198944Sobrienhppa_range_profitable_for_hw_watchpoint (int pid, CORE_ADDR start, LONGEST len)
553246283Sdfr{
553398944Sobrien  int range_is_stack_based;
553498944Sobrien  int range_is_accessible;
553598944Sobrien  CORE_ADDR page_start;
553698944Sobrien  int page_size;
553798944Sobrien  int page;
553898944Sobrien  LONGEST range_size_in_pages;
553946283Sdfr
554046283Sdfr  /* ??rehrauer: For now, say that all addresses are potentially
554146283Sdfr     profitable.  Possibly later we'll want to test the address
554246283Sdfr     for "stackness"?
554398944Sobrien   */
554446283Sdfr  range_is_stack_based = 0;
554546283Sdfr
554646283Sdfr  /* If any page in the range is inaccessible, then we cannot
554746283Sdfr     really use hardware watchpointing, even though our client
554846283Sdfr     thinks we can.  In that case, it's actually an error to
554946283Sdfr     attempt to use hw watchpoints, so we'll tell our client
555046283Sdfr     that the range is "unprofitable", and hope that they listen...
555198944Sobrien   */
555298944Sobrien  range_is_accessible = 1;	/* Until proven otherwise. */
555346283Sdfr
555446283Sdfr  /* Examine all pages in the address range. */
555546283Sdfr  errno = 0;
555646283Sdfr  page_size = sysconf (_SC_PAGE_SIZE);
555746283Sdfr
555846283Sdfr  /* If we can't determine page size, we're hosed.  Tell our
555946283Sdfr     client it's unprofitable to use hw watchpoints for this
556046283Sdfr     range.
556198944Sobrien   */
556246283Sdfr  if (errno || (page_size <= 0))
556346283Sdfr    {
556446283Sdfr      errno = 0;
556546283Sdfr      return 0;
556646283Sdfr    }
556746283Sdfr
556846283Sdfr  page_start = (start / page_size) * page_size;
556998944Sobrien  range_size_in_pages = len / (LONGEST) page_size;
557046283Sdfr
557198944Sobrien  for (page = 0; page < range_size_in_pages; page++, page_start += page_size)
557246283Sdfr    {
557398944Sobrien      int tt_status;
557498944Sobrien      int page_permissions;
557546283Sdfr
557646283Sdfr      /* Is this page accessible? */
557746283Sdfr      errno = 0;
557846283Sdfr      tt_status = call_ttrace (TT_PROC_GET_MPROTECT,
557998944Sobrien			       pid,
558098944Sobrien			       (TTRACE_ARG_TYPE) page_start,
558198944Sobrien			       TT_NIL,
558298944Sobrien			       (TTRACE_ARG_TYPE) & page_permissions);
558346283Sdfr      if (errno || (tt_status < 0))
558498944Sobrien	{
558598944Sobrien	  errno = 0;
558698944Sobrien	  range_is_accessible = 0;
558798944Sobrien	  break;
558898944Sobrien	}
558946283Sdfr
559046283Sdfr      /* Yes, go for another... */
559146283Sdfr    }
559246283Sdfr
559398944Sobrien  return (!range_is_stack_based && range_is_accessible);
559446283Sdfr}
559546283Sdfr
559646283Sdfr
559746283Sdfrchar *
559898944Sobrienhppa_pid_or_tid_to_str (ptid_t ptid)
559946283Sdfr{
560098944Sobrien  static char buf[100];		/* Static because address returned. */
560198944Sobrien  pid_t id = PIDGET (ptid);
560246283Sdfr
560346283Sdfr  /* Does this appear to be a process?  If so, print it that way. */
560446283Sdfr  if (is_process_id (id))
560598944Sobrien    return child_pid_to_str (ptid);
560646283Sdfr
560746283Sdfr  /* Else, print both the GDB thread number and the system thread id. */
560898944Sobrien  sprintf (buf, "thread %d (", pid_to_thread_id (ptid));
560998944Sobrien  strcat (buf, hppa_tid_to_str (ptid));
561046283Sdfr  strcat (buf, ")\0");
561146283Sdfr
561246283Sdfr  return buf;
561346283Sdfr}
561498944Sobrien
561546283Sdfr
561646283Sdfr/* If the current pid is not the pid this module reported
561746283Sdfr * from "ptrace_wait" with the most recent event, then the
561846283Sdfr * user has switched threads.
561946283Sdfr *
562046283Sdfr * If the last reported event was a breakpoint, then return
562146283Sdfr * the old thread id, else return 0.
562246283Sdfr */
562398944Sobrienpid_t
562498944Sobrienhppa_switched_threads (pid_t gdb_pid)
562546283Sdfr{
562698944Sobrien  if (gdb_pid == old_gdb_pid)
562798944Sobrien    {
562846283Sdfr      /*
562946283Sdfr       * Core gdb is working with the same pid that it
563046283Sdfr       * was before we reported the last event.  This
563146283Sdfr       * is ok: e.g. we reported hitting a thread-specific
563246283Sdfr       * breakpoint, but we were reporting the wrong
563346283Sdfr       * thread, so the core just ignored the event.
563446283Sdfr       *
563546283Sdfr       * No thread switch has happened.
563646283Sdfr       */
563746283Sdfr      return (pid_t) 0;
563898944Sobrien    }
563998944Sobrien  else if (gdb_pid == reported_pid)
564098944Sobrien    {
564146283Sdfr      /*
564246283Sdfr       * Core gdb is working with the pid we reported, so
564346283Sdfr       * any continue or step will be able to figure out
564446283Sdfr       * that it needs to step over any hit breakpoints
564546283Sdfr       * without our (i.e. PREPARE_TO_PROCEED's) help.
564646283Sdfr       */
564746283Sdfr      return (pid_t) 0;
564898944Sobrien    }
564998944Sobrien  else if (!reported_bpt)
565098944Sobrien    {
565198944Sobrien      /*
565298944Sobrien       * The core switched, but we didn't just report a
565398944Sobrien       * breakpoint, so there's no just-hit breakpoint
565498944Sobrien       * instruction at "reported_pid"'s PC, and thus there
565598944Sobrien       * is no need to step over it.
565698944Sobrien       */
565746283Sdfr      return (pid_t) 0;
565898944Sobrien    }
565998944Sobrien  else
566098944Sobrien    {
566198944Sobrien      /* There's been a real switch, and we reported
566298944Sobrien       * a hit breakpoint.  Let "hppa_prepare_to_proceed"
566398944Sobrien       * know, so it can see whether the breakpoint is
566498944Sobrien       * still active.
566598944Sobrien       */
566698944Sobrien      return reported_pid;
566798944Sobrien    }
566846283Sdfr
566946283Sdfr  /* Keep compiler happy with an obvious return at the end.
567046283Sdfr   */
567198944Sobrien  return (pid_t) 0;
567246283Sdfr}
567346283Sdfr
567446283Sdfrvoid
567598944Sobrienhppa_ensure_vforking_parent_remains_stopped (int pid)
567646283Sdfr{
567746283Sdfr  /* Nothing to do when using ttrace.  Only the ptrace-based implementation
567846283Sdfr     must do real work.
567946283Sdfr   */
568046283Sdfr}
568146283Sdfr
568246283Sdfr
568346283Sdfrint
568498944Sobrienhppa_resume_execd_vforking_child_to_get_parent_vfork (void)
568546283Sdfr{
568698944Sobrien  return 0;			/* No, the parent vfork is available now. */
568746283Sdfr}
568898944Sobrien
568946283Sdfr
569098944Sobrien/* Write a register as a 64bit value.  This may be necessary if the
569198944Sobrien   native OS is too braindamaged to allow some (or all) registers to
569298944Sobrien   be written in 32bit hunks such as hpux11 and the PC queue registers.
569346283Sdfr
569498944Sobrien   This is horribly gross and disgusting.  */
569598944Sobrien
569698944Sobrienint
569798944Sobrienttrace_write_reg_64 (int gdb_tid, CORE_ADDR dest_addr, CORE_ADDR src_addr)
569898944Sobrien{
569998944Sobrien  pid_t 	pid;
570098944Sobrien  lwpid_t 	tid;
570198944Sobrien  int  		tt_status;
570298944Sobrien
570398944Sobrien  tid = map_from_gdb_tid (gdb_tid);
570498944Sobrien  pid = get_pid_for (tid);
570598944Sobrien
570698944Sobrien  errno = 0;
570798944Sobrien  tt_status = ttrace (TT_LWP_WUREGS,
570898944Sobrien		      pid,
570998944Sobrien		      tid,
571098944Sobrien		      (TTRACE_ARG_TYPE) dest_addr,
571198944Sobrien		      8,
571298944Sobrien		      (TTRACE_ARG_TYPE) src_addr );
571398944Sobrien
571498944Sobrien#ifdef THREAD_DEBUG
571598944Sobrien  if (errno)
571698944Sobrien    {
571798944Sobrien      /* Don't bother for a known benign error: if you ask for the
571898944Sobrien         first thread state, but there is only one thread and it's
571998944Sobrien         not stopped, ttrace complains.
572098944Sobrien
572198944Sobrien         We have this inside the #ifdef because our caller will do
572298944Sobrien         this check for real.  */
572398944Sobrien      if( request != TT_PROC_GET_FIRST_LWP_STATE
572498944Sobrien          ||  errno   != EPROTO )
572598944Sobrien        {
572698944Sobrien          if( debug_on )
572798944Sobrien            printf( "TT fail for %s, with pid %d, tid %d, status %d \n",
572898944Sobrien                    get_printable_name_of_ttrace_request (TT_LWP_WUREGS),
572998944Sobrien                    pid, tid, tt_status );
573098944Sobrien        }
573198944Sobrien    }
573298944Sobrien#endif
573398944Sobrien
573498944Sobrien  return tt_status;
573598944Sobrien}
573698944Sobrien
573746283Sdfrvoid
573898944Sobrien_initialize_infttrace (void)
573946283Sdfr{
574046283Sdfr  /* Initialize the ttrace-based hardware watchpoint implementation. */
574198944Sobrien  memory_page_dictionary.page_count = (LONGEST) - 1;
574246283Sdfr  memory_page_dictionary.page_protections_allowed = 1;
574346283Sdfr
574446283Sdfr  errno = 0;
574546283Sdfr  memory_page_dictionary.page_size = sysconf (_SC_PAGE_SIZE);
574646283Sdfr
574798944Sobrien  /* We do a lot of casts from pointers to TTRACE_ARG_TYPE; make sure
574898944Sobrien     this is okay.  */
574998944Sobrien  if (sizeof (TTRACE_ARG_TYPE) < sizeof (void *))
575098944Sobrien    internal_error (__FILE__, __LINE__, "failed internal consistency check");
575198944Sobrien
575246283Sdfr  if (errno || (memory_page_dictionary.page_size <= 0))
575346283Sdfr    perror_with_name ("sysconf");
575446283Sdfr}
5755