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