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