mirror of
https://github.com/frida/tinycc
synced 2025-02-04 01:14:03 +03:00
Fix absolute memory references
This properly fixes what 870271ea tried to fix. Absolute memory references can't use %rip relative addressing, and additionally, if the address doesn't fit 32bit (signed) it must be loaded via movabs. No good testcase added, it would require catching signals and still be unreliable.
This commit is contained in:
parent
74463eb954
commit
348dd9f4a6
31
x86_64-gen.c
31
x86_64-gen.c
@ -288,12 +288,18 @@ static void gen_modrm_impl(int op_reg, int r, Sym *sym, int c, int is_got)
|
|||||||
op_reg = REG_VALUE(op_reg) << 3;
|
op_reg = REG_VALUE(op_reg) << 3;
|
||||||
if ((r & VT_VALMASK) == VT_CONST) {
|
if ((r & VT_VALMASK) == VT_CONST) {
|
||||||
/* constant memory reference */
|
/* constant memory reference */
|
||||||
o(0x05 | op_reg);
|
if (!(r & VT_SYM)) {
|
||||||
if (is_got) {
|
/* Absolute memory reference */
|
||||||
gen_gotpcrel(r, sym, c);
|
o(0x04 | op_reg); /* [sib] | destreg */
|
||||||
} else {
|
oad(0x25, c); /* disp32 */
|
||||||
gen_addrpc32(r, sym, c);
|
} else {
|
||||||
}
|
o(0x05 | op_reg); /* (%rip)+disp32 | destreg */
|
||||||
|
if (is_got) {
|
||||||
|
gen_gotpcrel(r, sym, c);
|
||||||
|
} else {
|
||||||
|
gen_addrpc32(r, sym, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if ((r & VT_VALMASK) == VT_LOCAL) {
|
} else if ((r & VT_VALMASK) == VT_LOCAL) {
|
||||||
/* currently, we use only ebp as base */
|
/* currently, we use only ebp as base */
|
||||||
if (c == (char)c) {
|
if (c == (char)c) {
|
||||||
@ -381,6 +387,19 @@ void load(int r, SValue *sv)
|
|||||||
fr = get_reg(RC_INT);
|
fr = get_reg(RC_INT);
|
||||||
load(fr, &v1);
|
load(fr, &v1);
|
||||||
}
|
}
|
||||||
|
if (fc != sv->c.i) {
|
||||||
|
/* If the addends doesn't fit into a 32bit signed
|
||||||
|
we must use a 64bit move. We've checked above
|
||||||
|
that this doesn't have a sym associated. */
|
||||||
|
v1.type.t = VT_LLONG;
|
||||||
|
v1.r = VT_CONST;
|
||||||
|
v1.c.i = sv->c.i;
|
||||||
|
fr = r;
|
||||||
|
if (!(reg_classes[fr] & (RC_INT|RC_R11)))
|
||||||
|
fr = get_reg(RC_INT);
|
||||||
|
load(fr, &v1);
|
||||||
|
fc = 0;
|
||||||
|
}
|
||||||
ll = 0;
|
ll = 0;
|
||||||
/* Like GCC we can load from small enough properly sized
|
/* Like GCC we can load from small enough properly sized
|
||||||
structs and unions as well.
|
structs and unions as well.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user