diff -r 000000000000 -r 6474c204b198 tools/reorder/histogram.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/reorder/histogram.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,142 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + + A program that computes a call histogram from runtime call + information. It reads a list of address references (e.g., as + computed by libcygprof.so), and uses an ELF image to map the + addresses to functions. + + */ + +#include +#include +#include +#include +#include +#include + +#include "elf_symbol_table.h" + +#define _GNU_SOURCE +#include + +const char *opt_exe; +int opt_tick = 0; + +elf_symbol_table table; + +typedef hash_map histogram_t; +histogram_t histogram; + +static struct option long_options[] = { + { "exe", required_argument, 0, 'e' }, + { "tick", optional_argument, 0, 't' }, + { 0, 0, 0, 0 } +}; + +static void +usage(const char *name) +{ + cerr << "usage: " << name << " --exe= [--tick[=count]]" << endl; +} + +static void +map_addrs(int fd) +{ + // Read the binary addresses from stdin. + unsigned int buf[128]; + ssize_t cb; + + unsigned int count = 0; + while ((cb = read(fd, buf, sizeof buf)) > 0) { + if (cb % sizeof buf[0]) + fprintf(stderr, "unaligned read\n"); + + unsigned int *addr = buf; + unsigned int *limit = buf + (cb / 4); + + for (; addr < limit; ++addr) { + const Elf32_Sym *sym = table.lookup(*addr); + if (sym) + ++histogram[reinterpret_cast(sym)]; + + if (opt_tick && (++count % opt_tick == 0)) { + cerr << "."; + flush(cerr); + } + } + } + + if (opt_tick) + cerr << endl; +} + +int +main(int argc, char *argv[]) +{ + int c; + while (1) { + int option_index = 0; + c = getopt_long(argc, argv, "e:t", long_options, &option_index); + + if (c < 0) + break; + + switch (c) { + case 'e': + opt_exe = optarg; + break; + + case 't': + opt_tick = optarg ? atoi(optarg) : 1000000; + break; + + default: + usage(argv[0]); + return 1; + } + } + + if (! opt_exe) { + usage(argv[0]); + return 1; + } + + table.init(opt_exe); + + // Process addresses. + if (optind >= argc) { + map_addrs(STDIN_FILENO); + } + else { + do { + int fd = open(argv[optind], O_RDONLY); + if (fd < 0) { + perror(argv[optind]); + return 1; + } + + map_addrs(fd); + close(fd); + } while (++optind < argc); + } + + // Emit the histogram. + histogram_t::const_iterator limit = histogram.end(); + histogram_t::const_iterator i; + for (i = histogram.begin(); i != limit; ++i) { + const Elf32_Sym *sym = reinterpret_cast(i->first); + cout.form("%08x %6d %2d %10d ", + sym->st_value, + sym->st_size, + sym->st_shndx, + i->second); + + cout << table.get_symbol_name(sym) << endl; + } + + return 0; +}