changed the way we are getting shared objects on Solaris platforms. We are no
[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 "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 "ast.h"
62 #include "os.h"
63 #include "main.h"
64 #include "dyninstRPC.xdr.h"
65 #include "showerror.h"
66
67 #include "symtab.h" // internalSym
68
69 #ifdef SHM_SAMPLING
70 #include "fastInferiorHeapMgr.h"
71 #include "fastInferiorHeap.h"
72 #include "fastInferiorHeapHKs.h"
73 #ifdef sparc_sun_sunos4_1_3
74 #include <kvm.h>
75 #include <sys/user.h>
76 #endif
77 #endif
78
79 #include "sharedobject.h"
80 #include "dynamiclinking.h"
81
82 extern unsigned activeProcesses; // number of active processes
83
84 class resource;
85 class instPoint;
86 class instInstance;
87 class trampTemplate;
88
89 // TODO a kludge - to prevent recursive includes
90 class image;
91
92 typedef enum { neonatal, running, stopped, exited } processState;
93 typedef enum { HEAPfree, HEAPallocated } heapStatus;
94 typedef enum { textHeap=0, dataHeap=1 } inferiorHeapType;
95 typedef vector<unsigned> unsigVecType;
96
97 class heapItem {
98  public:
99   heapItem() {
100     addr =0; length = 0; status = HEAPfree;
101   }
102   heapItem(const heapItem *h) {
103     addr = h->addr; length = h->length; status = h->status;
104   }
105   Address addr;
106   int length;
107   heapStatus status;
108 };
109
110 //
111 // an item on the heap that we are trying to free.
112 //
113 class disabledItem {
114  public:
115   disabledItem() { pointer = 0; }
116   disabledItem(unsigned iPointer, inferiorHeapType iHeapType, const vector<unsigVecType> &iPoints) : pointsToCheck(iPoints) {
117      pointer = iPointer;
118      whichHeap = iHeapType;
119   }
120   disabledItem(const disabledItem &src) : pointsToCheck(src.pointsToCheck) {
121     pointer = src.pointer; 
122     whichHeap = src.whichHeap;
123   }
124  ~disabledItem() {}
125   disabledItem &operator=(const disabledItem &src) {
126      if (&src == this) return *this; // the usual check for x=x
127
128      pointer = src.pointer;
129      whichHeap = src.whichHeap;
130      pointsToCheck = src.pointsToCheck;
131      return *this;
132   }
133   
134   unsigned getPointer() const {return pointer;}
135   inferiorHeapType getHeapType() const {return whichHeap;}
136   const vector<unsigVecType> &getPointsToCheck() const {return pointsToCheck;}
137   vector<unsigVecType> &getPointsToCheck() {return pointsToCheck;}
138
139  private:
140   unsigned pointer;                     // address in heap
141   inferiorHeapType whichHeap;           // which heap is it in
142   vector<unsigVecType> pointsToCheck;   // range of addrs to check
143 };
144
145
146 class inferiorHeap {
147  public:
148   inferiorHeap(): heapActive(addrHash16) {
149       freed = 0; disabledListTotalMem = 0; totalFreeMemAvailable = 0;
150   }
151   inferiorHeap(const inferiorHeap &src);  // create a new heap that is a copy of src.
152                                           // used on fork.
153   dictionary_hash<unsigned, heapItem*> heapActive; // active part of heap 
154   vector<heapItem*> heapFree;           // free block of data inferior heap 
155   vector<disabledItem> disabledList;    // items waiting to be freed.
156   int disabledListTotalMem;             // total size of item waiting to free
157   int totalFreeMemAvailable;            // total free memory in the heap
158   int freed;                            // total reclaimed (over time)
159 };
160
161
162 //
163 // read a C/C++ book to find out the difference
164 // between:
165 //
166 // (const T *) and (T * const)
167 //
168 static inline unsigned ipHash(instPoint * const &ip) {
169    // assume all addresses are 4-byte aligned
170    unsigned result = (unsigned)ip;
171    result >>= 2;
172    return result;  // how about %'ing by a huge prime number?
173 //  return ((unsigned)ip);
174 }
175
176 static inline unsigned instInstanceHash(instInstance * const &inst) {
177    unsigned result = (unsigned)inst;
178    result >>= 2;
179    return result; // how about %'ing by a huge prime number?
180 //  return ((unsigned)inst);
181 }
182
183 class Frame;
184
185 class process {
186  friend class ptraceKludge;
187
188  public:
189   process(int iPid, image *iImage, int iTraceLink, int iIoLink
190 #ifdef SHM_SAMPLING
191           , key_t theShmSegKey,
192           const vector<fastInferiorHeapMgr::oneHeapStats> &iShmHeapStats
193 #endif
194           );
195      // this is the "normal" ctor
196
197   process(const process &parentProc, int iPid
198 #ifdef SHM_SAMPLING
199           , key_t theShmSegKey,
200           void *applShmSegPtr,
201           const vector<fastInferiorHeapMgr::oneHeapStats> &iShmHeapStats
202 #endif
203           , bool childHasInstrumentation = true
204           );
205      // this is the "fork" ctor
206
207 #ifdef SHM_SAMPLING
208   void registerInferiorAttachedSegs(void *inferiorAttachedAtPtr);
209      // Where the inferior attached was left undefined in the constructor;
210      // this routine fills it in (tells paradynd where, in the inferior proc's addr
211      // space, the shm seg was attached.  The attaching was done in DYNINSTinit)
212 #endif
213
214   vector<Address> walkStack(bool noPause=false);
215
216   // 
217   // getActiveFrame and readDataFromFrame are platform dependant
218   //
219   bool getActiveFrame(int *fp, int *pc);
220   bool readDataFromFrame(int currentFP, int *previousFP, int *rtn, 
221                          bool uppermost=false);
222
223
224 #ifdef SHM_SAMPLING
225   unsigned long long getInferiorProcessCPUtime() const;
226      // returns user+sys time from the u or proc area of the inferior process, which in
227      // turn is presumably obtained by mmapping it (sunos) or by using a /proc ioctl
228      // to obtain it (solaris).  It is hoped that the implementation would not have to
229      // pause the inferior process (and then unpause it) in order to obtain the result,
230      // since pausing and unpausing are extremely slow (I've seen ~70ms).
231 #endif
232
233   processState status() const { return status_;}
234   inline void Exited();
235   inline void Stopped();
236
237   static string programName;
238   static vector<string> arg_list;
239
240   internalSym *findInternalSymbol(const string &name, bool warn) {
241      assert(symbols);
242      return symbols->findInternalSymbol(name, warn);
243   }
244   Address findInternalAddress(const string &name, bool warn, bool &err) const {
245      assert(symbols);
246      return symbols->findInternalAddress(name, warn, err);
247   }
248
249   bool dumpImage();
250
251   bool symbol_info(const string &name, Symbol &ret) {
252      assert(symbols);
253      return symbols->symbol_info(name, ret);
254   }
255   image *getImage() const {
256      assert(symbols);
257      return symbols;
258   }
259
260  private:
261   struct inferiorRPCtoDo {
262      // This structure keeps track of an inferiorRPC that we will start sometime
263      // in the (presumably near) future.  There is a different structure for RPCs
264      // which have been launched and which we're waiting to finish.  Don't confuse
265      // the two.
266
267      AstNode *action;
268      bool noCost; // if true, cost model isn't updated by generated code.
269      void (*callbackFunc)(process *, void *userData);
270      void *userData;
271   };
272   vectorSet<inferiorRPCtoDo> RPCsWaitingToStart;
273
274   struct inferiorRPCinProgress {
275      // This structure keeps track of an inferiorRPC that has been launched and
276      // for which we're waiting to complete.  Don't confuse with 'inferiorRPCtoDo',
277      // which is more of a wait queue of RPCs to start launching.
278      // Also note: It's only safe for 1 RPC to be in progress at a time.
279      // If you _really_ want to launch multiple RPCs at the same time, it's actually
280      // easy to do...just do one inferiorRPC with a sequenceNode AST! (neat, eh?)
281      // (Admittedly, that does confuse the semantics of callback functions.  So
282      // the official line remains: only 1 inferior RPC per process can be ongoing.)
283      void (*callbackFunc)(process *, void *userData);
284      void *userData;
285      
286      void *savedRegs; // crucial!
287
288      bool wasRunning;
289
290      unsigned firstInstrAddr; // location of temp tramp
291      unsigned firstPossibleBreakAddr, lastPossibleBreakAddr;
292   };
293   vectorSet<inferiorRPCinProgress> currRunningRPCs;
294       // see para above for reason why this 'vector' can have at most 1 elem!
295
296  public:
297   void postRPCtoDo(AstNode *, bool noCost, void (*)(process *, void *), void *);
298   bool existsRPCreadyToLaunch() const;
299   bool existsRPCinProgress() const;
300   bool launchRPCifAppropriate(bool wasRunning);
301      // returns true iff anything was launched.
302      // asynchronously launches iff RPCsWaitingToStart.size() > 0 AND
303      // if currRunningRPCs.size()==0 (the latter for safety)
304      // If we're gonna launch, then we'll stop the process (a necessity).
305      // Pass wasRunning as true iff you want the process  to continue after
306      // receiving the TRAP signifying completion of the RPC.
307
308   bool handleTrapIfDueToRPC();
309      // look for curr PC reg value in 'trapInstrAddr' of 'currRunningRPCs'.  Return
310      // true iff found.  Also, if true is being returned, then additionally does
311      // a 'launchRPCifAppropriate' to fire off the next waiting RPC, if any.
312
313  private:
314   // The follwing 2 routines are implemented in an arch-specific .C file
315   bool emitInferiorRPCheader(void *, unsigned &base);
316   bool emitInferiorRPCtrailer(void *, unsigned &base,
317                               unsigned &firstPossibBreakOffset,
318                               unsigned &lastPossibBreakOffset);
319
320   unsigned createRPCtempTramp(AstNode *action,
321                               bool noCost,
322                               unsigned &firstPossibBreakAddr,
323                               unsigned &lastPossibleBreakAddr);
324
325   // The parameter syscall is noly used for hpux platform right now
326   void *getRegisters(bool &syscall);
327      // ptrace-GETREGS and ptrace-GETFPREGS.  Result is returned in an opaque type
328      // which is allocated with new[]
329   bool changePC(unsigned addr,
330                 void *savedRegs // returned by getRegisters()
331                 );
332   bool restoreRegisters(void *buffer);
333
334  public:
335   // These member vrbles should be made private!
336   int traceLink;                /* pipe to transfer traces data over */
337   int ioLink;                   /* pipe to transfer stdout/stderr over */
338   processState status_;         /* running, stopped, etc. */
339   // on some platforms we use one heap for text and data so textHeapFree is not
340   // used.
341   bool splitHeaps;              /* are the inferior heap split I/D ? */
342   inferiorHeap  heaps[2];       /* the heaps text and data */
343   resource *rid;                /* handle to resource for this process */
344
345   /* map and inst point to its base tramp */
346   dictionary_hash<const instPoint*, trampTemplate *> baseMap;   
347
348   // the following 3 are used in perfStream.C
349   char buffer[2048];
350   unsigned bufStart;
351   unsigned bufEnd;
352
353   time64 wallTimeLastTrampSample;
354   time64 timeLastTrampSample;
355
356   int reachedFirstBreak;
357
358   int getPid() const { return pid;}
359
360   void initInferiorHeap(bool textHeap);
361      // true --> text heap, else data heap
362
363   bool writeDataSpace(void *inTracedProcess,
364                       int amount, const void *inSelf);
365   bool readDataSpace(const void *inTracedProcess, int amount,
366                      void *inSelf, bool displayErrMsg);
367
368   bool writeTextSpace(void *inTracedProcess, int amount, const void *inSelf);
369   bool writeTextWord(caddr_t inTracedProcess, int data);
370   bool continueProc();
371   bool pause();
372
373   inline bool dumpCore(const string coreFile);
374   bool detach(const bool paused);
375   bool attach();
376   string getProcessStatus() const;
377
378   bool continueWithForwardSignal(int sig); // arch-specific implementation
379   
380   // instInstanceMapping is used when a process we are tracing forks a child 
381   // process.
382   // The child will have a copy of all instrumentation in the parent.
383   // instInstanceMapping is a mapping of each instInstance of the parent to the
384   // corresponding instInstance of the child.
385   dictionary_hash<instInstance *, instInstance *>instInstanceMapping;
386
387   // forkProcess: this function should be called when a process we are tracing
388   // forks a child process.
389   // This function returns a new process object associated with the child.
390
391   static process *forkProcess(const process *parent, pid_t childPid
392 #ifdef SHM_SAMPLING
393                               ,key_t theKey,
394                               void *applAttachedAtPtr
395 #endif
396                               , bool childHasInstrumentation = true
397                               );
398
399   // get and set info. specifying if this is a dynamic executable
400   void setDynamicLinking(){ dynamiclinking = true;}
401   bool isDynamicallyLinked() { return (dynamiclinking); }
402
403   bool isInHandleStart() { return (inhandlestart); }
404   void setInHandleStart() { inhandlestart = true; }
405   void clearInHandleStart() { inhandlestart = false; }
406
407   // handleStartProcess: this function is called when an appplication 
408   // starts executing.  It is used to insert instrumentation necessary
409   // to handle dynamic linking
410   static bool handleStartProcess(process *pid);
411
412   // findDynamicLinkingInfo: This routine is called on exit point of 
413   // of the exec system call. It checks if the a.out is dynamically linked,
414   // and if so, it inserts any initial instrumentation that is necessary
415   // for collecting run-time linking info.
416   // bool findDynamicLinkingInfo();
417
418   // getSharedObjects: This routine is called before main() to get and
419   // process all shared objects that have been mapped into the process's
420   // address space
421   bool getSharedObjects();
422
423   // addASharedObject: This routine is called whenever a new shared object
424   // has been loaded by the run-time linker after the process starts running
425   // It processes the image, creates new resources
426   bool addASharedObject(shared_object &);
427
428   // findOneFunction: returns the function associated with function "func"
429   // and module "mod".  This routine checks both the a.out image and any
430   // shared object images for this function
431   pdFunction *findOneFunction(resource *func,resource *mod);
432
433   // findOneFunction: returns the function associated with function "func_name"
434   // This routine checks both the a.out image and any shared object images 
435   // for this function
436   pdFunction *findOneFunction(const string &func_name);
437
438   // findFunctionIn: returns the function which contains this address
439   // This routine checks both the a.out image and any shared object images 
440   // for this function
441   pdFunction *findFunctionIn(Address adr);
442
443   // findModule: returns the module associated with "mod_name" 
444   // this routine checks both the a.out image and any shared object 
445   // images for this module
446   module *findModule(const string &mod_name);
447
448   // getSymbolInfo:  get symbol info of symbol associated with name n
449   // this routine starts looking a.out for symbol and then in shared objects
450   bool getSymbolInfo(string &n, Symbol &info);
451
452   // getAllFunctions: returns a vector of all functions defined in the
453   // a.out and in the shared objects
454   vector<pdFunction *> *getAllFunctions();
455
456   // getAllModules: returns a vector of all modules defined in the
457   // a.out and in the shared objects
458   vector<module *> *getAllModules();
459
460   // getIncludedFunctions: returns a vector of all functions defined in the
461   // a.out and in shared objects that are not excluded by an mdl option 
462   vector<pdFunction *> *getIncludedFunctions();
463
464   // getIncludedModules: returns a vector of all functions defined in the
465   // a.out and in shared objects that are  not excluded by an mdl option
466   vector<module *> *getIncludedModules();
467
468   // getBaseAddress: sets baseAddress to the base address of the 
469   // image corresponding to which.  It returns true  if image is mapped
470   // in processes address space, otherwise it returns 0
471   bool getBaseAddress(const image *which, u_int &baseAddress);
472
473   // these routines are for testing, setting, and clearing the 
474   // waiting_for_resources flag, if this flag is true a process is not 
475   // started until all outstanding resourceInfoResponses have been received
476   void setWaitingForResources(){ waiting_for_resources = true; }
477   // called by perfStream.C on SIGSTOP if there are any
478   // resource::num_outstanding_creates,
479   // and process::handleStartProcess, also if there are any
480   // resource::num_outstanding_creates.
481   void clearWaitingForResources(){ waiting_for_resources = false; }
482   bool isWaitingForResources(){ return(waiting_for_resources); }
483
484   // findSignalHandler: if signal_handler is 0, then it checks all images
485   // associtated with this process for the signal handler function.
486   // Otherwise, the signal handler function has already been found
487   void findSignalHandler();
488
489   // continueProcessIfWaiting: if the waiting_for_resources flag
490   // is set then continue the process
491   void continueProcessIfWaiting(){
492       if(waiting_for_resources){
493           continueProc();
494       }
495       waiting_for_resources = false;
496   }
497
498   //  wasExeced: returns true is the process did an exec...this is set
499   //  in handleExec()
500   bool wasExeced(){ return execed_;}
501
502   //  receivedMysteryTrap: returns true if paradynd has received a SIGTRAP 
503   //  from this process before it receives a trace record telling it what 
504   //  the SIGTRAP is for (this is a kludge to get rid of a race condition
505   //  that can occur when a process does an exec).
506   bool  receivedMysteryTrap(){ return mysteryTrap_;}
507   void  setMysteryTrap(){ mysteryTrap_ = true;}
508   void  clearMysteryTrap(){ mysteryTrap_ = false;}
509
510   void handleExec();
511   bool cleanUpInstrumentation(bool wasRunning);
512   bool inExec;
513   string execFilePath;
514
515   int getProcFileDescriptor(){ return proc_fd;}
516
517   // attachToProcess: attach to an already running process, this routine sets
518   // up the connection to the process, creates a shared memory segment, parses
519   // the executable's image, creates a new process object, and processes
520   // shared objects.  It returns 0 on error.
521   static process *attachToProcess(int pid,string file_name);
522
523   static int waitProcs(int *status);
524   const process *getParent() const {return parent;}
525
526 #if defined(hppa1_1_hp_hpux)
527   bool freeNotOK;
528 #endif
529
530 #ifdef SHM_SAMPLING
531   key_t getShmKeyUsed() const {return inferiorHeapMgr.getShmKey();}
532   bool doMajorShmSample(unsigned long long currWallTime);
533   bool doMinorShmSample();
534
535   const fastInferiorHeap<intCounterHK, intCounter> &getInferiorIntCounters() const {
536      return inferiorIntCounters;
537   }
538   const fastInferiorHeap<wallTimerHK, tTimer> &getInferiorWallTimers() const {
539      return inferiorWallTimers;
540   }
541   const fastInferiorHeap<processTimerHK, tTimer> &getInferiorProcessTimers() const {
542      return inferiorProcessTimers;
543   }
544
545   fastInferiorHeap<intCounterHK, intCounter> &getInferiorIntCounters() {
546      return inferiorIntCounters;
547   }
548   fastInferiorHeap<wallTimerHK, tTimer> &getInferiorWallTimers() {
549      return inferiorWallTimers;
550   }
551   fastInferiorHeap<processTimerHK, tTimer> &getInferiorProcessTimers() {
552      return inferiorProcessTimers;
553   }
554
555   unsigned getShmHeapTotalNumBytes() {
556      return inferiorHeapMgr.getHeapTotalNumBytes();
557   }
558
559   void *getObsCostLowAddrInApplicSpace() {
560      void *result = inferiorHeapMgr.getObsCostAddrInApplicSpace();
561 //     cerr << "obs cost in addr space is @ " << result << endl;
562      return result;
563   }
564   unsigned *getObsCostLowAddrInParadyndSpace() {
565      unsigned *result = inferiorHeapMgr.getObsCostAddrInParadyndSpace();
566 //     cerr << "obs cost in paradynd space is @ " << (void*)result << endl;
567      return result;
568   }
569   void processCost(unsigned obsCostLow,
570                    unsigned long long wallTime, unsigned long long processTime);
571
572 #endif
573
574 #ifdef SHM_SAMPLING
575 #ifdef sparc_sun_sunos4_1_3
576    static user *tryToMapChildUarea(int pid);
577 #endif
578 #endif
579
580    bool isBootstrappedYet() const {
581       return hasBootstrapped;
582    }
583    bool tryToReadAndProcessBootstrapInfo();
584       // returns true iff processed.  If false is returned, no side effects.
585
586 private:
587   // Since we don't define these, 'private' makes sure they're not used:
588   process(const process &); // copy ctor
589   process &operator=(const process &); // assign oper
590
591   bool hasBootstrapped;
592      // set to true when we get callback from inferiorRPC call to DYNINSTinit
593
594   const process *parent;        /* parent of this proces */
595   image *symbols;               /* information related to the process */
596   int pid;                      /* id of this process */
597
598 #ifdef SHM_SAMPLING
599   // New components of the conceptual "inferior heap"
600   fastInferiorHeapMgr inferiorHeapMgr;
601   fastInferiorHeap<intCounterHK, intCounter> inferiorIntCounters;
602   fastInferiorHeap<wallTimerHK, tTimer>      inferiorWallTimers;
603   fastInferiorHeap<processTimerHK, tTimer>   inferiorProcessTimers;
604
605 #ifdef sparc_sun_sunos4_1_3
606   kvm_t *kvmHandle;
607   user *childUareaPtr;
608 #endif
609
610 #endif
611
612 public:
613   trampTableEntry trampTable[TRAMPTABLESZ];
614   unsigned trampTableItems;
615
616   unsigned currentPC() {
617     int pc, fp;
618     if (hasNewPC)
619       return currentPC_;
620     else if (getActiveFrame(&fp, &pc)) {
621       currentPC_ = (unsigned) pc;
622       return currentPC_;
623     }
624     else abort();
625     return 0;
626   }
627   void setNewPC(unsigned newPC) {
628     currentPC_ = newPC;
629     hasNewPC = true;
630   }
631
632   inline int costAddr()  const { return costAddr_; }  
633   void getObservedCostAddr();   
634
635 private:
636   unsigned currentPC_;
637   bool hasNewPC;
638   time64 firstRecordTime;
639
640   // for processing observed cost (see method processCost())
641   unsigned long long cumObsCost; // in cycles
642   unsigned lastObsCostLow; // in cycles
643
644   int costAddr_; 
645   bool execed_;  // true if this process does an exec...set in handleExec
646   bool mysteryTrap_; // true if paradynd receives a trap before a trace record 
647                     // when the trace record tells paradynd the trap's purpose
648
649   // deal with system differences for ptrace
650   bool writeDataSpace_(void *inTracedProcess, int amount, const void *inSelf);
651   bool readDataSpace_(const void *inTracedProcess, int amount, void *inSelf);
652
653   bool writeTextWord_(caddr_t inTracedProcess, int data);
654   bool writeTextSpace_(void *inTracedProcess, int amount, const void *inSelf);
655   bool pause_();
656   bool continueProc_();
657   bool dumpCore_(const string coreFile);
658   bool detach_();
659   bool attach_(); // low-level attach; called by attach() (formerly OS::osAttach())
660   bool stop_(); // formerly OS::osStop
661
662   // stops a process
663   bool loopUntilStopped();
664
665   // is it ok to attempt a ptrace operation
666   inline bool checkStatus();
667
668   int proc_fd; // file descriptor for platforms that use /proc file system.
669
670   dynamic_linking *dyn;   // platform specific dynamic linking routines & data
671   bool inhandlestart;     // true if the executable is dynamic & initial 
672                           // libraries have not yet been processed 
673   bool dynamiclinking;   // if true this a.out has a .dynamic section
674   vector<shared_object *> *shared_objects;  // list of dynamically linked libs
675
676   // The set of all functions and modules in the a.out and in the shared objects
677   vector<pdFunction *> *all_functions;
678   vector<module *> *all_modules;
679   // these are a restricted set of functions and modules which are those  
680   // from shared objects that are not excluded through an mdl "exclude_library"
681   // option: these are used to satisfy foci that are not refined on the
682   // Code heirarchy
683   vector<module *> *some_modules;  
684   vector<pdFunction *> *some_functions; 
685   bool waiting_for_resources;  // true if waiting for resourceInfoResponse
686   pdFunction *signal_handler;  // signal handler function (for stack walking)
687
688   // needToAddALeafFrame: returns true if the between the current frame 
689   // and the next frame there is a leaf function (this occurs when the 
690   // current frame is the signal handler)
691   bool needToAddALeafFrame(Frame current_frame, Address &leaf_pc);
692 };
693
694 extern vector<process*> processVec;
695 inline process *findProcess(int pid) {
696   unsigned size=processVec.size();
697   for (unsigned u=0; u<size; u++)
698     if (processVec[u] && processVec[u]->getPid() == pid)
699       return processVec[u];
700   return NULL;
701 }
702
703 inline bool process::checkStatus() {
704   if (status_ == exited) {
705     sprintf(errorLine, "attempt to ptrace exited process %d\n", pid);
706     logLine(errorLine);
707     return(false);
708   } else
709     return true;
710 }
711
712 inline bool process::dumpCore(const string fileOut) {
713   bool res = dumpCore_(fileOut);
714   if (!res) {
715     return false;
716   }
717   return true;
718 }
719
720 // getBaseAddress: sets baseAddress to the base address of the 
721 // image corresponding to which.  It returns true  if image is mapped
722 // in processes address space, otherwise it returns 0
723 inline bool process::getBaseAddress(const image *which,u_int &baseAddress){
724
725   if((u_int)(symbols) == (u_int)(which)){
726       baseAddress = 0; 
727       return true;
728   }
729   else if (shared_objects) {  
730       // find shared object corr. to this image and compute correct address
731       for(u_int i=0; i <  shared_objects->size(); i++){ 
732           if(((*shared_objects)[i])->isMapped()){
733             if(((*shared_objects)[i])->getImageId() == (u_int)which) { 
734               baseAddress = ((*shared_objects)[i])->getBaseAddress();
735               return true;
736           } }
737       }
738   }
739   return false;
740 }
741
742 process *createProcess(const string file, vector<string> argv, vector<string> envp, const string dir);
743 void handleProcessExit(process *p, int exitStatus);
744
745 unsigned inferiorMalloc(process *proc, int size, inferiorHeapType type);
746 void inferiorFree(process *proc, unsigned pointer, inferiorHeapType type,
747                   const vector<unsigVecType> &pointsToCheck);
748
749 extern resource *machineResource;
750
751 /*
752  *  The process has exited. Update its status and notify Paradyn.
753  */
754 inline void process::Exited() {
755   if (status_ != exited) {
756     status_ = exited;
757     tp->processStatus(pid, procExited);
758   }
759 }
760
761 /*
762  * The process was stopped by a signal. Update its status and notify Paradyn.
763  */
764 inline void process::Stopped() {
765   if (status_ != stopped) {
766     status_ = stopped;
767     tp->processStatus(pid, procPaused);
768   }
769 }
770
771 class Frame {
772   private:
773     int frame_;
774     int pc_;
775     bool uppermostFrame;
776
777   public:
778     Frame(process *);
779        // formerly getActiveStackFrameInfo
780
781     Frame(int theFrame, int thePc, bool theUppermost) {
782        frame_ = theFrame; pc_ = thePc;
783        uppermostFrame = theUppermost;
784     }
785
786     int getPC() const { return pc_; }
787     int getFramePtr(){ return frame_;}
788     bool isLastFrame() const { 
789         if ((pc_ == 0)||(frame_ == 0))
790             return(true);
791         else 
792             return(false); 
793     }
794
795     Frame getPreviousStackFrameInfo(process *proc) const;
796 };
797
798 #endif