[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