2024-11-18 18:43:35 +02:00
|
|
|
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)
|
2024-11-18 18:43:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
2024-11-18 18:43:35 +02:00
|
|
|
// 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();
|
|
|
|
debug_trace!("{}@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 {
|
2024-11-18 18:43:35 +02:00
|
|
|
// See make_tlsdesc_relocation()
|
|
|
|
R_AARCH64_TLSDESC => Ok(Some(make_tlsdesc_relocation(false, state, object_id, 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();
|
2024-11-18 18:43:35 +02:00
|
|
|
if s == 0 {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
match self.r_type {
|
2024-11-26 23:02:49 +02:00
|
|
|
// Direct 64 bit: S + A
|
|
|
|
R_AARCH64_ABS64 => {
|
|
|
|
Ok(Some(RelaValue::QWord(s + self.r_addend)))
|
|
|
|
}
|
2024-11-18 18:43:35 +02:00
|
|
|
// Direct 64 bit: S
|
2024-11-26 23:02:49 +02:00
|
|
|
R_AARCH64_JUMP_SLOT | R_AARCH64_GLOB_DAT => {
|
2024-11-18 18:43:35 +02:00
|
|
|
Ok(Some(RelaValue::QWord(s)))
|
|
|
|
}
|
|
|
|
_ => todo!("Unsupported relocation: {}", self.r_type),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|