Line data Source code
1 : use super::binary::Binary;
2 : use lief_ffi as ffi;
3 :
4 : use crate::{
5 : common::{into_optional, AsFFI, FromFFI},
6 : macho::header::CpuType,
7 : };
8 : use std::path::Path;
9 :
10 : /// This structure represents a FAT Mach-O
11 : pub struct FatBinary {
12 : pub nb_macho: u32,
13 : ptr: cxx::UniquePtr<ffi::MachO_FatBinary>,
14 : }
15 :
16 : impl FromFFI<ffi::MachO_FatBinary> for FatBinary {
17 416 : fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_FatBinary>) -> Self {
18 416 : Self {
19 416 : nb_macho: ptr.size(),
20 416 : ptr,
21 416 : }
22 416 : }
23 : }
24 :
25 : impl std::fmt::Debug for FatBinary {
26 0 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27 0 : f.debug_struct("FatBinary")
28 0 : .field("nb_macho", &self.nb_macho)
29 0 : .finish()
30 0 : }
31 : }
32 :
33 : /// Iterator over the different [`crate::macho::Binary`] wrapped by this FAT Mach-O
34 : pub struct FatBinaryIterator<'a> {
35 : index: u32,
36 : fat: &'a FatBinary,
37 : }
38 :
39 : impl FatBinary {
40 : /// Create a FatBinary from the given Mach-O path.
41 19 : pub fn parse<P: AsRef<Path>>(path: P) -> Option<Self> {
42 19 : let ffi = ffi::MachO_FatBinary::parse(path.as_ref().to_str().unwrap());
43 19 : if ffi.is_null() {
44 0 : return None;
45 19 : }
46 19 : Some(FatBinary::from_ffi(ffi))
47 19 : }
48 :
49 : /// Create a FatBinary from the given Mach-O path with the provided
50 : /// parser configuration.
51 0 : pub fn parse_with_config<P: AsRef<Path>>(
52 0 : path: P,
53 0 : config: &super::parser_config::Config,
54 0 : ) -> Option<Self> {
55 0 : let ffi_config = config.to_ffi();
56 0 : let ffi =
57 0 : ffi::MachO_FatBinary::parse_with_config(path.as_ref().to_str().unwrap(), &ffi_config);
58 0 : if ffi.is_null() {
59 0 : return None;
60 0 : }
61 0 : Some(FatBinary::from_ffi(ffi))
62 0 : }
63 :
64 : /// Gets the [`Binary`] that matches the given architecture
65 338 : pub fn with_cpu(&self, cpu: CpuType) -> Option<Binary> {
66 338 : into_optional(self.ptr.binary_from_arch(cpu.into()))
67 338 : }
68 :
69 : /// Iterator over the [`crate::macho::Binary`]
70 247 : pub fn iter(&self) -> FatBinaryIterator<'_> {
71 247 : FatBinaryIterator {
72 247 : index: 0,
73 247 : fat: self,
74 247 : }
75 247 : }
76 :
77 : /// Reconstruct the FAT binary object and write it to the given path
78 0 : pub fn write<P: AsRef<Path>>(&mut self, output: P) {
79 0 : self.ptr
80 0 : .as_mut()
81 0 : .unwrap()
82 0 : .write(output.as_ref().to_str().unwrap());
83 0 : }
84 : }
85 :
86 : impl AsFFI<ffi::MachO_FatBinary> for FatBinary {
87 0 : fn as_ffi(&self) -> &ffi::MachO_FatBinary {
88 0 : self.ptr.as_ref().unwrap()
89 0 : }
90 :
91 0 : fn as_mut_ffi(&mut self) -> std::pin::Pin<&mut ffi::MachO_FatBinary> {
92 0 : self.ptr.pin_mut()
93 0 : }
94 : }
95 :
96 : impl<'a> Iterator for FatBinaryIterator<'a> {
97 : type Item = Binary;
98 702 : fn next(&mut self) -> Option<Self::Item> {
99 702 : if self.index >= self.fat.nb_macho {
100 234 : return None;
101 468 : }
102 468 : self.index += 1;
103 468 : Some(Binary::from_ffi(self.fat.ptr.binary_at(self.index - 1)))
104 702 : }
105 : }
106 :
107 : impl<'a> ExactSizeIterator for FatBinaryIterator<'a> {
108 0 : fn len(&self) -> usize {
109 0 : self.fat.nb_macho.try_into().unwrap()
110 0 : }
111 : }
|