aboutsummaryrefslogtreecommitdiff
path: root/vendor/backtrace/src/symbolize/gimli
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2024-07-19 15:37:58 +0300
committerValentin Popov <valentin@popov.link>2024-07-19 15:37:58 +0300
commita990de90fe41456a23e58bd087d2f107d321f3a1 (patch)
tree15afc392522a9e85dc3332235e311b7d39352ea9 /vendor/backtrace/src/symbolize/gimli
parent3d48cd3f81164bbfc1a755dc1d4a9a02f98c8ddd (diff)
downloadfparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.tar.xz
fparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.zip
Deleted vendor folder
Diffstat (limited to 'vendor/backtrace/src/symbolize/gimli')
-rw-r--r--vendor/backtrace/src/symbolize/gimli/coff.rs118
-rw-r--r--vendor/backtrace/src/symbolize/gimli/elf.rs495
-rw-r--r--vendor/backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs71
-rw-r--r--vendor/backtrace/src/symbolize/gimli/libs_haiku.rs48
-rw-r--r--vendor/backtrace/src/symbolize/gimli/libs_illumos.rs99
-rw-r--r--vendor/backtrace/src/symbolize/gimli/libs_libnx.rs27
-rw-r--r--vendor/backtrace/src/symbolize/gimli/libs_macos.rs146
-rw-r--r--vendor/backtrace/src/symbolize/gimli/libs_windows.rs89
-rw-r--r--vendor/backtrace/src/symbolize/gimli/macho.rs333
-rw-r--r--vendor/backtrace/src/symbolize/gimli/mmap_fake.rs25
-rw-r--r--vendor/backtrace/src/symbolize/gimli/mmap_unix.rs49
-rw-r--r--vendor/backtrace/src/symbolize/gimli/mmap_windows.rs57
-rw-r--r--vendor/backtrace/src/symbolize/gimli/parse_running_mmaps_unix.rs295
-rw-r--r--vendor/backtrace/src/symbolize/gimli/stash.rs50
14 files changed, 0 insertions, 1902 deletions
diff --git a/vendor/backtrace/src/symbolize/gimli/coff.rs b/vendor/backtrace/src/symbolize/gimli/coff.rs
deleted file mode 100644
index 759c827..0000000
--- a/vendor/backtrace/src/symbolize/gimli/coff.rs
+++ /dev/null
@@ -1,118 +0,0 @@
-use super::{gimli, Context, Endian, EndianSlice, Mapping, Path, Stash, Vec};
-use alloc::sync::Arc;
-use core::convert::TryFrom;
-use object::pe::{ImageDosHeader, ImageSymbol};
-use object::read::coff::ImageSymbol as _;
-use object::read::pe::{ImageNtHeaders, ImageOptionalHeader, SectionTable};
-use object::read::StringTable;
-use object::LittleEndian as LE;
-
-#[cfg(target_pointer_width = "32")]
-type Pe = object::pe::ImageNtHeaders32;
-#[cfg(target_pointer_width = "64")]
-type Pe = object::pe::ImageNtHeaders64;
-
-impl Mapping {
- pub fn new(path: &Path) -> Option<Mapping> {
- let map = super::mmap(path)?;
- Mapping::mk(map, |data, stash| {
- Context::new(stash, Object::parse(data)?, None, None)
- })
- }
-}
-
-pub struct Object<'a> {
- data: &'a [u8],
- sections: SectionTable<'a>,
- symbols: Vec<(usize, &'a ImageSymbol)>,
- strings: StringTable<'a>,
-}
-
-pub fn get_image_base(data: &[u8]) -> Option<usize> {
- let dos_header = ImageDosHeader::parse(data).ok()?;
- let mut offset = dos_header.nt_headers_offset().into();
- let (nt_headers, _) = Pe::parse(data, &mut offset).ok()?;
- usize::try_from(nt_headers.optional_header().image_base()).ok()
-}
-
-impl<'a> Object<'a> {
- fn parse(data: &'a [u8]) -> Option<Object<'a>> {
- let dos_header = ImageDosHeader::parse(data).ok()?;
- let mut offset = dos_header.nt_headers_offset().into();
- let (nt_headers, _) = Pe::parse(data, &mut offset).ok()?;
- let sections = nt_headers.sections(data, offset).ok()?;
- let symtab = nt_headers.symbols(data).ok()?;
- let strings = symtab.strings();
- let image_base = usize::try_from(nt_headers.optional_header().image_base()).ok()?;
-
- // Collect all the symbols into a local vector which is sorted
- // by address and contains enough data to learn about the symbol
- // name. Note that we only look at function symbols and also
- // note that the sections are 1-indexed because the zero section
- // is special (apparently).
- let mut symbols = Vec::new();
- let mut i = 0;
- let len = symtab.len();
- while i < len {
- let sym = symtab.symbol(i).ok()?;
- i += 1 + sym.number_of_aux_symbols as usize;
- let section_number = sym.section_number.get(LE);
- if sym.derived_type() != object::pe::IMAGE_SYM_DTYPE_FUNCTION || section_number == 0 {
- continue;
- }
- let addr = usize::try_from(sym.value.get(LE)).ok()?;
- let section = sections
- .section(usize::try_from(section_number).ok()?)
- .ok()?;
- let va = usize::try_from(section.virtual_address.get(LE)).ok()?;
- symbols.push((addr + va + image_base, sym));
- }
- symbols.sort_unstable_by_key(|x| x.0);
- Some(Object {
- data,
- sections,
- strings,
- symbols,
- })
- }
-
- pub fn section(&self, _: &Stash, name: &str) -> Option<&'a [u8]> {
- Some(
- self.sections
- .section_by_name(self.strings, name.as_bytes())?
- .1
- .pe_data(self.data)
- .ok()?,
- )
- }
-
- pub fn search_symtab<'b>(&'b self, addr: u64) -> Option<&'b [u8]> {
- // Note that unlike other formats COFF doesn't embed the size of
- // each symbol. As a last ditch effort search for the *closest*
- // symbol to a particular address and return that one. This gets
- // really wonky once symbols start getting removed because the
- // symbols returned here can be totally incorrect, but we have
- // no idea of knowing how to detect that.
- let addr = usize::try_from(addr).ok()?;
- let i = match self.symbols.binary_search_by_key(&addr, |p| p.0) {
- Ok(i) => i,
- // typically `addr` isn't in the array, but `i` is where
- // we'd insert it, so the previous position must be the
- // greatest less than `addr`
- Err(i) => i.checked_sub(1)?,
- };
- self.symbols[i].1.name(self.strings).ok()
- }
-
- pub(super) fn search_object_map(&self, _addr: u64) -> Option<(&Context<'_>, u64)> {
- None
- }
-}
-
-pub(super) fn handle_split_dwarf<'data>(
- _package: Option<&gimli::DwarfPackage<EndianSlice<'data, Endian>>>,
- _stash: &'data Stash,
- _load: addr2line::SplitDwarfLoad<EndianSlice<'data, Endian>>,
-) -> Option<Arc<gimli::Dwarf<EndianSlice<'data, Endian>>>> {
- None
-}
diff --git a/vendor/backtrace/src/symbolize/gimli/elf.rs b/vendor/backtrace/src/symbolize/gimli/elf.rs
deleted file mode 100644
index b0eec07..0000000
--- a/vendor/backtrace/src/symbolize/gimli/elf.rs
+++ /dev/null
@@ -1,495 +0,0 @@
-use super::mystd::ffi::{OsStr, OsString};
-use super::mystd::fs;
-use super::mystd::os::unix::ffi::{OsStrExt, OsStringExt};
-use super::mystd::path::{Path, PathBuf};
-use super::Either;
-use super::{gimli, Context, Endian, EndianSlice, Mapping, Stash, Vec};
-use alloc::sync::Arc;
-use core::convert::{TryFrom, TryInto};
-use core::str;
-use object::elf::{ELFCOMPRESS_ZLIB, ELF_NOTE_GNU, NT_GNU_BUILD_ID, SHF_COMPRESSED};
-use object::read::elf::{CompressionHeader, FileHeader, SectionHeader, SectionTable, Sym};
-use object::read::StringTable;
-use object::{BigEndian, Bytes, NativeEndian};
-
-#[cfg(target_pointer_width = "32")]
-type Elf = object::elf::FileHeader32<NativeEndian>;
-#[cfg(target_pointer_width = "64")]
-type Elf = object::elf::FileHeader64<NativeEndian>;
-
-impl Mapping {
- pub fn new(path: &Path) -> Option<Mapping> {
- let map = super::mmap(path)?;
- Mapping::mk_or_other(map, |map, stash| {
- let object = Object::parse(&map)?;
-
- // Try to locate an external debug file using the build ID.
- if let Some(path_debug) = object.build_id().and_then(locate_build_id) {
- if let Some(mapping) = Mapping::new_debug(path, path_debug, None) {
- return Some(Either::A(mapping));
- }
- }
-
- // Try to locate an external debug file using the GNU debug link section.
- if let Some((path_debug, crc)) = object.gnu_debuglink_path(path) {
- if let Some(mapping) = Mapping::new_debug(path, path_debug, Some(crc)) {
- return Some(Either::A(mapping));
- }
- }
-
- let dwp = Mapping::load_dwarf_package(path, stash);
-
- Context::new(stash, object, None, dwp).map(Either::B)
- })
- }
-
- /// Load debuginfo from an external debug file.
- fn new_debug(original_path: &Path, path: PathBuf, crc: Option<u32>) -> Option<Mapping> {
- let map = super::mmap(&path)?;
- Mapping::mk(map, |map, stash| {
- let object = Object::parse(&map)?;
-
- if let Some(_crc) = crc {
- // TODO: check crc
- }
-
- // Try to locate a supplementary object file.
- let mut sup = None;
- if let Some((path_sup, build_id_sup)) = object.gnu_debugaltlink_path(&path) {
- if let Some(map_sup) = super::mmap(&path_sup) {
- let map_sup = stash.cache_mmap(map_sup);
- if let Some(sup_) = Object::parse(map_sup) {
- if sup_.build_id() == Some(build_id_sup) {
- sup = Some(sup_);
- }
- }
- }
- }
-
- let dwp = Mapping::load_dwarf_package(original_path, stash);
-
- Context::new(stash, object, sup, dwp)
- })
- }
-
- /// Try to locate a DWARF package file.
- fn load_dwarf_package<'data>(path: &Path, stash: &'data Stash) -> Option<Object<'data>> {
- let mut path_dwp = path.to_path_buf();
- let dwp_extension = path
- .extension()
- .map(|previous_extension| {
- let mut previous_extension = previous_extension.to_os_string();
- previous_extension.push(".dwp");
- previous_extension
- })
- .unwrap_or_else(|| "dwp".into());
- path_dwp.set_extension(dwp_extension);
- if let Some(map_dwp) = super::mmap(&path_dwp) {
- let map_dwp = stash.cache_mmap(map_dwp);
- if let Some(dwp_) = Object::parse(map_dwp) {
- return Some(dwp_);
- }
- }
-
- None
- }
-}
-
-struct ParsedSym {
- address: u64,
- size: u64,
- name: u32,
-}
-
-pub struct Object<'a> {
- /// Zero-sized type representing the native endianness.
- ///
- /// We could use a literal instead, but this helps ensure correctness.
- endian: NativeEndian,
- /// The entire file data.
- data: &'a [u8],
- sections: SectionTable<'a, Elf>,
- strings: StringTable<'a>,
- /// List of pre-parsed and sorted symbols by base address.
- syms: Vec<ParsedSym>,
-}
-
-impl<'a> Object<'a> {
- fn parse(data: &'a [u8]) -> Option<Object<'a>> {
- let elf = Elf::parse(data).ok()?;
- let endian = elf.endian().ok()?;
- let sections = elf.sections(endian, data).ok()?;
- let mut syms = sections
- .symbols(endian, data, object::elf::SHT_SYMTAB)
- .ok()?;
- if syms.is_empty() {
- syms = sections
- .symbols(endian, data, object::elf::SHT_DYNSYM)
- .ok()?;
- }
- let strings = syms.strings();
-
- let mut syms = syms
- .iter()
- // Only look at function/object symbols. This mirrors what
- // libbacktrace does and in general we're only symbolicating
- // function addresses in theory. Object symbols correspond
- // to data, and maybe someone's crazy enough to have a
- // function go into static data?
- .filter(|sym| {
- let st_type = sym.st_type();
- st_type == object::elf::STT_FUNC || st_type == object::elf::STT_OBJECT
- })
- // skip anything that's in an undefined section header,
- // since it means it's an imported function and we're only
- // symbolicating with locally defined functions.
- .filter(|sym| sym.st_shndx(endian) != object::elf::SHN_UNDEF)
- .map(|sym| {
- let address = sym.st_value(endian).into();
- let size = sym.st_size(endian).into();
- let name = sym.st_name(endian);
- ParsedSym {
- address,
- size,
- name,
- }
- })
- .collect::<Vec<_>>();
- syms.sort_unstable_by_key(|s| s.address);
- Some(Object {
- endian,
- data,
- sections,
- strings,
- syms,
- })
- }
-
- pub fn section(&self, stash: &'a Stash, name: &str) -> Option<&'a [u8]> {
- if let Some(section) = self.section_header(name) {
- let mut data = Bytes(section.data(self.endian, self.data).ok()?);
-
- // Check for DWARF-standard (gABI) compression, i.e., as generated
- // by ld's `--compress-debug-sections=zlib-gabi` flag.
- let flags: u64 = section.sh_flags(self.endian).into();
- if (flags & u64::from(SHF_COMPRESSED)) == 0 {
- // Not compressed.
- return Some(data.0);
- }
-
- let header = data.read::<<Elf as FileHeader>::CompressionHeader>().ok()?;
- if header.ch_type(self.endian) != ELFCOMPRESS_ZLIB {
- // Zlib compression is the only known type.
- return None;
- }
- let size = usize::try_from(header.ch_size(self.endian)).ok()?;
- let buf = stash.allocate(size);
- decompress_zlib(data.0, buf)?;
- return Some(buf);
- }
-
- // Check for the nonstandard GNU compression format, i.e., as generated
- // by ld's `--compress-debug-sections=zlib-gnu` flag. This means that if
- // we're actually asking for `.debug_info` then we need to look up a
- // section named `.zdebug_info`.
- if !name.starts_with(".debug_") {
- return None;
- }
- let debug_name = name[7..].as_bytes();
- let compressed_section = self
- .sections
- .iter()
- .filter_map(|header| {
- let name = self.sections.section_name(self.endian, header).ok()?;
- if name.starts_with(b".zdebug_") && &name[8..] == debug_name {
- Some(header)
- } else {
- None
- }
- })
- .next()?;
- let mut data = Bytes(compressed_section.data(self.endian, self.data).ok()?);
- if data.read_bytes(8).ok()?.0 != b"ZLIB\0\0\0\0" {
- return None;
- }
- let size = usize::try_from(data.read::<object::U32Bytes<_>>().ok()?.get(BigEndian)).ok()?;
- let buf = stash.allocate(size);
- decompress_zlib(data.0, buf)?;
- Some(buf)
- }
-
- fn section_header(&self, name: &str) -> Option<&<Elf as FileHeader>::SectionHeader> {
- self.sections
- .section_by_name(self.endian, name.as_bytes())
- .map(|(_index, section)| section)
- }
-
- pub fn search_symtab<'b>(&'b self, addr: u64) -> Option<&'b [u8]> {
- // Same sort of binary search as Windows above
- let i = match self.syms.binary_search_by_key(&addr, |sym| sym.address) {
- Ok(i) => i,
- Err(i) => i.checked_sub(1)?,
- };
- let sym = self.syms.get(i)?;
- if sym.address <= addr && addr <= sym.address + sym.size {
- self.strings.get(sym.name).ok()
- } else {
- None
- }
- }
-
- pub(super) fn search_object_map(&self, _addr: u64) -> Option<(&Context<'_>, u64)> {
- None
- }
-
- fn build_id(&self) -> Option<&'a [u8]> {
- for section in self.sections.iter() {
- if let Ok(Some(mut notes)) = section.notes(self.endian, self.data) {
- while let Ok(Some(note)) = notes.next() {
- if note.name() == ELF_NOTE_GNU && note.n_type(self.endian) == NT_GNU_BUILD_ID {
- return Some(note.desc());
- }
- }
- }
- }
- None
- }
-
- // The contents of the ".gnu_debuglink" section is documented at:
- // https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
- fn gnu_debuglink_path(&self, path: &Path) -> Option<(PathBuf, u32)> {
- let section = self.section_header(".gnu_debuglink")?;
- let data = section.data(self.endian, self.data).ok()?;
- let len = data.iter().position(|x| *x == 0)?;
- let filename = &data[..len];
- let offset = (len + 1 + 3) & !3;
- let crc_bytes = data
- .get(offset..offset + 4)
- .and_then(|bytes| bytes.try_into().ok())?;
- let crc = u32::from_ne_bytes(crc_bytes);
- let path_debug = locate_debuglink(path, filename)?;
- Some((path_debug, crc))
- }
-
- // The format of the ".gnu_debugaltlink" section is based on gdb.
- fn gnu_debugaltlink_path(&self, path: &Path) -> Option<(PathBuf, &'a [u8])> {
- let section = self.section_header(".gnu_debugaltlink")?;
- let data = section.data(self.endian, self.data).ok()?;
- let len = data.iter().position(|x| *x == 0)?;
- let filename = &data[..len];
- let build_id = &data[len + 1..];
- let path_sup = locate_debugaltlink(path, filename, build_id)?;
- Some((path_sup, build_id))
- }
-}
-
-fn decompress_zlib(input: &[u8], output: &mut [u8]) -> Option<()> {
- use miniz_oxide::inflate::core::inflate_flags::{
- TINFL_FLAG_PARSE_ZLIB_HEADER, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF,
- };
- use miniz_oxide::inflate::core::{decompress, DecompressorOxide};
- use miniz_oxide::inflate::TINFLStatus;
-
- let (status, in_read, out_read) = decompress(
- &mut DecompressorOxide::new(),
- input,
- output,
- 0,
- TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | TINFL_FLAG_PARSE_ZLIB_HEADER,
- );
- if status == TINFLStatus::Done && in_read == input.len() && out_read == output.len() {
- Some(())
- } else {
- None
- }
-}
-
-const DEBUG_PATH: &[u8] = b"/usr/lib/debug";
-
-fn debug_path_exists() -> bool {
- cfg_if::cfg_if! {
- if #[cfg(any(target_os = "freebsd", target_os = "linux"))] {
- use core::sync::atomic::{AtomicU8, Ordering};
- static DEBUG_PATH_EXISTS: AtomicU8 = AtomicU8::new(0);
-
- let mut exists = DEBUG_PATH_EXISTS.load(Ordering::Relaxed);
- if exists == 0 {
- exists = if Path::new(OsStr::from_bytes(DEBUG_PATH)).is_dir() {
- 1
- } else {
- 2
- };
- DEBUG_PATH_EXISTS.store(exists, Ordering::Relaxed);
- }
- exists == 1
- } else {
- false
- }
- }
-}
-
-/// Locate a debug file based on its build ID.
-///
-/// The format of build id paths is documented at:
-/// https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
-fn locate_build_id(build_id: &[u8]) -> Option<PathBuf> {
- const BUILD_ID_PATH: &[u8] = b"/usr/lib/debug/.build-id/";
- const BUILD_ID_SUFFIX: &[u8] = b".debug";
-
- if build_id.len() < 2 {
- return None;
- }
-
- if !debug_path_exists() {
- return None;
- }
-
- let mut path =
- Vec::with_capacity(BUILD_ID_PATH.len() + BUILD_ID_SUFFIX.len() + build_id.len() * 2 + 1);
- path.extend(BUILD_ID_PATH);
- path.push(hex(build_id[0] >> 4));
- path.push(hex(build_id[0] & 0xf));
- path.push(b'/');
- for byte in &build_id[1..] {
- path.push(hex(byte >> 4));
- path.push(hex(byte & 0xf));
- }
- path.extend(BUILD_ID_SUFFIX);
- Some(PathBuf::from(OsString::from_vec(path)))
-}
-
-fn hex(byte: u8) -> u8 {
- if byte < 10 {
- b'0' + byte
- } else {
- b'a' + byte - 10
- }
-}
-
-/// Locate a file specified in a `.gnu_debuglink` section.
-///
-/// `path` is the file containing the section.
-/// `filename` is from the contents of the section.
-///
-/// Search order is based on gdb, documented at:
-/// https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
-///
-/// gdb also allows the user to customize the debug search path, but we don't.
-///
-/// gdb also supports debuginfod, but we don't yet.
-fn locate_debuglink(path: &Path, filename: &[u8]) -> Option<PathBuf> {
- let path = fs::canonicalize(path).ok()?;
- let parent = path.parent()?;
- let mut f = PathBuf::from(OsString::with_capacity(
- DEBUG_PATH.len() + parent.as_os_str().len() + filename.len() + 2,
- ));
- let filename = Path::new(OsStr::from_bytes(filename));
-
- // Try "/parent/filename" if it differs from "path"
- f.push(parent);
- f.push(filename);
- if f != path && f.is_file() {
- return Some(f);
- }
-
- // Try "/parent/.debug/filename"
- let mut s = OsString::from(f);
- s.clear();
- f = PathBuf::from(s);
- f.push(parent);
- f.push(".debug");
- f.push(filename);
- if f.is_file() {
- return Some(f);
- }
-
- if debug_path_exists() {
- // Try "/usr/lib/debug/parent/filename"
- let mut s = OsString::from(f);
- s.clear();
- f = PathBuf::from(s);
- f.push(OsStr::from_bytes(DEBUG_PATH));
- f.push(parent.strip_prefix("/").unwrap());
- f.push(filename);
- if f.is_file() {
- return Some(f);
- }
- }
-
- None
-}
-
-/// Locate a file specified in a `.gnu_debugaltlink` section.
-///
-/// `path` is the file containing the section.
-/// `filename` and `build_id` are the contents of the section.
-///
-/// Search order is based on gdb:
-/// - filename, which is either absolute or relative to `path`
-/// - the build ID path under `BUILD_ID_PATH`
-///
-/// gdb also allows the user to customize the debug search path, but we don't.
-///
-/// gdb also supports debuginfod, but we don't yet.
-fn locate_debugaltlink(path: &Path, filename: &[u8], build_id: &[u8]) -> Option<PathBuf> {
- let filename = Path::new(OsStr::from_bytes(filename));
- if filename.is_absolute() {
- if filename.is_file() {
- return Some(filename.into());
- }
- } else {
- let path = fs::canonicalize(path).ok()?;
- let parent = path.parent()?;
- let mut f = PathBuf::from(parent);
- f.push(filename);
- if f.is_file() {
- return Some(f);
- }
- }
-
- locate_build_id(build_id)
-}
-
-fn convert_path<R: gimli::Reader>(r: &R) -> Result<PathBuf, gimli::Error> {
- let bytes = r.to_slice()?;
- Ok(PathBuf::from(OsStr::from_bytes(&bytes)))
-}
-
-pub(super) fn handle_split_dwarf<'data>(
- package: Option<&gimli::DwarfPackage<EndianSlice<'data, Endian>>>,
- stash: &'data Stash,
- load: addr2line::SplitDwarfLoad<EndianSlice<'data, Endian>>,
-) -> Option<Arc<gimli::Dwarf<EndianSlice<'data, Endian>>>> {
- if let Some(dwp) = package.as_ref() {
- if let Ok(Some(cu)) = dwp.find_cu(load.dwo_id, &load.parent) {
- return Some(Arc::new(cu));
- }
- }
-
- let mut path = PathBuf::new();
- if let Some(p) = load.comp_dir.as_ref() {
- path.push(convert_path(p).ok()?);
- }
-
- path.push(convert_path(load.path.as_ref()?).ok()?);
-
- if let Some(map_dwo) = super::mmap(&path) {
- let map_dwo = stash.cache_mmap(map_dwo);
- if let Some(dwo) = Object::parse(map_dwo) {
- return gimli::Dwarf::load(|id| -> Result<_, ()> {
- let data = id
- .dwo_name()
- .and_then(|name| dwo.section(stash, name))
- .unwrap_or(&[]);
- Ok(EndianSlice::new(data, Endian))
- })
- .ok()
- .map(|mut dwo_dwarf| {
- dwo_dwarf.make_dwo(&load.parent);
- Arc::new(dwo_dwarf)
- });
- }
- }
-
- None
-}
diff --git a/vendor/backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs b/vendor/backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs
deleted file mode 100644
index 9f0304c..0000000
--- a/vendor/backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs
+++ /dev/null
@@ -1,71 +0,0 @@
-// Other Unix (e.g. Linux) platforms use ELF as an object file format
-// and typically implement an API called `dl_iterate_phdr` to load
-// native libraries.
-
-use super::mystd::borrow::ToOwned;
-use super::mystd::env;
-use super::mystd::ffi::{CStr, OsStr};
-use super::mystd::os::unix::prelude::*;
-use super::{Library, LibrarySegment, OsString, Vec};
-use core::slice;
-
-pub(super) fn native_libraries() -> Vec<Library> {
- let mut ret = Vec::new();
- unsafe {
- libc::dl_iterate_phdr(Some(callback), &mut ret as *mut Vec<_> as *mut _);
- }
- return ret;
-}
-
-fn infer_current_exe(base_addr: usize) -> OsString {
- if let Ok(entries) = super::parse_running_mmaps::parse_maps() {
- let opt_path = entries
- .iter()
- .find(|e| e.ip_matches(base_addr) && e.pathname().len() > 0)
- .map(|e| e.pathname())
- .cloned();
- if let Some(path) = opt_path {
- return path;
- }
- }
- env::current_exe().map(|e| e.into()).unwrap_or_default()
-}
-
-// `info` should be a valid pointers.
-// `vec` should be a valid pointer to a `std::Vec`.
-unsafe extern "C" fn callback(
- info: *mut libc::dl_phdr_info,
- _size: libc::size_t,
- vec: *mut libc::c_void,
-) -> libc::c_int {
- let info = &*info;
- let libs = &mut *(vec as *mut Vec<Library>);
- let is_main_prog = info.dlpi_name.is_null() || *info.dlpi_name == 0;
- let name = if is_main_prog {
- // The man page for dl_iterate_phdr says that the first object visited by
- // callback is the main program; so the first time we encounter a
- // nameless entry, we can assume its the main program and try to infer its path.
- // After that, we cannot continue that assumption, and we use an empty string.
- if libs.is_empty() {
- infer_current_exe(info.dlpi_addr as usize)
- } else {
- OsString::new()
- }
- } else {
- let bytes = CStr::from_ptr(info.dlpi_name).to_bytes();
- OsStr::from_bytes(bytes).to_owned()
- };
- let headers = slice::from_raw_parts(info.dlpi_phdr, info.dlpi_phnum as usize);
- libs.push(Library {
- name,
- segments: headers
- .iter()
- .map(|header| LibrarySegment {
- len: (*header).p_memsz as usize,
- stated_virtual_memory_address: (*header).p_vaddr as usize,
- })
- .collect(),
- bias: info.dlpi_addr as usize,
- });
- 0
-}
diff --git a/vendor/backtrace/src/symbolize/gimli/libs_haiku.rs b/vendor/backtrace/src/symbolize/gimli/libs_haiku.rs
deleted file mode 100644
index 87e023e..0000000
--- a/vendor/backtrace/src/symbolize/gimli/libs_haiku.rs
+++ /dev/null
@@ -1,48 +0,0 @@
-// Haiku implements the image_info struct and the get_next_image_info()
-// functions to iterate through the loaded executable images. The
-// image_info struct contains a pointer to the start of the .text
-// section within the virtual address space, as well as the size of
-// that section. All the read-only segments of the ELF-binary are in
-// that part of the address space.
-
-use super::mystd::borrow::ToOwned;
-use super::mystd::ffi::{CStr, OsStr};
-use super::mystd::mem::MaybeUninit;
-use super::mystd::os::unix::prelude::*;
-use super::{Library, LibrarySegment, Vec};
-
-pub(super) fn native_libraries() -> Vec<Library> {
- let mut libraries: Vec<Library> = Vec::new();
-
- unsafe {
- let mut info = MaybeUninit::<libc::image_info>::zeroed();
- let mut cookie: i32 = 0;
- // Load the first image to get a valid info struct
- let mut status =
- libc::get_next_image_info(libc::B_CURRENT_TEAM, &mut cookie, info.as_mut_ptr());
- if status != libc::B_OK {
- return libraries;
- }
- let mut info = info.assume_init();
-
- while status == libc::B_OK {
- let mut segments = Vec::new();
- segments.push(LibrarySegment {
- stated_virtual_memory_address: 0,
- len: info.text_size as usize,
- });
-
- let bytes = CStr::from_ptr(info.name.as_ptr()).to_bytes();
- let name = OsStr::from_bytes(bytes).to_owned();
- libraries.push(Library {
- name: name,
- segments: segments,
- bias: info.text as usize,
- });
-
- status = libc::get_next_image_info(libc::B_CURRENT_TEAM, &mut cookie, &mut info);
- }
- }
-
- libraries
-}
diff --git a/vendor/backtrace/src/symbolize/gimli/libs_illumos.rs b/vendor/backtrace/src/symbolize/gimli/libs_illumos.rs
deleted file mode 100644
index e64975e..0000000
--- a/vendor/backtrace/src/symbolize/gimli/libs_illumos.rs
+++ /dev/null
@@ -1,99 +0,0 @@
-use super::mystd::borrow::ToOwned;
-use super::mystd::ffi::{CStr, OsStr};
-use super::mystd::os::unix::prelude::*;
-use super::{Library, LibrarySegment, Vec};
-use core::mem;
-use object::NativeEndian;
-
-#[cfg(target_pointer_width = "64")]
-use object::elf::{FileHeader64 as FileHeader, ProgramHeader64 as ProgramHeader};
-
-type EHdr = FileHeader<NativeEndian>;
-type PHdr = ProgramHeader<NativeEndian>;
-
-#[repr(C)]
-struct LinkMap {
- l_addr: libc::c_ulong,
- l_name: *const libc::c_char,
- l_ld: *const libc::c_void,
- l_next: *const LinkMap,
- l_prev: *const LinkMap,
- l_refname: *const libc::c_char,
-}
-
-const RTLD_SELF: *const libc::c_void = -3isize as *const libc::c_void;
-const RTLD_DI_LINKMAP: libc::c_int = 2;
-
-extern "C" {
- fn dlinfo(
- handle: *const libc::c_void,
- request: libc::c_int,
- p: *mut libc::c_void,
- ) -> libc::c_int;
-}
-
-pub(super) fn native_libraries() -> Vec<Library> {
- let mut libs = Vec::new();
-
- // Request the current link map from the runtime linker:
- let map = unsafe {
- let mut map: *const LinkMap = mem::zeroed();
- if dlinfo(
- RTLD_SELF,
- RTLD_DI_LINKMAP,
- (&mut map) as *mut *const LinkMap as *mut libc::c_void,
- ) != 0
- {
- return libs;
- }
- map
- };
-
- // Each entry in the link map represents a loaded object:
- let mut l = map;
- while !l.is_null() {
- // Fetch the fully qualified path of the loaded object:
- let bytes = unsafe { CStr::from_ptr((*l).l_name) }.to_bytes();
- let name = OsStr::from_bytes(bytes).to_owned();
-
- // The base address of the object loaded into memory:
- let addr = unsafe { (*l).l_addr };
-
- // Use the ELF header for this object to locate the program
- // header:
- let e: *const EHdr = unsafe { (*l).l_addr as *const EHdr };
- let phoff = unsafe { (*e).e_phoff }.get(NativeEndian);
- let phnum = unsafe { (*e).e_phnum }.get(NativeEndian);
- let etype = unsafe { (*e).e_type }.get(NativeEndian);
-
- let phdr: *const PHdr = (addr + phoff) as *const PHdr;
- let phdr = unsafe { core::slice::from_raw_parts(phdr, phnum as usize) };
-
- libs.push(Library {
- name,
- segments: phdr
- .iter()
- .map(|p| {
- let memsz = p.p_memsz.get(NativeEndian);
- let vaddr = p.p_vaddr.get(NativeEndian);
- LibrarySegment {
- len: memsz as usize,
- stated_virtual_memory_address: vaddr as usize,
- }
- })
- .collect(),
- bias: if etype == object::elf::ET_EXEC {
- // Program header addresses for the base executable are
- // already absolute.
- 0
- } else {
- // Other addresses are relative to the object base.
- addr as usize
- },
- });
-
- l = unsafe { (*l).l_next };
- }
-
- libs
-}
diff --git a/vendor/backtrace/src/symbolize/gimli/libs_libnx.rs b/vendor/backtrace/src/symbolize/gimli/libs_libnx.rs
deleted file mode 100644
index 93b5ba1..0000000
--- a/vendor/backtrace/src/symbolize/gimli/libs_libnx.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-use super::{Library, LibrarySegment, Vec};
-
-// DevkitA64 doesn't natively support debug info, but the build system will
-// place debug info at the path `romfs:/debug_info.elf`.
-pub(super) fn native_libraries() -> Vec<Library> {
- extern "C" {
- static __start__: u8;
- }
-
- let bias = unsafe { &__start__ } as *const u8 as usize;
-
- let mut ret = Vec::new();
- let mut segments = Vec::new();
- segments.push(LibrarySegment {
- stated_virtual_memory_address: 0,
- len: usize::max_value() - bias,
- });
-
- let path = "romfs:/debug_info.elf";
- ret.push(Library {
- name: path.into(),
- segments,
- bias,
- });
-
- ret
-}
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,
- })
-}
diff --git a/vendor/backtrace/src/symbolize/gimli/libs_windows.rs b/vendor/backtrace/src/symbolize/gimli/libs_windows.rs
deleted file mode 100644
index b47ed42..0000000
--- a/vendor/backtrace/src/symbolize/gimli/libs_windows.rs
+++ /dev/null
@@ -1,89 +0,0 @@
-use super::super::super::windows::*;
-use super::mystd::os::windows::prelude::*;
-use super::{coff, mmap, Library, LibrarySegment, OsString};
-use alloc::vec;
-use alloc::vec::Vec;
-use core::mem;
-use core::mem::MaybeUninit;
-
-// For loading native libraries on Windows, see some discussion on
-// rust-lang/rust#71060 for the various strategies here.
-pub(super) fn native_libraries() -> Vec<Library> {
- let mut ret = Vec::new();
- unsafe {
- add_loaded_images(&mut ret);
- }
- return ret;
-}
-
-unsafe fn add_loaded_images(ret: &mut Vec<Library>) {
- let snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0);
- if snap == INVALID_HANDLE_VALUE {
- return;
- }
-
- let mut me = MaybeUninit::<MODULEENTRY32W>::zeroed().assume_init();
- me.dwSize = mem::size_of_val(&me) as DWORD;
- if Module32FirstW(snap, &mut me) == TRUE {
- loop {
- if let Some(lib) = load_library(&me) {
- ret.push(lib);
- }
-
- if Module32NextW(snap, &mut me) != TRUE {
- break;
- }
- }
- }
-
- CloseHandle(snap);
-}
-
-unsafe fn load_library(me: &MODULEENTRY32W) -> Option<Library> {
- let pos = me
- .szExePath
- .iter()
- .position(|i| *i == 0)
- .unwrap_or(me.szExePath.len());
- let name = OsString::from_wide(&me.szExePath[..pos]);
-
- // MinGW libraries currently don't support ASLR
- // (rust-lang/rust#16514), but DLLs can still be relocated around in
- // the address space. It appears that addresses in debug info are
- // all as-if this library was loaded at its "image base", which is a
- // field in its COFF file headers. Since this is what debuginfo
- // seems to list we parse the symbol table and store addresses as if
- // the library was loaded at "image base" as well.
- //
- // The library may not be loaded at "image base", however.
- // (presumably something else may be loaded there?) This is where
- // the `bias` field comes into play, and we need to figure out the
- // value of `bias` here. Unfortunately though it's not clear how to
- // acquire this from a loaded module. What we do have, however, is
- // the actual load address (`modBaseAddr`).
- //
- // As a bit of a cop-out for now we mmap the file, read the file
- // header information, then drop the mmap. This is wasteful because
- // we'll probably reopen the mmap later, but this should work well
- // enough for now.
- //
- // Once we have the `image_base` (desired load location) and the
- // `base_addr` (actual load location) we can fill in the `bias`
- // (difference between the actual and desired) and then the stated
- // address of each segment is the `image_base` since that's what the
- // file says.
- //
- // For now it appears that unlike ELF/MachO we can make do with one
- // segment per library, using `modBaseSize` as the whole size.
- let mmap = mmap(name.as_ref())?;
- let image_base = coff::get_image_base(&mmap)?;
- let base_addr = me.modBaseAddr as usize;
- Some(Library {
- name,
- bias: base_addr.wrapping_sub(image_base),
- segments: vec![LibrarySegment {
- stated_virtual_memory_address: image_base,
- len: me.modBaseSize as usize,
- }],
- })
-}
diff --git a/vendor/backtrace/src/symbolize/gimli/macho.rs b/vendor/backtrace/src/symbolize/gimli/macho.rs
deleted file mode 100644
index 74ed809..0000000
--- a/vendor/backtrace/src/symbolize/gimli/macho.rs
+++ /dev/null
@@ -1,333 +0,0 @@
-use super::{gimli, Box, Context, Endian, EndianSlice, Mapping, Path, Stash, Vec};
-use alloc::sync::Arc;
-use core::convert::TryInto;
-use object::macho;
-use object::read::macho::{MachHeader, Nlist, Section, Segment as _};
-use object::{Bytes, NativeEndian};
-
-#[cfg(target_pointer_width = "32")]
-type Mach = object::macho::MachHeader32<NativeEndian>;
-#[cfg(target_pointer_width = "64")]
-type Mach = object::macho::MachHeader64<NativeEndian>;
-type MachSegment = <Mach as MachHeader>::Segment;
-type MachSection = <Mach as MachHeader>::Section;
-type MachNlist = <Mach as MachHeader>::Nlist;
-
-impl Mapping {
- // The loading path for macOS is so different we just have a completely
- // different implementation of the function here. On macOS we need to go
- // probing the filesystem for a bunch of files.
- pub fn new(path: &Path) -> Option<Mapping> {
- // First up we need to load the unique UUID which is stored in the macho
- // header of the file we're reading, specified at `path`.
- let map = super::mmap(path)?;
- let (macho, data) = find_header(&map)?;
- let endian = macho.endian().ok()?;
- let uuid = macho.uuid(endian, data, 0).ok()?;
-
- // Next we need to look for a `*.dSYM` file. For now we just probe the
- // containing directory and look around for something that matches
- // `*.dSYM`. Once it's found we root through the dwarf resources that it
- // contains and try to find a macho file which has a matching UUID as
- // the one of our own file. If we find a match that's the dwarf file we
- // want to return.
- if let Some(uuid) = uuid {
- if let Some(parent) = path.parent() {
- if let Some(mapping) = Mapping::load_dsym(parent, uuid) {
- return Some(mapping);
- }
- }
- }
-
- // Looks like nothing matched our UUID, so let's at least return our own
- // file. This should have the symbol table for at least some
- // symbolication purposes.
- Mapping::mk(map, |data, stash| {
- let (macho, data) = find_header(data)?;
- let endian = macho.endian().ok()?;
- let obj = Object::parse(macho, endian, data)?;
- Context::new(stash, obj, None, None)
- })
- }
-
- fn load_dsym(dir: &Path, uuid: [u8; 16]) -> Option<Mapping> {
- for entry in dir.read_dir().ok()? {
- let entry = entry.ok()?;
- let filename = match entry.file_name().into_string() {
- Ok(name) => name,
- Err(_) => continue,
- };
- if !filename.ends_with(".dSYM") {
- continue;
- }
- let candidates = entry.path().join("Contents/Resources/DWARF");
- if let Some(mapping) = Mapping::try_dsym_candidate(&candidates, uuid) {
- return Some(mapping);
- }
- }
- None
- }
-
- fn try_dsym_candidate(dir: &Path, uuid: [u8; 16]) -> Option<Mapping> {
- // Look for files in the `DWARF` directory which have a matching uuid to
- // the original object file. If we find one then we found the debug
- // information.
- for entry in dir.read_dir().ok()? {
- let entry = entry.ok()?;
- let map = super::mmap(&entry.path())?;
- let candidate = Mapping::mk(map, |data, stash| {
- let (macho, data) = find_header(data)?;
- let endian = macho.endian().ok()?;
- let entry_uuid = macho.uuid(endian, data, 0).ok()??;
- if entry_uuid != uuid {
- return None;
- }
- let obj = Object::parse(macho, endian, data)?;
- Context::new(stash, obj, None, None)
- });
- if let Some(candidate) = candidate {
- return Some(candidate);
- }
- }
-
- None
- }
-}
-
-fn find_header(data: &'_ [u8]) -> Option<(&'_ Mach, &'_ [u8])> {
- use object::endian::BigEndian;
-
- let desired_cpu = || {
- if cfg!(target_arch = "x86") {
- Some(macho::CPU_TYPE_X86)
- } else if cfg!(target_arch = "x86_64") {
- Some(macho::CPU_TYPE_X86_64)
- } else if cfg!(target_arch = "arm") {
- Some(macho::CPU_TYPE_ARM)
- } else if cfg!(target_arch = "aarch64") {
- Some(macho::CPU_TYPE_ARM64)
- } else {
- None
- }
- };
-
- let mut data = Bytes(data);
- match data
- .clone()
- .read::<object::endian::U32<NativeEndian>>()
- .ok()?
- .get(NativeEndian)
- {
- macho::MH_MAGIC_64 | macho::MH_CIGAM_64 | macho::MH_MAGIC | macho::MH_CIGAM => {}
-
- macho::FAT_MAGIC | macho::FAT_CIGAM => {
- let mut header_data = data;
- let endian = BigEndian;
- let header = header_data.read::<macho::FatHeader>().ok()?;
- let nfat = header.nfat_arch.get(endian);
- let arch = (0..nfat)
- .filter_map(|_| header_data.read::<macho::FatArch32>().ok())
- .find(|arch| desired_cpu() == Some(arch.cputype.get(endian)))?;
- let offset = arch.offset.get(endian);
- let size = arch.size.get(endian);
- data = data
- .read_bytes_at(offset.try_into().ok()?, size.try_into().ok()?)
- .ok()?;
- }
-
- macho::FAT_MAGIC_64 | macho::FAT_CIGAM_64 => {
- let mut header_data = data;
- let endian = BigEndian;
- let header = header_data.read::<macho::FatHeader>().ok()?;
- let nfat = header.nfat_arch.get(endian);
- let arch = (0..nfat)
- .filter_map(|_| header_data.read::<macho::FatArch64>().ok())
- .find(|arch| desired_cpu() == Some(arch.cputype.get(endian)))?;
- let offset = arch.offset.get(endian);
- let size = arch.size.get(endian);
- data = data
- .read_bytes_at(offset.try_into().ok()?, size.try_into().ok()?)
- .ok()?;
- }
-
- _ => return None,
- }
-
- Mach::parse(data.0, 0).ok().map(|h| (h, data.0))
-}
-
-// This is used both for executables/libraries and source object files.
-pub struct Object<'a> {
- endian: NativeEndian,
- data: &'a [u8],
- dwarf: Option<&'a [MachSection]>,
- syms: Vec<(&'a [u8], u64)>,
- syms_sort_by_name: bool,
- // Only set for executables/libraries, and not the source object files.
- object_map: Option<object::ObjectMap<'a>>,
- // The outer Option is for lazy loading, and the inner Option allows load errors to be cached.
- object_mappings: Box<[Option<Option<Mapping>>]>,
-}
-
-impl<'a> Object<'a> {
- fn parse(mach: &'a Mach, endian: NativeEndian, data: &'a [u8]) -> Option<Object<'a>> {
- let is_object = mach.filetype(endian) == object::macho::MH_OBJECT;
- let mut dwarf = None;
- let mut syms = Vec::new();
- let mut syms_sort_by_name = false;
- let mut commands = mach.load_commands(endian, data, 0).ok()?;
- let mut object_map = None;
- let mut object_mappings = Vec::new();
- while let Ok(Some(command)) = commands.next() {
- if let Some((segment, section_data)) = MachSegment::from_command(command).ok()? {
- // Object files should have all sections in a single unnamed segment load command.
- if segment.name() == b"__DWARF" || (is_object && segment.name() == b"") {
- dwarf = segment.sections(endian, section_data).ok();
- }
- } else if let Some(symtab) = command.symtab().ok()? {
- let symbols = symtab.symbols::<Mach, _>(endian, data).ok()?;
- syms = symbols
- .iter()
- .filter_map(|nlist: &MachNlist| {
- let name = nlist.name(endian, symbols.strings()).ok()?;
- if name.len() > 0 && nlist.is_definition() {
- Some((name, u64::from(nlist.n_value(endian))))
- } else {
- None
- }
- })
- .collect();
- if is_object {
- // We never search object file symbols by address.
- // Instead, we already know the symbol name from the executable, and we
- // need to search by name to find the matching symbol in the object file.
- syms.sort_unstable_by_key(|(name, _)| *name);
- syms_sort_by_name = true;
- } else {
- syms.sort_unstable_by_key(|(_, addr)| *addr);
- let map = symbols.object_map(endian);
- object_mappings.resize_with(map.objects().len(), || None);
- object_map = Some(map);
- }
- }
- }
-
- Some(Object {
- endian,
- data,
- dwarf,
- syms,
- syms_sort_by_name,
- object_map,
- object_mappings: object_mappings.into_boxed_slice(),
- })
- }
-
- pub fn section(&self, _: &Stash, name: &str) -> Option<&'a [u8]> {
- let name = name.as_bytes();
- let dwarf = self.dwarf?;
- let section = dwarf.into_iter().find(|section| {
- let section_name = section.name();
- section_name == name || {
- section_name.starts_with(b"__")
- && name.starts_with(b".")
- && &section_name[2..] == &name[1..]
- }
- })?;
- Some(section.data(self.endian, self.data).ok()?)
- }
-
- pub fn search_symtab<'b>(&'b self, addr: u64) -> Option<&'b [u8]> {
- debug_assert!(!self.syms_sort_by_name);
- let i = match self.syms.binary_search_by_key(&addr, |(_, addr)| *addr) {
- Ok(i) => i,
- Err(i) => i.checked_sub(1)?,
- };
- let (sym, _addr) = self.syms.get(i)?;
- Some(sym)
- }
-
- /// Try to load a context for an object file.
- ///
- /// If dsymutil was not run, then the DWARF may be found in the source object files.
- pub(super) fn search_object_map<'b>(&'b mut self, addr: u64) -> Option<(&Context<'b>, u64)> {
- // `object_map` contains a map from addresses to symbols and object paths.
- // Look up the address and get a mapping for the object.
- let object_map = self.object_map.as_ref()?;
- let symbol = object_map.get(addr)?;
- let object_index = symbol.object_index();
- let mapping = self.object_mappings.get_mut(object_index)?;
- if mapping.is_none() {
- // No cached mapping, so create it.
- *mapping = Some(object_mapping(object_map.objects().get(object_index)?));
- }
- let cx: &'b Context<'static> = &mapping.as_ref()?.as_ref()?.cx;
- // Don't leak the `'static` lifetime, make sure it's scoped to just ourselves.
- let cx = unsafe { core::mem::transmute::<&'b Context<'static>, &'b Context<'b>>(cx) };
-
- // We must translate the address in order to be able to look it up
- // in the DWARF in the object file.
- debug_assert!(cx.object.syms.is_empty() || cx.object.syms_sort_by_name);
- let i = cx
- .object
- .syms
- .binary_search_by_key(&symbol.name(), |(name, _)| *name)
- .ok()?;
- let object_symbol = cx.object.syms.get(i)?;
- let object_addr = addr
- .wrapping_sub(symbol.address())
- .wrapping_add(object_symbol.1);
- Some((cx, object_addr))
- }
-}
-
-fn object_mapping(path: &[u8]) -> Option<Mapping> {
- use super::mystd::ffi::OsStr;
- use super::mystd::os::unix::prelude::*;
-
- let map;
-
- // `N_OSO` symbol names can be either `/path/to/object.o` or `/path/to/archive.a(object.o)`.
- let member_name = if let Some((archive_path, member_name)) = split_archive_path(path) {
- map = super::mmap(Path::new(OsStr::from_bytes(archive_path)))?;
- Some(member_name)
- } else {
- map = super::mmap(Path::new(OsStr::from_bytes(path)))?;
- None
- };
- Mapping::mk(map, |data, stash| {
- let data = match member_name {
- Some(member_name) => {
- let archive = object::read::archive::ArchiveFile::parse(data).ok()?;
- let member = archive
- .members()
- .filter_map(Result::ok)
- .find(|m| m.name() == member_name)?;
- member.data(data).ok()?
- }
- None => data,
- };
- let (macho, data) = find_header(data)?;
- let endian = macho.endian().ok()?;
- let obj = Object::parse(macho, endian, data)?;
- Context::new(stash, obj, None, None)
- })
-}
-
-fn split_archive_path(path: &[u8]) -> Option<(&[u8], &[u8])> {
- let (last, path) = path.split_last()?;
- if *last != b')' {
- return None;
- }
- let index = path.iter().position(|&x| x == b'(')?;
- let (archive, rest) = path.split_at(index);
- Some((archive, &rest[1..]))
-}
-
-pub(super) fn handle_split_dwarf<'data>(
- _package: Option<&gimli::DwarfPackage<EndianSlice<'data, Endian>>>,
- _stash: &'data Stash,
- _load: addr2line::SplitDwarfLoad<EndianSlice<'data, Endian>>,
-) -> Option<Arc<gimli::Dwarf<EndianSlice<'data, Endian>>>> {
- None
-}
diff --git a/vendor/backtrace/src/symbolize/gimli/mmap_fake.rs b/vendor/backtrace/src/symbolize/gimli/mmap_fake.rs
deleted file mode 100644
index ce50964..0000000
--- a/vendor/backtrace/src/symbolize/gimli/mmap_fake.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-use super::{mystd::io::Read, File};
-use alloc::vec::Vec;
-use core::ops::Deref;
-
-pub struct Mmap {
- vec: Vec<u8>,
-}
-
-impl Mmap {
- pub unsafe fn map(mut file: &File, len: usize) -> Option<Mmap> {
- let mut mmap = Mmap {
- vec: Vec::with_capacity(len),
- };
- file.read_to_end(&mut mmap.vec).ok()?;
- Some(mmap)
- }
-}
-
-impl Deref for Mmap {
- type Target = [u8];
-
- fn deref(&self) -> &[u8] {
- &self.vec[..]
- }
-}
diff --git a/vendor/backtrace/src/symbolize/gimli/mmap_unix.rs b/vendor/backtrace/src/symbolize/gimli/mmap_unix.rs
deleted file mode 100644
index 261ffc1..0000000
--- a/vendor/backtrace/src/symbolize/gimli/mmap_unix.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-use super::mystd::fs::File;
-use super::mystd::os::unix::prelude::*;
-use core::ops::Deref;
-use core::ptr;
-use core::slice;
-
-#[cfg(not(all(target_os = "linux", target_env = "gnu")))]
-use libc::mmap as mmap64;
-#[cfg(all(target_os = "linux", target_env = "gnu"))]
-use libc::mmap64;
-
-pub struct Mmap {
- ptr: *mut libc::c_void,
- len: usize,
-}
-
-impl Mmap {
- pub unsafe fn map(file: &File, len: usize) -> Option<Mmap> {
- let ptr = mmap64(
- ptr::null_mut(),
- len,
- libc::PROT_READ,
- libc::MAP_PRIVATE,
- file.as_raw_fd(),
- 0,
- );
- if ptr == libc::MAP_FAILED {
- return None;
- }
- Some(Mmap { ptr, len })
- }
-}
-
-impl Deref for Mmap {
- type Target = [u8];
-
- fn deref(&self) -> &[u8] {
- unsafe { slice::from_raw_parts(self.ptr as *const u8, self.len) }
- }
-}
-
-impl Drop for Mmap {
- fn drop(&mut self) {
- unsafe {
- let r = libc::munmap(self.ptr, self.len);
- debug_assert_eq!(r, 0);
- }
- }
-}
diff --git a/vendor/backtrace/src/symbolize/gimli/mmap_windows.rs b/vendor/backtrace/src/symbolize/gimli/mmap_windows.rs
deleted file mode 100644
index b39509d..0000000
--- a/vendor/backtrace/src/symbolize/gimli/mmap_windows.rs
+++ /dev/null
@@ -1,57 +0,0 @@
-use super::super::super::windows::*;
-use super::mystd::fs::File;
-use super::mystd::os::windows::prelude::*;
-use core::ops::Deref;
-use core::ptr;
-use core::slice;
-
-pub struct Mmap {
- // keep the file alive to prevent it from being deleted which would cause
- // us to read bad data.
- _file: File,
- ptr: *mut c_void,
- len: usize,
-}
-
-impl Mmap {
- pub unsafe fn map(file: &File, len: usize) -> Option<Mmap> {
- let file = file.try_clone().ok()?;
- let mapping = CreateFileMappingA(
- file.as_raw_handle() as *mut _,
- ptr::null_mut(),
- PAGE_READONLY,
- 0,
- 0,
- ptr::null(),
- );
- if mapping.is_null() {
- return None;
- }
- let ptr = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, len);
- CloseHandle(mapping);
- if ptr.is_null() {
- return None;
- }
- Some(Mmap {
- _file: file,
- ptr,
- len,
- })
- }
-}
-impl Deref for Mmap {
- type Target = [u8];
-
- fn deref(&self) -> &[u8] {
- unsafe { slice::from_raw_parts(self.ptr as *const u8, self.len) }
- }
-}
-
-impl Drop for Mmap {
- fn drop(&mut self) {
- unsafe {
- let r = UnmapViewOfFile(self.ptr);
- debug_assert!(r != 0);
- }
- }
-}
diff --git a/vendor/backtrace/src/symbolize/gimli/parse_running_mmaps_unix.rs b/vendor/backtrace/src/symbolize/gimli/parse_running_mmaps_unix.rs
deleted file mode 100644
index 5d4b346..0000000
--- a/vendor/backtrace/src/symbolize/gimli/parse_running_mmaps_unix.rs
+++ /dev/null
@@ -1,295 +0,0 @@
-// Note: This file is only currently used on targets that call out to the code
-// in `mod libs_dl_iterate_phdr` (e.g. linux, freebsd, ...); it may be more
-// general purpose, but it hasn't been tested elsewhere.
-
-use super::mystd::fs::File;
-use super::mystd::io::Read;
-use super::mystd::str::FromStr;
-use super::{OsString, String, Vec};
-
-#[derive(PartialEq, Eq, Debug)]
-pub(super) struct MapsEntry {
- /// start (inclusive) and limit (exclusive) of address range.
- address: (usize, usize),
- /// The perms field are the permissions for the entry
- ///
- /// r = read
- /// w = write
- /// x = execute
- /// s = shared
- /// p = private (copy on write)
- perms: [char; 4],
- /// Offset into the file (or "whatever").
- offset: usize,
- /// device (major, minor)
- dev: (usize, usize),
- /// inode on the device. 0 indicates that no inode is associated with the memory region (e.g. uninitalized data aka BSS).
- inode: usize,
- /// Usually the file backing the mapping.
- ///
- /// Note: The man page for proc includes a note about "coordination" by
- /// using readelf to see the Offset field in ELF program headers. pnkfelix
- /// is not yet sure if that is intended to be a comment on pathname, or what
- /// form/purpose such coordination is meant to have.
- ///
- /// There are also some pseudo-paths:
- /// "[stack]": The initial process's (aka main thread's) stack.
- /// "[stack:<tid>]": a specific thread's stack. (This was only present for a limited range of Linux verisons; it was determined to be too expensive to provide.)
- /// "[vdso]": Virtual dynamically linked shared object
- /// "[heap]": The process's heap
- ///
- /// The pathname can be blank, which means it is an anonymous mapping
- /// obtained via mmap.
- ///
- /// Newlines in pathname are replaced with an octal escape sequence.
- ///
- /// The pathname may have "(deleted)" appended onto it if the file-backed
- /// path has been deleted.
- ///
- /// Note that modifications like the latter two indicated above imply that
- /// in general the pathname may be ambiguous. (I.e. you cannot tell if the
- /// denoted filename actually ended with the text "(deleted)", or if that
- /// was added by the maps rendering.
- pathname: OsString,
-}
-
-pub(super) fn parse_maps() -> Result<Vec<MapsEntry>, &'static str> {
- let mut v = Vec::new();
- let mut proc_self_maps =
- File::open("/proc/self/maps").map_err(|_| "Couldn't open /proc/self/maps")?;
- let mut buf = String::new();
- let _bytes_read = proc_self_maps
- .read_to_string(&mut buf)
- .map_err(|_| "Couldn't read /proc/self/maps")?;
- for line in buf.lines() {
- v.push(line.parse()?);
- }
-
- Ok(v)
-}
-
-impl MapsEntry {
- pub(super) fn pathname(&self) -> &OsString {
- &self.pathname
- }
-
- pub(super) fn ip_matches(&self, ip: usize) -> bool {
- self.address.0 <= ip && ip < self.address.1
- }
-}
-
-impl FromStr for MapsEntry {
- type Err = &'static str;
-
- // Format: address perms offset dev inode pathname
- // e.g.: "ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]"
- // e.g.: "7f5985f46000-7f5985f48000 rw-p 00039000 103:06 76021795 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2"
- // e.g.: "35b1a21000-35b1a22000 rw-p 00000000 00:00 0"
- //
- // Note that paths may contain spaces, so we can't use `str::split` for parsing (until
- // Split::remainder is stabilized #77998).
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- let (range_str, s) = s.trim_start().split_once(' ').unwrap_or((s, ""));
- if range_str.is_empty() {
- return Err("Couldn't find address");
- }
-
- let (perms_str, s) = s.trim_start().split_once(' ').unwrap_or((s, ""));
- if perms_str.is_empty() {
- return Err("Couldn't find permissions");
- }
-
- let (offset_str, s) = s.trim_start().split_once(' ').unwrap_or((s, ""));
- if offset_str.is_empty() {
- return Err("Couldn't find offset");
- }
-
- let (dev_str, s) = s.trim_start().split_once(' ').unwrap_or((s, ""));
- if dev_str.is_empty() {
- return Err("Couldn't find dev");
- }
-
- let (inode_str, s) = s.trim_start().split_once(' ').unwrap_or((s, ""));
- if inode_str.is_empty() {
- return Err("Couldn't find inode");
- }
-
- // Pathname may be omitted in which case it will be empty
- let pathname_str = s.trim_start();
-
- let hex = |s| usize::from_str_radix(s, 16).map_err(|_| "Couldn't parse hex number");
- let address = if let Some((start, limit)) = range_str.split_once('-') {
- (hex(start)?, hex(limit)?)
- } else {
- return Err("Couldn't parse address range");
- };
- let perms: [char; 4] = {
- let mut chars = perms_str.chars();
- let mut c = || chars.next().ok_or("insufficient perms");
- let perms = [c()?, c()?, c()?, c()?];
- if chars.next().is_some() {
- return Err("too many perms");
- }
- perms
- };
- let offset = hex(offset_str)?;
- let dev = if let Some((major, minor)) = dev_str.split_once(':') {
- (hex(major)?, hex(minor)?)
- } else {
- return Err("Couldn't parse dev");
- };
- let inode = hex(inode_str)?;
- let pathname = pathname_str.into();
-
- Ok(MapsEntry {
- address,
- perms,
- offset,
- dev,
- inode,
- pathname,
- })
- }
-}
-
-// Make sure we can parse 64-bit sample output if we're on a 64-bit target.
-#[cfg(target_pointer_width = "64")]
-#[test]
-fn check_maps_entry_parsing_64bit() {
- assert_eq!(
- "ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 \
- [vsyscall]"
- .parse::<MapsEntry>()
- .unwrap(),
- MapsEntry {
- address: (0xffffffffff600000, 0xffffffffff601000),
- perms: ['-', '-', 'x', 'p'],
- offset: 0x00000000,
- dev: (0x00, 0x00),
- inode: 0x0,
- pathname: "[vsyscall]".into(),
- }
- );
-
- assert_eq!(
- "7f5985f46000-7f5985f48000 rw-p 00039000 103:06 76021795 \
- /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2"
- .parse::<MapsEntry>()
- .unwrap(),
- MapsEntry {
- address: (0x7f5985f46000, 0x7f5985f48000),
- perms: ['r', 'w', '-', 'p'],
- offset: 0x00039000,
- dev: (0x103, 0x06),
- inode: 0x76021795,
- pathname: "/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2".into(),
- }
- );
- assert_eq!(
- "35b1a21000-35b1a22000 rw-p 00000000 00:00 0"
- .parse::<MapsEntry>()
- .unwrap(),
- MapsEntry {
- address: (0x35b1a21000, 0x35b1a22000),
- perms: ['r', 'w', '-', 'p'],
- offset: 0x00000000,
- dev: (0x00, 0x00),
- inode: 0x0,
- pathname: Default::default(),
- }
- );
-}
-
-// (This output was taken from a 32-bit machine, but will work on any target)
-#[test]
-fn check_maps_entry_parsing_32bit() {
- /* Example snippet of output:
- 08056000-08077000 rw-p 00000000 00:00 0 [heap]
- b7c79000-b7e02000 r--p 00000000 08:01 60662705 /usr/lib/locale/locale-archive
- b7e02000-b7e03000 rw-p 00000000 00:00 0
- */
- assert_eq!(
- "08056000-08077000 rw-p 00000000 00:00 0 \
- [heap]"
- .parse::<MapsEntry>()
- .unwrap(),
- MapsEntry {
- address: (0x08056000, 0x08077000),
- perms: ['r', 'w', '-', 'p'],
- offset: 0x00000000,
- dev: (0x00, 0x00),
- inode: 0x0,
- pathname: "[heap]".into(),
- }
- );
-
- assert_eq!(
- "b7c79000-b7e02000 r--p 00000000 08:01 60662705 \
- /usr/lib/locale/locale-archive"
- .parse::<MapsEntry>()
- .unwrap(),
- MapsEntry {
- address: (0xb7c79000, 0xb7e02000),
- perms: ['r', '-', '-', 'p'],
- offset: 0x00000000,
- dev: (0x08, 0x01),
- inode: 0x60662705,
- pathname: "/usr/lib/locale/locale-archive".into(),
- }
- );
- assert_eq!(
- "b7e02000-b7e03000 rw-p 00000000 00:00 0"
- .parse::<MapsEntry>()
- .unwrap(),
- MapsEntry {
- address: (0xb7e02000, 0xb7e03000),
- perms: ['r', 'w', '-', 'p'],
- offset: 0x00000000,
- dev: (0x00, 0x00),
- inode: 0x0,
- pathname: Default::default(),
- }
- );
- assert_eq!(
- "b7c79000-b7e02000 r--p 00000000 08:01 60662705 \
- /executable/path/with some spaces"
- .parse::<MapsEntry>()
- .unwrap(),
- MapsEntry {
- address: (0xb7c79000, 0xb7e02000),
- perms: ['r', '-', '-', 'p'],
- offset: 0x00000000,
- dev: (0x08, 0x01),
- inode: 0x60662705,
- pathname: "/executable/path/with some spaces".into(),
- }
- );
- assert_eq!(
- "b7c79000-b7e02000 r--p 00000000 08:01 60662705 \
- /executable/path/with multiple-continuous spaces "
- .parse::<MapsEntry>()
- .unwrap(),
- MapsEntry {
- address: (0xb7c79000, 0xb7e02000),
- perms: ['r', '-', '-', 'p'],
- offset: 0x00000000,
- dev: (0x08, 0x01),
- inode: 0x60662705,
- pathname: "/executable/path/with multiple-continuous spaces ".into(),
- }
- );
- assert_eq!(
- " b7c79000-b7e02000 r--p 00000000 08:01 60662705 \
- /executable/path/starts-with-spaces"
- .parse::<MapsEntry>()
- .unwrap(),
- MapsEntry {
- address: (0xb7c79000, 0xb7e02000),
- perms: ['r', '-', '-', 'p'],
- offset: 0x00000000,
- dev: (0x08, 0x01),
- inode: 0x60662705,
- pathname: "/executable/path/starts-with-spaces".into(),
- }
- );
-}
diff --git a/vendor/backtrace/src/symbolize/gimli/stash.rs b/vendor/backtrace/src/symbolize/gimli/stash.rs
deleted file mode 100644
index 792f9a6..0000000
--- a/vendor/backtrace/src/symbolize/gimli/stash.rs
+++ /dev/null
@@ -1,50 +0,0 @@
-// only used on Linux right now, so allow dead code elsewhere
-#![cfg_attr(not(target_os = "linux"), allow(dead_code))]
-
-use super::Mmap;
-use alloc::vec;
-use alloc::vec::Vec;
-use core::cell::UnsafeCell;
-
-/// A simple arena allocator for byte buffers.
-pub struct Stash {
- buffers: UnsafeCell<Vec<Vec<u8>>>,
- mmaps: UnsafeCell<Vec<Mmap>>,
-}
-
-impl Stash {
- pub fn new() -> Stash {
- Stash {
- buffers: UnsafeCell::new(Vec::new()),
- mmaps: UnsafeCell::new(Vec::new()),
- }
- }
-
- /// Allocates a buffer of the specified size and returns a mutable reference
- /// to it.
- pub fn allocate(&self, size: usize) -> &mut [u8] {
- // SAFETY: this is the only function that ever constructs a mutable
- // reference to `self.buffers`.
- let buffers = unsafe { &mut *self.buffers.get() };
- let i = buffers.len();
- buffers.push(vec![0; size]);
- // SAFETY: we never remove elements from `self.buffers`, so a reference
- // to the data inside any buffer will live as long as `self` does.
- &mut buffers[i]
- }
-
- /// Stores a `Mmap` for the lifetime of this `Stash`, returning a pointer
- /// which is scoped to just this lifetime.
- pub fn cache_mmap(&self, map: Mmap) -> &[u8] {
- // SAFETY: this is the only location for a mutable pointer to
- // `mmaps`, and this structure isn't threadsafe to shared across
- // threads either. We also never remove elements from `self.mmaps`,
- // so a reference to the data inside the map will live as long as
- // `self` does.
- unsafe {
- let mmaps = &mut *self.mmaps.get();
- mmaps.push(map);
- mmaps.last().unwrap()
- }
- }
-}