]>
Commit | Line | Data |
---|---|---|
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 ----------------- */ | |
50 | CollectorUtilFuncs __collector_util_funcs = {NULL}; | |
51 | int __collector_dlsym_guard = 0; | |
52 | int(*__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 | */ | |
66 | static unsigned gettid_key = COLLECTOR_TSD_INVALID_KEY; | |
67 | ||
68 | void | |
69 | __collector_ext_gettid_tsd_create_key () | |
70 | { | |
71 | gettid_key = __collector_tsd_create_key (sizeof (pid_t), NULL, NULL); | |
72 | } | |
73 | ||
74 | pid_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 | ||
103 | static inline int | |
104 | atomic_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 | ||
131 | int | |
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 | ||
148 | int | |
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 | ||
156 | int | |
157 | __collector_mutex_unlock (collector_mutex_t *lock_var) | |
158 | { | |
159 | (*lock_var) = 0; | |
160 | return 0; | |
161 | } | |
162 | ||
163 | #if ARCH(SPARC) | |
164 | void | |
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 | ||
180 | void | |
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 | ||
196 | uint32_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 | ||
205 | uint32_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 | ||
225 | void * | |
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 | ||
234 | uint64_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 | ||
250 | void * | |
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 | ||
259 | uint64_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 | ||
276 | void * | |
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 | ||
286 | static void * | |
287 | collector_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 | ||
295 | int | |
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 | ||
309 | int | |
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 | ||
325 | char * | |
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 | ||
337 | char * | |
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 | ||
348 | char * | |
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 | ||
358 | int | |
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 | ||
365 | size_t | |
366 | __collector_strlen (const char *s) | |
367 | { | |
368 | int len = -1; | |
369 | while (s[++len] != '\0') | |
370 | ; | |
371 | return len; | |
372 | } | |
373 | ||
374 | size_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 | ||
388 | size_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 | ||
401 | char * | |
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 | ||
414 | size_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 | ||
421 | void * | |
422 | __collector_malloc (size_t size) | |
423 | { | |
424 | void * ptr = __collector_allocCSize (__collector_heap, size, 0); | |
425 | return ptr; | |
426 | } | |
427 | ||
428 | void * | |
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 | ||
439 | char * | |
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 | |
454 | static char | |
455 | Printable[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 | }; | |
473 | static char hex[17] = "0123456789abcdef"; | |
474 | static char HEX[17] = "0123456789ABCDEF"; | |
475 | ||
476 | int | |
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 | ||
486 | int | |
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 | {//" | |
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 | {//' | |
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 | {//& | |
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 | {//< | |
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 | {//> | |
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 | {//" | |
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 | {//' | |
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 | {//& | |
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 | {//< | |
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 | {//> | |
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 */ | |
902 | typedef int (*sched_getcpu_ptr_t)(void); | |
903 | sched_getcpu_ptr_t sched_getcpu_ptr; | |
904 | static int need_warning = 0; | |
905 | ||
906 | /* the old, low-level code */ | |
907 | static int useLeafB = 0; | |
908 | ||
909 | /* access to the CPUID instruction on Intel/AMD */ | |
910 | typedef struct | |
911 | { | |
912 | uint32_t eax, ebx, ecx, edx; | |
913 | } CPUIDinfo; | |
914 | ||
915 | /** | |
916 | * This function returns the result of the "cpuid" instruction | |
917 | */ | |
918 | static __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 | ||
929 | static void | |
930 | getcpuid_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 | ||
949 | static uint32_t | |
950 | getcpuid () | |
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 | */ | |
997 | int sched_getcpu (); | |
998 | ||
999 | static int | |
1000 | getcpuid () | |
1001 | { | |
1002 | return sched_getcpu (); | |
1003 | } | |
1004 | #endif | |
1005 | ||
1006 | /* if ever retries time-out, we will stop allowing them */ | |
1007 | static int exhausted_retries = 0; | |
1008 | ||
1009 | int | |
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 | ||
1066 | int | |
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 | } |