xref: /netbsd-src/external/gpl3/binutils/dist/gprofng/libcollector/dispatcher.c (revision cb63e24e8d6aae7ddac1859a9015f48b1d8bd90e)
1 /* Copyright (C) 2021-2024 Free Software Foundation, Inc.
2    Contributed by Oracle.
3 
4    This file is part of GNU Binutils.
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3, or (at your option)
9    any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 51 Franklin Street - Fifth Floor, Boston,
19    MA 02110-1301, USA.  */
20 
21 /*
22  *	Central SIGPROF dispatcher to various module event handlers
23  *      (REALPROF profile, HWC check, overview sample, manual sample)
24  */
25 
26 #include "config.h"
27 #include <dlfcn.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <sys/param.h>
34 #include <sys/syscall.h>
35 #include <time.h>
36 #include <signal.h>
37 
38 #include "gp-defs.h"
39 #include "gp-experiment.h"
40 #include "collector.h"
41 #include "collector_module.h"
42 #include "tsd.h"
43 #include "hwcdrv.h"
44 #include "memmgr.h"
45 
46 static void collector_sigprof_dispatcher (int, siginfo_t*, void*);
47 static int init_interposition_intf ();
48 static int collector_timer_create (timer_t * ptimerid);
49 static int collector_timer_settime (int period, timer_t timerid);
50 static int collector_timer_gettime (timer_t timerid);
51 static volatile int collector_sigprof_entries = 0; /* counter for SIGPROF signals in DISPATCH_TST mode */
52 static timer_t collector_master_thread_timerid = NULL;
53 static collector_mutex_t collector_clone_libc_lock = COLLECTOR_MUTEX_INITIALIZER;
54 static unsigned dispatcher_key = COLLECTOR_TSD_INVALID_KEY;
55 
56 static int (*__real_clone) (int (*fn)(void *), void *child_stack, int flags,
57 			    void *arg, ...) = NULL;
58 static int (*__real_timer_create) (clockid_t clockid,
59 				struct sigevent *sevp, timer_t *timerid) = NULL;
60 static int (*__real_timer_settime) (timer_t timerid, int flags,
61 				    const struct itimerspec *new_value,
62 				    struct itimerspec *old_value) = NULL;
63 static int (*__real_timer_delete) (timer_t timerid) = NULL;
64 static int (*__real_timer_gettime) (timer_t timerid,
65 				    struct itimerspec *curr_value) = NULL;
66 
67 static int (*__real_pthread_create_2_34) (pthread_t *thread,
68 			const pthread_attr_t *attr,
69 			void *(*start_routine) (void *), void *arg) = NULL;
70 static int (*__real_pthread_create_2_17) (pthread_t *thread,
71 			const pthread_attr_t *attr,
72 			void *(*start_routine) (void *), void *arg) = NULL;
73 static int (*__real_pthread_create_2_2_5) (pthread_t *thread,
74 			const pthread_attr_t *attr,
75 			void *(*start_routine) (void *), void *arg) = NULL;
76 static int (*__real_pthread_create_2_1) (pthread_t *thread,
77 			const pthread_attr_t *attr,
78 			void *(*start_routine) (void *), void *arg) = NULL;
79 static int (*__real_pthread_create_2_0) (pthread_t *thread,
80 			const pthread_attr_t *attr,
81 			void *(*start_routine) (void *), void *arg) = NULL;
82 
83 static int (*__real_timer_create_2_34) (clockid_t clockid,
84 				struct sigevent *sevp, timer_t *timerid) = NULL;
85 static int (*__real_timer_create_2_17) (clockid_t clockid,
86 				struct sigevent *sevp, timer_t *timerid) = NULL;
87 static int (*__real_timer_create_2_3_3) (clockid_t clockid,
88 				struct sigevent *sevp, timer_t *timerid) = NULL;
89 static int (*__real_timer_create_2_2_5) (clockid_t clockid,
90 				struct sigevent *sevp, timer_t *timerid) = NULL;
91 static int (*__real_timer_create_2_2) (clockid_t clockid,
92 				struct sigevent *sevp, timer_t *timerid) = NULL;
93 
94 int (*__real_pthread_sigmask_2_32) (int, const sigset_t *, sigset_t *) = NULL;
95 int (*__real_pthread_sigmask_2_17) (int, const sigset_t *, sigset_t *) = NULL;
96 int (*__real_pthread_sigmask_2_2_5) (int, const sigset_t *, sigset_t *) = NULL;
97 int (*__real_pthread_sigmask_2_0) (int, const sigset_t *, sigset_t *) = NULL;
98 
99 
100 /* Original SIGPROF handler which will be replaced with the dispatcher.  Used
101  * to properly interact with libaio, which uses SIGPROF as its SIGAIOCANCEL. */
102 static struct sigaction original_sigprof_handler;
103 
104 enum
105 {
106   DISPATCH_NYI = -1,    /* dispatcher not yet installed */
107   DISPATCH_OFF = 0,     /* dispatcher installed, but disabled */
108   DISPATCH_ON = 1,      /* dispatcher installed, and enabled */
109   DISPATCH_TST = 2      /* dispatcher installed, and enabled in testing mode */
110 };
111 
112 static int dispatch_mode = DISPATCH_NYI;   /* controls SIGPROF dispatching */
113 static int itimer_period_requested = 0;    /* dispatcher itimer period */
114 static int itimer_period_actual = 0;       /* actual dispatcher itimer period */
115 
116 static int (*__real_sigaction) (int signum, const struct sigaction *act,
117                      struct sigaction *oldact) = NULL;
118 static int (*__real_setitimer) (int which, const struct itimerval *new_value,
119                      struct itimerval *old_value) = NULL;
120 static int (*__real_libc_setitimer) (int which,
121 	const struct itimerval *new_value, struct itimerval *old_value) = NULL;
122 static int (*__real_sigprocmask) (int how, const sigset_t *set,
123 				  sigset_t *oldset) = NULL;
124 static int (*__real_thr_sigsetmask) (int how, const sigset_t *iset,
125 				     sigset_t *oset) = NULL;
126 static int (*__real_pthread_sigmask) (int how, const sigset_t *set,
127 				      sigset_t *oldset) = NULL;
128 static int (*__real_pthread_create) (pthread_t *thread,
129 			const pthread_attr_t *attr,
130 			void *(*start_routine) (void *), void *arg) = NULL;
131 
132 /*
133  * void collector_sigprof_dispatcher()
134  *
135  * Common SIGPROF event handler which dispatches events to appropriate
136  * module handlers, if they are active for this collection and due.
137  * Dispatch sequence, logic and handlers currently hardcoded in dispatcher.
138  */
139 static void
collector_sigprof_dispatcher(int sig,siginfo_t * info,void * context)140 collector_sigprof_dispatcher (int sig, siginfo_t *info, void *context)
141 {
142   if (info == NULL || (info->si_code <= 0 && info->si_code != SI_TIMER))
143     {
144       TprintfT (DBG_LT2, "collector_sigprof_dispatcher signal for %p\n",
145 		original_sigprof_handler.sa_handler);
146       /* pass signal to previous handler */
147       /* watch for recursion, SIG_IGN, and SIG_DFL */
148       if (original_sigprof_handler.sa_handler == SIG_DFL)
149 	__collector_SIGDFL_handler (SIGPROF);
150       else if (original_sigprof_handler.sa_handler != SIG_IGN &&
151 	       original_sigprof_handler.sa_sigaction != &collector_sigprof_dispatcher)
152 	{
153 	  (original_sigprof_handler.sa_sigaction)(sig, info, context);
154 	  TprintfT (DBG_LT2, "collector_sigprof_dispatcher handled\n");
155 	}
156     }
157   else if (dispatch_mode == DISPATCH_ON)
158     {
159 #if ARCH(SPARC)
160       ucontext_t uctxmem;
161       ucontext_t *uctx = &uctxmem;
162       uctx->uc_link = NULL;
163       /* 23340823 signal handler third argument should point to a ucontext_t */
164       /* Convert sigcontext to ucontext_t on sparc-Linux */
165       struct sigcontext *sctx = (struct sigcontext*) context;
166 #if WSIZE(32)
167       uctx->uc_mcontext.gregs[REG_PC] = sctx->si_regs.pc;
168       __collector_memcpy (&uctx->uc_mcontext.gregs[3],
169 			  sctx->si_regs.u_regs,
170 			  sizeof (sctx->si_regs.u_regs));
171 #else
172       uctx->uc_mcontext.mc_gregs[MC_PC] = sctx->sigc_regs.tpc;
173       __collector_memcpy (&uctx->uc_mcontext.mc_gregs[3],
174 			  sctx->sigc_regs.u_regs,
175 			  sizeof (sctx->sigc_regs.u_regs));
176 #endif /* WSIZE() */
177 
178 #else /* not sparc-Linux */
179       ucontext_t *uctx = (ucontext_t*) context;
180 #endif /* ARCH() */
181       TprintfT (DBG_LT3, "collector_sigprof_dispatcher dispatching signal\n");
182 
183       /* XXXX the order of these checks/activities may need adjustment */
184       /* XXXX should also check (first) for a "cached" manual sample */
185       /* HWC check for each LWP: required even if collection is paused */
186       /* This should be first, otherwise it's likely to find the counters
187        * stopped due to an event/overflow during some of the other activities.
188        */
189       /* XXXX HWC check performed every time (skipping if HWC profiling inactive)
190        * to avoid complexity of maintaining separate check times for each LWP
191        */
192       __collector_ext_hwc_check (info, uctx);
193 
194       /* XXXX if sigemtpending, should perhaps skip __collector_ext_usage_sample
195        * (and get it next time through)
196        */
197 
198       /* check for experiment past delay start */
199       if (__collector_delay_start != 0)
200 	{
201 	  hrtime_t now = __collector_gethrtime ();
202 	  if (__collector_delay_start < now)
203 	    {
204 	      TprintfT (0, "__collector_ext_usage_sample: now (%lld) > delay_start (%lld)\n",
205 			(now - __collector_start_time), (__collector_delay_start - __collector_start_time));
206 
207 	      /* resume the data collection */
208 	      __collector_delay_start = 0;
209 	      __collector_resume ();
210 
211 	      /* don't take a periodic sample, just let the resume sample cover it */
212 	      if (__collector_sample_period != 0)
213 		{
214 		  /* this update should only be done for periodic samples */
215 		  while (__collector_next_sample < now)
216 		    __collector_next_sample += ((hrtime_t) NANOSEC) * __collector_sample_period;
217 		}
218 	      /* return; */
219 	    }
220 	}
221       /* check for periodic sampling */
222       if (__collector_gethrtime () > __collector_next_sample)
223 	__collector_ext_usage_sample (PERIOD_SMPL, "periodic");
224 
225       /* check for experiment past termination time */
226       if (__collector_exp_active && __collector_terminate_time != 0)
227 	{
228 	  hrtime_t now = __collector_gethrtime ();
229 	  if (__collector_terminate_time < now)
230 	    {
231 	      TprintfT (0, "__collector_ext_usage_sample: now (%lld) > terminate_time (%lld); closing experiment\n",
232 			(now - __collector_start_time), (__collector_terminate_time - __collector_start_time));
233 	      /* close the experiment */
234 	      __collector_close_experiment ();
235 	    }
236 	}
237 
238       /* call the code to process the profile data, and generate the packet */
239       /* (must always be called, otherwise profile data must be aggregated,
240        * but can be left till last, as already have the required data)
241        */
242       __collector_ext_profile_handler (info, uctx);
243     }
244   else if (dispatch_mode == DISPATCH_TST)
245     {
246       collector_sigprof_entries++;
247       return;
248     }
249 }
250 
251 /*
252  *  __collector_sigprof_install
253  */
254 int
__collector_sigprof_install()255 __collector_sigprof_install ()
256 {
257   TprintfT (DBG_LT2, "__collector_sigprof_install\n");
258   struct sigaction oact;
259   if (__collector_sigaction (SIGPROF, NULL, &oact) != 0)
260     return COL_ERROR_DISPINIT;
261   if (oact.sa_sigaction == collector_sigprof_dispatcher)
262     /* signal handler is already in place; we are probably in a fork-child */
263     TprintfT (DBG_LT1, "dispatcher: __collector_ext_dispatcher_install() collector_sigprof_dispatcher already installed\n");
264   else
265     {
266       struct sigaction c_act;
267       CALL_UTIL (memset)(&c_act, 0, sizeof c_act);
268       sigemptyset (&c_act.sa_mask);
269       sigaddset (&c_act.sa_mask, HWCFUNCS_SIGNAL); /* block SIGEMT delivery in handler */
270       c_act.sa_sigaction = collector_sigprof_dispatcher;
271       c_act.sa_flags = SA_RESTART | SA_SIGINFO;
272       if (__collector_sigaction (SIGPROF, &c_act, &original_sigprof_handler))
273 	return COL_ERROR_DISPINIT;
274     }
275   dispatch_mode = DISPATCH_OFF; /* don't dispatch yet */
276   TprintfT (DBG_LT2, "__collector_sigprof_install done\n");
277   return COL_ERROR_NONE;
278 }
279 
280 /*
281  * void __collector_ext_dispatcher_tsd_create_key()
282  *
283  * create tsd key for dispatcher
284  */
285 void
__collector_ext_dispatcher_tsd_create_key()286 __collector_ext_dispatcher_tsd_create_key ()
287 {
288   dispatcher_key = __collector_tsd_create_key (sizeof (timer_t), NULL, NULL);
289 }
290 /*
291  * int __collector_ext_dispatcher_install()
292  *
293  * installs a common handler/dispatcher (and itimer) for SIGPROF events
294  */
295 int
__collector_ext_dispatcher_install()296 __collector_ext_dispatcher_install ()
297 {
298   int timer_period;
299   TprintfT (DBG_LT2, "__collector_ext_dispatcher_install\n");
300 
301   /* check period set for interval timer, which will be used as the basis
302    * for all timed activities: if not set, no role for SIGPROF dispatcher
303    */
304   if (itimer_period_requested <= 0)
305     {
306       TprintfT (DBG_LT1, "No interval timer set: skipping dispatcher install!\n");
307       return COL_ERROR_NONE; /* no itimer/dispatcher required */
308     }
309 
310   /* check for an existing interval timer */
311   if (collector_master_thread_timerid == NULL)
312     if (collector_timer_create (&collector_master_thread_timerid) < 0)
313       return COL_ERROR_ITMRINIT;
314   timer_t *timeridptr = __collector_tsd_get_by_key (dispatcher_key);
315   if (timeridptr != NULL)
316     *timeridptr = collector_master_thread_timerid; // store for per thread timer stop/start
317   TprintfT (DBG_LT3, "__collector_ext_dispatcher_install: collector_master_thread_timerid=%p\n",
318 	    collector_master_thread_timerid);
319   timer_period = collector_timer_gettime (collector_master_thread_timerid);
320   if (timer_period > 0)
321     {
322       TprintfT (DBG_LT1, "Overriding app-set interval timer with period %d\n", timer_period);
323       (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%d->%d</event>\n",
324 				    SP_JCMD_CWARN, COL_WARN_ITMRPOVR, timer_period, itimer_period_requested);
325     }
326   /* install the interval timer used for all timed activities */
327   if (collector_timer_settime (itimer_period_requested, collector_master_thread_timerid) < 0)
328     return COL_ERROR_ITMRINIT;
329   TprintfT (DBG_LT2, "__collector_ext_dispatcher_install done\n");
330   dispatch_mode = DISPATCH_ON; /* activate SIGPROF dispatch to event handlers */
331   return COL_ERROR_NONE;
332 }
333 
334 int
__collector_sigaction(int sig,const struct sigaction * nact,struct sigaction * oact)335 __collector_sigaction (int sig, const struct sigaction *nact, struct sigaction *oact)
336 {
337   TprintfT (DBG_LT1, "__collector_sigaction: %d, %p\n", sig, nact ? nact->sa_sigaction : NULL);
338   if (NULL_PTR (sigaction))
339     init_interposition_intf ();
340 
341   /* Whether we change the signal handler in the kernel
342    * or not make sure the real sigaction is aware about
343    * our new handler (6227565)
344    */
345   return CALL_REAL (sigaction)(sig, nact, oact);
346 }
347 
348 /*
349  * We have special dispatchers for SIGPROF and HWCFUNCS_SIGNAL to
350  * decide whether the signal was intended for us or for the user.
351  * One special case is SIGDFL, in which case we don't have a
352  * user-function address to call.  If the user did indeed set
353  * default disposition for one of these signals and sent that
354  * signal, we honor that action, even though it will lead to
355  * termination.
356  */
357 void
__collector_SIGDFL_handler(int sig)358 __collector_SIGDFL_handler (int sig)
359 {
360   /* remove our dispatcher, replacing it with the default disposition */
361   struct sigaction act;
362   CALL_UTIL (memset)(&act, 0, sizeof (act));
363   act.sa_handler = SIG_DFL;
364   if (__collector_sigaction (sig, &act, NULL))
365     {
366       /* XXXXXX what are we supposed to do here? we're committing suicide anyhow */
367     }
368   /* resend the signal we intercepted earlier */
369   // XXXX Bug 18177509 - additional sigprof signal kills target program
370   kill (getpid (), sig);
371 }
372 
373 /*
374  * suspend/resume timer per thread
375  */
376 void
__collector_ext_dispatcher_thread_timer_suspend()377 __collector_ext_dispatcher_thread_timer_suspend ()
378 {
379   timer_t * timeridptr = __collector_tsd_get_by_key (dispatcher_key);
380   if (timeridptr != NULL && *timeridptr != NULL)
381     (void) collector_timer_settime (0, *timeridptr);
382   return;
383 }
384 
385 int
__collector_ext_dispatcher_thread_timer_resume()386 __collector_ext_dispatcher_thread_timer_resume ()
387 {
388   timer_t * timeridptr = __collector_tsd_get_by_key (dispatcher_key);
389   if (timeridptr == NULL)
390     return -1;
391   if (*timeridptr == NULL)
392     { // timer id not initialized yet
393       TprintfT (DBG_LT2, "__collector_ext_dispatcher_thread_timer_resume: timer not initialized yet, create it\n");
394       if (collector_timer_create (timeridptr) == -1)
395 	{
396 	  TprintfT (0, "__collector_ext_dispatcher_thread_timer_resume(): WARNING: No timer created\n");
397 	  return -1;
398 	}
399     }
400   return collector_timer_settime (itimer_period_requested, *timeridptr);
401 }
402 
403 void
__collector_ext_dispatcher_suspend()404 __collector_ext_dispatcher_suspend ()
405 {
406   TprintfT (DBG_LT2, "__collector_ext_dispatcher_suspend\n");
407   if (dispatch_mode == DISPATCH_NYI)
408     {
409       TprintfT (0, "__collector_ext_dispatcher_suspend(): WARNING: No dispatcher installed\n");
410       return;
411     }
412 
413   /* disable SIGPROF dispatching */
414   dispatch_mode = DISPATCH_OFF;
415 
416   /* disable the interval timer; ignore any failures */
417   __collector_ext_dispatcher_thread_timer_suspend ();
418   return;
419 }
420 
421 void
__collector_ext_dispatcher_restart()422 __collector_ext_dispatcher_restart ()
423 {
424   TprintfT (DBG_LT2, "__collector_ext_dispatcher_restart(ip=%d)\n", itimer_period_requested);
425   if (dispatch_mode == DISPATCH_NYI)
426     {
427       TprintfT (0, "__collector_ext_dispatcher_restart(): WARNING: No dispatcher installed\n");
428       return;
429     }
430 
431   /* restart the interval timer used for all timed activities */
432   if (__collector_ext_dispatcher_thread_timer_resume () == 0)
433     dispatch_mode = DISPATCH_ON; /* re-activate SIGPROF dispatch to handlers */
434   return;
435 }
436 /*
437  * void __collector_ext_dispatcher_deinstall()
438  *
439  * If installed, disables SIGPROF dispatch and interval timer.
440  * Includes checks for last SIGPROF dispatch time, interval timer period,
441  * and currently installed SIGPROF handler, with appropriate warnings logged.
442  * The dispatcher remains installed to handle pending collector SIGPROFs and
443  * forward non-collector SIGPROFs to the application's handler(s).
444  * If the decision is ever made actually to deinstall the dispatcher,
445  * consider bug 4183714 and what to do about any possible pending
446  * SIGPROFs.
447  */
448 
449 void
__collector_ext_dispatcher_deinstall()450 __collector_ext_dispatcher_deinstall ()
451 {
452   TprintfT (DBG_LT1, "__collector_ext_dispatcher_deinstall()\n");
453   if (dispatch_mode == DISPATCH_NYI)
454     {
455       TprintfT (0, "__collector_ext_dispatcher_deinstall(): WARNING: No dispatcher installed\n");
456       return;
457     }
458   dispatch_mode = DISPATCH_OFF; /* disable SIGPROF dispatching */
459 
460   /* verify that interval timer is still installed with expected period */
461   int timer_period = collector_timer_gettime (collector_master_thread_timerid);
462   if (timer_period != itimer_period_actual)
463     {
464       TprintfT (DBG_LT2, "dispatcher: Collector interval timer period changed %d -> %d\n",
465 		itimer_period_actual, timer_period);
466       if ((itimer_period_actual >= (timer_period + timer_period / 10)) ||
467 	  (itimer_period_actual <= (timer_period - timer_period / 10)))
468 	__collector_log_write ("<event kind=\"%s\" id=\"%d\">%d -> %d</event>\n",
469 			       SP_JCMD_CWARN, COL_WARN_ITMRREP,
470 			       itimer_period_actual, timer_period);
471       else
472 	__collector_log_write ("<event kind=\"%s\" id=\"%d\">%d -> %d</event>\n",
473 			       SP_JCMD_COMMENT, COL_WARN_PROFRND,
474 			       itimer_period_actual, timer_period);
475     }
476 
477   /* Verify that SIGPROF dispatcher is still installed.
478    * (still required with sigaction interposition and management,
479    * since interposition is not done for attach experiments)
480    */
481   struct sigaction curr;
482   if (__collector_sigaction (SIGPROF, NULL, &curr) == -1)
483     TprintfT (0, "ERROR: dispatcher sigaction check failed: errno=%d\n", errno);
484   else if (curr.sa_sigaction != collector_sigprof_dispatcher)
485     {
486       TprintfT (0, "ERROR: collector dispatcher replaced by %p!\n", curr.sa_handler);
487       (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%p</event>\n",
488 				    SP_JCMD_CWARN, COL_WARN_SIGPROF, curr.sa_handler);
489     }
490   else
491     TprintfT (DBG_LT2, "collector dispatcher integrity verified!\n");
492 
493   /* disable the interval timer; ignore any failures */
494   if (collector_master_thread_timerid != NULL)
495     {
496       (void) CALL_REAL (timer_delete)(collector_master_thread_timerid);
497       collector_master_thread_timerid = NULL;
498     }
499   dispatcher_key = COLLECTOR_TSD_INVALID_KEY;
500   itimer_period_requested = 0;
501   itimer_period_actual = 0;
502 }
503 
504 /*
505  * void __collector_ext_dispatcher_fork_child_cleanup()
506  *
507  * delete timer, clear timer interval
508  */
509 void
__collector_ext_dispatcher_fork_child_cleanup()510 __collector_ext_dispatcher_fork_child_cleanup ()
511 {
512   if (collector_master_thread_timerid != NULL)
513     {
514       (void) CALL_REAL (timer_delete)(collector_master_thread_timerid);
515       collector_master_thread_timerid = NULL;
516     }
517   __collector_mutex_init (&collector_clone_libc_lock);
518   dispatcher_key = COLLECTOR_TSD_INVALID_KEY;
519   itimer_period_requested = 0;
520   itimer_period_actual = 0;
521 }
522 /*
523  * int __collector_ext_itimer_set (int rperiod)
524  *
525  * set itimer period, if not yet set to a positive number of microseconds,
526  * (after rounding to sys_resolution if necessary) and return its value
527  */
528 int
__collector_ext_itimer_set(int rperiod)529 __collector_ext_itimer_set (int rperiod)
530 {
531   int period;
532   /* if rperiod is negative, force setting */
533   if (rperiod < 0)
534     {
535       itimer_period_actual = 0;
536       period = -rperiod;
537     }
538   else
539     period = rperiod;
540 
541   // ignore SIGPROF while testing itimer interval setting
542   int saved = dispatch_mode;
543   dispatch_mode = DISPATCH_OFF;
544   if (collector_timer_create (&collector_master_thread_timerid) == -1)
545     {
546       TprintfT (0, "__collector_ext_itimer_set(): WARNING: No timer created\n");
547       return itimer_period_actual;
548     }
549   if (collector_timer_settime (period, collector_master_thread_timerid) == 0)
550     {
551       itimer_period_actual = collector_timer_gettime (collector_master_thread_timerid);
552       (void) collector_timer_settime (0, collector_master_thread_timerid); /* XXXX unset for now */
553       itimer_period_requested = period;
554       if (itimer_period_requested != itimer_period_actual)
555 	{
556 	  TprintfT (DBG_LT2, "    itimer period %d adjusted to %d\n",
557 		    itimer_period_requested, itimer_period_actual);
558 	  // (void) __collector_log_write("<event kind=\"%s\" id=\"%d\">%d -> %d</event>\n",
559 	  //     SP_JCMD_CWARN, COL_WARN_PROFRND, itimer_period_requested, itimer_period_actual);
560 	}
561       else
562 	TprintfT (DBG_LT2, "    itimer period %d accepted\n", period);
563     }
564 
565   // restore dispatching SIGPROF handler
566   dispatch_mode = saved;
567   TprintfT (0, "__collector_ext_itimer_set(%d), requested=%d, actual=%d)\n",
568 	    rperiod, itimer_period_requested, itimer_period_actual);
569   return (itimer_period_actual);
570 }
571 
572 static int
collector_timer_gettime(timer_t timerid)573 collector_timer_gettime (timer_t timerid)
574 {
575   int timer_period;
576   struct itimerspec itimer;
577   if (timerid == NULL)
578     return (0); // timer was not initialized
579   if (CALL_REAL (timer_gettime)(timerid, &itimer) == -1)
580     {
581       /* this should never reasonably fail, so not worth logging */
582       TprintfT (DBG_LT1, "WARNING: timer_gettime failed: errno=%d\n", errno);
583       return (-1);
584     }
585   timer_period = ((itimer.it_interval.tv_sec * NANOSEC) +
586 		  itimer.it_interval.tv_nsec) / 1000;
587   TprintfT (DBG_LT2, "collector_timer_gettime (period=%d)\n", timer_period);
588   return (timer_period);
589 }
590 
591 static int
collector_timer_create(timer_t * ptimerid)592 collector_timer_create (timer_t * ptimerid)
593 {
594   struct sigevent sigev;
595   if (NULL_PTR (timer_create))
596     init_interposition_intf ();
597   TprintfT (DBG_LT2, "collector_timer_settime(): timer_create is %p\n", __real_timer_create);
598   sigev.sigev_notify = SIGEV_THREAD_ID | SIGEV_SIGNAL;
599   sigev.sigev_signo = SIGPROF;
600   sigev.sigev_value.sival_ptr = ptimerid;
601 #if !defined(__MUSL_LIBC)
602   sigev._sigev_un._tid = __collector_gettid ();
603 #endif
604   if (CALL_REAL (timer_create)(CLOCK_THREAD_CPUTIME_ID, &sigev, ptimerid) == -1)
605     {
606       TprintfT (DBG_LT2, "collector_timer_settime() failed! errno=%d\n", errno);
607       return -1;
608     }
609   return 0;
610 }
611 
612 static int
collector_timer_settime(int period,timer_t timerid)613 collector_timer_settime (int period, timer_t timerid)
614 {
615   struct itimerspec itimer;
616   if (NULL_PTR (timer_settime))
617     init_interposition_intf ();
618   TprintfT (DBG_LT2, "collector_timer_settime(period=%d)\n", period);
619   time_t NPM = 1000;
620   itimer.it_interval.tv_sec = NPM * period / NANOSEC;
621   itimer.it_interval.tv_nsec = (NPM * period) % NANOSEC;
622   itimer.it_value = itimer.it_interval;
623   if (CALL_REAL (timer_settime)(timerid, 0, &itimer, NULL) == -1)
624     {
625       TprintfT (DBG_LT2, "collector_timer_settime(%d) failed! errno=%d\n", period, errno);
626       return -1;
627     }
628   return 0;
629 }
630 
631 static void
protect_profiling_signals(sigset_t * lset)632 protect_profiling_signals (sigset_t* lset)
633 {
634   static unsigned int protected_sigprof = 0;
635   static unsigned int protected_sigemt = 0;
636   // T1 relies on thread signal masking, so best not to mess with it:
637   // T1 users have already been warned about the dangers of its use
638   if (__collector_libthread_T1)
639     return;
640   if (sigismember (lset, SIGPROF) && (dispatch_mode == DISPATCH_ON))
641     {
642       TprintfT (0, "WARNING: ignoring %s block while profiling\n", "SIGPROF");
643       if (protected_sigprof == 0)
644 	__collector_log_write ("<event kind=\"%s\" id=\"%d\">%s</event>\n",
645 			       SP_JCMD_CWARN, COL_WARN_SIGMASK, "SIGPROF");
646       sigdelset (lset, SIGPROF);
647       protected_sigprof++;
648     }
649   if (sigismember (lset, HWCFUNCS_SIGNAL) && __collector_ext_hwc_active ())
650     {
651       TprintfT (0, "WARNING: ignoring %s block while profiling\n", "SIGEMT");
652       if (protected_sigemt == 0)
653 	__collector_log_write ("<event kind=\"%s\" id=\"%d\">%s</event>\n",
654 			       SP_JCMD_CWARN, COL_WARN_SIGMASK, HWCFUNCS_SIGNAL_STRING);
655       sigdelset (lset, HWCFUNCS_SIGNAL);
656       protected_sigemt++;
657     }
658 }
659 
660 static int
init_interposition_intf()661 init_interposition_intf ()
662 {
663   if (__collector_dlsym_guard)
664     return 1;
665   void *dlflag;
666   /* Linux requires RTLD_LAZY, Solaris can do just RTLD_NOLOAD */
667   void *handle = dlopen (SYS_LIBC_NAME, RTLD_LAZY | RTLD_NOLOAD);
668 
669   __real_setitimer = dlsym (RTLD_NEXT, "setitimer");
670   if (__real_setitimer == NULL)
671     {
672       __real_setitimer = dlsym (RTLD_DEFAULT, "setitimer");
673       if (__real_setitimer == NULL)
674 	{
675 	  TprintfT (DBG_LT2, "init_interposition_intf() setitimer not found\n");
676 	  return 1;
677 	}
678       dlflag = RTLD_DEFAULT;
679     }
680   else
681     dlflag = RTLD_NEXT;
682 
683   TprintfT (DBG_LT2, "init_interposition_intf() using RTLD_%s\n",
684 	    (dlflag == RTLD_DEFAULT) ? "DEFAULT" : "NEXT");
685 
686   __real_sigaction = dlsym (dlflag, "sigaction");
687 
688   /* also explicitly get libc.so/setitimer (as a backup) */
689   __real_libc_setitimer = dlsym (handle, "setitimer");
690 
691   __real_sigprocmask = dlsym (dlflag, "sigprocmask");
692   __real_thr_sigsetmask = dlsym (dlflag, "thr_sigsetmask");
693 
694   __real_pthread_sigmask_2_32 = dlvsym (dlflag, "pthread_sigmask", "GLIBC_2.32");
695   __real_pthread_sigmask_2_17 = dlvsym (dlflag, "pthread_sigmask", "GLIBC_2.17");
696   __real_pthread_sigmask_2_2_5 = dlvsym (dlflag, "pthread_sigmask", "GLIBC_2.2.5");
697   __real_pthread_sigmask_2_0 = dlvsym (dlflag, "pthread_sigmask", "GLIBC_2.0");
698   if (__real_pthread_sigmask_2_32)
699     __real_pthread_sigmask = __real_pthread_sigmask_2_32;
700   else if (__real_pthread_sigmask_2_17)
701     __real_pthread_sigmask = __real_pthread_sigmask_2_17;
702   else if (__real_pthread_sigmask_2_2_5)
703     __real_pthread_sigmask = __real_pthread_sigmask_2_2_5;
704   else if (__real_pthread_sigmask_2_0)
705     __real_pthread_sigmask = __real_pthread_sigmask_2_0;
706   else
707     __real_pthread_sigmask = dlsym (dlflag, "pthread_sigmask");
708 
709   __real_pthread_create_2_34 = dlvsym (dlflag, "pthread_create", "GLIBC_2.34");
710   __real_pthread_create_2_17 = dlvsym (dlflag, "pthread_create", "GLIBC_2.17");
711   __real_pthread_create_2_2_5 = dlvsym (dlflag, "pthread_create", "GLIBC_2.2.5");
712   __real_pthread_create_2_1 = dlvsym (dlflag, "pthread_create", "GLIBC_2.1");
713   __real_pthread_create_2_0 = dlvsym (dlflag, "pthread_create", "GLIBC_2.0");
714   if (__real_pthread_create_2_34)
715     __real_pthread_create = __real_pthread_create_2_34;
716   else if (__real_pthread_create_2_17)
717     __real_pthread_create = __real_pthread_create_2_17;
718   else if (__real_pthread_create_2_2_5)
719     __real_pthread_create = __real_pthread_create_2_2_5;
720   else if (__real_pthread_create_2_1)
721     __real_pthread_create = __real_pthread_create_2_1;
722   else if (__real_pthread_create_2_0)
723     __real_pthread_create = __real_pthread_create_2_0;
724   else
725     __real_pthread_create = dlsym (dlflag, "pthread_create");
726 
727   __real_timer_create_2_34 = dlvsym (dlflag, "timer_create", "GLIBC_2.34");
728   __real_timer_create_2_17 = dlvsym (dlflag, "timer_create", "GLIBC_2.17");
729   __real_timer_create_2_3_3 = dlvsym (dlflag, "timer_create", "GLIBC_2.3.3");
730   __real_timer_create_2_2_5 = dlvsym (dlflag, "timer_create", "GLIBC_2.2.5");
731   __real_timer_create_2_2 = dlvsym (dlflag, "timer_create", "GLIBC_2.2");
732   if (__real_timer_create_2_34)
733     __real_timer_create = __real_timer_create_2_34;
734   else if (__real_timer_create_2_17)
735     __real_timer_create = __real_timer_create_2_17;
736   else if (__real_timer_create_2_3_3)
737     __real_timer_create = __real_timer_create_2_3_3;
738   else if (__real_timer_create_2_2_5)
739     __real_timer_create = __real_timer_create_2_2_5;
740   else if (__real_timer_create_2_2)
741     __real_timer_create = __real_timer_create_2_2;
742   else
743     __real_timer_create = dlsym (dlflag, "timer_create");
744 
745   void *t;
746   if ((t = dlvsym (dlflag, "timer_settime", "GLIBC_2.34")) != NULL)
747     __real_timer_settime = t;
748   else if ((t = dlvsym (dlflag, "timer_settime", "GLIBC_2.17")) != NULL)
749     __real_timer_settime = t;
750   else if ((t = dlvsym (dlflag, "timer_settime", "GLIBC_2.3.3")) != NULL)
751     __real_timer_settime = t;
752   else if ((t = dlvsym (dlflag, "timer_settime", "GLIBC_2.2.5")) != NULL)
753     __real_timer_settime = t;
754   else if ((t = dlvsym (dlflag, "timer_settime", "GLIBC_2.0")) != NULL)
755     __real_timer_settime = t;
756   else
757     __real_timer_settime = dlsym (dlflag, "timer_settime");
758 
759   if ((t = dlvsym (dlflag, "timer_delete", "GLIBC_2.34")) != NULL)
760     __real_timer_delete = t;
761   else if ((t = dlvsym (dlflag, "timer_delete", "GLIBC_2.17")) != NULL)
762     __real_timer_delete = t;
763   else if ((t = dlvsym (dlflag, "timer_delete", "GLIBC_2.3.3")) != NULL)
764     __real_timer_delete = t;
765   else if ((t = dlvsym (dlflag, "timer_delete", "GLIBC_2.2.5")) != NULL)
766     __real_timer_delete = t;
767   else if ((t = dlvsym (dlflag, "timer_delete", "GLIBC_2.2")) != NULL)
768     __real_timer_delete = t;
769   else
770     __real_timer_delete = dlsym (dlflag, "timer_delete");
771 
772   if ((t = dlvsym (dlflag, "timer_gettime", "GLIBC_2.34")) != NULL)
773     __real_timer_gettime = t;
774   else if ((t = dlvsym (dlflag, "timer_gettime", "GLIBC_2.17")) != NULL)
775     __real_timer_gettime = t;
776   else if ((t = dlvsym (dlflag, "timer_gettime", "GLIBC_2.3.3")) != NULL)
777     __real_timer_gettime = t;
778   else if ((t = dlvsym (dlflag, "timer_gettime", "GLIBC_2.2.5")) != NULL)
779     __real_timer_gettime = t;
780   else if ((t = dlvsym (dlflag, "timer_gettime", "GLIBC_2.0")) != NULL)
781     __real_timer_gettime = t;
782   else
783     __real_timer_gettime = dlsym (dlflag, "timer_gettime");
784 
785   __real_clone = dlsym (dlflag, "clone");
786 
787 #define PR_FUNC(f)  TprintfT (DBG_LT2, " dispetcher.c: " #f ": @%p\n", f)
788   PR_FUNC (__real_clone);
789   PR_FUNC (__real_libc_setitimer);
790   PR_FUNC (__real_pthread_create);
791   PR_FUNC (__real_pthread_create_2_0);
792   PR_FUNC (__real_pthread_create_2_1);
793   PR_FUNC (__real_pthread_create_2_17);
794   PR_FUNC (__real_pthread_create_2_2_5);
795   PR_FUNC (__real_pthread_create_2_34);
796   PR_FUNC (__real_pthread_sigmask);
797   PR_FUNC (__real_pthread_sigmask_2_0);
798   PR_FUNC (__real_pthread_sigmask_2_2_5);
799   PR_FUNC (__real_pthread_sigmask_2_17);
800   PR_FUNC (__real_pthread_sigmask_2_32);
801   PR_FUNC (__real_setitimer);
802   PR_FUNC (__real_sigaction);
803   PR_FUNC (__real_sigprocmask);
804   PR_FUNC (__real_thr_sigsetmask);
805   PR_FUNC (__real_timer_create);
806   PR_FUNC (__real_timer_create_2_17);
807   PR_FUNC (__real_timer_create_2_2);
808   PR_FUNC (__real_timer_create_2_2_5);
809   PR_FUNC (__real_timer_create_2_3_3);
810   PR_FUNC (__real_timer_create_2_34);
811   PR_FUNC (__real_timer_delete);
812   PR_FUNC (__real_timer_gettime);
813   PR_FUNC (__real_timer_settime);
814 
815   return 0;
816 }
817 
818 
819 /*------------------------------------------------------------- sigaction */
820 
821 /* NB: need a global interposing function called "sigaction" */
822 int
sigaction(int sig,const struct sigaction * nact,struct sigaction * oact)823 sigaction (int sig, const struct sigaction *nact, struct sigaction *oact)
824 {
825   int ret = 0;
826   int err = 0;
827   if (NULL_PTR (sigaction))
828     err = init_interposition_intf ();
829   if (err)
830     return -1;
831   TprintfT (DBG_LT3, "sigaction(sig=%02d, nact=%p) interposing\n", sig, nact);
832   if (sig == SIGPROF && dispatch_mode != DISPATCH_NYI)
833     {
834       if (oact != NULL)
835 	{
836 	  oact->sa_handler = original_sigprof_handler.sa_handler;
837 	  oact->sa_mask = original_sigprof_handler.sa_mask;
838 	  oact->sa_flags = original_sigprof_handler.sa_flags;
839 	}
840       if (nact != NULL)
841 	{
842 	  original_sigprof_handler.sa_handler = nact->sa_handler;
843 	  original_sigprof_handler.sa_mask = nact->sa_mask;
844 	  original_sigprof_handler.sa_flags = nact->sa_flags;
845 	  TprintfT (DBG_LT1, "dispatcher: new sigaction(sig=%02d) set\n", sig);
846 	}
847     }
848   else if (sig == HWCFUNCS_SIGNAL)
849     ret = collector_sigemt_sigaction (nact, oact);
850   else
851     {
852       if (sig != SIGCHLD || collector_sigchld_sigaction (nact, oact))
853 	ret = CALL_REAL (sigaction)(sig, nact, oact);
854       TprintfT (DBG_LT3, "Real sigaction(sig=%02d) returned %d (oact=%p)\n",
855 		sig, ret, oact);
856       /* but check for other important signals */
857       /* check for sample and pause/resume signals; give warning once, if need be */
858       if ((sig == __collector_sample_sig) && (__collector_sample_sig_warn == 0))
859 	{
860 	  /* give user a warning */
861 	  (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%d</event>\n",
862 					SP_JCMD_CWARN, COL_WARN_SAMPSIGUSED, __collector_sample_sig);
863 	  __collector_sample_sig_warn = 1;
864 	}
865       if ((sig == __collector_pause_sig) && (__collector_pause_sig_warn == 0))
866 	{
867 	  /* give user a warning */
868 	  (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%d</event>\n",
869 					SP_JCMD_CWARN, COL_WARN_PAUSESIGUSED, __collector_pause_sig);
870 	  __collector_pause_sig_warn = 1;
871 	}
872     }
873   TprintfT (DBG_LT3, "sigaction() returning %d (oact=%p)\n", ret, oact);
874   return ret;
875 }
876 
877 /*
878  * In addition to interposing on sigaction(), should we also interpose
879  * on other important signal functions like signal() or sigset()?
880  * - On Solaris, those other functions apparently call sigaction().
881  *   So, we only have to interpose on it.
882  * - On Linux, we should perhaps interpose on these other functions,
883  *   but they are less portable than sigaction() and deprecated or even obsolete.
884  *   So, we interpose, but don't overly worry about doing a good job.
885  */
886 sighandler_t
signal(int sig,sighandler_t handler)887 signal (int sig, sighandler_t handler)
888 {
889   struct sigaction nact;
890   struct sigaction oact;
891   TprintfT (DBG_LT3, "signal(sig=%02d, handler=%p) interposing\n", sig, handler);
892   sigemptyset (&nact.sa_mask);
893   nact.sa_handler = handler;
894   nact.sa_flags = SA_RESTART;
895   if (sigaction (sig, &nact, &oact))
896     return SIG_ERR;
897   TprintfT (DBG_LT3, "signal() returning %p\n", oact.sa_handler);
898   return oact.sa_handler;
899 }
900 
901 sighandler_t
sigset(int sig,sighandler_t handler)902 sigset (int sig, sighandler_t handler)
903 {
904   TprintfT (DBG_LT3, "sigset(sig=%02d, handler=%p) interposing\n", sig, handler);
905   return signal (sig, handler);
906 }
907 
908 /*------------------------------------------------------------- timer_create */
909 
910 // map interposed symbol versions
911 static int
gprofng_timer_create(int (real_func)(),clockid_t clockid,struct sigevent * sevp,timer_t * timerid)912 gprofng_timer_create (int (real_func) (), clockid_t clockid,
913                       struct sigevent *sevp, timer_t *timerid)
914 {
915   // collector reserves SIGPROF
916   if (sevp == NULL || sevp->sigev_notify != SIGEV_SIGNAL ||
917       sevp->sigev_signo != SIGPROF)
918     {
919       int ret = real_func (clockid, sevp, timerid);
920       TprintfT (DBG_LT2, "timer_create @%p (%d) ret=%d\n", real_func,
921                 (int) clockid, ret);
922       return ret;
923     }
924 
925   /* log that application's timer_create request is overridden */
926   (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%d</event>\n",
927 				SP_JCMD_CWARN, COL_WARN_ITMROVR, -1);
928   errno = EBUSY;
929   TprintfT (DBG_LT2, "timer_create @%p (%d) ret=%d\n", real_func,
930                 (int) clockid, -1); \
931   return -1;
932 }
933 
934 #define DCL_TIMER_CREATE(dcl_f) \
935   int dcl_f (clockid_t clockid, struct sigevent *sevp, timer_t *timerid) \
936   { \
937     if (__real_timer_create == NULL) \
938       init_interposition_intf (); \
939     return gprofng_timer_create (__real_timer_create, clockid, sevp, timerid); \
940   }
941 
942 DCL_FUNC_VER (DCL_TIMER_CREATE, timer_create_2_34, timer_create@GLIBC_2.34)
943 DCL_FUNC_VER (DCL_TIMER_CREATE, timer_create_2_17, timer_create@GLIBC_2.17)
944 DCL_FUNC_VER (DCL_TIMER_CREATE, timer_create_2_3_3, timer_create@GLIBC_2.3.3)
945 DCL_FUNC_VER (DCL_TIMER_CREATE, timer_create_2_2_5, timer_create@GLIBC_2.2.5)
946 DCL_FUNC_VER (DCL_TIMER_CREATE, timer_create_2_2, timer_create@GLIBC_2.2)
DCL_TIMER_CREATE(timer_create)947 DCL_TIMER_CREATE (timer_create)
948 
949 /*------------------------------------------------------------- setitimer */
950 int
951 _setitimer (int which, const struct itimerval *nval,
952 	    struct itimerval *oval)
953 {
954   int ret;
955   int period;
956 
957   if (NULL_PTR (setitimer))
958     init_interposition_intf ();
959 
960   if (nval == NULL)
961     period = -1;
962   else
963     period = (nval->it_interval.tv_sec * MICROSEC) +
964     nval->it_interval.tv_usec;
965   TprintfT (DBG_LT1, "setitimer(which=%d,nval=%dus) interposing\n", which, period);
966 
967   /* collector reserves ITIMER_REALPROF for its own use, and ITIMER_PROF
968    * uses the same signal (SIGPROF) so it must also be reserved
969    */
970   if (((which != ITIMER_REALPROF) && (which != ITIMER_PROF)) || (nval == NULL))
971     {
972       ret = CALL_REAL (setitimer)(which, nval, oval);
973       if (oval == NULL)
974 	period = -1;
975       else
976 	period = (oval->it_interval.tv_sec * MICROSEC) +
977 	oval->it_interval.tv_usec;
978       TprintfT (DBG_LT2, "Real setitimer(%d) returned %d (oval=%dus)\n",
979 		which, ret, period);
980       return ret;
981     }
982   /* log that application's setitimer request is overridden */
983   (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%d</event>\n",
984 				SP_JCMD_CWARN, COL_WARN_ITMROVR, period);
985   if (oval == NULL)
986     period = -1;
987   else
988     {
989       getitimer (which, oval); /* return current itimer setting */
990       period = (oval->it_interval.tv_sec * MICROSEC) +
991 	      oval->it_interval.tv_usec;
992     }
993   ret = -1;
994   errno = EBUSY;
995   TprintfT (DBG_LT2, "setitimer() returning %d (oval=%dus)\n", ret, period);
996   return ret;
997 }
998 
999 /*--------------------------------------------------------------- sigprocmask */
1000 int
__collector_sigprocmask(int how,const sigset_t * iset,sigset_t * oset)1001 __collector_sigprocmask (int how, const sigset_t* iset, sigset_t* oset)
1002 {
1003   int err = 0;
1004   if (NULL_PTR (sigprocmask))
1005     err = init_interposition_intf ();
1006   if (err)
1007     return -1;
1008   TprintfT (DBG_LT2, "__collector_sigprocmask(%d) interposing\n", how);
1009   sigset_t lsigset;
1010   sigset_t* lset = NULL;
1011   if (iset)
1012     {
1013       lsigset = *iset;
1014       lset = &lsigset;
1015       if ((how == SIG_BLOCK) || (how == SIG_SETMASK))
1016 	protect_profiling_signals (lset);
1017     }
1018   int ret = CALL_REAL (sigprocmask)(how, lset, oset);
1019   TprintfT (DBG_LT2, "__collector_sigprocmask(%d) returning %d\n", how, ret);
1020   return ret;
1021 }
1022 
1023 /*------------------------------------------------------------ thr_sigsetmask */
1024 int
__collector_thr_sigsetmask(int how,const sigset_t * iset,sigset_t * oset)1025 __collector_thr_sigsetmask (int how, const sigset_t* iset, sigset_t* oset)
1026 {
1027   if (NULL_PTR (thr_sigsetmask))
1028     init_interposition_intf ();
1029   TprintfT (DBG_LT1, "__collector_thr_sigsetmask(%d) interposing\n", how);
1030   sigset_t lsigset;
1031   sigset_t* lset = NULL;
1032   if (iset)
1033     {
1034       lsigset = *iset;
1035       lset = &lsigset;
1036       if ((how == SIG_BLOCK) || (how == SIG_SETMASK))
1037 	protect_profiling_signals (lset);
1038     }
1039   int ret = CALL_REAL (thr_sigsetmask)(how, lset, oset);
1040   TprintfT (DBG_LT1, "__collector_thr_sigsetmask(%d) returning %d\n", how, ret);
1041   return ret;
1042 }
1043 
1044 /*----------------------------------------------------------- pthread_sigmask */
1045 // map interposed symbol versions
1046 
1047 static int
gprofng_pthread_sigmask(int (real_func)(),int how,const sigset_t * iset,sigset_t * oset)1048 gprofng_pthread_sigmask (int (real_func) (),
1049                          int how, const sigset_t *iset, sigset_t* oset)
1050 {
1051   sigset_t lsigset;
1052   sigset_t* lset = NULL;
1053   if (iset)
1054     {
1055       lsigset = *iset;
1056       lset = &lsigset;
1057       if (how == SIG_BLOCK || how == SIG_SETMASK)
1058         protect_profiling_signals (lset);
1059     }
1060   int ret = (real_func) (how, lset, oset);
1061   TprintfT (DBG_LT1, "real_pthread_sigmask @%p (%d) ret=%d\n",
1062             real_func, how, ret);
1063   return ret;
1064 
1065 }
1066 
1067 #define DCL_PTHREAD_SIGMASK(dcl_f) \
1068   int dcl_f (int how, const sigset_t *iset, sigset_t* oset) \
1069   { \
1070     if (__real_pthread_sigmask == NULL) \
1071       init_interposition_intf (); \
1072     return gprofng_pthread_sigmask (__real_pthread_sigmask, how, iset, oset); \
1073   }
1074 
1075 DCL_FUNC_VER (DCL_PTHREAD_SIGMASK, pthread_sigmask_2_32, pthread_sigmask@GLIBC_2.32)
1076 DCL_FUNC_VER (DCL_PTHREAD_SIGMASK, pthread_sigmask_2_17, pthread_sigmask@GLIBC_2.17)
1077 DCL_FUNC_VER (DCL_PTHREAD_SIGMASK, pthread_sigmask_2_2_5, pthread_sigmask@GLIBC_2.2.5)
1078 DCL_FUNC_VER (DCL_PTHREAD_SIGMASK, pthread_sigmask_2_0, pthread_sigmask@GLIBC_2.0)
1079 DCL_PTHREAD_SIGMASK (pthread_sigmask)
1080 
1081 /*----------------------------------------------------------- pthread_create */
1082 typedef struct _CollectorArgs
1083 {
1084   void *(*func)(void*);
1085   void *arg;
1086   void *stack;
1087   int isPthread;
1088 } CollectorArgs;
1089 
1090 static void *
collector_root(void * cargs)1091 collector_root (void *cargs)
1092 {
1093   /* save the real arguments and free cargs */
1094   void *(*func)(void*) = ((CollectorArgs*) cargs)->func;
1095   void *arg = ((CollectorArgs*) cargs)->arg;
1096   void *stack = ((CollectorArgs*) cargs)->stack;
1097   int isPthread = ((CollectorArgs*) cargs)->isPthread;
1098   __collector_freeCSize (__collector_heap, cargs, sizeof (CollectorArgs));
1099 
1100   /* initialize tsd for this thread */
1101   if (__collector_tsd_allocate () == 0)
1102     /* init tsd for unwind, called right after __collector_tsd_allocate()*/
1103     __collector_ext_unwind_key_init (isPthread, stack);
1104 
1105   if (!isPthread)
1106     __collector_mutex_lock (&collector_clone_libc_lock);
1107 
1108   /* set the profile timer */
1109   timer_t *timeridptr = __collector_tsd_get_by_key (dispatcher_key);
1110   timer_t timerid = NULL;
1111   if (timeridptr != NULL)
1112     {
1113       collector_timer_create (timeridptr);
1114       if (*timeridptr != NULL)
1115 	collector_timer_settime (itimer_period_requested, *timeridptr);
1116       timerid = *timeridptr;
1117     }
1118   int hwc_rc = __collector_ext_hwc_lwp_init ();
1119 
1120   if (!isPthread)
1121     __collector_mutex_unlock (&collector_clone_libc_lock);
1122   /* call the real function */
1123   void *ret = func (arg);
1124   if (!isPthread)
1125     __collector_mutex_lock (&collector_clone_libc_lock);
1126   if (timerid != NULL)
1127     CALL_REAL (timer_delete)(timerid);
1128   if (!hwc_rc)
1129     /* pthread_kill not handled here */
1130     __collector_ext_hwc_lwp_fini ();
1131 
1132   if (!isPthread)
1133     __collector_mutex_unlock (&collector_clone_libc_lock);
1134   /* if we have this chance, release tsd */
1135   __collector_tsd_release ();
1136 
1137   return ret;
1138 }
1139 
1140 // map interposed symbol versions
1141 
1142 static int
gprofng_pthread_create(int (real_func)(),pthread_t * thread,const pthread_attr_t * attr,void * (* func)(void *),void * arg)1143 gprofng_pthread_create (int (real_func) (), pthread_t *thread,
1144                         const pthread_attr_t *attr,
1145                         void *(*func)(void*), void *arg)
1146 {
1147   TprintfT (DBG_LTT, "gprofng_pthread_create @%p\n", real_func);
1148   if (dispatch_mode != DISPATCH_ON)
1149     return (real_func) (thread, attr, func, arg);
1150   CollectorArgs *cargs = __collector_allocCSize (__collector_heap,
1151                                                  sizeof (CollectorArgs), 1);
1152   if (cargs == NULL)
1153     return (real_func) (thread, attr, func, arg);
1154   cargs->func = func;
1155   cargs->arg = arg;
1156   cargs->stack = NULL;
1157   cargs->isPthread = 1;
1158   int ret = (real_func) (thread, attr, &collector_root, cargs);
1159   if (ret)
1160     __collector_freeCSize (__collector_heap, cargs, sizeof (CollectorArgs));
1161   TprintfT (DBG_LT1, "gprofng_pthread_create @%p returns %d\n", real_func, ret);
1162   return ret;
1163 }
1164 
1165 
1166 #define DCL_PTHREAD_CREATE(dcl_f) \
1167   int dcl_f (pthread_t *thread, const pthread_attr_t *attr, \
1168              void *(*func)(void*), void *arg) \
1169   { \
1170     if (__real_pthread_create == NULL) \
1171       init_interposition_intf (); \
1172      return gprofng_pthread_create (__real_pthread_create, thread, attr, func, arg); \
1173   }
1174 
1175 DCL_FUNC_VER (DCL_PTHREAD_CREATE, pthread_create_2_34, pthread_create@GLIBC_2.34)
1176 DCL_FUNC_VER (DCL_PTHREAD_CREATE, pthread_create_2_17, pthread_create@GLIBC_2.17)
1177 DCL_FUNC_VER (DCL_PTHREAD_CREATE, pthread_create_2_2_5, pthread_create@GLIBC_2.2.5)
1178 DCL_FUNC_VER (DCL_PTHREAD_CREATE, pthread_create_2_1, pthread_create@GLIBC_2.1)
1179 DCL_FUNC_VER (DCL_PTHREAD_CREATE, pthread_create_2_0, pthread_create@GLIBC_2.0)
DCL_PTHREAD_CREATE(pthread_create)1180 DCL_PTHREAD_CREATE (pthread_create)
1181 
1182 int
1183 __collector_ext_clone_pthread (int (*fn)(void *), void *child_stack, int flags, void *arg,
1184 			       va_list va /* pid_t *ptid, struct user_desc *tls, pid_t *" ctid" */)
1185 {
1186   if (NULL_PTR (clone))
1187     init_interposition_intf ();
1188   TprintfT (0, "clone thread interposing\n");
1189   pid_t * ptid = NULL;
1190   struct user_desc * tls = NULL;
1191   pid_t * ctid = NULL;
1192   int num_args = 0;
1193   if (flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID))
1194     {
1195       ptid = va_arg (va, pid_t *);
1196       tls = va_arg (va, struct user_desc*);
1197       ctid = va_arg (va, pid_t *);
1198       num_args = 3;
1199     }
1200   else if (flags & CLONE_SETTLS)
1201     {
1202       ptid = va_arg (va, pid_t *);
1203       tls = va_arg (va, struct user_desc*);
1204       num_args = 2;
1205     }
1206   else if (flags & CLONE_PARENT_SETTID)
1207     {
1208       ptid = va_arg (va, pid_t *);
1209       num_args = 1;
1210     }
1211   int ret = 0;
1212   if (dispatch_mode != DISPATCH_ON)
1213     {
1214       switch (num_args)
1215 	{
1216 	case 3:
1217 	  ret = CALL_REAL (clone)(fn, child_stack, flags, arg, ptid, tls, ctid);
1218 	  break;
1219 	case 2:
1220 	  ret = CALL_REAL (clone)(fn, child_stack, flags, arg, ptid, tls);
1221 	  break;
1222 	case 1:
1223 	  ret = CALL_REAL (clone)(fn, child_stack, flags, arg, ptid);
1224 	  break;
1225 	default:
1226 	  ret = CALL_REAL (clone)(fn, child_stack, flags, arg);
1227 	  break;
1228 	}
1229       return ret;
1230     }
1231   CollectorArgs *cargs = __collector_allocCSize (__collector_heap, sizeof (CollectorArgs), 1);
1232   if (cargs == NULL)
1233     {
1234       switch (num_args)
1235 	{
1236 	case 3:
1237 	  ret = CALL_REAL (clone)(fn, child_stack, flags, arg, ptid, tls, ctid);
1238 	  break;
1239 	case 2:
1240 	  ret = CALL_REAL (clone)(fn, child_stack, flags, arg, ptid, tls);
1241 	  break;
1242 	case 1:
1243 	  ret = CALL_REAL (clone)(fn, child_stack, flags, arg, ptid);
1244 	  break;
1245 	default:
1246 	  ret = CALL_REAL (clone)(fn, child_stack, flags, arg);
1247 	  break;
1248 	}
1249       return ret;
1250     }
1251 
1252   cargs->func = (void *(*)(void*))fn;
1253   cargs->arg = arg;
1254   cargs->stack = child_stack;
1255   cargs->isPthread = 0;
1256 
1257   switch (num_args)
1258     {
1259     case 3:
1260       ret = CALL_REAL (clone)((int(*)(void*))collector_root, child_stack, flags, cargs, ptid, tls, ctid);
1261       break;
1262     case 2:
1263       ret = CALL_REAL (clone)((int(*)(void*))collector_root, child_stack, flags, cargs, ptid, tls);
1264       break;
1265     case 1:
1266       ret = CALL_REAL (clone)((int(*)(void*))collector_root, child_stack, flags, cargs, ptid);
1267       break;
1268     default:
1269       ret = CALL_REAL (clone)((int(*)(void*))collector_root, child_stack, flags, cargs);
1270       break;
1271     }
1272 
1273   if (ret < 0)
1274     __collector_freeCSize (__collector_heap, cargs, sizeof (CollectorArgs));
1275   TprintfT (DBG_LT1, "clone thread returning %d\n", ret);
1276   return ret;
1277 }
1278 
1279 // weak symbols:
1280 int sigprocmask () __attribute__ ((weak, alias ("__collector_sigprocmask")));
1281 int thr_sigsetmask () __attribute__ ((weak, alias ("__collector_thr_sigsetmask")));
1282 int setitimer () __attribute__ ((weak, alias ("_setitimer")));
1283