aboutsummaryrefslogtreecommitdiff
path: root/vendor/object/src/write/mod.rs
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/object/src/write/mod.rs
parent3d48cd3f81164bbfc1a755dc1d4a9a02f98c8ddd (diff)
downloadfparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.tar.xz
fparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.zip
Deleted vendor folder
Diffstat (limited to 'vendor/object/src/write/mod.rs')
-rw-r--r--vendor/object/src/write/mod.rs961
1 files changed, 0 insertions, 961 deletions
diff --git a/vendor/object/src/write/mod.rs b/vendor/object/src/write/mod.rs
deleted file mode 100644
index cea4d2e..0000000
--- a/vendor/object/src/write/mod.rs
+++ /dev/null
@@ -1,961 +0,0 @@
-//! Interface for writing object files.
-
-use alloc::borrow::Cow;
-use alloc::string::String;
-use alloc::vec::Vec;
-use core::{fmt, result, str};
-#[cfg(not(feature = "std"))]
-use hashbrown::HashMap;
-#[cfg(feature = "std")]
-use std::{boxed::Box, collections::HashMap, error, io};
-
-use crate::endian::{Endianness, U32, U64};
-use crate::{
- Architecture, BinaryFormat, ComdatKind, FileFlags, RelocationEncoding, RelocationKind,
- SectionFlags, SectionKind, SubArchitecture, SymbolFlags, SymbolKind, SymbolScope,
-};
-
-#[cfg(feature = "coff")]
-pub mod coff;
-#[cfg(feature = "coff")]
-pub use coff::CoffExportStyle;
-
-#[cfg(feature = "elf")]
-pub mod elf;
-
-#[cfg(feature = "macho")]
-mod macho;
-#[cfg(feature = "macho")]
-pub use macho::MachOBuildVersion;
-
-#[cfg(feature = "pe")]
-pub mod pe;
-
-#[cfg(feature = "xcoff")]
-mod xcoff;
-
-mod string;
-pub use string::StringId;
-
-mod util;
-pub use util::*;
-
-/// The error type used within the write module.
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct Error(String);
-
-impl fmt::Display for Error {
- #[inline]
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str(&self.0)
- }
-}
-
-#[cfg(feature = "std")]
-impl error::Error for Error {}
-
-/// The result type used within the write module.
-pub type Result<T> = result::Result<T, Error>;
-
-/// A writable relocatable object file.
-#[derive(Debug)]
-pub struct Object<'a> {
- format: BinaryFormat,
- architecture: Architecture,
- sub_architecture: Option<SubArchitecture>,
- endian: Endianness,
- sections: Vec<Section<'a>>,
- standard_sections: HashMap<StandardSection, SectionId>,
- symbols: Vec<Symbol>,
- symbol_map: HashMap<Vec<u8>, SymbolId>,
- stub_symbols: HashMap<SymbolId, SymbolId>,
- comdats: Vec<Comdat>,
- /// File flags that are specific to each file format.
- pub flags: FileFlags,
- /// The symbol name mangling scheme.
- pub mangling: Mangling,
- /// Mach-O "_tlv_bootstrap" symbol.
- tlv_bootstrap: Option<SymbolId>,
- /// Mach-O CPU subtype.
- #[cfg(feature = "macho")]
- macho_cpu_subtype: Option<u32>,
- #[cfg(feature = "macho")]
- macho_build_version: Option<MachOBuildVersion>,
-}
-
-impl<'a> Object<'a> {
- /// Create an empty object file.
- pub fn new(format: BinaryFormat, architecture: Architecture, endian: Endianness) -> Object<'a> {
- Object {
- format,
- architecture,
- sub_architecture: None,
- endian,
- sections: Vec::new(),
- standard_sections: HashMap::new(),
- symbols: Vec::new(),
- symbol_map: HashMap::new(),
- stub_symbols: HashMap::new(),
- comdats: Vec::new(),
- flags: FileFlags::None,
- mangling: Mangling::default(format, architecture),
- tlv_bootstrap: None,
- #[cfg(feature = "macho")]
- macho_cpu_subtype: None,
- #[cfg(feature = "macho")]
- macho_build_version: None,
- }
- }
-
- /// Return the file format.
- #[inline]
- pub fn format(&self) -> BinaryFormat {
- self.format
- }
-
- /// Return the architecture.
- #[inline]
- pub fn architecture(&self) -> Architecture {
- self.architecture
- }
-
- /// Return the sub-architecture.
- #[inline]
- pub fn sub_architecture(&self) -> Option<SubArchitecture> {
- self.sub_architecture
- }
-
- /// Specify the sub-architecture.
- pub fn set_sub_architecture(&mut self, sub_architecture: Option<SubArchitecture>) {
- self.sub_architecture = sub_architecture;
- }
-
- /// Return the current mangling setting.
- #[inline]
- pub fn mangling(&self) -> Mangling {
- self.mangling
- }
-
- /// Specify the mangling setting.
- #[inline]
- pub fn set_mangling(&mut self, mangling: Mangling) {
- self.mangling = mangling;
- }
-
- /// Return the name for a standard segment.
- ///
- /// This will vary based on the file format.
- #[allow(unused_variables)]
- pub fn segment_name(&self, segment: StandardSegment) -> &'static [u8] {
- match self.format {
- #[cfg(feature = "coff")]
- BinaryFormat::Coff => &[],
- #[cfg(feature = "elf")]
- BinaryFormat::Elf => &[],
- #[cfg(feature = "macho")]
- BinaryFormat::MachO => self.macho_segment_name(segment),
- _ => unimplemented!(),
- }
- }
-
- /// Get the section with the given `SectionId`.
- #[inline]
- pub fn section(&self, section: SectionId) -> &Section<'a> {
- &self.sections[section.0]
- }
-
- /// Mutably get the section with the given `SectionId`.
- #[inline]
- pub fn section_mut(&mut self, section: SectionId) -> &mut Section<'a> {
- &mut self.sections[section.0]
- }
-
- /// Set the data for an existing section.
- ///
- /// Must not be called for sections that already have data, or that contain uninitialized data.
- pub fn set_section_data<T>(&mut self, section: SectionId, data: T, align: u64)
- where
- T: Into<Cow<'a, [u8]>>,
- {
- self.sections[section.0].set_data(data, align)
- }
-
- /// Append data to an existing section. Returns the section offset of the data.
- pub fn append_section_data(&mut self, section: SectionId, data: &[u8], align: u64) -> u64 {
- self.sections[section.0].append_data(data, align)
- }
-
- /// Append zero-initialized data to an existing section. Returns the section offset of the data.
- pub fn append_section_bss(&mut self, section: SectionId, size: u64, align: u64) -> u64 {
- self.sections[section.0].append_bss(size, align)
- }
-
- /// Return the `SectionId` of a standard section.
- ///
- /// If the section doesn't already exist then it is created.
- pub fn section_id(&mut self, section: StandardSection) -> SectionId {
- self.standard_sections
- .get(&section)
- .cloned()
- .unwrap_or_else(|| {
- let (segment, name, kind, flags) = self.section_info(section);
- let id = self.add_section(segment.to_vec(), name.to_vec(), kind);
- self.section_mut(id).flags = flags;
- id
- })
- }
-
- /// Add a new section and return its `SectionId`.
- ///
- /// This also creates a section symbol.
- pub fn add_section(&mut self, segment: Vec<u8>, name: Vec<u8>, kind: SectionKind) -> SectionId {
- let id = SectionId(self.sections.len());
- self.sections.push(Section {
- segment,
- name,
- kind,
- size: 0,
- align: 1,
- data: Cow::Borrowed(&[]),
- relocations: Vec::new(),
- symbol: None,
- flags: SectionFlags::None,
- });
-
- // Add to self.standard_sections if required. This may match multiple standard sections.
- let section = &self.sections[id.0];
- for standard_section in StandardSection::all() {
- if !self.standard_sections.contains_key(standard_section) {
- let (segment, name, kind, _flags) = self.section_info(*standard_section);
- if segment == &*section.segment && name == &*section.name && kind == section.kind {
- self.standard_sections.insert(*standard_section, id);
- }
- }
- }
-
- id
- }
-
- fn section_info(
- &self,
- section: StandardSection,
- ) -> (&'static [u8], &'static [u8], SectionKind, SectionFlags) {
- match self.format {
- #[cfg(feature = "coff")]
- BinaryFormat::Coff => self.coff_section_info(section),
- #[cfg(feature = "elf")]
- BinaryFormat::Elf => self.elf_section_info(section),
- #[cfg(feature = "macho")]
- BinaryFormat::MachO => self.macho_section_info(section),
- #[cfg(feature = "xcoff")]
- BinaryFormat::Xcoff => self.xcoff_section_info(section),
- _ => unimplemented!(),
- }
- }
-
- /// Add a subsection. Returns the `SectionId` and section offset of the data.
- pub fn add_subsection(
- &mut self,
- section: StandardSection,
- name: &[u8],
- data: &[u8],
- align: u64,
- ) -> (SectionId, u64) {
- let section_id = if self.has_subsections_via_symbols() {
- self.set_subsections_via_symbols();
- self.section_id(section)
- } else {
- let (segment, name, kind, flags) = self.subsection_info(section, name);
- let id = self.add_section(segment.to_vec(), name, kind);
- self.section_mut(id).flags = flags;
- id
- };
- let offset = self.append_section_data(section_id, data, align);
- (section_id, offset)
- }
-
- fn has_subsections_via_symbols(&self) -> bool {
- match self.format {
- BinaryFormat::Coff | BinaryFormat::Elf | BinaryFormat::Xcoff => false,
- BinaryFormat::MachO => true,
- _ => unimplemented!(),
- }
- }
-
- fn set_subsections_via_symbols(&mut self) {
- match self.format {
- #[cfg(feature = "macho")]
- BinaryFormat::MachO => self.macho_set_subsections_via_symbols(),
- _ => unimplemented!(),
- }
- }
-
- fn subsection_info(
- &self,
- section: StandardSection,
- value: &[u8],
- ) -> (&'static [u8], Vec<u8>, SectionKind, SectionFlags) {
- let (segment, section, kind, flags) = self.section_info(section);
- let name = self.subsection_name(section, value);
- (segment, name, kind, flags)
- }
-
- #[allow(unused_variables)]
- fn subsection_name(&self, section: &[u8], value: &[u8]) -> Vec<u8> {
- debug_assert!(!self.has_subsections_via_symbols());
- match self.format {
- #[cfg(feature = "coff")]
- BinaryFormat::Coff => self.coff_subsection_name(section, value),
- #[cfg(feature = "elf")]
- BinaryFormat::Elf => self.elf_subsection_name(section, value),
- _ => unimplemented!(),
- }
- }
-
- /// Get the COMDAT section group with the given `ComdatId`.
- #[inline]
- pub fn comdat(&self, comdat: ComdatId) -> &Comdat {
- &self.comdats[comdat.0]
- }
-
- /// Mutably get the COMDAT section group with the given `ComdatId`.
- #[inline]
- pub fn comdat_mut(&mut self, comdat: ComdatId) -> &mut Comdat {
- &mut self.comdats[comdat.0]
- }
-
- /// Add a new COMDAT section group and return its `ComdatId`.
- pub fn add_comdat(&mut self, comdat: Comdat) -> ComdatId {
- let comdat_id = ComdatId(self.comdats.len());
- self.comdats.push(comdat);
- comdat_id
- }
-
- /// Get the `SymbolId` of the symbol with the given name.
- pub fn symbol_id(&self, name: &[u8]) -> Option<SymbolId> {
- self.symbol_map.get(name).cloned()
- }
-
- /// Get the symbol with the given `SymbolId`.
- #[inline]
- pub fn symbol(&self, symbol: SymbolId) -> &Symbol {
- &self.symbols[symbol.0]
- }
-
- /// Mutably get the symbol with the given `SymbolId`.
- #[inline]
- pub fn symbol_mut(&mut self, symbol: SymbolId) -> &mut Symbol {
- &mut self.symbols[symbol.0]
- }
-
- /// Add a new symbol and return its `SymbolId`.
- pub fn add_symbol(&mut self, mut symbol: Symbol) -> SymbolId {
- // Defined symbols must have a scope.
- debug_assert!(symbol.is_undefined() || symbol.scope != SymbolScope::Unknown);
- if symbol.kind == SymbolKind::Section {
- // There can only be one section symbol, but update its flags, since
- // the automatically generated section symbol will have none.
- let symbol_id = self.section_symbol(symbol.section.id().unwrap());
- if symbol.flags != SymbolFlags::None {
- self.symbol_mut(symbol_id).flags = symbol.flags;
- }
- return symbol_id;
- }
- if !symbol.name.is_empty()
- && (symbol.kind == SymbolKind::Text
- || symbol.kind == SymbolKind::Data
- || symbol.kind == SymbolKind::Tls)
- {
- let unmangled_name = symbol.name.clone();
- if let Some(prefix) = self.mangling.global_prefix() {
- symbol.name.insert(0, prefix);
- }
- let symbol_id = self.add_raw_symbol(symbol);
- self.symbol_map.insert(unmangled_name, symbol_id);
- symbol_id
- } else {
- self.add_raw_symbol(symbol)
- }
- }
-
- fn add_raw_symbol(&mut self, symbol: Symbol) -> SymbolId {
- let symbol_id = SymbolId(self.symbols.len());
- self.symbols.push(symbol);
- symbol_id
- }
-
- /// Return true if the file format supports `StandardSection::UninitializedTls`.
- #[inline]
- pub fn has_uninitialized_tls(&self) -> bool {
- self.format != BinaryFormat::Coff
- }
-
- /// Return true if the file format supports `StandardSection::Common`.
- #[inline]
- pub fn has_common(&self) -> bool {
- self.format == BinaryFormat::MachO
- }
-
- /// Add a new common symbol and return its `SymbolId`.
- ///
- /// For Mach-O, this appends the symbol to the `__common` section.
- pub fn add_common_symbol(&mut self, mut symbol: Symbol, size: u64, align: u64) -> SymbolId {
- if self.has_common() {
- let symbol_id = self.add_symbol(symbol);
- let section = self.section_id(StandardSection::Common);
- self.add_symbol_bss(symbol_id, section, size, align);
- symbol_id
- } else {
- symbol.section = SymbolSection::Common;
- symbol.size = size;
- self.add_symbol(symbol)
- }
- }
-
- /// Add a new file symbol and return its `SymbolId`.
- pub fn add_file_symbol(&mut self, name: Vec<u8>) -> SymbolId {
- self.add_raw_symbol(Symbol {
- name,
- value: 0,
- size: 0,
- kind: SymbolKind::File,
- scope: SymbolScope::Compilation,
- weak: false,
- section: SymbolSection::None,
- flags: SymbolFlags::None,
- })
- }
-
- /// Get the symbol for a section.
- pub fn section_symbol(&mut self, section_id: SectionId) -> SymbolId {
- let section = &mut self.sections[section_id.0];
- if let Some(symbol) = section.symbol {
- return symbol;
- }
- let name = if self.format == BinaryFormat::Coff {
- section.name.clone()
- } else {
- Vec::new()
- };
- let symbol_id = SymbolId(self.symbols.len());
- self.symbols.push(Symbol {
- name,
- value: 0,
- size: 0,
- kind: SymbolKind::Section,
- scope: SymbolScope::Compilation,
- weak: false,
- section: SymbolSection::Section(section_id),
- flags: SymbolFlags::None,
- });
- section.symbol = Some(symbol_id);
- symbol_id
- }
-
- /// Append data to an existing section, and update a symbol to refer to it.
- ///
- /// For Mach-O, this also creates a `__thread_vars` entry for TLS symbols, and the
- /// symbol will indirectly point to the added data via the `__thread_vars` entry.
- ///
- /// Returns the section offset of the data.
- pub fn add_symbol_data(
- &mut self,
- symbol_id: SymbolId,
- section: SectionId,
- data: &[u8],
- align: u64,
- ) -> u64 {
- let offset = self.append_section_data(section, data, align);
- self.set_symbol_data(symbol_id, section, offset, data.len() as u64);
- offset
- }
-
- /// Append zero-initialized data to an existing section, and update a symbol to refer to it.
- ///
- /// For Mach-O, this also creates a `__thread_vars` entry for TLS symbols, and the
- /// symbol will indirectly point to the added data via the `__thread_vars` entry.
- ///
- /// Returns the section offset of the data.
- pub fn add_symbol_bss(
- &mut self,
- symbol_id: SymbolId,
- section: SectionId,
- size: u64,
- align: u64,
- ) -> u64 {
- let offset = self.append_section_bss(section, size, align);
- self.set_symbol_data(symbol_id, section, offset, size);
- offset
- }
-
- /// Update a symbol to refer to the given data within a section.
- ///
- /// For Mach-O, this also creates a `__thread_vars` entry for TLS symbols, and the
- /// symbol will indirectly point to the data via the `__thread_vars` entry.
- #[allow(unused_mut)]
- pub fn set_symbol_data(
- &mut self,
- mut symbol_id: SymbolId,
- section: SectionId,
- offset: u64,
- size: u64,
- ) {
- // Defined symbols must have a scope.
- debug_assert!(self.symbol(symbol_id).scope != SymbolScope::Unknown);
- match self.format {
- #[cfg(feature = "macho")]
- BinaryFormat::MachO => symbol_id = self.macho_add_thread_var(symbol_id),
- _ => {}
- }
- let symbol = self.symbol_mut(symbol_id);
- symbol.value = offset;
- symbol.size = size;
- symbol.section = SymbolSection::Section(section);
- }
-
- /// Convert a symbol to a section symbol and offset.
- ///
- /// Returns `None` if the symbol does not have a section.
- pub fn symbol_section_and_offset(&mut self, symbol_id: SymbolId) -> Option<(SymbolId, u64)> {
- let symbol = self.symbol(symbol_id);
- if symbol.kind == SymbolKind::Section {
- return Some((symbol_id, 0));
- }
- let symbol_offset = symbol.value;
- let section = symbol.section.id()?;
- let section_symbol = self.section_symbol(section);
- Some((section_symbol, symbol_offset))
- }
-
- /// Add a relocation to a section.
- ///
- /// Relocations must only be added after the referenced symbols have been added
- /// and defined (if applicable).
- pub fn add_relocation(&mut self, section: SectionId, mut relocation: Relocation) -> Result<()> {
- let addend = match self.format {
- #[cfg(feature = "coff")]
- BinaryFormat::Coff => self.coff_fixup_relocation(&mut relocation),
- #[cfg(feature = "elf")]
- BinaryFormat::Elf => self.elf_fixup_relocation(&mut relocation)?,
- #[cfg(feature = "macho")]
- BinaryFormat::MachO => self.macho_fixup_relocation(&mut relocation),
- #[cfg(feature = "xcoff")]
- BinaryFormat::Xcoff => self.xcoff_fixup_relocation(&mut relocation),
- _ => unimplemented!(),
- };
- if addend != 0 {
- self.write_relocation_addend(section, &relocation, addend)?;
- }
- self.sections[section.0].relocations.push(relocation);
- Ok(())
- }
-
- fn write_relocation_addend(
- &mut self,
- section: SectionId,
- relocation: &Relocation,
- addend: i64,
- ) -> Result<()> {
- let data = self.sections[section.0].data_mut();
- let offset = relocation.offset as usize;
- match relocation.size {
- 32 => data.write_at(offset, &U32::new(self.endian, addend as u32)),
- 64 => data.write_at(offset, &U64::new(self.endian, addend as u64)),
- _ => {
- return Err(Error(format!(
- "unimplemented relocation addend {:?}",
- relocation
- )));
- }
- }
- .map_err(|_| {
- Error(format!(
- "invalid relocation offset {}+{} (max {})",
- relocation.offset,
- relocation.size,
- data.len()
- ))
- })
- }
-
- /// Write the object to a `Vec`.
- pub fn write(&self) -> Result<Vec<u8>> {
- let mut buffer = Vec::new();
- self.emit(&mut buffer)?;
- Ok(buffer)
- }
-
- /// Write the object to a `Write` implementation.
- ///
- /// Also flushes the writer.
- ///
- /// It is advisable to use a buffered writer like [`BufWriter`](std::io::BufWriter)
- /// instead of an unbuffered writer like [`File`](std::fs::File).
- #[cfg(feature = "std")]
- pub fn write_stream<W: io::Write>(&self, w: W) -> result::Result<(), Box<dyn error::Error>> {
- let mut stream = StreamingBuffer::new(w);
- self.emit(&mut stream)?;
- stream.result()?;
- stream.into_inner().flush()?;
- Ok(())
- }
-
- /// Write the object to a `WritableBuffer`.
- pub fn emit(&self, buffer: &mut dyn WritableBuffer) -> Result<()> {
- match self.format {
- #[cfg(feature = "coff")]
- BinaryFormat::Coff => self.coff_write(buffer),
- #[cfg(feature = "elf")]
- BinaryFormat::Elf => self.elf_write(buffer),
- #[cfg(feature = "macho")]
- BinaryFormat::MachO => self.macho_write(buffer),
- #[cfg(feature = "xcoff")]
- BinaryFormat::Xcoff => self.xcoff_write(buffer),
- _ => unimplemented!(),
- }
- }
-}
-
-/// A standard segment kind.
-#[allow(missing_docs)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
-#[non_exhaustive]
-pub enum StandardSegment {
- Text,
- Data,
- Debug,
-}
-
-/// A standard section kind.
-#[allow(missing_docs)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
-#[non_exhaustive]
-pub enum StandardSection {
- Text,
- Data,
- ReadOnlyData,
- ReadOnlyDataWithRel,
- ReadOnlyString,
- UninitializedData,
- Tls,
- /// Zero-fill TLS initializers. Unsupported for COFF.
- UninitializedTls,
- /// TLS variable structures. Only supported for Mach-O.
- TlsVariables,
- /// Common data. Only supported for Mach-O.
- Common,
- /// Notes for GNU properties. Only supported for ELF.
- GnuProperty,
-}
-
-impl StandardSection {
- /// Return the section kind of a standard section.
- pub fn kind(self) -> SectionKind {
- match self {
- StandardSection::Text => SectionKind::Text,
- StandardSection::Data => SectionKind::Data,
- StandardSection::ReadOnlyData => SectionKind::ReadOnlyData,
- StandardSection::ReadOnlyDataWithRel => SectionKind::ReadOnlyDataWithRel,
- StandardSection::ReadOnlyString => SectionKind::ReadOnlyString,
- StandardSection::UninitializedData => SectionKind::UninitializedData,
- StandardSection::Tls => SectionKind::Tls,
- StandardSection::UninitializedTls => SectionKind::UninitializedTls,
- StandardSection::TlsVariables => SectionKind::TlsVariables,
- StandardSection::Common => SectionKind::Common,
- StandardSection::GnuProperty => SectionKind::Note,
- }
- }
-
- // TODO: remembering to update this is error-prone, can we do better?
- fn all() -> &'static [StandardSection] {
- &[
- StandardSection::Text,
- StandardSection::Data,
- StandardSection::ReadOnlyData,
- StandardSection::ReadOnlyDataWithRel,
- StandardSection::ReadOnlyString,
- StandardSection::UninitializedData,
- StandardSection::Tls,
- StandardSection::UninitializedTls,
- StandardSection::TlsVariables,
- StandardSection::Common,
- StandardSection::GnuProperty,
- ]
- }
-}
-
-/// An identifier used to reference a section.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub struct SectionId(usize);
-
-/// A section in an object file.
-#[derive(Debug)]
-pub struct Section<'a> {
- segment: Vec<u8>,
- name: Vec<u8>,
- kind: SectionKind,
- size: u64,
- align: u64,
- data: Cow<'a, [u8]>,
- relocations: Vec<Relocation>,
- symbol: Option<SymbolId>,
- /// Section flags that are specific to each file format.
- pub flags: SectionFlags,
-}
-
-impl<'a> Section<'a> {
- /// Try to convert the name to a utf8 string.
- #[inline]
- pub fn name(&self) -> Option<&str> {
- str::from_utf8(&self.name).ok()
- }
-
- /// Try to convert the segment to a utf8 string.
- #[inline]
- pub fn segment(&self) -> Option<&str> {
- str::from_utf8(&self.segment).ok()
- }
-
- /// Return true if this section contains zerofill data.
- #[inline]
- pub fn is_bss(&self) -> bool {
- self.kind.is_bss()
- }
-
- /// Set the data for a section.
- ///
- /// Must not be called for sections that already have data, or that contain uninitialized data.
- pub fn set_data<T>(&mut self, data: T, align: u64)
- where
- T: Into<Cow<'a, [u8]>>,
- {
- debug_assert!(!self.is_bss());
- debug_assert_eq!(align & (align - 1), 0);
- debug_assert!(self.data.is_empty());
- self.data = data.into();
- self.size = self.data.len() as u64;
- self.align = align;
- }
-
- /// Append data to a section.
- ///
- /// Must not be called for sections that contain uninitialized data.
- pub fn append_data(&mut self, append_data: &[u8], align: u64) -> u64 {
- debug_assert!(!self.is_bss());
- debug_assert_eq!(align & (align - 1), 0);
- if self.align < align {
- self.align = align;
- }
- let align = align as usize;
- let data = self.data.to_mut();
- let mut offset = data.len();
- if offset & (align - 1) != 0 {
- offset += align - (offset & (align - 1));
- data.resize(offset, 0);
- }
- data.extend_from_slice(append_data);
- self.size = data.len() as u64;
- offset as u64
- }
-
- /// Append uninitialized data to a section.
- ///
- /// Must not be called for sections that contain initialized data.
- pub fn append_bss(&mut self, size: u64, align: u64) -> u64 {
- debug_assert!(self.is_bss());
- debug_assert_eq!(align & (align - 1), 0);
- if self.align < align {
- self.align = align;
- }
- let mut offset = self.size;
- if offset & (align - 1) != 0 {
- offset += align - (offset & (align - 1));
- self.size = offset;
- }
- self.size += size;
- offset
- }
-
- /// Returns the section as-built so far.
- ///
- /// This requires that the section is not a bss section.
- pub fn data(&self) -> &[u8] {
- debug_assert!(!self.is_bss());
- &self.data
- }
-
- /// Returns the section as-built so far.
- ///
- /// This requires that the section is not a bss section.
- pub fn data_mut(&mut self) -> &mut [u8] {
- debug_assert!(!self.is_bss());
- self.data.to_mut()
- }
-}
-
-/// The section where a symbol is defined.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-#[non_exhaustive]
-pub enum SymbolSection {
- /// The section is not applicable for this symbol (such as file symbols).
- None,
- /// The symbol is undefined.
- Undefined,
- /// The symbol has an absolute value.
- Absolute,
- /// The symbol is a zero-initialized symbol that will be combined with duplicate definitions.
- Common,
- /// The symbol is defined in the given section.
- Section(SectionId),
-}
-
-impl SymbolSection {
- /// Returns the section id for the section where the symbol is defined.
- ///
- /// May return `None` if the symbol is not defined in a section.
- #[inline]
- pub fn id(self) -> Option<SectionId> {
- if let SymbolSection::Section(id) = self {
- Some(id)
- } else {
- None
- }
- }
-}
-
-/// An identifier used to reference a symbol.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub struct SymbolId(usize);
-
-/// A symbol in an object file.
-#[derive(Debug)]
-pub struct Symbol {
- /// The name of the symbol.
- pub name: Vec<u8>,
- /// The value of the symbol.
- ///
- /// If the symbol defined in a section, then this is the section offset of the symbol.
- pub value: u64,
- /// The size of the symbol.
- pub size: u64,
- /// The kind of the symbol.
- pub kind: SymbolKind,
- /// The scope of the symbol.
- pub scope: SymbolScope,
- /// Whether the symbol has weak binding.
- pub weak: bool,
- /// The section containing the symbol.
- pub section: SymbolSection,
- /// Symbol flags that are specific to each file format.
- pub flags: SymbolFlags<SectionId, SymbolId>,
-}
-
-impl Symbol {
- /// Try to convert the name to a utf8 string.
- #[inline]
- pub fn name(&self) -> Option<&str> {
- str::from_utf8(&self.name).ok()
- }
-
- /// Return true if the symbol is undefined.
- #[inline]
- pub fn is_undefined(&self) -> bool {
- self.section == SymbolSection::Undefined
- }
-
- /// Return true if the symbol is common data.
- ///
- /// Note: does not check for `SymbolSection::Section` with `SectionKind::Common`.
- #[inline]
- pub fn is_common(&self) -> bool {
- self.section == SymbolSection::Common
- }
-
- /// Return true if the symbol scope is local.
- #[inline]
- pub fn is_local(&self) -> bool {
- self.scope == SymbolScope::Compilation
- }
-}
-
-/// A relocation in an object file.
-#[derive(Debug)]
-pub struct Relocation {
- /// The section offset of the place of the relocation.
- pub offset: u64,
- /// The size in bits of the place of relocation.
- pub size: u8,
- /// The operation used to calculate the result of the relocation.
- pub kind: RelocationKind,
- /// Information about how the result of the relocation operation is encoded in the place.
- pub encoding: RelocationEncoding,
- /// The symbol referred to by the relocation.
- ///
- /// This may be a section symbol.
- pub symbol: SymbolId,
- /// The addend to use in the relocation calculation.
- ///
- /// This may be in addition to an implicit addend stored at the place of the relocation.
- pub addend: i64,
-}
-
-/// An identifier used to reference a COMDAT section group.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub struct ComdatId(usize);
-
-/// A COMDAT section group.
-#[derive(Debug)]
-pub struct Comdat {
- /// The COMDAT selection kind.
- ///
- /// This determines the way in which the linker resolves multiple definitions of the COMDAT
- /// sections.
- pub kind: ComdatKind,
- /// The COMDAT symbol.
- ///
- /// If this symbol is referenced, then all sections in the group will be included by the
- /// linker.
- pub symbol: SymbolId,
- /// The sections in the group.
- pub sections: Vec<SectionId>,
-}
-
-/// The symbol name mangling scheme.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-#[non_exhaustive]
-pub enum Mangling {
- /// No symbol mangling.
- None,
- /// Windows COFF symbol mangling.
- Coff,
- /// Windows COFF i386 symbol mangling.
- CoffI386,
- /// ELF symbol mangling.
- Elf,
- /// Mach-O symbol mangling.
- MachO,
- /// Xcoff symbol mangling.
- Xcoff,
-}
-
-impl Mangling {
- /// Return the default symboling mangling for the given format and architecture.
- pub fn default(format: BinaryFormat, architecture: Architecture) -> Self {
- match (format, architecture) {
- (BinaryFormat::Coff, Architecture::I386) => Mangling::CoffI386,
- (BinaryFormat::Coff, _) => Mangling::Coff,
- (BinaryFormat::Elf, _) => Mangling::Elf,
- (BinaryFormat::MachO, _) => Mangling::MachO,
- (BinaryFormat::Xcoff, _) => Mangling::Xcoff,
- _ => Mangling::None,
- }
- }
-
- /// Return the prefix to use for global symbols.
- pub fn global_prefix(self) -> Option<u8> {
- match self {
- Mangling::None | Mangling::Elf | Mangling::Coff | Mangling::Xcoff => None,
- Mangling::CoffI386 | Mangling::MachO => Some(b'_'),
- }
- }
-}