//! Support for reading short import files. //! //! These are used by some Windows linkers as a more compact way to describe //! dynamically imported symbols.
/// A Windows short form description of a symbol to import. /// /// Used in Windows import libraries to provide a mapping from /// a symbol name to a DLL export. This is not an object file. /// /// This is a file that starts with [`pe::ImportObjectHeader`], and corresponds /// to [`crate::FileKind::CoffImport`]. #[derive(Debug, Clone)] pubstruct ImportFile<'data> {
header: &'data pe::ImportObjectHeader,
kind: ImportType,
dll: ByteString<'data>,
symbol: ByteString<'data>,
import: Option<ByteString<'data>>,
}
impl<'data> ImportFile<'data> { /// Parse it. pubfn parse<R: ReadRef<'data>>(data: R) -> Result<Self> { letmut offset = 0; let header = pe::ImportObjectHeader::parse(data, &mut offset)?; let data = header.parse_data(data, &mut offset)?;
// Unmangles a name by removing a `?`, `@` or `_` prefix. fn strip_prefix(s: &[u8]) -> &[u8] { match s.split_first() {
Some((b, rest)) if [b'?', b'@', b'_'].contains(b) => rest,
_ => s,
}
}
Ok(Self {
header,
dll: data.dll,
symbol: data.symbol,
kind: match header.import_type() {
pe::IMPORT_OBJECT_CODE => ImportType::Code,
pe::IMPORT_OBJECT_DATA => ImportType::Data,
pe::IMPORT_OBJECT_CONST => ImportType::Const,
_ => return Err(Error("Invalid COFF import library import type")),
},
import: match header.name_type() {
pe::IMPORT_OBJECT_ORDINAL => None,
pe::IMPORT_OBJECT_NAME => Some(data.symbol()),
pe::IMPORT_OBJECT_NAME_NO_PREFIX => Some(strip_prefix(data.symbol())),
pe::IMPORT_OBJECT_NAME_UNDECORATE => Some(
strip_prefix(data.symbol())
.split(|&b| b == b'@')
.next()
.unwrap(),
),
pe::IMPORT_OBJECT_NAME_EXPORTAS => data.export(),
_ => return Err(Error("Unknown COFF import library name type")),
}
.map(ByteString),
})
}
/// Get the sub machine type, if available. pubfn sub_architecture(&self) -> Option<SubArchitecture> { matchself.header.machine.get(LE) {
pe::IMAGE_FILE_MACHINE_ARM64EC => Some(SubArchitecture::Arm64EC),
_ => None,
}
}
/// The public symbol name. pubfn symbol(&self) -> &'data [u8] { self.symbol.0
}
/// The name of the DLL to import the symbol from. pubfn dll(&self) -> &'data [u8] { self.dll.0
}
/// The name exported from the DLL. pubfn import(&self) -> ImportName<'data> { matchself.import {
Some(name) => ImportName::Name(name.0),
None => ImportName::Ordinal(self.header.ordinal_or_hint.get(LE)),
}
}
/// The type of import. Usually either a function or data. pubfn import_type(&self) -> ImportType { self.kind
}
}
/// The name or ordinal to import from a DLL. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pubenum ImportName<'data> { /// Import by ordinal. Ordinarily this is a 1-based index.
Ordinal(u16), /// Import by name.
Name(&'data [u8]),
}
/// The kind of import symbol. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pubenum ImportType { /// An executable code symbol.
Code, /// A data symbol.
Data, /// A constant value. Const,
}
impl pe::ImportObjectHeader { /// Read the short import header. /// /// Also checks that the signature and version are valid. /// Directly following this header will be the string data. pubfn parse<'data, R: ReadRef<'data>>(data: R, offset: &mut u64) -> Result<&'data Self> { let header = data
.read::<pe::ImportObjectHeader>(offset)
.read_error("Invalid COFF import library header size")?; if header.sig1.get(LE) != 0 || header.sig2.get(LE) != pe::IMPORT_OBJECT_HDR_SIG2 {
Err(Error("Invalid COFF import library header"))
} elseif header.version.get(LE) != 0 {
Err(Error("Unknown COFF import library header version"))
} else {
Ok(header)
}
}
/// Parse the data following the header. pubfn parse_data<'data, R: ReadRef<'data>>(
&self,
data: R,
offset: &mut u64,
) -> Result<ImportObjectData<'data>> { letmut data = Bytes(
data.read_bytes(offset, u64::from(self.size_of_data.get(LE)))
.read_error("Invalid COFF import library data size")?,
); let symbol = data
.read_string()
.map(ByteString)
.read_error("Could not read COFF import library symbol name")?; let dll = data
.read_string()
.map(ByteString)
.read_error("Could not read COFF import library DLL name")?; let export = ifself.name_type() == pe::IMPORT_OBJECT_NAME_EXPORTAS {
data.read_string()
.map(ByteString)
.map(Some)
.read_error("Could not read COFF import library export name")?
} else {
None
};
Ok(ImportObjectData {
symbol,
dll,
export,
})
}
/// The type of import. /// /// This is one of the `IMPORT_OBJECT_*` constants. pubfn import_type(&self) -> u16 { self.name_type.get(LE) & pe::IMPORT_OBJECT_TYPE_MASK
}
/// The type of import name. /// /// This is one of the `IMPORT_OBJECT_*` constants. pubfn name_type(&self) -> u16 {
(self.name_type.get(LE) >> pe::IMPORT_OBJECT_NAME_SHIFT) & pe::IMPORT_OBJECT_NAME_MASK
}
}
/// The data following [`pe::ImportObjectHeader`]. #[derive(Debug, Clone)] pubstruct ImportObjectData<'data> {
symbol: ByteString<'data>,
dll: ByteString<'data>,
export: Option<ByteString<'data>>,
}
impl<'data> ImportObjectData<'data> { /// The public symbol name. pubfn symbol(&self) -> &'data [u8] { self.symbol.0
}
/// The name of the DLL to import the symbol from. pubfn dll(&self) -> &'data [u8] { self.dll.0
}
/// The name exported from the DLL. /// /// This is only set if the name is not derived from the symbol name. pubfn export(&self) -> Option<&'data [u8]> { self.export.map(|export| export.0)
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet am 2026-06-18)
¤
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.