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