operf_process_info.h

Go to the documentation of this file.
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_ */

Generated on 8 Nov 2012 for Oprofile by  doxygen 1.6.1