1 /* Copyright (C) 2021 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
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)
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.
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. */
22 #include <sys/types.h>
31 #include <sys/syscall.h>
33 #include <sys/ioctl.h>
36 #include "collector.h"
37 #include "libcol_util.h"
38 #include "gp-experiment.h"
40 #include "memmgr.h" // __collector_allocCSize, __collector_freeCSize
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
50 * This file is intended for collector's own implementation of
51 * various routines to avoid interaction with libc and other
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, ...);
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.
72 static unsigned gettid_key = COLLECTOR_TSD_INVALID_KEY;
75 __collector_ext_gettid_tsd_create_key ()
77 gettid_key = __collector_tsd_create_key (sizeof (pid_t), NULL, NULL);
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)
92 #define syscall_instr "int $0x80"
93 #define syscall_clobber "memory"
95 #define syscall_instr "syscall"
96 #define syscall_clobber "rcx", "r11", "memory"
98 __asm__ __volatile__(syscall_instr
99 : "=a" (r) : "0" (__NR_gettid)
102 r = syscall (__NR_gettid);
110 atomic_swap (volatile int * p, int v)
114 __asm__ __volatile__("xchg %1, %2" : "=r" (r) : "m" (*p), "0" (v));
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?
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
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.
133 return __collector_cas_32 ((volatile uint32_t *)p, 0, v);
138 __collector_mutex_lock (collector_mutex_t *lock_var)
140 volatile unsigned int i; /* xxxx volatile may not be honored on amd64 -x04 */
142 if (!(*lock_var) && !atomic_swap (lock_var, 1))
147 while ((collector_mutex_t) (*lock_var) == 1)
150 while (atomic_swap (lock_var, 1));
155 __collector_mutex_trylock (collector_mutex_t *lock_var)
157 if (!(*lock_var) && !atomic_swap (lock_var, 1))
163 __collector_mutex_unlock (collector_mutex_t *lock_var)
171 __collector_inc_32 (volatile uint32_t *mem)
174 __asm__ __volatile__(" ld %2,%0 \n"
180 : "=&r" (t1), "=&r" (t2)
187 __collector_dec_32 (volatile uint32_t *mem)
190 __asm__ __volatile__(" ld %2,%0 \n"
196 : "=&r" (t1), "=&r" (t2)
203 __collector_cas_32 (volatile uint32_t *mem, uint32_t old, uint32_t new)
205 __asm__ __volatile__("cas [%1],%2,%0"
207 : "r" (mem), "r" (old));
212 __collector_subget_32 (volatile uint32_t *mem, uint32_t val)
215 __asm__ __volatile__(" ld %2,%0 \n"
222 : "=&r" (t1), "=&r" (t2)
223 : "m" (*mem), "r" (val)
232 __collector_cas_ptr (volatile void *mem, void *old, void *new)
234 __asm__ __volatile__("cas [%1],%2,%0"
236 : "r" (mem), "r" (old));
241 __collector_cas_64p (volatile uint64_t *mem, uint64_t *old, uint64_t *new)
244 __asm__ __volatile__(" ldx [%2],%2 \n"
246 " casx [%1],%2,%3 \n"
249 : "r" (mem), "r" (old), "r" (new)
257 __collector_cas_ptr (volatile void *mem, void *old, void *new)
259 __asm__ __volatile__("casx [%1],%2,%0"
261 : "r" (mem), "r" (old));
266 __collector_cas_64p (volatile uint64_t *mem, uint64_t *old, uint64_t *new)
269 __asm__ __volatile__(" ldx [%2],%2 \n"
271 " casx [%1],%2,%3 \n"
274 : "r" (mem), "r" (old), "r" (new)
283 __collector_memcpy (void *s1, const void *s2, size_t n)
285 char *cp1 = (char*) s1;
286 char *cp2 = (char*) s2;
293 collector_memset (void *s, int c, size_t n)
295 unsigned char *s1 = s;
297 *s1++ = (unsigned char) c;
302 __collector_strcmp (const char *s1, const char *s2)
316 __collector_strncmp (const char *s1, const char *s2, size_t n)
332 __collector_strstr (const char *s1, const char *s2)
334 if (s2 == NULL || *s2 == 0)
336 size_t len = __collector_strlen (s2);
337 for (char c = *s2; *s1; s1++)
338 if (c == *s1 && __collector_strncmp (s1, s2, len) == 0)
344 __collector_strchr (const char *str, int chr)
347 return (char *) (str + __collector_strlen (str));
349 if (chr == (int) *str)
355 __collector_strrchr (const char *str, int chr)
357 const char *p = str + __collector_strlen (str);
358 for (; p - str >= 0; p--)
365 __collector_strStartWith (const char *s1, const char *s2)
367 size_t slen = __collector_strlen (s2);
368 return __collector_strncmp (s1, s2, slen);
372 __collector_strlen (const char *s)
375 while (s[++len] != '\0')
381 __collector_strlcpy (char *dst, const char *src, size_t dstsize)
384 size_t n = dstsize - 1;
386 while ((c = *src++) != 0)
395 __collector_strncpy (char *dst, const char *src, size_t dstsize)
398 for (i = 0; i < dstsize; i++)
408 __collector_strcat (char *dst, const char *src)
410 size_t sz = __collector_strlen (dst);
411 for (size_t i = 0;; i++)
413 dst[sz + i] = src[i];
421 __collector_strlcat (char *dst, const char *src, size_t dstsize)
423 size_t sz = __collector_strlen (dst);
424 return sz + __collector_strlcpy (dst + sz, src, dstsize - sz);
428 __collector_malloc (size_t size)
430 void * ptr = __collector_allocCSize (__collector_heap, size, 0);
435 __collector_calloc (size_t nelem, size_t elsize)
437 size_t n = nelem * elsize;
438 void * ptr = __collector_malloc (n);
441 collector_memset (ptr, 0, n);
446 __collector_strdup (const char * str)
450 size_t size = __collector_strlen (str);
451 char * dst = (char *) __collector_malloc (size + 1);
454 __collector_strncpy (dst, str, size + 1);
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 /* ................ */
479 static char hex[17] = "0123456789abcdef";
480 static char HEX[17] = "0123456789ABCDEF";
483 __collector_xml_snprintf (char *s, size_t n, const char *format, ...)
486 va_start (args, format);
487 int res = __collector_xml_vsnprintf (s, n, format, args);
493 __collector_xml_vsnprintf (char *s, size_t n, const char *format, va_list args)
495 const char *src = format;
499 while ((c = *src) != 0)
520 *dst++ = hex[c / 16];
522 *dst++ = hex[c % 16];
558 unsigned char c1 = (unsigned char) va_arg (args, int);
559 if ((Printable[(int) c1] & C_STR) == 0)
631 *dst++ = hex[c1 / 16];
633 *dst++ = hex[c1 % 16];
638 else if (cnt++ < n - 1)
646 /* Strings are always left justified */
647 char *str = va_arg (args, char*);
651 while ((c1 = *str++) != 0)
653 if ((Printable[(int) c1] & C_STR) == 0)
725 *dst++ = hex[c1 / 16];
727 *dst++ = hex[c1 % 16];
732 else if (cnt++ < n - 1)
770 else if (c == 'x' || c == 'X')
775 long long argll = 0LL;
779 argll = va_arg (args, unsigned int);
781 argll = va_arg (args, int);
786 argll = va_arg (args, unsigned long);
788 argll = va_arg (args, long);
791 argll = va_arg (args, long long);
792 unsigned long long argllu = 0ULL;
793 if (uflag || argll >= 0)
800 int idx = sizeof (numbuf);
803 numbuf[--idx] = (c == 'X' ? HEX[argllu % base] : hex[argllu % base]);
804 argllu = argllu / base;
821 while (idx < sizeof (numbuf) && width > 0)
824 *dst++ = numbuf[idx];
831 while (width > sizeof (numbuf) - idx)
834 *dst++ = zflag ? '0' : ' ';
837 while (idx != sizeof (numbuf))
840 *dst++ = numbuf[idx];
849 case '1': case '2': case '3': case '4': case '5':
850 case '6': case '7': case '8': case '9':
852 while (c >= '0' && c <= '9')
854 width = width * 10 + (c - '0');
865 else if ((Printable[(int) c] & C_FMT) == 0)
870 *dst++ = hex[c / 16];
872 *dst++ = hex[c % 16];
894 * Functions to be called directly from libc.so
896 #if ARCH(Intel) /* intel-Linux */
898 * The CPUIDinfo/__collector_cpuid() code is old,
899 * incorrect, and complicated. It returns the apicid
900 * rather than the processor number.
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.
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;
912 /* the old, low-level code */
913 static int useLeafB = 0;
915 /* access to the CPUID instruction on Intel/AMD */
918 uint32_t eax, ebx, ecx, edx;
922 * This function returns the result of the "cpuid" instruction
924 static __attribute__ ((always_inline)) inline void
925 __collector_cpuid (CPUIDinfo* info)
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));
939 info.eax = 0; /* max input value for CPUID */
940 __collector_cpuid (&info);
946 __collector_cpuid (&info);
947 useLeafB = info.ebx != 0;
950 /* indicate that we need a warning */
951 /* (need to wait until log mechanism has been initialized) */
958 /* if we found sched_getcpu(), use it */
959 if (sched_getcpu_ptr)
960 return (*sched_getcpu_ptr)();
962 /* otherwise, check if we need warning */
966 (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">x2APIC</event>\n",
967 SP_JCMD_CWARN, COL_WARN_LINUX_X86_APICID);
969 (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">APIC</event>\n",
970 SP_JCMD_CWARN, COL_WARN_LINUX_X86_APICID);
974 /* and use the old, low-level code */
980 __collector_cpuid (&info);
981 return info.edx; /* x2APIC ID */
987 __collector_cpuid (&info);
988 return info.ebx >> 24; /* APIC ID */
992 #else /* sparc-Linux */
996 * How should sched_getcpu() be prototyped? Like this?
999 * #define _GNU_SOURCE
1000 * #include <utmpx.h>
1001 * Or just prototype this function explicitly without bothering with include files.
1003 int sched_getcpu ();
1008 return sched_getcpu ();
1012 /* if ever retries time-out, we will stop allowing them */
1013 static int exhausted_retries = 0;
1016 __collector_open (const char *path, int oflag, ...)
1021 hrtime_t t_timeout = __collector_gethrtime () + 5 * ((hrtime_t) NANOSEC);
1023 long long delay = 100; /* start at some small, arbitrary value */
1025 /* get optional mode argument if it's expected/required */
1026 if (oflag | O_CREAT)
1029 va_start (ap, oflag);
1030 mode = (mode_t) va_arg (ap, mode_t);
1034 /* retry upon failure */
1035 while ((fd = CALL_UTIL (open_bare)(path, oflag, mode)) < 0)
1037 if (exhausted_retries)
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.
1045 if ((errno != EMFILE) && (errno != ENOENT))
1047 if (__collector_gethrtime () > t_timeout)
1049 exhausted_retries = 1;
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. */
1058 double xdummy = 0.5;
1059 for (ispin = 0; ispin < delay; ispin++)
1060 xdummy = 0.5 * (xdummy + 1.);
1062 /* should never happen, but we check so the loop won't be optimized away */
1065 if (delay > 100000000)
1066 delay = 100000000; /* cap at some large, arbitrary value */
1073 __collector_util_init ()
1077 /* Linux requires RTLD_LAZY, Solaris can do just RTLD_NOLOAD */
1078 void *libc = dlopen (SYS_LIBC_NAME, RTLD_LAZY | RTLD_NOLOAD);
1080 libc = dlopen (SYS_LIBC_NAME, RTLD_NOW | RTLD_LOCAL);
1083 /* libcollector will subsequently abort, as all the pointers in the vector are NULL */
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;
1092 void *ptr = dlsym (libc, "fprintf");
1094 __collector_util_funcs.fprintf = (int(*)(FILE *, const char *, ...))ptr;
1097 // We can't write any error messages without a libc reference
1099 fprintf (stderr, "__collector_util_init: COLERROR_UTIL_INIT fprintf: %s\n", dlerror ());
1100 return COL_ERROR_UTIL_INIT;
1106 ptr = dlsym (libc, "mmap");
1108 __collector_util_funcs.mmap = (void*(*)(void *, size_t, int, int, int, off_t))ptr;
1111 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT mmap: %s\n", dlerror ());
1112 err = COL_ERROR_UTIL_INIT;
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");
1119 __collector_util_funcs.mmap64_ = (void*(*)(void *, size_t, int, int, int, off_t))ptr;
1121 __collector_util_funcs.mmap64_ = __collector_util_funcs.mmap;
1123 ptr = dlsym (libc, "munmap");
1125 __collector_util_funcs.munmap = (int(*)())ptr;
1128 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT munmap: %s\n", dlerror ());
1129 err = COL_ERROR_UTIL_INIT;
1132 ptr = dlsym (libc, "close");
1134 __collector_util_funcs.close = (int(*)())ptr;
1137 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT close: %s\n", dlerror ());
1138 err = COL_ERROR_UTIL_INIT;
1141 ptr = dlsym (libc, "open");
1143 __collector_util_funcs.open = (int(*)(const char *path, int oflag, ...))ptr;
1146 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT open: %s\n", dlerror ());
1147 err = COL_ERROR_UTIL_INIT;
1150 #if ARCH(Intel) && WSIZE(32)
1151 ptr = dlvsym (libc, "open64", "GLIBC_2.2"); // it is in /lib/libpthread.so.0
1153 __collector_util_funcs.open_bare = (int(*)(const char *path, int oflag, ...))ptr;
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");
1160 __collector_util_funcs.open_bare = (int(*)(const char *path, int oflag, ...))ptr;
1162 __collector_util_funcs.open_bare = __collector_util_funcs.open;
1163 #if ARCH(Intel) && WSIZE(32)
1165 #endif /* ARCH(Intel) && WSIZE(32) */
1167 ptr = dlsym (libc, "close");
1169 __collector_util_funcs.close = (int(*)())ptr;
1172 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT close: %s\n", dlerror ());
1173 err = COL_ERROR_UTIL_INIT;
1176 ptr = dlsym (libc, "read");
1178 __collector_util_funcs.read = (ssize_t (*)())ptr;
1181 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT read: %s\n", dlerror ());
1182 err = COL_ERROR_UTIL_INIT;
1185 ptr = dlsym (libc, "write");
1187 __collector_util_funcs.write = (ssize_t (*)())ptr;
1190 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT write: %s\n", dlerror ());
1191 err = COL_ERROR_UTIL_INIT;
1194 #if ARCH(Intel) && WSIZE(32)
1195 ptr = dlvsym (libc, "pwrite", "GLIBC_2.2"); // it is in /lib/libpthread.so.0
1197 __collector_util_funcs.pwrite = (ssize_t (*)())ptr;
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");
1204 __collector_util_funcs.pwrite = (ssize_t (*)())ptr;
1207 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT pwrite: %s\n", dlerror ());
1208 err = COL_ERROR_UTIL_INIT;
1210 #if ARCH(Intel) && WSIZE(32)
1214 #if ARCH(Intel) && WSIZE(32)
1215 ptr = dlvsym (libc, "pwrite64", "GLIBC_2.2"); // it is in /lib/libpthread.so.0
1217 __collector_util_funcs.pwrite64_ = (ssize_t (*)())ptr;
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");
1224 __collector_util_funcs.pwrite64_ = (ssize_t (*)())ptr;
1226 __collector_util_funcs.pwrite64_ = __collector_util_funcs.pwrite;
1227 #if ARCH(Intel) && WSIZE(32)
1229 #endif /* ARCH(Intel) && WSIZE(32) */
1231 ptr = dlsym (libc, "lseek");
1233 __collector_util_funcs.lseek = (off_t (*)())ptr;
1236 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT lseek: %s\n", dlerror ());
1237 err = COL_ERROR_UTIL_INIT;
1240 ptr = dlsym (libc, "access");
1242 __collector_util_funcs.access = (int(*)())ptr;
1245 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT access: %s\n", dlerror ());
1246 err = COL_ERROR_UTIL_INIT;
1249 ptr = dlsym (libc, "mkdir");
1251 __collector_util_funcs.mkdir = (int(*)())ptr;
1254 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT mkdir: %s\n", dlerror ());
1255 err = COL_ERROR_UTIL_INIT;
1258 ptr = dlsym (libc, "opendir");
1260 __collector_util_funcs.opendir = (DIR * (*)())ptr;
1263 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT opendir: %s\n", dlerror ());
1264 err = COL_ERROR_UTIL_INIT;
1267 ptr = dlsym (libc, "closedir");
1269 __collector_util_funcs.closedir = (int(*)())ptr;
1272 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT closedir: %s\n", dlerror ());
1273 err = COL_ERROR_UTIL_INIT;
1276 ptr = dlsym (libc, "execv");
1278 __collector_util_funcs.execv = (int(*)())ptr;
1281 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT execv: %s\n", dlerror ());
1282 err = COL_ERROR_UTIL_INIT;
1285 ptr = dlsym (libc, "exit");
1287 __collector_util_funcs.exit = (void(*)())ptr;
1290 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT exit: %s\n", dlerror ());
1291 err = COL_ERROR_UTIL_INIT;
1294 ptr = dlsym (libc, "vfork");
1296 __collector_util_funcs.vfork = (pid_t (*)())ptr;
1299 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT vfork: %s\n", dlerror ());
1300 err = COL_ERROR_UTIL_INIT;
1303 ptr = dlsym (libc, "waitpid");
1305 __collector_util_funcs.waitpid = (pid_t (*)())ptr;
1308 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT waitpid: %s\n", dlerror ());
1309 err = COL_ERROR_UTIL_INIT;
1312 int (*__collector_getcpuid)() = (int(*)()) & getcpuid;
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)
1319 __collector_util_funcs.getcpuid = __collector_getcpuid;
1320 __collector_util_funcs.memset = collector_memset;
1322 ptr = dlsym (libc, "getcontext");
1324 __collector_util_funcs.getcontext = (int(*)())ptr;
1327 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT getcontext: %s\n", dlerror ());
1328 err = COL_ERROR_UTIL_INIT;
1331 ptr = dlsym (libc, "malloc");
1333 __collector_util_funcs.malloc = (void *(*)(size_t))ptr;
1336 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT malloc: %s\n", dlerror ());
1337 err = COL_ERROR_UTIL_INIT;
1340 ptr = dlsym (libc, "putenv");
1342 __collector_util_funcs.putenv = (int(*)())ptr;
1345 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT putenv: %s\n", dlerror ());
1346 err = COL_ERROR_UTIL_INIT;
1349 ptr = dlsym (libc, "getenv");
1351 __collector_util_funcs.getenv = (char*(*)())ptr;
1354 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT getenv: %s\n", dlerror ());
1355 err = COL_ERROR_UTIL_INIT;
1358 ptr = dlsym (libc, "time");
1360 __collector_util_funcs.time = (time_t (*)())ptr;
1363 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT time: %s\n", dlerror ());
1364 err = COL_ERROR_UTIL_INIT;
1367 ptr = dlsym (libc, "mktime");
1369 __collector_util_funcs.mktime = (time_t (*)())ptr;
1372 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT mktime: %s\n", dlerror ());
1373 err = COL_ERROR_UTIL_INIT;
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;
1381 ptr = dlsym (libc, "gmtime_r");
1383 __collector_util_funcs.gmtime_r = (struct tm * (*)())ptr;
1386 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT gmtime_r: %s\n", dlerror ());
1387 err = COL_ERROR_UTIL_INIT;
1390 ptr = dlsym (libc, "strtol");
1392 __collector_util_funcs.strtol = (long (*)())ptr;
1395 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT strtol: %s\n", dlerror ());
1396 err = COL_ERROR_UTIL_INIT;
1399 ptr = dlsym (libc, "strtoll");
1401 __collector_util_funcs.strtoll = (long long (*)())ptr;
1404 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT strtoll: %s\n", dlerror ());
1405 err = COL_ERROR_UTIL_INIT;
1408 __collector_util_funcs.strchr = __collector_strchr;
1409 __collector_util_funcs.strrchr = __collector_strrchr;
1411 ptr = dlsym (libc, "setenv");
1413 __collector_util_funcs.setenv = (int(*)())ptr;
1416 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT setenv: %s\n", dlerror ());
1417 err = COL_ERROR_UTIL_INIT;
1420 ptr = dlsym (libc, "unsetenv");
1422 __collector_util_funcs.unsetenv = (int(*)())ptr;
1425 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT unsetenv: %s\n", dlerror ());
1426 err = COL_ERROR_UTIL_INIT;
1429 ptr = dlsym (libc, "atof");
1431 __collector_util_funcs.atof = (double (*)())ptr;
1434 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT atof: %s\n", dlerror ());
1435 err = COL_ERROR_UTIL_INIT;
1438 ptr = dlsym (libc, "sysinfo");
1440 __collector_util_funcs.sysinfo = (long (*)())ptr;
1443 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT sysinfo: %s\n", dlerror ());
1444 err = COL_ERROR_UTIL_INIT;
1447 ptr = dlsym (libc, "clearenv");
1449 __collector_util_funcs.clearenv = (int(*)())ptr;
1452 /* suppress warning on S10 or earlier Solaris */
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 */
1459 #if ARCH(Intel) && WSIZE(32)
1460 ptr = dlvsym (libc, "fopen", "GLIBC_2.1");
1462 __collector_util_funcs.fopen = (FILE * (*)())ptr;
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");
1469 __collector_util_funcs.fopen = (FILE * (*)())ptr;
1472 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT fopen: %s\n", dlerror ());
1473 err = COL_ERROR_UTIL_INIT;
1475 #if ARCH(Intel) && WSIZE(32)
1479 ptr = dlsym (libc, "popen");
1481 __collector_util_funcs.popen = (FILE * (*)())ptr;
1484 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT popen: %s\n", dlerror ());
1485 err = COL_ERROR_UTIL_INIT;
1488 #if ARCH(Intel) && WSIZE(32)
1489 ptr = dlvsym (libc, "fclose", "GLIBC_2.1");
1491 __collector_util_funcs.fclose = (int(*)())ptr;
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");
1498 __collector_util_funcs.fclose = (int(*)())ptr;
1501 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT fclose: %s\n", dlerror ());
1502 err = COL_ERROR_UTIL_INIT;
1504 #if ARCH(Intel) && WSIZE(32)
1508 ptr = dlsym (libc, "pclose");
1510 __collector_util_funcs.pclose = (int(*)())ptr;
1513 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT pclose: %s\n", dlerror ());
1514 err = COL_ERROR_UTIL_INIT;
1517 ptr = dlsym (libc, "fgets");
1519 __collector_util_funcs.fgets = (char*(*)())ptr;
1522 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT fgets: %s\n", dlerror ());
1523 err = COL_ERROR_UTIL_INIT;
1526 ptr = dlsym (libc, "sscanf");
1528 __collector_sscanfp = (int(*)(const char *restrict s, const char *restrict fmt, ...))ptr;
1531 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT sscanf: %s\n", dlerror ());
1532 err = COL_ERROR_UTIL_INIT;
1535 ptr = dlsym (libc, "snprintf");
1537 __collector_util_funcs.snprintf = (int(*)(char *, size_t, const char *, ...))ptr;
1540 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT snprintf: %s\n", dlerror ());
1541 err = COL_ERROR_UTIL_INIT;
1544 ptr = dlsym (libc, "vsnprintf");
1546 __collector_util_funcs.vsnprintf = (int(*)())ptr;
1549 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT vsnprintf: %s\n", dlerror ());
1550 err = COL_ERROR_UTIL_INIT;
1553 ptr = dlsym (libc, "atoi");
1555 __collector_util_funcs.atoi = (int(*)())ptr;
1558 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT atoi: %s\n", dlerror ());
1559 err = COL_ERROR_UTIL_INIT;
1562 ptr = dlsym (libc, "calloc");
1564 __collector_util_funcs.calloc = (void*(*)())ptr;
1567 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT calloc: %s\n", dlerror ());
1568 err = COL_ERROR_UTIL_INIT;
1571 ptr = dlsym (libc, "free");
1574 __collector_util_funcs.free = (void(*)())ptr;
1578 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT free: %s\n", dlerror ());
1579 err = COL_ERROR_UTIL_INIT;
1582 ptr = dlsym (libc, "strdup");
1584 __collector_util_funcs.libc_strdup = (char*(*)())ptr;
1587 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT strdup: %s\n", dlerror ());
1588 err = COL_ERROR_UTIL_INIT;
1591 __collector_util_funcs.strlen = __collector_strlen;
1592 __collector_util_funcs.strlcat = __collector_strlcat;
1593 __collector_util_funcs.strlcpy = __collector_strlcpy;
1595 ptr = dlsym (libc, "strerror");
1597 __collector_util_funcs.strerror = (char*(*)())ptr;
1600 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT strerror: %s\n", dlerror ());
1601 err = COL_ERROR_UTIL_INIT;
1603 ptr = dlsym (libc, "strerror_r");
1605 __collector_util_funcs.strerror_r = (int(*)())ptr;
1608 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT strerror_r: %s\n", dlerror ());
1609 err = COL_ERROR_UTIL_INIT;
1611 ptr = dlsym (libc, "strspn");
1613 __collector_util_funcs.strspn = (size_t (*)())ptr;
1616 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT strspn: %s\n", dlerror ());
1617 err = COL_ERROR_UTIL_INIT;
1620 ptr = dlsym (libc, "strtoul");
1622 __collector_util_funcs.strtoul = (unsigned long int(*)())ptr;
1625 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT strtoul: %s\n", dlerror ());
1626 err = COL_ERROR_UTIL_INIT;
1629 ptr = dlsym (libc, "strtoull");
1631 __collector_util_funcs.strtoull = (unsigned long long int(*)())ptr;
1634 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT strtoull: %s\n", dlerror ());
1635 err = COL_ERROR_UTIL_INIT;
1638 ptr = dlsym (libc, "fcntl");
1640 __collector_util_funcs.fcntl = (int(*)(int, int, ...))ptr;
1643 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT fcntl: %s\n", dlerror ());
1644 err = COL_ERROR_UTIL_INIT;
1647 ptr = dlsym (libc, "ioctl");
1649 __collector_util_funcs.ioctl = (int(*)(int, int, ...))ptr;
1652 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT ioctl: %s\n", dlerror ());
1653 err = COL_ERROR_UTIL_INIT;
1656 ptr = dlsym (libc, "symlink");
1658 __collector_util_funcs.symlink = (int(*)(const char*, const char*))ptr;
1661 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT symlink: %s\n", dlerror ());
1662 err = COL_ERROR_UTIL_INIT;
1665 ptr = dlsym (libc, "syscall");
1667 __collector_util_funcs.syscall = (int(*)(int, ...))ptr;
1670 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT syscall: %s\n", dlerror ());
1671 err = COL_ERROR_UTIL_INIT;
1674 ptr = dlsym (libc, "sysconf");
1676 __collector_util_funcs.sysconf = (long(*)())ptr;
1679 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT sysconf: %s\n", dlerror ());
1680 err = COL_ERROR_UTIL_INIT;
1683 ptr = dlsym (libc, "sigfillset");
1685 __collector_util_funcs.sigfillset = (int(*)())ptr;
1688 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT sigfillset: %s\n", dlerror ());
1689 err = COL_ERROR_UTIL_INIT;
1692 ptr = dlsym (libc, "sigprocmask");
1694 __collector_util_funcs.sigprocmask = (int(*)())ptr;
1697 CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT sigprocmask: %s\n", dlerror ());
1698 err = COL_ERROR_UTIL_INIT;