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