pmcstat_log.c revision 185322
1193323Sed/*-
2193323Sed * Copyright (c) 2005-2007, Joseph Koshy
3193323Sed * Copyright (c) 2007 The FreeBSD Foundation
4193323Sed * All rights reserved.
5193323Sed *
6193323Sed * Portions of this software were developed by A. Joseph Koshy under
7193323Sed * sponsorship from the FreeBSD Foundation and Google, Inc.
8193323Sed *
9193323Sed * Redistribution and use in source and binary forms, with or without
10193323Sed * modification, are permitted provided that the following conditions
11193323Sed * are met:
12193323Sed * 1. Redistributions of source code must retain the above copyright
13193323Sed *    notice, this list of conditions and the following disclaimer.
14193323Sed * 2. Redistributions in binary form must reproduce the above copyright
15193323Sed *    notice, this list of conditions and the following disclaimer in the
16193323Sed *    documentation and/or other materials provided with the distribution.
17193323Sed *
18252723Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19252723Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20252723Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21245431Sdim * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22245431Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23193323Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24193323Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25193323Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26193323Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27221345Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28195340Sed * SUCH DAMAGE.
29193323Sed */
30221345Sdim
31221345Sdim/*
32221345Sdim * Transform a hwpmc(4) log into human readable form, and into
33193323Sed * gprof(1) compatible profiles.
34193323Sed */
35193323Sed
36193323Sed#include <sys/cdefs.h>
37193323Sed__FBSDID("$FreeBSD: head/usr.sbin/pmcstat/pmcstat_log.c 185322 2008-11-25 23:24:29Z attilio $");
38245431Sdim
39245431Sdim#include <sys/param.h>
40245431Sdim#include <sys/endian.h>
41221345Sdim#include <sys/gmon.h>
42263509Sdim#include <sys/imgact_aout.h>
43193323Sed#include <sys/imgact_elf.h>
44193323Sed#include <sys/mman.h>
45263509Sdim#include <sys/pmc.h>
46193323Sed#include <sys/queue.h>
47193323Sed#include <sys/socket.h>
48193323Sed#include <sys/stat.h>
49193323Sed#include <sys/wait.h>
50193323Sed
51193323Sed#include <netinet/in.h>
52193323Sed
53193323Sed#include <assert.h>
54223017Sdim#include <err.h>
55223017Sdim#include <errno.h>
56223017Sdim#include <fcntl.h>
57245431Sdim#include <gelf.h>
58245431Sdim#include <libgen.h>
59193323Sed#include <limits.h>
60193323Sed#include <netdb.h>
61193323Sed#include <pmc.h>
62193323Sed#include <pmclog.h>
63193323Sed#include <sysexits.h>
64193323Sed#include <stdint.h>
65193323Sed#include <stdio.h>
66193323Sed#include <stdlib.h>
67245431Sdim#include <string.h>
68193323Sed#include <unistd.h>
69193323Sed
70193323Sed#include "pmcstat.h"
71202375Srdivacky
72202375Srdivacky#define	min(A,B)		((A) < (B) ? (A) : (B))
73245431Sdim#define	max(A,B)		((A) > (B) ? (A) : (B))
74245431Sdim
75193323Sed#define	PMCSTAT_ALLOCATE		1
76193323Sed
77193323Sed/*
78193323Sed * PUBLIC INTERFACES
79193323Sed *
80219077Sdim * pmcstat_initialize_logging()	initialize this module, called first
81245431Sdim * pmcstat_shutdown_logging()		orderly shutdown, called last
82193323Sed * pmcstat_open_log()			open an eventlog for processing
83263509Sdim * pmcstat_process_log()		print/convert an event log
84202375Srdivacky * pmcstat_close_log()			finish processing an event log
85202375Srdivacky *
86202375Srdivacky * IMPLEMENTATION NOTES
87202375Srdivacky *
88202375Srdivacky * We correlate each 'callchain' or 'sample' entry seen in the event
89245431Sdim * log back to an executable object in the system. Executable objects
90245431Sdim * include:
91263509Sdim * 	- program executables,
92193323Sed *	- shared libraries loaded by the runtime loader,
93193323Sed *	- dlopen()'ed objects loaded by the program,
94193323Sed *	- the runtime loader itself,
95193323Sed *	- the kernel and kernel modules.
96199481Srdivacky *
97199481Srdivacky * Each process that we know about is treated as a set of regions that
98199481Srdivacky * map to executable objects.  Processes are described by
99199481Srdivacky * 'pmcstat_process' structures.  Executable objects are tracked by
100199481Srdivacky * 'pmcstat_image' structures.  The kernel and kernel modules are
101199481Srdivacky * common to all processes (they reside at the same virtual addresses
102199481Srdivacky * for all processes).  Individual processes can have their text
103199481Srdivacky * segments and shared libraries loaded at process-specific locations.
104199481Srdivacky *
105199481Srdivacky * A given executable object can be in use by multiple processes
106199481Srdivacky * (e.g., libc.so) and loaded at a different address in each.
107199481Srdivacky * pmcstat_pcmap structures track per-image mappings.
108245431Sdim *
109263509Sdim * The sample log could have samples from multiple PMCs; we
110263509Sdim * generate one 'gmon.out' profile per PMC.
111193323Sed *
112193323Sed * IMPLEMENTATION OF GMON OUTPUT
113193323Sed *
114193323Sed * Each executable object gets one 'gmon.out' profile, per PMC in
115193323Sed * use.  Creation of 'gmon.out' profiles is done lazily.  The
116198090Srdivacky * 'gmon.out' profiles generated for a given sampling PMC are
117199481Srdivacky * aggregates of all the samples for that particular executable
118263509Sdim * object.
119199481Srdivacky *
120199481Srdivacky * IMPLEMENTATION OF SYSTEM-WIDE CALLGRAPH OUTPUT
121199481Srdivacky *
122199481Srdivacky * Each active pmcid has its own callgraph structure, described by a
123199481Srdivacky * 'struct pmcstat_callgraph'.  Given a process id and a list of pc
124199481Srdivacky * values, we map each pc value to a tuple (image, symbol), where
125199511Srdivacky * 'image' denotes an executable object and 'symbol' is the closest
126199511Srdivacky * symbol that precedes the pc value.  Each pc value in the list is
127199511Srdivacky * also given a 'rank' that reflects its depth in the call stack.
128199511Srdivacky */
129199511Srdivacky
130199511Srdivackytypedef const void *pmcstat_interned_string;
131199511Srdivacky
132199511Srdivacky/*
133193323Sed * 'pmcstat_pmcrecord' is a mapping from PMC ids to human-readable
134193323Sed * names.
135193323Sed */
136193323Sed
137193323Sedstruct pmcstat_pmcrecord {
138193323Sed	LIST_ENTRY(pmcstat_pmcrecord)	pr_next;
139252723Sdim	pmc_id_t			pr_pmcid;
140252723Sdim	pmcstat_interned_string	pr_pmcname;
141193323Sed};
142263509Sdim
143263509Sdimstatic LIST_HEAD(,pmcstat_pmcrecord)	pmcstat_pmcs =
144263509Sdim	LIST_HEAD_INITIALIZER(&pmcstat_pmcs);
145263509Sdim
146263509Sdim
147263509Sdim/*
148195340Sed * struct pmcstat_gmonfile tracks a given 'gmon.out' file.  These
149195340Sed * files are mmap()'ed in as needed.
150195340Sed */
151195340Sed
152195340Sedstruct pmcstat_gmonfile {
153195340Sed	LIST_ENTRY(pmcstat_gmonfile)	pgf_next; /* list of entries */
154193323Sed	int		pgf_overflow;	/* whether a count overflowed */
155193323Sed	pmc_id_t	pgf_pmcid;	/* id of the associated pmc */
156193323Sed	size_t		pgf_nbuckets;	/* #buckets in this gmon.out */
157193323Sed	unsigned int	pgf_nsamples;	/* #samples in this gmon.out */
158193323Sed	pmcstat_interned_string pgf_name;	/* pathname of gmon.out file */
159193323Sed	size_t		pgf_ndatabytes;	/* number of bytes mapped */
160198090Srdivacky	void		*pgf_gmondata;	/* pointer to mmap'ed data */
161198090Srdivacky	FILE		*pgf_file;	/* used when writing gmon arcs */
162193323Sed};
163193323Sed
164193323Sed/*
165193323Sed * A 'pmcstat_image' structure describes an executable program on
166263509Sdim * disk.  'pi_execpath' is a cookie representing the pathname of
167193323Sed * the executable.  'pi_start' and 'pi_end' are the least and greatest
168193323Sed * virtual addresses for the text segments in the executable.
169218893Sdim * 'pi_gmonlist' contains a linked list of gmon.out files associated
170218893Sdim * with this image.
171218893Sdim */
172218893Sdim
173218893Sdimenum pmcstat_image_type {
174245431Sdim	PMCSTAT_IMAGE_UNKNOWN = 0,	/* never looked at the image */
175218893Sdim	PMCSTAT_IMAGE_INDETERMINABLE,	/* can't tell what the image is */
176218893Sdim	PMCSTAT_IMAGE_ELF32,		/* ELF 32 bit object */
177245431Sdim	PMCSTAT_IMAGE_ELF64,		/* ELF 64 bit object */
178218893Sdim	PMCSTAT_IMAGE_AOUT		/* AOUT object */
179218893Sdim};
180218893Sdim
181245431Sdimstruct pmcstat_image {
182245431Sdim	LIST_ENTRY(pmcstat_image) pi_next;	/* hash link */
183245431Sdim	TAILQ_ENTRY(pmcstat_image) pi_lru;	/* LRU list */
184245431Sdim	pmcstat_interned_string	pi_execpath;    /* cookie */
185245431Sdim	pmcstat_interned_string pi_samplename;  /* sample path name */
186245431Sdim	pmcstat_interned_string pi_fullpath;    /* path to FS object */
187245431Sdim
188245431Sdim	enum pmcstat_image_type pi_type;	/* executable type */
189263509Sdim
190263509Sdim	/*
191245431Sdim	 * Executables have pi_start and pi_end; these are zero
192245431Sdim	 * for shared libraries.
193245431Sdim	 */
194245431Sdim	uintfptr_t	pi_start;	/* start address (inclusive) */
195263509Sdim	uintfptr_t	pi_end;		/* end address (exclusive) */
196245431Sdim	uintfptr_t	pi_entry;	/* entry address */
197245431Sdim	uintfptr_t	pi_vaddr;	/* virtual address where loaded */
198263509Sdim	int		pi_isdynamic;	/* whether a dynamic object */
199263509Sdim	int		pi_iskernelmodule;
200245431Sdim	pmcstat_interned_string pi_dynlinkerpath; /* path in .interp */
201263509Sdim
202245431Sdim	/* All symbols associated with this object. */
203245431Sdim	struct pmcstat_symbol *pi_symbols;
204245431Sdim	size_t		pi_symcount;
205245431Sdim
206263509Sdim	/*
207263509Sdim	 * An image can be associated with one or more gmon.out files;
208263509Sdim	 * one per PMC.
209245431Sdim	 */
210245431Sdim	LIST_HEAD(,pmcstat_gmonfile) pi_gmlist;
211245431Sdim};
212263509Sdim
213263509Sdim/*
214245431Sdim * All image descriptors are kept in a hash table.
215263509Sdim */
216263509Sdimstatic LIST_HEAD(,pmcstat_image)	pmcstat_image_hash[PMCSTAT_NHASH];
217263509Sdim
218245431Sdim/*
219245431Sdim * A 'pmcstat_pcmap' structure maps a virtual address range to an
220245431Sdim * underlying 'pmcstat_image' descriptor.
221245431Sdim */
222245431Sdimstruct pmcstat_pcmap {
223245431Sdim	TAILQ_ENTRY(pmcstat_pcmap) ppm_next;
224245431Sdim	uintfptr_t	ppm_lowpc;
225245431Sdim	uintfptr_t	ppm_highpc;
226245431Sdim	struct pmcstat_image *ppm_image;
227245431Sdim};
228245431Sdim
229245431Sdim/*
230245431Sdim * A 'pmcstat_process' structure models processes.  Each process is
231245431Sdim * associated with a set of pmcstat_pcmap structures that map
232245431Sdim * addresses inside it to executable objects.  This set is implemented
233245431Sdim * as a list, kept sorted in ascending order of mapped addresses.
234245431Sdim *
235245431Sdim * 'pp_pid' holds the pid of the process.  When a process exits, the
236245431Sdim * 'pp_isactive' field is set to zero, but the process structure is
237245431Sdim * not immediately reclaimed because there may still be samples in the
238245431Sdim * log for this process.
239245431Sdim */
240245431Sdim
241245431Sdimstruct pmcstat_process {
242245431Sdim	LIST_ENTRY(pmcstat_process) pp_next;	/* hash-next */
243245431Sdim	pid_t			pp_pid;		/* associated pid */
244245431Sdim	int			pp_isactive;	/* whether active */
245245431Sdim	uintfptr_t		pp_entryaddr;	/* entry address */
246221345Sdim	TAILQ_HEAD(,pmcstat_pcmap) pp_map;	/* address range map */
247221345Sdim};
248221345Sdim
249221345Sdim/*
250252723Sdim * All process descriptors are kept in a hash table.
251221345Sdim */
252221345Sdimstatic LIST_HEAD(,pmcstat_process) pmcstat_process_hash[PMCSTAT_NHASH];
253221345Sdim
254221345Sdimstatic struct pmcstat_process *pmcstat_kernproc; /* kernel 'process' */
255252723Sdim
256221345Sdim/*
257221345Sdim * Each function symbol tracked by pmcstat(8).
258221345Sdim */
259221345Sdim
260221345Sdimstruct pmcstat_symbol {
261221345Sdim	pmcstat_interned_string ps_name;
262221345Sdim	uint64_t	ps_start;
263221345Sdim	uint64_t	ps_end;
264223017Sdim};
265223017Sdim
266223017Sdim/*
267223017Sdim * Each call graph node is tracked by a pmcstat_cgnode struct.
268252723Sdim */
269252723Sdim
270252723Sdimstruct pmcstat_cgnode {
271252723Sdim	struct pmcstat_image	*pcg_image;
272252723Sdim	uintfptr_t		pcg_func;
273252723Sdim	uint32_t		pcg_count;
274252723Sdim	uint32_t		pcg_nchildren;
275252723Sdim	LIST_ENTRY(pmcstat_cgnode) pcg_sibling;
276252723Sdim	LIST_HEAD(,pmcstat_cgnode) pcg_children;
277252723Sdim};
278193323Sed
279193323Sedstruct pmcstat_cgnode_hash {
280193323Sed	struct pmcstat_cgnode  *pch_cgnode;
281	uint32_t		pch_pmcid;
282	LIST_ENTRY(pmcstat_cgnode_hash) pch_next;
283};
284
285static int pmcstat_cgnode_hash_count;
286static pmcstat_interned_string pmcstat_previous_filename_printed;
287
288/*
289 * The toplevel CG nodes (i.e., with rank == 0) are placed in a hash table.
290 */
291
292static LIST_HEAD(,pmcstat_cgnode_hash) pmcstat_cgnode_hash[PMCSTAT_NHASH];
293
294/* Misc. statistics */
295static struct pmcstat_stats {
296	int ps_exec_aout;	/* # a.out executables seen */
297	int ps_exec_elf;	/* # elf executables seen */
298	int ps_exec_errors;	/* # errors processing executables */
299	int ps_exec_indeterminable; /* # unknown executables seen */
300	int ps_samples_total;	/* total number of samples processed */
301	int ps_samples_skipped; /* #samples filtered out for any reason */
302	int ps_samples_unknown_offset;	/* #samples of rank 0 not in a map */
303	int ps_samples_indeterminable;	/* #samples in indeterminable images */
304	int ps_callchain_dubious_frames;/* #dubious frame pointers seen */
305} pmcstat_stats;
306
307
308/*
309 * Prototypes
310 */
311
312static void	pmcstat_gmon_create_file(struct pmcstat_gmonfile *_pgf,
313    struct pmcstat_image *_image);
314static pmcstat_interned_string pmcstat_gmon_create_name(const char *_sd,
315    struct pmcstat_image *_img, pmc_id_t _pmcid);
316static void	pmcstat_gmon_map_file(struct pmcstat_gmonfile *_pgf);
317static void	pmcstat_gmon_unmap_file(struct pmcstat_gmonfile *_pgf);
318
319static void pmcstat_image_determine_type(struct pmcstat_image *_image,
320    struct pmcstat_args *_a);
321static struct pmcstat_gmonfile *pmcstat_image_find_gmonfile(struct
322    pmcstat_image *_i, pmc_id_t _id);
323static struct pmcstat_image *pmcstat_image_from_path(pmcstat_interned_string
324    _path, int _iskernelmodule);
325static void pmcstat_image_get_aout_params(struct pmcstat_image *_image,
326    struct pmcstat_args *_a);
327static void pmcstat_image_get_elf_params(struct pmcstat_image *_image,
328    struct pmcstat_args *_a);
329static void	pmcstat_image_increment_bucket(struct pmcstat_pcmap *_pcm,
330    uintfptr_t _pc, pmc_id_t _pmcid, struct pmcstat_args *_a);
331static void	pmcstat_image_link(struct pmcstat_process *_pp,
332    struct pmcstat_image *_i, uintfptr_t _lpc);
333
334static void	pmcstat_pmcid_add(pmc_id_t _pmcid,
335    pmcstat_interned_string _name, struct pmcstat_args *_a);
336static const char *pmcstat_pmcid_to_name(pmc_id_t _pmcid);
337
338static void	pmcstat_process_aout_exec(struct pmcstat_process *_pp,
339    struct pmcstat_image *_image, uintfptr_t _entryaddr,
340    struct pmcstat_args *_a);
341static void	pmcstat_process_elf_exec(struct pmcstat_process *_pp,
342    struct pmcstat_image *_image, uintfptr_t _entryaddr,
343    struct pmcstat_args *_a);
344static void	pmcstat_process_exec(struct pmcstat_process *_pp,
345    pmcstat_interned_string _path, uintfptr_t _entryaddr,
346    struct pmcstat_args *_ao);
347static struct pmcstat_process *pmcstat_process_lookup(pid_t _pid,
348    int _allocate);
349static struct pmcstat_pcmap *pmcstat_process_find_map(
350    struct pmcstat_process *_p, uintfptr_t _pc);
351
352static int	pmcstat_string_compute_hash(const char *_string);
353static void pmcstat_string_initialize(void);
354static pmcstat_interned_string pmcstat_string_intern(const char *_s);
355static pmcstat_interned_string pmcstat_string_lookup(const char *_s);
356static int	pmcstat_string_lookup_hash(pmcstat_interned_string _is);
357static void pmcstat_string_shutdown(void);
358static const char *pmcstat_string_unintern(pmcstat_interned_string _is);
359
360
361/*
362 * A simple implementation of interned strings.  Each interned string
363 * is assigned a unique address, so that subsequent string compares
364 * can be done by a simple pointer comparision instead of using
365 * strcmp().  This speeds up hash table lookups and saves memory if
366 * duplicate strings are the norm.
367 */
368struct pmcstat_string {
369	LIST_ENTRY(pmcstat_string)	ps_next;	/* hash link */
370	int		ps_len;
371	int		ps_hash;
372	char		*ps_string;
373};
374
375static LIST_HEAD(,pmcstat_string)	pmcstat_string_hash[PMCSTAT_NHASH];
376
377/*
378 * Compute a 'hash' value for a string.
379 */
380
381static int
382pmcstat_string_compute_hash(const char *s)
383{
384	int hash;
385
386	for (hash = 0; *s; s++)
387		hash ^= *s;
388
389	return (hash & PMCSTAT_HASH_MASK);
390}
391
392/*
393 * Intern a copy of string 's', and return a pointer to the
394 * interned structure.
395 */
396
397static pmcstat_interned_string
398pmcstat_string_intern(const char *s)
399{
400	struct pmcstat_string *ps;
401	const struct pmcstat_string *cps;
402	int hash, len;
403
404	if ((cps = pmcstat_string_lookup(s)) != NULL)
405		return (cps);
406
407	hash = pmcstat_string_compute_hash(s);
408	len  = strlen(s);
409
410	if ((ps = malloc(sizeof(*ps))) == NULL)
411		err(EX_OSERR, "ERROR: Could not intern string");
412	ps->ps_len = len;
413	ps->ps_hash = hash;
414	ps->ps_string = strdup(s);
415	LIST_INSERT_HEAD(&pmcstat_string_hash[hash], ps, ps_next);
416	return ((pmcstat_interned_string) ps);
417}
418
419static const char *
420pmcstat_string_unintern(pmcstat_interned_string str)
421{
422	const char *s;
423
424	s = ((const struct pmcstat_string *) str)->ps_string;
425	return (s);
426}
427
428static pmcstat_interned_string
429pmcstat_string_lookup(const char *s)
430{
431	struct pmcstat_string *ps;
432	int hash, len;
433
434	hash = pmcstat_string_compute_hash(s);
435	len = strlen(s);
436
437	LIST_FOREACH(ps, &pmcstat_string_hash[hash], ps_next)
438	    if (ps->ps_len == len && ps->ps_hash == hash &&
439		strcmp(ps->ps_string, s) == 0)
440		    return (ps);
441	return (NULL);
442}
443
444static int
445pmcstat_string_lookup_hash(pmcstat_interned_string s)
446{
447	const struct pmcstat_string *ps;
448
449	ps = (const struct pmcstat_string *) s;
450	return (ps->ps_hash);
451}
452
453/*
454 * Initialize the string interning facility.
455 */
456
457static void
458pmcstat_string_initialize(void)
459{
460	int i;
461
462	for (i = 0; i < PMCSTAT_NHASH; i++)
463		LIST_INIT(&pmcstat_string_hash[i]);
464}
465
466/*
467 * Destroy the string table, free'ing up space.
468 */
469
470static void
471pmcstat_string_shutdown(void)
472{
473	int i;
474	struct pmcstat_string *ps, *pstmp;
475
476	for (i = 0; i < PMCSTAT_NHASH; i++)
477		LIST_FOREACH_SAFE(ps, &pmcstat_string_hash[i], ps_next,
478		    pstmp) {
479			LIST_REMOVE(ps, ps_next);
480			free(ps->ps_string);
481			free(ps);
482		}
483}
484
485/*
486 * Create a gmon.out file and size it.
487 */
488
489static void
490pmcstat_gmon_create_file(struct pmcstat_gmonfile *pgf,
491    struct pmcstat_image *image)
492{
493	int fd;
494	size_t count;
495	struct gmonhdr gm;
496	const char *pathname;
497	char buffer[DEFAULT_BUFFER_SIZE];
498
499	pathname = pmcstat_string_unintern(pgf->pgf_name);
500	if ((fd = open(pathname, O_RDWR|O_NOFOLLOW|O_CREAT,
501		 S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
502		err(EX_OSERR, "ERROR: Cannot open \"%s\"", pathname);
503
504	gm.lpc = image->pi_start;
505	gm.hpc = image->pi_end;
506	gm.ncnt = (pgf->pgf_nbuckets * sizeof(HISTCOUNTER)) +
507	    sizeof(struct gmonhdr);
508	gm.version = GMONVERSION;
509	gm.profrate = 0;		/* use ticks */
510	gm.histcounter_type = 0;	/* compatibility with moncontrol() */
511	gm.spare[0] = gm.spare[1] = 0;
512
513	/* Write out the gmon header */
514	if (write(fd, &gm, sizeof(gm)) < 0)
515		goto error;
516
517	/* Zero fill the samples[] array */
518	(void) memset(buffer, 0, sizeof(buffer));
519
520	count = pgf->pgf_ndatabytes - sizeof(struct gmonhdr);
521	while (count > sizeof(buffer)) {
522		if (write(fd, &buffer, sizeof(buffer)) < 0)
523			goto error;
524		count -= sizeof(buffer);
525	}
526
527	if (write(fd, &buffer, count) < 0)
528		goto error;
529
530	(void) close(fd);
531
532	return;
533
534 error:
535	err(EX_OSERR, "ERROR: Cannot write \"%s\"", pathname);
536}
537
538/*
539 * Determine the full pathname of a gmon.out file for a given
540 * (image,pmcid) combination.  Return the interned string.
541 */
542
543pmcstat_interned_string
544pmcstat_gmon_create_name(const char *samplesdir, struct pmcstat_image *image,
545    pmc_id_t pmcid)
546{
547	const char *pmcname;
548	char fullpath[PATH_MAX];
549
550	pmcname = pmcstat_pmcid_to_name(pmcid);
551
552	(void) snprintf(fullpath, sizeof(fullpath),
553	    "%s/%s/%s", samplesdir, pmcname,
554	    pmcstat_string_unintern(image->pi_samplename));
555
556	return (pmcstat_string_intern(fullpath));
557}
558
559
560/*
561 * Mmap in a gmon.out file for processing.
562 */
563
564static void
565pmcstat_gmon_map_file(struct pmcstat_gmonfile *pgf)
566{
567	int fd;
568	const char *pathname;
569
570	pathname = pmcstat_string_unintern(pgf->pgf_name);
571
572	/* the gmon.out file must already exist */
573	if ((fd = open(pathname, O_RDWR | O_NOFOLLOW, 0)) < 0)
574		err(EX_OSERR, "ERROR: cannot open \"%s\"", pathname);
575
576	pgf->pgf_gmondata = mmap(NULL, pgf->pgf_ndatabytes,
577	    PROT_READ|PROT_WRITE, MAP_NOSYNC|MAP_SHARED, fd, 0);
578
579	if (pgf->pgf_gmondata == MAP_FAILED)
580		err(EX_OSERR, "ERROR: cannot map \"%s\"", pathname);
581
582	(void) close(fd);
583}
584
585/*
586 * Unmap a gmon.out file after sync'ing its data to disk.
587 */
588
589static void
590pmcstat_gmon_unmap_file(struct pmcstat_gmonfile *pgf)
591{
592	(void) msync(pgf->pgf_gmondata, pgf->pgf_ndatabytes,
593	    MS_SYNC);
594	(void) munmap(pgf->pgf_gmondata, pgf->pgf_ndatabytes);
595	pgf->pgf_gmondata = NULL;
596}
597
598static void
599pmcstat_gmon_append_arc(struct pmcstat_image *image, pmc_id_t pmcid,
600    uintptr_t rawfrom, uintptr_t rawto, uint32_t count)
601{
602	struct rawarc arc;	/* from <sys/gmon.h> */
603	const char *pathname;
604	struct pmcstat_gmonfile *pgf;
605
606	if ((pgf = pmcstat_image_find_gmonfile(image, pmcid)) == NULL)
607		return;
608
609	if (pgf->pgf_file == NULL) {
610		pathname = pmcstat_string_unintern(pgf->pgf_name);
611		if ((pgf->pgf_file = fopen(pathname, "a")) == NULL)
612			return;
613	}
614
615	arc.raw_frompc = rawfrom + image->pi_vaddr;
616	arc.raw_selfpc = rawto + image->pi_vaddr;
617	arc.raw_count = count;
618
619	(void) fwrite(&arc, sizeof(arc), 1, pgf->pgf_file);
620
621}
622
623static struct pmcstat_gmonfile *
624pmcstat_image_find_gmonfile(struct pmcstat_image *image, pmc_id_t pmcid)
625{
626	struct pmcstat_gmonfile *pgf;
627	LIST_FOREACH(pgf, &image->pi_gmlist, pgf_next)
628	    if (pgf->pgf_pmcid == pmcid)
629		    return (pgf);
630	return (NULL);
631}
632
633
634/*
635 * Determine whether a given executable image is an A.OUT object, and
636 * if so, fill in its parameters from the text file.
637 * Sets image->pi_type.
638 */
639
640static void
641pmcstat_image_get_aout_params(struct pmcstat_image *image,
642    struct pmcstat_args *a)
643{
644	int fd;
645	ssize_t nbytes;
646	struct exec ex;
647	const char *path;
648	char buffer[PATH_MAX];
649
650	path = pmcstat_string_unintern(image->pi_execpath);
651	assert(path != NULL);
652
653	if (image->pi_iskernelmodule)
654		errx(EX_SOFTWARE, "ERROR: a.out kernel modules are "
655		    "unsupported \"%s\"", path);
656
657	(void) snprintf(buffer, sizeof(buffer), "%s%s",
658	    a->pa_fsroot, path);
659
660	if ((fd = open(buffer, O_RDONLY, 0)) < 0 ||
661	    (nbytes = read(fd, &ex, sizeof(ex))) < 0) {
662		warn("WARNING: Cannot determine type of \"%s\"", path);
663		image->pi_type = PMCSTAT_IMAGE_INDETERMINABLE;
664		if (fd != -1)
665			(void) close(fd);
666		return;
667	}
668
669	(void) close(fd);
670
671	if ((unsigned) nbytes != sizeof(ex) ||
672	    N_BADMAG(ex))
673		return;
674
675	image->pi_type = PMCSTAT_IMAGE_AOUT;
676
677	/* TODO: the rest of a.out processing */
678
679	return;
680}
681
682/*
683 * Helper function.
684 */
685
686static int
687pmcstat_symbol_compare(const void *a, const void *b)
688{
689	const struct pmcstat_symbol *sym1, *sym2;
690
691	sym1 = (const struct pmcstat_symbol *) a;
692	sym2 = (const struct pmcstat_symbol *) b;
693
694	if (sym1->ps_end <= sym2->ps_start)
695		return (-1);
696	if (sym1->ps_start >= sym2->ps_end)
697		return (1);
698	return (0);
699}
700
701/*
702 * Map an address to a symbol in an image.
703 */
704
705static struct pmcstat_symbol *
706pmcstat_symbol_search(struct pmcstat_image *image, uintfptr_t addr)
707{
708	struct pmcstat_symbol sym;
709
710	if (image->pi_symbols == NULL)
711		return (NULL);
712
713	sym.ps_name  = NULL;
714	sym.ps_start = addr;
715	sym.ps_end   = addr + 1;
716
717	return (bsearch((void *) &sym, image->pi_symbols,
718		    image->pi_symcount, sizeof(struct pmcstat_symbol),
719		    pmcstat_symbol_compare));
720}
721
722/*
723 * Add the list of symbols in the given section to the list associated
724 * with the object.
725 */
726static void
727pmcstat_image_add_symbols(struct pmcstat_image *image, Elf *e,
728    Elf_Scn *scn, GElf_Shdr *sh)
729{
730	int firsttime;
731	size_t n, newsyms, nshsyms, nfuncsyms;
732	struct pmcstat_symbol *symptr;
733	char *fnname;
734	GElf_Sym sym;
735	Elf_Data *data;
736
737	if ((data = elf_getdata(scn, NULL)) == NULL)
738		return;
739
740	/*
741	 * Determine the number of functions named in this
742	 * section.
743	 */
744
745	nshsyms = sh->sh_size / sh->sh_entsize;
746	for (n = nfuncsyms = 0; n < nshsyms; n++) {
747		if (gelf_getsym(data, (int) n, &sym) != &sym)
748			return;
749		if (GELF_ST_TYPE(sym.st_info) == STT_FUNC)
750			nfuncsyms++;
751	}
752
753	if (nfuncsyms == 0)
754		return;
755
756	/*
757	 * Allocate space for the new entries.
758	 */
759	firsttime = image->pi_symbols == NULL;
760	symptr = realloc(image->pi_symbols,
761	    sizeof(*symptr) * (image->pi_symcount + nfuncsyms));
762	if (symptr == image->pi_symbols) /* realloc() failed. */
763		return;
764	image->pi_symbols = symptr;
765
766	/*
767	 * Append new symbols to the end of the current table.
768	 */
769	symptr += image->pi_symcount;
770
771	for (n = newsyms = 0; n < nshsyms; n++) {
772		if (gelf_getsym(data, (int) n, &sym) != &sym)
773			return;
774		if (GELF_ST_TYPE(sym.st_info) != STT_FUNC)
775			continue;
776
777		if (!firsttime && pmcstat_symbol_search(image, sym.st_value))
778			continue; /* We've seen this symbol already. */
779
780		if ((fnname = elf_strptr(e, sh->sh_link, sym.st_name))
781		    == NULL)
782			continue;
783
784		symptr->ps_name  = pmcstat_string_intern(fnname);
785		symptr->ps_start = sym.st_value - image->pi_vaddr;
786		symptr->ps_end   = symptr->ps_start + sym.st_size;
787		symptr++;
788
789		newsyms++;
790	}
791
792	image->pi_symcount += newsyms;
793
794	assert(newsyms <= nfuncsyms);
795
796	/*
797	 * Return space to the system if there were duplicates.
798	 */
799	if (newsyms < nfuncsyms)
800		image->pi_symbols = realloc(image->pi_symbols,
801		    sizeof(*symptr) * image->pi_symcount);
802
803	/*
804	 * Keep the list of symbols sorted.
805	 */
806	qsort(image->pi_symbols, image->pi_symcount, sizeof(*symptr),
807	    pmcstat_symbol_compare);
808
809	/*
810	 * Deal with function symbols that have a size of 'zero' by
811	 * making them extend to the next higher address.  These
812	 * symbols are usually defined in assembly code.
813	 */
814	for (symptr = image->pi_symbols;
815	     symptr < image->pi_symbols + (image->pi_symcount - 1);
816	     symptr++)
817		if (symptr->ps_start == symptr->ps_end)
818			symptr->ps_end = (symptr+1)->ps_start;
819}
820
821/*
822 * Examine an ELF file to determine the size of its text segment.
823 * Sets image->pi_type if anything conclusive can be determined about
824 * this image.
825 */
826
827static void
828pmcstat_image_get_elf_params(struct pmcstat_image *image,
829    struct pmcstat_args *a)
830{
831	int fd;
832	size_t i, nph, nsh;
833	const char *path, *elfbase;
834	uintfptr_t minva, maxva;
835	Elf *e;
836	Elf_Scn *scn;
837	GElf_Ehdr eh;
838	GElf_Phdr ph;
839	GElf_Shdr sh;
840	enum pmcstat_image_type image_type;
841	char buffer[PATH_MAX];
842
843	assert(image->pi_type == PMCSTAT_IMAGE_UNKNOWN);
844
845	image->pi_start = minva = ~(uintfptr_t) 0;
846	image->pi_end = maxva = (uintfptr_t) 0;
847	image->pi_type = image_type = PMCSTAT_IMAGE_INDETERMINABLE;
848	image->pi_isdynamic = 0;
849	image->pi_dynlinkerpath = NULL;
850	image->pi_vaddr = 0;
851
852	path = pmcstat_string_unintern(image->pi_execpath);
853	assert(path != NULL);
854
855	/*
856	 * Look for kernel modules under FSROOT/KERNELPATH/NAME,
857	 * and user mode executable objects under FSROOT/PATHNAME.
858	 */
859	if (image->pi_iskernelmodule)
860		(void) snprintf(buffer, sizeof(buffer), "%s%s/%s",
861		    a->pa_fsroot, a->pa_kernel, path);
862	else
863		(void) snprintf(buffer, sizeof(buffer), "%s%s",
864		    a->pa_fsroot, path);
865
866	e = NULL;
867	if ((fd = open(buffer, O_RDONLY, 0)) < 0 ||
868	    (e = elf_begin(fd, ELF_C_READ, NULL)) == NULL ||
869	    (elf_kind(e) != ELF_K_ELF)) {
870		warnx("WARNING: Cannot determine the type of \"%s\".",
871		    buffer);
872		goto done;
873	}
874
875	if (gelf_getehdr(e, &eh) != &eh) {
876		warnx("WARNING: Cannot retrieve the ELF Header for "
877		    "\"%s\": %s.", buffer, elf_errmsg(-1));
878		goto done;
879	}
880
881	if (eh.e_type != ET_EXEC && eh.e_type != ET_DYN &&
882	    !(image->pi_iskernelmodule && eh.e_type == ET_REL)) {
883		warnx("WARNING: \"%s\" is of an unsupported ELF type.",
884		    buffer);
885		goto done;
886	}
887
888	image_type = eh.e_ident[EI_CLASS] == ELFCLASS32 ?
889	    PMCSTAT_IMAGE_ELF32 : PMCSTAT_IMAGE_ELF64;
890
891	/*
892	 * Determine the virtual address where an executable would be
893	 * loaded.  Additionally, for dynamically linked executables,
894	 * save the pathname to the runtime linker.
895	 */
896	if (eh.e_type == ET_EXEC) {
897		if (elf_getphnum(e, &nph) == 0) {
898			warnx("WARNING: Could not determine the number of "
899			    "program headers in \"%s\": %s.", buffer,
900			    elf_errmsg(-1));
901			goto done;
902		}
903		for (i = 0; i < eh.e_phnum; i++) {
904			if (gelf_getphdr(e, i, &ph) != &ph) {
905				warnx("WARNING: Retrieval of PHDR entry #%ju "
906				    "in \"%s\" failed: %s.", (uintmax_t) i,
907				    buffer, elf_errmsg(-1));
908				goto done;
909			}
910			switch (ph.p_type) {
911			case PT_DYNAMIC:
912				image->pi_isdynamic = 1;
913				break;
914			case PT_INTERP:
915				if ((elfbase = elf_rawfile(e, NULL)) == NULL) {
916					warnx("WARNING: Cannot retrieve the "
917					    "interpreter for \"%s\": %s.",
918					    buffer, elf_errmsg(-1));
919					goto done;
920				}
921				image->pi_dynlinkerpath =
922				    pmcstat_string_intern(elfbase +
923					ph.p_offset);
924				break;
925			case PT_LOAD:
926				if (ph.p_offset == 0)
927					image->pi_vaddr = ph.p_vaddr;
928				break;
929			}
930		}
931	}
932
933	/*
934	 * Get the min and max VA associated with this ELF object.
935	 */
936	if (elf_getshnum(e, &nsh) == 0) {
937		warnx("WARNING: Could not determine the number of sections "
938		    "for \"%s\": %s.", buffer, elf_errmsg(-1));
939		goto done;
940	}
941
942	for (i = 0; i < nsh; i++) {
943		if ((scn = elf_getscn(e, i)) == NULL ||
944		    gelf_getshdr(scn, &sh) != &sh) {
945			warnx("WARNING: Could not retrieve section header "
946			    "#%ju in \"%s\": %s.", (uintmax_t) i, buffer,
947			    elf_errmsg(-1));
948			goto done;
949		}
950		if (sh.sh_flags & SHF_EXECINSTR) {
951			minva = min(minva, sh.sh_addr);
952			maxva = max(maxva, sh.sh_addr + sh.sh_size);
953		}
954		if (sh.sh_type == SHT_SYMTAB || sh.sh_type == SHT_DYNSYM)
955			pmcstat_image_add_symbols(image, e, scn, &sh);
956	}
957
958	image->pi_start = minva;
959	image->pi_end   = maxva;
960	image->pi_type  = image_type;
961	image->pi_fullpath = pmcstat_string_intern(buffer);
962
963 done:
964	(void) elf_end(e);
965	if (fd >= 0)
966		(void) close(fd);
967	return;
968}
969
970/*
971 * Given an image descriptor, determine whether it is an ELF, or AOUT.
972 * If no handler claims the image, set its type to 'INDETERMINABLE'.
973 */
974
975static void
976pmcstat_image_determine_type(struct pmcstat_image *image,
977    struct pmcstat_args *a)
978{
979	assert(image->pi_type == PMCSTAT_IMAGE_UNKNOWN);
980
981	/* Try each kind of handler in turn */
982	if (image->pi_type == PMCSTAT_IMAGE_UNKNOWN)
983		pmcstat_image_get_elf_params(image, a);
984	if (image->pi_type == PMCSTAT_IMAGE_UNKNOWN)
985		pmcstat_image_get_aout_params(image, a);
986
987	/*
988	 * Otherwise, remember that we tried to determine
989	 * the object's type and had failed.
990	 */
991	if (image->pi_type == PMCSTAT_IMAGE_UNKNOWN)
992		image->pi_type = PMCSTAT_IMAGE_INDETERMINABLE;
993}
994
995/*
996 * Locate an image descriptor given an interned path, adding a fresh
997 * descriptor to the cache if necessary.  This function also finds a
998 * suitable name for this image's sample file.
999 *
1000 * We defer filling in the file format specific parts of the image
1001 * structure till the time we actually see a sample that would fall
1002 * into this image.
1003 */
1004
1005static struct pmcstat_image *
1006pmcstat_image_from_path(pmcstat_interned_string internedpath,
1007    int iskernelmodule)
1008{
1009	int count, hash, nlen;
1010	struct pmcstat_image *pi;
1011	char *sn;
1012	char name[NAME_MAX];
1013
1014	hash = pmcstat_string_lookup_hash(internedpath);
1015
1016	/* First, look for an existing entry. */
1017	LIST_FOREACH(pi, &pmcstat_image_hash[hash], pi_next)
1018	    if (pi->pi_execpath == internedpath &&
1019		  pi->pi_iskernelmodule == iskernelmodule)
1020		    return (pi);
1021
1022	/*
1023	 * Allocate a new entry and place it at the head of the hash
1024	 * and LRU lists.
1025	 */
1026	pi = malloc(sizeof(*pi));
1027	if (pi == NULL)
1028		return (NULL);
1029
1030	pi->pi_type = PMCSTAT_IMAGE_UNKNOWN;
1031	pi->pi_execpath = internedpath;
1032	pi->pi_start = ~0;
1033	pi->pi_end = 0;
1034	pi->pi_entry = 0;
1035	pi->pi_vaddr = 0;
1036	pi->pi_isdynamic = 0;
1037	pi->pi_iskernelmodule = iskernelmodule;
1038	pi->pi_dynlinkerpath = NULL;
1039	pi->pi_symbols = NULL;
1040	pi->pi_symcount = 0;
1041
1042	/*
1043	 * Look for a suitable name for the sample files associated
1044	 * with this image: if `basename(path)`+".gmon" is available,
1045	 * we use that, otherwise we try iterating through
1046	 * `basename(path)`+ "~" + NNN + ".gmon" till we get a free
1047	 * entry.
1048	 */
1049	if ((sn = basename(pmcstat_string_unintern(internedpath))) == NULL)
1050		err(EX_OSERR, "ERROR: Cannot process \"%s\"",
1051		    pmcstat_string_unintern(internedpath));
1052
1053	nlen = strlen(sn);
1054	nlen = min(nlen, (int) (sizeof(name) - sizeof(".gmon")));
1055
1056	snprintf(name, sizeof(name), "%.*s.gmon", nlen, sn);
1057
1058	/* try use the unabridged name first */
1059	if (pmcstat_string_lookup(name) == NULL)
1060		pi->pi_samplename = pmcstat_string_intern(name);
1061	else {
1062		/*
1063		 * Otherwise use a prefix from the original name and
1064		 * upto 3 digits.
1065		 */
1066		nlen = strlen(sn);
1067		nlen = min(nlen, (int) (sizeof(name)-sizeof("~NNN.gmon")));
1068		count = 0;
1069		do {
1070			if (++count > 999)
1071				errx(EX_CANTCREAT, "ERROR: cannot create a "
1072				    "gmon file for \"%s\"", name);
1073			snprintf(name, sizeof(name), "%.*s~%3.3d.gmon",
1074			    nlen, sn, count);
1075			if (pmcstat_string_lookup(name) == NULL) {
1076				pi->pi_samplename =
1077				    pmcstat_string_intern(name);
1078				count = 0;
1079			}
1080		} while (count > 0);
1081	}
1082
1083
1084	LIST_INIT(&pi->pi_gmlist);
1085
1086	LIST_INSERT_HEAD(&pmcstat_image_hash[hash], pi, pi_next);
1087
1088	return (pi);
1089}
1090
1091/*
1092 * Increment the bucket in the gmon.out file corresponding to 'pmcid'
1093 * and 'pc'.
1094 */
1095
1096static void
1097pmcstat_image_increment_bucket(struct pmcstat_pcmap *map, uintfptr_t pc,
1098    pmc_id_t pmcid, struct pmcstat_args *a)
1099{
1100	struct pmcstat_image *image;
1101	struct pmcstat_gmonfile *pgf;
1102	uintfptr_t bucket;
1103	HISTCOUNTER *hc;
1104
1105	assert(pc >= map->ppm_lowpc && pc < map->ppm_highpc);
1106
1107	image = map->ppm_image;
1108
1109	/*
1110	 * If this is the first time we are seeing a sample for
1111	 * this executable image, try determine its parameters.
1112	 */
1113	if (image->pi_type == PMCSTAT_IMAGE_UNKNOWN)
1114		pmcstat_image_determine_type(image, a);
1115
1116	assert(image->pi_type != PMCSTAT_IMAGE_UNKNOWN);
1117
1118	/* Ignore samples in images that we know nothing about. */
1119	if (image->pi_type == PMCSTAT_IMAGE_INDETERMINABLE) {
1120		pmcstat_stats.ps_samples_indeterminable++;
1121		return;
1122	}
1123
1124	/*
1125	 * Find the gmon file corresponding to 'pmcid', creating it if
1126	 * needed.
1127	 */
1128	pgf = pmcstat_image_find_gmonfile(image, pmcid);
1129	if (pgf == NULL) {
1130		if ((pgf = calloc(1, sizeof(*pgf))) == NULL)
1131			err(EX_OSERR, "ERROR:");
1132
1133		pgf->pgf_gmondata = NULL;	/* mark as unmapped */
1134		pgf->pgf_name = pmcstat_gmon_create_name(a->pa_samplesdir,
1135		    image, pmcid);
1136		pgf->pgf_pmcid = pmcid;
1137		assert(image->pi_end > image->pi_start);
1138		pgf->pgf_nbuckets = (image->pi_end - image->pi_start) /
1139		    FUNCTION_ALIGNMENT;	/* see <machine/profile.h> */
1140		pgf->pgf_ndatabytes = sizeof(struct gmonhdr) +
1141		    pgf->pgf_nbuckets * sizeof(HISTCOUNTER);
1142		pgf->pgf_nsamples = 0;
1143		pgf->pgf_file = NULL;
1144
1145		pmcstat_gmon_create_file(pgf, image);
1146
1147		LIST_INSERT_HEAD(&image->pi_gmlist, pgf, pgf_next);
1148	}
1149
1150	/*
1151	 * Map the gmon file in if needed.  It may have been mapped
1152	 * out under memory pressure.
1153	 */
1154	if (pgf->pgf_gmondata == NULL)
1155		pmcstat_gmon_map_file(pgf);
1156
1157	assert(pgf->pgf_gmondata != NULL);
1158
1159	/*
1160	 *
1161	 */
1162
1163	bucket = (pc - map->ppm_lowpc) / FUNCTION_ALIGNMENT;
1164
1165	assert(bucket < pgf->pgf_nbuckets);
1166
1167	hc = (HISTCOUNTER *) ((uintptr_t) pgf->pgf_gmondata +
1168	    sizeof(struct gmonhdr));
1169
1170	/* saturating add */
1171	if (hc[bucket] < 0xFFFFU)  /* XXX tie this to sizeof(HISTCOUNTER) */
1172		hc[bucket]++;
1173	else /* mark that an overflow occurred */
1174		pgf->pgf_overflow = 1;
1175
1176	pgf->pgf_nsamples++;
1177}
1178
1179/*
1180 * Record the fact that PC values from 'start' to 'end' come from
1181 * image 'image'.
1182 */
1183
1184static void
1185pmcstat_image_link(struct pmcstat_process *pp, struct pmcstat_image *image,
1186    uintfptr_t start)
1187{
1188	struct pmcstat_pcmap *pcm, *pcmnew;
1189	uintfptr_t offset;
1190
1191	assert(image->pi_type != PMCSTAT_IMAGE_UNKNOWN &&
1192	    image->pi_type != PMCSTAT_IMAGE_INDETERMINABLE);
1193
1194	if ((pcmnew = malloc(sizeof(*pcmnew))) == NULL)
1195		err(EX_OSERR, "ERROR: Cannot create a map entry");
1196
1197	/*
1198	 * Adjust the map entry to only cover the text portion
1199	 * of the object.
1200	 */
1201
1202	offset = start - image->pi_vaddr;
1203	pcmnew->ppm_lowpc  = image->pi_start + offset;
1204	pcmnew->ppm_highpc = image->pi_end + offset;
1205	pcmnew->ppm_image  = image;
1206
1207	assert(pcmnew->ppm_lowpc < pcmnew->ppm_highpc);
1208
1209	/* Overlapped mmap()'s are assumed to never occur. */
1210	TAILQ_FOREACH(pcm, &pp->pp_map, ppm_next)
1211	    if (pcm->ppm_lowpc >= pcmnew->ppm_highpc)
1212		    break;
1213
1214	if (pcm == NULL)
1215		TAILQ_INSERT_TAIL(&pp->pp_map, pcmnew, ppm_next);
1216	else
1217		TAILQ_INSERT_BEFORE(pcm, pcmnew, ppm_next);
1218}
1219
1220/*
1221 * Unmap images in the range [start..end) associated with process
1222 * 'pp'.
1223 */
1224
1225static void
1226pmcstat_image_unmap(struct pmcstat_process *pp, uintfptr_t start,
1227    uintfptr_t end)
1228{
1229	struct pmcstat_pcmap *pcm, *pcmtmp, *pcmnew;
1230
1231	assert(pp != NULL);
1232	assert(start < end);
1233
1234	/*
1235	 * Cases:
1236	 * - we could have the range completely in the middle of an
1237	 *   existing pcmap; in this case we have to split the pcmap
1238	 *   structure into two (i.e., generate a 'hole').
1239	 * - we could have the range covering multiple pcmaps; these
1240	 *   will have to be removed.
1241	 * - we could have either 'start' or 'end' falling in the
1242	 *   middle of a pcmap; in this case shorten the entry.
1243	 */
1244	TAILQ_FOREACH_SAFE(pcm, &pp->pp_map, ppm_next, pcmtmp) {
1245		assert(pcm->ppm_lowpc < pcm->ppm_highpc);
1246		if (pcm->ppm_highpc <= start)
1247			continue;
1248		if (pcm->ppm_lowpc >= end)
1249			return;
1250		if (pcm->ppm_lowpc >= start && pcm->ppm_highpc <= end) {
1251			/*
1252			 * The current pcmap is completely inside the
1253			 * unmapped range: remove it entirely.
1254			 */
1255			TAILQ_REMOVE(&pp->pp_map, pcm, ppm_next);
1256			free(pcm);
1257		} else if (pcm->ppm_lowpc < start && pcm->ppm_highpc > end) {
1258			/*
1259			 * Split this pcmap into two; curtail the
1260			 * current map to end at [start-1], and start
1261			 * the new one at [end].
1262			 */
1263			if ((pcmnew = malloc(sizeof(*pcmnew))) == NULL)
1264				err(EX_OSERR, "ERROR: Cannot split a map "
1265				    "entry");
1266
1267			pcmnew->ppm_image = pcm->ppm_image;
1268
1269			pcmnew->ppm_lowpc = end;
1270			pcmnew->ppm_highpc = pcm->ppm_highpc;
1271
1272			pcm->ppm_highpc = start;
1273
1274			TAILQ_INSERT_AFTER(&pp->pp_map, pcm, pcmnew, ppm_next);
1275
1276			return;
1277		} else if (pcm->ppm_lowpc < start && pcm->ppm_highpc <= end)
1278			pcm->ppm_highpc = start;
1279		else if (pcm->ppm_lowpc >= start && pcm->ppm_highpc > end)
1280			pcm->ppm_lowpc = end;
1281		else
1282			assert(0);
1283	}
1284}
1285
1286/*
1287 * Add a {pmcid,name} mapping.
1288 */
1289
1290static void
1291pmcstat_pmcid_add(pmc_id_t pmcid, pmcstat_interned_string ps,
1292    struct pmcstat_args *a)
1293{
1294	struct pmcstat_pmcrecord *pr;
1295	struct stat st;
1296	char fullpath[PATH_MAX];
1297
1298	/* Replace an existing name for the PMC. */
1299	LIST_FOREACH(pr, &pmcstat_pmcs, pr_next)
1300	    if (pr->pr_pmcid == pmcid) {
1301		    pr->pr_pmcname = ps;
1302		    return;
1303	    }
1304
1305	/*
1306	 * Otherwise, allocate a new descriptor and create the
1307	 * appropriate directory to hold gmon.out files.
1308	 */
1309	if ((pr = malloc(sizeof(*pr))) == NULL)
1310		err(EX_OSERR, "ERROR: Cannot allocate pmc record");
1311
1312	pr->pr_pmcid = pmcid;
1313	pr->pr_pmcname = ps;
1314	LIST_INSERT_HEAD(&pmcstat_pmcs, pr, pr_next);
1315
1316	(void) snprintf(fullpath, sizeof(fullpath), "%s/%s", a->pa_samplesdir,
1317	    pmcstat_string_unintern(ps));
1318
1319	/* If the path name exists, it should be a directory */
1320	if (stat(fullpath, &st) == 0 && S_ISDIR(st.st_mode))
1321		return;
1322
1323	if (mkdir(fullpath, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) < 0)
1324		err(EX_OSERR, "ERROR: Cannot create directory \"%s\"",
1325		    fullpath);
1326}
1327
1328/*
1329 * Given a pmcid in use, find its human-readable name.
1330 */
1331
1332static const char *
1333pmcstat_pmcid_to_name(pmc_id_t pmcid)
1334{
1335	struct pmcstat_pmcrecord *pr;
1336	char fullpath[PATH_MAX];
1337
1338	LIST_FOREACH(pr, &pmcstat_pmcs, pr_next)
1339	    if (pr->pr_pmcid == pmcid)
1340		    return (pmcstat_string_unintern(pr->pr_pmcname));
1341
1342	/* create a default name and add this entry */
1343	if ((pr = malloc(sizeof(*pr))) == NULL)
1344		err(EX_OSERR, "ERROR: ");
1345	pr->pr_pmcid = pmcid;
1346
1347	(void) snprintf(fullpath, sizeof(fullpath), "%X", (unsigned int) pmcid);
1348	pr->pr_pmcname = pmcstat_string_intern(fullpath);
1349
1350	LIST_INSERT_HEAD(&pmcstat_pmcs, pr, pr_next);
1351
1352	return (pmcstat_string_unintern(pr->pr_pmcname));
1353}
1354
1355/*
1356 * Associate an AOUT image with a process.
1357 */
1358
1359static void
1360pmcstat_process_aout_exec(struct pmcstat_process *pp,
1361    struct pmcstat_image *image, uintfptr_t entryaddr,
1362    struct pmcstat_args *a)
1363{
1364	(void) pp;
1365	(void) image;
1366	(void) entryaddr;
1367	(void) a;
1368	/* TODO Implement a.out handling */
1369}
1370
1371/*
1372 * Associate an ELF image with a process.
1373 */
1374
1375static void
1376pmcstat_process_elf_exec(struct pmcstat_process *pp,
1377    struct pmcstat_image *image, uintfptr_t entryaddr,
1378    struct pmcstat_args *a)
1379{
1380	uintmax_t libstart;
1381	struct pmcstat_image *rtldimage;
1382
1383	assert(image->pi_type == PMCSTAT_IMAGE_ELF32 ||
1384	    image->pi_type == PMCSTAT_IMAGE_ELF64);
1385
1386	/* Create a map entry for the base executable. */
1387	pmcstat_image_link(pp, image, image->pi_vaddr);
1388
1389	/*
1390	 * For dynamically linked executables we need to determine
1391	 * where the dynamic linker was mapped to for this process,
1392	 * Subsequent executable objects that are mapped in by the
1393	 * dynamic linker will be tracked by log events of type
1394	 * PMCLOG_TYPE_MAP_IN.
1395	 */
1396
1397	if (image->pi_isdynamic) {
1398
1399		/*
1400		 * The runtime loader gets loaded just after the maximum
1401		 * possible heap address.  Like so:
1402		 *
1403		 * [  TEXT DATA BSS HEAP -->*RTLD  SHLIBS   <--STACK]
1404		 * ^					            ^
1405		 * 0				   VM_MAXUSER_ADDRESS
1406
1407		 *
1408		 * The exact address where the loader gets mapped in
1409		 * will vary according to the size of the executable
1410		 * and the limits on the size of the process'es data
1411		 * segment at the time of exec().  The entry address
1412		 * recorded at process exec time corresponds to the
1413		 * 'start' address inside the dynamic linker.  From
1414		 * this we can figure out the address where the
1415		 * runtime loader's file object had been mapped to.
1416		 */
1417		rtldimage = pmcstat_image_from_path(image->pi_dynlinkerpath,
1418		    0);
1419		if (rtldimage == NULL) {
1420			warnx("WARNING: Cannot find image for \"%s\".",
1421			    pmcstat_string_unintern(image->pi_dynlinkerpath));
1422			pmcstat_stats.ps_exec_errors++;
1423			return;
1424		}
1425
1426		if (rtldimage->pi_type == PMCSTAT_IMAGE_UNKNOWN)
1427			pmcstat_image_get_elf_params(rtldimage, a);
1428
1429		if (rtldimage->pi_type != PMCSTAT_IMAGE_ELF32 &&
1430		    rtldimage->pi_type != PMCSTAT_IMAGE_ELF64) {
1431			warnx("WARNING: rtld not an ELF object \"%s\".",
1432			    pmcstat_string_unintern(image->pi_dynlinkerpath));
1433			return;
1434		}
1435
1436		libstart = entryaddr - rtldimage->pi_entry;
1437		pmcstat_image_link(pp, rtldimage, libstart);
1438	}
1439}
1440
1441/*
1442 * Find the process descriptor corresponding to a PID.  If 'allocate'
1443 * is zero, we return a NULL if a pid descriptor could not be found or
1444 * a process descriptor process.  If 'allocate' is non-zero, then we
1445 * will attempt to allocate a fresh process descriptor.  Zombie
1446 * process descriptors are only removed if a fresh allocation for the
1447 * same PID is requested.
1448 */
1449
1450static struct pmcstat_process *
1451pmcstat_process_lookup(pid_t pid, int allocate)
1452{
1453	uint32_t hash;
1454	struct pmcstat_pcmap *ppm, *ppmtmp;
1455	struct pmcstat_process *pp, *pptmp;
1456
1457	hash = (uint32_t) pid & PMCSTAT_HASH_MASK;	/* simplicity wins */
1458
1459	LIST_FOREACH_SAFE(pp, &pmcstat_process_hash[hash], pp_next, pptmp)
1460	    if (pp->pp_pid == pid) {
1461		    /* Found a descriptor, check and process zombies */
1462		    if (allocate && pp->pp_isactive == 0) {
1463			    /* remove maps */
1464			    TAILQ_FOREACH_SAFE(ppm, &pp->pp_map, ppm_next,
1465				ppmtmp) {
1466				    TAILQ_REMOVE(&pp->pp_map, ppm, ppm_next);
1467				    free(ppm);
1468			    }
1469			    /* remove process entry */
1470			    LIST_REMOVE(pp, pp_next);
1471			    free(pp);
1472			    break;
1473		    }
1474		    return (pp);
1475	    }
1476
1477	if (!allocate)
1478		return (NULL);
1479
1480	if ((pp = malloc(sizeof(*pp))) == NULL)
1481		err(EX_OSERR, "ERROR: Cannot allocate pid descriptor");
1482
1483	pp->pp_pid = pid;
1484	pp->pp_isactive = 1;
1485
1486	TAILQ_INIT(&pp->pp_map);
1487
1488	LIST_INSERT_HEAD(&pmcstat_process_hash[hash], pp, pp_next);
1489	return (pp);
1490}
1491
1492/*
1493 * Associate an image and a process.
1494 */
1495
1496static void
1497pmcstat_process_exec(struct pmcstat_process *pp,
1498    pmcstat_interned_string path, uintfptr_t entryaddr,
1499    struct pmcstat_args *a)
1500{
1501	struct pmcstat_image *image;
1502
1503	if ((image = pmcstat_image_from_path(path, 0)) == NULL) {
1504		pmcstat_stats.ps_exec_errors++;
1505		return;
1506	}
1507
1508	if (image->pi_type == PMCSTAT_IMAGE_UNKNOWN)
1509		pmcstat_image_determine_type(image, a);
1510
1511	assert(image->pi_type != PMCSTAT_IMAGE_UNKNOWN);
1512
1513	switch (image->pi_type) {
1514	case PMCSTAT_IMAGE_ELF32:
1515	case PMCSTAT_IMAGE_ELF64:
1516		pmcstat_stats.ps_exec_elf++;
1517		pmcstat_process_elf_exec(pp, image, entryaddr, a);
1518		break;
1519
1520	case PMCSTAT_IMAGE_AOUT:
1521		pmcstat_stats.ps_exec_aout++;
1522		pmcstat_process_aout_exec(pp, image, entryaddr, a);
1523		break;
1524
1525	case PMCSTAT_IMAGE_INDETERMINABLE:
1526		pmcstat_stats.ps_exec_indeterminable++;
1527		break;
1528
1529	default:
1530		err(EX_SOFTWARE, "ERROR: Unsupported executable type for "
1531		    "\"%s\"", pmcstat_string_unintern(path));
1532	}
1533}
1534
1535
1536/*
1537 * Find the map entry associated with process 'p' at PC value 'pc'.
1538 */
1539
1540static struct pmcstat_pcmap *
1541pmcstat_process_find_map(struct pmcstat_process *p, uintfptr_t pc)
1542{
1543	struct pmcstat_pcmap *ppm;
1544
1545	TAILQ_FOREACH(ppm, &p->pp_map, ppm_next) {
1546		if (pc >= ppm->ppm_lowpc && pc < ppm->ppm_highpc)
1547			return (ppm);
1548		if (pc < ppm->ppm_lowpc)
1549			return (NULL);
1550	}
1551
1552	return (NULL);
1553}
1554
1555static struct pmcstat_cgnode *
1556pmcstat_cgnode_allocate(struct pmcstat_image *image, uintfptr_t pc)
1557{
1558	struct pmcstat_cgnode *cg;
1559
1560	if ((cg = malloc(sizeof(*cg))) == NULL)
1561		err(EX_OSERR, "ERROR: Cannot allocate callgraph node");
1562
1563	cg->pcg_image = image;
1564	cg->pcg_func = pc;
1565
1566	cg->pcg_count = 0;
1567	cg->pcg_nchildren = 0;
1568	LIST_INIT(&cg->pcg_children);
1569
1570	return (cg);
1571}
1572
1573/*
1574 * Free a node and its children.
1575 */
1576static void
1577pmcstat_cgnode_free(struct pmcstat_cgnode *cg)
1578{
1579	struct pmcstat_cgnode *cgc, *cgtmp;
1580
1581	LIST_FOREACH_SAFE(cgc, &cg->pcg_children, pcg_sibling, cgtmp)
1582		pmcstat_cgnode_free(cgc);
1583	free(cg);
1584}
1585
1586/*
1587 * Look for a callgraph node associated with pmc `pmcid' in the global
1588 * hash table that corresponds to the given `pc' value in the process
1589 * `pp'.
1590 */
1591static struct pmcstat_cgnode *
1592pmcstat_cgnode_hash_lookup_pc(struct pmcstat_process *pp, uint32_t pmcid,
1593    uintfptr_t pc, int usermode)
1594{
1595	struct pmcstat_pcmap *ppm;
1596	struct pmcstat_symbol *sym;
1597	struct pmcstat_image *image;
1598	struct pmcstat_cgnode *cg;
1599	struct pmcstat_cgnode_hash *h;
1600	uintfptr_t loadaddress;
1601	unsigned int i, hash;
1602
1603	ppm = pmcstat_process_find_map(usermode ? pp : pmcstat_kernproc, pc);
1604	if (ppm == NULL)
1605		return (NULL);
1606
1607	image = ppm->ppm_image;
1608
1609	loadaddress = ppm->ppm_lowpc + image->pi_vaddr - image->pi_start;
1610	pc -= loadaddress;	/* Convert to an offset in the image. */
1611
1612	/*
1613	 * Try determine the function at this offset.  If we can't
1614	 * find a function round leave the `pc' value alone.
1615	 */
1616	if ((sym = pmcstat_symbol_search(image, pc)) != NULL)
1617		pc = sym->ps_start;
1618
1619	for (hash = i = 0; i < sizeof(uintfptr_t); i++)
1620		hash += (pc >> i) & 0xFF;
1621
1622	hash &= PMCSTAT_HASH_MASK;
1623
1624	cg = NULL;
1625	LIST_FOREACH(h, &pmcstat_cgnode_hash[hash], pch_next)
1626	{
1627		if (h->pch_pmcid != pmcid)
1628			continue;
1629
1630		cg = h->pch_cgnode;
1631
1632		assert(cg != NULL);
1633
1634		if (cg->pcg_image == image && cg->pcg_func == pc)
1635			return (cg);
1636	}
1637
1638	/*
1639	 * We haven't seen this (pmcid, pc) tuple yet, so allocate a
1640	 * new callgraph node and a new hash table entry for it.
1641	 */
1642	cg = pmcstat_cgnode_allocate(image, pc);
1643	if ((h = malloc(sizeof(*h))) == NULL)
1644		err(EX_OSERR, "ERROR: Could not allocate callgraph node");
1645
1646	h->pch_pmcid = pmcid;
1647	h->pch_cgnode = cg;
1648	LIST_INSERT_HEAD(&pmcstat_cgnode_hash[hash], h, pch_next);
1649
1650	pmcstat_cgnode_hash_count++;
1651
1652	return (cg);
1653}
1654
1655/*
1656 * Compare two callgraph nodes for sorting.
1657 */
1658static int
1659pmcstat_cgnode_compare(const void *a, const void *b)
1660{
1661	const struct pmcstat_cgnode *const *pcg1, *const *pcg2, *cg1, *cg2;
1662
1663	pcg1 = (const struct pmcstat_cgnode *const *) a;
1664	cg1 = *pcg1;
1665	pcg2 = (const struct pmcstat_cgnode *const *) b;
1666	cg2 = *pcg2;
1667
1668	/* Sort in reverse order */
1669	if (cg1->pcg_count < cg2->pcg_count)
1670		return (1);
1671	if (cg1->pcg_count > cg2->pcg_count)
1672		return (-1);
1673	return (0);
1674}
1675
1676/*
1677 * Find (allocating if a needed) a callgraph node in the given
1678 * parent with the same (image, pcoffset) pair.
1679 */
1680
1681static struct pmcstat_cgnode *
1682pmcstat_cgnode_find(struct pmcstat_cgnode *parent, struct pmcstat_image *image,
1683    uintfptr_t pcoffset)
1684{
1685	struct pmcstat_cgnode *child;
1686
1687	LIST_FOREACH(child, &parent->pcg_children, pcg_sibling) {
1688		if (child->pcg_image == image &&
1689		    child->pcg_func == pcoffset)
1690			return (child);
1691	}
1692
1693	/*
1694	 * Allocate a new structure.
1695	 */
1696
1697	child = pmcstat_cgnode_allocate(image, pcoffset);
1698
1699	/*
1700	 * Link it into the parent.
1701	 */
1702	LIST_INSERT_HEAD(&parent->pcg_children, child, pcg_sibling);
1703	parent->pcg_nchildren++;
1704
1705	return (child);
1706}
1707
1708/*
1709 * Print one callgraph node.  The output format is:
1710 *
1711 * indentation %(parent's samples) #nsamples function@object
1712 */
1713static void
1714pmcstat_cgnode_print(struct pmcstat_args *a, struct pmcstat_cgnode *cg,
1715    int depth, uint32_t total)
1716{
1717	uint32_t n;
1718	const char *space;
1719	struct pmcstat_symbol *sym;
1720	struct pmcstat_cgnode **sortbuffer, **cgn, *pcg;
1721
1722	space = " ";
1723
1724	if (depth > 0)
1725		(void) fprintf(a->pa_graphfile, "%*s", depth, space);
1726
1727	if (cg->pcg_count == total)
1728		(void) fprintf(a->pa_graphfile, "100.0%% ");
1729	else
1730		(void) fprintf(a->pa_graphfile, "%05.2f%% ",
1731		    100.0 * cg->pcg_count / total);
1732
1733	n = fprintf(a->pa_graphfile, " [%u] ", cg->pcg_count);
1734
1735	/* #samples is a 12 character wide field. */
1736	if (n < 12)
1737		(void) fprintf(a->pa_graphfile, "%*s", 12 - n, space);
1738
1739	if (depth > 0)
1740		(void) fprintf(a->pa_graphfile, "%*s", depth, space);
1741
1742	sym = pmcstat_symbol_search(cg->pcg_image, cg->pcg_func);
1743	if (sym)
1744		(void) fprintf(a->pa_graphfile, "%s",
1745		    pmcstat_string_unintern(sym->ps_name));
1746	else
1747		(void) fprintf(a->pa_graphfile, "%p",
1748		    (void *) (cg->pcg_image->pi_vaddr + cg->pcg_func));
1749
1750	if (pmcstat_previous_filename_printed !=
1751	    cg->pcg_image->pi_fullpath) {
1752		pmcstat_previous_filename_printed = cg->pcg_image->pi_fullpath;
1753		(void) fprintf(a->pa_graphfile, " @ %s\n",
1754		    pmcstat_string_unintern(
1755		    pmcstat_previous_filename_printed));
1756	} else
1757		(void) fprintf(a->pa_graphfile, "\n");
1758
1759	if (cg->pcg_nchildren == 0)
1760		return;
1761
1762	if ((sortbuffer = (struct pmcstat_cgnode **)
1763		malloc(sizeof(struct pmcstat_cgnode *) *
1764		    cg->pcg_nchildren)) == NULL)
1765		err(EX_OSERR, "ERROR: Cannot print callgraph");
1766	cgn = sortbuffer;
1767
1768	LIST_FOREACH(pcg, &cg->pcg_children, pcg_sibling)
1769	    *cgn++ = pcg;
1770
1771	assert(cgn - sortbuffer == (int) cg->pcg_nchildren);
1772
1773	qsort(sortbuffer, cg->pcg_nchildren, sizeof(struct pmcstat_cgnode *),
1774	    pmcstat_cgnode_compare);
1775
1776	for (cgn = sortbuffer, n = 0; n < cg->pcg_nchildren; n++, cgn++)
1777		pmcstat_cgnode_print(a, *cgn, depth+1, cg->pcg_count);
1778
1779	free(sortbuffer);
1780}
1781
1782/*
1783 * Record a callchain.
1784 */
1785
1786static void
1787pmcstat_record_callchain(struct pmcstat_process *pp, uint32_t pmcid,
1788    uint32_t nsamples, uintfptr_t *cc, int usermode, struct pmcstat_args *a)
1789{
1790	uintfptr_t pc, loadaddress;
1791	uint32_t n;
1792	struct pmcstat_image *image;
1793	struct pmcstat_pcmap *ppm;
1794	struct pmcstat_symbol *sym;
1795	struct pmcstat_cgnode *parent, *child;
1796
1797	/*
1798	 * Find the callgraph node recorded in the global hash table
1799	 * for this (pmcid, pc).
1800	 */
1801
1802	pc = cc[0];
1803	parent = pmcstat_cgnode_hash_lookup_pc(pp, pmcid, pc, usermode);
1804	if (parent == NULL) {
1805		pmcstat_stats.ps_callchain_dubious_frames++;
1806		return;
1807	}
1808
1809	parent->pcg_count++;
1810
1811	/*
1812	 * For each return address in the call chain record, subject
1813	 * to the maximum depth desired.
1814	 * - Find the image associated with the sample.  Stop if there
1815	 *   there is no valid image at that address.
1816	 * - Find the function that overlaps the return address.
1817	 * - If found: use the start address of the function.
1818	 *   If not found (say an object's symbol table is not present or
1819	 *   is incomplete), round down to th gprof bucket granularity.
1820	 * - Convert return virtual address to an offset in the image.
1821	 * - Look for a child with the same {offset,image} tuple,
1822	 *   inserting one if needed.
1823	 * - Increment the count of occurrences of the child.
1824	 */
1825
1826	for (n = 1; n < (uint32_t) a->pa_graphdepth && n < nsamples; n++,
1827	    parent = child) {
1828		pc = cc[n];
1829
1830		ppm = pmcstat_process_find_map(usermode ? pp :
1831		    pmcstat_kernproc, pc);
1832		if (ppm == NULL)
1833			return;
1834
1835		image = ppm->ppm_image;
1836		loadaddress = ppm->ppm_lowpc + image->pi_vaddr -
1837		    image->pi_start;
1838		pc -= loadaddress;
1839
1840		if ((sym = pmcstat_symbol_search(image, pc)) != NULL)
1841			pc = sym->ps_start;
1842
1843		child = pmcstat_cgnode_find(parent, image, pc);
1844		child->pcg_count++;
1845	}
1846}
1847
1848/*
1849 * Printing a callgraph for a PMC.
1850 */
1851static void
1852pmcstat_callgraph_print_for_pmcid(struct pmcstat_args *a,
1853    struct pmcstat_pmcrecord *pmcr)
1854{
1855	int n, nentries;
1856	uint32_t nsamples, pmcid;
1857	struct pmcstat_cgnode **sortbuffer, **cgn;
1858	struct pmcstat_cgnode_hash *pch;
1859
1860	/*
1861	 * We pull out all callgraph nodes in the top-level hash table
1862	 * with a matching PMC id.  We then sort these based on the
1863	 * frequency of occurrence.  Each callgraph node is then
1864	 * printed.
1865	 */
1866
1867	nsamples = 0;
1868	pmcid = pmcr->pr_pmcid;
1869	if ((sortbuffer = (struct pmcstat_cgnode **)
1870	    malloc(sizeof(struct pmcstat_cgnode *) *
1871	    pmcstat_cgnode_hash_count)) == NULL)
1872		err(EX_OSERR, "ERROR: Cannot sort callgraph");
1873	cgn = sortbuffer;
1874
1875	memset(sortbuffer, 0xFF, pmcstat_cgnode_hash_count *
1876	    sizeof(struct pmcstat_cgnode **));
1877
1878	for (n = 0; n < PMCSTAT_NHASH; n++)
1879		LIST_FOREACH(pch, &pmcstat_cgnode_hash[n], pch_next)
1880		    if (pch->pch_pmcid == pmcid) {
1881			    nsamples += pch->pch_cgnode->pcg_count;
1882			    *cgn++ = pch->pch_cgnode;
1883		    }
1884
1885	nentries = cgn - sortbuffer;
1886	assert(nentries <= pmcstat_cgnode_hash_count);
1887
1888	if (nentries == 0)
1889		return;
1890
1891	qsort(sortbuffer, nentries, sizeof(struct pmcstat_cgnode *),
1892	    pmcstat_cgnode_compare);
1893
1894	(void) fprintf(a->pa_graphfile,
1895	    "@ %s [%u samples]\n\n",
1896	    pmcstat_string_unintern(pmcr->pr_pmcname),
1897	    nsamples);
1898
1899	for (cgn = sortbuffer, n = 0; n < nentries; n++, cgn++) {
1900		pmcstat_previous_filename_printed = NULL;
1901		pmcstat_cgnode_print(a, *cgn, 0, nsamples);
1902		(void) fprintf(a->pa_graphfile, "\n");
1903	}
1904
1905	free(sortbuffer);
1906}
1907
1908/*
1909 * Print out callgraphs.
1910 */
1911
1912static void
1913pmcstat_callgraph_print(struct pmcstat_args *a)
1914{
1915	struct pmcstat_pmcrecord *pmcr;
1916
1917	LIST_FOREACH(pmcr, &pmcstat_pmcs, pr_next)
1918	    pmcstat_callgraph_print_for_pmcid(a, pmcr);
1919}
1920
1921static void
1922pmcstat_cgnode_do_gmon_arcs(struct pmcstat_cgnode *cg, pmc_id_t pmcid)
1923{
1924	struct pmcstat_cgnode *cgc;
1925
1926	/*
1927	 * Look for child nodes that belong to the same image.
1928	 */
1929
1930	LIST_FOREACH(cgc, &cg->pcg_children, pcg_sibling) {
1931		if (cgc->pcg_image == cg->pcg_image)
1932			pmcstat_gmon_append_arc(cg->pcg_image, pmcid,
1933			    cgc->pcg_func, cg->pcg_func, cgc->pcg_count);
1934		if (cgc->pcg_nchildren > 0)
1935			pmcstat_cgnode_do_gmon_arcs(cgc, pmcid);
1936	}
1937}
1938
1939static void
1940pmcstat_callgraph_do_gmon_arcs_for_pmcid(pmc_id_t pmcid)
1941{
1942	int n;
1943	struct pmcstat_cgnode_hash *pch;
1944
1945	for (n = 0; n < PMCSTAT_NHASH; n++)
1946		LIST_FOREACH(pch, &pmcstat_cgnode_hash[n], pch_next)
1947			if (pch->pch_pmcid == pmcid &&
1948			    pch->pch_cgnode->pcg_nchildren > 1)
1949				pmcstat_cgnode_do_gmon_arcs(pch->pch_cgnode,
1950				    pmcid);
1951}
1952
1953
1954static void
1955pmcstat_callgraph_do_gmon_arcs(void)
1956{
1957	struct pmcstat_pmcrecord *pmcr;
1958
1959	LIST_FOREACH(pmcr, &pmcstat_pmcs, pr_next)
1960		pmcstat_callgraph_do_gmon_arcs_for_pmcid(pmcr->pr_pmcid);
1961}
1962
1963/*
1964 * Convert a hwpmc(4) log to profile information.  A system-wide
1965 * callgraph is generated if FLAG_DO_CALLGRAPHS is set.  gmon.out
1966 * files usable by gprof(1) are created if FLAG_DO_GPROF is set.
1967 */
1968static int
1969pmcstat_analyze_log(struct pmcstat_args *a)
1970{
1971	uint32_t cpu, cpuflags;
1972	uintfptr_t pc, newpc;
1973	pid_t pid;
1974	struct pmcstat_image *image;
1975	struct pmcstat_symbol *sym;
1976	struct pmcstat_process *pp, *ppnew;
1977	struct pmcstat_pcmap *ppm, *ppmtmp;
1978	struct pmclog_ev ev;
1979	pmcstat_interned_string image_path;
1980
1981	assert(a->pa_flags & FLAG_DO_ANALYSIS);
1982
1983	if (elf_version(EV_CURRENT) == EV_NONE)
1984		err(EX_UNAVAILABLE, "Elf library intialization failed");
1985
1986	while (pmclog_read(a->pa_logparser, &ev) == 0) {
1987		assert(ev.pl_state == PMCLOG_OK);
1988
1989		switch (ev.pl_type) {
1990		case PMCLOG_TYPE_INITIALIZE:
1991			if ((ev.pl_u.pl_i.pl_version & 0xFF000000) !=
1992			    PMC_VERSION_MAJOR << 24 && a->pa_verbosity > 0)
1993				warnx("WARNING: Log version 0x%x does not "
1994				    "match compiled version 0x%x.",
1995				    ev.pl_u.pl_i.pl_version,
1996				    PMC_VERSION_MAJOR);
1997			break;
1998
1999		case PMCLOG_TYPE_MAP_IN:
2000			/*
2001			 * Introduce an address range mapping for a
2002			 * userland process or the kernel (pid == -1).
2003			 *
2004			 * We always allocate a process descriptor so
2005			 * that subsequent samples seen for this
2006			 * address range are mapped to the current
2007			 * object being mapped in.
2008			 */
2009			pid = ev.pl_u.pl_mi.pl_pid;
2010			if (pid == -1)
2011				pp = pmcstat_kernproc;
2012			else
2013				pp = pmcstat_process_lookup(pid,
2014				    PMCSTAT_ALLOCATE);
2015
2016			assert(pp != NULL);
2017
2018			image_path = pmcstat_string_intern(ev.pl_u.pl_mi.
2019			    pl_pathname);
2020			image = pmcstat_image_from_path(image_path, pid == -1);
2021			if (image->pi_type == PMCSTAT_IMAGE_UNKNOWN)
2022				pmcstat_image_determine_type(image, a);
2023			if (image->pi_type != PMCSTAT_IMAGE_INDETERMINABLE)
2024				pmcstat_image_link(pp, image,
2025				    ev.pl_u.pl_mi.pl_start);
2026			break;
2027
2028		case PMCLOG_TYPE_MAP_OUT:
2029			/*
2030			 * Remove an address map.
2031			 */
2032			pid = ev.pl_u.pl_mo.pl_pid;
2033			if (pid == -1)
2034				pp = pmcstat_kernproc;
2035			else
2036				pp = pmcstat_process_lookup(pid, 0);
2037
2038			if (pp == NULL)	/* unknown process */
2039				break;
2040
2041			pmcstat_image_unmap(pp, ev.pl_u.pl_mo.pl_start,
2042			    ev.pl_u.pl_mo.pl_end);
2043			break;
2044
2045		case PMCLOG_TYPE_PCSAMPLE:
2046			/*
2047			 * Note: the `PCSAMPLE' log entry is not
2048			 * generated by hpwmc(4) after version 2.
2049			 */
2050
2051			/*
2052			 * We bring in the gmon file for the image
2053			 * currently associated with the PMC & pid
2054			 * pair and increment the appropriate entry
2055			 * bin inside this.
2056			 */
2057			pmcstat_stats.ps_samples_total++;
2058
2059			pc = ev.pl_u.pl_s.pl_pc;
2060			pp = pmcstat_process_lookup(ev.pl_u.pl_s.pl_pid,
2061			    PMCSTAT_ALLOCATE);
2062			if ((ppm = pmcstat_process_find_map(pp, pc)) == NULL &&
2063			    (ppm = pmcstat_process_find_map(pmcstat_kernproc,
2064				pc)) == NULL) {	/* unknown process,offset pair */
2065				pmcstat_stats.ps_samples_unknown_offset++;
2066				break;
2067			}
2068
2069			pmcstat_image_increment_bucket(ppm, pc,
2070			    ev.pl_u.pl_s.pl_pmcid, a);
2071
2072			break;
2073
2074		case PMCLOG_TYPE_CALLCHAIN:
2075			pmcstat_stats.ps_samples_total++;
2076
2077			cpuflags = ev.pl_u.pl_cc.pl_cpuflags;
2078			cpu = PMC_CALLCHAIN_CPUFLAGS_TO_CPU(cpuflags);
2079
2080			/* Filter on the CPU id. */
2081			if ((a->pa_cpumask & (1 << cpu)) == 0) {
2082				pmcstat_stats.ps_samples_skipped++;
2083				break;
2084			}
2085
2086			pp = pmcstat_process_lookup(ev.pl_u.pl_cc.pl_pid,
2087			    PMCSTAT_ALLOCATE);
2088
2089			if ((a->pa_flags & FLAG_WANTS_MAPPINGS) == 0)
2090				pmcstat_record_callchain(pp,
2091				    ev.pl_u.pl_cc.pl_pmcid,
2092				    ev.pl_u.pl_cc.pl_npc, ev.pl_u.pl_cc.pl_pc,
2093			PMC_CALLCHAIN_CPUFLAGS_TO_USERMODE(cpuflags), a);
2094
2095			if ((a->pa_flags &
2096			    (FLAG_DO_GPROF | FLAG_WANTS_MAPPINGS)) == 0)
2097				break;
2098
2099			pc = ev.pl_u.pl_cc.pl_pc[0];
2100			if (PMC_CALLCHAIN_CPUFLAGS_TO_USERMODE(cpuflags) == 0)
2101				pp = pmcstat_kernproc;
2102			ppm = pmcstat_process_find_map(pp, pc);
2103			if (ppm == NULL) {
2104
2105				/* Unknown offset. */
2106				pmcstat_stats.ps_samples_unknown_offset++;
2107				break;
2108			}
2109			if (a->pa_flags & FLAG_WANTS_MAPPINGS) {
2110				image = ppm->ppm_image;
2111				newpc = pc - (ppm->ppm_lowpc +
2112				    (image->pi_vaddr - image->pi_start));
2113				sym = pmcstat_symbol_search(image, newpc);
2114				if (sym == NULL)
2115					break;
2116				fprintf(a->pa_graphfile, "%p %s 0x%jx 0x%jx\n",
2117				    (void *)pc,
2118				    pmcstat_string_unintern(sym->ps_name),
2119				    (uintmax_t)(sym->ps_start +
2120				    image->pi_vaddr), (uintmax_t)(sym->ps_end +
2121				    image->pi_vaddr));
2122				break;
2123			}
2124
2125			pmcstat_image_increment_bucket(ppm, pc,
2126			    ev.pl_u.pl_cc.pl_pmcid, a);
2127
2128			break;
2129
2130		case PMCLOG_TYPE_PMCALLOCATE:
2131			/*
2132			 * Record the association pmc id between this
2133			 * PMC and its name.
2134			 */
2135			pmcstat_pmcid_add(ev.pl_u.pl_a.pl_pmcid,
2136			    pmcstat_string_intern(ev.pl_u.pl_a.pl_evname), a);
2137			break;
2138
2139		case PMCLOG_TYPE_PROCEXEC:
2140
2141			/*
2142			 * Change the executable image associated with
2143			 * a process.
2144			 */
2145			pp = pmcstat_process_lookup(ev.pl_u.pl_x.pl_pid,
2146			    PMCSTAT_ALLOCATE);
2147
2148			/* delete the current process map */
2149			TAILQ_FOREACH_SAFE(ppm, &pp->pp_map, ppm_next, ppmtmp) {
2150				TAILQ_REMOVE(&pp->pp_map, ppm, ppm_next);
2151				free(ppm);
2152			}
2153
2154			/* associate this process  image */
2155			image_path = pmcstat_string_intern(
2156				ev.pl_u.pl_x.pl_pathname);
2157			assert(image_path != NULL);
2158			pmcstat_process_exec(pp, image_path,
2159			    ev.pl_u.pl_x.pl_entryaddr, a);
2160			break;
2161
2162		case PMCLOG_TYPE_PROCEXIT:
2163
2164			/*
2165			 * Due to the way the log is generated, the
2166			 * last few samples corresponding to a process
2167			 * may appear in the log after the process
2168			 * exit event is recorded.  Thus we keep the
2169			 * process' descriptor and associated data
2170			 * structures around, but mark the process as
2171			 * having exited.
2172			 */
2173			pp = pmcstat_process_lookup(ev.pl_u.pl_e.pl_pid, 0);
2174			if (pp == NULL)
2175				break;
2176			pp->pp_isactive = 0;	/* mark as a zombie */
2177			break;
2178
2179		case PMCLOG_TYPE_SYSEXIT:
2180			pp = pmcstat_process_lookup(ev.pl_u.pl_se.pl_pid, 0);
2181			if (pp == NULL)
2182				break;
2183			pp->pp_isactive = 0;	/* make a zombie */
2184			break;
2185
2186		case PMCLOG_TYPE_PROCFORK:
2187
2188			/*
2189			 * Allocate a process descriptor for the new
2190			 * (child) process.
2191			 */
2192			ppnew =
2193			    pmcstat_process_lookup(ev.pl_u.pl_f.pl_newpid,
2194				PMCSTAT_ALLOCATE);
2195
2196			/*
2197			 * If we had been tracking the parent, clone
2198			 * its address maps.
2199			 */
2200			pp = pmcstat_process_lookup(ev.pl_u.pl_f.pl_oldpid, 0);
2201			if (pp == NULL)
2202				break;
2203			TAILQ_FOREACH(ppm, &pp->pp_map, ppm_next)
2204			    pmcstat_image_link(ppnew, ppm->ppm_image,
2205				ppm->ppm_lowpc);
2206			break;
2207
2208		default:	/* other types of entries are not relevant */
2209			break;
2210		}
2211	}
2212
2213	if (ev.pl_state == PMCLOG_EOF)
2214		return (PMCSTAT_FINISHED);
2215	else if (ev.pl_state == PMCLOG_REQUIRE_DATA)
2216		return (PMCSTAT_RUNNING);
2217
2218	err(EX_DATAERR, "ERROR: event parsing failed (record %jd, "
2219	    "offset 0x%jx)", (uintmax_t) ev.pl_count + 1, ev.pl_offset);
2220}
2221
2222/*
2223 * Print log entries as text.
2224 */
2225
2226static int
2227pmcstat_print_log(struct pmcstat_args *a)
2228{
2229	struct pmclog_ev ev;
2230	uint32_t npc;
2231
2232	while (pmclog_read(a->pa_logparser, &ev) == 0) {
2233		assert(ev.pl_state == PMCLOG_OK);
2234		switch (ev.pl_type) {
2235		case PMCLOG_TYPE_CALLCHAIN:
2236			PMCSTAT_PRINT_ENTRY(a, "callchain",
2237			    "%d 0x%x %d %d %c", ev.pl_u.pl_cc.pl_pid,
2238			    ev.pl_u.pl_cc.pl_pmcid,
2239			    PMC_CALLCHAIN_CPUFLAGS_TO_CPU(ev.pl_u.pl_cc. \
2240				pl_cpuflags), ev.pl_u.pl_cc.pl_npc,
2241			    PMC_CALLCHAIN_CPUFLAGS_TO_USERMODE(ev.pl_u.pl_cc.\
2242			        pl_cpuflags) ? 'u' : 's');
2243			for (npc = 0; npc < ev.pl_u.pl_cc.pl_npc; npc++)
2244				PMCSTAT_PRINT_ENTRY(a, "...", "%p",
2245				    (void *) ev.pl_u.pl_cc.pl_pc[npc]);
2246			break;
2247		case PMCLOG_TYPE_CLOSELOG:
2248			PMCSTAT_PRINT_ENTRY(a,"closelog",);
2249			break;
2250		case PMCLOG_TYPE_DROPNOTIFY:
2251			PMCSTAT_PRINT_ENTRY(a,"drop",);
2252			break;
2253		case PMCLOG_TYPE_INITIALIZE:
2254			PMCSTAT_PRINT_ENTRY(a,"initlog","0x%x \"%s\"",
2255			    ev.pl_u.pl_i.pl_version,
2256			    pmc_name_of_cputype(ev.pl_u.pl_i.pl_arch));
2257			if ((ev.pl_u.pl_i.pl_version & 0xFF000000) !=
2258			    PMC_VERSION_MAJOR << 24 && a->pa_verbosity > 0)
2259				warnx("WARNING: Log version 0x%x != expected "
2260				    "version 0x%x.", ev.pl_u.pl_i.pl_version,
2261				    PMC_VERSION);
2262			break;
2263		case PMCLOG_TYPE_MAP_IN:
2264			PMCSTAT_PRINT_ENTRY(a,"map-in","%d %p \"%s\"",
2265			    ev.pl_u.pl_mi.pl_pid,
2266			    (void *) ev.pl_u.pl_mi.pl_start,
2267			    ev.pl_u.pl_mi.pl_pathname);
2268			break;
2269		case PMCLOG_TYPE_MAP_OUT:
2270			PMCSTAT_PRINT_ENTRY(a,"map-out","%d %p %p",
2271			    ev.pl_u.pl_mo.pl_pid,
2272			    (void *) ev.pl_u.pl_mo.pl_start,
2273			    (void *) ev.pl_u.pl_mo.pl_end);
2274			break;
2275		case PMCLOG_TYPE_PCSAMPLE:
2276			PMCSTAT_PRINT_ENTRY(a,"sample","0x%x %d %p %c",
2277			    ev.pl_u.pl_s.pl_pmcid,
2278			    ev.pl_u.pl_s.pl_pid,
2279			    (void *) ev.pl_u.pl_s.pl_pc,
2280			    ev.pl_u.pl_s.pl_usermode ? 'u' : 's');
2281			break;
2282		case PMCLOG_TYPE_PMCALLOCATE:
2283			PMCSTAT_PRINT_ENTRY(a,"allocate","0x%x \"%s\" 0x%x",
2284			    ev.pl_u.pl_a.pl_pmcid,
2285			    ev.pl_u.pl_a.pl_evname,
2286			    ev.pl_u.pl_a.pl_flags);
2287			break;
2288		case PMCLOG_TYPE_PMCATTACH:
2289			PMCSTAT_PRINT_ENTRY(a,"attach","0x%x %d \"%s\"",
2290			    ev.pl_u.pl_t.pl_pmcid,
2291			    ev.pl_u.pl_t.pl_pid,
2292			    ev.pl_u.pl_t.pl_pathname);
2293			break;
2294		case PMCLOG_TYPE_PMCDETACH:
2295			PMCSTAT_PRINT_ENTRY(a,"detach","0x%x %d",
2296			    ev.pl_u.pl_d.pl_pmcid,
2297			    ev.pl_u.pl_d.pl_pid);
2298			break;
2299		case PMCLOG_TYPE_PROCCSW:
2300			PMCSTAT_PRINT_ENTRY(a,"cswval","0x%x %d %jd",
2301			    ev.pl_u.pl_c.pl_pmcid,
2302			    ev.pl_u.pl_c.pl_pid,
2303			    ev.pl_u.pl_c.pl_value);
2304			break;
2305		case PMCLOG_TYPE_PROCEXEC:
2306			PMCSTAT_PRINT_ENTRY(a,"exec","0x%x %d %p \"%s\"",
2307			    ev.pl_u.pl_x.pl_pmcid,
2308			    ev.pl_u.pl_x.pl_pid,
2309			    (void *) ev.pl_u.pl_x.pl_entryaddr,
2310			    ev.pl_u.pl_x.pl_pathname);
2311			break;
2312		case PMCLOG_TYPE_PROCEXIT:
2313			PMCSTAT_PRINT_ENTRY(a,"exitval","0x%x %d %jd",
2314			    ev.pl_u.pl_e.pl_pmcid,
2315			    ev.pl_u.pl_e.pl_pid,
2316			    ev.pl_u.pl_e.pl_value);
2317			break;
2318		case PMCLOG_TYPE_PROCFORK:
2319			PMCSTAT_PRINT_ENTRY(a,"fork","%d %d",
2320			    ev.pl_u.pl_f.pl_oldpid,
2321			    ev.pl_u.pl_f.pl_newpid);
2322			break;
2323		case PMCLOG_TYPE_USERDATA:
2324			PMCSTAT_PRINT_ENTRY(a,"userdata","0x%x",
2325			    ev.pl_u.pl_u.pl_userdata);
2326			break;
2327		case PMCLOG_TYPE_SYSEXIT:
2328			PMCSTAT_PRINT_ENTRY(a,"exit","%d",
2329			    ev.pl_u.pl_se.pl_pid);
2330			break;
2331		default:
2332			fprintf(a->pa_printfile, "unknown event (type %d).\n",
2333			    ev.pl_type);
2334		}
2335	}
2336
2337	if (ev.pl_state == PMCLOG_EOF)
2338		return (PMCSTAT_FINISHED);
2339	else if (ev.pl_state ==  PMCLOG_REQUIRE_DATA)
2340		return (PMCSTAT_RUNNING);
2341
2342	errx(EX_DATAERR, "ERROR: event parsing failed "
2343	    "(record %jd, offset 0x%jx).",
2344	    (uintmax_t) ev.pl_count + 1, ev.pl_offset);
2345	/*NOTREACHED*/
2346}
2347
2348/*
2349 * Public Interfaces.
2350 */
2351
2352/*
2353 * Close a logfile, after first flushing all in-module queued data.
2354 */
2355
2356int
2357pmcstat_close_log(struct pmcstat_args *a)
2358{
2359	if (pmc_flush_logfile() < 0 ||
2360	    pmc_configure_logfile(-1) < 0)
2361		err(EX_OSERR, "ERROR: logging failed");
2362	a->pa_flags &= ~(FLAG_HAS_OUTPUT_LOGFILE | FLAG_HAS_PIPE);
2363	return (a->pa_flags & FLAG_HAS_PIPE ? PMCSTAT_EXITING :
2364	    PMCSTAT_FINISHED);
2365}
2366
2367
2368
2369/*
2370 * Open a log file, for reading or writing.
2371 *
2372 * The function returns the fd of a successfully opened log or -1 in
2373 * case of failure.
2374 */
2375
2376int
2377pmcstat_open_log(const char *path, int mode)
2378{
2379	int error, fd;
2380	size_t hlen;
2381	const char *p, *errstr;
2382	struct addrinfo hints, *res, *res0;
2383	char hostname[MAXHOSTNAMELEN];
2384
2385	errstr = NULL;
2386	fd = -1;
2387
2388	/*
2389	 * If 'path' is "-" then open one of stdin or stdout depending
2390	 * on the value of 'mode'.
2391	 *
2392	 * If 'path' contains a ':' and does not start with a '/' or '.',
2393	 * and is being opened for writing, treat it as a "host:port"
2394	 * specification and open a network socket.
2395	 *
2396	 * Otherwise, treat 'path' as a file name and open that.
2397	 */
2398	if (path[0] == '-' && path[1] == '\0')
2399		fd = (mode == PMCSTAT_OPEN_FOR_READ) ? 0 : 1;
2400	else if (mode == PMCSTAT_OPEN_FOR_WRITE && path[0] != '/' &&
2401	    path[0] != '.' && strchr(path, ':') != NULL) {
2402
2403		p = strrchr(path, ':');
2404		hlen = p - path;
2405		if (p == path || hlen >= sizeof(hostname)) {
2406			errstr = strerror(EINVAL);
2407			goto done;
2408		}
2409
2410		assert(hlen < sizeof(hostname));
2411		(void) strncpy(hostname, path, hlen);
2412		hostname[hlen] = '\0';
2413
2414		(void) memset(&hints, 0, sizeof(hints));
2415		hints.ai_family = AF_UNSPEC;
2416		hints.ai_socktype = SOCK_STREAM;
2417		if ((error = getaddrinfo(hostname, p+1, &hints, &res0)) != 0) {
2418			errstr = gai_strerror(error);
2419			goto done;
2420		}
2421
2422		fd = -1;
2423		for (res = res0; res; res = res->ai_next) {
2424			if ((fd = socket(res->ai_family, res->ai_socktype,
2425			    res->ai_protocol)) < 0) {
2426				errstr = strerror(errno);
2427				continue;
2428			}
2429			if (connect(fd, res->ai_addr, res->ai_addrlen) < 0) {
2430				errstr = strerror(errno);
2431				(void) close(fd);
2432				fd = -1;
2433				continue;
2434			}
2435			errstr = NULL;
2436			break;
2437		}
2438		freeaddrinfo(res0);
2439
2440	} else if ((fd = open(path, mode == PMCSTAT_OPEN_FOR_READ ?
2441		    O_RDONLY : (O_WRONLY|O_CREAT|O_TRUNC),
2442		    S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
2443			errstr = strerror(errno);
2444
2445  done:
2446	if (errstr)
2447		errx(EX_OSERR, "ERROR: Cannot open \"%s\" for %s: %s.", path,
2448		    (mode == PMCSTAT_OPEN_FOR_READ ? "reading" : "writing"),
2449		    errstr);
2450
2451	return (fd);
2452}
2453
2454/*
2455 * Process a log file in offline analysis mode.
2456 */
2457
2458int
2459pmcstat_process_log(struct pmcstat_args *a)
2460{
2461
2462	/*
2463	 * If analysis has not been asked for, just print the log to
2464	 * the current output file.
2465	 */
2466	if (a->pa_flags & FLAG_DO_PRINT)
2467		return (pmcstat_print_log(a));
2468	else
2469		return (pmcstat_analyze_log(a));
2470}
2471
2472/*
2473 * Initialize module.
2474 */
2475
2476void
2477pmcstat_initialize_logging(struct pmcstat_args *a)
2478{
2479	int i;
2480
2481	(void) a;
2482
2483	/* use a convenient format for 'ldd' output */
2484	if (setenv("LD_TRACE_LOADED_OBJECTS_FMT1","%o \"%p\" %x\n",1) != 0)
2485		err(EX_OSERR, "ERROR: Cannot setenv");
2486
2487	/* Initialize hash tables */
2488	pmcstat_string_initialize();
2489	for (i = 0; i < PMCSTAT_NHASH; i++) {
2490		LIST_INIT(&pmcstat_image_hash[i]);
2491		LIST_INIT(&pmcstat_process_hash[i]);
2492	}
2493
2494	/*
2495	 * Create a fake 'process' entry for the kernel with pid -1.
2496	 * hwpmc(4) will subsequently inform us about where the kernel
2497	 * and any loaded kernel modules are mapped.
2498	 */
2499	if ((pmcstat_kernproc = pmcstat_process_lookup((pid_t) -1,
2500		 PMCSTAT_ALLOCATE)) == NULL)
2501		err(EX_OSERR, "ERROR: Cannot initialize logging");
2502}
2503
2504/*
2505 * Shutdown module.
2506 */
2507
2508void
2509pmcstat_shutdown_logging(struct pmcstat_args *a)
2510{
2511	int i;
2512	FILE *mf;
2513	struct pmcstat_gmonfile *pgf, *pgftmp;
2514	struct pmcstat_image *pi, *pitmp;
2515	struct pmcstat_process *pp, *pptmp;
2516	struct pmcstat_cgnode_hash *pch, *pchtmp;
2517
2518	/* determine where to send the map file */
2519	mf = NULL;
2520	if (a->pa_mapfilename != NULL)
2521		mf = (strcmp(a->pa_mapfilename, "-") == 0) ?
2522		    a->pa_printfile : fopen(a->pa_mapfilename, "w");
2523
2524	if (mf == NULL && a->pa_flags & FLAG_DO_GPROF &&
2525	    a->pa_verbosity >= 2)
2526		mf = a->pa_printfile;
2527
2528	if (mf)
2529		(void) fprintf(mf, "MAP:\n");
2530
2531
2532	if (a->pa_flags & FLAG_DO_CALLGRAPHS)
2533		pmcstat_callgraph_print(a);
2534
2535	/*
2536	 * Sync back all gprof flat profile data.
2537	 */
2538	for (i = 0; i < PMCSTAT_NHASH; i++) {
2539		LIST_FOREACH(pi, &pmcstat_image_hash[i], pi_next) {
2540			if (mf)
2541				(void) fprintf(mf, " \"%s\" => \"%s\"",
2542				    pmcstat_string_unintern(pi->pi_execpath),
2543				    pmcstat_string_unintern(
2544				    pi->pi_samplename));
2545
2546			/* flush gmon.out data to disk */
2547			LIST_FOREACH(pgf, &pi->pi_gmlist, pgf_next) {
2548				pmcstat_gmon_unmap_file(pgf);
2549				if (mf)
2550					(void) fprintf(mf, " %s/%d",
2551					    pmcstat_pmcid_to_name(
2552					    pgf->pgf_pmcid),
2553					    pgf->pgf_nsamples);
2554				if (pgf->pgf_overflow && a->pa_verbosity >= 1)
2555					warnx("WARNING: profile \"%s\" "
2556					    "overflowed.",
2557					    pmcstat_string_unintern(
2558					        pgf->pgf_name));
2559			}
2560
2561			if (mf)
2562				(void) fprintf(mf, "\n");
2563		}
2564	}
2565
2566	/*
2567	 * Compute arcs and add these to the gprof files.
2568	 */
2569	if (a->pa_flags & FLAG_DO_GPROF && a->pa_graphdepth > 1)
2570		pmcstat_callgraph_do_gmon_arcs();
2571
2572	/*
2573	 * Free memory.
2574	 */
2575	for (i = 0; i < PMCSTAT_NHASH; i++) {
2576		LIST_FOREACH_SAFE(pch, &pmcstat_cgnode_hash[i], pch_next,
2577		    pchtmp) {
2578			pmcstat_cgnode_free(pch->pch_cgnode);
2579			free(pch);
2580		}
2581	}
2582
2583	for (i = 0; i < PMCSTAT_NHASH; i++) {
2584		LIST_FOREACH_SAFE(pi, &pmcstat_image_hash[i], pi_next, pitmp)
2585		{
2586			LIST_FOREACH_SAFE(pgf, &pi->pi_gmlist, pgf_next,
2587			    pgftmp) {
2588				if (pgf->pgf_file)
2589					(void) fclose(pgf->pgf_file);
2590				LIST_REMOVE(pgf, pgf_next);
2591				free(pgf);
2592			}
2593			if (pi->pi_symbols)
2594				free(pi->pi_symbols);
2595
2596			LIST_REMOVE(pi, pi_next);
2597			free(pi);
2598		}
2599
2600		LIST_FOREACH_SAFE(pp, &pmcstat_process_hash[i], pp_next,
2601		    pptmp) {
2602			LIST_REMOVE(pp, pp_next);
2603			free(pp);
2604		}
2605	}
2606
2607	pmcstat_string_shutdown();
2608
2609	/*
2610	 * Print errors unless -q was specified.  Print all statistics
2611	 * if verbosity > 1.
2612	 */
2613#define	PRINT(N,V,A) do {						\
2614		if (pmcstat_stats.ps_##V || (A)->pa_verbosity >= 2)	\
2615			(void) fprintf((A)->pa_printfile, " %-40s %d\n",\
2616			    N, pmcstat_stats.ps_##V);			\
2617	} while (0)
2618
2619	if (a->pa_verbosity >= 1 && a->pa_flags & FLAG_DO_GPROF) {
2620		(void) fprintf(a->pa_printfile, "CONVERSION STATISTICS:\n");
2621		PRINT("#exec/a.out", exec_aout, a);
2622		PRINT("#exec/elf", exec_elf, a);
2623		PRINT("#exec/unknown", exec_indeterminable, a);
2624		PRINT("#exec handling errors", exec_errors, a);
2625		PRINT("#samples/total", samples_total, a);
2626		PRINT("#samples/unclaimed", samples_unknown_offset, a);
2627		PRINT("#samples/unknown-object", samples_indeterminable, a);
2628		PRINT("#callchain/dubious-frames", callchain_dubious_frames,
2629		    a);
2630	}
2631
2632	if (mf)
2633		(void) fclose(mf);
2634}
2635