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