[prev in list] [next in list] [prev in thread] [next in thread] 

List:       oprofile-list
Subject:    [patch 7/7] Oprofile AMD IBS support
From:       "Jason Yeh" <jason.yeh () amd ! com>
Date:       2008-01-29 21:50:01
Message-ID: 479F9F89.4000500 () amd ! com
[Download RAW message or body]

This patch includes changes to opannotate.

--- 

 opannotate.cpp |  211 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 202 insertions(+), 9 deletions(-)


diff -uprN -X dontdiff oprofile-cvs-original/pp/opannotate.cpp oprofile-cvs-ibs/pp/opannotate.cpp
--- oprofile-cvs-original/pp/opannotate.cpp	2008-01-28 16:05:26.000000000 -0600
+++ oprofile-cvs-ibs/pp/opannotate.cpp	2008-01-29 09:39:57.000000000 -0600
@@ -176,6 +176,92 @@ string asm_line_annotation(symbol_entry 
 }
 
 
+/// NOTE: This function annotates a list<string> containing output from objdump.
+/// It uses a list iterator, and a sample_container iterator which iterates 
+/// from the beginning to the end, and compare sample address 
+/// against the instruction address on the asm line.
+/// 
+/// There are 2 cases of annotation:
+/// 1. If sample address matches current line address, annotate the current line.
+/// 2. If (previous line address < sample address < current line address),
+///    then we annotate previous line.  This case happens when sample address 
+///    is not aligned with the instruction address, which is seen when profile 
+///    using the instruction fetch mode of AMD Instruction-Based Sampling (IBS).
+///
+string asm_list_annotation(symbol_entry const * last_symbol,
+			list<string>::iterator sit, 
+			sample_container::samples_iterator & samp_it )
+{
+	// do not use the bfd equivalent:
+	//  - it does not skip space at begin
+	//  - we does not need cross architecture compile so the native
+	// strtoull must work, assuming unsigned long long can contain a vma
+	// and on 32/64 bits box bfd_vma is 64 bits
+	// gcc 2.91.66 workaround
+	string value = *sit;
+	bfd_vma vma = strtoull(value.c_str(), NULL, 16);
+	string str;
+
+	sample_entry const * sample = &samp_it->second;
+	
+	if (sample->vma == vma) {
+		str += count_str(sample->counts, samples->samples_count());
+			
+		// For each events
+		for (size_t i = 1; i < nr_events; ++i)
+			str += "  ";
+
+		str += " :";
+		*sit = str + *sit;
+		if(samp_it != samples->end())
+			++samp_it;
+		samples->delete_samples(last_symbol, vma);	
+	} else	if (sample->vma < vma) {
+		// vma of the current line is greater than vma of the sample
+
+		// Get the string of previous line
+		list<string>::iterator sit_prev = sit;
+		--sit_prev;
+		string prev_line = *sit_prev;
+
+		// sub_string is the part that contains adderss
+		string sub_string = prev_line.substr(prev_line.find(":", 0)+1, prev_line.length());
+
+		bfd_vma vma_prev = strtoull(sub_string.c_str(), NULL, 16);
+
+		// Need to check if prev_vma < sample->vma 
+		if( vma_prev < sample->vma)
+		{
+			// Aggregate sample with previous line if it already has samples
+			sample_entry * prev_sample = (sample_entry *)samples->find_sample(last_symbol, vma_prev);
+			if (prev_sample)
+				prev_sample->counts += sample->counts;
+
+			str += count_str(sample->counts, samples->samples_count());
+
+			// For each events
+			for (size_t i = 1; i < nr_events; ++i)
+				str += "  ";
+
+			str += " :";
+			*sit_prev = str + sub_string; 
+			*sit = annotation_fill + *sit;
+			if(samp_it != samples->end())
+				++samp_it;
+			samples->delete_samples(last_symbol, sample->vma);
+		}else{
+			*sit = annotation_fill + *sit;
+			if(samp_it != samples->end())
+				++samp_it;
+		}
+	} else {
+		*sit = annotation_fill + *sit;
+	}
+
+	return str;
+}
+
+
 string symbol_annotation(symbol_entry const * symbol)
 {
 	if (!symbol)
@@ -269,11 +355,123 @@ symbol_entry const * output_objdump_asm_
 }
 
 
