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