Main Page   Reference Manual   Namespace List   Compound List   Namespace Members   Compound Members   File Members  

/usr/src/libcwd/libcwd/include/libcwd/class_function.h

Go to the documentation of this file.
00001 // $Header: /cvsroot/libcwd/libcwd/include/libcwd/class_function.h,v 1.6 2004/06/03 12:23:07 libcw Exp $
00002 //
00003 // Copyright (C) 2003 - 2004, by
00004 // 
00005 // Carlo Wood, Run on IRC <carlo@alinoe.com>
00006 // RSA-1024 0x624ACAD5 1997-01-26                    Sign & Encrypt
00007 // Fingerprint16 = 32 EC A7 B6 AC DB 65 A6  F6 F6 55 DD 1C DC FF 61
00008 //
00009 // This file may be distributed under the terms of the Q Public License
00010 // version 1.0 as appearing in the file LICENSE.QPL included in the
00011 // packaging of this file.
00012 //
00013 
00018 #ifndef LIBCWD_CLASS_FUNCTION_H
00019 #define LIBCWD_CLASS_FUNCTION_H
00020 
00021 #ifndef LIBCW_MAP
00022 #define LIBCW_MAP
00023 #include <map>
00024 #endif
00025 
00026 namespace libcwd {
00027 
00028 namespace _private_ {
00029 
00030 // A FunctionChunk represents a contiguous area of code generated by the source
00031 // of a single function, excluding its inlined functions.  The FunctionChunkKey defines
00032 // the begin and end address of the chunk.  A function chunk can therefore begin or
00033 // end at the real function begin or end, but also at the end of, or the beginning of,
00034 // a piece of code that belongs to an inlined function.  As a result, every memory
00035 // address belongs to at most one FunctionChunk.
00036 
00037 struct FunctionChunkKey {
00038   void const* M_start;          // The first byte of the chunk.
00039   void const* M_end;            // One past the last byte of the chunk.
00040 };
00041 
00042 // A FunctionChunk represents a contiguous area of code generated by the source
00043 // of a single function.
00044 
00045 class FunctionInstance;         // Forward declaration.
00046 typedef std::pair<FunctionChunkKey const, FunctionInstance*> FunctionChunk;
00047                                 // This is the value type of the chunk map (FunctionInstanceMap::value_type).
00048 
00049 // Function chunks will never overlap in the end, but while attempting to add
00050 // a new area to the chunk map it is possible that we find that an existing
00051 // chunk overlaps with one that we try to add because we first added the
00052 // outer function and then try to add an inlined function.
00053 //
00054 // by defining the operator<() for FunctionChunkKey's as follows, two overlapping
00055 // chunks A and B:
00056 //
00057 //    M_start                         M_end
00058 // A:  |-------------------------------|
00059 // B:         |----------|
00060 //           M_start    M_end
00061 //
00062 // will return `false' for both (A < B) and (B < A).
00063 // As a result, the chunk map<> will consider them to be equal and not
00064 // insert an overlapping chunk, but notify us of the overlap instead.
00065 
00066 inline bool
00067 operator<(FunctionChunkKey const& chunk1, FunctionChunkKey const& chunk2)
00068 {
00069   // Chunks of size 0 do not exist; therefore it is safe to use the equal sign here.
00070   return chunk1.M_end <= chunk2.M_start;
00071 }
00072 
00073 // A FunctionRootInstanceKey is used as key in FunctionRootsMap in order to garantee
00074 // uniqueness of the FunctionRootInstance objects.
00075 
00076 struct FunctionRootInstanceKey {
00077   char const* M_mangled_name;           // The mangled name is what makes a root instance unique because we
00078                                         // only keep functions from the a single compilation unit per map.
00079                                         // See class compilation_unit_ct.
00080 };
00081 
00082 // A sorting algorithm for this key.
00083 
00084 inline bool
00085 operator<(FunctionRootInstanceKey key1, FunctionRootInstanceKey key2)
00086 {
00087   return std::strcmp(key1.M_mangled_name, key2.M_mangled_name);
00088 }
00089 
00090 // A FunctionRootInstance represents the root instance of a function: it is not
00091 // an inlined instantiation but the standalone version of a function.
00092 //
00093 // All function roots are stored in a map functionRootsMap of type
00094 // map<FunctionRootInstanceKey, FunctionRootInstanceInfo>, see below.
00095 // The FunctionRootInstance contains images of all its instantiations,
00096 // so there should be only one copy of it.  The canonical copy is at
00097 // all times the instance that is added to the functionRootsMap.
00098 
00099 class FunctionRootInstanceInfo;         // Forward declaration.
00100 typedef std::pair<FunctionRootInstanceKey const, FunctionRootInstanceInfo> FunctionRootInstance;
00101                                 // This is the value type of the function roots map (FunctionRootsMap::value_type).
00102 
00103 // A FunctionInstance represents an instantiation of a function, whether inlined
00104 // or not.  As a result, a FunctionInstance belongs to precisely one memory area,
00105 // but a single memory address can belong to multiple FunctionInstances when
00106 // it belongs to a chunk of an inlined function:
00107 //
00108 //                              <--program address space-->
00109 //                            low_pc                                      high_pc
00110 // FunctionInstance f:         |--------------------------------------------|
00111 //                                     low_pc     high_pc
00112 // Inlined FunctionInstance g:          |-----------|
00113 //
00114 // Three function chunks:      |ffffffff|ggggggggggg|fffffffffffffffffffffff|
00115 //                                          ^
00116 //                                          x
00117 // Address 'x' belongs to a single chunk, but to two FunctionInstance's.
00118 
00119 class FunctionInstance {
00120 private:
00121   void const* M_lowpc;                  // The low_pc of the function instance.
00122   void const* M_highpc;                 // The high_pc of the function instance.
00123   FunctionRootInstance* M_root;         // Pointer to the root definition of this function.
00124   FunctionInstance* M_inlined_by;       // Pointer to the function instance that contains this
00125                                         // inlined function, or NULL when this is a root definition.
00126 public:
00127   FunctionInstance(void const* lowpc, void const* highpc, FunctionRootInstance* root, FunctionInstance* inlined_by) :
00128       M_lowpc(lowpc), M_highpc(highpc), M_root(root), M_inlined_by(inlined_by) { }
00129 
00130   void const* lowpc(void) const { return M_lowpc; }
00131   void const* highpc(void) const { return M_highpc; }
00132   inline FunctionRootInstance const* root(void) const;
00133   inline FunctionInstance const* inlined_by(void) const;
00134 };
00135 
00136 // The functionChunkMap contains a mapping of every memory address to the
00137 // function responsible for the assembly code at that address.
00138 //
00139 // Chunks may not overlap.  When trying to insert a chunk that overlaps
00140 // with an existing chunk, insert() will return a pair<..., bool> with
00141 // the boolean set to false.
00142 
00143 #if CWDEBUG_ALLOC
00144 typedef std::map<FunctionChunkKey, FunctionInstance*, std::less<FunctionChunkKey>,
00145     _private_::internal_allocator::rebind<FunctionChunk>::other> FunctionChunkMap;
00146 #else
00147 typedef std::map<FunctionChunkKey, FunctionInstance*, std::less<FunctionChunkKey> > FunctionChunkMap;
00148 #endif
00149 extern FunctionChunkMap functionChunkMap;
00150 
00151 // The remaining information for the function root instance.
00152 
00153 class FunctionRootInstanceInfo {
00154 private:
00155   FunctionInstance M_instance;                          // The root instance itself.
00156   std::string M_demangled_name;                         // The demangled name of this function.
00157   std::vector<FunctionInstance> M_inlined_instances;    // All the inlined instances.
00158 
00159 public:
00160   FunctionRootInstanceInfo(void const* lowpc, void const* highpc, std::string const& demangled_name);
00161   void const* lowpc(void) const { return M_instance.lowpc(); }
00162   void const* highpc(void) const { return M_instance.highpc(); }
00163   std::string const& demangled_name(void) const { return M_demangled_name; }
00164   std::vector<FunctionInstance> const& inlined_instances(void) const { return M_inlined_instances; }
00165   std::vector<FunctionInstance>& inlined_instances(void) { return M_inlined_instances; }
00166 };
00167 
00168 // The functionRootsMap contains all function roots.  The key used is the mangled name
00169 // of the function, causing each function root to be added to the map at most once.
00170 
00171 #if CWDEBUG_ALLOC
00172 typedef std::map<FunctionRootInstanceKey, FunctionRootInstanceInfo, std::less<FunctionRootInstanceKey>,
00173     _private_::internal_allocator::rebind<FunctionRootInstance>::other> FunctionRootsMap;
00174 #else
00175 typedef std::map<FunctionRootInstanceKey, FunctionRootInstanceInfo, std::less<FunctionRootInstanceKey> > FunctionRootsMap;
00176 #endif
00177 
00178 FunctionRootInstance const*
00179 FunctionInstance::root(void) const
00180 {
00181   return M_root;
00182 }
00183 
00184 FunctionInstance const*
00185 FunctionInstance::inlined_by(void) const
00186 {
00187   return M_inlined_by;
00188 }
00189 
00190 } // namespace _private_
00191 
00192 // The Function object represents a function and is intended to be
00193 // used by the user to designate a particular function.  Whether or not
00194 // the function is inlined is completely shielded from the user at
00195 // this point.
00196 
00197 class Function {
00198 private:
00199   int volatile M_initialized;
00200   unsigned int M_flags;
00201 
00202   _private_::FunctionRootInstance* M_root;
00203   char const* M_label;
00204 
00205 public:
00206   char const* label(void) const { return M_label; }
00207   bool is_initialized(void) const { return M_initialized; }
00208 
00209 private:
00210   void M_init(void);
00211   void M_init(Function& function);
00212   void M_init(char const* expr, unsigned int flags);
00213 
00214 public:
00215   static unsigned int const nofail = 1;
00216   static unsigned int const c_linkage = 2;
00217   static unsigned int const cpp_linkage = 4;
00218   static unsigned int const mangled = 8;
00219   static unsigned int const regexp = 16;
00220   static unsigned int const exactmatch = 32;
00221 
00222   Function(void) : M_initialized(false), M_flags(0) { }
00223   Function(unsigned int flags) : M_initialized(false), M_flags(flags) { }
00224  
00225   void init(void) { if (!M_initialized) M_init(); }
00226   void init(Function& function) { if (!function.is_initialized()) M_init(function); }
00227   void init(char const* expr, unsigned int flags = mangled|cpp_linkage) { if (!M_initialized) M_init(expr, flags); }
00228 
00229   void label(char const* lbl) { M_label = lbl; }
00230   void rmlabel(void) { M_label = NULL; }
00231 };
00232 
00233 } // namespace libcwd
00234 
00235 #endif // LIBCWD_CLASS_FUNCTION_H
Copyright © 2001 - 2004 Carlo Wood.  All rights reserved.