Added several calls to API (waitForStatusChange, BPatch_variableExpr
[dyninst.git] / dyninstAPI / src / process.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 /*
43  * process.h - interface to manage a process in execution. A process is a kernel
44  *   visible unit with a seperate code and data space.  It might not be
45  *   the only unit running the code, but it is only one changed when
46  *   ptrace updates are applied to the text space.
47  *
48  */
49
50 #ifndef PROCESS_H
51 #define PROCESS_H
52
53 #include <stdio.h>
54 #ifdef BPATCH_LIBRARY
55 #include "dyninstAPI_RT/h/rtinst.h"
56 #else
57 #include "rtinst/h/rtinst.h"
58 #endif
59 #include "dyninstAPI/src/util.h"
60 #include "util/h/String.h"
61 #include "util/h/vectorSet.h"
62 #include "util/h/Dictionary.h"
63 #include "util/h/Types.h"
64 #include "util/h/Timer.h"
65 #include "dyninstAPI/src/ast.h"
66 #include "dyninstAPI/src/os.h"
67 // #include "paradynd/src/main.h"
68 #include "paradynd/src/showerror.h"
69
70 #include "dyninstAPI/src/symtab.h" // internalSym
71
72 #ifdef SHM_SAMPLING
73 #include "paradynd/src/fastInferiorHeapMgr.h"
74 #include "paradynd/src/superTable.h"
75 #include "paradynd/src/hashTable.h"
76 #ifdef sparc_sun_sunos4_1_3
77 #include <kvm.h>
78 #include <sys/user.h>
79 #endif
80 #endif
81
82 #include "dyninstAPI/src/sharedobject.h"
83 #include "dyninstAPI/src/dynamiclinking.h"
84
85 extern unsigned activeProcesses; // number of active processes
86    // how about just processVec.size() instead?  At least, this should be made
87    // a (static) member vrble of class process
88
89 class resource;
90 class instPoint;
91 class instInstance;
92 class trampTemplate;
93 class pdThread;
94
95 // TODO a kludge - to prevent recursive includes
96 class image;
97
98 typedef enum { neonatal, running, stopped, exited } processState;
99 typedef enum { HEAPfree, HEAPallocated } heapStatus;
100 typedef enum { textHeap=0, dataHeap=1 } inferiorHeapType;
101 typedef vector<unsigned> unsigVecType;
102
103 const int LOAD_DYNINST_BUF_SIZE = 64;
104
105 class heapItem {
106  public:
107   heapItem() {
108     addr =0; length = 0; status = HEAPfree;
109   }
110   heapItem(const heapItem *h) {
111     addr = h->addr; length = h->length; status = h->status;
112   }
113   Address addr;
114   int length;
115   heapStatus status;
116 };
117
118 //
119 // an item on the heap that we are trying to free.
120 //
121 class disabledItem {
122  public:
123   disabledItem() { pointer = 0; }
124   disabledItem(unsigned iPointer, inferiorHeapType iHeapType, const vector<unsigVecType> &iPoints) : pointsToCheck(iPoints) {
125      pointer = iPointer;
126      whichHeap = iHeapType;
127   }
128   disabledItem(const disabledItem &src) : pointsToCheck(src.pointsToCheck) {
129     pointer = src.pointer; 
130     whichHeap = src.whichHeap;
131   }
132  ~disabledItem() {}
133   disabledItem &operator=(const disabledItem &src) {
134      if (&src == this) return *this; // the usual check for x=x
135
136      pointer = src.pointer;
137      whichHeap = src.whichHeap;
138      pointsToCheck = src.pointsToCheck;
139      return *this;
140   }
141   
142   unsigned getPointer() const {return pointer;}
143   inferiorHeapType getHeapType() const {return whichHeap;}
144   const vector<unsigVecType> &getPointsToCheck() const {return pointsToCheck;}
145   vector<unsigVecType> &getPointsToCheck() {return pointsToCheck;}
146
147  private:
148   unsigned pointer;                     // address in heap
149   inferiorHeapType whichHeap;           // which heap is it in
150   vector<unsigVecType> pointsToCheck;   // range of addrs to check
151 };
152
153
154 class inferiorHeap {
155  public:
156   inferiorHeap(): heapActive(addrHash16) {
157       freed = 0; disabledListTotalMem = 0; totalFreeMemAvailable = 0;
158 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
159       base = 0; size = 0;
160 #endif
161   }
162   inferiorHeap(const inferiorHeap &src);  // create a new heap that is a copy of src.
163                                           // used on fork.
164   dictionary_hash<unsigned, heapItem*> heapActive; // active part of heap 
165   vector<heapItem*> heapFree;           // free block of data inferior heap 
166   vector<disabledItem> disabledList;    // items waiting to be freed.
167   int disabledListTotalMem;             // total size of item waiting to free
168   int totalFreeMemAvailable;            // total free memory in the heap
169   int freed;                            // total reclaimed (over time)
170
171 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
172   Address base;                         // base of heap
173   int size;                             // size of heap
174 #endif /* BPATCH_SET_MUTATIONS_ACTIVE */
175 };
176
177 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
178 class mutationRecord {
179 public:
180     mutationRecord *next;
181     mutationRecord *prev;
182
183     Address     addr;
184     int         size;
185     void        *data;
186
187     mutationRecord(Address _addr, int _size, const void *_data);
188     ~mutationRecord();
189 };
190
191 class mutationList {
192 private:
193     mutationRecord      *head;
194     mutationRecord      *tail;
195 public:
196     mutationList() : head(NULL), tail(NULL) {};
197     ~mutationList();
198
199     void insertHead(Address addr, int size, const void *data);
200     void insertTail(Address addr, int size, const void *data);
201     mutationRecord *getHead() { return head; }
202     mutationRecord *getTail() { return tail; }
203 };
204 #endif /* BPATCH_SET_MUTATIONS_ACTIVE */
205
206 static inline unsigned ipHash(const instPoint * const &ip)
207 {
208   // assume all addresses are 4-byte aligned
209   unsigned result = (unsigned)ip;
210   result >>= 2;
211   return result;
212   // how about %'ing by a huge prime number?  Nah, x % y == x when x < y 
213   // so we don't want the number to be huge.
214 }
215
216
217 static inline unsigned instInstanceHash(instInstance * const &inst) {
218    unsigned result = (unsigned)inst;
219    result >>= 2;
220    return result; // how about %'ing by a huge prime number?
221 //  return ((unsigned)inst);
222 }
223
224 class Frame;
225
226 class process {
227  friend class ptraceKludge;
228 #ifdef BPATCH_LIBRARY
229  friend class BPatch_image;
230 #endif
231
232   //  
233   //  PUBLIC MEMBERS FUNCTIONS
234   //  
235
236  public:
237   process(int iPid, image *iImage, int iTraceLink, int iIoLink
238 #ifdef SHM_SAMPLING
239           , key_t theShmSegKey,
240           const vector<fastInferiorHeapMgr::oneHeapStats> &iShmHeapStats
241 #endif
242           );
243      // this is the "normal" ctor
244
245   process(int iPid, image *iSymbols,
246           int afterAttach, // 1 --> pause, 2 --> run, 0 --> leave as is
247           bool& success 
248 #ifdef SHM_SAMPLING
249           , key_t theShmSegKey,
250           const vector<fastInferiorHeapMgr::oneHeapStats> &iShmHeapStats
251 #endif
252           );
253      // this is the "attach" ctor
254
255   process(const process &parentProc, int iPid, int iTrace_fd
256 #ifdef SHM_SAMPLING
257           , key_t theShmSegKey,
258           void *applShmSegPtr,
259           const vector<fastInferiorHeapMgr::oneHeapStats> &iShmHeapStats
260 #endif
261           );
262      // this is the "fork" ctor
263
264 #ifdef SHM_SAMPLING
265   void registerInferiorAttachedSegs(void *inferiorAttachedAtPtr);
266      // Where the inferior attached was left undefined in the constructor;
267      // this routine fills it in (tells paradynd where, in the inferior proc's addr
268      // space, the shm seg was attached.  The attaching was done in DYNINSTinit)
269 #endif
270
271   vector<Address> walkStack(bool noPause=false);
272
273   // 
274   // getActiveFrame and readDataFromFrame are platform dependant
275   //
276   bool getActiveFrame(int *fp, int *pc);
277   bool readDataFromFrame(int currentFP, int *previousFP, int *rtn, 
278                          bool uppermost=false);
279
280
281 #ifdef SHM_SAMPLING
282   time64 getInferiorProcessCPUtime();
283      // returns user+sys time from the u or proc area of the inferior process, which in
284      // turn is presumably obtained by mmapping it (sunos) or by using a /proc ioctl
285      // to obtain it (solaris).  It is hoped that the implementation would not have to
286      // pause the inferior process (and then unpause it) in order to obtain the result,
287      // since pausing and unpausing are extremely slow (I've seen ~70ms).
288 #endif
289
290   processState status() const { return status_;}
291   string getStatusAsString() const; // useful for debug printing etc.
292
293   void continueAfterNextStop() { continueAfterNextStop_ = true; }
294   void Exited();
295   void Stopped();
296
297   bool findInternalSymbol(const string &name, bool warn, internalSym &ret_sym) const;
298
299   Address findInternalAddress(const string &name, bool warn, bool &err) const;
300
301 #ifdef BPATCH_LIBRARY
302   bool dumpImage(string outFile);
303 #else
304   bool dumpImage();
305 #endif
306
307   bool symbol_info(const string &name, Symbol &ret) {
308      assert(symbols);
309      return symbols->symbol_info(name, ret);
310   }
311   image *getImage() const {
312      assert(symbols);
313      return symbols;
314   }
315
316   // this is only used on aix so far - naim
317   vector<int> getTOCoffsetInfo() const;
318
319   bool dyninstLibAlreadyLoaded() { return hasLoadedDyninstLib; }
320   bool dyninstLibIsBeingLoaded() { return isLoadingDyninstLib; }
321   unsigned numOfActCounters_is;
322   unsigned numOfActProcTimers_is;
323   unsigned numOfActWallTimers_is; 
324   bool deferredContinueProc;
325   void updateActiveCT(bool flag, CTelementType type);
326   void cleanRPCreadyToLaunch(int mid);
327   void postRPCtoDo(AstNode *, bool noCost,
328                    void (*)(process *, void *, unsigned), void *, int);
329   bool existsRPCreadyToLaunch() const;
330   bool existsRPCinProgress() const;
331   bool launchRPCifAppropriate(bool wasRunning, bool finishingSysCall);
332      // returns true iff anything was launched.
333      // asynchronously launches iff RPCsWaitingToStart.size() > 0 AND
334      // if currRunningRPCs.size()==0 (the latter for safety)
335      // If we're gonna launch, then we'll stop the process (a necessity).
336      // Pass wasRunning as true iff you want the process  to continue after
337      // receiving the TRAP signifying completion of the RPC.
338   bool isRPCwaitingForSysCallToComplete() const {
339      return RPCs_waiting_for_syscall_to_complete;
340   }
341   void setRPCwaitingForSysCallToComplete(bool flag) {
342      RPCs_waiting_for_syscall_to_complete = flag;
343   }
344
345   bool handleTrapIfDueToRPC();
346      // look for curr PC reg value in 'trapInstrAddr' of 'currRunningRPCs'.  Return
347      // true iff found.  Also, if true is being returned, then additionally does
348      // a 'launchRPCifAppropriate' to fire off the next waiting RPC, if any.
349   bool changePC(unsigned addr);
350
351
352   void installBootstrapInst();
353   void installInstrRequests(const vector<instMapping*> &requests);
354
355
356   int getPid() const { return pid;}
357
358   bool heapIsOk(const vector<sym_data>&);
359   bool initDyninstLib();
360
361   void initInferiorHeap(bool textHeap);
362      // true --> text heap, else data heap
363
364 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
365   bool isAddrInHeap(Address addr) {
366             if ((addr >= heaps[dataHeap].base &&
367                  addr < heaps[dataHeap].base + heaps[dataHeap].size) ||
368                 (splitHeaps && addr >= heaps[textHeap].base &&
369                  addr < heaps[textHeap].base + heaps[textHeap].size))
370                 return true;
371             else
372                 return false;
373         };
374 #endif
375
376   bool writeDataSpace(void *inTracedProcess,
377                       int amount, const void *inSelf);
378   bool readDataSpace(const void *inTracedProcess, int amount,
379                      void *inSelf, bool displayErrMsg);
380
381   bool writeTextSpace(void *inTracedProcess, int amount, const void *inSelf);
382   bool writeTextWord(caddr_t inTracedProcess, int data);
383 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
384   bool readTextSpace(const void *inTracedProcess, int amount,
385                      const void *inSelf);
386 #endif
387   bool continueProc();
388 #ifdef BPATCH_LIBRARY
389   bool terminateProc() { return terminateProc_(); }
390 #endif
391   bool pause();
392
393   bool replaceFunctionCall(const instPoint *point,const function_base *newFunc);
394
395   bool dumpCore(const string coreFile);
396   bool detach(const bool paused); // why the param?
397   bool API_detach(const bool cont); // XXX Should eventually replace detach()
398   bool attach();
399
400   //  
401   //  PUBLIC DATA MEMBERS
402   //  
403
404   // the following 2 vrbles probably belong in a different class:
405   static string programName; // the name of paradynd (more specifically, its argv[0])
406   static vector<string> arg_list; // the arguments of paradynd
407   static string pdFlavor ;
408
409
410   // These member vrbles should be made private!
411   int traceLink;                /* pipe to transfer traces data over */
412   int ioLink;                   /* pipe to transfer stdout/stderr over */
413   processState status_;         /* running, stopped, etc. */
414   vector<pdThread *> threads;   /* threads belonging to this process */
415 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
416   hashTable *threadMap;         /* mapping table for threads into superTable */
417 #endif
418   bool continueAfterNextStop_;
419   // on some platforms we use one heap for text and data so textHeapFree is not
420   // used.
421   bool splitHeaps;              /* are the inferior heap split I/D ? */
422   inferiorHeap  heaps[2];       /* the heaps text and data */
423   resource *rid;                /* handle to resource for this process */
424
425   /* map an inst point to its base tramp */
426   dictionary_hash<const instPoint*, trampTemplate *> baseMap;   
427
428   // the following 3 are used in perfStream.C
429   char buffer[2048];
430   unsigned bufStart;
431   unsigned bufEnd;
432
433   time64 wallTimeLastTrampSample;
434   time64 timeLastTrampSample;
435
436   bool reachedFirstBreak; // should be renamed 'reachedInitialTRAP'
437   bool reachedVeryFirstTrap; 
438
439   //
440   //  PRIVATE DATA MEMBERS (and structure definitions)....
441   //
442  private:
443 #if defined(USES_LIBDYNINSTRT_SO)
444   unsigned char savedCodeBuffer[BYTES_TO_SAVE];
445 #endif
446   struct inferiorRPCtoDo {
447      // This structure keeps track of an inferiorRPC that we will start sometime
448      // in the (presumably near) future.  There is a different structure for RPCs
449      // which have been launched and which we're waiting to finish.  Don't confuse
450      // the two.
451
452      AstNode *action;
453      bool noCost; // if true, cost model isn't updated by generated code.
454      void (*callbackFunc)(process *, void *userData, unsigned result);
455      void *userData;
456      int mid;
457   };
458   vectorSet<inferiorRPCtoDo> RPCsWaitingToStart;
459   bool RPCs_waiting_for_syscall_to_complete;
460   void *save_exitset_ptr; // platform-specific (for now, just solaris;
461                           // it's actually a sysset_t*)
462                                                
463   struct inferiorRPCinProgress {
464      // This structure keeps track of an inferiorRPC that has been launched and
465      // for which we're waiting to complete.  Don't confuse with 'inferiorRPCtoDo',
466      // which is more of a wait queue of RPCs to start launching.
467      // Also note: It's only safe for 1 RPC to be in progress at a time.
468      // If you _really_ want to launch multiple RPCs at the same time, it's actually
469      // easy to do...just do one inferiorRPC with a sequenceNode AST! (neat, eh?)
470      // (Admittedly, that does confuse the semantics of callback functions.  So
471      // the official line remains: only 1 inferior RPC per process can be ongoing.)
472      void (*callbackFunc)(process *, void *userData, unsigned result);
473      void *userData;
474      
475      void *savedRegs; // crucial!
476
477      bool wasRunning; // were we running when we launched the inferiorRPC?
478
479      unsigned firstInstrAddr; // start location of temp tramp
480
481      unsigned stopForResultAddr;
482         // location of the TRAP or ILL which marks point where paradynd should grab the
483         // result register.  Undefined if no callback fn.
484      unsigned justAfter_stopForResultAddr; // undefined if no callback fn.
485      reg resultRegister; // undefined if no callback fn.
486
487      unsigned resultValue; // undefined until we stop-for-result, at which time we
488                            // fill this in.  The callback fn (which takes in this value)
489                            // isn't invoked until breakAddr (the final break)
490
491      unsigned breakAddr;
492         // location of the TRAP or ILL insn which marks the end of the inferiorRPC
493   };
494   vectorSet<inferiorRPCinProgress> currRunningRPCs;
495       // see para above for reason why this 'vector' can have at most 1 elem!
496
497
498   //
499   //  PRIVATE MEMBER FUNCTIONS
500   // 
501
502   // The follwing 5 routines are implemented in an arch-specific .C file
503   bool emitInferiorRPCheader(void *, unsigned &base);
504   bool emitInferiorRPCtrailer(void *, unsigned &base,
505                               unsigned &breakOffset,
506                               bool stopForResult,
507                               unsigned &stopForResultOffset,
508                               unsigned &justAfter_stopForResultOffset);
509
510   unsigned createRPCtempTramp(AstNode *action,
511                               bool noCost, bool careAboutResult,
512                               unsigned &breakAddr,
513                               unsigned &stopForResultAddr,
514                               unsigned &justAfter_stopForResultAddr,
515                               reg &resultReg);
516
517   void *getRegisters();
518      // ptrace-GETREGS and ptrace-GETFPREGS (or /proc PIOCGREG and PIOCGFPREG).
519      // Result is returned in an opaque type which is allocated with new[]
520
521   bool changePC(unsigned addr,
522                 const void *savedRegs // returned by getRegisters()
523                 );
524
525   bool executingSystemCall();
526
527   bool restoreRegisters(void *buffer);
528      // input is the opaque type returned by getRegisters()
529
530   bool set_breakpoint_for_syscall_completion();
531   unsigned read_inferiorRPC_result_register(reg);
532
533  public:
534
535 #if defined(USES_LIBDYNINSTRT_SO)
536   unsigned dyninstlib_brk_addr;
537   unsigned main_brk_addr;
538   bool dlopenDYNINSTlib();
539   bool trapDueToDyninstLib();
540   bool trapAtEntryPointOfMain();
541   bool wasCreatedViaAttach() { return createdViaAttach; }
542   void handleIfDueToDyninstLib();  
543   void insertTrapAtEntryPointOfMain();
544   void handleTrapAtEntryPointOfMain();
545 #endif
546
547   string getProcessStatus() const;
548
549   static string tryToFindExecutable(const string &progpath, int pid);
550       // os-specific implementation.  Returns empty string on failure.
551       // Otherwise, returns a full-path-name for the file.  Tries every
552       // trick to determine the full-path-name, even though "progpath" may
553       // be unspecified (empty string)
554
555   bool continueWithForwardSignal(int sig); // arch-specific implementation
556   
557   // forkProcess: this function should be called when a process we are tracing
558   // forks a child process.
559   // This function returns a new process object associated with the child.
560   // It also writes to "map" s.t. for each instInstance in the parent, we have the
561   // corresponding instInstance in the child.
562   static process *forkProcess(const process *parent, pid_t childPid,
563                               dictionary_hash<instInstance*,instInstance*> &map,
564                               int iTrace_fd
565 #ifdef SHM_SAMPLING
566                               ,key_t theKey,
567                               void *applAttachedAtPtr
568 #endif
569                               );
570
571   // get and set info. specifying if this is a dynamic executable
572   void setDynamicLinking(){ dynamiclinking = true;}
573   bool isDynamicallyLinked() { return (dynamiclinking); }
574
575   // handleIfDueToSharedObjectMapping: if a trap instruction was caused by
576   // a dlopen or dlclose event then return true
577   bool handleIfDueToSharedObjectMapping();
578
579   // handleStartProcess: this function is called when an appplication 
580   // starts executing.  It is used to insert instrumentation necessary
581   // to handle dynamic linking
582   bool handleStartProcess();
583
584   bool handleStopDueToExecEntry();
585
586 #if defined(USES_LIBDYNINSTRT_SO)
587   unsigned get_dlopen_addr() const;
588 #endif
589
590   // getSharedObjects: This routine is called before main() to get and
591   // process all shared objects that have been mapped into the process's
592   // address space
593   bool getSharedObjects();
594
595   // addASharedObject: This routine is called whenever a new shared object
596   // has been loaded by the run-time linker after the process starts running
597   // It processes the image, creates new resources
598   bool addASharedObject(shared_object &);
599
600   // return the list of dynamically linked libs
601   vector<shared_object *> *sharedObjects() { return shared_objects;  } 
602
603   // getMainFunction: returns the main function for this process
604   function_base *getMainFunction() const { return mainFunction; }
605
606   // findOneFunction: returns the function associated with function "func"
607   // and module "mod".  This routine checks both the a.out image and any
608   // shared object images for this function.  
609   // mcheyney - should return NULL if function is excluded!!!!
610   function_base *findOneFunction(resource *func,resource *mod);
611
612 #ifndef BPATCH_LIBRARY
613   // returns all the functions in the module "mod" that are not excluded by
614   // exclude_lib or exclude_func
615   // return 0 on error.
616   vector<function_base *> *getIncludedFunctions(module *mod); 
617 #endif
618
619   // findOneFunction: returns the function associated with function "func_name"
620   // This routine checks both the a.out image and any shared object images 
621   // for this function
622   function_base *findOneFunction(const string &func_name);
623
624   // findOneFunctionFromAll: returns the function associated with function "func_name"
625   // This routine checks both the a.out image and any shared object images 
626   // for this function
627   function_base *findOneFunctionFromAll(const string &func_name);
628
629   // findFunctionIn: returns the function which contains this address
630   // This routine checks both the a.out image and any shared object images 
631   // for this function
632   function_base *findFunctionIn(Address adr);
633
634   // findModule: returns the module associated with "mod_name" 
635   // this routine checks both the a.out image and any shared object 
636   // images for this module
637   // if check_excluded is true it checks to see if the module is excluded
638   // and if it is it returns 0.  If check_excluded is false it doesn't check
639   module *findModule(const string &mod_name,bool check_excluded);
640
641   // getSymbolInfo:  get symbol info of symbol associated with name n
642   // this routine starts looking a.out for symbol and then in shared objects
643   // baseAddr is set to the base address of the object containing the symbol
644   bool getSymbolInfo(const string &n, Symbol &info, Address &baseAddr) const;
645
646   // getAllFunctions: returns a vector of all functions defined in the
647   // a.out and in the shared objects
648   vector<function_base *> *getAllFunctions();
649
650   // getAllModules: returns a vector of all modules defined in the
651   // a.out and in the shared objects
652   vector<module *> *getAllModules();
653
654 #ifndef BPATCH_LIBRARY
655   // getIncludedFunctions: returns a vector of all functions defined in the
656   // a.out and in shared objects that are not excluded by an mdl option 
657   vector<function_base *> *getIncludedFunctions();
658 #endif
659
660   // getIncludedModules: returns a vector of all functions defined in the
661   // a.out and in shared objects that are  not excluded by an mdl option
662   vector<module *> *getIncludedModules();
663
664   // getBaseAddress: sets baseAddress to the base address of the 
665   // image corresponding to which.  It returns true  if image is mapped
666   // in processes address space, otherwise it returns 0
667   bool getBaseAddress(const image *which, u_int &baseAddress) const;
668
669   // findCallee: finds the function called by the instruction corresponding
670   // to the instPoint "instr". If the function call has been bound to an
671   // address, then the callee function is returned in "target" and the
672   // instPoint "callee" data member is set to pt to callee's function_base.
673   // If the function has not yet been bound, then "target" is set to the
674   // function_base associated with the name of the target function (this is
675   // obtained by the PLT and relocation entries in the image), and the instPoint
676   // callee is not set.  If the callee function cannot be found, (ex. function
677   // pointers, or other indirect calls), it returns false.
678   // Returns false on error (ex. process doesn't contain this instPoint).
679   bool findCallee(instPoint &instr, function_base *&target);
680
681   // these routines are for testing, setting, and clearing the 
682   // waiting_for_resources flag, if this flag is true a process is not 
683   // started until all outstanding resourceInfoResponses have been received
684   void setWaitingForResources(){ waiting_for_resources = true; }
685   // called by perfStream.C on SIGSTOP if there are any
686   // resource::num_outstanding_creates,
687   // and process::handleStartProcess, also if there are any
688   // resource::num_outstanding_creates.
689   void clearWaitingForResources(){ waiting_for_resources = false; }
690   bool isWaitingForResources(){ return(waiting_for_resources); }
691
692   // findSignalHandler: if signal_handler is 0, then it checks all images
693   // associtated with this process for the signal handler function.
694   // Otherwise, the signal handler function has already been found
695   void findSignalHandler();
696
697   // continueProcessIfWaiting: if the waiting_for_resources flag
698   // is set then continue the process; in any event, clear that flag
699   void continueProcessIfWaiting(){
700       if(waiting_for_resources){
701           continueProc();
702       }
703       waiting_for_resources = false;
704   }
705
706   //  wasExeced: returns true is the process did an exec...this is set
707   //  in handleExec()
708   bool wasExeced(){ return execed_;}
709
710   void handleExec();
711   bool cleanUpInstrumentation(bool wasRunning); // called on exit (also exec?)
712   bool inExec;
713
714   string execFilePath;
715
716   int getProcFileDescriptor(){ return proc_fd;}
717
718 #ifdef BPATCH_LIBRARY
719   static int waitProcs(int *status, bool block = false);
720 #else
721   static int waitProcs(int *status);
722 #endif
723   const process *getParent() const {return parent;}
724
725 #if defined(hppa1_1_hp_hpux)
726   bool freeNotOK;
727 #endif
728
729 #ifdef SHM_SAMPLING
730   key_t getShmKeyUsed() const {return inferiorHeapMgr.getShmKey();}
731   bool doMajorShmSample(time64 currWallTime);
732   bool doMinorShmSample();
733
734   const fastInferiorHeapMgr &getShmHeapMgr() const {
735      return(inferiorHeapMgr);
736   }
737
738   unsigned getShmHeapTotalNumBytes() {
739      return inferiorHeapMgr.getHeapTotalNumBytes();
740   }
741
742   void *getObsCostLowAddrInApplicSpace() {
743      void *result = inferiorHeapMgr.getObsCostAddrInApplicSpace();
744      return result;
745   }
746   unsigned *getObsCostLowAddrInParadyndSpace() {
747      unsigned *result = inferiorHeapMgr.getObsCostAddrInParadyndSpace();
748      return result;
749   }
750   void processCost(unsigned obsCostLow,
751                    time64 wallTime, time64 processTime);
752
753
754 #ifdef sparc_sun_sunos4_1_3
755    static user *tryToMapChildUarea(int pid);
756 #endif
757
758 #endif /* shm_sampling */
759
760    bool isBootstrappedYet() const {
761       return hasBootstrapped;
762    }
763    bool extractBootstrapStruct(DYNINST_bootstrapStruct *);
764    int procStopFromDYNINSTinit();
765       // returns 0 if not processed, 1 for the usual processed case (process is
766       // now paused), or 2 for the processed-but-still-running-inferiorRPC case
767
768    void handleCompletionOfDYNINSTinit(bool fromAttach);
769       // called by above routine.  Reads bs_record from applic, takes action.
770
771    static void DYNINSTinitCompletionCallback(process *, void *, unsigned);
772       // inferiorRPC callback routine.
773
774 private:
775   // Since we don't define these, 'private' makes sure they're not used:
776   process(const process &); // copy ctor
777   process &operator=(const process &); // assign oper
778
779   bool hasBootstrapped;
780      // set to true when we get callback from inferiorRPC call to DYNINSTinit
781
782   // the following two variables are used when libdyninstRT is dynamically linked
783   // which currently is done only on the Windows NT platform.
784   // On other platforms the values are undefined
785   bool hasLoadedDyninstLib; // true iff dyninstlib has been loaded already
786   bool isLoadingDyninstLib; // true iff we are currently loading dyninst lib
787   
788   // the next two variables are used when we are loading dyninstlib -- currently
789   // Windows NT only
790   // They are used by the special inferior RPC that makes the call to load the
791   // library -- we use a special inferior RPC because the regular RPC assumes
792   // that the inferior heap already exists, which is not true if libdyninstRT
793   // has not been loaded yet.
794   char savedData[LOAD_DYNINST_BUF_SIZE];
795   void *savedRegs;
796
797
798   const process *parent;        /* parent of this process */
799   image *symbols;               /* information related to the process */
800   int pid;                      /* id of this process */
801
802 #ifdef SHM_SAMPLING
803   time64 previous; // This is being used to avoid time going backwards in
804                    // getInferiorProcessCPUtime. We can't use a static variable
805                    // inside this procedure because there is one previous for
806                    // each process - naim 5/28/97
807
808   // New components of the conceptual "inferior heap"
809   fastInferiorHeapMgr inferiorHeapMgr;
810
811   superTable theSuperTable;
812
813 #ifdef sparc_sun_sunos4_1_3
814   kvm_t *kvmHandle;
815   user *childUareaPtr;
816 #endif
817
818 #endif
819
820 public:
821 #ifdef SHM_SAMPLING
822   const superTable &getTable() const {
823      return theSuperTable;
824   }
825   superTable &getTable() {
826      return theSuperTable;
827   }
828 #endif
829   trampTableEntry trampTable[TRAMPTABLESZ];
830   unsigned trampTableItems;
831
832   unsigned currentPC() {
833     int pc, fp;
834     if (hasNewPC)
835       return currentPC_;
836     else if (getActiveFrame(&fp, &pc)) {
837       currentPC_ = (unsigned) pc;
838       return currentPC_;
839     }
840     else abort();
841     return 0;
842   }
843   void setNewPC(unsigned newPC) {
844     currentPC_ = newPC;
845     hasNewPC = true;
846   }
847
848   inline int costAddr()  const { return costAddr_; }  // why an integer?
849   void getObservedCostAddr();   
850
851 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
852    bool uninstallMutations();
853    bool reinstallMutations();
854 #endif /* BPATCH_SET_MUTATIONS_ACTIVE */
855
856 private:
857   bool createdViaAttach;
858      // set in the ctor.  True iff this process was created with an attach,
859      // as opposed to being fired up by paradynd.  On fork, has the value of
860      // the parent process.  On exec, no change.
861      // This vrble is important because it tells us what to do when we exit.
862      // If we created via attach, we should (presumably) detach but not fry
863      // the application; otherwise, a kill(pid, 9) is called for.
864   // the following 2 are defined only if 'createdViaAttach' is true; action is taken
865   // on these vrbles once DYNINSTinit completes.
866
867   bool wasRunningWhenAttached;
868   bool needToContinueAfterDYNINSTinit;
869
870   unsigned currentPC_;
871   bool hasNewPC;
872
873   // for processing observed cost (see method processCost())
874   int64 cumObsCost; // in cycles
875   unsigned lastObsCostLow; // in cycles
876
877   int costAddr_;  // why an integer?
878   bool execed_;  // true if this process does an exec...set in handleExec
879
880   // deal with system differences for ptrace
881   bool writeDataSpace_(void *inTracedProcess, int amount, const void *inSelf);
882   bool readDataSpace_(const void *inTracedProcess, int amount, void *inSelf);
883
884   bool writeTextWord_(caddr_t inTracedProcess, int data);
885   bool writeTextSpace_(void *inTracedProcess, int amount, const void *inSelf);
886 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
887   bool readTextSpace_(void *inTracedProcess, int amount, const void *inSelf);
888 #endif
889   bool pause_();
890   bool continueProc_();
891 #ifdef BPATCH_LIBRARY
892   bool terminateProc_();
893 #endif
894   bool dumpCore_(const string coreFile);
895   bool detach_();
896 #ifdef BPATCH_LIBRARY
897   bool API_detach_(const bool cont); // XXX Should eventually replace detach_()
898 #endif
899   bool attach_(); // low-level attach; called by attach() (formerly OS::osAttach())
900   bool stop_(); // formerly OS::osStop
901
902   // stops a process
903   bool loopUntilStopped();
904
905   // returns true iff ok to do a ptrace; false (and prints a warning) if not
906   bool checkStatus();
907
908   int proc_fd; // file descriptor for platforms that use /proc file system.
909
910   dynamic_linking *dyn;   // platform specific dynamic linking routines & data
911
912   bool dynamiclinking;   // if true this a.out has a .dynamic section
913   vector<shared_object *> *shared_objects;  // list of dynamically linked libs
914
915   // The set of all functions and modules from the shared objects that show
916   // up on the Where axis (both  instrumentable and uninstrumentable due to 
917   // exclude_lib or exclude_func),  and all the functions from the a.out that
918   // are between DYNINSTStart and DYNINSTend
919   // TODO: these lists for a.out functions and modules should be handled the 
920   // same way as for shared object functions and modules
921   vector<function_base *> *all_functions;
922   vector<module *> *all_modules;
923
924   // these are a restricted set of functions and modules which are those  
925   // from the a.out and shared objects that are instrumentable (not excluded 
926   // through the mdl "exclude_lib" or "exclude_func" option) 
927   // "excluded" now means never able to instrument
928   vector<module *> *some_modules;  
929   vector<function_base *> *some_functions; 
930   bool waiting_for_resources;  // true if waiting for resourceInfoResponse
931   pd_Function *signal_handler;  // signal handler function (for stack walking)
932
933   function_base *mainFunction;  // the main function for this process,
934                               // this is usually, but not always, main
935                                  
936
937   // needToAddALeafFrame: returns true if the between the current frame 
938   // and the next frame there is a leaf function (this occurs when the 
939   // current frame is the signal handler)
940   bool needToAddALeafFrame(Frame current_frame, Address &leaf_pc);
941
942   // hasBeenBound: returns true if the runtime linker has bound the
943   // function symbol corresponding to the relocation entry in at the address 
944   // specified by entry and base_addr.  If it has been bound, then the callee 
945   // function is returned in "target_pdf", else it returns false. 
946   bool hasBeenBound(const relocationEntry entry, pd_Function *&target_pdf, 
947                     Address base_addr) ;
948
949   // findpdFunctionIn: returns the function which contains this address
950   // This routine checks both the a.out image and any shared object images 
951   // for this function
952   pd_Function *findpdFunctionIn(Address adr);
953
954   bool isRunning_() const;
955      // needed to initialize the 'wasRunningWhenAttached' member vrble.  Determines
956      // whether the process is running by doing a low-level OS check, not by checking
957      // member vrbles like status_.  May assume that process::attach() has already run,
958      // but can't assume anything else.  May barf with a not-yet-implemented error on a
959      // given platform if the platform doesn't yet support attaching to a running process.
960      // But there's no reason why we shouldn't be able to implement this on any platform;
961      // after all, the output from the "ps" command can be used (T --> return false,
962      // S or R --> return true, other --> return ?)
963
964 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
965    mutationList beforeMutationList, afterMutationList;
966
967    bool saveOriginalInstructions(Address addr, int size);
968    bool writeMutationList(mutationList &list);
969 #endif
970
971 #if defined(sparc_sun_solaris2_4) || defined(i386_unknown_solaris2_5) || defined(i386_unknown_linux2_0)
972    // some very useful items gathered from /proc (initialized in attach() [solaris.C],
973    // as soon as /proc fd is opened)
974    string argv0; // argv[0] of program, at the time it started up
975    string pathenv; // path env var of program, at the time it started up
976    string cwdenv; // curr working directory of program, at the time it started up
977
978 //   string fullPathToExecutable_;
979       // very useful, especially on attach (need this to parse the symbol table)
980
981  public:
982    const string &getArgv0() const {return argv0;}
983    const string &getPathEnv() const {return pathenv;}
984    const string &getCwdEnv() const {return cwdenv;}
985 #endif
986 };
987
988 process *createProcess(const string file, vector<string> argv, vector<string> envp, const string dir);
989 bool attachProcess(const string &progpath, int pid, int afterAttach
990 #ifdef BPATCH_LIBRARY
991                    , process *&newProcess
992 #endif
993                   );
994
995 void handleProcessExit(process *p, int exitStatus);
996
997 unsigned inferiorMalloc(process *proc, int size, inferiorHeapType type);
998 void inferiorFree(process *proc, unsigned pointer, inferiorHeapType type,
999                   const vector<unsigVecType> &pointsToCheck);
1000
1001 extern resource *machineResource;
1002
1003 class Frame {
1004   private:
1005     int frame_;
1006     int pc_;
1007     bool uppermostFrame;
1008
1009   public:
1010     Frame(process *);
1011        // formerly getActiveStackFrameInfo
1012
1013     Frame(int theFrame, int thePc, bool theUppermost) {
1014        frame_ = theFrame; pc_ = thePc;
1015        uppermostFrame = theUppermost;
1016     }
1017
1018     int getPC() const { return pc_; }
1019     int getFramePtr(){ return frame_;}
1020     bool isLastFrame() const { 
1021         if ((pc_ == 0)||(frame_ == 0))
1022             return(true);
1023         else 
1024             return(false); 
1025     }
1026
1027     Frame getPreviousStackFrameInfo(process *proc) const;
1028 };
1029
1030 extern vector<process *> processVec;
1031
1032 #endif