]> CyberLeo.Net >> Repos - FreeBSD/releng/8.2.git/blob - usr.sbin/pmcstat/pmcstat_log.c
MFC r216824:
[FreeBSD/releng/8.2.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 <curses.h>
55 #include <err.h>
56 #include <errno.h>
57 #include <fcntl.h>
58 #include <gelf.h>
59 #include <libgen.h>
60 #include <limits.h>
61 #include <netdb.h>
62 #include <pmc.h>
63 #include <pmclog.h>
64 #include <sysexits.h>
65 #include <stdint.h>
66 #include <stdio.h>
67 #include <stdlib.h>
68 #include <string.h>
69 #include <unistd.h>
70
71 #include "pmcstat.h"
72 #include "pmcstat_log.h"
73 #include "pmcstat_top.h"
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_display_log()                top mode display for the log
85  * pmcstat_close_log()                  finish processing an event log
86  *
87  * IMPLEMENTATION NOTES
88  *
89  * We correlate each 'callchain' or 'sample' entry seen in the event
90  * log back to an executable object in the system. Executable objects
91  * include:
92  *      - program executables,
93  *      - shared libraries loaded by the runtime loader,
94  *      - dlopen()'ed objects loaded by the program,
95  *      - the runtime loader itself,
96  *      - the kernel and kernel modules.
97  *
98  * Each process that we know about is treated as a set of regions that
99  * map to executable objects.  Processes are described by
100  * 'pmcstat_process' structures.  Executable objects are tracked by
101  * 'pmcstat_image' structures.  The kernel and kernel modules are
102  * common to all processes (they reside at the same virtual addresses
103  * for all processes).  Individual processes can have their text
104  * segments and shared libraries loaded at process-specific locations.
105  *
106  * A given executable object can be in use by multiple processes
107  * (e.g., libc.so) and loaded at a different address in each.
108  * pmcstat_pcmap structures track per-image mappings.
109  *
110  * The sample log could have samples from multiple PMCs; we
111  * generate one 'gmon.out' profile per PMC.
112  *
113  * IMPLEMENTATION OF GMON OUTPUT
114  *
115  * Each executable object gets one 'gmon.out' profile, per PMC in
116  * use.  Creation of 'gmon.out' profiles is done lazily.  The
117  * 'gmon.out' profiles generated for a given sampling PMC are
118  * aggregates of all the samples for that particular executable
119  * object.
120  *
121  * IMPLEMENTATION OF SYSTEM-WIDE CALLGRAPH OUTPUT
122  *
123  * Each active pmcid has its own callgraph structure, described by a
124  * 'struct pmcstat_callgraph'.  Given a process id and a list of pc
125  * values, we map each pc value to a tuple (image, symbol), where
126  * 'image' denotes an executable object and 'symbol' is the closest
127  * symbol that precedes the pc value.  Each pc value in the list is
128  * also given a 'rank' that reflects its depth in the call stack.
129  */
130
131 struct pmcstat_pmcs pmcstat_pmcs = LIST_HEAD_INITIALIZER(pmcstat_pmcs);
132
133 /*
134  * All image descriptors are kept in a hash table.
135  */
136 struct pmcstat_image_hash_list pmcstat_image_hash[PMCSTAT_NHASH];
137
138 /*
139  * All process descriptors are kept in a hash table.
140  */
141 struct pmcstat_process_hash_list pmcstat_process_hash[PMCSTAT_NHASH];
142
143 struct pmcstat_stats pmcstat_stats; /* statistics */
144 int ps_samples_period; /* samples count between top refresh. */
145
146 struct pmcstat_process *pmcstat_kernproc; /* kernel 'process' */
147
148 #include "pmcpl_gprof.h"
149 #include "pmcpl_callgraph.h"
150 #include "pmcpl_annotate.h"
151 #include "pmcpl_calltree.h"
152
153 struct pmc_plugins  {
154         const char      *pl_name;       /* name */
155
156         /* configure */
157         int (*pl_configure)(char *opt);
158
159         /* init and shutdown */
160         int (*pl_init)(void);
161         void (*pl_shutdown)(FILE *mf);
162
163         /* sample processing */
164         void (*pl_process)(struct pmcstat_process *pp,
165             struct pmcstat_pmcrecord *pmcr, uint32_t nsamples,
166             uintfptr_t *cc, int usermode, uint32_t cpu);
167
168         /* image */
169         void (*pl_initimage)(struct pmcstat_image *pi);
170         void (*pl_shutdownimage)(struct pmcstat_image *pi);
171
172         /* pmc */
173         void (*pl_newpmc)(pmcstat_interned_string ps,
174                 struct pmcstat_pmcrecord *pr);
175         
176         /* top display */
177         void (*pl_topdisplay)(void);
178
179         /* top keypress */
180         int (*pl_topkeypress)(int c, WINDOW *w);
181
182 } plugins[] = {
183         {
184                 .pl_name                = "none",
185         },
186         {
187                 .pl_name                = "callgraph",
188                 .pl_init                = pmcpl_cg_init,
189                 .pl_shutdown            = pmcpl_cg_shutdown,
190                 .pl_process             = pmcpl_cg_process,
191                 .pl_topkeypress         = pmcpl_cg_topkeypress,
192                 .pl_topdisplay          = pmcpl_cg_topdisplay
193         },
194         {
195                 .pl_name                = "gprof",
196                 .pl_shutdown            = pmcpl_gmon_shutdown,
197                 .pl_process             = pmcpl_gmon_process,
198                 .pl_initimage           = pmcpl_gmon_initimage,
199                 .pl_shutdownimage       = pmcpl_gmon_shutdownimage,
200                 .pl_newpmc              = pmcpl_gmon_newpmc
201         },
202         {
203                 .pl_name                = "annotate",
204                 .pl_process             = pmcpl_annotate_process
205         },
206         {
207                 .pl_name                = "calltree",
208                 .pl_configure           = pmcpl_ct_configure,
209                 .pl_init                = pmcpl_ct_init,
210                 .pl_shutdown            = pmcpl_ct_shutdown,
211                 .pl_process             = pmcpl_ct_process,
212                 .pl_topkeypress         = pmcpl_ct_topkeypress,
213                 .pl_topdisplay          = pmcpl_ct_topdisplay
214         },
215         {
216                 .pl_name                = NULL
217         }
218 };
219
220 int pmcstat_mergepmc;
221
222 int pmcstat_pmcinfilter = 0; /* PMC filter for top mode. */
223 float pmcstat_threshold = 0.5; /* Cost filter for top mode. */
224
225 /*
226  * Prototypes
227  */
228
229 static struct pmcstat_image *pmcstat_image_from_path(pmcstat_interned_string
230     _path, int _iskernelmodule);
231 static void pmcstat_image_get_aout_params(struct pmcstat_image *_image);
232 static void pmcstat_image_get_elf_params(struct pmcstat_image *_image);
233 static void     pmcstat_image_link(struct pmcstat_process *_pp,
234     struct pmcstat_image *_i, uintfptr_t _lpc);
235
236 static void     pmcstat_pmcid_add(pmc_id_t _pmcid,
237     pmcstat_interned_string _name);
238
239 static void     pmcstat_process_aout_exec(struct pmcstat_process *_pp,
240     struct pmcstat_image *_image, uintfptr_t _entryaddr);
241 static void     pmcstat_process_elf_exec(struct pmcstat_process *_pp,
242     struct pmcstat_image *_image, uintfptr_t _entryaddr);
243 static void     pmcstat_process_exec(struct pmcstat_process *_pp,
244     pmcstat_interned_string _path, uintfptr_t _entryaddr);
245 static struct pmcstat_process *pmcstat_process_lookup(pid_t _pid,
246     int _allocate);
247 static int      pmcstat_string_compute_hash(const char *_string);
248 static void pmcstat_string_initialize(void);
249 static int      pmcstat_string_lookup_hash(pmcstat_interned_string _is);
250 static void pmcstat_string_shutdown(void);
251 static void pmcstat_stats_reset(int _reset_global);
252
253 /*
254  * A simple implementation of interned strings.  Each interned string
255  * is assigned a unique address, so that subsequent string compares
256  * can be done by a simple pointer comparision instead of using
257  * strcmp().  This speeds up hash table lookups and saves memory if
258  * duplicate strings are the norm.
259  */
260 struct pmcstat_string {
261         LIST_ENTRY(pmcstat_string)      ps_next;        /* hash link */
262         int             ps_len;
263         int             ps_hash;
264         char            *ps_string;
265 };
266
267 static LIST_HEAD(,pmcstat_string)       pmcstat_string_hash[PMCSTAT_NHASH];
268
269 /*
270  * PMC count.
271  */
272 int pmcstat_npmcs;
273
274 /*
275  * PMC Top mode pause state.
276  */
277 int pmcstat_pause;
278
279 static void
280 pmcstat_stats_reset(int reset_global)
281 {
282         struct pmcstat_pmcrecord *pr;
283
284         /* Flush PMCs stats. */
285         LIST_FOREACH(pr, &pmcstat_pmcs, pr_next) {
286                 pr->pr_samples = 0;
287                 pr->pr_dubious_frames = 0;
288         }
289         ps_samples_period = 0;
290
291         /* Flush global stats. */
292         if (reset_global)
293                 bzero(&pmcstat_stats, sizeof(struct pmcstat_stats));
294 }
295
296 /*
297  * Compute a 'hash' value for a string.
298  */
299
300 static int
301 pmcstat_string_compute_hash(const char *s)
302 {
303         int hash;
304
305         for (hash = 0; *s; s++)
306                 hash ^= *s;
307
308         return (hash & PMCSTAT_HASH_MASK);
309 }
310
311 /*
312  * Intern a copy of string 's', and return a pointer to the
313  * interned structure.
314  */
315
316 pmcstat_interned_string
317 pmcstat_string_intern(const char *s)
318 {
319         struct pmcstat_string *ps;
320         const struct pmcstat_string *cps;
321         int hash, len;
322
323         if ((cps = pmcstat_string_lookup(s)) != NULL)
324                 return (cps);
325
326         hash = pmcstat_string_compute_hash(s);
327         len  = strlen(s);
328
329         if ((ps = malloc(sizeof(*ps))) == NULL)
330                 err(EX_OSERR, "ERROR: Could not intern string");
331         ps->ps_len = len;
332         ps->ps_hash = hash;
333         ps->ps_string = strdup(s);
334         LIST_INSERT_HEAD(&pmcstat_string_hash[hash], ps, ps_next);
335         return ((pmcstat_interned_string) ps);
336 }
337
338 const char *
339 pmcstat_string_unintern(pmcstat_interned_string str)
340 {
341         const char *s;
342
343         s = ((const struct pmcstat_string *) str)->ps_string;
344         return (s);
345 }
346
347 pmcstat_interned_string
348 pmcstat_string_lookup(const char *s)
349 {
350         struct pmcstat_string *ps;
351         int hash, len;
352
353         hash = pmcstat_string_compute_hash(s);
354         len = strlen(s);
355
356         LIST_FOREACH(ps, &pmcstat_string_hash[hash], ps_next)
357             if (ps->ps_len == len && ps->ps_hash == hash &&
358                 strcmp(ps->ps_string, s) == 0)
359                     return (ps);
360         return (NULL);
361 }
362
363 static int
364 pmcstat_string_lookup_hash(pmcstat_interned_string s)
365 {
366         const struct pmcstat_string *ps;
367
368         ps = (const struct pmcstat_string *) s;
369         return (ps->ps_hash);
370 }
371
372 /*
373  * Initialize the string interning facility.
374  */
375
376 static void
377 pmcstat_string_initialize(void)
378 {
379         int i;
380
381         for (i = 0; i < PMCSTAT_NHASH; i++)
382                 LIST_INIT(&pmcstat_string_hash[i]);
383 }
384
385 /*
386  * Destroy the string table, free'ing up space.
387  */
388
389 static void
390 pmcstat_string_shutdown(void)
391 {
392         int i;
393         struct pmcstat_string *ps, *pstmp;
394
395         for (i = 0; i < PMCSTAT_NHASH; i++)
396                 LIST_FOREACH_SAFE(ps, &pmcstat_string_hash[i], ps_next,
397                     pstmp) {
398                         LIST_REMOVE(ps, ps_next);
399                         free(ps->ps_string);
400                         free(ps);
401                 }
402 }
403
404 /*
405  * Determine whether a given executable image is an A.OUT object, and
406  * if so, fill in its parameters from the text file.
407  * Sets image->pi_type.
408  */
409
410 static void
411 pmcstat_image_get_aout_params(struct pmcstat_image *image)
412 {
413         int fd;
414         ssize_t nbytes;
415         struct exec ex;
416         const char *path;
417         char buffer[PATH_MAX];
418
419         path = pmcstat_string_unintern(image->pi_execpath);
420         assert(path != NULL);
421
422         if (image->pi_iskernelmodule)
423                 errx(EX_SOFTWARE, "ERROR: a.out kernel modules are "
424                     "unsupported \"%s\"", path);
425
426         (void) snprintf(buffer, sizeof(buffer), "%s%s",
427             args.pa_fsroot, path);
428
429         if ((fd = open(buffer, O_RDONLY, 0)) < 0 ||
430             (nbytes = read(fd, &ex, sizeof(ex))) < 0) {
431                 warn("WARNING: Cannot determine type of \"%s\"", path);
432                 image->pi_type = PMCSTAT_IMAGE_INDETERMINABLE;
433                 if (fd != -1)
434                         (void) close(fd);
435                 return;
436         }
437
438         (void) close(fd);
439
440         if ((unsigned) nbytes != sizeof(ex) ||
441             N_BADMAG(ex))
442                 return;
443
444         image->pi_type = PMCSTAT_IMAGE_AOUT;
445
446         /* TODO: the rest of a.out processing */
447
448         return;
449 }
450
451 /*
452  * Helper function.
453  */
454
455 static int
456 pmcstat_symbol_compare(const void *a, const void *b)
457 {
458         const struct pmcstat_symbol *sym1, *sym2;
459
460         sym1 = (const struct pmcstat_symbol *) a;
461         sym2 = (const struct pmcstat_symbol *) b;
462
463         if (sym1->ps_end <= sym2->ps_start)
464                 return (-1);
465         if (sym1->ps_start >= sym2->ps_end)
466                 return (1);
467         return (0);
468 }
469
470 /*
471  * Map an address to a symbol in an image.
472  */
473
474 struct pmcstat_symbol *
475 pmcstat_symbol_search(struct pmcstat_image *image, uintfptr_t addr)
476 {
477         struct pmcstat_symbol sym;
478
479         if (image->pi_symbols == NULL)
480                 return (NULL);
481
482         sym.ps_name  = NULL;
483         sym.ps_start = addr;
484         sym.ps_end   = addr + 1;
485
486         return (bsearch((void *) &sym, image->pi_symbols,
487                     image->pi_symcount, sizeof(struct pmcstat_symbol),
488                     pmcstat_symbol_compare));
489 }
490
491 /*
492  * Add the list of symbols in the given section to the list associated
493  * with the object.
494  */
495 static void
496 pmcstat_image_add_symbols(struct pmcstat_image *image, Elf *e,
497     Elf_Scn *scn, GElf_Shdr *sh)
498 {
499         int firsttime;
500         size_t n, newsyms, nshsyms, nfuncsyms;
501         struct pmcstat_symbol *symptr;
502         char *fnname;
503         GElf_Sym sym;
504         Elf_Data *data;
505
506         if ((data = elf_getdata(scn, NULL)) == NULL)
507                 return;
508
509         /*
510          * Determine the number of functions named in this
511          * section.
512          */
513
514         nshsyms = sh->sh_size / sh->sh_entsize;
515         for (n = nfuncsyms = 0; n < nshsyms; n++) {
516                 if (gelf_getsym(data, (int) n, &sym) != &sym)
517                         return;
518                 if (GELF_ST_TYPE(sym.st_info) == STT_FUNC)
519                         nfuncsyms++;
520         }
521
522         if (nfuncsyms == 0)
523                 return;
524
525         /*
526          * Allocate space for the new entries.
527          */
528         firsttime = image->pi_symbols == NULL;
529         symptr = realloc(image->pi_symbols,
530             sizeof(*symptr) * (image->pi_symcount + nfuncsyms));
531         if (symptr == image->pi_symbols) /* realloc() failed. */
532                 return;
533         image->pi_symbols = symptr;
534
535         /*
536          * Append new symbols to the end of the current table.
537          */
538         symptr += image->pi_symcount;
539
540         for (n = newsyms = 0; n < nshsyms; n++) {
541                 if (gelf_getsym(data, (int) n, &sym) != &sym)
542                         return;
543                 if (GELF_ST_TYPE(sym.st_info) != STT_FUNC)
544                         continue;
545                 if (sym.st_shndx == STN_UNDEF)
546                         continue;
547
548                 if (!firsttime && pmcstat_symbol_search(image, sym.st_value))
549                         continue; /* We've seen this symbol already. */
550
551                 if ((fnname = elf_strptr(e, sh->sh_link, sym.st_name))
552                     == NULL)
553                         continue;
554
555                 symptr->ps_name  = pmcstat_string_intern(fnname);
556                 symptr->ps_start = sym.st_value - image->pi_vaddr;
557                 symptr->ps_end   = symptr->ps_start + sym.st_size;
558                 symptr++;
559
560                 newsyms++;
561         }
562
563         image->pi_symcount += newsyms;
564
565         assert(newsyms <= nfuncsyms);
566
567         /*
568          * Return space to the system if there were duplicates.
569          */
570         if (newsyms < nfuncsyms)
571                 image->pi_symbols = realloc(image->pi_symbols,
572                     sizeof(*symptr) * image->pi_symcount);
573
574         /*
575          * Keep the list of symbols sorted.
576          */
577         qsort(image->pi_symbols, image->pi_symcount, sizeof(*symptr),
578             pmcstat_symbol_compare);
579
580         /*
581          * Deal with function symbols that have a size of 'zero' by
582          * making them extend to the next higher address.  These
583          * symbols are usually defined in assembly code.
584          */
585         for (symptr = image->pi_symbols;
586              symptr < image->pi_symbols + (image->pi_symcount - 1);
587              symptr++)
588                 if (symptr->ps_start == symptr->ps_end)
589                         symptr->ps_end = (symptr+1)->ps_start;
590 }
591
592 /*
593  * Examine an ELF file to determine the size of its text segment.
594  * Sets image->pi_type if anything conclusive can be determined about
595  * this image.
596  */
597
598 static void
599 pmcstat_image_get_elf_params(struct pmcstat_image *image)
600 {
601         int fd;
602         size_t i, nph, nsh;
603         const char *path, *elfbase;
604         char *p, *endp;
605         uintfptr_t minva, maxva;
606         Elf *e;
607         Elf_Scn *scn;
608         GElf_Ehdr eh;
609         GElf_Phdr ph;
610         GElf_Shdr sh;
611         enum pmcstat_image_type image_type;
612         char buffer[PATH_MAX];
613
614         assert(image->pi_type == PMCSTAT_IMAGE_UNKNOWN);
615
616         image->pi_start = minva = ~(uintfptr_t) 0;
617         image->pi_end = maxva = (uintfptr_t) 0;
618         image->pi_type = image_type = PMCSTAT_IMAGE_INDETERMINABLE;
619         image->pi_isdynamic = 0;
620         image->pi_dynlinkerpath = NULL;
621         image->pi_vaddr = 0;
622
623         path = pmcstat_string_unintern(image->pi_execpath);
624         assert(path != NULL);
625
626         /*
627          * Look for kernel modules under FSROOT/KERNELPATH/NAME,
628          * and user mode executable objects under FSROOT/PATHNAME.
629          */
630         if (image->pi_iskernelmodule)
631                 (void) snprintf(buffer, sizeof(buffer), "%s%s/%s",
632                     args.pa_fsroot, args.pa_kernel, path);
633         else
634                 (void) snprintf(buffer, sizeof(buffer), "%s%s",
635                     args.pa_fsroot, path);
636
637         e = NULL;
638         if ((fd = open(buffer, O_RDONLY, 0)) < 0 ||
639             (e = elf_begin(fd, ELF_C_READ, NULL)) == NULL ||
640             (elf_kind(e) != ELF_K_ELF)) {
641                 warnx("WARNING: Cannot determine the type of \"%s\".",
642                     buffer);
643                 goto done;
644         }
645
646         if (gelf_getehdr(e, &eh) != &eh) {
647                 warnx("WARNING: Cannot retrieve the ELF Header for "
648                     "\"%s\": %s.", buffer, elf_errmsg(-1));
649                 goto done;
650         }
651
652         if (eh.e_type != ET_EXEC && eh.e_type != ET_DYN &&
653             !(image->pi_iskernelmodule && eh.e_type == ET_REL)) {
654                 warnx("WARNING: \"%s\" is of an unsupported ELF type.",
655                     buffer);
656                 goto done;
657         }
658
659         image_type = eh.e_ident[EI_CLASS] == ELFCLASS32 ?
660             PMCSTAT_IMAGE_ELF32 : PMCSTAT_IMAGE_ELF64;
661
662         /*
663          * Determine the virtual address where an executable would be
664          * loaded.  Additionally, for dynamically linked executables,
665          * save the pathname to the runtime linker.
666          */
667         if (eh.e_type == ET_EXEC) {
668                 if (elf_getphnum(e, &nph) == 0) {
669                         warnx("WARNING: Could not determine the number of "
670                             "program headers in \"%s\": %s.", buffer,
671                             elf_errmsg(-1));
672                         goto done;
673                 }
674                 for (i = 0; i < eh.e_phnum; i++) {
675                         if (gelf_getphdr(e, i, &ph) != &ph) {
676                                 warnx("WARNING: Retrieval of PHDR entry #%ju "
677                                     "in \"%s\" failed: %s.", (uintmax_t) i,
678                                     buffer, elf_errmsg(-1));
679                                 goto done;
680                         }
681                         switch (ph.p_type) {
682                         case PT_DYNAMIC:
683                                 image->pi_isdynamic = 1;
684                                 break;
685                         case PT_INTERP:
686                                 if ((elfbase = elf_rawfile(e, NULL)) == NULL) {
687                                         warnx("WARNING: Cannot retrieve the "
688                                             "interpreter for \"%s\": %s.",
689                                             buffer, elf_errmsg(-1));
690                                         goto done;
691                                 }
692                                 image->pi_dynlinkerpath =
693                                     pmcstat_string_intern(elfbase +
694                                         ph.p_offset);
695                                 break;
696                         case PT_LOAD:
697                                 if (ph.p_offset == 0)
698                                         image->pi_vaddr = ph.p_vaddr;
699                                 break;
700                         }
701                 }
702         }
703
704         /*
705          * Get the min and max VA associated with this ELF object.
706          */
707         if (elf_getshnum(e, &nsh) == 0) {
708                 warnx("WARNING: Could not determine the number of sections "
709                     "for \"%s\": %s.", buffer, elf_errmsg(-1));
710                 goto done;
711         }
712
713         for (i = 0; i < nsh; i++) {
714                 if ((scn = elf_getscn(e, i)) == NULL ||
715                     gelf_getshdr(scn, &sh) != &sh) {
716                         warnx("WARNING: Could not retrieve section header "
717                             "#%ju in \"%s\": %s.", (uintmax_t) i, buffer,
718                             elf_errmsg(-1));
719                         goto done;
720                 }
721                 if (sh.sh_flags & SHF_EXECINSTR) {
722                         minva = min(minva, sh.sh_addr);
723                         maxva = max(maxva, sh.sh_addr + sh.sh_size);
724                 }
725                 if (sh.sh_type == SHT_SYMTAB || sh.sh_type == SHT_DYNSYM)
726                         pmcstat_image_add_symbols(image, e, scn, &sh);
727         }
728
729         image->pi_start = minva;
730         image->pi_end   = maxva;
731         image->pi_type  = image_type;
732         image->pi_fullpath = pmcstat_string_intern(buffer);
733
734         /* Build display name
735          */
736         endp = buffer;
737         for (p = buffer; *p; p++)
738                 if (*p == '/')
739                         endp = p+1;
740         image->pi_name = pmcstat_string_intern(endp);
741
742  done:
743         (void) elf_end(e);
744         if (fd >= 0)
745                 (void) close(fd);
746         return;
747 }
748
749 /*
750  * Given an image descriptor, determine whether it is an ELF, or AOUT.
751  * If no handler claims the image, set its type to 'INDETERMINABLE'.
752  */
753
754 void
755 pmcstat_image_determine_type(struct pmcstat_image *image)
756 {
757         assert(image->pi_type == PMCSTAT_IMAGE_UNKNOWN);
758
759         /* Try each kind of handler in turn */
760         if (image->pi_type == PMCSTAT_IMAGE_UNKNOWN)
761                 pmcstat_image_get_elf_params(image);
762         if (image->pi_type == PMCSTAT_IMAGE_UNKNOWN)
763                 pmcstat_image_get_aout_params(image);
764
765         /*
766          * Otherwise, remember that we tried to determine
767          * the object's type and had failed.
768          */
769         if (image->pi_type == PMCSTAT_IMAGE_UNKNOWN)
770                 image->pi_type = PMCSTAT_IMAGE_INDETERMINABLE;
771 }
772
773 /*
774  * Locate an image descriptor given an interned path, adding a fresh
775  * descriptor to the cache if necessary.  This function also finds a
776  * suitable name for this image's sample file.
777  *
778  * We defer filling in the file format specific parts of the image
779  * structure till the time we actually see a sample that would fall
780  * into this image.
781  */
782
783 static struct pmcstat_image *
784 pmcstat_image_from_path(pmcstat_interned_string internedpath,
785     int iskernelmodule)
786 {
787         int hash;
788         struct pmcstat_image *pi;
789
790         hash = pmcstat_string_lookup_hash(internedpath);
791
792         /* First, look for an existing entry. */
793         LIST_FOREACH(pi, &pmcstat_image_hash[hash], pi_next)
794             if (pi->pi_execpath == internedpath &&
795                   pi->pi_iskernelmodule == iskernelmodule)
796                     return (pi);
797
798         /*
799          * Allocate a new entry and place it at the head of the hash
800          * and LRU lists.
801          */
802         pi = malloc(sizeof(*pi));
803         if (pi == NULL)
804                 return (NULL);
805
806         pi->pi_type = PMCSTAT_IMAGE_UNKNOWN;
807         pi->pi_execpath = internedpath;
808         pi->pi_start = ~0;
809         pi->pi_end = 0;
810         pi->pi_entry = 0;
811         pi->pi_vaddr = 0;
812         pi->pi_isdynamic = 0;
813         pi->pi_iskernelmodule = iskernelmodule;
814         pi->pi_dynlinkerpath = NULL;
815         pi->pi_symbols = NULL;
816         pi->pi_symcount = 0;
817         pi->pi_addr2line = NULL;
818
819         if (plugins[args.pa_pplugin].pl_initimage != NULL)
820                 plugins[args.pa_pplugin].pl_initimage(pi);
821         if (plugins[args.pa_plugin].pl_initimage != NULL)
822                 plugins[args.pa_plugin].pl_initimage(pi);
823
824         LIST_INSERT_HEAD(&pmcstat_image_hash[hash], pi, pi_next);
825
826         return (pi);
827 }
828
829 /*
830  * Record the fact that PC values from 'start' to 'end' come from
831  * image 'image'.
832  */
833
834 static void
835 pmcstat_image_link(struct pmcstat_process *pp, struct pmcstat_image *image,
836     uintfptr_t start)
837 {
838         struct pmcstat_pcmap *pcm, *pcmnew;
839         uintfptr_t offset;
840
841         assert(image->pi_type != PMCSTAT_IMAGE_UNKNOWN &&
842             image->pi_type != PMCSTAT_IMAGE_INDETERMINABLE);
843
844         if ((pcmnew = malloc(sizeof(*pcmnew))) == NULL)
845                 err(EX_OSERR, "ERROR: Cannot create a map entry");
846
847         /*
848          * Adjust the map entry to only cover the text portion
849          * of the object.
850          */
851
852         offset = start - image->pi_vaddr;
853         pcmnew->ppm_lowpc  = image->pi_start + offset;
854         pcmnew->ppm_highpc = image->pi_end + offset;
855         pcmnew->ppm_image  = image;
856
857         assert(pcmnew->ppm_lowpc < pcmnew->ppm_highpc);
858
859         /* Overlapped mmap()'s are assumed to never occur. */
860         TAILQ_FOREACH(pcm, &pp->pp_map, ppm_next)
861             if (pcm->ppm_lowpc >= pcmnew->ppm_highpc)
862                     break;
863
864         if (pcm == NULL)
865                 TAILQ_INSERT_TAIL(&pp->pp_map, pcmnew, ppm_next);
866         else
867                 TAILQ_INSERT_BEFORE(pcm, pcmnew, ppm_next);
868 }
869
870 /*
871  * Unmap images in the range [start..end) associated with process
872  * 'pp'.
873  */
874
875 static void
876 pmcstat_image_unmap(struct pmcstat_process *pp, uintfptr_t start,
877     uintfptr_t end)
878 {
879         struct pmcstat_pcmap *pcm, *pcmtmp, *pcmnew;
880
881         assert(pp != NULL);
882         assert(start < end);
883
884         /*
885          * Cases:
886          * - we could have the range completely in the middle of an
887          *   existing pcmap; in this case we have to split the pcmap
888          *   structure into two (i.e., generate a 'hole').
889          * - we could have the range covering multiple pcmaps; these
890          *   will have to be removed.
891          * - we could have either 'start' or 'end' falling in the
892          *   middle of a pcmap; in this case shorten the entry.
893          */
894         TAILQ_FOREACH_SAFE(pcm, &pp->pp_map, ppm_next, pcmtmp) {
895                 assert(pcm->ppm_lowpc < pcm->ppm_highpc);
896                 if (pcm->ppm_highpc <= start)
897                         continue;
898                 if (pcm->ppm_lowpc >= end)
899                         return;
900                 if (pcm->ppm_lowpc >= start && pcm->ppm_highpc <= end) {
901                         /*
902                          * The current pcmap is completely inside the
903                          * unmapped range: remove it entirely.
904                          */
905                         TAILQ_REMOVE(&pp->pp_map, pcm, ppm_next);
906                         free(pcm);
907                 } else if (pcm->ppm_lowpc < start && pcm->ppm_highpc > end) {
908                         /*
909                          * Split this pcmap into two; curtail the
910                          * current map to end at [start-1], and start
911                          * the new one at [end].
912                          */
913                         if ((pcmnew = malloc(sizeof(*pcmnew))) == NULL)
914                                 err(EX_OSERR, "ERROR: Cannot split a map "
915                                     "entry");
916
917                         pcmnew->ppm_image = pcm->ppm_image;
918
919                         pcmnew->ppm_lowpc = end;
920                         pcmnew->ppm_highpc = pcm->ppm_highpc;
921
922                         pcm->ppm_highpc = start;
923
924                         TAILQ_INSERT_AFTER(&pp->pp_map, pcm, pcmnew, ppm_next);
925
926                         return;
927                 } else if (pcm->ppm_lowpc < start && pcm->ppm_highpc <= end)
928                         pcm->ppm_highpc = start;
929                 else if (pcm->ppm_lowpc >= start && pcm->ppm_highpc > end)
930                         pcm->ppm_lowpc = end;
931                 else
932                         assert(0);
933         }
934 }
935
936 /*
937  * Resolve file name and line number for the given address.
938  */
939 int
940 pmcstat_image_addr2line(struct pmcstat_image *image, uintfptr_t addr,
941     char *sourcefile, size_t sourcefile_len, unsigned *sourceline,
942     char *funcname, size_t funcname_len)
943 {
944         static int addr2line_warn = 0;
945
946         char *sep, cmdline[PATH_MAX], imagepath[PATH_MAX];
947         int fd;
948
949         if (image->pi_addr2line == NULL) {
950                 snprintf(imagepath, sizeof(imagepath), "%s%s.symbols",
951                     args.pa_fsroot,
952                     pmcstat_string_unintern(image->pi_fullpath));
953                 fd = open(imagepath, O_RDONLY);
954                 if (fd < 0) {
955                         snprintf(imagepath, sizeof(imagepath), "%s%s",
956                             args.pa_fsroot,
957                             pmcstat_string_unintern(image->pi_fullpath));
958                 } else
959                         close(fd);
960                 snprintf(cmdline, sizeof(cmdline), "addr2line -Cfe \"%s\"",
961                     imagepath);
962                 image->pi_addr2line = popen(cmdline, "r+");
963                 if (image->pi_addr2line == NULL) {
964                         if (!addr2line_warn) {
965                                 addr2line_warn = 1;
966                                 warnx("WARNING: addr2line is needed"
967                                     "for source code information.");
968                         }
969                         return (0);
970                 }
971         }
972
973         if (feof(image->pi_addr2line) || ferror(image->pi_addr2line)) {
974                 warnx("WARNING: addr2line pipe error");
975                 pclose(image->pi_addr2line);
976                 image->pi_addr2line = NULL;
977                 return (0);
978         }
979
980         fprintf(image->pi_addr2line, "%p\n", (void *)addr);
981
982         if (fgets(funcname, funcname_len, image->pi_addr2line) == NULL) {
983                 warnx("WARNING: addr2line function name read error");
984                 return (0);
985         }
986         sep = strchr(funcname, '\n');
987         if (sep != NULL)
988                 *sep = '\0';
989
990         if (fgets(sourcefile, sourcefile_len, image->pi_addr2line) == NULL) {
991                 warnx("WARNING: addr2line source file read error");
992                 return (0);
993         }
994         sep = strchr(sourcefile, ':');
995         if (sep == NULL) {
996                 warnx("WARNING: addr2line source line separator missing");
997                 return (0);
998         }
999         *sep = '\0';
1000         *sourceline = atoi(sep+1);
1001         if (*sourceline == 0)
1002                 return (0);
1003
1004         return (1);
1005 }
1006
1007 /*
1008  * Add a {pmcid,name} mapping.
1009  */
1010
1011 static void
1012 pmcstat_pmcid_add(pmc_id_t pmcid, pmcstat_interned_string ps)
1013 {
1014         struct pmcstat_pmcrecord *pr, *prm;
1015
1016         /* Replace an existing name for the PMC. */
1017         prm = NULL;
1018         LIST_FOREACH(pr, &pmcstat_pmcs, pr_next)
1019                 if (pr->pr_pmcid == pmcid) {
1020                         pr->pr_pmcname = ps;
1021                         return;
1022                 } else if (pr->pr_pmcname == ps)
1023                         prm = pr;
1024
1025         /*
1026          * Otherwise, allocate a new descriptor and call the
1027          * plugins hook.
1028          */
1029         if ((pr = malloc(sizeof(*pr))) == NULL)
1030                 err(EX_OSERR, "ERROR: Cannot allocate pmc record");
1031
1032         pr->pr_pmcid = pmcid;
1033         pr->pr_pmcname = ps;
1034         pr->pr_pmcin = pmcstat_npmcs++;
1035         pr->pr_samples = 0;
1036         pr->pr_dubious_frames = 0;
1037         pr->pr_merge = prm == NULL ? pr : prm;
1038
1039         LIST_INSERT_HEAD(&pmcstat_pmcs, pr, pr_next);
1040
1041         if (plugins[args.pa_pplugin].pl_newpmc != NULL)
1042                 plugins[args.pa_pplugin].pl_newpmc(ps, pr);
1043         if (plugins[args.pa_plugin].pl_newpmc != NULL)
1044                 plugins[args.pa_plugin].pl_newpmc(ps, pr);
1045 }
1046
1047 /*
1048  * Given a pmcid in use, find its human-readable name.
1049  */
1050
1051 const char *
1052 pmcstat_pmcid_to_name(pmc_id_t pmcid)
1053 {
1054         struct pmcstat_pmcrecord *pr;
1055
1056         LIST_FOREACH(pr, &pmcstat_pmcs, pr_next)
1057             if (pr->pr_pmcid == pmcid)
1058                     return (pmcstat_string_unintern(pr->pr_pmcname));
1059
1060         err(EX_SOFTWARE, "ERROR: cannot find pmcid");
1061         return NULL;
1062 }
1063
1064 /*
1065  * Convert PMC index to name.
1066  */
1067
1068 const char *
1069 pmcstat_pmcindex_to_name(int pmcin)
1070 {
1071         struct pmcstat_pmcrecord *pr;
1072
1073         LIST_FOREACH(pr, &pmcstat_pmcs, pr_next)
1074                 if (pr->pr_pmcin == pmcin)
1075                         return pmcstat_string_unintern(pr->pr_pmcname);
1076
1077         return NULL;
1078 }
1079
1080 /*
1081  * Return PMC record with given index.
1082  */
1083
1084 struct pmcstat_pmcrecord *
1085 pmcstat_pmcindex_to_pmcr(int pmcin)
1086 {
1087         struct pmcstat_pmcrecord *pr;
1088
1089         LIST_FOREACH(pr, &pmcstat_pmcs, pr_next)
1090                 if (pr->pr_pmcin == pmcin)
1091                         return pr;
1092
1093         err(EX_SOFTWARE, "ERROR: invalid pmcindex");
1094         return NULL;
1095 }
1096
1097 /*
1098  * Get PMC record by id, apply merge policy.
1099  */
1100
1101 static struct pmcstat_pmcrecord *
1102 pmcstat_lookup_pmcid(pmc_id_t pmcid)
1103 {
1104         struct pmcstat_pmcrecord *pr;
1105
1106         LIST_FOREACH(pr, &pmcstat_pmcs, pr_next) {
1107                 if (pr->pr_pmcid == pmcid) {
1108                         if (pmcstat_mergepmc)
1109                                 return pr->pr_merge;
1110                         return pr;
1111                 }
1112         }
1113
1114         return NULL;
1115 }
1116
1117 /*
1118  * Associate an AOUT image with a process.
1119  */
1120
1121 static void
1122 pmcstat_process_aout_exec(struct pmcstat_process *pp,
1123     struct pmcstat_image *image, uintfptr_t entryaddr)
1124 {
1125         (void) pp;
1126         (void) image;
1127         (void) entryaddr;
1128         /* TODO Implement a.out handling */
1129 }
1130
1131 /*
1132  * Associate an ELF image with a process.
1133  */
1134
1135 static void
1136 pmcstat_process_elf_exec(struct pmcstat_process *pp,
1137     struct pmcstat_image *image, uintfptr_t entryaddr)
1138 {
1139         uintmax_t libstart;
1140         struct pmcstat_image *rtldimage;
1141
1142         assert(image->pi_type == PMCSTAT_IMAGE_ELF32 ||
1143             image->pi_type == PMCSTAT_IMAGE_ELF64);
1144
1145         /* Create a map entry for the base executable. */
1146         pmcstat_image_link(pp, image, image->pi_vaddr);
1147
1148         /*
1149          * For dynamically linked executables we need to determine
1150          * where the dynamic linker was mapped to for this process,
1151          * Subsequent executable objects that are mapped in by the
1152          * dynamic linker will be tracked by log events of type
1153          * PMCLOG_TYPE_MAP_IN.
1154          */
1155
1156         if (image->pi_isdynamic) {
1157
1158                 /*
1159                  * The runtime loader gets loaded just after the maximum
1160                  * possible heap address.  Like so:
1161                  *
1162                  * [  TEXT DATA BSS HEAP -->*RTLD  SHLIBS   <--STACK]
1163                  * ^                                                ^
1164                  * 0                               VM_MAXUSER_ADDRESS
1165
1166                  *
1167                  * The exact address where the loader gets mapped in
1168                  * will vary according to the size of the executable
1169                  * and the limits on the size of the process'es data
1170                  * segment at the time of exec().  The entry address
1171                  * recorded at process exec time corresponds to the
1172                  * 'start' address inside the dynamic linker.  From
1173                  * this we can figure out the address where the
1174                  * runtime loader's file object had been mapped to.
1175                  */
1176                 rtldimage = pmcstat_image_from_path(image->pi_dynlinkerpath, 0);
1177                 if (rtldimage == NULL) {
1178                         warnx("WARNING: Cannot find image for \"%s\".",
1179                             pmcstat_string_unintern(image->pi_dynlinkerpath));
1180                         pmcstat_stats.ps_exec_errors++;
1181                         return;
1182                 }
1183
1184                 if (rtldimage->pi_type == PMCSTAT_IMAGE_UNKNOWN)
1185                         pmcstat_image_get_elf_params(rtldimage);
1186
1187                 if (rtldimage->pi_type != PMCSTAT_IMAGE_ELF32 &&
1188                     rtldimage->pi_type != PMCSTAT_IMAGE_ELF64) {
1189                         warnx("WARNING: rtld not an ELF object \"%s\".",
1190                             pmcstat_string_unintern(image->pi_dynlinkerpath));
1191                         return;
1192                 }
1193
1194                 libstart = entryaddr - rtldimage->pi_entry;
1195                 pmcstat_image_link(pp, rtldimage, libstart);
1196         }
1197 }
1198
1199 /*
1200  * Find the process descriptor corresponding to a PID.  If 'allocate'
1201  * is zero, we return a NULL if a pid descriptor could not be found or
1202  * a process descriptor process.  If 'allocate' is non-zero, then we
1203  * will attempt to allocate a fresh process descriptor.  Zombie
1204  * process descriptors are only removed if a fresh allocation for the
1205  * same PID is requested.
1206  */
1207
1208 static struct pmcstat_process *
1209 pmcstat_process_lookup(pid_t pid, int allocate)
1210 {
1211         uint32_t hash;
1212         struct pmcstat_pcmap *ppm, *ppmtmp;
1213         struct pmcstat_process *pp, *pptmp;
1214
1215         hash = (uint32_t) pid & PMCSTAT_HASH_MASK;      /* simplicity wins */
1216
1217         LIST_FOREACH_SAFE(pp, &pmcstat_process_hash[hash], pp_next, pptmp)
1218             if (pp->pp_pid == pid) {
1219                     /* Found a descriptor, check and process zombies */
1220                     if (allocate && pp->pp_isactive == 0) {
1221                             /* remove maps */
1222                             TAILQ_FOREACH_SAFE(ppm, &pp->pp_map, ppm_next,
1223                                 ppmtmp) {
1224                                     TAILQ_REMOVE(&pp->pp_map, ppm, ppm_next);
1225                                     free(ppm);
1226                             }
1227                             /* remove process entry */
1228                             LIST_REMOVE(pp, pp_next);
1229                             free(pp);
1230                             break;
1231                     }
1232                     return (pp);
1233             }
1234
1235         if (!allocate)
1236                 return (NULL);
1237
1238         if ((pp = malloc(sizeof(*pp))) == NULL)
1239                 err(EX_OSERR, "ERROR: Cannot allocate pid descriptor");
1240
1241         pp->pp_pid = pid;
1242         pp->pp_isactive = 1;
1243
1244         TAILQ_INIT(&pp->pp_map);
1245
1246         LIST_INSERT_HEAD(&pmcstat_process_hash[hash], pp, pp_next);
1247         return (pp);
1248 }
1249
1250 /*
1251  * Associate an image and a process.
1252  */
1253
1254 static void
1255 pmcstat_process_exec(struct pmcstat_process *pp,
1256     pmcstat_interned_string path, uintfptr_t entryaddr)
1257 {
1258         struct pmcstat_image *image;
1259
1260         if ((image = pmcstat_image_from_path(path, 0)) == NULL) {
1261                 pmcstat_stats.ps_exec_errors++;
1262                 return;
1263         }
1264
1265         if (image->pi_type == PMCSTAT_IMAGE_UNKNOWN)
1266                 pmcstat_image_determine_type(image);
1267
1268         assert(image->pi_type != PMCSTAT_IMAGE_UNKNOWN);
1269
1270         switch (image->pi_type) {
1271         case PMCSTAT_IMAGE_ELF32:
1272         case PMCSTAT_IMAGE_ELF64:
1273                 pmcstat_stats.ps_exec_elf++;
1274                 pmcstat_process_elf_exec(pp, image, entryaddr);
1275                 break;
1276
1277         case PMCSTAT_IMAGE_AOUT:
1278                 pmcstat_stats.ps_exec_aout++;
1279                 pmcstat_process_aout_exec(pp, image, entryaddr);
1280                 break;
1281
1282         case PMCSTAT_IMAGE_INDETERMINABLE:
1283                 pmcstat_stats.ps_exec_indeterminable++;
1284                 break;
1285
1286         default:
1287                 err(EX_SOFTWARE, "ERROR: Unsupported executable type for "
1288                     "\"%s\"", pmcstat_string_unintern(path));
1289         }
1290 }
1291
1292
1293 /*
1294  * Find the map entry associated with process 'p' at PC value 'pc'.
1295  */
1296
1297 struct pmcstat_pcmap *
1298 pmcstat_process_find_map(struct pmcstat_process *p, uintfptr_t pc)
1299 {
1300         struct pmcstat_pcmap *ppm;
1301
1302         TAILQ_FOREACH(ppm, &p->pp_map, ppm_next) {
1303                 if (pc >= ppm->ppm_lowpc && pc < ppm->ppm_highpc)
1304                         return (ppm);
1305                 if (pc < ppm->ppm_lowpc)
1306                         return (NULL);
1307         }
1308
1309         return (NULL);
1310 }
1311
1312 /*
1313  * Convert a hwpmc(4) log to profile information.  A system-wide
1314  * callgraph is generated if FLAG_DO_CALLGRAPHS is set.  gmon.out
1315  * files usable by gprof(1) are created if FLAG_DO_GPROF is set.
1316  */
1317 static int
1318 pmcstat_analyze_log(void)
1319 {
1320         uint32_t cpu, cpuflags;
1321         uintfptr_t pc;
1322         pid_t pid;
1323         struct pmcstat_image *image;
1324         struct pmcstat_process *pp, *ppnew;
1325         struct pmcstat_pcmap *ppm, *ppmtmp;
1326         struct pmclog_ev ev;
1327         struct pmcstat_pmcrecord *pmcr;
1328         pmcstat_interned_string image_path;
1329
1330         assert(args.pa_flags & FLAG_DO_ANALYSIS);
1331
1332         if (elf_version(EV_CURRENT) == EV_NONE)
1333                 err(EX_UNAVAILABLE, "Elf library intialization failed");
1334
1335         while (pmclog_read(args.pa_logparser, &ev) == 0) {
1336                 assert(ev.pl_state == PMCLOG_OK);
1337
1338                 switch (ev.pl_type) {
1339                 case PMCLOG_TYPE_INITIALIZE:
1340                         if ((ev.pl_u.pl_i.pl_version & 0xFF000000) !=
1341                             PMC_VERSION_MAJOR << 24 && args.pa_verbosity > 0)
1342                                 warnx("WARNING: Log version 0x%x does not "
1343                                     "match compiled version 0x%x.",
1344                                     ev.pl_u.pl_i.pl_version,
1345                                     PMC_VERSION_MAJOR);
1346                         break;
1347
1348                 case PMCLOG_TYPE_MAP_IN:
1349                         /*
1350                          * Introduce an address range mapping for a
1351                          * userland process or the kernel (pid == -1).
1352                          *
1353                          * We always allocate a process descriptor so
1354                          * that subsequent samples seen for this
1355                          * address range are mapped to the current
1356                          * object being mapped in.
1357                          */
1358                         pid = ev.pl_u.pl_mi.pl_pid;
1359                         if (pid == -1)
1360                                 pp = pmcstat_kernproc;
1361                         else
1362                                 pp = pmcstat_process_lookup(pid,
1363                                     PMCSTAT_ALLOCATE);
1364
1365                         assert(pp != NULL);
1366
1367                         image_path = pmcstat_string_intern(ev.pl_u.pl_mi.
1368                             pl_pathname);
1369                         image = pmcstat_image_from_path(image_path, pid == -1);
1370                         if (image->pi_type == PMCSTAT_IMAGE_UNKNOWN)
1371                                 pmcstat_image_determine_type(image);
1372                         if (image->pi_type != PMCSTAT_IMAGE_INDETERMINABLE)
1373                                 pmcstat_image_link(pp, image,
1374                                     ev.pl_u.pl_mi.pl_start);
1375                         break;
1376
1377                 case PMCLOG_TYPE_MAP_OUT:
1378                         /*
1379                          * Remove an address map.
1380                          */
1381                         pid = ev.pl_u.pl_mo.pl_pid;
1382                         if (pid == -1)
1383                                 pp = pmcstat_kernproc;
1384                         else
1385                                 pp = pmcstat_process_lookup(pid, 0);
1386
1387                         if (pp == NULL) /* unknown process */
1388                                 break;
1389
1390                         pmcstat_image_unmap(pp, ev.pl_u.pl_mo.pl_start,
1391                             ev.pl_u.pl_mo.pl_end);
1392                         break;
1393
1394                 case PMCLOG_TYPE_PCSAMPLE:
1395                         /*
1396                          * Note: the `PCSAMPLE' log entry is not
1397                          * generated by hpwmc(4) after version 2.
1398                          */
1399
1400                         /*
1401                          * We bring in the gmon file for the image
1402                          * currently associated with the PMC & pid
1403                          * pair and increment the appropriate entry
1404                          * bin inside this.
1405                          */
1406                         pmcstat_stats.ps_samples_total++;
1407                         ps_samples_period++;
1408
1409                         pc = ev.pl_u.pl_s.pl_pc;
1410                         pp = pmcstat_process_lookup(ev.pl_u.pl_s.pl_pid,
1411                             PMCSTAT_ALLOCATE);
1412
1413                         /* Get PMC record. */
1414                         pmcr = pmcstat_lookup_pmcid(ev.pl_u.pl_s.pl_pmcid);
1415                         assert(pmcr != NULL);
1416                         pmcr->pr_samples++;
1417
1418                         /*
1419                          * Call the plugins processing
1420                          * TODO: move pmcstat_process_find_map inside plugins
1421                          */
1422
1423                         if (plugins[args.pa_pplugin].pl_process != NULL)
1424                                 plugins[args.pa_pplugin].pl_process(
1425                                     pp, pmcr, 1, &pc,
1426                                     pmcstat_process_find_map(pp, pc) != NULL, 0);
1427                         plugins[args.pa_plugin].pl_process(
1428                             pp, pmcr, 1, &pc,
1429                             pmcstat_process_find_map(pp, pc) != NULL, 0);
1430                         break;
1431
1432                 case PMCLOG_TYPE_CALLCHAIN:
1433                         pmcstat_stats.ps_samples_total++;
1434                         ps_samples_period++;
1435
1436                         cpuflags = ev.pl_u.pl_cc.pl_cpuflags;
1437                         cpu = PMC_CALLCHAIN_CPUFLAGS_TO_CPU(cpuflags);
1438
1439                         /* Filter on the CPU id. */
1440                         if ((args.pa_cpumask & (1 << cpu)) == 0) {
1441                                 pmcstat_stats.ps_samples_skipped++;
1442                                 break;
1443                         }
1444
1445                         pp = pmcstat_process_lookup(ev.pl_u.pl_cc.pl_pid,
1446                             PMCSTAT_ALLOCATE);
1447
1448                         /* Get PMC record. */
1449                         pmcr = pmcstat_lookup_pmcid(ev.pl_u.pl_cc.pl_pmcid);
1450                         assert(pmcr != NULL);
1451                         pmcr->pr_samples++;
1452
1453                         /*
1454                          * Call the plugins processing
1455                          */
1456
1457                         if (plugins[args.pa_pplugin].pl_process != NULL)
1458                                 plugins[args.pa_pplugin].pl_process(
1459                                     pp, pmcr,
1460                                     ev.pl_u.pl_cc.pl_npc,
1461                                     ev.pl_u.pl_cc.pl_pc,
1462                                     PMC_CALLCHAIN_CPUFLAGS_TO_USERMODE(cpuflags),
1463                                     cpu);
1464                         plugins[args.pa_plugin].pl_process(
1465                             pp, pmcr,
1466                             ev.pl_u.pl_cc.pl_npc,
1467                             ev.pl_u.pl_cc.pl_pc,
1468                             PMC_CALLCHAIN_CPUFLAGS_TO_USERMODE(cpuflags),
1469                             cpu);
1470                         break;
1471
1472                 case PMCLOG_TYPE_PMCALLOCATE:
1473                         /*
1474                          * Record the association pmc id between this
1475                          * PMC and its name.
1476                          */
1477                         pmcstat_pmcid_add(ev.pl_u.pl_a.pl_pmcid,
1478                             pmcstat_string_intern(ev.pl_u.pl_a.pl_evname));
1479                         break;
1480
1481                 case PMCLOG_TYPE_PROCEXEC:
1482
1483                         /*
1484                          * Change the executable image associated with
1485                          * a process.
1486                          */
1487                         pp = pmcstat_process_lookup(ev.pl_u.pl_x.pl_pid,
1488                             PMCSTAT_ALLOCATE);
1489
1490                         /* delete the current process map */
1491                         TAILQ_FOREACH_SAFE(ppm, &pp->pp_map, ppm_next, ppmtmp) {
1492                                 TAILQ_REMOVE(&pp->pp_map, ppm, ppm_next);
1493                                 free(ppm);
1494                         }
1495
1496                         /* associate this process  image */
1497                         image_path = pmcstat_string_intern(
1498                                 ev.pl_u.pl_x.pl_pathname);
1499                         assert(image_path != NULL);
1500                         pmcstat_process_exec(pp, image_path,
1501                             ev.pl_u.pl_x.pl_entryaddr);
1502                         break;
1503
1504                 case PMCLOG_TYPE_PROCEXIT:
1505
1506                         /*
1507                          * Due to the way the log is generated, the
1508                          * last few samples corresponding to a process
1509                          * may appear in the log after the process
1510                          * exit event is recorded.  Thus we keep the
1511                          * process' descriptor and associated data
1512                          * structures around, but mark the process as
1513                          * having exited.
1514                          */
1515                         pp = pmcstat_process_lookup(ev.pl_u.pl_e.pl_pid, 0);
1516                         if (pp == NULL)
1517                                 break;
1518                         pp->pp_isactive = 0;    /* mark as a zombie */
1519                         break;
1520
1521                 case PMCLOG_TYPE_SYSEXIT:
1522                         pp = pmcstat_process_lookup(ev.pl_u.pl_se.pl_pid, 0);
1523                         if (pp == NULL)
1524                                 break;
1525                         pp->pp_isactive = 0;    /* make a zombie */
1526                         break;
1527
1528                 case PMCLOG_TYPE_PROCFORK:
1529
1530                         /*
1531                          * Allocate a process descriptor for the new
1532                          * (child) process.
1533                          */
1534                         ppnew =
1535                             pmcstat_process_lookup(ev.pl_u.pl_f.pl_newpid,
1536                                 PMCSTAT_ALLOCATE);
1537
1538                         /*
1539                          * If we had been tracking the parent, clone
1540                          * its address maps.
1541                          */
1542                         pp = pmcstat_process_lookup(ev.pl_u.pl_f.pl_oldpid, 0);
1543                         if (pp == NULL)
1544                                 break;
1545                         TAILQ_FOREACH(ppm, &pp->pp_map, ppm_next)
1546                             pmcstat_image_link(ppnew, ppm->ppm_image,
1547                                 ppm->ppm_lowpc);
1548                         break;
1549
1550                 default:        /* other types of entries are not relevant */
1551                         break;
1552                 }
1553         }
1554
1555         if (ev.pl_state == PMCLOG_EOF)
1556                 return (PMCSTAT_FINISHED);
1557         else if (ev.pl_state == PMCLOG_REQUIRE_DATA)
1558                 return (PMCSTAT_RUNNING);
1559
1560         err(EX_DATAERR, "ERROR: event parsing failed (record %jd, "
1561             "offset 0x%jx)", (uintmax_t) ev.pl_count + 1, ev.pl_offset);
1562 }
1563
1564 /*
1565  * Print log entries as text.
1566  */
1567
1568 static int
1569 pmcstat_print_log(void)
1570 {
1571         struct pmclog_ev ev;
1572         uint32_t npc;
1573
1574         while (pmclog_read(args.pa_logparser, &ev) == 0) {
1575                 assert(ev.pl_state == PMCLOG_OK);
1576                 switch (ev.pl_type) {
1577                 case PMCLOG_TYPE_CALLCHAIN:
1578                         PMCSTAT_PRINT_ENTRY("callchain",
1579                             "%d 0x%x %d %d %c", ev.pl_u.pl_cc.pl_pid,
1580                             ev.pl_u.pl_cc.pl_pmcid,
1581                             PMC_CALLCHAIN_CPUFLAGS_TO_CPU(ev.pl_u.pl_cc. \
1582                                 pl_cpuflags), ev.pl_u.pl_cc.pl_npc,
1583                             PMC_CALLCHAIN_CPUFLAGS_TO_USERMODE(ev.pl_u.pl_cc.\
1584                                 pl_cpuflags) ? 'u' : 's');
1585                         for (npc = 0; npc < ev.pl_u.pl_cc.pl_npc; npc++)
1586                                 PMCSTAT_PRINT_ENTRY("...", "%p",
1587                                     (void *) ev.pl_u.pl_cc.pl_pc[npc]);
1588                         break;
1589                 case PMCLOG_TYPE_CLOSELOG:
1590                         PMCSTAT_PRINT_ENTRY("closelog",);
1591                         break;
1592                 case PMCLOG_TYPE_DROPNOTIFY:
1593                         PMCSTAT_PRINT_ENTRY("drop",);
1594                         break;
1595                 case PMCLOG_TYPE_INITIALIZE:
1596                         PMCSTAT_PRINT_ENTRY("initlog","0x%x \"%s\"",
1597                             ev.pl_u.pl_i.pl_version,
1598                             pmc_name_of_cputype(ev.pl_u.pl_i.pl_arch));
1599                         if ((ev.pl_u.pl_i.pl_version & 0xFF000000) !=
1600                             PMC_VERSION_MAJOR << 24 && args.pa_verbosity > 0)
1601                                 warnx("WARNING: Log version 0x%x != expected "
1602                                     "version 0x%x.", ev.pl_u.pl_i.pl_version,
1603                                     PMC_VERSION);
1604                         break;
1605                 case PMCLOG_TYPE_MAP_IN:
1606                         PMCSTAT_PRINT_ENTRY("map-in","%d %p \"%s\"",
1607                             ev.pl_u.pl_mi.pl_pid,
1608                             (void *) ev.pl_u.pl_mi.pl_start,
1609                             ev.pl_u.pl_mi.pl_pathname);
1610                         break;
1611                 case PMCLOG_TYPE_MAP_OUT:
1612                         PMCSTAT_PRINT_ENTRY("map-out","%d %p %p",
1613                             ev.pl_u.pl_mo.pl_pid,
1614                             (void *) ev.pl_u.pl_mo.pl_start,
1615                             (void *) ev.pl_u.pl_mo.pl_end);
1616                         break;
1617                 case PMCLOG_TYPE_PCSAMPLE:
1618                         PMCSTAT_PRINT_ENTRY("sample","0x%x %d %p %c",
1619                             ev.pl_u.pl_s.pl_pmcid,
1620                             ev.pl_u.pl_s.pl_pid,
1621                             (void *) ev.pl_u.pl_s.pl_pc,
1622                             ev.pl_u.pl_s.pl_usermode ? 'u' : 's');
1623                         break;
1624                 case PMCLOG_TYPE_PMCALLOCATE:
1625                         PMCSTAT_PRINT_ENTRY("allocate","0x%x \"%s\" 0x%x",
1626                             ev.pl_u.pl_a.pl_pmcid,
1627                             ev.pl_u.pl_a.pl_evname,
1628                             ev.pl_u.pl_a.pl_flags);
1629                         break;
1630                 case PMCLOG_TYPE_PMCATTACH:
1631                         PMCSTAT_PRINT_ENTRY("attach","0x%x %d \"%s\"",
1632                             ev.pl_u.pl_t.pl_pmcid,
1633                             ev.pl_u.pl_t.pl_pid,
1634                             ev.pl_u.pl_t.pl_pathname);
1635                         break;
1636                 case PMCLOG_TYPE_PMCDETACH:
1637                         PMCSTAT_PRINT_ENTRY("detach","0x%x %d",
1638                             ev.pl_u.pl_d.pl_pmcid,
1639                             ev.pl_u.pl_d.pl_pid);
1640                         break;
1641                 case PMCLOG_TYPE_PROCCSW:
1642                         PMCSTAT_PRINT_ENTRY("cswval","0x%x %d %jd",
1643                             ev.pl_u.pl_c.pl_pmcid,
1644                             ev.pl_u.pl_c.pl_pid,
1645                             ev.pl_u.pl_c.pl_value);
1646                         break;
1647                 case PMCLOG_TYPE_PROCEXEC:
1648                         PMCSTAT_PRINT_ENTRY("exec","0x%x %d %p \"%s\"",
1649                             ev.pl_u.pl_x.pl_pmcid,
1650                             ev.pl_u.pl_x.pl_pid,
1651                             (void *) ev.pl_u.pl_x.pl_entryaddr,
1652                             ev.pl_u.pl_x.pl_pathname);
1653                         break;
1654                 case PMCLOG_TYPE_PROCEXIT:
1655                         PMCSTAT_PRINT_ENTRY("exitval","0x%x %d %jd",
1656                             ev.pl_u.pl_e.pl_pmcid,
1657                             ev.pl_u.pl_e.pl_pid,
1658                             ev.pl_u.pl_e.pl_value);
1659                         break;
1660                 case PMCLOG_TYPE_PROCFORK:
1661                         PMCSTAT_PRINT_ENTRY("fork","%d %d",
1662                             ev.pl_u.pl_f.pl_oldpid,
1663                             ev.pl_u.pl_f.pl_newpid);
1664                         break;
1665                 case PMCLOG_TYPE_USERDATA:
1666                         PMCSTAT_PRINT_ENTRY("userdata","0x%x",
1667                             ev.pl_u.pl_u.pl_userdata);
1668                         break;
1669                 case PMCLOG_TYPE_SYSEXIT:
1670                         PMCSTAT_PRINT_ENTRY("exit","%d",
1671                             ev.pl_u.pl_se.pl_pid);
1672                         break;
1673                 default:
1674                         fprintf(args.pa_printfile, "unknown event (type %d).\n",
1675                             ev.pl_type);
1676                 }
1677         }
1678
1679         if (ev.pl_state == PMCLOG_EOF)
1680                 return (PMCSTAT_FINISHED);
1681         else if (ev.pl_state ==  PMCLOG_REQUIRE_DATA)
1682                 return (PMCSTAT_RUNNING);
1683
1684         errx(EX_DATAERR, "ERROR: event parsing failed "
1685             "(record %jd, offset 0x%jx).",
1686             (uintmax_t) ev.pl_count + 1, ev.pl_offset);
1687         /*NOTREACHED*/
1688 }
1689
1690 /*
1691  * Public Interfaces.
1692  */
1693
1694 /*
1695  * Close a logfile, after first flushing all in-module queued data.
1696  */
1697
1698 int
1699 pmcstat_close_log(void)
1700 {
1701         /* If a local logfile is configured ask the kernel to stop
1702          * and flush data. Kernel will close the file when data is flushed
1703          * so keep the status to EXITING.
1704          */
1705         if (args.pa_logfd != -1) {
1706                 if (pmc_flush_logfile() < 0)
1707                         err(EX_OSERR, "ERROR: logging failed");
1708         }
1709
1710         return (args.pa_flags & FLAG_HAS_PIPE ? PMCSTAT_EXITING :
1711             PMCSTAT_FINISHED);
1712 }
1713
1714
1715
1716 /*
1717  * Open a log file, for reading or writing.
1718  *
1719  * The function returns the fd of a successfully opened log or -1 in
1720  * case of failure.
1721  */
1722
1723 int
1724 pmcstat_open_log(const char *path, int mode)
1725 {
1726         int error, fd, cfd;
1727         size_t hlen;
1728         const char *p, *errstr;
1729         struct addrinfo hints, *res, *res0;
1730         char hostname[MAXHOSTNAMELEN];
1731
1732         errstr = NULL;
1733         fd = -1;
1734
1735         /*
1736          * If 'path' is "-" then open one of stdin or stdout depending
1737          * on the value of 'mode'.
1738          *
1739          * If 'path' contains a ':' and does not start with a '/' or '.',
1740          * and is being opened for writing, treat it as a "host:port"
1741          * specification and open a network socket.
1742          *
1743          * Otherwise, treat 'path' as a file name and open that.
1744          */
1745         if (path[0] == '-' && path[1] == '\0')
1746                 fd = (mode == PMCSTAT_OPEN_FOR_READ) ? 0 : 1;
1747         else if (path[0] != '/' &&
1748             path[0] != '.' && strchr(path, ':') != NULL) {
1749
1750                 p = strrchr(path, ':');
1751                 hlen = p - path;
1752                 if (p == path || hlen >= sizeof(hostname)) {
1753                         errstr = strerror(EINVAL);
1754                         goto done;
1755                 }
1756
1757                 assert(hlen < sizeof(hostname));
1758                 (void) strncpy(hostname, path, hlen);
1759                 hostname[hlen] = '\0';
1760
1761                 (void) memset(&hints, 0, sizeof(hints));
1762                 hints.ai_family = AF_UNSPEC;
1763                 hints.ai_socktype = SOCK_STREAM;
1764                 if ((error = getaddrinfo(hostname, p+1, &hints, &res0)) != 0) {
1765                         errstr = gai_strerror(error);
1766                         goto done;
1767                 }
1768
1769                 fd = -1;
1770                 for (res = res0; res; res = res->ai_next) {
1771                         if ((fd = socket(res->ai_family, res->ai_socktype,
1772                             res->ai_protocol)) < 0) {
1773                                 errstr = strerror(errno);
1774                                 continue;
1775                         }
1776                         if (mode == PMCSTAT_OPEN_FOR_READ) {
1777                                 if (bind(fd, res->ai_addr, res->ai_addrlen) < 0) {
1778                                         errstr = strerror(errno);
1779                                         (void) close(fd);
1780                                         fd = -1;
1781                                         continue;
1782                                 }
1783                                 listen(fd, 1);
1784                                 cfd = accept(fd, NULL, NULL);
1785                                 (void) close(fd);
1786                                 if (cfd < 0) {
1787                                         errstr = strerror(errno);
1788                                         fd = -1;
1789                                         break;
1790                                 }
1791                                 fd = cfd;
1792                         } else {
1793                                 if (connect(fd, res->ai_addr, res->ai_addrlen) < 0) {
1794                                         errstr = strerror(errno);
1795                                         (void) close(fd);
1796                                         fd = -1;
1797                                         continue;
1798                                 }
1799                         }
1800                         errstr = NULL;
1801                         break;
1802                 }
1803                 freeaddrinfo(res0);
1804
1805         } else if ((fd = open(path, mode == PMCSTAT_OPEN_FOR_READ ?
1806                     O_RDONLY : (O_WRONLY|O_CREAT|O_TRUNC),
1807                     S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
1808                         errstr = strerror(errno);
1809
1810   done:
1811         if (errstr)
1812                 errx(EX_OSERR, "ERROR: Cannot open \"%s\" for %s: %s.", path,
1813                     (mode == PMCSTAT_OPEN_FOR_READ ? "reading" : "writing"),
1814                     errstr);
1815
1816         return (fd);
1817 }
1818
1819 /*
1820  * Process a log file in offline analysis mode.
1821  */
1822
1823 int
1824 pmcstat_process_log(void)
1825 {
1826
1827         /*
1828          * If analysis has not been asked for, just print the log to
1829          * the current output file.
1830          */
1831         if (args.pa_flags & FLAG_DO_PRINT)
1832                 return (pmcstat_print_log());
1833         else
1834                 return (pmcstat_analyze_log());
1835 }
1836
1837 /*
1838  * Refresh top display.
1839  */
1840
1841 static void
1842 pmcstat_refresh_top(void)
1843 {
1844         int v_attrs;
1845         float v;
1846         char pmcname[40];
1847         struct pmcstat_pmcrecord *pmcpr;
1848
1849         /* If in pause mode do not refresh display. */
1850         if (pmcstat_pause)
1851                 return;
1852
1853         /* Wait until PMC pop in the log. */
1854         pmcpr = pmcstat_pmcindex_to_pmcr(pmcstat_pmcinfilter);
1855         if (pmcpr == NULL)
1856                 return;
1857
1858         /* Format PMC name. */
1859         if (pmcstat_mergepmc)
1860                 snprintf(pmcname, sizeof(pmcname), "[%s]",
1861                     pmcstat_string_unintern(pmcpr->pr_pmcname));
1862         else
1863                 snprintf(pmcname, sizeof(pmcname), "%s.%d",
1864                     pmcstat_string_unintern(pmcpr->pr_pmcname),
1865                     pmcstat_pmcinfilter);
1866
1867         /* Format samples count. */
1868         if (ps_samples_period > 0)
1869                 v = (pmcpr->pr_samples * 100.0) / ps_samples_period;
1870         else
1871                 v = 0.;
1872         v_attrs = PMCSTAT_ATTRPERCENT(v);
1873
1874         PMCSTAT_PRINTBEGIN();
1875         PMCSTAT_PRINTW("PMC: %s Samples: %u ",
1876             pmcname,
1877             pmcpr->pr_samples);
1878         PMCSTAT_ATTRON(v_attrs);
1879         PMCSTAT_PRINTW("(%.1f%%) ", v);
1880         PMCSTAT_ATTROFF(v_attrs);
1881         PMCSTAT_PRINTW(", %u unresolved\n\n",
1882             pmcpr->pr_dubious_frames);
1883         if (plugins[args.pa_plugin].pl_topdisplay != NULL)
1884                 plugins[args.pa_plugin].pl_topdisplay();
1885         PMCSTAT_PRINTEND();
1886 }
1887
1888 /*
1889  * Find the next pmc index to display.
1890  */
1891
1892 static void
1893 pmcstat_changefilter(void)
1894 {
1895         int pmcin;
1896         struct pmcstat_pmcrecord *pmcr;
1897
1898         /*
1899          * Find the next merge target.
1900          */
1901         if (pmcstat_mergepmc) {
1902                 pmcin = pmcstat_pmcinfilter;
1903
1904                 do {
1905                         pmcr = pmcstat_pmcindex_to_pmcr(pmcstat_pmcinfilter);
1906                         if (pmcr == NULL || pmcr == pmcr->pr_merge)
1907                                 break;
1908
1909                         pmcstat_pmcinfilter++;
1910                         if (pmcstat_pmcinfilter >= pmcstat_npmcs)
1911                                 pmcstat_pmcinfilter = 0;
1912
1913                 } while (pmcstat_pmcinfilter != pmcin);
1914         }
1915 }
1916
1917 /*
1918  * Top mode keypress.
1919  */
1920
1921 int
1922 pmcstat_keypress_log(void)
1923 {
1924         int c, ret = 0;
1925         WINDOW *w;
1926
1927         w = newwin(1, 0, 1, 0);
1928         c = wgetch(w);
1929         wprintw(w, "Key: %c => ", c);
1930         switch (c) {
1931         case 'c':
1932                 wprintw(w, "enter mode 'd' or 'a' => ");
1933                 c = wgetch(w);
1934                 if (c == 'd') {
1935                         args.pa_topmode = PMCSTAT_TOP_DELTA;
1936                         wprintw(w, "switching to delta mode");
1937                 } else {
1938                         args.pa_topmode = PMCSTAT_TOP_ACCUM;
1939                         wprintw(w, "switching to accumulation mode");
1940                 }
1941                 break;
1942         case 'm':
1943                 pmcstat_mergepmc = !pmcstat_mergepmc;
1944                 /*
1945                  * Changing merge state require data reset.
1946                  */
1947                 if (plugins[args.pa_plugin].pl_shutdown != NULL)
1948                         plugins[args.pa_plugin].pl_shutdown(NULL);
1949                 pmcstat_stats_reset(0);
1950                 if (plugins[args.pa_plugin].pl_init != NULL)
1951                         plugins[args.pa_plugin].pl_init();
1952
1953                 /* Update filter to be on a merge target. */
1954                 pmcstat_changefilter();
1955                 wprintw(w, "merge PMC %s", pmcstat_mergepmc ? "on" : "off");
1956                 break;
1957         case 'n':
1958                 /* Close current plugin. */
1959                 if (plugins[args.pa_plugin].pl_shutdown != NULL)
1960                         plugins[args.pa_plugin].pl_shutdown(NULL);
1961
1962                 /* Find next top display available. */
1963                 do {
1964                         args.pa_plugin++;
1965                         if (plugins[args.pa_plugin].pl_name == NULL)
1966                                 args.pa_plugin = 0;
1967                 } while (plugins[args.pa_plugin].pl_topdisplay == NULL);
1968
1969                 /* Open new plugin. */
1970                 pmcstat_stats_reset(0);
1971                 if (plugins[args.pa_plugin].pl_init != NULL)
1972                         plugins[args.pa_plugin].pl_init();
1973                 wprintw(w, "switching to plugin %s",
1974                     plugins[args.pa_plugin].pl_name);
1975                 break;
1976         case 'p':
1977                 pmcstat_pmcinfilter++;
1978                 if (pmcstat_pmcinfilter >= pmcstat_npmcs)
1979                         pmcstat_pmcinfilter = 0;
1980                 pmcstat_changefilter();
1981                 wprintw(w, "switching to PMC %s.%d",
1982                     pmcstat_pmcindex_to_name(pmcstat_pmcinfilter),
1983                     pmcstat_pmcinfilter);
1984                 break;
1985         case ' ':
1986                 pmcstat_pause = !pmcstat_pause;
1987                 if (pmcstat_pause)
1988                         wprintw(w, "pause => press space again to continue");
1989                 break;
1990         case 'q':
1991                 wprintw(w, "exiting...");
1992                 ret = 1;
1993                 break;
1994         default:
1995                 if (plugins[args.pa_plugin].pl_topkeypress != NULL)
1996                         if (plugins[args.pa_plugin].pl_topkeypress(c, w))
1997                                 ret = 1;
1998         }
1999
2000         wrefresh(w);
2001         delwin(w);
2002         return ret;
2003 }
2004
2005
2006 /*
2007  * Top mode display.
2008  */
2009
2010 void
2011 pmcstat_display_log(void)
2012 {
2013
2014         pmcstat_refresh_top();
2015
2016         /* Reset everythings if delta mode. */
2017         if (args.pa_topmode == PMCSTAT_TOP_DELTA) {
2018                 if (plugins[args.pa_plugin].pl_shutdown != NULL)
2019                         plugins[args.pa_plugin].pl_shutdown(NULL);
2020                 pmcstat_stats_reset(0);
2021                 if (plugins[args.pa_plugin].pl_init != NULL)
2022                         plugins[args.pa_plugin].pl_init();
2023         }
2024
2025 }
2026
2027 /*
2028  * Configure a plugins.
2029  */
2030
2031 void
2032 pmcstat_pluginconfigure_log(char *opt)
2033 {
2034
2035         if (strncmp(opt, "threshold=", 10) == 0) {
2036                 pmcstat_threshold = atof(opt+10);
2037         } else {
2038                 if (plugins[args.pa_plugin].pl_configure != NULL) {
2039                         if (!plugins[args.pa_plugin].pl_configure(opt))
2040                                 err(EX_USAGE,
2041                                     "ERROR: unknown option <%s>.", opt);
2042                 }
2043         }
2044 }
2045
2046 /*
2047  * Initialize module.
2048  */
2049
2050 void
2051 pmcstat_initialize_logging(void)
2052 {
2053         int i;
2054
2055         /* use a convenient format for 'ldd' output */
2056         if (setenv("LD_TRACE_LOADED_OBJECTS_FMT1","%o \"%p\" %x\n",1) != 0)
2057                 err(EX_OSERR, "ERROR: Cannot setenv");
2058
2059         /* Initialize hash tables */
2060         pmcstat_string_initialize();
2061         for (i = 0; i < PMCSTAT_NHASH; i++) {
2062                 LIST_INIT(&pmcstat_image_hash[i]);
2063                 LIST_INIT(&pmcstat_process_hash[i]);
2064         }
2065
2066         /*
2067          * Create a fake 'process' entry for the kernel with pid -1.
2068          * hwpmc(4) will subsequently inform us about where the kernel
2069          * and any loaded kernel modules are mapped.
2070          */
2071         if ((pmcstat_kernproc = pmcstat_process_lookup((pid_t) -1,
2072                  PMCSTAT_ALLOCATE)) == NULL)
2073                 err(EX_OSERR, "ERROR: Cannot initialize logging");
2074
2075         /* PMC count. */
2076         pmcstat_npmcs = 0;
2077
2078         /* Merge PMC with same name. */
2079         pmcstat_mergepmc = args.pa_mergepmc;
2080
2081         /*
2082          * Initialize plugins
2083          */
2084
2085         if (plugins[args.pa_pplugin].pl_init != NULL)
2086                 plugins[args.pa_pplugin].pl_init();
2087         if (plugins[args.pa_plugin].pl_init != NULL)
2088                 plugins[args.pa_plugin].pl_init();
2089 }
2090
2091 /*
2092  * Shutdown module.
2093  */
2094
2095 void
2096 pmcstat_shutdown_logging(void)
2097 {
2098         int i;
2099         FILE *mf;
2100         struct pmcstat_image *pi, *pitmp;
2101         struct pmcstat_process *pp, *pptmp;
2102         struct pmcstat_pcmap *ppm, *ppmtmp;
2103
2104         /* determine where to send the map file */
2105         mf = NULL;
2106         if (args.pa_mapfilename != NULL)
2107                 mf = (strcmp(args.pa_mapfilename, "-") == 0) ?
2108                     args.pa_printfile : fopen(args.pa_mapfilename, "w");
2109
2110         if (mf == NULL && args.pa_flags & FLAG_DO_GPROF &&
2111             args.pa_verbosity >= 2)
2112                 mf = args.pa_printfile;
2113
2114         if (mf)
2115                 (void) fprintf(mf, "MAP:\n");
2116
2117         /*
2118          * Shutdown the plugins
2119          */
2120
2121         if (plugins[args.pa_plugin].pl_shutdown != NULL)
2122                 plugins[args.pa_plugin].pl_shutdown(mf);
2123         if (plugins[args.pa_pplugin].pl_shutdown != NULL)
2124                 plugins[args.pa_pplugin].pl_shutdown(mf);
2125
2126         for (i = 0; i < PMCSTAT_NHASH; i++) {
2127                 LIST_FOREACH_SAFE(pi, &pmcstat_image_hash[i], pi_next,
2128                     pitmp) {
2129                         if (plugins[args.pa_plugin].pl_shutdownimage != NULL)
2130                                 plugins[args.pa_plugin].pl_shutdownimage(pi);
2131                         if (plugins[args.pa_pplugin].pl_shutdownimage != NULL)
2132                                 plugins[args.pa_pplugin].pl_shutdownimage(pi);
2133
2134                         free(pi->pi_symbols);
2135                         if (pi->pi_addr2line != NULL)
2136                                 pclose(pi->pi_addr2line);
2137                         LIST_REMOVE(pi, pi_next);
2138                         free(pi);
2139                 }
2140
2141                 LIST_FOREACH_SAFE(pp, &pmcstat_process_hash[i], pp_next,
2142                     pptmp) {
2143                         TAILQ_FOREACH_SAFE(ppm, &pp->pp_map, ppm_next, ppmtmp) {
2144                                 TAILQ_REMOVE(&pp->pp_map, ppm, ppm_next);
2145                                 free(ppm);
2146                         }
2147                         LIST_REMOVE(pp, pp_next);
2148                         free(pp);
2149                 }
2150         }
2151
2152         pmcstat_string_shutdown();
2153
2154         /*
2155          * Print errors unless -q was specified.  Print all statistics
2156          * if verbosity > 1.
2157          */
2158 #define PRINT(N,V) do {                                                 \
2159                 if (pmcstat_stats.ps_##V || args.pa_verbosity >= 2)     \
2160                         (void) fprintf(args.pa_printfile, " %-40s %d\n",\
2161                             N, pmcstat_stats.ps_##V);                   \
2162         } while (0)
2163
2164         if (args.pa_verbosity >= 1 && (args.pa_flags & FLAG_DO_ANALYSIS)) {
2165                 (void) fprintf(args.pa_printfile, "CONVERSION STATISTICS:\n");
2166                 PRINT("#exec/a.out", exec_aout);
2167                 PRINT("#exec/elf", exec_elf);
2168                 PRINT("#exec/unknown", exec_indeterminable);
2169                 PRINT("#exec handling errors", exec_errors);
2170                 PRINT("#samples/total", samples_total);
2171                 PRINT("#samples/unclaimed", samples_unknown_offset);
2172                 PRINT("#samples/unknown-object", samples_indeterminable);
2173                 PRINT("#samples/unknown-function", samples_unknown_function);
2174                 PRINT("#callchain/dubious-frames", callchain_dubious_frames);
2175         }
2176
2177         if (mf)
2178                 (void) fclose(mf);
2179 }