Line data Source code
1 : use super::Command;
2 : use crate::common::{into_optional, FromFFI};
3 : use crate::declare_iterator;
4 : use crate::to_slice;
5 : use lief_ffi as ffi;
6 : use std::marker::PhantomData;
7 :
8 : use crate::macho::relocation::Relocation;
9 : use crate::macho::section::Section;
10 :
11 : use bitflags::bitflags;
12 :
13 0 : bitflags! {
14 0 : /// Segment flags
15 0 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
16 0 : pub struct Flags: u64 {
17 0 : const HIGHVM = 0x1;
18 0 : const FVMLIB = 0x2;
19 0 : const NORELOC = 0x4;
20 0 : const PROTECTED_VERSION_1 = 0x8;
21 0 : const READ_ONLY = 0x10;
22 0 : }
23 0 : }
24 :
25 : impl From<u64> for Flags {
26 0 : fn from(value: u64) -> Self {
27 0 : Flags::from_bits_truncate(value)
28 0 : }
29 : }
30 : impl From<Flags> for u64 {
31 0 : fn from(value: Flags) -> Self {
32 0 : value.bits()
33 0 : }
34 : }
35 : impl std::fmt::Display for Flags {
36 0 : fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
37 0 : bitflags::parser::to_writer(self, f)
38 0 : }
39 : }
40 :
41 0 : bitflags! {
42 0 : /// VM protection flags
43 0 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
44 0 : pub struct VmProtections: u32 {
45 0 : const READ = 0x1;
46 0 : const WRITE = 0x2;
47 0 : const EXECUTE = 0x4;
48 0 : }
49 0 : }
50 :
51 : impl From<u32> for VmProtections {
52 0 : fn from(value: u32) -> Self {
53 0 : VmProtections::from_bits_truncate(value)
54 0 : }
55 : }
56 : impl From<VmProtections> for u32 {
57 0 : fn from(value: VmProtections) -> Self {
58 0 : value.bits()
59 0 : }
60 : }
61 : impl std::fmt::Display for VmProtections {
62 0 : fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
63 0 : bitflags::parser::to_writer(self, f)
64 0 : }
65 : }
66 :
67 : /// Class which represents a `LC_SEGMENT/LC_SEGMENT_64` command
68 : pub struct Segment<'a> {
69 : ptr: cxx::UniquePtr<ffi::MachO_SegmentCommand>,
70 : _owner: PhantomData<&'a ffi::MachO_Binary>,
71 : }
72 :
73 : impl Segment<'_> {
74 : /// Name of the segment (e.g. `__TEXT`)
75 365235 : pub fn name(&self) -> String {
76 365235 : self.ptr.name().to_string()
77 365235 : }
78 :
79 : /// Absolute virtual base address of the segment
80 365235 : pub fn virtual_address(&self) -> u64 {
81 365235 : self.ptr.virtual_address()
82 365235 : }
83 :
84 : /// Virtual size of the segment
85 365235 : pub fn virtual_size(&self) -> u64 {
86 365235 : self.ptr.virtual_size()
87 365235 : }
88 :
89 : /// Size of this segment in the binary file
90 365235 : pub fn file_size(&self) -> u64 {
91 365235 : self.ptr.file_size()
92 365235 : }
93 :
94 : /// Offset of the data of this segment in the file
95 365235 : pub fn file_offset(&self) -> u64 {
96 365235 : self.ptr.file_offset()
97 365235 : }
98 :
99 : /// The maximum of protections for this segment
100 365235 : pub fn max_protection(&self) -> u32 {
101 365235 : self.ptr.max_protection()
102 365235 : }
103 :
104 : /// The initial protections of this segment
105 365235 : pub fn init_protection(&self) -> u32 {
106 365235 : self.ptr.init_protection()
107 365235 : }
108 :
109 : /// The number of sections associated with this segment
110 365235 : pub fn numberof_sections(&self) -> u32 {
111 365235 : self.ptr.numberof_sections()
112 365235 : }
113 :
114 : /// Flags associated with this segment
115 365235 : pub fn flags(&self) -> u32 {
116 365235 : self.ptr.flags()
117 365235 : }
118 :
119 : /// The raw content of this segment as a slice of bytes
120 1300 : pub fn content(&self) -> &[u8] {
121 1300 : to_slice!(self.ptr.content());
122 1300 : }
123 :
124 : /// Iterator over the [`crate::macho::Section`] owned by this segment
125 1300 : pub fn sections(&self) -> Sections<'_> {
126 1300 : Sections::new(self.ptr.sections())
127 1300 : }
128 :
129 : /// Return an iterator over the [`crate::macho::Relocation`] linked to this segment
130 : ///
131 : /// For Mach-O executable or library this iterator should be empty as
132 : /// the relocations are managed by the Dyld's rebase opcodes.
133 : /// On the other hand, for object files (`.o`) this iterator should not be empty.
134 1300 : pub fn relocations(&self) -> Relocations<'_> {
135 1300 : Relocations::new(self.ptr.relocations())
136 1300 : }
137 :
138 : /// The original index of this segment or -1 if not defined
139 0 : pub fn index(&self) -> Option<u8> {
140 0 : let idx = self.ptr.index();
141 0 : if idx < 0 {
142 0 : None
143 : } else {
144 0 : Some(idx as u8)
145 : }
146 0 : }
147 :
148 : /// Return the [`Section`] with the given name (if any)
149 0 : pub fn get_section(&self, name: &str) -> Option<Section<'_>> {
150 0 : into_optional(self.ptr.get_section(name.to_string()))
151 0 : }
152 : }
153 :
154 : impl std::fmt::Debug for Segment<'_> {
155 365235 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
156 365235 : let base = self as &dyn Command;
157 365235 : f.debug_struct("Segment")
158 365235 : .field("base", &base)
159 365235 : .field("name", &self.name())
160 365235 : .field("virtual_address", &self.virtual_address())
161 365235 : .field("virtual_size", &self.virtual_size())
162 365235 : .field("file_size", &self.file_size())
163 365235 : .field("file_offset", &self.file_offset())
164 365235 : .field("max_protection", &self.max_protection())
165 365235 : .field("init_protection", &self.init_protection())
166 365235 : .field("numberof_sections", &self.numberof_sections())
167 365235 : .field("flags", &self.flags())
168 365235 : .finish()
169 365235 : }
170 : }
171 :
172 : impl FromFFI<ffi::MachO_SegmentCommand> for Segment<'_> {
173 365235 : fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_SegmentCommand>) -> Self {
174 365235 : Self {
175 365235 : ptr: cmd,
176 365235 : _owner: PhantomData,
177 365235 : }
178 365235 : }
179 : }
180 :
181 : impl Command for Segment<'_> {
182 1460940 : fn get_base(&self) -> &ffi::MachO_Command {
183 1460940 : self.ptr.as_ref().unwrap().as_ref()
184 1460940 : }
185 : }
186 :
187 1300 : declare_iterator!(
188 1300 : Segments,
189 1300 : Segment<'a>,
190 1300 : ffi::MachO_SegmentCommand,
191 1300 : ffi::MachO_Binary,
192 1300 : ffi::MachO_Binary_it_segments
193 1300 : );
194 4121 : declare_iterator!(
195 4121 : Sections,
196 4121 : Section<'a>,
197 4121 : ffi::MachO_Section,
198 4121 : ffi::MachO_SegmentCommand,
199 4121 : ffi::MachO_SegmentCommand_it_sections
200 4121 : );
201 135018 : declare_iterator!(
202 135018 : Relocations,
203 135018 : Relocation<'a>,
204 135018 : ffi::MachO_Relocation,
205 135018 : ffi::MachO_SegmentCommand,
206 135018 : ffi::MachO_SegmentCommand_it_relocations
207 135018 : );
|