Problem 1:
[dyninst.git] / dyninstAPI / src / process.C
1 /*
2  * Copyright (c) 1996-2004 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 // $Id: process.C,v 1.581 2006/02/14 23:50:15 jaw Exp $
43
44 #include <ctype.h>
45
46 #if defined(i386_unknown_solaris2_5)
47 #include <sys/procfs.h>
48 #endif
49
50 #include <set>
51
52 #include <stdio.h>
53
54 #include "common/h/headers.h"
55 #include "dyninstAPI/src/function.h"
56 //#include "dyninstAPI/src/func-reloc.h"
57 #include "dyninstAPI/src/baseTramp.h"
58 #include "dyninstAPI/src/miniTramp.h"
59 #include "dyninstAPI/src/symtab.h"
60 #include "dyninstAPI/src/dyn_thread.h"
61 #include "dyninstAPI/src/dyn_lwp.h"
62 #include "dyninstAPI/src/signalhandler.h"
63 #include "dyninstAPI/src/mailbox.h"
64 #include "dyninstAPI/src/EventHandler.h"
65 #include "dyninstAPI/src/process.h"
66 #include "dyninstAPI/src/util.h"
67 #include "dyninstAPI/src/inst.h"
68 #include "dyninstAPI/src/instP.h"
69 #include "dyninstAPI/src/instPoint.h"
70 #include "dyninstAPI/src/os.h"
71 #include "dyninstAPI/src/showerror.h"
72 #include "dyninstAPI/src/callbacks.h"
73 #include "dyninstAPI/src/dynamiclinking.h"
74 #include "dyninstAPI/src/BPatch_asyncEventHandler.h"
75 #include "dyninstAPI/src/debuggerinterface.h"
76 #include "dyninstAPI_RT/h/dyninstAPI_RT.h"
77 // #include "paradynd/src/mdld.h"
78 #include "common/h/Timer.h"
79 #include "common/h/Time.h"
80 #include "common/h/timing.h"
81
82 #include "dyninstAPI/src/rpcMgr.h"
83
84 #include "mapped_module.h"
85 #include "mapped_object.h"
86
87 #include "dyninstAPI/h/BPatch.h"
88
89 #if defined(sparc_sun_solaris2_4) \
90  || defined(i386_unknown_linux2_0) \
91  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
92 #include "dyninstAPI/src/writeBackElf.h"
93 #include "dyninstAPI/src/saveSharedLibrary.h" 
94 #elif defined(rs6000_ibm_aix4_1)
95 #include "dyninstAPI/src/writeBackXCOFF.h"
96 #endif
97
98 #include "dyninstAPI/src/syscallNotification.h"
99
100 #if !defined(BPATCH_LIBRARY)
101 #include "rtinst/h/rtinst.h"
102 #include "rtinst/h/trace.h"
103 #include "paradynd/src/perfStream.h"
104 #include "paradynd/src/metricFocusNode.h"
105 #include "paradynd/src/costmetrics.h"
106 #include "paradynd/src/mdld.h"
107 #include "paradynd/src/main.h"
108 #include "paradynd/src/init.h"
109 #include "pdutil/h/pdDebugOstream.h"
110 #include "common/h/int64iostream.h"
111 #endif
112
113 #ifndef BPATCH_LIBRARY
114 #ifdef PAPI
115 #include "paradynd/src/papiMgr.h"
116 #endif
117 #endif
118
119 #include "common/h/debugOstream.h"
120
121 #include "common/h/Timer.h"
122
123 #define FREE_WATERMARK (hp->totalFreeMemAvailable/2)
124 #define SIZE_WATERMARK 100
125 static const timeLength MaxWaitingTime(10, timeUnit::sec());
126 static const timeLength MaxDeletingTime(2, timeUnit::sec());
127
128 unsigned activeProcesses; // number of active processes
129 pdvector<process*> processVec;
130
131
132 #ifndef BPATCH_LIBRARY
133 extern pdstring osName;
134 #endif
135
136 #if defined(i386_unknown_linux2_0) \
137  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
138 extern void cleanupVsysinfo(void *ehd);
139 #endif
140
141 pdvector<instMapping*> initialRequests;
142
143 void printLoadDyninstLibraryError() {
144     cerr << "Paradyn/Dyninst failed to load the runtime library. This is normally caused by " << endl;
145     cerr << "one of the following:" << endl;
146     cerr << "Incorrect DYNINSTAPI_RT_LIB environment variable" << endl;
147     cerr << "Missing RT library" << endl;
148     cerr << "Unavailable dependency of the library" << endl;
149 #if defined(rs6000_ibm_aix4_1)
150     cerr << "   libDyninstText.a must exist in a directory in the LIBPATH environment variable" << endl;
151 #endif
152     cerr << "Please check your environment and try again." << endl;
153 }
154
155
156 void setLibState(libraryState_t &lib, libraryState_t state) {
157     if (lib > state) cerr << "Error: attempting to revert library state" << endl;
158     else lib = state;
159 }
160
161 /* AIX method defined in aix.C; hijacked for IA-64's GP. */
162 #if !defined(rs6000_ibm_aix4_1) \
163  && !defined(ia64_unknown_linux2_4)
164 Address process::getTOCoffsetInfo(Address /*dest */)
165 {
166   Address tmp = 0;
167   assert(0 && "getTOCoffsetInfo not implemented");
168   return tmp; // this is to make the nt compiler happy! - naim
169 }
170 #else
171 Address process::getTOCoffsetInfo(Address dest)
172 {
173     // We have an address, and want to find the module the addr is
174     // contained in. Given the probabilities, we (probably) want
175     // the module dyninst_rt is contained in.
176     // I think this is the right func to use
177     
178     // Find out which object we're in (by addr).
179     codeRange *range = NULL;
180     codeSections_.find(dest, range);
181     if (!range)  // Try data?
182         dataSections_.find(dest, range);
183     if (!range)
184         return 0;
185     mapped_object *mobj = range->is_mapped_object();
186     if (!mobj) {
187         mappedObjData *tmp = dynamic_cast<mappedObjData *>(range);
188         if (tmp)
189             mobj = tmp->obj;
190     }
191     // Very odd case if this is not defined.
192     assert(mobj); 
193     
194     Address TOCoffset = mobj->parse_img()->getObject().getTOCoffset();
195     return TOCoffset + mobj->dataBase();
196 }
197
198 #endif
199
200 #if defined(os_linux) && (defined(arch_x86) || defined(arch_x86_64))
201 extern void calcVSyscallFrame(process *p);
202 #endif
203
204 // Windows NT has its own version of the walkStack function in pdwinnt.C
205
206 // Note: stack walks may terminate early. In this case, return what we can.
207 // Relies on the getCallerFrame method in the various <os>.C files
208
209 #if !defined(mips_unknown_ce2_11) && !defined(i386_unknown_nt4_0)
210 bool process::walkStackFromFrame(Frame startFrame,
211                                  pdvector<Frame> &stackWalk)
212 {
213   Address fpOld   = 0;
214   Address fpNew   = 0;
215
216   Frame currentFrame = startFrame;
217   
218   if (!isStopped()) {
219       fprintf(stderr, "%s[%d]:  walkStackFromFrame failing\n", FILE__, __LINE__);
220       return false;
221   }
222
223 #if defined( os_linux ) 
224         /* Do a special check for the vsyscall page.  Silently drop
225            the page if it exists. */
226 #if defined( arch_ia64 )
227         /* The IA-64 doesn't use DWARF to unwind out of the vsyscall page,
228            so calcVsyscallFrame() is overkill. */
229         if( getVsyscallStart() == 0x0 ) {
230                 if( ! readAuxvInfo() ) {
231                         /* We're probably on Linux 2.4; use default values. */
232                         setVsyscallRange( 0xffffffffffffe000, 0xfffffffffffff000 );
233                         setVsyscallData( NULL );
234                         }
235                 }
236 #else
237         calcVSyscallFrame( this );
238 #endif /* defined( arch_ia64 ) */
239   
240   Address next_pc = currentFrame.getPC();
241   if (next_pc >= getVsyscallStart() && next_pc < getVsyscallEnd()) {
242      currentFrame = currentFrame.getCallerFrame();
243   }
244 #endif /* defined( os_linux ) */
245
246   while (!currentFrame.isLastFrame()) {
247     // grab the frame pointer
248     fpNew = currentFrame.getFP();
249
250     // Check that we are not moving up the stack
251     // successive frame pointers might be the same (e.g. leaf functions)
252 #if ! defined( os_linux )
253     if (fpOld > fpNew) {
254       // AIX:
255       // There's a signal function in the MPI library that we're not
256       // handling properly. Instead of returning an empty stack,
257       // return what we have.
258       // One thing that makes me feel better: gdb is getting royally
259       // confused as well. This sucks for catchup.
260       
261 #if defined( ia64_unknown_linux2_4 )
262         /* My single-stepper needs to be able to continue past stackwalking errors. */      
263         // /* DEBUG */ fprintf( stderr, "Not terminating stackwalk early, even though fpOld (0x%lx) > fpNew (0x%lx).\n", fpOld, fpNew );
264         // /* DEBUG */ for( unsigned int i = 0; i < stackWalk.size(); i++ ) {
265         // /* DEBUG */  cerr << stackWalk[i] << endl;
266         // /* DEBUG */  } 
267         // /* DEBUG */  cerr << currentFrame << endl; 
268         // /* DEBUG */ cerr << endl;
269         break;
270 #else
271         // We should check to see if this early exit is warranted.
272         fprintf(stderr, "%s[%d]:  failing stackWalk here\n", FILE__, __LINE__);
273         //return false;
274 #endif
275     }
276 #endif
277     fpOld = fpNew;
278     stackWalk.push_back(currentFrame);    
279     currentFrame = currentFrame.getCallerFrame(); 
280   }
281   // Clean up after while loop (push end frame)
282   // FIXME: get LastFrame on AMD64 des not work the same as on other platforms
283   //        since the FP is not always zero
284   if (currentFrame.getProc() != NULL) {
285       stackWalk.push_back(currentFrame);
286   }
287
288   return true;
289 }
290 #endif
291
292 // Return a vector (possibly with one object) of active frames
293 // in the process
294
295 bool process::getAllActiveFrames(pdvector<Frame> &activeFrames)
296 {
297   Frame active;
298   bool success = true;
299   if (!threads.size()) { // Nothing defined in the thread data structures
300     // So use the process LWP instead (Dyninst)
301     active = getRepresentativeLWP()->getActiveFrame();
302     if (active == Frame()) { // Hrm.. should getActive return a bool?
303       return false;
304     }
305     activeFrames.push_back(active);
306   }
307   else { // Iterate through threads
308     for (unsigned i = 0; i < threads.size(); i++) {
309       active = threads[i]->getActiveFrame();
310       if (active == Frame()) {
311         success = true;
312       }
313       else {
314         activeFrames.push_back(active);
315       }
316     }
317   }
318   return success;
319 }
320
321 bool process::walkStacks(pdvector<pdvector<Frame> >&stackWalks, bool ignoreRPC /* = false */)
322 {
323   pdvector<Frame> stackWalk;
324   if (!threads.size()) { // Nothing defined in thread data structures
325     if (!getRepresentativeLWP()->walkStack(stackWalk, ignoreRPC))
326       return false;
327     // Use the walk from the default LWP
328     stackWalks.push_back(stackWalk);
329   }
330   else { // Have threads defined
331     for (unsigned i = 0; i < threads.size(); i++) {
332       if (!threads[i]->walkStack(stackWalk, ignoreRPC))
333          return false;
334       stackWalks.push_back(stackWalk);
335       stackWalk.resize(0);
336     }
337   }
338   return true;
339 }
340
341 extern "C" int heapItemCmpByAddr(const heapItem **A, const heapItem **B)
342 {
343   heapItem *a = *(heapItem **)const_cast<heapItem **>(A);
344   heapItem *b = *(heapItem **)const_cast<heapItem **>(B);
345
346   if (a->addr < b->addr) {
347       return -1;
348   } else if (a->addr > b->addr) {
349       return 1;
350   } else {
351       return 0;
352   }
353 }
354
355 // For exec/process deletion
356 void inferiorHeap::clear() {
357     Address addr;
358     heapItem *heapItemPtr;
359
360     dictionary_hash_iter<Address, heapItem *> activeIter(heapActive);
361     while (activeIter.next(addr, heapItemPtr))
362         delete heapItemPtr;
363     heapActive.clear();
364     
365     for (unsigned i = 0; i < heapFree.size(); i++)
366         delete heapFree[i];
367     heapFree.clear();
368
369     disabledList.clear();
370
371     disabledListTotalMem = 0;
372     totalFreeMemAvailable = 0;
373     freed = 0;
374
375     for (unsigned j = 0; j < bufferPool.size(); j++)
376         delete bufferPool[j];
377     bufferPool.clear();
378 }
379
380 void process::inferiorFreeCompact(inferiorHeap *hp)
381 {
382   pdvector<heapItem *> &freeList = hp->heapFree;
383   unsigned i, nbuf = freeList.size();
384
385   /* sort buffers by address */
386   VECTOR_SORT(freeList, heapItemCmpByAddr);
387
388   /* combine adjacent buffers */
389   bool needToCompact = false;
390   for (i = 1; i < freeList.size(); i++) {
391       heapItem *h1 = freeList[i-1];
392       heapItem *h2 = freeList[i];
393       assert(h1->length != 0);
394       if (h1->addr + h1->length > h2->addr) {
395           fprintf(stderr, "Error: heap 1 (0x%x to 0x%x) overlaps heap 2 (0x%x to 0x%x)\n",
396                   h1->addr, h1->addr + h1->length,
397                   h2->addr, h2->addr + h2->length);
398       }
399       assert(h1->addr + h1->length <= h2->addr);
400       if (h1->addr + h1->length == h2->addr
401           && h1->type == h2->type) {
402           h2->addr = h1->addr;
403           h2->length = h1->length + h2->length;
404           h1->length = 0;
405           nbuf--;
406           needToCompact = true;
407       }
408   }
409
410   /* remove any absorbed (empty) buffers */ 
411   if (needToCompact) {
412     pdvector<heapItem *> cleanList;
413     unsigned end = freeList.size();
414     for (i = 0; i < end; i++) {
415       heapItem *h1 = freeList[i];
416       if (h1->length != 0) {
417         cleanList.push_back(h1);
418       } else {
419         delete h1;
420       }
421     }
422     assert(cleanList.size() == nbuf);
423     for (i = 0; i < nbuf; i++) {
424       freeList[i] = cleanList[i];
425     }
426     freeList.resize(nbuf);
427     assert(freeList.size() == nbuf);
428   }
429 }
430
431 // Search an object for heapage
432
433 bool process::getInfHeapList(const mapped_object *obj,
434                              pdvector<heapDescriptor> &infHeaps)
435 {
436
437     pdvector<mapped_object::foundHeapDesc> foundHeaps;
438     obj->getInferiorHeaps(foundHeaps);
439
440     for (u_int j = 0; j < foundHeaps.size(); j++)
441     {
442         // The string layout is: DYNINSTstaticHeap_size_type_unique
443         // Can't allocate a variable-size array on NT, so malloc
444         // that sucker
445         char *temp_str = (char *)malloc(strlen(foundHeaps[j].name.c_str())+1);
446         strcpy(temp_str, foundHeaps[j].name.c_str());
447         char *garbage_str = strtok(temp_str, "_"); // Don't care about beginning
448         assert(!strcmp("DYNINSTstaticHeap", garbage_str));
449         // Name is as is.
450         // If address is zero, then skip (error condition)
451         if (foundHeaps[j].addr == 0)
452         {
453             cerr << "Skipping heap " << foundHeaps[j].name.c_str()
454                  << "with address 0" << endl;
455             continue;
456         }
457         // Size needs to be parsed out (second item)
458         // Just to make life difficult, the heap can have an optional
459         // trailing letter (k,K,m,M,g,G) which indicates that it's in
460         // kilobytes, megabytes, or gigabytes. Why gigs? I was bored.
461         char *heap_size_str = strtok(NULL, "_"); // Second element, null-terminated
462         unsigned heap_size = (unsigned) atol(heap_size_str);
463         if (heap_size == 0)
464             /* Zero size or error, either way this makes no sense for a heap */
465         {
466             free(temp_str);
467             continue;
468         }
469         switch (heap_size_str[strlen(heap_size_str)-1])
470         {
471       case 'g':
472       case 'G':
473           heap_size *= 1024;
474       case 'm':
475       case 'M':
476           heap_size *= 1024;
477       case 'k':
478       case 'K':
479           heap_size *= 1024;
480       default:
481           break;
482         }
483         
484         // Type needs to be parsed out. Can someone clean this up?
485         inferiorHeapType heap_type;
486         char *heap_type_str = strtok(NULL, "_");
487         
488         if (!strcmp(heap_type_str, "anyHeap"))
489             heap_type = anyHeap;
490         else if (!strcmp(heap_type_str, "lowmemHeap"))
491             heap_type = lowmemHeap;
492         else if (!strcmp(heap_type_str, "dataHeap"))
493             heap_type = dataHeap;
494         else if (!strcmp(heap_type_str, "textHeap"))
495             heap_type = textHeap;
496         else if (!strcmp(heap_type_str, "uncopiedHeap"))
497             heap_type = uncopiedHeap;
498         else
499         {
500             cerr << "Unknown heap string " << heap_type_str << " read from file!" << endl;
501             free(temp_str);
502             continue;
503         }
504         infHeaps.push_back(heapDescriptor(foundHeaps[j].name.c_str(),
505                                           foundHeaps[j].addr, 
506                                           heap_size, heap_type));
507         free(temp_str);
508     }
509   return foundHeaps.size() > 0;
510 }
511
512 /*
513  * Returns true if the address given is within the signal handler function,
514  * otherwise returns false.
515  */
516 bool process::isInSignalHandler(Address addr)
517 {
518 #if defined(arch_ia64)
519     // We handle this elsewhere
520     return false;
521 #endif
522     codeRange *range;
523     if (signalHandlerLocations_.find(addr, range))
524         return true;
525     return false;
526 }
527
528 /*
529  * This function adds an item to the dataUpdates vector
530  * which is used to maintain a list of variables that have
531  * been written by the mutator //ccw 26 nov 2001
532  */
533  
534 #if defined(sparc_sun_solaris2_4) \
535  || defined(i386_unknown_linux2_0) \
536  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */ \
537  || defined(rs6000_ibm_aix4_1)
538
539 void process::saveWorldData( Address address, int size, const void * src ) {
540         if( collectSaveWorldData ) {
541                 dataUpdate *newData = new dataUpdate;
542                 newData->address= address;
543                 newData->size = size;
544                 newData->value = new char[size];
545                 memcpy(newData->value, src, size);
546                 dataUpdates.push_back(newData);
547                 }
548         } /* end saveWorldData() */
549         
550 #else
551
552 void process::saveWorldData( Address, int, const void* ) { ; }    
553
554 #endif
555
556 #if defined(sparc_sun_solaris2_4) \
557  || defined(i386_unknown_linux2_0) \
558  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */ \
559  || defined(rs6000_ibm_aix4_1)
560 /* || defined(rs6000_ibm_aix4_1)*/
561
562 char* process::saveWorldFindDirectory(){
563
564         const char* directoryNameExt = "_dyninstsaved";
565         int dirNo = 0;
566 /* ccw */
567         char cwd[1024];
568         char* directoryName;
569         int lastChar;
570         getcwd(cwd, 1024);
571         lastChar = strlen(cwd);
572
573         if( cwd[lastChar] != '/' && lastChar != 1023){
574                 cwd[lastChar] = '/';
575                 cwd[++lastChar] ='\0';
576         }
577
578         directoryName = new char[strlen(cwd) +
579                         strlen(directoryNameExt) + 3+1+1];
580 /* ccw */
581         sprintf(directoryName,"%s%s%x",cwd, directoryNameExt,dirNo);
582         while(dirNo < 0x1000 && mkdir(directoryName, S_IRWXU) ){
583                  if(errno == EEXIST){
584                          dirNo ++;
585                  }else{
586                          BPatch_reportError(BPatchSerious, 122, "dumpPatchedImage: cannot open directory to store mutated binary. No files saved\n");
587                          delete [] directoryName;
588                          return NULL;
589                  }
590                  sprintf(directoryName, "%s%s%x",cwd,
591                          directoryNameExt,dirNo);
592         }
593         if(dirNo == 0x1000){
594                  BPatch_reportError(BPatchSerious, 122, "dumpPatchedImage: cannot open directory to store mutated binary. No files saved\n");
595                  delete [] directoryName;
596                  return NULL;
597         }
598         return directoryName;
599
600 }
601 #endif
602
603 #if defined(sparc_sun_solaris2_4) \
604  || defined(i386_unknown_linux2_0) \
605  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
606
607
608 char *process::saveWorldFindNewSharedLibraryName(pdstring originalLibNameFullPath, char* dirName){
609         const char *originalLibName = originalLibNameFullPath.c_str();
610         unsigned int index=0;
611
612         unsigned int nextIndex = 0;
613         for(nextIndex = 0; nextIndex < originalLibNameFullPath.length() ;nextIndex++){
614                 if(originalLibName[nextIndex] == '/'){
615                         index = nextIndex +1;
616                 }
617         }
618
619         pdstring oldLibName = originalLibNameFullPath.substr(index,originalLibNameFullPath.length());
620         char* newLibName = new char[strlen(dirName) + oldLibName.length()+1];
621         memcpy(newLibName,dirName,strlen(dirName)+1);
622         newLibName =strcat(newLibName, oldLibName.c_str());
623
624         return newLibName;
625
626         
627 }
628
629
630
631 unsigned int process::saveWorldSaveSharedLibs(int &mutatedSharedObjectsSize, 
632                                  unsigned int &dyninst_SharedLibrariesSize, 
633                                  char* directoryName, unsigned int &count) {
634
635    unsigned int dl_debug_statePltEntry=0;
636 #if defined(sparc_sun_solaris2_4)
637    unsigned int tmp_dlopen;
638 #endif
639    bool dlopenUsed = false;
640    
641    //In the mutated binary we need to catch the dlopen events and adjust the
642    //instrumentation of the shared libraries (and jumps into the shared
643    //libraries) as the base address of the shared libraries different for the
644    //base addresses during the original mutator/mutatee run.
645
646    //the r_debug interface ensures that a change to the dynamic linking
647    //information causes _dl_debug_state to be called.  This is because dlopen
648    //is too small and odd to instrument/breakpoint.  So our code will rely on
649    //this fact. (all these functions are contained in ld-linux.so)
650
651    //Our method: The Procedure Linking Table (.plt) for ld-linux contains an
652    //entry that jumps to a specified address in the .rel.plt table. To call a
653    //function, the compiler generates a jump to the correct .plt entry which
654    //reads its jump value out of the .rel.plt.
655
656    //On the sly, secretly replace the entry in .rel.plt with folgers crystals
657    //and poof, we jump to our own function in RTcommon.c
658    //(dyninst_dl_debug_state) [actually we replace the entry in .rel.plt with
659    //the address of dyninst_dl_debug_state].  To ensure correctness,
660    //dyninst_dl_debug_state contains a call to the real _dl_debug_state
661    //immediately before it returns, thus ensuring any code relying on that
662    //fact that _dl_debug_state is actually run remains happy.
663
664    //It is very important then, that we know the location of the entry in the
665    //.rel.plt table.  We need to record the offset of this entry with respect
666    //to the base address of ld-linux.so (for obvious reasons) This offset is
667    //then sent to RTcommon.c, and here is the slick part, by assigning it to
668    //the 'load address' of the section "dyninstAPI_SharedLibraries," which
669    //contains the shared library/basei address pairs used to fixup the saved
670    //binary. This way when checkElfFile() reads the section the offset will
671    //be there in the section header.
672
673    //neat, eh?  this is how it will work in the future, currently this is not
674    //yet fully implemented and part of the cvs tree.
675
676    //UPDATE: the above is implemented EXCEPT for adjusting the instrumentation
677    //when shared libraries move. currently an error is thrown when a shared
678    //lib is in the wrong place and execution is terminated!
679
680         //I have now added the notion of DirtyCalled to a shared library.
681         //This is a library that contains a function that is called by
682         //instrumentation.  The shared lib may or may not be instrumented itself.
683         //If it is not instrumented (Dirty) then it is NOT saved as a mutated 
684         //shared library.  A flag in dyninstAPI_mutatedSO section that follows
685         //the filename denotes whether the library is Dirty or merely DirtyCalled
686
687    count = 0;
688    for (unsigned i = 1; i < mapped_objects.size(); i++) {
689      // We start at 1 because 0 is the a.out
690      mapped_object *sh_obj = mapped_objects[i];
691
692       //ccw 24 jul 2003
693       if( (sh_obj->isDirty() || sh_obj->isDirtyCalled()) &&
694                 /* there are some libraries we should not save even if they are marked as mutated*/
695                 NULL==strstr(sh_obj->fileName().c_str(),"libdyninstAPI_RT") && 
696                 NULL== strstr(sh_obj->fileName().c_str(),"ld-linux.so") && 
697                 NULL==strstr(sh_obj->fileName().c_str(),"libc")){ //ccw 6 jul 2003
698          count ++;
699          if(!dlopenUsed && sh_obj->isopenedWithdlopen()){
700             BPatch_reportError(BPatchWarning,123,"dumpPatchedImage: dlopen used by the mutatee, this may cause the mutated binary to fail\n");
701             dlopenUsed = true;
702          }                      
703          //bperr(" %s is DIRTY!\n", sh_obj->fileName().c_str());
704         
705
706          if( sh_obj->isDirty()){ 
707                         //fprintf(stderr," SAVING SHARED LIB: %s\n", sh_obj->fileName().c_str());
708             //if the lib is only DirtyCalled dont save it! //ccw 24 jul 2003
709             Address textAddr, textSize;
710             char *newName = saveWorldFindNewSharedLibraryName(sh_obj->fileName(),directoryName);
711
712                         /*new char[strlen(sh_obj->fileName().c_str()) + 
713                                      strlen(directoryName) + 1];
714             memcpy(newName, directoryName, strlen(directoryName)+1);
715             const char *file = strrchr(sh_obj->fileName().c_str(), '/');
716             strcat(newName, file);*/
717            
718
719                 /*      what i need to do:
720                         open the ORIGINAL shared lib --> sh_obj->fileName()
721                         read the text section out.
722                         reapply the instrumentation code
723                         save this new, instrumented text section back to the NEW DLDUMPED file in the _dyninstSaved# dir --> newName
724                 */               
725
726             saveSharedLibrary *sharedObj =
727                new saveSharedLibrary(sh_obj->getBaseAddress(),
728                                      sh_obj->fileName().c_str(), newName);
729
730                 sharedObj->openBothLibraries();
731             
732                         sharedObj->getTextInfo(textAddr, textSize);
733                         char* textSection ;//= sharedObj->getTextSection(); /* get the text section from the ORIGINAL library */
734                         textSection = new char[textSize]; //ccw 14 dec 2005
735
736                         if(textSection){
737
738                                 //applyMutationsToTextSection(textSection, textAddr, textSize);
739
740                                 readDataSpace((void*)textAddr, textSize, (void*)textSection, true); //ccw 14 dec 2005
741                         sharedObj->saveMutations(textSection);
742                 sharedObj->closeNewLibrary();
743                     /*                  
744                //this is for the dlopen problem....
745                   if(strstr(sh_obj->fileName().c_str(), "ld-linux.so") ){
746                     //find the offset of _dl_debug_state in the .plt
747                dl_debug_statePltEntry = 
748                   sh_obj->parse_img()->getObject().getPltSlot("_dl_debug_state");
749                     }
750                */                       
751                                 delete [] textSection;
752                         }else{
753                                 char msg[strlen(sh_obj->fileName().c_str())+100];
754                                 sprintf(msg,"dumpPatchedImage: could not retreive .text section for %s\n",sh_obj->fileName().c_str());
755                         BPatch_reportError(BPatchWarning,123,msg);
756                                 sharedObj->closeNewLibrary();
757                         }
758                         sharedObj->closeOriginalLibrary();
759                   delete sharedObj;
760             delete [] newName;
761          }
762          mutatedSharedObjectsSize += strlen(sh_obj->fileName().c_str()) +1 ;
763          mutatedSharedObjectsSize += sizeof(int); //a flag to say if this is only DirtyCalled
764       }
765       //this is for the dlopen problem...
766       if(strstr(sh_obj->fileName().c_str(), "ld-linux.so") ){
767          //find the offset of _dl_debug_state in the .plt
768          dl_debug_statePltEntry = 
769             sh_obj->parse_img()->getObject().getPltSlot("_dl_debug_state");
770       }
771 #if defined(sparc_sun_solaris2_4)
772       
773       if( ((tmp_dlopen = sh_obj->parse_img()->getObject().getPltSlot("dlopen")) && 
774            !sh_obj->isopenedWithdlopen())){
775          dl_debug_statePltEntry = tmp_dlopen + sh_obj->getBaseAddress();
776       }
777 #endif
778       //this is for the dyninst_SharedLibraries section we need to find out
779       //the length of the names of each of the shared libraries to create the
780       //data buffer for the section
781       
782       dyninst_SharedLibrariesSize += strlen(sh_obj->fileName().c_str())+1;
783       //add the size of the address
784       dyninst_SharedLibrariesSize += sizeof(unsigned int);
785    }
786 #if defined(sparc_sun_solaris2_4)
787    if( (tmp_dlopen = getAOut()->parse_img()->getObject().getPltSlot("dlopen"))) {
788        dl_debug_statePltEntry = tmp_dlopen;
789    }
790    
791    //dl_debug_statePltEntry = parse_img()->getObject().getPltSlot("dlopen");
792 #endif
793    dyninst_SharedLibrariesSize += 1;//for the trailing '\0'
794    
795    return dl_debug_statePltEntry;
796 }
797         
798 bool process::applyMutationsToTextSection(char* /*textSection*/, unsigned /*textAddr*/, 
799                                           unsigned /*textSize*/)
800 {
801     // Uhh... what does this do?
802 #if 0
803         mutationRecord *mr = afterMutationList.getHead();
804
805         while (mr != NULL) {
806             if( mr->addr >= textAddr && mr->addr < (textAddr+textSize)){
807                 memcpy(&(textSection[mr->addr-textAddr]), mr->data, mr->size);
808             }
809             mr = mr->next;
810         }
811         return true;
812 #endif
813    return true;
814 }
815
816 char* process::saveWorldCreateSharedLibrariesSection(int dyninst_SharedLibrariesSize){
817         //dyninst_SharedLibraries
818         //the SharedLibraries sections contains a list of all the shared libraries
819         //that have been loaded and the base address for each one.
820         //The format of the sections is:
821         //
822         //sharedlibraryName
823         //baseAddr
824         //...
825         //sharedlibraryName
826         //baseAddr
827         //'\0'
828         
829         char *dyninst_SharedLibrariesData = new char[dyninst_SharedLibrariesSize];
830         char *ptr= dyninst_SharedLibrariesData;
831         //int size = mapped_objects->size() - 1; // a.out is included as well
832         mapped_object *sh_obj;
833
834         for(unsigned i=1; i < mapped_objects.size(); i++) {
835           sh_obj = mapped_objects[i];
836
837                 memcpy((void*) ptr, sh_obj->fileName().c_str(), strlen(sh_obj->fileName().c_str())+1);
838                 //fprintf(stderr,"loaded shared libs %s : ", ptr);
839                 ptr += strlen(sh_obj->fileName().c_str())+1;
840
841                 unsigned int baseAddr = sh_obj->getBaseAddress();
842                 /*      LINUX PROBLEM. in the link_map structure the map->l_addr field is NOT
843                         the load address of the dynamic object, as the documentation says.  It is the
844                         RELOCATED address of the object. If the object was not relocated then the
845                         value is ZERO.
846
847                         So, on LINUX we check the address of the dynamic section, map->l_ld, which is
848                         correct.
849                 */
850 #if defined(i386_unknown_linux2_0) || defined(x86_64_unknown_linux2_4)
851                 Symbol info;
852                 pdstring dynamicSection = "_DYNAMIC";
853                 sh_obj->getSymbolInfo(dynamicSection,info);
854                 baseAddr = sh_obj->getBaseAddress() + info.addr();
855                 //fprintf(stderr," %s DYNAMIC ADDR: %x\n",sh_obj->fileName().c_str(), baseAddr);
856 #endif
857
858                 memcpy( (void*)ptr, &baseAddr, sizeof(unsigned int));
859                 //fprintf(stderr," 0x%x \n", *(unsigned int*) ptr);
860                 ptr += sizeof(unsigned int);
861         }
862         memset( (void*)ptr, '\0' , 1);
863
864         return dyninst_SharedLibrariesData;
865 }
866 #endif
867
868 #if defined(sparc_sun_solaris2_4) \
869  || defined(i386_unknown_linux2_0) \
870  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */ \
871  || defined(rs6000_ibm_aix4_1)
872 void process::saveWorldCreateHighMemSections(
873                         pdvector<imageUpdate*> &compactedHighmemUpdates, 
874                         pdvector<imageUpdate*> &highmem_updates,
875                         void *ptr) {
876
877    Address guardFlagAddr= trampGuardBase();
878
879    unsigned int pageSize = getpagesize();
880    unsigned int startPage, stopPage;
881    unsigned int numberUpdates=1;
882    int startIndex, stopIndex;
883    char *data;
884    char name[50];
885 #if defined(sparc_sun_solaris2_4) \
886  || defined(i386_unknown_linux2_0) \
887  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
888         writeBackElf *newFile = (writeBackElf*) ptr;
889 #elif defined(rs6000_ibm_aix4_1)
890         writeBackXCOFF *newFile = (writeBackXCOFF*) ptr;
891
892 #endif
893
894 #if 0
895    unsigned int trampGuardValue;
896         bool err ;
897 //#if !defined(rs6000_ibm_aix4_1)
898
899         /*fprintf(stderr,"guardFlagAddr %x\n",guardFlagAddr);*/
900 //      readDataSpace((void*) guardFlagAddr, sizeof(unsigned int),
901 //                (void*) &trampGuardValue, true);
902    
903
904         for(int i=0;i< max_number_of_threads;i++){
905                 err = writeDataSpace((void*) &( ((int *)guardFlagAddr)[i]), sizeof(unsigned int),
906                   (void*) &numberUpdates);
907                 if (!err) fprintf(stderr, "%s[%d][%s]:  writeDataSpace failed\n", __FILE__, __LINE__, getThreadStr(getExecThreadID()));
908                         assert(err);
909
910                 saveWorldData( (Address) &( ((int *)guardFlagAddr)[i]),sizeof(unsigned int), &numberUpdates); //ccw 7 jul 2003
911         }
912 #endif
913
914       sprintf(name,"dyninstAPItrampguard");
915
916         data = new char[sizeof(max_number_of_threads)*max_number_of_threads];
917         memcpy(data, &max_number_of_threads,sizeof(max_number_of_threads));
918         //fprintf(stderr,"WRITING: max_number_of_threads %d\n",max_number_of_threads);
919         //ccw 14 dec 2005
920 #if defined(sparc_sun_solaris2_4) \
921  || defined(i386_unknown_linux2_0) \
922  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
923       newFile->addSection(guardFlagAddr,data,sizeof(max_number_of_threads),name,false);
924 #elif defined(rs6000_ibm_aix4_1)
925         sprintf(name,"trampg");
926         //fprintf(stderr," trampg 0x%x\n",guardFlagAddr);
927         newFile->addSection(name,guardFlagAddr,guardFlagAddr,sizeof(unsigned int) *max_number_of_threads,data);
928         //newFile->setDataEnd(guardFlagAddr+sizeof(unsigned int) *max_number_of_threads);
929 #endif
930         delete []data;
931
932                 
933 #if  defined(i386_unknown_linux2_0) \
934  || defined(x86_64_unknown_linux2_4) \
935  || defined(sparc_sun_solaris2_4)
936
937 #if defined(sparc_sun_solaris2_4)
938         if( imageUpdates.size() == 0 ){
939 #endif
940         //fprintf(stderr,"LOADING trampgu 0x%x\n",guardFlagAddr);
941         data = new char[sizeof(unsigned int) * max_number_of_threads];
942         memset(data,1,sizeof(unsigned int) * max_number_of_threads);            
943         newFile->addSection(guardFlagAddr,data,sizeof(unsigned int) * max_number_of_threads,"dyninstAPI_1",false);
944         delete []data;
945 #if defined(sparc_sun_solaris2_4)
946         }
947 #endif
948 #endif
949
950    for(unsigned int j=0; j<compactedHighmemUpdates.size(); j++) {
951       //the layout of dyninstAPIhighmem_%08x is:
952       //pageData
953       //address of update
954       //size of update
955       // ...
956       //address of update
957       //size of update
958       //number of updates
959
960       startPage = compactedHighmemUpdates[j]->address - 
961                   compactedHighmemUpdates[j]->address % pageSize;
962       stopPage = compactedHighmemUpdates[j]->address + 
963                  compactedHighmemUpdates[j]->size -
964                  (compactedHighmemUpdates[j]->address + 
965                   compactedHighmemUpdates[j]->size) % pageSize;
966
967       numberUpdates = 0;
968       startIndex = -1;
969       stopIndex = -1;
970       
971       for(unsigned index = 0;index < highmem_updates.size(); index++){
972          //here we ignore anything with an address of zero.
973          //these can be safely deleted in writeBackElf
974          if( highmem_updates[index]->address && 
975              startPage <= highmem_updates[index]->address &&
976              highmem_updates[index]->address  < (startPage + pageSize /*compactedHighmemUpdates[j]->sizei*/)){
977             numberUpdates ++;
978             stopIndex = index;
979             if(startIndex == -1){
980                startIndex = index;
981             }
982            //bperr(" HighMemUpdates address 0x%x \n", highmem_updates[index]->address );
983          }
984         //bperr(" high mem updates: 0x%x", highmem_updates[index]->address);
985       }
986       unsigned int dataSize = compactedHighmemUpdates[j]->size + 
987          sizeof(unsigned int) + 
988          (2*(stopIndex - startIndex + 1) /*numberUpdates*/ * sizeof(unsigned int));
989
990         //bperr("DATASIZE: %x : %x + 4 + ( 2*(%x - %x +1) * 4)\n", dataSize, compactedHighmemUpdates[j]->size, stopIndex, startIndex);
991       
992       data = new char[dataSize];
993       
994       //fill in pageData
995       readDataSpace((void*) compactedHighmemUpdates[j]->address, 
996                     compactedHighmemUpdates[j]->size, data, true);
997       
998       unsigned int *dataPtr = 
999          (unsigned int*) ( (char*) data + compactedHighmemUpdates[j]->size);
1000
1001       //fill in address of update
1002       //fill in size of update
1003       for(int index = startIndex; index<=stopIndex;index++){ 
1004
1005          memcpy(dataPtr, &highmem_updates[index]->address,
1006                 sizeof(unsigned int));
1007          dataPtr ++;
1008          memcpy(dataPtr, &highmem_updates[index]->size, sizeof(unsigned int));
1009
1010          dataPtr++;
1011          //bperr("%d J %d ADDRESS: 0x%x SIZE 0x%x\n",index, j,
1012          //highmem_updates[index]->address, highmem_updates[index]->size);
1013
1014         
1015       }
1016       //fill in number of updates
1017       memcpy(dataPtr, &numberUpdates, sizeof(unsigned int));
1018
1019       //bperr(" NUMBER OF UPDATES 0x%x  %d %x\n\n",numberUpdates,dataSize,dataSize);
1020       sprintf(name,"dyninstAPIhighmem_%08x",j);
1021 #if defined(sparc_sun_solaris2_4) \
1022  || defined(i386_unknown_linux2_0) \
1023  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
1024       newFile->addSection(compactedHighmemUpdates[j]->address,data ,dataSize,name,false);
1025 #elif defined(rs6000_ibm_aix4_1)
1026           sprintf(name, "dyH_%03x",j);
1027       newFile->addSection(&(name[0]), compactedHighmemUpdates[j]->address,compactedHighmemUpdates[j]->address,
1028                 dataSize, (char*) data );
1029
1030 #endif
1031       
1032       //lastCompactedUpdateAddress = compactedHighmemUpdates[j]->address+1;
1033       delete [] (char*) data;
1034    }
1035 #if 0
1036    err = writeDataSpace((void*)guardFlagAddr, sizeof(unsigned int), 
1037                   (void*)&trampGuardValue);
1038    if (!err) fprintf(stderr, "%s[%d][%s]:  writeDataSpace failed\n", __FILE__, __LINE__, getThreadStr(getExecThreadID()));
1039         assert(err);
1040 #endif 
1041 }
1042
1043 void process::saveWorldCreateDataSections(void* ptr){
1044
1045 #if defined(sparc_sun_solaris2_4) \
1046  || defined(i386_unknown_linux2_0) \
1047  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
1048         writeBackElf *newFile = (writeBackElf*) ptr;
1049 #elif defined(rs6000_ibm_aix4_1)
1050         writeBackXCOFF *newFile = (writeBackXCOFF*) ptr;
1051 #endif
1052
1053         char *dataUpdatesData;
1054         int sizeofDataUpdatesData=0;
1055         for(unsigned int m=0;m<dataUpdates.size();m++){
1056                 sizeofDataUpdatesData += (sizeof(int) + sizeof(Address)); //sizeof(size) +sizeof(Address);
1057                 sizeofDataUpdatesData += dataUpdates[m]->size;
1058         }
1059
1060
1061         if(dataUpdates.size() > 0) {
1062                 dataUpdatesData = new char[sizeofDataUpdatesData+(sizeof(int) + sizeof(Address))];
1063                 char* ptr = dataUpdatesData;
1064                 for(unsigned int k=0;k<dataUpdates.size();k++){
1065                         memcpy(ptr, &dataUpdates[k]->size, sizeof(int));
1066                         ptr += sizeof(int);
1067                         memcpy(ptr, &dataUpdates[k]->address, sizeof(Address));
1068                         ptr+=sizeof(Address);
1069                         memcpy(ptr, dataUpdates[k]->value, dataUpdates[k]->size);
1070                         ptr+=dataUpdates[k]->size;
1071                         /*fprintf(stderr," DATA UPDATE : from: %x to %x , value %x\n", dataUpdates[k]->address, dataUpdates[k]->address+ dataUpdates[k]->size, (unsigned int) dataUpdates[k]->value);*/
1072
1073                 }
1074                 *(int*) ptr=0;
1075                 ptr += sizeof(int);
1076                 *(unsigned int*) ptr=0;
1077 #if defined(sparc_sun_solaris2_4) \
1078  || defined(i386_unknown_linux2_0) \
1079  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
1080                 newFile->addSection(0/*lastCompactedUpdateAddress*/, dataUpdatesData, 
1081                         sizeofDataUpdatesData + (sizeof(int) + sizeof(Address)), "dyninstAPI_data", false);
1082 #elif defined(rs6000_ibm_aix4_1)
1083                 newFile->addSection("dyn_dat", 0/*lastCompactedUpdateAddress*/,0,
1084                         sizeofDataUpdatesData + (sizeof(int) + sizeof(Address)), (char*) dataUpdatesData);
1085
1086 #endif
1087
1088                 delete [] (char*) dataUpdatesData;
1089         }
1090
1091 }
1092 #endif
1093
1094 #if defined(sparc_sun_solaris2_4) \
1095  || defined(i386_unknown_linux2_0) \
1096  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */ \
1097  || defined(rs6000_ibm_aix4_1)
1098
1099 void process::saveWorldAddSharedLibs(void *ptr){ // ccw 14 may 2002 
1100
1101         int dataSize=0;
1102         char *data, *dataptr;
1103 #if defined(sparc_sun_solaris2_4) \
1104  || defined(i386_unknown_linux2_0) \
1105  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
1106         writeBackElf *newFile = (writeBackElf*) ptr;
1107 #elif defined(rs6000_ibm_aix4_1)
1108         writeBackXCOFF *newFile = (writeBackXCOFF*) ptr;
1109 #endif
1110
1111         for(unsigned i=0;i<loadLibraryUpdates.size();i++){
1112                 dataSize += loadLibraryUpdates[i].length() + 1 + sizeof(void *);
1113         }
1114         dataSize++;
1115         data = new char[dataSize];
1116         dataptr = data;
1117         /*bperr(" dataSize: %d\n", dataSize);*/
1118
1119         for(unsigned j=0;j<loadLibraryUpdates.size();j++){
1120                 memcpy( dataptr, loadLibraryUpdates[j].c_str(), loadLibraryUpdates[j].length()); 
1121
1122                 /*bperr("SAVING: %s %d\n", dataptr,dataSize);*/
1123                 dataptr += loadLibraryUpdates[j].length();
1124                 *dataptr = '\0';
1125                 dataptr++;
1126                 void *tmp_brk = loadLibraryBRKs[j];
1127                 memcpy( dataptr, &tmp_brk, sizeof(void *));
1128                 dataptr += sizeof(void *);
1129         }
1130         *dataptr = '\0'; //mark the end
1131         if(dataSize > 1){
1132 #if defined(sparc_sun_solaris2_4) \
1133  || defined(i386_unknown_linux2_0) \
1134  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
1135                 newFile->addSection(0, data, dataSize, "dyninstAPI_loadLib", false);
1136 #elif  defined(rs6000_ibm_aix4_1)
1137                 newFile->addSection("dyn_lib",0,0, dataSize, data);
1138 #endif
1139         }
1140         delete [] data;
1141 }
1142
1143 #endif
1144
1145
1146 /*
1147  * Given an image, add all static heaps inside it
1148  * (DYNINSTstaticHeap...) to the buffer pool.
1149  */
1150
1151 void process::addInferiorHeap(const mapped_object *obj)
1152 {
1153   pdvector<heapDescriptor> infHeaps;
1154   /* Get a list of inferior heaps in the new image */
1155   if (getInfHeapList(obj, infHeaps))
1156     {
1157       /* Add the vector to the inferior heap structure */
1158         for (u_int j=0; j < infHeaps.size(); j++)
1159         {
1160 #ifdef DEBUG
1161             fprintf(stderr, "Adding heap at 0x%x to 0x%x, name %s\n",
1162                     infHeaps[j].addr(),
1163                     infHeaps[j].addr() + infHeaps[j].size(),
1164                     infHeaps[j].name().c_str());
1165 #endif
1166 #if defined(arch_power)
1167             // MT: I've seen problems writing into a "found" heap that
1168             // is in the application heap (IE a dlopen'ed
1169             // library). Since we don't have any problems getting
1170             // memory there, I'm skipping any heap that is in 0x2.....
1171             
1172             if ((infHeaps[j].addr() > 0x20000000) &&
1173                 (infHeaps[j].addr() < 0xd0000000) &&
1174                 (infHeaps[j].type() == uncopiedHeap))
1175                 continue;
1176 #endif            
1177
1178             heapItem *h = new heapItem (infHeaps[j].addr(), infHeaps[j].size(),
1179                                         infHeaps[j].type(), false);
1180             heap.bufferPool.push_back(h);
1181             heapItem *h2 = new heapItem(h);
1182             h2->status = HEAPfree;
1183             heap.heapFree.push_back(h2);
1184             heap.totalFreeMemAvailable += h2->length;
1185         }
1186     }
1187   
1188 }
1189
1190
1191 /*
1192  * Called to (re)initialize the static inferior heap structure.
1193  * To incrementally add a static inferior heap (in a dlopen()d module,
1194  * for example), use addInferiorHeap(image *)
1195  */
1196 void process::initInferiorHeap()
1197 {
1198   // (re)initialize everything 
1199     heap.heapActive.clear();
1200     heap.heapFree.resize(0);
1201     heap.disabledList.resize(0);
1202     heap.disabledListTotalMem = 0;
1203     heap.freed = 0;
1204     heap.totalFreeMemAvailable = 0;
1205
1206     // first initialization: add static heaps to pool
1207     for (unsigned i = 0; i < mapped_objects.size(); i++) {
1208         addInferiorHeap(mapped_objects[i]);
1209     }
1210
1211     heapInitialized_ = true;
1212 }
1213
1214 bool process::initTrampGuard()
1215 {
1216   // This is slightly funky. Dyninst does not currently support
1217   // multiple threads -- so it uses a single tramp guard flag, 
1218   // which resides in the runtime library. However, this is not
1219   // enough for MT paradyn. So Paradyn overrides this setting as 
1220   // part of its initialization.
1221     const pdstring vrbleName = "DYNINST_tramp_guards";
1222     pdvector<int_variable *> vars;
1223     if (!findVarsByAll(vrbleName, vars)) 
1224     {
1225         return false;
1226     }
1227     assert(vars.size() == 1);
1228
1229     readDataSpace((void *) vars[0]->getAddress(), sizeof(Address), &trampGuardBase_, 
1230                   true);
1231     return true;
1232 }
1233
1234 // create a new inferior heap that is a copy of src. This is used when a process
1235 // we are tracing forks.
1236 inferiorHeap::inferiorHeap(const inferiorHeap &src):
1237     heapActive(addrHash16)
1238 {
1239     for (unsigned u1 = 0; u1 < src.heapFree.size(); u1++) {
1240       heapFree.push_back(new heapItem(src.heapFree[u1]));
1241     }
1242
1243     pdvector<heapItem *> items = src.heapActive.values();
1244     for (unsigned u2 = 0; u2 < items.size(); u2++) {
1245       heapActive[items[u2]->addr] = new heapItem(items[u2]);
1246     }
1247     
1248     for (unsigned u3 = 0; u3 < src.disabledList.size(); u3++) {
1249       disabledList.push_back(src.disabledList[u3]);
1250     }
1251
1252     for (unsigned u4 = 0; u4 < src.bufferPool.size(); u4++) {
1253       bufferPool.push_back(new heapItem(src.bufferPool[u4]));
1254     }
1255
1256     disabledListTotalMem = src.disabledListTotalMem;
1257     totalFreeMemAvailable = src.totalFreeMemAvailable;
1258     freed = 0;
1259 }
1260
1261 //
1262 // This function will return the index corresponding to the next position
1263 // available in heapFree.
1264 //
1265 int process::findFreeIndex(unsigned size, int type, Address lo, Address hi)
1266 {
1267     // type is a bitmask: match on any bit in the mask
1268   pdvector<heapItem *> &freeList = heap.heapFree;
1269
1270   int best = -1;
1271   for (unsigned i = 0; i < freeList.size(); i++) {
1272       heapItem *h = freeList[i];
1273       // check if free block matches allocation constraints
1274       // Split out to facilitate debugging
1275       if (h->addr >= lo &&
1276           (h->addr + size - 1) <= hi &&
1277           h->length >= size &&
1278           h->type & type) {
1279           if (best == -1)
1280               best = i;
1281           // check for better match
1282           if (h->length < freeList[best]->length) best = i;
1283       }
1284   }
1285   return best;
1286 }  
1287
1288 //
1289 // dynamic inferior heap stuff
1290 //
1291 #if defined(USES_DYNAMIC_INF_HEAP)
1292 #define HEAP_DYN_BUF_SIZE (0x100000)
1293 // "imd_rpc_ret" = Inferior Malloc Dynamic RPC RETurn structure
1294 typedef struct {
1295   bool ready;
1296   void *result;
1297 } imd_rpc_ret;
1298
1299 bool inferiorMallocCallbackFlag = false;
1300 void process::inferiorMallocCallback(process * /*p proc*/, unsigned /* rpc_id */,
1301                                      void *data, void *result)
1302 {
1303   global_mutex->_Lock(__FILE__, __LINE__);
1304   inferiorrpc_printf("%s[%d]:  inside inferior malloc callback\n", __FILE__, __LINE__);
1305   imd_rpc_ret *ret = (imd_rpc_ret *)data;
1306   ret->result = result;
1307   ret->ready = true;
1308   inferiorMallocCallbackFlag = true;
1309   global_mutex->_Unlock(__FILE__, __LINE__);
1310 }
1311
1312 void alignUp(int &val, int align)
1313 {
1314   assert(val >= 0);
1315   assert(align >= 0);
1316
1317   if (val % align != 0) {
1318     val = ((val / align) + 1) * align;
1319   }
1320 }
1321
1322 // dynamically allocate a new inferior heap segment using inferiorRPC
1323 void process::inferiorMallocDynamic(int size, Address lo, Address hi)
1324 {
1325    /* 03/07/2001 - Jeffrey Shergalis TODO: This code was placed to prevent
1326     * the infinite recursion on the call to inferiorMallocDynamic,
1327     * unfortunately it makes paradyn break on Irix, temporarily fixed by the
1328     * #if !defined(mips..., but should be properly fixed in the future, just
1329     * no time now
1330     */
1331    inferiorrpc_printf("%s[%d]:  welcome to inferiorMallocDynamic\n", __FILE__, __LINE__);
1332 #if !defined(mips_sgi_irix6_4)
1333   // Fun (not) case: there's no space for the RPC to execute.
1334   // It'll call inferiorMalloc, which will call inferiorMallocDynamic...
1335   // Avoid this with a static bool.
1336   if (inInferiorMallocDynamic) {
1337       fprintf(stderr, "%s[%d]:  recursion guard\n", __FILE__, __LINE__);
1338       return;
1339   }
1340   inInferiorMallocDynamic = true;
1341 #endif
1342
1343   // word-align buffer size 
1344   // (see "DYNINSTheap_align" in rtinst/src/RTheap-<os>.c)
1345   alignUp(size, 4);
1346   // build AstNode for "DYNINSTos_malloc" call
1347   pdstring callee = "DYNINSTos_malloc";
1348   pdvector<AstNode*> args(3);
1349   args[0] = new AstNode(AstNode::Constant, (void *)(Address)size);
1350   args[1] = new AstNode(AstNode::Constant, (void *)lo);
1351   args[2] = new AstNode(AstNode::Constant, (void *)hi);
1352   AstNode *code = new AstNode(callee, args);
1353   removeAst(args[0]);
1354   removeAst(args[1]);
1355   removeAst(args[2]);
1356
1357   // issue RPC and wait for result
1358   imd_rpc_ret ret = { false, NULL };
1359
1360  
1361   /* set lowmem to ensure there is space for inferior malloc */
1362   getRpcMgr()->postRPCtoDo(code, true, // noCost
1363                            &inferiorMallocCallback, &ret, 
1364                            true, // But use reserved memory
1365                            NULL, NULL); // process-wide
1366   bool wasRunning = (status() == running);
1367
1368   // Specify that we want to wait for a RPCDone event
1369   eventType res = evtUndefined;
1370
1371   inferiorMallocCallbackFlag = false;
1372      inferiorrpc_printf("%s[%d]:  waiting for rpc completion\n", FILE__, __LINE__);
1373   do {
1374      getRpcMgr()->launchRPCs(wasRunning);
1375      getMailbox()->executeCallbacks(FILE__, __LINE__);
1376
1377      if(hasExited()) {
1378         fprintf(stderr, "%s[%d]:  BAD NEWS, process has exited\n", __FILE__, __LINE__);
1379         return;
1380      }
1381     if (inferiorMallocCallbackFlag) {
1382        break;
1383      }
1384
1385      inferiorrpc_printf("%s[%d][%s]:  before wait for RPCDone, status == running is %s\n", 
1386                         FILE__, __LINE__, getThreadStr(getExecThreadID()), 
1387                         status() == running ? "true" : "false");
1388
1389      res = sh->waitForEvent(evtRPCSignal, this, NULL /*lwp*/, statusRPCDone);
1390      getMailbox()->executeCallbacks(FILE__, __LINE__);
1391    } while (res != evtRPCSignal); // Loop until callback has fired.
1392
1393   inferiorMallocCallbackFlag = false;
1394
1395    switch ((int)(Address)ret.result) {
1396      case 0:
1397 #ifdef DEBUG
1398         sprintf(errorLine, "DYNINSTos_malloc() failed\n");
1399         logLine(errorLine);
1400 #endif
1401         break;
1402      case -1:
1403         // TODO: assert?
1404         sprintf(errorLine, "DYNINSTos_malloc(): unaligned buffer size\n");
1405         logLine(errorLine);
1406         break;
1407      default:
1408         // add new segment to buffer pool
1409          // FIXME
1410 #if defined(os_aix)
1411          // for save the world...
1412         heapItem *h = new heapItem((Address)ret.result, size, dataHeap, true,
1413                                    HEAPfree);
1414 #else
1415         heapItem *h = new heapItem((Address)ret.result, size, anyHeap, true,
1416                                    HEAPfree);
1417 #endif
1418
1419
1420         heap.bufferPool.push_back(h);
1421         // add new segment to free list
1422         heapItem *h2 = new heapItem(h);
1423         heap.heapFree.push_back(h2);
1424         break;
1425    }
1426    
1427    /* 03/07/2001 - Jeffrey Shergalis
1428     * Part of the above #if !defined(mips... patch for the recursion problem
1429     * TODO: Need a better solution
1430     */
1431 #if !defined(mips_sgi_irix6_4)
1432    inInferiorMallocDynamic = false;
1433 #endif
1434 }
1435 #endif /* USES_DYNAMIC_INF_HEAP */
1436
1437 const Address ADDRESS_LO = ((Address)0);
1438 const Address ADDRESS_HI = ((Address)~((Address)0));
1439 //unsigned int totalSizeAlloc = 0;
1440
1441 Address process::inferiorMalloc(unsigned size, inferiorHeapType type, 
1442                                 Address near_, bool *err)
1443 {
1444    inferiorHeap *hp = &heap;
1445    if (err) *err = false;
1446    assert(size > 0);
1447    
1448    // allocation range
1449    Address lo = ADDRESS_LO; // Should get reset to a more reasonable value
1450    Address hi = ADDRESS_HI; // Should get reset to a more reasonable value
1451    
1452 #if defined(USES_DYNAMIC_INF_HEAP)
1453    inferiorMallocAlign(size); // align size
1454    // Set the lo/hi constraints (if necessary)
1455    inferiorMallocConstraints(near_, lo, hi, type);
1456 #else
1457    /* align to cache line size (32 bytes on SPARC) */
1458    size = (size + 0x1f) & ~0x1f; 
1459 #endif /* USES_DYNAMIC_INF_HEAP */
1460
1461
1462    // find free memory block (7 attempts)
1463    // attempt 0: as is
1464    // attempt 1: deferred free, compact free blocks
1465    // attempt 2: allocate new segment (1 MB, constrained)
1466    // attempt 3: allocate new segment (sized, constrained)
1467    // attempt 4: remove range constraints
1468    // attempt 5: allocate new segment (1 MB, unconstrained)
1469    // attempt 6: allocate new segment (sized, unconstrained)
1470    // attempt 7: deferred free, compact free blocks (why again?)
1471    int freeIndex = -1;
1472    int ntry = 0;
1473    for (ntry = 0; freeIndex == -1; ntry++) {
1474       switch(ntry) {
1475         case 0: // as is
1476            break;
1477 #if defined(USES_DYNAMIC_INF_HEAP)
1478         case 1: // compact free blocks
1479           gcInstrumentation();
1480           inferiorFreeCompact(hp);
1481           break;
1482         case 2: // allocate new segment (1MB, constrained)
1483         inferiorMallocDynamic(HEAP_DYN_BUF_SIZE, lo, hi);
1484            break;
1485         case 3: // allocate new segment (sized, constrained)
1486            inferiorMallocDynamic(size, lo, hi);
1487            break;
1488         case 4: // remove range constraints
1489            lo = ADDRESS_LO;
1490            hi = ADDRESS_HI;
1491            if (err) {
1492               fprintf(stderr, "%s[%d]: ERROR!\n", __FILE__, __LINE__);
1493               *err = true;
1494            }
1495            break;
1496         case 5: // allocate new segment (1MB, unconstrained)
1497            inferiorMallocDynamic(HEAP_DYN_BUF_SIZE, lo, hi);
1498            break;
1499         case 6: // allocate new segment (sized, unconstrained)
1500            inferiorMallocDynamic(size, lo, hi);
1501            break;
1502         case 7: // deferred free, compact free blocks
1503            inferiorFreeCompact(hp);
1504            break;
1505 #else /* !(USES_DYNAMIC_INF_HEAP) */
1506         case 1: // deferred free, compact free blocks
1507            inferiorFreeCompact(hp);
1508            break;
1509 #endif /* USES_DYNAMIC_INF_HEAP */
1510            
1511         default: // error - out of memory
1512            sprintf(errorLine, "***** Inferior heap overflow: %d bytes "
1513                    "freed, %d bytes requested \n", hp->freed, size);
1514            logLine(errorLine);
1515            showErrorCallback(66, (const char *) errorLine);    
1516               fprintf(stderr,"%s[%d]: ERROR!\n", __FILE__, __LINE__);
1517         fprintf(stderr, "%s\n", errorLine);
1518 #if defined(BPATCH_LIBRARY)
1519            return(0);
1520 #else
1521            P__exit(-1);
1522 #endif
1523       }
1524       freeIndex = findFreeIndex(size, type, lo, hi);
1525 //      bperr("  type %x",type);
1526    }
1527
1528    // adjust active and free lists
1529    assert(freeIndex != -1);
1530    heapItem *h = hp->heapFree[freeIndex];
1531    assert(h);
1532
1533    // remove allocated buffer from free list
1534    if (h->length != size) {
1535       // size mismatch: put remainder of block on free list
1536       heapItem *rem = new heapItem(h);
1537       rem->addr += size;
1538       rem->length -= size;
1539       hp->heapFree[freeIndex] = rem;
1540    } else {
1541       // size match: remove entire block from free list
1542       unsigned last = hp->heapFree.size();
1543       hp->heapFree[freeIndex] = hp->heapFree[last-1];
1544       hp->heapFree.resize(last-1);
1545    }
1546    // add allocated block to active list
1547    h->length = size;
1548    h->status = HEAPallocated;
1549    hp->heapActive[h->addr] = h;
1550    // bookkeeping
1551    hp->totalFreeMemAvailable -= size;
1552    assert(h->addr);
1553    
1554    // ccw: 28 oct 2001
1555    // create imageUpdate here:
1556    // imageUpdate(h->addr,size)
1557    
1558 #ifdef BPATCH_LIBRARY
1559 //      if( h->addr > 0xd0000000){
1560 //              bperr(" \n ALLOCATION: %lx %lx ntry: %d\n", h->addr, size,ntry);
1561 //              fflush(stdout);
1562 //      }
1563 #if defined(sparc_sun_solaris2_4) \
1564  || defined(i386_unknown_linux2_0) \
1565  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */ \
1566  || defined(rs6000_ibm_aix4_1)
1567    if(collectSaveWorldData){
1568       
1569 #if defined(sparc_sun_solaris2_4)
1570       if(h->addr < 0xF0000000)
1571 #elif defined(i386_unknown_linux2_0) \
1572    || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
1573       if(h->addr == 0 ) //< 0x40000000) //ccw TEST TEST TEST
1574 #elif defined(rs6000_ibm_aix4_1)
1575         if(h->addr < 0x20000000)
1576 #endif  
1577       {
1578          imageUpdate *imagePatch=new imageUpdate; 
1579          imagePatch->address = h->addr;
1580          imagePatch->size = size;
1581          imageUpdates.push_back(imagePatch);
1582          //totalSizeAlloc += size;
1583          //bperr(" PUSHBACK %x %x --- \n", imagePatch->address, imagePatch->size);              
1584          //fprintf(stderr," PUSHBACK %x %x --- \n", imagePatch->address, imagePatch->size);             
1585       } else {
1586          //     totalSizeAlloc += size;
1587          //fprintf(stderr,"HIGHMEM UPDATE %x %x \n", h->addr, size);
1588          imageUpdate *imagePatch=new imageUpdate;
1589          imagePatch->address = h->addr;
1590          imagePatch->size = size;
1591          highmemUpdates.push_back(imagePatch);
1592          //bperr(" PUSHBACK %x %x\n", imagePatch->address, imagePatch->size);
1593       }
1594       //fflush(stdout);
1595    }
1596 #endif
1597 #endif
1598    return(h->addr);
1599 }
1600
1601 /* returns true if memory was allocated for a variable starting at address
1602    "block", otherwise returns false
1603 */
1604 bool isInferiorAllocated(process *p, Address block) {
1605   heapItem *h = NULL;  
1606   inferiorHeap *hp = &p->heap;
1607   return hp->heapActive.find(block, h);
1608 }
1609
1610 void process::inferiorFree(Address block)
1611 {
1612   inferiorHeap *hp = &heap;
1613
1614   // find block on active list
1615   heapItem *h = NULL;  
1616   if (!hp->heapActive.find(block, h)) {
1617       // We can do this if we're at process teardown.
1618     return;
1619   }
1620   assert(h);
1621
1622   // Remove from the active list
1623   hp->heapActive.undef(block);
1624
1625   // Add to the free list
1626   h->status = HEAPfree;
1627   hp->heapFree.push_back(h);
1628   hp->totalFreeMemAvailable += h->length;
1629   hp->freed += h->length;
1630 }
1631  
1632 bool process::inferiorRealloc(Address block, unsigned newSize)
1633 {
1634   inferiorHeap *hp = &heap;
1635
1636 #if defined (USES_DYNAMIC_INF_HEAP)
1637   // This is why it's not a reference...
1638   inferiorMallocAlign(newSize);
1639 #endif
1640
1641   // find block on active list
1642   heapItem *h = NULL;  
1643   if (!hp->heapActive.find(block, h)) {
1644       // We can do this if we're at process teardown.
1645     return false;
1646   }
1647   assert(h);
1648
1649   if (h->length < newSize)
1650       return false; // Cannot make bigger...
1651   if (h->length == newSize)
1652       return true;
1653
1654   // We make a new "free" block that is the end of this one.
1655   Address freeStart = block + newSize;
1656   int shrink = h->length - newSize;
1657   
1658   assert(shrink > 0);
1659
1660   h->length = newSize;
1661
1662   heapItem *freeEnd = new heapItem(freeStart,
1663                                    shrink,
1664                                    h->type,
1665                                    h->dynamic,
1666                                    HEAPfree);
1667   hp->heapFree.push_back(freeEnd);
1668
1669   hp->totalFreeMemAvailable += shrink;
1670   hp->freed += shrink;
1671
1672   // And run a compact; otherwise we'll end up with hugely fragmented memory.
1673   inferiorFreeCompact(hp);
1674
1675
1676    // ccw: 28 oct 2001
1677    // create imageUpdate here:
1678    // imageUpdate(h->addr,size)
1679    
1680 #ifdef BPATCH_LIBRARY
1681 //      if( h->addr > 0xd0000000){
1682 //              bperr(" \n ALLOCATION: %lx %lx ntry: %d\n", h->addr, size,ntry);
1683 //              fflush(stdout);
1684 //      }
1685 #if defined(sparc_sun_solaris2_4) \
1686  || defined(i386_unknown_linux2_0) \
1687  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */ \
1688  || defined(rs6000_ibm_aix4_1)
1689    if(collectSaveWorldData){
1690       
1691 #if defined(sparc_sun_solaris2_4)
1692       if(h->addr < 0xF0000000)
1693 #elif defined(i386_unknown_linux2_0) \
1694    || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
1695       if(h->addr == 0 ) //< 0x40000000) //ccw TEST TEST TEST
1696 #elif defined(rs6000_ibm_aix4_1)
1697         if(h->addr < 0x20000000)
1698 #endif  
1699       {
1700
1701                 //fprintf(stderr,"INFERIOR REALLOC2\n");
1702                 imageUpdate *imagePatch=new imageUpdate; 
1703                  imagePatch->address = h->addr;
1704                  imagePatch->size = newSize;
1705                  imageUpdates.push_back(imagePatch);
1706       } else {
1707                 //fprintf(stderr,"INFERIOR REALLOC\n");
1708                  imageUpdate *imagePatch=new imageUpdate;
1709                  imagePatch->address = h->addr;
1710                  imagePatch->size = newSize;
1711                  highmemUpdates.push_back(imagePatch);
1712       }
1713    }
1714 #endif
1715 #endif
1716
1717
1718   return true;
1719 }
1720
1721
1722 // Cleanup the process object. Delete all sub-objects to ensure we aren't 
1723 // leaking memory and prepare for new versions. Useful when the process exits
1724 // (and the process object is deleted) and when it execs
1725
1726 void process::deleteProcess() 
1727 {
1728 #if 0
1729   fprintf(stderr, "%s[%d]:  welcome to delete process\n", FILE__, __LINE__);
1730 #endif
1731   // A lot of the behavior here is keyed off the current process status....
1732   // if it is exited we'll delete things without performing any operations
1733   // on the process. Otherwise we'll attempt to reverse behavior we've made.
1734     // For platforms that don't like repeated use of for (unsigned i...)
1735     unsigned iter = 0;
1736
1737   // We may call this function multiple times... once when the process exits,
1738   // once when we delete the process object.
1739   if (status() == deleted) return;
1740     
1741   // If this assert fires check whether we're setting the status vrble correctly
1742   // before calling this function
1743   assert(!isAttached() || !reachedBootstrapState(bootstrapped_bs) || execing());
1744
1745   // pid remains untouched
1746   // parent remains untouched
1747   for (iter = 0; iter < mapped_objects.size(); iter++) 
1748       delete mapped_objects[iter];
1749   mapped_objects.clear();
1750   runtime_lib = NULL;
1751
1752   // Signal handlers...
1753   signalHandlerLocations_.clear();
1754
1755   // creationMechanism_ remains untouched
1756   // stateWhenAttached_ remains untouched
1757   main_function = NULL;
1758
1759   if (dyn) {
1760       delete dyn;
1761       dyn = NULL;
1762   }
1763
1764   // Delete the thread and lwp structures
1765   dictionary_hash_iter<unsigned, dyn_lwp *> lwp_iter(real_lwps);
1766   dyn_lwp *lwp;
1767   unsigned index;
1768   
1769   // This differs on exec; we need to kill all but the representative LWP
1770   // Duplicate code for ease of reading
1771
1772   if (execing()) {
1773       while (lwp_iter.next(index, lwp)) {
1774           if (process::IndependentLwpControl() &&
1775               (index == (unsigned)getPid())) {
1776               // Keep this around instead of nuking it -- this is our
1777               // handle to the "real" LWP
1778               representativeLWP = lwp;
1779           }
1780           else
1781               delete lwp;
1782       }
1783       real_lwps.clear();
1784       
1785       // DO NOT DELETE THE REPRESENTATIVE LWP
1786
1787   }
1788   else { 
1789       while (lwp_iter.next(index, lwp)) {
1790           deleteLWP(lwp);
1791       }
1792       real_lwps.clear();
1793       
1794       if (representativeLWP) {
1795           delete representativeLWP;
1796           representativeLWP = NULL;
1797       }
1798   }
1799   
1800   // Blow away threads; we'll recreate later
1801   for (unsigned thr_iter = 0; thr_iter < threads.size(); thr_iter++) {
1802       delete threads[thr_iter];
1803   }
1804   threads.clear();
1805
1806
1807   deferredContinueProc = false;
1808   previousSignalAddr_ = 0;
1809   continueAfterNextStop_ = false;
1810   
1811   // Don't touch exec; statically allocated anyway.
1812
1813   if (theRpcMgr) {
1814       delete theRpcMgr;
1815   }
1816   theRpcMgr = NULL;
1817
1818   // Skipping saveTheWorld; don't know what to do with it.
1819
1820   trampTrapMapping.clear();
1821
1822   // Each instPoint may have several instances -- this gets instances and makes
1823   // a unique set
1824   std::set<instPoint *> allInstPoints;
1825   dictionary_hash_iter<Address, instPoint *> ipIter(instPMapping_);
1826   for (; ipIter; ipIter++) {
1827       instPoint *p = ipIter.currval();
1828       allInstPoints.insert(p);
1829   }
1830
1831   // And this deletes the set.
1832   for (std::set<instPoint *>::iterator ip = allInstPoints.begin();
1833        ip != allInstPoints.end();
1834        ip++) {
1835       delete (*ip);
1836   }
1837   instPMapping_.clear();
1838   
1839   codeRangesByAddr_.clear();
1840   
1841   // Iterate and clear? instPoint deletion should handle it.
1842   // What about replaced functions?
1843   modifiedAreas_.clear();
1844   multiTrampDict.clear();
1845
1846   // Blow away the replacedFunctionCalls list; codeGens are taken
1847   // care of statically and will deallocate
1848   dictionary_hash_iter<Address, replacedFunctionCall *> rfcIter(replacedFunctionCalls_);  
1849   for (; rfcIter; rfcIter++) {
1850       replacedFunctionCall *rfcVal = rfcIter.currval();
1851       assert(rfcVal->callAddr == rfcIter.currkey());
1852       assert(rfcVal);
1853       delete rfcVal;
1854   }
1855   replacedFunctionCalls_.clear();
1856
1857   codeSections_.clear();
1858   dataSections_.clear();
1859
1860   dyninstlib_brk_addr = 0;
1861   main_brk_addr = 0;
1862
1863   heapInitialized_ = false;
1864   heap.clear();
1865   inInferiorMallocDynamic = false;
1866
1867   // Get rid of our syscall tracing.
1868   if (tracedSyscalls_) {
1869       delete tracedSyscalls_;
1870       tracedSyscalls_ = NULL;
1871   }
1872
1873   for (iter = 0; iter < syscallTraps_.size(); iter++) 
1874       delete syscallTraps_[iter];
1875
1876   for (iter = 0; iter < tracingRequests.size(); iter++)
1877       delete tracingRequests[iter];
1878   tracingRequests.clear();
1879
1880   // By definition, these are dangling.
1881   for (iter = 0; iter < pendingGCInstrumentation.size(); iter++) {
1882       delete pendingGCInstrumentation[iter];
1883   }
1884   pendingGCInstrumentation.clear();
1885
1886   cumulativeObsCost = 0;
1887   lastObsCostLow = 0;
1888   costAddr_ = 0;
1889   threadIndexAddr = 0;
1890   trampGuardBase_ = 0;
1891
1892 #if defined(os_linux)
1893   vsyscall_start_ = 0;
1894   vsyscall_end_ = 0;
1895   vsyscall_text_ = 0;
1896   vsyscall_data_ = 0;
1897 #endif
1898   
1899   set_status(deleted);
1900 }
1901
1902 //
1903 // cleanup when a process is deleted. Assumed we are detached or the process is exited.
1904 //
1905 process::~process()
1906 {
1907     // Failed creation... nothing is here yet
1908     if (!reachedBootstrapState(initialized_bs)) {
1909         if (sh) SignalGeneratorCommon::stopSignalGenerator(sh);
1910         sh = NULL;
1911         return;
1912     }
1913
1914     // We require explicit detaching if the process still exists.
1915     // On the other hand, if it never started...
1916     if (reachedBootstrapState(bootstrapped_bs))
1917         assert(!isAttached());
1918
1919 #if defined( ia64_unknown_linux2_4 )
1920         if( unwindProcessArg != NULL ) { getDBI()->UPTdestroy( unwindProcessArg ); }
1921         if( unwindAddressSpace != NULL ) { getDBI()->destroyUnwindAddressSpace( unwindAddressSpace ); }
1922 #endif
1923     
1924     // Most of the deletion is encapsulated in deleteProcess
1925     deleteProcess();
1926
1927     if (sh) {
1928       signal_printf("%s[%d]:  removing signal handler for process\n", FILE__, __LINE__);
1929       SignalGeneratorCommon::stopSignalGenerator(sh);
1930     }
1931
1932     // We used to delete the particular process, but this created no end of problems
1933     // with people storing pointers into particular indices. We set the pointer to NULL.
1934     for (unsigned lcv=0; lcv < processVec.size(); lcv++) {
1935         if (processVec[lcv] == this) {
1936             processVec[lcv] = NULL;
1937         }        
1938     }
1939
1940 #if defined(i386_unknown_linux2_0) \
1941  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
1942     cleanupVsysinfo(getVsyscallData());
1943 #endif
1944
1945 }
1946
1947 // Default process class constructor. This handles both create,
1948 // attach, and attachToCreated cases. We then call an auxiliary
1949 // function (which can return an error value) to handle specific
1950 // cases.
1951 process::process(SignalGenerator *sh_) :
1952     cached_result(not_cached), // MOVE ME
1953     parent(NULL),
1954     sh(sh_),
1955     runtime_lib(NULL),
1956     creationMechanism_(unknown_cm),
1957     stateWhenAttached_(unknown_ps),
1958     main_function(NULL),
1959     dyn(NULL),
1960     representativeLWP(NULL),
1961     real_lwps(CThash),
1962     max_number_of_threads(MAX_THREADS),
1963     deferredContinueProc(false),
1964     previousSignalAddr_(0),
1965     continueAfterNextStop_(false),
1966     status_(neonatal),
1967     nextTrapIsExec(false),
1968     inExec_(false),
1969     theRpcMgr(NULL),
1970     collectSaveWorldData(true),
1971     requestTextMiniTramp(false),
1972     traceLink(0),
1973     trampTrapMapping(addrHash4),
1974     instPMapping_(addrHash4),
1975     multiTrampDict(intHash),
1976     replacedFunctionCalls_(addrHash4),
1977     bootstrapState(unstarted_bs),
1978     savedRegs(NULL),
1979     dyninstlib_brk_addr(0),
1980     main_brk_addr(0),
1981     systemPrelinkCommand(NULL),
1982 #if defined(os_windows)
1983     processHandle_(INVALID_HANDLE_VALUE),
1984     mainFileHandle_(INVALID_HANDLE_VALUE),
1985 #endif
1986     splitHeaps(false),
1987     heapInitialized_(false),
1988     inInferiorMallocDynamic(false),
1989     tracedSyscalls_(NULL),
1990     cumulativeObsCost(0),
1991     lastObsCostLow(0),
1992     costAddr_(0),
1993     threadIndexAddr(0),
1994     trampGuardBase_(0)
1995 #if defined(arch_ia64)
1996     , unwindAddressSpace(NULL) // Automatically created in getActiveFrame
1997     , unwindProcessArg(NULL) // And this one too
1998 #endif
1999 #if defined(os_linux)
2000     , vsys_status_(vsys_unknown)
2001     , vsyscall_start_(0)
2002     , vsyscall_end_(0)
2003     , vsyscall_text_(0)
2004     , vsyscall_data_(NULL)
2005 #endif
2006 {
2007
2008     // Let's try to profile memory usage
2009 #if defined(PROFILE_MEM_USAGE)
2010    void *mem_usage = sbrk(0);
2011    fprintf(stderr, "Process creation: sbrk %p\n", mem_usage);
2012 #endif
2013
2014     theRpcMgr = new rpcMgr(this);    
2015     dyn = new dynamic_linking(this);
2016
2017     // Not sure we need this anymore... on AIX you can run code
2018     // anywhere, so allocating by address _should_ be okay.
2019 #if defined(rs6000_ibm_aix3_2) \
2020  || defined(rs6000_ibm_aix4_1) \
2021  || defined(alpha_dec_osf4_0)
2022     splitHeaps = true;
2023 #endif
2024
2025 }
2026
2027 //
2028 // Process "normal" (non-attach, non-fork) ctor equivalent, for when a
2029 // new process is fired up by paradynd itself.  This ctor. is also
2030 // used in the case that the application has been fired up by another
2031 // process and stopped just after executing the execv() system call.
2032 // In the "normal" case, the parameter iTraceLink will be a
2033 // non-negative value which corresponds to the pipe descriptor of the
2034 // trace pipe used between the paradynd and the application. In the
2035 // later case, iTraceLink will be -1. This will be posteriorly used to
2036 // properly initialize the createdViaAttachToCreated flag. - Ana
2037 //
2038
2039
2040 bool process::setupCreated(int iTraceLink) 
2041 {
2042     traceLink = iTraceLink; // notice that tracelink will be -1 in the unique
2043     // case called "AttachToCreated" - Ana 
2044     // PARADYN ONLY
2045
2046     creationMechanism_ = created_cm;
2047     
2048 #if !defined(BPATCH_LIBRARY)
2049     if (iTraceLink == -1 ) {
2050         fprintf(stderr, "%s[%d]:  setting attachedToCreated\n", FILE__, __LINE__);
2051         creationMechanism_ = attachedToCreated_cm;
2052     }
2053 #endif
2054
2055     // Post-setup state variables
2056     stateWhenAttached_ = stopped; 
2057     
2058     startup_printf("%s[%d]: Creation method: attaching to process\n", FILE__, __LINE__);
2059     // attach to the child process (machine-specific implementation)
2060     if (!attach()) { // error check?
2061         status_ = detached;
2062          fprintf(stderr, "%s[%d] attach failing here\n", FILE__, __LINE__);
2063          pdstring msg = pdstring("Warning: unable to attach to specified process :")
2064             + pdstring(getPid());
2065         showErrorCallback(26, msg.c_str());
2066         return false;
2067     }
2068     startup_printf("%s[%d]: Creation method: returning\n", FILE__, __LINE__);
2069     return true;
2070 }
2071     
2072
2073 // Attach version of the above: no trace pipe, but we assume that
2074 // main() has been reached and passed. Someday we could unify the two
2075 // if someone has a good way of saying "has main been reached".
2076 bool process::setupAttached() 
2077 {
2078     fprintf(stderr, "%s[%d]:  welcome to setupAttached()\n", FILE__, __LINE__);
2079     creationMechanism_ = attached_cm;
2080     // We're post-main... run the bootstrapState forward
2081
2082 #if !defined(os_windows)
2083     bootstrapState = initialized_bs;
2084 #else
2085     // We need to wait for the CREATE_PROCESS debug event.
2086     // Set to "begun" here, and fix up in the signal loop
2087     bootstrapState = begun_bs;
2088 #endif
2089
2090    traceLink = -1; // will be set later, when the appl runs DYNINSTinit
2091
2092    startup_printf("Attach method: attaching to process\n");
2093
2094    // It is assumed that a call to attach() doesn't affect the running status
2095    // of the process.  But, unfortunately, some platforms may barf if the
2096    // running status is anything except paused. (How to deal with this?)
2097    // Note that solaris in particular seems able to attach even if the process
2098    // is running.
2099    if (!attach()) {
2100        status_ = detached;
2101        
2102          fprintf(stderr, "%s[%d] attach failing here\n", FILE__, __LINE__);
2103       pdstring msg = pdstring("Warning: unable to attach to specified process: ")
2104                    + pdstring(getPid());
2105       showErrorCallback(26, msg.c_str());
2106       return false;
2107    }
2108
2109    startup_printf("%s[%d]: attached, getting current process state\n", FILE__, __LINE__);
2110
2111    // Record what the process was doing when we attached, for possible
2112    // use later.
2113    if (isRunning_()) {
2114        startup_printf("%s[%d]: process running when attached, pausing...\n", FILE__, __LINE__);
2115        stateWhenAttached_ = running; 
2116        set_status(running);
2117        if (!pause())
2118            return false;
2119    }
2120    else {
2121        startup_printf("%s[%d]: attached to previously paused process\n", FILE__, __LINE__);
2122        stateWhenAttached_ = stopped;
2123        set_status(stopped);
2124    }
2125    startup_printf("%s[%d]: setupAttached returning true\n",FILE__, __LINE__);
2126
2127    assert(status() == stopped);
2128    return true;
2129 }
2130
2131 int HACKSTATUS = 0;
2132
2133 bool process::prepareExec(fileDescriptor &desc) 
2134 {
2135     ///////////////////////////// CONSTRUCTION STAGE ///////////////////////////
2136     // For all intents and purposes: a new id.
2137     // However, we don't want to make a new object since all sorts
2138     // of people have a pointer to this object. We could index by PID,
2139     // which would allow us to swap out processes; but hey.
2140
2141     // We should be attached to the process
2142
2143     // setupExec must get us to the point of putting a trap at the
2144     // beginning of main. We then continue. We might get called again,
2145     // or we might go into loading the dyninst lib; impossible to
2146     // tell.
2147     //
2148
2149 #if defined(AIX_PROC)
2150     // AIX oddly detaches from the process... fix that here
2151     // Actually, it looks like only the as FD is closed (probably because
2152     // the file it refers to is gone). Reopen.
2153    getRepresentativeLWP()->reopen_fds();
2154 #endif
2155
2156     // Revert the bootstrap state
2157     bootstrapState = attached_bs;
2158
2159     // First, duplicate constructor.
2160
2161     assert(theRpcMgr == NULL);
2162     assert(dyn == NULL);
2163     theRpcMgr = new rpcMgr(this);
2164     dyn = new dynamic_linking(this);
2165
2166     if (!setAOut(desc)) {
2167         return false;
2168     }
2169
2170     // Probably not going to find anything (as we haven't loaded the
2171     // RT lib yet, and that's where most of the space is). However,
2172     // any shared object added after this point will have infHeaps
2173     // auto-added.
2174     startup_printf("Initializing vector heap\n");
2175     initInferiorHeap();
2176
2177     // Now from setupGeneral...
2178     createInitialThread();
2179
2180     // Status: stopped.
2181     set_status(stopped);
2182
2183     // Annoying; most of our initialization code is in unix.C, and it
2184     // knows how to get us to main. Problem is, it triggers on a trap...
2185     // and guess what we just consumed. So replicate it manually.
2186     setBootstrapState(begun_bs);
2187     insertTrapAtEntryPointOfMain();
2188     continueProc();
2189
2190     return true;
2191 }
2192
2193 bool process::finishExec() {
2194     startup_printf("%s[%d]:  about to load DyninstLib\n", FILE__, __LINE__);
2195     bool res = loadDyninstLib();
2196     if (!res)
2197         return false;
2198     
2199     getMailbox()->executeCallbacks(FILE__, __LINE__);
2200     while(!reachedBootstrapState(bootstrapped_bs)) {
2201         // We're waiting for something... so wait
2202         // true: block until a signal is received (efficiency)
2203         if(hasExited()) {
2204             return false;
2205         }
2206         fprintf(stderr, "%s[%d][%s]:  before waitForEvent(evtProcessInitDone)\n", 
2207                 FILE__, __LINE__, getThreadStr(getExecThreadID()));
2208
2209         sh->waitForEvent(evtProcessInitDone);
2210         getMailbox()->executeCallbacks(FILE__, __LINE__);
2211     }
2212     
2213     if(process::IndependentLwpControl())
2214         independentLwpControlInit();
2215     
2216     set_status(stopped); // was 'exited'
2217     
2218     inExec_ = false;
2219     BPatch::bpatch->registerExecExit(this);
2220
2221     return true;
2222 }
2223
2224 bool process::setupFork() 
2225 {
2226     assert(parent);
2227     assert(parent->status() == stopped);
2228
2229     // Do stuff....
2230
2231     // Copy: 
2232     //   all mapped objects
2233     //   dynamic object tracer
2234     //   all threads
2235     //   all lwps
2236     //   rpc manager
2237     //   all vector heaps
2238     //   all defined instPoints
2239     //   all multiTramps
2240     //    ... and baseTramps, relocatedInstructions, trampEnds, miniTramps
2241     //   installed instrumentation
2242     //    ... including system call handling
2243     //   process state
2244     //   
2245
2246     // Mapped objects first
2247     for (unsigned i = 0; i < parent->mapped_objects.size(); i++) {
2248         mapped_object *par_obj = parent->mapped_objects[i];
2249         mapped_object *child_obj = new mapped_object(par_obj, this);
2250         if (!child_obj) {
2251             delete child_obj;
2252             return false;
2253         }
2254
2255         mapped_objects.push_back(child_obj);
2256         addCodeRange(child_obj);
2257
2258         if ((par_obj->fileName() == dyninstRT_name) ||
2259             (par_obj->fullName() == dyninstRT_name))
2260             runtime_lib = child_obj;
2261
2262         // This clones funcs, which then clone instPoints, which then 
2263         // clone baseTramps, which then clones miniTramps.
2264     }
2265     // And the main func and dyninst RT lib
2266     if (!setMainFunction())
2267         return false;
2268     if (parent->runtime_lib) {
2269         // This should be set by now...
2270         assert(runtime_lib);
2271     }
2272     
2273     /////////////////////////
2274     // Threads & LWPs
2275     /////////////////////////
2276
2277     if(process::IndependentLwpControl())
2278         independentLwpControlInit();
2279
2280     /////////////////////////
2281     // RPC manager
2282     /////////////////////////
2283     
2284     theRpcMgr = new rpcMgr(parent->theRpcMgr, this);
2285     assert(theRpcMgr);
2286
2287     /////////////////////////
2288     // Find new threads
2289     /////////////////////////    
2290
2291     recognize_threads(parent);
2292
2293
2294     /////////////////////////
2295     // Inferior heap
2296     /////////////////////////
2297     
2298     heap = inferiorHeap(parent->heap);
2299
2300     /////////////////////////
2301     // Instrumentation (multiTramps on down)
2302     /////////////////////////
2303
2304     dictionary_hash_iter<int, multiTramp *> multiTrampIter(parent->multiTrampDict);
2305     int mID;
2306     multiTramp *mTramp;
2307     for (; multiTrampIter; multiTrampIter++) {
2308         mID = multiTrampIter.currkey();
2309         mTramp = multiTrampIter.currval();
2310         assert(mTramp);
2311         multiTramp *newMulti = new multiTramp(mTramp, this);
2312         multiTrampDict[mID] = newMulti;
2313         addMultiTramp(newMulti);
2314     }
2315     // That will also create all baseTramps, miniTramps, ...
2316
2317     // Copy the replacedFunctionCalls...
2318     dictionary_hash_iter<Address, replacedFunctionCall *> rfcIter(replacedFunctionCalls_);  
2319     Address rfcKey;
2320     replacedFunctionCall *rfcVal;
2321     for (; rfcIter; rfcIter++) {
2322         rfcKey = rfcIter.currkey();
2323         assert(rfcKey);
2324         rfcVal = rfcIter.currval();
2325         assert(rfcVal);
2326         assert(rfcVal->callAddr == rfcKey);
2327         // Mmm copy constructor
2328         replacedFunctionCall *newRFC = new replacedFunctionCall(*rfcVal);
2329         replacedFunctionCalls_[rfcKey] = newRFC;
2330     }
2331
2332 #if 0
2333     // We create instPoints as part of copying functions
2334
2335     std::set<instPoint *> allInstPoints;
2336     dictionary_hash_iter<Address, instPoint *> ipIter(parent->instPMapping_);
2337     for (; ipIter; ipIter++) {
2338         instPoint *p = ipIter.currval();
2339         allInstPoints.insert(p);
2340     }
2341     
2342     for (std::set<instPoint *>::iterator ip = allInstPoints.begin();
2343          ip != allInstPoints.end();
2344          ip++) {
2345         instPoint *newIP = new instPoint(*ip, this);
2346         assert(newIP);
2347         // Adds to instPMapping_
2348     }
2349 #endif
2350
2351     // Tag the garbage collection list...
2352     for (unsigned ii = 0; ii < parent->pendingGCInstrumentation.size(); ii++) {
2353         // TODO. For now we'll just "leak"
2354     }
2355
2356     // Now that we have instPoints, we can create the (possibly) instrumentation-
2357     // based tracing code
2358
2359     /////////////////////////
2360     // Dynamic tracer
2361     /////////////////////////
2362
2363     dyn = new dynamic_linking(parent->dyn, this);
2364     assert(dyn);
2365
2366     /////////////////////////
2367     // Syscall tracer
2368     /////////////////////////
2369
2370     tracedSyscalls_ = new syscallNotification(parent->tracedSyscalls_, this);
2371
2372     // Copy signal handlers
2373
2374     pdvector<codeRange *> sigHandlers;
2375     parent->signalHandlerLocations_.elements(sigHandlers);
2376     for (unsigned iii = 0; iii < sigHandlers.size(); iii++) {
2377         signal_handler_location *oldSig = dynamic_cast<signal_handler_location *>(sigHandlers[iii]);
2378         assert(oldSig);
2379         signal_handler_location *newSig = new signal_handler_location(*oldSig);
2380         signalHandlerLocations_.insert(newSig);
2381     }
2382
2383
2384 #if defined(os_aix)
2385     // AIX doesn't copy memory past the ends of text segments, so we
2386     // do it manually here
2387     copyDanglingMemory(const_cast<process *>(parent));
2388 #endif
2389
2390     /////////////////////////
2391     // Process vector
2392     /////////////////////////
2393
2394     processVec.push_back(this);
2395     activeProcesses++;
2396     return true;
2397 }
2398
2399
2400 unsigned process::getAddressWidth() { 
2401     if (mapped_objects.size() > 0) 
2402         return mapped_objects[0]->parse_img()->getObject().getAddressWidth(); 
2403     // We can call this before we've attached.. 
2404     return 4;
2405 }
2406
2407 bool process::setAOut(fileDescriptor &desc) 
2408 {
2409     assert(reachedBootstrapState(attached_bs));
2410     assert(mapped_objects.size() == 0);
2411     mapped_object *aout = mapped_object::createMappedObject(desc, this);
2412     if (!aout)
2413         return false;
2414     
2415     mapped_objects.push_back(aout);
2416     addCodeRange(aout);
2417
2418     findSignalHandler(aout);
2419
2420     // Find main
2421     return setMainFunction();
2422 }
2423
2424 // Here's the list of functions to look for:
2425 #define NUMBER_OF_MAIN_POSSIBILITIES 7
2426 char main_function_names[NUMBER_OF_MAIN_POSSIBILITIES][20] = {
2427     "main",
2428     "DYNINST_pltMain",
2429     "_main",
2430     "WinMain",
2431     "_WinMain",
2432     "wWinMain",
2433     "_wWinMain"};
2434
2435 bool process::setMainFunction() 
2436 {
2437     assert(!main_function);
2438     
2439     for (unsigned i = 0; i < NUMBER_OF_MAIN_POSSIBILITIES; i++) {
2440         main_function = findOnlyOneFunction(main_function_names[i]);
2441         if (main_function) break;
2442     }
2443
2444     assert(main_function);
2445     return true;
2446 }
2447
2448 bool process::setupGeneral() 
2449 {
2450     // Need to have a.out at this point
2451     assert(mapped_objects.size() > 0);
2452
2453     if (reachedBootstrapState(bootstrapped_bs)) 
2454         return true;
2455
2456     // We should be paused; be sure.
2457     pause();
2458     
2459     // In the ST case, threads[0] (the only one) is effectively
2460     // a pass-through for process operations. In MT, it's the
2461     // main thread of the process and is handled correctly
2462
2463     startup_printf("Creating initial thread...\n");
2464
2465     createInitialThread();
2466
2467     // Probably not going to find anything (as we haven't loaded the
2468     // RT lib yet, and that's where most of the space is). However,
2469     // any shared object added after this point will have infHeaps
2470     // auto-added.
2471     startup_printf("Initializing vector heap\n");
2472     initInferiorHeap();
2473
2474     startup_printf("%s[%d]: Loading DYNINST lib...\n", FILE__, __LINE__);
2475     // TODO: loadDyninstLib actually embeds a lot of startup material;
2476     // should move it up to this function to make things more obvious.
2477     bool res = loadDyninstLib();
2478     if(res == false) {
2479         return false;
2480     }
2481     startup_printf("Waiting for bootstrapped state...\n");
2482     while (!reachedBootstrapState(bootstrapped_bs)) {
2483        // We're waiting for something... so wait
2484        // true: block until a signal is received (efficiency)
2485        if(hasExited()) {
2486            return false;
2487        }
2488        startup_printf("Checking for process event...\n");
2489        sh->waitForEvent(evtProcessInitDone);
2490        getMailbox()->executeCallbacks(FILE__, __LINE__);
2491     }
2492
2493     if(process::IndependentLwpControl())
2494         independentLwpControlInit();
2495     
2496     initTramps(multithread_capable());
2497
2498     return true;
2499 }
2500
2501 //
2502 // Process "fork" ctor, for when a process which is already being monitored by
2503 // paradynd executes the fork syscall.
2504 //
2505 // Needs to strictly duplicate all process information; this is a _lot_ of work.
2506
2507 process::process(const process *parentProc, SignalGenerator *sg_, int childTrace_fd) : 
2508     cached_result(parentProc->cached_result), // MOVE ME
2509     parent(parentProc),
2510     sh(sg_),
2511     runtime_lib(NULL), // Set later
2512     dyninstRT_name(parentProc->dyninstRT_name),
2513     creationMechanism_(parentProc->creationMechanism_),
2514     stateWhenAttached_(parentProc->stateWhenAttached_),
2515     main_function(NULL), // Set later
2516     dyn(NULL),  // Set later
2517     representativeLWP(NULL), // Set later
2518     real_lwps(CThash),
2519     max_number_of_threads(parentProc->max_number_of_threads),
2520     deferredContinueProc(parentProc->deferredContinueProc),
2521     previousSignalAddr_(parentProc->previousSignalAddr_),
2522     continueAfterNextStop_(parentProc->continueAfterNextStop_),
2523     status_(parentProc->status_),
2524     nextTrapIsExec(parentProc->nextTrapIsExec),
2525     inExec_(parentProc->inExec_),
2526     theRpcMgr(NULL), // Set later
2527     collectSaveWorldData(parentProc->collectSaveWorldData),
2528     requestTextMiniTramp(parentProc->requestTextMiniTramp),
2529     traceLink(childTrace_fd),
2530     trampTrapMapping(parentProc->trampTrapMapping),
2531     instPMapping_(addrHash4), // Later
2532     multiTrampDict(intHash), // Later
2533     replacedFunctionCalls_(addrHash4), // Also later
2534     bootstrapState(parentProc->bootstrapState),
2535     savedRegs(NULL), // Later
2536     dyninstlib_brk_addr(parentProc->dyninstlib_brk_addr),
2537     main_brk_addr(parentProc->main_brk_addr),
2538     systemPrelinkCommand(NULL),
2539     splitHeaps(parentProc->splitHeaps),
2540     heapInitialized_(parentProc->heapInitialized_),
2541     inInferiorMallocDynamic(parentProc->inInferiorMallocDynamic),
2542     tracedSyscalls_(NULL),  // Later
2543     cumulativeObsCost(parentProc->cumulativeObsCost),
2544     lastObsCostLow(parentProc->lastObsCostLow),
2545     costAddr_(parentProc->costAddr_),
2546     threadIndexAddr(parentProc->threadIndexAddr),
2547     trampGuardBase_(parentProc->trampGuardBase_)
2548 #if defined(arch_ia64)
2549     , unwindAddressSpace(NULL) // Recreated automatically in getActiveFrame
2550     , unwindProcessArg(NULL) // And this
2551 #endif
2552 #if defined(os_linux)
2553     , vsyscall_start_(parentProc->vsyscall_start_)
2554     , vsyscall_end_(parentProc->vsyscall_end_)
2555     , vsyscall_text_(parentProc->vsyscall_text_)
2556     , vsyscall_data_(parentProc->vsyscall_data_)
2557 #endif
2558 {
2559 }
2560
2561 static void cleanupBPatchHandle(int pid)
2562 {
2563    fprintf(stderr, "%s[%d]:  about to unRegisterProcess\n", FILE__, __LINE__);
2564    BPatch::bpatch->unRegisterProcess(pid);
2565 }
2566
2567
2568 /*
2569  * Create a new instance of the named process.  Read the symbols and start
2570  *   the program
2571  */
2572 process *ll_createProcess(const pdstring File, pdvector<pdstring> *argv,
2573                           pdvector<pdstring> *envp, const pdstring dir = "",
2574                           int stdin_fd=0, int stdout_fd=1, int stderr_fd=2)
2575 {
2576
2577         // prepend the directory (if any) to the filename,
2578         // unless the filename is an absolute pathname
2579         // 
2580         // The filename is an absolute pathname if it starts with a '/' on UNIX,
2581         // or a letter and colon pair on Windows.
2582
2583   startup_cerr << "Creating process " << File << " in directory " << dir << endl;
2584
2585   if (argv) {
2586     startup_cerr << "Arguments: (" << argv->size() << ")" << endl;
2587     for (unsigned a = 0; a < argv->size(); a++)
2588       startup_cerr << "   " << a << ": " << (*argv)[a] << endl;
2589   }
2590   if (envp) {
2591     startup_cerr << "Environment: (" << envp->size() << ")" << endl;
2592     for (unsigned e = 0; e < envp->size(); e++)
2593       startup_cerr << "   " << e << ": " << (*envp)[e] << endl;
2594   }
2595   startup_printf("Stdin: %d, stdout: %d, stderr: %d\n", stdin_fd, stdout_fd, stderr_fd);
2596
2597   //    int traceLink = -1; // set by forkNewProcess, below.
2598
2599   //    int pid = -1;
2600   //    int tid;
2601
2602     // NT
2603     int procHandle_temp;
2604     //    int thrHandle_temp;
2605
2606     process *theProc = SignalGeneratorCommon::newProcess(File, dir,
2607                                                                     argv, envp,
2608                                                                     stdin_fd, stdout_fd, 
2609                                                                     stderr_fd);
2610    if (!theProc || !theProc->sh) {
2611      fprintf(stderr, "%s[%d]:  failed to create process %s\n", 
2612              FILE__, __LINE__, File.c_str());
2613      getMailbox()->executeCallbacks(FILE__, __LINE__);
2614      return NULL;
2615    }
2616
2617     startup_printf( "%s[%d]:  Fork new process... succeeded",FILE__, __LINE__);
2618
2619 #ifdef BPATCH_LIBRARY
2620     // Register the pid with the BPatch library (not yet associated with a
2621     // BPatch_thread object).
2622     assert(BPatch::bpatch != NULL);
2623     BPatch::bpatch->registerProvisionalThread(theProc->sh->getPid());
2624 #endif
2625
2626 #if defined(i386_unknown_nt4_0)
2627     int status = procHandle_temp;
2628     // DEBUGGING
2629 #else
2630     int status = theProc->sh->getPid();
2631 #endif // defined(i386_unknown_nt4_0)
2632     
2633
2634     theProc->set_status(running);
2635
2636     // We need to add this as soon as possible, since a _lot_ of things
2637     // do lookups.
2638     processVec.push_back(theProc);
2639     activeProcesses++;
2640
2641     statusLine("initializing process data structures");
2642
2643     if (!theProc->setupGeneral()) {
2644         startup_printf("[%s:%u] - Couldn't setupGeneral\n", __FILE__, __LINE__);
2645         cleanupBPatchHandle(theProc->sh->getPid());
2646         processVec.pop_back();
2647         delete theProc;
2648         return NULL;
2649     }
2650
2651     // Let's try to profile memory usage
2652 #if defined(PROFILE_MEM_USAGE)
2653    void *mem_usage = sbrk(0);
2654    fprintf(stderr, "Post process: sbrk %p\n", mem_usage);
2655 #endif
2656
2657    assert(theProc->reachedBootstrapState(bootstrapped_bs));
2658    startup_printf("%s[%d]:  process state: %s\n\n\n\n", FILE__, __LINE__, theProc->getBootstrapStateAsString().c_str());
2659    return theProc;    
2660 }
2661
2662
2663 process *ll_attachProcess(const pdstring &progpath, int pid) 
2664 {
2665   // implementation of dynRPC::attach() (the igen call)
2666   // This is meant to be "the other way" to start a process (competes w/ createProcess)
2667   
2668   // progpath gives the full path name of the executable, which we use ONLY to
2669   // read the symbol table.
2670   
2671   // We try to make progpath optional, since given pid, we should be able to
2672   // calculate it with a clever enough search of the process' PATH, examining
2673   // its argv[0], examining its current directory, etc.  /proc gives us this
2674   // information on solaris...not sure about other platforms...
2675
2676     // No longer take the afterAttach argument. Instead, the process object records
2677     // the state of the process at attach, and the user can read and act on this as
2678     // they please -- bernat, JAN03
2679
2680   startup_cerr << "welcome to attachProcess for pid " << pid << endl;
2681   startup_cerr << "Given program path: " << progpath << endl;
2682
2683   // QUESTION: When we attach to a process, do we want to redirect its stdout/stderr
2684   //           (like we do when we fork off a new process the 'usual' way)?
2685   //           My first guess would be no.  -ari
2686   //           But although we may ignore the io, we still need the trace stream.
2687   
2688   // When we attach to a process, we don't fork...so this routine is much
2689   // simpler than its "competitor", ll_createProcess() (above).
2690   pdstring fullPathToExecutable = process::tryToFindExecutable(progpath, pid);
2691
2692   if (!fullPathToExecutable.length()) {
2693       return NULL;
2694   }
2695
2696   process *theProc = SignalGeneratorCommon::newProcess(fullPathToExecutable, pid);
2697   if (!theProc || !theProc->sh) {
2698     fprintf(stderr, "%s[%d]:  failed to create process %s\n", FILE__, __LINE__, progpath.c_str());
2699     getMailbox()->executeCallbacks(FILE__, __LINE__);
2700     return NULL;
2701   }
2702
2703   // Add this as we can't do _anything_ without a process to look up.
2704   processVec.push_back(theProc);
2705   activeProcesses++;
2706
2707   if (!theProc->setupGeneral()) {
2708         processVec.pop_back();
2709       delete theProc;
2710       return NULL;
2711   }
2712
2713   return theProc; // successful
2714 }
2715
2716 /***************************************************************************
2717  **** Runtime library initialization code (Dyninst)                     ****
2718  ***************************************************************************/
2719
2720 /*
2721  * Gratuitously large comment. This diagrams the startup flow of 
2722  * messages between the mutator and mutatee. Entry points 
2723  * for create and attach process are both given.
2724  *     Mutator           Signal              Mutatee
2725  * Create:
2726  *     Fork/Exec
2727  *                     <-- Trap              Halted in exec
2728  *     Install trap in main             
2729  *                     <-- Trap              Halted in main
2730  *  Attach: (also paused, not in main)
2731  *     Install call to dlopen/
2732  *     LoadLibrary       
2733  *                     <-- Trap              In library load
2734  *     Set parameters in library
2735  *                     <-- Trap              Finished loading
2736  *     Restore code and leave paused
2737  *     Finalize library
2738  *       If finalizing fails, 
2739  *       init via iRPC
2740  *
2741  * Note: we've actually stopped trying to trap the library, since
2742  * setting arguments via inferior RPC is just as easy and a _lot_
2743  * cleaner.
2744  */
2745
2746 /*
2747  * In all cases, the process is left paused at the entry of main
2748  * (create) or where it was (attach). No permanent instrumentation
2749  * is inserted.
2750  */
2751
2752 // Load and initialize the runtime library: returns when the RT lib
2753 // is both loaded and initialized.
2754 // Return val: false=error condition
2755
2756 bool process::loadDyninstLib() {
2757   startup_printf("Entry to loadDyninstLib\n");
2758     // Wait for the process to get to an initialized (dlopen exists)
2759     // state
2760     while (!reachedBootstrapState(initialized_bs)) {
2761       startup_printf("Waiting for process to reach initialized state...\n");
2762        if(hasExited()) {
2763            return false;
2764        }
2765        getMailbox()->executeCallbacks(FILE__, __LINE__);
2766        pdvector<eventType> evts;
2767        evts.push_back(evtProcessAttach); 
2768        evts.push_back(evtProcessInit); 
2769        evts.push_back(evtProcessExit); 
2770        if (reachedBootstrapState(initialized_bs)) break;
2771        sh->waitForOneOf(evts);
2772        getMailbox()->executeCallbacks(FILE__, __LINE__);
2773     }
2774     assert (isStopped());
2775     startup_printf("Stopped at entry of main\n");
2776
2777     // We've hit the initialization trap, so load dyninst lib and
2778     // force initialization
2779     pdstring buffer = pdstring("PID=") + pdstring(getPid());
2780     buffer += pdstring(", initializing shared objects");       
2781     statusLine(buffer.c_str());
2782
2783     // Perform initialization...
2784     if (!dyn->initialize()) 
2785     {
2786        cerr << "Dyninst was unable to load the dyninst runtime library "
2787             << "into the application.  This may be caused by statically "
2788             << "linked executables, or by having dyninst linked against a "
2789             << "different version of libelf than it was built with." << endl;
2790        return false;
2791     }
2792     startup_printf("Initialized dynamic linking tracer\n");
2793
2794     // And get the list of all shared objects in the process. More properly,
2795     // get the address of dlopen.
2796     if (!processSharedObjects()) {
2797       startup_printf("Failed to get initial shared objects\n");
2798       return false;
2799     }
2800
2801     startup_printf("Processed initial shared objects:\n");
2802
2803     for (unsigned debug_iter = 1; debug_iter < mapped_objects.size(); debug_iter++)
2804         startup_printf("%d: %s\n", debug_iter, 
2805                        mapped_objects[debug_iter]->debugString().c_str());
2806
2807     startup_printf("----\n");
2808
2809     if (dyninstLibAlreadyLoaded()) {
2810         logLine("ERROR: dyninst library already loaded, we missed initialization!");
2811         // TODO: We could handle this case better :)
2812         assert(0);
2813     }
2814     
2815     if (!getDyninstRTLibName()) {
2816         startup_printf("Failed to get Dyninst RT lib name\n");
2817         return false;
2818     }
2819     startup_printf("%s[%d]: Got Dyninst RT libname: %s\n", FILE__, __LINE__,
2820                    dyninstRT_name.c_str());
2821
2822     // Force a call to dlopen(dyninst_lib)
2823     buffer = pdstring("PID=") + pdstring(getPid());
2824     buffer += pdstring(", loading dyninst library");       
2825     statusLine(buffer.c_str());
2826
2827     startup_printf("%s[%d]: Starting load of Dyninst library...\n", FILE__, __LINE__);
2828     loadDYNINSTlib();
2829     startup_printf("Think we have Dyninst RT lib set up...\n");
2830     
2831     setBootstrapState(loadingRT_bs);
2832     
2833     if (!continueProc()) {
2834         assert(0);
2835     }
2836     // Loop until the dyninst lib is loaded
2837     while (!reachedBootstrapState(loadedRT_bs)) {
2838         if(hasExited()) {
2839             startup_printf("Odd, process exited while waiting for Dyninst RT lib load\n");
2840             return false;
2841         }
2842         sh->waitForEvent(evtProcessLoadedRT);
2843     }
2844     getMailbox()->executeCallbacks(FILE__, __LINE__);
2845     // We haven't inserted a trap at dlopen yet (as we require the runtime lib for that)
2846     // So re-check all loaded libraries (and add to the list gotten earlier)
2847     // We force a compare even though the PC is not at the correct address.
2848     dyn->set_force_library_check();
2849     EventRecord load_rt_event;
2850     load_rt_event.proc = this;
2851     load_rt_event.lwp = NULL;
2852     load_rt_event.type = evtLoadLibrary;
2853     load_rt_event.what = SHAREDOBJECT_ADDED;
2854     if (!handleChangeInSharedObjectMapping(load_rt_event)) {
2855       fprintf(stderr, "%s[%d]:  handleChangeInSharedObjectMapping failed!\n", FILE__, __LINE__);
2856     }
2857     dyn->unset_force_library_check();
2858
2859     // Make sure the library was actually loaded
2860     if (!runtime_lib) {
2861         fprintf(stderr, "%s[%d]:  Don't have runtime library handle\n", __FILE__, __LINE__);
2862         return false;
2863     }
2864     
2865     buffer = pdstring("PID=") + pdstring(getPid());
2866     buffer += pdstring(", initializing mutator-side structures");
2867     statusLine(buffer.c_str());    
2868
2869     // The library is loaded, so do mutator-side initialization
2870     buffer = pdstring("PID=") + pdstring(getPid());
2871     buffer += pdstring(", finalizing RT library");
2872     statusLine(buffer.c_str());    
2873     startup_printf("(%d) finalizing dyninst RT library\n", getPid());
2874
2875     if (!finalizeDyninstLib())
2876       startup_printf("%s[%d]:  failed to finalize dyninst lib\n", __FILE__, __LINE__);
2877
2878     if (!reachedBootstrapState(bootstrapped_bs)) {
2879         // For some reason we haven't run dyninstInit successfully.
2880         // Probably because we didn't set parameters before 
2881         // dyninstInit was automatically run. Catchup with
2882         // an inferiorRPC is the best bet.
2883         buffer = pdstring("PID=") + pdstring(getPid());
2884         buffer += pdstring(", finalizing library via inferior RPC");
2885         statusLine(buffer.c_str());    
2886         iRPCDyninstInit();        
2887     }
2888
2889     buffer = pdstring("PID=") + pdstring(getPid());
2890     buffer += pdstring(", dyninst RT lib ready");
2891     statusLine(buffer.c_str());    
2892
2893     return true;
2894 }
2895
2896 // Set the shared object mapping for the RT library
2897 bool process::setDyninstLibPtr(mapped_object *RTobj) {
2898     assert (!runtime_lib);
2899
2900     runtime_lib = RTobj;
2901     return true;
2902 }
2903
2904
2905 // Set up the parameters for DYNINSTinit in the RT lib
2906
2907 bool process::setDyninstLibInitParams() {
2908
2909    startup_cerr << "process::setDYNINSTinitArguments()" << endl;
2910
2911    int pid = getpid();
2912    
2913    // Cause: 
2914    // 1 = created
2915    // 2 = forked
2916    // 3 = attached
2917    
2918    int cause;
2919    switch (creationMechanism_) {
2920    case created_cm:
2921        cause = 1;
2922        break;
2923    case attached_cm:
2924        cause = 3;
2925        break;
2926    case attachedToCreated_cm:
2927        // Uhhh....
2928        cause = 3;
2929        break;
2930    default:
2931        assert(0);
2932        break;
2933    }
2934    
2935    // Now we write these variables into the following global vrbles
2936    // in the dyninst library:
2937    // libdyninstAPI_RT_init_localCause
2938    // libdyninstAPI_RT_init_localPid
2939
2940    pdvector<int_variable *> vars;
2941
2942    if (!findVarsByAll("libdyninstAPI_RT_init_localCause",
2943                       vars,
2944                       dyninstRT_name))
2945        if (!findVarsByAll("_libdyninstAPI_RT_init_localCause",
2946                           vars))
2947            assert(0 && "Could not find necessary internal variable");
2948    assert(vars.size() == 1);
2949    writeDataSpace((void*)vars[0]->getAddress(), sizeof(int), (void *)&cause);
2950    vars.clear();
2951
2952    if (!findVarsByAll("libdyninstAPI_RT_init_localPid", vars))
2953        if (!findVarsByAll("_libdyninstAPI_RT_init_localPid", vars))
2954            assert(0 && "Could not find necessary internal variable");
2955    assert(vars.size() == 1);
2956    writeDataSpace((void*)vars[0]->getAddress(), sizeof(int), (void *)&pid);
2957    vars.clear();   
2958
2959    if (!findVarsByAll("libdyninstAPI_RT_init_maxthreads", vars))
2960        if (!findVarsByAll("_libdyninstAPI_RT_init_maxthreads", vars))
2961            assert(0 && "Could not find necessary internal variable");
2962    assert(vars.size() == 1);
2963    writeDataSpace((void*)vars[0]->getAddress(), sizeof(int), (void *) &max_number_of_threads);
2964    vars.clear();   
2965
2966    startup_cerr << "process::installBootstrapInst() complete" << endl;   
2967    return true;
2968 }
2969
2970 // Call DYNINSTinit via an inferiorRPC
2971 bool process::iRPCDyninstInit() {
2972     startup_printf("[%s:%u] - Running DYNINSTinit via irpc\n", __FILE__, __LINE__);
2973     // Duplicates the parameter code in setDyninstLibInitParams()
2974     int pid = getpid();
2975     int maxthreads = maxNumberOfThreads();
2976
2977     int cause = 0;
2978     switch (creationMechanism_) {
2979     case created_cm:
2980         cause = 1;
2981         break;
2982     case attached_cm:
2983         cause = 3;
2984         break;
2985     case attachedToCreated_cm:
2986         // Uhhh....
2987         cause = 3;
2988         break;
2989     default:
2990         assert(0);
2991         break;
2992    }
2993
2994     pdvector<AstNode*> the_args(3);
2995     the_args[0] = new AstNode(AstNode::Constant, (void*)(Address)cause);
2996     the_args[1] = new AstNode(AstNode::Constant, (void*)(Address)pid);
2997     the_args[2] = new AstNode(AstNode::Constant, (void*)(Address)maxthreads);
2998     AstNode *dynInit = new AstNode("DYNINSTinit", the_args);
2999     removeAst(the_args[0]); removeAst(the_args[1]); removeAst(the_args[2]);
3000     getRpcMgr()->postRPCtoDo(dynInit,
3001                              true, // Don't update cost
3002                              process::DYNINSTinitCompletionCallback,
3003                              NULL, // No user data
3004                              true, // Use reserved memory
3005                              NULL, NULL);// No particular thread or LWP
3006
3007     // We loop until dyninst init has run (check via the callback)
3008      inferiorrpc_printf("%s[%d]:  waiting for rpc completion\n", FILE__, __LINE__);
3009     while (!reachedBootstrapState(bootstrapped_bs)) {
3010         getRpcMgr()->launchRPCs(false); // false: not running
3011         if(hasExited()) {
3012             fprintf(stderr, "%s[%d][%s]:  unexpected exit\n", __FILE__, __LINE__, getThreadStr(getExecThreadID()));
3013            return false;
3014         }
3015         getMailbox()->executeCallbacks(FILE__, __LINE__);
3016         sh->waitForEvent(evtRPCSignal, this, NULL /*lwp*/, statusRPCDone);
3017         getMailbox()->executeCallbacks(FILE__, __LINE__);
3018     }
3019     startup_printf("%s[%d][%s]:  bootstrapped\n", __FILE__, __LINE__, getThreadStr(getExecThreadID()));
3020     startup_printf("[%s:%u] - Ran DYNINSTinit via irpc\n", __FILE__, __LINE__);
3021     return true;
3022 }
3023
3024 bool process::attach() 
3025 {
3026    dictionary_hash_iter<unsigned, dyn_lwp *> lwp_iter(real_lwps);
3027    dyn_lwp *lwp;
3028    unsigned index;
3029    assert(getRepresentativeLWP());  // we expect this to be defined
3030    // Though on linux, if process found to be MT, there will be no
3031    // representativeLWP since there is no lwp which controls the entire
3032    // process for MT linux.
3033
3034    startup_printf("[%d]: attaching to representative LWP\n", getPid());
3035
3036    if( !getRepresentativeLWP()->attach()) {
3037       fprintf(stderr, "%s[%d]:  failed to attach to rep lwp\n", FILE__, __LINE__);
3038       return false;
3039    }
3040
3041    while (lwp_iter.next(index, lwp)) {
3042        startup_printf("[%d]: attaching to LWP %d\n", getPid(), index);
3043
3044       if (!lwp->attach()) {
3045          deleteLWP(lwp);
3046          return false;
3047       }
3048    }
3049    // Fork calls attach() but is probably past this; silencing warning
3050    if (!reachedBootstrapState(attached_bs))
3051        setBootstrapState(attached_bs);
3052    sh->signalActiveProcess();
3053    startup_printf("[%d]: setting process flags\n", getPid());
3054    return setProcessFlags();
3055 }
3056
3057
3058 // Callback: finish mutator-side processing for dyninst lib
3059
3060 bool process::finalizeDyninstLib() 
3061 {
3062    startup_printf("%s[%d]:  isAttached() = %s\n", __FILE__, __LINE__, isAttached() ? "true" : "false");
3063    startup_printf("%s[%d]: %s\n", __FILE__, __LINE__, getStatusAsString().c_str());
3064    
3065     assert (isStopped());
3066     if (reachedBootstrapState(bootstrapped_bs)) {
3067         return true;
3068     }
3069
3070    DYNINST_bootstrapStruct bs_record;
3071    if (!extractBootstrapStruct(&bs_record))
3072       assert(false);
3073
3074    // Read the structure; if event 0 then it's undefined! (not yet written)
3075    if (bs_record.event == 0)
3076    {
3077        startup_printf("[%s:%u] - bs_record.event is undefined\n", FILE__, __LINE__);
3078        return false;
3079    }
3080
3081    // Now that we have the dyninst library loaded, insert the hooks to dlopen/dlclose
3082    // (which may require the dyninst library)
3083     
3084    assert(bs_record.event == 1 || bs_record.event == 2 || bs_record.event==3);
3085
3086    bool calledFromFork = (bs_record.event == 2);
3087    bool calledFromAttach = (bs_record.event == 3);
3088
3089    pdvector<int_variable *> obsCostVec;
3090    if (!findVarsByAll("DYNINSTobsCostLow", obsCostVec))
3091        assert(0);
3092    assert(obsCostVec.size() == 1);
3093
3094    costAddr_ = obsCostVec[0]->getAddress();
3095
3096    assert(costAddr_);
3097
3098    // Set breakpoints to detect (un)loaded libraries
3099    // Do this after the observed cost is set, in case we use instrumentation
3100    if (!dyn->installTracing()) assert (0 && "Failed to install library mapping hooks");
3101
3102    if (!calledFromFork) {
3103
3104        // Install initial instrumentation requests
3105        pdstring str=pdstring("PID=") + pdstring(bs_record.pid) + ", installing default (DYNINST) inst...";
3106        statusLine(str.c_str());
3107        
3108        extern pdvector<instMapping*> initialRequests; // init.C
3109
3110        // Install any global instrumentation requests
3111        installInstrRequests(initialRequests);
3112
3113        // Install process-specific instrumentation requests
3114        installInstrRequests(tracingRequests);
3115        
3116        // Install our system call tracing
3117        tracedSyscalls_ = new syscallNotification(this);
3118
3119        //#ifdef i386_unknown_linux2_0
3120        //if(pdFlavor != "mpi") {
3121        //#endif
3122           // TODO: prefork and pre-exit should depend on whether a callback is defined
3123           if (!tracedSyscalls_->installPreFork()) 
3124              cerr << "Warning: failed pre-fork notification setup" << endl;
3125           if (!tracedSyscalls_->installPostFork()) 
3126              cerr << "Warning: failed post-fork notification setup" << endl;
3127           if (!tracedSyscalls_->installPreExec()) 
3128              cerr << "Warning: failed pre-exec notification setup" << endl;
3129           if (!tracedSyscalls_->installPostExec()) 
3130              cerr << "Warning: failed post-exec notification setup" << endl;
3131           if (!tracedSyscalls_->installPreExit()) 
3132              cerr << "Warning: failed pre-exit notification setup" << endl;
3133           if (!tracedSyscalls_->installPreLwpExit()) 
3134              cerr << "Warning: failed pre-lwp-exit notification setup" << endl;
3135           //#ifdef i386_unknown_linux2_0
3136           //}
3137           //#endif
3138    }
3139    else { // called from a forking process
3140        process *parentProcess = process::findProcess(bs_record.ppid);
3141        if (parentProcess) {
3142            if (parentProcess->status() == stopped) {
3143                if (!parentProcess->continueProc())
3144                    assert(false);
3145            }
3146            else
3147                parentProcess->continueAfterNextStop();
3148        }
3149        
3150    }
3151
3152    startup_printf("Initializing tramp guard\n");
3153    if (!initTrampGuard())
3154       assert(0);
3155
3156 #if defined(cap_threads)
3157    if (multithread_capable())
3158    {
3159       initMT();
3160    }
3161 #endif
3162
3163    if (!calledFromAttach) {
3164        pdstring str=pdstring("PID=") + pdstring(bs_record.pid) + ", dyninst ready.";
3165        statusLine(str.c_str());
3166    }
3167
3168    startup_printf("%s[%d]:  bootstrap done\n", __FILE__, __LINE__);
3169    // Ready to rock
3170    setBootstrapState(bootstrapped_bs);
3171    sh->signalEvent(evtProcessInitDone);
3172
3173    return true;
3174 }
3175
3176 void finalizeDyninstLibWrapper(process *p) 
3177 {
3178   global_mutex->_Lock(FILE__, __LINE__);
3179   p->finalizeDyninstLib();
3180   global_mutex->_Unlock(FILE__, __LINE__);
3181 }
3182 void process::DYNINSTinitCompletionCallback(process* theProc,
3183                                             unsigned /* rpc_id */,
3184                                             void* /*userData*/, // user data
3185                                             void* /*ret*/) // return value from DYNINSTinit
3186 {
3187     //global_mutex->_Lock(FILE__, __LINE__);
3188     startup_printf("%s[%d]:  about to finalize Dyninst Lib\n", __FILE__, __LINE__);
3189     theProc->finalizeDyninstLib();
3190     //FinalizeRTLibCallback *cbp = new FinalizeRTLibCallback(finalizeDyninstLibWrapper);
3191     //FinalizeRTLibCallback &cb = *cbp;
3192     //cb.setSynchronous(false);
3193     //cb(theProc);
3194     //global_mutex->_Unlock(FILE__, __LINE__);
3195 }
3196 /////////////////////////////////////////
3197 // Function lookup...
3198 /////////////////////////////////////////
3199
3200 bool process::findFuncsByAll(const pdstring &funcname,
3201                              pdvector<int_function *> &res,
3202                              const pdstring &libname) { // = "", btw
3203     
3204     unsigned starting_entries = res.size(); // We'll return true if we find something
3205     for (unsigned i = 0; i < mapped_objects.size(); i++) {
3206         if (libname == "" ||
3207             mapped_objects[i]->fileName() == libname ||
3208             mapped_objects[i]->fullName() == libname) {
3209             const pdvector<int_function *> *pretty = mapped_objects[i]->findFuncVectorByPretty(funcname);
3210             if (pretty) {
3211                 // We stop at first match...
3212                 for (unsigned pm = 0; pm < pretty->size(); pm++) {
3213                     res.push_back((*pretty)[pm]);
3214                 }
3215             }
3216             else {
3217                 const pdvector<int_function *> *mangled = mapped_objects[i]->findFuncVectorByMangled(funcname);
3218                 if (mangled) {
3219                     for (unsigned mm = 0; mm < mangled->size(); mm++) {
3220                         res.push_back((*mangled)[mm]);
3221                     }
3222                 }
3223             }
3224         }
3225     }
3226     return (res.size() != starting_entries);
3227 }
3228
3229
3230 bool process::findFuncsByPretty(const pdstring &funcname,
3231                              pdvector<int_function *> &res,
3232                              const pdstring &libname) { // = "", btw
3233
3234     unsigned starting_entries = res.size(); // We'll return true if we find something
3235
3236     for (unsigned i = 0; i < mapped_objects.size(); i++) {
3237         if (libname == "" ||
3238             mapped_objects[i]->fileName() == libname ||
3239             mapped_objects[i]->fullName() == libname) {
3240             const pdvector<int_function *> *pretty = mapped_objects[i]->findFuncVectorByPretty(funcname);
3241             if (pretty) {
3242                 // We stop at first match...
3243                 for (unsigned pm = 0; pm < pretty->size(); pm++) {
3244                     res.push_back((*pretty)[pm]);
3245                 }
3246             }
3247         }
3248     }
3249     return res.size() != starting_entries;
3250 }
3251
3252
3253 bool process::findFuncsByMangled(const pdstring &funcname,
3254                                  pdvector<int_function *> &res,
3255                                  const pdstring &libname) { // = "", btw
3256     unsigned starting_entries = res.size(); // We'll return true if we find something
3257
3258     for (unsigned i = 0; i < mapped_objects.size(); i++) {
3259         if (libname == "" ||
3260             mapped_objects[i]->fileName() == libname ||
3261             mapped_objects[i]->fullName() == libname) {
3262             const pdvector<int_function *> *mangled = 
3263                mapped_objects[i]->findFuncVectorByMangled(funcname);
3264             if (mangled) {
3265                 for (unsigned mm = 0; mm < mangled->size(); mm++) {
3266                    res.push_back((*mangled)[mm]);
3267                 }
3268             }
3269         }
3270     }
3271     return res.size() != starting_entries;
3272 }
3273
3274 int_function *process::findOnlyOneFunction(const pdstring &name,
3275                                            const pdstring &lib) 
3276 {
3277     pdvector<int_function *> allFuncs;
3278     if (!findFuncsByAll(name, allFuncs, lib))
3279         return NULL;
3280     if (allFuncs.size() > 1) {
3281         cerr << "Warning: multiple matches for " << name << ", returning first" << endl;
3282     }
3283     return allFuncs[0];
3284 }
3285
3286 /////////////////////////////////////////
3287 // Variable lookup...
3288 /////////////////////////////////////////
3289
3290 bool process::findVarsByAll(const pdstring &varname,
3291                             pdvector<int_variable *> &res,
3292                             const pdstring &libname) { // = "", btw
3293     unsigned starting_entries = res.size(); // We'll return true if we find something
3294     
3295     for (unsigned i = 0; i < mapped_objects.size(); i++) {
3296         if (libname == "" ||
3297             mapped_objects[i]->fileName() == libname ||
3298             mapped_objects[i]->fullName() == libname) {
3299             const pdvector<int_variable *> *pretty = mapped_objects[i]->findVarVectorByPretty(varname);
3300             if (pretty) {
3301                 // We stop at first match...
3302                 for (unsigned pm = 0; pm < pretty->size(); pm++) {
3303                     res.push_back((*pretty)[pm]);
3304                 }
3305             }
3306             else {
3307                 const pdvector<int_variable *> *mangled = mapped_objects[i]->findVarVectorByMangled(varname);
3308                 if (mangled) {
3309                     for (unsigned mm = 0; mm < mangled->size(); mm++) {
3310                         res.push_back((*mangled)[mm]);
3311                     }
3312                 }
3313             }
3314         }
3315     }
3316
3317     return res.size() != starting_entries;
3318 }
3319
3320
3321
3322 // Get me a pointer to the instruction: the return is a local
3323 // (mutator-side) store for the mutatee. This may duck into the local
3324 // copy for images, or a relocated function's self copy.
3325 // TODO: is this really worth it? Or should we just use ptrace?
3326
3327 void *process::getPtrToInstruction(Address addr) {
3328     codeRange *range;
3329     if (codeSections_.find(addr, range)) {
3330         return range->getPtrToInstruction(addr);
3331     }
3332     else if (dataSections_.find(addr, range)) {
3333         mappedObjData *data = dynamic_cast<mappedObjData *>(range);
3334         assert(data);
3335         return data->obj->getPtrToData(addr);
3336     }
3337     return NULL;
3338 }
3339
3340 bool process::isValidAddress(Address addr) {
3341     // "Is this part of the process address space?"
3342     // We should codeRange data sections as well... since we don't, this is 
3343     // slow.
3344     codeRange *dontcare;
3345     if (codeSections_.find(addr, dontcare))
3346         return true;
3347     if (dataSections_.find(addr, dontcare))
3348         return true;
3349     fprintf(stderr, "Warning: address 0x%x not valid!\n",
3350             addr);
3351     return false;
3352 }        
3353
3354 dyn_thread *process::STdyn_thread() { 
3355    assert(! multithread_capable());
3356    assert(threads.size()>0);
3357    return threads[0];
3358 }
3359
3360 #if !defined(BPATCH_LIBRARY)
3361 void process::processCost(unsigned obsCostLow,
3362                           timeStamp wallTime,
3363                           timeStamp processTime) {
3364   // wallTime and processTime should compare to DYNINSTgetWallTime() and
3365   // DYNINSTgetCPUtime().
3366
3367   // check for overflow, add to running total, convert cycles to seconds, and
3368   // report.  Member vrbles of class process: lastObsCostLow and cumulativeObsCost
3369   // (the latter a 64-bit value).
3370
3371   // code to handle overflow used to be in rtinst; we borrow it pretty much
3372   // verbatim. (see rtinst/RTposix.c)
3373   if (obsCostLow < lastObsCostLow) {
3374     // we have a wraparound
3375     cumulativeObsCost += ((unsigned)0xffffffff - lastObsCostLow) + obsCostLow + 1;
3376   }
3377   else
3378     cumulativeObsCost += (obsCostLow - lastObsCostLow);
3379   
3380   lastObsCostLow = obsCostLow;
3381   //  sampleVal_cerr << "processCost- cumulativeObsCost: " << cumulativeObsCost << "\n"; 
3382   timeLength observedCost((int64_t) cumulativeObsCost, getCyclesPerSecond());
3383   // timeUnit tu = getCyclesPerSecond(); // just used to print out
3384   //  sampleVal_cerr << "processCost: cyclesPerSecond=" << tu
3385   //             << "; cum obs cost=" << observedCost << "\n";
3386   
3387   // Notice how most of the rest of this is copied from processCost() of
3388   // metric.C.  Be sure to keep the two "in sync"!
3389
3390   extern costMetric *totalPredictedCost; // init.C
3391   extern costMetric *observed_cost;      // init.C
3392   
3393   const timeStamp lastProcessTime = 
3394     totalPredictedCost->getLastSampleProcessTime(this);
3395   //  sampleVal_cerr << "processCost- lastProcessTime: " <<lastProcessTime << "\n";
3396   // find the portion of uninstrumented time for this interval
3397   timeLength userPredCost = timeLength::sec() + getCurrentPredictedCost();
3398   //  sampleVal_cerr << "processCost- userPredCost: " << userPredCost << "\n";
3399   const double unInstTime = (processTime - lastProcessTime) / userPredCost; 
3400   //  sampleVal_cerr << "processCost- unInstTime: " << unInstTime << "\n";
3401   // update predicted cost
3402   // note: currentPredictedCost is the same for all processes
3403   //       this should be changed to be computed on a per process basis
3404   pdSample newPredCost = totalPredictedCost->getCumulativeValue(this);
3405   //  sampleVal_cerr << "processCost- newPredCost: " << newPredCost << "\n";
3406   timeLength tempPredCost = getCurrentPredictedCost() * unInstTime;
3407   //  sampleVal_cerr << "processCost- tempPredCost: " << tempPredCost << "\n";
3408   newPredCost += pdSample(tempPredCost.getI(timeUnit::ns()));
3409   //  sampleVal_cerr << "processCost- tempPredCost: " << newPredCost << "\n";
3410   totalPredictedCost->updateValue(this, wallTime, newPredCost, processTime);
3411   // update observed cost
3412   pdSample sObsCost(observedCost);
3413   observed_cost->updateValue(this, wallTime, sObsCost, processTime);
3414 }
3415 #endif
3416         
3417 // If true is passed for ignore_if_mt_not_set, then an error won't be
3418 // initiated if we're unable to determine if the program is multi-threaded.
3419 // We are unable to determine this if the daemon hasn't yet figured out what
3420 // libraries are linked against the application.  Currently, we identify an
3421 // application as being multi-threaded if it is linked against a thread
3422 // library (eg. libpthreads.a on AIX).  There are cases where we are querying
3423 // whether the app is multi-threaded, but it can't be determined yet but it
3424 // also isn't necessary to know.
3425 bool process::multithread_capable(bool ignore_if_mt_not_set)
3426 {
3427 #if !defined(cap_threads)
3428    return false;
3429 #endif
3430
3431    if(cached_result != not_cached) {
3432        if(cached_result == cached_mt_true) {
3433            return true;
3434        } else {
3435            assert(cached_result == cached_mt_false);
3436            return false;
3437        }
3438    }
3439    
3440    if(mapped_objects.size() <= 1) {
3441        if(! ignore_if_mt_not_set) {
3442            cerr << "   can't query MT state, assert\n";
3443            assert(false);
3444        }
3445        return false;
3446    }
3447
3448    if(findObject("libthread.so*", true) ||  // Solaris
3449       findObject("libpthreads.*", true)  ||  // AIX
3450       findObject("libpthread.so*", true))   // Linux
3451    {
3452        cached_result = cached_mt_true;
3453        return true;
3454    } else {
3455        cached_result = cached_mt_false;
3456        return false;
3457    }
3458 }
3459
3460 void process::addThread(dyn_thread *thread)
3461 {
3462    getRpcMgr()->addThread(thread);
3463    threads.push_back(thread);
3464 }
3465
3466 bool process::multithread_ready(bool ignore_if_mt_not_set) {
3467    if (!multithread_capable(ignore_if_mt_not_set))
3468       return false;
3469    return isBootstrappedYet();
3470 }
3471
3472 dyn_lwp *process::query_for_stopped_lwp() {
3473    dyn_lwp *foundLWP = NULL;
3474    dictionary_hash_iter<unsigned, dyn_lwp *> lwp_iter(real_lwps);
3475    dyn_lwp *lwp;
3476    unsigned index;
3477
3478    if(IndependentLwpControl()) {
3479       while (lwp_iter.next(index, lwp)) {
3480          if(lwp->status() == stopped || lwp->status() == neonatal) {
3481             foundLWP = lwp;
3482             break;
3483          }
3484       }
3485       if(foundLWP == NULL  &&  getRepresentativeLWP() != NULL) {
3486          if(getRepresentativeLWP()->status() == stopped ||
3487             getRepresentativeLWP()->status() == neonatal)
3488             foundLWP = getRepresentativeLWP();
3489       }
3490    } else {
3491       if(this->status() == stopped || this->status() == neonatal) {
3492          foundLWP = getRepresentativeLWP();
3493       }
3494    }
3495
3496    return foundLWP;
3497 }
3498
3499 dyn_lwp *process::query_for_running_lwp() 
3500 {
3501    dyn_lwp *foundLWP = NULL;
3502    dictionary_hash_iter<unsigned, dyn_lwp *> lwp_iter(real_lwps);
3503    dyn_lwp *lwp;
3504    unsigned index;
3505
3506    if(IndependentLwpControl()) {
3507       while (lwp_iter.next(index, lwp)) {
3508          if (!lwp) continue;
3509          if(lwp->status() == running || lwp->status() == neonatal) {
3510             foundLWP = lwp;
3511             break;
3512          }
3513       }
3514       if(foundLWP == NULL  &&  getRepresentativeLWP() != NULL) {
3515          if(getRepresentativeLWP()->status() == running ||
3516             getRepresentativeLWP()->status() == neonatal)
3517             foundLWP = getRepresentativeLWP();
3518       }
3519    } else {
3520       if(this->status() == running || this->status() == neonatal) {
3521          foundLWP = getRepresentativeLWP();
3522       }
3523    }
3524
3525    return foundLWP;
3526 }
3527
3528 // first searches for stopped lwp and if not found explicitly stops an lwp
3529 dyn_lwp *process::stop_an_lwp(bool *wasRunning) {
3530    dictionary_hash_iter<unsigned, dyn_lwp *> lwp_iter(real_lwps);
3531    dyn_lwp *lwp;
3532    dyn_lwp *stopped_lwp = NULL;
3533    unsigned index;
3534    if (!isAttached()) {
3535      fprintf(stderr, "%s[%d]:  cannot stop_an_lwp, process not attached\n", FILE__, __LINE__);
3536      return false;
3537    }
3538
3539    if(IndependentLwpControl()) {
3540       while(lwp_iter.next(index, lwp)) {
3541          if(lwp->status() == stopped) {
3542             stopped_lwp = lwp;
3543             *wasRunning = false;
3544             break;
3545          }
3546          if(lwp->pauseLWP()) {
3547             stopped_lwp = lwp;
3548             *wasRunning = true;
3549             break;
3550          }
3551       }
3552       if(stopped_lwp == NULL) {
3553           assert(getRepresentativeLWP());
3554          if(getRepresentativeLWP()->status() == stopped) {
3555             *wasRunning = false;
3556          } else {
3557             getRepresentativeLWP()->pauseLWP();
3558             *wasRunning = true;
3559          }
3560          stopped_lwp = getRepresentativeLWP();
3561       }
3562    } else {
3563       if(getRepresentativeLWP()->status() == stopped)
3564          *wasRunning = false;
3565       else {
3566          getRepresentativeLWP()->pauseLWP();
3567          *wasRunning = true;
3568       }
3569       stopped_lwp = getRepresentativeLWP();
3570    }
3571
3572    if (!stopped_lwp) {
3573      fprintf(stderr, "%s[%d][%s]:  stop_an_lwp failing\n", FILE__, __LINE__, getThreadStr(getExecThreadID()));
3574    }
3575    return stopped_lwp;
3576 }
3577
3578 bool process::terminateProc() 
3579 {
3580    if(status() == exited || status() == deleted || !sh->isRunning()) {
3581      // "Sure, we terminated it... really!"
3582      return true;
3583    }
3584    terminateProcStatus_t retVal = terminateProc_();
3585
3586    switch (retVal) {
3587    case terminateSucceeded:
3588      {
3589      // handle the kill signal on the process, which will dispatch exit callback
3590       signal_printf("%s[%d][%s]:  before waitForEvent(evtProcessExit)\n", 
3591               FILE__, __LINE__, getThreadStr(getExecThreadID()));
3592       fprintf(stderr, "%s[%d]:  waiting for evtProcessExit, lock depth is %d\n", FILE__, __LINE__, global_mutex->depth());
3593
3594
3595       // Let it run so we can see it die...      
3596       set_status(running);
3597
3598       if (getExecThreadID() != sh->getThreadID()) {
3599           signal_printf("%s[%d][%s]:  signalling active process\n", 
3600                         FILE__, __LINE__, getThreadStr(getExecThreadID()));
3601           sh->signalActiveProcess();
3602       }
3603
3604       sh->waitForEvent(evtProcessExit);
3605      return true;
3606      }
3607      break;
3608    case alreadyTerminated:
3609      // don't try to consume a signal (since we can't), 
3610      // just set process status to exited
3611      set_status(exited);
3612      return true;
3613      break;
3614    case terminateFailed:
3615      return false;
3616      break;
3617
3618    }
3619    assert (0 && "Can't be reached");
3620    return false;
3621 }
3622
3623 /*
3624  * Copy data from controller process to the named process.
3625  */
3626 bool process::writeDataSpace(void *inTracedProcess, unsigned size,
3627                              const void *inSelf) {
3628    bool needToCont = false;
3629
3630    //fprintf(stderr, "writeDataSpace to %p to %p, %d\n",
3631    //inTracedProcess, (int)inTracedProcess+size, size);
3632
3633    if (!isAttached()) return false;
3634
3635    dyn_lwp *stopped_lwp = query_for_stopped_lwp();
3636    if(stopped_lwp == NULL) {
3637       stopped_lwp = stop_an_lwp(&needToCont);
3638       if(stopped_lwp == NULL) {
3639          pdstring msg =
3640             pdstring("System error: unable to write to process data "
3641                      "space (WDS): couldn't stop an lwp\n");
3642          fprintf(stderr, "%s[%d]:  stop_an_lwp failed\n", __FILE__, __LINE__);
3643          showErrorCallback(38, msg);
3644          return false;
3645       }
3646    }
3647    
3648    bool res = stopped_lwp->writeDataSpace(inTracedProcess, size, inSelf);
3649    if (!res) {
3650        fprintf(stderr, "WDS: %d bytes from %p to %p, lwp %p\n",
3651                size, inSelf, inTracedProcess, stopped_lwp);
3652        cerr << endl;
3653        pdstring msg = pdstring("System error: unable to write to process data "
3654                                "space (WDS):") + pdstring(strerror(errno));
3655          fprintf(stderr, "%s[%d]:  wds failed\n", __FILE__, __LINE__);
3656        showErrorCallback(38, msg);
3657        return false;
3658    }
3659
3660    if(needToCont) {
3661       return stopped_lwp->continueLWP();
3662    }