summaryrefslogtreecommitdiffstats
path: root/vendor/object-0.26.2/src/write
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/object-0.26.2/src/write')
-rw-r--r--vendor/object-0.26.2/src/write/coff.rs626
-rw-r--r--vendor/object-0.26.2/src/write/elf.rs1314
-rw-r--r--vendor/object-0.26.2/src/write/macho.rs844
-rw-r--r--vendor/object-0.26.2/src/write/mod.rs858
-rw-r--r--vendor/object-0.26.2/src/write/string.rs139
-rw-r--r--vendor/object-0.26.2/src/write/util.rs129
6 files changed, 0 insertions, 3910 deletions
diff --git a/vendor/object-0.26.2/src/write/coff.rs b/vendor/object-0.26.2/src/write/coff.rs
deleted file mode 100644
index c8516c102..000000000
--- a/vendor/object-0.26.2/src/write/coff.rs
+++ /dev/null
@@ -1,626 +0,0 @@
-use std::mem;
-use std::vec::Vec;
-
-use crate::endian::{LittleEndian as LE, U16Bytes, U32Bytes, U16, U32};
-use crate::pe as coff;
-use crate::write::string::*;
-use crate::write::util::*;
-use crate::write::*;
-
-#[derive(Default, Clone, Copy)]
-struct SectionOffsets {
- offset: usize,
- str_id: Option<StringId>,
- reloc_offset: usize,
- selection: u8,
- associative_section: u16,
-}
-
-#[derive(Default, Clone, Copy)]
-struct SymbolOffsets {
- index: usize,
- str_id: Option<StringId>,
- aux_count: u8,
-}
-
-impl Object {
- pub(crate) fn coff_section_info(
- &self,
- section: StandardSection,
- ) -> (&'static [u8], &'static [u8], SectionKind) {
- match section {
- StandardSection::Text => (&[], &b".text"[..], SectionKind::Text),
- StandardSection::Data => (&[], &b".data"[..], SectionKind::Data),
- StandardSection::ReadOnlyData
- | StandardSection::ReadOnlyDataWithRel
- | StandardSection::ReadOnlyString => (&[], &b".rdata"[..], SectionKind::ReadOnlyData),
- StandardSection::UninitializedData => {
- (&[], &b".bss"[..], SectionKind::UninitializedData)
- }
- // TLS sections are data sections with a special name.
- StandardSection::Tls => (&[], &b".tls$"[..], SectionKind::Data),
- StandardSection::UninitializedTls => {
- // Unsupported section.
- (&[], &[], SectionKind::UninitializedTls)
- }
- StandardSection::TlsVariables => {
- // Unsupported section.
- (&[], &[], SectionKind::TlsVariables)
- }
- StandardSection::Common => {
- // Unsupported section.
- (&[], &[], SectionKind::Common)
- }
- }
- }
-
- pub(crate) fn coff_subsection_name(&self, section: &[u8], value: &[u8]) -> Vec<u8> {
- let mut name = section.to_vec();
- name.push(b'$');
- name.extend_from_slice(value);
- name
- }
-
- pub(crate) fn coff_fixup_relocation(&mut self, mut relocation: &mut Relocation) -> i64 {
- if relocation.kind == RelocationKind::GotRelative {
- // Use a stub symbol for the relocation instead.
- // This isn't really a GOT, but it's a similar purpose.
- // TODO: need to handle DLL imports differently?
- relocation.kind = RelocationKind::Relative;
- relocation.symbol = self.coff_add_stub_symbol(relocation.symbol);
- } else if relocation.kind == RelocationKind::PltRelative {
- // Windows doesn't need a separate relocation type for
- // references to functions in import libraries.
- // For convenience, treat this the same as Relative.
- relocation.kind = RelocationKind::Relative;
- }
-
- let constant = match self.architecture {
- Architecture::I386 => match relocation.kind {
- RelocationKind::Relative => {
- // IMAGE_REL_I386_REL32
- relocation.addend + 4
- }
- _ => relocation.addend,
- },
- Architecture::X86_64 => match relocation.kind {
- RelocationKind::Relative => {
- // IMAGE_REL_AMD64_REL32 through to IMAGE_REL_AMD64_REL32_5
- if relocation.addend <= -4 && relocation.addend >= -9 {
- 0
- } else {
- relocation.addend + 4
- }
- }
- _ => relocation.addend,
- },
- _ => unimplemented!(),
- };
- relocation.addend -= constant;
- constant
- }
-
- fn coff_add_stub_symbol(&mut self, symbol_id: SymbolId) -> SymbolId {
- if let Some(stub_id) = self.stub_symbols.get(&symbol_id) {
- return *stub_id;
- }
- let stub_size = self.architecture.address_size().unwrap().bytes();
-
- let mut name = b".rdata$.refptr.".to_vec();
- name.extend_from_slice(&self.symbols[symbol_id.0].name);
- let section_id = self.add_section(Vec::new(), name, SectionKind::ReadOnlyData);
- let section = self.section_mut(section_id);
- section.set_data(vec![0; stub_size as usize], u64::from(stub_size));
- section.relocations = vec![Relocation {
- offset: 0,
- size: stub_size * 8,
- kind: RelocationKind::Absolute,
- encoding: RelocationEncoding::Generic,
- symbol: symbol_id,
- addend: 0,
- }];
-
- let mut name = b".refptr.".to_vec();
- name.extend_from_slice(&self.symbol(symbol_id).name);
- let stub_id = self.add_raw_symbol(Symbol {
- name,
- value: 0,
- size: u64::from(stub_size),
- kind: SymbolKind::Data,
- scope: SymbolScope::Compilation,
- weak: false,
- section: SymbolSection::Section(section_id),
- flags: SymbolFlags::None,
- });
- self.stub_symbols.insert(symbol_id, stub_id);
-
- stub_id
- }
-
- pub(crate) fn coff_write(&self, buffer: &mut dyn WritableBuffer) -> Result<()> {
- // Calculate offsets of everything, and build strtab.
- let mut offset = 0;
- let mut strtab = StringTable::default();
-
- // COFF header.
- offset += mem::size_of::<coff::ImageFileHeader>();
-
- // Section headers.
- offset += self.sections.len() * mem::size_of::<coff::ImageSectionHeader>();
-
- // Calculate size of section data and add section strings to strtab.
- let mut section_offsets = vec![SectionOffsets::default(); self.sections.len()];
- for (index, section) in self.sections.iter().enumerate() {
- if section.name.len() > 8 {
- section_offsets[index].str_id = Some(strtab.add(&section.name));
- }
-
- let len = section.data.len();
- if len != 0 {
- // TODO: not sure what alignment is required here, but this seems to match LLVM
- offset = align(offset, 4);
- section_offsets[index].offset = offset;
- offset += len;
- } else {
- section_offsets[index].offset = 0;
- }
-
- // Calculate size of relocations.
- let count = section.relocations.len();
- if count != 0 {
- section_offsets[index].reloc_offset = offset;
- offset += count * mem::size_of::<coff::ImageRelocation>();
- }
- }
-
- // Set COMDAT flags.
- for comdat in &self.comdats {
- let symbol = &self.symbols[comdat.symbol.0];
- let comdat_section = match symbol.section {
- SymbolSection::Section(id) => id.0,
- _ => {
- return Err(Error(format!(
- "unsupported COMDAT symbol `{}` section {:?}",
- symbol.name().unwrap_or(""),
- symbol.section
- )));
- }
- };
- section_offsets[comdat_section].selection = match comdat.kind {
- ComdatKind::NoDuplicates => coff::IMAGE_COMDAT_SELECT_NODUPLICATES,
- ComdatKind::Any => coff::IMAGE_COMDAT_SELECT_ANY,
- ComdatKind::SameSize => coff::IMAGE_COMDAT_SELECT_SAME_SIZE,
- ComdatKind::ExactMatch => coff::IMAGE_COMDAT_SELECT_EXACT_MATCH,
- ComdatKind::Largest => coff::IMAGE_COMDAT_SELECT_LARGEST,
- ComdatKind::Newest => coff::IMAGE_COMDAT_SELECT_NEWEST,
- ComdatKind::Unknown => {
- return Err(Error(format!(
- "unsupported COMDAT symbol `{}` kind {:?}",
- symbol.name().unwrap_or(""),
- comdat.kind
- )));
- }
- };
- for id in &comdat.sections {
- let section = &self.sections[id.0];
- if section.symbol.is_none() {
- return Err(Error(format!(
- "missing symbol for COMDAT section `{}`",
- section.name().unwrap_or(""),
- )));
- }
- if id.0 != comdat_section {
- section_offsets[id.0].selection = coff::IMAGE_COMDAT_SELECT_ASSOCIATIVE;
- section_offsets[id.0].associative_section = comdat_section as u16 + 1;
- }
- }
- }
-
- // Calculate size of symbols and add symbol strings to strtab.
- let mut symbol_offsets = vec![SymbolOffsets::default(); self.symbols.len()];
- let mut symtab_count = 0;
- for (index, symbol) in self.symbols.iter().enumerate() {
- symbol_offsets[index].index = symtab_count;
- symtab_count += 1;
- match symbol.kind {
- SymbolKind::File => {
- // Name goes in auxilary symbol records.
- let aux_count = (symbol.name.len() + coff::IMAGE_SIZEOF_SYMBOL - 1)
- / coff::IMAGE_SIZEOF_SYMBOL;
- symbol_offsets[index].aux_count = aux_count as u8;
- symtab_count += aux_count;
- // Don't add name to strtab.
- continue;
- }
- SymbolKind::Section => {
- symbol_offsets[index].aux_count = 1;
- symtab_count += 1;
- }
- _ => {}
- }
- if symbol.name.len() > 8 {
- symbol_offsets[index].str_id = Some(strtab.add(&symbol.name));
- }
- }
-
- // Calculate size of symtab.
- let symtab_offset = offset;
- let symtab_len = symtab_count * coff::IMAGE_SIZEOF_SYMBOL;
- offset += symtab_len;
-
- // Calculate size of strtab.
- let strtab_offset = offset;
- let mut strtab_data = Vec::new();
- // First 4 bytes of strtab are the length.
- strtab.write(4, &mut strtab_data);
- let strtab_len = strtab_data.len() + 4;
- offset += strtab_len;
-
- // Start writing.
- buffer
- .reserve(offset)
- .map_err(|_| Error(String::from("Cannot allocate buffer")))?;
-
- // Write file header.
- let header = coff::ImageFileHeader {
- machine: U16::new(
- LE,
- match self.architecture {
- Architecture::Arm => coff::IMAGE_FILE_MACHINE_ARMNT,
- Architecture::Aarch64 => coff::IMAGE_FILE_MACHINE_ARM64,
- Architecture::I386 => coff::IMAGE_FILE_MACHINE_I386,
- Architecture::X86_64 => coff::IMAGE_FILE_MACHINE_AMD64,
- _ => {
- return Err(Error(format!(
- "unimplemented architecture {:?}",
- self.architecture
- )));
- }
- },
- ),
- number_of_sections: U16::new(LE, self.sections.len() as u16),
- time_date_stamp: U32::default(),
- pointer_to_symbol_table: U32::new(LE, symtab_offset as u32),
- number_of_symbols: U32::new(LE, symtab_count as u32),
- size_of_optional_header: U16::default(),
- characteristics: match self.flags {
- FileFlags::Coff { characteristics } => U16::new(LE, characteristics),
- _ => U16::default(),
- },
- };
- buffer.write(&header);
-
- // Write section headers.
- for (index, section) in self.sections.iter().enumerate() {
- let mut characteristics = match section.flags {
- SectionFlags::Coff {
- characteristics, ..
- } => characteristics,
- _ => 0,
- };
- if section_offsets[index].selection != 0 {
- characteristics |= coff::IMAGE_SCN_LNK_COMDAT;
- };
- characteristics |= match section.kind {
- SectionKind::Text => {
- coff::IMAGE_SCN_CNT_CODE
- | coff::IMAGE_SCN_MEM_EXECUTE
- | coff::IMAGE_SCN_MEM_READ
- }
- SectionKind::Data => {
- coff::IMAGE_SCN_CNT_INITIALIZED_DATA
- | coff::IMAGE_SCN_MEM_READ
- | coff::IMAGE_SCN_MEM_WRITE
- }
- SectionKind::UninitializedData => {
- coff::IMAGE_SCN_CNT_UNINITIALIZED_DATA
- | coff::IMAGE_SCN_MEM_READ
- | coff::IMAGE_SCN_MEM_WRITE
- }
- SectionKind::ReadOnlyData | SectionKind::ReadOnlyString => {
- coff::IMAGE_SCN_CNT_INITIALIZED_DATA | coff::IMAGE_SCN_MEM_READ
- }
- SectionKind::Debug | SectionKind::Other | SectionKind::OtherString => {
- coff::IMAGE_SCN_CNT_INITIALIZED_DATA
- | coff::IMAGE_SCN_MEM_READ
- | coff::IMAGE_SCN_MEM_DISCARDABLE
- }
- SectionKind::Linker => coff::IMAGE_SCN_LNK_INFO | coff::IMAGE_SCN_LNK_REMOVE,
- SectionKind::Common
- | SectionKind::Tls
- | SectionKind::UninitializedTls
- | SectionKind::TlsVariables
- | SectionKind::Note
- | SectionKind::Unknown
- | SectionKind::Metadata
- | SectionKind::Elf(_) => {
- return Err(Error(format!(
- "unimplemented section `{}` kind {:?}",
- section.name().unwrap_or(""),
- section.kind
- )));
- }
- } | match section.align {
- 1 => coff::IMAGE_SCN_ALIGN_1BYTES,
- 2 => coff::IMAGE_SCN_ALIGN_2BYTES,
- 4 => coff::IMAGE_SCN_ALIGN_4BYTES,
- 8 => coff::IMAGE_SCN_ALIGN_8BYTES,
- 16 => coff::IMAGE_SCN_ALIGN_16BYTES,
- 32 => coff::IMAGE_SCN_ALIGN_32BYTES,
- 64 => coff::IMAGE_SCN_ALIGN_64BYTES,
- 128 => coff::IMAGE_SCN_ALIGN_128BYTES,
- 256 => coff::IMAGE_SCN_ALIGN_256BYTES,
- 512 => coff::IMAGE_SCN_ALIGN_512BYTES,
- 1024 => coff::IMAGE_SCN_ALIGN_1024BYTES,
- 2048 => coff::IMAGE_SCN_ALIGN_2048BYTES,
- 4096 => coff::IMAGE_SCN_ALIGN_4096BYTES,
- 8192 => coff::IMAGE_SCN_ALIGN_8192BYTES,
- _ => {
- return Err(Error(format!(
- "unimplemented section `{}` align {}",
- section.name().unwrap_or(""),
- section.align
- )));
- }
- };
- let mut coff_section = coff::ImageSectionHeader {
- name: [0; 8],
- virtual_size: U32::default(),
- virtual_address: U32::default(),
- size_of_raw_data: U32::new(LE, section.size as u32),
- pointer_to_raw_data: U32::new(LE, section_offsets[index].offset as u32),
- pointer_to_relocations: U32::new(LE, section_offsets[index].reloc_offset as u32),
- pointer_to_linenumbers: U32::default(),
- number_of_relocations: U16::new(LE, section.relocations.len() as u16),
- number_of_linenumbers: U16::default(),
- characteristics: U32::new(LE, characteristics),
- };
- if section.name.len() <= 8 {
- coff_section.name[..section.name.len()].copy_from_slice(&section.name);
- } else {
- let mut str_offset = strtab.get_offset(section_offsets[index].str_id.unwrap());
- if str_offset <= 9_999_999 {
- let mut name = [0; 7];
- let mut len = 0;
- if str_offset == 0 {
- name[6] = b'0';
- len = 1;
- } else {
- while str_offset != 0 {
- let rem = (str_offset % 10) as u8;
- str_offset /= 10;
- name[6 - len] = b'0' + rem;
- len += 1;
- }
- }
- coff_section.name = [0; 8];
- coff_section.name[0] = b'/';
- coff_section.name[1..][..len].copy_from_slice(&name[7 - len..]);
- } else if str_offset as u64 <= 0xf_ffff_ffff {
- coff_section.name[0] = b'/';
- coff_section.name[1] = b'/';
- for i in 0..6 {
- let rem = (str_offset % 64) as u8;
- str_offset /= 64;
- let c = match rem {
- 0..=25 => b'A' + rem,
- 26..=51 => b'a' + rem - 26,
- 52..=61 => b'0' + rem - 52,
- 62 => b'+',
- 63 => b'/',
- _ => unreachable!(),
- };
- coff_section.name[7 - i] = c;
- }
- } else {
- return Err(Error(format!("invalid section name offset {}", str_offset)));
- }
- }
- buffer.write(&coff_section);
- }
-
- // Write section data and relocations.
- for (index, section) in self.sections.iter().enumerate() {
- let len = section.data.len();
- if len != 0 {
- write_align(buffer, 4);
- debug_assert_eq!(section_offsets[index].offset, buffer.len());
- buffer.write_bytes(&section.data);
- }
-
- if !section.relocations.is_empty() {
- debug_assert_eq!(section_offsets[index].reloc_offset, buffer.len());
- for reloc in &section.relocations {
- //assert!(reloc.implicit_addend);
- let typ = match self.architecture {
- Architecture::I386 => match (reloc.kind, reloc.size, reloc.addend) {
- (RelocationKind::Absolute, 16, 0) => coff::IMAGE_REL_I386_DIR16,
- (RelocationKind::Relative, 16, 0) => coff::IMAGE_REL_I386_REL16,
- (RelocationKind::Absolute, 32, 0) => coff::IMAGE_REL_I386_DIR32,
- (RelocationKind::ImageOffset, 32, 0) => coff::IMAGE_REL_I386_DIR32NB,
- (RelocationKind::SectionIndex, 16, 0) => coff::IMAGE_REL_I386_SECTION,
- (RelocationKind::SectionOffset, 32, 0) => coff::IMAGE_REL_I386_SECREL,
- (RelocationKind::SectionOffset, 7, 0) => coff::IMAGE_REL_I386_SECREL7,
- (RelocationKind::Relative, 32, -4) => coff::IMAGE_REL_I386_REL32,
- (RelocationKind::Coff(x), _, _) => x,
- _ => {
- return Err(Error(format!("unimplemented relocation {:?}", reloc)));
- }
- },
- Architecture::X86_64 => match (reloc.kind, reloc.size, reloc.addend) {
- (RelocationKind::Absolute, 64, 0) => coff::IMAGE_REL_AMD64_ADDR64,
- (RelocationKind::Absolute, 32, 0) => coff::IMAGE_REL_AMD64_ADDR32,
- (RelocationKind::ImageOffset, 32, 0) => coff::IMAGE_REL_AMD64_ADDR32NB,
- (RelocationKind::Relative, 32, -4) => coff::IMAGE_REL_AMD64_REL32,
- (RelocationKind::Relative, 32, -5) => coff::IMAGE_REL_AMD64_REL32_1,
- (RelocationKind::Relative, 32, -6) => coff::IMAGE_REL_AMD64_REL32_2,
- (RelocationKind::Relative, 32, -7) => coff::IMAGE_REL_AMD64_REL32_3,
- (RelocationKind::Relative, 32, -8) => coff::IMAGE_REL_AMD64_REL32_4,
- (RelocationKind::Relative, 32, -9) => coff::IMAGE_REL_AMD64_REL32_5,
- (RelocationKind::SectionIndex, 16, 0) => coff::IMAGE_REL_AMD64_SECTION,
- (RelocationKind::SectionOffset, 32, 0) => coff::IMAGE_REL_AMD64_SECREL,
- (RelocationKind::SectionOffset, 7, 0) => coff::IMAGE_REL_AMD64_SECREL7,
- (RelocationKind::Coff(x), _, _) => x,
- _ => {
- return Err(Error(format!("unimplemented relocation {:?}", reloc)));
- }
- },
- _ => {
- return Err(Error(format!(
- "unimplemented architecture {:?}",
- self.architecture
- )));
- }
- };
- let coff_relocation = coff::ImageRelocation {
- virtual_address: U32Bytes::new(LE, reloc.offset as u32),
- symbol_table_index: U32Bytes::new(
- LE,
- symbol_offsets[reloc.symbol.0].index as u32,
- ),
- typ: U16Bytes::new(LE, typ),
- };
- buffer.write(&coff_relocation);
- }
- }
- }
-
- // Write symbols.
- debug_assert_eq!(symtab_offset, buffer.len());
- for (index, symbol) in self.symbols.iter().enumerate() {
- let mut name = &symbol.name[..];
- let section_number = match symbol.section {
- SymbolSection::None => {
- debug_assert_eq!(symbol.kind, SymbolKind::File);
- coff::IMAGE_SYM_DEBUG
- }
- SymbolSection::Undefined => coff::IMAGE_SYM_UNDEFINED,
- SymbolSection::Absolute => coff::IMAGE_SYM_ABSOLUTE,
- SymbolSection::Common => coff::IMAGE_SYM_UNDEFINED,
- SymbolSection::Section(id) => id.0 as u16 + 1,
- };
- let typ = if symbol.kind == SymbolKind::Text {
- coff::IMAGE_SYM_DTYPE_FUNCTION << coff::IMAGE_SYM_DTYPE_SHIFT
- } else {
- coff::IMAGE_SYM_TYPE_NULL
- };
- let storage_class = match symbol.kind {
- SymbolKind::File => {
- // Name goes in auxilary symbol records.
- name = b".file";
- coff::IMAGE_SYM_CLASS_FILE
- }
- SymbolKind::Section => coff::IMAGE_SYM_CLASS_STATIC,
- SymbolKind::Label => coff::IMAGE_SYM_CLASS_LABEL,
- SymbolKind::Text | SymbolKind::Data | SymbolKind::Tls => {
- match symbol.section {
- SymbolSection::None => {
- return Err(Error(format!(
- "missing section for symbol `{}`",
- symbol.name().unwrap_or("")
- )));
- }
- SymbolSection::Undefined | SymbolSection::Common => {
- coff::IMAGE_SYM_CLASS_EXTERNAL
- }
- SymbolSection::Absolute | SymbolSection::Section(_) => {
- match symbol.scope {
- // TODO: does this need aux symbol records too?
- _ if symbol.weak => coff::IMAGE_SYM_CLASS_WEAK_EXTERNAL,
- SymbolScope::Unknown => {
- return Err(Error(format!(
- "unimplemented symbol `{}` scope {:?}",
- symbol.name().unwrap_or(""),
- symbol.scope
- )));
- }
- SymbolScope::Compilation => coff::IMAGE_SYM_CLASS_STATIC,
- SymbolScope::Linkage | SymbolScope::Dynamic => {
- coff::IMAGE_SYM_CLASS_EXTERNAL
- }
- }
- }
- }
- }
- SymbolKind::Unknown | SymbolKind::Null => {
- return Err(Error(format!(
- "unimplemented symbol `{}` kind {:?}",
- symbol.name().unwrap_or(""),
- symbol.kind
- )));
- }
- };
- let number_of_aux_symbols = symbol_offsets[index].aux_count;
- let value = if symbol.section == SymbolSection::Common {
- symbol.size as u32
- } else {
- symbol.value as u32
- };
- let mut coff_symbol = coff::ImageSymbol {
- name: [0; 8],
- value: U32Bytes::new(LE, value),
- section_number: U16Bytes::new(LE, section_number as u16),
- typ: U16Bytes::new(LE, typ),
- storage_class,
- number_of_aux_symbols,
- };
- if name.len() <= 8 {
- coff_symbol.name[..name.len()].copy_from_slice(name);
- } else {
- let str_offset = strtab.get_offset(symbol_offsets[index].str_id.unwrap());
- coff_symbol.name[4..8].copy_from_slice(&u32::to_le_bytes(str_offset as u32));
- }
- buffer.write(&coff_symbol);
-
- // Write auxiliary symbols.
- match symbol.kind {
- SymbolKind::File => {
- let aux_len = number_of_aux_symbols as usize * coff::IMAGE_SIZEOF_SYMBOL;
- debug_assert!(aux_len >= symbol.name.len());
- let old_len = buffer.len();
- buffer.write_bytes(&symbol.name);
- buffer.resize(old_len + aux_len, 0);
- }
- SymbolKind::Section => {
- debug_assert_eq!(number_of_aux_symbols, 1);
- let section_index = symbol.section.id().unwrap().0;
- let section = &self.sections[section_index];
- let aux = coff::ImageAuxSymbolSection {
- length: U32Bytes::new(LE, section.size as u32),
- number_of_relocations: U16Bytes::new(LE, section.relocations.len() as u16),
- number_of_linenumbers: U16Bytes::default(),
- check_sum: U32Bytes::new(LE, checksum(section.data.as_slice())),
- number: U16Bytes::new(
- LE,
- section_offsets[section_index].associative_section,
- ),
- selection: section_offsets[section_index].selection,
- reserved: 0,
- // TODO: bigobj
- high_number: U16Bytes::default(),
- };
- buffer.write(&aux);
- }
- _ => {
- debug_assert_eq!(number_of_aux_symbols, 0);
- }
- }
- }
-
- // Write strtab section.
- debug_assert_eq!(strtab_offset, buffer.len());
- buffer.write_bytes(&u32::to_le_bytes(strtab_len as u32));
- buffer.write_bytes(&strtab_data);
-
- debug_assert_eq!(offset, buffer.len());
-
- Ok(())
- }
-}
-
-// JamCRC
-fn checksum(data: &[u8]) -> u32 {
- let mut hasher = crc32fast::Hasher::new_with_initial(0xffff_ffff);
- hasher.update(data);
- !hasher.finalize()
-}
diff --git a/vendor/object-0.26.2/src/write/elf.rs b/vendor/object-0.26.2/src/write/elf.rs
deleted file mode 100644
index 34e0abc85..000000000
--- a/vendor/object-0.26.2/src/write/elf.rs
+++ /dev/null
@@ -1,1314 +0,0 @@
-use std::mem;
-use std::vec::Vec;
-
-use crate::elf;
-use crate::endian::*;
-use crate::write::string::*;
-use crate::write::util::*;
-use crate::write::*;
-use crate::AddressSize;
-
-#[derive(Default, Clone, Copy)]
-struct ComdatOffsets {
- offset: usize,
- str_id: Option<StringId>,
- len: usize,
-}
-
-#[derive(Default, Clone, Copy)]
-struct SectionOffsets {
- index: usize,
- offset: usize,
- str_id: Option<StringId>,
- reloc_index: usize,
- reloc_offset: usize,
- reloc_len: usize,
- reloc_str_id: Option<StringId>,
-}
-
-#[derive(Default, Clone, Copy)]
-struct SymbolOffsets {
- index: usize,
- str_id: Option<StringId>,
-}
-
-impl Object {
- pub(crate) fn elf_section_info(
- &self,
- section: StandardSection,
- ) -> (&'static [u8], &'static [u8], SectionKind) {
- match section {
- StandardSection::Text => (&[], &b".text"[..], SectionKind::Text),
- StandardSection::Data => (&[], &b".data"[..], SectionKind::Data),
- StandardSection::ReadOnlyData | StandardSection::ReadOnlyString => {
- (&[], &b".rodata"[..], SectionKind::ReadOnlyData)
- }
- StandardSection::ReadOnlyDataWithRel => (&[], b".data.rel.ro", SectionKind::Data),
- StandardSection::UninitializedData => {
- (&[], &b".bss"[..], SectionKind::UninitializedData)
- }
- StandardSection::Tls => (&[], &b".tdata"[..], SectionKind::Tls),
- StandardSection::UninitializedTls => {
- (&[], &b".tbss"[..], SectionKind::UninitializedTls)
- }
- StandardSection::TlsVariables => {
- // Unsupported section.
- (&[], &[], SectionKind::TlsVariables)
- }
- StandardSection::Common => {
- // Unsupported section.
- (&[], &[], SectionKind::Common)
- }
- }
- }
-
- pub(crate) fn elf_subsection_name(&self, section: &[u8], value: &[u8]) -> Vec<u8> {
- let mut name = section.to_vec();
- name.push(b'.');
- name.extend_from_slice(value);
- name
- }
-
- fn elf_has_relocation_addend(&self) -> Result<bool> {
- Ok(match self.architecture {
- Architecture::Aarch64 => true,
- Architecture::Arm => false,
- Architecture::Avr => true,
- Architecture::Bpf => false,
- Architecture::I386 => false,
- Architecture::X86_64 => true,
- Architecture::X86_64_X32 => true,
- Architecture::Hexagon => true,
- Architecture::Mips => false,
- Architecture::Mips64 => true,
- Architecture::Msp430 => true,
- Architecture::PowerPc => true,
- Architecture::PowerPc64 => true,
- Architecture::Riscv64 => true,
- Architecture::Riscv32 => true,
- Architecture::S390x => true,
- Architecture::Sparc64 => true,
- _ => {
- return Err(Error(format!(
- "unimplemented architecture {:?}",
- self.architecture
- )));
- }
- })
- }
-
- pub(crate) fn elf_fixup_relocation(&mut self, mut relocation: &mut Relocation) -> Result<i64> {
- // Return true if we should use a section symbol to avoid preemption.
- fn want_section_symbol(relocation: &Relocation, symbol: &Symbol) -> bool {
- if symbol.scope != SymbolScope::Dynamic {
- // Only dynamic symbols can be preemptible.
- return false;
- }
- match symbol.kind {
- SymbolKind::Text | SymbolKind::Data => {}
- _ => return false,
- }
- match relocation.kind {
- // Anything using GOT or PLT is preemptible.
- // We also require that `Other` relocations must already be correct.
- RelocationKind::Got
- | RelocationKind::GotRelative
- | RelocationKind::GotBaseRelative
- | RelocationKind::PltRelative
- | RelocationKind::Elf(_) => return false,
- // Absolute relocations are preemptible for non-local data.
- // TODO: not sure if this rule is exactly correct
- // This rule was added to handle global data references in debuginfo.
- // Maybe this should be a new relocation kind so that the caller can decide.
- RelocationKind::Absolute => {
- if symbol.kind == SymbolKind::Data {
- return false;
- }
- }
- _ => {}
- }
- true
- }
-
- // Use section symbols for relocations where required to avoid preemption.
- // Otherwise, the linker will fail with:
- // relocation R_X86_64_PC32 against symbol `SomeSymbolName' can not be used when
- // making a shared object; recompile with -fPIC
- let symbol = &self.symbols[relocation.symbol.0];
- if want_section_symbol(relocation, symbol) {
- if let Some(section) = symbol.section.id() {
- relocation.addend += symbol.value as i64;
- relocation.symbol = self.section_symbol(section);
- }
- }
-
- // Determine whether the addend is stored in the relocation or the data.
- if self.elf_has_relocation_addend()? {
- Ok(0)
- } else {
- let constant = relocation.addend;
- relocation.addend = 0;
- Ok(constant)
- }
- }
-
- pub(crate) fn elf_write(&self, buffer: &mut dyn WritableBuffer) -> Result<()> {
- let address_size = self.architecture.address_size().unwrap();
- let endian = self.endian;
- let elf32 = Elf32 { endian };
- let elf64 = Elf64 { endian };
- let elf: &dyn Elf = match address_size {
- AddressSize::U8 | AddressSize::U16 | AddressSize::U32 => &elf32,
- AddressSize::U64 => &elf64,
- };
- let pointer_align = address_size.bytes() as usize;
- let is_mips64el =
- self.architecture == Architecture::Mips64 && self.endian == Endianness::Little;
-
- // Calculate offsets of everything.
- let mut offset = 0;
-
- // ELF header.
- let e_ehsize = elf.file_header_size();
- offset += e_ehsize;
-
- // Create reloc section header names.
- let is_rela = self.elf_has_relocation_addend()?;
- let reloc_names: Vec<_> = self
- .sections
- .iter()
- .map(|section| {
- let mut reloc_name = Vec::new();
- if !section.relocations.is_empty() {
- reloc_name.extend_from_slice(if is_rela {
- &b".rela"[..]
- } else {
- &b".rel"[..]
- });
- reloc_name.extend_from_slice(&section.name);
- }
- reloc_name
- })
- .collect();
-
- // Calculate size of section data.
- let mut shstrtab = StringTable::default();
- let mut comdat_offsets = vec![ComdatOffsets::default(); self.comdats.len()];
- let mut section_offsets = vec![SectionOffsets::default(); self.sections.len()];
- // Null section.
- let mut section_num = 1;
- for (index, comdat) in self.comdats.iter().enumerate() {
- if comdat.kind != ComdatKind::Any {
- return Err(Error(format!(
- "unsupported COMDAT symbol `{}` kind {:?}",
- self.symbols[comdat.symbol.0].name().unwrap_or(""),
- comdat.kind
- )));
- }
-
- comdat_offsets[index].str_id = Some(shstrtab.add(b".group"));
- section_num += 1;
- offset = align(offset, 4);
- comdat_offsets[index].offset = offset;
- let len = (comdat.sections.len() + 1) * 4;
- comdat_offsets[index].len = len;
- offset += len;
- }
- for (index, section) in self.sections.iter().enumerate() {
- section_offsets[index].str_id = Some(shstrtab.add(&section.name));
- section_offsets[index].index = section_num;
- section_num += 1;
-
- let len = section.data.len();
- if len != 0 {
- offset = align(offset, section.align as usize);
- section_offsets[index].offset = offset;
- offset += len;
- } else {
- section_offsets[index].offset = offset;
- }
-
- if !section.relocations.is_empty() {
- section_offsets[index].reloc_str_id = Some(shstrtab.add(&reloc_names[index]));
- section_offsets[index].reloc_index = section_num;
- section_num += 1;
- }
- }
-
- // Calculate index of symbols and add symbol strings to strtab.
- let mut strtab = StringTable::default();
- let mut symbol_offsets = vec![SymbolOffsets::default(); self.symbols.len()];
- // Null symbol.
- let mut symtab_count = 1;
- // Local symbols must come before global.
- for (index, symbol) in self.symbols.iter().enumerate() {
- if symbol.is_local() {
- symbol_offsets[index].index = symtab_count;
- symtab_count += 1;
- }
- }
- let symtab_count_local = symtab_count;
- for (index, symbol) in self.symbols.iter().enumerate() {
- if !symbol.is_local() {
- symbol_offsets[index].index = symtab_count;
- symtab_count += 1;
- }
- }
- for (index, symbol) in self.symbols.iter().enumerate() {
- if symbol.kind != SymbolKind::Section && !symbol.name.is_empty() {
- symbol_offsets[index].str_id = Some(strtab.add(&symbol.name));
- }
- }
-
- // Calculate size of symtab.
- let symtab_str_id = shstrtab.add(&b".symtab"[..]);
- offset = align(offset, pointer_align);
- let symtab_offset = offset;
- let symtab_len = symtab_count * elf.symbol_size();
- offset += symtab_len;
- let symtab_index = section_num;
- section_num += 1;
-
- // Calculate size of symtab_shndx.
- let mut need_symtab_shndx = false;
- for symbol in &self.symbols {
- let index = symbol
- .section
- .id()
- .map(|s| section_offsets[s.0].index)
- .unwrap_or(0);
- if index >= elf::SHN_LORESERVE as usize {
- need_symtab_shndx = true;
- break;
- }
- }
- let symtab_shndx_offset = offset;
- let mut symtab_shndx_str_id = None;
- let mut symtab_shndx_len = 0;
- if need_symtab_shndx {
- symtab_shndx_str_id = Some(shstrtab.add(&b".symtab_shndx"[..]));
- symtab_shndx_len = symtab_count * 4;
- offset += symtab_shndx_len;
- section_num += 1;
- }
-
- // Calculate size of strtab.
- let strtab_str_id = shstrtab.add(&b".strtab"[..]);
- let strtab_offset = offset;
- // Start with null name.
- let mut strtab_data = vec![0];
- strtab.write(1, &mut strtab_data);
- offset += strtab_data.len();
- let strtab_index = section_num;
- section_num += 1;
-
- // Calculate size of relocations.
- for (index, section) in self.sections.iter().enumerate() {
- let count = section.relocations.len();
- if count != 0 {
- offset = align(offset, pointer_align);
- section_offsets[index].reloc_offset = offset;
- let len = count * elf.rel_size(is_rela);
- section_offsets[index].reloc_len = len;
- offset += len;
- }
- }
-
- // Calculate size of shstrtab.
- let shstrtab_str_id = shstrtab.add(&b".shstrtab"[..]);
- let shstrtab_offset = offset;
- // Start with null section name.
- let mut shstrtab_data = vec![0];
- shstrtab.write(1, &mut shstrtab_data);
- offset += shstrtab_data.len();
- let shstrtab_index = section_num;
- section_num += 1;
-
- // Calculate size of section headers.
- offset = align(offset, pointer_align);
- let e_shoff = offset;
- let e_shentsize = elf.section_header_size();
- offset += section_num * e_shentsize;
-
- // Start writing.
- buffer
- .reserve(offset)
- .map_err(|_| Error(String::from("Cannot allocate buffer")))?;
-
- // Write file header.
- let e_ident = elf::Ident {
- magic: elf::ELFMAG,
- class: match address_size {
- AddressSize::U8 | AddressSize::U16 | AddressSize::U32 => elf::ELFCLASS32,
- AddressSize::U64 => elf::ELFCLASS64,
- },
- data: if endian.is_little_endian() {
- elf::ELFDATA2LSB
- } else {
- elf::ELFDATA2MSB
- },
- version: elf::EV_CURRENT,
- os_abi: elf::ELFOSABI_NONE,
- abi_version: 0,
- padding: [0; 7],
- };
- let e_type = elf::ET_REL;
- let e_machine = match self.architecture {
- Architecture::Aarch64 => elf::EM_AARCH64,
- Architecture::Arm => elf::EM_ARM,
- Architecture::Avr => elf::EM_AVR,
- Architecture::Bpf => elf::EM_BPF,
- Architecture::I386 => elf::EM_386,
- Architecture::X86_64 => elf::EM_X86_64,
- Architecture::X86_64_X32 => elf::EM_X86_64,
- Architecture::Hexagon => elf::EM_HEXAGON,
- Architecture::Mips => elf::EM_MIPS,
- Architecture::Mips64 => elf::EM_MIPS,
- Architecture::Msp430 => elf::EM_MSP430,
- Architecture::PowerPc => elf::EM_PPC,
- Architecture::PowerPc64 => elf::EM_PPC64,
- Architecture::Riscv32 => elf::EM_RISCV,
- Architecture::Riscv64 => elf::EM_RISCV,
- Architecture::S390x => elf::EM_S390,
- Architecture::Sparc64 => elf::EM_SPARCV9,
- _ => {
- return Err(Error(format!(
- "unimplemented architecture {:?}",
- self.architecture
- )));
- }
- };
- let e_flags = if let FileFlags::Elf { e_flags } = self.flags {
- e_flags
- } else {
- 0
- };
- let e_shnum = if section_num >= elf::SHN_LORESERVE as usize {
- 0
- } else {
- section_num as u16
- };
- let e_shstrndx = if shstrtab_index >= elf::SHN_LORESERVE as usize {
- elf::SHN_XINDEX
- } else {
- shstrtab_index as u16
- };
-
- elf.write_file_header(
- buffer,
- FileHeader {
- e_ident,
- e_type,
- e_machine,
- e_version: elf::EV_CURRENT.into(),
- e_entry: 0,
- e_phoff: 0,
- e_shoff: e_shoff as u64,
- e_flags,
- e_ehsize: e_ehsize as u16,
- e_phentsize: 0,
- e_phnum: 0,
- e_shentsize: e_shentsize as u16,
- e_shnum,
- e_shstrndx,
- },
- );
-
- // Write section data.
- for (index, comdat) in self.comdats.iter().enumerate() {
- let mut data = Vec::new();
- data.write_pod(&U32::new(self.endian, elf::GRP_COMDAT));
- for section in &comdat.sections {
- data.write_pod(&U32::new(
- self.endian,
- section_offsets[section.0].index as u32,
- ));
- }
-
- write_align(buffer, 4);
- debug_assert_eq!(comdat_offsets[index].offset, buffer.len());
- debug_assert_eq!(comdat_offsets[index].len, data.len());
- buffer.write_bytes(&data);
- }
- for (index, section) in self.sections.iter().enumerate() {
- let len = section.data.len();
- if len != 0 {
- write_align(buffer, section.align as usize);
- debug_assert_eq!(section_offsets[index].offset, buffer.len());
- buffer.write_bytes(&section.data);
- }
- }
-
- // Write symbols.
- write_align(buffer, pointer_align);
- debug_assert_eq!(symtab_offset, buffer.len());
- elf.write_symbol(
- buffer,
- Sym {
- st_name: 0,
- st_info: 0,
- st_other: 0,
- st_shndx: 0,
- st_value: 0,
- st_size: 0,
- },
- );
- let mut symtab_shndx = Vec::new();
- if need_symtab_shndx {
- symtab_shndx.write_pod(&U32::new(endian, 0));
- }
- let mut write_symbol = |index: usize, symbol: &Symbol| -> Result<()> {
- let st_info = if let SymbolFlags::Elf { st_info, .. } = symbol.flags {
- st_info
- } else {
- let st_type = match symbol.kind {
- SymbolKind::Null => elf::STT_NOTYPE,
- SymbolKind::Text => {
- if symbol.is_undefined() {
- elf::STT_NOTYPE
- } else {
- elf::STT_FUNC
- }
- }
- SymbolKind::Data => {
- if symbol.is_undefined() {
- elf::STT_NOTYPE
- } else if symbol.is_common() {
- elf::STT_COMMON
- } else {
- elf::STT_OBJECT
- }
- }
- SymbolKind::Section => elf::STT_SECTION,
- SymbolKind::File => elf::STT_FILE,
- SymbolKind::Tls => elf::STT_TLS,
- SymbolKind::Label => elf::STT_NOTYPE,
- SymbolKind::Unknown => {
- if symbol.is_undefined() {
- elf::STT_NOTYPE
- } else {
- return Err(Error(format!(
- "unimplemented symbol `{}` kind {:?}",
- symbol.name().unwrap_or(""),
- symbol.kind
- )));
- }
- }
- };
- let st_bind = if symbol.weak {
- elf::STB_WEAK
- } else if symbol.is_undefined() {
- elf::STB_GLOBAL
- } else if symbol.is_local() {
- elf::STB_LOCAL
- } else {
- elf::STB_GLOBAL
- };
- (st_bind << 4) + st_type
- };
- let st_other = if let SymbolFlags::Elf { st_other, .. } = symbol.flags {
- st_other
- } else if symbol.scope == SymbolScope::Linkage {
- elf::STV_HIDDEN
- } else {
- elf::STV_DEFAULT
- };
- let (st_shndx, xindex) = match symbol.section {
- SymbolSection::None => {
- debug_assert_eq!(symbol.kind, SymbolKind::File);
- (elf::SHN_ABS, 0)
- }
- SymbolSection::Undefined => (elf::SHN_UNDEF, 0),
- SymbolSection::Absolute => (elf::SHN_ABS, 0),
- SymbolSection::Common => (elf::SHN_COMMON, 0),
- SymbolSection::Section(id) => {
- let index = section_offsets[id.0].index as u32;
- (
- if index >= elf::SHN_LORESERVE as u32 {
- elf::SHN_XINDEX
- } else {
- index as u16
- },
- index,
- )
- }
- };
- let st_name = symbol_offsets[index]
- .str_id
- .map(|id| strtab.get_offset(id))
- .unwrap_or(0) as u32;
- elf.write_symbol(
- buffer,
- Sym {
- st_name,
- st_info,
- st_other,
- st_shndx,
- st_value: symbol.value,
- st_size: symbol.size,
- },
- );
- if need_symtab_shndx {
- symtab_shndx.write_pod(&U32::new(endian, xindex));
- }
- Ok(())
- };
- for (index, symbol) in self.symbols.iter().enumerate() {
- if symbol.is_local() {
- write_symbol(index, symbol)?;
- }
- }
- for (index, symbol) in self.symbols.iter().enumerate() {
- if !symbol.is_local() {
- write_symbol(index, symbol)?;
- }
- }
- if need_symtab_shndx {
- debug_assert_eq!(symtab_shndx_offset, buffer.len());
- debug_assert_eq!(symtab_shndx_len, symtab_shndx.len());
- buffer.write_bytes(&symtab_shndx);
- }
-
- // Write strtab section.
- debug_assert_eq!(strtab_offset, buffer.len());
- buffer.write_bytes(&strtab_data);
-
- // Write relocations.
- for (index, section) in self.sections.iter().enumerate() {
- if !section.relocations.is_empty() {
- write_align(buffer, pointer_align);
- debug_assert_eq!(section_offsets[index].reloc_offset, buffer.len());
- for reloc in &section.relocations {
- let r_type = match self.architecture {
- Architecture::Aarch64 => match (reloc.kind, reloc.encoding, reloc.size) {
- (RelocationKind::Absolute, RelocationEncoding::Generic, 64) => {
- elf::R_AARCH64_ABS64
- }
- (RelocationKind::Absolute, RelocationEncoding::Generic, 32) => {
- elf::R_AARCH64_ABS32
- }
- (RelocationKind::Absolute, RelocationEncoding::Generic, 16) => {
- elf::R_AARCH64_ABS16
- }
- (RelocationKind::Relative, RelocationEncoding::Generic, 64) => {
- elf::R_AARCH64_PREL64
- }
- (RelocationKind::Relative, RelocationEncoding::Generic, 32) => {
- elf::R_AARCH64_PREL32
- }
- (RelocationKind::Relative, RelocationEncoding::Generic, 16) => {
- elf::R_AARCH64_PREL16
- }
- (RelocationKind::Relative, RelocationEncoding::AArch64Call, 26)
- | (RelocationKind::PltRelative, RelocationEncoding::AArch64Call, 26) => {
- elf::R_AARCH64_CALL26
- }
- (RelocationKind::Elf(x), _, _) => x,
- _ => {
- return Err(Error(format!("unimplemented relocation {:?}", reloc)));
- }
- },
- Architecture::Arm => match (reloc.kind, reloc.encoding, reloc.size) {
- (RelocationKind::Absolute, _, 32) => elf::R_ARM_ABS32,
- (RelocationKind::Elf(x), _, _) => x,
- _ => {
- return Err(Error(format!("unimplemented relocation {:?}", reloc)));
- }
- },
- Architecture::Avr => match (reloc.kind, reloc.encoding, reloc.size) {
- (RelocationKind::Absolute, _, 32) => elf::R_AVR_32,
- (RelocationKind::Absolute, _, 16) => elf::R_AVR_16,
- (RelocationKind::Elf(x), _, _) => x,
- _ => {
- return Err(Error(format!("unimplemented relocation {:?}", reloc)));
- }
- },
- Architecture::Bpf => match (reloc.kind, reloc.encoding, reloc.size) {
- (RelocationKind::Absolute, _, 64) => elf::R_BPF_64_64,
- (RelocationKind::Absolute, _, 32) => elf::R_BPF_64_32,
- (RelocationKind::Elf(x), _, _) => x,
- _ => {
- return Err(Error(format!("unimplemented relocation {:?}", reloc)));
- }
- },
- Architecture::I386 => match (reloc.kind, reloc.size) {
- (RelocationKind::Absolute, 32) => elf::R_386_32,
- (RelocationKind::Relative, 32) => elf::R_386_PC32,
- (RelocationKind::Got, 32) => elf::R_386_GOT32,
- (RelocationKind::PltRelative, 32) => elf::R_386_PLT32,
- (RelocationKind::GotBaseOffset, 32) => elf::R_386_GOTOFF,
- (RelocationKind::GotBaseRelative, 32) => elf::R_386_GOTPC,
- (RelocationKind::Absolute, 16) => elf::R_386_16,
- (RelocationKind::Relative, 16) => elf::R_386_PC16,
- (RelocationKind::Absolute, 8) => elf::R_386_8,
- (RelocationKind::Relative, 8) => elf::R_386_PC8,
- (RelocationKind::Elf(x), _) => x,
- _ => {
- return Err(Error(format!("unimplemented relocation {:?}", reloc)));
- }
- },
- Architecture::X86_64 | Architecture::X86_64_X32 => {
- match (reloc.kind, reloc.encoding, reloc.size) {
- (RelocationKind::Absolute, RelocationEncoding::Generic, 64) => {
- elf::R_X86_64_64
- }
- (RelocationKind::Relative, _, 32) => elf::R_X86_64_PC32,
- (RelocationKind::Got, _, 32) => elf::R_X86_64_GOT32,
- (RelocationKind::PltRelative, _, 32) => elf::R_X86_64_PLT32,
- (RelocationKind::GotRelative, _, 32) => elf::R_X86_64_GOTPCREL,
- (RelocationKind::Absolute, RelocationEncoding::Generic, 32) => {
- elf::R_X86_64_32
- }
- (RelocationKind::Absolute, RelocationEncoding::X86Signed, 32) => {
- elf::R_X86_64_32S
- }
- (RelocationKind::Absolute, _, 16) => elf::R_X86_64_16,
- (RelocationKind::Relative, _, 16) => elf::R_X86_64_PC16,
- (RelocationKind::Absolute, _, 8) => elf::R_X86_64_8,
- (RelocationKind::Relative, _, 8) => elf::R_X86_64_PC8,
- (RelocationKind::Elf(x), _, _) => x,
- _ => {
- return Err(Error(format!(
- "unimplemented relocation {:?}",
- reloc
- )));
- }
- }
- }
- Architecture::Hexagon => match (reloc.kind, reloc.encoding, reloc.size) {
- (RelocationKind::Absolute, _, 32) => elf::R_HEX_32,
- (RelocationKind::Elf(x), _, _) => x,
- _ => {
- return Err(Error(format!("unimplemented relocation {:?}", reloc)));
- }
- },
- Architecture::Mips | Architecture::Mips64 => {
- match (reloc.kind, reloc.encoding, reloc.size) {
- (RelocationKind::Absolute, _, 16) => elf::R_MIPS_16,
- (RelocationKind::Absolute, _, 32) => elf::R_MIPS_32,
- (RelocationKind::Absolute, _, 64) => elf::R_MIPS_64,
- (RelocationKind::Elf(x), _, _) => x,
- _ => {
- return Err(Error(format!(
- "unimplemented relocation {:?}",
- reloc
- )));
- }
- }
- }
- Architecture::Msp430 => match (reloc.kind, reloc.encoding, reloc.size) {
- (RelocationKind::Absolute, _, 32) => elf::R_MSP430_32,
- (RelocationKind::Absolute, _, 16) => elf::R_MSP430_16_BYTE,
- (RelocationKind::Elf(x), _, _) => x,
- _ => {
- return Err(Error(format!("unimplemented relocation {:?}", reloc)));
- }
- },
- Architecture::PowerPc => match (reloc.kind, reloc.encoding, reloc.size) {
- (RelocationKind::Absolute, _, 32) => elf::R_PPC_ADDR32,
- (RelocationKind::Elf(x), _, _) => x,
- _ => {
- return Err(Error(format!("unimplemented relocation {:?}", reloc)));
- }
- },
- Architecture::PowerPc64 => match (reloc.kind, reloc.encoding, reloc.size) {
- (RelocationKind::Absolute, _, 32) => elf::R_PPC64_ADDR32,
- (RelocationKind::Absolute, _, 64) => elf::R_PPC64_ADDR64,
- (RelocationKind::Elf(x), _, _) => x,
- _ => {
- return Err(Error(format!("unimplemented relocation {:?}", reloc)));
- }
- },
- Architecture::Riscv32 | Architecture::Riscv64 => {
- match (reloc.kind, reloc.encoding, reloc.size) {
- (RelocationKind::Absolute, _, 32) => elf::R_RISCV_32,
- (RelocationKind::Absolute, _, 64) => elf::R_RISCV_64,
- (RelocationKind::Elf(x), _, _) => x,
- _ => {
- return Err(Error(format!(
- "unimplemented relocation {:?}",
- reloc
- )));
- }
- }
- }
- Architecture::S390x => match (reloc.kind, reloc.encoding, reloc.size) {
- (RelocationKind::Absolute, RelocationEncoding::Generic, 8) => {
- elf::R_390_8
- }
- (RelocationKind::Absolute, RelocationEncoding::Generic, 16) => {
- elf::R_390_16
- }
- (RelocationKind::Absolute, RelocationEncoding::Generic, 32) => {
- elf::R_390_32
- }
- (RelocationKind::Absolute, RelocationEncoding::Generic, 64) => {
- elf::R_390_64
- }
- (RelocationKind::Relative, RelocationEncoding::Generic, 16) => {
- elf::R_390_PC16
- }
- (RelocationKind::Relative, RelocationEncoding::Generic, 32) => {
- elf::R_390_PC32
- }
- (RelocationKind::Relative, RelocationEncoding::Generic, 64) => {
- elf::R_390_PC64
- }
- (RelocationKind::Relative, RelocationEncoding::S390xDbl, 16) => {
- elf::R_390_PC16DBL
- }
- (RelocationKind::Relative, RelocationEncoding::S390xDbl, 32) => {
- elf::R_390_PC32DBL
- }
- (RelocationKind::PltRelative, RelocationEncoding::S390xDbl, 16) => {
- elf::R_390_PLT16DBL
- }
- (RelocationKind::PltRelative, RelocationEncoding::S390xDbl, 32) => {
- elf::R_390_PLT32DBL
- }
- (RelocationKind::Got, RelocationEncoding::Generic, 16) => {
- elf::R_390_GOT16
- }
- (RelocationKind::Got, RelocationEncoding::Generic, 32) => {
- elf::R_390_GOT32
- }
- (RelocationKind::Got, RelocationEncoding::Generic, 64) => {
- elf::R_390_GOT64
- }
- (RelocationKind::GotRelative, RelocationEncoding::S390xDbl, 32) => {
- elf::R_390_GOTENT
- }
- (RelocationKind::GotBaseOffset, RelocationEncoding::Generic, 16) => {
- elf::R_390_GOTOFF16
- }
- (RelocationKind::GotBaseOffset, RelocationEncoding::Generic, 32) => {
- elf::R_390_GOTOFF32
- }
- (RelocationKind::GotBaseOffset, RelocationEncoding::Generic, 64) => {
- elf::R_390_GOTOFF64
- }
- (RelocationKind::GotBaseRelative, RelocationEncoding::Generic, 64) => {
- elf::R_390_GOTPC
- }
- (RelocationKind::GotBaseRelative, RelocationEncoding::S390xDbl, 32) => {
- elf::R_390_GOTPCDBL
- }
- (RelocationKind::Elf(x), _, _) => x,
- _ => {
- return Err(Error(format!("unimplemented relocation {:?}", reloc)));
- }
- },
- Architecture::Sparc64 => match (reloc.kind, reloc.encoding, reloc.size) {
- // TODO: use R_SPARC_32/R_SPARC_64 if aligned.
- (RelocationKind::Absolute, _, 32) => elf::R_SPARC_UA32,
- (RelocationKind::Absolute, _, 64) => elf::R_SPARC_UA64,
- (RelocationKind::Elf(x), _, _) => x,
- _ => {
- return Err(Error(format!("unimplemented relocation {:?}", reloc)));
- }
- },
- _ => {
- if let RelocationKind::Elf(x) = reloc.kind {
- x
- } else {
- return Err(Error(format!("unimplemented relocation {:?}", reloc)));
- }
- }
- };
- let r_sym = symbol_offsets[reloc.symbol.0].index as u32;
- elf.write_rel(
- buffer,
- is_mips64el,
- is_rela,
- Rel {
- r_offset: reloc.offset,
- r_sym,
- r_type,
- r_addend: reloc.addend,
- },
- );
- }
- }
- }
-
- // Write shstrtab section.
- debug_assert_eq!(shstrtab_offset, buffer.len());
- buffer.write_bytes(&shstrtab_data);
-
- // Write section headers.
- write_align(buffer, pointer_align);
- debug_assert_eq!(e_shoff, buffer.len());
- elf.write_section_header(
- buffer,
- SectionHeader {
- sh_name: 0,
- sh_type: 0,
- sh_flags: 0,
- sh_addr: 0,
- sh_offset: 0,
- sh_size: if section_num >= elf::SHN_LORESERVE as usize {
- section_num as u64
- } else {
- 0
- },
- sh_link: if shstrtab_index >= elf::SHN_LORESERVE as usize {
- shstrtab_index as u32
- } else {
- 0
- },
- // TODO: e_phnum overflow
- sh_info: 0,
- sh_addralign: 0,
- sh_entsize: 0,
- },
- );
- for (index, comdat) in self.comdats.iter().enumerate() {
- let sh_name = comdat_offsets[index]
- .str_id
- .map(|id| shstrtab.get_offset(id))
- .unwrap_or(0) as u32;
- elf.write_section_header(
- buffer,
- SectionHeader {
- sh_name,
- sh_type: elf::SHT_GROUP,
- sh_flags: 0,
- sh_addr: 0,
- sh_offset: comdat_offsets[index].offset as u64,
- sh_size: comdat_offsets[index].len as u64,
- sh_link: symtab_index as u32,
- sh_info: symbol_offsets[comdat.symbol.0].index as u32,
- sh_addralign: 4,
- sh_entsize: 4,
- },
- );
- }
- for (index, section) in self.sections.iter().enumerate() {
- let sh_type = match section.kind {
- SectionKind::UninitializedData | SectionKind::UninitializedTls => elf::SHT_NOBITS,
- SectionKind::Note => elf::SHT_NOTE,
- SectionKind::Elf(sh_type) => sh_type,
- _ => elf::SHT_PROGBITS,
- };
- let sh_flags = if let SectionFlags::Elf { sh_flags } = section.flags {
- sh_flags
- } else {
- match section.kind {
- SectionKind::Text => elf::SHF_ALLOC | elf::SHF_EXECINSTR,
- SectionKind::Data => elf::SHF_ALLOC | elf::SHF_WRITE,
- SectionKind::Tls => elf::SHF_ALLOC | elf::SHF_WRITE | elf::SHF_TLS,
- SectionKind::UninitializedData => elf::SHF_ALLOC | elf::SHF_WRITE,
- SectionKind::UninitializedTls => elf::SHF_ALLOC | elf::SHF_WRITE | elf::SHF_TLS,
- SectionKind::ReadOnlyData => elf::SHF_ALLOC,
- SectionKind::ReadOnlyString => {
- elf::SHF_ALLOC | elf::SHF_STRINGS | elf::SHF_MERGE
- }
- SectionKind::OtherString => elf::SHF_STRINGS | elf::SHF_MERGE,
- SectionKind::Other
- | SectionKind::Debug
- | SectionKind::Metadata
- | SectionKind::Linker
- | SectionKind::Note
- | SectionKind::Elf(_) => 0,
- SectionKind::Unknown | SectionKind::Common | SectionKind::TlsVariables => {
- return Err(Error(format!(
- "unimplemented section `{}` kind {:?}",
- section.name().unwrap_or(""),
- section.kind
- )));
- }
- }
- .into()
- };
- // TODO: not sure if this is correct, maybe user should determine this
- let sh_entsize = match section.kind {
- SectionKind::ReadOnlyString | SectionKind::OtherString => 1,
- _ => 0,
- };
- let sh_name = section_offsets[index]
- .str_id
- .map(|id| shstrtab.get_offset(id))
- .unwrap_or(0) as u32;
- elf.write_section_header(
- buffer,
- SectionHeader {
- sh_name,
- sh_type,
- sh_flags,
- sh_addr: 0,
- sh_offset: section_offsets[index].offset as u64,
- sh_size: section.size,
- sh_link: 0,
- sh_info: 0,
- sh_addralign: section.align,
- sh_entsize,
- },
- );
-
- if !section.relocations.is_empty() {
- let sh_name = section_offsets[index]
- .reloc_str_id
- .map(|id| shstrtab.get_offset(id))
- .unwrap_or(0);
- elf.write_section_header(
- buffer,
- SectionHeader {
- sh_name: sh_name as u32,
- sh_type: if is_rela { elf::SHT_RELA } else { elf::SHT_REL },
- sh_flags: elf::SHF_INFO_LINK.into(),
- sh_addr: 0,
- sh_offset: section_offsets[index].reloc_offset as u64,
- sh_size: section_offsets[index].reloc_len as u64,
- sh_link: symtab_index as u32,
- sh_info: section_offsets[index].index as u32,
- sh_addralign: pointer_align as u64,
- sh_entsize: elf.rel_size(is_rela) as u64,
- },
- );
- }
- }
-
- // Write symtab section header.
- elf.write_section_header(
- buffer,
- SectionHeader {
- sh_name: shstrtab.get_offset(symtab_str_id) as u32,
- sh_type: elf::SHT_SYMTAB,
- sh_flags: 0,
- sh_addr: 0,
- sh_offset: symtab_offset as u64,
- sh_size: symtab_len as u64,
- sh_link: strtab_index as u32,
- sh_info: symtab_count_local as u32,
- sh_addralign: pointer_align as u64,
- sh_entsize: elf.symbol_size() as u64,
- },
- );
-
- // Write symtab_shndx section header.
- if need_symtab_shndx {
- elf.write_section_header(
- buffer,
- SectionHeader {
- sh_name: shstrtab.get_offset(symtab_shndx_str_id.unwrap()) as u32,
- sh_type: elf::SHT_SYMTAB_SHNDX,
- sh_flags: 0,
- sh_addr: 0,
- sh_offset: symtab_shndx_offset as u64,
- sh_size: symtab_shndx_len as u64,
- sh_link: symtab_index as u32,
- sh_info: symtab_count_local as u32,
- sh_addralign: 4,
- sh_entsize: 4,
- },
- );
- }
-
- // Write strtab section header.
- elf.write_section_header(
- buffer,
- SectionHeader {
- sh_name: shstrtab.get_offset(strtab_str_id) as u32,
- sh_type: elf::SHT_STRTAB,
- sh_flags: 0,
- sh_addr: 0,
- sh_offset: strtab_offset as u64,
- sh_size: strtab_data.len() as u64,
- sh_link: 0,
- sh_info: 0,
- sh_addralign: 1,
- sh_entsize: 0,
- },
- );
-
- // Write shstrtab section header.
- elf.write_section_header(
- buffer,
- SectionHeader {
- sh_name: shstrtab.get_offset(shstrtab_str_id) as u32,
- sh_type: elf::SHT_STRTAB,
- sh_flags: 0,
- sh_addr: 0,
- sh_offset: shstrtab_offset as u64,
- sh_size: shstrtab_data.len() as u64,
- sh_link: 0,
- sh_info: 0,
- sh_addralign: 1,
- sh_entsize: 0,
- },
- );
-
- debug_assert_eq!(offset, buffer.len());
-
- Ok(())
- }
-}
-
-/// Native endian version of `FileHeader64`.
-struct FileHeader {
- e_ident: elf::Ident,
- e_type: u16,
- e_machine: u16,
- e_version: u32,
- e_entry: u64,
- e_phoff: u64,
- e_shoff: u64,
- e_flags: u32,
- e_ehsize: u16,
- e_phentsize: u16,
- e_phnum: u16,
- e_shentsize: u16,
- e_shnum: u16,
- e_shstrndx: u16,
-}
-
-/// Native endian version of `SectionHeader64`.
-struct SectionHeader {
- sh_name: u32,
- sh_type: u32,
- sh_flags: u64,
- sh_addr: u64,
- sh_offset: u64,
- sh_size: u64,
- sh_link: u32,
- sh_info: u32,
- sh_addralign: u64,
- sh_entsize: u64,
-}
-
-/// Native endian version of `Sym64`.
-struct Sym {
- st_name: u32,
- st_info: u8,
- st_other: u8,
- st_shndx: u16,
- st_value: u64,
- st_size: u64,
-}
-
-/// Unified native endian version of `Rel*`.
-struct Rel {
- r_offset: u64,
- r_sym: u32,
- r_type: u32,
- r_addend: i64,
-}
-
-trait Elf {
- fn file_header_size(&self) -> usize;
- fn section_header_size(&self) -> usize;
- fn symbol_size(&self) -> usize;
- fn rel_size(&self, is_rela: bool) -> usize;
- fn write_file_header(&self, buffer: &mut dyn WritableBuffer, section: FileHeader);
- fn write_section_header(&self, buffer: &mut dyn WritableBuffer, section: SectionHeader);
- fn write_symbol(&self, buffer: &mut dyn WritableBuffer, symbol: Sym);
- fn write_rel(
- &self,
- buffer: &mut dyn WritableBuffer,
- is_mips64el: bool,
- is_rela: bool,
- rel: Rel,
- );
-}
-
-struct Elf32<E> {
- endian: E,
-}
-
-impl<E: Endian> Elf for Elf32<E> {
- fn file_header_size(&self) -> usize {
- mem::size_of::<elf::FileHeader32<E>>()
- }
-
- fn section_header_size(&self) -> usize {
- mem::size_of::<elf::SectionHeader32<E>>()
- }
-
- fn symbol_size(&self) -> usize {
- mem::size_of::<elf::Sym32<E>>()
- }
-
- fn rel_size(&self, is_rela: bool) -> usize {
- if is_rela {
- mem::size_of::<elf::Rela32<E>>()
- } else {
- mem::size_of::<elf::Rel32<E>>()
- }
- }
-
- fn write_file_header(&self, buffer: &mut dyn WritableBuffer, file: FileHeader) {
- let endian = self.endian;
- let file = elf::FileHeader32 {
- e_ident: file.e_ident,
- e_type: U16::new(endian, file.e_type),
- e_machine: U16::new(endian, file.e_machine),
- e_version: U32::new(endian, file.e_version),
- e_entry: U32::new(endian, file.e_entry as u32),
- e_phoff: U32::new(endian, file.e_phoff as u32),
- e_shoff: U32::new(endian, file.e_shoff as u32),
- e_flags: U32::new(endian, file.e_flags),
- e_ehsize: U16::new(endian, file.e_ehsize),
- e_phentsize: U16::new(endian, file.e_phentsize),
- e_phnum: U16::new(endian, file.e_phnum),
- e_shentsize: U16::new(endian, file.e_shentsize),
- e_shnum: U16::new(endian, file.e_shnum),
- e_shstrndx: U16::new(endian, file.e_shstrndx),
- };
- buffer.write(&file);
- }
-
- fn write_section_header(&self, buffer: &mut dyn WritableBuffer, section: SectionHeader) {
- let endian = self.endian;
- let section = elf::SectionHeader32 {
- sh_name: U32::new(endian, section.sh_name),
- sh_type: U32::new(endian, section.sh_type),
- sh_flags: U32::new(endian, section.sh_flags as u32),
- sh_addr: U32::new(endian, section.sh_addr as u32),
- sh_offset: U32::new(endian, section.sh_offset as u32),
- sh_size: U32::new(endian, section.sh_size as u32),
- sh_link: U32::new(endian, section.sh_link),
- sh_info: U32::new(endian, section.sh_info),
- sh_addralign: U32::new(endian, section.sh_addralign as u32),
- sh_entsize: U32::new(endian, section.sh_entsize as u32),
- };
- buffer.write(&section);
- }
-
- fn write_symbol(&self, buffer: &mut dyn WritableBuffer, symbol: Sym) {
- let endian = self.endian;
- let symbol = elf::Sym32 {
- st_name: U32::new(endian, symbol.st_name),
- st_info: symbol.st_info,
- st_other: symbol.st_other,
- st_shndx: U16::new(endian, symbol.st_shndx),
- st_value: U32::new(endian, symbol.st_value as u32),
- st_size: U32::new(endian, symbol.st_size as u32),
- };
- buffer.write(&symbol);
- }
-
- fn write_rel(
- &self,
- buffer: &mut dyn WritableBuffer,
- _is_mips64el: bool,
- is_rela: bool,
- rel: Rel,
- ) {
- let endian = self.endian;
- if is_rela {
- let rel = elf::Rela32 {
- r_offset: U32::new(endian, rel.r_offset as u32),
- r_info: elf::Rel32::r_info(endian, rel.r_sym, rel.r_type as u8),
- r_addend: I32::new(endian, rel.r_addend as i32),
- };
- buffer.write(&rel);
- } else {
- let rel = elf::Rel32 {
- r_offset: U32::new(endian, rel.r_offset as u32),
- r_info: elf::Rel32::r_info(endian, rel.r_sym, rel.r_type as u8),
- };
- buffer.write(&rel);
- }
- }
-}
-
-struct Elf64<E> {
- endian: E,
-}
-
-impl<E: Endian> Elf for Elf64<E> {
- fn file_header_size(&self) -> usize {
- mem::size_of::<elf::FileHeader64<E>>()
- }
-
- fn section_header_size(&self) -> usize {
- mem::size_of::<elf::SectionHeader64<E>>()
- }
-
- fn symbol_size(&self) -> usize {
- mem::size_of::<elf::Sym64<E>>()
- }
-
- fn rel_size(&self, is_rela: bool) -> usize {
- if is_rela {
- mem::size_of::<elf::Rela64<E>>()
- } else {
- mem::size_of::<elf::Rel64<E>>()
- }
- }
-
- fn write_file_header(&self, buffer: &mut dyn WritableBuffer, file: FileHeader) {
- let endian = self.endian;
- let file = elf::FileHeader64 {
- e_ident: file.e_ident,
- e_type: U16::new(endian, file.e_type),
- e_machine: U16::new(endian, file.e_machine),
- e_version: U32::new(endian, file.e_version),
- e_entry: U64::new(endian, file.e_entry),
- e_phoff: U64::new(endian, file.e_phoff),
- e_shoff: U64::new(endian, file.e_shoff),
- e_flags: U32::new(endian, file.e_flags),
- e_ehsize: U16::new(endian, file.e_ehsize),
- e_phentsize: U16::new(endian, file.e_phentsize),
- e_phnum: U16::new(endian, file.e_phnum),
- e_shentsize: U16::new(endian, file.e_shentsize),
- e_shnum: U16::new(endian, file.e_shnum),
- e_shstrndx: U16::new(endian, file.e_shstrndx),
- };
- buffer.write(&file)
- }
-
- fn write_section_header(&self, buffer: &mut dyn WritableBuffer, section: SectionHeader) {
- let endian = self.endian;
- let section = elf::SectionHeader64 {
- sh_name: U32::new(endian, section.sh_name),
- sh_type: U32::new(endian, section.sh_type),
- sh_flags: U64::new(endian, section.sh_flags),
- sh_addr: U64::new(endian, section.sh_addr),
- sh_offset: U64::new(endian, section.sh_offset),
- sh_size: U64::new(endian, section.sh_size),
- sh_link: U32::new(endian, section.sh_link),
- sh_info: U32::new(endian, section.sh_info),
- sh_addralign: U64::new(endian, section.sh_addralign),
- sh_entsize: U64::new(endian, section.sh_entsize),
- };
- buffer.write(&section);
- }
-
- fn write_symbol(&self, buffer: &mut dyn WritableBuffer, symbol: Sym) {
- let endian = self.endian;
- let symbol = elf::Sym64 {
- st_name: U32::new(endian, symbol.st_name),
- st_info: symbol.st_info,
- st_other: symbol.st_other,
- st_shndx: U16::new(endian, symbol.st_shndx),
- st_value: U64::new(endian, symbol.st_value),
- st_size: U64::new(endian, symbol.st_size),
- };
- buffer.write(&symbol);
- }
-
- fn write_rel(
- &self,
- buffer: &mut dyn WritableBuffer,
- is_mips64el: bool,
- is_rela: bool,
- rel: Rel,
- ) {
- let endian = self.endian;
- if is_rela {
- let rel = elf::Rela64 {
- r_offset: U64::new(endian, rel.r_offset),
- r_info: elf::Rela64::r_info(endian, is_mips64el, rel.r_sym, rel.r_type),
- r_addend: I64::new(endian, rel.r_addend),
- };
- buffer.write(&rel);
- } else {
- let rel = elf::Rel64 {
- r_offset: U64::new(endian, rel.r_offset),
- r_info: elf::Rel64::r_info(endian, rel.r_sym, rel.r_type),
- };
- buffer.write(&rel);
- }
- }
-}
diff --git a/vendor/object-0.26.2/src/write/macho.rs b/vendor/object-0.26.2/src/write/macho.rs
deleted file mode 100644
index ed25950d9..000000000
--- a/vendor/object-0.26.2/src/write/macho.rs
+++ /dev/null
@@ -1,844 +0,0 @@
-use std::mem;
-
-use crate::endian::*;
-use crate::macho;
-use crate::write::string::*;
-use crate::write::util::*;
-use crate::write::*;
-use crate::AddressSize;
-
-#[derive(Default, Clone, Copy)]
-struct SectionOffsets {
- index: usize,
- offset: usize,
- address: u64,
- reloc_offset: usize,
-}
-
-#[derive(Default, Clone, Copy)]
-struct SymbolOffsets {
- emit: bool,
- index: usize,
- str_id: Option<StringId>,
-}
-
-impl Object {
- pub(crate) fn macho_set_subsections_via_symbols(&mut self) {
- let flags = match self.flags {
- FileFlags::MachO { flags } => flags,
- _ => 0,
- };
- self.flags = FileFlags::MachO {
- flags: flags | macho::MH_SUBSECTIONS_VIA_SYMBOLS,
- };
- }
-
- pub(crate) fn macho_segment_name(&self, segment: StandardSegment) -> &'static [u8] {
- match segment {
- StandardSegment::Text => &b"__TEXT"[..],
- StandardSegment::Data => &b"__DATA"[..],
- StandardSegment::Debug => &b"__DWARF"[..],
- }
- }
-
- pub(crate) fn macho_section_info(
- &self,
- section: StandardSection,
- ) -> (&'static [u8], &'static [u8], SectionKind) {
- match section {
- StandardSection::Text => (&b"__TEXT"[..], &b"__text"[..], SectionKind::Text),
- StandardSection::Data => (&b"__DATA"[..], &b"__data"[..], SectionKind::Data),
- StandardSection::ReadOnlyData => {
- (&b"__TEXT"[..], &b"__const"[..], SectionKind::ReadOnlyData)
- }
- StandardSection::ReadOnlyDataWithRel => {
- (&b"__DATA"[..], &b"__const"[..], SectionKind::ReadOnlyData)
- }
- StandardSection::ReadOnlyString => (
- &b"__TEXT"[..],
- &b"__cstring"[..],
- SectionKind::ReadOnlyString,
- ),
- StandardSection::UninitializedData => (
- &b"__DATA"[..],
- &b"__bss"[..],
- SectionKind::UninitializedData,
- ),
- StandardSection::Tls => (&b"__DATA"[..], &b"__thread_data"[..], SectionKind::Tls),
- StandardSection::UninitializedTls => (
- &b"__DATA"[..],
- &b"__thread_bss"[..],
- SectionKind::UninitializedTls,
- ),
- StandardSection::TlsVariables => (
- &b"__DATA"[..],
- &b"__thread_vars"[..],
- SectionKind::TlsVariables,
- ),
- StandardSection::Common => (&b"__DATA"[..], &b"__common"[..], SectionKind::Common),
- }
- }
-
- fn macho_tlv_bootstrap(&mut self) -> SymbolId {
- match self.tlv_bootstrap {
- Some(id) => id,
- None => {
- let id = self.add_symbol(Symbol {
- name: b"_tlv_bootstrap".to_vec(),
- value: 0,
- size: 0,
- kind: SymbolKind::Text,
- scope: SymbolScope::Dynamic,
- weak: false,
- section: SymbolSection::Undefined,
- flags: SymbolFlags::None,
- });
- self.tlv_bootstrap = Some(id);
- id
- }
- }
- }
-
- /// Create the `__thread_vars` entry for a TLS variable.
- ///
- /// The symbol given by `symbol_id` will be updated to point to this entry.
- ///
- /// A new `SymbolId` will be returned. The caller must update this symbol
- /// to point to the initializer.
- ///
- /// If `symbol_id` is not for a TLS variable, then it is returned unchanged.
- pub(crate) fn macho_add_thread_var(&mut self, symbol_id: SymbolId) -> SymbolId {
- let symbol = self.symbol_mut(symbol_id);
- if symbol.kind != SymbolKind::Tls {
- return symbol_id;
- }
-
- // Create the initializer symbol.
- let mut name = symbol.name.clone();
- name.extend_from_slice(b"$tlv$init");
- let init_symbol_id = self.add_raw_symbol(Symbol {
- name,
- value: 0,
- size: 0,
- kind: SymbolKind::Tls,
- scope: SymbolScope::Compilation,
- weak: false,
- section: SymbolSection::Undefined,
- flags: SymbolFlags::None,
- });
-
- // Add the tlv entry.
- // Three pointers in size:
- // - __tlv_bootstrap - used to make sure support exists
- // - spare pointer - used when mapped by the runtime
- // - pointer to symbol initializer
- let section = self.section_id(StandardSection::TlsVariables);
- let address_size = self.architecture.address_size().unwrap().bytes();
- let size = u64::from(address_size) * 3;
- let data = vec![0; size as usize];
- let offset = self.append_section_data(section, &data, u64::from(address_size));
-
- let tlv_bootstrap = self.macho_tlv_bootstrap();
- self.add_relocation(
- section,
- Relocation {
- offset,
- size: address_size * 8,
- kind: RelocationKind::Absolute,
- encoding: RelocationEncoding::Generic,
- symbol: tlv_bootstrap,
- addend: 0,
- },
- )
- .unwrap();
- self.add_relocation(
- section,
- Relocation {
- offset: offset + u64::from(address_size) * 2,
- size: address_size * 8,
- kind: RelocationKind::Absolute,
- encoding: RelocationEncoding::Generic,
- symbol: init_symbol_id,
- addend: 0,
- },
- )
- .unwrap();
-
- // Update the symbol to point to the tlv.
- let symbol = self.symbol_mut(symbol_id);
- symbol.value = offset;
- symbol.size = size;
- symbol.section = SymbolSection::Section(section);
-
- init_symbol_id
- }
-
- pub(crate) fn macho_fixup_relocation(&mut self, mut relocation: &mut Relocation) -> i64 {
- let constant = match relocation.kind {
- RelocationKind::Relative
- | RelocationKind::GotRelative
- | RelocationKind::PltRelative => relocation.addend + 4,
- _ => relocation.addend,
- };
- relocation.addend -= constant;
- constant
- }
-
- pub(crate) fn macho_write(&self, buffer: &mut dyn WritableBuffer) -> Result<()> {
- let address_size = self.architecture.address_size().unwrap();
- let endian = self.endian;
- let macho32 = MachO32 { endian };
- let macho64 = MachO64 { endian };
- let macho: &dyn MachO = match address_size {
- AddressSize::U8 | AddressSize::U16 | AddressSize::U32 => &macho32,
- AddressSize::U64 => &macho64,
- };
- let pointer_align = address_size.bytes() as usize;
-
- // Calculate offsets of everything, and build strtab.
- let mut offset = 0;
-
- // Calculate size of Mach-O header.
- offset += macho.mach_header_size();
-
- // Calculate size of commands.
- let mut ncmds = 0;
- let command_offset = offset;
-
- // Calculate size of segment command and section headers.
- let segment_command_offset = offset;
- let segment_command_len =
- macho.segment_command_size() + self.sections.len() * macho.section_header_size();
- offset += segment_command_len;
- ncmds += 1;
-
- // Calculate size of symtab command.
- let symtab_command_offset = offset;
- let symtab_command_len = mem::size_of::<macho::SymtabCommand<Endianness>>();
- offset += symtab_command_len;
- ncmds += 1;
-
- let sizeofcmds = offset - command_offset;
-
- // Calculate size of section data.
- let mut segment_file_offset = None;
- let mut section_offsets = vec![SectionOffsets::default(); self.sections.len()];
- let mut address = 0;
- for (index, section) in self.sections.iter().enumerate() {
- section_offsets[index].index = 1 + index;
- if !section.is_bss() {
- let len = section.data.len();
- if len != 0 {
- offset = align(offset, section.align as usize);
- section_offsets[index].offset = offset;
- if segment_file_offset.is_none() {
- segment_file_offset = Some(offset);
- }
- offset += len;
- } else {
- section_offsets[index].offset = offset;
- }
- address = align_u64(address, section.align);
- section_offsets[index].address = address;
- address += section.size;
- }
- }
- for (index, section) in self.sections.iter().enumerate() {
- if section.kind.is_bss() {
- assert!(section.data.is_empty());
- address = align_u64(address, section.align);
- section_offsets[index].address = address;
- address += section.size;
- }
- }
- let segment_file_offset = segment_file_offset.unwrap_or(offset);
- let segment_file_size = offset - segment_file_offset;
- debug_assert!(segment_file_size as u64 <= address);
-
- // Count symbols and add symbol strings to strtab.
- let mut strtab = StringTable::default();
- let mut symbol_offsets = vec![SymbolOffsets::default(); self.symbols.len()];
- let mut nsyms = 0;
- for (index, symbol) in self.symbols.iter().enumerate() {
- // The unified API allows creating symbols that we don't emit, so filter
- // them out here.
- //
- // Since we don't actually emit the symbol kind, we validate it here too.
- match symbol.kind {
- SymbolKind::Text | SymbolKind::Data | SymbolKind::Tls => {}
- SymbolKind::File | SymbolKind::Section => continue,
- SymbolKind::Unknown => {
- if symbol.section != SymbolSection::Undefined {
- return Err(Error(format!(
- "defined symbol `{}` with unknown kind",
- symbol.name().unwrap_or(""),
- )));
- }
- }
- SymbolKind::Null | SymbolKind::Label => {
- return Err(Error(format!(
- "unimplemented symbol `{}` kind {:?}",
- symbol.name().unwrap_or(""),
- symbol.kind
- )));
- }
- }
- symbol_offsets[index].emit = true;
- symbol_offsets[index].index = nsyms;
- nsyms += 1;
- if !symbol.name.is_empty() {
- symbol_offsets[index].str_id = Some(strtab.add(&symbol.name));
- }
- }
-
- // Calculate size of symtab.
- offset = align(offset, pointer_align);
- let symtab_offset = offset;
- let symtab_len = nsyms * macho.nlist_size();
- offset += symtab_len;
-
- // Calculate size of strtab.
- let strtab_offset = offset;
- // Start with null name.
- let mut strtab_data = vec![0];
- strtab.write(1, &mut strtab_data);
- offset += strtab_data.len();
-
- // Calculate size of relocations.
- for (index, section) in self.sections.iter().enumerate() {
- let count = section.relocations.len();
- if count != 0 {
- offset = align(offset, 4);
- section_offsets[index].reloc_offset = offset;
- let len = count * mem::size_of::<macho::Relocation<Endianness>>();
- offset += len;
- }
- }
-
- // Start writing.
- buffer
- .reserve(offset)
- .map_err(|_| Error(String::from("Cannot allocate buffer")))?;
-
- // Write file header.
- let (cputype, cpusubtype) = match self.architecture {
- Architecture::Arm => (macho::CPU_TYPE_ARM, macho::CPU_SUBTYPE_ARM_ALL),
- Architecture::Aarch64 => (macho::CPU_TYPE_ARM64, macho::CPU_SUBTYPE_ARM64_ALL),
- Architecture::I386 => (macho::CPU_TYPE_X86, macho::CPU_SUBTYPE_I386_ALL),
- Architecture::X86_64 => (macho::CPU_TYPE_X86_64, macho::CPU_SUBTYPE_X86_64_ALL),
- _ => {
- return Err(Error(format!(
- "unimplemented architecture {:?}",
- self.architecture
- )));
- }
- };
-
- let flags = match self.flags {
- FileFlags::MachO { flags } => flags,
- _ => 0,
- };
- macho.write_mach_header(
- buffer,
- MachHeader {
- cputype,
- cpusubtype,
- filetype: macho::MH_OBJECT,
- ncmds,
- sizeofcmds: sizeofcmds as u32,
- flags,
- },
- );
-
- // Write segment command.
- debug_assert_eq!(segment_command_offset, buffer.len());
- macho.write_segment_command(
- buffer,
- SegmentCommand {
- cmdsize: segment_command_len as u32,
- segname: [0; 16],
- vmaddr: 0,
- vmsize: address,
- fileoff: segment_file_offset as u64,
- filesize: segment_file_size as u64,
- maxprot: macho::VM_PROT_READ | macho::VM_PROT_WRITE | macho::VM_PROT_EXECUTE,
- initprot: macho::VM_PROT_READ | macho::VM_PROT_WRITE | macho::VM_PROT_EXECUTE,
- nsects: self.sections.len() as u32,
- flags: 0,
- },
- );
-
- // Write section headers.
- for (index, section) in self.sections.iter().enumerate() {
- let mut sectname = [0; 16];
- sectname
- .get_mut(..section.name.len())
- .ok_or_else(|| {
- Error(format!(
- "section name `{}` is too long",
- section.name().unwrap_or(""),
- ))
- })?
- .copy_from_slice(&section.name);
- let mut segname = [0; 16];
- segname
- .get_mut(..section.segment.len())
- .ok_or_else(|| {
- Error(format!(
- "segment name `{}` is too long",
- section.segment().unwrap_or(""),
- ))
- })?
- .copy_from_slice(&section.segment);
- let flags = if let SectionFlags::MachO { flags } = section.flags {
- flags
- } else {
- match section.kind {
- SectionKind::Text => {
- macho::S_ATTR_PURE_INSTRUCTIONS | macho::S_ATTR_SOME_INSTRUCTIONS
- }
- SectionKind::Data => 0,
- SectionKind::ReadOnlyData => 0,
- SectionKind::ReadOnlyString => macho::S_CSTRING_LITERALS,
- SectionKind::UninitializedData | SectionKind::Common => macho::S_ZEROFILL,
- SectionKind::Tls => macho::S_THREAD_LOCAL_REGULAR,
- SectionKind::UninitializedTls => macho::S_THREAD_LOCAL_ZEROFILL,
- SectionKind::TlsVariables => macho::S_THREAD_LOCAL_VARIABLES,
- SectionKind::Debug => macho::S_ATTR_DEBUG,
- SectionKind::OtherString => macho::S_CSTRING_LITERALS,
- SectionKind::Other | SectionKind::Linker | SectionKind::Metadata => 0,
- SectionKind::Note | SectionKind::Unknown | SectionKind::Elf(_) => {
- return Err(Error(format!(
- "unimplemented section `{}` kind {:?}",
- section.name().unwrap_or(""),
- section.kind
- )));
- }
- }
- };
- macho.write_section(
- buffer,
- SectionHeader {
- sectname,
- segname,
- addr: section_offsets[index].address,
- size: section.size,
- offset: section_offsets[index].offset as u32,
- align: section.align.trailing_zeros(),
- reloff: section_offsets[index].reloc_offset as u32,
- nreloc: section.relocations.len() as u32,
- flags,
- },
- );
- }
-
- // Write symtab command.
- debug_assert_eq!(symtab_command_offset, buffer.len());
- let symtab_command = macho::SymtabCommand {
- cmd: U32::new(endian, macho::LC_SYMTAB),
- cmdsize: U32::new(endian, symtab_command_len as u32),
- symoff: U32::new(endian, symtab_offset as u32),
- nsyms: U32::new(endian, nsyms as u32),
- stroff: U32::new(endian, strtab_offset as u32),
- strsize: U32::new(endian, strtab_data.len() as u32),
- };
- buffer.write(&symtab_command);
-
- // Write section data.
- for (index, section) in self.sections.iter().enumerate() {
- let len = section.data.len();
- if len != 0 {
- write_align(buffer, section.align as usize);
- debug_assert_eq!(section_offsets[index].offset, buffer.len());
- buffer.write_bytes(&section.data);
- }
- }
- debug_assert_eq!(segment_file_offset + segment_file_size, buffer.len());
-
- // Write symtab.
- write_align(buffer, pointer_align);
- debug_assert_eq!(symtab_offset, buffer.len());
- for (index, symbol) in self.symbols.iter().enumerate() {
- if !symbol_offsets[index].emit {
- continue;
- }
- // TODO: N_STAB
- let (mut n_type, n_sect) = match symbol.section {
- SymbolSection::Undefined => (macho::N_UNDF | macho::N_EXT, 0),
- SymbolSection::Absolute => (macho::N_ABS, 0),
- SymbolSection::Section(id) => (macho::N_SECT, id.0 + 1),
- SymbolSection::None | SymbolSection::Common => {
- return Err(Error(format!(
- "unimplemented symbol `{}` section {:?}",
- symbol.name().unwrap_or(""),
- symbol.section
- )));
- }
- };
- match symbol.scope {
- SymbolScope::Unknown | SymbolScope::Compilation => {}
- SymbolScope::Linkage => {
- n_type |= macho::N_EXT | macho::N_PEXT;
- }
- SymbolScope::Dynamic => {
- n_type |= macho::N_EXT;
- }
- }
-
- let n_desc = if let SymbolFlags::MachO { n_desc } = symbol.flags {
- n_desc
- } else {
- let mut n_desc = 0;
- if symbol.weak {
- if symbol.is_undefined() {
- n_desc |= macho::N_WEAK_REF;
- } else {
- n_desc |= macho::N_WEAK_DEF;
- }
- }
- n_desc
- };
-
- let n_value = match symbol.section.id() {
- Some(section) => section_offsets[section.0].address + symbol.value,
- None => symbol.value,
- };
-
- let n_strx = symbol_offsets[index]
- .str_id
- .map(|id| strtab.get_offset(id))
- .unwrap_or(0);
-
- macho.write_nlist(
- buffer,
- Nlist {
- n_strx: n_strx as u32,
- n_type,
- n_sect: n_sect as u8,
- n_desc,
- n_value,
- },
- );
- }
-
- // Write strtab.
- debug_assert_eq!(strtab_offset, buffer.len());
- buffer.write_bytes(&strtab_data);
-
- // Write relocations.
- for (index, section) in self.sections.iter().enumerate() {
- if !section.relocations.is_empty() {
- write_align(buffer, 4);
- debug_assert_eq!(section_offsets[index].reloc_offset, buffer.len());
- for reloc in &section.relocations {
- let r_extern;
- let r_symbolnum;
- let symbol = &self.symbols[reloc.symbol.0];
- if symbol.kind == SymbolKind::Section {
- r_symbolnum = section_offsets[symbol.section.id().unwrap().0].index as u32;
- r_extern = false;
- } else {
- r_symbolnum = symbol_offsets[reloc.symbol.0].index as u32;
- r_extern = true;
- }
- let r_length = match reloc.size {
- 8 => 0,
- 16 => 1,
- 32 => 2,
- 64 => 3,
- _ => return Err(Error(format!("unimplemented reloc size {:?}", reloc))),
- };
- let (r_pcrel, r_type) = match self.architecture {
- Architecture::I386 => match reloc.kind {
- RelocationKind::Absolute => (false, macho::GENERIC_RELOC_VANILLA),
- _ => {
- return Err(Error(format!("unimplemented relocation {:?}", reloc)));
- }
- },
- Architecture::X86_64 => match (reloc.kind, reloc.encoding, reloc.addend) {
- (RelocationKind::Absolute, RelocationEncoding::Generic, 0) => {
- (false, macho::X86_64_RELOC_UNSIGNED)
- }
- (RelocationKind::Relative, RelocationEncoding::Generic, -4) => {
- (true, macho::X86_64_RELOC_SIGNED)
- }
- (RelocationKind::Relative, RelocationEncoding::X86RipRelative, -4) => {
- (true, macho::X86_64_RELOC_SIGNED)
- }
- (RelocationKind::Relative, RelocationEncoding::X86Branch, -4) => {
- (true, macho::X86_64_RELOC_BRANCH)
- }
- (RelocationKind::PltRelative, RelocationEncoding::X86Branch, -4) => {
- (true, macho::X86_64_RELOC_BRANCH)
- }
- (RelocationKind::GotRelative, RelocationEncoding::Generic, -4) => {
- (true, macho::X86_64_RELOC_GOT)
- }
- (
- RelocationKind::GotRelative,
- RelocationEncoding::X86RipRelativeMovq,
- -4,
- ) => (true, macho::X86_64_RELOC_GOT_LOAD),
- (RelocationKind::MachO { value, relative }, _, _) => (relative, value),
- _ => {
- return Err(Error(format!("unimplemented relocation {:?}", reloc)));
- }
- },
- _ => {
- return Err(Error(format!(
- "unimplemented architecture {:?}",
- self.architecture
- )));
- }
- };
- let reloc_info = macho::RelocationInfo {
- r_address: reloc.offset as u32,
- r_symbolnum,
- r_pcrel,
- r_length,
- r_extern,
- r_type,
- };
- buffer.write(&reloc_info.relocation(endian));
- }
- }
- }
-
- debug_assert_eq!(offset, buffer.len());
-
- Ok(())
- }
-}
-
-struct MachHeader {
- cputype: u32,
- cpusubtype: u32,
- filetype: u32,
- ncmds: u32,
- sizeofcmds: u32,
- flags: u32,
-}
-
-struct SegmentCommand {
- cmdsize: u32,
- segname: [u8; 16],
- vmaddr: u64,
- vmsize: u64,
- fileoff: u64,
- filesize: u64,
- maxprot: u32,
- initprot: u32,
- nsects: u32,
- flags: u32,
-}
-
-pub struct SectionHeader {
- sectname: [u8; 16],
- segname: [u8; 16],
- addr: u64,
- size: u64,
- offset: u32,
- align: u32,
- reloff: u32,
- nreloc: u32,
- flags: u32,
-}
-
-struct Nlist {
- n_strx: u32,
- n_type: u8,
- n_sect: u8,
- n_desc: u16,
- n_value: u64,
-}
-
-trait MachO {
- fn mach_header_size(&self) -> usize;
- fn segment_command_size(&self) -> usize;
- fn section_header_size(&self) -> usize;
- fn nlist_size(&self) -> usize;
- fn write_mach_header(&self, buffer: &mut dyn WritableBuffer, section: MachHeader);
- fn write_segment_command(&self, buffer: &mut dyn WritableBuffer, segment: SegmentCommand);
- fn write_section(&self, buffer: &mut dyn WritableBuffer, section: SectionHeader);
- fn write_nlist(&self, buffer: &mut dyn WritableBuffer, nlist: Nlist);
-}
-
-struct MachO32<E> {
- endian: E,
-}
-
-impl<E: Endian> MachO for MachO32<E> {
- fn mach_header_size(&self) -> usize {
- mem::size_of::<macho::MachHeader32<E>>()
- }
-
- fn segment_command_size(&self) -> usize {
- mem::size_of::<macho::SegmentCommand32<E>>()
- }
-
- fn section_header_size(&self) -> usize {
- mem::size_of::<macho::Section32<E>>()
- }
-
- fn nlist_size(&self) -> usize {
- mem::size_of::<macho::Nlist32<E>>()
- }
-
- fn write_mach_header(&self, buffer: &mut dyn WritableBuffer, header: MachHeader) {
- let endian = self.endian;
- let magic = if endian.is_big_endian() {
- macho::MH_MAGIC
- } else {
- macho::MH_CIGAM
- };
- let header = macho::MachHeader32 {
- magic: U32::new(BigEndian, magic),
- cputype: U32::new(endian, header.cputype),
- cpusubtype: U32::new(endian, header.cpusubtype),
- filetype: U32::new(endian, header.filetype),
- ncmds: U32::new(endian, header.ncmds),
- sizeofcmds: U32::new(endian, header.sizeofcmds),
- flags: U32::new(endian, header.flags),
- };
- buffer.write(&header);
- }
-
- fn write_segment_command(&self, buffer: &mut dyn WritableBuffer, segment: SegmentCommand) {
- let endian = self.endian;
- let segment = macho::SegmentCommand32 {
- cmd: U32::new(endian, macho::LC_SEGMENT),
- cmdsize: U32::new(endian, segment.cmdsize),
- segname: segment.segname,
- vmaddr: U32::new(endian, segment.vmaddr as u32),
- vmsize: U32::new(endian, segment.vmsize as u32),
- fileoff: U32::new(endian, segment.fileoff as u32),
- filesize: U32::new(endian, segment.filesize as u32),
- maxprot: U32::new(endian, segment.maxprot),
- initprot: U32::new(endian, segment.initprot),
- nsects: U32::new(endian, segment.nsects),
- flags: U32::new(endian, segment.flags),
- };
- buffer.write(&segment);
- }
-
- fn write_section(&self, buffer: &mut dyn WritableBuffer, section: SectionHeader) {
- let endian = self.endian;
- let section = macho::Section32 {
- sectname: section.sectname,
- segname: section.segname,
- addr: U32::new(endian, section.addr as u32),
- size: U32::new(endian, section.size as u32),
- offset: U32::new(endian, section.offset),
- align: U32::new(endian, section.align),
- reloff: U32::new(endian, section.reloff),
- nreloc: U32::new(endian, section.nreloc),
- flags: U32::new(endian, section.flags),
- reserved1: U32::default(),
- reserved2: U32::default(),
- };
- buffer.write(&section);
- }
-
- fn write_nlist(&self, buffer: &mut dyn WritableBuffer, nlist: Nlist) {
- let endian = self.endian;
- let nlist = macho::Nlist32 {
- n_strx: U32::new(endian, nlist.n_strx),
- n_type: nlist.n_type,
- n_sect: nlist.n_sect,
- n_desc: U16::new(endian, nlist.n_desc),
- n_value: U32::new(endian, nlist.n_value as u32),
- };
- buffer.write(&nlist);
- }
-}
-
-struct MachO64<E> {
- endian: E,
-}
-
-impl<E: Endian> MachO for MachO64<E> {
- fn mach_header_size(&self) -> usize {
- mem::size_of::<macho::MachHeader64<E>>()
- }
-
- fn segment_command_size(&self) -> usize {
- mem::size_of::<macho::SegmentCommand64<E>>()
- }
-
- fn section_header_size(&self) -> usize {
- mem::size_of::<macho::Section64<E>>()
- }
-
- fn nlist_size(&self) -> usize {
- mem::size_of::<macho::Nlist64<E>>()
- }
-
- fn write_mach_header(&self, buffer: &mut dyn WritableBuffer, header: MachHeader) {
- let endian = self.endian;
- let magic = if endian.is_big_endian() {
- macho::MH_MAGIC_64
- } else {
- macho::MH_CIGAM_64
- };
- let header = macho::MachHeader64 {
- magic: U32::new(BigEndian, magic),
- cputype: U32::new(endian, header.cputype),
- cpusubtype: U32::new(endian, header.cpusubtype),
- filetype: U32::new(endian, header.filetype),
- ncmds: U32::new(endian, header.ncmds),
- sizeofcmds: U32::new(endian, header.sizeofcmds),
- flags: U32::new(endian, header.flags),
- reserved: U32::default(),
- };
- buffer.write(&header);
- }
-
- fn write_segment_command(&self, buffer: &mut dyn WritableBuffer, segment: SegmentCommand) {
- let endian = self.endian;
- let segment = macho::SegmentCommand64 {
- cmd: U32::new(endian, macho::LC_SEGMENT_64),
- cmdsize: U32::new(endian, segment.cmdsize),
- segname: segment.segname,
- vmaddr: U64::new(endian, segment.vmaddr),
- vmsize: U64::new(endian, segment.vmsize),
- fileoff: U64::new(endian, segment.fileoff),
- filesize: U64::new(endian, segment.filesize),
- maxprot: U32::new(endian, segment.maxprot),
- initprot: U32::new(endian, segment.initprot),
- nsects: U32::new(endian, segment.nsects),
- flags: U32::new(endian, segment.flags),
- };
- buffer.write(&segment);
- }
-
- fn write_section(&self, buffer: &mut dyn WritableBuffer, section: SectionHeader) {
- let endian = self.endian;
- let section = macho::Section64 {
- sectname: section.sectname,
- segname: section.segname,
- addr: U64::new(endian, section.addr),
- size: U64::new(endian, section.size),
- offset: U32::new(endian, section.offset),
- align: U32::new(endian, section.align),
- reloff: U32::new(endian, section.reloff),
- nreloc: U32::new(endian, section.nreloc),
- flags: U32::new(endian, section.flags),
- reserved1: U32::default(),
- reserved2: U32::default(),
- reserved3: U32::default(),
- };
- buffer.write(&section);
- }
-
- fn write_nlist(&self, buffer: &mut dyn WritableBuffer, nlist: Nlist) {
- let endian = self.endian;
- let nlist = macho::Nlist64 {
- n_strx: U32::new(endian, nlist.n_strx),
- n_type: nlist.n_type,
- n_sect: nlist.n_sect,
- n_desc: U16::new(endian, nlist.n_desc),
- n_value: U64Bytes::new(endian, nlist.n_value),
- };
- buffer.write(&nlist);
- }
-}
diff --git a/vendor/object-0.26.2/src/write/mod.rs b/vendor/object-0.26.2/src/write/mod.rs
deleted file mode 100644
index 747e2a02e..000000000
--- a/vendor/object-0.26.2/src/write/mod.rs
+++ /dev/null
@@ -1,858 +0,0 @@
-//! Interface for writing object files.
-
-use std::collections::HashMap;
-use std::string::String;
-use std::vec::Vec;
-use std::{error, fmt, result, str};
-
-use crate::endian::{Endianness, U32, U64};
-use crate::{
- Architecture, BinaryFormat, ComdatKind, FileFlags, RelocationEncoding, RelocationKind,
- SectionFlags, SectionKind, SymbolFlags, SymbolKind, SymbolScope,
-};
-
-#[cfg(feature = "coff")]
-mod coff;
-#[cfg(feature = "elf")]
-mod elf;
-#[cfg(feature = "macho")]
-mod macho;
-mod string;
-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)
- }
-}
-
-impl error::Error for Error {}
-
-/// The result type used within the write module.
-pub type Result<T> = result::Result<T, Error>;
-
-/// A writable object file.
-#[derive(Debug)]
-pub struct Object {
- format: BinaryFormat,
- architecture: Architecture,
- endian: Endianness,
- sections: Vec<Section>,
- 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>,
-}
-
-impl Object {
- /// Create an empty object file.
- pub fn new(format: BinaryFormat, architecture: Architecture, endian: Endianness) -> Object {
- Object {
- format,
- architecture,
- 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,
- }
- }
-
- /// 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 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 {
- &self.sections[section.0]
- }
-
- /// Mutably get the section with the given `SectionId`.
- #[inline]
- pub fn section_mut(&mut self, section: SectionId) -> &mut Section {
- &mut self.sections[section.0]
- }
-
- /// 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) = self.section_info(section);
- self.add_section(segment.to_vec(), name.to_vec(), kind)
- })
- }
-
- /// 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: Vec::new(),
- 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) = 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) {
- 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),
- _ => 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) = self.subsection_info(section, name);
- self.add_section(segment.to_vec(), name, kind)
- };
- 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 => 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) {
- let (segment, section, kind) = self.section_info(section);
- let name = self.subsection_name(section, value);
- (segment, name, kind)
- }
-
- #[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),
- _ => 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 = &mut self.sections[section.0].data;
- 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 `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),
- _ => 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,
-}
-
-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 | StandardSection::ReadOnlyDataWithRel => {
- SectionKind::ReadOnlyData
- }
- StandardSection::ReadOnlyString => SectionKind::ReadOnlyString,
- StandardSection::UninitializedData => SectionKind::UninitializedData,
- StandardSection::Tls => SectionKind::Tls,
- StandardSection::UninitializedTls => SectionKind::UninitializedTls,
- StandardSection::TlsVariables => SectionKind::TlsVariables,
- StandardSection::Common => SectionKind::Common,
- }
- }
-
- // 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,
- ]
- }
-}
-
-/// 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 {
- segment: Vec<u8>,
- name: Vec<u8>,
- kind: SectionKind,
- size: u64,
- align: u64,
- data: Vec<u8>,
- relocations: Vec<Relocation>,
- symbol: Option<SymbolId>,
- /// Section flags that are specific to each file format.
- pub flags: SectionFlags,
-}
-
-impl Section {
- /// 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(&mut self, data: Vec<u8>, align: u64) {
- debug_assert!(!self.is_bss());
- debug_assert_eq!(align & (align - 1), 0);
- debug_assert!(self.data.is_empty());
- self.size = data.len() as u64;
- self.data = data;
- self.align = align;
- }
-
- /// Append data to a section.
- ///
- /// Must not be called for sections that contain uninitialized data.
- pub fn append_data(&mut self, 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 mut offset = self.data.len();
- if offset & (align - 1) != 0 {
- offset += align - (offset & (align - 1));
- self.data.resize(offset, 0);
- }
- self.data.extend_from_slice(data);
- self.size = self.data.len() as u64;
- offset as u64
- }
-
- /// Append unitialized 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 as u64
- }
-}
-
-/// 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>,
-}
-
-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,
-}
-
-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,
- _ => 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 => None,
- Mangling::CoffI386 | Mangling::MachO => Some(b'_'),
- }
- }
-}
diff --git a/vendor/object-0.26.2/src/write/string.rs b/vendor/object-0.26.2/src/write/string.rs
deleted file mode 100644
index c27934e60..000000000
--- a/vendor/object-0.26.2/src/write/string.rs
+++ /dev/null
@@ -1,139 +0,0 @@
-use indexmap::IndexSet;
-use std::vec::Vec;
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub(crate) struct StringId(usize);
-
-#[derive(Debug, Default)]
-pub(crate) struct StringTable<'a> {
- strings: IndexSet<&'a [u8]>,
- offsets: Vec<usize>,
-}
-
-impl<'a> StringTable<'a> {
- /// Add a string to the string table.
- ///
- /// Panics if the string table has already been written, or
- /// if the string contains a null byte.
- pub fn add(&mut self, string: &'a [u8]) -> StringId {
- assert!(self.offsets.is_empty());
- assert!(!string.contains(&0));
- let id = self.strings.insert_full(string).0;
- StringId(id)
- }
-
- /// Return the offset of the given string.
- ///
- /// Panics if the string table has not been written, or
- /// if the string is not in the string table.
- pub fn get_offset(&self, id: StringId) -> usize {
- self.offsets[id.0]
- }
-
- /// Append the string table to the given `Vec`, and
- /// calculate the list of string offsets.
- ///
- /// `base` is the initial string table offset. For example,
- /// this should be 1 for ELF, to account for the initial
- /// null byte (which must have been written by the caller).
- pub fn write(&mut self, base: usize, w: &mut Vec<u8>) {
- assert!(self.offsets.is_empty());
-
- let mut ids: Vec<_> = (0..self.strings.len()).collect();
- sort(&mut ids, 1, &self.strings);
-
- self.offsets = vec![0; ids.len()];
- let mut offset = base;
- let mut previous = &[][..];
- for id in ids {
- let string = self.strings.get_index(id).unwrap();
- if previous.ends_with(string) {
- self.offsets[id] = offset - string.len() - 1;
- } else {
- self.offsets[id] = offset;
- w.extend_from_slice(string);
- w.push(0);
- offset += string.len() + 1;
- previous = string;
- }
- }
- }
-}
-
-// Multi-key quicksort.
-//
-// Ordering is such that if a string is a suffix of at least one other string,
-// then it is placed immediately after one of those strings. That is:
-// - comparison starts at the end of the string
-// - shorter strings come later
-//
-// Based on the implementation in LLVM.
-fn sort(mut ids: &mut [usize], mut pos: usize, strings: &IndexSet<&[u8]>) {
- loop {
- if ids.len() <= 1 {
- return;
- }
-
- let pivot = byte(ids[0], pos, strings);
- let mut lower = 0;
- let mut upper = ids.len();
- let mut i = 1;
- while i < upper {
- let b = byte(ids[i], pos, strings);
- if b > pivot {
- ids.swap(lower, i);
- lower += 1;
- i += 1;
- } else if b < pivot {
- upper -= 1;
- ids.swap(upper, i);
- } else {
- i += 1;
- }
- }
-
- sort(&mut ids[..lower], pos, strings);
- sort(&mut ids[upper..], pos, strings);
-
- if pivot == 0 {
- return;
- }
- ids = &mut ids[lower..upper];
- pos += 1;
- }
-}
-
-fn byte(id: usize, pos: usize, strings: &IndexSet<&[u8]>) -> u8 {
- let string = strings.get_index(id).unwrap();
- let len = string.len();
- if len >= pos {
- string[len - pos]
- } else {
- // We know the strings don't contain null bytes.
- 0
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn string_table() {
- let mut table = StringTable::default();
- let id0 = table.add(b"");
- let id1 = table.add(b"foo");
- let id2 = table.add(b"bar");
- let id3 = table.add(b"foobar");
-
- let mut data = Vec::new();
- data.push(0);
- table.write(1, &mut data);
- assert_eq!(data, b"\0foobar\0foo\0");
-
- assert_eq!(table.get_offset(id0), 11);
- assert_eq!(table.get_offset(id1), 8);
- assert_eq!(table.get_offset(id2), 4);
- assert_eq!(table.get_offset(id3), 1);
- }
-}
diff --git a/vendor/object-0.26.2/src/write/util.rs b/vendor/object-0.26.2/src/write/util.rs
deleted file mode 100644
index bb6b8597b..000000000
--- a/vendor/object-0.26.2/src/write/util.rs
+++ /dev/null
@@ -1,129 +0,0 @@
-use std::vec::Vec;
-
-use crate::pod::{bytes_of, bytes_of_slice, Pod};
-
-/// Trait for writable buffer.
-#[allow(clippy::len_without_is_empty)]
-pub trait WritableBuffer {
- /// Returns position/offset for data to be written at.
- fn len(&self) -> usize;
-
- /// Reserves specified number of bytes in the buffer.
- fn reserve(&mut self, additional: usize) -> Result<(), ()>;
-
- /// Writes the specified value at the end of the buffer
- /// until the buffer has the specified length.
- fn resize(&mut self, new_len: usize, value: u8);
-
- /// Writes the specified slice of bytes at the end of the buffer.
- fn write_bytes(&mut self, val: &[u8]);
-
- /// Writes the specified `Pod` type at the end of the buffer.
- fn write_pod<T: Pod>(&mut self, val: &T)
- where
- Self: Sized,
- {
- self.write_bytes(bytes_of(val))
- }
-
- /// Writes the specified `Pod` slice at the end of the buffer.
- fn write_pod_slice<T: Pod>(&mut self, val: &[T])
- where
- Self: Sized,
- {
- self.write_bytes(bytes_of_slice(val))
- }
-}
-
-impl<'a> dyn WritableBuffer + 'a {
- /// Writes the specified `Pod` type at the end of the buffer.
- pub fn write<T: Pod>(&mut self, val: &T) {
- self.write_bytes(bytes_of(val))
- }
-
- /// Writes the specified `Pod` slice at the end of the buffer.
- pub fn write_slice<T: Pod>(&mut self, val: &[T]) {
- self.write_bytes(bytes_of_slice(val))
- }
-}
-
-impl WritableBuffer for Vec<u8> {
- #[inline]
- fn len(&self) -> usize {
- self.len()
- }
-
- #[inline]
- fn reserve(&mut self, additional: usize) -> Result<(), ()> {
- self.reserve(additional);
- Ok(())
- }
-
- #[inline]
- fn resize(&mut self, new_len: usize, value: u8) {
- self.resize(new_len, value);
- }
-
- #[inline]
- fn write_bytes(&mut self, val: &[u8]) {
- self.extend_from_slice(val)
- }
-}
-
-/// A trait for mutable byte slices.
-///
-/// It provides convenience methods for `Pod` types.
-pub(crate) trait BytesMut {
- fn write_at<T: Pod>(self, offset: usize, val: &T) -> Result<(), ()>;
-}
-
-impl<'a> BytesMut for &'a mut [u8] {
- #[inline]
- fn write_at<T: Pod>(self, offset: usize, val: &T) -> Result<(), ()> {
- let src = bytes_of(val);
- let dest = self.get_mut(offset..).ok_or(())?;
- let dest = dest.get_mut(..src.len()).ok_or(())?;
- dest.copy_from_slice(src);
- Ok(())
- }
-}
-
-pub(crate) fn align(offset: usize, size: usize) -> usize {
- (offset + (size - 1)) & !(size - 1)
-}
-
-#[allow(dead_code)]
-pub(crate) fn align_u64(offset: u64, size: u64) -> u64 {
- (offset + (size - 1)) & !(size - 1)
-}
-
-pub(crate) fn write_align(buffer: &mut dyn WritableBuffer, size: usize) {
- let new_len = align(buffer.len(), size);
- buffer.resize(new_len, 0);
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn bytes_mut() {
- let data = vec![0x01, 0x23, 0x45, 0x67];
-
- let mut bytes = data.clone();
- bytes.extend_from_slice(bytes_of(&u16::to_be(0x89ab)));
- assert_eq!(bytes, [0x01, 0x23, 0x45, 0x67, 0x89, 0xab]);
-
- let mut bytes = data.clone();
- assert_eq!(bytes.write_at(0, &u16::to_be(0x89ab)), Ok(()));
- assert_eq!(bytes, [0x89, 0xab, 0x45, 0x67]);
-
- let mut bytes = data.clone();
- assert_eq!(bytes.write_at(2, &u16::to_be(0x89ab)), Ok(()));
- assert_eq!(bytes, [0x01, 0x23, 0x89, 0xab]);
-
- assert_eq!(bytes.write_at(3, &u16::to_be(0x89ab)), Err(()));
- assert_eq!(bytes.write_at(4, &u16::to_be(0x89ab)), Err(()));
- assert_eq!(vec![].write_at(0, &u32::to_be(0x89ab)), Err(()));
- }
-}