Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(323)

Side by Side Diff: src/wasm/encoder.cc

Issue 1900153002: [wasm] Enforce strict ordering of WASM module sections. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/wasm/module-decoder.cc » ('j') | src/wasm/module-decoder.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/signature.h" 5 #include "src/signature.h"
6 6
7 #include "src/handles.h" 7 #include "src/handles.h"
8 #include "src/v8.h" 8 #include "src/v8.h"
9 #include "src/zone-containers.h" 9 #include "src/zone-containers.h"
10 10
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 47
48 void EmitUint32(byte** b, uint32_t x) { 48 void EmitUint32(byte** b, uint32_t x) {
49 WriteUnalignedUInt32(*b, x); 49 WriteUnalignedUInt32(*b, x);
50 *b += 4; 50 *b += 4;
51 } 51 }
52 52
53 // Sections all start with a size, but it's unknown at the start. 53 // Sections all start with a size, but it's unknown at the start.
54 // We generate a large varint which we then fixup later when the size is known. 54 // We generate a large varint which we then fixup later when the size is known.
55 // 55 //
56 // TODO(jfb) Not strictly necessary since sizes are calculated ahead of time. 56 // TODO(jfb) Not strictly necessary since sizes are calculated ahead of time.
57 const size_t padded_varint = 5; 57 const size_t kPaddedVarintSize = 5;
58 58
59 void EmitVarInt(byte** b, size_t val) { 59 void EmitVarInt(byte** b, size_t val) {
60 while (true) { 60 while (true) {
61 size_t next = val >> 7; 61 size_t next = val >> 7;
62 byte out = static_cast<byte>(val & 0x7f); 62 byte out = static_cast<byte>(val & 0x7f);
63 if (next) { 63 if (next) {
64 *((*b)++) = 0x80 | out; 64 *((*b)++) = 0x80 | out;
65 val = next; 65 val = next;
66 } else { 66 } else {
67 *((*b)++) = out; 67 *((*b)++) = out;
68 break; 68 break;
69 } 69 }
70 } 70 }
71 } 71 }
72 72
73 size_t SizeOfVarInt(size_t value) { 73 size_t SizeOfVarInt(size_t value) {
74 size_t size = 0; 74 size_t size = 0;
75 do { 75 do {
76 size++; 76 size++;
77 value = value >> 7; 77 value = value >> 7;
78 } while (value > 0); 78 } while (value > 0);
79 return size; 79 return size;
80 } 80 }
81 81
82 void FixupSection(byte* start, byte* end) { 82 void FixupSection(byte* start, byte* end) {
83 // Same as EmitVarInt, but fixed-width with zeroes in the MSBs. 83 // Same as EmitVarInt, but fixed-width with zeroes in the MSBs.
84 size_t val = end - start - padded_varint; 84 size_t val = end - start - kPaddedVarintSize;
85 TRACE(" fixup %u\n", (unsigned)val); 85 TRACE(" fixup %u\n", (unsigned)val);
86 for (size_t pos = 0; pos != padded_varint; ++pos) { 86 for (size_t pos = 0; pos != kPaddedVarintSize; ++pos) {
87 size_t next = val >> 7; 87 size_t next = val >> 7;
88 byte out = static_cast<byte>(val & 0x7f); 88 byte out = static_cast<byte>(val & 0x7f);
89 if (pos != padded_varint - 1) { 89 if (pos != kPaddedVarintSize - 1) {
90 *(start++) = 0x80 | out; 90 *(start++) = 0x80 | out;
91 val = next; 91 val = next;
92 } else { 92 } else {
93 *(start++) = out; 93 *(start++) = out;
94 // TODO(jfb) check that the pre-allocated fixup size isn't overflowed. 94 // TODO(jfb) check that the pre-allocated fixup size isn't overflowed.
95 } 95 }
96 } 96 }
97 } 97 }
98 98
99 // Returns the start of the section, where the section VarInt size is. 99 // Returns the start of the section, where the section VarInt size is.
100 byte* EmitSection(WasmSection::Code code, byte** b) { 100 byte* EmitSection(WasmSection::Code code, byte** b) {
101 // Emit a placeholder for the length.
101 byte* start = *b; 102 byte* start = *b;
102 const char* name = WasmSection::getName(code); 103 for (size_t padding = 0; padding != kPaddedVarintSize; ++padding) {
103 size_t length = WasmSection::getNameLength(code);
104 TRACE("emit section: %s\n", name);
105 for (size_t padding = 0; padding != padded_varint; ++padding) {
106 EmitUint8(b, 0xff); // Will get fixed up later. 104 EmitUint8(b, 0xff); // Will get fixed up later.
107 } 105 }
106 // Emit the section name.
107 const char* name = WasmSection::getName(code);
108 TRACE("emit section: %s\n", name);
109 size_t length = WasmSection::getNameLength(code);
108 EmitVarInt(b, length); // Section name string size. 110 EmitVarInt(b, length); // Section name string size.
109 for (size_t i = 0; i != length; ++i) EmitUint8(b, name[i]); 111 for (size_t i = 0; i != length; ++i) EmitUint8(b, name[i]);
112
110 return start; 113 return start;
111 } 114 }
112 } // namespace 115 } // namespace
113 116
114 struct WasmFunctionBuilder::Type { 117 struct WasmFunctionBuilder::Type {
115 bool param_; 118 bool param_;
116 LocalType type_; 119 LocalType type_;
117 }; 120 };
118 121
119 122
(...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after
544 size_t body_size; 547 size_t body_size;
545 548
546 size_t total() { return header_size + body_size; } 549 size_t total() { return header_size + body_size; }
547 550
548 void Add(size_t header, size_t body) { 551 void Add(size_t header, size_t body) {
549 header_size += header; 552 header_size += header;
550 body_size += body; 553 body_size += body;
551 } 554 }
552 555
553 void AddSection(WasmSection::Code code, size_t other_size) { 556 void AddSection(WasmSection::Code code, size_t other_size) {
554 Add(padded_varint + SizeOfVarInt(WasmSection::getNameLength(code)) + 557 Add(kPaddedVarintSize + SizeOfVarInt(WasmSection::getNameLength(code)) +
555 WasmSection::getNameLength(code), 558 WasmSection::getNameLength(code),
556 0); 559 0);
557 if (other_size) Add(SizeOfVarInt(other_size), 0); 560 if (other_size) Add(SizeOfVarInt(other_size), 0);
558 } 561 }
559 }; 562 };
560 563
561 WasmModuleIndex* WasmModuleWriter::WriteTo(Zone* zone) const { 564 WasmModuleIndex* WasmModuleWriter::WriteTo(Zone* zone) const {
562 Sizes sizes = {0, 0}; 565 Sizes sizes = {0, 0};
563 566
564 sizes.Add(2 * sizeof(uint32_t), 0); // header 567 sizes.Add(2 * sizeof(uint32_t), 0); // header
565 568
566 sizes.AddSection(WasmSection::Code::Memory, 0);
567 sizes.Add(kDeclMemorySize, 0);
568 TRACE("Size after memory: %u, %u\n", (unsigned)sizes.header_size,
569 (unsigned)sizes.body_size);
570
571 if (globals_.size() > 0) { 569 if (globals_.size() > 0) {
572 sizes.AddSection(WasmSection::Code::Globals, globals_.size()); 570 sizes.AddSection(WasmSection::Code::Globals, globals_.size());
573 /* These globals never have names, so are always 3 bytes. */ 571 /* These globals never have names, so are always 3 bytes. */
574 sizes.Add(3 * globals_.size(), 0); 572 sizes.Add(3 * globals_.size(), 0);
575 TRACE("Size after globals: %u, %u\n", (unsigned)sizes.header_size, 573 TRACE("Size after globals: %u, %u\n", (unsigned)sizes.header_size,
576 (unsigned)sizes.body_size); 574 (unsigned)sizes.body_size);
577 } 575 }
578 576
579 if (signatures_.size() > 0) { 577 if (signatures_.size() > 0) {
580 sizes.AddSection(WasmSection::Code::Signatures, signatures_.size()); 578 sizes.AddSection(WasmSection::Code::Signatures, signatures_.size());
581 for (auto sig : signatures_) { 579 for (auto sig : signatures_) {
582 sizes.Add( 580 sizes.Add(
583 1 + SizeOfVarInt(sig->parameter_count()) + sig->parameter_count(), 0); 581 1 + SizeOfVarInt(sig->parameter_count()) + sig->parameter_count(), 0);
584 } 582 }
585 TRACE("Size after signatures: %u, %u\n", (unsigned)sizes.header_size, 583 TRACE("Size after signatures: %u, %u\n", (unsigned)sizes.header_size,
586 (unsigned)sizes.body_size); 584 (unsigned)sizes.body_size);
587 } 585 }
588 586
589 if (functions_.size() > 0) { 587 if (functions_.size() > 0) {
590 sizes.AddSection(WasmSection::Code::Functions, functions_.size()); 588 sizes.AddSection(WasmSection::Code::Functions, functions_.size());
591 for (auto function : functions_) { 589 for (auto function : functions_) {
592 sizes.Add(function->HeaderSize() + function->BodySize(), 590 sizes.Add(function->HeaderSize() + function->BodySize(),
593 function->NameSize()); 591 function->NameSize());
594 } 592 }
595 TRACE("Size after functions: %u, %u\n", (unsigned)sizes.header_size, 593 TRACE("Size after functions: %u, %u\n", (unsigned)sizes.header_size,
596 (unsigned)sizes.body_size); 594 (unsigned)sizes.body_size);
597 } 595 }
598 596
597 if (indirect_functions_.size() > 0) {
598 sizes.AddSection(WasmSection::Code::FunctionTable,
599 indirect_functions_.size());
600 for (auto function_index : indirect_functions_) {
601 sizes.Add(SizeOfVarInt(function_index), 0);
602 }
603 TRACE("Size after indirect functions: %u, %u\n",
604 (unsigned)sizes.header_size, (unsigned)sizes.body_size);
605 }
606
607 sizes.AddSection(WasmSection::Code::Memory, 0);
608 sizes.Add(kDeclMemorySize, 0);
609 TRACE("Size after memory: %u, %u\n", (unsigned)sizes.header_size,
610 (unsigned)sizes.body_size);
611
599 if (start_function_index_ >= 0) { 612 if (start_function_index_ >= 0) {
600 sizes.AddSection(WasmSection::Code::StartFunction, 0); 613 sizes.AddSection(WasmSection::Code::StartFunction, 0);
601 sizes.Add(SizeOfVarInt(start_function_index_), 0); 614 sizes.Add(SizeOfVarInt(start_function_index_), 0);
602 TRACE("Size after start: %u, %u\n", (unsigned)sizes.header_size, 615 TRACE("Size after start: %u, %u\n", (unsigned)sizes.header_size,
603 (unsigned)sizes.body_size); 616 (unsigned)sizes.body_size);
604 } 617 }
605 618
606 if (data_segments_.size() > 0) { 619 if (data_segments_.size() > 0) {
607 sizes.AddSection(WasmSection::Code::DataSegments, data_segments_.size()); 620 sizes.AddSection(WasmSection::Code::DataSegments, data_segments_.size());
608 for (auto segment : data_segments_) { 621 for (auto segment : data_segments_) {
609 sizes.Add(segment->HeaderSize(), segment->BodySize()); 622 sizes.Add(segment->HeaderSize(), segment->BodySize());
610 } 623 }
611 TRACE("Size after data segments: %u, %u\n", (unsigned)sizes.header_size, 624 TRACE("Size after data segments: %u, %u\n", (unsigned)sizes.header_size,
612 (unsigned)sizes.body_size); 625 (unsigned)sizes.body_size);
613 } 626 }
614 627
615 if (indirect_functions_.size() > 0) {
616 sizes.AddSection(WasmSection::Code::FunctionTable,
617 indirect_functions_.size());
618 for (auto function_index : indirect_functions_) {
619 sizes.Add(SizeOfVarInt(function_index), 0);
620 }
621 TRACE("Size after indirect functions: %u, %u\n",
622 (unsigned)sizes.header_size, (unsigned)sizes.body_size);
623 }
624
625 if (sizes.body_size > 0) { 628 if (sizes.body_size > 0) {
626 sizes.AddSection(WasmSection::Code::End, 0); 629 sizes.AddSection(WasmSection::Code::End, 0);
627 TRACE("Size after end: %u, %u\n", (unsigned)sizes.header_size, 630 TRACE("Size after end: %u, %u\n", (unsigned)sizes.header_size,
628 (unsigned)sizes.body_size); 631 (unsigned)sizes.body_size);
629 } 632 }
630 633
631 ZoneVector<uint8_t> buffer_vector(sizes.total(), zone); 634 ZoneVector<uint8_t> buffer_vector(sizes.total(), zone);
632 byte* buffer = &buffer_vector[0]; 635 byte* buffer = &buffer_vector[0];
633 byte* header = buffer; 636 byte* header = buffer;
634 byte* body = buffer + sizes.header_size; 637 byte* body = buffer + sizes.header_size;
635 638
636 // -- emit magic ------------------------------------------------------------- 639 // -- emit magic -------------------------------------------------------------
637 TRACE("emit magic\n"); 640 TRACE("emit magic\n");
638 EmitUint32(&header, kWasmMagic); 641 EmitUint32(&header, kWasmMagic);
639 EmitUint32(&header, kWasmVersion); 642 EmitUint32(&header, kWasmVersion);
640 643
641 // -- emit memory declaration ------------------------------------------------
642 {
643 byte* section = EmitSection(WasmSection::Code::Memory, &header);
644 EmitVarInt(&header, 16); // min memory size
645 EmitVarInt(&header, 16); // max memory size
646 EmitUint8(&header, 0); // memory export
647 static_assert(kDeclMemorySize == 3, "memory size must match emit above");
648 FixupSection(section, header);
649 }
650
651 // -- emit globals ----------------------------------------------------------- 644 // -- emit globals -----------------------------------------------------------
652 if (globals_.size() > 0) { 645 if (globals_.size() > 0) {
653 byte* section = EmitSection(WasmSection::Code::Globals, &header); 646 byte* section = EmitSection(WasmSection::Code::Globals, &header);
654 EmitVarInt(&header, globals_.size()); 647 EmitVarInt(&header, globals_.size());
655 648
656 for (auto global : globals_) { 649 for (auto global : globals_) {
657 EmitVarInt(&header, 0); // Length of the global name. 650 EmitVarInt(&header, 0); // Length of the global name.
658 EmitUint8(&header, WasmOpcodes::MemTypeCodeFor(global.first)); 651 EmitUint8(&header, WasmOpcodes::MemTypeCodeFor(global.first));
659 EmitUint8(&header, global.second); 652 EmitUint8(&header, global.second);
660 } 653 }
(...skipping 23 matching lines...) Expand all
684 if (functions_.size() > 0) { 677 if (functions_.size() > 0) {
685 byte* section = EmitSection(WasmSection::Code::Functions, &header); 678 byte* section = EmitSection(WasmSection::Code::Functions, &header);
686 EmitVarInt(&header, functions_.size()); 679 EmitVarInt(&header, functions_.size());
687 680
688 for (auto func : functions_) { 681 for (auto func : functions_) {
689 func->Serialize(buffer, &header, &body); 682 func->Serialize(buffer, &header, &body);
690 } 683 }
691 FixupSection(section, header); 684 FixupSection(section, header);
692 } 685 }
693 686
687 // -- emit function table ----------------------------------------------------
688 if (indirect_functions_.size() > 0) {
689 byte* section = EmitSection(WasmSection::Code::FunctionTable, &header);
690 EmitVarInt(&header, indirect_functions_.size());
691
692 for (auto index : indirect_functions_) {
693 EmitVarInt(&header, index);
694 }
695 FixupSection(section, header);
696 }
697
698 // -- emit memory declaration ------------------------------------------------
699 {
700 byte* section = EmitSection(WasmSection::Code::Memory, &header);
701 EmitVarInt(&header, 16); // min memory size
702 EmitVarInt(&header, 16); // max memory size
703 EmitUint8(&header, 0); // memory export
704 static_assert(kDeclMemorySize == 3, "memory size must match emit above");
705 FixupSection(section, header);
706 }
707
694 // -- emit start function index ---------------------------------------------- 708 // -- emit start function index ----------------------------------------------
695 if (start_function_index_ >= 0) { 709 if (start_function_index_ >= 0) {
696 byte* section = EmitSection(WasmSection::Code::StartFunction, &header); 710 byte* section = EmitSection(WasmSection::Code::StartFunction, &header);
697 EmitVarInt(&header, start_function_index_); 711 EmitVarInt(&header, start_function_index_);
698 FixupSection(section, header); 712 FixupSection(section, header);
699 } 713 }
700 714
701 // -- emit data segments ----------------------------------------------------- 715 // -- emit data segments -----------------------------------------------------
702 if (data_segments_.size() > 0) { 716 if (data_segments_.size() > 0) {
703 byte* section = EmitSection(WasmSection::Code::DataSegments, &header); 717 byte* section = EmitSection(WasmSection::Code::DataSegments, &header);
704 EmitVarInt(&header, data_segments_.size()); 718 EmitVarInt(&header, data_segments_.size());
705 719
706 for (auto segment : data_segments_) { 720 for (auto segment : data_segments_) {
707 segment->Serialize(buffer, &header, &body); 721 segment->Serialize(buffer, &header, &body);
708 } 722 }
709 FixupSection(section, header); 723 FixupSection(section, header);
710 } 724 }
711 725
712 // -- emit function table ----------------------------------------------------
713 if (indirect_functions_.size() > 0) {
714 byte* section = EmitSection(WasmSection::Code::FunctionTable, &header);
715 EmitVarInt(&header, indirect_functions_.size());
716
717 for (auto index : indirect_functions_) {
718 EmitVarInt(&header, index);
719 }
720 FixupSection(section, header);
721 }
722
723 if (sizes.body_size > 0) { 726 if (sizes.body_size > 0) {
724 byte* section = EmitSection(WasmSection::Code::End, &header); 727 byte* section = EmitSection(WasmSection::Code::End, &header);
725 FixupSection(section, header); 728 FixupSection(section, header);
726 } 729 }
727 730
728 return new (zone) WasmModuleIndex(buffer, buffer + sizes.total()); 731 return new (zone) WasmModuleIndex(buffer, buffer + sizes.total());
729 } 732 }
730 733
731 734
732 std::vector<uint8_t> UnsignedLEB128From(uint32_t result) { 735 std::vector<uint8_t> UnsignedLEB128From(uint32_t result) {
733 std::vector<uint8_t> output; 736 std::vector<uint8_t> output;
734 uint8_t next = 0; 737 uint8_t next = 0;
735 int shift = 0; 738 int shift = 0;
736 do { 739 do {
737 next = static_cast<uint8_t>(result >> shift); 740 next = static_cast<uint8_t>(result >> shift);
738 if (((result >> shift) & 0xFFFFFF80) != 0) { 741 if (((result >> shift) & 0xFFFFFF80) != 0) {
739 next = next | 0x80; 742 next = next | 0x80;
740 } 743 }
741 output.push_back(next); 744 output.push_back(next);
742 shift += 7; 745 shift += 7;
743 } while ((next & 0x80) != 0); 746 } while ((next & 0x80) != 0);
744 return output; 747 return output;
745 } 748 }
746 } // namespace wasm 749 } // namespace wasm
747 } // namespace internal 750 } // namespace internal
748 } // namespace v8 751 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/wasm/module-decoder.cc » ('j') | src/wasm/module-decoder.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698