xref: /openbsd-src/gnu/usr.bin/binutils/gdb/uw-thread.c (revision 11efff7f3ac2b3cfeff0c0cddc14294d9b3aca4f)
1b725ae77Skettenis /* Low level interface for debugging UnixWare user-mode threads for
2b725ae77Skettenis    GDB, the GNU debugger.
3b725ae77Skettenis 
4b725ae77Skettenis    Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
5b725ae77Skettenis    Written by Nick Duffek <nsd@cygnus.com>.
6b725ae77Skettenis 
7b725ae77Skettenis    This file is part of GDB.
8b725ae77Skettenis 
9b725ae77Skettenis    This program is free software; you can redistribute it and/or modify
10b725ae77Skettenis    it under the terms of the GNU General Public License as published by
11b725ae77Skettenis    the Free Software Foundation; either version 2 of the License, or
12b725ae77Skettenis    (at your option) any later version.
13b725ae77Skettenis 
14b725ae77Skettenis    This program is distributed in the hope that it will be useful,
15b725ae77Skettenis    but WITHOUT ANY WARRANTY; without even the implied warranty of
16b725ae77Skettenis    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17b725ae77Skettenis    GNU General Public License for more details.
18b725ae77Skettenis 
19b725ae77Skettenis    You should have received a copy of the GNU General Public License
20b725ae77Skettenis    along with this program; if not, write to the Free Software
21b725ae77Skettenis    Foundation, Inc., 59 Temple Place - Suite 330,
22b725ae77Skettenis    Boston, MA 02111-1307, USA.  */
23b725ae77Skettenis 
24b725ae77Skettenis 
25b725ae77Skettenis /* Like many systems, UnixWare implements two classes of threads:
26b725ae77Skettenis    kernel-mode threads, which are scheduled by the kernel; and
27b725ae77Skettenis    user-mode threads, which are scheduled by a library.  UnixWare
28b725ae77Skettenis    calls these two classes lightweight processes (LWPs) and threads,
29b725ae77Skettenis    respectively.
30b725ae77Skettenis 
31b725ae77Skettenis    This module deals with user-mode threads.  It calls procfs_ops
32b725ae77Skettenis    functions to deal with LWPs and processes and core_ops functions to
33b725ae77Skettenis    deal with core files.
34b725ae77Skettenis 
35b725ae77Skettenis    As of this writing, the user-mode thread debugging interface is not
36b725ae77Skettenis    documented beyond the comments in <thread.h>.  The following
37b725ae77Skettenis    description has been gleaned from experience and from information
38b725ae77Skettenis    provided by SCO.
39b725ae77Skettenis 
40b725ae77Skettenis    libthread.so, against which all UnixWare user-mode thread programs
41b725ae77Skettenis    link, provides a global thread_debug structure named _thr_debug.
42b725ae77Skettenis    It has three fields:
43b725ae77Skettenis 
44b725ae77Skettenis      (1) thr_map is a pointer to a pointer to an element of a
45b725ae77Skettenis 	 thread_map ring.  A thread_map contains a single thread's id
46b725ae77Skettenis 	 number, state, LWP pointer, recent register state, and other
47b725ae77Skettenis 	 useful information.
48b725ae77Skettenis 
49b725ae77Skettenis      (2) thr_brk is a pointer to a stub function that libthread.so
50b725ae77Skettenis 	 calls when it changes a thread's state, e.g. by creating it,
51b725ae77Skettenis 	 switching it to an LWP, or causing it to exit.
52b725ae77Skettenis 
53b725ae77Skettenis      (3) thr_debug_on controls whether libthread.so calls thr_brk().
54b725ae77Skettenis 
55b725ae77Skettenis    Debuggers are able to track thread activity by setting a private
56b725ae77Skettenis    breakpoint on thr_brk() and setting thr_debug_on to 1.
57b725ae77Skettenis 
58b725ae77Skettenis    thr_brk() receives two arguments:
59b725ae77Skettenis 
60b725ae77Skettenis      (1) a pointer to a thread_map describing the thread being
61b725ae77Skettenis 	 changed; and
62b725ae77Skettenis 
63b725ae77Skettenis      (2) an enum thread_change specifying one of the following
64b725ae77Skettenis 	 changes:
65b725ae77Skettenis 
66b725ae77Skettenis 	 invalid		 unknown
67b725ae77Skettenis 	 thread_create		 thread has just been created
68b725ae77Skettenis 	 thread_exit		 thread has just exited
69b725ae77Skettenis 	 switch_begin		 thread will be switched to an LWP
70b725ae77Skettenis 	 switch_complete	 thread has been switched to an LWP
71b725ae77Skettenis 	 cancel_complete	 thread wasn't switched to an LWP
72b725ae77Skettenis 	 thread_suspend		 thread has been thr_suspend()ed
73b725ae77Skettenis 	 thread_suspend_pending	 thread will be thr_suspend()ed
74b725ae77Skettenis 	 thread_continue	 thread has been thr_continue()d
75b725ae77Skettenis 
76b725ae77Skettenis    The thread_map argument to thr_brk() is NULL under the following
77b725ae77Skettenis    circumstances:
78b725ae77Skettenis 
79b725ae77Skettenis      - The main thread is being acted upon.  The main thread always
80b725ae77Skettenis        has id 1, so its thread_map is easy to find by scanning through
81b725ae77Skettenis        _thr_debug.thr_map.
82b725ae77Skettenis 
83b725ae77Skettenis      - A "switch_complete" change is occurring, which means that the
84b725ae77Skettenis        thread specified in the most recent "switch_begin" change has
85b725ae77Skettenis        moved to an LWP.
86b725ae77Skettenis 
87b725ae77Skettenis      - A "cancel_complete" change is occurring, which means that the
88b725ae77Skettenis        thread specified in the most recent "switch_begin" change has
89b725ae77Skettenis        not moved to an LWP after all.
90b725ae77Skettenis 
91b725ae77Skettenis      - A spurious "switch_begin" change is occurring after a
92b725ae77Skettenis        "thread_exit" change.
93b725ae77Skettenis 
94b725ae77Skettenis    Between switch_begin and switch_complete or cancel_complete, the
95b725ae77Skettenis    affected thread's LWP pointer is not reliable.  It is possible that
96b725ae77Skettenis    other parts of the thread's thread_map are also unreliable during
97b725ae77Skettenis    that time. */
98b725ae77Skettenis 
99b725ae77Skettenis 
100b725ae77Skettenis #include "defs.h"
101b725ae77Skettenis #include "gdbthread.h"
102b725ae77Skettenis #include "target.h"
103b725ae77Skettenis #include "inferior.h"
104b725ae77Skettenis #include "regcache.h"
105b725ae77Skettenis #include <fcntl.h>
106b725ae77Skettenis 
107b725ae77Skettenis /* <thread.h> includes <sys/priocntl.h>, which requires boolean_t from
108b725ae77Skettenis    <sys/types.h>, which doesn't typedef boolean_t with gcc. */
109b725ae77Skettenis 
110b725ae77Skettenis #define boolean_t int
111b725ae77Skettenis #include <thread.h>
112b725ae77Skettenis #undef boolean_t
113b725ae77Skettenis 
114b725ae77Skettenis #include <synch.h>		/* for UnixWare 2.x */
115b725ae77Skettenis 
116b725ae77Skettenis /* Prototypes for supply_gregset etc. */
117b725ae77Skettenis #include "gregset.h"
118b725ae77Skettenis 
119b725ae77Skettenis /* Offset from SP to first arg on stack at first instruction of a
120b725ae77Skettenis    function.  We provide a default here that's right for most, if not
121b725ae77Skettenis    all, targets that use this file.  */
122b725ae77Skettenis 
123b725ae77Skettenis #ifndef SP_ARG0
124b725ae77Skettenis #define SP_ARG0 (1 * 4)
125b725ae77Skettenis #endif
126b725ae77Skettenis 
127b725ae77Skettenis /* Whether to emit debugging output. */
128b725ae77Skettenis 
129b725ae77Skettenis #define DEBUG 0
130b725ae77Skettenis 
131b725ae77Skettenis /* Default debugging output file, overridden by envvar UWTHR_DEBUG. */
132b725ae77Skettenis 
133b725ae77Skettenis #define DEBUG_FILE "/dev/tty"
134b725ae77Skettenis 
135b725ae77Skettenis /* #if DEBUG, write string S to the debugging output channel. */
136b725ae77Skettenis 
137b725ae77Skettenis #if !DEBUG
138b725ae77Skettenis # define DBG(fmt_and_args)
139b725ae77Skettenis # define DBG2(fmt_and_args)
140b725ae77Skettenis #else
141b725ae77Skettenis # define DBG(fmt_and_args) dbg fmt_and_args
142b725ae77Skettenis # define DBG2(fmt_and_args)
143b725ae77Skettenis #endif
144b725ae77Skettenis 
145b725ae77Skettenis /* Back end to CALL_BASE() and TRY_BASE(): evaluate CALL, then convert
146b725ae77Skettenis    inferior_ptid to a composite thread/process id. */
147b725ae77Skettenis 
148b725ae77Skettenis #define CALL_BASE_1(call)		\
149b725ae77Skettenis do {					\
150b725ae77Skettenis   DBG2(("CALL_BASE(" #call ")"));	\
151b725ae77Skettenis   call;					\
152b725ae77Skettenis   do_cleanups (infpid_cleanup);		\
153b725ae77Skettenis } while (0)
154b725ae77Skettenis 
155b725ae77Skettenis /* If inferior_ptid can be converted to a composite lwp/process id, do so,
156b725ae77Skettenis    evaluate base_ops function CALL, and then convert inferior_ptid back to a
157b725ae77Skettenis    composite thread/process id.
158b725ae77Skettenis 
159b725ae77Skettenis    Otherwise, issue an error message and return nonlocally. */
160b725ae77Skettenis 
161b725ae77Skettenis #define CALL_BASE(call)			\
162b725ae77Skettenis do {					\
163b725ae77Skettenis   if (!lwp_infpid ())			\
164b725ae77Skettenis     error ("uw-thread: no lwp");	\
165b725ae77Skettenis   CALL_BASE_1 (call);			\
166b725ae77Skettenis } while (0)
167b725ae77Skettenis 
168b725ae77Skettenis /* Like CALL_BASE(), but instead of returning nonlocally on error, set
169b725ae77Skettenis    *CALLED to whether the inferior_ptid conversion was successful. */
170b725ae77Skettenis 
171b725ae77Skettenis #define TRY_BASE(call, called)		\
172b725ae77Skettenis do {					\
173b725ae77Skettenis   if ((*(called) = lwp_infpid ()))	\
174b725ae77Skettenis     CALL_BASE_1 (call);			\
175b725ae77Skettenis } while (0)
176b725ae77Skettenis 
177b725ae77Skettenis /* Information passed by thread_iter() to its callback parameter. */
178b725ae77Skettenis 
179b725ae77Skettenis typedef struct {
180b725ae77Skettenis   struct thread_map map;
181b725ae77Skettenis   __lwp_desc_t lwp;
182b725ae77Skettenis   CORE_ADDR mapp;
183b725ae77Skettenis } iter_t;
184b725ae77Skettenis 
185b725ae77Skettenis /* Private thread data for the thread_info struct. */
186b725ae77Skettenis 
187b725ae77Skettenis struct private_thread_info {
188b725ae77Skettenis   int stable;		/* 0 if libthread.so is modifying thread map */
189b725ae77Skettenis   int thrid;		/* thread id assigned by libthread.so */
190b725ae77Skettenis   int lwpid;		/* thread's lwp if .stable, 0 means no lwp */
191b725ae77Skettenis   CORE_ADDR mapp;	/* address of thread's map structure */
192b725ae77Skettenis };
193b725ae77Skettenis 
194b725ae77Skettenis 
195b725ae77Skettenis /* procfs.c's target-specific operations. */
196b725ae77Skettenis extern struct target_ops procfs_ops;
197b725ae77Skettenis 
198b725ae77Skettenis /* Flag to prevent procfs.c from starting inferior processes. */
199b725ae77Skettenis extern int procfs_suppress_run;
200b725ae77Skettenis 
201b725ae77Skettenis /* This module's target-specific operations. */
202b725ae77Skettenis static struct target_ops uw_thread_ops;
203b725ae77Skettenis 
204b725ae77Skettenis /* Copy of the target over which uw_thread_ops is pushed.  This is
205b725ae77Skettenis    more convenient than a pointer to procfs_ops or core_ops, because
206b725ae77Skettenis    they lack current_target's default callbacks. */
207b725ae77Skettenis static struct target_ops base_ops;
208b725ae77Skettenis 
209*11efff7fSkettenis /* Saved pointer to previous owner of
210*11efff7fSkettenis    deprecated_target_new_objfile_hook.  */
211b725ae77Skettenis static void (*target_new_objfile_chain)(struct objfile *);
212b725ae77Skettenis 
213b725ae77Skettenis /* Whether we are debugging a user-space thread program.  This isn't
214b725ae77Skettenis    set until after libthread.so is loaded by the program being
215b725ae77Skettenis    debugged.
216b725ae77Skettenis 
217b725ae77Skettenis    Except for module one-time intialization and where otherwise
218b725ae77Skettenis    documented, no functions in this module get called when
219b725ae77Skettenis    !uw_thread_active. */
220b725ae77Skettenis static int uw_thread_active;
221b725ae77Skettenis 
222b725ae77Skettenis /* For efficiency, cache the addresses of libthread.so's _thr_debug
223b725ae77Skettenis    structure, its thr_brk stub function, and the main thread's map. */
224b725ae77Skettenis static CORE_ADDR thr_debug_addr;
225b725ae77Skettenis static CORE_ADDR thr_brk_addr;
226b725ae77Skettenis static CORE_ADDR thr_map_main;
227b725ae77Skettenis 
228b725ae77Skettenis /* Remember the thread most recently marked as switching.  Necessary because
229b725ae77Skettenis    libthread.so passes null map when calling stub with tc_*_complete. */
230b725ae77Skettenis static struct thread_info *switchto_thread;
231b725ae77Skettenis 
232b725ae77Skettenis /* Cleanup chain for safely restoring inferior_ptid after CALL_BASE. */
233b725ae77Skettenis static struct cleanup *infpid_cleanup;
234b725ae77Skettenis 
235b725ae77Skettenis 
236b725ae77Skettenis #if DEBUG
237b725ae77Skettenis /* Helper function for DBG() macro: if printf-style FMT is non-null, format it
238b725ae77Skettenis    with args and display the result on the debugging output channel. */
239b725ae77Skettenis 
240b725ae77Skettenis static void
dbg(char * fmt,...)241b725ae77Skettenis dbg (char *fmt, ...)
242b725ae77Skettenis {
243b725ae77Skettenis   static int fd = -1, len;
244b725ae77Skettenis   va_list args;
245b725ae77Skettenis   char buf[1024];
246b725ae77Skettenis   char *path;
247b725ae77Skettenis 
248b725ae77Skettenis   if (!fmt)
249b725ae77Skettenis     return;
250b725ae77Skettenis 
251b725ae77Skettenis   if (fd < 0)
252b725ae77Skettenis     {
253b725ae77Skettenis       path = getenv ("UWTHR_DEBUG");
254b725ae77Skettenis       if (!path)
255b725ae77Skettenis 	path = DEBUG_FILE;
256b725ae77Skettenis       if ((fd = open (path, O_WRONLY | O_CREAT | O_TRUNC, 0664)) < 0)
257b725ae77Skettenis 	error ("can't open %s\n", path);
258b725ae77Skettenis     }
259b725ae77Skettenis 
260b725ae77Skettenis   va_start (args, fmt);
261b725ae77Skettenis   vsprintf (buf, fmt, args);
262b725ae77Skettenis   va_end (args);
263b725ae77Skettenis 
264b725ae77Skettenis   len = strlen (buf);
265b725ae77Skettenis   buf[len] = '\n';
266b725ae77Skettenis   (void)write (fd, buf, len + 1);
267b725ae77Skettenis }
268b725ae77Skettenis 
269b725ae77Skettenis #if 0
270b725ae77Skettenis /* Return a string representing composite PID's components. */
271b725ae77Skettenis 
272b725ae77Skettenis static char *
273b725ae77Skettenis dbgpid (ptid_t ptid)
274b725ae77Skettenis {
275b725ae77Skettenis   static char *buf, buf1[80], buf2[80];
276b725ae77Skettenis   if (!buf || buf == buf2)
277b725ae77Skettenis     buf = buf1;
278b725ae77Skettenis   else
279b725ae77Skettenis     buf = buf2;
280b725ae77Skettenis 
281b725ae77Skettenis   if (PIDGET (ptid) <= 0)
282b725ae77Skettenis     sprintf (buf, "%d", PIDGET (ptid));
283b725ae77Skettenis   else
284b725ae77Skettenis     sprintf (buf, "%s %ld/%d", ISTID (pid) ? "thr" : "lwp",
285b725ae77Skettenis 	     TIDGET (pid), PIDGET (pid));
286b725ae77Skettenis 
287b725ae77Skettenis   return buf;
288b725ae77Skettenis }
289b725ae77Skettenis 
290b725ae77Skettenis /* Return a string representing thread state CHANGE. */
291b725ae77Skettenis 
292b725ae77Skettenis static char *
293b725ae77Skettenis dbgchange (enum thread_change change)
294b725ae77Skettenis {
295b725ae77Skettenis   switch (change) {
296b725ae77Skettenis   case tc_invalid:			return "invalid";
297b725ae77Skettenis   case tc_thread_create:		return "thread_create";
298b725ae77Skettenis   case tc_thread_exit:			return "thread_exit";
299b725ae77Skettenis   case tc_switch_begin:			return "switch_begin";
300b725ae77Skettenis   case tc_switch_complete:		return "switch_complete";
301b725ae77Skettenis   case tc_cancel_complete:		return "cancel_complete";
302b725ae77Skettenis   case tc_thread_suspend:		return "thread_suspend";
303b725ae77Skettenis   case tc_thread_suspend_pending:	return "thread_suspend_pending";
304b725ae77Skettenis   case tc_thread_continue:		return "thread_continue";
305b725ae77Skettenis   default:				return "unknown";
306b725ae77Skettenis   }
307b725ae77Skettenis }
308b725ae77Skettenis 
309b725ae77Skettenis /* Return a string representing thread STATE. */
310b725ae77Skettenis 
311b725ae77Skettenis static char *
312b725ae77Skettenis dbgstate (int state)
313b725ae77Skettenis {
314b725ae77Skettenis   switch (state) {
315b725ae77Skettenis   case TS_ONPROC:	return "running";
316b725ae77Skettenis   case TS_SLEEP:	return "sleeping";
317b725ae77Skettenis   case TS_RUNNABLE:	return "runnable";
318b725ae77Skettenis   case TS_ZOMBIE:	return "zombie";
319b725ae77Skettenis   case TS_SUSPENDED:	return "suspended";
320b725ae77Skettenis #ifdef TS_FORK
321b725ae77Skettenis   case TS_FORK:		return "forking";
322b725ae77Skettenis #endif
323b725ae77Skettenis   default:		return "confused";
324b725ae77Skettenis   }
325b725ae77Skettenis }
326b725ae77Skettenis #endif  /* 0 */
327b725ae77Skettenis #endif  /* DEBUG */
328b725ae77Skettenis 
329b725ae77Skettenis 
330b725ae77Skettenis /* Read the contents of _thr_debug into *DEBUGP.  Return success. */
331b725ae77Skettenis 
332b725ae77Skettenis static int
read_thr_debug(struct thread_debug * debugp)333b725ae77Skettenis read_thr_debug (struct thread_debug *debugp)
334b725ae77Skettenis {
335*11efff7fSkettenis   return base_ops.deprecated_xfer_memory (thr_debug_addr, (char *)debugp,
336*11efff7fSkettenis 					  sizeof (*debugp), 0, NULL,
337*11efff7fSkettenis 					  &base_ops);
338b725ae77Skettenis }
339b725ae77Skettenis 
340b725ae77Skettenis /* Read into MAP the contents of the thread map at inferior process address
341b725ae77Skettenis    MAPP.  Return success. */
342b725ae77Skettenis 
343b725ae77Skettenis static int
read_map(CORE_ADDR mapp,struct thread_map * map)344b725ae77Skettenis read_map (CORE_ADDR mapp, struct thread_map *map)
345b725ae77Skettenis {
346*11efff7fSkettenis   return base_ops.deprecated_xfer_memory ((CORE_ADDR)THR_MAP (mapp),
347*11efff7fSkettenis 					  (char *)map, sizeof (*map),
348*11efff7fSkettenis 					  0, NULL, &base_ops);
349b725ae77Skettenis }
350b725ae77Skettenis 
351b725ae77Skettenis /* Read into LWP the contents of the lwp decriptor at inferior process address
352b725ae77Skettenis    LWPP.  Return success. */
353b725ae77Skettenis 
354b725ae77Skettenis static int
read_lwp(CORE_ADDR lwpp,__lwp_desc_t * lwp)355b725ae77Skettenis read_lwp (CORE_ADDR lwpp, __lwp_desc_t *lwp)
356b725ae77Skettenis {
357*11efff7fSkettenis   return base_ops.deprecated_xfer_memory (lwpp, (char *)lwp,
358b725ae77Skettenis 					  sizeof (*lwp), 0, NULL, &base_ops);
359b725ae77Skettenis }
360b725ae77Skettenis 
361b725ae77Skettenis /* Iterate through all user threads, applying FUNC(<map>, <lwp>, DATA) until
362b725ae77Skettenis      (a) FUNC returns nonzero,
363b725ae77Skettenis      (b) FUNC has been applied to all threads, or
364b725ae77Skettenis      (c) an error occurs,
365b725ae77Skettenis    where <map> is the thread's struct thread_map and <lwp> if non-null is the
366b725ae77Skettenis    thread's current __lwp_desc_t.
367b725ae77Skettenis 
368b725ae77Skettenis    If a call to FUNC returns nonzero, return that value; otherwise, return 0. */
369b725ae77Skettenis 
370b725ae77Skettenis static int
thread_iter(int (* func)(iter_t *,void *),void * data)371b725ae77Skettenis thread_iter (int (*func)(iter_t *, void *), void *data)
372b725ae77Skettenis {
373b725ae77Skettenis   struct thread_debug debug;
374b725ae77Skettenis   CORE_ADDR first, mapp;
375b725ae77Skettenis   iter_t iter;
376b725ae77Skettenis   int ret;
377b725ae77Skettenis 
378b725ae77Skettenis   if (!read_thr_debug (&debug))
379b725ae77Skettenis     return 0;
380*11efff7fSkettenis   if (!base_ops.deprecated_xfer_memory ((CORE_ADDR)debug.thr_map,
381*11efff7fSkettenis 					(char *)&mapp, sizeof (mapp), 0, NULL,
382*11efff7fSkettenis 					&base_ops))
383b725ae77Skettenis     return 0;
384b725ae77Skettenis   if (!mapp)
385b725ae77Skettenis     return 0;
386b725ae77Skettenis 
387b725ae77Skettenis   for (first = mapp;;)
388b725ae77Skettenis     {
389b725ae77Skettenis       if (!read_map (mapp, &iter.map))
390b725ae77Skettenis 	return 0;
391b725ae77Skettenis 
392b725ae77Skettenis       if (iter.map.thr_lwpp)
393b725ae77Skettenis 	if (!read_lwp ((CORE_ADDR)iter.map.thr_lwpp, &iter.lwp))
394b725ae77Skettenis 	  return 0;
395b725ae77Skettenis 
396b725ae77Skettenis       iter.mapp = mapp;
397b725ae77Skettenis       if ((ret = func (&iter, data)))
398b725ae77Skettenis 	return ret;
399b725ae77Skettenis 
400b725ae77Skettenis       mapp = (CORE_ADDR)iter.map.thr_next;
401b725ae77Skettenis       if (mapp == first)
402b725ae77Skettenis 	return 0;
403b725ae77Skettenis     }
404b725ae77Skettenis }
405b725ae77Skettenis 
406b725ae77Skettenis /* Deactivate user-mode thread support. */
407b725ae77Skettenis 
408b725ae77Skettenis static void
deactivate_uw_thread(void)409b725ae77Skettenis deactivate_uw_thread (void)
410b725ae77Skettenis {
411b725ae77Skettenis   remove_thread_event_breakpoints ();
412b725ae77Skettenis   uw_thread_active = 0;
413b725ae77Skettenis   unpush_target (&uw_thread_ops);
414b725ae77Skettenis }
415b725ae77Skettenis 
416b725ae77Skettenis /* Return the composite lwp/process id corresponding to composite
417b725ae77Skettenis    id PID.  If PID is a thread with no lwp, return 0. */
418b725ae77Skettenis 
419b725ae77Skettenis static ptid_t
thr_to_lwp(ptid_t ptid)420b725ae77Skettenis thr_to_lwp (ptid_t ptid)
421b725ae77Skettenis {
422b725ae77Skettenis   struct thread_info *info;
423b725ae77Skettenis   ptid_t lid;
424b725ae77Skettenis 
425b725ae77Skettenis   if (!ISTID (ptid))
426b725ae77Skettenis     lid = ptid;
427b725ae77Skettenis   else if (!(info = find_thread_pid (ptid)))
428b725ae77Skettenis     lid = null_ptid;
429b725ae77Skettenis   else if (!info->private->lwpid)
430b725ae77Skettenis     lid = null_ptid;
431b725ae77Skettenis   else
432b725ae77Skettenis     lid = MKLID (PIDGET (ptid), info->private->lwpid);
433b725ae77Skettenis 
434b725ae77Skettenis   DBG2(("  thr_to_lwp(%s) = %s", dbgpid (pid), dbgpid (lid)));
435b725ae77Skettenis   return lid;
436b725ae77Skettenis }
437b725ae77Skettenis 
438b725ae77Skettenis /* find_thread_lwp() callback: return whether TP describes a thread
439b725ae77Skettenis    associated with lwp id DATA. */
440b725ae77Skettenis 
441b725ae77Skettenis static int
find_thread_lwp_callback(struct thread_info * tp,void * data)442b725ae77Skettenis find_thread_lwp_callback (struct thread_info *tp, void *data)
443b725ae77Skettenis {
444b725ae77Skettenis   int lwpid = (int)data;
445b725ae77Skettenis 
446b725ae77Skettenis   if (!ISTID (tp->ptid))
447b725ae77Skettenis     return 0;
448b725ae77Skettenis   if (!tp->private->stable)
449b725ae77Skettenis     return 0;
450b725ae77Skettenis   if (lwpid != tp->private->lwpid)
451b725ae77Skettenis     return 0;
452b725ae77Skettenis 
453b725ae77Skettenis   /* match */
454b725ae77Skettenis   return 1;
455b725ae77Skettenis }
456b725ae77Skettenis 
457b725ae77Skettenis /* If a thread is associated with lwp id LWPID, return the corresponding
458b725ae77Skettenis    member of the global thread list; otherwise, return null. */
459b725ae77Skettenis 
460b725ae77Skettenis static struct thread_info *
find_thread_lwp(int lwpid)461b725ae77Skettenis find_thread_lwp (int lwpid)
462b725ae77Skettenis {
463b725ae77Skettenis   return iterate_over_threads (find_thread_lwp_callback, (void *)lwpid);
464b725ae77Skettenis }
465b725ae77Skettenis 
466b725ae77Skettenis /* Return the composite thread/process id corresponding to composite
467b725ae77Skettenis    id PID.  If PID is an lwp with no thread, return PID. */
468b725ae77Skettenis 
469b725ae77Skettenis static ptid_t
lwp_to_thr(ptid_t ptid)470b725ae77Skettenis lwp_to_thr (ptid_t ptid)
471b725ae77Skettenis {
472b725ae77Skettenis   struct thread_info *info;
473b725ae77Skettenis   int lwpid;
474b725ae77Skettenis   ptid_t tid = ptid;
475b725ae77Skettenis 
476b725ae77Skettenis   if (ISTID (ptid))
477b725ae77Skettenis     goto done;
478b725ae77Skettenis   if (!(lwpid = LIDGET (ptid)))
479b725ae77Skettenis     goto done;
480b725ae77Skettenis   if (!(info = find_thread_lwp (lwpid)))
481b725ae77Skettenis     goto done;
482b725ae77Skettenis   tid = MKTID (PIDGET (ptid), info->private->thrid);
483b725ae77Skettenis 
484b725ae77Skettenis  done:
485b725ae77Skettenis   DBG2((ISTID (tid) ? NULL : "lwp_to_thr: no thr for %s", dbgpid (ptid)));
486b725ae77Skettenis   return tid;
487b725ae77Skettenis }
488b725ae77Skettenis 
489b725ae77Skettenis /* do_cleanups() callback: convert inferior_ptid to a composite
490b725ae77Skettenis    thread/process id after having made a procfs call. */
491b725ae77Skettenis 
492b725ae77Skettenis static void
thr_infpid(void * unused)493b725ae77Skettenis thr_infpid (void *unused)
494b725ae77Skettenis {
495b725ae77Skettenis   ptid_t ptid = lwp_to_thr (inferior_ptid);
496b725ae77Skettenis   DBG2((" inferior_ptid from procfs: %s => %s",
497b725ae77Skettenis 	dbgpid (inferior_ptid), dbgpid (ptid)));
498b725ae77Skettenis   inferior_ptid = ptid;
499b725ae77Skettenis }
500b725ae77Skettenis 
501b725ae77Skettenis /* If possible, convert inferior_ptid to a composite lwp/process id in
502b725ae77Skettenis    preparation for making a procfs call.  Return success. */
503b725ae77Skettenis 
504b725ae77Skettenis static int
lwp_infpid(void)505b725ae77Skettenis lwp_infpid (void)
506b725ae77Skettenis {
507b725ae77Skettenis   ptid_t ptid = thr_to_lwp (inferior_ptid);
508b725ae77Skettenis   DBG2((" inferior_ptid to procfs: %s => %s",
509b725ae77Skettenis 	dbgpid (inferior_ptid), dbgpid (ptid)));
510b725ae77Skettenis 
511b725ae77Skettenis   if (ptid_equal (ptid, null_ptid))
512b725ae77Skettenis     return 0;
513b725ae77Skettenis 
514b725ae77Skettenis   inferior_ptid = ptid;
515b725ae77Skettenis   infpid_cleanup = make_cleanup (thr_infpid, NULL);
516b725ae77Skettenis   return 1;
517b725ae77Skettenis }
518b725ae77Skettenis 
519b725ae77Skettenis /* Add to the global thread list a new user-mode thread with system id THRID,
520b725ae77Skettenis    lwp id LWPID, map address MAPP, and composite thread/process PID. */
521b725ae77Skettenis 
522b725ae77Skettenis static void
add_thread_uw(int thrid,int lwpid,CORE_ADDR mapp,ptid_t ptid)523b725ae77Skettenis add_thread_uw (int thrid, int lwpid, CORE_ADDR mapp, ptid_t ptid)
524b725ae77Skettenis {
525b725ae77Skettenis   struct thread_info *newthread;
526b725ae77Skettenis 
527b725ae77Skettenis   if ((newthread = add_thread (ptid)) == NULL)
528b725ae77Skettenis     error ("failed to create new thread structure");
529b725ae77Skettenis 
530b725ae77Skettenis   newthread->private = xmalloc (sizeof (struct private_thread_info));
531b725ae77Skettenis   newthread->private->stable = 1;
532b725ae77Skettenis   newthread->private->thrid = thrid;
533b725ae77Skettenis   newthread->private->lwpid = lwpid;
534b725ae77Skettenis   newthread->private->mapp = mapp;
535b725ae77Skettenis 
536b725ae77Skettenis   if (target_has_execution)
537b725ae77Skettenis     printf_unfiltered ("[New %s]\n", target_pid_to_str (ptid));
538b725ae77Skettenis }
539b725ae77Skettenis 
540b725ae77Skettenis /* notice_threads() and find_main() callback: if the thread list doesn't
541b725ae77Skettenis    already contain the thread described by ITER, add it if it's the main
542b725ae77Skettenis    thread or if !DATA. */
543b725ae77Skettenis 
544b725ae77Skettenis static int
notice_thread(iter_t * iter,void * data)545b725ae77Skettenis notice_thread (iter_t *iter, void *data)
546b725ae77Skettenis {
547b725ae77Skettenis   int thrid = iter->map.thr_tid;
548b725ae77Skettenis   int lwpid = !iter->map.thr_lwpp ? 0 : iter->lwp.lwp_id;
549b725ae77Skettenis   ptid_t ptid = MKTID (PIDGET (inferior_ptid), thrid);
550b725ae77Skettenis 
551b725ae77Skettenis   if (!find_thread_pid (ptid) && (!data || thrid == 1))
552b725ae77Skettenis     add_thread_uw (thrid, lwpid, iter->mapp, ptid);
553b725ae77Skettenis 
554b725ae77Skettenis   return 0;
555b725ae77Skettenis }
556b725ae77Skettenis 
557b725ae77Skettenis /* Add to the thread list any threads it doesn't already contain. */
558b725ae77Skettenis 
559b725ae77Skettenis static void
notice_threads(void)560b725ae77Skettenis notice_threads (void)
561b725ae77Skettenis {
562b725ae77Skettenis   thread_iter (notice_thread, NULL);
563b725ae77Skettenis }
564b725ae77Skettenis 
565b725ae77Skettenis /* Return the address of the main thread's map.  On error, return 0. */
566b725ae77Skettenis 
567b725ae77Skettenis static CORE_ADDR
find_main(void)568b725ae77Skettenis find_main (void)
569b725ae77Skettenis {
570b725ae77Skettenis   if (!thr_map_main)
571b725ae77Skettenis     {
572b725ae77Skettenis       struct thread_info *info;
573b725ae77Skettenis       thread_iter (notice_thread, (void *)1);
574b725ae77Skettenis       if ((info = find_thread_pid (MKTID (PIDGET (inferior_ptid), 1))))
575b725ae77Skettenis 	thr_map_main = info->private->mapp;
576b725ae77Skettenis     }
577b725ae77Skettenis   return thr_map_main;
578b725ae77Skettenis }
579b725ae77Skettenis 
580b725ae77Skettenis /* Attach to process specified by ARGS, then initialize for debugging it
581b725ae77Skettenis    and wait for the trace-trap that results from attaching.
582b725ae77Skettenis 
583b725ae77Skettenis    This function only gets called with uw_thread_active == 0. */
584b725ae77Skettenis 
585b725ae77Skettenis static void
uw_thread_attach(char * args,int from_tty)586b725ae77Skettenis uw_thread_attach (char *args, int from_tty)
587b725ae77Skettenis {
588b725ae77Skettenis   procfs_ops.to_attach (args, from_tty);
589b725ae77Skettenis   if (uw_thread_active)
590b725ae77Skettenis     thr_infpid (NULL);
591b725ae77Skettenis }
592b725ae77Skettenis 
593b725ae77Skettenis /* Detach from the process attached to by uw_thread_attach(). */
594b725ae77Skettenis 
595b725ae77Skettenis static void
uw_thread_detach(char * args,int from_tty)596b725ae77Skettenis uw_thread_detach (char *args, int from_tty)
597b725ae77Skettenis {
598b725ae77Skettenis   deactivate_uw_thread ();
599b725ae77Skettenis   base_ops.to_detach (args, from_tty);
600b725ae77Skettenis }
601b725ae77Skettenis 
602b725ae77Skettenis /* Tell the inferior process to continue running thread PID if >= 0
603b725ae77Skettenis    and all threads otherwise. */
604b725ae77Skettenis 
605b725ae77Skettenis static void
uw_thread_resume(ptid_t ptid,int step,enum target_signal signo)606b725ae77Skettenis uw_thread_resume (ptid_t ptid, int step, enum target_signal signo)
607b725ae77Skettenis {
608b725ae77Skettenis   if (PIDGET (ptid) > 0)
609b725ae77Skettenis     {
610b725ae77Skettenis       ptid = thr_to_lwp (ptid);
611b725ae77Skettenis       if (ptid_equal (ptid, null_ptid))
612b725ae77Skettenis 	ptid = pid_to_ptid (-1);
613b725ae77Skettenis     }
614b725ae77Skettenis 
615b725ae77Skettenis   CALL_BASE (base_ops.to_resume (ptid, step, signo));
616b725ae77Skettenis }
617b725ae77Skettenis 
618b725ae77Skettenis /* If the trap we just received from lwp PID was due to a breakpoint
619b725ae77Skettenis    on the libthread.so debugging stub, update this module's state
620b725ae77Skettenis    accordingly. */
621b725ae77Skettenis 
622b725ae77Skettenis static void
libthread_stub(ptid_t ptid)623b725ae77Skettenis libthread_stub (ptid_t ptid)
624b725ae77Skettenis {
625b725ae77Skettenis   CORE_ADDR sp, mapp, mapp_main;
626b725ae77Skettenis   enum thread_change change;
627b725ae77Skettenis   struct thread_map map;
628b725ae77Skettenis   __lwp_desc_t lwp;
629b725ae77Skettenis   int lwpid;
630b725ae77Skettenis   ptid_t tid = null_ptid;
631b725ae77Skettenis   struct thread_info *info;
632b725ae77Skettenis 
633b725ae77Skettenis   /* Check for stub breakpoint. */
634b725ae77Skettenis   if (read_pc_pid (ptid) - DECR_PC_AFTER_BREAK != thr_brk_addr)
635b725ae77Skettenis     return;
636b725ae77Skettenis 
637b725ae77Skettenis   /* Retrieve stub args. */
638b725ae77Skettenis   sp = read_register_pid (SP_REGNUM, ptid);
639*11efff7fSkettenis   if (!base_ops.deprecated_xfer_memory (sp + SP_ARG0, (char *)&mapp,
640b725ae77Skettenis 					sizeof (mapp), 0, NULL, &base_ops))
641b725ae77Skettenis     goto err;
642*11efff7fSkettenis   if (!base_ops.deprecated_xfer_memory (sp + SP_ARG0 + sizeof (mapp),
643*11efff7fSkettenis 					(char *)&change, sizeof (change), 0,
644*11efff7fSkettenis 					NULL, &base_ops))
645b725ae77Skettenis     goto err;
646b725ae77Skettenis 
647b725ae77Skettenis   /* create_inferior() may not have finished yet, so notice the main
648b725ae77Skettenis      thread to ensure that it's displayed first by add_thread(). */
649b725ae77Skettenis   mapp_main = find_main ();
650b725ae77Skettenis 
651b725ae77Skettenis   /* Notice thread creation, deletion, or stability change. */
652b725ae77Skettenis   switch (change) {
653b725ae77Skettenis   case tc_switch_begin:
654b725ae77Skettenis     if (!mapp)				/* usually means main thread */
655b725ae77Skettenis       mapp = mapp_main;
656b725ae77Skettenis     /* fall through */
657b725ae77Skettenis 
658b725ae77Skettenis   case tc_thread_create:
659b725ae77Skettenis   case tc_thread_exit:
660b725ae77Skettenis     if (!mapp)
661b725ae77Skettenis       break;
662b725ae77Skettenis     if (!read_map (mapp, &map))
663b725ae77Skettenis       goto err;
664b725ae77Skettenis     tid = MKTID (PIDGET (ptid), map.thr_tid);
665b725ae77Skettenis 
666b725ae77Skettenis     switch (change) {
667b725ae77Skettenis     case tc_thread_create:		/* new thread */
668b725ae77Skettenis       if (!map.thr_lwpp)
669b725ae77Skettenis 	lwpid = 0;
670b725ae77Skettenis       else if (!read_lwp ((CORE_ADDR)map.thr_lwpp, &lwp))
671b725ae77Skettenis 	goto err;
672b725ae77Skettenis       else
673b725ae77Skettenis 	lwpid = lwp.lwp_id;
674b725ae77Skettenis       add_thread_uw (map.thr_tid, lwpid, mapp, tid);
675b725ae77Skettenis       break;
676b725ae77Skettenis 
677b725ae77Skettenis     case tc_thread_exit:		/* thread has exited */
678b725ae77Skettenis       printf_unfiltered ("[Exited %s]\n", target_pid_to_str (tid));
679b725ae77Skettenis       delete_thread (tid);
680b725ae77Skettenis       if (ptid_equal (tid, inferior_ptid))
681b725ae77Skettenis 	inferior_ptid = ptid;
682b725ae77Skettenis       break;
683b725ae77Skettenis 
684b725ae77Skettenis     case tc_switch_begin:		/* lwp is switching threads */
685b725ae77Skettenis       if (switchto_thread)
686b725ae77Skettenis 	goto err;
687b725ae77Skettenis       if (!(switchto_thread = find_thread_pid (tid)))
688b725ae77Skettenis 	goto err;
689b725ae77Skettenis       switchto_thread->private->stable = 0;
690b725ae77Skettenis       break;
691b725ae77Skettenis 
692b725ae77Skettenis     default:
693b725ae77Skettenis       break;
694b725ae77Skettenis     }
695b725ae77Skettenis     break;
696b725ae77Skettenis 
697b725ae77Skettenis   case tc_switch_complete:		/* lwp has switched threads */
698b725ae77Skettenis   case tc_cancel_complete:		/* lwp didn't switch threads */
699b725ae77Skettenis     if (!switchto_thread)
700b725ae77Skettenis       goto err;
701b725ae77Skettenis 
702b725ae77Skettenis     if (change == tc_switch_complete)
703b725ae77Skettenis       {
704b725ae77Skettenis 	/* If switchto_thread is the main thread, then (a) the corresponding
705b725ae77Skettenis 	   tc_switch_begin probably received a null map argument and therefore
706b725ae77Skettenis 	   (b) it may have been a spurious switch following a tc_thread_exit.
707b725ae77Skettenis 
708b725ae77Skettenis 	   Therefore, explicitly query the thread's lwp before caching it in
709b725ae77Skettenis 	   its thread list entry. */
710b725ae77Skettenis 
711b725ae77Skettenis 	if (!read_map (switchto_thread->private->mapp, &map))
712b725ae77Skettenis 	  goto err;
713b725ae77Skettenis 	if (map.thr_lwpp)
714b725ae77Skettenis 	  {
715b725ae77Skettenis 	    if (!read_lwp ((CORE_ADDR)map.thr_lwpp, &lwp))
716b725ae77Skettenis 	      goto err;
717b725ae77Skettenis 	    if ((info = find_thread_lwp (lwp.lwp_id)))
718b725ae77Skettenis 	      info->private->lwpid = 0;
719b725ae77Skettenis 	    switchto_thread->private->lwpid = lwp.lwp_id;
720b725ae77Skettenis 	  }
721b725ae77Skettenis       }
722b725ae77Skettenis 
723b725ae77Skettenis     switchto_thread->private->stable = 1;
724b725ae77Skettenis     switchto_thread = NULL;
725b725ae77Skettenis     break;
726b725ae77Skettenis 
727b725ae77Skettenis   case tc_invalid:
728b725ae77Skettenis   case tc_thread_suspend:
729b725ae77Skettenis   case tc_thread_suspend_pending:
730b725ae77Skettenis   case tc_thread_continue:
731b725ae77Skettenis   err:
732b725ae77Skettenis     DBG(("unexpected condition in libthread_stub()"));
733b725ae77Skettenis     break;
734b725ae77Skettenis   }
735b725ae77Skettenis 
736b725ae77Skettenis   DBG2(("libthread_stub(%s): %s %s %s", dbgpid (pid), dbgpid (tid),
737b725ae77Skettenis 	dbgchange (change), tid ? dbgstate (map.thr_state) : ""));
738b725ae77Skettenis }
739b725ae77Skettenis 
740b725ae77Skettenis /* Wait for thread/lwp/process ID if >= 0 or for any thread otherwise. */
741b725ae77Skettenis 
742b725ae77Skettenis static ptid_t
uw_thread_wait(ptid_t ptid,struct target_waitstatus * status)743b725ae77Skettenis uw_thread_wait (ptid_t ptid, struct target_waitstatus *status)
744b725ae77Skettenis {
745b725ae77Skettenis   if (PIDGET (ptid) > 0)
746b725ae77Skettenis     ptid = thr_to_lwp (ptid);
747b725ae77Skettenis   if (PIDGET (ptid) <= 0)
748b725ae77Skettenis     ptid = pid_to_ptid (-1);
749b725ae77Skettenis 
750b725ae77Skettenis   CALL_BASE (ptid = base_ops.to_wait (ptid, status));
751b725ae77Skettenis 
752b725ae77Skettenis   if (status->kind == TARGET_WAITKIND_STOPPED &&
753b725ae77Skettenis       status->value.sig == TARGET_SIGNAL_TRAP)
754b725ae77Skettenis     libthread_stub (ptid);
755b725ae77Skettenis 
756b725ae77Skettenis   return lwp_to_thr (ptid);
757b725ae77Skettenis }
758b725ae77Skettenis 
759b725ae77Skettenis /* Tell gdb about the registers in the thread/lwp/process specified by
760b725ae77Skettenis    inferior_ptid. */
761b725ae77Skettenis 
762b725ae77Skettenis static void
uw_thread_fetch_registers(int regno)763b725ae77Skettenis uw_thread_fetch_registers (int regno)
764b725ae77Skettenis {
765b725ae77Skettenis   int called;
766b725ae77Skettenis   struct thread_info *info;
767b725ae77Skettenis   struct thread_map map;
768b725ae77Skettenis 
769b725ae77Skettenis   TRY_BASE (base_ops.to_fetch_registers (regno), &called);
770b725ae77Skettenis   if (called)
771b725ae77Skettenis     return;
772b725ae77Skettenis 
773b725ae77Skettenis   if (!(info = find_thread_pid (inferior_ptid)))
774b725ae77Skettenis     return;
775b725ae77Skettenis   if (!read_map (info->private->mapp, &map))
776b725ae77Skettenis     return;
777b725ae77Skettenis 
778b725ae77Skettenis   supply_gregset (&map.thr_ucontext.uc_mcontext.gregs);
779b725ae77Skettenis   supply_fpregset (&map.thr_ucontext.uc_mcontext.fpregs);
780b725ae77Skettenis }
781b725ae77Skettenis 
782b725ae77Skettenis /* Store gdb's current view of the register set into the thread/lwp/process
783b725ae77Skettenis    specified by inferior_ptid. */
784b725ae77Skettenis 
785b725ae77Skettenis static void
uw_thread_store_registers(int regno)786b725ae77Skettenis uw_thread_store_registers (int regno)
787b725ae77Skettenis {
788b725ae77Skettenis   CALL_BASE (base_ops.to_store_registers (regno));
789b725ae77Skettenis }
790b725ae77Skettenis 
791b725ae77Skettenis /* Prepare to modify the registers array. */
792b725ae77Skettenis 
793b725ae77Skettenis static void
uw_thread_prepare_to_store(void)794b725ae77Skettenis uw_thread_prepare_to_store (void)
795b725ae77Skettenis {
796b725ae77Skettenis   CALL_BASE (base_ops.to_prepare_to_store ());
797b725ae77Skettenis }
798b725ae77Skettenis 
799b725ae77Skettenis /* Fork an inferior process and start debugging it.
800b725ae77Skettenis 
801b725ae77Skettenis    This function only gets called with uw_thread_active == 0. */
802b725ae77Skettenis 
803b725ae77Skettenis static void
uw_thread_create_inferior(char * exec_file,char * allargs,char ** env,int from_tty)804*11efff7fSkettenis uw_thread_create_inferior (char *exec_file, char *allargs, char **env,
805*11efff7fSkettenis 			   int from_tty)
806b725ae77Skettenis {
807b725ae77Skettenis   if (uw_thread_active)
808b725ae77Skettenis     deactivate_uw_thread ();
809b725ae77Skettenis 
810*11efff7fSkettenis   procfs_ops.to_create_inferior (exec_file, allargs, env, from_tty);
811b725ae77Skettenis   if (uw_thread_active)
812b725ae77Skettenis     {
813b725ae77Skettenis       find_main ();
814b725ae77Skettenis       thr_infpid (NULL);
815b725ae77Skettenis     }
816b725ae77Skettenis }
817b725ae77Skettenis 
818b725ae77Skettenis /* Kill and forget about the inferior process. */
819b725ae77Skettenis 
820b725ae77Skettenis static void
uw_thread_kill(void)821b725ae77Skettenis uw_thread_kill (void)
822b725ae77Skettenis {
823b725ae77Skettenis   base_ops.to_kill ();
824b725ae77Skettenis }
825b725ae77Skettenis 
826b725ae77Skettenis /* Clean up after the inferior exits. */
827b725ae77Skettenis 
828b725ae77Skettenis static void
uw_thread_mourn_inferior(void)829b725ae77Skettenis uw_thread_mourn_inferior (void)
830b725ae77Skettenis {
831b725ae77Skettenis   deactivate_uw_thread ();
832b725ae77Skettenis   base_ops.to_mourn_inferior ();
833b725ae77Skettenis }
834b725ae77Skettenis 
835b725ae77Skettenis /* Return whether this module can attach to and run processes.
836b725ae77Skettenis 
837b725ae77Skettenis    This function only gets called with uw_thread_active == 0. */
838b725ae77Skettenis 
839b725ae77Skettenis static int
uw_thread_can_run(void)840b725ae77Skettenis uw_thread_can_run (void)
841b725ae77Skettenis {
842b725ae77Skettenis   return procfs_suppress_run;
843b725ae77Skettenis }
844b725ae77Skettenis 
845b725ae77Skettenis /* Return whether thread PID is still valid. */
846b725ae77Skettenis 
847b725ae77Skettenis static int
uw_thread_alive(ptid_t ptid)848b725ae77Skettenis uw_thread_alive (ptid_t ptid)
849b725ae77Skettenis {
850b725ae77Skettenis   if (!ISTID (ptid))
851b725ae77Skettenis     return base_ops.to_thread_alive (ptid);
852b725ae77Skettenis 
853b725ae77Skettenis   /* If it's in the thread list, it's valid, because otherwise
854b725ae77Skettenis      libthread_stub() would have deleted it. */
855b725ae77Skettenis   return in_thread_list (ptid);
856b725ae77Skettenis }
857b725ae77Skettenis 
858b725ae77Skettenis /* Add to the thread list any threads and lwps it doesn't already contain. */
859b725ae77Skettenis 
860b725ae77Skettenis static void
uw_thread_find_new_threads(void)861b725ae77Skettenis uw_thread_find_new_threads (void)
862b725ae77Skettenis {
863b725ae77Skettenis   CALL_BASE (if (base_ops.to_find_new_threads)
864b725ae77Skettenis 	       base_ops.to_find_new_threads ());
865b725ae77Skettenis   notice_threads ();
866b725ae77Skettenis }
867b725ae77Skettenis 
868b725ae77Skettenis /* Return a string for pretty-printing PID in "info threads" output.
869b725ae77Skettenis    This may be called by either procfs.c or by generic gdb. */
870b725ae77Skettenis 
871b725ae77Skettenis static char *
uw_thread_pid_to_str(ptid_t ptid)872b725ae77Skettenis uw_thread_pid_to_str (ptid_t ptid)
873b725ae77Skettenis {
874b725ae77Skettenis #define FMT "Thread %ld"
875b725ae77Skettenis   static char buf[sizeof (FMT) + 3 * sizeof (long)];
876b725ae77Skettenis 
877b725ae77Skettenis   if (!ISTID (ptid))
878b725ae77Skettenis     /* core_ops says "process foo", so call procfs_ops explicitly. */
879b725ae77Skettenis     return procfs_ops.to_pid_to_str (ptid);
880b725ae77Skettenis 
881b725ae77Skettenis   sprintf (buf, FMT, TIDGET (ptid));
882b725ae77Skettenis #undef FMT
883b725ae77Skettenis   return buf;
884b725ae77Skettenis }
885b725ae77Skettenis 
886b725ae77Skettenis /* Return a string displaying INFO state information in "info threads"
887b725ae77Skettenis    output. */
888b725ae77Skettenis 
889b725ae77Skettenis static char *
uw_extra_thread_info(struct thread_info * info)890b725ae77Skettenis uw_extra_thread_info (struct thread_info *info)
891b725ae77Skettenis {
892b725ae77Skettenis   static char buf[80];
893b725ae77Skettenis   struct thread_map map;
894b725ae77Skettenis   __lwp_desc_t lwp;
895b725ae77Skettenis   int lwpid;
896b725ae77Skettenis   char *name;
897b725ae77Skettenis 
898b725ae77Skettenis   if (!ISTID (info->ptid))
899b725ae77Skettenis     return NULL;
900b725ae77Skettenis 
901b725ae77Skettenis   if (!info->private->stable)
902b725ae77Skettenis     return "switching";
903b725ae77Skettenis 
904b725ae77Skettenis   if (!read_map (info->private->mapp, &map))
905b725ae77Skettenis     return NULL;
906b725ae77Skettenis 
907b725ae77Skettenis   if (!map.thr_lwpp || !read_lwp ((CORE_ADDR)map.thr_lwpp, &lwp))
908b725ae77Skettenis     lwpid = 0;
909b725ae77Skettenis   else
910b725ae77Skettenis     lwpid = lwp.lwp_id;
911b725ae77Skettenis 
912b725ae77Skettenis   switch (map.thr_state) {
913b725ae77Skettenis   case TS_ONPROC:	name = "running";	break;
914b725ae77Skettenis   case TS_SLEEP:	name = "sleeping";	break;
915b725ae77Skettenis   case TS_RUNNABLE:	name = "runnable";	break;
916b725ae77Skettenis   case TS_ZOMBIE:	name = "zombie";	break;
917b725ae77Skettenis   case TS_SUSPENDED:	name = "suspended";	break;
918b725ae77Skettenis #ifdef TS_FORK
919b725ae77Skettenis   case TS_FORK:		name = "forking";	break;
920b725ae77Skettenis #endif
921b725ae77Skettenis   default:		name = "confused";	break;
922b725ae77Skettenis   }
923b725ae77Skettenis 
924b725ae77Skettenis   if (!lwpid)
925b725ae77Skettenis     return name;
926b725ae77Skettenis 
927b725ae77Skettenis   sprintf (buf, "%s, LWP %d", name, lwpid);
928b725ae77Skettenis   return buf;
929b725ae77Skettenis }
930b725ae77Skettenis 
931b725ae77Skettenis /* Check whether libthread.so has just been loaded, and if so, try to
932b725ae77Skettenis    initialize user-space thread debugging support.
933b725ae77Skettenis 
934b725ae77Skettenis    libthread.so loading happens while (a) an inferior process is being
935b725ae77Skettenis    started by procfs and (b) a core image is being loaded.
936b725ae77Skettenis 
937b725ae77Skettenis    This function often gets called with uw_thread_active == 0. */
938b725ae77Skettenis 
939b725ae77Skettenis static void
libthread_init(void)940b725ae77Skettenis libthread_init (void)
941b725ae77Skettenis {
942b725ae77Skettenis   struct minimal_symbol *ms;
943b725ae77Skettenis   struct thread_debug debug;
944b725ae77Skettenis   CORE_ADDR onp;
945b725ae77Skettenis   struct breakpoint *b;
946b725ae77Skettenis   int one = 1;
947b725ae77Skettenis 
948b725ae77Skettenis   /* Don't initialize twice. */
949b725ae77Skettenis   if (uw_thread_active)
950b725ae77Skettenis     return;
951b725ae77Skettenis 
952b725ae77Skettenis   /* Check whether libthread.so has been loaded. */
953b725ae77Skettenis   if (!(ms = lookup_minimal_symbol ("_thr_debug", NULL, NULL)))
954b725ae77Skettenis     return;
955b725ae77Skettenis 
956b725ae77Skettenis   /* Cache _thr_debug's address. */
957b725ae77Skettenis   if (!(thr_debug_addr = SYMBOL_VALUE_ADDRESS (ms)))
958b725ae77Skettenis     return;
959b725ae77Skettenis 
960*11efff7fSkettenis   /* Initialize base_ops.deprecated_xfer_memory().  */
961b725ae77Skettenis   base_ops = current_target;
962b725ae77Skettenis 
963b725ae77Skettenis   /* Load _thr_debug's current contents. */
964b725ae77Skettenis   if (!read_thr_debug (&debug))
965b725ae77Skettenis     return;
966b725ae77Skettenis 
967b725ae77Skettenis   /* User code (e.g. my test programs) may dereference _thr_debug,
968b725ae77Skettenis      making it availble to GDB before shared libs are loaded. */
969b725ae77Skettenis   if (!debug.thr_map)
970b725ae77Skettenis     return;
971b725ae77Skettenis 
972b725ae77Skettenis   /* libthread.so has been loaded, and the current_target should now
973b725ae77Skettenis      reflect core_ops or procfs_ops. */
974b725ae77Skettenis   push_target (&uw_thread_ops);		/* must precede notice_threads() */
975b725ae77Skettenis   uw_thread_active = 1;
976b725ae77Skettenis 
977b725ae77Skettenis   if (!target_has_execution)
978b725ae77Skettenis 
979b725ae77Skettenis     /* Locate threads in core file. */
980b725ae77Skettenis     notice_threads ();
981b725ae77Skettenis 
982b725ae77Skettenis   else
983b725ae77Skettenis     {
984b725ae77Skettenis       /* Set a breakpoint on the stub function provided by libthread.so. */
985b725ae77Skettenis       thr_brk_addr = (CORE_ADDR)debug.thr_brk;
986b725ae77Skettenis       if (!(b = create_thread_event_breakpoint (thr_brk_addr)))
987b725ae77Skettenis 	goto err;
988b725ae77Skettenis 
989b725ae77Skettenis       /* Activate the stub function. */
990b725ae77Skettenis       onp = (CORE_ADDR)&((struct thread_debug *)thr_debug_addr)->thr_debug_on;
991*11efff7fSkettenis       if (!base_ops.deprecated_xfer_memory ((CORE_ADDR)onp, (char *)&one,
992b725ae77Skettenis 					    sizeof (one), 1, NULL, &base_ops))
993b725ae77Skettenis 	{
994b725ae77Skettenis 	  delete_breakpoint (b);
995b725ae77Skettenis 	  goto err;
996b725ae77Skettenis 	}
997b725ae77Skettenis 
998b725ae77Skettenis       /* Prepare for finding the main thread, which doesn't yet exist. */
999b725ae77Skettenis       thr_map_main = 0;
1000b725ae77Skettenis     }
1001b725ae77Skettenis 
1002b725ae77Skettenis   return;
1003b725ae77Skettenis 
1004b725ae77Skettenis  err:
1005b725ae77Skettenis   warning ("uw-thread: unable to initialize user-mode thread debugging\n");
1006b725ae77Skettenis   deactivate_uw_thread ();
1007b725ae77Skettenis }
1008b725ae77Skettenis 
1009*11efff7fSkettenis /* deprecated_target_new_objfile_hook callback.
1010b725ae77Skettenis 
1011b725ae77Skettenis    If OBJFILE is non-null, check whether libthread.so was just loaded,
1012b725ae77Skettenis    and if so, prepare for user-mode thread debugging.
1013b725ae77Skettenis 
1014b725ae77Skettenis    If OBJFILE is null, libthread.so has gone away, so stop debugging
1015b725ae77Skettenis    user-mode threads.
1016b725ae77Skettenis 
1017b725ae77Skettenis    This function often gets called with uw_thread_active == 0. */
1018b725ae77Skettenis 
1019b725ae77Skettenis static void
uw_thread_new_objfile(struct objfile * objfile)1020b725ae77Skettenis uw_thread_new_objfile (struct objfile *objfile)
1021b725ae77Skettenis {
1022b725ae77Skettenis   if (objfile)
1023b725ae77Skettenis     libthread_init ();
1024b725ae77Skettenis 
1025b725ae77Skettenis   else if (uw_thread_active)
1026b725ae77Skettenis     deactivate_uw_thread ();
1027b725ae77Skettenis 
1028b725ae77Skettenis   if (target_new_objfile_chain)
1029b725ae77Skettenis     target_new_objfile_chain (objfile);
1030b725ae77Skettenis }
1031b725ae77Skettenis 
1032b725ae77Skettenis /* Initialize uw_thread_ops. */
1033b725ae77Skettenis 
1034b725ae77Skettenis static void
init_uw_thread_ops(void)1035b725ae77Skettenis init_uw_thread_ops (void)
1036b725ae77Skettenis {
1037b725ae77Skettenis   uw_thread_ops.to_shortname          = "unixware-threads";
1038b725ae77Skettenis   uw_thread_ops.to_longname           = "UnixWare threads and pthread.";
1039b725ae77Skettenis   uw_thread_ops.to_doc        = "UnixWare threads and pthread support.";
1040b725ae77Skettenis   uw_thread_ops.to_attach             = uw_thread_attach;
1041b725ae77Skettenis   uw_thread_ops.to_detach             = uw_thread_detach;
1042b725ae77Skettenis   uw_thread_ops.to_resume             = uw_thread_resume;
1043b725ae77Skettenis   uw_thread_ops.to_wait               = uw_thread_wait;
1044b725ae77Skettenis   uw_thread_ops.to_fetch_registers    = uw_thread_fetch_registers;
1045b725ae77Skettenis   uw_thread_ops.to_store_registers    = uw_thread_store_registers;
1046b725ae77Skettenis   uw_thread_ops.to_prepare_to_store   = uw_thread_prepare_to_store;
1047b725ae77Skettenis   uw_thread_ops.to_create_inferior    = uw_thread_create_inferior;
1048b725ae77Skettenis   uw_thread_ops.to_kill               = uw_thread_kill;
1049b725ae77Skettenis   uw_thread_ops.to_mourn_inferior     = uw_thread_mourn_inferior;
1050b725ae77Skettenis   uw_thread_ops.to_can_run            = uw_thread_can_run;
1051b725ae77Skettenis   uw_thread_ops.to_thread_alive       = uw_thread_alive;
1052b725ae77Skettenis   uw_thread_ops.to_find_new_threads   = uw_thread_find_new_threads;
1053b725ae77Skettenis   uw_thread_ops.to_pid_to_str         = uw_thread_pid_to_str;
1054b725ae77Skettenis   uw_thread_ops.to_extra_thread_info  = uw_extra_thread_info;
1055b725ae77Skettenis   uw_thread_ops.to_stratum            = thread_stratum;
1056b725ae77Skettenis   uw_thread_ops.to_magic              = OPS_MAGIC;
1057b725ae77Skettenis }
1058b725ae77Skettenis 
1059b725ae77Skettenis /* Module startup initialization function, automagically called by
1060b725ae77Skettenis    init.c. */
1061b725ae77Skettenis 
1062b725ae77Skettenis void
_initialize_uw_thread(void)1063b725ae77Skettenis _initialize_uw_thread (void)
1064b725ae77Skettenis {
1065b725ae77Skettenis   init_uw_thread_ops ();
1066b725ae77Skettenis   add_target (&uw_thread_ops);
1067b725ae77Skettenis 
1068b725ae77Skettenis   procfs_suppress_run = 1;
1069b725ae77Skettenis 
1070b725ae77Skettenis   /* Notice when libthread.so gets loaded. */
1071*11efff7fSkettenis   target_new_objfile_chain = deprecated_target_new_objfile_hook;
1072*11efff7fSkettenis   deprecated_target_new_objfile_hook = uw_thread_new_objfile;
1073b725ae77Skettenis }
1074