]> CyberLeo.Net >> Repos - FreeBSD/releng/8.0.git/blob - usr.sbin/pmcstat/pmcstat_log.c
Adjust to reflect 8.0-RELEASE.
[FreeBSD/releng/8.0.git] / usr.sbin / pmcstat / pmcstat_log.c
1 /*-
2  * Copyright (c) 2005-2007, Joseph Koshy
3  * Copyright (c) 2007 The FreeBSD Foundation
4  * All rights reserved.
5  *
6  * Portions of this software were developed by A. Joseph Koshy under
7  * sponsorship from the FreeBSD Foundation and Google, Inc.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30
31 /*
32  * Transform a hwpmc(4) log into human readable form, and into
33  * gprof(1) compatible profiles.
34  */
35
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38
39 #include <sys/param.h>
40 #include <sys/endian.h>
41 #include <sys/gmon.h>
42 #include <sys/imgact_aout.h>
43 #include <sys/imgact_elf.h>
44 #include <sys/mman.h>
45 #include <sys/pmc.h>
46 #include <sys/queue.h>
47 #include <sys/socket.h>
48 #include <sys/stat.h>
49 #include <sys/wait.h>
50
51 #include <netinet/in.h>
52
53 #include <assert.h>
54 #include <err.h>
55 #include <errno.h>
56 #include <fcntl.h>
57 #include <gelf.h>
58 #include <libgen.h>
59 #include <limits.h>
60 #include <netdb.h>
61 #include <pmc.h>
62 #include <pmclog.h>
63 #include <sysexits.h>
64 #include <stdint.h>
65 #include <stdio.h>
66 #include <stdlib.h>
67 #include <string.h>
68 #include <unistd.h>
69
70 #include "pmcstat.h"
71
72 #define min(A,B)                ((A) < (B) ? (A) : (B))
73 #define max(A,B)                ((A) > (B) ? (A) : (B))
74
75 #define PMCSTAT_ALLOCATE                1
76
77 /*
78  * PUBLIC INTERFACES
79  *
80  * pmcstat_initialize_logging() initialize this module, called first
81  * pmcstat_shutdown_logging()           orderly shutdown, called last
82  * pmcstat_open_log()                   open an eventlog for processing
83  * pmcstat_process_log()                print/convert an event log
84  * pmcstat_close_log()                  finish processing an event log
85  *
86  * IMPLEMENTATION NOTES
87  *
88  * We correlate each 'callchain' or 'sample' entry seen in the event
89  * log back to an executable object in the system. Executable objects
90  * include:
91  *      - program executables,
92  *      - shared libraries loaded by the runtime loader,
93  *      - dlopen()'ed objects loaded by the program,
94  *      - the runtime loader itself,
95  *      - the kernel and kernel modules.
96  *
97  * Each process that we know about is treated as a set of regions that
98  * map to executable objects.  Processes are described by
99  * 'pmcstat_process' structures.  Executable objects are tracked by
100  * 'pmcstat_image' structures.  The kernel and kernel modules are
101  * common to all processes (they reside at the same virtual addresses
102  * for all processes).  Individual processes can have their text
103  * segments and shared libraries loaded at process-specific locations.
104  *
105  * A given executable object can be in use by multiple processes
106  * (e.g., libc.so) and loaded at a different address in each.
107  * pmcstat_pcmap structures track per-image mappings.
108  *
109  * The sample log could have samples from multiple PMCs; we
110  * generate one 'gmon.out' profile per PMC.
111  *
112  * IMPLEMENTATION OF GMON OUTPUT
113  *
114  * Each executable object gets one 'gmon.out' profile, per PMC in
115  * use.  Creation of 'gmon.out' profiles is done lazily.  The
116  * 'gmon.out' profiles generated for a given sampling PMC are
117  * aggregates of all the samples for that particular executable
118  * object.
119  *
120  * IMPLEMENTATION OF SYSTEM-WIDE CALLGRAPH OUTPUT
121  *
122  * Each active pmcid has its own callgraph structure, described by a
123  * 'struct pmcstat_callgraph'.  Given a process id and a list of pc
124  * values, we map each pc value to a tuple (image, symbol), where
125  * 'image' denotes an executable object and 'symbol' is the closest
126  * symbol that precedes the pc value.  Each pc value in the list is
127  * also given a 'rank' that reflects its depth in the call stack.
128  */
129
130 typedef const void *pmcstat_interned_string;
131
132 /*
133  * 'pmcstat_pmcrecord' is a mapping from PMC ids to human-readable
134  * names.
135  */
136
137 struct pmcstat_pmcrecord {
138         LIST_ENTRY(pmcstat_pmcrecord)   pr_next;
139         pmc_id_t                        pr_pmcid;
140         pmcstat_interned_string pr_pmcname;
141 };
142
143 static LIST_HEAD(,pmcstat_pmcrecord)    pmcstat_pmcs =
144         LIST_HEAD_INITIALIZER(&pmcstat_pmcs);
145
146
147 /*
148  * struct pmcstat_gmonfile tracks a given 'gmon.out' file.  These
149  * files are mmap()'ed in as needed.
150  */
151
152 struct pmcstat_gmonfile {
153         LIST_ENTRY(pmcstat_gmonfile)    pgf_next; /* list of entries */
154         int             pgf_overflow;   /* whether a count overflowed */
155         pmc_id_t        pgf_pmcid;      /* id of the associated pmc */
156         size_t          pgf_nbuckets;   /* #buckets in this gmon.out */
157         unsigned int    pgf_nsamples;   /* #samples in this gmon.out */
158         pmcstat_interned_string pgf_name;       /* pathname of gmon.out file */
159         size_t          pgf_ndatabytes; /* number of bytes mapped */
160         void            *pgf_gmondata;  /* pointer to mmap'ed data */
161         FILE            *pgf_file;      /* used when writing gmon arcs */
162 };
163
164 /*
165  * A 'pmcstat_image' structure describes an executable program on
166  * disk.  'pi_execpath' is a cookie representing the pathname of
167  * the executable.  'pi_start' and 'pi_end' are the least and greatest
168  * virtual addresses for the text segments in the executable.
169  * 'pi_gmonlist' contains a linked list of gmon.out files associated
170  * with this image.
171  */
172
173 enum pmcstat_image_type {
174         PMCSTAT_IMAGE_UNKNOWN = 0,      /* never looked at the image */
175         PMCSTAT_IMAGE_INDETERMINABLE,   /* can't tell what the image is */
176         PMCSTAT_IMAGE_ELF32,            /* ELF 32 bit object */
177         PMCSTAT_IMAGE_ELF64,            /* ELF 64 bit object */
178         PMCSTAT_IMAGE_AOUT              /* AOUT object */
179 };
180
181 struct pmcstat_image {
182         LIST_ENTRY(pmcstat_image) pi_next;      /* hash link */
183         TAILQ_ENTRY(pmcstat_image) pi_lru;      /* LRU list */
184         pmcstat_interned_string pi_execpath;    /* cookie */
185         pmcstat_interned_string pi_samplename;  /* sample path name */
186         pmcstat_interned_string pi_fullpath;    /* path to FS object */
187
188         enum pmcstat_image_type pi_type;        /* executable type */
189
190         /*
191          * Executables have pi_start and pi_end; these are zero
192          * for shared libraries.
193          */
194         uintfptr_t      pi_start;       /* start address (inclusive) */
195         uintfptr_t      pi_end;         /* end address (exclusive) */
196         uintfptr_t      pi_entry;       /* entry address */
197         uintfptr_t      pi_vaddr;       /* virtual address where loaded */
198         int             pi_isdynamic;   /* whether a dynamic object */
199         int             pi_iskernelmodule;
200         pmcstat_interned_string pi_dynlinkerpath; /* path in .interp */
201
202         /* All symbols associated with this object. */
203         struct pmcstat_symbol *pi_symbols;
204         size_t          pi_symcount;
205
206         /*
207          * An image can be associated with one or more gmon.out files;
208          * one per PMC.
209          */
210         LIST_HEAD(,pmcstat_gmonfile) pi_gmlist;
211 };
212
213 /*
214  * All image descriptors are kept in a hash table.
215  */
216 static LIST_HEAD(,pmcstat_image)        pmcstat_image_hash[PMCSTAT_NHASH];
217
218 /*
219  * A 'pmcstat_pcmap' structure maps a virtual address range to an
220  * underlying 'pmcstat_image' descriptor.
221  */
222 struct pmcstat_pcmap {
223         TAILQ_ENTRY(pmcstat_pcmap) ppm_next;
224         uintfptr_t      ppm_lowpc;
225         uintfptr_t      ppm_highpc;
226         struct pmcstat_image *ppm_image;
227 };
228
229 /*
230  * A 'pmcstat_process' structure models processes.  Each process is
231  * associated with a set of pmcstat_pcmap structures that map
232  * addresses inside it to executable objects.  This set is implemented
233  * as a list, kept sorted in ascending order of mapped addresses.
234  *
235  * 'pp_pid' holds the pid of the process.  When a process exits, the
236  * 'pp_isactive' field is set to zero, but the process structure is
237  * not immediately reclaimed because there may still be samples in the
238  * log for this process.
239  */
240
241 struct pmcstat_process {
242         LIST_ENTRY(pmcstat_process) pp_next;    /* hash-next */
243         pid_t                   pp_pid;         /* associated pid */
244         int                     pp_isactive;    /* whether active */
245         uintfptr_t              pp_entryaddr;   /* entry address */
246         TAILQ_HEAD(,pmcstat_pcmap) pp_map;      /* address range map */
247 };
248
249 /*
250  * All process descriptors are kept in a hash table.
251  */
252 static LIST_HEAD(,pmcstat_process) pmcstat_process_hash[PMCSTAT_NHASH];
253
254 static struct pmcstat_process *pmcstat_kernproc; /* kernel 'process' */
255
256 /*
257  * Each function symbol tracked by pmcstat(8).
258  */
259
260 struct pmcstat_symbol {
261         pmcstat_interned_string ps_name;
262         uint64_t        ps_start;
263         uint64_t        ps_end;
264 };
265
266 /*
267  * Each call graph node is tracked by a pmcstat_cgnode struct.
268  */
269
270 struct pmcstat_cgnode {
271         struct pmcstat_image    *pcg_image;
272         uintfptr_t              pcg_func;
273         uint32_t                pcg_count;
274         uint32_t                pcg_nchildren;
275         LIST_ENTRY(pmcstat_cgnode) pcg_sibling;
276         LIST_HEAD(,pmcstat_cgnode) pcg_children;
277 };
278
279 struct pmcstat_cgnode_hash {
280         struct pmcstat_cgnode  *pch_cgnode;
281         uint32_t                pch_pmcid;
282         LIST_ENTRY(pmcstat_cgnode_hash) pch_next;
283 };
284
285 static int pmcstat_cgnode_hash_count;
286 static 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
292 static LIST_HEAD(,pmcstat_cgnode_hash) pmcstat_cgnode_hash[PMCSTAT_NHASH];
293
294 /* Misc. statistics */
295 static 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
312 static void     pmcstat_gmon_create_file(struct pmcstat_gmonfile *_pgf,
313     struct pmcstat_image *_image);
314 static pmcstat_interned_string pmcstat_gmon_create_name(const char *_sd,
315     struct pmcstat_image *_img, pmc_id_t _pmcid);
316 static void     pmcstat_gmon_map_file(struct pmcstat_gmonfile *_pgf);
317 static void     pmcstat_gmon_unmap_file(struct pmcstat_gmonfile *_pgf);
318
319 static void pmcstat_image_determine_type(struct pmcstat_image *_image,
320     struct pmcstat_args *_a);
321 static struct pmcstat_gmonfile *pmcstat_image_find_gmonfile(struct
322     pmcstat_image *_i, pmc_id_t _id);
323 static struct pmcstat_image *pmcstat_image_from_path(pmcstat_interned_string
324     _path, int _iskernelmodule);
325 static void pmcstat_image_get_aout_params(struct pmcstat_image *_image,
326     struct pmcstat_args *_a);
327 static void pmcstat_image_get_elf_params(struct pmcstat_image *_image,
328     struct pmcstat_args *_a);
329 static void     pmcstat_image_increment_bucket(struct pmcstat_pcmap *_pcm,
330     uintfptr_t _pc, pmc_id_t _pmcid, struct pmcstat_args *_a);
331 static void     pmcstat_image_link(struct pmcstat_process *_pp,
332     struct pmcstat_image *_i, uintfptr_t _lpc);
333
334 static void     pmcstat_pmcid_add(pmc_id_t _pmcid,
335     pmcstat_interned_string _name, struct pmcstat_args *_a);
336 static const char *pmcstat_pmcid_to_name(pmc_id_t _pmcid);
337
338 static void     pmcstat_process_aout_exec(struct pmcstat_process *_pp,
339     struct pmcstat_image *_image, uintfptr_t _entryaddr,
340     struct pmcstat_args *_a);
341 static void     pmcstat_process_elf_exec(struct pmcstat_process *_pp,
342     struct pmcstat_image *_image, uintfptr_t _entryaddr,
343     struct pmcstat_args *_a);
344 static void     pmcstat_process_exec(struct pmcstat_process *_pp,
345     pmcstat_interned_string _path, uintfptr_t _entryaddr,
346     struct pmcstat_args *_ao);
347 static struct pmcstat_process *pmcstat_process_lookup(pid_t _pid,
348     int _allocate);
349 static struct pmcstat_pcmap *pmcstat_process_find_map(
350     struct pmcstat_process *_p, uintfptr_t _pc);
351
352 static int      pmcstat_string_compute_hash(const char *_string);
353 static void pmcstat_string_initialize(void);
354 static pmcstat_interned_string pmcstat_string_intern(const char *_s);
355 static pmcstat_interned_string pmcstat_string_lookup(const char *_s);
356 static int      pmcstat_string_lookup_hash(pmcstat_interned_string _is);
357 static void pmcstat_string_shutdown(void);
358 static 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  */
368 struct 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
375 static LIST_HEAD(,pmcstat_string)       pmcstat_string_hash[PMCSTAT_NHASH];
376
377 /*
378  * Compute a 'hash' value for a string.
379  */
380
381 static int
382 pmcstat_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
397 static pmcstat_interned_string
398 pmcstat_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
419 static const char *
420 pmcstat_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
428 static pmcstat_interned_string
429 pmcstat_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
444 static int
445 pmcstat_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
457 static void
458 pmcstat_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
470 static void
471 pmcstat_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
489 static void
490 pmcstat_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
543 pmcstat_interned_string
544 pmcstat_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
564 static void
565 pmcstat_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
589 static void
590 pmcstat_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
598 static void
599 pmcstat_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
623 static struct pmcstat_gmonfile *
624 pmcstat_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
640 static void
641 pmcstat_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
686 static int
687 pmcstat_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
705 static struct pmcstat_symbol *
706 pmcstat_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  */
726 static void
727 pmcstat_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
827 static void
828 pmcstat_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
975 static void
976 pmcstat_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
1005 static struct pmcstat_image *
1006 pmcstat_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
1096 static void
1097 pmcstat_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
1184 static void
1185 pmcstat_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
1225 static void
1226 pmcstat_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
1290 static void
1291 pmcstat_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
1332 static const char *
1333 pmcstat_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
1359 static void
1360 pmcstat_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
1375 static void
1376 pmcstat_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
1450 static struct pmcstat_process *
1451 pmcstat_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
1496 static void
1497 pmcstat_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
1540 static struct pmcstat_pcmap *
1541 pmcstat_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
1555 static struct pmcstat_cgnode *
1556 pmcstat_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  */
1576 static void
1577 pmcstat_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  */
1591 static struct pmcstat_cgnode *
1592 pmcstat_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  */
1658 static int
1659 pmcstat_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
1681 static struct pmcstat_cgnode *
1682 pmcstat_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  */
1713 static void
1714 pmcstat_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
1786 static void
1787 pmcstat_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  */
1851 static void
1852 pmcstat_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
1912 static void
1913 pmcstat_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
1921 static void
1922 pmcstat_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
1939 static void
1940 pmcstat_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
1954 static void
1955 pmcstat_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  */
1968 static int
1969 pmcstat_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
2226 static int
2227 pmcstat_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
2356 int
2357 pmcstat_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
2376 int
2377 pmcstat_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
2458 int
2459 pmcstat_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
2476 void
2477 pmcstat_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
2508 void
2509 pmcstat_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 }