From a29c34354ab52f25845a3b3145eaf8dd3887e9d8 Mon Sep 17 00:00:00 2001
From: whh8b <whh8b@git.zephyr-software.com>
Date: Wed, 19 Nov 2014 20:35:29 +0000
Subject: [PATCH] Add support for RIP addressing.

---
 src/zipr.cpp | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/src/zipr.cpp b/src/zipr.cpp
index aa1bee64d..028a6c24e 100644
--- a/src/zipr.cpp
+++ b/src/zipr.cpp
@@ -1044,16 +1044,79 @@ void Zipr_t::PatchInstruction(RangeAddress_t from_addr, Instruction_t* to_insn)
 	}
 }
 
+#define IS_RELATIVE(A) \
+((A.ArgType & MEMORY_TYPE) && (A.ArgType & RELATIVE_))
 
 RangeAddress_t Zipr_t::PlopInstruction(Instruction_t* insn,RangeAddress_t addr)
 {
 	DISASM d;
 	insn->Disassemble(d);
 	RangeAddress_t ret=addr;
+	bool is_instr_relative = false;
 
 
 	final_insn_locations[insn]=addr;
 
+	is_instr_relative = IS_RELATIVE(d.Argument1) ||
+	                    IS_RELATIVE(d.Argument2) ||
+											IS_RELATIVE(d.Argument3);
+	if (is_instr_relative) {
+		ARGTYPE *relative_arg = NULL;
+		uint32_t abs_displacement;
+		uint32_t *displacement;
+		char instr_raw[20] = {0,};
+		int size;
+		int offset;
+		string raw_data;
+
+		raw_data = insn->GetDataBits();
+		assert(raw_data.length() <= 20);
+
+		/*
+		 * Which argument is relative? There must be one.
+		 */
+		if (IS_RELATIVE(d.Argument1)) relative_arg = &d.Argument1;
+		if (IS_RELATIVE(d.Argument2)) relative_arg = &d.Argument2;
+		if (IS_RELATIVE(d.Argument3)) relative_arg = &d.Argument3;
+		assert(relative_arg);
+
+		/*
+		 * Calculate the offset into the instruction
+		 * of the displacement address.
+		 */
+		offset = relative_arg->Memory.DisplacementAddr - d.EIP;
+
+		/*
+		 * The size of the displacement address must be
+		 * four at this point.
+		 */
+		size = relative_arg->Memory.DisplacementSize;
+		assert(size == 4);
+
+		/*
+		 * Copy the instruction raw bytes to a place
+		 * where we can modify them.
+		 */
+		memcpy(instr_raw,raw_data.c_str(),raw_data.length());
+
+		/*
+		 * Calculate absolute displacement and relative
+		 * displacement.
+		 */
+		displacement = (uint32_t*)(&instr_raw[offset]);
+		abs_displacement = *displacement;
+		*displacement = abs_displacement - addr;
+
+		printf("absolute displacement: 0x%x\n", abs_displacement);
+		printf("relative displacement: 0x%x\n", *displacement);
+
+		/*
+		 * Update the instruction with the relative displacement.
+		 */
+		raw_data.replace(0, raw_data.length(), instr_raw, raw_data.length());
+		insn->SetDataBits(raw_data);
+	}
+
 	if(insn->GetTarget())
 	{
 		ret=PlopWithTarget(insn,addr);
-- 
GitLab