1use std::marker::PhantomData;
2use std::mem;
3
4use bitflags::bitflags;
5
6use crate::ffi::xref::cref_t::*;
7use crate::ffi::xref::dref_t::*;
8use crate::ffi::xref::*;
9
10use crate::idb::IDB;
11use crate::Address;
12
13pub struct XRef<'a> {
14 inner: xrefblk_t,
15 _marker: PhantomData<&'a IDB>,
16}
17
18impl<'a> Clone for XRef<'a> {
19 fn clone(&self) -> Self {
20 Self {
21 inner: xrefblk_t {
22 from: self.inner.from,
23 to: self.inner.to,
24 iscode: self.inner.iscode,
25 type_: self.inner.type_,
26 user: self.inner.user,
27 _flags: self.inner._flags,
28 },
29 _marker: PhantomData,
30 }
31 }
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
35pub enum XRefType {
36 Code(CodeRef),
37 Data(DataRef),
38}
39
40#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
41#[repr(u8)]
42pub enum CodeRef {
43 Unknown = fl_U as _,
44 FarCall = fl_CF as _,
45 NearCall = fl_CN as _,
46 FarJump = fl_JF as _,
47 NearJump = fl_JN as _,
48 Obsolete = fl_USobsolete as _,
49 Flow = fl_F as _,
50}
51
52#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
53#[repr(u8)]
54pub enum DataRef {
55 Unknown = dr_U as _,
56 Offset = dr_O as _,
57 Write = dr_W as _,
58 Read = dr_R as _,
59 Text = dr_T as _,
60 Informational = dr_I as _,
61 EnumMember = dr_S as _,
62}
63
64bitflags! {
65 #[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
66 pub struct XRefFlags: u8 {
67 const USER = XREF_USER as _;
68 const TAIL = XREF_TAIL as _;
69 const BASE = XREF_BASE as _;
70 }
71}
72
73bitflags! {
74 #[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
75 pub struct XRefQuery: i32 {
76 const ALL = XREF_ALL as _;
77 const FAR = XREF_FAR as _;
78 const DATA = XREF_DATA as _;
79 }
80}
81
82impl<'a> XRef<'a> {
83 pub(crate) fn from_repr(inner: xrefblk_t) -> Self {
84 Self {
85 inner,
86 _marker: PhantomData,
87 }
88 }
89
90 pub fn from(&self) -> Address {
91 self.inner.from.into()
92 }
93
94 pub fn to(&self) -> Address {
95 self.inner.to.into()
96 }
97
98 pub fn flags(&self) -> XRefFlags {
99 let flags = self.inner.type_ & !(XREF_MASK as u8);
100 XRefFlags::from_bits_retain(flags)
101 }
102
103 pub fn type_(&self) -> XRefType {
104 let type_ = self.inner.type_ & (XREF_MASK as u8);
105
106 if self.is_code() {
107 XRefType::Code(unsafe { mem::transmute::<u8, CodeRef>(type_) })
108 } else {
109 XRefType::Data(unsafe { mem::transmute::<u8, DataRef>(type_) })
110 }
111 }
112
113 pub fn is_code(&self) -> bool {
114 self.inner.iscode
115 }
116
117 pub fn is_data(&self) -> bool {
118 !self.is_code()
119 }
120
121 pub fn is_user_defined(&self) -> bool {
122 self.inner.user
123 }
124
125 pub fn next_to(&self) -> Option<Self> {
126 let mut curr = self.clone();
127
128 let found = unsafe { xrefblk_t_next_to(&mut curr.inner as *mut _) };
129
130 if found {
131 Some(curr)
132 } else {
133 None
134 }
135 }
136
137 pub fn next_from(&self) -> Option<Self> {
138 let mut curr = self.clone();
139
140 let found = unsafe { xrefblk_t_next_from(&mut curr.inner as *mut _) };
141
142 if found {
143 Some(curr)
144 } else {
145 None
146 }
147 }
148}