Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / aix.C
1 /*
2  * Copyright (c) 1996-2009 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  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 // $Id: aix.C,v 1.247 2008/09/03 06:08:44 jaw Exp $
33
34 #include <dlfcn.h>
35 #include <sys/types.h>
36 #include <sys/ldr.h>
37 #include <termio.h>
38
39 #include <pthread.h>
40
41 #include "common/h/headers.h"
42 #include "common/h/Types.h"
43 #include "common/h/Dictionary.h"
44 #include "common/h/pathName.h"
45 #include "common/h/debugOstream.h"
46
47 #include "symtabAPI/h/Symtab.h"
48
49 #include "dyninstAPI/src/os.h"
50 #include "dyninstAPI/src/signalhandler.h"
51 #include "dyninstAPI/src/signalgenerator.h"
52 #include "dyninstAPI/src/process.h"
53 #include "dyninstAPI/src/dyn_lwp.h"
54 #include "dyninstAPI/src/dyn_thread.h"
55 #include "dyninstAPI/src/symtab.h"
56 #include "common/h/stats.h"
57 #include "dyninstAPI/src/instPoint.h"
58 #include "dyninstAPI/src/baseTramp.h"
59 #include "dyninstAPI/src/miniTramp.h"
60 #include "dyninstAPI/src/inst-power.h" // Tramp constants
61 #include "dyninstAPI/src/multiTramp.h"
62 #include "dyninstAPI/src/InstrucIter.h"
63
64 #include "dyninstAPI/src/registerSpace.h"
65
66 #include "dyninstAPI/h/BPatch.h"
67 #include "dyninstAPI/h/BPatch_process.h"
68 #include "dyninstAPI/h/BPatch_function.h"
69
70
71 #include "mapped_module.h"
72 #include "mapped_object.h"
73
74 #include "ast.h"
75
76 #if defined(cap_proc)
77 #include <sys/procfs.h>
78 #endif
79
80 #include "writeBackXCOFF.h"
81
82 #include "dyninstAPI/src/debug.h"
83
84 extern "C" {
85 extern int ioctl(int, int, ...);
86 };
87
88 // The frame threesome: normal (singlethreaded), thread (given a pthread ID),
89 // and LWP (given an LWP/kernel thread).
90 // The behavior is identical unless we're in a leaf node where
91 // the LR is in a register, then it's different.
92
93 Frame Frame::getCallerFrame()
94 {
95   typedef struct {
96     unsigned oldFp;
97     unsigned savedCR;
98     unsigned savedLR;
99     unsigned compilerInfo;
100     unsigned binderInfo;
101     unsigned savedTOC;
102   } linkArea_t;
103   
104   const int savedLROffset=8;
105   //const int compilerInfoOffset=12;
106   
107   linkArea_t thisStackFrame;
108   linkArea_t lastStackFrame;
109   linkArea_t stackFrame;
110   Address basePCAddr;
111
112   Address newPC=0;
113   Address newFP=0;
114   Address newpcAddr=0;
115
116   // Are we in a leaf function?
117   bool isLeaf = false;
118   bool noFrame = false;
119
120   codeRange *range = getRange();
121   int_function *func = range->is_function();
122
123   if (uppermost_) {
124     if (func) {
125       isLeaf = func->makesNoCalls();
126       noFrame = func->hasNoStackFrame();
127     }
128   }
129
130   // Get current stack frame link area
131   if (!getProc()->readDataSpace((caddr_t)fp_, sizeof(linkArea_t),
132                         (caddr_t)&thisStackFrame, false))
133     return Frame();
134
135   getProc()->readDataSpace((caddr_t) thisStackFrame.oldFp, sizeof(linkArea_t),
136                            (caddr_t) &lastStackFrame, false);
137   
138   if (noFrame) {
139     stackFrame = thisStackFrame;
140     basePCAddr = fp_;
141   }
142   else {
143     stackFrame = lastStackFrame;
144     basePCAddr = thisStackFrame.oldFp;
145   }
146
147   // See if we're in instrumentation
148   baseTrampInstance *bti = NULL;
149
150   if (range->is_multitramp()) {
151       bti = range->is_multitramp()->getBaseTrampInstanceByAddr(getPC());
152       if (bti) {
153           // If we're not in instru, then re-set this to NULL
154           if (!bti->isInInstru(getPC()))
155               bti = NULL;
156       }
157   }
158   else if (range->is_minitramp()) {
159       bti = range->is_minitramp()->baseTI;
160   }
161
162   if (bti) {
163       // Oy. We saved the LR in the middle of the tramp; so pull it out
164       // by hand.
165       newpcAddr = fp_ + TRAMP_SPR_OFFSET + STK_LR;         
166       newFP = thisStackFrame.oldFp;
167
168       if (!getProc()->readDataSpace((caddr_t) newpcAddr,
169                                     sizeof(Address),
170                                     (caddr_t) &newPC, false))
171           return Frame();
172
173       // Instrumentation makes its own frame; we want to skip the
174       // function frame if there is one as well.
175       instPoint *point = bti->baseT->instP();
176       assert(point); // Will only be null if we're in an inferior RPC, which can't be.
177
178       // If we're inside the function (callSite or arbitrary; bad assumption about
179       // arbitrary but we don't know exactly where the frame was constructed) and the
180       // function has a frame, tear it down as well.
181       if ((point->getPointType() == callSite ||
182           point->getPointType() == otherPoint) &&
183           !point->func()->hasNoStackFrame()) {
184           if (!getProc()->readDataSpace((caddr_t) thisStackFrame.oldFp,
185                                         sizeof(unsigned),
186                                         (caddr_t) &newFP, false))
187               return Frame();
188       }
189       // Otherwise must be at a reloc insn
190   }
191   else if (isLeaf) {
192       // isLeaf: get the LR from the register instead of saved location on the stack
193       if (lwp_ && lwp_->get_lwp_id()) {
194           dyn_saved_regs regs;
195           bool status = lwp_->getRegisters(&regs);
196           if (! status) {
197               return Frame();
198           }
199           newPC = regs.theIntRegs.__lr;
200           newpcAddr = (Address) 1; 
201           /* I'm using an address to signify a register */
202       }
203       else if (thread_ && thread_->get_tid()) {
204           cerr << "NOT IMPLEMENTED YET" << endl;
205       }
206       else { // normal
207           dyn_saved_regs regs;
208           bool status = getProc()->getRepresentativeLWP()->getRegisters(&regs);
209           if (!status) {
210               return Frame();
211           }
212           newPC = regs.theIntRegs.__lr;
213           newpcAddr = (Address) 1;
214       }
215       
216
217       if (noFrame)
218           newFP = fp_;
219       else
220           newFP = thisStackFrame.oldFp;
221   }
222   else {
223       // Common case.
224       newPC = stackFrame.savedLR;
225       newpcAddr = basePCAddr + savedLROffset;
226       if (noFrame)
227         newFP = fp_;
228       else
229         newFP = thisStackFrame.oldFp;
230   }
231
232 #ifdef DEBUG_STACKWALK
233   fprintf(stderr, "PC %x, FP %x\n", newPC, newFP);
234 #endif
235   return Frame(newPC, newFP, 0, newpcAddr, this);
236 }
237
238 bool Frame::setPC(Address newpc) 
239 {
240     // Encapsulate all the logic necessary to set a new PC in a frame
241     // If the function is a leaf function, we need to overwrite the LR directly.
242     // The return addr for a frame is basically the parent's pc...
243     
244     if (pc_ == newpc) return true;
245     
246     if (isUppermost()) {
247         if (getLWP())
248             getLWP()->changePC(newpc, NULL);
249         else if (getThread())
250             getThread()->get_lwp()->changePC(newpc, NULL);
251         else 
252             getProc()->getRepresentativeLWP()->changePC(newpc, NULL);
253     }
254     else if (pcAddr_ == 1) {
255         // Stomp the LR
256         dyn_lwp *lwp = getLWP();
257         if (lwp && lwp->get_lwp_id()) {
258             // Get the current LR and reset it to our new version
259             dyn_saved_regs regs;
260             bool status = lwp->getRegisters(&regs);
261
262             if (!status) {
263                 bperr( "Failure to get registers in catchupSideEffect\n");
264                 return false;
265             }
266
267             regs.theIntRegs.__lr = newpc;
268
269             if (!lwp->restoreRegisters(regs)) {
270                 bperr( "Failure to restore registers in catchupSideEffect\n");
271                 return false;
272             }
273         }
274         else {
275             // Process-wide
276             dyn_saved_regs regs;
277             bool status = getProc()->getRepresentativeLWP()->getRegisters(&regs);
278
279             if (!status) {
280                 bperr("Failure to get registers in catchupSideEffect\n");
281                 return false;
282             }
283
284             regs.theIntRegs.__lr = newpc;
285             getProc()->getRepresentativeLWP()->restoreRegisters(regs);
286         }
287     }
288     else {    
289         // The LR is stored at pcAddr
290         if (!getProc()->writeDataSpace((void*)pcAddr_, sizeof(Address), 
291                                   &newpc))
292                   fprintf(stderr, "%s[%d]:  writeDataSpace failed\n", FILE__, __LINE__);
293     }
294     
295     pc_ = newpc;
296     range_ = NULL;
297     return true;
298 }
299
300 #ifdef DEBUG 
301 void decodeInstr(unsigned instr_raw) 
302 {
303   // Decode an instruction. Fun, eh?
304   union instructUnion instr;
305   instr.raw = instr_raw;
306
307   switch(instr.generic.op) {
308   case Bop:
309     bperr( "Branch (abs=%d, link=%d) to 0x%x\n",
310             instr.iform.aa, instr.iform.lk, instr.iform.li);
311     break;
312   case CMPIop:
313     bperr( "CMPI reg(%d), 0x%x\n",
314             instr.dform.ra, instr.dform.d_or_si);
315     break;
316   case SIop:
317     bperr( "SI src(%d), tgt(%d), 0x%x\n",
318             instr.dform.ra, instr.dform.rt, instr.dform.d_or_si);
319     break;
320   case CALop:
321     bperr( "CAL src(%d), tgt(%d), 0x%x\n",
322             instr.dform.ra, instr.dform.rt, instr.dform.d_or_si);
323     break;
324   case CAUop:
325     bperr( "CAU src(%d), tgt(%d), 0x%x\n",
326             instr.dform.ra, instr.dform.rt, instr.dform.d_or_si);
327     break;
328   case ORILop:
329     bperr( "ORIL src(%d), tgt(%d), 0x%x\n",
330             instr.dform.rt, instr.dform.ra, instr.dform.d_or_si);
331     break;
332   case ANDILop:
333     bperr( "CAU src(%d), tgt(%d), 0x%x\n",
334             instr.dform.rt, instr.dform.ra, instr.dform.d_or_si);
335     break;
336   case Lop:
337     bperr( "L src(%d)+0x%x, tgt(%d)\n",
338             instr.dform.ra, instr.dform.d_or_si, instr.dform.rt);
339     break;
340   case STop:
341     bperr( "L src(%d), tgt(%d)+0x%x\n",
342             instr.dform.rt, instr.dform.ra, instr.dform.d_or_si);
343     break;
344   case BCop:
345     bperr( "BC op(0x%x), CR bit(0x%x), abs(%d), link(%d), tgt(0x%x)\n",
346             instr.bform.bo, instr.bform.bi, instr.bform.aa, instr.bform.lk, instr.bform.bd);
347     break;
348   case BCLRop:
349     switch (instr.xform.xo) {
350     case BCLRxop:
351       bperr( "BCLR op(0x%x), bit(0x%x), link(%d)\n",
352               instr.xform.rt, instr.xform.ra, instr.xform.rc);
353       break;
354     default:
355       bperr( "%x\n", instr.raw);
356       break;
357     }
358     break;
359   case 0:
360     bperr( "NULL INSTRUCTION\n");
361     break;
362   default:
363     bperr( "Unknown instr with opcode %d\n",
364             instr.generic.op);
365
366     break;
367   }
368   return;
369 }      
370
371 #endif
372
373 // already setup on this FD.
374 // disconnect from controlling terminal 
375 void OS::osDisconnect(void) 
376 {
377   int ttyfd = open ("/dev/tty", O_RDONLY);
378   ioctl (ttyfd, TIOCNOTTY, NULL); 
379   P_close (ttyfd);
380 }
381
382 #if defined(duplicated_in_process_c_because_linux_ia64_needs_it)
383 Address process::getTOCoffsetInfo(Address dest)
384 {
385   // We have an address, and want to find the module the addr is
386   // contained in. Given the probabilities, we (probably) want
387   // the module dyninst_rt is contained in. 
388   // I think this is the right func to use
389
390   if (symbols->findFuncByAddr(dest, this))
391     return (Address) (symbols->getObject())->getTOCoffset();
392
393   if (shared_objects)
394       for (u_int j=0; j < shared_objects->size(); j++)
395       if (((*shared_objects)[j])->getImage()->findFuncByAddr(dest, this))
396         return (Address) (((*shared_objects)[j])->getImage()->getObject())->getTOCoffset();
397   // Serious error! Assert?
398   return 0;
399 }
400 #endif
401
402 #if defined(cap_dynamic_heap)
403
404 // 32-bit Address Space
405 // --------------------
406 // Segment 0 is kernel space, and off-limits
407 // Segment 1 is text space, and OK
408 // Segment 2-12 (c) is data space
409 // Segment 13 (d) is shared library text, and scavenged
410 // Segment 14 (e) is kernel space, and off-limits
411 // Segment 15 (f) is shared library data, and we don't care about it.
412 // However, we can scavenge some space in with the shared libraries.
413
414 static const Address lowest_addr32  = 0x10000000;
415 static const Address highest_addr32 = 0xe0000000;
416 static const Address data_hi_addr32 = 0xcfffff00;
417
418 // 64-bit Address Space
419 // --------------------
420 // 0x0000000000000000 -> 0x000000000fffffff Contains the kernel
421 // 0x00000000d0000000 -> 0x00000000dfffffff Contains 32-bit shared library text (inaccessable to 64-bit apps)
422 // 0x00000000e0000000 -> 0x00000000efffffff Shared memory segment available to 32-bit apps
423 // 0x00000000f0000000 -> 0x00000000ffffffff Contains 32-bit shared library data (inaccessable to 64-bit apps)
424 // 0x0000000100000000 -> 0x07ffffffffffffff Contains program data & text, plus shared memory or mmap segments
425 // 0x0800000000000000 -> 0x08ffffffffffffff Privately loaded 64-bit modules
426 // 0x0900000000000000 -> 0x09ffffffffffffff 64-bit shared library text & data
427 // 0x0f00000000000000 -> 0x0fffffffffffffff 64-bit application stack
428
429 #if defined(rs6000_ibm_aix64)
430 static const Address lowest_addr64  = 0x0000000100000000;
431 static const Address highest_addr64 = 0x0f00000000000000;
432 static const Address data_hi_addr64 = 0xffffffffffffffff;
433 // XXX
434 // According to the map above, data_hi_addr64 should probably be 0x0800000000000000.
435 // But, that causes us to write instrumentation into an invalid region of mutatee
436 // memory, though.  This should probably be fixed.
437 #endif
438
439 static const Address branch_range   = 0x01ff0000;
440 Address data_low_addr;
441
442 void process::inferiorMallocConstraints(Address near, Address &lo, 
443                                         Address &hi, inferiorHeapType type)
444 {
445    int addrWidth = getAddressWidth();
446    Address lowest_addr = 0, highest_addr = 0, data_hi_addr = 0;
447
448    switch (addrWidth) {
449       case 4:   lowest_addr = lowest_addr32;
450                highest_addr = highest_addr32;
451                data_hi_addr = data_hi_addr32;
452                break;
453 #if defined(rs6000_ibm_aix64)
454       case 8:   lowest_addr = lowest_addr64;
455                highest_addr = highest_addr64;
456                data_hi_addr = data_hi_addr64;
457                break;
458 #endif
459       default:  assert(0 && "Unknown address width");
460    }
461
462    // The notion of "near" only works on 32-bit processes. (For now?)
463    if (addrWidth == 4 && near) {
464       if (near < (lowest_addr + branch_range))
465          lo = lowest_addr;
466       else
467          lo = near - branch_range;
468
469       if (near > (highest_addr - branch_range))
470          hi = highest_addr;
471       else
472          hi = near + branch_range;
473    }
474
475    switch (type) {
476       case dataHeap:
477          // mmap, preexisting dataheap constraints
478          // so shift down lo and hi accordingly
479          if (lo < data_low_addr) {
480             lo = data_low_addr;
481             // Keep within branch range so that we know we can
482             // reach anywhere inside.
483             if (hi < (lo + branch_range))
484                hi = lo + branch_range;
485          }
486          if (hi > data_hi_addr) {
487             hi = data_hi_addr;
488             /*
489             // Not sure why this is commented out.
490             if (lo > (hi - branch_range))
491             lo = hi - branch_range;
492              */
493          }
494          break;
495       default:
496          // no change
497          break;
498    }
499 }
500
501 #endif
502
503
504 #define DEBUG_MSG 0 
505 #define _DEBUG_MSG 0
506 void compactLoadableSections(pdvector <imageUpdate*> imagePatches, pdvector<imageUpdate*> &newPatches){
507    int startPage, stopPage;
508    imageUpdate *patch;
509    //this function now returns only ONE section that is loadable.
510    int pageSize = getpagesize();
511
512    imageUpdate *curr, *next;
513    bool foundDup=true;
514    unsigned int j;
515
516    VECTOR_SORT(imagePatches, imageUpdateSort);
517
518    while(foundDup){
519       foundDup = false;
520       j =0;
521       while(imagePatches[j]->address==0 && j < imagePatches.size()){
522          j++;
523       }
524       curr = imagePatches[j];
525
526       for(j++;j<imagePatches.size();j++){
527          next = imagePatches[j];                
528          if(curr->address == next->address){
529             //duplicate
530             //find which is bigger and save that one.
531             if(curr->size > next->size){
532                next->address=0;
533             }else{
534                curr->address=0;
535                curr=next;
536             }
537             foundDup =true;
538          }else{
539             curr=next;
540          }
541
542       }
543       VECTOR_SORT(imagePatches, imageUpdateSort);
544    }
545
546
547         for(unsigned int i=0;i<imagePatches.size();i++){
548                 if(imagePatches[i]->address!=0){
549                         imagePatches[i]->startPage = imagePatches[i]->address- imagePatches[i]->address%pageSize;
550                         imagePatches[i]->stopPage = imagePatches[i]->address + imagePatches[i]->size- 
551                                         (imagePatches[i]->address + imagePatches[i]->size )%pageSize;
552
553                 }
554         }
555
556         foundDup = true;
557
558    while (foundDup){
559                 foundDup = false;
560
561                 j =0;
562
563       while (imagePatches[j]->address==0 && j < imagePatches.size()){
564                         j++;
565                 }
566
567                 VECTOR_ERASE(imagePatches,0,j-1);
568                 j=0;
569
570       for (;j<imagePatches.size()-1;j++){
571          if (imagePatches[j]->stopPage > imagePatches[j+1]->startPage){
572                                 foundDup = true;
573
574             if (imagePatches[j]->stopPage > imagePatches[j+1]->stopPage){
575                imagePatches[j+1]->address = 0;  
576             } else {
577                imagePatches[j]->size = 
578                   (imagePatches[j+1]->address + imagePatches[j+1]->size) -
579                                                 imagePatches[j]->address;
580                                         imagePatches[j+1]->address = 0; 
581                                         imagePatches[j]->stopPage = imagePatches[j]->address + imagePatches[j]->size-
582                                                 (imagePatches[j]->address + imagePatches[j]->size )%pageSize;           
583                                 }
584                         }  
585                 }
586       
587                 VECTOR_SORT(imagePatches, imageUpdateSort);
588         }
589
590         unsigned int k=0;
591
592    while (imagePatches[k]->address==0 && k < imagePatches.size()){
593                 k++;
594         }
595
596         startPage = imagePatches[k]->startPage;
597         stopPage = imagePatches[imagePatches.size()-1]->stopPage;
598         int startIndex=k, stopIndex=imagePatches.size()-1;
599
600         /*if(DEBUG_MSG){
601                 bperr("COMPACTING....\n");      
602                 bperr("COMPACTING %x %x %x\n", imagePatches[0]->startPage, stopPage, imagePatches[0]->address);
603         }
604         patch = new imageUpdate;
605         patch->address = imagePatches[startIndex]->address;
606         patch->size = imagePatches[stopIndex]->address - imagePatches[startIndex]->address +
607                                    imagePatches[stopIndex]->size;
608         newPatches.push_back(patch);
609         if(DEBUG_MSG){
610                 bperr(" COMPACTED: %x --> %x \n", patch->address, patch->size);
611         }*/
612
613         bool finished = false;
614
615         if(_DEBUG_MSG){
616                 bperr("COMPACTING....\n");      
617                 bperr("COMPACTING %x %x %x\n", imagePatches[0]->startPage, stopPage, imagePatches[0]->address);
618         }
619
620    for (;k<imagePatches.size();k++){
621       if (imagePatches[k]->address!=0){
622          if (_DEBUG_MSG){
623                                 bperr("COMPACTING k[start] %x k[stop] %x stop %x addr %x size %x\n", imagePatches[k]->startPage, 
624                                         imagePatches[k]->stopPage,stopPage, imagePatches[k]->address, imagePatches[k]->size);
625                         }
626          if (imagePatches[k]->startPage <= (unsigned int)stopPage){
627                                 stopIndex = k;
628                                 stopPage = imagePatches[k]->stopPage;
629          } else {
630
631                                 patch = new imageUpdate;
632                                 patch->address = imagePatches[startIndex]->address;
633                                 patch->size = imagePatches[stopIndex]->address - imagePatches[startIndex]->address + 
634                                                 imagePatches[stopIndex]->size;
635                                 newPatches.push_back(patch);
636
637             if (_DEBUG_MSG){
638                                         bperr(" COMPACTED: address %x --> %x    start %x  stop %x\n", 
639                                                 patch->address, patch->size, startPage,  stopPage);
640                                 }
641                                 finished = true;
642
643                                 //was k+1       
644             if (k < imagePatches.size()){
645                while (imagePatches[k]->address==0 && k < imagePatches.size()){
646                                                 k++;
647                                         }
648
649                                         startIndex = k;
650                                         stopIndex = k;
651                                         startPage = imagePatches[k]->startPage;
652                                         stopPage  = imagePatches[k]->stopPage;
653                                         finished = false;
654
655                if (k == imagePatches.size()){
656                                                 finished = true;
657                                         }
658                                 } 
659                         }
660                 }
661
662         }
663
664    if (!finished) {
665                 patch = new imageUpdate;
666                 patch->address = imagePatches[startIndex]->address;
667                 patch->size = imagePatches[stopIndex]->address - imagePatches[startIndex]->address +
668                                    imagePatches[stopIndex]->size;
669                 newPatches.push_back(patch);
670
671       if (_DEBUG_MSG){
672                         bperr(" COMPACTED: %x --> %x \n", patch->address, patch->size);
673                         fflush(stdout);
674                 }
675         }       
676
677         
678 }
679
680 void compactSections(pdvector <imageUpdate*> imagePatches, pdvector<imageUpdate*> &newPatches){
681
682         unsigned startPage, stopPage;
683         imageUpdate *patch;
684
685         int pageSize = getpagesize();
686
687         imageUpdate *curr, *next;
688         bool foundDup=true;
689         unsigned int j;
690
691         VECTOR_SORT(imagePatches, imageUpdateSort);
692
693    while (foundDup){
694                 foundDup = false;
695                 j =0;
696       while (imagePatches[j]->address==0 && j < imagePatches.size()){
697                         j++;
698                 }
699                 curr = imagePatches[j];
700
701       for (j++;j<imagePatches.size();j++){
702                         next = imagePatches[j];         
703          if (curr->address == next->address){
704                                 //duplicate
705                                 //find which is bigger and save that one.
706             if (curr->size > next->size){
707                                         next->address=0;
708                                 }else{
709                                         curr->address=0;
710                                         curr=next;
711                                 }
712                                 foundDup =true;
713                         }else{
714                                 curr=next;
715                         }
716
717                 }
718
719                 VECTOR_SORT(imagePatches, imageUpdateSort);
720         }
721
722    if (DEBUG_MSG){
723                 bperr(" SORT 1 %d \n", imagePatches.size());
724         
725                 for(unsigned int kk=0;kk<imagePatches.size();kk++){
726                         bperr("%d address 0x%x  size 0x%x \n",kk, imagePatches[kk]->address, imagePatches[kk]->size);
727                 }
728                 fflush(stdout);
729         }
730
731         unsigned int endAddr;
732    for (unsigned int i=0;i<imagePatches.size();i++){
733       if (imagePatches[i]->address!=0){
734                         imagePatches[i]->startPage = imagePatches[i]->address- (imagePatches[i]->address%pageSize);
735                                 
736                         endAddr = imagePatches[i]->address + imagePatches[i]->size;
737                         imagePatches[i]->stopPage =  endAddr - (endAddr % pageSize);
738
739          if (DEBUG_MSG){
740                                 bperr("%d address %x end addr %x : start page %x stop page %x \n",
741                                         i,imagePatches[i]->address ,imagePatches[i]->address + imagePatches[i]->size,
742                                         imagePatches[i]->startPage, imagePatches[i]->stopPage);
743                         }
744                 }
745         
746         }
747         foundDup = true;
748
749    while (foundDup){
750                 foundDup = false;
751                 j =0;
752       while (imagePatches[j]->address==0 && j < imagePatches.size()){
753                         j++;
754                 }
755
756                 //imagePatches.erase(0,j-1); //is it correct to erase here? 
757                 //j = 0;
758       for (;j<imagePatches.size()-1;j++){ 
759          if (imagePatches[j]->address!=0 && imagePatches[j]->stopPage >= imagePatches[j+1]->startPage){
760                                 foundDup = true;
761             if (imagePatches[j]->stopPage > imagePatches[j+1]->stopPage){
762                                         imagePatches[j+1]->address = 0; 
763                                 }else{
764                                         imagePatches[j]->size = (imagePatches[j+1]->address + imagePatches[j+1]->size) -
765                                                 imagePatches[j]->address;
766                                         imagePatches[j+1]->address = 0; 
767                                         endAddr = imagePatches[j]->address + imagePatches[j]->size;
768                                         imagePatches[j]->stopPage =  endAddr - (endAddr % pageSize);
769                                 }
770                         }  
771                 }
772
773                 VECTOR_SORT(imagePatches, imageUpdateSort);
774         }
775
776         unsigned int k=0;
777
778    if (DEBUG_MSG){
779                 bperr(" SORT 3 %d \n", imagePatches.size());
780
781       for (unsigned int kk=0;kk<imagePatches.size();kk++){
782                         bperr("%d address 0x%x  size 0x%x \n",kk, imagePatches[kk]->address, imagePatches[kk]->size);
783                 }
784                 fflush(stdout);
785         }
786    while (imagePatches[k]->address==0 && k < imagePatches.size()){
787                 k++;
788         }
789
790         startPage = imagePatches[k]->startPage;
791         stopPage = imagePatches[k]->stopPage;
792         int startIndex=k, stopIndex=k;
793         bool finished = false;
794    if (DEBUG_MSG){
795                 bperr("COMPACTING....\n");      
796                 bperr("COMPACTING %x %x %x\n", imagePatches[0]->startPage, stopPage, imagePatches[0]->address);
797         }
798
799    for (;k<imagePatches.size();k++){
800       if (imagePatches[k]->address!=0){
801          if (DEBUG_MSG){
802                                 bperr("COMPACTING k[start] %x k[stop] %x stop %x addr %x size %x\n", imagePatches[k]->startPage, 
803                                         imagePatches[k]->stopPage,stopPage, imagePatches[k]->address, imagePatches[k]->size);
804                         }
805          if (imagePatches[k]->startPage <= (unsigned int) stopPage){
806                                 stopIndex = k;
807                                 stopPage = imagePatches[k]->stopPage;
808          } else {
809
810                                 patch = new imageUpdate;
811                                 patch->address = imagePatches[startIndex]->address;
812                                 patch->size = imagePatches[stopIndex]->address - imagePatches[startIndex]->address + 
813                                                 imagePatches[stopIndex]->size;
814                                 newPatches.push_back(patch);
815
816             if (DEBUG_MSG){
817                                         bperr(" COMPACTED: address %x --> %x    start %x  stop %x\n", 
818                                                 patch->address, patch->size, startPage,  stopPage);
819                                 }
820
821                                 finished = true;
822
823                                 //was k+1       
824             if (k < imagePatches.size()){
825                while (imagePatches[k]->address==0 && k < imagePatches.size()){
826                                                 k++;
827                                         }
828                                         startIndex = k;
829                                         stopIndex = k;
830                                         startPage = imagePatches[k]->startPage;
831                                         stopPage  = imagePatches[k]->stopPage;
832                                         finished = false;
833                if (k == imagePatches.size()){
834                                                 finished = true;
835                                         }
836                                 } 
837                         }
838                 }
839
840         }
841
842    if (!finished){
843                 patch = new imageUpdate;
844                 patch->address = imagePatches[startIndex]->address;
845                 patch->size = imagePatches[stopIndex]->address - imagePatches[startIndex]->address +
846                                    imagePatches[stopIndex]->size;
847                 newPatches.push_back(patch);
848
849       if (DEBUG_MSG){
850                         bperr(" COMPACTED: %x --> %x \n", patch->address, patch->size);
851                 }
852         }       
853         
854 }
855
856
857 #if defined (cap_save_the_world)
858 void process::addLib(char* lname)
859 {
860
861         BPatch_process *appThread = BPatch::bpatch->getProcessByPid(getPid());
862         BPatch_image *appImage = appThread->getImage();
863
864    BPatch_Vector<BPatch_point *> *mainFunc;
865
866         bool isTrampRecursive = BPatch::bpatch->isTrampRecursive();
867     BPatch::bpatch->setTrampRecursive( true ); //ccw 31 jan 2003
868     BPatch_Vector<BPatch_function *> bpfv;
869     if (NULL == appImage->findFunction("main", bpfv) || !bpfv.size()) { 
870       bperr("Unable to find function \"main\". Save the world will fail.\n");
871       return;
872    }
873
874    BPatch_function *mainFuncPtr =bpfv[0];
875    mainFunc = mainFuncPtr->findPoint(BPatch_entry);
876     
877    if (!mainFunc || ((*mainFunc).size() == 0)) {
878       bperr( "    Unable to find entry point to \"main.\"\n");
879       exit(1);
880    }
881
882    bpfv.clear();
883    if (NULL == appImage->findFunction("dlopen", bpfv) || !bpfv.size()) {
884       bperr("Unable to find function \"dlopen\". Save the world will fail.\n");
885       return;
886    }
887    BPatch_function *dlopen_func = bpfv[0];
888    
889    BPatch_Vector<BPatch_snippet *> dlopen_args;
890    BPatch_constExpr nameArg(lname);
891    BPatch_constExpr rtldArg(4);
892    
893    dlopen_args.push_back(&nameArg);
894    dlopen_args.push_back(&rtldArg);
895    
896    BPatch_funcCallExpr dlopenExpr(*dlopen_func, dlopen_args);
897    
898         //bperr(" inserting DLOPEN(%s)\n",lname);
899         requestTextMiniTramp = 1;
900    
901    appThread->insertSnippet(dlopenExpr, *mainFunc, BPatch_callBefore,
902                             BPatch_firstSnippet);
903         requestTextMiniTramp = 0;
904    
905         BPatch::bpatch->setTrampRecursive( isTrampRecursive ); //ccw 31 jan 2003
906 }
907 #endif
908
909 #if defined (cap_save_the_world)
910 //save world
911 char* process::dumpPatchedImage(std::string imageFileName){ //ccw 28 oct 2001
912
913         writeBackXCOFF *newXCOFF;
914         //addLibrary *addLibraryXCOFF;
915         //char name[50];        
916         pdvector<imageUpdate*> compactedUpdates;
917         pdvector<imageUpdate*> compactedHighmemUpdates;
918         void *data;//, *paddedData;
919         //Address guardFlagAddr;
920         char *directoryName = 0;
921
922         if(!collectSaveWorldData){
923                 BPatch_reportError(BPatchSerious,122,"dumpPatchedImage: BPatch_thread::enableDumpPatchedImage() not called.  No mutated binary saved\n");
924                 return NULL;
925         }
926
927         directoryName = saveWorldFindDirectory();
928         if(!directoryName){
929             fprintf(stderr, "ERROR: could not find saveWorld directory\n");
930                 return NULL;
931         }
932         strcat(directoryName, "/");
933
934
935         //at this point build an ast to call dlopen("libdyninstAPI_RT.so.1",);
936         //and insert it at the entry point of main.
937
938         addLib("libdyninstAPI_RT.so.1");
939
940         
941         imageUpdates.sort(imageUpdateSort);// imageUpdate::mysort ); 
942
943         compactLoadableSections(imageUpdates,compactedUpdates);
944
945         highmemUpdates.sort( imageUpdateSort);
946         if(highmemUpdates.size() > 0){
947                 compactSections(highmemUpdates, compactedHighmemUpdates);
948         }
949
950         imageFileName = "dyninst_mutatedBinary";
951         char* fullName =
952       new char[strlen(directoryName) + strlen(imageFileName.c_str())+1];
953    strcpy(fullName, directoryName);
954    strcat(fullName, imageFileName.c_str());
955
956         bool openFileError;
957
958         newXCOFF = new writeBackXCOFF((const char *)(getAOut()->fullName().c_str()), fullName /*"/tmp/dyninstMutatee"*/ , openFileError);
959
960         if( openFileError ){
961             fprintf(stderr, "ERROR: Unable to open file\n");
962                 delete [] fullName;
963                 return NULL;
964         }
965         newXCOFF->registerProcess(this);
966         //int sectionsAdded = 0;
967         //unsigned int newSize, nextPage, paddedDiff;
968         //unsigned int pageSize = getpagesize();
969
970
971         //This adds the LOADABLE HEAP TRAMP sections
972         //AIX/XCOFF NOTES:
973         //On AIX we allocate the heap tramps in two locations: on the heap
974         //(0x20000000) and around the text section (0x10000000) The os loader will
975         //ONLY load ONE text section, ONE data section and ONE bss section. We
976         //cannot (from within the mutated binary) muck with addresses in the range
977         //0x10000000 - 0x1fffffff so to reload these tramps we MUST expand the
978         //text section and tack these on the end.  THIS WILL INCREASE THE FILE
979         //SIZE BY A HUGE AMOUNT.  The file size will increase by (sizeof(text
980         //section) + sizeof(tramps) + (gap between text section and tramps)) the
981         //gap may be quite large
982
983         //SO we do NOT do what we do on the other platforms, ie work around the
984         //heap with the compactedUpdates. we just expand the text section and 
985         //tack 'em on the end.
986
987         assert(compactedUpdates.size() < 2);
988 #if defined(__XLC__) || defined(__xlC__)
989       // XLC does not like typecasts on the left hand side of "="
990         char *data_c = new char[compactedUpdates[0]->size];
991         data = (void *) data_c;
992 #else
993         (char*) data = new char[compactedUpdates[0]->size];
994 #endif
995
996         readDataSpace((void *) compactedUpdates[0]->address,
997                  compactedUpdates[0]->size, data, true);        
998
999         newXCOFF->attachToText(compactedUpdates[0]->address,
1000                           compactedUpdates[0]->size, (char*)data);
1001
1002         if(compactedHighmemUpdates.size() > 0){
1003                 saveWorldCreateHighMemSections(compactedHighmemUpdates, highmemUpdates,
1004                                      (void*) newXCOFF);
1005         }
1006         saveWorldAddSharedLibs((void*) newXCOFF);
1007
1008    saveWorldCreateDataSections((void*)newXCOFF);
1009
1010         newXCOFF->createXCOFF();
1011         newXCOFF->outputXCOFF();
1012    /*
1013         char* fullName = new char[strlen(directoryName) + strlen ( (char*)imageFileName.c_str())+1];
1014    strcpy(fullName, directoryName);
1015    strcat(fullName, (char*)imageFileName.c_str());
1016    
1017    addLibraryXCOFF= new addLibrary(fullName, "/tmp/dyninstMutatee",
1018                                    "libdyninstAPI_RT.so.1");
1019
1020         addLibraryXCOFF->outputXCOFF();
1021     */
1022    delete [] fullName;
1023
1024         delete newXCOFF;
1025
1026         return directoryName;
1027 }
1028 #endif
1029 bool process::handleTrapAtLibcStartMain(dyn_lwp *)  { assert(0); return false; }
1030 bool process::instrumentLibcStartMain() { assert(0); return false; }
1031 bool process::decodeStartupSysCalls(EventRecord &) { assert(0); return false; }
1032 void process::setTraceSysCalls(bool) { assert(0); }
1033 void process::setTraceState(traceState_t) { assert(0); }
1034 bool process::getSysCallParameters(dyn_saved_regs *, long *, int) { assert(0); return false; }
1035 int process::getSysCallNumber(dyn_saved_regs *) { assert(0); return 0; }
1036 long process::getSysCallReturnValue(dyn_saved_regs *) { assert(0); return 0; }
1037 Address process::getSysCallProgramCounter(dyn_saved_regs *) { assert(0); return 0; }
1038 bool process::isMmapSysCall(int) { assert(0); return false; }
1039 Offset process::getMmapLength(int, dyn_saved_regs *) { assert(0); return 0;}
1040 Address process::getLibcStartMainParam(dyn_lwp *) { assert(0); return 0;}
1041
1042 #if 0
1043 // should use demangle.h here, but header is badly broken on AIX 5.1
1044 typedef void *Name;
1045 typedef enum { VirtualName, MemberVar, Function, MemberFunction, Class,
1046                Special, Long } NameKind;
1047 typedef enum { RegularNames = 0x1, ClassNames = 0x2, SpecialNames = 0x4,
1048                ParameterText = 0x8, QualifierText = 0x10 } DemanglingOptions;
1049
1050 Name *(*P_native_demangle)(char *, char **, unsigned long) = NULL;
1051 char *(*P_functionName)(Name *) = NULL;
1052 char *(*P_varName)(Name *) = NULL;
1053 char *(*P_text)(Name *) = NULL;
1054 NameKind (*P_kind)(Name *) = NULL;
1055
1056 void loadNativeDemangler() 
1057 {
1058    P_native_demangle = NULL;
1059    
1060    void *hDemangler = dlopen("libdemangle.so.1", RTLD_LAZY|RTLD_MEMBER);
1061    if (hDemangler != NULL) {
1062       P_native_demangle = (Name*(*)(char*, char**, long unsigned int)) dlsym(hDemangler, "demangle");
1063       if (!P_native_demangle) 
1064          BPatch_reportError(BPatchSerious,122,
1065                    "unable to locate function demangle in libdemangle.so.1\n");
1066
1067       P_functionName = (char*(*)(Name*)) dlsym(hDemangler, "functionName");
1068       if (!P_functionName) 
1069          BPatch_reportError(BPatchSerious,122,
1070                "unable to locate function functionName in libdemangle.so.1\n");
1071       
1072       P_varName = (char*(*)(Name*)) dlsym(hDemangler, "varName");
1073       if (!P_varName) 
1074          BPatch_reportError(BPatchSerious,122,
1075                     "unable to locate function varName in libdemangle.so.1\n");
1076
1077       P_kind = (NameKind(*)(Name*)) dlsym(hDemangler, "kind");
1078       if (!P_kind) 
1079          BPatch_reportError(BPatchSerious,122,
1080                             "unable to locate function kind in libdemangle.so.1\n");
1081       
1082       P_text = (char*(*)(Name*)) dlsym(hDemangler, "text");
1083       if (!P_text) 
1084          BPatch_reportError(BPatchSerious,122,
1085                        "unable to locate function text in libdemangle.so.1\n");
1086    } 
1087 }
1088
1089
1090 extern "C" char *cplus_demangle(char *, int);
1091 extern void dedemangle( const char * demangled, char * dedemangled );
1092
1093 #define DMGL_PARAMS      (1 << 0)       /* Include function args */
1094 #define DMGL_ANSI        (1 << 1)       /* Include const, volatile, etc */
1095
1096 char * P_cplus_demangle( const char * symbol, bool nativeCompiler, bool includeTypes ) {
1097         /* If the symbol isn't from the native compiler, or the native demangler
1098            isn't available, use the built-in. */
1099         bool nativeDemanglerAvailable = P_native_demangle != NULL &&
1100                                                                         P_text != NULL &&
1101                                                                         P_varName != NULL &&
1102                                                                         P_functionName != NULL;
1103         if( !nativeCompiler || ! nativeDemanglerAvailable ) {
1104                 char * demangled = cplus_demangle( const_cast<char *>(symbol),
1105                                         includeTypes ? DMGL_PARAMS | DMGL_ANSI : 0 );
1106                 if( demangled == NULL ) { return NULL; }
1107
1108                 if( ! includeTypes ) {
1109                         /* De-demangling never makes a string longer. */
1110                         char * dedemangled = strdup( demangled );
1111                         assert( dedemangled != NULL );
1112
1113                         dedemangle( demangled, dedemangled );
1114                         assert( dedemangled != NULL );
1115
1116                         free( demangled );
1117                         return dedemangled;
1118                         }
1119
1120                 return demangled;
1121    } /* end if not using native demangler. */
1122    else if( nativeDemanglerAvailable ) {
1123                 /* Use the native demangler, which apparently behaves funny. */
1124                 Name * name;
1125                 char * rest;
1126                 
1127                 /* P_native_demangle() won't actually demangled 'symbol'.
1128                    Find out what P_kind() of symbol it is and demangle from there. */
1129                 name = (P_native_demangle)( const_cast<char*>(symbol), (char **) & rest,
1130                         RegularNames | ClassNames | SpecialNames | ParameterText | QualifierText );
1131                 if( name == NULL ) { return NULL; }
1132
1133                 char * demangled = NULL;
1134                 switch( P_kind( name ) ) {
1135                         case Function:
1136                            if (includeTypes)
1137                                 demangled = (P_text)( name );
1138                            else
1139                                 demangled = (P_functionName)( name );                   
1140                                 break;
1141                         
1142                         case MemberFunction:
1143                                 /* Doing it this way preserves the leading classnames. */
1144                                 demangled = (P_text)( name );
1145                                 break;
1146
1147                         case MemberVar:
1148                                 demangled = (P_varName)( name );
1149                                 break;
1150
1151                         case VirtualName:
1152                         case Class:
1153                         case Special:
1154                         case Long:
1155                                 demangled = (P_text)( name );
1156                                 break;
1157                         default: assert( 0 );
1158                         } /* end P_kind() switch */
1159
1160                 /* Potential memory leak: no P_erase( name ) call.  Also, the
1161                    char *'s returned from a particular Name will be freed
1162                    when that name is erase()d or destroyed,     so strdup if we're
1163                    fond of them. */
1164    
1165                 if( ! includeTypes ) {
1166                         /* De-demangling never makes a string longer. */
1167                         char * dedemangled = strdup( demangled );
1168                         assert( dedemangled != NULL );
1169
1170                         dedemangle( demangled, dedemangled );
1171                         assert( dedemangled != NULL );
1172
1173                         return dedemangled;
1174                         }
1175
1176                 return demangled;
1177                 } /* end if using native demangler. */
1178         else {
1179                 /* We're trying to demangle a native binary but the native demangler isn't available.  Punt. */ 
1180                 return NULL;
1181                 }
1182         } /* end P_cplus_demangle() */
1183 #endif
1184
1185
1186 #include <dlfcn.h> // dlopen constants
1187
1188 #define DLOPEN_MODE (RTLD_NOW | RTLD_GLOBAL)
1189
1190 /*************************************************************************/
1191 /***  Code to handle dlopen()ing the runtime library                   ***/
1192 /***                                                                   ***/
1193 /***  get_dlopen_addr() -- return the address of the dlopen function   ***/
1194 /***  Address dyninstlib_brk_addr -- address of the breakpoint at the  ***/
1195 /***                                 end of the RT init function       ***/
1196 /***  Address main_brk_addr -- address when we switch to dlopen()ing   ***/
1197 /***                           the RT lib                              ***/
1198 /***  loadDYNINSTlib() -- Write the (string) name of the RT lib,     ***/
1199 /***                        set up and execute a call to dlopen()      ***/
1200 /***  trapDueToDyninstLib() -- returns true if trap addr is at         ***/
1201 /***                          dyninstlib_brk_addr                      ***/
1202 /***  trapAtEntryPointOfMain() -- see above                            ***/
1203 /***  handleIfDueToDyninstLib -- cleanup function                      ***/
1204 /***  handleTrapAtEntryPointOfMain -- cleanup function                 ***/
1205 /***  insertTrapAtEntryPointOfMain -- insert a breakpoint at the start ***/
1206 /***                                  of main                          ***/
1207 /*************************************************************************/
1208
1209
1210 /* Auxiliary function */
1211
1212 bool checkAllThreadsForBreakpoint(process *proc, Address break_addr)
1213 {
1214     startup_printf("[%d] Checking all process threads for breakpoint 0x%x\n",
1215                    proc->getPid(), break_addr);
1216   pdvector<Frame> activeFrames;
1217   if (!proc->getAllActiveFrames(activeFrames)) return false;
1218   for (unsigned frame_iter = 0; frame_iter < activeFrames.size(); frame_iter++) {
1219       if (activeFrames[frame_iter].getPC() == break_addr) {
1220           return true;
1221       }
1222   }
1223   return false;
1224 }
1225
1226 bool process::trapDueToDyninstLib(dyn_lwp *lwp)
1227 {
1228   // Since this call requires a PTRACE, optimize it slightly
1229   if (dyninstlib_brk_addr == 0x0) return false;
1230
1231   Frame active = lwp->getActiveFrame();
1232   
1233   if (active.getPC() == dyninstlib_brk_addr)
1234       return true;
1235
1236   return false;
1237 }
1238
1239 bool process::trapAtEntryPointOfMain(dyn_lwp *lwp, Address)
1240 {
1241   if (main_brk_addr == 0x0) return false;
1242
1243   Frame active = lwp->getActiveFrame();
1244   if (active.getPC() == main_brk_addr)
1245       return true;
1246   return false;
1247 }
1248
1249 /*
1250  * Restore "the original instruction" written into main so that
1251  * we can proceed after the trap. Saved in "savedCodeBuffer",
1252  * which is a chunk of space we use for dlopening the RT library.
1253  */
1254
1255 bool process::handleTrapAtEntryPointOfMain(dyn_lwp *)
1256 {
1257     
1258     if (!main_brk_addr) return false;
1259     // Put back the original insn
1260     if (!writeDataSpace((void *)main_brk_addr, 
1261                         instruction::size(), (char *)savedCodeBuffer)) {
1262         fprintf(stderr, "%s[%d]:  writeDataSpace failed\n", FILE__, __LINE__);
1263         return false;
1264     }
1265     
1266     // And zero out the main_brk_addr so we don't accidentally
1267     // trigger on it.
1268     main_brk_addr = 0x0;
1269     return true;
1270 }
1271
1272 /*
1273  * Stick a trap at the entry point of main. At this point,
1274  * libraries are mapped into the proc's address space, and
1275  * we can dlopen the RT library.
1276  */
1277
1278 bool process::insertTrapAtEntryPointOfMain()
1279 {
1280     int_function *f_main = NULL;
1281     pdvector<int_function *> funcs;
1282     bool res = findFuncsByPretty("main", funcs);
1283     if (!res) {
1284         // we can't instrument main - naim
1285         showErrorCallback(108,"main() uninstrumentable");
1286         return false;
1287     }
1288
1289     if( funcs.size() > 1 ) {
1290         cerr << __FILE__ << __LINE__ 
1291              << ": found more than one main! using the first" << endl;
1292     }
1293     f_main = funcs[0];
1294     assert(f_main);
1295
1296     Address addr = f_main->getAddress();
1297     
1298     startup_printf("[%d]: inserting trap at 0x%x\n",
1299                    getPid(), addr);
1300
1301     // save original instruction first
1302     readDataSpace((void *)addr, instruction::size(), savedCodeBuffer, true);
1303     // and now, insert trap
1304     codeGen gen(instruction::size());
1305     instruction::generateTrap(gen);
1306
1307     if (!writeDataSpace((void *)addr, gen.used(), gen.start_ptr()))
1308         fprintf(stderr, "%s[%d]:  writeDataSpace failed\n", FILE__, __LINE__);
1309     main_brk_addr = addr;
1310     
1311     return true;
1312 }
1313
1314 bool AddressSpace::getDyninstRTLibName() 
1315 {
1316     if (dyninstRT_name.length() == 0) {
1317         // Get env variable
1318         if (getenv("DYNINSTAPI_RT_LIB") != NULL) {
1319             dyninstRT_name = getenv("DYNINSTAPI_RT_LIB");
1320         }
1321         else {
1322            std::string msg = std::string("Environment variable ")
1323               + std::string("DYNINSTAPI_RT_LIB")
1324               + std::string(" has not been defined");
1325            showErrorCallback(101, msg);
1326            return false;
1327         }
1328     }
1329
1330     // Automatically choose 32-bit library if necessary.
1331     const char *modifier = "_32";
1332     const char *name = dyninstRT_name.c_str();
1333
1334     if (getAddressWidth() != sizeof(void *) && !P_strstr(name, modifier)) {
1335         const char *split = P_strrchr(name, '/');
1336
1337         if (!split) split = name;
1338         split = P_strchr(split, '.');
1339         if (!split) {
1340             // We should probably print some error here.
1341             // Then, of course, the user will find out soon enough.
1342             return false;
1343         }
1344
1345         dyninstRT_name = std::string(name, split - name) +
1346                          std::string(modifier) +
1347                          std::string(split);
1348     }
1349
1350     // Check to see if the library given exists.
1351     if (access(dyninstRT_name.c_str(), R_OK)) {
1352         std::string msg = std::string("Runtime library ") + dyninstRT_name
1353         + std::string(" does not exist or cannot be accessed!");
1354         showErrorCallback(101, msg);
1355         return false;
1356     }
1357     return true;
1358 }
1359
1360
1361   
1362
1363 /*
1364  * loadDYNINSTlib()
1365  *
1366  * The evil black magic function. What we want: for the runtime
1367  * library to show up in the process' address space. Magically.
1368  * No such luck. What we do: patch in a call to dlopen(DYNINSTRT_NAME)
1369  * at the entry of main, then restore the original instruction
1370  * and continue.
1371  */
1372
1373 bool process::loadDYNINSTlib()
1374 {
1375     // We use the address of main() to load the library, saving what's
1376     // there and restoring later
1377     
1378     // However, if we can get code_len_ + code_off_ from the object file,
1379     // then we can use the area above that point freely.
1380     
1381     // Steps: Get the library name (command line or ENV)
1382     //        Get the address for dlopen()
1383     //        Write in a call to dlopen()
1384     //        Write in a trap after the call
1385     //        Write the library name somewhere where dlopen can find it.
1386     // Actually, why not write the library name first?
1387
1388     int_function *scratch = findOnlyOneFunction("main");
1389     if (!scratch) return false;
1390
1391
1392     // Testing...
1393     // Round it up to the nearest instruction. 
1394     Address codeBase = scratch->getAddress();
1395
1396     startup_printf("[%d]: using address of 0x%lx for call to dlopen\n",
1397                    getPid(), codeBase);
1398
1399     codeGen scratchCodeBuffer(BYTES_TO_SAVE);
1400     scratchCodeBuffer.setAddrSpace(this);
1401     scratchCodeBuffer.setAddr(codeBase);
1402     scratchCodeBuffer.setFunction(scratch);
1403
1404     Address dyninstlib_addr = 0;
1405     Address dlopencall_addr = 0;
1406     
1407     // Do we want to save whatever is there? Can't see a reason why...
1408     
1409     // write library name...
1410     dyninstlib_addr = codeBase;
1411
1412     scratchCodeBuffer.copy(dyninstRT_name.c_str(), dyninstRT_name.length()+1);
1413     
1414     // Need a register space
1415     // make sure this syncs with inst-power.C
1416     
1417     registerSpace *dlopenRegSpace = registerSpace::savedRegSpace(this);
1418
1419     scratchCodeBuffer.setRegisterSpace(dlopenRegSpace);
1420
1421     int_function *dlopen_func = findOnlyOneFunction("dlopen");
1422     if (!dlopen_func) {
1423         fprintf(stderr, "%s[%d]: ERROR: unable to find dlopen!\n",
1424                 __FILE__, __LINE__);
1425         return false;
1426     }
1427     
1428     pdvector<AstNodePtr> dlopenAstArgs(2);
1429     AstNodePtr dlopenAst;
1430     
1431     dlopenAstArgs[0] = AstNode::operandNode(AstNode::Constant, (void *)(dyninstlib_addr));
1432     dlopenAstArgs[1] = AstNode::operandNode(AstNode::Constant, (void*)DLOPEN_MODE);
1433
1434     dlopenAst = AstNode::funcCallNode(dlopen_func, dlopenAstArgs);
1435
1436
1437     dlopencall_addr = codeBase + scratchCodeBuffer.used();
1438
1439     startup_printf("[%d]: call to dlopen starts at 0x%lx\n", getPid(), dlopencall_addr);
1440
1441     // We need to push down the stack before we call this
1442     pushStack(scratchCodeBuffer);
1443
1444     dlopenAst->generateCode(scratchCodeBuffer,
1445                             true);
1446
1447     popStack(scratchCodeBuffer);
1448
1449     dyninstlib_brk_addr = codeBase + scratchCodeBuffer.used();
1450     instruction::generateTrap(scratchCodeBuffer);
1451
1452     startup_printf("[%d]: call to dlopen breaks at 0x%lx\n", getPid(),
1453                    dyninstlib_brk_addr);
1454
1455     readDataSpace((void *)codeBase, sizeof(savedCodeBuffer), savedCodeBuffer, true);
1456     
1457     if (!writeDataSpace((void *)codeBase, scratchCodeBuffer.used(), 
1458                    scratchCodeBuffer.start_ptr()))
1459         fprintf(stderr, "%s[%d]:  writeDataSpace failed\n", FILE__, __LINE__);
1460     
1461     // save registers
1462     assert(savedRegs == NULL);
1463     savedRegs = new dyn_saved_regs;
1464    assert(savedRegs != NULL);
1465     bool status = getRepresentativeLWP()->getRegisters(savedRegs);
1466     assert((status!=false) && (savedRegs!=(void *)-1));
1467
1468     assert(dlopencall_addr);
1469     assert(dyninstlib_brk_addr);
1470
1471     if (!getRepresentativeLWP()->changePC(dlopencall_addr, NULL)) {
1472         logLine("WARNING: changePC failed in loadDYNINSTlib\n");
1473         assert(0);
1474     }
1475     
1476     setBootstrapState(loadingRT_bs);
1477
1478     return true;
1479 }
1480
1481 /*
1482  * Cleanup after dlopen()ing the runtime library. Since we don't overwrite
1483  * any existing functions, just restore saved registers. Cool, eh?
1484  */
1485
1486 bool process::loadDYNINSTlibCleanup(dyn_lwp *lwp)
1487 {
1488     lwp->restoreRegisters(*savedRegs);
1489     delete savedRegs;
1490     savedRegs = NULL;
1491     // We was never here.... 
1492
1493     int_function *scratch = findOnlyOneFunction("main");
1494     if (!scratch) return false;
1495     // Testing...
1496     // Round it up to the nearest instruction. 
1497     Address codeBase = scratch->getAddress();
1498     
1499     if (!writeDataSpace((void *)codeBase, sizeof(savedCodeBuffer), savedCodeBuffer))
1500         fprintf(stderr, "%s[%d]:  writeDataSpace failed\n", FILE__, __LINE__);
1501
1502     // But before we go, reset the dyninstlib_brk_addr so we don't
1503     // accidentally trigger it, eh?
1504     dyninstlib_brk_addr = 0x0;
1505     return true;
1506 }
1507
1508
1509 //////////////////////////////////////////////////////////
1510 // AIX /proc compatibility section
1511 /////////////////////////////////////////////////////////
1512
1513 #define GETREG_GPR(regs,reg)   (regs.__gpr[reg])
1514 // AIX system calls can vary in name and number. We need a way
1515 // to decode this mess. So what we do is #define the syscalls we 
1516 // want to numbers and use those to index into a mapping array.
1517 // The first time we try and map a syscall we fill the array in.
1518
1519 int SYSSET_MAP(int syscall, int pid)
1520 {
1521     static int syscall_mapping[NUM_SYSCALLS];
1522     static bool mapping_valid = false;
1523     
1524     if (mapping_valid)
1525         return syscall_mapping[syscall];
1526     
1527     for (int i = 0; i < NUM_SYSCALLS; i++)
1528         syscall_mapping[i] = -1;
1529     
1530     // Open and read the sysent file to find exit, fork, and exec.
1531     prsysent_t sysent;
1532     prsyscall_t *syscalls;
1533     int fd;
1534     char filename[256];
1535     char syscallname[256];
1536     sprintf(filename, "/proc/%d/sysent", pid);
1537     fd = open(filename, O_RDONLY, 0);
1538     if (read(fd, &sysent,
1539              sizeof(sysent) - sizeof(prsyscall_t))
1540         != sizeof(sysent) - sizeof(prsyscall_t))
1541         perror("AIX syscall_map: read");
1542     syscalls = (prsyscall_t *)malloc(sizeof(prsyscall_t)*sysent.pr_nsyscalls);
1543     if (read(fd, syscalls, sizeof(prsyscall_t)*sysent.pr_nsyscalls) !=
1544         (int) (sizeof(prsyscall_t) * sysent.pr_nsyscalls))
1545         perror("AIX syscall_map: read2");
1546     for (unsigned int j = 0; j < (unsigned) sysent.pr_nsyscalls; j++) {
1547         lseek(fd, syscalls[j].pr_nameoff, SEEK_SET);
1548         read(fd, syscallname, 256);
1549         // Now comes the interesting part. We're interested in a list of
1550         // system calls. Compare the freshly read name to the list, and if
1551         // there is a match then set the syscall mapping.
1552         if (!strcmp(syscallname, "_exit")) {
1553             syscall_mapping[SYS_exit] = syscalls[j].pr_number;
1554         }
1555         else if (!strcmp(syscallname, "kfork")) {
1556             syscall_mapping[SYS_fork] = syscalls[j].pr_number;
1557         }
1558         else if (!strcmp(syscallname, "execve")) {    
1559             syscall_mapping[SYS_exec] = syscalls[j].pr_number;
1560         }
1561         if (!strcmp(syscallname, "thread_terminate_unlock")) {
1562            syscall_mapping[SYS_lwp_exit] = syscalls[j].pr_number;
1563         }
1564     }
1565     P_close(fd);
1566     free(syscalls);
1567     mapping_valid = true;
1568     return syscall_mapping[syscall];
1569 }
1570
1571 // Bleah...
1572 unsigned SYSSET_SIZE(sysset_t *x)
1573 {
1574     // (pr_size - 1) because sysset_t is one uint64_t too large
1575     return sizeof(sysset_t) + (sizeof (uint64_t) * (x->pr_size-1));
1576 }
1577
1578 sysset_t *SYSSET_ALLOC(int pid)
1579 {
1580     static bool init = false;
1581     static int num_calls = 0;
1582     if (!init) {
1583         prsysent_t sysent;
1584         int fd;
1585         char filename[256];
1586         sprintf(filename, "/proc/%d/sysent", pid);
1587         fd = open(filename, O_RDONLY, 0);
1588         if (read(fd, &sysent,
1589                  sizeof(sysent) - sizeof(prsyscall_t))
1590             != (int) (sizeof(sysent) - sizeof(prsyscall_t)))
1591             perror("AIX syscall_alloc: read");
1592         num_calls = sysent.pr_nsyscalls;
1593         init = true;
1594         P_close(fd);
1595     }
1596     int size = 0; // Number of 64-bit ints we use for the bitmap
1597     // array size (*8 because we're bitmapping)
1598     size = ((num_calls / (8*sizeof(uint64_t))) + 1);
1599     sysset_t *ret = (sysset_t *)malloc(sizeof(sysset_t) 
1600                                        - sizeof(uint64_t) 
1601                                        + size*sizeof(uint64_t));
1602
1603     ret->pr_size = size;
1604     
1605     return ret;
1606 }
1607
1608 /*
1609  * The set operations (set_entry_syscalls and set_exit_syscalls) are defined
1610  * in sol_proc.C
1611  */
1612
1613 bool process::get_entry_syscalls(sysset_t *entry)
1614 {
1615     pstatus_t status;
1616     if (!get_status(&status)) return false;
1617     
1618     // If the offset is 0, no syscalls are being traced
1619     if (status.pr_sysentry_offset == 0) {
1620         premptysysset(entry);
1621     }
1622     else {
1623         // The entry member of the status vrble is a pointer
1624         // to the sysset_t array.
1625         if(pread(getRepresentativeLWP()->status_fd(), entry, 
1626                  SYSSET_SIZE(entry), status.pr_sysentry_offset)
1627            != (int) SYSSET_SIZE(entry)) {
1628            fprintf(stderr, "%s[%d]:  pread: %s\n", FILE__, __LINE__, strerror(errno));
1629             perror("get_entry_syscalls: read");
1630             return false;
1631         }
1632     }
1633     return true;
1634 }
1635
1636 bool process::get_exit_syscalls(sysset_t *exit)
1637 {
1638     pstatus_t status;
1639     if (!get_status(&status)) return false;
1640
1641     // If the offset is 0, no syscalls are being traced
1642     if(status.pr_sysexit_offset == 0) {
1643         premptysysset(exit);
1644     }
1645     else {
1646         if(pread(getRepresentativeLWP()->status_fd(), exit, 
1647                  SYSSET_SIZE(exit), status.pr_sysexit_offset)
1648            != (int) SYSSET_SIZE(exit)) {
1649            fprintf(stderr, "%s[%d]:  pread: %s\n", FILE__, __LINE__, strerror(errno));
1650             perror("get_exit_syscalls: read");
1651             return false;
1652         }
1653     }
1654     return true;
1655 }
1656
1657
1658
1659 bool process::dumpCore_(const std::string coreFile)
1660 {
1661     pause();
1662     
1663     if (!dumpImage(coreFile))
1664         return false;
1665     
1666     continueProc();
1667     return true;
1668 }
1669
1670 bool process::dumpImage(const std::string outFile)
1671 {
1672     // formerly OS::osDumpImage()
1673     const string &imageFileName = getAOut()->fullName();
1674
1675         
1676     // const Address codeOff = symbols->codeOffset();
1677     int i;
1678     int rd;
1679     int ifd;
1680     int ofd;
1681     int cnt;
1682     int total;
1683     int length;
1684
1685     char buffer[4096];
1686     struct filehdr hdr;
1687     struct stat statBuf;
1688     struct aouthdr aout;
1689     struct scnhdr *sectHdr;
1690     bool needsCont = false;
1691
1692     ifd = open(imageFileName.c_str(), O_RDONLY, 0);
1693     if (ifd < 0) {
1694       sprintf(errorLine, "Unable to open %s\n", imageFileName.c_str());
1695       logLine(errorLine);
1696       showErrorCallback(41, (const char *) errorLine);
1697       perror("open");
1698       return true;
1699     }
1700
1701     rd = fstat(ifd, &statBuf);
1702     if (rd != 0) {
1703       perror("fstat");
1704       sprintf(errorLine, "Unable to stat %s\n", imageFileName.c_str());
1705       logLine(errorLine);
1706       showErrorCallback(72, (const char *) errorLine);
1707       return true;
1708     }
1709     length = statBuf.st_size;
1710     ofd = open(outFile.c_str(), O_WRONLY|O_CREAT, 0777);
1711     if (ofd < 0) {
1712       perror("open");
1713       exit(-1);
1714     }
1715
1716     /* read header and section headers */
1717     cnt = read(ifd, &hdr, sizeof(struct filehdr));
1718     if (cnt != sizeof(struct filehdr)) {
1719         sprintf(errorLine, "Error reading header\n");
1720         logLine(errorLine);
1721         showErrorCallback(44, (const char *) errorLine);
1722         return false;
1723     }
1724
1725     cnt = read(ifd, &aout, sizeof(struct aouthdr));
1726
1727     sectHdr = (struct scnhdr *) calloc(sizeof(struct scnhdr), hdr.f_nscns);
1728     cnt = read(ifd, sectHdr, sizeof(struct scnhdr) * hdr.f_nscns);
1729     if ((unsigned) cnt != sizeof(struct scnhdr)* hdr.f_nscns) {
1730         sprintf(errorLine, "Section headers\n");
1731         logLine(errorLine);
1732         return false;
1733     }
1734
1735     /* now copy the entire file */
1736     lseek(ofd, 0, SEEK_SET);
1737     lseek(ifd, 0, SEEK_SET);
1738     for (i=0; i < length; i += 4096) {
1739         rd = read(ifd, buffer, 4096);
1740         write(ofd, buffer, rd);
1741         total += rd;
1742     }
1743
1744     if (!stopped) {
1745         // make sure it is stopped.
1746         pause();
1747         needsCont = true;
1748     }
1749     
1750     Address baseAddr = getAOut()->codeAbs();
1751
1752     sprintf(errorLine, "seeking to 0x%lx as the offset of the text segment \n",
1753             baseAddr);
1754     logLine(errorLine);
1755     sprintf(errorLine, "Code offset = 0x%lx\n", baseAddr);
1756     logLine(errorLine);
1757     
1758
1759     lseek(ofd, aout.text_start, SEEK_SET);
1760     
1761     /* Copy the text segment over */
1762     for (i = 0; i < aout.tsize; i += 4096) {
1763         length = ((i + 4096) < aout.tsize) ? 4096 : aout.tsize-i;
1764         readDataSpace((void *) (baseAddr+i), length, (void *)buffer, false);
1765
1766         
1767         write(ofd, buffer, length);
1768     }
1769     
1770     if (needsCont) {
1771         continueProc();
1772     }
1773     
1774     P_close(ofd);
1775     P_close(ifd);
1776     
1777     return true;
1778
1779 }
1780
1781 bool SignalGenerator::decodeSignal_NP(EventRecord &ev)
1782 {
1783   if (ev.type == evtSignalled && ev.what == SIGSTOP) {
1784     // On AIX we can't manipulate a process stopped on a
1785     // SIGSTOP... in any case, we clear it.
1786     // No other signal exhibits this behavior.
1787     ev.proc->getRepresentativeLWP()->clearSignal();
1788    }
1789
1790   return false;  // signall needs further deccoding
1791 }
1792
1793 bool SignalGeneratorCommon::getExecFileDescriptor(std::string filename,
1794                                                   int pid,
1795                                                   bool waitForTrap,
1796                                                   int &status,
1797                                                   fileDescriptor &desc) 
1798 {
1799     // AIX's /proc has a map file which contains data about
1800     // files loaded into the address space. The first two appear
1801     // to be the text and data from the process. We'll take it,
1802     // making sure that the filenames match.
1803
1804     // Amusingly, we don't use the filename parameter; we need to match with
1805     // later /proc reads, and little things like pathnames kinda get in the way.
1806       
1807     char tempstr[256];
1808
1809     // Can get rid of this; actually, move to attach.
1810
1811     if (waitForTrap) {
1812         
1813         pstatus_t pstatus;
1814         int trapped = 0;
1815         int timeout = 0;
1816         int stat_fd = 0;
1817         sprintf(tempstr, "/proc/%d/status", pid);
1818         
1819         while (!trapped &&
1820                (timeout < 10000) // 10 seconds, _should_ be enough
1821                ) {
1822             
1823             // On slower machines (sp3-cw.cs.wisc.edu) we can enter
1824             // this code before the forked child has actually been created.
1825             // We attempt to re-open the FD if it failed the first time.
1826             if (stat_fd <= 0) 
1827                 stat_fd = P_open(tempstr, O_RDONLY, 0);
1828             if (stat_fd > 0) {
1829                 if (pread(stat_fd, &pstatus, sizeof(pstatus), 0) != sizeof(pstatus)) {
1830                    fprintf(stderr, "%s[%d]:  pread: %s\n", FILE__, __LINE__, strerror(errno));
1831                     perror("pread failed while waiting for initial trap\n");
1832                 }
1833                 
1834                 if ((pstatus.pr_lwp.pr_why == PR_SYSEXIT))
1835                     trapped = 1;
1836             }
1837             timeout++;
1838             usleep(1000);
1839         }
1840         if (!trapped) {
1841             // Hit the timeout, assume failure
1842             fprintf(stderr, "%s[%d][%s] Failed to open application /proc status FD:%s\n",
1843                     __FILE__, __LINE__, getThreadStr(getExecThreadID()),tempstr);
1844             return false;
1845         }
1846         status = SIGTRAP;
1847         // Explicitly don't close the FD
1848     }
1849     
1850     int map_fd;
1851     sprintf(tempstr, "/proc/%d/map", pid);
1852     map_fd = P_open(tempstr, O_RDONLY, 0);
1853
1854     if (map_fd <= 0) {
1855         fprintf(stderr, "%s[%d]:  failed to open /proc/%d/map\n", __FILE__, __LINE__, pid);
1856         return false;
1857     }
1858
1859     prmap_t text_map;
1860     char prog_name[512];
1861     prog_name[0] = '\0';
1862
1863     prmap_t data_map;
1864     
1865     if (sizeof(prmap_t) != pread(map_fd, &text_map, sizeof(prmap_t), 0))
1866        fprintf(stderr, "%s[%d]:  pread: %s\n", FILE__, __LINE__, strerror(errno));
1867     pread(map_fd, prog_name, 512, text_map.pr_pathoff);
1868     if (prog_name[0] == '\0')
1869        fprintf(stderr, "%s[%d]:  pread: %s\n", FILE__, __LINE__, strerror(errno));
1870     //assert(text_map.pr_mflags & MA_MAINEXEC);
1871     
1872     if (sizeof(prmap_t) != pread(map_fd, &data_map, sizeof(prmap_t), sizeof(prmap_t)))
1873        fprintf(stderr, "%s[%d]:  pread: %s\n", FILE__, __LINE__, strerror(errno));
1874     if (!(data_map.pr_mflags & MA_MAINEXEC))
1875         data_map.pr_vaddr = 0;
1876     
1877     // We assume text = entry 0, data = entry 1
1878     // so they'll have the same names
1879
1880     Address textOrg = (Address) text_map.pr_vaddr;
1881     Address dataOrg = (Address) data_map.pr_vaddr;
1882
1883     // Round up to next multiple of wordsize;
1884     
1885     if (textOrg % sizeof(unsigned))
1886         textOrg += sizeof(unsigned) - (textOrg % sizeof(unsigned));
1887     if (dataOrg % sizeof(unsigned))
1888         dataOrg += sizeof(unsigned) - (dataOrg % sizeof(unsigned));
1889
1890    // Here's a fun one. For the a.out file, we normally have the data in
1891    // segment 2 (0x200...). This is not always the case. Programs compiled
1892    // with the -bmaxdata flag have the heap in segment 3. In this case, change
1893    // the lower bound for the allocation constants in aix.C.
1894    extern Address data_low_addr;
1895    if (dataOrg >= 0x30000000)
1896        data_low_addr = 0x30000000;
1897    else
1898        data_low_addr = 0x20000000;
1899
1900     // Check if text_name substring matches filename?
1901
1902    /* name... We generate relative paths of exe with and without "./" at different places. 
1903       This creates multiple mapped file for the same file due to different paths. 
1904       We will simplify it by stripping the "./" */
1905    char text_name[256];
1906    char name[256];
1907    strcpy(text_name, filename.c_str());
1908    if (text_name[0] == '.')
1909         strcpy(name,text_name+2);
1910    else
1911         strcpy(name, text_name);
1912    desc = fileDescriptor(name,
1913                           textOrg,
1914                           dataOrg,
1915                           false); // Not a shared object
1916     // Try and track the types of descriptors created in aixDL.C...
1917         // We set this to the pathless file name (so that we can distinguish
1918         // exec'ed processes)
1919     desc.setMember(name);
1920     //desc.setPid(pid);
1921     
1922     return true;
1923 }
1924
1925
1926 void process::copyDanglingMemory(process *parent) {
1927     assert(parent);
1928     assert(parent->status() == stopped);
1929     assert(status() == stopped);
1930
1931     // Copy everything in a heap marked "uncopied" over by hand
1932     pdvector<heapItem *> items = heap_.heapActive.values();
1933     for (unsigned i = 0; i < items.size(); i++) {
1934         if (items[i]->type == uncopiedHeap) {
1935             char *buffer = new char[items[i]->length];
1936             parent->readDataSpace((void *)items[i]->addr, items[i]->length,
1937                           buffer, true);
1938             if (! writeDataSpace((void *)items[i]->addr, 
1939                                   items[i]->length,
1940                                   buffer))
1941               fprintf(stderr, "%s[%d]:  writeDataSpace failed\n", FILE__, __LINE__);
1942             delete [] buffer;
1943         }
1944     }
1945     // Odd... some changes _aren't_ copied.
1946
1947     // Get all of the multiTramps and recopy the jumps
1948     // (copied from parent space)
1949
1950     pdvector<codeRange *> mods;
1951     modifiedRanges_.elements(mods);
1952
1953     for (unsigned j = 0; j < mods.size(); j++) {
1954         unsigned char buffer[mods[j]->get_size()];
1955
1956         parent->readDataSpace((void *)mods[j]->get_address(),
1957                               mods[j]->get_size(),
1958                               (void *)buffer, true);
1959         if (!writeDataSpace((void *)mods[j]->get_address(),
1960                        mods[j]->get_size(),
1961                        (void *)buffer))
1962             fprintf(stderr, "%s[%d]:  writeDataSpace failed\n", FILE__, __LINE__);
1963     }
1964 }
1965
1966
1967 // findCallee
1968 int_function *instPoint::findCallee() {
1969     if (callee_) {
1970         return callee_;
1971     }
1972
1973     if (ipType_ != callSite) {
1974         return NULL;
1975     }
1976
1977     if (isDynamic()) { 
1978         return NULL;
1979     }
1980
1981     // Check if we parsed an intra-module static call
1982     assert(img_p_);
1983     image_func *icallee = img_p_->getCallee();
1984     if (icallee) {
1985       // Now we have to look up our specialized version
1986       // Can't do module lookup because of DEFAULT_MODULE...
1987       const pdvector<int_function *> *possibles = func()->obj()->findFuncVectorByMangled(icallee->symTabName().c_str());
1988       if (!possibles) {
1989           return NULL;
1990       }
1991       for (unsigned i = 0; i < possibles->size(); i++) {
1992           if ((*possibles)[i]->ifunc() == icallee) {
1993               callee_ = (*possibles)[i];
1994               return callee_;
1995           }
1996       }
1997       // No match... very odd
1998       assert(0);
1999       return NULL;
2000   }
2001
2002     // Other possibilities: call through a function pointer,
2003     // or a inter-module call. We handle inter-module calls as
2004     // a static function call, since they're bound at load time.
2005
2006     // We figure out the linkage by running a quick instructiter over the target...
2007     // Code is similar to archCheckEntry in image-power.C
2008
2009     // TODO: encapsulate this in the instPoint so we can handle absolute branches
2010     // acceptably.
2011
2012     if (!proc()->isValidAddress(callTarget())) {
2013         return NULL;
2014     }
2015         
2016     InstrucIter targetIter(callTarget(), proc());
2017     if (!targetIter.getInstruction().valid()) {
2018         return NULL;
2019     }
2020     Address toc_offset = 0;
2021
2022     if (targetIter.isInterModuleCallSnippet(toc_offset)) {
2023         Address TOC_addr = (func()->obj()->parse_img()->getObject())->getTOCoffset();
2024         
2025         // We need to read out of memory rather than disk... so this is a call to
2026         // readDataSpace. Yummy.
2027
2028         Address linkageAddr = 0;
2029         Address linkageTarget = 0;
2030         // Basically, load r12, <x>(r2)
2031         if (!proc()->readDataSpace((void *)(TOC_addr + toc_offset),
2032                                    sizeof(Address),
2033                                    (void *)&linkageAddr, false))
2034             return NULL;
2035         // And load r0, 0(r12)
2036         if (!proc()->readDataSpace((void *)linkageAddr,
2037                                    sizeof(Address),
2038                                    (void *)&linkageTarget, false))
2039             return NULL;
2040
2041         if (linkageTarget == 0) {
2042             // No error for this one... looks like unloaded libs
2043             // do it.
2044             return NULL;
2045         }
2046
2047         // Again, by definition, the function is not in owner.
2048         // So look it up.
2049         int_function *pdf = proc()->findFuncByAddr(linkageTarget);
2050
2051         if (pdf) {
2052             callee_ = pdf;
2053             return callee_;
2054         }
2055         else
2056             return NULL;
2057     }
2058     return NULL;
2059 }
2060
2061 /**
2062  * Searches for function in order, with preference given first 
2063  * to libpthread, then to libc, then to the process.
2064  **/
2065 static void findThreadFuncs(process *p, std::string func, 
2066                             pdvector<int_function *> &result)
2067 {
2068    bool found = false;
2069    mapped_module *lpthread = p->findModule("libpthread.a", true);
2070    if (lpthread)
2071       found = lpthread->findFuncVectorByPretty(func, result);
2072    if (found)
2073       return;
2074
2075    mapped_module *lc = p->findModule("libc.a", true);
2076    if (lc)
2077       found = lc->findFuncVectorByPretty(func, result);
2078    if (found)
2079       return;
2080    
2081    p->findFuncsByPretty(func, result);
2082 }
2083
2084 static bool initWrapperFunction(process *p, std::string symbol_name, std::string func_name)
2085 {
2086    //Find symbol_name
2087    bool res;
2088    pdvector<int_variable *> dyn_syms;
2089    res = p->findVarsByAll(symbol_name, dyn_syms);
2090    if (!res)
2091    {
2092       fprintf(stderr, "[%s:%d] - Couldn't find any %s, expected 1\n", 
2093               __FILE__, __LINE__, symbol_name.c_str());
2094       return false;
2095    }
2096    Address sym_addr = dyn_syms[0]->getAddress();
2097
2098    //Find func_name
2099    pdvector<int_function *> funcs;
2100    findThreadFuncs(p, func_name, funcs);   
2101    if (funcs.size() != 1)
2102    {
2103       fprintf(stderr, "[%s:%d] - Found %d %s functions, expected 1\n",
2104               __FILE__, __LINE__, funcs.size(), func_name.c_str());
2105       return false;
2106    }   
2107    //Replace
2108    res = writeFunctionPtr(p, sym_addr, funcs[0]);
2109    if (!res)
2110    {
2111       fprintf(stderr, "[%s:%d] - Couldn't update %s\n",
2112               __FILE__, __LINE__, symbol_name.c_str());
2113       return false;
2114    }
2115    return true;
2116 }
2117
2118 static bool instrumentThrdFunc(int_function *dummy_create, std::string func_name, 
2119                                process *proc) 
2120 {
2121    //Find create_thread
2122    pdvector<int_function *> thread_init_funcs;
2123    findThreadFuncs(proc, func_name.c_str(), thread_init_funcs);
2124    //findThreadFuncs(this, "init_func", &thread_init_funcs);
2125    if (!thread_init_funcs.size()) {
2126       return false;
2127    }
2128    //Instrument
2129    for (unsigned i=0; i<thread_init_funcs.size(); i++)
2130    {
2131       pdvector<AstNodePtr> args;
2132       AstNodePtr call_dummy_create = AstNode::funcCallNode(dummy_create, args);
2133       const pdvector<instPoint *> &ips = thread_init_funcs[i]->funcEntries();
2134       for (unsigned j=0; j<ips.size(); j++)
2135       {
2136          miniTramp *mt;
2137          mt = ips[j]->instrument(call_dummy_create, callPreInsn, orderFirstAtPoint, false, 
2138                false);
2139          if (!mt)
2140          {
2141             fprintf(stderr, "[%s:%d] - Couldn't instrument thread_create\n",
2142                   __FILE__, __LINE__);
2143          }
2144       }
2145    }   
2146    return true;
2147 }
2148
2149 bool process::initMT()
2150 {
2151    bool res;
2152    bool result = true;
2153
2154    /** Check the magic environment variable.
2155     *  We want AIXTHREAD_SCOPE to be "S", which means map 1:1 pthread->kernel threads.
2156     *  If it isn't set, we can't track threads correctly.
2157     */
2158    char *thread_scope = getenv("AIXTHREAD_SCOPE");
2159    if ((thread_scope == NULL) ||
2160        (strcmp(thread_scope, "S") != 0)) {
2161        fprintf(stderr, "Error: multithread support requires the environment variable AIXTHREAD_SCOPE to be set to \"S\".\n");
2162        return false;
2163    }
2164
2165    /**
2166     * Instrument thread_create with calls to DYNINST_dummy_create
2167     **/
2168    //Find DYNINST_dummy_create
2169    pdvector<int_function *> dummy_create_funcs;
2170    int_function *dummy_create = findOnlyOneFunction("DYNINST_dummy_create");
2171    if (!dummy_create)
2172    {
2173       fprintf(stderr, "[%s:%d] - Could not find DYNINST_dummy_create\n",
2174               __FILE__, __LINE__);
2175       return false;
2176    }
2177
2178    bool res1 = instrumentThrdFunc(dummy_create, "_pthread_body", this);
2179    bool res2 = instrumentThrdFunc(dummy_create, "_pthread_body_start", this);
2180    if (!res1 && !res2)
2181    {
2182       startup_printf("[%s:%u] - Error. Couldn't find any thread init functions " 
2183                      "to instrument\n", FILE__, __LINE__);
2184       result = false;
2185    }
2186    
2187    res = initWrapperFunction(this, "DYNINST_pthread_getthrds_np_record", 
2188                              "pthread_getthrds_np");
2189    if (!res) result = false;
2190    res = initWrapperFunction(this, "DYNINST_pthread_self_record", 
2191                              "pthread_self");
2192    if (!res) result = false;
2193
2194    return result;
2195 }
2196  
2197 #include <sched.h>
2198 void dyninst_yield()
2199 {
2200    sched_yield();
2201 }
2202
2203 bool SignalHandler::handleProcessExitPlat(EventRecord & /*ev*/, bool &) 
2204 {
2205     return true;
2206 }
2207
2208 bool process::hasPassedMain() 
2209 {
2210    return true;
2211 }