initial dyninstAPI commit for code coverage
[dyninst.git] / dyninstAPI / src / BPatch_image.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_image.C,v 1.28 2001/09/07 21:15:07 tikir Exp $
43
44 #define BPATCH_FILE
45
46 #include <stdio.h>
47 #include <assert.h>
48 #include <string.h>
49
50 #include "process.h"
51 #include "symtab.h"
52 #include "instPoint.h"
53
54 #include "BPatch.h"
55 #include "BPatch_image.h"
56 #include "BPatch_type.h"
57 #include "BPatch_collections.h"
58 #include "LineInformation.h"
59
60 //
61 // We made this a seperate class to allow us to only expose a pointer to
62 //    it in the public header files of the dyninst API.  This keeps 
63 //    dictionary_hash and other internal dyninst things hidden.  The
64 //    things we do decouple interface from implementation! - jkh 8/28/99
65 //
66 class AddrToVarExprHash {
67     public:
68         AddrToVarExprHash(): hash(addrHash) { }
69         dictionary_hash <Address, BPatch_variableExpr*> hash;
70 };
71
72 /*
73  * BPatch_image::BPatch_image
74  *
75  * Construct a BPatch_image for the given process.
76  */
77
78 BPatch_image::BPatch_image(process *_proc) : proc(_proc)
79 {
80     modlist = NULL;
81     AddrToVarExpr = new AddrToVarExprHash();
82
83     _srcType = BPatch_sourceProgram;
84 }
85
86 /*
87  * BPatch_image::BPatch_image
88  *
89  * Construct a BPatch_image.
90  */
91 BPatch_image::BPatch_image() : proc(NULL), modlist(NULL) 
92 {
93     AddrToVarExpr = new AddrToVarExprHash();
94
95     _srcType = BPatch_sourceProgram;
96 }
97
98 /* 
99  * Cleanup the image's memory usage when done.
100  *
101  */
102 BPatch_image::~BPatch_image()
103 {
104     // modules are shared by multuple programs, don't delete them
105     // for (unsigned int i = 0; i < modlist->size(); i++) {
106          // delete (*modlist)[i];
107     // }
108
109     delete AddrToVarExpr;
110 }
111
112 /* 
113  * getSourceObj - Return the children (modules)
114  *
115  */
116 bool BPatch_image::getSourceObj(BPatch_Vector<BPatch_sourceObj *> &vect)
117 {
118     BPatch_Vector<BPatch_module *> *temp =  getModules();
119     if (temp) {
120        vect = * (BPatch_Vector<BPatch_sourceObj *> *) temp;
121        return (true);
122     } else {
123         return (false);
124     }
125 }
126
127 /* 
128  * getObjParent - Return the parent (this is the top level so its null)
129  *
130  */
131 BPatch_sourceObj *BPatch_image::getObjParent()
132 {
133     return NULL;
134 }
135
136 /*
137  * BPatch_image::getProcedures
138  *
139  * Returns a list of all procedures in the image upon success, and NULL
140  * upon failure.
141  */
142 BPatch_Vector<BPatch_function *> *BPatch_image::getProcedures()
143 {
144     BPatch_Vector<BPatch_function *> *proclist =
145         new BPatch_Vector<BPatch_function *>;
146
147     if (proclist == NULL) return NULL;
148
149     // XXX Also, what should we do about getting rid of this?  Should
150     //     the BPatch_functions already be made and kept around as long
151     //     as the process is, so the user doesn't have to delete them?
152     BPatch_Vector<BPatch_module *> *mods = getModules();
153
154     for (unsigned int i = 0; i < (unsigned) mods->size(); i++) {
155         BPatch_Vector<BPatch_function *> *funcs = (*mods)[i]->getProcedures();
156         for (unsigned int j=0; j < (unsigned) funcs->size(); j++) {
157             proclist->push_back((*funcs)[j]);
158         }
159     }
160
161     return proclist;
162 }
163
164
165 BPatch_variableExpr *BPatch_image::createVarExprByName(BPatch_module *mod, const char *name)
166 {
167     Symbol syminfo;
168     BPatch_type *type;
169     
170     type = mod->moduleTypes->globalVarsByName[name];
171     assert(type);
172     if (!proc->getSymbolInfo(name, syminfo)) {
173         printf("unable to find variable %s\n", name);
174     }
175     BPatch_variableExpr *var = AddrToVarExpr->hash[syminfo.addr()];
176     if (!var) {
177         var = new BPatch_variableExpr((char *) name, proc, 
178             (void *)syminfo.addr(), (const BPatch_type *) type);
179         AddrToVarExpr->hash[syminfo.addr()] = var;
180     }
181     return var;
182 }
183
184
185 /*
186  * BPatch_image::getProcedures
187  *
188  * Returns a list of all procedures in the image upon success, and NULL
189  * upon failure.
190  */
191 BPatch_Vector<BPatch_variableExpr *> *BPatch_image::getGlobalVariables()
192 {
193     BPatch_variableExpr *var;
194     BPatch_Vector<BPatch_variableExpr *> *varlist =
195         new BPatch_Vector<BPatch_variableExpr *>;
196
197     if (varlist == NULL) return NULL;
198
199     // XXX - should this stuff really be by image ??? jkh 3/19/99
200     BPatch_Vector<BPatch_module *> *mods = getModules();
201     BPatch_type *type;
202     for (int m = 0; m < mods->size(); m++) {
203         BPatch_module *module = (*mods)[m];
204         char name[255];
205         module->getName(name, sizeof(name));
206         vector<string> keys = module->moduleTypes->globalVarsByName.keys();
207         int limit = keys.size();
208         for (int j = 0; j < limit; j++) {
209             string name = keys[j];
210             var = createVarExprByName(module, name.string_of());
211             varlist->push_back(var);
212         }
213     }
214
215
216     return varlist;
217 }
218
219 bool BPatch_image::getVariables(BPatch_Vector<BPatch_variableExpr *> &vars)
220 {
221     BPatch_Vector<BPatch_variableExpr *> *temp = BPatch_image::getGlobalVariables();
222
223     if (temp) {
224         vars = *temp;
225         return true;
226     } else {
227         vars = BPatch_Vector<BPatch_variableExpr *>();
228         return false;
229     }
230 }
231
232
233 /*
234  * BPatch_image::getModules
235  *
236  * Returns a list of all procedures in the image upon success, and NULL
237  * upon failure.
238  */
239 BPatch_Vector<BPatch_module *> *BPatch_image::getModules()
240 {
241   if (modlist) {
242     return modlist;
243   }
244   
245   modlist = new BPatch_Vector<BPatch_module *>;
246   if (modlist == NULL) return NULL;
247   
248   // XXX Also, what should we do about getting rid of this?  Should
249   //     the BPatch_modules already be made and kept around as long
250   //     as the process is, so the user doesn't have to delete them?
251   vector<module *> *mods = proc->getAllModules();
252   
253   for (unsigned int m = 0; m < mods->size(); m++) {
254     pdmodule *curr = (pdmodule *) (*mods)[m];
255     BPatch_module *bpmod = new BPatch_module(proc, curr, this);
256     modlist->push_back(bpmod);
257   }
258   
259   // BPatch_procedures are only built on demand, and we need to make sure
260   //    they get built.
261   (void) getProcedures();
262
263   return modlist;
264 }
265
266 /*
267  * BPatch_image::findProcedurePoint
268  *
269  * Returns a vector of the instrumentation points from a procedure that is
270  * identified by the parameters, or returns NULL upon failure.
271  *
272  * name         The name of the procedure in which to look up the points.
273  * loc          The points within the procedure to return.  The following
274  *              values are valid for this parameter:
275  *                BPatch_entry         The function's entry point.
276  *                BPatch_exit          The function's exit point(s).
277  *                BPatch_subroutine    The points at which the procedure calls
278  *                                     other procedures.
279  *                BPatch_longJump      The points at which the procedure make
280  *                                     long jump calls.
281  *                BPatch_allLocations  All of the points described above.
282  */
283 BPatch_Vector<BPatch_point*> *BPatch_image::findProcedurePoint(
284         const char *name, const BPatch_procedureLocation loc)
285 {
286     /* XXX Right now this assumes that there's only one function with
287      * the given name.
288      */
289
290     BPatch_function *func = findBPFunction(name);
291     if (func == NULL) return NULL;
292
293     return func->findPoint(loc);
294 }
295
296
297 /*
298  * BPatch_image::createInstPointAtAddr
299  *
300  * Returns a pointer to a BPatch_point object representing an
301  * instrumentation point at the given address.
302  *
303  * Returns the pointer to the BPatch_point on success, or NULL upon
304  * failure.
305  *
306  * address      The address that the instrumenation point should refer to.
307  */
308 BPatch_point *BPatch_image::createInstPointAtAddr(void *address)
309 {
310         return createInstPointAtAddr(address,NULL);
311 }
312
313 BPatch_point *BPatch_image::createInstPointAtAddr(void *address,
314                                                   BPatch_point** alternative)
315 {
316     unsigned i;
317
318     /* First look in the list of non-standard instPoints. */
319     if (proc->instPointMap.defines((Address)address)) {
320         return proc->instPointMap[(Address)address];
321     }
322
323     /* Look in the regular instPoints of the enclosing function. */
324     function_base *func = proc->findFuncByAddr((Address)address);
325
326     pd_Function* pointFunction = (pd_Function*)func;
327     Address pointImageBase = 0;
328     if(!pointFunction || !pointFunction->file())
329         return NULL;
330     image* pointImage = pointFunction->file()->exec();
331     proc->getBaseAddress((const image*)pointImage,pointImageBase);
332
333     if (func != NULL) {
334         instPoint *entry = const_cast<instPoint *>(func->funcEntry(NULL));
335         assert(entry);
336         if ((entry->iPgetAddress() == (Address)address) ||
337             (pointImageBase && 
338              ((entry->iPgetAddress() + pointImageBase) == (Address)address))) 
339         {
340             return proc->findOrCreateBPPoint(NULL, entry, BPatch_entry);
341         }
342
343         const vector<instPoint*> &exits = func->funcExits(NULL);
344         for (i = 0; i < exits.size(); i++) {
345             assert(exits[i]);
346             if ((exits[i]->iPgetAddress() == (Address)address) ||
347                 (pointImageBase && 
348                  ((exits[i]->iPgetAddress() + pointImageBase) == (Address)address))) 
349             {
350                 return proc->findOrCreateBPPoint(NULL, exits[i], BPatch_exit);
351             }
352         }
353
354         const vector<instPoint*> &calls = func->funcCalls(NULL);
355         for (i = 0; i < calls.size(); i++) {
356             assert(calls[i]);
357             if ((calls[i]->iPgetAddress() == (Address)address) ||
358                 (pointImageBase && 
359                  ((calls[i]->iPgetAddress() + pointImageBase) == (Address)address))) 
360             {
361                 return proc->findOrCreateBPPoint(NULL, calls[i],
362                                                  BPatch_subroutine);
363             }
364         }
365     }
366
367     if(alternative)
368         *alternative = NULL;
369
370     /* We don't have an instPoint for this address, so make one. */
371     return createInstructionInstPoint(proc, address, alternative);
372 }
373
374
375 /*
376  * BPatch_image::findFunction
377  *
378  * Returns a NEW BPatch_function* representing the named function upon success,
379  * and NULL upon failure.
380  *
381  * name         The name of function to look up.
382  */
383 BPatch_function *BPatch_image::findFunction(const char *name)
384 {
385     function_base *func = proc->findOneFunction(name);
386
387     if (func == NULL) {
388         string fullname = string("_") + string(name);
389         func = proc->findOneFunction(fullname);
390     }
391
392     if (func == NULL) {
393         string msg = string("Unable to find function: ") + string(name);
394         showErrorCallback(100, msg);
395         return NULL;
396     }
397
398     BPatch_function *bpfunc = proc->PDFuncToBPFuncMap[func];
399     if (!bpfunc) {
400         bpfunc = new BPatch_function(proc, func, NULL);
401     }
402     return bpfunc;
403 }
404
405
406 /*
407  * BPatch_image::findVariable
408  *
409  * Returns a BPatch_variableExpr* representing the given variable in the
410  * application image.  If no such variable exists, returns NULL.
411  *
412  * name         The name of the variable to look up.
413  *
414  * First look for the name with an `_' prepended to it, and if that is not
415  *   found try the original name.
416  */
417 BPatch_variableExpr *BPatch_image::findVariable(const char *name, bool showError)
418 {
419     string full_name = string("_") + string(name);
420
421     Symbol syminfo;
422     if (!proc->getSymbolInfo(full_name, syminfo)) {
423         string short_name(name);
424         if (!proc->getSymbolInfo(short_name, syminfo) && showError) {
425             string msg = string("Unable to find variable: ") + string(name);
426             showErrorCallback(100, msg);
427             return NULL;
428         }
429     }
430     if( syminfo.type() == Symbol::PDST_FUNCTION)
431       return NULL;
432     
433     BPatch_variableExpr *bpvar = AddrToVarExpr->hash[syminfo.addr()];
434     if (bpvar) return bpvar;
435
436     // XXX - should this stuff really be by image ??? jkh 3/19/99
437     BPatch_Vector<BPatch_module *> *mods = getModules();
438     BPatch_type *type = NULL;
439     for (int m = 0; m < mods->size(); m++) {
440         BPatch_module *module = (*mods)[m];
441         //printf("The moduleType address is : %x\n", &(module->moduleTypes));
442         type = module->moduleTypes->findVariableType(name);
443         if (type) break;
444     }
445     if (!type) {
446         type = BPatch::bpatch->type_Untyped;
447     }
448
449     BPatch_variableExpr *ret = new BPatch_variableExpr((char *) name, 
450         proc, (void *)syminfo.addr(), (const BPatch_type *) type);
451     AddrToVarExpr->hash[syminfo.addr()] = ret;
452     return ret;
453 }
454
455 //
456 // findVariable
457 //      scp     - a BPatch_point that defines the scope of the current search
458 //      name    - name of the variable to find.
459 //
460 BPatch_variableExpr *BPatch_image::findVariable(BPatch_point &scp,
461                                                 const char *name)
462 {
463     // Get the function to search for it's local variables.
464     // XXX - should really use more detailed scoping info here - jkh 6/30/99
465     BPatch_function *func = (BPatch_function *) scp.getFunction();
466     if (!func) {
467         string msg = string("point passed to findVariable lacks a function\n address point type passed?");
468         showErrorCallback(100, msg);
469         return NULL;
470     }
471
472     BPatch_localVar *lv = func->findLocalVar(name);
473
474     if (!lv) {
475         // look for it in the parameter scope now
476         lv = func->findLocalParam(name);
477     }
478     if (lv) {
479         // create a local expr with the correct frame offset or absolute
480         //   address if that is what is needed
481         return new BPatch_variableExpr(proc, (void *) lv->getFrameOffset(), 
482             lv->getType(), lv->getFrameRelative(), &scp);
483     }
484
485     // finally check the global scope.
486     return findVariable(name);
487 }
488
489 /*
490  * BPatch_image::findType
491  *
492  * Returns a BPatch_type* representing the named type.  If no such type
493  * exists, returns NULL.
494  *
495  * name         The name of type to look up.
496  */
497 BPatch_type *BPatch_image::findType(const char *name)
498 {
499     BPatch_type *type;
500
501     assert(BPatch::bpatch != NULL);
502
503     // XXX - should this stuff really be by image ??? jkh 3/19/99
504     BPatch_Vector<BPatch_module *> *mods = getModules();
505     for (int m = 0; m < mods->size(); m++) {
506         BPatch_module *module = (*mods)[m];
507         type = module->moduleTypes->findType(name);
508         if (type) return type;
509     }
510
511     // check the default base types
512     type = BPatch::bpatch->stdTypes->findType(name);
513     if(type) return type;
514
515     // check the API types of last resort
516     return BPatch::bpatch->APITypes->findType(name);
517
518 }
519
520 /*
521  * BPatch_image::findBPFunnction
522  *
523  * Returns a BPatch_function* representing the named function or if no func
524  * exists, returns NULL.
525  *
526  * name         The name of function to look up.
527  */
528 BPatch_function  *BPatch_image::findBPFunction(const char *name)
529 {
530     BPatch_function *func;
531     BPatch_Vector<BPatch_function *> * funclist =
532       new BPatch_Vector<BPatch_function *>;
533       
534     assert(BPatch::bpatch != NULL);
535
536     // XXX - should this stuff really be by image ??? jkh 3/19/99
537     BPatch_Vector<BPatch_module *> *mods = getModules();
538     //printf(" Number of Modules %d\n",mods->size());
539     for (int m = 0; m < mods->size(); m++) {
540         BPatch_module *module = (*mods)[m];
541         func = module->findFunction(name);
542         if (func) {
543             if (func->getProc() != proc) {
544                 printf("got func in the wrong proc\n");
545             }
546             funclist->push_back(func);
547         }
548     }
549     if( funclist->size()){
550       //printf("Function list has %d functions\n", funclist->size());
551       if( funclist->size() == 2)
552         return (*funclist)[1];
553       else 
554         return (*funclist)[0];
555     }
556     // check the default base types of last resort
557     else
558       return NULL;
559 }
560
561
562 /*
563  * BPatch_image::addModule
564  *
565  * Adds a new module to the BPatch_module vector
566  * if modlist exists. 
567  *
568  * bpmod is a pointer to the BPatch_module to add to the vector
569  */
570 void BPatch_image::addModuleIfExist(BPatch_module *bpmod){
571
572   if( modlist )
573     modlist->push_back(bpmod);
574   
575 }
576
577 /*
578  * BPatch_image::ModuleListExist
579  *
580  * Checks to see if modlist has been created.
581  */
582 bool BPatch_image::ModuleListExist(){
583
584   if ( modlist )
585     return true;
586   else
587     return false;
588 }
589
590 /** method that retrieves the addresses corresponding to a line number
591   * in a file.It returns true in success. If the file is not in the image
592   * or line number is not found it retuns false. In case of exact match is not
593   * asked then the next line number which is greater or equal to the given one
594   * is used
595   */
596 //method to get the addresses corresponding to a line number given
597 //in case of success it returns true and inserts the addresses in to
598 //the vector given. If the file name is not found or the line information
599 //is not valid or if the exact match is not found it retuns false.
600 //If exact match is not asked then the line number is taken to be the
601 //first one greater or equal to the given one.
602 bool BPatch_image::getLineToAddr(const char* fileName,unsigned short lineNo,
603                                  BPatch_Vector<unsigned long>& buffer,
604                                  bool exactMatch)
605 {
606         string fName(fileName);
607
608         //first get all modules
609         BPatch_Vector<BPatch_module*>* appModules =  getModules();
610
611         LineInformation* lineInformation;
612         FileLineInformation* fLineInformation = NULL;
613                 
614         //in each module try to find the file
615         for(unsigned int i=0;i<appModules->size();i++){
616                 lineInformation = (*appModules)[i]->lineInformation;
617                 if(!lineInformation)
618                         continue;
619                 fLineInformation = lineInformation->getFileLineInformation(fName);              
620                 if(fLineInformation)
621                         break;
622         }
623         
624         //if there is no entry for the file is being found then give warning and return
625         if(!fLineInformation){
626 #ifdef DEBUG_LINE
627                 cerr << "BPatch_image::getLineToAddr : ";
628                 cerr << fileName << "/line information  is not found/available in the image\n";
629 #endif
630                 return false;
631         }
632
633         //get the addresses for the line number
634         BPatch_Set<Address> addresses;
635         if(!fLineInformation->getAddrFromLine(fName,addresses,lineNo,true,exactMatch))
636                 return false;
637
638         //then insert the elements to the vector given
639         Address* elements = new Address[addresses.size()];
640         addresses.elements(elements);
641         for(int j=0;j<addresses.size();j++)
642                 buffer.push_back(elements[j]);
643         delete[] elements;
644
645         return true;
646 }
647
648 #ifdef IBM_BPATCH_COMPAT
649 char *BPatch_image::programName(char *name, unsigned int len) { 
650     return getProgramName(name, len); 
651 }
652
653 char *BPatch_image::getProgramName(char *name, unsigned int len) {
654     strcpy(name, "<unknown>");
655     return name;
656 }
657
658 int  BPatch_image::lpType() 
659 {
660     return 0;
661 };
662
663 BPatch_Vector<BPatch_function*> *BPatch_image::findFunction(const char *name, BPatch_Vector<BPatch_function*> &funcs)
664 {
665     BPatch_function *temp = findFunction(name);
666
667     funcs = BPatch_Vector<BPatch_function*>();
668     if (temp) {
669         funcs.push_back(temp);
670     }
671 }
672 #endif
673