mods/additions largely under the USE_STL_VECTOR and IBM_BPATCH_COMPAT flags
[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.136 2002/03/19 22:57:22 jaw 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, mod);
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, pdmodule *mod) {
291     notInstruFunctions[func->prettyName()] = func;
292     mod->notInstruFuncs.push_back(func);
293 }
294
295 #ifdef DEBUG_TIME
296 static timer loadTimer;
297 static FILE *timeOut=0;
298 #endif /* DEBUG_TIME */
299
300 // addOneFunction(): find name of enclosing module and define function symbol
301 //
302 // module information comes from one of three sources:
303 //   #1 - debug format (stabs, DWARF, etc.)
304 //   #2 - file format (ELF, COFF)
305 //   #3 - file name (a.out, libXXX.so)
306 // (in order of decreasing reliability)
307 bool image::addOneFunction(vector<Symbol> &mods,
308                            const Symbol &lookUp) 
309 {
310   // find module name
311   Address modAddr = 0;
312   string modName = lookUp.module();
313
314   if (modName == "") {
315     modName = name_ + "_module";
316   } else if (modName == "DEFAULT_MODULE") {
317     string modName_3 = modName;
318     findModByAddr(lookUp, mods, modName, modAddr, modName_3);
319   }
320   
321   pdmodule *use = getOrCreateModule(modName, modAddr);
322   assert(use);
323   return newFunc(use, lookUp.name(), lookUp.addr(), lookUp.size());
324 }
325
326 /*
327  * Add another name for the current function to the names vector in
328  * the function object.  We also need to add the extra names to the
329  * lookup hash tables
330  */
331 void image::addMultipleFunctionNames(vector<Symbol> &mods,
332                                         const Symbol &lookUp)
333 {
334   pd_Function *func = findFuncByAddr(lookUp.addr());
335
336   /* sanity check, make sure we have actually seen this address before */
337   assert(func);
338
339   /* build the mangeled and pretty names so that we can add those to the
340    * lookup tables
341    */
342   string name = lookUp.name();
343   string mangled_name = name;
344   const char *p = P_strchr(name.string_of(), ':');
345   if (p) {
346      unsigned nchars = p - name.string_of();
347      mangled_name = string(name.string_of(), nchars);
348   }
349
350   string demangled;
351   if (!buildDemangledName(mangled_name, demangled)) 
352     demangled = mangled_name;
353
354   /* add the names to the vectors in the function object */
355   func->addSymTabName(mangled_name);
356   func->addPrettyName(demangled);
357
358   /* now we add the names and the function object to the hash tables */
359   vector<pd_Function*> *funcsByPrettyEntry = NULL;
360   vector<pd_Function*> *funcsByMangledEntry = NULL;
361
362   if(!funcsByPretty.find(demangled, funcsByPrettyEntry)) {
363     funcsByPrettyEntry = new vector<pd_Function*>;
364     funcsByPretty[demangled] = funcsByPrettyEntry;
365   }
366     
367   assert(funcsByPrettyEntry);
368   (*funcsByPrettyEntry).push_back(func);
369
370   if (!funcsByMangled.find(mangled_name, funcsByMangledEntry)) {
371     funcsByMangledEntry = new vector<pd_Function*>;
372     funcsByMangled[mangled_name] = funcsByMangledEntry;
373   }
374
375   assert(funcsByMangledEntry);
376   (*funcsByMangledEntry).push_back(func);
377 }
378
379 /*
380  * Add all the functions (*) in the list of symbols to our data
381  * structures. 
382  *
383  * We do a search for a "main" symbol (a couple of variants), and
384  * if found we flag this image as the executable (a.out). 
385  */
386
387 bool image::addAllFunctions(vector<Symbol> &mods)
388 {
389   Symbol lookUp;
390   string symString;
391
392   // is_a_out is a member variable
393   Symbol mainFuncSymbol;  //Keeps track of info on "main" function
394
395   //Checking "main" function names in same order as in the inst-*.C files
396   if (linkedFile.get_symbol(symString="main",     lookUp) ||
397       linkedFile.get_symbol(symString="_main",    lookUp) ||
398       linkedFile.get_symbol(symString="WinMain",  lookUp) ||
399       linkedFile.get_symbol(symString="_WinMain", lookUp)) {
400     mainFuncSymbol = lookUp;
401     is_a_out = true;
402   }
403   else
404     is_a_out = false;
405
406   // Checking for libdyninstRT (DYNINSTinit())
407   if (linkedFile.get_symbol(symString="DYNINSTinit",  lookUp) ||
408       linkedFile.get_symbol(symString="_DYNINSTinit", lookUp))
409     is_libdyninstRT = true;
410   else
411     is_libdyninstRT = false;
412   
413   // find the real functions -- those with the correct type in the symbol table
414   for(SymbolIter symIter(linkedFile); symIter;symIter++) {
415     const Symbol &lookUp = symIter.currval();
416     const char *np = lookUp.name().string_of();
417     if (linkedFile.isEEL() && np[0] == '.')
418          /* ignore these EEL symbols; we don't understand their values */
419          continue; 
420     if (funcsByAddr.defines(lookUp.addr())) {
421       // We have already seen a function at this addr. add a second name
422       // for this function.
423       addMultipleFunctionNames(mods, lookUp);
424       continue;
425     }
426     if (is_a_out && 
427         (lookUp.addr() == mainFuncSymbol.addr()) &&
428         (lookUp.name() != mainFuncSymbol.name()))
429       // Wait for main to appear. Couldn't we just add main to start with?
430       continue;
431     if (lookUp.type() == Symbol::PDST_FUNCTION) {
432       if (!isValidAddress(lookUp.addr())) {
433         string msg;
434         char tempBuffer[40];
435         sprintf(tempBuffer,"0x%lx",lookUp.addr());
436         msg = string("Function ") + lookUp.name() + string(" has bad address ")
437           + string(tempBuffer);
438         statusLine(msg.string_of());
439         showErrorCallback(29, msg);
440         return false;
441       }
442       addOneFunction(mods, lookUp);
443     }
444   }
445
446   // now find the pseudo functions -- this gets ugly
447   // kludge has been set if the symbol could be a function
448   // WHERE DO WE USE THESE KLUDGES? WHAT PLATFORM???
449   for(SymbolIter symIter2(linkedFile);symIter2;symIter2++) {
450     lookUp = symIter2.currval();
451     if (funcsByAddr.defines(lookUp.addr()))
452       // Already defined a symbol at this addr
453       continue;
454     if ((lookUp.type() == Symbol::PDST_OBJECT) && lookUp.kludge()) {
455       //logLine(P_strdup(symString.string_of()));
456       // Figure out where this happens
457       cerr << "Found <KLUDGE> function " << lookUp.name().string_of() << endl;
458       addOneFunction(mods, lookUp);
459     }
460   }
461   return true;
462 }
463
464 bool image::addAllVariables()
465 {
466 /* Eventually we'll have to do this on all platforms (because we'll retrieve
467  * the type information here).
468  */
469 #if defined(i386_unknown_nt4_0)  || (defined mips_unknown_ce2_11) //ccw 20 july 2000 : 29 mar 2001
470   string mangledName; 
471   Symbol symInfo;
472
473   for(SymbolIter symIter(linkedFile); symIter; symIter++) {
474      const string &mangledName = symIter.currkey();
475      const Symbol &symInfo = symIter.currval();
476
477     if (symInfo.type() == Symbol::PDST_OBJECT) {
478       char *name = cplus_demangle((char *)mangledName.string_of(), 0);
479       const char *unmangledName;
480       if (name) unmangledName = name;
481       else unmangledName = mangledName.string_of();
482       if (varsByPretty.defines(unmangledName)) {
483           (*(varsByPretty[unmangledName])).push_back(string(mangledName));
484       } else {
485           vector<string> *varEntry = new vector<string>;
486           (*varEntry).push_back(string(mangledName));
487           varsByPretty[unmangledName] = varEntry;
488       }
489       if (name) free(name);
490     }
491   }
492 #endif
493   return true;
494 }
495
496 /*
497  * will search for symbol NAME or _NAME
498  * returns false on failure 
499  */
500 bool image::findInternalSymbol(const string &name, 
501                                const bool warn, 
502                                internalSym &ret_sym)
503 {
504    Symbol lookUp;
505
506    if(linkedFile.get_symbol(name,lookUp)){
507       ret_sym = internalSym(lookUp.addr(),name); 
508       return true;
509    }
510    else {
511        string new_sym;
512        new_sym = string("_") + name;
513        if(linkedFile.get_symbol(new_sym,lookUp)){
514           ret_sym = internalSym(lookUp.addr(),name); 
515           return true;
516        }
517    } 
518    if(warn){
519       string msg;
520       msg = string("Unable to find symbol: ") + name;
521       statusLine(msg.string_of());
522       showErrorCallback(28, msg);
523    }
524    return false;
525 }
526
527 bool image::findInternalByPrefix(const string &prefix, 
528                                  vector<Symbol> &found) const
529 {
530   bool flag = false;
531   /*
532     Go through all defined symbols and return those which
533     match the prefix given 
534   */
535   for(SymbolIter symIter(linkedFile); symIter;symIter++) {
536     const Symbol &lookUp = symIter.currval();
537     if (!strncmp(prefix.string_of(), lookUp.name().string_of(),
538                  strlen(prefix.string_of())))
539       {
540         found.push_back(lookUp);
541         flag = true;
542       }
543   }
544   return flag;
545 }
546
547 pdmodule *image::findModule(const string &name, bool find_if_excluded)
548 {
549   unsigned i;
550
551   //cerr << "image::findModule " << name << " , " << find_if_excluded
552   //     << " called" << endl;
553
554   if (modsByFileName.defines(name)) {
555     //cerr << " (image::findModule) found module in modsByFileName" << endl;
556     return (modsByFileName[name]);
557   }
558   else if (modsByFullName.defines(name)) {
559     //cerr << " (image::findModule) found module in modsByFullName" << endl;
560     return (modsByFullName[name]);
561   }
562   
563   // if also looking for excluded functions, check through 
564   //  excludedFunction list to see if any match function by FullName
565   //  or FileName....
566   if (find_if_excluded) {
567       for(i=0;i<excludedMods.size();i++) {
568         if ((excludedMods[i]->fileName() == name) ||
569                   (excludedMods[i]->fullName() == name)) {
570           //cerr << " (image::findModule) found module in excludedMods" << endl;
571           return excludedMods[i];
572         }
573       }
574   }
575
576   //cerr << " (image::findModule) did not find module, returning NULL" << endl;
577   return NULL;
578 }
579
580 /* 
581  * return 0 if symbol <symname> exists in image, non-zero if it does not
582  */
583 bool image::symbolExists(const string &symname)
584 {
585   pd_Function *dummy = findFuncByName(symname);
586   return (dummy != NULL);
587 }
588
589 #ifndef BPATCH_LIBRARY
590 void image::postProcess(const string pifname)
591 {
592   FILE *Fil;
593   string fname, errorstr;
594   char key[5000];
595   char tmp1[5000], abstraction[500];
596   resource *parent;
597
598   return;
599
600   /* What file to open? */
601   if (!(pifname == (char*)NULL)) {
602     fname = pifname;
603   } else {
604     fname = desc_->file() + ".pif";
605   }
606
607   /* Open the file */
608   Fil = P_fopen(fname.string_of(), "r");
609
610   if (Fil == NULL) {
611     errorstr = string("Tried to open PIF file ") + fname;
612     errorstr += string(", but could not (continuing)\n");
613     logLine(P_strdup(errorstr.string_of()));
614     showErrorCallback(35, errorstr); 
615     return;
616   }
617
618   /* Process the file */
619   while (!feof(Fil)) {
620     fscanf(Fil, "%s", key);
621     switch (key[0]) {
622     case 'M':
623       /* Ignore mapping information for right now */
624       fgets(tmp1, 5000, Fil);
625       break;
626     case 'R':
627 #ifndef BPATCH_LIBRARY
628       /* Create a new resource */
629       fscanf(Fil, "%s {", abstraction);
630       parent = rootResource;
631       do {
632         fscanf(Fil, "%s", tmp1);
633         if (tmp1[0] != '}') {
634           parent = resource::newResource(parent, NULL,
635                                          abstraction,
636                                          tmp1, timeStamp::ts1970(),
637                                          nullString, // uniqifier
638                                          MDL_T_STRING,
639                                          true);
640         } else {
641           parent = NULL;
642         }
643       } while (parent != NULL);
644 #endif
645       break;
646     default:
647       errorstr = string("Ignoring bad line key (") + fname;
648       errorstr += string(") in file %s\n");
649       logLine(P_strdup(errorstr.string_of()));
650       fgets(tmp1, 5000, Fil);
651       break;
652     }
653   }
654   return;
655 }
656 #endif
657
658 void image::defineModules() {
659   unsigned i;
660
661   string pds; pdmodule *mod;
662   dictionary_hash_iter<string, pdmodule*> mi(modsByFileName);
663
664   while (mi.next(pds, mod)){
665     mod->define();
666   }
667
668   for(i=0;i<excludedMods.size();i++) {
669     mod = excludedMods[i];
670     mod->define();
671   }
672
673 #ifdef DEBUG_MDL
674   char buffer[100];
675   ostrstream osb(buffer, 100, ios::out);
676   osb << "IMAGE_" << name() << "__" << getpid() << ends;
677   ofstream of(buffer, ios::app);
678
679   of << "INCLUDED FUNCTIONS\n";
680   for (unsigned ni=0; ni<includedFunctions.size(); ni++) {
681     of << includedFunctions[ni]->prettyName() << "\t\t" 
682        << includedFunctions[ni]->addr() << "\t\t" << endl;
683   }
684   
685 #endif
686 }
687
688 #ifndef BPATCH_LIBRARY
689 void image::FillInCallGraphStatic(process *proc)
690 {
691   unsigned i;
692   string pds;
693   pdmodule *mod;
694   dictionary_hash_iter<string, pdmodule*> mi(modsByFileName);
695   string buffer;
696
697   // define call graph relations for all non-excluded modules.
698   while (mi.next(pds, mod)){
699     buffer = "building call graph module: " +
700       mod->fileName();
701     statusLine(buffer.string_of());
702     mod->FillInCallGraphStatic(proc);
703   }
704   // also define call graph relations for all excluded modules.
705   //  Call graph gets information about both included and excluded 
706   //  modules and functions, and allows the DM and PC to decide whether
707   //  to look at a given function based on whether the function is 
708   //  included or excluded....
709   for(i=0;i<excludedMods.size();i++) {
710     mod = excludedMods[i];
711     buffer = "building call graph module: " +
712       mod->fileName();
713     statusLine(buffer.string_of());
714     mod->FillInCallGraphStatic(proc);
715   }
716 }
717 #endif
718
719 //  Comments on what this does would be nice....
720 //  Appears to run over a pdmodule, after all code in it has been processed
721 //   and parsed into functions, and define a resource for the module + a 
722 //   resource for every function found in the module (apparently includes 
723 //   excluded functions, but not uninstrumentable ones)....
724 //  Can't directly register call graph relationships here as resources
725 //   are being defined, because need all resources defined to 
726 //   do that....
727
728
729 void pdmodule::define() {
730 #ifndef BPATCH_LIBRARY
731   resource *moduleResource = NULL;
732 #endif
733 #ifdef DEBUG_MODS
734   char buffer[100];
735   ostrstream osb(buffer, 100, ios::out);
736   osb << "MODS_" << exec->name() << "__" << getpid() << ends;
737   ofstream of(buffer, ios::app);
738 #endif
739
740   unsigned f_size = funcs.size();
741
742   for (unsigned f=0; f<f_size; f++) {
743 #ifndef BPATCH_LIBRARY
744     pd_Function *pdf = funcs[f];
745 #ifdef DEBUG_MODS
746     of << fileName << ":  " << pdf->prettyName() <<  "  "
747         << pdf->addr() << endl;
748 #endif
749     // ignore line numbers for now 
750
751     //if (!(pdf->isLibTag())) {
752     if (1) {
753       // see if we have created module yet.
754       if (!moduleResource) {
755         moduleResource = resource::newResource(moduleRoot, this,
756                                             nullString, // abstraction
757                                             fileName(), // name
758                                             timeStamp::ts1970(), // creation time
759                                             string(), // unique-ifier
760                                             MDL_T_MODULE,
761                                             false);
762       }
763
764       pdf->SetFuncResource(resource::newResource(moduleResource, pdf,
765                                                  nullString, // abstraction
766                                                  pdf->prettyName(), 
767                                                  timeStamp::ts1970(),
768                                                  nullString, // uniquifier
769                                                  MDL_T_PROCEDURE,
770                                                  false));                  
771       
772     }
773 #endif
774   }
775
776 #ifndef BPATCH_LIBRARY
777   resource::send_now();
778 #endif
779 }
780
781 // Why is this in symtab.C?
782 #ifndef BPATCH_LIBRARY
783 // send message to data manager to specify the entry function for the
784 //  call graph corresponding to a given image.  r should hold the 
785 //  FULL resourcename of the entry function (e.g. "/Code/module.c/main")
786 void CallGraphSetEntryFuncCallback(string exe_name, string r)
787 {
788     tp->CallGraphSetEntryFuncCallback(exe_name, r);
789 }
790
791 void CallGraphAddProgramCallback(string name){
792   tp->CallGraphAddProgramCallback(name);
793 }
794
795 //send message to the data manager, notifying it that all of the statically
796 //determinable functions have been registered with the call graph. The
797 //data manager will then be able to create the call graph.
798 void CallGraphFillDone(string exe_name)
799 {
800   tp->CallGraphFillDone(exe_name);
801 }
802
803 //send message to the data manager in order to register a function 
804 //in the call graph.
805 void AddCallGraphNodeCallback(string exe_name, string r)
806 {
807     tp->AddCallGraphNodeCallback(exe_name, r);
808 }
809
810 //send a message to the data manager in order register a the function
811 //calls made by a function (whose name is stored in r).
812 void AddCallGraphStaticChildrenCallback(string exe_name, string r,
813                                         const vector<string> children) 
814 {
815     tp->AddCallGraphStaticChildrenCallback(exe_name, r, children);
816 }
817
818 // Called across all modules (in a given image) to define the call
819 //  graph relationship between functions.
820 // Must be called AFTER all functions in all modules (in image) are
821 //  registered as resource (e.g. w/ pdmodule::define())....
822 void pdmodule::FillInCallGraphStatic(process *proc) {
823   pd_Function *pdf, *callee;
824   vector <pd_Function *>callees;
825   resource *r , *callee_as_resource;
826   string callee_full_name;
827   vector <string>callees_as_strings;
828   vector <instPoint*> callPoints; 
829   unsigned f, g,i, f_size = funcs.size();
830   
831   string resource_full_name;
832   
833   // for each INSTRUMENTABLE function in the module (including excluded 
834   //  functions, but NOT uninstrumentable ones)....
835   
836   for (f=0;f<f_size;f++) {
837     pdf = funcs[f];
838     
839     callees_as_strings.resize(0);
840     
841     // Translate from function name to resource *.
842     // Note that this probably is NOT the correct translation, as 
843     //  function names are not necessarily unique, but the paradyn
844     //  code assumes that they are in several places (e.g. 
845     //  resource::findResource)....
846     resource_full_name = pdf->ResourceFullName();
847     r = resource::findResource(resource_full_name);
848     // functions registered under pretty name....
849     assert(r != NULL);
850     
851     // get list of statically determined call destinations from pdf,
852     //  using the process info to help fill in calls througb PLT
853     //  entries....
854     pdf->getStaticCallees(proc, callees); 
855     
856     // and convert them into a list of resources....
857     for (g=0;g<callees.size();g++) {
858       callee = callees[g];
859       assert(callee);
860       
861       //if the funcResource is not set, then the function must be
862       //uninstrumentable, so we don't want to notify the front end
863       //of its existence
864       if(callee->FuncResourceSet()){
865         callee_full_name = callee->ResourceFullName();
866         
867         // if callee->funcResource has been set, then it should have 
868         //  been registered as a resource.... 
869         callee_as_resource = resource::findResource(callee_full_name);
870         assert(callee_as_resource);
871         callees_as_strings += callee_full_name;
872         }
873       
874     }//end for
875     
876     // register that callee_resources holds list of resource*s 
877     //  describing children of resource r....
878     string exe_name = proc->getImage()->file();
879     AddCallGraphNodeCallback(exe_name, resource_full_name);
880     AddCallGraphStaticChildrenCallback(exe_name, resource_full_name,
881                                        callees_as_strings);
882
883     //Locate the dynamic call sites within the function, and notify 
884     //the front end as to their existence
885     callPoints = pdf->funcCalls(proc);
886     for(i = 0; i < callPoints.size(); i++){
887       if(proc->isDynamicCallSite(callPoints[i])){
888         tp->CallGraphAddDynamicCallSiteCallback(exe_name, resource_full_name);
889         break;
890       }
891     }
892   }
893 }
894 #endif // ndef BPATCH_LIBRARY
895
896 #ifndef BPATCH_LIBRARY
897 // as per getAllFunctions, but filters out those excluded with 
898 // e.g. mdl "exclude" command....
899 // to clarify a function should NOT be returned from here if its 
900 //  module is excluded (with exclude "/Code/module") or if it
901 //  is excluded (with exclude "/Code/module/function"). 
902 const vector<pd_Function*> &image::getIncludedFunctions() {
903     unsigned int i;    
904     includedFunctions.resize(0);
905     vector<function_base *> *temp;
906     vector<pd_Function *> *temp2;
907
908     //cerr << "image::getIncludedFunctions called, name = " << name () << endl;
909     //cerr << " includedMods = " << endl;
910     //print_module_vector_by_short_name(string("  "), &includedMods);
911     for (i=0;i<includedMods.size();i++) {
912          temp = includedMods[i]->getIncludedFunctions();
913          temp2 = (vector<pd_Function *> *) temp;
914          includedFunctions += *temp2;
915     }
916
917     //cerr << " (image::getIncludedFunctions) returning : " << endl;
918     //print_func_vector_by_pretty_name(string("  "),
919     //           (vector<function_base*>*)&includedFunctions);
920
921     // what about shared objects????
922     return includedFunctions;
923 }
924 #endif
925
926
927 // get all functions in module which are not "excluded" (e.g.
928 //  with mdl "exclude" command.  
929 // Assed to provide support for mdl "exclude" on functions in
930 //  statically linked objects.
931 //  mcheyney 970727
932 vector<function_base *> *pdmodule::getIncludedFunctions() {
933     // laxy construction of some_funcs, as per sharedobject class....
934     // cerr << "pdmodule " << fileName() << " :: getIncludedFunctions called "
935     //      << endl;
936     if (some_funcs_inited == TRUE) {
937         //cerr << "  about to return : " << endl;
938         //print_func_vector_by_pretty_name(string("  "), (vector<function_base *>*)&some_funcs);
939         return (vector<function_base *>*)&some_funcs;
940     }
941 #ifdef BPATCH_LIBRARY  //BPatch Library doesn't know about excluded funcs 
942     some_funcs = funcs;
943 #else
944     some_funcs.resize(0);
945     
946     if (filter_excluded_functions(funcs, some_funcs, fileName()) == FALSE) {
947         //cerr << "  about to return NULL";
948         return NULL;
949     }
950 #endif
951     some_funcs_inited = TRUE;
952     
953     //cerr << "  about to return : " << endl;
954     //print_func_vector_by_pretty_name(string("  "),(vector<function_base *>*) &some_funcs);
955     return (vector<function_base *>*)&some_funcs;
956 }
957
958
959 const vector<pd_Function*> &image::getAllFunctions() {
960     //cerr << "pdmodule::getAllFunctions() called, about to return instrumentableFunctions = " << endl;
961     //print_func_vector_by_pretty_name(string("  "),
962     //        (vector<function_base*>*)&instrumentableFunctions);
963     return instrumentableFunctions;
964 }
965
966 const vector <pdmodule*> &image::getAllModules() {
967     // reinit all modules to empty vector....
968     allMods.resize(0);
969
970     // and add includedModules && excludedModules to it....
971     VECTOR_APPEND(allMods, includedMods);
972     VECTOR_APPEND(allMods, excludedMods);
973
974     //cerr << "image::getAllModules called" << endl;
975     //cerr << " about to return sum of includedMods and excludedMods" << endl;
976     //cerr << " includedMods : " << endl;
977     //print_module_vector_by_short_name(string("  "), &includedMods);
978     //cerr << " excludedMods : " << endl;
979     //print_module_vector_by_short_name(string("  "), &excludedMods);
980     
981     return allMods;
982 }
983
984
985 #ifndef BPATCH_LIBRARY
986 const vector <pdmodule*> &image::getIncludedModules() {
987     //cerr << "image::getIncludedModules called" << endl;
988     //cerr << " about to return includedMods = " << endl;
989     //print_module_vector_by_short_name(string("  "), &includedMods);
990
991     return includedMods;
992 }
993 #endif
994
995 void print_module_vector_by_short_name(string prefix ,
996                                        vector<pdmodule*> *mods) {
997     unsigned int i;
998     pdmodule *mod;
999     for(i=0;i<mods->size();i++) {
1000         mod = ((*mods)[i]);
1001         cerr << prefix << mod->fileName() << endl;
1002     }
1003 }
1004
1005 void print_func_vector_by_pretty_name(string prefix,
1006                                       vector<function_base *>*funcs) {
1007     unsigned int i;
1008     function_base *func;
1009     for(i=0;i<funcs->size();i++) {
1010       func = ((*funcs)[i]);
1011       cerr << prefix << func->prettyName() << endl;
1012     }
1013 }
1014
1015 // rip module name out of constraint....
1016 // Assumes that constraint is of form module/function, or
1017 // module.... 
1018 string getModuleName(string constraint) {
1019     string ret;
1020
1021     const char *data = constraint.string_of();
1022     const char *first_slash = P_strchr(data, RH_SEPERATOR);
1023     
1024     // no "/", assume string holds module name....
1025     if (first_slash == NULL) {
1026         return constraint;
1027     }    
1028     // has "/", assume everything up to "/" is module name....
1029     return string(data, first_slash - data);
1030 }
1031
1032 // rip function name out of constraint....
1033 // Assumes that constraint is of form module/function, or
1034 // module.... 
1035 string getFunctionName(string constraint) {
1036     string ret;
1037
1038     const char *data = constraint.string_of();
1039     const char *first_slash = P_strchr(data, RH_SEPERATOR);
1040     
1041     // no "/", assume constraint is module only....
1042     if (first_slash == NULL) {
1043         return string("");
1044     }    
1045     // has "/", assume everything after "/" is function....
1046     return string(first_slash+1);
1047 }
1048
1049
1050 #ifndef BPATCH_LIBRARY
1051
1052 // mcheyney, Oct. 6, 1997
1053 static dictionary_hash<string, string> func_constraint_hash(string::hash);
1054 static bool cache_func_constraint_hash() {
1055     static bool func_constraint_hash_loaded = FALSE;
1056
1057     // strings holding exclude constraints....
1058     vector<string> func_constraints;
1059     // if unble to get list of excluded functions, assume all functions
1060     //  are NOT excluded!!!!
1061     if(mdl_get_lib_constraints(func_constraints) == FALSE) {
1062         return FALSE;
1063     }
1064     func_constraint_hash_loaded = TRUE;
1065
1066     unsigned i;
1067     for(i=0;i<func_constraints.size();i++) {
1068         func_constraint_hash[func_constraints[i]] = func_constraints[i];
1069     }
1070     return TRUE;
1071 }
1072
1073 // mcheyney, Oct. 3, 1997
1074 // Return boolean value indicating whether function is found to
1075 //  be excluded via "exclude module_name/function_name" (but NOT
1076 //  via "exclude module_name").
1077 bool function_is_excluded(pd_Function *func, string module_name) {
1078     static bool func_constraint_hash_loaded = FALSE;
1079
1080     string function_name = func->prettyName();
1081     string full_name = module_name + string("/") + function_name;
1082
1083     if (func_constraint_hash_loaded == FALSE) {
1084         if (!cache_func_constraint_hash()) {
1085             return FALSE;
1086         }
1087     }
1088
1089     if (func_constraint_hash.defines(full_name)) {
1090         return TRUE;
1091     }
1092     return FALSE;
1093 }
1094
1095 bool module_is_excluded(pdmodule *module) {
1096     static bool func_constraint_hash_loaded = FALSE;
1097
1098     string full_name = module->fileName();
1099
1100     if (func_constraint_hash_loaded == FALSE) {
1101         if (!cache_func_constraint_hash()) {
1102             return FALSE;
1103         }
1104     }
1105
1106     if (func_constraint_hash.defines(full_name)) {
1107         return TRUE;
1108     }
1109     return FALSE;
1110 }
1111
1112 //
1113 // mcheyney, Sep 28, 1997
1114 // Take a list of functions (in vector <all_funcs>.  Copy all
1115 //  of those functions which are not excluded (via "exclude" 
1116 //  {module==module_name}/{function==function_name) into
1117 //  <some_functions>.  DONT filter out those excluded via
1118 //  exclude module==module_name...., eh????
1119 // Returns status of mdl_get_lib_constraints() call.
1120 //  If this status == FALSE< some_funcs is not modified....
1121 // We assume that all_funcs is generally longer than the list
1122 //  of constrained functions.  As such, internally proc. copies
1123 //  all funcs into some funcs, then runs over excluded funcs
1124 //  removing any matches, as opposed to doing to checking 
1125 //  while adding to some_funcs....
1126
1127 bool filter_excluded_functions(vector<pd_Function*> all_funcs,
1128     vector<pd_Function*>& some_funcs, string module_name) {
1129     unsigned i;
1130
1131     string full_name;
1132     static bool func_constraint_hash_loaded = FALSE;
1133
1134     if (func_constraint_hash_loaded == FALSE) {
1135         if (!cache_func_constraint_hash()) {
1136             return FALSE;
1137         }
1138     }
1139
1140     // run over all_funcs, check if module/function is caught
1141     //  by an exclude....
1142     for(i=0;i<all_funcs.size();i++) {
1143         full_name = module_name + string("/") + all_funcs[i]->prettyName();
1144         if (!(func_constraint_hash.defines(full_name))) {
1145             some_funcs += all_funcs[i];
1146         }
1147     }
1148     
1149     //cerr << " looks successful : about to return TRUE" << endl;
1150     //cerr << " some_funcs (by pretty name) " << endl;
1151     //for (i=0;i<some_funcs.size();i++) {
1152     //    cerr << "  " << some_funcs[i]->prettyName() << endl;
1153     //}
1154     
1155     return TRUE;
1156 }
1157
1158 #endif /* BPATCH_LIBRARY */
1159
1160 // identify module name from symbol address (binary search)
1161 // based on module tags found in file format (ELF/COFF)
1162 void image::findModByAddr (const Symbol &lookUp, vector<Symbol> &mods,
1163                            string &modName, Address &modAddr, 
1164                            const string &defName)
1165 {
1166   if (mods.size() == 0) {
1167     modAddr = 0;
1168     modName = defName;
1169     return;
1170   }
1171
1172   Address symAddr = lookUp.addr();
1173   int index;
1174   int start = 0;
1175   int end = mods.size() - 1;
1176   int last = end;
1177   bool found = false;
1178   while ((start <= end) && !found) {
1179     index = (start+end)/2;
1180     if ((index == last) ||
1181         ((mods[index].addr() <= symAddr) && 
1182          (mods[index+1].addr() > symAddr))) {
1183       modName = mods[index].name();
1184       modAddr = mods[index].addr();      
1185       found = true;
1186     } else if (symAddr < mods[index].addr()) {
1187       end = index - 1;
1188     } else {
1189       start = index + 1;
1190     }
1191   }
1192   if (!found) { 
1193     // must be (start > end)
1194     modAddr = 0;
1195     modName = defName;
1196     //modName = mods[0].name();
1197     //modAddr = mods[0].addr();
1198   }
1199 }
1200
1201 unsigned int int_addrHash(const Address& addr) {
1202   return (unsigned int)addr;
1203 }
1204
1205 /*
1206  * load an executable:
1207  *   1.) parse symbol table and identify rotuines.
1208  *   2.) scan executable to identify inst points.
1209  *
1210  *  offset is normally zero except on CM-5 where we have two images in one
1211  *    file.  The offset passed to parseImage is the logical offset (0/1), not
1212  *    the physical point in the file.  This makes it faster to "parse" multiple
1213  *    copies of the same image since we don't have to stat and read to find the
1214  *    physical offset. 
1215  */
1216
1217 image *image::parseImage(fileDescriptor *desc)
1218 {
1219   /*
1220    * Check to see if we have parsed this image at this offset before.
1221    * We only match if the entire file descriptor matches, which can
1222    * can be filename matching or filename/offset matching.
1223    */
1224   unsigned numImages = allImages.size();
1225
1226   // AIX: it's possible that we're reparsing a file with better information
1227   // about it. If so, yank the old one out of the images vector -- replace
1228   // it, basically.
1229   for (unsigned u=0; u<numImages; u++)
1230     if ((*desc) == *(allImages[u]->desc()))
1231       return allImages[u];
1232   /*
1233    * load the symbol table. (This is the a.out format specific routine).
1234    */
1235
1236   if(desc->isSharedObject()) 
1237     statusLine("Processing a shared object file");
1238   else  
1239     statusLine("Processing an executable file");
1240   bool err=false;
1241   
1242   // TODO -- kill process here
1243   image *ret = new image(desc, err);
1244   if (err || !ret) {
1245     if (ret)
1246       delete ret;
1247     return NULL;
1248   }
1249
1250   bool beenReplaced = false;
1251 #ifdef rs6000_ibm_aix4_1 
1252   // On AIX, we might have a "stub" image instead of the
1253   // actual image we want. So we check to see if we do,
1254   // and if so copy over the list. In normal practice,
1255   // the stub will be the first and only entry.
1256   for (unsigned i=0; i<numImages; i++)
1257     if (allImages[i]->desc()->addr() == (unsigned) -1) {
1258       image *imageTemp = allImages[i];
1259       allImages[i]=ret;
1260       beenReplaced = true;
1261       delete imageTemp;
1262   }
1263   // Add to master image list.
1264 #endif
1265   if (beenReplaced == false) // short-circuit on non-AIX
1266     image::allImages.push_back(ret);
1267
1268   // define all modules.
1269 #ifndef BPATCH_LIBRARY
1270   tp->resourceBatchMode(true);
1271 #endif
1272
1273   statusLine("defining modules");
1274   ret->defineModules();
1275
1276 //  statusLine("ready"); // this shouldn't be here, right? (cuz we're not done, right?)
1277
1278 #ifndef BPATCH_LIBRARY
1279   tp->resourceBatchMode(false);
1280 #endif
1281
1282   return(ret);
1283 }
1284
1285
1286 // Constructor for the image object. The fileDescriptor simply
1287 // wraps (in the normal case) the object name and a relocation
1288 // address (0 for a.out file). On the following platforms, we
1289 // are handling a special case:
1290 //   AIX: objects can possibly have a name like /lib/libc.so:shr.o
1291 //          since libraries are archives
1292 //        Both text and data sections have a relocation address
1293
1294
1295 image::image(fileDescriptor *desc, bool &err)
1296   : 
1297     desc_(desc),
1298     is_libdyninstRT(false),
1299     is_a_out(false),
1300     main_call_addr_(0),
1301     linkedFile(desc, pd_log_perror),
1302     knownJumpTargets(int_addrHash, 8192),
1303 #if !defined(USE_STL_VECTOR)
1304     includedMods(0),
1305     excludedMods(0),
1306     allMods(0),
1307     includedFunctions(0),
1308     instrumentableFunctions(0),
1309 #endif
1310     funcsByAddr(addrHash4),
1311     funcsByPretty(string::hash),
1312     funcsByMangled(string::hash),
1313     notInstruFunctions(string::hash),
1314     excludedFunctions(string::hash),
1315     modsByFileName(string::hash),
1316     modsByFullName(string::hash),
1317     varsByPretty(string::hash)
1318 {
1319   sharedobj_cerr << "image::image for file name="
1320                  << desc->file() << endl;
1321
1322   // initialize (data members) codeOffset_, dataOffset_,
1323   //  codeLen_, dataLen_.
1324   codeOffset_ = linkedFile.code_off();
1325   dataOffset_ = linkedFile.data_off();
1326   codeLen_ = linkedFile.code_len();
1327   dataLen_ = linkedFile.data_len();
1328     
1329   // if unable to parse object file (somehow??), try to
1330   //  notify luser/calling process + return....    
1331   if (!codeLen_ || !linkedFile.code_ptr()) {
1332     string msg = string("Parsing problem with executable file: ") + desc->file();
1333     statusLine(msg.string_of());
1334     msg += "\n";
1335     logLine(msg.string_of());
1336     err = true;
1337 #ifndef mips_unknown_ce2_11 //ccw 29 mar 2001
1338
1339 #if defined(BPATCH_LIBRARY)
1340     BPatch_reportError(BPatchWarning, 27, msg.string_of()); 
1341 #else
1342     showErrorCallback(27, msg); 
1343 #endif
1344 #endif
1345     return;
1346   }
1347   
1348   string msg;
1349   // give luser some feedback....
1350   msg = string("Parsing object file: ") + desc->file();
1351   statusLine(msg.string_of());
1352   
1353   name_ = extract_pathname_tail(desc->file());
1354   pathname_ = desc->file();
1355   err = false;
1356   
1357   // use the *DUMMY_MODULE* until a module is defined
1358   //pdmodule *dynModule = newModule(DYN_MODULE, 0);
1359   //pdmodule *libModule = newModule(LIBRARY_MODULE, 0);
1360   // TODO -- define inst points in define function ?
1361   
1362   // The functions cannot be verified until all of them have been seen
1363   // because calls out of each function must be tagged as calls to user
1364   // functions or call to "library" functions
1365   
1366   //
1367   // sort the modules by address into a vector to allow a binary search to 
1368   // determine the module that a symbol will map to -- this 
1369   // may be bsd specific....
1370   //
1371   vector <Symbol> tmods;
1372   
1373   for (SymbolIter symIter(linkedFile); symIter; symIter++) {
1374     const Symbol &lookUp = symIter.currval();
1375     if (lookUp.type() == Symbol::PDST_MODULE) {
1376       
1377       const string &lookUpName = lookUp.name();
1378       const char *str = lookUpName.string_of();
1379       assert(str);
1380       int ln = lookUpName.length();
1381       
1382       // directory definition -- ignored for now
1383       if (str[ln-1] != '/') {
1384         tmods.push_back(lookUp);
1385       }
1386     }
1387   }
1388   
1389   // sort the modules by address
1390   statusLine("sorting modules");
1391   VECTOR_SORT(tmods, symbol_compare);
1392   
1393   // remove duplicate entries -- some .o files may have the same 
1394   // address as .C files.  kludge is true for module symbols that 
1395   // I am guessing are modules
1396   vector<Symbol> uniq;
1397   
1398   unsigned int num_zeros = 0;
1399   // must use loop+1 not mods.size()-1 since it is an unsigned compare
1400   //  which could go negative - jkh 5/29/95
1401   for (unsigned loop=0; loop < tmods.size(); loop++) {
1402     if (tmods[loop].addr() == 0) num_zeros++;
1403     if ((loop+1 < tmods.size()) && 
1404         (tmods[loop].addr() == tmods[loop+1].addr())) {
1405       if (!tmods[loop].kludge())
1406         tmods[loop+1] = tmods[loop];
1407     } 
1408     else
1409       uniq.push_back(tmods[loop]);
1410   }
1411   // avoid case where all (ELF) module symbols have address zero
1412   if (num_zeros == tmods.size()) uniq.resize(0);
1413   
1414   // define all of the functions
1415   statusLine("winnowing functions");
1416   
1417   // define all of the functions
1418   if (!addAllFunctions(uniq)) {
1419     err = true;
1420     return;
1421   }
1422   
1423   // ALERT ALERT - Calling on both shared_object && !shared_object path.
1424   //  In origional code, only called in !shared_object case.  Was this 
1425   //  a bug????
1426   // XXX should have a statusLine("retrieving variable information") here,
1427   //     but it's left out for now since addAllVariables only does something
1428   //     when BPATCH_LIBRARY is defined
1429   addAllVariables();
1430   
1431   statusLine("checking call points");
1432   checkAllCallPoints();
1433   
1434   // TODO -- remove duplicates -- see earlier note
1435   dictionary_hash<Address, unsigned> addr_dict(addrHash4);
1436   vector<pd_Function*> temp_vec;
1437   
1438   // question??  Necessary to do same crap to includedFunctions &&
1439   //  excludedFunctions??
1440   unsigned f_size = instrumentableFunctions.size(), index;
1441   for (index=0; index<f_size; index++) {
1442     const Address the_address = 
1443       instrumentableFunctions[index]->getAddress(0);
1444     if (!addr_dict.defines(the_address)) {
1445       addr_dict[the_address] = 1;
1446       temp_vec.push_back(instrumentableFunctions[index]);
1447     }
1448   }
1449   // Memory leak, eh?
1450   instrumentableFunctions = temp_vec;
1451 }
1452
1453 void pdmodule::checkAllCallPoints() {
1454   unsigned fsize = funcs.size();
1455   for (unsigned f=0; f<fsize; f++)
1456       funcs[f]->checkCallPoints();
1457 }
1458
1459 function_base *pdmodule::findFunctionFromAll(const string &name) {
1460   unsigned fsize = funcs.size();
1461   unsigned f;
1462   for (f=0; f<fsize; f++) {
1463     if (funcs[f]->symTabName() == name)
1464       return funcs[f];
1465     else if (funcs[f]->prettyName() == name)
1466       return funcs[f];
1467   }
1468
1469   fsize = notInstruFuncs.size();
1470   for (f=0; f<fsize; f++) {
1471     if (notInstruFuncs[f]->symTabName() == name)
1472       return notInstruFuncs[f];
1473     else if (notInstruFuncs[f]->prettyName() == name)
1474       return notInstruFuncs[f];
1475   }
1476
1477   return NULL;
1478 }
1479
1480 void image::checkAllCallPoints() {
1481   dictionary_hash_iter<string, pdmodule*> di(modsByFullName);
1482   string s; pdmodule *mod;
1483   while (di.next(s, mod))
1484     mod->checkAllCallPoints();
1485 }
1486
1487 pdmodule *image::getOrCreateModule(const string &modName, 
1488                                       const Address modAddr) {
1489   const char *str = modName.string_of();
1490   int len = modName.length();
1491   assert(len>0);
1492
1493   // TODO ignore directory definitions for now
1494   if (str[len-1] == '/') {
1495     return NULL;
1496   } else {
1497     // TODO - navigate ".." and "."
1498     const char *lastSlash = P_strrchr(str, '/');
1499     if (lastSlash)
1500       return (newModule(++lastSlash, modAddr));
1501     else
1502       return (newModule(modName, modAddr));
1503   }
1504 }
1505
1506 // Verify that this is code
1507 // Find the call points
1508 // Find the return address
1509 // TODO -- use an instruction object to remove
1510 // Sets err to false on error, true on success
1511 //
1512 // Note - this must define funcEntry and funcReturn
1513 // 
1514 pd_Function::pd_Function(const string &symbol, const string &pretty, 
1515                        pdmodule *f, Address adr, const unsigned size, 
1516                        const image *owner, bool &err) : 
1517   function_base(symbol, pretty, adr, size),
1518   file_(f),
1519   funcEntry_(0),
1520 #ifndef BPATCH_LIBRARY
1521   funcResource(0),
1522 #endif
1523   relocatable_(false)
1524 {
1525   err = findInstPoints(owner) == false;
1526
1527   isInstrumentable_ = !err;
1528 }
1529
1530 // This method returns the address at which this function resides
1531 // in the process P, even if it is dynamic, even if it has been
1532 // relocated.  getAddress() (see symtab.h) does not always do this:
1533 // If the function is in a shlib and it has not been relocated,
1534 // getAddress() only returns the relative offset of the function
1535 // within its shlib.  We think that getAddress() should be fixed
1536 // to always return the effective address, but we are not sure
1537 // whether that would boggle any of its 75 callers.  Until that is
1538 // cleared up, call this method. -zandy, Apr-26-1999
1539 Address pd_Function::getEffectiveAddress(const process *p) const {
1540      assert(p);
1541      // Even if the function has been relocated, call it at its
1542      // original address since the call will be redirected to the
1543      // right place anyway.
1544      Address base;
1545      p->getBaseAddress(file()->exec(), base);
1546      return base + addr();
1547 }
1548
1549
1550 /*********************************************************************/
1551 /**** Function lookup (by name or address) routines               ****/
1552 /*********************************************************************/
1553
1554 /* Look up a function by the given address. Four-part method:
1555  * First, do a quick scan of funcsByAddr to see if we get a match
1556  *   -- will match function entry point
1557  * Second, do a complete search of funcsByAddr, using original address
1558  * Finally, check excludedFuncs and nonInstruFuncs
1559  */
1560
1561 pd_Function *image::findFuncByAddr(const Address &addr, 
1562                                    const process *p) const
1563 {
1564   pd_Function *pdf;
1565
1566   // Quick check of funcsByAddr
1567   if (funcsByAddr.find(addr, pdf))
1568     return pdf;
1569   
1570   // Slow check of funcsByAddr
1571   dictionary_hash_iter<Address, pd_Function*> mi(funcsByAddr);
1572   Address adr;
1573   while (mi.next(adr, pdf)) {
1574     if ( p && // getEffectiveAddress asserts p 
1575         (addr>=pdf->getEffectiveAddress(p)) &&
1576          (addr<(pdf->getEffectiveAddress(p)+pdf->size()))
1577          )
1578       return pdf;
1579     if ( (addr>=pdf->getAddress(p)) && 
1580          (addr < (pdf->getAddress(p)+pdf->size()))
1581          )
1582       return pdf;
1583   }
1584
1585   // next, look in excludedFunctions...
1586   dictionary_hash_iter<string, pd_Function*> ex(excludedFunctions);
1587   string str;
1588   while (ex.next(str, pdf)) {
1589     if ( p &&
1590          (addr>=pdf->getEffectiveAddress(p)) &&
1591          (addr<(pdf->getEffectiveAddress(p)+pdf->size()))
1592          )
1593       return pdf;
1594     if ( (addr>=pdf->getAddress(p)) && 
1595          (addr < (pdf->getAddress(p)+pdf->size()))
1596          )
1597       return pdf;
1598   }
1599   
1600   dictionary_hash_iter<string, pd_Function *> ni(notInstruFunctions);
1601   while (ni.next(str, pdf)) {
1602     if ( p &&
1603          (addr>=pdf->getEffectiveAddress(p)) &&
1604          (addr<(pdf->getEffectiveAddress(p)+pdf->size()))
1605          )
1606       return pdf;
1607     if ( (addr>=pdf->getAddress(p)) && 
1608          (addr < (pdf->getAddress(p)+pdf->size()))
1609          ) 
1610       return pdf;
1611   }
1612   return NULL; 
1613 }
1614
1615 // This function assumes the given address is an offset within
1616 // the file.
1617
1618 pd_Function *image::findFuncByEntryAddr(const Address &addr, 
1619                                         const process */*p*/) const
1620 {
1621   pd_Function *pdf;
1622
1623   if (funcsByAddr.find(addr, pdf))
1624     return pdf;
1625
1626   return NULL; 
1627 }
1628
1629 pd_Function *image::findFuncByRelocAddr(const Address &addr, 
1630                                         const process *p) const
1631 {
1632   pd_Function *pdf;
1633
1634   // Slow check of funcsByAddr
1635   dictionary_hash_iter<Address, pd_Function*> mi(funcsByAddr);
1636   Address adr;
1637   while (mi.next(adr, pdf)) {
1638     if ( (addr>=pdf->getAddress(p)) && 
1639          (addr < (pdf->getAddress(p)+pdf->size()))
1640          )
1641       return pdf;
1642   }
1643
1644   // next, look in excludedFunctions...
1645   dictionary_hash_iter<string, pd_Function*> ex(excludedFunctions);
1646   string str;
1647   while (ex.next(str, pdf)) {
1648     if ( (addr>=pdf->getAddress(p)) && 
1649          (addr < (pdf->getAddress(p)+pdf->size()))
1650          )
1651       return pdf;
1652   }
1653   
1654   dictionary_hash_iter<string, pd_Function *> ni(notInstruFunctions);
1655   while (ni.next(str, pdf)) {
1656     if ( (addr>=pdf->getAddress(p)) && 
1657          (addr < (pdf->getAddress(p)+pdf->size()))
1658          ) 
1659       return pdf;
1660   }
1661   return NULL; 
1662 }
1663
1664 pd_Function *image::findFuncByOrigAddr(const Address &addr, 
1665                                        const process *p) const
1666 {
1667   pd_Function *pdf;
1668   
1669   // Slow check of funcsByAddr
1670   dictionary_hash_iter<Address, pd_Function*> mi(funcsByAddr);
1671   Address adr;
1672   while (mi.next(adr, pdf)) {
1673     if ( p && // getEffectiveAddress asserts p 
1674         (addr>=pdf->getEffectiveAddress(p)) &&
1675          (addr<(pdf->getEffectiveAddress(p)+pdf->size()))
1676          )
1677       return pdf;
1678   }
1679
1680   // next, look in excludedFunctions...
1681   dictionary_hash_iter<string, pd_Function*> ex(excludedFunctions);
1682   string str;
1683   while (ex.next(str, pdf)) {
1684     if ( p &&
1685          (addr>=pdf->getEffectiveAddress(p)) &&
1686          (addr<(pdf->getEffectiveAddress(p)+pdf->size()))
1687          )
1688       return pdf;
1689   }
1690   
1691   dictionary_hash_iter<string, pd_Function *> ni(notInstruFunctions);
1692   while (ni.next(str, pdf)) {
1693     if ( p &&
1694          (addr>=pdf->getEffectiveAddress(p)) &&
1695          (addr<(pdf->getEffectiveAddress(p)+pdf->size()))
1696          )
1697       return pdf;
1698   }
1699   return NULL; 
1700 }
1701
1702 // Return the vector of functions associated with a pretty (demangled) name
1703 // Very well might be more than one!
1704
1705 vector <pd_Function *> *image::findFuncVectorByPretty(const string &name)
1706 {
1707 #ifdef IBM_BPATCH_COMPAT_STAB_DEBUG
1708   fprintf(stderr, "%s[%d]:  inside findFuncVectorByPretty\n", __FILE__, __LINE__);
1709   fflush(NULL);
1710 #endif
1711   if (funcsByPretty.defines(name))
1712     return funcsByPretty[name];
1713   return NULL;
1714 }
1715
1716 // Return a single function associated with a demangled name. Arbitrarily
1717 // pick the first one.
1718
1719 pd_Function *image::findFuncByPretty(const string &name)
1720 {
1721   vector <pd_Function *> *a;
1722
1723   if (funcsByPretty.defines(name)) {
1724     a = funcsByPretty[name];
1725     return ((*a)[0]);
1726   }
1727   return NULL;
1728 }
1729
1730 pd_Function *image::findFuncByMangled(const string &name)
1731 {
1732   vector <pd_Function *> *a;
1733
1734   if (funcsByMangled.defines(name)) {
1735     a = funcsByMangled[name];
1736     return ((*a)[0]);
1737   }
1738   return NULL;
1739 }
1740
1741 pd_Function *image::findExcludedFunc(const string &name)
1742 {
1743   if (excludedFunctions.defines(name))
1744     return excludedFunctions[name];
1745   return NULL;
1746 }
1747
1748 pd_Function *image::findNonInstruFunc(const string &name)
1749 {
1750   if (notInstruFunctions.defines(name)) 
1751     return notInstruFunctions[name];
1752   return NULL;
1753 }
1754
1755 // TODO -- this is only being used in cases where only one function
1756 // should exist -- should I assert that the vector size <= 1 ?
1757 // mcheyney - should return NULL when function being searched for 
1758 //  is excluded!!!!
1759 // Checks for function in pretty name hash first, then in
1760 //  mangled name hash to better handle many (mangled name) to one 
1761 //  (pretty name) mapping in C++ function names....
1762 pd_Function *image::findFuncByName(const string &name)
1763 {
1764   pd_Function *pdf;
1765
1766   if ( ( pdf = findFuncByPretty(name))) return pdf;
1767
1768   if ( ( pdf = findFuncByMangled(name))) return pdf;
1769
1770   return NULL;
1771 }
1772
1773 // This function supposely is only used to find function that
1774 // is not instrumentable which may not be totally defined.
1775 // Use with caution.  
1776 // NEW - also can be used to find an excluded function....
1777 pd_Function *image::findOneFunctionFromAll(const string &name) {
1778     pd_Function *ret = NULL;
1779     if ( (ret = findFuncByName(name))) 
1780       return ret;
1781
1782     if ( (ret = findNonInstruFunc(name)))
1783       return ret;
1784
1785     if ( (ret = findExcludedFunc(name)))
1786       return ret;
1787
1788     return NULL;
1789 }
1790
1791 #if 0
1792 // Only looks for function by pretty name.
1793 //  Should it also look by mangled name??
1794 bool image::findFunction(const string &name, vector<pd_Function*> &retList,
1795         bool find_if_excluded) {
1796
1797     bool found = FALSE;
1798     if (funcsByPretty.defines(name)) {
1799         retList = *funcsByPretty[name];
1800         found = TRUE;
1801     } 
1802
1803     if (find_if_excluded) {
1804       // should APPEND to retList!!!!
1805       if (excludedFunctions.defines(name))
1806         retList.push_back(excludedFunctions[name]);
1807       found = TRUE;
1808     }
1809     return found;
1810 }
1811 #endif