sleigh_sys/
lib.rs

1use cxx::CxxString;
2use cxx::CxxVector;
3use cxx::UniquePtr;
4use std::os::raw::c_char;
5
6use num_derive::FromPrimitive;
7
8#[derive(Debug, FromPrimitive)]
9pub enum SpaceType {
10    Constant = 0,
11    Processor = 1,
12    SpaceBase = 2,
13    Internal = 3,
14    Fspec = 4,
15    Iop = 5,
16    Join = 6,
17}
18
19impl SpaceType {
20    pub fn from_u32(val: u32) -> Option<Self> {
21        num::FromPrimitive::from_u32(val)
22    }
23}
24
25#[derive(Debug, FromPrimitive)]
26pub enum Opcode {
27    Copy = 1,
28    ///< Copy one operand to another
29    Load = 2,
30    ///< Load from a pointer into a specified address space
31    Store = 3,
32    ///< Store at a pointer into a specified address space
33    Branch = 4,
34    ///< Always branch
35    CBranch = 5,
36    ///< Conditional branch
37    BranchInd = 6,
38    ///< Indirect branch (jumptable)
39    Call = 7,
40    ///< Call to an absolute address
41    CallInd = 8,
42    ///< Call through an indirect address
43    CallOther = 9,
44    ///< User-defined operation
45    Return = 10,
46    ///< Return from subroutine
47    // Integer/bit operations
48    IntEqual = 11,
49    ///< Integer comparison, equality (==)
50    IntNotEqual = 12,
51    ///< Integer comparison, in-equality (!=)
52    IntSLess = 13,
53    ///< Integer comparison, signed less-than (<)
54    IntSLessEqual = 14,
55    ///< Integer comparison, signed less-than-or-equal (<=)
56    IntLess = 15,
57    ///< Integer comparison, unsigned less-than (<)
58    // This also indicates a borrow on unsigned substraction
59    IntLessEqual = 16,
60    ///< Integer comparison, unsigned less-than-or-equal (<=)
61    IntZExt = 17,
62    ///< Zero extension
63    IntSExt = 18,
64    ///< Sign extension
65    IntAdd = 19,
66    ///< Addition, signed or unsigned (+)
67    IntSub = 20,
68    ///< Subtraction, signed or unsigned (-)
69    IntCarry = 21,
70    ///< Test for unsigned carry
71    IntSCarry = 22,
72    ///< Test for signed carry
73    IntSBorrow = 23,
74    ///< Test for signed borrow
75    Int2Comp = 24,
76    ///< Twos complement
77    IntNegate = 25,
78    ///< Logical/bitwise negation (~)
79    IntXor = 26,
80    ///< Logical/bitwise exclusive-or (^)
81    IntAnd = 27,
82    ///< Logical/bitwise and (&)
83    IntOr = 28,
84    ///< Logical/bitwise or (|)
85    IntLeft = 29,
86    ///< Left shift (<<)
87    IntRight = 30,
88    ///< Right shift, logical (>>)
89    IntSRight = 31,
90    ///< Right shift, arithmetic (>>)
91    IntMult = 32,
92    ///< Integer multiplication, signed and unsigned (*)
93    IntDiv = 33,
94    ///< Integer division, unsigned (/)
95    IntSDiv = 34,
96    ///< Integer division, signed (/)
97    IntRem = 35,
98    ///< Remainder/modulo, unsigned (%)
99    IntSRem = 36,
100    ///< Remainder/modulo, signed (%)
101    BoolNegate = 37,
102    ///< Boolean negate (!)
103    BoolXor = 38,
104    ///< Boolean exclusive-or (^^)
105    BoolAnd = 39,
106    ///< Boolean and (&&)
107    BoolOr = 40,
108    ///< Boolean or (||)
109    // Floating point operations
110    FloatEqual = 41,
111    ///< Floating-point comparison, equality (==)
112    FloatNotEqual = 42,
113    ///< Floating-point comparison, in-equality (!=)
114    FloatLess = 43,
115    ///< Floating-point comparison, less-than (<)
116    FloatLessEqual = 44,
117    ///< Floating-point comparison, less-than-or-equal (<=)
118    // Slot 45 is currently unused
119    FloatNan = 46,
120    ///< Not-a-number test (NaN)
121    FloatAdd = 47,
122    ///< Floating-point addition (+)
123    FloatDiv = 48,
124    ///< Floating-point division (/)
125    FloatMult = 49,
126    ///< Floating-point multiplication (*)
127    FloatSub = 50,
128    ///< Floating-point subtraction (-)
129    FloatNeg = 51,
130    ///< Floating-point negation (-)
131    FloatAbs = 52,
132    ///< Floating-point absolute value (abs)
133    FloatSqrt = 53,
134    ///< Floating-point square root (sqrt)
135    FloatInt2Float = 54,
136    ///< Convert an integer to a floating-point
137    FloatFloat2Float = 55,
138    ///< Convert between different floating-point sizes
139    FloatTrunc = 56,
140    ///< Round towards zero
141    FloatCeil = 57,
142    ///< Round towards +infinity
143    FloatFloor = 58,
144    ///< Round towards -infinity
145    FloatRound = 59,
146    ///< Round towards nearest
147    // Internal opcodes for simplification. Not
148    // typically generated in a direct translation.
149
150    // Data-flow operations
151    MultiEqual = 60,
152    ///< Phi-node operator
153    Indirect = 61,
154    ///< Copy with an indirect effect
155    Piece = 62,
156    ///< Concatenate
157    SubPiece = 63,
158    ///< Truncate
159    Cast = 64,
160    ///< Cast from one data-type to another
161    PtrAdd = 65,
162    ///< Index into an array ([])
163    PtrSub = 66,
164    ///< Drill down to a sub-field  (->)
165    SegmentOp = 67,
166    ///< Look-up a \e segmented address
167    CPoolRef = 68,
168    ///< Recover a value from the \e constant \e pool
169    New = 69,
170    ///< Allocate a new object (new)
171    Insert = 70,
172    ///< Insert a bit-range
173    Extract = 71,
174    ///< Extract a bit-range
175    PopCount = 72,
176    ///< Count the 1-bits
177    Max = 73,
178}
179
180impl Opcode {
181    pub fn from_u32(val: u32) -> Option<Self> {
182        num::FromPrimitive::from_u32(val)
183    }
184}
185
186//unsafe impl cxx::ExternType for ffi::spacetype {
187//    type Id = type_id!("crate::SpaceType");
188//    type Kind = cxx::kind::Trivial;
189//}
190
191pub trait AssemblyEmit {
192    fn dump(&mut self, addr: &ffi::Address, mnem: &str, body: &str);
193}
194
195pub struct RustAssemblyEmit<'a> {
196    internal: &'a mut dyn AssemblyEmit,
197}
198
199impl<'a> RustAssemblyEmit<'a> {
200    pub fn from_internal(internal: &'a mut dyn AssemblyEmit) -> Self {
201        Self { internal }
202    }
203
204    pub fn dump(&mut self, address: &ffi::Address, mnem: &CxxString, body: &CxxString) {
205        let mnem = mnem.to_str().unwrap();
206        let body = body.to_str().unwrap();
207
208        self.internal.dump(address, mnem, body);
209    }
210}
211
212pub trait PCodeEmit {
213    /// Callback that will be called when disassembling, emitting the pcode
214    /// - address: the address of the machine instruction
215    /// - opcode: the opcode of the particular pcode instruction
216    /// - outvar: a data about the output varnode
217    /// - vars: an array of VarnodeData for each input varnode
218    fn dump(
219        &mut self,
220        address: &ffi::Address,
221        opcode: Opcode,
222        outvar: Option<&ffi::VarnodeData>,
223        vars: &[ffi::VarnodeData],
224    );
225}
226
227pub struct RustPCodeEmit<'a> {
228    pub internal: &'a mut dyn PCodeEmit,
229}
230
231pub trait LoadImage {
232    fn load_fill(&mut self, ptr: &mut [u8], addr: &ffi::Address);
233    fn adjust_vma(&mut self, _adjust: isize) {}
234}
235
236pub struct RustLoadImage<'a> {
237    internal: &'a mut dyn LoadImage,
238}
239
240impl<'a> RustLoadImage<'a> {
241    pub fn from_internal(internal: &'a mut dyn LoadImage) -> Self {
242        Self { internal }
243    }
244
245    unsafe fn load_fill(&mut self, ptr: *mut u8, size: u32, addr: &ffi::Address) {
246        let slice = std::slice::from_raw_parts_mut(ptr, size as usize);
247        self.internal.load_fill(slice, addr);
248    }
249
250    fn adjust_vma(&mut self, adjust: isize) {
251        self.internal.adjust_vma(adjust)
252    }
253}
254
255impl<'a> RustPCodeEmit<'a> {
256    pub fn from_internal(internal: &'a mut dyn PCodeEmit) -> Self {
257        Self { internal }
258    }
259
260    unsafe fn dump(
261        &mut self,
262        address: &ffi::Address,
263        opcode: u32,
264        outvar: *const ffi::VarnodeData,
265        vars: *const ffi::VarnodeData,
266        size: i32,
267    ) {
268        let outvar = if outvar.is_null() {
269            None
270        } else {
271            Some(&*outvar)
272        };
273        let vars = std::slice::from_raw_parts(vars, size as usize);
274        let opcode = num::FromPrimitive::from_u32(opcode).unwrap();
275        self.internal.dump(address, opcode, outvar, vars);
276    }
277}
278
279#[cxx::bridge]
280pub mod ffi {
281    extern "Rust" {
282        type RustAssemblyEmit<'a>;
283        fn dump(self: &mut RustAssemblyEmit, address: &Address, mnem: &CxxString, body: &CxxString);
284
285        type RustPCodeEmit<'a>;
286        unsafe fn dump(
287            self: &mut RustPCodeEmit,
288            address: &Address,
289            opcode: u32,
290            outvar: *const VarnodeData,
291            vars: *const VarnodeData,
292            size: i32,
293        );
294
295        type RustLoadImage<'a>;
296        unsafe fn load_fill(self: &mut RustLoadImage, ptr: *mut u8, size: u32, addr: &Address);
297        //fn get_arch_type(self: &RustLoadImage) -> String;
298        fn adjust_vma(self: &mut RustLoadImage, adjust: isize);
299    }
300
301    unsafe extern "C++" {
302        include!("bridge.hh");
303
304        type Address;
305        fn isInvalid(self: &Address) -> bool;
306        fn getAddrSize(self: &Address) -> i32;
307        fn isBigEndian(self: &Address) -> bool;
308        fn getSpace(self: &Address) -> *mut AddrSpace;
309        fn getOffset(self: &Address) -> u64;
310        fn toPhysical(self: Pin<&mut Address>);
311        fn getShortcut(self: &Address) -> c_char;
312        fn containedBy(self: &Address, sz: i32, op2: &Address, sz2: i32) -> bool;
313        fn justifiedContain(
314            self: &Address,
315            sz: i32,
316            op2: &Address,
317            sz2: i32,
318            forceleft: bool,
319        ) -> i32;
320        fn overlap(self: &Address, skip: i32, op: &Address, size: i32) -> i32;
321        fn isContiguous(self: &Address, sz: i32, loaddr: &Address, losz: i32) -> bool;
322        fn isConstant(self: &Address) -> bool;
323        fn renormalize(self: Pin<&mut Address>, size: i32);
324        fn isJoin(self: &Address) -> bool;
325
326        type VarnodeData;
327        fn getVarnodeDataAddress(data: &VarnodeData) -> UniquePtr<Address>;
328        fn getVarnodeSize(data: &VarnodeData) -> u32;
329
330        type spacetype;
331        type AddrSpace;
332        fn getName(self: &AddrSpace) -> &CxxString;
333        //fn getType(self: &AddrSpace) -> spacetype;
334        fn getDelay(self: &AddrSpace) -> i32;
335        fn getDeadcodeDelay(self: &AddrSpace) -> i32;
336        fn getIndex(self: &AddrSpace) -> i32;
337        fn getWordSize(self: &AddrSpace) -> u32;
338        fn getAddrSize(self: &AddrSpace) -> u32;
339        fn getHighest(self: &AddrSpace) -> u64;
340        fn getPointerLowerBound(self: &AddrSpace) -> u64;
341        fn getPointerUpperBound(self: &AddrSpace) -> u64;
342        fn getMinimumPtrSize(self: &AddrSpace) -> i32;
343        fn wrapOffset(self: &AddrSpace, off: u64) -> u64;
344        fn getShortcut(self: &AddrSpace) -> c_char;
345        fn isHeritaged(self: &AddrSpace) -> bool;
346        fn doesDeadcode(self: &AddrSpace) -> bool;
347        fn hasPhysical(self: &AddrSpace) -> bool;
348        fn isBigEndian(self: &AddrSpace) -> bool;
349        fn isReverseJustified(self: &AddrSpace) -> bool;
350        fn isOverlay(self: &AddrSpace) -> bool;
351        fn isOverlayBase(self: &AddrSpace) -> bool;
352        fn isOtherSpace(self: &AddrSpace) -> bool;
353        fn isTruncated(self: &AddrSpace) -> bool;
354        fn hasNearPointers(self: &AddrSpace) -> bool;
355        fn numSpacebase(self: &AddrSpace) -> i32;
356        fn getSpacebase(self: &AddrSpace, i: i32) -> &VarnodeData;
357        fn getSpacebaseFull(self: &AddrSpace, i: i32) -> &VarnodeData;
358        fn stackGrowsNegative(self: &AddrSpace) -> bool;
359        fn getContain(self: &AddrSpace) -> *mut AddrSpace;
360
361        type OpCode;
362
363        type DocumentStorage;
364
365        type ContextInternal;
366        type ContextDatabase;
367
368        fn setVariableDefault(self: Pin<&mut ContextDatabase>, nm: &CxxString, val: u32);
369        fn getDefaultValue(self: &ContextDatabase, nm: &CxxString) -> u32;
370        fn setVariable(self: Pin<&mut ContextDatabase>, nm: &CxxString, addr: &Address, val: u32);
371        fn getVariable(self: &ContextDatabase, nm: &CxxString, addr: &Address) -> u32;
372
373        fn newAddress() -> UniquePtr<Address>;
374        fn newContext() -> UniquePtr<ContextDatabase>;
375        fn newDocumentStorage(s: &CxxString) -> UniquePtr<DocumentStorage>;
376
377        fn getAddrSpaceType(addr: &AddrSpace) -> u32;
378
379        type Decompiler;
380        unsafe fn translate(self: &Decompiler, emit: *mut RustPCodeEmit, addr: u64) -> i32;
381        unsafe fn disassemble(self: &Decompiler, emit: *mut RustAssemblyEmit, addr: u64) -> i32;
382        unsafe fn getContext(self: Pin<&mut Decompiler>) -> *mut ContextDatabase;
383        unsafe fn newDecompiler(
384            loadImage: *mut RustLoadImage,
385            spec: UniquePtr<DocumentStorage>,
386        ) -> UniquePtr<Decompiler>;
387
388    }
389}
390
391#[cfg(test)]
392mod tests {
393    use super::ffi;
394    #[test]
395    fn test_new() {
396        let _a = ffi::newAddress();
397        let _a = ffi::newContext();
398    }
399}