Brought Dyninst API up to date with latest changes in Paradyn.
[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 #include <stdio.h>
43 #include <stdlib.h>
44 #include <assert.h>
45
46 // TODO - machine independent instruction functions
47 #include "dyninstAPI/src/symtab.h"
48 #include "dyninstAPI/src/arch.h"
49 #include "util/h/Object.h"
50 #include <fstream.h>
51 #include "dyninstAPI/src/util.h"
52 #include "dyninstAPI/src/dyninstP.h"
53 #include "util/h/String.h"
54 #include "dyninstAPI/src/inst.h"
55 #include "util/h/Timer.h"
56 #include "paradynd/src/showerror.h"
57 #include "util/h/debugOstream.h"
58
59 #ifndef BPATCH_LIBRARY
60 #include "paradynd/src/mdld.h"
61 #include "paradynd/src/main.h"
62 #include "paradynd/src/init.h"
63 #else
64 extern vector<sym_data> syms_to_find;
65 #endif
66
67 // All debug_ostream vrbles are defined in process.C (for no particular reason)
68 extern debug_ostream sharedobj_cerr;
69
70 vector<image*> image::allImages;
71
72 #if defined(i386_unknown_nt4_0)
73 extern char *cplus_demangle(char *, int);
74 #else
75 extern "C" char *cplus_demangle(char *, int);
76 #endif
77
78
79 /*
80   Debuggering info for function_base....
81  */
82 ostream & function_base::operator<<(ostream &s) const {
83     s << "symTabName_ = " << symTabName_ << " prettyName_ = " \
84       << prettyName_ \
85       << " line_ = " << line_ << " addr_ = "<< addr_ << " size_ = " << size_ \
86       << " tag_ = " << tag_ << endl;
87     return s;
88 }
89
90 ostream &operator<<(ostream &os, function_base &f) {
91     return f.operator<<(os);
92 }
93
94 /* imported from platform specific library list.  This is lists all
95    library functions we are interested in instrumenting. */
96
97 pdmodule *image::newModule(const string &name, const Address addr)
98 {
99     pdmodule *ret;
100     // modules can be defined several times in C++ due to templates and
101     //   in-line member functions.
102     if ((ret = findModule(name, TRUE)))
103       return(ret);
104
105     string fullNm, fileNm;
106     char *out = P_strdup(name.string_of());
107     char *sl = P_strrchr(out, '/');
108     if (sl) {
109       *sl = (char)0;
110       fullNm = out;
111       fileNm = sl+1;
112     } else {
113       fullNm = string("/default/") + out;
114       fileNm = out;
115     }
116     free(out);
117
118     ret = new pdmodule(langUnknown, addr, fullNm, fileNm, this);
119
120 #ifndef BPATCH_LIBRARY
121     // if module was excluded,stuff it into excludedMods (and dont
122     //  index it in modeByFileName && modsByFullName.
123     if (module_is_excluded(ret)) {
124         excludedMods += ret;
125     } else {
126 #endif /* BPATCH_LIBRARY */
127         modsByFileName[ret->fileName()] = ret;
128         modsByFullName[ret->fullName()] = ret;
129         includedMods += ret;
130 #ifndef BPATCH_LIBRARY
131     }
132 #endif /* BPATCH_LIBRARY */
133
134     return(ret);
135 }
136
137
138 // TODO -- is this g++ specific
139 bool buildDemangledName(const string &mangled, string &use)
140 {
141  /* The C++ demangling function demangles MPI__Allgather (and other MPI__
142   * functions with start with A) into the MPI constructor.  In order to
143   * prevent this a hack needed to be made, and this seemed the cleanest
144   * approach.
145   */
146   if(!mangled.prefixed_by("MPI__")) {
147     char *tempName = P_strdup(mangled.string_of());
148     char *demangled = cplus_demangle(tempName, 0);
149     
150     if (demangled) {
151       use = demangled;
152       free(tempName);
153       free(demangled);
154       return true;
155     } else {
156       free(tempName);
157       return false;
158     }
159   }
160   return(false);
161 }
162
163 // err is true if the function can't be defined
164 // COMMENTS????
165 // looks like this function attempts to do several things:
166 //  1) Check if can find the function (WHERE DOES IT LOOK????).
167 //  2) strip out something from function name which looks like
168 //    possible scoping info (everything up to?? ":")??
169 //  3) try to demangle this (descoped??) name.
170 //  4) make new pd_Function under origional name and demangled name.
171 //  5) Insert into (data members) funcsByAdd && mods->funcs.
172 //  n) insert into (data member) funcsByPretty (indexed under 
173 //    demangled name).
174 bool image::newFunc(pdmodule *mod, const string &name, const Address addr, 
175                     const unsigned size, const unsigned tag, 
176                     pd_Function *&retFunc) {
177   pd_Function *func;
178
179   retFunc = NULL;
180   // KLUDGE
181   if ((func = findFunction(addr, TRUE))){
182     string temp = name;
183     temp += string(" findFunction succeeded\n");
184     logLine(P_strdup(temp.string_of()));
185     return false;
186   }
187
188   if (!mod) {
189     logLine("Error function without module\n");
190     showErrorCallback(34, "Error function without module");
191     return false;
192   }
193
194   string mangled_name = name;
195   const char *p = P_strchr(name.string_of(), ':');
196   if (p) {
197      unsigned nchars = p - name.string_of();
198      mangled_name = string(name.string_of(), nchars);
199   }
200      
201   string demangled;
202   if (!buildDemangledName(mangled_name, demangled)) 
203     demangled = mangled_name;
204
205   bool err;
206
207   func = new pd_Function(name, demangled, mod, addr, size, tag, this, err);
208   assert(func);
209   //cout << name << " pretty: " << demangled << " addr :" << addr <<endl;
210   retFunc = func;
211   // if there was an error in determining the instrumentation info for
212   //  function, add it to notInstruFunction.
213   if (err) {
214     //delete func;
215     retFunc = NULL;
216     addNotInstruFunc(func);
217     return false;
218   }
219  
220   addInstruFunction(func, mod, addr,
221 #ifdef BPATCH_LIBRARY
222                     false);
223 #else
224                     function_is_excluded(func, mod->fileName()));
225 #endif
226   return true;
227 }
228
229 void image::addInstruFunction(pd_Function *func, pdmodule *mod, \
230                               const Address addr, bool excluded) {
231     vector<pd_Function*> *funcsByPrettyEntry;
232
233     // any functions whose instrumentation info could be determined 
234     //  get added to instrumentableFunctions, and mod->funcs.
235     instrumentableFunctions += func;
236     mod->funcs += func;
237
238     if (excluded) {
239         excludedFunctions[func->prettyName()] = func;
240     } else {
241         includedFunctions += func;
242         funcsByAddr[addr] = func;
243
244         if (!funcsByPretty.find(func->prettyName(), funcsByPrettyEntry)) {
245             funcsByPrettyEntry = new vector<pd_Function*>;
246             funcsByPretty[func->prettyName()] = funcsByPrettyEntry;
247         }
248         // several functions may have the same demangled name, and each one
249         // will appear in a different module
250         assert(funcsByPrettyEntry);
251         (*funcsByPrettyEntry) += func;
252     }
253 }
254
255 void image::addNotInstruFunc(pd_Function *func) {
256     notInstruFunctions[func->prettyName()] = func;
257 }
258
259 #ifdef DEBUG_TIME
260 static timer loadTimer;
261 static FILE *timeOut=0;
262 #endif /* DEBUG_TIME */
263
264 /*
265  * load an executable:
266  *   1.) parse symbol table and identify rotuines.
267  *   2.) scan executable to identify inst points.
268  *
269  *  offset is normally zero except on CM-5 where we have two images in one
270  *    file.  The offset passed to parseImage is the logical offset (0/1), not
271  *    the physical point in the file.  This makes it faster to "parse" multiple
272  *    copies of the same image since we don't have to stat and read to find the
273  *    physical offset. 
274  */
275 image *image::parseImage(const string file)
276 {
277   /*
278    * Check to see if we have parsed this image at this offeset before.
279    */
280   // TODO -- better method to detect same image/offset --> offset only for CM5
281
282   unsigned numImages = allImages.size();
283
284   for (unsigned u=0; u<numImages; u++)
285     if (file == allImages[u]->file())
286       return allImages[u];
287
288   /*
289    * load the symbol table. (This is the a.out format specific routine).
290    */
291
292   statusLine("Process executable file");
293   bool err;
294
295   // TODO -- kill process here
296   image *ret = new image(file, err);
297   if (err || !ret) {
298     if (ret)
299       delete ret;
300     return NULL;
301   }
302
303   // Add to master image list.
304   image::allImages += ret;
305
306   // define all modules.
307 #ifndef BPATCH_LIBRARY
308   tp->resourceBatchMode(true);
309 #endif
310
311   statusLine("defining modules");
312   ret->defineModules();
313
314 //  statusLine("ready"); // this shouldn't be here, right? (cuz we're not done, right?)
315
316 #ifndef BPATCH_LIBRARY
317   tp->resourceBatchMode(false);
318 #endif
319
320   return(ret);
321 }
322
323 /*
324  * load a shared object:
325  *   1.) parse symbol table and identify rotuines.
326  *   2.) scan executable to identify inst points.
327  *
328  */
329 image *image::parseImage(const string file,u_int baseAddr)
330 {
331   /*
332    * Check to see if we have parsed this image at this offeset before.
333    */
334   // TODO -- better method to detect same image/offset --> offset only for CM5
335
336   unsigned theSize = allImages.size();
337
338   for (unsigned u=0; u<theSize; u++)
339     if (file == allImages[u]->file())
340       return allImages[u];
341
342   /*
343    * load the symbol table. (This is the a.out format specific routine).
344    */
345
346   if(!baseAddr) statusLine("Processing an executable file");
347   else  statusLine("Processing a shared object file");
348   bool err;
349
350   // TODO -- kill process here
351   image *ret = new image(file, baseAddr,err);
352   if (err || !ret) {
353     if (ret)
354       delete ret;
355     logLine("error after new image in parseImage\n");
356     return NULL;
357   }
358
359   // Add to master image list.
360   image::allImages += ret;
361
362   // define all modules.
363   ret->defineModules();
364   return(ret);
365 }
366
367 // COMMENTS??  COMMENTS??
368 // check symbol whose name is in <str>.  If it is prefixed by
369 // "_DYNINST" or "_TRACELIB", then assume that that it is an
370 // "internal" symbol, and add it to (private data member) 
371 // iSymsMap.
372 bool image::addInternalSymbol(const string &str, const Address symValue) {
373   // Internal symbols are prefixed by { DYNINST, TRACELIB }
374   // don't ignore the underscore
375   static string dyn = "_DYNINST"; 
376   static string tlib = "_TRACELIB";
377
378
379   // normalize all symbols -- remove the leading "_"
380   if (str.prefixed_by(dyn)) {
381     const char *s = str.string_of(); s++;
382     if (!iSymsMap.defines(s)){
383       iSymsMap[s] = new internalSym(symValue, s);
384     }
385     return true;
386   } else if (str.prefixed_by(tlib)) {
387     const char *s = str.string_of(); s++;
388     if (!iSymsMap.defines(s))
389       iSymsMap[s] = new internalSym(symValue, s);
390     return true;
391   } else {
392     if (!iSymsMap.defines(str))
393       iSymsMap[str] = new internalSym(symValue, str);
394     return true;
395   }
396   return false;
397 }
398
399 /*
400  * will search for symbol NAME or _NAME
401  * returns false on failure 
402  */
403 bool image::findInternalSymbol(const string &name, const bool warn, internalSym &ret_sym){
404    Symbol lookUp;
405
406    if(linkedFile.get_symbol(name,lookUp)){
407       ret_sym = internalSym(lookUp.addr(),name); 
408       return true;
409    }
410    else {
411        string new_sym;
412        new_sym = string("_") + name;
413        if(linkedFile.get_symbol(new_sym,lookUp)){
414           ret_sym = internalSym(lookUp.addr(),name); 
415           return true;
416        }
417    } 
418    if(warn){
419       string msg;
420       msg = string("Unable to find symbol: ") + name;
421       statusLine(msg.string_of());
422       showErrorCallback(28, msg);
423    }
424    return false;
425 }
426
427 Address image::findInternalAddress(const string &name, const bool warn, bool &err)
428 {
429
430   err = false;
431
432   internalSym *theSym; // filled in by find()
433   if (!iSymsMap.find(name, theSym)) {
434     // not found!
435     if (warn) {
436       string msg = string("Unable to find symbol: ") + name;
437       statusLine(msg.string_of());
438       showErrorCallback(28, msg);
439     }
440     err = true;
441     return 0;
442   } 
443   else
444     return (theSym->getAddr());
445 }
446
447 pdmodule *image::findModule(const string &name, bool find_if_excluded)
448 {
449   unsigned i;
450
451   //cerr << "image::findModule " << name << " , " << find_if_excluded \
452   //       << " called" << endl;
453
454   if (modsByFileName.defines(name)) {
455     //cerr << " (image::findModule) found module in modsByFileName" << endl;
456     return (modsByFileName[name]);
457   }
458   else if (modsByFullName.defines(name)) {
459     //cerr << " (image::findModule) found module in modsByFuleName" << endl;
460     return (modsByFullName[name]);
461   }
462   
463   // if also looking for excluded functions, check through 
464   //  excludedFunction list to see if any match function by FullName
465   //  or FileName....
466   if (find_if_excluded) {
467       for(i=0;i<excludedMods.size();i++) {
468           if ((excludedMods[i]->fileName() == name) || \
469                   (excludedMods[i]->fullName() == name)) {
470               //cerr << " (image::findModule) found module in excludedMods" << endl;
471               return excludedMods[i];
472           }
473       }
474   }
475
476   //cerr << " (image::findModule) did not find module, returning NULL" << endl;
477   return NULL;
478 }
479
480 // TODO -- this is only being used in cases where only one function
481 // should exist -- should I assert that the vector size <= 1 ?
482 // mcheyney - should return NULL when function being searched for 
483 //  is excluded!!!!
484 pd_Function *image::findOneFunction(const string &name)
485 {
486   string demangName;
487   pd_Function *ret;
488
489   //cerr << "image::findOneFunction " << name << " called" << endl;
490
491   if (funcsByPretty.defines(name)) {
492     vector<pd_Function*> *a = funcsByPretty[name];
493     assert(a);
494     if (!a->size())
495       ret = NULL;
496     else
497       ret = ((*a)[0]);
498   } else if (buildDemangledName(name, demangName)) {
499     if (funcsByPretty.defines(demangName)) {
500       vector<pd_Function*> *a = funcsByPretty[demangName];
501       assert(a);
502       if (!a->size())
503         ret = NULL;
504       else
505         ret = ((*a)[0]);
506     } else
507       ret = NULL;
508   } else
509     ret = NULL;
510
511   //cerr << "(image::findOneFunction " << name << " ) about to return";
512   //if (ret == NULL) {
513   //    cerr << " NULL" << endl;
514   //} else {
515   //    cerr << " non-NULL" << endl;
516   //}
517
518   return ret;
519 }
520
521 // This function supposely is only used to find function that
522 // is not instrumentable which may not be totally defined.
523 // Use with caution.  
524 // NEW - also can be used to find an excluded function....
525 pd_Function *image::findOneFunctionFromAll(const string &name) {
526     pd_Function *ret;
527     if ((ret = findOneFunction(name))) 
528         return ret;
529
530     //cerr << "image::findOneFunctionFromAll " << name << \
531           " called, unable to find function in hash table" << endl; 
532
533     if (notInstruFunctions.defines(name)) {
534         //cerr << "  (image::findOneFunctionFromAll) found in notInstruFunctions" \
535            << endl;
536         return notInstruFunctions[name];
537     }
538
539     if (excludedFunctions.defines(name)) {
540         //cerr << "  (image::findOneFunctionFromAll) found in excludedFunctions" \
541            << endl;
542         return excludedFunctions[name];
543     }
544     return NULL;
545 }
546
547 bool image::findFunction(const string &name, vector<pd_Function*> &retList, \
548         bool find_if_excluded) {
549
550     bool found = FALSE;
551     if (funcsByPretty.defines(name)) {
552         retList = *funcsByPretty[name];
553         found = TRUE;
554     } 
555
556     if (find_if_excluded) {
557         // should APPEND to retList!!!!
558         if (find_excluded_function(name, retList)) {
559             found = TRUE;
560         }
561     }    
562     return found;
563 }
564
565 pd_Function *image::findFunction(const Address &addr, bool find_if_excluded) 
566 {
567   pd_Function *result; // filled in by find()
568   if (funcsByAddr.find(addr, result))
569      return result;
570   if (find_if_excluded) {
571      return find_excluded_function(addr);
572   }
573   return NULL;
574 }
575
576 // find (excluded only) function byt address.... 
577 pd_Function *image::find_excluded_function(const Address &addr) 
578 {
579     pd_Function *this_func;
580     string str;
581     dictionary_hash_iter<string, pd_Function*> ex(excludedFunctions);
582     while(ex.next(str, this_func)) {
583         // ALERT ALERT - assumes that code in image is NOT
584         //  relocated!!!!
585         if (addr == this_func->getAddress(0)) {
586             return this_func;
587         }
588     }
589     return NULL;
590 }
591
592 //  Question??  Currently only finding 1 excluded function reference by
593 //  name (e.g. findOneFunctionFromAll.  Want to keep multiple copies
594 // of same excluded function (as referenced by name)??
595 bool image::find_excluded_function(const string &name, \
596         vector<pd_Function*> &retList) {
597     bool found = FALSE;
598
599     found = excludedFunctions.defines(name);
600     if (found) {
601         retList += excludedFunctions[name];
602     }
603     return found;
604 }
605
606 pd_Function *image::findFunctionInInstAndUnInst(const Address &addr,const process *p) const 
607 {
608   pd_Function *pdf;
609   vector <pd_Function *> values;
610   unsigned i;
611
612   if (funcsByAddr.find(addr, pdf))
613      return pdf;
614   else
615      return NULL;
616   
617   // If not found, we are going to search them in the 
618   // uninstrumentable function
619   values = notInstruFunctions.values();
620   for (i = 0; i < values.size(); i++) {
621       pdf = values[i];
622       if ((addr>=pdf->getAddress(p))&&(addr<=(pdf->getAddress(p)\
623                                               +pdf->size()))) 
624           return pdf;
625   }
626
627   // and in excludedFunctions....
628   values = excludedFunctions.values();
629   for (i = 0; i < values.size(); i++) {
630       pdf = values[i];
631       if ((addr>=pdf->getAddress(p))&&(addr<=(pdf->getAddress(p)\
632                                               +pdf->size()))) 
633           return pdf;
634   }
635
636   return NULL; 
637 }
638  
639 pd_Function *image::findFunctionIn(const Address &addr,const process *p) const 
640 {
641   pd_Function *pdf;
642
643   // first, look in funcsByAddr - should contain instrumentable non-
644   //  excluded functions....
645   dictionary_hash_iter<Address, pd_Function*> mi(funcsByAddr);
646   Address adr;
647   while (mi.next(adr, pdf)) {
648       if ((addr>=pdf->getAddress(p))&&(addr<=(pdf->getAddress(p)+pdf->size()))) 
649           return pdf;
650   }
651   
652   // next, look in excludedFunctions...
653   dictionary_hash_iter<string, pd_Function*> ex(excludedFunctions);
654   string str;
655   while (ex.next(str, pdf)) {
656      if ((addr>=pdf->getAddress(p)) && \
657               (addr<=(pdf->getAddress(p)+pdf->size()))) 
658           return pdf;
659   }
660
661   dictionary_hash_iter<string, pd_Function *> ni(notInstruFunctions);
662   while (ni.next(str, pdf)) {
663       if ((addr>=pdf->getAddress(p)) && \
664               (addr<=(pdf->getAddress(p)+pdf->size()))) 
665           return pdf;
666   }
667
668   return NULL; 
669 }
670
671
672 #ifndef BPATCH_LIBRARY
673 void image::changeLibFlag(resource *res, const bool setSuppress)
674 {
675   image *ret;
676   pdmodule *mod;
677
678   unsigned numImages = image::allImages.size();
679   for (unsigned u=0; u<numImages; u++) {
680     ret = image::allImages[u];
681     // assume should work even if module excluded....
682     mod = ret->findModule(res->part_name(), TRUE);
683     if (mod) {
684       // suppress all procedures.
685       mod->changeLibFlag(setSuppress);
686     } else {
687       // more than one function may have this name --> templates, statics
688       vector<pd_Function*> pdfA;
689       if (ret->findFunction(res->part_name(), pdfA)) {
690         for (unsigned i=0; i<pdfA.size(); ++i) {
691           if (setSuppress) 
692             pdfA[i]->tagAsLib();
693           else
694             pdfA[i]->untagAsLib();
695         }
696       }
697     }
698   }
699 }
700 #endif
701
702
703 /* 
704  * return 0 if symbol <symname> exists in image, non-zero if it does not
705  */
706 bool image::symbolExists(const string &symname)
707 {
708   pd_Function *dummy = findOneFunction(symname);
709   return (dummy != NULL);
710 }
711
712 void image::postProcess(const string pifname)
713 {
714   FILE *Fil;
715   string fname, errorstr;
716   char key[5000];
717   char tmp1[5000], abstraction[500];
718 #ifndef BPATCH_LIBRARY
719   resource *parent;
720 #endif
721
722   return;
723
724   /* What file to open? */
725   if (!(pifname == (char*)NULL)) {
726     fname = pifname;
727   } else {
728     fname = file_ + ".pif";
729   }
730
731   /* Open the file */
732   Fil = P_fopen(fname.string_of(), "r");
733
734   if (Fil == NULL) {
735     errorstr = string("Tried to open PIF file ") + fname;
736     errorstr += string(", but could not (continuing)\n");
737     logLine(P_strdup(errorstr.string_of()));
738     showErrorCallback(35, errorstr); 
739     return;
740   }
741
742   /* Process the file */
743   while (!feof(Fil)) {
744     fscanf(Fil, "%s", key);
745     switch (key[0]) {
746     case 'M':
747       /* Ignore mapping information for right now */
748       fgets(tmp1, 5000, Fil);
749       break;
750     case 'R':
751 #ifndef BPATCH_LIBRARY
752       /* Create a new resource */
753       fscanf(Fil, "%s {", abstraction);
754       parent = rootResource;
755       do {
756         fscanf(Fil, "%s", tmp1);
757         if (tmp1[0] != '}') {
758           parent = resource::newResource(parent, NULL,
759                                          abstraction,
760                                          tmp1, 0.0,
761                                          nullString, // uniqifier
762                                          MDL_T_STRING,
763                                          true);
764         } else {
765           parent = NULL;
766         }
767       } while (parent != NULL);
768 #endif
769       break;
770     default:
771       errorstr = string("Ignoring bad line key (") + fname;
772       errorstr += string(") in file %s\n");
773       logLine(P_strdup(errorstr.string_of()));
774       fgets(tmp1, 5000, Fil);
775       break;
776     }
777   }
778   return;
779 }
780
781 void image::defineModules() {
782   unsigned i;
783
784   string pds; pdmodule *mod;
785   dictionary_hash_iter<string, pdmodule*> mi(modsByFileName);
786
787   while (mi.next(pds, mod)){
788     mod->define();
789   }
790
791   for(i=0;i<excludedMods.size();i++) {
792     mod = excludedMods[i];
793     mod->define();
794   }
795
796 #ifdef DEBUG_MDL
797   char buffer[100];
798   ostrstream osb(buffer, 100, ios::out);
799   osb << "IMAGE_" << name() << "__" << getpid() << ends;
800   ofstream of(buffer, ios::app);
801
802   of << "INCLUDED FUNCTIONS\n";
803   for (unsigned ni=0; ni<includedFunctions.size(); ni++) {
804     of << includedFunctions[ni]->prettyName() << "\t\t" << includedFunctions[ni]->addr() << "\t\t" << << endl;
805   }
806   
807 #endif
808 }
809
810 void pdmodule::define() {
811 #ifndef BPATCH_LIBRARY
812   resource *modResource = NULL;
813 #endif
814 #ifdef DEBUG_MODS
815   char buffer[100];
816   ostrstream osb(buffer, 100, ios::out);
817   osb << "MODS_" << exec->name() << "__" << getpid() << ends;
818   ofstream of(buffer, ios::app);
819 #endif
820
821   unsigned f_size = funcs.size();
822
823   for (unsigned f=0; f<f_size; f++) {
824     pd_Function *pdf = funcs[f];
825 #ifdef DEBUG_MODS
826     of << fileName << ":  " << pdf->prettyName() <<  "  " \
827         << pdf->addr() << endl;
828 #endif
829     // ignore line numbers for now 
830
831 #ifndef BPATCH_LIBRARY
832     //if (!(pdf->isLibTag())) {
833     if (1) {
834       // see if we have created module yet.
835       if (!modResource) {
836         modResource = resource::newResource(moduleRoot, this,
837                                             nullString, // abstraction
838                                             fileName(), // name
839                                             0.0, // creation time
840                                             string(), // unique-ifier
841                                             MDL_T_MODULE,
842                                             false);
843       }
844       resource::newResource(modResource, pdf,
845                             nullString, // abstraction
846                             pdf->prettyName(), 0.0,
847                             nullString, // uniquifier
848                             MDL_T_PROCEDURE,
849                             false);
850     }
851 #endif
852   }
853
854 #ifndef BPATCH_LIBRARY
855   resource::send_now();
856 #endif
857 }
858
859 // get all functions in module which are not "excluded" (e.g.
860 //  with mdl "exclude" command.  
861 // Assed to provide support for mdl "exclude" on functions in
862 //  statically linked objects.
863 //  mcheyney 970727
864 vector<function_base *> *pdmodule::getIncludedFunctions() {
865     // laxy construction of some_funcs, as per sharedobject class....
866     // cerr << "pdmodule " << fileName() << " :: getIncludedFunctions called " \
867        << endl;
868     if (some_funcs_inited == TRUE) {
869         //cerr << "  about to return : " << endl;
870         print_func_vector_by_pretty_name(string("  "), (vector<function_base *>*)&some_funcs);
871         return (vector<function_base *>*)&some_funcs;
872     }
873 #ifdef BPATCH_LIBRARY /* BPatch Library doesn't know about excluded funcs */
874     some_funcs = funcs;
875 #else
876     some_funcs.resize(0);
877     if (filter_excluded_functions(funcs, some_funcs, fileName()) == FALSE) {
878         //cerr << "  about to return NULL";
879         return NULL;
880     }
881 #endif
882     some_funcs_inited = TRUE;
883     
884     //cerr << "  about to return : " << endl;
885     //print_func_vector_by_pretty_name(string("  "),(vector<function_base *>*) &some_funcs);
886     return (vector<function_base *>*)&some_funcs;
887 }
888
889
890 // get all functions in module which are not "excluded" (e.g.
891 //  with mdl "exclude" command.  
892 // Assed to provide support for mdl "exclude" on functions in
893 //  statically linked objects.
894 //  mcheyney 970727
895 const vector<pd_Function *> &image::getIncludedFunctions() {
896     //cerr << "image::getIncludedFunctions() called, about to return includedFunctions = " << endl;
897     //print_func_vector_by_pretty_name(string("  "), \
898     //        (vector<function_base*>*)&includedFunctions);
899     return includedFunctions;
900 }
901
902 const vector<pd_Function*> &image::getAllFunctions() {
903     //cerr << "pdmodule::getAllFunctions() called, about to return instrumentableFunctions = " << endl;
904     //print_func_vector_by_pretty_name(string("  "), \
905     //        (vector<function_base*>*)&instrumentableFunctions);
906     return instrumentableFunctions;
907 }
908
909 const vector <pdmodule*> &image::getAllModules() {
910     // reinit all modules to empty vector....
911     allMods.resize(0);
912
913     // and add includedModules && excludedModules to it....
914     allMods += includedMods;
915     allMods += excludedMods;
916
917     //cerr << "image::getAllModules called" << endl;
918     //cerr << " about to return sum of includedMods and excludedMods" << endl;
919     //cerr << " includedMods : " << endl;
920     //print_module_vector_by_short_name(string("  "), &includedMods);
921     //cerr << " excludedMods : " << endl;
922     //print_module_vector_by_short_name(string("  "), &excludedMods);
923     
924     return allMods;
925 }
926
927 const vector <pdmodule*> &image::getIncludedModules() {
928     //cerr << "image::getIncludedModules called" << endl;
929     //cerr << " about to return includedMods = " << endl;
930     //print_module_vector_by_short_name(string("  "), &includedMods);
931
932     return includedMods;
933 }
934
935 void print_module_vector_by_short_name(string prefix , \
936                                        vector<pdmodule*> *mods) {
937     unsigned int i;
938     pdmodule *mod;
939     for(i=0;i<mods->size();i++) {
940         mod = ((*mods)[i]);
941         cerr << prefix << mod->fileName() << endl;
942     }
943 }
944
945 void print_func_vector_by_pretty_name(string prefix, \
946                                       vector<function_base *>*funcs) {
947     unsigned int i;
948     function_base *func;
949     for(i=0;i<funcs->size();i++) {
950       func = ((*funcs)[i]);
951       cerr << prefix << func->prettyName() << endl;
952     }
953 }
954
955 // rip module name out of constraint....
956 // Assumes that constraint is of form module/function, or
957 // module.... 
958 string getModuleName(string constraint) {
959     string ret;
960
961     const char *data = constraint.string_of();
962     const char *first_slash = P_strchr(data, RH_SEPERATOR);
963     
964     // no "/", assume string holds module name....
965     if (first_slash == NULL) {
966         return constraint;
967     }    
968     // has "/", assume everything up to "/" is module name....
969     return string(data, first_slash - data);
970 }
971
972 // rip function name out of constraint....
973 // Assumes that constraint is of form module/function, or
974 // module.... 
975 string getFunctionName(string constraint) {
976     string ret;
977
978     const char *data = constraint.string_of();
979     const char *first_slash = P_strchr(data, RH_SEPERATOR);
980     
981     // no "/", assume constraint is module only....
982     if (first_slash == NULL) {
983         return string("");
984     }    
985     // has "/", assume everything after "/" is function....
986     return string(first_slash+1);
987 }
988
989
990 #ifndef BPATCH_LIBRARY
991 // mcheyney, Oct. 6, 1997
992 bool module_is_excluded(pdmodule *module) {
993     unsigned i;
994     string constraint_function_name;
995     string constraint_module_name;
996     string module_name = module->fileName();
997     // strings holding exclude constraints....
998     vector<string> func_constraints;
999     string empty_string("");
1000
1001     //cerr << "module_is_excluded " << module_name << " called" << endl;
1002
1003     // if unble to get list of excluded functions, assume all modules
1004     //  are NOT excluded!!!!
1005     if(mdl_get_lib_constraints(func_constraints) == FALSE) {
1006         //cerr << " (module_is_excluded) unable to mdl_get_lib_constrants, returning FALSE" << endl;
1007         return FALSE;
1008     }
1009
1010     // run through func_constraints, looking for a constraint
1011     //  where constraint_module_name == module_name && 
1012     //  constraint_function_name == ""....
1013     for(i=0;i<func_constraints.size();i++) {
1014         constraint_module_name = getModuleName(func_constraints[i]);
1015         if (constraint_module_name == module_name) {
1016             constraint_function_name = getFunctionName(func_constraints[i]);
1017             if (constraint_function_name == empty_string) {
1018                 //cerr << " (module_is_excluded) found matching constraint " << func_constraints[i] << " returning TRUE" << endl;
1019                 return TRUE;
1020             }
1021         }
1022     }
1023
1024     //cerr << " (module_is_excluded) didnt find matching constraint returning FALSE" << endl;
1025     return FALSE;
1026 }
1027
1028 // mcheyney, Oct. 3, 1997
1029 // Return boolean value indicating whether function is found to
1030 //  be excluded (via "exclude module_name" or "exclude module_name/
1031 //  function_name").
1032 bool function_is_excluded(pd_Function *func, string module_name) {
1033     // strings holding exclude constraints....
1034     vector<string> func_constraints;
1035     string function_name = func->prettyName();
1036     string constraint_function_name;
1037     string constraint_module_name;
1038     unsigned i;
1039
1040     //cerr << "function_is_excluded " << function_name << " , " << \
1041       module_name << " called" << endl;
1042
1043     // if unble to get list of excluded functions, assume all functions
1044     //  are NOT excluded!!!!
1045     if(mdl_get_lib_constraints(func_constraints) == FALSE) {
1046         //cerr << " (function_is_excluded) unable to mdl_get_lib_constrants, returning FALSE" << endl;
1047         return FALSE;
1048     }
1049
1050     // run through func_constraints, looking for a constraint of 
1051     //  form module_name/function_name....
1052     for(i=0;i<func_constraints.size();i++) {
1053         constraint_module_name = getModuleName(func_constraints[i]);
1054         if (constraint_module_name == module_name) { 
1055             constraint_function_name = getFunctionName(func_constraints[i]);
1056             if (constraint_function_name == function_name) {
1057                 //cerr << " (function_is_excluded) found matching constraint " << func_constraints[i] << " returning TRUE" << endl;
1058                 return TRUE;
1059             }
1060         }
1061     }
1062
1063     //cerr << " (function_is_excluded) didnt find matching constraint, returing FALSE" << endl;
1064     return FALSE;
1065 }
1066
1067 //
1068 // mcheyney, Sep 28, 1997
1069 // Take a list of functions (in vector <all_funcs>.  Copy all
1070 //  of those functions which are not excluded (via "exclude" 
1071 //  {module==module_name}/{function==function_name) into
1072 //  <some_functions>.
1073 // Returns status of mdl_get_lib_constraints() call.
1074 //  If this status == FALSE< some_funcs is not modified....
1075 // We assume that all_funcs is generally longer than the list
1076 //  of constrained functions.  As such, internally proc. copies
1077 //  all funcs into some funcs, then runs over excluded funcs
1078 //  removing any matches, as opposed to doing to checking 
1079 //  while adding to some_funcs....
1080 bool filter_excluded_functions(vector<pd_Function*> all_funcs, \
1081     vector<pd_Function*>& some_funcs, string module_name) {
1082
1083     u_int i, j;
1084     // strings holding exclude constraints....
1085     vector<string> func_constraints;
1086     string constraint_module_name, constraint_function_name, empty_string;
1087     vector<string> tstrings;
1088     bool excluded;
1089
1090     empty_string = string("");
1091
1092     //cerr << "filter_excluded_functions called : " << endl;
1093     //cerr << " module_name = " << module_name << endl;
1094     //cerr << " all_funcs (by pretty name ) : " << endl;
1095     //for(i=0;i<all_funcs.size();i++) {
1096     //    cerr << "  " << all_funcs[i]->prettyName() << endl;
1097     //}
1098     
1099
1100     // if you cannot get set of lib constraints, return FALSE w/o
1101     // modifying some_funcs....
1102     if(mdl_get_lib_constraints(func_constraints) == FALSE) {
1103         if (0) {
1104             //cerr << " could not mdl_get_lib_constraints, about to return FALSE" \
1105                << endl;
1106         }
1107         return FALSE;
1108     }
1109
1110     // run through func_constraints, filtering all constraints
1111     //  not of form module/function, and all constraints of that
1112     //  form where constraint module name != module_name....
1113     for(i=0;i<func_constraints.size();i++) {
1114         constraint_module_name = getModuleName(func_constraints[i]);
1115         //cerr << "constraint = " << func_constraints[i] << endl;
1116         //cerr << " constraint_module_name = " << constraint_module_name \
1117                  << endl;
1118         
1119         if (module_name == constraint_module_name) {
1120             constraint_function_name = getFunctionName(func_constraints[i]);
1121             if (constraint_function_name != empty_string) { 
1122                 tstrings += getFunctionName(func_constraints[i]);
1123             }
1124         }
1125     }
1126     func_constraints = tstrings;
1127     
1128     //cerr << "func_constraints = " << endl;
1129     //for(i=0;i<func_constraints.size();i++) {
1130     //    cerr << "  " << func_constraints[i] << endl;
1131     //}
1132    
1133
1134     // run over functions in all_funcs.  If they dont match an excluded 
1135     //  function in module_name, then push them onto some_funcs....
1136     for(i=0;i<all_funcs.size();i++) {
1137         excluded = FALSE;
1138         for(j=0;j<func_constraints.size();j++) {
1139             if (all_funcs[i]->prettyName() == func_constraints[j]) {
1140                 excluded = TRUE;
1141                 break;
1142             }
1143         }
1144         if (excluded == FALSE) {
1145             some_funcs += all_funcs[i]; 
1146         }
1147     }
1148
1149     //cerr << " looks successful : about to return TRUE" << endl;
1150     //cerr << " some_funcs (by pretty name) " << endl;
1151     //for (i=0;i<some_funcs.size();i++) {
1152     //    cerr << "  " << some_funcs[i]->prettyName() << endl;
1153     //}
1154     
1155     return TRUE;
1156 }
1157 #endif /* BPATCH_LIBRARY */
1158
1159 // I commented this out since gcc says it ain't used --ari 10/97
1160 // I then uncommented it because non-Solaris platforms need it --ssuen 10/10/97
1161 static void binSearch (const Symbol &lookUp, vector<Symbol> &mods,
1162                        string &modName, Address &modAddr, const string &def) {
1163   int start=0, end=mods.size()-1, index;
1164   bool found=false;
1165
1166   if (!mods.size()) {
1167     modAddr = 0;
1168     modName = def;
1169     return;
1170   }
1171
1172   while ((start <= end) && !found) {
1173     index = (start+end)/2;
1174
1175     if ((index == (((int)mods.size())-1)) ||
1176         ((mods[index].addr() <= lookUp.addr()) && (mods[index+1].addr() > lookUp.addr()))) {
1177       modName = mods[index].name();
1178       modAddr = mods[index].addr();      
1179       found = true;
1180     } else if (lookUp.addr() < mods[index].addr()) {
1181       end = index - 1;
1182     } else {
1183       start = index + 1;
1184     }
1185   }
1186   if (!found) {
1187     modName = mods[0].name();
1188     modAddr = mods[0].addr();
1189   }
1190 }
1191
1192 // COMMENTS????
1193 // 
1194 bool image::addOneFunction(vector<Symbol> &mods,  \
1195                            pdmodule *lib, \
1196                            pdmodule *, \
1197                            const Symbol &lookUp, pd_Function  *&retFunc) {
1198   // TODO mdc
1199   // find the module
1200   // this is a "user" symbol
1201   string modName = lookUp.module();
1202   Address modAddr = 0;
1203   
1204   string progName = name_ + "_module";
1205
1206 #if defined (sparc_sun_solaris2_4) || defined (i386_unknown_solaris2_5) || defined (i386_unknown_linux2_0) 
1207   // In solaris there is no address for modules in the symbol table, 
1208   // so the binary search will not work. The module field in a symbol
1209   // already has the correct module name for a symbol, if it can be
1210   // obtained from the symbol table, otherwise the module is an empty
1211   // string.
1212   if (modName == "") {
1213     modName = progName;
1214   }
1215 #else
1216   binSearch(lookUp, mods, modName, modAddr, progName);
1217 #endif
1218
1219   return (defineFunction(lib, lookUp, modName, modAddr, retFunc));
1220 }
1221
1222 bool inLibrary(Address addr, Address boundary_start, Address boundary_end,
1223                       Address startAddr, bool startB,
1224                       Address endAddr, bool endB) {
1225   if ((addr >= boundary_start) && (addr <= boundary_end))
1226     return true;
1227   else if (startB) {
1228     if (addr <= startAddr)
1229       return true;
1230     else if (endB) {
1231       if (addr >= endAddr)
1232         return true;
1233       else 
1234         return false;
1235     } else 
1236       return false;
1237   } else if (endB) {
1238     if (addr >= endAddr)
1239       return true;
1240     else
1241       return false;
1242   } else
1243     return false;
1244 }
1245
1246 #ifdef NOT_DEFINED
1247 // as per getAllFunctions, but filters out those excluded with 
1248 // e.g. mdl "exclude" command....
1249 // Note that unlike several other paradynd classes, we do
1250 // not allocate a seperate list of some functions , but rather
1251 // filter the list of all functions whenevr queried for list 
1252 // of included funtions.....
1253 const vector<pd_Function*> &image::getIncludedFunctions() {
1254     unsigned int i;    
1255     includedFunctions.resize(0);
1256     vector<function_base *> *temp;
1257     vector<pd_Function *> *temp2;
1258
1259     //cerr << "image::getIncludedFunctions called, name = " << name () << endl;
1260     //cerr << " mods = " << endl;
1261     //print_module_vector_by_short_name(string("  "), &mods);
1262
1263     for (i=0;i<mods.size();i++) {
1264          temp = mods[i]->getIncludedFunctions();
1265          temp2 = (vector<pd_Function *> *) temp;
1266          includedFunctions += *temp2;
1267     }
1268
1269     //cerr << " (image::getIncludedFunctions) returning : " << endl;
1270     //print_func_vector_by_pretty_name(string("  "), \
1271     //           (vector<function_base*>*)&includedFunctions);
1272
1273     // what about shared objects????
1274     return includedFunctions;
1275 }
1276 #endif
1277
1278 //  COMMENTS??  HELLO?
1279 //  Here's a guess what this function tries to do:
1280 //  a. look through (data member of type Object) linkedFile,
1281 //   trying to file DYNINSTstart and DYNINSTend sections (
1282 //   beginning + ending of instrumentation code).
1283 //  b. ditto for main function (note variant names under which
1284 //   these functions are searched for)....
1285 //  c. iterate over all functions in linkedFile:
1286 //    if the function has already been defined, OR shadows the
1287 //     main function (has same address) - ignore it.
1288 //    else - 
1289 //     use (member function) inLibrary() to check
1290 //     whether function is in range of instrumented code (between
1291 //     DYNINSTstart and DYNINSTend)
1292 //     if in range - addInternalSymbol().
1293 //     else addOneFunction().
1294 //
1295 //  Questions : what do params mean????
1296 bool image::addAllFunctions(vector<Symbol> &mods,
1297                             pdmodule *lib, pdmodule *dyn, 
1298                             const bool startB, const Address startAddr,
1299                             const bool endB, const Address endAddr) {
1300
1301   Address boundary_start, boundary_end;
1302   Symbol lookUp;
1303   string symString;
1304
1305 #ifdef BPATCH_LIBRARY
1306   boundary_start = boundary_end = NULL;
1307 #else
1308   if (!linkedFile.get_symbol(symString="DYNINSTfirst", lookUp) &&
1309       !linkedFile.get_symbol(symString="_DYNINSTfirst", lookUp)) {
1310     //statusLine("Internal symbol DYNINSTfirst not found");
1311     //showErrorCallback(31, "Internal symbol DYNINSTfirst not found");
1312     //return false;
1313     boundary_start = NULL;
1314   } else
1315     boundary_start = lookUp.addr();
1316
1317   if (!linkedFile.get_symbol(symString="DYNINSTend", lookUp) &&
1318       !linkedFile.get_symbol(symString="_DYNINSTend", lookUp)) {
1319     //statusLine("Internal symbol DYNINSTend not found");
1320     //showErrorCallback(32, "Internal symbol DYNINSTend not found");
1321     //return false;
1322     boundary_end = NULL;
1323   } else
1324     boundary_end = lookUp.addr();
1325 #endif
1326
1327   Symbol mainFuncSymbol;  //Keeps track of info on "main" function
1328
1329   //Checking "main" function names in same order as in the inst-*.C files
1330   if (linkedFile.get_symbol(symString="main",     lookUp) ||
1331       linkedFile.get_symbol(symString="_main",    lookUp) ||
1332       linkedFile.get_symbol(symString="WinMain",  lookUp) ||
1333       linkedFile.get_symbol(symString="_WinMain", lookUp)) 
1334     mainFuncSymbol = lookUp;
1335
1336   // find the real functions -- those with the correct type in the symbol table
1337   for(SymbolIter symIter = linkedFile; symIter;symIter++) {
1338     const Symbol &lookUp = symIter.currval();
1339
1340     if (funcsByAddr.defines(lookUp.addr()) ||
1341         ((lookUp.addr() == mainFuncSymbol.addr()) &&
1342          (lookUp.name() != mainFuncSymbol.name()))) {
1343       // This function has been defined 
1344       // *or*
1345       // This function has the same address as the "main" function but does 
1346       //   not have the same name as the "main" function.  Therefore, skip
1347       //   it and let the "main" function be eventually associated with this
1348       //   function address.  If we don't do this, paradynd will not have a
1349       //   "main" function to start work with.
1350       ;
1351     } else if (lookUp.type() == Symbol::PDST_FUNCTION) {
1352       if (!isValidAddress(lookUp.addr())) {
1353         string msg;
1354         char tempBuffer[40];
1355         sprintf(tempBuffer,"%x",lookUp.addr());
1356         msg = string("Function") + lookUp.name() + string("has bad address ") +
1357               string(tempBuffer);
1358         statusLine(msg.string_of());
1359         showErrorCallback(29, msg);
1360         return false;
1361       }
1362       insert_function_internal_static(mods, lookUp, boundary_start,
1363               boundary_end, startAddr, startB, endAddr, endB, dyn, lib);
1364     }
1365   }
1366
1367   // now find the pseudo functions -- this gets ugly
1368   // kludge has been set if the symbol could be a function
1369   for(SymbolIter symIter2 = linkedFile;symIter2;symIter2++) {
1370     lookUp = symIter2.currval();
1371     if (funcsByAddr.defines(lookUp.addr())) {
1372         // This function has been defined
1373         ;
1374     } else if ((lookUp.type() == Symbol::PDST_OBJECT) && lookUp.kludge()) {
1375         //logLine(P_strdup(symString.string_of()));
1376         // see comment under image::insert_function_internal_static,
1377         // below....
1378         insert_function_internal_static(mods, lookUp, boundary_start, \
1379               boundary_end, startAddr, startB, endAddr, endB, dyn, lib);
1380     }
1381   }
1382   return true;
1383 }
1384
1385 bool image::addAllSharedObjFunctions(vector<Symbol> &mods,
1386                             pdmodule *lib, pdmodule *dyn) {
1387
1388   Symbol lookUp;
1389   string symString;
1390
1391   bool is_libdyninstRT = false; // true if this image is libdyninstRT
1392 #if defined(i386_unknown_nt4_0)
1393   if (linkedFile.get_symbol(symString="_DYNINSTfirst", lookUp)
1394       || linkedFile.get_symbol(symString="_DYNINSTfirst", lookUp))
1395     is_libdyninstRT = true;
1396 #endif
1397
1398   // find the real functions -- those with the correct type in the symbol table
1399   for(SymbolIter symIter3 = linkedFile;symIter3;symIter3++) { 
1400     const Symbol &lookUp = symIter3.currval();
1401     if (funcsByAddr.defines(lookUp.addr())) {
1402       // This function has been defined
1403       ;
1404     } else if (lookUp.type() == Symbol::PDST_FUNCTION) {
1405       if (!isValidAddress(lookUp.addr())) {
1406         string msg;
1407         char tempBuffer[40];
1408         sprintf(tempBuffer,"%x",lookUp.addr());
1409         msg = string("Function") + lookUp.name() + string("has bad address ") +
1410               string(tempBuffer);
1411         statusLine(msg.string_of());
1412         showErrorCallback(29, msg);
1413         return false;
1414       }
1415       // see comment under image::insert_functions_internal_dynamic,
1416       //  below....
1417       insert_function_internal_dynamic(mods, lookUp, dyn, lib, \
1418                                        is_libdyninstRT);
1419     }
1420   }
1421
1422   // now find the pseudo functions -- this gets ugly
1423   // kludge has been set if the symbol could be a function
1424   for(SymbolIter symIter4 = linkedFile;symIter4;symIter4++) {
1425     const Symbol &lookUp = symIter4.currval();
1426     if (funcsByAddr.defines(lookUp.addr())) {
1427       // This function has been defined
1428       ;
1429     } else if ((lookUp.type() == Symbol::PDST_OBJECT) && lookUp.kludge()) {
1430       pd_Function *pdf;
1431       addInternalSymbol(lookUp.name(), lookUp.addr());
1432       defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf);
1433     }
1434   }
1435   return true;
1436
1437
1438
1439 bool image::addAllVariables()
1440 {
1441 /* Eventually we'll have to do this on all platforms (because we'll retrieve
1442  * the type information here).
1443  */
1444 #ifdef i386_unknown_nt4_0
1445   string mangledName; 
1446   Symbol symInfo;
1447
1448   for(SymbolIter symIter = linkedFile; symIter; symIter++) {
1449      const string &mangledName = symIter.currkey();
1450      const Symbol &symInfo = symIter.currval();
1451
1452     if (symInfo.type() == Symbol::PDST_OBJECT) {
1453       char *name = cplus_demangle((char *)mangledName.string_of(), 0);
1454       const char *unmangledName;
1455       if (name) unmangledName = name;
1456       else unmangledName = mangledName.string_of();
1457       if (varsByPretty.defines(unmangledName)) {
1458           *(varsByPretty[unmangledName]) += string(mangledName);
1459       } else {
1460           vector<string> *varEntry = new vector<string>;
1461           *varEntry += string(mangledName);
1462           varsByPretty[unmangledName] = varEntry;
1463       }
1464       if (name) free(name);
1465     }
1466   }
1467 #endif
1468   return true;
1469 }
1470
1471 int symCompare(const void *s1, const void *s2) {
1472   const Symbol *sym1 = (const Symbol*)s1, *sym2 = (const Symbol*)s2;
1473   // TODO mdc
1474   return (sym1->addr() - sym2->addr());
1475 }
1476
1477
1478 unsigned int_addrHash(const unsigned &addr) {
1479   return addr;
1480 }
1481
1482 // Please note that this is now machine independent-almost.  Let us keep it that way
1483 // COMMENTS????
1484 //  Guesses as to what this cod does....
1485 //  image constructor:
1486 //   construct an image corresponding to the executable file on path
1487 //   fileName.  Fill in err based on success or failure....
1488 image::image(const string &fileName, bool &err)
1489 :   modsByFileName(string::hash),
1490     modsByFullName(string::hash),
1491     includedFunctions(0),
1492     excludedFunctions(string::hash),
1493     instrumentableFunctions(0),
1494     notInstruFunctions(string::hash),
1495     funcsByAddr(addrHash4),
1496     funcsByPretty(string::hash),
1497     file_(fileName),
1498     linkedFile(fileName, pd_log_perror),
1499     iSymsMap(string::hash),
1500     varsByPretty(string::hash),
1501     knownJumpTargets(int_addrHash, 8192)
1502 {
1503     sharedobj_cerr << "image::image for non-sharedobj; file name=" << \
1504       file_ << endl;
1505
1506     // shared_object and static object (a.out) constructors merged into
1507     //  common initialize routine.... 
1508     initialize(fileName, err, 0);
1509 }
1510
1511 // 
1512 // load a shared object
1513 //
1514 image::image(const string &fileName, u_int baseAddr, bool &err)
1515 :   
1516     modsByFileName(string::hash),
1517     modsByFullName(string::hash),
1518     includedFunctions(0),
1519     excludedFunctions(string::hash),
1520     instrumentableFunctions(0),
1521     notInstruFunctions(string::hash),
1522     funcsByAddr(addrHash4),
1523     funcsByPretty(string::hash),
1524     file_(fileName),
1525     linkedFile(fileName, baseAddr,pd_log_perror),
1526     iSymsMap(string::hash),
1527     varsByPretty(string::hash),
1528     knownJumpTargets(int_addrHash, 8192)
1529 {
1530 sharedobj_cerr << "welcome to image::image for shared obj; file name=" << file_ << endl;
1531
1532     // shared_object and static object (a.out) constructors merged into
1533     //  common initialize routine.... 
1534     initialize(fileName, err, 1, baseAddr);
1535 }
1536
1537 static bool findStartSymbol(Object &lf, Address &adr) {
1538   Symbol lookUp;
1539
1540   if (lf.get_symbol("DYNINSTstartUserCode", lookUp) ||
1541       lf.get_symbol("_DYNINSTstartUserCode", lookUp)) {
1542     adr = lookUp.addr();
1543     return true;
1544   } else
1545     return false;
1546 }
1547
1548 static bool findEndSymbol(Object &lf, Address &adr) {
1549   Symbol lookUp;
1550
1551   if (lf.get_symbol("DYNINSTendUserCode", lookUp) ||
1552       lf.get_symbol("_DYNINSTendUserCode", lookUp)) {
1553     adr = lookUp.addr();
1554     return true;
1555   } else
1556     return false;
1557 }
1558
1559 /*
1560     image::initialize - called by image a.out and shared_object 
1561     constructor to do common initialization....
1562
1563     paramaters - 
1564
1565       shared_object - pass 0 to denote initializing from statically
1566         linked executable (a.out file), pass 1 to denote initializing
1567         from shared library.
1568       base_addr - curr. used IFF shared_library == 1.
1569  */
1570 void image::initialize(const string &fileName, bool &err, \
1571         bool shared_object, u_int) {
1572
1573     // initialize (data members) codeOffset_, dataOffset_, \
1574     //  codeLen_, dataLen_.
1575     codeOffset_ = linkedFile.code_off();
1576     dataOffset_ = linkedFile.data_off();
1577     codeLen_ = linkedFile.code_len();
1578     dataLen_ = linkedFile.data_len();
1579
1580 #if defined(hppa1_1_hp_hpux)
1581   unwind   = linkedFile.unwind;
1582 #endif
1583
1584     // if unable to parse object file (somehow??), try to
1585     //  notify luser/calling process + return....    
1586     if (!codeLen_ || !linkedFile.code_ptr()) {
1587         string msg = string("Unable to open executable file: ") + fileName;
1588         statusLine(msg.string_of());
1589         msg += "\n";
1590         logLine(msg.string_of());
1591         err = true;
1592         showErrorCallback(27, msg); 
1593         return;
1594     }
1595
1596 #if !defined(i386_unknown_nt4_0) && !defined(USES_LIBDYNINSTRT_SO)
1597     // on architectures where statically linked programs to be run 
1598     //  w/ paradyn need to link with the DYNINST library, try to find
1599     //  the paradyn lib version # (DYNINSTversion or _DYNINSTversion
1600     //  symbol).
1601     if (!shared_object) {
1602         Symbol version;
1603         if (!linkedFile.get_symbol("DYNINSTversion", version) &&
1604                 !linkedFile.get_symbol("_DYNINSTversion", version)) {
1605             statusLine("Could not find version number in instrumentation\n");
1606             showErrorCallback(33, "Could not find version number in instrumentation");
1607             err = true;
1608             return;
1609         }
1610
1611         Word version_number = get_instruction(version.addr());
1612         if (version_number != 1) {
1613             string msg;
1614             msg = string("Incorrect version number, expected ") + string(1) + 
1615                  string("found ") + string(version_number);
1616             statusLine(msg.string_of());
1617             showErrorCallback(30, msg);
1618             err = true;
1619             return;
1620         }
1621     }
1622 #endif
1623
1624     string msg;
1625     // give luser some feedback....
1626     if (shared_object) {
1627         msg = string("Parsing shared object file : ") + fileName;
1628     } else {
1629         msg = string("Parsing static object file : ") + fileName;
1630     }
1631     statusLine(msg.string_of());
1632
1633     const char *nm = fileName.string_of();
1634     const char *pos = P_strrchr(nm, '/');
1635
1636     err = false;
1637     if (pos)
1638         name_ = pos + 1;
1639     else
1640         name_ = fileName;
1641
1642     // use the *DUMMY_MODULE* until a module is defined
1643     pdmodule *dynModule = newModule(DYN_MODULE, 0);
1644     pdmodule *libModule = newModule(LIBRARY_MODULE, 0);
1645     // TODO -- define inst points in define function ?
1646
1647     // The functions cannot be verified until all of them have been seen
1648     // because calls out of each function must be tagged as calls to user
1649     // functions or call to "library" functions
1650
1651     Symbol lookUp;
1652     string symString;
1653
1654     //
1655     // sort the modules by address into a vector to allow a binary search to 
1656     // determine the module that a symbol will map to -- this 
1657     // may be bsd specific....
1658     //
1659     vector <Symbol> tmods;
1660
1661     for (SymbolIter symIter = linkedFile; symIter; symIter++) {
1662         const Symbol &lookUp = symIter.currval();
1663         if (lookUp.type() == Symbol::PDST_MODULE) {
1664             const string &lookUpName = lookUp.name();
1665             const char *str = lookUpName.string_of();
1666             assert(str);
1667             int ln = lookUpName.length();
1668
1669             // directory definition -- ignored for now
1670             if (str[ln-1] != '/') {
1671                 tmods += lookUp;
1672             }
1673         }
1674     }
1675
1676     // sort the modules by address
1677     statusLine("sorting modules");
1678     tmods.sort(symCompare);
1679     //  assert(mods.sorted(symCompare));
1680
1681     // remove duplicate entries -- some .o files may have the same 
1682     // address as .C files.  kludge is true for module symbols that 
1683     // I am guessing are modules
1684     vector<Symbol> uniq;
1685     unsigned loop=0;
1686
1687     // must use loop+1 not mods.size()-1 since it is an unsigned compare
1688     //  which could go negative - jkh 5/29/95
1689     for (loop=0; loop < tmods.size(); loop++) {
1690         if ((loop+1 < tmods.size()) && 
1691                 (tmods[loop].addr() == tmods[loop+1].addr())) {
1692             if (!tmods[loop].kludge())
1693                 tmods[loop+1] = tmods[loop];
1694         } 
1695         else
1696           uniq += tmods[loop];
1697     }
1698
1699     // define all of the functions
1700     statusLine("winnowing functions");
1701
1702     // register functions differently depending on whether parsing 
1703     //  shared object or static executable.  
1704     // THIS MAY CHANGE WHEN REMOVE DYNINSTstart && DYNINSTend hacks....
1705     if (!shared_object) {
1706         // find the "user" code boundaries
1707         statusLine("finding user code boundaries");
1708         Address startUserAddr=0, endUserAddr=0;
1709         bool startBound = findStartSymbol(linkedFile, startUserAddr);
1710         bool endBound = findEndSymbol(linkedFile, endUserAddr);
1711
1712         if (!addAllFunctions(uniq, libModule, dynModule, startBound, \
1713                 startUserAddr, endBound, endUserAddr)) {
1714             err = true;
1715             return;
1716         }
1717     } else {
1718         // define all of the functions
1719         if (!addAllSharedObjFunctions(uniq, libModule, dynModule)) {
1720             err = true;
1721             return;
1722         }
1723     }
1724
1725     // ALERT ALERT - Calling on both shared_object && !shared_object path.
1726     //  In origional code, only called in !shared_object case.  Was this 
1727     //  a bug????
1728     // XXX should have a statusLine("retrieving variable information") here,
1729     //     but it's left out for now since addAllVariables only does something
1730     //     when BPATCH_LIBRARY is defined
1731     addAllVariables();
1732
1733     statusLine("checking call points");
1734     checkAllCallPoints();
1735
1736     // TODO -- remove duplicates -- see earlier note
1737     dictionary_hash<unsigned, unsigned> addr_dict(uiHash);
1738     vector<pd_Function*> temp_vec;
1739
1740     // question??  Necessary to do same crap to includedFunctions &&
1741     //  excludedFunctions??
1742     unsigned f_size = instrumentableFunctions.size(), index;
1743     for (index=0; index<f_size; index++) {
1744         const unsigned the_address = (unsigned)instrumentableFunctions[index]\
1745                                                ->getAddress(0);
1746         if (!addr_dict.defines(the_address)) {
1747             addr_dict[the_address] = 1;
1748             temp_vec += instrumentableFunctions[index];
1749         }
1750     }
1751     instrumentableFunctions = temp_vec;
1752 }
1753
1754
1755 void pdmodule::checkAllCallPoints() {
1756   unsigned fsize = funcs.size();
1757   for (unsigned f=0; f<fsize; f++)
1758       funcs[f]->checkCallPoints();
1759 }
1760
1761
1762 void image::checkAllCallPoints() {
1763   dictionary_hash_iter<string, pdmodule*> di(modsByFullName);
1764   string s; pdmodule *mod;
1765   while (di.next(s, mod))
1766     mod->checkAllCallPoints();
1767 }
1768
1769 // passing in tags allows a function to be tagged as TAG_LIB_FUNC even
1770 // if its entry is not in the tag dictionary of known functions
1771 bool image::defineFunction(pdmodule *use, const Symbol &sym, const unsigned tags,
1772                            pd_Function *&retFunc) {
1773   // We used to skip a leading underscore, but not anymore.
1774   // (I forgot why we ever did in the first place)
1775
1776   unsigned dictTags = findTags(sym.name());
1777   return (newFunc(use, sym.name(), sym.addr(), sym.size(), tags | dictTags, retFunc));
1778 }
1779
1780 pdmodule *image::getOrCreateModule(const string &modName, 
1781                                       const Address modAddr) {
1782   const char *str = modName.string_of();
1783   int len = modName.length();
1784   assert(len>0);
1785
1786   // TODO ignore directory definitions for now
1787   if (str[len-1] == '/') {
1788     return NULL;
1789   } else {
1790     // TODO - navigate ".." and "."
1791     const char *lastSlash = P_strrchr(str, '/');
1792     if (lastSlash)
1793       return (newModule(++lastSlash, modAddr));
1794     else
1795       return (newModule(modName, modAddr));
1796   }
1797 }
1798
1799 // COMMENTS????
1800 // looks like wrapper function for (member function) newFunc.
1801 //  appears to do some fiddling with tags paramater to that
1802 //  function.
1803 // Kludge TODO - internal functions are tagged with TAG_LIB_FUNC
1804 // but they won't have tags in the tag dict, so this happens...
1805 bool image::defineFunction(pdmodule *libModule, const Symbol &sym,
1806                            const string &modName, const Address modAddr,
1807                            pd_Function *&retFunc) {
1808
1809   // We used to skip a leading underscore, but not any more.
1810
1811   unsigned tags = findTags(sym.name());
1812
1813   if (TAG_LIB_FUNC & tags)
1814     return (newFunc(libModule, sym.name(), sym.addr(), sym.size(),
1815                     tags | TAG_LIB_FUNC, retFunc));
1816   else {
1817     pdmodule *use = getOrCreateModule(modName, modAddr);
1818     assert(use);
1819     return (newFunc(use, sym.name(), sym.addr(), sym.size(), tags, retFunc));
1820   }
1821 }
1822
1823 // Verify that this is code
1824 // Find the call points
1825 // Find the return address
1826 // TODO -- use an instruction object to remove
1827 // Sets err to false on error, true on success
1828 //
1829 // Note - this must define funcEntry and funcReturn
1830 // 
1831 pd_Function::pd_Function(const string &symbol, const string &pretty, 
1832                        pdmodule *f, Address adr, const unsigned size, 
1833                        const unsigned tg, const image *owner, bool &err) : 
1834   function_base(symbol, pretty, adr, size,tg),
1835   file_(f),
1836   funcEntry_(0),
1837   relocatable_(false)
1838 {
1839   err = findInstPoints(owner) == false;
1840 }
1841
1842 // image::addAllFunctions dupliactes this section of code.
1843 // As part of an effort to clean up the code a bit, I merged the
1844 // duplicates into this 1 function.  
1845 void image::insert_function_internal_static(vector<Symbol> &mods, \
1846         const Symbol &lookUp, \
1847         const Address boundary_start,  const Address boundary_end, \
1848         const Address startAddr, bool startB, const Address endAddr, \
1849         bool endB, pdmodule *dyn, pdmodule *lib) {
1850     pd_Function *pdf;
1851     //  COMMENTS??
1852     //  If CONDITION??
1853     if (inLibrary(lookUp.addr(), boundary_start, boundary_end,
1854                     startAddr, startB, endAddr, endB)) {
1855         // look at symbol name.  If it looks like "_DYNINST*" or 
1856         // "_TRACELIN*", add it to iSymsMap data member....
1857         addInternalSymbol(lookUp.name(), lookUp.addr());
1858         defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf);
1859     } else {
1860         addOneFunction(mods, lib, dyn, lookUp, pdf);
1861     } 
1862 }
1863
1864 // version of insert_function_internal_static (above) for 
1865 // shared objects....
1866 void image::insert_function_internal_dynamic(vector<Symbol> &mods,\
1867         const Symbol &lookUp, \
1868         pdmodule *dyn, pdmodule *lib, bool is_libdyninstRT) {
1869     pd_Function *pdf;
1870     if (is_libdyninstRT) {
1871         addInternalSymbol(lookUp.name(), lookUp.addr());
1872         defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf);
1873     } else {
1874         addOneFunction(mods, lib, dyn, lookUp, pdf);
1875     }
1876 }