]> git.proxmox.com Git - rustc.git/blame - vendor/object-0.27.1/src/read/wasm.rs
New upstream version 1.59.0+dfsg1
[rustc.git] / vendor / object-0.27.1 / src / read / wasm.rs
CommitLineData
a2a8927a
XL
1//! Support for reading Wasm files.
2//!
3//! Provides `WasmFile` and related types which implement the `Object` trait.
4//!
5//! Currently implements the minimum required to access DWARF debugging information.
6use alloc::boxed::Box;
7use alloc::vec::Vec;
8use core::marker::PhantomData;
9use core::{slice, str};
10use wasmparser as wp;
11
12use crate::read::{
13 self, Architecture, ComdatKind, CompressedData, CompressedFileRange, Error, Export, FileFlags,
14 Import, NoDynamicRelocationIterator, Object, ObjectComdat, ObjectKind, ObjectSection,
15 ObjectSegment, ObjectSymbol, ObjectSymbolTable, ReadError, ReadRef, Relocation, Result,
16 SectionFlags, SectionIndex, SectionKind, SymbolFlags, SymbolIndex, SymbolKind, SymbolScope,
17 SymbolSection,
18};
19
20const SECTION_CUSTOM: usize = 0;
21const SECTION_TYPE: usize = 1;
22const SECTION_IMPORT: usize = 2;
23const SECTION_FUNCTION: usize = 3;
24const SECTION_TABLE: usize = 4;
25const SECTION_MEMORY: usize = 5;
26const SECTION_GLOBAL: usize = 6;
27const SECTION_EXPORT: usize = 7;
28const SECTION_START: usize = 8;
29const SECTION_ELEMENT: usize = 9;
30const SECTION_CODE: usize = 10;
31const SECTION_DATA: usize = 11;
32const SECTION_DATA_COUNT: usize = 12;
33// Update this constant when adding new section id:
34const MAX_SECTION_ID: usize = SECTION_DATA_COUNT;
35
36/// A WebAssembly object file.
37#[derive(Debug)]
38pub struct WasmFile<'data, R = &'data [u8]> {
39 // All sections, including custom sections.
40 sections: Vec<wp::Section<'data>>,
41 // Indices into `sections` of sections with a non-zero id.
42 id_sections: Box<[Option<usize>; MAX_SECTION_ID + 1]>,
43 // Whether the file has DWARF information.
44 has_debug_symbols: bool,
45 // Symbols collected from imports, exports, code and name sections.
46 symbols: Vec<WasmSymbolInternal<'data>>,
47 // Address of the function body for the entry point.
48 entry: u64,
49 marker: PhantomData<R>,
50}
51
52#[derive(Clone)]
53enum LocalFunctionKind {
54 Unknown,
55 Exported { symbol_ids: Vec<u32> },
56 Local { symbol_id: u32 },
57}
58
59impl<T> ReadError<T> for wasmparser::Result<T> {
60 fn read_error(self, error: &'static str) -> Result<T> {
61 self.map_err(|_| Error(error))
62 }
63}
64
65impl<'data, R: ReadRef<'data>> WasmFile<'data, R> {
66 /// Parse the raw wasm data.
67 pub fn parse(data: R) -> Result<Self> {
68 let len = data.len().read_error("Unknown Wasm file size")?;
69 let data = data.read_bytes_at(0, len).read_error("Wasm read failed")?;
70 let module = wp::ModuleReader::new(data).read_error("Invalid Wasm header")?;
71
72 let mut file = WasmFile {
73 sections: Vec::new(),
74 id_sections: Default::default(),
75 has_debug_symbols: false,
76 symbols: Vec::new(),
77 entry: 0,
78 marker: PhantomData,
79 };
80
81 let mut main_file_symbol = Some(WasmSymbolInternal {
82 name: "",
83 address: 0,
84 size: 0,
85 kind: SymbolKind::File,
86 section: SymbolSection::None,
87 scope: SymbolScope::Compilation,
88 });
89
90 let mut imported_funcs_count = 0;
91 let mut local_func_kinds = Vec::new();
92 let mut entry_func_id = None;
93
94 for section in module {
95 let section = section.read_error("Invalid Wasm section header")?;
96
97 match section.code {
98 wp::SectionCode::Import => {
99 let mut last_module_name = None;
100
101 for import in section
102 .get_import_section_reader()
103 .read_error("Couldn't read header of the import section")?
104 {
105 let import = import.read_error("Couldn't read an import item")?;
106 let module_name = import.module;
107
108 if last_module_name != Some(module_name) {
109 file.symbols.push(WasmSymbolInternal {
110 name: module_name,
111 address: 0,
112 size: 0,
113 kind: SymbolKind::File,
114 section: SymbolSection::None,
115 scope: SymbolScope::Dynamic,
116 });
117 last_module_name = Some(module_name);
118 }
119
120 let kind = match import.ty {
121 wp::ImportSectionEntryType::Function(_) => {
122 imported_funcs_count += 1;
123 SymbolKind::Text
124 }
125 wp::ImportSectionEntryType::Table(_)
126 | wp::ImportSectionEntryType::Memory(_)
127 | wp::ImportSectionEntryType::Global(_) => SymbolKind::Data,
128 };
129
130 file.symbols.push(WasmSymbolInternal {
131 name: import.field,
132 address: 0,
133 size: 0,
134 kind,
135 section: SymbolSection::Undefined,
136 scope: SymbolScope::Dynamic,
137 });
138 }
139 }
140 wp::SectionCode::Function => {
141 local_func_kinds = vec![
142 LocalFunctionKind::Unknown;
143 section
144 .get_function_section_reader()
145 .read_error("Couldn't read header of the function section")?
146 .get_count() as usize
147 ];
148 }
149 wp::SectionCode::Export => {
150 if let Some(main_file_symbol) = main_file_symbol.take() {
151 file.symbols.push(main_file_symbol);
152 }
153
154 for export in section
155 .get_export_section_reader()
156 .read_error("Couldn't read header of the export section")?
157 {
158 let export = export.read_error("Couldn't read an export item")?;
159
160 let (kind, section_idx) = match export.kind {
161 wp::ExternalKind::Function => {
162 if let Some(local_func_id) =
163 export.index.checked_sub(imported_funcs_count)
164 {
165 let local_func_kind =
166 &mut local_func_kinds[local_func_id as usize];
167 if let LocalFunctionKind::Unknown = local_func_kind {
168 *local_func_kind = LocalFunctionKind::Exported {
169 symbol_ids: Vec::new(),
170 };
171 }
172 let symbol_ids = match local_func_kind {
173 LocalFunctionKind::Exported { symbol_ids } => symbol_ids,
174 _ => unreachable!(),
175 };
176 symbol_ids.push(file.symbols.len() as u32);
177 }
178 (SymbolKind::Text, SECTION_CODE)
179 }
180 wp::ExternalKind::Table
181 | wp::ExternalKind::Memory
182 | wp::ExternalKind::Global => (SymbolKind::Data, SECTION_DATA),
183 };
184
185 file.symbols.push(WasmSymbolInternal {
186 name: export.field,
187 address: 0,
188 size: 0,
189 kind,
190 section: SymbolSection::Section(SectionIndex(section_idx)),
191 scope: SymbolScope::Dynamic,
192 });
193 }
194 }
195 wp::SectionCode::Start => {
196 entry_func_id = Some(
197 section
198 .get_start_section_content()
199 .read_error("Couldn't read contents of the start section")?,
200 );
201 }
202 wp::SectionCode::Code => {
203 if let Some(main_file_symbol) = main_file_symbol.take() {
204 file.symbols.push(main_file_symbol);
205 }
206
207 for (i, (body, local_func_kind)) in section
208 .get_code_section_reader()
209 .read_error("Couldn't read header of the code section")?
210 .into_iter()
211 .zip(&mut local_func_kinds)
212 .enumerate()
213 {
214 let body = body.read_error("Couldn't read a function body")?;
215 let range = body.range();
216
217 let address = range.start as u64 - section.range().start as u64;
218 let size = (range.end - range.start) as u64;
219
220 if entry_func_id == Some(i as u32) {
221 file.entry = address;
222 }
223
224 match local_func_kind {
225 LocalFunctionKind::Unknown => {
226 *local_func_kind = LocalFunctionKind::Local {
227 symbol_id: file.symbols.len() as u32,
228 };
229 file.symbols.push(WasmSymbolInternal {
230 name: "",
231 address,
232 size,
233 kind: SymbolKind::Text,
234 section: SymbolSection::Section(SectionIndex(SECTION_CODE)),
235 scope: SymbolScope::Compilation,
236 });
237 }
238 LocalFunctionKind::Exported { symbol_ids } => {
239 for symbol_id in core::mem::take(symbol_ids) {
240 let export_symbol = &mut file.symbols[symbol_id as usize];
241 export_symbol.address = address;
242 export_symbol.size = size;
243 }
244 }
245 _ => unreachable!(),
246 }
247 }
248 }
249 wp::SectionCode::Custom {
250 kind: wp::CustomSectionKind::Name,
251 ..
252 } => {
253 for name in section
254 .get_name_section_reader()
255 .read_error("Couldn't read header of the name section")?
256 {
257 let name =
258 match name.read_error("Couldn't read header of a name subsection")? {
259 wp::Name::Function(name) => name,
260 _ => continue,
261 };
262 let mut name_map = name
263 .get_map()
264 .read_error("Couldn't read header of the function name subsection")?;
265 for _ in 0..name_map.get_count() {
266 let naming = name_map
267 .read()
268 .read_error("Couldn't read a function name")?;
269 if let Some(local_index) =
270 naming.index.checked_sub(imported_funcs_count)
271 {
272 if let LocalFunctionKind::Local { symbol_id } =
273 local_func_kinds[local_index as usize]
274 {
275 file.symbols[symbol_id as usize].name = naming.name;
276 }
277 }
278 }
279 }
280 }
281 wp::SectionCode::Custom { name, .. } if name.starts_with(".debug_") => {
282 file.has_debug_symbols = true;
283 }
284 _ => {}
285 }
286
287 let id = section_code_to_id(section.code);
288 file.id_sections[id] = Some(file.sections.len());
289
290 file.sections.push(section);
291 }
292
293 Ok(file)
294 }
295}
296
297impl<'data, R> read::private::Sealed for WasmFile<'data, R> {}
298
299impl<'data, 'file, R> Object<'data, 'file> for WasmFile<'data, R>
300where
301 'data: 'file,
302 R: 'file,
303{
304 type Segment = WasmSegment<'data, 'file, R>;
305 type SegmentIterator = WasmSegmentIterator<'data, 'file, R>;
306 type Section = WasmSection<'data, 'file, R>;
307 type SectionIterator = WasmSectionIterator<'data, 'file, R>;
308 type Comdat = WasmComdat<'data, 'file, R>;
309 type ComdatIterator = WasmComdatIterator<'data, 'file, R>;
310 type Symbol = WasmSymbol<'data, 'file>;
311 type SymbolIterator = WasmSymbolIterator<'data, 'file>;
312 type SymbolTable = WasmSymbolTable<'data, 'file>;
313 type DynamicRelocationIterator = NoDynamicRelocationIterator;
314
315 #[inline]
316 fn architecture(&self) -> Architecture {
317 Architecture::Wasm32
318 }
319
320 #[inline]
321 fn is_little_endian(&self) -> bool {
322 true
323 }
324
325 #[inline]
326 fn is_64(&self) -> bool {
327 false
328 }
329
330 fn kind(&self) -> ObjectKind {
331 // TODO: check for `linking` custom section
332 ObjectKind::Unknown
333 }
334
335 fn segments(&'file self) -> Self::SegmentIterator {
336 WasmSegmentIterator { file: self }
337 }
338
339 fn section_by_name_bytes(
340 &'file self,
341 section_name: &[u8],
342 ) -> Option<WasmSection<'data, 'file, R>> {
343 self.sections()
344 .find(|section| section.name_bytes() == Ok(section_name))
345 }
346
347 fn section_by_index(&'file self, index: SectionIndex) -> Result<WasmSection<'data, 'file, R>> {
348 // TODO: Missing sections should return an empty section.
349 let id_section = self
350 .id_sections
351 .get(index.0)
352 .and_then(|x| *x)
353 .read_error("Invalid Wasm section index")?;
354 let section = self.sections.get(id_section).unwrap();
355 Ok(WasmSection {
356 section,
357 marker: PhantomData,
358 })
359 }
360
361 fn sections(&'file self) -> Self::SectionIterator {
362 WasmSectionIterator {
363 sections: self.sections.iter(),
364 marker: PhantomData,
365 }
366 }
367
368 fn comdats(&'file self) -> Self::ComdatIterator {
369 WasmComdatIterator { file: self }
370 }
371
372 #[inline]
373 fn symbol_by_index(&'file self, index: SymbolIndex) -> Result<WasmSymbol<'data, 'file>> {
374 let symbol = self
375 .symbols
376 .get(index.0)
377 .read_error("Invalid Wasm symbol index")?;
378 Ok(WasmSymbol { index, symbol })
379 }
380
381 fn symbols(&'file self) -> Self::SymbolIterator {
382 WasmSymbolIterator {
383 symbols: self.symbols.iter().enumerate(),
384 }
385 }
386
387 fn symbol_table(&'file self) -> Option<WasmSymbolTable<'data, 'file>> {
388 Some(WasmSymbolTable {
389 symbols: &self.symbols,
390 })
391 }
392
393 fn dynamic_symbols(&'file self) -> Self::SymbolIterator {
394 WasmSymbolIterator {
395 symbols: [].iter().enumerate(),
396 }
397 }
398
399 #[inline]
400 fn dynamic_symbol_table(&'file self) -> Option<WasmSymbolTable<'data, 'file>> {
401 None
402 }
403
404 #[inline]
405 fn dynamic_relocations(&self) -> Option<NoDynamicRelocationIterator> {
406 None
407 }
408
409 fn imports(&self) -> Result<Vec<Import<'data>>> {
410 // TODO: return entries in the import section
411 Ok(Vec::new())
412 }
413
414 fn exports(&self) -> Result<Vec<Export<'data>>> {
415 // TODO: return entries in the export section
416 Ok(Vec::new())
417 }
418
419 fn has_debug_symbols(&self) -> bool {
420 self.has_debug_symbols
421 }
422
423 fn relative_address_base(&self) -> u64 {
424 0
425 }
426
427 #[inline]
428 fn entry(&'file self) -> u64 {
429 self.entry
430 }
431
432 #[inline]
433 fn flags(&self) -> FileFlags {
434 FileFlags::None
435 }
436}
437
438/// An iterator over the segments of a `WasmFile`.
439#[derive(Debug)]
440pub struct WasmSegmentIterator<'data, 'file, R = &'data [u8]> {
441 file: &'file WasmFile<'data, R>,
442}
443
444impl<'data, 'file, R> Iterator for WasmSegmentIterator<'data, 'file, R> {
445 type Item = WasmSegment<'data, 'file, R>;
446
447 #[inline]
448 fn next(&mut self) -> Option<Self::Item> {
449 None
450 }
451}
452
453/// A segment of a `WasmFile`.
454#[derive(Debug)]
455pub struct WasmSegment<'data, 'file, R = &'data [u8]> {
456 file: &'file WasmFile<'data, R>,
457}
458
459impl<'data, 'file, R> read::private::Sealed for WasmSegment<'data, 'file, R> {}
460
461impl<'data, 'file, R> ObjectSegment<'data> for WasmSegment<'data, 'file, R> {
462 #[inline]
463 fn address(&self) -> u64 {
464 unreachable!()
465 }
466
467 #[inline]
468 fn size(&self) -> u64 {
469 unreachable!()
470 }
471
472 #[inline]
473 fn align(&self) -> u64 {
474 unreachable!()
475 }
476
477 #[inline]
478 fn file_range(&self) -> (u64, u64) {
479 unreachable!()
480 }
481
482 fn data(&self) -> Result<&'data [u8]> {
483 unreachable!()
484 }
485
486 fn data_range(&self, _address: u64, _size: u64) -> Result<Option<&'data [u8]>> {
487 unreachable!()
488 }
489
490 #[inline]
491 fn name_bytes(&self) -> Result<Option<&[u8]>> {
492 unreachable!()
493 }
494
495 #[inline]
496 fn name(&self) -> Result<Option<&str>> {
497 unreachable!()
498 }
499}
500
501/// An iterator over the sections of a `WasmFile`.
502#[derive(Debug)]
503pub struct WasmSectionIterator<'data, 'file, R = &'data [u8]> {
504 sections: slice::Iter<'file, wp::Section<'data>>,
505 marker: PhantomData<R>,
506}
507
508impl<'data, 'file, R> Iterator for WasmSectionIterator<'data, 'file, R> {
509 type Item = WasmSection<'data, 'file, R>;
510
511 fn next(&mut self) -> Option<Self::Item> {
512 let section = self.sections.next()?;
513 Some(WasmSection {
514 section,
515 marker: PhantomData,
516 })
517 }
518}
519
520/// A section of a `WasmFile`.
521#[derive(Debug)]
522pub struct WasmSection<'data, 'file, R = &'data [u8]> {
523 section: &'file wp::Section<'data>,
524 marker: PhantomData<R>,
525}
526
527impl<'data, 'file, R> read::private::Sealed for WasmSection<'data, 'file, R> {}
528
529impl<'data, 'file, R> ObjectSection<'data> for WasmSection<'data, 'file, R> {
530 type RelocationIterator = WasmRelocationIterator<'data, 'file, R>;
531
532 #[inline]
533 fn index(&self) -> SectionIndex {
534 // Note that we treat all custom sections as index 0.
535 // This is ok because they are never looked up by index.
536 SectionIndex(section_code_to_id(self.section.code))
537 }
538
539 #[inline]
540 fn address(&self) -> u64 {
541 0
542 }
543
544 #[inline]
545 fn size(&self) -> u64 {
546 let range = self.section.range();
547 (range.end - range.start) as u64
548 }
549
550 #[inline]
551 fn align(&self) -> u64 {
552 1
553 }
554
555 #[inline]
556 fn file_range(&self) -> Option<(u64, u64)> {
557 let range = self.section.range();
558 Some((range.start as _, range.end as _))
559 }
560
561 #[inline]
562 fn data(&self) -> Result<&'data [u8]> {
563 let mut reader = self.section.get_binary_reader();
564 // TODO: raise a feature request upstream to be able
565 // to get remaining slice from a BinaryReader directly.
566 Ok(reader.read_bytes(reader.bytes_remaining()).unwrap())
567 }
568
569 fn data_range(&self, _address: u64, _size: u64) -> Result<Option<&'data [u8]>> {
570 unimplemented!()
571 }
572
573 #[inline]
574 fn compressed_file_range(&self) -> Result<CompressedFileRange> {
575 Ok(CompressedFileRange::none(self.file_range()))
576 }
577
578 #[inline]
579 fn compressed_data(&self) -> Result<CompressedData<'data>> {
580 self.data().map(CompressedData::none)
581 }
582
583 #[inline]
584 fn name_bytes(&self) -> Result<&[u8]> {
585 self.name().map(str::as_bytes)
586 }
587
588 #[inline]
589 fn name(&self) -> Result<&str> {
590 Ok(match self.section.code {
591 wp::SectionCode::Custom { name, .. } => name,
592 wp::SectionCode::Type => "<type>",
593 wp::SectionCode::Import => "<import>",
594 wp::SectionCode::Function => "<function>",
595 wp::SectionCode::Table => "<table>",
596 wp::SectionCode::Memory => "<memory>",
597 wp::SectionCode::Global => "<global>",
598 wp::SectionCode::Export => "<export>",
599 wp::SectionCode::Start => "<start>",
600 wp::SectionCode::Element => "<element>",
601 wp::SectionCode::Code => "<code>",
602 wp::SectionCode::Data => "<data>",
603 wp::SectionCode::DataCount => "<data_count>",
604 })
605 }
606
607 #[inline]
608 fn segment_name_bytes(&self) -> Result<Option<&[u8]>> {
609 Ok(None)
610 }
611
612 #[inline]
613 fn segment_name(&self) -> Result<Option<&str>> {
614 Ok(None)
615 }
616
617 #[inline]
618 fn kind(&self) -> SectionKind {
619 match self.section.code {
620 wp::SectionCode::Custom { kind, .. } => match kind {
621 wp::CustomSectionKind::Reloc | wp::CustomSectionKind::Linking => {
622 SectionKind::Linker
623 }
624 _ => SectionKind::Other,
625 },
626 wp::SectionCode::Type => SectionKind::Metadata,
627 wp::SectionCode::Import => SectionKind::Linker,
628 wp::SectionCode::Function => SectionKind::Metadata,
629 wp::SectionCode::Table => SectionKind::UninitializedData,
630 wp::SectionCode::Memory => SectionKind::UninitializedData,
631 wp::SectionCode::Global => SectionKind::Data,
632 wp::SectionCode::Export => SectionKind::Linker,
633 wp::SectionCode::Start => SectionKind::Linker,
634 wp::SectionCode::Element => SectionKind::Data,
635 wp::SectionCode::Code => SectionKind::Text,
636 wp::SectionCode::Data => SectionKind::Data,
637 wp::SectionCode::DataCount => SectionKind::UninitializedData,
638 }
639 }
640
641 #[inline]
642 fn relocations(&self) -> WasmRelocationIterator<'data, 'file, R> {
643 WasmRelocationIterator(PhantomData)
644 }
645
646 #[inline]
647 fn flags(&self) -> SectionFlags {
648 SectionFlags::None
649 }
650}
651
652/// An iterator over the COMDAT section groups of a `WasmFile`.
653#[derive(Debug)]
654pub struct WasmComdatIterator<'data, 'file, R = &'data [u8]> {
655 file: &'file WasmFile<'data, R>,
656}
657
658impl<'data, 'file, R> Iterator for WasmComdatIterator<'data, 'file, R> {
659 type Item = WasmComdat<'data, 'file, R>;
660
661 #[inline]
662 fn next(&mut self) -> Option<Self::Item> {
663 None
664 }
665}
666
667/// A COMDAT section group of a `WasmFile`.
668#[derive(Debug)]
669pub struct WasmComdat<'data, 'file, R = &'data [u8]> {
670 file: &'file WasmFile<'data, R>,
671}
672
673impl<'data, 'file, R> read::private::Sealed for WasmComdat<'data, 'file, R> {}
674
675impl<'data, 'file, R> ObjectComdat<'data> for WasmComdat<'data, 'file, R> {
676 type SectionIterator = WasmComdatSectionIterator<'data, 'file, R>;
677
678 #[inline]
679 fn kind(&self) -> ComdatKind {
680 unreachable!();
681 }
682
683 #[inline]
684 fn symbol(&self) -> SymbolIndex {
685 unreachable!();
686 }
687
688 #[inline]
689 fn name_bytes(&self) -> Result<&[u8]> {
690 unreachable!();
691 }
692
693 #[inline]
694 fn name(&self) -> Result<&str> {
695 unreachable!();
696 }
697
698 #[inline]
699 fn sections(&self) -> Self::SectionIterator {
700 unreachable!();
701 }
702}
703
704/// An iterator over the sections in a COMDAT section group of a `WasmFile`.
705#[derive(Debug)]
706pub struct WasmComdatSectionIterator<'data, 'file, R = &'data [u8]>
707where
708 'data: 'file,
709{
710 file: &'file WasmFile<'data, R>,
711}
712
713impl<'data, 'file, R> Iterator for WasmComdatSectionIterator<'data, 'file, R> {
714 type Item = SectionIndex;
715
716 fn next(&mut self) -> Option<Self::Item> {
717 None
718 }
719}
720
721/// A symbol table of a `WasmFile`.
722#[derive(Debug)]
723pub struct WasmSymbolTable<'data, 'file> {
724 symbols: &'file [WasmSymbolInternal<'data>],
725}
726
727impl<'data, 'file> read::private::Sealed for WasmSymbolTable<'data, 'file> {}
728
729impl<'data, 'file> ObjectSymbolTable<'data> for WasmSymbolTable<'data, 'file> {
730 type Symbol = WasmSymbol<'data, 'file>;
731 type SymbolIterator = WasmSymbolIterator<'data, 'file>;
732
733 fn symbols(&self) -> Self::SymbolIterator {
734 WasmSymbolIterator {
735 symbols: self.symbols.iter().enumerate(),
736 }
737 }
738
739 fn symbol_by_index(&self, index: SymbolIndex) -> Result<Self::Symbol> {
740 let symbol = self
741 .symbols
742 .get(index.0)
743 .read_error("Invalid Wasm symbol index")?;
744 Ok(WasmSymbol { index, symbol })
745 }
746}
747
748/// An iterator over the symbols of a `WasmFile`.
749#[derive(Debug)]
750pub struct WasmSymbolIterator<'data, 'file> {
751 symbols: core::iter::Enumerate<slice::Iter<'file, WasmSymbolInternal<'data>>>,
752}
753
754impl<'data, 'file> Iterator for WasmSymbolIterator<'data, 'file> {
755 type Item = WasmSymbol<'data, 'file>;
756
757 fn next(&mut self) -> Option<Self::Item> {
758 let (index, symbol) = self.symbols.next()?;
759 Some(WasmSymbol {
760 index: SymbolIndex(index),
761 symbol,
762 })
763 }
764}
765
766/// A symbol of a `WasmFile`.
767#[derive(Clone, Copy, Debug)]
768pub struct WasmSymbol<'data, 'file> {
769 index: SymbolIndex,
770 symbol: &'file WasmSymbolInternal<'data>,
771}
772
773#[derive(Clone, Debug)]
774struct WasmSymbolInternal<'data> {
775 name: &'data str,
776 address: u64,
777 size: u64,
778 kind: SymbolKind,
779 section: SymbolSection,
780 scope: SymbolScope,
781}
782
783impl<'data, 'file> read::private::Sealed for WasmSymbol<'data, 'file> {}
784
785impl<'data, 'file> ObjectSymbol<'data> for WasmSymbol<'data, 'file> {
786 #[inline]
787 fn index(&self) -> SymbolIndex {
788 self.index
789 }
790
791 #[inline]
792 fn name_bytes(&self) -> read::Result<&'data [u8]> {
793 Ok(self.symbol.name.as_bytes())
794 }
795
796 #[inline]
797 fn name(&self) -> read::Result<&'data str> {
798 Ok(self.symbol.name)
799 }
800
801 #[inline]
802 fn address(&self) -> u64 {
803 self.symbol.address
804 }
805
806 #[inline]
807 fn size(&self) -> u64 {
808 self.symbol.size
809 }
810
811 #[inline]
812 fn kind(&self) -> SymbolKind {
813 self.symbol.kind
814 }
815
816 #[inline]
817 fn section(&self) -> SymbolSection {
818 self.symbol.section
819 }
820
821 #[inline]
822 fn is_undefined(&self) -> bool {
823 self.symbol.section == SymbolSection::Undefined
824 }
825
826 #[inline]
827 fn is_definition(&self) -> bool {
828 self.symbol.kind == SymbolKind::Text && self.symbol.section != SymbolSection::Undefined
829 }
830
831 #[inline]
832 fn is_common(&self) -> bool {
833 self.symbol.section == SymbolSection::Common
834 }
835
836 #[inline]
837 fn is_weak(&self) -> bool {
838 false
839 }
840
841 #[inline]
842 fn scope(&self) -> SymbolScope {
843 self.symbol.scope
844 }
845
846 #[inline]
847 fn is_global(&self) -> bool {
848 self.symbol.scope != SymbolScope::Compilation
849 }
850
851 #[inline]
852 fn is_local(&self) -> bool {
853 self.symbol.scope == SymbolScope::Compilation
854 }
855
856 #[inline]
857 fn flags(&self) -> SymbolFlags<SectionIndex> {
858 SymbolFlags::None
859 }
860}
861
862/// An iterator over the relocations in a `WasmSection`.
863#[derive(Debug)]
864pub struct WasmRelocationIterator<'data, 'file, R = &'data [u8]>(
865 PhantomData<(&'data (), &'file (), R)>,
866);
867
868impl<'data, 'file, R> Iterator for WasmRelocationIterator<'data, 'file, R> {
869 type Item = (u64, Relocation);
870
871 #[inline]
872 fn next(&mut self) -> Option<Self::Item> {
873 None
874 }
875}
876
877fn section_code_to_id(code: wp::SectionCode) -> usize {
878 match code {
879 wp::SectionCode::Custom { .. } => SECTION_CUSTOM,
880 wp::SectionCode::Type => SECTION_TYPE,
881 wp::SectionCode::Import => SECTION_IMPORT,
882 wp::SectionCode::Function => SECTION_FUNCTION,
883 wp::SectionCode::Table => SECTION_TABLE,
884 wp::SectionCode::Memory => SECTION_MEMORY,
885 wp::SectionCode::Global => SECTION_GLOBAL,
886 wp::SectionCode::Export => SECTION_EXPORT,
887 wp::SectionCode::Start => SECTION_START,
888 wp::SectionCode::Element => SECTION_ELEMENT,
889 wp::SectionCode::Code => SECTION_CODE,
890 wp::SectionCode::Data => SECTION_DATA,
891 wp::SectionCode::DataCount => SECTION_DATA_COUNT,
892 }
893}