xref: /dflybsd-src/contrib/gdb-7/gdb/bsd-uthread.c (revision 5796c8dc12c637f18a1740c26afd8d40ffa9b719)
1*5796c8dcSSimon Schubert /* BSD user-level threads support.
2*5796c8dcSSimon Schubert 
3*5796c8dcSSimon Schubert    Copyright (C) 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
4*5796c8dcSSimon Schubert 
5*5796c8dcSSimon Schubert    This file is part of GDB.
6*5796c8dcSSimon Schubert 
7*5796c8dcSSimon Schubert    This program is free software; you can redistribute it and/or modify
8*5796c8dcSSimon Schubert    it under the terms of the GNU General Public License as published by
9*5796c8dcSSimon Schubert    the Free Software Foundation; either version 3 of the License, or
10*5796c8dcSSimon Schubert    (at your option) any later version.
11*5796c8dcSSimon Schubert 
12*5796c8dcSSimon Schubert    This program is distributed in the hope that it will be useful,
13*5796c8dcSSimon Schubert    but WITHOUT ANY WARRANTY; without even the implied warranty of
14*5796c8dcSSimon Schubert    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*5796c8dcSSimon Schubert    GNU General Public License for more details.
16*5796c8dcSSimon Schubert 
17*5796c8dcSSimon Schubert    You should have received a copy of the GNU General Public License
18*5796c8dcSSimon Schubert    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19*5796c8dcSSimon Schubert 
20*5796c8dcSSimon Schubert #include "defs.h"
21*5796c8dcSSimon Schubert #include "gdbcore.h"
22*5796c8dcSSimon Schubert #include "gdbthread.h"
23*5796c8dcSSimon Schubert #include "inferior.h"
24*5796c8dcSSimon Schubert #include "objfiles.h"
25*5796c8dcSSimon Schubert #include "observer.h"
26*5796c8dcSSimon Schubert #include "regcache.h"
27*5796c8dcSSimon Schubert #include "solib.h"
28*5796c8dcSSimon Schubert #include "solist.h"
29*5796c8dcSSimon Schubert #include "symfile.h"
30*5796c8dcSSimon Schubert #include "target.h"
31*5796c8dcSSimon Schubert 
32*5796c8dcSSimon Schubert #include "gdb_assert.h"
33*5796c8dcSSimon Schubert #include "gdb_obstack.h"
34*5796c8dcSSimon Schubert 
35*5796c8dcSSimon Schubert #include "bsd-uthread.h"
36*5796c8dcSSimon Schubert 
37*5796c8dcSSimon Schubert /* HACK: Save the bsd_uthreads ops returned by bsd_uthread_target.  */
38*5796c8dcSSimon Schubert static struct target_ops *bsd_uthread_ops_hack;
39*5796c8dcSSimon Schubert 
40*5796c8dcSSimon Schubert 
41*5796c8dcSSimon Schubert /* Architecture-specific operations.  */
42*5796c8dcSSimon Schubert 
43*5796c8dcSSimon Schubert /* Per-architecture data key.  */
44*5796c8dcSSimon Schubert static struct gdbarch_data *bsd_uthread_data;
45*5796c8dcSSimon Schubert 
46*5796c8dcSSimon Schubert struct bsd_uthread_ops
47*5796c8dcSSimon Schubert {
48*5796c8dcSSimon Schubert   /* Supply registers for an inactive thread to a register cache.  */
49*5796c8dcSSimon Schubert   void (*supply_uthread)(struct regcache *, int, CORE_ADDR);
50*5796c8dcSSimon Schubert 
51*5796c8dcSSimon Schubert   /* Collect registers for an inactive thread from a register cache.  */
52*5796c8dcSSimon Schubert   void (*collect_uthread)(const struct regcache *, int, CORE_ADDR);
53*5796c8dcSSimon Schubert };
54*5796c8dcSSimon Schubert 
55*5796c8dcSSimon Schubert static void *
56*5796c8dcSSimon Schubert bsd_uthread_init (struct obstack *obstack)
57*5796c8dcSSimon Schubert {
58*5796c8dcSSimon Schubert   struct bsd_uthread_ops *ops;
59*5796c8dcSSimon Schubert 
60*5796c8dcSSimon Schubert   ops = OBSTACK_ZALLOC (obstack, struct bsd_uthread_ops);
61*5796c8dcSSimon Schubert   return ops;
62*5796c8dcSSimon Schubert }
63*5796c8dcSSimon Schubert 
64*5796c8dcSSimon Schubert /* Set the function that supplies registers from an inactive thread
65*5796c8dcSSimon Schubert    for architecture GDBARCH to SUPPLY_UTHREAD.  */
66*5796c8dcSSimon Schubert 
67*5796c8dcSSimon Schubert void
68*5796c8dcSSimon Schubert bsd_uthread_set_supply_uthread (struct gdbarch *gdbarch,
69*5796c8dcSSimon Schubert 				void (*supply_uthread) (struct regcache *,
70*5796c8dcSSimon Schubert 							int, CORE_ADDR))
71*5796c8dcSSimon Schubert {
72*5796c8dcSSimon Schubert   struct bsd_uthread_ops *ops = gdbarch_data (gdbarch, bsd_uthread_data);
73*5796c8dcSSimon Schubert   ops->supply_uthread = supply_uthread;
74*5796c8dcSSimon Schubert }
75*5796c8dcSSimon Schubert 
76*5796c8dcSSimon Schubert /* Set the function that collects registers for an inactive thread for
77*5796c8dcSSimon Schubert    architecture GDBARCH to SUPPLY_UTHREAD.  */
78*5796c8dcSSimon Schubert 
79*5796c8dcSSimon Schubert void
80*5796c8dcSSimon Schubert bsd_uthread_set_collect_uthread (struct gdbarch *gdbarch,
81*5796c8dcSSimon Schubert 			 void (*collect_uthread) (const struct regcache *,
82*5796c8dcSSimon Schubert 						  int, CORE_ADDR))
83*5796c8dcSSimon Schubert {
84*5796c8dcSSimon Schubert   struct bsd_uthread_ops *ops = gdbarch_data (gdbarch, bsd_uthread_data);
85*5796c8dcSSimon Schubert   ops->collect_uthread = collect_uthread;
86*5796c8dcSSimon Schubert }
87*5796c8dcSSimon Schubert 
88*5796c8dcSSimon Schubert /* Magic number to help recognize a valid thread structure.  */
89*5796c8dcSSimon Schubert #define BSD_UTHREAD_PTHREAD_MAGIC	0xd09ba115
90*5796c8dcSSimon Schubert 
91*5796c8dcSSimon Schubert /* Check whether the thread structure at ADDR is valid.  */
92*5796c8dcSSimon Schubert 
93*5796c8dcSSimon Schubert static void
94*5796c8dcSSimon Schubert bsd_uthread_check_magic (CORE_ADDR addr)
95*5796c8dcSSimon Schubert {
96*5796c8dcSSimon Schubert   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
97*5796c8dcSSimon Schubert   ULONGEST magic = read_memory_unsigned_integer (addr, 4, byte_order);
98*5796c8dcSSimon Schubert 
99*5796c8dcSSimon Schubert   if (magic != BSD_UTHREAD_PTHREAD_MAGIC)
100*5796c8dcSSimon Schubert     error (_("Bad magic"));
101*5796c8dcSSimon Schubert }
102*5796c8dcSSimon Schubert 
103*5796c8dcSSimon Schubert /* Thread states.  */
104*5796c8dcSSimon Schubert #define BSD_UTHREAD_PS_RUNNING	0
105*5796c8dcSSimon Schubert #define BSD_UTHREAD_PS_DEAD	18
106*5796c8dcSSimon Schubert 
107*5796c8dcSSimon Schubert /* Address of the pointer to the the thread structure for the running
108*5796c8dcSSimon Schubert    thread.  */
109*5796c8dcSSimon Schubert static CORE_ADDR bsd_uthread_thread_run_addr;
110*5796c8dcSSimon Schubert 
111*5796c8dcSSimon Schubert /* Address of the list of all threads.  */
112*5796c8dcSSimon Schubert static CORE_ADDR bsd_uthread_thread_list_addr;
113*5796c8dcSSimon Schubert 
114*5796c8dcSSimon Schubert /* Offsets of various "interesting" bits in the thread structure.  */
115*5796c8dcSSimon Schubert static int bsd_uthread_thread_state_offset = -1;
116*5796c8dcSSimon Schubert static int bsd_uthread_thread_next_offset = -1;
117*5796c8dcSSimon Schubert static int bsd_uthread_thread_ctx_offset;
118*5796c8dcSSimon Schubert 
119*5796c8dcSSimon Schubert /* Name of shared threads library.  */
120*5796c8dcSSimon Schubert static const char *bsd_uthread_solib_name;
121*5796c8dcSSimon Schubert 
122*5796c8dcSSimon Schubert /* Non-zero if the thread startum implemented by this module is active.  */
123*5796c8dcSSimon Schubert static int bsd_uthread_active;
124*5796c8dcSSimon Schubert 
125*5796c8dcSSimon Schubert static CORE_ADDR
126*5796c8dcSSimon Schubert bsd_uthread_lookup_address (const char *name, struct objfile *objfile)
127*5796c8dcSSimon Schubert {
128*5796c8dcSSimon Schubert   struct minimal_symbol *sym;
129*5796c8dcSSimon Schubert 
130*5796c8dcSSimon Schubert   sym = lookup_minimal_symbol (name, NULL, objfile);
131*5796c8dcSSimon Schubert   if (sym)
132*5796c8dcSSimon Schubert     return SYMBOL_VALUE_ADDRESS (sym);
133*5796c8dcSSimon Schubert 
134*5796c8dcSSimon Schubert   return 0;
135*5796c8dcSSimon Schubert }
136*5796c8dcSSimon Schubert 
137*5796c8dcSSimon Schubert static int
138*5796c8dcSSimon Schubert bsd_uthread_lookup_offset (const char *name, struct objfile *objfile)
139*5796c8dcSSimon Schubert {
140*5796c8dcSSimon Schubert   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
141*5796c8dcSSimon Schubert   CORE_ADDR addr;
142*5796c8dcSSimon Schubert 
143*5796c8dcSSimon Schubert   addr = bsd_uthread_lookup_address (name, objfile);
144*5796c8dcSSimon Schubert   if (addr == 0)
145*5796c8dcSSimon Schubert     return 0;
146*5796c8dcSSimon Schubert 
147*5796c8dcSSimon Schubert   return read_memory_unsigned_integer (addr, 4, byte_order);
148*5796c8dcSSimon Schubert }
149*5796c8dcSSimon Schubert 
150*5796c8dcSSimon Schubert static CORE_ADDR
151*5796c8dcSSimon Schubert bsd_uthread_read_memory_address (CORE_ADDR addr)
152*5796c8dcSSimon Schubert {
153*5796c8dcSSimon Schubert   struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
154*5796c8dcSSimon Schubert   return read_memory_typed_address (addr, ptr_type);
155*5796c8dcSSimon Schubert }
156*5796c8dcSSimon Schubert 
157*5796c8dcSSimon Schubert /* If OBJFILE contains the symbols corresponding to one of the
158*5796c8dcSSimon Schubert    supported user-level threads libraries, activate the thread stratum
159*5796c8dcSSimon Schubert    implemented by this module.  */
160*5796c8dcSSimon Schubert 
161*5796c8dcSSimon Schubert static int
162*5796c8dcSSimon Schubert bsd_uthread_activate (struct objfile *objfile)
163*5796c8dcSSimon Schubert {
164*5796c8dcSSimon Schubert   struct gdbarch *gdbarch = target_gdbarch;
165*5796c8dcSSimon Schubert   struct bsd_uthread_ops *ops = gdbarch_data (gdbarch, bsd_uthread_data);
166*5796c8dcSSimon Schubert 
167*5796c8dcSSimon Schubert   /* Skip if the thread stratum has already been activated.  */
168*5796c8dcSSimon Schubert   if (bsd_uthread_active)
169*5796c8dcSSimon Schubert     return 0;
170*5796c8dcSSimon Schubert 
171*5796c8dcSSimon Schubert   /* There's no point in enabling this module if no
172*5796c8dcSSimon Schubert      architecture-specific operations are provided.  */
173*5796c8dcSSimon Schubert   if (!ops->supply_uthread)
174*5796c8dcSSimon Schubert     return 0;
175*5796c8dcSSimon Schubert 
176*5796c8dcSSimon Schubert   bsd_uthread_thread_run_addr =
177*5796c8dcSSimon Schubert     bsd_uthread_lookup_address ("_thread_run", objfile);
178*5796c8dcSSimon Schubert   if (bsd_uthread_thread_run_addr == 0)
179*5796c8dcSSimon Schubert     return 0;
180*5796c8dcSSimon Schubert 
181*5796c8dcSSimon Schubert   bsd_uthread_thread_list_addr =
182*5796c8dcSSimon Schubert     bsd_uthread_lookup_address ("_thread_list", objfile);
183*5796c8dcSSimon Schubert   if (bsd_uthread_thread_list_addr == 0)
184*5796c8dcSSimon Schubert     return 0;
185*5796c8dcSSimon Schubert 
186*5796c8dcSSimon Schubert   bsd_uthread_thread_state_offset =
187*5796c8dcSSimon Schubert     bsd_uthread_lookup_offset ("_thread_state_offset", objfile);
188*5796c8dcSSimon Schubert   if (bsd_uthread_thread_state_offset == 0)
189*5796c8dcSSimon Schubert     return 0;
190*5796c8dcSSimon Schubert 
191*5796c8dcSSimon Schubert   bsd_uthread_thread_next_offset =
192*5796c8dcSSimon Schubert     bsd_uthread_lookup_offset ("_thread_next_offset", objfile);
193*5796c8dcSSimon Schubert   if (bsd_uthread_thread_next_offset == 0)
194*5796c8dcSSimon Schubert     return 0;
195*5796c8dcSSimon Schubert 
196*5796c8dcSSimon Schubert   bsd_uthread_thread_ctx_offset =
197*5796c8dcSSimon Schubert     bsd_uthread_lookup_offset ("_thread_ctx_offset", objfile);
198*5796c8dcSSimon Schubert 
199*5796c8dcSSimon Schubert   push_target (bsd_uthread_ops_hack);
200*5796c8dcSSimon Schubert   bsd_uthread_active = 1;
201*5796c8dcSSimon Schubert   return 1;
202*5796c8dcSSimon Schubert }
203*5796c8dcSSimon Schubert 
204*5796c8dcSSimon Schubert /* Cleanup due to deactivation.  */
205*5796c8dcSSimon Schubert 
206*5796c8dcSSimon Schubert static void
207*5796c8dcSSimon Schubert bsd_uthread_close (int quitting)
208*5796c8dcSSimon Schubert {
209*5796c8dcSSimon Schubert   bsd_uthread_active = 0;
210*5796c8dcSSimon Schubert   bsd_uthread_thread_run_addr = 0;
211*5796c8dcSSimon Schubert   bsd_uthread_thread_list_addr = 0;
212*5796c8dcSSimon Schubert   bsd_uthread_thread_state_offset = 0;
213*5796c8dcSSimon Schubert   bsd_uthread_thread_next_offset = 0;
214*5796c8dcSSimon Schubert   bsd_uthread_thread_ctx_offset = 0;
215*5796c8dcSSimon Schubert   bsd_uthread_solib_name = NULL;
216*5796c8dcSSimon Schubert }
217*5796c8dcSSimon Schubert 
218*5796c8dcSSimon Schubert /* Deactivate the thread stratum implemented by this module.  */
219*5796c8dcSSimon Schubert 
220*5796c8dcSSimon Schubert static void
221*5796c8dcSSimon Schubert bsd_uthread_deactivate (void)
222*5796c8dcSSimon Schubert {
223*5796c8dcSSimon Schubert   /* Skip if the thread stratum has already been deactivated.  */
224*5796c8dcSSimon Schubert   if (!bsd_uthread_active)
225*5796c8dcSSimon Schubert     return;
226*5796c8dcSSimon Schubert 
227*5796c8dcSSimon Schubert   unpush_target (bsd_uthread_ops_hack);
228*5796c8dcSSimon Schubert }
229*5796c8dcSSimon Schubert 
230*5796c8dcSSimon Schubert static void
231*5796c8dcSSimon Schubert bsd_uthread_inferior_created (struct target_ops *ops, int from_tty)
232*5796c8dcSSimon Schubert {
233*5796c8dcSSimon Schubert   bsd_uthread_activate (NULL);
234*5796c8dcSSimon Schubert }
235*5796c8dcSSimon Schubert 
236*5796c8dcSSimon Schubert /* Likely candidates for the threads library.  */
237*5796c8dcSSimon Schubert static const char *bsd_uthread_solib_names[] =
238*5796c8dcSSimon Schubert {
239*5796c8dcSSimon Schubert   "/usr/lib/libc_r.so",		/* FreeBSD */
240*5796c8dcSSimon Schubert   "/usr/lib/libpthread.so",	/* OpenBSD */
241*5796c8dcSSimon Schubert   NULL
242*5796c8dcSSimon Schubert };
243*5796c8dcSSimon Schubert 
244*5796c8dcSSimon Schubert static void
245*5796c8dcSSimon Schubert bsd_uthread_solib_loaded (struct so_list *so)
246*5796c8dcSSimon Schubert {
247*5796c8dcSSimon Schubert   const char **names = bsd_uthread_solib_names;
248*5796c8dcSSimon Schubert 
249*5796c8dcSSimon Schubert   for (names = bsd_uthread_solib_names; *names; names++)
250*5796c8dcSSimon Schubert     {
251*5796c8dcSSimon Schubert       if (strncmp (so->so_original_name, *names, strlen (*names)) == 0)
252*5796c8dcSSimon Schubert 	{
253*5796c8dcSSimon Schubert 	  solib_read_symbols (so, so->from_tty ? SYMFILE_VERBOSE : 0);
254*5796c8dcSSimon Schubert 
255*5796c8dcSSimon Schubert 	  if (bsd_uthread_activate (so->objfile))
256*5796c8dcSSimon Schubert 	    {
257*5796c8dcSSimon Schubert 	      bsd_uthread_solib_name = so->so_original_name;
258*5796c8dcSSimon Schubert 	      return;
259*5796c8dcSSimon Schubert 	    }
260*5796c8dcSSimon Schubert 	}
261*5796c8dcSSimon Schubert     }
262*5796c8dcSSimon Schubert }
263*5796c8dcSSimon Schubert 
264*5796c8dcSSimon Schubert static void
265*5796c8dcSSimon Schubert bsd_uthread_solib_unloaded (struct so_list *so)
266*5796c8dcSSimon Schubert {
267*5796c8dcSSimon Schubert   if (!bsd_uthread_solib_name)
268*5796c8dcSSimon Schubert     return;
269*5796c8dcSSimon Schubert 
270*5796c8dcSSimon Schubert   if (strcmp (so->so_original_name, bsd_uthread_solib_name) == 0)
271*5796c8dcSSimon Schubert     bsd_uthread_deactivate ();
272*5796c8dcSSimon Schubert }
273*5796c8dcSSimon Schubert 
274*5796c8dcSSimon Schubert static void
275*5796c8dcSSimon Schubert bsd_uthread_mourn_inferior (struct target_ops *ops)
276*5796c8dcSSimon Schubert {
277*5796c8dcSSimon Schubert   struct target_ops *beneath = find_target_beneath (ops);
278*5796c8dcSSimon Schubert   beneath->to_mourn_inferior (beneath);
279*5796c8dcSSimon Schubert   bsd_uthread_deactivate ();
280*5796c8dcSSimon Schubert }
281*5796c8dcSSimon Schubert 
282*5796c8dcSSimon Schubert static void
283*5796c8dcSSimon Schubert bsd_uthread_fetch_registers (struct target_ops *ops,
284*5796c8dcSSimon Schubert 			     struct regcache *regcache, int regnum)
285*5796c8dcSSimon Schubert {
286*5796c8dcSSimon Schubert   struct gdbarch *gdbarch = get_regcache_arch (regcache);
287*5796c8dcSSimon Schubert   struct bsd_uthread_ops *uthread_ops = gdbarch_data (gdbarch, bsd_uthread_data);
288*5796c8dcSSimon Schubert   CORE_ADDR addr = ptid_get_tid (inferior_ptid);
289*5796c8dcSSimon Schubert   struct target_ops *beneath = find_target_beneath (ops);
290*5796c8dcSSimon Schubert   CORE_ADDR active_addr;
291*5796c8dcSSimon Schubert 
292*5796c8dcSSimon Schubert   /* Always fetch the appropriate registers from the layer beneath.  */
293*5796c8dcSSimon Schubert   beneath->to_fetch_registers (beneath, regcache, regnum);
294*5796c8dcSSimon Schubert 
295*5796c8dcSSimon Schubert   /* FIXME: That might have gotten us more than we asked for.  Make
296*5796c8dcSSimon Schubert      sure we overwrite all relevant registers with values from the
297*5796c8dcSSimon Schubert      thread structure.  This can go once we fix the underlying target.  */
298*5796c8dcSSimon Schubert   regnum = -1;
299*5796c8dcSSimon Schubert 
300*5796c8dcSSimon Schubert   active_addr = bsd_uthread_read_memory_address (bsd_uthread_thread_run_addr);
301*5796c8dcSSimon Schubert   if (addr != 0 && addr != active_addr)
302*5796c8dcSSimon Schubert     {
303*5796c8dcSSimon Schubert       bsd_uthread_check_magic (addr);
304*5796c8dcSSimon Schubert       uthread_ops->supply_uthread (regcache, regnum,
305*5796c8dcSSimon Schubert 				   addr + bsd_uthread_thread_ctx_offset);
306*5796c8dcSSimon Schubert     }
307*5796c8dcSSimon Schubert }
308*5796c8dcSSimon Schubert 
309*5796c8dcSSimon Schubert static void
310*5796c8dcSSimon Schubert bsd_uthread_store_registers (struct target_ops *ops,
311*5796c8dcSSimon Schubert 			     struct regcache *regcache, int regnum)
312*5796c8dcSSimon Schubert {
313*5796c8dcSSimon Schubert   struct gdbarch *gdbarch = get_regcache_arch (regcache);
314*5796c8dcSSimon Schubert   struct bsd_uthread_ops *uthread_ops = gdbarch_data (gdbarch, bsd_uthread_data);
315*5796c8dcSSimon Schubert   struct target_ops *beneath = find_target_beneath (ops);
316*5796c8dcSSimon Schubert   CORE_ADDR addr = ptid_get_tid (inferior_ptid);
317*5796c8dcSSimon Schubert   CORE_ADDR active_addr;
318*5796c8dcSSimon Schubert 
319*5796c8dcSSimon Schubert   active_addr = bsd_uthread_read_memory_address (bsd_uthread_thread_run_addr);
320*5796c8dcSSimon Schubert   if (addr != 0 && addr != active_addr)
321*5796c8dcSSimon Schubert     {
322*5796c8dcSSimon Schubert       bsd_uthread_check_magic (addr);
323*5796c8dcSSimon Schubert       uthread_ops->collect_uthread (regcache, regnum,
324*5796c8dcSSimon Schubert 				    addr + bsd_uthread_thread_ctx_offset);
325*5796c8dcSSimon Schubert     }
326*5796c8dcSSimon Schubert   else
327*5796c8dcSSimon Schubert     {
328*5796c8dcSSimon Schubert       /* Updating the thread that is currently running; pass the
329*5796c8dcSSimon Schubert          request to the layer beneath.  */
330*5796c8dcSSimon Schubert       beneath->to_store_registers (beneath, regcache, regnum);
331*5796c8dcSSimon Schubert     }
332*5796c8dcSSimon Schubert }
333*5796c8dcSSimon Schubert 
334*5796c8dcSSimon Schubert /* FIXME: This function is only there because otherwise GDB tries to
335*5796c8dcSSimon Schubert    invoke deprecate_xfer_memory.  */
336*5796c8dcSSimon Schubert 
337*5796c8dcSSimon Schubert static LONGEST
338*5796c8dcSSimon Schubert bsd_uthread_xfer_partial (struct target_ops *ops, enum target_object object,
339*5796c8dcSSimon Schubert 			  const char *annex, gdb_byte *readbuf,
340*5796c8dcSSimon Schubert 			  const gdb_byte *writebuf,
341*5796c8dcSSimon Schubert 			  ULONGEST offset, LONGEST len)
342*5796c8dcSSimon Schubert {
343*5796c8dcSSimon Schubert   gdb_assert (ops->beneath->to_xfer_partial);
344*5796c8dcSSimon Schubert   return ops->beneath->to_xfer_partial (ops->beneath, object, annex, readbuf,
345*5796c8dcSSimon Schubert 					writebuf, offset, len);
346*5796c8dcSSimon Schubert }
347*5796c8dcSSimon Schubert 
348*5796c8dcSSimon Schubert static ptid_t
349*5796c8dcSSimon Schubert bsd_uthread_wait (struct target_ops *ops,
350*5796c8dcSSimon Schubert 		  ptid_t ptid, struct target_waitstatus *status, int options)
351*5796c8dcSSimon Schubert {
352*5796c8dcSSimon Schubert   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
353*5796c8dcSSimon Schubert   CORE_ADDR addr;
354*5796c8dcSSimon Schubert   struct target_ops *beneath = find_target_beneath (ops);
355*5796c8dcSSimon Schubert 
356*5796c8dcSSimon Schubert   /* Pass the request to the layer beneath.  */
357*5796c8dcSSimon Schubert   ptid = beneath->to_wait (beneath, ptid, status, options);
358*5796c8dcSSimon Schubert 
359*5796c8dcSSimon Schubert   /* If the process is no longer alive, there's no point in figuring
360*5796c8dcSSimon Schubert      out the thread ID.  It will fail anyway.  */
361*5796c8dcSSimon Schubert   if (status->kind == TARGET_WAITKIND_SIGNALLED
362*5796c8dcSSimon Schubert       || status->kind == TARGET_WAITKIND_EXITED)
363*5796c8dcSSimon Schubert     return ptid;
364*5796c8dcSSimon Schubert 
365*5796c8dcSSimon Schubert   /* Fetch the corresponding thread ID, and augment the returned
366*5796c8dcSSimon Schubert      process ID with it.  */
367*5796c8dcSSimon Schubert   addr = bsd_uthread_read_memory_address (bsd_uthread_thread_run_addr);
368*5796c8dcSSimon Schubert   if (addr != 0)
369*5796c8dcSSimon Schubert     {
370*5796c8dcSSimon Schubert       gdb_byte buf[4];
371*5796c8dcSSimon Schubert 
372*5796c8dcSSimon Schubert       /* FIXME: For executables linked statically with the threads
373*5796c8dcSSimon Schubert          library, we end up here before the program has actually been
374*5796c8dcSSimon Schubert          executed.  In that case ADDR will be garbage since it has
375*5796c8dcSSimon Schubert          been read from the wrong virtual memory image.  */
376*5796c8dcSSimon Schubert       if (target_read_memory (addr, buf, 4) == 0)
377*5796c8dcSSimon Schubert 	{
378*5796c8dcSSimon Schubert 	  ULONGEST magic = extract_unsigned_integer (buf, 4, byte_order);
379*5796c8dcSSimon Schubert 	  if (magic == BSD_UTHREAD_PTHREAD_MAGIC)
380*5796c8dcSSimon Schubert 	    ptid = ptid_build (ptid_get_pid (ptid), 0, addr);
381*5796c8dcSSimon Schubert 	}
382*5796c8dcSSimon Schubert     }
383*5796c8dcSSimon Schubert 
384*5796c8dcSSimon Schubert   /* If INFERIOR_PTID doesn't have a tid member yet, and we now have a
385*5796c8dcSSimon Schubert      ptid with tid set, then ptid is still the initial thread of
386*5796c8dcSSimon Schubert      the process.  Notify GDB core about it.  */
387*5796c8dcSSimon Schubert   if (ptid_get_tid (inferior_ptid) == 0
388*5796c8dcSSimon Schubert       && ptid_get_tid (ptid) != 0 && !in_thread_list (ptid))
389*5796c8dcSSimon Schubert     thread_change_ptid (inferior_ptid, ptid);
390*5796c8dcSSimon Schubert 
391*5796c8dcSSimon Schubert   /* Don't let the core see a ptid without a corresponding thread.  */
392*5796c8dcSSimon Schubert   if (!in_thread_list (ptid) || is_exited (ptid))
393*5796c8dcSSimon Schubert     add_thread (ptid);
394*5796c8dcSSimon Schubert 
395*5796c8dcSSimon Schubert   return ptid;
396*5796c8dcSSimon Schubert }
397*5796c8dcSSimon Schubert 
398*5796c8dcSSimon Schubert static void
399*5796c8dcSSimon Schubert bsd_uthread_resume (struct target_ops *ops,
400*5796c8dcSSimon Schubert 		    ptid_t ptid, int step, enum target_signal sig)
401*5796c8dcSSimon Schubert {
402*5796c8dcSSimon Schubert   /* Pass the request to the layer beneath.  */
403*5796c8dcSSimon Schubert   struct target_ops *beneath = find_target_beneath (ops);
404*5796c8dcSSimon Schubert   beneath->to_resume (beneath, ptid, step, sig);
405*5796c8dcSSimon Schubert }
406*5796c8dcSSimon Schubert 
407*5796c8dcSSimon Schubert static int
408*5796c8dcSSimon Schubert bsd_uthread_thread_alive (struct target_ops *ops, ptid_t ptid)
409*5796c8dcSSimon Schubert {
410*5796c8dcSSimon Schubert   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
411*5796c8dcSSimon Schubert   struct target_ops *beneath = find_target_beneath (ops);
412*5796c8dcSSimon Schubert   CORE_ADDR addr = ptid_get_tid (inferior_ptid);
413*5796c8dcSSimon Schubert 
414*5796c8dcSSimon Schubert   if (addr != 0)
415*5796c8dcSSimon Schubert     {
416*5796c8dcSSimon Schubert       int offset = bsd_uthread_thread_state_offset;
417*5796c8dcSSimon Schubert       ULONGEST state;
418*5796c8dcSSimon Schubert 
419*5796c8dcSSimon Schubert       bsd_uthread_check_magic (addr);
420*5796c8dcSSimon Schubert 
421*5796c8dcSSimon Schubert       state = read_memory_unsigned_integer (addr + offset, 4, byte_order);
422*5796c8dcSSimon Schubert       if (state == BSD_UTHREAD_PS_DEAD)
423*5796c8dcSSimon Schubert 	return 0;
424*5796c8dcSSimon Schubert     }
425*5796c8dcSSimon Schubert 
426*5796c8dcSSimon Schubert   return beneath->to_thread_alive (beneath, ptid);
427*5796c8dcSSimon Schubert }
428*5796c8dcSSimon Schubert 
429*5796c8dcSSimon Schubert static void
430*5796c8dcSSimon Schubert bsd_uthread_find_new_threads (struct target_ops *ops)
431*5796c8dcSSimon Schubert {
432*5796c8dcSSimon Schubert   pid_t pid = ptid_get_pid (inferior_ptid);
433*5796c8dcSSimon Schubert   int offset = bsd_uthread_thread_next_offset;
434*5796c8dcSSimon Schubert   CORE_ADDR addr;
435*5796c8dcSSimon Schubert 
436*5796c8dcSSimon Schubert   addr = bsd_uthread_read_memory_address (bsd_uthread_thread_list_addr);
437*5796c8dcSSimon Schubert   while (addr != 0)
438*5796c8dcSSimon Schubert     {
439*5796c8dcSSimon Schubert       ptid_t ptid = ptid_build (pid, 0, addr);
440*5796c8dcSSimon Schubert 
441*5796c8dcSSimon Schubert       if (!in_thread_list (ptid) || is_exited (ptid))
442*5796c8dcSSimon Schubert 	{
443*5796c8dcSSimon Schubert 	  /* If INFERIOR_PTID doesn't have a tid member yet, then ptid
444*5796c8dcSSimon Schubert 	     is still the initial thread of the process.  Notify GDB
445*5796c8dcSSimon Schubert 	     core about it.  */
446*5796c8dcSSimon Schubert 	  if (ptid_get_tid (inferior_ptid) == 0)
447*5796c8dcSSimon Schubert 	    thread_change_ptid (inferior_ptid, ptid);
448*5796c8dcSSimon Schubert 	  else
449*5796c8dcSSimon Schubert 	    add_thread (ptid);
450*5796c8dcSSimon Schubert 	}
451*5796c8dcSSimon Schubert 
452*5796c8dcSSimon Schubert       addr = bsd_uthread_read_memory_address (addr + offset);
453*5796c8dcSSimon Schubert     }
454*5796c8dcSSimon Schubert }
455*5796c8dcSSimon Schubert 
456*5796c8dcSSimon Schubert /* Possible states a thread can be in.  */
457*5796c8dcSSimon Schubert static char *bsd_uthread_state[] =
458*5796c8dcSSimon Schubert {
459*5796c8dcSSimon Schubert   "RUNNING",
460*5796c8dcSSimon Schubert   "SIGTHREAD",
461*5796c8dcSSimon Schubert   "MUTEX_WAIT",
462*5796c8dcSSimon Schubert   "COND_WAIT",
463*5796c8dcSSimon Schubert   "FDLR_WAIT",
464*5796c8dcSSimon Schubert   "FDLW_WAIT",
465*5796c8dcSSimon Schubert   "FDR_WAIT",
466*5796c8dcSSimon Schubert   "FDW_WAIT",
467*5796c8dcSSimon Schubert   "FILE_WAIT",
468*5796c8dcSSimon Schubert   "POLL_WAIT",
469*5796c8dcSSimon Schubert   "SELECT_WAIT",
470*5796c8dcSSimon Schubert   "SLEEP_WAIT",
471*5796c8dcSSimon Schubert   "WAIT_WAIT",
472*5796c8dcSSimon Schubert   "SIGSUSPEND",
473*5796c8dcSSimon Schubert   "SIGWAIT",
474*5796c8dcSSimon Schubert   "SPINBLOCK",
475*5796c8dcSSimon Schubert   "JOIN",
476*5796c8dcSSimon Schubert   "SUSPENDED",
477*5796c8dcSSimon Schubert   "DEAD",
478*5796c8dcSSimon Schubert   "DEADLOCK"
479*5796c8dcSSimon Schubert };
480*5796c8dcSSimon Schubert 
481*5796c8dcSSimon Schubert /* Return a string describing th state of the thread specified by
482*5796c8dcSSimon Schubert    INFO.  */
483*5796c8dcSSimon Schubert 
484*5796c8dcSSimon Schubert static char *
485*5796c8dcSSimon Schubert bsd_uthread_extra_thread_info (struct thread_info *info)
486*5796c8dcSSimon Schubert {
487*5796c8dcSSimon Schubert   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
488*5796c8dcSSimon Schubert   CORE_ADDR addr = ptid_get_tid (info->ptid);
489*5796c8dcSSimon Schubert 
490*5796c8dcSSimon Schubert   if (addr != 0)
491*5796c8dcSSimon Schubert     {
492*5796c8dcSSimon Schubert       int offset = bsd_uthread_thread_state_offset;
493*5796c8dcSSimon Schubert       ULONGEST state;
494*5796c8dcSSimon Schubert 
495*5796c8dcSSimon Schubert       state = read_memory_unsigned_integer (addr + offset, 4, byte_order);
496*5796c8dcSSimon Schubert       if (state < ARRAY_SIZE (bsd_uthread_state))
497*5796c8dcSSimon Schubert 	return bsd_uthread_state[state];
498*5796c8dcSSimon Schubert     }
499*5796c8dcSSimon Schubert 
500*5796c8dcSSimon Schubert   return NULL;
501*5796c8dcSSimon Schubert }
502*5796c8dcSSimon Schubert 
503*5796c8dcSSimon Schubert static char *
504*5796c8dcSSimon Schubert bsd_uthread_pid_to_str (struct target_ops *ops, ptid_t ptid)
505*5796c8dcSSimon Schubert {
506*5796c8dcSSimon Schubert   if (ptid_get_tid (ptid) != 0)
507*5796c8dcSSimon Schubert     {
508*5796c8dcSSimon Schubert       static char buf[64];
509*5796c8dcSSimon Schubert 
510*5796c8dcSSimon Schubert       xsnprintf (buf, sizeof buf, "process %d, thread 0x%lx",
511*5796c8dcSSimon Schubert 		 ptid_get_pid (ptid), ptid_get_tid (ptid));
512*5796c8dcSSimon Schubert       return buf;
513*5796c8dcSSimon Schubert     }
514*5796c8dcSSimon Schubert 
515*5796c8dcSSimon Schubert   return normal_pid_to_str (ptid);
516*5796c8dcSSimon Schubert }
517*5796c8dcSSimon Schubert 
518*5796c8dcSSimon Schubert static struct target_ops *
519*5796c8dcSSimon Schubert bsd_uthread_target (void)
520*5796c8dcSSimon Schubert {
521*5796c8dcSSimon Schubert   struct target_ops *t = XZALLOC (struct target_ops);
522*5796c8dcSSimon Schubert 
523*5796c8dcSSimon Schubert   t->to_shortname = "bsd-uthreads";
524*5796c8dcSSimon Schubert   t->to_longname = "BSD user-level threads";
525*5796c8dcSSimon Schubert   t->to_doc = "BSD user-level threads";
526*5796c8dcSSimon Schubert   t->to_close = bsd_uthread_close;
527*5796c8dcSSimon Schubert   t->to_mourn_inferior = bsd_uthread_mourn_inferior;
528*5796c8dcSSimon Schubert   t->to_fetch_registers = bsd_uthread_fetch_registers;
529*5796c8dcSSimon Schubert   t->to_store_registers = bsd_uthread_store_registers;
530*5796c8dcSSimon Schubert   t->to_xfer_partial = bsd_uthread_xfer_partial;
531*5796c8dcSSimon Schubert   t->to_wait = bsd_uthread_wait;
532*5796c8dcSSimon Schubert   t->to_resume = bsd_uthread_resume;
533*5796c8dcSSimon Schubert   t->to_thread_alive = bsd_uthread_thread_alive;
534*5796c8dcSSimon Schubert   t->to_find_new_threads = bsd_uthread_find_new_threads;
535*5796c8dcSSimon Schubert   t->to_extra_thread_info = bsd_uthread_extra_thread_info;
536*5796c8dcSSimon Schubert   t->to_pid_to_str = bsd_uthread_pid_to_str;
537*5796c8dcSSimon Schubert   t->to_stratum = thread_stratum;
538*5796c8dcSSimon Schubert   t->to_magic = OPS_MAGIC;
539*5796c8dcSSimon Schubert   bsd_uthread_ops_hack = t;
540*5796c8dcSSimon Schubert 
541*5796c8dcSSimon Schubert   return t;
542*5796c8dcSSimon Schubert }
543*5796c8dcSSimon Schubert 
544*5796c8dcSSimon Schubert /* Provide a prototype to silence -Wmissing-prototypes.  */
545*5796c8dcSSimon Schubert extern initialize_file_ftype _initialize_bsd_uthread;
546*5796c8dcSSimon Schubert 
547*5796c8dcSSimon Schubert void
548*5796c8dcSSimon Schubert _initialize_bsd_uthread (void)
549*5796c8dcSSimon Schubert {
550*5796c8dcSSimon Schubert   add_target (bsd_uthread_target ());
551*5796c8dcSSimon Schubert 
552*5796c8dcSSimon Schubert   bsd_uthread_data = gdbarch_data_register_pre_init (bsd_uthread_init);
553*5796c8dcSSimon Schubert 
554*5796c8dcSSimon Schubert   observer_attach_inferior_created (bsd_uthread_inferior_created);
555*5796c8dcSSimon Schubert   observer_attach_solib_loaded (bsd_uthread_solib_loaded);
556*5796c8dcSSimon Schubert   observer_attach_solib_unloaded (bsd_uthread_solib_unloaded);
557*5796c8dcSSimon Schubert }
558