1e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata/* 2e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * This file is part of ltrace. 32834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata * Copyright (C) 2012,2013 Petr Machata, Red Hat Inc. 4e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * Copyright (C) 2003,2008,2009 Juan Cespedes 5e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * Copyright (C) 2006 Ian Wienand 6e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * 7e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * This program is free software; you can redistribute it and/or 8e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * modify it under the terms of the GNU General Public License as 9e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * published by the Free Software Foundation; either version 2 of the 10e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * License, or (at your option) any later version. 11e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * 12e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * This program is distributed in the hope that it will be useful, but 13e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * WITHOUT ANY WARRANTY; without even the implied warranty of 14e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * General Public License for more details. 16e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * 17e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * You should have received a copy of the GNU General Public License 18e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * along with this program; if not, write to the Free Software 19e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * 02110-1301 USA 21e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata */ 22e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata 23bfdaacb835f3dbaed88242100bd8604b5fc7d67fIan Wienand#include "config.h" 24bfdaacb835f3dbaed88242100bd8604b5fc7d67fIan Wienand 258a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata#include <sys/time.h> 26d65efa37b1fd73305ce4469841dc760514d74202Juan Cespedes#include <stdio.h> 27d65efa37b1fd73305ce4469841dc760514d74202Juan Cespedes#include <stdlib.h> 288a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata#include <string.h> 29d65efa37b1fd73305ce4469841dc760514d74202Juan Cespedes 308a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata#include "summary.h" 318a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata#include "dict.h" 328a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata#include "library.h" 338a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata#include "options.h" 34d65efa37b1fd73305ce4469841dc760514d74202Juan Cespedes 352834f72014dc8b13ba13b9a06da744dd023f3555Petr Machatastruct entry_st { 362834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata const char *name; 372834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata unsigned count; 38d65efa37b1fd73305ce4469841dc760514d74202Juan Cespedes struct timeval tv; 392834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata}; 40d65efa37b1fd73305ce4469841dc760514d74202Juan Cespedes 412834f72014dc8b13ba13b9a06da744dd023f3555Petr Machatastruct fill_struct_data { 422834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata struct vect entries; 432834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata unsigned tot_count; 442834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata unsigned long tot_usecs; 452834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata}; 46d65efa37b1fd73305ce4469841dc760514d74202Juan Cespedes 478a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machatastruct opt_c_struct { 488a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata int count; 498a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata struct timeval tv; 508a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata}; 518a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata 528a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machatastatic struct dict *dict_opt_c; 538a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata 548a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machatastruct timedelta 558a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machatacalc_time_spent(struct timeval start) 568a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata{ 578a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata struct timeval tv; 588a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata gettimeofday(&tv, NULL); 598a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata 608a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata struct timeval diff; 618a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata diff.tv_sec = tv.tv_sec - start.tv_sec; 628a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata if (tv.tv_usec >= start.tv_usec) { 638a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata diff.tv_usec = tv.tv_usec - start.tv_usec; 648a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata } else { 658a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata diff.tv_sec--; 668a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata diff.tv_usec = 1000000 + tv.tv_usec - start.tv_usec; 678a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata } 688a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata 698a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata struct timedelta ret = { diff }; 708a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata return ret; 718a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata} 728a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata 73d7e4ca82e1cf20bb2605befb1da74dd1688c706ePetr Machatastatic enum callback_status 742834f72014dc8b13ba13b9a06da744dd023f3555Petr Machatafill_struct(const char **namep, struct opt_c_struct *st, void *u) 752d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand{ 762834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata struct fill_struct_data *data = u; 772834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata struct entry_st entry = { *namep, st->count, st->tv }; 782834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata if (VECT_PUSHBACK(&data->entries, &entry) < 0) 792834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata return CBS_STOP; 802834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata 812834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata data->tot_count += st->count; 822834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata data->tot_usecs += 1000000 * st->tv.tv_sec; 832834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata data->tot_usecs += st->tv.tv_usec; 84d7e4ca82e1cf20bb2605befb1da74dd1688c706ePetr Machata return CBS_CONT; 85d65efa37b1fd73305ce4469841dc760514d74202Juan Cespedes} 86d65efa37b1fd73305ce4469841dc760514d74202Juan Cespedes 872834f72014dc8b13ba13b9a06da744dd023f3555Petr Machatastatic int 882834f72014dc8b13ba13b9a06da744dd023f3555Petr Machatacompar(const struct entry_st *en1, const struct entry_st *en2) 892d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand{ 902834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata if (en2->tv.tv_sec - en1->tv.tv_sec) 912834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata return en2->tv.tv_sec - en1->tv.tv_sec; 922834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata else 932834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata return en2->tv.tv_usec - en1->tv.tv_usec; 942834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata} 95d65efa37b1fd73305ce4469841dc760514d74202Juan Cespedes 962834f72014dc8b13ba13b9a06da744dd023f3555Petr Machatastatic enum callback_status 972834f72014dc8b13ba13b9a06da744dd023f3555Petr Machatadump_one(struct entry_st *entry, void *u) 982834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata{ 992834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata struct fill_struct_data *data = u; 1002834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata unsigned long long int c; 1012834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata unsigned long long int p; 1022834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata c = 1000000 * (int)entry->tv.tv_sec + 1032834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata (int)entry->tv.tv_usec; 1042834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata p = 100000 * c / data->tot_usecs + 5; 1052834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata fprintf(options.output, "%3lu.%02lu %4d.%06d %11lu %9d %s\n", 1062834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata (unsigned long int)(p / 1000), 1072834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata (unsigned long int)((p / 10) % 100), 1082834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata (int)entry->tv.tv_sec, (int)entry->tv.tv_usec, 1092834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata (unsigned long int)(c / entry->count), 1102834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata entry->count, 1112834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata#ifdef USE_DEMANGLE 1122834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata options.demangle ? my_demangle(entry->name) : 1132834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata#endif 1142834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata entry->name); 115d65efa37b1fd73305ce4469841dc760514d74202Juan Cespedes 1162834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata return CBS_CONT; 117d65efa37b1fd73305ce4469841dc760514d74202Juan Cespedes} 118d65efa37b1fd73305ce4469841dc760514d74202Juan Cespedes 1192834f72014dc8b13ba13b9a06da744dd023f3555Petr Machatavoid 1202834f72014dc8b13ba13b9a06da744dd023f3555Petr Machatashow_summary(void) 1212d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand{ 1222834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata struct fill_struct_data cdata = {}; 1232834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata VECT_INIT(&cdata.entries, struct entry_st); 124d65efa37b1fd73305ce4469841dc760514d74202Juan Cespedes 1252834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata if (dict_opt_c != NULL) { 126881e1fd61524bd916cdce782f8d3beadd7e5aaecPetr Machata DICT_EACH(dict_opt_c, const char *, struct opt_c_struct, NULL, 1272834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata fill_struct, &cdata); 1282834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata 1292834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata VECT_QSORT(&cdata.entries, struct entry_st, &compar); 130d65efa37b1fd73305ce4469841dc760514d74202Juan Cespedes } 1312834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata 1322834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata fprintf(options.output, 1332834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata "%% time seconds usecs/call calls function\n"); 1342834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata fprintf(options.output, 1352834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata "------ ----------- ----------- --------- --------------------\n"); 1362834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata 1372834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata VECT_EACH(&cdata.entries, struct entry_st, NULL, dump_one, &cdata); 1382834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata 1392834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata fprintf(options.output, 1402834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata "------ ----------- ----------- --------- --------------------\n"); 1412834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata fprintf(options.output, "100.00 %4lu.%06lu %9d total\n", 1422834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata cdata.tot_usecs / 1000000, 1432834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata cdata.tot_usecs % 1000000, cdata.tot_count); 1442834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata 1452834f72014dc8b13ba13b9a06da744dd023f3555Petr Machata vect_destroy(&cdata.entries, NULL, NULL); 146d65efa37b1fd73305ce4469841dc760514d74202Juan Cespedes} 1478a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata 1488a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machatastatic void 1498a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machatafree_stringp_cb(const char **stringp, void *data) 1508a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata{ 1518a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata free((char *)*stringp); 1528a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata} 1538a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata 1548a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machatavoid 1558a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machatasummary_account_call(struct library_symbol *libsym, struct timedelta spent) 1568a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata{ 1578a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata assert(options.summary); 1588a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata 1598a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata if (dict_opt_c == NULL) { 1608a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata dict_opt_c = malloc(sizeof(*dict_opt_c)); 1618a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata if (dict_opt_c == NULL) { 1628a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata oom: 1638a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata fprintf(stderr, 1648a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata "Can't allocate memory for " 1658a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata "keeping track of -c.\n"); 1668a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata free(dict_opt_c); 1678a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata options.summary = 0; 1688a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata return; 1698a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata } 1708a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata DICT_INIT(dict_opt_c, char *, struct opt_c_struct, 1718a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata dict_hash_string, dict_eq_string, NULL); 1728a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata } 1738a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata 1748a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata struct opt_c_struct *st = DICT_FIND_REF(dict_opt_c, &libsym->name, 1758a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata struct opt_c_struct); 1768a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata if (st == NULL) { 1778a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata const char *na = strdup(libsym->name); 1788a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata struct opt_c_struct new_st = {.count = 0, .tv = {0, 0}}; 1798a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata if (na == NULL 1808a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata || DICT_INSERT(dict_opt_c, &na, &new_st) < 0) { 1818a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata free((char *) na); 1828a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata DICT_DESTROY(dict_opt_c, const char *, 1838a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata struct opt_c_struct, 1848a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata free_stringp_cb, NULL, NULL); 1858a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata goto oom; 1868a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata } 1878a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata st = DICT_FIND_REF(dict_opt_c, &libsym->name, 1888a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata struct opt_c_struct); 1898a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata assert(st != NULL); 1908a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata } 1918a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata 1928a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata if (st->tv.tv_usec + spent.tm.tv_usec > 1000000) { 1938a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata st->tv.tv_usec += spent.tm.tv_usec - 1000000; 1948a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata st->tv.tv_sec++; 1958a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata } else { 1968a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata st->tv.tv_usec += spent.tm.tv_usec; 1978a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata } 1988a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata st->count++; 1998a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata st->tv.tv_sec += spent.tm.tv_sec; 2008a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata return; 2018a730f3e5844b86386032e93f91aa3df814ad9c3Petr Machata} 202