Skip to content

Commit

Permalink
feat: add many safe wrapper functions
Browse files Browse the repository at this point in the history
  • Loading branch information
anatawa12 committed Nov 25, 2024
1 parent bde72aa commit 0828838
Show file tree
Hide file tree
Showing 8 changed files with 240 additions and 4 deletions.
15 changes: 15 additions & 0 deletions src/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,21 @@ impl SBAddress {
pub fn line_entry(&self) -> Option<SBLineEntry> {
SBLineEntry::maybe_wrap(unsafe { sys::SBAddressGetLineEntry(self.raw) })
}

/// Returns offset of the address in the section
///
/// See also:
/// - [`get_section`] for get the section corresponding to this address
///
/// [`get_section`]: Self::get_section
pub fn get_offset(&self) -> lldb_addr_t {
unsafe { sys::SBAddressGetOffset(self.raw) }
}

/// Returns the corresponding section of this address.
pub fn get_section(&self) -> Option<SBSection> {
SBSection::maybe_wrap(unsafe { sys::SBAddressGetSection(self.raw) });
}
}

impl Clone for SBAddress {
Expand Down
32 changes: 31 additions & 1 deletion src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use crate::sys;
use crate::{sys, SBError};

/// A block of data.
#[derive(Debug)]
Expand Down Expand Up @@ -32,6 +32,36 @@ impl SBData {
pub fn is_valid(&self) -> bool {
unsafe { sys::SBDataIsValid(self.raw) }
}

/// Get address of the specified offset in this data region
pub fn get_address(&self, offset: sys::lldb_offset_t) -> Result<sys::lldb_addr_t, SBError> {
let error = SBError::default();
let result = unsafe { sys::SBDataGetAddress(self.raw, error.raw, offset) };
if error.is_success() {
Ok(result)
} else {
Err(error)
}
}

/// Reads the data at specified offset to the buffer.
fn read_raw_data(&self, offset: sys::lldb_offset_t, buffer: &mut [u8]) -> Result<(), SBError> {
let error = SBError::default();
unsafe {
sys::SBDataReadRawData(
self.raw,
error.raw,
offset,
buffer.as_mut_ptr() as *mut _,
buffer.len(),
);
}
if error.is_success() {
Ok(())
} else {
Err(error)
}
}
}

impl Clone for SBData {
Expand Down
6 changes: 6 additions & 0 deletions src/filespec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ impl SBFileSpec {
}
}

/// Create SBFileSpec from path
pub fn from_path(path: &str, resolve: bool) -> Self {
let path_cstring = std::ffi::CString::new(path).unwrap();
Self::wrap(unsafe { sys::CreateSBFileSpec3(path_cstring.as_ptr(), resolve) })
}

/// Check whether or not this is a valid `SBFileSpec` value.
pub fn is_valid(&self) -> bool {
unsafe { sys::SBFileSpecIsValid(self.raw) }
Expand Down
65 changes: 64 additions & 1 deletion src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
// except according to those terms.

use crate::{
sys, SBFileSpec, SBSection, SBStream, SBSymbolContextList, SBTypeList, SymbolType, TypeClass,
sys, SBFileSpec, SBSection, SBStream, SBSymbol, SBSymbolContextList, SBTypeList, SymbolType,
TypeClass,
};
use std::ffi::CString;
use std::fmt;
Expand Down Expand Up @@ -99,6 +100,11 @@ impl SBModule {
pub fn types(&self, type_mask: TypeClass) -> SBTypeList {
SBTypeList::wrap(unsafe { sys::SBModuleGetTypes(self.raw, type_mask.bits()) })
}

/// Get a list of all symbols in the module
pub fn symbols(&self) -> ModuleSymbols {
ModuleSymbols { module: self }
}
}

/// Iterate over the [sections] in a [module].
Expand Down Expand Up @@ -133,6 +139,63 @@ impl<'d> Iterator for SBModuleSectionIter<'d> {

impl<'d> ExactSizeIterator for SBModuleSectionIter<'d> {}

/// The list of symbols in the module
pub struct ModuleSymbols<'d> {
module: &'d SBModule,
}

impl<'d> ModuleSymbols<'d> {
pub fn len(&self) -> usize {
unsafe { sys::SBModuleGetNumSymbols(self.module.raw) }
}

pub fn get(&self, index: usize) -> Option<SBSymbol> {
if index < self.len() {
let symbol = unsafe { sys::SBModuleGetSymbolAtIndex(self.module.raw, index) };
Some(SBSymbol { raw: symbol })
} else {
None
}
}
}

impl<'a> IntoIterator for ModuleSymbols<'a> {
type Item = SBSymbol;
type IntoIter = ModuleSymbolsIter<'a>;

fn into_iter(self) -> Self::IntoIter {
ModuleSymbolsIter {
module: self,
index: 0,
}
}
}

struct ModuleSymbolsIter<'d> {
module: ModuleSymbols<'d>,
index: usize,
}

impl<'d> Iterator for ModuleSymbolsIter<'d> {
type Item = SBSymbol;

fn next(&mut self) -> Option<Self::Item> {
if self.index < self.module.len() {
self.index += 1;
self.module.get(self.index - 1)
} else {
None
}
}

fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.module.len() - self.index;
(len, Some(len))
}
}

impl<'d> ExactSizeIterator for ModuleSymbolsIter<'d> {}

