Removed code to use full paht name for name_.
[dyninst.git] / dyninstAPI / src / symtab.C
1 /*
2  * Copyright (c) 1996 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 // $Id: symtab.C,v 1.129 2001/08/30 19:10:47 hollings Exp $
43
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <assert.h>
47
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"
53 #include <fstream.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()
63
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"
69 #else
70 extern vector<sym_data> syms_to_find;
71 #endif
72
73 // All debug_ostream vrbles are defined in process.C (for no particular reason)
74 extern debug_ostream sharedobj_cerr;
75
76 vector<image*> image::allImages;
77
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);
80 #else
81 extern "C" char *cplus_demangle(char *, int);
82 #endif
83
84 // coming to dyninstAPI/src/symtab.hC
85 // needed in metric.C
86 bool function_base::match(function_base *fb)
87 {
88   if (this == fb)
89     return true;
90   else
91     return ((symTabName_ == fb->symTabName_) &&
92             (prettyName_ == fb->prettyName_) &&
93             (line_       == fb->line_) &&
94             (addr_       == fb->addr_) &&
95             (size_       == fb->size_));
96 }
97
98 /*
99   Debuggering info for function_base....
100  */
101 ostream & function_base::operator<<(ostream &s) const {
102   
103     unsigned i=0;
104     s << "Mangled name(s): " << symTabName_[0];
105     for(i = 1; i < symTabName_.size(); i++) {
106         s << ", " << symTabName_[i];
107     }
108
109     s << "\nPretty name(s): " << prettyName_[0];
110     for(i = 1; i < prettyName_.size(); i++) {
111         s << ", " << prettyName_[i];
112     }
113       s << "\nline_ = " << line_ << " addr_ = "<< addr_ << " size_ = ";
114       s << size_ << endl;
115   
116     return s;
117 }
118
119 ostream &operator<<(ostream &os, function_base &f) {
120     return f.operator<<(os);
121 }
122
123 /* imported from platform specific library list.  This is lists all
124    library functions we are interested in instrumenting. */
125
126 pdmodule *image::newModule(const string &name, const Address addr)
127 {
128     pdmodule *ret;
129     // modules can be defined several times in C++ due to templates and
130     //   in-line member functions.
131     if ((ret = findModule(name, TRUE)))
132       return(ret);
133
134     string fullNm, fileNm;
135     char *out = P_strdup(name.string_of());
136     char *sl = P_strrchr(out, '/');
137     if (sl) {
138       *sl = (char)0;
139       fullNm = out;
140       fileNm = sl+1;
141     } else {
142       fullNm = string("/default/") + out;
143       fileNm = out;
144     }
145     free(out);
146
147     ret = new pdmodule(lang_Unknown, addr, fullNm, fileNm, this);
148
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)) {
153         excludedMods += ret;
154     } else {
155 #endif /* BPATCH_LIBRARY */
156         modsByFileName[ret->fileName()] = ret;
157         modsByFullName[ret->fullName()] = ret;
158         includedMods.push_back(ret);
159 #ifndef BPATCH_LIBRARY
160     }
161 #endif /* BPATCH_LIBRARY */
162
163     return(ret);
164 }
165
166
167 // TODO -- is this g++ specific
168 bool buildDemangledName(const string &mangled, string &use)
169 {
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
173   * approach.
174   */
175   if(!mangled.prefixed_by("MPI__")) {
176     char *tempName = P_strdup(mangled.string_of());
177     char *demangled = cplus_demangle(tempName, 0);
178     
179     if (demangled) {
180       use = demangled;
181       free(tempName);
182       free(demangled);
183       return true;
184     } else {
185       free(tempName);
186       return false;
187     }
188   }
189   return(false);
190 }
191
192 // err is true if the function can't be defined
193 // COMMENTS????
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 
202 //    demangled name).
203 bool image::newFunc(pdmodule *mod, const string &name, 
204                     const Address addr, 
205                     const unsigned size) {
206   pd_Function *func;
207
208   // KLUDGE
209   if ((func = findFuncByAddr(addr))){
210     //string temp = name;
211     //temp += string(" findFunction succeeded\n");
212     //logLine(P_strdup(temp.string_of()));
213     return false;
214   }
215
216   if (!mod) {
217     logLine("Error function without module\n");
218     showErrorCallback(34, "Error function without module");
219     return false;
220   }
221   
222   string mangled_name = name;
223   const char *p = P_strchr(name.string_of(), ':');
224   if (p) {
225      unsigned nchars = p - name.string_of();
226      mangled_name = string(name.string_of(), nchars);
227   }
228   
229   string demangled;
230   if (!buildDemangledName(mangled_name, demangled)) 
231     demangled = mangled_name;
232
233   bool err=false;
234
235   func = new pd_Function(name, demangled, mod, addr, size, this, err);
236   assert(func);
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.
240   if (err) {
241     //delete func;
242     addNotInstruFunc(func);
243     return false;
244   }
245  
246   addInstruFunction(func, mod, addr,
247 #ifdef BPATCH_LIBRARY
248                     false);
249 #else
250                     function_is_excluded(func, mod->fileName()));
251 #endif
252   return true;
253 }
254
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;
259
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);
264
265     if (excluded) {
266         excludedFunctions[func->prettyName()] = func;
267     } else {
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;
273         }
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);
278
279         if (!funcsByMangled.find(func->symTabName(), funcsByMangledEntry)) {
280             funcsByMangledEntry = new vector<pd_Function*>;
281             funcsByMangled[func->symTabName()] = funcsByMangledEntry;
282         }
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);
287     }
288 }
289
290 void image::addNotInstruFunc(pd_Function *func) {
291     notInstruFunctions[func->prettyName()] = func;
292 }
293
294 #ifdef DEBUG_TIME
295 static timer loadTimer;
296 static FILE *timeOut=0;
297 #endif /* DEBUG_TIME */
298
299 // addOneFunction(): find name of enclosing module and define function symbol
300 //
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) 
308 {
309   // find module name
310   Address modAddr = 0;
311   string modName = lookUp.module();
312
313   if (modName == "") {
314     modName = name_ + "_module";
315   } else if (modName == "DEFAULT_MODULE") {
316     string modName_3 = modName;
317     findModByAddr(lookUp, mods, modName, modAddr, modName_3);
318   }
319   
320   pdmodule *use = getOrCreateModule(modName, modAddr);
321   assert(use);
322   return newFunc(use, lookUp.name(), lookUp.addr(), lookUp.size());
323 }
324
325 /*
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
328  * lookup hash tables
329  */
330 void image::addMultipleFunctionNames(vector<Symbol> &mods,
331                                         const Symbol &lookUp)
332 {
333   pd_Function *func = findFuncByAddr(lookUp.addr());
334
335   /* sanity check, make sure we have actually seen this address before */
336   assert(func);
337
338   /* build the mangeled and pretty names so that we can add those to the
339    * lookup tables
340    */
341   string name = lookUp.name();
342   string mangled_name = name;
343   const char *p = P_strchr(name.string_of(), ':');
344   if (p) {
345      unsigned nchars = p - name.string_of();
346      mangled_name = string(name.string_of(), nchars);
347   }
348
349   string demangled;
350   if (!buildDemangledName(mangled_name, demangled)) 
351     demangled = mangled_name;
352
353   /* add the names to the vectors in the function object */
354   func->addSymTabName(mangled_name);
355   func->addPrettyName(demangled);
356
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;
360
361   if(!funcsByPretty.find(demangled, funcsByPrettyEntry)) {
362     funcsByPrettyEntry = new vector<pd_Function*>;
363     funcsByPretty[demangled] = funcsByPrettyEntry;
364   }
365     
366   assert(funcsByPrettyEntry);
367   (*funcsByPrettyEntry).push_back(func);
368
369   if (!funcsByMangled.find(mangled_name, funcsByMangledEntry)) {
370     funcsByMangledEntry = new vector<pd_Function*>;
371     funcsByMangled[mangled_name] = funcsByMangledEntry;
372   }
373
374   assert(funcsByMangledEntry);
375   (*funcsByMangledEntry).push_back(func);
376 }
377
378 /*
379  * Add all the functions (*) in the list of symbols to our data
380  * structures. 
381  *
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). 
384  */
385
386 bool image::addAllFunctions(vector<Symbol> &mods)
387 {
388   Symbol lookUp;
389   string symString;
390
391   // is_a_out is a member variable
392   Symbol mainFuncSymbol;  //Keeps track of info on "main" function
393
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;
400     is_a_out = true;
401   }
402   else
403     is_a_out = false;
404
405   // Checking for libdyninstRT (DYNINSTinit())
406   if (linkedFile.get_symbol(symString="DYNINSTinit",  lookUp) ||
407       linkedFile.get_symbol(symString="_DYNINSTinit", lookUp))
408     is_libdyninstRT = true;
409   else
410     is_libdyninstRT = false;
411   
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);
419       continue;
420     }
421     if (is_a_out && 
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?
425       continue;
426     if (lookUp.type() == Symbol::PDST_FUNCTION) {
427       if (!isValidAddress(lookUp.addr())) {
428         string msg;
429         char tempBuffer[40];
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);
435         return false;
436       }
437       addOneFunction(mods, lookUp);
438     }
439   }
440
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
448       continue;
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);
454     }
455   }
456   return true;
457 }
458
459 bool image::addAllVariables()
460 {
461 /* Eventually we'll have to do this on all platforms (because we'll retrieve
462  * the type information here).
463  */
464 #if defined(i386_unknown_nt4_0)  || (defined mips_unknown_ce2_11) //ccw 20 july 2000 : 29 mar 2001
465   string mangledName; 
466   Symbol symInfo;
467
468   for(SymbolIter symIter(linkedFile); symIter; symIter++) {
469      const string &mangledName = symIter.currkey();
470      const Symbol &symInfo = symIter.currval();
471
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));
479       } else {
480           vector<string> *varEntry = new vector<string>;
481           (*varEntry).push_back(string(mangledName));
482           varsByPretty[unmangledName] = varEntry;
483       }
484       if (name) free(name);
485     }
486   }
487 #endif
488   return true;
489 }
490
491 /*
492  * will search for symbol NAME or _NAME
493  * returns false on failure 
494  */
495 bool image::findInternalSymbol(const string &name, 
496                                const bool warn, 
497                                internalSym &ret_sym)
498 {
499    Symbol lookUp;
500
501    if(linkedFile.get_symbol(name,lookUp)){
502       ret_sym = internalSym(lookUp.addr(),name); 
503       return true;
504    }
505    else {
506        string new_sym;
507        new_sym = string("_") + name;
508        if(linkedFile.get_symbol(new_sym,lookUp)){
509           ret_sym = internalSym(lookUp.addr(),name); 
510           return true;
511        }
512    } 
513    if(warn){
514       string msg;
515       msg = string("Unable to find symbol: ") + name;
516       statusLine(msg.string_of());
517       showErrorCallback(28, msg);
518    }
519    return false;
520 }
521
522 bool image::findInternalByPrefix(const string &prefix, 
523                                  vector<Symbol> &found) const
524 {
525   bool flag = false;
526   /*
527     Go through all defined symbols and return those which
528     match the prefix given 
529   */
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())))
534       {
535         found.push_back(lookUp);
536         flag = true;
537       }
538   }
539   return flag;
540 }
541
542 pdmodule *image::findModule(const string &name, bool find_if_excluded)
543 {
544   unsigned i;
545
546   //cerr << "image::findModule " << name << " , " << find_if_excluded
547   //     << " called" << endl;
548
549   if (modsByFileName.defines(name)) {
550     //cerr << " (image::findModule) found module in modsByFileName" << endl;
551     return (modsByFileName[name]);
552   }
553   else if (modsByFullName.defines(name)) {
554     //cerr << " (image::findModule) found module in modsByFullName" << endl;
555     return (modsByFullName[name]);
556   }
557   
558   // if also looking for excluded functions, check through 
559   //  excludedFunction list to see if any match function by FullName
560   //  or FileName....
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];
567         }
568       }
569   }
570
571   //cerr << " (image::findModule) did not find module, returning NULL" << endl;
572   return NULL;
573 }
574
575 /* 
576  * return 0 if symbol <symname> exists in image, non-zero if it does not
577  */
578 bool image::symbolExists(const string &symname)
579 {
580   pd_Function *dummy = findFuncByName(symname);
581   return (dummy != NULL);
582 }
583
584 #ifndef BPATCH_LIBRARY
585 void image::postProcess(const string pifname)
586 {
587   FILE *Fil;
588   string fname, errorstr;
589   char key[5000];
590   char tmp1[5000], abstraction[500];
591   resource *parent;
592
593   return;
594
595   /* What file to open? */
596   if (!(pifname == (char*)NULL)) {
597     fname = pifname;
598   } else {
599     fname = desc_->file() + ".pif";
600   }
601
602   /* Open the file */
603   Fil = P_fopen(fname.string_of(), "r");
604
605   if (Fil == NULL) {
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); 
610     return;
611   }
612
613   /* Process the file */
614   while (!feof(Fil)) {
615     fscanf(Fil, "%s", key);
616     switch (key[0]) {
617     case 'M':
618       /* Ignore mapping information for right now */
619       fgets(tmp1, 5000, Fil);
620       break;
621     case 'R':
622 #ifndef BPATCH_LIBRARY
623       /* Create a new resource */
624       fscanf(Fil, "%s {", abstraction);
625       parent = rootResource;
626       do {
627         fscanf(Fil, "%s", tmp1);
628         if (tmp1[0] != '}') {
629           parent = resource::newResource(parent, NULL,
630                                          abstraction,
631                                          tmp1, timeStamp::ts1970(),
632                                          nullString, // uniqifier
633                                          MDL_T_STRING,
634                                          true);
635         } else {
636           parent = NULL;
637         }
638       } while (parent != NULL);
639 #endif
640       break;
641     default:
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);
646       break;
647     }
648   }
649   return;
650 }
651 #endif
652
653 void image::defineModules() {
654   unsigned i;
655
656   string pds; pdmodule *mod;
657   dictionary_hash_iter<string, pdmodule*> mi(modsByFileName);
658
659   while (mi.next(pds, mod)){
660     mod->define();
661   }
662
663   for(i=0;i<excludedMods.size();i++) {
664     mod = excludedMods[i];
665     mod->define();
666   }
667
668 #ifdef DEBUG_MDL
669   char buffer[100];
670   ostrstream osb(buffer, 100, ios::out);
671   osb << "IMAGE_" << name() << "__" << getpid() << ends;
672   ofstream of(buffer, ios::app);
673
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;
678   }
679   
680 #endif
681 }
682
683 #ifndef BPATCH_LIBRARY
684 void image::FillInCallGraphStatic(process *proc)
685 {
686   unsigned i;
687   string pds;
688   pdmodule *mod;
689   dictionary_hash_iter<string, pdmodule*> mi(modsByFileName);
690   string buffer;
691
692   // define call graph relations for all non-excluded modules.
693   while (mi.next(pds, mod)){
694     buffer = "building call graph module: " +
695       mod->fileName();
696     statusLine(buffer.string_of());
697     mod->FillInCallGraphStatic(proc);
698   }
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: " +
707       mod->fileName();
708     statusLine(buffer.string_of());
709     mod->FillInCallGraphStatic(proc);
710   }
711 }
712 #endif
713
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 
721 //   do that....
722
723
724 void pdmodule::define() {
725 #ifndef BPATCH_LIBRARY
726   resource *moduleResource = NULL;
727 #endif
728 #ifdef DEBUG_MODS
729   char buffer[100];
730   ostrstream osb(buffer, 100, ios::out);
731   osb << "MODS_" << exec->name() << "__" << getpid() << ends;
732   ofstream of(buffer, ios::app);
733 #endif
734
735   unsigned f_size = funcs.size();
736
737   for (unsigned f=0; f<f_size; f++) {
738 #ifndef BPATCH_LIBRARY
739     pd_Function *pdf = funcs[f];
740 #ifdef DEBUG_MODS
741     of << fileName << ":  " << pdf->prettyName() <<  "  "
742         << pdf->addr() << endl;
743 #endif
744     // ignore line numbers for now 
745
746     //if (!(pdf->isLibTag())) {
747     if (1) {
748       // see if we have created module yet.
749       if (!moduleResource) {
750         moduleResource = resource::newResource(moduleRoot, this,
751                                             nullString, // abstraction
752                                             fileName(), // name
753                                             timeStamp::ts1970(), // creation time
754                                             string(), // unique-ifier
755                                             MDL_T_MODULE,
756                                             false);
757       }
758
759       pdf->SetFuncResource(resource::newResource(moduleResource, pdf,
760                                                  nullString, // abstraction
761                                                  pdf->prettyName(), 
762                                                  timeStamp::ts1970(),
763                                                  nullString, // uniquifier
764                                                  MDL_T_PROCEDURE,
765                                                  false));                  
766       
767     }
768 #endif
769   }
770
771 #ifndef BPATCH_LIBRARY
772   resource::send_now();
773 #endif
774 }
775
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)
782 {
783     tp->CallGraphSetEntryFuncCallback(exe_name, r);
784 }
785
786 void CallGraphAddProgramCallback(string name){
787   tp->CallGraphAddProgramCallback(name);
788 }
789
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)
794 {
795   tp->CallGraphFillDone(exe_name);
796 }
797
798 //send message to the data manager in order to register a function 
799 //in the call graph.
800 void AddCallGraphNodeCallback(string exe_name, string r)
801 {
802     tp->AddCallGraphNodeCallback(exe_name, r);
803 }
804
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) 
809 {
810     tp->AddCallGraphStaticChildrenCallback(exe_name, r, children);
811 }
812
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();
825   
826   string resource_full_name;
827   
828   // for each INSTRUMENTABLE function in the module (including excluded 
829   //  functions, but NOT uninstrumentable ones)....
830   
831   for (f=0;f<f_size;f++) {
832     pdf = funcs[f];
833     
834     callees_as_strings.resize(0);
835     
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....
844     assert(r != NULL);
845     
846     // get list of statically determined call destinations from pdf,
847     //  using the process info to help fill in calls througb PLT
848     //  entries....
849     pdf->getStaticCallees(proc, callees); 
850     
851     // and convert them into a list of resources....
852     for (g=0;g<callees.size();g++) {
853       callee = callees[g];
854       assert(callee);
855       
856       //if the funcResource is not set, then the function must be
857       //uninstrumentable, so we don't want to notify the front end
858       //of its existence
859       if(callee->FuncResourceSet()){
860         callee_full_name = callee->ResourceFullName();
861         
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;
867         }
868       
869     }//end for
870     
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,
876                                        callees_as_strings);
877
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);
884         break;
885       }
886     }
887   }
888 }
889 #endif // ndef BPATCH_LIBRARY
890
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() {
898     unsigned int i;    
899     includedFunctions.resize(0);
900     vector<function_base *> *temp;
901     vector<pd_Function *> *temp2;
902
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;
910     }
911
912     //cerr << " (image::getIncludedFunctions) returning : " << endl;
913     //print_func_vector_by_pretty_name(string("  "),
914     //           (vector<function_base*>*)&includedFunctions);
915
916     // what about shared objects????
917     return includedFunctions;
918 }
919 #endif
920
921
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.
926 //  mcheyney 970727
927 vector<function_base *> *pdmodule::getIncludedFunctions() {
928     // laxy construction of some_funcs, as per sharedobject class....
929     // cerr << "pdmodule " << fileName() << " :: getIncludedFunctions called "
930     //      << endl;
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;
935     }
936 #ifdef BPATCH_LIBRARY  //BPatch Library doesn't know about excluded funcs 
937     some_funcs = funcs;
938 #else
939     some_funcs.resize(0);
940     
941     if (filter_excluded_functions(funcs, some_funcs, fileName()) == FALSE) {
942         //cerr << "  about to return NULL";
943         return NULL;
944     }
945 #endif
946     some_funcs_inited = TRUE;
947     
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;
951 }
952
953
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;
959 }
960
961 const vector <pdmodule*> &image::getAllModules() {
962     // reinit all modules to empty vector....
963     allMods.resize(0);
964
965     // and add includedModules && excludedModules to it....
966     VECTOR_APPEND(allMods, includedMods);
967     VECTOR_APPEND(allMods, excludedMods);
968
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);
975     
976     return allMods;
977 }
978
979
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);
985
986     return includedMods;
987 }
988 #endif
989
990 void print_module_vector_by_short_name(string prefix ,
991                                        vector<pdmodule*> *mods) {
992     unsigned int i;
993     pdmodule *mod;
994     for(i=0;i<mods->size();i++) {
995         mod = ((*mods)[i]);
996         cerr << prefix << mod->fileName() << endl;
997     }
998 }
999
1000 void print_func_vector_by_pretty_name(string prefix,
1001                                       vector<function_base *>*funcs) {
1002     unsigned int i;
1003     function_base *func;
1004     for(i=0;i<funcs->size();i++) {
1005       func = ((*funcs)[i]);
1006       cerr << prefix << func->prettyName() << endl;
1007     }
1008 }
1009
1010 // rip module name out of constraint....
1011 // Assumes that constraint is of form module/function, or
1012 // module.... 
1013 string getModuleName(string constraint) {
1014     string ret;
1015
1016     const char *data = constraint.string_of();
1017     const char *first_slash = P_strchr(data, RH_SEPERATOR);
1018     
1019     // no "/", assume string holds module name....
1020     if (first_slash == NULL) {
1021         return constraint;
1022     }    
1023     // has "/", assume everything up to "/" is module name....
1024     return string(data, first_slash - data);
1025 }
1026
1027 // rip function name out of constraint....
1028 // Assumes that constraint is of form module/function, or
1029 // module.... 
1030 string getFunctionName(string constraint) {
1031     string ret;
1032
1033     const char *data = constraint.string_of();
1034     const char *first_slash = P_strchr(data, RH_SEPERATOR);
1035     
1036     // no "/", assume constraint is module only....
1037     if (first_slash == NULL) {
1038         return string("");
1039     }    
1040     // has "/", assume everything after "/" is function....
1041     return string(first_slash+1);
1042 }
1043
1044
1045 #ifndef BPATCH_LIBRARY
1046
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;
1051
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) {
1057         return FALSE;
1058     }
1059     func_constraint_hash_loaded = TRUE;
1060
1061     unsigned i;
1062     for(i=0;i<func_constraints.size();i++) {
1063         func_constraint_hash[func_constraints[i]] = func_constraints[i];
1064     }
1065     return TRUE;
1066 }
1067
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;
1074
1075     string function_name = func->prettyName();
1076     string full_name = module_name + string("/") + function_name;
1077
1078     if (func_constraint_hash_loaded == FALSE) {
1079         if (!cache_func_constraint_hash()) {
1080             return FALSE;
1081         }
1082     }
1083
1084     if (func_constraint_hash.defines(full_name)) {
1085         return TRUE;
1086     }
1087     return FALSE;
1088 }
1089
1090 bool module_is_excluded(pdmodule *module) {
1091     static bool func_constraint_hash_loaded = FALSE;
1092
1093     string full_name = module->fileName();
1094
1095     if (func_constraint_hash_loaded == FALSE) {
1096         if (!cache_func_constraint_hash()) {
1097             return FALSE;
1098         }
1099     }
1100
1101     if (func_constraint_hash.defines(full_name)) {
1102         return TRUE;
1103     }
1104     return FALSE;
1105 }
1106
1107 //
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....
1121
1122 bool filter_excluded_functions(vector<pd_Function*> all_funcs,
1123     vector<pd_Function*>& some_funcs, string module_name) {
1124     unsigned i;
1125
1126     string full_name;
1127     static bool func_constraint_hash_loaded = FALSE;
1128
1129     if (func_constraint_hash_loaded == FALSE) {
1130         if (!cache_func_constraint_hash()) {
1131             return FALSE;
1132         }
1133     }
1134
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];
1141         }
1142     }
1143     
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;
1148     //}
1149     
1150     return TRUE;
1151 }
1152
1153 #endif /* BPATCH_LIBRARY */
1154
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)
1160 {
1161   if (mods.size() == 0) {
1162     modAddr = 0;
1163     modName = defName;
1164     return;
1165   }
1166
1167   Address symAddr = lookUp.addr();
1168   int index;
1169   int start = 0;
1170   int end = mods.size() - 1;
1171   int last = end;
1172   bool found = false;
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();      
1180       found = true;
1181     } else if (symAddr < mods[index].addr()) {
1182       end = index - 1;
1183     } else {
1184       start = index + 1;
1185     }
1186   }
1187   if (!found) { 
1188     // must be (start > end)
1189     modAddr = 0;
1190     modName = defName;
1191     //modName = mods[0].name();
1192     //modAddr = mods[0].addr();
1193   }
1194 }
1195
1196 unsigned int int_addrHash(const Address& addr) {
1197   return (unsigned int)addr;
1198 }
1199
1200 /*
1201  * load an executable:
1202  *   1.) parse symbol table and identify rotuines.
1203  *   2.) scan executable to identify inst points.
1204  *
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
1209  *    physical offset. 
1210  */
1211
1212 image *image::parseImage(fileDescriptor *desc)
1213 {
1214   /*
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.
1218    */
1219   unsigned numImages = allImages.size();
1220
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
1223   // it, basically.
1224   for (unsigned u=0; u<numImages; u++)
1225     if ((*desc) == *(allImages[u]->desc()))
1226       return allImages[u];
1227   /*
1228    * load the symbol table. (This is the a.out format specific routine).
1229    */
1230
1231   if(desc->isSharedObject()) 
1232     statusLine("Processing a shared object file");
1233   else  
1234     statusLine("Processing an executable file");
1235   bool err=false;
1236   
1237   // TODO -- kill process here
1238   image *ret = new image(desc, err);
1239   if (err || !ret) {
1240     if (ret)
1241       delete ret;
1242     return NULL;
1243   }
1244
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];
1254       allImages[i]=ret;
1255       beenReplaced = true;
1256       delete imageTemp;
1257   }
1258   // Add to master image list.
1259 #endif
1260   if (beenReplaced == false) // short-circuit on non-AIX
1261     image::allImages.push_back(ret);
1262
1263   // define all modules.
1264 #ifndef BPATCH_LIBRARY
1265   tp->resourceBatchMode(true);
1266 #endif
1267
1268   statusLine("defining modules");
1269   ret->defineModules();
1270
1271 //  statusLine("ready"); // this shouldn't be here, right? (cuz we're not done, right?)
1272
1273 #ifndef BPATCH_LIBRARY
1274   tp->resourceBatchMode(false);
1275 #endif
1276
1277   return(ret);
1278 }
1279
1280
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
1288
1289 image::image(fileDescriptor *desc, bool &err)
1290   : 
1291     desc_(desc),
1292     is_libdyninstRT(false),
1293     is_a_out(false),
1294     main_call_addr_(0),
1295     linkedFile(desc, pd_log_perror),
1296     knownJumpTargets(int_addrHash, 8192),
1297     includedMods(0),
1298     excludedMods(0),
1299     allMods(0),
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)
1310 {
1311   sharedobj_cerr << "image::image for file name="
1312                  << desc->file() << endl;
1313
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();
1320     
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());
1326     msg += "\n";
1327     logLine(msg.string_of());
1328     err = true;
1329 #ifndef mips_unknown_ce2_11 //ccw 29 mar 2001
1330
1331 #if defined(BPATCH_LIBRARY)
1332     BPatch_reportError(BPatchWarning, 27, msg.string_of()); 
1333 #else
1334     showErrorCallback(27, msg); 
1335 #endif
1336 #endif
1337     return;
1338   }
1339   
1340   string msg;
1341   // give luser some feedback....
1342   msg = string("Parsing object file: ") + desc->file();
1343   statusLine(msg.string_of());
1344   
1345   name_ = extract_pathname_tail(desc->file());
1346   err = false;
1347   
1348   // use the *DUMMY_MODULE* until a module is defined
1349   //pdmodule *dynModule = newModule(DYN_MODULE, 0);
1350   //pdmodule *libModule = newModule(LIBRARY_MODULE, 0);
1351   // TODO -- define inst points in define function ?
1352   
1353   // The functions cannot be verified until all of them have been seen
1354   // because calls out of each function must be tagged as calls to user
1355   // functions or call to "library" functions
1356   
1357   //
1358   // sort the modules by address into a vector to allow a binary search to 
1359   // determine the module that a symbol will map to -- this 
1360   // may be bsd specific....
1361   //
1362   vector <Symbol> tmods;
1363   
1364   for (SymbolIter symIter(linkedFile); symIter; symIter++) {
1365     const Symbol &lookUp = symIter.currval();
1366     if (lookUp.type() == Symbol::PDST_MODULE) {
1367       
1368       const string &lookUpName = lookUp.name();
1369       const char *str = lookUpName.string_of();
1370       assert(str);
1371       int ln = lookUpName.length();
1372       
1373       // directory definition -- ignored for now
1374       if (str[ln-1] != '/') {
1375         tmods.push_back(lookUp);
1376       }
1377     }
1378   }
1379   
1380   // sort the modules by address
1381   statusLine("sorting modules");
1382   VECTOR_SORT(tmods, symbol_compare);
1383   
1384   // remove duplicate entries -- some .o files may have the same 
1385   // address as .C files.  kludge is true for module symbols that 
1386   // I am guessing are modules
1387   vector<Symbol> uniq;
1388   
1389   unsigned int num_zeros = 0;
1390   // must use loop+1 not mods.size()-1 since it is an unsigned compare
1391   //  which could go negative - jkh 5/29/95
1392   for (unsigned loop=0; loop < tmods.size(); loop++) {
1393     if (tmods[loop].addr() == 0) num_zeros++;
1394     if ((loop+1 < tmods.size()) && 
1395         (tmods[loop].addr() == tmods[loop+1].addr())) {
1396       if (!tmods[loop].kludge())
1397         tmods[loop+1] = tmods[loop];
1398     } 
1399     else
1400       uniq.push_back(tmods[loop]);
1401   }
1402   // avoid case where all (ELF) module symbols have address zero
1403   if (num_zeros == tmods.size()) uniq.resize(0);
1404   
1405   // define all of the functions
1406   statusLine("winnowing functions");
1407   
1408   // define all of the functions
1409   if (!addAllFunctions(uniq)) {
1410     err = true;
1411     return;
1412   }
1413   
1414   // ALERT ALERT - Calling on both shared_object && !shared_object path.
1415   //  In origional code, only called in !shared_object case.  Was this 
1416   //  a bug????
1417   // XXX should have a statusLine("retrieving variable information") here,
1418   //     but it's left out for now since addAllVariables only does something
1419   //     when BPATCH_LIBRARY is defined
1420   addAllVariables();
1421   
1422   statusLine("checking call points");
1423   checkAllCallPoints();
1424   
1425   // TODO -- remove duplicates -- see earlier note
1426   dictionary_hash<Address, unsigned> addr_dict(addrHash4);
1427   vector<pd_Function*> temp_vec;
1428   
1429   // question??  Necessary to do same crap to includedFunctions &&
1430   //  excludedFunctions??
1431   unsigned f_size = instrumentableFunctions.size(), index;
1432   for (index=0; index<f_size; index++) {
1433     const Address the_address = 
1434       instrumentableFunctions[index]->getAddress(0);
1435     if (!addr_dict.defines(the_address)) {
1436       addr_dict[the_address] = 1;
1437       temp_vec.push_back(instrumentableFunctions[index]);
1438     }
1439   }
1440   // Memory leak, eh?
1441   instrumentableFunctions = temp_vec;
1442 }
1443
1444 void pdmodule::checkAllCallPoints() {
1445   unsigned fsize = funcs.size();
1446   for (unsigned f=0; f<fsize; f++)
1447       funcs[f]->checkCallPoints();
1448 }
1449
1450
1451 void image::checkAllCallPoints() {
1452   dictionary_hash_iter<string, pdmodule*> di(modsByFullName);
1453   string s; pdmodule *mod;
1454   while (di.next(s, mod))
1455     mod->checkAllCallPoints();
1456 }
1457
1458 pdmodule *image::getOrCreateModule(const string &modName, 
1459                                       const Address modAddr) {
1460   const char *str = modName.string_of();
1461   int len = modName.length();
1462   assert(len>0);
1463
1464   // TODO ignore directory definitions for now
1465   if (str[len-1] == '/') {
1466     return NULL;
1467   } else {
1468     // TODO - navigate ".." and "."
1469     const char *lastSlash = P_strrchr(str, '/');
1470     if (lastSlash)
1471       return (newModule(++lastSlash, modAddr));
1472     else
1473       return (newModule(modName, modAddr));
1474   }
1475 }
1476
1477 // Verify that this is code
1478 // Find the call points
1479 // Find the return address
1480 // TODO -- use an instruction object to remove
1481 // Sets err to false on error, true on success
1482 //
1483 // Note - this must define funcEntry and funcReturn
1484 // 
1485 pd_Function::pd_Function(const string &symbol, const string &pretty, 
1486                        pdmodule *f, Address adr, const unsigned size, 
1487                        const image *owner, bool &err) : 
1488   function_base(symbol, pretty, adr, size),
1489   file_(f),
1490   funcEntry_(0),
1491 #ifndef BPATCH_LIBRARY
1492   funcResource(0),
1493 #endif
1494   relocatable_(false)
1495 {
1496   err = findInstPoints(owner) == false;
1497 }
1498
1499 // This method returns the address at which this function resides
1500 // in the process P, even if it is dynamic, even if it has been
1501 // relocated.  getAddress() (see symtab.h) does not always do this:
1502 // If the function is in a shlib and it has not been relocated,
1503 // getAddress() only returns the relative offset of the function
1504 // within its shlib.  We think that getAddress() should be fixed
1505 // to always return the effective address, but we are not sure
1506 // whether that would boggle any of its 75 callers.  Until that is
1507 // cleared up, call this method. -zandy, Apr-26-1999
1508 Address pd_Function::getEffectiveAddress(const process *p) const {
1509      assert(p);
1510      // Even if the function has been relocated, call it at its
1511      // original address since the call will be redirected to the
1512      // right place anyway.
1513      Address base;
1514      p->getBaseAddress(file()->exec(), base);
1515      return base + addr();
1516 }
1517
1518
1519 /*********************************************************************/
1520 /**** Function lookup (by name or address) routines               ****/
1521 /*********************************************************************/
1522
1523 /* Look up a function by the given address. Four-part method:
1524  * First, do a quick scan of funcsByAddr to see if we get a match
1525  *   -- will match function entry point
1526  * Second, do a complete search of funcsByAddr, using original address
1527  * Finally, check excludedFuncs and nonInstruFuncs
1528  */
1529
1530 pd_Function *image::findFuncByAddr(const Address &addr, 
1531                                    const process *p) const
1532 {
1533   pd_Function *pdf;
1534
1535   // Quick check of funcsByAddr
1536   if (funcsByAddr.find(addr, pdf))
1537     return pdf;
1538   
1539   // Slow check of funcsByAddr
1540   dictionary_hash_iter<Address, pd_Function*> mi(funcsByAddr);
1541   Address adr;
1542   while (mi.next(adr, pdf)) {
1543     if ( p && // getEffectiveAddress asserts p 
1544         (addr>=pdf->getEffectiveAddress(p)) &&
1545          (addr<(pdf->getEffectiveAddress(p)+pdf->size()))
1546          )
1547       return pdf;
1548     if ( (addr>=pdf->getAddress(p)) && 
1549          (addr < (pdf->getAddress(p)+pdf->size()))
1550          )
1551       return pdf;
1552   }
1553
1554   // next, look in excludedFunctions...
1555   dictionary_hash_iter<string, pd_Function*> ex(excludedFunctions);
1556   string str;
1557   while (ex.next(str, pdf)) {
1558     if ( p &&
1559          (addr>=pdf->getEffectiveAddress(p)) &&
1560          (addr<(pdf->getEffectiveAddress(p)+pdf->size()))
1561          )
1562       return pdf;
1563     if ( (addr>=pdf->getAddress(p)) && 
1564          (addr < (pdf->getAddress(p)+pdf->size()))
1565          )
1566       return pdf;
1567   }
1568   
1569   dictionary_hash_iter<string, pd_Function *> ni(notInstruFunctions);
1570   while (ni.next(str, pdf)) {
1571     if ( p &&
1572          (addr>=pdf->getEffectiveAddress(p)) &&
1573          (addr<(pdf->getEffectiveAddress(p)+pdf->size()))
1574          )
1575       return pdf;
1576     if ( (addr>=pdf->getAddress(p)) && 
1577          (addr < (pdf->getAddress(p)+pdf->size()))
1578          ) 
1579       return pdf;
1580   }
1581   return NULL; 
1582 }
1583
1584 // Return the vector of functions associated with a pretty (demangled) name
1585 // Very well might be more than one!
1586
1587 vector <pd_Function *> *image::findFuncVectorByPretty(const string &name)
1588 {
1589   if (funcsByPretty.defines(name))
1590     return funcsByPretty[name];
1591   return NULL;
1592 }
1593
1594 // Return a single function associated with a demangled name. Arbitrarily
1595 // pick the first one.
1596
1597 pd_Function *image::findFuncByPretty(const string &name)
1598 {
1599   vector <pd_Function *> *a;
1600
1601   if (funcsByPretty.defines(name)) {
1602     a = funcsByPretty[name];
1603     return ((*a)[0]);
1604   }
1605   return NULL;
1606 }
1607
1608 pd_Function *image::findFuncByMangled(const string &name)
1609 {
1610   vector <pd_Function *> *a;
1611
1612   if (funcsByMangled.defines(name)) {
1613     a = funcsByMangled[name];
1614     return ((*a)[0]);
1615   }
1616   return NULL;
1617 }
1618
1619 pd_Function *image::findExcludedFunc(const string &name)
1620 {
1621   if (excludedFunctions.defines(name))
1622     return excludedFunctions[name];
1623   return NULL;
1624 }
1625
1626 pd_Function *image::findNonInstruFunc(const string &name)
1627 {
1628   if (notInstruFunctions.defines(name)) 
1629     return notInstruFunctions[name];
1630   return NULL;
1631 }
1632
1633 // TODO -- this is only being used in cases where only one function
1634 // should exist -- should I assert that the vector size <= 1 ?
1635 // mcheyney - should return NULL when function being searched for 
1636 //  is excluded!!!!
1637 // Checks for function in pretty name hash first, then in
1638 //  mangled name hash to better handle many (mangled name) to one 
1639 //  (pretty name) mapping in C++ function names....
1640 pd_Function *image::findFuncByName(const string &name)
1641 {
1642   pd_Function *pdf;
1643
1644   if ( ( pdf = findFuncByPretty(name))) return pdf;
1645
1646   if ( ( pdf = findFuncByMangled(name))) return pdf;
1647
1648   return NULL;
1649 }
1650
1651 // This function supposely is only used to find function that
1652 // is not instrumentable which may not be totally defined.
1653 // Use with caution.  
1654 // NEW - also can be used to find an excluded function....
1655 pd_Function *image::findOneFunctionFromAll(const string &name) {
1656     pd_Function *ret = NULL;
1657     if ( (ret = findFuncByName(name))) 
1658       return ret;
1659
1660     if ( (ret = findNonInstruFunc(name)))
1661       return ret;
1662
1663     if ( (ret = findExcludedFunc(name)))
1664       return ret;
1665
1666     return NULL;
1667 }
1668
1669 #if 0
1670 // Only looks for function by pretty name.
1671 //  Should it also look by mangled name??
1672 bool image::findFunction(const string &name, vector<pd_Function*> &retList,
1673         bool find_if_excluded) {
1674
1675     bool found = FALSE;
1676     if (funcsByPretty.defines(name)) {
1677         retList = *funcsByPretty[name];
1678         found = TRUE;
1679     } 
1680
1681     if (find_if_excluded) {
1682       // should APPEND to retList!!!!
1683       if (excludedFunctions.defines(name))
1684         retList.push_back(excludedFunctions[name]);
1685       found = TRUE;
1686     }
1687     return found;
1688 }
1689 #endif