aboutsummaryrefslogtreecommitdiff
path: root/vendor/object/src/write/elf
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2024-07-19 15:37:58 +0300
committerValentin Popov <valentin@popov.link>2024-07-19 15:37:58 +0300
commita990de90fe41456a23e58bd087d2f107d321f3a1 (patch)
tree15afc392522a9e85dc3332235e311b7d39352ea9 /vendor/object/src/write/elf
parent3d48cd3f81164bbfc1a755dc1d4a9a02f98c8ddd (diff)
downloadfparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.tar.xz
fparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.zip
Deleted vendor folder
Diffstat (limited to 'vendor/object/src/write/elf')
-rw-r--r--vendor/object/src/write/elf/mod.rs9
-rw-r--r--vendor/object/src/write/elf/object.rs907
-rw-r--r--vendor/object/src/write/elf/writer.rs2143
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(&section.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(&section.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(&section.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 &section.relocations {
- let r_type = match self.architecture {
- Architecture::Aarch64 => match (reloc.kind, reloc.encoding, reloc.size) {
- (RelocationKind::Absolute, RelocationEncoding::Generic, 64) => {
- elf::R_AARCH64_ABS64
- }
- (RelocationKind::Absolute, RelocationEncoding::Generic, 32) => {
- elf::R_AARCH64_ABS32
- }
- (RelocationKind::Absolute, RelocationEncoding::Generic, 16) => {
- elf::R_AARCH64_ABS16
- }
- (RelocationKind::Relative, RelocationEncoding::Generic, 64) => {
- elf::R_AARCH64_PREL64
- }
- (RelocationKind::Relative, RelocationEncoding::Generic, 32) => {
- elf::R_AARCH64_PREL32
- }
- (RelocationKind::Relative, RelocationEncoding::Generic, 16) => {
- elf::R_AARCH64_PREL16
- }
- (RelocationKind::Relative, RelocationEncoding::AArch64Call, 26)
- | (RelocationKind::PltRelative, RelocationEncoding::AArch64Call, 26) => {
- elf::R_AARCH64_CALL26
- }
- (RelocationKind::Elf(x), _, _) => x,
- _ => {
- return Err(Error(format!("unimplemented relocation {:?}", reloc)));
- }
- },
- Architecture::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(&section);
- } 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(&section);
- }
- }
-
- /// 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,
-}