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.128 2001/08/29 23:25:28 hollings 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);
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) {
291 notInstruFunctions[func->prettyName()] = func;
295 static timer loadTimer;
296 static FILE *timeOut=0;
297 #endif /* DEBUG_TIME */
299 // addOneFunction(): find name of enclosing module and define function symbol
301 // module information comes from one of three sources:
302 // #1 - debug format (stabs, DWARF, etc.)
303 // #2 - file format (ELF, COFF)
304 // #3 - file name (a.out, libXXX.so)
305 // (in order of decreasing reliability)
306 bool image::addOneFunction(vector<Symbol> &mods,
307 const Symbol &lookUp)
311 string modName = lookUp.module();
314 modName = name_ + "_module";
315 } else if (modName == "DEFAULT_MODULE") {
316 string modName_3 = modName;
317 findModByAddr(lookUp, mods, modName, modAddr, modName_3);
320 pdmodule *use = getOrCreateModule(modName, modAddr);
322 return newFunc(use, lookUp.name(), lookUp.addr(), lookUp.size());
326 * Add another name for the current function to the names vector in
327 * the function object. We also need to add the extra names to the
330 void image::addMultipleFunctionNames(vector<Symbol> &mods,
331 const Symbol &lookUp)
333 pd_Function *func = findFuncByAddr(lookUp.addr());
335 /* sanity check, make sure we have actually seen this address before */
338 /* build the mangeled and pretty names so that we can add those to the
341 string name = lookUp.name();
342 string mangled_name = name;
343 const char *p = P_strchr(name.string_of(), ':');
345 unsigned nchars = p - name.string_of();
346 mangled_name = string(name.string_of(), nchars);
350 if (!buildDemangledName(mangled_name, demangled))
351 demangled = mangled_name;
353 /* add the names to the vectors in the function object */
354 func->addSymTabName(mangled_name);
355 func->addPrettyName(demangled);
357 /* now we add the names and the function object to the hash tables */
358 vector<pd_Function*> *funcsByPrettyEntry = NULL;
359 vector<pd_Function*> *funcsByMangledEntry = NULL;
361 if(!funcsByPretty.find(demangled, funcsByPrettyEntry)) {
362 funcsByPrettyEntry = new vector<pd_Function*>;
363 funcsByPretty[demangled] = funcsByPrettyEntry;
366 assert(funcsByPrettyEntry);
367 (*funcsByPrettyEntry).push_back(func);
369 if (!funcsByMangled.find(mangled_name, funcsByMangledEntry)) {
370 funcsByMangledEntry = new vector<pd_Function*>;
371 funcsByMangled[mangled_name] = funcsByMangledEntry;
374 assert(funcsByMangledEntry);
375 (*funcsByMangledEntry).push_back(func);
379 * Add all the functions (*) in the list of symbols to our data
382 * We do a search for a "main" symbol (a couple of variants), and
383 * if found we flag this image as the executable (a.out).
386 bool image::addAllFunctions(vector<Symbol> &mods)
391 // is_a_out is a member variable
392 Symbol mainFuncSymbol; //Keeps track of info on "main" function
394 //Checking "main" function names in same order as in the inst-*.C files
395 if (linkedFile.get_symbol(symString="main", lookUp) ||
396 linkedFile.get_symbol(symString="_main", lookUp) ||
397 linkedFile.get_symbol(symString="WinMain", lookUp) ||
398 linkedFile.get_symbol(symString="_WinMain", lookUp)) {
399 mainFuncSymbol = lookUp;
405 // Checking for libdyninstRT (DYNINSTinit())
406 if (linkedFile.get_symbol(symString="DYNINSTinit", lookUp) ||
407 linkedFile.get_symbol(symString="_DYNINSTinit", lookUp))
408 is_libdyninstRT = true;
410 is_libdyninstRT = false;
412 // find the real functions -- those with the correct type in the symbol table
413 for(SymbolIter symIter(linkedFile); symIter;symIter++) {
414 const Symbol &lookUp = symIter.currval();
415 if (funcsByAddr.defines(lookUp.addr())) {
416 // We have already seen a function at this addr. add a second name
417 // for this function.
418 addMultipleFunctionNames(mods, lookUp);
422 (lookUp.addr() == mainFuncSymbol.addr()) &&
423 (lookUp.name() != mainFuncSymbol.name()))
424 // Wait for main to appear. Couldn't we just add main to start with?
426 if (lookUp.type() == Symbol::PDST_FUNCTION) {
427 if (!isValidAddress(lookUp.addr())) {
430 sprintf(tempBuffer,"0x%lx",lookUp.addr());
431 msg = string("Function ") + lookUp.name() + string(" has bad address ")
432 + string(tempBuffer);
433 statusLine(msg.string_of());
434 showErrorCallback(29, msg);
437 addOneFunction(mods, lookUp);
441 // now find the pseudo functions -- this gets ugly
442 // kludge has been set if the symbol could be a function
443 // WHERE DO WE USE THESE KLUDGES? WHAT PLATFORM???
444 for(SymbolIter symIter2(linkedFile);symIter2;symIter2++) {
445 lookUp = symIter2.currval();
446 if (funcsByAddr.defines(lookUp.addr()))
447 // Already defined a symbol at this addr
449 if ((lookUp.type() == Symbol::PDST_OBJECT) && lookUp.kludge()) {
450 //logLine(P_strdup(symString.string_of()));
451 // Figure out where this happens
452 cerr << "Found <KLUDGE> function " << lookUp.name().string_of() << endl;
453 addOneFunction(mods, lookUp);
459 bool image::addAllVariables()
461 /* Eventually we'll have to do this on all platforms (because we'll retrieve
462 * the type information here).
464 #if defined(i386_unknown_nt4_0) || (defined mips_unknown_ce2_11) //ccw 20 july 2000 : 29 mar 2001
468 for(SymbolIter symIter(linkedFile); symIter; symIter++) {
469 const string &mangledName = symIter.currkey();
470 const Symbol &symInfo = symIter.currval();
472 if (symInfo.type() == Symbol::PDST_OBJECT) {
473 char *name = cplus_demangle((char *)mangledName.string_of(), 0);
474 const char *unmangledName;
475 if (name) unmangledName = name;
476 else unmangledName = mangledName.string_of();
477 if (varsByPretty.defines(unmangledName)) {
478 (*(varsByPretty[unmangledName])).push_back(string(mangledName));
480 vector<string> *varEntry = new vector<string>;
481 (*varEntry).push_back(string(mangledName));
482 varsByPretty[unmangledName] = varEntry;
484 if (name) free(name);
492 * will search for symbol NAME or _NAME
493 * returns false on failure
495 bool image::findInternalSymbol(const string &name,
497 internalSym &ret_sym)
501 if(linkedFile.get_symbol(name,lookUp)){
502 ret_sym = internalSym(lookUp.addr(),name);
507 new_sym = string("_") + name;
508 if(linkedFile.get_symbol(new_sym,lookUp)){
509 ret_sym = internalSym(lookUp.addr(),name);
515 msg = string("Unable to find symbol: ") + name;
516 statusLine(msg.string_of());
517 showErrorCallback(28, msg);
522 bool image::findInternalByPrefix(const string &prefix,
523 vector<Symbol> &found) const
527 Go through all defined symbols and return those which
528 match the prefix given
530 for(SymbolIter symIter(linkedFile); symIter;symIter++) {
531 const Symbol &lookUp = symIter.currval();
532 if (!strncmp(prefix.string_of(), lookUp.name().string_of(),
533 strlen(prefix.string_of())))
535 found.push_back(lookUp);
542 pdmodule *image::findModule(const string &name, bool find_if_excluded)
546 //cerr << "image::findModule " << name << " , " << find_if_excluded
547 // << " called" << endl;
549 if (modsByFileName.defines(name)) {
550 //cerr << " (image::findModule) found module in modsByFileName" << endl;
551 return (modsByFileName[name]);
553 else if (modsByFullName.defines(name)) {
554 //cerr << " (image::findModule) found module in modsByFullName" << endl;
555 return (modsByFullName[name]);
558 // if also looking for excluded functions, check through
559 // excludedFunction list to see if any match function by FullName
561 if (find_if_excluded) {
562 for(i=0;i<excludedMods.size();i++) {
563 if ((excludedMods[i]->fileName() == name) ||
564 (excludedMods[i]->fullName() == name)) {
565 //cerr << " (image::findModule) found module in excludedMods" << endl;
566 return excludedMods[i];
571 //cerr << " (image::findModule) did not find module, returning NULL" << endl;
576 * return 0 if symbol <symname> exists in image, non-zero if it does not
578 bool image::symbolExists(const string &symname)
580 pd_Function *dummy = findFuncByName(symname);
581 return (dummy != NULL);
584 #ifndef BPATCH_LIBRARY
585 void image::postProcess(const string pifname)
588 string fname, errorstr;
590 char tmp1[5000], abstraction[500];
595 /* What file to open? */
596 if (!(pifname == (char*)NULL)) {
599 fname = desc_->file() + ".pif";
603 Fil = P_fopen(fname.string_of(), "r");
606 errorstr = string("Tried to open PIF file ") + fname;
607 errorstr += string(", but could not (continuing)\n");
608 logLine(P_strdup(errorstr.string_of()));
609 showErrorCallback(35, errorstr);
613 /* Process the file */
615 fscanf(Fil, "%s", key);
618 /* Ignore mapping information for right now */
619 fgets(tmp1, 5000, Fil);
622 #ifndef BPATCH_LIBRARY
623 /* Create a new resource */
624 fscanf(Fil, "%s {", abstraction);
625 parent = rootResource;
627 fscanf(Fil, "%s", tmp1);
628 if (tmp1[0] != '}') {
629 parent = resource::newResource(parent, NULL,
631 tmp1, timeStamp::ts1970(),
632 nullString, // uniqifier
638 } while (parent != NULL);
642 errorstr = string("Ignoring bad line key (") + fname;
643 errorstr += string(") in file %s\n");
644 logLine(P_strdup(errorstr.string_of()));
645 fgets(tmp1, 5000, Fil);
653 void image::defineModules() {
656 string pds; pdmodule *mod;
657 dictionary_hash_iter<string, pdmodule*> mi(modsByFileName);
659 while (mi.next(pds, mod)){
663 for(i=0;i<excludedMods.size();i++) {
664 mod = excludedMods[i];
670 ostrstream osb(buffer, 100, ios::out);
671 osb << "IMAGE_" << name() << "__" << getpid() << ends;
672 ofstream of(buffer, ios::app);
674 of << "INCLUDED FUNCTIONS\n";
675 for (unsigned ni=0; ni<includedFunctions.size(); ni++) {
676 of << includedFunctions[ni]->prettyName() << "\t\t"
677 << includedFunctions[ni]->addr() << "\t\t" << endl;
683 #ifndef BPATCH_LIBRARY
684 void image::FillInCallGraphStatic(process *proc)
689 dictionary_hash_iter<string, pdmodule*> mi(modsByFileName);
692 // define call graph relations for all non-excluded modules.
693 while (mi.next(pds, mod)){
694 buffer = "building call graph module: " +
696 statusLine(buffer.string_of());
697 mod->FillInCallGraphStatic(proc);
699 // also define call graph relations for all excluded modules.
700 // Call graph gets information about both included and excluded
701 // modules and functions, and allows the DM and PC to decide whether
702 // to look at a given function based on whether the function is
703 // included or excluded....
704 for(i=0;i<excludedMods.size();i++) {
705 mod = excludedMods[i];
706 buffer = "building call graph module: " +
708 statusLine(buffer.string_of());
709 mod->FillInCallGraphStatic(proc);
714 // Comments on what this does would be nice....
715 // Appears to run over a pdmodule, after all code in it has been processed
716 // and parsed into functions, and define a resource for the module + a
717 // resource for every function found in the module (apparently includes
718 // excluded functions, but not uninstrumentable ones)....
719 // Can't directly register call graph relationships here as resources
720 // are being defined, because need all resources defined to
724 void pdmodule::define() {
725 #ifndef BPATCH_LIBRARY
726 resource *moduleResource = NULL;
730 ostrstream osb(buffer, 100, ios::out);
731 osb << "MODS_" << exec->name() << "__" << getpid() << ends;
732 ofstream of(buffer, ios::app);
735 unsigned f_size = funcs.size();
737 for (unsigned f=0; f<f_size; f++) {
738 #ifndef BPATCH_LIBRARY
739 pd_Function *pdf = funcs[f];
741 of << fileName << ": " << pdf->prettyName() << " "
742 << pdf->addr() << endl;
744 // ignore line numbers for now
746 //if (!(pdf->isLibTag())) {
748 // see if we have created module yet.
749 if (!moduleResource) {
750 moduleResource = resource::newResource(moduleRoot, this,
751 nullString, // abstraction
753 timeStamp::ts1970(), // creation time
754 string(), // unique-ifier
759 pdf->SetFuncResource(resource::newResource(moduleResource, pdf,
760 nullString, // abstraction
763 nullString, // uniquifier
771 #ifndef BPATCH_LIBRARY
772 resource::send_now();
776 // Why is this in symtab.C?
777 #ifndef BPATCH_LIBRARY
778 // send message to data manager to specify the entry function for the
779 // call graph corresponding to a given image. r should hold the
780 // FULL resourcename of the entry function (e.g. "/Code/module.c/main")
781 void CallGraphSetEntryFuncCallback(string exe_name, string r)
783 tp->CallGraphSetEntryFuncCallback(exe_name, r);
786 void CallGraphAddProgramCallback(string name){
787 tp->CallGraphAddProgramCallback(name);
790 //send message to the data manager, notifying it that all of the statically
791 //determinable functions have been registered with the call graph. The
792 //data manager will then be able to create the call graph.
793 void CallGraphFillDone(string exe_name)
795 tp->CallGraphFillDone(exe_name);
798 //send message to the data manager in order to register a function
800 void AddCallGraphNodeCallback(string exe_name, string r)
802 tp->AddCallGraphNodeCallback(exe_name, r);
805 //send a message to the data manager in order register a the function
806 //calls made by a function (whose name is stored in r).
807 void AddCallGraphStaticChildrenCallback(string exe_name, string r,
808 const vector<string> children)
810 tp->AddCallGraphStaticChildrenCallback(exe_name, r, children);
813 // Called across all modules (in a given image) to define the call
814 // graph relationship between functions.
815 // Must be called AFTER all functions in all modules (in image) are
816 // registered as resource (e.g. w/ pdmodule::define())....
817 void pdmodule::FillInCallGraphStatic(process *proc) {
818 pd_Function *pdf, *callee;
819 vector <pd_Function *>callees;
820 resource *r , *callee_as_resource;
821 string callee_full_name;
822 vector <string>callees_as_strings;
823 vector <instPoint*> callPoints;
824 unsigned f, g,i, f_size = funcs.size();
826 string resource_full_name;
828 // for each INSTRUMENTABLE function in the module (including excluded
829 // functions, but NOT uninstrumentable ones)....
831 for (f=0;f<f_size;f++) {
834 callees_as_strings.resize(0);
836 // Translate from function name to resource *.
837 // Note that this probably is NOT the correct translation, as
838 // function names are not necessarily unique, but the paradyn
839 // code assumes that they are in several places (e.g.
840 // resource::findResource)....
841 resource_full_name = pdf->ResourceFullName();
842 r = resource::findResource(resource_full_name);
843 // functions registered under pretty name....
846 // get list of statically determined call destinations from pdf,
847 // using the process info to help fill in calls througb PLT
849 pdf->getStaticCallees(proc, callees);
851 // and convert them into a list of resources....
852 for (g=0;g<callees.size();g++) {
856 //if the funcResource is not set, then the function must be
857 //uninstrumentable, so we don't want to notify the front end
859 if(callee->FuncResourceSet()){
860 callee_full_name = callee->ResourceFullName();
862 // if callee->funcResource has been set, then it should have
863 // been registered as a resource....
864 callee_as_resource = resource::findResource(callee_full_name);
865 assert(callee_as_resource);
866 callees_as_strings += callee_full_name;
871 // register that callee_resources holds list of resource*s
872 // describing children of resource r....
873 string exe_name = proc->getImage()->file();
874 AddCallGraphNodeCallback(exe_name, resource_full_name);
875 AddCallGraphStaticChildrenCallback(exe_name, resource_full_name,
878 //Locate the dynamic call sites within the function, and notify
879 //the front end as to their existence
880 callPoints = pdf->funcCalls(proc);
881 for(i = 0; i < callPoints.size(); i++){
882 if(proc->isDynamicCallSite(callPoints[i])){
883 tp->CallGraphAddDynamicCallSiteCallback(exe_name, resource_full_name);
889 #endif // ndef BPATCH_LIBRARY
891 #ifndef BPATCH_LIBRARY
892 // as per getAllFunctions, but filters out those excluded with
893 // e.g. mdl "exclude" command....
894 // to clarify a function should NOT be returned from here if its
895 // module is excluded (with exclude "/Code/module") or if it
896 // is excluded (with exclude "/Code/module/function").
897 const vector<pd_Function*> &image::getIncludedFunctions() {
899 includedFunctions.resize(0);
900 vector<function_base *> *temp;
901 vector<pd_Function *> *temp2;
903 //cerr << "image::getIncludedFunctions called, name = " << name () << endl;
904 //cerr << " includedMods = " << endl;
905 //print_module_vector_by_short_name(string(" "), &includedMods);
906 for (i=0;i<includedMods.size();i++) {
907 temp = includedMods[i]->getIncludedFunctions();
908 temp2 = (vector<pd_Function *> *) temp;
909 includedFunctions += *temp2;
912 //cerr << " (image::getIncludedFunctions) returning : " << endl;
913 //print_func_vector_by_pretty_name(string(" "),
914 // (vector<function_base*>*)&includedFunctions);
916 // what about shared objects????
917 return includedFunctions;
922 // get all functions in module which are not "excluded" (e.g.
923 // with mdl "exclude" command.
924 // Assed to provide support for mdl "exclude" on functions in
925 // statically linked objects.
927 vector<function_base *> *pdmodule::getIncludedFunctions() {
928 // laxy construction of some_funcs, as per sharedobject class....
929 // cerr << "pdmodule " << fileName() << " :: getIncludedFunctions called "
931 if (some_funcs_inited == TRUE) {
932 //cerr << " about to return : " << endl;
933 //print_func_vector_by_pretty_name(string(" "), (vector<function_base *>*)&some_funcs);
934 return (vector<function_base *>*)&some_funcs;
936 #ifdef BPATCH_LIBRARY //BPatch Library doesn't know about excluded funcs
939 some_funcs.resize(0);
941 if (filter_excluded_functions(funcs, some_funcs, fileName()) == FALSE) {
942 //cerr << " about to return NULL";
946 some_funcs_inited = TRUE;
948 //cerr << " about to return : " << endl;
949 //print_func_vector_by_pretty_name(string(" "),(vector<function_base *>*) &some_funcs);
950 return (vector<function_base *>*)&some_funcs;
954 const vector<pd_Function*> &image::getAllFunctions() {
955 //cerr << "pdmodule::getAllFunctions() called, about to return instrumentableFunctions = " << endl;
956 //print_func_vector_by_pretty_name(string(" "),
957 // (vector<function_base*>*)&instrumentableFunctions);
958 return instrumentableFunctions;
961 const vector <pdmodule*> &image::getAllModules() {
962 // reinit all modules to empty vector....
965 // and add includedModules && excludedModules to it....
966 VECTOR_APPEND(allMods, includedMods);
967 VECTOR_APPEND(allMods, excludedMods);
969 //cerr << "image::getAllModules called" << endl;
970 //cerr << " about to return sum of includedMods and excludedMods" << endl;
971 //cerr << " includedMods : " << endl;
972 //print_module_vector_by_short_name(string(" "), &includedMods);
973 //cerr << " excludedMods : " << endl;
974 //print_module_vector_by_short_name(string(" "), &excludedMods);
980 #ifndef BPATCH_LIBRARY
981 const vector <pdmodule*> &image::getIncludedModules() {
982 //cerr << "image::getIncludedModules called" << endl;
983 //cerr << " about to return includedMods = " << endl;
984 //print_module_vector_by_short_name(string(" "), &includedMods);
990 void print_module_vector_by_short_name(string prefix ,
991 vector<pdmodule*> *mods) {
994 for(i=0;i<mods->size();i++) {
996 cerr << prefix << mod->fileName() << endl;
1000 void print_func_vector_by_pretty_name(string prefix,
1001 vector<function_base *>*funcs) {
1003 function_base *func;
1004 for(i=0;i<funcs->size();i++) {
1005 func = ((*funcs)[i]);
1006 cerr << prefix << func->prettyName() << endl;
1010 // rip module name out of constraint....
1011 // Assumes that constraint is of form module/function, or
1013 string getModuleName(string constraint) {
1016 const char *data = constraint.string_of();
1017 const char *first_slash = P_strchr(data, RH_SEPERATOR);
1019 // no "/", assume string holds module name....
1020 if (first_slash == NULL) {
1023 // has "/", assume everything up to "/" is module name....
1024 return string(data, first_slash - data);
1027 // rip function name out of constraint....
1028 // Assumes that constraint is of form module/function, or
1030 string getFunctionName(string constraint) {
1033 const char *data = constraint.string_of();
1034 const char *first_slash = P_strchr(data, RH_SEPERATOR);
1036 // no "/", assume constraint is module only....
1037 if (first_slash == NULL) {
1040 // has "/", assume everything after "/" is function....
1041 return string(first_slash+1);
1045 #ifndef BPATCH_LIBRARY
1047 // mcheyney, Oct. 6, 1997
1048 static dictionary_hash<string, string> func_constraint_hash(string::hash);
1049 static bool cache_func_constraint_hash() {
1050 static bool func_constraint_hash_loaded = FALSE;
1052 // strings holding exclude constraints....
1053 vector<string> func_constraints;
1054 // if unble to get list of excluded functions, assume all functions
1055 // are NOT excluded!!!!
1056 if(mdl_get_lib_constraints(func_constraints) == FALSE) {
1059 func_constraint_hash_loaded = TRUE;
1062 for(i=0;i<func_constraints.size();i++) {
1063 func_constraint_hash[func_constraints[i]] = func_constraints[i];
1068 // mcheyney, Oct. 3, 1997
1069 // Return boolean value indicating whether function is found to
1070 // be excluded via "exclude module_name/function_name" (but NOT
1071 // via "exclude module_name").
1072 bool function_is_excluded(pd_Function *func, string module_name) {
1073 static bool func_constraint_hash_loaded = FALSE;
1075 string function_name = func->prettyName();
1076 string full_name = module_name + string("/") + function_name;
1078 if (func_constraint_hash_loaded == FALSE) {
1079 if (!cache_func_constraint_hash()) {
1084 if (func_constraint_hash.defines(full_name)) {
1090 bool module_is_excluded(pdmodule *module) {
1091 static bool func_constraint_hash_loaded = FALSE;
1093 string full_name = module->fileName();
1095 if (func_constraint_hash_loaded == FALSE) {
1096 if (!cache_func_constraint_hash()) {
1101 if (func_constraint_hash.defines(full_name)) {
1108 // mcheyney, Sep 28, 1997
1109 // Take a list of functions (in vector <all_funcs>. Copy all
1110 // of those functions which are not excluded (via "exclude"
1111 // {module==module_name}/{function==function_name) into
1112 // <some_functions>. DONT filter out those excluded via
1113 // exclude module==module_name...., eh????
1114 // Returns status of mdl_get_lib_constraints() call.
1115 // If this status == FALSE< some_funcs is not modified....
1116 // We assume that all_funcs is generally longer than the list
1117 // of constrained functions. As such, internally proc. copies
1118 // all funcs into some funcs, then runs over excluded funcs
1119 // removing any matches, as opposed to doing to checking
1120 // while adding to some_funcs....
1122 bool filter_excluded_functions(vector<pd_Function*> all_funcs,
1123 vector<pd_Function*>& some_funcs, string module_name) {
1127 static bool func_constraint_hash_loaded = FALSE;
1129 if (func_constraint_hash_loaded == FALSE) {
1130 if (!cache_func_constraint_hash()) {
1135 // run over all_funcs, check if module/function is caught
1136 // by an exclude....
1137 for(i=0;i<all_funcs.size();i++) {
1138 full_name = module_name + string("/") + all_funcs[i]->prettyName();
1139 if (!(func_constraint_hash.defines(full_name))) {
1140 some_funcs += all_funcs[i];
1144 //cerr << " looks successful : about to return TRUE" << endl;
1145 //cerr << " some_funcs (by pretty name) " << endl;
1146 //for (i=0;i<some_funcs.size();i++) {
1147 // cerr << " " << some_funcs[i]->prettyName() << endl;
1153 #endif /* BPATCH_LIBRARY */
1155 // identify module name from symbol address (binary search)
1156 // based on module tags found in file format (ELF/COFF)
1157 void image::findModByAddr (const Symbol &lookUp, vector<Symbol> &mods,
1158 string &modName, Address &modAddr,
1159 const string &defName)
1161 if (mods.size() == 0) {
1167 Address symAddr = lookUp.addr();
1170 int end = mods.size() - 1;
1173 while ((start <= end) && !found) {
1174 index = (start+end)/2;
1175 if ((index == last) ||
1176 ((mods[index].addr() <= symAddr) &&
1177 (mods[index+1].addr() > symAddr))) {
1178 modName = mods[index].name();
1179 modAddr = mods[index].addr();
1181 } else if (symAddr < mods[index].addr()) {
1188 // must be (start > end)
1191 //modName = mods[0].name();
1192 //modAddr = mods[0].addr();
1196 unsigned int int_addrHash(const Address& addr) {
1197 return (unsigned int)addr;
1201 * load an executable:
1202 * 1.) parse symbol table and identify rotuines.
1203 * 2.) scan executable to identify inst points.
1205 * offset is normally zero except on CM-5 where we have two images in one
1206 * file. The offset passed to parseImage is the logical offset (0/1), not
1207 * the physical point in the file. This makes it faster to "parse" multiple
1208 * copies of the same image since we don't have to stat and read to find the
1212 image *image::parseImage(fileDescriptor *desc)
1215 * Check to see if we have parsed this image at this offset before.
1216 * We only match if the entire file descriptor matches, which can
1217 * can be filename matching or filename/offset matching.
1219 unsigned numImages = allImages.size();
1221 // AIX: it's possible that we're reparsing a file with better information
1222 // about it. If so, yank the old one out of the images vector -- replace
1224 for (unsigned u=0; u<numImages; u++)
1225 if ((*desc) == *(allImages[u]->desc()))
1226 return allImages[u];
1228 * load the symbol table. (This is the a.out format specific routine).
1231 if(desc->isSharedObject())
1232 statusLine("Processing a shared object file");
1234 statusLine("Processing an executable file");
1237 // TODO -- kill process here
1238 image *ret = new image(desc, err);
1245 bool beenReplaced = false;
1246 #ifdef rs6000_ibm_aix4_1
1247 // On AIX, we might have a "stub" image instead of the
1248 // actual image we want. So we check to see if we do,
1249 // and if so copy over the list. In normal practice,
1250 // the stub will be the first and only entry.
1251 for (unsigned i=0; i<numImages; i++)
1252 if (allImages[i]->desc()->addr() == (unsigned) -1) {
1253 image *imageTemp = allImages[i];
1255 beenReplaced = true;
1258 // Add to master image list.
1260 if (beenReplaced == false) // short-circuit on non-AIX
1261 image::allImages.push_back(ret);
1263 // define all modules.
1264 #ifndef BPATCH_LIBRARY
1265 tp->resourceBatchMode(true);
1268 statusLine("defining modules");
1269 ret->defineModules();
1271 // statusLine("ready"); // this shouldn't be here, right? (cuz we're not done, right?)
1273 #ifndef BPATCH_LIBRARY
1274 tp->resourceBatchMode(false);
1281 // Constructor for the image object. The fileDescriptor simply
1282 // wraps (in the normal case) the object name and a relocation
1283 // address (0 for a.out file). On the following platforms, we
1284 // are handling a special case:
1285 // AIX: objects can possibly have a name like /lib/libc.so:shr.o
1286 // since libraries are archives
1287 // Both text and data sections have a relocation address
1289 image::image(fileDescriptor *desc, bool &err)
1292 is_libdyninstRT(false),
1295 linkedFile(desc, pd_log_perror),
1296 knownJumpTargets(int_addrHash, 8192),
1300 includedFunctions(0),
1301 instrumentableFunctions(0),
1302 funcsByAddr(addrHash4),
1303 funcsByPretty(string::hash),
1304 funcsByMangled(string::hash),
1305 notInstruFunctions(string::hash),
1306 excludedFunctions(string::hash),
1307 modsByFileName(string::hash),
1308 modsByFullName(string::hash),
1309 varsByPretty(string::hash)
1311 sharedobj_cerr << "image::image for file name="
1312 << desc->file() << endl;
1314 // initialize (data members) codeOffset_, dataOffset_,
1315 // codeLen_, dataLen_.
1316 codeOffset_ = linkedFile.code_off();
1317 dataOffset_ = linkedFile.data_off();
1318 codeLen_ = linkedFile.code_len();
1319 dataLen_ = linkedFile.data_len();
1321 // if unable to parse object file (somehow??), try to
1322 // notify luser/calling process + return....
1323 if (!codeLen_ || !linkedFile.code_ptr()) {
1324 string msg = string("Parsing problem with executable file: ") + desc->file();
1325 statusLine(msg.string_of());
1327 logLine(msg.string_of());
1329 #ifndef mips_unknown_ce2_11 //ccw 29 mar 2001
1331 #if defined(BPATCH_LIBRARY)
1332 BPatch_reportError(BPatchWarning, 27, msg.string_of());
1334 showErrorCallback(27, msg);
1341 // give luser some feedback....
1342 msg = string("Parsing object file: ") + desc->file();
1343 statusLine(msg.string_of());
1346 // XXX still need full name for later parsing steps
1348 // name_ = extract_pathname_tail(desc->file());
1349 name_ = desc->file();
1352 // use the *DUMMY_MODULE* until a module is defined
1353 //pdmodule *dynModule = newModule(DYN_MODULE, 0);
1354 //pdmodule *libModule = newModule(LIBRARY_MODULE, 0);
1355 // TODO -- define inst points in define function ?
1357 // The functions cannot be verified until all of them have been seen
1358 // because calls out of each function must be tagged as calls to user
1359 // functions or call to "library" functions
1362 // sort the modules by address into a vector to allow a binary search to
1363 // determine the module that a symbol will map to -- this
1364 // may be bsd specific....
1366 vector <Symbol> tmods;
1368 for (SymbolIter symIter(linkedFile); symIter; symIter++) {
1369 const Symbol &lookUp = symIter.currval();
1370 if (lookUp.type() == Symbol::PDST_MODULE) {
1372 const string &lookUpName = lookUp.name();
1373 const char *str = lookUpName.string_of();
1375 int ln = lookUpName.length();
1377 // directory definition -- ignored for now
1378 if (str[ln-1] != '/') {
1379 tmods.push_back(lookUp);
1384 // sort the modules by address
1385 statusLine("sorting modules");
1386 VECTOR_SORT(tmods, symbol_compare);
1388 // remove duplicate entries -- some .o files may have the same
1389 // address as .C files. kludge is true for module symbols that
1390 // I am guessing are modules
1391 vector<Symbol> uniq;
1393 unsigned int num_zeros = 0;
1394 // must use loop+1 not mods.size()-1 since it is an unsigned compare
1395 // which could go negative - jkh 5/29/95
1396 for (unsigned loop=0; loop < tmods.size(); loop++) {
1397 if (tmods[loop].addr() == 0) num_zeros++;
1398 if ((loop+1 < tmods.size()) &&
1399 (tmods[loop].addr() == tmods[loop+1].addr())) {
1400 if (!tmods[loop].kludge())
1401 tmods[loop+1] = tmods[loop];
1404 uniq.push_back(tmods[loop]);
1406 // avoid case where all (ELF) module symbols have address zero
1407 if (num_zeros == tmods.size()) uniq.resize(0);
1409 // define all of the functions
1410 statusLine("winnowing functions");
1412 // define all of the functions
1413 if (!addAllFunctions(uniq)) {
1418 // ALERT ALERT - Calling on both shared_object && !shared_object path.
1419 // In origional code, only called in !shared_object case. Was this
1421 // XXX should have a statusLine("retrieving variable information") here,
1422 // but it's left out for now since addAllVariables only does something
1423 // when BPATCH_LIBRARY is defined
1426 statusLine("checking call points");
1427 checkAllCallPoints();
1429 // TODO -- remove duplicates -- see earlier note
1430 dictionary_hash<Address, unsigned> addr_dict(addrHash4);
1431 vector<pd_Function*> temp_vec;
1433 // question?? Necessary to do same crap to includedFunctions &&
1434 // excludedFunctions??
1435 unsigned f_size = instrumentableFunctions.size(), index;
1436 for (index=0; index<f_size; index++) {
1437 const Address the_address =
1438 instrumentableFunctions[index]->getAddress(0);
1439 if (!addr_dict.defines(the_address)) {
1440 addr_dict[the_address] = 1;
1441 temp_vec.push_back(instrumentableFunctions[index]);
1445 instrumentableFunctions = temp_vec;
1448 void pdmodule::checkAllCallPoints() {
1449 unsigned fsize = funcs.size();
1450 for (unsigned f=0; f<fsize; f++)
1451 funcs[f]->checkCallPoints();
1455 void image::checkAllCallPoints() {
1456 dictionary_hash_iter<string, pdmodule*> di(modsByFullName);
1457 string s; pdmodule *mod;
1458 while (di.next(s, mod))
1459 mod->checkAllCallPoints();
1462 pdmodule *image::getOrCreateModule(const string &modName,
1463 const Address modAddr) {
1464 const char *str = modName.string_of();
1465 int len = modName.length();
1468 // TODO ignore directory definitions for now
1469 if (str[len-1] == '/') {
1472 // TODO - navigate ".." and "."
1473 const char *lastSlash = P_strrchr(str, '/');
1475 return (newModule(++lastSlash, modAddr));
1477 return (newModule(modName, modAddr));
1481 // Verify that this is code
1482 // Find the call points
1483 // Find the return address
1484 // TODO -- use an instruction object to remove
1485 // Sets err to false on error, true on success
1487 // Note - this must define funcEntry and funcReturn
1489 pd_Function::pd_Function(const string &symbol, const string &pretty,
1490 pdmodule *f, Address adr, const unsigned size,
1491 const image *owner, bool &err) :
1492 function_base(symbol, pretty, adr, size),
1495 #ifndef BPATCH_LIBRARY
1500 err = findInstPoints(owner) == false;
1503 // This method returns the address at which this function resides
1504 // in the process P, even if it is dynamic, even if it has been
1505 // relocated. getAddress() (see symtab.h) does not always do this:
1506 // If the function is in a shlib and it has not been relocated,
1507 // getAddress() only returns the relative offset of the function
1508 // within its shlib. We think that getAddress() should be fixed
1509 // to always return the effective address, but we are not sure
1510 // whether that would boggle any of its 75 callers. Until that is
1511 // cleared up, call this method. -zandy, Apr-26-1999
1512 Address pd_Function::getEffectiveAddress(const process *p) const {
1514 // Even if the function has been relocated, call it at its
1515 // original address since the call will be redirected to the
1516 // right place anyway.
1518 p->getBaseAddress(file()->exec(), base);
1519 return base + addr();
1523 /*********************************************************************/
1524 /**** Function lookup (by name or address) routines ****/
1525 /*********************************************************************/
1527 /* Look up a function by the given address. Four-part method:
1528 * First, do a quick scan of funcsByAddr to see if we get a match
1529 * -- will match function entry point
1530 * Second, do a complete search of funcsByAddr, using original address
1531 * Finally, check excludedFuncs and nonInstruFuncs
1534 pd_Function *image::findFuncByAddr(const Address &addr,
1535 const process *p) const
1539 // Quick check of funcsByAddr
1540 if (funcsByAddr.find(addr, pdf))
1543 // Slow check of funcsByAddr
1544 dictionary_hash_iter<Address, pd_Function*> mi(funcsByAddr);
1546 while (mi.next(adr, pdf)) {
1547 if ( p && // getEffectiveAddress asserts p
1548 (addr>=pdf->getEffectiveAddress(p)) &&
1549 (addr<(pdf->getEffectiveAddress(p)+pdf->size()))
1552 if ( (addr>=pdf->getAddress(p)) &&
1553 (addr < (pdf->getAddress(p)+pdf->size()))
1558 // next, look in excludedFunctions...
1559 dictionary_hash_iter<string, pd_Function*> ex(excludedFunctions);
1561 while (ex.next(str, pdf)) {
1563 (addr>=pdf->getEffectiveAddress(p)) &&
1564 (addr<(pdf->getEffectiveAddress(p)+pdf->size()))
1567 if ( (addr>=pdf->getAddress(p)) &&
1568 (addr < (pdf->getAddress(p)+pdf->size()))
1573 dictionary_hash_iter<string, pd_Function *> ni(notInstruFunctions);
1574 while (ni.next(str, pdf)) {
1576 (addr>=pdf->getEffectiveAddress(p)) &&
1577 (addr<(pdf->getEffectiveAddress(p)+pdf->size()))
1580 if ( (addr>=pdf->getAddress(p)) &&
1581 (addr < (pdf->getAddress(p)+pdf->size()))
1588 // Return the vector of functions associated with a pretty (demangled) name
1589 // Very well might be more than one!
1591 vector <pd_Function *> *image::findFuncVectorByPretty(const string &name)
1593 if (funcsByPretty.defines(name))
1594 return funcsByPretty[name];
1598 // Return a single function associated with a demangled name. Arbitrarily
1599 // pick the first one.
1601 pd_Function *image::findFuncByPretty(const string &name)
1603 vector <pd_Function *> *a;
1605 if (funcsByPretty.defines(name)) {
1606 a = funcsByPretty[name];
1612 pd_Function *image::findFuncByMangled(const string &name)
1614 vector <pd_Function *> *a;
1616 if (funcsByMangled.defines(name)) {
1617 a = funcsByMangled[name];
1623 pd_Function *image::findExcludedFunc(const string &name)
1625 if (excludedFunctions.defines(name))
1626 return excludedFunctions[name];
1630 pd_Function *image::findNonInstruFunc(const string &name)
1632 if (notInstruFunctions.defines(name))
1633 return notInstruFunctions[name];
1637 // TODO -- this is only being used in cases where only one function
1638 // should exist -- should I assert that the vector size <= 1 ?
1639 // mcheyney - should return NULL when function being searched for
1641 // Checks for function in pretty name hash first, then in
1642 // mangled name hash to better handle many (mangled name) to one
1643 // (pretty name) mapping in C++ function names....
1644 pd_Function *image::findFuncByName(const string &name)
1648 if ( ( pdf = findFuncByPretty(name))) return pdf;
1650 if ( ( pdf = findFuncByMangled(name))) return pdf;
1655 // This function supposely is only used to find function that
1656 // is not instrumentable which may not be totally defined.
1657 // Use with caution.
1658 // NEW - also can be used to find an excluded function....
1659 pd_Function *image::findOneFunctionFromAll(const string &name) {
1660 pd_Function *ret = NULL;
1661 if ( (ret = findFuncByName(name)))
1664 if ( (ret = findNonInstruFunc(name)))
1667 if ( (ret = findExcludedFunc(name)))
1674 // Only looks for function by pretty name.
1675 // Should it also look by mangled name??
1676 bool image::findFunction(const string &name, vector<pd_Function*> &retList,
1677 bool find_if_excluded) {
1680 if (funcsByPretty.defines(name)) {
1681 retList = *funcsByPretty[name];
1685 if (find_if_excluded) {
1686 // should APPEND to retList!!!!
1687 if (excludedFunctions.defines(name))
1688 retList.push_back(excludedFunctions[name]);