Fix for #116
[dyninst.git] / dyninstAPI / src / codegen-x86.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 #include <assert.h>
32 #include <stdio.h>
33 #include "boost/assign/list_of.hpp"
34 #include "boost/assign/std/vector.hpp"
35 #include "boost/assign/std/set.hpp"
36 #include <map>
37 #include <string>
38 #include "common/src/Types.h"
39 #include "codegen.h"
40 #include "util.h"
41 #include "debug.h"
42 #include "addressSpace.h"
43
44 #include "InstructionDecoder.h"
45 #include "Instruction.h"
46
47 #include "emit-x86.h"
48 #include "inst-x86.h"
49 #include "instructionAPI/h/RegisterIDs.h"
50 #include "pcrel.h"
51
52 #include "StackMod/StackAccess.h"
53
54 #if defined(os_vxworks)
55 #include "common/src/wtxKludges.h"
56 #endif
57
58 using namespace std;
59 using namespace boost::assign;
60 using namespace Dyninst::InstructionAPI;
61
62
63 #define MODRM_MOD(x) ((x) >> 6)
64 #define MODRM_RM(x) ((x) & 7)
65 #define MODRM_REG(x) (((x) & (7 << 3)) >> 3)
66 #define MODRM_SET_MOD(x, y) (x) = static_cast<unsigned char>((x) | ((y) << 6))
67 #define MODRM_SET_RM(x, y) (x) = static_cast<unsigned char>((x) | (y))
68 #define MODRM_SET_REG(x, y) (x) = static_cast<unsigned char>((x) | ((y) << 3))
69
70 #define REX_ISREX(x) (((x) >> 4) == 4)
71 #define REX_W(x) ((x) & 0x8)
72 #define REX_R(x) ((x) & 0x4)
73 #define REX_X(x) ((x) & 0x2)
74 #define REX_B(x) ((x) & 0x1)
75
76 #define REX_INIT(x) ((x) = 0x40)
77 #define REX_SET_W(x, v) ((x) = static_cast<unsigned char>((x) | ((v) ? 0x8 : 0)))
78 #define REX_SET_R(x, v) ((x) = static_cast<unsigned char>((x) | ((v) ? 0x4 : 0)))
79 #define REX_SET_X(x, v) ((x) = static_cast<unsigned char>((x) | ((v) ? 0x2 : 0)))
80 #define REX_SET_B(x, v) ((x) = static_cast<unsigned char>((x) | ((v) ? 0x1 : 0)))
81 unsigned copy_prefixes(const unsigned char *&origInsn, unsigned char *&newInsn, unsigned insnType) {
82   unsigned nPrefixes = count_prefixes(insnType);
83
84   for (unsigned u = 0; u < nPrefixes; u++)
85      *newInsn++ = *origInsn++;
86   return nPrefixes;
87 }
88
89 //Copy all prefixes but the Operand-Size and Address-Size prefixes (0x66 and 0x67)
90 unsigned copy_prefixes_nosize(const unsigned char *&origInsn, unsigned char *&newInsn, 
91                               unsigned insnType) 
92 {
93     unsigned retval = 0;
94     unsigned nPrefixes = count_prefixes(insnType);
95
96     for (unsigned u = 0; u < nPrefixes; u++) {
97         if (*origInsn == 0x66 || *origInsn == 0x67)
98         {
99             origInsn++;
100             continue;
101         }
102         retval++;
103         *newInsn++ = *origInsn++;
104     }
105     return retval;
106 }
107
108 //Copy all prefixes but the Operand-Size and Address-Size prefixes (0x66 and 0x67)
109 // Returns the number of bytes copied
110 unsigned copy_prefixes_nosize_or_segments(const unsigned char *&origInsn, unsigned char *&newInsn, 
111                               unsigned insnType) 
112 {
113     unsigned retval = 0;
114   unsigned nPrefixes = count_prefixes(insnType);
115   if (0 == nPrefixes) {
116       return 0;
117   }
118
119   // duplicate prefixes are possible and are not identified by count_prefixes
120   unsigned nWithDups = 0; 
121   while(true) {
122      if ((*origInsn) >= 0x64 && (*origInsn) <= 0x67) {
123         origInsn++;
124      }
125      else {
126          if (nWithDups >= nPrefixes) {
127             break;
128          }
129          *newInsn++ = *origInsn++;
130          retval++;
131      }
132      nWithDups++;
133   }
134
135   return retval;
136 }
137
138 bool convert_to_rel8(const unsigned char*&origInsn, unsigned char *&newInsn) {
139   if (*origInsn == 0x0f)
140     origInsn++;
141
142   // We think that an opcode in the 0x8? range can be mapped to an equivalent
143   // opcode in the 0x7? range...
144
145   if ((*origInsn >= 0x70) &&
146       (*origInsn < 0x80)) {
147     *newInsn++ = *origInsn++;
148     return true;
149   }
150
151   if ((*origInsn >= 0x80) &&
152       (*origInsn < 0x90)) {
153      *newInsn++ = static_cast<unsigned char>(*origInsn++ - 0x10);
154      return true;
155   }
156
157   if (0xE0 <= *origInsn || *origInsn <= 0xE3) {
158     *newInsn++ = *origInsn++;
159     return true;
160   }
161
162   // Oops...
163   fprintf(stderr, "Unhandled jump conversion case: opcode is 0x%x\n", *origInsn);
164   assert(0 && "Unhandled jump conversion case!");
165   return false;
166 }
167
168 bool convert_to_rel32(const unsigned char*&origInsn, unsigned char *&newInsn) {
169   if (*origInsn == 0x0f)
170     origInsn++;
171   *newInsn++ = 0x0f;
172
173   // We think that an opcode in the 0x7? range can be mapped to an equivalent
174   // opcode in the 0x8? range...
175
176   if ((*origInsn >= 0x70) &&
177       (*origInsn < 0x80)) {
178     *newInsn++ = static_cast<unsigned char>(*origInsn++ + 0x10);
179     return true;
180   }
181
182   if ((*origInsn >= 0x80) &&
183       (*origInsn < 0x90)) {
184     *newInsn++ = *origInsn++;
185     return true;
186   }
187
188   // TODO handle loops
189
190   // Oops...
191   fprintf(stderr, "Unhandled jump conversion case: opcode is 0x%x\n", *origInsn);
192   assert(0 && "Unhandled jump conversion case!");
193   return false;
194 }
195
196
197 // We keep array-lets that represents various fixed insns.
198 // They are larger than necessary so static analyzers don't think
199 // they'll be read out of bounds.
200 static const unsigned char illegalRep[8] = {0x0f, 0x0b};
201 static const unsigned char trapRep[8] = {0xCC};
202
203
204 void insnCodeGen::generateIllegal(codeGen &gen) {
205     instruction insn;
206     insn.setInstruction(illegalRep);
207     generate(gen,insn);
208 }
209
210 void insnCodeGen::generateTrap(codeGen &gen) {
211     instruction insn;
212     insn.setInstruction(trapRep);
213     generate(gen,insn);
214 }
215
216 /*
217  * change the insn at addr to be a branch to newAddr.
218  *   Used to add multiple tramps to a point.
219  */
220
221 void insnCodeGen::generateBranch(codeGen &gen,
222                                  Address fromAddr, Address toAddr)
223 {
224   GET_PTR(insn, gen);
225   long disp;
226
227   disp = toAddr - (fromAddr + 2);
228   if (is_disp8(disp)) {
229      *insn++ = 0xEB;
230      *((signed char*) insn) = (signed char) disp;
231      insn += sizeof(signed char);
232      SET_PTR(insn, gen);
233      return;
234   }
235   /*  
236   disp = toAddr - (fromAddr + 4);
237   if (is_disp16(disp) && gen.addrSpace()->getAddressWidth() != 8) {
238      *insn++ = 0x66;
239      *insn++ = 0xE9;
240      *((signed short*) insn) = (signed short) disp;
241      insn += sizeof(signed short);
242      SET_PTR(insn, gen);
243      return;
244   }
245   */
246   disp = toAddr - fromAddr;
247   if (is_disp32(disp) || gen.addrSpace()->getAddressWidth() == 4) {
248      generateBranch(gen, disp);
249      return;
250   }
251   
252   if(gen.addrSpace()->getAddressWidth() == 8)
253   {
254       generateBranch64(gen, toAddr);
255   }
256   else
257   {
258       generateBranch32(gen, toAddr);
259   }
260   return;
261 }
262
263 void insnCodeGen::generateBranch(codeGen &gen,
264                                  int disp32)
265 {
266    // Branches have sizes...
267    if (disp32 >= 0)
268       assert ((unsigned)disp32 < unsigned(1<<31));
269    else
270       assert ((unsigned)(-disp32) < unsigned(1<<31));
271
272    GET_PTR(insn, gen);
273    *insn++ = 0xE9;
274
275    // 5 for a 5-byte branch.
276    *((int *)insn) = disp32 - 5;
277    insn += sizeof(int);
278   
279    SET_PTR(insn, gen);
280    return;
281 }
282
283
284 // Unified the 64-bit push between branch and call
285 void insnCodeGen::generatePush64(codeGen &gen, Address val)
286 {
287   GET_PTR(insn, gen);
288 #if 0
289   for (int i = 3; i >= 0; i--) {
290     unsigned short word = static_cast<unsigned short>((val >> (16 * i)) & 0xffff);
291     *insn++ = 0x66; // operand size override
292     *insn++ = 0x68; // push immediate (16-bits b/c of prefix)
293     *(unsigned short *)insn = word;
294     insn += 2;
295   }
296 #endif
297   // NOTE: The size of this generated instruction(+1 for the ret) is stored in CALL_ABS64_SZ
298   unsigned int high = static_cast<unsigned int>(val >> 32);
299   unsigned int low = static_cast<unsigned int>(val);
300
301   // push the low 4
302   *insn++ = 0x68; 
303   *(unsigned int*)insn = low;
304   insn += 4;
305
306   // move the high 4 to rsp+4
307   *insn++ = 0xC7;
308   *insn++ = 0x44;
309   *insn++ = 0x24;
310   *insn++ = 0x04;
311   *(unsigned int*)insn = high;
312   insn += 4;
313
314   SET_PTR(insn, gen);
315 }
316
317 void insnCodeGen::generateBranch64(codeGen &gen, Address to)
318 {
319     // "long jump" - generates sequence to jump to any 64-bit address
320     // pushes the value on the stack (using 4 16-bit pushes) the uses a 'RET'
321
322   generatePush64(gen, to);
323
324   GET_PTR(insn, gen);
325   *insn++ = 0xC3; // RET
326   SET_PTR(insn, gen);
327
328 }
329
330 void insnCodeGen::generateBranch32(codeGen &gen, Address to)
331 {
332    // "long jump" - generates sequence to jump to any 32-bit address
333    emitPushImm(to, gen);
334    
335    GET_PTR(insn, gen);
336    *insn++ = 0xC3; // RET
337    SET_PTR(insn, gen);
338 }
339
340 void insnCodeGen::generateCall(codeGen &gen,
341                                Address from,
342                                Address target)
343 {
344   //assert(target);
345   long disp = target - (from + CALL_REL32_SZ);
346   
347   if (is_disp32(disp)) {
348     GET_PTR(insn, gen);
349     *insn++ = 0xE8;
350     *((int *)insn) = (int) disp;
351     insn += sizeof(int);
352     SET_PTR(insn, gen);
353   }
354   else {
355     // Wheee....
356     // We use a technique similar to our 64-bit
357     // branch; push the return addr onto the stack (from),
358     // then push to, then return. 
359     
360     // This looks like
361     // A: push D
362     // B: push <...>
363     // C: return
364     // D:
365
366 #if defined(arch_x86_64)
367     // So we need to know where D is off of "from"
368     if(gen.addrSpace()->getAddressWidth() == 8)
369     {
370         generatePush64(gen, from+CALL_ABS64_SZ);
371         generateBranch64(gen, target);
372     }
373     else
374     {
375         emitPushImm(from+CALL_ABS32_SZ, gen);
376         generateBranch32( gen, target);
377     }
378 #else
379     emitPushImm(from+CALL_ABS32_SZ, gen);
380     generateBranch32( gen, target);
381 #endif
382   }
383 }
384
385 void insnCodeGen::generateNOOP(codeGen &gen, unsigned size) {
386     // Be more efficient here...
387     while (size) {
388         GET_PTR(insn, gen);
389         *insn++ = NOP;
390         SET_PTR(insn, gen);
391         size -= sizeof(unsigned char);
392     }
393 }
394
395 void insnCodeGen::generate(codeGen &gen,instruction & insn) {
396     assert(insn.ptr());
397     assert(insn.size());
398     memcpy(gen.cur_ptr(), insn.ptr(), insn.size());
399     gen.moveIndex(insn.size());
400 }
401
402 pcRelJump::pcRelJump(patchTarget *t, const instruction &i, bool copyPrefixes) :
403    pcRelRegion(i),
404    addr_targ(0x0),
405    targ(t),
406    copy_prefixes_(copyPrefixes)
407 {
408 }
409
410 pcRelJump::pcRelJump(Address target, const instruction &i, bool copyPrefixes) :
411    pcRelRegion(i),
412    addr_targ(target),
413    targ(NULL),
414    copy_prefixes_(copyPrefixes)
415 {
416 }
417
418 Address pcRelJump::get_target() 
419 {
420    if (targ)
421       return targ->get_address();
422    return addr_targ;
423 }
424
425 pcRelJump::~pcRelJump()
426 {
427 }
428
429 unsigned pcRelJump::apply(Address addr)
430 {
431    const unsigned char *origInsn = orig_instruc.ptr();
432    unsigned insnType = orig_instruc.type();
433    unsigned char *orig_loc;
434   
435    GET_PTR(newInsn, *gen);
436    orig_loc = newInsn;
437    if (copy_prefixes_) {
438        addr += copy_prefixes(origInsn, newInsn, insnType);
439        // Otherwise we will fail to account for them and
440        // generate a branch that is +(# prefix bytes)
441    }
442    SET_PTR(newInsn, *gen);
443     
444    insnCodeGen::generateBranch(*gen, addr, get_target());
445    REGET_PTR(newInsn, *gen);
446    return (unsigned) (newInsn - orig_loc);
447 }
448
449 unsigned pcRelJump::maxSize()
450 {
451    unsigned prefixes = count_prefixes(orig_instruc.type());
452 #if defined(arch_x86_64)
453    if (gen->addrSpace()->getAddressWidth() == 8)
454       return prefixes + JUMP_ABS64_SZ;
455 #endif
456    return prefixes + JUMP_SZ;
457 }
458
459 bool pcRelJump::canPreApply()
460 {
461    return gen->startAddr() && (!targ || get_target());
462 }
463
464
465 pcRelJCC::pcRelJCC(patchTarget *t, const instruction &i) :
466    pcRelRegion(i),
467    addr_targ(0x0),
468    targ(t)
469 {
470 }
471
472 pcRelJCC::pcRelJCC(Address target, const instruction &i) :
473    pcRelRegion(i),
474    addr_targ(target),
475    targ(NULL)
476 {
477 }
478
479 Address pcRelJCC::get_target() 
480 {
481    if (targ)
482       return targ->get_address();
483    return addr_targ;
484 }
485
486 pcRelJCC::~pcRelJCC()
487 {
488 }
489
490 unsigned pcRelJCC::apply(Address addr)
491 {
492    const unsigned char *origInsn = orig_instruc.ptr();
493    unsigned insnType = orig_instruc.type();
494    Address target = get_target();
495    Address potential;
496    signed long disp;
497    codeBufIndex_t start = gen->getIndex();
498    GET_PTR(newInsn, *gen);
499
500    addr += copy_prefixes_nosize_or_segments(origInsn, newInsn, insnType); 
501    
502
503    //8-bit jump
504    potential = addr + 2;
505    disp = target - potential;
506    if (is_disp8(disp)) {
507       convert_to_rel8(origInsn, newInsn);
508       *newInsn++ = (signed char) disp;
509       SET_PTR(newInsn, *gen);
510       return (unsigned) gen->getIndex() - start;
511    }
512
513    //Can't convert short E0-E3 loops/jumps to 32-bit equivalents
514    if (*origInsn < 0xE0 || *origInsn > 0xE3) {
515      /*
516       //16-bit jump
517       potential = addr + 5;
518       disp = target - potential;
519       if (is_disp16(disp) && gen->addrSpace()->getAddressWidth() != 8) {
520          *newInsn++ = 0x66; //Prefix to shift 32-bit to 16-bit
521          convert_to_rel32(origInsn, newInsn);
522          *((signed short *) newInsn) = (signed short) disp;
523          newInsn += 2;
524          SET_PTR(newInsn, *gen);
525          return (unsigned) (newInsn - orig_loc);
526       }
527      */
528       //32-bit jump
529       potential = addr + 6;
530       disp = target - potential;
531       if (is_disp32(disp)) {
532          convert_to_rel32(origInsn, newInsn);
533          *((signed int *) newInsn) = (signed int) disp;
534          newInsn += 4;
535          SET_PTR(newInsn, *gen);
536          return (unsigned) gen->getIndex() - start;
537       }
538    }
539    
540    // We use a three-step branch system that looks like so:
541    //   jump conditional <A> 
542    // becomes
543    //   jump conditional <B>
544    //   jump <C>
545    //   B: jump <A>
546    //   C: ... next insn
547
548    // Moves as appropriate...
549    convert_to_rel8(origInsn, newInsn);
550    // We now want a 2-byte branch past the branch at B
551    *newInsn++ = 2;
552    
553    // Now for the branch to C - <jumpSize> unconditional branch
554    *newInsn++ = 0xEB; 
555    SET_PTR(newInsn, *gen);
556     // We now want to 1) move forward a byte (the offset we haven't filled
557    // in yet) and track that we want to fill it in once we're done.
558    codeBufIndex_t jump_to_c_offset_index = gen->getIndex();
559    gen->moveIndex(1);
560    codeBufIndex_t jump_from_index = gen->getIndex();
561
562    // Original address is a little skewed... 
563    // We've moved past the original address (to the tune of nPrefixes + 2 (JCC) + 2 (J))
564    Address currAddr = addr + (unsigned) gen->getIndex() - start;
565    insnCodeGen::generateBranch(*gen, currAddr, target);
566    codeBufIndex_t done = gen->getIndex();
567
568    // Go back and generate the branch _around_ the offset we just calculated
569    gen->setIndex(jump_to_c_offset_index);
570    REGET_PTR(newInsn, *gen);
571
572    //Go back and fill in the size of the jump at B into the 'jump <C>'
573    // The -1 is because 
574    *newInsn = gen->getDisplacement(jump_from_index, done);
575    SET_PTR(newInsn, *gen);
576    gen->setIndex(done);
577
578    return gen->getIndex() - start;
579 }
580
581 unsigned pcRelJCC::maxSize()
582 {
583    unsigned prefixes = count_prefixes(orig_instruc.type());
584 #if defined(arch_x86_64)
585    if (gen->addrSpace()->getAddressWidth() == 8)
586       return prefixes + JUMP_ABS64_SZ + 4;
587 #endif
588    return prefixes + 2 + 2 + JUMP_SZ;
589 }
590
591 bool pcRelJCC::canPreApply()
592 {
593    return gen->startAddr() && (!targ || get_target());
594 }
595
596 pcRelCall::pcRelCall(patchTarget *t, const instruction &i) :
597    pcRelRegion(i),
598    targ_addr(0x0),
599    targ(t)
600 {
601 }
602
603 pcRelCall::pcRelCall(Address target, const instruction &i) :
604    pcRelRegion(i),
605    targ_addr(target),
606    targ(NULL)
607 {
608 }
609
610 Address pcRelCall::get_target()
611 {
612    if (targ)
613       return targ->get_address();
614    return targ_addr;
615 }
616
617 pcRelCall::~pcRelCall()
618 {
619 }
620
621 unsigned pcRelCall::apply(Address addr)
622 {
623    const unsigned char *origInsn = orig_instruc.ptr();
624    unsigned insnType = orig_instruc.type();
625    unsigned char *orig_loc;
626    GET_PTR(newInsn, *gen);
627    orig_loc = newInsn;
628
629    addr += copy_prefixes_nosize(origInsn, newInsn, insnType);
630    SET_PTR(newInsn, *gen);
631    insnCodeGen::generateCall(*gen, addr, get_target());
632    REGET_PTR(newInsn, *gen);
633    return (unsigned) (newInsn - orig_loc);
634 }
635
636 unsigned pcRelCall::maxSize()
637 {
638    unsigned prefixes = count_prefixes(orig_instruc.type());
639 #if defined(arch_x86_64)
640    if (gen->addrSpace()->getAddressWidth() == 8)
641       return prefixes + 2*JUMP_ABS64_SZ;
642 #endif
643    return prefixes + JUMP_REL32_SZ;
644 }
645
646 bool pcRelCall::canPreApply()
647 {
648    return gen->startAddr() && (!targ || get_target());
649 }
650
651 pcRelData::pcRelData(Address a, const instruction &i) :
652    pcRelRegion(i),
653    data_addr(a)
654 {
655 }
656
657 #define REL_DATA_MAXSIZE 2/*push r*/ + 10/*movImmToReg64*/ + 7/*orig insn*/ + 2/*pop r*/
658
659 #if !defined(arch_x86_64)
660 unsigned pcRelData::apply(Address) {
661    assert(0);
662    return 0;
663 }
664
665 #else
666 unsigned pcRelData::apply(Address addr) 
667 {
668    // We may need to change these from 32-bit relative
669    // to 64-bit absolute. This happens with the jumps and calls
670    // as well, but it's better encapsulated there.
671    
672    // We have three options:
673    // a) 32-bit relative (AKA "original").
674    // b) 32-bit absolute version (where 32-bit relative would fail but we're low)
675    // c) 64-bit absolute version
676    const unsigned char *origInsn = orig_instruc.ptr();
677    unsigned insnType = orig_instruc.type();
678    unsigned insnSz = orig_instruc.size();   
679    bool is_data_abs64 = false;
680    unsigned nPrefixes = count_prefixes(insnType);
681    signed long newDisp = data_addr - addr;
682    unsigned char *orig_loc;
683    GET_PTR(newInsn, *gen);
684    orig_loc = newInsn;
685
686    // count opcode bytes (1 or 2)
687    unsigned nOpcodeBytes = 1;
688    if (*(origInsn + nPrefixes) == 0x0F)
689       nOpcodeBytes = 2;
690    if ((*(origInsn + nPrefixes) == 0x0F) && (*(origInsn + nPrefixes + 1) == 0x38 || *(origInsn + nPrefixes + 1) == 0x3A))
691           nOpcodeBytes = 3;
692    
693    Register pointer_reg = (Register)-1;
694      
695    if (!is_disp32(newDisp+insnSz) && !is_addr32(data_addr)) {
696       // Case C: replace with 64-bit.
697       is_data_abs64 = true;
698       unsigned char mod_rm = *(origInsn + nPrefixes + nOpcodeBytes);
699       pointer_reg = (mod_rm & 0x38) != 0 ? 0 : 3;
700       SET_PTR(newInsn, *gen);
701       emitPushReg64(pointer_reg, *gen);
702       emitMovImmToReg64(pointer_reg, data_addr, true, *gen);
703       REGET_PTR(newInsn, *gen);
704    }
705
706    const unsigned char* origInsnStart = origInsn;
707
708    // In other cases, we can rewrite the insn directly; in the 64-bit case, we
709    // still need to copy the insn
710    addr += copy_prefixes(origInsn, newInsn, insnType);
711
712    if (*origInsn == 0x0F) {
713       *newInsn++ = *origInsn++;
714        // 3-byte opcode support
715        if (*origInsn == 0x38 || *origInsn == 0x3A) {
716            *newInsn++ = *origInsn++;
717        }
718    }
719      
720    // And the normal opcode
721    *newInsn++ = *origInsn++;
722    
723    if (is_data_abs64) {
724       // change ModRM byte to use [pointer_reg]: requires
725       // us to change last three bits (the r/m field)
726       // to the value of pointer_reg
727       unsigned char mod_rm = *origInsn++;
728       assert(pointer_reg != (Register)-1);
729       mod_rm = (mod_rm & 0xf8) + pointer_reg;
730       *newInsn++ = mod_rm;
731    }
732    else if (is_disp32(newDisp+insnSz)) {
733       // Whee easy case
734       *newInsn++ = *origInsn++;
735       // Size doesn't change....
736       *((int *)newInsn) = (int)(newDisp - insnSz);
737       newInsn += 4;
738    }
739    else if (is_addr32(data_addr)) {
740       assert(!is_disp32(newDisp+insnSz));
741       unsigned char mod_rm = *origInsn++;
742       
743       // change ModRM byte to use SIB addressing (r/m == 4)
744       mod_rm = (mod_rm & 0xf8) + 4;
745       *newInsn++ = mod_rm;
746       
747       // SIB == 0x25 specifies [disp32] addressing when mod == 0
748       *newInsn++ = 0x25;
749       
750       // now throw in the displacement (the absolute 32-bit address)
751       *((int *)newInsn) = (int)(data_addr);
752       newInsn += 4;
753    }
754    else {
755       // Should never be reached...
756       assert(0);
757    }
758    
759    // there may be an immediate after the displacement for RIP-relative
760    // so we copy over the rest of the instruction here
761    origInsn += 4;
762    while (origInsn - origInsnStart < (int)insnSz)
763       *newInsn++ = *origInsn++;
764    
765    SET_PTR(newInsn, *gen);
766    
767    if (is_data_abs64) {
768       // Cleanup on aisle pointer_reg...
769       assert(pointer_reg != (Register)-1);
770       emitPopReg64(pointer_reg, *gen);
771    }
772    return (unsigned) (newInsn - orig_loc);
773 }
774 #endif
775
776 unsigned pcRelData::maxSize() 
777 {
778    unsigned prefixes = count_prefixes(orig_instruc.type());
779    return REL_DATA_MAXSIZE + prefixes;
780 }
781
782 bool pcRelData::canPreApply()
783 {
784    return (gen->startAddr() != 0x0);
785 }
786
787 bool insnCodeGen::generate(codeGen &,
788                            instruction &,
789                            AddressSpace *,
790                            Address , // Could be kept in the instruction class.
791                            Address ,
792                            patchTarget *,
793                            patchTarget *) 
794 {
795    assert(0 && "Deprecated");
796    return false;
797 }
798
799 #define SIB_SET_REG(x, y) ((x) |= ((y) & 7))
800 #define SIB_SET_INDEX(x, y) ((x) |= (((y) & 7) << 3))
801 #define SIB_SET_SS(x, y) ((x) | (((y) & 3) << 6))
802
803 /**
804  * The comments and naming schemes in this function assume some familiarity with
805  * the IA32/IA32e instruction encoding.  If you don't understand this, I suggest
806  * you start with Chapter 2 of:
807  *  _IA-32 Intel Architecture Software Developer's Manual, Volume 2a_
808  * and appendix A of:
809  *  _IA-32 Intel Architecture Software Developer's Manual, Volume 2b_
810  *
811  * This function takes an instruction that accesses memory, and emits a 
812  * copy of that instruction that has the load/store replaces with a load/store
813  * through a register.  For example, if this function were called with 'loadExpr = r12'
814  * on the instruction 'mov 12(%rax)->%rbx', we would emit 'mov (%r12)->%rbx'.
815  * Note that we strip off any displacements, indexs, etc...  The register is assumed
816  * to contain the final address that will be loaded/stored.
817  **/
818 bool insnCodeGen::generateMem(codeGen &gen,
819                               instruction & insn,
820                               Address /*origAddr*/, 
821                               Address /*newAddr*/,
822                               Register loadExpr,
823                               Register storeExpr) 
824 {
825    /**********
826     * Check parameters
827     **********/
828    Register newreg = Null_Register;
829    if (loadExpr != Null_Register && storeExpr != Null_Register) {
830        cerr << "can't rewrite insn\nerror 1" << endl;
831       return false; //Can only do one memory replace per instruction now
832    }
833    else if (loadExpr == Null_Register && storeExpr == Null_Register)  {
834       cerr << "can't rewrite insn\nError in generateMem: loadExpr " << loadExpr << ", storeExpr " << storeExpr << endl;
835       assert(0);
836      return false; //None specified
837    }
838    else if (loadExpr != Null_Register && storeExpr == Null_Register) 
839       newreg = loadExpr;
840    else if (loadExpr == Null_Register && storeExpr != Null_Register) 
841       newreg = storeExpr;
842
843    /********************************
844     * Section 1.  Read the instruction into our internal data structures.
845     ********************************/
846    GET_PTR(insnBuf, gen);
847    const unsigned char *insn_ptr = insn.ptr();
848
849    struct ia32_memacc memacc[3];
850    struct ia32_condition cond;
851    class ia32_locations loc;
852
853    ia32_instruction orig_instr(memacc, &cond, &loc);
854    ia32_decode(IA32_DECODE_MEMACCESS | IA32_DECODE_CONDITION,
855                insn_ptr, orig_instr);
856
857    if (orig_instr.getPrefix()->getPrefix(1) != 0) {
858            //The instruction accesses memory via segment registers.  Disallow.
859       // That just takes all the fun out of it. Don't disallow, but still skip FS
860            if (orig_instr.getPrefix()->getPrefix(1) == 0x64) {
861                    cerr << "Warning: insn at << uses segment regs: " << hex << (int) orig_instr.getPrefix()->getPrefix(1) << endl;
862          return false;
863       }
864    }
865    if (loc.modrm_position == -1) {
866       //Only supporting MOD/RM instructions now
867       return false; // e.g., leave, pushad instruction
868    }
869
870    //if (loc.address_size == 1) {
871    //  //Don't support 16-bit instructions yet
872    //  cerr << "Error: insn is 16-bit" << endl;
873    //  return false;
874    //}
875
876    if (loc.modrm_reg == 4 && !loc.rex_r && loc.address_size != 1) {
877       //cerr << "Error: insn uses esp/rsp" << endl;
878       //The non-memory access register is %rsp/%esp, we can't work with
879       // this register due to our register saving techniques.
880       //return false;
881    }
882
883    if (loc.modrm_mod == 3) {
884       cerr << "can't rewrite insn\nError: insn doesn't use MOD/RM (2)" <<  endl;
885       //This instruction doesn't use the MOD/RM to access memory
886       return false;
887    }
888    
889    /*********************************
890     * Section 2.  We understand the instruction.  Output it
891     *********************************/
892    int emit_displacement = 0;
893    int emit_mod = 0;
894    int emit_sib = 0;
895    int new_sib = 0;
896    
897    unsigned char *walker = insnBuf;
898    
899    /**
900     * Handle two special cases, where we emit a memory instruction
901     * that loads from/to RBP/R13 or RSP/R12
902     **/
903    if (newreg == REGNUM_RBP || newreg == REGNUM_R13) {
904       //You can't encode rbp or r13 normally i.e. 'mov (%r13)->%rax'
905       // Instead we encode using a displacement, so 'mov 0(%r13)->%rax'
906       emit_displacement = 1;
907       emit_mod = 1; //1 encodes the 0(%reg) format
908    }
909    
910    if (newreg == REGNUM_RSP || newreg == REGNUM_R12) {
911       //You can't encode rsp or r12 normally.  We'll emit a SIB instruction.
912       // So instead of 'mov (%r12)->%rax' we'll emit 'mov (%r12,0,0)->%rax
913       emit_sib = 1;
914       SIB_SET_REG(new_sib, newreg & 7);
915       SIB_SET_INDEX(new_sib, newreg & 4); //4 encodes to no-index
916       //SIB_SET_SS(new_sib, 0); //Gives gcc warning statement w/ no effect
917       loc.rex_x = 0; //If we emit a rex, don't extend the index.
918    }
919    
920    /**
921     * Emit prefixes
922     **/
923
924    //Emit all prefixes except for rex
925    for (int i=0; i<loc.num_prefixes; i++) {
926       if (i != loc.rex_position)
927          *walker++ = insn_ptr[i];
928    }
929
930    unsigned char new_rex = 0;
931    
932    //Emit the rex
933    if (loc.rex_position != -1 || (newreg & 8)) {
934       //If there was no REX byte, and the high bit of the new register
935       // is set, then we'll need to make a rex byte to encode that high bit.
936       loc.rex_b = static_cast<unsigned char>(newreg & 8);
937       REX_INIT(new_rex);
938       REX_SET_W(new_rex, loc.rex_w);
939       REX_SET_R(new_rex, loc.rex_r);
940
941       REX_SET_X(new_rex, 0);
942
943       REX_SET_B(new_rex, loc.rex_b); 
944    }
945    
946    /**
947     * Copy opcode
948     **/
949    for (int i=loc.num_prefixes; i<loc.num_prefixes+(int)loc.opcode_size; i++) {
950      if ((insn_ptr[i] != 0xf0) &&
951          (insn_ptr[i] != 0xf2) &&
952          (insn_ptr[i] != 0xf3) &&
953          (insn_ptr[i] != 0x2e) &&
954          (insn_ptr[i] != 0x36) &&
955          (insn_ptr[i] != 0x3e) &&
956          (insn_ptr[i] != 0x26) &&
957          (insn_ptr[i] != 0x64) &&
958          (insn_ptr[i] != 0x65) &&
959          (insn_ptr[i] != 0x66) &&
960          (insn_ptr[i] != 0x67)) {
961        if (new_rex != 0) {
962          *walker++ = new_rex;
963          new_rex = 0;
964        }
965      }
966      *walker++ = insn_ptr[i];
967    }
968    
969    /**
970     * Emit MOD/RM byte
971     **/
972    unsigned char new_modrm = 0;
973    MODRM_SET_MOD(new_modrm, emit_mod); 
974    MODRM_SET_RM(new_modrm, newreg & 7); //The new register replacing the memaccess
975    // Only the bottom 3 bits go here
976    MODRM_SET_REG(new_modrm, loc.modrm_reg); //The bottom old register
977    *walker++ = new_modrm;
978    
979    /**
980     * Emit SIB byte
981     **/
982    if (emit_sib) {
983       *walker++ = static_cast<unsigned char>(new_sib);
984    }
985    
986    /**
987     * Emit displacement
988     **/
989    if (emit_displacement) {
990       *walker++ = 0x0; //We only need 0 displacements now.
991    }
992    
993    /**
994     * Emit immediate
995     **/
996    for (unsigned i=0; i<loc.imm_size[0]; i++)
997    {
998      *walker++ = insn_ptr[loc.imm_position[0] + i];
999    }
1000
1001    //Debug output.  Fix the end of testdump.c, compile it, the do an
1002    // objdump -D
1003    /*   static FILE *f = NULL;
1004    if (f == NULL)
1005    {
1006       f = fopen("testdump.c", "w+");
1007       if (!f)
1008          perror("Couldn't open");
1009       fprintf(f, "char buffer[] = {\n");
1010    }
1011    fprintf(f, "144, 144, 144, 144, 144, 144, 144, 144, 144,\n");
1012    for (unsigned i=0; i<orig_instr.getSize(); i++) {
1013       fprintf(f, "%u, ", (unsigned) insn_ptr[i]);
1014    }
1015    fprintf(f, "\n");
1016    for (int i=0; i<(walker-insnBuf); i++) {
1017       fprintf(f, "%u, ", (unsigned) insnBuf[i]);
1018    }
1019    fprintf(f, "\n");
1020    fprintf(f, "144, 144, 144, 144, 144, 144, 144, 144, 144,\n");*/
1021    SET_PTR(walker, gen);
1022    return true;
1023 }
1024
1025
1026 bool insnCodeGen::modifyJump(Address targetAddr, NS_x86::instruction &insn, codeGen &gen) {
1027    Address from = gen.currAddr();
1028
1029    const unsigned char *origInsn = insn.ptr();
1030    unsigned insnType = insn.type();
1031   
1032    GET_PTR(newInsn, gen);
1033
1034    from += copy_prefixes(origInsn, newInsn, insnType);
1035    // Otherwise we will fail to account for them and
1036    // generate a branch that is +(# prefix bytes)
1037
1038    SET_PTR(newInsn, gen);
1039     
1040    insnCodeGen::generateBranch(gen, from, targetAddr);
1041    return true;
1042 }
1043
1044 bool insnCodeGen::modifyJcc(Address targetAddr, NS_x86::instruction &insn, codeGen &gen) {
1045    const unsigned char *origInsn = insn.ptr();
1046    unsigned insnType = insn.type();
1047    Address from = gen.currAddr();
1048
1049    Address potential;
1050    signed long disp;
1051    codeBufIndex_t start = gen.getIndex();
1052    GET_PTR(newInsn, gen);
1053
1054    from += copy_prefixes_nosize_or_segments(origInsn, newInsn, insnType); 
1055    
1056
1057    //8-bit jump
1058    potential = from + 2;
1059    disp = targetAddr - potential;
1060    if (is_disp8(disp)) {
1061       convert_to_rel8(origInsn, newInsn);
1062       *newInsn++ = (signed char) disp;
1063       SET_PTR(newInsn, gen);
1064       return true;
1065    }
1066
1067    //Can't convert short E0-E3 loops/jumps to 32-bit equivalents
1068    if (*origInsn < 0xE0 || *origInsn > 0xE3) {
1069      /*
1070       //16-bit jump
1071       potential = from + 5;
1072       disp = targetAddr - potential;
1073       if (is_disp16(disp) && gen.fromSpace()->getAddressWidth() != 8) {
1074          *newInsn++ = 0x66; //Prefix to shift 32-bit to 16-bit
1075          convert_to_rel32(origInsn, newInsn);
1076          *((signed short *) newInsn) = (signed short) disp;
1077          newInsn += 2;
1078          SET_PTR(newInsn, gen);
1079          return true;
1080       }
1081      */
1082       //32-bit jump
1083       potential = from + 6;
1084       disp = targetAddr - potential;
1085       if (is_disp32(disp)) {
1086          convert_to_rel32(origInsn, newInsn);
1087          *((signed int *) newInsn) = (signed int) disp;
1088          newInsn += 4;
1089          SET_PTR(newInsn, gen);
1090          return true;
1091       }
1092    }
1093    
1094    // We use a three-step branch system that looks like so:
1095    //   jump conditional <A> 
1096    // becomes
1097    //   jump conditional <B>
1098    //   jump <C>
1099    //   B: jump <A>
1100    //   C: ... next insn
1101
1102    // Moves as appropriate...
1103    convert_to_rel8(origInsn, newInsn);
1104    // We now want a 2-byte branch past the branch at B
1105    *newInsn++ = 2;
1106    
1107    // Now for the branch to C - <jumpSize> unconditional branch
1108    *newInsn++ = 0xEB; 
1109    SET_PTR(newInsn, gen);
1110     // We now want to 1) move forward a byte (the offset we haven't filled
1111    // in yet) and track that we want to fill it in once we're done.
1112    codeBufIndex_t jump_to_c_offset_index = gen.getIndex();
1113    gen.moveIndex(1);
1114    codeBufIndex_t jump_from_index = gen.getIndex();
1115
1116    // Original address is a little skewed... 
1117    // We've moved past the original address (to the tune of nPrefixes + 2 (JCC) + 2 (J))
1118    Address currAddr = from + (unsigned) gen.getIndex() - start;
1119    insnCodeGen::generateBranch(gen, currAddr, targetAddr);
1120    codeBufIndex_t done = gen.getIndex();
1121
1122    // Go back and generate the branch _around_ the offset we just calculated
1123    gen.setIndex(jump_to_c_offset_index);
1124    REGET_PTR(newInsn, gen);
1125
1126    //Go back and fill in the size of the jump at B into the 'jump <C>'
1127    // The -1 is because 
1128    *newInsn = gen.getDisplacement(jump_from_index, done);
1129    SET_PTR(newInsn, gen);
1130    gen.setIndex(done);
1131    return true;
1132 }
1133
1134 bool insnCodeGen::modifyCall(Address targetAddr, NS_x86::instruction &insn, codeGen &gen) {
1135    // If we're within a 32-bit displacement, we reuse the original call. 
1136    // Otherwise we say "welp, sucks to be us", strip any prefixes, 
1137    // and do a 64-bit long thang
1138
1139    const unsigned char *origInsn = insn.ptr();
1140    unsigned insnType = insn.type();
1141    codeBufIndex_t cur = gen.getIndex();
1142
1143    // Let's try copying prefixes
1144
1145    GET_PTR(newInsn, gen);
1146    copy_prefixes_nosize(origInsn, newInsn, insnType);
1147    SET_PTR(newInsn, gen);
1148
1149    // If we're within 32-bits, then okay; otherwise rewind and use
1150    // 64-bit
1151    long disp = (targetAddr - (gen.currAddr() + CALL_REL32_SZ));
1152    if (is_disp32(disp)) {
1153       insnCodeGen::generateCall(gen, gen.currAddr(), targetAddr);
1154       return true;
1155    }
1156
1157    // Otherwise suck monkey
1158    gen.setIndex(cur);
1159    insnCodeGen::generateCall(gen, gen.currAddr(), targetAddr);
1160    
1161    return true;
1162 }
1163
1164 bool insnCodeGen::modifyData(Address targetAddr, instruction &insn, codeGen &gen) 
1165 {
1166     // We may need to change these from 32-bit relative
1167     // to 64-bit absolute. This happens with the jumps and calls
1168     // as well, but it's better encapsulated there.
1169
1170     // We have three options:
1171     // a) 32-bit relative (AKA "original").
1172     // b) 32-bit absolute version (where 32-bit relative would fail but we're low)
1173     // c) 64-bit absolute version
1174     const unsigned char *origInsn = insn.ptr();
1175     const unsigned char* origInsnStart = origInsn;
1176     // unsigned insnType = insn.type();
1177     unsigned insnSz = insn.size();
1178     Address from = gen.currAddr();
1179
1180     bool is_data_abs64 = false;
1181     signed long newDisp = targetAddr - from;
1182     GET_PTR(newInsn, gen);
1183
1184     Register pointer_reg = (Register)-1;
1185
1186     /******************************************* prefix/opcode ****************/
1187
1188     ia32_instruction instruct;
1189
1190     /**
1191      * This information is generated during ia32_decode. To make this faster
1192      * We are only going to do the prefix and opcode decodings
1193      */
1194     if(!ia32_decode_prefixes(origInsn, instruct))
1195         assert(!"Couldn't decode prefix of already known instruction!\n");
1196
1197     /* get the prefix count */
1198     size_t pref_count = instruct.getSize();
1199
1200     /* copy the prefix */
1201     memcpy(newInsn, origInsn, pref_count);
1202     newInsn += pref_count;
1203     origInsn += pref_count;
1204
1205     /* Decode the opcode */
1206     if(ia32_decode_opcode(0, origInsn, instruct, NULL) < 0)
1207         assert(!"Couldn't decode opcode of already known instruction!\n");
1208
1209     /* Calculate the amount of opcode bytes */
1210     size_t opcode_len = instruct.getSize() - pref_count;
1211
1212     /* Copy the opcode bytes */
1213     memcpy(newInsn, origInsn, opcode_len);
1214     newInsn += opcode_len;
1215     origInsn += opcode_len;
1216
1217     /* Get the value of the Mod/RM byte */
1218     unsigned char mod_rm = *origInsn;
1219     origInsn++;
1220
1221     if (!is_disp32(newDisp+insnSz) && !is_addr32(targetAddr)) 
1222     {
1223         // Case C: replace with 64-bit.
1224         is_data_abs64 = true;
1225 #if defined(arch_x86_64)
1226         pointer_reg = (mod_rm & 0x38) != 0 ? 0 : 3;
1227         SET_PTR(newInsn, gen);
1228         emitPushReg64(pointer_reg, gen);
1229         emitMovImmToReg64(pointer_reg, targetAddr, true, gen);
1230         REGET_PTR(newInsn, gen);
1231
1232         // change ModRM byte to use [pointer_reg]: requires
1233         // us to change last three bits (the r/m field)
1234         // to the value of pointer_reg
1235
1236         mod_rm = (mod_rm & 0xf8) | pointer_reg;
1237         /* Set the new ModR/M byte of the new instruction */
1238         *newInsn++ = mod_rm;
1239 #endif
1240     } else if (is_disp32(newDisp + insnSz)) 
1241     {
1242         /* Instruction can remain a 32 bit instruction */
1243
1244         /* Copy the ModR/M byte */
1245         *newInsn++ = mod_rm;
1246         /* Use the new relative displacement */
1247         *((int *)newInsn) = (int)(newDisp - insnSz);
1248         newInsn += 4;
1249     } else if (is_addr32(targetAddr)) 
1250     {
1251         // change ModRM byte to use SIB addressing (r/m == 4)
1252         mod_rm = (mod_rm & 0xf8) + 4;
1253         *newInsn++ = mod_rm;
1254
1255         // SIB == 0x25 specifies [disp32] addressing when mod == 0
1256         *newInsn++ = 0x25;
1257
1258         // now throw in the displacement (the absolute 32-bit address)
1259         *((int *)newInsn) = (int)(targetAddr);
1260         newInsn += 4;
1261     } else {
1262         /* Impossible case */
1263         assert(0);
1264     }
1265
1266     // there may be an immediate after the displacement for RIP-relative
1267     // so we copy over the rest of the instruction here
1268     origInsn += 4;
1269     while (origInsn - origInsnStart < (int)insnSz)
1270         *newInsn++ = *origInsn++;
1271
1272     SET_PTR(newInsn, gen);
1273
1274 #if defined(arch_x86_64)
1275     if (is_data_abs64) {
1276         // Cleanup on aisle pointer_reg...
1277         assert(pointer_reg != (Register)-1);
1278         emitPopReg64(pointer_reg, gen);
1279     }
1280 #endif
1281
1282     return true;
1283 }
1284
1285 bool insnCodeGen::modifyDisp(signed long newDisp, instruction &insn, codeGen &gen, Architecture arch, Address addr) {
1286
1287     relocation_cerr << "modifyDisp "
1288         << std::hex << addr
1289         << std::dec << ", newDisp = " << newDisp << endl;
1290
1291     const unsigned char* origInsn = insn.ptr();
1292     unsigned insnSz = insn.size();
1293
1294     unsigned newInsnSz = 0;
1295
1296     InstructionAPI::InstructionDecoder d2(origInsn, insnSz, arch);
1297     InstructionAPI::Instruction::Ptr origInsnPtr = d2.decode();
1298
1299     StackAccess* origAccess;
1300     signed long origDisp;
1301     if (!getMemoryOffset(NULL, NULL, origInsnPtr, addr, MachRegister(), StackAnalysis::Height(0), origAccess, arch)) {
1302         assert(0);
1303     } else {
1304         origDisp = origAccess->disp();
1305     }
1306
1307     GET_PTR(newInsn, gen);
1308
1309     const unsigned char* newInsnStart = newInsn;
1310     const unsigned char* origInsnStart = origInsn;
1311
1312     /******************************************* prefix/opcode ****************/
1313    
1314     ia32_instruction instruct; 
1315     /**
1316      * This information is generated during ia32_decode. To make this faster
1317      * We are only going to do the prefix and opcode decodings
1318      */
1319     if(!ia32_decode_prefixes(origInsn, instruct))
1320         assert(!"Couldn't decode prefix of already known instruction!\n");
1321
1322     /* get the prefix count */
1323     size_t pref_count = instruct.getSize();
1324
1325     /* copy the prefix */
1326     memcpy(newInsn, origInsn, pref_count);
1327     newInsn += pref_count;
1328     origInsn += pref_count;
1329
1330     /* Decode the opcode */
1331     if(ia32_decode_opcode(0, origInsn, instruct, NULL) < 0)
1332         assert(!"Couldn't decode opcode of already known instruction!\n");
1333
1334     /* Calculate the amount of opcode bytes */
1335     size_t opcode_len = instruct.getSize() - pref_count;
1336
1337     /* Copy the opcode bytes */
1338     memcpy(newInsn, origInsn, opcode_len);
1339     newInsn += opcode_len;
1340     origInsn += opcode_len;
1341
1342     /******************************************* modRM *************************/
1343     // Update displacement size (mod bits in ModRM), if necessary
1344     int expectedDifference = 0;
1345     unsigned char modrm = *origInsn++;
1346     unsigned char modrm_mod = MODRM_MOD(modrm);
1347     //unsigned char modrm_reg = MODRM_REG(modrm);
1348     unsigned char modrm_rm = MODRM_RM(modrm);
1349
1350
1351     int origDispSize = -1;
1352
1353     if (origDisp != newDisp) {
1354         if (modrm_mod == 0) {
1355             if (modrm_rm == 5) {
1356                 origDispSize = 32;
1357             } else {
1358                 origDispSize = -1;
1359             }
1360         } else if (modrm_mod == 1) {
1361             origDispSize = 8;
1362         } else if (modrm_mod == 2) {
1363             origDispSize = 32;
1364         } else {
1365             origDispSize = -1;
1366         }
1367
1368         // Switch modrm_mod if necessary
1369         if (origDispSize == -1) {
1370             // If we didn't have a displacement before, and we do now, need to handle it!
1371             if (is_disp8(newDisp)) {
1372                 modrm = modrm + 0x40;
1373                 expectedDifference = 1;
1374             } else if (is_disp32(newDisp)) {
1375                 modrm = modrm + 0x80;
1376                 expectedDifference = 4;
1377             }
1378
1379         } else if (origDispSize == 8) {
1380             if (is_disp8(newDisp)) {
1381             } else if (is_disp32(newDisp)) {
1382                 modrm = modrm + 0x40;
1383                 expectedDifference = 3;
1384             }
1385         } else if (origDispSize == 32) {
1386             if (is_disp8(newDisp)) {
1387                 modrm = modrm - 0x40;
1388                 expectedDifference = -3;
1389             } else if (is_disp32(newDisp)) {
1390             }
1391         }
1392     }
1393
1394     /******************************************* SIB ***************************/
1395
1396     // Copy the SIB byte when necessary
1397     if (modrm_rm == 4) {
1398
1399         unsigned char sib = *origInsn++;
1400         unsigned char sib_base = MODRM_RM(sib);
1401
1402         // Check for displacement in the SIB
1403         if (sib_base == 5 && modrm_mod == 0) {
1404             origDispSize = 32;
1405         }
1406
1407         // Copy MODRM byte
1408         *newInsn++ = modrm;
1409         newInsnSz++;
1410
1411         // Copy SIB byte
1412         *newInsn++ = sib;
1413         newInsnSz++;
1414     } else {
1415         // Copy MODRM byte
1416         *newInsn++ = modrm;
1417         newInsnSz++;
1418
1419         // Skip SIB byte
1420     }
1421
1422     /********************************* displacement ***************************/
1423
1424     // Put the displacement back in
1425     if (origDisp != newDisp) {
1426         // Replace displacement
1427         if (is_disp8(newDisp)) {
1428             *((signed char *)newInsn) = (signed char)(newDisp);
1429             newInsn += sizeof(signed char);
1430             newInsnSz += sizeof(signed char);
1431         } else if (is_disp32(newDisp)) {
1432             *((int *)newInsn) = (int)(newDisp);
1433             newInsn += sizeof(int);
1434             newInsnSz += sizeof(int);
1435         } else {
1436             // Should never be reached...
1437             assert(0);
1438         }
1439     }
1440
1441     if (origDispSize == -1) {
1442         // Do nothing
1443     } else if (origDispSize == 8) {
1444         origInsn += sizeof(signed char);
1445     } else if (origDispSize == 32) {
1446         origInsn += sizeof(int);
1447     } else {
1448         // Should never be reached
1449         assert(0);
1450     }
1451
1452     /********************************* immedidate *****************************/
1453
1454     // there may be an immediate after the displacement
1455     // so we copy over the rest of the instruction here
1456     while (origInsn - origInsnStart < (int)insnSz) {
1457         unsigned char nextByte = *origInsn++;
1458         *newInsn++ = nextByte;
1459         newInsnSz++;
1460     }
1461
1462     /******************************** done ************************************/
1463
1464     InstructionAPI::InstructionDecoder d(newInsnStart, newInsnSz, arch);
1465     InstructionAPI::Instruction::Ptr newInsnPtr = d.decode();
1466
1467     if ((insnSz + expectedDifference) != newInsnSz) {
1468         return false;
1469     }
1470
1471     // Validate
1472     StackAccess* newAccess = NULL;
1473     getMemoryOffset(NULL, NULL, newInsnPtr, addr, MachRegister(), StackAnalysis::Height(0), newAccess, arch);
1474     if (!newAccess) {
1475         if (newDisp != 0) {
1476             return false;
1477         }
1478     } else {
1479         if (newAccess->disp() != newDisp){
1480             return false;
1481         }
1482     }
1483
1484     SET_PTR(newInsn, gen);
1485
1486     return true;
1487 }