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.28 2001/09/07 21:15:07 tikir Exp $
52 #include "instPoint.h"
55 #include "BPatch_image.h"
56 #include "BPatch_type.h"
57 #include "BPatch_collections.h"
58 #include "LineInformation.h"
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
66 class AddrToVarExprHash {
68 AddrToVarExprHash(): hash(addrHash) { }
69 dictionary_hash <Address, BPatch_variableExpr*> hash;
73 * BPatch_image::BPatch_image
75 * Construct a BPatch_image for the given process.
78 BPatch_image::BPatch_image(process *_proc) : proc(_proc)
81 AddrToVarExpr = new AddrToVarExprHash();
83 _srcType = BPatch_sourceProgram;
87 * BPatch_image::BPatch_image
89 * Construct a BPatch_image.
91 BPatch_image::BPatch_image() : proc(NULL), modlist(NULL)
93 AddrToVarExpr = new AddrToVarExprHash();
95 _srcType = BPatch_sourceProgram;
99 * Cleanup the image's memory usage when done.
102 BPatch_image::~BPatch_image()
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];
109 delete AddrToVarExpr;
113 * getSourceObj - Return the children (modules)
116 bool BPatch_image::getSourceObj(BPatch_Vector<BPatch_sourceObj *> &vect)
118 BPatch_Vector<BPatch_module *> *temp = getModules();
120 vect = * (BPatch_Vector<BPatch_sourceObj *> *) temp;
128 * getObjParent - Return the parent (this is the top level so its null)
131 BPatch_sourceObj *BPatch_image::getObjParent()
137 * BPatch_image::getProcedures
139 * Returns a list of all procedures in the image upon success, and NULL
142 BPatch_Vector<BPatch_function *> *BPatch_image::getProcedures()
144 BPatch_Vector<BPatch_function *> *proclist =
145 new BPatch_Vector<BPatch_function *>;
147 if (proclist == NULL) return NULL;
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();
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]);
165 BPatch_variableExpr *BPatch_image::createVarExprByName(BPatch_module *mod, const char *name)
170 type = mod->moduleTypes->globalVarsByName[name];
172 if (!proc->getSymbolInfo(name, syminfo)) {
173 printf("unable to find variable %s\n", name);
175 BPatch_variableExpr *var = AddrToVarExpr->hash[syminfo.addr()];
177 var = new BPatch_variableExpr((char *) name, proc,
178 (void *)syminfo.addr(), (const BPatch_type *) type);
179 AddrToVarExpr->hash[syminfo.addr()] = var;
186 * BPatch_image::getProcedures
188 * Returns a list of all procedures in the image upon success, and NULL
191 BPatch_Vector<BPatch_variableExpr *> *BPatch_image::getGlobalVariables()
193 BPatch_variableExpr *var;
194 BPatch_Vector<BPatch_variableExpr *> *varlist =
195 new BPatch_Vector<BPatch_variableExpr *>;
197 if (varlist == NULL) return NULL;
199 // XXX - should this stuff really be by image ??? jkh 3/19/99
200 BPatch_Vector<BPatch_module *> *mods = getModules();
202 for (int m = 0; m < mods->size(); m++) {
203 BPatch_module *module = (*mods)[m];
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);
219 bool BPatch_image::getVariables(BPatch_Vector<BPatch_variableExpr *> &vars)
221 BPatch_Vector<BPatch_variableExpr *> *temp = BPatch_image::getGlobalVariables();
227 vars = BPatch_Vector<BPatch_variableExpr *>();
234 * BPatch_image::getModules
236 * Returns a list of all procedures in the image upon success, and NULL
239 BPatch_Vector<BPatch_module *> *BPatch_image::getModules()
245 modlist = new BPatch_Vector<BPatch_module *>;
246 if (modlist == NULL) return NULL;
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();
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);
259 // BPatch_procedures are only built on demand, and we need to make sure
261 (void) getProcedures();
267 * BPatch_image::findProcedurePoint
269 * Returns a vector of the instrumentation points from a procedure that is
270 * identified by the parameters, or returns NULL upon failure.
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
279 * BPatch_longJump The points at which the procedure make
281 * BPatch_allLocations All of the points described above.
283 BPatch_Vector<BPatch_point*> *BPatch_image::findProcedurePoint(
284 const char *name, const BPatch_procedureLocation loc)
286 /* XXX Right now this assumes that there's only one function with
290 BPatch_function *func = findBPFunction(name);
291 if (func == NULL) return NULL;
293 return func->findPoint(loc);
298 * BPatch_image::createInstPointAtAddr
300 * Returns a pointer to a BPatch_point object representing an
301 * instrumentation point at the given address.
303 * Returns the pointer to the BPatch_point on success, or NULL upon
306 * address The address that the instrumenation point should refer to.
308 BPatch_point *BPatch_image::createInstPointAtAddr(void *address)
310 return createInstPointAtAddr(address,NULL);
313 BPatch_point *BPatch_image::createInstPointAtAddr(void *address,
314 BPatch_point** alternative)
318 /* First look in the list of non-standard instPoints. */
319 if (proc->instPointMap.defines((Address)address)) {
320 return proc->instPointMap[(Address)address];
323 /* Look in the regular instPoints of the enclosing function. */
324 function_base *func = proc->findFuncByAddr((Address)address);
326 pd_Function* pointFunction = (pd_Function*)func;
327 Address pointImageBase = 0;
328 if(!pointFunction || !pointFunction->file())
330 image* pointImage = pointFunction->file()->exec();
331 proc->getBaseAddress((const image*)pointImage,pointImageBase);
334 instPoint *entry = const_cast<instPoint *>(func->funcEntry(NULL));
336 if ((entry->iPgetAddress() == (Address)address) ||
338 ((entry->iPgetAddress() + pointImageBase) == (Address)address)))
340 return proc->findOrCreateBPPoint(NULL, entry, BPatch_entry);
343 const vector<instPoint*> &exits = func->funcExits(NULL);
344 for (i = 0; i < exits.size(); i++) {
346 if ((exits[i]->iPgetAddress() == (Address)address) ||
348 ((exits[i]->iPgetAddress() + pointImageBase) == (Address)address)))
350 return proc->findOrCreateBPPoint(NULL, exits[i], BPatch_exit);
354 const vector<instPoint*> &calls = func->funcCalls(NULL);
355 for (i = 0; i < calls.size(); i++) {
357 if ((calls[i]->iPgetAddress() == (Address)address) ||
359 ((calls[i]->iPgetAddress() + pointImageBase) == (Address)address)))
361 return proc->findOrCreateBPPoint(NULL, calls[i],
370 /* We don't have an instPoint for this address, so make one. */
371 return createInstructionInstPoint(proc, address, alternative);
376 * BPatch_image::findFunction
378 * Returns a NEW BPatch_function* representing the named function upon success,
379 * and NULL upon failure.
381 * name The name of function to look up.
383 BPatch_function *BPatch_image::findFunction(const char *name)
385 function_base *func = proc->findOneFunction(name);
388 string fullname = string("_") + string(name);
389 func = proc->findOneFunction(fullname);
393 string msg = string("Unable to find function: ") + string(name);
394 showErrorCallback(100, msg);
398 BPatch_function *bpfunc = proc->PDFuncToBPFuncMap[func];
400 bpfunc = new BPatch_function(proc, func, NULL);
407 * BPatch_image::findVariable
409 * Returns a BPatch_variableExpr* representing the given variable in the
410 * application image. If no such variable exists, returns NULL.
412 * name The name of the variable to look up.
414 * First look for the name with an `_' prepended to it, and if that is not
415 * found try the original name.
417 BPatch_variableExpr *BPatch_image::findVariable(const char *name, bool showError)
419 string full_name = string("_") + string(name);
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);
430 if( syminfo.type() == Symbol::PDST_FUNCTION)
433 BPatch_variableExpr *bpvar = AddrToVarExpr->hash[syminfo.addr()];
434 if (bpvar) return bpvar;
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);
446 type = BPatch::bpatch->type_Untyped;
449 BPatch_variableExpr *ret = new BPatch_variableExpr((char *) name,
450 proc, (void *)syminfo.addr(), (const BPatch_type *) type);
451 AddrToVarExpr->hash[syminfo.addr()] = ret;
457 // scp - a BPatch_point that defines the scope of the current search
458 // name - name of the variable to find.
460 BPatch_variableExpr *BPatch_image::findVariable(BPatch_point &scp,
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();
467 string msg = string("point passed to findVariable lacks a function\n address point type passed?");
468 showErrorCallback(100, msg);
472 BPatch_localVar *lv = func->findLocalVar(name);
475 // look for it in the parameter scope now
476 lv = func->findLocalParam(name);
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);
485 // finally check the global scope.
486 return findVariable(name);
490 * BPatch_image::findType
492 * Returns a BPatch_type* representing the named type. If no such type
493 * exists, returns NULL.
495 * name The name of type to look up.
497 BPatch_type *BPatch_image::findType(const char *name)
501 assert(BPatch::bpatch != NULL);
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;
511 // check the default base types
512 type = BPatch::bpatch->stdTypes->findType(name);
513 if(type) return type;
515 // check the API types of last resort
516 return BPatch::bpatch->APITypes->findType(name);
521 * BPatch_image::findBPFunnction
523 * Returns a BPatch_function* representing the named function or if no func
524 * exists, returns NULL.
526 * name The name of function to look up.
528 BPatch_function *BPatch_image::findBPFunction(const char *name)
530 BPatch_function *func;
531 BPatch_Vector<BPatch_function *> * funclist =
532 new BPatch_Vector<BPatch_function *>;
534 assert(BPatch::bpatch != NULL);
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);
543 if (func->getProc() != proc) {
544 printf("got func in the wrong proc\n");
546 funclist->push_back(func);
549 if( funclist->size()){
550 //printf("Function list has %d functions\n", funclist->size());
551 if( funclist->size() == 2)
552 return (*funclist)[1];
554 return (*funclist)[0];
556 // check the default base types of last resort
563 * BPatch_image::addModule
565 * Adds a new module to the BPatch_module vector
568 * bpmod is a pointer to the BPatch_module to add to the vector
570 void BPatch_image::addModuleIfExist(BPatch_module *bpmod){
573 modlist->push_back(bpmod);
578 * BPatch_image::ModuleListExist
580 * Checks to see if modlist has been created.
582 bool BPatch_image::ModuleListExist(){
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
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,
606 string fName(fileName);
608 //first get all modules
609 BPatch_Vector<BPatch_module*>* appModules = getModules();
611 LineInformation* lineInformation;
612 FileLineInformation* fLineInformation = NULL;
614 //in each module try to find the file
615 for(unsigned int i=0;i<appModules->size();i++){
616 lineInformation = (*appModules)[i]->lineInformation;
619 fLineInformation = lineInformation->getFileLineInformation(fName);
624 //if there is no entry for the file is being found then give warning and return
625 if(!fLineInformation){
627 cerr << "BPatch_image::getLineToAddr : ";
628 cerr << fileName << "/line information is not found/available in the image\n";
633 //get the addresses for the line number
634 BPatch_Set<Address> addresses;
635 if(!fLineInformation->getAddrFromLine(fName,addresses,lineNo,true,exactMatch))
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]);
648 #ifdef IBM_BPATCH_COMPAT
649 char *BPatch_image::programName(char *name, unsigned int len) {
650 return getProgramName(name, len);
653 char *BPatch_image::getProgramName(char *name, unsigned int len) {
654 strcpy(name, "<unknown>");
658 int BPatch_image::lpType()
663 BPatch_Vector<BPatch_function*> *BPatch_image::findFunction(const char *name, BPatch_Vector<BPatch_function*> &funcs)
665 BPatch_function *temp = findFunction(name);
667 funcs = BPatch_Vector<BPatch_function*>();
669 funcs.push_back(temp);