Extremely minimal wasm module reader. Currently only used for parsing the dylink section.
| 190 | |
| 191 | |
| 192 | class Module: |
| 193 | """Extremely minimal wasm module reader. |
| 194 | |
| 195 | Currently only used for parsing the dylink section. |
| 196 | """ |
| 197 | |
| 198 | def __init__(self, filename): |
| 199 | self.buf = None # Set this before FS calls below in case they throw. |
| 200 | self.filename = filename |
| 201 | self.size = os.path.getsize(filename) |
| 202 | self.buf = open(filename, 'rb') |
| 203 | magic = self.buf.read(4) |
| 204 | version = self.buf.read(4) |
| 205 | if magic != MAGIC or version != VERSION: |
| 206 | raise InvalidWasmError(f'{filename} is not a valid wasm file') |
| 207 | self._cache = {} |
| 208 | |
| 209 | def __del__(self): |
| 210 | assert not self.buf, '`__exit__` should have already been called, please use context manager' |
| 211 | |
| 212 | def __enter__(self): |
| 213 | return self |
| 214 | |
| 215 | def __exit__(self, _exc_type, _exc_val, _exc_tb): |
| 216 | if self.buf: |
| 217 | self.buf.close() |
| 218 | self.buf = None |
| 219 | |
| 220 | def read_at(self, offset, count): |
| 221 | self.buf.seek(offset) |
| 222 | return self.buf.read(count) |
| 223 | |
| 224 | def read_byte(self): |
| 225 | return self.buf.read(1)[0] |
| 226 | |
| 227 | def read_uleb(self): |
| 228 | return read_uleb(self.buf) |
| 229 | |
| 230 | def read_sleb(self): |
| 231 | return read_sleb(self.buf) |
| 232 | |
| 233 | def read_string(self): |
| 234 | size = self.read_uleb() |
| 235 | return self.buf.read(size).decode('utf-8') |
| 236 | |
| 237 | def read_limits(self): |
| 238 | flags = self.read_byte() |
| 239 | initial = self.read_uleb() |
| 240 | maximum = 0 |
| 241 | if flags & LIMITS_HAS_MAX: |
| 242 | maximum = self.read_uleb() |
| 243 | return Limits(flags, initial, maximum) |
| 244 | |
| 245 | def read_type(self): |
| 246 | return Type(self.read_uleb()) |
| 247 | |
| 248 | def read_init(self): |
| 249 | code = [] |
no outgoing calls
no test coverage detected