]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/pmcstat/pmcstat_log.c
Merge OpenSSL 0.9.8q into head.
[FreeBSD/FreeBSD.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         return NULL;
1061 }
1062
1063 /*
1064  * Convert PMC index to name.
1065  */
1066
1067 const char *
1068 pmcstat_pmcindex_to_name(int pmcin)
1069 {
1070         struct pmcstat_pmcrecord *pr;
1071
1072         LIST_FOREACH(pr, &pmcstat_pmcs, pr_next)
1073                 if (pr->pr_pmcin == pmcin)
1074                         return pmcstat_string_unintern(pr->pr_pmcname);
1075
1076         return NULL;
1077 }
1078
1079 /*
1080  * Return PMC record with given index.
1081  */
1082
1083 struct pmcstat_pmcrecord *
1084 pmcstat_pmcindex_to_pmcr(int pmcin)
1085 {
1086         struct pmcstat_pmcrecord *pr;
1087
1088         LIST_FOREACH(pr, &pmcstat_pmcs, pr_next)
1089                 if (pr->pr_pmcin == pmcin)
1090                         return pr;
1091
1092         return NULL;
1093 }
1094
1095 /*
1096  * Get PMC record by id, apply merge policy.
1097  */
1098
1099 static struct pmcstat_pmcrecord *
1100 pmcstat_lookup_pmcid(pmc_id_t pmcid)
1101 {
1102         struct pmcstat_pmcrecord *pr;
1103
1104         LIST_FOREACH(pr, &pmcstat_pmcs, pr_next) {
1105                 if (pr->pr_pmcid == pmcid) {
1106                         if (pmcstat_mergepmc)
1107                                 return pr->pr_merge;
1108                         return pr;
1109                 }
1110         }
1111
1112         return NULL;
1113 }
1114
1115 /*
1116  * Associate an AOUT image with a process.
1117  */
1118
1119 static void
1120 pmcstat_process_aout_exec(struct pmcstat_process *pp,
1121     struct pmcstat_image *image, uintfptr_t entryaddr)
1122 {
1123         (void) pp;
1124         (void) image;
1125         (void) entryaddr;
1126         /* TODO Implement a.out handling */
1127 }
1128
1129 /*
1130  * Associate an ELF image with a process.
1131  */
1132
1133 static void
1134 pmcstat_process_elf_exec(struct pmcstat_process *pp,
1135     struct pmcstat_image *image, uintfptr_t entryaddr)
1136 {
1137         uintmax_t libstart;
1138         struct pmcstat_image *rtldimage;
1139
1140         assert(image->pi_type == PMCSTAT_IMAGE_ELF32 ||
1141             image->pi_type == PMCSTAT_IMAGE_ELF64);
1142
1143         /* Create a map entry for the base executable. */
1144         pmcstat_image_link(pp, image, image->pi_vaddr);
1145
1146         /*
1147          * For dynamically linked executables we need to determine
1148          * where the dynamic linker was mapped to for this process,
1149          * Subsequent executable objects that are mapped in by the
1150          * dynamic linker will be tracked by log events of type
1151          * PMCLOG_TYPE_MAP_IN.
1152          */
1153
1154         if (image->pi_isdynamic) {
1155
1156                 /*
1157                  * The runtime loader gets loaded just after the maximum
1158                  * possible heap address.  Like so:
1159                  *
1160                  * [  TEXT DATA BSS HEAP -->*RTLD  SHLIBS   <--STACK]
1161                  * ^                                                ^
1162                  * 0                               VM_MAXUSER_ADDRESS
1163
1164                  *
1165                  * The exact address where the loader gets mapped in
1166                  * will vary according to the size of the executable
1167                  * and the limits on the size of the process'es data
1168                  * segment at the time of exec().  The entry address
1169                  * recorded at process exec time corresponds to the
1170                  * 'start' address inside the dynamic linker.  From
1171                  * this we can figure out the address where the
1172                  * runtime loader's file object had been mapped to.
1173                  */
1174                 rtldimage = pmcstat_image_from_path(image->pi_dynlinkerpath, 0);
1175                 if (rtldimage == NULL) {
1176                         warnx("WARNING: Cannot find image for \"%s\".",
1177                             pmcstat_string_unintern(image->pi_dynlinkerpath));
1178                         pmcstat_stats.ps_exec_errors++;
1179                         return;
1180                 }
1181
1182                 if (rtldimage->pi_type == PMCSTAT_IMAGE_UNKNOWN)
1183                         pmcstat_image_get_elf_params(rtldimage);
1184
1185                 if (rtldimage->pi_type != PMCSTAT_IMAGE_ELF32 &&
1186                     rtldimage->pi_type != PMCSTAT_IMAGE_ELF64) {
1187                         warnx("WARNING: rtld not an ELF object \"%s\".",
1188                             pmcstat_string_unintern(image->pi_dynlinkerpath));
1189                         return;
1190                 }
1191
1192                 libstart = entryaddr - rtldimage->pi_entry;
1193                 pmcstat_image_link(pp, rtldimage, libstart);
1194         }
1195 }
1196
1197 /*
1198  * Find the process descriptor corresponding to a PID.  If 'allocate'
1199  * is zero, we return a NULL if a pid descriptor could not be found or
1200  * a process descriptor process.  If 'allocate' is non-zero, then we
1201  * will attempt to allocate a fresh process descriptor.  Zombie
1202  * process descriptors are only removed if a fresh allocation for the
1203  * same PID is requested.
1204  */
1205
1206 static struct pmcstat_process *
1207 pmcstat_process_lookup(pid_t pid, int allocate)
1208 {
1209         uint32_t hash;
1210         struct pmcstat_pcmap *ppm, *ppmtmp;
1211         struct pmcstat_process *pp, *pptmp;
1212
1213         hash = (uint32_t) pid & PMCSTAT_HASH_MASK;      /* simplicity wins */
1214
1215         LIST_FOREACH_SAFE(pp, &pmcstat_process_hash[hash], pp_next, pptmp)
1216             if (pp->pp_pid == pid) {
1217                     /* Found a descriptor, check and process zombies */
1218                     if (allocate && pp->pp_isactive == 0) {
1219                             /* remove maps */
1220                             TAILQ_FOREACH_SAFE(ppm, &pp->pp_map, ppm_next,
1221                                 ppmtmp) {
1222                                     TAILQ_REMOVE(&pp->pp_map, ppm, ppm_next);
1223                                     free(ppm);
1224                             }
1225                             /* remove process entry */
1226                             LIST_REMOVE(pp, pp_next);
1227                             free(pp);
1228                             break;
1229                     }
1230                     return (pp);
1231             }
1232
1233         if (!allocate)
1234                 return (NULL);
1235
1236         if ((pp = malloc(sizeof(*pp))) == NULL)
1237                 err(EX_OSERR, "ERROR: Cannot allocate pid descriptor");
1238
1239         pp->pp_pid = pid;
1240         pp->pp_isactive = 1;
1241
1242         TAILQ_INIT(&pp->pp_map);
1243
1244         LIST_INSERT_HEAD(&pmcstat_process_hash[hash], pp, pp_next);
1245         return (pp);
1246 }
1247
1248 /*
1249  * Associate an image and a process.
1250  */
1251
1252 static void
1253 pmcstat_process_exec(struct pmcstat_process *pp,
1254     pmcstat_interned_string path, uintfptr_t entryaddr)
1255 {
1256         struct pmcstat_image *image;
1257
1258         if ((image = pmcstat_image_from_path(path, 0)) == NULL) {
1259                 pmcstat_stats.ps_exec_errors++;
1260                 return;
1261         }
1262
1263         if (image->pi_type == PMCSTAT_IMAGE_UNKNOWN)
1264                 pmcstat_image_determine_type(image);
1265
1266         assert(image->pi_type != PMCSTAT_IMAGE_UNKNOWN);
1267
1268         switch (image->pi_type) {
1269         case PMCSTAT_IMAGE_ELF32:
1270         case PMCSTAT_IMAGE_ELF64:
1271                 pmcstat_stats.ps_exec_elf++;
1272                 pmcstat_process_elf_exec(pp, image, entryaddr);
1273                 break;
1274
1275         case PMCSTAT_IMAGE_AOUT:
1276                 pmcstat_stats.ps_exec_aout++;
1277                 pmcstat_process_aout_exec(pp, image, entryaddr);
1278                 break;
1279
1280         case PMCSTAT_IMAGE_INDETERMINABLE:
1281                 pmcstat_stats.ps_exec_indeterminable++;
1282                 break;
1283
1284         default:
1285                 err(EX_SOFTWARE, "ERROR: Unsupported executable type for "
1286                     "\"%s\"", pmcstat_string_unintern(path));
1287         }
1288 }
1289
1290
1291 /*
1292  * Find the map entry associated with process 'p' at PC value 'pc'.
1293  */
1294
1295 struct pmcstat_pcmap *
1296 pmcstat_process_find_map(struct pmcstat_process *p, uintfptr_t pc)
1297 {
1298         struct pmcstat_pcmap *ppm;
1299
1300         TAILQ_FOREACH(ppm, &p->pp_map, ppm_next) {
1301                 if (pc >= ppm->ppm_lowpc && pc < ppm->ppm_highpc)
1302                         return (ppm);
1303                 if (pc < ppm->ppm_lowpc)
1304                         return (NULL);
1305         }
1306
1307         return (NULL);
1308 }
1309
1310 /*
1311  * Convert a hwpmc(4) log to profile information.  A system-wide
1312  * callgraph is generated if FLAG_DO_CALLGRAPHS is set.  gmon.out
1313  * files usable by gprof(1) are created if FLAG_DO_GPROF is set.
1314  */
1315 static int
1316 pmcstat_analyze_log(void)
1317 {
1318         uint32_t cpu, cpuflags;
1319         uintfptr_t pc;
1320         pid_t pid;
1321         struct pmcstat_image *image;
1322         struct pmcstat_process *pp, *ppnew;
1323         struct pmcstat_pcmap *ppm, *ppmtmp;
1324         struct pmclog_ev ev;
1325         struct pmcstat_pmcrecord *pmcr;
1326         pmcstat_interned_string image_path;
1327
1328         assert(args.pa_flags & FLAG_DO_ANALYSIS);
1329
1330         if (elf_version(EV_CURRENT) == EV_NONE)
1331                 err(EX_UNAVAILABLE, "Elf library intialization failed");
1332
1333         while (pmclog_read(args.pa_logparser, &ev) == 0) {
1334                 assert(ev.pl_state == PMCLOG_OK);
1335
1336                 switch (ev.pl_type) {
1337                 case PMCLOG_TYPE_INITIALIZE:
1338                         if ((ev.pl_u.pl_i.pl_version & 0xFF000000) !=
1339                             PMC_VERSION_MAJOR << 24 && args.pa_verbosity > 0)
1340                                 warnx("WARNING: Log version 0x%x does not "
1341                                     "match compiled version 0x%x.",
1342                                     ev.pl_u.pl_i.pl_version,
1343                                     PMC_VERSION_MAJOR);
1344                         break;
1345
1346                 case PMCLOG_TYPE_MAP_IN:
1347                         /*
1348                          * Introduce an address range mapping for a
1349                          * userland process or the kernel (pid == -1).
1350                          *
1351                          * We always allocate a process descriptor so
1352                          * that subsequent samples seen for this
1353                          * address range are mapped to the current
1354                          * object being mapped in.
1355                          */
1356                         pid = ev.pl_u.pl_mi.pl_pid;
1357                         if (pid == -1)
1358                                 pp = pmcstat_kernproc;
1359                         else
1360                                 pp = pmcstat_process_lookup(pid,
1361                                     PMCSTAT_ALLOCATE);
1362
1363                         assert(pp != NULL);
1364
1365                         image_path = pmcstat_string_intern(ev.pl_u.pl_mi.
1366                             pl_pathname);
1367                         image = pmcstat_image_from_path(image_path, pid == -1);
1368                         if (image->pi_type == PMCSTAT_IMAGE_UNKNOWN)
1369                                 pmcstat_image_determine_type(image);
1370                         if (image->pi_type != PMCSTAT_IMAGE_INDETERMINABLE)
1371                                 pmcstat_image_link(pp, image,
1372                                     ev.pl_u.pl_mi.pl_start);
1373                         break;
1374
1375                 case PMCLOG_TYPE_MAP_OUT:
1376                         /*
1377                          * Remove an address map.
1378                          */
1379                         pid = ev.pl_u.pl_mo.pl_pid;
1380                         if (pid == -1)
1381                                 pp = pmcstat_kernproc;
1382                         else
1383                                 pp = pmcstat_process_lookup(pid, 0);
1384
1385                         if (pp == NULL) /* unknown process */
1386                                 break;
1387
1388                         pmcstat_image_unmap(pp, ev.pl_u.pl_mo.pl_start,
1389                             ev.pl_u.pl_mo.pl_end);
1390                         break;
1391
1392                 case PMCLOG_TYPE_PCSAMPLE:
1393                         /*
1394                          * Note: the `PCSAMPLE' log entry is not
1395                          * generated by hpwmc(4) after version 2.
1396                          */
1397
1398                         /*
1399                          * We bring in the gmon file for the image
1400                          * currently associated with the PMC & pid
1401                          * pair and increment the appropriate entry
1402                          * bin inside this.
1403                          */
1404                         pmcstat_stats.ps_samples_total++;
1405                         ps_samples_period++;
1406
1407                         pc = ev.pl_u.pl_s.pl_pc;
1408                         pp = pmcstat_process_lookup(ev.pl_u.pl_s.pl_pid,
1409                             PMCSTAT_ALLOCATE);
1410
1411                         /* Get PMC record. */
1412                         pmcr = pmcstat_lookup_pmcid(ev.pl_u.pl_s.pl_pmcid);
1413                         assert(pmcr != NULL);
1414                         pmcr->pr_samples++;
1415
1416                         /*
1417                          * Call the plugins processing
1418                          * TODO: move pmcstat_process_find_map inside plugins
1419                          */
1420
1421                         if (plugins[args.pa_pplugin].pl_process != NULL)
1422                                 plugins[args.pa_pplugin].pl_process(
1423                                     pp, pmcr, 1, &pc,
1424                                     pmcstat_process_find_map(pp, pc) != NULL, 0);
1425                         plugins[args.pa_plugin].pl_process(
1426                             pp, pmcr, 1, &pc,
1427                             pmcstat_process_find_map(pp, pc) != NULL, 0);
1428                         break;
1429
1430                 case PMCLOG_TYPE_CALLCHAIN:
1431                         pmcstat_stats.ps_samples_total++;
1432                         ps_samples_period++;
1433
1434                         cpuflags = ev.pl_u.pl_cc.pl_cpuflags;
1435                         cpu = PMC_CALLCHAIN_CPUFLAGS_TO_CPU(cpuflags);
1436
1437                         /* Filter on the CPU id. */
1438                         if ((args.pa_cpumask & (1 << cpu)) == 0) {
1439                                 pmcstat_stats.ps_samples_skipped++;
1440                                 break;
1441                         }
1442
1443                         pp = pmcstat_process_lookup(ev.pl_u.pl_cc.pl_pid,
1444                             PMCSTAT_ALLOCATE);
1445
1446                         /* Get PMC record. */
1447                         pmcr = pmcstat_lookup_pmcid(ev.pl_u.pl_cc.pl_pmcid);
1448                         assert(pmcr != NULL);
1449                         pmcr->pr_samples++;
1450
1451                         /*
1452                          * Call the plugins processing
1453                          */
1454
1455                         if (plugins[args.pa_pplugin].pl_process != NULL)
1456                                 plugins[args.pa_pplugin].pl_process(
1457                                     pp, pmcr,
1458                                     ev.pl_u.pl_cc.pl_npc,
1459                                     ev.pl_u.pl_cc.pl_pc,
1460                                     PMC_CALLCHAIN_CPUFLAGS_TO_USERMODE(cpuflags),
1461                                     cpu);
1462                         plugins[args.pa_plugin].pl_process(
1463                             pp, pmcr,
1464                             ev.pl_u.pl_cc.pl_npc,
1465                             ev.pl_u.pl_cc.pl_pc,
1466                             PMC_CALLCHAIN_CPUFLAGS_TO_USERMODE(cpuflags),
1467                             cpu);
1468                         break;
1469
1470                 case PMCLOG_TYPE_PMCALLOCATE:
1471                         /*
1472                          * Record the association pmc id between this
1473                          * PMC and its name.
1474                          */
1475                         pmcstat_pmcid_add(ev.pl_u.pl_a.pl_pmcid,
1476                             pmcstat_string_intern(ev.pl_u.pl_a.pl_evname));
1477                         break;
1478
1479                 case PMCLOG_TYPE_PROCEXEC:
1480
1481                         /*
1482                          * Change the executable image associated with
1483                          * a process.
1484                          */
1485                         pp = pmcstat_process_lookup(ev.pl_u.pl_x.pl_pid,
1486                             PMCSTAT_ALLOCATE);
1487
1488                         /* delete the current process map */
1489                         TAILQ_FOREACH_SAFE(ppm, &pp->pp_map, ppm_next, ppmtmp) {
1490                                 TAILQ_REMOVE(&pp->pp_map, ppm, ppm_next);
1491                                 free(ppm);
1492                         }
1493
1494                         /* associate this process  image */
1495                         image_path = pmcstat_string_intern(
1496                                 ev.pl_u.pl_x.pl_pathname);
1497                         assert(image_path != NULL);
1498                         pmcstat_process_exec(pp, image_path,
1499                             ev.pl_u.pl_x.pl_entryaddr);
1500                         break;
1501
1502                 case PMCLOG_TYPE_PROCEXIT:
1503
1504                         /*
1505                          * Due to the way the log is generated, the
1506                          * last few samples corresponding to a process
1507                          * may appear in the log after the process
1508                          * exit event is recorded.  Thus we keep the
1509                          * process' descriptor and associated data
1510                          * structures around, but mark the process as
1511                          * having exited.
1512                          */
1513                         pp = pmcstat_process_lookup(ev.pl_u.pl_e.pl_pid, 0);
1514                         if (pp == NULL)
1515                                 break;
1516                         pp->pp_isactive = 0;    /* mark as a zombie */
1517                         break;
1518
1519                 case PMCLOG_TYPE_SYSEXIT:
1520                         pp = pmcstat_process_lookup(ev.pl_u.pl_se.pl_pid, 0);
1521                         if (pp == NULL)
1522                                 break;
1523                         pp->pp_isactive = 0;    /* make a zombie */
1524                         break;
1525
1526                 case PMCLOG_TYPE_PROCFORK:
1527
1528                         /*
1529                          * Allocate a process descriptor for the new
1530                          * (child) process.
1531                          */
1532                         ppnew =
1533                             pmcstat_process_lookup(ev.pl_u.pl_f.pl_newpid,
1534                                 PMCSTAT_ALLOCATE);
1535
1536                         /*
1537                          * If we had been tracking the parent, clone
1538                          * its address maps.
1539                          */
1540                         pp = pmcstat_process_lookup(ev.pl_u.pl_f.pl_oldpid, 0);
1541                         if (pp == NULL)
1542                                 break;
1543                         TAILQ_FOREACH(ppm, &pp->pp_map, ppm_next)
1544                             pmcstat_image_link(ppnew, ppm->ppm_image,
1545                                 ppm->ppm_lowpc);
1546                         break;
1547
1548                 default:        /* other types of entries are not relevant */
1549                         break;
1550                 }
1551         }
1552
1553         if (ev.pl_state == PMCLOG_EOF)
1554                 return (PMCSTAT_FINISHED);
1555         else if (ev.pl_state == PMCLOG_REQUIRE_DATA)
1556                 return (PMCSTAT_RUNNING);
1557
1558         err(EX_DATAERR, "ERROR: event parsing failed (record %jd, "
1559             "offset 0x%jx)", (uintmax_t) ev.pl_count + 1, ev.pl_offset);
1560 }
1561
1562 /*
1563  * Print log entries as text.
1564  */
1565
1566 static int
1567 pmcstat_print_log(void)
1568 {
1569         struct pmclog_ev ev;
1570         uint32_t npc;
1571
1572         while (pmclog_read(args.pa_logparser, &ev) == 0) {
1573                 assert(ev.pl_state == PMCLOG_OK);
1574                 switch (ev.pl_type) {
1575                 case PMCLOG_TYPE_CALLCHAIN:
1576                         PMCSTAT_PRINT_ENTRY("callchain",
1577                             "%d 0x%x %d %d %c", ev.pl_u.pl_cc.pl_pid,
1578                             ev.pl_u.pl_cc.pl_pmcid,
1579                             PMC_CALLCHAIN_CPUFLAGS_TO_CPU(ev.pl_u.pl_cc. \
1580                                 pl_cpuflags), ev.pl_u.pl_cc.pl_npc,
1581                             PMC_CALLCHAIN_CPUFLAGS_TO_USERMODE(ev.pl_u.pl_cc.\
1582                                 pl_cpuflags) ? 'u' : 's');
1583                         for (npc = 0; npc < ev.pl_u.pl_cc.pl_npc; npc++)
1584                                 PMCSTAT_PRINT_ENTRY("...", "%p",
1585                                     (void *) ev.pl_u.pl_cc.pl_pc[npc]);
1586                         break;
1587                 case PMCLOG_TYPE_CLOSELOG:
1588                         PMCSTAT_PRINT_ENTRY("closelog",);
1589                         break;
1590                 case PMCLOG_TYPE_DROPNOTIFY:
1591                         PMCSTAT_PRINT_ENTRY("drop",);
1592                         break;
1593                 case PMCLOG_TYPE_INITIALIZE:
1594                         PMCSTAT_PRINT_ENTRY("initlog","0x%x \"%s\"",
1595                             ev.pl_u.pl_i.pl_version,
1596                             pmc_name_of_cputype(ev.pl_u.pl_i.pl_arch));
1597                         if ((ev.pl_u.pl_i.pl_version & 0xFF000000) !=
1598                             PMC_VERSION_MAJOR << 24 && args.pa_verbosity > 0)
1599                                 warnx("WARNING: Log version 0x%x != expected "
1600                                     "version 0x%x.", ev.pl_u.pl_i.pl_version,
1601                                     PMC_VERSION);
1602                         break;
1603                 case PMCLOG_TYPE_MAP_IN:
1604                         PMCSTAT_PRINT_ENTRY("map-in","%d %p \"%s\"",
1605                             ev.pl_u.pl_mi.pl_pid,
1606                             (void *) ev.pl_u.pl_mi.pl_start,
1607                             ev.pl_u.pl_mi.pl_pathname);
1608                         break;
1609                 case PMCLOG_TYPE_MAP_OUT:
1610                         PMCSTAT_PRINT_ENTRY("map-out","%d %p %p",
1611                             ev.pl_u.pl_mo.pl_pid,
1612                             (void *) ev.pl_u.pl_mo.pl_start,
1613                             (void *) ev.pl_u.pl_mo.pl_end);
1614                         break;
1615                 case PMCLOG_TYPE_PCSAMPLE:
1616                         PMCSTAT_PRINT_ENTRY("sample","0x%x %d %p %c",
1617                             ev.pl_u.pl_s.pl_pmcid,
1618                             ev.pl_u.pl_s.pl_pid,
1619                             (void *) ev.pl_u.pl_s.pl_pc,
1620                             ev.pl_u.pl_s.pl_usermode ? 'u' : 's');
1621                         break;
1622                 case PMCLOG_TYPE_PMCALLOCATE:
1623                         PMCSTAT_PRINT_ENTRY("allocate","0x%x \"%s\" 0x%x",
1624                             ev.pl_u.pl_a.pl_pmcid,
1625                             ev.pl_u.pl_a.pl_evname,
1626                             ev.pl_u.pl_a.pl_flags);
1627                         break;
1628                 case PMCLOG_TYPE_PMCATTACH:
1629                         PMCSTAT_PRINT_ENTRY("attach","0x%x %d \"%s\"",
1630                             ev.pl_u.pl_t.pl_pmcid,
1631                             ev.pl_u.pl_t.pl_pid,
1632                             ev.pl_u.pl_t.pl_pathname);
1633                         break;
1634                 case PMCLOG_TYPE_PMCDETACH:
1635                         PMCSTAT_PRINT_ENTRY("detach","0x%x %d",
1636                             ev.pl_u.pl_d.pl_pmcid,
1637                             ev.pl_u.pl_d.pl_pid);
1638                         break;
1639                 case PMCLOG_TYPE_PROCCSW:
1640                         PMCSTAT_PRINT_ENTRY("cswval","0x%x %d %jd",
1641                             ev.pl_u.pl_c.pl_pmcid,
1642                             ev.pl_u.pl_c.pl_pid,
1643                             ev.pl_u.pl_c.pl_value);
1644                         break;
1645                 case PMCLOG_TYPE_PROCEXEC:
1646                         PMCSTAT_PRINT_ENTRY("exec","0x%x %d %p \"%s\"",
1647                             ev.pl_u.pl_x.pl_pmcid,
1648                             ev.pl_u.pl_x.pl_pid,
1649                             (void *) ev.pl_u.pl_x.pl_entryaddr,
1650                             ev.pl_u.pl_x.pl_pathname);
1651                         break;
1652                 case PMCLOG_TYPE_PROCEXIT:
1653                         PMCSTAT_PRINT_ENTRY("exitval","0x%x %d %jd",
1654                             ev.pl_u.pl_e.pl_pmcid,
1655                             ev.pl_u.pl_e.pl_pid,
1656                             ev.pl_u.pl_e.pl_value);
1657                         break;
1658                 case PMCLOG_TYPE_PROCFORK:
1659                         PMCSTAT_PRINT_ENTRY("fork","%d %d",
1660                             ev.pl_u.pl_f.pl_oldpid,
1661                             ev.pl_u.pl_f.pl_newpid);
1662                         break;
1663                 case PMCLOG_TYPE_USERDATA:
1664                         PMCSTAT_PRINT_ENTRY("userdata","0x%x",
1665                             ev.pl_u.pl_u.pl_userdata);
1666                         break;
1667                 case PMCLOG_TYPE_SYSEXIT:
1668                         PMCSTAT_PRINT_ENTRY("exit","%d",
1669                             ev.pl_u.pl_se.pl_pid);
1670                         break;
1671                 default:
1672                         fprintf(args.pa_printfile, "unknown event (type %d).\n",
1673                             ev.pl_type);
1674                 }
1675         }
1676
1677         if (ev.pl_state == PMCLOG_EOF)
1678                 return (PMCSTAT_FINISHED);
1679         else if (ev.pl_state ==  PMCLOG_REQUIRE_DATA)
1680                 return (PMCSTAT_RUNNING);
1681
1682         errx(EX_DATAERR, "ERROR: event parsing failed "
1683             "(record %jd, offset 0x%jx).",
1684             (uintmax_t) ev.pl_count + 1, ev.pl_offset);
1685         /*NOTREACHED*/
1686 }
1687
1688 /*
1689  * Public Interfaces.
1690  */
1691
1692 /*
1693  * Close a logfile, after first flushing all in-module queued data.
1694  */
1695
1696 int
1697 pmcstat_close_log(void)
1698 {
1699         /* If a local logfile is configured ask the kernel to stop
1700          * and flush data. Kernel will close the file when data is flushed
1701          * so keep the status to EXITING.
1702          */
1703         if (args.pa_logfd != -1) {
1704                 if (pmc_flush_logfile() < 0)
1705                         err(EX_OSERR, "ERROR: logging failed");
1706         }
1707
1708         return (args.pa_flags & FLAG_HAS_PIPE ? PMCSTAT_EXITING :
1709             PMCSTAT_FINISHED);
1710 }
1711
1712
1713
1714 /*
1715  * Open a log file, for reading or writing.
1716  *
1717  * The function returns the fd of a successfully opened log or -1 in
1718  * case of failure.
1719  */
1720
1721 int
1722 pmcstat_open_log(const char *path, int mode)
1723 {
1724         int error, fd, cfd;
1725         size_t hlen;
1726         const char *p, *errstr;
1727         struct addrinfo hints, *res, *res0;
1728         char hostname[MAXHOSTNAMELEN];
1729
1730         errstr = NULL;
1731         fd = -1;
1732
1733         /*
1734          * If 'path' is "-" then open one of stdin or stdout depending
1735          * on the value of 'mode'.
1736          *
1737          * If 'path' contains a ':' and does not start with a '/' or '.',
1738          * and is being opened for writing, treat it as a "host:port"
1739          * specification and open a network socket.
1740          *
1741          * Otherwise, treat 'path' as a file name and open that.
1742          */
1743         if (path[0] == '-' && path[1] == '\0')
1744                 fd = (mode == PMCSTAT_OPEN_FOR_READ) ? 0 : 1;
1745         else if (path[0] != '/' &&
1746             path[0] != '.' && strchr(path, ':') != NULL) {
1747
1748                 p = strrchr(path, ':');
1749                 hlen = p - path;
1750                 if (p == path || hlen >= sizeof(hostname)) {
1751                         errstr = strerror(EINVAL);
1752                         goto done;
1753                 }
1754
1755                 assert(hlen < sizeof(hostname));
1756                 (void) strncpy(hostname, path, hlen);
1757                 hostname[hlen] = '\0';
1758
1759                 (void) memset(&hints, 0, sizeof(hints));
1760                 hints.ai_family = AF_UNSPEC;
1761                 hints.ai_socktype = SOCK_STREAM;
1762                 if ((error = getaddrinfo(hostname, p+1, &hints, &res0)) != 0) {
1763                         errstr = gai_strerror(error);
1764                         goto done;
1765                 }
1766
1767                 fd = -1;
1768                 for (res = res0; res; res = res->ai_next) {
1769                         if ((fd = socket(res->ai_family, res->ai_socktype,
1770                             res->ai_protocol)) < 0) {
1771                                 errstr = strerror(errno);
1772                                 continue;
1773                         }
1774                         if (mode == PMCSTAT_OPEN_FOR_READ) {
1775                                 if (bind(fd, res->ai_addr, res->ai_addrlen) < 0) {
1776                                         errstr = strerror(errno);
1777                                         (void) close(fd);
1778                                         fd = -1;
1779                                         continue;
1780                                 }
1781                                 listen(fd, 1);
1782                                 cfd = accept(fd, NULL, NULL);
1783                                 (void) close(fd);
1784                                 if (cfd < 0) {
1785                                         errstr = strerror(errno);
1786                                         fd = -1;
1787                                         break;
1788                                 }
1789                                 fd = cfd;
1790                         } else {
1791                                 if (connect(fd, res->ai_addr, res->ai_addrlen) < 0) {
1792                                         errstr = strerror(errno);
1793                                         (void) close(fd);
1794                                         fd = -1;
1795                                         continue;
1796                                 }
1797                         }
1798                         errstr = NULL;
1799                         break;
1800                 }
1801                 freeaddrinfo(res0);
1802
1803         } else if ((fd = open(path, mode == PMCSTAT_OPEN_FOR_READ ?
1804                     O_RDONLY : (O_WRONLY|O_CREAT|O_TRUNC),
1805                     S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
1806                         errstr = strerror(errno);
1807
1808   done:
1809         if (errstr)
1810                 errx(EX_OSERR, "ERROR: Cannot open \"%s\" for %s: %s.", path,
1811                     (mode == PMCSTAT_OPEN_FOR_READ ? "reading" : "writing"),
1812                     errstr);
1813
1814         return (fd);
1815 }
1816
1817 /*
1818  * Process a log file in offline analysis mode.
1819  */
1820
1821 int
1822 pmcstat_process_log(void)
1823 {
1824
1825         /*
1826          * If analysis has not been asked for, just print the log to
1827          * the current output file.
1828          */
1829         if (args.pa_flags & FLAG_DO_PRINT)
1830                 return (pmcstat_print_log());
1831         else
1832                 return (pmcstat_analyze_log());
1833 }
1834
1835 /*
1836  * Refresh top display.
1837  */
1838
1839 static void
1840 pmcstat_refresh_top(void)
1841 {
1842         int v_attrs;
1843         float v;
1844         char pmcname[40];
1845         struct pmcstat_pmcrecord *pmcpr;
1846
1847         /* If in pause mode do not refresh display. */
1848         if (pmcstat_pause)
1849                 return;
1850
1851         /* Wait until PMC pop in the log. */
1852         pmcpr = pmcstat_pmcindex_to_pmcr(pmcstat_pmcinfilter);
1853         if (pmcpr == NULL)
1854                 return;
1855
1856         /* Format PMC name. */
1857         if (pmcstat_mergepmc)
1858                 snprintf(pmcname, sizeof(pmcname), "[%s]",
1859                     pmcstat_string_unintern(pmcpr->pr_pmcname));
1860         else
1861                 snprintf(pmcname, sizeof(pmcname), "%s.%d",
1862                     pmcstat_string_unintern(pmcpr->pr_pmcname),
1863                     pmcstat_pmcinfilter);
1864
1865         /* Format samples count. */
1866         if (ps_samples_period > 0)
1867                 v = (pmcpr->pr_samples * 100.0) / ps_samples_period;
1868         else
1869                 v = 0.;
1870         v_attrs = PMCSTAT_ATTRPERCENT(v);
1871
1872         PMCSTAT_PRINTBEGIN();
1873         PMCSTAT_PRINTW("PMC: %s Samples: %u ",
1874             pmcname,
1875             pmcpr->pr_samples);
1876         PMCSTAT_ATTRON(v_attrs);
1877         PMCSTAT_PRINTW("(%.1f%%) ", v);
1878         PMCSTAT_ATTROFF(v_attrs);
1879         PMCSTAT_PRINTW(", %u unresolved\n\n",
1880             pmcpr->pr_dubious_frames);
1881         if (plugins[args.pa_plugin].pl_topdisplay != NULL)
1882                 plugins[args.pa_plugin].pl_topdisplay();
1883         PMCSTAT_PRINTEND();
1884 }
1885
1886 /*
1887  * Find the next pmc index to display.
1888  */
1889
1890 static void
1891 pmcstat_changefilter(void)
1892 {
1893         int pmcin;
1894         struct pmcstat_pmcrecord *pmcr;
1895
1896         /*
1897          * Find the next merge target.
1898          */
1899         if (pmcstat_mergepmc) {
1900                 pmcin = pmcstat_pmcinfilter;
1901
1902                 do {
1903                         pmcr = pmcstat_pmcindex_to_pmcr(pmcstat_pmcinfilter);
1904                         if (pmcr == NULL || pmcr == pmcr->pr_merge)
1905                                 break;
1906
1907                         pmcstat_pmcinfilter++;
1908                         if (pmcstat_pmcinfilter >= pmcstat_npmcs)
1909                                 pmcstat_pmcinfilter = 0;
1910
1911                 } while (pmcstat_pmcinfilter != pmcin);
1912         }
1913 }
1914
1915 /*
1916  * Top mode keypress.
1917  */
1918
1919 int
1920 pmcstat_keypress_log(void)
1921 {
1922         int c, ret = 0;
1923         WINDOW *w;
1924
1925         w = newwin(1, 0, 1, 0);
1926         c = wgetch(w);
1927         wprintw(w, "Key: %c => ", c);
1928         switch (c) {
1929         case 'c':
1930                 wprintw(w, "enter mode 'd' or 'a' => ");
1931                 c = wgetch(w);
1932                 if (c == 'd') {
1933                         args.pa_topmode = PMCSTAT_TOP_DELTA;
1934                         wprintw(w, "switching to delta mode");
1935                 } else {
1936                         args.pa_topmode = PMCSTAT_TOP_ACCUM;
1937                         wprintw(w, "switching to accumulation mode");
1938                 }
1939                 break;
1940         case 'm':
1941                 pmcstat_mergepmc = !pmcstat_mergepmc;
1942                 /*
1943                  * Changing merge state require data reset.
1944                  */
1945                 if (plugins[args.pa_plugin].pl_shutdown != NULL)
1946                         plugins[args.pa_plugin].pl_shutdown(NULL);
1947                 pmcstat_stats_reset(0);
1948                 if (plugins[args.pa_plugin].pl_init != NULL)
1949                         plugins[args.pa_plugin].pl_init();
1950
1951                 /* Update filter to be on a merge target. */
1952                 pmcstat_changefilter();
1953                 wprintw(w, "merge PMC %s", pmcstat_mergepmc ? "on" : "off");
1954                 break;
1955         case 'n':
1956                 /* Close current plugin. */
1957                 if (plugins[args.pa_plugin].pl_shutdown != NULL)
1958                         plugins[args.pa_plugin].pl_shutdown(NULL);
1959
1960                 /* Find next top display available. */
1961                 do {
1962                         args.pa_plugin++;
1963                         if (plugins[args.pa_plugin].pl_name == NULL)
1964                                 args.pa_plugin = 0;
1965                 } while (plugins[args.pa_plugin].pl_topdisplay == NULL);
1966
1967                 /* Open new plugin. */
1968                 pmcstat_stats_reset(0);
1969                 if (plugins[args.pa_plugin].pl_init != NULL)
1970                         plugins[args.pa_plugin].pl_init();
1971                 wprintw(w, "switching to plugin %s",
1972                     plugins[args.pa_plugin].pl_name);
1973                 break;
1974         case 'p':
1975                 pmcstat_pmcinfilter++;
1976                 if (pmcstat_pmcinfilter >= pmcstat_npmcs)
1977                         pmcstat_pmcinfilter = 0;
1978                 pmcstat_changefilter();
1979                 wprintw(w, "switching to PMC %s.%d",
1980                     pmcstat_pmcindex_to_name(pmcstat_pmcinfilter),
1981                     pmcstat_pmcinfilter);
1982                 break;
1983         case ' ':
1984                 pmcstat_pause = !pmcstat_pause;
1985                 if (pmcstat_pause)
1986                         wprintw(w, "pause => press space again to continue");
1987                 break;
1988         case 'q':
1989                 wprintw(w, "exiting...");
1990                 ret = 1;
1991                 break;
1992         default:
1993                 if (plugins[args.pa_plugin].pl_topkeypress != NULL)
1994                         if (plugins[args.pa_plugin].pl_topkeypress(c, w))
1995                                 ret = 1;
1996         }
1997
1998         wrefresh(w);
1999         delwin(w);
2000         return ret;
2001 }
2002
2003
2004 /*
2005  * Top mode display.
2006  */
2007
2008 void
2009 pmcstat_display_log(void)
2010 {
2011
2012         pmcstat_refresh_top();
2013
2014         /* Reset everythings if delta mode. */
2015         if (args.pa_topmode == PMCSTAT_TOP_DELTA) {
2016                 if (plugins[args.pa_plugin].pl_shutdown != NULL)
2017                         plugins[args.pa_plugin].pl_shutdown(NULL);
2018                 pmcstat_stats_reset(0);
2019                 if (plugins[args.pa_plugin].pl_init != NULL)
2020                         plugins[args.pa_plugin].pl_init();
2021         }
2022
2023 }
2024
2025 /*
2026  * Configure a plugins.
2027  */
2028
2029 void
2030 pmcstat_pluginconfigure_log(char *opt)
2031 {
2032
2033         if (strncmp(opt, "threshold=", 10) == 0) {
2034                 pmcstat_threshold = atof(opt+10);
2035         } else {
2036                 if (plugins[args.pa_plugin].pl_configure != NULL) {
2037                         if (!plugins[args.pa_plugin].pl_configure(opt))
2038                                 err(EX_USAGE,
2039                                     "ERROR: unknown option <%s>.", opt);
2040                 }
2041         }
2042 }
2043
2044 /*
2045  * Initialize module.
2046  */
2047
2048 void
2049 pmcstat_initialize_logging(void)
2050 {
2051         int i;
2052
2053         /* use a convenient format for 'ldd' output */
2054         if (setenv("LD_TRACE_LOADED_OBJECTS_FMT1","%o \"%p\" %x\n",1) != 0)
2055                 err(EX_OSERR, "ERROR: Cannot setenv");
2056
2057         /* Initialize hash tables */
2058         pmcstat_string_initialize();
2059         for (i = 0; i < PMCSTAT_NHASH; i++) {
2060                 LIST_INIT(&pmcstat_image_hash[i]);
2061                 LIST_INIT(&pmcstat_process_hash[i]);
2062         }
2063
2064         /*
2065          * Create a fake 'process' entry for the kernel with pid -1.
2066          * hwpmc(4) will subsequently inform us about where the kernel
2067          * and any loaded kernel modules are mapped.
2068          */
2069         if ((pmcstat_kernproc = pmcstat_process_lookup((pid_t) -1,
2070                  PMCSTAT_ALLOCATE)) == NULL)
2071                 err(EX_OSERR, "ERROR: Cannot initialize logging");
2072
2073         /* PMC count. */
2074         pmcstat_npmcs = 0;
2075
2076         /* Merge PMC with same name. */
2077         pmcstat_mergepmc = args.pa_mergepmc;
2078
2079         /*
2080          * Initialize plugins
2081          */
2082
2083         if (plugins[args.pa_pplugin].pl_init != NULL)
2084                 plugins[args.pa_pplugin].pl_init();
2085         if (plugins[args.pa_plugin].pl_init != NULL)
2086                 plugins[args.pa_plugin].pl_init();
2087 }
2088
2089 /*
2090  * Shutdown module.
2091  */
2092
2093 void
2094 pmcstat_shutdown_logging(void)
2095 {
2096         int i;
2097         FILE *mf;
2098         struct pmcstat_image *pi, *pitmp;
2099         struct pmcstat_process *pp, *pptmp;
2100         struct pmcstat_pcmap *ppm, *ppmtmp;
2101
2102         /* determine where to send the map file */
2103         mf = NULL;
2104         if (args.pa_mapfilename != NULL)
2105                 mf = (strcmp(args.pa_mapfilename, "-") == 0) ?
2106                     args.pa_printfile : fopen(args.pa_mapfilename, "w");
2107
2108         if (mf == NULL && args.pa_flags & FLAG_DO_GPROF &&
2109             args.pa_verbosity >= 2)
2110                 mf = args.pa_printfile;
2111
2112         if (mf)
2113                 (void) fprintf(mf, "MAP:\n");
2114
2115         /*
2116          * Shutdown the plugins
2117          */
2118
2119         if (plugins[args.pa_plugin].pl_shutdown != NULL)
2120                 plugins[args.pa_plugin].pl_shutdown(mf);
2121         if (plugins[args.pa_pplugin].pl_shutdown != NULL)
2122                 plugins[args.pa_pplugin].pl_shutdown(mf);
2123
2124         for (i = 0; i < PMCSTAT_NHASH; i++) {
2125                 LIST_FOREACH_SAFE(pi, &pmcstat_image_hash[i], pi_next,
2126                     pitmp) {
2127                         if (plugins[args.pa_plugin].pl_shutdownimage != NULL)
2128                                 plugins[args.pa_plugin].pl_shutdownimage(pi);
2129                         if (plugins[args.pa_pplugin].pl_shutdownimage != NULL)
2130                                 plugins[args.pa_pplugin].pl_shutdownimage(pi);
2131
2132                         free(pi->pi_symbols);
2133                         if (pi->pi_addr2line != NULL)
2134                                 pclose(pi->pi_addr2line);
2135                         LIST_REMOVE(pi, pi_next);
2136                         free(pi);
2137                 }
2138
2139                 LIST_FOREACH_SAFE(pp, &pmcstat_process_hash[i], pp_next,
2140                     pptmp) {
2141                         TAILQ_FOREACH_SAFE(ppm, &pp->pp_map, ppm_next, ppmtmp) {
2142                                 TAILQ_REMOVE(&pp->pp_map, ppm, ppm_next);
2143                                 free(ppm);
2144                         }
2145                         LIST_REMOVE(pp, pp_next);
2146                         free(pp);
2147                 }
2148         }
2149
2150         pmcstat_string_shutdown();
2151
2152         /*
2153          * Print errors unless -q was specified.  Print all statistics
2154          * if verbosity > 1.
2155          */
2156 #define PRINT(N,V) do {                                                 \
2157                 if (pmcstat_stats.ps_##V || args.pa_verbosity >= 2)     \
2158                         (void) fprintf(args.pa_printfile, " %-40s %d\n",\
2159                             N, pmcstat_stats.ps_##V);                   \
2160         } while (0)
2161
2162         if (args.pa_verbosity >= 1 && (args.pa_flags & FLAG_DO_ANALYSIS)) {
2163                 (void) fprintf(args.pa_printfile, "CONVERSION STATISTICS:\n");
2164                 PRINT("#exec/a.out", exec_aout);
2165                 PRINT("#exec/elf", exec_elf);
2166                 PRINT("#exec/unknown", exec_indeterminable);
2167                 PRINT("#exec handling errors", exec_errors);
2168                 PRINT("#samples/total", samples_total);
2169                 PRINT("#samples/unclaimed", samples_unknown_offset);
2170                 PRINT("#samples/unknown-object", samples_indeterminable);
2171                 PRINT("#samples/unknown-function", samples_unknown_function);
2172                 PRINT("#callchain/dubious-frames", callchain_dubious_frames);
2173         }
2174
2175         if (mf)
2176                 (void) fclose(mf);
2177 }