diff options
Diffstat (limited to 'vendor/backtrace/src/symbolize/gimli/libs_macos.rs')
-rw-r--r-- | vendor/backtrace/src/symbolize/gimli/libs_macos.rs | 146 |
1 files changed, 0 insertions, 146 deletions
diff --git a/vendor/backtrace/src/symbolize/gimli/libs_macos.rs b/vendor/backtrace/src/symbolize/gimli/libs_macos.rs deleted file mode 100644 index 438bbff..0000000 --- a/vendor/backtrace/src/symbolize/gimli/libs_macos.rs +++ /dev/null @@ -1,146 +0,0 @@ -#![allow(deprecated)] - -use super::mystd::ffi::{CStr, OsStr}; -use super::mystd::os::unix::prelude::*; -use super::mystd::prelude::v1::*; -use super::{Library, LibrarySegment}; -use core::convert::TryInto; -use core::mem; - -pub(super) fn native_libraries() -> Vec<Library> { - let mut ret = Vec::new(); - let images = unsafe { libc::_dyld_image_count() }; - for i in 0..images { - ret.extend(native_library(i)); - } - return ret; -} - -fn native_library(i: u32) -> Option<Library> { - use object::macho; - use object::read::macho::{MachHeader, Segment}; - use object::NativeEndian; - - // Fetch the name of this library which corresponds to the path of - // where to load it as well. - let name = unsafe { - let name = libc::_dyld_get_image_name(i); - if name.is_null() { - return None; - } - CStr::from_ptr(name) - }; - - // Load the image header of this library and delegate to `object` to - // parse all the load commands so we can figure out all the segments - // involved here. - let (mut load_commands, endian) = unsafe { - let header = libc::_dyld_get_image_header(i); - if header.is_null() { - return None; - } - match (*header).magic { - macho::MH_MAGIC => { - let endian = NativeEndian; - let header = &*(header as *const macho::MachHeader32<NativeEndian>); - let data = core::slice::from_raw_parts( - header as *const _ as *const u8, - mem::size_of_val(header) + header.sizeofcmds.get(endian) as usize, - ); - (header.load_commands(endian, data, 0).ok()?, endian) - } - macho::MH_MAGIC_64 => { - let endian = NativeEndian; - let header = &*(header as *const macho::MachHeader64<NativeEndian>); - let data = core::slice::from_raw_parts( - header as *const _ as *const u8, - mem::size_of_val(header) + header.sizeofcmds.get(endian) as usize, - ); - (header.load_commands(endian, data, 0).ok()?, endian) - } - _ => return None, - } - }; - - // Iterate over the segments and register known regions for segments - // that we find. Additionally record information bout text segments - // for processing later, see comments below. - let mut segments = Vec::new(); - let mut first_text = 0; - let mut text_fileoff_zero = false; - while let Some(cmd) = load_commands.next().ok()? { - if let Some((seg, _)) = cmd.segment_32().ok()? { - if seg.name() == b"__TEXT" { - first_text = segments.len(); - if seg.fileoff(endian) == 0 && seg.filesize(endian) > 0 { - text_fileoff_zero = true; - } - } - segments.push(LibrarySegment { - len: seg.vmsize(endian).try_into().ok()?, - stated_virtual_memory_address: seg.vmaddr(endian).try_into().ok()?, - }); - } - if let Some((seg, _)) = cmd.segment_64().ok()? { - if seg.name() == b"__TEXT" { - first_text = segments.len(); - if seg.fileoff(endian) == 0 && seg.filesize(endian) > 0 { - text_fileoff_zero = true; - } - } - segments.push(LibrarySegment { - len: seg.vmsize(endian).try_into().ok()?, - stated_virtual_memory_address: seg.vmaddr(endian).try_into().ok()?, - }); - } - } - - // Determine the "slide" for this library which ends up being the - // bias we use to figure out where in memory objects are loaded. - // This is a bit of a weird computation though and is the result of - // trying a few things in the wild and seeing what sticks. - // - // The general idea is that the `bias` plus a segment's - // `stated_virtual_memory_address` is going to be where in the - // actual address space the segment resides. The other thing we rely - // on though is that a real address minus the `bias` is the index to - // look up in the symbol table and debuginfo. - // - // It turns out, though, that for system loaded libraries these - // calculations are incorrect. For native executables, however, it - // appears correct. Lifting some logic from LLDB's source it has - // some special-casing for the first `__TEXT` section loaded from - // file offset 0 with a nonzero size. For whatever reason when this - // is present it appears to mean that the symbol table is relative - // to just the vmaddr slide for the library. If it's *not* present - // then the symbol table is relative to the vmaddr slide plus the - // segment's stated address. - // - // To handle this situation if we *don't* find a text section at - // file offset zero then we increase the bias by the first text - // sections's stated address and decrease all stated addresses by - // that amount as well. That way the symbol table is always appears - // relative to the library's bias amount. This appears to have the - // right results for symbolizing via the symbol table. - // - // Honestly I'm not entirely sure whether this is right or if - // there's something else that should indicate how to do this. For - // now though this seems to work well enough (?) and we should - // always be able to tweak this over time if necessary. - // - // For some more information see #318 - let mut slide = unsafe { libc::_dyld_get_image_vmaddr_slide(i) as usize }; - if !text_fileoff_zero { - let adjust = segments[first_text].stated_virtual_memory_address; - for segment in segments.iter_mut() { - segment.stated_virtual_memory_address -= adjust; - } - slide += adjust; - } - - Some(Library { - name: OsStr::from_bytes(name.to_bytes()).to_owned(), - segments, - bias: slide, - }) -} |