-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add many safe wrapper functions #39
Changes from 2 commits
d93ca79
87d7afc
19ed04e
c43ae51
149f8de
77005e5
2eb1d9d
2abccb6
4d51f87
c13a29f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,6 +33,12 @@ impl SBFileSpec { | |
} | ||
} | ||
|
||
/// Create SBFileSpec from path | ||
pub fn from_path(path: &str, resolve: bool) -> Self { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it make sense for this to be generic on something like:
? |
||
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) } | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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; | ||
|
@@ -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]. | ||
|
@@ -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> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't this just be a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it should have direct indexed accessor and length access so I made it have intermediate struct. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Curious to know why... but not going to block on it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When I want to get first library (excluding exexutable), I think it should be possible to access 1th element without accessing 0th element, but I came up with implementing |
||
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, | ||
} | ||
} | ||
} | ||
|
||
pub 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 { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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; | ||
|
@@ -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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "will return an error if the" (2 missing words) |
||
// 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "into the" and a missing period at the end. |
||
pub fn load_image(&self, file: &SBFileSpec) -> Result<u32, SBError> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd probably make a quick |
||
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`] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing period at the end. |
||
/// | ||
/// [`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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "instead of causing" |
||
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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "corresponding" and missing backticks on |
||
/// | ||
/// 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]. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"for getting the"