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/types.h>
28 #include <sys/cpuset.h>
29 #include <sys/param.h>
30 #include <sys/endian.h>
31 #include <sys/pmc.h>
32 #include <sys/sysctl.h>
33 #include <sys/imgact_aout.h>
34 #include <sys/imgact_elf.h>
35
36 #include <netinet/in.h>
37
38 #include <assert.h>
39 #include <err.h>
40 #include <fcntl.h>
41 #include <pmc.h>
42 #include <pmclog.h>
43 #include <stdbool.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <sysexits.h>
48 #include <unistd.h>
49
50 #include "libpmcstat.h"
51
52 #define min(A,B) ((A) < (B) ? (A) : (B))
53 #define max(A,B) ((A) > (B) ? (A) : (B))
54
55 /*
56 * Add the list of symbols in the given section to the list associated
57 * with the object.
58 */
59 void
pmcstat_image_add_symbols(struct pmcstat_image * image,Elf * e,Elf_Scn * scn,GElf_Shdr * sh)60 pmcstat_image_add_symbols(struct pmcstat_image *image, Elf *e,
61 Elf_Scn *scn, GElf_Shdr *sh)
62 {
63 int firsttime;
64 size_t n, newsyms, nshsyms, nfuncsyms;
65 struct pmcstat_symbol *symptr;
66 char *fnname;
67 GElf_Sym sym;
68 Elf_Data *data;
69
70 if ((data = elf_getdata(scn, NULL)) == NULL)
71 return;
72
73 /*
74 * Determine the number of functions named in this
75 * section.
76 */
77
78 nshsyms = sh->sh_size / sh->sh_entsize;
79 for (n = nfuncsyms = 0; n < nshsyms; n++) {
80 if (gelf_getsym(data, (int) n, &sym) != &sym)
81 return;
82 if (GELF_ST_TYPE(sym.st_info) == STT_FUNC)
83 nfuncsyms++;
84 }
85
86 if (nfuncsyms == 0)
87 return;
88
89 /*
90 * Allocate space for the new entries.
91 */
92 firsttime = image->pi_symbols == NULL;
93 symptr = reallocarray(image->pi_symbols,
94 image->pi_symcount + nfuncsyms, sizeof(*symptr));
95 if (symptr == image->pi_symbols) /* realloc() failed. */
96 return;
97 image->pi_symbols = symptr;
98
99 /*
100 * Append new symbols to the end of the current table.
101 */
102 symptr += image->pi_symcount;
103
104 for (n = newsyms = 0; n < nshsyms; n++) {
105 if (gelf_getsym(data, (int) n, &sym) != &sym)
106 return;
107 if (GELF_ST_TYPE(sym.st_info) != STT_FUNC)
108 continue;
109
110 if (sym.st_shndx == STN_UNDEF)
111 continue;
112
113 if (!firsttime && pmcstat_symbol_search(image, sym.st_value))
114 continue; /* We've seen this symbol already. */
115
116 if ((fnname = elf_strptr(e, sh->sh_link, sym.st_name))
117 == NULL)
118 continue;
119
120 #if defined(__aarch64__) || defined(__arm__)
121 /* Ignore ARM mapping symbols. */
122 if (fnname[0] == '$' &&
123 (fnname[1] == 'a' || fnname[1] == 't' ||
124 fnname[1] == 'd' || fnname[1] == 'x'))
125 continue;
126
127 /*
128 * Clear LSB from starting addresses for functions
129 * which execute in Thumb mode. We should perhaps
130 * only do this for functions in a $t mapping symbol
131 * range, but parsing mapping symbols would be a lot
132 * of work and function addresses shouldn't have the
133 * LSB set otherwise.
134 */
135 sym.st_value &= ~1;
136 #endif
137
138 symptr->ps_name = pmcstat_string_intern(fnname);
139 symptr->ps_start = sym.st_value - image->pi_vaddr;
140 symptr->ps_end = symptr->ps_start + sym.st_size;
141
142 symptr++;
143 newsyms++;
144 }
145
146 image->pi_symcount += newsyms;
147 if (image->pi_symcount == 0)
148 return;
149
150 assert(newsyms <= nfuncsyms);
151
152 /*
153 * Return space to the system if there were duplicates.
154 */
155 if (newsyms < nfuncsyms)
156 image->pi_symbols = reallocarray(image->pi_symbols,
157 image->pi_symcount, sizeof(*symptr));
158
159 /*
160 * Keep the list of symbols sorted.
161 */
162 qsort(image->pi_symbols, image->pi_symcount, sizeof(*symptr),
163 pmcstat_symbol_compare);
164
165 /*
166 * Deal with function symbols that have a size of 'zero' by
167 * making them extend to the next higher address. These
168 * symbols are usually defined in assembly code.
169 */
170 for (symptr = image->pi_symbols;
171 symptr < image->pi_symbols + (image->pi_symcount - 1);
172 symptr++)
173 if (symptr->ps_start == symptr->ps_end)
174 symptr->ps_end = (symptr+1)->ps_start;
175 }
176
177 /*
178 * Record the fact that PC values from 'start' to 'end' come from
179 * image 'image'.
180 */
181
182 void
pmcstat_image_link(struct pmcstat_process * pp,struct pmcstat_image * image,uintfptr_t start)183 pmcstat_image_link(struct pmcstat_process *pp, struct pmcstat_image *image,
184 uintfptr_t start)
185 {
186 struct pmcstat_pcmap *pcm, *pcmnew;
187 uintfptr_t offset;
188 #ifdef __powerpc__
189 unsigned long kernbase;
190 size_t kernbase_len;
191 #endif
192
193 assert(image->pi_type != PMCSTAT_IMAGE_UNKNOWN &&
194 image->pi_type != PMCSTAT_IMAGE_INDETERMINABLE);
195
196 /*
197 * It's possible to have images with nothing of value in .text
198 * legitimately. We shouldn't have any samples from this image, so
199 * don't bother with a map entry either.
200 */
201 if (image->pi_start == 0 && image->pi_end == 0)
202 return;
203
204 if ((pcmnew = malloc(sizeof(*pcmnew))) == NULL)
205 err(EX_OSERR, "ERROR: Cannot create a map entry");
206
207 /*
208 * PowerPC kernel is of DYN type and it has a base address
209 * where it is initially loaded, before being relocated.
210 * As the address in 'start' is where the kernel was relocated to,
211 * but the symbols always use the original base address, we need to
212 * subtract it to get the correct offset.
213 */
214 #ifdef __powerpc__
215 if (pp->pp_pid == -1) {
216 kernbase = 0;
217 kernbase_len = sizeof(kernbase);
218 if (sysctlbyname("kern.base_address", &kernbase, &kernbase_len,
219 NULL, 0) == -1)
220 warnx(
221 "WARNING: Could not retrieve kernel base address");
222 else
223 start -= kernbase;
224 }
225 #endif
226
227 /*
228 * Adjust the map entry to only cover the text portion
229 * of the object.
230 */
231
232 offset = start - image->pi_vaddr;
233 pcmnew->ppm_lowpc = image->pi_start + offset;
234 pcmnew->ppm_highpc = image->pi_end + offset;
235 pcmnew->ppm_image = image;
236
237 assert(pcmnew->ppm_lowpc < pcmnew->ppm_highpc);
238
239 /* Overlapped mmap()'s are assumed to never occur. */
240 TAILQ_FOREACH(pcm, &pp->pp_map, ppm_next)
241 if (pcm->ppm_lowpc >= pcmnew->ppm_highpc)
242 break;
243
244 if (pcm == NULL)
245 TAILQ_INSERT_TAIL(&pp->pp_map, pcmnew, ppm_next);
246 else
247 TAILQ_INSERT_BEFORE(pcm, pcmnew, ppm_next);
248 }
249
250 /*
251 * Determine whether a given executable image is an A.OUT object, and
252 * if so, fill in its parameters from the text file.
253 * Sets image->pi_type.
254 */
255
256 void
pmcstat_image_get_aout_params(struct pmcstat_image * image,struct pmcstat_args * args)257 pmcstat_image_get_aout_params(struct pmcstat_image *image,
258 struct pmcstat_args *args)
259 {
260 int fd;
261 ssize_t nbytes;
262 struct exec ex;
263 const char *path;
264 char buffer[PATH_MAX];
265
266 path = pmcstat_string_unintern(image->pi_execpath);
267 assert(path != NULL);
268
269 if (image->pi_iskernelmodule)
270 errx(EX_SOFTWARE,
271 "ERROR: a.out kernel modules are unsupported \"%s\"", path);
272
273 (void) snprintf(buffer, sizeof(buffer), "%s%s",
274 args->pa_fsroot, path);
275
276 if ((fd = open(buffer, O_RDONLY, 0)) < 0 ||
277 (nbytes = read(fd, &ex, sizeof(ex))) < 0) {
278 if (args->pa_verbosity >= 2)
279 warn("WARNING: Cannot determine type of \"%s\"",
280 path);
281 image->pi_type = PMCSTAT_IMAGE_INDETERMINABLE;
282 if (fd != -1)
283 (void) close(fd);
284 return;
285 }
286
287 (void) close(fd);
288
289 if ((unsigned) nbytes != sizeof(ex) ||
290 N_BADMAG(ex))
291 return;
292
293 image->pi_type = PMCSTAT_IMAGE_AOUT;
294
295 /* TODO: the rest of a.out processing */
296
297 return;
298 }
299
300 /*
301 * Examine an ELF file to determine the size of its text segment.
302 * Sets image->pi_type if anything conclusive can be determined about
303 * this image.
304 */
305
306 void
pmcstat_image_get_elf_params(struct pmcstat_image * image,struct pmcstat_args * args)307 pmcstat_image_get_elf_params(struct pmcstat_image *image,
308 struct pmcstat_args *args)
309 {
310 int fd;
311 size_t i, nph, nsh;
312 const char *path, *elfbase;
313 char *p, *endp;
314 bool first_exec_segment;
315 uintfptr_t minva, maxva, pagesize;
316 Elf *e;
317 Elf_Scn *scn;
318 GElf_Ehdr eh;
319 GElf_Phdr ph;
320 GElf_Shdr sh;
321 enum pmcstat_image_type image_type;
322 char buffer[PATH_MAX];
323
324 assert(image->pi_type == PMCSTAT_IMAGE_UNKNOWN);
325
326 image->pi_start = minva = ~(uintfptr_t) 0;
327 image->pi_end = maxva = (uintfptr_t) 0;
328 image->pi_type = image_type = PMCSTAT_IMAGE_INDETERMINABLE;
329 image->pi_isdynamic = 0;
330 image->pi_dynlinkerpath = NULL;
331 image->pi_vaddr = 0;
332
333 if (args->pa_pageshift != 0)
334 pagesize = 1ULL << args->pa_pageshift;
335 else
336 pagesize = getpagesize();
337
338 path = pmcstat_string_unintern(image->pi_execpath);
339 assert(path != NULL);
340
341 /*
342 * Look for files under FSROOT/PATHNAME.
343 */
344 (void) snprintf(buffer, sizeof(buffer), "%s%s",
345 args->pa_fsroot, path);
346
347 e = NULL;
348 fd = open(buffer, O_RDONLY, 0);
349 if (fd < 0) {
350 warnx("WARNING: Cannot open \"%s\".",
351 buffer);
352 goto done;
353 }
354
355 if (elf_version(EV_CURRENT) == EV_NONE) {
356 warnx("WARNING: failed to init elf\n");
357 goto done;
358 }
359
360 if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
361 warnx("WARNING: Cannot read \"%s\".",
362 buffer);
363 goto done;
364 }
365
366 if (elf_kind(e) != ELF_K_ELF) {
367 if (args->pa_verbosity >= 2)
368 warnx("WARNING: Cannot determine the type of \"%s\".",
369 buffer);
370 goto done;
371 }
372
373 if (gelf_getehdr(e, &eh) != &eh) {
374 warnx(
375 "WARNING: Cannot retrieve the ELF Header for \"%s\": %s.",
376 buffer, elf_errmsg(-1));
377 goto done;
378 }
379
380 if (eh.e_type != ET_EXEC && eh.e_type != ET_DYN &&
381 !(image->pi_iskernelmodule && eh.e_type == ET_REL)) {
382 warnx("WARNING: \"%s\" is of an unsupported ELF type.",
383 buffer);
384 goto done;
385 }
386
387 image_type = eh.e_ident[EI_CLASS] == ELFCLASS32 ?
388 PMCSTAT_IMAGE_ELF32 : PMCSTAT_IMAGE_ELF64;
389
390 /*
391 * Determine the virtual address where an executable would be
392 * loaded. Additionally, for dynamically linked executables,
393 * save the pathname to the runtime linker.
394 */
395 if (eh.e_type != ET_REL) {
396 if (elf_getphnum(e, &nph) == 0) {
397 warnx(
398 "WARNING: Could not determine the number of program headers in \"%s\": %s.",
399 buffer,
400 elf_errmsg(-1));
401 goto done;
402 }
403 first_exec_segment = true;
404 for (i = 0; i < eh.e_phnum; i++) {
405 if (gelf_getphdr(e, i, &ph) != &ph) {
406 warnx(
407 "WARNING: Retrieval of PHDR entry #%ju in \"%s\" failed: %s.",
408 (uintmax_t) i, buffer, elf_errmsg(-1));
409 goto done;
410 }
411 switch (ph.p_type) {
412 case PT_DYNAMIC:
413 image->pi_isdynamic = 1;
414 break;
415 case PT_INTERP:
416 if ((elfbase = elf_rawfile(e, NULL)) == NULL) {
417 warnx(
418 "WARNING: Cannot retrieve the interpreter for \"%s\": %s.",
419 buffer, elf_errmsg(-1));
420 goto done;
421 }
422 image->pi_dynlinkerpath =
423 pmcstat_string_intern(elfbase +
424 ph.p_offset);
425 break;
426 case PT_LOAD:
427 if ((ph.p_flags & PF_X) != 0 &&
428 first_exec_segment) {
429 if (image->pi_iskernelmodule) {
430 image->pi_vaddr = ph.p_vaddr &
431 (-ph.p_align);
432 } else {
433 /*
434 * User MAP_IN records depend
435 * on page size.
436 */
437 image->pi_vaddr = rounddown2(
438 ph.p_vaddr, pagesize);
439 }
440 first_exec_segment = false;
441 }
442 break;
443 }
444 }
445 }
446
447 /*
448 * Get the min and max VA associated with this ELF object.
449 */
450 if (elf_getshnum(e, &nsh) == 0) {
451 warnx(
452 "WARNING: Could not determine the number of sections for \"%s\": %s.",
453 buffer, elf_errmsg(-1));
454 goto done;
455 }
456
457 for (i = 0; i < nsh; i++) {
458 if ((scn = elf_getscn(e, i)) == NULL ||
459 gelf_getshdr(scn, &sh) != &sh) {
460 warnx(
461 "WARNING: Could not retrieve section header #%ju in \"%s\": %s.",
462 (uintmax_t) i, buffer, elf_errmsg(-1));
463 goto done;
464 }
465 if (sh.sh_flags & SHF_EXECINSTR) {
466 minva = min(minva, sh.sh_addr);
467 maxva = max(maxva, sh.sh_addr + sh.sh_size);
468 }
469 if (sh.sh_type == SHT_SYMTAB || sh.sh_type == SHT_DYNSYM)
470 pmcstat_image_add_symbols(image, e, scn, &sh);
471 }
472
473 image->pi_start = minva;
474 image->pi_end = maxva;
475 image->pi_type = image_type;
476 image->pi_fullpath = pmcstat_string_intern(buffer);
477
478 /* Build display name
479 */
480 endp = buffer;
481 for (p = buffer; *p; p++)
482 if (*p == '/')
483 endp = p+1;
484 image->pi_name = pmcstat_string_intern(endp);
485
486 done:
487 (void) elf_end(e);
488 if (fd >= 0)
489 (void) close(fd);
490 return;
491 }
492
493 /*
494 * Given an image descriptor, determine whether it is an ELF, or AOUT.
495 * If no handler claims the image, set its type to 'INDETERMINABLE'.
496 */
497
498 void
pmcstat_image_determine_type(struct pmcstat_image * image,struct pmcstat_args * args)499 pmcstat_image_determine_type(struct pmcstat_image *image,
500 struct pmcstat_args *args)
501 {
502 assert(image->pi_type == PMCSTAT_IMAGE_UNKNOWN);
503
504 /* Try each kind of handler in turn */
505 if (image->pi_type == PMCSTAT_IMAGE_UNKNOWN)
506 pmcstat_image_get_elf_params(image, args);
507 if (image->pi_type == PMCSTAT_IMAGE_UNKNOWN)
508 pmcstat_image_get_aout_params(image, args);
509
510 /*
511 * Otherwise, remember that we tried to determine
512 * the object's type and had failed.
513 */
514 if (image->pi_type == PMCSTAT_IMAGE_UNKNOWN)
515 image->pi_type = PMCSTAT_IMAGE_INDETERMINABLE;
516 }
517
518 /*
519 * Locate an image descriptor given an interned path, adding a fresh
520 * descriptor to the cache if necessary. This function also finds a
521 * suitable name for this image's sample file.
522 *
523 * We defer filling in the file format specific parts of the image
524 * structure till the time we actually see a sample that would fall
525 * into this image.
526 */
527
528 struct pmcstat_image *
pmcstat_image_from_path(pmcstat_interned_string internedpath,int iskernelmodule,struct pmcstat_args * args,struct pmc_plugins * plugins)529 pmcstat_image_from_path(pmcstat_interned_string internedpath,
530 int iskernelmodule, struct pmcstat_args *args,
531 struct pmc_plugins *plugins)
532 {
533 int hash;
534 struct pmcstat_image *pi;
535
536 hash = pmcstat_string_lookup_hash(internedpath);
537
538 /* First, look for an existing entry. */
539 LIST_FOREACH(pi, &pmcstat_image_hash[hash], pi_next)
540 if (pi->pi_execpath == internedpath &&
541 pi->pi_iskernelmodule == iskernelmodule)
542 return (pi);
543
544 /*
545 * Allocate a new entry and place it at the head of the hash
546 * and LRU lists.
547 */
548 pi = malloc(sizeof(*pi));
549 if (pi == NULL)
550 return (NULL);
551
552 pi->pi_type = PMCSTAT_IMAGE_UNKNOWN;
553 pi->pi_execpath = internedpath;
554 pi->pi_start = ~0;
555 pi->pi_end = 0;
556 pi->pi_entry = 0;
557 pi->pi_vaddr = 0;
558 pi->pi_isdynamic = 0;
559 pi->pi_iskernelmodule = iskernelmodule;
560 pi->pi_dynlinkerpath = NULL;
561 pi->pi_symbols = NULL;
562 pi->pi_symcount = 0;
563 pi->pi_addr2line = NULL;
564
565 if (plugins[args->pa_pplugin].pl_initimage != NULL)
566 plugins[args->pa_pplugin].pl_initimage(pi);
567 if (plugins[args->pa_plugin].pl_initimage != NULL)
568 plugins[args->pa_plugin].pl_initimage(pi);
569
570 LIST_INSERT_HEAD(&pmcstat_image_hash[hash], pi, pi_next);
571
572 return (pi);
573 }
574