WasmBinaryReader.cpp 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "WasmReaderPch.h"
  6. #ifdef ENABLE_WASM
  7. #if ENABLE_DEBUG_CONFIG_OPTIONS
  8. #include "Codex/Utf8Helper.h"
  9. #endif
  10. namespace Wasm
  11. {
  12. namespace WasmTypes
  13. {
  14. bool IsLocalType(WasmTypes::WasmType type)
  15. {
  16. // Check if type in range ]Void,Limit[
  17. return (uint)(type - 1) < (WasmTypes::Limit - 1);
  18. }
  19. uint32 GetTypeByteSize(WasmType type)
  20. {
  21. switch (type)
  22. {
  23. case Void: return sizeof(Js::Var);
  24. case I32: return sizeof(int32);
  25. case I64: return sizeof(int64);
  26. case F32: return sizeof(float);
  27. case F64: return sizeof(double);
  28. default:
  29. Js::Throw::InternalError();
  30. }
  31. }
  32. } // namespace WasmTypes
  33. WasmTypes::WasmType
  34. LanguageTypes::ToWasmType(int8 binType)
  35. {
  36. switch (binType)
  37. {
  38. case LanguageTypes::i32: return WasmTypes::I32;
  39. case LanguageTypes::i64: return WasmTypes::I64;
  40. case LanguageTypes::f32: return WasmTypes::F32;
  41. case LanguageTypes::f64: return WasmTypes::F64;
  42. default:
  43. throw WasmCompilationException(_u("Invalid binary type %d"), binType);
  44. }
  45. }
  46. bool
  47. FunctionIndexTypes::CanBeExported(FunctionIndexTypes::Type funcType)
  48. {
  49. return funcType == FunctionIndexTypes::Function || funcType == FunctionIndexTypes::ImportThunk;
  50. }
  51. WasmBinaryReader::WasmBinaryReader(ArenaAllocator* alloc, Js::WebAssemblyModule * module, const byte* source, size_t length) :
  52. m_module(module),
  53. m_curFuncEnd(nullptr),
  54. m_alloc(alloc),
  55. m_readerState(READER_STATE_UNKNOWN)
  56. {
  57. m_start = m_pc = source;
  58. m_end = source + length;
  59. m_currentSection.code = bSectLimit;
  60. #if DBG_DUMP
  61. m_ops = Anew(m_alloc, OpSet, m_alloc);
  62. #endif
  63. }
  64. void WasmBinaryReader::InitializeReader()
  65. {
  66. ValidateModuleHeader();
  67. m_readerState = READER_STATE_UNKNOWN;
  68. }
  69. void
  70. WasmBinaryReader::ThrowDecodingError(const char16* msg, ...)
  71. {
  72. va_list argptr;
  73. va_start(argptr, msg);
  74. throw WasmCompilationException(msg, argptr);
  75. }
  76. bool
  77. WasmBinaryReader::ReadNextSection(SectionCode nextSection)
  78. {
  79. while (true)
  80. {
  81. if (EndOfModule() || SectionInfo::All[nextSection].flag == fSectIgnore)
  82. {
  83. return false;
  84. }
  85. m_currentSection = ReadSectionHeader();
  86. if (SectionInfo::All[m_currentSection.code].flag == fSectIgnore)
  87. {
  88. TRACE_WASM_DECODER(_u("Ignore this section"));
  89. m_pc = m_currentSection.end;
  90. // Read next section
  91. continue;
  92. }
  93. // Process the custom sections now
  94. if (m_currentSection.code == bSectCustom)
  95. {
  96. if (!ProcessCurrentSection())
  97. {
  98. ThrowDecodingError(_u("Error while reading custom section %s"), m_currentSection.name);
  99. }
  100. // Read next section
  101. continue;
  102. }
  103. if (m_currentSection.code < nextSection)
  104. {
  105. ThrowDecodingError(_u("Invalid Section %s"), m_currentSection.code);
  106. }
  107. if (m_currentSection.code != nextSection)
  108. {
  109. TRACE_WASM_DECODER(_u("The current section is not the one we are looking for"));
  110. // We know about this section, but it's not the one we're looking for
  111. m_pc = m_currentSection.start;
  112. return false;
  113. }
  114. return true;
  115. }
  116. }
  117. bool
  118. WasmBinaryReader::ProcessCurrentSection()
  119. {
  120. Assert(m_currentSection.code != bSectLimit);
  121. TRACE_WASM_SECTION(_u("Process section %s"), SectionInfo::All[m_currentSection.code].name);
  122. m_readerState = READER_STATE_MODULE;
  123. switch (m_currentSection.code)
  124. {
  125. case bSectMemory:
  126. ReadMemorySection(false);
  127. break;
  128. case bSectSignatures:
  129. ReadSignatures();
  130. break;
  131. case bSectImportTable:
  132. ReadImportEntries();
  133. break;
  134. case bSectFunctionSignatures:
  135. ReadFunctionsSignatures();
  136. break;
  137. case bSectFunctionBodies:
  138. ReadFunctionHeaders();
  139. break;
  140. case bSectExportTable:
  141. ReadExportTable();
  142. break;
  143. case bSectStartFunction:
  144. ReadStartFunction();
  145. break;
  146. case bSectDataSegments:
  147. ReadDataSegments();
  148. break;
  149. case bSectIndirectFunctionTable:
  150. ReadTableSection(false);
  151. break;
  152. case bSectElement:
  153. ReadElementSection();
  154. break;
  155. case bSectNames:
  156. ReadNamesSection();
  157. break;
  158. case bSectGlobal:
  159. ReadGlobalsSection();
  160. break;
  161. case bSectCustom:
  162. ReadCustomSection();
  163. break;
  164. default:
  165. Assert(UNREACHED);
  166. m_readerState = READER_STATE_UNKNOWN;
  167. return false;
  168. }
  169. m_readerState = READER_STATE_UNKNOWN;
  170. return m_pc == m_currentSection.end;
  171. }
  172. SectionHeader
  173. WasmBinaryReader::ReadSectionHeader()
  174. {
  175. SectionHeader header;
  176. header.start = m_pc;
  177. header.code = bSectLimit;
  178. UINT len = 0;
  179. CompileAssert(sizeof(SectionCode) == sizeof(uint8));
  180. SectionCode sectionId = (SectionCode)ReadVarUInt7();
  181. if (sectionId > bsectLastKnownSection)
  182. {
  183. ThrowDecodingError(_u("Invalid known section opcode %u"), sectionId);
  184. }
  185. UINT32 sectionSize = LEB128(len);
  186. header.end = m_pc + sectionSize;
  187. CheckBytesLeft(sectionSize);
  188. header.code = sectionId;
  189. if (sectionId == bSectCustom)
  190. {
  191. header.name = ReadInlineName(len, header.nameLength);
  192. }
  193. else
  194. {
  195. header.name = SectionInfo::All[sectionId].name;
  196. header.nameLength = SectionInfo::All[sectionId].nameLength;
  197. }
  198. TRACE_WASM_SECTION(_u("Section Header: %s, length = %u (0x%x)"), header.name, sectionSize, sectionSize);
  199. return header;
  200. }
  201. #if DBG_DUMP
  202. void
  203. WasmBinaryReader::PrintOps()
  204. {
  205. int count = m_ops->Count();
  206. if (count == 0)
  207. {
  208. return;
  209. }
  210. WasmOp * ops = HeapNewArray(WasmOp, count);
  211. auto iter = m_ops->GetIterator();
  212. int i = 0;
  213. while (iter.IsValid())
  214. {
  215. ops[i] = iter.CurrentKey();
  216. iter.MoveNext();
  217. ++i;
  218. }
  219. for (i = 0; i < count; ++i)
  220. {
  221. int j = i;
  222. while (j > 0 && ops[j-1] > ops[j])
  223. {
  224. WasmOp tmp = ops[j];
  225. ops[j] = ops[j - 1];
  226. ops[j - 1] = tmp;
  227. --j;
  228. }
  229. }
  230. for (i = 0; i < count; ++i)
  231. {
  232. switch (ops[i])
  233. {
  234. #define WASM_OPCODE(opname, opcode, sig, nyi) \
  235. case opcode: \
  236. Output::Print(_u("%s\r\n"), _u(#opname)); \
  237. break;
  238. #include "WasmBinaryOpCodes.h"
  239. }
  240. }
  241. HeapDeleteArray(count, ops);
  242. }
  243. #endif
  244. void
  245. WasmBinaryReader::ReadFunctionHeaders()
  246. {
  247. uint32 len;
  248. uint32 entries = LEB128(len);
  249. uint32 importCount = m_module->GetImportedFunctionCount();
  250. if (m_module->GetWasmFunctionCount() < importCount ||
  251. entries != m_module->GetWasmFunctionCount() - importCount)
  252. {
  253. ThrowDecodingError(_u("Function signatures and function bodies count mismatch"));
  254. }
  255. for (uint32 i = 0; i < entries; ++i)
  256. {
  257. uint32 funcIndex = i + importCount;
  258. WasmFunctionInfo* funcInfo = m_module->GetWasmFunctionInfo(funcIndex);
  259. const uint32 funcSize = LEB128(len);
  260. funcInfo->m_readerInfo.index = funcIndex;
  261. funcInfo->m_readerInfo.size = funcSize;
  262. funcInfo->m_readerInfo.startOffset = (m_pc - m_start);
  263. CheckBytesLeft(funcSize);
  264. TRACE_WASM_DECODER(_u("Function body header: index = %u, size = %u"), funcIndex, funcSize);
  265. const byte* end = m_pc + funcSize;
  266. m_pc = end;
  267. }
  268. }
  269. void
  270. WasmBinaryReader::SeekToFunctionBody(FunctionBodyReaderInfo readerInfo)
  271. {
  272. if (readerInfo.startOffset >= (m_end - m_start))
  273. {
  274. ThrowDecodingError(_u("Function byte offset out of bounds"));
  275. }
  276. if (m_readerState != READER_STATE_UNKNOWN)
  277. {
  278. ThrowDecodingError(_u("Wasm reader in an invalid state to read function code"));
  279. }
  280. m_readerState = READER_STATE_FUNCTION;
  281. // Seek to the function start and skip function header (count)
  282. m_pc = m_start + readerInfo.startOffset;
  283. m_funcState.size = readerInfo.size;
  284. m_funcState.count = 0;
  285. CheckBytesLeft(readerInfo.size);
  286. m_curFuncEnd = m_pc + m_funcState.size;
  287. uint32 len = 0;
  288. uint32 entryCount = LEB128(len);
  289. m_funcState.count += len;
  290. WasmFunctionInfo* funcInfo = m_module->GetWasmFunctionInfo(readerInfo.index);
  291. // locals
  292. for (uint32 j = 0; j < entryCount; j++)
  293. {
  294. uint32 count = LEB128(len);
  295. m_funcState.count += len;
  296. WasmTypes::WasmType type = ReadWasmType(len);
  297. if (!WasmTypes::IsLocalType(type))
  298. {
  299. ThrowDecodingError(_u("Invalid local type"));
  300. }
  301. m_funcState.count += len;
  302. funcInfo->AddLocal(type, count);
  303. switch (type)
  304. {
  305. case WasmTypes::I32: TRACE_WASM_DECODER(_u("Local: type = I32, count = %u"), count); break;
  306. case WasmTypes::I64: TRACE_WASM_DECODER(_u("Local: type = I64, count = %u"), count); break;
  307. case WasmTypes::F32: TRACE_WASM_DECODER(_u("Local: type = F32, count = %u"), count); break;
  308. case WasmTypes::F64: TRACE_WASM_DECODER(_u("Local: type = F64, count = %u"), count); break;
  309. break;
  310. default:
  311. break;
  312. }
  313. }
  314. }
  315. void WasmBinaryReader::FunctionEnd()
  316. {
  317. m_readerState = READER_STATE_UNKNOWN;
  318. }
  319. bool WasmBinaryReader::IsCurrentFunctionCompleted() const
  320. {
  321. return m_pc == m_curFuncEnd;
  322. }
  323. WasmOp
  324. WasmBinaryReader::ReadExpr()
  325. {
  326. WasmOp op = m_currentNode.op = (WasmOp)*m_pc++;
  327. ++m_funcState.count;
  328. if (EndOfFunc())
  329. {
  330. // end of AST
  331. if (op != wbEnd)
  332. {
  333. ThrowDecodingError(_u("missing function end opcode"));
  334. }
  335. return op;
  336. }
  337. switch (op)
  338. {
  339. case wbBlock:
  340. case wbLoop:
  341. case wbIf:
  342. BlockNode();
  343. break;
  344. case wbElse:
  345. // no node attributes
  346. break;
  347. case wbCall:
  348. CallNode();
  349. break;
  350. case wbCallIndirect:
  351. CallIndirectNode();
  352. break;
  353. case wbBr:
  354. case wbBrIf:
  355. BrNode();
  356. break;
  357. case wbBrTable:
  358. BrTableNode();
  359. break;
  360. case wbReturn:
  361. break;
  362. case wbI32Const:
  363. ConstNode<WasmTypes::I32>();
  364. break;
  365. case wbI64Const:
  366. ConstNode<WasmTypes::I64>();
  367. break;
  368. case wbF32Const:
  369. ConstNode<WasmTypes::F32>();
  370. break;
  371. case wbF64Const:
  372. ConstNode<WasmTypes::F64>();
  373. break;
  374. case wbSetLocal:
  375. case wbGetLocal:
  376. case wbTeeLocal:
  377. case wbGetGlobal:
  378. case wbSetGlobal:
  379. VarNode();
  380. break;
  381. case wbDrop:
  382. break;
  383. case wbEnd:
  384. break;
  385. case wbNop:
  386. break;
  387. case wbCurrentMemory:
  388. case wbGrowMemory:
  389. // Reserved value currently unused
  390. ReadConst<uint8>();
  391. break;
  392. #define WASM_MEM_OPCODE(opname, opcode, sig, nyi) \
  393. case wb##opname: \
  394. MemNode(); \
  395. break;
  396. #include "WasmBinaryOpCodes.h"
  397. default:
  398. break;
  399. }
  400. #if DBG_DUMP
  401. m_ops->AddNew(op);
  402. #endif
  403. return op;
  404. }
  405. void
  406. WasmBinaryReader::ValidateModuleHeader()
  407. {
  408. uint32 magicNumber = ReadConst<UINT32>();
  409. uint32 version = ReadConst<UINT32>();
  410. TRACE_WASM_DECODER(_u("Module Header: Magic 0x%x, Version %u"), magicNumber, version);
  411. if (magicNumber != 0x6d736100)
  412. {
  413. ThrowDecodingError(_u("Malformed WASM module header!"));
  414. }
  415. if (CONFIG_FLAG(WasmCheckVersion))
  416. {
  417. // Accept version 0xd to avoid problem in our test infrastructure
  418. // We should eventually remove support for 0xd.
  419. // The Assert is here as a reminder in case we change the binary version and we haven't removed 0xd support yet
  420. CompileAssert(binaryVersion == 0x1);
  421. if (version != binaryVersion && version != 0xd)
  422. {
  423. ThrowDecodingError(_u("Invalid WASM version!"));
  424. }
  425. }
  426. }
  427. void
  428. WasmBinaryReader::CallNode()
  429. {
  430. UINT length = 0;
  431. UINT32 funcNum = LEB128(length);
  432. m_funcState.count += length;
  433. FunctionIndexTypes::Type funcType = m_module->GetFunctionIndexType(funcNum);
  434. if (funcType == FunctionIndexTypes::Invalid)
  435. {
  436. ThrowDecodingError(_u("Function is out of bound"));
  437. }
  438. m_currentNode.call.funcType = funcType;
  439. m_currentNode.call.num = funcNum;
  440. }
  441. void
  442. WasmBinaryReader::CallIndirectNode()
  443. {
  444. UINT length = 0;
  445. UINT32 funcNum = LEB128(length);
  446. // Reserved value currently unused
  447. ReadConst<uint8>();
  448. if (!m_module->HasTable() && !m_module->HasTableImport())
  449. {
  450. ThrowDecodingError(_u("Found call_indirect operator, but no table"));
  451. }
  452. m_funcState.count += length;
  453. if (funcNum >= m_module->GetSignatureCount())
  454. {
  455. ThrowDecodingError(_u("Function is out of bound"));
  456. }
  457. m_currentNode.call.num = funcNum;
  458. m_currentNode.call.funcType = FunctionIndexTypes::Function;
  459. }
  460. void WasmBinaryReader::BlockNode()
  461. {
  462. int8 blockType = ReadConst<int8>();
  463. m_funcState.count++;
  464. m_currentNode.block.sig = blockType == LanguageTypes::emptyBlock ? WasmTypes::Void : LanguageTypes::ToWasmType(blockType);
  465. }
  466. // control flow
  467. void
  468. WasmBinaryReader::BrNode()
  469. {
  470. UINT len = 0;
  471. m_currentNode.br.depth = LEB128(len);
  472. m_funcState.count += len;
  473. }
  474. void
  475. WasmBinaryReader::BrTableNode()
  476. {
  477. UINT len = 0;
  478. m_currentNode.brTable.numTargets = LEB128(len);
  479. m_funcState.count += len;
  480. m_currentNode.brTable.targetTable = AnewArray(m_alloc, UINT32, m_currentNode.brTable.numTargets);
  481. for (UINT32 i = 0; i < m_currentNode.brTable.numTargets; i++)
  482. {
  483. m_currentNode.brTable.targetTable[i] = LEB128(len);
  484. m_funcState.count += len;
  485. }
  486. m_currentNode.brTable.defaultTarget = LEB128(len);
  487. m_funcState.count += len;
  488. }
  489. void
  490. WasmBinaryReader::MemNode()
  491. {
  492. uint len = 0;
  493. // flags
  494. const uint32 flags = LEB128(len);
  495. m_currentNode.mem.alignment = (uint8)flags;
  496. m_funcState.count += len;
  497. m_currentNode.mem.offset = LEB128(len);
  498. m_funcState.count += len;
  499. }
  500. // Locals/Globals
  501. void
  502. WasmBinaryReader::VarNode()
  503. {
  504. UINT length;
  505. m_currentNode.var.num = LEB128(length);
  506. m_funcState.count += length;
  507. }
  508. // Const
  509. template <WasmTypes::WasmType localType>
  510. void WasmBinaryReader::ConstNode()
  511. {
  512. UINT len = 0;
  513. switch (localType)
  514. {
  515. case WasmTypes::I32:
  516. m_currentNode.cnst.i32 = SLEB128(len);
  517. m_funcState.count += len;
  518. break;
  519. case WasmTypes::I64:
  520. m_currentNode.cnst.i64 = SLEB128<INT64>(len);
  521. m_funcState.count += len;
  522. break;
  523. case WasmTypes::F32:
  524. m_currentNode.cnst.f32 = ReadConst<float>();
  525. m_funcState.count += sizeof(float);
  526. break;
  527. case WasmTypes::F64:
  528. m_currentNode.cnst.f64 = ReadConst<double>();
  529. m_funcState.count += sizeof(double);
  530. break;
  531. }
  532. }
  533. bool
  534. WasmBinaryReader::EndOfFunc()
  535. {
  536. return m_funcState.count >= m_funcState.size;
  537. }
  538. bool
  539. WasmBinaryReader::EndOfModule()
  540. {
  541. return (m_pc >= m_end);
  542. }
  543. // readers
  544. void
  545. WasmBinaryReader::ReadMemorySection(bool isImportSection)
  546. {
  547. UINT length = 0;
  548. UINT32 count;
  549. if (isImportSection)
  550. {
  551. count = 1;
  552. }
  553. else
  554. {
  555. count = LEB128(length);
  556. }
  557. if (count > 1)
  558. {
  559. ThrowDecodingError(_u("Maximum of 1 memory allowed"));
  560. }
  561. if (count == 1)
  562. {
  563. uint32 flags = LEB128(length);
  564. uint32 minPage = LEB128(length);
  565. if (minPage > 65536)
  566. {
  567. throw Wasm::WasmCompilationException(_u("Memory size must be at most 65536 pages (4GiB)"));
  568. }
  569. uint32 maxPage = UINT32_MAX;
  570. if (flags & 0x1)
  571. {
  572. maxPage = LEB128(length);
  573. if (maxPage > 65536)
  574. {
  575. throw Wasm::WasmCompilationException(_u("Memory size must be at most 65536 pages (4GiB)"));
  576. }
  577. }
  578. m_module->InitializeMemory(minPage, maxPage);
  579. }
  580. }
  581. void
  582. WasmBinaryReader::ReadSignatures()
  583. {
  584. UINT len = 0;
  585. const uint32 count = LEB128(len);
  586. m_module->SetSignatureCount(count);
  587. // signatures table
  588. for (UINT32 i = 0; i < count; i++)
  589. {
  590. TRACE_WASM_DECODER(_u("Signature #%u"), i);
  591. WasmSignature * sig = m_module->GetSignature(i);
  592. sig->SetSignatureId(i);
  593. int8 form = ReadConst<int8>();
  594. if (form != LanguageTypes::func)
  595. {
  596. ThrowDecodingError(_u("Unexpected type form 0x%X"), form);
  597. }
  598. UINT32 paramCount = LEB128(len);
  599. WasmTypes::WasmType type;
  600. sig->AllocateParams(paramCount, m_module->GetRecycler());
  601. for (UINT32 j = 0; j < paramCount; j++)
  602. {
  603. type = ReadWasmType(len);
  604. sig->SetParam(type, j);
  605. }
  606. UINT32 resultCount = LEB128(len);
  607. if (resultCount != 0 && resultCount != 1)
  608. {
  609. ThrowDecodingError(_u("Unexpected result count %u"), resultCount);
  610. }
  611. if (resultCount == 1)
  612. {
  613. type = ReadWasmType(len);
  614. sig->SetResultType(type);
  615. }
  616. sig->FinalizeSignature();
  617. }
  618. }
  619. void
  620. WasmBinaryReader::ReadFunctionsSignatures()
  621. {
  622. UINT len = 0;
  623. uint32 nFunctions = LEB128(len);
  624. for (uint32 iFunc = 0; iFunc < nFunctions; iFunc++)
  625. {
  626. uint32 sigIndex = LEB128(len);
  627. if (sigIndex >= m_module->GetSignatureCount())
  628. {
  629. ThrowDecodingError(_u("Function signature is out of bound"));
  630. }
  631. WasmSignature* sig = m_module->GetSignature(sigIndex);
  632. m_module->AddWasmFunctionInfo(sig);
  633. }
  634. }
  635. void WasmBinaryReader::ReadExportTable()
  636. {
  637. uint32 length;
  638. uint32 entries = LEB128(length);
  639. m_module->AllocateFunctionExports(entries);
  640. ArenaAllocator tmpAlloc(_u("ExportDupCheck"), m_module->GetScriptContext()->GetThreadContext()->GetPageAllocator(), Js::Throw::OutOfMemory);
  641. typedef SList<const char16*> NameList;
  642. JsUtil::BaseDictionary<uint32, NameList*, ArenaAllocator> exportsNameDict(&tmpAlloc);
  643. for (uint32 iExport = 0; iExport < entries; iExport++)
  644. {
  645. uint32 nameLength;
  646. const char16* exportName = ReadInlineName(length, nameLength);
  647. // Check if the name is already used
  648. NameList* list;
  649. if (exportsNameDict.TryGetValue(nameLength, &list))
  650. {
  651. const char16** found = list->Find([exportName, nameLength](const char16* existing) {
  652. return wcsncmp(exportName, existing, nameLength) == 0;
  653. });
  654. if (found)
  655. {
  656. ThrowDecodingError(_u("Duplicate export name: %s"), exportName);
  657. }
  658. }
  659. else
  660. {
  661. list = Anew(&tmpAlloc, NameList, &tmpAlloc);
  662. exportsNameDict.Add(nameLength, list);
  663. }
  664. list->Push(exportName);
  665. ExternalKinds::ExternalKind kind = (ExternalKinds::ExternalKind)ReadConst<int8>();
  666. uint32 index = LEB128(length);
  667. switch (kind)
  668. {
  669. case ExternalKinds::Function:
  670. {
  671. FunctionIndexTypes::Type type = m_module->GetFunctionIndexType(index);
  672. if (!FunctionIndexTypes::CanBeExported(type))
  673. {
  674. ThrowDecodingError(_u("Invalid Export %u => func[%u]"), iExport, index);
  675. }
  676. m_module->SetExport(iExport, index, exportName, nameLength, kind);
  677. #if DBG_DUMP
  678. if (type == FunctionIndexTypes::ImportThunk)
  679. {
  680. WasmImport* import = m_module->GetWasmFunctionInfo(index)->importedFunctionReference;
  681. TRACE_WASM_DECODER(_u("Export #%u: Import(%s.%s)(%u) => %s"), iExport, import->modName, import->importName, index, exportName);
  682. }
  683. else
  684. {
  685. TRACE_WASM_DECODER(_u("Export #%u: Function(%u) => %s"), iExport, index, exportName);
  686. }
  687. #endif
  688. break;
  689. }
  690. case ExternalKinds::Memory:
  691. if (index != 0)
  692. {
  693. ThrowDecodingError(_u("Unknown memory index %u for export %s"), index, exportName);
  694. }
  695. m_module->SetExport(iExport, index, exportName, nameLength, kind);
  696. break;
  697. case ExternalKinds::Table:
  698. if (index != 0)
  699. {
  700. ThrowDecodingError(_u("Unknown table index %u for export %s"), index, exportName);
  701. }
  702. m_module->SetExport(iExport, index, exportName, nameLength, kind);
  703. break;
  704. case ExternalKinds::Global:
  705. if (index >= m_module->GetGlobalCount())
  706. {
  707. ThrowDecodingError(_u("Unknown global %u for export %s"), index, exportName);
  708. }
  709. if (m_module->GetGlobal(index)->IsMutable())
  710. {
  711. ThrowDecodingError(_u("Mutable globals cannot be exported"), index, exportName);
  712. }
  713. m_module->SetExport(iExport, index, exportName, nameLength, kind);
  714. break;
  715. default:
  716. ThrowDecodingError(_u("Exported Kind %d, NYI"), kind);
  717. break;
  718. }
  719. }
  720. }
  721. void WasmBinaryReader::ReadTableSection(bool isImportSection)
  722. {
  723. uint32 length;
  724. uint32 entries;
  725. if (isImportSection)
  726. {
  727. entries = 1;
  728. }
  729. else
  730. {
  731. entries = LEB128(length);
  732. }
  733. if (entries > 1)
  734. {
  735. ThrowDecodingError(_u("Maximum of one table allowed"));
  736. }
  737. if (entries == 1)
  738. {
  739. int8 elementType = ReadConst<int8>();
  740. if (elementType != LanguageTypes::anyfunc)
  741. {
  742. ThrowDecodingError(_u("Only anyfunc type is supported. Unknown type %d"), elementType);
  743. }
  744. uint32 flags = LEB128(length);
  745. uint32 initialLength = LEB128(length);
  746. uint32 maximumLength = UINT32_MAX;
  747. if (flags & 0x1)
  748. {
  749. maximumLength = LEB128(length);
  750. }
  751. m_module->InitializeTable(initialLength, maximumLength);
  752. TRACE_WASM_DECODER(_u("Indirect table: %u to %u entries"), initialLength, maximumLength);
  753. }
  754. }
  755. void
  756. WasmBinaryReader::ReadElementSection()
  757. {
  758. uint32 length = 0;
  759. uint32 count = LEB128(length);
  760. if (count != 0)
  761. {
  762. m_module->AllocateElementSegs(count);
  763. }
  764. TRACE_WASM_DECODER(_u("Indirect table element: %u entries"), count);
  765. for (uint32 i = 0; i < count; ++i)
  766. {
  767. uint32 index = LEB128(length); // Table id
  768. if (index != 0 || !(m_module->HasTable() || m_module->HasTableImport()))
  769. {
  770. ThrowDecodingError(_u("Unknown table index %d"), index); //MVP limitation
  771. }
  772. WasmNode initExpr = ReadInitExpr(true);
  773. uint32 numElem = LEB128(length);
  774. WasmElementSegment *eSeg = Anew(m_alloc, WasmElementSegment, m_alloc, index, initExpr, numElem);
  775. for (uint32 iElem = 0; iElem < numElem; ++iElem)
  776. {
  777. uint32 elem = LEB128(length);
  778. FunctionIndexTypes::Type funcType = m_module->GetFunctionIndexType(elem);
  779. if (!FunctionIndexTypes::CanBeExported(funcType))
  780. {
  781. ThrowDecodingError(_u("Invalid function to insert in the table %u"), elem);
  782. }
  783. eSeg->AddElement(elem, *m_module);
  784. }
  785. m_module->SetElementSeg(eSeg, i);
  786. }
  787. }
  788. void
  789. WasmBinaryReader::ReadDataSegments()
  790. {
  791. UINT len = 0;
  792. const uint32 entries = LEB128(len);
  793. if (entries > 0)
  794. {
  795. m_module->AllocateDataSegs(entries);
  796. }
  797. for (uint32 i = 0; i < entries; ++i)
  798. {
  799. UINT32 index = LEB128(len);
  800. if (index != 0 || !(m_module->HasMemory() || m_module->HasMemoryImport()))
  801. {
  802. ThrowDecodingError(_u("Unknown memory index %u"), index);
  803. }
  804. TRACE_WASM_DECODER(_u("Data Segment #%u"), i);
  805. WasmNode initExpr = ReadInitExpr(true);
  806. //UINT32 offset = initExpr.cnst.i32;
  807. UINT32 dataByteLen = LEB128(len);
  808. WasmDataSegment *dseg = Anew(m_alloc, WasmDataSegment, m_alloc, initExpr, dataByteLen, m_pc);
  809. CheckBytesLeft(dataByteLen);
  810. m_pc += dataByteLen;
  811. m_module->SetDataSeg(dseg, i);
  812. }
  813. }
  814. void
  815. WasmBinaryReader::ReadNamesSection()
  816. {
  817. UINT len = 0;
  818. UINT numEntries = LEB128(len);
  819. for (UINT i = 0; i < numEntries; ++i)
  820. {
  821. UINT fnNameLen = 0;
  822. WasmFunctionInfo* funsig = m_module->GetWasmFunctionInfo(i);
  823. const char16* name = ReadInlineName(len, fnNameLen);
  824. funsig->SetName(name, fnNameLen);
  825. UINT numLocals = LEB128(len);
  826. if (numLocals != funsig->GetLocalCount())
  827. {
  828. ThrowDecodingError(_u("num locals mismatch in names section"));
  829. }
  830. for (UINT j = 0; j < numLocals; ++j)
  831. {
  832. UINT localNameLen = 0;
  833. ReadInlineName(len, localNameLen);
  834. }
  835. }
  836. }
  837. void
  838. WasmBinaryReader::ReadGlobalsSection()
  839. {
  840. UINT len = 0;
  841. UINT numEntries = LEB128(len);
  842. for (UINT i = 0; i < numEntries; ++i)
  843. {
  844. WasmTypes::WasmType type = ReadWasmType(len);
  845. bool isMutable = ReadMutableValue();
  846. WasmNode globalNode = ReadInitExpr();
  847. GlobalReferenceTypes::Type refType = GlobalReferenceTypes::Const;
  848. WasmTypes::WasmType initType;
  849. switch (globalNode.op) {
  850. case wbI32Const: initType = WasmTypes::I32; break;
  851. case wbF32Const: initType = WasmTypes::F32; break;
  852. case wbF64Const: initType = WasmTypes::F64; break;
  853. case wbI64Const: initType = WasmTypes::I64; break;
  854. case wbGetGlobal:
  855. initType = m_module->GetGlobal(globalNode.var.num)->GetType();
  856. refType = GlobalReferenceTypes::LocalReference;
  857. break;
  858. default:
  859. Assert(UNREACHED);
  860. ThrowDecodingError(_u("Unknown global init_expr"));
  861. }
  862. if (type != initType)
  863. {
  864. ThrowDecodingError(_u("Type mismatch for global initialization"));
  865. }
  866. m_module->AddGlobal(refType, type, isMutable, globalNode);
  867. }
  868. }
  869. void
  870. WasmBinaryReader::ReadCustomSection()
  871. {
  872. CustomSection customSection;
  873. customSection.name = m_currentSection.name;
  874. customSection.nameLength = m_currentSection.nameLength;
  875. customSection.payload = m_pc;
  876. size_t size = m_currentSection.end - m_pc;
  877. if (m_currentSection.end < m_pc || !Math::FitsInDWord(size))
  878. {
  879. ThrowDecodingError(_u("Invalid custom section size"));
  880. }
  881. customSection.payloadSize = (uint32)size;
  882. m_module->AddCustomSection(customSection);
  883. m_pc = m_currentSection.end;
  884. }
  885. const char16*
  886. WasmBinaryReader::ReadInlineName(uint32& length, uint32& nameLength)
  887. {
  888. nameLength = LEB128(length);
  889. CheckBytesLeft(nameLength);
  890. LPCUTF8 rawName = m_pc;
  891. m_pc += nameLength;
  892. length += nameLength;
  893. return CvtUtf8Str(rawName, nameLength, &nameLength);
  894. }
  895. const char16*
  896. WasmBinaryReader::CvtUtf8Str(LPCUTF8 name, uint32 nameLen, charcount_t* dstLength)
  897. {
  898. utf8::DecodeOptions decodeOptions = utf8::doDefault;
  899. charcount_t utf16Len = utf8::ByteIndexIntoCharacterIndex(name, nameLen, decodeOptions);
  900. char16* contents = AnewArray(m_alloc, char16, utf16Len + 1);
  901. if (contents == nullptr)
  902. {
  903. Js::Throw::OutOfMemory();
  904. }
  905. utf8::DecodeUnitsIntoAndNullTerminate(contents, name, name + nameLen, decodeOptions);
  906. if (dstLength)
  907. {
  908. *dstLength = utf16Len;
  909. }
  910. return contents;
  911. }
  912. void
  913. WasmBinaryReader::ReadImportEntries()
  914. {
  915. uint32 len = 0;
  916. uint32 entries = LEB128(len);
  917. for (uint32 i = 0; i < entries; ++i)
  918. {
  919. uint32 modNameLen = 0, fnNameLen = 0;
  920. const char16* modName = ReadInlineName(len, modNameLen);
  921. const char16* fnName = ReadInlineName(len, fnNameLen);
  922. ExternalKinds::ExternalKind kind = (ExternalKinds::ExternalKind)ReadConst<int8>();
  923. TRACE_WASM_DECODER(_u("Import #%u: \"%s\".\"%s\", kind: %d"), i, modName, fnName, kind);
  924. switch (kind)
  925. {
  926. case ExternalKinds::Function:
  927. {
  928. uint32 sigId = LEB128(len);
  929. m_module->AddFunctionImport(sigId, modName, modNameLen, fnName, fnNameLen);
  930. break;
  931. }
  932. case ExternalKinds::Global:
  933. {
  934. WasmTypes::WasmType type = ReadWasmType(len);
  935. bool isMutable = ReadMutableValue();
  936. if (isMutable)
  937. {
  938. ThrowDecodingError(_u("Mutable globals cannot be imported"));
  939. }
  940. m_module->AddGlobal(GlobalReferenceTypes::ImportedReference, type, isMutable, {});
  941. m_module->AddGlobalImport(modName, modNameLen, fnName, fnNameLen);
  942. break;
  943. }
  944. case ExternalKinds::Table:
  945. ReadTableSection(true);
  946. m_module->AddTableImport(modName, modNameLen, fnName, fnNameLen);
  947. break;
  948. case ExternalKinds::Memory:
  949. ReadMemorySection(true);
  950. m_module->AddMemoryImport(modName, modNameLen, fnName, fnNameLen);
  951. break;
  952. default:
  953. ThrowDecodingError(_u("Imported Kind %d, NYI"), kind);
  954. break;
  955. }
  956. }
  957. }
  958. void
  959. WasmBinaryReader::ReadStartFunction()
  960. {
  961. uint32 len = 0;
  962. uint32 id = LEB128(len);
  963. Wasm::FunctionIndexTypes::Type funcType = m_module->GetFunctionIndexType(id);
  964. if (!FunctionIndexTypes::CanBeExported(funcType))
  965. {
  966. ThrowDecodingError(_u("Invalid function index for start function %u"), id);
  967. }
  968. WasmSignature* sig = m_module->GetWasmFunctionInfo(id)->GetSignature();
  969. if (sig->GetParamCount() > 0 || sig->GetResultType() != WasmTypes::Void)
  970. {
  971. ThrowDecodingError(_u("Start function must be void and nullary"));
  972. }
  973. m_module->SetStartFunction(id);
  974. }
  975. template<typename MaxAllowedType>
  976. MaxAllowedType
  977. WasmBinaryReader::LEB128(UINT &length, bool sgn)
  978. {
  979. MaxAllowedType result = 0;
  980. uint shamt = 0;
  981. byte b = 0;
  982. length = 1;
  983. uint maxReads = sizeof(MaxAllowedType) == 4 ? 5 : 10;
  984. CompileAssert(sizeof(MaxAllowedType) == 4 || sizeof(MaxAllowedType) == 8);
  985. for (uint i = 0; i < maxReads; i++, length++)
  986. {
  987. CheckBytesLeft(1);
  988. b = *m_pc++;
  989. result = result | ((MaxAllowedType)(b & 0x7f) << shamt);
  990. if (sgn)
  991. {
  992. shamt += 7;
  993. if ((b & 0x80) == 0)
  994. break;
  995. }
  996. else
  997. {
  998. if ((b & 0x80) == 0)
  999. break;
  1000. shamt += 7;
  1001. }
  1002. }
  1003. if (b & 0x80 || m_pc > m_end)
  1004. {
  1005. ThrowDecodingError(_u("Invalid LEB128 format"));
  1006. }
  1007. if (sgn && (shamt < sizeof(MaxAllowedType) * 8) && (0x40 & b))
  1008. {
  1009. if (sizeof(MaxAllowedType) == 4)
  1010. {
  1011. result |= -(1 << shamt);
  1012. }
  1013. else if (sizeof(MaxAllowedType) == 8)
  1014. {
  1015. result |= -((int64)1 << shamt);
  1016. }
  1017. }
  1018. if (!sgn)
  1019. {
  1020. if (sizeof(MaxAllowedType) == 4)
  1021. {
  1022. TRACE_WASM_LEB128(_u("Binary decoder: LEB128 length = %u, value = %u (0x%x)"), length, result, result);
  1023. }
  1024. else if (sizeof(MaxAllowedType) == 8)
  1025. {
  1026. TRACE_WASM_LEB128(_u("Binary decoder: LEB128 length = %u, value = %llu (0x%llx)"), length, result, result);
  1027. }
  1028. }
  1029. return result;
  1030. }
  1031. // Signed LEB128
  1032. template<>
  1033. INT
  1034. WasmBinaryReader::SLEB128(UINT &length)
  1035. {
  1036. INT result = LEB128<UINT>(length, true);
  1037. TRACE_WASM_LEB128(_u("Binary decoder: SLEB128 length = %u, value = %d (0x%x)"), length, result, result);
  1038. return result;
  1039. }
  1040. template<>
  1041. INT64
  1042. WasmBinaryReader::SLEB128(UINT &length)
  1043. {
  1044. INT64 result = LEB128<UINT64>(length, true);
  1045. TRACE_WASM_LEB128(_u("Binary decoder: SLEB128 length = %u, value = %lld (0x%llx)"), length, result, result);
  1046. return result;
  1047. }
  1048. WasmNode
  1049. WasmBinaryReader::ReadInitExpr(bool isOffset)
  1050. {
  1051. if (m_readerState != READER_STATE_MODULE)
  1052. {
  1053. ThrowDecodingError(_u("Wasm reader in an invalid state to read init_expr"));
  1054. }
  1055. m_funcState.count = 0;
  1056. m_funcState.size = m_currentSection.end - m_pc;
  1057. ReadExpr();
  1058. WasmNode node = m_currentNode;
  1059. switch (node.op)
  1060. {
  1061. case wbI32Const:
  1062. case wbF32Const:
  1063. case wbI64Const:
  1064. case wbF64Const:
  1065. break;
  1066. case wbGetGlobal:
  1067. {
  1068. uint32 globalIndex = node.var.num;
  1069. WasmGlobal* global = m_module->GetGlobal(globalIndex);
  1070. if (global->GetReferenceType() != GlobalReferenceTypes::ImportedReference)
  1071. {
  1072. ThrowDecodingError(_u("initializer expression can only use imported globals"));
  1073. }
  1074. if (global->IsMutable())
  1075. {
  1076. ThrowDecodingError(_u("initializer expression cannot reference a mutable global"));
  1077. }
  1078. break;
  1079. }
  1080. default:
  1081. ThrowDecodingError(_u("Invalid initexpr opcode"));
  1082. }
  1083. if (ReadExpr() != wbEnd)
  1084. {
  1085. ThrowDecodingError(_u("Missing end opcode after init expr"));
  1086. }
  1087. if (isOffset)
  1088. {
  1089. m_module->ValidateInitExportForOffset(node);
  1090. }
  1091. return node;
  1092. }
  1093. template <typename T>
  1094. T WasmBinaryReader::ReadConst()
  1095. {
  1096. CheckBytesLeft(sizeof(T));
  1097. T value = *((T*)m_pc);
  1098. m_pc += sizeof(T);
  1099. return value;
  1100. }
  1101. uint8
  1102. WasmBinaryReader::ReadVarUInt7()
  1103. {
  1104. return ReadConst<uint8>() & 0x7F;
  1105. }
  1106. bool WasmBinaryReader::ReadMutableValue()
  1107. {
  1108. uint8 mutableValue = ReadConst<UINT8>();
  1109. switch (mutableValue)
  1110. {
  1111. case 0: return false;
  1112. case 1: return true;
  1113. default:
  1114. ThrowDecodingError(_u("invalid mutability"));
  1115. }
  1116. }
  1117. WasmTypes::WasmType
  1118. WasmBinaryReader::ReadWasmType(uint32& length)
  1119. {
  1120. length = 1;
  1121. return LanguageTypes::ToWasmType(ReadConst<int8>());
  1122. }
  1123. void
  1124. WasmBinaryReader::CheckBytesLeft(UINT bytesNeeded)
  1125. {
  1126. UINT bytesLeft = (UINT)(m_end - m_pc);
  1127. if (bytesNeeded > bytesLeft)
  1128. {
  1129. ThrowDecodingError(_u("Out of file: Needed: %d, Left: %d"), bytesNeeded, bytesLeft);
  1130. }
  1131. }
  1132. } // namespace Wasm
  1133. #undef TRACE_WASM_DECODER
  1134. #endif // ENABLE_WASM