lldb/
address.rs

1// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
2// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
3// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
4// option. This file may not be copied, modified, or distributed
5// except according to those terms.
6
7use crate::{
8    lldb_addr_t, sys, SBBlock, SBCompileUnit, SBFunction, SBLineEntry, SBModule, SBSection,
9    SBStream, SBSymbol, SBSymbolContext, SBTarget,
10};
11use std::fmt;
12
13/// A section + offset based address class.
14///
15/// The `SBAddress` class allows addresses to be relative to a section
16/// that can move during runtime due to images (executables, shared
17/// libraries, bundles, frameworks) being loaded at different
18/// addresses than the addresses found in the object file that
19/// represents them on disk. There are currently two types of addresses
20/// for a section:
21///
22/// * file addresses
23/// * load addresses
24///
25/// File addresses represents the virtual addresses that are in the 'on
26/// disk' object files. These virtual addresses are converted to be
27/// relative to unique sections scoped to the object file so that
28/// when/if the addresses slide when the images are loaded/unloaded
29/// in memory, we can easily track these changes without having to
30/// update every object (compile unit ranges, line tables, function
31/// address ranges, lexical block and inlined subroutine address
32/// ranges, global and static variables) each time an image is loaded or
33/// unloaded.
34///
35/// Load addresses represents the virtual addresses where each section
36/// ends up getting loaded at runtime. Before executing a program, it
37/// is common for all of the load addresses to be unresolved. When a
38/// `DynamicLoader` plug-in receives notification that shared libraries
39/// have been loaded/unloaded, the load addresses of the main executable
40/// and any images (shared libraries) will be  resolved/unresolved. When
41/// this happens, breakpoints that are in one of these sections can be
42/// set/cleared.
43pub struct SBAddress {
44    /// The underlying raw `SBAddressRef`.
45    pub raw: sys::SBAddressRef,
46}
47
48impl SBAddress {
49    /// Construct a new `SBAddress`.
50    pub(crate) fn wrap(raw: sys::SBAddressRef) -> SBAddress {
51        SBAddress { raw }
52    }
53
54    /// Construct a new `Some(SBAddress)` or `None`.
55    pub(crate) fn maybe_wrap(raw: sys::SBAddressRef) -> Option<SBAddress> {
56        if unsafe { sys::SBAddressIsValid(raw) } {
57            Some(SBAddress { raw })
58        } else {
59            None
60        }
61    }
62
63    /// Check whether or not this is a valid `SBAddress` value.
64    pub fn is_valid(&self) -> bool {
65        unsafe { sys::SBAddressIsValid(self.raw) }
66    }
67
68    /// Construct a new `SBAddress` from the given section and offset.
69    pub fn from_section_offset(section: &SBSection, offset: lldb_addr_t) -> SBAddress {
70        let a = unsafe { sys::CreateSBAddress2(section.raw, offset) };
71        SBAddress::wrap(a)
72    }
73
74    /// Create a new `SBAddress` from the given load address within the target.
75    pub fn from_load_address(load_addr: lldb_addr_t, target: &SBTarget) -> SBAddress {
76        let a = unsafe { sys::CreateSBAddress3(load_addr, target.raw) };
77        SBAddress::wrap(a)
78    }
79
80    /// The address that represents the address as it is found in the
81    /// object file that defines it.
82    pub fn file_address(&self) -> u64 {
83        unsafe { sys::SBAddressGetFileAddress(self.raw) }
84    }
85
86    /// The address as it has been loaded into memory by a target.
87    pub fn load_address(&self, target: &SBTarget) -> u64 {
88        unsafe { sys::SBAddressGetLoadAddress(self.raw, target.raw) }
89    }
90
91    /// Get the `SBSymbolContext` for a given address.
92    ///
93    /// An address might refer to code or data from an existing
94    /// module, or it might refer to something on the stack or heap.
95    /// This will only return valid values if the address has been
96    /// resolved to a code or data address using
97    /// [`SBAddress::from_load_address`] or [`SBTarget::resolve_load_address`].
98    ///
99    /// * `resolve_scope`: Flags that specify what type of symbol context
100    ///   is needed by the caller. These flags have constants starting
101    ///   with `SYMBOL_CONTEXT_ITEM_`.
102    pub fn symbol_context(&self, resolve_scope: u32) -> SBSymbolContext {
103        SBSymbolContext::wrap(unsafe { sys::SBAddressGetSymbolContext(self.raw, resolve_scope) })
104    }
105
106    /// Get the `SBModule` for a given address.
107    ///
108    /// An address might refer to code or data from an existing
109    /// module, or it might refer to something on the stack or heap.
110    /// This will only return valid values if the address has been
111    /// resolved to a code or data address using
112    /// [`SBAddress::from_load_address`] or [`SBTarget::resolve_load_address`].
113    ///
114    /// This grabs an individual object for a given address and
115    /// is less efficient if you want more than one symbol related objects.
116    /// Use one of the following when you want multiple debug symbol related
117    /// objects for an address:
118    ///
119    /// * [`SBAddress::symbol_context`]
120    /// * `SBTarget::resolve_symbol_context_for_address`
121    ///
122    /// One or more bits from the `SymbolContextItem` enumerations can be logically
123    /// OR'ed together to more efficiently retrieve multiple symbol objects.
124    pub fn module(&self) -> Option<SBModule> {
125        SBModule::maybe_wrap(unsafe { sys::SBAddressGetModule(self.raw) })
126    }
127
128    /// Get the `SBCompileUnit` for a given address.
129    ///
130    /// An address might refer to code or data from an existing
131    /// module, or it might refer to something on the stack or heap.
132    /// This will only return valid values if the address has been
133    /// resolved to a code or data address using
134    /// [`SBAddress::from_load_address`] or [`SBTarget::resolve_load_address`].
135    ///
136    /// This grabs an individual object for a given address and
137    /// is less efficient if you want more than one symbol related objects.
138    /// Use one of the following when you want multiple debug symbol related
139    /// objects for an address:
140    ///
141    /// * [`SBAddress::symbol_context`]
142    /// * `SBTarget::resolve_symbol_context_for_address`
143    ///
144    /// One or more bits from the `SymbolContextItem` enumerations can be logically
145    /// OR'ed together to more efficiently retrieve multiple symbol objects.
146    pub fn compile_unit(&self) -> Option<SBCompileUnit> {
147        SBCompileUnit::maybe_wrap(unsafe { sys::SBAddressGetCompileUnit(self.raw) })
148    }
149
150    /// Get the `SBFunction` for a given address.
151    ///
152    /// An address might refer to code or data from an existing
153    /// module, or it might refer to something on the stack or heap.
154    /// This will only return valid values if the address has been
155    /// resolved to a code or data address using
156    /// [`SBAddress::from_load_address`] or [`SBTarget::resolve_load_address`].
157    ///
158    /// This grabs an individual object for a given address and
159    /// is less efficient if you want more than one symbol related objects.
160    /// Use one of the following when you want multiple debug symbol related
161    /// objects for an address:
162    ///
163    /// * [`SBAddress::symbol_context`]
164    /// * `SBTarget::resolve_symbol_context_for_address`
165    ///
166    /// One or more bits from the `SymbolContextItem` enumerations can be logically
167    /// OR'ed together to more efficiently retrieve multiple symbol objects.
168    pub fn function(&self) -> Option<SBFunction> {
169        SBFunction::maybe_wrap(unsafe { sys::SBAddressGetFunction(self.raw) })
170    }
171
172    /// Get the `SBBlock` for a given address.
173    ///
174    /// An address might refer to code or data from an existing
175    /// module, or it might refer to something on the stack or heap.
176    /// This will only return valid values if the address has been
177    /// resolved to a code or data address using
178    /// [`SBAddress::from_load_address`] or [`SBTarget::resolve_load_address`].
179    ///
180    /// This grabs an individual object for a given address and
181    /// is less efficient if you want more than one symbol related objects.
182    /// Use one of the following when you want multiple debug symbol related
183    /// objects for an address:
184    ///
185    /// * [`SBAddress::symbol_context`]
186    /// * `SBTarget::resolve_symbol_context_for_address`
187    ///
188    /// One or more bits from the `SymbolContextItem` enumerations can be logically
189    /// OR'ed together to more efficiently retrieve multiple symbol objects.
190    pub fn block(&self) -> Option<SBBlock> {
191        SBBlock::maybe_wrap(unsafe { sys::SBAddressGetBlock(self.raw) })
192    }
193
194    /// Get the `SBSymbol` for a given address.
195    ///
196    /// An address might refer to code or data from an existing
197    /// module, or it might refer to something on the stack or heap.
198    /// This will only return valid values if the address has been
199    /// resolved to a code or data address using
200    /// [`SBAddress::from_load_address`] or [`SBTarget::resolve_load_address`].
201    ///
202    /// This grabs an individual object for a given address and
203    /// is less efficient if you want more than one symbol related objects.
204    /// Use one of the following when you want multiple debug symbol related
205    /// objects for an address:
206    ///
207    /// * [`SBAddress::symbol_context`]
208    /// * `SBTarget::resolve_symbol_context_for_address`
209    ///
210    /// One or more bits from the `SymbolContextItem` enumerations can be logically
211    /// OR'ed together to more efficiently retrieve multiple symbol objects.
212    pub fn symbol(&self) -> Option<SBSymbol> {
213        SBSymbol::maybe_wrap(unsafe { sys::SBAddressGetSymbol(self.raw) })
214    }
215
216    /// Get the `SBLineEntry` for a given address.
217    ///
218    /// An address might refer to code or data from an existing
219    /// module, or it might refer to something on the stack or heap.
220    /// This will only return valid values if the address has been
221    /// resolved to a code or data address using
222    /// [`SBAddress::from_load_address`] or [`SBTarget::resolve_load_address`].
223    ///
224    /// This grabs an individual object for a given address and
225    /// is less efficient if you want more than one symbol related objects.
226    /// Use one of the following when you want multiple debug symbol related
227    /// objects for an address:
228    ///
229    /// * [`SBAddress::symbol_context`]
230    /// * `SBTarget::resolve_symbol_context_for_address`
231    ///
232    /// One or more bits from the `SymbolContextItem` enumerations can be logically
233    /// OR'ed together to more efficiently retrieve multiple symbol objects.
234    pub fn line_entry(&self) -> Option<SBLineEntry> {
235        SBLineEntry::maybe_wrap(unsafe { sys::SBAddressGetLineEntry(self.raw) })
236    }
237
238    /// Returns offset of the address in the section
239    ///
240    /// See also:
241    /// - [`get_section`] for getting the section corresponding to this address
242    ///
243    /// [`get_section`]: Self::get_section
244    pub fn get_offset(&self) -> lldb_addr_t {
245        unsafe { sys::SBAddressGetOffset(self.raw) }
246    }
247
248    /// Returns the corresponding section of this address.
249    pub fn get_section(&self) -> Option<SBSection> {
250        SBSection::maybe_wrap(unsafe { sys::SBAddressGetSection(self.raw) })
251    }
252}
253
254impl Clone for SBAddress {
255    fn clone(&self) -> SBAddress {
256        SBAddress {
257            raw: unsafe { sys::CloneSBAddress(self.raw) },
258        }
259    }
260}
261
262impl fmt::Debug for SBAddress {
263    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
264        let stream = SBStream::new();
265        unsafe { sys::SBAddressGetDescription(self.raw, stream.raw) };
266        write!(fmt, "SBAddress {{ {} }}", stream.data())
267    }
268}
269
270impl Drop for SBAddress {
271    fn drop(&mut self) {
272        unsafe { sys::DisposeSBAddress(self.raw) };
273    }
274}
275
276unsafe impl Send for SBAddress {}
277unsafe impl Sync for SBAddress {}
278
279impl PartialEq for SBAddress {
280    fn eq(&self, other: &Self) -> bool {
281        unsafe { sys::SBAddressIsEqual(self.raw, other.raw) }
282    }
283}
284
285impl Eq for SBAddress {}
286
287#[cfg(feature = "graphql")]
288#[juniper::graphql_object]
289impl SBAddress {
290    // TODO(bm) This should be u64
291    fn file_address() -> i32 {
292        self.file_address() as i32
293    }
294
295    fn module() -> Option<SBModule> {
296        self.module()
297    }
298
299    fn compile_unit() -> Option<SBCompileUnit> {
300        self.compile_unit()
301    }
302
303    fn function() -> Option<SBFunction> {
304        self.function()
305    }
306
307    fn block() -> Option<SBBlock> {
308        self.block()
309    }
310
311    fn symbol() -> Option<SBSymbol> {
312        self.symbol()
313    }
314
315    fn line_entry() -> Option<SBLineEntry> {
316        self.line_entry()
317    }
318}
319
320#[cfg(test)]
321mod tests {
322    use super::SBAddress;
323    use crate::sys;
324
325    #[test]
326    fn test_equal() {
327        let sect = unsafe { sys::CreateSBSection() };
328        let a = SBAddress::maybe_wrap(unsafe { sys::CreateSBAddress2(sect, 42) }).unwrap();
329        let b = SBAddress::maybe_wrap(unsafe { sys::CreateSBAddress2(sect, 42) }).unwrap();
330        assert!(a == b);
331    }
332
333    #[test]
334    fn test_not_equal() {
335        let sect = unsafe { sys::CreateSBSection() };
336        let a = SBAddress::maybe_wrap(unsafe { sys::CreateSBAddress2(sect, 42) }).unwrap();
337        let b = SBAddress::maybe_wrap(unsafe { sys::CreateSBAddress2(sect, 111) }).unwrap();
338        assert!(a != b);
339    }
340}