- New file to extract type info from executables in Coff format
[dyninst.git] / dyninstAPI / src / inst-x86.C
1 /*
2  * Copyright (c) 1996 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 /*
43  * inst-x86.C - x86 dependent functions and code generator
44  * $Id: inst-x86.C,v 1.53 2000/01/11 21:55:35 altinel Exp $
45  */
46
47 #include <limits.h>
48 #include "util/h/headers.h"
49
50 #ifndef BPATCH_LIBRARY
51 #include "rtinst/h/rtinst.h"
52 #endif
53 #include "util/h/Dictionary.h"
54 #include "dyninstAPI/src/symtab.h"
55 #include "dyninstAPI/src/process.h"
56 #include "dyninstAPI/src/inst.h"
57 #include "dyninstAPI/src/instP.h"
58 #include "dyninstAPI/src/ast.h"
59 #include "dyninstAPI/src/util.h"
60 #include "dyninstAPI/src/stats.h"
61 #include "dyninstAPI/src/os.h"
62 #include "dyninstAPI/src/showerror.h"
63
64 #include "dyninstAPI/src/arch-x86.h"
65 #include "dyninstAPI/src/inst-x86.h"
66 #include "dyninstAPI/src/instPoint.h" // includes instPoint-x86.h
67 #include "dyninstAPI/src/instP.h" // class returnInstance
68
69 extern bool isPowerOf2(int value, int &result);
70 void BaseTrampTrapHandler(int); //siginfo_t*, ucontext_t*);
71
72 // The general machine registers. 
73 // These values are taken from the Pentium manual and CANNOT be changed.
74 #undef EAX 
75 #define EAX (0)
76 #undef ECX
77 #define ECX (1)
78 #undef EDX
79 #define EDX (2)
80 #undef EBX
81 #define EBX (3)
82 #undef ESP
83 #define ESP (4)
84 #undef EBP
85 #define EBP (5)
86 #undef ESI
87 #define ESI (6)
88 #undef EDI
89 #define EDI (7)
90
91 // Size of a jump rel32 instruction
92 #define JUMP_REL32_SZ (5)
93 #define JUMP_SZ (5)
94 // Size of a call rel32 instruction
95 #define CALL_REL32_SZ (5)
96
97 #define PUSH_RM_OPC1 (0xFF)
98 #define PUSH_RM_OPC2 (6)
99 #define CALL_RM_OPC1 (0xFF)
100 #define CALL_RM_OPC2 (2)
101 #define PUSH_EBP (0x50+EBP)
102 #define SUB_REG_IMM32 (5)
103 #define LEAVE (0xC9)
104
105 /*
106    Function arguments are in the stack and are addressed with a displacement
107    from EBP. EBP points to the saved EBP, EBP+4 is the saved return address,
108    EBP+8 is the first parameter.
109    TODO: what about far calls?
110  */
111
112 #define PARAM_OFFSET (8)
113
114
115 // number of virtual registers
116 #define NUM_VIRTUAL_REGISTERS (32)
117
118 // offset from EBP of the saved EAX for a tramp
119 #define SAVED_EAX_OFFSET (-NUM_VIRTUAL_REGISTERS*4-4)
120
121
122
123
124 /*
125    checkInstructions: check that there are no known jumps to the instructions
126    before and after the point.
127 */
128 void instPoint::checkInstructions() {
129   Address currAddr = addr_;
130   unsigned OKinsns = 0;
131
132   // if jumpAddr_ is not zero, this point has been checked already
133   if (jumpAddr_) 
134     return;
135
136   unsigned tSize;
137   unsigned maxSize = JUMP_SZ;
138   if (address() == func()->getAddress(0)) // entry point
139     maxSize = 2*JUMP_SZ;
140   tSize = insnAtPoint_.size();
141
142   if (!owner()->isJumpTarget(currAddr)) {
143     // check instructions before point
144     unsigned insnsBefore_ = insnsBefore();
145     for (unsigned u = 0; u < insnsBefore_; u++) {
146       OKinsns++;
147       tSize += (*insnBeforePt_)[u].size();
148       currAddr -= (*insnBeforePt_)[u].size();
149       if (owner()->isJumpTarget(currAddr)) {
150         // must remove instruction from point
151         // fprintf(stderr, "check instructions point 0x%lx, jmp to 0x%lx\n",
152         //                addr,currAddr);
153         break;
154       }
155     }
156   }
157   if (insnBeforePt_)
158     (*insnBeforePt_).resize(OKinsns);
159
160   // this is the address where we insert the jump
161   jumpAddr_ = currAddr;
162
163   // check instructions after point
164   currAddr = addr_ + insnAtPoint_.size();
165   OKinsns = 0;
166   unsigned insnsAfter_ = insnsAfter();
167   for (unsigned u = 0; tSize < maxSize && u < insnsAfter_; u++) {
168     if (owner()->isJumpTarget(currAddr))
169       break;
170     OKinsns++;
171     unsigned size = (*insnAfterPt_)[u].size();
172     currAddr += size;
173     tSize += size;
174   }
175   if (insnAfterPt_)
176     (*insnAfterPt_).resize(OKinsns);
177   
178 #ifdef notdef
179   if (tSize < maxSize) {
180     tSize = insnAtPoint_.size();
181     jumpAddr_ = addr_;
182     if (insnBeforePt_) (*insnBeforePt_).resize(0);
183     if (insnAfterPt_) (*insnAfterPt_).resize(0);
184   }
185 #endif
186 }
187
188 #ifndef BPATCH_LIBRARY
189 // Would inst point *this have been triggered in the specified stack frame?
190 // For entry instrumentation, the inst point is assumed to be triggered
191 //  once for every time the function it applies to appears on the stack.
192 // For call site instrumentation, the inst point is assumed to be triggered
193 //  when the function to which apoplies appears on the stack only if the 
194 //  return pc in that function is directloy after the call site.
195 // For other types of instrumentation, thee inst point is assumed not to
196 //  be triggered.
197 bool instPoint::triggeredInStackFrame( pd_Function *stack_func, Address stack_pc,
198                                       callWhen when, process *proc ) {
199     bool ret = false;
200
201     //cerr << "instPoint (Addr =  " << (void*)addr_ << " size = " << size()
202     //     << " func->name = " << func_->prettyName() << ")" << endl;
203     //cerr << " triggeredInStackFrame called, stack_func = ";
204     //if ( stack_func != NULL ) { 
205         //      cerr << stack_func->prettyName(); 
206     //} else {
207     //    cerr << "<null-function>";
208     //}
209     //cerr << " stack_pc = " << (void*)stack_pc << " when = " << (int)when << endl;
210
211     if ( addr_ == func_->addr() && stack_func == func_ ) {
212         //cerr << " hit for function entry" << endl;
213         ret = true;
214     } else if ( insnAtPoint_.isCall() ) {
215         if ( stack_func == func_ && when == callPreInsn ) {
216             // check if the stack_pc points to the instruction after the call site
217             Address base, target;
218             proc->getBaseAddress( stack_func->file()->exec(), base );
219             target = base + addr_ + insnAtPoint_.size();
220             //cerr << " stack_pc should be " << (void*)target;
221             if ( stack_pc == target ) {
222                 //cerr << " -- HIT";
223                 ret = true;
224             } else {
225                 // Check if the stack_pc is from inside this instPoint
226                 trampTemplate *bt = findBaseTramp( this, proc );
227                 target = bt->baseAddr + bt->emulateInsOffset + insnAtPoint_.size();
228                 if( stack_pc == target )
229                     ret = true;
230             }
231             //cerr << endl;
232         }
233     }
234
235     //cerr << " returning " << ret << endl;
236
237     return ret;
238 }
239
240 bool instPoint::triggeredExitingStackFrame( pd_Function *stack_func, Address stack_pc,
241                                       callWhen when, process *proc ) {
242     bool ret = false;
243
244     if ( insnAtPoint_.isCall() ) {
245         if ( stack_func == func_ && when == callPostInsn ) {
246             Address base, target;
247             proc->getBaseAddress( stack_func->file()->exec(), base );
248             target = base + addr_ + insnAtPoint_.size();
249             if ( stack_pc == target ) {
250                 ret = true;
251             } else {
252                 trampTemplate *bt = findBaseTramp( this, proc );
253                 target = bt->baseAddr + bt->emulateInsOffset + insnAtPoint_.size();
254                 if( stack_pc == target )
255                     ret = true;
256             }
257         }
258     } else if ( addr_ != func_->addr() && stack_func == func_ ) {
259         ret = true;
260     }
261
262     return ret;
263 }
264 #endif
265
266
267 #ifdef BPATCH_LIBRARY
268 /*
269    Returns true if we can use the extra slot for a jump at the entry point
270    to insert a jump to a base tramp at this point.
271  */
272 bool instPoint::canUseExtraSlot(process *proc) const {
273   // We get 10 bytes for the entry points, instead of the usual five,
274   // so that we have space for an extra jump. We can then insert a
275   // jump to the basetramp in the second slot of the base tramp
276   // and use a short 2-byte jump from the point to the second jump.
277   // We adopt the following rule: Only one point in the function
278   // can use the indirect jump, and this is the first return point
279   // with a size that is less than five bytes
280   vector<instPoint *>fReturns = func()->funcExits(proc);
281
282   // first check if this point can use the extra slot in the entry point
283   bool canUse = false;
284   for (unsigned u = 0; u < fReturns.size(); u++) {
285     if (fReturns[u] == this) {
286       canUse = true;
287       break;
288     } else if (fReturns[u]->size() < JUMP_SZ)
289       break;
290   }
291
292   return canUse;
293 }
294
295 bool instPoint::usesTrap(process *proc)
296 {
297   checkInstructions();
298
299   if (size() < JUMP_REL32_SZ) {
300     if (canUseExtraSlot(proc)) {
301       const instPoint *entry = func()->funcEntry(proc);
302 #ifdef DONT_MAKE_BASETRAMP_FOR_TRAP
303       if (proc->baseMap.defines(entry) && entry->size() >= 2*JUMP_SZ) {
304 #else
305       const_cast<instPoint *>(entry)->checkInstructions();
306       if (entry->size() >= 2*JUMP_SZ) {
307 #endif /* DONT_MAKE_BASETRAMP_FOR_TRAP */
308         // actual displacement needs to subtract size of instruction (2 bytes)
309         int displacement = entry->address() + 5 - jumpAddr();
310         assert(displacement < 0);
311         if (size() >= 2 && (displacement-2) > SCHAR_MIN) {
312           return false;
313         }
314       }
315     }
316     return true;
317   }
318   return false;
319 }
320 #endif
321
322 /**************************************************************
323  *
324  *  machine dependent methods of pdFunction
325  *
326  **************************************************************/
327
328 // Determine if the called function is a "library" function or a "user" function
329 // This cannot be done until all of the functions have been seen, verified, and
330 // classified
331 //
332 void pd_Function::checkCallPoints() {
333   unsigned int i;
334   instPoint *p;
335   Address loc_addr;
336
337   vector<instPoint*> non_lib;
338
339   for (i=0; i<calls.size(); ++i) {
340     /* check to see where we are calling */
341     p = calls[i];
342     assert(p);
343
344     if (!p->insnAtPoint().isCallIndir()) {
345       loc_addr = p->insnAtPoint().getTarget(p->address());
346       file()->exec()->addJumpTarget(loc_addr);
347       pd_Function *pdf = (file_->exec())->findFunction(loc_addr);
348
349       if (pdf) {
350         p->set_callee(pdf);
351         non_lib += p;
352       } else {
353            // if this is a call outside the fuction, keep it
354            if((loc_addr < getAddress(0))||(loc_addr > (getAddress(0)+size()))){
355                 non_lib += p;
356            }
357            else {
358                delete p;
359            }
360       } 
361     } else {
362       // Indirect call -- be conservative, assume it is a call to
363       // an unnamed user function
364       //assert(!p->callee());
365       p->set_callee(NULL);
366       non_lib += p;
367     }
368   }
369   calls = non_lib;
370
371 }
372
373 // this function is not needed
374 Address pd_Function::newCallPoint(Address, const instruction,
375                                  const image *, bool &)
376 { assert(0); return 0; }
377
378
379 // see if we can recognize a jump table and skip it
380 // return the size of the table in tableSz.
381 bool checkJumpTable(image *im, instruction insn, Address addr, 
382                     Address funcBegin, 
383                     Address &funcEnd,
384                     unsigned &tableSz) {
385
386   const unsigned char *instr = insn.ptr();
387   tableSz = 0;
388   /*
389      the instruction usually used for jump tables is 
390        jmp dword ptr [REG*4 + ADDR]
391      where ADDR is an immediate following the SIB byte.
392      The opcode is 0xFF and the MOD/RM byte is 0x24. 
393      The SS field (bits 7 and 6) of SIB is 2, and the
394      base ( bits 2, 1, 0) is 5. The index bits (5,4,3) 
395      select the register.
396   */
397   if (instr[0] == 0xFF && instr[1] == 0x24 &&
398       ((instr[2] & 0xC0)>>6) == 2 && (instr[2] & 0x7) == 5) {
399     const Address tableBase = *(const Address *)(instr+3);
400     //fprintf(stderr, "Found jump table at 0x%lx 0x%lx\n",addr, tableBase);
401     // check if the table is right after the jump and inside the current function
402     if (tableBase > funcBegin && tableBase < funcEnd) {
403       // table is within function code
404       if (tableBase < addr+insn.size()) {
405         fprintf(stderr, "bad indirect jump at 0x%lx\n", addr);
406         return false;
407       } else if (tableBase > addr+insn.size()) {
408         // jump table may be at the end of the function code - adjust funcEnd
409         funcEnd = tableBase;
410         return true;
411       }
412       // skip the jump table
413       for (const unsigned *ptr = (const unsigned *)im->getPtrToInstruction(tableBase);
414            *ptr >= funcBegin && *ptr <= funcEnd; ptr++) {
415         //fprintf(stderr, " jump table entry = 0x%lx\n", *(unsigned *)ptr);
416         tableSz += sizeof(int);
417       }
418     }
419     else {
420         // fprintf(stderr, "Ignoring external jump table at 0x%lx.\n", tableBase);
421     }
422   }
423   return true;
424 }
425
426
427 /* auxiliary data structures for function findInstPoints */
428 enum { EntryPt, CallPt, ReturnPt };
429 class point_ {
430   public:
431      point_(): point(0), index(0), type(0) {};
432      point_(instPoint *p, unsigned i, unsigned t): point(p), index(i), type(t) {};
433      instPoint *point;
434      unsigned index;
435      unsigned type;
436 };
437
438
439 bool pd_Function::findInstPoints(const image *i_owner) {
440    // sorry this this hack, but this routine can modify the image passed in,
441    // which doesn't occur on other platforms --ari
442    image *owner = const_cast<image *>(i_owner); // const cast
443
444    if (size() == 0) {
445      //fprintf(stderr,"Function %s, size = %d\n", prettyName().string_of(), size());
446      return false;
447    }
448
449 // XXXXX kludge: these functions are called by DYNINSTgetCPUtime, 
450 // they can't be instrumented or we would have an infinite loop
451 if (prettyName() == "gethrvtime" || prettyName() == "_divdi3"
452     || prettyName() == "GetProcessTimes")
453   return false;
454
455    point_ *points = new point_[size()];
456    //point_ *points = (point_ *)alloca(size()*sizeof(point));
457    unsigned npoints = 0;
458
459    const unsigned char *instr = (const unsigned char *)owner->getPtrToInstruction(getAddress(0));
460    Address adr = getAddress(0);
461    unsigned numInsns = 0;
462
463    instruction insn;
464    unsigned insnSize;
465
466    // keep a buffer with all the instructions in this function
467    instruction *allInstr = new instruction[size()+5];
468    //instruction *allInstr = (instruction *)alloca((size()+5)*sizeof(instruction));
469
470    // define the entry point
471    insnSize = insn.getNextInstruction(instr);
472    instPoint *p = new instPoint(this, owner, adr, insn);
473    funcEntry_ = p;
474    points[npoints++] = point_(p, numInsns, EntryPt);
475
476    // check if the entry point contains another point
477    if (insn.isJumpDir()) {
478      Address target = insn.getTarget(adr);
479      owner->addJumpTarget(target);
480      if (target < getAddress(0) || target >= getAddress(0) + size()) {
481        // jump out of function
482        // this is an empty function
483        delete points;
484        delete allInstr;
485        return false;
486      }
487    } else if (insn.isReturn()) {
488      // this is an empty function
489      delete points;
490      delete allInstr;
491      return false;
492    } else if (insn.isCall()) {
493      // TODO: handle calls at entry point
494      // call at entry point
495      //instPoint *p = new instPoint(this, owner, adr, insn);
496      //calls += p;
497      //points[npoints++] = point_(p, numInsns, CallPt);
498      //fprintf(stderr,"Function %s, call at entry point\n", prettyName().string_of());
499      delete points;
500      delete allInstr;
501      return false;
502    }
503
504    allInstr[numInsns] = insn;
505    numInsns++;
506    instr += insnSize;
507    adr += insnSize;
508
509    // get all the instructions for this function, and define the instrumentation
510    // points. For now, we only add one instruction to each point.
511    // Additional instructions, for the points that need them, will be added later.
512
513    Address funcEnd = getAddress(0) + size();
514    for ( ; adr < funcEnd; instr += insnSize, adr += insnSize) {
515      insnSize = insn.getNextInstruction(instr);
516      assert(insnSize > 0);
517
518      if (adr + insnSize > funcEnd) {
519        break;
520      }
521
522      if (insn.isJumpIndir()) {
523        unsigned jumpTableSz;
524        // check for jump table. This may update funcEnd
525        if (!checkJumpTable(owner, insn, adr, getAddress(0), funcEnd, jumpTableSz)) {
526          delete points;
527          delete allInstr;
528          //fprintf(stderr,"Function %s, size = %d, bad jump table\n", 
529          //          prettyName().string_of(), size());
530          return false;
531        }
532        // process the jump instruction
533        allInstr[numInsns] = insn;
534        numInsns++;
535
536        if (jumpTableSz > 0) {
537          // skip the jump table
538          // insert an illegal instruction with the size of the jump table
539          insn = instruction(instr, ILLEGAL, jumpTableSz);
540          allInstr[numInsns] = insn;
541          numInsns++;
542          insnSize += jumpTableSz;
543        }
544      } else if (insn.isJumpDir()) {
545        // check for jumps out of this function
546        Address target = insn.getTarget(adr);
547        owner->addJumpTarget(target);
548        if (target < getAddress(0) || target >= getAddress(0) + size()) {
549          // jump out of function
550          instPoint *p = new instPoint(this, owner, adr, insn);
551          funcReturns += p;
552          points[npoints++] = point_(p, numInsns, ReturnPt);
553        } 
554      } else if (insn.isReturn()) {
555        instPoint *p = new instPoint(this, owner, adr, insn);
556        funcReturns += p;
557        points[npoints++] = point_(p, numInsns, ReturnPt);
558
559      } else if (insn.isCall()) {
560        // calls to adr+5 are not really calls, they are used in dynamically linked
561        // libraries to get the address of the code.
562        // We skip them here.
563        if (insn.getTarget(adr) != adr + 5) {
564          instPoint *p = new instPoint(this, owner, adr, insn);
565          calls += p;
566          points[npoints++] = point_(p, numInsns, CallPt);
567        }
568      }
569
570      allInstr[numInsns] = insn;
571      numInsns++;
572      assert(npoints < size());
573      assert(numInsns <= size());
574    }
575
576    unsigned u;
577    // there are often nops after the end of the function. We get them here,
578    // since they may be usefull to instrument the return point
579    for (u = 0; u < 4; u++) {
580      if (owner->isValidAddress(adr)) {
581        insnSize = insn.getNextInstruction(instr);
582        if (insn.isNop()) {
583          allInstr[numInsns] = insn;
584          numInsns++;
585          assert(numInsns < size()+5);
586          instr += insnSize;
587          adr += insnSize;
588        }
589        else
590          break;
591      }
592    }
593
594
595    // add extra instructions to the points that need it.
596    unsigned lastPointEnd = 0;
597    unsigned thisPointEnd = 0;
598    for (u = 0; u < npoints; u++) {
599      instPoint *p = points[u].point;
600      unsigned index = points[u].index;
601      unsigned type = points[u].type;
602      lastPointEnd = thisPointEnd;
603      thisPointEnd = index;
604
605      // add instructions before the point
606      unsigned size = p->size();
607      for (int u1 = index-1; size < JUMP_SZ && u1 >= 0 && u1 > (int)lastPointEnd; u1--) {
608        if (!allInstr[u1].isCall()) {
609          p->addInstrBeforePt(allInstr[u1]);
610          size += allInstr[u1].size();
611        } else
612          break;
613      }
614
615      lastPointEnd = index;
616      // add instructions after the point
617      if (type == ReturnPt) {
618        // normally, we would not add instructions after the return, but the 
619        // compilers often add nops after the return, and we can use them if necessary
620        for (unsigned u1 = index+1; u1 < index+JUMP_SZ-1 && u1 < numInsns; u1++) {
621          if (allInstr[u1].isNop() || *(allInstr[u1].ptr()) == 0xCC) {
622            p->addInstrAfterPt(allInstr[u1]);
623            thisPointEnd = u1;
624          }
625          else 
626            break;
627        }
628      } else {
629        size = p->size();
630        unsigned maxSize = JUMP_SZ;
631        if (type == EntryPt) maxSize = 2*JUMP_SZ;
632        for (unsigned u1 = index+1; size < maxSize && u1 <= numInsns; u1++) {
633          if (((u+1 == npoints) || (u+1 < npoints && points[u+1].index > u1))
634              && !allInstr[u1].isCall()) {
635            p->addInstrAfterPt(allInstr[u1]);
636            size += allInstr[u1].size();
637            thisPointEnd = u1;
638          }
639          else 
640            break;
641        }
642      }
643    }
644
645    delete points;
646    delete allInstr;
647
648    return true;
649 }
650
651
652 /*
653  * Given an instruction, relocate it to a new address, patching up
654  *   any relative addressing that is present.
655  * The instruction may need to be replaced with a different size instruction
656  * or with multiple instructions.
657  * Return the size of the new instruction(s)
658  */
659 unsigned relocateInstruction(instruction insn,
660                          int origAddr, int newAddr,
661                          unsigned char *&newInsn)
662 {
663   /* 
664      Relative address instructions need to be modified. The relative address
665      can be a 8, 16, or 32-byte displacement relative to the next instruction.
666      Since we are relocating the instruction to a different area, we have
667      to replace 8 and 16-byte displacements with 32-byte displacements.
668
669      All relative address instructions are one or two-byte opcode followed
670      by a displacement relative to the next instruction:
671
672        CALL rel16 / CALL rel32
673        Jcc rel8 / Jcc rel16 / Jcc rel32
674        JMP rel8 / JMP rel16 / JMP rel32
675
676      The only two-byte opcode instructions are the Jcc rel16/rel32,
677      all others have one byte opcode.
678
679      The instruction JCXZ/JECXZ rel8 does not have an equivalent with rel32
680      displacement. We must generate code to emulate this instruction:
681      
682        JCXZ rel8
683
684      becomes
685
686        A0: JCXZ 2 (jump to A4)
687        A2: JMP 5  (jump to A9)
688        A4: JMP rel32 (relocated displacement)
689        A9: ...
690
691   */
692
693   const unsigned char *origInsn = insn.ptr();
694   unsigned insnType = insn.type();
695   unsigned insnSz = insn.size();
696   unsigned char *first = newInsn;
697
698   int oldDisp;
699   int newDisp;
700
701   if (insnType & REL_B) {
702     /* replace with rel32 instruction, opcode is one byte. */
703     if (*origInsn == JCXZ) {
704       oldDisp = (int)*(const char *)(origInsn+1);
705       newDisp = (origAddr + 2) + oldDisp - (newAddr + 9);
706       *newInsn++ = *origInsn; *(newInsn++) = 2; // jcxz 2
707       *newInsn++ = 0xEB; *newInsn++ = 5;        // jmp 5
708       *newInsn++ = 0xE9;                        // jmp rel32
709       *((int *)newInsn) = newDisp;
710       newInsn += sizeof(int);
711     }
712     else {
713       unsigned newSz=UINT_MAX;
714       if (insnType & IS_JCC) {
715         /* Change a Jcc rel8 to Jcc rel32. 
716            Must generate a new opcode: a 0x0F followed by (old opcode + 16) */
717         unsigned char opcode = *origInsn++;
718         *newInsn++ = 0x0F;
719         *newInsn++ = opcode + 0x10;
720         newSz = 6;
721       }
722       else if (insnType & IS_JUMP) {
723         /* change opcode to 0xE9 */
724         origInsn++;
725         *newInsn++ = 0xE9;
726         newSz = 5;
727       }
728       assert(newSz!=UINT_MAX);
729       oldDisp = (int)*(const char *)origInsn;
730       newDisp = (origAddr + 2) + oldDisp - (newAddr + newSz);
731       *((int *)newInsn) = newDisp;
732       newInsn += sizeof(int);
733     }
734   }
735   else if (insnType & REL_W) {
736     /* Skip prefixes */
737     if (insnType & PREFIX_OPR)
738       origInsn++;
739     if (insnType & PREFIX_SEG)
740       origInsn++;
741     /* opcode is unchanged, just relocate the displacement */
742     if (*origInsn == (unsigned char)0x0F)
743       *newInsn++ = *origInsn++;
744     *newInsn++ = *origInsn++;
745     oldDisp = *((const short *)origInsn);
746     newDisp = (origAddr + 5) + oldDisp - (newAddr + 3);
747     *((int *)newInsn) = newDisp;
748     newInsn += sizeof(int);
749   } else if (insnType & REL_D) {
750     // Skip prefixes
751     unsigned nPrefixes = 0;
752     if (insnType & PREFIX_OPR)
753       nPrefixes++;
754     if (insnType & PREFIX_SEG)
755       nPrefixes++;
756     for (unsigned u = 0; u < nPrefixes; u++)
757       *newInsn++ = *origInsn++;
758
759     /* opcode is unchanged, just relocate the displacement */
760     if (*origInsn == 0x0F)
761       *newInsn++ = *origInsn++;
762     *newInsn++ = *origInsn++;
763     oldDisp = *((const int *)origInsn);
764     newDisp = (origAddr + insnSz) + oldDisp - (newAddr + insnSz);
765     *((int *)newInsn) = newDisp;
766     newInsn += sizeof(int);
767   }
768   else {
769     /* instruction is unchanged */
770     for (unsigned u = 0; u < insnSz; u++)
771       *newInsn++ = *origInsn++;
772   }
773
774   return (newInsn - first);
775 }
776
777
778 /*
779  * Relocate a conditional jump and change the target to newTarget.
780  * The new target must be within 128 bytes from the new address
781  * Size of instruction is unchanged.
782  * Returns the old target
783  */
784 unsigned changeConditionalJump(instruction insn,
785                          int origAddr, int newAddr, int newTargetAddr,
786                          unsigned char *&newInsn)
787 {
788
789   const unsigned char *origInsn = insn.ptr();
790   unsigned insnType = insn.type();
791   unsigned insnSz = insn.size();
792
793   int oldDisp=-1;
794   int newDisp;
795
796   if (insnType & REL_B) {
797     /* one byte opcode followed by displacement */
798     /* opcode is unchanged */
799     assert(insnSz==2);
800     *newInsn++ = *origInsn++;
801     oldDisp = (int)*(const char *)origInsn;
802     newDisp = newTargetAddr - (newAddr + insnSz);
803     *newInsn++ = (char)newDisp;
804   }
805   else if (insnType & REL_W) {
806     /* Skip prefixes */
807     if (insnType & PREFIX_OPR)
808       *newInsn++ = *origInsn++;
809     if (insnType & PREFIX_SEG)
810       *newInsn++ = *origInsn++;
811
812     assert(*origInsn==0x0F);
813     *newInsn++ = *origInsn++; // copy the 0x0F
814     *newInsn++ = *origInsn++; // second opcode byte
815
816     oldDisp = *((const short *)origInsn);
817     newDisp = newTargetAddr - (newAddr + insnSz);
818     *((short *)newInsn) = (short)newDisp;
819     newInsn += sizeof(short);
820   }
821   else if (insnType & REL_D) {
822     // Skip prefixes
823     if (insnType & PREFIX_OPR)
824       *newInsn++ = *origInsn++;
825     if (insnType & PREFIX_SEG)
826       *newInsn++ = *origInsn++;
827
828     assert(*origInsn==0x0F);
829     *newInsn++ = *origInsn++; // copy the 0x0F
830     *newInsn++ = *origInsn++; // second opcode byte
831
832     oldDisp = *((const int *)origInsn);
833     newDisp = newTargetAddr - (newAddr + insnSz);
834     *((int *)newInsn) = (int)newDisp;
835     newInsn += sizeof(int);
836   }
837
838   assert (oldDisp!=-1);
839   return (origAddr+insnSz+oldDisp);
840 }
841
842
843
844 unsigned getRelocatedInstructionSz(instruction insn)
845 {
846   const unsigned char *origInsn = insn.ptr();
847   unsigned insnType = insn.type();
848   unsigned insnSz = insn.size();
849
850   if (insnType & REL_B) {
851     if (*origInsn == JCXZ)
852       return 9;
853     else {
854       if (insnType & IS_JCC)
855         return 6;
856       else if (insnType & IS_JUMP) {
857         return 5;
858       }
859     }
860   }
861   else if (insnType & REL_W) {
862     return insnSz + 2;
863   }
864   return insnSz;
865 }
866
867
868 registerSpace *regSpace;
869
870
871 bool registerSpace::readOnlyRegister(Register) {
872   return false;
873 }
874
875 /*
876    We don't use the machine registers to store temporaries,
877    but "virtual registers" that are located on the stack.
878    The stack frame for a tramp is:
879
880      ebp->    saved ebp (4 bytes)
881      ebp-4:   128-byte space for 32 virtual registers (32*4 bytes)
882      ebp-132: saved registers (8*4 bytes)
883      ebp-164: saved flags registers (4 bytes)
884
885      The temporaries are assigned numbers from 1 so that it is easier
886      to refer to them: -(reg*4)[ebp]. So the first reg is -4[ebp].
887
888      We are using a fixed number of temporaries now (32), but we could 
889      change to using an arbitrary number.
890
891 */
892 Register deadList[NUM_VIRTUAL_REGISTERS];
893 int deadListSize = sizeof(deadList);
894
895 void initTramps()
896 {
897     static bool inited=false;
898
899     if (inited) return;
900     inited = true;
901
902 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
903     for (unsigned u = 0; u < NUM_VIRTUAL_REGISTERS-1; u++) {
904 #else
905     for (unsigned u = 0; u < NUM_VIRTUAL_REGISTERS; u++) {
906 #endif
907       deadList[u] = u+1;
908     }
909
910     regSpace = new registerSpace(deadListSize/sizeof(Register), deadList,
911                                 0, NULL);
912 }
913
914
915 void emitJump(unsigned disp32, unsigned char *&insn);
916 void emitSimpleInsn(unsigned opcode, unsigned char *&insn);
917 void emitMovRegToReg(Register dest, Register src, unsigned char *&insn);
918 void emitAddMemImm32(Address dest, int imm, unsigned char *&insn);
919 void emitAddRegImm32(Register dest, int imm, unsigned char *&insn);
920 void emitOpRegImm(int opcode, Register dest, int imm, unsigned char *&insn);
921 void emitMovRegToRM(Register base, int disp, Register src, unsigned char *&insn);
922 void emitMovRMToReg(Register dest, Register base, int disp, unsigned char *&insn);
923 void emitCallRel32(unsigned disp32, unsigned char *&insn);
924
925
926 /*
927  * change the insn at addr to be a branch to newAddr.
928  *   Used to add multiple tramps to a point.
929  */
930 void generateBranch(process *proc, Address fromAddr, Address newAddr)
931 {
932   unsigned char inst[JUMP_REL32_SZ+1];
933   unsigned char *insn = inst;
934   emitJump(newAddr - (fromAddr + JUMP_REL32_SZ), insn);
935   proc->writeTextSpace((caddr_t)fromAddr, JUMP_REL32_SZ, (caddr_t)inst);
936 }
937
938
939 bool insertInTrampTable(process *proc, unsigned key, unsigned val) {
940   unsigned u;
941
942   // check for overflow of the tramp table. 
943   // stop at 95% capacicty to ensure good performance
944   if (proc->trampTableItems == (TRAMPTABLESZ - TRAMPTABLESZ/20))
945     return false;
946   proc->trampTableItems++;
947   for (u = HASH1(key); proc->trampTable[u].key != 0; 
948        u = (u + HASH2(key)) % TRAMPTABLESZ)
949     ;
950   proc->trampTable[u].key = key;
951   proc->trampTable[u].val = val;
952
953 #if !defined(i386_unknown_nt4_0)
954   bool err = false;
955   Address addr = proc->findInternalAddress("DYNINSTtrampTable",true, err);
956   assert(err==false);
957   return proc->writeTextSpace((caddr_t)addr+u*sizeof(trampTableEntry),
958                        sizeof(trampTableEntry),
959                        (caddr_t)&(proc->trampTable[u]));
960 #else
961   return true;
962 #endif
963 }
964
965 // generate a jump to a base tramp or a trap
966 // return the size of the instruction generated
967 unsigned generateBranchToTramp(process *proc, const instPoint *point, Address baseAddr, 
968                            Address imageBaseAddr, unsigned char *insn) {
969   if (point->size() < JUMP_REL32_SZ) {
970
971     // the point is not big enough for a jump
972     // First, check if we can use an indirection with the entry point
973     // if that is not possible, we must use a trap
974 #ifdef BPATCH_LIBRARY
975     pd_Function *f = point->func();
976     if (point->canUseExtraSlot(proc)) {
977 #else
978     // We get 10 bytes for the entry points, instead of the usual five,
979     // so that we have space for an extra jump. We can then insert a
980     // jump to the basetramp in the second slot of the base tramp
981     // and use a short 2-byte jump from the point to the second jump.
982     // We adopt the following rule: Only one point in the function
983     // can use the indirect jump, and this is the first return point
984     // with a size that is less than five bytes
985     pd_Function *f = point->func();
986     vector<instPoint *>fReturns = f->funcExits(proc);
987
988     // first check if this point can use the extra slot in the entry point
989     bool canUse = false;
990     for (unsigned u = 0; u < fReturns.size(); u++) {
991       if (fReturns[u] == point) {
992         canUse = true;
993         break;
994       } else if (fReturns[u]->size() < JUMP_SZ)
995         break;
996     }
997     if (canUse) {
998 #endif
999       const instPoint *the_entry = f->funcEntry(proc);
1000 #ifdef DONT_MAKE_BASETRAMP_FOR_TRAP
1001       if (proc->baseMap.defines(the_entry) && the_entry->size() >= 2*JUMP_SZ) {
1002         assert(point->jumpAddr() > the_entry->address());
1003         // actual displacement needs to subtract size of instruction (2 bytes)
1004         int displacement = the_entry->address() + 5 - point->jumpAddr();
1005         assert(displacement < 0);
1006         if (point->size() >= 2 && (displacement-2) > SCHAR_MIN) {
1007           generateBranch(proc, the_entry->address()+5, baseAddr);
1008           *insn++ = 0xEB;
1009           *insn++ = (char)(displacement-2);
1010           return 2;
1011         }
1012       }
1013 #else /* DONT_MAKE_BASETRAMP_FOR_TRAP */
1014       const_cast<instPoint *>(the_entry)->checkInstructions();
1015       if (the_entry->size() >= 2*JUMP_SZ) {
1016         assert(point->jumpAddr() > the_entry->address());
1017         // actual displacement needs to subtract size of instruction (2 bytes)
1018         int displacement = the_entry->address() + 5 - point->jumpAddr();
1019         assert(displacement < 0);
1020         if (point->size() >= 2 && (displacement-2) > SCHAR_MIN) {
1021           returnInstance *retInstance;
1022           instPoint *nonConstEntry = const_cast<instPoint *>(the_entry);
1023           // XXX Is making the noCost parameter always false okay here?
1024           trampTemplate *entryBase =
1025               findAndInstallBaseTramp(proc, nonConstEntry,
1026                                       retInstance, false);
1027           assert(entryBase);
1028           if (retInstance) {
1029               retInstance->installReturnInstance(proc);
1030           }
1031           generateBranch(proc, the_entry->address()+imageBaseAddr+5, baseAddr);
1032           *insn++ = 0xEB;
1033           *insn++ = (char)(displacement-2);
1034           return 2;
1035         }
1036       }
1037 #endif /* DONT_MAKE_BASETRAMP_FOR_TRAP */
1038     }
1039
1040     // must use trap
1041     //sprintf(errorLine, "Warning: unable to insert jump in function %s,"
1042     //            " address 0x%lx. Using trap\n",
1043     //            point->func()->prettyName().string_of(),point->address());
1044     //logLine(errorLine);
1045 #ifdef INST_TRAP_DEBUG
1046         cerr << "Warning: unable to insert jump in function " <<
1047                 point->func()->prettyName().string_of() << ", address " <<
1048                 (void*)point->address() << ". Using trap." << endl;
1049 #endif
1050
1051     if (!insertInTrampTable(proc, point->jumpAddr()+imageBaseAddr, baseAddr))
1052       return 0;
1053
1054     *insn = 0xCC;
1055     return 1;
1056   } else {
1057     // replace instructions at point with jump to base tramp
1058     emitJump(baseAddr - (point->jumpAddr() + imageBaseAddr + JUMP_REL32_SZ), insn);
1059     return JUMP_REL32_SZ;
1060   }
1061 }
1062
1063
1064 /*
1065  * Install a base tramp, relocating the instructions at location
1066  * The pre and post jumps are filled with a 'jump 0'
1067  * Return a descriptor for the base tramp.
1068  *
1069  */
1070
1071 trampTemplate *installBaseTramp(const instPoint *location, process *proc, bool noCost) 
1072 {
1073    bool aflag;
1074 /*
1075    The base tramp:
1076    addr   instruction             cost
1077    0:    <relocated instructions before point>
1078    a = size of relocated instructions before point
1079    a+0:   jmp a+30 <skip pre insn>  1
1080    a+5:   push ebp                  1
1081    a+6:   mov esp, ebp              1
1082    a+8:   subl esp, 0x80            1
1083    a+14:  pushad                    5
1084    a+15:  pushaf                    9
1085    a+16:  jmp <global pre inst>     1
1086    a+21:  jmp <local pre inst>      1
1087    a+26:  popaf                    14
1088    a+27:  popad                     5
1089    a+28:  leave                     3
1090    a+29:  add costAddr, cost        3
1091    a+39:  <relocated instructions at point>
1092
1093    b = a +30 + size of relocated instructions at point
1094    b+0:   jmp b+30 <skip post insn>
1095    b+5:   push ebp
1096    b+6:   mov esp, ebp
1097    b+8:   subl esp, 0x80
1098    b+14:  pushad
1099    b+15:  pushaf
1100    b+16:  jmp <global post inst>
1101    b+21:  jmp <local post inst>
1102    b+26:  popaf
1103    b+27:  popad
1104    b+28:  leave
1105    b+29:  <relocated instructions after point>
1106
1107    c:     jmp <return to user code>
1108
1109    tramp size = 2*23 + 10 + 5 + size of relocated instructions
1110    Make sure to update the size if the tramp is changed
1111
1112    cost of pre and post instrumentation is (1+1+1+5+9+1+1+15+5+3) = 42
1113    cost of rest of tramp is (1+3+1+1)
1114
1115 */
1116
1117   unsigned u;
1118   trampTemplate *ret = new trampTemplate;
1119   ret->trampTemp = 0;
1120   unsigned jccTarget = 0; // used when the instruction at the point is a cond. jump
1121   unsigned auxJumpOffset = 0;
1122
1123   // check instructions at this point to find how many instructions 
1124   // we should relocate
1125   const_cast<instPoint*>(location)->checkInstructions();
1126
1127   // compute the tramp size
1128   // if there are any changes to the tramp, the size must be updated.
1129 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
1130   unsigned trampSize = 73+2*27 + 66;
1131 #else
1132   unsigned trampSize = 73;
1133 #endif
1134
1135   for (u = 0; u < location->insnsBefore(); u++) {
1136     trampSize += getRelocatedInstructionSz(location->insnBeforePt(u));
1137   }
1138   if (location->insnAtPoint().type() & IS_JCC)
1139     trampSize += location->insnAtPoint().size() + 2 * JUMP_SZ;
1140   else
1141     trampSize += getRelocatedInstructionSz(location->insnAtPoint());
1142   for (u = 0; u < location->insnsAfter(); u++) {
1143     trampSize += getRelocatedInstructionSz(location->insnAfterPt(u));
1144   }
1145
1146   Address imageBaseAddr;
1147   if (!proc->getBaseAddress(location->owner(), imageBaseAddr)) {
1148     abort();
1149   }
1150
1151   Address costAddr = 0; // for now...
1152   if (!noCost) {
1153 #ifdef SHM_SAMPLING
1154      costAddr = (Address)proc->getObsCostLowAddrInApplicSpace();
1155      assert(costAddr);
1156 #else
1157      // get address of DYNINSTobsCostLow to update observed cost
1158      bool err = false;
1159      costAddr = proc->findInternalAddress("DYNINSTobsCostLow",
1160                                           true, err);
1161      assert(costAddr && !err);
1162 #endif
1163   }
1164
1165   ret->size = trampSize;
1166   Address baseAddr = inferiorMalloc(proc, trampSize, textHeap);
1167   ret->baseAddr = baseAddr;
1168
1169   unsigned char *code = new unsigned char[2*trampSize];
1170   unsigned char *insn = code;
1171   Address currAddr = baseAddr;
1172
1173   // get the current instruction that is being executed. If the PC is at a
1174   // instruction that is being relocated, we must change the PC.
1175   Address currentPC = proc->currentPC();
1176
1177   // emulate the instructions before the point
1178   Address origAddr = location->jumpAddr() + imageBaseAddr;
1179   for (u = location->insnsBefore(); u > 0; ) {
1180     --u;
1181     if (currentPC == origAddr) {
1182       //fprintf(stderr, "changed PC: 0x%lx to 0x%lx\n", currentPC, currAddr);
1183       proc->setNewPC(currAddr);
1184     }
1185
1186     unsigned newSize = relocateInstruction(location->insnBeforePt(u), origAddr, currAddr, insn);
1187     aflag=(newSize == getRelocatedInstructionSz(location->insnBeforePt(u)));
1188     assert(aflag);
1189     currAddr += newSize;
1190     origAddr += location->insnBeforePt(u).size();
1191   }
1192
1193
1194   /***
1195     If the instruction at the point is a conditional jump, we relocate it to
1196     the top of the base tramp, and change the code so that the tramp is executed
1197     only if the branch is taken.
1198
1199     e.g.
1200      L1:  jne target
1201      L2:  ...
1202
1203     becomes
1204
1205           jne T1
1206           jmp T2
1207           jne
1208      T1:  ...
1209
1210      T2:  relocated instructions after point
1211
1212      then later at the base tramp, at the point where we relocate the instruction
1213      at the point, we insert a jump to target
1214   ***/
1215   if (location->insnAtPoint().type() & IS_JCC) {
1216      currAddr = baseAddr + (insn - code);
1217      assert(origAddr == location->address() + imageBaseAddr);
1218      origAddr = location->address() + imageBaseAddr;
1219      if (currentPC == origAddr &&
1220          currentPC != (location->jumpAddr() + imageBaseAddr)) {
1221        //fprintf(stderr, "changed PC: 0x%lx to 0x%lx\n", currentPC, currAddr);
1222        proc->setNewPC(currAddr);
1223      }
1224
1225      jccTarget = changeConditionalJump(location->insnAtPoint(), origAddr, currAddr,
1226                                        currAddr+location->insnAtPoint().size()+5, insn);
1227      currAddr += location->insnAtPoint().size();
1228      auxJumpOffset = insn-code;
1229      emitJump(0, insn);
1230      origAddr += location->insnAtPoint().size();
1231   }
1232
1233   // pre branches
1234   // skip pre instrumentation
1235   ret->skipPreInsOffset = insn-code;
1236   emitJump(0, insn);
1237
1238   // save registers and create a new stack frame for the tramp
1239   ret->savePreInsOffset = insn-code;
1240   emitSimpleInsn(PUSH_EBP, insn);  // push ebp
1241   emitMovRegToReg(EBP, ESP, insn); // mov ebp, esp  (2-byte instruction)
1242   // allocate space for temporaries (virtual registers)
1243   emitOpRegImm(5, ESP, 128, insn); // sub esp, 128
1244   emitSimpleInsn(PUSHAD, insn);    // pushad
1245   emitSimpleInsn(PUSHFD, insn);    // pushfd
1246
1247 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
1248   // generate preamble for MT version
1249   Address base=0;
1250   generateMTpreamble((char *)insn, base, proc);
1251   insn += base;
1252 #endif
1253
1254   // global pre branch
1255   ret->globalPreOffset = insn-code;
1256   emitJump(0, insn);
1257
1258   // local pre branch
1259   ret->localPreOffset = insn-code;
1260   emitJump(0, insn);
1261
1262   ret->localPreReturnOffset = insn-code;
1263
1264   // restore registers
1265   emitSimpleInsn(POPFD, insn);     // popfd
1266   emitSimpleInsn(POPAD, insn);     // popad
1267   ret->restorePreInsOffset = insn-code;
1268   emitSimpleInsn(LEAVE, insn);     // leave
1269
1270   // update cost
1271   // update cost -- a 10-byte instruction
1272   ret->updateCostOffset = insn-code;
1273   currAddr = baseAddr + (insn-code);
1274   ret->costAddr = currAddr;
1275   if (!noCost) {
1276      emitAddMemImm32(costAddr, 88, insn);  // add (costAddr), cost
1277   }
1278   else {
1279      // minor hack: we still need to fill up the rest of the 10 bytes, since
1280      // assumptions are made about the positioning of instructions that follow.
1281      // (This could in theory be fixed)
1282      // So, 10 NOP instructions (each 1 byte)
1283      for (unsigned foo=0; foo < 10; foo++)
1284         emitSimpleInsn(0x90, insn); // NOP
1285   }
1286
1287    
1288   if (!(location->insnAtPoint().type() & IS_JCC)) {
1289     // emulate the instruction at the point 
1290     ret->emulateInsOffset = insn-code;
1291     currAddr = baseAddr + (insn - code);
1292     assert(origAddr == location->address() + imageBaseAddr);
1293     origAddr = location->address() + imageBaseAddr;
1294     if (currentPC == origAddr &&
1295         currentPC != (location->jumpAddr() + imageBaseAddr)) {
1296       //fprintf(stderr, "changed PC: 0x%lx to 0x%lx\n", currentPC, currAddr);
1297       proc->setNewPC(currAddr);
1298     }
1299
1300     unsigned newSize = relocateInstruction(location->insnAtPoint(), origAddr, currAddr, insn);
1301     aflag=(newSize == getRelocatedInstructionSz(location->insnAtPoint()));
1302     assert(aflag);
1303     currAddr += newSize;
1304     origAddr += location->insnAtPoint().size();
1305   } else {
1306     // instruction at point is a conditional jump. 
1307     // The instruction was relocated to the beggining of the tramp (see comments above)
1308     // We must generate a jump to the original target here
1309     assert(jccTarget > 0);
1310     currAddr = baseAddr + (insn - code);
1311     emitJump(jccTarget-(currAddr+JUMP_SZ), insn);
1312     currAddr += JUMP_SZ;
1313   }
1314
1315   // post branches
1316   // skip post instrumentation
1317   ret->skipPostInsOffset = insn-code;
1318   emitJump(0, insn);
1319
1320
1321   // save registers and create a new stack frame for the tramp
1322   ret->savePostInsOffset = insn-code;
1323   emitSimpleInsn(PUSH_EBP, insn);  // push ebp
1324   emitMovRegToReg(EBP, ESP, insn); // mov ebp, esp
1325   // allocate space for temporaries (virtual registers)
1326   emitOpRegImm(5, ESP, 128, insn); // sub esp, 128
1327   emitSimpleInsn(PUSHAD, insn);    // pushad
1328   emitSimpleInsn(PUSHFD, insn);    // pushfd
1329
1330 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
1331   // generate preamble for MT version
1332   base=0;
1333   generateMTpreamble((char *)insn, base, proc);
1334   insn += base;
1335 #endif
1336
1337   // global post branch
1338   ret->globalPostOffset = insn-code; 
1339   emitJump(0, insn);
1340
1341   // local post branch
1342   ret->localPostOffset = insn-code;
1343   emitJump(0, insn);
1344
1345   ret->localPostReturnOffset = insn-code;
1346
1347   // restore registers
1348   emitSimpleInsn(POPFD, insn);     // popfd
1349   emitSimpleInsn(POPAD, insn);     // popad
1350   ret->restorePostInsOffset = insn-code;
1351   emitSimpleInsn(LEAVE, insn);     // leave
1352   
1353   // emulate the instructions after the point
1354   ret->returnInsOffset = insn-code;
1355   currAddr = baseAddr + (insn - code);
1356   assert(origAddr == location->address() + imageBaseAddr + location->insnAtPoint().size());
1357   origAddr = location->address() + imageBaseAddr + location->insnAtPoint().size();
1358   for (u = 0; u < location->insnsAfter(); u++) {
1359     if (currentPC == origAddr) {
1360       //fprintf(stderr, "changed PC: 0x%lx to 0x%lx\n", currentPC, currAddr);
1361       proc->setNewPC(currAddr);
1362     }
1363     unsigned newSize = relocateInstruction(location->insnAfterPt(u), origAddr, currAddr, insn);
1364     aflag=(newSize == getRelocatedInstructionSz(location->insnAfterPt(u)));
1365     assert(aflag);
1366     currAddr += newSize;
1367     origAddr += location->insnAfterPt(u).size();
1368   }
1369
1370   // return to user code
1371   currAddr = baseAddr + (insn - code);
1372   emitJump(location->returnAddr()+imageBaseAddr - (currAddr+JUMP_SZ), insn);
1373 #ifdef INST_TRAP_DEBUG
1374   cerr << "installBaseTramp jump back to " <<
1375           (void*)( location->returnAddr() + imageBaseAddr ) << endl;
1376 #endif
1377
1378   assert((unsigned)(insn-code) == trampSize);
1379
1380   // update the jumps to skip pre and post instrumentation
1381   unsigned char *ip = code + ret->skipPreInsOffset;
1382   emitJump(ret->updateCostOffset - (ret->skipPreInsOffset+JUMP_SZ), ip);
1383   ip = code + ret->skipPostInsOffset;
1384   emitJump(ret->returnInsOffset - (ret->skipPostInsOffset+JUMP_SZ), ip);
1385
1386   if (auxJumpOffset > 0) {
1387     ip = code + auxJumpOffset;
1388     emitJump(ret->returnInsOffset - (auxJumpOffset+JUMP_SZ), ip);
1389   }
1390   
1391   // put the tramp in the application space
1392   proc->writeDataSpace((caddr_t)baseAddr, insn-code, (caddr_t) code);
1393
1394   delete [] code;
1395
1396   ret->cost = 6;
1397   //
1398   // The cost for generateMTpreamble is 25 for pre and post instrumentation:
1399   // movl   $0x80570ec,%eax                1
1400   // call   *%ea                           5
1401   // movl   %eax,0xfffffffc(%ebp)          1
1402   // shll   $0x2,0xfffffffc(%ebp)         12
1403   // addl   $0x84ac670,0xfffffffc(%ebp)    4
1404   // movl   0xfffffffc(%ebp),%eax          1
1405   // movl   %eax,0xffffff80(%ebp)          1
1406   //
1407   ret->prevBaseCost = 42+25;
1408   ret->postBaseCost = 42+25;
1409   ret->prevInstru = false;
1410   ret->postInstru = false;
1411   return ret;
1412 }
1413
1414
1415 // This function is used to clear a jump from base to minitramps
1416 // For the x86 platform, we generate a jump to the next instruction
1417 void generateNoOp(process *proc, Address addr) 
1418 {
1419   static unsigned char jump0[5] = { 0xE9, 0, 0, 0, 0 };
1420   proc->writeDataSpace((caddr_t) addr, 5, (caddr_t)jump0);
1421 }
1422
1423
1424 trampTemplate *findAndInstallBaseTramp(process *proc, 
1425                                        instPoint *&location, 
1426                                        returnInstance *&retInstance,
1427                                        bool noCost)
1428 {
1429     trampTemplate *ret;
1430     retInstance = NULL;
1431
1432     if (!proc->baseMap.defines(location)) {
1433         ret = installBaseTramp(location, proc, noCost);
1434         proc->baseMap[location] = ret;
1435         // generate branch from instrumentation point to base tramp
1436         Address imageBaseAddr;
1437         if (!proc->getBaseAddress(location->owner(), imageBaseAddr))
1438           abort();
1439         unsigned char *insn = new unsigned char[JUMP_REL32_SZ];
1440         unsigned size = generateBranchToTramp(proc, location, ret->baseAddr, 
1441                                               imageBaseAddr, insn);
1442         if (size == 0)
1443           return NULL;
1444         retInstance = new returnInstance(new instruction(insn, 0, size), size,
1445                                          location->jumpAddr() + imageBaseAddr, size);
1446     } else {
1447         ret = proc->baseMap[location];
1448     }
1449     return(ret);
1450 }
1451
1452
1453 /*
1454  * Install a single mini-tramp.
1455  *
1456  */
1457 void installTramp(instInstance *inst, char *code, int codeSize) 
1458 {
1459     totalMiniTramps++;
1460     //insnGenerated += codeSize/sizeof(int);
1461     (inst->proc)->writeDataSpace((caddr_t)inst->trampBase, codeSize, code);
1462     Address atAddr;
1463     if (inst->when == callPreInsn) {
1464         if (inst->baseInstance->prevInstru == false) {
1465             atAddr = inst->baseInstance->baseAddr+inst->baseInstance->skipPreInsOffset;
1466             inst->baseInstance->cost += inst->baseInstance->prevBaseCost;
1467             inst->baseInstance->prevInstru = true;
1468             generateNoOp(inst->proc, atAddr);
1469         }
1470     }
1471     else {
1472         if (inst->baseInstance->postInstru == false) {
1473             atAddr = inst->baseInstance->baseAddr+inst->baseInstance->skipPostInsOffset; 
1474             inst->baseInstance->cost += inst->baseInstance->postBaseCost;
1475             inst->baseInstance->postInstru = true;
1476             generateNoOp(inst->proc, atAddr);
1477         }
1478     }
1479 }
1480
1481
1482 /**************************************************************
1483  *
1484  *  code generator for x86
1485  *
1486  **************************************************************/
1487
1488
1489
1490
1491 #define MAX_BRANCH      (0x1<<31)
1492
1493 Address getMaxBranch() {
1494   return (Address)MAX_BRANCH;
1495 }
1496
1497
1498 bool doNotOverflow(int)
1499 {
1500   //
1501   // this should be changed by the correct code. If there isn't any case to
1502   // be checked here, then the function should return TRUE. If there isn't
1503   // any immediate code to be generated, then it should return FALSE - naim
1504   //
1505   // any int value can be an immediate on the pentium
1506   return(true);
1507 }
1508
1509
1510
1511 /* build the MOD/RM byte of an instruction */
1512 inline unsigned char makeModRMbyte(unsigned Mod, unsigned Reg, unsigned RM) {
1513   return ((Mod & 0x3) << 6) + ((Reg & 0x7) << 3) + (RM & 0x7);
1514 }
1515
1516 /* 
1517    Emit the ModRM byte and displacement for addressing modes.
1518    base is a register (EAX, ECX, EDX, EBX, EBP, ESI, EDI)
1519    disp is a displacement
1520    reg_opcode is either a register or an opcode
1521  */
1522 void emitAddressingMode(Register base, RegValue disp, int reg_opcode, 
1523                         unsigned char *&insn) {
1524   assert(base != ESP);
1525   if (base == Null_Register) {
1526     *insn++ = makeModRMbyte(0, reg_opcode, 5);
1527     *((int *)insn) = disp;
1528     insn += sizeof(int);
1529   } else if (disp == 0 && base != EBP) {
1530     *insn++ = makeModRMbyte(0, reg_opcode, base);
1531   } else if (disp >= -128 && disp <= 127) {
1532     *insn++ = makeModRMbyte(1, reg_opcode, base);
1533     *((char *)insn++) = (char) disp;
1534   } else {
1535     *insn++ = makeModRMbyte(2, reg_opcode, base);
1536     *((int *)insn) = disp;
1537     insn += sizeof(int);
1538   }
1539 }
1540
1541
1542 /* emit a simple one-byte instruction */
1543 void emitSimpleInsn(unsigned op, unsigned char *&insn) {
1544   *insn++ = op;
1545 }
1546
1547 // emit a simple register to register instruction: OP dest, src
1548 // opcode is one or two byte
1549 void emitOpRegReg(unsigned opcode, Register dest, Register src,
1550                   unsigned char *&insn) {
1551   if (opcode <= 0xFF)
1552     *insn++ = opcode;
1553   else {
1554     *insn++ = opcode >> 8;
1555     *insn++ = opcode & 0xFF;
1556   }
1557   // ModRM byte define the operands: Mod = 3, Reg = dest, RM = src
1558   *insn++ = makeModRMbyte(3, dest, src);
1559 }
1560
1561 // emit OP reg, r/m
1562 void emitOpRegRM(unsigned opcode, Register dest, Register base, int disp,
1563                  unsigned char *&insn) {
1564   if (opcode <= 0xff) {
1565     *insn++ = opcode;
1566   } else {
1567     *insn++ = opcode >> 8;
1568     *insn++ = opcode & 0xff;
1569   }
1570   emitAddressingMode(base, disp, dest, insn);
1571 }
1572
1573 // emit OP r/m, reg
1574 void emitOpRMReg(unsigned opcode, Register base, int disp, Register src,
1575                  unsigned char *&insn) {
1576   *insn++ = opcode;
1577   emitAddressingMode(base, disp, src, insn);
1578 }
1579
1580 // emit OP reg, imm32
1581 void emitOpRegImm(int opcode, Register dest, int imm, unsigned char *&insn) {
1582   *insn++ = 0x81;
1583   *insn++ = makeModRMbyte(3, opcode, dest);
1584   *((int *)insn) = imm;
1585   insn+= sizeof(int);
1586 }
1587
1588 /*
1589 // emit OP r/m, imm32
1590 void emitOpRMImm(unsigned opcode, Register base, int disp, int imm,
1591                  unsigned char *&insn) {
1592   *insn++ = 0x81;
1593   emitAddressingMode(base, disp, opcode, insn);
1594   *((int *)insn) = imm;
1595   insn += sizeof(int);
1596 }
1597 */
1598
1599 // emit OP r/m, imm32
1600 void emitOpRMImm(unsigned opcode1, unsigned opcode2,
1601                  Register base, int disp, int imm, unsigned char *&insn) {
1602   *insn++ = opcode1;
1603   emitAddressingMode(base, disp, opcode2, insn);
1604   *((int *)insn) = imm;
1605   insn += sizeof(int);
1606 }
1607
1608 // emit OP r/m, imm8
1609 void emitOpRMImm8(unsigned opcode1, unsigned opcode2,
1610                  Register base, int disp, char imm, unsigned char *&insn) {
1611   *insn++ = opcode1;
1612   emitAddressingMode(base, disp, opcode2, insn);
1613   *insn++ = imm;
1614 }
1615
1616 // emit OP reg, r/m, imm32
1617 void emitOpRegRMImm(unsigned opcode, Register dest,
1618                  Register base, int disp, int imm, unsigned char *&insn) {
1619   *insn++ = opcode;
1620   emitAddressingMode(base, disp, dest, insn);
1621   *((int *)insn) = imm;
1622   insn += sizeof(int);
1623 }
1624
1625 // emit MOV reg, reg
1626 void emitMovRegToReg(Register dest, Register src, unsigned char *&insn) {
1627   *insn++ = 0x8B;
1628   *insn++ = makeModRMbyte(3, dest, src);
1629 }
1630
1631 // emit MOV reg, r/m
1632 void emitMovRMToReg(Register dest, Register base, int disp, unsigned char *&insn) {
1633   *insn++ = 0x8B;
1634   emitAddressingMode(base, disp, dest, insn);
1635 }
1636
1637 // emit MOV r/m, reg
1638 void emitMovRegToRM(Register base, int disp, Register src, unsigned char *&insn) {
1639   *insn++ = 0x89;
1640   emitAddressingMode(base, disp, src, insn);
1641 }
1642
1643 // emit MOV m, reg
1644 void emitMovRegToM(int disp, Register src, unsigned char *&insn) {
1645   *insn++ = 0x89;
1646   emitAddressingMode(Null_Register, disp, src, insn);
1647 }
1648
1649 // emit MOV reg, m
1650 void emitMovMToReg(Register dest, int disp, unsigned char *&insn) {
1651   *insn++ = 0x8B;
1652   emitAddressingMode(Null_Register, disp, dest, insn);
1653 }
1654
1655 // emit MOV reg, imm32
1656 void emitMovImmToReg(Register dest, int imm, unsigned char *&insn) {
1657   *insn++ = 0xB8 + dest;
1658   *((int *)insn) = imm;
1659   insn += sizeof(int);
1660 }
1661
1662 // emit MOV r/m32, imm32
1663 void emitMovImmToRM(Register base, int disp, int imm, unsigned char *&insn) {
1664   *insn++ = 0xC7;
1665   emitAddressingMode(base, disp, 0, insn);
1666   *((int*)insn) = imm;
1667   insn += sizeof(int);
1668 }
1669
1670 // emit MOV mem32, imm32
1671 void emitMovImmToMem(Address maddr, int imm, unsigned char *&insn) {
1672   *insn++ = 0xC7;
1673   // emit the ModRM byte: we use a 32-bit displacement for the address,
1674   // the ModRM value is 0x05
1675   *insn++ = 0x05;
1676   *((unsigned *)insn) = maddr;
1677   insn += sizeof(unsigned);
1678   *((int*)insn) = imm;
1679   insn += sizeof(int);
1680 }
1681
1682
1683 // emit Add dword ptr DS:[addr], imm
1684 void emitAddMemImm32(Address addr, int imm, unsigned char *&insn) {
1685   *insn++ = 0x81;
1686   *insn++ = 0x05;
1687   *((unsigned *)insn) = addr;
1688   insn += sizeof(unsigned);
1689   *((int *)insn) = imm;
1690   insn += sizeof(int);
1691 }
1692
1693 // emit Add reg, imm32
1694 void emitAddRegImm32(Register reg, int imm, unsigned char *&insn) {
1695   *insn++ = 0x81;
1696   *insn++ = makeModRMbyte(3, 0, reg);
1697   *((int *)insn) = imm;
1698   insn += sizeof(int);
1699 }
1700
1701 // emit JUMP rel32
1702 void emitJump(unsigned disp32, unsigned char *&insn) {
1703   if ((signed)disp32 >= 0)
1704     assert (disp32 < unsigned(1<<31));
1705   else
1706     assert ((unsigned)(-(signed)disp32) < unsigned(1<<31));
1707   *insn++ = 0xE9;
1708   *((int *)insn) = disp32;
1709   insn += sizeof(int);
1710
1711
1712 // emit CALL rel32
1713 void emitCallRel32(unsigned disp32, unsigned char *&insn) {
1714   *insn++ = 0xE8;
1715   *((int *)insn) = disp32;
1716   insn += sizeof(int);
1717 }
1718
1719 // set dest=1 if src1 op src2, otherwise dest = 0
1720 void emitRelOp(unsigned op, Register dest, Register src1, Register src2,
1721                unsigned char *&insn) {
1722   //fprintf(stderr,"Relop dest = %d, src1 = %d, src2 = %d\n", dest, src1, src2);
1723   emitOpRegReg(0x29, ECX, ECX, insn);           // clear ECX
1724   emitMovRMToReg(EAX, EBP, -(src1*4), insn);    // mov eax, -(src1*4)[ebp]
1725   emitOpRegRM(0x3B, EAX, EBP, -(src2*4), insn); // cmp eax, -(src2*4)[ebp]
1726   unsigned char opcode;
1727   switch (op) {
1728     case eqOp: opcode = JNE_R8; break;
1729     case neOp: opcode = JE_R8; break;
1730     case lessOp: opcode = JGE_R8; break;
1731     case leOp: opcode = JG_R8; break;
1732     case greaterOp: opcode = JLE_R8; break;
1733     case geOp: opcode = JL_R8; break;
1734     default: assert(0);
1735   }
1736   *insn++ = opcode; *insn++ = 1;                // jcc 1
1737   emitSimpleInsn(0x40+ECX, insn);               // inc ECX
1738   emitMovRegToRM(EBP, -(dest*4), ECX, insn);    // mov -(dest*4)[ebp], ecx
1739
1740 }
1741
1742 // set dest=1 if src1 op src2imm, otherwise dest = 0
1743 void emitRelOpImm(unsigned op, Register dest, Register src1, int src2imm,
1744                   unsigned char *&insn) {
1745   //fprintf(stderr,"Relop dest = %d, src1 = %d, src2 = %d\n", dest, src1, src2);
1746   emitOpRegReg(0x29, ECX, ECX, insn);           // clear ECX
1747   emitMovRMToReg(EAX, EBP, -(src1*4), insn);    // mov eax, -(src1*4)[ebp]
1748   emitOpRegImm(0x3D, EAX, src2imm, insn);       // cmp eax, src2
1749   unsigned char opcode;
1750   switch (op) {
1751     case eqOp: opcode = JNE_R8; break;
1752     case neOp: opcode = JE_R8; break;
1753     case lessOp: opcode = JGE_R8; break;
1754     case leOp: opcode = JG_R8; break;
1755     case greaterOp: opcode = JLE_R8; break;
1756     case geOp: opcode = JL_R8; break;
1757     default: assert(0);
1758   }
1759   *insn++ = opcode; *insn++ = 1;                // jcc 1
1760   emitSimpleInsn(0x40+ECX, insn);               // inc ECX
1761   emitMovRegToRM(EBP, -(dest*4), ECX, insn);    // mov -(dest*4)[ebp], ecx
1762
1763 }
1764
1765 void emitEnter(short imm16, unsigned char *&insn) {
1766   *insn++ = 0xC8;
1767   *((short*)insn) = imm16;
1768   insn += sizeof(short);
1769   *insn++ = 0;
1770 }
1771
1772
1773
1774 Register emitFuncCall(opCode op, 
1775                       registerSpace *rs,
1776                       char *ibuf, Address &base,
1777                       const vector<AstNode *> &operands, 
1778                       const string &callee, process *proc,
1779                       bool noCost, const function_base *calleefunc)
1780 {
1781   assert(op == callOp);
1782   Address addr;
1783   bool err;
1784   vector <Register> srcs;
1785
1786   if (calleefunc)
1787        addr = calleefunc->getEffectiveAddress(proc);
1788   else {
1789        addr = proc->findInternalAddress(callee, false, err);
1790        if (err) {
1791             function_base *func = proc->findOneFunction(callee);
1792             if (!func) {
1793                  ostrstream os(errorLine, 1024, ios::out);
1794                  os << "Internal error: unable to find addr of " << callee << endl;
1795                  logLine(errorLine);
1796                  showErrorCallback(80, (const char *) errorLine);
1797                  P_abort();
1798             }
1799             addr = func->getAddress(0);
1800        }
1801   }
1802   for (unsigned u = 0; u < operands.size(); u++)
1803     srcs += (Register)operands[u]->generateCode(proc, rs, ibuf, base, noCost, false);
1804
1805   unsigned char *insn = (unsigned char *) ((void*)&ibuf[base]);
1806   unsigned char *first = insn;
1807
1808   // push arguments in reverse order, last argument first
1809   // must use int instead of unsigned to avoid nasty underflow problem:
1810   for (int i=srcs.size() - 1 ; i >= 0; i--) {
1811      emitOpRMReg(PUSH_RM_OPC1, EBP, -(srcs[i]*4), PUSH_RM_OPC2, insn);
1812      rs->freeRegister(srcs[i]);
1813   }
1814
1815   // make the call
1816   // we are using an indirect call here because we don't know the
1817   // address of this instruction, so we can't use a relative call.
1818   // TODO: change this to use a direct call
1819   emitMovImmToReg(EAX, addr, insn);       // mov eax, addr
1820   emitOpRegReg(CALL_RM_OPC1, CALL_RM_OPC2, EAX, insn);   // call *(eax)
1821
1822   // reset the stack pointer
1823   if (srcs.size() > 0)
1824      emitOpRegImm(0, ESP, srcs.size()*4, insn); // add esp, srcs.size()*4
1825
1826   // allocate a (virtual) register to store the return value
1827   Register ret = rs->allocateRegister((char *)insn, base, noCost);
1828   emitMovRegToRM(EBP, -(ret*4), EAX, insn);
1829
1830   base += insn - first;
1831   return ret;
1832 }
1833
1834
1835
1836 /*
1837  * emit code for op(src1,src2, dest)
1838  * ibuf is an instruction buffer where instructions are generated
1839  * base is the next free position on ibuf where code is to be generated
1840  */
1841
1842 Address emitA(opCode op, Register src1, Register /*src2*/, Register dest,
1843              char *ibuf, Address &base, bool /*noCost*/)
1844 {
1845     //fprintf(stderr,"emitA(op=%d,src1=%d,src2=XX,dest=%d)\n",op,src1,dest);
1846
1847     unsigned char *insn = (unsigned char *) (&ibuf[base]);
1848     unsigned char *first = insn;
1849
1850     switch (op) {
1851     case ifOp: {
1852       // if src1 == 0 jump to dest
1853       // src1 is a temporary
1854       // dest is a target address
1855       emitOpRegReg(0x29, EAX, EAX, insn);           // sub EAX, EAX ; clear EAX
1856       emitOpRegRM(0x3B, EAX, EBP, -(src1*4), insn); // cmp -(src1*4)[EBP], EAX
1857       // je dest
1858       *insn++ = 0x0F;
1859       *insn++ = 0x84;
1860       *((int *)insn) = dest;
1861       insn += sizeof(int);
1862       base += insn-first;
1863       return base;
1864       }
1865     case branchOp: { 
1866         emitJump(dest - JUMP_REL32_SZ, insn); 
1867         base += JUMP_REL32_SZ;
1868         return(base - JUMP_REL32_SZ);
1869       }
1870     case trampTrailer: {
1871       // generate the template for a jump -- actual jump is generated elsewhere
1872       emitJump(0, insn); // jump xxxx
1873       // return the offset of the previous jump
1874       base += insn - first;
1875       return(base - JUMP_REL32_SZ);
1876       }
1877     case trampPreamble: {
1878         base += insn - first;
1879         return(0);      // let's hope this is expected!
1880       }
1881     default:
1882         abort();        // unexpected op for this emit!
1883     }
1884   return(0);            // should never reach here!
1885 }
1886
1887 Register emitR(opCode op, Register src1, Register /*src2*/, Register dest,
1888              char *ibuf, Address &base, bool /*noCost*/)
1889 {
1890     //fprintf(stderr,"emitR(op=%d,src1=%d,src2=XX,dest=%d)\n",op,src1,dest);
1891
1892     unsigned char *insn = (unsigned char *) (&ibuf[base]);
1893     unsigned char *first = insn;
1894
1895     switch (op) {
1896     case getRetValOp: {
1897       // dest is a register where we can store the value
1898       // the return value is in the saved EAX
1899       emitMovRMToReg(EAX, EBP, SAVED_EAX_OFFSET, insn);
1900       emitMovRegToRM(EBP, -(dest*4), EAX, insn);
1901       base += insn - first;
1902       return dest;
1903       }
1904     case getParamOp: {
1905       // src1 is the number of the argument
1906       // dest is a register where we can store the value
1907       // Parameters are addressed by a positive offset from ebp,
1908       // the first is PARAM_OFFSET[ebp]
1909       emitMovRMToReg(EAX, EBP, PARAM_OFFSET + src1*4, insn);
1910       emitMovRegToRM(EBP, -(dest*4), EAX, insn);
1911       base += insn - first;
1912       return dest;
1913       }
1914     default:
1915       abort();                  // unexpected op for this emit!
1916     }
1917   return(Null_Register);        // should never be reached!
1918 }
1919
1920 void emitVload(opCode op, Address src1, Register /*src2*/, Register dest, 
1921              char *ibuf, Address &base, bool /*noCost*/, int /* size */)
1922 {
1923     unsigned char *insn = (unsigned char *) (&ibuf[base]);
1924     unsigned char *first = insn;
1925
1926     if (op == loadConstOp) {
1927       // dest is a temporary
1928       // src1 is an immediate value 
1929       // dest = src1:imm32
1930       emitMovImmToRM(EBP, -(dest*4), src1, insn);
1931       base += insn - first;
1932       return;
1933     } else if (op ==  loadOp) {
1934       // dest is a temporary
1935       // src1 is the address of the operand
1936       // dest = [src1]
1937       emitMovMToReg(EAX, src1, insn);               // mov eax, src1
1938       emitMovRegToRM(EBP, -(dest*4), EAX, insn);    // mov -(dest*4)[ebp], eax
1939       base += insn - first;
1940       return;
1941     } else if (op == loadFrameRelativeOp) {
1942       // dest is a temporary
1943       // src1 is the offset of the from the frame of the variable
1944       // eax = [eax]    - saved sp
1945       // dest = [eax](src1)
1946       emitMovRMToReg(EAX, EBP, 0, insn);       // mov (%ebp), %eax 
1947       emitMovRMToReg(EAX, EAX, src1, insn);    // mov <offset>(%eax), %eax 
1948       emitMovRegToRM(EBP, -(dest*4), EAX, insn);    // mov -(dest*4)[ebp], eax
1949       base += insn - first;
1950       return;
1951     } else if (op == loadFrameAddr) {
1952       emitMovRMToReg(EAX, EBP, 0, insn);       // mov (%ebp), %eax 
1953       emitAddRegImm32(EAX, src1, insn);        // add #<offset>, %eax
1954       emitMovRegToRM(EBP, -(dest*4), EAX, insn);    // mov -(dest*4)[ebp], eax
1955       base += insn - first;
1956       return;
1957     } else {
1958         abort();                // unexpected op for this emit!
1959     }
1960 }
1961
1962 void emitVstore(opCode op, Register src1, Register src2, Address dest,
1963              char *ibuf, Address &base, bool /*noCost*/, int /* size */)
1964 {
1965     unsigned char *insn = (unsigned char *) (&ibuf[base]);
1966     unsigned char *first = insn;
1967
1968     if (op ==  storeOp) {
1969       // [dest] = src1
1970       // dest has the address where src1 is to be stored
1971       // src1 is a temporary
1972       // src2 is a "scratch" register, we don't need it in this architecture
1973       emitMovRMToReg(EAX, EBP, -(src1*4), insn);    // mov eax, -(src1*4)[ebp]
1974       emitMovRegToM(dest, EAX, insn);               // mov dest, eax
1975       base += insn - first;
1976       return;
1977     } else if (op == storeFrameRelativeOp) {
1978       // src1 is a temporary
1979       // src2 is a "scratch" register, we don't need it in this architecture
1980       // dest is the frame offset 
1981       //
1982       // src2 = [ebp]   - saved sp
1983       // (dest)[src2] = src1
1984       emitMovRMToReg(src2, EBP, 0, insn);           // mov src2, (ebp)
1985       emitMovRMToReg(EAX, EBP, -(src1*4), insn);    // mov eax, -(src1*4)[ebp]
1986       emitMovRegToRM(src2, dest, EAX, insn);        // mov (dest)[src2], eax
1987       base += insn - first;
1988       return;
1989     } else {
1990         abort();                // unexpected op for this emit!
1991     }
1992 }
1993
1994 void emitVupdate(opCode op, RegValue src1, Register /*src2*/, Address dest, 
1995              char *ibuf, Address &base, bool noCost)
1996 {
1997     unsigned char *insn = (unsigned char *) (&ibuf[base]);
1998     unsigned char *first = insn;
1999
2000     if (op == updateCostOp) {
2001       // src1 is the cost value
2002       // src2 is not used
2003       // dest is the address of observed cost
2004
2005       if (!noCost) {
2006          // update observed cost
2007          // dest = address of DYNINSTobsCostLow
2008          // src1 = cost
2009          emitAddMemImm32(dest, src1, insn);  // ADD (dest), src1
2010       }
2011       base += insn-first;
2012       return;           //return base;    // never seem to ever need this
2013     } else {
2014         abort();                // unexpected op for this emit!
2015     }
2016 }
2017
2018 void emitV(opCode op, Register src1, Register src2, Register dest, 
2019              char *ibuf, Address &base, bool /*noCost*/, int /* size */)
2020 {
2021     //fprintf(stderr,"emitV(op=%d,src1=%d,src2=%d,dest=%d)\n",op,src1,src2,dest);
2022
2023     assert ((op!=branchOp) && (op!=ifOp) &&
2024             (op!=trampTrailer) && (op!=trampPreamble));         // !emitA
2025     assert ((op!=getRetValOp) && (op!=getParamOp));             // !emitR
2026     assert ((op!=loadOp) && (op!=loadConstOp));                 // !emitVload
2027     assert ((op!=storeOp));                                     // !emitVstore
2028     assert ((op!=updateCostOp));                                // !emitVupdate
2029
2030     unsigned char *insn = (unsigned char *) (&ibuf[base]);
2031     unsigned char *first = insn;
2032
2033     if (op ==  loadIndirOp) {
2034       // same as loadOp, but the value to load is already in a register
2035       emitMovRMToReg(EAX, EBP, -(src1*4), insn); // mov eax, -(src1*4)[ebp]
2036       emitMovRMToReg(EAX, EAX, 0, insn);         // mov eax, [eax]
2037       emitMovRegToRM(EBP, -(dest*4), EAX, insn); // mov -(dest*4)[ebp], eax
2038
2039     } 
2040     else if (op ==  storeIndirOp) {
2041       // same as storeOp, but the address where to store is already in a
2042       // register
2043       emitMovRMToReg(EAX, EBP, -(src1*4), insn);   // mov eax, -(src1*4)[ebp]
2044       emitMovRMToReg(ECX, EBP, -(dest*4), insn);   // mov ecx, -(dest*4)[ebp]
2045       emitMovRegToRM(ECX, 0, EAX, insn);           // mov [ecx], eax
2046
2047     } else if (op == noOp) {
2048        emitSimpleInsn(NOP, insn); // nop
2049
2050     } else if (op == saveRegOp) {
2051       // should not be used on this platform
2052       assert(0);
2053
2054     } else {
2055         unsigned opcode;
2056         switch (op) {
2057             // integer ops
2058             case plusOp:
2059                 // dest = src1 + src2
2060                 // mv eax, src1
2061                 // add eax, src2
2062                 // mov dest, eax
2063                 opcode = 0x03; // ADD
2064                 break;
2065
2066             case minusOp:
2067                 opcode = 0x2B; // SUB
2068                 break;
2069
2070             case timesOp:
2071                 opcode = 0x0FAF; // IMUL
2072                 break;
2073
2074             case divOp:
2075                 // dest = src1 div src2
2076                 // mov eax, src1
2077                 // cdq   ; edx = sign extend of eax
2078                 // idiv eax, src2 ; eax = edx:eax div src2, edx = edx:eax mod src2
2079                 // mov dest, eax
2080                 emitMovRMToReg(EAX, EBP, -(src1*4), insn);
2081                 emitSimpleInsn(0x99, insn);
2082                 emitOpRegRM(0xF7, 0x7 /*opcode extension*/, EBP, -(src2*4), insn);
2083                 emitMovRegToRM(EBP, -(dest*4), EAX, insn);
2084                 base += insn-first;
2085                 return;
2086                 break;
2087
2088             // Bool ops
2089             case orOp:
2090                 opcode = 0x0B; // OR 
2091                 break;
2092
2093             case andOp:
2094                 opcode = 0x23; // AND
2095                 break;
2096
2097             // rel ops
2098             // dest = src1 relop src2
2099             case eqOp:
2100             case neOp:
2101             case lessOp:
2102             case leOp:
2103             case greaterOp:
2104             case geOp:
2105                 emitRelOp(op, dest, src1, src2, insn);
2106                 base += insn-first;
2107                 return;
2108                 break;
2109
2110             default:
2111                 abort();
2112                 break;
2113         }
2114
2115         emitMovRMToReg(EAX, EBP, -(src1*4), insn);
2116         emitOpRegRM(opcode, EAX, EBP, -(src2*4), insn);
2117         emitMovRegToRM(EBP, -(dest*4), EAX, insn);
2118       }
2119     base += insn - first;
2120     return;
2121 }
2122
2123
2124 void emitImm(opCode op, Register src1, RegValue src2imm, Register dest, 
2125              char *ibuf, Address &base, bool)
2126 {
2127     unsigned char *insn = (unsigned char *) (&ibuf[base]);
2128     unsigned char *first = insn;
2129
2130     if (op ==  storeOp) {
2131       // [dest] = src1
2132       // dest has the address where src1 is to be stored
2133       // src1 is an immediate value
2134       // src2 is a "scratch" register, we don't need it in this architecture
2135       emitMovImmToReg(EAX, dest, insn);
2136       emitMovImmToRM(EAX, 0, src1, insn);
2137     } else {
2138         unsigned opcode1;
2139         unsigned opcode2;
2140         switch (op) {
2141             // integer ops
2142             case plusOp:
2143                 opcode1 = 0x81;
2144                 opcode2 = 0x0; // ADD
2145                 break;
2146
2147             case minusOp:
2148                 opcode1 = 0x81;
2149                 opcode2 = 0x5; // SUB
2150                 break;
2151
2152             case timesOp: {
2153                 int result=-1;
2154                 if (isPowerOf2(src2imm, result) && result <= MAX_IMM8) {
2155                   if (src1 != dest) {
2156                     emitMovRMToReg(EAX, EBP, -(src1*4), insn);
2157                     emitMovRegToRM(EBP, -(dest*4), EAX, insn);
2158                   }
2159                   // sal dest, result
2160                   emitOpRMImm8(0xC1, 4, EBP, -(dest*4), result, insn);
2161                 }
2162                 else {
2163                   // imul EAX, -(src1*4)[ebp], src2imm
2164                   emitOpRegRMImm(0x69, EAX, EBP, -(src1*4), src2imm, insn);
2165                   emitMovRegToRM(EBP, -(dest*4), EAX, insn);
2166                 } 
2167                 base += insn-first;
2168                 return;
2169               }
2170                 break;
2171
2172             case divOp: {
2173                 int result=-1;
2174                 if (isPowerOf2(src2imm, result) && result <= MAX_IMM8) {
2175                   if (src1 != dest) {
2176                     emitMovRMToReg(EAX, EBP, -(src1*4), insn);
2177                     emitMovRegToRM(EBP, -(dest*4), EAX, insn);
2178                   }
2179                   // sar dest, result
2180                   emitOpRMImm8(0xC1, 7, EBP, -(dest*4), result, insn);
2181                 }
2182                 else {
2183                   // dest = src1 div src2imm
2184                   // mov eax, src1
2185                   // cdq   ; edx = sign extend of eax
2186                   // mov ebx, src2imm
2187                   // idiv eax, ebx ; eax = edx:eax div src2, edx = edx:eax mod src2
2188                   // mov dest, eax
2189                   emitMovRMToReg(EAX, EBP, -(src1*4), insn);
2190                   emitSimpleInsn(0x99, insn);
2191                   emitMovImmToReg(EBX, src2imm, insn);
2192                   // idiv eax, ebx
2193                   emitOpRegReg(0xF7, 0x7 /*opcode extension*/, EBX, insn); 
2194                   emitMovRegToRM(EBP, -(dest*4), EAX, insn);
2195                 }
2196               }
2197                 base += insn-first;
2198                 return;
2199                 break;
2200
2201             // Bool ops
2202             case orOp:
2203                 opcode1 = 0x81;
2204                 opcode2 = 0x1; // OR 
2205                 break;
2206
2207             case andOp:
2208                 opcode1 = 0x81;
2209                 opcode2 = 0x4; // AND
2210                 break;
2211
2212             // rel ops
2213             // dest = src1 relop src2
2214             case eqOp:
2215             case neOp:
2216             case lessOp:
2217             case leOp:
2218             case greaterOp:
2219             case geOp:
2220                 emitRelOpImm(op, dest, src1, src2imm, insn);
2221                 base += insn-first;
2222                 return;
2223                 break;
2224
2225             default:
2226                 abort();
2227                 break;
2228         }
2229         if (src1 != dest) {
2230           emitMovRMToReg(EAX, EBP, -(src1*4), insn);
2231           emitMovRegToRM(EBP, -(dest*4), EAX, insn);
2232         }
2233         emitOpRMImm(opcode1, opcode2, EBP, -(dest*4), src2imm, insn);
2234       }
2235     base += insn - first;
2236     return;
2237 }
2238
2239
2240
2241 int getInsnCost(opCode op)
2242 {
2243     if (op == loadConstOp) {
2244         return(1);
2245     } else if (op ==  loadOp) {
2246         return(1+1);
2247     } else if (op ==  loadIndirOp) {
2248         return(3);
2249     } else if (op ==  storeOp) {
2250         return(1+1); 
2251     } else if (op ==  storeIndirOp) {
2252         return(3);
2253     } else if (op ==  ifOp) {
2254         return(1+2+1);
2255     } else if (op ==  whileOp) {
2256         return(1+2+1+1); /* Need to find out about this */
2257     } else if (op == branchOp) {
2258         return(1);      /* XXX Need to find out what value this should be. */
2259     } else if (op ==  callOp) {
2260         // cost of call only
2261         return(1+2+1+1);
2262     } else if (op == updateCostOp) {
2263         return(3);
2264     } else if (op ==  trampPreamble) {
2265         return(0);
2266     } else if (op ==  trampTrailer) {
2267         return(1);
2268     } else if (op == noOp) {
2269         return(1);
2270     } else if (op == getRetValOp) {
2271         return (1+1);
2272     } else if (op == getParamOp) {
2273         return(1+1);
2274     } else {
2275         switch (op) {
2276             // rel ops
2277             case eqOp:
2278             case neOp:
2279             case lessOp:
2280             case leOp:
2281             case greaterOp:
2282             case geOp:
2283                 return(1+1+2+1+1+1);
2284                 break;
2285             case divOp:
2286                 return(1+2+46+1);
2287             case timesOp:
2288                 return(1+10+1);
2289             case plusOp:
2290             case minusOp:
2291             case orOp:
2292             case andOp:
2293                 return(1+2+1);
2294             case getAddrOp:
2295                 return(0);      // doesn't add anything to operand
2296             default:
2297                 assert(0);
2298                 return 0;
2299                 break;
2300         }
2301     }
2302 }
2303
2304
2305
2306 bool process::heapIsOk(const vector<sym_data> &find_us) {
2307   Symbol sym;
2308   string str;
2309   Address baseAddr;
2310
2311   // find the main function
2312   // first look for main or _main
2313 #if !defined(i386_unknown_nt4_0)
2314   if (!((mainFunction = findOneFunction("main")) 
2315         || (mainFunction = findOneFunction("_main")))) {
2316      string msg = "Cannot find main. Exiting.";
2317      statusLine(msg.string_of());
2318      showErrorCallback(50, msg);
2319      return false;
2320   }
2321 #else
2322   if (!((mainFunction = findOneFunction("main")) 
2323         || (mainFunction = findOneFunction("_main"))
2324         || (mainFunction = findOneFunction("WinMain"))
2325         || (mainFunction = findOneFunction("_WinMain")))) {
2326      string msg = "Cannot find main or WinMain. Exiting.";
2327      statusLine(msg.string_of());
2328      showErrorCallback(50, msg);
2329      return false;
2330   }
2331 #endif
2332
2333   for (unsigned i=0; i<find_us.size(); i++) {
2334     str = find_us[i].name;
2335     if (!getSymbolInfo(str, sym, baseAddr)) {
2336       string str1 = string("_") + str.string_of();
2337       if (!getSymbolInfo(str1, sym, baseAddr) && find_us[i].must_find) {
2338         string msg;
2339         msg = string("Cannot find ") + str + string(". Exiting");
2340         statusLine(msg.string_of());
2341         showErrorCallback(50, msg);
2342         return false;
2343       }
2344     }
2345   }
2346
2347 //  string ghb = GLOBAL_HEAP_BASE;
2348 //  if (!getSymbolInfo(ghb, sym, baseAddr)) {
2349 //    ghb = U_GLOBAL_HEAP_BASE;
2350 //    if (!getSymbolInfo(ghb, symm baseAddr)) {
2351 //      string msg;
2352 //      msg = string("Cannot find ") + str + string(". Exiting");
2353 //      statusLine(msg.string_of());
2354 //      showErrorCallback(50, msg);
2355 //      return false;
2356 //    }
2357 //  }
2358 //  Address instHeapEnd = sym.addr()+baseAddr;
2359 //  addInternalSymbol(ghb, instHeapEnd);
2360
2361   string ghb = INFERIOR_HEAP_BASE;
2362   if (!getSymbolInfo(ghb, sym, baseAddr)) {
2363     ghb = UINFERIOR_HEAP_BASE;
2364     if (!getSymbolInfo(ghb, sym, baseAddr)) {
2365       string msg;
2366       msg = string("Cannot find ") + ghb + string(". Cannot use this application");
2367       statusLine(msg.string_of());
2368       showErrorCallback(50, msg);
2369       return false;
2370     }
2371   }
2372 #if !defined(USES_LIBDYNINSTRT_SO) || defined(i386_unknown_nt4_0)
2373   Address currAddr = sym.addr()+baseAddr;
2374 #endif
2375
2376 #if !defined(i386_unknown_nt4_0)
2377   string tt = "DYNINSTtrampTable";
2378   if (!getSymbolInfo(tt, sym, baseAddr)) {
2379       string msg;
2380       msg = string("Cannot find ") + tt + string(". Cannot use this application");
2381       statusLine(msg.string_of());
2382       showErrorCallback(50, msg);
2383       return false;
2384   }
2385 #endif
2386
2387 #if !defined(USES_LIBDYNINSTRT_SO) || defined(i386_unknown_nt4_0)
2388   // Check that we can patch up user code to jump to our base trampolines:
2389   const Address instHeapStart = currAddr;
2390   const Address instHeapEnd = instHeapStart + SYN_INST_BUF_SIZE - 1;
2391
2392   if (instHeapEnd > getMaxBranch()) {
2393     logLine("*** FATAL ERROR: Program text + data too big for dyninst\n");
2394     sprintf(errorLine, "    heap starts at 0x%lx and ends at 0x%lx\n",
2395             instHeapStart, instHeapEnd);
2396     logLine(errorLine);
2397     return false;
2398   }
2399 #endif
2400   return true;
2401 }
2402
2403
2404
2405 dictionary_hash<string, unsigned> funcFrequencyTable(string::hash);
2406
2407 //
2408 // initDefaultPointFrequencyTable - define the expected call frequency of
2409 //    procedures.  Currently we just define several one shots with a
2410 //    frequency of one, and provide a hook to read a file with more accurate
2411 //    information.
2412 //
2413 void initDefaultPointFrequencyTable()
2414 {
2415     FILE *fp;
2416     float value;
2417     char name[512];
2418
2419     funcFrequencyTable["main"] = 1;
2420     funcFrequencyTable["DYNINSTsampleValues"] = 1;
2421     funcFrequencyTable[EXIT_NAME] = 1;
2422
2423     // try to read file.
2424     fp = fopen("freq.input", "r");
2425     if (!fp) {
2426         return;
2427     } else {
2428         printf("found freq.input file\n");
2429     }
2430     while (!feof(fp)) {
2431         fscanf(fp, "%s %f\n", name, &value);
2432         funcFrequencyTable[name] = (int) value;
2433         printf("adding %s %f\n", name, value);
2434     }
2435     fclose(fp);
2436 }
2437
2438 /*
2439  * Get an estimate of the frequency for the passed instPoint.  
2440  *    This is not (always) the same as the function that contains the point.
2441  * 
2442  *  The function is selected as follows:
2443  *
2444  *  If the point is an entry or an exit return the function name.
2445  *  If the point is a call and the callee can be determined, return the called
2446  *     function.
2447  *  else return the funcation containing the point.
2448  *
2449  *  WARNING: This code contains arbitrary values for func frequency (both user 
2450  *     and system).  This should be refined over time.
2451  *
2452  * Using 1000 calls sec to be one SD from the mean for most FPSPEC apps.
2453  *      -- jkh 6/24/94
2454  *
2455  */
2456 float getPointFrequency(instPoint *point)
2457 {
2458
2459     pd_Function *func = point->callee();
2460
2461     if (!func)
2462       func = point->func();
2463
2464     if (!funcFrequencyTable.defines(func->prettyName())) {
2465       // Changing this value from 250 to 100 because predictedCost was
2466       // too high - naim 07/18/96
2467       return(100.0);       
2468     } else {
2469       return ((float)funcFrequencyTable[func->prettyName()]);
2470     }
2471 }
2472
2473 //
2474 // return cost in cycles of executing at this point.  This is the cost
2475 //   of the base tramp if it is the first at this point or 0 otherwise.
2476 //
2477 int getPointCost(process *proc, const instPoint *point)
2478 {
2479     const_cast<instPoint*>(point)->checkInstructions();
2480
2481     if (proc->baseMap.defines(point)) {
2482         return(0);
2483     } else {
2484         if (point->size() == 1)
2485           return 9000; // estimated number of cycles for traps
2486         else
2487           return(83);
2488     }
2489 }
2490
2491
2492
2493 bool returnInstance::checkReturnInstance(const vector<Address> &stack, u_int &index) {
2494         return true;
2495
2496     // If false (unsafe) is returned, then 'index' is set to the first unsafe call stack
2497     // index.
2498     for (u_int i=0; i < stack.size(); i++) {
2499         index = i;
2500
2501         if (stack[i] >= addr_ && stack[i] < addr_+size_)
2502             return false;
2503     }
2504
2505     return true;
2506 }
2507  
2508 void returnInstance::installReturnInstance(process *proc) {
2509     assert(instructionSeq);
2510     proc->writeTextSpace((void *)addr_, instSeqSize, instructionSeq->ptr());
2511     delete instructionSeq;
2512     instructionSeq = 0;
2513         installed = true;
2514 }
2515
2516 void returnInstance::addToReturnWaitingList(Address , process *) {
2517     //P_abort();
2518         assert(0);
2519 }
2520
2521 void generateBreakPoint(instruction &insn) {
2522   insn = instruction ((const unsigned char*)"\017\013", ILLEGAL, 2);
2523 }
2524
2525 void instWaitingList::cleanUp(process *, Address ) {
2526   P_abort();
2527 /*
2528   proc->writeTextSpace((caddr_t)pc, relocatedInstruction.size(),
2529             (caddr_t&)(relocatedInstruction.ptr()));
2530   proc->writeTextSpace((caddr_t)addr_, instSeqSize,
2531             (caddr_t)instructionSeq);
2532 */
2533 }
2534
2535 /* ***************************************************** */
2536
2537 bool process::emitInferiorRPCheader(void *void_insnPtr, Address &baseBytes) {
2538    unsigned char *insnPtr = (unsigned char *)void_insnPtr;
2539    unsigned char *origInsnPtr = insnPtr;
2540    insnPtr += baseBytes;
2541
2542    // We emit the following here (to set up a fresh stack frame):
2543    // pushl %ebp        (0x55)
2544    // movl  %esp, %ebp  (0x89 0xe5)
2545    // pushad
2546    // pushfd
2547
2548    emitSimpleInsn(PUSH_EBP, insnPtr);
2549    emitMovRegToReg(EBP, ESP, insnPtr);
2550    // allocate space for temporaries (virtual registers)
2551    emitOpRegImm(5, ESP, 128, insnPtr); // sub esp, 128
2552    emitSimpleInsn(PUSHAD, insnPtr);
2553    emitSimpleInsn(PUSHFD, insnPtr);
2554
2555    baseBytes += (insnPtr - origInsnPtr);
2556
2557    return true;
2558 }
2559
2560 bool process::emitInferiorRPCtrailer(void *void_insnPtr, Address &baseBytes,
2561                                      unsigned &breakOffset,
2562                                      bool shouldStopForResult,
2563                                      unsigned &stopForResultOffset,
2564                                      unsigned &justAfter_stopForResultOffset) {
2565    unsigned char *insnPtr = (unsigned char *)void_insnPtr;
2566       // unsigned char * is the most natural to work with on x86, since instructions
2567       // are always an integral # of bytes.  Besides, it makes the following line easy:
2568    insnPtr += baseBytes; // start off in the right spot
2569
2570    if (shouldStopForResult) {
2571       // illegal insn: 0x0f0b does the trick.
2572       stopForResultOffset = baseBytes;
2573       *insnPtr++ = 0x0f;
2574       *insnPtr++ = 0x0b;
2575       baseBytes += 2;
2576
2577       justAfter_stopForResultOffset = baseBytes;
2578    }
2579
2580    // Sequence: popfd, popad, leave (0xc9), call DYNINSTbreakPoint(), illegal
2581
2582    emitSimpleInsn(POPFD, insnPtr); // popfd
2583    emitSimpleInsn(POPAD, insnPtr); // popad
2584    emitSimpleInsn(LEAVE, insnPtr); // leave
2585    baseBytes += 3; // all simple insns are 1 byte
2586
2587    // We can't do a SIGTRAP since SIGTRAP is reserved in x86.
2588    // So we do a SIGILL instead.
2589    breakOffset = baseBytes;
2590    *insnPtr++ = 0x0f;
2591    *insnPtr++ = 0x0b;
2592    baseBytes += 2;
2593
2594    // Here, we should generate an illegal insn, or something.
2595    // A two-byte insn, 0x0f0b, should do the trick.  The idea is that
2596    // the code should never be executed.
2597    *insnPtr++ = 0x0f;
2598    *insnPtr++ = 0x0b;
2599    baseBytes += 2;
2600
2601    return true;
2602 }
2603
2604 // process::replaceFunctionCall
2605 //
2606 // Replace the function call at the given instrumentation point with a call to
2607 // a different function, or with a NOOP.  In order to replace the call with a
2608 // NOOP, pass NULL as the parameter "func."
2609 // Returns true if sucessful, false if not.  Fails if the site is not a call
2610 // site, or if the site has already been instrumented using a base tramp.
2611 //
2612 // Note that right now we can only replace a call instruction that is five
2613 // bytes long (like a call to a 32-bit relative address).
2614 bool process::replaceFunctionCall(const instPoint *point,
2615                                   const function_base *func) {
2616     // Must be a call site
2617     if (!point->insnAtPoint().isCall())
2618         return false;
2619
2620     // Cannot already be instrumented with a base tramp
2621     if (baseMap.defines(point))
2622         return false;
2623
2624     // Replace the call
2625     if (func == NULL) { // Replace with NOOPs
2626         unsigned char *newInsn = new unsigned char[point->insnAtPoint().size()];
2627         unsigned char *p = newInsn;
2628         for (unsigned i = 0; i < point->insnAtPoint().size(); i++)
2629             emitSimpleInsn(NOP, p);
2630         writeTextSpace((void *)point->iPgetAddress(),
2631                        point->insnAtPoint().size(), newInsn);
2632     } else { // Replace with a call to a different function
2633         // XXX Right only, call has to be 5 bytes -- sometime, we should make
2634         // it work for other calls as well.
2635         assert(point->insnAtPoint().size() == CALL_REL32_SZ);
2636         unsigned char *newInsn = new unsigned char[CALL_REL32_SZ];
2637         unsigned char *p = newInsn;
2638         emitCallRel32(func->addr() - (point->iPgetAddress()+CALL_REL32_SZ), p);
2639         writeTextSpace((void *)point->iPgetAddress(), CALL_REL32_SZ, newInsn);
2640     }
2641
2642     return true;
2643 }
2644
2645 // Emit code to jump to function CALLEE without linking.  (I.e., when
2646 // CALLEE returns, it returns to the current caller.)
2647 void emitFuncJump(opCode /*op*/, 
2648                   char * /*i*/, Address & /*base*/, 
2649                   const function_base * /*callee*/, process * /*proc*/)
2650 {
2651      /* Unimplemented on this platform! */
2652      assert(0);
2653 }
2654
2655 void emitLoadPreviousStackFrameRegister(Address, Register, char *, Address&,
2656                                         int, bool){
2657   assert(0);
2658 }
2659
2660
2661 #ifndef BPATCH_LIBRARY
2662 bool process::isDynamicCallSite(instPoint *callSite){
2663   function_base *temp;
2664   if(!findCallee(*(callSite),temp)){
2665     return true;
2666   }
2667   return false;
2668 }
2669
2670 bool process::MonitorCallSite(instPoint *callSite){
2671   return false;
2672 }
2673 #endif
2674
2675 #if (defined(i386_unknown_solaris2_5) || defined(i386_unknown_linux2_0))
2676 #include <sys/signal.h>
2677 //#include <sys/ucontext.h>
2678
2679 void
2680 BaseTrampTrapHandler (int)//, siginfo_t*, ucontext_t*)
2681 {
2682   cout << "In BaseTrampTrapHandler()" << endl;
2683   // unset trap handler, so that DYNINSTtrapHandler can take place
2684   if (sigaction(SIGTRAP, NULL, NULL) != 0) {
2685     perror("sigaction(SIGTRAP)");
2686     assert(0);
2687     abort();
2688   }
2689 }
2690
2691 #endif