Added support for the x86 Solaris platform and dynamically linked
[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 #ifndef BPATCH_LIBRARY
654   resource::send_now();
655 #endif
656 }
657
658 static inline bool findStartSymbol(Object &lf, Address &adr) {
659   Symbol lookUp;
660
661   if (lf.get_symbol("DYNINSTstartUserCode", lookUp) ||
662       lf.get_symbol("_DYNINSTstartUserCode", lookUp)) {
663     adr = lookUp.addr();
664     return true;
665   } else
666     return false;
667 }
668
669 static inline bool findEndSymbol(Object &lf, Address &adr) {
670   Symbol lookUp;
671
672   if (lf.get_symbol("DYNINSTendUserCode", lookUp) ||
673       lf.get_symbol("_DYNINSTendUserCode", lookUp)) {
674     adr = lookUp.addr();
675     return true;
676   } else
677     return false;
678 }
679
680 // TODO this assumes an ordering in the symbol table wrt modules KLUDGE
681 static inline bool notInUserRange(const Address adr,
682                                   const bool start, const Address startAdr,
683                                   const bool end, const Address endAdr) {
684   return ((start && (adr < startAdr)) || (end && (adr >= endAdr)));
685 }
686
687 static void binSearch (const Symbol &lookUp, vector<Symbol> &mods,
688                        string &modName, Address &modAddr, const string &def) {
689   int start=0, end=mods.size()-1, index;
690   bool found=false;
691
692   if (!mods.size()) {
693     modAddr = 0;
694     modName = def;
695     return;
696   }
697
698   while ((start <= end) && !found) {
699     index = (start+end)/2;
700
701     if ((index == (((int)mods.size())-1)) ||
702         ((mods[index].addr() <= lookUp.addr()) && (mods[index+1].addr() > lookUp.addr()))) {
703       modName = mods[index].name();
704       modAddr = mods[index].addr();      
705       found = true;
706     } else if (lookUp.addr() < mods[index].addr()) {
707       end = index - 1;
708     } else {
709       start = index + 1;
710     }
711   }
712   if (!found) {
713     modName = mods[0].name();
714     modAddr = mods[0].addr();
715   }
716 }
717
718 bool image::addOneFunction(vector<Symbol> &mods, pdmodule *lib, pdmodule *dyn,
719                            const Symbol &lookUp, pd_Function  *&retFunc) {
720   // TODO mdc
721   // find the module
722   // this is a "user" symbol
723   string modName = lookUp.module();
724   Address modAddr = 0;
725   
726   string progName = name_ + "_module";
727
728 #if defined (sparc_sun_solaris2_4) || defined (i386_unknown_solaris2_5) 
729   // In solaris there is no address for modules in the symbol table, 
730   // so the binary search will not work. The module field in a symbol
731   // already has the correct module name for a symbol, if it can be
732   // obtained from the symbol table, otherwise the module is an empty
733   // string.
734   if (modName == "") {
735     modName = progName;
736   }
737 #else
738   binSearch(lookUp, mods, modName, modAddr, progName);
739 #endif
740
741   return (defineFunction(lib, lookUp, modName, modAddr, retFunc));
742 }
743
744 bool inLibrary(Address addr, Address boundary_start, Address boundary_end,
745                       Address startAddr, bool startB,
746                       Address endAddr, bool endB) {
747   if ((addr >= boundary_start) && (addr <= boundary_end))
748     return true;
749   else if (startB) {
750     if (addr <= startAddr)
751       return true;
752     else if (endB) {
753       if (addr >= endAddr)
754         return true;
755       else 
756         return false;
757     } else 
758       return false;
759   } else if (endB) {
760     if (addr >= endAddr)
761       return true;
762     else
763       return false;
764   } else
765     return false;
766 }
767
768 bool image::addAllFunctions(vector<Symbol> &mods,
769                             pdmodule *lib, pdmodule *dyn, 
770                             const bool startB, const Address startAddr,
771                             const bool endB, const Address endAddr) {
772
773   Address boundary_start, boundary_end;
774   Symbol lookUp;
775   string symString;
776   SymbolIter symIter(linkedFile);
777
778 #ifdef BPATCH_LIBRARY
779   boundary_start = boundary_end = NULL;
780 #else
781   if (!linkedFile.get_symbol(symString="DYNINSTfirst", lookUp) &&
782       !linkedFile.get_symbol(symString="_DYNINSTfirst", lookUp)) {
783     //statusLine("Internal symbol DYNINSTfirst not found");
784     //showErrorCallback(31, "Internal symbol DYNINSTfirst not found");
785     //return false;
786     boundary_start = NULL;
787   } else
788     boundary_start = lookUp.addr();
789
790   if (!linkedFile.get_symbol(symString="DYNINSTend", lookUp) &&
791       !linkedFile.get_symbol(symString="_DYNINSTend", lookUp)) {
792     //statusLine("Internal symbol DYNINSTend not found");
793     //showErrorCallback(32, "Internal symbol DYNINSTend not found");
794     //return false;
795     boundary_end = NULL;
796   } else
797     boundary_end = lookUp.addr();
798 #endif
799
800   Symbol mainFuncSymbol;  //Keeps track of info on "main" function
801
802   //Checking "main" function names in same order as in the inst-*.C files
803   if (linkedFile.get_symbol(symString="main",     lookUp) ||
804       linkedFile.get_symbol(symString="_main",    lookUp) ||
805       linkedFile.get_symbol(symString="WinMain",  lookUp) ||
806       linkedFile.get_symbol(symString="_WinMain", lookUp)) 
807     mainFuncSymbol = lookUp;
808
809   // find the real functions -- those with the correct type in the symbol table
810   while (symIter.next(symString, lookUp)) {
811
812     if (funcsByAddr.defines(lookUp.addr()) ||
813         ((lookUp.addr() == mainFuncSymbol.addr()) &&
814          (lookUp.name() != mainFuncSymbol.name()))) {
815       // This function has been defined 
816       // *or*
817       // This function has the same address as the "main" function but does 
818       //   not have the same name as the "main" function.  Therefore, skip
819       //   it and let the "main" function be eventually associated with this
820       //   function address.  If we don't do this, paradynd will not have a
821       //   "main" function to start work with.
822       ;
823     } else if (lookUp.type() == Symbol::PDST_FUNCTION) {
824       if (!isValidAddress(lookUp.addr())) {
825         string msg;
826         char tempBuffer[40];
827         sprintf(tempBuffer,"%x",lookUp.addr());
828         msg = string("Function") + lookUp.name() + string("has bad address ") +
829               string(tempBuffer);
830         statusLine(msg.string_of());
831         showErrorCallback(29, msg);
832         return false;
833       }
834       pd_Function *pdf;
835       if (inLibrary(lookUp.addr(), boundary_start, boundary_end,
836                     startAddr, startB, endAddr, endB)) {
837         addInternalSymbol(lookUp.name(), lookUp.addr());
838         if (defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf)) {
839           assert(pdf); mdlLib += pdf;
840         }
841       } else {
842         if (addOneFunction(mods, lib, dyn, lookUp, pdf)) {
843           assert(pdf); mdlNormal += pdf;
844         }
845       }
846     }
847   }
848
849   // now find the pseudo functions -- this gets ugly
850   // kludge has been set if the symbol could be a function
851   symIter.reset();
852   while (symIter.next(symString, lookUp)) {
853     if (funcsByAddr.defines(lookUp.addr())) {
854       // This function has been defined
855       ;
856     } else if ((lookUp.type() == Symbol::PDST_OBJECT) && lookUp.kludge()) {
857       //logLine(P_strdup(symString.string_of()));
858       pd_Function *pdf;
859       if (inLibrary(lookUp.addr(), boundary_start, boundary_end,
860                     startAddr, startB, endAddr, endB)) {
861         addInternalSymbol(lookUp.name(), lookUp.addr());
862         if (defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf)) {
863           assert(pdf); mdlLib += pdf;
864         }
865       } else {
866         if (addOneFunction(mods, lib, dyn, lookUp, pdf)) {
867           assert(pdf); mdlNormal += pdf;
868         }
869       }
870     }
871   }
872   return true;
873 }
874
875 bool image::addAllSharedObjFunctions(vector<Symbol> &mods,
876                             pdmodule *lib, pdmodule *dyn) {
877
878   Symbol lookUp;
879   string symString;
880   SymbolIter symIter(linkedFile);
881
882   bool is_libdyninstRT = false; // true if this image is libdyninstRT
883 #if defined(i386_unknown_nt4_0)
884   if (linkedFile.get_symbol(symString="_DYNINSTfirst", lookUp)
885       || linkedFile.get_symbol(symString="_DYNINSTfirst", lookUp))
886     is_libdyninstRT = true;
887 #endif
888
889   // find the real functions -- those with the correct type in the symbol table
890   while (symIter.next(symString, lookUp)) {
891
892     if (funcsByAddr.defines(lookUp.addr())) {
893       // This function has been defined
894       ;
895     } else if (lookUp.type() == Symbol::PDST_FUNCTION) {
896       if (!isValidAddress(lookUp.addr())) {
897         string msg;
898         char tempBuffer[40];
899         sprintf(tempBuffer,"%x",lookUp.addr());
900         msg = string("Function") + lookUp.name() + string("has bad address ") +
901               string(tempBuffer);
902         statusLine(msg.string_of());
903         showErrorCallback(29, msg);
904         return false;
905       }
906       pd_Function *pdf;
907       if (is_libdyninstRT) {
908         addInternalSymbol(lookUp.name(), lookUp.addr());
909         if (defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf)) {
910           assert(pdf); mdlLib += pdf;
911         }
912       } else if (addOneFunction(mods, lib, dyn, lookUp, pdf)) {
913         assert(pdf); mdlNormal += pdf;
914       }
915     }
916   }
917
918   // now find the pseudo functions -- this gets ugly
919   // kludge has been set if the symbol could be a function
920   symIter.reset();
921   while (symIter.next(symString, lookUp)) {
922     if (funcsByAddr.defines(lookUp.addr())) {
923       // This function has been defined
924       ;
925     } else if ((lookUp.type() == Symbol::PDST_OBJECT) && lookUp.kludge()) {
926       //logLine(P_strdup(symString.string_of()));
927       pd_Function *pdf;
928       addInternalSymbol(lookUp.name(), lookUp.addr());
929       if (defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf)) {
930           assert(pdf); mdlLib += pdf;
931       }
932     }
933   }
934   return true;
935
936
937
938 int symCompare(const void *s1, const void *s2) {
939   const Symbol *sym1 = (const Symbol*)s1, *sym2 = (const Symbol*)s2;
940   // TODO mdc
941   return (sym1->addr() - sym2->addr());
942 }
943
944
945 unsigned int_addrHash(const unsigned &addr) {
946   return addr;
947 }
948
949 // Please note that this is now machine independent-almost.  Let us keep it that way
950 // 
951 image::image(const string &fileName, bool &err)
952 :   funcsByAddr(addrHash4),
953     modsByFileName(string::hash),
954     modsByFullName(string::hash),
955     file_(fileName),
956     linkedFile(fileName, pd_log_perror),
957     iSymsMap(string::hash),
958     funcsByPretty(string::hash),
959     knownJumpTargets(int_addrHash, 8192)
960 {
961 sharedobj_cerr << "image::image for non-sharedobj; file name=" << file_ << endl;
962
963   codeOffset_ = linkedFile.code_off();
964   dataOffset_ = linkedFile.data_off();
965   codeLen_ = linkedFile.code_len();
966   dataLen_ = linkedFile.data_len();
967
968 #if defined(hppa1_1_hp_hpux)
969   unwind   = linkedFile.unwind;
970 #endif
971
972   if (!codeLen_ || !linkedFile.code_ptr()) {
973     string msg = string("Unable to open executable file: ") + fileName;
974     statusLine(msg.string_of());
975
976     msg += "\n";
977     logLine(msg.string_of());
978
979     err = true;
980
981     showErrorCallback(27, msg); 
982     return;
983   }
984
985 #if !defined(i386_unknown_nt4_0)
986   Symbol version;
987   if (!linkedFile.get_symbol("DYNINSTversion", version) &&
988       !linkedFile.get_symbol("_DYNINSTversion", version)) {
989     statusLine("Could not find version number in instrumentation\n");
990     showErrorCallback(33, "Could not find version number in instrumentation");
991     err = true;
992     return;
993   }
994
995   Word version_number = get_instruction(version.addr());
996   if (version_number != 1) {
997     string msg;
998     msg = string("Incorrect version number, expected ") + string(1) + 
999           string("found ") + string(version_number);
1000     statusLine(msg.string_of());
1001     showErrorCallback(30, msg);
1002     err = true;
1003     return;
1004   }
1005 #endif
1006
1007   const char *nm = fileName.string_of();
1008   const char *pos = P_strrchr(nm, '/');
1009
1010   err = false;
1011   if (pos)
1012     name_ = pos + 1;
1013   else
1014     name_ = fileName;
1015
1016   // find the "user" code boundaries
1017   statusLine("finding user code boundaries");
1018   Address startUserAddr=0, endUserAddr=0;
1019   bool startBound = findStartSymbol(linkedFile, startUserAddr);
1020   bool endBound = findEndSymbol(linkedFile, endUserAddr);
1021
1022   // use the *DUMMY_MODULE* until a module is defined
1023   pdmodule *dynModule = newModule(DYN_MODULE, 0);
1024   pdmodule *libModule = newModule(LIBRARY_MODULE, 0);
1025   // TODO -- define inst points in define function ?
1026
1027   // The functions cannot be verified until all of them have been seen
1028   // because calls out of each function must be tagged as calls to user
1029   // functions or call to "library" functions
1030
1031   Symbol lookUp;
1032   string symString;
1033   SymbolIter symIter(linkedFile);
1034
1035   // sort the modules by address into a vector to allow a binary search to 
1036   // determine the module that a symbol will map to -- this may be bsd specific
1037   vector<Symbol> mods;
1038
1039   while (symIter.next(symString, lookUp)) {
1040
1041     if (lookUp.type() == Symbol::PDST_MODULE) {
1042       const string &lookUpName = lookUp.name();
1043       const char *str = lookUpName.string_of();
1044       assert(str);
1045       int ln = lookUpName.length();
1046
1047       // directory definition -- ignored for now
1048       if (str[ln-1] != '/')
1049         mods += lookUp;
1050     }
1051   }
1052
1053   // sort the modules by address
1054   statusLine("sorting modules");
1055   mods.sort(symCompare);
1056 //  assert(mods.sorted(symCompare));
1057
1058   // remove duplicate entries -- some .o files may have the same address as .C files
1059   // kludge is true for module symbols that I am guessing are modules
1060   vector<Symbol> uniq;
1061   unsigned loop=0;
1062
1063   // must use loop+1 not mods.size()-1 since it is an unsigned compare
1064   //  which could go negative - jkh 5/29/95
1065   for (loop=0; loop < mods.size(); loop++) {
1066     if ((loop+1 < mods.size()) && 
1067         (mods[loop].addr() == mods[loop+1].addr())) {
1068       if (!mods[loop].kludge())
1069         mods[loop+1] = mods[loop];
1070     } else
1071       uniq += mods[loop];
1072   }
1073
1074   // define all of the functions
1075   statusLine("winnowing functions");
1076   if (!addAllFunctions(uniq, libModule, dynModule, startBound, startUserAddr,
1077                        endBound, endUserAddr)) {
1078     err = true;
1079     return;
1080   }
1081   statusLine("checking call points");
1082   checkAllCallPoints();
1083
1084 //  statusLine("ready"); // this shouldn't be here, right? (cuz we're not really ready)
1085
1086   // TODO -- remove duplicates -- see earlier note
1087   dictionary_hash<unsigned, unsigned> addr_dict(uiHash);
1088   vector<pd_Function*> temp_vec;
1089   unsigned f_size = mdlLib.size(), index;
1090   for (index=0; index<f_size; index++) {
1091     const unsigned the_address = (unsigned)mdlLib[index]->getAddress(0);
1092     if (!addr_dict.defines(the_address)) {
1093       addr_dict[the_address] = 1;
1094       temp_vec += mdlLib[index];
1095     }
1096   }
1097   mdlLib = temp_vec;
1098   temp_vec.resize(0); addr_dict.clear();
1099   f_size = mdlNormal.size();
1100   for (index=0; index<f_size; index++) {
1101     const unsigned the_address = (unsigned)mdlNormal[index]->getAddress(0);
1102     if (!addr_dict.defines(the_address)) {
1103       addr_dict[the_address] = 1;
1104       temp_vec += mdlNormal[index];
1105     }
1106   }
1107   mdlNormal = temp_vec;
1108 }
1109
1110 // 
1111 // load a shared object
1112 //
1113 image::image(const string &fileName, u_int baseAddr, bool &err)
1114 :   funcsByAddr(addrHash4),
1115     modsByFileName(string::hash),
1116     modsByFullName(string::hash),
1117     file_(fileName),
1118     linkedFile(fileName, baseAddr,pd_log_perror),
1119     iSymsMap(string::hash),
1120     funcsByPretty(string::hash),
1121     knownJumpTargets(int_addrHash, 8192)
1122 {
1123 sharedobj_cerr << "welcome to image::image for shared obj; file name=" << file_ << endl;
1124
1125   codeOffset_ = linkedFile.code_off();
1126   dataOffset_ = linkedFile.data_off();
1127   codeLen_ = linkedFile.code_len();
1128   dataLen_ = linkedFile.data_len();
1129   //logLine("IN image::image\n");
1130
1131 #if defined(hppa1_1_hp_hpux)
1132   unwind   = linkedFile.unwind;
1133 #endif
1134
1135   if (!codeLen_ || !linkedFile.code_ptr()) {
1136     string msg = string("Unable to open shared object file: ") + fileName;
1137     statusLine(msg.string_of());
1138     
1139     msg += "\n";
1140     logLine(msg.string_of());
1141
1142     err = true;
1143     showErrorCallback(27, msg); 
1144
1145     assert(false);
1146
1147     return;
1148   }
1149   else {
1150     string msg = string("Parsing shared object file: ") + fileName;
1151     statusLine(msg.string_of());
1152   }
1153
1154   const char *nm = fileName.string_of();
1155   const char *pos = P_strrchr(nm, '/');
1156
1157   err = false;
1158   if (pos)
1159     name_ = pos + 1;
1160   else
1161     name_ = fileName;
1162
1163   // use the *DUMMY_MODULE* until a module is defined
1164   pdmodule *dynModule = newModule(DYN_MODULE, 0);
1165   pdmodule *libModule = newModule(LIBRARY_MODULE, 0);
1166   // TODO -- define inst points in define function ?
1167
1168   // The functions cannot be verified until all of them have been seen
1169   // because calls out of each function must be tagged as calls to user
1170   // functions or call to "library" functions
1171
1172   Symbol lookUp;
1173   string symString;
1174   SymbolIter symIter(linkedFile);
1175
1176   // sort the modules by address into a vector to allow a binary search to 
1177   // determine the module that a symbol will map to -- this may be bsd specific
1178   vector<Symbol> mods;
1179
1180   while (symIter.next(symString, lookUp)) {
1181
1182     if (lookUp.type() == Symbol::PDST_MODULE) {
1183       const char *str = (lookUp.name()).string_of();
1184       assert(str);
1185       int ln = P_strlen(str);
1186
1187       // directory definition -- ignored for now
1188       if (str[ln-1] != '/')
1189         mods += lookUp;
1190       // string temp = string("NEW MODULE: ");
1191       // temp += lookUp.name();
1192       // temp += string("\n");
1193       // logLine(P_strdup(temp.string_of()));
1194     }
1195   }
1196
1197   // sort the modules by address
1198   mods.sort(symCompare);
1199 //  assert(mods.sorted(symCompare));
1200
1201   // remove duplicate entries -- some .o files may have the same address as .C files
1202   // kludge is true for module symbols that I am guessing are modules
1203   vector<Symbol> uniq;
1204   unsigned loop=0;
1205
1206   // must use loop+1 not mods.size()-1 since it is an unsigned compare
1207   //  which could go negative - jkh 5/29/95
1208   for (loop=0; loop < mods.size(); loop++) {
1209     if ((loop+1 < mods.size()) && 
1210          (mods[loop].addr() == mods[loop+1].addr())) {
1211       if (!mods[loop].kludge())
1212         mods[loop+1] = mods[loop];
1213     } else
1214       uniq += mods[loop];
1215   }
1216
1217   // define all of the functions
1218   if (!addAllSharedObjFunctions(uniq, libModule, dynModule)) {
1219     err = true;
1220     return;
1221   }
1222   checkAllCallPoints();
1223
1224   // TODO -- remove duplicates -- see earlier note
1225   dictionary_hash<unsigned, unsigned> addr_dict(uiHash);
1226   vector<pd_Function*> temp_vec;
1227   unsigned f_size = mdlLib.size(), index;
1228   for (index=0; index<f_size; index++) {
1229     const unsigned the_address = (unsigned)mdlLib[index]->getAddress(0);
1230     if (!addr_dict.defines(the_address)) {
1231       addr_dict[the_address] = 1;
1232       temp_vec += mdlLib[index];
1233     }
1234   }
1235   mdlLib = temp_vec;
1236   temp_vec.resize(0); addr_dict.clear();
1237   f_size = mdlNormal.size();
1238   for (index=0; index<f_size; index++) {
1239     const unsigned the_address = (unsigned)mdlNormal[index]->getAddress(0);
1240     if (!addr_dict.defines(the_address)) {
1241       addr_dict[the_address] = 1;
1242       temp_vec += mdlNormal[index];
1243     }
1244   }
1245   mdlNormal = temp_vec;
1246
1247 }
1248
1249
1250 void pdmodule::checkAllCallPoints() {
1251   unsigned fsize = funcs.size();
1252   for (unsigned f=0; f<fsize; f++)
1253       funcs[f]->checkCallPoints();
1254 }
1255
1256
1257 void image::checkAllCallPoints() {
1258   dictionary_hash_iter<string, pdmodule*> di(modsByFullName);
1259   string s; pdmodule *mod;
1260   while (di.next(s, mod))
1261     mod->checkAllCallPoints();
1262 }
1263
1264 // passing in tags allows a function to be tagged as TAG_LIB_FUNC even
1265 // if its entry is not in the tag dictionary of known functions
1266 bool image::defineFunction(pdmodule *use, const Symbol &sym, const unsigned tags,
1267                            pd_Function *&retFunc) {
1268   // We used to skip a leading underscore, but not anymore.
1269   // (I forgot why we ever did in the first place)
1270
1271   unsigned dictTags = findTags(sym.name());
1272   return (newFunc(use, sym.name(), sym.addr(), sym.size(), tags | dictTags, retFunc));
1273 }
1274
1275 pdmodule *image::getOrCreateModule(const string &modName, 
1276                                       const Address modAddr) {
1277   const char *str = modName.string_of();
1278   int len = modName.length();
1279   assert(len>0);
1280
1281   // TODO ignore directory definitions for now
1282   if (str[len-1] == '/') {
1283     return NULL;
1284   } else {
1285     // TODO - navigate ".." and "."
1286     const char *lastSlash = P_strrchr(str, '/');
1287     if (lastSlash)
1288       return (newModule(++lastSlash, modAddr));
1289     else
1290       return (newModule(modName, modAddr));
1291   }
1292 }
1293
1294 // KLUDGE TODO - internal functions are tagged with TAG_LIB_FUNC
1295 // but they won't have tags in the tag dict, so this happens...
1296 bool image::defineFunction(pdmodule *libModule, const Symbol &sym,
1297                            const string &modName, const Address modAddr,
1298                            pd_Function *&retFunc) {
1299
1300   // We used to skip a leading underscore, but not any more.
1301
1302   unsigned tags = findTags(sym.name());
1303
1304   if (TAG_LIB_FUNC & tags)
1305     return (newFunc(libModule, sym.name(), sym.addr(), sym.size(),
1306                     tags | TAG_LIB_FUNC, retFunc));
1307   else {
1308     pdmodule *use = getOrCreateModule(modName, modAddr);
1309     assert(use);
1310     return (newFunc(use, sym.name(), sym.addr(), sym.size(), tags, retFunc));
1311   }
1312 }
1313
1314 // Verify that this is code
1315 // Find the call points
1316 // Find the return address
1317 // TODO -- use an instruction object to remove
1318 // Sets err to false on error, true on success
1319 //
1320 // Note - this must define funcEntry and funcReturn
1321 // 
1322 pd_Function::pd_Function(const string &symbol, const string &pretty, 
1323                        pdmodule *f, Address adr, const unsigned size, 
1324                        const unsigned tg, const image *owner, bool &err) : 
1325   function_base(symbol, pretty, adr, size,tg),
1326   file_(f),
1327   funcEntry_(0),
1328   relocatable_(false)
1329 {
1330   err = findInstPoints(owner) == false;
1331 }
1332