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.
44 int pvmputenv (const char *);
49 #include "util/h/headers.h"
50 #include "dyninstAPI/src/symtab.h"
51 #include "dyninstAPI/src/pdThread.h"
52 #include "dyninstAPI/src/process.h"
53 #include "dyninstAPI/src/util.h"
54 #include "dyninstAPI/src/inst.h"
55 #include "dyninstAPI/src/instP.h"
56 #include "dyninstAPI/src/dyninstP.h"
57 #include "dyninstAPI/src/os.h"
58 #include "paradynd/src/showerror.h"
59 #include "dyninstAPI/src/dynamiclinking.h"
60 // #include "paradynd/src/mdld.h"
62 #ifndef BPATCH_LIBRARY
63 #include "rtinst/h/rtinst.h"
64 #include "rtinst/h/trace.h"
65 #include "paradynd/src/perfStream.h"
66 #include "paradynd/src/costmetrics.h"
67 #include "paradynd/src/mdld.h"
68 #include "paradynd/src/main.h"
71 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
72 extern void generateMTpreamble(char *insn, unsigned &base, process *proc);
75 #include "util/h/debugOstream.h"
77 #ifdef ATTACH_DETACH_DEBUG
78 debug_ostream attach_cerr(cerr, true);
80 debug_ostream attach_cerr(cerr, false);
83 #ifdef INFERIOR_RPC_DEBUG
84 debug_ostream inferiorrpc_cerr(cerr, true);
86 debug_ostream inferiorrpc_cerr(cerr, false);
89 #ifdef SHM_SAMPLING_DEBUG
90 debug_ostream shmsample_cerr(cerr, true);
92 debug_ostream shmsample_cerr(cerr, false);
95 #ifdef FORK_EXEC_DEBUG
96 debug_ostream forkexec_cerr(cerr, true);
98 debug_ostream forkexec_cerr(cerr, false);
102 debug_ostream metric_cerr(cerr, true);
104 debug_ostream metric_cerr(cerr, false);
108 debug_ostream signal_cerr(cerr, true);
110 debug_ostream signal_cerr(cerr, false);
113 #ifdef SHAREDOBJ_DEBUG
114 debug_ostream sharedobj_cerr(cerr, true);
116 debug_ostream sharedobj_cerr(cerr, false);
119 #define FREE_WATERMARK (hp->totalFreeMemAvailable/2)
120 #define SIZE_WATERMARK 100
121 static const timeStamp MAX_WAITING_TIME=10.0;
122 static const timeStamp MAX_DELETING_TIME=2.0;
123 unsigned inferiorMemAvailable=0;
125 unsigned activeProcesses; // number of active processes
126 vector<process*> processVec;
127 string process::programName;
128 string process::pdFlavor;
129 vector<string> process::arg_list;
131 process *findProcess(int pid) { // make a public static member fn of class process
132 unsigned size=processVec.size();
133 for (unsigned u=0; u<size; u++)
134 if (processVec[u] && processVec[u]->getPid() == pid)
135 return processVec[u];
140 static unsigned numIntCounters=100000; // rather arbitrary; can we do better?
141 static unsigned numWallTimers =100000; // rather arbitrary; can we do better?
142 static unsigned numProcTimers =100000; // rather arbitrary; can we do better?
145 bool waitingPeriodIsOver()
147 static timeStamp previous=0;
152 previous=getCurrentTime(false);
156 current=getCurrentTime(false);
157 if ( (current-previous) > MAX_WAITING_TIME ) {
158 previous=getCurrentTime(false);
165 Frame::Frame(process *proc) {
168 proc->getActiveFrame(&frame_, &pc_);
170 uppermostFrame = true;
173 Frame Frame::getPreviousStackFrameInfo(process *proc) const {
175 // no prev frame exists; must return frame with 0 pc value otherwise
176 // will never break out of loop in walkStack()
177 Frame fake_frame(0,0,false);
184 Frame result(0, 0, false);
185 if (proc->readDataFromFrame(frame_, &fp, &rtn, uppermostFrame)) {
194 #if !defined(i386_unknown_nt4_0)
195 // Windows NT has its own version of the walkStack function in pdwinnt.C
196 // Note: it may not always be possible to do a correct stack walk.
197 // If it can't do a complete walk, the function should return an empty
198 // vector, which means that there was an error, and we can't walk the stack.
199 vector<Address> process::walkStack(bool noPause)
202 bool needToCont = noPause ? false : (status() == running);
204 if (!noPause && !pause()) {
205 // pause failed...give up
206 cerr << "walkStack: pause failed" << endl;
210 Address sig_addr = 0;
213 const image *sig_image = (signal_handler->file())->exec();
214 if(getBaseAddress(sig_image, sig_addr)){
215 sig_addr += signal_handler->getAddress(this);
217 sig_addr = signal_handler->getAddress(this);
219 sig_size = signal_handler->size();
220 // printf("signal_handler = %s size = %d addr = 0x%x\n",
221 // (signal_handler->prettyName()).string_of(),sig_size,sig_addr);
225 Frame currentFrame(this);
226 while (!currentFrame.isLastFrame()) {
227 Address next_pc = currentFrame.getPC();
228 // printf("currentFrame pc = %d\n",next_pc);
230 // is this pc in the signal_handler function?
231 if(signal_handler && (next_pc >= sig_addr)
232 && (next_pc < (sig_addr+sig_size))){
233 // check to see if a leaf function was executing when the signal
234 // handler was called. If so, then an extra frame should be added
235 // for the leaf function...the call to getPreviousStackFrameInfo
236 // will get the function that called the leaf function
238 if(this->needToAddALeafFrame(currentFrame,leaf_pc)){
242 currentFrame = currentFrame.getPreviousStackFrameInfo(this);
244 pcs += currentFrame.getPC();
246 if (!noPause && needToCont) {
247 if (!continueProc()){
248 cerr << "walkStack: continueProc failed" << endl;
255 bool isFreeOK(process *proc, const disabledItem &disItem, vector<Address> &pcs) {
256 const unsigned disItemPointer = disItem.getPointer();
257 const inferiorHeapType disItemHeap = disItem.getHeapType();
259 #if defined(hppa1_1_hp_hpux)
260 if (proc->freeNotOK) return(false);
264 if (!proc->heaps[disItemHeap].heapActive.find(disItemPointer, ptr)) {
265 sprintf(errorLine,"Warning: attempt to free not defined heap entry %x (pid=%d, heapActive.size()=%d)\n", disItemPointer, proc->getPid(), proc->heaps[disItemHeap].heapActive.size());
267 //showErrorCallback(67, (const char *)errorLine);
273 sprintf(errorLine, "isFreeOK called on 0x%x\n", ptr->addr);
277 const vector<unsigVecType> &disItemPoints = disItem.getPointsToCheck();
278 const unsigned disItemNumPoints = disItemPoints.size();
280 for (unsigned int j=0;j<disItemNumPoints;j++) {
281 for (unsigned int k=0;k<disItemPoints[j].size();k++) {
282 unsigned pointer = disItemPoints[j][k];
284 if (disItemHeap == dataHeap)
285 sprintf(errorLine, "checking DATA pointer 0x%x\n", pointer);
287 sprintf(errorLine, "checking TEXT pointer 0x%x\n", pointer);
291 const dictionary_hash<unsigned, heapItem*> &heapActivePart =
292 proc->splitHeaps ? proc->heaps[textHeap].heapActive :
293 proc->heaps[dataHeap].heapActive;
296 if (!heapActivePart.find(pointer, np)) { // fills in "np" if found
298 sprintf(errorLine, "something freed addr 0x%x from us\n", pointer);
303 // This point was deleted already and we don't need it anymore in
306 const int size=disItemPoints[j].size();
307 disItemPoints[j][k] = disItemPoints[j][size-1];
308 disItemPoints[j].resize(size-1);
310 // need to make sure we check the next item too
315 if ( (ptr->addr >= np->addr) &&
316 (ptr->addr <= (np->addr + np->length)) )
320 sprintf(errorLine,"*** TEST *** IN isFreeOK: (1) we found 0x%x in our inst. range!\n",ptr->addr);
327 for (unsigned int l=0;l<pcs.size();l++) {
329 if ((pcs[l] >= ptr->addr) &&
330 (pcs[l] <= (ptr->addr + ptr->length)))
334 sprintf(errorLine,"*** TEST *** IN isFreeOK: (2) we found 0x%x in our inst. range!\n", ptr->addr);
341 if ( ((pcs[l] >= np->addr) && (pcs[l] <= (np->addr + np->length))) )
345 sprintf(errorLine,"*** TEST *** IN isFreeOK: (3) we found PC in our inst. range!\n");
359 // This procedure will try to compact the framented memory available in
360 // heapFree. This is an emergency procedure that will be called if we
361 // are running out of memory to insert instrumentation - naim
363 void inferiorFreeCompact(inferiorHeap *hp)
367 size = hp->heapFree.size();
371 logLine("***** Trying to compact freed memory...\n");
375 np = hp->heapFree[i];
377 sprintf(errorLine,"***** Checking address=%d\n",ALIGN_TO_WORDSIZE(np->addr+np->length));
380 for (j=0; j < size; j++) {
382 if ( (np->addr+np->length)==(hp->heapFree[j])->addr )
384 np->length += (hp->heapFree[j])->length;
385 hp->heapFree[j] = hp->heapFree[size-1];
386 hp->heapFree.resize(size-1);
387 size = hp->heapFree.size();
389 sprintf(errorLine,"***** Compacting free memory (%d bytes, i=%d, j=%d, heapFree.size=%d)\n",np->length,i,j,size);
400 for (i=0;i<hp->disabledList.size();i++) {
401 for (j=i+1;j<hp->disabledList.size();j++) {
402 if ( (hp->disabledList[i]).getPointer() ==
403 (hp->disabledList[j]).getPointer() ) {
404 sprintf(errorLine,"***** ERROR: address 0x%x appears more than once\n",(hp->disabledList[j]).getPointer());
412 logLine("***** Compact memory procedure END...\n");
416 void inferiorFreeDefered(process *proc, inferiorHeap *hp, bool runOutOfMem)
420 vector<disabledItem> *disList;
421 timeStamp initTime, maxDelTime;
423 pcs = proc->walkStack();
425 #if defined(i386_unknown_nt4_0)
426 // It may not always be possible to get a correct stack walk.
427 // If walkStack fails, it returns an empty vector. In this
428 // case, we assume that it is not safe to delete anything
433 // this is a while loop since we don't update i if an item is deleted.
434 disList = &hp->disabledList;
436 maxDelTime = MAX_DELETING_TIME*2.0;
437 sprintf(errorLine,"Emergency attempt to free memory (pid=%d). Please, wait...\n",proc->getPid());
440 sprintf(errorLine,"***** disList.size() = %d\n",disList->size());
445 maxDelTime = MAX_DELETING_TIME;
446 initTime=getCurrentTime(false);
447 while ( (i < disList->size()) &&
448 ((getCurrentTime(false)-initTime) < maxDelTime) )
450 disabledItem &item = (*disList)[i];
451 if (isFreeOK(proc,item,pcs)) {
453 unsigned pointer = item.getPointer();
454 if (!hp->heapActive.find(pointer,np)) {
455 showErrorCallback(96,"");
460 if (np->status != HEAPallocated) {
461 sprintf(errorLine,"Attempt to free already freed heap entry %x\n", pointer);
463 showErrorCallback(67, (const char *)errorLine);
466 np->status = HEAPfree;
468 // remove from active list.
469 hp->heapActive.undef(pointer);
472 sprintf(errorLine,"inferiorFreeDefered: deleting 0x%x from heap\n",pointer);
477 hp->freed += np->length;
479 // updating disabledList
480 hp->disabledList[i]=hp->disabledList[hp->disabledList.size()-1];
481 hp->disabledList.resize(hp->disabledList.size()-1);
482 hp->disabledListTotalMem -= np->length;
483 hp->totalFreeMemAvailable += np->length;
484 inferiorMemAvailable = hp->totalFreeMemAvailable;
491 void process::initInferiorHeap(bool initTextHeap)
493 assert(this->symbols);
497 hp = &this->heaps[textHeap];
499 hp = &this->heaps[dataHeap];
502 heapItem *np = new heapItem;
505 np->addr = findInternalAddress("DYNINSTtext", true,err);
510 np->addr = findInternalAddress(INFERIOR_HEAP_BASE, true, err);
514 np->length = SYN_INST_BUF_SIZE;
515 np->status = HEAPfree;
517 // make the heap double-word aligned
518 Address base = np->addr & ~0x1f;
519 Address diff = np->addr - base;
521 np->addr = base + 32;
522 np->length -= (32 - diff);
525 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
527 hp->size = np->length;
528 #endif /* BPATCH_SET_MUTATIONS_ACTIVE */
530 hp->totalFreeMemAvailable = np->length;
531 inferiorMemAvailable = hp->totalFreeMemAvailable;
533 // need to clear everything here, since this function may be called to
535 hp->heapActive.clear();
536 hp->heapFree.resize(0);
538 hp->disabledList.resize(0);
539 hp->disabledListTotalMem = 0;
543 // create a new inferior heap that is a copy of src. This is used when a process
544 // we are tracing forks.
545 inferiorHeap::inferiorHeap(const inferiorHeap &src):
546 heapActive(addrHash16)
548 for (unsigned u1 = 0; u1 < src.heapFree.size(); u1++) {
549 heapFree += new heapItem(src.heapFree[u1]);
552 vector<heapItem *> items = src.heapActive.values();
553 for (unsigned u2 = 0; u2 < items.size(); u2++) {
554 heapActive[items[u2]->addr] = new heapItem(items[u2]);
557 for (unsigned u3 = 0; u3 < src.disabledList.size(); u3++) {
558 disabledList += src.disabledList[u3];
560 disabledListTotalMem = src.disabledListTotalMem;
561 totalFreeMemAvailable = src.totalFreeMemAvailable;
562 inferiorMemAvailable = totalFreeMemAvailable;
567 void printHeapFree(process *proc, inferiorHeap *hp, int size)
569 for (unsigned i=0; i < hp->heapFree.size(); i++) {
570 sprintf(errorLine,"***** (pid=%d) i=%d, addr=%d, length=%d, heapFree.size()=%d, size=%d\n",proc->getPid(),i,(hp->heapFree[i])->addr,(hp->heapFree[i])->length,hp->heapFree.size(),size);
577 // This function will return the index corresponding to the next position
578 // available in heapFree.
580 bool findFreeIndex(inferiorHeap *hp, int size, unsigned *index)
582 bool foundFree=false;
585 for (unsigned i=0; i < hp->heapFree.size(); i++) {
586 length = (hp->heapFree[i])->length;
587 if (length >= size) {
600 unsigned inferiorMalloc(process *proc, int size, inferiorHeapType type)
603 heapItem *np=NULL, *newEntry = NULL;
606 /* round to next cache line size */
607 /* 32 bytes on a SPARC */
608 size = (size + 0x1f) & ~0x1f;
610 if ((type == textHeap) && (proc->splitHeaps)) {
611 hp = &proc->heaps[textHeap];
613 hp = &proc->heaps[dataHeap];
616 bool secondChance=false;
618 if (!findFreeIndex(hp,size,&foundIndex)) {
621 sprintf(errorLine,"==> TEST <== In inferiorMalloc: heap overflow, calling inferiorFreeDefered for a second chance...\n");
625 inferiorFreeDefered(proc, hp, true);
626 inferiorFreeCompact(hp);
630 if (secondChance && !findFreeIndex(hp,size,&foundIndex)) {
633 printHeapFree(proc,hp,size);
636 sprintf(errorLine, "***** Inferior heap overflow: %d bytes freed, %d bytes requested\n", hp->freed, size);
638 showErrorCallback(66, (const char *) errorLine);
644 // We must have found a free position in heapFree
647 np = hp->heapFree[foundIndex];
649 if (np->length != size) {
651 newEntry = new heapItem;
652 newEntry->length = np->length - size;
653 newEntry->addr = np->addr + size;
654 hp->totalFreeMemAvailable -= size;
655 inferiorMemAvailable = hp->totalFreeMemAvailable;
656 // overwrite the old entry
657 hp->heapFree[foundIndex] = newEntry;
662 unsigned i = hp->heapFree.size();
663 // copy the last element over this element
664 hp->heapFree[foundIndex] = hp->heapFree[i-1];
665 hp->heapFree.resize(i-1);
669 np->status = HEAPallocated;
672 hp->heapActive[np->addr] = np;
674 // make sure its a valid pointer.
680 void inferiorFree(process *proc, unsigned pointer, inferiorHeapType type,
681 const vector<unsigVecType> &pointsToCheck)
683 inferiorHeapType which = (type == textHeap && proc->splitHeaps) ? textHeap : dataHeap;
684 inferiorHeap *hp = &proc->heaps[which];
687 if (!hp->heapActive.find(pointer, np)) {
688 showErrorCallback(96,"");
693 disabledItem newItem(pointer, which, pointsToCheck);
696 for (unsigned i=0;i<hp->disabledList.size();i++) {
697 if (hp->disabledList[i].getPointer() == pointer) {
698 sprintf(errorLine,"***** ERROR, pointer 0x%x already defined in disabledList\n",pointer);
704 hp->disabledList += newItem;
705 hp->disabledListTotalMem += np->length;
708 sprintf(errorLine,"==> TEST <== In inferiorFree: disabledList has %d items, %d bytes, and FREE_WATERMARK is %d\n",hp->disabledList.size(),hp->disabledListTotalMem,FREE_WATERMARK);
710 for (unsigned i=0; i < hp->disabledList.size(); i++) {
711 sprintf(errorLine, " %x is on list\n", hp->disabledList[i].pointer);
717 // If the size of the disabled instrumentation list is greater than
718 // half of the size of the heapFree list, then we attempt to free
719 // all the defered requests. In my opinion, this seems to be a good
720 // time to proceed with the defered delete since this is an expensive
721 // procedure and should not be executed often - naim 03/19/96
723 if (((hp->disabledListTotalMem > FREE_WATERMARK) ||
724 (hp->disabledList.size() > SIZE_WATERMARK)) && waitingPeriodIsOver())
729 static timeStamp t3=0.0;
730 static timeStamp totalTime=0.0;
731 static timeStamp worst=0.0;
732 static int counter=0;
733 t1=getCurrentTime(false);
736 inferiorFreeDefered(proc, hp, false);
739 t2=getCurrentTime(false);
743 if ((t2-t1) > worst) worst=t2-t1;
744 if ((float)(t2-t1) > 1.0) {
745 sprintf(errorLine,">>>> TEST <<<< (pid=%d) inferiorFreeDefered took %5.2f secs, avg=%5.2f, worst=%5.2f, heapFree=%d, heapActive=%d, disabledList=%d, last call=%5.2f\n", proc->getPid(),(float) (t2-t1), (float) (totalTime/counter), (float)worst, hp->heapFree.size(), hp->heapActive.size(), hp->disabledList.size(), (float)(t1-t3));
755 // initializes all DYNINST lib stuff: init the inferior heap and check for
757 // This is only called after we get the first breakpoint (SIGTRAP), because
758 // the DYNINST lib can be dynamically linked (currently it is only dynamically
759 // linked on Windows NT)
760 bool process::initDyninstLib() {
762 #if defined(i386_unknown_nt4_0)
764 Kludge for Windows NT: we need to call waitProcs here so that
765 we can load libdyninstRT when we attach to an already running
766 process. The solution to avoid this kludge is to divide
767 attachProcess in two parts: first we attach to a process,
768 and later, after libdyninstRT has been loaded,
769 we install the call to DYNINSTinit.
772 // libDyninstRT should already be loaded when we get here,
773 // except if the process was created via attach
774 if (createdViaAttach) {
775 // need to set reachedFirstBreak to false here, so that
776 // libdyninstRT gets loaded in waitProcs.
777 reachedFirstBreak = false;
778 while (!hasLoadedDyninstLib) {
783 assert(hasLoadedDyninstLib);
787 extern vector<sym_data> syms_to_find;
788 if (!heapIsOk(syms_to_find))
791 initInferiorHeap(false);
793 initInferiorHeap(true);
801 // Process "normal" (non-attach, non-fork) ctor, for when a new process
802 // is fired up by paradynd itself.
805 process::process(int iPid, image *iImage, int iTraceLink, int iIoLink
808 const vector<fastInferiorHeapMgr::oneHeapStats> &iShmHeapStats
812 pid(iPid) // needed in fastInferiorHeap ctors below
815 inferiorHeapMgr(theShmKey, iShmHeapStats, iPid),
817 iShmHeapStats[0].maxNumElems,
818 iShmHeapStats[1].maxNumElems,
819 iShmHeapStats[2].maxNumElems)
822 hasBootstrapped = false;
823 save_exitset_ptr = NULL;
825 // the next two variables are used only if libdyninstRT is dynamically linked
826 hasLoadedDyninstLib = false;
827 isLoadingDyninstLib = false;
829 reachedFirstBreak = false; // haven't yet seen first trap
830 createdViaAttach = false;
833 mainFunction = NULL; // set in platform dependent function heapIsOk
836 continueAfterNextStop_ = false;
837 deferredContinueProc = false;
839 #ifndef BPATCH_LIBRARY
840 string buffer = string(pid) + string("_") + getHostName();
841 rid = resource::newResource(processResource, // parent
842 (void*)this, // handle
843 nullString, // abstraction
844 iImage->name(), // process name
845 0.0, // creation time
846 buffer, // unique name (?)
847 MDL_T_STRING, // mdl type (?)
863 memset(trampTable, 0, sizeof(trampTable));
867 dynamiclinking = false;
868 dyn = new dynamic_linking;
874 waiting_for_resources = false;
879 #ifdef sparc_sun_sunos4_1_3
880 kvmHandle = kvm_open(0, 0, 0, O_RDONLY, 0);
881 if (kvmHandle == NULL) {
882 perror("could not map child's uarea; kvm_open");
886 // childUareaPtr = tryToMapChildUarea(iPid);
887 childUareaPtr = NULL;
893 #if defined(rs6000_ibm_aix3_2) || defined(rs6000_ibm_aix4_1)
894 // XXXX - move this to a machine dependant place.
896 // create a seperate text heap.
897 //initInferiorHeap(true);
901 traceLink = iTraceLink;
904 RPCs_waiting_for_syscall_to_complete = false;
906 // attach to the child process (machine-specific implementation)
907 attach(); // error check?
911 // Process "attach" ctor, for when paradynd is attaching to an already-existing
915 process::process(int iPid, image *iSymbols,
916 int afterAttach // 1 --> pause, 2 --> run, 0 --> leave as is
919 const vector<fastInferiorHeapMgr::oneHeapStats> &iShmHeapStats
926 inferiorHeapMgr(theShmKey, iShmHeapStats, iPid),
928 iShmHeapStats[0].maxNumElems,
929 iShmHeapStats[1].maxNumElems,
930 iShmHeapStats[2].maxNumElems)
933 RPCs_waiting_for_syscall_to_complete = false;
934 save_exitset_ptr = NULL;
936 hasBootstrapped = false;
937 reachedFirstBreak = true; // the initial trap of program entry was passed long ago...
938 createdViaAttach = true;
940 // the next two variables are used only if libdyninstRT is dynamically linked
941 hasLoadedDyninstLib = false;
942 isLoadingDyninstLib = false;
945 mainFunction = NULL; // set in platform dependent function heapIsOk
948 continueAfterNextStop_ = false;
949 deferredContinueProc = false;
951 #ifndef BPATCH_LIBRARY
952 string buffer = string(pid) + string("_") + getHostName();
953 rid = resource::newResource(processResource, // parent
954 (void*)this, // handle
955 nullString, // abstraction
957 0.0, // creation time
958 buffer, // unique name (?)
959 MDL_T_STRING, // mdl type (?)
975 memset(trampTable, 0, sizeof(trampTable));
979 dynamiclinking = false;
980 dyn = new dynamic_linking;
986 waiting_for_resources = false;
992 #if defined(rs6000_ibm_aix3_2) || defined(rs6000_ibm_aix4_1)
993 // XXXX - move this to a machine dependant place.
995 // create a seperate text heap.
996 //initInferiorHeap(true);
1000 traceLink = -1; // will be set later, when the appl runs DYNINSTinit
1002 ioLink = -1; // (ARGUABLY) NOT YET IMPLEMENTED...MAYBE WHEN WE ATTACH WE DON'T WANT
1003 // TO REDIRECT STDIO SO WE CAN LEAVE IT AT -1.
1005 // Now the actual attach...the moment we've all been waiting for
1007 attach_cerr << "process attach ctor: about to attach to pid " << getPid() << endl;
1009 // It is assumed that a call to attach() doesn't affect the running status
1010 // of the process. But, unfortunately, some platforms may barf if the
1011 // running status is anything except paused. (How to deal with this?)
1012 // Note that solaris in particular seems able to attach even if the process
1015 showErrorCallback(26, ""); // unable-to-attach
1019 wasRunningWhenAttached = isRunning_();
1021 // Note: we used to pause the program here, but not anymore.
1024 if (afterAttach == 0)
1025 needToContinueAfterDYNINSTinit = wasRunningWhenAttached;
1026 else if (afterAttach == 1)
1027 needToContinueAfterDYNINSTinit = false;
1028 else if (afterAttach == 2)
1029 needToContinueAfterDYNINSTinit = true;
1033 // Does attach() send a SIGTRAP, a la the initial SIGTRAP sent at the
1034 // end of exec? It seems that on some platforms it does; on others
1035 // it doesn't. Ick. On solaris, it doesn't.
1037 // note: we don't call getSharedObjects() yet; that happens once DYNINSTinit
1038 // finishes (handleStartProcess)
1042 // Process "fork" ctor, for when a process which is already being monitored by
1043 // paradynd executes the fork syscall.
1046 process::process(const process &parentProc, int iPid, int iTrace_fd
1049 void *applShmSegPtr,
1050 const vector<fastInferiorHeapMgr::oneHeapStats> &iShmHeapStats
1053 baseMap(ipHash) // could change to baseMap(parentProc.baseMap)
1056 inferiorHeapMgr(parentProc.inferiorHeapMgr,
1058 theShmKey, iShmHeapStats, iPid)
1059 ,theSuperTable(parentProc.getTable(),this)
1062 // This is the "fork" ctor
1064 RPCs_waiting_for_syscall_to_complete = false;
1065 save_exitset_ptr = NULL;
1067 hasBootstrapped = false;
1068 // The child of fork ("this") has yet to run DYNINSTinit.
1070 // the next two variables are used only if libdyninstRT is dynamically linked
1071 hasLoadedDyninstLib = false; // TODO: is this the right value?
1072 isLoadingDyninstLib = false;
1074 createdViaAttach = parentProc.createdViaAttach;
1075 wasRunningWhenAttached = true;
1076 needToContinueAfterDYNINSTinit = true;
1078 symbols = parentProc.symbols; // shouldn't a reference count also be bumped?
1079 mainFunction = parentProc.mainFunction;
1081 traceLink = iTrace_fd;
1083 ioLink = -1; // when does this get set?
1085 status_ = neonatal; // is neonatal right?
1086 continueAfterNextStop_ = false;
1087 deferredContinueProc = false;
1091 #ifndef BPATCH_LIBRARY
1092 string buffer = string(pid) + string("_") + getHostName();
1093 rid = resource::newResource(processResource, // parent
1094 (void*)this, // handle
1095 nullString, // abstraction
1096 parentProc.symbols->name(),
1097 0.0, // creation time
1098 buffer, // unique name (?)
1099 MDL_T_STRING, // mdl type (?)
1104 threads += new pdThread(this);
1105 parent = &parentProc;
1110 reachedFirstBreak = true; // initial TRAP has (long since) been reached
1112 splitHeaps = parentProc.splitHeaps;
1114 heaps[0] = inferiorHeap(parentProc.heaps[0]);
1115 heaps[1] = inferiorHeap(parentProc.heaps[1]);
1124 trampTableItems = 0;
1125 memset(trampTable, 0, sizeof(trampTable));
1129 dynamiclinking = parentProc.dynamiclinking;
1130 dyn = new dynamic_linking;
1131 *dyn = *parentProc.dyn;
1135 // make copy of parent's shared_objects vector
1136 if (parentProc.shared_objects) {
1137 shared_objects = new vector<shared_object*>;
1138 for (unsigned u1 = 0; u1 < parentProc.shared_objects->size(); u1++){
1140 new shared_object(*(*parentProc.shared_objects)[u1]);
1145 if (parentProc.all_functions) {
1146 all_functions = new vector<function_base *>;
1147 for (unsigned u2 = 0; u2 < parentProc.all_functions->size(); u2++)
1148 *all_functions += (*parentProc.all_functions)[u2];
1152 if (parentProc.all_modules) {
1153 all_modules = new vector<module *>;
1154 for (unsigned u3 = 0; u3 < parentProc.all_modules->size(); u3++)
1155 *all_modules += (*parentProc.all_modules)[u3];
1159 if (parentProc.some_modules) {
1160 some_modules = new vector<module *>;
1161 for (unsigned u4 = 0; u4 < parentProc.some_modules->size(); u4++)
1162 *some_modules += (*parentProc.some_modules)[u4];
1166 if (parentProc.some_functions) {
1167 some_functions = new vector<function_base *>;
1168 for (unsigned u5 = 0; u5 < parentProc.some_functions->size(); u5++)
1169 *some_functions += (*parentProc.some_functions)[u5];
1172 waiting_for_resources = false;
1173 signal_handler = parentProc.signal_handler;
1177 for (unsigned i=0; i<parentProc.threads.size(); i++) {
1178 threads += new pdThread(this,parentProc.threads[i]);
1182 #ifdef sparc_sun_sunos4_1_3
1183 childUareaPtr = NULL;
1185 // thread mapping table
1186 threadMap = new hashTable(parentProc.threadMap);
1189 if (!attach()) { // moved from ::forkProcess
1190 showErrorCallback(69, "Error in fork: cannot attach to child process");
1194 // would neonatal be more appropriate? Nah, we've reached the first trap
1198 void process::registerInferiorAttachedSegs(void *inferiorAttachedAtPtr) {
1199 shmsample_cerr << "process pid " << getPid() << ": welcome to register with inferiorAttachedAtPtr=" << inferiorAttachedAtPtr << endl;
1201 inferiorHeapMgr.registerInferiorAttachedAt(inferiorAttachedAtPtr);
1202 theSuperTable.setBaseAddrInApplic(0,(intCounter*) inferiorHeapMgr.getSubHeapInApplic(0));
1203 theSuperTable.setBaseAddrInApplic(1,(tTimer*) inferiorHeapMgr.getSubHeapInApplic(1));
1204 theSuperTable.setBaseAddrInApplic(2,(tTimer*) inferiorHeapMgr.getSubHeapInApplic(2));
1209 extern bool forkNewProcess(string file, string dir, vector<string> argv,
1210 vector<string>envp, string inputFile, string outputFile,
1211 int &traceLink, int &ioLink,
1213 int &procHandle, int &thrHandle);
1216 * Create a new instance of the named process. Read the symbols and start
1219 process *createProcess(const string File, vector<string> argv, vector<string> envp, const string dir = "")
1221 // prepend the directory (if any) to the file, unless the filename
1224 if (!file.prefixed_by("/") && dir.length() > 0)
1225 file = dir + "/" + file;
1227 #ifdef BPATCH_LIBRARY
1231 // check for I/O redirection in arg list.
1233 for (unsigned i1=0; i1<argv.size(); i1++) {
1234 if (argv[i1] == "<") {
1235 inputFile = argv[i1+1];
1236 for (unsigned j=i1+2, k=i1; j<argv.size(); j++, k++)
1238 argv.resize(argv.size()-2);
1241 // TODO -- this assumes no more than 1 of each "<", ">"
1243 for (unsigned i2=0; i2<argv.size(); i2++) {
1244 if (argv[i2] == ">") {
1245 outputFile = argv[i2+1];
1246 for (unsigned j=i2+2, k=i2; j<argv.size(); j++, k++)
1248 argv.resize(argv.size()-2);
1251 #endif /* BPATCH_LIBRARY */
1260 if (!forkNewProcess(file, dir, argv, envp, inputFile, outputFile,
1261 traceLink, ioLink, pid, tid, procHandle, thrHandle)) {
1262 // forkNewProcess is resposible for displaying error messages
1266 #if defined(rs6000_ibm_aix3_2) || defined(rs6000_ibm_aix4_1)
1267 extern bool establishBaseAddrs(int pid, int &status, bool waitForTrap);
1270 if (!establishBaseAddrs(pid, status, true)) {
1275 #ifndef BPATCH_LIBRARY
1276 // NEW: We bump up batch mode here; the matching bump-down occurs after shared objects
1277 // are processed (after receiving the SIGSTOP indicating the end of running
1278 // DYNINSTinit; more specifically, procStopFromDYNINSTinit().
1279 // Prevents a diabolical w/w deadlock on solaris --ari
1280 tp->resourceBatchMode(true);
1281 #endif /* BPATCH_LIBRARY */
1283 image *img = image::parseImage(file);
1285 // For better error reporting, two failure return values would be useful
1286 // One for simple error like because-file-not-because
1287 // Another for serious errors like found-but-parsing-failed (internal error;
1288 // please report to paradyn@cs.wisc.edu)
1290 string msg = string("Unable to parse image: ") + file;
1291 showErrorCallback(68, msg.string_of());
1292 // destroy child process
1299 statusLine("initializing process data structures");
1302 vector<fastInferiorHeapMgr::oneHeapStats> theShmHeapStats(3);
1303 theShmHeapStats[0].elemNumBytes = sizeof(intCounter);
1304 theShmHeapStats[0].maxNumElems = numIntCounters;
1306 theShmHeapStats[1].elemNumBytes = sizeof(tTimer);
1307 theShmHeapStats[1].maxNumElems = numWallTimers;
1309 theShmHeapStats[2].elemNumBytes = sizeof(tTimer);
1310 theShmHeapStats[2].maxNumElems = numProcTimers;
1313 process *ret = new process(pid, img, traceLink, ioLink
1315 , 7000, // shm seg key to try first
1319 // change this to a ctor that takes in more args
1326 #ifndef BPATCH_LIBRARY
1327 if (!costMetric::addProcessToAll(ret))
1330 // find the signal handler function
1331 ret->findSignalHandler(); // should this be in the ctor?
1333 // initializing vector of threads - thread[0] is really the
1336 #if defined(i386_unknown_nt4_0)
1337 ret->threads += new pdThread(ret, tid, (handleT)thrHandle);
1339 ret->threads += new pdThread(ret);
1342 // initializing hash table for threads. This table maps threads to
1343 // positions in the superTable - naim 4/14/97
1344 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
1345 ret->threadMap = new hashTable(MAX_NUMBER_OF_THREADS,1,0);
1348 // we use this flag to solve race condition between inferiorRPC and
1349 // continueProc message from paradyn - naim
1350 ret->deferredContinueProc = false;
1352 ret->numOfActCounters_is=0;
1353 ret->numOfActProcTimers_is=0;
1354 ret->numOfActWallTimers_is=0;
1356 #if defined(rs6000_ibm_aix3_2) || defined(rs6000_ibm_aix4_1)
1357 // XXXX - this is a hack since establishBaseAddrs needed to wait for
1359 // We really need to move most of the above code (esp parse image)
1360 // to the TRAP signal handler. The problem is that we don't
1361 // know the base addresses until we get the load info via ptrace.
1362 // In general it is even harder, since dynamic libs can be loaded
1364 extern int handleSigChild(int pid, int status);
1366 (void) handleSigChild(pid, status);
1373 void process::DYNINSTinitCompletionCallback(process *theProc,
1374 void *, // user data
1375 unsigned // return value from DYNINSTinit
1377 attach_cerr << "Welcome to DYNINSTinitCompletionCallback" << endl;
1378 theProc->handleCompletionOfDYNINSTinit(true);
1382 bool attachProcess(const string &progpath, int pid, int afterAttach
1383 #ifdef BPATCH_LIBRARY
1384 , process *&newProcess
1387 // implementation of dynRPC::attach() (the igen call)
1388 // This is meant to be "the other way" to start a process (competes w/ createProcess)
1390 // progpath gives the full path name of the executable, which we use ONLY to
1391 // read the symbol table.
1393 // We try to make progpath optional, since given pid, we should be able to
1394 // calculate it with a clever enough search of the process' PATH, examining
1395 // its argv[0], examining its current directory, etc. /proc gives us this
1396 // information on solaris...not sure about other platforms...
1398 // possible values for afterAttach: 1 --> pause, 2 --> run, 0 --> leave as is
1400 attach_cerr << "welcome to attachProcess for pid " << pid << endl;
1402 // QUESTION: When we attach to a process, do we want to redirect its stdout/stderr
1403 // (like we do when we fork off a new process the 'usual' way)?
1404 // My first guess would be no. -ari
1405 // But although we may ignore the io, we still need the trace stream.
1407 // When we attach to a process, we don't fork...so this routine is much simpler
1408 // than its "competitor", createProcess() (above).
1410 // TODO: What about AIX establishBaseAddrs??? Do that now?
1412 string fullPathToExecutable = process::tryToFindExecutable(progpath, pid);
1413 if (!fullPathToExecutable.length())
1416 #ifndef BPATCH_LIBRARY
1417 tp->resourceBatchMode(true);
1418 // matching bump-down occurs in procStopFromDYNINSTinit().
1421 image *theImage = image::parseImage(fullPathToExecutable);
1422 if (theImage == NULL) {
1423 // two failure return values would be useful here, to differentiate
1424 // file-not-found vs. catastrophic-parse-error.
1425 string msg = string("Unable to parse image: ") + fullPathToExecutable;
1426 showErrorCallback(68, msg.string_of());
1427 return false; // failure
1431 vector<fastInferiorHeapMgr::oneHeapStats> theShmHeapStats(3);
1432 theShmHeapStats[0].elemNumBytes = sizeof(intCounter);
1433 theShmHeapStats[0].maxNumElems = numIntCounters;
1435 theShmHeapStats[1].elemNumBytes = sizeof(tTimer);
1436 theShmHeapStats[1].maxNumElems = numWallTimers;
1438 theShmHeapStats[2].elemNumBytes = sizeof(tTimer);
1439 theShmHeapStats[2].maxNumElems = numProcTimers;
1442 // NOTE: the actual attach happens in the process "attach" constructor:
1443 process *theProc = new process(pid, theImage, afterAttach
1445 ,7000, // shm seg key to try first
1451 // Note: it used to be that the attach ctor called pause()...not anymore...so
1452 // the process is probably running even as we speak.
1454 processVec += theProc;
1457 theProc->threads += new pdThread(theProc);
1458 theProc->initDyninstLib();
1460 #ifndef BPATCH_LIBRARY
1461 if (!costMetric::addProcessToAll(theProc))
1465 // find the signal handler function
1466 theProc->findSignalHandler(); // shouldn't this be in the ctor?
1468 // Now force DYNINSTinit() to be invoked, via inferiorRPC.
1469 string buffer = string("PID=") + string(pid) + ", running DYNINSTinit()...";
1470 statusLine(buffer.string_of());
1472 #ifdef BPATCH_LIBRARY
1473 newProcess = theProc;
1475 vector<AstNode*> the_args(2);
1477 the_args[0] = new AstNode(AstNode::Constant, (void*)3);
1478 the_args[1] = new AstNode(AstNode::Constant, (void*)getpid());
1479 #else /* BPATCH_LIBRARY */
1480 attach_cerr << "calling DYNINSTinit with args:" << endl;
1482 vector<AstNode*> the_args(3);
1485 the_args[0] = new AstNode(AstNode::Constant,
1486 (void*)(theProc->getShmKeyUsed()));
1487 attach_cerr << theProc->getShmKeyUsed() << endl;
1489 const unsigned shmHeapTotalNumBytes = theProc->getShmHeapTotalNumBytes();
1490 the_args[1] = new AstNode(AstNode::Constant,
1491 (void*)shmHeapTotalNumBytes);
1492 attach_cerr << shmHeapTotalNumBytes << endl;;
1494 // 2 dummy args when not shm sampling -- just make sure they're not both -1, which
1495 // would indicate that we're called from fork
1496 the_args[0] = new AstNode(AstNode::Constant, (void*)0);
1497 the_args[1] = new AstNode(AstNode::Constant, (void*)0);
1501 The third argument to DYNINSTinit is our (paradynd's) pid. It is used
1502 by DYNINSTinit to build the socket path to which it connects to in order
1503 to get the trace-stream connection. We make it negative to indicate
1504 to DYNINSTinit that it's being called from attach (sorry for that little
1505 kludge...if we didn't have it, we'd probably need to boost DYNINSTinit
1506 from 3 to 4 parameters).
1508 This socket is set up in controllerMainLoop (perfStream.C).
1510 the_args[2] = new AstNode(AstNode::Constant, (void*)(-1 * traceConnectInfo));
1511 attach_cerr << (-1* getpid()) << endl;
1512 #endif /* BPATCH_LIBRARY */
1514 AstNode *the_ast = new AstNode("DYNINSTinit", the_args);
1515 for (unsigned j=0;j<the_args.size();j++) removeAst(the_args[j]);
1517 theProc->postRPCtoDo(the_ast,
1518 true, // true --> don't try to update cost yet
1519 process::DYNINSTinitCompletionCallback, // callback routine
1522 // the rpc will be launched with a call to launchRPCifAppropriate()
1523 // in the main loop (perfStream.C).
1524 // DYNINSTinit() ends with a DYNINSTbreakPoint(), so we pick up
1525 // where we left off in the processing of the forwarded SIGSTOP signal.
1526 // In other words, there's lots more work to do, but since we can't do it until
1527 // DYNINSTinit has run, we wait until the SIGSTOP is forwarded.
1529 // Note: we used to pause() the process while attaching. Not anymore.
1530 // The attached process is running even as we speak. (Though we'll interrupt
1531 // it pretty soon when the inferior RPC of DYNINSTinit gets launched).
1533 return true; // successful
1537 bool process::doMajorShmSample(time64 theWallTime) {
1538 bool result = true; // will be set to false if any processAll() doesn't complete
1541 if (!theSuperTable.doMajorSample (theWallTime, 0))
1543 // inferiorProcessTimers used to take in a non-dummy process time as the
1544 // 2d arg, but it looks like that we need to re-read the process time for
1545 // each proc timer, at the time of sampling the timer's value, to avoid
1546 // ugly jagged spikes in histogram (i.e. to avoid incorrect sampled
1547 // values). Come to think of it: the same may have to be done for the
1550 const time64 theProcTime = getInferiorProcessCPUtime();
1552 // Now sample the observed cost.
1553 unsigned *costAddr = this->getObsCostLowAddrInParadyndSpace();
1554 const unsigned theCost = *costAddr; // WARNING: shouldn't we be using a mutex?!
1556 this->processCost(theCost, theWallTime, theProcTime);
1561 bool process::doMinorShmSample() {
1562 // Returns true if the minor sample has successfully completed all outstanding
1564 bool result = true; // so far...
1566 if (!theSuperTable.doMinorSample())
1573 extern void removeFromMetricInstances(process *);
1574 extern void disableAllInternalMetrics();
1576 void handleProcessExit(process *proc, int exitStatus) {
1577 if (proc->status() == exited)
1580 proc->Exited(); // updates status line
1581 if (proc->traceLink >= 0) {
1582 // We used to call processTraceStream(proc) here to soak up any last
1583 // messages but since it uses a blocking read, that doesn't seem like such
1585 //processTraceStream(proc);
1587 P_close(proc->traceLink);
1588 proc->traceLink = -1;
1590 if (proc->ioLink >= 0) {
1591 // We used to call processAppIO(proc) here to soak up any last
1592 // messages but since it uses a blocking read, that doesn't seem like such
1594 //processAppIO(proc);
1596 P_close(proc->ioLink);
1600 #ifndef BPATCH_LIBRARY
1601 // for each component mi of this process, remove it from all aggregate mi's it
1602 // belongs to. (And if the agg mi now has no components, fry it too.)
1603 // Also removes this proc from all cost metrics (but what about internal metrics?)
1604 removeFromMetricInstances(proc);
1609 #ifndef BPATCH_LIBRARY
1610 if (activeProcesses == 0)
1611 disableAllInternalMetrics();
1614 proc->detach(false);
1615 // after this, the process will continue to run (presumably, just to complete
1620 PDYN_reportSIGCHLD(proc->getPid(), exitStatus);
1624 // Perhaps these lines can be un-commented out in the future, but since
1625 // cleanUpAndExit() does the same thing, and it always gets called
1626 // (when paradynd detects that paradyn died), it's not really necessary
1628 // for (unsigned lcv=0; lcv < processVec.size(); lcv++)
1629 // if (processVec[lcv] == proc) {
1630 // delete proc; // destructor removes shm segments...
1631 // processVec[lcv] = NULL;
1637 process::forkProcess: called when a process forks, to initialize a new
1638 process object for the child.
1640 the variable childHasInstrumentation is true if the child process has the
1641 instrumentation of the parent. This is the common case.
1642 On some platforms (AIX) the child does not have any instrumentation because
1643 the text segment of the child is not a copy of the parent text segment at
1644 the time of the fork, but a copy of the original text segment of the parent,
1645 without any instrumentation.
1646 (actually, childHasInstr is obsoleted by aix's completeTheFork() routine)
1648 process *process::forkProcess(const process *theParent, pid_t childPid,
1649 dictionary_hash<instInstance*,instInstance*> &map, // gets filled in
1653 void *applAttachedPtr
1657 vector<fastInferiorHeapMgr::oneHeapStats> theShmHeapStats(3);
1658 theShmHeapStats[0].elemNumBytes = sizeof(intCounter);
1659 theShmHeapStats[0].maxNumElems = numIntCounters;
1661 theShmHeapStats[1].elemNumBytes = sizeof(tTimer);
1662 theShmHeapStats[1].maxNumElems = numWallTimers;
1664 theShmHeapStats[2].elemNumBytes = sizeof(tTimer);
1665 theShmHeapStats[2].maxNumElems = numProcTimers;
1668 forkexec_cerr << "paradynd welcome to process::forkProcess; parent pid=" << theParent->getPid() << "; calling fork ctor now" << endl;
1670 // Call the "fork" ctor:
1671 process *ret = new process(*theParent, (int)childPid, iTrace_fd
1680 forkexec_cerr << "paradynd fork ctor has completed ok...child pid is " << ret->getPid() << endl;
1685 #ifndef BPATCH_LIBRARY
1686 if (!costMetric::addProcessToAll(ret))
1690 // We used to do a ret->attach() here...it was moved to the fork ctor, so it's
1691 // been done already.
1693 /* all instrumentation on the parent is active on the child */
1694 /* TODO: what about instrumentation inserted near the fork time??? */
1695 ret->baseMap = theParent->baseMap; // WHY IS THIS HERE?
1697 // the following writes to "map", s.t. for each instInstance in the parent
1698 // process, we have a map to the corresponding one in the child process.
1699 // that's all this routine does -- it doesn't actually touch
1700 // any instrumentation (because it doesn't need to -- fork() syscall copied
1701 // all of the actual instrumentation [but what about AIX and its weird load
1703 copyInstInstances(theParent, ret, map);
1704 // doesn't copy anything; just writes to "map"
1710 void process::processCost(unsigned obsCostLow,
1712 time64 processTime) {
1713 // wallTime and processTime should compare to DYNINSTgetWallTime() and
1714 // DYNINSTgetCPUtime().
1716 // check for overflow, add to running total, convert cycles to
1717 // seconds, and report.
1718 // Member vrbles of class process: lastObsCostLow and cumObsCost (the latter
1721 // code to handle overflow used to be in rtinst; we borrow it pretty much
1722 // verbatim. (see rtinst/RTposix.c)
1723 if (obsCostLow < lastObsCostLow) {
1724 // we have a wraparound
1725 cumObsCost += ((unsigned)0xffffffff - lastObsCostLow) + obsCostLow + 1;
1728 cumObsCost += (obsCostLow - lastObsCostLow);
1730 lastObsCostLow = obsCostLow;
1732 extern double cyclesPerSecond; // perfStream.C
1734 double observedCostSecs = cumObsCost;
1735 observedCostSecs /= cyclesPerSecond;
1736 // cerr << "processCost: cyclesPerSecond=" << cyclesPerSecond << "; cum obs cost=" << observedCostSecs << endl;
1738 // Notice how most of the rest of this is copied from processCost() of metric.C
1739 // Be sure to keep the two "in sync"!
1740 timeStamp newSampleTime = (double)wallTime / 1000000.0; // usec to seconds
1741 timeStamp newProcessTime = (double)processTime / 1000000.0; // usec to secs
1743 extern costMetric *totalPredictedCost; // init.C
1744 extern costMetric *observed_cost; // init.C
1745 extern costMetric *smooth_obs_cost; // init.C
1747 const timeStamp lastProcessTime =
1748 totalPredictedCost->getLastSampleProcessTime(this);
1750 // find the portion of uninstrumented time for this interval
1751 const double unInstTime = ((newProcessTime - lastProcessTime)
1752 / (1+currentPredictedCost));
1753 // update predicted cost
1754 // note: currentPredictedCost is the same for all processes
1755 // this should be changed to be computed on a per process basis
1756 sampleValue newPredCost = totalPredictedCost->getCumulativeValue(this);
1757 newPredCost += (float)(currentPredictedCost*unInstTime);
1759 totalPredictedCost->updateValue(this,newPredCost,
1760 newSampleTime,newProcessTime);
1761 // update observed cost
1762 observed_cost->updateValue(this,observedCostSecs,
1763 newSampleTime,newProcessTime);
1765 // update smooth observed cost
1766 smooth_obs_cost->updateSmoothValue(this,observedCostSecs,
1767 newSampleTime,newProcessTime);
1772 * Copy data from controller process to the named process.
1774 bool process::writeDataSpace(void *inTracedProcess, int size,
1775 const void *inSelf) {
1776 bool needToCont = false;
1778 if (status_ == exited)
1781 if (status_ == running) {
1787 if (status_ != stopped && status_ != neonatal) {
1788 showErrorCallback(38, "Internal paradynd error in process::writeDataSpace");
1792 bool res = writeDataSpace_(inTracedProcess, size, inSelf);
1794 string msg = string("System error: unable to write to process data space:")
1795 + string(sys_errlist[errno]);
1796 showErrorCallback(38, msg);
1801 return this->continueProc();
1805 bool process::readDataSpace(const void *inTracedProcess, int size,
1806 void *inSelf, bool displayErrMsg) {
1807 bool needToCont = false;
1809 if (status_ == exited)
1812 if (status_ == running) {
1818 if (status_ != stopped && status_ != neonatal) {
1819 showErrorCallback(38, "Internal paradynd error in process::readDataSpace");
1823 bool res = readDataSpace_(inTracedProcess, size, inSelf);
1825 if (displayErrMsg) {
1827 msg=string("System error: unable to read from process data space:")
1828 + string(sys_errlist[errno]);
1829 showErrorCallback(38, msg);
1835 return this->continueProc();
1840 bool process::writeTextWord(caddr_t inTracedProcess, int data) {
1841 bool needToCont = false;
1843 if (status_ == exited)
1846 if (status_ == running) {
1852 if (status_ != stopped && status_ != neonatal) {
1853 string msg = string("Internal paradynd error in process::writeTextWord")
1854 + string((int)status_);
1855 showErrorCallback(38, msg);
1856 //showErrorCallback(38, "Internal paradynd error in process::writeTextWord");
1860 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
1861 if (!isAddrInHeap((Address)inTracedProcess)) {
1862 if (!saveOriginalInstructions((Address)inTracedProcess, sizeof(int)))
1864 afterMutationList.insertTail((Address)inTracedProcess, sizeof(int), &data);
1868 bool res = writeTextWord_(inTracedProcess, data);
1870 string msg = string("System error: unable to write to process text word:")
1871 + string(sys_errlist[errno]);
1872 showErrorCallback(38, msg);
1877 return this->continueProc();
1882 bool process::writeTextSpace(void *inTracedProcess, int amount, const void *inSelf) {
1883 bool needToCont = false;
1885 if (status_ == exited)
1888 if (status_ == running) {
1894 if (status_ != stopped && status_ != neonatal) {
1895 string msg = string("Internal paradynd error in process::writeTextSpace")
1896 + string((int)status_);
1897 showErrorCallback(38, msg);
1898 //showErrorCallback(38, "Internal paradynd error in process::writeTextSpace");
1902 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
1903 if (!isAddrInHeap((Address)inTracedProcess)) {
1904 if (!saveOriginalInstructions((Address)inTracedProcess, amount))
1906 afterMutationList.insertTail((Address)inTracedProcess, amount, inSelf);
1910 bool res = writeTextSpace_(inTracedProcess, amount, inSelf);
1912 string msg = string("System error: unable to write to process text space:")
1913 + string(sys_errlist[errno]);
1914 showErrorCallback(38, msg);
1919 return this->continueProc();
1923 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
1924 bool process::readTextSpace(const void *inTracedProcess, int amount,
1927 bool needToCont = false;
1929 if (status_ == exited)
1932 if (status_ == running) {
1938 if (status_ != stopped && status_ != neonatal) {
1939 showErrorCallback(38, "Internal paradynd error in process::readTextSpace");
1943 bool res = readTextSpace_(inTracedProcess, amount, inSelf);
1946 msg=string("System error: unable to read from process data space:")
1947 + string(sys_errlist[errno]);
1948 showErrorCallback(38, msg);
1953 return this->continueProc();
1957 #endif /* BPATCH_SET_MUTATIONS_ACTIVE */
1959 bool process::pause() {
1960 if (status_ == stopped || status_ == neonatal)
1963 if (status_ == exited)
1966 if (status_ == running && reachedFirstBreak) {
1967 bool res = pause_();
1974 // The only remaining combination is: status==running but haven't yet
1975 // reached first break. We never want to pause before reaching the
1976 // first break (trap, actually). But should we be returning true or false in this
1983 // handleIfDueToSharedObjectMapping: if a trap instruction was caused by
1984 // a dlopen or dlclose event then return true
1985 bool process::handleIfDueToSharedObjectMapping(){
1991 vector<shared_object *> *changed_objects = 0;
1992 u_int change_type = 0;
1993 bool error_occured = false;
1994 bool ok = dyn->handleIfDueToSharedObjectMapping(this,&changed_objects,
1995 change_type,error_occured);
1997 // if this trap was due to dlopen or dlclose, and if something changed
1998 // then figure out how it changed and either add or remove shared objects
1999 if(ok && !error_occured && (change_type != SHAREDOBJECT_NOCHANGE)) {
2001 // if something was added then call process::addASharedObject with
2002 // each element in the vector of changed_objects
2003 if((change_type == SHAREDOBJECT_ADDED) && changed_objects) {
2004 for(u_int i=0; i < changed_objects->size(); i++) {
2005 // TODO: currently we aren't handling dlopen because
2006 // we don't have the code in place to modify existing metrics
2008 // This is what we really want to do:
2009 if(!addASharedObject(*((*changed_objects)[i]))){
2010 logLine("Error after call to addASharedObject\n");
2011 delete (*changed_objects)[i];
2014 *shared_objects += (*changed_objects)[i];
2017 // for now, just delete shared_objects to avoid memory leeks
2018 delete (*changed_objects)[i];
2020 delete changed_objects;
2022 else if((change_type == SHAREDOBJECT_REMOVED) && (changed_objects)) {
2023 // TODO: handle this case
2024 // if something was removed then call process::removeASharedObject
2025 // with each element in the vector of changed_objects
2027 // for now, just delete shared_objects to avoid memory leeks
2028 for(u_int i=0; i < changed_objects->size(); i++){
2029 delete (*changed_objects)[i];
2031 delete changed_objects;
2034 // TODO: add support for adding or removing new code resource once the
2035 // process has started running...this means that currently collected
2036 // metrics may have to have aggregate components added or deleted
2037 // this should be added to process::addASharedObject and
2038 // process::removeASharedObject
2048 // If this process is a dynamic executable, then get all its
2049 // shared objects, parse them, and define new instpoints and resources
2051 bool process::handleStartProcess(process *p){
2057 // get shared objects, parse them, and define new resources
2058 // For WindowsNT we don't call getSharedObjects here, instead
2059 // addASharedObject will be called directly by pdwinnt.C
2060 #if !defined(i386_unknown_nt4_0)
2061 p->getSharedObjects();
2064 #ifndef BPATCH_LIBRARY
2065 if(resource::num_outstanding_creates)
2066 p->setWaitingForResources();
2072 // addASharedObject: This routine is called whenever a new shared object
2073 // has been loaded by the run-time linker
2074 // It processes the image, creates new resources
2075 bool process::addASharedObject(shared_object &new_obj){
2077 image *img = image::parseImage(new_obj.getName(),new_obj.getBaseAddress());
2079 logLine("error parsing image in addASharedObject\n");
2082 new_obj.addImage(img);
2084 // if the list of all functions and all modules have already been
2085 // created for this process, then the functions and modules from this
2086 // shared object need to be added to those lists
2088 *all_modules += *((vector<module *> *)(new_obj.getModules()));
2091 vector<function_base *> *normal_funcs = (vector<function_base *> *)
2092 (new_obj.getAllFunctions());
2093 *all_functions += *normal_funcs;
2097 // if the signal handler function has not yet been found search for it
2098 if(!signal_handler){
2099 signal_handler = img->findOneFunction(SIGNAL_HANDLER);
2102 // clear the include_funcs flag if this shared object should not be
2103 // included in the some_functions and some_modules lists
2104 #ifndef BPATCH_LIBRARY
2105 vector<string> lib_constraints;
2106 if(mdl_get_lib_constraints(lib_constraints)){
2107 for(u_int j=0; j < lib_constraints.size(); j++){
2109 // if the lib constraint is not of the form "module/function" and
2110 // if it is contained in the name of this object, then exclude
2111 // this shared object
2112 char *obj_name = P_strdup(new_obj.getName().string_of());
2113 char *lib_name = P_strdup(lib_constraints[j].string_of());
2114 if(obj_name && lib_name && (where=P_strstr(obj_name, lib_name))){
2115 new_obj.changeIncludeFuncs(false);
2117 if(lib_name) free(lib_name);
2118 if(obj_name) free(obj_name);
2122 if(new_obj.includeFunctions()){
2124 *some_modules += *((vector<module *> *)(new_obj.getModules()));
2126 if(some_functions) {
2127 // gets only functions not excluded by mdl "exclude_node" option
2129 *((vector<function_base *> *)(new_obj.getSomeFunctions()));
2132 #endif /* BPATCH_LIBRARY */
2136 // getSharedObjects: This routine is called before main() or on attach
2137 // to an already running process. It gets and process all shared objects
2138 // that have been mapped into the process's address space
2139 bool process::getSharedObjects() {
2141 assert(!shared_objects);
2142 shared_objects = dyn->getSharedObjects(this);
2144 statusLine("parsing shared object files");
2146 #ifndef BPATCH_LIBRARY
2147 tp->resourceBatchMode(true);
2149 // for each element in shared_objects list process the
2150 // image file to find new instrumentaiton points
2151 for(u_int j=0; j < shared_objects->size(); j++){
2152 //string temp2 = string(i);
2153 //temp2 += string("th shared obj, addr: ");
2154 //temp2 += string(((*shared_objects)[i])->getBaseAddress());
2155 //temp2 += string(" name: ");
2156 //temp2 += string(((*shared_objects)[i])->getName());
2157 //temp2 += string("\n");
2158 // logLine(P_strdup(temp2.string_of()));
2160 if(!addASharedObject(*((*shared_objects)[j]))){
2161 logLine("Error after call to addASharedObject\n");
2165 #ifndef BPATCH_LIBRARY
2166 tp->resourceBatchMode(false);
2170 // else this a.out does not have a .dynamic section
2171 dynamiclinking = false;
2175 // findOneFunction: returns the function associated with func
2176 // this routine checks both the a.out image and any shared object
2177 // images for this resource
2178 #ifndef BPATCH_LIBRARY
2179 function_base *process::findOneFunction(resource *func,resource *mod){
2181 if((!func) || (!mod)) { return 0; }
2182 if(func->type() != MDL_T_PROCEDURE) { return 0; }
2183 if(mod->type() != MDL_T_MODULE) { return 0; }
2185 const vector<string> &f_names = func->names();
2186 const vector<string> &m_names = mod->names();
2187 string func_name = f_names[f_names.size() -1];
2188 string mod_name = m_names[m_names.size() -1];
2190 // KLUDGE: first search any shared libraries for the module name
2191 // (there is only one module in each shared library, and that
2192 // is the library name)
2193 if(dynamiclinking && shared_objects){
2194 for(u_int j=0; j < shared_objects->size(); j++){
2196 next = ((*shared_objects)[j])->findModule(mod_name,true);
2198 if(((*shared_objects)[j])->includeFunctions()){
2199 return(((*shared_objects)[j])->findOneFunction(func_name,
2207 // check a.out for function symbol
2208 return(symbols->findOneFunction(func_name));
2210 #endif /* BPATCH_LIBRARY */
2212 #ifndef BPATCH_LIBRARY
2213 // returns all the functions in the module "mod" that are not excluded by
2214 // exclude_lib or exclude_func
2215 // return 0 on error.
2216 vector<function_base *> *process::getIncludedFunctions(module *mod) {
2218 if((!mod)) { return 0; }
2220 // KLUDGE: first search any shared libraries for the module name
2221 // (there is only one module in each shared library, and that
2222 // is the library name)
2223 if(dynamiclinking && shared_objects){
2224 for(u_int j=0; j < shared_objects->size(); j++){
2226 next = ((*shared_objects)[j])->findModule(mod->fileName(), true);
2228 if(((*shared_objects)[j])->includeFunctions()){
2229 return((vector<function_base *> *)
2230 ((*shared_objects)[j])->getSomeFunctions());
2237 // this must be an a.out module so just return the list associated
2239 return(mod->getFunctions());
2241 #endif /* BPATCH_LIBRARY */
2244 // findOneFunction: returns the function associated with func
2245 // this routine checks both the a.out image and any shared object
2246 // images for this resource
2247 function_base *process::findOneFunction(const string &func_name){
2249 // first check a.out for function symbol
2250 function_base *pdf = symbols->findOneFunction(func_name);
2253 // search any shared libraries for the file name
2254 if(dynamiclinking && shared_objects){
2255 for(u_int j=0; j < shared_objects->size(); j++){
2256 pdf = ((*shared_objects)[j])->findOneFunction(func_name,false);
2264 // findOneFunctionFromAll: returns the function associated with func
2265 // this routine checks both the a.out image and any shared object
2266 // images for this resource
2267 function_base *process::findOneFunctionFromAll(const string &func_name){
2269 // first check a.out for function symbol
2270 function_base *pdf = symbols->findOneFunctionFromAll(func_name);
2273 // search any shared libraries for the file name
2274 if(dynamiclinking && shared_objects){
2275 for(u_int j=0; j < shared_objects->size(); j++){
2276 pdf=((*shared_objects)[j])->findOneFunctionFromAll(func_name,false);
2286 // findpdFunctionIn: returns the function which contains this address
2287 // This routine checks both the a.out image and any shared object images
2288 // for this function
2289 pd_Function *process::findpdFunctionIn(Address adr) {
2291 // first check a.out for function symbol
2292 pd_Function *pdf = symbols->findFunctionIn(adr,this);
2294 // search any shared libraries for the function
2295 if(dynamiclinking && shared_objects){
2296 for(u_int j=0; j < shared_objects->size(); j++){
2297 pdf = ((*shared_objects)[j])->findFunctionIn(adr,this);
2303 if(!all_functions) getAllFunctions();
2305 // if the function was not found, then see if this addr corresponds
2306 // to a function that was relocated in the heap
2308 for(u_int j=0; j < all_functions->size(); j++){
2309 Address func_adr = ((*all_functions)[j])->getAddress(this);
2310 if((adr>=func_adr) &&
2311 (adr<=(((*all_functions)[j])->size()+func_adr))){
2312 // yes, this is very bad, but too bad
2313 return((pd_Function*)((*all_functions)[j]));
2321 // findFunctionIn: returns the function containing the address "adr"
2322 // this routine checks both the a.out image and any shared object
2323 // images for this resource
2324 function_base *process::findFunctionIn(Address adr){
2326 // first check a.out for function symbol
2327 pd_Function *pdf = symbols->findFunctionIn(adr,this);
2329 // search any shared libraries for the function
2330 if(dynamiclinking && shared_objects){
2331 for(u_int j=0; j < shared_objects->size(); j++){
2332 pdf = ((*shared_objects)[j])->findFunctionIn(adr,this);
2338 if(!all_functions) getAllFunctions();
2341 // if the function was not found, then see if this addr corresponds
2342 // to a function that was relocated in the heap
2344 for(u_int j=0; j < all_functions->size(); j++){
2345 Address func_adr = ((*all_functions)[j])->getAddress(this);
2346 if((adr>=func_adr) &&
2347 (adr<=(((*all_functions)[j])->size()+func_adr))){
2348 return((*all_functions)[j]);
2357 // findModule: returns the module associated with mod_name
2358 // this routine checks both the a.out image and any shared object
2359 // images for this resource
2360 // if check_excluded is true it checks to see if the module is excluded
2361 // and if it is it returns 0. If check_excluded is false it doesn't check
2362 module *process::findModule(const string &mod_name,bool check_excluded){
2364 // KLUDGE: first search any shared libraries for the module name
2365 // (there is only one module in each shared library, and that
2366 // is the library name)
2367 if(dynamiclinking && shared_objects){
2368 for(u_int j=0; j < shared_objects->size(); j++){
2369 module *next = ((*shared_objects)[j])->findModule(mod_name,
2377 // check a.out for function symbol
2378 return(symbols->findModule(mod_name));
2381 // getSymbolInfo: get symbol info of symbol associated with name n
2382 // this routine starts looking a.out for symbol and then in shared objects
2383 // baseAddr is set to the base address of the object containing the symbol
2384 bool process::getSymbolInfo(const string &name, Symbol &info, Address &baseAddr) const {
2386 // first check a.out for symbol
2387 if(symbols->symbol_info(name,info))
2388 return getBaseAddress(symbols, baseAddr);
2390 // next check shared objects
2391 if(dynamiclinking && shared_objects)
2392 for(u_int j=0; j < shared_objects->size(); j++)
2393 if(((*shared_objects)[j])->getSymbolInfo(name,info))
2394 return getBaseAddress(((*shared_objects)[j])->getImage(), baseAddr);
2400 // getAllFunctions: returns a vector of all functions defined in the
2401 // a.out and in the shared objects
2402 // TODO: what to do about duplicate function names?
2403 vector<function_base *> *process::getAllFunctions(){
2405 // if this list has already been created, return it
2407 return all_functions;
2409 // else create the list of all functions
2410 all_functions = new vector<function_base *>;
2411 const vector<function_base *> &blah =
2412 (vector<function_base *> &)(symbols->getNormalFuncs());
2413 *all_functions += blah;
2415 if(dynamiclinking && shared_objects){
2416 for(u_int j=0; j < shared_objects->size(); j++){
2417 vector<function_base *> *funcs = (vector<function_base *> *)
2418 (((*shared_objects)[j])->getAllFunctions());
2420 *all_functions += *funcs;
2424 return all_functions;
2427 // getAllModules: returns a vector of all modules defined in the
2428 // a.out and in the shared objects
2429 vector<module *> *process::getAllModules(){
2431 // if the list of all modules has already been created, the return it
2432 if(all_modules) return all_modules;
2434 // else create the list of all modules
2435 all_modules = new vector<module *>;
2436 *all_modules += *((vector<module *> *)(&(symbols->mods)));
2438 if(dynamiclinking && shared_objects){
2439 for(u_int j=0; j < shared_objects->size(); j++){
2440 vector<module *> *mods =
2441 (vector<module *> *)(((*shared_objects)[j])->getModules());
2443 *all_modules += *mods;
2449 #ifndef BPATCH_LIBRARY
2450 // getIncludedFunctions: returns a vector of all functions defined in the
2451 // a.out and in the shared objects
2452 // TODO: what to do about duplicate function names?
2453 vector<function_base *> *process::getIncludedFunctions(){
2455 // if this list has already been created, return it
2457 return some_functions;
2459 // else create the list of all functions
2460 some_functions = new vector<function_base *>;
2461 const vector<function_base *> &normal_funcs =
2462 (vector<function_base *> &)(symbols->getNormalFuncs());
2463 *some_functions += normal_funcs;
2465 if(dynamiclinking && shared_objects){
2466 for(u_int j=0; j < shared_objects->size(); j++){
2467 if(((*shared_objects)[j])->includeFunctions()){
2468 // kludge: can't assign a vector<derived_class *> to
2469 // a vector<base_class *> so recast
2470 vector<function_base *> *funcs = (vector<function_base *> *)
2471 (((*shared_objects)[j])->getSomeFunctions());
2473 *some_functions += (*funcs);
2477 return some_functions;
2479 #endif /* BPATCH_LIBRARY */
2481 // getIncludedModules: returns a vector of all modules defined in the
2482 // a.out and in the shared objects that are included as specified in
2484 vector<module *> *process::getIncludedModules(){
2486 // if the list of all modules has already been created, the return it
2487 if(some_modules) return some_modules;
2489 // else create the list of all modules
2490 some_modules = new vector<module *>;
2491 *some_modules += *((vector<module *> *)(&(symbols->mods)));
2493 if(dynamiclinking && shared_objects){
2494 for(u_int j=0; j < shared_objects->size(); j++){
2495 if(((*shared_objects)[j])->includeFunctions()){
2496 vector<module *> *mods = (vector<module *> *)
2497 (((*shared_objects)[j])->getModules());
2499 *some_modules += *mods;
2503 return some_modules;
2506 // getBaseAddress: sets baseAddress to the base address of the
2507 // image corresponding to which. It returns true if image is mapped
2508 // in processes address space, otherwise it returns 0
2509 bool process::getBaseAddress(const image *which,u_int &baseAddress) const {
2511 if((u_int)(symbols) == (u_int)(which)){
2515 else if (shared_objects) {
2516 // find shared object corr. to this image and compute correct address
2517 for(unsigned j=0; j < shared_objects->size(); j++){
2518 if(((*shared_objects)[j])->isMapped()){
2519 if(((*shared_objects)[j])->getImageId() == (u_int)which) {
2520 baseAddress = ((*shared_objects)[j])->getBaseAddress();
2528 // findSignalHandler: if signal_handler is 0, then it checks all images
2529 // associtated with this process for the signal handler function.
2530 // Otherwise, the signal handler function has already been found
2531 void process::findSignalHandler(){
2533 if(SIGNAL_HANDLER == 0) return;
2534 if(!signal_handler) {
2535 // first check a.out for signal handler function
2536 signal_handler = symbols->findOneFunction(SIGNAL_HANDLER);
2538 // search any shared libraries for signal handler function
2539 if(!signal_handler && dynamiclinking && shared_objects) {
2540 for(u_int j=0;(j < shared_objects->size()) && !signal_handler; j++){
2542 ((*shared_objects)[j])->findOneFunction(SIGNAL_HANDLER,false);
2548 bool process::findInternalSymbol(const string &name, bool warn, internalSym &ret_sym) const {
2549 // On some platforms, internal symbols may be dynamic linked
2550 // so we search both the a.out and the shared objects
2553 static const string underscore = "_";
2554 if (getSymbolInfo(name, sym, baseAddr)
2555 || getSymbolInfo(underscore+name, sym, baseAddr)) {
2556 ret_sym = internalSym(sym.addr()+baseAddr, name);
2561 msg = string("Unable to find symbol: ") + name;
2562 statusLine(msg.string_of());
2563 showErrorCallback(28, msg);
2568 Address process::findInternalAddress(const string &name, bool warn, bool &err) const {
2569 // On some platforms, internal symbols may be dynamic linked
2570 // so we search both the a.out and the shared objects
2573 static const string underscore = "_";
2574 if (getSymbolInfo(name, sym, baseAddr)
2575 || getSymbolInfo(underscore+name, sym, baseAddr)) {
2577 return sym.addr()+baseAddr;
2581 msg = string("Unable to find symbol: ") + name;
2582 statusLine(msg.string_of());
2583 showErrorCallback(28, msg);
2591 bool process::continueProc() {
2592 if (status_ == exited) return false;
2594 if (status_ != stopped && status_ != neonatal) {
2595 showErrorCallback(38, "Internal paradynd error in process::continueProc");
2599 bool res = continueProc_();
2602 showErrorCallback(38, "System error: can't continue process");
2609 bool process::detach(const bool paused) {
2611 logLine("detach: pause not implemented\n"); // why not? --ari
2613 bool res = detach_();
2615 // process may have exited
2621 #ifdef BPATCH_LIBRARY
2622 // XXX Eventually detach() above should go away and this should be
2624 /* process::API_detach: detach from the application, leaving all
2625 instrumentation place. Returns true upon success and false upon failure.
2626 Fails if the application is not stopped when the call is made. The
2627 parameter "cont" indicates whether or not the application should be made
2628 running or not as a consquence of detaching (true indicates that it should
2631 bool process::API_detach(const bool cont)
2633 if (status() != neonatal && status() != stopped)
2636 return API_detach_(cont);
2640 /* process::handleExec: called when a process successfully exec's.
2641 Parse the new image, disable metric instances on the old image, create a
2642 new (and blank) shm segment. The process hasn't yet bootstrapped, so we
2643 mustn't try to enable anything...
2645 void process::handleExec() {
2646 // NOTE: for shm sampling, the shm segment has been removed, so we
2647 // mustn't try to disable any dataReqNodes in the standard way...
2649 // since the exec syscall has run, we're not ready to enable any m/f pairs or
2651 // So we set hasBootstrapped to false until we run DYNINSTinit again.
2652 hasBootstrapped = false;
2654 // all instrumentation that was inserted in this process is gone.
2655 // set exited here so that the disables won't try to write to process
2658 // Clean up state from old exec: all dynamic linking stuff, all lists
2659 // of functions and modules from old executable
2661 // can't delete dynamic linking stuff here, because parent process
2662 // could still have pointers
2663 dynamiclinking = false;
2664 dyn = 0; // AHEM. LEAKED MEMORY! not if the parent still has a pointer
2665 // to this dynamic_linking object.
2666 dyn = new dynamic_linking;
2668 for(u_int j=0; j< shared_objects->size(); j++){
2669 delete (*shared_objects)[j];
2671 delete shared_objects;
2675 // TODO: when can pdFunction's be deleted??? definitely not here.
2676 delete some_modules;
2677 delete some_functions;
2678 delete all_functions;
2685 trampTableItems = 0;
2686 memset(trampTable, 0, sizeof(trampTable));
2689 #if defined(rs6000_ibm_aix3_2) || defined(rs6000_ibm_aix4_1)
2690 // must call establishBaseAddrs before parsing the new image,
2691 // but doesn't need to wait for trap, since we already got the trap.
2692 bool establishBaseAddrs(int pid, int &status, bool waitForTrap);
2694 establishBaseAddrs(getPid(), status, false);
2697 image *img = image::parseImage(execFilePath);
2699 // For better error reporting, two failure return values would be useful
2700 // One for simple error like because-file-not-found
2701 // Another for serious errors like found-but-parsing-failed (internal error;
2702 // please report to paradyn@cs.wisc.edu)
2704 string msg = string("Unable to parse image: ") + execFilePath;
2705 showErrorCallback(68, msg.string_of());
2707 // err..what if we had attached? Wouldn't a detach be appropriate in this case?
2711 // delete proc->symbols ??? No, the image can be shared by more
2712 // than one process...images and instPoints can not be deleted...TODO
2713 // add some sort of reference count to these classes so that they can
2715 symbols = img; // AHEM! LEAKED MEMORY!!! ...not if parent has ptr to
2718 // see if new image contains the signal handler function
2719 this->findSignalHandler();
2721 // initInferiorHeap can only be called after symbols is set!
2722 initInferiorHeap(false);
2724 initInferiorHeap(true); // create separate text heap
2727 /* update process status */
2728 reachedFirstBreak = false;
2729 // we haven't yet seen initial SIGTRAP for this proc (is this right?)
2731 status_ = stopped; // was 'exited'
2733 // TODO: We should remove (code) items from the where axis, if the exec'd process
2734 // was the only one who had them.
2736 // the exec'd process has the same fd's as the pre-exec, so we don't need
2737 // to re-initialize traceLink or ioLink (is this right???)
2739 // we don't need to re-attach after an exec (is this right???)
2742 inferiorHeapMgr.handleExec();
2743 // reuses the shm seg (paradynd's already attached to it); resets applic-attached-
2744 // at to NULL. Quite similar to the (non-fork) ctor, really.
2746 theSuperTable.handleExec();
2754 process::cleanUpInstrumentation called when paradynd catch
2755 a SIGTRAP to find out if there's any previous unfinished instrumentation
2758 bool process::cleanUpInstrumentation(bool wasRunning) {
2759 // Try to process an item off of the waiting list 'instWlist'.
2760 // If something was found & processed, then true will be returned.
2761 // Additionally, if true is returned, the process will be continued
2762 // if 'wasRunning' is true.
2763 // But if false is returned, then there should be no side effects: noone
2764 // should be continued, nothing removed from 'instWList', no change
2765 // to this->status_, and so on (this is important to avoid bugs).
2767 assert(status_ == stopped); // since we're always called after a SIGTRAP
2769 Address pc = frame.getPC();
2771 // Go thru the instWList to find out the ones to be deleted
2776 //process *p = (instWList[i])->which_proc;
2777 if(((instWList[i])->pc_ == pc) && ((instWList[i])->which_proc == this)){
2778 (instWList[i])->cleanUp(this,pc);
2779 u_int last = instWList.size()-1;
2780 delete (instWList[i]);
2781 instWList[i] = instWList[last];
2782 instWList.resize(last);
2788 if(i >= instWList.size()) done = true;
2790 if(found && wasRunning) continueProc();
2794 void process::postRPCtoDo(AstNode *action, bool noCost,
2795 void (*callbackFunc)(process *, void *, unsigned),
2797 // posts an RPC, but does NOT make any effort to launch it.
2798 inferiorRPCtoDo theStruct;
2799 theStruct.action = action;
2800 theStruct.noCost = noCost;
2801 theStruct.callbackFunc = callbackFunc;
2802 theStruct.userData = userData;
2804 RPCsWaitingToStart += theStruct;
2807 bool process::existsRPCreadyToLaunch() const {
2808 if (currRunningRPCs.empty() && !RPCsWaitingToStart.empty())
2813 bool process::existsRPCinProgress() const {
2814 return (!currRunningRPCs.empty());
2817 bool process::launchRPCifAppropriate(bool wasRunning, bool finishingSysCall) {
2818 // asynchronously launches an inferiorRPC iff RPCsWaitingToStart.size() > 0 AND
2819 // if currRunningRPCs.size()==0 (the latter for safety)
2821 if (!currRunningRPCs.empty())
2822 // an RPC is currently executing, so it's not safe to launch a new one.
2825 if (RPCsWaitingToStart.empty())
2826 // duh, no RPC is waiting to run, so there's nothing to do.
2829 if (status_ == exited)
2832 if (status_ == neonatal)
2833 // not sure if this should be some kind of error...is the inferior ready
2834 // to execute inferior RPCs??? For now, we'll allow it.
2837 /* ****************************************************** */
2839 // Steps to take (on sparc, at least)
2840 // 1) pause the process and wait for it to stop
2841 // 2) Get a copy of the registers...store them away
2842 // 3) create temp trampoline: save, action, restore, trap, illegal
2843 // (the illegal is just ot be sure that the trap never returns)
2844 // 4) set the PC and nPC regs to addr of temp tramp
2845 // 5) Continue the process...go back to the main loop (SIGTRAP will
2846 // eventually be delivered)
2848 // When SIGTRAP is received,
2849 // 5) verify that PC is the location of the TRAP instr in the temp tramp
2850 // 6) free temp trampoline
2851 // 7) SETREGS to restore all regs, including PC and nPC.
2852 // 8) continue inferior, if the inferior had been running when we had
2853 // paused it in step 1, above.
2855 if (!finishingSysCall && RPCs_waiting_for_syscall_to_complete) {
2856 assert(executingSystemCall());
2861 cerr << "launchRPCifAppropriate failed because pause failed" << endl;
2865 // If we're in the middle of a system call, then it's not safe to launch
2866 // an inferiorRPC on most platforms. On some platforms, it's safe, but the
2867 // actual launching won't take place until the system call finishes. In such
2868 // cases it's a good idea to set a breakpoint for when the sys call exits
2869 // (using /proc PIOCSEXIT), and launch the inferiorRPC then.
2870 if (!finishingSysCall && executingSystemCall()) {
2871 if (RPCs_waiting_for_syscall_to_complete) {
2872 inferiorrpc_cerr << "launchRPCifAppropriate: still waiting for syscall to "
2873 << "complete" << endl;
2875 inferiorrpc_cerr << "launchRPC: continuing so syscall may complete" << endl;
2876 (void)continueProc();
2879 inferiorrpc_cerr << "launchRPC: sorry not continuing (problem?)" << endl;
2883 // don't do the inferior rpc until the system call finishes. Determine
2884 // which system call is in the way, and set a breakpoint at its exit point
2885 // so we know when it's safe to launch the RPC. Platform-specific
2888 inferiorrpc_cerr << "launchRPCifAppropriate: within a system call" << endl;
2890 if (!set_breakpoint_for_syscall_completion()) {
2891 // sorry, this platform can't set a breakpoint at the system call
2892 // completion point. In such a case, we keep polling executingSystemCall()
2895 (void)continueProc();
2897 inferiorrpc_cerr << "launchRPCifAppropriate: couldn't set bkpt for "
2898 << "syscall completion; will just poll." << endl;
2902 inferiorrpc_cerr << "launchRPCifAppropriate: set bkpt for syscall completion"
2905 // a SIGTRAP will get delivered when the RPC is ready to go. Until then,
2906 // mark the rpc as deferred. Setting this flag prevents us from executing
2907 // this code too many times.
2909 RPCs_waiting_for_syscall_to_complete = true;
2912 (void)continueProc();
2917 // Okay, we're not in the middle of a system call, so we can fire off the rpc now!
2918 if (RPCs_waiting_for_syscall_to_complete)
2920 RPCs_waiting_for_syscall_to_complete = false;
2922 void *theSavedRegs = getRegisters(); // machine-specific implementation
2923 // result is allocated via new[]; we'll delete[] it later.
2924 // return value of NULL indicates total failure.
2925 // return value of (void *)-1 indicates that the state of the machine isn't quite
2926 // ready for an inferiorRPC, and that we should try again 'later'. In
2927 // particular, we must handle the (void *)-1 case very gracefully (i.e., leave
2928 // the vrble 'RPCsWaitingToStart' untouched).
2930 if (theSavedRegs == (void *)-1) {
2931 // cerr << "launchRPCifAppropriate: deferring" << endl;
2933 (void)continueProc();
2937 if (theSavedRegs == NULL) {
2938 cerr << "launchRPCifAppropriate failed because getRegisters() failed" << endl;
2940 (void)continueProc();
2945 inferiorrpc_cerr << "NOTE: launchIfAppropriate: wasRunning==false!!" << endl;
2947 inferiorRPCtoDo todo = RPCsWaitingToStart.removeOne();
2948 // note: this line should always be below the test for (void*)-1, thus
2949 // leaving 'RPCsWaitingToStart' alone in that case.
2951 inferiorRPCinProgress inProgStruct;
2952 inProgStruct.callbackFunc = todo.callbackFunc;
2953 inProgStruct.userData = todo.userData;
2954 inProgStruct.savedRegs = theSavedRegs;
2955 inProgStruct.wasRunning = wasRunning || finishingSysCall;
2956 // If finishing up a system call, current state is paused, but we want to
2957 // set wasRunning to true so that it'll continue when the inferiorRPC
2958 // completes. Sorry for the kludge.
2959 unsigned tempTrampBase = createRPCtempTramp(todo.action,
2961 inProgStruct.callbackFunc != NULL,
2962 inProgStruct.breakAddr,
2963 inProgStruct.stopForResultAddr,
2964 inProgStruct.justAfter_stopForResultAddr,
2965 inProgStruct.resultRegister);
2966 // the last 4 args are written to
2968 if (tempTrampBase == NULL) {
2969 cerr << "launchRPCifAppropriate failed because createRPCtempTramp failed" << endl;
2971 (void)continueProc();
2975 assert(tempTrampBase);
2977 inProgStruct.firstInstrAddr = tempTrampBase;
2979 assert(currRunningRPCs.empty()); // since it's unsafe to run > 1 at a time
2980 currRunningRPCs += inProgStruct;
2982 inferiorrpc_cerr << "Changing pc and exec.." << endl;
2984 // change the PC and nPC registers to the addr of the temp tramp
2985 if (!changePC(tempTrampBase, theSavedRegs)) {
2986 cerr << "launchRPCifAppropriate failed because changePC() failed" << endl;
2988 (void)continueProc();
2992 if (!continueProc()) {
2993 cerr << "launchRPCifAppropriate: continueProc() failed" << endl;
2997 inferiorrpc_cerr << "inferiorRPC should be running now" << endl;
2999 return true; // success
3002 unsigned process::createRPCtempTramp(AstNode *action,
3004 bool shouldStopForResult,
3005 unsigned &breakAddr,
3006 unsigned &stopForResultAddr,
3007 unsigned &justAfter_stopForResultAddr,
3010 // Returns addr of temp tramp, which was allocated in the inferior heap.
3011 // You must free it yourself when done.
3013 // Note how this is, in many ways, a greatly simplified version of
3016 // Temp tramp structure: save; code; restore; trap; illegal
3017 // the illegal is just to make sure that the trap never returns
3018 // note that we may not need to save and restore anything, since we've
3019 // already done a GETREGS and we'll restore with a SETREGS, right?
3021 unsigned char insnBuffer[4096];
3023 initTramps(); // initializes "regSpace", but only the 1st time it gets called...
3024 extern registerSpace *regSpace;
3025 regSpace->resetSpace();
3029 // The following is implemented in an arch-specific source file...
3030 if (!emitInferiorRPCheader(insnBuffer, count)) {
3031 // a fancy dialog box is probably called for here...
3032 cerr << "createRPCtempTramp failed because emitInferiorRPCheader failed." << endl;
3036 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
3037 generateMTpreamble((char*)insnBuffer,count,this);
3040 resultReg = action->generateCode(this, regSpace,
3044 if (!shouldStopForResult) {
3045 regSpace->freeRegister(resultReg);
3048 ; // in this case, we'll call freeRegister() the inferior rpc completes
3050 // Now, the trailer (restore, TRAP, illegal)
3051 // (the following is implemented in an arch-specific source file...)
3053 unsigned breakOffset, stopForResultOffset, justAfter_stopForResultOffset;
3054 if (!emitInferiorRPCtrailer(insnBuffer, count,
3055 breakOffset, shouldStopForResult, stopForResultOffset,
3056 justAfter_stopForResultOffset)) {
3057 // last 4 args except shouldStopForResult are modified by the call
3058 cerr << "createRPCtempTramp failed because emitInferiorRPCtrailer failed." << endl;
3062 unsigned tempTrampBase = inferiorMalloc(this, count, textHeap);
3063 assert(tempTrampBase);
3066 breakAddr = tempTrampBase + breakOffset;
3067 if (shouldStopForResult) {
3068 stopForResultAddr = tempTrampBase + stopForResultOffset;
3069 justAfter_stopForResultAddr = tempTrampBase + justAfter_stopForResultOffset;
3072 stopForResultAddr = justAfter_stopForResultAddr = 0;
3075 inferiorrpc_cerr << "createRPCtempTramp: temp tramp base=" << (void*)tempTrampBase
3076 << ", stopForResultAddr=" << (void*)stopForResultAddr
3077 << ", justAfter_stopForResultAddr=" << (void*)justAfter_stopForResultAddr
3078 << ", breakAddr=" << (void*)breakAddr
3079 << ", count=" << count << " so end addr="
3080 << (void*)(tempTrampBase + count - 1) << endl;
3082 #if defined(MT_DEBUG)
3083 sprintf(errorLine,"********>>>>> tempTrampBase = 0x%x\n",tempTrampBase);
3087 /* Now, write to the tempTramp, in the inferior addr's data space
3088 (all tramps are allocated in data space) */
3089 if (!writeDataSpace((void*)tempTrampBase, count, insnBuffer)) {
3090 // should put up a nice error dialog window
3091 cerr << "createRPCtempTramp failed because writeDataSpace failed" << endl;
3095 extern int trampBytes; // stats.h
3096 trampBytes += count;
3098 return tempTrampBase;
3101 bool process::handleTrapIfDueToRPC() {
3102 // get curr PC register (can assume process is stopped), search for it in
3103 // 'currRunningRPCs'. If found, restore regs, do callback, delete tramp, and
3104 // return true. Returns false if not processed.
3106 assert(status_ == stopped); // a TRAP should always stop a process (duh)
3108 if (currRunningRPCs.empty())
3109 return false; // no chance of a match
3111 assert(currRunningRPCs.size() == 1);
3112 // it's unsafe to have > 1 RPCs going on at a time within a single process
3114 // Okay, time to do a stack trace.
3115 // If we determine that the PC of any level of the back trace
3116 // equals the current running RPC's stopForResultAddr or breakAddr,
3117 // then we have a match. Note: since all platforms currently
3118 // inline their trap/ill instruction instead of make a fn call e.g. to
3119 // DYNINSTbreakPoint(), we can probably get rid of the stack walk.
3121 int match_type = 0; // 1 --> stop for result, 2 --> really done
3122 Frame theFrame(this);
3124 // do we have a match?
3125 const int framePC = theFrame.getPC();
3126 if ((unsigned)framePC == currRunningRPCs[0].breakAddr) {
3127 // we've got a match!
3131 else if (currRunningRPCs[0].callbackFunc != NULL &&
3132 ((unsigned)framePC == currRunningRPCs[0].stopForResultAddr)) {
3137 if (theFrame.isLastFrame())
3138 // well, we've gone as far as we can, with no match.
3141 // else, backtrace 1 more level
3142 theFrame = theFrame.getPreviousStackFrameInfo(this);
3145 assert(match_type == 1 || match_type == 2);
3147 inferiorRPCinProgress &theStruct = currRunningRPCs[0];
3149 if (match_type == 1) {
3150 // We have stopped in order to grab the result. Grab it and write
3151 // to theStruct.resultValue, for use when we get match_type==2.
3153 inferiorrpc_cerr << "Welcome to handleTrapIfDueToRPC match type 1" << endl;
3155 assert(theStruct.callbackFunc != NULL);
3156 // must be a callback to ever see this match_type
3158 const unsigned returnValue = read_inferiorRPC_result_register(theStruct.resultRegister);
3160 extern registerSpace *regSpace;
3161 regSpace->freeRegister(theStruct.resultRegister);
3163 theStruct.resultValue = returnValue;
3165 // we don't remove the RPC from 'currRunningRPCs', since it's not yet done.
3166 // we continue the process...but not quite at the PC where we left off, since
3167 // that will just re-do the trap! Instead, we need to continue at the location
3168 // of the next instruction.
3169 if (!changePC(theStruct.justAfter_stopForResultAddr))
3172 if (!continueProc())
3173 cerr << "RPC getting result: continueProc failed" << endl;
3178 inferiorrpc_cerr << "Welcome to handleTrapIfDueToRPC match type 2" << endl;
3180 assert(match_type == 2);
3182 // step 1) restore registers:
3183 if (!restoreRegisters(theStruct.savedRegs)) {
3184 cerr << "handleTrapIfDueToRPC failed because restoreRegisters failed" << endl;
3187 currRunningRPCs.removeByIndex(0);
3189 if (currRunningRPCs.empty() && deferredContinueProc) {
3190 // We have a pending continueProc that we had to delay because
3191 // there was an inferior RPC in progress at that time, but now
3192 // we are ready to execute it - naim
3193 deferredContinueProc=false;
3194 if (continueProc()) statusLine("application running");
3197 delete [] theStruct.savedRegs;
3199 // step 2) delete temp tramp
3200 vector< vector<unsigned> > pointsToCheck;
3201 // blank on purpose; deletion is safe to take place even right now
3202 inferiorFree(this, theStruct.firstInstrAddr, textHeap, pointsToCheck);
3204 // step 3) continue process, if appropriate
3205 if (theStruct.wasRunning) {
3206 inferiorrpc_cerr << "end of rpc -- continuing process, since it had been running" << endl;
3208 if (!continueProc()) {
3209 cerr << "RPC completion: continueProc failed" << endl;
3213 inferiorrpc_cerr << "end of rpc -- leaving process paused, since it wasn't running before" << endl;
3215 // step 4) invoke user callback, if any
3216 // note: I feel it's important to do the user callback last, since it
3217 // may perform arbitrary actions (such as making igen calls) which can lead
3218 // to re-actions (such as receiving igen calls) that can alter the process
3219 // (e.g. continuing it). So clearly we need to restore registers, change the
3220 // PC, etc. BEFORE any such thing might happen. Hence we do the callback last.
3221 // I think the only potential controversy is whether we should do the callback
3222 // before step 3, above.
3224 inferiorrpc_cerr << "handleTrapIfDueToRPC match type 2 -- about to do callbackFunc, if any" << endl;
3226 if (theStruct.callbackFunc)
3227 theStruct.callbackFunc(this, theStruct.userData, theStruct.resultValue);
3229 inferiorrpc_cerr << "handleTrapIfDueToRPC match type 2 -- done with callbackFunc, if any" << endl;
3234 void process::installBootstrapInst() {
3235 // instrument main to call DYNINSTinit(). Don't use the shm seg for any
3236 // temp tramp space, since we can't assume that it's been intialized yet.
3237 // We build an ast saying: "call DYNINSTinit() with args
3238 // key_base, nbytes, paradynd_pid"
3240 #ifdef BPATCH_LIBRARY
3241 vector<AstNode *> the_args(2);
3243 the_args[0] = new AstNode(AstNode::Constant, (void*)1);
3244 the_args[1] = new AstNode(AstNode::Constant, (void*)getpid());
3246 AstNode *ast = new AstNode("DYNINSTinit", the_args);
3248 vector<AstNode *> the_args(3);
3250 // 2 dummy args when not shm sampling (just don't use -1, which is reserved
3252 unsigned numBytes = 0;
3255 key_t theKey = getShmKeyUsed();
3256 numBytes = getShmHeapTotalNumBytes();
3261 #ifdef SHM_SAMPLING_DEBUG
3262 cerr << "paradynd inst.C: about to call DYNINSTinit() with key=" << theKey
3263 << " and #bytes=" << numBytes << endl;
3266 the_args[0] = new AstNode(AstNode::Constant, (void*)theKey);
3267 the_args[1] = new AstNode(AstNode::Constant, (void*)numBytes);
3268 #ifdef BPATCH_LIBRARY
3269 // Unused by the dyninstAPI library
3270 the_args[2] = new AstNode(AstNode::Constant, (void *)0);
3272 the_args[2] = new AstNode(AstNode::Constant, (void*)traceConnectInfo);
3275 AstNode *ast = new AstNode("DYNINSTinit", the_args);
3276 for (unsigned j=0; j<the_args.size(); j++) {
3277 removeAst(the_args[j]);
3279 #endif /* BPATCH_LIBRARY */
3281 function_base *func = getMainFunction();
3284 instPoint *func_entry = (instPoint *)func->funcEntry(this);
3285 addInstFunc(this, func_entry, ast, callPreInsn,
3287 true // true --> don't try to have tramp code update the cost
3290 // returns an "instInstance", which we ignore (but should we?)
3293 void process::installInstrRequests(const vector<instMapping*> &requests) {
3294 for (unsigned lcv=0; lcv < requests.size(); lcv++) {
3295 instMapping *req = requests[lcv];
3297 function_base *func = findOneFunction(req->func);
3299 continue; // probably should have a flag telling us whether errors should
3300 // be silently handled or not
3303 if (req->where & FUNC_ARG) {
3304 // ast = new AstNode(req->inst, req->arg);
3305 ast = new AstNode(req->inst, req->args);
3307 AstNode *tmp = new AstNode(AstNode::Constant, (void*)0);
3308 ast = new AstNode(req->inst, tmp);
3312 if (req->where & FUNC_EXIT) {
3313 const vector<instPoint*> func_rets = func->funcExits(this);
3314 for (unsigned j=0; j < func_rets.size(); j++)
3315 (void)addInstFunc(this, func_rets[j], ast,
3316 callPreInsn, orderLastAtPoint, false);
3320 if (req->where & FUNC_ENTRY) {
3321 instPoint *func_entry = (instPoint *)func->funcEntry(this);
3322 (void)addInstFunc(this, func_entry, ast,
3323 callPreInsn, orderLastAtPoint, false);
3327 if (req->where & FUNC_CALL) {
3328 vector<instPoint*> func_calls = func->funcCalls(this);
3329 if (func_calls.size() == 0)
3332 for (unsigned j=0; j < func_calls.size(); j++)
3333 (void)addInstFunc(this, func_calls[j], ast,
3334 callPreInsn, orderLastAtPoint, false);
3342 bool process::extractBootstrapStruct(DYNINST_bootstrapStruct *bs_record) {
3343 const string vrbleName = "DYNINST_bootstrap_info";
3346 bool flag = findInternalSymbol(vrbleName, true, sym);
3349 Address symAddr = sym.getAddr();
3351 if (!readDataSpace((const void*)symAddr, sizeof(*bs_record), bs_record, true)) {
3352 cerr << "extractBootstrapStruct failed because readDataSpace failed" << endl;
3359 bool process::handleStopDueToExecEntry() {
3360 // returns true iff we are processing a stop due to the entry point of exec
3361 // The exec hasn't yet occurred.
3363 assert(status_ == stopped);
3365 DYNINST_bootstrapStruct bs_record;
3366 if (!extractBootstrapStruct(&bs_record))
3369 if (bs_record.event != 4)
3372 assert(getPid() == bs_record.pid);
3374 // for now, we just set aside the following information, to be used after the
3375 // exec actually happens (we'll get a SIGTRAP for that).
3378 execFilePath = string(bs_record.path);
3380 // the process was stopped...let's continue it so we can process the exec...
3381 assert(status_ == stopped);
3382 if (!continueProc())
3385 // should we set status_ to neonatal now? Nah, probably having the inExec flag
3386 // set is good enough...
3388 // shouldn't we be setting reachedFirstBreak to false???
3393 int process::procStopFromDYNINSTinit() {
3394 // possible return values:
3395 // 0 --> no, the stop wasn't the end of DYNINSTinit
3396 // 1 --> handled stop at end of DYNINSTinit, leaving program paused
3397 // 2 --> handled stop at end of DYNINSTinit...which had been invoked via
3398 // inferiorRPC...so we've continued the process in order to let the
3399 // inferiorRPC get its sigtrap.
3401 // Note that DYNINSTinit could have been run under several cases:
3402 // 1) the normal case (detect by bs_record.event==1 && execed_ == false)
3403 // 2) called after a fork (detect by bs_record.event==2)
3404 // 3) called after an exec (detect by bs_record.event==1 and execed_ == true)
3405 // 4) called for an attach (detect by bs_record.event==3)
3406 // note that bs_record.event == 4 is reserved for "sending" a tr_exec "record".
3408 // The exec case is tricky: we must loop thru all component mi's of this process
3409 // and decide now whether or not to carry them over to the new process.
3411 // if 0 is returned, there must be no side effects.
3413 assert(status_ == stopped);
3415 if (hasBootstrapped)
3418 DYNINST_bootstrapStruct bs_record;
3419 if (!extractBootstrapStruct(&bs_record))
3422 // Read the structure; if event 0 then it's undefined! (not yet written)
3423 if (bs_record.event == 0)
3426 forkexec_cerr << "procStopFromDYNINSTinit pid " << getPid() << "; got rec" << endl;
3428 assert(bs_record.event == 1 || bs_record.event == 2 || bs_record.event==3);
3429 assert(bs_record.pid == getPid());
3431 if (bs_record.event != 3) {
3432 // we don't want to do this stuff (yet) when DYNINSTinit was run via attach...we
3433 // want to wait until the inferiorRPC (thru which DYNINSTinit is being run)
3435 handleCompletionOfDYNINSTinit(false);
3439 if (!continueProc())
3445 void process::handleCompletionOfDYNINSTinit(bool fromAttach) {
3446 // 'event' values: (1) DYNINSTinit was started normally via paradynd
3447 // or via exec, (2) called from fork, (3) called from attach.
3449 DYNINST_bootstrapStruct bs_record;
3450 if (!extractBootstrapStruct(&bs_record))
3453 if (!fromAttach) // reset to 0 already if attaching, but other fields (attachedAtPtr) ok
3454 assert(bs_record.event == 1 || bs_record.event == 2 || bs_record.event==3);
3456 assert(bs_record.pid == getPid());
3458 // Note: the process isn't necessarily paused at this moment. In particular,
3459 // if we had attached to the process, then it will be running even as we speak.
3460 // While we're parsing the shared libraries, we should pause. So do that now.
3461 bool wasRunning = status_ == running;
3464 const bool calledFromFork = (bs_record.event == 2);
3465 const bool calledFromExec = (bs_record.event == 1 && execed_);
3466 const bool calledFromAttach = fromAttach || bs_record.event == 3;
3467 if (calledFromAttach)
3468 assert(createdViaAttach);
3471 if (!calledFromFork)
3472 registerInferiorAttachedSegs(bs_record.appl_attachedAtPtr);
3475 if (!calledFromFork)
3476 getObservedCostAddr();
3478 // handleStartProcess gets shared objects, so no need to do it again after a fork.
3479 // (question: do we need to do this after an exec???)
3480 if (!calledFromFork) {
3481 string str=string("PID=") + string(bs_record.pid) + ", calling handleStartProcess...";
3482 statusLine(str.string_of());
3484 if (!handleStartProcess(this)) // reads in shared libraries...can take a while
3485 logLine("warning: handleStartProcess failed\n");
3487 #ifndef BPATCH_LIBRARY
3488 // we decrement the batch mode here; it matches the bump-up in createProcess()
3489 tp->resourceBatchMode(false);
3492 str=string("PID=") + string(bs_record.pid) + ", installing default inst...";
3493 statusLine(str.string_of());
3495 extern vector<instMapping*> initialRequests; // init.C
3496 installInstrRequests(initialRequests);
3498 str=string("PID=") + string(bs_record.pid) + ", propagating mi's...";
3499 statusLine(str.string_of());
3501 forkexec_cerr << "procStopFromDYNINSTinit pid " << getPid() << "; about to propagate mi's" << endl;
3503 #ifndef BPATCH_LIBRARY
3504 if (!calledFromExec) {
3505 // propagate any metric that is already enabled to the new process.
3506 // For a forked process, this isn't needed because handleFork() has its own
3507 // special propagation algorithm (it propagates every aggregate mi having the
3508 // parent as a component, except for aggregate mi's whose focus is specifically
3509 // refined to the parent).
3510 vector<metricDefinitionNode *> MIs = allMIs.values();
3511 for (unsigned j = 0; j < MIs.size(); j++) {
3512 MIs[j]->propagateToNewProcess(this);
3513 // change to a process:: method which takes in the metricDefinitionNode
3517 // exec propagates in its own, special way that differs from a new process.
3518 // (propagate all mi's that make sense in the new process)
3519 metricDefinitionNode::handleExec(this);
3523 forkexec_cerr << "procStopFromDYNINSTinit pid " << getPid() << "; done propagate mi's" << endl;
3526 hasBootstrapped = true; // now, shm sampling may safely take place.
3528 string str=string("PID=") + string(bs_record.pid) + ", executing new-prog callback...";
3529 statusLine(str.string_of());
3531 #ifndef BPATCH_LIBRARY
3532 time64 currWallTime = calledFromExec ? 0 : getCurrWallTime();
3533 if (!calledFromExec && !calledFromFork) {
3534 // The following must be done before any samples are sent to
3535 // paradyn; otherwise, prepare for an assert fail.
3537 if (!::firstRecordTime)
3538 ::firstRecordTime = currWallTime;
3542 assert(status_ == stopped);
3544 #ifndef BPATCH_LIBRARY
3545 tp->newProgramCallbackFunc(bs_record.pid, this->arg_list,
3546 machineResource->part_name(),
3549 // in paradyn, this will call paradynDaemon::addRunningProgram().
3550 // If the state of the application as a whole is 'running' paradyn will
3551 // soon issue an igen call to us that'll continue this process.
3553 if (!calledFromExec)
3554 tp->firstSampleCallback(getPid(), (double)currWallTime / 1000000.0);
3557 if (calledFromFork) {
3558 // the parent proc has been waiting patiently at the start of DYNINSTfork
3559 // (i.e. the fork syscall executed but that's it). We can continue it now.
3560 process *parentProcess = findProcess(bs_record.ppid);
3561 if (parentProcess) {
3562 if (parentProcess->status() == stopped) {
3563 if (!parentProcess->continueProc())
3567 parentProcess->continueAfterNextStop();
3571 if (!calledFromAttach) {
3572 str=string("PID=") + string(bs_record.pid) + ", ready.";
3573 statusLine(str.string_of());
3576 assert(status_ == stopped);
3577 // though not for long, if 'wasRunning' is true (paradyn will soon continue us)
3580 void process::getObservedCostAddr() {
3582 #ifndef SHM_SAMPLING
3584 costAddr_ = findInternalAddress("DYNINSTobsCostLow", true, err);
3586 logLine("Internal error: unable to find addr of DYNINSTobsCostLow\n");
3587 showErrorCallback(79, "");
3591 costAddr_ = (int)getObsCostLowAddrInApplicSpace();
3595 bool process::checkStatus() {
3596 if (status_ == exited) {
3597 sprintf(errorLine, "attempt to ptrace exited process %d\n", pid);
3604 bool process::dumpCore(const string fileOut) {
3605 bool res = dumpCore_(fileOut);
3614 * The process was stopped by a signal. Update its status and notify Paradyn.
3616 void process::Stopped() {
3617 if (status_ != stopped) {
3619 #ifndef BPATCH_LIBRARY
3620 tp->processStatus(pid, procPaused);
3623 if (continueAfterNextStop_) {
3624 continueAfterNextStop_ = false;
3625 if (!continueProc())
3632 * The process has exited. Update its status and notify Paradyn.
3634 void process::Exited() {
3635 if (status_ != exited) {
3637 #ifndef BPATCH_LIBRARY
3638 tp->processStatus(pid, procExited);
3643 string process::getStatusAsString() const {
3644 // useful for debugging
3645 if (status_ == neonatal)
3647 if (status_ == stopped)
3649 if (status_ == running)
3651 if (status_ == exited)
3658 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
3659 bool process::saveOriginalInstructions(Address addr, int size) {
3660 char *data = new char[size];
3663 if (!readTextSpace((const void *)addr, size, data))
3666 beforeMutationList.insertHead(addr, size, data);
3673 bool process::writeMutationList(mutationList &list) {
3674 bool needToCont = false;
3676 if (status_ == exited)
3679 if (status_ == running) {
3685 if (status_ != stopped && status_ != neonatal) {
3687 string("Internal paradynd error in process::writeMutationList") +
3688 string((int)status_);
3689 showErrorCallback(38, msg); // XXX Should get its own error code
3693 mutationRecord *mr = list.getHead();
3695 while (mr != NULL) {
3696 bool res = writeTextSpace_((void *)mr->addr, mr->size, mr->data);
3698 // XXX Should we do something special when an error occurs, since
3699 // it could leave the process with only some mutations
3702 string("System error: unable to write to process text space: ")
3703 + string(sys_errlist[errno]);
3704 showErrorCallback(38, msg); // XXX Own error number?