| 1 | use crate::prelude::*; | 
| 2 | use crate::{ | 
|---|
| 3 | BinaryReader, BinaryReaderError, FromReader, Result, SectionLimited, Subsection, Subsections, | 
|---|
| 4 | }; | 
|---|
| 5 | use core::ops::Range; | 
|---|
| 6 |  | 
|---|
| 7 | bitflags::bitflags! { | 
|---|
| 8 | /// Flags for WebAssembly symbols. | 
|---|
| 9 | /// | 
|---|
| 10 | /// These flags correspond to those described in | 
|---|
| 11 | /// <https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md> | 
|---|
| 12 | /// with the `WASM_SYM_*` prefix. | 
|---|
| 13 | #[ repr(transparent)] | 
|---|
| 14 | #[ derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] | 
|---|
| 15 | pub struct SymbolFlags: u32 { | 
|---|
| 16 | /* N.B.: | 
|---|
| 17 | Newly added flags should be keep in sync with `print_dylink0_flags` | 
|---|
| 18 | in `crates/wasmprinter/src/lib.rs`. | 
|---|
| 19 | */ | 
|---|
| 20 | /// This is a weak symbol. | 
|---|
| 21 | const BINDING_WEAK = 1 << 0; | 
|---|
| 22 | /// This is a local symbol (this is exclusive with [BINDING_WEAK]). | 
|---|
| 23 | const BINDING_LOCAL = 1 << 1; | 
|---|
| 24 | /// This is a hidden symbol. | 
|---|
| 25 | const VISIBILITY_HIDDEN = 1 << 2; | 
|---|
| 26 | /// This symbol is not defined. | 
|---|
| 27 | const UNDEFINED = 1 << 4; | 
|---|
| 28 | /// This symbol is intended to be exported from the wasm module to the host environment. | 
|---|
| 29 | const EXPORTED = 1 << 5; | 
|---|
| 30 | /// This symbol uses an explicit symbol name, rather than reusing the name from a wasm import. | 
|---|
| 31 | const EXPLICIT_NAME = 1 << 6; | 
|---|
| 32 | /// This symbol is intended to be included in the linker output, regardless of whether it is used by the program. | 
|---|
| 33 | const NO_STRIP = 1 << 7; | 
|---|
| 34 | /// This symbol resides in thread local storage. | 
|---|
| 35 | const TLS = 1 << 8; | 
|---|
| 36 | /// This symbol represents an absolute address. | 
|---|
| 37 | const ABSOLUTE = 1 << 9; | 
|---|
| 38 | } | 
|---|
| 39 |  | 
|---|
| 40 | /// Flags for WebAssembly segments. | 
|---|
| 41 | /// | 
|---|
| 42 | /// These flags are defined by implementation at the time of writing: | 
|---|
| 43 | /// <https://github.com/llvm/llvm-project/blob/llvmorg-17.0.6/llvm/include/llvm/BinaryFormat/Wasm.h#L391-L394> | 
|---|
| 44 | #[ repr(transparent)] | 
|---|
| 45 | #[ derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)] | 
|---|
| 46 | pub struct SegmentFlags: u32 { | 
|---|
| 47 | /// The segment contains only null-terminated strings, which allows the linker to perform merging. | 
|---|
| 48 | const STRINGS = 0x1; | 
|---|
| 49 | /// The segment contains thread-local data. | 
|---|
| 50 | const TLS = 0x2; | 
|---|
| 51 | } | 
|---|
| 52 | } | 
|---|
| 53 |  | 
|---|
| 54 | impl<'a> FromReader<'a> for SymbolFlags { | 
|---|
| 55 | fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> { | 
|---|
| 56 | Ok(Self::from_bits_retain(bits:reader.read_var_u32()?)) | 
|---|
| 57 | } | 
|---|
| 58 | } | 
|---|
| 59 |  | 
|---|
| 60 | impl<'a> FromReader<'a> for SegmentFlags { | 
|---|
| 61 | fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> { | 
|---|
| 62 | Ok(Self::from_bits_retain(bits:reader.read_var_u32()?)) | 
|---|
| 63 | } | 
|---|
| 64 | } | 
|---|
| 65 |  | 
|---|
| 66 | /// A reader for the `linking` custom section of a WebAssembly module. | 
|---|
| 67 | /// | 
|---|
| 68 | /// This format is currently defined upstream at | 
|---|
| 69 | /// <https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md>. | 
|---|
| 70 | #[ derive(Debug, Clone)] | 
|---|
| 71 | pub struct LinkingSectionReader<'a> { | 
|---|
| 72 | /// The version of linking metadata contained in this section. | 
|---|
| 73 | version: u32, | 
|---|
| 74 | /// The subsections in this section. | 
|---|
| 75 | subsections: Subsections<'a, Linking<'a>>, | 
|---|
| 76 | /// The range of the entire section, including the version. | 
|---|
| 77 | range: Range<usize>, | 
|---|
| 78 | } | 
|---|
| 79 |  | 
|---|
| 80 | /// Represents a reader for segments from the linking custom section. | 
|---|
| 81 | pub type SegmentMap<'a> = SectionLimited<'a, Segment<'a>>; | 
|---|
| 82 |  | 
|---|
| 83 | /// Represents extra metadata about the data segments. | 
|---|
| 84 | #[ derive(Debug, Copy, Clone)] | 
|---|
| 85 | pub struct Segment<'a> { | 
|---|
| 86 | /// The name for the segment. | 
|---|
| 87 | pub name: &'a str, | 
|---|
| 88 | /// The required alignment of the segment, encoded as a power of 2. | 
|---|
| 89 | pub alignment: u32, | 
|---|
| 90 | /// The flags for the segment. | 
|---|
| 91 | pub flags: SegmentFlags, | 
|---|
| 92 | } | 
|---|
| 93 |  | 
|---|
| 94 | impl<'a> FromReader<'a> for Segment<'a> { | 
|---|
| 95 | fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> { | 
|---|
| 96 | let name: &'a str = reader.read_string()?; | 
|---|
| 97 | let alignment: u32 = reader.read_var_u32()?; | 
|---|
| 98 | let flags: SegmentFlags = reader.read()?; | 
|---|
| 99 | Ok(Self { | 
|---|
| 100 | name, | 
|---|
| 101 | alignment, | 
|---|
| 102 | flags, | 
|---|
| 103 | }) | 
|---|
| 104 | } | 
|---|
| 105 | } | 
|---|
| 106 |  | 
|---|
| 107 | /// Represents a reader for init functions from the linking custom section. | 
|---|
| 108 | pub type InitFuncMap<'a> = SectionLimited<'a, InitFunc>; | 
|---|
| 109 |  | 
|---|
| 110 | /// Represents an init function in the linking custom section. | 
|---|
| 111 | #[ derive(Debug, Copy, Clone)] | 
|---|
| 112 | pub struct InitFunc { | 
|---|
| 113 | /// The priority of the init function. | 
|---|
| 114 | pub priority: u32, | 
|---|
| 115 | /// The symbol index of init function (*not* the function index). | 
|---|
| 116 | pub symbol_index: u32, | 
|---|
| 117 | } | 
|---|
| 118 |  | 
|---|
| 119 | impl<'a> FromReader<'a> for InitFunc { | 
|---|
| 120 | fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> { | 
|---|
| 121 | let priority: u32 = reader.read_var_u32()?; | 
|---|
| 122 | let symbol_index: u32 = reader.read_var_u32()?; | 
|---|
| 123 | Ok(Self { | 
|---|
| 124 | priority, | 
|---|
| 125 | symbol_index, | 
|---|
| 126 | }) | 
|---|
| 127 | } | 
|---|
| 128 | } | 
|---|
| 129 |  | 
|---|
| 130 | /// Represents a reader for COMDAT data from the linking custom section. | 
|---|
| 131 | pub type ComdatMap<'a> = SectionLimited<'a, Comdat<'a>>; | 
|---|
| 132 |  | 
|---|
| 133 | /// Represents [COMDAT](https://llvm.org/docs/LangRef.html#comdats) data in the linking custom section. | 
|---|
| 134 | #[ derive(Debug, Clone)] | 
|---|
| 135 | pub struct Comdat<'a> { | 
|---|
| 136 | /// The name of this comdat. | 
|---|
| 137 | pub name: &'a str, | 
|---|
| 138 | /// The flags. | 
|---|
| 139 | pub flags: u32, | 
|---|
| 140 | /// The member symbols of this comdat. | 
|---|
| 141 | pub symbols: SectionLimited<'a, ComdatSymbol>, | 
|---|
| 142 | } | 
|---|
| 143 |  | 
|---|
| 144 | impl<'a> FromReader<'a> for Comdat<'a> { | 
|---|
| 145 | fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> { | 
|---|
| 146 | let name: &'a str = reader.read_string()?; | 
|---|
| 147 | let flags: u32 = reader.read_var_u32()?; | 
|---|
| 148 | // FIXME(#188) ideally shouldn't need to skip here | 
|---|
| 149 | let symbols: BinaryReader<'a> = reader.skip(|reader: &mut BinaryReader<'a>| { | 
|---|
| 150 | let count: u32 = reader.read_var_u32()?; | 
|---|
| 151 | for _ in 0..count { | 
|---|
| 152 | reader.read::<ComdatSymbol>()?; | 
|---|
| 153 | } | 
|---|
| 154 | Ok(()) | 
|---|
| 155 | })?; | 
|---|
| 156 | Ok(Self { | 
|---|
| 157 | name, | 
|---|
| 158 | flags, | 
|---|
| 159 | symbols: SectionLimited::new(reader:symbols)?, | 
|---|
| 160 | }) | 
|---|
| 161 | } | 
|---|
| 162 | } | 
|---|
| 163 |  | 
|---|
| 164 | /// Represents a symbol that is part of a comdat. | 
|---|
| 165 | #[ derive(Debug, Copy, Clone)] | 
|---|
| 166 | pub struct ComdatSymbol { | 
|---|
| 167 | /// The kind of the symbol. | 
|---|
| 168 | pub kind: ComdatSymbolKind, | 
|---|
| 169 | /// The index of the symbol. Must not be an import. | 
|---|
| 170 | pub index: u32, | 
|---|
| 171 | } | 
|---|
| 172 |  | 
|---|
| 173 | impl<'a> FromReader<'a> for ComdatSymbol { | 
|---|
| 174 | fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> { | 
|---|
| 175 | let kind: ComdatSymbolKind = reader.read()?; | 
|---|
| 176 | let index: u32 = reader.read_var_u32()?; | 
|---|
| 177 | Ok(Self { kind, index }) | 
|---|
| 178 | } | 
|---|
| 179 | } | 
|---|
| 180 |  | 
|---|
| 181 | /// Represents a symbol kind. | 
|---|
| 182 | #[ derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | 
|---|
| 183 | pub enum ComdatSymbolKind { | 
|---|
| 184 | /// The symbol is a data segment. | 
|---|
| 185 | Data, | 
|---|
| 186 | /// The symbol is a function. | 
|---|
| 187 | Func, | 
|---|
| 188 | /// The symbol is a global. | 
|---|
| 189 | Global, | 
|---|
| 190 | /// The symbol is an event. | 
|---|
| 191 | Event, | 
|---|
| 192 | /// The symbol is a table. | 
|---|
| 193 | Table, | 
|---|
| 194 | /// The symbol is a section. | 
|---|
| 195 | Section, | 
|---|
| 196 | } | 
|---|
| 197 |  | 
|---|
| 198 | impl<'a> FromReader<'a> for ComdatSymbolKind { | 
|---|
| 199 | fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> { | 
|---|
| 200 | let offset: usize = reader.original_position(); | 
|---|
| 201 | match reader.read_u8()? { | 
|---|
| 202 | 0 => Ok(Self::Data), | 
|---|
| 203 | 1 => Ok(Self::Func), | 
|---|
| 204 | 2 => Ok(Self::Global), | 
|---|
| 205 | 3 => Ok(Self::Event), | 
|---|
| 206 | 4 => Ok(Self::Table), | 
|---|
| 207 | 5 => Ok(Self::Section), | 
|---|
| 208 | k: u8 => Err(BinaryReader::invalid_leading_byte_error( | 
|---|
| 209 | byte:k, | 
|---|
| 210 | desc: "comdat symbol kind", | 
|---|
| 211 | offset, | 
|---|
| 212 | )), | 
|---|
| 213 | } | 
|---|
| 214 | } | 
|---|
| 215 | } | 
|---|
| 216 |  | 
|---|
| 217 | /// Represents a reader for symbol info from the linking custom section. | 
|---|
| 218 | pub type SymbolInfoMap<'a> = SectionLimited<'a, SymbolInfo<'a>>; | 
|---|
| 219 |  | 
|---|
| 220 | /// Represents extra information about symbols in the linking custom section. | 
|---|
| 221 | /// | 
|---|
| 222 | /// The symbol flags correspond to those described in | 
|---|
| 223 | /// <https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md> | 
|---|
| 224 | /// with the `WASM_SYM_*` prefix. | 
|---|
| 225 | #[ derive(Debug, Copy, Clone)] | 
|---|
| 226 | pub enum SymbolInfo<'a> { | 
|---|
| 227 | /// The symbol is a function. | 
|---|
| 228 | Func { | 
|---|
| 229 | /// The flags for the symbol. | 
|---|
| 230 | flags: SymbolFlags, | 
|---|
| 231 | /// The index of the function corresponding to this symbol. | 
|---|
| 232 | index: u32, | 
|---|
| 233 | /// The name for the function, if it is defined or uses an explicit name. | 
|---|
| 234 | name: Option<&'a str>, | 
|---|
| 235 | }, | 
|---|
| 236 | /// The symbol is a data symbol. | 
|---|
| 237 | Data { | 
|---|
| 238 | /// The flags for the symbol. | 
|---|
| 239 | flags: SymbolFlags, | 
|---|
| 240 | /// The name for the symbol. | 
|---|
| 241 | name: &'a str, | 
|---|
| 242 | /// The definition of the data symbol, if it is defined. | 
|---|
| 243 | symbol: Option<DefinedDataSymbol>, | 
|---|
| 244 | }, | 
|---|
| 245 | /// The symbol is a global. | 
|---|
| 246 | Global { | 
|---|
| 247 | /// The flags for the symbol. | 
|---|
| 248 | flags: SymbolFlags, | 
|---|
| 249 | /// The index of the global corresponding to this symbol. | 
|---|
| 250 | index: u32, | 
|---|
| 251 | /// The name for the global, if it is defined or uses an explicit name. | 
|---|
| 252 | name: Option<&'a str>, | 
|---|
| 253 | }, | 
|---|
| 254 | /// The symbol is a section. | 
|---|
| 255 | Section { | 
|---|
| 256 | /// The flags for the symbol. | 
|---|
| 257 | flags: SymbolFlags, | 
|---|
| 258 | /// The index of the function corresponding to this symbol. | 
|---|
| 259 | section: u32, | 
|---|
| 260 | }, | 
|---|
| 261 | /// The symbol is an event. | 
|---|
| 262 | Event { | 
|---|
| 263 | /// The flags for the symbol. | 
|---|
| 264 | flags: SymbolFlags, | 
|---|
| 265 | /// The index of the event corresponding to this symbol. | 
|---|
| 266 | index: u32, | 
|---|
| 267 | /// The name for the event, if it is defined or uses an explicit name. | 
|---|
| 268 | name: Option<&'a str>, | 
|---|
| 269 | }, | 
|---|
| 270 | /// The symbol is a table. | 
|---|
| 271 | Table { | 
|---|
| 272 | /// The flags for the symbol. | 
|---|
| 273 | flags: SymbolFlags, | 
|---|
| 274 | /// The index of the table corresponding to this symbol. | 
|---|
| 275 | index: u32, | 
|---|
| 276 | /// The name for the table, if it is defined or uses an explicit name. | 
|---|
| 277 | name: Option<&'a str>, | 
|---|
| 278 | }, | 
|---|
| 279 | } | 
|---|
| 280 |  | 
|---|
| 281 | impl<'a> FromReader<'a> for SymbolInfo<'a> { | 
|---|
| 282 | fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> { | 
|---|
| 283 | let offset = reader.original_position(); | 
|---|
| 284 | let kind = reader.read_u8()?; | 
|---|
| 285 | let flags: SymbolFlags = reader.read()?; | 
|---|
| 286 |  | 
|---|
| 287 | let defined = !flags.contains(SymbolFlags::UNDEFINED); | 
|---|
| 288 | let explicit_name = flags.contains(SymbolFlags::EXPLICIT_NAME); | 
|---|
| 289 |  | 
|---|
| 290 | const SYMTAB_FUNCTION: u8 = 0; | 
|---|
| 291 | const SYMTAB_DATA: u8 = 1; | 
|---|
| 292 | const SYMTAB_GLOBAL: u8 = 2; | 
|---|
| 293 | const SYMTAB_SECTION: u8 = 3; | 
|---|
| 294 | const SYMTAB_EVENT: u8 = 4; | 
|---|
| 295 | const SYMTAB_TABLE: u8 = 5; | 
|---|
| 296 |  | 
|---|
| 297 | // https://github.com/WebAssembly/wabt/blob/1.0.34/src/binary-writer.cc#L1226 | 
|---|
| 298 | match kind { | 
|---|
| 299 | SYMTAB_FUNCTION | SYMTAB_GLOBAL | SYMTAB_EVENT | SYMTAB_TABLE => { | 
|---|
| 300 | let index = reader.read_var_u32()?; | 
|---|
| 301 | let name = match defined || explicit_name { | 
|---|
| 302 | true => Some(reader.read_string()?), | 
|---|
| 303 | false => None, | 
|---|
| 304 | }; | 
|---|
| 305 | Ok(match kind { | 
|---|
| 306 | SYMTAB_FUNCTION => Self::Func { flags, index, name }, | 
|---|
| 307 | SYMTAB_GLOBAL => Self::Global { flags, index, name }, | 
|---|
| 308 | SYMTAB_EVENT => Self::Event { flags, index, name }, | 
|---|
| 309 | SYMTAB_TABLE => Self::Table { flags, index, name }, | 
|---|
| 310 | _ => unreachable!(), | 
|---|
| 311 | }) | 
|---|
| 312 | } | 
|---|
| 313 | SYMTAB_DATA => { | 
|---|
| 314 | let name = reader.read_string()?; | 
|---|
| 315 | let data = match defined { | 
|---|
| 316 | true => Some(reader.read()?), | 
|---|
| 317 | false => None, | 
|---|
| 318 | }; | 
|---|
| 319 | Ok(Self::Data { | 
|---|
| 320 | flags, | 
|---|
| 321 | name, | 
|---|
| 322 | symbol: data, | 
|---|
| 323 | }) | 
|---|
| 324 | } | 
|---|
| 325 | SYMTAB_SECTION => { | 
|---|
| 326 | let section = reader.read_var_u32()?; | 
|---|
| 327 | Ok(Self::Section { flags, section }) | 
|---|
| 328 | } | 
|---|
| 329 | k => Err(BinaryReader::invalid_leading_byte_error( | 
|---|
| 330 | k, | 
|---|
| 331 | "symbol kind", | 
|---|
| 332 | offset, | 
|---|
| 333 | )), | 
|---|
| 334 | } | 
|---|
| 335 | } | 
|---|
| 336 | } | 
|---|
| 337 |  | 
|---|
| 338 | /// Represents the metadata about a data symbol defined in the wasm file. | 
|---|
| 339 | #[ derive(Debug, Copy, Clone)] | 
|---|
| 340 | pub struct DefinedDataSymbol { | 
|---|
| 341 | /// The index of the data segment. | 
|---|
| 342 | pub index: u32, | 
|---|
| 343 | /// The offset within the segment. Must be <= the segment's size. | 
|---|
| 344 | pub offset: u32, | 
|---|
| 345 | /// The size of the data, which can be zero. `offset + size` must be <= the segment's size. | 
|---|
| 346 | pub size: u32, | 
|---|
| 347 | } | 
|---|
| 348 |  | 
|---|
| 349 | impl<'a> FromReader<'a> for DefinedDataSymbol { | 
|---|
| 350 | fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> { | 
|---|
| 351 | let index: u32 = reader.read_var_u32()?; | 
|---|
| 352 | let offset: u32 = reader.read_var_u32()?; | 
|---|
| 353 | let size: u32 = reader.read_var_u32()?; | 
|---|
| 354 | Ok(Self { | 
|---|
| 355 | index, | 
|---|
| 356 | offset, | 
|---|
| 357 | size, | 
|---|
| 358 | }) | 
|---|
| 359 | } | 
|---|
| 360 | } | 
|---|
| 361 |  | 
|---|
| 362 | /// Represents a subsection read from the linking custom section. | 
|---|
| 363 | #[ derive(Debug, Clone)] | 
|---|
| 364 | pub enum Linking<'a> { | 
|---|
| 365 | /// Extra metadata about the data segments. | 
|---|
| 366 | SegmentInfo(SegmentMap<'a>), | 
|---|
| 367 | /// A list of constructor functions to be called at startup. | 
|---|
| 368 | InitFuncs(InitFuncMap<'a>), | 
|---|
| 369 | /// The [COMDAT](https://llvm.org/docs/LangRef.html#comdats) groups of associated linking objects. | 
|---|
| 370 | ComdatInfo(ComdatMap<'a>), | 
|---|
| 371 | /// Extra information about the symbols present in the module. | 
|---|
| 372 | SymbolTable(SymbolInfoMap<'a>), | 
|---|
| 373 | /// An unknown [linking subsection](https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md#linking-metadata-section). | 
|---|
| 374 | Unknown { | 
|---|
| 375 | /// The identifier for this subsection. | 
|---|
| 376 | ty: u8, | 
|---|
| 377 | /// The contents of this subsection. | 
|---|
| 378 | data: &'a [u8], | 
|---|
| 379 | /// The range of bytes, relative to the start of the original data | 
|---|
| 380 | /// stream, that the contents of this subsection reside in. | 
|---|
| 381 | range: Range<usize>, | 
|---|
| 382 | }, | 
|---|
| 383 | } | 
|---|
| 384 |  | 
|---|
| 385 | impl<'a> Subsection<'a> for Linking<'a> { | 
|---|
| 386 | fn from_reader(id: u8, reader: BinaryReader<'a>) -> Result<Self> { | 
|---|
| 387 | let data: &[u8] = reader.remaining_buffer(); | 
|---|
| 388 | let offset: usize = reader.original_position(); | 
|---|
| 389 | Ok(match id { | 
|---|
| 390 | 5 => Self::SegmentInfo(SegmentMap::new(reader)?), | 
|---|
| 391 | 6 => Self::InitFuncs(InitFuncMap::new(reader)?), | 
|---|
| 392 | 7 => Self::ComdatInfo(ComdatMap::new(reader)?), | 
|---|
| 393 | 8 => Self::SymbolTable(SymbolInfoMap::new(reader)?), | 
|---|
| 394 | ty: u8 => Self::Unknown { | 
|---|
| 395 | ty, | 
|---|
| 396 | data, | 
|---|
| 397 | range: offset..offset + data.len(), | 
|---|
| 398 | }, | 
|---|
| 399 | }) | 
|---|
| 400 | } | 
|---|
| 401 | } | 
|---|
| 402 |  | 
|---|
| 403 | impl<'a> LinkingSectionReader<'a> { | 
|---|
| 404 | /// Creates a new reader for the linking section contents starting at | 
|---|
| 405 | /// `offset` within the original wasm file. | 
|---|
| 406 | pub fn new(mut reader: BinaryReader<'a>) -> Result<Self> { | 
|---|
| 407 | let range = reader.range(); | 
|---|
| 408 | let offset = reader.original_position(); | 
|---|
| 409 |  | 
|---|
| 410 | let version = reader.read_var_u32()?; | 
|---|
| 411 | if version != 2 { | 
|---|
| 412 | return Err(BinaryReaderError::new( | 
|---|
| 413 | format!( "unsupported linking section version: {} ", version), | 
|---|
| 414 | offset, | 
|---|
| 415 | )); | 
|---|
| 416 | } | 
|---|
| 417 |  | 
|---|
| 418 | let subsections = Subsections::new(reader.shrink()); | 
|---|
| 419 | Ok(Self { | 
|---|
| 420 | version, | 
|---|
| 421 | subsections, | 
|---|
| 422 | range, | 
|---|
| 423 | }) | 
|---|
| 424 | } | 
|---|
| 425 |  | 
|---|
| 426 | /// Returns the version of linking metadata contained in this section. | 
|---|
| 427 | pub fn version(&self) -> u32 { | 
|---|
| 428 | self.version | 
|---|
| 429 | } | 
|---|
| 430 |  | 
|---|
| 431 | /// Returns the original byte offset of this section. | 
|---|
| 432 | pub fn original_position(&self) -> usize { | 
|---|
| 433 | self.subsections.original_position() | 
|---|
| 434 | } | 
|---|
| 435 |  | 
|---|
| 436 | /// Returns the range, as byte offsets, of this section within the original | 
|---|
| 437 | /// wasm binary. | 
|---|
| 438 | pub fn range(&self) -> Range<usize> { | 
|---|
| 439 | self.range.clone() | 
|---|
| 440 | } | 
|---|
| 441 |  | 
|---|
| 442 | /// Returns the iterator for advancing through the subsections. | 
|---|
| 443 | /// | 
|---|
| 444 | /// You can also use [`IntoIterator::into_iter`] directly on this type. | 
|---|
| 445 | pub fn subsections(&self) -> Subsections<'a, Linking<'a>> { | 
|---|
| 446 | self.subsections.clone() | 
|---|
| 447 | } | 
|---|
| 448 | } | 
|---|
| 449 |  | 
|---|
| 450 | impl<'a> IntoIterator for LinkingSectionReader<'a> { | 
|---|
| 451 | type Item = Result<Linking<'a>>; | 
|---|
| 452 | type IntoIter = Subsections<'a, Linking<'a>>; | 
|---|
| 453 |  | 
|---|
| 454 | fn into_iter(self) -> Self::IntoIter { | 
|---|
| 455 | self.subsections | 
|---|
| 456 | } | 
|---|
| 457 | } | 
|---|
| 458 |  | 
|---|