1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/tools/reorder/histogram.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,142 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +/* 1.9 + 1.10 + A program that computes a call histogram from runtime call 1.11 + information. It reads a list of address references (e.g., as 1.12 + computed by libcygprof.so), and uses an ELF image to map the 1.13 + addresses to functions. 1.14 + 1.15 + */ 1.16 + 1.17 +#include <fstream> 1.18 +#include <hash_map> 1.19 +#include <limits.h> 1.20 +#include <unistd.h> 1.21 +#include <stdio.h> 1.22 +#include <fcntl.h> 1.23 + 1.24 +#include "elf_symbol_table.h" 1.25 + 1.26 +#define _GNU_SOURCE 1.27 +#include <getopt.h> 1.28 + 1.29 +const char *opt_exe; 1.30 +int opt_tick = 0; 1.31 + 1.32 +elf_symbol_table table; 1.33 + 1.34 +typedef hash_map<unsigned int, unsigned int> histogram_t; 1.35 +histogram_t histogram; 1.36 + 1.37 +static struct option long_options[] = { 1.38 + { "exe", required_argument, 0, 'e' }, 1.39 + { "tick", optional_argument, 0, 't' }, 1.40 + { 0, 0, 0, 0 } 1.41 +}; 1.42 + 1.43 +static void 1.44 +usage(const char *name) 1.45 +{ 1.46 + cerr << "usage: " << name << " --exe=<image> [--tick[=count]]" << endl; 1.47 +} 1.48 + 1.49 +static void 1.50 +map_addrs(int fd) 1.51 +{ 1.52 + // Read the binary addresses from stdin. 1.53 + unsigned int buf[128]; 1.54 + ssize_t cb; 1.55 + 1.56 + unsigned int count = 0; 1.57 + while ((cb = read(fd, buf, sizeof buf)) > 0) { 1.58 + if (cb % sizeof buf[0]) 1.59 + fprintf(stderr, "unaligned read\n"); 1.60 + 1.61 + unsigned int *addr = buf; 1.62 + unsigned int *limit = buf + (cb / 4); 1.63 + 1.64 + for (; addr < limit; ++addr) { 1.65 + const Elf32_Sym *sym = table.lookup(*addr); 1.66 + if (sym) 1.67 + ++histogram[reinterpret_cast<unsigned int>(sym)]; 1.68 + 1.69 + if (opt_tick && (++count % opt_tick == 0)) { 1.70 + cerr << "."; 1.71 + flush(cerr); 1.72 + } 1.73 + } 1.74 + } 1.75 + 1.76 + if (opt_tick) 1.77 + cerr << endl; 1.78 +} 1.79 + 1.80 +int 1.81 +main(int argc, char *argv[]) 1.82 +{ 1.83 + int c; 1.84 + while (1) { 1.85 + int option_index = 0; 1.86 + c = getopt_long(argc, argv, "e:t", long_options, &option_index); 1.87 + 1.88 + if (c < 0) 1.89 + break; 1.90 + 1.91 + switch (c) { 1.92 + case 'e': 1.93 + opt_exe = optarg; 1.94 + break; 1.95 + 1.96 + case 't': 1.97 + opt_tick = optarg ? atoi(optarg) : 1000000; 1.98 + break; 1.99 + 1.100 + default: 1.101 + usage(argv[0]); 1.102 + return 1; 1.103 + } 1.104 + } 1.105 + 1.106 + if (! opt_exe) { 1.107 + usage(argv[0]); 1.108 + return 1; 1.109 + } 1.110 + 1.111 + table.init(opt_exe); 1.112 + 1.113 + // Process addresses. 1.114 + if (optind >= argc) { 1.115 + map_addrs(STDIN_FILENO); 1.116 + } 1.117 + else { 1.118 + do { 1.119 + int fd = open(argv[optind], O_RDONLY); 1.120 + if (fd < 0) { 1.121 + perror(argv[optind]); 1.122 + return 1; 1.123 + } 1.124 + 1.125 + map_addrs(fd); 1.126 + close(fd); 1.127 + } while (++optind < argc); 1.128 + } 1.129 + 1.130 + // Emit the histogram. 1.131 + histogram_t::const_iterator limit = histogram.end(); 1.132 + histogram_t::const_iterator i; 1.133 + for (i = histogram.begin(); i != limit; ++i) { 1.134 + const Elf32_Sym *sym = reinterpret_cast<const Elf32_Sym *>(i->first); 1.135 + cout.form("%08x %6d %2d %10d ", 1.136 + sym->st_value, 1.137 + sym->st_size, 1.138 + sym->st_shndx, 1.139 + i->second); 1.140 + 1.141 + cout << table.get_symbol_name(sym) << endl; 1.142 + } 1.143 + 1.144 + return 0; 1.145 +}