Skip to main content

macho2/command/
mod.rs

1pub mod build_version;
2pub mod codesign;
3pub mod dyld_chained_fixup;
4pub mod dyld_exports_trie;
5pub mod dyld_info;
6pub mod dylib;
7pub mod dylib_use;
8pub mod dylinker;
9pub mod dysymtab;
10pub mod encryption_info;
11pub mod entry_point;
12pub mod fileset_entry;
13pub mod function_starts;
14pub mod linkedit_data;
15pub mod linker_option;
16pub mod note;
17pub mod prebind_cksum;
18pub mod prebound_dylib;
19pub mod routines;
20pub mod rpath;
21pub mod segment;
22pub mod source_version;
23pub mod sub_client;
24pub mod sub_framework;
25pub mod sub_library;
26pub mod sub_umbrella;
27pub mod symseg;
28pub mod symtab;
29pub mod thread;
30pub mod two_level_hints;
31pub mod uuid;
32pub mod version_min;
33
34use std::io::{Read, Seek, SeekFrom};
35
36use crate::header::MachHeader;
37use crate::macho::{MachOErr, MachOResult};
38use nom::bytes::complete::take;
39use nom::number::complete::le_u32;
40use nom::IResult;
41use nom_derive::{Nom, Parse};
42
43// Re-export all command types for easier access
44pub use build_version::BuildVersionCommand;
45pub use codesign::CodeSignCommand;
46pub use dyld_chained_fixup::DyldChainedFixupCommand;
47pub use dyld_exports_trie::DyldExportsTrie;
48pub use dyld_info::DyldInfoCommand;
49pub use dylib::DylibCommand;
50pub use dylinker::DylinkerCommand;
51pub use dysymtab::DysymtabCommand;
52pub use encryption_info::{EncryptionInfoCommand, EncryptionInfoCommand64};
53pub use entry_point::EntryPointCommand;
54pub use fileset_entry::FilesetEntryCommand;
55pub use function_starts::FunctionStartsCommand;
56pub use linkedit_data::LinkeditDataCommand;
57pub use linker_option::LinkerOptionCommand;
58pub use note::NoteCommand;
59pub use prebind_cksum::PrebindCksumCommand;
60pub use prebound_dylib::PreboundDylibCommand;
61pub use routines::RoutinesCommand64;
62pub use rpath::RpathCommand;
63pub use segment::{SegmentCommand32, SegmentCommand64};
64pub use source_version::SourceVersionCommand;
65pub use sub_client::SubClientCommand;
66pub use sub_framework::SubFrameworkCommand;
67pub use sub_library::SubLibraryCommand;
68pub use sub_umbrella::SubUmbrellaCommand;
69pub use symseg::SymsegCommand;
70pub use symtab::SymtabCommand;
71pub use thread::ThreadCommand;
72pub use two_level_hints::TwoLevelHintsCommand;
73pub use uuid::UuidCommand;
74pub use version_min::VersionMinCommand;
75
76
77pub trait LoadCommandParser {
78    fn parse(ldcmd: &[u8]) -> MachOResult<Self>
79    where
80        Self: Sized;
81    fn serialize(&self) -> Vec<u8>;
82}
83
84fn pad_to_size(buf: &mut Vec<u8>, size: usize) {
85    let pad_size = size.checked_sub(buf.len()).expect(&format!(
86        "Serialized buf size exceeds cmdsize. Expected: {}, Actual: {}",
87        size,
88        buf.len()
89    ));
90    buf.extend(vec![0u8; pad_size]);
91}
92
93pub trait LoadCommandResolver<T, R> {
94    fn resolve(&self, buf: &mut T) -> MachOResult<R>;
95}
96
97#[derive(Debug, Clone, Copy)]
98pub struct LoadCommandBase {
99    pub cmd: LCLoadCommand,
100    pub cmdsize: u32,
101}
102
103impl LoadCommandBase {
104    pub fn parse<'a>(bytes: &[u8]) -> IResult<&[u8], LoadCommandBase> {
105        let (bytes, cmd) = LCLoadCommand::parse_le(bytes)?;
106        let (bytes, cmdsize) = le_u32(bytes)?;
107
108        Ok((bytes, LoadCommandBase { cmd, cmdsize }))
109    }
110
111    pub fn skip(bytes: &[u8]) -> IResult<&[u8], ()> {
112        let (remaining, _) = take(8usize)(bytes)?;
113        Ok((remaining, ()))
114    }
115}
116
117#[repr(u32)]
118#[derive(Debug, Clone, Copy, PartialEq, Eq, Nom)]
119pub enum LCLoadCommand {
120    // TODO: What is this load command doing ? e.g. /System/Library/VideoProcessors/CCPortrait.bundle/ccportrait_archive_bin.metallib
121    None = 0x0,
122    LcSegment = 0x1,
123    LcSymtab = 0x2,
124    LcSymseg = 0x3,
125    LcThread = 0x4,
126    LcUnixThread = 0x5,
127    LcDysymtab = 0xb,
128    LcLoadDylib = 0xc,
129    LcIdDylib = 0xd,
130    LcLoadDylinker = 0xe,
131    LcIdDylinker = 0xf,
132    LcPreboundDylib = 0x10,
133    LcRoutines = 0x11,
134    LcSubFramework = 0x12,
135    LcSubUmbrella = 0x13,
136    LcSubClient = 0x14,
137    LcSubLibrary = 0x15,
138    LcTwolevelHints = 0x16,
139    LcPrebindCksum = 0x17,
140    LcLoadWeakDylib = 0x18 | Self::LC_REQ_DYLD,
141    LcSegment64 = 0x19,
142    LcRoutines64 = 0x1a,
143    LcUuid = 0x1b,
144    LcRpath = 0x1c | Self::LC_REQ_DYLD,
145    LcCodeSignature = 0x1d,
146    LcSegmentSplitInfo = 0x1e,
147    LcReexportDylib = 0x1f | Self::LC_REQ_DYLD,
148    LcLazyLoadDylib = 0x20,
149    LcEncryptionInfo = 0x21,
150    LcDyldInfo = 0x22,
151    LcDyldInfoOnly = 0x22 | Self::LC_REQ_DYLD,
152    LcLoadUpwardDylib = 0x23 | Self::LC_REQ_DYLD,
153    LcVersionMinMacosx = 0x24,
154    LcVersionMinIphoneos = 0x25,
155    LcFunctionStarts = 0x26,
156    LcDyldEnvironment = 0x27,
157    LcMain = 0x28 | Self::LC_REQ_DYLD,
158    LcDataInCode = 0x29,
159    LcSourceVersion = 0x2A,
160    LcDylibCodeSignDrs = 0x2B,
161    LcEncryptionInfo64 = 0x2C,
162    LcLinkerOption = 0x2D,
163    LcLinkerOptimizationHint = 0x2E,
164    LcVersionMinTvos = 0x2F,
165    LcVersionMinWatchos = 0x30,
166    LcNote = 0x31,
167    LcBuildVersion = 0x32,
168    LcDyldExportsTrie = 0x33 | Self::LC_REQ_DYLD,
169    LcDyldChainedFixups = 0x34 | Self::LC_REQ_DYLD,
170    LcFilesetEntry = 0x35 | Self::LC_REQ_DYLD,
171    LcAtomInfo = 0x36,
172}
173
174impl LCLoadCommand {
175    pub const LC_REQ_DYLD: u32 = 0x80000000;
176
177    pub fn serialize(&self) -> Vec<u8> {
178        (*self as u32).to_le_bytes().to_vec()
179    }
180}
181
182#[derive(Debug, PartialEq, Eq)]
183pub enum LoadCommand {
184    None,
185    Segment32(SegmentCommand32),
186    Symtab(SymtabCommand),
187    Symseg(SymsegCommand),
188    Thread(ThreadCommand),
189    UnixThread(ThreadCommand),
190    Dysymtab(DysymtabCommand),
191    LoadDylib(DylibCommand),
192    DylibId(DylibCommand),
193    LoadDylinker(DylinkerCommand),
194    IdDylinker(DylinkerCommand),
195    PreboundDylib(PreboundDylibCommand),
196    Routines(RoutinesCommand64),
197    SubFramework(SubFrameworkCommand),
198    SubUmbrella(SubUmbrellaCommand),
199    SubClient(SubClientCommand),
200    SubLibrary(SubLibraryCommand),
201    TwoLevelHints(TwoLevelHintsCommand),
202    PrebindCksum(PrebindCksumCommand),
203    LoadWeakDylib(DylibCommand),
204    Segment64(SegmentCommand64),
205    Routines64(RoutinesCommand64),
206    UUID(UuidCommand),
207    Rpath(RpathCommand),
208    CodeSignature(CodeSignCommand),
209    SegmentSplitInfo(LinkeditDataCommand),
210    ReexportDylib(DylibCommand),
211    LazyLoadDylib(DylibCommand),
212    EncryptionInfo(EncryptionInfoCommand),
213    DyldInfo(DyldInfoCommand),
214    DyldInfoOnly(DyldInfoCommand),
215    LoadUpwardDylib(DylibCommand),
216    VersionMinMacosx(VersionMinCommand),
217    VersionMinIphoneos(VersionMinCommand),
218    FunctionStarts(FunctionStartsCommand),
219    DyldEnvironment(DylinkerCommand),
220    Main(EntryPointCommand),
221    DataInCode(LinkeditDataCommand),
222    SourceVersion(SourceVersionCommand),
223    DylibCodeSignDrs(LinkeditDataCommand),
224    EncryptionInfo64(EncryptionInfoCommand64),
225    LinkerOption(LinkerOptionCommand),
226    LinkerOptimizationHint(LinkeditDataCommand),
227    VersionMinTvos(VersionMinCommand),
228    VersionMinWatchos(VersionMinCommand),
229    Note(NoteCommand),
230    BuildVersion(BuildVersionCommand),
231    DyldExportsTrie(DyldExportsTrie),
232    DyldChainedFixups(DyldChainedFixupCommand),
233    FilesetEntry(FilesetEntryCommand),
234    AtomInfo(LinkeditDataCommand),
235}
236
237pub fn iterate_load_commands<F, T>(
238    buf: &mut T,
239    header: MachHeader,
240    mut f: F,
241) -> MachOResult<Vec<LoadCommand>>
242where
243    F: FnMut(
244        LoadCommandBase,
245        &[u8],
246    ) -> MachOResult<LoadCommand>,
247    T: Seek + Read,
248{
249    let mut ldcmds = vec![0u8; header.sizeofcmds() as usize];
250    buf.seek(SeekFrom::Start(header.size() as u64))
251        .map_err(|e| MachOErr::IOError(e))?;
252    buf.read_exact(&mut ldcmds).map_err(|e| MachOErr::IOError(e))?;
253
254    let mut results = Vec::new();
255    let mut remaining_ldcmds = &ldcmds[..];
256
257    for i in 0..header.ncmds() {
258        let (_, base) = LoadCommandBase::parse(remaining_ldcmds).map_err(|_| MachOErr::ParsingError(format!("Unable to parse load command base for index {}", i)))?;
259
260        let cmdsize = base.cmdsize as usize;
261        if cmdsize > remaining_ldcmds.len() {
262            return Err(MachOErr::InvalidValue(format!("Load command size exceeds available data at index {}", i)));
263        }
264
265        let cmd_bytes = &remaining_ldcmds[..cmdsize];
266        let result = f(base, cmd_bytes)?;
267        results.push(result);
268
269        remaining_ldcmds = &remaining_ldcmds[cmdsize..];
270    }
271
272    Ok(results)
273}
274
275impl LoadCommand {
276    pub fn parse_all<T>(buf: &mut T, header: MachHeader) -> MachOResult<Vec<Self>>
277    where
278        T: Seek + Read,
279    {
280        let cmds =
281            iterate_load_commands(
282                buf,
283                header,
284                |base, ldcmd| LoadCommand::parse(base, ldcmd) 
285            )?;
286
287        Ok(cmds)
288    }
289
290    pub fn parse(
291        base: LoadCommandBase,
292        ldcmd: &[u8],
293    ) -> MachOResult<Self>
294    {
295        match base.cmd {
296            LCLoadCommand::LcSegment => {
297                Ok(LoadCommand::Segment32(SegmentCommand32::parse(ldcmd)?))
298            }
299            LCLoadCommand::LcSegment64 => {
300                Ok(LoadCommand::Segment64(SegmentCommand64::parse(ldcmd)?))
301            }
302            LCLoadCommand::LcLoadDylib
303            | LCLoadCommand::LcIdDylib
304            | LCLoadCommand::LcLoadWeakDylib
305            | LCLoadCommand::LcReexportDylib
306            | LCLoadCommand::LcLazyLoadDylib
307            | LCLoadCommand::LcLoadUpwardDylib => {
308                let cmd = DylibCommand::parse(ldcmd)?;
309                match base.clone().cmd {
310                    LCLoadCommand::LcLoadDylib => Ok(LoadCommand::LoadDylib(cmd)),
311                    LCLoadCommand::LcIdDylib => Ok(LoadCommand::DylibId(cmd)),
312                    LCLoadCommand::LcLoadWeakDylib => Ok(LoadCommand::LoadWeakDylib(cmd)),
313                    LCLoadCommand::LcReexportDylib => Ok(LoadCommand::ReexportDylib(cmd)),
314                    LCLoadCommand::LcLazyLoadDylib => Ok(LoadCommand::LazyLoadDylib(cmd)),
315                    LCLoadCommand::LcLoadUpwardDylib => {
316                        Ok(LoadCommand::LoadUpwardDylib(cmd))
317                    }
318                    _ => unreachable!(),
319                }
320            }
321            LCLoadCommand::LcSymtab => {
322                Ok(LoadCommand::Symtab(SymtabCommand::parse(ldcmd)?))
323            }
324            LCLoadCommand::LcSymseg => {
325                Ok(LoadCommand::Symseg(SymsegCommand::parse(ldcmd)?))
326            }
327            LCLoadCommand::LcThread | LCLoadCommand::LcUnixThread => {
328                let cmd = ThreadCommand::parse(ldcmd)?;
329                match base.cmd {
330                    LCLoadCommand::LcThread => Ok(LoadCommand::Thread(cmd)),
331                    LCLoadCommand::LcUnixThread => Ok(LoadCommand::UnixThread(cmd)),
332                    _ => unreachable!(),
333                }
334            }
335            LCLoadCommand::LcDysymtab => {
336                Ok(LoadCommand::Dysymtab(DysymtabCommand::parse(ldcmd)?))
337            }
338            LCLoadCommand::LcLoadDylinker
339            | LCLoadCommand::LcIdDylinker
340            | LCLoadCommand::LcDyldEnvironment => {
341                let cmd = DylinkerCommand::parse(ldcmd)?;
342                match base.cmd {
343                    LCLoadCommand::LcLoadDylinker => Ok(LoadCommand::LoadDylinker(cmd)),
344                    LCLoadCommand::LcIdDylinker => Ok(LoadCommand::IdDylinker(cmd)),
345                    LCLoadCommand::LcDyldEnvironment => {
346                        Ok(LoadCommand::DyldEnvironment(cmd))
347                    }
348                    _ => unreachable!(),
349                }
350            }
351            LCLoadCommand::LcPreboundDylib => {
352                Ok(LoadCommand::PreboundDylib(PreboundDylibCommand::parse(ldcmd)?))
353            }
354            LCLoadCommand::LcRoutines | LCLoadCommand::LcRoutines64 => {
355                let cmd = RoutinesCommand64::parse(ldcmd)?;
356                match base.cmd {
357                    LCLoadCommand::LcRoutines => Ok(LoadCommand::Routines(cmd)),
358                    LCLoadCommand::LcRoutines64 => Ok(LoadCommand::Routines64(cmd)),
359                    _ => unreachable!(),
360                }
361            }
362            LCLoadCommand::LcSubFramework => {
363                Ok(LoadCommand::SubFramework(SubFrameworkCommand::parse(ldcmd)?))
364            }
365            LCLoadCommand::LcSubUmbrella => {
366                Ok(LoadCommand::SubUmbrella(SubUmbrellaCommand::parse(ldcmd)?))
367            }
368            LCLoadCommand::LcSubClient => {
369                Ok(LoadCommand::SubClient(SubClientCommand::parse(ldcmd)?))
370            }
371            LCLoadCommand::LcSubLibrary => {
372                Ok(LoadCommand::SubLibrary(SubLibraryCommand::parse(ldcmd)?))
373            }
374            LCLoadCommand::LcTwolevelHints => {
375                Ok(LoadCommand::TwoLevelHints(TwoLevelHintsCommand::parse(ldcmd)?))
376            }
377            LCLoadCommand::LcPrebindCksum => {
378                Ok(LoadCommand::PrebindCksum(PrebindCksumCommand::parse(ldcmd)?))
379            }
380            LCLoadCommand::LcUuid => {
381                Ok(LoadCommand::UUID(UuidCommand::parse(ldcmd)?))
382            }
383            LCLoadCommand::LcRpath => {
384                Ok(LoadCommand::Rpath(RpathCommand::parse(ldcmd)?))
385            }
386            LCLoadCommand::LcFunctionStarts => {
387                Ok(LoadCommand::FunctionStarts(FunctionStartsCommand::parse(ldcmd)?))
388            }
389            LCLoadCommand::LcCodeSignature => {
390                Ok(LoadCommand::CodeSignature(CodeSignCommand::parse(ldcmd)?))
391            }
392            LCLoadCommand::LcDyldChainedFixups => {
393                Ok(LoadCommand::DyldChainedFixups(DyldChainedFixupCommand::parse(ldcmd)?))
394            }
395            LCLoadCommand::LcDyldExportsTrie => {
396                Ok(LoadCommand::DyldExportsTrie(DyldExportsTrie::parse(ldcmd)?))
397            }
398            LCLoadCommand::LcSegmentSplitInfo
399            | LCLoadCommand::LcDataInCode
400            | LCLoadCommand::LcDylibCodeSignDrs
401            | LCLoadCommand::LcLinkerOptimizationHint
402            | LCLoadCommand::LcAtomInfo => {
403                let (_, cmd) = LinkeditDataCommand::parse(ldcmd)?;
404                match base.cmd {
405                    LCLoadCommand::LcSegmentSplitInfo => {
406                        Ok(LoadCommand::SegmentSplitInfo(cmd))
407                    }
408                    LCLoadCommand::LcDataInCode => Ok(LoadCommand::DataInCode(cmd)),
409                    LCLoadCommand::LcDylibCodeSignDrs => {
410                        Ok(LoadCommand::DylibCodeSignDrs(cmd))
411                    }
412                    LCLoadCommand::LcLinkerOptimizationHint => {
413                        Ok(LoadCommand::LinkerOptimizationHint(cmd))
414                    }
415                    LCLoadCommand::LcAtomInfo => Ok(LoadCommand::AtomInfo(cmd)),
416                    _ => unreachable!(),
417                }
418            }
419            LCLoadCommand::LcEncryptionInfo => {
420                Ok(LoadCommand::EncryptionInfo(EncryptionInfoCommand::parse(ldcmd)?))
421            }
422            LCLoadCommand::LcDyldInfo | LCLoadCommand::LcDyldInfoOnly => {
423                let cmd = DyldInfoCommand::parse(ldcmd)?;
424                match base.cmd {
425                    LCLoadCommand::LcDyldInfo => Ok(LoadCommand::DyldInfo(cmd)),
426                    LCLoadCommand::LcDyldInfoOnly => Ok(LoadCommand::DyldInfoOnly(cmd)),
427                    _ => unreachable!(),
428                }
429            }
430            LCLoadCommand::LcVersionMinMacosx
431            | LCLoadCommand::LcVersionMinIphoneos
432            | LCLoadCommand::LcVersionMinTvos
433            | LCLoadCommand::LcVersionMinWatchos => {
434                let cmd = VersionMinCommand::parse(ldcmd)?;
435                match base.cmd {
436                    LCLoadCommand::LcVersionMinMacosx => {
437                        Ok(LoadCommand::VersionMinMacosx(cmd))
438                    }
439                    LCLoadCommand::LcVersionMinIphoneos => {
440                        Ok(LoadCommand::VersionMinIphoneos(cmd))
441                    }
442                    LCLoadCommand::LcVersionMinTvos => {
443                        Ok(LoadCommand::VersionMinTvos(cmd))
444                    }
445                    LCLoadCommand::LcVersionMinWatchos => {
446                        Ok(LoadCommand::VersionMinWatchos(cmd))
447                    }
448                    _ => unreachable!(),
449                }
450            }
451            LCLoadCommand::LcMain => {
452                Ok(LoadCommand::Main(EntryPointCommand::parse(ldcmd)?))
453            }
454            LCLoadCommand::LcSourceVersion => {
455                Ok(LoadCommand::SourceVersion(SourceVersionCommand::parse(ldcmd)?))
456            }
457            LCLoadCommand::LcEncryptionInfo64 => {
458                Ok(LoadCommand::EncryptionInfo64(EncryptionInfoCommand64::parse(ldcmd)?))
459            }
460            LCLoadCommand::LcLinkerOption => {
461                Ok(LoadCommand::LinkerOption(LinkerOptionCommand::parse(ldcmd)?))
462            }
463            LCLoadCommand::LcNote => {
464                Ok(LoadCommand::Note(NoteCommand::parse(ldcmd)?))
465            }
466            LCLoadCommand::LcBuildVersion => {
467                Ok(LoadCommand::BuildVersion(BuildVersionCommand::parse(ldcmd)?))
468            }
469            LCLoadCommand::LcFilesetEntry => {
470                Ok(LoadCommand::FilesetEntry(FilesetEntryCommand::parse(ldcmd)?))
471            }
472            LCLoadCommand::None => Err(MachOErr::UnknownLoadCommand),
473        }
474    }
475
476    pub fn serialize(&self) -> Vec<u8> {
477        match self {
478            LoadCommand::None => vec![],
479            LoadCommand::Segment32(cmd) => cmd.serialize(),
480            LoadCommand::Symtab(cmd) => cmd.serialize(),
481            LoadCommand::Symseg(cmd) => cmd.serialize(),
482            LoadCommand::Thread(cmd) => cmd.serialize(),
483            LoadCommand::UnixThread(cmd) => cmd.serialize(),
484            LoadCommand::Dysymtab(cmd) => cmd.serialize(),
485            LoadCommand::LoadDylib(cmd) => cmd.serialize(),
486            LoadCommand::DylibId(cmd) => cmd.serialize(),
487            LoadCommand::LoadDylinker(cmd) => cmd.serialize(),
488            LoadCommand::IdDylinker(cmd) => cmd.serialize(),
489            LoadCommand::PreboundDylib(cmd) => cmd.serialize(),
490            LoadCommand::Routines(cmd) => cmd.serialize(),
491            LoadCommand::SubFramework(cmd) => cmd.serialize(),
492            LoadCommand::SubUmbrella(cmd) => cmd.serialize(),
493            LoadCommand::SubClient(cmd) => cmd.serialize(),
494            LoadCommand::SubLibrary(cmd) => cmd.serialize(),
495            LoadCommand::TwoLevelHints(cmd) => cmd.serialize(),
496            LoadCommand::PrebindCksum(cmd) => cmd.serialize(),
497            LoadCommand::LoadWeakDylib(cmd) => cmd.serialize(),
498            LoadCommand::Segment64(cmd) => cmd.serialize(),
499            LoadCommand::Routines64(cmd) => cmd.serialize(),
500            LoadCommand::UUID(cmd) => cmd.serialize(),
501            LoadCommand::Rpath(cmd) => cmd.serialize(),
502            LoadCommand::CodeSignature(cmd) => cmd.serialize(),
503            LoadCommand::SegmentSplitInfo(cmd) => cmd.serialize(),
504            LoadCommand::ReexportDylib(cmd) => cmd.serialize(),
505            LoadCommand::LazyLoadDylib(cmd) => cmd.serialize(),
506            LoadCommand::EncryptionInfo(cmd) => cmd.serialize(),
507            LoadCommand::DyldInfo(cmd) => cmd.serialize(),
508            LoadCommand::DyldInfoOnly(cmd) => cmd.serialize(),
509            LoadCommand::LoadUpwardDylib(cmd) => cmd.serialize(),
510            LoadCommand::VersionMinMacosx(cmd) => cmd.serialize(),
511            LoadCommand::VersionMinIphoneos(cmd) => cmd.serialize(),
512            LoadCommand::FunctionStarts(cmd) => cmd.serialize(),
513            LoadCommand::DyldEnvironment(cmd) => cmd.serialize(),
514            LoadCommand::Main(cmd) => cmd.serialize(),
515            LoadCommand::DataInCode(cmd) => cmd.serialize(),
516            LoadCommand::SourceVersion(cmd) => cmd.serialize(),
517            LoadCommand::DylibCodeSignDrs(cmd) => cmd.serialize(),
518            LoadCommand::EncryptionInfo64(cmd) => cmd.serialize(),
519            LoadCommand::LinkerOption(cmd) => cmd.serialize(),
520            LoadCommand::LinkerOptimizationHint(cmd) => cmd.serialize(),
521            LoadCommand::VersionMinTvos(cmd) => cmd.serialize(),
522            LoadCommand::VersionMinWatchos(cmd) => cmd.serialize(),
523            LoadCommand::Note(cmd) => cmd.serialize(),
524            LoadCommand::BuildVersion(cmd) => cmd.serialize(),
525            LoadCommand::DyldExportsTrie(cmd) => cmd.serialize(),
526            LoadCommand::DyldChainedFixups(cmd) => cmd.serialize(),
527            LoadCommand::FilesetEntry(cmd) => cmd.serialize(),
528            LoadCommand::AtomInfo(cmd) => cmd.serialize(),
529        }
530    }
531}