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
, "malloc");
1324 __collector_util_funcs
.malloc
= (void *(*)(size_t))ptr
;
1327 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT malloc: %s\n", dlerror ());
1328 err
= COL_ERROR_UTIL_INIT
;
1331 ptr
= dlsym (libc
, "putenv");
1333 __collector_util_funcs
.putenv
= (int(*)())ptr
;
1336 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT putenv: %s\n", dlerror ());
1337 err
= COL_ERROR_UTIL_INIT
;
1340 ptr
= dlsym (libc
, "getenv");
1342 __collector_util_funcs
.getenv
= (char*(*)())ptr
;
1345 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT getenv: %s\n", dlerror ());
1346 err
= COL_ERROR_UTIL_INIT
;
1349 ptr
= dlsym (libc
, "time");
1351 __collector_util_funcs
.time
= (time_t (*)())ptr
;
1354 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT time: %s\n", dlerror ());
1355 err
= COL_ERROR_UTIL_INIT
;
1358 ptr
= dlsym (libc
, "mktime");
1360 __collector_util_funcs
.mktime
= (time_t (*)())ptr
;
1363 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT mktime: %s\n", dlerror ());
1364 err
= COL_ERROR_UTIL_INIT
;
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
;
1372 ptr
= dlsym (libc
, "gmtime_r");
1374 __collector_util_funcs
.gmtime_r
= (struct tm
* (*)())ptr
;
1377 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT gmtime_r: %s\n", dlerror ());
1378 err
= COL_ERROR_UTIL_INIT
;
1381 ptr
= dlsym (libc
, "strtol");
1383 __collector_util_funcs
.strtol
= (long (*)())ptr
;
1386 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT strtol: %s\n", dlerror ());
1387 err
= COL_ERROR_UTIL_INIT
;
1390 ptr
= dlsym (libc
, "strtoll");
1392 __collector_util_funcs
.strtoll
= (long long (*)())ptr
;
1395 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT strtoll: %s\n", dlerror ());
1396 err
= COL_ERROR_UTIL_INIT
;
1399 __collector_util_funcs
.strchr
= __collector_strchr
;
1400 __collector_util_funcs
.strrchr
= __collector_strrchr
;
1402 ptr
= dlsym (libc
, "setenv");
1404 __collector_util_funcs
.setenv
= (int(*)())ptr
;
1407 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT setenv: %s\n", dlerror ());
1408 err
= COL_ERROR_UTIL_INIT
;
1411 ptr
= dlsym (libc
, "unsetenv");
1413 __collector_util_funcs
.unsetenv
= (int(*)())ptr
;
1416 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT unsetenv: %s\n", dlerror ());
1417 err
= COL_ERROR_UTIL_INIT
;
1420 ptr
= dlsym (libc
, "atof");
1422 __collector_util_funcs
.atof
= (double (*)())ptr
;
1425 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT atof: %s\n", dlerror ());
1426 err
= COL_ERROR_UTIL_INIT
;
1429 ptr
= dlsym (libc
, "sysinfo");
1431 __collector_util_funcs
.sysinfo
= (long (*)())ptr
;
1434 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT sysinfo: %s\n", dlerror ());
1435 err
= COL_ERROR_UTIL_INIT
;
1438 ptr
= dlsym (libc
, "clearenv");
1440 __collector_util_funcs
.clearenv
= (int(*)())ptr
;
1443 /* suppress warning on S10 or earlier Solaris */
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 */
1450 #if ARCH(Intel) && WSIZE(32)
1451 ptr
= dlvsym (libc
, "fopen", "GLIBC_2.1");
1453 __collector_util_funcs
.fopen
= (FILE * (*)())ptr
;
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");
1460 __collector_util_funcs
.fopen
= (FILE * (*)())ptr
;
1463 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT fopen: %s\n", dlerror ());
1464 err
= COL_ERROR_UTIL_INIT
;
1466 #if ARCH(Intel) && WSIZE(32)
1470 ptr
= dlsym (libc
, "popen");
1472 __collector_util_funcs
.popen
= (FILE * (*)())ptr
;
1475 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT popen: %s\n", dlerror ());
1476 err
= COL_ERROR_UTIL_INIT
;
1479 #if ARCH(Intel) && WSIZE(32)
1480 ptr
= dlvsym (libc
, "fclose", "GLIBC_2.1");
1482 __collector_util_funcs
.fclose
= (int(*)())ptr
;
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");
1489 __collector_util_funcs
.fclose
= (int(*)())ptr
;
1492 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT fclose: %s\n", dlerror ());
1493 err
= COL_ERROR_UTIL_INIT
;
1495 #if ARCH(Intel) && WSIZE(32)
1499 ptr
= dlsym (libc
, "pclose");
1501 __collector_util_funcs
.pclose
= (int(*)())ptr
;
1504 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT pclose: %s\n", dlerror ());
1505 err
= COL_ERROR_UTIL_INIT
;
1508 ptr
= dlsym (libc
, "fgets");
1510 __collector_util_funcs
.fgets
= (char*(*)())ptr
;
1513 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT fgets: %s\n", dlerror ());
1514 err
= COL_ERROR_UTIL_INIT
;
1517 ptr
= dlsym (libc
, "sscanf");
1519 __collector_sscanfp
= (int(*)(const char *restrict s
, const char *restrict fmt
, ...))ptr
;
1522 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT sscanf: %s\n", dlerror ());
1523 err
= COL_ERROR_UTIL_INIT
;
1526 ptr
= dlsym (libc
, "snprintf");
1528 __collector_util_funcs
.snprintf
= (int(*)(char *, size_t, const char *, ...))ptr
;
1531 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT snprintf: %s\n", dlerror ());
1532 err
= COL_ERROR_UTIL_INIT
;
1535 ptr
= dlsym (libc
, "vsnprintf");
1537 __collector_util_funcs
.vsnprintf
= (int(*)())ptr
;
1540 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT vsnprintf: %s\n", dlerror ());
1541 err
= COL_ERROR_UTIL_INIT
;
1544 ptr
= dlsym (libc
, "atoi");
1546 __collector_util_funcs
.atoi
= (int(*)())ptr
;
1549 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT atoi: %s\n", dlerror ());
1550 err
= COL_ERROR_UTIL_INIT
;
1553 ptr
= dlsym (libc
, "calloc");
1555 __collector_util_funcs
.calloc
= (void*(*)())ptr
;
1558 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT calloc: %s\n", dlerror ());
1559 err
= COL_ERROR_UTIL_INIT
;
1562 ptr
= dlsym (libc
, "free");
1565 __collector_util_funcs
.free
= (void(*)())ptr
;
1569 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT free: %s\n", dlerror ());
1570 err
= COL_ERROR_UTIL_INIT
;
1573 ptr
= dlsym (libc
, "strdup");
1575 __collector_util_funcs
.libc_strdup
= (char*(*)())ptr
;
1578 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT strdup: %s\n", dlerror ());
1579 err
= COL_ERROR_UTIL_INIT
;
1582 __collector_util_funcs
.strlen
= __collector_strlen
;
1583 __collector_util_funcs
.strlcat
= __collector_strlcat
;
1584 __collector_util_funcs
.strlcpy
= __collector_strlcpy
;
1586 ptr
= dlsym (libc
, "strerror");
1588 __collector_util_funcs
.strerror
= (char*(*)())ptr
;
1591 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT strerror: %s\n", dlerror ());
1592 err
= COL_ERROR_UTIL_INIT
;
1594 ptr
= dlsym (libc
, "strerror_r");
1596 __collector_util_funcs
.strerror_r
= (int(*)())ptr
;
1599 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT strerror_r: %s\n", dlerror ());
1600 err
= COL_ERROR_UTIL_INIT
;
1602 ptr
= dlsym (libc
, "strspn");
1604 __collector_util_funcs
.strspn
= (size_t (*)())ptr
;
1607 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT strspn: %s\n", dlerror ());
1608 err
= COL_ERROR_UTIL_INIT
;
1611 ptr
= dlsym (libc
, "strtoul");
1613 __collector_util_funcs
.strtoul
= (unsigned long int(*)())ptr
;
1616 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT strtoul: %s\n", dlerror ());
1617 err
= COL_ERROR_UTIL_INIT
;
1620 ptr
= dlsym (libc
, "strtoull");
1622 __collector_util_funcs
.strtoull
= (unsigned long long int(*)())ptr
;
1625 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT strtoull: %s\n", dlerror ());
1626 err
= COL_ERROR_UTIL_INIT
;
1629 ptr
= dlsym (libc
, "fcntl");
1631 __collector_util_funcs
.fcntl
= (int(*)(int, int, ...))ptr
;
1634 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT fcntl: %s\n", dlerror ());
1635 err
= COL_ERROR_UTIL_INIT
;
1638 ptr
= dlsym (libc
, "ioctl");
1640 __collector_util_funcs
.ioctl
= (int(*)(int, int, ...))ptr
;
1643 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT ioctl: %s\n", dlerror ());
1644 err
= COL_ERROR_UTIL_INIT
;
1647 ptr
= dlsym (libc
, "symlink");
1649 __collector_util_funcs
.symlink
= (int(*)(const char*, const char*))ptr
;
1652 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT symlink: %s\n", dlerror ());
1653 err
= COL_ERROR_UTIL_INIT
;
1656 ptr
= dlsym (libc
, "syscall");
1658 __collector_util_funcs
.syscall
= (int(*)(int, ...))ptr
;
1661 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT syscall: %s\n", dlerror ());
1662 err
= COL_ERROR_UTIL_INIT
;
1665 ptr
= dlsym (libc
, "sysconf");
1667 __collector_util_funcs
.sysconf
= (long(*)())ptr
;
1670 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT sysconf: %s\n", dlerror ());
1671 err
= COL_ERROR_UTIL_INIT
;
1674 ptr
= dlsym (libc
, "sigfillset");
1676 __collector_util_funcs
.sigfillset
= (int(*)())ptr
;
1679 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT sigfillset: %s\n", dlerror ());
1680 err
= COL_ERROR_UTIL_INIT
;
1683 ptr
= dlsym (libc
, "sigprocmask");
1685 __collector_util_funcs
.sigprocmask
= (int(*)())ptr
;
1688 CALL_UTIL (fprintf
)(stderr
, "collector_util_init COL_ERROR_UTIL_INIT sigprocmask: %s\n", dlerror ());
1689 err
= COL_ERROR_UTIL_INIT
;