1 /*- 2 * Copyright (c) 2003-2008 Joseph Koshy 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <sys/types.h> 31 #include <sys/cpuset.h> 32 #include <sys/param.h> 33 #include <sys/endian.h> 34 #include <sys/pmc.h> 35 #include <sys/imgact_aout.h> 36 #include <sys/imgact_elf.h> 37 38 #include <netinet/in.h> 39 40 #include <assert.h> 41 #include <err.h> 42 #include <fcntl.h> 43 #include <pmc.h> 44 #include <pmclog.h> 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <string.h> 48 #include <sysexits.h> 49 #include <unistd.h> 50 51 #include "libpmcstat.h" 52 53 #define min(A,B) ((A) < (B) ? (A) : (B)) 54 #define max(A,B) ((A) > (B) ? (A) : (B)) 55 56 /* 57 * Add the list of symbols in the given section to the list associated 58 * with the object. 59 */ 60 void 61 pmcstat_image_add_symbols(struct pmcstat_image *image, Elf *e, 62 Elf_Scn *scn, GElf_Shdr *sh) 63 { 64 int firsttime; 65 size_t n, newsyms, nshsyms, nfuncsyms; 66 struct pmcstat_symbol *symptr; 67 char *fnname; 68 GElf_Sym sym; 69 Elf_Data *data; 70 71 if ((data = elf_getdata(scn, NULL)) == NULL) 72 return; 73 74 /* 75 * Determine the number of functions named in this 76 * section. 77 */ 78 79 nshsyms = sh->sh_size / sh->sh_entsize; 80 for (n = nfuncsyms = 0; n < nshsyms; n++) { 81 if (gelf_getsym(data, (int) n, &sym) != &sym) 82 return; 83 if (GELF_ST_TYPE(sym.st_info) == STT_FUNC) 84 nfuncsyms++; 85 } 86 87 if (nfuncsyms == 0) 88 return; 89 90 /* 91 * Allocate space for the new entries. 92 */ 93 firsttime = image->pi_symbols == NULL; 94 symptr = reallocarray(image->pi_symbols, 95 image->pi_symcount + nfuncsyms, sizeof(*symptr)); 96 if (symptr == image->pi_symbols) /* realloc() failed. */ 97 return; 98 image->pi_symbols = symptr; 99 100 /* 101 * Append new symbols to the end of the current table. 102 */ 103 symptr += image->pi_symcount; 104 105 for (n = newsyms = 0; n < nshsyms; n++) { 106 if (gelf_getsym(data, (int) n, &sym) != &sym) 107 return; 108 if (GELF_ST_TYPE(sym.st_info) != STT_FUNC) 109 continue; 110 111 if (sym.st_shndx == STN_UNDEF) 112 continue; 113 114 if (!firsttime && pmcstat_symbol_search(image, sym.st_value)) 115 continue; /* We've seen this symbol already. */ 116 117 if ((fnname = elf_strptr(e, sh->sh_link, sym.st_name)) 118 == NULL) 119 continue; 120 #ifdef __arm__ 121 /* Remove spurious ARM function name. */ 122 if (fnname[0] == '$' && 123 (fnname[1] == 'a' || fnname[1] == 't' || 124 fnname[1] == 'd') && 125 fnname[2] == '\0') 126 continue; 127 #endif 128 129 symptr->ps_name = pmcstat_string_intern(fnname); 130 symptr->ps_start = sym.st_value - image->pi_vaddr; 131 symptr->ps_end = symptr->ps_start + sym.st_size; 132 133 symptr++; 134 newsyms++; 135 } 136 137 image->pi_symcount += newsyms; 138 if (image->pi_symcount == 0) 139 return; 140 141 assert(newsyms <= nfuncsyms); 142 143 /* 144 * Return space to the system if there were duplicates. 145 */ 146 if (newsyms < nfuncsyms) 147 image->pi_symbols = reallocarray(image->pi_symbols, 148 image->pi_symcount, sizeof(*symptr)); 149 150 /* 151 * Keep the list of symbols sorted. 152 */ 153 qsort(image->pi_symbols, image->pi_symcount, sizeof(*symptr), 154 pmcstat_symbol_compare); 155 156 /* 157 * Deal with function symbols that have a size of 'zero' by 158 * making them extend to the next higher address. These 159 * symbols are usually defined in assembly code. 160 */ 161 for (symptr = image->pi_symbols; 162 symptr < image->pi_symbols + (image->pi_symcount - 1); 163 symptr++) 164 if (symptr->ps_start == symptr->ps_end) 165 symptr->ps_end = (symptr+1)->ps_start; 166 } 167 168 /* 169 * Record the fact that PC values from 'start' to 'end' come from 170 * image 'image'. 171 */ 172 173 void 174 pmcstat_image_link(struct pmcstat_process *pp, struct pmcstat_image *image, 175 uintfptr_t start) 176 { 177 struct pmcstat_pcmap *pcm, *pcmnew; 178 uintfptr_t offset; 179 180 assert(image->pi_type != PMCSTAT_IMAGE_UNKNOWN && 181 image->pi_type != PMCSTAT_IMAGE_INDETERMINABLE); 182 183 if ((pcmnew = malloc(sizeof(*pcmnew))) == NULL) 184 err(EX_OSERR, "ERROR: Cannot create a map entry"); 185 186 /* 187 * Adjust the map entry to only cover the text portion 188 * of the object. 189 */ 190 191 offset = start - image->pi_vaddr; 192 pcmnew->ppm_lowpc = image->pi_start + offset; 193 pcmnew->ppm_highpc = image->pi_end + offset; 194 pcmnew->ppm_image = image; 195 196 assert(pcmnew->ppm_lowpc < pcmnew->ppm_highpc); 197 198 /* Overlapped mmap()'s are assumed to never occur. */ 199 TAILQ_FOREACH(pcm, &pp->pp_map, ppm_next) 200 if (pcm->ppm_lowpc >= pcmnew->ppm_highpc) 201 break; 202 203 if (pcm == NULL) 204 TAILQ_INSERT_TAIL(&pp->pp_map, pcmnew, ppm_next); 205 else 206 TAILQ_INSERT_BEFORE(pcm, pcmnew, ppm_next); 207 } 208 209 /* 210 * Determine whether a given executable image is an A.OUT object, and 211 * if so, fill in its parameters from the text file. 212 * Sets image->pi_type. 213 */ 214 215 void 216 pmcstat_image_get_aout_params(struct pmcstat_image *image, 217 struct pmcstat_args *args) 218 { 219 int fd; 220 ssize_t nbytes; 221 struct exec ex; 222 const char *path; 223 char buffer[PATH_MAX]; 224 225 path = pmcstat_string_unintern(image->pi_execpath); 226 assert(path != NULL); 227 228 if (image->pi_iskernelmodule) 229 errx(EX_SOFTWARE, 230 "ERROR: a.out kernel modules are unsupported \"%s\"", path); 231 232 (void) snprintf(buffer, sizeof(buffer), "%s%s", 233 args->pa_fsroot, path); 234 235 if ((fd = open(buffer, O_RDONLY, 0)) < 0 || 236 (nbytes = read(fd, &ex, sizeof(ex))) < 0) { 237 if (args->pa_verbosity >= 2) 238 warn("WARNING: Cannot determine type of \"%s\"", 239 path); 240 image->pi_type = PMCSTAT_IMAGE_INDETERMINABLE; 241 if (fd != -1) 242 (void) close(fd); 243 return; 244 } 245 246 (void) close(fd); 247 248 if ((unsigned) nbytes != sizeof(ex) || 249 N_BADMAG(ex)) 250 return; 251 252 image->pi_type = PMCSTAT_IMAGE_AOUT; 253 254 /* TODO: the rest of a.out processing */ 255 256 return; 257 } 258 259 /* 260 * Examine an ELF file to determine the size of its text segment. 261 * Sets image->pi_type if anything conclusive can be determined about 262 * this image. 263 */ 264 265 void 266 pmcstat_image_get_elf_params(struct pmcstat_image *image, 267 struct pmcstat_args *args) 268 { 269 int fd; 270 size_t i, nph, nsh; 271 const char *path, *elfbase; 272 char *p, *endp; 273 uintfptr_t minva, maxva; 274 Elf *e; 275 Elf_Scn *scn; 276 GElf_Ehdr eh; 277 GElf_Phdr ph; 278 GElf_Shdr sh; 279 enum pmcstat_image_type image_type; 280 char buffer[PATH_MAX]; 281 char buffer_modules[PATH_MAX]; 282 283 assert(image->pi_type == PMCSTAT_IMAGE_UNKNOWN); 284 285 image->pi_start = minva = ~(uintfptr_t) 0; 286 image->pi_end = maxva = (uintfptr_t) 0; 287 image->pi_type = image_type = PMCSTAT_IMAGE_INDETERMINABLE; 288 image->pi_isdynamic = 0; 289 image->pi_dynlinkerpath = NULL; 290 image->pi_vaddr = 0; 291 292 path = pmcstat_string_unintern(image->pi_execpath); 293 assert(path != NULL); 294 295 /* 296 * Look for kernel modules under FSROOT/KERNELPATH/NAME and 297 * FSROOT/boot/modules/NAME, and user mode executable objects 298 * under FSROOT/PATHNAME. 299 */ 300 if (image->pi_iskernelmodule) { 301 (void) snprintf(buffer, sizeof(buffer), "%s%s/%s", 302 args->pa_fsroot, args->pa_kernel, path); 303 (void) snprintf(buffer_modules, sizeof(buffer_modules), 304 "%s/boot/modules/%s", args->pa_fsroot, path); 305 } else { 306 (void) snprintf(buffer, sizeof(buffer), "%s%s", 307 args->pa_fsroot, path); 308 } 309 310 e = NULL; 311 fd = open(buffer, O_RDONLY, 0); 312 if (fd < 0 && !image->pi_iskernelmodule) { 313 warnx("WARNING: Cannot open \"%s\".", 314 buffer); 315 goto done; 316 } 317 if (fd < 0 && (fd = open(buffer_modules, O_RDONLY, 0)) < 0) { 318 warnx("WARNING: Cannot open \"%s\" or \"%s\".", 319 buffer, buffer_modules); 320 goto done; 321 } 322 if (elf_version(EV_CURRENT) == EV_NONE) { 323 warnx("WARNING: failed to init elf\n"); 324 goto done; 325 } 326 327 if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 328 warnx("WARNING: Cannot read \"%s\".", 329 buffer); 330 goto done; 331 } 332 333 if (elf_kind(e) != ELF_K_ELF) { 334 if (args->pa_verbosity >= 2) 335 warnx("WARNING: Cannot determine the type of \"%s\".", 336 buffer); 337 goto done; 338 } 339 340 if (gelf_getehdr(e, &eh) != &eh) { 341 warnx( 342 "WARNING: Cannot retrieve the ELF Header for \"%s\": %s.", 343 buffer, elf_errmsg(-1)); 344 goto done; 345 } 346 347 if (eh.e_type != ET_EXEC && eh.e_type != ET_DYN && 348 !(image->pi_iskernelmodule && eh.e_type == ET_REL)) { 349 warnx("WARNING: \"%s\" is of an unsupported ELF type.", 350 buffer); 351 goto done; 352 } 353 354 image_type = eh.e_ident[EI_CLASS] == ELFCLASS32 ? 355 PMCSTAT_IMAGE_ELF32 : PMCSTAT_IMAGE_ELF64; 356 357 /* 358 * Determine the virtual address where an executable would be 359 * loaded. Additionally, for dynamically linked executables, 360 * save the pathname to the runtime linker. 361 */ 362 if (eh.e_type == ET_EXEC) { 363 if (elf_getphnum(e, &nph) == 0) { 364 warnx( 365 "WARNING: Could not determine the number of program headers in \"%s\": %s.", 366 buffer, 367 elf_errmsg(-1)); 368 goto done; 369 } 370 for (i = 0; i < eh.e_phnum; i++) { 371 if (gelf_getphdr(e, i, &ph) != &ph) { 372 warnx( 373 "WARNING: Retrieval of PHDR entry #%ju in \"%s\" failed: %s.", 374 (uintmax_t) i, buffer, elf_errmsg(-1)); 375 goto done; 376 } 377 switch (ph.p_type) { 378 case PT_DYNAMIC: 379 image->pi_isdynamic = 1; 380 break; 381 case PT_INTERP: 382 if ((elfbase = elf_rawfile(e, NULL)) == NULL) { 383 warnx( 384 "WARNING: Cannot retrieve the interpreter for \"%s\": %s.", 385 buffer, elf_errmsg(-1)); 386 goto done; 387 } 388 image->pi_dynlinkerpath = 389 pmcstat_string_intern(elfbase + 390 ph.p_offset); 391 break; 392 case PT_LOAD: 393 if ((ph.p_flags & PF_X) != 0 && 394 (ph.p_offset & (-ph.p_align)) == 0) 395 image->pi_vaddr = ph.p_vaddr & (-ph.p_align); 396 break; 397 } 398 } 399 } 400 401 /* 402 * Get the min and max VA associated with this ELF object. 403 */ 404 if (elf_getshnum(e, &nsh) == 0) { 405 warnx( 406 "WARNING: Could not determine the number of sections for \"%s\": %s.", 407 buffer, elf_errmsg(-1)); 408 goto done; 409 } 410 411 for (i = 0; i < nsh; i++) { 412 if ((scn = elf_getscn(e, i)) == NULL || 413 gelf_getshdr(scn, &sh) != &sh) { 414 warnx( 415 "WARNING: Could not retrieve section header #%ju in \"%s\": %s.", 416 (uintmax_t) i, buffer, elf_errmsg(-1)); 417 goto done; 418 } 419 if (sh.sh_flags & SHF_EXECINSTR) { 420 minva = min(minva, sh.sh_addr); 421 maxva = max(maxva, sh.sh_addr + sh.sh_size); 422 } 423 if (sh.sh_type == SHT_SYMTAB || sh.sh_type == SHT_DYNSYM) 424 pmcstat_image_add_symbols(image, e, scn, &sh); 425 } 426 427 image->pi_start = minva; 428 image->pi_end = maxva; 429 image->pi_type = image_type; 430 image->pi_fullpath = pmcstat_string_intern(buffer); 431 432 /* Build display name 433 */ 434 endp = buffer; 435 for (p = buffer; *p; p++) 436 if (*p == '/') 437 endp = p+1; 438 image->pi_name = pmcstat_string_intern(endp); 439 440 done: 441 (void) elf_end(e); 442 if (fd >= 0) 443 (void) close(fd); 444 return; 445 } 446 447 /* 448 * Given an image descriptor, determine whether it is an ELF, or AOUT. 449 * If no handler claims the image, set its type to 'INDETERMINABLE'. 450 */ 451 452 void 453 pmcstat_image_determine_type(struct pmcstat_image *image, 454 struct pmcstat_args *args) 455 { 456 assert(image->pi_type == PMCSTAT_IMAGE_UNKNOWN); 457 458 /* Try each kind of handler in turn */ 459 if (image->pi_type == PMCSTAT_IMAGE_UNKNOWN) 460 pmcstat_image_get_elf_params(image, args); 461 if (image->pi_type == PMCSTAT_IMAGE_UNKNOWN) 462 pmcstat_image_get_aout_params(image, args); 463 464 /* 465 * Otherwise, remember that we tried to determine 466 * the object's type and had failed. 467 */ 468 if (image->pi_type == PMCSTAT_IMAGE_UNKNOWN) 469 image->pi_type = PMCSTAT_IMAGE_INDETERMINABLE; 470 } 471 472 /* 473 * Locate an image descriptor given an interned path, adding a fresh 474 * descriptor to the cache if necessary. This function also finds a 475 * suitable name for this image's sample file. 476 * 477 * We defer filling in the file format specific parts of the image 478 * structure till the time we actually see a sample that would fall 479 * into this image. 480 */ 481 482 struct pmcstat_image * 483 pmcstat_image_from_path(pmcstat_interned_string internedpath, 484 int iskernelmodule, struct pmcstat_args *args, 485 struct pmc_plugins *plugins) 486 { 487 int hash; 488 struct pmcstat_image *pi; 489 490 hash = pmcstat_string_lookup_hash(internedpath); 491 492 /* First, look for an existing entry. */ 493 LIST_FOREACH(pi, &pmcstat_image_hash[hash], pi_next) 494 if (pi->pi_execpath == internedpath && 495 pi->pi_iskernelmodule == iskernelmodule) 496 return (pi); 497 498 /* 499 * Allocate a new entry and place it at the head of the hash 500 * and LRU lists. 501 */ 502 pi = malloc(sizeof(*pi)); 503 if (pi == NULL) 504 return (NULL); 505 506 pi->pi_type = PMCSTAT_IMAGE_UNKNOWN; 507 pi->pi_execpath = internedpath; 508 pi->pi_start = ~0; 509 pi->pi_end = 0; 510 pi->pi_entry = 0; 511 pi->pi_vaddr = 0; 512 pi->pi_isdynamic = 0; 513 pi->pi_iskernelmodule = iskernelmodule; 514 pi->pi_dynlinkerpath = NULL; 515 pi->pi_symbols = NULL; 516 pi->pi_symcount = 0; 517 pi->pi_addr2line = NULL; 518 519 if (plugins[args->pa_pplugin].pl_initimage != NULL) 520 plugins[args->pa_pplugin].pl_initimage(pi); 521 if (plugins[args->pa_plugin].pl_initimage != NULL) 522 plugins[args->pa_plugin].pl_initimage(pi); 523 524 LIST_INSERT_HEAD(&pmcstat_image_hash[hash], pi, pi_next); 525 526 return (pi); 527 } 528