impl Clone for SBModule {
fn clone(&self) -> SBModule {
SBModule {
Expand Down
10 changes: 10 additions & 0 deletions src/modulespec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ pub struct SBModuleSpec {
}

impl SBModuleSpec {
/// Construct a new `SBModuleSpec`.
pub(crate) fn wrap(raw: sys::SBModuleSpecRef) -> SBModuleSpec {
SBModuleSpec { raw }
}

/// Construct a new `Some(SBModuleSpec)` or `None`.
#[allow(dead_code)]
pub(crate) fn maybe_wrap(raw: sys::SBModuleSpecRef) -> Option<SBModuleSpec> {
Expand All @@ -29,6 +34,11 @@ impl SBModuleSpec {
unsafe { sys::SBModuleSpecIsValid(self.raw) }
}

/// Creates new empty SBModuleSpec
pub fn new() -> Self {
Self::wrap(unsafe { sys::CreateSBModuleSpec() })
}

/// The file for the module on the host system that is running LLDB.
///
/// This can differ from the path on the platform since we might
Expand Down
83 changes: 81 additions & 2 deletions src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

use crate::{
lldb_addr_t, lldb_pid_t, lldb_tid_t, sys, Permissions, SBBroadcaster, SBError, SBEvent,
SBMemoryRegionInfo, SBMemoryRegionInfoList, SBProcessInfo, SBQueue, SBStream, SBStructuredData,
SBThread, StateType,
SBFileSpec, SBMemoryRegionInfo, SBMemoryRegionInfoList, SBProcessInfo, SBQueue, SBStream,
SBStructuredData, SBTarget, SBThread, StateType,
};
use std::ffi::{CStr, CString};
use std::fmt;
Expand Down Expand Up @@ -559,6 +559,85 @@ impl SBProcess {
pub fn get_memory_regions(&self) -> SBMemoryRegionInfoList {
SBMemoryRegionInfoList::wrap(unsafe { sys::SBProcessGetMemoryRegions(self.raw) })
}

/// Reads the memory at specified address in the process to the `buffer`
pub fn read_memory(&self, addr: lldb_addr_t, buffer: &mut [u8]) -> Result<(), SBError> {
// SBProcessReadMemory will return error the memory region is not allowed to read
// and does not cause bad behavior so this method can be safe.
let error = SBError::default();
unsafe {
sys::SBProcessReadMemory(
self.raw,
addr,
buffer.as_mut_ptr() as *mut _,
buffer.len(),
error.raw,
);
}
if error.is_success() {
Ok(())
} else {
Err(error)
}
}

/// Writes the `buffer` data to the memory at specified address in the process
pub fn write_memory(&self, addr: lldb_addr_t, buffer: &[u8]) -> Result<(), SBError> {
let error = SBError::default();
unsafe {
sys::SBProcessWriteMemory(
self.raw,
addr,
buffer.as_ptr() as *mut _,
buffer.len(),
error.raw,
);
}
if error.is_success() {
Ok(())
} else {
Err(error)
}
}

/// Returns the byte order of target process
pub fn byte_order(&self) -> crate::ByteOrder {
unsafe { sys::SBProcessGetByteOrder(self.raw) }
}

/// Loads the specified image to the process
pub fn load_image(&self, file: &SBFileSpec) -> Result<u32, SBError> {
let error = SBError::default();
let image_token = unsafe { sys::SBProcessLoadImage(self.raw, file.raw, error.raw) };
if error.is_failure() {
Err(error)
} else {
Ok(image_token)
}
}

/// Unloads the image loaded with [`load_image`]
///
/// [`load_image`]: Self::load_image
pub fn unload_image(&self, image_token: u32) -> Result<(), SBError> {
// the method returns error if image_token is not valid, instead of cause undefined behavior
let error = SBError::wrap(unsafe { sys::SBProcessUnloadImage(self.raw, image_token) });
if error.is_failure() {
Err(error)
} else {
Ok(())
}
}

/// Returns the [`SBTarget`] corresponds to this SBProcess.
///
/// This never return None if `self` is [`valid`].
///
/// [`SBTarget`]: SBTarget
/// [`valid`]: Self::is_valid
pub fn target(&self) -> Option<SBTarget> {
SBTarget::maybe_wrap(unsafe { sys::SBProcessGetTarget(self.raw) })
}
}

/// Iterate over the [threads] in a [process].
Expand Down
11 changes: 11 additions & 0 deletions src/target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::{
SBModule, SBModuleSpec, SBPlatform, SBProcess, SBStream, SBSymbolContextList, SBValue,
SBWatchpoint, SymbolType,
};
use lldb_sys::ByteOrder;
use std::ffi::{CStr, CString};
use std::fmt;

Expand Down Expand Up @@ -386,6 +387,16 @@ impl SBTarget {
pub fn set_launch_info(&self, launch_info: SBLaunchInfo) {
unsafe { sys::SBTargetSetLaunchInfo(self.raw, launch_info.raw) };
}

/// Returns the byte order of target
pub fn byte_order(&self) -> ByteOrder {
unsafe { sys::SBTargetGetByteOrder(self.raw) }
}

/// Returns the size of address in bytes
fn get_address_byte_size(&self) -> u32 {
unsafe { sys::SBTargetGetAddressByteSize(self.raw) }
}
}

impl Clone for SBTarget {
Expand Down
22 changes: 22 additions & 0 deletions src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,28 @@ impl SBValue {
None
}
}

/// Get the value as signed integer
fn get_as_signed(&self) -> Result<i64, SBError> {
let error = SBError::default();
let result = unsafe { sys::SBValueGetValueAsSigned(self.raw, error.raw, 0) };
if error.is_success() {
Ok(result)
} else {
Err(error)
}
}

/// Get the value as unsigned integer
pub fn get_as_unsigned(&self) -> Result<u64, SBError> {
let error = SBError::default();
let result = unsafe { sys::SBValueGetValueAsUnsigned(self.raw, error.raw, 0) };
if error.is_success() {
Ok(result)
} else {
Err(error)
}
}
}

impl Clone for SBValue {
Expand Down

0 comments on commit 0828838

Please sign in to comment.