llvm.org GIT mirror llvm / e2f3e50
[WebAssembly] Check if the section order is correct Summary: This patch checks if the section order is correct when reading a wasm object file in `WasmObjectFile` and converting YAML to wasm object in yaml2wasm. (It is not possible to check when reading YAML because it is handled exclusively by the YAML reader.) This checks the ordering of all known sections (core sections + known custom sections). This also adds section ID DataCount section that will be scheduled to be added in near future. Reviewers: sbc100 Subscribers: dschuff, mgorny, jgravelle-google, sunfish, llvm-commits Differential Revision: https://reviews.llvm.org/D54924 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@349221 91177308-0d34-0410-b5e6-96231b3b80d8 Heejin Ahn 8 months ago
7 changed file(s) with 169 addition(s) and 16 deletion(s). Raw diff Collapse all Expand all
187187 };
188188
189189 enum : unsigned {
190 WASM_SEC_CUSTOM = 0, // Custom / User-defined section
191 WASM_SEC_TYPE = 1, // Function signature declarations
192 WASM_SEC_IMPORT = 2, // Import declarations
193 WASM_SEC_FUNCTION = 3, // Function declarations
194 WASM_SEC_TABLE = 4, // Indirect function table and other tables
195 WASM_SEC_MEMORY = 5, // Memory attributes
196 WASM_SEC_GLOBAL = 6, // Global declarations
197 WASM_SEC_EXPORT = 7, // Exports
198 WASM_SEC_START = 8, // Start function declaration
199 WASM_SEC_ELEM = 9, // Elements section
200 WASM_SEC_CODE = 10, // Function bodies (code)
201 WASM_SEC_DATA = 11, // Data segments
202 WASM_SEC_EVENT = 13 // Event declarations
190 WASM_SEC_CUSTOM = 0, // Custom / User-defined section
191 WASM_SEC_TYPE = 1, // Function signature declarations
192 WASM_SEC_IMPORT = 2, // Import declarations
193 WASM_SEC_FUNCTION = 3, // Function declarations
194 WASM_SEC_TABLE = 4, // Indirect function table and other tables
195 WASM_SEC_MEMORY = 5, // Memory attributes
196 WASM_SEC_GLOBAL = 6, // Global declarations
197 WASM_SEC_EXPORT = 7, // Exports
198 WASM_SEC_START = 8, // Start function declaration
199 WASM_SEC_ELEM = 9, // Elements section
200 WASM_SEC_CODE = 10, // Function bodies (code)
201 WASM_SEC_DATA = 11, // Data segments
202 WASM_SEC_DATACOUNT = 12, // Data segment count
203 WASM_SEC_EVENT = 13 // Event declarations
203204 };
204205
205206 // Type immediate encodings used in various contexts.
282282 uint32_t EventSection = 0;
283283 };
284284
285 class WasmSectionOrderChecker {
286 public:
287 // We define orders for all core wasm sections and known custom sections.
288 enum : int {
289 // Core sections
290 // The order of standard sections is precisely given by the spec.
291 WASM_SEC_ORDER_TYPE = 1,
292 WASM_SEC_ORDER_IMPORT = 2,
293 WASM_SEC_ORDER_FUNCTION = 3,
294 WASM_SEC_ORDER_TABLE = 4,
295 WASM_SEC_ORDER_MEMORY = 5,
296 WASM_SEC_ORDER_GLOBAL = 6,
297 WASM_SEC_ORDER_EVENT = 7,
298 WASM_SEC_ORDER_EXPORT = 8,
299 WASM_SEC_ORDER_START = 9,
300 WASM_SEC_ORDER_ELEM = 10,
301 WASM_SEC_ORDER_DATACOUNT = 11,
302 WASM_SEC_ORDER_CODE = 12,
303 WASM_SEC_ORDER_DATA = 13,
304
305 // Custom sections
306 // "dylink" should be the very first section in the module
307 WASM_SEC_ORDER_DYLINK = 0,
308 // "linking" section requires DATA section in order to validate data symbols
309 WASM_SEC_ORDER_LINKING = 100,
310 // Must come after "linking" section in order to validate reloc indexes.
311 WASM_SEC_ORDER_RELOC = 101,
312 // "name" section must appear after DATA. Comes after "linking" to allow
313 // symbol table to set default function name.
314 WASM_SEC_ORDER_NAME = 102,
315 // "producers" section must appear after "name" section.
316 WASM_SEC_ORDER_PRODUCERS = 103
317 };
318
319 bool isValidSectionOrder(unsigned ID, StringRef CustomSectionName = "");
320
321 private:
322 int LastOrder = -1; // Lastly seen known section's order
323
324 // Returns -1 for unknown sections.
325 int getSectionOrder(unsigned ID, StringRef CustomSectionName = "");
326 };
327
285328 } // end namespace object
286329
287330 inline raw_ostream &operator<<(raw_ostream &OS, const object::WasmSymbol &Sym) {
2323 #include "llvm/Support/Error.h"
2424 #include "llvm/Support/ErrorHandling.h"
2525 #include "llvm/Support/LEB128.h"
26 #include "llvm/Support/ScopedPrinter.h"
2627 #include
2728 #include
2829 #include
206207 return Table;
207208 }
208209
209 static Error readSection(WasmSection &Section,
210 WasmObjectFile::ReadContext &Ctx) {
210 static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx,
211 WasmSectionOrderChecker &Checker) {
211212 Section.Offset = Ctx.Ptr - Ctx.Start;
212213 Section.Type = readUint8(Ctx);
213214 LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n");
230231 Ctx.Ptr += SectionNameSize;
231232 Size -= SectionNameSize;
232233 }
234
235 if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) {
236 return make_error("Out of order section type: " +
237 llvm::to_string(Section.Type),
238 object_error::parse_failed);
239 }
240
233241 Section.Content = ArrayRef(Ctx.Ptr, Size);
234242 Ctx.Ptr += Size;
235243 return Error::success();
264272 }
265273
266274 WasmSection Sec;
275 WasmSectionOrderChecker Checker;
267276 while (Ctx.Ptr < Ctx.End) {
268 if ((Err = readSection(Sec, Ctx)))
277 if ((Err = readSection(Sec, Ctx, Checker)))
269278 return;
270279 if ((Err = parseSection(Sec)))
271280 return;
14321441 assert(Ref.d.b < Sec.Relocations.size());
14331442 return Sec.Relocations[Ref.d.b];
14341443 }
1444
1445 int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
1446 StringRef CustomSectionName) {
1447 switch (ID) {
1448 case wasm::WASM_SEC_CUSTOM:
1449 return StringSwitch(CustomSectionName)
1450 .Case("dylink", WASM_SEC_ORDER_DYLINK)
1451 .Case("linking", WASM_SEC_ORDER_LINKING)
1452 .StartsWith("reloc.", WASM_SEC_ORDER_RELOC)
1453 .Case("name", WASM_SEC_ORDER_NAME)
1454 .Case("producers", WASM_SEC_ORDER_PRODUCERS)
1455 .Default(-1);
1456 case wasm::WASM_SEC_TYPE:
1457 return WASM_SEC_ORDER_TYPE;
1458 case wasm::WASM_SEC_IMPORT:
1459 return WASM_SEC_ORDER_IMPORT;
1460 case wasm::WASM_SEC_FUNCTION:
1461 return WASM_SEC_ORDER_FUNCTION;
1462 case wasm::WASM_SEC_TABLE:
1463 return WASM_SEC_ORDER_TABLE;
1464 case wasm::WASM_SEC_MEMORY:
1465 return WASM_SEC_ORDER_MEMORY;
1466 case wasm::WASM_SEC_GLOBAL:
1467 return WASM_SEC_ORDER_GLOBAL;
1468 case wasm::WASM_SEC_EXPORT:
1469 return WASM_SEC_ORDER_EXPORT;
1470 case wasm::WASM_SEC_START:
1471 return WASM_SEC_ORDER_START;
1472 case wasm::WASM_SEC_ELEM:
1473 return WASM_SEC_ORDER_ELEM;
1474 case wasm::WASM_SEC_CODE:
1475 return WASM_SEC_ORDER_CODE;
1476 case wasm::WASM_SEC_DATA:
1477 return WASM_SEC_ORDER_DATA;
1478 case wasm::WASM_SEC_DATACOUNT:
1479 return WASM_SEC_ORDER_DATACOUNT;
1480 case wasm::WASM_SEC_EVENT:
1481 return WASM_SEC_ORDER_EVENT;
1482 default:
1483 llvm_unreachable("invalid section");
1484 }
1485 }
1486
1487 bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID,
1488 StringRef CustomSectionName) {
1489 int Order = getSectionOrder(ID, CustomSectionName);
1490 if (Order == -1) // Skip unknown sections
1491 return true;
1492 // There can be multiple "reloc." sections. Otherwise there shouldn't be any
1493 // duplicate section orders.
1494 bool IsValid = (LastOrder == Order && Order == WASM_SEC_ORDER_RELOC) ||
1495 LastOrder < Order;
1496 LastOrder = Order;
1497 return IsValid;
1498 }
0 # RUN: not obj2yaml %p/Inputs/WASM/invalid-section-order.wasm 2>&1 | FileCheck %s
1 # CHECK: {{.*}}: Out of order section type: 10
2
3 # Inputs/WASM/invalid-section-order.wasm is generated from this ll file, by
4 # modifying WasmObjectWriter to incorrectly write the data section before the
5 # code section.
6 #
7 # target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
8 # target triple = "wasm32-unknown-unknown"
9 #
10 # @data = global i32 0, align 4
11 #
12 # define void @foo() {
13 # entry:
14 # ret void
15 # }
0 # RUN: not yaml2obj %s -o /dev/null 2>&1 | FileCheck %s
1
2 --- !WASM
3 FileHeader:
4 Version: 0x00000001
5 Sections:
6 - Type: TYPE
7 Signatures:
8 - Index: 0
9 ReturnType: NORESULT
10 ParamTypes: []
11 - Type: CODE
12 Functions:
13 - Index: 0
14 Locals: []
15 Body: 0B
16 # CHECK: Out of order section type: 3
17 - Type: FUNCTION
18 FunctionTypes: [ 0 ]
19 ...
1212 //===----------------------------------------------------------------------===//
1313 //
1414
15 #include "llvm/Object/Wasm.h"
1516 #include "llvm/ObjectYAML/ObjectYAML.h"
1617 #include "llvm/Support/Endian.h"
1718 #include "llvm/Support/LEB128.h"
515516 writeUint32(OS, Obj.Header.Version);
516517
517518 // Write each section
519 llvm::object::WasmSectionOrderChecker Checker;
518520 for (const std::unique_ptr &Sec : Obj.Sections) {
521 StringRef SecName = "";
522 if (auto S = dyn_cast(Sec.get()))
523 SecName = S->Name;
524 if (!Checker.isValidSectionOrder(Sec->Type, SecName)) {
525 errs() << "Out of order section type: " << Sec->Type << "\n";
526 return 1;
527 }
519528 encodeULEB128(Sec->Type, OS);
520529 std::string OutString;
521530 raw_string_ostream StringStream(OutString);