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