Line data Source code
1 : use lief_ffi as ffi;
2 : use crate::common::FromFFI;
3 : use crate::declare_fwd_iterator;
4 : use crate::common::into_optional;
5 : use crate::declare_iterator;
6 : use crate::assembly::Instructions;
7 : use super::{Relocation, Symbol, Section, Header, String};
8 :
9 : pub struct Binary {
10 : ptr: cxx::UniquePtr<ffi::COFF_Binary>,
11 : }
12 :
13 : impl FromFFI<ffi::COFF_Binary> for Binary {
14 84 : fn from_ffi(ptr: cxx::UniquePtr<ffi::COFF_Binary>) -> Self {
15 84 : Self { ptr }
16 84 : }
17 : }
18 :
19 : impl Binary {
20 : /// Parse from a file path given as a string
21 96 : pub fn parse(path: &str) -> Option<Self> {
22 96 : let ffi = ffi::COFF_Binary::parse(path);
23 96 : if ffi.is_null() {
24 12 : return None;
25 84 : }
26 84 : Some(Binary::from_ffi(ffi))
27 96 : }
28 :
29 : /// The COFF header
30 84 : pub fn header(&self) -> Header {
31 84 : Header::from_ffi(self.ptr.header())
32 84 : }
33 :
34 : /// Iterator over the different sections located in this COFF binary
35 84 : pub fn sections(&self) -> Sections {
36 84 : Sections::new(self.ptr.sections())
37 84 : }
38 :
39 : /// Iterator over **all** the relocations used by this COFF binary
40 84 : pub fn relocations(&self) -> Relocations {
41 84 : Relocations::new(self.ptr.relocations())
42 84 : }
43 :
44 : /// Iterator over the COFF's symbols
45 84 : pub fn symbols(&self) -> Symbols {
46 84 : Symbols::new(self.ptr.symbols())
47 84 : }
48 :
49 : /// Iterator over the functions implemented in this COFF
50 84 : pub fn functions(&self) -> Functions {
51 84 : Functions::new(self.ptr.functions())
52 84 : }
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 168 : pub fn find_string(&self, offset: u32) -> Option<String> {
66 168 : into_optional(self.ptr.find_string(offset))
67 168 : }
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(), slice.len().try_into().unwrap(),
86 0 : address))
87 0 : }
88 0 : }
89 :
90 : /// Disassemble code for the given function name
91 : ///
92 : /// ```
93 : /// let insts = binary.disassemble_function("int __cdecl bar(int, int)");
94 : /// for inst in insts {
95 : /// println!("{}", inst.to_string());
96 : /// }
97 : /// ```
98 : ///
99 : /// See also [`crate::assembly::Instruction`] and [`crate::assembly::Instructions`]
100 0 : pub fn disassemble_function(&self, name: &str) -> InstructionsIt {
101 0 : InstructionsIt::new(self.ptr.disassemble_function(name.to_string()))
102 0 : }
103 :
104 :
105 : /// Disassemble code for the given symbol
106 : ///
107 : /// ```
108 : /// let symbol = binary.find_demangled_function("int __cdecl bar(int, int)").unwrap();
109 : /// let insts = binary.disassemble_symbol(&symbol);
110 : /// for inst in insts {
111 : /// println!("{}", inst.to_string());
112 : /// }
113 : /// ```
114 : ///
115 : /// See also [`crate::assembly::Instruction`] and [`crate::assembly::Instructions`]
116 0 : pub fn disassemble_symbol(&self, symbol: &Symbol) -> InstructionsIt {
117 0 : InstructionsIt::new(self.ptr.disassemble_symbol(symbol.ptr.as_ref().unwrap()))
118 0 : }
119 : }
120 :
121 : impl std::fmt::Display for Binary {
122 0 : fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
123 0 : write!(f, "{}", self.ptr.to_string())
124 0 : }
125 : }
126 :
127 : impl std::fmt::Debug for Binary {
128 0 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
129 0 : f.debug_struct("COFF Binary")
130 0 : .finish()
131 0 : }
132 : }
133 :
134 :
135 :
136 11184 : declare_iterator!(
137 11184 : Relocations,
138 11184 : Relocation<'a>,
139 11184 : ffi::COFF_Relocation,
140 11184 : ffi::COFF_Binary,
141 11184 : ffi::COFF_Binary_it_relocations
142 11184 : );
143 :
144 4020 : declare_iterator!(
145 4020 : Sections,
146 4020 : Section<'a>,
147 4020 : ffi::COFF_Section,
148 4020 : ffi::COFF_Binary,
149 4020 : ffi::COFF_Binary_it_sections
150 4020 : );
151 :
152 9384 : declare_iterator!(
153 9384 : Symbols,
154 9384 : Symbol<'a>,
155 9384 : ffi::COFF_Symbol,
156 9384 : ffi::COFF_Binary,
157 9384 : ffi::COFF_Binary_it_symbols
158 9384 : );
159 :
160 0 : declare_iterator!(
161 0 : Strings,
162 0 : String<'a>,
163 0 : ffi::COFF_String,
164 0 : ffi::COFF_Binary,
165 0 : ffi::COFF_Binary_it_strings
166 0 : );
167 :
168 1392 : declare_iterator!(
169 1392 : Functions,
170 1392 : Symbol<'a>,
171 1392 : ffi::COFF_Symbol,
172 1392 : ffi::COFF_Binary,
173 1392 : ffi::COFF_Binary_it_functions
174 1392 : );
175 :
176 :
177 0 : declare_fwd_iterator!(
178 0 : InstructionsIt,
179 0 : Instructions,
180 0 : ffi::asm_Instruction,
181 0 : ffi::COFF_Binary,
182 0 : ffi::COFF_Binary_it_instructions
183 0 : );
|