1 /* Copyright 2018 Mozilla Foundation 2 * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 use core::iter::{IntoIterator, Iterator}; 17 18 use super::{ 19 BinaryReader, BinaryReaderError, CustomSectionKind, Range, Result, SectionCode, SectionHeader, 20 }; 21 22 use super::{ 23 read_data_count_section_content, read_sourcemappingurl_section_content, 24 read_start_section_content, CodeSectionReader, DataSectionReader, ElementSectionReader, 25 ExportSectionReader, FunctionSectionReader, GlobalSectionReader, ImportSectionReader, 26 LinkingSectionReader, MemorySectionReader, NameSectionReader, ProducersSectionReader, 27 RelocSectionReader, TableSectionReader, TypeSectionReader, 28 }; 29 30 #[derive(Debug)] 31 pub struct Section<'a> { 32 pub code: SectionCode<'a>, 33 offset: usize, 34 data: &'a [u8], 35 } 36 37 impl<'a> Section<'a> { 38 /// Creates reader for the type section. Available when the reader just read 39 /// the type section. get_type_section_reader<'b>(&self) -> Result<TypeSectionReader<'b>> where 'a: 'b,40 pub fn get_type_section_reader<'b>(&self) -> Result<TypeSectionReader<'b>> 41 where 42 'a: 'b, 43 { 44 match self.code { 45 SectionCode::Type => TypeSectionReader::new(self.data, self.offset), 46 _ => panic!("Invalid state for get_type_section_reader"), 47 } 48 } 49 50 /// Creates reader for the function section. Available when the reader just read 51 /// the function section. get_function_section_reader<'b>(&self) -> Result<FunctionSectionReader<'b>> where 'a: 'b,52 pub fn get_function_section_reader<'b>(&self) -> Result<FunctionSectionReader<'b>> 53 where 54 'a: 'b, 55 { 56 match self.code { 57 SectionCode::Function => FunctionSectionReader::new(self.data, self.offset), 58 _ => panic!("Invalid state for get_function_section_reader"), 59 } 60 } 61 62 /// Creates reader for the code section. Available when the reader just read 63 /// the code section. get_code_section_reader<'b>(&self) -> Result<CodeSectionReader<'b>> where 'a: 'b,64 pub fn get_code_section_reader<'b>(&self) -> Result<CodeSectionReader<'b>> 65 where 66 'a: 'b, 67 { 68 match self.code { 69 SectionCode::Code => CodeSectionReader::new(self.data, self.offset), 70 _ => panic!("Invalid state for get_function_section_reader"), 71 } 72 } 73 74 /// Creates reader for the export section. Available when the reader just read 75 /// the export section. get_export_section_reader<'b>(&self) -> Result<ExportSectionReader<'b>> where 'a: 'b,76 pub fn get_export_section_reader<'b>(&self) -> Result<ExportSectionReader<'b>> 77 where 78 'a: 'b, 79 { 80 match self.code { 81 SectionCode::Export => ExportSectionReader::new(self.data, self.offset), 82 _ => panic!("Invalid state for get_export_section_reader"), 83 } 84 } 85 86 /// Creates reader for the import section. Available when the reader just read 87 /// the import section. get_import_section_reader<'b>(&self) -> Result<ImportSectionReader<'b>> where 'a: 'b,88 pub fn get_import_section_reader<'b>(&self) -> Result<ImportSectionReader<'b>> 89 where 90 'a: 'b, 91 { 92 match self.code { 93 SectionCode::Import => ImportSectionReader::new(self.data, self.offset), 94 _ => panic!("Invalid state for get_import_section_reader"), 95 } 96 } 97 98 /// Creates reader for the global section. Available when the reader just read 99 /// the global section. get_global_section_reader<'b>(&self) -> Result<GlobalSectionReader<'b>> where 'a: 'b,100 pub fn get_global_section_reader<'b>(&self) -> Result<GlobalSectionReader<'b>> 101 where 102 'a: 'b, 103 { 104 match self.code { 105 SectionCode::Global => GlobalSectionReader::new(self.data, self.offset), 106 _ => panic!("Invalid state for get_global_section_reader"), 107 } 108 } 109 110 /// Creates reader for the memory section. Available when the reader just read 111 /// the memory section. get_memory_section_reader<'b>(&self) -> Result<MemorySectionReader<'b>> where 'a: 'b,112 pub fn get_memory_section_reader<'b>(&self) -> Result<MemorySectionReader<'b>> 113 where 114 'a: 'b, 115 { 116 match self.code { 117 SectionCode::Memory => MemorySectionReader::new(self.data, self.offset), 118 _ => panic!("Invalid state for get_memory_section_reader"), 119 } 120 } 121 122 /// Creates reader for the data section. Available when the reader just read 123 /// the data section. get_data_section_reader<'b>(&self) -> Result<DataSectionReader<'b>> where 'a: 'b,124 pub fn get_data_section_reader<'b>(&self) -> Result<DataSectionReader<'b>> 125 where 126 'a: 'b, 127 { 128 match self.code { 129 SectionCode::Data => DataSectionReader::new(self.data, self.offset), 130 _ => panic!("Invalid state for get_data_section_reader"), 131 } 132 } 133 134 /// Creates reader for the table section. Available when the reader just read 135 /// the table section. get_table_section_reader<'b>(&self) -> Result<TableSectionReader<'b>> where 'a: 'b,136 pub fn get_table_section_reader<'b>(&self) -> Result<TableSectionReader<'b>> 137 where 138 'a: 'b, 139 { 140 match self.code { 141 SectionCode::Table => TableSectionReader::new(self.data, self.offset), 142 _ => panic!("Invalid state for get_table_section_reader"), 143 } 144 } 145 146 /// Creates reader for the element section. Available when the reader just read 147 /// the element section. get_element_section_reader<'b>(&self) -> Result<ElementSectionReader<'b>> where 'a: 'b,148 pub fn get_element_section_reader<'b>(&self) -> Result<ElementSectionReader<'b>> 149 where 150 'a: 'b, 151 { 152 match self.code { 153 SectionCode::Element => ElementSectionReader::new(self.data, self.offset), 154 _ => panic!("Invalid state for get_element_section_reader"), 155 } 156 } 157 get_name_section_reader<'b>(&self) -> Result<NameSectionReader<'b>> where 'a: 'b,158 pub fn get_name_section_reader<'b>(&self) -> Result<NameSectionReader<'b>> 159 where 160 'a: 'b, 161 { 162 match self.code { 163 SectionCode::Custom { 164 kind: CustomSectionKind::Name, 165 .. 166 } => NameSectionReader::new(self.data, self.offset), 167 _ => panic!("Invalid state for get_name_section_reader"), 168 } 169 } 170 get_producers_section_reader<'b>(&self) -> Result<ProducersSectionReader<'b>> where 'a: 'b,171 pub fn get_producers_section_reader<'b>(&self) -> Result<ProducersSectionReader<'b>> 172 where 173 'a: 'b, 174 { 175 match self.code { 176 SectionCode::Custom { 177 kind: CustomSectionKind::Producers, 178 .. 179 } => ProducersSectionReader::new(self.data, self.offset), 180 _ => panic!("Invalid state for get_producers_section_reader"), 181 } 182 } 183 get_linking_section_reader<'b>(&self) -> Result<LinkingSectionReader<'b>> where 'a: 'b,184 pub fn get_linking_section_reader<'b>(&self) -> Result<LinkingSectionReader<'b>> 185 where 186 'a: 'b, 187 { 188 match self.code { 189 SectionCode::Custom { 190 kind: CustomSectionKind::Linking, 191 .. 192 } => LinkingSectionReader::new(self.data, self.offset), 193 _ => panic!("Invalid state for get_linking_section_reader"), 194 } 195 } 196 get_reloc_section_reader<'b>(&self) -> Result<RelocSectionReader<'b>> where 'a: 'b,197 pub fn get_reloc_section_reader<'b>(&self) -> Result<RelocSectionReader<'b>> 198 where 199 'a: 'b, 200 { 201 match self.code { 202 SectionCode::Custom { 203 kind: CustomSectionKind::Reloc, 204 .. 205 } => RelocSectionReader::new(self.data, self.offset), 206 _ => panic!("Invalid state for get_reloc_section_reader"), 207 } 208 } 209 get_start_section_content(&self) -> Result<u32>210 pub fn get_start_section_content(&self) -> Result<u32> { 211 match self.code { 212 SectionCode::Start => read_start_section_content(self.data, self.offset), 213 _ => panic!("Invalid state for get_start_section_content"), 214 } 215 } 216 get_data_count_section_content(&self) -> Result<u32>217 pub fn get_data_count_section_content(&self) -> Result<u32> { 218 match self.code { 219 SectionCode::DataCount => read_data_count_section_content(self.data, self.offset), 220 _ => panic!("Invalid state for get_data_count_section_content"), 221 } 222 } 223 get_sourcemappingurl_section_content<'b>(&self) -> Result<&'b str> where 'a: 'b,224 pub fn get_sourcemappingurl_section_content<'b>(&self) -> Result<&'b str> 225 where 226 'a: 'b, 227 { 228 match self.code { 229 SectionCode::Custom { 230 kind: CustomSectionKind::SourceMappingURL, 231 .. 232 } => read_sourcemappingurl_section_content(self.data, self.offset), 233 _ => panic!("Invalid state for get_start_section_content"), 234 } 235 } 236 get_binary_reader<'b>(&self) -> BinaryReader<'b> where 'a: 'b,237 pub fn get_binary_reader<'b>(&self) -> BinaryReader<'b> 238 where 239 'a: 'b, 240 { 241 BinaryReader::new_with_offset(self.data, self.offset) 242 } 243 range(&self) -> Range244 pub fn range(&self) -> Range { 245 Range { 246 start: self.offset, 247 end: self.offset + self.data.len(), 248 } 249 } 250 content<'b>(&self) -> Result<SectionContent<'b>> where 'a: 'b,251 pub fn content<'b>(&self) -> Result<SectionContent<'b>> 252 where 253 'a: 'b, 254 { 255 let c = match self.code { 256 SectionCode::Type => SectionContent::Type(self.get_type_section_reader()?), 257 SectionCode::Function => SectionContent::Function(self.get_function_section_reader()?), 258 SectionCode::Code => SectionContent::Code(self.get_code_section_reader()?), 259 SectionCode::Export => SectionContent::Export(self.get_export_section_reader()?), 260 SectionCode::Import => SectionContent::Import(self.get_import_section_reader()?), 261 SectionCode::Global => SectionContent::Global(self.get_global_section_reader()?), 262 SectionCode::Memory => SectionContent::Memory(self.get_memory_section_reader()?), 263 SectionCode::Data => SectionContent::Data(self.get_data_section_reader()?), 264 SectionCode::Table => SectionContent::Table(self.get_table_section_reader()?), 265 SectionCode::Element => SectionContent::Element(self.get_element_section_reader()?), 266 SectionCode::Start => SectionContent::Start(self.get_start_section_content()?), 267 SectionCode::DataCount => { 268 SectionContent::DataCount(self.get_data_count_section_content()?) 269 } 270 SectionCode::Custom { kind, name } => { 271 let binary = self.get_binary_reader(); 272 let content = match kind { 273 CustomSectionKind::Name => { 274 Some(CustomSectionContent::Name(self.get_name_section_reader()?)) 275 } 276 CustomSectionKind::Producers => Some(CustomSectionContent::Producers( 277 self.get_producers_section_reader()?, 278 )), 279 CustomSectionKind::Linking => Some(CustomSectionContent::Linking( 280 self.get_linking_section_reader()?, 281 )), 282 CustomSectionKind::Reloc => Some(CustomSectionContent::Reloc( 283 self.get_reloc_section_reader()?, 284 )), 285 CustomSectionKind::SourceMappingURL => { 286 Some(CustomSectionContent::SourceMappingURL( 287 self.get_sourcemappingurl_section_content()?, 288 )) 289 } 290 291 _ => None, 292 }; 293 SectionContent::Custom { 294 name, 295 binary, 296 content, 297 } 298 } 299 }; 300 Ok(c) 301 } 302 } 303 304 pub enum SectionContent<'a> { 305 Type(TypeSectionReader<'a>), 306 Function(FunctionSectionReader<'a>), 307 Code(CodeSectionReader<'a>), 308 Export(ExportSectionReader<'a>), 309 Import(ImportSectionReader<'a>), 310 Global(GlobalSectionReader<'a>), 311 Memory(MemorySectionReader<'a>), 312 Data(DataSectionReader<'a>), 313 Table(TableSectionReader<'a>), 314 Element(ElementSectionReader<'a>), 315 Start(u32), 316 DataCount(u32), 317 Custom { 318 name: &'a str, 319 binary: BinaryReader<'a>, 320 content: Option<CustomSectionContent<'a>>, 321 }, 322 } 323 324 pub enum CustomSectionContent<'a> { 325 Name(NameSectionReader<'a>), 326 Producers(ProducersSectionReader<'a>), 327 Linking(LinkingSectionReader<'a>), 328 Reloc(RelocSectionReader<'a>), 329 SourceMappingURL(&'a str), 330 } 331 332 /// Reads top-level WebAssembly file structure: header and sections. 333 pub struct ModuleReader<'a> { 334 reader: BinaryReader<'a>, 335 version: u32, 336 read_ahead: Option<(usize, SectionHeader<'a>)>, 337 } 338 339 impl<'a> ModuleReader<'a> { new(data: &[u8]) -> Result<ModuleReader>340 pub fn new(data: &[u8]) -> Result<ModuleReader> { 341 let mut reader = BinaryReader::new(data); 342 let version = reader.read_file_header()?; 343 Ok(ModuleReader { 344 reader, 345 version, 346 read_ahead: None, 347 }) 348 } 349 get_version(&self) -> u32350 pub fn get_version(&self) -> u32 { 351 self.version 352 } 353 current_position(&self) -> usize354 pub fn current_position(&self) -> usize { 355 match self.read_ahead { 356 Some((position, _)) => position, 357 _ => self.reader.current_position(), 358 } 359 } 360 eof(&self) -> bool361 pub fn eof(&self) -> bool { 362 self.read_ahead.is_none() && self.reader.eof() 363 } 364 verify_section_end(&self, end: usize) -> Result<()>365 fn verify_section_end(&self, end: usize) -> Result<()> { 366 if self.reader.buffer.len() < end { 367 return Err(BinaryReaderError { 368 message: "Section body extends past end of file", 369 offset: self.reader.buffer.len(), 370 }); 371 } 372 if self.reader.position > end { 373 return Err(BinaryReaderError { 374 message: "Section header is too big to fit into section body", 375 offset: end, 376 }); 377 } 378 Ok(()) 379 } 380 381 /// Reads next top-level record from the WebAssembly binary data. 382 /// The methods returns reference to current state of the reader. 383 /// 384 /// # Examples 385 /// ``` 386 /// # let data: &[u8] = &[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 387 /// # 0x01, 0x4, 0x01, 0x60, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 388 /// # 0x0a, 0x05, 0x01, 0x03, 0x00, 0x01, 0x0b]; 389 /// use wasmparser::ModuleReader; 390 /// let mut reader = ModuleReader::new(data).expect("reader"); 391 /// let section = reader.read().expect("section #1"); 392 /// println!("First section {:?}", section); 393 /// let section = reader.read().expect("section #2"); 394 /// println!("Second section {:?}", section); 395 /// assert!(!reader.eof(), "there are more sections"); 396 /// ``` read<'b>(&mut self) -> Result<Section<'b>> where 'a: 'b,397 pub fn read<'b>(&mut self) -> Result<Section<'b>> 398 where 399 'a: 'b, 400 { 401 let SectionHeader { 402 code, 403 payload_start, 404 payload_len, 405 } = match self.read_ahead.take() { 406 Some((_, section_header)) => section_header, 407 None => self.reader.read_section_header()?, 408 }; 409 let payload_end = payload_start + payload_len; 410 self.verify_section_end(payload_end)?; 411 let body_start = self.reader.position; 412 self.reader.skip_to(payload_end); 413 Ok(Section { 414 code, 415 offset: body_start, 416 data: &self.reader.buffer[body_start..payload_end], 417 }) 418 } 419 ensure_read_ahead(&mut self) -> Result<()>420 fn ensure_read_ahead(&mut self) -> Result<()> { 421 if self.read_ahead.is_none() && !self.eof() { 422 let position = self.reader.current_position(); 423 self.read_ahead = Some((position, self.reader.read_section_header()?)); 424 } 425 Ok(()) 426 } 427 428 /// Skips custom sections. 429 /// 430 /// # Examples 431 /// ``` 432 /// # let data: &[u8] = &[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 433 /// # 0x00, 0x8, 0x03, 0x63, 0x61, 0x74, 0x01, 0x02, 0x03, 0x04, 434 /// # 0x01, 0x4, 0x01, 0x60, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 435 /// # 0x0a, 0x05, 0x01, 0x03, 0x00, 0x01, 0x0b]; 436 /// use wasmparser::ModuleReader; 437 /// use wasmparser::SectionCode; 438 /// let mut reader = ModuleReader::new(data).expect("reader"); 439 /// while { reader.skip_custom_sections(); !reader.eof() } { 440 /// let section = reader.read().expect("section"); 441 /// if let SectionCode::Custom {..} = section.code { panic!("no custom"); } 442 /// println!("Section {:?}", section); 443 /// } 444 /// ``` skip_custom_sections(&mut self) -> Result<()>445 pub fn skip_custom_sections(&mut self) -> Result<()> { 446 loop { 447 self.ensure_read_ahead()?; 448 match self.read_ahead { 449 Some(( 450 _, 451 SectionHeader { 452 code: SectionCode::Custom { .. }, 453 payload_start, 454 payload_len, 455 }, 456 )) => { 457 self.verify_section_end(payload_start + payload_len)?; 458 // Skip section 459 self.read_ahead = None; 460 self.reader.skip_to(payload_start + payload_len); 461 } 462 _ => break, 463 }; 464 } 465 Ok(()) 466 } 467 } 468 469 impl<'a> IntoIterator for ModuleReader<'a> { 470 type Item = Result<Section<'a>>; 471 type IntoIter = ModuleIterator<'a>; into_iter(self) -> Self::IntoIter472 fn into_iter(self) -> Self::IntoIter { 473 ModuleIterator { 474 reader: self, 475 err: false, 476 } 477 } 478 } 479 480 pub struct ModuleIterator<'a> { 481 reader: ModuleReader<'a>, 482 err: bool, 483 } 484 485 impl<'a> Iterator for ModuleIterator<'a> { 486 type Item = Result<Section<'a>>; 487 488 /// Iterates sections from the WebAssembly binary data. Stops at first error. 489 /// 490 /// # Examples 491 /// ``` 492 /// # let data: &[u8] = &[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 493 /// # 0x01, 0x4, 0x01, 0x60, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 494 /// # 0x0a, 0x05, 0x01, 0x03, 0x00, 0x01, 0x0b]; 495 /// use wasmparser::ModuleReader; 496 /// for section in ModuleReader::new(data).expect("reader") { 497 /// println!("Section {:?}", section); 498 /// } 499 /// ``` next(&mut self) -> Option<Self::Item>500 fn next(&mut self) -> Option<Self::Item> { 501 if self.err || self.reader.eof() { 502 return None; 503 } 504 let result = self.reader.read(); 505 self.err = result.is_err(); 506 Some(result) 507 } 508 } 509