Line data Source code
1 : use super::commands::segment::Segment;
2 : use super::thread_local_variables::ThreadLocalVariables;
3 : use super::Relocation;
4 : use lief_ffi as ffi;
5 : use std::fmt;
6 : use std::marker::PhantomData;
7 : use std::pin::Pin;
8 :
9 : use crate::common::{into_optional, FromFFI};
10 : use crate::declare_iterator;
11 : use crate::generic;
12 :
13 : use bitflags::bitflags;
14 :
15 : /// Enum that wraps all the Mach-O section types, dispatching to the
16 : /// appropriate concrete type when extra semantics are available.
17 304681 : #[derive(Debug)]
18 : pub enum Section<'a> {
19 : /// A section without additional specialization.
20 : Generic(Generic<'a>),
21 :
22 : /// A section whose type is [`Type::THREAD_LOCAL_VARIABLES`], providing access
23 : /// to thread-local variable descriptors.
24 : ThreadLocalVariables(ThreadLocalVariables<'a>),
25 : }
26 :
27 : pub struct Generic<'a> {
28 : ptr: cxx::UniquePtr<ffi::MachO_Section>,
29 : _owner: PhantomData<&'a ()>,
30 : }
31 :
32 : #[allow(non_camel_case_types)]
33 304642 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
34 : pub enum Type {
35 : /// Regular section.
36 : REGULAR,
37 : /// Zero fill on demand section.
38 : ZEROFILL,
39 : /// Section with literal C strings.
40 : CSTRING_LITERALS,
41 : /// Section with 4 byte literals.
42 : S_4BYTE_LITERALS,
43 : /// Section with 8 byte literals.
44 : S_8BYTE_LITERALS,
45 : /// Section with pointers to literals.
46 : LITERAL_POINTERS,
47 : /// Section with non-lazy symbol pointers.
48 : NON_LAZY_SYMBOL_POINTERS,
49 : /// Section with lazy symbol pointers.
50 : LAZY_SYMBOL_POINTERS,
51 : /// Section with symbol stubs, byte size of stub in the Reserved2 field.
52 : SYMBOL_STUBS,
53 : /// Section with only function pointers for initialization.
54 : MOD_INIT_FUNC_POINTERS,
55 : /// Section with only function pointers for termination.
56 : MOD_TERM_FUNC_POINTERS,
57 : /// Section contains symbols that are to be coalesced.
58 : COALESCED,
59 : /// Zero fill on demand section (that can be larger than 4 gigabytes).
60 : GB_ZEROFILL,
61 : /// Section with only pairs of function pointers for interposing.
62 : INTERPOSING,
63 : /// Section with only 16 byte literals.
64 : S_16BYTE_LITERALS,
65 : /// Section contains DTrace Object Format.
66 : DTRACE_DOF,
67 : /// Section with lazy symbol pointers to lazy loaded dylibs.
68 : LAZY_DYLIB_SYMBOL_POINTERS,
69 : /// Thread local data section.
70 : THREAD_LOCAL_REGULAR,
71 : /// Thread local zerofill section.
72 : THREAD_LOCAL_ZEROFILL,
73 : /// Section with thread local variable structure data.
74 : THREAD_LOCAL_VARIABLES,
75 : /// Section with pointers to thread local structures.
76 : THREAD_LOCAL_VARIABLE_POINTERS,
77 : /// Section with thread local variable initialization pointers to functions.
78 : THREAD_LOCAL_INIT_FUNCTION_POINTERS,
79 : /// Section with 32-bit offsets to initializer functions
80 : INIT_FUNC_OFFSETS,
81 : UNKNOWN(u64),
82 : }
83 :
84 : impl From<u64> for Type {
85 304837 : fn from(value: u64) -> Self {
86 304837 : match value {
87 252785 : 0x00000000 => Type::REGULAR,
88 702 : 0x00000001 => Type::ZEROFILL,
89 637 : 0x00000002 => Type::CSTRING_LITERALS,
90 0 : 0x00000003 => Type::S_4BYTE_LITERALS,
91 0 : 0x00000004 => Type::S_8BYTE_LITERALS,
92 78 : 0x00000005 => Type::LITERAL_POINTERS,
93 21879 : 0x00000006 => Type::NON_LAZY_SYMBOL_POINTERS,
94 17381 : 0x00000007 => Type::LAZY_SYMBOL_POINTERS,
95 3081 : 0x00000008 => Type::SYMBOL_STUBS,
96 325 : 0x00000009 => Type::MOD_INIT_FUNC_POINTERS,
97 0 : 0x0000000a => Type::MOD_TERM_FUNC_POINTERS,
98 7813 : 0x0000000b => Type::COALESCED,
99 0 : 0x0000000c => Type::GB_ZEROFILL,
100 0 : 0x0000000d => Type::INTERPOSING,
101 26 : 0x0000000e => Type::S_16BYTE_LITERALS,
102 52 : 0x0000000f => Type::DTRACE_DOF,
103 0 : 0x00000010 => Type::LAZY_DYLIB_SYMBOL_POINTERS,
104 0 : 0x00000011 => Type::THREAD_LOCAL_REGULAR,
105 26 : 0x00000012 => Type::THREAD_LOCAL_ZEROFILL,
106 26 : 0x00000013 => Type::THREAD_LOCAL_VARIABLES,
107 0 : 0x00000014 => Type::THREAD_LOCAL_VARIABLE_POINTERS,
108 0 : 0x00000015 => Type::THREAD_LOCAL_INIT_FUNCTION_POINTERS,
109 26 : 0x00000016 => Type::INIT_FUNC_OFFSETS,
110 0 : _ => Type::UNKNOWN(value),
111 : }
112 304837 : }
113 : }
114 :
115 0 : bitflags! {
116 304642 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
117 0 : pub struct Flags: u64 {
118 0 : const PURE_INSTRUCTIONS = 0x80000000;
119 0 : const NO_TOC = 0x40000000;
120 0 : const STRIP_STATIC_SYMS = 0x20000000;
121 0 : const NO_DEAD_STRIP = 0x10000000;
122 0 : const LIVE_SUPPORT = 0x8000000;
123 0 : const SELF_MODIFYING_CODE = 0x4000000;
124 0 : const DEBUG_INFO = 0x2000000;
125 0 : const SOME_INSTRUCTIONS = 0x400;
126 0 : const EXT_RELOC = 0x200;
127 0 : const LOC_RELOC = 0x100;
128 0 : }
129 0 : }
130 :
131 : impl From<u64> for Flags {
132 0 : fn from(value: u64) -> Self {
133 0 : Flags::from_bits_truncate(value)
134 0 : }
135 : }
136 : impl From<Flags> for u64 {
137 0 : fn from(value: Flags) -> Self {
138 0 : value.bits()
139 0 : }
140 : }
141 : impl std::fmt::Display for Flags {
142 0 : fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
143 0 : bitflags::parser::to_writer(self, f)
144 0 : }
145 : }
146 :
147 : /// Trait shared by **all** Mach-O section types in the [`Section`] enum.
148 : pub trait MachOSection {
149 : #[doc(hidden)]
150 : fn as_base(&self) -> &ffi::MachO_Section;
151 :
152 : #[doc(hidden)]
153 : fn as_mut_base(&mut self) -> Pin<&mut ffi::MachO_Section>;
154 :
155 : /// Name of the segment that owns this section
156 304643 : fn segment_name(&self) -> String {
157 304643 : self.as_base().segment_name().to_string()
158 304643 : }
159 :
160 : /// Virtual base address of this section
161 304642 : fn address(&self) -> u64 {
162 304642 : self.as_base().address()
163 304642 : }
164 :
165 : /// Section alignment as a power of 2
166 304642 : fn alignment(&self) -> u32 {
167 304642 : self.as_base().alignment()
168 304642 : }
169 :
170 : /// Offset of the relocation table. This value should be 0
171 : /// for executable and libraries as the relocations are managed by
172 : /// [`crate::macho::Relocation::Dyld`] or [`crate::macho::Relocation::Fixup`]
173 : ///
174 : /// On the other hand, for object files (`.o`) this value should not be 0 (c.f. [`crate::macho::Relocation::Object`])
175 304642 : fn relocation_offset(&self) -> u32 {
176 304642 : self.as_base().relocation_offset()
177 304642 : }
178 :
179 : /// Number of relocations associated with this section
180 304642 : fn numberof_relocations(&self) -> u32 {
181 304642 : self.as_base().numberof_relocations()
182 304642 : }
183 :
184 304642 : fn raw_flags(&self) -> u32 {
185 304642 : self.as_base().raw_flags()
186 304642 : }
187 :
188 : /// Section's flags masked with `SECTION_FLAGS_MASK`
189 304642 : fn flags(&self) -> Flags {
190 304642 : Flags::from_bits_truncate(self.as_base().flags())
191 304642 : }
192 :
193 : /// Type of the section. This value can help to determine the purpose of the section
194 304657 : fn section_type(&self) -> Type {
195 304657 : Type::from(self.as_base().section_type())
196 304657 : }
197 :
198 : /// According to the official `loader.h` file, this value is reserved
199 : /// for *offset* or *index*
200 304642 : fn reserved1(&self) -> u32 {
201 304642 : self.as_base().reserved1()
202 304642 : }
203 :
204 : /// According to the official `loader.h` file, this value is reserved
205 : /// for *count* or *sizeof*
206 304642 : fn reserved2(&self) -> u32 {
207 304642 : self.as_base().reserved2()
208 304642 : }
209 :
210 : /// This value is only present for 64 bits Mach-O files. In that case,
211 : /// the value is *reserved*.
212 304642 : fn reserved3(&self) -> u32 {
213 304642 : self.as_base().reserved3()
214 304642 : }
215 :
216 : /// Segment bound to this section
217 317 : fn segment(&self) -> Option<Segment<'_>> {
218 317 : into_optional(self.as_base().segment())
219 317 : }
220 :
221 : /// Iterator over the [`crate::macho::Relocation`] associated with this section
222 317 : fn relocations(&self) -> Relocations<'_> {
223 317 : Relocations::new(self.as_base().relocations())
224 317 : }
225 : }
226 :
227 : impl MachOSection for Generic<'_> {
228 4578015 : fn as_base(&self) -> &ffi::MachO_Section {
229 4578015 : self.ptr.as_ref().unwrap()
230 4578015 : }
231 :
232 0 : fn as_mut_base(&mut self) -> Pin<&mut ffi::MachO_Section> {
233 0 : unsafe {
234 0 : Pin::new_unchecked({
235 0 : (self.ptr.as_ref().unwrap() as *const ffi::MachO_Section as *mut ffi::MachO_Section)
236 0 : .as_mut()
237 0 : .unwrap()
238 0 : })
239 0 : }
240 0 : }
241 : }
242 :
243 : impl MachOSection for Section<'_> {
244 8450 : fn as_base(&self) -> &ffi::MachO_Section {
245 8450 : match self {
246 8385 : Section::Generic(s) => s.as_base(),
247 65 : Section::ThreadLocalVariables(s) => s.as_base(),
248 : }
249 8450 : }
250 :
251 0 : fn as_mut_base(&mut self) -> Pin<&mut ffi::MachO_Section> {
252 0 : match self {
253 0 : Section::Generic(s) => s.as_mut_base(),
254 0 : Section::ThreadLocalVariables(s) => s.as_mut_base(),
255 : }
256 0 : }
257 : }
258 :
259 : impl fmt::Debug for Generic<'_> {
260 304642 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
261 304642 : let base = self as &dyn generic::Section;
262 304642 : f.debug_struct("Generic")
263 304642 : .field("base", &base)
264 304642 : .field("segment_name", &MachOSection::segment_name(self))
265 304642 : .field("address", &MachOSection::address(self))
266 304642 : .field("alignment", &MachOSection::alignment(self))
267 304642 : .field("relocation_offset", &MachOSection::relocation_offset(self))
268 304642 : .field(
269 304642 : "numberof_relocations",
270 304642 : &MachOSection::numberof_relocations(self),
271 304642 : )
272 304642 : .field("raw_flags", &MachOSection::raw_flags(self))
273 304642 : .field("flags", &MachOSection::flags(self))
274 304642 : .field("type", &MachOSection::section_type(self))
275 304642 : .field("reserved1", &MachOSection::reserved1(self))
276 304642 : .field("reserved2", &MachOSection::reserved2(self))
277 304642 : .field("reserved3", &MachOSection::reserved3(self))
278 304642 : .finish()
279 304642 : }
280 : }
281 :
282 : impl<'a> FromFFI<ffi::MachO_Section> for Generic<'a> {
283 304811 : fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_Section>) -> Self {
284 304811 : Self {
285 304811 : ptr,
286 304811 : _owner: PhantomData,
287 304811 : }
288 304811 : }
289 : }
290 :
291 : impl<'a> FromFFI<ffi::MachO_Section> for Section<'a> {
292 304850 : fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::MachO_Section>) -> Self {
293 304850 : unsafe {
294 304850 : let sec_ref = ffi_entry.as_ref().unwrap();
295 304850 : if ffi::MachO_ThreadLocalVariables::classof(sec_ref) {
296 39 : let raw = {
297 39 : type From = cxx::UniquePtr<ffi::MachO_Section>;
298 39 : type To = cxx::UniquePtr<ffi::MachO_ThreadLocalVariables>;
299 39 : std::mem::transmute::<From, To>(ffi_entry)
300 39 : };
301 39 : Section::ThreadLocalVariables(ThreadLocalVariables::from_ffi(raw))
302 : } else {
303 304811 : Section::Generic(Generic::from_ffi(ffi_entry))
304 : }
305 : }
306 304850 : }
307 : }
308 :
309 : impl generic::Section for Generic<'_> {
310 1218568 : fn as_generic(&self) -> &ffi::AbstractSection {
311 1218568 : self.as_base().as_ref()
312 1218568 : }
313 :
314 0 : fn as_generic_mut(&mut self) -> Pin<&mut ffi::AbstractSection> {
315 0 : unsafe {
316 0 : Pin::new_unchecked({
317 0 : (self.as_generic() as *const ffi::AbstractSection as *mut ffi::AbstractSection)
318 0 : .as_mut()
319 0 : .unwrap()
320 0 : })
321 0 : }
322 0 : }
323 : }
324 :
325 : impl generic::Section for Section<'_> {
326 13 : fn as_generic(&self) -> &ffi::AbstractSection {
327 13 : match self {
328 0 : Section::Generic(s) => s.as_generic(),
329 13 : Section::ThreadLocalVariables(s) => s.as_generic(),
330 : }
331 13 : }
332 :
333 0 : fn as_generic_mut(&mut self) -> Pin<&mut ffi::AbstractSection> {
334 0 : match self {
335 0 : Section::Generic(s) => s.as_generic_mut(),
336 0 : Section::ThreadLocalVariables(s) => s.as_generic_mut(),
337 : }
338 0 : }
339 : }
340 :
341 4303 : declare_iterator!(
342 4303 : Sections,
343 4303 : Section<'a>,
344 4303 : ffi::MachO_Section,
345 4303 : ffi::MachO_Binary,
346 4303 : ffi::MachO_Binary_it_sections
347 4303 : );
348 14976 : declare_iterator!(
349 14976 : Relocations,
350 14976 : Relocation<'a>,
351 14976 : ffi::MachO_Relocation,
352 14976 : ffi::MachO_Section,
353 14976 : ffi::MachO_Section_it_relocations
354 14976 : );
|