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