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