Line data Source code
1 : use lief_ffi as ffi;
2 :
3 : use num_traits::{cast, Num};
4 : use std::mem::size_of;
5 : use std::path::Path;
6 : use std::pin::Pin;
7 :
8 : use super::builder::Config;
9 : use super::data_directory::{DataDirectories, DataDirectory};
10 : use super::debug::CodeViewPDB;
11 : use super::debug::{self, DebugEntry, Entries};
12 : use super::delay_import::{DelayImport, DelayImports};
13 : use super::exception::RuntimeExceptionFunction;
14 : use super::export::Export;
15 : use super::import::{Import, Imports};
16 : use super::load_configuration::LoadConfiguration;
17 : use super::parser_config::Config as ParserConfig;
18 : use super::relocation::Relocations;
19 : use super::resources::Node as ResourceNode;
20 : use super::resources::{Manager as ResourcesManager, NodeBase};
21 : use super::rich_header::RichHeader;
22 : use super::section::{Section, Sections};
23 : use super::signature::Signatures;
24 : use super::tls::TLS;
25 : use super::{data_directory, signature};
26 : use crate::coff;
27 : use crate::coff::Symbol;
28 :
29 : use crate::common::{into_optional, AsFFI, FromFFI};
30 : use crate::declare_iterator;
31 : use crate::generic;
32 : use crate::to_conv_result;
33 : use crate::to_slice;
34 : use crate::Error;
35 :
36 : use super::Algorithms;
37 : use super::{DosHeader, Header, OptionalHeader};
38 :
39 : /// This is the main interface to read and write PE binary attributes.
40 : ///
41 : /// Note that this structure implements the [`generic::Binary`] trait from which other generic
42 : /// functions are exposed
43 : ///
44 : /// ```
45 : /// fn use_trait(pe: &Binary) {
46 : /// let generic_binary = pe as &dyn generic::Binary;
47 : /// println!("{}", generic_binary.entrypoint());
48 : /// }
49 : ///
50 : /// ```
51 : pub struct Binary {
52 : ptr: cxx::UniquePtr<ffi::PE_Binary>,
53 : }
54 :
55 : impl FromFFI<ffi::PE_Binary> for Binary {
56 351 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Binary>) -> Self {
57 351 : Self { ptr }
58 351 : }
59 : }
60 :
61 : impl Binary {
62 : /// Parse from a filepath given as a string
63 2 : pub fn parse<P: AsRef<Path>>(path: P) -> Option<Self> {
64 2 : let ffi = ffi::PE_Binary::parse(path.as_ref().to_str().unwrap());
65 2 : if ffi.is_null() {
66 0 : return None;
67 2 : }
68 2 : Some(Binary::from_ffi(ffi))
69 2 : }
70 :
71 : /// Parse from a string file path and with a provided configuration
72 12 : pub fn parse_with_config<P: AsRef<Path>>(path: P, config: &ParserConfig) -> Option<Self> {
73 12 : let ffi_config = config.to_ffi();
74 12 : let ffi = ffi::PE_Binary::parse_with_config(path.as_ref().to_str().unwrap(), &ffi_config);
75 12 : if ffi.is_null() {
76 0 : return None;
77 12 : }
78 12 : Some(Binary::from_ffi(ffi))
79 12 : }
80 :
81 : /// DosHeader which starts the PE files
82 169 : pub fn dos_header(&self) -> DosHeader<'_> {
83 169 : DosHeader::from_ffi(self.ptr.dos_header())
84 169 : }
85 :
86 : /// Header that follows the [`Binary::header`]. It is named
87 : /// *optional* from the COFF specification but it is mandatory in a PE file.
88 182 : pub fn optional_header(&self) -> OptionalHeader<'_> {
89 182 : OptionalHeader::from_ffi(self.ptr.optional_header())
90 182 : }
91 :
92 : /// Re-compute the value of [`OptionalHeader::checksum`]
93 169 : pub fn compute_checksum(&self) -> u32 {
94 169 : self.ptr.compute_checksum()
95 169 : }
96 :
97 : /// Next header after the [`Binary::dos_header`]
98 169 : pub fn header(&self) -> Header<'_> {
99 169 : Header::from_ffi(self.ptr.header())
100 169 : }
101 :
102 : /// Return TLS information if present
103 169 : pub fn tls(&self) -> Option<TLS<'_>> {
104 169 : into_optional(self.ptr.tls())
105 169 : }
106 :
107 : /// Return rich header information if present.
108 169 : pub fn rich_header(&self) -> Option<RichHeader<'_>> {
109 169 : into_optional(self.ptr.rich_header())
110 169 : }
111 :
112 : /// Return export information
113 169 : pub fn export(&self) -> Option<Export<'_>> {
114 169 : into_optional(self.ptr.get_export())
115 169 : }
116 :
117 : /// Return the root of the PE's resource tree
118 338 : pub fn resources(&self) -> Option<ResourceNode<'_>> {
119 338 : into_optional(self.ptr.resources())
120 338 : }
121 :
122 : /// Return a manager interface to read and manipulate the resources tree with a user friendly
123 : /// interface.
124 169 : pub fn resources_manager(&self) -> Option<ResourcesManager<'_>> {
125 169 : into_optional(self.ptr.resources_manager())
126 169 : }
127 :
128 : /// Return the imports as an **iterator** over the [`Import`] structure
129 169 : pub fn imports(&self) -> Imports<'_> {
130 169 : Imports::new(self.ptr.imports())
131 169 : }
132 :
133 : /// Return the data directories as an iterator over the [`DataDirectory`] structure
134 169 : pub fn data_directories(&self) -> DataDirectories<'_> {
135 169 : DataDirectories::new(self.ptr.data_directories())
136 169 : }
137 :
138 : /// Return the sections as an iterator over the [`Section`] structure
139 169 : pub fn sections(&self) -> Sections<'_> {
140 169 : Sections::new(self.ptr.sections())
141 169 : }
142 :
143 : /// Return the relocations as an iterator over the [`super::Relocation`] structure
144 169 : pub fn relocations(&self) -> Relocations<'_> {
145 169 : Relocations::new(self.ptr.relocations())
146 169 : }
147 :
148 : /// Return the delayed imports as an iterator over the [`DelayImport`] structure
149 169 : pub fn delay_imports(&self) -> DelayImports<'_> {
150 169 : DelayImports::new(self.ptr.delay_imports())
151 169 : }
152 :
153 : /// Return an iterator over the [`signature::Signature`] if the current PE is authenticode-signed.
154 182 : pub fn signatures(&self) -> Signatures<'_> {
155 182 : Signatures::new(self.ptr.signatures())
156 182 : }
157 :
158 : /// Return an iterator over the [`debug::Entries`] of the binary.
159 169 : pub fn debug(&self) -> DebugEntries<'_> {
160 169 : DebugEntries::new(self.ptr.debug())
161 169 : }
162 :
163 : /// Compute the authentihash for the current PE with the given algorithms.
164 169 : pub fn authentihash(&self, algo: Algorithms) -> Vec<u8> {
165 169 : Vec::from(self.ptr.authentihash(algo.into()).as_slice())
166 169 : }
167 :
168 : /// Return load configuration info if present.
169 169 : pub fn load_configuration(&self) -> Option<LoadConfiguration<'_>> {
170 169 : into_optional(self.ptr.load_configuration())
171 169 : }
172 :
173 : /// Return the raw data between the [`Binary::dos_header`] and the regular [`Binary::header`]
174 169 : pub fn dos_stub(&self) -> &[u8] {
175 169 : to_slice!(self.ptr.dos_stub());
176 169 : }
177 :
178 : /// Return the original overlay data of the file
179 169 : pub fn overlay(&self) -> &[u8] {
180 169 : to_slice!(self.ptr.overlay());
181 169 : }
182 :
183 : /// Return the offset computed by LIEF to identify overlay data
184 169 : pub fn overlay_offset(&self) -> u64 {
185 169 : self.ptr.overlay_offset()
186 169 : }
187 :
188 : /// Convert a **relative** virtual address into an offset
189 13 : pub fn rva_to_offset(&self, rva: u64) -> u64 {
190 13 : self.ptr.rva_to_offset(rva)
191 13 : }
192 :
193 : /// Convert an **absolute** virtual address into an offset.
194 13 : pub fn va_to_offset(&self, va: u64) -> u64 {
195 13 : self.ptr.va_to_offset(va)
196 13 : }
197 :
198 : /// Convert the given offset into a relative virtual address (RVA).
199 13 : pub fn offset_to_rva(&self, offset: u64) -> u64 {
200 13 : self.ptr.offset_to_rva(offset)
201 13 : }
202 :
203 : /// Return the size of the current binary when loaded in memory.
204 169 : pub fn virtual_size(&self) -> u64 {
205 169 : self.ptr.virtual_size()
206 169 : }
207 :
208 : /// Compute the size of all the headers.
209 169 : pub fn sizeof_headers(&self) -> u64 {
210 169 : self.ptr.sizeof_headers()
211 169 : }
212 :
213 : /// Find a section by its offset
214 26 : pub fn section_from_offset(&self, offset: u64) -> Option<Section<'_>> {
215 26 : into_optional(self.ptr.section_from_offset(offset))
216 26 : }
217 :
218 : /// Find a section by its **relative** virtual address
219 26 : pub fn section_from_rva(&self, rva: u64) -> Option<Section<'_>> {
220 26 : into_optional(self.ptr.section_from_rva(rva))
221 26 : }
222 :
223 : /// Find a section by its name
224 52 : pub fn section_by_name(&self, name: &str) -> Option<Section<'_>> {
225 52 : into_optional(self.ptr.section_by_name(name))
226 52 : }
227 :
228 : /// Add a section to the binary and return the section added.
229 0 : pub fn add_section(&mut self, section: Section) -> Option<Section<'_>> {
230 0 : into_optional(self.ptr.as_mut().unwrap().add_section(section.as_ffi()))
231 0 : }
232 :
233 : /// Find the data directory with the given type
234 182 : pub fn data_directory_by_type(
235 182 : &self,
236 182 : dir_type: data_directory::Type,
237 182 : ) -> Option<DataDirectory<'_>> {
238 182 : into_optional(self.ptr.data_directory_by_type(dir_type.into()))
239 182 : }
240 :
241 : /// Verify the binary against the embedded signature(s) (if any)
242 : ///
243 : /// First, it checks that the embedded signatures are correct (c.f. [`signature::Signature::check`])
244 : /// and then, it checks that the authentihash matches [`crate::pe::signature::content_info::ContentInfo::digest`]
245 13 : pub fn verify_signature(
246 13 : &self,
247 13 : checks: signature::VerificationChecks,
248 13 : ) -> signature::VerificationFlags {
249 13 : signature::VerificationFlags::from(self.ptr.verify_signature(checks.into()))
250 13 : }
251 :
252 : /// Verify the binary with the [`signature::Signature`] object provided in the first parameter.
253 : /// It can be used to verify a detached signature:
254 : ///
255 : /// ```
256 : /// if let Some(sig) = Signature::from_file(path_str.unwrap()) {
257 : /// pe.verify_signature(&sig, signature::VerificationChecks::DEFAULT);
258 : /// }
259 : /// ```
260 13 : pub fn verify_with_signature(
261 13 : &self,
262 13 : sig: &signature::Signature,
263 13 : checks: signature::VerificationChecks,
264 13 : ) -> signature::VerificationFlags {
265 13 : signature::VerificationFlags::from(
266 13 : self.ptr.verify_with_signature(sig.into(), checks.into()),
267 13 : )
268 13 : }
269 :
270 : /// Find an import by its DLL name (case insensitive)
271 26 : pub fn import_by_name(&self, name: &str) -> Option<Import<'_>> {
272 26 : into_optional(self.ptr.import_by_name(name))
273 26 : }
274 :
275 : /// Find a delayed import by its name
276 26 : pub fn delay_import_by_name(&self, name: &str) -> Option<DelayImport<'_>> {
277 26 : into_optional(self.ptr.delay_import_by_name(name))
278 26 : }
279 :
280 : /// Return the sized content from the virtual address
281 39 : pub fn content_from_virtual_address(&self, address: u64, size: u64) -> &[u8] {
282 39 : to_slice!(self.ptr.get_content_from_virtual_address(address, size));
283 39 : }
284 :
285 169 : pub fn functions(&self) -> generic::Functions<'_> {
286 169 : generic::Functions::new(self.ptr.functions())
287 169 : }
288 :
289 : /// Return the data directory associated with the export table
290 0 : pub fn export_dir(&self) -> Option<DataDirectory<'_>> {
291 0 : into_optional(self.ptr.export_dir())
292 0 : }
293 :
294 : /// Return the data directory associated with the import table
295 0 : pub fn import_dir(&self) -> Option<DataDirectory<'_>> {
296 0 : into_optional(self.ptr.import_dir())
297 0 : }
298 :
299 : /// Return the data directory associated with the resources tree
300 0 : pub fn rsrc_dir(&self) -> Option<DataDirectory<'_>> {
301 0 : into_optional(self.ptr.rsrc_dir())
302 0 : }
303 :
304 : /// Return the data directory associated with the exceptions
305 0 : pub fn exceptions_dir(&self) -> Option<DataDirectory<'_>> {
306 0 : into_optional(self.ptr.exceptions_dir())
307 0 : }
308 :
309 : /// Return the data directory associated with the certificate table
310 : /// (authenticode)
311 0 : pub fn cert_dir(&self) -> Option<DataDirectory<'_>> {
312 0 : into_optional(self.ptr.cert_dir())
313 0 : }
314 :
315 : /// Return the data directory associated with the relocation table
316 0 : pub fn relocation_dir(&self) -> Option<DataDirectory<'_>> {
317 0 : into_optional(self.ptr.relocation_dir())
318 0 : }
319 :
320 : /// Return the data directory associated with the debug table
321 0 : pub fn debug_dir(&self) -> Option<DataDirectory<'_>> {
322 0 : into_optional(self.ptr.debug_dir())
323 0 : }
324 :
325 : /// Return the data directory associated with TLS
326 0 : pub fn tls_dir(&self) -> Option<DataDirectory<'_>> {
327 0 : into_optional(self.ptr.tls_dir())
328 0 : }
329 :
330 : /// Return the data directory associated with the load config
331 0 : pub fn load_config_dir(&self) -> Option<DataDirectory<'_>> {
332 0 : into_optional(self.ptr.load_config_dir())
333 0 : }
334 :
335 : /// Return the data directory associated with the IAT
336 0 : pub fn iat_dir(&self) -> Option<DataDirectory<'_>> {
337 0 : into_optional(self.ptr.iat_dir())
338 0 : }
339 :
340 : /// Return the data directory associated with delayed imports
341 0 : pub fn export_delay_dirdir(&self) -> Option<DataDirectory<'_>> {
342 0 : into_optional(self.ptr.delay_dir())
343 0 : }
344 :
345 : /// Get the integer value at the given virtual address
346 0 : pub fn get_int_from_virtual_address<T>(&self, addr: u64) -> Result<T, Error>
347 0 : where
348 0 : T: Num + cast::FromPrimitive + cast::ToPrimitive,
349 0 : {
350 0 : // Can't be in the generic trait because of:
351 0 : // > for a trait to be "object safe" it needs to allow building a vtable to allow the call
352 0 : // > to be resolvable dynamically; for more information visit
353 0 : // > https://doc.rust-lang.org/reference/items/traits.html#object-safety
354 0 : if size_of::<T>() == size_of::<u8>() {
355 0 : to_conv_result!(
356 0 : ffi::AbstractBinary::get_u8,
357 0 : self.ptr.as_ref().unwrap().as_ref(),
358 0 : |value| {
359 0 : T::from_u8(value).unwrap_or_else(|| panic!("Can't cast value: {value}"))
360 0 : },
361 0 : addr
362 : );
363 0 : }
364 0 :
365 0 : if size_of::<T>() == size_of::<u16>() {
366 0 : to_conv_result!(
367 0 : ffi::AbstractBinary::get_u16,
368 0 : self.ptr.as_ref().unwrap().as_ref(),
369 0 : |value| {
370 0 : T::from_u16(value).unwrap_or_else(|| panic!("Can't cast value: {value}"))
371 0 : },
372 0 : addr
373 : );
374 0 : }
375 0 :
376 0 : if size_of::<T>() == size_of::<u32>() {
377 0 : to_conv_result!(
378 0 : ffi::AbstractBinary::get_u32,
379 0 : self.ptr.as_ref().unwrap().as_ref(),
380 0 : |value| {
381 0 : T::from_u32(value).unwrap_or_else(|| panic!("Can't cast value: {value}"))
382 0 : },
383 0 : addr
384 : );
385 0 : }
386 0 :
387 0 : if size_of::<T>() == size_of::<u64>() {
388 0 : to_conv_result!(
389 0 : ffi::AbstractBinary::get_u64,
390 0 : self.ptr.as_ref().unwrap().as_ref(),
391 0 : |value| {
392 0 : T::from_u64(value).unwrap_or_else(|| panic!("Can't cast value: {value}"))
393 0 : },
394 0 : addr
395 : );
396 0 : }
397 0 :
398 0 : Err(Error::NotSupported)
399 0 : }
400 :
401 : /// Add an imported library (i.e. `DLL`) to the binary
402 0 : pub fn add_import<'a>(&'a mut self, name: &str) -> Import<'a> {
403 0 : Import::from_ffi(self.ptr.pin_mut().add_import(name))
404 0 : }
405 :
406 : /// Add an imported library (i.e. `DLL`) to the binary.
407 : ///
408 : /// The second parameter `pos` defines where to insert the import.
409 0 : pub fn add_import_at_pos<'a>(&'a mut self, name: &str, pos: u32) -> Import<'a> {
410 0 : Import::from_ffi(self.ptr.pin_mut().add_import_pos(name, pos))
411 0 : }
412 :
413 : /// Remove the imported library with the given `name`
414 0 : pub fn remove_import(&mut self, name: &str) {
415 0 : self.ptr.pin_mut().remove_import(name);
416 0 : }
417 :
418 : /// Remove all libraries in the binary
419 0 : pub fn remove_all_imports(&mut self) {
420 0 : self.ptr.pin_mut().remove_all_imports();
421 0 : }
422 :
423 : /// Remove the TLS from the binary
424 0 : pub fn remove_tls(&mut self) {
425 0 : self.ptr.pin_mut().remove_tls();
426 0 : }
427 :
428 : /// Set or change the TLS information
429 0 : pub fn set_tls(&mut self, tls: &TLS) {
430 0 : self.ptr.pin_mut().set_tls(tls.as_ffi());
431 0 : }
432 :
433 : /// Change or set the resources tree to given node
434 0 : pub fn set_resources(&mut self, node: &dyn NodeBase) {
435 0 : self.ptr.pin_mut().set_resources(node.get_base());
436 0 : }
437 :
438 : /// Add a new debug entry
439 0 : pub fn add_debug_info<'a>(&'a mut self, entry: &dyn DebugEntry) -> Option<Entries<'a>> {
440 0 : into_optional(self.ptr.pin_mut().add_debug_info(entry.get_base()))
441 0 : }
442 :
443 : /// Remove a specific debug entry
444 0 : pub fn remove_debug(&mut self, entry: &dyn DebugEntry) -> bool {
445 0 : self.ptr.pin_mut().remove_debug(entry.get_base())
446 0 : }
447 :
448 : /// Remove all debug info
449 0 : pub fn clear_debug(&mut self) -> bool {
450 0 : self.ptr.pin_mut().clear_debug()
451 0 : }
452 :
453 : /// Return the [`CodeViewPDB`] object if present
454 0 : pub fn codeview_pdb(&self) -> Option<CodeViewPDB<'_>> {
455 0 : into_optional(self.ptr.codeview_pdb())
456 0 : }
457 :
458 : /// Write back the current PE binary into the file specified in parameter
459 0 : pub fn write<P: AsRef<Path>>(&mut self, output: P) {
460 0 : self.ptr
461 0 : .as_mut()
462 0 : .unwrap()
463 0 : .write(output.as_ref().to_str().unwrap());
464 0 : }
465 :
466 : /// Write back the current PE binary into the file specified in parameter with the
467 : /// configuration provided in the second parameter.
468 0 : pub fn write_with_config<P: AsRef<Path>>(&mut self, output: P, config: Config) {
469 0 : let ffi_config = config.to_ffi();
470 0 : self.ptr.as_mut().unwrap().write_with_config(
471 0 : output.as_ref().to_str().unwrap(),
472 0 : ffi_config.as_ref().unwrap(),
473 0 : );
474 0 : }
475 :
476 : /// Iterator over the strings located in the COFF string table
477 169 : pub fn coff_string_table(&self) -> COFFStrings<'_> {
478 169 : COFFStrings::new(self.ptr.coff_string_table())
479 169 : }
480 :
481 : /// Return an iterator over the binary (COFF) symbols (if any).
482 169 : pub fn symbols(&self) -> Symbols<'_> {
483 169 : Symbols::new(self.ptr.symbols())
484 169 : }
485 :
486 : /// Try to find the COFF string at the given offset in the COFF string table.
487 : ///
488 : /// <div class="warning">
489 : /// This offset must include the first 4 bytes holding the size of the table.
490 : /// Hence, the first string starts a the offset 4.
491 : /// </div>
492 0 : pub fn find_coff_string_at(&self, offset: u32) -> Option<coff::String<'_>> {
493 0 : into_optional(self.ptr.find_coff_string_at(offset))
494 0 : }
495 :
496 : /// Iterator over the exception (`_RUNTIME_FUNCTION`) functions
497 : ///
498 : /// This function requires that the option [`ParserConfig::parse_exceptions`] was turned on
499 : /// (default is `false`) when parsing the binary.
500 169 : pub fn exceptions(&self) -> Exceptions<'_> {
501 169 : Exceptions::new(self.ptr.exceptions())
502 169 : }
503 :
504 : /// Try to find the exception info at the given RVA
505 : ///
506 : /// This function requires that the option [`ParserConfig::parse_exceptions`] was turned on
507 : /// (default is `false`) when parsing the binary.
508 0 : pub fn find_exception_at(&self, rva: u32) -> Option<RuntimeExceptionFunction<'_>> {
509 0 : into_optional(self.ptr.find_exception_at(rva))
510 0 : }
511 :
512 : /// True if this binary is compiled in ARM64EC mode (emulation compatible)
513 0 : pub fn is_arm64ec(&self) -> bool {
514 0 : self.ptr.is_arm64ec()
515 0 : }
516 :
517 : /// True if this binary is compiled in ARM64X mode (contains both ARM64 and ARM64EC).
518 0 : pub fn is_arm64x(&self) -> bool {
519 0 : self.ptr.is_arm64x()
520 0 : }
521 :
522 : /// If the current binary contains dynamic relocations
523 : /// (e.g. LIEF::PE::DynamicFixupARM64X), this function returns the
524 : /// **relocated** view of the current PE.
525 : ///
526 : /// This can be used to get the alternative PE binary, targeting a different
527 : /// architectures.
528 : ///
529 : /// <div class="warning">
530 : /// This function is <b>moving</b> and taking the ownership of the nested
531 : /// PE binary. This means that subsequent calls to this function will return None.
532 : /// </div>
533 : ///
534 : /// This function requires that the option [`ParserConfig::parse_arm64x_binary`] was turned on
535 : /// (default is `false`) when parsing the binary.
536 169 : pub fn nested_pe_binary(&self) -> Option<Binary> {
537 169 : into_optional(self.ptr.nested_pe_binary())
538 169 : }
539 :
540 : /// Set or change the export table
541 0 : pub fn set_export(&mut self, export: &Export) {
542 0 : self.ptr.pin_mut().set_export(export.as_ffi());
543 0 : }
544 :
545 : /// Whether the current binary is a reproducible build
546 0 : pub fn is_reproducible_build(&self) -> bool {
547 0 : self.ptr.is_reproducible_build()
548 0 : }
549 :
550 : /// Check if the binary imports the given library name
551 0 : pub fn has_import(&self, name: &str) -> bool {
552 0 : self.ptr.has_import(name.to_string())
553 0 : }
554 :
555 : /// Check if the binary has a delay import with the given name
556 0 : pub fn has_delay_import(&self, name: &str) -> bool {
557 0 : self.ptr.has_delay_import(name.to_string())
558 0 : }
559 :
560 : /// Return the exception functions (from the exception directory)
561 0 : pub fn exception_functions(&self) -> generic::Functions<'_> {
562 0 : generic::Functions::new(self.ptr.exception_functions())
563 0 : }
564 :
565 : /// Remove the section with the given name
566 0 : pub fn remove_section(&mut self, name: &str, clear: bool) {
567 0 : self.ptr.pin_mut().remove_section(name.to_string(), clear);
568 0 : }
569 :
570 : /// Fill the content at the given virtual address with the specified value
571 0 : pub fn fill_address(&mut self, address: u64, size: u64, value: u8) {
572 0 : self.ptr.pin_mut().fill_address(address, size, value);
573 0 : }
574 :
575 : /// Remove all relocations
576 0 : pub fn remove_all_relocations(&mut self) {
577 0 : self.ptr.pin_mut().remove_all_relocations();
578 0 : }
579 : }
580 :
581 : impl AsFFI<ffi::PE_Binary> for Binary {
582 0 : fn as_ffi(&self) -> &ffi::PE_Binary {
583 0 : self.ptr.as_ref().unwrap()
584 0 : }
585 :
586 0 : fn as_mut_ffi(&mut self) -> std::pin::Pin<&mut ffi::PE_Binary> {
587 0 : self.ptr.pin_mut()
588 0 : }
589 : }
590 :
591 : impl std::fmt::Debug for Binary {
592 169 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
593 169 : f.debug_struct("Binary").finish()
594 169 : }
595 : }
596 :
597 : impl generic::Binary for Binary {
598 195 : fn as_generic(&self) -> &ffi::AbstractBinary {
599 195 : self.ptr.as_ref().unwrap().as_ref()
600 195 : }
601 :
602 0 : fn as_pin_mut_generic(&mut self) -> Pin<&mut ffi::AbstractBinary> {
603 0 : unsafe {
604 0 : Pin::new_unchecked({
605 0 : (self.ptr.as_ref().unwrap().as_ref() as *const ffi::AbstractBinary
606 0 : as *mut ffi::AbstractBinary)
607 0 : .as_mut()
608 0 : .unwrap()
609 0 : })
610 0 : }
611 0 : }
612 : }
613 :
614 403 : declare_iterator!(
615 403 : DebugEntries,
616 403 : debug::Entries<'a>,
617 403 : ffi::PE_Debug,
618 403 : ffi::PE_Binary,
619 403 : ffi::PE_Binary_it_debug
620 403 : );
621 :
622 320515 : declare_iterator!(
623 320515 : COFFStrings,
624 320515 : coff::String<'a>,
625 320515 : ffi::PE_COFFString,
626 320515 : ffi::PE_Binary,
627 320515 : ffi::PE_Binary_it_strings_table
628 320515 : );
629 :
630 396721 : declare_iterator!(
631 396721 : Symbols,
632 396721 : Symbol<'a>,
633 396721 : ffi::PE_Symbol,
634 396721 : ffi::PE_Binary,
635 396721 : ffi::PE_Binary_it_symbols
636 396721 : );
637 :
638 1002417 : declare_iterator!(
639 1002417 : Exceptions,
640 1002417 : RuntimeExceptionFunction<'a>,
641 1002417 : ffi::PE_ExceptionInfo,
642 1002417 : ffi::PE_Binary,
643 1002417 : ffi::PE_Binary_it_exceptions
644 1002417 : );
|