Line data Source code
1 : use num_traits::{cast, Num};
2 : use std::mem::size_of;
3 : use std::path::Path;
4 : use std::pin::Pin;
5 :
6 : use super::binding_info::BindingInfo;
7 : use super::builder::Config;
8 : use super::commands::atom_info::AtomInfo;
9 : use super::commands::build_version::{BuildVersion, Platform};
10 : use super::commands::code_signature::CodeSignature;
11 : use super::commands::code_signature_dir::CodeSignatureDir;
12 : use super::commands::data_in_code::DataInCode;
13 : use super::commands::dyld_chained_fixups::DyldChainedFixups;
14 : use super::commands::dyld_environment::DyldEnvironment;
15 : use super::commands::dyld_export_trie::DyldExportsTrie;
16 : use super::commands::dyldinfo::DyldInfo;
17 : use super::commands::dylib::Libraries;
18 : use super::commands::dylinker::Dylinker;
19 : use super::commands::dynamic_symbol_command::DynamicSymbolCommand;
20 : use super::commands::encryption_info::EncryptionInfo;
21 : use super::commands::function_variant_fixups::FunctionVariantFixups;
22 : use super::commands::function_variants::FunctionVariants;
23 : use super::commands::functionstarts::FunctionStarts;
24 : use super::commands::linker_opt_hint::LinkerOptHint;
25 : use super::commands::main_cmd::Main;
26 : use super::commands::note::Note;
27 : use super::commands::routine::Routine;
28 : use super::commands::rpath::RPath;
29 : use super::commands::rpath::RPaths;
30 : use super::commands::segment::{Segment, Segments};
31 : use super::commands::segment_split_info::SegmentSplitInfo;
32 : use super::commands::source_version::SourceVersion;
33 : use super::commands::sub_client::SubClients;
34 : use super::commands::sub_framework::SubFramework;
35 : use super::commands::symbol_command::SymbolCommand;
36 : use super::commands::thread_command::ThreadCommand;
37 : use super::commands::two_level_hints::TwoLevelHints;
38 : use super::commands::uuid::UUID;
39 : use super::commands::version_min::VersionMin;
40 : use super::commands::{Command, Commands, CommandsIter, Dylib, LoadCommandTypes};
41 : use super::export_info::ExportInfo;
42 : use super::header::Header;
43 : use super::relocation::Relocations;
44 : use super::section::{Section, Sections};
45 : use super::stub::Stub;
46 : use super::symbol::{Symbol, Symbols};
47 : use crate::Error;
48 : use lief_ffi as ffi;
49 :
50 : use crate::common::{into_optional, AsFFI, FromFFI};
51 : use crate::objc::Metadata;
52 : use crate::{declare_fwd_iterator, declare_iterator, generic, to_conv_result, to_result, to_slice};
53 :
54 : /// This is the main interface to read and write Mach-O binary attributes.
55 : ///
56 : /// Note that this structure implements the [`generic::Binary`] trait from which other generic
57 : /// functions are exposed
58 : pub struct Binary {
59 : ptr: cxx::UniquePtr<ffi::MachO_Binary>,
60 : }
61 :
62 : impl std::fmt::Debug for Binary {
63 416 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64 416 : f.debug_struct("Binary").finish()
65 416 : }
66 : }
67 :
68 : impl FromFFI<ffi::MachO_Binary> for Binary {
69 4355 : fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_Binary>) -> Self {
70 4355 : Binary { ptr }
71 4355 : }
72 : }
73 :
74 : impl Binary {
75 : /// Return the main Mach-O header
76 1248 : pub fn header(&self) -> Header<'_> {
77 1248 : Header::from_ffi(self.ptr.header())
78 1248 : }
79 :
80 : /// Return an iterator over the different [`crate::macho::Commands`] used by the
81 : /// Mach-O binary
82 416 : pub fn commands(&self) -> CommandsIter<'_> {
83 416 : CommandsIter::new(self.ptr.commands())
84 416 : }
85 :
86 : /// Return an iterator over the different [`crate::macho::Section`] of the binary
87 429 : pub fn sections(&self) -> Sections<'_> {
88 429 : Sections::new(self.ptr.sections())
89 429 : }
90 :
91 : /// Return an iterator over the different [`crate::macho::commands::Segment`] (`LC_SEGMENT/LC_SIGNATURE`)
92 : /// of the binary.
93 416 : pub fn segments(&self) -> Segments<'_> {
94 416 : Segments::new(self.ptr.segments())
95 416 : }
96 :
97 : /// Return an iterator over the [`crate::macho::commands::Dylib`] used by this binary
98 416 : pub fn libraries(&self) -> Libraries<'_> {
99 416 : Libraries::new(self.ptr.libraries())
100 416 : }
101 :
102 : /// Return an iterator over the different [`crate::macho::Relocation`] of this binary
103 416 : pub fn relocations(&self) -> Relocations<'_> {
104 416 : Relocations::new(self.ptr.relocations())
105 416 : }
106 :
107 : /// Return an iterator over the different [`crate::macho::commands::RPath`] of this binary
108 0 : pub fn rpaths(&self) -> RPaths<'_> {
109 0 : RPaths::new(self.ptr.rpaths())
110 0 : }
111 :
112 : /// Return an iterator over the different [`crate::macho::Symbol`] of this binary
113 416 : pub fn symbols(&self) -> Symbols<'_> {
114 416 : Symbols::new(self.ptr.symbols())
115 416 : }
116 :
117 : /// Return the `LC_DYLD_INFO/LC_DYLD_INFO_ONLY` command if present
118 416 : pub fn dyld_info(&self) -> Option<DyldInfo<'_>> {
119 416 : into_optional(self.ptr.dyld_info())
120 416 : }
121 :
122 : /// Return the `LC_UUID` command if present
123 416 : pub fn uuid(&self) -> Option<UUID<'_>> {
124 416 : into_optional(self.ptr.uuid())
125 416 : }
126 :
127 : /// Return the `LC_MAIN` command if present
128 416 : pub fn main_command(&self) -> Option<Main<'_>> {
129 416 : into_optional(self.ptr.main_command())
130 416 : }
131 :
132 : /// Return the `LC_LOAD_DYLINKER/LC_ID_DYLINKER` command if present
133 416 : pub fn dylinker(&self) -> Option<Dylinker<'_>> {
134 416 : into_optional(self.ptr.dylinker())
135 416 : }
136 :
137 : /// Return the `LC_FUNCTION_STARTS` command if present
138 416 : pub fn function_starts(&self) -> Option<FunctionStarts<'_>> {
139 416 : into_optional(self.ptr.function_starts())
140 416 : }
141 :
142 : /// Return the `LC_SOURCE_VERSION` command if present
143 416 : pub fn source_version(&self) -> Option<SourceVersion<'_>> {
144 416 : into_optional(self.ptr.source_version())
145 416 : }
146 :
147 : /// Return the `LC_THREAD/LC_UNIXTHREAD` command if present
148 416 : pub fn thread_command(&self) -> Option<ThreadCommand<'_>> {
149 416 : into_optional(self.ptr.thread_command())
150 416 : }
151 :
152 : /// Return the `LC_RPATH` command if present
153 416 : pub fn rpath(&self) -> Option<RPath<'_>> {
154 416 : into_optional(self.ptr.rpath())
155 416 : }
156 :
157 : /// Return the `LC_ROUTINE/LC_ROUTINE64` command if present
158 416 : pub fn routine(&self) -> Option<Routine<'_>> {
159 416 : into_optional(self.ptr.routine_command())
160 416 : }
161 :
162 : /// Return the `LC_SYMTAB` command if present
163 416 : pub fn symbol_command(&self) -> Option<SymbolCommand<'_>> {
164 416 : into_optional(self.ptr.symbol_command())
165 416 : }
166 :
167 : /// Return the `LC_DYSYMTAB` command if present
168 416 : pub fn dynamic_symbol(&self) -> Option<DynamicSymbolCommand<'_>> {
169 416 : into_optional(self.ptr.dynamic_symbol_command())
170 416 : }
171 :
172 : /// Return the `LC_CODE_SIGNATURE` command if present
173 416 : pub fn code_signature(&self) -> Option<CodeSignature<'_>> {
174 416 : into_optional(self.ptr.code_signature())
175 416 : }
176 :
177 : /// Return the `LC_DYLIB_CODE_SIGN_DRS` command if present
178 416 : pub fn code_signature_dir(&self) -> Option<CodeSignatureDir<'_>> {
179 416 : into_optional(self.ptr.code_signature_dir())
180 416 : }
181 :
182 : /// Return the `LC_DATA_IN_CODE` command if present
183 416 : pub fn data_in_code(&self) -> Option<DataInCode<'_>> {
184 416 : into_optional(self.ptr.data_in_code())
185 416 : }
186 :
187 : /// Return the `LC_SEGMENT_SPLIT_INFO` command if present
188 416 : pub fn segment_split_info(&self) -> Option<SegmentSplitInfo<'_>> {
189 416 : into_optional(self.ptr.segment_split_info())
190 416 : }
191 :
192 : /// Return the `LC_ENCRYPTION_INFO/LC_ENCRYPTION_INFO_64` command if present
193 416 : pub fn encryption_info(&self) -> Option<EncryptionInfo<'_>> {
194 416 : into_optional(self.ptr.encryption_info())
195 416 : }
196 :
197 : /// Return the `LC_SUB_FRAMEWORK` command if present
198 416 : pub fn sub_framework(&self) -> Option<SubFramework<'_>> {
199 416 : into_optional(self.ptr.sub_framework())
200 416 : }
201 :
202 : /// Return the `LC_SUBCLIENT` command if present
203 416 : pub fn subclients(&self) -> SubClients<'_> {
204 416 : SubClients::new(self.ptr.subclients())
205 416 : }
206 :
207 : /// Return the `LC_DYLD_ENVIRONMENT` command if present
208 416 : pub fn dyld_environment(&self) -> Option<DyldEnvironment<'_>> {
209 416 : into_optional(self.ptr.dyld_environment())
210 416 : }
211 :
212 : /// Return the `LC_BUILD_VERSION` command if present
213 416 : pub fn build_version(&self) -> Option<BuildVersion<'_>> {
214 416 : into_optional(self.ptr.build_version())
215 416 : }
216 :
217 : /// Return the `LC_DYLD_CHAINED_FIXUPS` command if present
218 416 : pub fn dyld_chained_fixups(&self) -> Option<DyldChainedFixups<'_>> {
219 416 : into_optional(self.ptr.dyld_chained_fixups())
220 416 : }
221 :
222 : /// Return the `LC_DYLD_EXPORTS_TRIE` command if present
223 416 : pub fn dyld_exports_trie(&self) -> Option<DyldExportsTrie<'_>> {
224 416 : into_optional(self.ptr.dyld_exports_trie())
225 416 : }
226 :
227 : /// Return the `LC_TWOLEVEL_HINTS` command if present
228 416 : pub fn two_level_hints(&self) -> Option<TwoLevelHints<'_>> {
229 416 : into_optional(self.ptr.two_level_hints())
230 416 : }
231 :
232 : /// Return the `LC_LINKER_OPTIMIZATION_HINT` command if present
233 416 : pub fn linker_opt_hint(&self) -> Option<LinkerOptHint<'_>> {
234 416 : into_optional(self.ptr.linker_opt_hint())
235 416 : }
236 :
237 : /// Return the `LC_ATOM_INFO` command if present
238 0 : pub fn atom_info(&self) -> Option<AtomInfo<'_>> {
239 0 : into_optional(self.ptr.atom_info())
240 0 : }
241 :
242 : /// Return the `LC_FUNCTION_VARIANTS` command if present
243 0 : pub fn function_variants(&self) -> Option<FunctionVariants<'_>> {
244 0 : into_optional(self.ptr.function_variants())
245 0 : }
246 :
247 : /// Return the `LC_FUNCTION_VARIANT_FIXUPS` command if present
248 0 : pub fn function_variant_fixups(&self) -> Option<FunctionVariantFixups<'_>> {
249 0 : into_optional(self.ptr.function_variant_fixups())
250 0 : }
251 :
252 : /// Return the `LC_VERSION_MIN_MACOSX/VERSION_MIN_IPHONEOS` command if present
253 416 : pub fn version_min(&self) -> Option<VersionMin<'_>> {
254 416 : into_optional(self.ptr.version_min())
255 416 : }
256 :
257 : /// Check if the binary is supporting ARM64 pointer authentication (arm64e)
258 0 : pub fn support_arm64_ptr_auth(&self) -> bool {
259 0 : self.ptr.support_arm64_ptr_auth()
260 0 : }
261 :
262 : /// Return an iterator over the bindings located in [`DyldInfo`] or [`DyldChainedFixups`]
263 416 : pub fn bindings(&self) -> BindingsInfo<'_> {
264 416 : BindingsInfo::new(self.ptr.bindings())
265 416 : }
266 :
267 : /// Return an iterator over the symbol stubs.
268 : ///
269 : /// These stubs are involved when calling an **imported** function and are
270 : /// similar to the ELF's plt/got mechanism.
271 : ///
272 : /// There are located in sections like: `__stubs,__auth_stubs,__symbol_stub,__picsymbolstub4`
273 416 : pub fn symbol_stubs(&self) -> Stubs<'_> {
274 416 : Stubs::new(self.ptr.symbol_stubs())
275 416 : }
276 :
277 : /// Return Objective-C metadata if present
278 0 : pub fn objc_metadata(&self) -> Option<Metadata<'_>> {
279 0 : into_optional(self.ptr.objc_metadata())
280 0 : }
281 :
282 : /// Return the platform for which this Mach-O has been compiled
283 416 : pub fn platform(&self) -> Platform {
284 416 : Platform::from(self.ptr.platform())
285 416 : }
286 :
287 : /// True if this binary targets iOS
288 416 : pub fn is_ios(&self) -> bool {
289 416 : self.ptr.is_ios()
290 416 : }
291 :
292 : /// True if this binary targets macOS
293 416 : pub fn is_macos(&self) -> bool {
294 416 : self.ptr.is_macos()
295 416 : }
296 :
297 : /// Try to find the library with the given library name.
298 : ///
299 : /// This function tries to match the fullpath of the DylibCommand or the
300 : /// library name suffix.
301 0 : pub fn find_library(&self, name: &str) -> Option<Dylib<'_>> {
302 0 : into_optional(self.ptr.find_library(name.to_string()))
303 0 : }
304 :
305 : /// Get the integer value at the given virtual address
306 0 : pub fn get_int_from_virtual_address<T>(&self, addr: u64) -> Result<T, Error>
307 0 : where
308 0 : T: Num + cast::FromPrimitive + cast::ToPrimitive,
309 0 : {
310 0 : // Can't be in the generic trait because of:
311 0 : // > for a trait to be "object safe" it needs to allow building a vtable to allow the call
312 0 : // > to be resolvable dynamically; for more information visit
313 0 : // > https://doc.rust-lang.org/reference/items/traits.html#object-safety
314 0 : if size_of::<T>() == size_of::<u8>() {
315 0 : to_conv_result!(
316 0 : ffi::AbstractBinary::get_u8,
317 0 : self.ptr.as_ref().unwrap().as_ref(),
318 0 : |value| {
319 0 : T::from_u8(value).unwrap_or_else(|| panic!("Can't cast value: {value}"))
320 0 : },
321 0 : addr
322 : );
323 0 : }
324 0 :
325 0 : if size_of::<T>() == size_of::<u16>() {
326 0 : to_conv_result!(
327 0 : ffi::AbstractBinary::get_u16,
328 0 : self.ptr.as_ref().unwrap().as_ref(),
329 0 : |value| {
330 0 : T::from_u16(value).unwrap_or_else(|| panic!("Can't cast value: {value}"))
331 0 : },
332 0 : addr
333 : );
334 0 : }
335 0 :
336 0 : if size_of::<T>() == size_of::<u32>() {
337 0 : to_conv_result!(
338 0 : ffi::AbstractBinary::get_u32,
339 0 : self.ptr.as_ref().unwrap().as_ref(),
340 0 : |value| {
341 0 : T::from_u32(value).unwrap_or_else(|| panic!("Can't cast value: {value}"))
342 0 : },
343 0 : addr
344 : );
345 0 : }
346 0 :
347 0 : if size_of::<T>() == size_of::<u64>() {
348 0 : to_conv_result!(
349 0 : ffi::AbstractBinary::get_u64,
350 0 : self.ptr.as_ref().unwrap().as_ref(),
351 0 : |value| {
352 0 : T::from_u64(value).unwrap_or_else(|| panic!("Can't cast value: {value}"))
353 0 : },
354 0 : addr
355 : );
356 0 : }
357 0 :
358 0 : Err(Error::NotSupported)
359 0 : }
360 :
361 : /// Write back the current MachO binary into the file specified in parameter
362 2 : pub fn write<P: AsRef<Path>>(&mut self, output: P) {
363 2 : self.ptr
364 2 : .as_mut()
365 2 : .unwrap()
366 2 : .write(output.as_ref().to_str().unwrap());
367 2 : }
368 :
369 : /// Write back the current MachO binary into the file specified in parameter with the
370 : /// configuration provided in the second parameter.
371 1 : pub fn write_with_config<P: AsRef<Path>>(&mut self, output: P, config: Config) {
372 1 : self.ptr
373 1 : .as_mut()
374 1 : .unwrap()
375 1 : .write_with_config(output.as_ref().to_str().unwrap(), config.to_ffi());
376 1 : }
377 :
378 : /// Insert a new command
379 0 : pub fn add_command(&mut self, command: impl Command) -> Option<Commands<'_>> {
380 0 : into_optional(self.ptr.as_mut().unwrap().add_command(command.get_base()))
381 0 : }
382 :
383 : /// Insert a new shared library through a `LC_LOAD_DYLIB` command
384 26 : pub fn add_library<'a>(&'a mut self, libname: &str) -> Dylib<'a> {
385 26 : Dylib::from_ffi(self.ptr.as_mut().unwrap().add_library(libname))
386 26 : }
387 :
388 : /// Remove all commands that have the given type
389 0 : pub fn remove_commands_by_type(&mut self, ty: LoadCommandTypes) -> bool {
390 0 : self.ptr
391 0 : .as_mut()
392 0 : .unwrap()
393 0 : .remove_commands_by_type(ty.into())
394 0 : }
395 :
396 416 : pub fn functions(&self) -> generic::Functions<'_> {
397 416 : generic::Functions::new(self.ptr.functions())
398 416 : }
399 :
400 : /// Return an iterator over the `LC_NOTE` commands
401 416 : pub fn notes(&self) -> Notes<'_> {
402 416 : Notes::new(self.ptr.notes())
403 416 : }
404 :
405 : /// Name associated with the `LC_FILESET_ENTRY` for this MachO.
406 : /// For instance: `com.apple.kec.corecrypto`
407 3809 : pub fn fileset_name(&self) -> String {
408 3809 : self.ptr.fileset_name().to_string()
409 3809 : }
410 :
411 : /// Original address associated with the `LC_FILESET_ENTRY` for this MachO.
412 3809 : pub fn fileset_addr(&self) -> u64 {
413 3809 : self.ptr.fileset_addr()
414 3809 : }
415 :
416 : /// Return an iterator over the [`Binary`] associated with the `LC_FILESET_ENTRY` commands
417 416 : pub fn filesets(&self) -> FilesetBinaries<'_> {
418 416 : FilesetBinaries::new(self.ptr.filesets())
419 416 : }
420 :
421 : /// Convert the given virtual address into an offset
422 0 : pub fn virtual_address_to_offset(&self, address: u64) -> Result<u64, Error> {
423 0 : to_result!(ffi::MachO_Binary::virtual_address_to_offset, &self, address);
424 0 : }
425 : /// Return the [`Segment`] associated with the given offset
426 0 : pub fn segment_from_offset(&self, offset: u64) -> Option<Segment<'_>> {
427 0 : into_optional(self.ptr.segment_from_offset(offset))
428 0 : }
429 :
430 : /// Return the [`Segment`] associated with the given virtual address
431 0 : pub fn segment_from_virtual_address(&self, va: u64) -> Option<Segment<'_>> {
432 0 : into_optional(self.ptr.segment_from_virtual_address(va))
433 0 : }
434 :
435 : /// Return the [`Section`] associated with the given virtual address
436 0 : pub fn section_from_virtual_address(&self, va: u64) -> Option<Section<'_>> {
437 0 : into_optional(self.ptr.section_from_virtual_address(va))
438 0 : }
439 :
440 : /// Return the [`Segment`] matching the given name
441 0 : pub fn get_segment(&self, name: String) -> Option<Segment<'_>> {
442 0 : into_optional(self.ptr.get_segment(name))
443 0 : }
444 :
445 : /// Return the [`Section`] embedded in the given segment's name
446 0 : pub fn get_section(&self, segment_name: String, section_name: String) -> Option<Section<'_>> {
447 0 : into_optional(self.ptr.get_section(segment_name, section_name))
448 0 : }
449 :
450 : /// Return the offset of this binary in the FAT binary
451 0 : pub fn fat_offset(&self) -> u64 {
452 0 : self.ptr.fat_offset()
453 0 : }
454 :
455 : /// Return the overlay data (if any)
456 0 : pub fn overlay(&self) -> &[u8] {
457 0 : to_slice!(self.ptr.overlay());
458 0 : }
459 :
460 : /// Return the TLV initial content range
461 0 : pub fn tlv_initial_content_range(&self) -> crate::Range {
462 0 : crate::Range::from_ffi(&self.ptr.tlv_initial_content_range())
463 0 : }
464 :
465 : /// Check if the given address is valid for this binary
466 0 : pub fn is_valid_addr(&self, address: u64) -> bool {
467 0 : self.ptr.is_valid_addr(address)
468 0 : }
469 :
470 : /// Check if the binary contains a symbol with the given name
471 0 : pub fn has_symbol(&self, name: &str) -> bool {
472 0 : self.ptr.has_symbol(name.to_string())
473 0 : }
474 :
475 : /// Return the symbol with the given name (if any)
476 0 : pub fn get_symbol(&self, name: &str) -> Option<Symbol<'_>> {
477 0 : into_optional(self.ptr.get_symbol(name.to_string()))
478 0 : }
479 :
480 : /// Check if the binary contains a section with the given name
481 0 : pub fn has_section(&self, name: &str) -> bool {
482 0 : self.ptr.has_section(name.to_string())
483 0 : }
484 :
485 : /// Return the [`Section`] associated with the given offset
486 0 : pub fn section_from_offset(&self, offset: u64) -> Option<Section<'_>> {
487 0 : into_optional(self.ptr.section_from_offset(offset))
488 0 : }
489 :
490 : /// Check if the binary contains a segment with the given name
491 0 : pub fn has_segment(&self, name: &str) -> bool {
492 0 : self.ptr.has_segment(name.to_string())
493 0 : }
494 :
495 : /// Check if the binary has a command with the given type
496 0 : pub fn has_command_type(&self, ty: LoadCommandTypes) -> bool {
497 0 : self.ptr.has_command_type(ty.into())
498 0 : }
499 :
500 : /// Get a command with the given type
501 0 : pub fn get_command_type(&self, ty: LoadCommandTypes) -> Option<Commands<'_>> {
502 0 : into_optional(self.ptr.get_command_type(ty.into()))
503 0 : }
504 :
505 : /// Remove the command at the given index
506 0 : pub fn remove_command(&mut self, index: u32) -> bool {
507 0 : self.ptr.as_mut().unwrap().remove_command(index)
508 0 : }
509 :
510 : /// Remove a section by name
511 0 : pub fn remove_section(&mut self, name: &str, clear: bool) {
512 0 : self.ptr
513 0 : .as_mut()
514 0 : .unwrap()
515 0 : .remove_section(name.to_string(), clear);
516 0 : }
517 :
518 : /// Remove a section by segment name and section name
519 0 : pub fn remove_section_from_segment(&mut self, segname: &str, secname: &str, clear: bool) {
520 0 : self.ptr.as_mut().unwrap().remove_section_seg(
521 0 : segname.to_string(),
522 0 : secname.to_string(),
523 0 : clear,
524 0 : );
525 0 : }
526 :
527 : /// Remove the `LC_CODE_SIGNATURE` command
528 0 : pub fn remove_signature(&mut self) -> bool {
529 0 : self.ptr.as_mut().unwrap().remove_signature()
530 0 : }
531 :
532 : /// Remove a symbol by name
533 0 : pub fn remove_symbol(&mut self, name: &str) -> bool {
534 0 : self.ptr.as_mut().unwrap().remove_symbol(name.to_string())
535 0 : }
536 :
537 : /// Check if the given symbol can be safely removed
538 0 : pub fn can_remove(&self, sym: &Symbol<'_>) -> bool {
539 0 : self.ptr.can_remove(sym.as_ffi())
540 0 : }
541 :
542 : /// Check if the symbol with the given name can be safely removed
543 0 : pub fn can_remove_symbol(&self, name: &str) -> bool {
544 0 : self.ptr.can_remove_symbol(name.to_string())
545 0 : }
546 :
547 : /// Unexport the symbol with the given name
548 0 : pub fn unexport_name(&mut self, name: &str) -> bool {
549 0 : self.ptr.as_mut().unwrap().unexport_name(name.to_string())
550 0 : }
551 :
552 : /// Unexport the given symbol
553 0 : pub fn unexport_symbol(&mut self, sym: &super::Symbol<'_>) -> bool {
554 0 : self.ptr.as_mut().unwrap().unexport_symbol(sym.as_ffi())
555 0 : }
556 :
557 : /// Add a new exported function
558 0 : pub fn add_exported_function(&mut self, address: u64, name: &str) -> Option<ExportInfo<'_>> {
559 0 : into_optional(
560 0 : self.ptr
561 0 : .as_mut()
562 0 : .unwrap()
563 0 : .add_exported_function(address, name.to_string()),
564 0 : )
565 0 : }
566 :
567 : /// Add a new local symbol
568 0 : pub fn add_local_symbol(&mut self, address: u64, name: &str) -> Option<Symbol<'_>> {
569 0 : into_optional(
570 0 : self.ptr
571 0 : .as_mut()
572 0 : .unwrap()
573 0 : .add_local_symbol(address, name.to_string()),
574 0 : )
575 0 : }
576 :
577 : /// Shift the content of the binary
578 0 : pub fn shift(&mut self, value: u64) -> Result<(), Error> {
579 0 : to_conv_result!(ffi::MachO_Binary::shift, self.ptr.pin_mut(), |_| (), value);
580 0 : }
581 :
582 : /// Shift the __LINKEDIT segment
583 0 : pub fn shift_linkedit(&mut self, width: u64) -> Result<(), Error> {
584 0 : to_conv_result!(
585 0 : ffi::MachO_Binary::shift_linkedit,
586 0 : self.ptr.pin_mut(),
587 0 : |_| (),
588 0 : width
589 : );
590 0 : }
591 : }
592 :
593 : impl AsFFI<ffi::MachO_Binary> for Binary {
594 0 : fn as_ffi(&self) -> &ffi::MachO_Binary {
595 0 : self.ptr.as_ref().unwrap()
596 0 : }
597 :
598 0 : fn as_mut_ffi(&mut self) -> std::pin::Pin<&mut ffi::MachO_Binary> {
599 0 : self.ptr.pin_mut()
600 0 : }
601 : }
602 :
603 : impl generic::Binary for Binary {
604 416 : fn as_generic(&self) -> &ffi::AbstractBinary {
605 416 : self.ptr.as_ref().unwrap().as_ref()
606 416 : }
607 :
608 0 : fn as_pin_mut_generic(&mut self) -> Pin<&mut ffi::AbstractBinary> {
609 0 : unsafe {
610 0 : Pin::new_unchecked({
611 0 : (self.ptr.as_ref().unwrap().as_ref() as *const ffi::AbstractBinary
612 0 : as *mut ffi::AbstractBinary)
613 0 : .as_mut()
614 0 : .unwrap()
615 0 : })
616 0 : }
617 0 : }
618 : }
619 :
620 90103 : declare_fwd_iterator!(
621 90103 : BindingsInfo,
622 90103 : BindingInfo<'a>,
623 90103 : ffi::MachO_BindingInfo,
624 90103 : ffi::MachO_Binary,
625 90103 : ffi::MachO_Binary_it_bindings_info
626 90103 : );
627 :
628 23478 : declare_iterator!(
629 23478 : Stubs,
630 23478 : Stub<'a>,
631 23478 : ffi::MachO_Stub,
632 23478 : ffi::MachO_Binary,
633 23478 : ffi::MachO_Binary_it_stubs
634 23478 : );
635 :
636 1560 : declare_iterator!(
637 1560 : Notes,
638 1560 : Note<'a>,
639 1560 : ffi::MachO_NoteCommand,
640 1560 : ffi::MachO_Binary,
641 1560 : ffi::MachO_Binary_it_notes
642 1560 : );
643 :
644 3809 : declare_iterator!(
645 3809 : FilesetBinaries,
646 3809 : Binary,
647 3809 : ffi::MachO_Binary,
648 3809 : ffi::MachO_Binary,
649 3809 : ffi::MachO_Binary_it_fileset_binaries
650 3809 : );
|