changes made for CFG for alpha architecture and
[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.10 2000/12/19 17:08:04 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 "BPatch_flowGraph.h"
54 #include "LineInformation.h"
55
56 /* XXX Should be in a dyninst API include file (right now in perfStream.h) */
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), cfg(NULL), 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), cfg(NULL), 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     if (cfg) delete cfg;
109 }
110
111 /* 
112  * BPatch_function::getSourceObj()
113  *
114  * Return the contained source objects (e.g. statements).
115  *    This is not currently supported.
116  *
117  */
118 BPatch_Vector<BPatch_sourceObj *> *BPatch_function::getSourceObj()
119 {
120     return NULL;
121 }
122
123 /*
124  * BPatch_function::getObjParent()
125  *
126  * Return the parent of the function (i.e. the module)
127  *
128  */
129 BPatch_sourceObj *BPatch_function::getObjParent()
130 {
131     return (BPatch_sourceObj *) mod;
132 }
133
134 /*
135  * BPatch_function::getName
136  *
137  * Copies the name of the function into a buffer, up to a given maximum
138  * length.  Returns a pointer to the beginning of the buffer that was
139  * passed in.
140  *
141  * s            The buffer into which the name will be copied.
142  * len          The size of the buffer.
143  */
144 char *BPatch_function::getName(char *s, int len)
145 {
146     assert(func);
147     string name = func->prettyName();
148     strncpy(s, name.string_of(), len);
149
150     return s;
151 }
152
153
154 /*
155  * BPatch_function::getBaseAddr
156  *
157  * Returns the starting address of the function.
158  */
159 void *BPatch_function::getBaseAddr()
160 {
161      return (void *)func->getEffectiveAddress(proc);
162 }
163
164 /*
165 * BPatch_function::getBaseAddrRelative
166 *
167 * Returns the starting address of the function in the module, relative
168 * to the module.
169 */
170 void *BPatch_function::getBaseAddrRelative()
171 {
172         return (void *)func->addr();
173 }
174
175
176 /*
177  * BPatch_function::getSize
178  *
179  * Returns the size of the function in bytes.
180  */
181 unsigned int BPatch_function::getSize()
182 {
183   return func->size();
184 }
185
186
187 /*
188  * BPatch_function::findPoint
189  *
190  * Returns a vector of the instrumentation points from a procedure that is
191  * identified by the parameters, or returns NULL upon failure.
192  * (Points are sorted by address in the vector returned.)
193  *
194  * loc          The points within the procedure to return.  The following
195  *              values are valid for this parameter:
196  *                BPatch_entry         The function's entry point.
197  *                BPatch_exit          The function's exit point(s).
198  *                BPatch_subroutine    The points at which the procedure calls
199  *                                     other procedures.
200  *                BPatch_longJump      The points at which the procedure make
201  *                                     long jump calls.
202  *                BPatch_allLocations  All of the points described above.
203  */
204 BPatch_Vector<BPatch_point*> *BPatch_function::findPoint(
205         const BPatch_procedureLocation loc)
206 {
207     // function does not exist!
208     if (func == NULL) return NULL;
209
210     // function is generally uninstrumentable (with current technology)
211     if (func->funcEntry(proc) == NULL) return NULL;
212
213     BPatch_Vector<BPatch_point*> *result = new BPatch_Vector<BPatch_point *>;
214
215     if (loc == BPatch_entry || loc == BPatch_allLocations) {
216         result->push_back(proc->findOrCreateBPPoint(
217             this,const_cast<instPoint *>(func->funcEntry(proc)),BPatch_entry));
218     }
219     switch (loc) {
220       case BPatch_entry: // already done
221           break;
222       case BPatch_allLocations:
223         {
224           const vector<instPoint *> &Rpoints = func->funcExits(proc);
225           const vector<instPoint *> &Cpoints = func->funcCalls(proc);
226           unsigned int c=0, r=0;
227           Address cAddr, rAddr;
228           while (c < Cpoints.size() || r < Rpoints.size()) {
229               if (c < Cpoints.size()) cAddr = Cpoints[c]->iPgetAddress();
230               else                    cAddr = (Address)(-1);
231               if (r < Rpoints.size()) rAddr = Rpoints[r]->iPgetAddress();
232               else                    rAddr = (Address)(-1);
233               if (cAddr <= rAddr) {
234                   result->push_back(proc->findOrCreateBPPoint(
235                       this, Cpoints[c], BPatch_subroutine));
236                   c++;
237               } else {
238                   result->push_back(proc->findOrCreateBPPoint(
239                       this, Rpoints[r], BPatch_exit));
240                   r++;
241               }
242           }
243           break;
244         }
245       case BPatch_exit:
246         {
247           const vector<instPoint *> &points = func->funcExits(proc);
248           for (unsigned i = 0; i < points.size(); i++) {
249               result->push_back(proc->findOrCreateBPPoint(
250                   this, points[i], BPatch_exit));
251           }
252           break;
253         }
254       case BPatch_subroutine:
255         {
256           const vector<instPoint *> &points = func->funcCalls(proc);
257           for (unsigned i = 0; i < points.size(); i++) {
258               result->push_back(proc->findOrCreateBPPoint(
259                   this, points[i], BPatch_subroutine));
260           }
261           break;
262         }
263       case BPatch_longJump:
264         /* XXX Not yet implemented */
265       default:
266         assert( 0 );
267     }
268
269     return result;
270 }
271 /*
272  * BPatch_function::addParam()
273  *
274  * This function adds a function parameter to the BPatch_function parameter
275  * vector.
276  */
277 void BPatch_function::addParam(char * _name, BPatch_type *_type, int _linenum,
278                                int _frameOffset, int _sc)
279 {
280   BPatch_localVar * param = new BPatch_localVar(_name, _type, _linenum,
281                                                 _frameOffset, _sc);
282
283   // Add parameter to list of parameters
284   params.push_back(param);
285 }
286
287 /*
288  * BPatch_function::findLocalVar()
289  *
290  * This function searchs for a local variable in the BPatch_function's
291  * local variable collection.
292  */
293 BPatch_localVar * BPatch_function::findLocalVar(const char * name)
294 {
295
296   BPatch_localVar * var = localVariables->findLocalVar(name);
297   return (var);
298
299 }
300
301 /*
302  * BPatch_function::findLocalParam()
303  *
304  * This function searchs for a function parameter in the BPatch_function's
305  * parameter collection.
306  */
307 BPatch_localVar * BPatch_function::findLocalParam(const char * name)
308 {
309
310   BPatch_localVar * var = funcParameters->findLocalVar(name);
311   return (var);
312
313 }
314
315 /** method to retrieve addresses for a given line in the function
316   * if the line number is not valid, or if the line info is not available
317   * or if the module does not contain entry for the function then it returns
318   * false. If exact match is not set then the line which is the next
319   * greater or equal will be used.
320   */
321 bool BPatch_function::getLineToAddr(unsigned short lineNo,
322                    BPatch_Vector<unsigned long>& buffer,
323                    bool exactMatch)
324 {
325
326         //get the line info object and check whether it is available
327         LineInformation* lineInformation = mod->lineInformation;
328         if(!lineInformation){
329 #ifdef DEBUG_LINE
330                 cerr << "BPatch_function::getLineToAddr : ";
331                 cerr << "Line information is not available\n";
332 #endif
333                 return false;
334         }
335
336         //get the object which contains the function being asked
337         FileLineInformation* fLineInformation = 
338                         lineInformation->getFunctionLineInformation(func->prettyName());
339         if(!fLineInformation){
340 #ifdef DEBUG_LINE
341                 cerr << "BPatch_function::getLineToAddr : ";
342                 cerr << func->prettyName() << " is not found in its module\n";
343 #endif
344                 return false;
345         }
346
347         //retrieve the addresses
348         BPatch_Set<Address> addresses;
349         if(!fLineInformation->getAddrFromLine(func->prettyName(),addresses,
350                                               lineNo,false,exactMatch))
351                 return false;
352
353         //then insert the elements to the vector given
354         Address* elements = new Address[addresses.size()];
355         addresses.elements(elements);
356         for(int i=0;i<addresses.size();i++)
357                 buffer.push_back(elements[i]);
358         delete[] elements;
359         
360         return true;
361 }
362
363 //
364 // Return the module name, first and last line numbers of the function.
365 //
366 bool BPatch_function::getLineAndFile(unsigned short &start,
367                                      unsigned short &end,
368                                      char *fileName, unsigned &length)
369 {
370     start = end = 0;
371
372     //get the line info object and check whether it is available
373     LineInformation* lineInformation = mod->lineInformation;
374
375     if (!lineInformation) {
376         logLine("BPatch_function::getLineToAddr : Line info is not available");
377         return false;
378     }
379
380     //get the object which contains the function being asked
381     FileLineInformation* fLineInformation = 
382         lineInformation->getFunctionLineInformation(func->prettyName());
383
384     if (!fLineInformation) {
385         logLine("BPatch_function::getLineToAddr: Line info is not available");
386         return false;
387     }
388
389     //retrieve the addresses
390     FunctionInfo *funcLineInfo;
391
392     funcLineInfo = fLineInformation->findFunctionInfo(func->prettyName());
393
394     if (!funcLineInfo) return false;
395
396     if (funcLineInfo->startLinePtr)
397         start = funcLineInfo->startLinePtr->lineNo;
398
399     if (funcLineInfo->endLinePtr)
400         end = funcLineInfo->endLinePtr->lineNo;
401
402     strncpy(fileName, fLineInformation->getFileName().string_of(), length);
403     if (strlen(fLineInformation->getFileName().string_of()) < length) {
404         length = strlen(fLineInformation->getFileName().string_of());
405     }
406
407     return true;
408 }
409
410
411
412 BPatch_flowGraph* BPatch_function::getCFG(){
413         if(cfg)
414                 return cfg;
415
416 #if defined(sparc_sun_solaris2_4) ||\
417     defined(mips_sgi_irix6_4) ||\
418     defined(rs6000_ibm_aix4_1) ||\
419     defined(alpha_dec_osf4_0)
420         cfg = new BPatch_flowGraph((BPatch_function*)this);
421 #else
422         cerr << "WARNING : BPatch_function::getCFG is not implemented";
423         cerr << " for this platform\n";
424 #endif
425
426         return cfg;
427 }
428
429
430 BPatch_Vector<BPatch_localVar *> *BPatch_function::getVars() {
431       return localVariables->getAllVars(); 
432 }