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