This is a minor update related to type information system in dyninst.
[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.5 2000/03/21 21:45:06 altinel 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 "BPatch_flowGraph.h"
54 #include "LineInformation.h"
55
56 /* XXX Should be in a dyninst API include file (right now in perfStream.h) */
57 extern double cyclesPerSecond;
58
59
60 /**************************************************************************
61  * BPatch_function
62  *************************************************************************/
63 /*
64  * BPatch_function::BPatch_function
65  *
66  * Constructor that creates a BPatch_function.
67  *
68  */
69 BPatch_function::BPatch_function(process *_proc, function_base *_func,
70         BPatch_module *_mod) :
71         proc(_proc), mod(_mod), func(_func),cfg(NULL)
72 {
73
74   // there should be at most one BPatch_func for each function_base per process
75   assert(proc->thread && !proc->PDFuncToBPFuncMap[func]);
76
77   _srcType = BPatch_sourceFunction;
78
79   localVariables = new BPatch_localVarCollection;
80   funcParameters = new BPatch_localVarCollection;
81   retType = NULL;
82
83   proc->PDFuncToBPFuncMap[_func] = this;
84 };
85
86 /*
87  * BPatch_function::BPatch_function
88  *
89  * Constructor that creates the BPatch_function with return type.
90  *
91  */
92 BPatch_function::BPatch_function(process *_proc, function_base *_func,
93                                  BPatch_type * _retType, BPatch_module *_mod) :
94         proc(_proc), mod(_mod), func(_func),cfg(NULL)
95 {
96   _srcType = BPatch_sourceFunction;
97   localVariables = new BPatch_localVarCollection;
98   funcParameters = new BPatch_localVarCollection;
99   retType = _retType;
100 };
101
102
103 BPatch_function::~BPatch_function()
104 {
105     // if (ast != NULL)
106         // removeAst(ast);
107     if (localVariables) delete localVariables;
108     if (funcParameters) delete funcParameters;
109     if (cfg) delete cfg;
110 }
111
112 /* 
113  * BPatch_function::getSourceObj()
114  *
115  * Return the contained source objects (e.g. statements).
116  *    This is not currently supported.
117  *
118  */
119 BPatch_Vector<BPatch_sourceObj *> *BPatch_function::getSourceObj()
120 {
121     return NULL;
122 }
123
124 /*
125  * BPatch_function::getObjParent()
126  *
127  * Return the parent of the function (i.e. the module)
128  *
129  */
130 BPatch_sourceObj *BPatch_function::getObjParent()
131 {
132     return (BPatch_sourceObj *) mod;
133 }
134
135 /*
136  * BPatch_function::getName
137  *
138  * Copies the name of the function into a buffer, up to a given maximum
139  * length.  Returns a pointer to the beginning of the buffer that was
140  * passed in.
141  *
142  * s            The buffer into which the name will be copied.
143  * len          The size of the buffer.
144  */
145 char *BPatch_function::getName(char *s, int len)
146 {
147     assert(func);
148     string name = func->prettyName();
149     strncpy(s, name.string_of(), len);
150
151     return s;
152 }
153
154
155 /*
156  * BPatch_function::getBaseAddr
157  *
158  * Returns the starting address of the function.
159  */
160 void *BPatch_function::getBaseAddr()
161 {
162      return (void *)func->getEffectiveAddress(proc);
163 }
164
165 /*
166 * BPatch_function::getBaseAddrRelative
167 *
168 * Returns the starting address of the function in the module, relative
169 * to the module.
170 */
171 void *BPatch_function::getBaseAddrRelative()
172 {
173         return (void *)func->addr();
174 }
175
176
177 /*
178  * BPatch_function::getSize
179  *
180  * Returns the size of the function in bytes.
181  */
182 unsigned int BPatch_function::getSize()
183 {
184   return func->size();
185 }
186
187
188 /*
189  * BPatch_function::findPoint
190  *
191  * Returns a vector of the instrumentation points from a procedure that is
192  * identified by the parameters, or returns NULL upon failure.
193  * (Points are sorted by address in the vector returned.)
194  *
195  * loc          The points within the procedure to return.  The following
196  *              values are valid for this parameter:
197  *                BPatch_entry         The function's entry point.
198  *                BPatch_exit          The function's exit point(s).
199  *                BPatch_subroutine    The points at which the procedure calls
200  *                                     other procedures.
201  *                BPatch_longJump      The points at which the procedure make
202  *                                     long jump calls.
203  *                BPatch_allLocations  All of the points described above.
204  */
205 BPatch_Vector<BPatch_point*> *BPatch_function::findPoint(
206         const BPatch_procedureLocation loc)
207 {
208     // function does not exist!
209     if (func == NULL) return NULL;
210
211     // function is generally uninstrumentable (with current technology)
212     if (func->funcEntry(proc) == NULL) return NULL;
213
214     BPatch_Vector<BPatch_point*> *result = new BPatch_Vector<BPatch_point *>;
215
216     if (loc == BPatch_entry || loc == BPatch_allLocations) {
217         BPatch_point *new_point = new BPatch_point(proc, this,
218                 const_cast<instPoint *>(func->funcEntry(proc)), BPatch_entry);
219         result->push_back(new_point);
220     }
221     switch (loc) {
222       case BPatch_entry: // already done
223           break;
224       case BPatch_allLocations:
225         {
226           const vector<instPoint *> &Rpoints = func->funcExits(proc);
227           const vector<instPoint *> &Cpoints = func->funcCalls(proc);
228           BPatch_point *new_point;
229           unsigned int c=0, r=0;
230           Address cAddr, rAddr;
231           while (c < Cpoints.size() || r < Rpoints.size()) {
232               if (c < Cpoints.size()) cAddr = Cpoints[c]->iPgetAddress();
233               else                    cAddr = (Address)(-1);
234               if (r < Rpoints.size()) rAddr = Rpoints[r]->iPgetAddress();
235               else                    rAddr = (Address)(-1);
236               if (cAddr <= rAddr) {
237                   new_point = new BPatch_point(proc, this, Cpoints[c], 
238                         BPatch_subroutine);
239                   c++;
240               } else {
241                   new_point = new BPatch_point(proc, this, Rpoints[r], 
242                         BPatch_exit);
243                   r++;
244               }
245               result->push_back(new_point);
246           }
247           break;
248         }
249       case BPatch_exit:
250         {
251           const vector<instPoint *> &points = func->funcExits(proc);
252           for (unsigned i = 0; i < points.size(); i++) {
253               BPatch_point *new_point = new BPatch_point(proc, this, points[i],
254                                                          BPatch_exit);
255               result->push_back(new_point);
256           }
257           break;
258         }
259       case BPatch_subroutine:
260         {
261           const vector<instPoint *> &points = func->funcCalls(proc);
262           for (unsigned i = 0; i < points.size(); i++) {
263               BPatch_point *new_point = new BPatch_point(proc, this, points[i],
264                                                          BPatch_subroutine);
265               result->push_back(new_point);
266           }
267           break;
268         }
269       case BPatch_longJump:
270         /* XXX Not yet implemented */
271       default:
272         assert( 0 );
273     }
274
275     return result;
276 }
277 /*
278  * BPatch_function::addParam()
279  *
280  * This function adds a function parameter to the BPatch_function parameter
281  * vector.
282  */
283 void BPatch_function::addParam(char * _name, BPatch_type *_type, int _linenum,
284                                int _frameOffset, int _sc)
285 {
286   BPatch_localVar * param = new BPatch_localVar(_name, _type, _linenum,
287                                                 _frameOffset, _sc);
288
289   // Add parameter to list of parameters
290   params.push_back(param);
291 }
292
293 /*
294  * BPatch_function::findLocalVar()
295  *
296  * This function searchs for a local variable in the BPatch_function's
297  * local variable collection.
298  */
299 BPatch_localVar * BPatch_function::findLocalVar(const char * name)
300 {
301
302   BPatch_localVar * var = localVariables->findLocalVar(name);
303   return (var);
304
305 }
306
307 /*
308  * BPatch_function::findLocalParam()
309  *
310  * This function searchs for a function parameter in the BPatch_function's
311  * parameter collection.
312  */
313 BPatch_localVar * BPatch_function::findLocalParam(const char * name)
314 {
315
316   BPatch_localVar * var = funcParameters->findLocalVar(name);
317   return (var);
318
319 }
320
321 /** method to retrieve addresses for a given line in the function
322   * if the line number is not valid, or if the line info is not available
323   * or if the module does not contain entry for the function then it returns
324   * false. If exact match is not set then the line which is the next
325   * greater or equal will be used.
326   */
327 bool BPatch_function::getLineToAddr(unsigned short lineNo,
328                    BPatch_Vector<unsigned long>& buffer,
329                    bool exactMatch)
330 {
331
332         //get the line info object and check whether it is available
333         LineInformation* lineInformation = mod->lineInformation;
334         if(!lineInformation){
335 #ifdef DEBUG_LINE
336                 cerr << "BPatch_function::getLineToAddr : ";
337                 cerr << "Line information is not available\n";
338 #endif
339                 return false;
340         }
341
342         //get the object which contains the function being asked
343         FileLineInformation* fLineInformation = 
344                         lineInformation->getFunctionLineInformation(func->prettyName());
345         if(!fLineInformation){
346 #ifdef DEBUG_LINE
347                 cerr << "BPatch_function::getLineToAddr : ";
348                 cerr << func->prettyName() << " is not found in its module\n";
349 #endif
350                 return false;
351         }
352
353         //retrieve the addresses
354         BPatch_Set<Address> addresses;
355         if(!fLineInformation->getAddrFromLine(func->prettyName(),addresses,
356                                               lineNo,false,exactMatch))
357                 return false;
358
359         //then insert the elements to the vector given
360         Address* elements = new Address[addresses.size()];
361         addresses.elements(elements);
362         for(int i=0;i<addresses.size();i++)
363                 buffer.push_back(elements[i]);
364         delete[] elements;
365         
366         return true;
367 }
368
369
370 BPatch_flowGraph* BPatch_function::getCFG(){
371         if(cfg)
372                 return cfg;
373
374 #if defined(sparc_sun_solaris2_4)
375         cfg = new BPatch_flowGraph((BPatch_function*)this);
376 #else
377         cerr << "WARNING : BPatch_function::getCFG is not implemented";
378         cerr << " for this platform\n";
379 #endif
380
381         return cfg;
382 }
383
384 BPatch_Vector<BPatch_localVar *> *BPatch_function::getVars() {
385       return localVariables->getAllVars(); 
386 }
387