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 264 : pub fn data_offset(&self) -> u32 {
20 264 : self.ptr.data_offset()
21 264 : }
22 :
23 : /// Size of the (raw) array (`size = sizeof(DataCodeEntry) * nb_elements`)
24 264 : pub fn data_size(&self) -> u32 {
25 264 : self.ptr.data_size()
26 264 : }
27 :
28 : /// Raw content as a slice of bytes
29 132 : pub fn content(&self) -> &[u8] {
30 132 : to_slice!(self.ptr.content());
31 132 : }
32 :
33 : /// Iterator over the [`DataCodeEntry`]
34 132 : pub fn entries(&self) -> Entries {
35 132 : Entries::new(self.ptr.entries())
36 132 : }
37 : }
38 :
39 : impl std::fmt::Debug for DataInCode<'_> {
40 264 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41 264 : let base = self as &dyn Command;
42 264 : f.debug_struct("DataInCode")
43 264 : .field("base", &base)
44 264 : .field("data_offset", &self.data_offset())
45 264 : .field("data_size", &self.data_size())
46 264 : .finish()
47 264 : }
48 : }
49 :
50 : impl FromFFI<ffi::MachO_DataInCode> for DataInCode<'_> {
51 264 : fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_DataInCode>) -> Self {
52 264 : Self {
53 264 : ptr: cmd,
54 264 : _owner: PhantomData,
55 264 : }
56 264 : }
57 : }
58 :
59 : impl Command for DataInCode<'_> {
60 1056 : fn get_base(&self) -> &ffi::MachO_Command {
61 1056 : self.ptr.as_ref().unwrap().as_ref()
62 1056 : }
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 30576 : #[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 30576 : fn from(value: u32) -> Self {
83 30576 : match value {
84 28656 : 0x00000001 => EntryType::DATA,
85 1392 : 0x00000002 => EntryType::JUMP_TABLE_8,
86 528 : 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 30576 : }
92 : }
93 :
94 : impl DataCodeEntry<'_> {
95 : /// Offset of the data
96 30576 : pub fn offset(&self) -> u32 {
97 30576 : self.ptr.offset()
98 30576 : }
99 : /// Length of the data
100 30576 : pub fn length(&self) -> u32 {
101 30576 : self.ptr.length()
102 30576 : }
103 :
104 : /// Type of the data
105 30576 : pub fn get_type(&self) -> EntryType {
106 30576 : EntryType::from(self.ptr.get_type())
107 30576 : }
108 : }
109 :
110 : impl std::fmt::Debug for DataCodeEntry<'_> {
111 30576 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112 30576 : f.debug_struct("DataCodeEntry")
113 30576 : .field("offset", &self.offset())
114 30576 : .field("length", &self.length())
115 30576 : .field("type", &self.get_type())
116 30576 : .finish()
117 30576 : }
118 : }
119 :
120 : impl FromFFI<ffi::MachO_DataCodeEntry> for DataCodeEntry<'_> {
121 30576 : fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_DataCodeEntry>) -> Self {
122 30576 : Self {
123 30576 : ptr,
124 30576 : _owner: PhantomData,
125 30576 : }
126 30576 : }
127 : }
128 :
129 30576 : declare_iterator!(
130 30576 : Entries,
131 30576 : DataCodeEntry<'a>,
132 30576 : ffi::MachO_DataCodeEntry,
133 30576 : ffi::MachO_DataInCode,
134 30576 : ffi::MachO_DataInCode_it_entries
135 30576 : );
|