use crate::{
container::Container,
demangle::modpath::{self, ModulePath},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum InitKind {
Init,
DatInit,
HcrInit,
}
#[derive(Debug, Clone)]
pub struct InitFunction<'a> {
pub kind: InitKind,
pub symbol_name: &'a str,
pub address: u64,
pub module_path: ModulePath,
}
const INIT_SUFFIXES: &[(&str, InitKind)] = &[
("HcrInit000", InitKind::HcrInit),
("DatInit000", InitKind::DatInit),
("Init000", InitKind::Init),
];
pub fn scan<'a>(container: &'a Container<'a>) -> Vec<InitFunction<'a>> {
let mut result = Vec::new();
for sym in container.symbols() {
let name = sym.name.as_ref();
if name.contains(".cold.") || name.contains(".TM_") || name.contains(".part.") {
continue;
}
for &(suffix, kind) in INIT_SUFFIXES {
if let Some(module_part) = name.strip_suffix(suffix) {
if module_part.is_empty() || module_part.ends_with("NimMain") {
continue;
}
let module_path = modpath::decode(module_part);
result.push(InitFunction {
kind,
symbol_name: name,
address: sym.vm_addr,
module_path,
});
break;
}
}
}
result
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn init_kind_eq() {
assert_eq!(InitKind::Init, InitKind::Init);
assert_ne!(InitKind::Init, InitKind::DatInit);
}
}