110 lines
3.6 KiB
Rust
Raw Normal View History

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}");
};
2024-11-19 19:33:08 +02:00
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<Option<Self::Value>, 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<Option<Self::Value>, Error> {
2024-11-19 19:33:08 +02:00
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();
2025-02-19 22:06:29 +02:00
log::debug!("{}@tprel -> {}", name, offset);
Ok(Some(RelaValue::QWord(offset as _)))
}
_ => todo!("Unsupported relocation against TLS symbol: {}", self.r_type),
},
2024-11-19 19:33:08 +02:00
ResolvedSymbol::Null(object_id) => match self.r_type {
// See make_tlsdesc_relocation()
2025-02-19 22:06:29 +02:00
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
),
},
_ => {
2024-11-19 19:33:08 +02:00
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),
}
}
}
}
}