18cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/** 28cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @file opannotate.cpp 38cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Implement opannotate utility 48cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * 58cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Copyright 2003 OProfile authors 68cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Read the file COPYING 78cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * 88cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author John Levon 98cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author Philippe Elie 108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */ 118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <iostream> 138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <sstream> 148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <algorithm> 158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <iomanip> 168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <fstream> 178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <utility> 188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_exception.h" 208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_header.h" 218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "profile.h" 228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "populate.h" 238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_sample_file.h" 248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "cverb.h" 258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "string_manip.h" 268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "demangle_symbol.h" 278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "child_reader.h" 288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_file.h" 298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "file_manip.h" 308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "arrange_profiles.h" 318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "opannotate_options.h" 328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "profile_container.h" 338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "symbol_sort.h" 348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "image_errors.h" 358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddusing namespace std; 378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddusing namespace options; 388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddnamespace { 408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddsize_t nr_events; 428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddscoped_ptr<profile_container> samples; 448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// how opannotate was invoked 468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstring cmdline; 478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// empty annotation fill string 498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstring annotation_fill; 508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// string used as start / end comment to annotate source 528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstring const begin_comment("/* "); 538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstring const in_comment(" * "); 548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstring const end_comment(" */"); 558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// field width for the sample count 578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddunsigned int const count_width = 6; 588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstring get_annotation_fill() 608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string str; 628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (size_t i = 0; i < nr_events; ++i) { 648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd str += string(count_width, ' ') + ' '; 658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd str += string(percent_width, ' '); 668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (size_t i = 1; i < nr_events; ++i) 698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd str += " "; 708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd str += " :"; 728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return str; 738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddsymbol_entry const * find_symbol(string const & image_name, 778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string const & str_vma) 788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // do not use the bfd equivalent: 808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // - it does not skip space at begin 818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // - we does not need cross architecture compile so the native 828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // strtoull must work, assuming unsigned long long can contain a vma 838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // and on 32/64 bits box bfd_vma is 64 bits 848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd bfd_vma vma = strtoull(str_vma.c_str(), NULL, 16); 858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return samples->find_symbol(image_name, vma); 878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid output_info(ostream & out) 918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd out << begin_comment << '\n'; 938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd out << in_comment << "Command line: " << cmdline << '\n' 958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << in_comment << '\n'; 968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd out << in_comment << "Interpretation of command line:" << '\n'; 988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!assembly) { 1008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd out << in_comment 1018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << "Output annotated source file with samples" << '\n'; 1028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (options::threshold != 0) { 1048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd out << in_comment 1058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << "Output files where samples count reach " 1068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << options::threshold << "% of the samples\n"; 1078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } else { 1088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd out << in_comment << "Output all files" << '\n'; 1098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 1108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } else { 1118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd out << in_comment 1128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << "Output annotated assembly listing with samples" 1138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << '\n'; 1148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!objdump_params.empty()) { 1168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd out << in_comment << "Passing the following " 1178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd "additional arguments to objdump ; \""; 1188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (size_t i = 0 ; i < objdump_params.size() ; ++i) 1198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd out << objdump_params[i] << " "; 1208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd out << "\"" << '\n'; 1218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 1228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 1238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd out << in_comment << '\n'; 1258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd out << in_comment << classes.cpuinfo << endl; 1278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!classes.event.empty()) 1288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd out << in_comment << classes.event << endl; 1298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (size_t i = 0; i < classes.v.size(); ++i) 1318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd out << in_comment << classes.v[i].longname << endl; 1328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd out << end_comment << '\n'; 1348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 1358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstring count_str(count_array_t const & count, 1388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd count_array_t const & total) 1398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 1408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ostringstream os; 1418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (size_t i = 0; i < nr_events; ++i) { 1428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd os << setw(count_width) << count[i] << ' '; 1438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd os << format_percent(op_ratio(count[i], total[i]) * 100.0, 1458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd percent_int_width, percent_fract_width); 1468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 1478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return os.str(); 1488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 1498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// NOTE: This function annotates a list<string> containing output from objdump. 1528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// It uses a list iterator, and a sample_container iterator which iterates 1538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// from the beginning to the end, and compare sample address 1548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// against the instruction address on the asm line. 1558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// 1568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// There are 2 cases of annotation: 1578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// 1. If sample address matches current line address, annotate the current line. 1588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// 2. If (previous line address < sample address < current line address), 1598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// then we annotate previous line. This case happens when sample address 1608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// is not aligned with the instruction address, which is seen when profile 1618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// using the instruction fetch mode of AMD Instruction-Based Sampling (IBS). 1628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// 1638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddint asm_list_annotation(symbol_entry const * last_symbol, 1648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd bfd_vma last_symbol_vma, 1658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd list<string>::iterator sit, 1668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sample_container::samples_iterator & samp_it, 1678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd list<string> & asm_lines) 1688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 1698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd int ret = 0; 1708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sample_entry const * sample = NULL; 1728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (samp_it != samples->end()) 1748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sample = &samp_it->second; 1758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // do not use the bfd equivalent: 1778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // - it does not skip space at begin 1788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // - we does not need cross architecture compile so the native 1798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // strtoull must work, assuming unsigned long long can contain a vma 1808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // and on 32/64 bits box bfd_vma is 64 bits 1818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // gcc 2.91.66 workaround 1828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd bfd_vma vma = strtoull((*sit).c_str(), NULL, 16); 1838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (sample 1858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd && ((sample->vma < last_symbol_vma) || (sample->vma > vma))) { 1868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *sit = annotation_fill + *sit; 1878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } else if (sample && sample->vma == vma) { 1888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // Case 1 : Sample address match current line address. 1898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string str = count_str(sample->counts, samples->samples_count()); 1908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // For each events 1928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (size_t i = 1; i < nr_events; ++i) 1938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd str += " "; 1948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *sit = str + " :" + *sit; 1968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (samp_it != samples->end()) 1978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ++samp_it; 1988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } else if (sample && sample->vma < vma) { 2008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // Case 2 : vma of the current line is greater than vma of the sample 2018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // Get the string of previous assembly line 2038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd list<string>::iterator sit_prev = sit; 2048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string prev_line, prev_vma_str; 2058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string::size_type loc1 = string::npos, loc2 = string::npos; 2068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd while (sit_prev != asm_lines.begin()) { 2078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd --sit_prev; 2088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd prev_line = *sit_prev; 2098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd loc1 = prev_line.find(":", 0); 2118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (loc1 != string::npos) { 2128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd loc2 = prev_line.find(":", loc1+1); 2138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (loc2 != string::npos) { 2148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd prev_vma_str = prev_line.substr(loc1+1, loc2); 2158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd break; 2168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 2178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 2188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 2198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd bfd_vma prev_vma = strtoull(prev_vma_str.c_str(), NULL, 16); 2218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // Need to check if prev_vma < sample->vma 2238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (prev_vma != 0 && prev_vma < sample->vma) { 2248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string str; 2258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // Get sample for previous line. 2278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sample_entry * prev_sample = (sample_entry *)samples-> 2288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd find_sample(last_symbol, prev_vma); 2298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (prev_sample) { 2308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // Aggregate sample with previous line if it already has samples 2318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd prev_sample->counts += sample->counts; 2328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd str = count_str(prev_sample->counts, samples->samples_count()); 2338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } else { 2348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd str = count_str(sample->counts, samples->samples_count()); 2358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 2368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // For each events 2388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (size_t i = 1; i < nr_events; ++i) 2398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd str += " "; 2408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *sit_prev = str + " :" + prev_line.substr(loc1+1); 2428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (samp_it != samples->end()) 2438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ++samp_it; 2448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ret = -1; 2458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } else { 2468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // Failed to annotate the previous line. Skip sample. 2478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *sit = annotation_fill + *sit; 2488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (samp_it != samples->end()) 2498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ++samp_it; 2508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 2518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } else { 2528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // In case sample is NULL 2538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *sit = annotation_fill + *sit; 2548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 2558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return ret; 2578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 2588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstring symbol_annotation(symbol_entry const * symbol) 2618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 2628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!symbol) 2638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return string(); 2648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string annot = count_str(symbol->sample.counts, 2668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd samples->samples_count()); 2678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string const & symname = symbol_names.demangle(symbol->name); 2698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string str = " "; 2718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd str += begin_comment + symname + " total: "; 2728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd str += count_str(symbol->sample.counts, samples->samples_count()); 2738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd str += end_comment; 2748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return str; 2758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 2768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// return true if this line contains a symbol name in objdump formatting 2798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// symbol are on the form 08030434 <symbol_name>: we need to be strict 2808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/// here to avoid any interpretation of a source line as a symbol line 2818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddbool is_symbol_line(string const & str, string::size_type pos) 2828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 2838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (str[pos] != ' ' || str[pos + 1] != '<') 2848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return false; 2858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return str[str.length() - 1] == ':'; 2878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 2888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid annotate_objdump_str_list(string const & app_name, 2918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd symbol_collection const & symbols, 2928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd list<string> & asm_lines) 2938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 2948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd symbol_entry const * last_symbol = 0; 2958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd bfd_vma last_symbol_vma = 0; 2968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd int ret = 0; 2978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 2988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // to filter output of symbols (filter based on command line options) 2998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd bool do_output = true; 3008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // We simultaneously walk the two structures (list and sample_container) 3028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // which are sorted by address. and do address comparision. 3038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd list<string>::iterator sit = asm_lines.begin(); 3048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd list<string>::iterator send = asm_lines.end(); 3058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sample_container::samples_iterator samp_it = samples->begin(); 3068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (; sit != send; (!ret? sit++: sit)) { 3088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // output of objdump is a human readable form and can contain some 3098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // ambiguity so this code is dirty. It is also optimized a little bit 3108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // so it is difficult to simplify it without breaking something ... 3118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // line of interest are: "[:space:]*[:xdigit:]?[ :]", the last char of 3138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // this regexp dis-ambiguate between a symbol line and an asm line. If 3148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // source contain line of this form an ambiguity occur and we rely on 3158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // the robustness of this code. 3168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string str = *sit; 3178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd size_t pos = 0; 3188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd while (pos < str.length() && isspace(str[pos])) 3198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ++pos; 3208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (pos == str.length() || !isxdigit(str[pos])) { 3228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (do_output) { 3238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *sit = annotation_fill + str; 3248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd continue; 3258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 3268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 3278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd while (pos < str.length() && isxdigit(str[pos])) 3298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ++pos; 3308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (pos == str.length() || (!isspace(str[pos]) && str[pos] != ':')) { 3328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (do_output) { 3338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *sit = annotation_fill + str; 3348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd continue; 3358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 3368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 3378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (is_symbol_line(str, pos)) { 3398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd last_symbol = find_symbol(app_name, str); 3418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd last_symbol_vma = strtoull(str.c_str(), NULL, 16); 3428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // ! complexity: linear in number of symbol must use sorted 3448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // by address vector and lower_bound ? 3458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // Note this use a pointer comparison. It work because symbols 3468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // pointer are unique 3478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (find(symbols.begin(), symbols.end(), last_symbol) 3488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd != symbols.end()) 3498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd do_output = true; 3508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd else 3518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd do_output = false; 3528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (do_output) { 3548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *sit += symbol_annotation(last_symbol); 3558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // Realign the sample iterator to 3578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // the beginning of this symbols 3588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd samp_it = samples->begin(last_symbol); 3598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 3608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } else { 3618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // not a symbol, probably an asm line. 3628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (do_output) 3638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ret = asm_list_annotation(last_symbol, 3648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd last_symbol_vma, 3658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sit, samp_it, 3668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd asm_lines); 3678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 3688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!do_output) 3708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *sit = ""; 3718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 3728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 3738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid output_objdump_str_list(symbol_collection const & symbols, 3768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string const & app_name, 3778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd list<string> & asm_lines) 3788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 3798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd annotate_objdump_str_list(app_name, symbols, asm_lines); 3818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // Printing objdump output to stdout 3838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd list<string>::iterator sit = asm_lines.begin(); 3848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd list<string>::iterator send = asm_lines.end(); 3858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sit = asm_lines.begin(); 3868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (; sit != send; ++sit) { 3878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string str = *sit; 3888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (str.length() != 0) 3898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cout << str << '\n'; 3908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 3918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 3928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 3948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid do_one_output_objdump(symbol_collection const & symbols, 3958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string const & image_name, string const & app_name, 3968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd bfd_vma start, bfd_vma end) 3978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 3988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd vector<string> args; 3998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd list<string> asm_lines; 4008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd args.push_back("-d"); 4028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd args.push_back("--no-show-raw-insn"); 4038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (source) 4048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd args.push_back("-S"); 4058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (start || end != ~(bfd_vma)0) { 4078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ostringstream arg1, arg2; 4088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd arg1 << "--start-address=" << start; 4098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd arg2 << "--stop-address=" << end; 4108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd args.push_back(arg1.str()); 4118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd args.push_back(arg2.str()); 4128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 4138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!objdump_params.empty()) { 4158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (size_t i = 0 ; i < objdump_params.size() ; ++i) 4168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd args.push_back(objdump_params[i]); 4178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 4188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd args.push_back(image_name); 420e4b944c9df64336e4c2dd87be5653077ff6c415cBen Cheng#if defined(ANDROID) 421e4b944c9df64336e4c2dd87be5653077ff6c415cBen Cheng child_reader reader("arm-eabi-objdump", args); 422e4b944c9df64336e4c2dd87be5653077ff6c415cBen Cheng#else 4238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd child_reader reader("objdump", args); 424e4b944c9df64336e4c2dd87be5653077ff6c415cBen Cheng#endif 4258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (reader.error()) { 4268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cerr << "An error occur during the execution of objdump:\n\n"; 4278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cerr << reader.error_str() << endl; 4288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return; 4298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 4308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // Read each output line from objdump and store in a list. 4328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string str; 4338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd while (reader.getline(str)) 4348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd asm_lines.push_back(str); 4358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd output_objdump_str_list(symbols, app_name, asm_lines); 4378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // objdump always returns SUCCESS so we must rely on the stderr state 4398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // of objdump. If objdump error message is cryptic our own error 4408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // message will be probably also cryptic 4418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ostringstream std_err; 4428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ostringstream std_out; 4438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd reader.get_data(std_out, std_err); 4448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (std_err.str().length()) { 4458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cerr << "An error occur during the execution of objdump:\n\n"; 4468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cerr << std_err.str() << endl; 4478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return ; 4488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 4498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // force error code to be acquired 4518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd reader.terminate_process(); 4528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // required because if objdump stop by signal all above things suceeed 4548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // (signal error message are not output through stdout/stderr) 4558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (reader.error()) { 4568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cerr << "An error occur during the execution of objdump:\n\n"; 4578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cerr << reader.error_str() << endl; 4588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return; 4598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 4608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 4618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid output_objdump_asm(symbol_collection const & symbols, 4648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string const & app_name) 4658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 4668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd image_error error; 4678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string image = 4688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd classes.extra_found_images.find_image_path(app_name, error, 4698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd true); 4708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // this is only an optimisation, we can either filter output by 4728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // directly calling objdump and rely on the symbol filtering or 4738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // we can call objdump with the right parameter to just disassemble 4748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // the needed part. This is a real win only when calling objdump 4758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // a medium number of times, I dunno if the used threshold is optimal 4768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // but it is a conservative value. 4778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd size_t const max_objdump_exec = 50; 4788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (symbols.size() <= max_objdump_exec || error != image_ok) { 4798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd symbol_collection::const_iterator cit = symbols.begin(); 4808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd symbol_collection::const_iterator end = symbols.end(); 4818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (; cit != end; ++cit) { 4828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd bfd_vma start = (*cit)->sample.vma; 4838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd bfd_vma end = start + (*cit)->size; 4848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd do_one_output_objdump(symbols, image, app_name, 4858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd start, end); 4868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 4878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } else { 4888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd do_one_output_objdump(symbols, image, 4898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd app_name, 0, ~bfd_vma(0)); 4908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 4918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 4928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 4948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddbool output_asm(string const & app_name) 4958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 4968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd profile_container::symbol_choice choice; 4978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd choice.threshold = options::threshold; 4988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd choice.image_name = app_name; 4998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd choice.match_image = true; 5008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd symbol_collection symbols = samples->select_symbols(choice); 5018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!symbols.empty()) { 5038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd sort_options options; 5048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd options.add_sort_option(sort_options::sample); 5058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd options.sort(symbols, false, false); 5068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd output_info(cout); 5088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd output_objdump_asm(symbols, app_name); 5108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return true; 5128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 5138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return false; 5158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 5168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstring const source_line_annotation(debug_name_id filename, size_t linenr) 5198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 5208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string str; 5218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd count_array_t counts = samples->samples_count(filename, linenr); 5238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!counts.zero()) { 5248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd str += count_str(counts, samples->samples_count()); 5258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (size_t i = 1; i < nr_events; ++i) 5268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd str += " "; 5278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd str += " :"; 5288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } else { 5298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd str = annotation_fill; 5308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 5318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return str; 5338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 5348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstring source_symbol_annotation(debug_name_id filename, size_t linenr) 5378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 5388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd symbol_collection const symbols = samples->find_symbol(filename, linenr); 5398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (symbols.empty()) 5418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return string(); 5428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string str = " " + begin_comment; 5448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd count_array_t counts; 5468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (size_t i = 0; i < symbols.size(); ++i) { 5478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd str += symbol_names.demangle(symbols[i]->name); 5488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (symbols.size() == 1) 5498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd str += " total: "; 5508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd else 5518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd str += " "; 5528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd str += count_str(symbols[i]->sample.counts, 5538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd samples->samples_count()); 5548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (symbols.size() != 1) 5558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd str += ", "; 5568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd counts += symbols[i]->sample.counts; 5588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 5598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (symbols.size() > 1) 5618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd str += "total: " + count_str(counts, samples->samples_count()); 5628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd str += end_comment; 5638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return str; 5658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 5668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid output_per_file_info(ostream & out, debug_name_id filename, 5698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd count_array_t const & total_file_count) 5708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 5718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd out << begin_comment << '\n' 5728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << in_comment << "Total samples for file : " 5738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << '"' << debug_names.name(filename) << '"' 5748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << '\n'; 5758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd out << in_comment << '\n' << in_comment 5768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << count_str(total_file_count, samples->samples_count()) 5778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << '\n'; 5788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd out << end_comment << '\n' << '\n'; 5798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 5808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstring const line0_info(debug_name_id filename) 5838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 5848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string annotation = source_line_annotation(filename, 0); 5858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (trim(annotation, " \t:").empty()) 5868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return string(); 5878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string str = "<credited to line zero> "; 5898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd str += annotation; 5908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return str; 5918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 5928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid do_output_one_file(ostream & out, istream & in, debug_name_id filename, 5958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd bool header) 5968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 5978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd count_array_t count = samples->samples_count(filename); 5988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 5998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (header) { 6008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd output_per_file_info(out, filename, count); 6018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd out << line0_info(filename) << '\n'; 6028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 6038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 6048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 6058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (in) { 6068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string str; 6078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 6088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (size_t linenr = 1 ; getline(in, str) ; ++linenr) { 6098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd out << source_line_annotation(filename, linenr) << str 6108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << source_symbol_annotation(filename, linenr) 6118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << '\n'; 6128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 6138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 6148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } else { 6158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // source is not available but we can at least output all the 6168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // symbols belonging to this file. This make more visible the 6178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // problem of having less samples for a given file than the 6188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // sum of all symbols samples for this file due to inlining 6198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd symbol_collection const symbols = samples->select_symbols(filename); 6208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (size_t i = 0; i < symbols.size(); ++i) 6218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd out << symbol_annotation(symbols[i]) << endl; 6228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 6238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 6248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!header) { 6258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd output_per_file_info(out, filename, count); 6268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd out << line0_info(filename) << '\n'; 6278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 6288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 6298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 6308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 6318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid output_one_file(istream & in, debug_name_id filename, 6328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string const & source) 6338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 6348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (output_dir.empty()) { 6358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd do_output_one_file(cout, in, filename, true); 6368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return; 6378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 6388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 6398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string const out_file = op_realpath(output_dir + source); 6408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 6418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* Just because you're paranoid doesn't mean they're not out to 6428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * get you ... 6438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * 6448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * This is just a lame final safety check. If we found the 6458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * source, then "source" should be canonical already, and 6468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * can't escape from the output dir. We can't use op_realpath() 6478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * alone as that needs the file to exist already. 6488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * 6498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Let's not complain again if we couldn't find the file anyway. 6508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */ 6518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (out_file.find("/../") != string::npos) { 6528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (in) { 6538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cerr << "refusing to create non-canonical filename " 6548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << out_file << endl; 6558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 6568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return; 6578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } else if (!is_prefix(out_file, output_dir)) { 6588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (in) { 6598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cerr << "refusing to create file " << out_file 6608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << " outside of output directory " << output_dir 6618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << endl; 6628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 6638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return; 6648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 6658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 6668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (is_files_identical(out_file, source)) { 6678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cerr << "input and output files are identical: " 6688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << out_file << endl; 6698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return; 6708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 6718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 6728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (create_path(out_file.c_str())) { 6738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cerr << "unable to create file: " 6748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << '"' << op_dirname(out_file) << '"' << endl; 6758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return; 6768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 6778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 6788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ofstream out(out_file.c_str()); 6798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!out) { 6808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cerr << "unable to open output file " 6818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << '"' << out_file << '"' << endl; 6828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } else { 6838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd do_output_one_file(out, in, filename, false); 6848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd output_info(out); 6858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 6868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 6878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 6888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 6898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/* Locate a source file from debug info, which may be relative */ 6908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstring const locate_source_file(debug_name_id filename_id) 6918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 6928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string const origfile = debug_names.name(filename_id); 6938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string file = origfile; 6948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 6958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (file.empty()) 6968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return file; 6978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 6988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* Allow absolute paths to be relocated to a different directory */ 6998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (file[0] == '/') { 7008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd vector<string>::const_iterator cit = base_dirs.begin(); 7018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd vector<string>::const_iterator end = base_dirs.end(); 7028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (; cit != end; ++cit) { 7038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string path = op_realpath(*cit); 7048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 7058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (is_prefix(file, path)) { 7068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd file = file.substr(path.length()); 7078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd break; 7088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 7098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 7108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 7118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 7128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd vector<string>::const_iterator cit = search_dirs.begin(); 7138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd vector<string>::const_iterator end = search_dirs.end(); 7148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 7158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (; cit != end; ++cit) { 7168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string const absfile = op_realpath(*cit + "/" + file); 7178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 7188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (op_file_readable(absfile)) 7198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return absfile; 7208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 7218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 7228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* We didn't find a relocated absolute file, or a relative file, 7238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * assume the original is correct, accounting for the 7248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * possibility it's relative the cwd 7258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */ 7268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return op_realpath(origfile); 7278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 7288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 7298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 7308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid output_source(path_filter const & filter) 7318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 7328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd bool const separate_file = !output_dir.empty(); 7338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 7348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!separate_file) 7358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd output_info(cout); 7368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 7378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd vector<debug_name_id> filenames = 7388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd samples->select_filename(options::threshold); 7398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 7408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (size_t i = 0 ; i < filenames.size() ; ++i) { 7418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd string const & source = locate_source_file(filenames[i]); 7428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 7438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!filter.match(source)) 7448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd continue; 7458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 7468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ifstream in(source.c_str()); 7478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 7488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // it is common to have empty filename due to the lack 7498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // of debug info (eg _init function) so warn only 7508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // if the filename is non empty. The case: no debug 7518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // info at all has already been checked. 7528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!in && source.length()) { 7538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cerr << "opannotate (warning): unable to open for " 7548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd "reading: " << source << endl; 7558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 7568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 7578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (source.length()) 7588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd output_one_file(in, filenames[i], source); 7598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 7608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 7618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 7628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 7638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddbool annotate_source(list<string> const & images) 7648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 7658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd annotation_fill = get_annotation_fill(); 7668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 7678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!output_dir.empty()) { 7688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 7698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (create_path(output_dir.c_str())) { 7708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cerr << "unable to create " << output_dir 7718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << " directory: " << endl; 7728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return false; 7738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 7748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 7758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // Make sure we have an absolute path. 7768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd output_dir = op_realpath(output_dir); 7778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (output_dir.length() && 7788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd output_dir[output_dir.length() - 1] != '/') 7798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd output_dir += '/'; 7808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 7818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* Don't let the user stomp on their sources */ 7828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (output_dir == "/") { 7838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cerr << "Output path of / would over-write the " 7848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd "source files" << endl; 7858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return false; 7868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 7878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 7888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 7898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (assembly) { 7908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd bool some_output = false; 7918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 7928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd list<string>::const_iterator it = images.begin(); 7938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd list<string>::const_iterator const end = images.end(); 7948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 7958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (; it != end; ++it) { 7968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (output_asm(*it)) 7978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd some_output = true; 7988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 7998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 8008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!some_output) { 8018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // It's the only case we must care since we know the 8028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // selected image set is not empty 8038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cerr << "selected image set doesn't contain any of " 8048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << "the selected symbol\n"; 8058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 8068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } else { 8078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd output_source(file_filter); 8088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 8098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 8108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return true; 8118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 8128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 8138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 8148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddint opannotate(options::spec const & spec) 8158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 8168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd handle_options(spec); 8178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 8188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd nr_events = classes.v.size(); 8198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 8208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd samples.reset(new profile_container(true, true, 8218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd classes.extra_found_images)); 8228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 8238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd list<string> images; 8248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 8258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd list<inverted_profile> iprofiles = invert_profiles(classes); 8268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 8278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd report_image_errors(iprofiles, classes.extra_found_images); 8288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 8298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd list<inverted_profile>::iterator it = iprofiles.begin(); 8308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd list<inverted_profile>::iterator const end = iprofiles.end(); 8318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 8328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd bool debug_info = false; 8338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (; it != end; ++it) { 8348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd bool tmp = false; 8358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd populate_for_image(*samples, *it, 8368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd options::symbol_filter, &tmp); 8378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd images.push_back(it->image); 8388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (tmp) 8398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd debug_info = true; 8408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 8418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 8428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!debug_info && !options::assembly) { 8438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cerr << "opannotate (warning): no debug information available for binary " 8448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << it->image << ", and --assembly not requested\n"; 8458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 8468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 8478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd annotate_source(images); 8488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 8498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return 0; 8508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 8518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 8528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} // anonymous namespace 8538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 8548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 8558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddint main(int argc, char const * argv[]) 8568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 8578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd // set the invocation, for the file headers later 8588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd for (int i = 0 ; i < argc ; ++i) 8598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cmdline += string(argv[i]) + " "; 8608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 8618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return run_pp_tool(argc, argv, opannotate); 8628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 863