diff options
Diffstat (limited to 'vendor/object-0.26.2/src/write')
-rw-r--r-- | vendor/object-0.26.2/src/write/coff.rs | 626 | ||||
-rw-r--r-- | vendor/object-0.26.2/src/write/elf.rs | 1314 | ||||
-rw-r--r-- | vendor/object-0.26.2/src/write/macho.rs | 844 | ||||
-rw-r--r-- | vendor/object-0.26.2/src/write/mod.rs | 858 | ||||
-rw-r--r-- | vendor/object-0.26.2/src/write/string.rs | 139 | ||||
-rw-r--r-- | vendor/object-0.26.2/src/write/util.rs | 129 |
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(§ion.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(§ion.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(§ion.data); - } - - if !section.relocations.is_empty() { - debug_assert_eq!(section_offsets[index].reloc_offset, buffer.len()); - for reloc in §ion.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(§ion.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(§ion.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(§ion.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 §ion.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(§ion); - } - - 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(§ion); - } - - 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(§ion.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(§ion.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(§ion.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 §ion.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(§ion); - } - - 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(§ion); - } - - 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(§ion) - .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(())); - } -} |