Sets the brk pointer for save-the-world binaries to what it was when each
[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.566 2006/01/13 00:00:47 jodom 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)
322 {
323   pdvector<Frame> stackWalk;
324   if (!threads.size()) { // Nothing defined in thread data structures
325     if (!getRepresentativeLWP()->walkStack(stackWalk))
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))
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    unsigned int trampGuardValue;
878    Address guardFlagAddr= trampGuardBase();
879
880    unsigned int pageSize = getpagesize();
881    unsigned int startPage, stopPage;
882    unsigned int numberUpdates=1;
883    int startIndex, stopIndex;
884    char *data;
885    char name[50];
886 #if defined(sparc_sun_solaris2_4) \
887  || defined(i386_unknown_linux2_0) \
888  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
889         writeBackElf *newFile = (writeBackElf*) ptr;
890 #elif defined(rs6000_ibm_aix4_1)
891         writeBackXCOFF *newFile = (writeBackXCOFF*) ptr;
892
893 #endif
894
895 #if 0
896         /*fprintf(stderr,"guardFlagAddr %x\n",guardFlagAddr);*/
897         readDataSpace((void*) guardFlagAddr, sizeof(unsigned int),
898                  (void*) &trampGuardValue, true);
899    
900         bool err = writeDataSpace((void*)guardFlagAddr, sizeof(unsigned int),
901                   (void*) &numberUpdates);
902         if (!err) fprintf(stderr, "%s[%d][%s]:  writeDataSpace failed\n", __FILE__, __LINE__, getThreadStr(getExecThreadID()));
903         assert(err);
904
905         saveWorldData((Address) guardFlagAddr,sizeof(unsigned int), &numberUpdates); //ccw 6 jul 2003
906 #endif
907
908         bool err;
909       sprintf(name,"dyninstAPItrampguard");
910
911         data = new char[sizeof(max_number_of_threads)];
912         memcpy(data, &max_number_of_threads,sizeof(max_number_of_threads));
913         //fprintf(stderr,"WRITING: max_number_of_threads %d\n",max_number_of_threads);
914         //ccw 14 dec 2005
915 #if defined(sparc_sun_solaris2_4) \
916  || defined(i386_unknown_linux2_0) \
917  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
918       newFile->addSection(guardFlagAddr,data,sizeof(max_number_of_threads),name,false);
919 #elif defined(rs6000_ibm_aix4_1)
920         newFile->addSection(name,guardFlagAddr,guardFlagAddr,sizeof(max_number_of_threads),data);
921 #endif
922         delete []data;
923
924
925
926    for(unsigned int j=0; j<compactedHighmemUpdates.size(); j++) {
927       //the layout of dyninstAPIhighmem_%08x is:
928       //pageData
929       //address of update
930       //size of update
931       // ...
932       //address of update
933       //size of update
934       //number of updates
935
936       startPage = compactedHighmemUpdates[j]->address - 
937                   compactedHighmemUpdates[j]->address % pageSize;
938       stopPage = compactedHighmemUpdates[j]->address + 
939                  compactedHighmemUpdates[j]->size -
940                  (compactedHighmemUpdates[j]->address + 
941                   compactedHighmemUpdates[j]->size) % pageSize;
942
943       numberUpdates = 0;
944       startIndex = -1;
945       stopIndex = -1;
946       
947       for(unsigned index = 0;index < highmem_updates.size(); index++){
948          //here we ignore anything with an address of zero.
949          //these can be safely deleted in writeBackElf
950          if( highmem_updates[index]->address && 
951              startPage <= highmem_updates[index]->address &&
952              highmem_updates[index]->address  < (startPage + pageSize /*compactedHighmemUpdates[j]->sizei*/)){
953             numberUpdates ++;
954             stopIndex = index;
955             if(startIndex == -1){
956                startIndex = index;
957             }
958            //bperr(" HighMemUpdates address 0x%x \n", highmem_updates[index]->address );
959          }
960         //bperr(" high mem updates: 0x%x", highmem_updates[index]->address);
961       }
962       unsigned int dataSize = compactedHighmemUpdates[j]->size + 
963          sizeof(unsigned int) + 
964          (2*(stopIndex - startIndex + 1) /*numberUpdates*/ * sizeof(unsigned int));
965
966         //bperr("DATASIZE: %x : %x + 4 + ( 2*(%x - %x +1) * 4)\n", dataSize, compactedHighmemUpdates[j]->size, stopIndex, startIndex);
967       
968       data = new char[dataSize];
969       
970       //fill in pageData
971       readDataSpace((void*) compactedHighmemUpdates[j]->address, 
972                     compactedHighmemUpdates[j]->size, data, true);
973       
974       unsigned int *dataPtr = 
975          (unsigned int*) ( (char*) data + compactedHighmemUpdates[j]->size);
976
977       //fill in address of update
978       //fill in size of update
979       for(int index = startIndex; index<=stopIndex;index++){ 
980
981          memcpy(dataPtr, &highmem_updates[index]->address,
982                 sizeof(unsigned int));
983          dataPtr ++;
984          memcpy(dataPtr, &highmem_updates[index]->size, sizeof(unsigned int));
985
986          dataPtr++;
987          //bperr("%d J %d ADDRESS: 0x%x SIZE 0x%x\n",index, j,
988          //highmem_updates[index]->address, highmem_updates[index]->size);
989
990         
991       }
992       //fill in number of updates
993       memcpy(dataPtr, &numberUpdates, sizeof(unsigned int));
994
995       //bperr(" NUMBER OF UPDATES 0x%x  %d %x\n\n",numberUpdates,dataSize,dataSize);
996       sprintf(name,"dyninstAPIhighmem_%08x",j);
997 #if defined(sparc_sun_solaris2_4) \
998  || defined(i386_unknown_linux2_0) \
999  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
1000       newFile->addSection(compactedHighmemUpdates[j]->address,data ,dataSize,name,false);
1001 #elif defined(rs6000_ibm_aix4_1)
1002           sprintf(name, "dyH_%03x",j);
1003       newFile->addSection(&(name[0]), compactedHighmemUpdates[j]->address,compactedHighmemUpdates[j]->address,
1004                 dataSize, (char*) data );
1005 #endif
1006       
1007       //lastCompactedUpdateAddress = compactedHighmemUpdates[j]->address+1;
1008       delete [] (char*) data;
1009    }
1010    err = writeDataSpace((void*)guardFlagAddr, sizeof(unsigned int), 
1011                   (void*)&trampGuardValue);
1012    if (!err) fprintf(stderr, "%s[%d][%s]:  writeDataSpace failed\n", __FILE__, __LINE__, getThreadStr(getExecThreadID()));
1013         assert(err);
1014 }
1015
1016 void process::saveWorldCreateDataSections(void* ptr){
1017
1018 #if defined(sparc_sun_solaris2_4) \
1019  || defined(i386_unknown_linux2_0) \
1020  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
1021         writeBackElf *newFile = (writeBackElf*) ptr;
1022 #elif defined(rs6000_ibm_aix4_1)
1023         writeBackXCOFF *newFile = (writeBackXCOFF*) ptr;
1024 #endif
1025
1026         char *dataUpdatesData;
1027         int sizeofDataUpdatesData=0;
1028         for(unsigned int m=0;m<dataUpdates.size();m++){
1029                 sizeofDataUpdatesData += (sizeof(int) + sizeof(Address)); //sizeof(size) +sizeof(Address);
1030                 sizeofDataUpdatesData += dataUpdates[m]->size;
1031         }
1032
1033
1034         if(dataUpdates.size() > 0) {
1035                 dataUpdatesData = new char[sizeofDataUpdatesData+(sizeof(int) + sizeof(Address))];
1036                 char* ptr = dataUpdatesData;
1037                 for(unsigned int k=0;k<dataUpdates.size();k++){
1038                         memcpy(ptr, &dataUpdates[k]->size, sizeof(int));
1039                         ptr += sizeof(int);
1040                         memcpy(ptr, &dataUpdates[k]->address, sizeof(Address));
1041                         ptr+=sizeof(Address);
1042                         memcpy(ptr, dataUpdates[k]->value, dataUpdates[k]->size);
1043                         ptr+=dataUpdates[k]->size;
1044                         /*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);*/
1045
1046                 }
1047                 *(int*) ptr=0;
1048                 ptr += sizeof(int);
1049                 *(unsigned int*) ptr=0;
1050 #if defined(sparc_sun_solaris2_4) \
1051  || defined(i386_unknown_linux2_0) \
1052  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
1053                 newFile->addSection(0/*lastCompactedUpdateAddress*/, dataUpdatesData, 
1054                         sizeofDataUpdatesData + (sizeof(int) + sizeof(Address)), "dyninstAPI_data", false);
1055 #elif defined(rs6000_ibm_aix4_1)
1056                 newFile->addSection("dyn_dat", 0/*lastCompactedUpdateAddress*/,0,
1057                         sizeofDataUpdatesData + (sizeof(int) + sizeof(Address)), (char*) dataUpdatesData);
1058
1059 #endif
1060
1061                 delete [] (char*) dataUpdatesData;
1062         }
1063
1064 }
1065 #endif
1066
1067 #if defined(sparc_sun_solaris2_4) \
1068  || defined(i386_unknown_linux2_0) \
1069  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */ \
1070  || defined(rs6000_ibm_aix4_1)
1071
1072 void process::saveWorldAddSharedLibs(void *ptr){ // ccw 14 may 2002 
1073
1074         int dataSize=0;
1075         char *data, *dataptr;
1076 #if defined(sparc_sun_solaris2_4) \
1077  || defined(i386_unknown_linux2_0) \
1078  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
1079         writeBackElf *newFile = (writeBackElf*) ptr;
1080 #elif defined(rs6000_ibm_aix4_1)
1081         writeBackXCOFF *newFile = (writeBackXCOFF*) ptr;
1082 #endif
1083
1084         for(unsigned i=0;i<loadLibraryUpdates.size();i++){
1085                 dataSize += loadLibraryUpdates[i].length() + 1 + sizeof(void *);
1086         }
1087         dataSize++;
1088         data = new char[dataSize];
1089         dataptr = data;
1090         /*bperr(" dataSize: %d\n", dataSize);*/
1091
1092         for(unsigned j=0;j<loadLibraryUpdates.size();j++){
1093                 memcpy( dataptr, loadLibraryUpdates[j].c_str(), loadLibraryUpdates[j].length()); 
1094
1095                 /*bperr("SAVING: %s %d\n", dataptr,dataSize);*/
1096                 dataptr += loadLibraryUpdates[j].length();
1097                 *dataptr = '\0';
1098                 dataptr++;
1099                 void *tmp_brk = loadLibraryBRKs[j];
1100                 memcpy( dataptr, &tmp_brk, sizeof(void *));
1101                 dataptr += sizeof(void *);
1102         }
1103         *dataptr = '\0'; //mark the end
1104         if(dataSize > 1){
1105 #if defined(sparc_sun_solaris2_4) \
1106  || defined(i386_unknown_linux2_0) \
1107  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
1108                 newFile->addSection(0, data, dataSize, "dyninstAPI_loadLib", false);
1109 #elif  defined(rs6000_ibm_aix4_1)
1110                 newFile->addSection("dyn_lib",0,0, dataSize, data);
1111 #endif
1112         }
1113         delete [] data;
1114 }
1115
1116 #endif
1117
1118
1119 /*
1120  * Given an image, add all static heaps inside it
1121  * (DYNINSTstaticHeap...) to the buffer pool.
1122  */
1123
1124 void process::addInferiorHeap(const mapped_object *obj)
1125 {
1126     //fprintf(stderr, "Adding inferior heaps in %s\n", obj->fileName().c_str());
1127   pdvector<heapDescriptor> infHeaps;
1128   /* Get a list of inferior heaps in the new image */
1129   if (getInfHeapList(obj, infHeaps))
1130     {
1131       /* Add the vector to the inferior heap structure */
1132         for (u_int j=0; j < infHeaps.size(); j++)
1133         {
1134 #ifdef DEBUG
1135             fprintf(stderr, "Adding heap at 0x%x to 0x%x, name %s\n",
1136                     infHeaps[j].addr(),
1137                     infHeaps[j].addr() + infHeaps[j].size(),
1138                     infHeaps[j].name().c_str());
1139 #endif
1140 #if defined(arch_power)
1141             // MT: I've seen problems writing into a "found" heap that
1142             // is in the application heap (IE a dlopen'ed
1143             // library). Since we don't have any problems getting
1144             // memory there, I'm skipping any heap that is in 0x2.....
1145             
1146             if ((infHeaps[j].addr() > 0x20000000) &&
1147                 (infHeaps[j].addr() < 0xd0000000) &&
1148                 (infHeaps[j].type() == uncopiedHeap))
1149                 continue;
1150 #endif            
1151
1152             heapItem *h = new heapItem (infHeaps[j].addr(), infHeaps[j].size(),
1153                                         infHeaps[j].type(), false);
1154             heap.bufferPool.push_back(h);
1155             heapItem *h2 = new heapItem(h);
1156             h2->status = HEAPfree;
1157             heap.heapFree.push_back(h2);
1158             heap.totalFreeMemAvailable += h2->length;
1159         }
1160     }
1161   
1162 }
1163
1164
1165 /*
1166  * Called to (re)initialize the static inferior heap structure.
1167  * To incrementally add a static inferior heap (in a dlopen()d module,
1168  * for example), use addInferiorHeap(image *)
1169  */
1170 void process::initInferiorHeap()
1171 {
1172   // (re)initialize everything 
1173     heap.heapActive.clear();
1174     heap.heapFree.resize(0);
1175     heap.disabledList.resize(0);
1176     heap.disabledListTotalMem = 0;
1177     heap.freed = 0;
1178     heap.totalFreeMemAvailable = 0;
1179
1180     // first initialization: add static heaps to pool
1181     for (unsigned i = 0; i < mapped_objects.size(); i++) {
1182         addInferiorHeap(mapped_objects[i]);
1183     }
1184
1185     heapInitialized_ = true;
1186 }
1187
1188 bool process::initTrampGuard()
1189 {
1190   // This is slightly funky. Dyninst does not currently support
1191   // multiple threads -- so it uses a single tramp guard flag, 
1192   // which resides in the runtime library. However, this is not
1193   // enough for MT paradyn. So Paradyn overrides this setting as 
1194   // part of its initialization.
1195     const pdstring vrbleName = "DYNINST_tramp_guards";
1196     pdvector<int_variable *> vars;
1197     if (!findVarsByAll(vrbleName, vars)) 
1198     {
1199         return false;
1200     }
1201     assert(vars.size() == 1);
1202
1203     readDataSpace((void *) vars[0]->getAddress(), sizeof(Address), &trampGuardBase_, 
1204                   true);
1205     return true;
1206 }
1207
1208 // create a new inferior heap that is a copy of src. This is used when a process
1209 // we are tracing forks.
1210 inferiorHeap::inferiorHeap(const inferiorHeap &src):
1211     heapActive(addrHash16)
1212 {
1213     for (unsigned u1 = 0; u1 < src.heapFree.size(); u1++) {
1214       heapFree.push_back(new heapItem(src.heapFree[u1]));
1215     }
1216
1217     pdvector<heapItem *> items = src.heapActive.values();
1218     for (unsigned u2 = 0; u2 < items.size(); u2++) {
1219       heapActive[items[u2]->addr] = new heapItem(items[u2]);
1220     }
1221     
1222     for (unsigned u3 = 0; u3 < src.disabledList.size(); u3++) {
1223       disabledList.push_back(src.disabledList[u3]);
1224     }
1225
1226     for (unsigned u4 = 0; u4 < src.bufferPool.size(); u4++) {
1227       bufferPool.push_back(new heapItem(src.bufferPool[u4]));
1228     }
1229
1230     disabledListTotalMem = src.disabledListTotalMem;
1231     totalFreeMemAvailable = src.totalFreeMemAvailable;
1232     freed = 0;
1233 }
1234
1235 //
1236 // This function will return the index corresponding to the next position
1237 // available in heapFree.
1238 //
1239 int process::findFreeIndex(unsigned size, int type, Address lo, Address hi)
1240 {
1241     // type is a bitmask: match on any bit in the mask
1242   pdvector<heapItem *> &freeList = heap.heapFree;
1243
1244   int best = -1;
1245   for (unsigned i = 0; i < freeList.size(); i++) {
1246       heapItem *h = freeList[i];
1247       // check if free block matches allocation constraints
1248       // Split out to facilitate debugging
1249       if (h->addr >= lo &&
1250           (h->addr + size - 1) <= hi &&
1251           h->length >= size &&
1252           h->type & type) {
1253           if (best == -1)
1254               best = i;
1255           // check for better match
1256           if (h->length < freeList[best]->length) best = i;
1257       }
1258   }
1259   return best;
1260 }  
1261
1262 //
1263 // dynamic inferior heap stuff
1264 //
1265 #if defined(USES_DYNAMIC_INF_HEAP)
1266 #define HEAP_DYN_BUF_SIZE (0x100000)
1267 // "imd_rpc_ret" = Inferior Malloc Dynamic RPC RETurn structure
1268 typedef struct {
1269   bool ready;
1270   void *result;
1271 } imd_rpc_ret;
1272
1273 bool inferiorMallocCallbackFlag = false;
1274 void process::inferiorMallocCallback(process * /*p proc*/, unsigned /* rpc_id */,
1275                                      void *data, void *result)
1276 {
1277   global_mutex->_Lock(__FILE__, __LINE__);
1278   inferiorrpc_printf("%s[%d]:  inside inferior malloc callback\n", __FILE__, __LINE__);
1279   imd_rpc_ret *ret = (imd_rpc_ret *)data;
1280   ret->result = result;
1281   ret->ready = true;
1282   inferiorMallocCallbackFlag = true;
1283   global_mutex->_Unlock(__FILE__, __LINE__);
1284 }
1285
1286 void alignUp(int &val, int align)
1287 {
1288   assert(val >= 0);
1289   assert(align >= 0);
1290
1291   if (val % align != 0) {
1292     val = ((val / align) + 1) * align;
1293   }
1294 }
1295
1296 // dynamically allocate a new inferior heap segment using inferiorRPC
1297 void process::inferiorMallocDynamic(int size, Address lo, Address hi)
1298 {
1299    /* 03/07/2001 - Jeffrey Shergalis TODO: This code was placed to prevent
1300     * the infinite recursion on the call to inferiorMallocDynamic,
1301     * unfortunately it makes paradyn break on Irix, temporarily fixed by the
1302     * #if !defined(mips..., but should be properly fixed in the future, just
1303     * no time now
1304     */
1305    inferiorrpc_printf("%s[%d]:  welcome to inferiorMallocDynamic\n", __FILE__, __LINE__);
1306 #if !defined(mips_sgi_irix6_4)
1307   // Fun (not) case: there's no space for the RPC to execute.
1308   // It'll call inferiorMalloc, which will call inferiorMallocDynamic...
1309   // Avoid this with a static bool.
1310   if (inInferiorMallocDynamic) {
1311       fprintf(stderr, "%s[%d]:  recursion guard\n", __FILE__, __LINE__);
1312       return;
1313   }
1314   inInferiorMallocDynamic = true;
1315 #endif
1316
1317   // word-align buffer size 
1318   // (see "DYNINSTheap_align" in rtinst/src/RTheap-<os>.c)
1319   alignUp(size, 4);
1320   // build AstNode for "DYNINSTos_malloc" call
1321   pdstring callee = "DYNINSTos_malloc";
1322   pdvector<AstNode*> args(3);
1323   args[0] = new AstNode(AstNode::Constant, (void *)(Address)size);
1324   args[1] = new AstNode(AstNode::Constant, (void *)lo);
1325   args[2] = new AstNode(AstNode::Constant, (void *)hi);
1326   AstNode *code = new AstNode(callee, args);
1327   removeAst(args[0]);
1328   removeAst(args[1]);
1329   removeAst(args[2]);
1330
1331   // issue RPC and wait for result
1332   imd_rpc_ret ret = { false, NULL };
1333
1334  
1335   /* set lowmem to ensure there is space for inferior malloc */
1336   getRpcMgr()->postRPCtoDo(code, true, // noCost
1337                            &inferiorMallocCallback, &ret, 
1338                            true, // But use reserved memory
1339                            NULL, NULL); // process-wide
1340   bool wasRunning = (status() == running);
1341
1342   // Specify that we want to wait for a RPCDone event
1343   eventType res = evtUndefined;
1344
1345   inferiorMallocCallbackFlag = false;
1346      inferiorrpc_printf("%s[%d]:  waiting for rpc completion\n", FILE__, __LINE__);
1347   do {
1348      getRpcMgr()->launchRPCs(wasRunning);
1349      getMailbox()->executeCallbacks(FILE__, __LINE__);
1350
1351      if(hasExited()) {
1352         fprintf(stderr, "%s[%d]:  BAD NEWS, process has exited\n", __FILE__, __LINE__);
1353         return;
1354      }
1355     if (inferiorMallocCallbackFlag) {
1356        break;
1357      }
1358
1359      inferiorrpc_printf("%s[%d][%s]:  before wait for RPCDone, status == running is %s\n", 
1360                         FILE__, __LINE__, getThreadStr(getExecThreadID()), 
1361                         status() == running ? "true" : "false");
1362
1363      res = getSH()->waitForEvent(evtRPCSignal, this, NULL /*lwp*/, statusRPCDone);
1364      getMailbox()->executeCallbacks(FILE__, __LINE__);
1365    } while (res != evtRPCSignal); // Loop until callback has fired.
1366
1367   inferiorMallocCallbackFlag = false;
1368
1369    switch ((int)(Address)ret.result) {
1370      case 0:
1371 #ifdef DEBUG
1372         sprintf(errorLine, "DYNINSTos_malloc() failed\n");
1373         logLine(errorLine);
1374 #endif
1375         break;
1376      case -1:
1377         // TODO: assert?
1378         sprintf(errorLine, "DYNINSTos_malloc(): unaligned buffer size\n");
1379         logLine(errorLine);
1380         break;
1381      default:
1382         // add new segment to buffer pool
1383          // FIXME
1384 #if defined(os_aix)
1385          // for save the world...
1386         heapItem *h = new heapItem((Address)ret.result, size, dataHeap, true,
1387                                    HEAPfree);
1388 #else
1389         heapItem *h = new heapItem((Address)ret.result, size, anyHeap, true,
1390                                    HEAPfree);
1391 #endif
1392
1393
1394         heap.bufferPool.push_back(h);
1395         // add new segment to free list
1396         heapItem *h2 = new heapItem(h);
1397         heap.heapFree.push_back(h2);
1398         break;
1399    }
1400    
1401    /* 03/07/2001 - Jeffrey Shergalis
1402     * Part of the above #if !defined(mips... patch for the recursion problem
1403     * TODO: Need a better solution
1404     */
1405 #if !defined(mips_sgi_irix6_4)
1406    inInferiorMallocDynamic = false;
1407 #endif
1408 }
1409 #endif /* USES_DYNAMIC_INF_HEAP */
1410
1411 const Address ADDRESS_LO = ((Address)0);
1412 const Address ADDRESS_HI = ((Address)~((Address)0));
1413 //unsigned int totalSizeAlloc = 0;
1414
1415 Address process::inferiorMalloc(unsigned size, inferiorHeapType type, 
1416                                 Address near_, bool *err)
1417 {
1418    inferiorHeap *hp = &heap;
1419    if (err) *err = false;
1420    assert(size > 0);
1421    
1422    // allocation range
1423    Address lo = ADDRESS_LO; // Should get reset to a more reasonable value
1424    Address hi = ADDRESS_HI; // Should get reset to a more reasonable value
1425    
1426 #if defined(USES_DYNAMIC_INF_HEAP)
1427    inferiorMallocAlign(size); // align size
1428    // Set the lo/hi constraints (if necessary)
1429    inferiorMallocConstraints(near_, lo, hi, type);
1430 #else
1431    /* align to cache line size (32 bytes on SPARC) */
1432    size = (size + 0x1f) & ~0x1f; 
1433 #endif /* USES_DYNAMIC_INF_HEAP */
1434
1435
1436    // find free memory block (7 attempts)
1437    // attempt 0: as is
1438    // attempt 1: deferred free, compact free blocks
1439    // attempt 2: allocate new segment (1 MB, constrained)
1440    // attempt 3: allocate new segment (sized, constrained)
1441    // attempt 4: remove range constraints
1442    // attempt 5: allocate new segment (1 MB, unconstrained)
1443    // attempt 6: allocate new segment (sized, unconstrained)
1444    // attempt 7: deferred free, compact free blocks (why again?)
1445    int freeIndex = -1;
1446    int ntry = 0;
1447    for (ntry = 0; freeIndex == -1; ntry++) {
1448       switch(ntry) {
1449         case 0: // as is
1450            break;
1451 #if defined(USES_DYNAMIC_INF_HEAP)
1452         case 1: // compact free blocks
1453           gcInstrumentation();
1454           inferiorFreeCompact(hp);
1455           break;
1456         case 2: // allocate new segment (1MB, constrained)
1457         inferiorMallocDynamic(HEAP_DYN_BUF_SIZE, lo, hi);
1458            break;
1459         case 3: // allocate new segment (sized, constrained)
1460            inferiorMallocDynamic(size, lo, hi);
1461            break;
1462         case 4: // remove range constraints
1463            lo = ADDRESS_LO;
1464            hi = ADDRESS_HI;
1465            if (err) {
1466               fprintf(stderr, "%s[%d]: ERROR!\n", __FILE__, __LINE__);
1467               *err = true;
1468            }
1469            break;
1470         case 5: // allocate new segment (1MB, unconstrained)
1471            inferiorMallocDynamic(HEAP_DYN_BUF_SIZE, lo, hi);
1472            break;
1473         case 6: // allocate new segment (sized, unconstrained)
1474            inferiorMallocDynamic(size, lo, hi);
1475            break;
1476         case 7: // deferred free, compact free blocks
1477            inferiorFreeCompact(hp);
1478            break;
1479 #else /* !(USES_DYNAMIC_INF_HEAP) */
1480         case 1: // deferred free, compact free blocks
1481            inferiorFreeCompact(hp);
1482            break;
1483 #endif /* USES_DYNAMIC_INF_HEAP */
1484            
1485         default: // error - out of memory
1486            sprintf(errorLine, "***** Inferior heap overflow: %d bytes "
1487                    "freed, %d bytes requested \n", hp->freed, size);
1488            logLine(errorLine);
1489            showErrorCallback(66, (const char *) errorLine);    
1490               fprintf(stderr,"%s[%d]: ERROR!\n", __FILE__, __LINE__);
1491 #if defined(BPATCH_LIBRARY)
1492            return(0);
1493 #else
1494            P__exit(-1);
1495 #endif
1496       }
1497       freeIndex = findFreeIndex(size, type, lo, hi);
1498 //      bperr("  type %x",type);
1499    }
1500
1501    // adjust active and free lists
1502    assert(freeIndex != -1);
1503    heapItem *h = hp->heapFree[freeIndex];
1504    assert(h);
1505
1506    // remove allocated buffer from free list
1507    if (h->length != size) {
1508       // size mismatch: put remainder of block on free list
1509       heapItem *rem = new heapItem(h);
1510       rem->addr += size;
1511       rem->length -= size;
1512       hp->heapFree[freeIndex] = rem;
1513    } else {
1514       // size match: remove entire block from free list
1515       unsigned last = hp->heapFree.size();
1516       hp->heapFree[freeIndex] = hp->heapFree[last-1];
1517       hp->heapFree.resize(last-1);
1518    }
1519    // add allocated block to active list
1520    h->length = size;
1521    h->status = HEAPallocated;
1522    hp->heapActive[h->addr] = h;
1523    // bookkeeping
1524    hp->totalFreeMemAvailable -= size;
1525    assert(h->addr);
1526    
1527    // ccw: 28 oct 2001
1528    // create imageUpdate here:
1529    // imageUpdate(h->addr,size)
1530    
1531 #ifdef BPATCH_LIBRARY
1532 //      if( h->addr > 0xd0000000){
1533 //              bperr(" \n ALLOCATION: %lx %lx ntry: %d\n", h->addr, size,ntry);
1534 //              fflush(stdout);
1535 //      }
1536 #if defined(sparc_sun_solaris2_4) \
1537  || defined(i386_unknown_linux2_0) \
1538  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */ \
1539  || defined(rs6000_ibm_aix4_1)
1540    if(collectSaveWorldData){
1541       
1542 #if defined(sparc_sun_solaris2_4)
1543       if(h->addr < 0xF0000000)
1544 #elif defined(i386_unknown_linux2_0) \
1545    || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
1546       if(h->addr == 0 ) //< 0x40000000) //ccw TEST TEST TEST
1547 #elif defined(rs6000_ibm_aix4_1)
1548         if(h->addr < 0x20000000)
1549 #endif  
1550       {
1551          imageUpdate *imagePatch=new imageUpdate; 
1552          imagePatch->address = h->addr;
1553          imagePatch->size = size;
1554          imageUpdates.push_back(imagePatch);
1555          //totalSizeAlloc += size;
1556          //bperr(" PUSHBACK %x %x --- \n", imagePatch->address, imagePatch->size);              
1557          //fprintf(stderr," PUSHBACK %x %x --- \n", imagePatch->address, imagePatch->size);             
1558       } else {
1559          //     totalSizeAlloc += size;
1560          //fprintf(stderr,"HIGHMEM UPDATE %x %x \n", h->addr, size);
1561          imageUpdate *imagePatch=new imageUpdate;
1562          imagePatch->address = h->addr;
1563          imagePatch->size = size;
1564          highmemUpdates.push_back(imagePatch);
1565          //bperr(" PUSHBACK %x %x\n", imagePatch->address, imagePatch->size);
1566       }
1567       //fflush(stdout);
1568    }
1569 #endif
1570 #endif
1571    return(h->addr);
1572 }
1573
1574 /* returns true if memory was allocated for a variable starting at address
1575    "block", otherwise returns false
1576 */
1577 bool isInferiorAllocated(process *p, Address block) {
1578   heapItem *h = NULL;  
1579   inferiorHeap *hp = &p->heap;
1580   return hp->heapActive.find(block, h);
1581 }
1582
1583 void process::inferiorFree(Address block)
1584 {
1585   inferiorHeap *hp = &heap;
1586
1587   // find block on active list
1588   heapItem *h = NULL;  
1589   if (!hp->heapActive.find(block, h)) {
1590       // We can do this if we're at process teardown.
1591     return;
1592   }
1593   assert(h);
1594
1595   // Remove from the active list
1596   hp->heapActive.undef(block);
1597
1598   // Add to the free list
1599   h->status = HEAPfree;
1600   hp->heapFree.push_back(h);
1601   hp->totalFreeMemAvailable += h->length;
1602   hp->freed += h->length;
1603 }
1604  
1605 bool process::inferiorRealloc(Address block, unsigned newSize)
1606 {
1607   inferiorHeap *hp = &heap;
1608
1609   // This is why it's not a reference...
1610   inferiorMallocAlign(newSize);
1611
1612   // find block on active list
1613   heapItem *h = NULL;  
1614   if (!hp->heapActive.find(block, h)) {
1615       // We can do this if we're at process teardown.
1616     return false;
1617   }
1618   assert(h);
1619
1620   if (h->length < newSize)
1621       return false; // Cannot make bigger...
1622   if (h->length == newSize)
1623       return true;
1624
1625   // We make a new "free" block that is the end of this one.
1626   Address freeStart = block + newSize;
1627   int shrink = h->length - newSize;
1628   
1629   assert(shrink > 0);
1630
1631   h->length = newSize;
1632
1633   heapItem *freeEnd = new heapItem(freeStart,
1634                                    shrink,
1635                                    h->type,
1636                                    h->dynamic,
1637                                    HEAPfree);
1638   hp->heapFree.push_back(freeEnd);
1639
1640   hp->totalFreeMemAvailable += shrink;
1641   hp->freed += shrink;
1642
1643   // And run a compact; otherwise we'll end up with hugely fragmented memory.
1644   inferiorFreeCompact(hp);
1645
1646   return true;
1647 }
1648
1649
1650 // Cleanup the process object. Delete all sub-objects to ensure we aren't 
1651 // leaking memory and prepare for new versions. Useful when the process exits
1652 // (and the process object is deleted) and when it execs
1653
1654 void process::deleteProcess() {
1655
1656   // A lot of the behavior here is keyed off the current process status....
1657   // if it is exited we'll delete things without performing any operations
1658   // on the process. Otherwise we'll attempt to reverse behavior we've made.
1659     // For platforms that don't like repeated use of for (unsigned i...)
1660     unsigned iter = 0;
1661
1662   // We may call this function multiple times... once when the process exits,
1663   // once when we delete the process object.
1664   if (status() == deleted) return;
1665     
1666   // If this assert fires check whether we're setting the status vrble correctly
1667   // before calling this function
1668   assert(!isAttached() || !reachedBootstrapState(bootstrapped_bs) || execing());
1669
1670   // pid remains untouched
1671   // parent remains untouched
1672   for (iter = 0; iter < mapped_objects.size(); iter++) 
1673       delete mapped_objects[iter];
1674   mapped_objects.clear();
1675   runtime_lib = NULL;
1676
1677   // Signal handlers...
1678   signalHandlerLocations_.clear();
1679
1680   // creationMechanism_ remains untouched
1681   // stateWhenAttached_ remains untouched
1682   main_function = NULL;
1683
1684   if (dyn) {
1685       delete dyn;
1686       dyn = NULL;
1687   }
1688
1689   // Delete the thread and lwp structures
1690   dictionary_hash_iter<unsigned, dyn_lwp *> lwp_iter(real_lwps);
1691   dyn_lwp *lwp;
1692   unsigned index;
1693   
1694   // This differs on exec; we need to kill all but the representative LWP
1695   // Duplicate code for ease of reading
1696
1697   if (execing()) {
1698       while (lwp_iter.next(index, lwp)) {
1699           if (process::IndependentLwpControl() &&
1700               (index == (unsigned)getPid())) {
1701               // Keep this around instead of nuking it -- this is our
1702               // handle to the "real" LWP
1703               representativeLWP = lwp;
1704           }
1705           else
1706               delete lwp;
1707       }
1708       real_lwps.clear();
1709       
1710       // DO NOT DELETE THE REPRESENTATIVE LWP
1711
1712   }
1713   else { 
1714       while (lwp_iter.next(index, lwp)) {
1715           deleteLWP(lwp);
1716       }
1717       real_lwps.clear();
1718       
1719       if (representativeLWP) {
1720           delete representativeLWP;
1721           representativeLWP = NULL;
1722       }
1723   }
1724   
1725   // Blow away threads; we'll recreate later
1726   for (unsigned thr_iter = 0; thr_iter < threads.size(); thr_iter++) {
1727       delete threads[thr_iter];
1728   }
1729   threads.clear();
1730
1731
1732   deferredContinueProc = false;
1733   previousSignalAddr_ = 0;
1734   continueAfterNextStop_ = false;
1735   suppressCont_ = false;
1736   
1737   // Don't touch exec; statically allocated anyway.
1738
1739   if (theRpcMgr) {
1740       delete theRpcMgr;
1741   }
1742   theRpcMgr = NULL;
1743
1744   // Skipping saveTheWorld; don't know what to do with it.
1745
1746   trampTrapMapping.clear();
1747
1748   // Each instPoint may have several instances -- this gets instances and makes
1749   // a unique set
1750   std::set<instPoint *> allInstPoints;
1751   dictionary_hash_iter<Address, instPoint *> ipIter(instPMapping_);
1752   for (; ipIter; ipIter++) {
1753       instPoint *p = ipIter.currval();
1754       allInstPoints.insert(p);
1755   }
1756
1757   // And this deletes the set.
1758   for (std::set<instPoint *>::iterator ip = allInstPoints.begin();
1759        ip != allInstPoints.end();
1760        ip++) {
1761       delete (*ip);
1762   }
1763   instPMapping_.clear();
1764   
1765   codeRangesByAddr_.clear();
1766   
1767   // Iterate and clear? instPoint deletion should handle it.
1768   // What about replaced functions?
1769   modifiedAreas_.clear();
1770   multiTrampDict.clear();
1771
1772   // Blow away the replacedFunctionCalls list; codeGens are taken
1773   // care of statically and will deallocate
1774   dictionary_hash_iter<Address, replacedFunctionCall *> rfcIter(replacedFunctionCalls_);  
1775   for (; rfcIter; rfcIter++) {
1776       replacedFunctionCall *rfcVal = rfcIter.currval();
1777       assert(rfcVal->callAddr == rfcIter.currkey());
1778       assert(rfcVal);
1779       free(rfcVal);
1780   }
1781   replacedFunctionCalls_.clear();
1782
1783   codeSections_.clear();
1784   dataSections_.clear();
1785
1786   dyninstlib_brk_addr = 0;
1787   main_brk_addr = 0;
1788
1789   heapInitialized_ = false;
1790   heap.clear();
1791   inInferiorMallocDynamic = false;
1792
1793   // Get rid of our syscall tracing.
1794   if (tracedSyscalls_) {
1795       delete tracedSyscalls_;
1796       tracedSyscalls_ = NULL;
1797   }
1798
1799   for (iter = 0; iter < syscallTraps_.size(); iter++) 
1800       delete syscallTraps_[iter];
1801
1802   for (iter = 0; iter < tracingRequests.size(); iter++)
1803       delete tracingRequests[iter];
1804   tracingRequests.clear();
1805
1806   // By definition, these are dangling.
1807   for (iter = 0; iter < pendingGCInstrumentation.size(); iter++) {
1808       delete pendingGCInstrumentation[iter];
1809   }
1810   pendingGCInstrumentation.clear();
1811
1812   cumulativeObsCost = 0;
1813   lastObsCostLow = 0;
1814   costAddr_ = 0;
1815   threadIndexAddr = 0;
1816   trampGuardBase_ = 0;
1817
1818 #if defined(os_linux)
1819   vsyscall_start_ = 0;
1820   vsyscall_end_ = 0;
1821   vsyscall_text_ = 0;
1822   vsyscall_data_ = 0;
1823 #endif
1824   
1825   set_status(deleted);
1826 }
1827
1828 //
1829 // cleanup when a process is deleted. Assumed we are detached or the process is exited.
1830 //
1831 process::~process()
1832 {
1833     // Failed creation... nothing is here yet
1834     if (!reachedBootstrapState(initialized_bs))
1835         return;
1836
1837     // We require explicit detaching if the process still exists.
1838     // On the other hand, if it never started...
1839     if (reachedBootstrapState(bootstrapped_bs))
1840         assert(!isAttached());
1841
1842 #if defined( ia64_unknown_linux2_4 )
1843         if( unwindProcessArg != NULL ) { getDBI()->UPTdestroy( unwindProcessArg ); }
1844         if( unwindAddressSpace != NULL ) { getDBI()->destroyUnwindAddressSpace( unwindAddressSpace ); }
1845 #endif
1846     
1847     // Most of the deletion is encapsulated in deleteProcess
1848     deleteProcess();
1849
1850     // We used to delete the particular process, but this created no end of problems
1851     // with people storing pointers into particular indices. We set the pointer to NULL.
1852     for (unsigned lcv=0; lcv < processVec.size(); lcv++) {
1853         if (processVec[lcv] == this) {
1854             processVec[lcv] = NULL;
1855         }        
1856     }
1857
1858 #if defined(i386_unknown_linux2_0) \
1859  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
1860     cleanupVsysinfo(getVsyscallData());
1861 #endif
1862
1863 }
1864
1865 // Default process class constructor. This handles both create,
1866 // attach, and attachToCreated cases. We then call an auxiliary
1867 // function (which can return an error value) to handle specific
1868 // cases.
1869 process::process(int ipid) :
1870     cached_result(not_cached), // MOVE ME
1871     pid(ipid),
1872     parent(NULL),
1873     runtime_lib(NULL),
1874     creationMechanism_(unknown_cm),
1875     stateWhenAttached_(unknown_ps),
1876     main_function(NULL),
1877     dyn(NULL),
1878     representativeLWP(NULL),
1879     real_lwps(CThash),
1880     max_number_of_threads(MAX_THREADS),
1881     deferredContinueProc(false),
1882     previousSignalAddr_(0),
1883     continueAfterNextStop_(false),
1884     suppressCont_(false),
1885     status_(neonatal),
1886     nextTrapIsExec(false),
1887     inExec_(false),
1888     theRpcMgr(NULL),
1889     collectSaveWorldData(true),
1890     requestTextMiniTramp(false),
1891     traceLink(0),
1892     trampTrapMapping(addrHash4),
1893     instPMapping_(addrHash4),
1894     multiTrampDict(intHash),
1895     replacedFunctionCalls_(addrHash4),
1896     bootstrapState(unstarted_bs),
1897     savedRegs(NULL),
1898     dyninstlib_brk_addr(0),
1899     main_brk_addr(0),
1900     runProcessAfterInit(false),
1901     systemPrelinkCommand(NULL),
1902 #if defined(os_windows)
1903     processHandle_(INVALID_HANDLE_VALUE),
1904     mainFileHandle_(INVALID_HANDLE_VALUE),
1905 #endif
1906     splitHeaps(false),
1907     heapInitialized_(false),
1908     inInferiorMallocDynamic(false),
1909     tracedSyscalls_(NULL),
1910     cumulativeObsCost(0),
1911     lastObsCostLow(0),
1912     costAddr_(0),
1913     threadIndexAddr(0),
1914     trampGuardBase_(0)
1915 #if defined(arch_ia64)
1916     , unwindAddressSpace(NULL) // Automatically created in getActiveFrame
1917     , unwindProcessArg(NULL) // And this one too
1918 #endif
1919 #if defined(os_linux)
1920     , vsyscall_start_(0)
1921     , vsyscall_end_(0)
1922     , vsyscall_text_(0)
1923     , vsyscall_data_(NULL)
1924 #endif
1925 {
1926
1927     // Let's try to profile memory usage
1928 #if defined(PROFILE_MEM_USAGE)
1929    void *mem_usage = sbrk(0);
1930    fprintf(stderr, "Process creation: sbrk %p\n", mem_usage);
1931 #endif
1932
1933     theRpcMgr = new rpcMgr(this);    
1934     dyn = new dynamic_linking(this);
1935     createRepresentativeLWP();
1936
1937     // Not sure we need this anymore... on AIX you can run code
1938     // anywhere, so allocating by address _should_ be okay.
1939 #if defined(rs6000_ibm_aix3_2) \
1940  || defined(rs6000_ibm_aix4_1) \
1941  || defined(alpha_dec_osf4_0)
1942     splitHeaps = true;
1943 #endif
1944
1945 }
1946
1947 //
1948 // Process "normal" (non-attach, non-fork) ctor equivalent, for when a
1949 // new process is fired up by paradynd itself.  This ctor. is also
1950 // used in the case that the application has been fired up by another
1951 // process and stopped just after executing the execv() system call.
1952 // In the "normal" case, the parameter iTraceLink will be a
1953 // non-negative value which corresponds to the pipe descriptor of the
1954 // trace pipe used between the paradynd and the application. In the
1955 // later case, iTraceLink will be -1. This will be posteriorly used to
1956 // properly initialize the createdViaAttachToCreated flag. - Ana
1957 //
1958
1959
1960 bool process::setupCreated(int iTraceLink) {
1961     traceLink = iTraceLink; // notice that tracelink will be -1 in the unique
1962     // case called "AttachToCreated" - Ana 
1963     // PARADYN ONLY
1964
1965     creationMechanism_ = created_cm;
1966     
1967 #if !defined(BPATCH_LIBRARY)
1968     if (iTraceLink == -1 ) {
1969         fprintf(stderr, "%s[%d]:  setting attachedToCreated\n", FILE__, __LINE__);
1970         creationMechanism_ = attachedToCreated_cm;
1971     }
1972 #endif
1973
1974     // Post-setup state variables
1975     runProcessAfterInit = false;
1976     stateWhenAttached_ = stopped; 
1977     
1978     startup_printf("Creation method: attaching to process\n");
1979     // attach to the child process (machine-specific implementation)
1980     if (!attach()) { // error check?
1981         status_ = detached;
1982          pdstring msg = pdstring("Warning: unable to attach to specified process :")
1983             + pdstring(pid);
1984         showErrorCallback(26, msg.c_str());
1985         return false;
1986     }
1987     startup_printf("Creation method: returning\n");
1988     return true;
1989 }
1990     
1991
1992 // Attach version of the above: no trace pipe, but we assume that
1993 // main() has been reached and passed. Someday we could unify the two
1994 // if someone has a good way of saying "has main been reached".
1995 bool process::setupAttached() {
1996     creationMechanism_ = attached_cm;
1997     // We're post-main... run the bootstrapState forward
1998
1999 #if !defined(os_windows)
2000     bootstrapState = initialized_bs;
2001 #else
2002     // We need to wait for the CREATE_PROCESS debug event.
2003     // Set to "begun" here, and fix up in the signal loop
2004     bootstrapState = begun_bs;
2005 #endif
2006
2007    traceLink = -1; // will be set later, when the appl runs DYNINSTinit
2008
2009    startup_printf("Attach method: attaching to process\n");
2010
2011    // It is assumed that a call to attach() doesn't affect the running status
2012    // of the process.  But, unfortunately, some platforms may barf if the
2013    // running status is anything except paused. (How to deal with this?)
2014    // Note that solaris in particular seems able to attach even if the process
2015    // is running.
2016    if (!attach()) {
2017        status_ = detached;
2018        
2019       pdstring msg = pdstring("Warning: unable to attach to specified process: ")
2020                    + pdstring(pid);
2021       showErrorCallback(26, msg.c_str());
2022       return false;
2023    }
2024
2025    startup_printf("[%d]: attached, getting current process state\n", getPid());
2026
2027    // Record what the process was doing when we attached, for possible
2028    // use later.
2029    if (isRunning_()) {
2030        startup_printf("[%d]: process running when attached, pausing...\n", getPid());
2031        stateWhenAttached_ = running; 
2032        set_status(running);
2033        if (!pause())
2034            return false;
2035    }
2036    else {
2037        startup_printf("[%d]: attached to previously paused process\n", getPid());
2038        stateWhenAttached_ = stopped;
2039        set_status(stopped);
2040    }
2041    startup_printf("[%d]: setupAttached returning true\n", getPid());
2042
2043    assert(status() == stopped);
2044    return true;
2045 }
2046
2047 int HACKSTATUS = 0;
2048
2049 bool process::prepareExec() {
2050     ///////////////////////////// CONSTRUCTION STAGE ///////////////////////////
2051     // For all intents and purposes: a new id.
2052     // However, we don't want to make a new object since all sorts
2053     // of people have a pointer to this object. We could index by PID,
2054     // which would allow us to swap out processes; but hey.
2055
2056     // We should be attached to the process
2057
2058     // setupExec must get us to the point of putting a trap at the
2059     // beginning of main. We then continue. We might get called again,
2060     // or we might go into loading the dyninst lib; impossible to
2061     // tell.
2062     //
2063
2064 #if defined(AIX_PROC)
2065     // AIX oddly detaches from the process... fix that here
2066     // Actually, it looks like only the as FD is closed (probably because
2067     // the file it refers to is gone). Reopen.
2068    getRepresentativeLWP()->reopen_fds();
2069 #endif
2070
2071     // Revert the bootstrap state
2072     bootstrapState = attached_bs;
2073
2074     // First, duplicate constructor.
2075
2076     assert(theRpcMgr == NULL);
2077     assert(dyn == NULL);
2078     theRpcMgr = new rpcMgr(this);
2079     dyn = new dynamic_linking(this);
2080     int status = 0;
2081
2082     // False: not waitin' for a signal (theoretically, we already got
2083     // it when we attached)
2084     fileDescriptor desc;
2085     if (!getExecFileDescriptor(execFilePath, 
2086                                pid,
2087                                false,
2088                                status, 
2089                                desc)) {
2090         cerr << "Failed to find exec descriptor" << endl;
2091         return false;
2092     }
2093     if (!setAOut(desc)) {
2094         return false;
2095     }
2096
2097     // Probably not going to find anything (as we haven't loaded the
2098     // RT lib yet, and that's where most of the space is). However,
2099     // any shared object added after this point will have infHeaps
2100     // auto-added.
2101     startup_printf("Initializing vector heap\n");
2102     initInferiorHeap();
2103
2104     // Now from setupGeneral...
2105     createInitialThread();
2106
2107     // Status: stopped.
2108     set_status(stopped);
2109
2110     // Annoying; most of our initialization code is in unix.C, and it
2111     // knows how to get us to main. Problem is, it triggers on a trap...
2112     // and guess what we just consumed. So replicate it manually.
2113     setBootstrapState(begun_bs);
2114     insertTrapAtEntryPointOfMain();
2115     continueProc();
2116
2117     return true;
2118 }
2119
2120 bool process::finishExec() {
2121     startup_printf("%s[%d]:  about toloadDyninstLib\n", FILE__, __LINE__);
2122     bool res = loadDyninstLib();
2123     if (!res)
2124         return false;
2125     
2126     getMailbox()->executeCallbacks(FILE__, __LINE__);
2127     while(!reachedBootstrapState(bootstrapped_bs)) {
2128         // We're waiting for something... so wait
2129         // true: block until a signal is received (efficiency)
2130         if(hasExited()) {
2131             return false;
2132         }
2133         fprintf(stderr, "%s[%d][%s]:  before waitForEvent(evtProcessInitDone)\n", 
2134                 FILE__, __LINE__, getThreadStr(getExecThreadID()));
2135
2136         getSH()->waitForEvent(evtProcessInitDone);
2137         getMailbox()->executeCallbacks(FILE__, __LINE__);
2138     }
2139     
2140     if(process::IndependentLwpControl())
2141         independentLwpControlInit();
2142     
2143     set_status(stopped); // was 'exited'
2144     
2145     inExec_ = false;
2146     BPatch::bpatch->registerExec(this);
2147
2148     return true;
2149 }
2150
2151 bool process::setupFork() {
2152     
2153     assert(parent);
2154     assert(parent->status() == stopped);
2155
2156     // Do stuff....
2157
2158     // Copy: 
2159     //   all mapped objects
2160     //   dynamic object tracer
2161     //   all threads
2162     //   all lwps
2163     //   rpc manager
2164     //   all vector heaps
2165     //   all defined instPoints
2166     //   all multiTramps
2167     //    ... and baseTramps, relocatedInstructions, trampEnds, miniTramps
2168     //   installed instrumentation
2169     //    ... including system call handling
2170     //   process state
2171     //   
2172
2173     // Mapped objects first
2174     for (unsigned i = 0; i < parent->mapped_objects.size(); i++) {
2175         mapped_object *par_obj = parent->mapped_objects[i];
2176         mapped_object *child_obj = new mapped_object(par_obj, this);
2177         if (!child_obj) {
2178             delete child_obj;
2179             return false;
2180         }
2181
2182         mapped_objects.push_back(child_obj);
2183         addCodeRange(child_obj);
2184
2185         if ((par_obj->fileName() == dyninstRT_name) ||
2186             (par_obj->fullName() == dyninstRT_name))
2187             runtime_lib = child_obj;
2188
2189         // This clones funcs, which then clone instPoints, which then 
2190         // clone baseTramps, which then clones miniTramps.
2191     }
2192     // And the main func and dyninst RT lib
2193     if (!setMainFunction())
2194         return false;
2195     if (parent->runtime_lib) {
2196         // This should be set by now...
2197         assert(runtime_lib);
2198     }
2199     
2200     /////////////////////////
2201     // Threads & LWPs
2202     /////////////////////////
2203     createRepresentativeLWP();
2204     if (!attach()) {
2205         status_ = detached;
2206         showErrorCallback(69, "Error in fork: cannot attach to child process");
2207         return false;
2208     }
2209
2210     if(process::IndependentLwpControl())
2211         independentLwpControlInit();
2212
2213     /////////////////////////
2214     // RPC manager
2215     /////////////////////////
2216     
2217     theRpcMgr = new rpcMgr(parent->theRpcMgr, this);
2218     assert(theRpcMgr);
2219
2220     /////////////////////////
2221     // Find new threads
2222     /////////////////////////    
2223
2224     recognize_threads(parent);
2225
2226
2227     /////////////////////////
2228     // Inferior heap
2229     /////////////////////////
2230     
2231     heap = inferiorHeap(parent->heap);
2232
2233     /////////////////////////
2234     // Instrumentation (multiTramps on down)
2235     /////////////////////////
2236
2237     dictionary_hash_iter<int, multiTramp *> multiTrampIter(parent->multiTrampDict);
2238     int mID;
2239     multiTramp *mTramp;
2240     for (; multiTrampIter; multiTrampIter++) {
2241         mID = multiTrampIter.currkey();
2242         mTramp = multiTrampIter.currval();
2243         assert(mTramp);
2244         multiTramp *newMulti = new multiTramp(mTramp, this);
2245         multiTrampDict[mID] = newMulti;
2246         addMultiTramp(newMulti);
2247     }
2248     // That will also create all baseTramps, miniTramps, ...
2249
2250     // Copy the replacedFunctionCalls...
2251     dictionary_hash_iter<Address, replacedFunctionCall *> rfcIter(replacedFunctionCalls_);  
2252     Address rfcKey;
2253     replacedFunctionCall *rfcVal;
2254     for (; rfcIter; rfcIter++) {
2255         rfcKey = rfcIter.currkey();
2256         assert(rfcKey);
2257         rfcVal = rfcIter.currval();
2258         assert(rfcVal);
2259         assert(rfcVal->callAddr == rfcKey);
2260         // Mmm copy constructor
2261         replacedFunctionCall *newRFC = new replacedFunctionCall(*rfcVal);
2262         replacedFunctionCalls_[rfcKey] = newRFC;
2263     }
2264
2265 #if 0
2266     // We create instPoints as part of copying functions
2267
2268     std::set<instPoint *> allInstPoints;
2269     dictionary_hash_iter<Address, instPoint *> ipIter(parent->instPMapping_);
2270     for (; ipIter; ipIter++) {
2271         instPoint *p = ipIter.currval();
2272         allInstPoints.insert(p);
2273     }
2274     
2275     for (std::set<instPoint *>::iterator ip = allInstPoints.begin();
2276          ip != allInstPoints.end();
2277          ip++) {
2278         instPoint *newIP = new instPoint(*ip, this);
2279         assert(newIP);
2280         // Adds to instPMapping_
2281     }
2282 #endif
2283
2284     // Tag the garbage collection list...
2285     for (unsigned ii = 0; ii < parent->pendingGCInstrumentation.size(); ii++) {
2286         // TODO. For now we'll just "leak"
2287     }
2288
2289     // Now that we have instPoints, we can create the (possibly) instrumentation-
2290     // based tracing code
2291
2292     /////////////////////////
2293     // Dynamic tracer
2294     /////////////////////////
2295
2296     dyn = new dynamic_linking(parent->dyn, this);
2297     assert(dyn);
2298
2299     /////////////////////////
2300     // Syscall tracer
2301     /////////////////////////
2302
2303     tracedSyscalls_ = new syscallNotification(parent->tracedSyscalls_, this);
2304
2305     // Copy signal handlers
2306
2307     pdvector<codeRange *> sigHandlers;
2308     parent->signalHandlerLocations_.elements(sigHandlers);
2309     for (unsigned iii = 0; iii < sigHandlers.size(); iii++) {
2310         signal_handler_location *oldSig = dynamic_cast<signal_handler_location *>(sigHandlers[iii]);
2311         assert(oldSig);
2312         signal_handler_location *newSig = new signal_handler_location(*oldSig);
2313         signalHandlerLocations_.insert(newSig);
2314     }
2315
2316
2317 #if defined(os_aix)
2318     // AIX doesn't copy memory past the ends of text segments, so we
2319     // do it manually here
2320     copyDanglingMemory(const_cast<process *>(parent));
2321 #endif
2322
2323     /////////////////////////
2324     // Process vector
2325     /////////////////////////
2326
2327     processVec.push_back(this);
2328     activeProcesses++;
2329     return true;
2330 }
2331
2332
2333 unsigned process::getAddressWidth() { 
2334     if (mapped_objects.size() > 0) 
2335         return mapped_objects[0]->parse_img()->getObject().getAddressWidth(); 
2336     // We can call this before we've attached.. 
2337     return 4;
2338 }
2339
2340 bool process::setAOut(fileDescriptor &desc) {
2341     assert(reachedBootstrapState(attached_bs));
2342     assert(mapped_objects.size() == 0);
2343     mapped_object *aout = mapped_object::createMappedObject(desc, this);
2344     if (!aout)
2345         return false;
2346     
2347     mapped_objects.push_back(aout);
2348     addCodeRange(aout);
2349
2350     findSignalHandler(aout);
2351
2352     // Find main
2353     return setMainFunction();
2354 }
2355
2356 // Here's the list of functions to look for:
2357 #define NUMBER_OF_MAIN_POSSIBILITIES 7
2358 char main_function_names[NUMBER_OF_MAIN_POSSIBILITIES][20] = {
2359     "main",
2360     "DYNINST_pltMain",
2361     "_main",
2362     "WinMain",
2363     "_WinMain",
2364     "wWinMain",
2365     "_wWinMain"};
2366
2367 bool process::setMainFunction() {
2368     assert(!main_function);
2369     
2370     for (unsigned i = 0; i < NUMBER_OF_MAIN_POSSIBILITIES; i++) {
2371         main_function = findOnlyOneFunction(main_function_names[i]);
2372         if (main_function) break;
2373     }
2374
2375     assert(main_function);
2376     return true;
2377 }
2378
2379 bool process::setupGeneral() {
2380     // Need to have a.out at this point
2381     assert(mapped_objects.size() > 0);
2382
2383     if (reachedBootstrapState(bootstrapped_bs)) 
2384         return true;
2385
2386     // We should be paused; be sure.
2387     pause();
2388     
2389     // In the ST case, threads[0] (the only one) is effectively
2390     // a pass-through for process operations. In MT, it's the
2391     // main thread of the process and is handled correctly
2392
2393     startup_printf("Creating initial thread...\n");
2394
2395     createInitialThread();
2396
2397     // Probably not going to find anything (as we haven't loaded the
2398     // RT lib yet, and that's where most of the space is). However,
2399     // any shared object added after this point will have infHeaps
2400     // auto-added.
2401     startup_printf("Initializing vector heap\n");
2402     initInferiorHeap();
2403
2404 #if defined(os_aix)
2405     if (HACKSTATUS == SIGTRAP) {
2406       EventRecord ev;
2407       ev.proc = this;
2408       ev.type = evtSignalled;
2409       ev.what = HACKSTATUS;
2410       ev.info = 0;
2411       //getSH()->handleSigTrap(ev);
2412       SignalHandlerUnix::handleSigTrap(ev);
2413     }
2414 #endif
2415         
2416
2417     startup_printf("%s[%d]: Loading DYNINST lib...\n", FILE__, __LINE__);
2418     // TODO: loadDyninstLib actually embeds a lot of startup material;
2419     // should move it up to this function to make things more obvious.
2420     bool res = loadDyninstLib();
2421     if(res == false) {
2422         return false;
2423     }
2424     startup_printf("Waiting for bootstrapped state...\n");
2425     while (!reachedBootstrapState(bootstrapped_bs)) {
2426        // We're waiting for something... so wait
2427        // true: block until a signal is received (efficiency)
2428        if(hasExited()) {
2429            return false;
2430        }
2431        startup_printf("Checking for process event...\n");
2432        getSH()->waitForEvent(evtProcessInitDone);
2433        getMailbox()->executeCallbacks(FILE__, __LINE__);
2434     }
2435
2436     if(process::IndependentLwpControl())
2437         independentLwpControlInit();
2438     
2439     initTramps(multithread_capable());
2440
2441     return true;
2442 }
2443
2444 //
2445 // Process "fork" ctor, for when a process which is already being monitored by
2446 // paradynd executes the fork syscall.
2447 //
2448 // Needs to strictly duplicate all process information; this is a _lot_ of work.
2449
2450 process::process(const process *parentProc, int childPid, int childTrace_fd) : 
2451     cached_result(parentProc->cached_result), // MOVE ME
2452     pid(childPid),
2453     parent(parentProc),
2454     runtime_lib(NULL), // Set later
2455     dyninstRT_name(parentProc->dyninstRT_name),
2456     creationMechanism_(parentProc->creationMechanism_),
2457     stateWhenAttached_(parentProc->stateWhenAttached_),
2458     main_function(NULL), // Set later
2459     dyn(NULL),  // Set later
2460     representativeLWP(NULL), // Set later
2461     real_lwps(CThash),
2462     max_number_of_threads(parentProc->max_number_of_threads),
2463     deferredContinueProc(parentProc->deferredContinueProc),
2464     previousSignalAddr_(parentProc->previousSignalAddr_),
2465     continueAfterNextStop_(parentProc->continueAfterNextStop_),
2466     suppressCont_(parentProc->suppressCont_),
2467     status_(parentProc->status_),
2468     nextTrapIsExec(parentProc->nextTrapIsExec),
2469     inExec_(parentProc->inExec_),
2470     theRpcMgr(NULL), // Set later
2471     collectSaveWorldData(parentProc->collectSaveWorldData),
2472     requestTextMiniTramp(parentProc->requestTextMiniTramp),
2473     traceLink(childTrace_fd),
2474     trampTrapMapping(parentProc->trampTrapMapping),
2475     instPMapping_(addrHash4), // Later
2476     multiTrampDict(intHash), // Later
2477     replacedFunctionCalls_(addrHash4), // Also later
2478     bootstrapState(parentProc->bootstrapState),
2479     savedRegs(NULL), // Later
2480     dyninstlib_brk_addr(parentProc->dyninstlib_brk_addr),
2481     main_brk_addr(parentProc->main_brk_addr),
2482     runProcessAfterInit(parentProc->runProcessAfterInit),
2483     splitHeaps(parentProc->splitHeaps),
2484     heapInitialized_(parentProc->heapInitialized_),
2485     inInferiorMallocDynamic(parentProc->inInferiorMallocDynamic),
2486     tracedSyscalls_(NULL),  // Later
2487     cumulativeObsCost(parentProc->cumulativeObsCost),
2488     lastObsCostLow(parentProc->lastObsCostLow),
2489     costAddr_(parentProc->costAddr_),
2490     threadIndexAddr(parentProc->threadIndexAddr),
2491     trampGuardBase_(parentProc->trampGuardBase_),
2492     systemPrelinkCommand(NULL)
2493 #if defined(arch_ia64)
2494     , unwindAddressSpace(NULL) // Recreated automatically in getActiveFrame
2495     , unwindProcessArg(NULL) // And this
2496 #endif
2497 #if defined(os_linux)
2498     , vsyscall_start_(parentProc->vsyscall_start_)
2499     , vsyscall_end_(parentProc->vsyscall_end_)
2500     , vsyscall_text_(parentProc->vsyscall_text_)
2501     , vsyscall_data_(parentProc->vsyscall_data_)
2502 #endif
2503 {
2504 }
2505
2506 static void cleanupBPatchHandle(int pid)
2507 {
2508    BPatch::bpatch->unRegisterProcess(pid);
2509 }
2510
2511
2512 /*
2513  * Create a new instance of the named process.  Read the symbols and start
2514  *   the program
2515  */
2516 process *ll_createProcess(const pdstring File, pdvector<pdstring> *argv,
2517                           pdvector<pdstring> *envp, const pdstring dir = "",
2518                           int stdin_fd=0, int stdout_fd=1, int stderr_fd=2)
2519 {
2520
2521         // prepend the directory (if any) to the filename,
2522         // unless the filename is an absolute pathname
2523         // 
2524         // The filename is an absolute pathname if it starts with a '/' on UNIX,
2525         // or a letter and colon pair on Windows.
2526
2527   startup_cerr << "Creating process " << File << " in directory " << dir << endl;
2528
2529   if (argv) {
2530     startup_cerr << "Arguments: (" << argv->size() << ")" << endl;
2531     for (unsigned a = 0; a < argv->size(); a++)
2532       startup_cerr << "   " << a << ": " << (*argv)[a] << endl;
2533   }
2534   if (envp) {
2535     startup_cerr << "Environment: (" << envp->size() << ")" << endl;
2536     for (unsigned e = 0; e < envp->size(); e++)
2537       startup_cerr << "   " << e << ": " << (*envp)[e] << endl;
2538   }
2539   startup_printf("Stdin: %d, stdout: %d, stderr: %d\n", stdin_fd, stdout_fd, stderr_fd);
2540
2541     
2542    pdstring file = File;
2543         if( dir.length() > 0 )
2544         {
2545 #if !defined(i386_unknown_nt4_0)
2546                 if( !file.prefixed_by("/") )
2547                 {
2548                         // file does not start  with a '/', so it is a relative pathname
2549                         // we modify it to prepend the given directory
2550                         if( dir.suffixed_by("/") )
2551                         {
2552                                 // the dir already has a trailing '/', so we can
2553                                 // just concatenate them to get an absolute path
2554                                 file = dir + file;
2555                         }
2556                         else
2557                         {
2558                                 // the dir does not have a trailing '/', so we must
2559                                 // add a '/' to get the absolute path
2560                                 file = dir + "/" + file;
2561                         }
2562                 }
2563                 else
2564                 {
2565                         // file starts with a '/', so it is an absolute pathname
2566                         // DO NOT prepend the directory, regardless of what the
2567                         // directory variable holds.
2568                         // nothing to do in this case
2569                 }
2570
2571 #else // !defined(i386_unknown_nt4_0)
2572                 if( (file.length() < 2) ||      // file is too short to be a drive specifier
2573                         !isalpha( file[0] ) ||  // first character in file is not a letter
2574                         (file[1] != ':') )              // second character in file is not a colon
2575                 {
2576                         file = dir + "\\" + file;
2577                 }
2578 #endif // !defined(i386_unknown_nt4_0)
2579         }
2580
2581 #if defined(BPATCH_LIBRARY) && !defined(BPATCH_REDIRECT_IO)
2582     pdstring inputFile;
2583     pdstring outputFile;
2584 #else
2585     // check for I/O redirection in arg list.
2586     pdstring inputFile;
2587     for (unsigned i1=0; i1<argv->size(); i1++) {
2588       if ((*argv)[i1] == "<") {
2589         inputFile = (*argv)[i1+1];
2590         for (unsigned j=i1+2, k=i1; j<argv->size(); j++, k++)
2591           (*argv)[k] = (*argv)[j];
2592         argv->resize(argv->size()-2);
2593       }
2594     }
2595     // TODO -- this assumes no more than 1 of each "<", ">"
2596     pdstring outputFile;
2597     for (unsigned i2=0; i2<argv->size(); i2++) {
2598       if ((*argv)[i2] == ">") {
2599         outputFile = (*argv)[i2+1];
2600         for (unsigned j=i2+2, k=i2; j<argv->size(); j++, k++)
2601           (*argv)[k] = (*argv)[j];
2602         argv->resize(argv->size()-2);
2603       }
2604     }
2605
2606
2607 #endif /* BPATCH_LIBRARY */
2608
2609     int traceLink = -1; // set by forkNewProcess, below.
2610
2611     int pid;
2612     int tid;
2613
2614     // NT
2615     int procHandle_temp;
2616     int thrHandle_temp;
2617
2618     struct stat file_stat;
2619     int stat_result;
2620
2621     stat_result = stat(file.c_str(), &file_stat);
2622     
2623     if(stat_result == -1) {
2624         startup_printf("%s[%d]:  failed to read file %s\n", __FILE__, __LINE__, file.c_str());
2625         pdstring msg = pdstring("Can't read executable file ") + file + (": ") + strerror(errno);
2626         showErrorCallback(68, msg.c_str());
2627         return(NULL);
2628     }
2629
2630     if (!getDBI()->forkNewProcess(file, dir, argv, envp, inputFile, outputFile,
2631                         traceLink, pid, tid, procHandle_temp, thrHandle_temp,
2632                         stdin_fd, stdout_fd, stderr_fd)) {
2633         // forkNewProcess is responsible for displaying error messages
2634         // Note: if the fork succeeds, but exec fails, forkNew...
2635         // will return true. 
2636        fprintf(stderr, "[%s:%u] - Couldn't fork\n", __FILE__, __LINE__);
2637        return NULL;
2638     }
2639
2640     startup_cerr << "Fork new process... succeeded" << endl;
2641
2642 #ifdef BPATCH_LIBRARY
2643     // Register the pid with the BPatch library (not yet associated with a
2644     // BPatch_thread object).
2645     assert(BPatch::bpatch != NULL);
2646     BPatch::bpatch->registerProvisionalThread(pid);
2647 #endif
2648
2649 #if defined(i386_unknown_nt4_0)
2650     int status = procHandle_temp;
2651     // DEBUGGING
2652 #else
2653     int status = pid;
2654 #endif // defined(i386_unknown_nt4_0)
2655     
2656     statusLine("initializing process data structures");
2657
2658     process *theProc = new process(pid);
2659     assert(theProc);
2660     //fprintf(stderr, "%s[%d]:  setting initial process state to running\n", FILE__, __LINE__);
2661     theProc->set_status(running);
2662
2663     // We need to add this as soon as possible, since a _lot_ of things
2664     // do lookups.
2665     processVec.push_back(theProc);
2666     activeProcesses++;
2667
2668     if (!theProc->setupCreated(traceLink)) {
2669         cleanupBPatchHandle(pid);
2670         processVec.pop_back();
2671         delete theProc;
2672         return NULL;
2673     }
2674
2675     // AIX: wait for a trap so that we're sure the process is loaded
2676     // This is because we still read out of memory; bad idea, but...
2677     fileDescriptor desc;
2678     if (!process::getExecFileDescriptor(file, pid, true, status, desc)) {
2679         startup_cerr << "Failed to find exec descriptor" << endl;
2680         cleanupBPatchHandle(pid);
2681         processVec.pop_back();
2682         delete theProc;
2683         return NULL;
2684     }
2685     HACKSTATUS = status;
2686
2687     if (!theProc->setAOut(desc)) {
2688         startup_printf("[%s:%u] - Couldn't setAOut\n", __FILE__, __LINE__);
2689         cleanupBPatchHandle(pid);
2690         processVec.pop_back();
2691         delete theProc;
2692         return NULL;
2693     }
2694
2695     if (!theProc->setupGeneral()) {
2696         startup_printf("[%s:%u] - Couldn't setupGeneral\n", __FILE__, __LINE__);
2697         cleanupBPatchHandle(pid);
2698         processVec.pop_back();
2699         delete theProc;
2700         return NULL;
2701     }
2702
2703     // Let's try to profile memory usage
2704 #if defined(PROFILE_MEM_USAGE)
2705    void *mem_usage = sbrk(0);
2706    fprintf(stderr, "Post process: sbrk %p\n", mem_usage);
2707 #endif
2708
2709    return theProc;    
2710 }
2711
2712
2713 process *ll_attachProcess(const pdstring &progpath, int pid) 
2714 {
2715   // implementation of dynRPC::attach() (the igen call)
2716   // This is meant to be "the other way" to start a process (competes w/ createProcess)
2717   
2718   // progpath gives the full path name of the executable, which we use ONLY to
2719   // read the symbol table.
2720   
2721   // We try to make progpath optional, since given pid, we should be able to
2722   // calculate it with a clever enough search of the process' PATH, examining
2723   // its argv[0], examining its current directory, etc.  /proc gives us this
2724   // information on solaris...not sure about other platforms...
2725
2726     // No longer take the afterAttach argument. Instead, the process object records
2727     // the state of the process at attach, and the user can read and act on this as
2728     // they please -- bernat, JAN03
2729
2730   startup_cerr << "welcome to attachProcess for pid " << pid << endl;
2731   startup_cerr << "Given program path: " << progpath << endl;
2732
2733   // QUESTION: When we attach to a process, do we want to redirect its stdout/stderr
2734   //           (like we do when we fork off a new process the 'usual' way)?
2735   //           My first guess would be no.  -ari
2736   //           But although we may ignore the io, we still need the trace stream.
2737   
2738   // When we attach to a process, we don't fork...so this routine is much
2739   // simpler than its "competitor", ll_createProcess() (above).
2740   pdstring fullPathToExecutable = process::tryToFindExecutable(progpath, pid);
2741
2742   if (!fullPathToExecutable.length()) {
2743       return NULL;
2744   }
2745
2746   process *theProc = new process(pid);
2747   assert(theProc);
2748
2749   // Add this as we can't do _anything_ without a process to look up.
2750   processVec.push_back(theProc);
2751   activeProcesses++;
2752
2753   if (!theProc->setupAttached()) {
2754         processVec.pop_back();
2755       delete theProc;
2756       return NULL;
2757   }
2758
2759 #if defined(i386_unknown_nt4_0)
2760   int status = (int)INVALID_HANDLE_VALUE;       // indicates we need to obtain a valid handle
2761 #else
2762   int status = pid;
2763 #endif // defined(i386_unknown_nt4_0)
2764
2765   fileDescriptor desc;
2766   if (!process::getExecFileDescriptor(fullPathToExecutable,
2767 #if defined(os_windows)
2768                              (int)INVALID_HANDLE_VALUE,
2769 #else
2770                              pid,
2771 #endif
2772                              false,
2773                              status, 
2774                              desc)) {
2775         processVec.pop_back();
2776       delete theProc;
2777       return NULL;
2778   }
2779   
2780   if (!theProc->setAOut(desc)) {
2781         processVec.pop_back();
2782       delete theProc;
2783       return NULL;
2784   }
2785   if (!theProc->setupGeneral()) {
2786         processVec.pop_back();
2787       delete theProc;
2788       return NULL;
2789   }
2790
2791   return theProc; // successful
2792 }
2793
2794 /*
2795  * This function is needed in the unique case where we want to 
2796  * attach to an application which has been previously stopped
2797  * in the exec() system call as in the normal case (createProcess).
2798  * In this particular case, the SIGTRAP due to the exec() has been 
2799  * previously caught by another process, therefore we should taking into
2800  * account this issue in the necessary platforms. 
2801  * Basically, is an hybrid case between addprocess() and attachProcess().
2802  * 
2803  */
2804
2805 process *ll_attachToCreatedProcess(int pid, const pdstring &progpath)
2806 {
2807     /* parent */
2808     statusLine("initializing process data structures");
2809
2810     process *theProc = new process(pid);
2811     assert(theProc);
2812
2813     // Add immediately
2814     processVec.push_back(theProc);
2815     activeProcesses++;
2816
2817     // This is the same as attaching...
2818     if (!theProc->setupAttached()) {
2819         processVec.pop_back();
2820         delete theProc;
2821         return NULL;
2822     }
2823     // But here we reset the bootstrap state to indicate that we're between
2824     // exec and main
2825     theProc->resetBootstrapState(begun_bs);
2826     // Now, we missed the trap (because the creator already saw
2827     // it). However, we can always create a signal. We do that as soon
2828     // as we've parsed the image.
2829
2830     pdstring fullPathToExecutable = process::tryToFindExecutable(progpath, pid);
2831     
2832     if (!fullPathToExecutable.length()) {
2833         return false;
2834     }  
2835     
2836     int status = pid;
2837     
2838     // Get the file descriptor for the executable file
2839     // "true" value is for AIX -- waiting for an initial trap
2840     // it's ignored on other platforms
2841     fileDescriptor desc;
2842     if (!process::getExecFileDescriptor(fullPathToExecutable, 
2843                                pid, 
2844                                false,
2845                                status, desc)) {
2846         processVec.pop_back();
2847         delete theProc;
2848         return false;
2849     } 
2850
2851     if (!theProc->setAOut(desc)) {
2852         processVec.pop_back();
2853         delete theProc;
2854         return NULL;
2855     }
2856
2857 #if !defined(os_windows)    
2858     // Now, fake a trap signal and off to setupGeneral
2859     EventRecord ev;
2860     ev.proc = theProc;
2861     bool res = SignalHandlerUnix::handleSigTrap(ev);
2862     assert(res);
2863 #endif
2864
2865     // Process ran for about a second....
2866     // should now be stopped at main
2867     if (!theProc->setupGeneral()) {
2868         processVec.pop_back();
2869         delete theProc;
2870         return NULL;
2871     }
2872     
2873     return theProc;
2874 } // end of AttachToCreatedProcess
2875
2876
2877
2878
2879 /***************************************************************************
2880  **** Runtime library initialization code (Dyninst)                     ****
2881  ***************************************************************************/
2882
2883 /*
2884  * Gratuitously large comment. This diagrams the startup flow of 
2885  * messages between the mutator and mutatee. Entry points 
2886  * for create and attach process are both given.
2887  *     Mutator           Signal              Mutatee
2888  * Create:
2889  *     Fork/Exec
2890  *                     <-- Trap              Halted in exec
2891  *     Install trap in main             
2892  *                     <-- Trap              Halted in main
2893  *  Attach: (also paused, not in main)
2894  *     Install call to dlopen/
2895  *     LoadLibrary       
2896  *                     <-- Trap              In library load
2897  *     Set parameters in library
2898  *                     <-- Trap              Finished loading
2899  *     Restore code and leave paused
2900  *     Finalize library
2901  *       If finalizing fails, 
2902  *       init via iRPC
2903  *
2904  * Note: we've actually stopped trying to trap the library, since
2905  * setting arguments via inferior RPC is just as easy and a _lot_
2906  * cleaner.
2907  */
2908
2909 /*
2910  * In all cases, the process is left paused at the entry of main
2911  * (create) or where it was (attach). No permanent instrumentation
2912  * is inserted.
2913  */
2914
2915 // Load and initialize the runtime library: returns when the RT lib
2916 // is both loaded and initialized.
2917 // Return val: false=error condition
2918
2919 bool process::loadDyninstLib() {
2920   startup_printf("Entry to loadDyninstLib\n");
2921     // Wait for the process to get to an initialized (dlopen exists)
2922     // state
2923     while (!reachedBootstrapState(initialized_bs)) {
2924       startup_printf("Waiting for process to reach initialized state...\n");
2925        if(hasExited()) {
2926            return false;
2927        }
2928        getMailbox()->executeCallbacks(FILE__, __LINE__);
2929        getSH()->waitForEvent(evtProcessInit);
2930        getMailbox()->executeCallbacks(FILE__, __LINE__);
2931     }
2932     assert (isStopped());
2933     startup_printf("Stopped at entry of main\n");
2934
2935     // We've hit the initialization trap, so load dyninst lib and
2936     // force initialization
2937     pdstring buffer = pdstring("PID=") + pdstring(pid);
2938     buffer += pdstring(", initializing shared objects");       
2939     statusLine(buffer.c_str());
2940
2941     // Perform initialization...
2942     if (!dyn->initialize()) 
2943     {
2944        cerr << "Dyninst was unable to load the dyninst runtime library "
2945             << "into the application.  This may be caused by statically "
2946             << "linked executables, or by having dyninst linked against a "
2947             << "different version of libelf than it was built with." << endl;
2948        return false;
2949     }
2950     startup_printf("Initialized dynamic linking tracer\n");
2951
2952     // And get the list of all shared objects in the process. More properly,
2953     // get the address of dlopen.
2954     if (!processSharedObjects()) {
2955       startup_printf("Failed to get initial shared objects\n");
2956       return false;
2957     }
2958
2959     startup_printf("Processed initial shared objects:\n");
2960
2961     for (unsigned debug_iter = 1; debug_iter < mapped_objects.size(); debug_iter++)
2962         startup_printf("%d: %s\n", debug_iter, 
2963                        mapped_objects[debug_iter]->debugString().c_str());
2964
2965     startup_printf("----\n");
2966
2967     if (dyninstLibAlreadyLoaded()) {
2968         logLine("ERROR: dyninst library already loaded, we missed initialization!");
2969         // TODO: We could handle this case better :)
2970         assert(0);
2971     }
2972     
2973     if (!getDyninstRTLibName()) {
2974         startup_printf("Failed to get Dyninst RT lib name\n");
2975         return false;
2976     }
2977     startup_printf("%s[%d]: Got Dyninst RT libname: %s\n", FILE__, __LINE__,
2978                    dyninstRT_name.c_str());
2979
2980     // Force a call to dlopen(dyninst_lib)
2981     buffer = pdstring("PID=") + pdstring(pid);
2982     buffer += pdstring(", loading dyninst library");       
2983     statusLine(buffer.c_str());
2984
2985     startup_printf("%s[%d]: Starting load of Dyninst library...\n", FILE__, __LINE__);
2986     loadDYNINSTlib();
2987     startup_printf("Think we have Dyninst RT lib set up...\n");
2988     
2989     setBootstrapState(loadingRT_bs);
2990     
2991     if (!continueProc()) {
2992         assert(0);
2993     }
2994     // Loop until the dyninst lib is loaded
2995     while (!reachedBootstrapState(loadedRT_bs)) {
2996         if(hasExited()) {
2997             startup_printf("Odd, process exited while waiting for Dyninst RT lib load\n");
2998             return false;
2999         }
3000         getSH()->waitForEvent(evtProcessLoadedRT);
3001     }
3002     getMailbox()->executeCallbacks(FILE__, __LINE__);
3003     // We haven't inserted a trap at dlopen yet (as we require the runtime lib for that)
3004     // So re-check all loaded libraries (and add to the list gotten earlier)
3005     // We force a compare even though the PC is not at the correct address.
3006     dyn->set_force_library_check();
3007     handleIfDueToSharedObjectMapping();
3008     dyn->unset_force_library_check();
3009
3010     // Make sure the library was actually loaded
3011     if (!runtime_lib) {
3012         fprintf(stderr, "%s[%d]:  Don't have runtime library handle\n", __FILE__, __LINE__);
3013         return false;
3014     }
3015     
3016     buffer = pdstring("PID=") + pdstring(pid);
3017     buffer += pdstring(", initializing mutator-side structures");
3018     statusLine(buffer.c_str());    
3019
3020     // The library is loaded, so do mutator-side initialization
3021     buffer = pdstring("PID=") + pdstring(pid);
3022     buffer += pdstring(", finalizing RT library");
3023     statusLine(buffer.c_str());    
3024     startup_printf("(%d) finalizing dyninst RT library\n", getPid());
3025
3026     if (!finalizeDyninstLib())
3027       startup_printf("%s[%d]:  failed to finalize dyninst lib\n", __FILE__, __LINE__);
3028
3029     if (!reachedBootstrapState(bootstrapped_bs)) {
3030         // For some reason we haven't run dyninstInit successfully.
3031         // Probably because we didn't set parameters before 
3032         // dyninstInit was automatically run. Catchup with
3033         // an inferiorRPC is the best bet.
3034         buffer = pdstring("PID=") + pdstring(pid);
3035         buffer += pdstring(", finalizing library via inferior RPC");
3036         statusLine(buffer.c_str());    
3037         iRPCDyninstInit();        
3038     }
3039
3040     buffer = pdstring("PID=") + pdstring(pid);
3041     buffer += pdstring(", dyninst RT lib ready");
3042     statusLine(buffer.c_str());    
3043
3044     return true;
3045 }
3046
3047 // Set the shared object mapping for the RT library
3048 bool process::setDyninstLibPtr(mapped_object *RTobj) {
3049     assert (!runtime_lib);
3050
3051     runtime_lib = RTobj;
3052     return true;
3053 }
3054
3055
3056 // Set up the parameters for DYNINSTinit in the RT lib
3057
3058 bool process::setDyninstLibInitParams() {
3059
3060    startup_cerr << "process::setDYNINSTinitArguments()" << endl;
3061
3062    int pid = getpid();
3063    
3064    // Cause: 
3065    // 1 = created
3066    // 2 = forked
3067    // 3 = attached
3068    
3069    int cause;
3070    switch (creationMechanism_) {
3071    case created_cm:
3072        cause = 1;
3073        break;
3074    case attached_cm:
3075        cause = 3;
3076        break;
3077    case attachedToCreated_cm:
3078        // Uhhh....
3079        cause = 3;
3080        break;
3081    default:
3082        assert(0);
3083        break;
3084    }
3085    
3086    // Now we write these variables into the following global vrbles
3087    // in the dyninst library:
3088    // libdyninstAPI_RT_init_localCause
3089    // libdyninstAPI_RT_init_localPid
3090
3091    pdvector<int_variable *> vars;
3092
3093    if (!findVarsByAll("libdyninstAPI_RT_init_localCause",
3094                       vars,
3095                       dyninstRT_name))
3096        if (!findVarsByAll("_libdyninstAPI_RT_init_localCause",
3097                           vars))
3098            assert(0 && "Could not find necessary internal variable");
3099    assert(vars.size() == 1);
3100    writeDataSpace((void*)vars[0]->getAddress(), sizeof(int), (void *)&cause);
3101    vars.clear();
3102
3103    if (!findVarsByAll("libdyninstAPI_RT_init_localPid", vars))
3104        if (!findVarsByAll("_libdyninstAPI_RT_init_localPid", vars))
3105            assert(0 && "Could not find necessary internal variable");
3106    assert(vars.size() == 1);
3107    writeDataSpace((void*)vars[0]->getAddress(), sizeof(int), (void *)&pid);
3108    vars.clear();   
3109
3110    if (!findVarsByAll("libdyninstAPI_RT_init_maxthreads", vars))
3111        if (!findVarsByAll("_libdyninstAPI_RT_init_maxthreads", vars))
3112            assert(0 && "Could not find necessary internal variable");
3113    assert(vars.size() == 1);
3114    writeDataSpace((void*)vars[0]->getAddress(), sizeof(int), (void *) &max_number_of_threads);
3115    vars.clear();   
3116
3117    startup_cerr << "process::installBootstrapInst() complete" << endl;   
3118    return true;
3119 }
3120
3121 // Call DYNINSTinit via an inferiorRPC
3122 bool process::iRPCDyninstInit() {
3123     startup_printf("[%s:%u] - Running DYNINSTinit via irpc\n", __FILE__, __LINE__);
3124     // Duplicates the parameter code in setDyninstLibInitParams()
3125     int pid = getpid();
3126     int maxthreads = maxNumberOfThreads();
3127
3128     int cause = 0;
3129     switch (creationMechanism_) {
3130     case created_cm:
3131         cause = 1;
3132         break;
3133     case attached_cm:
3134         cause = 3;
3135         break;
3136     case attachedToCreated_cm:
3137         // Uhhh....
3138         cause = 3;
3139         break;
3140     default:
3141         assert(0);
3142         break;
3143    }
3144
3145     pdvector<AstNode*> the_args(3);
3146     the_args[0] = new AstNode(AstNode::Constant, (void*)(Address)cause);
3147     the_args[1] = new AstNode(AstNode::Constant, (void*)(Address)pid);
3148     the_args[2] = new AstNode(AstNode::Constant, (void*)(Address)maxthreads);
3149     AstNode *dynInit = new AstNode("DYNINSTinit", the_args);
3150     removeAst(the_args[0]); removeAst(the_args[1]); removeAst(the_args[2]);
3151     getRpcMgr()->postRPCtoDo(dynInit,
3152                              true, // Don't update cost
3153                              process::DYNINSTinitCompletionCallback,
3154                              NULL, // No user data
3155                              true, // Use reserved memory
3156                              NULL, NULL);// No particular thread or LWP
3157
3158     // We loop until dyninst init has run (check via the callback)
3159      inferiorrpc_printf("%s[%d]:  waiting for rpc completion\n", FILE__, __LINE__);
3160     while (!reachedBootstrapState(bootstrapped_bs)) {
3161         getRpcMgr()->launchRPCs(false); // false: not running
3162         if(hasExited()) {
3163             fprintf(stderr, "%s[%d][%s]:  unexpected exit\n", __FILE__, __LINE__, getThreadStr(getExecThreadID()));
3164            return false;
3165         }
3166         getMailbox()->executeCallbacks(FILE__, __LINE__);
3167         getSH()->waitForEvent(evtRPCSignal, this, NULL /*lwp*/, statusRPCDone);
3168         getMailbox()->executeCallbacks(FILE__, __LINE__);
3169     }
3170     startup_printf("%s[%d][%s]:  bootstrapped\n", __FILE__, __LINE__, getThreadStr(getExecThreadID()));
3171     startup_printf("[%s:%u] - Ran DYNINSTinit via irpc\n", __FILE__, __LINE__);
3172     return true;
3173 }
3174
3175 bool process::attach() {
3176    dictionary_hash_iter<unsigned, dyn_lwp *> lwp_iter(real_lwps);
3177    dyn_lwp *lwp;
3178    unsigned index;
3179    assert(getRepresentativeLWP());  // we expect this to be defined
3180    // Though on linux, if process found to be MT, there will be no
3181    // representativeLWP since there is no lwp which controls the entire
3182    // process for MT linux.
3183
3184    startup_printf("[%d]: attaching to representative LWP\n", getPid());
3185
3186    if(! getRepresentativeLWP()->attach())
3187       return false;
3188
3189    while (lwp_iter.next(index, lwp)) {
3190        startup_printf("[%d]: attaching to LWP %d\n", getPid(), index);
3191
3192       if (!lwp->attach()) {
3193          deleteLWP(lwp);
3194          return false;
3195       }
3196    }
3197    // Fork calls attach() but is probably past this; silencing warning
3198    if (!reachedBootstrapState(attached_bs))
3199        setBootstrapState(attached_bs);
3200    getSH()->signalActiveProcess();
3201    startup_printf("[%d]: setting process flags\n", getPid());
3202    return setProcessFlags();
3203 }
3204
3205
3206 // Callback: finish mutator-side processing for dyninst lib
3207
3208 bool process::finalizeDyninstLib() 
3209 {
3210    startup_printf("%s[%d]:  isAttached() = %s\n", __FILE__, __LINE__, isAttached() ? "true" : "false");
3211    startup_printf("%s[%d]: %s\n", __FILE__, __LINE__, getStatusAsString().c_str());
3212    
3213     assert (isStopped());
3214     if (reachedBootstrapState(bootstrapped_bs)) {
3215         return true;
3216     }
3217
3218    DYNINST_bootstrapStruct bs_record;
3219    if (!extractBootstrapStruct(&bs_record))
3220       assert(false);
3221
3222    // Read the structure; if event 0 then it's undefined! (not yet written)
3223    if (bs_record.event == 0)
3224    {
3225        startup_printf("[%s:%u] - bs_record.event is undefined\n");
3226        return false;
3227    }
3228
3229    // Now that we have the dyninst library loaded, insert the hooks to dlopen/dlclose
3230    // (which may require the dyninst library)
3231     
3232    assert(bs_record.event == 1 || bs_record.event == 2 || bs_record.event==3);
3233
3234    bool calledFromFork = (bs_record.event == 2);
3235    bool calledFromAttach = (bs_record.event == 3);
3236
3237    pdvector<int_variable *> obsCostVec;
3238    if (!findVarsByAll("DYNINSTobsCostLow", obsCostVec))
3239        assert(0);
3240    assert(obsCostVec.size() == 1);
3241
3242    costAddr_ = obsCostVec[0]->getAddress();
3243
3244    assert(costAddr_);
3245
3246    // Set breakpoints to detect (un)loaded libraries
3247    // Do this after the observed cost is set, in case we use instrumentation
3248    if (!dyn->installTracing()) assert (0 && "Failed to install library mapping hooks");
3249
3250    if (!calledFromFork) {
3251
3252        // Install initial instrumentation requests
3253        pdstring str=pdstring("PID=") + pdstring(bs_record.pid) + ", installing default (DYNINST) inst...";
3254        statusLine(str.c_str());
3255        
3256        extern pdvector<instMapping*> initialRequests; // init.C
3257
3258        // Install any global instrumentation requests
3259        installInstrRequests(initialRequests);
3260
3261        // Install process-specific instrumentation requests
3262        installInstrRequests(tracingRequests);
3263        
3264        // Install our system call tracing
3265        tracedSyscalls_ = new syscallNotification(this);
3266
3267        //#ifdef i386_unknown_linux2_0
3268        //if(pdFlavor != "mpi") {
3269        //#endif
3270           // TODO: prefork and pre-exit should depend on whether a callback is defined
3271           if (!tracedSyscalls_->installPreFork()) 
3272              cerr << "Warning: failed pre-fork notification setup" << endl;
3273           if (!tracedSyscalls_->installPostFork()) 
3274              cerr << "Warning: failed post-fork notification setup" << endl;
3275           if (!tracedSyscalls_->installPreExec()) 
3276              cerr << "Warning: failed pre-exec notification setup" << endl;
3277           if (!tracedSyscalls_->installPostExec()) 
3278              cerr << "Warning: failed post-exec notification setup" << endl;
3279           if (!tracedSyscalls_->installPreExit()) 
3280              cerr << "Warning: failed pre-exit notification setup" << endl;
3281           if (!tracedSyscalls_->installPreLwpExit()) 
3282              cerr << "Warning: failed pre-lwp-exit notification setup" << endl;
3283           //#ifdef i386_unknown_linux2_0
3284           //}
3285           //#endif
3286    }
3287    else { // called from a forking process
3288        process *parentProcess = process::findProcess(bs_record.ppid);
3289        if (parentProcess) {
3290            if (parentProcess->status() == stopped) {
3291                if (!parentProcess->continueProc())
3292                    assert(false);
3293            }
3294            else
3295                parentProcess->continueAfterNextStop();
3296        }
3297        
3298    }
3299
3300    startup_printf("Initializing tramp guard\n");
3301    if (!initTrampGuard())
3302       assert(0);
3303
3304 #if defined(cap_threads)
3305    if (multithread_capable())
3306    {
3307       initMT();
3308    }
3309 #endif
3310
3311    if (!calledFromAttach) {
3312        pdstring str=pdstring("PID=") + pdstring(bs_record.pid) + ", dyninst ready.";
3313        statusLine(str.c_str());
3314    }
3315
3316    startup_printf("%s[%d]:  bootstrap done\n", __FILE__, __LINE__);
3317    // Ready to rock
3318    setBootstrapState(bootstrapped_bs);
3319    getSH()->signalEvent(evtProcessInitDone);
3320
3321    return true;
3322 }
3323
3324 void finalizeDyninstLibWrapper(process *p) 
3325 {
3326   global_mutex->_Lock(FILE__, __LINE__);
3327   p->finalizeDyninstLib();
3328   global_mutex->_Unlock(FILE__, __LINE__);
3329 }
3330 void process::DYNINSTinitCompletionCallback(process* theProc,
3331                                             unsigned /* rpc_id */,
3332                                             void* /*userData*/, // user data
3333                                             void* /*ret*/) // return value from DYNINSTinit
3334 {
3335     //global_mutex->_Lock(FILE__, __LINE__);
3336     startup_printf("%s[%d]:  about to finalize Dyninst Lib\n", __FILE__, __LINE__);
3337     theProc->finalizeDyninstLib();
3338     //FinalizeRTLibCallback *cbp = new FinalizeRTLibCallback(finalizeDyninstLibWrapper);
3339     //FinalizeRTLibCallback &cb = *cbp;
3340     //cb.setSynchronous(false);
3341     //cb(theProc);
3342     //global_mutex->_Unlock(FILE__, __LINE__);
3343 }
3344 /////////////////////////////////////////
3345 // Function lookup...
3346 /////////////////////////////////////////
3347
3348 bool process::findFuncsByAll(const pdstring &funcname,
3349                              pdvector<int_function *> &res,
3350                              const pdstring &libname) { // = "", btw
3351     
3352     unsigned starting_entries = res.size(); // We'll return true if we find something
3353     for (unsigned i = 0; i < mapped_objects.size(); i++) {
3354         if (libname == "" ||
3355             mapped_objects[i]->fileName() == libname ||
3356             mapped_objects[i]->fullName() == libname) {
3357             const pdvector<int_function *> *pretty = mapped_objects[i]->findFuncVectorByPretty(funcname);
3358             if (pretty) {
3359                 // We stop at first match...
3360                 for (unsigned pm = 0; pm < pretty->size(); pm++) {
3361                     res.push_back((*pretty)[pm]);
3362                 }
3363             }
3364             else {
3365                 const pdvector<int_function *> *mangled = mapped_objects[i]->findFuncVectorByMangled(funcname);
3366                 if (mangled) {
3367                     for (unsigned mm = 0; mm < mangled->size(); mm++) {
3368                         res.push_back((*mangled)[mm]);
3369                     }
3370                 }
3371             }
3372         }
3373     }
3374     return (res.size() != starting_entries);
3375 }
3376
3377
3378 bool process::findFuncsByPretty(const pdstring &funcname,
3379                              pdvector<int_function *> &res,
3380                              const pdstring &libname) { // = "", btw
3381
3382     unsigned starting_entries = res.size(); // We'll return true if we find something
3383
3384     for (unsigned i = 0; i < mapped_objects.size(); i++) {
3385         if (libname == "" ||
3386             mapped_objects[i]->fileName() == libname ||
3387             mapped_objects[i]->fullName() == libname) {
3388             const pdvector<int_function *> *pretty = mapped_objects[i]->findFuncVectorByPretty(funcname);
3389             if (pretty) {
3390                 // We stop at first match...
3391                 for (unsigned pm = 0; pm < pretty->size(); pm++) {
3392                     res.push_back((*pretty)[pm]);
3393                 }
3394             }
3395         }
3396     }
3397     return res.size() != starting_entries;
3398 }
3399
3400
3401 bool process::findFuncsByMangled(const pdstring &funcname,
3402                                  pdvector<int_function *> &res,
3403                                  const pdstring &libname) { // = "", btw
3404     unsigned starting_entries = res.size(); // We'll return true if we find something
3405
3406     for (unsigned i = 0; i < mapped_objects.size(); i++) {
3407         if (libname == "" ||
3408             mapped_objects[i]->fileName() == libname ||
3409             mapped_objects[i]->fullName() == libname) {
3410             const pdvector<int_function *> *mangled = 
3411                mapped_objects[i]->findFuncVectorByMangled(funcname);
3412             if (mangled) {
3413                 for (unsigned mm = 0; mm < mangled->size(); mm++) {
3414                    res.push_back((*mangled)[mm]);
3415                 }
3416             }
3417         }
3418     }
3419     return res.size() != starting_entries;
3420 }
3421
3422 int_function *process::findOnlyOneFunction(const pdstring &name,
3423                                            const pdstring &lib) {
3424     pdvector<int_function *> allFuncs;
3425     if (!findFuncsByAll(name, allFuncs, lib))
3426         return NULL;
3427     if (allFuncs.size() > 1) {
3428         cerr << "Warning: multiple matches for " << name << ", returning first" << endl;
3429     }
3430     return allFuncs[0];
3431 }
3432
3433 /////////////////////////////////////////
3434 // Variable lookup...
3435 /////////////////////////////////////////
3436
3437 bool process::findVarsByAll(const pdstring &varname,
3438                             pdvector<int_variable *> &res,
3439                             const pdstring &libname) { // = "", btw
3440     unsigned starting_entries = res.size(); // We'll return true if we find something
3441     
3442     for (unsigned i = 0; i < mapped_objects.size(); i++) {
3443         if (libname == "" ||
3444             mapped_objects[i]->fileName() == libname ||
3445             mapped_objects[i]->fullName() == libname) {
3446             const pdvector<int_variable *> *pretty = mapped_objects[i]->findVarVectorByPretty(varname);
3447             if (pretty) {
3448                 // We stop at first match...
3449                 for (unsigned pm = 0; pm < pretty->size(); pm++) {
3450                     res.push_back((*pretty)[pm]);
3451                 }
3452             }
3453             else {
3454                 const pdvector<int_variable *> *mangled = mapped_objects[i]->findVarVectorByMangled(varname);
3455                 if (mangled) {
3456                     for (unsigned mm = 0; mm < mangled->size(); mm++) {
3457                         res.push_back((*mangled)[mm]);
3458                     }
3459                 }
3460             }
3461         }
3462     }
3463     return res.size() != starting_entries;
3464 }
3465
3466
3467
3468 // Get me a pointer to the instruction: the return is a local
3469 // (mutator-side) store for the mutatee. This may duck into the local
3470 // copy for images, or a relocated function's self copy.
3471 // TODO: is this really worth it? Or should we just use ptrace?
3472
3473 void *process::getPtrToInstruction(Address addr) {
3474     codeRange *range;
3475     if (codeSections_.find(addr, range)) {
3476         return range->getPtrToInstruction(addr);
3477     }
3478     else if (dataSections_.find(addr, range)) {
3479         mappedObjData *data = dynamic_cast<mappedObjData *>(range);
3480         assert(data);
3481         return data->obj->getPtrToData(addr);
3482     }
3483     return NULL;
3484 }
3485
3486 bool process::isValidAddress(Address addr) {
3487     // "Is this part of the process address space?"
3488     // We should codeRange data sections as well... since we don't, this is 
3489     // slow.
3490     codeRange *dontcare;
3491     if (codeSections_.find(addr, dontcare))
3492         return true;
3493     if (dataSections_.find(addr, dontcare))
3494         return true;
3495     fprintf(stderr, "Warning: address 0x%x not valid!\n",
3496             addr);
3497     return false;
3498 }        
3499
3500 dyn_thread *process::STdyn_thread() { 
3501    assert(! multithread_capable());
3502    assert(threads.size()>0);
3503    return threads[0];
3504 }
3505
3506 #if !defined(BPATCH_LIBRARY)
3507 void process::processCost(unsigned obsCostLow,
3508                           timeStamp wallTime,
3509                           timeStamp processTime) {
3510   // wallTime and processTime should compare to DYNINSTgetWallTime() and
3511   // DYNINSTgetCPUtime().
3512
3513   // check for overflow, add to running total, convert cycles to seconds, and
3514   // report.  Member vrbles of class process: lastObsCostLow and cumulativeObsCost
3515   // (the latter a 64-bit value).
3516
3517   // code to handle overflow used to be in rtinst; we borrow it pretty much
3518   // verbatim. (see rtinst/RTposix.c)
3519   if (obsCostLow < lastObsCostLow) {
3520     // we have a wraparound
3521     cumulativeObsCost += ((unsigned)0xffffffff - lastObsCostLow) + obsCostLow + 1;
3522   }
3523   else
3524     cumulativeObsCost += (obsCostLow - lastObsCostLow);
3525   
3526   lastObsCostLow = obsCostLow;
3527   //  sampleVal_cerr << "processCost- cumulativeObsCost: " << cumulativeObsCost << "\n"; 
3528   timeLength observedCost((int64_t) cumulativeObsCost, getCyclesPerSecond());
3529   // timeUnit tu = getCyclesPerSecond(); // just used to print out
3530   //  sampleVal_cerr << "processCost: cyclesPerSecond=" << tu
3531   //             << "; cum obs cost=" << observedCost << "\n";
3532   
3533   // Notice how most of the rest of this is copied from processCost() of
3534   // metric.C.  Be sure to keep the two "in sync"!
3535
3536   extern costMetric *totalPredictedCost; // init.C
3537   extern costMetric *observed_cost;      // init.C
3538   
3539   const timeStamp lastProcessTime = 
3540     totalPredictedCost->getLastSampleProcessTime(this);
3541   //  sampleVal_cerr << "processCost- lastProcessTime: " <<lastProcessTime << "\n";
3542   // find the portion of uninstrumented time for this interval
3543   timeLength userPredCost = timeLength::sec() + getCurrentPredictedCost();
3544   //  sampleVal_cerr << "processCost- userPredCost: " << userPredCost << "\n";
3545   const double unInstTime = (processTime - lastProcessTime) / userPredCost; 
3546   //  sampleVal_cerr << "processCost- unInstTime: " << unInstTime << "\n";
3547   // update predicted cost
3548   // note: currentPredictedCost is the same for all processes
3549   //       this should be changed to be computed on a per process basis
3550   pdSample newPredCost = totalPredictedCost->getCumulativeValue(this);
3551   //  sampleVal_cerr << "processCost- newPredCost: " << newPredCost << "\n";
3552   timeLength tempPredCost = getCurrentPredictedCost() * unInstTime;
3553   //  sampleVal_cerr << "processCost- tempPredCost: " << tempPredCost << "\n";
3554   newPredCost += pdSample(tempPredCost.getI(timeUnit::ns()));
3555   //  sampleVal_cerr << "processCost- tempPredCost: " << newPredCost << "\n";
3556   totalPredictedCost->updateValue(this, wallTime, newPredCost, processTime);
3557   // update observed cost
3558   pdSample sObsCost(observedCost);
3559   observed_cost->updateValue(this, wallTime, sObsCost, processTime);
3560 }
3561 #endif
3562         
3563 // If true is passed for ignore_if_mt_not_set, then an error won't be
3564 // initiated if we're unable to determine if the program is multi-threaded.
3565 // We are unable to determine this if the daemon hasn't yet figured out what
3566 // libraries are linked against the application.  Currently, we identify an
3567 // application as being multi-threaded if it is linked against a thread
3568 // library (eg. libpthreads.a on AIX).  There are cases where we are querying
3569 // whether the app is multi-threaded, but it can't be determined yet but it
3570 // also isn't necessary to know.
3571 bool process::multithread_capable(bool ignore_if_mt_not_set)
3572 {
3573 #if !defined(cap_threads)
3574    return false;
3575 #endif
3576
3577    if(cached_result != not_cached) {
3578        if(cached_result == cached_mt_true) {
3579            return true;
3580        } else {
3581            assert(cached_result == cached_mt_false);
3582            return false;
3583        }
3584    }
3585    
3586    if(mapped_objects.size() <= 1) {
3587        if(! ignore_if_mt_not_set) {
3588            cerr << "   can't query MT state, assert\n";
3589            assert(false);
3590        }
3591        return false;
3592    }
3593
3594    if(findObject("libthread.so*", true) ||  // Solaris
3595       findObject("libpthreads.*", true)  ||  // AIX
3596       findObject("libpthread.so*", true))   // Linux
3597    {
3598        cached_result = cached_mt_true;
3599        return true;
3600    } else {
3601        cached_result = cached_mt_false;
3602        return false;
3603    }
3604 }
3605
3606 void process::addThread(dyn_thread *thread)
3607 {
3608    getRpcMgr()->addThread(thread);
3609    threads.push_back(thread);
3610 }
3611
3612 bool process::multithread_ready(bool ignore_if_mt_not_set) {
3613    if (!multithread_capable(ignore_if_mt_not_set))
3614       return false;
3615    return isBootstrappedYet();
3616 }
3617
3618 dyn_lwp *process::query_for_stopped_lwp() {
3619    dyn_lwp *foundLWP = NULL;
3620    dictionary_hash_iter<unsigned, dyn_lwp *> lwp_iter(real_lwps);
3621    dyn_lwp *lwp;
3622    unsigned index;
3623
3624    if(IndependentLwpControl()) {
3625       while (lwp_iter.next(index, lwp)) {
3626          if(lwp->status() == stopped || lwp->status() == neonatal) {
3627             foundLWP = lwp;
3628             break;
3629          }
3630       }
3631       if(foundLWP == NULL  &&  getRepresentativeLWP() != NULL) {
3632          if(getRepresentativeLWP()->status() == stopped ||
3633             getRepresentativeLWP()->status() == neonatal)
3634             foundLWP = getRepresentativeLWP();
3635       }
3636    } else {
3637       if(this->status() == stopped || this->status() == neonatal) {
3638          foundLWP = getRepresentativeLWP();
3639       }
3640    }
3641
3642    return foundLWP;
3643 }
3644
3645 dyn_lwp *process::query_for_running_lwp() {
3646    dyn_lwp *foundLWP = NULL;
3647    dictionary_hash_iter<unsigned, dyn_lwp *> lwp_iter(real_lwps);
3648    dyn_lwp *lwp;
3649    unsigned index;
3650
3651    if(IndependentLwpControl()) {
3652       while (lwp_iter.next(index, lwp)) {
3653          if(lwp->status() == running || lwp->status() == neonatal) {
3654             foundLWP = lwp;
3655             break;
3656