Fixing race condition between continueProc and inferiorRPC in progress - naim
[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    // how about just processVec.size() instead?  At least, this should be made
84    // a (static) member vrble of class process
85
86 class resource;
87 class instPoint;
88 class instInstance;
89 class trampTemplate;
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   }
153   inferiorHeap(const inferiorHeap &src);  // create a new heap that is a copy of src.
154                                           // used on fork.
155   dictionary_hash<unsigned, heapItem*> heapActive; // active part of heap 
156   vector<heapItem*> heapFree;           // free block of data inferior heap 
157   vector<disabledItem> disabledList;    // items waiting to be freed.
158   int disabledListTotalMem;             // total size of item waiting to free
159   int totalFreeMemAvailable;            // total free memory in the heap
160   int freed;                            // total reclaimed (over time)
161 };
162
163
164 //
165 // read a C/C++ book to find out the difference
166 // between:
167 //
168 // (const T *) and (T * const)
169 //
170 static inline unsigned ipHash(instPoint * const &ip) {
171    // assume all addresses are 4-byte aligned
172    unsigned result = (unsigned)ip;
173    result >>= 2;
174    return result;
175       // how about %'ing by a huge prime number?  Nah, x % y == x when x < y
176       // so we don't want the number to be huge.
177 //  return ((unsigned)ip);
178 }
179
180 static inline unsigned instInstanceHash(instInstance * const &inst) {
181    unsigned result = (unsigned)inst;
182    result >>= 2;
183    return result; // how about %'ing by a huge prime number?
184 //  return ((unsigned)inst);
185 }
186
187 class Thread;
188 class Frame;
189
190 class process {
191  friend class ptraceKludge;
192
193  public:
194   process(int iPid, image *iImage, int iTraceLink, int iIoLink
195 #ifdef SHM_SAMPLING
196           , key_t theShmSegKey,
197           const vector<fastInferiorHeapMgr::oneHeapStats> &iShmHeapStats
198 #endif
199           );
200      // this is the "normal" ctor
201
202   process(int iPid, image *iSymbols,
203           int afterAttach // 1 --> pause, 2 --> run, 0 --> leave as is
204 #ifdef SHM_SAMPLING
205           , key_t theShmSegKey,
206           const vector<fastInferiorHeapMgr::oneHeapStats> &iShmHeapStats
207 #endif
208           );
209      // this is the "attach" ctor
210
211   process(const process &parentProc, int iPid, int iTrace_fd
212 #ifdef SHM_SAMPLING
213           , key_t theShmSegKey,
214           void *applShmSegPtr,
215           const vector<fastInferiorHeapMgr::oneHeapStats> &iShmHeapStats
216 #endif
217           );
218      // this is the "fork" ctor
219
220 #ifdef SHM_SAMPLING
221   void registerInferiorAttachedSegs(void *inferiorAttachedAtPtr);
222      // Where the inferior attached was left undefined in the constructor;
223      // this routine fills it in (tells paradynd where, in the inferior proc's addr
224      // space, the shm seg was attached.  The attaching was done in DYNINSTinit)
225 #endif
226
227   vector<Address> walkStack(bool noPause=false);
228
229   // 
230   // getActiveFrame and readDataFromFrame are platform dependant
231   //
232   bool getActiveFrame(int *fp, int *pc);
233   bool readDataFromFrame(int currentFP, int *previousFP, int *rtn, 
234                          bool uppermost=false);
235
236
237 #ifdef SHM_SAMPLING
238   unsigned long long getInferiorProcessCPUtime() const;
239      // returns user+sys time from the u or proc area of the inferior process, which in
240      // turn is presumably obtained by mmapping it (sunos) or by using a /proc ioctl
241      // to obtain it (solaris).  It is hoped that the implementation would not have to
242      // pause the inferior process (and then unpause it) in order to obtain the result,
243      // since pausing and unpausing are extremely slow (I've seen ~70ms).
244 #endif
245
246   processState status() const { return status_;}
247   string getStatusAsString() const; // useful for debug printing etc.
248
249   void continueAfterNextStop() { continueAfterNextStop_ = true; }
250   void Exited();
251   void Stopped();
252
253   // the following 2 vrbles probably belong in a different class:
254   static string programName; // the name of paradynd (more specifically, its argv[0])
255   static vector<string> arg_list; // the arguments of paradynd
256
257   internalSym *findInternalSymbol(const string &name, bool warn) {
258      assert(symbols);
259      return symbols->findInternalSymbol(name, warn);
260   }
261   Address findInternalAddress(const string &name, bool warn, bool &err) const {
262      assert(symbols);
263      return symbols->findInternalAddress(name, warn, err);
264   }
265
266   bool dumpImage();
267
268   bool symbol_info(const string &name, Symbol &ret) {
269      assert(symbols);
270      return symbols->symbol_info(name, ret);
271   }
272   image *getImage() const {
273      assert(symbols);
274      return symbols;
275   }
276
277  private:
278   struct inferiorRPCtoDo {
279      // This structure keeps track of an inferiorRPC that we will start sometime
280      // in the (presumably near) future.  There is a different structure for RPCs
281      // which have been launched and which we're waiting to finish.  Don't confuse
282      // the two.
283
284      AstNode *action;
285      bool noCost; // if true, cost model isn't updated by generated code.
286      void (*callbackFunc)(process *, void *userData, unsigned result);
287      void *userData;
288   };
289   vectorSet<inferiorRPCtoDo> RPCsWaitingToStart;
290
291   struct inferiorRPCinProgress {
292      // This structure keeps track of an inferiorRPC that has been launched and
293      // for which we're waiting to complete.  Don't confuse with 'inferiorRPCtoDo',
294      // which is more of a wait queue of RPCs to start launching.
295      // Also note: It's only safe for 1 RPC to be in progress at a time.
296      // If you _really_ want to launch multiple RPCs at the same time, it's actually
297      // easy to do...just do one inferiorRPC with a sequenceNode AST! (neat, eh?)
298      // (Admittedly, that does confuse the semantics of callback functions.  So
299      // the official line remains: only 1 inferior RPC per process can be ongoing.)
300      void (*callbackFunc)(process *, void *userData, unsigned result);
301      void *userData;
302      
303      void *savedRegs; // crucial!
304
305      bool wasRunning; // were we running when we launched the inferiorRPC?
306
307      unsigned firstInstrAddr; // start location of temp tramp
308
309      unsigned stopForResultAddr;
310         // location of the TRAP or ILL which marks point where paradynd should grab the
311         // result register.  Undefined if no callback fn.
312      unsigned justAfter_stopForResultAddr; // undefined if no callback fn.
313      reg resultRegister; // undefined if no callback fn.
314
315      unsigned resultValue; // undefined until we stop-for-result, at which time we
316                            // fill this in.  The callback fn (which takes in this value)
317                            // isn't invoked until breakAddr (the final break)
318
319      unsigned breakAddr;
320         // location of the TRAP or ILL insn which marks the end of the inferiorRPC
321   };
322   vectorSet<inferiorRPCinProgress> currRunningRPCs;
323       // see para above for reason why this 'vector' can have at most 1 elem!
324
325  public:
326   bool deferredContinueProc;
327   void postRPCtoDo(AstNode *, bool noCost,
328                    void (*)(process *, void *, unsigned), void *);
329   bool existsRPCreadyToLaunch() const;
330   bool existsRPCinProgress() const;
331   bool launchRPCifAppropriate(bool wasRunning);
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
339   bool handleTrapIfDueToRPC();
340      // look for curr PC reg value in 'trapInstrAddr' of 'currRunningRPCs'.  Return
341      // true iff found.  Also, if true is being returned, then additionally does
342      // a 'launchRPCifAppropriate' to fire off the next waiting RPC, if any.
343
344  private:
345   // The follwing 5 routines are implemented in an arch-specific .C file
346   bool emitInferiorRPCheader(void *, unsigned &base);
347   bool emitInferiorRPCtrailer(void *, unsigned &base,
348                               unsigned &breakOffset,
349                               bool stopForResult,
350                               unsigned &stopForResultOffset,
351                               unsigned &justAfter_stopForResultOffset);
352
353   unsigned createRPCtempTramp(AstNode *action,
354                               bool noCost, bool careAboutResult,
355                               unsigned &breakAddr,
356                               unsigned &stopForResultAddr,
357                               unsigned &justAfter_stopForResultAddr,
358                               reg &resultReg);
359
360   // The parameter syscall is only used for hpux platform right now
361   // Can "syscall" be embedded into the opaque type?
362   void *getRegisters(bool &syscall);
363      // ptrace-GETREGS and ptrace-GETFPREGS.  Result is returned in an opaque type
364      // which is allocated with new[]
365
366   bool changePC(unsigned addr,
367                 const void *savedRegs // returned by getRegisters()
368                 );
369   bool changePC(unsigned addr);
370
371   bool restoreRegisters(void *buffer);
372      // input is the opaque type returned by getRegisters()
373
374   unsigned read_inferiorRPC_result_register(reg);
375
376  public:
377   void installBootstrapInst();
378   void installInstrRequests(const vector<instMapping*> &requests);
379  
380   // These member vrbles should be made private!
381   int traceLink;                /* pipe to transfer traces data over */
382   int ioLink;                   /* pipe to transfer stdout/stderr over */
383   processState status_;         /* running, stopped, etc. */
384   vector<Thread *> threads;     /* threads belonging to this process */
385   bool continueAfterNextStop_;
386   // on some platforms we use one heap for text and data so textHeapFree is not
387   // used.
388   bool splitHeaps;              /* are the inferior heap split I/D ? */
389   inferiorHeap  heaps[2];       /* the heaps text and data */
390   resource *rid;                /* handle to resource for this process */
391
392   /* map an inst point to its base tramp */
393   dictionary_hash<const instPoint*, trampTemplate *> baseMap;   
394
395   // the following 3 are used in perfStream.C
396   char buffer[2048];
397   unsigned bufStart;
398   unsigned bufEnd;
399
400   time64 wallTimeLastTrampSample;
401   time64 timeLastTrampSample;
402
403   bool reachedFirstBreak; // should be renamed 'reachedInitialTRAP'
404
405   int getPid() const { return pid;}
406
407   void initInferiorHeap(bool textHeap);
408      // true --> text heap, else data heap
409
410   bool writeDataSpace(void *inTracedProcess,
411                       int amount, const void *inSelf);
412   bool readDataSpace(const void *inTracedProcess, int amount,
413                      void *inSelf, bool displayErrMsg);
414
415   bool writeTextSpace(void *inTracedProcess, int amount, const void *inSelf);
416   bool writeTextWord(caddr_t inTracedProcess, int data);
417   bool continueProc();
418   bool pause();
419
420   bool dumpCore(const string coreFile);
421   bool detach(const bool paused); // why the param?
422   bool attach();
423   string getProcessStatus() const;
424
425   static string tryToFindExecutable(const string &progpath, int pid);
426       // os-specific implementation.  Returns empty string on failure.
427       // Otherwise, returns a full-path-name for the file.  Tries every
428       // trick to determine the full-path-name, even though "progpath" may
429       // be unspecified (empty string)
430
431   bool continueWithForwardSignal(int sig); // arch-specific implementation
432   
433   // forkProcess: this function should be called when a process we are tracing
434   // forks a child process.
435   // This function returns a new process object associated with the child.
436   // It also writes to "map" s.t. for each instInstance in the parent, we have the
437   // corresponding instInstance in the child.
438   static process *forkProcess(const process *parent, pid_t childPid,
439                               dictionary_hash<instInstance*,instInstance*> &map,
440                               int iTrace_fd
441 #ifdef SHM_SAMPLING
442                               ,key_t theKey,
443                               void *applAttachedAtPtr
444 #endif
445                               );
446
447   // get and set info. specifying if this is a dynamic executable
448   void setDynamicLinking(){ dynamiclinking = true;}
449   bool isDynamicallyLinked() { return (dynamiclinking); }
450
451   // handleStartProcess: this function is called when an appplication 
452   // starts executing.  It is used to insert instrumentation necessary
453   // to handle dynamic linking
454   static bool handleStartProcess(process *pid);
455
456   bool handleStopDueToExecEntry();
457
458   // getSharedObjects: This routine is called before main() to get and
459   // process all shared objects that have been mapped into the process's
460   // address space
461   bool getSharedObjects();
462
463   // addASharedObject: This routine is called whenever a new shared object
464   // has been loaded by the run-time linker after the process starts running
465   // It processes the image, creates new resources
466   bool addASharedObject(shared_object &);
467
468   // findOneFunction: returns the function associated with function "func"
469   // and module "mod".  This routine checks both the a.out image and any
470   // shared object images for this function
471   pdFunction *findOneFunction(resource *func,resource *mod);
472
473   // findOneFunction: returns the function associated with function "func_name"
474   // This routine checks both the a.out image and any shared object images 
475   // for this function
476   pdFunction *findOneFunction(const string &func_name);
477
478   // findFunctionIn: returns the function which contains this address
479   // This routine checks both the a.out image and any shared object images 
480   // for this function
481   pdFunction *findFunctionIn(Address adr);
482
483   // findModule: returns the module associated with "mod_name" 
484   // this routine checks both the a.out image and any shared object 
485   // images for this module
486   module *findModule(const string &mod_name);
487
488   // getSymbolInfo:  get symbol info of symbol associated with name n
489   // this routine starts looking a.out for symbol and then in shared objects
490   bool getSymbolInfo(string &n, Symbol &info);
491
492   // getAllFunctions: returns a vector of all functions defined in the
493   // a.out and in the shared objects
494   vector<pdFunction *> *getAllFunctions();
495
496   // getAllModules: returns a vector of all modules defined in the
497   // a.out and in the shared objects
498   vector<module *> *getAllModules();
499
500   // getIncludedFunctions: returns a vector of all functions defined in the
501   // a.out and in shared objects that are not excluded by an mdl option 
502   vector<pdFunction *> *getIncludedFunctions();
503
504   // getIncludedModules: returns a vector of all functions defined in the
505   // a.out and in shared objects that are  not excluded by an mdl option
506   vector<module *> *getIncludedModules();
507
508   // getBaseAddress: sets baseAddress to the base address of the 
509   // image corresponding to which.  It returns true  if image is mapped
510   // in processes address space, otherwise it returns 0
511   bool getBaseAddress(const image *which, u_int &baseAddress);
512
513   // these routines are for testing, setting, and clearing the 
514   // waiting_for_resources flag, if this flag is true a process is not 
515   // started until all outstanding resourceInfoResponses have been received
516   void setWaitingForResources(){ waiting_for_resources = true; }
517   // called by perfStream.C on SIGSTOP if there are any
518   // resource::num_outstanding_creates,
519   // and process::handleStartProcess, also if there are any
520   // resource::num_outstanding_creates.
521   void clearWaitingForResources(){ waiting_for_resources = false; }
522   bool isWaitingForResources(){ return(waiting_for_resources); }
523
524   // findSignalHandler: if signal_handler is 0, then it checks all images
525   // associtated with this process for the signal handler function.
526   // Otherwise, the signal handler function has already been found
527   void findSignalHandler();
528
529   // continueProcessIfWaiting: if the waiting_for_resources flag
530   // is set then continue the process; in any event, clear that flag
531   void continueProcessIfWaiting(){
532       if(waiting_for_resources){
533           continueProc();
534       }
535       waiting_for_resources = false;
536   }
537
538   //  wasExeced: returns true is the process did an exec...this is set
539   //  in handleExec()
540   bool wasExeced(){ return execed_;}
541
542   void handleExec();
543   bool cleanUpInstrumentation(bool wasRunning); // called on exit (also exec?)
544   bool inExec;
545
546   string execFilePath;
547
548   int getProcFileDescriptor(){ return proc_fd;}
549
550   static int waitProcs(int *status);
551   const process *getParent() const {return parent;}
552
553 #if defined(hppa1_1_hp_hpux)
554   bool freeNotOK;
555 #endif
556
557 #ifdef SHM_SAMPLING
558   key_t getShmKeyUsed() const {return inferiorHeapMgr.getShmKey();}
559   bool doMajorShmSample(unsigned long long currWallTime);
560   bool doMinorShmSample();
561
562   const fastInferiorHeap<intCounterHK, intCounter> &getInferiorIntCounters() const {
563      return inferiorIntCounters;
564   }
565   const fastInferiorHeap<wallTimerHK, tTimer> &getInferiorWallTimers() const {
566      return inferiorWallTimers;
567   }
568   const fastInferiorHeap<processTimerHK, tTimer> &getInferiorProcessTimers() const {
569      return inferiorProcessTimers;
570   }
571
572   fastInferiorHeap<intCounterHK, intCounter> &getInferiorIntCounters() {
573      return inferiorIntCounters;
574   }
575   fastInferiorHeap<wallTimerHK, tTimer> &getInferiorWallTimers() {
576      return inferiorWallTimers;
577   }
578   fastInferiorHeap<processTimerHK, tTimer> &getInferiorProcessTimers() {
579      return inferiorProcessTimers;
580   }
581
582   unsigned getShmHeapTotalNumBytes() {
583      return inferiorHeapMgr.getHeapTotalNumBytes();
584   }
585
586   void *getObsCostLowAddrInApplicSpace() {
587      void *result = inferiorHeapMgr.getObsCostAddrInApplicSpace();
588      return result;
589   }
590   unsigned *getObsCostLowAddrInParadyndSpace() {
591      unsigned *result = inferiorHeapMgr.getObsCostAddrInParadyndSpace();
592      return result;
593   }
594   void processCost(unsigned obsCostLow,
595                    unsigned long long wallTime, unsigned long long processTime);
596
597
598 #ifdef sparc_sun_sunos4_1_3
599    static user *tryToMapChildUarea(int pid);
600 #endif
601
602 #endif /* shm_sampling */
603
604    bool isBootstrappedYet() const {
605       return hasBootstrapped;
606    }
607    bool extractBootstrapStruct(DYNINST_bootstrapStruct *);
608    int procStopFromDYNINSTinit();
609       // returns 0 if not processed, 1 for the usual processed case (process is
610       // now paused), or 2 for the processed-but-still-running-inferiorRPC case
611
612    void handleCompletionOfDYNINSTinit(bool fromAttach);
613       // called by above routine.  Reads bs_record from applic, takes action.
614
615    static void DYNINSTinitCompletionCallback(process *, void *, unsigned);
616       // inferiorRPC callback routine.
617
618 private:
619   // Since we don't define these, 'private' makes sure they're not used:
620   process(const process &); // copy ctor
621   process &operator=(const process &); // assign oper
622
623   bool hasBootstrapped;
624      // set to true when we get callback from inferiorRPC call to DYNINSTinit
625
626   const process *parent;        /* parent of this proces */
627   image *symbols;               /* information related to the process */
628   int pid;                      /* id of this process */
629
630 #ifdef SHM_SAMPLING
631   // New components of the conceptual "inferior heap"
632   fastInferiorHeapMgr inferiorHeapMgr;
633   fastInferiorHeap<intCounterHK, intCounter> inferiorIntCounters;
634   fastInferiorHeap<wallTimerHK, tTimer>      inferiorWallTimers;
635   fastInferiorHeap<processTimerHK, tTimer>   inferiorProcessTimers;
636
637 #ifdef sparc_sun_sunos4_1_3
638   kvm_t *kvmHandle;
639   user *childUareaPtr;
640 #endif
641
642 #endif
643
644 public:
645   trampTableEntry trampTable[TRAMPTABLESZ];
646   unsigned trampTableItems;
647
648   unsigned currentPC() {
649     int pc, fp;
650     if (hasNewPC)
651       return currentPC_;
652     else if (getActiveFrame(&fp, &pc)) {
653       currentPC_ = (unsigned) pc;
654       return currentPC_;
655     }
656     else abort();
657     return 0;
658   }
659   void setNewPC(unsigned newPC) {
660     currentPC_ = newPC;
661     hasNewPC = true;
662   }
663
664   inline int costAddr()  const { return costAddr_; }  // why an integer?
665   void getObservedCostAddr();   
666
667 private:
668   bool createdViaAttach;
669      // set in the ctor.  True iff this process was created with an attach,
670      // as opposed to being fired up by paradynd.  On fork, has the value of
671      // the parent process.  On exec, no change.
672      // This vrble is important because it tells us what to do when we exit.
673      // If we created via attach, we should (presumably) detach but not fry
674      // the application; otherwise, a kill(pid, 9) is called for.
675   // the following 2 are defined only if 'createdViaAttach' is true; action is taken
676   // on these vrbles once DYNINSTinit completes.
677
678   bool wasRunningWhenAttached;
679   bool needToContinueAfterDYNINSTinit;
680
681   unsigned currentPC_;
682   bool hasNewPC;
683
684   // for processing observed cost (see method processCost())
685   unsigned long long cumObsCost; // in cycles
686   unsigned lastObsCostLow; // in cycles
687
688   int costAddr_;  // why an integer?
689   bool execed_;  // true if this process does an exec...set in handleExec
690
691   // deal with system differences for ptrace
692   bool writeDataSpace_(void *inTracedProcess, int amount, const void *inSelf);
693   bool readDataSpace_(const void *inTracedProcess, int amount, void *inSelf);
694
695   bool writeTextWord_(caddr_t inTracedProcess, int data);
696   bool writeTextSpace_(void *inTracedProcess, int amount, const void *inSelf);
697   bool pause_();
698   bool continueProc_();
699   bool dumpCore_(const string coreFile);
700   bool detach_();
701   bool attach_(); // low-level attach; called by attach() (formerly OS::osAttach())
702   bool stop_(); // formerly OS::osStop
703
704   // stops a process
705   bool loopUntilStopped();
706
707   // returns true iff ok to do a ptrace; false (and prints a warning) if not
708   bool checkStatus();
709
710   int proc_fd; // file descriptor for platforms that use /proc file system.
711
712   dynamic_linking *dyn;   // platform specific dynamic linking routines & data
713
714   bool dynamiclinking;   // if true this a.out has a .dynamic section
715   vector<shared_object *> *shared_objects;  // list of dynamically linked libs
716
717   // The set of all functions and modules in the a.out and in the shared objects
718   vector<pdFunction *> *all_functions;
719   vector<module *> *all_modules;
720   // these are a restricted set of functions and modules which are those  
721   // from shared objects that are not excluded through an mdl "exclude_library"
722   // option: these are used to satisfy foci that are not refined on the
723   // Code heirarchy
724   vector<module *> *some_modules;  
725   vector<pdFunction *> *some_functions; 
726   bool waiting_for_resources;  // true if waiting for resourceInfoResponse
727   pdFunction *signal_handler;  // signal handler function (for stack walking)
728
729   // needToAddALeafFrame: returns true if the between the current frame 
730   // and the next frame there is a leaf function (this occurs when the 
731   // current frame is the signal handler)
732   bool needToAddALeafFrame(Frame current_frame, Address &leaf_pc);
733
734   bool isRunning_() const;
735      // needed to initialize the 'wasRunningWhenAttached' member vrble.  Determines
736      // whether the process is running by doing a low-level OS check, not by checking
737      // member vrbles like status_.  May assume that process::attach() has already run,
738      // but can't assume anything else.  May barf with a not-yet-implemented error on a
739      // given platform if the platform doesn't yet support attaching to a running process.
740      // But there's no reason why we shouldn't be able to implement this on any platform;
741      // after all, the output from the "ps" command can be used (T --> return false,
742      // S or R --> return true, other --> return ?)
743
744 #if defined(sparc_sun_solaris2_4) || defined(i386_unknown_solaris2_5)
745    // some very useful items gathered from /proc (initialized in attach() [solaris.C],
746    // as soon as /proc fd is opened)
747    string argv0; // argv[0] of program, at the time it started up
748    string pathenv; // path env var of program, at the time it started up
749    string cwdenv; // curr working directory of program, at the time it started up
750
751 //   string fullPathToExecutable_;
752       // very useful, especially on attach (need this to parse the symbol table)
753
754  public:
755    const string &getArgv0() const {return argv0;}
756    const string &getPathEnv() const {return pathenv;}
757    const string &getCwdEnv() const {return cwdenv;}
758 #endif
759 };
760
761 process *createProcess(const string file, vector<string> argv, vector<string> envp, const string dir);
762 bool attachProcess(const string &progpath, int pid, int afterAttach);
763
764 void handleProcessExit(process *p, int exitStatus);
765
766 unsigned inferiorMalloc(process *proc, int size, inferiorHeapType type);
767 void inferiorFree(process *proc, unsigned pointer, inferiorHeapType type,
768                   const vector<unsigVecType> &pointsToCheck);
769
770 extern resource *machineResource;
771
772 class Frame {
773   private:
774     int frame_;
775     int pc_;
776     bool uppermostFrame;
777
778   public:
779     Frame(process *);
780        // formerly getActiveStackFrameInfo
781
782     Frame(int theFrame, int thePc, bool theUppermost) {
783        frame_ = theFrame; pc_ = thePc;
784        uppermostFrame = theUppermost;
785     }
786
787     int getPC() const { return pc_; }
788     int getFramePtr(){ return frame_;}
789     bool isLastFrame() const { 
790         if ((pc_ == 0)||(frame_ == 0))
791             return(true);
792         else 
793             return(false); 
794     }
795
796     Frame getPreviousStackFrameInfo(process *proc) const;
797 };
798
799 extern vector<process *> processVec;
800
801 #define CT_BLOCK_SIZE 300
802
803 class CT {
804   public:
805     CT(process *pproc) : CTvectorAddr(0), CTvectorSize(0), CTmapTable(CThash) 
806     { 
807       proc = pproc; 
808     }
809     unsigned size() { return(CTvectorSize); }
810     bool update(unsigned tableAddr);
811     void add(unsigned CTid, unsigned &position); 
812     void remove(unsigned CTid, unsigned position);
813     void dup(unsigned CTid, unsigned mid, Thread *thr, unsigned &position);
814     unsigned getCTmapId(unsigned mid) 
815     {
816       assert(CTmapTable.defines(mid));
817       return(CTmapTable[mid]); 
818     }
819     unsigned getCTusagePos(unsigned position) {
820       assert(position < CTusage.size()); 
821       return(CTusage[position]); 
822     }
823   private:
824     unsigned CTvectorAddr;
825     unsigned CTvectorSize;
826     dictionary_hash<unsigned, unsigned> CTmapTable;
827     vector<int> CTusage;
828     vector<int> CTfree;
829     process *proc;
830 };
831
832 class Thread {
833   public:
834     // This definition must be completed later when we get the result of a call
835     // to thr_self in the application. We are assuming that 
836     // 0 <= thr_self,tid < MAX_NUMBER_OF_THREADS - naim
837     Thread(process *pproc) : tid(0), pos(0), rid(NULL) 
838     { 
839       proc = pproc; 
840       ppid = pproc->getPid();
841       CTvector = new CT(proc);
842     }
843     Thread(process *proc_, int tid_, int pos_, resource *rid_ )
844     { 
845       proc = proc_; 
846       ppid = proc_->getPid();
847       tid = tid_;
848       pos = pos_;
849       rid = rid_;
850       CTvector = new CT(proc_);
851       //assert(tid>=0 && tid<MAX_NUMBER_OF_THREADS);
852     }
853     ~Thread() 
854     { 
855       delete CTvector;
856     }
857     int get_tid() { return(tid); }
858     unsigned get_pos() { return(pos); }
859     void update_tid(int id, int p) { tid = id; pos = p; }
860     int get_ppid() { return(ppid); }
861     resource *get_rid() { return(rid); }
862     process *get_proc() { return(proc); }
863     CT *CTvector;
864   private:
865     int tid;
866     int ppid;
867     int pos;
868     resource *rid;
869     process *proc;
870 };
871
872 #endif