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

class_function.h
Go to the documentation of this file.
1 // $Header$
2 //
3 // Copyright (C) 2003 - 2004, by
4 //
5 // Carlo Wood, Run on IRC <carlo@alinoe.com>
6 // RSA-1024 0x624ACAD5 1997-01-26 Sign & Encrypt
7 // Fingerprint16 = 32 EC A7 B6 AC DB 65 A6 F6 F6 55 DD 1C DC FF 61
8 //
9 // This file may be distributed under the terms of the Q Public License
10 // version 1.0 as appearing in the file LICENSE.QPL included in the
11 // packaging of this file.
12 //
13 
18 #ifndef LIBCWD_CLASS_FUNCTION_H
19 #define LIBCWD_CLASS_FUNCTION_H
20 
21 #ifndef LIBCW_MAP
22 #define LIBCW_MAP
23 #include <map>
24 #endif
25 #ifndef LIBCW_VECTOR
26 #define LIBCW_VECTOR
27 #include <vector>
28 #endif
29 
30 namespace libcwd {
31 
32 namespace _private_ {
33 
34 // A FunctionChunk represents a contiguous area of code generated by the source
35 // of a single function, excluding its inlined functions. The FunctionChunkKey defines
36 // the begin and end address of the chunk. A function chunk can therefore begin or
37 // end at the real function begin or end, but also at the end of, or the beginning of,
38 // a piece of code that belongs to an inlined function. As a result, every memory
39 // address belongs to at most one FunctionChunk.
40 
41 struct FunctionChunkKey {
42  void const* M_start; // The first byte of the chunk.
43  void const* M_end; // One past the last byte of the chunk.
44 };
45 
46 // A FunctionChunk represents a contiguous area of code generated by the source
47 // of a single function.
48 
49 class FunctionInstance; // Forward declaration.
50 typedef std::pair<FunctionChunkKey const, FunctionInstance*> FunctionChunk;
51  // This is the value type of the chunk map (FunctionInstanceMap::value_type).
52 
53 // Function chunks will never overlap in the end, but while attempting to add
54 // a new area to the chunk map it is possible that we find that an existing
55 // chunk overlaps with one that we try to add because we first added the
56 // outer function and then try to add an inlined function.
57 //
58 // by defining the operator<() for FunctionChunkKey's as follows, two overlapping
59 // chunks A and B:
60 //
61 // M_start M_end
62 // A: |-------------------------------|
63 // B: |----------|
64 // M_start M_end
65 //
66 // will return `false' for both (A < B) and (B < A).
67 // As a result, the chunk map<> will consider them to be equal and not
68 // insert an overlapping chunk, but notify us of the overlap instead.
69 
70 inline bool
71 operator<(FunctionChunkKey const& chunk1, FunctionChunkKey const& chunk2)
72 {
73  // Chunks of size 0 do not exist; therefore it is safe to use the equal sign here.
74  return chunk1.M_end <= chunk2.M_start;
75 }
76 
77 // A FunctionRootInstanceKey is used as key in FunctionRootsMap in order to garantee
78 // uniqueness of the FunctionRootInstance objects.
79 
80 struct FunctionRootInstanceKey {
81  char const* M_mangled_name; // The mangled name is what makes a root instance unique because we
82  // only keep functions from the a single compilation unit per map.
83  // See class compilation_unit_ct.
84 };
85 
86 // A sorting algorithm for this key.
87 
88 inline bool
89 operator<(FunctionRootInstanceKey key1, FunctionRootInstanceKey key2)
90 {
91  return std::strcmp(key1.M_mangled_name, key2.M_mangled_name);
92 }
93 
94 // A FunctionRootInstance represents the root instance of a function: it is not
95 // an inlined instantiation but the standalone version of a function.
96 //
97 // All function roots are stored in a map functionRootsMap of type
98 // map<FunctionRootInstanceKey, FunctionRootInstanceInfo>, see below.
99 // The FunctionRootInstance contains images of all its instantiations,
100 // so there should be only one copy of it. The canonical copy is at
101 // all times the instance that is added to the functionRootsMap.
102 
103 class FunctionRootInstanceInfo; // Forward declaration.
104 typedef std::pair<FunctionRootInstanceKey const, FunctionRootInstanceInfo> FunctionRootInstance;
105  // This is the value type of the function roots map (FunctionRootsMap::value_type).
106 
107 // A FunctionInstance represents an instantiation of a function, whether inlined
108 // or not. As a result, a FunctionInstance belongs to precisely one memory area,
109 // but a single memory address can belong to multiple FunctionInstances when
110 // it belongs to a chunk of an inlined function:
111 //
112 // <--program address space-->
113 // low_pc high_pc
114 // FunctionInstance f: |--------------------------------------------|
115 // low_pc high_pc
116 // Inlined FunctionInstance g: |-----------|
117 //
118 // Three function chunks: |ffffffff|ggggggggggg|fffffffffffffffffffffff|
119 // ^
120 // x
121 // Address 'x' belongs to a single chunk, but to two FunctionInstance's.
122 
123 class FunctionInstance {
124 private:
125  void const* M_lowpc; // The low_pc of the function instance.
126  void const* M_highpc; // The high_pc of the function instance.
127  FunctionRootInstance* M_root; // Pointer to the root definition of this function.
128  FunctionInstance* M_inlined_by; // Pointer to the function instance that contains this
129  // inlined function, or NULL when this is a root definition.
130 public:
131  FunctionInstance(void const* lowpc, void const* highpc, FunctionRootInstance* root, FunctionInstance* inlined_by) :
132  M_lowpc(lowpc), M_highpc(highpc), M_root(root), M_inlined_by(inlined_by) { }
133 
134  void const* lowpc() const { return M_lowpc; }
135  void const* highpc() const { return M_highpc; }
136  inline FunctionRootInstance const* root() const;
137  inline FunctionInstance const* inlined_by() const;
138 };
139 
140 // The functionChunkMap contains a mapping of every memory address to the
141 // function responsible for the assembly code at that address.
142 //
143 // Chunks may not overlap. When trying to insert a chunk that overlaps
144 // with an existing chunk, insert() will return a pair<..., bool> with
145 // the boolean set to false.
146 
147 #if CWDEBUG_ALLOC
148 typedef std::map<FunctionChunkKey, FunctionInstance*, std::less<FunctionChunkKey>,
149  _private_::internal_allocator::rebind<FunctionChunk>::other> FunctionChunkMap;
150 #else
151 typedef std::map<FunctionChunkKey, FunctionInstance*, std::less<FunctionChunkKey> > FunctionChunkMap;
152 #endif
153 extern FunctionChunkMap functionChunkMap;
154 
155 // The remaining information for the function root instance.
156 
157 class FunctionRootInstanceInfo {
158 private:
159  FunctionInstance M_instance; // The root instance itself.
160  std::string M_demangled_name; // The demangled name of this function.
161  std::vector<FunctionInstance> M_inlined_instances; // All the inlined instances.
162 
163 public:
164  FunctionRootInstanceInfo(void const* lowpc, void const* highpc, std::string const& demangled_name);
165  void const* lowpc() const { return M_instance.lowpc(); }
166  void const* highpc() const { return M_instance.highpc(); }
167  std::string const& demangled_name() const { return M_demangled_name; }
168  std::vector<FunctionInstance> const& inlined_instances() const { return M_inlined_instances; }
169  std::vector<FunctionInstance>& inlined_instances() { return M_inlined_instances; }
170 };
171 
172 // The functionRootsMap contains all function roots. The key used is the mangled name
173 // of the function, causing each function root to be added to the map at most once.
174 
175 #if CWDEBUG_ALLOC
176 typedef std::map<FunctionRootInstanceKey, FunctionRootInstanceInfo, std::less<FunctionRootInstanceKey>,
177  _private_::internal_allocator::rebind<FunctionRootInstance>::other> FunctionRootsMap;
178 #else
179 typedef std::map<FunctionRootInstanceKey, FunctionRootInstanceInfo, std::less<FunctionRootInstanceKey> > FunctionRootsMap;
180 #endif
181 
182 FunctionRootInstance const*
183 FunctionInstance::root() const
184 {
185  return M_root;
186 }
187 
188 FunctionInstance const*
189 FunctionInstance::inlined_by() const
190 {
191  return M_inlined_by;
192 }
193 
194 } // namespace _private_
195 
196 // The Function object represents a function and is intended to be
197 // used by the user to designate a particular function. Whether or not
198 // the function is inlined is completely shielded from the user at
199 // this point.
200 
201 class Function {
202 private:
203  int volatile M_initialized;
204  unsigned int M_flags;
205 
206  _private_::FunctionRootInstance* M_root;
207  char const* M_label;
208 
209 public:
210  char const* label() const { return M_label; }
211  bool is_initialized() const { return M_initialized; }
212 
213 private:
214  void M_init();
215  void M_init(Function& function);
216  void M_init(char const* expr, unsigned int flags);
217 
218 public:
219  static unsigned int const nofail = 1;
220  static unsigned int const c_linkage = 2;
221  static unsigned int const cpp_linkage = 4;
222  static unsigned int const mangled = 8;
223  static unsigned int const regexp = 16;
224  static unsigned int const exactmatch = 32;
225 
226  Function() : M_initialized(false), M_flags(0) { }
227  Function(unsigned int flags) : M_initialized(false), M_flags(flags) { }
228 
229  void init() { if (!M_initialized) M_init(); }
230  void init(Function& function) { if (!function.is_initialized()) M_init(function); }
231  void init(char const* expr, unsigned int flags = mangled|cpp_linkage) { if (!M_initialized) M_init(expr, flags); }
232 
233  void label(char const* lbl) { M_label = lbl; }
234  void rmlabel() { M_label = NULL; }
235 };
236 
237 } // namespace libcwd
238 
239 #endif // LIBCWD_CLASS_FUNCTION_H
namespace for libcwd.
Definition: debug.cc:87
Copyright © 2001 - 2004 Carlo Wood.  All rights reserved.