+/// NOTE: This function is similar to the function "output_objdump_asm_line" above.
+/// It operates on the list<string> instead of just one string.
+symbol_entry const * annotate_objdump_str_list(symbol_entry const * last_symbol,
+					string const & app_name, 
+					list<string>::iterator sit,
+					symbol_collection const & symbols,
+					bool & do_output, 
+					sample_container::samples_iterator & samp_it)
+{
+	// output of objdump is a human readable form and can contain some
+	// ambiguity so this code is dirty. It is also optimized a little bit
+	// so it is difficult to simplify it without breaking something ...
+
+	// line of interest are: "[:space:]*[:xdigit:]?[ :]", the last char of
+	// this regexp dis-ambiguate between a symbol line and an asm line. If
+	// source contain line of this form an ambiguity occur and we rely on
+	// the robustness of this code.
+	string str = *sit;
+	size_t pos = 0;
+	while (pos < str.length() && isspace(str[pos]))
+		++pos;
+
+	if (pos == str.length() || !isxdigit(str[pos])) {
+		if (do_output) {
+			*sit = annotation_fill + str;
+			return last_symbol;
+		}
+	}
+
+	while (pos < str.length() && isxdigit(str[pos]))
+		++pos;
+
+	if (pos == str.length() || (!isspace(str[pos]) && str[pos] != ':')) {
+		if (do_output) {
+			 *sit = annotation_fill + str;
+			return last_symbol;
+		}
+	}
+
+	if (is_symbol_line(str, pos)) {
+
+		last_symbol = find_symbol(app_name, str);
+
+		// ! complexity: linear in number of symbol must use sorted
+		// by address vector and lower_bound ?
+		// Note this use a pointer comparison. It work because symbols
+		// pointer are unique
+		if (find(symbols.begin(), symbols.end(), last_symbol)
+			!= symbols.end()) {
+			do_output = true;
+		} else {
+			do_output = false;
+		}
+		if(do_output){
+			*sit += symbol_annotation(last_symbol);
+
+			// Realign the sample iterator to 
+			// the beginning of this symbols
+			samp_it = samples->begin(last_symbol);	
+		}
+	} else {
+		// not a symbol, probably an asm line.
+		if(do_output){
+			asm_list_annotation(last_symbol, sit, samp_it);
+		}
+	}
+
+	return last_symbol;
+}
+
+
+void output_objdump_str_list( symbol_collection const & symbols,
+			string const & app_name, 
+			list<string> & asm_lines)
+{
+	symbol_entry const * last_symbol = 0;
+
+	// to filter output of symbols (filter based on command line options)
+	bool do_output = true;
+
+	// We simultaneously walk the two structures (list and sample_container)
+	// which are sorted by address. and do address comparision.
+	list<string>::iterator sit  = asm_lines.begin();
+	list<string>::iterator send = asm_lines.end();
+	sample_container::samples_iterator samp_it = samples->begin();
+
+	for(; sit != send; sit++) {
+		last_symbol = annotate_objdump_str_list(last_symbol, 
+							app_name,
+							sit, 
+							symbols, 
+							do_output, 
+							samp_it);
+		
+		if(!do_output) {
+			*sit = "";
+		}
+	}
+	
+	// Printing objdump output to stdout
+	sit = asm_lines.begin();
+	for(; sit != send; ++sit) {
+		string str = *sit;
+		if(str.length() != 0)
+			cout << str << '\n';
+	}
+}
+
+
+
+
 void do_one_output_objdump(symbol_collection const & symbols,
 			   string const & image_name, string const & app_name,
 			   bfd_vma start, bfd_vma end)
 {
 	vector<string> args;
+	list<string> asm_lines;
 
 	args.push_back("-d");
 	args.push_back("--no-show-raw-insn");
@@ -301,16 +499,14 @@ void do_one_output_objdump(symbol_collec
 		return;
 	}
 
-	// to filter output of symbols (filter based on command line options)
-	bool do_output = true;
-
-	symbol_entry const * last_symbol = 0;
+	// Read each output line from objdump and store in a list.
 	string str;
 	while (reader.getline(str)) {
-		last_symbol = output_objdump_asm_line(last_symbol, app_name,
-					str, symbols, do_output);
+		asm_lines.push_back(str);
 	}
 
+	output_objdump_str_list(symbols, app_name, asm_lines);
+
 	// objdump always returns SUCCESS so we must rely on the stderr state
 	// of objdump. If objdump error message is cryptic our own error
 	// message will be probably also cryptic
@@ -693,9 +889,6 @@ int opannotate(options::spec const & spe
 
 	nr_events = classes.v.size();
 
-	samples.reset(new profile_container(true, true,
-					    classes.extra_found_images));
-
 	list<string> images;
 
 	list<inverted_profile> iprofiles = invert_profiles(classes);

["op_cvs_IBS_PATCH_7" (text/plain)]

diff -uprN -X dontdiff oprofile-cvs-original/pp/opannotate.cpp oprofile-cvs-ibs/pp/opannotate.cpp
--- oprofile-cvs-original/pp/opannotate.cpp	2008-01-28 16:05:26.000000000 -0600
+++ oprofile-cvs-ibs/pp/opannotate.cpp	2008-01-29 09:39:57.000000000 -0600
@@ -176,6 +176,92 @@ string asm_line_annotation(symbol_entry 
 }
 
 
+/// NOTE: This function annotates a list<string> containing output from objdump.
+/// It uses a list iterator, and a sample_container iterator which iterates 
+/// from the beginning to the end, and compare sample address 
+/// against the instruction address on the asm line.
+/// 
+/// There are 2 cases of annotation:
+/// 1. If sample address matches current line address, annotate the current line.
+/// 2. If (previous line address < sample address < current line address),
+///    then we annotate previous line.  This case happens when sample address 
+///    is not aligned with the instruction address, which is seen when profile 
+///    using the instruction fetch mode of AMD Instruction-Based Sampling (IBS).
+///
+string asm_list_annotation(symbol_entry const * last_symbol,
+			list<string>::iterator sit, 
+			sample_container::samples_iterator & samp_it )
+{
+	// do not use the bfd equivalent:
+	//  - it does not skip space at begin
+	//  - we does not need cross architecture compile so the native
+	// strtoull must work, assuming unsigned long long can contain a vma
+	// and on 32/64 bits box bfd_vma is 64 bits
+	// gcc 2.91.66 workaround
+	string value = *sit;
+	bfd_vma vma = strtoull(value.c_str(), NULL, 16);
+	string str;
+
+	sample_entry const * sample = &samp_it->second;
+	
+	if (sample->vma == vma) {
+		str += count_str(sample->counts, samples->samples_count());
+			
+		// For each events
+		for (size_t i = 1; i < nr_events; ++i)
+			str += "  ";
+
+		str += " :";
+		*sit = str + *sit;
+		if(samp_it != samples->end())
+			++samp_it;
+		samples->delete_samples(last_symbol, vma);	
+	} else	if (sample->vma < vma) {
+		// vma of the current line is greater than vma of the sample
+
+		// Get the string of previous line
+		list<string>::iterator sit_prev = sit;
+		--sit_prev;
+		string prev_line = *sit_prev;
+
+		// sub_string is the part that contains adderss
+		string sub_string = prev_line.substr(prev_line.find(":", 0)+1, prev_line.length());
+
+		bfd_vma vma_prev = strtoull(sub_string.c_str(), NULL, 16);
+
+		// Need to check if prev_vma < sample->vma 
+		if( vma_prev < sample->vma)
+		{
+			// Aggregate sample with previous line if it already has samples
+			sample_entry * prev_sample = (sample_entry *)samples->find_sample(last_symbol, vma_prev);
+			if (prev_sample)
+				prev_sample->counts += sample->counts;
+
+			str += count_str(sample->counts, samples->samples_count());
+
+			// For each events
+			for (size_t i = 1; i < nr_events; ++i)
+				str += "  ";
+
+			str += " :";
+			*sit_prev = str + sub_string; 
+			*sit = annotation_fill + *sit;
+			if(samp_it != samples->end())
+				++samp_it;
+			samples->delete_samples(last_symbol, sample->vma);
+		}else{
+			*sit = annotation_fill + *sit;
+			if(samp_it != samples->end())
+				++samp_it;
+		}
+	} else {
+		*sit = annotation_fill + *sit;
+	}
+
+	return str;
+}
+
+
 string symbol_annotation(symbol_entry const * symbol)
 {
 	if (!symbol)
@@ -269,11 +355,123 @@ symbol_entry const * output_objdump_asm_
 }
 
 
+/// NOTE: This function is similar to the function "output_objdump_asm_line" above.
+/// It operates on the list<string> instead of just one string.
+symbol_entry const * annotate_objdump_str_list(symbol_entry const * last_symbol,
+					string const & app_name, 
+					list<string>::iterator sit,
+					symbol_collection const & symbols,
+					bool & do_output, 
+					sample_container::samples_iterator & samp_it)
+{
+	// output of objdump is a human readable form and can contain some
+	// ambiguity so this code is dirty. It is also optimized a little bit
+	// so it is difficult to simplify it without breaking something ...
+
+	// line of interest are: "[:space:]*[:xdigit:]?[ :]", the last char of
+	// this regexp dis-ambiguate between a symbol line and an asm line. If
+	// source contain line of this form an ambiguity occur and we rely on
+	// the robustness of this code.
+	string str = *sit;
+	size_t pos = 0;
+	while (pos < str.length() && isspace(str[pos]))
+		++pos;
+
+	if (pos == str.length() || !isxdigit(str[pos])) {
+		if (do_output) {
+			*sit = annotation_fill + str;
+			return last_symbol;
+		}
+	}
+
+	while (pos < str.length() && isxdigit(str[pos]))
+		++pos;
+
+	if (pos == str.length() || (!isspace(str[pos]) && str[pos] != ':')) {
+		if (do_output) {
+			 *sit = annotation_fill + str;
+			return last_symbol;
+		}
+	}
+
+	if (is_symbol_line(str, pos)) {
+
+		last_symbol = find_symbol(app_name, str);
+
+		// ! complexity: linear in number of symbol must use sorted
+		// by address vector and lower_bound ?
+		// Note this use a pointer comparison. It work because symbols
+		// pointer are unique
+		if (find(symbols.begin(), symbols.end(), last_symbol)
+			!= symbols.end()) {
+			do_output = true;
+		} else {
+			do_output = false;
+		}
+		if(do_output){
+			*sit += symbol_annotation(last_symbol);
+
+			// Realign the sample iterator to 
+			// the beginning of this symbols
+			samp_it = samples->begin(last_symbol);	
+		}
+	} else {
+		// not a symbol, probably an asm line.
+		if(do_output){
+			asm_list_annotation(last_symbol, sit, samp_it);
+		}
+	}
+
+	return last_symbol;
+}
+
+
+void output_objdump_str_list( symbol_collection const & symbols,
+			string const & app_name, 
+			list<string> & asm_lines)
+{
+	symbol_entry const * last_symbol = 0;
+
+	// to filter output of symbols (filter based on command line options)
+	bool do_output = true;
+
+	// We simultaneously walk the two structures (list and sample_container)
+	// which are sorted by address. and do address comparision.
+	list<string>::iterator sit  = asm_lines.begin();
+	list<string>::iterator send = asm_lines.end();
+	sample_container::samples_iterator samp_it = samples->begin();
+
+	for(; sit != send; sit++) {
+		last_symbol = annotate_objdump_str_list(last_symbol, 
+							app_name,
+							sit, 
+							symbols, 
+							do_output, 
+							samp_it);
+		
+		if(!do_output) {
+			*sit = "";
+		}
+	}
+	
+	// Printing objdump output to stdout
+	sit = asm_lines.begin();
+	for(; sit != send; ++sit) {
+		string str = *sit;
+		if(str.length() != 0)
+			cout << str << '\n';
+	}
+}
+
+
+
+
 void do_one_output_objdump(symbol_collection const & symbols,
 			   string const & image_name, string const & app_name,
 			   bfd_vma start, bfd_vma end)
 {
 	vector<string> args;
+	list<string> asm_lines;
 
 	args.push_back("-d");
 	args.push_back("--no-show-raw-insn");
@@ -301,16 +499,14 @@ void do_one_output_objdump(symbol_collec
 		return;
 	}
 
-	// to filter output of symbols (filter based on command line options)
-	bool do_output = true;
-
-	symbol_entry const * last_symbol = 0;
+	// Read each output line from objdump and store in a list.
 	string str;
 	while (reader.getline(str)) {
-		last_symbol = output_objdump_asm_line(last_symbol, app_name,
-					str, symbols, do_output);
+		asm_lines.push_back(str);
 	}
 
+	output_objdump_str_list(symbols, app_name, asm_lines);
+
 	// objdump always returns SUCCESS so we must rely on the stderr state
 	// of objdump. If objdump error message is cryptic our own error
 	// message will be probably also cryptic
@@ -693,9 +889,6 @@ int opannotate(options::spec const & spe
 
 	nr_events = classes.v.size();
 
-	samples.reset(new profile_container(true, true,
-					    classes.extra_found_images));
-
 	list<string> images;
 
 	list<inverted_profile> iprofiles = invert_profiles(classes);



-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

_______________________________________________
oprofile-list mailing list
oprofile-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/oprofile-list


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic