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