initial dyninstAPI commit for code coverage
[dyninst.git] / dyninstAPI / src / symtab.h
1 /*
2  * Copyright (c) 1996 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 // $Id: symtab.h,v 1.99 2001/09/07 21:15:09 tikir Exp $
43
44 #ifndef SYMTAB_HDR
45 #define SYMTAB_HDR
46
47 extern "C" {
48 #include <sys/types.h>
49 #include <stdlib.h>
50 #include <stdio.h>
51 #include <assert.h>
52 }
53
54 #include "common/h/Pair.h"
55 #include "common/h/Vector.h"
56 #include "common/h/Dictionary.h"
57 #include "common/h/list.h"
58 #include "dyninstAPI/src/Object.h"
59 #include "dyninstAPI/src/dyninst.h"
60 #include "dyninstAPI/src/arch.h"
61 #include "dyninstAPI/src/util.h"
62 #include "common/h/String.h"
63
64 #ifndef BPATCH_LIBRARY
65 #include "paradynd/src/resource.h"
66 #endif
67
68 #include "common/h/Types.h"
69 #include "common/h/Symbol.h"
70 #include "dyninstAPI/src/inst.h"
71
72 #ifndef mips_unknown_ce2_11 //ccw 8 apr 2001
73 #include "dyninstAPI/src/FunctionExpansionRecord.h"
74 class LocalAlterationSet;
75 #endif
76
77 #define RH_SEPERATOR '/'
78
79 /*
80  * List of supported languages.
81  *
82  */
83 typedef enum { lang_Unknown,
84                lang_Assembly,
85                lang_C,
86                lang_CPlusPlus,
87                lang_GnuCPlusPlus,
88                lang_Fortran,
89                lang_CMFortran
90                } supportedLanguages;
91
92  
93 /* contents of line number field if line is unknown */
94 #define UNKNOWN_LINE    0
95
96 #define TAG_LIB_FUNC    0x1
97 #define TAG_IO_OUT      0x2
98 #define TAG_IO_IN       0x4
99 #define TAG_MSG_SEND    0x8
100 #define TAG_MSG_RECV    0x10
101 #define TAG_SYNC_FUNC   0x20
102 #define TAG_CPU_STATE   0x40    /* does the func block waiting for ext. event */
103 #define TAG_MSG_FILT    0x80
104
105 #define DYN_MODULE "DYN_MODULE"
106 #define EXTRA_MODULE "EXTRA_MODULE"
107 #define USER_MODULE "USER_MODULE"
108 #define LIBRARY_MODULE  "LIBRARY_MODULE"
109
110 class image;
111 class lineTable;
112 class process;
113 class pd_Function;
114
115 // if a function needs to be relocated when it's instrumented then we need
116 // to keep track of new instrumentation points for this function on a per
117 // process basis (there is no guarentee that two processes are going to
118 // relocated this function to the same location in the heap)
119 class relocatedFuncInfo {
120 public:
121     relocatedFuncInfo(process *p,Address na):proc_(p),
122                       addr_(na),funcEntry_(0),installed_(false){}
123     ~relocatedFuncInfo(){proc_ = 0;}
124     Address address(){ return addr_;}
125     const process *getProcess(){ return proc_;}
126     const vector<instPoint*> &funcReturns(){ return funcReturns_;}
127     const vector<instPoint*> &funcCallSites(){ return calls_;}
128     const vector<instPoint*> &funcArbitraryPoints(){ return arbitraryPoints_;}
129     const instPoint *funcEntry(){ return funcEntry_;}
130     void addFuncEntry(instPoint *e){ if(e) funcEntry_ = e; }
131     void addFuncReturn(instPoint *r){ if(r) funcReturns_.push_back(r); }
132     void addFuncCall(instPoint *c){ if(c) calls_.push_back(c); }
133     void addArbitraryPoint(instPoint *r){ if(r) arbitraryPoints_.push_back(r); }
134     bool isInstalled(){ return installed_; }
135     void setInstalled() { installed_ = true; }
136 private:
137     const process *proc_;               // process assoc. with the relocation
138     Address addr_;                      // function's relocated address
139     instPoint *funcEntry_;              // function entry point
140     bool installed_;                    // if true, function has been relocated
141     vector<instPoint*> funcReturns_;    // return point(s)
142     vector<instPoint*> calls_;          // pointer to the calls
143     vector<instPoint*> arbitraryPoints_;          // pointer to the calls
144 };
145
146
147 class pdmodule;
148 class module;
149
150 class function_base {
151 public:
152     function_base(const string &symbol, const string &pretty,
153                 Address adr, const unsigned size):
154                 line_(0), addr_(adr),size_(size) { 
155                 symTabName_.push_back(symbol); prettyName_.push_back(pretty); }
156     virtual ~function_base() { /* TODO */ }
157
158     /* The next two asserts should necver be reached, function_base has no
159      * default constructor which leaves the string vectors empty, the if
160      * is more or less a sanity check, if the asserts here are ever reached
161      * then something really bad must have happened.  Since we will never
162      * make it past the assert, in order to remove the compiler warnings
163      * we add the return to return the same string from the first part
164      * of the if statement
165      */
166     const string &symTabName() const { 
167         if (symTabName_.size() > 0) return symTabName_[0];
168         else assert(0 && "symtab name"); return symTabName_[0]; }
169     const string &prettyName() const {
170         if (prettyName_.size() > 0) return prettyName_[0];
171         else assert(0 && "pretty name"); return prettyName_[0]; } 
172     vector<string> symTabNameVector() { return symTabName_; }
173     vector<string> prettyNameVector() { return prettyName_; }
174     void addSymTabName(string name) { symTabName_.push_back(name); }
175     void addPrettyName(string name) { prettyName_.push_back(name); }
176     unsigned size() const {return size_;}
177     Address addr() const {return addr_;}
178
179     bool match(function_base *p);
180
181     virtual Address getAddress(const process *p) = 0;
182     virtual Address getEffectiveAddress(const process *p) const = 0;
183     virtual const instPoint *funcEntry(process *p) const = 0;
184     virtual const vector<instPoint*> &funcExits(process *p) const = 0;
185     virtual const vector<instPoint*> &funcCalls(process *p) const = 0; 
186     virtual const vector<instPoint*> &funcArbitraryPoints(process *p) const = 0; 
187     virtual bool hasNoStackFrame() const = 0;
188        // formerly "isLeafFunc()" but that led to confusion, since people assign two
189        // different meanings to "leaf" fns: (1) has no stack frame, (2) makes no calls.
190        // By renaming this fn, we make clear that we're returning (1), not (2).
191
192     // extra debuggering info....
193     ostream & operator<<(ostream &s) const;
194     friend ostream &operator<<(ostream &os, function_base &f);
195 private:
196     vector<string> symTabName_; /* name as it appears in the symbol table */
197     vector<string> prettyName_; /* user's view of name (i.e. de-mangled) */
198     int line_;                  /* first line of function */
199     Address addr_;              /* address of the start of the func */
200     unsigned size_;             /* the function size, in bytes, used to
201                                    define the function boundaries. This may not
202                                    be exact, and may not be used on all 
203                                    platforms. */
204     
205 };
206
207
208 class instPoint;
209 class pd_Function : public function_base {
210  public:
211     pd_Function(const string &symbol, const string &pretty, pdmodule *f, 
212                 Address adr, const unsigned size, 
213                 const image *owner, bool &err);
214     ~pd_Function() { delete relocatedCode;  // delete the rewritten version 
215                      delete originalCode;   // of the function if it was 
216                      delete instructions;   // relocated      
217                                /* TODO */ }
218
219     bool findInstPoints(const image *owner);
220     void checkCallPoints();
221     bool defineInstPoint();
222     pdmodule *file() const { return file_;}
223     Address newCallPoint(Address adr, const instruction code, 
224                          const image *owner, bool &err);
225
226     // passing in a value of 0 for p will return the original address
227     // otherwise, if the process is relocated it will return the new address
228     Address getAddress(const process *p){
229         if(p && relocatable_) { 
230           for(u_int i=0; i < relocatedByProcess.size(); i++){
231             if((relocatedByProcess[i])->getProcess() == p) 
232                 return (relocatedByProcess[i])->address();
233         } }
234         return addr();
235     }
236     Address getEffectiveAddress(const process *p) const;
237     const instPoint *funcEntry(process *p) const {
238         if(p && relocatable_) { 
239           for(u_int i=0; i < relocatedByProcess.size(); i++){
240             if((relocatedByProcess[i])->getProcess() == p) 
241                 return (relocatedByProcess[i])->funcEntry();
242         } }
243         return funcEntry_;
244     }
245     const vector<instPoint*> &funcExits(process *p) const {
246         if(p && relocatable_) {
247           for(u_int i=0; i < relocatedByProcess.size(); i++){
248             if((relocatedByProcess[i])->getProcess() == p) 
249                 return (relocatedByProcess[i])->funcReturns();
250         } }
251         return funcReturns;
252     }
253     const vector<instPoint*> &funcArbitraryPoints(process *p) const {
254         if(p && relocatable_) {
255           for(u_int i=0; i < relocatedByProcess.size(); i++){
256             if((relocatedByProcess[i])->getProcess() == p) 
257                 return (relocatedByProcess[i])->funcArbitraryPoints();
258         } }
259         return arbitraryPoints;
260     }
261     void addArbitraryPoint(instPoint* insp,process* p){
262         if(insp) arbitraryPoints.push_back(insp);
263
264         // Cheesy get-rid-of-compiler-warning
265         process *unused = p;
266         unused = 0;
267
268 #if defined(i386_unknown_nt4_0) || \
269     defined(i386_unknown_linux2_0) || \
270     defined(sparc_sun_solaris2_4)
271
272         if(insp && p && relocatable_)
273           for(u_int i=0; i < relocatedByProcess.size(); i++)
274             if((relocatedByProcess[i])->getProcess() == p) {
275                 addArbitraryPoint(insp,p,relocatedByProcess[i]);
276                 return;
277             }
278 #endif
279     }
280
281 #if defined(i386_unknown_nt4_0) || \
282     defined(i386_unknown_linux2_0) || \
283     defined(sparc_sun_solaris2_4)
284
285     void addArbitraryPoint(instPoint*,process*,relocatedFuncInfo*);
286
287 #endif
288
289     const vector<instPoint*> &funcCalls(process *p) const {
290         if(p && relocatable_) {
291           for(u_int i=0; i < relocatedByProcess.size(); i++){
292             if((relocatedByProcess[i])->getProcess() == p) 
293                 return (relocatedByProcess[i])->funcCallSites();
294         } }
295         return calls;
296     }
297     bool isInstalled(process *p){
298         if(p && relocatable_) {
299           for(u_int i=0; i < relocatedByProcess.size(); i++){
300             if((relocatedByProcess[i])->getProcess() == p) 
301                 return (relocatedByProcess[i])->isInstalled();
302         } }
303         return false;
304     }
305     void setInstalled(process *p){
306         if(p && relocatable_) {
307           for(u_int i=0; i < relocatedByProcess.size(); i++){
308             if((relocatedByProcess[i])->getProcess() == p) 
309                 (relocatedByProcess[i])->setInstalled();
310         } }
311     }
312     bool hasNoStackFrame() const {return noStackFrame;}
313        // formerly "isLeafFunc()" but that led to confusion, since people assign two
314        // different meanings to "leaf" fns: (1) has no stack frame, (2) makes no calls.
315        // By renaming this fn, we make clear that we're returning (1), not (2).
316
317     bool isTrapFunc() {return isTrap;}
318     bool needsRelocation() {return relocatable_;}
319     void setRelocatable(bool value) { relocatable_ = value; }
320
321     
322 #ifndef BPATCH_LIBRARY
323     // Fill in <callees> vector with pointers to all other pd functions
324     //  statically determined to be called from any call sites in 
325     //  this function.
326     // Returns false if unable to fill in that information....
327     bool getStaticCallees(process *proc, vector <pd_Function *> &callees);
328 #endif
329
330 #if defined(sparc_sun_sunos4_1_3) || defined(sparc_sun_solaris2_4)   
331
332     bool checkInstPoints(const image *owner);
333     bool findInstPoints(const image *owner, Address adr, process *proc);
334     // Add a new call point to a function that will be, or currently is
335     // being relocated (if location != 0 && reloc_info != 0,  then this is
336     // called when the the function is actually being relocated
337     Address newCallPoint(Address &adr, const instruction code,
338                          const image *owner, bool &err, unsigned &id, 
339                          Address &addr, relocatedFuncInfo *reloc_info,
340                          instPoint *&point, const instPoint *&location);
341
342     bool PA_attachTailCalls(LocalAlterationSet *temp_alteration_set);
343
344     //
345     // NEW routines for function code rewrites using peephole alterations....
346     //
347     bool readFunctionCode(const image *owner, instruction *into);
348     int moveOutOfDelaySlot(int offset, instruction loadedCode[],
349           int codeSize);
350 #elif defined(mips_sgi_irix6_4)  || defined(mips_unknown_ce2_11) //ccw 29 mar 2001
351     bool    checkInstPoints();
352     Address findTarget(instPoint *p);
353     Address findBranchTarget(instPoint *p, instruction i);
354     Address findJumpTarget(instPoint *p, instruction i);
355     Address findIndirectJumpTarget(instPoint *p, instruction i);
356     void    setVectorIds();
357
358     // stack frame info
359     Address findStackFrame(const image *owner);
360     // register saves into frame
361     struct regSave_t {
362       int           slot;       // stack frame ($fp) offset of saved register
363       bool          dword;      // is register saved as 64-bit doubleword?
364       Address       insn;       // offset of insn that saves this register
365     } reg_saves[NUM_REGS];
366     // $sp-style frame (common)
367     Address         sp_mod;     // offset of insn that modifies $sp
368     vector<Address> sp_ret;     // offset of insn that restores $sp
369     int             frame_size; // stack frame size ($sp frame only)
370     // $fp-style frame (rare)
371     Address         fp_mod;     // offset of insn that modifies $fp
372     bool            uses_fp;    // does this fn use $s8 as a frame pointer?
373
374     typedef struct inactiveRange {
375        int popOffset;
376        int retOffset;
377        } InactiveFrameRange;
378
379        vector<InactiveFrameRange> inactiveRanges;
380
381 #elif defined(i386_unknown_solaris2_5) || defined(i386_unknown_nt4_0) || defined(i386_unknown_linux2_0)
382
383     void instrAroundPt(instPoint *p, instruction allInstr[], int numBefore, 
384                        int numAfter, unsigned type, int index);
385
386     int getArrayOffset(Address adr, instruction code[]);
387
388     bool isTrueCallInsn(const instruction insn);
389  
390     bool canUseExtraSlot(instPoint *&ip) const;
391
392     bool usesTrap(instPoint *&ip);
393
394 #elif defined(alpha_dec_osf4_0)
395     int             frame_size; // stack frame size
396 #endif
397
398 #if defined(sparc_sun_solaris2_4)
399     bool is_o7_live(){ return o7_live; }
400 #endif
401
402 #if defined(i386_unknown_solaris2_5) || defined(i386_unknown_nt4_0) || defined(i386_unknown_linux2_0) || defined(sparc_sun_solaris2_4)
403
404     // modifyInstPoint: change the value of the instPoint if it is wrong: 
405     // if this instPoint is from a function that was just relocated, then
406     // it may not have the correct address.  This routine finds the correct
407     // address for the instPoint
408     void modifyInstPoint(const instPoint *&location, process *proc);
409
410     bool isNearBranchInsn(const instruction insn);
411
412     bool fillInRelocInstPoints(const image *owner, process *proc,
413                                instPoint *&location, 
414                                relocatedFuncInfo *&reloc_info, Address mutatee,
415                                Address mutator, instruction oldCode[],
416                                Address newAdr, instruction newCode[],
417                                LocalAlterationSet &alteration_set);
418
419     int relocateInstructionWithFunction(bool setDisp, 
420                                         instruction *insn, 
421                                         Address origAddr, 
422                                         Address targetAddr, 
423                                         Address oldFunctionAddr, 
424                                         unsigned originalCodeSize);
425
426     int patchOffset(bool setDisp, LocalAlterationSet *alteration_set, 
427                     instruction& insn, Address adr, 
428                     Address firstAddress, unsigned originalCodeSize);
429
430     bool findAndApplyAlterations(const image *owner, 
431                                  instPoint *&location,
432                                  u_int &newAdr,
433                                  process *proc,
434                                  relocatedFuncInfo *&reloc_info, 
435                                  unsigned &size_change);
436
437     int findAlterations(const image *owner, process *proc, 
438                         instruction *&oldCode,
439                         LocalAlterationSet &normalized_alteration_set,
440                         Address &mutator, Address &mutatee);
441
442     int relocatedSizeChange(const image *owner, process *proc);
443
444     bool loadCode(const image *owner, process *proc, instruction *&oldCode, 
445                   unsigned &totalSize, Address &firstAddress);
446
447     bool expandInstPoints(const image *owner, 
448                           LocalAlterationSet *temp_alteration_set, 
449                           LocalAlterationSet &normalized_alteration_set, 
450                           Address baseAddress, Address mutator, 
451                           Address mutatee, instruction oldCode[], 
452                           unsigned numberOfInstructions);
453
454     bool PA_attachGeneralRewrites(const image *owner, 
455                                   LocalAlterationSet *temp_alteration_set, 
456                                   Address baseAddress, Address firstAddress,
457                                   instruction loadedCode[], 
458                                   unsigned numInstructions, int codeSize);
459
460
461     bool PA_attachOverlappingInstPoints(LocalAlterationSet *temp_alteration_set,
462                                         Address baseAddress,
463                                         Address firstAddress,
464                                         instruction loadedCode[], int codeSize);
465
466     bool PA_attachBranchOverlaps(LocalAlterationSet *temp_alteration_set, 
467                                  Address baseAddress, Address firstAddress,
468                                  instruction loadedCode[],
469                                  unsigned  numberOfInstructions, int codeSize);
470
471     bool discoverAlterations(LocalAlterationSet *temp_alteration_set, 
472                              LocalAlterationSet &normalized_alteration_set,
473                              Address baseAddress, Address firstAddress, 
474                              instruction originalCode[], int originalCodeSize); 
475
476     bool applyAlterations(LocalAlterationSet &normalized_alteration_set,
477                           Address mutator, Address mutatee, Address newAdr, 
478                           instruction originalCode[], 
479                           unsigned originalCodeSize, instruction newCode[]);
480
481     bool updateAlterations(LocalAlterationSet *temp_alteration_set,
482                            LocalAlterationSet &normalized_alteration_set,
483                            instruction *oldCode, 
484                            Address baseAddress, Address firstAddress,
485                            int &totalSizeChange);
486
487     bool relocateFunction(process *proc, instPoint *&location, bool &deferred);
488
489     void sorted_ips_vector(vector<instPoint*>&fill_in);
490
491     void copyInstruction(instruction &newInsn, instruction &oldInsn,  
492                                                unsigned &codeOffset);
493
494     int expandInstructions(LocalAlterationSet &alteration_set, 
495                            instruction &insn, 
496                            Address offset,
497                            instruction &newCodeInsn);
498
499     int fixRelocatedInstruction(bool setDisp, instruction *insn, 
500                                 Address origAddr, Address targetAddr);
501
502     bool branchInsideRange(instruction insn, Address branchAddress, 
503                        Address firstAddress, Address lastAddress);
504
505     bool trueCallInsideRange(instruction insn, Address callAddress, 
506                          Address firstAddress, Address lastAddress);
507
508     instPoint *find_overlap(vector<instPoint*> v, Address targetAddress);
509 #endif
510
511     void setNumInstructions(unsigned num) { numInstructions = num; }
512     unsigned getNumInstructions() { return numInstructions; }
513  
514     instruction *getInstructions() { return instructions; }
515
516
517
518 #ifndef BPATCH_LIBRARY
519     void SetFuncResource(resource *r) {
520       assert(r != NULL); 
521       funcResource = r;
522     }
523
524     string ResourceFullName() {
525       assert(funcResource); 
526       return funcResource->full_name();
527     }
528
529     bool FuncResourceSet() {
530       return (funcResource != NULL);
531     }
532 #endif
533
534   private:
535     pdmodule *file_;            /* pointer to file that defines func. */
536     instPoint *funcEntry_;      /* place to instrument entry (often not addr) */
537     vector<instPoint*> funcReturns;     /* return point(s). */
538     vector<instPoint*> calls;           /* pointer to the calls */
539     vector<instPoint*> arbitraryPoints;         /* pointer to the calls */
540 #ifndef BPATCH_LIBRARY
541     resource *funcResource;
542 #endif
543     
544     // these are for relocated functions
545     bool relocatable_;             // true if func will be relocated when instr
546
547     unsigned char *relocatedCode;  // points to copy of rewritten function    
548     unsigned char *originalCode;   // points to copy of original function
549
550     unsigned numInstructions;      // num instructions in original func
551     instruction *instructions;     // instructions that correspond to the 
552                                    // original function 
553
554     bool noStackFrame; // formerly "leaf".  True iff this fn has no stack frame.
555
556     bool isTrap;                // true if function contains a trap instruct
557     vector<relocatedFuncInfo *> relocatedByProcess; // one element per process
558
559 #if defined(sparc_sun_solaris2_4)
560     bool o7_live;
561 #endif
562 };
563
564 /* Stores source code to address in text association for modules */
565 class lineDict {
566 public:
567   lineDict() : lineMap(uiHash) { }
568   ~lineDict() { /* TODO */ }
569   void setLineAddr (unsigned line, Address addr) { lineMap[line] = addr; }
570   inline bool getLineAddr (const unsigned line, Address &adr);
571
572 private:
573   dictionary_hash<unsigned, Address> lineMap;
574 };
575
576
577 class module {
578 public:
579     module(){}
580     module(supportedLanguages lang, Address adr, string &fullNm,
581            string &fileNm): fileName_(fileNm), fullName_(fullNm), 
582                 language_(lang), addr_(adr){}
583     virtual ~module(){}
584
585     string fileName() const { return fileName_; }
586     string fullName() const { return fullName_; }
587     supportedLanguages language() const { return language_;}
588     Address addr() const { return addr_; }
589
590     virtual function_base *findFunction (const string &name) = 0;
591     virtual void define() = 0;    // defines module to paradyn
592     virtual vector<function_base *> *getFunctions() = 0;
593
594 #ifndef BPATCH_LIBRARY
595     virtual vector<function_base *> *getIncludedFunctions() = 0;
596 #endif
597
598 private:
599     string fileName_;                   // short file 
600     string fullName_;                   // full path to file 
601     supportedLanguages language_;
602     Address addr_;                      // starting address of module
603 };
604
605 class pdmodule: public module {
606 friend class image;
607 public:
608   pdmodule(supportedLanguages lang, Address adr, string &fullNm,
609            string &fileNm, image *e): module(lang,adr,fullNm,fileNm),
610 #ifndef BPATCH_LIBRARY
611     modResource(0),
612 #endif
613     exec_(e){
614     some_funcs_inited = FALSE;
615   }
616   ~pdmodule() { /* TODO */ }
617
618   void setLineAddr(unsigned line, Address addr) {
619         lines_.setLineAddr(line, addr);}
620   bool getLineAddr(unsigned line, Address &addr) { 
621        return (lines_.getLineAddr(line, addr)); }
622
623   image *exec() const { return exec_; }
624   void mapLines() { }           // line number info is not used now
625   void checkAllCallPoints();
626   void define();    // defines module to paradyn
627
628 #ifndef BPATCH_LIBRARY
629   void FillInCallGraphStatic(process *proc);
630       // fill in statically determined part of caller-callee relationship
631       //  for paradyn....
632 #endif
633
634   vector<function_base *> *getFunctions() { return (vector<function_base *>*)&funcs;} 
635   vector<function_base *> *getIncludedFunctions();
636   function_base *findFunction (const string &name);
637
638
639 private:
640 #ifndef BPATCH_LIBRARY
641   resource *modResource;
642 #endif
643   image *exec_;                      // what executable it came from 
644   lineDict lines_;
645   //  list of all found functions in module....
646   vector<pd_Function*> funcs;
647   // added as part of exclude support for statically linked objects.
648   //  mcheyny, 970928
649   //  list of non-excluded found functions in module....
650   vector<pd_Function*> some_funcs;
651   bool some_funcs_inited;
652 };
653
654
655 extern bool mdl_get_lib_constraints(vector<string> &);
656
657 void print_func_vector_by_pretty_name(string prefix,
658                                       vector<function_base *>*funcs);
659 void print_module_vector_by_short_name(string prefix,
660                                       vector<pdmodule*> *mods);
661 string getModuleName(string constraint);
662 string getFunctionName(string constraint);
663 //used by both sharedobject and pdmodule class....
664 bool filter_excluded_functions(vector<pd_Function*> all_funcs,
665     vector<pd_Function*>& some_funcs, string module_name);
666 bool function_is_excluded(pd_Function *func, string module_name);
667 bool module_is_excluded(pdmodule *module);
668
669
670 /*
671  * symbols we need to find from our RTinst library.  This is how we know
672  *   were our inst primatives got loaded as well as the data space variables
673  *   we use to put counters/timers and inst trampolines.  An array of these
674  *   is placed in the image structure.
675  *
676  */
677 class internalSym {
678 public:
679   internalSym() { }
680   internalSym(const Address adr, const string &nm) : name(nm), addr(adr) { }
681   Address getAddr() const { return addr;}
682
683 private:
684   string name;            /* name as it appears in the symbol table. */
685   Address addr;      /* absolute address of the symbol */
686 };
687
688
689 // modsByFileName
690 // modsbyFullName
691 // includedMods
692 // excludedMods
693 // allMods
694 // includedFunctions
695 // excludedFunctions
696 // instrumentableFunctions
697 // notInstruFunctions
698 // funcsByAddr
699 // funcsByPretty
700 // file_
701 // name_
702 // codeOffset_
703 // codeLen_
704 // dataOffset_
705 // dataLen_
706 // linkedFile
707 // iSymsMap
708 // allImages
709 // varsByPretty
710 // knownJumpTargets
711 // COMMENTS????
712 //  Image class contains information about statically and dynamically linked code 
713 //  belonging to a process....
714 class image {
715    friend class process;
716    friend class pd_Function;
717
718    //
719    // ****  PUBLIC MEMBER FUBCTIONS  ****
720    //
721 public:
722   static image *parseImage(const string file);
723   static image *parseImage(fileDescriptor *desc);
724
725   image(fileDescriptor *desc, bool &err);
726   ~image() { /* TODO */ }
727
728   // Check the list of symbols returned by the parser, return
729   // name/addr pair
730   bool findInternalSymbol(const string &name, const bool warn, internalSym &iSym);
731
732   // Check the list of symbols returned by the parser, return
733   // all which start with the given prefix
734   bool findInternalByPrefix(const string &prefix, vector<Symbol> &found) const;
735
736   
737   //Address findInternalAddress (const string &name, const bool warn, bool &err);
738
739   // find the named module  
740   pdmodule *findModule(const string &name, bool find_if_excluded = FALSE);
741
742   // Note to self later: find is a const operation, [] isn't, for
743   // dictionary access. If we need to make the findFuncBy* methods
744   // consts, we can move from [] to find()
745
746   // Find the vector of functions associated with a (demangled) name
747   vector <pd_Function *> *findFuncVectorByPretty(const string &name);
748   // Find a (single) function by pretty (demangled) name. Picks one if more than
749   // one exists. Probably shouldn't exist.
750   pd_Function *findFuncByPretty(const string &name);
751   // Find a function by mangled (original) name. Guaranteed unique
752   pd_Function *findFuncByMangled(const string &name);
753   // Look for the function in the non instrumentable list
754   pd_Function *findNonInstruFunc(const string &name);
755   // Look for the function in the excluded list
756   pd_Function *findExcludedFunc(const string &name);
757   // Looks only for an instrumentable, non-excluded function
758   pd_Function *findFuncByName(const string &name);
759   // Looks for the name in all lists (inc. excluded and non-instrumentable)
760   pd_Function *findOneFunctionFromAll(const string &name);
761
762   // Given an address, do an exhaustive search for that function
763   pd_Function *findFuncByAddr(const Address &addr, const process *p = 0) const;
764
765   // Break apart the above
766   pd_Function *findFuncByEntryAddr(const Address &addr, const process *p = 0) const;
767   pd_Function *findFuncByRelocAddr(const Address &addr, const process *p = 0) const;
768   pd_Function *findFuncByOrigAddr(const Address &addr, const process *p = 0) const;
769
770   void findModByAddr (const Symbol &lookUp, vector<Symbol> &mods,
771                       string &modName, Address &modAddr, 
772                       const string &defName);
773
774   // report modules to paradyn
775   void defineModules();
776
777 #ifndef BPATCH_LIBRARY
778  // report statically determinable caller-callee relationship to paradyn....
779   void FillInCallGraphStatic(process *proc);
780 #endif
781
782   bool symbolExists(const string &); /* Does the symbol exist in the image? */
783   void postProcess(const string);          /* Load .pif file */
784
785
786   void addJumpTarget(Address addr) {
787     if (!knownJumpTargets.defines(addr)) knownJumpTargets[addr] = addr; 
788   }
789
790   bool isJumpTarget(Address addr) { 
791     return knownJumpTargets.defines(addr); 
792   }
793
794
795   // data member access
796
797   string file() const {return desc_->file();}
798   string name() const { return name_;}
799   const fileDescriptor *desc() const { return desc_; }
800   Address codeOffset() { return codeOffset_;}
801   Address dataOffset() { return dataOffset_;}
802   Address dataLength() { return (dataLen_ << 2);} 
803   Address codeLength() { return (codeLen_ << 2);} 
804   const Object &getObject() const { return linkedFile; }
805
806   Object &getObjectNC() { return linkedFile; } //ccw 27 july 2000 : this is a TERRIBLE hack : 29 mar 2001
807
808   bool isDyninstRTLib() const { return is_libdyninstRT; }
809   bool isAOut() const { return is_a_out; }
810
811   inline bool isCode(const Address &where) const;
812   inline bool isData(const Address &where) const;
813   inline bool isValidAddress(const Address &where) const;
814   inline const Word get_instruction(Address adr) const;
815   inline const unsigned char *getPtrToInstruction(Address adr) const;
816
817   // Return symbol table information
818   inline bool symbol_info(const string& symbol_name, Symbol& ret);
819
820   // Called from the mdl -- lists of functions to look for
821   static void watch_functions(string& name, vector<string> *vs, bool is_lib,
822                               vector<pd_Function*> *updateDict);
823
824   // origionally return mdlNormal;....
825   // Note that (unlike name), this returns ONLY functions for which
826   // necessary instrumentation info could be found)!!!!
827   const vector<pd_Function*> &getAllFunctions();
828
829   // get all modules, including excluded ones....
830   const vector<pdmodule *> &getAllModules();
831
832 #ifndef BPATCH_LIBRARY
833   const vector<pd_Function*> &getIncludedFunctions();
834   const vector<pdmodule *> &getIncludedModules();
835 #endif 
836
837   //
838   //  ****  PUBLIC DATA MEMBERS  ****
839   //
840
841   Address get_main_call_addr() const { return main_call_addr_; }
842  
843   private:
844
845   // Call tree:
846   //
847   // AddOneFunction:
848   //    Gets/Creates a module name ("DEFAULT_MODULE")
849   //    newFunc
850   // newFunc
851   //    new pd_Function()
852   //    if (problem determining instr)
853   //      addNotInstruFunction
854   //    else
855   //      addInstruFunction
856   //        function_is_excluded (MDL exclusion via "exclude <mod>/<func>", BUT NOT "exclude <mod>)
857   // addInstruFunction
858   //   if (excluded) [from above]
859   //     add to excludedFunctions (hash)
860   //   else
861   //     add to includedFunctions
862   //     add to funcsByAddr
863   //     add to funcsByPretty (if not already in there)
864   //     add to funcsByMangled (if not already in there)
865   // addNotInstruFunction
866   //   add to notInstruFunctions (by pretty name)
867
868   // Add a function to (if excluded) excluded list, otherwise to includedFunctions,
869   // funcsByAddr, funcsByPretty, funcsByMangled
870   void addInstruFunction(pd_Function *func, pdmodule *mod,
871         const Address addr, bool excluded);
872
873   // Add a function which could not be instrumented.  Sticks it in
874   // notInstruFuncs (list)
875   void addNotInstruFunc(pd_Function *func);
876
877   // Determines if a function is instrumentable, and calls add(Not)InstruFunction
878   bool newFunc(pdmodule *, const string &name, const Address addr, 
879                const unsigned size);
880
881   bool addOneFunction(vector<Symbol> &mods,
882                       const Symbol &lookUp);
883
884   void addMultipleFunctionNames(vector<Symbol> &mods,
885                                 const Symbol &lookUp);
886
887   //
888   //  ****  PRIVATE MEMBERS FUNCTIONS  ****
889   //
890
891   // private methods for findind an excluded function by name or
892   //  address....
893   bool find_excluded_function(const string &name,
894       vector<pd_Function*> &retList);
895   pd_Function *find_excluded_function(const Address &addr);
896
897   void checkAllCallPoints();
898
899 #if 0
900   bool addInternalSymbol(const string &str, const Address symValue);
901 #endif
902   // creates the module if it does not exist
903   pdmodule *getOrCreateModule (const string &modName, const Address modAddr);
904   pdmodule *newModule(const string &name, const Address addr);
905
906   bool addAllFunctions(vector<Symbol> &mods);
907
908   bool addAllVariables();
909
910
911   //
912   //  ****  PRIVATE DATA MEMBERS  ****
913   //
914
915   fileDescriptor *desc_; /* file descriptor (includes name) */
916   string name_;         /* filename part of file, no slashes */
917
918   Address codeOffset_;
919   unsigned codeLen_;
920   Address dataOffset_;
921   unsigned dataLen_;
922
923   bool is_libdyninstRT;
924   bool is_a_out;
925   Address main_call_addr_; // address of call to main()
926
927   // data from the symbol table 
928   Object linkedFile;
929
930   //dictionary_hash <string, internalSym*> iSymsMap;   // internal RTinst symbols
931
932   // A vector of all images. Used to avoid duplicating
933   // an "image" that already exists.
934   static vector<image*> allImages;
935
936   // knownJumpTargets: the addresses in this image that are known to 
937   // be targets of jumps. It is used to check points with multiple 
938   // instructions.
939   // This is a subset of the addresses that are actually targets of jumps.
940   dictionary_hash<Address, Address> knownJumpTargets;
941
942   // list of modules which have not been excluded.
943   vector<pdmodule *> includedMods;
944   // list of excluded module.  includedMods && excludedMods
945   //  should be disjoint!!!!
946   vector<pdmodule *> excludedMods;
947   // list of all modules, should = includedMods + excludedMods;
948   // Not actually created until getAllModules called....
949   vector<pdmodule *> allMods;
950
951   // list of all functions for which necessary instrumentation data
952   //  could be found which are NOT excluded....
953   vector<pd_Function*> includedFunctions;
954   // includedFunctions + excludedFunctions (but not notInstruFunctions)....
955   vector<pd_Function*> instrumentableFunctions;
956
957
958   //
959   // Hash Tables of Functions....
960   //
961
962   // functions by address for all modules.  Only contains instrumentable
963   //  funtions.
964   dictionary_hash <Address, pd_Function*> funcsByAddr;
965   // note, a prettyName is not unique, it may map to a function appearing
966   // in several modules.  Also only contains instrumentable functions....
967   dictionary_hash <string, vector<pd_Function*>*> funcsByPretty;
968   // Hash table holding functions by mangled name.
969   // Should contain same functions as funcsByPretty....
970   dictionary_hash <string, vector<pd_Function*>*> funcsByMangled;
971   // The functions that can't be instrumented
972   // Note that notInstruFunctions holds list of functions for which
973   //  necessary instrumentation data could NOT be found....
974   dictionary_hash <string, pd_Function*> notInstruFunctions;
975   // hash table of all functions for which necessary instrumentation data
976   //  could be found which ARE excluded....
977   dictionary_hash <string, pd_Function*> excludedFunctions;
978   // TODO -- get rid of one of these
979   // Note : as of 971001 (mcheyney), these hash tables only 
980   //  hold entries in includedMods --> this implies that
981   //  it may sometimes be necessary to do a linear sort
982   //  through excludedMods if searching for a module which
983   //  was excluded....
984   dictionary_hash <string, pdmodule *> modsByFileName;
985   dictionary_hash <string, pdmodule*> modsByFullName;
986   // Variables indexed by pretty (non-mangled) name
987   dictionary_hash <string, vector<string>*> varsByPretty;
988  
989
990 };
991
992
993 #ifndef BPATCH_LIBRARY
994 // forward declarations....
995 void CallGraphSetEntryFuncCallback(string exe_name, string r);
996 void CallGraphFillDone(string exe_name);
997 void CallGraphAddProgramCallback(string exe_name);
998 #endif
999 /*
1000  * a definition of a library function that we may wish to identify.  This is
1001  *   how we describe it to the symbol table parser, not how it appears in
1002  *   the symbol table.  Library functions are placed in a pseudo module 
1003  *   named LIBRARY_MODULE. 
1004  *
1005  */
1006
1007
1008 class libraryFunc {
1009 public:
1010   libraryFunc(const string n, unsigned t) : name(n), tags(t) { }
1011   unsigned getTags() const { return tags;}
1012
1013 private:
1014   string name;
1015   unsigned tags;
1016 };
1017
1018 #ifndef BPATCH_LIBRARY
1019 // TODO -- remove this
1020 extern resource *moduleRoot;
1021 #endif
1022
1023 inline bool lineDict::getLineAddr (const unsigned line, Address &adr) {
1024   if (!lineMap.defines(line)) {
1025     return false;
1026   } else {
1027     adr = lineMap[line];
1028     return true;
1029   }
1030 }
1031
1032 inline function_base *pdmodule::findFunction (const string &name) {
1033   unsigned fsize = funcs.size();
1034   for (unsigned f=0; f<fsize; f++) {
1035     if (funcs[f]->symTabName() == name)
1036       return funcs[f];
1037     else if (funcs[f]->prettyName() == name)
1038       return funcs[f];
1039   }
1040   return NULL;
1041 }
1042
1043 inline const Word image::get_instruction(Address adr) const{
1044   // TODO remove assert
1045   // assert(isValidAddress(adr));
1046   if(!isValidAddress(adr)){
1047       // logLine("address not valid in get_instruction\n");
1048       return 0;
1049   }
1050
1051   if (isCode(adr)) {
1052     adr -= codeOffset_;
1053     adr >>= 2;
1054     const Word *inst = linkedFile.code_ptr();
1055     return (inst[adr]);
1056   } else if (isData(adr)) {
1057     adr -= dataOffset_;
1058     adr >>= 2;
1059     const Word *inst = linkedFile.data_ptr();
1060     return (inst[adr]);
1061   } else {
1062     abort();
1063     return 0;
1064   }
1065 }
1066
1067 // return a pointer to the instruction at address adr
1068 inline const unsigned char *image::getPtrToInstruction(Address adr) const {
1069   assert(isValidAddress(adr));
1070   if (isCode(adr)) {
1071     adr -= codeOffset_;
1072     const unsigned char *inst = (const unsigned char *)linkedFile.code_ptr();
1073     return (&inst[adr]);
1074   } else if (isData(adr)) {
1075     adr -= dataOffset_;
1076     const unsigned char *inst = (const unsigned char *)linkedFile.data_ptr();
1077     return (&inst[adr]);
1078   } else {
1079     abort();
1080     return 0;
1081   }
1082 }
1083
1084
1085 // Address must be in code or data range since some code may end up
1086 // in the data segment
1087 inline bool image::isValidAddress(const Address &where) const{
1088   return (isAligned(where) && (isCode(where) || isData(where)));
1089 }
1090
1091 inline bool image::isCode(const Address &where)  const{
1092   return (linkedFile.code_ptr() && 
1093           (where >= codeOffset_) && (where < (codeOffset_+(codeLen_<<2))));
1094 }
1095
1096 inline bool image::isData(const Address &where)  const{
1097    return (linkedFile.data_ptr() && 
1098           (where >= dataOffset_) && (where < (dataOffset_+(dataLen_<<2))));
1099 }
1100
1101 inline bool image::symbol_info(const string& symbol_name, Symbol &ret_sym) {
1102   if (linkedFile.get_symbol(symbol_name, ret_sym))
1103     return true;
1104
1105   if (varsByPretty.defines(symbol_name)) {
1106     vector<string> *mangledNames = varsByPretty[symbol_name];
1107     assert(mangledNames && mangledNames->size() == 1);
1108     if (linkedFile.get_symbol((*mangledNames)[0], ret_sym))
1109       return true;
1110   }
1111
1112   return false;
1113 }
1114
1115 #endif
1116