xref: /openbsd-src/gnu/usr.bin/binutils/gdb/aix-thread.c (revision 11efff7f3ac2b3cfeff0c0cddc14294d9b3aca4f)
1b725ae77Skettenis /* Low level interface for debugging AIX 4.3+ pthreads.
2b725ae77Skettenis 
3b725ae77Skettenis    Copyright 1999, 2000, 2002 Free Software Foundation, Inc.
4b725ae77Skettenis    Written by Nick Duffek <nsd@redhat.com>.
5b725ae77Skettenis 
6b725ae77Skettenis    This file is part of GDB.
7b725ae77Skettenis 
8b725ae77Skettenis    This program is free software; you can redistribute it and/or modify
9b725ae77Skettenis    it under the terms of the GNU General Public License as published by
10b725ae77Skettenis    the Free Software Foundation; either version 2 of the License, or
11b725ae77Skettenis    (at your option) any later version.
12b725ae77Skettenis 
13b725ae77Skettenis    This program is distributed in the hope that it will be useful,
14b725ae77Skettenis    but WITHOUT ANY WARRANTY; without even the implied warranty of
15b725ae77Skettenis    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16b725ae77Skettenis    GNU General Public License for more details.
17b725ae77Skettenis 
18b725ae77Skettenis    You should have received a copy of the GNU General Public License
19b725ae77Skettenis    along with this program; if not, write to the Free Software
20b725ae77Skettenis    Foundation, Inc., 59 Temple Place - Suite 330,
21b725ae77Skettenis    Boston, MA 02111-1307, USA.  */
22b725ae77Skettenis 
23b725ae77Skettenis 
24b725ae77Skettenis /* This module uses the libpthdebug.a library provided by AIX 4.3+ for
25b725ae77Skettenis    debugging pthread applications.
26b725ae77Skettenis 
27b725ae77Skettenis    Some name prefix conventions:
28b725ae77Skettenis      pthdb_	provided by libpthdebug.a
29b725ae77Skettenis      pdc_	callbacks that this module provides to libpthdebug.a
30b725ae77Skettenis      pd_	variables or functions interfacing with libpthdebug.a
31b725ae77Skettenis 
32b725ae77Skettenis    libpthdebug peculiarities:
33b725ae77Skettenis 
34b725ae77Skettenis      - pthdb_ptid_pthread() is prototyped in <sys/pthdebug.h>, but
35b725ae77Skettenis        it's not documented, and after several calls it stops working
36b725ae77Skettenis        and causes other libpthdebug functions to fail.
37b725ae77Skettenis 
38b725ae77Skettenis      - pthdb_tid_pthread() doesn't always work after
39b725ae77Skettenis        pthdb_session_update(), but it does work after cycling through
40b725ae77Skettenis        all threads using pthdb_pthread().
41b725ae77Skettenis 
42b725ae77Skettenis      */
43b725ae77Skettenis 
44b725ae77Skettenis #include "defs.h"
45b725ae77Skettenis #include "gdb_assert.h"
46b725ae77Skettenis #include "gdbthread.h"
47b725ae77Skettenis #include "target.h"
48b725ae77Skettenis #include "inferior.h"
49b725ae77Skettenis #include "regcache.h"
50b725ae77Skettenis #include "gdbcmd.h"
51b725ae77Skettenis #include "ppc-tdep.h"
52*11efff7fSkettenis #include "gdb_string.h"
53b725ae77Skettenis 
54b725ae77Skettenis #include <procinfo.h>
55b725ae77Skettenis #include <sys/types.h>
56b725ae77Skettenis #include <sys/ptrace.h>
57b725ae77Skettenis #include <sys/reg.h>
58b725ae77Skettenis #include <sched.h>
59b725ae77Skettenis #include <sys/pthdebug.h>
60b725ae77Skettenis 
61b725ae77Skettenis /* Whether to emit debugging output.  */
62b725ae77Skettenis static int debug_aix_thread;
63b725ae77Skettenis 
64b725ae77Skettenis /* In AIX 5.1, functions use pthdb_tid_t instead of tid_t.  */
65b725ae77Skettenis #ifndef PTHDB_VERSION_3
66b725ae77Skettenis #define pthdb_tid_t	tid_t
67b725ae77Skettenis #endif
68b725ae77Skettenis 
69b725ae77Skettenis /* Return whether to treat PID as a debuggable thread id.  */
70b725ae77Skettenis 
71b725ae77Skettenis #define PD_TID(ptid)	(pd_active && ptid_get_tid (ptid) != 0)
72b725ae77Skettenis 
73b725ae77Skettenis /* Build a thread ptid.  */
74b725ae77Skettenis #define BUILD_THREAD(TID, PID) ptid_build (PID, 0, TID)
75b725ae77Skettenis 
76b725ae77Skettenis /* Build and lwp ptid.  */
77b725ae77Skettenis #define BUILD_LWP(LWP, PID) MERGEPID (PID, LWP)
78b725ae77Skettenis 
79b725ae77Skettenis /* pthdb_user_t value that we pass to pthdb functions.  0 causes
80b725ae77Skettenis    PTHDB_BAD_USER errors, so use 1.  */
81b725ae77Skettenis 
82b725ae77Skettenis #define PD_USER	1
83b725ae77Skettenis 
84b725ae77Skettenis /* Success and failure values returned by pthdb callbacks.  */
85b725ae77Skettenis 
86b725ae77Skettenis #define PDC_SUCCESS	PTHDB_SUCCESS
87b725ae77Skettenis #define PDC_FAILURE	PTHDB_CALLBACK
88b725ae77Skettenis 
89b725ae77Skettenis /* Private data attached to each element in GDB's thread list.  */
90b725ae77Skettenis 
91b725ae77Skettenis struct private_thread_info {
92b725ae77Skettenis   pthdb_pthread_t pdtid;	 /* thread's libpthdebug id */
93b725ae77Skettenis   pthdb_tid_t tid;			/* kernel thread id */
94b725ae77Skettenis };
95b725ae77Skettenis 
96b725ae77Skettenis /* Information about a thread of which libpthdebug is aware.  */
97b725ae77Skettenis 
98b725ae77Skettenis struct pd_thread {
99b725ae77Skettenis   pthdb_pthread_t pdtid;
100b725ae77Skettenis   pthread_t pthid;
101b725ae77Skettenis   pthdb_tid_t tid;
102b725ae77Skettenis };
103b725ae77Skettenis 
104b725ae77Skettenis /* This module's target-specific operations, active while pd_able is true.  */
105b725ae77Skettenis 
106b725ae77Skettenis static struct target_ops aix_thread_ops;
107b725ae77Skettenis 
108*11efff7fSkettenis /* Copy of the target over which ops is pushed.  This is more
109*11efff7fSkettenis    convenient than a pointer to deprecated_child_ops or core_ops,
110b725ae77Skettenis    because they lack current_target's default callbacks.  */
111b725ae77Skettenis 
112b725ae77Skettenis static struct target_ops base_target;
113b725ae77Skettenis 
114b725ae77Skettenis /* Address of the function that libpthread will call when libpthdebug
115b725ae77Skettenis    is ready to be initialized.  */
116b725ae77Skettenis 
117b725ae77Skettenis static CORE_ADDR pd_brk_addr;
118b725ae77Skettenis 
119b725ae77Skettenis /* Whether the current application is debuggable by pthdb.  */
120b725ae77Skettenis 
121b725ae77Skettenis static int pd_able = 0;
122b725ae77Skettenis 
123b725ae77Skettenis /* Whether a threaded application is being debugged.  */
124b725ae77Skettenis 
125b725ae77Skettenis static int pd_active = 0;
126b725ae77Skettenis 
127b725ae77Skettenis /* Whether the current architecture is 64-bit.
128b725ae77Skettenis    Only valid when pd_able is true.  */
129b725ae77Skettenis 
130b725ae77Skettenis static int arch64;
131b725ae77Skettenis 
132*11efff7fSkettenis /* Saved pointer to previous owner of
133*11efff7fSkettenis    deprecated_target_new_objfile_hook.  */
134b725ae77Skettenis 
135b725ae77Skettenis static void (*target_new_objfile_chain)(struct objfile *);
136b725ae77Skettenis 
137b725ae77Skettenis /* Forward declarations for pthdb callbacks.  */
138b725ae77Skettenis 
139b725ae77Skettenis static int pdc_symbol_addrs (pthdb_user_t, pthdb_symbol_t *, int);
140b725ae77Skettenis static int pdc_read_data (pthdb_user_t, void *, pthdb_addr_t, size_t);
141b725ae77Skettenis static int pdc_write_data (pthdb_user_t, void *, pthdb_addr_t, size_t);
142b725ae77Skettenis static int pdc_read_regs (pthdb_user_t user, pthdb_tid_t tid,
143b725ae77Skettenis 			  unsigned long long flags,
144b725ae77Skettenis 			  pthdb_context_t *context);
145b725ae77Skettenis static int pdc_write_regs (pthdb_user_t user, pthdb_tid_t tid,
146b725ae77Skettenis 			   unsigned long long flags,
147b725ae77Skettenis 			   pthdb_context_t *context);
148b725ae77Skettenis static int pdc_alloc (pthdb_user_t, size_t, void **);
149b725ae77Skettenis static int pdc_realloc (pthdb_user_t, void *, size_t, void **);
150b725ae77Skettenis static int pdc_dealloc (pthdb_user_t, void *);
151b725ae77Skettenis 
152b725ae77Skettenis /* pthdb callbacks.  */
153b725ae77Skettenis 
154b725ae77Skettenis static pthdb_callbacks_t pd_callbacks = {
155b725ae77Skettenis   pdc_symbol_addrs,
156b725ae77Skettenis   pdc_read_data,
157b725ae77Skettenis   pdc_write_data,
158b725ae77Skettenis   pdc_read_regs,
159b725ae77Skettenis   pdc_write_regs,
160b725ae77Skettenis   pdc_alloc,
161b725ae77Skettenis   pdc_realloc,
162b725ae77Skettenis   pdc_dealloc,
163b725ae77Skettenis   NULL
164b725ae77Skettenis };
165b725ae77Skettenis 
166b725ae77Skettenis /* Current pthdb session.  */
167b725ae77Skettenis 
168b725ae77Skettenis static pthdb_session_t pd_session;
169b725ae77Skettenis 
170b725ae77Skettenis /* Return a printable representation of pthdebug function return
171b725ae77Skettenis    STATUS.  */
172b725ae77Skettenis 
173b725ae77Skettenis static char *
pd_status2str(int status)174b725ae77Skettenis pd_status2str (int status)
175b725ae77Skettenis {
176b725ae77Skettenis   switch (status)
177b725ae77Skettenis     {
178b725ae77Skettenis     case PTHDB_SUCCESS:		return "SUCCESS";
179b725ae77Skettenis     case PTHDB_NOSYS:		return "NOSYS";
180b725ae77Skettenis     case PTHDB_NOTSUP:		return "NOTSUP";
181b725ae77Skettenis     case PTHDB_BAD_VERSION:	return "BAD_VERSION";
182b725ae77Skettenis     case PTHDB_BAD_USER:	return "BAD_USER";
183b725ae77Skettenis     case PTHDB_BAD_SESSION:	return "BAD_SESSION";
184b725ae77Skettenis     case PTHDB_BAD_MODE:	return "BAD_MODE";
185b725ae77Skettenis     case PTHDB_BAD_FLAGS:	return "BAD_FLAGS";
186b725ae77Skettenis     case PTHDB_BAD_CALLBACK:	return "BAD_CALLBACK";
187b725ae77Skettenis     case PTHDB_BAD_POINTER:	return "BAD_POINTER";
188b725ae77Skettenis     case PTHDB_BAD_CMD:		return "BAD_CMD";
189b725ae77Skettenis     case PTHDB_BAD_PTHREAD:	return "BAD_PTHREAD";
190b725ae77Skettenis     case PTHDB_BAD_ATTR:	return "BAD_ATTR";
191b725ae77Skettenis     case PTHDB_BAD_MUTEX:	return "BAD_MUTEX";
192b725ae77Skettenis     case PTHDB_BAD_MUTEXATTR:	return "BAD_MUTEXATTR";
193b725ae77Skettenis     case PTHDB_BAD_COND:	return "BAD_COND";
194b725ae77Skettenis     case PTHDB_BAD_CONDATTR:	return "BAD_CONDATTR";
195b725ae77Skettenis     case PTHDB_BAD_RWLOCK:	return "BAD_RWLOCK";
196b725ae77Skettenis     case PTHDB_BAD_RWLOCKATTR:	return "BAD_RWLOCKATTR";
197b725ae77Skettenis     case PTHDB_BAD_KEY:		return "BAD_KEY";
198b725ae77Skettenis     case PTHDB_BAD_PTID:	return "BAD_PTID";
199b725ae77Skettenis     case PTHDB_BAD_TID:		return "BAD_TID";
200b725ae77Skettenis     case PTHDB_CALLBACK:	return "CALLBACK";
201b725ae77Skettenis     case PTHDB_CONTEXT:		return "CONTEXT";
202b725ae77Skettenis     case PTHDB_HELD:		return "HELD";
203b725ae77Skettenis     case PTHDB_NOT_HELD:	return "NOT_HELD";
204b725ae77Skettenis     case PTHDB_MEMORY:		return "MEMORY";
205b725ae77Skettenis     case PTHDB_NOT_PTHREADED:	return "NOT_PTHREADED";
206b725ae77Skettenis     case PTHDB_SYMBOL:		return "SYMBOL";
207b725ae77Skettenis     case PTHDB_NOT_AVAIL:	return "NOT_AVAIL";
208b725ae77Skettenis     case PTHDB_INTERNAL:	return "INTERNAL";
209b725ae77Skettenis     default:			return "UNKNOWN";
210b725ae77Skettenis     }
211b725ae77Skettenis }
212b725ae77Skettenis 
213b725ae77Skettenis /* A call to ptrace(REQ, ID, ...) just returned RET.  Check for
214b725ae77Skettenis    exceptional conditions and either return nonlocally or else return
215b725ae77Skettenis    1 for success and 0 for failure.  */
216b725ae77Skettenis 
217b725ae77Skettenis static int
ptrace_check(int req,int id,int ret)218b725ae77Skettenis ptrace_check (int req, int id, int ret)
219b725ae77Skettenis {
220b725ae77Skettenis   if (ret == 0 && !errno)
221b725ae77Skettenis     return 1;
222b725ae77Skettenis 
223b725ae77Skettenis   /* According to ptrace(2), ptrace may fail with EPERM if "the
224b725ae77Skettenis      Identifier parameter corresponds to a kernel thread which is
225b725ae77Skettenis      stopped in kernel mode and whose computational state cannot be
226b725ae77Skettenis      read or written."  This happens quite often with register reads.  */
227b725ae77Skettenis 
228b725ae77Skettenis   switch (req)
229b725ae77Skettenis     {
230b725ae77Skettenis     case PTT_READ_GPRS:
231b725ae77Skettenis     case PTT_READ_FPRS:
232b725ae77Skettenis     case PTT_READ_SPRS:
233b725ae77Skettenis       if (ret == -1 && errno == EPERM)
234b725ae77Skettenis 	{
235b725ae77Skettenis 	  if (debug_aix_thread)
236b725ae77Skettenis 	    fprintf_unfiltered (gdb_stdlog,
237b725ae77Skettenis 				"ptrace (%d, %d) = %d (errno = %d)\n",
238b725ae77Skettenis 				req, id, ret, errno);
239b725ae77Skettenis 	  return ret == -1 ? 0 : 1;
240b725ae77Skettenis 	}
241b725ae77Skettenis       break;
242b725ae77Skettenis     }
243b725ae77Skettenis   error ("aix-thread: ptrace (%d, %d) returned %d (errno = %d %s)",
244b725ae77Skettenis 	 req, id, ret, errno, safe_strerror (errno));
245b725ae77Skettenis   return 0;  /* Not reached.  */
246b725ae77Skettenis }
247b725ae77Skettenis 
248b725ae77Skettenis /* Call ptracex (REQ, ID, ADDR, DATA, BUF).  Return success.  */
249b725ae77Skettenis 
250b725ae77Skettenis static int
ptrace64aix(int req,int id,long long addr,int data,int * buf)251b725ae77Skettenis ptrace64aix (int req, int id, long long addr, int data, int *buf)
252b725ae77Skettenis {
253b725ae77Skettenis   errno = 0;
254b725ae77Skettenis   return ptrace_check (req, id, ptracex (req, id, addr, data, buf));
255b725ae77Skettenis }
256b725ae77Skettenis 
257b725ae77Skettenis /* Call ptrace (REQ, ID, ADDR, DATA, BUF).  Return success.  */
258b725ae77Skettenis 
259b725ae77Skettenis static int
ptrace32(int req,int id,int * addr,int data,int * buf)260b725ae77Skettenis ptrace32 (int req, int id, int *addr, int data, int *buf)
261b725ae77Skettenis {
262b725ae77Skettenis   errno = 0;
263b725ae77Skettenis   return ptrace_check (req, id,
264b725ae77Skettenis 		       ptrace (req, id, (int *) addr, data, buf));
265b725ae77Skettenis }
266b725ae77Skettenis 
267b725ae77Skettenis /* If *PIDP is a composite process/thread id, convert it to a
268b725ae77Skettenis    process id.  */
269b725ae77Skettenis 
270b725ae77Skettenis static void
pid_to_prc(ptid_t * ptidp)271b725ae77Skettenis pid_to_prc (ptid_t *ptidp)
272b725ae77Skettenis {
273b725ae77Skettenis   ptid_t ptid;
274b725ae77Skettenis 
275b725ae77Skettenis   ptid = *ptidp;
276b725ae77Skettenis   if (PD_TID (ptid))
277b725ae77Skettenis     *ptidp = pid_to_ptid (PIDGET (ptid));
278b725ae77Skettenis }
279b725ae77Skettenis 
280b725ae77Skettenis /* pthdb callback: for <i> from 0 to COUNT, set SYMBOLS[<i>].addr to
281b725ae77Skettenis    the address of SYMBOLS[<i>].name.  */
282b725ae77Skettenis 
283b725ae77Skettenis static int
pdc_symbol_addrs(pthdb_user_t user,pthdb_symbol_t * symbols,int count)284b725ae77Skettenis pdc_symbol_addrs (pthdb_user_t user, pthdb_symbol_t *symbols, int count)
285b725ae77Skettenis {
286b725ae77Skettenis   struct minimal_symbol *ms;
287b725ae77Skettenis   int i;
288b725ae77Skettenis   char *name;
289b725ae77Skettenis 
290b725ae77Skettenis   if (debug_aix_thread)
291b725ae77Skettenis     fprintf_unfiltered (gdb_stdlog,
292b725ae77Skettenis       "pdc_symbol_addrs (user = %ld, symbols = 0x%lx, count = %d)\n",
293b725ae77Skettenis       user, (long) symbols, count);
294b725ae77Skettenis 
295b725ae77Skettenis   for (i = 0; i < count; i++)
296b725ae77Skettenis     {
297b725ae77Skettenis       name = symbols[i].name;
298b725ae77Skettenis       if (debug_aix_thread)
299b725ae77Skettenis 	fprintf_unfiltered (gdb_stdlog,
300b725ae77Skettenis 			    "  symbols[%d].name = \"%s\"\n", i, name);
301b725ae77Skettenis 
302b725ae77Skettenis       if (!*name)
303b725ae77Skettenis 	symbols[i].addr = 0;
304b725ae77Skettenis       else
305b725ae77Skettenis 	{
306b725ae77Skettenis 	  if (!(ms = lookup_minimal_symbol (name, NULL, NULL)))
307b725ae77Skettenis 	    {
308b725ae77Skettenis 	      if (debug_aix_thread)
309b725ae77Skettenis 		fprintf_unfiltered (gdb_stdlog, " returning PDC_FAILURE\n");
310b725ae77Skettenis 	      return PDC_FAILURE;
311b725ae77Skettenis 	    }
312b725ae77Skettenis 	  symbols[i].addr = SYMBOL_VALUE_ADDRESS (ms);
313b725ae77Skettenis 	}
314b725ae77Skettenis       if (debug_aix_thread)
315b725ae77Skettenis 	fprintf_unfiltered (gdb_stdlog, "  symbols[%d].addr = %s\n",
316*11efff7fSkettenis 			    i, hex_string (symbols[i].addr));
317b725ae77Skettenis     }
318b725ae77Skettenis   if (debug_aix_thread)
319b725ae77Skettenis     fprintf_unfiltered (gdb_stdlog, " returning PDC_SUCCESS\n");
320b725ae77Skettenis   return PDC_SUCCESS;
321b725ae77Skettenis }
322b725ae77Skettenis 
323b725ae77Skettenis /* Read registers call back function should be able to read the
324b725ae77Skettenis    context information of a debuggee kernel thread from an active
325b725ae77Skettenis    process or from a core file.  The information should be formatted
326b725ae77Skettenis    in context64 form for both 32-bit and 64-bit process.
327b725ae77Skettenis    If successful return 0, else non-zero is returned.  */
328b725ae77Skettenis 
329b725ae77Skettenis static int
pdc_read_regs(pthdb_user_t user,pthdb_tid_t tid,unsigned long long flags,pthdb_context_t * context)330b725ae77Skettenis pdc_read_regs (pthdb_user_t user,
331b725ae77Skettenis 	       pthdb_tid_t tid,
332b725ae77Skettenis 	       unsigned long long flags,
333b725ae77Skettenis 	       pthdb_context_t *context)
334b725ae77Skettenis {
335b725ae77Skettenis   /* This function doesn't appear to be used, so we could probably
336b725ae77Skettenis    just return 0 here.  HOWEVER, if it is not defined, the OS will
337b725ae77Skettenis    complain and several thread debug functions will fail.  In case
338b725ae77Skettenis    this is needed, I have implemented what I think it should do,
339b725ae77Skettenis    however this code is untested.  */
340b725ae77Skettenis 
341*11efff7fSkettenis   uint64_t gprs64[ppc_num_gprs];
342*11efff7fSkettenis   uint32_t gprs32[ppc_num_gprs];
343*11efff7fSkettenis   double fprs[ppc_num_fprs];
344b725ae77Skettenis   struct ptxsprs sprs64;
345b725ae77Skettenis   struct ptsprs sprs32;
346b725ae77Skettenis 
347b725ae77Skettenis   if (debug_aix_thread)
348b725ae77Skettenis     fprintf_unfiltered (gdb_stdlog, "pdc_read_regs tid=%d flags=%s\n",
349*11efff7fSkettenis                         (int) tid, hex_string (flags));
350b725ae77Skettenis 
351b725ae77Skettenis   /* General-purpose registers.  */
352b725ae77Skettenis   if (flags & PTHDB_FLAG_GPRS)
353b725ae77Skettenis     {
354b725ae77Skettenis       if (arch64)
355b725ae77Skettenis 	{
356b725ae77Skettenis 	  if (!ptrace64aix (PTT_READ_GPRS, tid,
357b725ae77Skettenis 			    (unsigned long) gprs64, 0, NULL))
358b725ae77Skettenis 	    memset (gprs64, 0, sizeof (gprs64));
359b725ae77Skettenis 	  memcpy (context->gpr, gprs64, sizeof(gprs64));
360b725ae77Skettenis 	}
361b725ae77Skettenis       else
362b725ae77Skettenis 	{
363b725ae77Skettenis 	  if (!ptrace32 (PTT_READ_GPRS, tid, gprs32, 0, NULL))
364b725ae77Skettenis 	    memset (gprs32, 0, sizeof (gprs32));
365b725ae77Skettenis 	  memcpy (context->gpr, gprs32, sizeof(gprs32));
366b725ae77Skettenis 	}
367b725ae77Skettenis     }
368b725ae77Skettenis 
369b725ae77Skettenis   /* Floating-point registers.  */
370b725ae77Skettenis   if (flags & PTHDB_FLAG_FPRS)
371b725ae77Skettenis     {
372b725ae77Skettenis       if (!ptrace32 (PTT_READ_FPRS, tid, (int *) fprs, 0, NULL))
373b725ae77Skettenis 	memset (fprs, 0, sizeof (fprs));
374b725ae77Skettenis       	  memcpy (context->fpr, fprs, sizeof(fprs));
375b725ae77Skettenis     }
376b725ae77Skettenis 
377b725ae77Skettenis   /* Special-purpose registers.  */
378b725ae77Skettenis   if (flags & PTHDB_FLAG_SPRS)
379b725ae77Skettenis     {
380b725ae77Skettenis       if (arch64)
381b725ae77Skettenis 	{
382b725ae77Skettenis 	  if (!ptrace64aix (PTT_READ_SPRS, tid,
383b725ae77Skettenis 			    (unsigned long) &sprs64, 0, NULL))
384b725ae77Skettenis 	    memset (&sprs64, 0, sizeof (sprs64));
385b725ae77Skettenis       	  memcpy (&context->msr, &sprs64, sizeof(sprs64));
386b725ae77Skettenis 	}
387b725ae77Skettenis       else
388b725ae77Skettenis 	{
389b725ae77Skettenis 	  if (!ptrace32 (PTT_READ_SPRS, tid, (int *) &sprs32, 0, NULL))
390b725ae77Skettenis 	    memset (&sprs32, 0, sizeof (sprs32));
391b725ae77Skettenis       	  memcpy (&context->msr, &sprs32, sizeof(sprs32));
392b725ae77Skettenis 	}
393b725ae77Skettenis     }
394b725ae77Skettenis   return 0;
395b725ae77Skettenis }
396b725ae77Skettenis 
397b725ae77Skettenis /* Write register function should be able to write requested context
398b725ae77Skettenis    information to specified debuggee's kernel thread id.
399b725ae77Skettenis    If successful return 0, else non-zero is returned.  */
400b725ae77Skettenis 
401b725ae77Skettenis static int
pdc_write_regs(pthdb_user_t user,pthdb_tid_t tid,unsigned long long flags,pthdb_context_t * context)402b725ae77Skettenis pdc_write_regs (pthdb_user_t user,
403b725ae77Skettenis 		pthdb_tid_t tid,
404b725ae77Skettenis 		unsigned long long flags,
405b725ae77Skettenis 		pthdb_context_t *context)
406b725ae77Skettenis {
407b725ae77Skettenis   /* This function doesn't appear to be used, so we could probably
408b725ae77Skettenis      just return 0 here.  HOWEVER, if it is not defined, the OS will
409b725ae77Skettenis      complain and several thread debug functions will fail.  In case
410b725ae77Skettenis      this is needed, I have implemented what I think it should do,
411b725ae77Skettenis      however this code is untested.  */
412b725ae77Skettenis 
413b725ae77Skettenis   if (debug_aix_thread)
414b725ae77Skettenis     fprintf_unfiltered (gdb_stdlog, "pdc_write_regs tid=%d flags=%s\n",
415*11efff7fSkettenis                         (int) tid, hex_string (flags));
416b725ae77Skettenis 
417b725ae77Skettenis   /* General-purpose registers.  */
418b725ae77Skettenis   if (flags & PTHDB_FLAG_GPRS)
419b725ae77Skettenis     {
420b725ae77Skettenis       if (arch64)
421b725ae77Skettenis 	ptrace64aix (PTT_WRITE_GPRS, tid,
422b725ae77Skettenis 		     (unsigned long) context->gpr, 0, NULL);
423b725ae77Skettenis       else
424b725ae77Skettenis 	ptrace32 (PTT_WRITE_GPRS, tid, (int *) context->gpr, 0, NULL);
425b725ae77Skettenis     }
426b725ae77Skettenis 
427b725ae77Skettenis  /* Floating-point registers.  */
428b725ae77Skettenis   if (flags & PTHDB_FLAG_FPRS)
429b725ae77Skettenis     {
430b725ae77Skettenis       ptrace32 (PTT_WRITE_FPRS, tid, (int *) context->fpr, 0, NULL);
431b725ae77Skettenis     }
432b725ae77Skettenis 
433b725ae77Skettenis   /* Special-purpose registers.  */
434b725ae77Skettenis   if (flags & PTHDB_FLAG_SPRS)
435b725ae77Skettenis     {
436b725ae77Skettenis       if (arch64)
437b725ae77Skettenis 	{
438b725ae77Skettenis 	  ptrace64aix (PTT_WRITE_SPRS, tid,
439b725ae77Skettenis 		       (unsigned long) &context->msr, 0, NULL);
440b725ae77Skettenis 	}
441b725ae77Skettenis       else
442b725ae77Skettenis 	{
443b725ae77Skettenis 	  ptrace32 (PTT_WRITE_SPRS, tid, (int *) &context->msr, 0, NULL);
444b725ae77Skettenis 	}
445b725ae77Skettenis     }
446b725ae77Skettenis   return 0;
447b725ae77Skettenis }
448b725ae77Skettenis 
449b725ae77Skettenis /* pthdb callback: read LEN bytes from process ADDR into BUF.  */
450b725ae77Skettenis 
451b725ae77Skettenis static int
pdc_read_data(pthdb_user_t user,void * buf,pthdb_addr_t addr,size_t len)452b725ae77Skettenis pdc_read_data (pthdb_user_t user, void *buf,
453b725ae77Skettenis 	       pthdb_addr_t addr, size_t len)
454b725ae77Skettenis {
455b725ae77Skettenis   int status, ret;
456b725ae77Skettenis 
457b725ae77Skettenis   if (debug_aix_thread)
458b725ae77Skettenis     fprintf_unfiltered (gdb_stdlog,
459b725ae77Skettenis       "pdc_read_data (user = %ld, buf = 0x%lx, addr = %s, len = %ld)\n",
460*11efff7fSkettenis       user, (long) buf, hex_string (addr), len);
461b725ae77Skettenis 
462b725ae77Skettenis   status = target_read_memory (addr, buf, len);
463b725ae77Skettenis   ret = status == 0 ? PDC_SUCCESS : PDC_FAILURE;
464b725ae77Skettenis 
465b725ae77Skettenis   if (debug_aix_thread)
466b725ae77Skettenis     fprintf_unfiltered (gdb_stdlog, "  status=%d, returning %s\n",
467b725ae77Skettenis 			status, pd_status2str (ret));
468b725ae77Skettenis   return ret;
469b725ae77Skettenis }
470b725ae77Skettenis 
471b725ae77Skettenis /* pthdb callback: write LEN bytes from BUF to process ADDR.  */
472b725ae77Skettenis 
473b725ae77Skettenis static int
pdc_write_data(pthdb_user_t user,void * buf,pthdb_addr_t addr,size_t len)474b725ae77Skettenis pdc_write_data (pthdb_user_t user, void *buf,
475b725ae77Skettenis 		pthdb_addr_t addr, size_t len)
476b725ae77Skettenis {
477b725ae77Skettenis   int status, ret;
478b725ae77Skettenis 
479b725ae77Skettenis   if (debug_aix_thread)
480b725ae77Skettenis     fprintf_unfiltered (gdb_stdlog,
481b725ae77Skettenis       "pdc_write_data (user = %ld, buf = 0x%lx, addr = %s, len = %ld)\n",
482*11efff7fSkettenis       user, (long) buf, hex_string (addr), len);
483b725ae77Skettenis 
484b725ae77Skettenis   status = target_write_memory (addr, buf, len);
485b725ae77Skettenis   ret = status == 0 ? PDC_SUCCESS : PDC_FAILURE;
486b725ae77Skettenis 
487b725ae77Skettenis   if (debug_aix_thread)
488b725ae77Skettenis     fprintf_unfiltered (gdb_stdlog, "  status=%d, returning %s\n", status,
489b725ae77Skettenis 			pd_status2str (ret));
490b725ae77Skettenis   return ret;
491b725ae77Skettenis }
492b725ae77Skettenis 
493b725ae77Skettenis /* pthdb callback: allocate a LEN-byte buffer and store a pointer to it
494b725ae77Skettenis    in BUFP.  */
495b725ae77Skettenis 
496b725ae77Skettenis static int
pdc_alloc(pthdb_user_t user,size_t len,void ** bufp)497b725ae77Skettenis pdc_alloc (pthdb_user_t user, size_t len, void **bufp)
498b725ae77Skettenis {
499b725ae77Skettenis   if (debug_aix_thread)
500b725ae77Skettenis     fprintf_unfiltered (gdb_stdlog,
501b725ae77Skettenis                         "pdc_alloc (user = %ld, len = %ld, bufp = 0x%lx)\n",
502b725ae77Skettenis 			user, len, (long) bufp);
503b725ae77Skettenis   *bufp = xmalloc (len);
504b725ae77Skettenis   if (debug_aix_thread)
505b725ae77Skettenis     fprintf_unfiltered (gdb_stdlog,
506b725ae77Skettenis 			"  malloc returned 0x%lx\n", (long) *bufp);
507b725ae77Skettenis 
508b725ae77Skettenis   /* Note: xmalloc() can't return 0; therefore PDC_FAILURE will never
509b725ae77Skettenis      be returned.  */
510b725ae77Skettenis 
511b725ae77Skettenis   return *bufp ? PDC_SUCCESS : PDC_FAILURE;
512b725ae77Skettenis }
513b725ae77Skettenis 
514b725ae77Skettenis /* pthdb callback: reallocate BUF, which was allocated by the alloc or
515b725ae77Skettenis    realloc callback, so that it contains LEN bytes, and store a
516b725ae77Skettenis    pointer to the result in BUFP.  */
517b725ae77Skettenis 
518b725ae77Skettenis static int
pdc_realloc(pthdb_user_t user,void * buf,size_t len,void ** bufp)519b725ae77Skettenis pdc_realloc (pthdb_user_t user, void *buf, size_t len, void **bufp)
520b725ae77Skettenis {
521b725ae77Skettenis   if (debug_aix_thread)
522b725ae77Skettenis     fprintf_unfiltered (gdb_stdlog,
523b725ae77Skettenis       "pdc_realloc (user = %ld, buf = 0x%lx, len = %ld, bufp = 0x%lx)\n",
524b725ae77Skettenis       user, (long) buf, len, (long) bufp);
525b725ae77Skettenis   *bufp = xrealloc (buf, len);
526b725ae77Skettenis   if (debug_aix_thread)
527b725ae77Skettenis     fprintf_unfiltered (gdb_stdlog,
528b725ae77Skettenis 			"  realloc returned 0x%lx\n", (long) *bufp);
529b725ae77Skettenis   return *bufp ? PDC_SUCCESS : PDC_FAILURE;
530b725ae77Skettenis }
531b725ae77Skettenis 
532b725ae77Skettenis /* pthdb callback: free BUF, which was allocated by the alloc or
533b725ae77Skettenis    realloc callback.  */
534b725ae77Skettenis 
535b725ae77Skettenis static int
pdc_dealloc(pthdb_user_t user,void * buf)536b725ae77Skettenis pdc_dealloc (pthdb_user_t user, void *buf)
537b725ae77Skettenis {
538b725ae77Skettenis   if (debug_aix_thread)
539b725ae77Skettenis     fprintf_unfiltered (gdb_stdlog,
540b725ae77Skettenis 			"pdc_free (user = %ld, buf = 0x%lx)\n", user,
541b725ae77Skettenis                         (long) buf);
542b725ae77Skettenis   xfree (buf);
543b725ae77Skettenis   return PDC_SUCCESS;
544b725ae77Skettenis }
545b725ae77Skettenis 
546b725ae77Skettenis /* Return a printable representation of pthread STATE.  */
547b725ae77Skettenis 
548b725ae77Skettenis static char *
state2str(pthdb_state_t state)549b725ae77Skettenis state2str (pthdb_state_t state)
550b725ae77Skettenis {
551b725ae77Skettenis   switch (state)
552b725ae77Skettenis     {
553b725ae77Skettenis     case PST_IDLE:	return "idle";		/* being created */
554b725ae77Skettenis     case PST_RUN:	return "running";	/* running */
555b725ae77Skettenis     case PST_SLEEP:	return "sleeping";	/* awaiting an event */
556b725ae77Skettenis     case PST_READY:	return "ready";		/* runnable */
557b725ae77Skettenis     case PST_TERM:	return "finished";	/* awaiting a join/detach */
558b725ae77Skettenis     default:		return "unknown";
559b725ae77Skettenis     }
560b725ae77Skettenis }
561b725ae77Skettenis 
562b725ae77Skettenis /* qsort() comparison function for sorting pd_thread structs by pthid.  */
563b725ae77Skettenis 
564b725ae77Skettenis static int
pcmp(const void * p1v,const void * p2v)565b725ae77Skettenis pcmp (const void *p1v, const void *p2v)
566b725ae77Skettenis {
567b725ae77Skettenis   struct pd_thread *p1 = (struct pd_thread *) p1v;
568b725ae77Skettenis   struct pd_thread *p2 = (struct pd_thread *) p2v;
569b725ae77Skettenis   return p1->pthid < p2->pthid ? -1 : p1->pthid > p2->pthid;
570b725ae77Skettenis }
571b725ae77Skettenis 
572b725ae77Skettenis /* iterate_over_threads() callback for counting GDB threads.  */
573b725ae77Skettenis 
574b725ae77Skettenis static int
giter_count(struct thread_info * thread,void * countp)575b725ae77Skettenis giter_count (struct thread_info *thread, void *countp)
576b725ae77Skettenis {
577b725ae77Skettenis   (*(int *) countp)++;
578b725ae77Skettenis   return 0;
579b725ae77Skettenis }
580b725ae77Skettenis 
581b725ae77Skettenis /* iterate_over_threads() callback for accumulating GDB thread pids.  */
582b725ae77Skettenis 
583b725ae77Skettenis static int
giter_accum(struct thread_info * thread,void * bufp)584b725ae77Skettenis giter_accum (struct thread_info *thread, void *bufp)
585b725ae77Skettenis {
586b725ae77Skettenis   **(struct thread_info ***) bufp = thread;
587b725ae77Skettenis   (*(struct thread_info ***) bufp)++;
588b725ae77Skettenis   return 0;
589b725ae77Skettenis }
590b725ae77Skettenis 
591b725ae77Skettenis /* ptid comparison function */
592b725ae77Skettenis 
593b725ae77Skettenis static int
ptid_cmp(ptid_t ptid1,ptid_t ptid2)594b725ae77Skettenis ptid_cmp (ptid_t ptid1, ptid_t ptid2)
595b725ae77Skettenis {
596b725ae77Skettenis   int pid1, pid2;
597b725ae77Skettenis 
598b725ae77Skettenis   if (ptid_get_pid (ptid1) < ptid_get_pid (ptid2))
599b725ae77Skettenis     return -1;
600b725ae77Skettenis   else if (ptid_get_pid (ptid1) > ptid_get_pid (ptid2))
601b725ae77Skettenis     return 1;
602b725ae77Skettenis   else if (ptid_get_tid (ptid1) < ptid_get_tid (ptid2))
603b725ae77Skettenis     return -1;
604b725ae77Skettenis   else if (ptid_get_tid (ptid1) > ptid_get_tid (ptid2))
605b725ae77Skettenis     return 1;
606b725ae77Skettenis   else if (ptid_get_lwp (ptid1) < ptid_get_lwp (ptid2))
607b725ae77Skettenis     return -1;
608b725ae77Skettenis   else if (ptid_get_lwp (ptid1) > ptid_get_lwp (ptid2))
609b725ae77Skettenis     return 1;
610b725ae77Skettenis   else
611b725ae77Skettenis     return 0;
612b725ae77Skettenis }
613b725ae77Skettenis 
614b725ae77Skettenis /* qsort() comparison function for sorting thread_info structs by pid.  */
615b725ae77Skettenis 
616b725ae77Skettenis static int
gcmp(const void * t1v,const void * t2v)617b725ae77Skettenis gcmp (const void *t1v, const void *t2v)
618b725ae77Skettenis {
619b725ae77Skettenis   struct thread_info *t1 = *(struct thread_info **) t1v;
620b725ae77Skettenis   struct thread_info *t2 = *(struct thread_info **) t2v;
621b725ae77Skettenis   return ptid_cmp (t1->ptid, t2->ptid);
622b725ae77Skettenis }
623b725ae77Skettenis 
624*11efff7fSkettenis /* Search through the list of all kernel threads for the thread
625*11efff7fSkettenis    that has stopped on a SIGTRAP signal, and return its TID.
626*11efff7fSkettenis    Return 0 if none found.  */
627*11efff7fSkettenis 
628*11efff7fSkettenis static pthdb_tid_t
get_signaled_thread(void)629*11efff7fSkettenis get_signaled_thread (void)
630*11efff7fSkettenis {
631*11efff7fSkettenis   struct thrdsinfo64 thrinf;
632*11efff7fSkettenis   pthdb_tid_t ktid = 0;
633*11efff7fSkettenis   int result = 0;
634*11efff7fSkettenis 
635*11efff7fSkettenis   /* getthrds(3) isn't prototyped in any AIX 4.3.3 #include file.  */
636*11efff7fSkettenis   extern int getthrds (pid_t, struct thrdsinfo64 *,
637*11efff7fSkettenis 		       int, pthdb_tid_t *, int);
638*11efff7fSkettenis 
639*11efff7fSkettenis   while (1)
640*11efff7fSkettenis   {
641*11efff7fSkettenis     if (getthrds (PIDGET (inferior_ptid), &thrinf,
642*11efff7fSkettenis           	  sizeof (thrinf), &ktid, 1) != 1)
643*11efff7fSkettenis       break;
644*11efff7fSkettenis 
645*11efff7fSkettenis     if (thrinf.ti_cursig == SIGTRAP)
646*11efff7fSkettenis       return thrinf.ti_tid;
647*11efff7fSkettenis   }
648*11efff7fSkettenis 
649*11efff7fSkettenis   /* Didn't find any thread stopped on a SIGTRAP signal.  */
650*11efff7fSkettenis   return 0;
651*11efff7fSkettenis }
652*11efff7fSkettenis 
653b725ae77Skettenis /* Synchronize GDB's thread list with libpthdebug's.
654b725ae77Skettenis 
655b725ae77Skettenis    There are some benefits of doing this every time the inferior stops:
656b725ae77Skettenis 
657b725ae77Skettenis      - allows users to run thread-specific commands without needing to
658b725ae77Skettenis        run "info threads" first
659b725ae77Skettenis 
660b725ae77Skettenis      - helps pthdb_tid_pthread() work properly (see "libpthdebug
661b725ae77Skettenis        peculiarities" at the top of this module)
662b725ae77Skettenis 
663b725ae77Skettenis      - simplifies the demands placed on libpthdebug, which seems to
664b725ae77Skettenis        have difficulty with certain call patterns */
665b725ae77Skettenis 
666b725ae77Skettenis static void
sync_threadlists(void)667b725ae77Skettenis sync_threadlists (void)
668b725ae77Skettenis {
669b725ae77Skettenis   int cmd, status, infpid;
670b725ae77Skettenis   int pcount, psize, pi, gcount, gi;
671b725ae77Skettenis   struct pd_thread *pbuf;
672b725ae77Skettenis   struct thread_info **gbuf, **g, *thread;
673b725ae77Skettenis   pthdb_pthread_t pdtid;
674b725ae77Skettenis   pthread_t pthid;
675b725ae77Skettenis   pthdb_tid_t tid;
676b725ae77Skettenis 
677b725ae77Skettenis   /* Accumulate an array of libpthdebug threads sorted by pthread id.  */
678b725ae77Skettenis 
679b725ae77Skettenis   pcount = 0;
680b725ae77Skettenis   psize = 1;
681b725ae77Skettenis   pbuf = (struct pd_thread *) xmalloc (psize * sizeof *pbuf);
682b725ae77Skettenis 
683b725ae77Skettenis   for (cmd = PTHDB_LIST_FIRST;; cmd = PTHDB_LIST_NEXT)
684b725ae77Skettenis     {
685b725ae77Skettenis       status = pthdb_pthread (pd_session, &pdtid, cmd);
686b725ae77Skettenis       if (status != PTHDB_SUCCESS || pdtid == PTHDB_INVALID_PTHREAD)
687b725ae77Skettenis 	break;
688b725ae77Skettenis 
689b725ae77Skettenis       status = pthdb_pthread_ptid (pd_session, pdtid, &pthid);
690b725ae77Skettenis       if (status != PTHDB_SUCCESS || pthid == PTHDB_INVALID_PTID)
691b725ae77Skettenis 	continue;
692b725ae77Skettenis 
693b725ae77Skettenis       if (pcount == psize)
694b725ae77Skettenis 	{
695b725ae77Skettenis 	  psize *= 2;
696b725ae77Skettenis 	  pbuf = (struct pd_thread *) xrealloc (pbuf,
697b725ae77Skettenis 						psize * sizeof *pbuf);
698b725ae77Skettenis 	}
699b725ae77Skettenis       pbuf[pcount].pdtid = pdtid;
700b725ae77Skettenis       pbuf[pcount].pthid = pthid;
701b725ae77Skettenis       pcount++;
702b725ae77Skettenis     }
703b725ae77Skettenis 
704b725ae77Skettenis   for (pi = 0; pi < pcount; pi++)
705b725ae77Skettenis     {
706b725ae77Skettenis       status = pthdb_pthread_tid (pd_session, pbuf[pi].pdtid, &tid);
707b725ae77Skettenis       if (status != PTHDB_SUCCESS)
708b725ae77Skettenis 	tid = PTHDB_INVALID_TID;
709b725ae77Skettenis       pbuf[pi].tid = tid;
710b725ae77Skettenis     }
711b725ae77Skettenis 
712b725ae77Skettenis   qsort (pbuf, pcount, sizeof *pbuf, pcmp);
713b725ae77Skettenis 
714b725ae77Skettenis   /* Accumulate an array of GDB threads sorted by pid.  */
715b725ae77Skettenis 
716b725ae77Skettenis   gcount = 0;
717b725ae77Skettenis   iterate_over_threads (giter_count, &gcount);
718b725ae77Skettenis   g = gbuf = (struct thread_info **) xmalloc (gcount * sizeof *gbuf);
719b725ae77Skettenis   iterate_over_threads (giter_accum, &g);
720b725ae77Skettenis   qsort (gbuf, gcount, sizeof *gbuf, gcmp);
721b725ae77Skettenis 
722b725ae77Skettenis   /* Apply differences between the two arrays to GDB's thread list.  */
723b725ae77Skettenis 
724b725ae77Skettenis   infpid = PIDGET (inferior_ptid);
725b725ae77Skettenis   for (pi = gi = 0; pi < pcount || gi < gcount;)
726b725ae77Skettenis     {
727b725ae77Skettenis       if (pi == pcount)
728b725ae77Skettenis 	{
729b725ae77Skettenis 	  delete_thread (gbuf[gi]->ptid);
730b725ae77Skettenis 	  gi++;
731b725ae77Skettenis 	}
732b725ae77Skettenis       else if (gi == gcount)
733b725ae77Skettenis 	{
734b725ae77Skettenis 	  thread = add_thread (BUILD_THREAD (pbuf[pi].pthid, infpid));
735b725ae77Skettenis 	  thread->private = xmalloc (sizeof (struct private_thread_info));
736b725ae77Skettenis 	  thread->private->pdtid = pbuf[pi].pdtid;
737b725ae77Skettenis 	  thread->private->tid = pbuf[pi].tid;
738b725ae77Skettenis 	  pi++;
739b725ae77Skettenis 	}
740b725ae77Skettenis       else
741b725ae77Skettenis 	{
742b725ae77Skettenis 	  ptid_t pptid, gptid;
743b725ae77Skettenis 	  int cmp_result;
744b725ae77Skettenis 
745b725ae77Skettenis 	  pptid = BUILD_THREAD (pbuf[pi].pthid, infpid);
746b725ae77Skettenis 	  gptid = gbuf[gi]->ptid;
747b725ae77Skettenis 	  pdtid = pbuf[pi].pdtid;
748b725ae77Skettenis 	  tid = pbuf[pi].tid;
749b725ae77Skettenis 
750b725ae77Skettenis 	  cmp_result = ptid_cmp (pptid, gptid);
751b725ae77Skettenis 
752b725ae77Skettenis 	  if (cmp_result == 0)
753b725ae77Skettenis 	    {
754b725ae77Skettenis 	      gbuf[gi]->private->pdtid = pdtid;
755b725ae77Skettenis 	      gbuf[gi]->private->tid = tid;
756b725ae77Skettenis 	      pi++;
757b725ae77Skettenis 	      gi++;
758b725ae77Skettenis 	    }
759b725ae77Skettenis 	  else if (cmp_result > 0)
760b725ae77Skettenis 	    {
761b725ae77Skettenis 	      delete_thread (gptid);
762b725ae77Skettenis 	      gi++;
763b725ae77Skettenis 	    }
764b725ae77Skettenis 	  else
765b725ae77Skettenis 	    {
766b725ae77Skettenis 	      thread = add_thread (pptid);
767b725ae77Skettenis 	      thread->private = xmalloc (sizeof (struct private_thread_info));
768b725ae77Skettenis 	      thread->private->pdtid = pdtid;
769b725ae77Skettenis 	      thread->private->tid = tid;
770b725ae77Skettenis 	      pi++;
771b725ae77Skettenis 	    }
772b725ae77Skettenis 	}
773b725ae77Skettenis     }
774b725ae77Skettenis 
775b725ae77Skettenis   xfree (pbuf);
776b725ae77Skettenis   xfree (gbuf);
777b725ae77Skettenis }
778b725ae77Skettenis 
779*11efff7fSkettenis /* Iterate_over_threads() callback for locating a thread, using
780*11efff7fSkettenis    the TID of its associated kernel thread.  */
781b725ae77Skettenis 
782b725ae77Skettenis static int
iter_tid(struct thread_info * thread,void * tidp)783*11efff7fSkettenis iter_tid (struct thread_info *thread, void *tidp)
784b725ae77Skettenis {
785*11efff7fSkettenis   const pthdb_tid_t tid = *(pthdb_tid_t *)tidp;
786b725ae77Skettenis 
787*11efff7fSkettenis   return (thread->private->tid == tid);
788b725ae77Skettenis }
789b725ae77Skettenis 
790b725ae77Skettenis /* Synchronize libpthdebug's state with the inferior and with GDB,
791b725ae77Skettenis    generate a composite process/thread <pid> for the current thread,
792b725ae77Skettenis    set inferior_ptid to <pid> if SET_INFPID, and return <pid>.  */
793b725ae77Skettenis 
794b725ae77Skettenis static ptid_t
pd_update(int set_infpid)795b725ae77Skettenis pd_update (int set_infpid)
796b725ae77Skettenis {
797b725ae77Skettenis   int status;
798b725ae77Skettenis   ptid_t ptid;
799*11efff7fSkettenis   pthdb_tid_t tid;
800*11efff7fSkettenis   struct thread_info *thread = NULL;
801b725ae77Skettenis 
802b725ae77Skettenis   if (!pd_active)
803b725ae77Skettenis     return inferior_ptid;
804b725ae77Skettenis 
805b725ae77Skettenis   status = pthdb_session_update (pd_session);
806b725ae77Skettenis   if (status != PTHDB_SUCCESS)
807b725ae77Skettenis     return inferior_ptid;
808b725ae77Skettenis 
809b725ae77Skettenis   sync_threadlists ();
810b725ae77Skettenis 
811b725ae77Skettenis   /* Define "current thread" as one that just received a trap signal.  */
812b725ae77Skettenis 
813*11efff7fSkettenis   tid = get_signaled_thread ();
814*11efff7fSkettenis   if (tid != 0)
815*11efff7fSkettenis     thread = iterate_over_threads (iter_tid, &tid);
816b725ae77Skettenis   if (!thread)
817b725ae77Skettenis     ptid = inferior_ptid;
818b725ae77Skettenis   else
819b725ae77Skettenis     {
820b725ae77Skettenis       ptid = thread->ptid;
821b725ae77Skettenis       if (set_infpid)
822b725ae77Skettenis 	inferior_ptid = ptid;
823b725ae77Skettenis     }
824b725ae77Skettenis   return ptid;
825b725ae77Skettenis }
826b725ae77Skettenis 
827b725ae77Skettenis /* Try to start debugging threads in the current process.
828b725ae77Skettenis    If successful and SET_INFPID, set inferior_ptid to reflect the
829b725ae77Skettenis    current thread.  */
830b725ae77Skettenis 
831b725ae77Skettenis static ptid_t
pd_activate(int set_infpid)832b725ae77Skettenis pd_activate (int set_infpid)
833b725ae77Skettenis {
834b725ae77Skettenis   int status;
835b725ae77Skettenis 
836b725ae77Skettenis   status = pthdb_session_init (PD_USER, arch64 ? PEM_64BIT : PEM_32BIT,
837b725ae77Skettenis 			       PTHDB_FLAG_REGS, &pd_callbacks,
838b725ae77Skettenis 			       &pd_session);
839b725ae77Skettenis   if (status != PTHDB_SUCCESS)
840b725ae77Skettenis     {
841b725ae77Skettenis       return inferior_ptid;
842b725ae77Skettenis     }
843b725ae77Skettenis   pd_active = 1;
844b725ae77Skettenis   return pd_update (set_infpid);
845b725ae77Skettenis }
846b725ae77Skettenis 
847b725ae77Skettenis /* Undo the effects of pd_activate().  */
848b725ae77Skettenis 
849b725ae77Skettenis static void
pd_deactivate(void)850b725ae77Skettenis pd_deactivate (void)
851b725ae77Skettenis {
852b725ae77Skettenis   if (!pd_active)
853b725ae77Skettenis     return;
854b725ae77Skettenis   pthdb_session_destroy (pd_session);
855b725ae77Skettenis 
856b725ae77Skettenis   pid_to_prc (&inferior_ptid);
857b725ae77Skettenis   pd_active = 0;
858b725ae77Skettenis }
859b725ae77Skettenis 
860b725ae77Skettenis /* An object file has just been loaded.  Check whether the current
861b725ae77Skettenis    application is pthreaded, and if so, prepare for thread debugging.  */
862b725ae77Skettenis 
863b725ae77Skettenis static void
pd_enable(void)864b725ae77Skettenis pd_enable (void)
865b725ae77Skettenis {
866b725ae77Skettenis   int status;
867b725ae77Skettenis   char *stub_name;
868b725ae77Skettenis   struct minimal_symbol *ms;
869b725ae77Skettenis 
870b725ae77Skettenis   /* Don't initialize twice.  */
871b725ae77Skettenis   if (pd_able)
872b725ae77Skettenis     return;
873b725ae77Skettenis 
874b725ae77Skettenis   /* Check application word size.  */
875*11efff7fSkettenis   arch64 = register_size (current_gdbarch, 0) == 8;
876b725ae77Skettenis 
877b725ae77Skettenis   /* Check whether the application is pthreaded.  */
878b725ae77Skettenis   stub_name = NULL;
879b725ae77Skettenis   status = pthdb_session_pthreaded (PD_USER, PTHDB_FLAG_REGS,
880b725ae77Skettenis 				    &pd_callbacks, &stub_name);
881b725ae77Skettenis   if ((status != PTHDB_SUCCESS &&
882b725ae77Skettenis        status != PTHDB_NOT_PTHREADED) || !stub_name)
883b725ae77Skettenis     return;
884b725ae77Skettenis 
885b725ae77Skettenis   /* Set a breakpoint on the returned stub function.  */
886b725ae77Skettenis   if (!(ms = lookup_minimal_symbol (stub_name, NULL, NULL)))
887b725ae77Skettenis     return;
888b725ae77Skettenis   pd_brk_addr = SYMBOL_VALUE_ADDRESS (ms);
889b725ae77Skettenis   if (!create_thread_event_breakpoint (pd_brk_addr))
890b725ae77Skettenis     return;
891b725ae77Skettenis 
892b725ae77Skettenis   /* Prepare for thread debugging.  */
893b725ae77Skettenis   base_target = current_target;
894b725ae77Skettenis   push_target (&aix_thread_ops);
895b725ae77Skettenis   pd_able = 1;
896b725ae77Skettenis 
897b725ae77Skettenis   /* If we're debugging a core file or an attached inferior, the
898b725ae77Skettenis      pthread library may already have been initialized, so try to
899b725ae77Skettenis      activate thread debugging.  */
900b725ae77Skettenis   pd_activate (1);
901b725ae77Skettenis }
902b725ae77Skettenis 
903b725ae77Skettenis /* Undo the effects of pd_enable().  */
904b725ae77Skettenis 
905b725ae77Skettenis static void
pd_disable(void)906b725ae77Skettenis pd_disable (void)
907b725ae77Skettenis {
908b725ae77Skettenis   if (!pd_able)
909b725ae77Skettenis     return;
910b725ae77Skettenis   if (pd_active)
911b725ae77Skettenis     pd_deactivate ();
912b725ae77Skettenis   pd_able = 0;
913b725ae77Skettenis   unpush_target (&aix_thread_ops);
914b725ae77Skettenis }
915b725ae77Skettenis 
916*11efff7fSkettenis /* deprecated_target_new_objfile_hook callback.
917b725ae77Skettenis 
918b725ae77Skettenis    If OBJFILE is non-null, check whether a threaded application is
919b725ae77Skettenis    being debugged, and if so, prepare for thread debugging.
920b725ae77Skettenis 
921b725ae77Skettenis    If OBJFILE is null, stop debugging threads.  */
922b725ae77Skettenis 
923b725ae77Skettenis static void
new_objfile(struct objfile * objfile)924b725ae77Skettenis new_objfile (struct objfile *objfile)
925b725ae77Skettenis {
926b725ae77Skettenis   if (objfile)
927b725ae77Skettenis     pd_enable ();
928b725ae77Skettenis   else
929b725ae77Skettenis     pd_disable ();
930b725ae77Skettenis 
931b725ae77Skettenis   if (target_new_objfile_chain)
932b725ae77Skettenis     target_new_objfile_chain (objfile);
933b725ae77Skettenis }
934b725ae77Skettenis 
935b725ae77Skettenis /* Attach to process specified by ARGS.  */
936b725ae77Skettenis 
937b725ae77Skettenis static void
aix_thread_attach(char * args,int from_tty)938b725ae77Skettenis aix_thread_attach (char *args, int from_tty)
939b725ae77Skettenis {
940b725ae77Skettenis   base_target.to_attach (args, from_tty);
941b725ae77Skettenis   pd_activate (1);
942b725ae77Skettenis }
943b725ae77Skettenis 
944b725ae77Skettenis /* Detach from the process attached to by aix_thread_attach().  */
945b725ae77Skettenis 
946b725ae77Skettenis static void
aix_thread_detach(char * args,int from_tty)947b725ae77Skettenis aix_thread_detach (char *args, int from_tty)
948b725ae77Skettenis {
949b725ae77Skettenis   pd_disable ();
950b725ae77Skettenis   base_target.to_detach (args, from_tty);
951b725ae77Skettenis }
952b725ae77Skettenis 
953b725ae77Skettenis /* Tell the inferior process to continue running thread PID if != -1
954b725ae77Skettenis    and all threads otherwise.  */
955b725ae77Skettenis 
956b725ae77Skettenis static void
aix_thread_resume(ptid_t ptid,int step,enum target_signal sig)957b725ae77Skettenis aix_thread_resume (ptid_t ptid, int step, enum target_signal sig)
958b725ae77Skettenis {
959b725ae77Skettenis   struct thread_info *thread;
960b725ae77Skettenis   pthdb_tid_t tid[2];
961b725ae77Skettenis 
962b725ae77Skettenis   if (!PD_TID (ptid))
963b725ae77Skettenis     {
964b725ae77Skettenis       struct cleanup *cleanup = save_inferior_ptid ();
965b725ae77Skettenis       inferior_ptid = pid_to_ptid (PIDGET (inferior_ptid));
966b725ae77Skettenis       base_target.to_resume (ptid, step, sig);
967b725ae77Skettenis       do_cleanups (cleanup);
968b725ae77Skettenis     }
969b725ae77Skettenis   else
970b725ae77Skettenis     {
971b725ae77Skettenis       thread = find_thread_pid (ptid);
972b725ae77Skettenis       if (!thread)
973b725ae77Skettenis 	error ("aix-thread resume: unknown pthread %ld",
974b725ae77Skettenis 	       TIDGET (ptid));
975b725ae77Skettenis 
976b725ae77Skettenis       tid[0] = thread->private->tid;
977b725ae77Skettenis       if (tid[0] == PTHDB_INVALID_TID)
978b725ae77Skettenis 	error ("aix-thread resume: no tid for pthread %ld",
979b725ae77Skettenis 	       TIDGET (ptid));
980b725ae77Skettenis       tid[1] = 0;
981b725ae77Skettenis 
982b725ae77Skettenis       if (arch64)
983b725ae77Skettenis 	ptrace64aix (PTT_CONTINUE, tid[0], 1,
984b725ae77Skettenis 		     target_signal_to_host (sig), (int *) tid);
985b725ae77Skettenis       else
986b725ae77Skettenis 	ptrace32 (PTT_CONTINUE, tid[0], (int *) 1,
987b725ae77Skettenis 		  target_signal_to_host (sig), (int *) tid);
988b725ae77Skettenis     }
989b725ae77Skettenis }
990b725ae77Skettenis 
991b725ae77Skettenis /* Wait for thread/process ID if != -1 or for any thread otherwise.
992b725ae77Skettenis    If an error occurs, return -1, else return the pid of the stopped
993b725ae77Skettenis    thread.  */
994b725ae77Skettenis 
995b725ae77Skettenis static ptid_t
aix_thread_wait(ptid_t ptid,struct target_waitstatus * status)996b725ae77Skettenis aix_thread_wait (ptid_t ptid, struct target_waitstatus *status)
997b725ae77Skettenis {
998b725ae77Skettenis   struct cleanup *cleanup = save_inferior_ptid ();
999b725ae77Skettenis 
1000b725ae77Skettenis   pid_to_prc (&ptid);
1001b725ae77Skettenis 
1002b725ae77Skettenis   inferior_ptid = pid_to_ptid (PIDGET (inferior_ptid));
1003b725ae77Skettenis   ptid = base_target.to_wait (ptid, status);
1004b725ae77Skettenis   do_cleanups (cleanup);
1005b725ae77Skettenis 
1006b725ae77Skettenis   if (PIDGET (ptid) == -1)
1007b725ae77Skettenis     return pid_to_ptid (-1);
1008b725ae77Skettenis 
1009b725ae77Skettenis   /* Check whether libpthdebug might be ready to be initialized.  */
1010b725ae77Skettenis   if (!pd_active && status->kind == TARGET_WAITKIND_STOPPED &&
1011b725ae77Skettenis       status->value.sig == TARGET_SIGNAL_TRAP &&
1012b725ae77Skettenis       read_pc_pid (ptid) - DECR_PC_AFTER_BREAK == pd_brk_addr)
1013b725ae77Skettenis     return pd_activate (0);
1014b725ae77Skettenis 
1015b725ae77Skettenis   return pd_update (0);
1016b725ae77Skettenis }
1017b725ae77Skettenis 
1018b725ae77Skettenis /* Record that the 64-bit general-purpose registers contain VALS.  */
1019b725ae77Skettenis 
1020b725ae77Skettenis static void
supply_gprs64(uint64_t * vals)1021b725ae77Skettenis supply_gprs64 (uint64_t *vals)
1022b725ae77Skettenis {
1023*11efff7fSkettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
1024b725ae77Skettenis   int regno;
1025b725ae77Skettenis 
1026*11efff7fSkettenis   for (regno = 0; regno < ppc_num_gprs; regno++)
1027*11efff7fSkettenis     regcache_raw_supply (current_regcache, tdep->ppc_gp0_regnum + regno,
1028*11efff7fSkettenis 			 (char *) (vals + regno));
1029b725ae77Skettenis }
1030b725ae77Skettenis 
1031b725ae77Skettenis /* Record that 32-bit register REGNO contains VAL.  */
1032b725ae77Skettenis 
1033b725ae77Skettenis static void
supply_reg32(int regno,uint32_t val)1034b725ae77Skettenis supply_reg32 (int regno, uint32_t val)
1035b725ae77Skettenis {
1036*11efff7fSkettenis   regcache_raw_supply (current_regcache, regno, (char *) &val);
1037b725ae77Skettenis }
1038b725ae77Skettenis 
1039b725ae77Skettenis /* Record that the floating-point registers contain VALS.  */
1040b725ae77Skettenis 
1041b725ae77Skettenis static void
supply_fprs(double * vals)1042b725ae77Skettenis supply_fprs (double *vals)
1043b725ae77Skettenis {
1044*11efff7fSkettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
1045b725ae77Skettenis   int regno;
1046b725ae77Skettenis 
1047*11efff7fSkettenis   /* This function should never be called on architectures without
1048*11efff7fSkettenis      floating-point registers.  */
1049*11efff7fSkettenis   gdb_assert (ppc_floating_point_unit_p (current_gdbarch));
1050*11efff7fSkettenis 
1051*11efff7fSkettenis   for (regno = 0; regno < ppc_num_fprs; regno++)
1052*11efff7fSkettenis     regcache_raw_supply (current_regcache, regno + tdep->ppc_fp0_regnum,
1053*11efff7fSkettenis 			 (char *) (vals + regno));
1054b725ae77Skettenis }
1055b725ae77Skettenis 
1056b725ae77Skettenis /* Predicate to test whether given register number is a "special" register.  */
1057b725ae77Skettenis static int
special_register_p(int regno)1058b725ae77Skettenis special_register_p (int regno)
1059b725ae77Skettenis {
1060b725ae77Skettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
1061b725ae77Skettenis 
1062b725ae77Skettenis   return regno == PC_REGNUM
1063b725ae77Skettenis       || regno == tdep->ppc_ps_regnum
1064b725ae77Skettenis       || regno == tdep->ppc_cr_regnum
1065b725ae77Skettenis       || regno == tdep->ppc_lr_regnum
1066b725ae77Skettenis       || regno == tdep->ppc_ctr_regnum
1067b725ae77Skettenis       || regno == tdep->ppc_xer_regnum
1068*11efff7fSkettenis       || (tdep->ppc_fpscr_regnum >= 0 && regno == tdep->ppc_fpscr_regnum)
1069b725ae77Skettenis       || (tdep->ppc_mq_regnum >= 0 && regno == tdep->ppc_mq_regnum);
1070b725ae77Skettenis }
1071b725ae77Skettenis 
1072b725ae77Skettenis 
1073b725ae77Skettenis /* Record that the special registers contain the specified 64-bit and
1074b725ae77Skettenis    32-bit values.  */
1075b725ae77Skettenis 
1076b725ae77Skettenis static void
supply_sprs64(uint64_t iar,uint64_t msr,uint32_t cr,uint64_t lr,uint64_t ctr,uint32_t xer,uint32_t fpscr)1077b725ae77Skettenis supply_sprs64 (uint64_t iar, uint64_t msr, uint32_t cr,
1078b725ae77Skettenis 	       uint64_t lr, uint64_t ctr, uint32_t xer,
1079b725ae77Skettenis 	       uint32_t fpscr)
1080b725ae77Skettenis {
1081b725ae77Skettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
1082b725ae77Skettenis 
1083*11efff7fSkettenis   regcache_raw_supply (current_regcache, PC_REGNUM, (char *) &iar);
1084*11efff7fSkettenis   regcache_raw_supply (current_regcache, tdep->ppc_ps_regnum, (char *) &msr);
1085*11efff7fSkettenis   regcache_raw_supply (current_regcache, tdep->ppc_cr_regnum, (char *) &cr);
1086*11efff7fSkettenis   regcache_raw_supply (current_regcache, tdep->ppc_lr_regnum, (char *) &lr);
1087*11efff7fSkettenis   regcache_raw_supply (current_regcache, tdep->ppc_ctr_regnum, (char *) &ctr);
1088*11efff7fSkettenis   regcache_raw_supply (current_regcache, tdep->ppc_xer_regnum, (char *) &xer);
1089*11efff7fSkettenis   if (tdep->ppc_fpscr_regnum >= 0)
1090*11efff7fSkettenis     regcache_raw_supply (current_regcache, tdep->ppc_fpscr_regnum,
1091*11efff7fSkettenis 			 (char *) &fpscr);
1092b725ae77Skettenis }
1093b725ae77Skettenis 
1094b725ae77Skettenis /* Record that the special registers contain the specified 32-bit
1095b725ae77Skettenis    values.  */
1096b725ae77Skettenis 
1097b725ae77Skettenis static void
supply_sprs32(uint32_t iar,uint32_t msr,uint32_t cr,uint32_t lr,uint32_t ctr,uint32_t xer,uint32_t fpscr)1098b725ae77Skettenis supply_sprs32 (uint32_t iar, uint32_t msr, uint32_t cr,
1099b725ae77Skettenis 	       uint32_t lr, uint32_t ctr, uint32_t xer,
1100b725ae77Skettenis 	       uint32_t fpscr)
1101b725ae77Skettenis {
1102b725ae77Skettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
1103b725ae77Skettenis 
1104*11efff7fSkettenis   regcache_raw_supply (current_regcache, PC_REGNUM, (char *) &iar);
1105*11efff7fSkettenis   regcache_raw_supply (current_regcache, tdep->ppc_ps_regnum, (char *) &msr);
1106*11efff7fSkettenis   regcache_raw_supply (current_regcache, tdep->ppc_cr_regnum, (char *) &cr);
1107*11efff7fSkettenis   regcache_raw_supply (current_regcache, tdep->ppc_lr_regnum, (char *) &lr);
1108*11efff7fSkettenis   regcache_raw_supply (current_regcache, tdep->ppc_ctr_regnum, (char *) &ctr);
1109*11efff7fSkettenis   regcache_raw_supply (current_regcache, tdep->ppc_xer_regnum, (char *) &xer);
1110*11efff7fSkettenis   if (tdep->ppc_fpscr_regnum >= 0)
1111*11efff7fSkettenis     regcache_raw_supply (current_regcache, tdep->ppc_fpscr_regnum,
1112*11efff7fSkettenis 			 (char *) &fpscr);
1113b725ae77Skettenis }
1114b725ae77Skettenis 
1115b725ae77Skettenis /* Fetch all registers from pthread PDTID, which doesn't have a kernel
1116b725ae77Skettenis    thread.
1117b725ae77Skettenis 
1118b725ae77Skettenis    There's no way to query a single register from a non-kernel
1119b725ae77Skettenis    pthread, so there's no need for a single-register version of this
1120b725ae77Skettenis    function.  */
1121b725ae77Skettenis 
1122b725ae77Skettenis static void
fetch_regs_user_thread(pthdb_pthread_t pdtid)1123b725ae77Skettenis fetch_regs_user_thread (pthdb_pthread_t pdtid)
1124b725ae77Skettenis {
1125*11efff7fSkettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
1126b725ae77Skettenis   int status, i;
1127b725ae77Skettenis   pthdb_context_t ctx;
1128b725ae77Skettenis 
1129b725ae77Skettenis   if (debug_aix_thread)
1130b725ae77Skettenis     fprintf_unfiltered (gdb_stdlog,
1131b725ae77Skettenis 			"fetch_regs_user_thread %lx\n", (long) pdtid);
1132b725ae77Skettenis   status = pthdb_pthread_context (pd_session, pdtid, &ctx);
1133b725ae77Skettenis   if (status != PTHDB_SUCCESS)
1134b725ae77Skettenis     error ("aix-thread: fetch_registers: pthdb_pthread_context returned %s",
1135b725ae77Skettenis            pd_status2str (status));
1136b725ae77Skettenis 
1137b725ae77Skettenis   /* General-purpose registers.  */
1138b725ae77Skettenis 
1139b725ae77Skettenis   if (arch64)
1140b725ae77Skettenis     supply_gprs64 (ctx.gpr);
1141b725ae77Skettenis   else
1142*11efff7fSkettenis     for (i = 0; i < ppc_num_gprs; i++)
1143*11efff7fSkettenis       supply_reg32 (tdep->ppc_gp0_regnum + i, ctx.gpr[i]);
1144b725ae77Skettenis 
1145b725ae77Skettenis   /* Floating-point registers.  */
1146b725ae77Skettenis 
1147*11efff7fSkettenis   if (ppc_floating_point_unit_p (current_gdbarch))
1148b725ae77Skettenis     supply_fprs (ctx.fpr);
1149b725ae77Skettenis 
1150b725ae77Skettenis   /* Special registers.  */
1151b725ae77Skettenis 
1152b725ae77Skettenis   if (arch64)
1153b725ae77Skettenis     supply_sprs64 (ctx.iar, ctx.msr, ctx.cr, ctx.lr, ctx.ctr, ctx.xer,
1154b725ae77Skettenis                    ctx.fpscr);
1155b725ae77Skettenis   else
1156b725ae77Skettenis     supply_sprs32 (ctx.iar, ctx.msr, ctx.cr, ctx.lr, ctx.ctr, ctx.xer,
1157b725ae77Skettenis                    ctx.fpscr);
1158b725ae77Skettenis }
1159b725ae77Skettenis 
1160b725ae77Skettenis /* Fetch register REGNO if != -1 or all registers otherwise from
1161b725ae77Skettenis    kernel thread TID.
1162b725ae77Skettenis 
1163b725ae77Skettenis    AIX provides a way to query all of a kernel thread's GPRs, FPRs, or
1164b725ae77Skettenis    SPRs, but there's no way to query individual registers within those
1165b725ae77Skettenis    groups.  Therefore, if REGNO != -1, this function fetches an entire
1166b725ae77Skettenis    group.
1167b725ae77Skettenis 
1168b725ae77Skettenis    Unfortunately, kernel thread register queries often fail with
1169b725ae77Skettenis    EPERM, indicating that the thread is in kernel space.  This breaks
1170b725ae77Skettenis    backtraces of threads other than the current one.  To make that
1171b725ae77Skettenis    breakage obvious without throwing an error to top level (which is
1172b725ae77Skettenis    bad e.g. during "info threads" output), zero registers that can't
1173b725ae77Skettenis    be retrieved.  */
1174b725ae77Skettenis 
1175b725ae77Skettenis static void
fetch_regs_kernel_thread(int regno,pthdb_tid_t tid)1176b725ae77Skettenis fetch_regs_kernel_thread (int regno, pthdb_tid_t tid)
1177b725ae77Skettenis {
1178*11efff7fSkettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
1179*11efff7fSkettenis   uint64_t gprs64[ppc_num_gprs];
1180*11efff7fSkettenis   uint32_t gprs32[ppc_num_gprs];
1181*11efff7fSkettenis   double fprs[ppc_num_fprs];
1182b725ae77Skettenis   struct ptxsprs sprs64;
1183b725ae77Skettenis   struct ptsprs sprs32;
1184b725ae77Skettenis   int i;
1185b725ae77Skettenis 
1186b725ae77Skettenis   if (debug_aix_thread)
1187b725ae77Skettenis     fprintf_unfiltered (gdb_stdlog,
1188b725ae77Skettenis 	"fetch_regs_kernel_thread tid=%lx regno=%d arch64=%d\n",
1189b725ae77Skettenis 	(long) tid, regno, arch64);
1190b725ae77Skettenis 
1191b725ae77Skettenis   /* General-purpose registers.  */
1192*11efff7fSkettenis   if (regno == -1
1193*11efff7fSkettenis       || (tdep->ppc_gp0_regnum <= regno
1194*11efff7fSkettenis           && regno < tdep->ppc_gp0_regnum + ppc_num_gprs))
1195b725ae77Skettenis     {
1196b725ae77Skettenis       if (arch64)
1197b725ae77Skettenis 	{
1198b725ae77Skettenis 	  if (!ptrace64aix (PTT_READ_GPRS, tid,
1199b725ae77Skettenis 			    (unsigned long) gprs64, 0, NULL))
1200b725ae77Skettenis 	    memset (gprs64, 0, sizeof (gprs64));
1201b725ae77Skettenis 	  supply_gprs64 (gprs64);
1202b725ae77Skettenis 	}
1203b725ae77Skettenis       else
1204b725ae77Skettenis 	{
1205b725ae77Skettenis 	  if (!ptrace32 (PTT_READ_GPRS, tid, gprs32, 0, NULL))
1206b725ae77Skettenis 	    memset (gprs32, 0, sizeof (gprs32));
1207*11efff7fSkettenis 	  for (i = 0; i < ppc_num_gprs; i++)
1208*11efff7fSkettenis 	    supply_reg32 (tdep->ppc_gp0_regnum + i, gprs32[i]);
1209b725ae77Skettenis 	}
1210b725ae77Skettenis     }
1211b725ae77Skettenis 
1212b725ae77Skettenis   /* Floating-point registers.  */
1213b725ae77Skettenis 
1214*11efff7fSkettenis   if (ppc_floating_point_unit_p (current_gdbarch)
1215*11efff7fSkettenis       && (regno == -1
1216*11efff7fSkettenis           || (regno >= tdep->ppc_fp0_regnum
1217*11efff7fSkettenis               && regno < tdep->ppc_fp0_regnum + ppc_num_fprs)))
1218b725ae77Skettenis     {
1219b725ae77Skettenis       if (!ptrace32 (PTT_READ_FPRS, tid, (int *) fprs, 0, NULL))
1220b725ae77Skettenis 	memset (fprs, 0, sizeof (fprs));
1221b725ae77Skettenis       supply_fprs (fprs);
1222b725ae77Skettenis     }
1223b725ae77Skettenis 
1224b725ae77Skettenis   /* Special-purpose registers.  */
1225b725ae77Skettenis 
1226b725ae77Skettenis   if (regno == -1 || special_register_p (regno))
1227b725ae77Skettenis     {
1228b725ae77Skettenis       if (arch64)
1229b725ae77Skettenis 	{
1230b725ae77Skettenis 	  if (!ptrace64aix (PTT_READ_SPRS, tid,
1231b725ae77Skettenis 			    (unsigned long) &sprs64, 0, NULL))
1232b725ae77Skettenis 	    memset (&sprs64, 0, sizeof (sprs64));
1233b725ae77Skettenis 	  supply_sprs64 (sprs64.pt_iar, sprs64.pt_msr, sprs64.pt_cr,
1234b725ae77Skettenis 			 sprs64.pt_lr, sprs64.pt_ctr, sprs64.pt_xer,
1235b725ae77Skettenis 			 sprs64.pt_fpscr);
1236b725ae77Skettenis 	}
1237b725ae77Skettenis       else
1238b725ae77Skettenis 	{
1239b725ae77Skettenis 	  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
1240b725ae77Skettenis 
1241b725ae77Skettenis 	  if (!ptrace32 (PTT_READ_SPRS, tid, (int *) &sprs32, 0, NULL))
1242b725ae77Skettenis 	    memset (&sprs32, 0, sizeof (sprs32));
1243b725ae77Skettenis 	  supply_sprs32 (sprs32.pt_iar, sprs32.pt_msr, sprs32.pt_cr,
1244b725ae77Skettenis 			 sprs32.pt_lr, sprs32.pt_ctr, sprs32.pt_xer,
1245b725ae77Skettenis 			 sprs32.pt_fpscr);
1246b725ae77Skettenis 
1247b725ae77Skettenis 	  if (tdep->ppc_mq_regnum >= 0)
1248*11efff7fSkettenis 	    regcache_raw_supply (current_regcache, tdep->ppc_mq_regnum,
1249*11efff7fSkettenis 				 (char *) &sprs32.pt_mq);
1250b725ae77Skettenis 	}
1251b725ae77Skettenis     }
1252b725ae77Skettenis }
1253b725ae77Skettenis 
1254b725ae77Skettenis /* Fetch register REGNO if != -1 or all registers otherwise in the
1255b725ae77Skettenis    thread/process specified by inferior_ptid.  */
1256b725ae77Skettenis 
1257b725ae77Skettenis static void
aix_thread_fetch_registers(int regno)1258b725ae77Skettenis aix_thread_fetch_registers (int regno)
1259b725ae77Skettenis {
1260b725ae77Skettenis   struct thread_info *thread;
1261b725ae77Skettenis   pthdb_tid_t tid;
1262b725ae77Skettenis 
1263b725ae77Skettenis   if (!PD_TID (inferior_ptid))
1264b725ae77Skettenis     base_target.to_fetch_registers (regno);
1265b725ae77Skettenis   else
1266b725ae77Skettenis     {
1267b725ae77Skettenis       thread = find_thread_pid (inferior_ptid);
1268b725ae77Skettenis       tid = thread->private->tid;
1269b725ae77Skettenis 
1270b725ae77Skettenis       if (tid == PTHDB_INVALID_TID)
1271b725ae77Skettenis 	fetch_regs_user_thread (thread->private->pdtid);
1272b725ae77Skettenis       else
1273b725ae77Skettenis 	fetch_regs_kernel_thread (regno, tid);
1274b725ae77Skettenis     }
1275b725ae77Skettenis }
1276b725ae77Skettenis 
1277b725ae77Skettenis /* Store the gp registers into an array of uint32_t or uint64_t.  */
1278b725ae77Skettenis 
1279b725ae77Skettenis static void
fill_gprs64(uint64_t * vals)1280b725ae77Skettenis fill_gprs64 (uint64_t *vals)
1281b725ae77Skettenis {
1282*11efff7fSkettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
1283b725ae77Skettenis   int regno;
1284b725ae77Skettenis 
1285*11efff7fSkettenis   for (regno = 0; regno < ppc_num_gprs; regno++)
1286*11efff7fSkettenis     if (register_cached (tdep->ppc_gp0_regnum + regno))
1287*11efff7fSkettenis       regcache_raw_collect (current_regcache, tdep->ppc_gp0_regnum + regno,
1288*11efff7fSkettenis 			    vals + regno);
1289b725ae77Skettenis }
1290b725ae77Skettenis 
1291b725ae77Skettenis static void
fill_gprs32(uint32_t * vals)1292b725ae77Skettenis fill_gprs32 (uint32_t *vals)
1293b725ae77Skettenis {
1294*11efff7fSkettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
1295b725ae77Skettenis   int regno;
1296b725ae77Skettenis 
1297*11efff7fSkettenis   for (regno = 0; regno < ppc_num_gprs; regno++)
1298*11efff7fSkettenis     if (register_cached (tdep->ppc_gp0_regnum + regno))
1299*11efff7fSkettenis       regcache_raw_collect (current_regcache, tdep->ppc_gp0_regnum + regno,
1300*11efff7fSkettenis 			    vals + regno);
1301b725ae77Skettenis }
1302b725ae77Skettenis 
1303b725ae77Skettenis /* Store the floating point registers into a double array.  */
1304b725ae77Skettenis static void
fill_fprs(double * vals)1305b725ae77Skettenis fill_fprs (double *vals)
1306b725ae77Skettenis {
1307*11efff7fSkettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
1308b725ae77Skettenis   int regno;
1309b725ae77Skettenis 
1310*11efff7fSkettenis   /* This function should never be called on architectures without
1311*11efff7fSkettenis      floating-point registers.  */
1312*11efff7fSkettenis   gdb_assert (ppc_floating_point_unit_p (current_gdbarch));
1313*11efff7fSkettenis 
1314*11efff7fSkettenis   for (regno = tdep->ppc_fp0_regnum;
1315*11efff7fSkettenis        regno < tdep->ppc_fp0_regnum + ppc_num_fprs;
1316*11efff7fSkettenis        regno++)
1317b725ae77Skettenis     if (register_cached (regno))
1318*11efff7fSkettenis       regcache_raw_collect (current_regcache, regno, vals + regno);
1319b725ae77Skettenis }
1320b725ae77Skettenis 
1321b725ae77Skettenis /* Store the special registers into the specified 64-bit and 32-bit
1322b725ae77Skettenis    locations.  */
1323b725ae77Skettenis 
1324b725ae77Skettenis static void
fill_sprs64(uint64_t * iar,uint64_t * msr,uint32_t * cr,uint64_t * lr,uint64_t * ctr,uint32_t * xer,uint32_t * fpscr)1325b725ae77Skettenis fill_sprs64 (uint64_t *iar, uint64_t *msr, uint32_t *cr,
1326b725ae77Skettenis 	     uint64_t *lr, uint64_t *ctr, uint32_t *xer,
1327b725ae77Skettenis 	     uint32_t *fpscr)
1328b725ae77Skettenis {
1329b725ae77Skettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
1330b725ae77Skettenis 
1331b725ae77Skettenis   /* Verify that the size of the size of the IAR buffer is the
1332b725ae77Skettenis      same as the raw size of the PC (in the register cache).  If
1333b725ae77Skettenis      they're not, then either GDB has been built incorrectly, or
1334b725ae77Skettenis      there's some other kind of internal error.  To be really safe,
1335b725ae77Skettenis      we should check all of the sizes.   */
1336*11efff7fSkettenis   gdb_assert (sizeof (*iar) == register_size (current_gdbarch, PC_REGNUM));
1337b725ae77Skettenis 
1338b725ae77Skettenis   if (register_cached (PC_REGNUM))
1339*11efff7fSkettenis     regcache_raw_collect (current_regcache, PC_REGNUM, iar);
1340b725ae77Skettenis   if (register_cached (tdep->ppc_ps_regnum))
1341*11efff7fSkettenis     regcache_raw_collect (current_regcache, tdep->ppc_ps_regnum, msr);
1342b725ae77Skettenis   if (register_cached (tdep->ppc_cr_regnum))
1343*11efff7fSkettenis     regcache_raw_collect (current_regcache, tdep->ppc_cr_regnum, cr);
1344b725ae77Skettenis   if (register_cached (tdep->ppc_lr_regnum))
1345*11efff7fSkettenis     regcache_raw_collect (current_regcache, tdep->ppc_lr_regnum, lr);
1346b725ae77Skettenis   if (register_cached (tdep->ppc_ctr_regnum))
1347*11efff7fSkettenis     regcache_raw_collect (current_regcache, tdep->ppc_ctr_regnum, ctr);
1348b725ae77Skettenis   if (register_cached (tdep->ppc_xer_regnum))
1349*11efff7fSkettenis     regcache_raw_collect (current_regcache, tdep->ppc_xer_regnum, xer);
1350*11efff7fSkettenis   if (tdep->ppc_fpscr_regnum >= 0
1351*11efff7fSkettenis       && register_cached (tdep->ppc_fpscr_regnum))
1352*11efff7fSkettenis     regcache_raw_collect (current_regcache, tdep->ppc_fpscr_regnum, fpscr);
1353b725ae77Skettenis }
1354b725ae77Skettenis 
1355b725ae77Skettenis static void
fill_sprs32(unsigned long * iar,unsigned long * msr,unsigned long * cr,unsigned long * lr,unsigned long * ctr,unsigned long * xer,unsigned long * fpscr)1356b725ae77Skettenis fill_sprs32 (unsigned long *iar, unsigned long *msr, unsigned long *cr,
1357b725ae77Skettenis 	     unsigned long *lr,  unsigned long *ctr, unsigned long *xer,
1358b725ae77Skettenis 	     unsigned long *fpscr)
1359b725ae77Skettenis {
1360b725ae77Skettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
1361b725ae77Skettenis 
1362b725ae77Skettenis   /* Verify that the size of the size of the IAR buffer is the
1363b725ae77Skettenis      same as the raw size of the PC (in the register cache).  If
1364b725ae77Skettenis      they're not, then either GDB has been built incorrectly, or
1365b725ae77Skettenis      there's some other kind of internal error.  To be really safe,
1366b725ae77Skettenis      we should check all of the sizes.
1367b725ae77Skettenis 
1368b725ae77Skettenis      If this assert() fails, the most likely reason is that GDB was
1369b725ae77Skettenis      built incorrectly.  In order to make use of many of the header
1370b725ae77Skettenis      files in /usr/include/sys, GDB needs to be configured so that
1371b725ae77Skettenis      sizeof (long) == 4).  */
1372*11efff7fSkettenis   gdb_assert (sizeof (*iar) == register_size (current_gdbarch, PC_REGNUM));
1373b725ae77Skettenis 
1374b725ae77Skettenis   if (register_cached (PC_REGNUM))
1375*11efff7fSkettenis     regcache_raw_collect (current_regcache, PC_REGNUM, iar);
1376b725ae77Skettenis   if (register_cached (tdep->ppc_ps_regnum))
1377*11efff7fSkettenis     regcache_raw_collect (current_regcache, tdep->ppc_ps_regnum, msr);
1378b725ae77Skettenis   if (register_cached (tdep->ppc_cr_regnum))
1379*11efff7fSkettenis     regcache_raw_collect (current_regcache, tdep->ppc_cr_regnum, cr);
1380b725ae77Skettenis   if (register_cached (tdep->ppc_lr_regnum))
1381*11efff7fSkettenis     regcache_raw_collect (current_regcache, tdep->ppc_lr_regnum, lr);
1382b725ae77Skettenis   if (register_cached (tdep->ppc_ctr_regnum))
1383*11efff7fSkettenis     regcache_raw_collect (current_regcache, tdep->ppc_ctr_regnum, ctr);
1384b725ae77Skettenis   if (register_cached (tdep->ppc_xer_regnum))
1385*11efff7fSkettenis     regcache_raw_collect (current_regcache, tdep->ppc_xer_regnum, xer);
1386*11efff7fSkettenis   if (tdep->ppc_fpscr_regnum >= 0
1387*11efff7fSkettenis       && register_cached (tdep->ppc_fpscr_regnum))
1388*11efff7fSkettenis     regcache_raw_collect (current_regcache, tdep->ppc_fpscr_regnum, fpscr);
1389b725ae77Skettenis }
1390b725ae77Skettenis 
1391b725ae77Skettenis /* Store all registers into pthread PDTID, which doesn't have a kernel
1392b725ae77Skettenis    thread.
1393b725ae77Skettenis 
1394b725ae77Skettenis    It's possible to store a single register into a non-kernel pthread,
1395b725ae77Skettenis    but I doubt it's worth the effort.  */
1396b725ae77Skettenis 
1397b725ae77Skettenis static void
store_regs_user_thread(pthdb_pthread_t pdtid)1398b725ae77Skettenis store_regs_user_thread (pthdb_pthread_t pdtid)
1399b725ae77Skettenis {
1400*11efff7fSkettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
1401b725ae77Skettenis   int status, i;
1402b725ae77Skettenis   pthdb_context_t ctx;
1403b725ae77Skettenis   uint32_t int32;
1404b725ae77Skettenis   uint64_t int64;
1405b725ae77Skettenis   double   dbl;
1406b725ae77Skettenis 
1407b725ae77Skettenis   if (debug_aix_thread)
1408b725ae77Skettenis     fprintf_unfiltered (gdb_stdlog,
1409b725ae77Skettenis 			"store_regs_user_thread %lx\n", (long) pdtid);
1410b725ae77Skettenis 
1411b725ae77Skettenis   /* Retrieve the thread's current context for its non-register
1412b725ae77Skettenis      values.  */
1413b725ae77Skettenis   status = pthdb_pthread_context (pd_session, pdtid, &ctx);
1414b725ae77Skettenis   if (status != PTHDB_SUCCESS)
1415b725ae77Skettenis     error ("aix-thread: store_registers: pthdb_pthread_context returned %s",
1416b725ae77Skettenis            pd_status2str (status));
1417b725ae77Skettenis 
1418b725ae77Skettenis   /* Collect general-purpose register values from the regcache.  */
1419b725ae77Skettenis 
1420*11efff7fSkettenis   for (i = 0; i < ppc_num_gprs; i++)
1421*11efff7fSkettenis     if (register_cached (tdep->ppc_gp0_regnum + i))
1422b725ae77Skettenis       {
1423b725ae77Skettenis 	if (arch64)
1424b725ae77Skettenis 	  {
1425*11efff7fSkettenis 	    regcache_raw_collect (current_regcache, tdep->ppc_gp0_regnum + i,
1426*11efff7fSkettenis 				  (void *) &int64);
1427b725ae77Skettenis 	    ctx.gpr[i] = int64;
1428b725ae77Skettenis 	  }
1429b725ae77Skettenis 	else
1430b725ae77Skettenis 	  {
1431*11efff7fSkettenis 	    regcache_raw_collect (current_regcache, tdep->ppc_gp0_regnum + i,
1432*11efff7fSkettenis 				  (void *) &int32);
1433b725ae77Skettenis 	    ctx.gpr[i] = int32;
1434b725ae77Skettenis 	  }
1435b725ae77Skettenis       }
1436b725ae77Skettenis 
1437b725ae77Skettenis   /* Collect floating-point register values from the regcache.  */
1438*11efff7fSkettenis   if (ppc_floating_point_unit_p (current_gdbarch))
1439b725ae77Skettenis     fill_fprs (ctx.fpr);
1440b725ae77Skettenis 
1441b725ae77Skettenis   /* Special registers (always kept in ctx as 64 bits).  */
1442b725ae77Skettenis   if (arch64)
1443b725ae77Skettenis     {
1444b725ae77Skettenis       fill_sprs64 (&ctx.iar, &ctx.msr, &ctx.cr, &ctx.lr, &ctx.ctr, &ctx.xer,
1445b725ae77Skettenis                    &ctx.fpscr);
1446b725ae77Skettenis     }
1447b725ae77Skettenis   else
1448b725ae77Skettenis     {
1449b725ae77Skettenis       /* Problem: ctx.iar etc. are 64 bits, but raw_registers are 32.
1450b725ae77Skettenis 	 Solution: use 32-bit temp variables.  (The assert() in fill_sprs32()
1451b725ae77Skettenis 	 will fail if the size of an unsigned long is incorrect.  If this
1452b725ae77Skettenis 	 happens, GDB needs to be reconfigured so that longs are 32-bits.)  */
1453b725ae77Skettenis       unsigned long tmp_iar, tmp_msr, tmp_cr, tmp_lr, tmp_ctr, tmp_xer,
1454b725ae77Skettenis                     tmp_fpscr;
1455b725ae77Skettenis 
1456b725ae77Skettenis       fill_sprs32 (&tmp_iar, &tmp_msr, &tmp_cr, &tmp_lr, &tmp_ctr, &tmp_xer,
1457b725ae77Skettenis                    &tmp_fpscr);
1458b725ae77Skettenis       if (register_cached (PC_REGNUM))
1459b725ae77Skettenis 	ctx.iar = tmp_iar;
1460b725ae77Skettenis       if (register_cached (tdep->ppc_ps_regnum))
1461b725ae77Skettenis 	ctx.msr = tmp_msr;
1462b725ae77Skettenis       if (register_cached (tdep->ppc_cr_regnum))
1463b725ae77Skettenis 	ctx.cr  = tmp_cr;
1464b725ae77Skettenis       if (register_cached (tdep->ppc_lr_regnum))
1465b725ae77Skettenis 	ctx.lr  = tmp_lr;
1466b725ae77Skettenis       if (register_cached (tdep->ppc_ctr_regnum))
1467b725ae77Skettenis 	ctx.ctr = tmp_ctr;
1468b725ae77Skettenis       if (register_cached (tdep->ppc_xer_regnum))
1469b725ae77Skettenis 	ctx.xer = tmp_xer;
1470b725ae77Skettenis       if (register_cached (tdep->ppc_xer_regnum))
1471b725ae77Skettenis 	ctx.fpscr = tmp_fpscr;
1472b725ae77Skettenis     }
1473b725ae77Skettenis 
1474b725ae77Skettenis   status = pthdb_pthread_setcontext (pd_session, pdtid, &ctx);
1475b725ae77Skettenis   if (status != PTHDB_SUCCESS)
1476b725ae77Skettenis     error ("aix-thread: store_registers: pthdb_pthread_setcontext returned %s",
1477b725ae77Skettenis            pd_status2str (status));
1478b725ae77Skettenis }
1479b725ae77Skettenis 
1480b725ae77Skettenis /* Store register REGNO if != -1 or all registers otherwise into
1481b725ae77Skettenis    kernel thread TID.
1482b725ae77Skettenis 
1483b725ae77Skettenis    AIX provides a way to set all of a kernel thread's GPRs, FPRs, or
1484b725ae77Skettenis    SPRs, but there's no way to set individual registers within those
1485b725ae77Skettenis    groups.  Therefore, if REGNO != -1, this function stores an entire
1486b725ae77Skettenis    group.  */
1487b725ae77Skettenis 
1488b725ae77Skettenis static void
store_regs_kernel_thread(int regno,pthdb_tid_t tid)1489b725ae77Skettenis store_regs_kernel_thread (int regno, pthdb_tid_t tid)
1490b725ae77Skettenis {
1491*11efff7fSkettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
1492*11efff7fSkettenis   uint64_t gprs64[ppc_num_gprs];
1493*11efff7fSkettenis   uint32_t gprs32[ppc_num_gprs];
1494*11efff7fSkettenis   double fprs[ppc_num_fprs];
1495b725ae77Skettenis   struct ptxsprs sprs64;
1496b725ae77Skettenis   struct ptsprs  sprs32;
1497b725ae77Skettenis   int i;
1498b725ae77Skettenis 
1499b725ae77Skettenis   if (debug_aix_thread)
1500b725ae77Skettenis     fprintf_unfiltered (gdb_stdlog,
1501b725ae77Skettenis 			"store_regs_kernel_thread tid=%lx regno=%d\n",
1502b725ae77Skettenis                         (long) tid, regno);
1503b725ae77Skettenis 
1504b725ae77Skettenis   /* General-purpose registers.  */
1505*11efff7fSkettenis   if (regno == -1
1506*11efff7fSkettenis       || (tdep->ppc_gp0_regnum <= regno
1507*11efff7fSkettenis           && regno < tdep->ppc_gp0_regnum + ppc_num_fprs))
1508b725ae77Skettenis     {
1509b725ae77Skettenis       if (arch64)
1510b725ae77Skettenis 	{
1511b725ae77Skettenis 	  /* Pre-fetch: some regs may not be in the cache.  */
1512b725ae77Skettenis 	  ptrace64aix (PTT_READ_GPRS, tid, (unsigned long) gprs64, 0, NULL);
1513b725ae77Skettenis 	  fill_gprs64 (gprs64);
1514b725ae77Skettenis 	  ptrace64aix (PTT_WRITE_GPRS, tid, (unsigned long) gprs64, 0, NULL);
1515b725ae77Skettenis 	}
1516b725ae77Skettenis       else
1517b725ae77Skettenis 	{
1518b725ae77Skettenis 	  /* Pre-fetch: some regs may not be in the cache.  */
1519b725ae77Skettenis 	  ptrace32 (PTT_READ_GPRS, tid, gprs32, 0, NULL);
1520b725ae77Skettenis 	  fill_gprs32 (gprs32);
1521b725ae77Skettenis 	  ptrace32 (PTT_WRITE_GPRS, tid, gprs32, 0, NULL);
1522b725ae77Skettenis 	}
1523b725ae77Skettenis     }
1524b725ae77Skettenis 
1525b725ae77Skettenis   /* Floating-point registers.  */
1526b725ae77Skettenis 
1527*11efff7fSkettenis   if (ppc_floating_point_unit_p (current_gdbarch)
1528*11efff7fSkettenis       && (regno == -1
1529*11efff7fSkettenis           || (regno >= tdep->ppc_fp0_regnum
1530*11efff7fSkettenis               && regno < tdep->ppc_fp0_regnum + ppc_num_fprs)))
1531b725ae77Skettenis     {
1532b725ae77Skettenis       /* Pre-fetch: some regs may not be in the cache.  */
1533b725ae77Skettenis       ptrace32 (PTT_READ_FPRS, tid, (int *) fprs, 0, NULL);
1534b725ae77Skettenis       fill_fprs (fprs);
1535b725ae77Skettenis       ptrace32 (PTT_WRITE_FPRS, tid, (int *) fprs, 0, NULL);
1536b725ae77Skettenis     }
1537b725ae77Skettenis 
1538b725ae77Skettenis   /* Special-purpose registers.  */
1539b725ae77Skettenis 
1540b725ae77Skettenis   if (regno == -1 || special_register_p (regno))
1541b725ae77Skettenis     {
1542b725ae77Skettenis       if (arch64)
1543b725ae77Skettenis 	{
1544b725ae77Skettenis 	  /* Pre-fetch: some registers won't be in the cache.  */
1545b725ae77Skettenis 	  ptrace64aix (PTT_READ_SPRS, tid,
1546b725ae77Skettenis 		       (unsigned long) &sprs64, 0, NULL);
1547b725ae77Skettenis 	  fill_sprs64 (&sprs64.pt_iar, &sprs64.pt_msr, &sprs64.pt_cr,
1548b725ae77Skettenis 		       &sprs64.pt_lr,  &sprs64.pt_ctr, &sprs64.pt_xer,
1549b725ae77Skettenis 		       &sprs64.pt_fpscr);
1550b725ae77Skettenis 	  ptrace64aix (PTT_WRITE_SPRS, tid,
1551b725ae77Skettenis 		       (unsigned long) &sprs64, 0, NULL);
1552b725ae77Skettenis 	}
1553b725ae77Skettenis       else
1554b725ae77Skettenis 	{
1555b725ae77Skettenis 	  /* Pre-fetch: some registers won't be in the cache.  */
1556b725ae77Skettenis 	  ptrace32 (PTT_READ_SPRS, tid, (int *) &sprs32, 0, NULL);
1557b725ae77Skettenis 
1558b725ae77Skettenis 	  fill_sprs32 (&sprs32.pt_iar, &sprs32.pt_msr, &sprs32.pt_cr,
1559b725ae77Skettenis 		       &sprs32.pt_lr,  &sprs32.pt_ctr, &sprs32.pt_xer,
1560b725ae77Skettenis 		       &sprs32.pt_fpscr);
1561b725ae77Skettenis 
1562b725ae77Skettenis 	  if (tdep->ppc_mq_regnum >= 0)
1563b725ae77Skettenis 	    if (register_cached (tdep->ppc_mq_regnum))
1564*11efff7fSkettenis 	      regcache_raw_collect (current_regcache, tdep->ppc_mq_regnum,
1565*11efff7fSkettenis 				    &sprs32.pt_mq);
1566b725ae77Skettenis 
1567b725ae77Skettenis 	  ptrace32 (PTT_WRITE_SPRS, tid, (int *) &sprs32, 0, NULL);
1568b725ae77Skettenis 	}
1569b725ae77Skettenis     }
1570b725ae77Skettenis }
1571b725ae77Skettenis 
1572b725ae77Skettenis /* Store gdb's current view of the register set into the
1573b725ae77Skettenis    thread/process specified by inferior_ptid.  */
1574b725ae77Skettenis 
1575b725ae77Skettenis static void
aix_thread_store_registers(int regno)1576b725ae77Skettenis aix_thread_store_registers (int regno)
1577b725ae77Skettenis {
1578b725ae77Skettenis   struct thread_info *thread;
1579b725ae77Skettenis   pthdb_tid_t tid;
1580b725ae77Skettenis 
1581b725ae77Skettenis   if (!PD_TID (inferior_ptid))
1582b725ae77Skettenis     base_target.to_store_registers (regno);
1583b725ae77Skettenis   else
1584b725ae77Skettenis     {
1585b725ae77Skettenis       thread = find_thread_pid (inferior_ptid);
1586b725ae77Skettenis       tid = thread->private->tid;
1587b725ae77Skettenis 
1588b725ae77Skettenis       if (tid == PTHDB_INVALID_TID)
1589b725ae77Skettenis 	store_regs_user_thread (thread->private->pdtid);
1590b725ae77Skettenis       else
1591b725ae77Skettenis 	store_regs_kernel_thread (regno, tid);
1592b725ae77Skettenis     }
1593b725ae77Skettenis }
1594b725ae77Skettenis 
1595b725ae77Skettenis /* Transfer LEN bytes of memory from GDB address MYADDR to target
1596b725ae77Skettenis    address MEMADDR if WRITE and vice versa otherwise.  */
1597b725ae77Skettenis 
1598b725ae77Skettenis static int
aix_thread_xfer_memory(CORE_ADDR memaddr,char * myaddr,int len,int write,struct mem_attrib * attrib,struct target_ops * target)1599b725ae77Skettenis aix_thread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
1600b725ae77Skettenis 		      struct mem_attrib *attrib,
1601b725ae77Skettenis 		      struct target_ops *target)
1602b725ae77Skettenis {
1603b725ae77Skettenis   int n;
1604b725ae77Skettenis   struct cleanup *cleanup = save_inferior_ptid ();
1605b725ae77Skettenis 
1606b725ae77Skettenis   inferior_ptid = pid_to_ptid (PIDGET (inferior_ptid));
1607*11efff7fSkettenis   n = base_target.deprecated_xfer_memory (memaddr, myaddr, len,
1608b725ae77Skettenis 					  write, attrib, &base_target);
1609b725ae77Skettenis   do_cleanups (cleanup);
1610b725ae77Skettenis 
1611b725ae77Skettenis   return n;
1612b725ae77Skettenis }
1613b725ae77Skettenis 
1614b725ae77Skettenis /* Kill and forget about the inferior process.  */
1615b725ae77Skettenis 
1616b725ae77Skettenis static void
aix_thread_kill(void)1617b725ae77Skettenis aix_thread_kill (void)
1618b725ae77Skettenis {
1619b725ae77Skettenis   struct cleanup *cleanup = save_inferior_ptid ();
1620b725ae77Skettenis 
1621b725ae77Skettenis   inferior_ptid = pid_to_ptid (PIDGET (inferior_ptid));
1622b725ae77Skettenis   base_target.to_kill ();
1623b725ae77Skettenis   do_cleanups (cleanup);
1624b725ae77Skettenis }
1625b725ae77Skettenis 
1626b725ae77Skettenis /* Clean up after the inferior exits.  */
1627b725ae77Skettenis 
1628b725ae77Skettenis static void
aix_thread_mourn_inferior(void)1629b725ae77Skettenis aix_thread_mourn_inferior (void)
1630b725ae77Skettenis {
1631b725ae77Skettenis   pd_deactivate ();
1632b725ae77Skettenis   base_target.to_mourn_inferior ();
1633b725ae77Skettenis }
1634b725ae77Skettenis 
1635b725ae77Skettenis /* Return whether thread PID is still valid.  */
1636b725ae77Skettenis 
1637b725ae77Skettenis static int
aix_thread_thread_alive(ptid_t ptid)1638b725ae77Skettenis aix_thread_thread_alive (ptid_t ptid)
1639b725ae77Skettenis {
1640b725ae77Skettenis   if (!PD_TID (ptid))
1641b725ae77Skettenis     return base_target.to_thread_alive (ptid);
1642b725ae77Skettenis 
1643b725ae77Skettenis   /* We update the thread list every time the child stops, so all
1644b725ae77Skettenis      valid threads should be in the thread list.  */
1645b725ae77Skettenis   return in_thread_list (ptid);
1646b725ae77Skettenis }
1647b725ae77Skettenis 
1648b725ae77Skettenis /* Return a printable representation of composite PID for use in
1649b725ae77Skettenis    "info threads" output.  */
1650b725ae77Skettenis 
1651b725ae77Skettenis static char *
aix_thread_pid_to_str(ptid_t ptid)1652b725ae77Skettenis aix_thread_pid_to_str (ptid_t ptid)
1653b725ae77Skettenis {
1654b725ae77Skettenis   static char *ret = NULL;
1655b725ae77Skettenis 
1656b725ae77Skettenis   if (!PD_TID (ptid))
1657b725ae77Skettenis     return base_target.to_pid_to_str (ptid);
1658b725ae77Skettenis 
1659b725ae77Skettenis   /* Free previous return value; a new one will be allocated by
1660*11efff7fSkettenis      xstrprintf().  */
1661b725ae77Skettenis   xfree (ret);
1662b725ae77Skettenis 
1663*11efff7fSkettenis   ret = xstrprintf ("Thread %ld", ptid_get_tid (ptid));
1664b725ae77Skettenis   return ret;
1665b725ae77Skettenis }
1666b725ae77Skettenis 
1667b725ae77Skettenis /* Return a printable representation of extra information about
1668b725ae77Skettenis    THREAD, for use in "info threads" output.  */
1669b725ae77Skettenis 
1670b725ae77Skettenis static char *
aix_thread_extra_thread_info(struct thread_info * thread)1671b725ae77Skettenis aix_thread_extra_thread_info (struct thread_info *thread)
1672b725ae77Skettenis {
1673b725ae77Skettenis   struct ui_file *buf;
1674b725ae77Skettenis   int status;
1675b725ae77Skettenis   pthdb_pthread_t pdtid;
1676b725ae77Skettenis   pthdb_tid_t tid;
1677b725ae77Skettenis   pthdb_state_t state;
1678b725ae77Skettenis   pthdb_suspendstate_t suspendstate;
1679b725ae77Skettenis   pthdb_detachstate_t detachstate;
1680b725ae77Skettenis   int cancelpend;
1681b725ae77Skettenis   long length;
1682b725ae77Skettenis   static char *ret = NULL;
1683b725ae77Skettenis 
1684b725ae77Skettenis   if (!PD_TID (thread->ptid))
1685b725ae77Skettenis     return NULL;
1686b725ae77Skettenis 
1687b725ae77Skettenis   buf = mem_fileopen ();
1688b725ae77Skettenis 
1689b725ae77Skettenis   pdtid = thread->private->pdtid;
1690b725ae77Skettenis   tid = thread->private->tid;
1691b725ae77Skettenis 
1692b725ae77Skettenis   if (tid != PTHDB_INVALID_TID)
1693b725ae77Skettenis     fprintf_unfiltered (buf, "tid %d", tid);
1694b725ae77Skettenis 
1695b725ae77Skettenis   status = pthdb_pthread_state (pd_session, pdtid, &state);
1696b725ae77Skettenis   if (status != PTHDB_SUCCESS)
1697b725ae77Skettenis     state = PST_NOTSUP;
1698b725ae77Skettenis   fprintf_unfiltered (buf, ", %s", state2str (state));
1699b725ae77Skettenis 
1700b725ae77Skettenis   status = pthdb_pthread_suspendstate (pd_session, pdtid,
1701b725ae77Skettenis 				       &suspendstate);
1702b725ae77Skettenis   if (status == PTHDB_SUCCESS && suspendstate == PSS_SUSPENDED)
1703b725ae77Skettenis     fprintf_unfiltered (buf, ", suspended");
1704b725ae77Skettenis 
1705b725ae77Skettenis   status = pthdb_pthread_detachstate (pd_session, pdtid,
1706b725ae77Skettenis 				      &detachstate);
1707b725ae77Skettenis   if (status == PTHDB_SUCCESS && detachstate == PDS_DETACHED)
1708b725ae77Skettenis     fprintf_unfiltered (buf, ", detached");
1709b725ae77Skettenis 
1710b725ae77Skettenis   pthdb_pthread_cancelpend (pd_session, pdtid, &cancelpend);
1711b725ae77Skettenis   if (status == PTHDB_SUCCESS && cancelpend)
1712b725ae77Skettenis     fprintf_unfiltered (buf, ", cancel pending");
1713b725ae77Skettenis 
1714b725ae77Skettenis   ui_file_write (buf, "", 1);
1715b725ae77Skettenis 
1716b725ae77Skettenis   xfree (ret);			/* Free old buffer.  */
1717b725ae77Skettenis 
1718b725ae77Skettenis   ret = ui_file_xstrdup (buf, &length);
1719b725ae77Skettenis   ui_file_delete (buf);
1720b725ae77Skettenis 
1721b725ae77Skettenis   return ret;
1722b725ae77Skettenis }
1723b725ae77Skettenis 
1724b725ae77Skettenis /* Initialize target aix_thread_ops.  */
1725b725ae77Skettenis 
1726b725ae77Skettenis static void
init_aix_thread_ops(void)1727b725ae77Skettenis init_aix_thread_ops (void)
1728b725ae77Skettenis {
1729b725ae77Skettenis   aix_thread_ops.to_shortname          = "aix-threads";
1730b725ae77Skettenis   aix_thread_ops.to_longname           = "AIX pthread support";
1731b725ae77Skettenis   aix_thread_ops.to_doc                = "AIX pthread support";
1732b725ae77Skettenis 
1733b725ae77Skettenis   aix_thread_ops.to_attach             = aix_thread_attach;
1734b725ae77Skettenis   aix_thread_ops.to_detach             = aix_thread_detach;
1735b725ae77Skettenis   aix_thread_ops.to_resume             = aix_thread_resume;
1736b725ae77Skettenis   aix_thread_ops.to_wait               = aix_thread_wait;
1737b725ae77Skettenis   aix_thread_ops.to_fetch_registers    = aix_thread_fetch_registers;
1738b725ae77Skettenis   aix_thread_ops.to_store_registers    = aix_thread_store_registers;
1739*11efff7fSkettenis   aix_thread_ops.deprecated_xfer_memory = aix_thread_xfer_memory;
1740b725ae77Skettenis   /* No need for aix_thread_ops.to_create_inferior, because we activate thread
1741b725ae77Skettenis      debugging when the inferior reaches pd_brk_addr.  */
1742b725ae77Skettenis   aix_thread_ops.to_kill               = aix_thread_kill;
1743b725ae77Skettenis   aix_thread_ops.to_mourn_inferior     = aix_thread_mourn_inferior;
1744b725ae77Skettenis   aix_thread_ops.to_thread_alive       = aix_thread_thread_alive;
1745b725ae77Skettenis   aix_thread_ops.to_pid_to_str         = aix_thread_pid_to_str;
1746b725ae77Skettenis   aix_thread_ops.to_extra_thread_info  = aix_thread_extra_thread_info;
1747b725ae77Skettenis   aix_thread_ops.to_stratum            = thread_stratum;
1748b725ae77Skettenis   aix_thread_ops.to_magic              = OPS_MAGIC;
1749b725ae77Skettenis }
1750b725ae77Skettenis 
1751b725ae77Skettenis /* Module startup initialization function, automagically called by
1752b725ae77Skettenis    init.c.  */
1753b725ae77Skettenis 
1754b725ae77Skettenis void
_initialize_aix_thread(void)1755b725ae77Skettenis _initialize_aix_thread (void)
1756b725ae77Skettenis {
1757b725ae77Skettenis   init_aix_thread_ops ();
1758b725ae77Skettenis   add_target (&aix_thread_ops);
1759b725ae77Skettenis 
1760b725ae77Skettenis   /* Notice when object files get loaded and unloaded.  */
1761*11efff7fSkettenis   target_new_objfile_chain = deprecated_target_new_objfile_hook;
1762*11efff7fSkettenis   deprecated_target_new_objfile_hook = new_objfile;
1763b725ae77Skettenis 
1764*11efff7fSkettenis   deprecated_add_show_from_set
1765*11efff7fSkettenis     (add_set_cmd ("aix-thread", no_class, var_zinteger,
1766b725ae77Skettenis 		  (char *) &debug_aix_thread,
1767b725ae77Skettenis 		  "Set debugging of AIX thread module.\n"
1768b725ae77Skettenis 		  "Enables printf debugging output.\n",
1769b725ae77Skettenis 		  &setdebuglist),
1770b725ae77Skettenis      &showdebuglist);
1771b725ae77Skettenis }
1772