1 /* Copyright (C) 1999, 2001 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3 
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8 
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.  */
18 
19 #ifndef _THREAD_DB_H
20 #define _THREAD_DB_H	1
21 
22 /* This is the debugger interface for the LinuxThreads library.  It is
23    modelled closely after the interface with same names in Solaris with
24    the goal to share the same code in the debugger.  */
25 #include <pthread.h>
26 #include <stdint.h>
27 #include <sys/types.h>
28 #include <sys/procfs.h>
29 
30 
31 /* Error codes of the library.  */
32 typedef enum
33 {
34   TD_OK,	  /* No error.  */
35   TD_ERR,	  /* No further specified error.  */
36   TD_NOTHR,	  /* No matching thread found.  */
37   TD_NOSV,	  /* No matching synchronization handle found.  */
38   TD_NOLWP,	  /* No matching light-weighted process found.  */
39   TD_BADPH,	  /* Invalid process handle.  */
40   TD_BADTH,	  /* Invalid thread handle.  */
41   TD_BADSH,	  /* Invalid synchronization handle.  */
42   TD_BADTA,	  /* Invalid thread agent.  */
43   TD_BADKEY,	  /* Invalid key.  */
44   TD_NOMSG,	  /* No event available.  */
45   TD_NOFPREGS,	  /* No floating-point register content available.  */
46   TD_NOLIBTHREAD, /* Application not linked with thread library.  */
47   TD_NOEVENT,	  /* Requested event is not supported.  */
48   TD_NOCAPAB,	  /* Capability not available.  */
49   TD_DBERR,	  /* Internal debug library error.  */
50   TD_NOAPLIC,	  /* Operation is not applicable.  */
51   TD_NOTSD,	  /* No thread-specific data available.  */
52   TD_MALLOC,	  /* Out of memory.  */
53   TD_PARTIALREG,  /* Not entire register set was read or written.  */
54   TD_NOXREGS	  /* X register set not available for given thread.  */
55 } td_err_e;
56 
57 
58 /* Possible thread states.  TD_THR_ANY_STATE is a pseudo-state used to
59    select threads regardless of state in td_ta_thr_iter().  */
60 typedef enum
61 {
62   TD_THR_ANY_STATE,
63   TD_THR_UNKNOWN,
64   TD_THR_STOPPED,
65   TD_THR_RUN,
66   TD_THR_ACTIVE,
67   TD_THR_ZOMBIE,
68   TD_THR_SLEEP,
69   TD_THR_STOPPED_ASLEEP
70 } td_thr_state_e;
71 
72 /* Thread type: user or system.  TD_THR_ANY_TYPE is a pseudo-type used
73    to select threads regardless of type in td_ta_thr_iter().  */
74 typedef enum
75 {
76   TD_THR_ANY_TYPE,
77   TD_THR_USER,
78   TD_THR_SYSTEM
79 } td_thr_type_e;
80 
81 
82 /* Types of the debugging library.  */
83 
84 /* Handle for a process.  This type is opaque.  */
85 typedef struct td_thragent td_thragent_t;
86 
87 /* The actual thread handle type.  This is also opaque.  */
88 typedef struct td_thrhandle
89 {
90   td_thragent_t *th_ta_p;
91   psaddr_t th_unique;
92 } td_thrhandle_t;
93 
94 
95 /* Flags for `td_ta_thr_iter'.  */
96 #define TD_THR_ANY_USER_FLAGS	0xffffffff
97 #define TD_THR_LOWEST_PRIORITY	-20
98 #define TD_SIGNO_MASK		NULL
99 
100 
101 #define TD_EVENTSIZE	2
102 #define BT_UISHIFT	5 /* log base 2 of BT_NBIPUI, to extract word index */
103 #define BT_NBIPUI	(1 << BT_UISHIFT)       /* n bits per uint */
104 #define BT_UIMASK	(BT_NBIPUI - 1)         /* to extract bit index */
105 
106 /* Bitmask of enabled events. */
107 typedef struct td_thr_events
108 {
109   uint32_t event_bits[TD_EVENTSIZE];
110 } td_thr_events_t;
111 
112 /* Event set manipulation macros. */
113 #define __td_eventmask(n) \
114   (UINT32_C (1) << (((n) - 1) & BT_UIMASK))
115 #define __td_eventword(n) \
116   ((UINT32_C ((n) - 1)) >> BT_UISHIFT)
117 
118 #define td_event_emptyset(setp) \
119   do {									      \
120     int __i;								      \
121     for (__i = TD_EVENTSIZE; __i > 0; --__i)				      \
122       (setp)->event_bits[__i - 1] = 0;					      \
123   } while (0)
124 
125 #define td_event_fillset(setp) \
126   do {									      \
127     int __i;								      \
128     for (__i = TD_EVENTSIZE; __i > 0; --__i)				      \
129       (setp)->event_bits[__i - 1] = UINT32_C (0xffffffff);		      \
130   } while (0)
131 
132 #define td_event_addset(setp, n) \
133   (((setp)->event_bits[__td_eventword (n)]) |= __td_eventmask (n))
134 #define td_event_delset(setp, n) \
135   (((setp)->event_bits[__td_eventword (n)]) &= ~__td_eventmask (n))
136 #define td_eventismember(setp, n) \
137   (__td_eventmask (n) & ((setp)->event_bits[__td_eventword (n)]))
138 #if TD_EVENTSIZE == 2
139 # define td_eventisempty(setp) \
140   (!((setp)->event_bits[0]) && !((setp)->event_bits[1]))
141 #else
142 # error "td_eventisempty must be changed to match TD_EVENTSIZE"
143 #endif
144 
145 /* Events reportable by the thread implementation.  */
146 typedef enum
147 {
148   TD_ALL_EVENTS,		 /* Pseudo-event number.  */
149   TD_EVENT_NONE = TD_ALL_EVENTS, /* Depends on context.  */
150   TD_READY,			 /* Is executable now. */
151   TD_SLEEP,			 /* Blocked in a synchronization obj.  */
152   TD_SWITCHTO,			 /* Now assigned to a process.  */
153   TD_SWITCHFROM,		 /* Not anymore assigned to a process.  */
154   TD_LOCK_TRY,			 /* Trying to get an unavailable lock.  */
155   TD_CATCHSIG,			 /* Signal posted to the thread.  */
156   TD_IDLE,			 /* Process getting idle.  */
157   TD_CREATE,			 /* New thread created.  */
158   TD_DEATH,			 /* Thread terminated.  */
159   TD_PREEMPT,			 /* Preempted.  */
160   TD_PRI_INHERIT,		 /* Inherited elevated priority.  */
161   TD_REAP,			 /* Reaped.  */
162   TD_CONCURRENCY,		 /* Number of processes changing.  */
163   TD_TIMEOUT,			 /* Conditional variable wait timed out.  */
164   TD_MIN_EVENT_NUM = TD_READY,
165   TD_MAX_EVENT_NUM = TD_TIMEOUT,
166   TD_EVENTS_ENABLE = 31		/* Event reporting enabled.  */
167 } td_event_e;
168 
169 /* Values representing the different ways events are reported.  */
170 typedef enum
171 {
172   NOTIFY_BPT,			/* User must insert breakpoint at u.bptaddr. */
173   NOTIFY_AUTOBPT,		/* Breakpoint at u.bptaddr is automatically
174 				   inserted.  */
175   NOTIFY_SYSCALL		/* System call u.syscallno will be invoked.  */
176 } td_notify_e;
177 
178 /* Description how event type is reported.  */
179 typedef struct td_notify
180 {
181   td_notify_e type;		/* Way the event is reported.  */
182   union
183   {
184     psaddr_t bptaddr;		/* Address of breakpoint.  */
185     int syscallno;		/* Number of system call used.  */
186   } u;
187 } td_notify_t;
188 
189 /* Structure used to report event.  */
190 typedef struct td_event_msg
191 {
192   td_event_e event;		/* Event type being reported.  */
193   const td_thrhandle_t *th_p;	/* Thread reporting the event.  */
194   union
195   {
196 # if 0
197     td_synchandle_t *sh;	/* Handle of synchronization object.  */
198 #endif
199     uintptr_t data;		/* Event specific data.  */
200   } msg;
201 } td_event_msg_t;
202 
203 /* Structure containing event data available in each thread structure.  */
204 typedef struct
205 {
206   td_thr_events_t eventmask;	/* Mask of enabled events.  */
207   td_event_e eventnum;		/* Number of last event.  */
208   void *eventdata;		/* Data associated with event.  */
209 } td_eventbuf_t;
210 
211 
212 /* Gathered statistics about the process.  */
213 typedef struct td_ta_stats
214 {
215   int nthreads;       		/* Total number of threads in use.  */
216   int r_concurrency;		/* Concurrency level requested by user.  */
217   int nrunnable_num;		/* Average runnable threads, numerator.  */
218   int nrunnable_den;		/* Average runnable threads, denominator.  */
219   int a_concurrency_num;	/* Achieved concurrency level, numerator.  */
220   int a_concurrency_den;	/* Achieved concurrency level, denominator.  */
221   int nlwps_num;		/* Average number of processes in use,
222 				   numerator.  */
223   int nlwps_den;		/* Average number of processes in use,
224 				   denominator.  */
225   int nidle_num;		/* Average number of idling processes,
226 				   numerator.  */
227   int nidle_den;		/* Average number of idling processes,
228 				   denominator.  */
229 } td_ta_stats_t;
230 
231 
232 /* Since Sun's library is based on Solaris threads we have to define a few
233    types to map them to POSIX threads.  */
234 typedef pthread_t thread_t;
235 typedef pthread_key_t thread_key_t;
236 
237 
238 /* Callback for iteration over threads.  */
239 typedef int td_thr_iter_f (const td_thrhandle_t *, void *);
240 
241 /* Callback for iteration over thread local data.  */
242 typedef int td_key_iter_f (thread_key_t, void (*) (void *), void *);
243 
244 
245 
246 /* Forward declaration.  This has to be defined by the user.  */
247 struct ps_prochandle;
248 
249 
250 /* Information about the thread.  */
251 typedef struct td_thrinfo
252 {
253   td_thragent_t *ti_ta_p;		/* Process handle.  */
254   unsigned int ti_user_flags;		/* Unused.  */
255   thread_t ti_tid;			/* Thread ID returned by
256 					   pthread_create().  */
257   char *ti_tls;				/* Pointer to thread-local data.  */
258   psaddr_t ti_startfunc;		/* Start function passed to
259 					   pthread_create().  */
260   psaddr_t ti_stkbase;			/* Base of thread's stack.  */
261   long int ti_stksize;			/* Size of thread's stack.  */
262   psaddr_t ti_ro_area;			/* Unused.  */
263   int ti_ro_size;			/* Unused.  */
264   td_thr_state_e ti_state;		/* Thread state.  */
265   unsigned char ti_db_suspended;	/* Nonzero if suspended by debugger. */
266   td_thr_type_e ti_type;		/* Type of the thread (system vs
267 					   user thread).  */
268   intptr_t ti_pc;			/* Unused.  */
269   intptr_t ti_sp;			/* Unused.  */
270   short int ti_flags;			/* Unused.  */
271   int ti_pri;				/* Thread priority.  */
272   lwpid_t ti_lid;			/* Unused.  */
273   sigset_t ti_sigmask;			/* Signal mask.  */
274   unsigned char ti_traceme;		/* Nonzero if event reporting
275 					   enabled.  */
276   unsigned char ti_preemptflag;		/* Unused.  */
277   unsigned char ti_pirecflag;		/* Unused.  */
278   sigset_t ti_pending;			/* Set of pending signals.  */
279   td_thr_events_t ti_events;		/* Set of enabled events.  */
280 } td_thrinfo_t;
281 
282 
283 
284 /* Prototypes for exported library functions.  */
285 
286 /* Initialize the thread debug support library.  */
287 extern td_err_e td_init (void);
288 
289 /* Historical relict.  Should not be used anymore.  */
290 extern td_err_e td_log (void);
291 
292 /* Return list of symbols the library can request.  */
293 extern const char **td_symbol_list (void);
294 
295 /* Generate new thread debug library handle for process PS.  */
296 extern td_err_e td_ta_new (struct ps_prochandle *__ps, td_thragent_t **__ta);
297 
298 /* Free resources allocated for TA.  */
299 extern td_err_e td_ta_delete (td_thragent_t *__ta);
300 
301 /* Get number of currently running threads in process associated with TA.  */
302 extern td_err_e td_ta_get_nthreads (const td_thragent_t *__ta, int *__np);
303 
304 /* Return process handle passed in `td_ta_new' for process associated with
305    TA.  */
306 extern td_err_e td_ta_get_ph (const td_thragent_t *__ta,
307 			      struct ps_prochandle **__ph);
308 
309 /* Map thread library handle PT to thread debug library handle for process
310    associated with TA and store result in *TH.  */
311 extern td_err_e td_ta_map_id2thr (const td_thragent_t *__ta, pthread_t __pt,
312 				  td_thrhandle_t *__th);
313 
314 /* Map process ID LWPID to thread debug library handle for process
315    associated with TA and store result in *TH.  */
316 extern td_err_e td_ta_map_lwp2thr (const td_thragent_t *__ta, lwpid_t __lwpid,
317 				   td_thrhandle_t *__th);
318 
319 
320 /* Call for each thread in a process associated with TA the callback function
321    CALLBACK.  */
322 extern td_err_e td_ta_thr_iter (const td_thragent_t *__ta,
323 				td_thr_iter_f *__callback, void *__cbdata_p,
324 				td_thr_state_e __state, int __ti_pri,
325 				sigset_t *__ti_sigmask_p,
326 				unsigned int __ti_user_flags);
327 
328 /* Call for each defined thread local data entry the callback function KI.  */
329 extern td_err_e td_ta_tsd_iter (const td_thragent_t *__ta, td_key_iter_f *__ki,
330 				void *__p);
331 
332 
333 /* Get event address for EVENT.  */
334 extern td_err_e td_ta_event_addr (const td_thragent_t *__ta,
335 				  td_event_e __event, td_notify_t *__ptr);
336 
337 /* Enable EVENT in global mask.  */
338 extern td_err_e td_ta_set_event (const td_thragent_t *__ta,
339 				 td_thr_events_t *__event);
340 
341 /* Disable EVENT in global mask.  */
342 extern td_err_e td_ta_clear_event (const td_thragent_t *__ta,
343 				   td_thr_events_t *__event);
344 
345 /* Return information about last event.  */
346 extern td_err_e td_ta_event_getmsg (const td_thragent_t *__ta,
347 				    td_event_msg_t *msg);
348 
349 
350 /* Set suggested concurrency level for process associated with TA.  */
351 extern td_err_e td_ta_setconcurrency (const td_thragent_t *__ta, int __level);
352 
353 
354 /* Enable collecting statistics for process associated with TA.  */
355 extern td_err_e td_ta_enable_stats (const td_thragent_t *__ta, int __enable);
356 
357 /* Reset statistics.  */
358 extern td_err_e td_ta_reset_stats (const td_thragent_t *__ta);
359 
360 /* Retrieve statistics from process associated with TA.  */
361 extern td_err_e td_ta_get_stats (const td_thragent_t *__ta,
362 				 td_ta_stats_t *__statsp);
363 
364 
365 /* Validate that TH is a thread handle.  */
366 extern td_err_e td_thr_validate (const td_thrhandle_t *__th);
367 
368 /* Return information about thread TH.  */
369 extern td_err_e td_thr_get_info (const td_thrhandle_t *__th,
370 				 td_thrinfo_t *__infop);
371 
372 /* Retrieve floating-point register contents of process running thread TH.  */
373 extern td_err_e td_thr_getfpregs (const td_thrhandle_t *__th,
374 				  prfpregset_t *__regset);
375 
376 /* Retrieve general register contents of process running thread TH.  */
377 extern td_err_e td_thr_getgregs (const td_thrhandle_t *__th,
378 				 prgregset_t __gregs);
379 
380 /* Retrieve extended register contents of process running thread TH.  */
381 extern td_err_e td_thr_getxregs (const td_thrhandle_t *__th, void *__xregs);
382 
383 /* Get size of extended register set of process running thread TH.  */
384 extern td_err_e td_thr_getxregsize (const td_thrhandle_t *__th, int *__sizep);
385 
386 /* Set floating-point register contents of process running thread TH.  */
387 extern td_err_e td_thr_setfpregs (const td_thrhandle_t *__th,
388 				  const prfpregset_t *__fpregs);
389 
390 /* Set general register contents of process running thread TH.  */
391 extern td_err_e td_thr_setgregs (const td_thrhandle_t *__th,
392 				 prgregset_t __gregs);
393 
394 /* Set extended register contents of process running thread TH.  */
395 extern td_err_e td_thr_setxregs (const td_thrhandle_t *__th,
396 				 const void *__addr);
397 
398 
399 /* Enable reporting for EVENT for thread TH.  */
400 extern td_err_e td_thr_event_enable (const td_thrhandle_t *__th, int __event);
401 
402 /* Enable EVENT for thread TH.  */
403 extern td_err_e td_thr_set_event (const td_thrhandle_t *__th,
404 				  td_thr_events_t *__event);
405 
406 /* Disable EVENT for thread TH.  */
407 extern td_err_e td_thr_clear_event (const td_thrhandle_t *__th,
408 				    td_thr_events_t *__event);
409 
410 /* Get event message for thread TH.  */
411 extern td_err_e td_thr_event_getmsg (const td_thrhandle_t *__th,
412 				     td_event_msg_t *__msg);
413 
414 
415 /* Set priority of thread TH.  */
416 extern td_err_e td_thr_setprio (const td_thrhandle_t *__th, int __prio);
417 
418 
419 /* Set pending signals for thread TH.  */
420 extern td_err_e td_thr_setsigpending (const td_thrhandle_t *__th,
421 				      unsigned char __n, const sigset_t *__ss);
422 
423 /* Set signal mask for thread TH.  */
424 extern td_err_e td_thr_sigsetmask (const td_thrhandle_t *__th,
425 				   const sigset_t *__ss);
426 
427 
428 /* Return thread local data associated with key TK in thread TH.  */
429 extern td_err_e td_thr_tsd (const td_thrhandle_t *__th,
430 			    const thread_key_t __tk, void **__data);
431 
432 
433 /* Suspend execution of thread TH.  */
434 extern td_err_e td_thr_dbsuspend (const td_thrhandle_t *__th);
435 
436 /* Resume execution of thread TH.  */
437 extern td_err_e td_thr_dbresume (const td_thrhandle_t *__th);
438 
439 #endif	/* thread_db.h */
440