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