commit c3db2bda113dff501862928bcf4f2efbc531f520 (from 9d5a42622dfd95dcefccc1de756f42ac3a7ee352)
Merge: 9d5a42622dfd 2ef16d809162
Author: Josh Stone <cuviper@gmail.com>
Date: Tue Aug 30 12:08:52 2016 -0700
Merge pull request #163 from cuviper/modify-data-64
fix insnCodeGen::modifyData's 64-bit conversion
diff --git a/dyninstAPI/src/codegen-x86.C b/dyninstAPI/src/codegen-x86.C
index ef8a6b0b4731..ad9ac8ec90ba 100644
--- a/dyninstAPI/src/codegen-x86.C
+++ b/dyninstAPI/src/codegen-x86.C
@@ -1196,10 +1196,6 @@ bool insnCodeGen::modifyData(Address targetAddr, instruction &insn, codeGen &gen
/* get the prefix count */
size_t pref_count = instruct.getSize();
-
- /* copy the prefix */
- memcpy(newInsn, origInsn, pref_count);
- newInsn += pref_count;
origInsn += pref_count;
/* Decode the opcode */
@@ -1208,27 +1204,31 @@ bool insnCodeGen::modifyData(Address targetAddr, instruction &insn, codeGen &gen
/* Calculate the amount of opcode bytes */
size_t opcode_len = instruct.getSize() - pref_count;
-
- /* Copy the opcode bytes */
- memcpy(newInsn, origInsn, opcode_len);
- newInsn += opcode_len;
origInsn += opcode_len;
/* Get the value of the Mod/RM byte */
- unsigned char mod_rm = *origInsn;
- origInsn++;
+ unsigned char mod_rm = *origInsn++;
+#if defined(arch_x86_64)
if (!is_disp32(newDisp+insnSz) && !is_addr32(targetAddr))
{
// Case C: replace with 64-bit.
+ // This preamble must come before any writes to newInsn!
is_data_abs64 = true;
-#if defined(arch_x86_64)
pointer_reg = (mod_rm & 0x38) != 0 ? 0 : 3;
SET_PTR(newInsn, gen);
emitPushReg64(pointer_reg, gen);
emitMovImmToReg64(pointer_reg, targetAddr, true, gen);
REGET_PTR(newInsn, gen);
+ }
+#endif
+
+ /* copy the prefix and opcode bytes */
+ memcpy(newInsn, origInsnStart, pref_count + opcode_len);
+ newInsn += pref_count + opcode_len;
+ if (is_data_abs64)
+ {
// change ModRM byte to use [pointer_reg]: requires
// us to change last three bits (the r/m field)
// to the value of pointer_reg
@@ -1236,7 +1236,6 @@ bool insnCodeGen::modifyData(Address targetAddr, instruction &insn, codeGen &gen
mod_rm = (mod_rm & 0xf8) | pointer_reg;
/* Set the new ModR/M byte of the new instruction */
*newInsn++ = mod_rm;
-#endif
} else if (is_disp32(newDisp + insnSz))
{
/* Instruction can remain a 32 bit instruction */