Line data Source code
1 : //! COFF section module
2 :
3 : use std::marker::PhantomData;
4 :
5 : use lief_ffi as ffi;
6 :
7 : use crate::common::FromFFI;
8 : use crate::pe;
9 : use crate::to_slice;
10 :
11 : /// This enum represents the different types of COFF header.
12 : pub enum Header<'a> {
13 : /// Regular (default) header
14 : Regular(RegularHeader<'a>),
15 :
16 : /// Header for COFF files that contain more than 65536 sections (compiled with `/bigobj`)
17 : BigObj(BigObjHeader<'a>),
18 : }
19 :
20 : impl FromFFI<ffi::COFF_Header> for Header<'_> {
21 91 : fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::COFF_Header>) -> Self {
22 91 : unsafe {
23 91 : let obj_ref = ffi_entry.as_ref().unwrap();
24 91 : if ffi::COFF_RegularHeader::classof(obj_ref) {
25 65 : let raw = {
26 65 : type From = cxx::UniquePtr<ffi::COFF_Header>;
27 65 : type To = cxx::UniquePtr<ffi::COFF_RegularHeader>;
28 65 : std::mem::transmute::<From, To>(ffi_entry)
29 65 : };
30 65 : Header::Regular(RegularHeader::from_ffi(raw))
31 26 : } else if ffi::COFF_BigObjHeader::classof(obj_ref) {
32 26 : let raw = {
33 26 : type From = cxx::UniquePtr<ffi::COFF_Header>;
34 26 : type To = cxx::UniquePtr<ffi::COFF_BigObjHeader>;
35 26 : std::mem::transmute::<From, To>(ffi_entry)
36 26 : };
37 26 : Header::BigObj(BigObjHeader::from_ffi(raw))
38 : } else {
39 0 : panic!("unsupported header");
40 : }
41 : }
42 91 : }
43 : }
44 :
45 : /// Trait shared by the different COFF headers
46 : pub trait GenericHeader {
47 : #[doc(hidden)]
48 : fn as_generic(&self) -> &ffi::COFF_Header;
49 :
50 : /// The machine type targeted by this COFF
51 91 : fn machine(&self) -> pe::headers::MachineType {
52 91 : pe::headers::MachineType::from(self.as_generic().machine())
53 91 : }
54 :
55 : /// The number of sections
56 91 : fn nb_sections(&self) -> u32 {
57 91 : self.as_generic().nb_sections()
58 91 : }
59 :
60 : /// Offset of the symbols table
61 91 : fn pointerto_symbol_table(&self) -> u32 {
62 91 : self.as_generic().pointerto_symbol_table()
63 91 : }
64 :
65 : /// Number of symbols (including auxiliary symbols)
66 91 : fn nb_symbols(&self) -> u32 {
67 91 : self.as_generic().nb_symbols()
68 91 : }
69 :
70 : /// Timestamp when the COFF has been generated
71 91 : fn timedatestamp(&self) -> u32 {
72 91 : self.as_generic().timedatestamp()
73 91 : }
74 : }
75 :
76 : impl GenericHeader for Header<'_> {
77 0 : fn as_generic(&self) -> &ffi::COFF_Header {
78 0 : match &self {
79 0 : Header::Regular(h) => h.as_generic(),
80 0 : Header::BigObj(h) => h.as_generic(),
81 : }
82 0 : }
83 : }
84 :
85 : impl std::fmt::Debug for &dyn GenericHeader {
86 91 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87 91 : f.debug_struct("GenericHeader")
88 91 : .field("machine", &self.machine())
89 91 : .field("nb_sections", &self.nb_sections())
90 91 : .field("pointerto_symbol_table", &self.pointerto_symbol_table())
91 91 : .field("nb_symbols", &self.nb_symbols())
92 91 : .field("timedatestamp", &self.timedatestamp())
93 91 : .finish()
94 91 : }
95 : }
96 :
97 : impl std::fmt::Display for &dyn GenericHeader {
98 0 : fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
99 0 : write!(f, "{}", self.as_generic().to_string())
100 0 : }
101 : }
102 :
103 : /// Regular (default) header
104 : pub struct RegularHeader<'a> {
105 : ptr: cxx::UniquePtr<ffi::COFF_RegularHeader>,
106 : _owner: PhantomData<&'a ffi::COFF_Binary>,
107 : }
108 :
109 : impl FromFFI<ffi::COFF_RegularHeader> for RegularHeader<'_> {
110 65 : fn from_ffi(ptr: cxx::UniquePtr<ffi::COFF_RegularHeader>) -> Self {
111 65 : Self {
112 65 : ptr,
113 65 : _owner: PhantomData,
114 65 : }
115 65 : }
116 : }
117 :
118 : impl RegularHeader<'_> {
119 : /// The size of the optional header that follows this header (should be 0)
120 65 : pub fn sizeof_optionalheader(&self) -> u16 {
121 65 : self.ptr.sizeof_optionalheader()
122 65 : }
123 :
124 : /// Characteristics
125 65 : pub fn characteristics(&self) -> u16 {
126 65 : self.ptr.characteristics()
127 65 : }
128 : }
129 :
130 : impl GenericHeader for RegularHeader<'_> {
131 390 : fn as_generic(&self) -> &ffi::COFF_Header {
132 390 : self.ptr.as_ref().unwrap().as_ref()
133 390 : }
134 : }
135 :
136 : impl std::fmt::Debug for RegularHeader<'_> {
137 65 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
138 65 : let base = self as &dyn GenericHeader;
139 65 : f.debug_struct("RegularHeader")
140 65 : .field("base", &base)
141 65 : .field("sizeof_optionalheader", &self.sizeof_optionalheader())
142 65 : .field("characteristics", &self.characteristics())
143 65 : .finish()
144 65 : }
145 : }
146 :
147 : impl std::fmt::Display for RegularHeader<'_> {
148 65 : fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
149 65 : write!(f, "{}", self.as_generic().to_string())
150 65 : }
151 : }
152 :
153 : /// Header for COFF files that contain more than 65536 sections (compiled with `/bigobj`)
154 : pub struct BigObjHeader<'a> {
155 : ptr: cxx::UniquePtr<ffi::COFF_BigObjHeader>,
156 : _owner: PhantomData<&'a ffi::COFF_Binary>,
157 : }
158 :
159 : impl FromFFI<ffi::COFF_BigObjHeader> for BigObjHeader<'_> {
160 26 : fn from_ffi(ptr: cxx::UniquePtr<ffi::COFF_BigObjHeader>) -> Self {
161 26 : Self {
162 26 : ptr,
163 26 : _owner: PhantomData,
164 26 : }
165 26 : }
166 : }
167 :
168 : impl BigObjHeader<'_> {
169 : /// The version of this header which must be >= 2
170 26 : pub fn version(&self) -> u16 {
171 26 : self.ptr.version()
172 26 : }
173 :
174 : /// Originally named `ClassID`, this uuid should match: `{D1BAA1C7-BAEE-4ba9-AF20-FAF66AA4DCB8}`
175 26 : pub fn uuid(&self) -> &[u8] {
176 26 : to_slice!(self.ptr.uuid());
177 26 : }
178 :
179 : /// Size of data that follows the header
180 26 : pub fn sizeof_data(&self) -> u32 {
181 26 : self.ptr.sizeof_data()
182 26 : }
183 :
184 : /// 1 means that it contains metadata
185 26 : pub fn flags(&self) -> u32 {
186 26 : self.ptr.flags()
187 26 : }
188 :
189 : /// Size of CLR metadata
190 26 : pub fn metadata_size(&self) -> u32 {
191 26 : self.ptr.metadata_size()
192 26 : }
193 :
194 : /// Offset of CLR metadata
195 26 : pub fn metadata_offset(&self) -> u32 {
196 26 : self.ptr.metadata_offset()
197 26 : }
198 : }
199 :
200 : impl std::fmt::Debug for BigObjHeader<'_> {
201 26 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
202 26 : let base = self as &dyn GenericHeader;
203 26 : f.debug_struct("BigObjHeader")
204 26 : .field("base", &base)
205 26 : .field("version", &self.version())
206 26 : .field("uuid", &self.uuid())
207 26 : .field("sizeof_data", &self.sizeof_data())
208 26 : .field("flags", &self.flags())
209 26 : .field("metadata_size", &self.metadata_size())
210 26 : .field("metadata_offset", &self.metadata_offset())
211 26 : .finish()
212 26 : }
213 : }
214 :
215 : impl GenericHeader for BigObjHeader<'_> {
216 156 : fn as_generic(&self) -> &ffi::COFF_Header {
217 156 : self.ptr.as_ref().unwrap().as_ref()
218 156 : }
219 : }
220 :
221 : impl std::fmt::Display for BigObjHeader<'_> {
222 26 : fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
223 26 : write!(f, "{}", self.as_generic().to_string())
224 26 : }
225 : }
|