/// A table of symbol entries in a Mach-O file. /// /// Also includes the string table used for the symbol names. /// /// Returned by [`macho::SymtabCommand::symbols`]. #[derive(Debug, Clone, Copy)] pubstruct SymbolTable<'data, Mach: MachHeader, R = &'data [u8]> where
R: ReadRef<'data>,
{
symbols: &'data [Mach::Nlist],
strings: StringTable<'data, R>,
}
/// Return the string table used for the symbol names. #[inline] pubfn strings(&self) -> StringTable<'data, R> { self.strings
}
/// Iterate over the symbols. #[inline] pubfn iter(&self) -> slice::Iter<'data, Mach::Nlist> { self.symbols.iter()
}
/// Return true if the symbol table is empty. #[inline] pubfn is_empty(&self) -> bool { self.symbols.is_empty()
}
/// The number of symbols. #[inline] pubfn len(&self) -> usize { self.symbols.len()
}
/// Return the symbol at the given index. pubfn symbol(&self, index: SymbolIndex) -> Result<&'data Mach::Nlist> { self.symbols
.get(index.0)
.read_error("Invalid Mach-O symbol index")
}
/// Construct a map from addresses to a user-defined map entry. pubfn map<Entry: SymbolMapEntry, F: Fn(&'data Mach::Nlist) -> Option<Entry>>(
&self,
f: F,
) -> SymbolMap<Entry> { letmut symbols = Vec::new(); for nlist inself.symbols { if !nlist.is_definition() { continue;
} iflet Some(entry) = f(nlist) {
symbols.push(entry);
}
}
SymbolMap::new(symbols)
}
/// Construct a map from addresses to symbol names and object file names. pubfn object_map(&self, endian: Mach::Endian) -> ObjectMap<'data> { letmut symbols = Vec::new(); letmut objects = Vec::new(); letmut object = None; letmut current_function = None; // Each module starts with one or two N_SO symbols (path, or directory + filename) // and one N_OSO symbol. The module is terminated by an empty N_SO symbol. for nlist inself.symbols { let n_type = nlist.n_type(); if n_type & macho::N_STAB == 0 { continue;
} // TODO: includes variables too (N_GSYM, N_STSYM). These may need to get their // address from regular symbols though. match n_type {
macho::N_SO => {
object = None;
}
macho::N_OSO => {
object = None; iflet Ok(name) = nlist.name(endian, self.strings) { if !name.is_empty() {
object = Some(objects.len()); // `N_OSO` symbol names can be either `/path/to/object.o` // or `/path/to/archive.a(object.o)`. let (path, member) = name
.split_last()
.and_then(|(last, head)| { if *last != b')' { return None;
} let index = head.iter().position(|&x| x == b'(')?; let (archive, rest) = head.split_at(index);
Some((archive, Some(&rest[1..])))
})
.unwrap_or((name, None));
objects.push(ObjectMapFile::new(path, member));
}
}
}
macho::N_FUN => { iflet Ok(name) = nlist.name(endian, self.strings) { if !name.is_empty() {
current_function = Some((name, nlist.n_value(endian).into()))
} elseiflet Some((name, address)) = current_function.take() { iflet Some(object) = object {
symbols.push(ObjectMapEntry {
address,
size: nlist.n_value(endian).into(),
name,
object,
});
}
}
}
}
_ => {}
}
}
ObjectMap {
symbols: SymbolMap::new(symbols),
objects,
}
}
}
/// A symbol table in a [`MachOFile32`](super::MachOFile32). pubtype MachOSymbolTable32<'data, 'file, Endian = Endianness, R = &>'data [u8]> =
MachOSymbolTable<'data, 'file, macho::MachHeader32<Endian>, R>; /// A symbol table in a [`MachOFile64`](super::MachOFile64). pubtype MachOSymbolTable64<'data, 'file, Endian = Endianness, R = &>'data [u8]> =
MachOSymbolTable<'data, 'file, macho::MachHeader64<Endian>, R>;
/// A symbol table in a [`MachOFile`]. #[derive(Debug, Clone, Copy)] pubstruct MachOSymbolTable<'data, 'file, Mach, R = &'data [u8]> where
Mach: MachHeader,
R: ReadRef<'data>,
{ pub(super) file: &'file MachOFile<'data, Mach, R>,
}
impl<'data, 'file, Mach, R> read::private::Sealed for MachOSymbolTable<'data, 'file, Mach, R> where
Mach: MachHeader,
R: ReadRef<'data>,
{
}
impl<'data, 'file, Mach, R> ObjectSymbolTable<'data> for MachOSymbolTable<'data, 'file, Mach, R> where
Mach: MachHeader,
R: ReadRef<'data>,
{ type Symbol = MachOSymbol<'data, 'file, Mach, R>; type SymbolIterator = MachOSymbolIterator<'data, 'file, Mach, R>;
fn symbol_by_index(&self, index: SymbolIndex) -> Result<Self::Symbol> { let nlist = self.file.symbols.symbol(index)?;
MachOSymbol::new(self.file, index, nlist).read_error("Unsupported Mach-O symbol index")
}
}
/// An iterator for the symbols in a [`MachOFile32`](super::MachOFile32). pubtype MachOSymbolIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
MachOSymbolIterator<'data, 'file, macho::MachHeader32<Endian>, R>; /// An iterator for the symbols in a [`MachOFile64`](super::MachOFile64). pubtype MachOSymbolIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
MachOSymbolIterator<'data, 'file, macho::MachHeader64<Endian>, R>;
/// An iterator for the symbols in a [`MachOFile`]. pubstruct MachOSymbolIterator<'data, 'file, Mach, R = &'data [u8]> where
Mach: MachHeader,
R: ReadRef<'data>,
{
file: &'file MachOFile<'data, Mach, R>,
index: SymbolIndex,
}
/// A symbol in a [`MachOFile32`](super::MachOFile32). pubtype MachOSymbol32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
MachOSymbol<'data, 'file, macho::MachHeader32<Endian>, R>; /// A symbol in a [`MachOFile64`](super::MachOFile64). pubtype MachOSymbol64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
MachOSymbol<'data, 'file, macho::MachHeader64<Endian>, R>;
/// A symbol in a [`MachOFile`]. /// /// Most functionality is provided by the [`ObjectSymbol`] trait implementation. #[derive(Debug, Clone, Copy)] pubstruct MachOSymbol<'data, 'file, Mach, R = &'data [u8]> where
Mach: MachHeader,
R: ReadRef<'data>,
{
file: &'file MachOFile<'data, Mach, R>,
index: SymbolIndex,
nlist: &'data Mach::Nlist,
}
/// A trait for generic access to [`macho::Nlist32`] and [`macho::Nlist64`]. #[allow(missing_docs)] pubtrait Nlist: Debug + Pod { type Word: Into<u64>; type Endian: endian::Endian;
/// Return true if this is a STAB symbol. /// /// This determines the meaning of the `n_type` field. fn is_stab(&self) -> bool { self.n_type() & macho::N_STAB != 0
}
/// Return true if this is an undefined symbol. fn is_undefined(&self) -> bool { let n_type = self.n_type();
n_type & macho::N_STAB == 0 && n_type & macho::N_TYPE == macho::N_UNDF
}
/// Return true if the symbol is a definition of a function or data object. fn is_definition(&self) -> bool { let n_type = self.n_type();
n_type & macho::N_STAB == 0 && n_type & macho::N_TYPE == macho::N_SECT
}
/// Return the library ordinal. /// /// This is either a 1-based index into the dylib load commands, /// or a special ordinal. #[inline] fn library_ordinal(&self, endian: Self::Endian) -> u8 {
(self.n_desc(endian) >> 8) as u8
}
}
impl<Endian: endian::Endian> Nlist for macho::Nlist32<Endian> { type Word = u32; type Endian = Endian;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.