Addition of changesand new classes for implementation of
[dyninst.git] / dyninstAPI / src / BPatch_function.C
1 /*
2  * Copyright (c) 1996 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  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 // $Id: BPatch_function.C,v 1.3 2000/03/14 22:31:25 tikir Exp $
43
44 #include <string.h>
45 #include "symtab.h"
46 #include "process.h"
47 #include "instPoint.h"
48
49 #include "BPatch.h"
50 #include "BPatch_type.h"
51 #include "BPatch_collections.h"
52 #include "BPatch_Vector.h"
53 #include "LineInformation.h"
54
55 /* XXX Should be in a dyninst API include file (right now in perfStream.h) */
56 extern double cyclesPerSecond;
57
58
59 /**************************************************************************
60  * BPatch_function
61  *************************************************************************/
62 /*
63  * BPatch_function::BPatch_function
64  *
65  * Constructor that creates a BPatch_function.
66  *
67  */
68 BPatch_function::BPatch_function(process *_proc, function_base *_func,
69         BPatch_module *_mod) :
70         proc(_proc), mod(_mod), func(_func)
71 {
72
73   // there should be at most one BPatch_func for each function_base per process
74   assert(proc->thread && !proc->PDFuncToBPFuncMap[func]);
75
76   _srcType = BPatch_sourceFunction;
77
78   localVariables = new BPatch_localVarCollection;
79   funcParameters = new BPatch_localVarCollection;
80   retType = NULL;
81
82   proc->PDFuncToBPFuncMap[_func] = this;
83 };
84
85 /*
86  * BPatch_function::BPatch_function
87  *
88  * Constructor that creates the BPatch_function with return type.
89  *
90  */
91 BPatch_function::BPatch_function(process *_proc, function_base *_func,
92                                  BPatch_type * _retType, BPatch_module *_mod) :
93         proc(_proc), mod(_mod), func(_func)
94 {
95   _srcType = BPatch_sourceFunction;
96   localVariables = new BPatch_localVarCollection;
97   funcParameters = new BPatch_localVarCollection;
98   retType = _retType;
99 };
100
101
102 BPatch_function::~BPatch_function()
103 {
104     // if (ast != NULL)
105         // removeAst(ast);
106     if (localVariables) delete localVariables;
107     if (funcParameters) delete funcParameters;
108 }
109
110 /* 
111  * BPatch_function::getSourceObj()
112  *
113  * Return the contained source objects (e.g. statements).
114  *    This is not currently supported.
115  *
116  */
117 BPatch_Vector<BPatch_sourceObj *> *BPatch_function::getSourceObj()
118 {
119     return NULL;
120 }
121
122 /*
123  * BPatch_function::getObjParent()
124  *
125  * Return the parent of the function (i.e. the module)
126  *
127  */
128 BPatch_sourceObj *BPatch_function::getObjParent()
129 {
130     return (BPatch_sourceObj *) mod;
131 }
132
133 /*
134  * BPatch_function::getName
135  *
136  * Copies the name of the function into a buffer, up to a given maximum
137  * length.  Returns a pointer to the beginning of the buffer that was
138  * passed in.
139  *
140  * s            The buffer into which the name will be copied.
141  * len          The size of the buffer.
142  */
143 char *BPatch_function::getName(char *s, int len)
144 {
145     assert(func);
146     string name = func->prettyName();
147     strncpy(s, name.string_of(), len);
148
149     return s;
150 }
151
152
153 /*
154  * BPatch_function::getBaseAddr
155  *
156  * Returns the starting address of the function.
157  */
158 void *BPatch_function::getBaseAddr()
159 {
160      return (void *)func->getEffectiveAddress(proc);
161 }
162
163
164 /*
165  * BPatch_function::getSize
166  *
167  * Returns the size of the function in bytes.
168  */
169 unsigned int BPatch_function::getSize()
170 {
171   return func->size();
172 }
173
174
175 /*
176  * BPatch_function::findPoint
177  *
178  * Returns a vector of the instrumentation points from a procedure that is
179  * identified by the parameters, or returns NULL upon failure.
180  * (Points are sorted by address in the vector returned.)
181  *
182  * loc          The points within the procedure to return.  The following
183  *              values are valid for this parameter:
184  *                BPatch_entry         The function's entry point.
185  *                BPatch_exit          The function's exit point(s).
186  *                BPatch_subroutine    The points at which the procedure calls
187  *                                     other procedures.
188  *                BPatch_longJump      The points at which the procedure make
189  *                                     long jump calls.
190  *                BPatch_allLocations  All of the points described above.
191  */
192 BPatch_Vector<BPatch_point*> *BPatch_function::findPoint(
193         const BPatch_procedureLocation loc)
194 {
195     // function does not exist!
196     if (func == NULL) return NULL;
197
198     // function is generally uninstrumentable (with current technology)
199     if (func->funcEntry(proc) == NULL) return NULL;
200
201     BPatch_Vector<BPatch_point*> *result = new BPatch_Vector<BPatch_point *>;
202
203     if (loc == BPatch_entry || loc == BPatch_allLocations) {
204         BPatch_point *new_point = new BPatch_point(proc, this,
205                 const_cast<instPoint *>(func->funcEntry(proc)), BPatch_entry);
206         result->push_back(new_point);
207     }
208     switch (loc) {
209       case BPatch_entry: // already done
210           break;
211       case BPatch_allLocations:
212         {
213           const vector<instPoint *> &Rpoints = func->funcExits(proc);
214           const vector<instPoint *> &Cpoints = func->funcCalls(proc);
215           BPatch_point *new_point;
216           unsigned int c=0, r=0;
217           Address cAddr, rAddr;
218           while (c < Cpoints.size() || r < Rpoints.size()) {
219               if (c < Cpoints.size()) cAddr = Cpoints[c]->iPgetAddress();
220               else                    cAddr = (Address)(-1);
221               if (r < Rpoints.size()) rAddr = Rpoints[r]->iPgetAddress();
222               else                    rAddr = (Address)(-1);
223               if (cAddr <= rAddr) {
224                   new_point = new BPatch_point(proc, this, Cpoints[c], 
225                         BPatch_subroutine);
226                   c++;
227               } else {
228                   new_point = new BPatch_point(proc, this, Rpoints[r], 
229                         BPatch_exit);
230                   r++;
231               }
232               result->push_back(new_point);
233           }
234           break;
235         }
236       case BPatch_exit:
237         {
238           const vector<instPoint *> &points = func->funcExits(proc);
239           for (unsigned i = 0; i < points.size(); i++) {
240               BPatch_point *new_point = new BPatch_point(proc, this, points[i],
241                                                          BPatch_exit);
242               result->push_back(new_point);
243           }
244           break;
245         }
246       case BPatch_subroutine:
247         {
248           const vector<instPoint *> &points = func->funcCalls(proc);
249           for (unsigned i = 0; i < points.size(); i++) {
250               BPatch_point *new_point = new BPatch_point(proc, this, points[i],
251                                                          BPatch_subroutine);
252               result->push_back(new_point);
253           }
254           break;
255         }
256       case BPatch_longJump:
257         /* XXX Not yet implemented */
258       default:
259         assert( 0 );
260     }
261
262     return result;
263 }
264 /*
265  * BPatch_function::addParam()
266  *
267  * This function adds a function parameter to the BPatch_function parameter
268  * vector.
269  */
270 void BPatch_function::addParam(char * _name, BPatch_type *_type, int _linenum,
271                                int _frameOffset, int _sc)
272 {
273   BPatch_localVar * param = new BPatch_localVar(_name, _type, _linenum,
274                                                 _frameOffset, _sc);
275
276   // Add parameter to list of parameters
277   params.push_back(param);
278 }
279
280 /*
281  * BPatch_function::findLocalVar()
282  *
283  * This function searchs for a local variable in the BPatch_function's
284  * local variable collection.
285  */
286 BPatch_localVar * BPatch_function::findLocalVar(const char * name)
287 {
288
289   BPatch_localVar * var = localVariables->findLocalVar(name);
290   return (var);
291
292 }
293
294 /*
295  * BPatch_function::findLocalParam()
296  *
297  * This function searchs for a function parameter in the BPatch_function's
298  * parameter collection.
299  */
300 BPatch_localVar * BPatch_function::findLocalParam(const char * name)
301 {
302
303   BPatch_localVar * var = funcParameters->findLocalVar(name);
304   return (var);
305
306 }
307
308 /** method to retrieve addresses for a given line in the function
309   * if the line number is not valid, or if the line info is not available
310   * or if the module does not contain entry for the function then it returns
311   * false. If exact match is not set then the line which is the next
312   * greater or equal will be used.
313   */
314 bool BPatch_function::getLineToAddr(unsigned short lineNo,
315                    BPatch_Vector<unsigned long>& buffer,
316                    bool exactMatch)
317 {
318
319         //get the line info object and check whether it is available
320         LineInformation* lineInformation = mod->lineInformation;
321         if(!lineInformation){
322 #ifdef DEBUG_LINE
323                 cerr << "BPatch_function::getLineToAddr : ";
324                 cerr << "Line information is not available\n";
325 #endif
326                 return false;
327         }
328
329         //get the object which contains the function being asked
330         FileLineInformation* fLineInformation = 
331                         lineInformation->getFunctionLineInformation(func->prettyName());
332         if(!fLineInformation){
333 #ifdef DEBUG_LINE
334                 cerr << "BPatch_function::getLineToAddr : ";
335                 cerr << func->prettyName() << " is not found in its module\n";
336 #endif
337                 return false;
338         }
339
340         //retrieve the addresses
341         BPatch_Set<Address> addresses;
342         if(!fLineInformation->getAddrFromLine(func->prettyName(),addresses,
343                                               lineNo,false,exactMatch))
344                 return false;
345
346         //then insert the elements to the vector given
347         Address* elements = new Address[addresses.size()];
348         addresses.elements(elements);
349         for(int i=0;i<addresses.size();i++)
350                 buffer.push_back(elements[i]);
351         delete[] elements;
352         
353         return true;
354 }