use crate::{arch::NativeArch, relocation::RelocationArch};
use super::{
layout::{ElfLayout, NativeElfLayout},
raw::{ElfRelRaw, ElfRelaRaw, ElfWord},
types::{ElfRelocationType, ElfSectionType},
};
#[repr(transparent)]
pub struct ElfRelr<L: ElfLayout = NativeElfLayout> {
relr: L::Relr,
}
impl<L: ElfLayout> ElfRelr<L> {
#[inline]
pub fn value(&self) -> usize {
self.relr.to_usize()
}
}
#[repr(transparent)]
pub struct ElfRela<L: ElfLayout = NativeElfLayout> {
rela: L::Rela,
}
impl<L: ElfLayout> ElfRela<L> {
#[inline]
pub fn r_type(&self) -> ElfRelocationType {
ElfRelocationType::new((self.rela.r_info() & L::REL_MASK) as u32)
}
#[inline]
pub fn r_symbol(&self) -> usize {
self.rela.r_info() >> L::REL_BIT
}
#[inline]
pub fn r_offset(&self) -> usize {
self.rela.r_offset()
}
#[inline]
pub fn r_addend(&self, _base: usize) -> isize {
self.rela.r_addend()
}
#[inline]
pub(crate) fn set_offset(&mut self, offset: usize) {
self.rela.set_r_offset(offset);
}
#[inline]
pub(crate) fn set_addend(&mut self, _base: usize, addend: isize) {
self.rela.set_r_addend(addend);
}
}
#[repr(transparent)]
pub struct ElfRel<L: ElfLayout = NativeElfLayout> {
rel: L::Rel,
}
impl<L: ElfLayout> ElfRel<L> {
#[inline]
pub fn r_type(&self) -> ElfRelocationType {
ElfRelocationType::new((self.rel.r_info() & L::REL_MASK) as u32)
}
#[inline]
pub fn r_symbol(&self) -> usize {
self.rel.r_info() >> L::REL_BIT
}
#[inline]
pub fn r_offset(&self) -> usize {
self.rel.r_offset()
}
#[inline]
pub fn r_addend(&self, base: usize) -> isize {
let ptr = (self.r_offset() + base) as *const L::Word;
unsafe { ptr.read_unaligned().to_usize() as isize }
}
#[inline]
pub(crate) fn set_offset(&mut self, offset: usize) {
self.rel.set_r_offset(offset);
}
#[inline]
#[allow(dead_code)]
pub(crate) fn set_addend(&mut self, base: usize, addend: isize) {
let ptr = (self.r_offset() + base) as *mut L::Word;
unsafe { ptr.write_unaligned(L::Word::from_usize(addend as usize)) };
}
}
pub trait ElfRelEntry<L: ElfLayout = NativeElfLayout> {
const SECTION_TYPE: ElfSectionType;
const HAS_IMPLICIT_ADDEND: bool;
fn r_type(&self) -> ElfRelocationType;
fn r_symbol(&self) -> usize;
fn r_offset(&self) -> usize;
fn r_addend(&self, base: usize) -> isize;
fn set_offset(&mut self, offset: usize);
fn set_addend(&mut self, base: usize, addend: isize);
}
impl<L: ElfLayout> ElfRelEntry<L> for ElfRela<L> {
const SECTION_TYPE: ElfSectionType = ElfSectionType::RELA;
const HAS_IMPLICIT_ADDEND: bool = false;
#[inline]
fn r_type(&self) -> ElfRelocationType {
self.r_type()
}
#[inline]
fn r_symbol(&self) -> usize {
self.r_symbol()
}
#[inline]
fn r_offset(&self) -> usize {
self.r_offset()
}
#[inline]
fn r_addend(&self, base: usize) -> isize {
self.r_addend(base)
}
#[inline]
fn set_offset(&mut self, offset: usize) {
self.set_offset(offset);
}
#[inline]
fn set_addend(&mut self, base: usize, addend: isize) {
self.set_addend(base, addend);
}
}
impl<L: ElfLayout> ElfRelEntry<L> for ElfRel<L> {
const SECTION_TYPE: ElfSectionType = ElfSectionType::REL;
const HAS_IMPLICIT_ADDEND: bool = true;
#[inline]
fn r_type(&self) -> ElfRelocationType {
self.r_type()
}
#[inline]
fn r_symbol(&self) -> usize {
self.r_symbol()
}
#[inline]
fn r_offset(&self) -> usize {
self.r_offset()
}
#[inline]
fn r_addend(&self, base: usize) -> isize {
self.r_addend(base)
}
#[inline]
fn set_offset(&mut self, offset: usize) {
self.set_offset(offset);
}
#[inline]
fn set_addend(&mut self, base: usize, addend: isize) {
self.set_addend(base, addend);
}
}
pub type ElfRelType<Arch = NativeArch> = <Arch as RelocationArch>::Relocation;