]> Git Repo - binutils.git/blob - gprofng/libcollector/libcol_util.c
Automatic date update in version.in
[binutils.git] / gprofng / libcollector / libcol_util.c
1 /* Copyright (C) 2021 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 #include "config.h"
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <signal.h>
27 #include <dlfcn.h>
28 #include <errno.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <sys/syscall.h>
32 #include <sys/mman.h>
33 #include <sys/ioctl.h>
34
35 #include "gp-defs.h"
36 #include "collector.h"
37 #include "libcol_util.h"
38 #include "gp-experiment.h"
39 #include "Emsgnum.h"
40 #include "memmgr.h"  // __collector_allocCSize, __collector_freeCSize
41 #include "tsd.h"
42
43 /* TprintfT(<level>,...) definitions.  Adjust per module as needed */
44 #define DBG_LT0 0 // for high-level configuration, unexpected errors/warnings
45 #define DBG_LT1 1 // for configuration details, warnings
46 #define DBG_LT2 2
47 #define DBG_LT3 3
48
49 /*
50  *    This file is intended for collector's own implementation of
51  *    various routines to avoid interaction with libc and other
52  *    libraries.
53  */
54
55 /* -------  libc interface ----------------- */
56 CollectorUtilFuncs __collector_util_funcs = {NULL};
57 int __collector_dlsym_guard = 0;
58 int(*__collector_sscanfp)(const char *restrict s, const char *restrict fmt, ...);
59
60 /*
61  * We have calls on Solaris to get the thread ID.
62  * On Linux, there is a gettid() system call.
63  * From user space, we have to use syscall(__NR_gettid).
64  * The call is probably fast (with the tid in vdso), but dbx intercepts the syscall.
65  *     7182047 syscall() has large overhead under dbx on linux
66  * One option is to use an assembly call to get the tid.
67  * We know how to do this on x86, but not on SPARC.
68  * So another option is to do the syscall once and cache the result in thread-local storage.
69  * This solves the SPARC case.
70  * On x86 we could use one or both strategies.  So there are opportunities here to simplify the code.
71  */
72 static unsigned gettid_key = COLLECTOR_TSD_INVALID_KEY;
73
74 void
75 __collector_ext_gettid_tsd_create_key ()
76 {
77   gettid_key = __collector_tsd_create_key (sizeof (pid_t), NULL, NULL);
78 }
79
80 pid_t
81 __collector_gettid ()
82 {
83   pid_t *tid_ptr = (pid_t *) __collector_tsd_get_by_key (gettid_key);
84   // check if we have a thread-specific tid and if it's been initialized
85   // (it's 0 before initialization and cannot be 0 after since pid 0 is the boot process)
86   if (tid_ptr && *tid_ptr > 0)
87     return *tid_ptr;
88   pid_t r;
89
90 #if ARCH(Intel)
91 #if WSIZE(32)
92 #define syscall_instr          "int $0x80"
93 #define syscall_clobber        "memory"
94 #else //WSIZE(64)
95 #define syscall_instr          "syscall"
96 #define syscall_clobber        "rcx", "r11", "memory"
97 #endif
98   __asm__ __volatile__(syscall_instr
99                        : "=a" (r) : "0" (__NR_gettid)
100                        : syscall_clobber);
101 #else
102   r = syscall (__NR_gettid);
103 #endif
104   if (tid_ptr)
105     *tid_ptr = r;
106   return r;
107 }
108
109 static inline int
110 atomic_swap (volatile int * p, int v)
111 {
112 #if ARCH(Intel)
113   int r;
114   __asm__ __volatile__("xchg %1, %2" : "=r" (r) : "m" (*p), "0" (v));
115   return r;
116 #else
117   /* Since the inline templates perfan/libcollector/src/inline.*.il all
118    * have implementations for __collector_cas_32(), how about we just
119    * use that interface for Intel as well and drop the "#if ARCH()" stuff here?
120    *
121    * As it is, we're using an atomic swap on Intel and
122    * compare-and-swap on SPARC.  The semantics are different
123    * (cas requires an expected "compare" value and swaps ONLY
124    * if we match that value).  Nevertheless, the results of the
125    * two operations
126    *     Intel:  atomic_swap(&lock,  1)
127    *     SPARC:          cas(&lock,0,1)
128    * happen to be the same for the two cases we're interested in:
129    *     if lock==0  lock=1 return 0
130    *     if lock==1  lock=1 return 1
131    * You CANNOT always simply substitute cas for swap.
132    */
133   return __collector_cas_32 ((volatile uint32_t *)p, 0, v);
134 #endif
135 }
136
137 int
138 __collector_mutex_lock (collector_mutex_t *lock_var)
139 {
140   volatile unsigned int i; /* xxxx volatile may not be honored on amd64 -x04 */
141
142   if (!(*lock_var) && !atomic_swap (lock_var, 1))
143     return 0;
144
145   do
146     {
147       while ((collector_mutex_t) (*lock_var) == 1)
148         i++;
149     }
150   while (atomic_swap (lock_var, 1));
151   return 0;
152 }
153
154 int
155 __collector_mutex_trylock (collector_mutex_t *lock_var)
156 {
157   if (!(*lock_var) && !atomic_swap (lock_var, 1))
158     return 0;
159   return EBUSY;
160 }
161
162 int
163 __collector_mutex_unlock (collector_mutex_t *lock_var)
164 {
165   (*lock_var) = 0;
166   return 0;
167 }
168
169 #if ARCH(SPARC)
170 void
171 __collector_inc_32 (volatile uint32_t *mem)
172 {
173   uint32_t t1, t2;
174   __asm__ __volatile__("        ld      %2,%0 \n"
175                        "1:      add     %0,1,%1 \n"
176                        "        cas     %2,%0,%1 \n"
177                        "        cmp     %0,%1 \n"
178                        "        bne,a   1b \n"
179                        "        mov     %1,%0 \n"
180                        : "=&r" (t1), "=&r" (t2)
181                        : "m" (*mem)
182                        : "cc"
183                        );
184 }
185
186 void
187 __collector_dec_32 (volatile uint32_t *mem)
188 {
189   uint32_t t1, t2;
190   __asm__ __volatile__("        ld      %2,%0 \n"
191                        "1:      sub     %0,1,%1 \n"
192                        "        cas     %2,%0,%1 \n"
193                        "        cmp     %0,%1 \n"
194                        "        bne,a   1b \n"
195                        "        mov     %1,%0 \n"
196                        : "=&r" (t1), "=&r" (t2)
197                        : "m" (*mem)
198                        : "cc"
199                        );
200 }
201
202 uint32_t
203 __collector_cas_32 (volatile uint32_t *mem, uint32_t old, uint32_t new)
204 {
205   __asm__ __volatile__("cas [%1],%2,%0"
206                        : "+r" (new)
207                        : "r" (mem), "r" (old));
208   return new;
209 }
210
211 uint32_t
212 __collector_subget_32 (volatile uint32_t *mem, uint32_t val)
213 {
214   uint32_t t1, t2;
215   __asm__ __volatile__("        ld      %2,%0 \n"
216                        "1:      sub     %0,%3,%1 \n"
217                        "        cas     %2,%0,%1 \n"
218                        "        cmp     %0,%1 \n"
219                        "        bne,a   1b \n"
220                        "        mov     %1,%0 \n"
221                        "        sub     %0,%3,%1 \n"
222                        : "=&r" (t1), "=&r" (t2)
223                        : "m" (*mem), "r" (val)
224                        : "cc"
225                        );
226   return t2;
227 }
228
229 #if WSIZE(32)
230
231 void *
232 __collector_cas_ptr (volatile void *mem, void *old, void *new)
233 {
234   __asm__ __volatile__("cas [%1],%2,%0"
235                        : "+r" (new)
236                        : "r" (mem), "r" (old));
237   return new;
238 }
239
240 uint64_t
241 __collector_cas_64p (volatile uint64_t *mem, uint64_t *old, uint64_t *new)
242 {
243   uint64_t t;
244   __asm__ __volatile__("        ldx     [%2],%2 \n"
245                        "        ldx     [%3],%3 \n"
246                        "        casx    [%1],%2,%3 \n"
247                        "        stx     %3,%0 \n"
248                        : "=m" (t)
249                        : "r" (mem), "r" (old), "r" (new)
250                        );
251   return t;
252 }
253
254 #elif WSIZE(64)
255
256 void *
257 __collector_cas_ptr (volatile void *mem, void *old, void *new)
258 {
259   __asm__ __volatile__("casx [%1],%2,%0"
260                        : "+r" (new)
261                        : "r" (mem), "r" (old));
262   return new;
263 }
264
265 uint64_t
266 __collector_cas_64p (volatile uint64_t *mem, uint64_t *old, uint64_t *new)
267 {
268   uint64_t t;
269   __asm__ __volatile__("        ldx     [%2],%2 \n"
270                        "        ldx     [%3],%3 \n"
271                        "        casx    [%1],%2,%3 \n"
272                        "        mov     %3,%0 \n"
273                        : "=&r" (t)
274                        : "r" (mem), "r" (old), "r" (new)
275                        );
276   return t;
277 }
278
279 #endif /* WSIZE() */
280 #endif /* ARCH() */
281
282 void *
283 __collector_memcpy (void *s1, const void *s2, size_t n)
284 {
285   char *cp1 = (char*) s1;
286   char *cp2 = (char*) s2;
287   while (n--)
288     *cp1++ = *cp2++;
289   return s1;
290 }
291
292 static void *
293 collector_memset (void *s, int c, size_t n)
294 {
295   unsigned char *s1 = s;
296   while (n--)
297     *s1++ = (unsigned char) c;
298   return s;
299 }
300
301 int
302 __collector_strcmp (const char *s1, const char *s2)
303 {
304   for (;;)
305     {
306       if (*s1 != *s2)
307         return *s1 - *s2;
308       if (*s1 == 0)
309         return 0;
310       s1++;
311       s2++;
312     }
313 }
314
315 int
316 __collector_strncmp (const char *s1, const char *s2, size_t n)
317 {
318   while (n > 0)
319     {
320       if (*s1 != *s2)
321         return *s1 - *s2;
322       if (*s1 == 0)
323         return 0;
324       s1++;
325       s2++;
326       n--;
327     }
328   return 0;
329 }
330
331 char *
332 __collector_strstr (const char *s1, const char *s2)
333 {
334   if (s2 == NULL || *s2 == 0)
335     return NULL;
336   size_t len = __collector_strlen (s2);
337   for (char c = *s2; *s1; s1++)
338     if (c == *s1 && __collector_strncmp (s1, s2, len) == 0)
339       return (char *) s1;
340   return NULL;
341 }
342
343 char *
344 __collector_strchr (const char *str, int chr)
345 {
346   if (chr == '\0')
347     return (char *) (str + __collector_strlen (str));
348   for (; *str; str++)
349     if (chr == (int) *str)
350       return (char *) str;
351   return NULL;
352 }
353
354 char *
355 __collector_strrchr (const char *str, int chr)
356 {
357   const char *p = str + __collector_strlen (str);
358   for (; p - str >= 0; p--)
359     if (chr == *p)
360       return (char *) p;
361   return NULL;
362 }
363
364 int
365 __collector_strStartWith (const char *s1, const char *s2)
366 {
367   size_t slen = __collector_strlen (s2);
368   return __collector_strncmp (s1, s2, slen);
369 }
370
371 size_t
372 __collector_strlen (const char *s)
373 {
374   int len = -1;
375   while (s[++len] != '\0')
376     ;
377   return len;
378 }
379
380 size_t
381 __collector_strlcpy (char *dst, const char *src, size_t dstsize)
382 {
383   size_t srcsize = 0;
384   size_t n = dstsize - 1;
385   char c;
386   while ((c = *src++) != 0)
387     if (srcsize++ < n)
388       *dst++ = c;
389   if (dstsize > 0)
390     *dst = '\0';
391   return srcsize;
392 }
393
394 size_t
395 __collector_strncpy (char *dst, const char *src, size_t dstsize)
396 {
397   size_t i;
398   for (i = 0; i < dstsize; i++)
399     {
400       dst[i] = src[i];
401       if (src[i] == '\0')
402         break;
403     }
404   return i;
405 }
406
407 char *
408 __collector_strcat (char *dst, const char *src)
409 {
410   size_t sz = __collector_strlen (dst);
411   for (size_t i = 0;; i++)
412     {
413       dst[sz + i] = src[i];
414       if (src[i] == '\0')
415         break;
416     }
417   return dst;
418 }
419
420 size_t
421 __collector_strlcat (char *dst, const char *src, size_t dstsize)
422 {
423   size_t sz = __collector_strlen (dst);
424   return sz + __collector_strlcpy (dst + sz, src, dstsize - sz);
425 }
426
427 void *
428 __collector_malloc (size_t size)
429 {
430   void * ptr = __collector_allocCSize (__collector_heap, size, 0);
431   return ptr;
432 }
433
434 void *
435 __collector_calloc (size_t nelem, size_t elsize)
436 {
437   size_t n = nelem * elsize;
438   void * ptr = __collector_malloc (n);
439   if (NULL == ptr)
440     return NULL;
441   collector_memset (ptr, 0, n);
442   return ptr;
443 }
444
445 char *
446 __collector_strdup (const char * str)
447 {
448   if (NULL == str)
449     return NULL;
450   size_t size = __collector_strlen (str);
451   char * dst = (char *) __collector_malloc (size + 1);
452   if (NULL == dst)
453     return NULL;
454   __collector_strncpy (dst, str, size + 1);
455   return dst;
456 }
457
458 #define C_FMT 1
459 #define C_STR 2
460 static char
461 Printable[256] = {//characters should be escaped by xml: "'<>&
462   0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0,   /* ................ */
463   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* ................ */
464   3, 3, 1, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3,   /*  !"#$%&'()*+,-./ */
465   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, 1, 3,   /* 0123456789:;<=>? */
466   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,   /* @ABCDEFGHIJKLMNO */
467   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,   /* PQRSTUVWXYZ[\]^_ */
468   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,   /* `abcdefghijklmno */
469   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0,   /* pqrstuvwxyz{|}~. */
470   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* ................ */
471   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* ................ */
472   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* ................ */
473   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* ................ */
474   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* ................ */
475   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* ................ */
476   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* ................ */
477   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0    /* ................ */
478 };
479 static char hex[17] = "0123456789abcdef";
480 static char HEX[17] = "0123456789ABCDEF";
481
482 int
483 __collector_xml_snprintf (char *s, size_t n, const char *format, ...)
484 {
485   va_list args;
486   va_start (args, format);
487   int res = __collector_xml_vsnprintf (s, n, format, args);
488   va_end (args);
489   return res;
490 }
491
492 int
493 __collector_xml_vsnprintf (char *s, size_t n, const char *format, va_list args)
494 {
495   const char *src = format;
496   char *dst = s;
497   int cnt = 0;
498   unsigned char c;
499   while ((c = *src) != 0)
500     {
501       if (c == '%')
502         {
503           char numbuf[32];
504           int done = 0;
505           int jflag = 0;
506           int lflag = 0;
507           int zflag = 0;
508           int width = 0;
509           src++;
510           while (!done)
511             {
512               c = *src;
513               switch (c)
514                 {
515                 case '%':
516                   {
517                     if (cnt++ < n - 1)
518                       *dst++ = '%';
519                     if (cnt++ < n - 1)
520                       *dst++ = hex[c / 16];
521                     if (cnt++ < n - 1)
522                       *dst++ = hex[c % 16];
523                     if (cnt++ < n - 1)
524                       *dst++ = '%';
525                     src++;
526                     done = 1;
527                     break;
528                   }
529                 case '-':
530                   {
531                     if (jflag != 0)
532                       done = 1;
533                     else
534                       {
535                         jflag = 1;
536                         src++;
537                       }
538                     break;
539                   }
540                 case 'l':
541                   {
542                     if (lflag != 0)
543                       done = 1;
544                     else
545                       {
546                         lflag = 1;
547                         c = *++src;
548                         if (c == 'l')
549                           {
550                             lflag++;
551                             src++;
552                           }
553                       }
554                     break;
555                   }
556                 case 'c':
557                   {
558                     unsigned char c1 = (unsigned char) va_arg (args, int);
559                     if ((Printable[(int) c1] & C_STR) == 0)
560                       {
561                         if (c1 == '"')
562                           {//&quot;
563                             if (cnt++ < n - 1)
564                               *dst++ = '&';
565                             if (cnt++ < n - 1)
566                               *dst++ = 'q';
567                             if (cnt++ < n - 1)
568                               *dst++ = 'u';
569                             if (cnt++ < n - 1)
570                               *dst++ = 'o';
571                             if (cnt++ < n - 1)
572                               *dst++ = 't';
573                             if (cnt++ < n - 1)
574                               *dst++ = ';';
575                           }
576                         else if (c1 == '\'')
577                           {//&apos;
578                             if (cnt++ < n - 1)
579                               *dst++ = '&';
580                             if (cnt++ < n - 1)
581                               *dst++ = 'a';
582                             if (cnt++ < n - 1)
583                               *dst++ = 'p';
584                             if (cnt++ < n - 1)
585                               *dst++ = 'o';
586                             if (cnt++ < n - 1)
587                               *dst++ = 's';
588                             if (cnt++ < n - 1)
589                               *dst++ = ';';
590                           }
591                         else if (c1 == '&')
592                           {//&amp;
593                             if (cnt++ < n - 1)
594                               *dst++ = '&';
595                             if (cnt++ < n - 1)
596                               *dst++ = 'a';
597                             if (cnt++ < n - 1)
598                               *dst++ = 'm';
599                             if (cnt++ < n - 1)
600                               *dst++ = 'p';
601                             if (cnt++ < n - 1)
602                               *dst++ = ';';
603                           }
604                         else if (c1 == '<')
605                           {//&lt;
606                             if (cnt++ < n - 1)
607                               *dst++ = '&';
608                             if (cnt++ < n - 1)
609                               *dst++ = 'l';
610                             if (cnt++ < n - 1)
611                               *dst++ = 't';
612                             if (cnt++ < n - 1)
613                               *dst++ = ';';
614                           }
615                         else if (c1 == '>')
616                           {//&gt;
617                             if (cnt++ < n - 1)
618                               *dst++ = '&';
619                             if (cnt++ < n - 1)
620                               *dst++ = 'g';
621                             if (cnt++ < n - 1)
622                               *dst++ = 't';
623                             if (cnt++ < n - 1)
624                               *dst++ = ';';
625                           }
626                         else
627                           {
628                             if (cnt++ < n - 1)
629                               *dst++ = '%';
630                             if (cnt++ < n - 1)
631                               *dst++ = hex[c1 / 16];
632                             if (cnt++ < n - 1)
633                               *dst++ = hex[c1 % 16];
634                             if (cnt++ < n - 1)
635                               *dst++ = '%';
636                           }
637                       }
638                     else if (cnt++ < n - 1)
639                       *dst++ = c1;
640                     src++;
641                     done = 1;
642                     break;
643                   }
644                 case 's':
645                   {
646                     /* Strings are always left justified */
647                     char *str = va_arg (args, char*);
648                     if (!str)
649                       str = "<NULL>";
650                     unsigned char c1;
651                     while ((c1 = *str++) != 0)
652                       {
653                         if ((Printable[(int) c1] & C_STR) == 0)
654                           {
655                             if (c1 == '"')
656                               {//&quot;
657                                 if (cnt++ < n - 1)
658                                   *dst++ = '&';
659                                 if (cnt++ < n - 1)
660                                   *dst++ = 'q';
661                                 if (cnt++ < n - 1)
662                                   *dst++ = 'u';
663                                 if (cnt++ < n - 1)
664                                   *dst++ = 'o';
665                                 if (cnt++ < n - 1)
666                                   *dst++ = 't';
667                                 if (cnt++ < n - 1)
668                                   *dst++ = ';';
669                               }
670                             else if (c1 == '\'')
671                               {//&apos;
672                                 if (cnt++ < n - 1)
673                                   *dst++ = '&';
674                                 if (cnt++ < n - 1)
675                                   *dst++ = 'a';
676                                 if (cnt++ < n - 1)
677                                   *dst++ = 'p';
678                                 if (cnt++ < n - 1)
679                                   *dst++ = 'o';
680                                 if (cnt++ < n - 1)
681                                   *dst++ = 's';
682                                 if (cnt++ < n - 1)
683                                   *dst++ = ';';
684                               }
685                             else if (c1 == '&')
686                               {//&amp;
687                                 if (cnt++ < n - 1)
688                                   *dst++ = '&';
689                                 if (cnt++ < n - 1)
690                                   *dst++ = 'a';
691                                 if (cnt++ < n - 1)
692                                   *dst++ = 'm';
693                                 if (cnt++ < n - 1)
694                                   *dst++ = 'p';
695                                 if (cnt++ < n - 1)
696                                   *dst++ = ';';
697                               }
698                             else if (c1 == '<')
699                               {//&lt;
700                                 if (cnt++ < n - 1)
701                                   *dst++ = '&';
702                                 if (cnt++ < n - 1)
703                                   *dst++ = 'l';
704                                 if (cnt++ < n - 1)
705                                   *dst++ = 't';
706                                 if (cnt++ < n - 1)
707                                   *dst++ = ';';
708                               }
709                             else if (c1 == '>')
710                               {//&gt;
711                                 if (cnt++ < n - 1)
712                                   *dst++ = '&';
713                                 if (cnt++ < n - 1)
714                                   *dst++ = 'g';
715                                 if (cnt++ < n - 1)
716                                   *dst++ = 't';
717                                 if (cnt++ < n - 1)
718                                   *dst++ = ';';
719                               }
720                             else
721                               {
722                                 if (cnt++ < n - 1)
723                                   *dst++ = '%';
724                                 if (cnt++ < n - 1)
725                                   *dst++ = hex[c1 / 16];
726                                 if (cnt++ < n - 1)
727                                   *dst++ = hex[c1 % 16];
728                                 if (cnt++ < n - 1)
729                                   *dst++ = '%';
730                               }
731                           }
732                         else if (cnt++ < n - 1)
733                           *dst++ = c1;
734                         width--;
735                       }
736                     while (width > 0)
737                       {
738                         if (cnt++ < n - 1)
739                           *dst++ = ' ';
740                         width--;
741                       }
742                     src++;
743                     done = 1;
744                     break;
745                   }
746                 case 'i':
747                 case 'd':
748                 case 'o':
749                 case 'p':
750                 case 'u':
751                 case 'x':
752                 case 'X':
753                   {
754                     int base = 10;
755                     int uflag = 0;
756                     int sflag = 0;
757                     if (c == 'o')
758                       {
759                         uflag = 1;
760                         base = 8;
761                       }
762                     else if (c == 'u')
763                       uflag = 1;
764                     else if (c == 'p')
765                       {
766                         lflag = 1;
767                         uflag = 1;
768                         base = 16;
769                       }
770                     else if (c == 'x' || c == 'X')
771                       {
772                         uflag = 1;
773                         base = 16;
774                       }
775                     long long argll = 0LL;
776                     if (lflag == 0)
777                       {
778                         if (uflag)
779                           argll = va_arg (args, unsigned int);
780                         else
781                           argll = va_arg (args, int);
782                       }
783                     else if (lflag == 1)
784                       {
785                         if (uflag)
786                           argll = va_arg (args, unsigned long);
787                         else
788                           argll = va_arg (args, long);
789                       }
790                     else if (lflag == 2)
791                       argll = va_arg (args, long long);
792                     unsigned long long argllu = 0ULL;
793                     if (uflag || argll >= 0)
794                       argllu = argll;
795                     else
796                       {
797                         sflag = 1;
798                         argllu = -argll;
799                       }
800                     int idx = sizeof (numbuf);
801                     do
802                       {
803                         numbuf[--idx] = (c == 'X' ? HEX[argllu % base] : hex[argllu % base]);
804                         argllu = argllu / base;
805                       }
806                     while (argllu != 0)
807                       ;
808                     if (sflag)
809                       {
810                         if (jflag || zflag)
811                           {
812                             if (cnt++ < n - 1)
813                               *dst++ = '-';
814                           }
815                         else
816                           numbuf[--idx] = '-';
817                       }
818
819                     if (jflag)
820                       {
821                         while (idx < sizeof (numbuf) && width > 0)
822                           {
823                             if (cnt++ < n - 1)
824                               *dst++ = numbuf[idx];
825                             idx++;
826                             width--;
827                           }
828                         zflag = 0;
829                       }
830
831                     while (width > sizeof (numbuf) - idx)
832                       {
833                         if (cnt++ < n - 1)
834                           *dst++ = zflag ? '0' : ' ';
835                         width--;
836                       }
837                     while (idx != sizeof (numbuf))
838                       {
839                         if (cnt++ < n - 1)
840                           *dst++ = numbuf[idx];
841                         idx++;
842                       }
843                     src++;
844                     done = 1;
845                     break;
846                   }
847                 case '0':
848                   zflag = 1;
849                 case '1': case '2': case '3': case '4': case '5':
850                 case '6': case '7': case '8': case '9':
851                   {
852                     while (c >= '0' && c <= '9')
853                       {
854                         width = width * 10 + (c - '0');
855                         c = *++src;
856                       }
857                     break;
858                   }
859                 default:
860                   done = 1;
861                   break;
862                 }
863             }
864         }
865       else if ((Printable[(int) c] & C_FMT) == 0)
866         {
867           if (cnt++ < n - 1)
868             *dst++ = '%';
869           if (cnt++ < n - 1)
870             *dst++ = hex[c / 16];
871           if (cnt++ < n - 1)
872             *dst++ = hex[c % 16];
873           if (cnt++ < n - 1)
874             *dst++ = '%';
875           src++;
876         }
877       else
878         {
879           if (cnt++ < n - 1)
880             *dst++ = c;
881           src++;
882         }
883     }
884
885   if (cnt < n - 1)
886     s[cnt] = '\0';
887   else
888     s[n - 1] = '\0';
889
890   return cnt;
891 }
892
893 /*
894  *    Functions to be called directly from libc.so
895  */
896 #if ARCH(Intel)    /* intel-Linux */
897 /*
898  * The CPUIDinfo/__collector_cpuid() code is old,
899  * incorrect, and complicated.  It returns the apicid
900  * rather than the processor number.
901  *
902  * Unfortunately, the higher-level sched_getcpu() function,
903  * which we use on SPARC-Linux, is not available on Oracle
904  * Linux 5.  So we have to test for its existence.
905  */
906
907 /* a pointer to sched_getcpu(), in case we find it */
908 typedef int (*sched_getcpu_ptr_t)(void);
909 sched_getcpu_ptr_t sched_getcpu_ptr;
910 static int need_warning = 0;
911
912 /* the old, low-level code */
913 static int useLeafB = 0;
914
915 /* access to the CPUID instruction on Intel/AMD */
916 typedef struct
917 {
918   uint32_t eax, ebx, ecx, edx;
919 } CPUIDinfo;
920
921 /**
922  * This function returns the result of the "cpuid" instruction
923  */
924 static __attribute__ ((always_inline)) inline void
925 __collector_cpuid (CPUIDinfo* info)
926 {
927   uint32_t ebx = info->ebx, ecx = info->ecx, edx = info->edx, eax = info->eax;
928   __asm__ ("cpuid" : "=b" (ebx), "=c" (ecx), "=d" (edx), "=a" (eax) : "a" (eax));
929   info->eax = eax;
930   info->ebx = ebx;
931   info->ecx = ecx;
932   info->edx = edx;
933 }
934
935 static void
936 getcpuid_init ()
937 {
938   CPUIDinfo info;
939   info.eax = 0; /* max input value for CPUID */
940   __collector_cpuid (&info);
941
942   if (info.eax >= 0xb)
943     {
944       info.eax = 0xb;
945       info.ecx = 0;
946       __collector_cpuid (&info);
947       useLeafB = info.ebx != 0;
948     }
949
950   /* indicate that we need a warning */
951   /* (need to wait until log mechanism has been initialized) */
952   need_warning = 1;
953 }
954
955 static uint32_t
956 getcpuid ()
957 {
958   /* if we found sched_getcpu(), use it */
959   if (sched_getcpu_ptr)
960     return (*sched_getcpu_ptr)();
961
962   /* otherwise, check if we need warning */
963   if (need_warning)
964     {
965       if (useLeafB)
966         (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">x2APIC</event>\n",
967                                       SP_JCMD_CWARN, COL_WARN_LINUX_X86_APICID);
968       else
969         (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">APIC</event>\n",
970                                       SP_JCMD_CWARN, COL_WARN_LINUX_X86_APICID);
971       need_warning = 0;
972     }
973
974   /* and use the old, low-level code */
975   CPUIDinfo info;
976   if (useLeafB)
977     {
978       info.eax = 0xb;
979       info.ecx = 0;
980       __collector_cpuid (&info);
981       return info.edx; /*  x2APIC ID */
982     }
983   else
984     {
985       info.eax = 0x1;
986       info.ecx = 0;
987       __collector_cpuid (&info);
988       return info.ebx >> 24; /* APIC ID */
989     }
990 }
991
992 #else /* sparc-Linux */
993
994 /*
995  * EUGENE
996  * How should sched_getcpu() be prototyped?  Like this?
997  *     #include <sched.h>
998  * Or like this?
999  *     #define _GNU_SOURCE
1000  *     #include <utmpx.h>
1001  * Or just prototype this function explicitly without bothering with include files.
1002  */
1003 int sched_getcpu ();
1004
1005 static int
1006 getcpuid ()
1007 {
1008   return sched_getcpu ();
1009 }
1010 #endif
1011
1012 /* if ever retries time-out, we will stop allowing them */
1013 static int exhausted_retries = 0;
1014
1015 int
1016 __collector_open (const char *path, int oflag, ...)
1017 {
1018   int fd;
1019   mode_t mode = 0;
1020
1021   hrtime_t t_timeout = __collector_gethrtime () + 5 * ((hrtime_t) NANOSEC);
1022   int nretries = 0;
1023   long long delay = 100; /* start at some small, arbitrary value */
1024
1025   /* get optional mode argument if it's expected/required */
1026   if (oflag | O_CREAT)
1027     {
1028       va_list ap;
1029       va_start (ap, oflag);
1030       mode = (mode_t) va_arg (ap, mode_t);
1031       va_end (ap);
1032     }
1033
1034   /* retry upon failure */
1035   while ((fd = CALL_UTIL (open_bare)(path, oflag, mode)) < 0)
1036     {
1037       if (exhausted_retries)
1038         break;
1039
1040       /* The particular condition we're willing to retry is if
1041        * too many file descriptors were in use.  The errno should
1042        * be EMFILE, but apparently and mysteriously it can also be
1043        * and often is ENOENT.
1044        */
1045       if ((errno != EMFILE) && (errno != ENOENT))
1046         break;
1047       if (__collector_gethrtime () > t_timeout)
1048         {
1049           exhausted_retries = 1;
1050           break;
1051         }
1052
1053       /* Oddly, if I replace this spin wait with
1054        *   -  a usleep() call or
1055        *   -  a loop on gethrtime() calls
1056        * for roughly the same length of time, retries aren't very effective. */
1057       int ispin;
1058       double xdummy = 0.5;
1059       for (ispin = 0; ispin < delay; ispin++)
1060         xdummy = 0.5 * (xdummy + 1.);
1061       if (xdummy < 0.1)
1062         /* should never happen, but we check so the loop won't be optimized away */
1063         break;
1064       delay *= 2;
1065       if (delay > 100000000)
1066         delay = 100000000; /* cap at some large, arbitrary value */
1067       nretries++;
1068     }
1069   return fd;
1070 }
1071
1072 int
1073 __collector_util_init ()
1074 {
1075   int oldos = 0;
1076
1077   /* Linux requires RTLD_LAZY, Solaris can do just RTLD_NOLOAD */
1078   void *libc = dlopen (SYS_LIBC_NAME, RTLD_LAZY | RTLD_NOLOAD);
1079   if (libc == NULL)
1080     libc = dlopen (SYS_LIBC_NAME, RTLD_NOW | RTLD_LOCAL);
1081   if (libc == NULL)
1082     {
1083       /* libcollector will subsequently abort, as all the pointers in the vector are NULL */
1084 #if 0
1085       /* SP_COLLECTOR_TRACELEVEL is not yet set, so no Tprintf */
1086       fprintf (stderr, "__collector_util_init: dlopen(%s) failed: %s\n", SYS_LIBC_NAME, dlerror ());
1087       return COL_ERROR_UTIL_INIT;
1088 #endif
1089       abort ();
1090     }
1091
1092   void *ptr = dlsym (libc, "fprintf");
1093   if (ptr)
1094     __collector_util_funcs.fprintf = (int(*)(FILE *, const char *, ...))ptr;
1095   else
1096     {
1097       // We can't write any error messages without a libc reference
1098 #if 0
1099       fprintf (stderr, "__collector_util_init: COLERROR_UTIL_INIT fprintf: %s\n", dlerror ());
1100       return COL_ERROR_UTIL_INIT;
1101 #endif
1102       abort ();
1103     }
1104   int err = 0;
1105
1106   ptr = dlsym (libc, "mmap");
1107   if (ptr)
1108     __collector_util_funcs.mmap = (void*(*)(void *, size_t, int, int, int, off_t))ptr;
1109   else
1110     {
1111       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT mmap: %s\n", dlerror ());
1112       err = COL_ERROR_UTIL_INIT;
1113     }
1114
1115   /* mmap64 is only in 32-bits; this call goes to mmap in 64-bits */
1116   /*    internal calls for mapping in libcollector call mmap64 */
1117   ptr = dlsym (libc, "mmap64");
1118   if (ptr)
1119     __collector_util_funcs.mmap64_ = (void*(*)(void *, size_t, int, int, int, off_t))ptr;
1120   else
1121     __collector_util_funcs.mmap64_ = __collector_util_funcs.mmap;
1122
1123   ptr = dlsym (libc, "munmap");
1124   if (ptr)
1125     __collector_util_funcs.munmap = (int(*)())ptr;
1126   else
1127     {
1128       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT munmap: %s\n", dlerror ());
1129       err = COL_ERROR_UTIL_INIT;
1130     }
1131
1132   ptr = dlsym (libc, "close");
1133   if (ptr)
1134     __collector_util_funcs.close = (int(*)())ptr;
1135   else
1136     {
1137       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT close: %s\n", dlerror ());
1138       err = COL_ERROR_UTIL_INIT;
1139     }
1140
1141   ptr = dlsym (libc, "open");
1142   if (ptr)
1143     __collector_util_funcs.open = (int(*)(const char *path, int oflag, ...))ptr;
1144   else
1145     {
1146       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT open: %s\n", dlerror ());
1147       err = COL_ERROR_UTIL_INIT;
1148     }
1149
1150 #if ARCH(Intel) && WSIZE(32)
1151   ptr = dlvsym (libc, "open64", "GLIBC_2.2"); // it is in /lib/libpthread.so.0
1152   if (ptr)
1153     __collector_util_funcs.open_bare = (int(*)(const char *path, int oflag, ...))ptr;
1154   else
1155     {
1156       Tprintf (DBG_LT0, "libcol_util: WARNING: dlvsym for %s@%s failed. Using dlsym() instead.", "open64", "GLIBC_2.2");
1157 #endif /* ARCH(Intel) && WSIZE(32) */
1158       ptr = dlsym (libc, "open64");
1159       if (ptr)
1160         __collector_util_funcs.open_bare = (int(*)(const char *path, int oflag, ...))ptr;
1161       else
1162         __collector_util_funcs.open_bare = __collector_util_funcs.open;
1163 #if ARCH(Intel) && WSIZE(32)
1164     }
1165 #endif /* ARCH(Intel) && WSIZE(32) */
1166
1167   ptr = dlsym (libc, "close");
1168   if (ptr)
1169     __collector_util_funcs.close = (int(*)())ptr;
1170   else
1171     {
1172       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT close: %s\n", dlerror ());
1173       err = COL_ERROR_UTIL_INIT;
1174     }
1175
1176   ptr = dlsym (libc, "read");
1177   if (ptr)
1178     __collector_util_funcs.read = (ssize_t (*)())ptr;
1179   else
1180     {
1181       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT read: %s\n", dlerror ());
1182       err = COL_ERROR_UTIL_INIT;
1183     }
1184
1185   ptr = dlsym (libc, "write");
1186   if (ptr)
1187     __collector_util_funcs.write = (ssize_t (*)())ptr;
1188   else
1189     {
1190       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT write: %s\n", dlerror ());
1191       err = COL_ERROR_UTIL_INIT;
1192     }
1193
1194 #if ARCH(Intel) && WSIZE(32)
1195   ptr = dlvsym (libc, "pwrite", "GLIBC_2.2"); // it is in /lib/libpthread.so.0
1196   if (ptr)
1197     __collector_util_funcs.pwrite = (ssize_t (*)())ptr;
1198   else
1199     {
1200       Tprintf (DBG_LT0, "libcol_util: WARNING: dlvsym for %s@%s failed. Using dlsym() instead.", "pwrite", "GLIBC_2.2");
1201 #endif /* ARCH(Intel) && WSIZE(32) */
1202       ptr = dlsym (libc, "pwrite");
1203       if (ptr)
1204         __collector_util_funcs.pwrite = (ssize_t (*)())ptr;
1205       else
1206         {
1207           CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT pwrite: %s\n", dlerror ());
1208           err = COL_ERROR_UTIL_INIT;
1209         }
1210 #if ARCH(Intel) && WSIZE(32)
1211     }
1212 #endif
1213
1214 #if ARCH(Intel) && WSIZE(32)
1215   ptr = dlvsym (libc, "pwrite64", "GLIBC_2.2"); // it is in /lib/libpthread.so.0
1216   if (ptr)
1217     __collector_util_funcs.pwrite64_ = (ssize_t (*)())ptr;
1218   else
1219     {
1220       Tprintf (DBG_LT0, "libcol_util: WARNING: dlvsym for %s@%s failed. Using dlsym() instead.", "pwrite64", "GLIBC_2.2");
1221 #endif /* ARCH(Intel) && WSIZE(32) */
1222       ptr = dlsym (libc, "pwrite64");
1223       if (ptr)
1224         __collector_util_funcs.pwrite64_ = (ssize_t (*)())ptr;
1225       else
1226         __collector_util_funcs.pwrite64_ = __collector_util_funcs.pwrite;
1227 #if ARCH(Intel) && WSIZE(32)
1228     }
1229 #endif /* ARCH(Intel) && WSIZE(32) */
1230
1231   ptr = dlsym (libc, "lseek");
1232   if (ptr)
1233     __collector_util_funcs.lseek = (off_t (*)())ptr;
1234   else
1235     {
1236       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT lseek: %s\n", dlerror ());
1237       err = COL_ERROR_UTIL_INIT;
1238     }
1239
1240   ptr = dlsym (libc, "access");
1241   if (ptr)
1242     __collector_util_funcs.access = (int(*)())ptr;
1243   else
1244     {
1245       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT access: %s\n", dlerror ());
1246       err = COL_ERROR_UTIL_INIT;
1247     }
1248
1249   ptr = dlsym (libc, "mkdir");
1250   if (ptr)
1251     __collector_util_funcs.mkdir = (int(*)())ptr;
1252   else
1253     {
1254       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT mkdir: %s\n", dlerror ());
1255       err = COL_ERROR_UTIL_INIT;
1256     }
1257
1258   ptr = dlsym (libc, "opendir");
1259   if (ptr)
1260     __collector_util_funcs.opendir = (DIR * (*)())ptr;
1261   else
1262     {
1263       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT opendir: %s\n", dlerror ());
1264       err = COL_ERROR_UTIL_INIT;
1265     }
1266
1267   ptr = dlsym (libc, "closedir");
1268   if (ptr)
1269     __collector_util_funcs.closedir = (int(*)())ptr;
1270   else
1271     {
1272       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT closedir: %s\n", dlerror ());
1273       err = COL_ERROR_UTIL_INIT;
1274     }
1275
1276   ptr = dlsym (libc, "execv");
1277   if (ptr)
1278     __collector_util_funcs.execv = (int(*)())ptr;
1279   else
1280     {
1281       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT execv: %s\n", dlerror ());
1282       err = COL_ERROR_UTIL_INIT;
1283     }
1284
1285   ptr = dlsym (libc, "exit");
1286   if (ptr)
1287     __collector_util_funcs.exit = (void(*)())ptr;
1288   else
1289     {
1290       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT exit: %s\n", dlerror ());
1291       err = COL_ERROR_UTIL_INIT;
1292     }
1293
1294   ptr = dlsym (libc, "vfork");
1295   if (ptr)
1296     __collector_util_funcs.vfork = (pid_t (*)())ptr;
1297   else
1298     {
1299       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT vfork: %s\n", dlerror ());
1300       err = COL_ERROR_UTIL_INIT;
1301     }
1302
1303   ptr = dlsym (libc, "waitpid");
1304   if (ptr)
1305     __collector_util_funcs.waitpid = (pid_t (*)())ptr;
1306   else
1307     {
1308       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT waitpid: %s\n", dlerror ());
1309       err = COL_ERROR_UTIL_INIT;
1310     }
1311
1312   int (*__collector_getcpuid)() = (int(*)()) & getcpuid;
1313 #if ARCH(Intel)
1314   /* if sched_getcpu() not found, init our getcpuid() */
1315   sched_getcpu_ptr = (sched_getcpu_ptr_t) dlsym (libc, "sched_getcpu");
1316   if (sched_getcpu_ptr == NULL)
1317     getcpuid_init ();
1318 #endif
1319   __collector_util_funcs.getcpuid = __collector_getcpuid;
1320   __collector_util_funcs.memset = collector_memset;
1321
1322   ptr = dlsym (libc, "getcontext");
1323   if (ptr)
1324     __collector_util_funcs.getcontext = (int(*)())ptr;
1325   else
1326     {
1327       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT getcontext: %s\n", dlerror ());
1328       err = COL_ERROR_UTIL_INIT;
1329     }
1330
1331   ptr = dlsym (libc, "malloc");
1332   if (ptr)
1333     __collector_util_funcs.malloc = (void *(*)(size_t))ptr;
1334   else
1335     {
1336       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT malloc: %s\n", dlerror ());
1337       err = COL_ERROR_UTIL_INIT;
1338     }
1339
1340   ptr = dlsym (libc, "putenv");
1341   if (ptr)
1342     __collector_util_funcs.putenv = (int(*)())ptr;
1343   else
1344     {
1345       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT putenv: %s\n", dlerror ());
1346       err = COL_ERROR_UTIL_INIT;
1347     }
1348
1349   ptr = dlsym (libc, "getenv");
1350   if (ptr)
1351     __collector_util_funcs.getenv = (char*(*)())ptr;
1352   else
1353     {
1354       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT getenv: %s\n", dlerror ());
1355       err = COL_ERROR_UTIL_INIT;
1356     }
1357
1358   ptr = dlsym (libc, "time");
1359   if (ptr)
1360     __collector_util_funcs.time = (time_t (*)())ptr;
1361   else
1362     {
1363       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT time: %s\n", dlerror ());
1364       err = COL_ERROR_UTIL_INIT;
1365     }
1366
1367   ptr = dlsym (libc, "mktime");
1368   if (ptr)
1369     __collector_util_funcs.mktime = (time_t (*)())ptr;
1370   else
1371     {
1372       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT mktime: %s\n", dlerror ());
1373       err = COL_ERROR_UTIL_INIT;
1374     }
1375
1376   __collector_util_funcs.strcmp = __collector_strcmp;
1377   __collector_util_funcs.strncmp = __collector_strncmp;
1378   __collector_util_funcs.strncpy = __collector_strncpy;
1379   __collector_util_funcs.strstr = __collector_strstr;
1380
1381   ptr = dlsym (libc, "gmtime_r");
1382   if (ptr)
1383     __collector_util_funcs.gmtime_r = (struct tm * (*)())ptr;
1384   else
1385     {
1386       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT gmtime_r: %s\n", dlerror ());
1387       err = COL_ERROR_UTIL_INIT;
1388     }
1389
1390   ptr = dlsym (libc, "strtol");
1391   if (ptr)
1392     __collector_util_funcs.strtol = (long (*)())ptr;
1393   else
1394     {
1395       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT strtol: %s\n", dlerror ());
1396       err = COL_ERROR_UTIL_INIT;
1397     }
1398
1399   ptr = dlsym (libc, "strtoll");
1400   if (ptr)
1401     __collector_util_funcs.strtoll = (long long (*)())ptr;
1402   else
1403     {
1404       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT strtoll: %s\n", dlerror ());
1405       err = COL_ERROR_UTIL_INIT;
1406     }
1407
1408   __collector_util_funcs.strchr = __collector_strchr;
1409   __collector_util_funcs.strrchr = __collector_strrchr;
1410
1411   ptr = dlsym (libc, "setenv");
1412   if (ptr)
1413     __collector_util_funcs.setenv = (int(*)())ptr;
1414   else
1415     {
1416       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT setenv: %s\n", dlerror ());
1417       err = COL_ERROR_UTIL_INIT;
1418     }
1419
1420   ptr = dlsym (libc, "unsetenv");
1421   if (ptr)
1422     __collector_util_funcs.unsetenv = (int(*)())ptr;
1423   else
1424     {
1425       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT unsetenv: %s\n", dlerror ());
1426       err = COL_ERROR_UTIL_INIT;
1427     }
1428
1429   ptr = dlsym (libc, "atof");
1430   if (ptr)
1431     __collector_util_funcs.atof = (double (*)())ptr;
1432   else
1433     {
1434       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT atof: %s\n", dlerror ());
1435       err = COL_ERROR_UTIL_INIT;
1436     }
1437
1438   ptr = dlsym (libc, "sysinfo");
1439   if (ptr)
1440     __collector_util_funcs.sysinfo = (long (*)())ptr;
1441   else
1442     {
1443       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT sysinfo: %s\n", dlerror ());
1444       err = COL_ERROR_UTIL_INIT;
1445     }
1446
1447   ptr = dlsym (libc, "clearenv");
1448   if (ptr)
1449     __collector_util_funcs.clearenv = (int(*)())ptr;
1450   else
1451     {
1452       /* suppress warning on S10 or earlier Solaris */
1453       if (oldos == 0)
1454         CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT clearenv: %s\n", dlerror ());
1455       /* err = COL_ERROR_UTIL_INIT; */
1456       /* don't treat this as fatal, so that S10 could work */
1457     }
1458
1459 #if ARCH(Intel) && WSIZE(32)
1460   ptr = dlvsym (libc, "fopen", "GLIBC_2.1");
1461   if (ptr)
1462     __collector_util_funcs.fopen = (FILE * (*)())ptr;
1463   else
1464     {
1465       Tprintf (DBG_LT0, "libcol_util: WARNING: dlvsym for %s@%s failed. Using dlsym() instead.", "fopen", "GLIBC_2.1");
1466 #endif /* ARCH(Intel) && WSIZE(32) */
1467       ptr = dlsym (libc, "fopen");
1468       if (ptr)
1469         __collector_util_funcs.fopen = (FILE * (*)())ptr;
1470       else
1471         {
1472           CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT fopen: %s\n", dlerror ());
1473           err = COL_ERROR_UTIL_INIT;
1474         }
1475 #if ARCH(Intel) && WSIZE(32)
1476     }
1477 #endif
1478
1479   ptr = dlsym (libc, "popen");
1480   if (ptr)
1481     __collector_util_funcs.popen = (FILE * (*)())ptr;
1482   else
1483     {
1484       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT popen: %s\n", dlerror ());
1485       err = COL_ERROR_UTIL_INIT;
1486     }
1487
1488 #if ARCH(Intel) && WSIZE(32)
1489   ptr = dlvsym (libc, "fclose", "GLIBC_2.1");
1490   if (ptr)
1491     __collector_util_funcs.fclose = (int(*)())ptr;
1492   else
1493     {
1494       Tprintf (DBG_LT0, "libcol_util: WARNING: dlvsym for %s@%s failed. Using dlsym() instead.", "fclose", "GLIBC_2.1");
1495 #endif /* ARCH(Intel) && WSIZE(32) */
1496       ptr = dlsym (libc, "fclose");
1497       if (ptr)
1498         __collector_util_funcs.fclose = (int(*)())ptr;
1499       else
1500         {
1501           CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT fclose: %s\n", dlerror ());
1502           err = COL_ERROR_UTIL_INIT;
1503         }
1504 #if ARCH(Intel) && WSIZE(32)
1505     }
1506 #endif
1507
1508   ptr = dlsym (libc, "pclose");
1509   if (ptr)
1510     __collector_util_funcs.pclose = (int(*)())ptr;
1511   else
1512     {
1513       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT pclose: %s\n", dlerror ());
1514       err = COL_ERROR_UTIL_INIT;
1515     }
1516
1517   ptr = dlsym (libc, "fgets");
1518   if (ptr)
1519     __collector_util_funcs.fgets = (char*(*)())ptr;
1520   else
1521     {
1522       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT fgets: %s\n", dlerror ());
1523       err = COL_ERROR_UTIL_INIT;
1524     }
1525
1526   ptr = dlsym (libc, "sscanf");
1527   if (ptr)
1528     __collector_sscanfp = (int(*)(const char *restrict s, const char *restrict fmt, ...))ptr;
1529   else
1530     {
1531       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT sscanf: %s\n", dlerror ());
1532       err = COL_ERROR_UTIL_INIT;
1533     }
1534
1535   ptr = dlsym (libc, "snprintf");
1536   if (ptr)
1537     __collector_util_funcs.snprintf = (int(*)(char *, size_t, const char *, ...))ptr;
1538   else
1539     {
1540       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT snprintf: %s\n", dlerror ());
1541       err = COL_ERROR_UTIL_INIT;
1542     }
1543
1544   ptr = dlsym (libc, "vsnprintf");
1545   if (ptr)
1546     __collector_util_funcs.vsnprintf = (int(*)())ptr;
1547   else
1548     {
1549       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT vsnprintf: %s\n", dlerror ());
1550       err = COL_ERROR_UTIL_INIT;
1551     }
1552
1553   ptr = dlsym (libc, "atoi");
1554   if (ptr)
1555     __collector_util_funcs.atoi = (int(*)())ptr;
1556   else
1557     {
1558       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT atoi: %s\n", dlerror ());
1559       err = COL_ERROR_UTIL_INIT;
1560     }
1561
1562   ptr = dlsym (libc, "calloc");
1563   if (ptr)
1564     __collector_util_funcs.calloc = (void*(*)())ptr;
1565   else
1566     {
1567       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT calloc: %s\n", dlerror ());
1568       err = COL_ERROR_UTIL_INIT;
1569     }
1570
1571   ptr = dlsym (libc, "free");
1572   if (ptr)
1573     {
1574       __collector_util_funcs.free = (void(*)())ptr;
1575     }
1576   else
1577     {
1578       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT free: %s\n", dlerror ());
1579       err = COL_ERROR_UTIL_INIT;
1580     }
1581
1582   ptr = dlsym (libc, "strdup");
1583   if (ptr)
1584     __collector_util_funcs.libc_strdup = (char*(*)())ptr;
1585   else
1586     {
1587       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT strdup: %s\n", dlerror ());
1588       err = COL_ERROR_UTIL_INIT;
1589     }
1590
1591   __collector_util_funcs.strlen = __collector_strlen;
1592   __collector_util_funcs.strlcat = __collector_strlcat;
1593   __collector_util_funcs.strlcpy = __collector_strlcpy;
1594
1595   ptr = dlsym (libc, "strerror");
1596   if (ptr)
1597     __collector_util_funcs.strerror = (char*(*)())ptr;
1598   else
1599     {
1600       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT strerror: %s\n", dlerror ());
1601       err = COL_ERROR_UTIL_INIT;
1602     }
1603   ptr = dlsym (libc, "strerror_r");
1604   if (ptr)
1605     __collector_util_funcs.strerror_r = (int(*)())ptr;
1606   else
1607     {
1608       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT strerror_r: %s\n", dlerror ());
1609       err = COL_ERROR_UTIL_INIT;
1610     }
1611   ptr = dlsym (libc, "strspn");
1612   if (ptr)
1613     __collector_util_funcs.strspn = (size_t (*)())ptr;
1614   else
1615     {
1616       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT strspn: %s\n", dlerror ());
1617       err = COL_ERROR_UTIL_INIT;
1618     }
1619
1620   ptr = dlsym (libc, "strtoul");
1621   if (ptr)
1622     __collector_util_funcs.strtoul = (unsigned long int(*)())ptr;
1623   else
1624     {
1625       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT strtoul: %s\n", dlerror ());
1626       err = COL_ERROR_UTIL_INIT;
1627     }
1628
1629   ptr = dlsym (libc, "strtoull");
1630   if (ptr)
1631     __collector_util_funcs.strtoull = (unsigned long long int(*)())ptr;
1632   else
1633     {
1634       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT strtoull: %s\n", dlerror ());
1635       err = COL_ERROR_UTIL_INIT;
1636     }
1637
1638   ptr = dlsym (libc, "fcntl");
1639   if (ptr)
1640     __collector_util_funcs.fcntl = (int(*)(int, int, ...))ptr;
1641   else
1642     {
1643       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT fcntl: %s\n", dlerror ());
1644       err = COL_ERROR_UTIL_INIT;
1645     }
1646
1647   ptr = dlsym (libc, "ioctl");
1648   if (ptr)
1649     __collector_util_funcs.ioctl = (int(*)(int, int, ...))ptr;
1650   else
1651     {
1652       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT ioctl: %s\n", dlerror ());
1653       err = COL_ERROR_UTIL_INIT;
1654     }
1655
1656   ptr = dlsym (libc, "symlink");
1657   if (ptr)
1658     __collector_util_funcs.symlink = (int(*)(const char*, const char*))ptr;
1659   else
1660     {
1661       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT symlink: %s\n", dlerror ());
1662       err = COL_ERROR_UTIL_INIT;
1663     }
1664
1665   ptr = dlsym (libc, "syscall");
1666   if (ptr)
1667     __collector_util_funcs.syscall = (int(*)(int, ...))ptr;
1668   else
1669     {
1670       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT syscall: %s\n", dlerror ());
1671       err = COL_ERROR_UTIL_INIT;
1672     }
1673
1674   ptr = dlsym (libc, "sysconf");
1675   if (ptr)
1676     __collector_util_funcs.sysconf = (long(*)())ptr;
1677   else
1678     {
1679       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT sysconf: %s\n", dlerror ());
1680       err = COL_ERROR_UTIL_INIT;
1681     }
1682
1683   ptr = dlsym (libc, "sigfillset");
1684   if (ptr)
1685     __collector_util_funcs.sigfillset = (int(*)())ptr;
1686   else
1687     {
1688       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT sigfillset: %s\n", dlerror ());
1689       err = COL_ERROR_UTIL_INIT;
1690     }
1691
1692   ptr = dlsym (libc, "sigprocmask");
1693   if (ptr)
1694     __collector_util_funcs.sigprocmask = (int(*)())ptr;
1695   else
1696     {
1697       CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT sigprocmask: %s\n", dlerror ());
1698       err = COL_ERROR_UTIL_INIT;
1699     }
1700
1701   return err;
1702 }
This page took 0.129703 seconds and 4 git commands to generate.