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