Line data Source code
1 : //! Module related to assembly instructions
2 :
3 : use lief_ffi as ffi;
4 :
5 : use crate::to_slice;
6 :
7 : use crate::common::FromFFI;
8 :
9 : use super::aarch64;
10 : use super::x86;
11 : use super::arm;
12 : use super::mips;
13 : use super::powerpc;
14 : use super::riscv;
15 : use super::ebpf;
16 :
17 : /// This trait is shared by all [`Instructions`] supported by LIEF
18 : pub trait Instruction {
19 : #[doc(hidden)]
20 : fn as_generic(&self) -> &ffi::asm_Instruction;
21 :
22 : /// Address of the instruction
23 0 : fn address(&self) -> u64 {
24 0 : self.as_generic().address()
25 0 : }
26 :
27 : /// Size of the instruction in bytes
28 0 : fn size(&self) -> u64 {
29 0 : self.as_generic().size()
30 0 : }
31 :
32 : /// Raw bytes of the current instruction
33 0 : fn raw(&self) -> &[u8] {
34 0 : to_slice!(self.as_generic().raw());
35 0 : }
36 :
37 : /// Instruction mnemonic (e.g. `br`)
38 0 : fn mnemonic(&self) -> String {
39 0 : self.as_generic().mnemonic().to_string()
40 0 : }
41 :
42 : /// Representation of the current instruction in a pretty assembly way
43 0 : fn to_string(&self) -> String {
44 0 : self.as_generic().to_string().to_string()
45 0 : }
46 :
47 : /// Same as [`Instruction::to_string`] but without the address as prefix
48 0 : fn to_string_no_address(&self) -> String {
49 0 : self.as_generic().to_string_no_address().to_string()
50 0 : }
51 :
52 : /// True if the instruction is a call
53 0 : fn is_call(&self) -> bool {
54 0 : self.as_generic().is_call()
55 0 : }
56 :
57 : /// True if the instruction marks the end of a basic block
58 0 : fn is_terminator(&self) -> bool {
59 0 : self.as_generic().is_terminator()
60 0 : }
61 :
62 : /// True if the instruction is a branch
63 0 : fn is_branch(&self) -> bool {
64 0 : self.as_generic().is_branch()
65 0 : }
66 :
67 : /// True if the instruction is a syscall
68 0 : fn is_syscall(&self) -> bool {
69 0 : self.as_generic().is_syscall()
70 0 : }
71 : }
72 :
73 : /// All instruction variants supported by LIEF
74 : pub enum Instructions {
75 : /// An AArch64 instruction
76 : AArch64(aarch64::Instruction),
77 :
78 : /// A x86/x86-64 instruction
79 : X86(x86::Instruction),
80 :
81 : /// An ARM/thumb instruction
82 : ARM(arm::Instruction),
83 :
84 : /// An eBPF instruction
85 : EBPF(ebpf::Instruction),
86 :
87 : /// A PowerPC (ppc64/ppc32) instruction
88 : PowerPC(powerpc::Instruction),
89 :
90 : /// A Mips (mips32/mips64) instruction
91 : Mips(mips::Instruction),
92 :
93 : /// A RISC-V (32 or 64 bit) instruction
94 : RiscV(riscv::Instruction),
95 :
96 : /// A generic instruction that doesn't have an extended structure
97 : Generic(Generic),
98 : }
99 :
100 : impl FromFFI<ffi::asm_Instruction> for Instructions {
101 0 : fn from_ffi(ptr: cxx::UniquePtr<ffi::asm_Instruction>) -> Self {
102 0 : unsafe {
103 0 : let inst_ref = ptr.as_ref().unwrap();
104 0 : if ffi::asm_aarch64_Instruction::classof(inst_ref) {
105 0 : let raw = {
106 0 : type From = cxx::UniquePtr<ffi::asm_Instruction>;
107 0 : type To = cxx::UniquePtr<ffi::asm_aarch64_Instruction>;
108 0 : std::mem::transmute::<From, To>(ptr)
109 0 : };
110 0 : return Instructions::AArch64(aarch64::Instruction::from_ffi(raw));
111 : }
112 0 : else if ffi::asm_x86_Instruction::classof(inst_ref) {
113 0 : let raw = {
114 0 : type From = cxx::UniquePtr<ffi::asm_Instruction>;
115 0 : type To = cxx::UniquePtr<ffi::asm_x86_Instruction>;
116 0 : std::mem::transmute::<From, To>(ptr)
117 0 : };
118 0 : return Instructions::X86(x86::Instruction::from_ffi(raw));
119 : }
120 0 : else if ffi::asm_arm_Instruction::classof(inst_ref) {
121 0 : let raw = {
122 0 : type From = cxx::UniquePtr<ffi::asm_Instruction>;
123 0 : type To = cxx::UniquePtr<ffi::asm_arm_Instruction>;
124 0 : std::mem::transmute::<From, To>(ptr)
125 0 : };
126 0 : return Instructions::ARM(arm::Instruction::from_ffi(raw));
127 : }
128 0 : else if ffi::asm_mips_Instruction::classof(inst_ref) {
129 0 : let raw = {
130 0 : type From = cxx::UniquePtr<ffi::asm_Instruction>;
131 0 : type To = cxx::UniquePtr<ffi::asm_mips_Instruction>;
132 0 : std::mem::transmute::<From, To>(ptr)
133 0 : };
134 0 : return Instructions::Mips(mips::Instruction::from_ffi(raw));
135 : }
136 0 : else if ffi::asm_powerpc_Instruction::classof(inst_ref) {
137 0 : let raw = {
138 0 : type From = cxx::UniquePtr<ffi::asm_Instruction>;
139 0 : type To = cxx::UniquePtr<ffi::asm_powerpc_Instruction>;
140 0 : std::mem::transmute::<From, To>(ptr)
141 0 : };
142 0 : return Instructions::PowerPC(powerpc::Instruction::from_ffi(raw));
143 : }
144 0 : else if ffi::asm_riscv_Instruction::classof(inst_ref) {
145 0 : let raw = {
146 0 : type From = cxx::UniquePtr<ffi::asm_Instruction>;
147 0 : type To = cxx::UniquePtr<ffi::asm_riscv_Instruction>;
148 0 : std::mem::transmute::<From, To>(ptr)
149 0 : };
150 0 : return Instructions::RiscV(riscv::Instruction::from_ffi(raw));
151 : }
152 :
153 0 : else if ffi::asm_ebpf_Instruction::classof(inst_ref) {
154 0 : let raw = {
155 0 : type From = cxx::UniquePtr<ffi::asm_Instruction>;
156 0 : type To = cxx::UniquePtr<ffi::asm_ebpf_Instruction>;
157 0 : std::mem::transmute::<From, To>(ptr)
158 0 : };
159 0 : return Instructions::EBPF(ebpf::Instruction::from_ffi(raw));
160 0 : }
161 0 : return Instructions::Generic(Generic::from_ffi(ptr));
162 : }
163 0 : }
164 : }
165 :
166 : impl Instruction for Instructions {
167 : #[doc(hidden)]
168 0 : fn as_generic(&self) -> &ffi::asm_Instruction {
169 0 : match &self {
170 0 : Instructions::Generic(inst) => {
171 0 : inst.as_generic()
172 : }
173 0 : Instructions::AArch64(inst) => {
174 0 : inst.as_generic()
175 : }
176 0 : Instructions::X86(inst) => {
177 0 : inst.as_generic()
178 : }
179 0 : Instructions::ARM(inst) => {
180 0 : inst.as_generic()
181 : }
182 0 : Instructions::Mips(inst) => {
183 0 : inst.as_generic()
184 : }
185 0 : Instructions::PowerPC(inst) => {
186 0 : inst.as_generic()
187 : }
188 0 : Instructions::EBPF(inst) => {
189 0 : inst.as_generic()
190 : }
191 0 : Instructions::RiscV(inst) => {
192 0 : inst.as_generic()
193 : }
194 : }
195 0 : }
196 : }
197 :
198 : /// Generic Instruction
199 : pub struct Generic {
200 : ptr: cxx::UniquePtr<ffi::asm_Instruction>,
201 : }
202 :
203 : impl FromFFI<ffi::asm_Instruction> for Generic {
204 0 : fn from_ffi(ptr: cxx::UniquePtr<ffi::asm_Instruction>) -> Self {
205 0 : Self {
206 0 : ptr,
207 0 : }
208 0 : }
209 : }
210 :
211 : impl Instruction for Generic {
212 : #[doc(hidden)]
213 0 : fn as_generic(&self) -> &ffi::asm_Instruction {
214 0 : self.ptr.as_ref().unwrap()
215 0 : }
216 : }
|