diff options
Diffstat (limited to 'vendor/object/src/write/elf/object.rs')
-rw-r--r-- | vendor/object/src/write/elf/object.rs | 115 |
1 files changed, 86 insertions, 29 deletions
diff --git a/vendor/object/src/write/elf/object.rs b/vendor/object/src/write/elf/object.rs index 068ada6bd..8b9eadaf8 100644 --- a/vendor/object/src/write/elf/object.rs +++ b/vendor/object/src/write/elf/object.rs @@ -1,10 +1,10 @@ use alloc::vec::Vec; -use crate::elf; 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 { @@ -27,33 +27,88 @@ struct SymbolOffsets { 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) { + ) -> (&'static [u8], &'static [u8], SectionKind, SectionFlags) { match section { - StandardSection::Text => (&[], &b".text"[..], SectionKind::Text), - StandardSection::Data => (&[], &b".data"[..], SectionKind::Data), - StandardSection::ReadOnlyData | StandardSection::ReadOnlyString => { - (&[], &b".rodata"[..], SectionKind::ReadOnlyData) - } - StandardSection::ReadOnlyDataWithRel => (&[], b".data.rel.ro", SectionKind::Data), - StandardSection::UninitializedData => { - (&[], &b".bss"[..], SectionKind::UninitializedData) - } - StandardSection::Tls => (&[], &b".tdata"[..], SectionKind::Tls), - StandardSection::UninitializedTls => { - (&[], &b".tbss"[..], SectionKind::UninitializedTls) - } + StandardSection::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) + (&[], &[], SectionKind::TlsVariables, SectionFlags::None) } StandardSection::Common => { // Unsupported section. - (&[], &[], SectionKind::Common) + (&[], &[], SectionKind::Common, SectionFlags::None) } + StandardSection::GnuProperty => ( + &[], + &b".note.gnu.property"[..], + SectionKind::Note, + SectionFlags::Elf { + sh_flags: u64::from(elf::SHF_ALLOC), + }, + ), } } @@ -151,6 +206,13 @@ impl<'a> Object<'a> { } } + 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()?; @@ -174,11 +236,7 @@ impl<'a> Object<'a> { .collect(); // Start calculating offsets of everything. - let is_64 = match self.architecture.address_size().unwrap() { - AddressSize::U8 | AddressSize::U16 | AddressSize::U32 => false, - AddressSize::U64 => true, - }; - let mut writer = Writer::new(self.endian, is_64, buffer); + let mut writer = Writer::new(self.endian, self.elf_is_64(), buffer); writer.reserve_file_header(); // Calculate size of section data. @@ -321,12 +379,9 @@ impl<'a> Object<'a> { } } for (index, section) in self.sections.iter().enumerate() { - let len = section.data.len(); - if len != 0 { - writer.write_align(section.align as usize); - debug_assert_eq!(section_offsets[index].offset, writer.len()); - writer.write(§ion.data); - } + writer.write_align(section.align as usize); + debug_assert_eq!(section_offsets[index].offset, writer.len()); + writer.write(§ion.data); } // Write symbols. @@ -767,7 +822,9 @@ impl<'a> Object<'a> { } else { match section.kind { SectionKind::Text => elf::SHF_ALLOC | elf::SHF_EXECINSTR, - SectionKind::Data => elf::SHF_ALLOC | elf::SHF_WRITE, + 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, |