2 * Copyright (c) 1996 Barton P. Miller
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.
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.
18 * (for other uses, please contact us at paradyn@cs.wisc.edu)
20 * All warranties, including without limitation, any warranty of
21 * merchantability or fitness for a particular purpose, are hereby
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.
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.
42 // $Id: symtab.h,v 1.99 2001/09/07 21:15:09 tikir Exp $
48 #include <sys/types.h>
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"
64 #ifndef BPATCH_LIBRARY
65 #include "paradynd/src/resource.h"
68 #include "common/h/Types.h"
69 #include "common/h/Symbol.h"
70 #include "dyninstAPI/src/inst.h"
72 #ifndef mips_unknown_ce2_11 //ccw 8 apr 2001
73 #include "dyninstAPI/src/FunctionExpansionRecord.h"
74 class LocalAlterationSet;
77 #define RH_SEPERATOR '/'
80 * List of supported languages.
83 typedef enum { lang_Unknown,
93 /* contents of line number field if line is unknown */
94 #define UNKNOWN_LINE 0
96 #define TAG_LIB_FUNC 0x1
97 #define TAG_IO_OUT 0x2
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
105 #define DYN_MODULE "DYN_MODULE"
106 #define EXTRA_MODULE "EXTRA_MODULE"
107 #define USER_MODULE "USER_MODULE"
108 #define LIBRARY_MODULE "LIBRARY_MODULE"
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 {
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; }
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
150 class function_base {
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 */ }
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
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_;}
179 bool match(function_base *p);
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).
192 // extra debuggering info....
193 ostream & operator<<(ostream &s) const;
194 friend ostream &operator<<(ostream &os, function_base &f);
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
209 class pd_Function : public function_base {
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
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);
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();
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();
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();
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();
259 return arbitraryPoints;
261 void addArbitraryPoint(instPoint* insp,process* p){
262 if(insp) arbitraryPoints.push_back(insp);
264 // Cheesy get-rid-of-compiler-warning
268 #if defined(i386_unknown_nt4_0) || \
269 defined(i386_unknown_linux2_0) || \
270 defined(sparc_sun_solaris2_4)
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]);
281 #if defined(i386_unknown_nt4_0) || \
282 defined(i386_unknown_linux2_0) || \
283 defined(sparc_sun_solaris2_4)
285 void addArbitraryPoint(instPoint*,process*,relocatedFuncInfo*);
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();
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();
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();
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).
317 bool isTrapFunc() {return isTrap;}
318 bool needsRelocation() {return relocatable_;}
319 void setRelocatable(bool value) { relocatable_ = value; }
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
326 // Returns false if unable to fill in that information....
327 bool getStaticCallees(process *proc, vector <pd_Function *> &callees);
330 #if defined(sparc_sun_sunos4_1_3) || defined(sparc_sun_solaris2_4)
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);
342 bool PA_attachTailCalls(LocalAlterationSet *temp_alteration_set);
345 // NEW routines for function code rewrites using peephole alterations....
347 bool readFunctionCode(const image *owner, instruction *into);
348 int moveOutOfDelaySlot(int offset, instruction loadedCode[],
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);
359 Address findStackFrame(const image *owner);
360 // register saves into frame
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?
374 typedef struct inactiveRange {
377 } InactiveFrameRange;
379 vector<InactiveFrameRange> inactiveRanges;
381 #elif defined(i386_unknown_solaris2_5) || defined(i386_unknown_nt4_0) || defined(i386_unknown_linux2_0)
383 void instrAroundPt(instPoint *p, instruction allInstr[], int numBefore,
384 int numAfter, unsigned type, int index);
386 int getArrayOffset(Address adr, instruction code[]);
388 bool isTrueCallInsn(const instruction insn);
390 bool canUseExtraSlot(instPoint *&ip) const;
392 bool usesTrap(instPoint *&ip);
394 #elif defined(alpha_dec_osf4_0)
395 int frame_size; // stack frame size
398 #if defined(sparc_sun_solaris2_4)
399 bool is_o7_live(){ return o7_live; }
402 #if defined(i386_unknown_solaris2_5) || defined(i386_unknown_nt4_0) || defined(i386_unknown_linux2_0) || defined(sparc_sun_solaris2_4)
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);
410 bool isNearBranchInsn(const instruction insn);
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);
419 int relocateInstructionWithFunction(bool setDisp,
423 Address oldFunctionAddr,
424 unsigned originalCodeSize);
426 int patchOffset(bool setDisp, LocalAlterationSet *alteration_set,
427 instruction& insn, Address adr,
428 Address firstAddress, unsigned originalCodeSize);
430 bool findAndApplyAlterations(const image *owner,
431 instPoint *&location,
434 relocatedFuncInfo *&reloc_info,
435 unsigned &size_change);
437 int findAlterations(const image *owner, process *proc,
438 instruction *&oldCode,
439 LocalAlterationSet &normalized_alteration_set,
440 Address &mutator, Address &mutatee);
442 int relocatedSizeChange(const image *owner, process *proc);
444 bool loadCode(const image *owner, process *proc, instruction *&oldCode,
445 unsigned &totalSize, Address &firstAddress);
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);
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);
461 bool PA_attachOverlappingInstPoints(LocalAlterationSet *temp_alteration_set,
463 Address firstAddress,
464 instruction loadedCode[], int codeSize);
466 bool PA_attachBranchOverlaps(LocalAlterationSet *temp_alteration_set,
467 Address baseAddress, Address firstAddress,
468 instruction loadedCode[],
469 unsigned numberOfInstructions, int codeSize);
471 bool discoverAlterations(LocalAlterationSet *temp_alteration_set,
472 LocalAlterationSet &normalized_alteration_set,
473 Address baseAddress, Address firstAddress,
474 instruction originalCode[], int originalCodeSize);
476 bool applyAlterations(LocalAlterationSet &normalized_alteration_set,
477 Address mutator, Address mutatee, Address newAdr,
478 instruction originalCode[],
479 unsigned originalCodeSize, instruction newCode[]);
481 bool updateAlterations(LocalAlterationSet *temp_alteration_set,
482 LocalAlterationSet &normalized_alteration_set,
483 instruction *oldCode,
484 Address baseAddress, Address firstAddress,
485 int &totalSizeChange);
487 bool relocateFunction(process *proc, instPoint *&location, bool &deferred);
489 void sorted_ips_vector(vector<instPoint*>&fill_in);
491 void copyInstruction(instruction &newInsn, instruction &oldInsn,
492 unsigned &codeOffset);
494 int expandInstructions(LocalAlterationSet &alteration_set,
497 instruction &newCodeInsn);
499 int fixRelocatedInstruction(bool setDisp, instruction *insn,
500 Address origAddr, Address targetAddr);
502 bool branchInsideRange(instruction insn, Address branchAddress,
503 Address firstAddress, Address lastAddress);
505 bool trueCallInsideRange(instruction insn, Address callAddress,
506 Address firstAddress, Address lastAddress);
508 instPoint *find_overlap(vector<instPoint*> v, Address targetAddress);
511 void setNumInstructions(unsigned num) { numInstructions = num; }
512 unsigned getNumInstructions() { return numInstructions; }
514 instruction *getInstructions() { return instructions; }
518 #ifndef BPATCH_LIBRARY
519 void SetFuncResource(resource *r) {
524 string ResourceFullName() {
525 assert(funcResource);
526 return funcResource->full_name();
529 bool FuncResourceSet() {
530 return (funcResource != NULL);
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;
544 // these are for relocated functions
545 bool relocatable_; // true if func will be relocated when instr
547 unsigned char *relocatedCode; // points to copy of rewritten function
548 unsigned char *originalCode; // points to copy of original function
550 unsigned numInstructions; // num instructions in original func
551 instruction *instructions; // instructions that correspond to the
554 bool noStackFrame; // formerly "leaf". True iff this fn has no stack frame.
556 bool isTrap; // true if function contains a trap instruct
557 vector<relocatedFuncInfo *> relocatedByProcess; // one element per process
559 #if defined(sparc_sun_solaris2_4)
564 /* Stores source code to address in text association for modules */
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);
573 dictionary_hash<unsigned, Address> lineMap;
580 module(supportedLanguages lang, Address adr, string &fullNm,
581 string &fileNm): fileName_(fileNm), fullName_(fullNm),
582 language_(lang), addr_(adr){}
585 string fileName() const { return fileName_; }
586 string fullName() const { return fullName_; }
587 supportedLanguages language() const { return language_;}
588 Address addr() const { return addr_; }
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;
594 #ifndef BPATCH_LIBRARY
595 virtual vector<function_base *> *getIncludedFunctions() = 0;
599 string fileName_; // short file
600 string fullName_; // full path to file
601 supportedLanguages language_;
602 Address addr_; // starting address of module
605 class pdmodule: public module {
608 pdmodule(supportedLanguages lang, Address adr, string &fullNm,
609 string &fileNm, image *e): module(lang,adr,fullNm,fileNm),
610 #ifndef BPATCH_LIBRARY
614 some_funcs_inited = FALSE;
616 ~pdmodule() { /* TODO */ }
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)); }
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
628 #ifndef BPATCH_LIBRARY
629 void FillInCallGraphStatic(process *proc);
630 // fill in statically determined part of caller-callee relationship
634 vector<function_base *> *getFunctions() { return (vector<function_base *>*)&funcs;}
635 vector<function_base *> *getIncludedFunctions();
636 function_base *findFunction (const string &name);
640 #ifndef BPATCH_LIBRARY
641 resource *modResource;
643 image *exec_; // what executable it came from
645 // list of all found functions in module....
646 vector<pd_Function*> funcs;
647 // added as part of exclude support for statically linked objects.
649 // list of non-excluded found functions in module....
650 vector<pd_Function*> some_funcs;
651 bool some_funcs_inited;
655 extern bool mdl_get_lib_constraints(vector<string> &);
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);
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.
680 internalSym(const Address adr, const string &nm) : name(nm), addr(adr) { }
681 Address getAddr() const { return addr;}
684 string name; /* name as it appears in the symbol table. */
685 Address addr; /* absolute address of the symbol */
696 // instrumentableFunctions
697 // notInstruFunctions
712 // Image class contains information about statically and dynamically linked code
713 // belonging to a process....
715 friend class process;
716 friend class pd_Function;
719 // **** PUBLIC MEMBER FUBCTIONS ****
722 static image *parseImage(const string file);
723 static image *parseImage(fileDescriptor *desc);
725 image(fileDescriptor *desc, bool &err);
726 ~image() { /* TODO */ }
728 // Check the list of symbols returned by the parser, return
730 bool findInternalSymbol(const string &name, const bool warn, internalSym &iSym);
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;
737 //Address findInternalAddress (const string &name, const bool warn, bool &err);
739 // find the named module
740 pdmodule *findModule(const string &name, bool find_if_excluded = FALSE);
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()
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);
762 // Given an address, do an exhaustive search for that function
763 pd_Function *findFuncByAddr(const Address &addr, const process *p = 0) const;
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;
770 void findModByAddr (const Symbol &lookUp, vector<Symbol> &mods,
771 string &modName, Address &modAddr,
772 const string &defName);
774 // report modules to paradyn
775 void defineModules();
777 #ifndef BPATCH_LIBRARY
778 // report statically determinable caller-callee relationship to paradyn....
779 void FillInCallGraphStatic(process *proc);
782 bool symbolExists(const string &); /* Does the symbol exist in the image? */
783 void postProcess(const string); /* Load .pif file */
786 void addJumpTarget(Address addr) {
787 if (!knownJumpTargets.defines(addr)) knownJumpTargets[addr] = addr;
790 bool isJumpTarget(Address addr) {
791 return knownJumpTargets.defines(addr);
795 // data member access
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; }
806 Object &getObjectNC() { return linkedFile; } //ccw 27 july 2000 : this is a TERRIBLE hack : 29 mar 2001
808 bool isDyninstRTLib() const { return is_libdyninstRT; }
809 bool isAOut() const { return is_a_out; }
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;
817 // Return symbol table information
818 inline bool symbol_info(const string& symbol_name, Symbol& ret);
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);
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();
829 // get all modules, including excluded ones....
830 const vector<pdmodule *> &getAllModules();
832 #ifndef BPATCH_LIBRARY
833 const vector<pd_Function*> &getIncludedFunctions();
834 const vector<pdmodule *> &getIncludedModules();
838 // **** PUBLIC DATA MEMBERS ****
841 Address get_main_call_addr() const { return main_call_addr_; }
848 // Gets/Creates a module name ("DEFAULT_MODULE")
852 // if (problem determining instr)
853 // addNotInstruFunction
856 // function_is_excluded (MDL exclusion via "exclude <mod>/<func>", BUT NOT "exclude <mod>)
858 // if (excluded) [from above]
859 // add to excludedFunctions (hash)
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)
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);
873 // Add a function which could not be instrumented. Sticks it in
874 // notInstruFuncs (list)
875 void addNotInstruFunc(pd_Function *func);
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);
881 bool addOneFunction(vector<Symbol> &mods,
882 const Symbol &lookUp);
884 void addMultipleFunctionNames(vector<Symbol> &mods,
885 const Symbol &lookUp);
888 // **** PRIVATE MEMBERS FUNCTIONS ****
891 // private methods for findind an excluded function by name or
893 bool find_excluded_function(const string &name,
894 vector<pd_Function*> &retList);
895 pd_Function *find_excluded_function(const Address &addr);
897 void checkAllCallPoints();
900 bool addInternalSymbol(const string &str, const Address symValue);
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);
906 bool addAllFunctions(vector<Symbol> &mods);
908 bool addAllVariables();
912 // **** PRIVATE DATA MEMBERS ****
915 fileDescriptor *desc_; /* file descriptor (includes name) */
916 string name_; /* filename part of file, no slashes */
923 bool is_libdyninstRT;
925 Address main_call_addr_; // address of call to main()
927 // data from the symbol table
930 //dictionary_hash <string, internalSym*> iSymsMap; // internal RTinst symbols
932 // A vector of all images. Used to avoid duplicating
933 // an "image" that already exists.
934 static vector<image*> allImages;
936 // knownJumpTargets: the addresses in this image that are known to
937 // be targets of jumps. It is used to check points with multiple
939 // This is a subset of the addresses that are actually targets of jumps.
940 dictionary_hash<Address, Address> knownJumpTargets;
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;
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;
959 // Hash Tables of Functions....
962 // functions by address for all modules. Only contains instrumentable
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
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;
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);
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.
1010 libraryFunc(const string n, unsigned t) : name(n), tags(t) { }
1011 unsigned getTags() const { return tags;}
1018 #ifndef BPATCH_LIBRARY
1019 // TODO -- remove this
1020 extern resource *moduleRoot;
1023 inline bool lineDict::getLineAddr (const unsigned line, Address &adr) {
1024 if (!lineMap.defines(line)) {
1027 adr = lineMap[line];
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)
1037 else if (funcs[f]->prettyName() == name)
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");
1054 const Word *inst = linkedFile.code_ptr();
1056 } else if (isData(adr)) {
1059 const Word *inst = linkedFile.data_ptr();
1067 // return a pointer to the instruction at address adr
1068 inline const unsigned char *image::getPtrToInstruction(Address adr) const {
1069 assert(isValidAddress(adr));
1072 const unsigned char *inst = (const unsigned char *)linkedFile.code_ptr();
1073 return (&inst[adr]);
1074 } else if (isData(adr)) {
1076 const unsigned char *inst = (const unsigned char *)linkedFile.data_ptr();
1077 return (&inst[adr]);
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)));
1091 inline bool image::isCode(const Address &where) const{
1092 return (linkedFile.code_ptr() &&
1093 (where >= codeOffset_) && (where < (codeOffset_+(codeLen_<<2))));
1096 inline bool image::isData(const Address &where) const{
1097 return (linkedFile.data_ptr() &&
1098 (where >= dataOffset_) && (where < (dataOffset_+(dataLen_<<2))));
1101 inline bool image::symbol_info(const string& symbol_name, Symbol &ret_sym) {
1102 if (linkedFile.get_symbol(symbol_name, ret_sym))
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))