1
2use std::{mem};
3
4#[derive(Clone, Debug)]
5struct Reader<'a> {
6 bytes: &'a [u8],
7 offset: usize
8}
9
10#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
11pub struct WasmParseError;
12
13impl<'a> Reader<'a> {
14 fn new(bytes: &'a [u8]) -> Reader<'a> {
15 Reader { bytes, offset:0 }
16 }
17
18 fn skip(&mut self, count: usize) -> Result<(),WasmParseError> {
19 if count > self.bytes.len() {
20 return Err(WasmParseError);
21 }
22 self.offset += count;
23 self.bytes = &self.bytes[count..];
24 Ok(())
25 }
26
27 fn read(&mut self, bytes: &mut [u8]) -> Result<(),WasmParseError> {
28 if bytes.len() > self.bytes.len() {
29 return Err(WasmParseError);
30 }
31 bytes.copy_from_slice(&self.bytes[..bytes.len()]);
32 self.bytes = &self.bytes[bytes.len()..];
33 self.offset += bytes.len();
34 Ok(())
35 }
36
37 fn read_u8(&mut self) -> Result<u8,WasmParseError> {
38 let mut bytes = [0; mem::size_of::<u8>()];
39 self.read(&mut bytes)?;
40 Ok(u8::from_le_bytes(bytes))
41 }
42
43 fn read_u32(&mut self) -> Result<u32,WasmParseError> {
44 let mut bytes = [0; mem::size_of::<u32>()];
45 self.read(&mut bytes)?;
46 Ok(u32::from_le_bytes(bytes))
47 }
48
49 fn read_var_u32(&mut self) -> Result<u32,WasmParseError>{
50 let byte = self.read_u8()? as u32;
51 if byte&0x80 == 0{
52 return Ok(byte)
53 }
54
55 let mut result = byte & 0x7F;
56 let mut shift = 7;
57 loop {
58 let byte = self.read_u8()?;
59 result |= ((byte & 0x7F) as u32) << shift;
60 if shift >= 25 && (byte >> (32 - shift)) != 0 {
61 return Err(WasmParseError);
63 }
64 shift += 7;
65 if (byte & 0x80) == 0 {
66 break;
67 }
68 }
69 Ok(result)
70 }
71
72}
73
74struct WasmSection{
75 pub type_id: u8,
76 pub start: usize,
77 pub end: usize,
78 pub name: String
79}
80
81fn read_wasm_sections(buf:&[u8])->Result<Vec<WasmSection>,WasmParseError>{
82 let mut sections = Vec::new();
83 let mut reader = Reader::new(&buf);
84 if reader.read_u32()? != 0x6d736100{
85 println!("Not a wasm file!");
86 return Err(WasmParseError);
87 }
88 if reader.read_u32()? != 0x1{
89 println!("Wrong version");
90 return Err(WasmParseError);
91 }
92 loop{
93 let offset = reader.offset;
94 if let Ok(type_id) = reader.read_u8(){
95 let payload_len = reader.read_var_u32()? as usize;
96 let start = reader.offset;
97 if type_id == 0{
98 let name_len = reader.read_var_u32()? as usize;
99 if let Ok(name) = std::str::from_utf8(&reader.bytes[0..name_len]){
100 sections.push(WasmSection{
101 start: offset,
102 type_id: type_id,
103 end: offset + payload_len + (start-offset),
104 name: name.to_string()
105 })
106 }
107 else{
108 return Err(WasmParseError);
109 }
110 let end = reader.offset;
111 reader.skip(payload_len - (end-start))?;
112 }
113 else{
114 sections.push(WasmSection{
115 start: offset,
116 type_id: type_id,
117 end: offset + payload_len + (start-offset),
118 name: "".to_string()
119 });
120 reader.skip(payload_len)?;
121 }
122 }
123 else{
124 break;
125 }
126 }
127 return Ok(sections);
128}
129
130pub fn wasm_strip_debug(buf: &[u8])->Result<Vec<u8>,WasmParseError>{
131 let mut strip = Vec::new();
132 strip.extend_from_slice(&[0, 97, 115, 109, 1, 0, 0, 0]);
133 let sections = read_wasm_sections(&buf)?;
134 for section in §ions{
136 if section.type_id != 0{strip.extend_from_slice(&buf[section.start..section.end]);
138 }
139
140 }
141 Ok(strip)
142}