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