operf_process_info.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <stdio.h>
00015 #include <iostream>
00016 #include <map>
00017 #include <string.h>
00018 #include "operf_process_info.h"
00019 #include "file_manip.h"
00020 #include "operf_utils.h"
00021
00022 using namespace std;
00023 using namespace OP_perf_utils;
00024
00025 operf_process_info::operf_process_info(pid_t tgid, const char * appname, bool app_arg_is_fullname, bool is_valid)
00026 : pid(tgid), _appname(appname ? appname : ""), valid(is_valid)
00027 {
00028 if (app_arg_is_fullname && appname) {
00029 appname_is_fullname = YES_FULLNAME;
00030 app_basename = op_basename(appname);
00031 num_app_chars_matched = (int)app_basename.length();
00032 } else if (appname) {
00033 appname_is_fullname = MAYBE_FULLNAME;
00034 num_app_chars_matched = -1;
00035 app_basename = appname;
00036 } else {
00037 appname_is_fullname = NOT_FULLNAME;
00038 num_app_chars_matched = -1;
00039 app_basename = "";
00040 }
00041 forked = false;
00042 parent_of_fork = NULL;
00043 }
00044
00045 operf_process_info::~operf_process_info()
00046 {
00047 map<u64, struct operf_mmap *>::iterator it;
00048 map<u64, struct operf_mmap *>::iterator end;
00049
00050 if (valid) {
00051 it = mmappings.begin();
00052 end = mmappings.end();
00053 } else {
00054 it = deferred_mmappings.begin();
00055 end = deferred_mmappings.end();
00056 }
00057 mmappings.clear();
00058 deferred_mmappings.clear();
00059 }
00060
00061 void operf_process_info::process_new_mapping(struct operf_mmap * mapping)
00062 {
00063
00064
00065
00066
00067 if (!mapping->is_anon_mapping && (appname_is_fullname < YES_FULLNAME) && (num_app_chars_matched < (int)app_basename.length())) {
00068 string basename;
00069 int num_matched_chars = get_num_matching_chars(mapping->filename, basename);
00070 if (num_matched_chars > num_app_chars_matched) {
00071 appname_is_fullname = MAYBE_FULLNAME;
00072 _appname = mapping->filename;
00073 app_basename = basename;
00074 num_app_chars_matched = num_matched_chars;
00075 cverb << vmisc << "Best appname match is " << _appname << endl;
00076 }
00077 }
00078 mmappings[mapping->start_addr] = mapping;
00079 vector<operf_process_info *>::iterator it = forked_processes.begin();
00080 while (it != forked_processes.end()) {
00081 operf_process_info * p = *it;
00082 p->copy_new_parent_mapping(mapping);
00083 cverb << vmisc << "Copied new parent mapping for " << mapping->filename
00084 << " for forked process " << p->pid << endl;
00085 it++;
00086 }
00087
00088 }
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 void operf_process_info::process_deferred_mappings(string app_shortname)
00099 {
00100 _appname = app_shortname;
00101 app_basename = app_shortname;
00102 valid = true;
00103 map<u64, struct operf_mmap *>::iterator it = deferred_mmappings.begin();
00104 while (it != deferred_mmappings.end()) {
00105 process_new_mapping(it->second);
00106 cverb << vmisc << "Processed deferred mapping for " << it->second->filename << endl;
00107 it++;
00108 }
00109 deferred_mmappings.clear();
00110 process_deferred_forked_processes();
00111 }
00112
00113 int operf_process_info::get_num_matching_chars(string mapped_filename, string & basename)
00114 {
00115 size_t app_length;
00116 size_t basename_length;
00117 const char * app_cstr, * basename_cstr;
00118 string app_basename;
00119 basename = op_basename(mapped_filename);
00120 if (appname_is_fullname == NOT_FULLNAME) {
00121
00122 app_length = _appname.length();
00123 app_cstr = _appname.c_str();
00124 } else {
00125 app_basename = op_basename(_appname);
00126 app_length = app_basename.length();
00127 app_cstr = app_basename.c_str();
00128 }
00129 basename_length = basename.length();
00130 if (app_length > basename_length)
00131 return -1;
00132
00133 basename_cstr = basename.c_str();
00134 int num_matched_chars = 0;
00135 for (size_t i = 0; i < app_length; i++) {
00136 if (app_cstr[i] == basename_cstr[i])
00137 num_matched_chars++;
00138 else
00139 break;
00140 }
00141 return num_matched_chars ? num_matched_chars : -1;
00142 }
00143
00144 const struct operf_mmap * operf_process_info::find_mapping_for_sample(u64 sample_addr)
00145 {
00146 map<u64, struct operf_mmap *>::iterator it = mmappings.begin();
00147 while (it != mmappings.end()) {
00148 if (sample_addr >= it->second->start_addr && sample_addr <= it->second->end_addr)
00149 return it->second;
00150 it++;
00151 }
00152 return NULL;
00153 }
00154
00173 void operf_process_info::process_hypervisor_mapping(u64 ip)
00174 {
00175 bool create_new_hyperv_mmap = true;
00176 u64 curr_start, curr_end;
00177 map<u64, struct operf_mmap *>::iterator it;
00178 map<u64, struct operf_mmap *>::iterator end;
00179
00180 curr_end = curr_start = ~0ULL;
00181 if (valid) {
00182 it = mmappings.begin();
00183 end = mmappings.end();
00184 } else {
00185 it = deferred_mmappings.begin();
00186 end = deferred_mmappings.end();
00187 }
00188 while (it != end) {
00189 if (it->second->is_hypervisor) {
00190 struct operf_mmap * _mmap = it->second;
00191 curr_start = _mmap->start_addr;
00192 curr_end = _mmap->end_addr;
00193 if (curr_start > ip) {
00194 if (valid)
00195 mmappings.erase(it);
00196 else
00197 deferred_mmappings.erase(it);
00198 delete _mmap;
00199 } else {
00200 create_new_hyperv_mmap = false;
00201 if (curr_end <= ip)
00202 _mmap->end_addr = ip;
00203 }
00204 break;
00205 }
00206 it++;
00207 }
00208
00209 if (create_new_hyperv_mmap) {
00210 struct operf_mmap * hypervisor_mmap = new struct operf_mmap;
00211 memset(hypervisor_mmap, 0, sizeof(struct operf_mmap));
00212 hypervisor_mmap->start_addr = ip;
00213 hypervisor_mmap->end_addr = ((curr_end == ~0ULL) || (curr_end < ip)) ? ip : curr_end;
00214 strcpy(hypervisor_mmap->filename, "[hypervisor_bucket]");
00215 hypervisor_mmap->is_anon_mapping = true;
00216 hypervisor_mmap->pgoff = 0;
00217 hypervisor_mmap->is_hypervisor = true;
00218 if (cverb << vmisc) {
00219 cout << "Synthesize mmapping for " << hypervisor_mmap->filename << endl;
00220 cout << "\tstart_addr: " << hex << hypervisor_mmap->start_addr;
00221 cout << "; end addr: " << hypervisor_mmap->end_addr << endl;
00222 }
00223 if (valid)
00224 process_new_mapping(hypervisor_mmap);
00225 else
00226 add_deferred_mapping(hypervisor_mmap);
00227 }
00228 }
00229
00230 void operf_process_info::copy_mappings_to_forked_process(operf_process_info * forked_pid)
00231 {
00232 map<u64, struct operf_mmap *>::iterator it = mmappings.begin();
00233 while (it != mmappings.end()) {
00234 struct operf_mmap * mapping = it->second;
00235
00236
00237
00238
00239 forked_pid->process_new_mapping(mapping);
00240 it++;
00241 }
00242 }
00243
00244 void operf_process_info::connect_forked_process_to_parent(operf_process_info * parent)
00245 {
00246 forked = true;
00247 parent_of_fork = parent;
00248 if (parent->is_valid()) {
00249 valid = true;
00250 _appname = parent->get_app_name();
00251 if (parent->is_appname_valid() && !_appname.empty()) {
00252 appname_is_fullname = YES_FULLNAME;
00253 app_basename = op_basename(_appname);
00254 num_app_chars_matched = (int)app_basename.length();
00255 } else if (!_appname.empty()) {
00256 appname_is_fullname = MAYBE_FULLNAME;
00257 num_app_chars_matched = -1;
00258 app_basename = _appname;
00259 } else {
00260 appname_is_fullname = NOT_FULLNAME;
00261 num_app_chars_matched = -1;
00262 app_basename = "";
00263 }
00264 parent->copy_mappings_to_forked_process(this);
00265 }
00266 }
00267
00268 void operf_process_info::process_deferred_forked_processes(void)
00269 {
00270 vector<operf_process_info *>::iterator it = forked_processes.begin();
00271 while (it != forked_processes.end()) {
00272 operf_process_info * p = *it;
00273 p->connect_forked_process_to_parent(this);
00274 cverb << vmisc << "Processed deferred forked process " << p->pid << endl;
00275 it++;
00276 }
00277 }
00278
00279 void operf_process_info::remove_forked_process(pid_t forked_pid)
00280 {
00281 std::vector<operf_process_info *>::iterator it = forked_processes.begin();
00282 while (it != forked_processes.end()) {
00283 if ((*it)->pid == forked_pid) {
00284 forked_processes.erase(it);
00285 break;
00286 }
00287 it++;
00288 }
00289 }
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 void operf_process_info::disassociate_from_parent(char * app_shortname)
00300 {
00301 _appname = app_shortname;
00302 app_basename = app_shortname;
00303 appname_is_fullname = NOT_FULLNAME;
00304 valid = true;
00305
00306
00307
00308
00309 num_app_chars_matched = 0;
00310 map<u64, struct operf_mmap *>::iterator it = mmappings.begin();
00311 while (it != mmappings.end()) {
00312 process_new_mapping(it->second);
00313 it++;
00314 }
00315 parent_of_fork->remove_forked_process(this->pid);
00316 }