Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / miniTramp.h
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 // $Id: miniTramp.h,v 1.19 2008/01/16 22:01:37 legendre Exp $
33
34 #ifndef MINI_TRAMP_H
35 #define MINI_TRAMP_H
36
37 #include "common/h/Types.h"
38 #include "dyninstAPI/src/codeRange.h"
39 #include "dyninstAPI/src/inst.h" // callOrder and callWhen
40 #include "dyninstAPI/src/instPoint.h" // generatedCodeObject
41 #include "dyninstAPI/src/multiTramp.h" // generatedCodeObject
42 #include "dyninstAPI/src/ast.h"
43
44 // This is a serious problem: our code generation has no way to check
45 // the size of the buffer it's emitting to.
46 // 1 megabyte buffer
47 #define MAX_MINITRAMP_SIZE (0x100000)
48
49 // Callback func for deletion of a minitramp
50 class miniTramp;
51 class AstNode;
52 class AstMiniTrampNode;
53 class AddressSpace;
54
55 typedef void (*miniTrampFreeCallback)(void *, miniTramp *);
56
57 // The new miniTramp class -- description of a particular minitramp.
58 // mini tramps are kind of annoying... there can be multiple copies of
59 // a single minitramp depending on whether a function has been cloned
60 // or not. So we need a single miniTramp structure that can handle
61 // multiple instantiations of actual code.
62
63 class miniTrampInstance : public generatedCodeObject {
64     friend class miniTramp;
65  public:
66
67   miniTrampInstance(miniTramp *mini,
68                     baseTrampInstance *bti) :
69       generatedCodeObject(),
70       baseTI(bti),
71       mini(mini),
72       trampBase(0),
73       deleted(false) {
74   }
75
76   // FORK!
77   miniTrampInstance(const miniTrampInstance *parMini,
78                     baseTrampInstance *cBTI,
79                     miniTramp *cMT,
80                     process *child);
81
82   // Inline replacing of code
83   miniTrampInstance(const miniTrampInstance *origMTI,
84                     baseTrampInstance *newParent);
85   
86   // Need to have a destructor, so we can track when each instance goes away. 
87   ~miniTrampInstance();
88
89   baseTrampInstance *baseTI;
90   miniTramp *mini;
91   Address trampBase;
92   bool deleted;
93
94   Address get_address() const { return trampBase; }
95   unsigned get_size() const; // needs miniTramp and is so defined
96                                 // in .C file
97   void *getPtrToInstruction(Address addr) const;
98
99   Address uninstrumentedAddr() const;
100   
101   unsigned maxSizeRequired();
102
103   bool hasChanged();
104
105   bool generateCode(codeGen &gen,
106                     Address baseInMutatee,
107                     UNW_INFO_TYPE * * unwindInformation);
108   bool installCode();
109   
110   void invalidateCode();
111
112   bool linkCode();
113
114   void removeCode(generatedCodeObject *subObject);
115
116   generatedCodeObject *replaceCode(generatedCodeObject *newParent);
117
118   bool safeToFree(codeRange *range);
119
120   void freeCode();
121
122   unsigned cost();
123
124   AddressSpace *proc() const;
125
126 };
127
128 class miniTramp {
129     friend class miniTrampInstance;
130   friend class instPoint;
131     // Global numbering of minitramps
132   static int _id;
133
134   miniTramp();
135
136   public:
137
138   miniTramp(callWhen when_,
139             AstNodePtr ast,
140             baseTramp *base,
141             bool noCost);
142   
143   // Fork constructor
144   miniTramp(const miniTramp *parMini, baseTramp *childT, process *proc);
145   
146   ~miniTramp();
147
148   // Given a child address space, get the corresponding miniTramp to us.
149   miniTramp *getInheritedMiniTramp(process *child);
150
151   // Catchup...
152
153   // Returns true if newMT is "after" (later in the chain) than the
154   // curMT (and we're out-of-lining), _OR_ if the miniTramps
155   // are generated in-line (in which case we miss it
156   // completely). TODO: in-line needs to update this.
157   
158   static bool catchupRequired(miniTramp *curMT, miniTramp *newMT, bool active);
159
160   // Generate the code necessary
161   // We use a single global image of a minitramp.
162   bool generateMT(registerSpace *rs);
163   codeGen miniTrampCode_;
164   
165   // The delete operator, just without delete. Uninstruments minis.
166   bool uninstrument();
167
168   unsigned get_size() const {
169     assert(returnOffset);
170     return returnOffset;
171   }
172
173   // Returns true if we were put in via a trap. Actually... returns if
174   // all miniTrampInstances have multiTramps that were trapped to.
175   // Since we can relocate (and not use a trap in one instance, but 
176   // do in another).
177   bool instrumentedViaTrap() const;
178
179   // Register a callback for when the mini is finally deleted...
180   void registerCallback(miniTrampFreeCallback cb, void *data) {
181     callback = cb;
182     callbackData = data;
183   };
184
185
186   // Returns true if all's well.
187   bool checkMTStatus();
188
189   miniTrampInstance *getMTInstanceByBTI(baseTrampInstance *instance,
190                                         bool create_if_not_found = true);
191
192   int ID;                    // used to match up miniTramps in forked procs
193   Address returnOffset;      // Offset from base to the return addr
194   unsigned size_;
195
196   // Base tramp we're installed at
197   baseTramp *baseT;
198
199   // Sucks it out of the baseTramp
200   instPoint *instP() const;
201   int_function *func() const;
202
203   // instPs can go away... keep a local process pointer to let us
204   // use it in the future.
205
206   AddressSpace *proc_;
207
208   AddressSpace *proc() const { return proc_; }
209
210   void deleteMTI(miniTrampInstance *);
211
212   // This is nice for back-tracking.
213   callWhen when; /* Pre or post */
214
215   int cost;                  // cost in cycles of this inst req.
216   bool noCost_;
217
218   /**
219    * When cleaning up minitramps and minitramp instances we could be doing a 
220    * bottom-up cleanup (delete an instance, which deletes a minitramp) during gc
221    * or top-down cleanup (delete a minitramp, which deletes an instance) when 
222    * instrumentation is removing.  If topDownDelete_ is set to true, we're removing
223    * instrumentation and the minitramp instance should not delete it's minitramp.
224    **/
225   bool topDownDelete_; 
226
227   pdvector<miniTrampInstance *> instances;
228   pdvector<miniTrampInstance *> deletedMTIs;
229
230   // Make sure all jumps are consistent...
231   bool correctMTJumps();
232
233   // Previous and next minitramps
234   miniTramp *prev;
235   miniTramp *next;
236
237   // Material to check when deleting this miniTramp
238   miniTrampFreeCallback callback; /* Callback to be made when
239                                         instance is deleted */
240   void *callbackData;                /* Associated data */
241
242   bool deleteInProgress; // Don't double-delete
243
244   AstMiniTrampNodePtr ast_; // For regenerating miniTs
245 };
246
247
248 #endif