diff options
Diffstat (limited to 'vendor/object/src/write/elf')
-rw-r--r-- | vendor/object/src/write/elf/mod.rs | 9 | ||||
-rw-r--r-- | vendor/object/src/write/elf/object.rs | 907 | ||||
-rw-r--r-- | vendor/object/src/write/elf/writer.rs | 2143 |
3 files changed, 0 insertions, 3059 deletions
diff --git a/vendor/object/src/write/elf/mod.rs b/vendor/object/src/write/elf/mod.rs deleted file mode 100644 index 3a4f371..0000000 --- a/vendor/object/src/write/elf/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -//! Support for writing ELF files. -//! -//! Provides [`Writer`] for low level writing of ELF files. -//! This is also used to provide ELF support for [`write::Object`](crate::write::Object). - -mod object; - -mod writer; -pub use writer::*; diff --git a/vendor/object/src/write/elf/object.rs b/vendor/object/src/write/elf/object.rs deleted file mode 100644 index 5d7a93e..0000000 --- a/vendor/object/src/write/elf/object.rs +++ /dev/null @@ -1,907 +0,0 @@ -use alloc::vec::Vec; - -use crate::write::elf::writer::*; -use crate::write::string::StringId; -use crate::write::*; -use crate::AddressSize; -use crate::{elf, pod}; - -#[derive(Clone, Copy)] -struct ComdatOffsets { - offset: usize, - str_id: StringId, -} - -#[derive(Clone, Copy)] -struct SectionOffsets { - index: SectionIndex, - offset: usize, - str_id: StringId, - reloc_offset: usize, - reloc_str_id: Option<StringId>, -} - -#[derive(Default, Clone, Copy)] -struct SymbolOffsets { - index: SymbolIndex, - str_id: Option<StringId>, -} - -// Public methods. -impl<'a> Object<'a> { - /// Add a property with a u32 value to the ELF ".note.gnu.property" section. - /// - /// Requires `feature = "elf"`. - pub fn add_elf_gnu_property_u32(&mut self, property: u32, value: u32) { - if self.format != BinaryFormat::Elf { - return; - } - - let align = if self.elf_is_64() { 8 } else { 4 }; - let mut data = Vec::with_capacity(32); - let n_name = b"GNU\0"; - data.extend_from_slice(pod::bytes_of(&elf::NoteHeader32 { - n_namesz: U32::new(self.endian, n_name.len() as u32), - n_descsz: U32::new(self.endian, util::align(3 * 4, align) as u32), - n_type: U32::new(self.endian, elf::NT_GNU_PROPERTY_TYPE_0), - })); - data.extend_from_slice(n_name); - // This happens to already be aligned correctly. - debug_assert_eq!(util::align(data.len(), align), data.len()); - data.extend_from_slice(pod::bytes_of(&U32::new(self.endian, property))); - // Value size - data.extend_from_slice(pod::bytes_of(&U32::new(self.endian, 4))); - data.extend_from_slice(pod::bytes_of(&U32::new(self.endian, value))); - util::write_align(&mut data, align); - - let section = self.section_id(StandardSection::GnuProperty); - self.append_section_data(section, &data, align as u64); - } -} - -// Private methods. -impl<'a> Object<'a> { - pub(crate) fn elf_section_info( - &self, - section: StandardSection, - ) -> (&'static [u8], &'static [u8], SectionKind, SectionFlags) { - match section { - StandardSection::Text => (&[], &b".text"[..], SectionKind::Text, SectionFlags::None), - StandardSection::Data => (&[], &b".data"[..], SectionKind::Data, SectionFlags::None), - StandardSection::ReadOnlyData | StandardSection::ReadOnlyString => ( - &[], - &b".rodata"[..], - SectionKind::ReadOnlyData, - SectionFlags::None, - ), - StandardSection::ReadOnlyDataWithRel => ( - &[], - b".data.rel.ro", - SectionKind::ReadOnlyDataWithRel, - SectionFlags::None, - ), - StandardSection::UninitializedData => ( - &[], - &b".bss"[..], - SectionKind::UninitializedData, - SectionFlags::None, - ), - StandardSection::Tls => (&[], &b".tdata"[..], SectionKind::Tls, SectionFlags::None), - StandardSection::UninitializedTls => ( - &[], - &b".tbss"[..], - SectionKind::UninitializedTls, - SectionFlags::None, - ), - StandardSection::TlsVariables => { - // Unsupported section. - (&[], &[], SectionKind::TlsVariables, SectionFlags::None) - } - StandardSection::Common => { - // Unsupported section. - (&[], &[], SectionKind::Common, SectionFlags::None) - } - StandardSection::GnuProperty => ( - &[], - &b".note.gnu.property"[..], - SectionKind::Note, - SectionFlags::Elf { - sh_flags: u64::from(elf::SHF_ALLOC), - }, - ), - } - } - - 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::Aarch64_Ilp32 => true, - Architecture::Arm => false, - Architecture::Avr => true, - Architecture::Bpf => false, - Architecture::Csky => true, - Architecture::I386 => false, - Architecture::X86_64 => true, - Architecture::X86_64_X32 => true, - Architecture::Hexagon => true, - Architecture::LoongArch64 => 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::Sbf => false, - Architecture::Sharc => true, - Architecture::Sparc64 => true, - Architecture::Xtensa => true, - _ => { - return Err(Error(format!( - "unimplemented architecture {:?}", - self.architecture - ))); - } - }) - } - - pub(crate) fn elf_fixup_relocation(&mut self, relocation: &mut Relocation) -> Result<i64> { - // 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_is_64(&self) -> bool { - match self.architecture.address_size().unwrap() { - AddressSize::U8 | AddressSize::U16 | AddressSize::U32 => false, - AddressSize::U64 => true, - } - } - - pub(crate) fn elf_write(&self, buffer: &mut dyn WritableBuffer) -> Result<()> { - // Create reloc section header names so we can reference them. - let is_rela = self.elf_has_relocation_addend()?; - let reloc_names: Vec<_> = self - .sections - .iter() - .map(|section| { - let mut reloc_name = Vec::with_capacity( - if is_rela { ".rela".len() } else { ".rel".len() } + section.name.len(), - ); - 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(); - - // Start calculating offsets of everything. - let mut writer = Writer::new(self.endian, self.elf_is_64(), buffer); - writer.reserve_file_header(); - - // Calculate size of section data. - let mut comdat_offsets = Vec::with_capacity(self.comdats.len()); - for comdat in &self.comdats { - if comdat.kind != ComdatKind::Any { - return Err(Error(format!( - "unsupported COMDAT symbol `{}` kind {:?}", - self.symbols[comdat.symbol.0].name().unwrap_or(""), - comdat.kind - ))); - } - - writer.reserve_section_index(); - let offset = writer.reserve_comdat(comdat.sections.len()); - let str_id = writer.add_section_name(b".group"); - comdat_offsets.push(ComdatOffsets { offset, str_id }); - } - let mut section_offsets = Vec::with_capacity(self.sections.len()); - for (section, reloc_name) in self.sections.iter().zip(reloc_names.iter()) { - let index = writer.reserve_section_index(); - let offset = writer.reserve(section.data.len(), section.align as usize); - let str_id = writer.add_section_name(§ion.name); - let mut reloc_str_id = None; - if !section.relocations.is_empty() { - writer.reserve_section_index(); - reloc_str_id = Some(writer.add_section_name(reloc_name)); - } - section_offsets.push(SectionOffsets { - index, - offset, - str_id, - // Relocation data is reserved later. - reloc_offset: 0, - reloc_str_id, - }); - } - - // Calculate index of symbols and add symbol strings to strtab. - let mut symbol_offsets = vec![SymbolOffsets::default(); self.symbols.len()]; - writer.reserve_null_symbol_index(); - // Local symbols must come before global. - for (index, symbol) in self.symbols.iter().enumerate() { - if symbol.is_local() { - let section_index = symbol.section.id().map(|s| section_offsets[s.0].index); - symbol_offsets[index].index = writer.reserve_symbol_index(section_index); - } - } - let symtab_num_local = writer.symbol_count(); - for (index, symbol) in self.symbols.iter().enumerate() { - if !symbol.is_local() { - let section_index = symbol.section.id().map(|s| section_offsets[s.0].index); - symbol_offsets[index].index = writer.reserve_symbol_index(section_index); - } - } - for (index, symbol) in self.symbols.iter().enumerate() { - if symbol.kind != SymbolKind::Section && !symbol.name.is_empty() { - symbol_offsets[index].str_id = Some(writer.add_string(&symbol.name)); - } - } - - // Calculate size of symbols. - writer.reserve_symtab_section_index(); - writer.reserve_symtab(); - if writer.symtab_shndx_needed() { - writer.reserve_symtab_shndx_section_index(); - } - writer.reserve_symtab_shndx(); - writer.reserve_strtab_section_index(); - writer.reserve_strtab(); - - // Calculate size of relocations. - for (index, section) in self.sections.iter().enumerate() { - let count = section.relocations.len(); - if count != 0 { - section_offsets[index].reloc_offset = writer.reserve_relocations(count, is_rela); - } - } - - // Calculate size of section headers. - writer.reserve_shstrtab_section_index(); - writer.reserve_shstrtab(); - writer.reserve_section_headers(); - - // Start writing. - let e_type = elf::ET_REL; - let e_machine = match (self.architecture, self.sub_architecture) { - (Architecture::Aarch64, None) => elf::EM_AARCH64, - (Architecture::Aarch64_Ilp32, None) => elf::EM_AARCH64, - (Architecture::Arm, None) => elf::EM_ARM, - (Architecture::Avr, None) => elf::EM_AVR, - (Architecture::Bpf, None) => elf::EM_BPF, - (Architecture::Csky, None) => elf::EM_CSKY, - (Architecture::I386, None) => elf::EM_386, - (Architecture::X86_64, None) => elf::EM_X86_64, - (Architecture::X86_64_X32, None) => elf::EM_X86_64, - (Architecture::Hexagon, None) => elf::EM_HEXAGON, - (Architecture::LoongArch64, None) => elf::EM_LOONGARCH, - (Architecture::Mips, None) => elf::EM_MIPS, - (Architecture::Mips64, None) => elf::EM_MIPS, - (Architecture::Msp430, None) => elf::EM_MSP430, - (Architecture::PowerPc, None) => elf::EM_PPC, - (Architecture::PowerPc64, None) => elf::EM_PPC64, - (Architecture::Riscv32, None) => elf::EM_RISCV, - (Architecture::Riscv64, None) => elf::EM_RISCV, - (Architecture::S390x, None) => elf::EM_S390, - (Architecture::Sbf, None) => elf::EM_SBF, - (Architecture::Sharc, None) => elf::EM_SHARC, - (Architecture::Sparc64, None) => elf::EM_SPARCV9, - (Architecture::Xtensa, None) => elf::EM_XTENSA, - _ => { - return Err(Error(format!( - "unimplemented architecture {:?} with sub-architecture {:?}", - self.architecture, self.sub_architecture - ))); - } - }; - let (os_abi, abi_version, e_flags) = if let FileFlags::Elf { - os_abi, - abi_version, - e_flags, - } = self.flags - { - (os_abi, abi_version, e_flags) - } else { - (elf::ELFOSABI_NONE, 0, 0) - }; - writer.write_file_header(&FileHeader { - os_abi, - abi_version, - e_type, - e_machine, - e_entry: 0, - e_flags, - })?; - - // Write section data. - for comdat in &self.comdats { - writer.write_comdat_header(); - for section in &comdat.sections { - writer.write_comdat_entry(section_offsets[section.0].index); - } - } - for (index, section) in self.sections.iter().enumerate() { - writer.write_align(section.align as usize); - debug_assert_eq!(section_offsets[index].offset, writer.len()); - writer.write(§ion.data); - } - - // Write symbols. - writer.write_null_symbol(); - 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, section) = match symbol.section { - SymbolSection::None => { - debug_assert_eq!(symbol.kind, SymbolKind::File); - (elf::SHN_ABS, None) - } - SymbolSection::Undefined => (elf::SHN_UNDEF, None), - SymbolSection::Absolute => (elf::SHN_ABS, None), - SymbolSection::Common => (elf::SHN_COMMON, None), - SymbolSection::Section(id) => (0, Some(section_offsets[id.0].index)), - }; - writer.write_symbol(&Sym { - name: symbol_offsets[index].str_id, - section, - st_info, - st_other, - st_shndx, - st_value: symbol.value, - st_size: symbol.size, - }); - 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)?; - } - } - writer.write_symtab_shndx(); - writer.write_strtab(); - - // Write relocations. - for (index, section) in self.sections.iter().enumerate() { - if !section.relocations.is_empty() { - writer.write_align_relocation(); - debug_assert_eq!(section_offsets[index].reloc_offset, writer.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::Aarch64_Ilp32 => { - match (reloc.kind, reloc.encoding, reloc.size) { - (RelocationKind::Absolute, RelocationEncoding::Generic, 32) => { - elf::R_AARCH64_P32_ABS32 - } - (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::Csky => match (reloc.kind, reloc.encoding, reloc.size) { - (RelocationKind::Absolute, _, 32) => elf::R_CKCORE_ADDR32, - (RelocationKind::Relative, RelocationEncoding::Generic, 32) => { - elf::R_CKCORE_PCREL32 - } - (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, RelocationEncoding::X86Branch, 32) => { - elf::R_X86_64_PLT32 - } - (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::LoongArch64 => match (reloc.kind, reloc.encoding, reloc.size) - { - (RelocationKind::Absolute, _, 32) => elf::R_LARCH_32, - (RelocationKind::Absolute, _, 64) => elf::R_LARCH_64, - (RelocationKind::Relative, _, 32) => elf::R_LARCH_32_PCREL, - (RelocationKind::Relative, _, 64) => elf::R_LARCH_64_PCREL, - (RelocationKind::Relative, RelocationEncoding::LoongArchBranch, 16) - | ( - RelocationKind::PltRelative, - RelocationEncoding::LoongArchBranch, - 16, - ) => elf::R_LARCH_B16, - (RelocationKind::Relative, RelocationEncoding::LoongArchBranch, 21) - | ( - RelocationKind::PltRelative, - RelocationEncoding::LoongArchBranch, - 21, - ) => elf::R_LARCH_B21, - (RelocationKind::Relative, RelocationEncoding::LoongArchBranch, 26) - | ( - RelocationKind::PltRelative, - RelocationEncoding::LoongArchBranch, - 26, - ) => elf::R_LARCH_B26, - (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::Relative, RelocationEncoding::Generic, 32) => { - elf::R_RISCV_32_PCREL - } - (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::Sbf => match (reloc.kind, reloc.encoding, reloc.size) { - (RelocationKind::Absolute, _, 64) => elf::R_SBF_64_64, - (RelocationKind::Absolute, _, 32) => elf::R_SBF_64_32, - (RelocationKind::Elf(x), _, _) => x, - _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); - } - }, - Architecture::Sharc => match (reloc.kind, reloc.encoding, reloc.size) { - (RelocationKind::Absolute, RelocationEncoding::SharcTypeA, 32) => { - elf::R_SHARC_ADDR32_V3 - } - (RelocationKind::Absolute, RelocationEncoding::Generic, 32) => { - elf::R_SHARC_ADDR_VAR_V3 - } - (RelocationKind::Relative, RelocationEncoding::SharcTypeA, 24) => { - elf::R_SHARC_PCRLONG_V3 - } - (RelocationKind::Relative, RelocationEncoding::SharcTypeA, 6) => { - elf::R_SHARC_PCRSHORT_V3 - } - (RelocationKind::Relative, RelocationEncoding::SharcTypeB, 6) => { - elf::R_SHARC_PCRSHORT_V3 - } - (RelocationKind::Absolute, RelocationEncoding::Generic, 16) => { - elf::R_SHARC_ADDR_VAR16_V3 - } - (RelocationKind::Absolute, RelocationEncoding::SharcTypeA, 16) => { - elf::R_SHARC_DATA16_V3 - } - (RelocationKind::Absolute, RelocationEncoding::SharcTypeB, 16) => { - elf::R_SHARC_DATA16_VISA_V3 - } - (RelocationKind::Absolute, RelocationEncoding::SharcTypeA, 24) => { - elf::R_SHARC_ADDR24_V3 - } - (RelocationKind::Absolute, RelocationEncoding::SharcTypeA, 6) => { - elf::R_SHARC_DATA6_V3 - } - (RelocationKind::Absolute, RelocationEncoding::SharcTypeB, 6) => { - elf::R_SHARC_DATA6_VISA_V3 - } - (RelocationKind::Absolute, RelocationEncoding::SharcTypeB, 7) => { - elf::R_SHARC_DATA7_VISA_V3 - } - (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))); - } - }, - Architecture::Xtensa => match (reloc.kind, reloc.encoding, reloc.size) { - (RelocationKind::Absolute, _, 32) => elf::R_XTENSA_32, - (RelocationKind::Relative, RelocationEncoding::Generic, 32) => { - elf::R_XTENSA_32_PCREL - } - (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.0; - writer.write_relocation( - is_rela, - &Rel { - r_offset: reloc.offset, - r_sym, - r_type, - r_addend: reloc.addend, - }, - ); - } - } - } - - writer.write_shstrtab(); - - // Write section headers. - writer.write_null_section_header(); - - let symtab_index = writer.symtab_index(); - for (comdat, comdat_offset) in self.comdats.iter().zip(comdat_offsets.iter()) { - writer.write_comdat_section_header( - comdat_offset.str_id, - symtab_index, - symbol_offsets[comdat.symbol.0].index, - comdat_offset.offset, - comdat.sections.len(), - ); - } - 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 | SectionKind::ReadOnlyDataWithRel => { - 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, - }; - writer.write_section_header(&SectionHeader { - name: Some(section_offsets[index].str_id), - 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() { - writer.write_relocation_section_header( - section_offsets[index].reloc_str_id.unwrap(), - section_offsets[index].index, - symtab_index, - section_offsets[index].reloc_offset, - section.relocations.len(), - is_rela, - ); - } - } - - writer.write_symtab_section_header(symtab_num_local); - writer.write_symtab_shndx_section_header(); - writer.write_strtab_section_header(); - writer.write_shstrtab_section_header(); - - debug_assert_eq!(writer.reserved_len(), writer.len()); - - Ok(()) - } -} diff --git a/vendor/object/src/write/elf/writer.rs b/vendor/object/src/write/elf/writer.rs deleted file mode 100644 index 9750924..0000000 --- a/vendor/object/src/write/elf/writer.rs +++ /dev/null @@ -1,2143 +0,0 @@ -//! Helper for writing ELF files. -use alloc::string::String; -use alloc::vec::Vec; -use core::mem; - -use crate::elf; -use crate::endian::*; -use crate::pod; -use crate::write::string::{StringId, StringTable}; -use crate::write::util; -use crate::write::{Error, Result, WritableBuffer}; - -/// The index of an ELF section. -#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct SectionIndex(pub u32); - -/// The index of an ELF symbol. -#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct SymbolIndex(pub u32); - -/// A helper for writing ELF files. -/// -/// Writing uses a two phase approach. The first phase builds up all of the information -/// that may need to be known ahead of time: -/// - build string tables -/// - reserve section indices -/// - reserve symbol indices -/// - reserve file ranges for headers and sections -/// -/// Some of the information has ordering requirements. For example, strings must be added -/// to string tables before reserving the file range for the string table. Symbol indices -/// must be reserved after reserving the section indices they reference. There are debug -/// asserts to check some of these requirements. -/// -/// The second phase writes everything out in order. Thus the caller must ensure writing -/// is in the same order that file ranges were reserved. There are debug asserts to assist -/// with checking this. -#[allow(missing_debug_implementations)] -pub struct Writer<'a> { - endian: Endianness, - is_64: bool, - is_mips64el: bool, - elf_align: usize, - - buffer: &'a mut dyn WritableBuffer, - len: usize, - - segment_offset: usize, - segment_num: u32, - - section_offset: usize, - section_num: u32, - - shstrtab: StringTable<'a>, - shstrtab_str_id: Option<StringId>, - shstrtab_index: SectionIndex, - shstrtab_offset: usize, - shstrtab_data: Vec<u8>, - - need_strtab: bool, - strtab: StringTable<'a>, - strtab_str_id: Option<StringId>, - strtab_index: SectionIndex, - strtab_offset: usize, - strtab_data: Vec<u8>, - - symtab_str_id: Option<StringId>, - symtab_index: SectionIndex, - symtab_offset: usize, - symtab_num: u32, - - need_symtab_shndx: bool, - symtab_shndx_str_id: Option<StringId>, - symtab_shndx_offset: usize, - symtab_shndx_data: Vec<u8>, - - need_dynstr: bool, - dynstr: StringTable<'a>, - dynstr_str_id: Option<StringId>, - dynstr_index: SectionIndex, - dynstr_offset: usize, - dynstr_data: Vec<u8>, - - dynsym_str_id: Option<StringId>, - dynsym_index: SectionIndex, - dynsym_offset: usize, - dynsym_num: u32, - - dynamic_str_id: Option<StringId>, - dynamic_offset: usize, - dynamic_num: usize, - - hash_str_id: Option<StringId>, - hash_offset: usize, - hash_size: usize, - - gnu_hash_str_id: Option<StringId>, - gnu_hash_offset: usize, - gnu_hash_size: usize, - - gnu_versym_str_id: Option<StringId>, - gnu_versym_offset: usize, - - gnu_verdef_str_id: Option<StringId>, - gnu_verdef_offset: usize, - gnu_verdef_size: usize, - gnu_verdef_count: u16, - gnu_verdef_remaining: u16, - gnu_verdaux_remaining: u16, - - gnu_verneed_str_id: Option<StringId>, - gnu_verneed_offset: usize, - gnu_verneed_size: usize, - gnu_verneed_count: u16, - gnu_verneed_remaining: u16, - gnu_vernaux_remaining: u16, - - gnu_attributes_str_id: Option<StringId>, - gnu_attributes_offset: usize, - gnu_attributes_size: usize, -} - -impl<'a> Writer<'a> { - /// Create a new `Writer` for the given endianness and ELF class. - pub fn new(endian: Endianness, is_64: bool, buffer: &'a mut dyn WritableBuffer) -> Self { - let elf_align = if is_64 { 8 } else { 4 }; - Writer { - endian, - is_64, - // Determined later. - is_mips64el: false, - elf_align, - - buffer, - len: 0, - - segment_offset: 0, - segment_num: 0, - - section_offset: 0, - section_num: 0, - - shstrtab: StringTable::default(), - shstrtab_str_id: None, - shstrtab_index: SectionIndex(0), - shstrtab_offset: 0, - shstrtab_data: Vec::new(), - - need_strtab: false, - strtab: StringTable::default(), - strtab_str_id: None, - strtab_index: SectionIndex(0), - strtab_offset: 0, - strtab_data: Vec::new(), - - symtab_str_id: None, - symtab_index: SectionIndex(0), - symtab_offset: 0, - symtab_num: 0, - - need_symtab_shndx: false, - symtab_shndx_str_id: None, - symtab_shndx_offset: 0, - symtab_shndx_data: Vec::new(), - - need_dynstr: false, - dynstr: StringTable::default(), - dynstr_str_id: None, - dynstr_index: SectionIndex(0), - dynstr_offset: 0, - dynstr_data: Vec::new(), - - dynsym_str_id: None, - dynsym_index: SectionIndex(0), - dynsym_offset: 0, - dynsym_num: 0, - - dynamic_str_id: None, - dynamic_offset: 0, - dynamic_num: 0, - - hash_str_id: None, - hash_offset: 0, - hash_size: 0, - - gnu_hash_str_id: None, - gnu_hash_offset: 0, - gnu_hash_size: 0, - - gnu_versym_str_id: None, - gnu_versym_offset: 0, - - gnu_verdef_str_id: None, - gnu_verdef_offset: 0, - gnu_verdef_size: 0, - gnu_verdef_count: 0, - gnu_verdef_remaining: 0, - gnu_verdaux_remaining: 0, - - gnu_verneed_str_id: None, - gnu_verneed_offset: 0, - gnu_verneed_size: 0, - gnu_verneed_count: 0, - gnu_verneed_remaining: 0, - gnu_vernaux_remaining: 0, - - gnu_attributes_str_id: None, - gnu_attributes_offset: 0, - gnu_attributes_size: 0, - } - } - - /// Return the current file length that has been reserved. - pub fn reserved_len(&self) -> usize { - self.len - } - - /// Return the current file length that has been written. - #[allow(clippy::len_without_is_empty)] - pub fn len(&self) -> usize { - self.buffer.len() - } - - /// Reserve a file range with the given size and starting alignment. - /// - /// Returns the aligned offset of the start of the range. - pub fn reserve(&mut self, len: usize, align_start: usize) -> usize { - if align_start > 1 { - self.len = util::align(self.len, align_start); - } - let offset = self.len; - self.len += len; - offset - } - - /// Write alignment padding bytes. - pub fn write_align(&mut self, align_start: usize) { - if align_start > 1 { - util::write_align(self.buffer, align_start); - } - } - - /// Write data. - /// - /// This is typically used to write section data. - pub fn write(&mut self, data: &[u8]) { - self.buffer.write_bytes(data); - } - - /// Reserve the file range up to the given file offset. - pub fn reserve_until(&mut self, offset: usize) { - debug_assert!(self.len <= offset); - self.len = offset; - } - - /// Write padding up to the given file offset. - pub fn pad_until(&mut self, offset: usize) { - debug_assert!(self.buffer.len() <= offset); - self.buffer.resize(offset); - } - - fn file_header_size(&self) -> usize { - if self.is_64 { - mem::size_of::<elf::FileHeader64<Endianness>>() - } else { - mem::size_of::<elf::FileHeader32<Endianness>>() - } - } - - /// Reserve the range for the file header. - /// - /// This must be at the start of the file. - pub fn reserve_file_header(&mut self) { - debug_assert_eq!(self.len, 0); - self.reserve(self.file_header_size(), 1); - } - - /// Write the file header. - /// - /// This must be at the start of the file. - /// - /// Fields that can be derived from known information are automatically set by this function. - pub fn write_file_header(&mut self, header: &FileHeader) -> Result<()> { - debug_assert_eq!(self.buffer.len(), 0); - - self.is_mips64el = - self.is_64 && self.endian.is_little_endian() && header.e_machine == elf::EM_MIPS; - - // Start writing. - self.buffer - .reserve(self.len) - .map_err(|_| Error(String::from("Cannot allocate buffer")))?; - - // Write file header. - let e_ident = elf::Ident { - magic: elf::ELFMAG, - class: if self.is_64 { - elf::ELFCLASS64 - } else { - elf::ELFCLASS32 - }, - data: if self.endian.is_little_endian() { - elf::ELFDATA2LSB - } else { - elf::ELFDATA2MSB - }, - version: elf::EV_CURRENT, - os_abi: header.os_abi, - abi_version: header.abi_version, - padding: [0; 7], - }; - - let e_ehsize = self.file_header_size() as u16; - - let e_phoff = self.segment_offset as u64; - let e_phentsize = if self.segment_num == 0 { - 0 - } else { - self.program_header_size() as u16 - }; - // TODO: overflow - let e_phnum = self.segment_num as u16; - - let e_shoff = self.section_offset as u64; - let e_shentsize = if self.section_num == 0 { - 0 - } else { - self.section_header_size() as u16 - }; - let e_shnum = if self.section_num >= elf::SHN_LORESERVE.into() { - 0 - } else { - self.section_num as u16 - }; - let e_shstrndx = if self.shstrtab_index.0 >= elf::SHN_LORESERVE.into() { - elf::SHN_XINDEX - } else { - self.shstrtab_index.0 as u16 - }; - - let endian = self.endian; - if self.is_64 { - let file = elf::FileHeader64 { - e_ident, - e_type: U16::new(endian, header.e_type), - e_machine: U16::new(endian, header.e_machine), - e_version: U32::new(endian, elf::EV_CURRENT.into()), - e_entry: U64::new(endian, header.e_entry), - e_phoff: U64::new(endian, e_phoff), - e_shoff: U64::new(endian, e_shoff), - e_flags: U32::new(endian, header.e_flags), - e_ehsize: U16::new(endian, e_ehsize), - e_phentsize: U16::new(endian, e_phentsize), - e_phnum: U16::new(endian, e_phnum), - e_shentsize: U16::new(endian, e_shentsize), - e_shnum: U16::new(endian, e_shnum), - e_shstrndx: U16::new(endian, e_shstrndx), - }; - self.buffer.write(&file) - } else { - let file = elf::FileHeader32 { - e_ident, - e_type: U16::new(endian, header.e_type), - e_machine: U16::new(endian, header.e_machine), - e_version: U32::new(endian, elf::EV_CURRENT.into()), - e_entry: U32::new(endian, header.e_entry as u32), - e_phoff: U32::new(endian, e_phoff as u32), - e_shoff: U32::new(endian, e_shoff as u32), - e_flags: U32::new(endian, header.e_flags), - e_ehsize: U16::new(endian, e_ehsize), - e_phentsize: U16::new(endian, e_phentsize), - e_phnum: U16::new(endian, e_phnum), - e_shentsize: U16::new(endian, e_shentsize), - e_shnum: U16::new(endian, e_shnum), - e_shstrndx: U16::new(endian, e_shstrndx), - }; - self.buffer.write(&file); - } - - Ok(()) - } - - fn program_header_size(&self) -> usize { - if self.is_64 { - mem::size_of::<elf::ProgramHeader64<Endianness>>() - } else { - mem::size_of::<elf::ProgramHeader32<Endianness>>() - } - } - - /// Reserve the range for the program headers. - pub fn reserve_program_headers(&mut self, num: u32) { - debug_assert_eq!(self.segment_offset, 0); - if num == 0 { - return; - } - self.segment_num = num; - self.segment_offset = - self.reserve(num as usize * self.program_header_size(), self.elf_align); - } - - /// Write alignment padding bytes prior to the program headers. - pub fn write_align_program_headers(&mut self) { - if self.segment_offset == 0 { - return; - } - util::write_align(self.buffer, self.elf_align); - debug_assert_eq!(self.segment_offset, self.buffer.len()); - } - - /// Write a program header. - pub fn write_program_header(&mut self, header: &ProgramHeader) { - let endian = self.endian; - if self.is_64 { - let header = elf::ProgramHeader64 { - p_type: U32::new(endian, header.p_type), - p_flags: U32::new(endian, header.p_flags), - p_offset: U64::new(endian, header.p_offset), - p_vaddr: U64::new(endian, header.p_vaddr), - p_paddr: U64::new(endian, header.p_paddr), - p_filesz: U64::new(endian, header.p_filesz), - p_memsz: U64::new(endian, header.p_memsz), - p_align: U64::new(endian, header.p_align), - }; - self.buffer.write(&header); - } else { - let header = elf::ProgramHeader32 { - p_type: U32::new(endian, header.p_type), - p_offset: U32::new(endian, header.p_offset as u32), - p_vaddr: U32::new(endian, header.p_vaddr as u32), - p_paddr: U32::new(endian, header.p_paddr as u32), - p_filesz: U32::new(endian, header.p_filesz as u32), - p_memsz: U32::new(endian, header.p_memsz as u32), - p_flags: U32::new(endian, header.p_flags), - p_align: U32::new(endian, header.p_align as u32), - }; - self.buffer.write(&header); - } - } - - /// Reserve the section index for the null section header. - /// - /// The null section header is usually automatically reserved, - /// but this can be used to force an empty section table. - /// - /// This must be called before [`Self::reserve_section_headers`]. - pub fn reserve_null_section_index(&mut self) -> SectionIndex { - debug_assert_eq!(self.section_num, 0); - if self.section_num == 0 { - self.section_num = 1; - } - SectionIndex(0) - } - - /// Reserve a section table index. - /// - /// Automatically also reserves the null section header if required. - /// - /// This must be called before [`Self::reserve_section_headers`]. - pub fn reserve_section_index(&mut self) -> SectionIndex { - debug_assert_eq!(self.section_offset, 0); - if self.section_num == 0 { - self.section_num = 1; - } - let index = self.section_num; - self.section_num += 1; - SectionIndex(index) - } - - fn section_header_size(&self) -> usize { - if self.is_64 { - mem::size_of::<elf::SectionHeader64<Endianness>>() - } else { - mem::size_of::<elf::SectionHeader32<Endianness>>() - } - } - - /// Reserve the range for the section headers. - /// - /// This function does nothing if no sections were reserved. - /// This must be called after [`Self::reserve_section_index`] - /// and other functions that reserve section indices. - pub fn reserve_section_headers(&mut self) { - debug_assert_eq!(self.section_offset, 0); - if self.section_num == 0 { - return; - } - self.section_offset = self.reserve( - self.section_num as usize * self.section_header_size(), - self.elf_align, - ); - } - - /// Write the null section header. - /// - /// This must be the first section header that is written. - /// This function does nothing if no sections were reserved. - pub fn write_null_section_header(&mut self) { - if self.section_num == 0 { - return; - } - util::write_align(self.buffer, self.elf_align); - debug_assert_eq!(self.section_offset, self.buffer.len()); - self.write_section_header(&SectionHeader { - name: None, - sh_type: 0, - sh_flags: 0, - sh_addr: 0, - sh_offset: 0, - sh_size: if self.section_num >= elf::SHN_LORESERVE.into() { - self.section_num.into() - } else { - 0 - }, - sh_link: if self.shstrtab_index.0 >= elf::SHN_LORESERVE.into() { - self.shstrtab_index.0 - } else { - 0 - }, - // TODO: e_phnum overflow - sh_info: 0, - sh_addralign: 0, - sh_entsize: 0, - }); - } - - /// Write a section header. - pub fn write_section_header(&mut self, section: &SectionHeader) { - let sh_name = if let Some(name) = section.name { - self.shstrtab.get_offset(name) as u32 - } else { - 0 - }; - let endian = self.endian; - if self.is_64 { - let section = elf::SectionHeader64 { - sh_name: U32::new(endian, 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), - }; - self.buffer.write(§ion); - } else { - let section = elf::SectionHeader32 { - sh_name: U32::new(endian, 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), - }; - self.buffer.write(§ion); - } - } - - /// Add a section name to the section header string table. - /// - /// This will be stored in the `.shstrtab` section. - /// - /// This must be called before [`Self::reserve_shstrtab`]. - pub fn add_section_name(&mut self, name: &'a [u8]) -> StringId { - debug_assert_eq!(self.shstrtab_offset, 0); - self.shstrtab.add(name) - } - - /// Reserve the range for the section header string table. - /// - /// This range is used for a section named `.shstrtab`. - /// - /// This function does nothing if no sections were reserved. - /// This must be called after [`Self::add_section_name`]. - /// and other functions that reserve section names and indices. - pub fn reserve_shstrtab(&mut self) { - debug_assert_eq!(self.shstrtab_offset, 0); - if self.section_num == 0 { - return; - } - // Start with null section name. - self.shstrtab_data = vec![0]; - self.shstrtab.write(1, &mut self.shstrtab_data); - self.shstrtab_offset = self.reserve(self.shstrtab_data.len(), 1); - } - - /// Write the section header string table. - /// - /// This function does nothing if the section was not reserved. - pub fn write_shstrtab(&mut self) { - if self.shstrtab_offset == 0 { - return; - } - debug_assert_eq!(self.shstrtab_offset, self.buffer.len()); - self.buffer.write_bytes(&self.shstrtab_data); - } - - /// Reserve the section index for the section header string table. - /// - /// This must be called before [`Self::reserve_shstrtab`] - /// and [`Self::reserve_section_headers`]. - pub fn reserve_shstrtab_section_index(&mut self) -> SectionIndex { - debug_assert_eq!(self.shstrtab_index, SectionIndex(0)); - self.shstrtab_str_id = Some(self.add_section_name(&b".shstrtab"[..])); - self.shstrtab_index = self.reserve_section_index(); - self.shstrtab_index - } - - /// Write the section header for the section header string table. - /// - /// This function does nothing if the section index was not reserved. - pub fn write_shstrtab_section_header(&mut self) { - if self.shstrtab_index == SectionIndex(0) { - return; - } - self.write_section_header(&SectionHeader { - name: self.shstrtab_str_id, - sh_type: elf::SHT_STRTAB, - sh_flags: 0, - sh_addr: 0, - sh_offset: self.shstrtab_offset as u64, - sh_size: self.shstrtab_data.len() as u64, - sh_link: 0, - sh_info: 0, - sh_addralign: 1, - sh_entsize: 0, - }); - } - - /// Add a string to the string table. - /// - /// This will be stored in the `.strtab` section. - /// - /// This must be called before [`Self::reserve_strtab`]. - pub fn add_string(&mut self, name: &'a [u8]) -> StringId { - debug_assert_eq!(self.strtab_offset, 0); - self.need_strtab = true; - self.strtab.add(name) - } - - /// Return true if `.strtab` is needed. - pub fn strtab_needed(&self) -> bool { - self.need_strtab - } - - /// Reserve the range for the string table. - /// - /// This range is used for a section named `.strtab`. - /// - /// This function does nothing if no strings or symbols were defined. - /// This must be called after [`Self::add_string`]. - pub fn reserve_strtab(&mut self) { - debug_assert_eq!(self.strtab_offset, 0); - if !self.need_strtab { - return; - } - // Start with null string. - self.strtab_data = vec![0]; - self.strtab.write(1, &mut self.strtab_data); - self.strtab_offset = self.reserve(self.strtab_data.len(), 1); - } - - /// Write the string table. - /// - /// This function does nothing if the section was not reserved. - pub fn write_strtab(&mut self) { - if self.strtab_offset == 0 { - return; - } - debug_assert_eq!(self.strtab_offset, self.buffer.len()); - self.buffer.write_bytes(&self.strtab_data); - } - - /// Reserve the section index for the string table. - /// - /// This must be called before [`Self::reserve_section_headers`]. - pub fn reserve_strtab_section_index(&mut self) -> SectionIndex { - debug_assert_eq!(self.strtab_index, SectionIndex(0)); - self.strtab_str_id = Some(self.add_section_name(&b".strtab"[..])); - self.strtab_index = self.reserve_section_index(); - self.strtab_index - } - - /// Write the section header for the string table. - /// - /// This function does nothing if the section index was not reserved. - pub fn write_strtab_section_header(&mut self) { - if self.strtab_index == SectionIndex(0) { - return; - } - self.write_section_header(&SectionHeader { - name: self.strtab_str_id, - sh_type: elf::SHT_STRTAB, - sh_flags: 0, - sh_addr: 0, - sh_offset: self.strtab_offset as u64, - sh_size: self.strtab_data.len() as u64, - sh_link: 0, - sh_info: 0, - sh_addralign: 1, - sh_entsize: 0, - }); - } - - /// Reserve the null symbol table entry. - /// - /// This will be stored in the `.symtab` section. - /// - /// The null symbol table entry is usually automatically reserved, - /// but this can be used to force an empty symbol table. - /// - /// This must be called before [`Self::reserve_symtab`]. - pub fn reserve_null_symbol_index(&mut self) -> SymbolIndex { - debug_assert_eq!(self.symtab_offset, 0); - debug_assert_eq!(self.symtab_num, 0); - self.symtab_num = 1; - // The symtab must link to a strtab. - self.need_strtab = true; - SymbolIndex(0) - } - - /// Reserve a symbol table entry. - /// - /// This will be stored in the `.symtab` section. - /// - /// `section_index` is used to determine whether `.symtab_shndx` is required. - /// - /// Automatically also reserves the null symbol if required. - /// Callers may assume that the returned indices will be sequential - /// starting at 1. - /// - /// This must be called before [`Self::reserve_symtab`] and - /// [`Self::reserve_symtab_shndx`]. - pub fn reserve_symbol_index(&mut self, section_index: Option<SectionIndex>) -> SymbolIndex { - debug_assert_eq!(self.symtab_offset, 0); - debug_assert_eq!(self.symtab_shndx_offset, 0); - if self.symtab_num == 0 { - self.symtab_num = 1; - // The symtab must link to a strtab. - self.need_strtab = true; - } - let index = self.symtab_num; - self.symtab_num += 1; - if let Some(section_index) = section_index { - if section_index.0 >= elf::SHN_LORESERVE.into() { - self.need_symtab_shndx = true; - } - } - SymbolIndex(index) - } - - /// Return the number of reserved symbol table entries. - /// - /// Includes the null symbol. - pub fn symbol_count(&self) -> u32 { - self.symtab_num - } - - fn symbol_size(&self) -> usize { - if self.is_64 { - mem::size_of::<elf::Sym64<Endianness>>() - } else { - mem::size_of::<elf::Sym32<Endianness>>() - } - } - - /// Reserve the range for the symbol table. - /// - /// This range is used for a section named `.symtab`. - /// This function does nothing if no symbols were reserved. - /// This must be called after [`Self::reserve_symbol_index`]. - pub fn reserve_symtab(&mut self) { - debug_assert_eq!(self.symtab_offset, 0); - if self.symtab_num == 0 { - return; - } - self.symtab_offset = self.reserve( - self.symtab_num as usize * self.symbol_size(), - self.elf_align, - ); - } - - /// Write the null symbol. - /// - /// This must be the first symbol that is written. - /// This function does nothing if no symbols were reserved. - pub fn write_null_symbol(&mut self) { - if self.symtab_num == 0 { - return; - } - util::write_align(self.buffer, self.elf_align); - debug_assert_eq!(self.symtab_offset, self.buffer.len()); - if self.is_64 { - self.buffer.write(&elf::Sym64::<Endianness>::default()); - } else { - self.buffer.write(&elf::Sym32::<Endianness>::default()); - } - - if self.need_symtab_shndx { - self.symtab_shndx_data.write_pod(&U32::new(self.endian, 0)); - } - } - - /// Write a symbol. - pub fn write_symbol(&mut self, sym: &Sym) { - let st_name = if let Some(name) = sym.name { - self.strtab.get_offset(name) as u32 - } else { - 0 - }; - let st_shndx = if let Some(section) = sym.section { - if section.0 >= elf::SHN_LORESERVE as u32 { - elf::SHN_XINDEX - } else { - section.0 as u16 - } - } else { - sym.st_shndx - }; - - let endian = self.endian; - if self.is_64 { - let sym = elf::Sym64 { - st_name: U32::new(endian, st_name), - st_info: sym.st_info, - st_other: sym.st_other, - st_shndx: U16::new(endian, st_shndx), - st_value: U64::new(endian, sym.st_value), - st_size: U64::new(endian, sym.st_size), - }; - self.buffer.write(&sym); - } else { - let sym = elf::Sym32 { - st_name: U32::new(endian, st_name), - st_info: sym.st_info, - st_other: sym.st_other, - st_shndx: U16::new(endian, st_shndx), - st_value: U32::new(endian, sym.st_value as u32), - st_size: U32::new(endian, sym.st_size as u32), - }; - self.buffer.write(&sym); - } - - if self.need_symtab_shndx { - let section_index = sym.section.unwrap_or(SectionIndex(0)); - self.symtab_shndx_data - .write_pod(&U32::new(self.endian, section_index.0)); - } - } - - /// Reserve the section index for the symbol table. - /// - /// This must be called before [`Self::reserve_section_headers`]. - pub fn reserve_symtab_section_index(&mut self) -> SectionIndex { - debug_assert_eq!(self.symtab_index, SectionIndex(0)); - self.symtab_str_id = Some(self.add_section_name(&b".symtab"[..])); - self.symtab_index = self.reserve_section_index(); - self.symtab_index - } - - /// Return the section index of the symbol table. - pub fn symtab_index(&mut self) -> SectionIndex { - self.symtab_index - } - - /// Write the section header for the symbol table. - /// - /// This function does nothing if the section index was not reserved. - pub fn write_symtab_section_header(&mut self, num_local: u32) { - if self.symtab_index == SectionIndex(0) { - return; - } - self.write_section_header(&SectionHeader { - name: self.symtab_str_id, - sh_type: elf::SHT_SYMTAB, - sh_flags: 0, - sh_addr: 0, - sh_offset: self.symtab_offset as u64, - sh_size: self.symtab_num as u64 * self.symbol_size() as u64, - sh_link: self.strtab_index.0, - sh_info: num_local, - sh_addralign: self.elf_align as u64, - sh_entsize: self.symbol_size() as u64, - }); - } - - /// Return true if `.symtab_shndx` is needed. - pub fn symtab_shndx_needed(&self) -> bool { - self.need_symtab_shndx - } - - /// Reserve the range for the extended section indices for the symbol table. - /// - /// This range is used for a section named `.symtab_shndx`. - /// This also reserves a section index. - /// - /// This function does nothing if extended section indices are not needed. - /// This must be called after [`Self::reserve_symbol_index`]. - pub fn reserve_symtab_shndx(&mut self) { - debug_assert_eq!(self.symtab_shndx_offset, 0); - if !self.need_symtab_shndx { - return; - } - self.symtab_shndx_offset = self.reserve(self.symtab_num as usize * 4, 4); - self.symtab_shndx_data.reserve(self.symtab_num as usize * 4); - } - - /// Write the extended section indices for the symbol table. - /// - /// This function does nothing if the section was not reserved. - pub fn write_symtab_shndx(&mut self) { - if self.symtab_shndx_offset == 0 { - return; - } - debug_assert_eq!(self.symtab_shndx_offset, self.buffer.len()); - debug_assert_eq!(self.symtab_num as usize * 4, self.symtab_shndx_data.len()); - self.buffer.write_bytes(&self.symtab_shndx_data); - } - - /// Reserve the section index for the extended section indices symbol table. - /// - /// You should check [`Self::symtab_shndx_needed`] before calling this - /// unless you have other means of knowing if this section is needed. - /// - /// This must be called before [`Self::reserve_section_headers`]. - pub fn reserve_symtab_shndx_section_index(&mut self) -> SectionIndex { - debug_assert!(self.symtab_shndx_str_id.is_none()); - self.symtab_shndx_str_id = Some(self.add_section_name(&b".symtab_shndx"[..])); - self.reserve_section_index() - } - - /// Write the section header for the extended section indices for the symbol table. - /// - /// This function does nothing if the section index was not reserved. - pub fn write_symtab_shndx_section_header(&mut self) { - if self.symtab_shndx_str_id.is_none() { - return; - } - let sh_size = if self.symtab_shndx_offset == 0 { - 0 - } else { - (self.symtab_num * 4) as u64 - }; - self.write_section_header(&SectionHeader { - name: self.symtab_shndx_str_id, - sh_type: elf::SHT_SYMTAB_SHNDX, - sh_flags: 0, - sh_addr: 0, - sh_offset: self.symtab_shndx_offset as u64, - sh_size, - sh_link: self.symtab_index.0, - sh_info: 0, - sh_addralign: 4, - sh_entsize: 4, - }); - } - - /// Add a string to the dynamic string table. - /// - /// This will be stored in the `.dynstr` section. - /// - /// This must be called before [`Self::reserve_dynstr`]. - pub fn add_dynamic_string(&mut self, name: &'a [u8]) -> StringId { - debug_assert_eq!(self.dynstr_offset, 0); - self.need_dynstr = true; - self.dynstr.add(name) - } - - /// Get a string that was previously added to the dynamic string table. - /// - /// Panics if the string was not added. - pub fn get_dynamic_string(&self, name: &'a [u8]) -> StringId { - self.dynstr.get_id(name) - } - - /// Return true if `.dynstr` is needed. - pub fn dynstr_needed(&self) -> bool { - self.need_dynstr - } - - /// Reserve the range for the dynamic string table. - /// - /// This range is used for a section named `.dynstr`. - /// - /// This function does nothing if no dynamic strings or symbols were defined. - /// This must be called after [`Self::add_dynamic_string`]. - pub fn reserve_dynstr(&mut self) { - debug_assert_eq!(self.dynstr_offset, 0); - if !self.need_dynstr { - return; - } - // Start with null string. - self.dynstr_data = vec![0]; - self.dynstr.write(1, &mut self.dynstr_data); - self.dynstr_offset = self.reserve(self.dynstr_data.len(), 1); - } - - /// Write the dynamic string table. - /// - /// This function does nothing if the section was not reserved. - pub fn write_dynstr(&mut self) { - if self.dynstr_offset == 0 { - return; - } - debug_assert_eq!(self.dynstr_offset, self.buffer.len()); - self.buffer.write_bytes(&self.dynstr_data); - } - - /// Reserve the section index for the dynamic string table. - /// - /// This must be called before [`Self::reserve_section_headers`]. - pub fn reserve_dynstr_section_index(&mut self) -> SectionIndex { - debug_assert_eq!(self.dynstr_index, SectionIndex(0)); - self.dynstr_str_id = Some(self.add_section_name(&b".dynstr"[..])); - self.dynstr_index = self.reserve_section_index(); - self.dynstr_index - } - - /// Return the section index of the dynamic string table. - pub fn dynstr_index(&mut self) -> SectionIndex { - self.dynstr_index - } - - /// Write the section header for the dynamic string table. - /// - /// This function does nothing if the section index was not reserved. - pub fn write_dynstr_section_header(&mut self, sh_addr: u64) { - if self.dynstr_index == SectionIndex(0) { - return; - } - self.write_section_header(&SectionHeader { - name: self.dynstr_str_id, - sh_type: elf::SHT_STRTAB, - sh_flags: elf::SHF_ALLOC.into(), - sh_addr, - sh_offset: self.dynstr_offset as u64, - sh_size: self.dynstr_data.len() as u64, - sh_link: 0, - sh_info: 0, - sh_addralign: 1, - sh_entsize: 0, - }); - } - - /// Reserve the null dynamic symbol table entry. - /// - /// This will be stored in the `.dynsym` section. - /// - /// The null dynamic symbol table entry is usually automatically reserved, - /// but this can be used to force an empty dynamic symbol table. - /// - /// This must be called before [`Self::reserve_dynsym`]. - pub fn reserve_null_dynamic_symbol_index(&mut self) -> SymbolIndex { - debug_assert_eq!(self.dynsym_offset, 0); - debug_assert_eq!(self.dynsym_num, 0); - self.dynsym_num = 1; - // The symtab must link to a strtab. - self.need_dynstr = true; - SymbolIndex(0) - } - - /// Reserve a dynamic symbol table entry. - /// - /// This will be stored in the `.dynsym` section. - /// - /// Automatically also reserves the null symbol if required. - /// Callers may assume that the returned indices will be sequential - /// starting at 1. - /// - /// This must be called before [`Self::reserve_dynsym`]. - pub fn reserve_dynamic_symbol_index(&mut self) -> SymbolIndex { - debug_assert_eq!(self.dynsym_offset, 0); - if self.dynsym_num == 0 { - self.dynsym_num = 1; - // The symtab must link to a strtab. - self.need_dynstr = true; - } - let index = self.dynsym_num; - self.dynsym_num += 1; - SymbolIndex(index) - } - - /// Return the number of reserved dynamic symbols. - /// - /// Includes the null symbol. - pub fn dynamic_symbol_count(&mut self) -> u32 { - self.dynsym_num - } - - /// Reserve the range for the dynamic symbol table. - /// - /// This range is used for a section named `.dynsym`. - /// - /// This function does nothing if no dynamic symbols were reserved. - /// This must be called after [`Self::reserve_dynamic_symbol_index`]. - pub fn reserve_dynsym(&mut self) { - debug_assert_eq!(self.dynsym_offset, 0); - if self.dynsym_num == 0 { - return; - } - self.dynsym_offset = self.reserve( - self.dynsym_num as usize * self.symbol_size(), - self.elf_align, - ); - } - - /// Write the null dynamic symbol. - /// - /// This must be the first dynamic symbol that is written. - /// This function does nothing if no dynamic symbols were reserved. - pub fn write_null_dynamic_symbol(&mut self) { - if self.dynsym_num == 0 { - return; - } - util::write_align(self.buffer, self.elf_align); - debug_assert_eq!(self.dynsym_offset, self.buffer.len()); - if self.is_64 { - self.buffer.write(&elf::Sym64::<Endianness>::default()); - } else { - self.buffer.write(&elf::Sym32::<Endianness>::default()); - } - } - - /// Write a dynamic symbol. - pub fn write_dynamic_symbol(&mut self, sym: &Sym) { - let st_name = if let Some(name) = sym.name { - self.dynstr.get_offset(name) as u32 - } else { - 0 - }; - - let st_shndx = if let Some(section) = sym.section { - if section.0 >= elf::SHN_LORESERVE as u32 { - // TODO: we don't actually write out .dynsym_shndx yet. - // This is unlikely to be needed though. - elf::SHN_XINDEX - } else { - section.0 as u16 - } - } else { - sym.st_shndx - }; - - let endian = self.endian; - if self.is_64 { - let sym = elf::Sym64 { - st_name: U32::new(endian, st_name), - st_info: sym.st_info, - st_other: sym.st_other, - st_shndx: U16::new(endian, st_shndx), - st_value: U64::new(endian, sym.st_value), - st_size: U64::new(endian, sym.st_size), - }; - self.buffer.write(&sym); - } else { - let sym = elf::Sym32 { - st_name: U32::new(endian, st_name), - st_info: sym.st_info, - st_other: sym.st_other, - st_shndx: U16::new(endian, st_shndx), - st_value: U32::new(endian, sym.st_value as u32), - st_size: U32::new(endian, sym.st_size as u32), - }; - self.buffer.write(&sym); - } - } - - /// Reserve the section index for the dynamic symbol table. - /// - /// This must be called before [`Self::reserve_section_headers`]. - pub fn reserve_dynsym_section_index(&mut self) -> SectionIndex { - debug_assert_eq!(self.dynsym_index, SectionIndex(0)); - self.dynsym_str_id = Some(self.add_section_name(&b".dynsym"[..])); - self.dynsym_index = self.reserve_section_index(); - self.dynsym_index - } - - /// Return the section index of the dynamic symbol table. - pub fn dynsym_index(&mut self) -> SectionIndex { - self.dynsym_index - } - - /// Write the section header for the dynamic symbol table. - /// - /// This function does nothing if the section index was not reserved. - pub fn write_dynsym_section_header(&mut self, sh_addr: u64, num_local: u32) { - if self.dynsym_index == SectionIndex(0) { - return; - } - self.write_section_header(&SectionHeader { - name: self.dynsym_str_id, - sh_type: elf::SHT_DYNSYM, - sh_flags: elf::SHF_ALLOC.into(), - sh_addr, - sh_offset: self.dynsym_offset as u64, - sh_size: self.dynsym_num as u64 * self.symbol_size() as u64, - sh_link: self.dynstr_index.0, - sh_info: num_local, - sh_addralign: self.elf_align as u64, - sh_entsize: self.symbol_size() as u64, - }); - } - - fn dyn_size(&self) -> usize { - if self.is_64 { - mem::size_of::<elf::Dyn64<Endianness>>() - } else { - mem::size_of::<elf::Dyn32<Endianness>>() - } - } - - /// Reserve the range for the `.dynamic` section. - /// - /// This function does nothing if `dynamic_num` is zero. - pub fn reserve_dynamic(&mut self, dynamic_num: usize) { - debug_assert_eq!(self.dynamic_offset, 0); - if dynamic_num == 0 { - return; - } - self.dynamic_num = dynamic_num; - self.dynamic_offset = self.reserve(dynamic_num * self.dyn_size(), self.elf_align); - } - - /// Write alignment padding bytes prior to the `.dynamic` section. - /// - /// This function does nothing if the section was not reserved. - pub fn write_align_dynamic(&mut self) { - if self.dynamic_offset == 0 { - return; - } - util::write_align(self.buffer, self.elf_align); - debug_assert_eq!(self.dynamic_offset, self.buffer.len()); - } - - /// Write a dynamic string entry. - pub fn write_dynamic_string(&mut self, tag: u32, id: StringId) { - self.write_dynamic(tag, self.dynstr.get_offset(id) as u64); - } - - /// Write a dynamic value entry. - pub fn write_dynamic(&mut self, d_tag: u32, d_val: u64) { - debug_assert!(self.dynamic_offset <= self.buffer.len()); - let endian = self.endian; - if self.is_64 { - let d = elf::Dyn64 { - d_tag: U64::new(endian, d_tag.into()), - d_val: U64::new(endian, d_val), - }; - self.buffer.write(&d); - } else { - let d = elf::Dyn32 { - d_tag: U32::new(endian, d_tag), - d_val: U32::new(endian, d_val as u32), - }; - self.buffer.write(&d); - } - debug_assert!( - self.dynamic_offset + self.dynamic_num * self.dyn_size() >= self.buffer.len() - ); - } - - /// Reserve the section index for the dynamic table. - pub fn reserve_dynamic_section_index(&mut self) -> SectionIndex { - debug_assert!(self.dynamic_str_id.is_none()); - self.dynamic_str_id = Some(self.add_section_name(&b".dynamic"[..])); - self.reserve_section_index() - } - - /// Write the section header for the dynamic table. - /// - /// This function does nothing if the section index was not reserved. - pub fn write_dynamic_section_header(&mut self, sh_addr: u64) { - if self.dynamic_str_id.is_none() { - return; - } - self.write_section_header(&SectionHeader { - name: self.dynamic_str_id, - sh_type: elf::SHT_DYNAMIC, - sh_flags: (elf::SHF_WRITE | elf::SHF_ALLOC).into(), - sh_addr, - sh_offset: self.dynamic_offset as u64, - sh_size: (self.dynamic_num * self.dyn_size()) as u64, - sh_link: self.dynstr_index.0, - sh_info: 0, - sh_addralign: self.elf_align as u64, - sh_entsize: self.dyn_size() as u64, - }); - } - - fn rel_size(&self, is_rela: bool) -> usize { - if self.is_64 { - if is_rela { - mem::size_of::<elf::Rela64<Endianness>>() - } else { - mem::size_of::<elf::Rel64<Endianness>>() - } - } else { - if is_rela { - mem::size_of::<elf::Rela32<Endianness>>() - } else { - mem::size_of::<elf::Rel32<Endianness>>() - } - } - } - - /// Reserve a file range for a SysV hash section. - /// - /// `symbol_count` is the number of symbols in the hash, - /// not the total number of symbols. - pub fn reserve_hash(&mut self, bucket_count: u32, chain_count: u32) { - self.hash_size = mem::size_of::<elf::HashHeader<Endianness>>() - + bucket_count as usize * 4 - + chain_count as usize * 4; - self.hash_offset = self.reserve(self.hash_size, self.elf_align); - } - - /// Write a SysV hash section. - /// - /// `chain_count` is the number of symbols in the hash. - /// The argument to `hash` will be in the range `0..chain_count`. - pub fn write_hash<F>(&mut self, bucket_count: u32, chain_count: u32, hash: F) - where - F: Fn(u32) -> Option<u32>, - { - let mut buckets = vec![U32::new(self.endian, 0); bucket_count as usize]; - let mut chains = vec![U32::new(self.endian, 0); chain_count as usize]; - for i in 0..chain_count { - if let Some(hash) = hash(i) { - let bucket = hash % bucket_count; - chains[i as usize] = buckets[bucket as usize]; - buckets[bucket as usize] = U32::new(self.endian, i); - } - } - - util::write_align(self.buffer, self.elf_align); - debug_assert_eq!(self.hash_offset, self.buffer.len()); - self.buffer.write(&elf::HashHeader { - bucket_count: U32::new(self.endian, bucket_count), - chain_count: U32::new(self.endian, chain_count), - }); - self.buffer.write_slice(&buckets); - self.buffer.write_slice(&chains); - } - - /// Reserve the section index for the SysV hash table. - pub fn reserve_hash_section_index(&mut self) -> SectionIndex { - debug_assert!(self.hash_str_id.is_none()); - self.hash_str_id = Some(self.add_section_name(&b".hash"[..])); - self.reserve_section_index() - } - - /// Write the section header for the SysV hash table. - /// - /// This function does nothing if the section index was not reserved. - pub fn write_hash_section_header(&mut self, sh_addr: u64) { - if self.hash_str_id.is_none() { - return; - } - self.write_section_header(&SectionHeader { - name: self.hash_str_id, - sh_type: elf::SHT_HASH, - sh_flags: elf::SHF_ALLOC.into(), - sh_addr, - sh_offset: self.hash_offset as u64, - sh_size: self.hash_size as u64, - sh_link: self.dynsym_index.0, - sh_info: 0, - sh_addralign: self.elf_align as u64, - sh_entsize: 4, - }); - } - - /// Reserve a file range for a GNU hash section. - /// - /// `symbol_count` is the number of symbols in the hash, - /// not the total number of symbols. - pub fn reserve_gnu_hash(&mut self, bloom_count: u32, bucket_count: u32, symbol_count: u32) { - self.gnu_hash_size = mem::size_of::<elf::GnuHashHeader<Endianness>>() - + bloom_count as usize * self.elf_align - + bucket_count as usize * 4 - + symbol_count as usize * 4; - self.gnu_hash_offset = self.reserve(self.gnu_hash_size, self.elf_align); - } - - /// Write a GNU hash section. - /// - /// `symbol_count` is the number of symbols in the hash. - /// The argument to `hash` will be in the range `0..symbol_count`. - /// - /// This requires that symbols are already sorted by bucket. - pub fn write_gnu_hash<F>( - &mut self, - symbol_base: u32, - bloom_shift: u32, - bloom_count: u32, - bucket_count: u32, - symbol_count: u32, - hash: F, - ) where - F: Fn(u32) -> u32, - { - util::write_align(self.buffer, self.elf_align); - debug_assert_eq!(self.gnu_hash_offset, self.buffer.len()); - self.buffer.write(&elf::GnuHashHeader { - bucket_count: U32::new(self.endian, bucket_count), - symbol_base: U32::new(self.endian, symbol_base), - bloom_count: U32::new(self.endian, bloom_count), - bloom_shift: U32::new(self.endian, bloom_shift), - }); - - // Calculate and write bloom filter. - if self.is_64 { - let mut bloom_filters = vec![0; bloom_count as usize]; - for i in 0..symbol_count { - let h = hash(i); - bloom_filters[((h / 64) & (bloom_count - 1)) as usize] |= - 1 << (h % 64) | 1 << ((h >> bloom_shift) % 64); - } - for bloom_filter in bloom_filters { - self.buffer.write(&U64::new(self.endian, bloom_filter)); - } - } else { - let mut bloom_filters = vec![0; bloom_count as usize]; - for i in 0..symbol_count { - let h = hash(i); - bloom_filters[((h / 32) & (bloom_count - 1)) as usize] |= - 1 << (h % 32) | 1 << ((h >> bloom_shift) % 32); - } - for bloom_filter in bloom_filters { - self.buffer.write(&U32::new(self.endian, bloom_filter)); - } - } - - // Write buckets. - // - // This requires that symbols are already sorted by bucket. - let mut bucket = 0; - for i in 0..symbol_count { - let symbol_bucket = hash(i) % bucket_count; - while bucket < symbol_bucket { - self.buffer.write(&U32::new(self.endian, 0)); - bucket += 1; - } - if bucket == symbol_bucket { - self.buffer.write(&U32::new(self.endian, symbol_base + i)); - bucket += 1; - } - } - while bucket < bucket_count { - self.buffer.write(&U32::new(self.endian, 0)); - bucket += 1; - } - - // Write hash values. - for i in 0..symbol_count { - let mut h = hash(i); - if i == symbol_count - 1 || h % bucket_count != hash(i + 1) % bucket_count { - h |= 1; - } else { - h &= !1; - } - self.buffer.write(&U32::new(self.endian, h)); - } - } - - /// Reserve the section index for the GNU hash table. - pub fn reserve_gnu_hash_section_index(&mut self) -> SectionIndex { - debug_assert!(self.gnu_hash_str_id.is_none()); - self.gnu_hash_str_id = Some(self.add_section_name(&b".gnu.hash"[..])); - self.reserve_section_index() - } - - /// Write the section header for the GNU hash table. - /// - /// This function does nothing if the section index was not reserved. - pub fn write_gnu_hash_section_header(&mut self, sh_addr: u64) { - if self.gnu_hash_str_id.is_none() { - return; - } - self.write_section_header(&SectionHeader { - name: self.gnu_hash_str_id, - sh_type: elf::SHT_GNU_HASH, - sh_flags: elf::SHF_ALLOC.into(), - sh_addr, - sh_offset: self.gnu_hash_offset as u64, - sh_size: self.gnu_hash_size as u64, - sh_link: self.dynsym_index.0, - sh_info: 0, - sh_addralign: self.elf_align as u64, - sh_entsize: 0, - }); - } - - /// Reserve the range for the `.gnu.version` section. - /// - /// This function does nothing if no dynamic symbols were reserved. - pub fn reserve_gnu_versym(&mut self) { - debug_assert_eq!(self.gnu_versym_offset, 0); - if self.dynsym_num == 0 { - return; - } - self.gnu_versym_offset = self.reserve(self.dynsym_num as usize * 2, 2); - } - - /// Write the null symbol version entry. - /// - /// This must be the first symbol version that is written. - /// This function does nothing if no dynamic symbols were reserved. - pub fn write_null_gnu_versym(&mut self) { - if self.dynsym_num == 0 { - return; - } - util::write_align(self.buffer, 2); - debug_assert_eq!(self.gnu_versym_offset, self.buffer.len()); - self.write_gnu_versym(0); - } - - /// Write a symbol version entry. - pub fn write_gnu_versym(&mut self, versym: u16) { - self.buffer.write(&U16::new(self.endian, versym)); - } - - /// Reserve the section index for the `.gnu.version` section. - pub fn reserve_gnu_versym_section_index(&mut self) -> SectionIndex { - debug_assert!(self.gnu_versym_str_id.is_none()); - self.gnu_versym_str_id = Some(self.add_section_name(&b".gnu.version"[..])); - self.reserve_section_index() - } - - /// Write the section header for the `.gnu.version` section. - /// - /// This function does nothing if the section index was not reserved. - pub fn write_gnu_versym_section_header(&mut self, sh_addr: u64) { - if self.gnu_versym_str_id.is_none() { - return; - } - self.write_section_header(&SectionHeader { - name: self.gnu_versym_str_id, - sh_type: elf::SHT_GNU_VERSYM, - sh_flags: elf::SHF_ALLOC.into(), - sh_addr, - sh_offset: self.gnu_versym_offset as u64, - sh_size: self.dynsym_num as u64 * 2, - sh_link: self.dynsym_index.0, - sh_info: 0, - sh_addralign: 2, - sh_entsize: 2, - }); - } - - /// Reserve the range for the `.gnu.version_d` section. - pub fn reserve_gnu_verdef(&mut self, verdef_count: usize, verdaux_count: usize) { - debug_assert_eq!(self.gnu_verdef_offset, 0); - if verdef_count == 0 { - return; - } - self.gnu_verdef_size = verdef_count * mem::size_of::<elf::Verdef<Endianness>>() - + verdaux_count * mem::size_of::<elf::Verdaux<Endianness>>(); - self.gnu_verdef_offset = self.reserve(self.gnu_verdef_size, self.elf_align); - self.gnu_verdef_count = verdef_count as u16; - self.gnu_verdef_remaining = self.gnu_verdef_count; - } - - /// Write alignment padding bytes prior to a `.gnu.version_d` section. - pub fn write_align_gnu_verdef(&mut self) { - if self.gnu_verdef_offset == 0 { - return; - } - util::write_align(self.buffer, self.elf_align); - debug_assert_eq!(self.gnu_verdef_offset, self.buffer.len()); - } - - /// Write a version definition entry. - pub fn write_gnu_verdef(&mut self, verdef: &Verdef) { - debug_assert_ne!(self.gnu_verdef_remaining, 0); - self.gnu_verdef_remaining -= 1; - let vd_next = if self.gnu_verdef_remaining == 0 { - 0 - } else { - mem::size_of::<elf::Verdef<Endianness>>() as u32 - + verdef.aux_count as u32 * mem::size_of::<elf::Verdaux<Endianness>>() as u32 - }; - - self.gnu_verdaux_remaining = verdef.aux_count; - let vd_aux = if verdef.aux_count == 0 { - 0 - } else { - mem::size_of::<elf::Verdef<Endianness>>() as u32 - }; - - self.buffer.write(&elf::Verdef { - vd_version: U16::new(self.endian, verdef.version), - vd_flags: U16::new(self.endian, verdef.flags), - vd_ndx: U16::new(self.endian, verdef.index), - vd_cnt: U16::new(self.endian, verdef.aux_count), - vd_hash: U32::new(self.endian, elf::hash(self.dynstr.get_string(verdef.name))), - vd_aux: U32::new(self.endian, vd_aux), - vd_next: U32::new(self.endian, vd_next), - }); - self.write_gnu_verdaux(verdef.name); - } - - /// Write a version definition auxiliary entry. - pub fn write_gnu_verdaux(&mut self, name: StringId) { - debug_assert_ne!(self.gnu_verdaux_remaining, 0); - self.gnu_verdaux_remaining -= 1; - let vda_next = if self.gnu_verdaux_remaining == 0 { - 0 - } else { - mem::size_of::<elf::Verdaux<Endianness>>() as u32 - }; - self.buffer.write(&elf::Verdaux { - vda_name: U32::new(self.endian, self.dynstr.get_offset(name) as u32), - vda_next: U32::new(self.endian, vda_next), - }); - } - - /// Reserve the section index for the `.gnu.version_d` section. - pub fn reserve_gnu_verdef_section_index(&mut self) -> SectionIndex { - debug_assert!(self.gnu_verdef_str_id.is_none()); - self.gnu_verdef_str_id = Some(self.add_section_name(&b".gnu.version_d"[..])); - self.reserve_section_index() - } - - /// Write the section header for the `.gnu.version_d` section. - /// - /// This function does nothing if the section index was not reserved. - pub fn write_gnu_verdef_section_header(&mut self, sh_addr: u64) { - if self.gnu_verdef_str_id.is_none() { - return; - } - self.write_section_header(&SectionHeader { - name: self.gnu_verdef_str_id, - sh_type: elf::SHT_GNU_VERDEF, - sh_flags: elf::SHF_ALLOC.into(), - sh_addr, - sh_offset: self.gnu_verdef_offset as u64, - sh_size: self.gnu_verdef_size as u64, - sh_link: self.dynstr_index.0, - sh_info: self.gnu_verdef_count.into(), - sh_addralign: self.elf_align as u64, - sh_entsize: 0, - }); - } - - /// Reserve the range for the `.gnu.version_r` section. - pub fn reserve_gnu_verneed(&mut self, verneed_count: usize, vernaux_count: usize) { - debug_assert_eq!(self.gnu_verneed_offset, 0); - if verneed_count == 0 { - return; - } - self.gnu_verneed_size = verneed_count * mem::size_of::<elf::Verneed<Endianness>>() - + vernaux_count * mem::size_of::<elf::Vernaux<Endianness>>(); - self.gnu_verneed_offset = self.reserve(self.gnu_verneed_size, self.elf_align); - self.gnu_verneed_count = verneed_count as u16; - self.gnu_verneed_remaining = self.gnu_verneed_count; - } - - /// Write alignment padding bytes prior to a `.gnu.version_r` section. - pub fn write_align_gnu_verneed(&mut self) { - if self.gnu_verneed_offset == 0 { - return; - } - util::write_align(self.buffer, self.elf_align); - debug_assert_eq!(self.gnu_verneed_offset, self.buffer.len()); - } - - /// Write a version need entry. - pub fn write_gnu_verneed(&mut self, verneed: &Verneed) { - debug_assert_ne!(self.gnu_verneed_remaining, 0); - self.gnu_verneed_remaining -= 1; - let vn_next = if self.gnu_verneed_remaining == 0 { - 0 - } else { - mem::size_of::<elf::Verneed<Endianness>>() as u32 - + verneed.aux_count as u32 * mem::size_of::<elf::Vernaux<Endianness>>() as u32 - }; - - self.gnu_vernaux_remaining = verneed.aux_count; - let vn_aux = if verneed.aux_count == 0 { - 0 - } else { - mem::size_of::<elf::Verneed<Endianness>>() as u32 - }; - - self.buffer.write(&elf::Verneed { - vn_version: U16::new(self.endian, verneed.version), - vn_cnt: U16::new(self.endian, verneed.aux_count), - vn_file: U32::new(self.endian, self.dynstr.get_offset(verneed.file) as u32), - vn_aux: U32::new(self.endian, vn_aux), - vn_next: U32::new(self.endian, vn_next), - }); - } - - /// Write a version need auxiliary entry. - pub fn write_gnu_vernaux(&mut self, vernaux: &Vernaux) { - debug_assert_ne!(self.gnu_vernaux_remaining, 0); - self.gnu_vernaux_remaining -= 1; - let vna_next = if self.gnu_vernaux_remaining == 0 { - 0 - } else { - mem::size_of::<elf::Vernaux<Endianness>>() as u32 - }; - self.buffer.write(&elf::Vernaux { - vna_hash: U32::new(self.endian, elf::hash(self.dynstr.get_string(vernaux.name))), - vna_flags: U16::new(self.endian, vernaux.flags), - vna_other: U16::new(self.endian, vernaux.index), - vna_name: U32::new(self.endian, self.dynstr.get_offset(vernaux.name) as u32), - vna_next: U32::new(self.endian, vna_next), - }); - } - - /// Reserve the section index for the `.gnu.version_r` section. - pub fn reserve_gnu_verneed_section_index(&mut self) -> SectionIndex { - debug_assert!(self.gnu_verneed_str_id.is_none()); - self.gnu_verneed_str_id = Some(self.add_section_name(&b".gnu.version_r"[..])); - self.reserve_section_index() - } - - /// Write the section header for the `.gnu.version_r` section. - /// - /// This function does nothing if the section index was not reserved. - pub fn write_gnu_verneed_section_header(&mut self, sh_addr: u64) { - if self.gnu_verneed_str_id.is_none() { - return; - } - self.write_section_header(&SectionHeader { - name: self.gnu_verneed_str_id, - sh_type: elf::SHT_GNU_VERNEED, - sh_flags: elf::SHF_ALLOC.into(), - sh_addr, - sh_offset: self.gnu_verneed_offset as u64, - sh_size: self.gnu_verneed_size as u64, - sh_link: self.dynstr_index.0, - sh_info: self.gnu_verneed_count.into(), - sh_addralign: self.elf_align as u64, - sh_entsize: 0, - }); - } - - /// Reserve the section index for the `.gnu.attributes` section. - pub fn reserve_gnu_attributes_section_index(&mut self) -> SectionIndex { - debug_assert!(self.gnu_attributes_str_id.is_none()); - self.gnu_attributes_str_id = Some(self.add_section_name(&b".gnu.attributes"[..])); - self.reserve_section_index() - } - - /// Reserve the range for the `.gnu.attributes` section. - pub fn reserve_gnu_attributes(&mut self, gnu_attributes_size: usize) { - debug_assert_eq!(self.gnu_attributes_offset, 0); - if gnu_attributes_size == 0 { - return; - } - self.gnu_attributes_size = gnu_attributes_size; - self.gnu_attributes_offset = self.reserve(self.gnu_attributes_size, self.elf_align); - } - - /// Write the section header for the `.gnu.attributes` section. - /// - /// This function does nothing if the section index was not reserved. - pub fn write_gnu_attributes_section_header(&mut self) { - if self.gnu_attributes_str_id.is_none() { - return; - } - self.write_section_header(&SectionHeader { - name: self.gnu_attributes_str_id, - sh_type: elf::SHT_GNU_ATTRIBUTES, - sh_flags: 0, - sh_addr: 0, - sh_offset: self.gnu_attributes_offset as u64, - sh_size: self.gnu_attributes_size as u64, - sh_link: self.dynstr_index.0, - sh_info: 0, // TODO - sh_addralign: self.elf_align as u64, - sh_entsize: 0, - }); - } - - /// Write the data for the `.gnu.attributes` section. - pub fn write_gnu_attributes(&mut self, data: &[u8]) { - if self.gnu_attributes_offset == 0 { - return; - } - util::write_align(self.buffer, self.elf_align); - debug_assert_eq!(self.gnu_attributes_offset, self.buffer.len()); - self.buffer.write_bytes(data); - } - - /// Reserve a file range for the given number of relocations. - /// - /// Returns the offset of the range. - pub fn reserve_relocations(&mut self, count: usize, is_rela: bool) -> usize { - self.reserve(count * self.rel_size(is_rela), self.elf_align) - } - - /// Write alignment padding bytes prior to a relocation section. - pub fn write_align_relocation(&mut self) { - util::write_align(self.buffer, self.elf_align); - } - - /// Write a relocation. - pub fn write_relocation(&mut self, is_rela: bool, rel: &Rel) { - let endian = self.endian; - if self.is_64 { - if is_rela { - let rel = elf::Rela64 { - r_offset: U64::new(endian, rel.r_offset), - r_info: elf::Rela64::r_info(endian, self.is_mips64el, rel.r_sym, rel.r_type), - r_addend: I64::new(endian, rel.r_addend), - }; - self.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), - }; - self.buffer.write(&rel); - } - } else { - 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), - }; - self.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), - }; - self.buffer.write(&rel); - } - } - } - - /// Write the section header for a relocation section. - /// - /// `section` is the index of the section the relocations apply to, - /// or 0 if none. - /// - /// `symtab` is the index of the symbol table the relocations refer to, - /// or 0 if none. - /// - /// `offset` is the file offset of the relocations. - pub fn write_relocation_section_header( - &mut self, - name: StringId, - section: SectionIndex, - symtab: SectionIndex, - offset: usize, - count: usize, - is_rela: bool, - ) { - self.write_section_header(&SectionHeader { - name: Some(name), - sh_type: if is_rela { elf::SHT_RELA } else { elf::SHT_REL }, - sh_flags: elf::SHF_INFO_LINK.into(), - sh_addr: 0, - sh_offset: offset as u64, - sh_size: (count * self.rel_size(is_rela)) as u64, - sh_link: symtab.0, - sh_info: section.0, - sh_addralign: self.elf_align as u64, - sh_entsize: self.rel_size(is_rela) as u64, - }); - } - - /// Reserve a file range for a COMDAT section. - /// - /// `count` is the number of sections in the COMDAT group. - /// - /// Returns the offset of the range. - pub fn reserve_comdat(&mut self, count: usize) -> usize { - self.reserve((count + 1) * 4, 4) - } - - /// Write `GRP_COMDAT` at the start of the COMDAT section. - pub fn write_comdat_header(&mut self) { - util::write_align(self.buffer, 4); - self.buffer.write(&U32::new(self.endian, elf::GRP_COMDAT)); - } - - /// Write an entry in a COMDAT section. - pub fn write_comdat_entry(&mut self, entry: SectionIndex) { - self.buffer.write(&U32::new(self.endian, entry.0)); - } - - /// Write the section header for a COMDAT section. - pub fn write_comdat_section_header( - &mut self, - name: StringId, - symtab: SectionIndex, - symbol: SymbolIndex, - offset: usize, - count: usize, - ) { - self.write_section_header(&SectionHeader { - name: Some(name), - sh_type: elf::SHT_GROUP, - sh_flags: 0, - sh_addr: 0, - sh_offset: offset as u64, - sh_size: ((count + 1) * 4) as u64, - sh_link: symtab.0, - sh_info: symbol.0, - sh_addralign: 4, - sh_entsize: 4, - }); - } - - /// Return a helper for writing an attributes section. - pub fn attributes_writer(&self) -> AttributesWriter { - AttributesWriter::new(self.endian) - } -} - -/// A helper for writing an attributes section. -/// -/// Attributes have a variable length encoding, so it is awkward to write them in a -/// single pass. Instead, we build the entire attributes section data in memory, using -/// placeholders for unknown lengths that are filled in later. -#[allow(missing_debug_implementations)] -pub struct AttributesWriter { - endian: Endianness, - data: Vec<u8>, - subsection_offset: usize, - subsubsection_offset: usize, -} - -impl AttributesWriter { - /// Create a new `AttributesWriter` for the given endianness. - pub fn new(endian: Endianness) -> Self { - AttributesWriter { - endian, - data: vec![0x41], - subsection_offset: 0, - subsubsection_offset: 0, - } - } - - /// Start a new subsection with the given vendor name. - pub fn start_subsection(&mut self, vendor: &[u8]) { - debug_assert_eq!(self.subsection_offset, 0); - debug_assert_eq!(self.subsubsection_offset, 0); - self.subsection_offset = self.data.len(); - self.data.extend_from_slice(&[0; 4]); - self.data.extend_from_slice(vendor); - self.data.push(0); - } - - /// End the subsection. - /// - /// The subsection length is automatically calculated and written. - pub fn end_subsection(&mut self) { - debug_assert_ne!(self.subsection_offset, 0); - debug_assert_eq!(self.subsubsection_offset, 0); - let length = self.data.len() - self.subsection_offset; - self.data[self.subsection_offset..][..4] - .copy_from_slice(pod::bytes_of(&U32::new(self.endian, length as u32))); - self.subsection_offset = 0; - } - - /// Start a new sub-subsection with the given tag. - pub fn start_subsubsection(&mut self, tag: u8) { - debug_assert_ne!(self.subsection_offset, 0); - debug_assert_eq!(self.subsubsection_offset, 0); - self.subsubsection_offset = self.data.len(); - self.data.push(tag); - self.data.extend_from_slice(&[0; 4]); - } - - /// Write a section or symbol index to the sub-subsection. - /// - /// The user must also call this function to write the terminating 0 index. - pub fn write_subsubsection_index(&mut self, index: u32) { - debug_assert_ne!(self.subsection_offset, 0); - debug_assert_ne!(self.subsubsection_offset, 0); - util::write_uleb128(&mut self.data, u64::from(index)); - } - - /// Write raw index data to the sub-subsection. - /// - /// The terminating 0 index is automatically written. - pub fn write_subsubsection_indices(&mut self, indices: &[u8]) { - debug_assert_ne!(self.subsection_offset, 0); - debug_assert_ne!(self.subsubsection_offset, 0); - self.data.extend_from_slice(indices); - self.data.push(0); - } - - /// Write an attribute tag to the sub-subsection. - pub fn write_attribute_tag(&mut self, tag: u64) { - debug_assert_ne!(self.subsection_offset, 0); - debug_assert_ne!(self.subsubsection_offset, 0); - util::write_uleb128(&mut self.data, tag); - } - - /// Write an attribute integer value to the sub-subsection. - pub fn write_attribute_integer(&mut self, value: u64) { - debug_assert_ne!(self.subsection_offset, 0); - debug_assert_ne!(self.subsubsection_offset, 0); - util::write_uleb128(&mut self.data, value); - } - - /// Write an attribute string value to the sub-subsection. - /// - /// The value must not include the null terminator. - pub fn write_attribute_string(&mut self, value: &[u8]) { - debug_assert_ne!(self.subsection_offset, 0); - debug_assert_ne!(self.subsubsection_offset, 0); - self.data.extend_from_slice(value); - self.data.push(0); - } - - /// Write raw attribute data to the sub-subsection. - pub fn write_subsubsection_attributes(&mut self, attributes: &[u8]) { - debug_assert_ne!(self.subsection_offset, 0); - debug_assert_ne!(self.subsubsection_offset, 0); - self.data.extend_from_slice(attributes); - } - - /// End the sub-subsection. - /// - /// The sub-subsection length is automatically calculated and written. - pub fn end_subsubsection(&mut self) { - debug_assert_ne!(self.subsection_offset, 0); - debug_assert_ne!(self.subsubsection_offset, 0); - let length = self.data.len() - self.subsubsection_offset; - self.data[self.subsubsection_offset + 1..][..4] - .copy_from_slice(pod::bytes_of(&U32::new(self.endian, length as u32))); - self.subsubsection_offset = 0; - } - - /// Return the completed section data. - pub fn data(self) -> Vec<u8> { - debug_assert_eq!(self.subsection_offset, 0); - debug_assert_eq!(self.subsubsection_offset, 0); - self.data - } -} - -/// Native endian version of [`elf::FileHeader64`]. -#[allow(missing_docs)] -#[derive(Debug, Clone)] -pub struct FileHeader { - pub os_abi: u8, - pub abi_version: u8, - pub e_type: u16, - pub e_machine: u16, - pub e_entry: u64, - pub e_flags: u32, -} - -/// Native endian version of [`elf::ProgramHeader64`]. -#[allow(missing_docs)] -#[derive(Debug, Clone)] -pub struct ProgramHeader { - pub p_type: u32, - pub p_flags: u32, - pub p_offset: u64, - pub p_vaddr: u64, - pub p_paddr: u64, - pub p_filesz: u64, - pub p_memsz: u64, - pub p_align: u64, -} - -/// Native endian version of [`elf::SectionHeader64`]. -#[allow(missing_docs)] -#[derive(Debug, Clone)] -pub struct SectionHeader { - pub name: Option<StringId>, - pub sh_type: u32, - pub sh_flags: u64, - pub sh_addr: u64, - pub sh_offset: u64, - pub sh_size: u64, - pub sh_link: u32, - pub sh_info: u32, - pub sh_addralign: u64, - pub sh_entsize: u64, -} - -/// Native endian version of [`elf::Sym64`]. -#[allow(missing_docs)] -#[derive(Debug, Clone)] -pub struct Sym { - pub name: Option<StringId>, - pub section: Option<SectionIndex>, - pub st_info: u8, - pub st_other: u8, - pub st_shndx: u16, - pub st_value: u64, - pub st_size: u64, -} - -/// Unified native endian version of [`elf::Rel64`] and [`elf::Rela64`]. -#[allow(missing_docs)] -#[derive(Debug, Clone)] -pub struct Rel { - pub r_offset: u64, - pub r_sym: u32, - pub r_type: u32, - pub r_addend: i64, -} - -/// Information required for writing [`elf::Verdef`]. -#[allow(missing_docs)] -#[derive(Debug, Clone)] -pub struct Verdef { - pub version: u16, - pub flags: u16, - pub index: u16, - pub aux_count: u16, - /// The name for the first [`elf::Verdaux`] entry. - pub name: StringId, -} - -/// Information required for writing [`elf::Verneed`]. -#[allow(missing_docs)] -#[derive(Debug, Clone)] -pub struct Verneed { - pub version: u16, - pub aux_count: u16, - pub file: StringId, -} - -/// Information required for writing [`elf::Vernaux`]. -#[allow(missing_docs)] -#[derive(Debug, Clone)] -pub struct Vernaux { - pub flags: u16, - pub index: u16, - pub name: StringId, -} |