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