use super::*;
use std::convert::TryInto;
#[derive(Clone, Debug)]
pub struct LinkingSection {
bytes: Vec<u8>,
}
impl LinkingSection {
pub fn new() -> Self {
LinkingSection { bytes: vec![] }
}
pub fn symbol_table(&mut self, symbol_table: &SymbolTable) -> &mut Self {
symbol_table.encode(&mut self.bytes);
self
}
}
impl Section for LinkingSection {
fn id(&self) -> u8 {
SectionId::Custom.into()
}
fn encode<S>(&self, sink: &mut S)
where
S: Extend<u8>,
{
let name_len = encoders::u32(u32::try_from("linking".len()).unwrap());
let name_len_len = name_len.len();
let version = 2;
sink.extend(
encoders::u32(
u32::try_from(name_len_len + "linking".len() + 1 + self.bytes.len()).unwrap(),
)
.chain(name_len)
.chain(b"linking".iter().copied())
.chain(encoders::u32(version))
.chain(self.bytes.iter().copied()),
);
}
}
#[allow(unused)]
const WASM_SEGMENT_INFO: u8 = 5;
#[allow(unused)]
const WASM_INIT_FUNCS: u8 = 6;
#[allow(unused)]
const WASM_COMDAT_INFO: u8 = 7;
const WASM_SYMBOL_TABLE: u8 = 8;
#[derive(Clone, Debug)]
pub struct SymbolTable {
bytes: Vec<u8>,
num_added: u32,
}
const SYMTAB_FUNCTION: u32 = 0;
const SYMTAB_DATA: u32 = 1;
const SYMTAB_GLOBAL: u32 = 2;
#[allow(unused)]
const SYMTAB_SECTION: u32 = 3;
#[allow(unused)]
const SYMTAB_TAG: u32 = 4;
const SYMTAB_TABLE: u32 = 5;
impl SymbolTable {
pub fn new() -> Self {
SymbolTable {
bytes: vec![],
num_added: 0,
}
}
pub fn function(&mut self, flags: u32, index: u32, name: Option<&str>) -> &mut Self {
self.bytes.extend(
encoders::u32(SYMTAB_FUNCTION)
.chain(encoders::u32(flags))
.chain(encoders::u32(index)),
);
if let Some(name) = name {
self.bytes.extend(
encoders::u32(name.len().try_into().unwrap())
.chain(name.as_bytes().iter().copied()),
);
}
self.num_added += 1;
self
}
pub fn global(&mut self, flags: u32, index: u32, name: Option<&str>) -> &mut Self {
self.bytes.extend(
encoders::u32(SYMTAB_GLOBAL)
.chain(encoders::u32(flags))
.chain(encoders::u32(index)),
);
if let Some(name) = name {
self.bytes.extend(
encoders::u32(name.len().try_into().unwrap())
.chain(name.as_bytes().iter().copied()),
);
}
self.num_added += 1;
self
}
pub fn table(&mut self, flags: u32, index: u32, name: Option<&str>) -> &mut Self {
self.bytes.extend(
encoders::u32(SYMTAB_TABLE)
.chain(encoders::u32(flags))
.chain(encoders::u32(index)),
);
if let Some(name) = name {
self.bytes.extend(
encoders::u32(name.len().try_into().unwrap())
.chain(name.as_bytes().iter().copied()),
);
}
self.num_added += 1;
self
}
pub fn data(
&mut self,
flags: u32,
name: &str,
definition: Option<DataSymbolDefinition>,
) -> &mut Self {
self.bytes.extend(
encoders::u32(SYMTAB_DATA)
.chain(encoders::u32(flags))
.chain(encoders::u32(name.len().try_into().unwrap()))
.chain(name.as_bytes().iter().copied()),
);
if let Some(def) = definition {
self.bytes.extend(
encoders::u32(def.index)
.chain(encoders::u32(def.offset))
.chain(encoders::u32(def.size)),
);
}
self.num_added += 1;
self
}
fn encode(&self, bytes: &mut Vec<u8>) {
let num_added = encoders::u32(self.num_added);
let num_added_len = num_added.len();
let payload_len = num_added_len + self.bytes.len();
bytes.extend(
std::iter::once(WASM_SYMBOL_TABLE)
.chain(encoders::u32(payload_len.try_into().unwrap()))
.chain(num_added)
.chain(self.bytes.iter().copied()),
);
}
}
impl SymbolTable {
pub const WASM_SYM_BINDING_WEAK: u32 = 0x1;
pub const WASM_SYM_BINDING_LOCAL: u32 = 0x02;
pub const WASM_SYM_VISIBILITY_HIDDEN: u32 = 0x04;
pub const WASM_SYM_UNDEFINED: u32 = 0x10;
pub const WASM_SYM_EXPORTED: u32 = 0x20;
pub const WASM_SYM_EXPLICIT_NAME: u32 = 0x40;
pub const WASM_SYM_NO_STRIP: u32 = 0x80;
}
#[derive(Clone, Debug)]
pub struct DataSymbolDefinition {
pub index: u32,
pub offset: u32,
pub size: u32,
}