Added several calls to API (waitForStatusChange, BPatch_variableExpr
[dyninst.git] / dyninstAPI / src / process.C
1 /*
2  * Copyright (c) 1996 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 extern "C" {
43 #ifdef PARADYND_PVM
44 int pvmputenv (const char *);
45 int pvmendtask();
46 #endif
47 }
48
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"
61
62 #ifdef BPATCH_LIBRARY
63 #include "dyninstAPI/h/BPatch.h"
64 #else
65 #include "rtinst/h/rtinst.h"
66 #include "rtinst/h/trace.h"
67 #include "paradynd/src/perfStream.h"
68 #include "paradynd/src/costmetrics.h"
69 #include "paradynd/src/mdld.h"
70 #include "paradynd/src/main.h"
71 #endif
72
73 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
74 extern void generateMTpreamble(char *insn, unsigned &base, process *proc);
75 #endif
76
77 #include "util/h/debugOstream.h"
78
79 #ifdef ATTACH_DETACH_DEBUG
80 debug_ostream attach_cerr(cerr, true);
81 #else
82 debug_ostream attach_cerr(cerr, false);
83 #endif
84
85 #ifdef INFERIOR_RPC_DEBUG
86 debug_ostream inferiorrpc_cerr(cerr, true);
87 #else
88 debug_ostream inferiorrpc_cerr(cerr, false);
89 #endif
90
91 #ifdef SHM_SAMPLING_DEBUG
92 debug_ostream shmsample_cerr(cerr, true);
93 #else
94 debug_ostream shmsample_cerr(cerr, false);
95 #endif
96
97 #ifdef FORK_EXEC_DEBUG
98 debug_ostream forkexec_cerr(cerr, true);
99 #else
100 debug_ostream forkexec_cerr(cerr, false);
101 #endif
102
103 #ifdef METRIC_DEBUG
104 debug_ostream metric_cerr(cerr, true);
105 #else
106 debug_ostream metric_cerr(cerr, false);
107 #endif
108
109 #ifdef SIGNAL_DEBUG
110 debug_ostream signal_cerr(cerr, true);
111 #else
112 debug_ostream signal_cerr(cerr, false);
113 #endif
114
115 #ifdef SHAREDOBJ_DEBUG
116 debug_ostream sharedobj_cerr(cerr, true);
117 #else
118 debug_ostream sharedobj_cerr(cerr, false);
119 #endif
120
121 #define FREE_WATERMARK (hp->totalFreeMemAvailable/2)
122 #define SIZE_WATERMARK 100
123 static const timeStamp MAX_WAITING_TIME=10.0;
124 static const timeStamp MAX_DELETING_TIME=2.0;
125 unsigned inferiorMemAvailable=0;
126
127 unsigned activeProcesses; // number of active processes
128 vector<process*> processVec;
129 string process::programName;
130 string process::pdFlavor;
131 vector<string> process::arg_list;
132
133 process *findProcess(int pid) { // make a public static member fn of class process
134   unsigned size=processVec.size();
135   for (unsigned u=0; u<size; u++)
136     if (processVec[u] && processVec[u]->getPid() == pid)
137       return processVec[u];
138   return NULL;
139 }
140
141 #ifdef SHM_SAMPLING
142 static unsigned numIntCounters=10000; // rather arbitrary; can we do better?
143 static unsigned numWallTimers =10000; // rather arbitrary; can we do better?
144 static unsigned numProcTimers =10000; // rather arbitrary; can we do better?
145 #endif
146
147 bool waitingPeriodIsOver()
148 {
149 static timeStamp previous=0;
150 timeStamp current;
151 bool waiting=false;
152
153   if (!previous) {
154     previous=getCurrentTime(false);
155     waiting=true;
156   }
157   else {
158     current=getCurrentTime(false);
159     if ( (current-previous) > MAX_WAITING_TIME ) {
160       previous=getCurrentTime(false);
161       waiting=true;
162     }
163   }
164   return(waiting);
165 }
166
167 Frame::Frame(process *proc) {
168
169     frame_ = pc_ = 0;
170     proc->getActiveFrame(&frame_, &pc_);
171
172     uppermostFrame = true;
173 }
174
175 Frame Frame::getPreviousStackFrameInfo(process *proc) const {
176    if (frame_ == 0){
177       // no prev frame exists; must return frame with 0 pc value otherwise
178       // will never break out of loop in walkStack()
179       Frame fake_frame(0,0,false);
180       return fake_frame; 
181    }
182
183    int fp = frame_;
184    int rtn = pc_;
185
186    Frame result(0, 0, false);
187    if (proc->readDataFromFrame(frame_, &fp, &rtn, uppermostFrame)) {
188       result.frame_ = fp;
189       result.pc_    = rtn;
190    }
191
192    return result;
193 }
194
195 #if !defined(rs6000_ibm_aix4_1)
196 vector<int> process::getTOCoffsetInfo() const
197 {
198   vector<int> tmp;
199   assert(0);
200   return tmp; // this is to make the nt compiler happy! - naim
201 }
202 #endif
203
204 #if !defined(i386_unknown_nt4_0)
205 // Windows NT has its own version of the walkStack function in pdwinnt.C
206 // Note: it may not always be possible to do a correct stack walk.
207 // If it can't do a complete walk, the function should return an empty
208 // vector, which means that there was an error, and we can't walk the stack.
209 vector<Address> process::walkStack(bool noPause)
210 {
211   vector<Address> pcs;
212   bool needToCont = noPause ? false : (status() == running);
213
214   if (!noPause && !pause()) {
215      // pause failed...give up
216      cerr << "walkStack: pause failed" << endl;
217      return pcs;
218   }
219
220   Address sig_addr = 0;
221   u_int sig_size = 0;
222   if(signal_handler){
223       const image *sig_image = (signal_handler->file())->exec();
224       if(getBaseAddress(sig_image, sig_addr)){
225           sig_addr += signal_handler->getAddress(this);
226       } else {
227           sig_addr = signal_handler->getAddress(this);
228       }
229       sig_size = signal_handler->size();
230       // printf("signal_handler = %s size = %d addr = 0x%x\n",
231       //     (signal_handler->prettyName()).string_of(),sig_size,sig_addr);
232   }
233
234   if (pause()) {
235     Frame   currentFrame(this);
236     Address fpOld = 0;
237     while (!currentFrame.isLastFrame()) {
238       Address fpNew = currentFrame.getFramePtr();
239       if (fpOld >= fpNew) {                             //Not moving up stack
240         if (!noPause && needToCont && !continueProc())
241           cerr << "walkStack: continueProc failed" << endl;
242         vector<Address> ev;                             //Empty vector
243         return ev;
244       }
245       fpOld = fpNew;
246
247       Address next_pc = currentFrame.getPC();
248       // printf("currentFrame pc = %d\n",next_pc);
249       pcs += next_pc;
250       // is this pc in the signal_handler function?
251       if(signal_handler && (next_pc >= sig_addr)
252           && (next_pc < (sig_addr+sig_size))){
253           // check to see if a leaf function was executing when the signal
254           // handler was called.  If so, then an extra frame should be added
255           // for the leaf function...the call to getPreviousStackFrameInfo
256           // will get the function that called the leaf function
257           Address leaf_pc = 0;
258           if(this->needToAddALeafFrame(currentFrame,leaf_pc)){
259               pcs += leaf_pc;
260           }
261       }
262       currentFrame = currentFrame.getPreviousStackFrameInfo(this); 
263     }
264     pcs += currentFrame.getPC();
265   }
266   if (!noPause && needToCont) {
267      if (!continueProc()){
268         cerr << "walkStack: continueProc failed" << endl;
269      }
270   }  
271   return(pcs);
272 }
273 #endif
274
275         // disItem is generally unchanged and was previously declared const,
276         // however, the heap management occasionally deletes such items
277         // so it's now no longer const'd
278 bool isFreeOK(process *proc, disabledItem &disItem, vector<Address> &pcs) {
279   const unsigned disItemPointer = disItem.getPointer();
280   const inferiorHeapType disItemHeap = disItem.getHeapType();
281
282 #if defined(hppa1_1_hp_hpux)
283   if (proc->freeNotOK) return(false);
284 #endif
285
286   heapItem *ptr=NULL;
287   if (!proc->heaps[disItemHeap].heapActive.find(disItemPointer, ptr)) {
288     sprintf(errorLine,"Warning: attempt to free not defined heap entry "
289                       "%x (pid=%d, heapActive.size()=%d)\n", 
290         disItemPointer, proc->getPid(), 
291         proc->heaps[disItemHeap].heapActive.size());
292     logLine(errorLine);
293     //showErrorCallback(67, (const char *)errorLine);
294     return(false);
295   }
296   assert(ptr);
297
298 #ifdef FREEDEBUG1
299   sprintf(errorLine, "isFreeOK  called on 0x%x\n", ptr->addr);
300   logLine(errorLine);
301 #endif
302
303   // the following can't be const; we're sometimes gonna change it
304   vector<unsigVecType> &disItemPoints = disItem.getPointsToCheck(); 
305
306   const unsigned disItemNumPoints = disItemPoints.size();
307
308   for (unsigned int j=0;j<disItemNumPoints;j++) {
309     for (unsigned int k=0;k<disItemPoints[j].size();k++) {
310       unsigned pointer = disItemPoints[j][k];
311 #ifdef FREEDEBUG_ON
312       if (disItemHeap == dataHeap)
313         sprintf(errorLine, "checking DATA pointer 0x%x\n", pointer);
314       else
315         sprintf(errorLine, "checking TEXT pointer 0x%x\n", pointer);
316       logLine(errorLine);
317 #endif
318
319       const dictionary_hash<unsigned, heapItem*> &heapActivePart =
320               proc->splitHeaps ? proc->heaps[textHeap].heapActive :
321                                  proc->heaps[dataHeap].heapActive;
322
323       heapItem *np=NULL;
324       if (!heapActivePart.find(pointer, np)) { // fills in "np" if found
325 #ifdef FREEDEBUG1
326             sprintf(errorLine, "something freed addr 0x%x from us\n", pointer);
327             logLine(errorLine);
328 #endif
329         
330         // 
331         // This point was deleted already and we don't need it anymore in
332         // pointsToCheck
333         // 
334         const int size=disItemPoints[j].size();
335         disItemPoints[j][k] = disItemPoints[j][size-1];
336         disItemPoints[j].resize(size-1);
337
338         // need to make sure we check the next item too 
339         k--;
340       } else {
341         // Condition 1
342         assert(np);
343         if ( (ptr->addr >= np->addr) && 
344              (ptr->addr <= (np->addr + np->length)) )
345         {
346
347 #ifdef FREEDEBUG_ON
348           sprintf(errorLine,"*** TEST *** IN isFreeOK: (1) we found 0x%x in our inst. range!\n",ptr->addr);
349           logLine(errorLine);
350 #endif
351
352           return(false);     
353         }
354
355         for (unsigned int l=0;l<pcs.size();l++) {
356           // Condition 2
357           if ((pcs[l] >= ptr->addr) && 
358               (pcs[l] <= (ptr->addr + ptr->length))) 
359           {
360
361 #ifdef FREEDEBUG_ON
362     sprintf(errorLine,"*** TEST *** IN isFreeOK: (2) we found 0x%x in our inst. range!\n", ptr->addr);
363     logLine(errorLine);
364 #endif
365
366             return(false);
367           }
368           // Condition 3
369           if ( ((pcs[l] >= np->addr) && (pcs[l] <= (np->addr + np->length))) )
370           {
371
372 #ifdef FREEDEBUG_ON
373     sprintf(errorLine,"*** TEST *** IN isFreeOK: (3) we found PC in our inst. range!\n");
374     logLine(errorLine);
375 #endif
376
377             return(false);     
378           }
379         }
380       }
381     }
382   }
383   return(true);
384 }
385
386 //
387 // This procedure will try to compact the framented memory available in 
388 // heapFree. This is an emergency procedure that will be called if we
389 // are running out of memory to insert instrumentation - naim
390 //
391 void inferiorFreeCompact(inferiorHeap *hp)
392 {
393   unsigned size;
394   heapItem *np;
395   size = hp->heapFree.size();
396   unsigned j,i=0;
397
398 #ifdef FREEDEBUG
399   logLine("***** Trying to compact freed memory...\n");
400 #endif
401
402   while (i < size) {
403     np = hp->heapFree[i];
404 #ifdef FREEDEBUG1
405     sprintf(errorLine,"***** Checking address=%d\n",ALIGN_TO_WORDSIZE(np->addr+np->length));
406     logLine(errorLine);
407 #endif
408     for (j=0; j < size; j++) {
409       if (i != j) {
410         if ( (np->addr+np->length)==(hp->heapFree[j])->addr )
411         {
412           np->length += (hp->heapFree[j])->length;
413           hp->heapFree[j] = hp->heapFree[size-1];
414           hp->heapFree.resize(size-1);
415           size = hp->heapFree.size();
416 #ifdef FREEDEBUG1
417           sprintf(errorLine,"***** Compacting free memory (%d bytes, i=%d, j=%d, heapFree.size=%d)\n",np->length,i,j,size);
418           logLine(errorLine);
419 #endif
420           break;
421         }
422       }
423     }
424     if (j == size) i++;
425   }
426
427 #ifdef FREEDEBUG
428   for (i=0;i<hp->disabledList.size();i++) {
429     for (j=i+1;j<hp->disabledList.size();j++) {
430       if ( (hp->disabledList[i]).getPointer() == 
431            (hp->disabledList[j]).getPointer() ) {
432         sprintf(errorLine,"***** ERROR: address 0x%x appears more than once\n",(hp->disabledList[j]).getPointer());
433         logLine(errorLine);
434       }
435     }
436   }
437 #endif
438
439 #ifdef FREEDEBUG
440   logLine("***** Compact memory procedure END...\n");
441 #endif
442 }
443
444 void inferiorFreeDefered(process *proc, inferiorHeap *hp, bool runOutOfMem)
445 {
446   unsigned int i=0;
447   vector<Address> pcs;
448   vector<disabledItem> *disList;
449   timeStamp initTime, maxDelTime;
450
451   pcs = proc->walkStack();
452
453 #if defined(i386_unknown_nt4_0)
454   // It may not always be possible to get a correct stack walk.
455   // If walkStack fails, it returns an empty vector. In this
456   // case, we assume that it is not safe to delete anything
457   if (pcs.size() == 0)
458     return;
459 #endif
460
461   // this is a while loop since we don't update i if an item is deleted.
462   disList = &hp->disabledList;
463   if (runOutOfMem) {
464     maxDelTime = MAX_DELETING_TIME*2.0;
465     sprintf(errorLine,"Emergency attempt to free memory (pid=%d). Please, wait...\n",proc->getPid());
466     logLine(errorLine);
467 #ifdef FREEDEBUG1
468     sprintf(errorLine,"***** disList.size() = %d\n",disList->size());
469     logLine(errorLine);
470 #endif
471   }
472   else
473     maxDelTime = MAX_DELETING_TIME;
474   initTime=getCurrentTime(false);
475   while ( (i < disList->size()) && 
476           ((getCurrentTime(false)-initTime) < maxDelTime) )
477   {
478     disabledItem &item = (*disList)[i];
479     if (isFreeOK(proc,item,pcs)) {
480       heapItem *np=NULL;
481       unsigned pointer = item.getPointer();
482       if (!hp->heapActive.find(pointer,np)) {
483         showErrorCallback(96,"");
484         return;
485       }
486       assert(np);
487
488       if (np->status != HEAPallocated) {
489         sprintf(errorLine,"Attempt to free already freed heap entry %x\n", pointer);
490         logLine(errorLine);
491         showErrorCallback(67, (const char *)errorLine); 
492         return;
493       }
494       np->status = HEAPfree;      
495
496       // remove from active list.
497       hp->heapActive.undef(pointer);
498
499 #ifdef FREEDEBUG_ON
500    sprintf(errorLine,"inferiorFreeDefered: deleting 0x%x from heap\n",pointer);
501    logLine(errorLine);
502 #endif
503
504       hp->heapFree += np;
505       hp->freed += np->length;
506
507       // updating disabledList
508       hp->disabledList[i]=hp->disabledList[hp->disabledList.size()-1];
509       hp->disabledList.resize(hp->disabledList.size()-1);
510       hp->disabledListTotalMem -= np->length;
511       hp->totalFreeMemAvailable += np->length;
512       inferiorMemAvailable = hp->totalFreeMemAvailable;
513     } else {
514       i++;
515     }
516   }
517 }
518
519 void process::initInferiorHeap(bool initTextHeap)
520 {
521     assert(this->symbols);
522
523     inferiorHeap *hp;
524     if (initTextHeap) {
525         hp = &this->heaps[textHeap];
526     } else {
527         hp = &this->heaps[dataHeap];
528     }
529
530     heapItem *np = new heapItem;
531     if (initTextHeap) {
532         bool err;
533         np->addr = findInternalAddress("DYNINSTtext", true,err);
534         if (err)
535           abort();
536     } else {
537         bool err;
538         np->addr = findInternalAddress(INFERIOR_HEAP_BASE, true, err);
539         if (err)
540           abort();
541     }
542     np->length = SYN_INST_BUF_SIZE;
543     np->status = HEAPfree;
544
545     // make the heap double-word aligned
546     Address base = np->addr & ~0x1f;
547     Address diff = np->addr - base;
548     if (diff) {
549       np->addr = base + 32;
550       np->length -= (32 - diff);
551     }
552
553 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
554     hp->base = np->addr;
555     hp->size = np->length;
556 #endif /* BPATCH_SET_MUTATIONS_ACTIVE */
557
558     hp->totalFreeMemAvailable = np->length;
559     inferiorMemAvailable = hp->totalFreeMemAvailable;
560
561     // need to clear everything here, since this function may be called to 
562     // re-init a heap
563     hp->heapActive.clear();
564     hp->heapFree.resize(0);
565     hp->heapFree += np;
566     hp->disabledList.resize(0);
567     hp->disabledListTotalMem = 0;
568     hp->freed = 0;
569 }
570
571 // create a new inferior heap that is a copy of src. This is used when a process
572 // we are tracing forks.
573 inferiorHeap::inferiorHeap(const inferiorHeap &src):
574     heapActive(addrHash16)
575 {
576     for (unsigned u1 = 0; u1 < src.heapFree.size(); u1++) {
577       heapFree += new heapItem(src.heapFree[u1]);
578     }
579
580     vector<heapItem *> items = src.heapActive.values();
581     for (unsigned u2 = 0; u2 < items.size(); u2++) {
582       heapActive[items[u2]->addr] = new heapItem(items[u2]);
583     }
584     
585     for (unsigned u3 = 0; u3 < src.disabledList.size(); u3++) {
586       disabledList += src.disabledList[u3];
587     }
588     disabledListTotalMem = src.disabledListTotalMem;
589     totalFreeMemAvailable = src.totalFreeMemAvailable;
590     inferiorMemAvailable = totalFreeMemAvailable;
591     freed = 0;
592 }
593
594 #ifdef FREEDEBUG
595 void printHeapFree(process *proc, inferiorHeap *hp, int size)
596 {
597   for (unsigned i=0; i < hp->heapFree.size(); i++) {
598     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); 
599     logLine(errorLine);
600   }
601 }
602 #endif
603
604 //
605 // This function will return the index corresponding to the next position
606 // available in heapFree.
607 //
608 bool findFreeIndex(inferiorHeap *hp, int size, unsigned *index)
609 {
610   bool foundFree=false;
611   unsigned best=0;
612   int length=0;
613   for (unsigned i=0; i < hp->heapFree.size(); i++) {
614     length = (hp->heapFree[i])->length;
615     if (length >= size) {
616       foundFree = true;
617       best=i;
618       break;
619     }
620   }
621   if (index) 
622     *index = best;
623   else
624     foundFree=false;
625   return(foundFree);
626 }  
627
628 unsigned inferiorMalloc(process *proc, int size, inferiorHeapType type)
629 {
630     inferiorHeap *hp;
631     heapItem *np=NULL, *newEntry = NULL;
632
633     assert(size > 0);
634     /* round to next cache line size */
635     /* 32 bytes on a SPARC */
636     size = (size + 0x1f) & ~0x1f; 
637
638     if ((type == textHeap) && (proc->splitHeaps)) {
639         hp = &proc->heaps[textHeap];
640     } else {
641         hp = &proc->heaps[dataHeap];
642     }
643
644     bool secondChance=false;
645     unsigned foundIndex;
646     if (!findFreeIndex(hp,size,&foundIndex)) {
647
648 #ifdef FREEDEBUG
649       sprintf(errorLine,"==> TEST <== In inferiorMalloc: heap overflow, calling inferiorFreeDefered for a second chance...\n");
650       logLine(errorLine);
651 #endif
652
653       inferiorFreeDefered(proc, hp, true);
654       inferiorFreeCompact(hp);
655       secondChance=true;
656     }
657
658     if (secondChance && !findFreeIndex(hp,size,&foundIndex)) {
659
660 #ifdef FREEDEBUG
661       printHeapFree(proc,hp,size);
662 #endif
663
664       sprintf(errorLine, "***** Inferior heap overflow: %d bytes freed, %d bytes requested\n", hp->freed, size);
665       logLine(errorLine);
666       showErrorCallback(66, (const char *) errorLine);
667       P__exit(-1);
668       //return(0);
669     }
670
671     //
672     // We must have found a free position in heapFree
673     //
674
675     np = hp->heapFree[foundIndex];
676     assert(np);
677     if (np->length != size) {
678         // divide it up.
679         newEntry = new heapItem;
680         newEntry->length = np->length - size;
681         newEntry->addr = np->addr + size;
682         hp->totalFreeMemAvailable -= size;
683         inferiorMemAvailable = hp->totalFreeMemAvailable;
684         // overwrite the old entry
685         hp->heapFree[foundIndex] = newEntry;
686
687         /* now split curr */
688         np->length = size;
689     } else {
690       unsigned i = hp->heapFree.size();
691       // copy the last element over this element
692       hp->heapFree[foundIndex] = hp->heapFree[i-1];
693       hp->heapFree.resize(i-1);
694     }
695
696     // mark it used
697     np->status = HEAPallocated;
698
699     // onto in use list
700     hp->heapActive[np->addr] = np;
701
702     // make sure its a valid pointer.
703     assert(np->addr);
704
705     return(np->addr);
706 }
707
708 void inferiorFree(process *proc, unsigned pointer, inferiorHeapType type,
709                   const vector<unsigVecType> &pointsToCheck)
710 {
711     inferiorHeapType which = (type == textHeap && proc->splitHeaps) ? textHeap : dataHeap;
712     inferiorHeap *hp = &proc->heaps[which];
713     heapItem *np=NULL;
714
715     if (!hp->heapActive.find(pointer, np)) {
716       showErrorCallback(96,"");
717       return;
718     }
719     assert(np);
720
721     disabledItem newItem(pointer, which, pointsToCheck);
722
723 #ifdef FREEDEBUG
724     for (unsigned i=0;i<hp->disabledList.size();i++) {
725       if (hp->disabledList[i].getPointer() == pointer) {
726         sprintf(errorLine,"***** ERROR, pointer 0x%x already defined in disabledList\n",pointer);
727         logLine(errorLine);
728       }
729     }
730 #endif
731
732     hp->disabledList += newItem;
733     hp->disabledListTotalMem += np->length;
734
735 #ifdef FREEDEBUG1
736     sprintf(errorLine,"==> TEST <== In inferiorFree: disabledList has %d items, %d bytes, and FREE_WATERMARK is %d\n",hp->disabledList.size(),hp->disabledListTotalMem,FREE_WATERMARK);
737     logLine(errorLine);
738     for (unsigned i=0; i < hp->disabledList.size(); i++) {
739         sprintf(errorLine, "   %x is on list\n", hp->disabledList[i].pointer);
740         logLine(errorLine);
741     }
742 #endif
743
744     //
745     // If the size of the disabled instrumentation list is greater than
746     // half of the size of the heapFree list, then we attempt to free
747     // all the defered requests. In my opinion, this seems to be a good
748     // time to proceed with the defered delete since this is an expensive
749     // procedure and should not be executed often - naim 03/19/96
750     //
751     if (((hp->disabledListTotalMem > FREE_WATERMARK) ||
752          (hp->disabledList.size() > SIZE_WATERMARK)) && waitingPeriodIsOver()) 
753     {
754
755 #ifdef FREEDEBUG
756 timeStamp t1,t2;
757 static timeStamp t3=0.0;
758 static timeStamp totalTime=0.0;
759 static timeStamp worst=0.0;
760 static int counter=0;
761 t1=getCurrentTime(false);
762 #endif
763
764       inferiorFreeDefered(proc, hp, false);
765
766 #ifdef FREEDEBUG
767 t2=getCurrentTime(false);
768 if (!t3) t3=t1;
769 counter++;
770 totalTime += t2-t1;
771 if ((t2-t1) > worst) worst=t2-t1;
772 if ((float)(t2-t1) > 1.0) {
773   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));
774   logLine(errorLine);
775 }
776 t3=t1;
777 #endif
778
779     }
780 }
781
782
783 // initializes all DYNINST lib stuff: init the inferior heap and check for 
784 // required symbols.
785 // This is only called after we get the first breakpoint (SIGTRAP), because
786 // the DYNINST lib can be dynamically linked (currently it is only dynamically
787 // linked on Windows NT)
788 bool process::initDyninstLib() {
789
790 #if defined(i386_unknown_nt4_0)
791    /***
792      Kludge for Windows NT: we need to call waitProcs here so that
793      we can load libdyninstRT when we attach to an already running
794      process. The solution to avoid this kludge is to divide 
795      attachProcess in two parts: first we attach to a process,
796      and later, after libdyninstRT has been loaded,
797      we install the call to DYNINSTinit.
798     ***/
799
800    // libDyninstRT should already be loaded when we get here,
801    // except if the process was created via attach
802    if (createdViaAttach) {
803      // need to set reachedFirstBreak to false here, so that
804      // libdyninstRT gets loaded in waitProcs.
805      reachedFirstBreak = false;
806      while (!hasLoadedDyninstLib) {
807        int status;
808        waitProcs(&status);
809      }
810    }
811    assert(hasLoadedDyninstLib);
812 #endif
813
814
815   extern vector<sym_data> syms_to_find;
816   if (!heapIsOk(syms_to_find))
817     return false;
818
819   initInferiorHeap(false);
820   if (splitHeaps)
821     initInferiorHeap(true);
822
823   return true;
824 }
825
826
827
828 //
829 // Process "normal" (non-attach, non-fork) ctor, for when a new process
830 // is fired up by paradynd itself.
831 //
832
833 process::process(int iPid, image *iImage, int iTraceLink, int iIoLink
834 #ifdef SHM_SAMPLING
835                  , key_t theShmKey,
836                  const vector<fastInferiorHeapMgr::oneHeapStats> &iShmHeapStats
837 #endif
838 ) :
839              baseMap(ipHash), 
840              pid(iPid) // needed in fastInferiorHeap ctors below
841 #ifdef SHM_SAMPLING
842              ,previous(0),
843              inferiorHeapMgr(theShmKey, iShmHeapStats, iPid),
844              theSuperTable(this,
845                         iShmHeapStats[0].maxNumElems,
846                         iShmHeapStats[1].maxNumElems,
847                         iShmHeapStats[2].maxNumElems)
848 #endif
849 {
850     hasBootstrapped = false;
851     save_exitset_ptr = NULL;
852
853     // the next two variables are used only if libdyninstRT is dynamically linked
854     hasLoadedDyninstLib = false;
855     isLoadingDyninstLib = false;
856
857     reachedFirstBreak = false; // haven't yet seen first trap
858     reachedVeryFirstTrap = false;
859     createdViaAttach = false;
860     needToContinueAfterDYNINSTinit = false;  //Wait for press of "RUN" button
861
862     symbols = iImage;
863     mainFunction = NULL; // set in platform dependent function heapIsOk
864
865     status_ = neonatal;
866     continueAfterNextStop_ = false;
867     deferredContinueProc = false;
868
869 #ifndef BPATCH_LIBRARY
870     string buffer = string(pid) + string("_") + getHostName();
871     rid = resource::newResource(processResource, // parent
872                                 (void*)this, // handle
873                                 nullString, // abstraction
874                                 iImage->name(), // process name
875                                 0.0, // creation time
876                                 buffer, // unique name (?)
877                                 MDL_T_STRING, // mdl type (?)
878                                 true
879                                 );
880 #endif
881
882     parent = NULL;
883     bufStart = 0;
884     bufEnd = 0;
885     inExec = false;
886
887     cumObsCost = 0;
888     lastObsCostLow = 0;
889
890     proc_fd = -1;
891
892     trampTableItems = 0;
893     memset(trampTable, 0, sizeof(trampTable));
894     currentPC_ = 0;
895     hasNewPC = false;
896     
897     dynamiclinking = false;
898     dyn = new dynamic_linking;
899     shared_objects = 0;
900     all_functions = 0;
901     all_modules = 0;
902     some_modules = 0;
903     some_functions = 0;
904     waiting_for_resources = false;
905     signal_handler = 0;
906     execed_ = false;
907
908 #ifdef SHM_SAMPLING
909 #ifdef sparc_sun_sunos4_1_3
910    kvmHandle = kvm_open(0, 0, 0, O_RDONLY, 0);
911    if (kvmHandle == NULL) {
912       perror("could not map child's uarea; kvm_open");
913       exit(5);
914    }
915
916 //   childUareaPtr = tryToMapChildUarea(iPid);
917    childUareaPtr = NULL;
918 #endif
919 #endif
920
921    splitHeaps = false;
922
923 #if defined(rs6000_ibm_aix3_2) || defined(rs6000_ibm_aix4_1)
924         // XXXX - move this to a machine dependant place.
925
926         // create a seperate text heap.
927         //initInferiorHeap(true);
928         splitHeaps = true;
929 #endif
930
931    traceLink = iTraceLink;
932    ioLink = iIoLink;
933
934    RPCs_waiting_for_syscall_to_complete = false;
935
936    // attach to the child process (machine-specific implementation)
937    attach(); // error check?
938 }
939
940 //
941 // Process "attach" ctor, for when paradynd is attaching to an already-existing
942 // process.
943 //
944
945 process::process(int iPid, image *iSymbols,
946                  int afterAttach, // 1 --> pause, 2 --> run, 0 --> leave as is
947                  bool &success
948 #ifdef SHM_SAMPLING
949                  , key_t theShmKey,
950                  const vector<fastInferiorHeapMgr::oneHeapStats> &iShmHeapStats
951 #endif
952                  ) :
953                  baseMap(ipHash),
954                  pid(iPid)
955 #ifdef SHM_SAMPLING
956              ,previous(0),
957              inferiorHeapMgr(theShmKey, iShmHeapStats, iPid),
958              theSuperTable(this,
959                         iShmHeapStats[0].maxNumElems,
960                         iShmHeapStats[1].maxNumElems,
961                         iShmHeapStats[2].maxNumElems)
962 #endif
963 {
964    RPCs_waiting_for_syscall_to_complete = false;
965    save_exitset_ptr = NULL;
966
967    hasBootstrapped = false;
968    reachedFirstBreak = true; // the initial trap of program entry was passed long ago...
969    reachedVeryFirstTrap = true;
970    createdViaAttach = true;
971
972    // the next two variables are used only if libdyninstRT is dynamically linked
973    hasLoadedDyninstLib = false;
974    isLoadingDyninstLib = false;
975
976    symbols = iSymbols;
977    mainFunction = NULL; // set in platform dependent function heapIsOk
978
979    status_ = neonatal;
980    continueAfterNextStop_ = false;
981    deferredContinueProc = false;
982
983 #ifndef BPATCH_LIBRARY
984     string buffer = string(pid) + string("_") + getHostName();
985     rid = resource::newResource(processResource, // parent
986                                 (void*)this, // handle
987                                 nullString, // abstraction
988                                 symbols->name(),
989                                 0.0, // creation time
990                                 buffer, // unique name (?)
991                                 MDL_T_STRING, // mdl type (?)
992                                 true
993                                 );
994 #endif
995
996     parent = NULL;
997     bufStart = 0;
998     bufEnd = 0;
999     inExec = false;
1000
1001     cumObsCost = 0;
1002     lastObsCostLow = 0;
1003
1004     proc_fd = -1;
1005
1006     trampTableItems = 0;
1007     memset(trampTable, 0, sizeof(trampTable));
1008     currentPC_ = 0;
1009     hasNewPC = false;
1010     
1011     dynamiclinking = false;
1012     dyn = new dynamic_linking;
1013     shared_objects = 0;
1014     all_functions = 0;
1015     all_modules = 0;
1016     some_modules = 0;
1017     some_functions = 0;
1018     waiting_for_resources = false;
1019     signal_handler = 0;
1020     execed_ = false;
1021
1022     splitHeaps = false;
1023
1024 #if defined(rs6000_ibm_aix3_2) || defined(rs6000_ibm_aix4_1)
1025         // XXXX - move this to a machine dependant place.
1026
1027         // create a seperate text heap.
1028         //initInferiorHeap(true);
1029         splitHeaps = true;
1030 #endif
1031
1032    traceLink = -1; // will be set later, when the appl runs DYNINSTinit
1033
1034    ioLink = -1; // (ARGUABLY) NOT YET IMPLEMENTED...MAYBE WHEN WE ATTACH WE DON'T WANT
1035                 // TO REDIRECT STDIO SO WE CAN LEAVE IT AT -1.
1036
1037    // Now the actual attach...the moment we've all been waiting for
1038
1039    attach_cerr << "process attach ctor: about to attach to pid " << getPid() << endl;
1040
1041    // It is assumed that a call to attach() doesn't affect the running status
1042    // of the process.  But, unfortunately, some platforms may barf if the
1043    // running status is anything except paused. (How to deal with this?)
1044    // Note that solaris in particular seems able to attach even if the process
1045    // is running.
1046    if (!attach()) {
1047       showErrorCallback(26, ""); // unable-to-attach
1048       success = false;
1049       return;
1050    }
1051
1052 #if defined(BPATCH_LIBRARY) && defined(rs6000_ibm_aix4_1)
1053    wasRunningWhenAttached = false; /* XXX Or should the default be true? */
1054 #else
1055    wasRunningWhenAttached = isRunning_();
1056 #endif
1057
1058 #if defined(BPATCH_LIBRARY) && defined(rs6000_ibm_aix4_1)
1059    // We use ptrace of AIX, which stops the process on attach.
1060    status_ = stopped;
1061 #else
1062    // Note: we used to pause the program here, but not anymore.
1063    status_ = running;
1064 #endif
1065
1066 #ifdef i386_unknown_nt4_0 // Except we still pause on NT.
1067     if (!pause())
1068         assert(false);
1069 #endif
1070
1071    if (afterAttach == 0)
1072       needToContinueAfterDYNINSTinit = wasRunningWhenAttached;
1073    else if (afterAttach == 1)
1074       needToContinueAfterDYNINSTinit = false;
1075    else if (afterAttach == 2)
1076       needToContinueAfterDYNINSTinit = true;
1077    else
1078       assert(false);
1079
1080    // Does attach() send a SIGTRAP, a la the initial SIGTRAP sent at the
1081    // end of exec?  It seems that on some platforms it does; on others
1082    // it doesn't.  Ick.  On solaris, it doesn't.
1083
1084    // note: we don't call getSharedObjects() yet; that happens once DYNINSTinit
1085    //       finishes (handleStartProcess)
1086
1087    // Everything worked
1088    success = true;
1089 }
1090
1091 //
1092 // Process "fork" ctor, for when a process which is already being monitored by
1093 // paradynd executes the fork syscall.
1094 //
1095
1096 process::process(const process &parentProc, int iPid, int iTrace_fd
1097 #ifdef SHM_SAMPLING
1098                  ,key_t theShmKey,
1099                  void *applShmSegPtr,
1100                  const vector<fastInferiorHeapMgr::oneHeapStats> &iShmHeapStats
1101 #endif
1102                  ) :
1103                      baseMap(ipHash) // could change to baseMap(parentProc.baseMap)
1104 #ifdef SHM_SAMPLING
1105                      ,previous(0),
1106                      inferiorHeapMgr(parentProc.inferiorHeapMgr, 
1107                                       applShmSegPtr,
1108                                       theShmKey, iShmHeapStats, iPid)
1109                      ,theSuperTable(parentProc.getTable(),this)
1110 #endif
1111 {
1112     // This is the "fork" ctor
1113
1114     RPCs_waiting_for_syscall_to_complete = false;
1115     save_exitset_ptr = NULL;
1116
1117     hasBootstrapped = false;
1118        // The child of fork ("this") has yet to run DYNINSTinit.
1119
1120     // the next two variables are used only if libdyninstRT is dynamically linked
1121     hasLoadedDyninstLib = false; // TODO: is this the right value?
1122     isLoadingDyninstLib = false;
1123
1124     createdViaAttach = parentProc.createdViaAttach;
1125     wasRunningWhenAttached = true;
1126     needToContinueAfterDYNINSTinit = true;
1127
1128     symbols = parentProc.symbols; // shouldn't a reference count also be bumped?
1129     mainFunction = parentProc.mainFunction;
1130
1131     traceLink = iTrace_fd;
1132
1133     ioLink = -1; // when does this get set?
1134
1135     status_ = neonatal; // is neonatal right?
1136     continueAfterNextStop_ = false;
1137     deferredContinueProc = false;
1138
1139     pid = iPid; 
1140
1141 #ifndef BPATCH_LIBRARY
1142     string buffer = string(pid) + string("_") + getHostName();
1143     rid = resource::newResource(processResource, // parent
1144                                 (void*)this, // handle
1145                                 nullString, // abstraction
1146                                 parentProc.symbols->name(),
1147                                 0.0, // creation time
1148                                 buffer, // unique name (?)
1149                                 MDL_T_STRING, // mdl type (?)
1150                                 true
1151                                 );
1152 #endif
1153
1154     parent = &parentProc;
1155     
1156     bufStart = 0;
1157     bufEnd = 0;
1158
1159     reachedFirstBreak = true; // initial TRAP has (long since) been reached
1160     reachedVeryFirstTrap = true;
1161
1162     splitHeaps = parentProc.splitHeaps;
1163
1164     heaps[0] = inferiorHeap(parentProc.heaps[0]);
1165     heaps[1] = inferiorHeap(parentProc.heaps[1]);
1166
1167     inExec = false;
1168
1169     cumObsCost = 0;
1170     lastObsCostLow = 0;
1171
1172     proc_fd = -1;
1173
1174     trampTableItems = 0;
1175     memset(trampTable, 0, sizeof(trampTable));
1176     currentPC_ = 0;
1177     hasNewPC = false;
1178
1179     dynamiclinking = parentProc.dynamiclinking;
1180     dyn = new dynamic_linking;
1181     *dyn = *parentProc.dyn;
1182
1183     shared_objects = 0;
1184
1185     // make copy of parent's shared_objects vector
1186     if (parentProc.shared_objects) {
1187       shared_objects = new vector<shared_object*>;
1188       for (unsigned u1 = 0; u1 < parentProc.shared_objects->size(); u1++){
1189         *shared_objects += 
1190                 new shared_object(*(*parentProc.shared_objects)[u1]);
1191       }
1192     }
1193
1194     all_functions = 0;
1195     if (parentProc.all_functions) {
1196       all_functions = new vector<function_base *>;
1197       for (unsigned u2 = 0; u2 < parentProc.all_functions->size(); u2++)
1198         *all_functions += (*parentProc.all_functions)[u2];
1199     }
1200
1201     all_modules = 0;
1202     if (parentProc.all_modules) {
1203       all_modules = new vector<module *>;
1204       for (unsigned u3 = 0; u3 < parentProc.all_modules->size(); u3++)
1205         *all_modules += (*parentProc.all_modules)[u3];
1206     }
1207
1208     some_modules = 0;
1209     if (parentProc.some_modules) {
1210       some_modules = new vector<module *>;
1211       for (unsigned u4 = 0; u4 < parentProc.some_modules->size(); u4++)
1212         *some_modules += (*parentProc.some_modules)[u4];
1213     }
1214     
1215     some_functions = 0;
1216     if (parentProc.some_functions) {
1217       some_functions = new vector<function_base *>;
1218       for (unsigned u5 = 0; u5 < parentProc.some_functions->size(); u5++)
1219         *some_functions += (*parentProc.some_functions)[u5];
1220     }
1221
1222     waiting_for_resources = false;
1223     signal_handler = parentProc.signal_handler;
1224     execed_ = false;
1225
1226    // threads...
1227    for (unsigned i=0; i<parentProc.threads.size(); i++) {
1228      threads += new pdThread(this,parentProc.threads[i]);
1229    }
1230
1231 #if defined(SHM_SAMPLING) && defined(sparc_sun_sunos4_1_3)
1232    childUareaPtr = NULL;
1233 #endif
1234
1235 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
1236    // thread mapping table
1237    threadMap = new hashTable(parentProc.threadMap);
1238 #endif
1239
1240    if (!attach()) {     // moved from ::forkProcess
1241       showErrorCallback(69, "Error in fork: cannot attach to child process");
1242    }
1243
1244    status_ = stopped;
1245       // would neonatal be more appropriate?  Nah, we've reached the first trap
1246 }
1247
1248 #ifdef SHM_SAMPLING
1249 void process::registerInferiorAttachedSegs(void *inferiorAttachedAtPtr) {
1250    shmsample_cerr << "process pid " << getPid() << ": welcome to register with inferiorAttachedAtPtr=" << inferiorAttachedAtPtr << endl;
1251
1252    inferiorHeapMgr.registerInferiorAttachedAt(inferiorAttachedAtPtr);
1253    theSuperTable.setBaseAddrInApplic(0,(intCounter*) inferiorHeapMgr.getSubHeapInApplic(0));
1254    theSuperTable.setBaseAddrInApplic(1,(tTimer*) inferiorHeapMgr.getSubHeapInApplic(1));
1255    theSuperTable.setBaseAddrInApplic(2,(tTimer*) inferiorHeapMgr.getSubHeapInApplic(2));
1256 }
1257 #endif
1258
1259
1260 extern bool forkNewProcess(string file, string dir, vector<string> argv, 
1261                     vector<string>envp, string inputFile, string outputFile,
1262                     int &traceLink, int &ioLink, 
1263                     int &pid, int &tid, 
1264                     int &procHandle, int &thrHandle);
1265
1266 /*
1267  * Create a new instance of the named process.  Read the symbols and start
1268  *   the program
1269  */
1270 process *createProcess(const string File, vector<string> argv, vector<string> envp, const string dir = "")
1271 {
1272     // prepend the directory (if any) to the file, unless the filename
1273     // starts with a /
1274     string file = File;
1275     if (!file.prefixed_by("/") && dir.length() > 0)
1276       file = dir + "/" + file;
1277
1278 #if defined(BPATCH_LIBRARY) && !defined(BPATCH_REDIRECT_IO)
1279     string inputFile;
1280     string outputFile;
1281 #else
1282     // check for I/O redirection in arg list.
1283     string inputFile;
1284     for (unsigned i1=0; i1<argv.size(); i1++) {
1285       if (argv[i1] == "<") {
1286         inputFile = argv[i1+1];
1287         for (unsigned j=i1+2, k=i1; j<argv.size(); j++, k++)
1288           argv[k] = argv[j];
1289         argv.resize(argv.size()-2);
1290       }
1291     }
1292     // TODO -- this assumes no more than 1 of each "<", ">"
1293     string outputFile;
1294     for (unsigned i2=0; i2<argv.size(); i2++) {
1295       if (argv[i2] == ">") {
1296         outputFile = argv[i2+1];
1297         for (unsigned j=i2+2, k=i2; j<argv.size(); j++, k++)
1298           argv[k] = argv[j];
1299         argv.resize(argv.size()-2);
1300       }
1301     }
1302 #endif /* BPATCH_LIBRARY */
1303
1304     int traceLink;
1305     int ioLink;
1306     int pid;
1307     int tid;
1308     int procHandle;
1309     int thrHandle;
1310
1311     if (!forkNewProcess(file, dir, argv, envp, inputFile, outputFile,
1312                    traceLink, ioLink, pid, tid, procHandle, thrHandle)) {
1313       // forkNewProcess is resposible for displaying error messages
1314       return NULL;
1315     }
1316
1317 #ifdef BPATCH_LIBRARY
1318     // Register the pid with the BPatch library (not yet associated with a
1319     // BPatch_thread object).
1320     assert(BPatch::bpatch != NULL);
1321     BPatch::bpatch->registerProvisionalThread(pid);
1322 #endif
1323
1324 #if defined(rs6000_ibm_aix3_2) || defined(rs6000_ibm_aix4_1)
1325         extern bool establishBaseAddrs(int pid, int &status, bool waitForTrap);
1326         int status;
1327
1328         if (!establishBaseAddrs(pid, status, true)) {
1329             return(NULL);
1330         }
1331 #endif
1332
1333 #ifndef BPATCH_LIBRARY
1334 // NEW: We bump up batch mode here; the matching bump-down occurs after shared objects
1335 //      are processed (after receiving the SIGSTOP indicating the end of running
1336 //      DYNINSTinit; more specifically, procStopFromDYNINSTinit().
1337 //      Prevents a diabolical w/w deadlock on solaris --ari
1338 tp->resourceBatchMode(true);
1339 #endif /* BPATCH_LIBRARY */
1340
1341         image *img = image::parseImage(file);
1342         if (!img) {
1343             // For better error reporting, two failure return values would be useful
1344             // One for simple error like because-file-not-because
1345             // Another for serious errors like found-but-parsing-failed (internal error;
1346             //    please report to paradyn@cs.wisc.edu)
1347
1348             string msg = string("Unable to parse image: ") + file;
1349             showErrorCallback(68, msg.string_of());
1350             // destroy child process
1351             OS::osKill(pid);
1352
1353             return(NULL);
1354         }
1355
1356         /* parent */
1357         statusLine("initializing process data structures");
1358
1359 #ifdef SHM_SAMPLING
1360         vector<fastInferiorHeapMgr::oneHeapStats> theShmHeapStats(3);
1361         theShmHeapStats[0].elemNumBytes = sizeof(intCounter);
1362         theShmHeapStats[0].maxNumElems  = numIntCounters;
1363
1364         theShmHeapStats[1].elemNumBytes = sizeof(tTimer);
1365         theShmHeapStats[1].maxNumElems  = numWallTimers;
1366
1367         theShmHeapStats[2].elemNumBytes = sizeof(tTimer);
1368         theShmHeapStats[2].maxNumElems  = numProcTimers;
1369 #endif
1370
1371         process *ret = new process(pid, img, traceLink, ioLink
1372 #ifdef SHM_SAMPLING
1373                                    , 7000, // shm seg key to try first
1374                                    theShmHeapStats
1375 #endif
1376                                    );
1377            // change this to a ctor that takes in more args
1378
1379         assert(ret);
1380
1381         processVec += ret;
1382         activeProcesses++;
1383
1384 #ifndef BPATCH_LIBRARY
1385         if (!costMetric::addProcessToAll(ret))
1386            assert(false);
1387 #endif
1388         // find the signal handler function
1389         ret->findSignalHandler(); // should this be in the ctor?
1390
1391         // initializing vector of threads - thread[0] is really the 
1392         // same process
1393
1394 #if defined(i386_unknown_nt4_0)
1395         ret->threads += new pdThread(ret, tid, (handleT)thrHandle);
1396 #else
1397         ret->threads += new pdThread(ret);
1398 #endif
1399
1400         // initializing hash table for threads. This table maps threads to
1401         // positions in the superTable - naim 4/14/97
1402 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
1403         ret->threadMap = new hashTable(MAX_NUMBER_OF_THREADS,1,0);
1404 #endif
1405
1406         // we use this flag to solve race condition between inferiorRPC and 
1407         // continueProc message from paradyn - naim
1408         ret->deferredContinueProc = false;
1409
1410         ret->numOfActCounters_is=0;
1411         ret->numOfActProcTimers_is=0;
1412         ret->numOfActWallTimers_is=0;
1413
1414 #if defined(rs6000_ibm_aix3_2) || defined(rs6000_ibm_aix4_1)
1415         // XXXX - this is a hack since establishBaseAddrs needed to wait for
1416         //    the TRAP signal.
1417         // We really need to move most of the above code (esp parse image)
1418         //    to the TRAP signal handler.  The problem is that we don't
1419         //    know the base addresses until we get the load info via ptrace.
1420         //    In general it is even harder, since dynamic libs can be loaded
1421         //    at any time.
1422         extern int handleSigChild(int pid, int status);
1423
1424         (void) handleSigChild(pid, status);
1425 #endif
1426     return ret;
1427
1428 }
1429
1430
1431 void process::DYNINSTinitCompletionCallback(process *theProc,
1432                                             void *, // user data
1433                                             unsigned // return value from DYNINSTinit
1434                                             ) {
1435    attach_cerr << "Welcome to DYNINSTinitCompletionCallback" << endl;
1436    theProc->handleCompletionOfDYNINSTinit(true);
1437 }
1438
1439
1440 bool attachProcess(const string &progpath, int pid, int afterAttach
1441 #ifdef BPATCH_LIBRARY
1442                    , process *&newProcess
1443 #endif
1444                    ) {
1445    // implementation of dynRPC::attach() (the igen call)
1446    // This is meant to be "the other way" to start a process (competes w/ createProcess)
1447
1448    // progpath gives the full path name of the executable, which we use ONLY to
1449    // read the symbol table.
1450
1451    // We try to make progpath optional, since given pid, we should be able to
1452    // calculate it with a clever enough search of the process' PATH, examining
1453    // its argv[0], examining its current directory, etc.  /proc gives us this
1454    // information on solaris...not sure about other platforms...
1455
1456    // possible values for afterAttach: 1 --> pause, 2 --> run, 0 --> leave as is
1457
1458    attach_cerr << "welcome to attachProcess for pid " << pid << endl;
1459
1460    // QUESTION: When we attach to a process, do we want to redirect its stdout/stderr
1461    //           (like we do when we fork off a new process the 'usual' way)?
1462    //           My first guess would be no.  -ari
1463    //           But although we may ignore the io, we still need the trace stream.
1464
1465    // When we attach to a process, we don't fork...so this routine is much simpler
1466    // than its "competitor", createProcess() (above).
1467
1468    // TODO: What about AIX establishBaseAddrs???  Do that now?
1469
1470    string fullPathToExecutable = process::tryToFindExecutable(progpath, pid);
1471    if (!fullPathToExecutable.length())
1472       return false;
1473
1474 #ifndef BPATCH_LIBRARY
1475    tp->resourceBatchMode(true);
1476       // matching bump-down occurs in procStopFromDYNINSTinit().
1477 #endif
1478
1479    image *theImage = image::parseImage(fullPathToExecutable);
1480    if (theImage == NULL) {
1481       // two failure return values would be useful here, to differentiate
1482       // file-not-found vs. catastrophic-parse-error.
1483       string msg = string("Unable to parse image: ") + fullPathToExecutable;
1484       showErrorCallback(68, msg.string_of());
1485       return false; // failure
1486    }
1487
1488 #ifdef SHM_SAMPLING
1489    vector<fastInferiorHeapMgr::oneHeapStats> theShmHeapStats(3);
1490    theShmHeapStats[0].elemNumBytes = sizeof(intCounter);
1491    theShmHeapStats[0].maxNumElems  = numIntCounters;
1492
1493    theShmHeapStats[1].elemNumBytes = sizeof(tTimer);
1494    theShmHeapStats[1].maxNumElems  = numWallTimers;
1495
1496    theShmHeapStats[2].elemNumBytes = sizeof(tTimer);
1497    theShmHeapStats[2].maxNumElems  = numProcTimers;
1498 #endif
1499
1500    // NOTE: the actual attach happens in the process "attach" constructor:
1501    bool success;
1502    process *theProc = new process(pid, theImage, afterAttach, success
1503 #ifdef SHM_SAMPLING
1504                                   ,7000, // shm seg key to try first
1505                                   theShmHeapStats
1506 #endif                            
1507                                   );
1508    assert(theProc);
1509    if (!success) {
1510        // XXX Do we need to do something to get rid of theImage, too?
1511        delete theProc;
1512        return false;
1513    }
1514
1515    // Note: it used to be that the attach ctor called pause()...not anymore...so
1516    // the process is probably running even as we speak.
1517
1518    processVec += theProc;
1519    activeProcesses++;
1520
1521    theProc->threads += new pdThread(theProc);
1522
1523 #if defined(USES_LIBDYNINSTRT_SO)
1524    // we now need to dynamically load libdyninstRT.so.1 - naim
1525    if (theProc->handleStartProcess()) {
1526      if (!theProc->pause()) {
1527        logLine("WARNING: pause failed\n");
1528        assert(0);
1529      }
1530      theProc->dlopenDYNINSTlib();
1531      // this will set isLoadingDyninstLib to true - naim
1532      if (!theProc->continueProc()) {
1533        logLine("WARNING: continueProc failed\n");
1534        assert(0);
1535      }
1536      int status;
1537      while (!theProc->dyninstLibAlreadyLoaded()) {
1538        theProc->waitProcs(&status);
1539      }
1540    }
1541 #endif
1542
1543    theProc->initDyninstLib();
1544
1545 #ifndef BPATCH_LIBRARY
1546    if (!costMetric::addProcessToAll(theProc))
1547       assert(false);
1548 #endif
1549
1550    // find the signal handler function
1551    theProc->findSignalHandler(); // shouldn't this be in the ctor?
1552
1553    // Now force DYNINSTinit() to be invoked, via inferiorRPC.
1554    string buffer = string("PID=") + string(pid) + ", running DYNINSTinit()...";
1555    statusLine(buffer.string_of());
1556
1557 #ifdef BPATCH_LIBRARY
1558    newProcess = theProc;
1559
1560    vector<AstNode*> the_args(2);
1561
1562    the_args[0] = new AstNode(AstNode::Constant, (void*)3);
1563    the_args[1] = new AstNode(AstNode::Constant, (void*)getpid());
1564 #else /* BPATCH_LIBRARY */
1565    attach_cerr << "calling DYNINSTinit with args:" << endl;
1566
1567    vector<AstNode*> the_args(3);
1568
1569 #ifdef SHM_SAMPLING
1570    the_args[0] = new AstNode(AstNode::Constant,
1571                              (void*)(theProc->getShmKeyUsed()));
1572    attach_cerr << theProc->getShmKeyUsed() << endl;
1573
1574    const unsigned shmHeapTotalNumBytes = theProc->getShmHeapTotalNumBytes();
1575    the_args[1] = new AstNode(AstNode::Constant,
1576                              (void*)shmHeapTotalNumBytes);
1577    attach_cerr << shmHeapTotalNumBytes << endl;;
1578 #else
1579    // 2 dummy args when not shm sampling -- just make sure they're not both -1, which
1580    // would indicate that we're called from fork
1581    the_args[0] = new AstNode(AstNode::Constant, (void*)0);
1582    the_args[1] = new AstNode(AstNode::Constant, (void*)0);
1583 #endif
1584
1585    /*
1586       The third argument to DYNINSTinit is our (paradynd's) pid. It is used
1587       by DYNINSTinit to build the socket path to which it connects to in order
1588       to get the trace-stream connection.  We make it negative to indicate
1589       to DYNINSTinit that it's being called from attach (sorry for that little
1590       kludge...if we didn't have it, we'd probably need to boost DYNINSTinit
1591       from 3 to 4 parameters).
1592       
1593       This socket is set up in controllerMainLoop (perfStream.C).
1594    */
1595    the_args[2] = new AstNode(AstNode::Constant, (void*)(-1 * traceConnectInfo));
1596    attach_cerr << (-1* getpid()) << endl;
1597 #endif /* BPATCH_LIBRARY */
1598
1599    AstNode *the_ast = new AstNode("DYNINSTinit", the_args);
1600    for (unsigned j=0;j<the_args.size();j++) removeAst(the_args[j]);
1601
1602    theProc->postRPCtoDo(the_ast,
1603                         true, // true --> don't try to update cost yet
1604                         process::DYNINSTinitCompletionCallback, // callback routine
1605                         NULL, // user data
1606                         -1);  // we use -1 if this is not metric definition - naim
1607       // the rpc will be launched with a call to launchRPCifAppropriate()
1608       // in the main loop (perfStream.C).
1609       // DYNINSTinit() ends with a DYNINSTbreakPoint(), so we pick up
1610       // where we left off in the processing of the forwarded SIGSTOP signal.
1611       // In other words, there's lots more work to do, but since we can't do it until
1612       // DYNINSTinit has run, we wait until the SIGSTOP is forwarded.
1613
1614    // Note: we used to pause() the process while attaching.  Not anymore.
1615    // The attached process is running even as we speak.  (Though we'll interrupt
1616    // it pretty soon when the inferior RPC of DYNINSTinit gets launched).
1617
1618    return true; // successful
1619 }
1620
1621 #ifdef SHM_SAMPLING
1622 bool process::doMajorShmSample(time64 theWallTime) {
1623    bool result = true; // will be set to false if any processAll() doesn't complete
1624                        // successfully.
1625
1626    if (!theSuperTable.doMajorSample  (theWallTime, 0))
1627       result = false;
1628       // inferiorProcessTimers used to take in a non-dummy process time as the
1629       // 2d arg, but it looks like that we need to re-read the process time for
1630       // each proc timer, at the time of sampling the timer's value, to avoid
1631       // ugly jagged spikes in histogram (i.e. to avoid incorrect sampled 
1632       // values).  Come to think of it: the same may have to be done for the 
1633       // wall time too!!!
1634
1635    const time64 theProcTime = getInferiorProcessCPUtime();
1636
1637    // Now sample the observed cost.
1638    unsigned *costAddr = this->getObsCostLowAddrInParadyndSpace();
1639    const unsigned theCost = *costAddr; // WARNING: shouldn't we be using a mutex?!
1640
1641    this->processCost(theCost, theWallTime, theProcTime);
1642
1643    return result;
1644 }
1645
1646 bool process::doMinorShmSample() {
1647    // Returns true if the minor sample has successfully completed all outstanding
1648    // samplings.
1649    bool result = true; // so far...
1650
1651    if (!theSuperTable.doMinorSample())
1652       result = false;
1653
1654    return result;
1655 }
1656 #endif
1657
1658 extern void removeFromMetricInstances(process *);
1659 extern void disableAllInternalMetrics();
1660
1661 void handleProcessExit(process *proc, int exitStatus) {
1662   if (proc->status() == exited)
1663     return;
1664
1665   proc->Exited(); // updates status line
1666
1667   --activeProcesses;
1668
1669 #ifndef BPATCH_LIBRARY
1670   if (activeProcesses == 0)
1671     disableAllInternalMetrics();
1672 #endif
1673
1674 #ifdef PARADYND_PVM
1675   if (pvm_running) {
1676     PDYN_reportSIGCHLD(proc->getPid(), exitStatus);
1677   }
1678 #endif
1679
1680   // Perhaps these lines can be un-commented out in the future, but since
1681   // cleanUpAndExit() does the same thing, and it always gets called
1682   // (when paradynd detects that paradyn died), it's not really necessary
1683   // here.  -ari
1684 //  for (unsigned lcv=0; lcv < processVec.size(); lcv++)
1685 //     if (processVec[lcv] == proc) {
1686 //        delete proc; // destructor removes shm segments...
1687 //      processVec[lcv] = NULL;
1688 //     }
1689 }
1690
1691
1692 /*
1693    process::forkProcess: called when a process forks, to initialize a new
1694    process object for the child.
1695
1696    the variable childHasInstrumentation is true if the child process has the 
1697    instrumentation of the parent. This is the common case.
1698    On some platforms (AIX) the child does not have any instrumentation because
1699    the text segment of the child is not a copy of the parent text segment at
1700    the time of the fork, but a copy of the original text segment of the parent,
1701    without any instrumentation.
1702    (actually, childHasInstr is obsoleted by aix's completeTheFork() routine)
1703 */
1704 process *process::forkProcess(const process *theParent, pid_t childPid,
1705                       dictionary_hash<instInstance*,instInstance*> &map, // gets filled in
1706                       int iTrace_fd
1707 #ifdef SHM_SAMPLING
1708                               ,key_t theKey,
1709                               void *applAttachedPtr
1710 #endif
1711                               ) {
1712 #ifdef SHM_SAMPLING
1713     vector<fastInferiorHeapMgr::oneHeapStats> theShmHeapStats(3);
1714     theShmHeapStats[0].elemNumBytes = sizeof(intCounter);
1715     theShmHeapStats[0].maxNumElems  = numIntCounters;
1716     
1717     theShmHeapStats[1].elemNumBytes = sizeof(tTimer);
1718     theShmHeapStats[1].maxNumElems  = numWallTimers;
1719
1720     theShmHeapStats[2].elemNumBytes = sizeof(tTimer);
1721     theShmHeapStats[2].maxNumElems  = numProcTimers;
1722 #endif
1723
1724     forkexec_cerr << "paradynd welcome to process::forkProcess; parent pid=" << theParent->getPid() << "; calling fork ctor now" << endl;
1725
1726     // Call the "fork" ctor:
1727     process *ret = new process(*theParent, (int)childPid, iTrace_fd
1728 #ifdef SHM_SAMPLING
1729                                , theKey,
1730                                applAttachedPtr,
1731                                theShmHeapStats
1732 #endif
1733                                );
1734     assert(ret);
1735
1736     forkexec_cerr << "paradynd fork ctor has completed ok...child pid is " << ret->getPid() << endl;
1737
1738     processVec += ret;
1739     activeProcesses++;
1740
1741 #ifndef BPATCH_LIBRARY
1742     if (!costMetric::addProcessToAll(ret))
1743        assert(false);
1744 #endif
1745
1746     // We used to do a ret->attach() here...it was moved to the fork ctor, so it's
1747     // been done already.
1748
1749     /* all instrumentation on the parent is active on the child */
1750     /* TODO: what about instrumentation inserted near the fork time??? */
1751     ret->baseMap = theParent->baseMap; // WHY IS THIS HERE?
1752
1753     // the following writes to "map", s.t. for each instInstance in the parent
1754     // process, we have a map to the corresponding one in the child process.
1755     // that's all this routine does -- it doesn't actually touch
1756     // any instrumentation (because it doesn't need to -- fork() syscall copied
1757     // all of the actual instrumentation [but what about AIX and its weird load
1758     // behavior?])
1759     copyInstInstances(theParent, ret, map);
1760          // doesn't copy anything; just writes to "map"
1761
1762     return ret;
1763 }
1764
1765 #ifdef SHM_SAMPLING
1766 void process::processCost(unsigned obsCostLow,
1767                           time64 wallTime,
1768                           time64 processTime) {
1769    // wallTime and processTime should compare to DYNINSTgetWallTime() and
1770    // DYNINSTgetCPUtime().
1771
1772    // check for overflow, add to running total, convert cycles to
1773    // seconds, and report.
1774    // Member vrbles of class process: lastObsCostLow and cumObsCost (the latter
1775    // a 64-bit value).
1776
1777    // code to handle overflow used to be in rtinst; we borrow it pretty much
1778    // verbatim. (see rtinst/RTposix.c)
1779    if (obsCostLow < lastObsCostLow) {
1780       // we have a wraparound
1781       cumObsCost += ((unsigned)0xffffffff - lastObsCostLow) + obsCostLow + 1;
1782    }
1783    else
1784       cumObsCost += (obsCostLow - lastObsCostLow);
1785
1786    lastObsCostLow = obsCostLow;
1787
1788    extern double cyclesPerSecond; // perfStream.C
1789
1790    double observedCostSecs = cumObsCost;
1791    observedCostSecs /= cyclesPerSecond;
1792 //   cerr << "processCost: cyclesPerSecond=" << cyclesPerSecond << "; cum obs cost=" << observedCostSecs << endl;
1793
1794    // Notice how most of the rest of this is copied from processCost() of metric.C
1795    // Be sure to keep the two "in sync"!
1796    timeStamp newSampleTime  = (double)wallTime / 1000000.0; // usec to seconds
1797    timeStamp newProcessTime = (double)processTime / 1000000.0; // usec to secs
1798
1799    extern costMetric *totalPredictedCost; // init.C
1800    extern costMetric *observed_cost; // init.C
1801    extern costMetric *smooth_obs_cost; // init.C
1802
1803    const timeStamp lastProcessTime =
1804                         totalPredictedCost->getLastSampleProcessTime(this);
1805
1806     // find the portion of uninstrumented time for this interval
1807     const double unInstTime = ((newProcessTime - lastProcessTime)
1808                          / (1+currentPredictedCost));
1809     // update predicted cost
1810     // note: currentPredictedCost is the same for all processes
1811     //       this should be changed to be computed on a per process basis
1812     sampleValue newPredCost = totalPredictedCost->getCumulativeValue(this);
1813     newPredCost += (float)(currentPredictedCost*unInstTime);
1814
1815     totalPredictedCost->updateValue(this,newPredCost,
1816                                     newSampleTime,newProcessTime);
1817     // update observed cost
1818     observed_cost->updateValue(this,observedCostSecs,
1819                                newSampleTime,newProcessTime);
1820
1821     // update smooth observed cost
1822     smooth_obs_cost->updateSmoothValue(this,observedCostSecs,
1823                                        newSampleTime,newProcessTime);
1824 }
1825 #endif
1826
1827 /*
1828  * Copy data from controller process to the named process.
1829  */
1830 bool process::writeDataSpace(void *inTracedProcess, int size,
1831                              const void *inSelf) {
1832   bool needToCont = false;
1833
1834   if (status_ == exited)
1835     return false;
1836
1837   if (status_ == running) {
1838     needToCont = true;
1839     if (! pause())
1840       return false;
1841   }
1842
1843   if (status_ != stopped && status_ != neonatal) {
1844     showErrorCallback(38, "Internal paradynd error in process::writeDataSpace");
1845     return false;
1846   }
1847
1848   bool res = writeDataSpace_(inTracedProcess, size, inSelf);
1849   if (!res) {
1850     string msg = string("System error: unable to write to process data space:")
1851                    + string(sys_errlist[errno]);
1852     showErrorCallback(38, msg);
1853     return false;
1854   }
1855
1856   if (needToCont)
1857     return this->continueProc();
1858   return true;
1859 }
1860
1861 bool process::readDataSpace(const void *inTracedProcess, int size,
1862                             void *inSelf, bool displayErrMsg) {
1863   bool needToCont = false;
1864
1865   if (status_ == exited)
1866     return false;
1867
1868   if (status_ == running) {
1869     needToCont = true;
1870     if (! pause()) {
1871       sprintf(errorLine, "in readDataSpace, status_ = running, but unable to pause()\n");
1872       logLine(errorLine);
1873       return false;
1874     }
1875   }
1876
1877   if (status_ != stopped && status_ != neonatal) {
1878     showErrorCallback(38, "Internal paradynd error in process::readDataSpace");
1879     sprintf(errorLine, "Internal paradynd error in process::readDataSpace");
1880     logLine(errorLine);
1881     return false;
1882   }
1883
1884   bool res = readDataSpace_(inTracedProcess, size, inSelf);
1885   if (!res) {
1886     if (displayErrMsg) {
1887       string msg;
1888       msg=string("System error: unable to read from process data space:")
1889           + string(sys_errlist[errno]);
1890       sprintf(errorLine, msg.string_of());
1891       logLine(errorLine);
1892       showErrorCallback(38, msg);
1893     }
1894     return false;
1895   }
1896
1897   if (needToCont) {
1898     needToCont = this->continueProc();
1899     if (!needToCont) {
1900         sprintf(errorLine, "warning : readDataSpace, needToCont FALSE, returning FALSE\n");
1901         logLine(errorLine);
1902     }
1903     return needToCont;
1904   }
1905   return true;
1906
1907 }
1908
1909 bool process::writeTextWord(caddr_t inTracedProcess, int data) {
1910   bool needToCont = false;
1911
1912   if (status_ == exited)
1913     return false;
1914
1915   if (status_ == running) {
1916     needToCont = true;
1917     if (! pause())
1918       return false;
1919   }
1920
1921   if (status_ != stopped && status_ != neonatal) {
1922     string msg = string("Internal paradynd error in process::writeTextWord")
1923                + string((int)status_);
1924     showErrorCallback(38, msg);
1925     //showErrorCallback(38, "Internal paradynd error in process::writeTextWord");
1926     return false;
1927   }
1928
1929 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
1930   if (!isAddrInHeap((Address)inTracedProcess)) {
1931     if (!saveOriginalInstructions((Address)inTracedProcess, sizeof(int)))
1932         return false;
1933     afterMutationList.insertTail((Address)inTracedProcess, sizeof(int), &data);
1934   }
1935 #endif
1936
1937   bool res = writeTextWord_(inTracedProcess, data);
1938   if (!res) {
1939     string msg = string("System error: unable to write to process text word:")
1940                    + string(sys_errlist[errno]);
1941     showErrorCallback(38, msg);
1942     return false;
1943   }
1944
1945   if (needToCont)
1946     return this->continueProc();
1947   return true;
1948
1949 }
1950
1951 bool process::writeTextSpace(void *inTracedProcess, int amount, const void *inSelf) {
1952   bool needToCont = false;
1953
1954   if (status_ == exited)
1955     return false;
1956
1957   if (status_ == running) {
1958     needToCont = true;
1959     if (! pause())
1960       return false;
1961   }
1962
1963   if (status_ != stopped && status_ != neonatal) {
1964     string msg = string("Internal paradynd error in process::writeTextSpace")
1965                + string((int)status_);
1966     showErrorCallback(38, msg);
1967     //showErrorCallback(38, "Internal paradynd error in process::writeTextSpace");
1968     return false;
1969   }
1970
1971 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
1972   if (!isAddrInHeap((Address)inTracedProcess)) {
1973     if (!saveOriginalInstructions((Address)inTracedProcess, amount))
1974         return false;
1975     afterMutationList.insertTail((Address)inTracedProcess, amount, inSelf);
1976   }
1977 #endif
1978
1979   bool res = writeTextSpace_(inTracedProcess, amount, inSelf);
1980   if (!res) {
1981     string msg = string("System error: unable to write to process text space:")
1982                    + string(sys_errlist[errno]);
1983     showErrorCallback(38, msg);
1984     return false;
1985   }
1986
1987   if (needToCont)
1988     return this->continueProc();
1989   return true;
1990 }
1991
1992 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
1993 bool process::readTextSpace(const void *inTracedProcess, int amount,
1994                             const void *inSelf)
1995 {
1996   bool needToCont = false;
1997
1998   if (status_ == exited)
1999     return false;
2000
2001   if (status_ == running) {
2002     needToCont = true;
2003     if (! pause())
2004       return false;
2005   }
2006
2007   if (status_ != stopped && status_ != neonatal) {
2008     showErrorCallback(38, "Internal paradynd error in process::readTextSpace");
2009     return false;
2010   }
2011
2012   bool res = readTextSpace_((void *)inTracedProcess, amount, inSelf);
2013   if (!res) {
2014     string msg;
2015     msg=string("System error: unable to read from process data space:")
2016         + string(sys_errlist[errno]);
2017     showErrorCallback(38, msg);
2018     return false;
2019   }
2020
2021   if (needToCont)
2022     return this->continueProc();
2023   return true;
2024
2025 }
2026 #endif /* BPATCH_SET_MUTATIONS_ACTIVE */
2027
2028 bool process::pause() {
2029   if (status_ == stopped || status_ == neonatal)
2030     return true;
2031
2032   if (status_ == exited) {
2033     sprintf(errorLine, "warn : in process::pause, trying to pause exited process, returning FALSE");
2034     logLine(errorLine);
2035     return false;
2036   }
2037
2038   if (status_ == running && reachedFirstBreak) {
2039     bool res = pause_();
2040     if (!res) {
2041       sprintf(errorLine, "warn : in process::pause, pause_ unable to pause process");
2042     logLine(errorLine);
2043       return false;
2044     }
2045
2046     status_ = stopped;
2047   }
2048   else {
2049     // The only remaining combination is: status==running but haven't yet
2050     // reached first break.  We never want to pause before reaching the
2051     // first break (trap, actually).  But should we be returning true or false in this
2052     // case?
2053   }
2054
2055   return true;
2056 }
2057
2058 // handleIfDueToSharedObjectMapping: if a trap instruction was caused by
2059 // a dlopen or dlclose event then return true
2060 bool process::handleIfDueToSharedObjectMapping(){
2061
2062   if(!dyn) { 
2063     return false;
2064   }
2065
2066   vector<shared_object *> *changed_objects = 0;
2067   u_int change_type = 0;
2068   bool error_occured = false;
2069   bool ok = dyn->handleIfDueToSharedObjectMapping(this,&changed_objects,
2070                                                   change_type,error_occured);
2071
2072   // if this trap was due to dlopen or dlclose, and if something changed
2073   // then figure out how it changed and either add or remove shared objects
2074   if(ok && !error_occured && (change_type != SHAREDOBJECT_NOCHANGE)) {
2075
2076       // if something was added then call process::addASharedObject with
2077       // each element in the vector of changed_objects
2078       if((change_type == SHAREDOBJECT_ADDED) && changed_objects) {
2079           for(u_int i=0; i < changed_objects->size(); i++) {
2080              // TODO: currently we aren't handling dlopen because  
2081              // we don't have the code in place to modify existing metrics
2082              // This is what we really want to do:
2083 #ifndef BPATCH_LIBRARY
2084              if (((*changed_objects)[i])->getName() == string(getenv("PARADYN_LIB"))) 
2085              {
2086 #endif
2087                if(addASharedObject(*((*changed_objects)[i]))){
2088                  *shared_objects += (*changed_objects)[i];
2089                  hasLoadedDyninstLib = true;
2090                  isLoadingDyninstLib = false;
2091                } else {
2092                  logLine("Error after call to addASharedObject\n");
2093                  delete (*changed_objects)[i];
2094                }
2095 #ifndef BPATCH_LIBRARY
2096              } else {
2097                // for now, just delete shared_objects to avoid memory leeks
2098                delete (*changed_objects)[i];
2099              }
2100 #endif
2101           }
2102           delete changed_objects;
2103       } 
2104       else if((change_type == SHAREDOBJECT_REMOVED) && (changed_objects)) { 
2105           // TODO: handle this case
2106           // if something was removed then call process::removeASharedObject
2107           // with each element in the vector of changed_objects
2108
2109           // for now, just delete shared_objects to avoid memory leeks
2110           for(u_int i=0; i < changed_objects->size(); i++){
2111               delete (*changed_objects)[i];
2112           }
2113           delete changed_objects;
2114       }
2115
2116       // TODO: add support for adding or removing new code resource once the 
2117       // process has started running...this means that currently collected
2118       // metrics may have to have aggregate components added or deleted
2119       // this should be added to process::addASharedObject and 
2120       // process::removeASharedObject  
2121   }
2122   return ok;
2123 }
2124
2125
2126
2127
2128
2129 //
2130 //  If this process is a dynamic executable, then get all its 
2131 //  shared objects, parse them, and define new instpoints and resources 
2132 //
2133 bool process::handleStartProcess(){
2134
2135     // get shared objects, parse them, and define new resources 
2136     // For WindowsNT we don't call getSharedObjects here, instead
2137     // addASharedObject will be called directly by pdwinnt.C
2138 #if !defined(i386_unknown_nt4_0)
2139     this->getSharedObjects();
2140 #endif
2141
2142 #ifndef BPATCH_LIBRARY
2143     if(resource::num_outstanding_creates)
2144        this->setWaitingForResources();
2145 #endif
2146
2147     return true;
2148 }
2149
2150 // addASharedObject: This routine is called whenever a new shared object
2151 // has been loaded by the run-time linker
2152 // It processes the image, creates new resources
2153 bool process::addASharedObject(shared_object &new_obj){
2154
2155     image *img = image::parseImage(new_obj.getName(),new_obj.getBaseAddress());
2156     if(!img){
2157         logLine("error parsing image in addASharedObject\n");
2158         return false;
2159     }
2160     new_obj.addImage(img);
2161
2162     // if the list of all functions and all modules have already been 
2163     // created for this process, then the functions and modules from this
2164     // shared object need to be added to those lists 
2165     if(all_modules){
2166         *all_modules += *((vector<module *> *)(new_obj.getModules())); 
2167     }
2168     if(all_functions){
2169         vector<function_base *> *normal_funcs = (vector<function_base *> *)
2170                         (new_obj.getAllFunctions());
2171         *all_functions += *normal_funcs; 
2172         normal_funcs = 0;
2173     }
2174
2175     // if the signal handler function has not yet been found search for it
2176     if(!signal_handler){
2177         signal_handler = img->findOneFunction(SIGNAL_HANDLER);
2178     }
2179
2180     // clear the include_funcs flag if this shared object should not be
2181     // included in the some_functions and some_modules lists
2182 #ifndef BPATCH_LIBRARY
2183     vector<string> lib_constraints;
2184     if(mdl_get_lib_constraints(lib_constraints)){
2185         for(u_int j=0; j < lib_constraints.size(); j++){
2186            char *where = 0; 
2187            // if the lib constraint is not of the form "module/function" and
2188            // if it is contained in the name of this object, then exclude
2189            // this shared object
2190            char *obj_name = P_strdup(new_obj.getName().string_of());
2191            char *lib_name = P_strdup(lib_constraints[j].string_of());
2192            if(obj_name && lib_name && (where=P_strstr(obj_name, lib_name))){
2193               new_obj.changeIncludeFuncs(false); 
2194            }
2195            if(lib_name) free(lib_name);
2196            if(obj_name) free(obj_name);
2197         }
2198     }
2199
2200     // This looks a bit wierd at first glance, but apparently is ok -
2201     //  A shared object has 1 module.  If that module is excluded,
2202     //  then new_obj.includeFunctions() should return FALSE.  As such,
2203     //  the some_modules += new_obj.getModules() is OK as long as
2204     //  shared objects have ONLY 1 module.
2205     if(new_obj.includeFunctions()){
2206         if(some_modules) {
2207             *some_modules += *((vector<module *> *)(new_obj.getModules())); 
2208         }
2209         if(some_functions) {
2210             // gets only functions not excluded by mdl "exclude_node" option
2211             *some_functions += 
2212                 *((vector<function_base *> *)(new_obj.getSomeFunctions()));
2213         }
2214     }
2215 #endif /* BPATCH_LIBRARY */
2216     return true;
2217 }
2218
2219 // getSharedObjects: This routine is called before main() or on attach
2220 // to an already running process.  It gets and process all shared objects
2221 // that have been mapped into the process's address space
2222 bool process::getSharedObjects() {
2223
2224     assert(!shared_objects);
2225     shared_objects = dyn->getSharedObjects(this); 
2226     if(shared_objects){
2227         statusLine("parsing shared object files");
2228
2229 #ifndef BPATCH_LIBRARY
2230         tp->resourceBatchMode(true);
2231 #endif
2232         // for each element in shared_objects list process the 
2233         // image file to find new instrumentaiton points
2234         for(u_int j=0; j < shared_objects->size(); j++){
2235             //string temp2 = string(i);
2236             //temp2 += string("th shared obj, addr: ");
2237             //temp2 += string(((*shared_objects)[i])->getBaseAddress());
2238             //temp2 += string(" name: ");
2239             //temp2 += string(((*shared_objects)[i])->getName());
2240             //temp2 += string("\n");
2241             // logLine(P_strdup(temp2.string_of()));
2242
2243             if(!addASharedObject(*((*shared_objects)[j]))){
2244                 logLine("Error after call to addASharedObject\n");
2245             }
2246         }
2247
2248 #ifndef BPATCH_LIBRARY
2249         tp->resourceBatchMode(false);
2250 #endif
2251         return true;
2252     }
2253     // else this a.out does not have a .dynamic section
2254     dynamiclinking = false;
2255     return false;
2256 }
2257
2258 // findOneFunction: returns the function associated with func  
2259 // this routine checks both the a.out image and any shared object
2260 // images for this resource.
2261 // Semantics of excluded functions - Once "exclude" works for both
2262 // static and dynamically linked objects, this should return NULL
2263 // if the function being sought is excluded....
2264 #ifndef BPATCH_LIBRARY
2265 function_base *process::findOneFunction(resource *func,resource *mod){
2266     
2267     if((!func) || (!mod)) { return 0; }
2268     if(func->type() != MDL_T_PROCEDURE) { return 0; }
2269     if(mod->type() != MDL_T_MODULE) { return 0; }
2270
2271     const vector<string> &f_names = func->names();
2272     const vector<string> &m_names = mod->names();
2273     string func_name = f_names[f_names.size() -1]; 
2274     string mod_name = m_names[m_names.size() -1]; 
2275
2276     //cerr << "process::findOneFunction called.  function name = " 
2277     //     << func_name.string_of() << endl;
2278
2279     // KLUDGE: first search any shared libraries for the module name 
2280     //  (there is only one module in each shared library, and that 
2281     //  is the library name)
2282     if(dynamiclinking && shared_objects){
2283         for(u_int j=0; j < shared_objects->size(); j++){
2284             module *next = 0;
2285             next = ((*shared_objects)[j])->findModule(mod_name,true);
2286             if(next){
2287                 if(((*shared_objects)[j])->includeFunctions()){ 
2288                     //cerr << "function found in module " << mod_name.string_of() << endl;
2289                     return(((*shared_objects)[j])->findOneFunction(func_name,
2290                                                                    true));
2291                 } 
2292                 else { 
2293                     //cerr << "function found in module " << mod_name.string()
2294                     //     << " that module excluded" << endl;
2295                   return 0;
2296                 } 
2297             }
2298         }
2299     }
2300
2301     return(symbols->findOneFunction(func_name));
2302 }
2303 #endif /* BPATCH_LIBRARY */
2304
2305 #ifndef BPATCH_LIBRARY
2306 // returns all the functions in the module "mod" that are not excluded by
2307 // exclude_lib or exclude_func
2308 // return 0 on error.
2309 vector<function_base *> *process::getIncludedFunctions(module *mod) {
2310
2311     if((!mod)) { return 0; }
2312
2313     //cerr << "process::getIncludedFunctions(" << mod->fileName() << ") called" << endl;
2314
2315     // KLUDGE: first search any shared libraries for the module name 
2316     //  (there is only one module in each shared library, and that 
2317     //  is the library name)
2318     if(dynamiclinking && shared_objects){
2319         for(u_int j=0; j < shared_objects->size(); j++){
2320             module *next = 0;
2321             next = ((*shared_objects)[j])->findModule(mod->fileName(), true);
2322             if(next){
2323                 if(((*shared_objects)[j])->includeFunctions()){ 
2324                     return((vector<function_base *> *)
2325                            ((*shared_objects)[j])->getSomeFunctions());
2326                 } 
2327                 else { return 0;} 
2328             }
2329         }
2330     }
2331
2332     // this must be an a.out module so just return the list associated
2333     // with the module.
2334     // Now that exclude should work for both static and dynamically
2335     // linked executables, probably need to either filter excluded
2336     // files here, or let the module do it and pass the information not
2337     // to include excluded functions along with this proc call....
2338     // mcheyney 970927
2339     return(mod->getIncludedFunctions());
2340 }
2341 #endif /* BPATCH_LIBRARY */
2342
2343
2344 // findOneFunction: returns the function associated with func  
2345 // this routine checks both the a.out image and any shared object
2346 // images for this resource
2347 function_base *process::findOneFunction(const string &func_name){
2348     // first check a.out for function symbol
2349     function_base *pdf = symbols->findOneFunction(func_name);
2350     if(pdf) {
2351       return pdf;
2352     }
2353
2354     // search any shared libraries for the file name 
2355     if(dynamiclinking && shared_objects){
2356         for(u_int j=0; j < shared_objects->size(); j++){
2357             pdf = ((*shared_objects)[j])->findOneFunction(func_name,false);
2358             if(pdf){
2359                 return(pdf);
2360             }
2361     } }
2362     return(0);
2363 }
2364
2365 // findOneFunctionFromAll: returns the function associated with func  
2366 // this routine checks both the a.out image and any shared object
2367 // images for this resource
2368 function_base *process::findOneFunctionFromAll(const string &func_name){
2369     
2370     // first check a.out for function symbol
2371     function_base *pdf = symbols->findOneFunctionFromAll(func_name);
2372     if(pdf) return pdf;
2373
2374     // search any shared libraries for the file name 
2375     if(dynamiclinking && shared_objects){
2376         for(u_int j=0; j < shared_objects->size(); j++){
2377             pdf=((*shared_objects)[j])->findOneFunctionFromAll(func_name,false);
2378             if(pdf){
2379                 return(pdf);
2380             }
2381     } }
2382     return(0);
2383
2384     return(0);
2385 }
2386
2387 // findpdFunctionIn: returns the function which contains this address
2388 // This routine checks both the a.out image and any shared object images
2389 // for this function
2390 pd_Function *process::findpdFunctionIn(Address adr) {
2391
2392     // first check a.out for function symbol
2393     // findFunctionInInstAndUnInst will search the instrumentable and
2394     // uninstrumentable functions. We are assuming that "adr" is the
2395     // entry point of the function, so we will use as the key to search
2396     // in the dictionary - naim
2397     pd_Function *pdf = symbols->findFunctionInInstAndUnInst(adr,this);
2398     if(pdf) return pdf;
2399     // search any shared libraries for the function 
2400     if(dynamiclinking && shared_objects){
2401         for(u_int j=0; j < shared_objects->size(); j++){
2402           pdf = ((*shared_objects)[j])->findFunctionInInstAndUnInst(adr,this);
2403           if(pdf){
2404             return(pdf);          
2405           }
2406         }
2407     }
2408
2409     if(!all_functions) getAllFunctions();
2410
2411     // if the function was not found, then see if this addr corresponds
2412     // to  a function that was relocated in the heap
2413     if(all_functions){
2414         for(u_int j=0; j < all_functions->size(); j++){
2415             Address func_adr = ((*all_functions)[j])->getAddress(this);
2416             if((adr>=func_adr) && 
2417                 (adr<=(((*all_functions)[j])->size()+func_adr))){
2418                 // yes, this is very bad, but too bad
2419                 return((pd_Function*)((*all_functions)[j]));
2420             }
2421         }
2422     }
2423     return(0);
2424 }
2425     
2426
2427 // findFunctionIn: returns the function containing the address "adr"
2428 // this routine checks both the a.out image and any shared object
2429 // images for this resource
2430 function_base *process::findFunctionIn(Address adr){
2431
2432     // first check a.out for function symbol
2433     pd_Function *pdf = symbols->findFunctionIn(adr,this);
2434     if(pdf) return pdf;
2435     // search any shared libraries for the function 
2436     if(dynamiclinking && shared_objects){
2437         for(u_int j=0; j < shared_objects->size(); j++){
2438             pdf = ((*shared_objects)[j])->findFunctionIn(adr,this);
2439             if(pdf){
2440                 return(pdf);
2441             }
2442     } }
2443
2444     if(!all_functions) getAllFunctions();
2445
2446     // if the function was not found, then see if this addr corresponds
2447     // to  a function that was relocated in the heap
2448     if(all_functions){
2449         for(u_int j=0; j < all_functions->size(); j++){
2450             Address func_adr = ((*all_functions)[j])->getAddress(this);
2451             if((adr>=func_adr) && 
2452                 (adr<=(((*all_functions)[j])->size()+func_adr))){
2453                 return((*all_functions)[j]);
2454             }
2455         }
2456     }
2457     return(0);
2458 }
2459         
2460
2461         
2462 // findModule: returns the module associated with mod_name 
2463 // this routine checks both the a.out image and any shared object
2464 // images for this resource
2465 // if check_excluded is true it checks to see if the module is excluded
2466 // and if it is it returns 0.  If check_excluded is false it doesn't check
2467 module *process::findModule(const string &mod_name,bool check_excluded){
2468
2469     // KLUDGE: first search any shared libraries for the module name 
2470     //  (there is only one module in each shared library, and that 
2471     //  is the library name)
2472     if(dynamiclinking && shared_objects){
2473         for(u_int j=0; j < shared_objects->size(); j++){
2474             module *next = ((*shared_objects)[j])->findModule(mod_name,
2475                               check_excluded);
2476             if(next) {
2477                 return(next);
2478             }
2479         }
2480     }
2481
2482     // check a.out for function symbol
2483     //  Note that symbols is data member of type image* (comment says
2484     //  "information related to the process"....
2485     return(symbols->findModule(mod_name));
2486 }
2487
2488 // getSymbolInfo:  get symbol info of symbol associated with name n
2489 // this routine starts looking a.out for symbol and then in shared objects
2490 // baseAddr is set to the base address of the object containing the symbol.
2491 // This function appears to return symbol info even if module/function
2492 // is excluded.  In extending excludes to statically linked executable,
2493 // we preserve these semantics....
2494 bool process::getSymbolInfo(const string &name, Symbol &info, Address &baseAddr) const {
2495     
2496     // first check a.out for symbol
2497     if(symbols->symbol_info(name,info))
2498       return getBaseAddress(symbols, baseAddr);
2499
2500     // next check shared objects
2501     if(dynamiclinking && shared_objects) {
2502       for(u_int j=0; j < shared_objects->size(); j++) {
2503             if(((*shared_objects)[j])->getSymbolInfo(name,info))
2504                 return getBaseAddress(((*shared_objects)[j])->getImage(), baseAddr); 
2505       }
2506     }
2507
2508     return false;
2509 }
2510
2511
2512 // getAllFunctions: returns a vector of all functions defined in the
2513 // a.out and in the shared objects
2514 // TODO: what to do about duplicate function names?
2515 vector<function_base *> *process::getAllFunctions(){
2516
2517     // if this list has already been created, return it
2518     if(all_functions) 
2519         return all_functions;
2520
2521     // else create the list of all functions
2522     all_functions = new vector<function_base *>;
2523     const vector<function_base *> &blah = 
2524                     (vector<function_base *> &)(symbols->getAllFunctions());
2525     *all_functions += blah;
2526
2527     if(dynamiclinking && shared_objects){
2528         for(u_int j=0; j < shared_objects->size(); j++){
2529            vector<function_base *> *funcs = (vector<function_base *> *) 
2530                         (((*shared_objects)[j])->getAllFunctions());
2531            if(funcs){
2532                *all_functions += *funcs; 
2533            }
2534         }
2535     }
2536     return all_functions;
2537 }
2538       
2539 // getAllModules: returns a vector of all modules defined in the
2540 // a.out and in the shared objects
2541 // Includes "excluded" modules....
2542 vector<module *> *process::getAllModules(){
2543
2544     // if the list of all modules has already been created, the return it
2545     if(all_modules) return all_modules;
2546
2547     // else create the list of all modules
2548     all_modules = new vector<module *>;
2549     *all_modules += *((vector<module *> *)(&(symbols->getAllModules())));
2550
2551     if(dynamiclinking && shared_objects){
2552         for(u_int j=0; j < shared_objects->size(); j++){
2553            vector<module *> *mods = 
2554                 (vector<module *> *)(((*shared_objects)[j])->getModules());
2555            if(mods) {
2556                *all_modules += *mods; 
2557            }
2558     } } 
2559     return all_modules;
2560 }
2561
2562 #ifndef BPATCH_LIBRARY
2563 // getIncludedFunctions: returns a vector of all functions defined in the
2564 // a.out and in the shared objects
2565 // TODO: what to do about duplicate function names?
2566 vector<function_base *> *process::getIncludedFunctions(){
2567     //cerr << "process " << programName << " :: getIncludedFunctions() called"
2568     //   << endl;
2569     // if this list has already been created, return it
2570     if(some_functions) 
2571         return some_functions;
2572
2573     // else create the list of all functions
2574     some_functions = new vector<function_base *>;
2575     const vector<function_base *> &incl_funcs = 
2576         (vector<function_base *> &)(symbols->getIncludedFunctions());
2577         *some_functions += incl_funcs;
2578
2579     //cerr << " (process::getIncludedFunctions), about to add incl_funcs to some_functions, incl_funcs = " << endl;
2580     //print_func_vector_by_pretty_name(string(">>>"), &incl_funcs);
2581
2582     if(dynamiclinking && shared_objects){
2583         for(u_int j=0; j < shared_objects->size(); j++){
2584             if(((*shared_objects)[j])->includeFunctions()){
2585                 // kludge: can't assign a vector<derived_class *> to 
2586                 // a vector<base_class *> so recast
2587                 vector<function_base *> *funcs = (vector<function_base *> *)
2588                         (((*shared_objects)[j])->getSomeFunctions());
2589                 if(funcs) { 
2590                     *some_functions += (*funcs); 
2591                 } 
2592             } 
2593     } } 
2594
2595     //cerr << " (process::getIncludedFunctions()) about to return fucntion list : ";
2596     //print_func_vector_by_pretty_name(string("  "), some_functions);
2597
2598     return some_functions;
2599 }
2600 #endif /* BPATCH_LIBRARY */
2601
2602 // getIncludedModules: returns a vector of all modules defined in the
2603 // a.out and in the shared objects that are included as specified in
2604 // the mdl
2605 vector<module *> *process::getIncludedModules(){
2606
2607     //cerr << "process::getIncludedModules called" << endl;
2608
2609     // if the list of all modules has already been created, the return it
2610     if(some_modules) {
2611         //cerr << "some_modules already created, returning it:" << endl;
2612         //print_module_vector_by_short_name(string("  "), (vector<pdmodule*>*)some_modules);
2613         return some_modules;
2614     }
2615
2616     // else create the list of all modules
2617     some_modules = new vector<module *>;
2618     *some_modules += *((vector<module *> *)(&(symbols->getIncludedModules())));
2619
2620     if(dynamiclinking && shared_objects){
2621         for(u_int j=0; j < shared_objects->size(); j++){
2622             if(((*shared_objects)[j])->includeFunctions()){
2623                vector<module *> *mods = (vector<module *> *) 
2624                         (((*shared_objects)[j])->getModules());
2625                if(mods) {
2626                    *some_modules += *mods; 
2627                }
2628            }
2629     } } 
2630
2631     //cerr << "some_modules newlyu created, returning it:" << endl;
2632     //print_module_vector_by_short_name(string("  "),
2633     //    (vector<pdmodule*>*)some_modules);
2634     return some_modules;
2635 }
2636       
2637 // getBaseAddress: sets baseAddress to the base address of the 
2638 // image corresponding to which.  It returns true  if image is mapped
2639 // in processes address space, otherwise it returns 0
2640 bool process::getBaseAddress(const image *which,u_int &baseAddress) const {
2641
2642   if((u_int)(symbols) == (u_int)(which)){
2643       baseAddress = 0; 
2644       return true;
2645   }
2646   else if (shared_objects) {  
2647       // find shared object corr. to this image and compute correct address
2648       for(unsigned j=0; j < shared_objects->size(); j++){ 
2649           if(((*shared_objects)[j])->isMapped()){
2650             if(((*shared_objects)[j])->getImageId() == (u_int)which) { 
2651               baseAddress = ((*shared_objects)[j])->getBaseAddress();
2652               return true;
2653           } }
2654       }
2655   }
2656   return false;
2657 }
2658
2659 // findSignalHandler: if signal_handler is 0, then it checks all images
2660 // associtated with this process for the signal handler function.
2661 // Otherwise, the signal handler function has already been found
2662 void process::findSignalHandler(){
2663
2664     if(SIGNAL_HANDLER == 0) return;
2665     if(!signal_handler) { 
2666         // first check a.out for signal handler function
2667         signal_handler = symbols->findOneFunction(SIGNAL_HANDLER);
2668
2669         // search any shared libraries for signal handler function
2670         if(!signal_handler && dynamiclinking && shared_objects) { 
2671             for(u_int j=0;(j < shared_objects->size()) && !signal_handler; j++){
2672                 signal_handler = 
2673                       ((*shared_objects)[j])->findOneFunction(SIGNAL_HANDLER,false);
2674         } }
2675     }
2676 }
2677
2678
2679 bool process::findInternalSymbol(const string &name, bool warn, internalSym &ret_sym) const {
2680      // On some platforms, internal symbols may be dynamic linked
2681      // so we search both the a.out and the shared objects
2682      Symbol sym;
2683      Address baseAddr;
2684      static const string underscore = "_";
2685      if (getSymbolInfo(name, sym, baseAddr)
2686          || getSymbolInfo(underscore+name, sym, baseAddr)) {
2687         ret_sym = internalSym(sym.addr()+baseAddr, name);
2688         return true;
2689      }
2690      if (warn) {
2691         string msg;
2692         msg = string("Unable to find symbol: ") + name;
2693         statusLine(msg.string_of());
2694         showErrorCallback(28, msg);
2695      }
2696      return false;
2697 }
2698
2699 Address process::findInternalAddress(const string &name, bool warn, bool &err) const {
2700      // On some platforms, internal symbols may be dynamic linked
2701      // so we search both the a.out and the shared objects
2702      Symbol sym;
2703      Address baseAddr;
2704      static const string underscore = "_";
2705 #if defined(USES_LIBDYNINSTRT_SO)
2706      // we use "dlopen" because we took out the leading "_"'s from the name
2707      if (name==string("dlopen")) {
2708        // if the function is dlopen, we use the address in ld.so.1 directly
2709        baseAddr = get_dlopen_addr();
2710        if (baseAddr != NULL) {
2711          err = false;
2712          return baseAddr;
2713        } else {
2714          err = true;
2715          return 0;
2716        }
2717      }
2718 #endif
2719      if (getSymbolInfo(name, sym, baseAddr)
2720          || getSymbolInfo(underscore+name, sym, baseAddr)) {
2721         err = false;
2722         return sym.addr()+baseAddr;
2723      }
2724      if (warn) {
2725         string msg;
2726         msg = string("Unable to find symbol: ") + name;
2727         statusLine(msg.string_of());
2728         showErrorCallback(28, msg);
2729      }
2730      err = true;
2731      return 0;
2732 }
2733
2734
2735
2736 bool process::continueProc() {
2737   if (status_ == exited) return false;
2738
2739   if (status_ != stopped && status_ != neonatal) {
2740     showErrorCallback(38, "Internal paradynd error in process::continueProc");
2741     return false;
2742   }
2743
2744   bool res = continueProc_();
2745
2746   if (!res) {
2747     showErrorCallback(38, "System error: can't continue process");
2748     return false;
2749   }
2750   status_ = running;
2751   return true;
2752 }
2753
2754 bool process::detach(const bool paused) {
2755   if (paused) {
2756     logLine("detach: pause not implemented\n"); // why not? --ari
2757   }
2758   bool res = detach_();
2759   if (!res) {
2760     // process may have exited
2761     return false;
2762   }
2763   return true;
2764 }
2765
2766 #ifdef BPATCH_LIBRARY
2767 // XXX Eventually detach() above should go away and this should be
2768 //     renamed detach()
2769 /* process::API_detach: detach from the application, leaving all
2770    instrumentation place.  Returns true upon success and false upon failure.
2771    Fails if the application is not stopped when the call is made.  The
2772    parameter "cont" indicates whether or not the application should be made
2773    running or not as a consquence of detaching (true indicates that it should
2774    be run).
2775 */
2776 bool process::API_detach(const bool cont)
2777 {
2778   if (status() != neonatal && status() != stopped)
2779       return false;
2780
2781   return API_detach_(cont);
2782 }
2783 #endif
2784
2785 /* process::handleExec: called when a process successfully exec's.
2786    Parse the new image, disable metric instances on the old image, create a
2787    new (and blank) shm segment.  The process hasn't yet bootstrapped, so we
2788    mustn't try to enable anything...
2789 */
2790 void process::handleExec() {
2791     // NOTE: for shm sampling, the shm segment has been removed, so we
2792     //       mustn't try to disable any dataReqNodes in the standard way...
2793
2794    // since the exec syscall has run, we're not ready to enable any m/f pairs or
2795    // sample anything.
2796    // So we set hasBootstrapped to false until we run DYNINSTinit again.
2797    hasBootstrapped = false;
2798
2799     // all instrumentation that was inserted in this process is gone.
2800     // set exited here so that the disables won't try to write to process
2801     status_ = exited; 
2802    
2803     // Clean up state from old exec: all dynamic linking stuff, all lists 
2804     // of functions and modules from old executable
2805
2806     // can't delete dynamic linking stuff here, because parent process
2807     // could still have pointers
2808     dynamiclinking = false;
2809     dyn = 0; // AHEM.  LEAKED MEMORY!  not if the parent still has a pointer
2810              // to this dynamic_linking object.
2811     dyn = new dynamic_linking;
2812     if(shared_objects){
2813         for(u_int j=0; j< shared_objects->size(); j++){
2814             delete (*shared_objects)[j];
2815         }
2816         delete shared_objects;
2817         shared_objects = 0;
2818     }
2819
2820     // TODO: when can pdFunction's be deleted???  definitely not here.
2821     delete some_modules;
2822     delete some_functions;
2823     delete all_functions;
2824     delete all_modules;
2825     some_modules = 0;
2826     some_functions = 0;
2827     all_functions = 0;
2828     all_modules = 0;
2829     signal_handler = 0;
2830     trampTableItems = 0;
2831     memset(trampTable, 0, sizeof(trampTable));
2832     baseMap.clear();
2833     cleanInstFromActivePoints(this);
2834
2835 #if defined(rs6000_ibm_aix3_2) || defined(rs6000_ibm_aix4_1)
2836     // must call establishBaseAddrs before parsing the new image,
2837     // but doesn't need to wait for trap, since we already got the trap.
2838     bool establishBaseAddrs(int pid, int &status, bool waitForTrap);
2839     int status;
2840     establishBaseAddrs(getPid(), status, false);
2841 #endif
2842
2843     image *img = image::parseImage(execFilePath);
2844
2845     if (!img) {
2846        // For better error reporting, two failure return values would be useful
2847        // One for simple error like because-file-not-found
2848        // Another for serious errors like found-but-parsing-failed (internal error;
2849        //    please report to paradyn@cs.wisc.edu)
2850
2851        string msg = string("Unable to parse image: ") + execFilePath;
2852        showErrorCallback(68, msg.string_of());
2853        OS::osKill(pid);
2854           // err..what if we had attached?  Wouldn't a detach be appropriate in this case?
2855        return;
2856     }
2857
2858     // delete proc->symbols ???  No, the image can be shared by more
2859     // than one process...images and instPoints can not be deleted...TODO
2860     // add some sort of reference count to these classes so that they can
2861     // be deleted
2862     symbols = img; // AHEM!  LEAKED MEMORY!!! ...not if parent has ptr to 
2863                    // previous image
2864
2865     // see if new image contains the signal handler function
2866     this->findSignalHandler();
2867
2868     // initInferiorHeap can only be called after symbols is set!
2869 #if !defined(USES_LIBDYNINSTRT_SO)
2870     initInferiorHeap(false);
2871     if (splitHeaps) {
2872       initInferiorHeap(true);  // create separate text heap
2873     }
2874 #endif
2875
2876     /* update process status */
2877     reachedFirstBreak = false;
2878        // we haven't yet seen initial SIGTRAP for this proc (is this right?)
2879     reachedVeryFirstTrap = false;
2880
2881     status_ = stopped; // was 'exited'
2882
2883    // TODO: We should remove (code) items from the where axis, if the exec'd process
2884    // was the only one who had them.
2885
2886    // the exec'd process has the same fd's as the pre-exec, so we don't need
2887    // to re-initialize traceLink or ioLink (is this right???)
2888
2889    // we don't need to re-attach after an exec (is this right???)
2890  
2891 #ifdef SHM_SAMPLING
2892    inferiorHeapMgr.handleExec();
2893       // reuses the shm seg (paradynd's already attached to it); resets applic-attached-
2894       // at to NULL.  Quite similar to the (non-fork) ctor, really.
2895
2896    theSuperTable.handleExec();
2897 #endif
2898
2899    inExec = false;
2900    execed_ = true;
2901 }
2902
2903 /* 
2904    process::cleanUpInstrumentation called when paradynd catch
2905    a SIGTRAP to find out if there's any previous unfinished instrumentation
2906    requests 
2907 */
2908 bool process::cleanUpInstrumentation(bool wasRunning) {
2909     // Try to process an item off of the waiting list 'instWlist'.
2910     // If something was found & processed, then true will be returned.
2911     // Additionally, if true is returned, the process will be continued
2912     // if 'wasRunning' is true.
2913     // But if false is returned, then there should be no side effects: noone
2914     // should be continued, nothing removed from 'instWList', no change
2915     // to this->status_, and so on (this is important to avoid bugs).
2916
2917     assert(status_ == stopped); // since we're always called after a SIGTRAP
2918     Frame frame(this);
2919     Address pc = frame.getPC();
2920
2921     // Go thru the instWList to find out the ones to be deleted 
2922     bool done = false;
2923     u_int i=0;
2924     bool found = false;
2925     while(!done){
2926         //process *p = (instWList[i])->which_proc;
2927         if(((instWList[i])->pc_ == pc) && ((instWList[i])->which_proc == this)){
2928             (instWList[i])->cleanUp(this,pc);
2929             u_int last = instWList.size()-1;
2930             delete (instWList[i]);
2931             instWList[i] = instWList[last];
2932             instWList.resize(last);
2933             found = true;
2934         }
2935         else {
2936             i++;
2937         }
2938         if(i >= instWList.size()) done = true;
2939     }
2940     if(found && wasRunning) continueProc();
2941     return found;
2942 }
2943
2944 void process::cleanRPCreadyToLaunch(int mid) 
2945 {
2946   vectorSet<inferiorRPCtoDo> tmpRPCsWaitingToStart;
2947   while (RPCsWaitingToStart.size() > 0) {
2948     inferiorRPCtoDo currElem = RPCsWaitingToStart.removeOne();
2949     if (currElem.mid == mid)
2950       break;
2951     else
2952       tmpRPCsWaitingToStart += currElem;
2953   }
2954   // reconstruct RPCsWaitingToStart
2955   while (tmpRPCsWaitingToStart.size() > 0) {
2956     RPCsWaitingToStart += tmpRPCsWaitingToStart.removeOne();
2957   }
2958 }
2959
2960 void process::postRPCtoDo(AstNode *action, bool noCost,
2961                           void (*callbackFunc)(process *, void *, unsigned),
2962                           void *userData,
2963                           int mid) {
2964    // posts an RPC, but does NOT make any effort to launch it.
2965    inferiorRPCtoDo theStruct;
2966    theStruct.action = action;
2967    theStruct.noCost = noCost;
2968    theStruct.callbackFunc = callbackFunc;
2969    theStruct.userData = userData;
2970    theStruct.mid = mid;
2971
2972    RPCsWaitingToStart += theStruct;
2973 }
2974
2975 bool process::existsRPCreadyToLaunch() const {
2976    if (currRunningRPCs.empty() && !RPCsWaitingToStart.empty())
2977       return true;
2978    return false;
2979 }
2980
2981 bool process::existsRPCinProgress() const {
2982    return (!currRunningRPCs.empty());
2983 }
2984
2985 bool process::launchRPCifAppropriate(bool wasRunning, bool finishingSysCall) {
2986    // asynchronously launches an inferiorRPC iff RPCsWaitingToStart.size() > 0 AND
2987    // if currRunningRPCs.size()==0 (the latter for safety)
2988
2989    if (!currRunningRPCs.empty())
2990       // an RPC is currently executing, so it's not safe to launch a new one.
2991       return false;
2992
2993    if (RPCsWaitingToStart.empty())
2994       // duh, no RPC is waiting to run, so there's nothing to do.
2995       return false;
2996
2997    if (status_ == exited)
2998       return false;
2999
3000    if (status_ == neonatal)
3001       // not sure if this should be some kind of error...is the inferior ready
3002       // to execute inferior RPCs??? For now, we'll allow it.
3003       ; 
3004
3005    /* ****************************************************** */
3006
3007    // Steps to take (on sparc, at least)
3008    // 1) pause the process and wait for it to stop
3009    // 2) Get a copy of the registers...store them away
3010    // 3) create temp trampoline: save, action, restore, trap, illegal
3011    //    (the illegal is just ot be sure that the trap never returns)
3012    // 4) set the PC and nPC regs to addr of temp tramp
3013    // 5) Continue the process...go back to the main loop (SIGTRAP will
3014    //    eventually be delivered)
3015
3016    // When SIGTRAP is received,
3017    // 5) verify that PC is the location of the TRAP instr in the temp tramp
3018    // 6) free temp trampoline
3019    // 7) SETREGS to restore all regs, including PC and nPC.
3020    // 8) continue inferior, if the inferior had been running when we had
3021    //    paused it in step 1, above.
3022
3023    if (!finishingSysCall && RPCs_waiting_for_syscall_to_complete) {
3024       assert(executingSystemCall());
3025       return false;
3026    }
3027
3028    if (!pause()) {
3029       cerr << "launchRPCifAppropriate failed because pause failed" << endl;
3030       return false;
3031    }
3032
3033    // If we're in the middle of a system call, then it's not safe to launch
3034    // an inferiorRPC on most platforms.  On some platforms, it's safe, but the
3035    // actual launching won't take place until the system call finishes.  In such
3036    // cases it's a good idea to set a breakpoint for when the sys call exits
3037    // (using /proc PIOCSEXIT), and launch the inferiorRPC then.
3038    if (!finishingSysCall && executingSystemCall()) {
3039       if (RPCs_waiting_for_syscall_to_complete) {
3040          inferiorrpc_cerr << "launchRPCifAppropriate: still waiting for syscall to "
3041                           << "complete" << endl;
3042          if (wasRunning) {
3043             inferiorrpc_cerr << "launchRPC: continuing so syscall may complete" << endl;
3044             (void)continueProc();
3045          }
3046          else
3047             inferiorrpc_cerr << "launchRPC: sorry not continuing (problem?)" << endl;
3048          return false;
3049       }
3050
3051       // don't do the inferior rpc until the system call finishes.  Determine
3052       // which system call is in the way, and set a breakpoint at its exit point
3053       // so we know when it's safe to launch the RPC.  Platform-specific
3054       // details:
3055
3056       inferiorrpc_cerr << "launchRPCifAppropriate: within a system call" << endl;
3057
3058       if (!set_breakpoint_for_syscall_completion()) {
3059          // sorry, this platform can't set a breakpoint at the system call
3060          // completion point.  In such a case, we keep polling executingSystemCall()
3061          // inefficiently.
3062          if (wasRunning)
3063             (void)continueProc();
3064
3065          inferiorrpc_cerr << "launchRPCifAppropriate: couldn't set bkpt for "
3066                           << "syscall completion; will just poll." << endl;
3067          return false;
3068       }
3069
3070       inferiorrpc_cerr << "launchRPCifAppropriate: set bkpt for syscall completion"
3071                        << endl;
3072
3073       // a SIGTRAP will get delivered when the RPC is ready to go.  Until then,
3074       // mark the rpc as deferred.  Setting this flag prevents us from executing
3075       // this code too many times.
3076
3077       RPCs_waiting_for_syscall_to_complete = true;
3078
3079       if (wasRunning)
3080          (void)continueProc();
3081
3082       return false;
3083    }
3084
3085    // Okay, we're not in the middle of a system call, so we can fire off the rpc now!
3086    if (RPCs_waiting_for_syscall_to_complete)
3087       // not any more
3088       RPCs_waiting_for_syscall_to_complete = false;
3089
3090    void *theSavedRegs = getRegisters(); // machine-specific implementation
3091       // result is allocated via new[]; we'll delete[] it later.
3092       // return value of NULL indicates total failure.
3093       // return value of (void *)-1 indicates that the state of the machine isn't quite
3094       //    ready for an inferiorRPC, and that we should try again 'later'.  In
3095       //    particular, we must handle the (void *)-1 case very gracefully (i.e., leave
3096       //    the vrble 'RPCsWaitingToStart' untouched).
3097
3098    if (theSavedRegs == (void *)-1) {
3099       // cerr << "launchRPCifAppropriate: deferring" << endl;
3100       if (wasRunning)
3101          (void)continueProc();
3102       return false;
3103    }
3104
3105    if (theSavedRegs == NULL) {
3106       cerr << "launchRPCifAppropriate failed because getRegisters() failed" << endl;
3107       if (wasRunning)
3108          (void)continueProc();
3109       return false;
3110    }
3111
3112    if (!wasRunning)
3113      inferiorrpc_cerr << "NOTE: launchIfAppropriate: wasRunning==false!!" << endl;
3114
3115    inferiorRPCtoDo todo = RPCsWaitingToStart.removeOne();
3116       // note: this line should always be below the test for (void*)-1, thus
3117       // leaving 'RPCsWaitingToStart' alone in that case.
3118
3119    inferiorRPCinProgress inProgStruct;
3120    inProgStruct.callbackFunc = todo.callbackFunc;
3121    inProgStruct.userData = todo.userData;
3122    inProgStruct.savedRegs = theSavedRegs;
3123    inProgStruct.wasRunning = wasRunning || finishingSysCall;
3124       // If finishing up a system call, current state is paused, but we want to
3125       // set wasRunning to true so that it'll continue when the inferiorRPC
3126       // completes.  Sorry for the kludge.
3127    unsigned tempTrampBase = createRPCtempTramp(todo.action,
3128                                                todo.noCost,
3129                                                inProgStruct.callbackFunc != NULL,
3130                                                inProgStruct.breakAddr,
3131                                                inProgStruct.stopForResultAddr,
3132                                                inProgStruct.justAfter_stopForResultAddr,
3133                                                inProgStruct.resultRegister);
3134       // the last 4 args are written to
3135
3136    if (tempTrampBase == 0) {
3137       cerr << "launchRPCifAppropriate failed because createRPCtempTramp failed" << endl;
3138       if (wasRunning)
3139          (void)continueProc();
3140       return false;
3141    }
3142
3143    assert(tempTrampBase);
3144
3145    inProgStruct.firstInstrAddr = tempTrampBase;
3146
3147    assert(currRunningRPCs.empty()); // since it's unsafe to run > 1 at a time
3148    currRunningRPCs += inProgStruct;
3149
3150    inferiorrpc_cerr << "Changing pc and exec.." << endl;
3151
3152    // change the PC and nPC registers to the addr of the temp tramp
3153    if (!changePC(tempTrampBase, theSavedRegs)) {
3154       cerr << "launchRPCifAppropriate failed because changePC() failed" << endl;
3155       if (wasRunning)
3156          (void)continueProc();
3157       return false;
3158    }
3159
3160    if (!continueProc()) {
3161       cerr << "launchRPCifAppropriate: continueProc() failed" << endl;
3162       return false;
3163    }
3164
3165    inferiorrpc_cerr << "inferiorRPC should be running now" << endl;
3166
3167    return true; // success
3168 }
3169
3170 unsigned process::createRPCtempTramp(AstNode *action,
3171                                      bool noCost,
3172                                      bool shouldStopForResult,
3173                                      unsigned &breakAddr,
3174                                      unsigned &stopForResultAddr,
3175                                      unsigned &justAfter_stopForResultAddr,
3176                                      reg &resultReg) {
3177
3178    // Returns addr of temp tramp, which was allocated in the inferior heap.
3179    // You must free it yourself when done.
3180
3181    // Note how this is, in many ways, a greatly simplified version of
3182    // addInstFunc().
3183
3184    // Temp tramp structure: save; code; restore; trap; illegal
3185    // the illegal is just to make sure that the trap never returns
3186    // note that we may not need to save and restore anything, since we've
3187    // already done a GETREGS and we'll restore with a SETREGS, right?
3188
3189    unsigned char insnBuffer[4096];
3190
3191    initTramps(); // initializes "regSpace", but only the 1st time it gets called...
3192    extern registerSpace *regSpace;
3193    regSpace->resetSpace();
3194
3195    unsigned count = 0;
3196
3197    // The following is implemented in an arch-specific source file...
3198    if (!emitInferiorRPCheader(insnBuffer, count)) {
3199       // a fancy dialog box is probably called for here...
3200       cerr << "createRPCtempTramp failed because emitInferiorRPCheader failed." << endl;
3201       return NULL;
3202    }
3203
3204 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
3205    generateMTpreamble((char*)insnBuffer,count,this);
3206 #endif
3207
3208    resultReg = action->generateCode(this, regSpace,
3209                                     (char*)insnBuffer,
3210                                     count, noCost);
3211
3212    if (!shouldStopForResult) {
3213       regSpace->freeRegister(resultReg);
3214    }
3215    else
3216       ; // in this case, we'll call freeRegister() the inferior rpc completes
3217
3218    // Now, the trailer (restore, TRAP, illegal)
3219    // (the following is implemented in an arch-specific source file...)
3220
3221    unsigned breakOffset, stopForResultOffset, justAfter_stopForResultOffset;
3222    if (!emitInferiorRPCtrailer(insnBuffer, count,
3223                                breakOffset, shouldStopForResult, stopForResultOffset,
3224                                justAfter_stopForResultOffset)) {
3225       // last 4 args except shouldStopForResult are modified by the call
3226       cerr << "createRPCtempTramp failed because emitInferiorRPCtrailer failed." << endl;
3227       return NULL;
3228    }
3229
3230    unsigned tempTrampBase = inferiorMalloc(this, count, textHeap);
3231    assert(tempTrampBase);
3232
3233
3234    breakAddr                   = tempTrampBase + breakOffset;
3235    if (shouldStopForResult) {
3236       stopForResultAddr           = tempTrampBase + stopForResultOffset;
3237       justAfter_stopForResultAddr = tempTrampBase + justAfter_stopForResultOffset;
3238    }
3239    else {
3240       stopForResultAddr = justAfter_stopForResultAddr = 0;
3241    }
3242
3243    inferiorrpc_cerr << "createRPCtempTramp: temp tramp base=" << (void*)tempTrampBase
3244                     << ", stopForResultAddr=" << (void*)stopForResultAddr
3245                     << ", justAfter_stopForResultAddr=" << (void*)justAfter_stopForResultAddr
3246                     << ", breakAddr=" << (void*)breakAddr
3247                     << ", count=" << count << " so end addr="
3248                     << (void*)(tempTrampBase + count - 1) << endl;
3249
3250 #if defined(MT_DEBUG)
3251    sprintf(errorLine,"********>>>>> tempTrampBase = 0x%x\n",tempTrampBase);
3252    logLine(errorLine);
3253 #endif
3254
3255    /* Now, write to the tempTramp, in the inferior addr's data space
3256       (all tramps are allocated in data space) */
3257    if (!writeDataSpace((void*)tempTrampBase, count, insnBuffer)) {
3258       // should put up a nice error dialog window
3259       cerr << "createRPCtempTramp failed because writeDataSpace failed" << endl;
3260       return NULL;
3261    }
3262
3263    extern int trampBytes; // stats.h
3264    trampBytes += count;
3265
3266    return tempTrampBase;
3267 }
3268
3269 bool process::handleTrapIfDueToRPC() {
3270    // get curr PC register (can assume process is stopped), search for it in
3271    // 'currRunningRPCs'.  If found, restore regs, do callback, delete tramp, and
3272    // return true.  Returns false if not processed.
3273
3274    assert(status_ == stopped); // a TRAP should always stop a process (duh)
3275    
3276    if (currRunningRPCs.empty())
3277       return false; // no chance of a match
3278
3279    assert(currRunningRPCs.size() == 1);
3280       // it's unsafe to have > 1 RPCs going on at a time within a single process
3281
3282    // Okay, time to do a stack trace.
3283    // If we determine that the PC of any level of the back trace
3284    // equals the current running RPC's stopForResultAddr or breakAddr,
3285    // then we have a match.  Note: since all platforms currently
3286    // inline their trap/ill instruction instead of make a fn call e.g. to
3287    // DYNINSTbreakPoint(), we can probably get rid of the stack walk.
3288
3289    int match_type = 0; // 1 --> stop for result, 2 --> really done
3290    Frame theFrame(this);
3291    while (true) {
3292       // do we have a match?
3293       const int framePC = theFrame.getPC();
3294       if ((unsigned)framePC == currRunningRPCs[0].breakAddr) {
3295          // we've got a match!
3296          match_type = 2;
3297          break;
3298       }
3299       else if (currRunningRPCs[0].callbackFunc != NULL &&
3300                ((unsigned)framePC == currRunningRPCs[0].stopForResultAddr)) {
3301          match_type = 1;
3302          break;
3303       }
3304
3305       if (theFrame.isLastFrame())
3306          // well, we've gone as far as we can, with no match.
3307          return false;
3308
3309       // else, backtrace 1 more level
3310       theFrame = theFrame.getPreviousStackFrameInfo(this);
3311    }
3312
3313    assert(match_type == 1 || match_type == 2);
3314
3315    inferiorRPCinProgress &theStruct = currRunningRPCs[0];
3316
3317    if (match_type == 1) {
3318       // We have stopped in order to grab the result.  Grab it and write
3319       // to theStruct.resultValue, for use when we get match_type==2.
3320
3321       inferiorrpc_cerr << "Welcome to handleTrapIfDueToRPC match type 1" << endl;
3322
3323       assert(theStruct.callbackFunc != NULL);
3324         // must be a callback to ever see this match_type
3325
3326       const unsigned returnValue = read_inferiorRPC_result_register(theStruct.resultRegister);
3327
3328       extern registerSpace *regSpace;
3329       regSpace->freeRegister(theStruct.resultRegister);
3330
3331       theStruct.resultValue = returnValue;
3332
3333       // we don't remove the RPC from 'currRunningRPCs', since it's not yet done.
3334       // we continue the process...but not quite at the PC where we left off, since
3335       // that will just re-do the trap!  Instead, we need to continue at the location
3336       // of the next instruction.
3337       if (!changePC(theStruct.justAfter_stopForResultAddr))
3338          assert(false);
3339
3340       if (!continueProc())
3341          cerr << "RPC getting result: continueProc failed" << endl;
3342
3343       return true;
3344    }
3345
3346    inferiorrpc_cerr << "Welcome to handleTrapIfDueToRPC match type 2" << endl;
3347
3348    assert(match_type == 2);
3349
3350    // step 1) restore registers:
3351    if (!restoreRegisters(theStruct.savedRegs)) {
3352       cerr << "handleTrapIfDueToRPC failed because restoreRegisters failed" << endl;
3353       assert(false);
3354    }
3355    currRunningRPCs.removeByIndex(0);
3356
3357    if (currRunningRPCs.empty() && deferredContinueProc) {
3358      // We have a pending continueProc that we had to delay because
3359      // there was an inferior RPC in progress at that time, but now
3360      // we are ready to execute it - naim
3361      deferredContinueProc=false;
3362      if (continueProc()) statusLine("application running");
3363    }
3364
3365    delete [] theStruct.savedRegs;
3366
3367    // step 2) delete temp tramp
3368    vector< vector<unsigned> > pointsToCheck;
3369       // blank on purpose; deletion is safe to take place even right now
3370    inferiorFree(this, theStruct.firstInstrAddr, textHeap, pointsToCheck);
3371
3372    // step 3) continue process, if appropriate
3373    if (theStruct.wasRunning) {
3374       inferiorrpc_cerr << "end of rpc -- continuing process, since it had been running" << endl;
3375
3376       if (!continueProc()) {
3377          cerr << "RPC completion: continueProc failed" << endl;
3378       }
3379    }
3380    else
3381       inferiorrpc_cerr << "end of rpc -- leaving process paused, since it wasn't running before" << endl;
3382
3383    // step 4) invoke user callback, if any
3384    // note: I feel it's important to do the user callback last, since it
3385    // may perform arbitrary actions (such as making igen calls) which can lead
3386    // to re-actions (such as receiving igen calls) that can alter the process
3387    // (e.g. continuing it).  So clearly we need to restore registers, change the
3388    // PC, etc. BEFORE any such thing might happen.  Hence we do the callback last.
3389    // I think the only potential controversy is whether we should do the callback
3390    // before step 3, above.
3391
3392    inferiorrpc_cerr << "handleTrapIfDueToRPC match type 2 -- about to do callbackFunc, if any" << endl;
3393
3394    if (theStruct.callbackFunc)
3395       theStruct.callbackFunc(this, theStruct.userData, theStruct.resultValue);
3396
3397    inferiorrpc_cerr << "handleTrapIfDueToRPC match type 2 -- done with callbackFunc, if any" << endl;
3398
3399    return true;
3400 }
3401
3402 void process::installBootstrapInst() {
3403    // instrument main to call DYNINSTinit().  Don't use the shm seg for any
3404    // temp tramp space, since we can't assume that it's been intialized yet.
3405    // We build an ast saying: "call DYNINSTinit() with args
3406    // key_base, nbytes, paradynd_pid"
3407
3408 #ifdef BPATCH_LIBRARY
3409    vector<AstNode *> the_args(2);
3410
3411    the_args[0] = new AstNode(AstNode::Constant, (void*)1);
3412    the_args[1] = new AstNode(AstNode::Constant, (void*)getpid());
3413
3414    AstNode *ast = new AstNode("DYNINSTinit", the_args);
3415 #else
3416    vector<AstNode *> the_args(3);
3417
3418    // 2 dummy args when not shm sampling (just don't use -1, which is reserved
3419    // for fork)
3420    unsigned numBytes = 0;
3421    
3422 #ifdef SHM_SAMPLING
3423    key_t theKey   = getShmKeyUsed();
3424    numBytes = getShmHeapTotalNumBytes();
3425 #else
3426    int theKey = 0;
3427 #endif
3428
3429 #ifdef SHM_SAMPLING_DEBUG
3430    cerr << "paradynd inst.C: about to call DYNINSTinit() with key=" << theKey
3431         << " and #bytes=" << numBytes << endl;
3432 #endif
3433
3434    the_args[0] = new AstNode(AstNode::Constant, (void*)theKey);
3435    the_args[1] = new AstNode(AstNode::Constant, (void*)numBytes);
3436 #ifdef BPATCH_LIBRARY
3437    // Unused by the dyninstAPI library
3438    the_args[2] = new AstNode(AstNode::Constant, (void *)0);
3439 #else
3440    the_args[2] = new AstNode(AstNode::Constant, (void*)traceConnectInfo);
3441 #endif
3442
3443    AstNode *ast = new AstNode("DYNINSTinit", the_args);
3444    for (unsigned j=0; j<the_args.size(); j++) {
3445        removeAst(the_args[j]);
3446    }
3447 #endif /* BPATCH_LIBRARY */
3448
3449    function_base *func = getMainFunction();
3450    assert(func);
3451
3452    instPoint *func_entry = (instPoint *)func->funcEntry(this);
3453    addInstFunc(this, func_entry, ast, callPreInsn,
3454                orderFirstAtPoint,
3455                true // true --> don't try to have tramp code update the cost
3456                );
3457    // returns an "instInstance", which we ignore (but should we?)
3458    removeAst(ast);
3459 }
3460
3461 void process::installInstrRequests(const vector<instMapping*> &requests) {
3462    for (unsigned lcv=0; lcv < requests.size(); lcv++) {
3463       instMapping *req = requests[lcv];
3464
3465       function_base *func = findOneFunction(req->func);
3466       if (!func)
3467          continue;  // probably should have a flag telling us whether errors should
3468                     // be silently handled or not
3469
3470       AstNode *ast;
3471       if (req->where & FUNC_ARG) {
3472         // ast = new AstNode(req->inst, req->arg);
3473         ast = new AstNode(req->inst, req->args);
3474       } else {
3475         AstNode *tmp = new AstNode(AstNode::Constant, (void*)0);
3476         ast = new AstNode(req->inst, tmp);
3477         removeAst(tmp);
3478       }
3479
3480       if (req->where & FUNC_EXIT) {
3481          const vector<instPoint*> func_rets = func->funcExits(this);
3482          for (unsigned j=0; j < func_rets.size(); j++)
3483             (void)addInstFunc(this, func_rets[j], ast,
3484                               callPreInsn, orderLastAtPoint, false);
3485
3486       }
3487
3488       if (req->where & FUNC_ENTRY) {
3489          instPoint *func_entry = (instPoint *)func->funcEntry(this);
3490          (void)addInstFunc(this, func_entry, ast,
3491                            callPreInsn, orderLastAtPoint, false);
3492
3493       }
3494
3495       if (req->where & FUNC_CALL) {
3496          vector<instPoint*> func_calls = func->funcCalls(this);
3497          if (func_calls.size() == 0)
3498             continue;
3499
3500          for (unsigned j=0; j < func_calls.size(); j++)
3501             (void)addInstFunc(this, func_calls[j], ast,
3502                               callPreInsn, orderLastAtPoint, false);
3503
3504       }
3505
3506       removeAst(ast);
3507    }
3508 }
3509
3510 bool process::extractBootstrapStruct(DYNINST_bootstrapStruct *bs_record) {
3511    const string vrbleName = "DYNINST_bootstrap_info";
3512    internalSym sym;
3513
3514    bool flag = findInternalSymbol(vrbleName, true, sym);
3515    assert(flag);
3516
3517    Address symAddr = sym.getAddr();
3518
3519    if (!readDataSpace((const void*)symAddr, sizeof(*bs_record), bs_record, true)) {
3520       cerr << "extractBootstrapStruct failed because readDataSpace failed" << endl;
3521       return false;
3522    }
3523
3524    return true;
3525 }
3526
3527 bool process::handleStopDueToExecEntry() {
3528    // returns true iff we are processing a stop due to the entry point of exec
3529    // The exec hasn't yet occurred.
3530
3531    assert(status_ == stopped);
3532
3533    DYNINST_bootstrapStruct bs_record;
3534    if (!extractBootstrapStruct(&bs_record))
3535       assert(false);
3536
3537    if (bs_record.event != 4)
3538       return false;
3539
3540    assert(getPid() == bs_record.pid);
3541
3542    // for now, we just set aside the following information, to be used after the
3543    // exec actually happens (we'll get a SIGTRAP for that).
3544    assert(!inExec);
3545    inExec = true;
3546    execFilePath = string(bs_record.path);
3547
3548    // the process was stopped...let's continue it so we can process the exec...
3549    assert(status_ == stopped);
3550    if (!continueProc())
3551       assert(false);
3552
3553    // should we set status_ to neonatal now?  Nah, probably having the inExec flag
3554    // set is good enough...
3555
3556    // shouldn't we be setting reachedFirstBreak to false???
3557
3558    return true;
3559 }
3560
3561 int process::procStopFromDYNINSTinit() {
3562    // possible return values:
3563    // 0 --> no, the stop wasn't the end of DYNINSTinit
3564    // 1 --> handled stop at end of DYNINSTinit, leaving program paused
3565    // 2 --> handled stop at end of DYNINSTinit...which had been invoked via
3566    //       inferiorRPC...so we've continued the process in order to let the
3567    //       inferiorRPC get its sigtrap.
3568
3569    // Note that DYNINSTinit could have been run under several cases:
3570    // 1) the normal case     (detect by bs_record.event==1 && execed_ == false)
3571    // 2) called after a fork (detect by bs_record.event==2)
3572    // 3) called after an exec (detect by bs_record.event==1 and execed_ == true)
3573    // 4) called for an attach (detect by bs_record.event==3)
3574    // note that bs_record.event == 4 is reserved for "sending" a tr_exec "record".
3575    //
3576    // The exec case is tricky: we must loop thru all component mi's of this process
3577    // and decide now whether or not to carry them over to the new process.
3578
3579    // if 0 is returned, there must be no side effects.
3580
3581    assert(status_ == stopped);
3582
3583    if (hasBootstrapped)
3584       return 0;
3585
3586    DYNINST_bootstrapStruct bs_record;
3587    if (!extractBootstrapStruct(&bs_record))
3588       assert(false);
3589
3590    // Read the structure; if event 0 then it's undefined! (not yet written)
3591    if (bs_record.event == 0)
3592       return 0;
3593
3594    forkexec_cerr << "procStopFromDYNINSTinit pid " << getPid() << "; got rec" << endl;
3595
3596    assert(bs_record.event == 1 || bs_record.event == 2 || bs_record.event==3);
3597    assert(bs_record.pid == getPid());
3598
3599    if (bs_record.event != 3) {
3600       // we don't want to do this stuff (yet) when DYNINSTinit was run via attach...we
3601       // want to wait until the inferiorRPC (thru which DYNINSTinit is being run)
3602       // completes.
3603       handleCompletionOfDYNINSTinit(false);
3604       return 1;
3605    }
3606    else {
3607       if (!continueProc())
3608          assert(false);
3609       return 2;
3610    }
3611 }
3612
3613 void process::handleCompletionOfDYNINSTinit(bool fromAttach) {
3614    // 'event' values: (1) DYNINSTinit was started normally via paradynd
3615    // or via exec, (2) called from fork, (3) called from attach.
3616
3617    DYNINST_bootstrapStruct bs_record;
3618    if (!extractBootstrapStruct(&bs_record))
3619       assert(false);
3620
3621    if (!fromAttach) // reset to 0 already if attaching, but other fields (attachedAtPtr) ok
3622       assert(bs_record.event == 1 || bs_record.event == 2 || bs_record.event==3);
3623
3624    assert(bs_record.pid == getPid());
3625
3626    // Note: the process isn't necessarily paused at this moment.  In particular,
3627    // if we had attached to the process, then it will be running even as we speak.
3628    // While we're parsing the shared libraries, we should pause.  So do that now.
3629    bool wasRunning;
3630    if (needToContinueAfterDYNINSTinit) 
3631      wasRunning = true;
3632    else 
3633      wasRunning = status_ == running;
3634    (void)pause();
3635
3636    const bool calledFromFork   = (bs_record.event == 2);
3637    const bool calledFromExec   = (bs_record.event == 1 && execed_);
3638    const bool calledFromAttach = fromAttach || bs_record.event == 3;
3639    if (calledFromAttach)
3640       assert(createdViaAttach);
3641
3642 #ifdef SHM_SAMPLING
3643    if (!calledFromFork)
3644       registerInferiorAttachedSegs(bs_record.appl_attachedAtPtr);
3645 #endif
3646
3647    if (!calledFromFork)
3648       getObservedCostAddr();
3649
3650    // handleStartProcess gets shared objects, so no need to do it again after a fork.
3651    // (question: do we need to do this after an exec???)
3652    if (!calledFromFork) {
3653       string str=string("PID=") + string(bs_record.pid) + ", calling handleStartProcess...";
3654       statusLine(str.string_of());
3655
3656 #if !defined(USES_LIBDYNINSTRT_SO)
3657       if (!handleStartProcess()) {
3658         // reads in shared libraries...can take a while
3659         logLine("WARNING: handleStartProcess failed\n");
3660       }
3661 #endif
3662
3663 #ifndef BPATCH_LIBRARY
3664       // we decrement the batch mode here; it matches the bump-up in createProcess()
3665       tp->resourceBatchMode(false);
3666 #endif
3667
3668       str=string("PID=") + string(bs_record.pid) + ", installing default inst...";
3669       statusLine(str.string_of());
3670
3671       extern vector<instMapping*> initialRequests; // init.C
3672       installInstrRequests(initialRequests);
3673
3674       str=string("PID=") + string(bs_record.pid) + ", propagating mi's...";
3675       statusLine(str.string_of());
3676
3677       forkexec_cerr << "procStopFromDYNINSTinit pid " << getPid() << "; about to propagate mi's" << endl;
3678
3679 #ifndef BPATCH_LIBRARY
3680       if (!calledFromExec) {
3681          // propagate any metric that is already enabled to the new process.
3682          // For a forked process, this isn't needed because handleFork() has its own
3683          // special propagation algorithm (it propagates every aggregate mi having the
3684          // parent as a component, except for aggregate mi's whose focus is specifically
3685          // refined to the parent).
3686          vector<metricDefinitionNode *> MIs = allMIs.values();
3687          for (unsigned j = 0; j < MIs.size(); j++) {
3688             MIs[j]->propagateToNewProcess(this);
3689             // change to a process:: method which takes in the metricDefinitionNode
3690          }