1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 /* 27 * Routines to provide profiling of shared libraries required by the called 28 * executable. 29 */ 30 #include <stdio.h> 31 #include <fcntl.h> 32 #include <sys/mman.h> 33 #include <unistd.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <sys/types.h> 37 #include <sys/stat.h> 38 #include <synch.h> 39 #include <signal.h> 40 #include <synch.h> 41 #include <link.h> 42 #include <libintl.h> 43 #include <sys/param.h> 44 #include <procfs.h> 45 #include "msg.h" 46 #include "sgs.h" 47 #include "profile.h" 48 #include "_rtld.h" 49 50 51 static char Profile[MAXPATHLEN]; /* Profile buffer pathname */ 52 static char *pname = 0; /* name of object to profile */ 53 static L_hdr *Hptr; /* profile buffer header pointer */ 54 static L_cgarc *Cptr; /* profile buffer call graph pointer */ 55 static caddr_t Hpc, Lpc; /* Range of addresses being monitored */ 56 static size_t Fsize; /* Size of mapped in profile buffer */ 57 uintptr_t profcookie = 0; 58 59 /* 60 * When handling mutex's locally we need to mask signals. The signal 61 * mask is for everything except SIGWAITING. 62 */ 63 static const sigset_t iset = { ~0U, ~0U, ~0U, ~0U }; 64 65 static lwp_mutex_t sharedmutex = SHAREDMUTEX; 66 67 static int 68 prof_mutex_init(lwp_mutex_t *mp) 69 { 70 (void) memcpy(mp, &sharedmutex, sizeof (lwp_mutex_t)); 71 return (0); 72 } 73 74 static int 75 prof_mutex_lock(lwp_mutex_t *mp, sigset_t *oset) 76 { 77 if (oset) 78 (void) sigprocmask(SIG_BLOCK, &iset, oset); 79 (void) _lwp_mutex_lock(mp); 80 return (0); 81 } 82 83 static int 84 prof_mutex_unlock(mutex_t *mp, sigset_t *oset) 85 { 86 (void) _lwp_mutex_unlock(mp); 87 if (oset) 88 (void) sigprocmask(SIG_SETMASK, oset, NULL); 89 return (0); 90 } 91 92 const char * 93 _ldprof_msg(Msg mid) 94 { 95 return (dgettext(MSG_ORIG(MSG_SUNW_OST_SGS), MSG_ORIG(mid))); 96 } 97 98 /* 99 * Determine whether a set (of arbitrary size) is in use - used to analyze proc 100 * status information. 101 */ 102 static int 103 setisinuse(uint32_t *sp, uint_t n) 104 { 105 while (n--) 106 if (*sp++) 107 return (1); 108 return (0); 109 } 110 111 #define prisinuse(sp) \ 112 setisinuse((uint32_t *)(sp), \ 113 (uint_t)(sizeof (*(sp)) / sizeof (uint32_t))) 114 115 uint_t 116 la_version(uint_t version) 117 { 118 int fd; 119 ssize_t num; 120 pstatus_t status; 121 122 if (version < LAV_CURRENT) { 123 (void) fprintf(stderr, MSG_INTL(MSG_GEN_AUDITVERSION), 124 LAV_CURRENT, version); 125 return (LAV_CURRENT); 126 } 127 128 /* 129 * To reduce the potential for deadlock conditions that can arise from 130 * being monitored (say by truss(1)) while setting a lock in the profile 131 * buffer, determine if someone is monitoring us. If so silently 132 * disable profiling. 133 */ 134 if ((fd = open(MSG_ORIG(MSG_FMT_PROCSELF), O_RDONLY)) < 0) 135 return (LAV_CURRENT); 136 137 num = read(fd, &status, sizeof (status)); 138 (void) close(fd); 139 140 if ((num != sizeof (status)) || 141 prisinuse(&status.pr_sigtrace) || prisinuse(&status.pr_flttrace) || 142 prisinuse(&status.pr_sysentry) || prisinuse(&status.pr_sysexit)) { 143 return (LAV_CURRENT); 144 } 145 146 /* 147 * We're presently not being monitored (although there's no control of 148 * someone attaching to us later), so retrieve the profile target name. 149 */ 150 if (dlinfo((void *)NULL, RTLD_DI_PROFILENAME, &pname) == -1) 151 (void) fprintf(stderr, MSG_INTL(MSG_GEN_PROFNOTSET)); 152 153 return (LAV_CURRENT); 154 } 155 156 157 int 158 profile_open(const char *fname, Link_map *lmp) 159 { 160 size_t hsize; /* struct hdr size */ 161 size_t psize; /* profile histogram size */ 162 size_t csize; /* call graph array size */ 163 size_t msize; /* size of memory being profiled */ 164 int i, fd, fixed = 0; 165 caddr_t lpc; 166 caddr_t hpc; 167 caddr_t addr; 168 struct stat status; 169 int new_buffer = 0; 170 sigset_t mask; 171 int err; 172 Ehdr * ehdr; /* ELF header for file */ 173 Phdr * phdr; /* program headers for file */ 174 Dyn * dynp = 0; /* Dynamic section */ 175 Word nsym = 0; /* no. of symtab ntries */ 176 177 if (*Profile == '\0') { 178 const char *dir, *suf; 179 char *tmp; 180 181 /* 182 * From the basename of the specified filename generate the 183 * appropriate profile buffer name. The profile file is created 184 * if it does not already exist. 185 */ 186 if (((tmp = strrchr(fname, '/')) != 0) && (*(++tmp))) 187 fname = tmp; 188 189 #if defined(_ELF64) 190 suf = MSG_ORIG(MSG_SUF_PROFILE_64); 191 #else 192 suf = MSG_ORIG(MSG_SUF_PROFILE); 193 #endif 194 if (dlinfo((void *)NULL, RTLD_DI_PROFILEOUT, &dir) == -1) 195 dir = MSG_ORIG(MSG_PTH_VARTMP); 196 197 (void) snprintf(Profile, MAXPATHLEN, MSG_ORIG(MSG_FMT_PROFILE), 198 dir, fname, suf); 199 } 200 201 if ((fd = open(Profile, (O_RDWR | O_CREAT), 0666)) == -1) { 202 err = errno; 203 (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), Profile, 204 strerror(err)); 205 return (0); 206 } 207 208 /* 209 * Now we determine the valid pc range for this object. The lpc is easy 210 * (lmp->l_addr), to determine the hpc we must examine the Phdrs. 211 */ 212 lpc = hpc = (caddr_t)lmp->l_addr; 213 /* LINTED */ 214 ehdr = (Ehdr *)lpc; 215 if (ehdr->e_phnum == 0) { 216 (void) close(fd); 217 return (0); 218 } 219 if (ehdr->e_type == ET_EXEC) 220 fixed = 1; 221 /* LINTED */ 222 phdr = (Phdr *)(ehdr->e_phoff + lpc); 223 for (i = 0; i < ehdr->e_phnum; i++, phdr++) { 224 caddr_t _hpc; 225 226 if (phdr->p_type == PT_DYNAMIC) { 227 dynp = (Dyn *)phdr->p_vaddr; 228 if (fixed == 0) { 229 dynp = (Dyn *)((unsigned long)dynp + 230 (unsigned long)lpc); 231 } 232 continue; 233 } 234 235 if (phdr->p_type != PT_LOAD) 236 continue; 237 238 _hpc = (caddr_t)(phdr->p_vaddr + phdr->p_memsz); 239 if (fixed == 0) { 240 _hpc = (caddr_t)((unsigned long)_hpc + 241 (unsigned long)lpc); 242 } 243 if (_hpc > hpc) 244 hpc = _hpc; 245 } 246 if (lpc == hpc) { 247 (void) close(fd); 248 return (0); 249 } 250 251 /* 252 * In order to determine the number of symbols in the object scan the 253 * dynamic section until we find the DT_HASH entry (hash[1] == symcnt). 254 */ 255 if (dynp) { 256 for (; dynp->d_tag != DT_NULL; dynp++) { 257 unsigned int *hashp; 258 259 if (dynp->d_tag != DT_HASH) 260 continue; 261 262 hashp = (unsigned int *)dynp->d_un.d_ptr; 263 if (fixed == 0) { 264 hashp = (unsigned int *)((unsigned long)hashp + 265 (unsigned long)lpc); 266 } 267 nsym = hashp[1]; 268 break; 269 } 270 } 271 272 /* 273 * Determine the (minimum) size of the buffer to allocate 274 */ 275 Lpc = lpc = (caddr_t)PRF_ROUNDWN((long)lpc, sizeof (long)); 276 Hpc = hpc = (caddr_t)PRF_ROUNDUP((long)hpc, sizeof (long)); 277 278 hsize = sizeof (L_hdr); 279 msize = (size_t)(hpc - lpc); 280 psize = (size_t)PRF_ROUNDUP((msize / PRF_BARSIZE), sizeof (long)); 281 csize = (nsym + 1) * PRF_CGINIT * sizeof (L_cgarc); 282 Fsize = (hsize + psize + csize); 283 284 /* 285 * If the file size is zero (ie. we just created it), truncate it 286 * to the minimum size. 287 */ 288 (void) fstat(fd, &status); 289 if (status.st_size == 0) { 290 if (ftruncate(fd, Fsize) == -1) { 291 err = errno; 292 (void) fprintf(stderr, MSG_INTL(MSG_SYS_FTRUNC), 293 Profile, strerror(err)); 294 (void) close(fd); 295 return (0); 296 } 297 new_buffer++; 298 } else 299 Fsize = status.st_size; 300 301 /* 302 * Map the file in. 303 */ 304 if ((addr = (caddr_t)mmap(0, Fsize, (PROT_READ | PROT_WRITE), 305 MAP_SHARED, fd, 0)) == (char *)-1) { 306 err = errno; 307 (void) fprintf(stderr, MSG_INTL(MSG_SYS_MMAP), Profile, 308 strerror(err)); 309 (void) close(fd); 310 return (0); 311 } 312 (void) close(fd); 313 314 /* 315 * Initialize the remaining elements of the header. All pc addresses 316 * that are recorded are relative to zero thus allowing the recorded 317 * entries to be correlated with the symbols in the original file, 318 * and to compensate for any differences in where the file is mapped. 319 * If the high pc address has been initialized from a previous run, 320 * and the new entry is different from the original then a new library 321 * must have been installed. In this case bale out. 322 */ 323 /* LINTED */ 324 Hptr = (L_hdr *)addr; 325 326 if (new_buffer) 327 (void) prof_mutex_init((lwp_mutex_t *)&Hptr->hd_mutex); 328 329 (void) prof_mutex_lock((mutex_t *)&Hptr->hd_mutex, &mask); 330 if (Hptr->hd_hpc) { 331 if (Hptr->hd_hpc != (caddr_t)(hpc - lpc)) { 332 (void) fprintf(stderr, MSG_INTL(MSG_GEN_PROFSZCHG), 333 Profile); 334 (void) prof_mutex_unlock((mutex_t *)&Hptr-> 335 hd_mutex, &mask); 336 (void) munmap((caddr_t)Hptr, Fsize); 337 return (0); 338 } 339 } else { 340 /* 341 * Initialize the header information as we must have just 342 * created the output file. 343 */ 344 Hptr->hd_magic = (unsigned int)PRF_MAGIC; 345 #if defined(_ELF64) 346 Hptr->hd_version = (unsigned int)PRF_VERSION_64; 347 #else 348 Hptr->hd_version = (unsigned int)PRF_VERSION; 349 #endif 350 Hptr->hd_hpc = (caddr_t)(hpc - lpc); 351 /* LINTED */ 352 Hptr->hd_psize = (unsigned int)psize; 353 /* LINTED */ 354 Hptr->hd_fsize = (unsigned int)Fsize; 355 Hptr->hd_ncndx = nsym; 356 Hptr->hd_lcndx = (nsym + 1) * PRF_CGINIT; 357 } 358 359 (void) prof_mutex_unlock((mutex_t *)&Hptr->hd_mutex, &mask); 360 /* LINTED */ 361 Cptr = (L_cgarc *)(addr + hsize + psize); 362 363 /* 364 * Turn on profiling 365 */ 366 /* LINTED */ 367 profil((unsigned short *)(addr + hsize), 368 psize, (unsigned long)lpc, (unsigned int) PRF_SCALE); 369 370 return (1); 371 } 372 373 374 uint_t 375 /* ARGSUSED1 */ 376 la_objopen(Link_map *lmp, Lmid_t lmid, uintptr_t *cookie) 377 { 378 char *objname; 379 380 /* 381 * This would only occur if the getenv() in la_version() failed. 382 * at this point there is nothing for us to do. 383 */ 384 if (pname == 0) 385 return (0); 386 387 /* 388 * Just grab the 'basename' of the object current object for 389 * comparing against the 'profiled object name' 390 */ 391 if (((objname = strrchr(lmp->l_name, '/')) == 0) || 392 (*(++objname) == 0)) 393 objname = lmp->l_name; 394 395 /* 396 * Is this the object we are going to profile. If not 397 * just set the 'BINDFROM' flag for this object. 398 */ 399 if ((strcmp(pname, objname) != 0) && 400 (strcmp(pname, lmp->l_name) != 0)) 401 return (LA_FLG_BINDFROM); 402 403 /* 404 * Don't even try to profile an object that does not have 405 * auditing enabled on it's link-map. This catches 'ld.so.1'. 406 */ 407 if (LIST(LINKMAP_TO_RTMAP(lmp))->lm_tflags & LML_TFLG_NOAUDIT) 408 return (LA_FLG_BINDFROM); 409 410 if (profile_open(pname, lmp) == 0) 411 return (0); 412 413 profcookie = *cookie; 414 415 return (LA_FLG_BINDFROM | LA_FLG_BINDTO); 416 } 417 418 419 420 uint_t 421 la_objclose(uintptr_t *cookie) 422 { 423 if (*cookie != profcookie) 424 return (0); 425 426 profcookie = 0; 427 /* 428 * Turn profil() off. 429 */ 430 profil(0, 0, 0, 0); 431 (void) munmap((caddr_t)Hptr, Fsize); 432 return (0); 433 } 434 435 436 static int 437 remap_profile(int fd) 438 { 439 caddr_t addr; 440 size_t l_fsize; 441 442 l_fsize = Hptr->hd_fsize; 443 444 if ((addr = (caddr_t)mmap(0, l_fsize, (PROT_READ | PROT_WRITE), 445 MAP_SHARED, fd, 0)) == (char *)-1) { 446 int err = errno; 447 448 (void) fprintf(stderr, MSG_INTL(MSG_SYS_MMAP), Profile, 449 strerror(err)); 450 return (0); 451 } 452 (void) munmap((caddr_t)Hptr, Fsize); 453 454 Fsize = l_fsize; 455 /* LINTED */ 456 Hptr = (L_hdr*) addr; 457 /* LINTED */ 458 Cptr = (L_cgarc *)(addr + sizeof (L_hdr) + Hptr->hd_psize); 459 return (1); 460 } 461 462 463 /* 464 * Update a call graph arc entry. This routine can be called three ways; 465 * o On initialization from one of the bndr() functions. 466 * In this case the `to' address is known, and may be used to 467 * initialize the call graph entry if this function has not 468 * been entered before. 469 * o On initial relocation (ie. LD_BIND_NOW). In this case the `to' 470 * address is known but the `from' isn't. The call graph entry 471 * is initialized to hold this dummy `to' address, but will be 472 * re-initialized later when a function is first called. 473 * o From an initialized plt entry. When profiling, the plt entries 474 * are filled in with the calling functions symbol index and 475 * the plt_cg_elf interface function. This interface function 476 * calls here to determine the `to' functions address, and in so 477 * doing increments the call count. 478 */ 479 uintptr_t 480 plt_cg_interp(uint_t ndx, caddr_t from, caddr_t to) 481 { 482 L_cgarc * cptr, cbucket; 483 sigset_t mask; 484 485 /* 486 * If the from address is outside of the address range being profiled, 487 * simply assign it to the `outside' address. 488 */ 489 if (from != PRF_UNKNOWN) { 490 if ((from > Hpc) || (from < Lpc)) 491 from = PRF_OUTADDR; 492 else 493 from = (caddr_t)(from - Lpc); 494 } 495 496 (void) prof_mutex_lock((mutex_t *)&Hptr->hd_mutex, &mask); 497 /* 498 * Has the buffer grown since last we looked at it (another processes 499 * could have grown it...). 500 */ 501 /* LINTED */ 502 if (Hptr->hd_fsize != (unsigned int)Fsize) { 503 int fd; 504 fd = open(Profile, O_RDWR, 0); 505 if (remap_profile(fd) == 0) { 506 (void) prof_mutex_unlock((mutex_t *)&Hptr->hd_mutex, 507 &mask); 508 exit(1); 509 } 510 (void) close(fd); 511 } 512 513 cptr = &Cptr[ndx]; 514 515 if (cptr->cg_to == 0) { 516 /* 517 * If this is the first time this function has been called we 518 * got here from one of the binders or an initial relocation 519 * (ie. LD_BIND_NOW). In this case the `to' address is 520 * provided. Initialize this functions call graph entry with 521 * the functions address (retained as a relative offset). 522 * If we know where the function call originated from 523 * initialize the count field. 524 */ 525 cptr->cg_to = (caddr_t)(to - Lpc); 526 cptr->cg_from = from; 527 if (from != PRF_UNKNOWN) 528 cptr->cg_count = 1; 529 } else { 530 /* 531 * If a function has been called from a previous run, but we 532 * don't know where we came from (ie. LD_BIND_NOW), then later 533 * calls through the plt will be able to obtain the required 534 * functions address, thus there is no need to proceed further. 535 */ 536 if (from != PRF_UNKNOWN) { 537 /* 538 * If the from addresses match simply bump the count. 539 * If not scan the link list to find a match for this 540 * `from' address. If one doesn't exit create a new 541 * entry and link it in. 542 */ 543 while ((cptr->cg_from != from) && 544 (cptr->cg_from != PRF_UNKNOWN)) { 545 if (cptr->cg_next != 0) 546 cptr = &Cptr[cptr->cg_next]; 547 else { 548 to = cptr->cg_to; 549 cptr->cg_next = Hptr->hd_ncndx++; 550 cptr = &Cptr[cptr->cg_next]; 551 /* 552 * If we've run out of file, extend it. 553 */ 554 if (Hptr->hd_ncndx == Hptr->hd_lcndx) { 555 caddr_t addr; 556 int fd; 557 558 /* LINTED */ 559 Hptr->hd_fsize += (unsigned int) 560 PRF_CGNUMB * 561 sizeof (L_cgarc); 562 fd = open(Profile, O_RDWR, 0); 563 if (ftruncate(fd, 564 Hptr->hd_fsize) == -1) { 565 int err = errno; 566 567 (void) fprintf(stderr, 568 MSG_INTL( 569 MSG_SYS_FTRUNC), 570 Profile, 571 strerror(err)); 572 (void) close(fd); 573 cptr = &cbucket; 574 } 575 /* 576 * Since the buffer will be 577 * remapped, we need to be 578 * prepared to adjust cptr. 579 */ 580 addr = (caddr_t)((Addr)cptr - 581 (Addr)Cptr); 582 if (remap_profile(fd) == 0) { 583 /* CSTYLED */ 584 (void) prof_mutex_unlock( 585 (mutex_t *)&Hptr-> 586 hd_mutex, &mask); 587 exit(1); 588 } 589 cptr = (L_cgarc *)((Addr)addr + 590 (Addr)Cptr); 591 (void) close(fd); 592 Hptr->hd_lcndx += PRF_CGNUMB; 593 } 594 cptr->cg_from = from; 595 cptr->cg_to = to; 596 } 597 } 598 /* 599 * If we're updating an entry from an unknown call 600 * address initialize this element, otherwise 601 * increment the call count. 602 */ 603 if (cptr->cg_from == PRF_UNKNOWN) { 604 cptr->cg_from = from; 605 cptr->cg_count = 1; 606 } else 607 cptr->cg_count++; 608 } 609 } 610 /* 611 * Return the real address of the function. 612 */ 613 (void) prof_mutex_unlock((mutex_t *)&Hptr->hd_mutex, &mask); 614 615 return ((uintptr_t)((Addr)cptr->cg_to + (Addr)Lpc)); 616 } 617 618 /* ARGSUSED2 */ 619 #if defined(__sparcv9) 620 uintptr_t 621 la_sparcv9_pltenter(Elf64_Sym *symp, uint_t symndx, uintptr_t *refcookie, 622 uintptr_t *defcookie, La_sparcv9_regs *regset, uint_t *sbflags, 623 const char *sym_name) 624 #elif defined(__sparc) 625 uintptr_t 626 la_sparcv8_pltenter(Elf32_Sym *symp, uint_t symndx, uintptr_t *refcookie, 627 uintptr_t *defcookie, La_sparcv8_regs *regset, uint_t *sbflags) 628 #elif defined(__amd64) 629 uintptr_t 630 la_amd64_pltenter(Elf64_Sym *symp, uint_t symndx, uintptr_t *refcookie, 631 uintptr_t *defcookie, La_amd64_regs *regset, uint_t *sbflags, 632 const char *sym_name) 633 #elif defined(__i386) 634 uintptr_t 635 la_i86_pltenter(Elf32_Sym *symp, uint_t symndx, uintptr_t *refcookie, 636 uintptr_t *defcookie, La_i86_regs *regset, uint_t *sbflags) 637 #else 638 #error unexpected architecture! 639 #endif 640 { 641 caddr_t from; 642 643 /* 644 * profiling has been disabled. 645 */ 646 if (profcookie == 0) 647 return (symp->st_value); 648 #if defined(__sparc) 649 /* 650 * The callers return address is currently stored in O7 (which 651 * will become I7 when the window shift occurs). 652 */ 653 from = (caddr_t)regset->lr_rego7; 654 #elif defined(__amd64) 655 /* 656 * The callers return address is on the top of the stack for amd64 657 */ 658 from = *(caddr_t *)(regset->lr_rsp); 659 #elif defined(__i386) 660 /* 661 * The callers return address is on the top of the stack for i386 662 */ 663 from = *(caddr_t *)(regset->lr_esp); 664 #else 665 #error unexpected architecture! 666 #endif 667 return (plt_cg_interp(symndx, (caddr_t)from, (caddr_t)symp->st_value)); 668 } 669