atom_macho/load_command/
mod.rs1pub mod build_version;
2pub mod dysymtab;
3pub mod segment64;
4pub mod source_version;
5pub mod symtab;
6pub mod unix_thread;
7pub mod uuid;
8
9pub use self::{
10 build_version::{BuildToolVersion, BuildVersionCommand},
11 dysymtab::DysymtabCommand,
12 segment64::{Section64, SegmentCommand64},
13 source_version::SourceVersionCommand,
14 symtab::SymtabCommand,
15 unix_thread::UnixThreadCommand,
16 uuid::UuidCommand,
17};
18
19use crate::io::{Endian, ReadExt as _};
20use byteorder::{BigEndian, LittleEndian, WriteBytesExt as _};
21use std::io::{Read, Write};
22
23#[derive(Debug, Clone, PartialEq, Eq)]
24pub enum LoadCommand {
25 Segment64(SegmentCommand64, Vec<Section64>),
26 Symtab(SymtabCommand),
27 UnixThread(UnixThreadCommand),
28 Dysymtab(DysymtabCommand),
29 Uuid(UuidCommand),
30 BuildVersion(BuildVersionCommand, Vec<BuildToolVersion>),
31 SourceVersion(SourceVersionCommand),
32 Unsupported(u32, Vec<u8>),
33}
34
35impl LoadCommand {
36 pub fn cmd(&self) -> u32 {
37 use LoadCommand as LC;
38
39 match self {
40 LC::Segment64(cmd, _) => cmd.cmd,
41 LC::Symtab(cmd) => cmd.cmd,
42 LC::UnixThread(cmd) => cmd.cmd,
43 LC::Dysymtab(cmd) => cmd.cmd,
44 LC::Uuid(cmd) => cmd.cmd,
45 LC::BuildVersion(cmd, _) => cmd.cmd,
46 LC::SourceVersion(cmd) => cmd.cmd,
47 LC::Unsupported(cmd, _) => *cmd,
48 }
49 }
50
51 pub fn cmd_size(&self) -> u32 {
52 use LoadCommand as LC;
53
54 match self {
55 LC::Segment64(cmd, _) => cmd.cmdsize,
56 LC::Symtab(cmd) => cmd.cmdsize,
57 LC::UnixThread(cmd) => cmd.cmdsize,
58 LC::Dysymtab(cmd) => cmd.cmdsize,
59 LC::Uuid(cmd) => cmd.cmdsize,
60 LC::BuildVersion(cmd, _) => cmd.cmdsize,
61 LC::SourceVersion(cmd) => cmd.cmdsize,
62 LC::Unsupported(_, data) => data.len() as u32 - 8,
63 }
64 }
65
66 pub fn read_from_in<R: Read>(read: &mut R, endian: Endian) -> Self {
67 use LoadCommand as LC;
68
69 let cmd = read.read_u32_in(endian);
70
71 let mut cmd_bytes = [0u8; 4];
72 match endian {
73 Endian::Little => (&mut cmd_bytes[..]).write_u32::<LittleEndian>(cmd).unwrap(),
74 Endian::Big => (&mut cmd_bytes[..]).write_u32::<BigEndian>(cmd).unwrap(),
75 };
76
77 let mut read = cmd_bytes.chain(read);
78
79 match cmd {
80 SegmentCommand64::TYPE => {
81 let cmd = SegmentCommand64::read_from_in(&mut read, endian);
82
83 let mut sections = Vec::with_capacity(cmd.nsects as usize);
84 for _ in 0..cmd.nsects {
85 sections.push(Section64::read_from_in(&mut read, endian));
86 }
87
88 LC::Segment64(cmd, sections)
89 }
90 SymtabCommand::TYPE => {
91 let cmd = SymtabCommand::read_from_in(&mut read, endian);
92 LC::Symtab(cmd)
93 }
94 UnixThreadCommand::TYPE => {
95 let cmd = UnixThreadCommand::read_from_in(&mut read, endian);
96 LC::UnixThread(cmd)
97 }
98 DysymtabCommand::TYPE => {
99 let cmd = DysymtabCommand::read_from_in(&mut read, endian);
100 LC::Dysymtab(cmd)
101 }
102 UuidCommand::TYPE => {
103 let cmd = UuidCommand::read_from_in(&mut read, endian);
104 LC::Uuid(cmd)
105 }
106 BuildVersionCommand::TYPE => {
107 let cmd = BuildVersionCommand::read_from_in(&mut read, endian);
108
109 let mut tools = Vec::with_capacity(cmd.ntools as usize);
110 for _ in 0..cmd.ntools {
111 tools.push(BuildToolVersion::read_from_in(&mut read, endian));
112 }
113 LC::BuildVersion(cmd, tools)
114 }
115 SourceVersionCommand::TYPE => {
116 let cmd = SourceVersionCommand::read_from_in(&mut read, endian);
117 LC::SourceVersion(cmd)
118 }
119 _ => {
120 let _cmd = read.read_u32_in(endian);
121 let cmdsize = read.read_u32_in(endian) as usize;
122 let mut data = Vec::with_capacity(cmdsize - 8);
123 data.resize(cmdsize - 8, 0);
124 read.read_exact(&mut data).unwrap();
125 LC::Unsupported(cmd, data)
126 }
127 }
128 }
129
130 pub fn write_into<W: Write>(&self, write: &mut W) {
131 use LoadCommand as LC;
132
133 match self {
134 LC::Segment64(cmd, sections) => {
135 cmd.write_into(write);
136 for section in sections.iter() {
137 section.write_into(write);
138 }
139 }
140 LC::Symtab(cmd) => {
141 cmd.write_into(write);
142 }
143 LC::UnixThread(cmd) => {
144 cmd.write_into(write);
145 }
146 LC::Dysymtab(cmd) => {
147 cmd.write_into(write);
148 }
149 LC::Uuid(cmd) => {
150 cmd.write_into(write);
151 }
152 LC::BuildVersion(cmd, tools) => {
153 cmd.write_into(write);
154 for tool in tools.iter() {
155 tool.write_into(write);
156 }
157 }
158 LC::SourceVersion(cmd) => {
159 cmd.write_into(write);
160 }
161 LC::Unsupported(_, _) => {
162 panic!("Unsupported LoadCommand is unwritable");
163 }
164 }
165 }
166}