optimized newResource. optimized some memory ops when parsing.
[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/main.h"
61 #include "paradynd/src/init.h"
62 #else
63 extern vector<sym_data> syms_to_find;
64 #endif
65
66 // All debug_ostream vrbles are defined in process.C (for no particular reason)
67 extern debug_ostream sharedobj_cerr;
68
69 vector<image*> image::allImages;
70
71 #if defined(i386_unknown_nt4_0)
72 extern char *cplus_demangle(char *, int);
73 #else
74 extern "C" char *cplus_demangle(char *, int);
75 #endif
76
77
78 /* imported from platform specific library list.  This is lists all
79    library functions we are interested in instrumenting. */
80
81 pdmodule *image::newModule(const string &name, const Address addr)
82 {
83     pdmodule *ret;
84     // modules can be defined several times in C++ due to templates and
85     //   in-line member functions.
86     if ((ret = findModule(name)))
87       return(ret);
88
89     string fullNm, fileNm;
90     char *out = P_strdup(name.string_of());
91     char *sl = P_strrchr(out, '/');
92     if (sl) {
93       *sl = (char)0;
94       fullNm = out;
95       fileNm = sl+1;
96     } else {
97       fullNm = string("/default/") + out;
98       fileNm = out;
99     }
100     free(out);
101
102     ret = new pdmodule(langUnknown, addr, fullNm, fileNm, this);
103     modsByFileName[ret->fileName()] = ret;
104     modsByFullName[ret->fullName()] = ret;
105     mods += ret;
106     return(ret);
107 }
108
109
110 // TODO -- is this g++ specific
111 bool buildDemangledName(const string &mangled, string &use)
112 {
113  /* The C++ demangling function demangles MPI__Allgather (and other MPI__
114   * functions with start with A) into the MPI constructor.  In order to
115   * prevent this a hack needed to be made, and this seemed the cleanest
116   * approach.
117   */
118   if(!mangled.prefixed_by("MPI__")) {
119     char *tempName = P_strdup(mangled.string_of());
120     char *demangled = cplus_demangle(tempName, 0);
121     
122     if (demangled) {
123       use = demangled;
124       free(tempName);
125       free(demangled);
126       return true;
127     } else {
128       free(tempName);
129       return false;
130     }
131   }
132   return(false);
133 }
134
135 // err is true if the function can't be defined
136 bool image::newFunc(pdmodule *mod, const string &name, const Address addr, 
137                     const unsigned size, const unsigned tag, 
138                     pd_Function *&retFunc) {
139   pd_Function *func;
140   retFunc = NULL;
141   // KLUDGE
142   if ((func = findFunction(addr))){
143     string temp = name;
144     temp += string(" findFunction failed\n");
145     logLine(P_strdup(temp.string_of()));
146     return false;
147   }
148
149   if (!mod) {
150     logLine("Error function without module\n");
151     showErrorCallback(34, "Error function without module");
152     return false;
153   }
154
155   string mangled_name = name;
156   const char *p = P_strchr(name.string_of(), ':');
157   if (p) {
158      unsigned nchars = p - name.string_of();
159      mangled_name = string(name.string_of(), nchars);
160   }
161      
162   string demangled;
163   if (!buildDemangledName(mangled_name, demangled)) 
164     demangled = mangled_name;
165
166   bool err;
167
168   func = new pd_Function(name, demangled, mod, addr, size, tag, this, err);
169   //cout << name << " pretty: " << demangled << " addr :" << addr <<endl;
170   retFunc = func;
171   if (err) {
172     //delete func;
173     retFunc = NULL;
174     notInstruFunction += func;
175     return false;
176   }
177   
178   funcsByAddr[addr] = func;
179   mod->funcs += func;
180
181   vector<pd_Function*> *funcsByPrettyEntry;
182   if (!funcsByPretty.find(func->prettyName(), funcsByPrettyEntry)) {
183     funcsByPrettyEntry = new vector<pd_Function*>;
184     funcsByPretty[func->prettyName()] = funcsByPrettyEntry;
185   }
186
187   // several functions may have the same demangled name, and each one
188   // will appear in a different module
189 //  vector<pdFunction*> *ap = funcsByPretty[func->prettyName()];
190   assert(funcsByPrettyEntry);
191   (*funcsByPrettyEntry) += func;
192   return true;
193 }
194
195 #ifdef DEBUG_TIME
196 static timer loadTimer;
197 static FILE *timeOut=0;
198 #endif /* DEBUG_TIME */
199
200 /*
201  * load an executable:
202  *   1.) parse symbol table and identify rotuines.
203  *   2.) scan executable to identify inst points.
204  *
205  *  offset is normally zero except on CM-5 where we have two images in one
206  *    file.  The offset passed to parseImage is the logical offset (0/1), not
207  *    the physical point in the file.  This makes it faster to "parse" multiple
208  *    copies of the same image since we don't have to stat and read to find the
209  *    physical offset. 
210  */
211 image *image::parseImage(const string file)
212 {
213   /*
214    * Check to see if we have parsed this image at this offeset before.
215    */
216   // TODO -- better method to detect same image/offset --> offset only for CM5
217
218   unsigned numImages = allImages.size();
219
220   for (unsigned u=0; u<numImages; u++)
221     if (file == allImages[u]->file())
222       return allImages[u];
223
224   /*
225    * load the symbol table. (This is the a.out format specific routine).
226    */
227
228   statusLine("Process executable file");
229   bool err;
230
231   // TODO -- kill process here
232   image *ret = new image(file, err);
233   if (err || !ret) {
234     if (ret)
235       delete ret;
236     return NULL;
237   }
238
239   // Add to master image list.
240   image::allImages += ret;
241
242   // define all modules.
243 #ifndef BPATCH_LIBRARY
244   tp->resourceBatchMode(true);
245 #endif
246
247   statusLine("defining modules");
248   ret->defineModules();
249
250 //  statusLine("ready"); // this shouldn't be here, right? (cuz we're not done, right?)
251
252 #ifndef BPATCH_LIBRARY
253   tp->resourceBatchMode(false);
254 #endif
255
256   return(ret);
257 }
258
259 /*
260  * load a shared object:
261  *   1.) parse symbol table and identify rotuines.
262  *   2.) scan executable to identify inst points.
263  *
264  */
265 image *image::parseImage(const string file,u_int baseAddr)
266 {
267   /*
268    * Check to see if we have parsed this image at this offeset before.
269    */
270   // TODO -- better method to detect same image/offset --> offset only for CM5
271
272   unsigned theSize = allImages.size();
273
274   for (unsigned u=0; u<theSize; u++)
275     if (file == allImages[u]->file())
276       return allImages[u];
277
278   /*
279    * load the symbol table. (This is the a.out format specific routine).
280    */
281
282   if(!baseAddr) statusLine("Processing an executable file");
283   else  statusLine("Processing a shared object file");
284   bool err;
285
286   // TODO -- kill process here
287   image *ret = new image(file, baseAddr,err);
288   if (err || !ret) {
289     if (ret)
290       delete ret;
291     logLine("error after new image in parseImage\n");
292     return NULL;
293   }
294
295   // Add to master image list.
296   image::allImages += ret;
297
298   // define all modules.
299   ret->defineModules();
300   return(ret);
301 }
302
303 bool image::addInternalSymbol(const string &str, const Address symValue) {
304   // Internal symbols are prefixed by { DYNINST, TRACELIB }
305   // don't ignore the underscore
306   static string dyn = "_DYNINST"; 
307   static string tlib = "_TRACELIB";
308
309
310   // normalize all symbols -- remove the leading "_"
311   if (str.prefixed_by(dyn)) {
312     const char *s = str.string_of(); s++;
313     if (!iSymsMap.defines(s)){
314       iSymsMap[s] = new internalSym(symValue, s);
315     }
316     return true;
317   } else if (str.prefixed_by(tlib)) {
318     const char *s = str.string_of(); s++;
319     if (!iSymsMap.defines(s))
320       iSymsMap[s] = new internalSym(symValue, s);
321     return true;
322   } else {
323     if (!iSymsMap.defines(str))
324       iSymsMap[str] = new internalSym(symValue, str);
325     return true;
326   }
327   return false;
328 }
329
330 /*
331  * will search for symbol NAME or _NAME
332  * returns false on failure 
333  */
334 bool image::findInternalSymbol(const string &name, const bool warn, internalSym &ret_sym){
335    Symbol lookUp;
336
337    if(linkedFile.get_symbol(name,lookUp)){
338       ret_sym = internalSym(lookUp.addr(),name); 
339       return true;
340    }
341    else {
342        string new_sym;
343        new_sym = string("_") + name;
344        if(linkedFile.get_symbol(new_sym,lookUp)){
345           ret_sym = internalSym(lookUp.addr(),name); 
346           return true;
347        }
348    } 
349    if(warn){
350       string msg;
351       msg = string("Unable to find symbol: ") + name;
352       statusLine(msg.string_of());
353       showErrorCallback(28, msg);
354    }
355    return false;
356 }
357
358 Address image::findInternalAddress(const string &name, const bool warn, bool &err)
359 {
360
361   err = false;
362
363   internalSym *theSym; // filled in by find()
364   if (!iSymsMap.find(name, theSym)) {
365     // not found!
366     if (warn) {
367       string msg = string("Unable to find symbol: ") + name;
368       statusLine(msg.string_of());
369       showErrorCallback(28, msg);
370     }
371     err = true;
372     return 0;
373   } 
374   else
375     return (theSym->getAddr());
376 }
377
378 pdmodule *image::findModule(const string &name)
379 {
380   if (modsByFileName.defines(name))
381     return (modsByFileName[name]);
382   else if (modsByFullName.defines(name))
383     return (modsByFullName[name]);
384   else
385     return NULL;
386 }
387
388 // TODO -- this is only being used in cases where only one function
389 // should exist -- should I assert that the vector size <= 1 ?
390 pd_Function *image::findOneFunction(const string &name)
391 {
392   string demangName;
393
394   if (funcsByPretty.defines(name)) {
395     vector<pd_Function*> *a = funcsByPretty[name];
396     assert(a);
397     if (!a->size())
398       return NULL;
399     else
400       return ((*a)[0]);
401   } else if (buildDemangledName(name, demangName)) {
402     if (funcsByPretty.defines(demangName)) {
403       vector<pd_Function*> *a = funcsByPretty[demangName];
404       assert(a);
405       if (!a->size())
406         return NULL;
407       else
408         return ((*a)[0]);
409     } else
410       return NULL;
411   } else
412     return NULL;
413 }
414
415 // This function supposely is only used to find function that
416 // is not instrumentable which may not be totally defined.
417 // Use with caution.  
418 pd_Function *image::findOneFunctionFromAll(const string &name) {
419
420     pd_Function *ret;
421     if ((ret = findOneFunction(name))) 
422         return ret;
423     else {
424         for (unsigned i = 0; i < notInstruFunction.size(); i++) {
425             ret = notInstruFunction[i];
426             if (ret->prettyName() == name)
427                 return ret;
428         }
429     }
430     return NULL;
431 }
432
433 bool image::findFunction(const string &name, vector<pd_Function*> &retList) {
434
435   if (funcsByPretty.defines(name)) {
436     retList = *funcsByPretty[name];
437     return true;
438   } else
439     return false;
440 }
441
442 pd_Function *image::findFunction(const Address &addr) 
443 {
444   pd_Function *result; // filled in by find()
445   if (funcsByAddr.find(addr, result))
446      return result;
447   else
448      return NULL;
449 }
450   
451 pd_Function *image::findFunctionIn(const Address &addr,const process *p) const 
452 {
453   pd_Function *pdf;
454
455   dictionary_hash_iter<Address, pd_Function*> mi(funcsByAddr);
456   Address adr;
457   while (mi.next(adr, pdf)) {
458       if ((addr>=pdf->getAddress(p))&&(addr<=(pdf->getAddress(p)+pdf->size()))) 
459           return pdf;
460   }
461   
462   // If not found, we are going to search them in the 
463   // uninstrumentable function
464   for (unsigned i = 0; i < notInstruFunction.size(); i++) {
465       pdf = notInstruFunction[i];
466       if ((addr>=pdf->getAddress(p))&&(addr<=(pdf->getAddress(p)+pdf->size()))) 
467           return pdf;
468   }
469
470   return NULL; 
471 }
472
473
474 #ifndef BPATCH_LIBRARY
475 void image::changeLibFlag(resource *res, const bool setSuppress)
476 {
477   image *ret;
478   pdmodule *mod;
479
480   unsigned numImages = image::allImages.size();
481   for (unsigned u=0; u<numImages; u++) {
482     ret = image::allImages[u];
483     mod = ret->findModule(res->part_name());
484     if (mod) {
485       // suppress all procedures.
486       mod->changeLibFlag(setSuppress);
487     } else {
488       // more than one function may have this name --> templates, statics
489       vector<pd_Function*> pdfA;
490       if (ret->findFunction(res->part_name(), pdfA)) {
491         for (unsigned i=0; i<pdfA.size(); ++i) {
492           if (setSuppress) 
493             pdfA[i]->tagAsLib();
494           else
495             pdfA[i]->untagAsLib();
496         }
497       }
498     }
499   }
500 }
501 #endif
502
503
504 /* 
505  * return 0 if symbol <symname> exists in image, non-zero if it does not
506  */
507 bool image::symbolExists(const string &symname)
508 {
509   pd_Function *dummy = findOneFunction(symname);
510   return (dummy != NULL);
511 }
512
513 void image::postProcess(const string pifname)
514 {
515   FILE *Fil;
516   string fname, errorstr;
517   char key[5000];
518   char tmp1[5000], abstraction[500];
519 #ifndef BPATCH_LIBRARY
520   resource *parent;
521 #endif
522
523   return;
524
525   /* What file to open? */
526   if (!(pifname == (char*)NULL)) {
527     fname = pifname;
528   } else {
529     fname = file_ + ".pif";
530   }
531
532   /* Open the file */
533   Fil = P_fopen(fname.string_of(), "r");
534
535   if (Fil == NULL) {
536     errorstr = string("Tried to open PIF file ") + fname;
537     errorstr += string(", but could not (continuing)\n");
538     logLine(P_strdup(errorstr.string_of()));
539     showErrorCallback(35, errorstr); 
540     return;
541   }
542
543   /* Process the file */
544   while (!feof(Fil)) {
545     fscanf(Fil, "%s", key);
546     switch (key[0]) {
547     case 'M':
548       /* Ignore mapping information for right now */
549       fgets(tmp1, 5000, Fil);
550       break;
551     case 'R':
552 #ifndef BPATCH_LIBRARY
553       /* Create a new resource */
554       fscanf(Fil, "%s {", abstraction);
555       parent = rootResource;
556       do {
557         fscanf(Fil, "%s", tmp1);
558         if (tmp1[0] != '}') {
559           parent = resource::newResource(parent, NULL,
560                                          abstraction,
561                                          tmp1, 0.0,
562                                          nullString, // uniqifier
563                                          MDL_T_STRING,
564                                          true);
565         } else {
566           parent = NULL;
567         }
568       } while (parent != NULL);
569 #endif
570       break;
571     default:
572       errorstr = string("Ignoring bad line key (") + fname;
573       errorstr += string(") in file %s\n");
574       logLine(P_strdup(errorstr.string_of()));
575       fgets(tmp1, 5000, Fil);
576       break;
577     }
578   }
579   return;
580 }
581
582 void image::defineModules() {
583   string pds; pdmodule *mod;
584   dictionary_hash_iter<string, pdmodule*> mi(modsByFileName);
585
586   while (mi.next(pds, mod)){
587     mod->define();
588   }
589
590 #ifdef DEBUG_MDL
591   char buffer[100];
592   ostrstream osb(buffer, 100, ios::out);
593   osb << "IMAGE_" << name() << "__" << getpid() << ends;
594   ofstream of(buffer, ios::app);
595   unsigned n_size = mdlNormal.size();
596   of << "NORMAL\n";
597   for (unsigned ni=0; ni<n_size; ni++) {
598     of << mdlNormal[ni]->prettyName() << "\t\t" << mdlNormal[ni]->addr() << "\t\t" << 
599       mdlNormal[ni]->isLibTag() << endl;
600   }
601   n_size = mdlLib.size();
602   of << "\n\nLIB\n";
603   for (ni=0; ni<n_size; ni++) {
604     of << mdlLib[ni]->prettyName() << "\t\t" << mdlLib[ni]->addr() << "\t\t" <<
605       mdlLib[ni]->isLibTag() << endl;
606   }
607 #endif
608 }
609
610 void pdmodule::define() {
611 #ifndef BPATCH_LIBRARY
612   resource *modResource = NULL;
613 #endif
614 #ifdef DEBUG_MODS
615   char buffer[100];
616   ostrstream osb(buffer, 100, ios::out);
617   osb << "MODS_" << exec->name() << "__" << getpid() << ends;
618   ofstream of(buffer, ios::app);
619 #endif
620
621   unsigned f_size = funcs.size();
622
623   for (unsigned f=0; f<f_size; f++) {
624     pd_Function *pdf = funcs[f];
625 #ifdef DEBUG_MODS
626     of << fileName << ":  " << pdf->prettyName() <<  "  " <<
627       pdf->isLibTag() << "  " << pdf->addr() << endl;
628 #endif
629     // ignore line numbers for now 
630
631 #ifndef BPATCH_LIBRARY
632     if (!(pdf->isLibTag())) {
633       // see if we have created module yet.
634       if (!modResource) {
635         modResource = resource::newResource(moduleRoot, this,
636                                             nullString, // abstraction
637                                             fileName(), // name
638                                             0.0, // creation time
639                                             string::nil, // unique-ifier
640                                             MDL_T_MODULE,
641                                             false);
642       }
643       resource::newResource(modResource, pdf,
644                             nullString, // abstraction
645                             pdf->prettyName(), 0.0,
646                             nullString, // uniquifier
647                             MDL_T_PROCEDURE,
648                             false);
649     }
650 #endif
651   }
652
653   resource::send_now();
654 }
655
656 static inline bool findStartSymbol(Object &lf, Address &adr) {
657   Symbol lookUp;
658
659   if (lf.get_symbol("DYNINSTstartUserCode", lookUp) ||
660       lf.get_symbol("_DYNINSTstartUserCode", lookUp)) {
661     adr = lookUp.addr();
662     return true;
663   } else
664     return false;
665 }
666
667 static inline bool findEndSymbol(Object &lf, Address &adr) {
668   Symbol lookUp;
669
670   if (lf.get_symbol("DYNINSTendUserCode", lookUp) ||
671       lf.get_symbol("_DYNINSTendUserCode", lookUp)) {
672     adr = lookUp.addr();
673     return true;
674   } else
675     return false;
676 }
677
678 // TODO this assumes an ordering in the symbol table wrt modules KLUDGE
679 static inline bool notInUserRange(const Address adr,
680                                   const bool start, const Address startAdr,
681                                   const bool end, const Address endAdr) {
682   return ((start && (adr < startAdr)) || (end && (adr >= endAdr)));
683 }
684
685 static void binSearch (const Symbol &lookUp, vector<Symbol> &mods,
686                        string &modName, Address &modAddr, const string &def) {
687   int start=0, end=mods.size()-1, index;
688   bool found=false;
689
690   if (!mods.size()) {
691     modAddr = 0;
692     modName = def;
693     return;
694   }
695
696   while ((start <= end) && !found) {
697     index = (start+end)/2;
698
699     if ((index == (((int)mods.size())-1)) ||
700         ((mods[index].addr() <= lookUp.addr()) && (mods[index+1].addr() > lookUp.addr()))) {
701       modName = mods[index].name();
702       modAddr = mods[index].addr();      
703       found = true;
704     } else if (lookUp.addr() < mods[index].addr()) {
705       end = index - 1;
706     } else {
707       start = index + 1;
708     }
709   }
710   if (!found) {
711     modName = mods[0].name();
712     modAddr = mods[0].addr();
713   }
714 }
715
716 bool image::addOneFunction(vector<Symbol> &mods, pdmodule *lib, pdmodule *dyn,
717                            const Symbol &lookUp, pd_Function  *&retFunc) {
718   // TODO mdc
719   // find the module
720   // this is a "user" symbol
721   string modName = lookUp.module();
722   Address modAddr = 0;
723   
724 #if defined (sparc_sun_solaris2_4) || defined (i386_unknown_solaris2_5) 
725   // In solaris there is no address for modules in the symbol table, 
726   // so the binary search will not work. The module field in a symbol
727   // already has the correct module name for a symbol, if it can be
728   // obtained from the symbol table, otherwise the module is an empty
729   // string.
730   if (modName == "") {
731     string progName = name_ + "_module";
732     modName = progName;
733   }
734 #else
735   binSearch(lookUp, mods, modName, modAddr, progName);
736 #endif
737
738   return (defineFunction(lib, lookUp, modName, modAddr, retFunc));
739 }
740
741 bool inLibrary(Address addr, Address boundary_start, Address boundary_end,
742                       Address startAddr, bool startB,
743                       Address endAddr, bool endB) {
744   if ((addr >= boundary_start) && (addr <= boundary_end))
745     return true;
746   else if (startB) {
747     if (addr <= startAddr)
748       return true;
749     else if (endB) {
750       if (addr >= endAddr)
751         return true;
752       else 
753         return false;
754     } else 
755       return false;
756   } else if (endB) {
757     if (addr >= endAddr)
758       return true;
759     else
760       return false;
761   } else
762     return false;
763 }
764
765 bool image::addAllFunctions(vector<Symbol> &mods,
766                             pdmodule *lib, pdmodule *dyn, 
767                             const bool startB, const Address startAddr,
768                             const bool endB, const Address endAddr) {
769
770   Address boundary_start, boundary_end;
771   Symbol lookUp;
772   string symString;
773   SymbolIter symIter(linkedFile);
774
775 #ifdef BPATCH_LIBRARY
776   boundary_start = boundary_end = NULL;
777 #else
778   if (!linkedFile.get_symbol(symString="DYNINSTfirst", lookUp) &&
779       !linkedFile.get_symbol(symString="_DYNINSTfirst", lookUp)) {
780     //statusLine("Internal symbol DYNINSTfirst not found");
781     //showErrorCallback(31, "Internal symbol DYNINSTfirst not found");
782     //return false;
783     boundary_start = NULL;
784   } else
785     boundary_start = lookUp.addr();
786
787   if (!linkedFile.get_symbol(symString="DYNINSTend", lookUp) &&
788       !linkedFile.get_symbol(symString="_DYNINSTend", lookUp)) {
789     //statusLine("Internal symbol DYNINSTend not found");
790     //showErrorCallback(32, "Internal symbol DYNINSTend not found");
791     //return false;
792     boundary_end = NULL;
793   } else
794     boundary_end = lookUp.addr();
795 #endif
796
797   Symbol mainFuncSymbol;  //Keeps track of info on "main" function
798
799   //Checking "main" function names in same order as in the inst-*.C files
800   if (linkedFile.get_symbol(symString="main",     lookUp) ||
801       linkedFile.get_symbol(symString="_main",    lookUp) ||
802       linkedFile.get_symbol(symString="WinMain",  lookUp) ||
803       linkedFile.get_symbol(symString="_WinMain", lookUp)) 
804     mainFuncSymbol = lookUp;
805
806   // find the real functions -- those with the correct type in the symbol table
807   while (symIter.next(symString, lookUp)) {
808
809     if (funcsByAddr.defines(lookUp.addr()) ||
810         ((lookUp.addr() == mainFuncSymbol.addr()) &&
811          (lookUp.name() != mainFuncSymbol.name()))) {
812       // This function has been defined 
813       // *or*
814       // This function has the same address as the "main" function but does 
815       //   not have the same name as the "main" function.  Therefore, skip
816       //   it and let the "main" function be eventually associated with this
817       //   function address.  If we don't do this, paradynd will not have a
818       //   "main" function to start work with.
819       ;
820     } else if (lookUp.type() == Symbol::PDST_FUNCTION) {
821       if (!isValidAddress(lookUp.addr())) {
822         string msg;
823         char tempBuffer[40];
824         sprintf(tempBuffer,"%x",lookUp.addr());
825         msg = string("Function") + lookUp.name() + string("has bad address ") +
826               string(tempBuffer);
827         statusLine(msg.string_of());
828         showErrorCallback(29, msg);
829         return false;
830       }
831       pd_Function *pdf;
832       if (inLibrary(lookUp.addr(), boundary_start, boundary_end,
833                     startAddr, startB, endAddr, endB)) {
834         addInternalSymbol(lookUp.name(), lookUp.addr());
835         if (defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf)) {
836           assert(pdf); mdlLib += pdf;
837         }
838       } else {
839         if (addOneFunction(mods, lib, dyn, lookUp, pdf)) {
840           assert(pdf); mdlNormal += pdf;
841         }
842       }
843     }
844   }
845
846   // now find the pseudo functions -- this gets ugly
847   // kludge has been set if the symbol could be a function
848   symIter.reset();
849   while (symIter.next(symString, lookUp)) {
850     if (funcsByAddr.defines(lookUp.addr())) {
851       // This function has been defined
852       ;
853     } else if ((lookUp.type() == Symbol::PDST_OBJECT) && lookUp.kludge()) {
854       //logLine(P_strdup(symString.string_of()));
855       pd_Function *pdf;
856       if (inLibrary(lookUp.addr(), boundary_start, boundary_end,
857                     startAddr, startB, endAddr, endB)) {
858         addInternalSymbol(lookUp.name(), lookUp.addr());
859         if (defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf)) {
860           assert(pdf); mdlLib += pdf;
861         }
862       } else {
863         if (addOneFunction(mods, lib, dyn, lookUp, pdf)) {
864           assert(pdf); mdlNormal += pdf;
865         }
866       }
867     }
868   }
869   return true;
870 }
871
872 bool image::addAllSharedObjFunctions(vector<Symbol> &mods,
873                             pdmodule *lib, pdmodule *dyn) {
874
875   Symbol lookUp;
876   string symString;
877   SymbolIter symIter(linkedFile);
878
879   bool is_libdyninstRT = false; // true if this image is libdyninstRT
880 #if defined(i386_unknown_nt4_0)
881   if (linkedFile.get_symbol(symString="_DYNINSTfirst", lookUp)
882       || linkedFile.get_symbol(symString="_DYNINSTfirst", lookUp))
883     is_libdyninstRT = true;
884 #endif
885
886   // find the real functions -- those with the correct type in the symbol table
887   while (symIter.next(symString, lookUp)) {
888
889     if (funcsByAddr.defines(lookUp.addr())) {
890       // This function has been defined
891       ;
892     } else if (lookUp.type() == Symbol::PDST_FUNCTION) {
893       if (!isValidAddress(lookUp.addr())) {
894         string msg;
895         char tempBuffer[40];
896         sprintf(tempBuffer,"%x",lookUp.addr());
897         msg = string("Function") + lookUp.name() + string("has bad address ") +
898               string(tempBuffer);
899         statusLine(msg.string_of());
900         showErrorCallback(29, msg);
901         return false;
902       }
903       pd_Function *pdf;
904       if (is_libdyninstRT) {
905         addInternalSymbol(lookUp.name(), lookUp.addr());
906         if (defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf)) {
907           assert(pdf); mdlLib += pdf;
908         }
909       } else if (addOneFunction(mods, lib, dyn, lookUp, pdf)) {
910         assert(pdf); mdlNormal += pdf;
911       }
912     }
913   }
914
915   // now find the pseudo functions -- this gets ugly
916   // kludge has been set if the symbol could be a function
917   symIter.reset();
918   while (symIter.next(symString, lookUp)) {
919     if (funcsByAddr.defines(lookUp.addr())) {
920       // This function has been defined
921       ;
922     } else if ((lookUp.type() == Symbol::PDST_OBJECT) && lookUp.kludge()) {
923       //logLine(P_strdup(symString.string_of()));
924       pd_Function *pdf;
925       addInternalSymbol(lookUp.name(), lookUp.addr());
926       if (defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf)) {
927           assert(pdf); mdlLib += pdf;
928       }
929     }
930   }
931   return true;
932
933
934
935 int symCompare(const void *s1, const void *s2) {
936   const Symbol *sym1 = (const Symbol*)s1, *sym2 = (const Symbol*)s2;
937   // TODO mdc
938   return (sym1->addr() - sym2->addr());
939 }
940
941
942 unsigned int_addrHash(const unsigned &addr) {
943   return addr;
944 }
945
946 // Please note that this is now machine independent-almost.  Let us keep it that way
947 // 
948 image::image(const string &fileName, bool &err)
949 :   funcsByAddr(addrHash4),
950     modsByFileName(string::hash),
951     modsByFullName(string::hash),
952     file_(fileName),
953     linkedFile(fileName, pd_log_perror),
954     iSymsMap(string::hash),
955     funcsByPretty(string::hash),
956     knownJumpTargets(int_addrHash, 8192)
957 {
958 sharedobj_cerr << "image::image for non-sharedobj; file name=" << file_ << endl;
959
960   codeOffset_ = linkedFile.code_off();
961   dataOffset_ = linkedFile.data_off();
962   codeLen_ = linkedFile.code_len();
963   dataLen_ = linkedFile.data_len();
964
965 #if defined(hppa1_1_hp_hpux)
966   unwind   = linkedFile.unwind;
967 #endif
968
969   if (!codeLen_ || !linkedFile.code_ptr()) {
970     string msg = string("Unable to open executable file: ") + fileName;
971     statusLine(msg.string_of());
972
973     msg += "\n";
974     logLine(msg.string_of());
975
976     err = true;
977
978     showErrorCallback(27, msg); 
979     return;
980   }
981
982 #if !defined(i386_unknown_nt4_0)
983   Symbol version;
984   if (!linkedFile.get_symbol("DYNINSTversion", version) &&
985       !linkedFile.get_symbol("_DYNINSTversion", version)) {
986     statusLine("Could not find version number in instrumentation\n");
987     showErrorCallback(33, "Could not find version number in instrumentation");
988     err = true;
989     return;
990   }
991
992   Word version_number = get_instruction(version.addr());
993   if (version_number != 1) {
994     string msg;
995     msg = string("Incorrect version number, expected ") + string(1) + 
996           string("found ") + string(version_number);
997     statusLine(msg.string_of());
998     showErrorCallback(30, msg);
999     err = true;
1000     return;
1001   }
1002 #endif
1003
1004   const char *nm = fileName.string_of();
1005   const char *pos = P_strrchr(nm, '/');
1006
1007   err = false;
1008   if (pos)
1009     name_ = pos + 1;
1010   else
1011     name_ = fileName;
1012
1013   // find the "user" code boundaries
1014   statusLine("finding user code boundaries");
1015   Address startUserAddr=0, endUserAddr=0;
1016   bool startBound = findStartSymbol(linkedFile, startUserAddr);
1017   bool endBound = findEndSymbol(linkedFile, endUserAddr);
1018
1019   // use the *DUMMY_MODULE* until a module is defined
1020   pdmodule *dynModule = newModule(DYN_MODULE, 0);
1021   pdmodule *libModule = newModule(LIBRARY_MODULE, 0);
1022   // TODO -- define inst points in define function ?
1023
1024   // The functions cannot be verified until all of them have been seen
1025   // because calls out of each function must be tagged as calls to user
1026   // functions or call to "library" functions
1027
1028   Symbol lookUp;
1029   string symString;
1030   SymbolIter symIter(linkedFile);
1031
1032   // sort the modules by address into a vector to allow a binary search to 
1033   // determine the module that a symbol will map to -- this may be bsd specific
1034   vector<Symbol> mods;
1035
1036   while (symIter.next(symString, lookUp)) {
1037
1038     if (lookUp.type() == Symbol::PDST_MODULE) {
1039       const string &lookUpName = lookUp.name();
1040       const char *str = lookUpName.string_of();
1041       assert(str);
1042       int ln = lookUpName.length();
1043
1044       // directory definition -- ignored for now
1045       if (str[ln-1] != '/')
1046         mods += lookUp;
1047     }
1048   }
1049
1050   // sort the modules by address
1051   statusLine("sorting modules");
1052   mods.sort(symCompare);
1053 //  assert(mods.sorted(symCompare));
1054
1055   // remove duplicate entries -- some .o files may have the same address as .C files
1056   // kludge is true for module symbols that I am guessing are modules
1057   vector<Symbol> uniq;
1058   unsigned loop=0;
1059
1060   // must use loop+1 not mods.size()-1 since it is an unsigned compare
1061   //  which could go negative - jkh 5/29/95
1062   for (loop=0; loop < mods.size(); loop++) {
1063     if ((loop+1 < mods.size()) && 
1064         (mods[loop].addr() == mods[loop+1].addr())) {
1065       if (!mods[loop].kludge())
1066         mods[loop+1] = mods[loop];
1067     } else
1068       uniq += mods[loop];
1069   }
1070
1071   // define all of the functions
1072   statusLine("winnowing functions");
1073   if (!addAllFunctions(uniq, libModule, dynModule, startBound, startUserAddr,
1074                        endBound, endUserAddr)) {
1075     err = true;
1076     return;
1077   }
1078   statusLine("checking call points");
1079   checkAllCallPoints();
1080
1081 //  statusLine("ready"); // this shouldn't be here, right? (cuz we're not really ready)
1082
1083   // TODO -- remove duplicates -- see earlier note
1084   dictionary_hash<unsigned, unsigned> addr_dict(uiHash);
1085   vector<pd_Function*> temp_vec;
1086   unsigned f_size = mdlLib.size(), index;
1087   for (index=0; index<f_size; index++) {
1088     const unsigned the_address = (unsigned)mdlLib[index]->getAddress(0);
1089     if (!addr_dict.defines(the_address)) {
1090       addr_dict[the_address] = 1;
1091       temp_vec += mdlLib[index];
1092     }
1093   }
1094   mdlLib = temp_vec;
1095   temp_vec.resize(0); addr_dict.clear();
1096   f_size = mdlNormal.size();
1097   for (index=0; index<f_size; index++) {
1098     const unsigned the_address = (unsigned)mdlNormal[index]->getAddress(0);
1099     if (!addr_dict.defines(the_address)) {
1100       addr_dict[the_address] = 1;
1101       temp_vec += mdlNormal[index];
1102     }
1103   }
1104   mdlNormal = temp_vec;
1105 }
1106
1107 // 
1108 // load a shared object
1109 //
1110 image::image(const string &fileName, u_int baseAddr, bool &err)
1111 :   funcsByAddr(addrHash4),
1112     modsByFileName(string::hash),
1113     modsByFullName(string::hash),
1114     file_(fileName),
1115     linkedFile(fileName, baseAddr,pd_log_perror),
1116     iSymsMap(string::hash),
1117     funcsByPretty(string::hash),
1118     knownJumpTargets(int_addrHash, 8192)
1119 {
1120 sharedobj_cerr << "welcome to image::image for shared obj; file name=" << file_ << endl;
1121
1122   codeOffset_ = linkedFile.code_off();
1123   dataOffset_ = linkedFile.data_off();
1124   codeLen_ = linkedFile.code_len();
1125   dataLen_ = linkedFile.data_len();
1126   //logLine("IN image::image\n");
1127
1128 #if defined(hppa1_1_hp_hpux)
1129   unwind   = linkedFile.unwind;
1130 #endif
1131
1132   if (!codeLen_ || !linkedFile.code_ptr()) {
1133     string msg = string("Unable to open shared object file: ") + fileName;
1134     statusLine(msg.string_of());
1135     
1136     msg += "\n";
1137     logLine(msg.string_of());
1138
1139     err = true;
1140     showErrorCallback(27, msg); 
1141
1142     assert(false);
1143
1144     return;
1145   }
1146   else {
1147     string msg = string("Parsing shared object file: ") + fileName;
1148     statusLine(msg.string_of());
1149   }
1150
1151   const char *nm = fileName.string_of();
1152   const char *pos = P_strrchr(nm, '/');
1153
1154   err = false;
1155   if (pos)
1156     name_ = pos + 1;
1157   else
1158     name_ = fileName;
1159
1160   // use the *DUMMY_MODULE* until a module is defined
1161   pdmodule *dynModule = newModule(DYN_MODULE, 0);
1162   pdmodule *libModule = newModule(LIBRARY_MODULE, 0);
1163   // TODO -- define inst points in define function ?
1164
1165   // The functions cannot be verified until all of them have been seen
1166   // because calls out of each function must be tagged as calls to user
1167   // functions or call to "library" functions
1168
1169   Symbol lookUp;
1170   string symString;
1171   SymbolIter symIter(linkedFile);
1172
1173   // sort the modules by address into a vector to allow a binary search to 
1174   // determine the module that a symbol will map to -- this may be bsd specific
1175   vector<Symbol> mods;
1176
1177   while (symIter.next(symString, lookUp)) {
1178
1179     if (lookUp.type() == Symbol::PDST_MODULE) {
1180       const char *str = (lookUp.name()).string_of();
1181       assert(str);
1182       int ln = P_strlen(str);
1183
1184       // directory definition -- ignored for now
1185       if (str[ln-1] != '/')
1186         mods += lookUp;
1187       // string temp = string("NEW MODULE: ");
1188       // temp += lookUp.name();
1189       // temp += string("\n");
1190       // logLine(P_strdup(temp.string_of()));
1191     }
1192   }
1193
1194   // sort the modules by address
1195   mods.sort(symCompare);
1196 //  assert(mods.sorted(symCompare));
1197
1198   // remove duplicate entries -- some .o files may have the same address as .C files
1199   // kludge is true for module symbols that I am guessing are modules
1200   vector<Symbol> uniq;
1201   unsigned loop=0;
1202
1203   // must use loop+1 not mods.size()-1 since it is an unsigned compare
1204   //  which could go negative - jkh 5/29/95
1205   for (loop=0; loop < mods.size(); loop++) {
1206     if ((loop+1 < mods.size()) && 
1207          (mods[loop].addr() == mods[loop+1].addr())) {
1208       if (!mods[loop].kludge())
1209         mods[loop+1] = mods[loop];
1210     } else
1211       uniq += mods[loop];
1212   }
1213
1214   // define all of the functions
1215   if (!addAllSharedObjFunctions(uniq, libModule, dynModule)) {
1216     err = true;
1217     return;
1218   }
1219   checkAllCallPoints();
1220
1221   // TODO -- remove duplicates -- see earlier note
1222   dictionary_hash<unsigned, unsigned> addr_dict(uiHash);
1223   vector<pd_Function*> temp_vec;
1224   unsigned f_size = mdlLib.size(), index;
1225   for (index=0; index<f_size; index++) {
1226     const unsigned the_address = (unsigned)mdlLib[index]->getAddress(0);
1227     if (!addr_dict.defines(the_address)) {
1228       addr_dict[the_address] = 1;
1229       temp_vec += mdlLib[index];
1230     }
1231   }
1232   mdlLib = temp_vec;
1233   temp_vec.resize(0); addr_dict.clear();
1234   f_size = mdlNormal.size();
1235   for (index=0; index<f_size; index++) {
1236     const unsigned the_address = (unsigned)mdlNormal[index]->getAddress(0);
1237     if (!addr_dict.defines(the_address)) {
1238       addr_dict[the_address] = 1;
1239       temp_vec += mdlNormal[index];
1240     }
1241   }
1242   mdlNormal = temp_vec;
1243
1244 }
1245
1246
1247 void pdmodule::checkAllCallPoints() {
1248   unsigned fsize = funcs.size();
1249   for (unsigned f=0; f<fsize; f++)
1250       funcs[f]->checkCallPoints();
1251 }
1252
1253
1254 void image::checkAllCallPoints() {
1255   dictionary_hash_iter<string, pdmodule*> di(modsByFullName);
1256   string s; pdmodule *mod;
1257   while (di.next(s, mod))
1258     mod->checkAllCallPoints();
1259 }
1260
1261 // passing in tags allows a function to be tagged as TAG_LIB_FUNC even
1262 // if its entry is not in the tag dictionary of known functions
1263 bool image::defineFunction(pdmodule *use, const Symbol &sym, const unsigned tags,
1264                            pd_Function *&retFunc) {
1265   // We used to skip a leading underscore, but not anymore.
1266   // (I forgot why we ever did in the first place)
1267
1268   unsigned dictTags = findTags(sym.name());
1269   return (newFunc(use, sym.name(), sym.addr(), sym.size(), tags | dictTags, retFunc));
1270 }
1271
1272 pdmodule *image::getOrCreateModule(const string &modName, 
1273                                       const Address modAddr) {
1274   const char *str = modName.string_of();
1275   int len = modName.length();
1276   assert(len>0);
1277
1278   // TODO ignore directory definitions for now
1279   if (str[len-1] == '/') {
1280     return NULL;
1281   } else {
1282     // TODO - navigate ".." and "."
1283     const char *lastSlash = P_strrchr(str, '/');
1284     if (lastSlash)
1285       return (newModule(++lastSlash, modAddr));
1286     else
1287       return (newModule(modName, modAddr));
1288   }
1289 }
1290
1291 // KLUDGE TODO - internal functions are tagged with TAG_LIB_FUNC
1292 // but they won't have tags in the tag dict, so this happens...
1293 bool image::defineFunction(pdmodule *libModule, const Symbol &sym,
1294                            const string &modName, const Address modAddr,
1295                            pd_Function *&retFunc) {
1296
1297   // We used to skip a leading underscore, but not any more.
1298
1299   unsigned tags = findTags(sym.name());
1300
1301   if (TAG_LIB_FUNC & tags)
1302     return (newFunc(libModule, sym.name(), sym.addr(), sym.size(),
1303                     tags | TAG_LIB_FUNC, retFunc));
1304   else {
1305     pdmodule *use = getOrCreateModule(modName, modAddr);
1306     assert(use);
1307     return (newFunc(use, sym.name(), sym.addr(), sym.size(), tags, retFunc));
1308   }
1309 }
1310
1311 // Verify that this is code
1312 // Find the call points
1313 // Find the return address
1314 // TODO -- use an instruction object to remove
1315 // Sets err to false on error, true on success
1316 //
1317 // Note - this must define funcEntry and funcReturn
1318 // 
1319 pd_Function::pd_Function(const string &symbol, const string &pretty, 
1320                        pdmodule *f, Address adr, const unsigned size, 
1321                        const unsigned tg, const image *owner, bool &err) : 
1322   function_base(symbol, pretty, adr, size,tg),
1323   file_(f),
1324   funcEntry_(0),
1325   relocatable_(false)
1326 {
1327   err = findInstPoints(owner) == false;
1328 }
1329