1 /* Copyright (C) 2021-2024 Free Software Foundation, Inc. 2 Contributed by Oracle. 3 4 This file is part of GNU Binutils. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3, or (at your option) 9 any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, 51 Franklin Street - Fifth Floor, Boston, 19 MA 02110-1301, USA. */ 20 21 #include "config.h" 22 #include <sys/types.h> 23 #include <sys/stat.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <signal.h> 27 #include <dlfcn.h> 28 #include <errno.h> 29 #include <unistd.h> 30 #include <fcntl.h> 31 #include <sys/syscall.h> 32 #include <sys/mman.h> 33 #include <sys/ioctl.h> 34 35 #include "gp-defs.h" 36 #include "collector.h" 37 #include "libcol_util.h" 38 #include "gp-experiment.h" 39 #include "Emsgnum.h" 40 #include "memmgr.h" // __collector_allocCSize, __collector_freeCSize 41 #include "tsd.h" 42 43 /* 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 { 134 volatile unsigned int i = 0; /* xxxx volatile may not be honored on amd64 -x04 */ 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) 1113 __collector_util_funcs.mmap64_ = (void*(*)(void *, size_t, int, int, int, off_t))ptr; 1114 else 1115 __collector_util_funcs.mmap64_ = __collector_util_funcs.mmap; 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) 1211 __collector_util_funcs.pwrite64_ = (ssize_t (*)())ptr; 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) 1218 __collector_util_funcs.pwrite64_ = (ssize_t (*)())ptr; 1219 else 1220 __collector_util_funcs.pwrite64_ = __collector_util_funcs.pwrite; 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 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 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 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; 1461 else 1462 ptr = dlsym (libc, "fopen"); 1463 if (__collector_util_funcs.fopen == NULL) 1464 { 1465 CALL_UTIL (fprintf)(stderr, "COL_ERROR_UTIL_INIT fopen: %s\n", dlerror ()); 1466 err = COL_ERROR_UTIL_INIT; 1467 } 1468 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; 1477 else 1478 ptr = dlsym (libc, "popen"); 1479 if (__collector_util_funcs.popen == NULL) 1480 { 1481 CALL_UTIL (fprintf)(stderr, "COL_ERROR_UTIL_INIT popen: %s\n", dlerror ()); 1482 err = COL_ERROR_UTIL_INIT; 1483 } 1484 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; 1493 else 1494 ptr = dlsym (libc, "fclose"); 1495 if (__collector_util_funcs.fclose == NULL) 1496 { 1497 CALL_UTIL (fprintf)(stderr, "COL_ERROR_UTIL_INIT fclose: %s\n", dlerror ()); 1498 err = COL_ERROR_UTIL_INIT; 1499 } 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 } 1696