]> git.proxmox.com Git - rustc.git/blob - vendor/object/src/read/macho/load_command.rs
New upstream version 1.48.0+dfsg1
[rustc.git] / vendor / object / src / read / macho / load_command.rs
1 use core::marker::PhantomData;
2
3 use crate::endian::Endian;
4 use crate::macho;
5 use crate::pod::Bytes;
6 use crate::read::macho::{MachHeader, SymbolTable};
7 use crate::read::{ReadError, Result, StringTable};
8
9 /// An iterator over the load commands of a `MachHeader`.
10 #[derive(Debug, Default, Clone, Copy)]
11 pub struct MachOLoadCommandIterator<'data, E: Endian> {
12 endian: E,
13 data: Bytes<'data>,
14 ncmds: u32,
15 }
16
17 impl<'data, E: Endian> MachOLoadCommandIterator<'data, E> {
18 pub(super) fn new(endian: E, data: Bytes<'data>, ncmds: u32) -> Self {
19 MachOLoadCommandIterator {
20 endian,
21 data,
22 ncmds,
23 }
24 }
25
26 /// Return the next load command.
27 pub fn next(&mut self) -> Result<Option<MachOLoadCommand<'data, E>>> {
28 if self.ncmds == 0 {
29 return Ok(None);
30 }
31 let header = self
32 .data
33 .read_at::<macho::LoadCommand<E>>(0)
34 .read_error("Invalid Mach-O load command header")?;
35 let cmd = header.cmd.get(self.endian);
36 let cmdsize = header.cmdsize.get(self.endian) as usize;
37 let data = self
38 .data
39 .read_bytes(cmdsize)
40 .read_error("Invalid Mach-O load command size")?;
41 self.ncmds -= 1;
42 Ok(Some(MachOLoadCommand {
43 cmd,
44 data,
45 marker: Default::default(),
46 }))
47 }
48 }
49
50 /// A parsed `LoadCommand`.
51 #[derive(Debug, Clone, Copy)]
52 pub struct MachOLoadCommand<'data, E: Endian> {
53 cmd: u32,
54 // Includes the header.
55 data: Bytes<'data>,
56 marker: PhantomData<E>,
57 }
58
59 impl<'data, E: Endian> MachOLoadCommand<'data, E> {
60 /// Try to parse this command as a `SegmentCommand32`.
61 pub fn segment_32(self) -> Result<Option<(&'data macho::SegmentCommand32<E>, Bytes<'data>)>> {
62 if self.cmd == macho::LC_SEGMENT {
63 let mut data = self.data;
64 let command = data
65 .read()
66 .read_error("Invalid Mach-O LC_SEGMENT command size")?;
67 Ok(Some((command, data)))
68 } else {
69 Ok(None)
70 }
71 }
72
73 /// Try to parse this command as a `SymtabCommand`.
74 pub fn symtab(self) -> Result<Option<&'data macho::SymtabCommand<E>>> {
75 if self.cmd == macho::LC_SYMTAB {
76 Some(
77 self.data
78 .clone()
79 .read()
80 .read_error("Invalid Mach-O LC_SYMTAB command size"),
81 )
82 .transpose()
83 } else {
84 Ok(None)
85 }
86 }
87
88 /// Try to parse this command as a `UuidCommand`.
89 pub fn uuid(self) -> Result<Option<&'data macho::UuidCommand<E>>> {
90 if self.cmd == macho::LC_UUID {
91 Some(
92 self.data
93 .clone()
94 .read()
95 .read_error("Invalid Mach-O LC_UUID command size"),
96 )
97 .transpose()
98 } else {
99 Ok(None)
100 }
101 }
102
103 /// Try to parse this command as a `SegmentCommand64`.
104 pub fn segment_64(self) -> Result<Option<(&'data macho::SegmentCommand64<E>, Bytes<'data>)>> {
105 if self.cmd == macho::LC_SEGMENT_64 {
106 let mut data = self.data;
107 let command = data
108 .read()
109 .read_error("Invalid Mach-O LC_SEGMENT_64 command size")?;
110 Ok(Some((command, data)))
111 } else {
112 Ok(None)
113 }
114 }
115
116 /// Try to parse this command as an `EntryPointCommand`.
117 pub fn entry_point(self) -> Result<Option<&'data macho::EntryPointCommand<E>>> {
118 if self.cmd == macho::LC_MAIN {
119 Some(
120 self.data
121 .clone()
122 .read()
123 .read_error("Invalid Mach-O LC_MAIN command size"),
124 )
125 .transpose()
126 } else {
127 Ok(None)
128 }
129 }
130 }
131
132 impl<E: Endian> macho::SymtabCommand<E> {
133 /// Return the symbol table that this command references.
134 pub fn symbols<'data, Mach: MachHeader<Endian = E>>(
135 &self,
136 endian: E,
137 data: Bytes<'data>,
138 ) -> Result<SymbolTable<'data, Mach>> {
139 let symbols = data
140 .read_slice_at(
141 self.symoff.get(endian) as usize,
142 self.nsyms.get(endian) as usize,
143 )
144 .read_error("Invalid Mach-O symbol table offset or size")?;
145 let strings = data
146 .read_bytes_at(
147 self.stroff.get(endian) as usize,
148 self.strsize.get(endian) as usize,
149 )
150 .read_error("Invalid Mach-O string table offset or size")?;
151 let strings = StringTable::new(strings);
152 Ok(SymbolTable::new(symbols, strings))
153 }
154 }