2 * Copyright (c) 1996 Barton P. Miller
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.
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.
18 * (for other uses, please contact us at paradyn@cs.wisc.edu)
20 * All warranties, including without limitation, any warranty of
21 * merchantability or fitness for a particular purpose, are hereby
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.
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.
42 // $Id: BPatch_image.C,v 1.34 2002/03/19 22:57:20 jaw Exp $
52 #include "instPoint.h"
55 #include "BPatch_image.h"
56 #include "BPatch_type.h"
57 #include "BPatch_collections.h"
58 #include "LineInformation.h"
62 // We made this a seperate class to allow us to only expose a pointer to
63 // it in the public header files of the dyninst API. This keeps
64 // dictionary_hash and other internal dyninst things hidden. The
65 // things we do decouple interface from implementation! - jkh 8/28/99
67 class AddrToVarExprHash {
69 AddrToVarExprHash(): hash(addrHash) { }
70 dictionary_hash <Address, BPatch_variableExpr*> hash;
74 * BPatch_image::BPatch_image
76 * Construct a BPatch_image for the given process.
79 BPatch_image::BPatch_image(process *_proc) : proc(_proc)
83 AddrToVarExpr = new AddrToVarExprHash();
85 _srcType = BPatch_sourceProgram;
89 * BPatch_image::BPatch_image
91 * Construct a BPatch_image.
93 BPatch_image::BPatch_image() : proc(NULL), modlist(NULL)
95 AddrToVarExpr = new AddrToVarExprHash();
97 _srcType = BPatch_sourceProgram;
101 * Cleanup the image's memory usage when done.
104 BPatch_image::~BPatch_image()
106 // modules are shared by multuple programs, don't delete them
107 // for (unsigned int i = 0; i < modlist->size(); i++) {
108 // delete (*modlist)[i];
111 delete AddrToVarExpr;
115 * getSourceObj - Return the children (modules)
118 bool BPatch_image::getSourceObj(BPatch_Vector<BPatch_sourceObj *> &vect)
120 BPatch_Vector<BPatch_module *> *temp = getModules();
122 vect = * (BPatch_Vector<BPatch_sourceObj *> *) temp;
130 * getObjParent - Return the parent (this is the top level so its null)
133 BPatch_sourceObj *BPatch_image::getObjParent()
139 * BPatch_image::getProcedures
141 * Returns a list of all procedures in the image upon success, and NULL
144 BPatch_Vector<BPatch_function *> *BPatch_image::getProcedures()
146 BPatch_Vector<BPatch_function *> *proclist =
147 new BPatch_Vector<BPatch_function *>;
149 if (proclist == NULL) return NULL;
151 // XXX Also, what should we do about getting rid of this? Should
152 // the BPatch_functions already be made and kept around as long
153 // as the process is, so the user doesn't have to delete them?
154 BPatch_Vector<BPatch_module *> *mods = getModules();
156 for (unsigned int i = 0; i < (unsigned) mods->size(); i++) {
157 BPatch_Vector<BPatch_function *> *funcs = (*mods)[i]->getProcedures();
158 for (unsigned int j=0; j < (unsigned) funcs->size(); j++) {
159 proclist->push_back((*funcs)[j]);
167 BPatch_variableExpr *BPatch_image::createVarExprByName(BPatch_module *mod, const char *name)
172 type = mod->moduleTypes->globalVarsByName[name];
174 if (!proc->getSymbolInfo(name, syminfo)) {
175 printf("unable to find variable %s\n", name);
177 BPatch_variableExpr *var = AddrToVarExpr->hash[syminfo.addr()];
179 var = new BPatch_variableExpr( (char *)name, proc,
180 (void *)syminfo.addr(), (const BPatch_type *) type);
181 AddrToVarExpr->hash[syminfo.addr()] = var;
188 * BPatch_image::getProcedures
190 * Returns a list of all procedures in the image upon success, and NULL
193 BPatch_Vector<BPatch_variableExpr *> *BPatch_image::getGlobalVariables()
195 BPatch_variableExpr *var;
196 BPatch_Vector<BPatch_variableExpr *> *varlist =
197 new BPatch_Vector<BPatch_variableExpr *>;
199 if (varlist == NULL) return NULL;
201 // XXX - should this stuff really be by image ??? jkh 3/19/99
202 BPatch_Vector<BPatch_module *> *mods = getModules();
204 for (unsigned int m = 0; m < mods->size(); m++) {
205 BPatch_module *module = (*mods)[m];
207 module->getName(name, sizeof(name));
208 vector<string> keys = module->moduleTypes->globalVarsByName.keys();
209 int limit = keys.size();
210 for (int j = 0; j < limit; j++) {
211 string name = keys[j];
212 var = createVarExprByName(module, name.string_of());
213 varlist->push_back(var);
221 bool BPatch_image::getVariables(BPatch_Vector<BPatch_variableExpr *> &vars)
223 BPatch_Vector<BPatch_variableExpr *> *temp = BPatch_image::getGlobalVariables();
229 vars = BPatch_Vector<BPatch_variableExpr *>();
236 * BPatch_image::getModules
238 * Returns a list of all procedures in the image upon success, and NULL
241 BPatch_Vector<BPatch_module *> *BPatch_image::getModules()
247 modlist = new BPatch_Vector<BPatch_module *>;
248 if (modlist == NULL) return NULL;
250 // XXX Also, what should we do about getting rid of this? Should
251 // the BPatch_modules already be made and kept around as long
252 // as the process is, so the user doesn't have to delete them?
253 vector<module *> *mods = proc->getAllModules();
255 for (unsigned int m = 0; m < mods->size(); m++) {
256 pdmodule *curr = (pdmodule *) (*mods)[m];
257 BPatch_module *bpmod = new BPatch_module(proc, curr, this);
258 modlist->push_back(bpmod);
261 // BPatch_procedures are only built on demand, and we need to make sure
263 (void) getProcedures();
269 * BPatch_image::findProcedurePoint
271 * Returns a vector of the instrumentation points from a procedure that is
272 * identified by the parameters, or returns NULL upon failure.
274 * name The name of the procedure in which to look up the points.
275 * loc The points within the procedure to return. The following
276 * values are valid for this parameter:
277 * BPatch_entry The function's entry point.
278 * BPatch_exit The function's exit point(s).
279 * BPatch_subroutine The points at which the procedure calls
281 * BPatch_longJump The points at which the procedure make
283 * BPatch_allLocations All of the points described above.
285 BPatch_Vector<BPatch_point*> *BPatch_image::findProcedurePoint(
286 const char *name, const BPatch_procedureLocation loc)
288 /* XXX Right now this assumes that there's only one function with
292 BPatch_function *func = findBPFunction(name);
293 if (func == NULL) return NULL;
295 return func->findPoint(loc);
299 * BPatch_image::findProcedurePoint (VG 09/05/01)
301 * Returns a vector of the instrumentation points from a procedure that is
302 * identified by the parameters, or returns NULL upon failure.
304 * name The name of the procedure in which to look up the points.
305 * ops The points within the procedure to return. A set of op codes
308 BPatch_Vector<BPatch_point*> *BPatch_image::findProcedurePoint(
309 const char *name, const BPatch_Set<BPatch_opCode>& ops)
311 /* XXX Right now this assumes that there's only one function with
315 BPatch_function *func = findBPFunction(name);
316 if (func == NULL) return NULL;
318 return func->findPoint(ops);
322 * BPatch_image::createInstPointAtAddr
324 * Returns a pointer to a BPatch_point object representing an
325 * instrumentation point at the given address.
327 * Returns the pointer to the BPatch_point on success, or NULL upon
330 * address The address that the instrumenation point should refer to.
332 BPatch_point *BPatch_image::createInstPointAtAddr(void *address)
334 return createInstPointAtAddr(address,NULL);
337 BPatch_point *BPatch_image::createInstPointAtAddr(void *address,
338 BPatch_point** alternative)
342 /* First look in the list of non-standard instPoints. */
343 if (proc->instPointMap.defines((Address)address)) {
344 return proc->instPointMap[(Address)address];
347 /* Look in the regular instPoints of the enclosing function. */
348 function_base *func = proc->findFuncByAddr((Address)address);
350 // If it's in an uninstrumentable function, just return an error.
351 if (!((pd_Function*)func)->isInstrumentable())
354 pd_Function* pointFunction = (pd_Function*)func;
355 Address pointImageBase = 0;
356 if(!pointFunction || !pointFunction->file())
358 image* pointImage = pointFunction->file()->exec();
359 proc->getBaseAddress((const image*)pointImage,pointImageBase);
362 instPoint *entry = const_cast<instPoint *>(func->funcEntry(NULL));
364 if ((entry->iPgetAddress() == (Address)address) ||
366 ((entry->iPgetAddress() + pointImageBase) == (Address)address)))
368 return proc->findOrCreateBPPoint(NULL, entry, BPatch_entry);
371 const vector<instPoint*> &exits = func->funcExits(NULL);
372 for (i = 0; i < exits.size(); i++) {
374 if ((exits[i]->iPgetAddress() == (Address)address) ||
376 ((exits[i]->iPgetAddress() + pointImageBase) == (Address)address)))
378 return proc->findOrCreateBPPoint(NULL, exits[i], BPatch_exit);
382 const vector<instPoint*> &calls = func->funcCalls(NULL);
383 for (i = 0; i < calls.size(); i++) {
385 if ((calls[i]->iPgetAddress() == (Address)address) ||
387 ((calls[i]->iPgetAddress() + pointImageBase) == (Address)address)))
389 return proc->findOrCreateBPPoint(NULL, calls[i],
398 /* We don't have an instPoint for this address, so make one. */
399 return createInstructionInstPoint(proc, address, alternative);
404 * BPatch_image::findFunctionInImage
406 * Searches a single image (class image object) for all functions of
407 * the given name. Results are returned in the vector that is passed in.
408 * Note that the vector is not cleared first, so anything in the vector
409 * when it is passed in remains there.
411 * name The name of function to look up.
412 * img The image to search.
413 * funcs The vector in which to return the results.
415 * This function would make a lot more sense as a method of the image class,
416 * but it's here since it deals with BPatch_functions and not pd_Functions.
418 void BPatch_image::findFunctionInImage(
419 const char *name, image *img, BPatch_Vector<BPatch_function*>& funcs)
422 vector<pd_Function*> *pdfv;
424 if ((pdfv = img->findFuncVectorByPretty(name)) != NULL) {
425 assert(pdfv->size() > 0);
427 for (unsigned int i = 0; i < pdfv->size(); i++)
428 funcs.push_back(proc->findOrCreateBPFunc((*pdfv)[i]));
431 if ((pdf = img->findFuncByMangled(name)) != NULL)
432 funcs.push_back(proc->findOrCreateBPFunc(pdf));
435 // Note that we can only return one non instrumentable function right now.
436 if ((pdf = img->findNonInstruFunc(name)) != NULL)
437 funcs.push_back(proc->findOrCreateBPFunc(pdf));
439 // Note that we can only return one excluded function right now.
440 if ((pdf = img->findExcludedFunc(name)) != NULL)
441 funcs.push_back(proc->findOrCreateBPFunc(pdf));
446 * BPatch_image::findFunction
448 * Returns a BPatch_function* representing the named function upon success,
449 * and NULL upon failure.
451 * name The name of function to look up.
453 BPatch_function *BPatch_image::findFunction(const char *name, bool showError)
455 BPatch_Vector<BPatch_function*> funcs;
457 findFunction(name, funcs, false);
459 if (funcs.size() == 0) {
460 string fullname = string(name) + string("_");
461 findFunction(fullname.string_of(), funcs, false);
464 if (funcs.size() > 0) {
469 string msg = string("Unable to find function: ") + string(name);
470 BPatch_reportError(BPatchSerious, 100, msg.string_of());
478 * BPatch_image::findFunction
480 * Fills a vector with BPatch_function pointers representing all functions in
481 * the image with the given name. Returns a pointer to the vector that was
482 * passed in on success, and NULL on error.
484 * name The name of function to look up.
485 * funcs The vector in which to place the results.
487 BPatch_Vector<BPatch_function*> *BPatch_image::findFunction(
488 const char *name, BPatch_Vector<BPatch_function*> &funcs, bool showError)
491 #ifdef USE_STL_VECTOR
492 BPatch_Vector<BPatch_function*> *init_funcs = new BPatch_Vector<BPatch_function*>();
495 funcs = BPatch_Vector<BPatch_function*>();
498 findFunctionInImage(name, proc->symbols, funcs);
500 if (proc->dynamiclinking && proc->shared_objects) {
501 for(unsigned int j = 0; j < proc->shared_objects->size(); j++){
502 const image *obj_image = ((*proc->shared_objects)[j])->getImage();
504 findFunctionInImage(name, (image*)obj_image, funcs);
509 if (funcs.size() > 0) {
514 string msg = string("Unable to find function: ") + string(name);
515 BPatch_reportError(BPatchSerious, 100, msg.string_of());
523 * BPatch_image::findVariable
525 * Returns a BPatch_variableExpr* representing the given variable in the
526 * application image. If no such variable exists, returns NULL.
528 * name The name of the variable to look up.
530 * First look for the name with an `_' prepended to it, and if that is not
531 * found try the original name.
533 BPatch_variableExpr *BPatch_image::findVariable(const char *name, bool showError)
535 string full_name = string("_") + string(name);
538 if (!proc->getSymbolInfo(full_name, syminfo)) {
539 string short_name(name);
540 if (!proc->getSymbolInfo(short_name, syminfo) && showError) {
541 string msg = string("Unable to find variable: ") + string(name);
542 showErrorCallback(100, msg);
546 if( syminfo.type() == Symbol::PDST_FUNCTION)
549 BPatch_variableExpr *bpvar = AddrToVarExpr->hash[syminfo.addr()];
550 if (bpvar) return bpvar;
552 // XXX - should this stuff really be by image ??? jkh 3/19/99
553 BPatch_Vector<BPatch_module *> *mods = getModules();
554 BPatch_type *type = NULL;
555 for (unsigned int m = 0; m < mods->size(); m++) {
556 BPatch_module *module = (*mods)[m];
557 //printf("The moduleType address is : %x\n", &(module->moduleTypes));
558 type = module->moduleTypes->findVariableType(name);
562 type = BPatch::bpatch->type_Untyped;
565 char *nameCopy = strdup(name);
567 BPatch_variableExpr *ret = new BPatch_variableExpr((char *) nameCopy,
568 proc, (void *)syminfo.addr(), (const BPatch_type *) type);
569 AddrToVarExpr->hash[syminfo.addr()] = ret;
575 // scp - a BPatch_point that defines the scope of the current search
576 // name - name of the variable to find.
578 BPatch_variableExpr *BPatch_image::findVariable(BPatch_point &scp,
581 // Get the function to search for it's local variables.
582 // XXX - should really use more detailed scoping info here - jkh 6/30/99
583 BPatch_function *func = (BPatch_function *) scp.getFunction();
585 string msg = string("point passed to findVariable lacks a function\n address point type passed?");
586 showErrorCallback(100, msg);
590 BPatch_localVar *lv = func->findLocalVar(name);
593 // look for it in the parameter scope now
594 lv = func->findLocalParam(name);
597 // create a local expr with the correct frame offset or absolute
598 // address if that is what is needed
599 return new BPatch_variableExpr(proc, (void *) lv->getFrameOffset(),
600 lv->getType(), lv->getFrameRelative(), &scp);
603 // finally check the global scope.
604 return findVariable(name);
608 * BPatch_image::findType
610 * Returns a BPatch_type* representing the named type. If no such type
611 * exists, returns NULL.
613 * name The name of type to look up.
615 BPatch_type *BPatch_image::findType(const char *name)
619 assert(BPatch::bpatch != NULL);
621 // XXX - should this stuff really be by image ??? jkh 3/19/99
622 BPatch_Vector<BPatch_module *> *mods = getModules();
623 for (unsigned int m = 0; m < mods->size(); m++) {
624 BPatch_module *module = (*mods)[m];
625 type = module->moduleTypes->findType(name);
626 if (type) return type;
629 // check the default base types
630 type = BPatch::bpatch->stdTypes->findType(name);
631 if(type) return type;
633 // check the API types of last resort
634 return BPatch::bpatch->APITypes->findType(name);
639 * BPatch_image::findBPFunnction
641 * Returns a BPatch_function* representing the named function or if no func
642 * exists, returns NULL.
644 * name The name of function to look up.
646 BPatch_function *BPatch_image::findBPFunction(const char *name)
649 BPatch_function *func;
650 BPatch_Vector<BPatch_function *> * funclist =
651 new BPatch_Vector<BPatch_function *>;
653 assert(BPatch::bpatch != NULL);
655 // XXX - should this stuff really be by image ??? jkh 3/19/99
656 BPatch_Vector<BPatch_module *> *mods = getModules();
657 //printf(" Number of Modules %d\n",mods->size());
658 for (unsigned int m = 0; m < mods->size(); m++) {
659 BPatch_module *module = (*mods)[m];
660 func = module->findFunction(name);
662 if (func->getProc() != proc) {
663 printf("got func in the wrong proc\n");
665 funclist->push_back(func);
669 if (!funclist->size()) {
670 fullName = (char *) malloc(strlen(name) + 2);
671 sprintf(fullName, "%s_", name);
672 for (unsigned int m = 0; m < mods->size(); m++) {
673 BPatch_module *module = (*mods)[m];
674 func = module->findFunction(fullName);
676 if (func->getProc() != proc) {
677 printf("got func in the wrong proc\n");
679 funclist->push_back(func);
685 if( funclist->size()){
686 //printf("Function list has %d functions\n", funclist->size());
687 if( funclist->size() == 2)
688 return (*funclist)[1];
690 return (*funclist)[0];
692 // check the default base types of last resort
699 * BPatch_image::addModule
701 * Adds a new module to the BPatch_module vector
704 * bpmod is a pointer to the BPatch_module to add to the vector
706 void BPatch_image::addModuleIfExist(BPatch_module *bpmod){
709 modlist->push_back(bpmod);
714 * BPatch_image::ModuleListExist
716 * Checks to see if modlist has been created.
718 bool BPatch_image::ModuleListExist(){
726 /** method that retrieves the addresses corresponding to a line number
727 * in a file.It returns true in success. If the file is not in the image
728 * or line number is not found it retuns false. In case of exact match is not
729 * asked then the next line number which is greater or equal to the given one
732 //method to get the addresses corresponding to a line number given
733 //in case of success it returns true and inserts the addresses in to
734 //the vector given. If the file name is not found or the line information
735 //is not valid or if the exact match is not found it retuns false.
736 //If exact match is not asked then the line number is taken to be the
737 //first one greater or equal to the given one.
738 bool BPatch_image::getLineToAddr(const char* fileName,unsigned short lineNo,
739 BPatch_Vector<unsigned long>& buffer,
742 string fName(fileName);
744 //first get all modules
745 BPatch_Vector<BPatch_module*>* appModules = getModules();
747 LineInformation* lineInformation;
748 FileLineInformation* fLineInformation = NULL;
750 //in each module try to find the file
751 for(unsigned int i=0;i<appModules->size();i++){
752 lineInformation = (*appModules)[i]->lineInformation;
755 fLineInformation = lineInformation->getFileLineInformation(fName);
760 //if there is no entry for the file is being found then give warning and return
761 if(!fLineInformation){
765 //get the addresses for the line number
766 BPatch_Set<Address> addresses;
767 if(!fLineInformation->getAddrFromLine(fName,addresses,lineNo,true,exactMatch))
770 //then insert the elements to the vector given
771 Address* elements = new Address[addresses.size()];
772 addresses.elements(elements);
773 for(int j=0;j<addresses.size();j++)
774 buffer.push_back(elements[j]);
780 #ifdef IBM_BPATCH_COMPAT
781 char *BPatch_image::programName(char *name, unsigned int len) {
782 return getProgramName(name, len);
785 char *BPatch_image::getProgramName(char *name, unsigned int len) {
786 len < strlen("<unknown") ?
787 strncpy(name, "<unknown>", len) : strcpy(name, "<unknown>");
791 int BPatch_image::lpType()