/// A table of symbol entries in an XCOFF file. /// /// Also includes the string table used for the symbol names. /// /// Returned by [`FileHeader::symbols`]. #[derive(Debug)] pubstruct SymbolTable<'data, Xcoff, R = &'data [u8]> where
Xcoff: FileHeader,
R: ReadRef<'data>,
{
symbols: &'data [xcoff::SymbolBytes],
strings: StringTable<'data, R>,
header: PhantomData<Xcoff>,
}
impl<'data, Xcoff, R> SymbolTable<'data, Xcoff, R> where
Xcoff: FileHeader,
R: ReadRef<'data>,
{ /// Parse the symbol table. pubfn parse(header: Xcoff, data: R) -> Result<Self> { letmut offset = header.f_symptr().into(); let (symbols, strings) = if offset != 0 { let symbols = data
.read_slice(&mut offset, header.f_nsyms() as usize)
.read_error("Invalid XCOFF symbol table offset or size")?;
// Parse the string table. // Note: don't update data when reading length; the length includes itself. let length = data
.read_at::<U32Bytes<_>>(offset)
.read_error("Missing XCOFF string table")?
.get(BE); let str_end = offset
.checked_add(length as u64)
.read_error("Invalid XCOFF string table length")?; let strings = StringTable::new(data, offset, str_end);
/// Return the symbol entry at the given index and offset. pubfn get<T: Pod>(&self, index: SymbolIndex, offset: usize) -> Result<&<span style='color:blue'>'data T> { let entry = index
.0
.checked_add(offset)
.and_then(|x| self.symbols.get(x))
.read_error("Invalid XCOFF symbol index")?; let bytes = bytes_of(entry);
Bytes(bytes).read().read_error("Invalid XCOFF symbol data")
}
/// Get the symbol at the given index. /// /// This does not check if the symbol is null, but does check if the index is in bounds. fn symbol_unchecked(&self, index: SymbolIndex) -> Result<&le='color:blue'>'data Xcoff::Symbol> { self.get::<Xcoff::Symbol>(index, 0)
}
/// Get the symbol at the given index. /// /// Returns an error for null symbols and out of bounds indices. /// Note that this is unable to check whether the index is an auxiliary symbol. pubfn symbol(&self, index: SymbolIndex) -> Result<&'data Xcoff::Symbol> { let symbol = self.symbol_unchecked(index)?; if symbol.is_null() { return Err(Error("Invalid XCOFF symbol index"));
}
Ok(symbol)
}
/// Return a file auxiliary symbol. pubfn aux_file(&self, index: SymbolIndex, offset: usize) -> Result<&<span style='color:blue'>'data Xcoff::FileAux> {
debug_assert!(self.symbol(index)?.has_aux_file()); let aux_file = self.get::<Xcoff::FileAux>(index, offset)?; iflet Some(aux_type) = aux_file.x_auxtype() { if aux_type != xcoff::AUX_FILE { return Err(Error("Invalid index for file auxiliary symbol."));
}
}
Ok(aux_file)
}
/// Return true if the symbol table is empty. #[inline] pubfn is_empty(&self) -> bool { self.symbols.is_empty()
}
/// The number of symbol table entries. /// /// This includes auxiliary symbol table entries. #[inline] pubfn len(&self) -> usize { self.symbols.len()
}
}
/// An iterator for symbol entries in an XCOFF file. /// /// Yields the index and symbol structure for each symbol. #[derive(Debug)] pubstruct SymbolIterator<'data, 'table, Xcoff, R = &'data [u8]> where
Xcoff: FileHeader,
R: ReadRef<'data>,
{
symbols: &'table SymbolTable<'data, Xcoff, R>,
index: usize,
}
impl<'data, 'table, Xcoff: FileHeader, R: ReadRef<'data>> Iterator for SymbolIterator<'data, 'table, Xcoff, R>
{ type Item = (SymbolIndex, &'data Xcoff::Symbol);
fn next(&mutself) -> Option<Self::Item> { loop { let index = SymbolIndex(self.index); let symbol = self.symbols.symbol_unchecked(index).ok()?; self.index += 1 + symbol.n_numaux() as usize; if !symbol.is_null() { return Some((index, symbol));
}
}
}
}
/// A symbol table in an [`XcoffFile32`](super::XcoffFile32). pubtype XcoffSymbolTable32<'data, 'file, R = &'data [u8]> =
XcoffSymbolTable<'data, 'file, xcoff::FileHeader32, R>; /// A symbol table in an [`XcoffFile64`](super::XcoffFile64). pubtype XcoffSymbolTable64<'data, 'file, R = &'data [u8]> =
XcoffSymbolTable<'data, 'file, xcoff::FileHeader64, R>;
/// A symbol table in an [`XcoffFile`]. #[derive(Debug, Clone, Copy)] pubstruct XcoffSymbolTable<'data, 'file, Xcoff, R = &'data [u8]> where
Xcoff: FileHeader,
R: ReadRef<'data>,
{ pub(super) file: &'file XcoffFile<'data, Xcoff, R>, pub(super) symbols: &'file SymbolTable<'data, Xcoff, R>,
}
/// An iterator for the symbols in an [`XcoffFile32`](super::XcoffFile32). pubtype XcoffSymbolIterator32<'data, 'file, R = &'data [u8]> =
XcoffSymbolIterator<'data, 'file, xcoff::FileHeader32, R>; /// An iterator for the symbols in an [`XcoffFile64`](super::XcoffFile64). pubtype XcoffSymbolIterator64<'data, 'file, R = &'data [u8]> =
XcoffSymbolIterator<'data, 'file, xcoff::FileHeader64, R>;
/// An iterator for the symbols in an [`XcoffFile`]. pubstruct XcoffSymbolIterator<'data, 'file, Xcoff, R = &'data [u8]> where
Xcoff: FileHeader,
R: ReadRef<'data>,
{ pub(super) file: &'file XcoffFile<'data, Xcoff, R>, pub(super) symbols: SymbolIterator<'data, 'file, Xcoff, R>,
}
/// A symbol in an [`XcoffFile32`](super::XcoffFile32). pubtype XcoffSymbol32<'data, 'file, R = &'data [u8]> =
XcoffSymbol<'data, 'file, xcoff::FileHeader32, R>; /// A symbol in an [`XcoffFile64`](super::XcoffFile64). pubtype XcoffSymbol64<'data, 'file, R = &'data [u8]> =
XcoffSymbol<'data, 'file, xcoff::FileHeader64, R>;
/// A symbol in an [`XcoffFile`]. /// /// Most functionality is provided by the [`ObjectSymbol`] trait implementation. #[derive(Debug, Clone, Copy)] pubstruct XcoffSymbol<'data, 'file, Xcoff, R = &'data [u8]> where
Xcoff: FileHeader,
R: ReadRef<'data>,
{ pub(super) file: &'file XcoffFile<'data, Xcoff, R>, pub(super) symbols: &'file SymbolTable<'data, Xcoff, R>, pub(super) index: SymbolIndex, pub(super) symbol: &'data Xcoff::Symbol,
}
impl<'data, 'file, Xcoff, R> XcoffSymbol<'data, 'file, Xcoff, R> where
Xcoff: FileHeader,
R: ReadRef<'data>,
{ /// Get the XCOFF file containing this symbol. pubfn xcoff_file(&self) -> &'file XcoffFile<'data, Xcoff, R> { self.file
}
/// Get the raw XCOFF symbol structure. pubfn xcoff_symbol(&self) -> &'data Xcoff::Symbol { self.symbol
}
}
fn name_bytes(&self) -> Result<&'data [u8]> { ifself.symbol.has_aux_file() { // By convention the file name is in the first auxiliary entry. self.symbols
.aux_file(self.index, 1)?
.fname(self.symbols.strings)
} else { self.symbol.name(self.symbols.strings)
}
}
fn name(&self) -> Result<&'data str> { let name = self.name_bytes()?;
str::from_utf8(name)
.ok()
.read_error("Non UTF-8 XCOFF symbol name")
}
/// A trait for generic access to [`xcoff::Symbol32`] and [`xcoff::Symbol64`]. #[allow(missing_docs)] pubtrait Symbol: Debug + Pod { type Word: Into<u64>;
/// Return the section index for the symbol. fn section(&self) -> Option<SectionIndex> { let index = self.n_scnum(); if index > 0 {
Some(SectionIndex(index as usize))
} else {
None
}
}
/// Return true if the symbol is a null placeholder. #[inline] fn is_null(&self) -> bool { self.n_sclass() == xcoff::C_NULL
}
/// Return true if the symbol is undefined. #[inline] fn is_undefined(&self) -> bool { let n_sclass = self.n_sclass();
(n_sclass == xcoff::C_EXT || n_sclass == xcoff::C_WEAKEXT)
&& self.n_scnum() == xcoff::N_UNDEF
}
/// Return true if the symbol has file auxiliary entry. fn has_aux_file(&self) -> bool { self.n_numaux() > 0 && self.n_sclass() == xcoff::C_FILE
}
/// Return true if the symbol has csect auxiliary entry. /// /// A csect auxiliary entry is required for each symbol table entry that has /// a storage class value of C_EXT, C_WEAKEXT, or C_HIDEXT. fn has_aux_csect(&self) -> bool { let sclass = self.n_sclass(); self.n_numaux() > 0
&& (sclass == xcoff::C_EXT || sclass == xcoff::C_WEAKEXT || sclass == xcoff::C_HIDEXT)
}
}
impl Symbol for xcoff::Symbol64 { type Word = u64;
/// Parse the symbol name for XCOFF64. fn name<'data, R: ReadRef<'data>>(
&'data self,
strings: StringTable<'data, R>,
) -> Result<&'data [u8]> {
strings
.get(self.n_offset.get(BE))
.read_error("Invalid XCOFF symbol name offset")
}
}
impl Symbol for xcoff::Symbol32 { type Word = u32;
/// Parse the symbol name for XCOFF32. fn name<'data, R: ReadRef<'data>>(
&'data self,
strings: StringTable<'data, R>,
) -> Result<&'data [u8]> { iflet Some(offset) = self.name_offset() { // If the name starts with 0 then the last 4 bytes are a string table offset.
strings
.get(offset)
.read_error("Invalid XCOFF symbol name offset")
} else { // The name is inline and padded with nulls.
Ok(match memchr::memchr(b'\0', &self.n_name) {
Some(end) => &self.n_name[..end],
None => &self.n_name,
})
}
}
}
/// A trait for generic access to [`xcoff::FileAux32`] and [`xcoff::FileAux64`]. #[allow(missing_docs)] pubtrait FileAux: Debug + Pod { fn x_fname(&self) -> &[u8; 8]; fn x_ftype(&self) -> u8; fn x_auxtype(&self) -> Option<u8>;
/// Parse the x_fname field, which may be an inline string or a string table offset. fn fname<'data, R: ReadRef<'data>>(
&'data self,
strings: StringTable<'data, R>,
) -> Result<&'data [u8]> { iflet Some(offset) = self.name_offset() { // If the name starts with 0 then the last 4 bytes are a string table offset.
strings
.get(offset)
.read_error("Invalid XCOFF symbol name offset")
} else { // The name is inline and padded with nulls. let x_fname = self.x_fname();
Ok(match memchr::memchr(b'\0', x_fname) {
Some(end) => &x_fname[..end],
None => x_fname,
})
}
}
}
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.