Line data Source code
1 : use super::Command;
2 : use lief_ffi as ffi;
3 :
4 : use crate::to_slice;
5 : use crate::{common::FromFFI, declare_iterator};
6 : use std::marker::PhantomData;
7 :
8 : /// Structure that represents the `LC_DATA_IN_CODE` command
9 : ///
10 : /// This command is used to list slices of code sections that contain data. The *slices*
11 : /// information are stored as an array of [`DataCodeEntry`]
12 : pub struct DataInCode<'a> {
13 : ptr: cxx::UniquePtr<ffi::MachO_DataInCode>,
14 : _owner: PhantomData<&'a ffi::MachO_Binary>,
15 : }
16 :
17 : impl DataInCode<'_> {
18 : /// Start of the array of the [`DataCodeEntry`] entries
19 220 : pub fn data_offset(&self) -> u32 {
20 220 : self.ptr.data_offset()
21 220 : }
22 :
23 : /// Size of the (raw) array (`size = sizeof(DataCodeEntry) * nb_elements`)
24 220 : pub fn data_size(&self) -> u32 {
25 220 : self.ptr.data_size()
26 220 : }
27 :
28 : /// Raw content as a slice of bytes
29 110 : pub fn content(&self) -> &[u8] {
30 110 : to_slice!(self.ptr.content());
31 110 : }
32 :
33 : /// Iterator over the [`DataCodeEntry`]
34 110 : pub fn entries(&self) -> Entries {
35 110 : Entries::new(self.ptr.entries())
36 110 : }
37 : }
38 :
39 : impl std::fmt::Debug for DataInCode<'_> {
40 220 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41 220 : let base = self as &dyn Command;
42 220 : f.debug_struct("DataInCode")
43 220 : .field("base", &base)
44 220 : .field("data_offset", &self.data_offset())
45 220 : .field("data_size", &self.data_size())
46 220 : .finish()
47 220 : }
48 : }
49 :
50 : impl FromFFI<ffi::MachO_DataInCode> for DataInCode<'_> {
51 220 : fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_DataInCode>) -> Self {
52 220 : Self {
53 220 : ptr: cmd,
54 220 : _owner: PhantomData,
55 220 : }
56 220 : }
57 : }
58 :
59 : impl Command for DataInCode<'_> {
60 880 : fn get_base(&self) -> &ffi::MachO_Command {
61 880 : self.ptr.as_ref().unwrap().as_ref()
62 880 : }
63 : }
64 :
65 : pub struct DataCodeEntry<'a> {
66 : ptr: cxx::UniquePtr<ffi::MachO_DataCodeEntry>,
67 : _owner: PhantomData<&'a ffi::MachO_DataInCode>,
68 : }
69 :
70 : #[allow(non_camel_case_types)]
71 25480 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
72 : pub enum EntryType {
73 : DATA,
74 : JUMP_TABLE_8,
75 : JUMP_TABLE_16,
76 : JUMP_TABLE_32,
77 : ABS_JUMP_TABLE_32,
78 : UNKNOWN(u32),
79 : }
80 :
81 : impl From<u32> for EntryType {
82 25480 : fn from(value: u32) -> Self {
83 25480 : match value {
84 23880 : 0x00000001 => EntryType::DATA,
85 1160 : 0x00000002 => EntryType::JUMP_TABLE_8,
86 440 : 0x00000003 => EntryType::JUMP_TABLE_16,
87 0 : 0x00000004 => EntryType::JUMP_TABLE_32,
88 0 : 0x00000005 => EntryType::ABS_JUMP_TABLE_32,
89 0 : _ => EntryType::UNKNOWN(value),
90 : }
91 25480 : }
92 : }
93 :
94 : impl DataCodeEntry<'_> {
95 : /// Offset of the data
96 25480 : pub fn offset(&self) -> u32 {
97 25480 : self.ptr.offset()
98 25480 : }
99 : /// Length of the data
100 25480 : pub fn length(&self) -> u32 {
101 25480 : self.ptr.length()
102 25480 : }
103 :
104 : /// Type of the data
105 25480 : pub fn get_type(&self) -> EntryType {
106 25480 : EntryType::from(self.ptr.get_type())
107 25480 : }
108 : }
109 :
110 : impl std::fmt::Debug for DataCodeEntry<'_> {
111 25480 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112 25480 : f.debug_struct("DataCodeEntry")
113 25480 : .field("offset", &self.offset())
114 25480 : .field("length", &self.length())
115 25480 : .field("type", &self.get_type())
116 25480 : .finish()
117 25480 : }
118 : }
119 :
120 : impl FromFFI<ffi::MachO_DataCodeEntry> for DataCodeEntry<'_> {
121 25480 : fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_DataCodeEntry>) -> Self {
122 25480 : Self {
123 25480 : ptr,
124 25480 : _owner: PhantomData,
125 25480 : }
126 25480 : }
127 : }
128 :
129 25480 : declare_iterator!(
130 25480 : Entries,
131 25480 : DataCodeEntry<'a>,
132 25480 : ffi::MachO_DataCodeEntry,
133 25480 : ffi::MachO_DataInCode,
134 25480 : ffi::MachO_DataInCode_it_entries
135 25480 : );
|