Line data Source code
1 : use lief_ffi as ffi;
2 : use crate::{to_slice, declare_fwd_iterator};
3 : use crate::common::{into_optional, FromFFI};
4 : use crate::assembly::Instructions;
5 :
6 : use std::pin::Pin;
7 :
8 : /// Trait shared by all the symbols in executable formats
9 : pub trait Symbol {
10 : #[doc(hidden)]
11 : fn as_generic(&self) -> &ffi::AbstractSymbol;
12 :
13 : /// Symbol's name
14 493710 : fn name(&self) -> String {
15 493710 : self.as_generic().name().to_string()
16 493710 : }
17 : /// Symbol's value whose interpretation depends on the symbol's kind.
18 : /// Usually this is the address of the symbol though.
19 451630 : fn value(&self) -> u64 {
20 451630 : self.as_generic().value()
21 451630 : }
22 : /// Size of the symbol (can be 0)
23 451630 : fn size(&self) -> u64 {
24 451630 : self.as_generic().size()
25 451630 : }
26 : }
27 :
28 : impl std::fmt::Debug for &dyn Symbol {
29 443860 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30 443860 : f.debug_struct("Symbol")
31 443860 : .field("name", &self.name())
32 443860 : .field("value", &self.value())
33 443860 : .field("size", &self.size())
34 443860 : .finish()
35 443860 : }
36 : }
37 :
38 : /// Trait shared by all the sections in executable formats
39 : pub trait Section {
40 : #[doc(hidden)]
41 : fn as_generic(&self) -> &ffi::AbstractSection;
42 :
43 : /// Name of the section
44 229180 : fn name(&self) -> String {
45 229180 : self.as_generic().name().to_string()
46 229180 : }
47 :
48 : /// Size of the section **in the file**
49 227260 : fn size(&self) -> u64 {
50 227260 : self.as_generic().size()
51 227260 : }
52 :
53 : /// Offset of the section **in the file**
54 227190 : fn offset(&self) -> u64 {
55 227190 : self.as_generic().offset()
56 227190 : }
57 :
58 : /// Address of the section **in memory**
59 227190 : fn virtual_address(&self) -> u64 {
60 227190 : self.as_generic().virtual_address()
61 227190 : }
62 :
63 : /// Content of the section
64 0 : fn content(&self) -> &[u8] {
65 0 : to_slice!(self.as_generic().content());
66 0 : }
67 : }
68 :
69 : impl std::fmt::Debug for &dyn Section {
70 225200 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71 225200 : f.debug_struct("Section")
72 225200 : .field("name", &self.name())
73 225200 : .field("size", &self.size())
74 225200 : .field("offset", &self.offset())
75 225200 : .field("virtual_address", &self.virtual_address())
76 225200 : .finish()
77 225200 : }
78 : }
79 :
80 : pub trait Relocation {
81 : #[doc(hidden)]
82 : fn as_generic(&self) -> &ffi::AbstractRelocation;
83 :
84 : /// Address where the relocation should take place
85 1421480 : fn address(&self) -> u64 {
86 1421480 : self.as_generic().address()
87 1421480 : }
88 :
89 : /// Size of the relocation
90 1421480 : fn size(&self) -> u64 {
91 1421480 : self.as_generic().size()
92 1421480 : }
93 : }
94 :
95 : impl std::fmt::Debug for &dyn Relocation {
96 1421480 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97 1421480 : f.debug_struct("Relocation")
98 1421480 : .field("address", &self.address())
99 1421480 : .field("size", &self.size())
100 1421480 : .finish()
101 1421480 : }
102 : }
103 :
104 : pub trait Binary {
105 : #[doc(hidden)]
106 : fn as_generic(&self) -> &ffi::AbstractBinary;
107 :
108 : #[doc(hidden)]
109 : fn as_pin_mut_generic(&mut self) -> Pin<&mut ffi::AbstractBinary>;
110 :
111 : /// Binary's entrypoint
112 30 : fn entrypoint(&self) -> u64 {
113 30 : self.as_generic().entrypoint()
114 30 : }
115 :
116 : /// Default base address where the binary should be mapped
117 8 : fn imagebase(&self) -> u64 {
118 8 : self.as_generic().imagebase()
119 8 : }
120 :
121 : /// Whether the current binary is **an executable** and **position independent**
122 8 : fn is_pie(&self) -> bool {
123 8 : self.as_generic().is_pie()
124 8 : }
125 :
126 : /// Whether the binary defines a non-executable stack
127 8 : fn has_nx(&self) -> bool {
128 8 : self.as_generic().has_nx()
129 8 : }
130 :
131 : /// Original file size of the binary
132 8 : fn original_size(&self) -> u64 {
133 8 : self.as_generic().original_size()
134 8 : }
135 :
136 : /// Return the debug info if present. It can be either a
137 : /// [`crate::pdb::DebugInfo`] or [`crate::dwarf::DebugInfo`].
138 : ///
139 : /// For ELF and Mach-O binaries, it returns the given DebugInfo object **only**
140 : /// if the binary embeds the DWARF debug info in the binary itself.
141 : ///
142 : /// For PE file, this function tries to find the **external** PDB using
143 : /// the [`crate::pe::debug::CodeViewPDB::filename`] output (if present). One can also
144 : /// use [`crate::pdb::load`] or [`crate::pdb::DebugInfo::from`] to get PDB debug
145 : /// info.
146 : ///
147 : /// <div class="warning">
148 : /// This function requires LIEF's extended version otherwise it always return `None`
149 : /// </div>
150 0 : fn debug_info(&self) -> Option<crate::DebugInfo> {
151 0 : into_optional(self.as_generic().debug_info())
152 0 : }
153 :
154 : /// Disassemble code starting a the given virtual address and with the given
155 : /// size.
156 : ///
157 : /// ```
158 : /// let insts = binary.disassemble(0xacde, 100);
159 : /// for inst in insts {
160 : /// println!("{}", inst.to_string());
161 : /// }
162 : /// ```
163 : ///
164 : /// See also [`crate::assembly::Instruction`] and [`crate::assembly::Instructions`]
165 0 : fn disassemble(&self, address: u64, size: u64) -> InstructionsIt {
166 0 : InstructionsIt::new(self.as_generic().disassemble(address, size))
167 0 : }
168 :
169 : /// Disassemble code for the given symbol name
170 : ///
171 : /// ```
172 : /// let insts = binary.disassemble_symbol("__libc_start_main");
173 : /// for inst in insts {
174 : /// println!("{}", inst.to_string());
175 : /// }
176 : /// ```
177 : ///
178 : /// See also [`crate::assembly::Instruction`] and [`crate::assembly::Instructions`]
179 0 : fn disassemble_symbol(&self, name: &str) -> InstructionsIt {
180 0 : InstructionsIt::new(self.as_generic().disassemble_function(name.to_string()))
181 0 : }
182 :
183 : /// Disassemble code at the given virtual address
184 : ///
185 : /// ```
186 : /// let insts = binary.disassemble_address(0xacde);
187 : /// for inst in insts {
188 : /// println!("{}", inst.to_string());
189 : /// }
190 : /// ```
191 : ///
192 : /// See also [`crate::assembly::Instruction`] and [`crate::assembly::Instructions`]
193 0 : fn disassemble_address(&self, address: u64) -> InstructionsIt {
194 0 : InstructionsIt::new(self.as_generic().disassemble_address(address))
195 0 : }
196 :
197 : /// Disassemble code provided by the given slice at the specified `address` parameter.
198 : ///
199 : /// See also [`crate::assembly::Instruction`] and [`crate::assembly::Instructions`]
200 0 : fn disassemble_slice(&self, slice: &[u8], address: u64) -> InstructionsIt {
201 0 : unsafe {
202 0 : InstructionsIt::new(self.as_generic().disassemble_buffer(
203 0 : slice.as_ptr(), slice.len().try_into().unwrap(),
204 0 : address))
205 0 : }
206 0 : }
207 :
208 : /// Assemble **and patch** the provided assembly code at the specified address.
209 : ///
210 : /// The generated assembly is returned by the function
211 : ///
212 : /// ```
213 : /// let mut bin = get_binary();
214 : ///
215 : /// let Vec<u8> bytes = bin.assemble(0x12000440, r#"
216 : /// xor rax, rbx;
217 : /// mov rcx, rax;
218 : /// "#);
219 : /// ```
220 0 : fn assemble(&mut self, address: u64, asm: &str) -> Vec<u8> {
221 0 : Vec::from(self.as_pin_mut_generic().assemble(address, asm).as_slice())
222 0 : }
223 : }
224 :
225 : pub trait DebugInfo {
226 : #[doc(hidden)]
227 : fn as_generic(&self) -> &ffi::AbstracDebugInfo;
228 : }
229 :
230 0 : declare_fwd_iterator!(
231 0 : InstructionsIt,
232 0 : Instructions,
233 0 : ffi::asm_Instruction,
234 0 : ffi::AbstractBinary,
235 0 : ffi::AbstractBinary_it_instructions
236 0 : );
|