From 9f8171317d27fbee3326ed2ffc917de2c7f1dd42 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 6 Oct 2008 19:11:07 -0700 Subject: [PATCH] BR 2148448: Fix RIP-relative addressing with an immediate When there is an immediate in the instruction, a RIP-relative offset may not be relative to the end of the offset itself, since it is relative to the end of the *instruction*, not the end of the *offset*. Signed-off-by: H. Peter Anvin --- assemble.c | 17 +++++++++++------ test/riprel2.asm | 11 +++++++++++ 2 files changed, 22 insertions(+), 6 deletions(-) create mode 100644 test/riprel2.asm diff --git a/assemble.c b/assemble.c index d6abeac..d7e9eae 100644 --- a/assemble.c +++ b/assemble.c @@ -796,7 +796,7 @@ static bool is_sbyte64(operand *o) return v >= -128 && v <= 127; } static int64_t calcsize(int32_t segment, int64_t offset, int bits, - insn * ins, const uint8_t *codes) + insn * ins, const uint8_t *codes) { int64_t length = 0; uint8_t c; @@ -1777,6 +1777,7 @@ static void gencode(int32_t segment, int64_t offset, int bits, int32_t rflags; uint8_t *p; int32_t s; + enum out_type type; if (c <= 0177) { /* pick rfield from operand b */ @@ -1840,12 +1841,16 @@ static void gencode(int32_t segment, int64_t offset, int bits, case 4: data = ins->oprs[(c >> 3) & 7].offset; warn_overflow(ea_data.bytes, opx); - out(offset, segment, &data, - ea_data.rip ? OUT_REL4ADR : OUT_ADDRESS, - ea_data.bytes, - ins->oprs[(c >> 3) & 7].segment, - ins->oprs[(c >> 3) & 7].wrt); s += ea_data.bytes; + if (ea_data.rip) { + data -= insn_end - (offset+ea_data.bytes); + type = OUT_REL4ADR; + } else { + type = OUT_ADDRESS; + } + out(offset, segment, &data, type, ea_data.bytes, + ins->oprs[(c >> 3) & 7].segment, + ins->oprs[(c >> 3) & 7].wrt); break; } offset += s; diff --git a/test/riprel2.asm b/test/riprel2.asm new file mode 100644 index 0000000..2d13d3e --- /dev/null +++ b/test/riprel2.asm @@ -0,0 +1,11 @@ +;Testname=unoptimized; Arguments=-fbin -oriprel2.bin -O0; Files=stdout stderr riprel.bin +;Testname=optimized; Arguments=-fbin -oriprel2.bin -Ox; Files=stdout stderr riprel.bin + + bits 64 + + default rel + mov dword [foo],12345678h + mov qword [foo],12345678h + mov [foo],rax + mov dword [foo],12345678h +foo: -- 2.7.4