xref: /freebsd/lib/libpmcstat/libpmcstat_image.c (revision 069ac184)
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
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
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 	if ((pcmnew = malloc(sizeof(*pcmnew))) == NULL)
197 		err(EX_OSERR, "ERROR: Cannot create a map entry");
198 
199 	/*
200 	 * PowerPC kernel is of DYN type and it has a base address
201 	 * where it is initially loaded, before being relocated.
202 	 * As the address in 'start' is where the kernel was relocated to,
203 	 * but the symbols always use the original base address, we need to
204 	 * subtract it to get the correct offset.
205 	 */
206 #ifdef __powerpc__
207 	if (pp->pp_pid == -1) {
208 		kernbase = 0;
209 		kernbase_len = sizeof(kernbase);
210 		if (sysctlbyname("kern.base_address", &kernbase, &kernbase_len,
211 		    NULL, 0) == -1)
212 			warnx(
213 			    "WARNING: Could not retrieve kernel base address");
214 		else
215 			start -= kernbase;
216 	}
217 #endif
218 
219 	/*
220 	 * Adjust the map entry to only cover the text portion
221 	 * of the object.
222 	 */
223 
224 	offset = start - image->pi_vaddr;
225 	pcmnew->ppm_lowpc  = image->pi_start + offset;
226 	pcmnew->ppm_highpc = image->pi_end + offset;
227 	pcmnew->ppm_image  = image;
228 
229 	assert(pcmnew->ppm_lowpc < pcmnew->ppm_highpc);
230 
231 	/* Overlapped mmap()'s are assumed to never occur. */
232 	TAILQ_FOREACH(pcm, &pp->pp_map, ppm_next)
233 	    if (pcm->ppm_lowpc >= pcmnew->ppm_highpc)
234 		    break;
235 
236 	if (pcm == NULL)
237 		TAILQ_INSERT_TAIL(&pp->pp_map, pcmnew, ppm_next);
238 	else
239 		TAILQ_INSERT_BEFORE(pcm, pcmnew, ppm_next);
240 }
241 
242 /*
243  * Determine whether a given executable image is an A.OUT object, and
244  * if so, fill in its parameters from the text file.
245  * Sets image->pi_type.
246  */
247 
248 void
249 pmcstat_image_get_aout_params(struct pmcstat_image *image,
250     struct pmcstat_args *args)
251 {
252 	int fd;
253 	ssize_t nbytes;
254 	struct exec ex;
255 	const char *path;
256 	char buffer[PATH_MAX];
257 
258 	path = pmcstat_string_unintern(image->pi_execpath);
259 	assert(path != NULL);
260 
261 	if (image->pi_iskernelmodule)
262 		errx(EX_SOFTWARE,
263 		    "ERROR: a.out kernel modules are unsupported \"%s\"", path);
264 
265 	(void) snprintf(buffer, sizeof(buffer), "%s%s",
266 	    args->pa_fsroot, path);
267 
268 	if ((fd = open(buffer, O_RDONLY, 0)) < 0 ||
269 	    (nbytes = read(fd, &ex, sizeof(ex))) < 0) {
270 		if (args->pa_verbosity >= 2)
271 			warn("WARNING: Cannot determine type of \"%s\"",
272 			    path);
273 		image->pi_type = PMCSTAT_IMAGE_INDETERMINABLE;
274 		if (fd != -1)
275 			(void) close(fd);
276 		return;
277 	}
278 
279 	(void) close(fd);
280 
281 	if ((unsigned) nbytes != sizeof(ex) ||
282 	    N_BADMAG(ex))
283 		return;
284 
285 	image->pi_type = PMCSTAT_IMAGE_AOUT;
286 
287 	/* TODO: the rest of a.out processing */
288 
289 	return;
290 }
291 
292 /*
293  * Examine an ELF file to determine the size of its text segment.
294  * Sets image->pi_type if anything conclusive can be determined about
295  * this image.
296  */
297 
298 void
299 pmcstat_image_get_elf_params(struct pmcstat_image *image,
300     struct pmcstat_args *args)
301 {
302 	int fd;
303 	size_t i, nph, nsh;
304 	const char *path, *elfbase;
305 	char *p, *endp;
306 	bool first_exec_segment;
307 	uintfptr_t minva, maxva;
308 	Elf *e;
309 	Elf_Scn *scn;
310 	GElf_Ehdr eh;
311 	GElf_Phdr ph;
312 	GElf_Shdr sh;
313 	enum pmcstat_image_type image_type;
314 	char buffer[PATH_MAX];
315 
316 	assert(image->pi_type == PMCSTAT_IMAGE_UNKNOWN);
317 
318 	image->pi_start = minva = ~(uintfptr_t) 0;
319 	image->pi_end = maxva = (uintfptr_t) 0;
320 	image->pi_type = image_type = PMCSTAT_IMAGE_INDETERMINABLE;
321 	image->pi_isdynamic = 0;
322 	image->pi_dynlinkerpath = NULL;
323 	image->pi_vaddr = 0;
324 
325 	path = pmcstat_string_unintern(image->pi_execpath);
326 	assert(path != NULL);
327 
328 	/*
329 	 * Look for files under FSROOT/PATHNAME.
330 	 */
331 	(void) snprintf(buffer, sizeof(buffer), "%s%s",
332 	    args->pa_fsroot, path);
333 
334 	e = NULL;
335 	fd = open(buffer, O_RDONLY, 0);
336 	if (fd < 0) {
337 		warnx("WARNING: Cannot open \"%s\".",
338 		    buffer);
339 		goto done;
340 	}
341 
342 	if (elf_version(EV_CURRENT) == EV_NONE) {
343 		warnx("WARNING: failed to init elf\n");
344 		goto done;
345 	}
346 
347 	if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
348 		warnx("WARNING: Cannot read \"%s\".",
349 		    buffer);
350 		goto done;
351 	}
352 
353 	if (elf_kind(e) != ELF_K_ELF) {
354 		if (args->pa_verbosity >= 2)
355 			warnx("WARNING: Cannot determine the type of \"%s\".",
356 			    buffer);
357 		goto done;
358 	}
359 
360 	if (gelf_getehdr(e, &eh) != &eh) {
361 		warnx(
362 		    "WARNING: Cannot retrieve the ELF Header for \"%s\": %s.",
363 		    buffer, elf_errmsg(-1));
364 		goto done;
365 	}
366 
367 	if (eh.e_type != ET_EXEC && eh.e_type != ET_DYN &&
368 	    !(image->pi_iskernelmodule && eh.e_type == ET_REL)) {
369 		warnx("WARNING: \"%s\" is of an unsupported ELF type.",
370 		    buffer);
371 		goto done;
372 	}
373 
374 	image_type = eh.e_ident[EI_CLASS] == ELFCLASS32 ?
375 	    PMCSTAT_IMAGE_ELF32 : PMCSTAT_IMAGE_ELF64;
376 
377 	/*
378 	 * Determine the virtual address where an executable would be
379 	 * loaded.  Additionally, for dynamically linked executables,
380 	 * save the pathname to the runtime linker.
381 	 */
382 	if (eh.e_type != ET_REL) {
383 		if (elf_getphnum(e, &nph) == 0) {
384 			warnx(
385 "WARNING: Could not determine the number of program headers in \"%s\": %s.",
386 			    buffer,
387 			    elf_errmsg(-1));
388 			goto done;
389 		}
390 		first_exec_segment = true;
391 		for (i = 0; i < eh.e_phnum; i++) {
392 			if (gelf_getphdr(e, i, &ph) != &ph) {
393 				warnx(
394 "WARNING: Retrieval of PHDR entry #%ju in \"%s\" failed: %s.",
395 				    (uintmax_t) i, buffer, elf_errmsg(-1));
396 				goto done;
397 			}
398 			switch (ph.p_type) {
399 			case PT_DYNAMIC:
400 				image->pi_isdynamic = 1;
401 				break;
402 			case PT_INTERP:
403 				if ((elfbase = elf_rawfile(e, NULL)) == NULL) {
404 					warnx(
405 "WARNING: Cannot retrieve the interpreter for \"%s\": %s.",
406 					    buffer, elf_errmsg(-1));
407 					goto done;
408 				}
409 				image->pi_dynlinkerpath =
410 				    pmcstat_string_intern(elfbase +
411 				        ph.p_offset);
412 				break;
413 			case PT_LOAD:
414 				if ((ph.p_flags & PF_X) != 0 &&
415 				    first_exec_segment) {
416 					image->pi_vaddr = ph.p_vaddr & (-ph.p_align);
417 					first_exec_segment = false;
418 				}
419 				break;
420 			}
421 		}
422 	}
423 
424 	/*
425 	 * Get the min and max VA associated with this ELF object.
426 	 */
427 	if (elf_getshnum(e, &nsh) == 0) {
428 		warnx(
429 "WARNING: Could not determine the number of sections for \"%s\": %s.",
430 		    buffer, elf_errmsg(-1));
431 		goto done;
432 	}
433 
434 	for (i = 0; i < nsh; i++) {
435 		if ((scn = elf_getscn(e, i)) == NULL ||
436 		    gelf_getshdr(scn, &sh) != &sh) {
437 			warnx(
438 "WARNING: Could not retrieve section header #%ju in \"%s\": %s.",
439 			    (uintmax_t) i, buffer, elf_errmsg(-1));
440 			goto done;
441 		}
442 		if (sh.sh_flags & SHF_EXECINSTR) {
443 			minva = min(minva, sh.sh_addr);
444 			maxva = max(maxva, sh.sh_addr + sh.sh_size);
445 		}
446 		if (sh.sh_type == SHT_SYMTAB || sh.sh_type == SHT_DYNSYM)
447 			pmcstat_image_add_symbols(image, e, scn, &sh);
448 	}
449 
450 	image->pi_start = minva;
451 	image->pi_end   = maxva;
452 	image->pi_type  = image_type;
453 	image->pi_fullpath = pmcstat_string_intern(buffer);
454 
455 	/* Build display name
456 	 */
457 	endp = buffer;
458 	for (p = buffer; *p; p++)
459 		if (*p == '/')
460 			endp = p+1;
461 	image->pi_name = pmcstat_string_intern(endp);
462 
463  done:
464 	(void) elf_end(e);
465 	if (fd >= 0)
466 		(void) close(fd);
467 	return;
468 }
469 
470 /*
471  * Given an image descriptor, determine whether it is an ELF, or AOUT.
472  * If no handler claims the image, set its type to 'INDETERMINABLE'.
473  */
474 
475 void
476 pmcstat_image_determine_type(struct pmcstat_image *image,
477     struct pmcstat_args *args)
478 {
479 	assert(image->pi_type == PMCSTAT_IMAGE_UNKNOWN);
480 
481 	/* Try each kind of handler in turn */
482 	if (image->pi_type == PMCSTAT_IMAGE_UNKNOWN)
483 		pmcstat_image_get_elf_params(image, args);
484 	if (image->pi_type == PMCSTAT_IMAGE_UNKNOWN)
485 		pmcstat_image_get_aout_params(image, args);
486 
487 	/*
488 	 * Otherwise, remember that we tried to determine
489 	 * the object's type and had failed.
490 	 */
491 	if (image->pi_type == PMCSTAT_IMAGE_UNKNOWN)
492 		image->pi_type = PMCSTAT_IMAGE_INDETERMINABLE;
493 }
494 
495 /*
496  * Locate an image descriptor given an interned path, adding a fresh
497  * descriptor to the cache if necessary.  This function also finds a
498  * suitable name for this image's sample file.
499  *
500  * We defer filling in the file format specific parts of the image
501  * structure till the time we actually see a sample that would fall
502  * into this image.
503  */
504 
505 struct pmcstat_image *
506 pmcstat_image_from_path(pmcstat_interned_string internedpath,
507     int iskernelmodule, struct pmcstat_args *args,
508     struct pmc_plugins *plugins)
509 {
510 	int hash;
511 	struct pmcstat_image *pi;
512 
513 	hash = pmcstat_string_lookup_hash(internedpath);
514 
515 	/* First, look for an existing entry. */
516 	LIST_FOREACH(pi, &pmcstat_image_hash[hash], pi_next)
517 	    if (pi->pi_execpath == internedpath &&
518 		  pi->pi_iskernelmodule == iskernelmodule)
519 		    return (pi);
520 
521 	/*
522 	 * Allocate a new entry and place it at the head of the hash
523 	 * and LRU lists.
524 	 */
525 	pi = malloc(sizeof(*pi));
526 	if (pi == NULL)
527 		return (NULL);
528 
529 	pi->pi_type = PMCSTAT_IMAGE_UNKNOWN;
530 	pi->pi_execpath = internedpath;
531 	pi->pi_start = ~0;
532 	pi->pi_end = 0;
533 	pi->pi_entry = 0;
534 	pi->pi_vaddr = 0;
535 	pi->pi_isdynamic = 0;
536 	pi->pi_iskernelmodule = iskernelmodule;
537 	pi->pi_dynlinkerpath = NULL;
538 	pi->pi_symbols = NULL;
539 	pi->pi_symcount = 0;
540 	pi->pi_addr2line = NULL;
541 
542 	if (plugins[args->pa_pplugin].pl_initimage != NULL)
543 		plugins[args->pa_pplugin].pl_initimage(pi);
544 	if (plugins[args->pa_plugin].pl_initimage != NULL)
545 		plugins[args->pa_plugin].pl_initimage(pi);
546 
547 	LIST_INSERT_HEAD(&pmcstat_image_hash[hash], pi, pi_next);
548 
549 	return (pi);
550 }
551