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