binaryninja/
tags.rs

1// Copyright 2022-2026 Vector 35 Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Interfaces for creating and modifying tags in a BinaryView.
16
17use binaryninjacore_sys::*;
18use std::fmt::{Debug, Formatter};
19use std::ptr::NonNull;
20
21use crate::architecture::CoreArchitecture;
22use crate::binary_view::BinaryView;
23
24use crate::function::Function;
25use crate::rc::*;
26use crate::string::*;
27
28pub type TagTypeType = BNTagTypeType;
29pub type TagReferenceType = BNTagReferenceType;
30
31pub struct Tag {
32    pub(crate) handle: *mut BNTag,
33}
34
35impl Tag {
36    pub(crate) unsafe fn from_raw(handle: *mut BNTag) -> Self {
37        debug_assert!(!handle.is_null());
38        Self { handle }
39    }
40
41    pub(crate) unsafe fn ref_from_raw(handle: *mut BNTag) -> Ref<Self> {
42        debug_assert!(!handle.is_null());
43        Ref::new(Self { handle })
44    }
45
46    pub fn new(t: &TagType, data: &str) -> Ref<Self> {
47        let data = data.to_cstr();
48        unsafe { Self::ref_from_raw(BNCreateTag(t.handle, data.as_ptr())) }
49    }
50
51    pub fn id(&self) -> String {
52        unsafe { BnString::into_string(BNTagGetId(self.handle)) }
53    }
54
55    pub fn data(&self) -> String {
56        unsafe { BnString::into_string(BNTagGetData(self.handle)) }
57    }
58
59    pub fn ty(&self) -> Ref<TagType> {
60        unsafe { TagType::ref_from_raw(BNTagGetType(self.handle)) }
61    }
62
63    pub fn set_data(&self, data: &str) {
64        let data = data.to_cstr();
65        unsafe {
66            BNTagSetData(self.handle, data.as_ptr());
67        }
68    }
69}
70
71impl Debug for Tag {
72    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
73        f.debug_struct("Tag")
74            .field("id", &self.id())
75            .field("data", &self.data())
76            .field("type", &self.ty())
77            .finish()
78    }
79}
80
81impl PartialEq for Tag {
82    fn eq(&self, other: &Self) -> bool {
83        self.id() == other.id()
84    }
85}
86
87impl Eq for Tag {}
88
89unsafe impl RefCountable for Tag {
90    unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
91        Ref::new(Self {
92            handle: BNNewTagReference(handle.handle),
93        })
94    }
95
96    unsafe fn dec_ref(handle: &Self) {
97        BNFreeTag(handle.handle);
98    }
99}
100
101impl ToOwned for Tag {
102    type Owned = Ref<Self>;
103
104    fn to_owned(&self) -> Self::Owned {
105        unsafe { RefCountable::inc_ref(self) }
106    }
107}
108
109impl CoreArrayProvider for Tag {
110    type Raw = *mut BNTag;
111    type Context = ();
112    type Wrapped<'a> = Guard<'a, Tag>;
113}
114
115unsafe impl CoreArrayProviderInner for Tag {
116    unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
117        BNFreeTagList(raw, count)
118    }
119
120    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
121        Guard::new(Self { handle: *raw }, &context)
122    }
123}
124
125unsafe impl Send for Tag {}
126unsafe impl Sync for Tag {}
127
128pub struct TagType {
129    pub(crate) handle: *mut BNTagType,
130}
131
132impl CoreArrayProvider for TagType {
133    type Raw = *mut BNTagType;
134    type Context = ();
135    type Wrapped<'a> = Guard<'a, Self>;
136}
137
138unsafe impl CoreArrayProviderInner for TagType {
139    unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
140        BNFreeTagTypeList(raw, count)
141    }
142
143    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
144        Guard::new(Self::from_raw(*raw), context)
145    }
146}
147
148impl TagType {
149    pub(crate) unsafe fn from_raw(handle: *mut BNTagType) -> Self {
150        debug_assert!(!handle.is_null());
151        Self { handle }
152    }
153
154    pub(crate) unsafe fn ref_from_raw(handle: *mut BNTagType) -> Ref<Self> {
155        debug_assert!(!handle.is_null());
156        Ref::new(Self { handle })
157    }
158
159    pub fn create(view: &BinaryView, name: &str, icon: &str) -> Ref<Self> {
160        let tag_type = unsafe { Self::ref_from_raw(BNCreateTagType(view.handle)) };
161        tag_type.set_name(name);
162        tag_type.set_icon(icon);
163        tag_type.set_type(TagTypeType::UserTagType);
164        tag_type
165    }
166
167    pub fn id(&self) -> String {
168        unsafe { BnString::into_string(BNTagTypeGetId(self.handle)) }
169    }
170
171    pub fn icon(&self) -> String {
172        unsafe { BnString::into_string(BNTagTypeGetIcon(self.handle)) }
173    }
174
175    pub fn set_icon(&self, icon: &str) {
176        let icon = icon.to_cstr();
177        unsafe {
178            BNTagTypeSetIcon(self.handle, icon.as_ptr());
179        }
180    }
181
182    pub fn name(&self) -> String {
183        unsafe { BnString::into_string(BNTagTypeGetName(self.handle)) }
184    }
185
186    pub fn set_name(&self, name: &str) {
187        let name = name.to_cstr();
188        unsafe {
189            BNTagTypeSetName(self.handle, name.as_ptr());
190        }
191    }
192
193    pub fn visible(&self) -> bool {
194        unsafe { BNTagTypeGetVisible(self.handle) }
195    }
196
197    pub fn set_visible(&self, visible: bool) {
198        unsafe { BNTagTypeSetVisible(self.handle, visible) }
199    }
200
201    pub fn ty(&self) -> TagTypeType {
202        unsafe { BNTagTypeGetType(self.handle) }
203    }
204
205    pub fn set_type(&self, ty: TagTypeType) {
206        unsafe {
207            BNTagTypeSetType(self.handle, ty);
208        }
209    }
210
211    pub fn view(&self) -> Ref<BinaryView> {
212        unsafe { BinaryView::ref_from_raw(BNTagTypeGetView(self.handle)) }
213    }
214}
215
216impl Debug for TagType {
217    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
218        f.debug_struct("TagType")
219            .field("id", &self.id())
220            .field("name", &self.name())
221            .field("icon", &self.icon())
222            .field("visible", &self.visible())
223            .field("type", &self.ty())
224            .finish()
225    }
226}
227
228impl PartialEq for TagType {
229    fn eq(&self, other: &Self) -> bool {
230        self.id() == other.id()
231    }
232}
233
234impl Eq for TagType {}
235
236unsafe impl RefCountable for TagType {
237    unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
238        Ref::new(Self {
239            handle: BNNewTagTypeReference(handle.handle),
240        })
241    }
242
243    unsafe fn dec_ref(handle: &Self) {
244        BNFreeTagType(handle.handle);
245    }
246}
247
248impl ToOwned for TagType {
249    type Owned = Ref<Self>;
250
251    fn to_owned(&self) -> Self::Owned {
252        unsafe { RefCountable::inc_ref(self) }
253    }
254}
255
256unsafe impl Send for TagType {}
257unsafe impl Sync for TagType {}
258
259#[derive(Clone, PartialEq)]
260pub struct TagReference {
261    pub arch: Option<CoreArchitecture>,
262    pub func: Option<Ref<Function>>,
263    pub addr: u64,
264    pub auto_defined: bool,
265    pub reference_type: TagReferenceType,
266    pub tag: Ref<Tag>,
267}
268
269impl From<&BNTagReference> for TagReference {
270    fn from(value: &BNTagReference) -> Self {
271        Self {
272            reference_type: value.refType,
273            auto_defined: value.autoDefined,
274            tag: unsafe { Tag::from_raw(value.tag).to_owned() },
275            arch: NonNull::new(value.arch)
276                .map(|arch| unsafe { CoreArchitecture::from_raw(arch.as_ptr()) }),
277            func: NonNull::new(value.func)
278                .map(|func| unsafe { Function::from_raw(func.as_ptr()).to_owned() }),
279            addr: value.addr,
280        }
281    }
282}
283
284impl Debug for TagReference {
285    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
286        f.debug_struct("TagReference")
287            .field("addr", &self.addr)
288            .field("auto_defined", &self.auto_defined)
289            .field("reference_type", &self.reference_type)
290            .field("tag", &self.tag)
291            .finish()
292    }
293}
294
295impl CoreArrayProvider for TagReference {
296    type Raw = BNTagReference;
297    type Context = ();
298    type Wrapped<'a> = Self;
299}
300
301unsafe impl CoreArrayProviderInner for TagReference {
302    unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
303        BNFreeTagReferences(raw, count)
304    }
305
306    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
307        raw.into()
308    }
309}