schnauzer/types/load_command/
mod.rs

1use crate::X64Context;
2
3use super::fmt_ext::*;
4use super::Section;
5use super::RcReader;
6use super::Result;
7use scroll::{Endian, IOread};
8
9use std::fmt::Debug;
10use std::io::{Seek, SeekFrom};
11
12use super::auto_enum_fields::*;
13use schnauzer_derive::AutoEnumFields;
14
15pub mod constants;
16pub use constants::*;
17
18pub mod common;
19pub use common::*;
20
21pub mod segment_command;
22pub use segment_command::*;
23
24pub mod symtab_command;
25pub use symtab_command::*;
26
27pub mod dylib_command;
28pub use dylib_command::*;
29
30pub mod sub_framework_command;
31pub use sub_framework_command::*;
32
33pub mod sub_client_command;
34pub use sub_client_command::*;
35
36pub mod sub_umbrella_command;
37pub use sub_umbrella_command::*;
38
39pub mod sub_library_command;
40pub use sub_library_command::*;
41
42pub mod prebound_dylib_command;
43pub use prebound_dylib_command::*;
44
45pub mod dylinker_command;
46pub use dylinker_command::*;
47
48pub mod thread_command;
49pub use thread_command::*;
50
51pub mod routines_command;
52pub use routines_command::*;
53
54pub mod dysymtab_command;
55pub use dysymtab_command::*;
56
57pub mod twolevel_hints_command;
58pub use twolevel_hints_command::*;
59
60pub mod prebind_cksum_command;
61pub use prebind_cksum_command::*;
62
63pub mod uuid_command;
64pub use uuid_command::*;
65
66pub mod rpath_command;
67pub use rpath_command::*;
68
69pub mod linkedit_data_command;
70pub use linkedit_data_command::*;
71
72pub mod encryption_info_command;
73pub use encryption_info_command::*;
74
75pub mod version_min_command;
76pub use version_min_command::*;
77
78pub mod build_version_command;
79pub use build_version_command::*;
80
81pub mod dyld_info_command;
82pub use dyld_info_command::*;
83
84pub mod linker_option_command;
85pub use linker_option_command::*;
86
87pub mod note_command;
88pub use note_command::*;
89
90pub mod source_version_command;
91pub use source_version_command::*;
92
93pub mod entry_point_command;
94pub use entry_point_command::*;
95
96pub mod fvmfile_command;
97pub use fvmfile_command::*;
98
99pub mod symseg_command;
100pub use symseg_command::*;
101
102/// Represents general load command struct - `load_command`
103#[derive(AutoEnumFields)]
104pub struct LoadCommand {
105    pub cmd: u32,
106    pub cmdsize: u32,
107
108    pub variant: LcVariant,
109}
110
111impl Debug for LoadCommand {
112    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
113        f.debug_struct("LoadCommand")
114            .field("cmd", &load_command_to_string(self.cmd))
115            .field("cmdsize", &self.cmdsize)
116            .field("variant", &self.variant)
117            .finish()
118    }
119}
120
121impl LoadCommand {
122    pub(super) fn parse(
123        reader: RcReader,
124        base_offset: usize,
125        endian: scroll::Endian,
126        is_64: bool,
127        object_file_offset: u64,
128    ) -> Result<LoadCommand> {
129        let mut reader_mut = reader.borrow_mut();
130        reader_mut.seek(SeekFrom::Start(base_offset as u64))?;
131
132        let cmd: u32 = reader_mut.ioread_with(endian)?;
133        let cmdsize: u32 = reader_mut.ioread_with(endian)?;
134
135        std::mem::drop(reader_mut);
136
137        let variant = LcVariant::parse(
138            reader.clone(),
139            cmd,
140            base_offset,
141            endian,
142            is_64,
143            object_file_offset,
144        )?;
145
146        Ok(LoadCommand {
147            cmd,
148            cmdsize,
149            variant,
150        })
151    }
152}
153
154/// Load command has variable set of fields dependent to `cmd` field
155/// List of load commands here - <https://opensource.apple.com/source/xnu/xnu-4570.71.2/EXTERNAL_HEADERS/mach-o/loader.h.auto.html>
156#[derive(Debug, AutoEnumFields)]
157pub enum LcVariant {
158    /// LC_SEGMENT
159    Segment32(LcSegment),
160    /// LC_SEGMENT_64
161    Segment64(LcSegment),
162    /// LC_ID_DYLIB
163    IdDylib(LcDylib),
164    /// LC_LOAD_DYLIB
165    LoadDylib(LcDylib),
166    /// LC_LOAD_WEAK_DYLIB
167    LoadWeakDylib(LcDylib),
168    /// LC_REEXPORT_DYLIB
169    ReexportDylib(LcDylib),
170    /// LC_SUB_FRAMEWORK
171    Subframework(LcSubframework),
172    /// LC_SUB_CLIENT
173    Subclient(LcSubclient),
174    /// LC_SUB_UMBRELLA
175    Subumbrella(LcSubumbrella),
176    /// LC_SUB_LIBRARY
177    Sublibrary(LcSublibrary),
178    /// LC_PREBOUND_DYLIB
179    PreboundDylib(LcPreboundDylib),
180    /// LC_ID_DYLINKER,
181    IdDylinker(LcDylinker),
182    /// LC_LOAD_DYLINKER,
183    LoadDylinker(LcDylinker),
184    /// LC_DYLD_ENVIRONMENT
185    DyldEnvironment(LcDylinker),
186    /// LC_THREAD
187    Thread(LcThread),
188    /// LC_UNIXTHREAD
189    UnixThread(LcThread),
190    /// LC_ROUTINES
191    Routines(LcRoutines),
192    /// LC_ROUTINES_64
193    Routines64(LcRoutines64),
194    /// LC_SYMTAB
195    Symtab(LcSymtab),
196    /// LC_DYSYMTAB
197    Dysimtab(LcDysimtab),
198    /// LC_TWOLEVEL_HINTS
199    TwoLevelHints(LcTwoLevelHints),
200    /// LC_PREBIND_CKSUM
201    PrebindChekSum(LcPrebindChekSum),
202    /// LC_UUID
203    Uuid(LcUuid),
204    /// LC_RPATH
205    Rpath(LcRpath),
206    /// LC_CODE_SIGNATURE,
207    CodeSignature(LcLinkEditData),
208    /// LC_SEGMENT_SPLIT_INFO,
209    SegmentSplitInfo(LcLinkEditData),
210    /// LC_FUNCTION_STARTS,
211    FunctionStarts(LcLinkEditData),
212    /// LC_DATA_IN_CODE,
213    DataInCode(LcLinkEditData),
214    /// LC_DYLIB_CODE_SIGN_DRS,
215    DylibCodeSignature(LcLinkEditData),
216    /// LC_LINKER_OPTIMIZATION_HINT,
217    LinkerOptimizationHint(LcLinkEditData),
218    /// LC_ENCRYPTION_INFO
219    EncryptionInfo(LcEncryptionInfo),
220    /// LC_ENCRYPTION_INFO_64
221    EncryptionInfo64(LcEncryptionInfo64),
222    /// LC_VERSION_MIN_MACOSX,
223    VersionMinMacOsx(LcVersionMin),
224    /// LC_VERSION_MIN_IPHONEOS,
225    VersionMinIphoneOs(LcVersionMin),
226    /// LC_VERSION_MIN_WATCHOS,
227    VersionMinWatchOs(LcVersionMin),
228    /// LC_VERSION_MIN_TVOS,
229    VersionMinTvOs(LcVersionMin),
230    /// LC_BUILD_VERSION
231    BuildVersion(LcBuildVersion),
232    /// LC_DYLD_INFO
233    DyldInfo(LcDyldInfo),
234    /// LC_DYLD_INFO_ONLY
235    DyldInfoOnly(LcDyldInfo),
236    /// LC_LINKER_OPTION
237    LinkerOption(LcLinkerOption),
238    /// LC_SYMSEG
239    SymSeg(LcSymSeg),
240    /// LC_FVMFILE
241    FvmFile(LcFvmFile),
242    /// LC_MAIN
243    EntryPoint(LcEntryPoint),
244    /// LC_SOURCE_VERSION
245    SourceVersion(LcSourceVersion),
246    /// LC_NOTE
247    Note(LcNote),
248    /// Any other command type unknown for lib
249    Other,
250}
251
252impl LcVariant {
253    fn parse(
254        reader: RcReader,
255        cmd: u32,
256        command_offset: usize,
257        endian: Endian,
258        is_64: bool,
259        object_file_offset: u64,
260    ) -> Result<Self> {
261        let reader_clone = reader.clone();
262        let mut reader_mut = reader.borrow_mut();
263        let base_offset = reader_mut.stream_position()? as usize;
264        // We assume reader already stay right after `cmd` and `cmdsize`
265        match cmd {
266            LC_SEGMENT => {
267                let c = LcSegment::parse(reader_clone, base_offset, object_file_offset, X64Context::Off(endian))?;
268                Ok(Self::Segment32(c))
269            }
270            LC_SEGMENT_64 => {
271                std::mem::drop(reader_mut);
272                let c = LcSegment::parse(reader_clone, base_offset, object_file_offset, X64Context::On(endian))?;
273                Ok(Self::Segment64(c))
274            }
275            LC_ID_DYLIB => {
276                std::mem::drop(reader_mut);
277                let c = LcDylib::parse(reader_clone, command_offset, base_offset, endian)?;
278                Ok(Self::IdDylib(c))
279            }
280            LC_LOAD_DYLIB => {
281                std::mem::drop(reader_mut);
282                let c = LcDylib::parse(reader_clone, command_offset, base_offset, endian)?;
283                Ok(Self::LoadDylib(c))
284            }
285            LC_LOAD_WEAK_DYLIB => {
286                std::mem::drop(reader_mut);
287                let c = LcDylib::parse(reader_clone, command_offset, base_offset, endian)?;
288                Ok(Self::LoadWeakDylib(c))
289            }
290            LC_REEXPORT_DYLIB => {
291                std::mem::drop(reader_mut);
292                let c = LcDylib::parse(reader_clone, command_offset, base_offset, endian)?;
293                Ok(Self::ReexportDylib(c))
294            }
295            LC_SUB_FRAMEWORK => {
296                std::mem::drop(reader_mut);
297                let c = LcSubframework::parse(reader_clone, command_offset, base_offset, endian)?;
298                Ok(Self::Subframework(c))
299            }
300            LC_SUB_CLIENT => {
301                std::mem::drop(reader_mut);
302                let c = LcSubclient::parse(reader_clone, command_offset, base_offset, endian)?;
303                Ok(Self::Subclient(c))
304            }
305            LC_SUB_UMBRELLA => {
306                std::mem::drop(reader_mut);
307                let c = LcSubumbrella::parse(reader_clone, command_offset, base_offset, endian)?;
308                Ok(Self::Subumbrella(c))
309            }
310            LC_SUB_LIBRARY => {
311                std::mem::drop(reader_mut);
312                let c = LcSublibrary::parse(reader_clone, command_offset, base_offset, endian)?;
313                Ok(Self::Sublibrary(c))
314            }
315            LC_PREBOUND_DYLIB => {
316                std::mem::drop(reader_mut);
317                let c = LcPreboundDylib::parse(reader_clone, command_offset, base_offset, endian)?;
318                Ok(Self::PreboundDylib(c))
319            }
320            LC_ID_DYLINKER => {
321                std::mem::drop(reader_mut);
322                let c = LcDylinker::parse(reader_clone, command_offset, base_offset, endian)?;
323                Ok(Self::IdDylinker(c))
324            }
325            LC_LOAD_DYLINKER => {
326                std::mem::drop(reader_mut);
327                let c = LcDylinker::parse(reader_clone, command_offset, base_offset, endian)?;
328                Ok(Self::LoadDylinker(c))
329            }
330            LC_DYLD_ENVIRONMENT => {
331                std::mem::drop(reader_mut);
332                let c = LcDylinker::parse(reader_clone, command_offset, base_offset, endian)?;
333                Ok(Self::DyldEnvironment(c))
334            }
335            LC_THREAD => {
336                let c = reader_mut.ioread_with(endian)?;
337                Ok(Self::Thread(c))
338            }
339            LC_UNIXTHREAD => {
340                let c = reader_mut.ioread_with(endian)?;
341                Ok(Self::Thread(c))
342            }
343            LC_ROUTINES => {
344                let c = reader_mut.ioread_with(endian)?;
345                Ok(Self::Routines(c))
346            }
347            LC_ROUTINES_64 => {
348                let c = reader_mut.ioread_with(endian)?;
349                Ok(Self::Routines64(c))
350            }
351            LC_SYMTAB => {
352                std::mem::drop(reader_mut);
353                let c =
354                    LcSymtab::parse(reader_clone, is_64, base_offset, endian, object_file_offset)?;
355                Ok(Self::Symtab(c))
356            }
357            LC_DYSYMTAB => {
358                let c = reader_mut.ioread_with(endian)?;
359                Ok(Self::Dysimtab(c))
360            }
361            LC_TWOLEVEL_HINTS => {
362                let c = reader_mut.ioread_with(endian)?;
363                Ok(Self::TwoLevelHints(c))
364            }
365            LC_PREBIND_CKSUM => {
366                let c = reader_mut.ioread_with(endian)?;
367                Ok(Self::PrebindChekSum(c))
368            }
369            LC_UUID => {
370                let c = reader_mut.ioread_with(endian)?;
371                Ok(Self::Uuid(c))
372            }
373            LC_RPATH => {
374                std::mem::drop(reader_mut);
375                let c = LcRpath::parse(reader_clone, command_offset, base_offset, endian)?;
376                Ok(Self::Rpath(c))
377            }
378            LC_CODE_SIGNATURE => {
379                let c = reader_mut.ioread_with(endian)?;
380                Ok(Self::CodeSignature(c))
381            }
382            LC_SEGMENT_SPLIT_INFO => {
383                let c = reader_mut.ioread_with(endian)?;
384                Ok(Self::SegmentSplitInfo(c))
385            }
386            LC_FUNCTION_STARTS => {
387                let c = reader_mut.ioread_with(endian)?;
388                Ok(Self::FunctionStarts(c))
389            }
390            LC_DATA_IN_CODE => {
391                let c = reader_mut.ioread_with(endian)?;
392                Ok(Self::DataInCode(c))
393            }
394            LC_DYLIB_CODE_SIGN_DRS => {
395                let c = reader_mut.ioread_with(endian)?;
396                Ok(Self::DylibCodeSignature(c))
397            }
398            LC_LINKER_OPTIMIZATION_HINT => {
399                let c = reader_mut.ioread_with(endian)?;
400                Ok(Self::LinkerOptimizationHint(c))
401            }
402            LC_ENCRYPTION_INFO => {
403                let c = reader_mut.ioread_with(endian)?;
404                Ok(Self::EncryptionInfo(c))
405            }
406            LC_ENCRYPTION_INFO_64 => {
407                let c = reader_mut.ioread_with(endian)?;
408                Ok(Self::EncryptionInfo64(c))
409            }
410            LC_VERSION_MIN_MACOSX => {
411                let c = reader_mut.ioread_with(endian)?;
412                Ok(Self::VersionMinMacOsx(c))
413            }
414            LC_VERSION_MIN_IPHONEOS => {
415                let c = reader_mut.ioread_with(endian)?;
416                Ok(Self::VersionMinIphoneOs(c))
417            }
418            LC_VERSION_MIN_WATCHOS => {
419                let c = reader_mut.ioread_with(endian)?;
420                Ok(Self::VersionMinWatchOs(c))
421            }
422            LC_VERSION_MIN_TVOS => {
423                let c = reader_mut.ioread_with(endian)?;
424                Ok(Self::VersionMinTvOs(c))
425            }
426            LC_BUILD_VERSION => {
427                let c = reader_mut.ioread_with(endian)?;
428                Ok(Self::BuildVersion(c))
429            }
430            LC_DYLD_INFO => {
431                let c = reader_mut.ioread_with(endian)?;
432                Ok(Self::DyldInfo(c))
433            }
434            LC_DYLD_INFO_ONLY => {
435                let c = reader_mut.ioread_with(endian)?;
436                Ok(Self::DyldInfoOnly(c))
437            }
438            LC_LINKER_OPTION => {
439                let c = reader_mut.ioread_with(endian)?;
440                Ok(Self::LinkerOption(c))
441            }
442            LC_SYMSEG => {
443                let c = reader_mut.ioread_with(endian)?;
444                Ok(Self::SymSeg(c))
445            }
446            LC_FVMFILE => {
447                std::mem::drop(reader_mut);
448                let c = LcFvmFile::parse(reader_clone, command_offset, base_offset, endian)?;
449                Ok(Self::FvmFile(c))
450            }
451            LC_MAIN => {
452                let c = reader_mut.ioread_with(endian)?;
453                Ok(Self::EntryPoint(c))
454            }
455            LC_SOURCE_VERSION => {
456                let c = reader_mut.ioread_with(endian)?;
457                Ok(Self::SourceVersion(c))
458            }
459            LC_NOTE => {
460                let c = reader_mut.ioread_with(endian)?;
461                Ok(Self::Note(c))
462            }
463            _ => Ok(Self::Other),
464        }
465    }
466}