Skip to content

Commit

Permalink
feat: implement parsing for LC_DYLD_EXPORTS_TRIE for mach-o (#303)
Browse files Browse the repository at this point in the history
Implements the parsing required for exports defined via `LC_DYLD_EXPORTS_TRIE` as described in #301.
  • Loading branch information
latonis authored Feb 6, 2025
1 parent cfa20b8 commit 29d5700
Show file tree
Hide file tree
Showing 4 changed files with 960 additions and 8 deletions.
42 changes: 35 additions & 7 deletions lib/src/modules/macho/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ const LC_LINKER_OPTION: u32 = 0x0000002d;
const LC_VERSION_MIN_TVOS: u32 = 0x0000002f;
const LC_VERSION_MIN_WATCHOS: u32 = 0x00000030;
const LC_BUILD_VERSION: u32 = 0x00000032;
const LC_DYLD_EXPORTS_TRIE: u32 = 0x00000033 | LC_REQ_DYLD;
const _LC_DYLD_CHAINED_FIXUPS: u32 = 0x00000034 | LC_REQ_DYLD;

/// Mach-O CPU types
const CPU_TYPE_MC680X0: u32 = 0x00000006;
Expand Down Expand Up @@ -296,6 +298,7 @@ impl<'a> MachO<'a> {
dynamic_linker: None,
linker_options: Vec::new(),
dyld_info: None,
dyld_export_trie: None,
source_version: None,
entry_point_offset: None,
entry_point_rva: None,
Expand Down Expand Up @@ -369,9 +372,19 @@ impl<'a> MachO<'a> {
}
}

if let Some(ref dyld_info) = macho.dyld_info {
let offset = dyld_info.export_off as usize;
let size = dyld_info.export_size as usize;
for (offset, size) in [
macho
.dyld_export_trie
.as_ref()
.map(|t| (t.data_off as usize, t.data_size as usize)),
macho
.dyld_info
.as_ref()
.map(|i| (i.export_off as usize, i.export_size as usize)),
]
.into_iter()
.flatten()
{
if let Some(export_data) =
data.get(offset..offset.saturating_add(size))
{
Expand Down Expand Up @@ -423,6 +436,7 @@ pub struct MachOFile<'a> {
symtab: Option<Symtab<'a>>,
dysymtab: Option<Dysymtab>,
dyld_info: Option<DyldInfo>,
dyld_export_trie: Option<DyldExportTrie>,
dynamic_linker: Option<&'a [u8]>,
linker_options: Vec<&'a [u8]>,
source_version: Option<String>,
Expand Down Expand Up @@ -577,6 +591,14 @@ impl<'a> MachOFile<'a> {
let (_, lid) = self.linkeditdata_command()(command_data)?;
self.code_signature_data = Some(lid);
}
LC_DYLD_EXPORTS_TRIE => {
let (_, exports_data) =
self.linkeditdata_command()(command_data)?;
self.dyld_export_trie = Some(DyldExportTrie {
data_off: exports_data.dataoff,
data_size: exports_data.datasize,
});
}
LC_DYLD_INFO | LC_DYLD_INFO_ONLY => {
let (_, dyld_info) =
self.dyld_info_command()(command_data)?;
Expand Down Expand Up @@ -893,9 +915,10 @@ impl<'a> MachOFile<'a> {
let size_of_blob = std::mem::size_of::<CSBlob>();
match blob.magic {
CS_MAGIC_EMBEDDED_ENTITLEMENTS => {
let xml_data = match super_data
.get(offset.saturating_add(size_of_blob) .. offset.saturating_add(length))
{
let xml_data = match super_data.get(
offset.saturating_add(size_of_blob)
..offset.saturating_add(length),
) {
Some(data) => data,
None => continue,
};
Expand Down Expand Up @@ -1090,7 +1113,7 @@ impl<'a> MachOFile<'a> {
}

/// Parser that parses the exports at the offsets defined within
/// LC_DYLD_INFO and LC_DYLD_INFO_ONLY.
/// LC_DYLD_INFO, LC_DYLD_INFO_ONLY, and LC_DYLD_EXPORTS_TRIE.
fn exports(
&mut self,
) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], Vec<String>> + '_ {
Expand Down Expand Up @@ -1551,6 +1574,11 @@ struct DyldInfo {
export_size: u32,
}

struct DyldExportTrie {
data_off: u32,
data_size: u32,
}

struct BuildVersionCommand {
platform: u32,
minos: u32,
Expand Down
Binary file not shown.
Loading

0 comments on commit 29d5700

Please sign in to comment.