00001 /* 00002 * @file pe_profiling/operf_process_info.h 00003 * This file contains functions for storing process information, 00004 * handling exectuable mmappings, etc. 00005 * 00006 * @remark Copyright 2011 OProfile authors 00007 * @remark Read the file COPYING 00008 * 00009 * Created on: Dec 7, 2011 00010 * @author Maynard Johnson 00011 * (C) Copyright IBM Corp. 2011 00012 */ 00013 00014 #ifndef OPERF_PROCESS_INFO_H_ 00015 #define OPERF_PROCESS_INFO_H_ 00016 00017 #include <map> 00018 #include <limits.h> 00019 #include "op_types.h" 00020 #include "cverb.h" 00021 00022 extern verbose vmisc; 00023 00024 struct operf_mmap { 00025 u64 start_addr; 00026 u64 end_addr; 00027 u64 pgoff; 00028 bool is_anon_mapping; 00029 bool is_hypervisor; 00030 char filename[PATH_MAX]; 00031 }; 00032 00033 /* This class is designed to hold information about a process for which a COMM event 00034 * has been recorded in the profile data: application name, process ID, and a map 00035 * containing all of the libraries and executable anonymous memory mappings used by this 00036 * process. 00037 * 00038 * The COMM event provides only a 16-char (possibly abbreviated) "comm" field for the 00039 * executable's basename. If operf is being run in single-process mode vs system-wide, 00040 * then we will know what the full pathname of the executable is, in which case, that 00041 * will be the value stored in the app_name field; otherwise, as MMAP events are 00042 * processed, we compare their basenames to the short name we got from the COMM event. 00043 * The mmap'ing whose basename has the most matching characters is chosen to use as 00044 * the full pathname of the application. TODO: It's possible that this choice may be wrong; 00045 * we should verify the choice by looking at the ELF data (ELF header e_type field should 00046 * be "ET_EXEC"). 00047 * 00048 * This class is designed to handle the possibility that MMAP events may occur for a process 00049 * prior to the COMM event. I don't know if this is possible, but it didn't take much to 00050 * add code to handle this exigency. 00051 */ 00052 class operf_process_info { 00053 public: 00054 operf_process_info(pid_t tgid, const char * appname, bool app_arg_is_fullname, bool is_valid); 00055 ~operf_process_info(void); 00056 bool is_valid(void) { return (valid); } 00057 bool is_forked(void) { return forked; } 00058 void process_new_mapping(struct operf_mmap * mapping); 00059 void process_hypervisor_mapping(u64 ip); 00060 void process_deferred_mappings(std::string app_shortname); 00061 void connect_forked_process_to_parent(operf_process_info * parent); 00062 void copy_new_parent_mapping(struct operf_mmap * mapping) 00063 { mmappings[mapping->start_addr] = mapping; } 00064 void add_forked_pid_association(operf_process_info * forked_pid) 00065 { forked_processes.push_back(forked_pid); } 00066 void copy_mappings_to_forked_process(operf_process_info * forked_pid); 00067 void disassociate_from_parent(char * appname); 00068 void remove_forked_process(pid_t forked_pid); 00069 std::string get_app_name(void) { return _appname; } 00070 void add_deferred_mapping(struct operf_mmap * mapping) 00071 { deferred_mmappings[mapping->start_addr] = mapping; } 00072 const struct operf_mmap * find_mapping_for_sample(u64 sample_addr); 00073 00074 /* The valid bit is set when a COMM event has been received for the process 00075 * represented by this object. But since the COMM event only gives a shortname 00076 * for the app (16 chars at most), the process_info object is not completely 00077 * baked until appname_valid() returns true. In truth, if appname_valid returns 00078 * true, we can't really be sure we've got a valid full app name since the true 00079 * result could be from: 00080 * (appname_is_fullname == MAYBE_FULLNAME) &&(num_app_chars_matched > 0) 00081 * But this is the best guess we can make. 00082 */ 00083 bool is_appname_valid(void) 00084 { 00085 bool result; 00086 if (!valid) 00087 return false; 00088 if (appname_is_fullname == YES_FULLNAME) 00089 result = true; 00090 else if ((appname_is_fullname == MAYBE_FULLNAME) && 00091 (num_app_chars_matched > 0)) 00092 result = true; 00093 else 00094 result = false; 00095 return result; 00096 } 00097 00098 private: 00099 typedef enum { 00100 NOT_FULLNAME, 00101 MAYBE_FULLNAME, 00102 YES_FULLNAME 00103 } op_fullname_t; 00104 pid_t pid; 00105 std::string _appname; 00106 bool valid; 00107 bool forked; 00108 op_fullname_t appname_is_fullname; 00109 std::string app_basename; 00110 int num_app_chars_matched; 00111 std::map<u64, struct operf_mmap *> mmappings; 00112 std::map<u64, struct operf_mmap *> deferred_mmappings; 00113 /* When a FORK event is recieved, we try to associate that forked 00114 * process with its parent, but if the parent operf_process_info is 00115 * not yet valid, we have to defer this association until 00116 * after the parent becomes valid. This forked_processes collection 00117 * holds those forked processes for which the association to the 00118 * parent has been deferred. 00119 */ 00120 std::vector<operf_process_info *> forked_processes; 00121 operf_process_info * parent_of_fork; 00122 int get_num_matching_chars(std::string mapped_filename, std::string & basename); 00123 void process_deferred_forked_processes(void); 00124 }; 00125 00126 00127 #endif /* OPERF_PROCESS_INFO_H_ */