use crate::elf::{
ElfDynamic, ElfDynamicHashTab, ElfLayout, ElfSymbol, SymbolTable, symbol::SymbolInfo,
};
#[cfg(feature = "object")]
use crate::object::CustomHash;
use core::fmt::Debug;
use gnu::ElfGnuHash;
use sysv::ElfHash;
mod gnu;
mod sysv;
mod traits;
pub(crate) use traits::ElfHashTable;
pub(crate) enum HashTable {
Gnu(ElfGnuHash),
Elf(ElfHash),
#[cfg(feature = "object")]
Custom(CustomHash),
}
impl Debug for HashTable {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
HashTable::Gnu(_) => write!(f, "GnuHash"),
HashTable::Elf(_) => write!(f, "ElfHash"),
#[cfg(feature = "object")]
HashTable::Custom(_) => write!(f, "CustomHash"),
}
}
}
pub struct PreCompute {
gnuhash: u32,
hash: Option<u32>,
#[cfg(feature = "object")]
pub(crate) custom: Option<u64>,
}
impl HashTable {
#[inline]
#[allow(dead_code)]
pub(crate) fn count_syms(&self) -> usize {
match &self {
HashTable::Gnu(hashtab) => hashtab.count_syms(),
HashTable::Elf(hashtab) => hashtab.count_syms(),
#[cfg(feature = "object")]
HashTable::Custom(hashtab) => hashtab.count_syms(),
}
}
pub(crate) fn lookup<'sym, L>(
&self,
table: &'sym SymbolTable<L>,
symbol: &SymbolInfo,
precompute: &mut PreCompute,
) -> Option<&'sym ElfSymbol<L>>
where
L: ElfLayout,
{
match self {
HashTable::Gnu(_) => ElfGnuHash::lookup(table, symbol, precompute),
HashTable::Elf(_) => ElfHash::lookup(table, symbol, precompute),
#[cfg(feature = "object")]
HashTable::Custom(_) => CustomHash::lookup(table, symbol, precompute),
}
}
pub(crate) fn from_dynamic<Arch>(dynamic: &ElfDynamic<Arch>) -> Self
where
Arch: crate::relocation::RelocationArch,
{
match dynamic.hashtab {
ElfDynamicHashTab::Gnu(off) => {
HashTable::Gnu(ElfGnuHash::parse::<Arch::Layout>(off as *const u8))
}
ElfDynamicHashTab::Elf(off) => HashTable::Elf(ElfHash::parse(off as *const u8)),
}
}
fn into_gnuhash(&self) -> Option<&ElfGnuHash> {
match self {
HashTable::Gnu(hashtab) => Some(hashtab),
_ => None,
}
}
fn into_elfhash(&self) -> Option<&ElfHash> {
match self {
HashTable::Elf(hashtab) => Some(hashtab),
_ => None,
}
}
}
impl SymbolInfo<'_> {
#[inline]
pub fn precompute(&self) -> PreCompute {
let gnuhash = ElfGnuHash::hash(self.name().as_bytes()) as u32;
PreCompute {
gnuhash,
hash: None,
#[cfg(feature = "object")]
custom: None,
}
}
}