Line data Source code
1 : use lief_ffi as ffi;
2 : use bitflags::bitflags;
3 : use crate::{to_slice, declare_fwd_iterator};
4 : use crate::common::{into_optional, FromFFI};
5 : use crate::assembly::Instructions;
6 :
7 : use std::pin::Pin;
8 :
9 : /// Trait shared by all the symbols in executable formats
10 : pub trait Symbol {
11 : #[doc(hidden)]
12 : fn as_generic(&self) -> &ffi::AbstractSymbol;
13 :
14 : /// Symbol's name
15 1596570 : fn name(&self) -> String {
16 1596570 : self.as_generic().name().to_string()
17 1596570 : }
18 : /// Symbol's value whose interpretation depends on the symbol's kind.
19 : /// Usually this is the address of the symbol though.
20 830540 : fn value(&self) -> u64 {
21 830540 : self.as_generic().value()
22 830540 : }
23 : /// Size of the symbol (can be 0)
24 830540 : fn size(&self) -> u64 {
25 830540 : self.as_generic().size()
26 830540 : }
27 : }
28 :
29 : impl std::fmt::Debug for &dyn Symbol {
30 822770 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 822770 : f.debug_struct("Symbol")
32 822770 : .field("name", &self.name())
33 822770 : .field("value", &self.value())
34 822770 : .field("size", &self.size())
35 822770 : .finish()
36 822770 : }
37 : }
38 :
39 : /// Trait shared by all the sections in executable formats
40 : pub trait Section {
41 : #[doc(hidden)]
42 : fn as_generic(&self) -> &ffi::AbstractSection;
43 :
44 : /// Name of the section
45 232830 : fn name(&self) -> String {
46 232830 : self.as_generic().name().to_string()
47 232830 : }
48 :
49 : /// Size of the section **in the file**
50 230910 : fn size(&self) -> u64 {
51 230910 : self.as_generic().size()
52 230910 : }
53 :
54 : /// Offset of the section **in the file**
55 230840 : fn offset(&self) -> u64 {
56 230840 : self.as_generic().offset()
57 230840 : }
58 :
59 : /// Address of the section **in memory**
60 230840 : fn virtual_address(&self) -> u64 {
61 230840 : self.as_generic().virtual_address()
62 230840 : }
63 :
64 : /// Content of the section
65 0 : fn content(&self) -> &[u8] {
66 0 : to_slice!(self.as_generic().content());
67 0 : }
68 : }
69 :
70 : impl std::fmt::Debug for &dyn Section {
71 228850 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72 228850 : f.debug_struct("Section")
73 228850 : .field("name", &self.name())
74 228850 : .field("size", &self.size())
75 228850 : .field("offset", &self.offset())
76 228850 : .field("virtual_address", &self.virtual_address())
77 228850 : .finish()
78 228850 : }
79 : }
80 :
81 : pub trait Relocation {
82 : #[doc(hidden)]
83 : fn as_generic(&self) -> &ffi::AbstractRelocation;
84 :
85 : /// Address where the relocation should take place
86 2264100 : fn address(&self) -> u64 {
87 2264100 : self.as_generic().address()
88 2264100 : }
89 :
90 : /// Size of the relocation
91 2264100 : fn size(&self) -> u64 {
92 2264100 : self.as_generic().size()
93 2264100 : }
94 : }
95 :
96 : impl std::fmt::Debug for &dyn Relocation {
97 2264100 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
98 2264100 : f.debug_struct("Relocation")
99 2264100 : .field("address", &self.address())
100 2264100 : .field("size", &self.size())
101 2264100 : .finish()
102 2264100 : }
103 : }
104 :
105 : pub trait Binary {
106 : #[doc(hidden)]
107 : fn as_generic(&self) -> &ffi::AbstractBinary;
108 :
109 : #[doc(hidden)]
110 : fn as_pin_mut_generic(&mut self) -> Pin<&mut ffi::AbstractBinary>;
111 :
112 : /// Binary's entrypoint
113 35 : fn entrypoint(&self) -> u64 {
114 35 : self.as_generic().entrypoint()
115 35 : }
116 :
117 : /// Default base address where the binary should be mapped
118 8 : fn imagebase(&self) -> u64 {
119 8 : self.as_generic().imagebase()
120 8 : }
121 :
122 : /// Whether the current binary is **an executable** and **position independent**
123 8 : fn is_pie(&self) -> bool {
124 8 : self.as_generic().is_pie()
125 8 : }
126 :
127 : /// Whether the binary defines a non-executable stack
128 8 : fn has_nx(&self) -> bool {
129 8 : self.as_generic().has_nx()
130 8 : }
131 :
132 : /// Original file size of the binary
133 8 : fn original_size(&self) -> u64 {
134 8 : self.as_generic().original_size()
135 8 : }
136 :
137 : /// Return the debug info if present. It can be either a
138 : /// [`crate::pdb::DebugInfo`] or [`crate::dwarf::DebugInfo`].
139 : ///
140 : /// For ELF and Mach-O binaries, it returns the given DebugInfo object **only**
141 : /// if the binary embeds the DWARF debug info in the binary itself.
142 : ///
143 : /// For PE file, this function tries to find the **external** PDB using
144 : /// the [`crate::pe::debug::CodeViewPDB::filename`] output (if present). One can also
145 : /// use [`crate::pdb::load`] or [`crate::pdb::DebugInfo::from`] to get PDB debug
146 : /// info.
147 : ///
148 : /// <div class="warning">
149 : /// This function requires LIEF's extended version otherwise it always return `None`
150 : /// </div>
151 0 : fn debug_info(&self) -> Option<crate::DebugInfo> {
152 0 : into_optional(self.as_generic().debug_info())
153 0 : }
154 :
155 : /// Disassemble code starting a the given virtual address and with the given
156 : /// size.
157 : ///
158 : /// ```
159 : /// let insts = binary.disassemble(0xacde, 100);
160 : /// for inst in insts {
161 : /// println!("{}", inst.to_string());
162 : /// }
163 : /// ```
164 : ///
165 : /// See also [`crate::assembly::Instruction`] and [`crate::assembly::Instructions`]
166 0 : fn disassemble(&self, address: u64, size: u64) -> InstructionsIt {
167 0 : InstructionsIt::new(self.as_generic().disassemble(address, size))
168 0 : }
169 :
170 : /// Disassemble code for the given symbol name
171 : ///
172 : /// ```
173 : /// let insts = binary.disassemble_symbol("__libc_start_main");
174 : /// for inst in insts {
175 : /// println!("{}", inst.to_string());
176 : /// }
177 : /// ```
178 : ///
179 : /// See also [`crate::assembly::Instruction`] and [`crate::assembly::Instructions`]
180 0 : fn disassemble_symbol(&self, name: &str) -> InstructionsIt {
181 0 : InstructionsIt::new(self.as_generic().disassemble_function(name.to_string()))
182 0 : }
183 :
184 : /// Disassemble code at the given virtual address
185 : ///
186 : /// ```
187 : /// let insts = binary.disassemble_address(0xacde);
188 : /// for inst in insts {
189 : /// println!("{}", inst.to_string());
190 : /// }
191 : /// ```
192 : ///
193 : /// See also [`crate::assembly::Instruction`] and [`crate::assembly::Instructions`]
194 0 : fn disassemble_address(&self, address: u64) -> InstructionsIt {
195 0 : InstructionsIt::new(self.as_generic().disassemble_address(address))
196 0 : }
197 :
198 : /// Disassemble code provided by the given slice at the specified `address` parameter.
199 : ///
200 : /// See also [`crate::assembly::Instruction`] and [`crate::assembly::Instructions`]
201 0 : fn disassemble_slice(&self, slice: &[u8], address: u64) -> InstructionsIt {
202 0 : unsafe {
203 0 : InstructionsIt::new(self.as_generic().disassemble_buffer(
204 0 : slice.as_ptr(), slice.len().try_into().unwrap(),
205 0 : address))
206 0 : }
207 0 : }
208 :
209 : /// Assemble **and patch** the provided assembly code at the specified address.
210 : ///
211 : /// The generated assembly is returned by the function
212 : ///
213 : /// ```
214 : /// let mut bin = get_binary();
215 : ///
216 : /// let Vec<u8> bytes = bin.assemble(0x12000440, r#"
217 : /// xor rax, rbx;
218 : /// mov rcx, rax;
219 : /// "#);
220 : /// ```
221 0 : fn assemble(&mut self, address: u64, asm: &str) -> Vec<u8> {
222 0 : Vec::from(self.as_pin_mut_generic().assemble(address, asm).as_slice())
223 0 : }
224 : }
225 :
226 : pub trait DebugInfo {
227 : #[doc(hidden)]
228 : fn as_generic(&self) -> &ffi::AbstracDebugInfo;
229 : }
230 :
231 :
232 0 : bitflags! {
233 0 : /// Flags used to characterize the semantics of the function
234 723950 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
235 0 : pub struct FunctionFlags: u32 {
236 0 : const NONE = 0x0;
237 0 : /// The function acts as constructor.
238 0 : ///
239 0 : /// Usually this flag is associated with functions
240 0 : /// that are located in the `.init_array`, `__mod_init_func` or `.tls` sections
241 0 : const CONSTRUCTOR = 0x1;
242 0 :
243 0 : /// The function acts as a destructor.
244 0 : ///
245 0 : /// Usually this flag is associated with functions
246 0 : /// that are located in the `.fini_array` or `__mod_term_func` sections
247 0 : const DESTRUCTOR = 0x2;
248 0 :
249 0 : /// The function is associated with Debug information
250 0 : const DEBUG_INFO = 0x4;
251 0 :
252 0 : /// The function is exported by the binary and the [`Function::address`]
253 0 : /// returns its virtual address in the binary
254 0 : const EXPORTED = 0x8;
255 0 :
256 0 : /// The function is **imported** by the binary and the [`Function::address`]
257 0 : /// should return 0
258 0 : const IMPORTED = 0x10;
259 0 : }
260 0 : }
261 :
262 :
263 : impl From<u32> for FunctionFlags {
264 723950 : fn from(value: u32) -> Self {
265 723950 : FunctionFlags::from_bits_truncate(value)
266 723950 : }
267 : }
268 :
269 : impl From<FunctionFlags> for u32 {
270 0 : fn from(value: FunctionFlags) -> Self {
271 0 : value.bits()
272 0 : }
273 : }
274 :
275 : impl std::fmt::Display for FunctionFlags {
276 0 : fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
277 0 : bitflags::parser::to_writer(self, f)
278 0 : }
279 : }
280 :
281 : /// Structure that represents a binary's function
282 : pub struct Function {
283 : ptr: cxx::UniquePtr<ffi::AbstractFunction>,
284 : }
285 :
286 : impl FromFFI<ffi::AbstractFunction> for Function {
287 723950 : fn from_ffi(ptr: cxx::UniquePtr<ffi::AbstractFunction>) -> Self {
288 723950 : Self {
289 723950 : ptr,
290 723950 : }
291 723950 : }
292 : }
293 :
294 : impl Symbol for Function {
295 723950 : fn as_generic(&self) -> &lief_ffi::AbstractSymbol {
296 723950 : self.ptr.as_ref().unwrap().as_ref()
297 723950 : }
298 : }
299 :
300 : impl Function {
301 : /// Flags characterizing the semantics of the function
302 723950 : pub fn flags(&self) -> FunctionFlags {
303 723950 : FunctionFlags::from(self.ptr.flags())
304 723950 : }
305 :
306 : /// Address of the function (if not imported)
307 723950 : pub fn address(&self) -> u64 {
308 723950 : self.ptr.address()
309 723950 : }
310 : }
311 :
312 : impl std::fmt::Debug for Function {
313 723950 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
314 723950 : f.debug_struct("Function")
315 723950 : .field("name", &self.name())
316 723950 : .field("address", &self.address())
317 723950 : .field("flags", &self.flags())
318 723950 : .finish()
319 723950 : }
320 : }
321 :
322 723950 : declare_fwd_iterator!(
323 723950 : Functions,
324 723950 : Function,
325 723950 : ffi::AbstractFunction,
326 723950 : ffi::AbstractBinary,
327 723950 : ffi::AbstractBinary_it_functions
328 723950 : );
329 :
330 0 : declare_fwd_iterator!(
331 0 : InstructionsIt,
332 0 : Instructions,
333 0 : ffi::asm_Instruction,
334 0 : ffi::AbstractBinary,
335 0 : ffi::AbstractBinary_it_instructions
336 0 : );
|