2 * Copyright (c) 1996 Barton P. Miller
4 * We provide the Paradyn Parallel Performance Tools (below
5 * described as Paradyn") on an AS IS basis, and do not warrant its
6 * validity or performance. We reserve the right to update, modify,
7 * or discontinue this software at any time. We shall have no
8 * obligation to supply such updates or modifications or any other
9 * form of support to you.
11 * This license is for research uses. For such uses, there is no
12 * charge. We define "research use" to mean you may freely use it
13 * inside your organization for whatever purposes you see fit. But you
14 * may not re-distribute Paradyn or parts of Paradyn, in any form
15 * source or binary (including derivatives), electronic or otherwise,
16 * to any other organization or entity without our permission.
18 * (for other uses, please contact us at paradyn@cs.wisc.edu)
20 * All warranties, including without limitation, any warranty of
21 * merchantability or fitness for a particular purpose, are hereby
24 * By your use of Paradyn, you understand and agree that we (or any
25 * other person or entity with proprietary rights in Paradyn) are
26 * under no obligation to provide either maintenance services,
27 * update services, notices of latent defects, or correction of
28 * defects for Paradyn.
30 * Even if advised of the possibility of such damages, under no
31 * circumstances shall we (or any other person or entity with
32 * proprietary rights in the software licensed hereunder) be liable
33 * to you or any third party for direct, indirect, or consequential
34 * damages of any character regardless of type of action, including,
35 * without limitation, loss of profits, loss of use, loss of good
36 * will, or computer failure or malfunction. You agree to indemnify
37 * us (and any other person or entity with proprietary rights in the
38 * software licensed hereunder) for any and all liability it may
39 * incur to third parties resulting from your use of Paradyn.
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.
55 #include "dyninstAPI_RT/h/rtinst.h"
57 #include "rtinst/h/rtinst.h"
59 #include "dyninstAPI/src/util.h"
60 #include "util/h/String.h"
61 #include "util/h/vectorSet.h"
62 #include "util/h/Dictionary.h"
63 #include "util/h/Types.h"
64 #include "util/h/Timer.h"
65 #include "dyninstAPI/src/ast.h"
66 #include "dyninstAPI/src/os.h"
67 // #include "paradynd/src/main.h"
68 #include "paradynd/src/showerror.h"
70 #include "dyninstAPI/src/symtab.h" // internalSym
73 #include "paradynd/src/fastInferiorHeapMgr.h"
74 #include "paradynd/src/superTable.h"
75 #include "paradynd/src/hashTable.h"
76 #ifdef sparc_sun_sunos4_1_3
82 #include "dyninstAPI/src/sharedobject.h"
83 #include "dyninstAPI/src/dynamiclinking.h"
85 extern unsigned activeProcesses; // number of active processes
86 // how about just processVec.size() instead? At least, this should be made
87 // a (static) member vrble of class process
95 // TODO a kludge - to prevent recursive includes
98 typedef enum { neonatal, running, stopped, exited } processState;
99 typedef enum { HEAPfree, HEAPallocated } heapStatus;
100 typedef enum { textHeap=0, dataHeap=1 } inferiorHeapType;
101 typedef vector<unsigned> unsigVecType;
103 const int LOAD_DYNINST_BUF_SIZE = 64;
108 addr =0; length = 0; status = HEAPfree;
110 heapItem(const heapItem *h) {
111 addr = h->addr; length = h->length; status = h->status;
119 // an item on the heap that we are trying to free.
123 disabledItem() { pointer = 0; }
124 disabledItem(unsigned iPointer, inferiorHeapType iHeapType, const vector<unsigVecType> &iPoints) : pointsToCheck(iPoints) {
126 whichHeap = iHeapType;
128 disabledItem(const disabledItem &src) : pointsToCheck(src.pointsToCheck) {
129 pointer = src.pointer;
130 whichHeap = src.whichHeap;
133 disabledItem &operator=(const disabledItem &src) {
134 if (&src == this) return *this; // the usual check for x=x
136 pointer = src.pointer;
137 whichHeap = src.whichHeap;
138 pointsToCheck = src.pointsToCheck;
142 unsigned getPointer() const {return pointer;}
143 inferiorHeapType getHeapType() const {return whichHeap;}
144 const vector<unsigVecType> &getPointsToCheck() const {return pointsToCheck;}
145 vector<unsigVecType> &getPointsToCheck() {return pointsToCheck;}
148 unsigned pointer; // address in heap
149 inferiorHeapType whichHeap; // which heap is it in
150 vector<unsigVecType> pointsToCheck; // range of addrs to check
156 inferiorHeap(): heapActive(addrHash16) {
157 freed = 0; disabledListTotalMem = 0; totalFreeMemAvailable = 0;
158 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
162 inferiorHeap(const inferiorHeap &src); // create a new heap that is a copy of src.
164 dictionary_hash<unsigned, heapItem*> heapActive; // active part of heap
165 vector<heapItem*> heapFree; // free block of data inferior heap
166 vector<disabledItem> disabledList; // items waiting to be freed.
167 int disabledListTotalMem; // total size of item waiting to free
168 int totalFreeMemAvailable; // total free memory in the heap
169 int freed; // total reclaimed (over time)
171 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
172 Address base; // base of heap
173 int size; // size of heap
174 #endif /* BPATCH_SET_MUTATIONS_ACTIVE */
177 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
178 class mutationRecord {
180 mutationRecord *next;
181 mutationRecord *prev;
187 mutationRecord(Address _addr, int _size, const void *_data);
193 mutationRecord *head;
194 mutationRecord *tail;
196 mutationList() : head(NULL), tail(NULL) {};
199 void insertHead(Address addr, int size, const void *data);
200 void insertTail(Address addr, int size, const void *data);
201 mutationRecord *getHead() { return head; }
202 mutationRecord *getTail() { return tail; }
204 #endif /* BPATCH_SET_MUTATIONS_ACTIVE */
206 static inline unsigned ipHash(const instPoint * const &ip)
208 // assume all addresses are 4-byte aligned
209 unsigned result = (unsigned)ip;
212 // how about %'ing by a huge prime number? Nah, x % y == x when x < y
213 // so we don't want the number to be huge.
217 static inline unsigned instInstanceHash(instInstance * const &inst) {
218 unsigned result = (unsigned)inst;
220 return result; // how about %'ing by a huge prime number?
221 // return ((unsigned)inst);
227 friend class ptraceKludge;
228 #ifdef BPATCH_LIBRARY
229 friend class BPatch_image;
233 // PUBLIC MEMBERS FUNCTIONS
237 process(int iPid, image *iImage, int iTraceLink, int iIoLink
239 , key_t theShmSegKey,
240 const vector<fastInferiorHeapMgr::oneHeapStats> &iShmHeapStats
243 // this is the "normal" ctor
245 process(int iPid, image *iSymbols,
246 int afterAttach, // 1 --> pause, 2 --> run, 0 --> leave as is
249 , key_t theShmSegKey,
250 const vector<fastInferiorHeapMgr::oneHeapStats> &iShmHeapStats
253 // this is the "attach" ctor
255 process(const process &parentProc, int iPid, int iTrace_fd
257 , key_t theShmSegKey,
259 const vector<fastInferiorHeapMgr::oneHeapStats> &iShmHeapStats
262 // this is the "fork" ctor
265 void registerInferiorAttachedSegs(void *inferiorAttachedAtPtr);
266 // Where the inferior attached was left undefined in the constructor;
267 // this routine fills it in (tells paradynd where, in the inferior proc's addr
268 // space, the shm seg was attached. The attaching was done in DYNINSTinit)
271 vector<Address> walkStack(bool noPause=false);
274 // getActiveFrame and readDataFromFrame are platform dependant
276 bool getActiveFrame(int *fp, int *pc);
277 bool readDataFromFrame(int currentFP, int *previousFP, int *rtn,
278 bool uppermost=false);
282 time64 getInferiorProcessCPUtime();
283 // returns user+sys time from the u or proc area of the inferior process, which in
284 // turn is presumably obtained by mmapping it (sunos) or by using a /proc ioctl
285 // to obtain it (solaris). It is hoped that the implementation would not have to
286 // pause the inferior process (and then unpause it) in order to obtain the result,
287 // since pausing and unpausing are extremely slow (I've seen ~70ms).
290 processState status() const { return status_;}
291 string getStatusAsString() const; // useful for debug printing etc.
293 void continueAfterNextStop() { continueAfterNextStop_ = true; }
297 bool findInternalSymbol(const string &name, bool warn, internalSym &ret_sym) const;
299 Address findInternalAddress(const string &name, bool warn, bool &err) const;
301 #ifdef BPATCH_LIBRARY
302 bool dumpImage(string outFile);
307 bool symbol_info(const string &name, Symbol &ret) {
309 return symbols->symbol_info(name, ret);
311 image *getImage() const {
316 // this is only used on aix so far - naim
317 vector<int> getTOCoffsetInfo() const;
319 bool dyninstLibAlreadyLoaded() { return hasLoadedDyninstLib; }
320 bool dyninstLibIsBeingLoaded() { return isLoadingDyninstLib; }
321 unsigned numOfActCounters_is;
322 unsigned numOfActProcTimers_is;
323 unsigned numOfActWallTimers_is;
324 bool deferredContinueProc;
325 void updateActiveCT(bool flag, CTelementType type);
326 void cleanRPCreadyToLaunch(int mid);
327 void postRPCtoDo(AstNode *, bool noCost,
328 void (*)(process *, void *, unsigned), void *, int);
329 bool existsRPCreadyToLaunch() const;
330 bool existsRPCinProgress() const;
331 bool launchRPCifAppropriate(bool wasRunning, bool finishingSysCall);
332 // returns true iff anything was launched.
333 // asynchronously launches iff RPCsWaitingToStart.size() > 0 AND
334 // if currRunningRPCs.size()==0 (the latter for safety)
335 // If we're gonna launch, then we'll stop the process (a necessity).
336 // Pass wasRunning as true iff you want the process to continue after
337 // receiving the TRAP signifying completion of the RPC.
338 bool isRPCwaitingForSysCallToComplete() const {
339 return RPCs_waiting_for_syscall_to_complete;
341 void setRPCwaitingForSysCallToComplete(bool flag) {
342 RPCs_waiting_for_syscall_to_complete = flag;
345 bool handleTrapIfDueToRPC();
346 // look for curr PC reg value in 'trapInstrAddr' of 'currRunningRPCs'. Return
347 // true iff found. Also, if true is being returned, then additionally does
348 // a 'launchRPCifAppropriate' to fire off the next waiting RPC, if any.
349 bool changePC(unsigned addr);
352 void installBootstrapInst();
353 void installInstrRequests(const vector<instMapping*> &requests);
356 int getPid() const { return pid;}
358 bool heapIsOk(const vector<sym_data>&);
359 bool initDyninstLib();
361 void initInferiorHeap(bool textHeap);
362 // true --> text heap, else data heap
364 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
365 bool isAddrInHeap(Address addr) {
366 if ((addr >= heaps[dataHeap].base &&
367 addr < heaps[dataHeap].base + heaps[dataHeap].size) ||
368 (splitHeaps && addr >= heaps[textHeap].base &&
369 addr < heaps[textHeap].base + heaps[textHeap].size))
376 bool writeDataSpace(void *inTracedProcess,
377 int amount, const void *inSelf);
378 bool readDataSpace(const void *inTracedProcess, int amount,
379 void *inSelf, bool displayErrMsg);
381 bool writeTextSpace(void *inTracedProcess, int amount, const void *inSelf);
382 bool writeTextWord(caddr_t inTracedProcess, int data);
383 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
384 bool readTextSpace(const void *inTracedProcess, int amount,
388 #ifdef BPATCH_LIBRARY
389 bool terminateProc() { return terminateProc_(); }
393 bool replaceFunctionCall(const instPoint *point,const function_base *newFunc);
395 bool dumpCore(const string coreFile);
396 bool detach(const bool paused); // why the param?
397 bool API_detach(const bool cont); // XXX Should eventually replace detach()
401 // PUBLIC DATA MEMBERS
404 // the following 2 vrbles probably belong in a different class:
405 static string programName; // the name of paradynd (more specifically, its argv[0])
406 static vector<string> arg_list; // the arguments of paradynd
407 static string pdFlavor ;
410 // These member vrbles should be made private!
411 int traceLink; /* pipe to transfer traces data over */
412 int ioLink; /* pipe to transfer stdout/stderr over */
413 processState status_; /* running, stopped, etc. */
414 vector<pdThread *> threads; /* threads belonging to this process */
415 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
416 hashTable *threadMap; /* mapping table for threads into superTable */
418 bool continueAfterNextStop_;
419 // on some platforms we use one heap for text and data so textHeapFree is not
421 bool splitHeaps; /* are the inferior heap split I/D ? */
422 inferiorHeap heaps[2]; /* the heaps text and data */
423 resource *rid; /* handle to resource for this process */
425 /* map an inst point to its base tramp */
426 dictionary_hash<const instPoint*, trampTemplate *> baseMap;
428 // the following 3 are used in perfStream.C
433 time64 wallTimeLastTrampSample;
434 time64 timeLastTrampSample;
436 bool reachedFirstBreak; // should be renamed 'reachedInitialTRAP'
437 bool reachedVeryFirstTrap;
440 // PRIVATE DATA MEMBERS (and structure definitions)....
443 #if defined(USES_LIBDYNINSTRT_SO)
444 unsigned char savedCodeBuffer[BYTES_TO_SAVE];
446 struct inferiorRPCtoDo {
447 // This structure keeps track of an inferiorRPC that we will start sometime
448 // in the (presumably near) future. There is a different structure for RPCs
449 // which have been launched and which we're waiting to finish. Don't confuse
453 bool noCost; // if true, cost model isn't updated by generated code.
454 void (*callbackFunc)(process *, void *userData, unsigned result);
458 vectorSet<inferiorRPCtoDo> RPCsWaitingToStart;
459 bool RPCs_waiting_for_syscall_to_complete;
460 void *save_exitset_ptr; // platform-specific (for now, just solaris;
461 // it's actually a sysset_t*)
463 struct inferiorRPCinProgress {
464 // This structure keeps track of an inferiorRPC that has been launched and
465 // for which we're waiting to complete. Don't confuse with 'inferiorRPCtoDo',
466 // which is more of a wait queue of RPCs to start launching.
467 // Also note: It's only safe for 1 RPC to be in progress at a time.
468 // If you _really_ want to launch multiple RPCs at the same time, it's actually
469 // easy to do...just do one inferiorRPC with a sequenceNode AST! (neat, eh?)
470 // (Admittedly, that does confuse the semantics of callback functions. So
471 // the official line remains: only 1 inferior RPC per process can be ongoing.)
472 void (*callbackFunc)(process *, void *userData, unsigned result);
475 void *savedRegs; // crucial!
477 bool wasRunning; // were we running when we launched the inferiorRPC?
479 unsigned firstInstrAddr; // start location of temp tramp
481 unsigned stopForResultAddr;
482 // location of the TRAP or ILL which marks point where paradynd should grab the
483 // result register. Undefined if no callback fn.
484 unsigned justAfter_stopForResultAddr; // undefined if no callback fn.
485 reg resultRegister; // undefined if no callback fn.
487 unsigned resultValue; // undefined until we stop-for-result, at which time we
488 // fill this in. The callback fn (which takes in this value)
489 // isn't invoked until breakAddr (the final break)
492 // location of the TRAP or ILL insn which marks the end of the inferiorRPC
494 vectorSet<inferiorRPCinProgress> currRunningRPCs;
495 // see para above for reason why this 'vector' can have at most 1 elem!
499 // PRIVATE MEMBER FUNCTIONS
502 // The follwing 5 routines are implemented in an arch-specific .C file
503 bool emitInferiorRPCheader(void *, unsigned &base);
504 bool emitInferiorRPCtrailer(void *, unsigned &base,
505 unsigned &breakOffset,
507 unsigned &stopForResultOffset,
508 unsigned &justAfter_stopForResultOffset);
510 unsigned createRPCtempTramp(AstNode *action,
511 bool noCost, bool careAboutResult,
513 unsigned &stopForResultAddr,
514 unsigned &justAfter_stopForResultAddr,
517 void *getRegisters();
518 // ptrace-GETREGS and ptrace-GETFPREGS (or /proc PIOCGREG and PIOCGFPREG).
519 // Result is returned in an opaque type which is allocated with new[]
521 bool changePC(unsigned addr,
522 const void *savedRegs // returned by getRegisters()
525 bool executingSystemCall();
527 bool restoreRegisters(void *buffer);
528 // input is the opaque type returned by getRegisters()
530 bool set_breakpoint_for_syscall_completion();
531 unsigned read_inferiorRPC_result_register(reg);
535 #if defined(USES_LIBDYNINSTRT_SO)
536 unsigned dyninstlib_brk_addr;
537 unsigned main_brk_addr;
538 bool dlopenDYNINSTlib();
539 bool trapDueToDyninstLib();
540 bool trapAtEntryPointOfMain();
541 bool wasCreatedViaAttach() { return createdViaAttach; }
542 void handleIfDueToDyninstLib();
543 void insertTrapAtEntryPointOfMain();
544 void handleTrapAtEntryPointOfMain();
547 string getProcessStatus() const;
549 static string tryToFindExecutable(const string &progpath, int pid);
550 // os-specific implementation. Returns empty string on failure.
551 // Otherwise, returns a full-path-name for the file. Tries every
552 // trick to determine the full-path-name, even though "progpath" may
553 // be unspecified (empty string)
555 bool continueWithForwardSignal(int sig); // arch-specific implementation
557 // forkProcess: this function should be called when a process we are tracing
558 // forks a child process.
559 // This function returns a new process object associated with the child.
560 // It also writes to "map" s.t. for each instInstance in the parent, we have the
561 // corresponding instInstance in the child.
562 static process *forkProcess(const process *parent, pid_t childPid,
563 dictionary_hash<instInstance*,instInstance*> &map,
567 void *applAttachedAtPtr
571 // get and set info. specifying if this is a dynamic executable
572 void setDynamicLinking(){ dynamiclinking = true;}
573 bool isDynamicallyLinked() { return (dynamiclinking); }
575 // handleIfDueToSharedObjectMapping: if a trap instruction was caused by
576 // a dlopen or dlclose event then return true
577 bool handleIfDueToSharedObjectMapping();
579 // handleStartProcess: this function is called when an appplication
580 // starts executing. It is used to insert instrumentation necessary
581 // to handle dynamic linking
582 bool handleStartProcess();
584 bool handleStopDueToExecEntry();
586 #if defined(USES_LIBDYNINSTRT_SO)
587 unsigned get_dlopen_addr() const;
590 // getSharedObjects: This routine is called before main() to get and
591 // process all shared objects that have been mapped into the process's
593 bool getSharedObjects();
595 // addASharedObject: This routine is called whenever a new shared object
596 // has been loaded by the run-time linker after the process starts running
597 // It processes the image, creates new resources
598 bool addASharedObject(shared_object &);
600 // return the list of dynamically linked libs
601 vector<shared_object *> *sharedObjects() { return shared_objects; }
603 // getMainFunction: returns the main function for this process
604 function_base *getMainFunction() const { return mainFunction; }
606 // findOneFunction: returns the function associated with function "func"
607 // and module "mod". This routine checks both the a.out image and any
608 // shared object images for this function.
609 // mcheyney - should return NULL if function is excluded!!!!
610 function_base *findOneFunction(resource *func,resource *mod);
612 #ifndef BPATCH_LIBRARY
613 // returns all the functions in the module "mod" that are not excluded by
614 // exclude_lib or exclude_func
615 // return 0 on error.
616 vector<function_base *> *getIncludedFunctions(module *mod);
619 // findOneFunction: returns the function associated with function "func_name"
620 // This routine checks both the a.out image and any shared object images
622 function_base *findOneFunction(const string &func_name);
624 // findOneFunctionFromAll: returns the function associated with function "func_name"
625 // This routine checks both the a.out image and any shared object images
627 function_base *findOneFunctionFromAll(const string &func_name);
629 // findFunctionIn: returns the function which contains this address
630 // This routine checks both the a.out image and any shared object images
632 function_base *findFunctionIn(Address adr);
634 // findModule: returns the module associated with "mod_name"
635 // this routine checks both the a.out image and any shared object
636 // images for this module
637 // if check_excluded is true it checks to see if the module is excluded
638 // and if it is it returns 0. If check_excluded is false it doesn't check
639 module *findModule(const string &mod_name,bool check_excluded);
641 // getSymbolInfo: get symbol info of symbol associated with name n
642 // this routine starts looking a.out for symbol and then in shared objects
643 // baseAddr is set to the base address of the object containing the symbol
644 bool getSymbolInfo(const string &n, Symbol &info, Address &baseAddr) const;
646 // getAllFunctions: returns a vector of all functions defined in the
647 // a.out and in the shared objects
648 vector<function_base *> *getAllFunctions();
650 // getAllModules: returns a vector of all modules defined in the
651 // a.out and in the shared objects
652 vector<module *> *getAllModules();
654 #ifndef BPATCH_LIBRARY
655 // getIncludedFunctions: returns a vector of all functions defined in the
656 // a.out and in shared objects that are not excluded by an mdl option
657 vector<function_base *> *getIncludedFunctions();
660 // getIncludedModules: returns a vector of all functions defined in the
661 // a.out and in shared objects that are not excluded by an mdl option
662 vector<module *> *getIncludedModules();
664 // getBaseAddress: sets baseAddress to the base address of the
665 // image corresponding to which. It returns true if image is mapped
666 // in processes address space, otherwise it returns 0
667 bool getBaseAddress(const image *which, u_int &baseAddress) const;
669 // findCallee: finds the function called by the instruction corresponding
670 // to the instPoint "instr". If the function call has been bound to an
671 // address, then the callee function is returned in "target" and the
672 // instPoint "callee" data member is set to pt to callee's function_base.
673 // If the function has not yet been bound, then "target" is set to the
674 // function_base associated with the name of the target function (this is
675 // obtained by the PLT and relocation entries in the image), and the instPoint
676 // callee is not set. If the callee function cannot be found, (ex. function
677 // pointers, or other indirect calls), it returns false.
678 // Returns false on error (ex. process doesn't contain this instPoint).
679 bool findCallee(instPoint &instr, function_base *&target);
681 // these routines are for testing, setting, and clearing the
682 // waiting_for_resources flag, if this flag is true a process is not
683 // started until all outstanding resourceInfoResponses have been received
684 void setWaitingForResources(){ waiting_for_resources = true; }
685 // called by perfStream.C on SIGSTOP if there are any
686 // resource::num_outstanding_creates,
687 // and process::handleStartProcess, also if there are any
688 // resource::num_outstanding_creates.
689 void clearWaitingForResources(){ waiting_for_resources = false; }
690 bool isWaitingForResources(){ return(waiting_for_resources); }
692 // findSignalHandler: if signal_handler is 0, then it checks all images
693 // associtated with this process for the signal handler function.
694 // Otherwise, the signal handler function has already been found
695 void findSignalHandler();
697 // continueProcessIfWaiting: if the waiting_for_resources flag
698 // is set then continue the process; in any event, clear that flag
699 void continueProcessIfWaiting(){
700 if(waiting_for_resources){
703 waiting_for_resources = false;
706 // wasExeced: returns true is the process did an exec...this is set
708 bool wasExeced(){ return execed_;}
711 bool cleanUpInstrumentation(bool wasRunning); // called on exit (also exec?)
716 int getProcFileDescriptor(){ return proc_fd;}
718 #ifdef BPATCH_LIBRARY
719 static int waitProcs(int *status, bool block = false);
721 static int waitProcs(int *status);
723 const process *getParent() const {return parent;}
725 #if defined(hppa1_1_hp_hpux)
730 key_t getShmKeyUsed() const {return inferiorHeapMgr.getShmKey();}
731 bool doMajorShmSample(time64 currWallTime);
732 bool doMinorShmSample();
734 const fastInferiorHeapMgr &getShmHeapMgr() const {
735 return(inferiorHeapMgr);
738 unsigned getShmHeapTotalNumBytes() {
739 return inferiorHeapMgr.getHeapTotalNumBytes();
742 void *getObsCostLowAddrInApplicSpace() {
743 void *result = inferiorHeapMgr.getObsCostAddrInApplicSpace();
746 unsigned *getObsCostLowAddrInParadyndSpace() {
747 unsigned *result = inferiorHeapMgr.getObsCostAddrInParadyndSpace();
750 void processCost(unsigned obsCostLow,
751 time64 wallTime, time64 processTime);
754 #ifdef sparc_sun_sunos4_1_3
755 static user *tryToMapChildUarea(int pid);
758 #endif /* shm_sampling */
760 bool isBootstrappedYet() const {
761 return hasBootstrapped;
763 bool extractBootstrapStruct(DYNINST_bootstrapStruct *);
764 int procStopFromDYNINSTinit();
765 // returns 0 if not processed, 1 for the usual processed case (process is
766 // now paused), or 2 for the processed-but-still-running-inferiorRPC case
768 void handleCompletionOfDYNINSTinit(bool fromAttach);
769 // called by above routine. Reads bs_record from applic, takes action.
771 static void DYNINSTinitCompletionCallback(process *, void *, unsigned);
772 // inferiorRPC callback routine.
775 // Since we don't define these, 'private' makes sure they're not used:
776 process(const process &); // copy ctor
777 process &operator=(const process &); // assign oper
779 bool hasBootstrapped;
780 // set to true when we get callback from inferiorRPC call to DYNINSTinit
782 // the following two variables are used when libdyninstRT is dynamically linked
783 // which currently is done only on the Windows NT platform.
784 // On other platforms the values are undefined
785 bool hasLoadedDyninstLib; // true iff dyninstlib has been loaded already
786 bool isLoadingDyninstLib; // true iff we are currently loading dyninst lib
788 // the next two variables are used when we are loading dyninstlib -- currently
790 // They are used by the special inferior RPC that makes the call to load the
791 // library -- we use a special inferior RPC because the regular RPC assumes
792 // that the inferior heap already exists, which is not true if libdyninstRT
793 // has not been loaded yet.
794 char savedData[LOAD_DYNINST_BUF_SIZE];
798 const process *parent; /* parent of this process */
799 image *symbols; /* information related to the process */
800 int pid; /* id of this process */
803 time64 previous; // This is being used to avoid time going backwards in
804 // getInferiorProcessCPUtime. We can't use a static variable
805 // inside this procedure because there is one previous for
806 // each process - naim 5/28/97
808 // New components of the conceptual "inferior heap"
809 fastInferiorHeapMgr inferiorHeapMgr;
811 superTable theSuperTable;
813 #ifdef sparc_sun_sunos4_1_3
822 const superTable &getTable() const {
823 return theSuperTable;
825 superTable &getTable() {
826 return theSuperTable;
829 trampTableEntry trampTable[TRAMPTABLESZ];
830 unsigned trampTableItems;
832 unsigned currentPC() {
836 else if (getActiveFrame(&fp, &pc)) {
837 currentPC_ = (unsigned) pc;
843 void setNewPC(unsigned newPC) {
848 inline int costAddr() const { return costAddr_; } // why an integer?
849 void getObservedCostAddr();
851 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
852 bool uninstallMutations();
853 bool reinstallMutations();
854 #endif /* BPATCH_SET_MUTATIONS_ACTIVE */
857 bool createdViaAttach;
858 // set in the ctor. True iff this process was created with an attach,
859 // as opposed to being fired up by paradynd. On fork, has the value of
860 // the parent process. On exec, no change.
861 // This vrble is important because it tells us what to do when we exit.
862 // If we created via attach, we should (presumably) detach but not fry
863 // the application; otherwise, a kill(pid, 9) is called for.
864 // the following 2 are defined only if 'createdViaAttach' is true; action is taken
865 // on these vrbles once DYNINSTinit completes.
867 bool wasRunningWhenAttached;
868 bool needToContinueAfterDYNINSTinit;
873 // for processing observed cost (see method processCost())
874 int64 cumObsCost; // in cycles
875 unsigned lastObsCostLow; // in cycles
877 int costAddr_; // why an integer?
878 bool execed_; // true if this process does an exec...set in handleExec
880 // deal with system differences for ptrace
881 bool writeDataSpace_(void *inTracedProcess, int amount, const void *inSelf);
882 bool readDataSpace_(const void *inTracedProcess, int amount, void *inSelf);
884 bool writeTextWord_(caddr_t inTracedProcess, int data);
885 bool writeTextSpace_(void *inTracedProcess, int amount, const void *inSelf);
886 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
887 bool readTextSpace_(void *inTracedProcess, int amount, const void *inSelf);
890 bool continueProc_();
891 #ifdef BPATCH_LIBRARY
892 bool terminateProc_();
894 bool dumpCore_(const string coreFile);
896 #ifdef BPATCH_LIBRARY
897 bool API_detach_(const bool cont); // XXX Should eventually replace detach_()
899 bool attach_(); // low-level attach; called by attach() (formerly OS::osAttach())
900 bool stop_(); // formerly OS::osStop
903 bool loopUntilStopped();
905 // returns true iff ok to do a ptrace; false (and prints a warning) if not
908 int proc_fd; // file descriptor for platforms that use /proc file system.
910 dynamic_linking *dyn; // platform specific dynamic linking routines & data
912 bool dynamiclinking; // if true this a.out has a .dynamic section
913 vector<shared_object *> *shared_objects; // list of dynamically linked libs
915 // The set of all functions and modules from the shared objects that show
916 // up on the Where axis (both instrumentable and uninstrumentable due to
917 // exclude_lib or exclude_func), and all the functions from the a.out that
918 // are between DYNINSTStart and DYNINSTend
919 // TODO: these lists for a.out functions and modules should be handled the
920 // same way as for shared object functions and modules
921 vector<function_base *> *all_functions;
922 vector<module *> *all_modules;
924 // these are a restricted set of functions and modules which are those
925 // from the a.out and shared objects that are instrumentable (not excluded
926 // through the mdl "exclude_lib" or "exclude_func" option)
927 // "excluded" now means never able to instrument
928 vector<module *> *some_modules;
929 vector<function_base *> *some_functions;
930 bool waiting_for_resources; // true if waiting for resourceInfoResponse
931 pd_Function *signal_handler; // signal handler function (for stack walking)
933 function_base *mainFunction; // the main function for this process,
934 // this is usually, but not always, main
937 // needToAddALeafFrame: returns true if the between the current frame
938 // and the next frame there is a leaf function (this occurs when the
939 // current frame is the signal handler)
940 bool needToAddALeafFrame(Frame current_frame, Address &leaf_pc);
942 // hasBeenBound: returns true if the runtime linker has bound the
943 // function symbol corresponding to the relocation entry in at the address
944 // specified by entry and base_addr. If it has been bound, then the callee
945 // function is returned in "target_pdf", else it returns false.
946 bool hasBeenBound(const relocationEntry entry, pd_Function *&target_pdf,
949 // findpdFunctionIn: returns the function which contains this address
950 // This routine checks both the a.out image and any shared object images
952 pd_Function *findpdFunctionIn(Address adr);
954 bool isRunning_() const;
955 // needed to initialize the 'wasRunningWhenAttached' member vrble. Determines
956 // whether the process is running by doing a low-level OS check, not by checking
957 // member vrbles like status_. May assume that process::attach() has already run,
958 // but can't assume anything else. May barf with a not-yet-implemented error on a
959 // given platform if the platform doesn't yet support attaching to a running process.
960 // But there's no reason why we shouldn't be able to implement this on any platform;
961 // after all, the output from the "ps" command can be used (T --> return false,
962 // S or R --> return true, other --> return ?)
964 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
965 mutationList beforeMutationList, afterMutationList;
967 bool saveOriginalInstructions(Address addr, int size);
968 bool writeMutationList(mutationList &list);
971 #if defined(sparc_sun_solaris2_4) || defined(i386_unknown_solaris2_5) || defined(i386_unknown_linux2_0)
972 // some very useful items gathered from /proc (initialized in attach() [solaris.C],
973 // as soon as /proc fd is opened)
974 string argv0; // argv[0] of program, at the time it started up
975 string pathenv; // path env var of program, at the time it started up
976 string cwdenv; // curr working directory of program, at the time it started up
978 // string fullPathToExecutable_;
979 // very useful, especially on attach (need this to parse the symbol table)
982 const string &getArgv0() const {return argv0;}
983 const string &getPathEnv() const {return pathenv;}
984 const string &getCwdEnv() const {return cwdenv;}
988 process *createProcess(const string file, vector<string> argv, vector<string> envp, const string dir);
989 bool attachProcess(const string &progpath, int pid, int afterAttach
990 #ifdef BPATCH_LIBRARY
991 , process *&newProcess
995 void handleProcessExit(process *p, int exitStatus);
997 unsigned inferiorMalloc(process *proc, int size, inferiorHeapType type);
998 void inferiorFree(process *proc, unsigned pointer, inferiorHeapType type,
999 const vector<unsigVecType> &pointsToCheck);
1001 extern resource *machineResource;
1007 bool uppermostFrame;
1011 // formerly getActiveStackFrameInfo
1013 Frame(int theFrame, int thePc, bool theUppermost) {
1014 frame_ = theFrame; pc_ = thePc;
1015 uppermostFrame = theUppermost;
1018 int getPC() const { return pc_; }
1019 int getFramePtr(){ return frame_;}
1020 bool isLastFrame() const {
1021 if ((pc_ == 0)||(frame_ == 0))
1027 Frame getPreviousStackFrameInfo(process *proc) const;
1030 extern vector<process *> processVec;