Align IntelGOTPCRel4 with R_X86_64_GOTPCREL.
Add an addend field to reloc_external, and use it to move the responsibility for accounting for the difference between the end of an instruction (where the PC is considered to be in PC-relative on intel) and the beginning of the immediate field into the encoding code. Specifically, this makes IntelGOTPCRel4 directly correspond to R_X86_64_GOTPCREL, instead of also carrying an implicit `- 4`.
This commit is contained in:
@@ -30,11 +30,11 @@ ebb0:
|
|||||||
call fn0() ; bin: e8 PLTRel4(%foo) 00000000
|
call fn0() ; bin: e8 PLTRel4(%foo) 00000000
|
||||||
|
|
||||||
; asm: mov 0x0(%rip), %rax
|
; asm: mov 0x0(%rip), %rax
|
||||||
[-,%rax] v0 = func_addr.i64 fn0 ; bin: 48 8b 05 GOTPCRel4(%foo) 00000000
|
[-,%rax] v0 = func_addr.i64 fn0 ; bin: 48 8b 05 GOTPCRel4(%foo-4) 00000000
|
||||||
; asm: mov 0x0(%rip), %rsi
|
; asm: mov 0x0(%rip), %rsi
|
||||||
[-,%rsi] v1 = func_addr.i64 fn0 ; bin: 48 8b 35 GOTPCRel4(%foo) 00000000
|
[-,%rsi] v1 = func_addr.i64 fn0 ; bin: 48 8b 35 GOTPCRel4(%foo-4) 00000000
|
||||||
; asm: mov 0x0(%rip), %r10
|
; asm: mov 0x0(%rip), %r10
|
||||||
[-,%r10] v2 = func_addr.i64 fn0 ; bin: 4c 8b 15 GOTPCRel4(%foo) 00000000
|
[-,%r10] v2 = func_addr.i64 fn0 ; bin: 4c 8b 15 GOTPCRel4(%foo-4) 00000000
|
||||||
|
|
||||||
; asm: call *%rax
|
; asm: call *%rax
|
||||||
call_indirect sig0, v0() ; bin: ff d0
|
call_indirect sig0, v0() ; bin: ff d0
|
||||||
@@ -44,11 +44,11 @@ ebb0:
|
|||||||
call_indirect sig0, v2() ; bin: 41 ff d2
|
call_indirect sig0, v2() ; bin: 41 ff d2
|
||||||
|
|
||||||
; asm: mov 0x0(%rip), %rcx
|
; asm: mov 0x0(%rip), %rcx
|
||||||
[-,%rcx] v3 = globalsym_addr.i64 gv0 ; bin: 48 8b 0d GOTPCRel4(%some_gv) 00000000
|
[-,%rcx] v3 = globalsym_addr.i64 gv0 ; bin: 48 8b 0d GOTPCRel4(%some_gv-4) 00000000
|
||||||
; asm: mov 0x0(%rip), %rsi
|
; asm: mov 0x0(%rip), %rsi
|
||||||
[-,%rsi] v4 = globalsym_addr.i64 gv0 ; bin: 48 8b 35 GOTPCRel4(%some_gv) 00000000
|
[-,%rsi] v4 = globalsym_addr.i64 gv0 ; bin: 48 8b 35 GOTPCRel4(%some_gv-4) 00000000
|
||||||
; asm: mov 0x0(%rip), %r10
|
; asm: mov 0x0(%rip), %r10
|
||||||
[-,%r10] v5 = globalsym_addr.i64 gv0 ; bin: 4c 8b 15 GOTPCRel4(%some_gv) 00000000
|
[-,%r10] v5 = globalsym_addr.i64 gv0 ; bin: 4c 8b 15 GOTPCRel4(%some_gv-4) 00000000
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,13 +72,29 @@ impl binemit::CodeSink for TextSink {
|
|||||||
write!(self.text, "{}({}) ", reloc, ebb_offset).unwrap();
|
write!(self.text, "{}({}) ", reloc, ebb_offset).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reloc_external(&mut self, reloc: binemit::Reloc, name: &ir::ExternalName) {
|
fn reloc_external(
|
||||||
|
&mut self,
|
||||||
|
reloc: binemit::Reloc,
|
||||||
|
name: &ir::ExternalName,
|
||||||
|
addend: binemit::Addend,
|
||||||
|
) {
|
||||||
write!(
|
write!(
|
||||||
self.text,
|
self.text,
|
||||||
"{}({}) ",
|
"{}({}",
|
||||||
reloc,
|
reloc,
|
||||||
name,
|
name,
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
if addend != 0 {
|
||||||
|
write!(
|
||||||
|
self.text,
|
||||||
|
"{:+}",
|
||||||
|
addend,
|
||||||
|
).unwrap();
|
||||||
|
}
|
||||||
|
write!(
|
||||||
|
self.text,
|
||||||
|
") ",
|
||||||
|
).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reloc_jt(&mut self, reloc: binemit::Reloc, jt: ir::JumpTable) {
|
fn reloc_jt(&mut self, reloc: binemit::Reloc, jt: ir::JumpTable) {
|
||||||
|
|||||||
@@ -103,6 +103,12 @@ impl binemit::CodeSink for SizeSink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn reloc_ebb(&mut self, _reloc: binemit::Reloc, _ebb_offset: binemit::CodeOffset) {}
|
fn reloc_ebb(&mut self, _reloc: binemit::Reloc, _ebb_offset: binemit::CodeOffset) {}
|
||||||
fn reloc_external(&mut self, _reloc: binemit::Reloc, _name: &ir::ExternalName) {}
|
fn reloc_external(
|
||||||
|
&mut self,
|
||||||
|
_reloc: binemit::Reloc,
|
||||||
|
_name: &ir::ExternalName,
|
||||||
|
_addend: binemit::Addend,
|
||||||
|
) {
|
||||||
|
}
|
||||||
fn reloc_jt(&mut self, _reloc: binemit::Reloc, _jt: ir::JumpTable) {}
|
fn reloc_jt(&mut self, _reloc: binemit::Reloc, _jt: ir::JumpTable) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -522,7 +522,8 @@ fnaddr4 = TailRecipe(
|
|||||||
emit='''
|
emit='''
|
||||||
PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink);
|
PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink);
|
||||||
sink.reloc_external(Reloc::IntelAbs4,
|
sink.reloc_external(Reloc::IntelAbs4,
|
||||||
&func.dfg.ext_funcs[func_ref].name);
|
&func.dfg.ext_funcs[func_ref].name,
|
||||||
|
0);
|
||||||
sink.put4(0);
|
sink.put4(0);
|
||||||
''')
|
''')
|
||||||
|
|
||||||
@@ -532,7 +533,8 @@ fnaddr8 = TailRecipe(
|
|||||||
emit='''
|
emit='''
|
||||||
PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink);
|
PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink);
|
||||||
sink.reloc_external(Reloc::IntelAbs8,
|
sink.reloc_external(Reloc::IntelAbs8,
|
||||||
&func.dfg.ext_funcs[func_ref].name);
|
&func.dfg.ext_funcs[func_ref].name,
|
||||||
|
0);
|
||||||
sink.put8(0);
|
sink.put8(0);
|
||||||
''')
|
''')
|
||||||
|
|
||||||
@@ -542,7 +544,8 @@ allones_fnaddr4 = TailRecipe(
|
|||||||
emit='''
|
emit='''
|
||||||
PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink);
|
PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink);
|
||||||
sink.reloc_external(Reloc::IntelAbs4,
|
sink.reloc_external(Reloc::IntelAbs4,
|
||||||
&func.dfg.ext_funcs[func_ref].name);
|
&func.dfg.ext_funcs[func_ref].name,
|
||||||
|
0);
|
||||||
// Write the immediate as `!0` for the benefit of BaldrMonkey.
|
// Write the immediate as `!0` for the benefit of BaldrMonkey.
|
||||||
sink.put4(!0);
|
sink.put4(!0);
|
||||||
''')
|
''')
|
||||||
@@ -553,7 +556,8 @@ allones_fnaddr8 = TailRecipe(
|
|||||||
emit='''
|
emit='''
|
||||||
PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink);
|
PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink);
|
||||||
sink.reloc_external(Reloc::IntelAbs8,
|
sink.reloc_external(Reloc::IntelAbs8,
|
||||||
&func.dfg.ext_funcs[func_ref].name);
|
&func.dfg.ext_funcs[func_ref].name,
|
||||||
|
0);
|
||||||
// Write the immediate as `!0` for the benefit of BaldrMonkey.
|
// Write the immediate as `!0` for the benefit of BaldrMonkey.
|
||||||
sink.put8(!0);
|
sink.put8(!0);
|
||||||
''')
|
''')
|
||||||
@@ -565,8 +569,11 @@ got_fnaddr8 = TailRecipe(
|
|||||||
emit='''
|
emit='''
|
||||||
PUT_OP(bits, rex2(0, out_reg0), sink);
|
PUT_OP(bits, rex2(0, out_reg0), sink);
|
||||||
modrm_riprel(out_reg0, sink);
|
modrm_riprel(out_reg0, sink);
|
||||||
|
// The addend adjusts for the difference between the end of the
|
||||||
|
// instruction and the beginning of the immediate field.
|
||||||
sink.reloc_external(Reloc::IntelGOTPCRel4,
|
sink.reloc_external(Reloc::IntelGOTPCRel4,
|
||||||
&func.dfg.ext_funcs[func_ref].name);
|
&func.dfg.ext_funcs[func_ref].name,
|
||||||
|
-4);
|
||||||
sink.put4(0);
|
sink.put4(0);
|
||||||
''')
|
''')
|
||||||
|
|
||||||
@@ -577,7 +584,8 @@ gvaddr4 = TailRecipe(
|
|||||||
emit='''
|
emit='''
|
||||||
PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink);
|
PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink);
|
||||||
sink.reloc_external(Reloc::IntelAbs4,
|
sink.reloc_external(Reloc::IntelAbs4,
|
||||||
&func.global_vars[global_var].symbol_name());
|
&func.global_vars[global_var].symbol_name(),
|
||||||
|
0);
|
||||||
sink.put4(0);
|
sink.put4(0);
|
||||||
''')
|
''')
|
||||||
|
|
||||||
@@ -587,7 +595,8 @@ gvaddr8 = TailRecipe(
|
|||||||
emit='''
|
emit='''
|
||||||
PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink);
|
PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink);
|
||||||
sink.reloc_external(Reloc::IntelAbs8,
|
sink.reloc_external(Reloc::IntelAbs8,
|
||||||
&func.global_vars[global_var].symbol_name());
|
&func.global_vars[global_var].symbol_name(),
|
||||||
|
0);
|
||||||
sink.put8(0);
|
sink.put8(0);
|
||||||
''')
|
''')
|
||||||
|
|
||||||
@@ -597,8 +606,11 @@ got_gvaddr8 = TailRecipe(
|
|||||||
emit='''
|
emit='''
|
||||||
PUT_OP(bits, rex2(0, out_reg0), sink);
|
PUT_OP(bits, rex2(0, out_reg0), sink);
|
||||||
modrm_rm(5, out_reg0, sink);
|
modrm_rm(5, out_reg0, sink);
|
||||||
|
// The addend adjusts for the difference between the end of the
|
||||||
|
// instruction and the beginning of the immediate field.
|
||||||
sink.reloc_external(Reloc::IntelGOTPCRel4,
|
sink.reloc_external(Reloc::IntelGOTPCRel4,
|
||||||
&func.global_vars[global_var].symbol_name());
|
&func.global_vars[global_var].symbol_name(),
|
||||||
|
-4);
|
||||||
sink.put4(0);
|
sink.put4(0);
|
||||||
''')
|
''')
|
||||||
|
|
||||||
@@ -874,7 +886,8 @@ call_id = TailRecipe(
|
|||||||
emit='''
|
emit='''
|
||||||
PUT_OP(bits, BASE_REX, sink);
|
PUT_OP(bits, BASE_REX, sink);
|
||||||
sink.reloc_external(Reloc::IntelPCRel4,
|
sink.reloc_external(Reloc::IntelPCRel4,
|
||||||
&func.dfg.ext_funcs[func_ref].name);
|
&func.dfg.ext_funcs[func_ref].name,
|
||||||
|
0);
|
||||||
sink.put4(0);
|
sink.put4(0);
|
||||||
''')
|
''')
|
||||||
|
|
||||||
@@ -883,7 +896,8 @@ call_plt_id = TailRecipe(
|
|||||||
emit='''
|
emit='''
|
||||||
PUT_OP(bits, BASE_REX, sink);
|
PUT_OP(bits, BASE_REX, sink);
|
||||||
sink.reloc_external(Reloc::IntelPLTRel4,
|
sink.reloc_external(Reloc::IntelPLTRel4,
|
||||||
&func.dfg.ext_funcs[func_ref].name);
|
&func.dfg.ext_funcs[func_ref].name,
|
||||||
|
0);
|
||||||
sink.put4(0);
|
sink.put4(0);
|
||||||
''')
|
''')
|
||||||
|
|
||||||
|
|||||||
@@ -184,7 +184,8 @@ UJcall = EncRecipe(
|
|||||||
'UJcall', Call, size=4, ins=(), outs=(),
|
'UJcall', Call, size=4, ins=(), outs=(),
|
||||||
emit='''
|
emit='''
|
||||||
sink.reloc_external(Reloc::RiscvCall,
|
sink.reloc_external(Reloc::RiscvCall,
|
||||||
&func.dfg.ext_funcs[func_ref].name);
|
&func.dfg.ext_funcs[func_ref].name,
|
||||||
|
0);
|
||||||
// rd=%x1 is the standard link register.
|
// rd=%x1 is the standard link register.
|
||||||
put_uj(bits, 0, 1, sink);
|
put_uj(bits, 0, 1, sink);
|
||||||
''')
|
''')
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
//! `CodeSink::put*` methods, so the performance impact of the virtual callbacks is less severe.
|
//! `CodeSink::put*` methods, so the performance impact of the virtual callbacks is less severe.
|
||||||
|
|
||||||
use ir::{ExternalName, JumpTable};
|
use ir::{ExternalName, JumpTable};
|
||||||
use super::{CodeSink, CodeOffset, Reloc};
|
use super::{CodeSink, CodeOffset, Reloc, Addend};
|
||||||
use std::ptr::write_unaligned;
|
use std::ptr::write_unaligned;
|
||||||
|
|
||||||
/// A `CodeSink` that writes binary machine code directly into memory.
|
/// A `CodeSink` that writes binary machine code directly into memory.
|
||||||
@@ -52,7 +52,7 @@ pub trait RelocSink {
|
|||||||
fn reloc_ebb(&mut self, CodeOffset, Reloc, CodeOffset);
|
fn reloc_ebb(&mut self, CodeOffset, Reloc, CodeOffset);
|
||||||
|
|
||||||
/// Add a relocation referencing an external symbol at the current offset.
|
/// Add a relocation referencing an external symbol at the current offset.
|
||||||
fn reloc_external(&mut self, CodeOffset, Reloc, &ExternalName);
|
fn reloc_external(&mut self, CodeOffset, Reloc, &ExternalName, Addend);
|
||||||
|
|
||||||
/// Add a relocation referencing a jump table.
|
/// Add a relocation referencing a jump table.
|
||||||
fn reloc_jt(&mut self, CodeOffset, Reloc, JumpTable);
|
fn reloc_jt(&mut self, CodeOffset, Reloc, JumpTable);
|
||||||
@@ -96,9 +96,9 @@ impl<'a> CodeSink for MemoryCodeSink<'a> {
|
|||||||
self.relocs.reloc_ebb(ofs, rel, ebb_offset);
|
self.relocs.reloc_ebb(ofs, rel, ebb_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reloc_external(&mut self, rel: Reloc, name: &ExternalName) {
|
fn reloc_external(&mut self, rel: Reloc, name: &ExternalName, addend: Addend) {
|
||||||
let ofs = self.offset();
|
let ofs = self.offset();
|
||||||
self.relocs.reloc_external(ofs, rel, name);
|
self.relocs.reloc_external(ofs, rel, name, addend);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reloc_jt(&mut self, rel: Reloc, jt: JumpTable) {
|
fn reloc_jt(&mut self, rel: Reloc, jt: JumpTable) {
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ use std::fmt;
|
|||||||
/// depends on the *host* platform, not the *target* platform.
|
/// depends on the *host* platform, not the *target* platform.
|
||||||
pub type CodeOffset = u32;
|
pub type CodeOffset = u32;
|
||||||
|
|
||||||
|
/// Addend to add to the symbol value.
|
||||||
|
pub type Addend = i64;
|
||||||
|
|
||||||
/// Relocation kinds for every ISA
|
/// Relocation kinds for every ISA
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Reloc {
|
pub enum Reloc {
|
||||||
@@ -78,8 +81,8 @@ pub trait CodeSink {
|
|||||||
/// Add a relocation referencing an EBB at the current offset.
|
/// Add a relocation referencing an EBB at the current offset.
|
||||||
fn reloc_ebb(&mut self, Reloc, CodeOffset);
|
fn reloc_ebb(&mut self, Reloc, CodeOffset);
|
||||||
|
|
||||||
/// Add a relocation referencing an external symbol at the current offset.
|
/// Add a relocation referencing an external symbol plus the addend at the current offset.
|
||||||
fn reloc_external(&mut self, Reloc, &ExternalName);
|
fn reloc_external(&mut self, Reloc, &ExternalName, Addend);
|
||||||
|
|
||||||
/// Add a relocation referencing a jump table.
|
/// Add a relocation referencing a jump table.
|
||||||
fn reloc_jt(&mut self, Reloc, JumpTable);
|
fn reloc_jt(&mut self, Reloc, JumpTable);
|
||||||
|
|||||||
Reference in New Issue
Block a user