aboutsummaryrefslogtreecommitdiff
path: root/vendor/object/src/read/macho/symbol.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/object/src/read/macho/symbol.rs')
-rw-r--r--vendor/object/src/read/macho/symbol.rs492
1 files changed, 0 insertions, 492 deletions
diff --git a/vendor/object/src/read/macho/symbol.rs b/vendor/object/src/read/macho/symbol.rs
deleted file mode 100644
index 434361f..0000000
--- a/vendor/object/src/read/macho/symbol.rs
+++ /dev/null
@@ -1,492 +0,0 @@
-use alloc::vec::Vec;
-use core::fmt::Debug;
-use core::{fmt, slice, str};
-
-use crate::endian::{self, Endianness};
-use crate::macho;
-use crate::pod::Pod;
-use crate::read::util::StringTable;
-use crate::read::{
- self, ObjectMap, ObjectMapEntry, ObjectSymbol, ObjectSymbolTable, ReadError, ReadRef, Result,
- SectionIndex, SectionKind, SymbolFlags, SymbolIndex, SymbolKind, SymbolMap, SymbolMapEntry,
- SymbolScope, SymbolSection,
-};
-
-use super::{MachHeader, MachOFile};
-
-/// 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)]
-pub struct SymbolTable<'data, Mach: MachHeader, R = &'data [u8]>
-where
- R: ReadRef<'data>,
-{
- symbols: &'data [Mach::Nlist],
- strings: StringTable<'data, R>,
-}
-
-impl<'data, Mach: MachHeader, R: ReadRef<'data>> Default for SymbolTable<'data, Mach, R> {
- fn default() -> Self {
- SymbolTable {
- symbols: &[],
- strings: Default::default(),
- }
- }
-}
-
-impl<'data, Mach: MachHeader, R: ReadRef<'data>> SymbolTable<'data, Mach, R> {
- #[inline]
- pub(super) fn new(symbols: &'data [Mach::Nlist], strings: StringTable<'data, R>) -> Self {
- SymbolTable { symbols, strings }
- }
-
- /// Return the string table used for the symbol names.
- #[inline]
- pub fn strings(&self) -> StringTable<'data, R> {
- self.strings
- }
-
- /// Iterate over the symbols.
- #[inline]
- pub fn iter(&self) -> slice::Iter<'data, Mach::Nlist> {
- self.symbols.iter()
- }
-
- /// Return true if the symbol table is empty.
- #[inline]
- pub fn is_empty(&self) -> bool {
- self.symbols.is_empty()
- }
-
- /// The number of symbols.
- #[inline]
- pub fn len(&self) -> usize {
- self.symbols.len()
- }
-
- /// Return the symbol at the given index.
- pub fn symbol(&self, index: usize) -> Result<&'data Mach::Nlist> {
- self.symbols
- .get(index)
- .read_error("Invalid Mach-O symbol index")
- }
-
- /// Construct a map from addresses to a user-defined map entry.
- pub fn map<Entry: SymbolMapEntry, F: Fn(&'data Mach::Nlist) -> Option<Entry>>(
- &self,
- f: F,
- ) -> SymbolMap<Entry> {
- let mut symbols = Vec::new();
- for nlist in self.symbols {
- if !nlist.is_definition() {
- continue;
- }
- if let Some(entry) = f(nlist) {
- symbols.push(entry);
- }
- }
- SymbolMap::new(symbols)
- }
-
- /// Construct a map from addresses to symbol names and object file names.
- pub fn object_map(&self, endian: Mach::Endian) -> ObjectMap<'data> {
- let mut symbols = Vec::new();
- let mut objects = Vec::new();
- let mut object = None;
- let mut 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 in self.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;
- if let Ok(name) = nlist.name(endian, self.strings) {
- if !name.is_empty() {
- object = Some(objects.len());
- objects.push(name);
- }
- }
- }
- macho::N_FUN => {
- if let Ok(name) = nlist.name(endian, self.strings) {
- if !name.is_empty() {
- current_function = Some((name, nlist.n_value(endian).into()))
- } else if let Some((name, address)) = current_function.take() {
- if let 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).
-pub type MachOSymbolTable32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- MachOSymbolTable<'data, 'file, macho::MachHeader32<Endian>, R>;
-/// A symbol table in a [`MachOFile64`](super::MachOFile64).
-pub type 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)]
-pub struct 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 symbols(&self) -> Self::SymbolIterator {
- MachOSymbolIterator {
- file: self.file,
- index: 0,
- }
- }
-
- fn symbol_by_index(&self, index: SymbolIndex) -> Result<Self::Symbol> {
- let nlist = self.file.symbols.symbol(index.0)?;
- MachOSymbol::new(self.file, index, nlist).read_error("Unsupported Mach-O symbol index")
- }
-}
-
-/// An iterator for the symbols in a [`MachOFile32`](super::MachOFile32).
-pub type 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).
-pub type MachOSymbolIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- MachOSymbolIterator<'data, 'file, macho::MachHeader64<Endian>, R>;
-
-/// An iterator for the symbols in a [`MachOFile`].
-pub struct MachOSymbolIterator<'data, 'file, Mach, R = &'data [u8]>
-where
- Mach: MachHeader,
- R: ReadRef<'data>,
-{
- pub(super) file: &'file MachOFile<'data, Mach, R>,
- pub(super) index: usize,
-}
-
-impl<'data, 'file, Mach, R> fmt::Debug for MachOSymbolIterator<'data, 'file, Mach, R>
-where
- Mach: MachHeader,
- R: ReadRef<'data>,
-{
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("MachOSymbolIterator").finish()
- }
-}
-
-impl<'data, 'file, Mach, R> Iterator for MachOSymbolIterator<'data, 'file, Mach, R>
-where
- Mach: MachHeader,
- R: ReadRef<'data>,
-{
- type Item = MachOSymbol<'data, 'file, Mach, R>;
-
- fn next(&mut self) -> Option<Self::Item> {
- loop {
- let index = self.index;
- let nlist = self.file.symbols.symbols.get(index)?;
- self.index += 1;
- if let Some(symbol) = MachOSymbol::new(self.file, SymbolIndex(index), nlist) {
- return Some(symbol);
- }
- }
- }
-}
-
-/// A symbol in a [`MachOFile32`](super::MachOFile32).
-pub type MachOSymbol32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
- MachOSymbol<'data, 'file, macho::MachHeader32<Endian>, R>;
-/// A symbol in a [`MachOFile64`](super::MachOFile64).
-pub type 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)]
-pub struct 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,
-}
-
-impl<'data, 'file, Mach, R> MachOSymbol<'data, 'file, Mach, R>
-where
- Mach: MachHeader,
- R: ReadRef<'data>,
-{
- pub(super) fn new(
- file: &'file MachOFile<'data, Mach, R>,
- index: SymbolIndex,
- nlist: &'data Mach::Nlist,
- ) -> Option<Self> {
- if nlist.n_type() & macho::N_STAB != 0 {
- return None;
- }
- Some(MachOSymbol { file, index, nlist })
- }
-}
-
-impl<'data, 'file, Mach, R> read::private::Sealed for MachOSymbol<'data, 'file, Mach, R>
-where
- Mach: MachHeader,
- R: ReadRef<'data>,
-{
-}
-
-impl<'data, 'file, Mach, R> ObjectSymbol<'data> for MachOSymbol<'data, 'file, Mach, R>
-where
- Mach: MachHeader,
- R: ReadRef<'data>,
-{
- #[inline]
- fn index(&self) -> SymbolIndex {
- self.index
- }
-
- fn name_bytes(&self) -> Result<&'data [u8]> {
- self.nlist.name(self.file.endian, self.file.symbols.strings)
- }
-
- fn name(&self) -> Result<&'data str> {
- let name = self.name_bytes()?;
- str::from_utf8(name)
- .ok()
- .read_error("Non UTF-8 Mach-O symbol name")
- }
-
- #[inline]
- fn address(&self) -> u64 {
- self.nlist.n_value(self.file.endian).into()
- }
-
- #[inline]
- fn size(&self) -> u64 {
- 0
- }
-
- fn kind(&self) -> SymbolKind {
- self.section()
- .index()
- .and_then(|index| self.file.section_internal(index).ok())
- .map(|section| match section.kind {
- SectionKind::Text => SymbolKind::Text,
- SectionKind::Data
- | SectionKind::ReadOnlyData
- | SectionKind::ReadOnlyString
- | SectionKind::UninitializedData
- | SectionKind::Common => SymbolKind::Data,
- SectionKind::Tls | SectionKind::UninitializedTls | SectionKind::TlsVariables => {
- SymbolKind::Tls
- }
- _ => SymbolKind::Unknown,
- })
- .unwrap_or(SymbolKind::Unknown)
- }
-
- fn section(&self) -> SymbolSection {
- match self.nlist.n_type() & macho::N_TYPE {
- macho::N_UNDF => SymbolSection::Undefined,
- macho::N_ABS => SymbolSection::Absolute,
- macho::N_SECT => {
- let n_sect = self.nlist.n_sect();
- if n_sect != 0 {
- SymbolSection::Section(SectionIndex(n_sect as usize))
- } else {
- SymbolSection::Unknown
- }
- }
- _ => SymbolSection::Unknown,
- }
- }
-
- #[inline]
- fn is_undefined(&self) -> bool {
- self.nlist.n_type() & macho::N_TYPE == macho::N_UNDF
- }
-
- #[inline]
- fn is_definition(&self) -> bool {
- self.nlist.is_definition()
- }
-
- #[inline]
- fn is_common(&self) -> bool {
- // Mach-O common symbols are based on section, not symbol
- false
- }
-
- #[inline]
- fn is_weak(&self) -> bool {
- self.nlist.n_desc(self.file.endian) & (macho::N_WEAK_REF | macho::N_WEAK_DEF) != 0
- }
-
- fn scope(&self) -> SymbolScope {
- let n_type = self.nlist.n_type();
- if n_type & macho::N_TYPE == macho::N_UNDF {
- SymbolScope::Unknown
- } else if n_type & macho::N_EXT == 0 {
- SymbolScope::Compilation
- } else if n_type & macho::N_PEXT != 0 {
- SymbolScope::Linkage
- } else {
- SymbolScope::Dynamic
- }
- }
-
- #[inline]
- fn is_global(&self) -> bool {
- self.scope() != SymbolScope::Compilation
- }
-
- #[inline]
- fn is_local(&self) -> bool {
- self.scope() == SymbolScope::Compilation
- }
-
- #[inline]
- fn flags(&self) -> SymbolFlags<SectionIndex, SymbolIndex> {
- let n_desc = self.nlist.n_desc(self.file.endian);
- SymbolFlags::MachO { n_desc }
- }
-}
-
-/// A trait for generic access to [`macho::Nlist32`] and [`macho::Nlist64`].
-#[allow(missing_docs)]
-pub trait Nlist: Debug + Pod {
- type Word: Into<u64>;
- type Endian: endian::Endian;
-
- fn n_strx(&self, endian: Self::Endian) -> u32;
- fn n_type(&self) -> u8;
- fn n_sect(&self) -> u8;
- fn n_desc(&self, endian: Self::Endian) -> u16;
- fn n_value(&self, endian: Self::Endian) -> Self::Word;
-
- fn name<'data, R: ReadRef<'data>>(
- &self,
- endian: Self::Endian,
- strings: StringTable<'data, R>,
- ) -> Result<&'data [u8]> {
- strings
- .get(self.n_strx(endian))
- .read_error("Invalid Mach-O symbol name offset")
- }
-
- /// 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;
-
- fn n_strx(&self, endian: Self::Endian) -> u32 {
- self.n_strx.get(endian)
- }
- fn n_type(&self) -> u8 {
- self.n_type
- }
- fn n_sect(&self) -> u8 {
- self.n_sect
- }
- fn n_desc(&self, endian: Self::Endian) -> u16 {
- self.n_desc.get(endian)
- }
- fn n_value(&self, endian: Self::Endian) -> Self::Word {
- self.n_value.get(endian)
- }
-}
-
-impl<Endian: endian::Endian> Nlist for macho::Nlist64<Endian> {
- type Word = u64;
- type Endian = Endian;
-
- fn n_strx(&self, endian: Self::Endian) -> u32 {
- self.n_strx.get(endian)
- }
- fn n_type(&self) -> u8 {
- self.n_type
- }
- fn n_sect(&self) -> u8 {
- self.n_sect
- }
- fn n_desc(&self, endian: Self::Endian) -> u16 {
- self.n_desc.get(endian)
- }
- fn n_value(&self, endian: Self::Endian) -> Self::Word {
- self.n_value.get(endian)
- }
-}