diff options
Diffstat (limited to 'third_party/rust/parity-wasm/src/elements/reloc_section.rs')
-rw-r--r-- | third_party/rust/parity-wasm/src/elements/reloc_section.rs | 347 |
1 files changed, 347 insertions, 0 deletions
diff --git a/third_party/rust/parity-wasm/src/elements/reloc_section.rs b/third_party/rust/parity-wasm/src/elements/reloc_section.rs new file mode 100644 index 0000000000..50c867f7ca --- /dev/null +++ b/third_party/rust/parity-wasm/src/elements/reloc_section.rs @@ -0,0 +1,347 @@ +use alloc::{string::String, vec::Vec}; +use crate::io; + +use super::{CountedList, CountedListWriter, CountedWriter, Deserialize, Error, Serialize, VarInt32, VarUint32, VarUint7}; + +const FUNCTION_INDEX_LEB: u8 = 0; +const TABLE_INDEX_SLEB: u8 = 1; +const TABLE_INDEX_I32: u8 = 2; +const MEMORY_ADDR_LEB: u8 = 3; +const MEMORY_ADDR_SLEB: u8 = 4; +const MEMORY_ADDR_I32: u8 = 5; +const TYPE_INDEX_LEB: u8 = 6; +const GLOBAL_INDEX_LEB: u8 = 7; + +/// Relocation information. +#[derive(Clone, Debug, PartialEq)] +pub struct RelocSection { + /// Name of this section. + name: String, + + /// ID of the section containing the relocations described in this section. + section_id: u32, + + /// Name of the section containing the relocations described in this section. Only set if section_id is 0. + relocation_section_name: Option<String>, + + /// Relocation entries. + entries: Vec<RelocationEntry>, +} + +impl RelocSection { + /// Name of this section. + pub fn name(&self) -> &str { + &self.name + } + + /// Name of this section (mutable). + pub fn name_mut(&mut self) -> &mut String { + &mut self.name + } + + /// ID of the section containing the relocations described in this section. + pub fn section_id(&self) -> u32 { + self.section_id + } + + /// ID of the section containing the relocations described in this section (mutable). + pub fn section_id_mut(&mut self) -> &mut u32 { + &mut self.section_id + } + + /// Name of the section containing the relocations described in this section. + pub fn relocation_section_name(&self) -> Option<&str> { + self.relocation_section_name.as_ref().map(String::as_str) + } + + /// Name of the section containing the relocations described in this section (mutable). + pub fn relocation_section_name_mut(&mut self) -> &mut Option<String> { + &mut self.relocation_section_name + } + + /// List of relocation entries. + pub fn entries(&self) -> &[RelocationEntry] { + &self.entries + } + + /// List of relocation entries (mutable). + pub fn entries_mut(&mut self) -> &mut Vec<RelocationEntry> { + &mut self.entries + } +} + +impl RelocSection { + /// Deserialize a reloc section. + pub fn deserialize<R: io::Read>( + name: String, + rdr: &mut R, + ) -> Result<Self, Error> { + let section_id = VarUint32::deserialize(rdr)?.into(); + + let relocation_section_name = + if section_id == 0 { + Some(String::deserialize(rdr)?) + } + else { + None + }; + + let entries = CountedList::deserialize(rdr)?.into_inner(); + + Ok(RelocSection { + name, + section_id, + relocation_section_name, + entries, + }) + } +} + +impl Serialize for RelocSection { + type Error = Error; + + fn serialize<W: io::Write>(self, wtr: &mut W) -> Result<(), Error> { + let mut counted_writer = CountedWriter::new(wtr); + + self.name.serialize(&mut counted_writer)?; + + VarUint32::from(self.section_id).serialize(&mut counted_writer)?; + + if let Some(relocation_section_name) = self.relocation_section_name { + relocation_section_name.serialize(&mut counted_writer)?; + } + + let counted_list = CountedListWriter(self.entries.len(), self.entries.into_iter()); + counted_list.serialize(&mut counted_writer)?; + + counted_writer.done()?; + + Ok(()) + } +} + +/// Relocation entry. +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum RelocationEntry { + /// Function index. + FunctionIndexLeb { + /// Offset of the value to rewrite. + offset: u32, + + /// Index of the function symbol in the symbol table. + index: u32, + }, + + /// Function table index. + TableIndexSleb { + /// Offset of the value to rewrite. + offset: u32, + + /// Index of the function symbol in the symbol table. + index: u32, + }, + + /// Function table index. + TableIndexI32 { + /// Offset of the value to rewrite. + offset: u32, + + /// Index of the function symbol in the symbol table. + index: u32, + }, + + /// Linear memory index. + MemoryAddressLeb { + /// Offset of the value to rewrite. + offset: u32, + + /// Index of the data symbol in the symbol table. + index: u32, + + /// Addend to add to the address. + addend: i32, + }, + + /// Linear memory index. + MemoryAddressSleb { + /// Offset of the value to rewrite. + offset: u32, + + /// Index of the data symbol in the symbol table. + index: u32, + + /// Addend to add to the address. + addend: i32, + }, + + /// Linear memory index. + MemoryAddressI32 { + /// Offset of the value to rewrite. + offset: u32, + + /// Index of the data symbol in the symbol table. + index: u32, + + /// Addend to add to the address. + addend: i32, + }, + + /// Type table index. + TypeIndexLeb { + /// Offset of the value to rewrite. + offset: u32, + + /// Index of the type used. + index: u32, + }, + + /// Global index. + GlobalIndexLeb { + /// Offset of the value to rewrite. + offset: u32, + + /// Index of the global symbol in the symbol table. + index: u32, + }, +} + +impl Deserialize for RelocationEntry { + type Error = Error; + + fn deserialize<R: io::Read>(rdr: &mut R) -> Result<Self, Self::Error> { + match VarUint7::deserialize(rdr)?.into() { + FUNCTION_INDEX_LEB => Ok(RelocationEntry::FunctionIndexLeb { + offset: VarUint32::deserialize(rdr)?.into(), + index: VarUint32::deserialize(rdr)?.into(), + }), + + TABLE_INDEX_SLEB => Ok(RelocationEntry::TableIndexSleb { + offset: VarUint32::deserialize(rdr)?.into(), + index: VarUint32::deserialize(rdr)?.into(), + }), + + TABLE_INDEX_I32 => Ok(RelocationEntry::TableIndexI32 { + offset: VarUint32::deserialize(rdr)?.into(), + index: VarUint32::deserialize(rdr)?.into(), + }), + + MEMORY_ADDR_LEB => Ok(RelocationEntry::MemoryAddressLeb { + offset: VarUint32::deserialize(rdr)?.into(), + index: VarUint32::deserialize(rdr)?.into(), + addend: VarInt32::deserialize(rdr)?.into(), + }), + + MEMORY_ADDR_SLEB => Ok(RelocationEntry::MemoryAddressSleb { + offset: VarUint32::deserialize(rdr)?.into(), + index: VarUint32::deserialize(rdr)?.into(), + addend: VarInt32::deserialize(rdr)?.into(), + }), + + MEMORY_ADDR_I32 => Ok(RelocationEntry::MemoryAddressI32 { + offset: VarUint32::deserialize(rdr)?.into(), + index: VarUint32::deserialize(rdr)?.into(), + addend: VarInt32::deserialize(rdr)?.into(), + }), + + TYPE_INDEX_LEB => Ok(RelocationEntry::TypeIndexLeb { + offset: VarUint32::deserialize(rdr)?.into(), + index: VarUint32::deserialize(rdr)?.into(), + }), + + GLOBAL_INDEX_LEB => Ok(RelocationEntry::GlobalIndexLeb { + offset: VarUint32::deserialize(rdr)?.into(), + index: VarUint32::deserialize(rdr)?.into(), + }), + + entry_type => Err(Error::UnknownValueType(entry_type as i8)), + } + } +} + +impl Serialize for RelocationEntry { + type Error = Error; + + fn serialize<W: io::Write>(self, wtr: &mut W) -> Result<(), Error> { + match self { + RelocationEntry::FunctionIndexLeb { offset, index } => { + VarUint7::from(FUNCTION_INDEX_LEB).serialize(wtr)?; + VarUint32::from(offset).serialize(wtr)?; + VarUint32::from(index).serialize(wtr)?; + }, + + RelocationEntry::TableIndexSleb { offset, index } => { + VarUint7::from(TABLE_INDEX_SLEB).serialize(wtr)?; + VarUint32::from(offset).serialize(wtr)?; + VarUint32::from(index).serialize(wtr)?; + }, + + RelocationEntry::TableIndexI32 { offset, index } => { + VarUint7::from(TABLE_INDEX_I32).serialize(wtr)?; + VarUint32::from(offset).serialize(wtr)?; + VarUint32::from(index).serialize(wtr)?; + }, + + RelocationEntry::MemoryAddressLeb { offset, index, addend } => { + VarUint7::from(MEMORY_ADDR_LEB).serialize(wtr)?; + VarUint32::from(offset).serialize(wtr)?; + VarUint32::from(index).serialize(wtr)?; + VarInt32::from(addend).serialize(wtr)?; + }, + + RelocationEntry::MemoryAddressSleb { offset, index, addend } => { + VarUint7::from(MEMORY_ADDR_SLEB).serialize(wtr)?; + VarUint32::from(offset).serialize(wtr)?; + VarUint32::from(index).serialize(wtr)?; + VarInt32::from(addend).serialize(wtr)?; + }, + + RelocationEntry::MemoryAddressI32 { offset, index, addend } => { + VarUint7::from(MEMORY_ADDR_I32).serialize(wtr)?; + VarUint32::from(offset).serialize(wtr)?; + VarUint32::from(index).serialize(wtr)?; + VarInt32::from(addend).serialize(wtr)?; + }, + + RelocationEntry::TypeIndexLeb { offset, index } => { + VarUint7::from(TYPE_INDEX_LEB).serialize(wtr)?; + VarUint32::from(offset).serialize(wtr)?; + VarUint32::from(index).serialize(wtr)?; + }, + + RelocationEntry::GlobalIndexLeb { offset, index } => { + VarUint7::from(GLOBAL_INDEX_LEB).serialize(wtr)?; + VarUint32::from(offset).serialize(wtr)?; + VarUint32::from(index).serialize(wtr)?; + }, + } + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::super::{Section, deserialize_file}; + use super::RelocationEntry; + + #[test] + fn reloc_section() { + let module = + deserialize_file("./res/cases/v1/relocatable.wasm").expect("Module should be deserialized") + .parse_reloc().expect("Reloc section should be deserialized"); + let mut found = false; + for section in module.sections() { + match *section { + Section::Reloc(ref reloc_section) => { + assert_eq!(vec![ + RelocationEntry::MemoryAddressSleb { offset: 4, index: 0, addend: 0 }, + RelocationEntry::FunctionIndexLeb { offset: 12, index: 0 }, + ], reloc_section.entries()); + found = true + }, + _ => { } + } + } + assert!(found, "There should be a reloc section in relocatable.wasm"); + } +} |