gprofng: Don't hardcode -Wno-nonnull-compare
[binutils-gdb.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, "malloc");
1323 if (ptr)
1324 __collector_util_funcs.malloc = (void *(*)(size_t))ptr;
1325 else
1326 {
1327 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT malloc: %s\n", dlerror ());
1328 err = COL_ERROR_UTIL_INIT;
1329 }
1330
1331 ptr = dlsym (libc, "putenv");
1332 if (ptr)
1333 __collector_util_funcs.putenv = (int(*)())ptr;
1334 else
1335 {
1336 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT putenv: %s\n", dlerror ());
1337 err = COL_ERROR_UTIL_INIT;
1338 }
1339
1340 ptr = dlsym (libc, "getenv");
1341 if (ptr)
1342 __collector_util_funcs.getenv = (char*(*)())ptr;
1343 else
1344 {
1345 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT getenv: %s\n", dlerror ());
1346 err = COL_ERROR_UTIL_INIT;
1347 }
1348
1349 ptr = dlsym (libc, "time");
1350 if (ptr)
1351 __collector_util_funcs.time = (time_t (*)())ptr;
1352 else
1353 {
1354 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT time: %s\n", dlerror ());
1355 err = COL_ERROR_UTIL_INIT;
1356 }
1357
1358 ptr = dlsym (libc, "mktime");
1359 if (ptr)
1360 __collector_util_funcs.mktime = (time_t (*)())ptr;
1361 else
1362 {
1363 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT mktime: %s\n", dlerror ());
1364 err = COL_ERROR_UTIL_INIT;
1365 }
1366
1367 __collector_util_funcs.strcmp = __collector_strcmp;
1368 __collector_util_funcs.strncmp = __collector_strncmp;
1369 __collector_util_funcs.strncpy = __collector_strncpy;
1370 __collector_util_funcs.strstr = __collector_strstr;
1371
1372 ptr = dlsym (libc, "gmtime_r");
1373 if (ptr)
1374 __collector_util_funcs.gmtime_r = (struct tm * (*)())ptr;
1375 else
1376 {
1377 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT gmtime_r: %s\n", dlerror ());
1378 err = COL_ERROR_UTIL_INIT;
1379 }
1380
1381 ptr = dlsym (libc, "strtol");
1382 if (ptr)
1383 __collector_util_funcs.strtol = (long (*)())ptr;
1384 else
1385 {
1386 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT strtol: %s\n", dlerror ());
1387 err = COL_ERROR_UTIL_INIT;
1388 }
1389
1390 ptr = dlsym (libc, "strtoll");
1391 if (ptr)
1392 __collector_util_funcs.strtoll = (long long (*)())ptr;
1393 else
1394 {
1395 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT strtoll: %s\n", dlerror ());
1396 err = COL_ERROR_UTIL_INIT;
1397 }
1398
1399 __collector_util_funcs.strchr = __collector_strchr;
1400 __collector_util_funcs.strrchr = __collector_strrchr;
1401
1402 ptr = dlsym (libc, "setenv");
1403 if (ptr)
1404 __collector_util_funcs.setenv = (int(*)())ptr;
1405 else
1406 {
1407 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT setenv: %s\n", dlerror ());
1408 err = COL_ERROR_UTIL_INIT;
1409 }
1410
1411 ptr = dlsym (libc, "unsetenv");
1412 if (ptr)
1413 __collector_util_funcs.unsetenv = (int(*)())ptr;
1414 else
1415 {
1416 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT unsetenv: %s\n", dlerror ());
1417 err = COL_ERROR_UTIL_INIT;
1418 }
1419
1420 ptr = dlsym (libc, "atof");
1421 if (ptr)
1422 __collector_util_funcs.atof = (double (*)())ptr;
1423 else
1424 {
1425 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT atof: %s\n", dlerror ());
1426 err = COL_ERROR_UTIL_INIT;
1427 }
1428
1429 ptr = dlsym (libc, "sysinfo");
1430 if (ptr)
1431 __collector_util_funcs.sysinfo = (long (*)())ptr;
1432 else
1433 {
1434 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT sysinfo: %s\n", dlerror ());
1435 err = COL_ERROR_UTIL_INIT;
1436 }
1437
1438 ptr = dlsym (libc, "clearenv");
1439 if (ptr)
1440 __collector_util_funcs.clearenv = (int(*)())ptr;
1441 else
1442 {
1443 /* suppress warning on S10 or earlier Solaris */
1444 if (oldos == 0)
1445 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT clearenv: %s\n", dlerror ());
1446 /* err = COL_ERROR_UTIL_INIT; */
1447 /* don't treat this as fatal, so that S10 could work */
1448 }
1449
1450 #if ARCH(Intel) && WSIZE(32)
1451 ptr = dlvsym (libc, "fopen", "GLIBC_2.1");
1452 if (ptr)
1453 __collector_util_funcs.fopen = (FILE * (*)())ptr;
1454 else
1455 {
1456 Tprintf (DBG_LT0, "libcol_util: WARNING: dlvsym for %s@%s failed. Using dlsym() instead.", "fopen", "GLIBC_2.1");
1457 #endif /* ARCH(Intel) && WSIZE(32) */
1458 ptr = dlsym (libc, "fopen");
1459 if (ptr)
1460 __collector_util_funcs.fopen = (FILE * (*)())ptr;
1461 else
1462 {
1463 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT fopen: %s\n", dlerror ());
1464 err = COL_ERROR_UTIL_INIT;
1465 }
1466 #if ARCH(Intel) && WSIZE(32)
1467 }
1468 #endif
1469
1470 ptr = dlsym (libc, "popen");
1471 if (ptr)
1472 __collector_util_funcs.popen = (FILE * (*)())ptr;
1473 else
1474 {
1475 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT popen: %s\n", dlerror ());
1476 err = COL_ERROR_UTIL_INIT;
1477 }
1478
1479 #if ARCH(Intel) && WSIZE(32)
1480 ptr = dlvsym (libc, "fclose", "GLIBC_2.1");
1481 if (ptr)
1482 __collector_util_funcs.fclose = (int(*)())ptr;
1483 else
1484 {
1485 Tprintf (DBG_LT0, "libcol_util: WARNING: dlvsym for %s@%s failed. Using dlsym() instead.", "fclose", "GLIBC_2.1");
1486 #endif /* ARCH(Intel) && WSIZE(32) */
1487 ptr = dlsym (libc, "fclose");
1488 if (ptr)
1489 __collector_util_funcs.fclose = (int(*)())ptr;
1490 else
1491 {
1492 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT fclose: %s\n", dlerror ());
1493 err = COL_ERROR_UTIL_INIT;
1494 }
1495 #if ARCH(Intel) && WSIZE(32)
1496 }
1497 #endif
1498
1499 ptr = dlsym (libc, "pclose");
1500 if (ptr)
1501 __collector_util_funcs.pclose = (int(*)())ptr;
1502 else
1503 {
1504 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT pclose: %s\n", dlerror ());
1505 err = COL_ERROR_UTIL_INIT;
1506 }
1507
1508 ptr = dlsym (libc, "fgets");
1509 if (ptr)
1510 __collector_util_funcs.fgets = (char*(*)())ptr;
1511 else
1512 {
1513 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT fgets: %s\n", dlerror ());
1514 err = COL_ERROR_UTIL_INIT;
1515 }
1516
1517 ptr = dlsym (libc, "sscanf");
1518 if (ptr)
1519 __collector_sscanfp = (int(*)(const char *restrict s, const char *restrict fmt, ...))ptr;
1520 else
1521 {
1522 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT sscanf: %s\n", dlerror ());
1523 err = COL_ERROR_UTIL_INIT;
1524 }
1525
1526 ptr = dlsym (libc, "snprintf");
1527 if (ptr)
1528 __collector_util_funcs.snprintf = (int(*)(char *, size_t, const char *, ...))ptr;
1529 else
1530 {
1531 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT snprintf: %s\n", dlerror ());
1532 err = COL_ERROR_UTIL_INIT;
1533 }
1534
1535 ptr = dlsym (libc, "vsnprintf");
1536 if (ptr)
1537 __collector_util_funcs.vsnprintf = (int(*)())ptr;
1538 else
1539 {
1540 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT vsnprintf: %s\n", dlerror ());
1541 err = COL_ERROR_UTIL_INIT;
1542 }
1543
1544 ptr = dlsym (libc, "atoi");
1545 if (ptr)
1546 __collector_util_funcs.atoi = (int(*)())ptr;
1547 else
1548 {
1549 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT atoi: %s\n", dlerror ());
1550 err = COL_ERROR_UTIL_INIT;
1551 }
1552
1553 ptr = dlsym (libc, "calloc");
1554 if (ptr)
1555 __collector_util_funcs.calloc = (void*(*)())ptr;
1556 else
1557 {
1558 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT calloc: %s\n", dlerror ());
1559 err = COL_ERROR_UTIL_INIT;
1560 }
1561
1562 ptr = dlsym (libc, "free");
1563 if (ptr)
1564 {
1565 __collector_util_funcs.free = (void(*)())ptr;
1566 }
1567 else
1568 {
1569 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT free: %s\n", dlerror ());
1570 err = COL_ERROR_UTIL_INIT;
1571 }
1572
1573 ptr = dlsym (libc, "strdup");
1574 if (ptr)
1575 __collector_util_funcs.libc_strdup = (char*(*)())ptr;
1576 else
1577 {
1578 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT strdup: %s\n", dlerror ());
1579 err = COL_ERROR_UTIL_INIT;
1580 }
1581
1582 __collector_util_funcs.strlen = __collector_strlen;
1583 __collector_util_funcs.strlcat = __collector_strlcat;
1584 __collector_util_funcs.strlcpy = __collector_strlcpy;
1585
1586 ptr = dlsym (libc, "strerror");
1587 if (ptr)
1588 __collector_util_funcs.strerror = (char*(*)())ptr;
1589 else
1590 {
1591 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT strerror: %s\n", dlerror ());
1592 err = COL_ERROR_UTIL_INIT;
1593 }
1594 ptr = dlsym (libc, "strerror_r");
1595 if (ptr)
1596 __collector_util_funcs.strerror_r = (int(*)())ptr;
1597 else
1598 {
1599 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT strerror_r: %s\n", dlerror ());
1600 err = COL_ERROR_UTIL_INIT;
1601 }
1602 ptr = dlsym (libc, "strspn");
1603 if (ptr)
1604 __collector_util_funcs.strspn = (size_t (*)())ptr;
1605 else
1606 {
1607 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT strspn: %s\n", dlerror ());
1608 err = COL_ERROR_UTIL_INIT;
1609 }
1610
1611 ptr = dlsym (libc, "strtoul");
1612 if (ptr)
1613 __collector_util_funcs.strtoul = (unsigned long int(*)())ptr;
1614 else
1615 {
1616 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT strtoul: %s\n", dlerror ());
1617 err = COL_ERROR_UTIL_INIT;
1618 }
1619
1620 ptr = dlsym (libc, "strtoull");
1621 if (ptr)
1622 __collector_util_funcs.strtoull = (unsigned long long int(*)())ptr;
1623 else
1624 {
1625 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT strtoull: %s\n", dlerror ());
1626 err = COL_ERROR_UTIL_INIT;
1627 }
1628
1629 ptr = dlsym (libc, "fcntl");
1630 if (ptr)
1631 __collector_util_funcs.fcntl = (int(*)(int, int, ...))ptr;
1632 else
1633 {
1634 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT fcntl: %s\n", dlerror ());
1635 err = COL_ERROR_UTIL_INIT;
1636 }
1637
1638 ptr = dlsym (libc, "ioctl");
1639 if (ptr)
1640 __collector_util_funcs.ioctl = (int(*)(int, int, ...))ptr;
1641 else
1642 {
1643 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT ioctl: %s\n", dlerror ());
1644 err = COL_ERROR_UTIL_INIT;
1645 }
1646
1647 ptr = dlsym (libc, "symlink");
1648 if (ptr)
1649 __collector_util_funcs.symlink = (int(*)(const char*, const char*))ptr;
1650 else
1651 {
1652 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT symlink: %s\n", dlerror ());
1653 err = COL_ERROR_UTIL_INIT;
1654 }
1655
1656 ptr = dlsym (libc, "syscall");
1657 if (ptr)
1658 __collector_util_funcs.syscall = (int(*)(int, ...))ptr;
1659 else
1660 {
1661 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT syscall: %s\n", dlerror ());
1662 err = COL_ERROR_UTIL_INIT;
1663 }
1664
1665 ptr = dlsym (libc, "sysconf");
1666 if (ptr)
1667 __collector_util_funcs.sysconf = (long(*)())ptr;
1668 else
1669 {
1670 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT sysconf: %s\n", dlerror ());
1671 err = COL_ERROR_UTIL_INIT;
1672 }
1673
1674 ptr = dlsym (libc, "sigfillset");
1675 if (ptr)
1676 __collector_util_funcs.sigfillset = (int(*)())ptr;
1677 else
1678 {
1679 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT sigfillset: %s\n", dlerror ());
1680 err = COL_ERROR_UTIL_INIT;
1681 }
1682
1683 ptr = dlsym (libc, "sigprocmask");
1684 if (ptr)
1685 __collector_util_funcs.sigprocmask = (int(*)())ptr;
1686 else
1687 {
1688 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT sigprocmask: %s\n", dlerror ());
1689 err = COL_ERROR_UTIL_INIT;
1690 }
1691
1692 return err;
1693 }