Line data Source code
1 : use super::{Header, Relocation, Section, String, Symbol};
2 : use crate::assembly::Instructions;
3 : use crate::common::into_optional;
4 : use crate::common::FromFFI;
5 : use crate::{declare_iterator, declare_lazy_iterator};
6 : use lief_ffi as ffi;
7 : use std::path::Path;
8 :
9 : pub struct Binary {
10 : ptr: cxx::UniquePtr<ffi::COFF_Binary>,
11 : }
12 :
13 : impl FromFFI<ffi::COFF_Binary> for Binary {
14 91 : fn from_ffi(ptr: cxx::UniquePtr<ffi::COFF_Binary>) -> Self {
15 91 : Self { ptr }
16 91 : }
17 : }
18 :
19 : impl Binary {
20 : /// Parse from a file path given as a string
21 8 : pub fn parse<P: AsRef<Path>>(path: P) -> Option<Self> {
22 8 : let ffi = ffi::COFF_Binary::parse(path.as_ref().to_str().unwrap());
23 8 : if ffi.is_null() {
24 1 : return None;
25 7 : }
26 7 : Some(Binary::from_ffi(ffi))
27 8 : }
28 :
29 : /// The COFF header
30 91 : pub fn header(&self) -> Header<'_> {
31 91 : Header::from_ffi(self.ptr.header())
32 91 : }
33 :
34 : /// Iterator over the different sections located in this COFF binary
35 91 : pub fn sections(&self) -> Sections<'_> {
36 91 : Sections::new(self.ptr.sections())
37 91 : }
38 :
39 : /// Iterator over **all** the relocations used by this COFF binary
40 91 : pub fn relocations(&self) -> Relocations<'_> {
41 91 : Relocations::new(self.ptr.relocations())
42 91 : }
43 :
44 : /// Iterator over the COFF's symbols
45 91 : pub fn symbols(&self) -> Symbols<'_> {
46 91 : Symbols::new(self.ptr.symbols())
47 91 : }
48 :
49 : /// Iterator over the functions implemented in this COFF
50 91 : pub fn functions(&self) -> Functions<'_> {
51 91 : Functions::new(self.ptr.functions())
52 91 : }
53 :
54 : /// Iterator over the COFF's strings
55 0 : pub fn string_table(&self) -> Strings<'_> {
56 0 : Strings::new(self.ptr.string_table())
57 0 : }
58 :
59 : /// Try to find the COFF string at the given offset in the COFF string table.
60 : ///
61 : /// <div class="warning">
62 : /// This offset must include the first 4 bytes holding the size of the table. Hence,
63 : /// the first string starts a the offset 4.
64 : /// </div>
65 182 : pub fn find_string(&self, offset: u32) -> Option<String<'_>> {
66 182 : into_optional(self.ptr.find_string(offset))
67 182 : }
68 :
69 : /// Try to find the function (symbol) with the given name
70 0 : pub fn find_function(&self, name: &str) -> Option<Symbol<'_>> {
71 0 : into_optional(self.ptr.find_function(name))
72 0 : }
73 :
74 : /// Try to find the function (symbol) with the given **demangled** name
75 0 : pub fn find_demangled_function(&self, name: &str) -> Option<Symbol<'_>> {
76 0 : into_optional(self.ptr.find_demangled_function(name))
77 0 : }
78 :
79 : /// Disassemble code provided by the given slice at the specified `address` parameter.
80 : ///
81 : /// See also [`crate::assembly::Instruction`] and [`crate::assembly::Instructions`]
82 0 : pub fn disassemble_slice(&self, slice: &[u8], address: u64) -> InstructionsIt<'_> {
83 0 : unsafe {
84 0 : InstructionsIt::new(self.ptr.disassemble_buffer(
85 0 : slice.as_ptr(),
86 0 : slice.len().try_into().unwrap(),
87 0 : address,
88 0 : ))
89 0 : }
90 0 : }
91 :
92 : /// Disassemble code for the given function name
93 : ///
94 : /// ```
95 : /// let insts = binary.disassemble_function("int __cdecl bar(int, int)");
96 : /// for inst in insts {
97 : /// println!("{}", inst.to_string());
98 : /// }
99 : /// ```
100 : ///
101 : /// See also [`crate::assembly::Instruction`] and [`crate::assembly::Instructions`]
102 0 : pub fn disassemble_function(&self, name: &str) -> InstructionsIt<'_> {
103 0 : InstructionsIt::new(self.ptr.disassemble_function(name.to_string()))
104 0 : }
105 :
106 : /// Disassemble code for the given symbol
107 : ///
108 : /// ```
109 : /// let symbol = binary.find_demangled_function("int __cdecl bar(int, int)").unwrap();
110 : /// let insts = binary.disassemble_symbol(&symbol);
111 : /// for inst in insts {
112 : /// println!("{}", inst.to_string());
113 : /// }
114 : /// ```
115 : ///
116 : /// See also [`crate::assembly::Instruction`] and [`crate::assembly::Instructions`]
117 0 : pub fn disassemble_symbol(&self, symbol: &Symbol) -> InstructionsIt<'_> {
118 0 : InstructionsIt::new(self.ptr.disassemble_symbol(symbol.ptr.as_ref().unwrap()))
119 0 : }
120 : }
121 :
122 : impl std::fmt::Display for Binary {
123 0 : fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
124 0 : write!(f, "{}", self.ptr.to_string())
125 0 : }
126 : }
127 :
128 : impl std::fmt::Debug for Binary {
129 0 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
130 0 : f.debug_struct("COFF Binary").finish()
131 0 : }
132 : }
133 :
134 12116 : declare_iterator!(
135 12116 : Relocations,
136 12116 : Relocation<'a>,
137 12116 : ffi::COFF_Relocation,
138 12116 : ffi::COFF_Binary,
139 12116 : ffi::COFF_Binary_it_relocations
140 12116 : );
141 :
142 4355 : declare_iterator!(
143 4355 : Sections,
144 4355 : Section<'a>,
145 4355 : ffi::COFF_Section,
146 4355 : ffi::COFF_Binary,
147 4355 : ffi::COFF_Binary_it_sections
148 4355 : );
149 :
150 10166 : declare_iterator!(
151 10166 : Symbols,
152 10166 : Symbol<'a>,
153 10166 : ffi::COFF_Symbol,
154 10166 : ffi::COFF_Binary,
155 10166 : ffi::COFF_Binary_it_symbols
156 10166 : );
157 :
158 0 : declare_iterator!(
159 0 : Strings,
160 0 : String<'a>,
161 0 : ffi::COFF_String,
162 0 : ffi::COFF_Binary,
163 0 : ffi::COFF_Binary_it_strings
164 0 : );
165 :
166 1508 : declare_iterator!(
167 1508 : Functions,
168 1508 : Symbol<'a>,
169 1508 : ffi::COFF_Symbol,
170 1508 : ffi::COFF_Binary,
171 1508 : ffi::COFF_Binary_it_functions
172 1508 : );
173 :
174 0 : declare_lazy_iterator!(
175 0 : InstructionsIt,
176 0 : Instructions,
177 0 : ffi::asm_Instruction,
178 0 : ffi::COFF_Binary,
179 0 : ffi::COFF_Binary_it_instructions
180 0 : );
|