op_header.cpp

Go to the documentation of this file.
00001 
00013 #include <cstring>
00014 #include <iostream>
00015 #include <cstdlib>
00016 #include <iomanip>
00017 #include <set>
00018 #include <sstream>
00019 #include <cstring>
00020 
00021 #include <sys/types.h>
00022 #include <sys/stat.h>
00023 #include <fcntl.h>
00024 #include <unistd.h>
00025 
00026 #include "op_config.h"
00027 #include "op_exception.h"
00028 #include "odb.h"
00029 #include "op_cpu_type.h"
00030 #include "op_file.h"
00031 #include "op_header.h"
00032 #include "op_events.h"
00033 #include "string_manip.h"
00034 #include "format_output.h"
00035 #include "xml_utils.h"
00036 #include "cverb.h"
00037 
00038 using namespace std;
00039 
00040 extern verbose vbfd;
00041 
00042 void op_check_header(opd_header const & h1, opd_header const & h2,
00043              string const & filename)
00044 {
00045     if (h1.mtime != h2.mtime) {
00046         ostringstream os;
00047         os << "header timestamps are different ("
00048            << h1.mtime << ", " << h2.mtime << ") for "
00049            << filename << "\n";
00050         throw op_fatal_error(os.str());
00051     }
00052 
00053     if (h1.is_kernel != h2.is_kernel) {
00054         ostringstream os;
00055         os << "header is_kernel flags are different for "
00056            << filename << "\n";
00057         throw op_fatal_error(os.str());
00058     }
00059     
00060     // Note that in the generated ELF file for anonymous code the vma
00061     // of the symbol is exaclty the same vma as the code had during sampling.
00062     
00063     // Note that we don't check CPU speed since that can vary
00064     // freely on the same machine
00065 }
00066 
00067 
00068 namespace {
00069 
00070 set<string> warned_files;
00071 
00072 }
00073 
00074 bool is_jit_sample(string const & filename)
00075 {
00076     // suffix for JIT sample files (see FIXME in check_mtime() below)
00077     string suf = ".jo";
00078     
00079     string::size_type pos;
00080     pos = filename.rfind(suf);
00081     // for JIT sample files do not output the warning to stderr.
00082     if (pos != string::npos && pos == filename.size() - suf.size())
00083         return true;
00084     else
00085         return false;
00086 }
00087 
00088 void check_mtime(string const & file, opd_header const & header)
00089 {
00090     u64 newmtime = op_get_mtime(file.c_str());
00091 
00092     if (newmtime == header.mtime)
00093         return;
00094 
00095     if (warned_files.find(file) != warned_files.end())
00096         return;
00097 
00098     warned_files.insert(file);
00099 
00100     // Files we couldn't get mtime of have zero mtime
00101     if (!header.mtime) {
00102         // FIXME: header.mtime for JIT sample files is 0. The problem could be that
00103         //        in opd_mangling.c:opd_open_sample_file() the call of fill_header()
00104         //        think that the JIT sample file is not a binary file.
00105         if (is_jit_sample(file)) {
00106             cverb << vbfd << "warning: could not check that the binary file "
00107                   << file << " has not been modified since "
00108                   "the profile was taken. Results may be inaccurate.\n";
00109         } else {
00110             cerr << "warning: could not check that the binary file "
00111                  << file << " has not been modified since "
00112                  "the profile was taken. Results may be inaccurate.\n";
00113         }
00114     } else {
00115         static bool warned_already = false;
00116 
00117         cerr << "warning: the last modified time of the binary file "
00118              "does not match that of the sample file for " << file
00119              << "\n";
00120 
00121         if (!warned_already) {
00122             cerr << "Either this is the wrong binary or the binary "
00123             "has been modified since the sample file was created.\n";
00124             warned_already = true;
00125         }
00126     }
00127 }
00128 
00129 
00130 opd_header const read_header(string const & sample_filename)
00131 {
00132     int fd = open(sample_filename.c_str(), O_RDONLY);
00133     if (fd < 0)
00134         throw op_fatal_error("Can't open sample file:" +
00135                      sample_filename);
00136 
00137     opd_header header;
00138     if (read(fd, &header, sizeof(header)) != sizeof(header)) {
00139         close(fd);
00140         throw op_fatal_error("Can't read sample file header:" +
00141                      sample_filename);
00142     }
00143 
00144     if (memcmp(header.magic, OPD_MAGIC, sizeof(header.magic))) {
00145         close(fd);
00146         throw op_fatal_error("Invalid sample file, "
00147                      "bad magic number: " +
00148                      sample_filename);
00149     }
00150 
00151     close(fd);
00152 
00153     return header;
00154 }
00155 
00156 
00157 namespace {
00158 
00159 string const op_print_event(op_cpu cpu_type, u32 type, u32 um, u32 count)
00160 {
00161     string str;
00162 
00163     if (cpu_type == CPU_TIMER_INT) {
00164         str += "Profiling through timer interrupt";
00165         return str;
00166     }
00167 
00168     struct op_event * event = op_find_event(cpu_type, type, um);
00169 
00170     if (!event) {
00171         event = op_find_event_any(cpu_type, type);
00172         if (!event) { 
00173             cerr << "Could not locate event " << int(type) << endl;
00174             str = "Unknown event";
00175             return str;
00176         }
00177     }
00178 
00179     char const * um_desc = 0;
00180 
00181     for (size_t i = 0; i < event->unit->num; ++i) {
00182         if (event->unit->um[i].value == um)
00183             um_desc = event->unit->um[i].desc;
00184     }
00185 
00186     str += string("Counted ") + event->name;
00187     str += string(" events (") + event->desc + ")";
00188 
00189     if (cpu_type != CPU_RTC) {
00190         str += " with a unit mask of 0x";
00191 
00192         ostringstream ss;
00193         ss << hex << setw(2) << setfill('0') << unsigned(um);
00194         str += ss.str();
00195 
00196         str += " (";
00197         str += um_desc ? um_desc : "multiple flags";
00198         str += ")";
00199     }
00200 
00201     str += " count " + op_lexical_cast<string>(count);
00202     return str;
00203 }
00204 
00205 string const op_xml_print_event(op_cpu cpu_type, u32 type, u32 um, u32 count)
00206 {
00207     string unit_mask;
00208 
00209     if (cpu_type == CPU_TIMER_INT || cpu_type == CPU_RTC)
00210         return xml_utils::get_timer_setup((size_t)count);
00211 
00212     struct op_event * event = op_find_event(cpu_type, type, um);
00213     if (!event) {
00214         event = op_find_event_any(cpu_type, type);
00215         if (!event) { 
00216             cerr << "Could not locate event " << int(type) << endl;
00217             return "";
00218         }
00219     }
00220 
00221     if (cpu_type != CPU_RTC) {
00222         ostringstream str_out;
00223         str_out << um;
00224         unit_mask = str_out.str();
00225     }
00226 
00227     return xml_utils::get_event_setup(string(event->name),
00228         (size_t)count, unit_mask);
00229 }
00230 
00231 }
00232 
00233 string const describe_header(opd_header const & header)
00234 {
00235     op_cpu cpu = static_cast<op_cpu>(header.cpu_type);
00236 
00237     if (want_xml)
00238         return op_xml_print_event(cpu, header.ctr_event,
00239                           header.ctr_um, header.ctr_count);
00240     else
00241         return op_print_event(cpu, header.ctr_event,
00242                           header.ctr_um, header.ctr_count);
00243 }
00244 
00245 
00246 string const describe_cpu(opd_header const & header)
00247 {
00248     op_cpu cpu = static_cast<op_cpu>(header.cpu_type);
00249 
00250     string str;
00251     if (want_xml) {
00252         string cpu_name = op_get_cpu_name(cpu);
00253 
00254         str = xml_utils::get_profile_header(cpu_name, header.cpu_speed);
00255     } else {
00256         str += string("CPU: ") + op_get_cpu_type_str(cpu);
00257         if (header.cpu_speed > 0) {
00258             ostringstream ss;
00259 
00260             str += ", speed ";
00261             ss << header.cpu_speed;
00262             str += ss.str() + " MHz (estimated)";
00263         }
00264     }
00265     return str;
00266 }

Generated on 8 Nov 2012 for Oprofile by  doxygen 1.6.1