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