use elf::{ abi::{ R_AARCH64_ABS64, R_AARCH64_GLOB_DAT, R_AARCH64_JUMP_SLOT, R_AARCH64_RELATIVE, R_AARCH64_TLSDESC, R_AARCH64_TLS_TPREL, }, relocation::{Rel, Rela}, }; use crate::{builtins, error::Error, object::ResolvedSymbol, state::State}; use super::{RelValue, RelaValue, Relocation}; // Descriptor method of TLS access: // * For static access: // [0]: resolver function pointer // [1]: fixed offset of the variable with the TLS area // * For dynamic, TODO fn make_tlsdesc_relocation( dynamic: bool, state: &State, module_id: u32, symbol_offset: usize, ) -> RelaValue { if dynamic { todo!("Dynamic TLSDESC relocations are not yet supported") } let layout = state .tls_layout .as_ref() .expect("TLSDESC relocation, but no TLS segments in linked objects"); let Some(offset) = layout.offset(module_id, symbol_offset) else { panic!("TLSDESC relocation against unknown module_id={module_id}, offset={symbol_offset}"); }; let resolver = builtins::tlsdesc_resolve_static as usize; RelaValue::DQWord(resolver as i64, offset as i64) } impl Relocation for Rel { type Value = RelValue; fn resolve( &self, _state: &State, _name: &str, _symbol: &ResolvedSymbol, _load_base: usize, ) -> Result, Error> { unimplemented!("rel-type relocations are not implemented for aarch64") } } impl Relocation for Rela { type Value = RelaValue; fn resolve( &self, state: &State, name: &str, symbol: &ResolvedSymbol, load_base: usize, ) -> Result, Error> { match *symbol { ResolvedSymbol::Tls(tls) => match self.r_type { // See make_tlsdesc_relocation() R_AARCH64_TLSDESC => Ok(Some(make_tlsdesc_relocation( false, state, tls.module_id, tls.offset, ))), R_AARCH64_TLS_TPREL => { let layout = state.tls_layout.as_ref().unwrap(); let offset = layout.offset(tls.module_id, tls.offset).unwrap(); log::debug!("{}@tprel -> {}", name, offset); Ok(Some(RelaValue::QWord(offset as _))) } _ => todo!("Unsupported relocation against TLS symbol: {}", self.r_type), }, ResolvedSymbol::Null(object_id) => match self.r_type { // See make_tlsdesc_relocation() R_AARCH64_TLSDESC => Ok(Some(make_tlsdesc_relocation(false, state, object_id + 1, 0))), // B + A R_AARCH64_RELATIVE => Ok(Some(RelaValue::QWord(load_base as i64 + self.r_addend))), _ => todo!( "Unsupported relocation against NULL symbol: {}", self.r_type ), }, _ => { let s = symbol.value(); if s == 0 { todo!() } match self.r_type { // Direct 64 bit: S + A R_AARCH64_ABS64 => { Ok(Some(RelaValue::QWord(s + self.r_addend))) } // Direct 64 bit: S R_AARCH64_JUMP_SLOT | R_AARCH64_GLOB_DAT => { Ok(Some(RelaValue::QWord(s))) } _ => todo!("Unsupported relocation: {}", self.r_type), } } } } }