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: symtab.C,v 1.136 2002/03/19 22:57:22 jaw Exp $
48 // TODO - machine independent instruction functions
49 #include "dyninstAPI/src/symtab.h"
50 #include "dyninstAPI/src/arch.h"
51 #include "dyninstAPI/src/instPoint.h"
52 #include "dyninstAPI/src/Object.h"
54 #include "dyninstAPI/src/util.h"
55 #include "dyninstAPI/src/dyninstP.h"
56 #include "common/h/String.h"
57 #include "dyninstAPI/src/inst.h"
58 #include "common/h/Timer.h"
59 #include "dyninstAPI/src/showerror.h"
60 #include "common/h/debugOstream.h"
61 #include "common/h/pathName.h" // extract_pathname_tail()
62 #include "dyninstAPI/src/process.h" // process::getBaseAddress()
64 #ifndef BPATCH_LIBRARY
65 #include "paradynd/src/mdld.h"
66 #include "paradynd/src/main.h"
67 #include "paradynd/src/init.h"
68 #include "common/h/Dictionary.h"
70 extern vector<sym_data> syms_to_find;
73 // All debug_ostream vrbles are defined in process.C (for no particular reason)
74 extern debug_ostream sharedobj_cerr;
76 vector<image*> image::allImages;
78 #if defined(i386_unknown_nt4_0) || (defined mips_unknown_ce2_11) //ccw 20 july 2000 : 29 mar 2001
79 extern char *cplus_demangle(char *, int);
81 extern "C" char *cplus_demangle(char *, int);
84 // coming to dyninstAPI/src/symtab.hC
86 bool function_base::match(function_base *fb)
91 return ((symTabName_ == fb->symTabName_) &&
92 (prettyName_ == fb->prettyName_) &&
93 (line_ == fb->line_) &&
94 (addr_ == fb->addr_) &&
95 (size_ == fb->size_));
99 Debuggering info for function_base....
101 ostream & function_base::operator<<(ostream &s) const {
104 s << "Mangled name(s): " << symTabName_[0];
105 for(i = 1; i < symTabName_.size(); i++) {
106 s << ", " << symTabName_[i];
109 s << "\nPretty name(s): " << prettyName_[0];
110 for(i = 1; i < prettyName_.size(); i++) {
111 s << ", " << prettyName_[i];
113 s << "\nline_ = " << line_ << " addr_ = "<< addr_ << " size_ = ";
119 ostream &operator<<(ostream &os, function_base &f) {
120 return f.operator<<(os);
123 /* imported from platform specific library list. This is lists all
124 library functions we are interested in instrumenting. */
126 pdmodule *image::newModule(const string &name, const Address addr)
129 // modules can be defined several times in C++ due to templates and
130 // in-line member functions.
131 if ((ret = findModule(name, TRUE)))
134 string fullNm, fileNm;
135 char *out = P_strdup(name.string_of());
136 char *sl = P_strrchr(out, '/');
142 fullNm = string("/default/") + out;
147 ret = new pdmodule(lang_Unknown, addr, fullNm, fileNm, this);
149 #ifndef BPATCH_LIBRARY
150 // if module was excluded,stuff it into excludedMods (and dont
151 // index it in modeByFileName && modsByFullName.
152 if (module_is_excluded(ret)) {
155 #endif /* BPATCH_LIBRARY */
156 modsByFileName[ret->fileName()] = ret;
157 modsByFullName[ret->fullName()] = ret;
158 includedMods.push_back(ret);
159 #ifndef BPATCH_LIBRARY
161 #endif /* BPATCH_LIBRARY */
167 // TODO -- is this g++ specific
168 bool buildDemangledName(const string &mangled, string &use)
170 /* The C++ demangling function demangles MPI__Allgather (and other MPI__
171 * functions with start with A) into the MPI constructor. In order to
172 * prevent this a hack needed to be made, and this seemed the cleanest
175 if(!mangled.prefixed_by("MPI__")) {
176 char *tempName = P_strdup(mangled.string_of());
177 char *demangled = cplus_demangle(tempName, 0);
192 // err is true if the function can't be defined
194 // looks like this function attempts to do several things:
195 // 1) Check if can find the function (WHERE DOES IT LOOK????).
196 // 2) strip out something from function name which looks like
197 // possible scoping info (everything up to?? ":")??
198 // 3) try to demangle this (descoped??) name.
199 // 4) make new pd_Function under origional name and demangled name.
200 // 5) Insert into (data members) funcsByAdd && mods->funcs.
201 // n) insert into (data member) funcsByPretty (indexed under
203 bool image::newFunc(pdmodule *mod, const string &name,
205 const unsigned size) {
209 if ((func = findFuncByAddr(addr))){
210 //string temp = name;
211 //temp += string(" findFunction succeeded\n");
212 //logLine(P_strdup(temp.string_of()));
217 logLine("Error function without module\n");
218 showErrorCallback(34, "Error function without module");
222 string mangled_name = name;
223 const char *p = P_strchr(name.string_of(), ':');
225 unsigned nchars = p - name.string_of();
226 mangled_name = string(name.string_of(), nchars);
230 if (!buildDemangledName(mangled_name, demangled))
231 demangled = mangled_name;
235 func = new pd_Function(name, demangled, mod, addr, size, this, err);
237 //cout << name << " pretty: " << demangled << " addr :" << addr <<endl;
238 // if there was an error in determining the instrumentation info for
239 // function, add it to notInstruFunction.
242 addNotInstruFunc(func, mod);
246 addInstruFunction(func, mod, addr,
247 #ifdef BPATCH_LIBRARY
250 function_is_excluded(func, mod->fileName()));
255 void image::addInstruFunction(pd_Function *func, pdmodule *mod,
256 const Address addr, bool excluded) {
257 vector<pd_Function*> *funcsByPrettyEntry = NULL;
258 vector<pd_Function*> *funcsByMangledEntry = NULL;
260 // any functions whose instrumentation info could be determined
261 // get added to instrumentableFunctions, and mod->funcs.
262 instrumentableFunctions.push_back(func);
263 mod->funcs.push_back(func);
266 excludedFunctions[func->prettyName()] = func;
268 includedFunctions.push_back(func);
269 funcsByAddr[addr] = func;
270 if (!funcsByPretty.find(func->prettyName(), funcsByPrettyEntry)) {
271 funcsByPrettyEntry = new vector<pd_Function*>;
272 funcsByPretty[func->prettyName()] = funcsByPrettyEntry;
274 // several functions may have the same demangled name, and each one
275 // will appear in a different module
276 assert(funcsByPrettyEntry);
277 (*funcsByPrettyEntry).push_back(func);
279 if (!funcsByMangled.find(func->symTabName(), funcsByMangledEntry)) {
280 funcsByMangledEntry = new vector<pd_Function*>;
281 funcsByMangled[func->symTabName()] = funcsByMangledEntry;
283 // several functions may have the same demangled name, and each one
284 // will appear in a different module
285 assert(funcsByMangledEntry);
286 (*funcsByMangledEntry).push_back(func);
290 void image::addNotInstruFunc(pd_Function *func, pdmodule *mod) {
291 notInstruFunctions[func->prettyName()] = func;
292 mod->notInstruFuncs.push_back(func);
296 static timer loadTimer;
297 static FILE *timeOut=0;
298 #endif /* DEBUG_TIME */
300 // addOneFunction(): find name of enclosing module and define function symbol
302 // module information comes from one of three sources:
303 // #1 - debug format (stabs, DWARF, etc.)
304 // #2 - file format (ELF, COFF)
305 // #3 - file name (a.out, libXXX.so)
306 // (in order of decreasing reliability)
307 bool image::addOneFunction(vector<Symbol> &mods,
308 const Symbol &lookUp)
312 string modName = lookUp.module();
315 modName = name_ + "_module";
316 } else if (modName == "DEFAULT_MODULE") {
317 string modName_3 = modName;
318 findModByAddr(lookUp, mods, modName, modAddr, modName_3);
321 pdmodule *use = getOrCreateModule(modName, modAddr);
323 return newFunc(use, lookUp.name(), lookUp.addr(), lookUp.size());
327 * Add another name for the current function to the names vector in
328 * the function object. We also need to add the extra names to the
331 void image::addMultipleFunctionNames(vector<Symbol> &mods,
332 const Symbol &lookUp)
334 pd_Function *func = findFuncByAddr(lookUp.addr());
336 /* sanity check, make sure we have actually seen this address before */
339 /* build the mangeled and pretty names so that we can add those to the
342 string name = lookUp.name();
343 string mangled_name = name;
344 const char *p = P_strchr(name.string_of(), ':');
346 unsigned nchars = p - name.string_of();
347 mangled_name = string(name.string_of(), nchars);
351 if (!buildDemangledName(mangled_name, demangled))
352 demangled = mangled_name;
354 /* add the names to the vectors in the function object */
355 func->addSymTabName(mangled_name);
356 func->addPrettyName(demangled);
358 /* now we add the names and the function object to the hash tables */
359 vector<pd_Function*> *funcsByPrettyEntry = NULL;
360 vector<pd_Function*> *funcsByMangledEntry = NULL;
362 if(!funcsByPretty.find(demangled, funcsByPrettyEntry)) {
363 funcsByPrettyEntry = new vector<pd_Function*>;
364 funcsByPretty[demangled] = funcsByPrettyEntry;
367 assert(funcsByPrettyEntry);
368 (*funcsByPrettyEntry).push_back(func);
370 if (!funcsByMangled.find(mangled_name, funcsByMangledEntry)) {
371 funcsByMangledEntry = new vector<pd_Function*>;
372 funcsByMangled[mangled_name] = funcsByMangledEntry;
375 assert(funcsByMangledEntry);
376 (*funcsByMangledEntry).push_back(func);
380 * Add all the functions (*) in the list of symbols to our data
383 * We do a search for a "main" symbol (a couple of variants), and
384 * if found we flag this image as the executable (a.out).
387 bool image::addAllFunctions(vector<Symbol> &mods)
392 // is_a_out is a member variable
393 Symbol mainFuncSymbol; //Keeps track of info on "main" function
395 //Checking "main" function names in same order as in the inst-*.C files
396 if (linkedFile.get_symbol(symString="main", lookUp) ||
397 linkedFile.get_symbol(symString="_main", lookUp) ||
398 linkedFile.get_symbol(symString="WinMain", lookUp) ||
399 linkedFile.get_symbol(symString="_WinMain", lookUp)) {
400 mainFuncSymbol = lookUp;
406 // Checking for libdyninstRT (DYNINSTinit())
407 if (linkedFile.get_symbol(symString="DYNINSTinit", lookUp) ||
408 linkedFile.get_symbol(symString="_DYNINSTinit", lookUp))
409 is_libdyninstRT = true;
411 is_libdyninstRT = false;
413 // find the real functions -- those with the correct type in the symbol table
414 for(SymbolIter symIter(linkedFile); symIter;symIter++) {
415 const Symbol &lookUp = symIter.currval();
416 const char *np = lookUp.name().string_of();
417 if (linkedFile.isEEL() && np[0] == '.')
418 /* ignore these EEL symbols; we don't understand their values */
420 if (funcsByAddr.defines(lookUp.addr())) {
421 // We have already seen a function at this addr. add a second name
422 // for this function.
423 addMultipleFunctionNames(mods, lookUp);
427 (lookUp.addr() == mainFuncSymbol.addr()) &&
428 (lookUp.name() != mainFuncSymbol.name()))
429 // Wait for main to appear. Couldn't we just add main to start with?
431 if (lookUp.type() == Symbol::PDST_FUNCTION) {
432 if (!isValidAddress(lookUp.addr())) {
435 sprintf(tempBuffer,"0x%lx",lookUp.addr());
436 msg = string("Function ") + lookUp.name() + string(" has bad address ")
437 + string(tempBuffer);
438 statusLine(msg.string_of());
439 showErrorCallback(29, msg);
442 addOneFunction(mods, lookUp);
446 // now find the pseudo functions -- this gets ugly
447 // kludge has been set if the symbol could be a function
448 // WHERE DO WE USE THESE KLUDGES? WHAT PLATFORM???
449 for(SymbolIter symIter2(linkedFile);symIter2;symIter2++) {
450 lookUp = symIter2.currval();
451 if (funcsByAddr.defines(lookUp.addr()))
452 // Already defined a symbol at this addr
454 if ((lookUp.type() == Symbol::PDST_OBJECT) && lookUp.kludge()) {
455 //logLine(P_strdup(symString.string_of()));
456 // Figure out where this happens
457 cerr << "Found <KLUDGE> function " << lookUp.name().string_of() << endl;
458 addOneFunction(mods, lookUp);
464 bool image::addAllVariables()
466 /* Eventually we'll have to do this on all platforms (because we'll retrieve
467 * the type information here).
469 #if defined(i386_unknown_nt4_0) || (defined mips_unknown_ce2_11) //ccw 20 july 2000 : 29 mar 2001
473 for(SymbolIter symIter(linkedFile); symIter; symIter++) {
474 const string &mangledName = symIter.currkey();
475 const Symbol &symInfo = symIter.currval();
477 if (symInfo.type() == Symbol::PDST_OBJECT) {
478 char *name = cplus_demangle((char *)mangledName.string_of(), 0);
479 const char *unmangledName;
480 if (name) unmangledName = name;
481 else unmangledName = mangledName.string_of();
482 if (varsByPretty.defines(unmangledName)) {
483 (*(varsByPretty[unmangledName])).push_back(string(mangledName));
485 vector<string> *varEntry = new vector<string>;
486 (*varEntry).push_back(string(mangledName));
487 varsByPretty[unmangledName] = varEntry;
489 if (name) free(name);
497 * will search for symbol NAME or _NAME
498 * returns false on failure
500 bool image::findInternalSymbol(const string &name,
502 internalSym &ret_sym)
506 if(linkedFile.get_symbol(name,lookUp)){
507 ret_sym = internalSym(lookUp.addr(),name);
512 new_sym = string("_") + name;
513 if(linkedFile.get_symbol(new_sym,lookUp)){
514 ret_sym = internalSym(lookUp.addr(),name);
520 msg = string("Unable to find symbol: ") + name;
521 statusLine(msg.string_of());
522 showErrorCallback(28, msg);
527 bool image::findInternalByPrefix(const string &prefix,
528 vector<Symbol> &found) const
532 Go through all defined symbols and return those which
533 match the prefix given
535 for(SymbolIter symIter(linkedFile); symIter;symIter++) {
536 const Symbol &lookUp = symIter.currval();
537 if (!strncmp(prefix.string_of(), lookUp.name().string_of(),
538 strlen(prefix.string_of())))
540 found.push_back(lookUp);
547 pdmodule *image::findModule(const string &name, bool find_if_excluded)
551 //cerr << "image::findModule " << name << " , " << find_if_excluded
552 // << " called" << endl;
554 if (modsByFileName.defines(name)) {
555 //cerr << " (image::findModule) found module in modsByFileName" << endl;
556 return (modsByFileName[name]);
558 else if (modsByFullName.defines(name)) {
559 //cerr << " (image::findModule) found module in modsByFullName" << endl;
560 return (modsByFullName[name]);
563 // if also looking for excluded functions, check through
564 // excludedFunction list to see if any match function by FullName
566 if (find_if_excluded) {
567 for(i=0;i<excludedMods.size();i++) {
568 if ((excludedMods[i]->fileName() == name) ||
569 (excludedMods[i]->fullName() == name)) {
570 //cerr << " (image::findModule) found module in excludedMods" << endl;
571 return excludedMods[i];
576 //cerr << " (image::findModule) did not find module, returning NULL" << endl;
581 * return 0 if symbol <symname> exists in image, non-zero if it does not
583 bool image::symbolExists(const string &symname)
585 pd_Function *dummy = findFuncByName(symname);
586 return (dummy != NULL);
589 #ifndef BPATCH_LIBRARY
590 void image::postProcess(const string pifname)
593 string fname, errorstr;
595 char tmp1[5000], abstraction[500];
600 /* What file to open? */
601 if (!(pifname == (char*)NULL)) {
604 fname = desc_->file() + ".pif";
608 Fil = P_fopen(fname.string_of(), "r");
611 errorstr = string("Tried to open PIF file ") + fname;
612 errorstr += string(", but could not (continuing)\n");
613 logLine(P_strdup(errorstr.string_of()));
614 showErrorCallback(35, errorstr);
618 /* Process the file */
620 fscanf(Fil, "%s", key);
623 /* Ignore mapping information for right now */
624 fgets(tmp1, 5000, Fil);
627 #ifndef BPATCH_LIBRARY
628 /* Create a new resource */
629 fscanf(Fil, "%s {", abstraction);
630 parent = rootResource;
632 fscanf(Fil, "%s", tmp1);
633 if (tmp1[0] != '}') {
634 parent = resource::newResource(parent, NULL,
636 tmp1, timeStamp::ts1970(),
637 nullString, // uniqifier
643 } while (parent != NULL);
647 errorstr = string("Ignoring bad line key (") + fname;
648 errorstr += string(") in file %s\n");
649 logLine(P_strdup(errorstr.string_of()));
650 fgets(tmp1, 5000, Fil);
658 void image::defineModules() {
661 string pds; pdmodule *mod;
662 dictionary_hash_iter<string, pdmodule*> mi(modsByFileName);
664 while (mi.next(pds, mod)){
668 for(i=0;i<excludedMods.size();i++) {
669 mod = excludedMods[i];
675 ostrstream osb(buffer, 100, ios::out);
676 osb << "IMAGE_" << name() << "__" << getpid() << ends;
677 ofstream of(buffer, ios::app);
679 of << "INCLUDED FUNCTIONS\n";
680 for (unsigned ni=0; ni<includedFunctions.size(); ni++) {
681 of << includedFunctions[ni]->prettyName() << "\t\t"
682 << includedFunctions[ni]->addr() << "\t\t" << endl;
688 #ifndef BPATCH_LIBRARY
689 void image::FillInCallGraphStatic(process *proc)
694 dictionary_hash_iter<string, pdmodule*> mi(modsByFileName);
697 // define call graph relations for all non-excluded modules.
698 while (mi.next(pds, mod)){
699 buffer = "building call graph module: " +
701 statusLine(buffer.string_of());
702 mod->FillInCallGraphStatic(proc);
704 // also define call graph relations for all excluded modules.
705 // Call graph gets information about both included and excluded
706 // modules and functions, and allows the DM and PC to decide whether
707 // to look at a given function based on whether the function is
708 // included or excluded....
709 for(i=0;i<excludedMods.size();i++) {
710 mod = excludedMods[i];
711 buffer = "building call graph module: " +
713 statusLine(buffer.string_of());
714 mod->FillInCallGraphStatic(proc);
719 // Comments on what this does would be nice....
720 // Appears to run over a pdmodule, after all code in it has been processed
721 // and parsed into functions, and define a resource for the module + a
722 // resource for every function found in the module (apparently includes
723 // excluded functions, but not uninstrumentable ones)....
724 // Can't directly register call graph relationships here as resources
725 // are being defined, because need all resources defined to
729 void pdmodule::define() {
730 #ifndef BPATCH_LIBRARY
731 resource *moduleResource = NULL;
735 ostrstream osb(buffer, 100, ios::out);
736 osb << "MODS_" << exec->name() << "__" << getpid() << ends;
737 ofstream of(buffer, ios::app);
740 unsigned f_size = funcs.size();
742 for (unsigned f=0; f<f_size; f++) {
743 #ifndef BPATCH_LIBRARY
744 pd_Function *pdf = funcs[f];
746 of << fileName << ": " << pdf->prettyName() << " "
747 << pdf->addr() << endl;
749 // ignore line numbers for now
751 //if (!(pdf->isLibTag())) {
753 // see if we have created module yet.
754 if (!moduleResource) {
755 moduleResource = resource::newResource(moduleRoot, this,
756 nullString, // abstraction
758 timeStamp::ts1970(), // creation time
759 string(), // unique-ifier
764 pdf->SetFuncResource(resource::newResource(moduleResource, pdf,
765 nullString, // abstraction
768 nullString, // uniquifier
776 #ifndef BPATCH_LIBRARY
777 resource::send_now();
781 // Why is this in symtab.C?
782 #ifndef BPATCH_LIBRARY
783 // send message to data manager to specify the entry function for the
784 // call graph corresponding to a given image. r should hold the
785 // FULL resourcename of the entry function (e.g. "/Code/module.c/main")
786 void CallGraphSetEntryFuncCallback(string exe_name, string r)
788 tp->CallGraphSetEntryFuncCallback(exe_name, r);
791 void CallGraphAddProgramCallback(string name){
792 tp->CallGraphAddProgramCallback(name);
795 //send message to the data manager, notifying it that all of the statically
796 //determinable functions have been registered with the call graph. The
797 //data manager will then be able to create the call graph.
798 void CallGraphFillDone(string exe_name)
800 tp->CallGraphFillDone(exe_name);
803 //send message to the data manager in order to register a function
805 void AddCallGraphNodeCallback(string exe_name, string r)
807 tp->AddCallGraphNodeCallback(exe_name, r);
810 //send a message to the data manager in order register a the function
811 //calls made by a function (whose name is stored in r).
812 void AddCallGraphStaticChildrenCallback(string exe_name, string r,
813 const vector<string> children)
815 tp->AddCallGraphStaticChildrenCallback(exe_name, r, children);
818 // Called across all modules (in a given image) to define the call
819 // graph relationship between functions.
820 // Must be called AFTER all functions in all modules (in image) are
821 // registered as resource (e.g. w/ pdmodule::define())....
822 void pdmodule::FillInCallGraphStatic(process *proc) {
823 pd_Function *pdf, *callee;
824 vector <pd_Function *>callees;
825 resource *r , *callee_as_resource;
826 string callee_full_name;
827 vector <string>callees_as_strings;
828 vector <instPoint*> callPoints;
829 unsigned f, g,i, f_size = funcs.size();
831 string resource_full_name;
833 // for each INSTRUMENTABLE function in the module (including excluded
834 // functions, but NOT uninstrumentable ones)....
836 for (f=0;f<f_size;f++) {
839 callees_as_strings.resize(0);
841 // Translate from function name to resource *.
842 // Note that this probably is NOT the correct translation, as
843 // function names are not necessarily unique, but the paradyn
844 // code assumes that they are in several places (e.g.
845 // resource::findResource)....
846 resource_full_name = pdf->ResourceFullName();
847 r = resource::findResource(resource_full_name);
848 // functions registered under pretty name....
851 // get list of statically determined call destinations from pdf,
852 // using the process info to help fill in calls througb PLT
854 pdf->getStaticCallees(proc, callees);
856 // and convert them into a list of resources....
857 for (g=0;g<callees.size();g++) {
861 //if the funcResource is not set, then the function must be
862 //uninstrumentable, so we don't want to notify the front end
864 if(callee->FuncResourceSet()){
865 callee_full_name = callee->ResourceFullName();
867 // if callee->funcResource has been set, then it should have
868 // been registered as a resource....
869 callee_as_resource = resource::findResource(callee_full_name);
870 assert(callee_as_resource);
871 callees_as_strings += callee_full_name;
876 // register that callee_resources holds list of resource*s
877 // describing children of resource r....
878 string exe_name = proc->getImage()->file();
879 AddCallGraphNodeCallback(exe_name, resource_full_name);
880 AddCallGraphStaticChildrenCallback(exe_name, resource_full_name,
883 //Locate the dynamic call sites within the function, and notify
884 //the front end as to their existence
885 callPoints = pdf->funcCalls(proc);
886 for(i = 0; i < callPoints.size(); i++){
887 if(proc->isDynamicCallSite(callPoints[i])){
888 tp->CallGraphAddDynamicCallSiteCallback(exe_name, resource_full_name);
894 #endif // ndef BPATCH_LIBRARY
896 #ifndef BPATCH_LIBRARY
897 // as per getAllFunctions, but filters out those excluded with
898 // e.g. mdl "exclude" command....
899 // to clarify a function should NOT be returned from here if its
900 // module is excluded (with exclude "/Code/module") or if it
901 // is excluded (with exclude "/Code/module/function").
902 const vector<pd_Function*> &image::getIncludedFunctions() {
904 includedFunctions.resize(0);
905 vector<function_base *> *temp;
906 vector<pd_Function *> *temp2;
908 //cerr << "image::getIncludedFunctions called, name = " << name () << endl;
909 //cerr << " includedMods = " << endl;
910 //print_module_vector_by_short_name(string(" "), &includedMods);
911 for (i=0;i<includedMods.size();i++) {
912 temp = includedMods[i]->getIncludedFunctions();
913 temp2 = (vector<pd_Function *> *) temp;
914 includedFunctions += *temp2;
917 //cerr << " (image::getIncludedFunctions) returning : " << endl;
918 //print_func_vector_by_pretty_name(string(" "),
919 // (vector<function_base*>*)&includedFunctions);
921 // what about shared objects????
922 return includedFunctions;
927 // get all functions in module which are not "excluded" (e.g.
928 // with mdl "exclude" command.
929 // Assed to provide support for mdl "exclude" on functions in
930 // statically linked objects.
932 vector<function_base *> *pdmodule::getIncludedFunctions() {
933 // laxy construction of some_funcs, as per sharedobject class....
934 // cerr << "pdmodule " << fileName() << " :: getIncludedFunctions called "
936 if (some_funcs_inited == TRUE) {
937 //cerr << " about to return : " << endl;
938 //print_func_vector_by_pretty_name(string(" "), (vector<function_base *>*)&some_funcs);
939 return (vector<function_base *>*)&some_funcs;
941 #ifdef BPATCH_LIBRARY //BPatch Library doesn't know about excluded funcs
944 some_funcs.resize(0);
946 if (filter_excluded_functions(funcs, some_funcs, fileName()) == FALSE) {
947 //cerr << " about to return NULL";
951 some_funcs_inited = TRUE;
953 //cerr << " about to return : " << endl;
954 //print_func_vector_by_pretty_name(string(" "),(vector<function_base *>*) &some_funcs);
955 return (vector<function_base *>*)&some_funcs;
959 const vector<pd_Function*> &image::getAllFunctions() {
960 //cerr << "pdmodule::getAllFunctions() called, about to return instrumentableFunctions = " << endl;
961 //print_func_vector_by_pretty_name(string(" "),
962 // (vector<function_base*>*)&instrumentableFunctions);
963 return instrumentableFunctions;
966 const vector <pdmodule*> &image::getAllModules() {
967 // reinit all modules to empty vector....
970 // and add includedModules && excludedModules to it....
971 VECTOR_APPEND(allMods, includedMods);
972 VECTOR_APPEND(allMods, excludedMods);
974 //cerr << "image::getAllModules called" << endl;
975 //cerr << " about to return sum of includedMods and excludedMods" << endl;
976 //cerr << " includedMods : " << endl;
977 //print_module_vector_by_short_name(string(" "), &includedMods);
978 //cerr << " excludedMods : " << endl;
979 //print_module_vector_by_short_name(string(" "), &excludedMods);
985 #ifndef BPATCH_LIBRARY
986 const vector <pdmodule*> &image::getIncludedModules() {
987 //cerr << "image::getIncludedModules called" << endl;
988 //cerr << " about to return includedMods = " << endl;
989 //print_module_vector_by_short_name(string(" "), &includedMods);
995 void print_module_vector_by_short_name(string prefix ,
996 vector<pdmodule*> *mods) {
999 for(i=0;i<mods->size();i++) {
1001 cerr << prefix << mod->fileName() << endl;
1005 void print_func_vector_by_pretty_name(string prefix,
1006 vector<function_base *>*funcs) {
1008 function_base *func;
1009 for(i=0;i<funcs->size();i++) {
1010 func = ((*funcs)[i]);
1011 cerr << prefix << func->prettyName() << endl;
1015 // rip module name out of constraint....
1016 // Assumes that constraint is of form module/function, or
1018 string getModuleName(string constraint) {
1021 const char *data = constraint.string_of();
1022 const char *first_slash = P_strchr(data, RH_SEPERATOR);
1024 // no "/", assume string holds module name....
1025 if (first_slash == NULL) {
1028 // has "/", assume everything up to "/" is module name....
1029 return string(data, first_slash - data);
1032 // rip function name out of constraint....
1033 // Assumes that constraint is of form module/function, or
1035 string getFunctionName(string constraint) {
1038 const char *data = constraint.string_of();
1039 const char *first_slash = P_strchr(data, RH_SEPERATOR);
1041 // no "/", assume constraint is module only....
1042 if (first_slash == NULL) {
1045 // has "/", assume everything after "/" is function....
1046 return string(first_slash+1);
1050 #ifndef BPATCH_LIBRARY
1052 // mcheyney, Oct. 6, 1997
1053 static dictionary_hash<string, string> func_constraint_hash(string::hash);
1054 static bool cache_func_constraint_hash() {
1055 static bool func_constraint_hash_loaded = FALSE;
1057 // strings holding exclude constraints....
1058 vector<string> func_constraints;
1059 // if unble to get list of excluded functions, assume all functions
1060 // are NOT excluded!!!!
1061 if(mdl_get_lib_constraints(func_constraints) == FALSE) {
1064 func_constraint_hash_loaded = TRUE;
1067 for(i=0;i<func_constraints.size();i++) {
1068 func_constraint_hash[func_constraints[i]] = func_constraints[i];
1073 // mcheyney, Oct. 3, 1997
1074 // Return boolean value indicating whether function is found to
1075 // be excluded via "exclude module_name/function_name" (but NOT
1076 // via "exclude module_name").
1077 bool function_is_excluded(pd_Function *func, string module_name) {
1078 static bool func_constraint_hash_loaded = FALSE;
1080 string function_name = func->prettyName();
1081 string full_name = module_name + string("/") + function_name;
1083 if (func_constraint_hash_loaded == FALSE) {
1084 if (!cache_func_constraint_hash()) {
1089 if (func_constraint_hash.defines(full_name)) {
1095 bool module_is_excluded(pdmodule *module) {
1096 static bool func_constraint_hash_loaded = FALSE;
1098 string full_name = module->fileName();
1100 if (func_constraint_hash_loaded == FALSE) {
1101 if (!cache_func_constraint_hash()) {
1106 if (func_constraint_hash.defines(full_name)) {
1113 // mcheyney, Sep 28, 1997
1114 // Take a list of functions (in vector <all_funcs>. Copy all
1115 // of those functions which are not excluded (via "exclude"
1116 // {module==module_name}/{function==function_name) into
1117 // <some_functions>. DONT filter out those excluded via
1118 // exclude module==module_name...., eh????
1119 // Returns status of mdl_get_lib_constraints() call.
1120 // If this status == FALSE< some_funcs is not modified....
1121 // We assume that all_funcs is generally longer than the list
1122 // of constrained functions. As such, internally proc. copies
1123 // all funcs into some funcs, then runs over excluded funcs
1124 // removing any matches, as opposed to doing to checking
1125 // while adding to some_funcs....
1127 bool filter_excluded_functions(vector<pd_Function*> all_funcs,
1128 vector<pd_Function*>& some_funcs, string module_name) {
1132 static bool func_constraint_hash_loaded = FALSE;
1134 if (func_constraint_hash_loaded == FALSE) {
1135 if (!cache_func_constraint_hash()) {
1140 // run over all_funcs, check if module/function is caught
1141 // by an exclude....
1142 for(i=0;i<all_funcs.size();i++) {
1143 full_name = module_name + string("/") + all_funcs[i]->prettyName();
1144 if (!(func_constraint_hash.defines(full_name))) {
1145 some_funcs += all_funcs[i];
1149 //cerr << " looks successful : about to return TRUE" << endl;
1150 //cerr << " some_funcs (by pretty name) " << endl;
1151 //for (i=0;i<some_funcs.size();i++) {
1152 // cerr << " " << some_funcs[i]->prettyName() << endl;
1158 #endif /* BPATCH_LIBRARY */
1160 // identify module name from symbol address (binary search)
1161 // based on module tags found in file format (ELF/COFF)
1162 void image::findModByAddr (const Symbol &lookUp, vector<Symbol> &mods,
1163 string &modName, Address &modAddr,
1164 const string &defName)
1166 if (mods.size() == 0) {
1172 Address symAddr = lookUp.addr();
1175 int end = mods.size() - 1;
1178 while ((start <= end) && !found) {
1179 index = (start+end)/2;
1180 if ((index == last) ||
1181 ((mods[index].addr() <= symAddr) &&
1182 (mods[index+1].addr() > symAddr))) {
1183 modName = mods[index].name();
1184 modAddr = mods[index].addr();
1186 } else if (symAddr < mods[index].addr()) {
1193 // must be (start > end)
1196 //modName = mods[0].name();
1197 //modAddr = mods[0].addr();
1201 unsigned int int_addrHash(const Address& addr) {
1202 return (unsigned int)addr;
1206 * load an executable:
1207 * 1.) parse symbol table and identify rotuines.
1208 * 2.) scan executable to identify inst points.
1210 * offset is normally zero except on CM-5 where we have two images in one
1211 * file. The offset passed to parseImage is the logical offset (0/1), not
1212 * the physical point in the file. This makes it faster to "parse" multiple
1213 * copies of the same image since we don't have to stat and read to find the
1217 image *image::parseImage(fileDescriptor *desc)
1220 * Check to see if we have parsed this image at this offset before.
1221 * We only match if the entire file descriptor matches, which can
1222 * can be filename matching or filename/offset matching.
1224 unsigned numImages = allImages.size();
1226 // AIX: it's possible that we're reparsing a file with better information
1227 // about it. If so, yank the old one out of the images vector -- replace
1229 for (unsigned u=0; u<numImages; u++)
1230 if ((*desc) == *(allImages[u]->desc()))
1231 return allImages[u];
1233 * load the symbol table. (This is the a.out format specific routine).
1236 if(desc->isSharedObject())
1237 statusLine("Processing a shared object file");
1239 statusLine("Processing an executable file");
1242 // TODO -- kill process here
1243 image *ret = new image(desc, err);
1250 bool beenReplaced = false;
1251 #ifdef rs6000_ibm_aix4_1
1252 // On AIX, we might have a "stub" image instead of the
1253 // actual image we want. So we check to see if we do,
1254 // and if so copy over the list. In normal practice,
1255 // the stub will be the first and only entry.
1256 for (unsigned i=0; i<numImages; i++)
1257 if (allImages[i]->desc()->addr() == (unsigned) -1) {
1258 image *imageTemp = allImages[i];
1260 beenReplaced = true;
1263 // Add to master image list.
1265 if (beenReplaced == false) // short-circuit on non-AIX
1266 image::allImages.push_back(ret);
1268 // define all modules.
1269 #ifndef BPATCH_LIBRARY
1270 tp->resourceBatchMode(true);
1273 statusLine("defining modules");
1274 ret->defineModules();
1276 // statusLine("ready"); // this shouldn't be here, right? (cuz we're not done, right?)
1278 #ifndef BPATCH_LIBRARY
1279 tp->resourceBatchMode(false);
1286 // Constructor for the image object. The fileDescriptor simply
1287 // wraps (in the normal case) the object name and a relocation
1288 // address (0 for a.out file). On the following platforms, we
1289 // are handling a special case:
1290 // AIX: objects can possibly have a name like /lib/libc.so:shr.o
1291 // since libraries are archives
1292 // Both text and data sections have a relocation address
1295 image::image(fileDescriptor *desc, bool &err)
1298 is_libdyninstRT(false),
1301 linkedFile(desc, pd_log_perror),
1302 knownJumpTargets(int_addrHash, 8192),
1303 #if !defined(USE_STL_VECTOR)
1307 includedFunctions(0),
1308 instrumentableFunctions(0),
1310 funcsByAddr(addrHash4),
1311 funcsByPretty(string::hash),
1312 funcsByMangled(string::hash),
1313 notInstruFunctions(string::hash),
1314 excludedFunctions(string::hash),
1315 modsByFileName(string::hash),
1316 modsByFullName(string::hash),
1317 varsByPretty(string::hash)
1319 sharedobj_cerr << "image::image for file name="
1320 << desc->file() << endl;
1322 // initialize (data members) codeOffset_, dataOffset_,
1323 // codeLen_, dataLen_.
1324 codeOffset_ = linkedFile.code_off();
1325 dataOffset_ = linkedFile.data_off();
1326 codeLen_ = linkedFile.code_len();
1327 dataLen_ = linkedFile.data_len();
1329 // if unable to parse object file (somehow??), try to
1330 // notify luser/calling process + return....
1331 if (!codeLen_ || !linkedFile.code_ptr()) {
1332 string msg = string("Parsing problem with executable file: ") + desc->file();
1333 statusLine(msg.string_of());
1335 logLine(msg.string_of());
1337 #ifndef mips_unknown_ce2_11 //ccw 29 mar 2001
1339 #if defined(BPATCH_LIBRARY)
1340 BPatch_reportError(BPatchWarning, 27, msg.string_of());
1342 showErrorCallback(27, msg);
1349 // give luser some feedback....
1350 msg = string("Parsing object file: ") + desc->file();
1351 statusLine(msg.string_of());
1353 name_ = extract_pathname_tail(desc->file());
1354 pathname_ = desc->file();
1357 // use the *DUMMY_MODULE* until a module is defined
1358 //pdmodule *dynModule = newModule(DYN_MODULE, 0);
1359 //pdmodule *libModule = newModule(LIBRARY_MODULE, 0);
1360 // TODO -- define inst points in define function ?
1362 // The functions cannot be verified until all of them have been seen
1363 // because calls out of each function must be tagged as calls to user
1364 // functions or call to "library" functions
1367 // sort the modules by address into a vector to allow a binary search to
1368 // determine the module that a symbol will map to -- this
1369 // may be bsd specific....
1371 vector <Symbol> tmods;
1373 for (SymbolIter symIter(linkedFile); symIter; symIter++) {
1374 const Symbol &lookUp = symIter.currval();
1375 if (lookUp.type() == Symbol::PDST_MODULE) {
1377 const string &lookUpName = lookUp.name();
1378 const char *str = lookUpName.string_of();
1380 int ln = lookUpName.length();
1382 // directory definition -- ignored for now
1383 if (str[ln-1] != '/') {
1384 tmods.push_back(lookUp);
1389 // sort the modules by address
1390 statusLine("sorting modules");
1391 VECTOR_SORT(tmods, symbol_compare);
1393 // remove duplicate entries -- some .o files may have the same
1394 // address as .C files. kludge is true for module symbols that
1395 // I am guessing are modules
1396 vector<Symbol> uniq;
1398 unsigned int num_zeros = 0;
1399 // must use loop+1 not mods.size()-1 since it is an unsigned compare
1400 // which could go negative - jkh 5/29/95
1401 for (unsigned loop=0; loop < tmods.size(); loop++) {
1402 if (tmods[loop].addr() == 0) num_zeros++;
1403 if ((loop+1 < tmods.size()) &&
1404 (tmods[loop].addr() == tmods[loop+1].addr())) {
1405 if (!tmods[loop].kludge())
1406 tmods[loop+1] = tmods[loop];
1409 uniq.push_back(tmods[loop]);
1411 // avoid case where all (ELF) module symbols have address zero
1412 if (num_zeros == tmods.size()) uniq.resize(0);
1414 // define all of the functions
1415 statusLine("winnowing functions");
1417 // define all of the functions
1418 if (!addAllFunctions(uniq)) {
1423 // ALERT ALERT - Calling on both shared_object && !shared_object path.
1424 // In origional code, only called in !shared_object case. Was this
1426 // XXX should have a statusLine("retrieving variable information") here,
1427 // but it's left out for now since addAllVariables only does something
1428 // when BPATCH_LIBRARY is defined
1431 statusLine("checking call points");
1432 checkAllCallPoints();
1434 // TODO -- remove duplicates -- see earlier note
1435 dictionary_hash<Address, unsigned> addr_dict(addrHash4);
1436 vector<pd_Function*> temp_vec;
1438 // question?? Necessary to do same crap to includedFunctions &&
1439 // excludedFunctions??
1440 unsigned f_size = instrumentableFunctions.size(), index;
1441 for (index=0; index<f_size; index++) {
1442 const Address the_address =
1443 instrumentableFunctions[index]->getAddress(0);
1444 if (!addr_dict.defines(the_address)) {
1445 addr_dict[the_address] = 1;
1446 temp_vec.push_back(instrumentableFunctions[index]);
1450 instrumentableFunctions = temp_vec;
1453 void pdmodule::checkAllCallPoints() {
1454 unsigned fsize = funcs.size();
1455 for (unsigned f=0; f<fsize; f++)
1456 funcs[f]->checkCallPoints();
1459 function_base *pdmodule::findFunctionFromAll(const string &name) {
1460 unsigned fsize = funcs.size();
1462 for (f=0; f<fsize; f++) {
1463 if (funcs[f]->symTabName() == name)
1465 else if (funcs[f]->prettyName() == name)
1469 fsize = notInstruFuncs.size();
1470 for (f=0; f<fsize; f++) {
1471 if (notInstruFuncs[f]->symTabName() == name)
1472 return notInstruFuncs[f];
1473 else if (notInstruFuncs[f]->prettyName() == name)
1474 return notInstruFuncs[f];
1480 void image::checkAllCallPoints() {
1481 dictionary_hash_iter<string, pdmodule*> di(modsByFullName);
1482 string s; pdmodule *mod;
1483 while (di.next(s, mod))
1484 mod->checkAllCallPoints();
1487 pdmodule *image::getOrCreateModule(const string &modName,
1488 const Address modAddr) {
1489 const char *str = modName.string_of();
1490 int len = modName.length();
1493 // TODO ignore directory definitions for now
1494 if (str[len-1] == '/') {
1497 // TODO - navigate ".." and "."
1498 const char *lastSlash = P_strrchr(str, '/');
1500 return (newModule(++lastSlash, modAddr));
1502 return (newModule(modName, modAddr));
1506 // Verify that this is code
1507 // Find the call points
1508 // Find the return address
1509 // TODO -- use an instruction object to remove
1510 // Sets err to false on error, true on success
1512 // Note - this must define funcEntry and funcReturn
1514 pd_Function::pd_Function(const string &symbol, const string &pretty,
1515 pdmodule *f, Address adr, const unsigned size,
1516 const image *owner, bool &err) :
1517 function_base(symbol, pretty, adr, size),
1520 #ifndef BPATCH_LIBRARY
1525 err = findInstPoints(owner) == false;
1527 isInstrumentable_ = !err;
1530 // This method returns the address at which this function resides
1531 // in the process P, even if it is dynamic, even if it has been
1532 // relocated. getAddress() (see symtab.h) does not always do this:
1533 // If the function is in a shlib and it has not been relocated,
1534 // getAddress() only returns the relative offset of the function
1535 // within its shlib. We think that getAddress() should be fixed
1536 // to always return the effective address, but we are not sure
1537 // whether that would boggle any of its 75 callers. Until that is
1538 // cleared up, call this method. -zandy, Apr-26-1999
1539 Address pd_Function::getEffectiveAddress(const process *p) const {
1541 // Even if the function has been relocated, call it at its
1542 // original address since the call will be redirected to the
1543 // right place anyway.
1545 p->getBaseAddress(file()->exec(), base);
1546 return base + addr();
1550 /*********************************************************************/
1551 /**** Function lookup (by name or address) routines ****/
1552 /*********************************************************************/
1554 /* Look up a function by the given address. Four-part method:
1555 * First, do a quick scan of funcsByAddr to see if we get a match
1556 * -- will match function entry point
1557 * Second, do a complete search of funcsByAddr, using original address
1558 * Finally, check excludedFuncs and nonInstruFuncs
1561 pd_Function *image::findFuncByAddr(const Address &addr,
1562 const process *p) const
1566 // Quick check of funcsByAddr
1567 if (funcsByAddr.find(addr, pdf))
1570 // Slow check of funcsByAddr
1571 dictionary_hash_iter<Address, pd_Function*> mi(funcsByAddr);
1573 while (mi.next(adr, pdf)) {
1574 if ( p && // getEffectiveAddress asserts p
1575 (addr>=pdf->getEffectiveAddress(p)) &&
1576 (addr<(pdf->getEffectiveAddress(p)+pdf->size()))
1579 if ( (addr>=pdf->getAddress(p)) &&
1580 (addr < (pdf->getAddress(p)+pdf->size()))
1585 // next, look in excludedFunctions...
1586 dictionary_hash_iter<string, pd_Function*> ex(excludedFunctions);
1588 while (ex.next(str, pdf)) {
1590 (addr>=pdf->getEffectiveAddress(p)) &&
1591 (addr<(pdf->getEffectiveAddress(p)+pdf->size()))
1594 if ( (addr>=pdf->getAddress(p)) &&
1595 (addr < (pdf->getAddress(p)+pdf->size()))
1600 dictionary_hash_iter<string, pd_Function *> ni(notInstruFunctions);
1601 while (ni.next(str, pdf)) {
1603 (addr>=pdf->getEffectiveAddress(p)) &&
1604 (addr<(pdf->getEffectiveAddress(p)+pdf->size()))
1607 if ( (addr>=pdf->getAddress(p)) &&
1608 (addr < (pdf->getAddress(p)+pdf->size()))
1615 // This function assumes the given address is an offset within
1618 pd_Function *image::findFuncByEntryAddr(const Address &addr,
1619 const process */*p*/) const
1623 if (funcsByAddr.find(addr, pdf))
1629 pd_Function *image::findFuncByRelocAddr(const Address &addr,
1630 const process *p) const
1634 // Slow check of funcsByAddr
1635 dictionary_hash_iter<Address, pd_Function*> mi(funcsByAddr);
1637 while (mi.next(adr, pdf)) {
1638 if ( (addr>=pdf->getAddress(p)) &&
1639 (addr < (pdf->getAddress(p)+pdf->size()))
1644 // next, look in excludedFunctions...
1645 dictionary_hash_iter<string, pd_Function*> ex(excludedFunctions);
1647 while (ex.next(str, pdf)) {
1648 if ( (addr>=pdf->getAddress(p)) &&
1649 (addr < (pdf->getAddress(p)+pdf->size()))
1654 dictionary_hash_iter<string, pd_Function *> ni(notInstruFunctions);
1655 while (ni.next(str, pdf)) {
1656 if ( (addr>=pdf->getAddress(p)) &&
1657 (addr < (pdf->getAddress(p)+pdf->size()))
1664 pd_Function *image::findFuncByOrigAddr(const Address &addr,
1665 const process *p) const
1669 // Slow check of funcsByAddr
1670 dictionary_hash_iter<Address, pd_Function*> mi(funcsByAddr);
1672 while (mi.next(adr, pdf)) {
1673 if ( p && // getEffectiveAddress asserts p
1674 (addr>=pdf->getEffectiveAddress(p)) &&
1675 (addr<(pdf->getEffectiveAddress(p)+pdf->size()))
1680 // next, look in excludedFunctions...
1681 dictionary_hash_iter<string, pd_Function*> ex(excludedFunctions);
1683 while (ex.next(str, pdf)) {
1685 (addr>=pdf->getEffectiveAddress(p)) &&
1686 (addr<(pdf->getEffectiveAddress(p)+pdf->size()))
1691 dictionary_hash_iter<string, pd_Function *> ni(notInstruFunctions);
1692 while (ni.next(str, pdf)) {
1694 (addr>=pdf->getEffectiveAddress(p)) &&
1695 (addr<(pdf->getEffectiveAddress(p)+pdf->size()))
1702 // Return the vector of functions associated with a pretty (demangled) name
1703 // Very well might be more than one!
1705 vector <pd_Function *> *image::findFuncVectorByPretty(const string &name)
1707 #ifdef IBM_BPATCH_COMPAT_STAB_DEBUG
1708 fprintf(stderr, "%s[%d]: inside findFuncVectorByPretty\n", __FILE__, __LINE__);
1711 if (funcsByPretty.defines(name))
1712 return funcsByPretty[name];
1716 // Return a single function associated with a demangled name. Arbitrarily
1717 // pick the first one.
1719 pd_Function *image::findFuncByPretty(const string &name)
1721 vector <pd_Function *> *a;
1723 if (funcsByPretty.defines(name)) {
1724 a = funcsByPretty[name];
1730 pd_Function *image::findFuncByMangled(const string &name)
1732 vector <pd_Function *> *a;
1734 if (funcsByMangled.defines(name)) {
1735 a = funcsByMangled[name];
1741 pd_Function *image::findExcludedFunc(const string &name)
1743 if (excludedFunctions.defines(name))
1744 return excludedFunctions[name];
1748 pd_Function *image::findNonInstruFunc(const string &name)
1750 if (notInstruFunctions.defines(name))
1751 return notInstruFunctions[name];
1755 // TODO -- this is only being used in cases where only one function
1756 // should exist -- should I assert that the vector size <= 1 ?
1757 // mcheyney - should return NULL when function being searched for
1759 // Checks for function in pretty name hash first, then in
1760 // mangled name hash to better handle many (mangled name) to one
1761 // (pretty name) mapping in C++ function names....
1762 pd_Function *image::findFuncByName(const string &name)
1766 if ( ( pdf = findFuncByPretty(name))) return pdf;
1768 if ( ( pdf = findFuncByMangled(name))) return pdf;
1773 // This function supposely is only used to find function that
1774 // is not instrumentable which may not be totally defined.
1775 // Use with caution.
1776 // NEW - also can be used to find an excluded function....
1777 pd_Function *image::findOneFunctionFromAll(const string &name) {
1778 pd_Function *ret = NULL;
1779 if ( (ret = findFuncByName(name)))
1782 if ( (ret = findNonInstruFunc(name)))
1785 if ( (ret = findExcludedFunc(name)))
1792 // Only looks for function by pretty name.
1793 // Should it also look by mangled name??
1794 bool image::findFunction(const string &name, vector<pd_Function*> &retList,
1795 bool find_if_excluded) {
1798 if (funcsByPretty.defines(name)) {
1799 retList = *funcsByPretty[name];
1803 if (find_if_excluded) {
1804 // should APPEND to retList!!!!
1805 if (excludedFunctions.defines(name))
1806 retList.push_back(excludedFunctions[name]);