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 (¬ifiable_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 (¬ifiable_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 ®ister_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 ®ister_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