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