Introduce DataDescription::all_relocs to dedup some code

This commit is contained in:
bjorn3
2020-11-11 12:19:37 +01:00
parent a5501e12a6
commit 1dc27c93a4
3 changed files with 111 additions and 116 deletions

View File

@@ -1,6 +1,6 @@
//! Defines `DataContext`. //! Defines `DataContext`.
use cranelift_codegen::binemit::{Addend, CodeOffset}; use cranelift_codegen::binemit::{Addend, CodeOffset, Reloc};
use cranelift_codegen::entity::PrimaryMap; use cranelift_codegen::entity::PrimaryMap;
use cranelift_codegen::ir; use cranelift_codegen::ir;
use std::borrow::ToOwned; use std::borrow::ToOwned;
@@ -8,6 +8,8 @@ use std::boxed::Box;
use std::string::String; use std::string::String;
use std::vec::Vec; use std::vec::Vec;
use crate::RelocRecord;
/// This specifies how data is to be initialized. /// This specifies how data is to be initialized.
#[derive(PartialEq, Eq, Debug)] #[derive(PartialEq, Eq, Debug)]
pub enum Init { pub enum Init {
@@ -55,6 +57,34 @@ pub struct DataDescription {
pub align: Option<u64>, pub align: Option<u64>,
} }
impl DataDescription {
/// An iterator over all relocations of the data object.
pub fn all_relocs<'a>(
&'a self,
pointer_reloc: Reloc,
) -> impl Iterator<Item = RelocRecord> + 'a {
let func_relocs = self
.function_relocs
.iter()
.map(move |&(offset, id)| RelocRecord {
reloc: pointer_reloc,
offset,
name: self.function_decls[id].clone(),
addend: 0,
});
let data_relocs = self
.data_relocs
.iter()
.map(move |&(offset, id, addend)| RelocRecord {
reloc: pointer_reloc,
offset,
name: self.data_decls[id].clone(),
addend,
});
func_relocs.chain(data_relocs)
}
}
/// This is to data objects what cranelift_codegen::Context is to functions. /// This is to data objects what cranelift_codegen::Context is to functions.
pub struct DataContext { pub struct DataContext {
description: DataDescription, description: DataDescription,

View File

@@ -305,7 +305,10 @@ impl Module for ObjectModule {
}; };
if !relocs.is_empty() { if !relocs.is_empty() {
let relocs = self.process_relocs(relocs); let relocs = relocs
.iter()
.map(|record| self.process_reloc(record))
.collect();
self.relocs.push(SymbolRelocs { self.relocs.push(SymbolRelocs {
section, section,
offset, offset,
@@ -330,40 +333,24 @@ impl Module for ObjectModule {
let &DataDescription { let &DataDescription {
ref init, ref init,
ref function_decls, function_decls: _,
ref data_decls, data_decls: _,
ref function_relocs, function_relocs: _,
ref data_relocs, data_relocs: _,
ref custom_segment_section, ref custom_segment_section,
align, align,
} = data_ctx.description(); } = data_ctx.description();
let reloc_size = match self.isa.triple().pointer_width().unwrap() { let pointer_reloc = match self.isa.triple().pointer_width().unwrap() {
PointerWidth::U16 => 16, PointerWidth::U16 => unimplemented!("16bit pointers"),
PointerWidth::U32 => 32, PointerWidth::U32 => Reloc::Abs4,
PointerWidth::U64 => 64, PointerWidth::U64 => Reloc::Abs8,
}; };
let mut relocs = Vec::new(); let relocs = data_ctx
for &(offset, id) in function_relocs { .description()
relocs.push(ObjectRelocRecord { .all_relocs(pointer_reloc)
offset, .map(|record| self.process_reloc(&record))
name: function_decls[id].clone(), .collect::<Vec<_>>();
kind: RelocationKind::Absolute,
encoding: RelocationEncoding::Generic,
size: reloc_size,
addend: 0,
});
}
for &(offset, id, addend) in data_relocs {
relocs.push(ObjectRelocRecord {
offset,
name: data_decls[id].clone(),
kind: RelocationKind::Absolute,
encoding: RelocationEncoding::Generic,
size: reloc_size,
addend,
});
}
let section = if custom_segment_section.is_none() { let section = if custom_segment_section.is_none() {
let section_kind = if let Init::Zeros { .. } = *init { let section_kind = if let Init::Zeros { .. } = *init {
@@ -510,69 +497,60 @@ impl ObjectModule {
} }
} }
fn process_relocs(&self, relocs: &[RelocRecord]) -> Vec<ObjectRelocRecord> { fn process_reloc(&self, record: &RelocRecord) -> ObjectRelocRecord {
relocs let mut addend = record.addend;
.iter() let (kind, encoding, size) = match record.reloc {
.map(|record| { Reloc::Abs4 => (RelocationKind::Absolute, RelocationEncoding::Generic, 32),
let mut addend = record.addend; Reloc::Abs8 => (RelocationKind::Absolute, RelocationEncoding::Generic, 64),
let (kind, encoding, size) = match record.reloc { Reloc::X86PCRel4 => (RelocationKind::Relative, RelocationEncoding::Generic, 32),
Reloc::Abs4 => (RelocationKind::Absolute, RelocationEncoding::Generic, 32), Reloc::X86CallPCRel4 => (RelocationKind::Relative, RelocationEncoding::X86Branch, 32),
Reloc::Abs8 => (RelocationKind::Absolute, RelocationEncoding::Generic, 64), // TODO: Get Cranelift to tell us when we can use
Reloc::X86PCRel4 => (RelocationKind::Relative, RelocationEncoding::Generic, 32), // R_X86_64_GOTPCRELX/R_X86_64_REX_GOTPCRELX.
Reloc::X86CallPCRel4 => { Reloc::X86CallPLTRel4 => (
(RelocationKind::Relative, RelocationEncoding::X86Branch, 32) RelocationKind::PltRelative,
} RelocationEncoding::X86Branch,
// TODO: Get Cranelift to tell us when we can use 32,
// R_X86_64_GOTPCRELX/R_X86_64_REX_GOTPCRELX. ),
Reloc::X86CallPLTRel4 => ( Reloc::X86GOTPCRel4 => (RelocationKind::GotRelative, RelocationEncoding::Generic, 32),
RelocationKind::PltRelative, Reloc::ElfX86_64TlsGd => {
RelocationEncoding::X86Branch, assert_eq!(
32, self.object.format(),
), object::BinaryFormat::Elf,
Reloc::X86GOTPCRel4 => { "ElfX86_64TlsGd is not supported for this file format"
(RelocationKind::GotRelative, RelocationEncoding::Generic, 32) );
} (
Reloc::ElfX86_64TlsGd => { RelocationKind::Elf(object::elf::R_X86_64_TLSGD),
assert_eq!( RelocationEncoding::Generic,
self.object.format(), 32,
object::BinaryFormat::Elf, )
"ElfX86_64TlsGd is not supported for this file format" }
); Reloc::MachOX86_64Tlv => {
( assert_eq!(
RelocationKind::Elf(object::elf::R_X86_64_TLSGD), self.object.format(),
RelocationEncoding::Generic, object::BinaryFormat::MachO,
32, "MachOX86_64Tlv is not supported for this file format"
) );
} addend += 4; // X86_64_RELOC_TLV has an implicit addend of -4
Reloc::MachOX86_64Tlv => { (
assert_eq!( RelocationKind::MachO {
self.object.format(), value: object::macho::X86_64_RELOC_TLV,
object::BinaryFormat::MachO, relative: true,
"MachOX86_64Tlv is not supported for this file format" },
); RelocationEncoding::Generic,
addend += 4; // X86_64_RELOC_TLV has an implicit addend of -4 32,
( )
RelocationKind::MachO { }
value: object::macho::X86_64_RELOC_TLV, // FIXME
relative: true, _ => unimplemented!(),
}, };
RelocationEncoding::Generic, ObjectRelocRecord {
32, offset: record.offset,
) name: record.name.clone(),
} kind,
// FIXME encoding,
_ => unimplemented!(), size,
}; addend,
ObjectRelocRecord { }
offset: record.offset,
name: record.name.clone(),
kind,
encoding,
size,
addend,
}
})
.collect()
} }
} }

View File

@@ -443,10 +443,10 @@ impl<'simple_jit_backend> Module for SimpleJITModule {
let &DataDescription { let &DataDescription {
ref init, ref init,
ref function_decls, function_decls: _,
ref data_decls, data_decls: _,
ref function_relocs, function_relocs: _,
ref data_relocs, data_relocs: _,
custom_segment_section: _, custom_segment_section: _,
align, align,
} = data.description(); } = data.description();
@@ -477,28 +477,15 @@ impl<'simple_jit_backend> Module for SimpleJITModule {
} }
} }
let reloc = match self.isa.triple().pointer_width().unwrap() { let pointer_reloc = match self.isa.triple().pointer_width().unwrap() {
PointerWidth::U16 => panic!(), PointerWidth::U16 => panic!(),
PointerWidth::U32 => Reloc::Abs4, PointerWidth::U32 => Reloc::Abs4,
PointerWidth::U64 => Reloc::Abs8, PointerWidth::U64 => Reloc::Abs8,
}; };
let mut relocs = Vec::new(); let relocs = data
for &(offset, id) in function_relocs { .description()
relocs.push(RelocRecord { .all_relocs(pointer_reloc)
reloc, .collect::<Vec<_>>();
offset,
name: function_decls[id].clone(),
addend: 0,
});
}
for &(offset, id, addend) in data_relocs {
relocs.push(RelocRecord {
reloc,
offset,
name: data_decls[id].clone(),
addend,
});
}
self.compiled_data_objects[id] = Some(CompiledBlob { ptr, size, relocs }); self.compiled_data_objects[id] = Some(CompiledBlob { ptr, size, relocs });
self.data_objects_to_finalize.push(id); self.data_objects_to_finalize.push(id);