use std::marker::PhantomData;
use std::pin::Pin;
use crate::common::{AsFFI, FromFFI, into_optional};
use crate::declare_iterator;
use crate::generic;
use lief_ffi as ffi;
use super::commands::Dylib;
use super::{BindingInfo, ExportInfo};
pub struct Symbol<'a> {
ptr: cxx::UniquePtr<ffi::MachO_Symbol>,
_owner: PhantomData<&'a ()>,
}
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Category {
NONE,
LOCAL,
EXTERNAL,
UNDEFINED,
INDIRECT_ABS,
INDIRECT_LOCAL,
INDIRECT_ABS_LOCAL,
UNKNOWN(u32),
}
impl From<u32> for Category {
fn from(value: u32) -> Self {
match value {
0x00000000 => Category::NONE,
0x00000001 => Category::LOCAL,
0x00000002 => Category::EXTERNAL,
0x00000003 => Category::UNDEFINED,
0x00000004 => Category::INDIRECT_ABS,
0x00000005 => Category::INDIRECT_LOCAL,
0x00000006 => Category::INDIRECT_ABS_LOCAL,
_ => Category::UNKNOWN(value),
}
}
}
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Origin {
DYLD_EXPORT,
DYLD_BIND,
LC_SYMTAB,
UNKNOWN(u32),
}
impl From<u32> for Origin {
fn from(value: u32) -> Self {
match value {
0x00000001 => Origin::DYLD_EXPORT,
0x00000002 => Origin::DYLD_BIND,
0x00000003 => Origin::LC_SYMTAB,
_ => Origin::UNKNOWN(value),
}
}
}
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Type {
UNDEFINED,
ABSOLUTE_SYM,
SECTION,
PREBOUND,
INDIRECT,
UNKNOWN(u32),
}
impl From<u32> for Type {
fn from(value: u32) -> Self {
match value {
0x0 => Type::UNDEFINED,
0x2 => Type::ABSOLUTE_SYM,
0xe => Type::SECTION,
0xc => Type::PREBOUND,
0xa => Type::INDIRECT,
_ => Type::UNKNOWN(value),
}
}
}
impl From<Type> for u32 {
fn from(value: Type) -> u32 {
match value {
Type::UNDEFINED => 0x0,
Type::ABSOLUTE_SYM => 0x2,
Type::SECTION => 0xe,
Type::PREBOUND => 0xc,
Type::INDIRECT => 0xa,
Type::UNKNOWN(v) => v,
}
}
}
impl Symbol<'_> {
pub fn get_type(&self) -> u8 {
self.ptr.get_type()
}
pub fn numberof_sections(&self) -> u8 {
self.ptr.numberof_sections()
}
pub fn description(&self) -> u16 {
self.ptr.description()
}
pub fn origin(&self) -> Origin {
Origin::from(self.ptr.origin())
}
pub fn category(&self) -> Category {
Category::from(self.ptr.category())
}
pub fn export_info(&self) -> Option<ExportInfo<'_>> {
into_optional(self.ptr.export_info())
}
pub fn binding_info(&self) -> Option<BindingInfo<'_>> {
into_optional(self.ptr.binding_info())
}
pub fn library(&self) -> Option<Dylib<'_>> {
into_optional(self.ptr.library())
}
pub fn is_external(&self) -> bool {
self.ptr.is_external()
}
pub fn library_ordinal(&self) -> i32 {
self.ptr.library_ordinal()
}
pub fn demangled_name(&self) -> String {
self.ptr.demangled_name().to_string()
}
}
impl std::fmt::Debug for Symbol<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let base = self as &dyn generic::Symbol;
f.debug_struct("Symbol")
.field("base", &base)
.field("type", &self.get_type())
.field("numberof_sections", &self.numberof_sections())
.field("description", &self.description())
.field("origin", &self.origin())
.field("category", &self.category())
.field("export_info", &self.export_info())
.field("binding_info", &self.binding_info())
.field("library", &self.library())
.finish()
}
}
impl<'a> FromFFI<ffi::MachO_Symbol> for Symbol<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_Symbol>) -> Self {
Self {
ptr,
_owner: PhantomData,
}
}
}
impl AsFFI<ffi::MachO_Symbol> for Symbol<'_> {
fn as_ffi(&self) -> &ffi::MachO_Symbol {
self.ptr.as_ref().unwrap()
}
fn as_mut_ffi(&mut self) -> Pin<&mut ffi::MachO_Symbol> {
self.ptr.pin_mut()
}
}
impl generic::Symbol for Symbol<'_> {
fn as_generic(&self) -> &ffi::AbstractSymbol {
self.ptr.as_ref().unwrap().as_ref()
}
fn as_pin_mut_generic(&mut self) -> Pin<&mut ffi::AbstractSymbol> {
unsafe {
Pin::new_unchecked({
(self.ptr.as_ref().unwrap().as_ref() as *const ffi::AbstractSymbol
as *mut ffi::AbstractSymbol)
.as_mut()
.unwrap()
})
}
}
}
declare_iterator!(
Symbols,
Symbol<'a>,
ffi::MachO_Symbol,
ffi::MachO_Binary,
ffi::MachO_Binary_it_symbols
);
declare_iterator!(
ExportedSymbols,
Symbol<'a>,
ffi::MachO_Symbol,
ffi::MachO_Binary,
ffi::MachO_Binary_it_exported_symbols
);