From 3d6f6d24e18e558ae040f0ca303b57a62283301f Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Tue, 10 Apr 2018 20:56:02 +0200 Subject: [PATCH 1/4] Fixed deprecated usage of tyvar_behind_raw_pointer --- src/macos/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/macos/mod.rs b/src/macos/mod.rs index 33c148a..ccd799a 100644 --- a/src/macos/mod.rs +++ b/src/macos/mod.rs @@ -141,7 +141,8 @@ impl<'a> MachHeader<'a> { MachType::from_header_ptr(header).and_then(|ty| { match ty { MachType::Mach32 => header.as_ref().map(MachHeader::Header32), - MachType::Mach64 => (header as *const _).as_ref().map(MachHeader::Header64), + MachType::Mach64 => (header as *const bindings::mach_header_64) + .as_ref().map(MachHeader::Header64), } }) } From 9d83263fa4deaf71cd8e4e88fada0e9386bb709f Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Tue, 10 Apr 2018 21:29:23 +0200 Subject: [PATCH 2/4] Added support for fetching IDs from a shared library --- build.rs | 2 ++ src/lib.rs | 37 +++++++++++++++++++++++++++++++++++++ src/macos/mod.rs | 33 ++++++++++++++++++++++++++++++++- 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/build.rs b/build.rs index a0fb9c9..0355e20 100644 --- a/build.rs +++ b/build.rs @@ -34,9 +34,11 @@ fn generate_macos_bindings() { .whitelist_function("_dyld_.*") .whitelist_type("mach_header.*") .whitelist_type("load_command.*") + .whitelist_type("uuid_command.*") .whitelist_type("segment_command.*") .whitelist_var("MH_MAGIC.*") .whitelist_var("LC_SEGMENT.*") + .whitelist_var("LC_UUID.*") .generate() .expect("Should generate macOS FFI bindings OK"); diff --git a/src/lib.rs b/src/lib.rs index b6fa00a..39542d2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -225,6 +225,40 @@ pub trait Segment: Sized + Debug { } } +/// Represents an ID for a shared library. +#[derive(PartialEq, Eq, Hash)] +pub enum SharedLibraryId { + /// A UUID (used on mac) + Uuid([u8; 16]), +} + +impl fmt::Display for SharedLibraryId { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + SharedLibraryId::Uuid(ref bytes) => { + for (idx, byte) in bytes.iter().enumerate() { + if idx == 4 || idx == 6 || idx == 8 || idx == 10 { + try!(write!(f, "-")); + } + try!(write!(f, "{:02x}", byte)); + } + } + } + Ok(()) + } +} + +impl fmt::Debug for SharedLibraryId { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + SharedLibraryId::Uuid(..) => { + write!(f, "Uuid(\"{}\")", self)?; + } + } + Ok(()) + } +} + /// A trait representing a shared library that is loaded in this process. pub trait SharedLibrary: Sized + Debug { /// The associated segment type for this shared library. @@ -236,6 +270,9 @@ pub trait SharedLibrary: Sized + Debug { /// Get the name of this shared library. fn name(&self) -> &CStr; + /// Get the debug-id of this shared library if available. + fn id(&self) -> Option { None } + /// Iterate over this shared library's segments. fn segments(&self) -> Self::SegmentIter; diff --git a/src/macos/mod.rs b/src/macos/mod.rs index ccd799a..39b289d 100644 --- a/src/macos/mod.rs +++ b/src/macos/mod.rs @@ -1,7 +1,7 @@ //! The MacOS implementation of the [SharedLibrary //! trait](../trait.SharedLibrary.html). -use super::{Bias, IterationControl, Svma}; +use super::{Bias, IterationControl, Svma, SharedLibraryId}; use super::Segment as SegmentTrait; use super::SharedLibrary as SharedLibraryTrait; @@ -74,6 +74,26 @@ pub struct SegmentIter<'a> { num_commands: usize, } +impl<'a> SegmentIter<'a> { + fn find_uuid(&self) -> Option<[u8; 16]> { + let mut num_commands = self.num_commands; + let mut commands = self.commands; + + while num_commands > 0 { + num_commands -= 1; + let this_command = unsafe { commands.as_ref().unwrap() }; + let command_size = this_command.cmdsize as isize; + if let bindings::LC_UUID = this_command.cmd { + let uuid_cmd = commands as *const bindings::uuid_command; + return Some(unsafe { (*uuid_cmd).uuid }); + } + commands = unsafe { (commands as *const u8).offset(command_size) as *const _ }; + } + + None + } +} + impl<'a> Iterator for SegmentIter<'a> { type Item = Segment<'a>; @@ -180,6 +200,10 @@ impl<'a> SharedLibraryTrait for SharedLibrary<'a> { self.name } + fn id(&self) -> Option { + self.segments().find_uuid().map(SharedLibraryId::Uuid) + } + fn segments(&self) -> Self::SegmentIter { match self.header { MachHeader::Header32(header) => { @@ -291,6 +315,13 @@ mod tests { }); } + #[test] + fn get_id() { + macos::SharedLibrary::each(|shlib| { + assert!(shlib.id().is_some()); + }); + } + #[test] fn have_text_or_pagezero() { macos::SharedLibrary::each(|shlib| { From 117544868d2755cbba7bc1c2ea84d921e871bfa5 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Tue, 10 Apr 2018 21:34:58 +0200 Subject: [PATCH 3/4] Do not implement defaults for id() --- src/lib.rs | 2 +- src/linux/mod.rs | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 39542d2..30645d0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -271,7 +271,7 @@ pub trait SharedLibrary: Sized + Debug { fn name(&self) -> &CStr; /// Get the debug-id of this shared library if available. - fn id(&self) -> Option { None } + fn id(&self) -> Option; /// Iterate over this shared library's segments. fn segments(&self) -> Self::SegmentIter; diff --git a/src/linux/mod.rs b/src/linux/mod.rs index 5b0d79f..b104ac4 100644 --- a/src/linux/mod.rs +++ b/src/linux/mod.rs @@ -1,6 +1,6 @@ //! Linux-specific implementation of the `SharedLibrary` trait. -use super::{Bias, IterationControl, Svma}; +use super::{Bias, IterationControl, Svma, SharedLibraryId}; use super::Segment as SegmentTrait; use super::SharedLibrary as SharedLibraryTrait; @@ -55,6 +55,10 @@ impl<'a> SegmentTrait for Segment<'a> { } } + fn id(&self) -> Option { + None + } + #[inline] fn stated_virtual_memory_address(&self) -> Svma { Svma(unsafe { From 2deb38a69c5e1e723a53730effd9fd2801c398d1 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Tue, 10 Apr 2018 22:35:59 +0200 Subject: [PATCH 4/4] Moved a method to the right trait implementation --- src/linux/mod.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/linux/mod.rs b/src/linux/mod.rs index b104ac4..ccb0f51 100644 --- a/src/linux/mod.rs +++ b/src/linux/mod.rs @@ -55,10 +55,6 @@ impl<'a> SegmentTrait for Segment<'a> { } } - fn id(&self) -> Option { - None - } - #[inline] fn stated_virtual_memory_address(&self) -> Svma { Svma(unsafe { @@ -153,6 +149,11 @@ impl<'a> SharedLibraryTrait for SharedLibrary<'a> { self.name } + #[inline] + fn id(&self) -> Option { + None + } + #[inline] fn segments(&self) -> Self::SegmentIter { SegmentIter { inner: self.headers.iter() }