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