patch to fix exclude whole module
[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)+pdf->size())))
623           return pdf;
624   }
625
626   // and in excludedFunctions....
627   values = excludedFunctions.values();
628   for (i = 0; i < values.size(); i++) {
629       pdf = values[i];
630       if ((addr>=pdf->getAddress(p))&&(addr<=(pdf->getAddress(p)+pdf->size())))
631           return pdf;
632   }
633
634   return NULL; 
635 }
636  
637 pd_Function *image::findFunctionIn(const Address &addr,const process *p) const 
638 {
639   pd_Function *pdf;
640
641   // first, look in funcsByAddr - should contain instrumentable non-
642   //  excluded functions....
643   dictionary_hash_iter<Address, pd_Function*> mi(funcsByAddr);
644   Address adr;
645   while (mi.next(adr, pdf)) {
646       if ((addr>=pdf->getAddress(p))&&(addr<=(pdf->getAddress(p)+pdf->size()))) 
647           return pdf;
648   }
649   
650   // next, look in excludedFunctions...
651   dictionary_hash_iter<string, pd_Function*> ex(excludedFunctions);
652   string str;
653   while (ex.next(str, pdf)) {
654      if ((addr>=pdf->getAddress(p)) &&
655               (addr<=(pdf->getAddress(p)+pdf->size()))) 
656           return pdf;
657   }
658
659   dictionary_hash_iter<string, pd_Function *> ni(notInstruFunctions);
660   while (ni.next(str, pdf)) {
661       if ((addr>=pdf->getAddress(p)) &&
662               (addr<=(pdf->getAddress(p)+pdf->size()))) 
663           return pdf;
664   }
665
666   return NULL; 
667 }
668
669
670 #ifndef BPATCH_LIBRARY
671 void image::changeLibFlag(resource *res, const bool setSuppress)
672 {
673   image *ret;
674   pdmodule *mod;
675
676   unsigned numImages = image::allImages.size();
677   for (unsigned u=0; u<numImages; u++) {
678     ret = image::allImages[u];
679     // assume should work even if module excluded....
680     mod = ret->findModule(res->part_name(), TRUE);
681     if (mod) {
682       // suppress all procedures.
683       mod->changeLibFlag(setSuppress);
684     } else {
685       // more than one function may have this name --> templates, statics
686       vector<pd_Function*> pdfA;
687       if (ret->findFunction(res->part_name(), pdfA)) {
688         for (unsigned i=0; i<pdfA.size(); ++i) {
689           if (setSuppress) 
690             pdfA[i]->tagAsLib();
691           else
692             pdfA[i]->untagAsLib();
693         }
694       }
695     }
696   }
697 }
698 #endif
699
700
701 /* 
702  * return 0 if symbol <symname> exists in image, non-zero if it does not
703  */
704 bool image::symbolExists(const string &symname)
705 {
706   pd_Function *dummy = findOneFunction(symname);
707   return (dummy != NULL);
708 }
709
710 void image::postProcess(const string pifname)
711 {
712   FILE *Fil;
713   string fname, errorstr;
714   char key[5000];
715   char tmp1[5000], abstraction[500];
716 #ifndef BPATCH_LIBRARY
717   resource *parent;
718 #endif
719
720   return;
721
722   /* What file to open? */
723   if (!(pifname == (char*)NULL)) {
724     fname = pifname;
725   } else {
726     fname = file_ + ".pif";
727   }
728
729   /* Open the file */
730   Fil = P_fopen(fname.string_of(), "r");
731
732   if (Fil == NULL) {
733     errorstr = string("Tried to open PIF file ") + fname;
734     errorstr += string(", but could not (continuing)\n");
735     logLine(P_strdup(errorstr.string_of()));
736     showErrorCallback(35, errorstr); 
737     return;
738   }
739
740   /* Process the file */
741   while (!feof(Fil)) {
742     fscanf(Fil, "%s", key);
743     switch (key[0]) {
744     case 'M':
745       /* Ignore mapping information for right now */
746       fgets(tmp1, 5000, Fil);
747       break;
748     case 'R':
749 #ifndef BPATCH_LIBRARY
750       /* Create a new resource */
751       fscanf(Fil, "%s {", abstraction);
752       parent = rootResource;
753       do {
754         fscanf(Fil, "%s", tmp1);
755         if (tmp1[0] != '}') {
756           parent = resource::newResource(parent, NULL,
757                                          abstraction,
758                                          tmp1, 0.0,
759                                          nullString, // uniqifier
760                                          MDL_T_STRING,
761                                          true);
762         } else {
763           parent = NULL;
764         }
765       } while (parent != NULL);
766 #endif
767       break;
768     default:
769       errorstr = string("Ignoring bad line key (") + fname;
770       errorstr += string(") in file %s\n");
771       logLine(P_strdup(errorstr.string_of()));
772       fgets(tmp1, 5000, Fil);
773       break;
774     }
775   }
776   return;
777 }
778
779 void image::defineModules() {
780   unsigned i;
781
782   string pds; pdmodule *mod;
783   dictionary_hash_iter<string, pdmodule*> mi(modsByFileName);
784
785   while (mi.next(pds, mod)){
786     mod->define();
787   }
788
789   for(i=0;i<excludedMods.size();i++) {
790     mod = excludedMods[i];
791     mod->define();
792   }
793
794 #ifdef DEBUG_MDL
795   char buffer[100];
796   ostrstream osb(buffer, 100, ios::out);
797   osb << "IMAGE_" << name() << "__" << getpid() << ends;
798   ofstream of(buffer, ios::app);
799
800   of << "INCLUDED FUNCTIONS\n";
801   for (unsigned ni=0; ni<includedFunctions.size(); ni++) {
802     of << includedFunctions[ni]->prettyName() << "\t\t" << includedFunctions[ni]->addr() << "\t\t" << << endl;
803   }
804   
805 #endif
806 }
807
808 void pdmodule::define() {
809 #ifndef BPATCH_LIBRARY
810   resource *modResource = NULL;
811 #endif
812 #ifdef DEBUG_MODS
813   char buffer[100];
814   ostrstream osb(buffer, 100, ios::out);
815   osb << "MODS_" << exec->name() << "__" << getpid() << ends;
816   ofstream of(buffer, ios::app);
817 #endif
818
819   unsigned f_size = funcs.size();
820
821   for (unsigned f=0; f<f_size; f++) {
822     pd_Function *pdf = funcs[f];
823 #ifdef DEBUG_MODS
824     of << fileName << ":  " << pdf->prettyName() <<  "  "
825         << pdf->addr() << endl;
826 #endif
827     // ignore line numbers for now 
828
829 #ifndef BPATCH_LIBRARY
830     //if (!(pdf->isLibTag())) {
831     if (1) {
832       // see if we have created module yet.
833       if (!modResource) {
834         modResource = resource::newResource(moduleRoot, this,
835                                             nullString, // abstraction
836                                             fileName(), // name
837                                             0.0, // creation time
838                                             string(), // unique-ifier
839                                             MDL_T_MODULE,
840                                             false);
841       }
842       resource::newResource(modResource, pdf,
843                             nullString, // abstraction
844                             pdf->prettyName(), 0.0,
845                             nullString, // uniquifier
846                             MDL_T_PROCEDURE,
847                             false);
848     }
849 #endif
850   }
851
852 #ifndef BPATCH_LIBRARY
853   resource::send_now();
854 #endif
855 }
856
857 // get all functions in module which are not "excluded" (e.g.
858 //  with mdl "exclude" command.  
859 // Assed to provide support for mdl "exclude" on functions in
860 //  statically linked objects.
861 //  mcheyney 970727
862 vector<function_base *> *pdmodule::getIncludedFunctions() {
863     // laxy construction of some_funcs, as per sharedobject class....
864     // cerr << "pdmodule " << fileName() << " :: getIncludedFunctions called "
865     //      << endl;
866     if (some_funcs_inited == TRUE) {
867         //cerr << "  about to return : " << endl;
868         //print_func_vector_by_pretty_name(string("  "), (vector<function_base *>*)&some_funcs);
869         return (vector<function_base *>*)&some_funcs;
870     }
871 #ifdef BPATCH_LIBRARY /* BPatch Library doesn't know about excluded funcs */
872     some_funcs = funcs;
873 #else
874     some_funcs.resize(0);
875     
876     if (filter_excluded_functions(funcs, some_funcs, fileName()) == FALSE) {
877         //cerr << "  about to return NULL";
878         return NULL;
879     }
880 #endif
881     some_funcs_inited = TRUE;
882     
883     //cerr << "  about to return : " << endl;
884     //print_func_vector_by_pretty_name(string("  "),(vector<function_base *>*) &some_funcs);
885     return (vector<function_base *>*)&some_funcs;
886 }
887
888 #ifdef NOT_DEFINED
889 // get all functions in module which are not "excluded" (e.g.
890 //  with mdl "exclude" command.  
891 // Assed to provide support for mdl "exclude" on functions in
892 //  statically linked objects.
893 //  mcheyney 970727
894 const vector<pd_Function *> &image::getIncludedFunctions() {
895     //cerr << "image::getIncludedFunctions() called, about to return includedFunctions = " << endl;
896     //print_func_vector_by_pretty_name(string("  "),
897     //        (vector<function_base*>*)&includedFunctions);
898     return includedFunctions;
899 }
900 #endif
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/function_name" (but NOT
1031 //  via "exclude module_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 module/function is excluded....
1057             if (constraint_function_name == function_name) {
1058                 //cerr << " (function_is_excluded) found matching FUNCTION constraint " << func_constraints[i] << " returning TRUE" << endl;
1059                 return TRUE;
1060             }
1061         }
1062     }
1063
1064     //cerr << " (function_is_excluded) didnt find matching constraint, returing FALSE" << endl;
1065     return FALSE;
1066 }
1067
1068 //
1069 // mcheyney, Sep 28, 1997
1070 // Take a list of functions (in vector <all_funcs>.  Copy all
1071 //  of those functions which are not excluded (via "exclude" 
1072 //  {module==module_name}/{function==function_name) into
1073 //  <some_functions>.
1074 // Returns status of mdl_get_lib_constraints() call.
1075 //  If this status == FALSE< some_funcs is not modified....
1076 // We assume that all_funcs is generally longer than the list
1077 //  of constrained functions.  As such, internally proc. copies
1078 //  all funcs into some funcs, then runs over excluded funcs
1079 //  removing any matches, as opposed to doing to checking 
1080 //  while adding to some_funcs....
1081 bool filter_excluded_functions(vector<pd_Function*> all_funcs,
1082     vector<pd_Function*>& some_funcs, string module_name) {
1083
1084     u_int i, j;
1085     // strings holding exclude constraints....
1086     vector<string> func_constraints;
1087     string constraint_module_name, constraint_function_name, empty_string;
1088     vector<string> tstrings;
1089     bool excluded;
1090
1091     empty_string = string("");
1092
1093     //cerr << "filter_excluded_functions called : " << endl;
1094     //cerr << " module_name = " << module_name << endl;
1095     //cerr << " all_funcs (by pretty name ) : " << endl;
1096     //for(i=0;i<all_funcs.size();i++) {
1097     //    cerr << "  " << all_funcs[i]->prettyName() << endl;
1098     //}
1099     
1100
1101     // if you cannot get set of lib constraints, return FALSE w/o
1102     // modifying some_funcs....
1103     if(mdl_get_lib_constraints(func_constraints) == FALSE) {
1104         if (0) {
1105             //cerr << " could not mdl_get_lib_constraints, about to return FALSE"
1106             //     << endl;
1107         }
1108         return FALSE;
1109     }
1110
1111     // run through func_constraints, filtering all constraints
1112     //  not of form module/function, and all constraints of that
1113     //  form where constraint module name != module_name....
1114     for(i=0;i<func_constraints.size();i++) {
1115         constraint_module_name = getModuleName(func_constraints[i]);
1116         //cerr << "constraint = " << func_constraints[i] << endl;
1117         //cerr << " constraint_module_name = " << constraint_module_name
1118         //     << endl;
1119         
1120         if (module_name == constraint_module_name) {
1121             constraint_function_name = getFunctionName(func_constraints[i]);
1122             if (constraint_function_name != empty_string) { 
1123                 tstrings += getFunctionName(func_constraints[i]);
1124             }
1125         }
1126     }
1127     func_constraints = tstrings;
1128     
1129     //cerr << "func_constraints = " << endl;
1130     //for(i=0;i<func_constraints.size();i++) {
1131     //    cerr << "  " << func_constraints[i] << endl;
1132     //}
1133    
1134
1135     // run over functions in all_funcs.  If they dont match an excluded 
1136     //  function in module_name, then push them onto some_funcs....
1137     for(i=0;i<all_funcs.size();i++) {
1138         excluded = FALSE;
1139         for(j=0;j<func_constraints.size();j++) {
1140             if (all_funcs[i]->prettyName() == func_constraints[j]) {
1141                 excluded = TRUE;
1142                 break;
1143             }
1144         }
1145         if (excluded == FALSE) {
1146             some_funcs += all_funcs[i]; 
1147         }
1148     }
1149
1150     //cerr << " looks successful : about to return TRUE" << endl;
1151     //cerr << " some_funcs (by pretty name) " << endl;
1152     //for (i=0;i<some_funcs.size();i++) {
1153     //    cerr << "  " << some_funcs[i]->prettyName() << endl;
1154     //}
1155     
1156     return TRUE;
1157 }
1158 #endif /* BPATCH_LIBRARY */
1159
1160 // I commented this out since gcc says it ain't used --ari 10/97
1161 // I then uncommented it because non-Solaris platforms need it --ssuen 10/10/97
1162 static void binSearch (const Symbol &lookUp, vector<Symbol> &mods,
1163                        string &modName, Address &modAddr, const string &def) {
1164   int start=0, end=mods.size()-1, index;
1165   bool found=false;
1166
1167   if (!mods.size()) {
1168     modAddr = 0;
1169     modName = def;
1170     return;
1171   }
1172
1173   while ((start <= end) && !found) {
1174     index = (start+end)/2;
1175
1176     if ((index == (((int)mods.size())-1)) ||
1177         ((mods[index].addr() <= lookUp.addr()) && (mods[index+1].addr() > lookUp.addr()))) {
1178       modName = mods[index].name();
1179       modAddr = mods[index].addr();      
1180       found = true;
1181     } else if (lookUp.addr() < mods[index].addr()) {
1182       end = index - 1;
1183     } else {
1184       start = index + 1;
1185     }
1186   }
1187   if (!found) {
1188     modName = mods[0].name();
1189     modAddr = mods[0].addr();
1190   }
1191 }
1192
1193 // COMMENTS????
1194 // 
1195 bool image::addOneFunction(vector<Symbol> &mods,
1196                            pdmodule *lib,
1197                            pdmodule *,
1198                            const Symbol &lookUp, pd_Function  *&retFunc) {
1199   // TODO mdc
1200   // find the module
1201   // this is a "user" symbol
1202   string modName = lookUp.module();
1203   Address modAddr = 0;
1204   
1205   string progName = name_ + "_module";
1206
1207 #if defined (sparc_sun_solaris2_4) || defined (i386_unknown_solaris2_5) || defined (i386_unknown_linux2_0) 
1208   // In solaris there is no address for modules in the symbol table, 
1209   // so the binary search will not work. The module field in a symbol
1210   // already has the correct module name for a symbol, if it can be
1211   // obtained from the symbol table, otherwise the module is an empty
1212   // string.
1213   if (modName == "") {
1214     modName = progName;
1215   }
1216 #else
1217   binSearch(lookUp, mods, modName, modAddr, progName);
1218 #endif
1219
1220   return (defineFunction(lib, lookUp, modName, modAddr, retFunc));
1221 }
1222
1223 bool inLibrary(Address addr, Address boundary_start, Address boundary_end,
1224                       Address startAddr, bool startB,
1225                       Address endAddr, bool endB) {
1226   if ((addr >= boundary_start) && (addr <= boundary_end))
1227     return true;
1228   else if (startB) {
1229     if (addr <= startAddr)
1230       return true;
1231     else if (endB) {
1232       if (addr >= endAddr)
1233         return true;
1234       else 
1235         return false;
1236     } else 
1237       return false;
1238   } else if (endB) {
1239     if (addr >= endAddr)
1240       return true;
1241     else
1242       return false;
1243   } else
1244     return false;
1245 }
1246
1247 // as per getAllFunctions, but filters out those excluded with 
1248 // e.g. mdl "exclude" command....
1249 // to clarify a function should NOT be returned from here if its 
1250 //  module is excluded (with exclude "/Code/module") or if it
1251 //  is excluded (with exclude "/Code/module/function"). 
1252 const vector<pd_Function*> &image::getIncludedFunctions() {
1253     unsigned int i;    
1254     includedFunctions.resize(0);
1255     vector<function_base *> *temp;
1256     vector<pd_Function *> *temp2;
1257
1258     //cerr << "image::getIncludedFunctions called, name = " << name () << endl;
1259     //cerr << " includedMods = " << endl;
1260     //print_module_vector_by_short_name(string("  "), &includedMods);
1261     for (i=0;i<includedMods.size();i++) {
1262          temp = includedMods[i]->getIncludedFunctions();
1263          temp2 = (vector<pd_Function *> *) temp;
1264          includedFunctions += *temp2;
1265     }
1266
1267     //cerr << " (image::getIncludedFunctions) returning : " << endl;
1268     //print_func_vector_by_pretty_name(string("  "),
1269     //           (vector<function_base*>*)&includedFunctions);
1270
1271     // what about shared objects????
1272     return includedFunctions;
1273 }
1274
1275 //  COMMENTS??  HELLO?
1276 //  Here's a guess what this function tries to do:
1277 //  a. look through (data member of type Object) linkedFile,
1278 //   trying to file DYNINSTstart and DYNINSTend sections (
1279 //   beginning + ending of instrumentation code).
1280 //  b. ditto for main function (note variant names under which
1281 //   these functions are searched for)....
1282 //  c. iterate over all functions in linkedFile:
1283 //    if the function has already been defined, OR shadows the
1284 //     main function (has same address) - ignore it.
1285 //    else - 
1286 //     use (member function) inLibrary() to check
1287 //     whether function is in range of instrumented code (between
1288 //     DYNINSTstart and DYNINSTend)
1289 //     if in range - addInternalSymbol().
1290 //     else addOneFunction().
1291 //
1292 //  Questions : what do params mean????
1293 bool image::addAllFunctions(vector<Symbol> &mods,
1294                             pdmodule *lib, pdmodule *dyn, 
1295                             const bool startB, const Address startAddr,
1296                             const bool endB, const Address endAddr) {
1297
1298   Address boundary_start, boundary_end;
1299   Symbol lookUp;
1300   string symString;
1301
1302 #ifdef BPATCH_LIBRARY
1303   boundary_start = boundary_end = NULL;
1304 #else
1305   if (!linkedFile.get_symbol(symString="DYNINSTfirst", lookUp) &&
1306       !linkedFile.get_symbol(symString="_DYNINSTfirst", lookUp)) {
1307     //statusLine("Internal symbol DYNINSTfirst not found");
1308     //showErrorCallback(31, "Internal symbol DYNINSTfirst not found");
1309     //return false;
1310     boundary_start = NULL;
1311   } else
1312     boundary_start = lookUp.addr();
1313
1314   if (!linkedFile.get_symbol(symString="DYNINSTend", lookUp) &&
1315       !linkedFile.get_symbol(symString="_DYNINSTend", lookUp)) {
1316     //statusLine("Internal symbol DYNINSTend not found");
1317     //showErrorCallback(32, "Internal symbol DYNINSTend not found");
1318     //return false;
1319     boundary_end = NULL;
1320   } else
1321     boundary_end = lookUp.addr();
1322 #endif
1323
1324   Symbol mainFuncSymbol;  //Keeps track of info on "main" function
1325
1326   //Checking "main" function names in same order as in the inst-*.C files
1327   if (linkedFile.get_symbol(symString="main",     lookUp) ||
1328       linkedFile.get_symbol(symString="_main",    lookUp) ||
1329       linkedFile.get_symbol(symString="WinMain",  lookUp) ||
1330       linkedFile.get_symbol(symString="_WinMain", lookUp)) 
1331     mainFuncSymbol = lookUp;
1332
1333   // find the real functions -- those with the correct type in the symbol table
1334   for(SymbolIter symIter = linkedFile; symIter;symIter++) {
1335     const Symbol &lookUp = symIter.currval();
1336
1337     if (funcsByAddr.defines(lookUp.addr()) ||
1338         ((lookUp.addr() == mainFuncSymbol.addr()) &&
1339          (lookUp.name() != mainFuncSymbol.name()))) {
1340       // This function has been defined 
1341       // *or*
1342       // This function has the same address as the "main" function but does 
1343       //   not have the same name as the "main" function.  Therefore, skip
1344       //   it and let the "main" function be eventually associated with this
1345       //   function address.  If we don't do this, paradynd will not have a
1346       //   "main" function to start work with.
1347       ;
1348     } else if (lookUp.type() == Symbol::PDST_FUNCTION) {
1349       if (!isValidAddress(lookUp.addr())) {
1350         string msg;
1351         char tempBuffer[40];
1352         sprintf(tempBuffer,"%x",lookUp.addr());
1353         msg = string("Function") + lookUp.name() + string("has bad address ") +
1354               string(tempBuffer);
1355         statusLine(msg.string_of());
1356         showErrorCallback(29, msg);
1357         return false;
1358       }
1359       insert_function_internal_static(mods, lookUp, boundary_start,
1360               boundary_end, startAddr, startB, endAddr, endB, dyn, lib);
1361     }
1362   }
1363
1364   // now find the pseudo functions -- this gets ugly
1365   // kludge has been set if the symbol could be a function
1366   for(SymbolIter symIter2 = linkedFile;symIter2;symIter2++) {
1367     lookUp = symIter2.currval();
1368     if (funcsByAddr.defines(lookUp.addr())) {
1369         // This function has been defined
1370         ;
1371     } else if ((lookUp.type() == Symbol::PDST_OBJECT) && lookUp.kludge()) {
1372         //logLine(P_strdup(symString.string_of()));
1373         // see comment under image::insert_function_internal_static,
1374         // below....
1375         insert_function_internal_static(mods, lookUp, boundary_start,
1376               boundary_end, startAddr, startB, endAddr, endB, dyn, lib);
1377     }
1378   }
1379   return true;
1380 }
1381
1382 bool image::addAllSharedObjFunctions(vector<Symbol> &mods,
1383                             pdmodule *lib, pdmodule *dyn) {
1384
1385   Symbol lookUp;
1386   string symString;
1387
1388   bool is_libdyninstRT = false; // true if this image is libdyninstRT
1389 #if defined(i386_unknown_nt4_0)
1390   if (linkedFile.get_symbol(symString="_DYNINSTfirst", lookUp)
1391       || linkedFile.get_symbol(symString="_DYNINSTfirst", lookUp))
1392     is_libdyninstRT = true;
1393 #endif
1394
1395   // find the real functions -- those with the correct type in the symbol table
1396   for(SymbolIter symIter3 = linkedFile;symIter3;symIter3++) { 
1397     const Symbol &lookUp = symIter3.currval();
1398     if (funcsByAddr.defines(lookUp.addr())) {
1399       // This function has been defined
1400       ;
1401     } else if (lookUp.type() == Symbol::PDST_FUNCTION) {
1402       if (!isValidAddress(lookUp.addr())) {
1403         string msg;
1404         char tempBuffer[40];
1405         sprintf(tempBuffer,"%x",lookUp.addr());
1406         msg = string("Function") + lookUp.name() + string("has bad address ") +
1407               string(tempBuffer);
1408         statusLine(msg.string_of());
1409         showErrorCallback(29, msg);
1410         return false;
1411       }
1412       // see comment under image::insert_functions_internal_dynamic,
1413       //  below....
1414       insert_function_internal_dynamic(mods, lookUp, dyn, lib, is_libdyninstRT);
1415     }
1416   }
1417
1418   // now find the pseudo functions -- this gets ugly
1419   // kludge has been set if the symbol could be a function
1420   for(SymbolIter symIter4 = linkedFile;symIter4;symIter4++) {
1421     const Symbol &lookUp = symIter4.currval();
1422     if (funcsByAddr.defines(lookUp.addr())) {
1423       // This function has been defined
1424       ;
1425     } else if ((lookUp.type() == Symbol::PDST_OBJECT) && lookUp.kludge()) {
1426       pd_Function *pdf;
1427       addInternalSymbol(lookUp.name(), lookUp.addr());
1428       defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf);
1429     }
1430   }
1431   return true;
1432
1433
1434
1435 bool image::addAllVariables()
1436 {
1437 /* Eventually we'll have to do this on all platforms (because we'll retrieve
1438  * the type information here).
1439  */
1440 #ifdef i386_unknown_nt4_0
1441   string mangledName; 
1442   Symbol symInfo;
1443
1444   for(SymbolIter symIter = linkedFile; symIter; symIter++) {
1445      const string &mangledName = symIter.currkey();
1446      const Symbol &symInfo = symIter.currval();
1447
1448     if (symInfo.type() == Symbol::PDST_OBJECT) {
1449       char *name = cplus_demangle((char *)mangledName.string_of(), 0);
1450       const char *unmangledName;
1451       if (name) unmangledName = name;
1452       else unmangledName = mangledName.string_of();
1453       if (varsByPretty.defines(unmangledName)) {
1454           *(varsByPretty[unmangledName]) += string(mangledName);
1455       } else {
1456           vector<string> *varEntry = new vector<string>;
1457           *varEntry += string(mangledName);
1458           varsByPretty[unmangledName] = varEntry;
1459       }
1460       if (name) free(name);
1461     }
1462   }
1463 #endif
1464   return true;
1465 }
1466
1467 int symCompare(const void *s1, const void *s2) {
1468   const Symbol *sym1 = (const Symbol*)s1, *sym2 = (const Symbol*)s2;
1469   // TODO mdc
1470   return (sym1->addr() - sym2->addr());
1471 }
1472
1473
1474 unsigned int_addrHash(const unsigned &addr) {
1475   return addr;
1476 }
1477
1478 // Please note that this is now machine independent-almost.  Let us keep it that way
1479 // COMMENTS????
1480 //  Guesses as to what this cod does....
1481 //  image constructor:
1482 //   construct an image corresponding to the executable file on path
1483 //   fileName.  Fill in err based on success or failure....
1484 image::image(const string &fileName, bool &err)
1485 :   modsByFileName(string::hash),
1486     modsByFullName(string::hash),
1487     includedFunctions(0),
1488     excludedFunctions(string::hash),
1489     instrumentableFunctions(0),
1490     notInstruFunctions(string::hash),
1491     funcsByAddr(addrHash4),
1492     funcsByPretty(string::hash),
1493     file_(fileName),
1494     linkedFile(fileName, pd_log_perror),
1495     iSymsMap(string::hash),
1496     varsByPretty(string::hash),
1497     knownJumpTargets(int_addrHash, 8192)
1498 {
1499     sharedobj_cerr << "image::image for non-sharedobj; file name="
1500                    << file_ << endl;
1501
1502     // shared_object and static object (a.out) constructors merged into
1503     //  common initialize routine.... 
1504     initialize(fileName, err, 0);
1505 }
1506
1507 // 
1508 // load a shared object
1509 //
1510 image::image(const string &fileName, u_int baseAddr, bool &err)
1511 :   
1512     modsByFileName(string::hash),
1513     modsByFullName(string::hash),
1514     includedFunctions(0),
1515     excludedFunctions(string::hash),
1516     instrumentableFunctions(0),
1517     notInstruFunctions(string::hash),
1518     funcsByAddr(addrHash4),
1519     funcsByPretty(string::hash),
1520     file_(fileName),
1521     linkedFile(fileName, baseAddr,pd_log_perror),
1522     iSymsMap(string::hash),
1523     varsByPretty(string::hash),
1524     knownJumpTargets(int_addrHash, 8192)
1525 {
1526     sharedobj_cerr << "welcome to image::image for shared obj; file name="
1527                    << file_ << endl;
1528
1529     // shared_object and static object (a.out) constructors merged into
1530     //  common initialize routine.... 
1531     initialize(fileName, err, 1, baseAddr);
1532 }
1533
1534 static bool findStartSymbol(Object &lf, Address &adr) {
1535   Symbol lookUp;
1536
1537   if (lf.get_symbol("DYNINSTstartUserCode", lookUp) ||
1538       lf.get_symbol("_DYNINSTstartUserCode", lookUp)) {
1539     adr = lookUp.addr();
1540     return true;
1541   } else
1542     return false;
1543 }
1544
1545 static bool findEndSymbol(Object &lf, Address &adr) {
1546   Symbol lookUp;
1547
1548   if (lf.get_symbol("DYNINSTendUserCode", lookUp) ||
1549       lf.get_symbol("_DYNINSTendUserCode", lookUp)) {
1550     adr = lookUp.addr();
1551     return true;
1552   } else
1553     return false;
1554 }
1555
1556 /*
1557     image::initialize - called by image a.out and shared_object 
1558     constructor to do common initialization....
1559
1560     paramaters - 
1561
1562       shared_object - pass 0 to denote initializing from statically
1563         linked executable (a.out file), pass 1 to denote initializing
1564         from shared library.
1565       base_addr - curr. used IFF shared_library == 1.
1566  */
1567 void image::initialize(const string &fileName, bool &err,
1568         bool shared_object, u_int) {
1569
1570     // initialize (data members) codeOffset_, dataOffset_,
1571     //  codeLen_, dataLen_.
1572     codeOffset_ = linkedFile.code_off();
1573     dataOffset_ = linkedFile.data_off();
1574     codeLen_ = linkedFile.code_len();
1575     dataLen_ = linkedFile.data_len();
1576
1577 #if defined(hppa1_1_hp_hpux)
1578   unwind   = linkedFile.unwind;
1579 #endif
1580
1581     // if unable to parse object file (somehow??), try to
1582     //  notify luser/calling process + return....    
1583     if (!codeLen_ || !linkedFile.code_ptr()) {
1584         string msg = string("Unable to open executable file: ") + fileName;
1585         statusLine(msg.string_of());
1586         msg += "\n";
1587         logLine(msg.string_of());
1588         err = true;
1589         showErrorCallback(27, msg); 
1590         return;
1591     }
1592
1593 #if !defined(i386_unknown_nt4_0) && !defined(USES_LIBDYNINSTRT_SO)
1594     // on architectures where statically linked programs to be run 
1595     //  w/ paradyn need to link with the DYNINST library, try to find
1596     //  the paradyn lib version # (DYNINSTversion or _DYNINSTversion
1597     //  symbol).
1598     if (!shared_object) {
1599         Symbol version;
1600         if (!linkedFile.get_symbol("DYNINSTversion", version) &&
1601                 !linkedFile.get_symbol("_DYNINSTversion", version)) {
1602             statusLine("Could not find version number in instrumentation\n");
1603             showErrorCallback(33, "Could not find version number in instrumentation");
1604             err = true;
1605             return;
1606         }
1607
1608         Word version_number = get_instruction(version.addr());
1609         if (version_number != 1) {
1610             string msg;
1611             msg = string("Incorrect version number, expected ") + string(1) + 
1612                  string("found ") + string(version_number);
1613             statusLine(msg.string_of());
1614             showErrorCallback(30, msg);
1615             err = true;
1616             return;
1617         }
1618     }
1619 #endif
1620
1621     string msg;
1622     // give luser some feedback....
1623     if (shared_object) {
1624         msg = string("Parsing shared object file : ") + fileName;
1625     } else {
1626         msg = string("Parsing static object file : ") + fileName;
1627     }
1628     statusLine(msg.string_of());
1629
1630     const char *nm = fileName.string_of();
1631     const char *pos = P_strrchr(nm, '/');
1632
1633     err = false;
1634     if (pos)
1635         name_ = pos + 1;
1636     else
1637         name_ = fileName;
1638
1639     // use the *DUMMY_MODULE* until a module is defined
1640     pdmodule *dynModule = newModule(DYN_MODULE, 0);
1641     pdmodule *libModule = newModule(LIBRARY_MODULE, 0);
1642     // TODO -- define inst points in define function ?
1643
1644     // The functions cannot be verified until all of them have been seen
1645     // because calls out of each function must be tagged as calls to user
1646     // functions or call to "library" functions
1647
1648     Symbol lookUp;
1649     string symString;
1650
1651     //
1652     // sort the modules by address into a vector to allow a binary search to 
1653     // determine the module that a symbol will map to -- this 
1654     // may be bsd specific....
1655     //
1656     vector <Symbol> tmods;
1657
1658     for (SymbolIter symIter = linkedFile; symIter; symIter++) {
1659         const Symbol &lookUp = symIter.currval();
1660         if (lookUp.type() == Symbol::PDST_MODULE) {
1661             const string &lookUpName = lookUp.name();
1662             const char *str = lookUpName.string_of();
1663             assert(str);
1664             int ln = lookUpName.length();
1665
1666             // directory definition -- ignored for now
1667             if (str[ln-1] != '/') {
1668                 tmods += lookUp;
1669             }
1670         }
1671     }
1672
1673     // sort the modules by address
1674     statusLine("sorting modules");
1675     tmods.sort(symCompare);
1676     //  assert(mods.sorted(symCompare));
1677
1678     // remove duplicate entries -- some .o files may have the same 
1679     // address as .C files.  kludge is true for module symbols that 
1680     // I am guessing are modules
1681     vector<Symbol> uniq;
1682     unsigned loop=0;
1683
1684     // must use loop+1 not mods.size()-1 since it is an unsigned compare
1685     //  which could go negative - jkh 5/29/95
1686     for (loop=0; loop < tmods.size(); loop++) {
1687         if ((loop+1 < tmods.size()) && 
1688                 (tmods[loop].addr() == tmods[loop+1].addr())) {
1689             if (!tmods[loop].kludge())
1690                 tmods[loop+1] = tmods[loop];
1691         } 
1692         else
1693           uniq += tmods[loop];
1694     }
1695
1696     // define all of the functions
1697     statusLine("winnowing functions");
1698
1699     // register functions differently depending on whether parsing 
1700     //  shared object or static executable.  
1701     // THIS MAY CHANGE WHEN REMOVE DYNINSTstart && DYNINSTend hacks....
1702     if (!shared_object) {
1703         // find the "user" code boundaries
1704         statusLine("finding user code boundaries");
1705         Address startUserAddr=0, endUserAddr=0;
1706         bool startBound = findStartSymbol(linkedFile, startUserAddr);
1707         bool endBound = findEndSymbol(linkedFile, endUserAddr);
1708
1709         if (!addAllFunctions(uniq, libModule, dynModule, startBound,
1710                 startUserAddr, endBound, endUserAddr)) {
1711             err = true;
1712             return;
1713         }
1714     } else {
1715         // define all of the functions
1716         if (!addAllSharedObjFunctions(uniq, libModule, dynModule)) {
1717             err = true;
1718             return;
1719         }
1720     }
1721
1722     // ALERT ALERT - Calling on both shared_object && !shared_object path.
1723     //  In origional code, only called in !shared_object case.  Was this 
1724     //  a bug????
1725     // XXX should have a statusLine("retrieving variable information") here,
1726     //     but it's left out for now since addAllVariables only does something
1727     //     when BPATCH_LIBRARY is defined
1728     addAllVariables();
1729
1730     statusLine("checking call points");
1731     checkAllCallPoints();
1732
1733     // TODO -- remove duplicates -- see earlier note
1734     dictionary_hash<unsigned, unsigned> addr_dict(uiHash);
1735     vector<pd_Function*> temp_vec;
1736
1737     // question??  Necessary to do same crap to includedFunctions &&
1738     //  excludedFunctions??
1739     unsigned f_size = instrumentableFunctions.size(), index;
1740     for (index=0; index<f_size; index++) {
1741         const unsigned the_address = 
1742             (unsigned)instrumentableFunctions[index]->getAddress(0);
1743         if (!addr_dict.defines(the_address)) {
1744             addr_dict[the_address] = 1;
1745             temp_vec += instrumentableFunctions[index];
1746         }
1747     }
1748     instrumentableFunctions = temp_vec;
1749 }
1750
1751
1752 void pdmodule::checkAllCallPoints() {
1753   unsigned fsize = funcs.size();
1754   for (unsigned f=0; f<fsize; f++)
1755       funcs[f]->checkCallPoints();
1756 }
1757
1758
1759 void image::checkAllCallPoints() {
1760   dictionary_hash_iter<string, pdmodule*> di(modsByFullName);
1761   string s; pdmodule *mod;
1762   while (di.next(s, mod))
1763     mod->checkAllCallPoints();
1764 }
1765
1766 // passing in tags allows a function to be tagged as TAG_LIB_FUNC even
1767 // if its entry is not in the tag dictionary of known functions
1768 bool image::defineFunction(pdmodule *use, const Symbol &sym, const unsigned tags,
1769                            pd_Function *&retFunc) {
1770   // We used to skip a leading underscore, but not anymore.
1771   // (I forgot why we ever did in the first place)
1772
1773   unsigned dictTags = findTags(sym.name());
1774   return (newFunc(use, sym.name(), sym.addr(), sym.size(), tags | dictTags, retFunc));
1775 }
1776
1777 pdmodule *image::getOrCreateModule(const string &modName, 
1778                                       const Address modAddr) {
1779   const char *str = modName.string_of();
1780   int len = modName.length();
1781   assert(len>0);
1782
1783   // TODO ignore directory definitions for now
1784   if (str[len-1] == '/') {
1785     return NULL;
1786   } else {
1787     // TODO - navigate ".." and "."
1788     const char *lastSlash = P_strrchr(str, '/');
1789     if (lastSlash)
1790       return (newModule(++lastSlash, modAddr));
1791     else
1792       return (newModule(modName, modAddr));
1793   }
1794 }
1795
1796 // COMMENTS????
1797 // looks like wrapper function for (member function) newFunc.
1798 //  appears to do some fiddling with tags paramater to that
1799 //  function.
1800 // Kludge TODO - internal functions are tagged with TAG_LIB_FUNC
1801 // but they won't have tags in the tag dict, so this happens...
1802 bool image::defineFunction(pdmodule *libModule, const Symbol &sym,
1803                            const string &modName, const Address modAddr,
1804                            pd_Function *&retFunc) {
1805
1806   // We used to skip a leading underscore, but not any more.
1807
1808   unsigned tags = findTags(sym.name());
1809
1810   if (TAG_LIB_FUNC & tags)
1811     return (newFunc(libModule, sym.name(), sym.addr(), sym.size(),
1812                     tags | TAG_LIB_FUNC, retFunc));
1813   else {
1814     pdmodule *use = getOrCreateModule(modName, modAddr);
1815     assert(use);
1816     return (newFunc(use, sym.name(), sym.addr(), sym.size(), tags, retFunc));
1817   }
1818 }
1819
1820 // Verify that this is code
1821 // Find the call points
1822 // Find the return address
1823 // TODO -- use an instruction object to remove
1824 // Sets err to false on error, true on success
1825 //
1826 // Note - this must define funcEntry and funcReturn
1827 // 
1828 pd_Function::pd_Function(const string &symbol, const string &pretty, 
1829                        pdmodule *f, Address adr, const unsigned size, 
1830                        const unsigned tg, const image *owner, bool &err) : 
1831   function_base(symbol, pretty, adr, size,tg),
1832   file_(f),
1833   funcEntry_(0),
1834   relocatable_(false)
1835 {
1836   err = findInstPoints(owner) == false;
1837 }
1838
1839 // image::addAllFunctions dupliactes this section of code.
1840 // As part of an effort to clean up the code a bit, I merged the
1841 // duplicates into this 1 function.  
1842 void image::insert_function_internal_static(vector<Symbol> &mods,
1843         const Symbol &lookUp,
1844         const Address boundary_start,  const Address boundary_end,
1845         const Address startAddr, bool startB, const Address endAddr,
1846         bool endB, pdmodule *dyn, pdmodule *lib) {
1847     pd_Function *pdf;
1848     //  COMMENTS??
1849     //  If CONDITION??
1850     if (inLibrary(lookUp.addr(), boundary_start, boundary_end,
1851                     startAddr, startB, endAddr, endB)) {
1852         // look at symbol name.  If it looks like "_DYNINST*" or 
1853         // "_TRACELIN*", add it to iSymsMap data member....
1854         addInternalSymbol(lookUp.name(), lookUp.addr());
1855         defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf);
1856     } else {
1857         addOneFunction(mods, lib, dyn, lookUp, pdf);
1858     } 
1859 }
1860
1861 // version of insert_function_internal_static (above) for 
1862 // shared objects....
1863 void image::insert_function_internal_dynamic(vector<Symbol> &mods,
1864         const Symbol &lookUp,
1865         pdmodule *dyn, pdmodule *lib, bool is_libdyninstRT) {
1866     pd_Function *pdf;
1867     if (is_libdyninstRT) {
1868         addInternalSymbol(lookUp.name(), lookUp.addr());
1869         defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf);
1870     } else {
1871         addOneFunction(mods, lib, dyn, lookUp, pdf);
1872     }
1873 }