Line data Source code
1 : use super::commands::segment::Segment;
2 : use super::Relocation;
3 : use lief_ffi as ffi;
4 : use std::fmt;
5 : use std::marker::PhantomData;
6 :
7 : use crate::common::{into_optional, FromFFI};
8 : use crate::declare_iterator;
9 : use crate::generic;
10 :
11 : use bitflags::bitflags;
12 :
13 : pub struct Section<'a> {
14 : ptr: cxx::UniquePtr<ffi::MachO_Section>,
15 : _owner: PhantomData<&'a ()>,
16 : }
17 :
18 : #[allow(non_camel_case_types)]
19 169824 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
20 : pub enum Type {
21 : /// Regular section.
22 : REGULAR,
23 : /// Zero fill on demand section.
24 : ZEROFILL,
25 : /// Section with literal C strings.
26 : CSTRING_LITERALS,
27 : /// Section with 4 byte literals.
28 : S_4BYTE_LITERALS,
29 : /// Section with 8 byte literals.
30 : S_8BYTE_LITERALS,
31 : /// Section with pointers to literals.
32 : LITERAL_POINTERS,
33 : /// Section with non-lazy symbol pointers.
34 : NON_LAZY_SYMBOL_POINTERS,
35 : /// Section with lazy symbol pointers.
36 : LAZY_SYMBOL_POINTERS,
37 : /// Section with symbol stubs, byte size of stub in the Reserved2 field.
38 : SYMBOL_STUBS,
39 : /// Section with only function pointers for initialization.
40 : MOD_INIT_FUNC_POINTERS,
41 : /// Section with only function pointers for termination.
42 : MOD_TERM_FUNC_POINTERS,
43 : /// Section contains symbols that are to be coalesced.
44 : COALESCED,
45 : /// Zero fill on demand section (that can be larger than 4 gigabytes).
46 : GB_ZEROFILL,
47 : /// Section with only pairs of function pointers for interposing.
48 : INTERPOSING,
49 : /// Section with only 16 byte literals.
50 : S_16BYTE_LITERALS,
51 : /// Section contains DTrace Object Format.
52 : DTRACE_DOF,
53 : /// Section with lazy symbol pointers to lazy loaded dylibs.
54 : LAZY_DYLIB_SYMBOL_POINTERS,
55 : /// Thread local data section.
56 : THREAD_LOCAL_REGULAR,
57 : /// Thread local zerofill section.
58 : THREAD_LOCAL_ZEROFILL,
59 : /// Section with thread local variable structure data.
60 : THREAD_LOCAL_VARIABLES,
61 : /// Section with pointers to thread local structures.
62 : THREAD_LOCAL_VARIABLE_POINTERS,
63 : /// Section with thread local variable initialization pointers to functions.
64 : THREAD_LOCAL_INIT_FUNCTION_POINTERS,
65 : /// Section with 32-bit offsets to initializer functions
66 : INIT_FUNC_OFFSETS,
67 : UNKNOWN(u64),
68 : }
69 :
70 : impl From<u64> for Type {
71 169824 : fn from(value: u64) -> Self {
72 169824 : match value {
73 142680 : 0x00000000 => Type::REGULAR,
74 384 : 0x00000001 => Type::ZEROFILL,
75 352 : 0x00000002 => Type::CSTRING_LITERALS,
76 0 : 0x00000003 => Type::S_4BYTE_LITERALS,
77 0 : 0x00000004 => Type::S_8BYTE_LITERALS,
78 48 : 0x00000005 => Type::LITERAL_POINTERS,
79 13424 : 0x00000006 => Type::NON_LAZY_SYMBOL_POINTERS,
80 6208 : 0x00000007 => Type::LAZY_SYMBOL_POINTERS,
81 1856 : 0x00000008 => Type::SYMBOL_STUBS,
82 0 : 0x00000009 => Type::MOD_INIT_FUNC_POINTERS,
83 0 : 0x0000000a => Type::MOD_TERM_FUNC_POINTERS,
84 4808 : 0x0000000b => Type::COALESCED,
85 0 : 0x0000000c => Type::GB_ZEROFILL,
86 0 : 0x0000000d => Type::INTERPOSING,
87 16 : 0x0000000e => Type::S_16BYTE_LITERALS,
88 32 : 0x0000000f => Type::DTRACE_DOF,
89 0 : 0x00000010 => Type::LAZY_DYLIB_SYMBOL_POINTERS,
90 0 : 0x00000011 => Type::THREAD_LOCAL_REGULAR,
91 0 : 0x00000012 => Type::THREAD_LOCAL_ZEROFILL,
92 0 : 0x00000013 => Type::THREAD_LOCAL_VARIABLES,
93 0 : 0x00000014 => Type::THREAD_LOCAL_VARIABLE_POINTERS,
94 0 : 0x00000015 => Type::THREAD_LOCAL_INIT_FUNCTION_POINTERS,
95 16 : 0x00000016 => Type::INIT_FUNC_OFFSETS,
96 0 : _ => Type::UNKNOWN(value),
97 : }
98 169824 : }
99 : }
100 :
101 :
102 0 : bitflags! {
103 169824 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
104 0 : pub struct Flags: u64 {
105 0 : const PURE_INSTRUCTIONS = 0x80000000;
106 0 : const NO_TOC = 0x40000000;
107 0 : const STRIP_STATIC_SYMS = 0x20000000;
108 0 : const NO_DEAD_STRIP = 0x10000000;
109 0 : const LIVE_SUPPORT = 0x8000000;
110 0 : const SELF_MODIFYING_CODE = 0x4000000;
111 0 : const DEBUG_INFO = 0x2000000;
112 0 : const SOME_INSTRUCTIONS = 0x400;
113 0 : const EXT_RELOC = 0x200;
114 0 : const LOC_RELOC = 0x100;
115 0 : }
116 0 : }
117 :
118 :
119 : impl From<u64> for Flags {
120 0 : fn from(value: u64) -> Self {
121 0 : Flags::from_bits_truncate(value)
122 0 : }
123 : }
124 : impl From<Flags> for u64 {
125 0 : fn from(value: Flags) -> Self {
126 0 : value.bits()
127 0 : }
128 : }
129 : impl std::fmt::Display for Flags {
130 0 : fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
131 0 : bitflags::parser::to_writer(self, f)
132 0 : }
133 : }
134 :
135 : impl Section<'_> {
136 : /// Name of the segment that owns this section
137 169824 : pub fn segment_name(&self) -> String {
138 169824 : self.ptr.segment_name().to_string()
139 169824 : }
140 :
141 : /// Virtual base address of this section
142 169824 : pub fn address(&self) -> u64 {
143 169824 : self.ptr.address()
144 169824 : }
145 :
146 : /// Section alignment as a power of 2
147 169824 : pub fn alignment(&self) -> u32 {
148 169824 : self.ptr.alignment()
149 169824 : }
150 :
151 :
152 : /// Offset of the relocation table. This value should be 0
153 : /// for executable and libraries as the relocations are managed by
154 : /// [`crate::macho::Relocation::Dyld`] or [`crate::macho::Relocation::Fixup`]
155 : ///
156 : /// On the other hand, for object files (`.o`) this value should not be 0 (c.f. [`crate::macho::Relocation::Object`])
157 169824 : pub fn relocation_offset(&self) -> u32 {
158 169824 : self.ptr.relocation_offset()
159 169824 : }
160 :
161 : /// Number of relocations associated with this section
162 169824 : pub fn numberof_relocations(&self) -> u32 {
163 169824 : self.ptr.numberof_relocations()
164 169824 : }
165 :
166 169824 : pub fn raw_flags(&self) -> u32 {
167 169824 : self.ptr.raw_flags()
168 169824 : }
169 :
170 : /// Section's flags masked with `SECTION_FLAGS_MASK`
171 169824 : pub fn flags(&self) -> Flags {
172 169824 : Flags::from_bits_truncate(self.ptr.flags())
173 169824 : }
174 :
175 : /// Type of the section. This value can help to determine the purpose of the section
176 169824 : pub fn section_type(&self) -> Type {
177 169824 : Type::from(self.ptr.section_type())
178 169824 : }
179 :
180 : /// According to the official `loader.h` file, this value is reserved
181 : /// for *offset* or *index*
182 169824 : pub fn reserved1(&self) -> u32 {
183 169824 : self.ptr.reserved1()
184 169824 : }
185 :
186 : /// According to the official `loader.h` file, this value is reserved
187 : /// for *count* or *sizeof*
188 169824 : pub fn reserved2(&self) -> u32 {
189 169824 : self.ptr.reserved2()
190 169824 : }
191 :
192 : /// This value is only present for 64 bits Mach-O files. In that case,
193 : /// the value is *reserved*.
194 169824 : pub fn reserved3(&self) -> u32 {
195 169824 : self.ptr.reserved3()
196 169824 : }
197 :
198 : /// Segment bound to this section
199 1848 : pub fn segment(&self) -> Option<Segment> {
200 1848 : into_optional(self.ptr.segment())
201 1848 : }
202 :
203 : /// Iterator over the [`crate::macho::Relocation`] associated with thi section
204 1848 : pub fn relocations(&self) -> Relocations {
205 1848 : Relocations::new(self.ptr.relocations())
206 1848 : }
207 : }
208 :
209 : impl fmt::Debug for Section<'_> {
210 169824 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
211 169824 : let base = self as &dyn generic::Section;
212 169824 : f.debug_struct("Section")
213 169824 : .field("base", &base)
214 169824 : .field("segment_name", &self.segment_name())
215 169824 : .field("address", &self.address())
216 169824 : .field("alignment", &self.alignment())
217 169824 : .field("relocation_offset", &self.relocation_offset())
218 169824 : .field("numberof_relocations", &self.numberof_relocations())
219 169824 : .field("raw_flags", &self.raw_flags())
220 169824 : .field("flags", &self.flags())
221 169824 : .field("type", &self.section_type())
222 169824 : .field("reserved1", &self.reserved1())
223 169824 : .field("reserved2", &self.reserved2())
224 169824 : .field("reserved3", &self.reserved3())
225 169824 : .finish()
226 169824 : }
227 : }
228 :
229 : impl<'a> FromFFI<ffi::MachO_Section> for Section<'a> {
230 169824 : fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_Section>) -> Self {
231 169824 : Self {
232 169824 : ptr,
233 169824 : _owner: PhantomData,
234 169824 : }
235 169824 : }
236 : }
237 :
238 : impl generic::Section for Section<'_> {
239 679296 : fn as_generic(&self) -> &ffi::AbstractSection {
240 679296 : self.ptr.as_ref().unwrap().as_ref()
241 679296 : }
242 : }
243 :
244 1848 : declare_iterator!(
245 1848 : Sections,
246 1848 : Section<'a>,
247 1848 : ffi::MachO_Section,
248 1848 : ffi::MachO_Binary,
249 1848 : ffi::MachO_Binary_it_sections
250 1848 : );
251 9216 : declare_iterator!(
252 9216 : Relocations,
253 9216 : Relocation<'a>,
254 9216 : ffi::MachO_Relocation,
255 9216 : ffi::MachO_Section,
256 9216 : ffi::MachO_Section_it_relocations
257 9216 : );
|