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