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