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}