1use log::error;
4use std::borrow::Cow;
5use std::cmp::PartialEq;
6use std::collections::HashMap;
7use std::fmt::Formatter;
8use std::fmt::{self};
9use std::mem::discriminant;
10use std::slice::Iter;
11use wasm_encoder::reencode::Reencode;
12use wasm_encoder::{AbstractHeapType, Encode, Ieee32, Ieee64};
13
14use wasmparser::types::TypeIdentifier;
15use wasmparser::{ConstExpr, HeapType, Operator, RefType, UnpackedIndex, ValType};
16
17use crate::error::Error;
18use crate::error::Error::{InstrumentationError, UnknownId};
19use crate::ir::id::{CustomSectionID, FunctionID, GlobalID, ModuleID, TypeID};
20use crate::ir::module::add_injection;
21use crate::ir::module::reindex::fix_op_id_mapping;
22use crate::ir::module::side_effects::{InjectType, Injection};
23use crate::ir::types;
24
25pub type Result<T> = std::result::Result<T, Error>;
26
27pub type InjectTag = Option<Tag>;
31
32#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
33pub struct Tag {
34 data: Vec<u8>,
35}
36impl Tag {
37 pub fn new(data: Vec<u8>) -> Self {
38 Self { data }
39 }
40 pub fn data_mut(&mut self) -> &mut Vec<u8> {
41 &mut self.data
42 }
43 pub fn data(&self) -> &Vec<u8> {
44 &self.data
45 }
46 pub fn is_empty(&self) -> bool {
47 self.data.is_empty()
48 }
49}
50pub(crate) trait TagUtils {
51 fn get_or_create_tag(&mut self) -> &mut Tag;
52 fn get_tag(&self) -> &Option<Tag>;
53}
54#[allow(private_bounds)]
56pub trait HasInjectTag: TagUtils {
57 fn append_to_tag(&mut self, mut data: Vec<u8>) {
58 self.get_or_create_tag().data.append(&mut data);
59 }
60}
61
62#[derive(Debug, Clone, Eq, Hash, PartialEq, Copy)]
66pub enum DataType {
67 I8,
68 I16,
69 I32,
70 I64,
71 F32,
72 F64,
73 V128,
74 FuncRef,
75 FuncRefNull,
76 ExternRef,
77 ExternRefNull,
78 Any,
79 AnyNull,
80 None,
81 NoneNull,
82 NoExtern,
83 NoExternNull,
84 NoFunc,
85 NoFuncNull,
86 Eq,
87 EqNull,
88 Struct,
89 StructNull,
90 Array,
91 ArrayNull,
92 I31,
93 I31Null,
94 Exn,
95 ExnNull,
96 NoExn,
97 NoExnNull,
98 Module { ty_id: u32, nullable: bool },
99 RecGroup(u32),
100 CoreTypeId(u32), Cont,
102 ContNull,
103 NoCont,
104 NoContNull,
105}
106
107impl fmt::Display for DataType {
108 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
109 match *self {
110 DataType::I8 => write!(f, "DataType: I8"),
111 DataType::I16 => write!(f, "DataType: I16"),
112 DataType::I32 => write!(f, "DataType: I32"),
113 DataType::I64 => write!(f, "DataType: I64"),
114 DataType::F32 => write!(f, "DataType: F32"),
115 DataType::F64 => write!(f, "DataType: F64"),
116 DataType::V128 => write!(f, "DataType: V128"),
117 DataType::FuncRef => write!(f, "DataType: FuncRef"),
118 DataType::ExternRef => write!(f, "DataType: ExternRef"),
119 DataType::Any => write!(f, "DataType: Any"),
120 DataType::None => write!(f, "DataType: None"),
121 DataType::NoExtern => write!(f, "DataType: NoExtern"),
122 DataType::NoFunc => write!(f, "DataType: NoFunc"),
123 DataType::Eq => write!(f, "DataType: Eq"),
124 DataType::Struct => write!(f, "DataType: Struct"),
125 DataType::Array => write!(f, "DataType: Array"),
126 DataType::I31 => write!(f, "DataType: I31"),
127 DataType::Exn => write!(f, "DataType: Exn"),
128 DataType::ExnNull => write!(f, "exn: null"),
129 DataType::NoExn => write!(f, "DataType: NoExn"),
130 DataType::NoExnNull => write!(f, "noexn: null"),
131 DataType::Module { ty_id, nullable } => {
132 write!(f, "module: {ty_id}, nullable: {nullable}",)
133 }
134 DataType::RecGroup(idx) => write!(f, "recgroup: {idx}"),
135 DataType::CoreTypeId(idx) => write!(f, "coretypeid: {idx}"),
136 DataType::Cont => write!(f, "cont"),
137 DataType::ContNull => write!(f, "cont: null"),
138 DataType::NoCont => write!(f, "nocont"),
139 DataType::NoContNull => write!(f, "nocont: null"),
140 DataType::FuncRefNull => write!(f, "funcref: null"),
141 DataType::ExternRefNull => write!(f, "externref: null"),
142 DataType::AnyNull => write!(f, "any: null"),
143 DataType::NoneNull => write!(f, "none: null"),
144 DataType::NoFuncNull => write!(f, "nofunc: null"),
145 DataType::NoExternNull => write!(f, "noextern: null"),
146 DataType::EqNull => write!(f, "eq: null"),
147 DataType::StructNull => write!(f, "struct: null"),
148 DataType::ArrayNull => write!(f, "array: null"),
149 DataType::I31Null => write!(f, "i31: null"),
150 }
151 }
152}
153
154impl From<wasmparser::StorageType> for DataType {
155 fn from(value: wasmparser::StorageType) -> Self {
156 match value {
157 wasmparser::StorageType::I8 => DataType::I8,
158 wasmparser::StorageType::I16 => DataType::I16,
159 wasmparser::StorageType::Val(val) => DataType::from(val),
160 }
161 }
162}
163
164impl From<DataType> for wasm_encoder::StorageType {
165 fn from(value: DataType) -> Self {
166 match value {
167 DataType::I8 => wasm_encoder::StorageType::I8,
168 DataType::I16 => wasm_encoder::StorageType::I16,
169 _ => wasm_encoder::StorageType::Val(wasm_encoder::ValType::from(&value)),
170 }
171 }
172}
173
174impl From<ValType> for DataType {
175 fn from(value: ValType) -> Self {
176 match value {
177 ValType::I32 => DataType::I32,
178 ValType::I64 => DataType::I64,
179 ValType::F32 => DataType::F32,
180 ValType::F64 => DataType::F64,
181 ValType::V128 => DataType::V128,
182 ValType::Ref(ref_type) => match ref_type.heap_type() {
183 HeapType::Abstract { shared: _, ty } => match ty {
184 wasmparser::AbstractHeapType::Func => {
185 if ref_type.is_nullable() {
186 DataType::FuncRefNull
187 } else {
188 DataType::FuncRef
189 }
190 }
191 wasmparser::AbstractHeapType::Extern => {
192 if ref_type.is_nullable() {
193 DataType::ExternRefNull
194 } else {
195 DataType::ExternRef
196 }
197 }
198 wasmparser::AbstractHeapType::Any => {
199 if ref_type.is_nullable() {
200 DataType::AnyNull
201 } else {
202 DataType::Any
203 }
204 }
205 wasmparser::AbstractHeapType::None => {
206 if ref_type.is_nullable() {
207 DataType::NoneNull
208 } else {
209 DataType::None
210 }
211 }
212 wasmparser::AbstractHeapType::NoExtern => {
213 if ref_type.is_nullable() {
214 DataType::NoExternNull
215 } else {
216 DataType::NoExtern
217 }
218 }
219 wasmparser::AbstractHeapType::NoFunc => {
220 if ref_type.is_nullable() {
221 DataType::NoFuncNull
222 } else {
223 DataType::NoFunc
224 }
225 }
226 wasmparser::AbstractHeapType::Eq => {
227 if ref_type.is_nullable() {
228 DataType::EqNull
229 } else {
230 DataType::Eq
231 }
232 }
233 wasmparser::AbstractHeapType::Struct => {
234 if ref_type.is_nullable() {
235 DataType::StructNull
236 } else {
237 DataType::Struct
238 }
239 }
240 wasmparser::AbstractHeapType::Array => {
241 if ref_type.is_nullable() {
242 DataType::ArrayNull
243 } else {
244 DataType::Array
245 }
246 }
247 wasmparser::AbstractHeapType::I31 => {
248 if ref_type.is_nullable() {
249 DataType::I31Null
250 } else {
251 DataType::I31
252 }
253 }
254 wasmparser::AbstractHeapType::Exn => {
255 if ref_type.is_nullable() {
256 DataType::ExnNull
257 } else {
258 DataType::Exn
259 }
260 }
261 wasmparser::AbstractHeapType::NoExn => {
262 if ref_type.is_nullable() {
263 DataType::NoExnNull
264 } else {
265 DataType::NoExn
266 }
267 }
268 wasmparser::AbstractHeapType::Cont => {
269 if ref_type.is_nullable() {
270 DataType::ContNull
271 } else {
272 DataType::Cont
273 }
274 }
275 wasmparser::AbstractHeapType::NoCont => {
276 if ref_type.is_nullable() {
277 DataType::NoContNull
278 } else {
279 DataType::NoCont
280 }
281 }
282 },
283 HeapType::Concrete(u) | HeapType::Exact(u) => match u {
284 UnpackedIndex::Module(idx) => DataType::Module {
285 ty_id: *ModuleID(idx),
286 nullable: ref_type.is_nullable(),
287 },
288 UnpackedIndex::RecGroup(idx) => DataType::RecGroup(idx),
289 UnpackedIndex::Id(_id) => unimplemented!("Not supported yet!"),
290 },
291 },
292 }
293 }
294}
295
296impl From<&DataType> for wasm_encoder::ValType {
300 fn from(ty: &DataType) -> Self {
301 match ty {
302 DataType::I8 | DataType::I16 => panic!("Not valtype equivalent!"),
303 DataType::I32 => wasm_encoder::ValType::I32,
304 DataType::I64 => wasm_encoder::ValType::I64,
305 DataType::F32 => wasm_encoder::ValType::F32,
306 DataType::F64 => wasm_encoder::ValType::F64,
307 DataType::V128 => wasm_encoder::ValType::V128,
308 DataType::FuncRef => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
309 nullable: false,
310 heap_type: wasm_encoder::HeapType::Abstract {
311 shared: false,
312 ty: AbstractHeapType::Func,
313 },
314 }),
315 DataType::ExternRef => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
316 nullable: false,
317 heap_type: wasm_encoder::HeapType::Abstract {
318 shared: false,
319 ty: AbstractHeapType::Extern,
320 },
321 }),
322 DataType::Any => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
323 nullable: false,
324 heap_type: wasm_encoder::HeapType::Abstract {
325 shared: false,
326 ty: AbstractHeapType::Any,
327 },
328 }),
329 DataType::NoneNull => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
330 nullable: true,
331 heap_type: wasm_encoder::HeapType::Abstract {
332 shared: false,
333 ty: AbstractHeapType::None,
334 },
335 }),
336 DataType::None => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
337 nullable: false,
338 heap_type: wasm_encoder::HeapType::Abstract {
339 shared: false,
340 ty: AbstractHeapType::None,
341 },
342 }),
343 DataType::NoExtern => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
344 nullable: false,
345 heap_type: wasm_encoder::HeapType::Abstract {
346 shared: false,
347 ty: AbstractHeapType::NoExtern,
348 },
349 }),
350 DataType::NoExternNull => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
351 nullable: true,
352 heap_type: wasm_encoder::HeapType::Abstract {
353 shared: false,
354 ty: AbstractHeapType::NoExtern,
355 },
356 }),
357 DataType::NoFunc => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
358 nullable: false,
359 heap_type: wasm_encoder::HeapType::Abstract {
360 shared: false,
361 ty: AbstractHeapType::NoFunc,
362 },
363 }),
364 DataType::NoFuncNull => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
365 nullable: true,
366 heap_type: wasm_encoder::HeapType::Abstract {
367 shared: false,
368 ty: AbstractHeapType::NoFunc,
369 },
370 }),
371 DataType::Eq => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
372 nullable: false,
373 heap_type: wasm_encoder::HeapType::Abstract {
374 shared: false,
375 ty: AbstractHeapType::Eq,
376 },
377 }),
378 DataType::Struct => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
379 nullable: false,
380 heap_type: wasm_encoder::HeapType::Abstract {
381 shared: false,
382 ty: AbstractHeapType::Struct,
383 },
384 }),
385 DataType::Array => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
386 nullable: false,
387 heap_type: wasm_encoder::HeapType::Abstract {
388 shared: false,
389 ty: AbstractHeapType::Array,
390 },
391 }),
392 DataType::I31 => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
393 nullable: false,
394 heap_type: wasm_encoder::HeapType::Abstract {
395 shared: false,
396 ty: AbstractHeapType::I31,
397 },
398 }),
399 DataType::Exn => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
400 nullable: false,
401 heap_type: wasm_encoder::HeapType::Abstract {
402 shared: false,
403 ty: AbstractHeapType::Exn,
404 },
405 }),
406 DataType::ExnNull => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
407 nullable: true,
408 heap_type: wasm_encoder::HeapType::Abstract {
409 shared: false,
410 ty: AbstractHeapType::Exn,
411 },
412 }),
413 DataType::NoExn => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
414 nullable: false,
415 heap_type: wasm_encoder::HeapType::Abstract {
416 shared: false,
417 ty: AbstractHeapType::NoExn,
418 },
419 }),
420 DataType::NoExnNull => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
421 nullable: true,
422 heap_type: wasm_encoder::HeapType::Abstract {
423 shared: false,
424 ty: AbstractHeapType::NoExn,
425 },
426 }),
427 DataType::Module { ty_id, nullable } => {
428 wasm_encoder::ValType::Ref(wasm_encoder::RefType {
429 nullable: *nullable,
430 heap_type: wasm_encoder::HeapType::Concrete(*ty_id),
431 })
432 }
433 DataType::RecGroup(idx) => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
434 nullable: false,
435 heap_type: wasm_encoder::HeapType::Concrete(*idx),
436 }),
437 DataType::CoreTypeId(idx) => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
438 nullable: false,
439 heap_type: wasm_encoder::HeapType::Concrete(*idx),
440 }),
441 DataType::Cont => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
442 nullable: false,
443 heap_type: wasm_encoder::HeapType::Abstract {
444 shared: false,
445 ty: AbstractHeapType::Cont,
446 },
447 }),
448 DataType::ContNull => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
449 nullable: true,
450 heap_type: wasm_encoder::HeapType::Abstract {
451 shared: false,
452 ty: AbstractHeapType::Cont,
453 },
454 }),
455 DataType::NoCont => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
456 nullable: false,
457 heap_type: wasm_encoder::HeapType::Abstract {
458 shared: false,
459 ty: AbstractHeapType::NoCont,
460 },
461 }),
462 DataType::NoContNull => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
463 nullable: true,
464 heap_type: wasm_encoder::HeapType::Abstract {
465 shared: false,
466 ty: AbstractHeapType::NoCont,
467 },
468 }),
469 DataType::FuncRefNull => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
470 nullable: true,
471 heap_type: wasm_encoder::HeapType::Abstract {
472 shared: false,
473 ty: AbstractHeapType::Func,
474 },
475 }),
476 DataType::ExternRefNull => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
477 nullable: true,
478 heap_type: wasm_encoder::HeapType::Abstract {
479 shared: false,
480 ty: AbstractHeapType::Extern,
481 },
482 }),
483 DataType::AnyNull => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
484 nullable: true,
485 heap_type: wasm_encoder::HeapType::Abstract {
486 shared: false,
487 ty: AbstractHeapType::Any,
488 },
489 }),
490 DataType::EqNull => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
491 nullable: true,
492 heap_type: wasm_encoder::HeapType::Abstract {
493 shared: false,
494 ty: AbstractHeapType::Eq,
495 },
496 }),
497 DataType::StructNull => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
498 nullable: true,
499 heap_type: wasm_encoder::HeapType::Abstract {
500 shared: false,
501 ty: AbstractHeapType::Struct,
502 },
503 }),
504 DataType::ArrayNull => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
505 nullable: true,
506 heap_type: wasm_encoder::HeapType::Abstract {
507 shared: false,
508 ty: AbstractHeapType::Array,
509 },
510 }),
511 DataType::I31Null => wasm_encoder::ValType::Ref(wasm_encoder::RefType {
512 nullable: true,
513 heap_type: wasm_encoder::HeapType::Abstract {
514 shared: false,
515 ty: AbstractHeapType::I31,
516 },
517 }),
518 }
519 }
520}
521
522impl From<&DataType> for ValType {
523 fn from(ty: &DataType) -> Self {
524 match ty {
525 DataType::I8 | DataType::I16 => panic!("No valtype equivalent!"),
526 DataType::I32 => ValType::I32,
527 DataType::I64 => ValType::I64,
528 DataType::F32 => ValType::F32,
529 DataType::F64 => ValType::F64,
530 DataType::V128 => ValType::V128,
531 DataType::FuncRef => ValType::FUNCREF,
532 DataType::ExternRef => ValType::EXTERNREF,
533 DataType::Any => ValType::Ref(
534 RefType::new(
535 false,
536 HeapType::Abstract {
537 shared: false,
538 ty: wasmparser::AbstractHeapType::Any,
539 },
540 )
541 .unwrap(),
542 ),
543 DataType::None => ValType::Ref(
544 RefType::new(
545 false,
546 HeapType::Abstract {
547 shared: false,
548 ty: wasmparser::AbstractHeapType::None,
549 },
550 )
551 .unwrap(),
552 ),
553 DataType::NoneNull => ValType::Ref(
554 RefType::new(
555 true,
556 HeapType::Abstract {
557 shared: false,
558 ty: wasmparser::AbstractHeapType::None,
559 },
560 )
561 .unwrap(),
562 ),
563 DataType::NoExtern => ValType::Ref(
564 RefType::new(
565 false,
566 HeapType::Abstract {
567 shared: false,
568 ty: wasmparser::AbstractHeapType::NoExtern,
569 },
570 )
571 .unwrap(),
572 ),
573 DataType::NoExternNull => ValType::Ref(
574 RefType::new(
575 true,
576 HeapType::Abstract {
577 shared: false,
578 ty: wasmparser::AbstractHeapType::NoExtern,
579 },
580 )
581 .unwrap(),
582 ),
583 DataType::NoFunc => ValType::Ref(
584 RefType::new(
585 false,
586 HeapType::Abstract {
587 shared: false,
588 ty: wasmparser::AbstractHeapType::NoFunc,
589 },
590 )
591 .unwrap(),
592 ),
593 DataType::NoFuncNull => ValType::Ref(
594 RefType::new(
595 true,
596 HeapType::Abstract {
597 shared: false,
598 ty: wasmparser::AbstractHeapType::NoFunc,
599 },
600 )
601 .unwrap(),
602 ),
603 DataType::Eq => ValType::Ref(
604 RefType::new(
605 false,
606 HeapType::Abstract {
607 shared: false,
608 ty: wasmparser::AbstractHeapType::Eq,
609 },
610 )
611 .unwrap(),
612 ),
613 DataType::Struct => ValType::Ref(
614 RefType::new(
615 false,
616 HeapType::Abstract {
617 shared: false,
618 ty: wasmparser::AbstractHeapType::Struct,
619 },
620 )
621 .unwrap(),
622 ),
623 DataType::Array => ValType::Ref(
624 RefType::new(
625 false,
626 HeapType::Abstract {
627 shared: false,
628 ty: wasmparser::AbstractHeapType::Array,
629 },
630 )
631 .unwrap(),
632 ),
633 DataType::I31 => ValType::Ref(
634 RefType::new(
635 false,
636 HeapType::Abstract {
637 shared: false,
638 ty: wasmparser::AbstractHeapType::I31,
639 },
640 )
641 .unwrap(),
642 ),
643 DataType::Exn => ValType::Ref(
644 RefType::new(
645 false,
646 HeapType::Abstract {
647 shared: false,
648 ty: wasmparser::AbstractHeapType::Exn,
649 },
650 )
651 .unwrap(),
652 ),
653 DataType::ExnNull => ValType::Ref(
654 RefType::new(
655 true,
656 HeapType::Abstract {
657 shared: false,
658 ty: wasmparser::AbstractHeapType::Exn,
659 },
660 )
661 .unwrap(),
662 ),
663 DataType::NoExn => ValType::Ref(
664 RefType::new(
665 false,
666 HeapType::Abstract {
667 shared: false,
668 ty: wasmparser::AbstractHeapType::NoExn,
669 },
670 )
671 .unwrap(),
672 ),
673 DataType::NoExnNull => ValType::Ref(
674 RefType::new(
675 true,
676 HeapType::Abstract {
677 shared: false,
678 ty: wasmparser::AbstractHeapType::NoExn,
679 },
680 )
681 .unwrap(),
682 ),
683 DataType::Module { ty_id, nullable } => ValType::Ref(
684 RefType::new(
685 *nullable,
686 HeapType::Concrete(wasmparser::UnpackedIndex::Module(*ty_id)),
687 )
688 .unwrap(),
689 ),
690 DataType::RecGroup(idx) => ValType::Ref(
691 RefType::new(
692 false,
693 HeapType::Concrete(wasmparser::UnpackedIndex::RecGroup(*idx)),
694 )
695 .unwrap(),
696 ),
697 DataType::CoreTypeId(_idx) => unimplemented!("Not Supported Yet!"),
698 DataType::Cont => ValType::Ref(
699 RefType::new(
700 false,
701 HeapType::Abstract {
702 shared: false,
703 ty: wasmparser::AbstractHeapType::Cont,
704 },
705 )
706 .unwrap(),
707 ),
708 DataType::ContNull => ValType::Ref(
709 RefType::new(
710 true,
711 HeapType::Abstract {
712 shared: false,
713 ty: wasmparser::AbstractHeapType::Cont,
714 },
715 )
716 .unwrap(),
717 ),
718 DataType::NoCont => ValType::Ref(
719 RefType::new(
720 false,
721 HeapType::Abstract {
722 shared: false,
723 ty: wasmparser::AbstractHeapType::NoCont,
724 },
725 )
726 .unwrap(),
727 ),
728 DataType::NoContNull => ValType::Ref(
729 RefType::new(
730 true,
731 HeapType::Abstract {
732 shared: false,
733 ty: wasmparser::AbstractHeapType::NoCont,
734 },
735 )
736 .unwrap(),
737 ),
738 DataType::FuncRefNull => ValType::Ref(
739 RefType::new(
740 true,
741 HeapType::Abstract {
742 shared: false,
743 ty: wasmparser::AbstractHeapType::Func,
744 },
745 )
746 .unwrap(),
747 ),
748 DataType::ExternRefNull => ValType::Ref(
749 RefType::new(
750 true,
751 HeapType::Abstract {
752 shared: false,
753 ty: wasmparser::AbstractHeapType::Extern,
754 },
755 )
756 .unwrap(),
757 ),
758 DataType::AnyNull => ValType::Ref(
759 RefType::new(
760 true,
761 HeapType::Abstract {
762 shared: false,
763 ty: wasmparser::AbstractHeapType::Any,
764 },
765 )
766 .unwrap(),
767 ),
768 DataType::EqNull => ValType::Ref(
769 RefType::new(
770 true,
771 HeapType::Abstract {
772 shared: false,
773 ty: wasmparser::AbstractHeapType::Eq,
774 },
775 )
776 .unwrap(),
777 ),
778 DataType::StructNull => ValType::Ref(
779 RefType::new(
780 true,
781 HeapType::Abstract {
782 shared: false,
783 ty: wasmparser::AbstractHeapType::Struct,
784 },
785 )
786 .unwrap(),
787 ),
788 DataType::ArrayNull => ValType::Ref(
789 RefType::new(
790 true,
791 HeapType::Abstract {
792 shared: false,
793 ty: wasmparser::AbstractHeapType::Array,
794 },
795 )
796 .unwrap(),
797 ),
798 DataType::I31Null => ValType::Ref(
799 RefType::new(
800 true,
801 HeapType::Abstract {
802 shared: false,
803 ty: wasmparser::AbstractHeapType::I31,
804 },
805 )
806 .unwrap(),
807 ),
808 }
809 }
810}
811
812pub fn valtype_to_wasmencoder_type(val_type: &ValType) -> wasm_encoder::ValType {
817 let mut reencoder = wasm_encoder::reencode::RoundtripReencoder;
818 reencoder.val_type(*val_type).unwrap()
819}
820
821#[derive(Debug, Clone)]
822pub struct DataSegment {
824 pub kind: DataSegmentKind,
826 pub data: Vec<u8>,
828 pub tag: InjectTag,
829}
830
831impl DataSegment {
832 pub fn from_wasmparser(data: wasmparser::Data) -> Result<DataSegment> {
833 Ok(DataSegment {
834 kind: DataSegmentKind::from_wasmparser(data.kind)?,
835 data: data.data.to_vec(),
836 tag: None,
837 })
838 }
839}
840impl TagUtils for DataSegment {
841 fn get_or_create_tag(&mut self) -> &mut Tag {
842 self.tag.get_or_insert_default()
843 }
844
845 fn get_tag(&self) -> &Option<Tag> {
846 &self.tag
847 }
848}
849
850#[derive(Debug, Clone)]
852pub enum DataSegmentKind {
853 Passive,
855 Active {
857 memory_index: u32,
859 offset_expr: InitExpr,
862 },
863}
864
865impl DataSegmentKind {
866 pub(crate) fn from_wasmparser(kind: wasmparser::DataKind) -> Result<DataSegmentKind> {
867 Ok(match kind {
868 wasmparser::DataKind::Passive => DataSegmentKind::Passive,
869 wasmparser::DataKind::Active {
870 memory_index,
871 offset_expr,
872 } => DataSegmentKind::Active {
873 memory_index,
874 offset_expr: InitExpr::eval(&offset_expr)?,
875 },
876 })
877 }
878}
879
880#[derive(Debug, Clone)]
881pub enum ElementKind {
883 Passive,
884 Active {
885 table_index: Option<u32>,
886 offset_expr: InitExpr,
887 },
888 Declared,
889}
890
891impl ElementKind {
892 pub(crate) fn from_wasmparser(kind: wasmparser::ElementKind) -> Result<ElementKind> {
893 match kind {
894 wasmparser::ElementKind::Passive => Ok(ElementKind::Passive),
895 wasmparser::ElementKind::Declared => Ok(ElementKind::Declared),
896 wasmparser::ElementKind::Active {
897 table_index,
898 offset_expr,
899 } => Ok(ElementKind::Active {
900 table_index,
901 offset_expr: InitExpr::eval(&offset_expr)?,
902 }),
903 }
904 }
905}
906
907#[derive(Debug, Clone)]
908pub enum ElementItems {
910 Functions(Vec<FunctionID>),
911 ConstExprs { ty: RefType, exprs: Vec<InitExpr> },
912}
913
914impl ElementItems {
915 pub(crate) fn from_wasmparser(items: wasmparser::ElementItems) -> Result<ElementItems> {
916 match items {
917 wasmparser::ElementItems::Functions(reader) => {
918 let functions = reader
919 .into_iter()
920 .collect::<std::result::Result<Vec<_>, _>>()?;
921 let fids = functions.iter().map(|id| FunctionID(*id)).collect();
923 Ok(ElementItems::Functions(fids))
924 }
925 wasmparser::ElementItems::Expressions(ref_type, reader) => {
926 let exprs = reader
927 .into_iter()
928 .collect::<std::result::Result<Vec<_>, _>>()?;
929 Ok(ElementItems::ConstExprs {
930 ty: ref_type,
931 exprs: exprs
932 .iter()
933 .map(InitExpr::eval)
934 .collect::<Result<Vec<_>>>()?,
935 })
936 }
937 }
938 }
939}
940
941#[derive(Debug, Clone)]
942pub enum FuncInstrMode {
944 Entry,
945 Exit,
946}
947
948#[derive(Default, Debug, Clone)]
949pub struct FuncInstrFlag<'a> {
951 pub has_special_instr: bool,
954 pub current_mode: Option<FuncInstrMode>,
955 pub entry: InjectedInstrs<'a>,
956 pub exit: InjectedInstrs<'a>,
957}
958
959impl TagUtils for FuncInstrFlag<'_> {
960 fn get_or_create_tag(&mut self) -> &mut Tag {
961 match self.current_mode {
962 None => {
963 panic!("Internal error: Current mode is not set...cannot append to the tag!")
964 }
965 Some(FuncInstrMode::Entry) => self.entry.get_or_create_tag(),
966 Some(FuncInstrMode::Exit) => self.exit.get_or_create_tag(),
967 }
968 }
969
970 fn get_tag(&self) -> &Option<Tag> {
971 match self.current_mode {
972 None => {
973 panic!("Internal error: Current mode is not set...cannot append to the tag!")
974 }
975 Some(FuncInstrMode::Entry) => self.entry.get_tag(),
976 Some(FuncInstrMode::Exit) => self.exit.get_tag(),
977 }
978 }
979}
980impl HasInjectTag for FuncInstrFlag<'_> {}
981impl fmt::Display for FuncInstrFlag<'_> {
982 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
983 let FuncInstrFlag {
984 has_special_instr,
985 entry,
986 exit,
987 current_mode: _,
988 } = self;
989 if !self.has_instr() {
990 write!(f, "Not Instrumented")?;
991 }
992 write!(
993 f,
994 "Has special instrumentation: {}\n \
995 Func Entry: {:?} instructions\n \
996 Func Exit: {:?} instructions",
997 has_special_instr,
998 entry.instrs.len(),
999 exit.instrs.len()
1000 )
1001 }
1002}
1003
1004impl PartialEq for FuncInstrFlag<'_> {
1005 fn eq(&self, other: &Self) -> bool {
1006 let Self {
1008 has_special_instr,
1009 entry,
1010 exit,
1011 current_mode,
1012 } = self;
1013 let mut result = *has_special_instr == other.has_special_instr;
1014 result &= entry.eq(&other.entry);
1015 result &= exit.eq(&other.exit);
1016 result &= discriminant(current_mode) == discriminant(&other.current_mode);
1017
1018 result
1019 }
1020}
1021
1022impl Eq for FuncInstrFlag<'_> {}
1023
1024impl<'a> FuncInstrFlag<'a> {
1025 pub fn has_instr(&self) -> bool {
1026 let Self {
1028 entry,
1029 exit,
1030 has_special_instr: _,
1031 current_mode: _,
1032 } = self;
1033 !entry.instrs.is_empty() || !exit.instrs.is_empty()
1034 }
1035
1036 pub fn has_special_instr(&self) -> bool {
1037 self.has_special_instr
1038 }
1039
1040 pub fn add_instr(&mut self, val: Operator<'a>) {
1042 self.has_special_instr = true;
1043 match self.current_mode {
1044 None => {
1045 panic!("Internal error: Current mode is not set...cannot inject instructions!")
1046 }
1047 Some(FuncInstrMode::Entry) => self.entry.instrs.push(val),
1048 Some(FuncInstrMode::Exit) => self.exit.instrs.push(val),
1049 }
1050 }
1051
1052 pub fn get_instr(&self, idx: usize) -> &Operator<'_> {
1054 match self.current_mode {
1055 None => {
1056 panic!("Internal error: Current mode is not set...cannot grab instruction without context!")
1057 }
1058 Some(FuncInstrMode::Entry) => &self.entry.instrs[idx],
1059 Some(FuncInstrMode::Exit) => &self.exit.instrs[idx],
1060 }
1061 }
1062
1063 pub fn instr_len(&self) -> usize {
1064 match self.current_mode {
1065 None => {
1066 panic!("Internal error: Current mode is not set...cannot grab instruction without context!")
1067 }
1068 Some(FuncInstrMode::Entry) => self.entry.instrs.len(),
1069 Some(FuncInstrMode::Exit) => self.exit.instrs.len(),
1070 }
1071 }
1072
1073 pub fn add_injections(
1074 &mut self,
1075 fid: u32,
1076 func_mapping: &HashMap<u32, u32>,
1077 global_mapping: &HashMap<u32, u32>,
1078 memory_mapping: &HashMap<u32, u32>,
1079 side_effects: &mut HashMap<InjectType, Vec<Injection<'a>>>,
1080 ) -> types::Result<()> {
1081 let Self { entry, exit, .. } = self;
1082 let mut add_inj =
1083 |mode: FuncInstrMode, instrs: &mut InjectedInstrs<'a>| -> types::Result<()> {
1084 for op in instrs.instrs.iter_mut() {
1086 fix_op_id_mapping(op, func_mapping, global_mapping, memory_mapping)?;
1087 }
1088
1089 if instrs.instrs.is_empty() {
1090 return Ok(());
1091 }
1092
1093 add_injection(
1094 side_effects,
1095 InjectType::Probe,
1096 Injection::FuncProbe {
1097 target_fid: fid,
1098 mode,
1099 body: instrs.instrs.clone(),
1100 tag: instrs.tag.clone().unwrap_or_default(),
1101 },
1102 );
1103 Ok(())
1104 };
1105
1106 add_inj(FuncInstrMode::Entry, entry)?;
1107 add_inj(FuncInstrMode::Exit, exit)?;
1108 Ok(())
1109 }
1110
1111 pub fn finish_instr(&mut self) {
1113 self.current_mode = None
1114 }
1115}
1116
1117#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1118pub enum InstrumentationMode {
1120 Before,
1121 After,
1122 Alternate,
1123
1124 SemanticAfter,
1126 BlockEntry,
1127 BlockExit,
1128 BlockAlt,
1129}
1130
1131#[derive(Default, Debug, Clone)]
1132pub struct InstrumentationFlag<'a> {
1134 pub current_mode: Option<InstrumentationMode>,
1135 pub before: InjectedInstrs<'a>,
1136 pub after: InjectedInstrs<'a>,
1137 pub alternate: Option<InjectedInstrs<'a>>,
1141
1142 pub semantic_after: InjectedInstrs<'a>,
1144 pub block_entry: InjectedInstrs<'a>,
1145 pub block_exit: InjectedInstrs<'a>,
1146 pub block_alt: Option<InjectedInstrs<'a>>,
1150}
1151impl TagUtils for InstrumentationFlag<'_> {
1152 fn get_or_create_tag(&mut self) -> &mut Tag {
1153 match self.current_mode {
1154 None => {
1155 panic!("Internal error: Current mode is not set...cannot get the tag!")
1156 }
1157 Some(InstrumentationMode::Before) => self.before.get_or_create_tag(),
1158 Some(InstrumentationMode::After) => self.after.get_or_create_tag(),
1159 Some(InstrumentationMode::Alternate) => {
1160 self.alternate.get_or_insert_default().get_or_create_tag()
1161 }
1162 Some(InstrumentationMode::SemanticAfter) => self.semantic_after.get_or_create_tag(),
1163 Some(InstrumentationMode::BlockEntry) => self.block_entry.get_or_create_tag(),
1164 Some(InstrumentationMode::BlockExit) => self.block_exit.get_or_create_tag(),
1165 Some(InstrumentationMode::BlockAlt) => {
1166 self.block_alt.get_or_insert_default().get_or_create_tag()
1167 }
1168 }
1169 }
1170
1171 fn get_tag(&self) -> &Option<Tag> {
1172 match self.current_mode {
1173 None => {
1174 panic!("Internal error: Current mode is not set...cannot get the tag!")
1175 }
1176 Some(InstrumentationMode::Before) => self.before.get_tag(),
1177 Some(InstrumentationMode::After) => self.after.get_tag(),
1178 Some(InstrumentationMode::Alternate) => {
1179 if let Some(alt) = &self.alternate {
1180 alt.get_tag()
1181 } else {
1182 &None
1183 }
1184 }
1185 Some(InstrumentationMode::SemanticAfter) => self.semantic_after.get_tag(),
1186 Some(InstrumentationMode::BlockEntry) => self.block_entry.get_tag(),
1187 Some(InstrumentationMode::BlockExit) => self.block_exit.get_tag(),
1188 Some(InstrumentationMode::BlockAlt) => {
1189 if let Some(alt) = &self.block_alt {
1190 alt.get_tag()
1191 } else {
1192 &None
1193 }
1194 }
1195 }
1196 }
1197}
1198impl HasInjectTag for InstrumentationFlag<'_> {}
1199
1200impl fmt::Display for InstrumentationFlag<'_> {
1201 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1202 let InstrumentationFlag {
1203 before,
1204 after,
1205 alternate,
1206 semantic_after,
1207 block_entry,
1208 block_exit,
1209 block_alt,
1210 current_mode: _,
1211 } = self;
1212 if !self.has_instr() {
1213 write!(f, "Not Instrumented")?;
1214 }
1215 write!(
1216 f,
1217 "Before: {:?} instructions\n \
1218 After: {:?} instructions\n \
1219 Alternate: {:?} instructions\n \
1220 Semantic After: {:?} instructions\n \
1221 Block Entry: {:?} instructions\n \
1222 Block Exit: {:?} instructions\n \
1223 Block Alt: {:?} instructions",
1224 before.instrs.len(),
1225 after.instrs.len(),
1226 alternate.as_ref().unwrap().instrs.len(),
1227 semantic_after.instrs.len(),
1228 block_entry.instrs.len(),
1229 block_exit.instrs.len(),
1230 block_alt.as_ref().unwrap().instrs.len()
1231 )
1232 }
1233}
1234
1235impl PartialEq for InstrumentationFlag<'_> {
1236 fn eq(&self, other: &Self) -> bool {
1237 let Self {
1239 before,
1240 after,
1241 alternate,
1242 semantic_after,
1243 block_entry,
1244 block_exit,
1245 block_alt,
1246 current_mode,
1247 } = self;
1248 let mut result = before.eq(&other.before);
1249 result &= after.eq(&other.after);
1250 result &= *alternate == other.alternate;
1251 result &= semantic_after.eq(&other.semantic_after);
1252 result &= block_entry.eq(&other.block_entry);
1253 result &= block_exit.eq(&other.block_exit);
1254 result &= block_alt.eq(&other.block_alt);
1255 result &= *current_mode == other.current_mode;
1256
1257 result
1258 }
1259}
1260
1261impl Eq for InstrumentationFlag<'_> {}
1262
1263impl<'a> InstrumentationFlag<'a> {
1264 pub fn has_instr(&self) -> bool {
1265 let Self {
1267 before,
1268 after,
1269 alternate,
1270 semantic_after,
1271 block_entry,
1272 block_exit,
1273 block_alt,
1274 current_mode: _,
1275 } = self;
1276 !before.instrs.is_empty()
1277 || !after.instrs.is_empty()
1278 || !alternate.is_none() || !semantic_after.instrs.is_empty()
1280 || !block_entry.instrs.is_empty()
1281 || !block_exit.instrs.is_empty()
1282 || !block_alt.is_none() }
1284
1285 pub(crate) fn check_special_is_resolved(&self) {
1286 let Self {
1287 semantic_after,
1288 block_entry,
1289 block_exit,
1290 block_alt,
1291 ..
1292 } = self;
1293
1294 if !semantic_after.instrs.is_empty() {
1296 error!(
1297 "BUG: Semantic after instrumentation should be resolved already, please report."
1298 );
1299 }
1300 if !block_entry.instrs.is_empty() {
1301 error!("BUG: Block entry instrumentation should be resolved already, please report.");
1302 }
1303 if !block_exit.instrs.is_empty() {
1304 error!("BUG: Block exit instrumentation should be resolved already, please report.");
1305 }
1306 if !block_alt.is_none() {
1307 error!("BUG: Block alt instrumentation should be resolved already, please report.");
1308 }
1309 }
1310
1311 pub(crate) fn add_injections(
1312 &self,
1313 fid: u32,
1314 idx: u32,
1315 side_effects: &mut HashMap<InjectType, Vec<Injection<'a>>>,
1316 ) {
1317 let Self {
1318 before,
1319 after,
1320 alternate,
1321 ..
1322 } = self;
1323
1324 let mut add_inj = |mode: InstrumentationMode, instrs: &InjectedInstrs<'a>| {
1325 if instrs.instrs.is_empty() {
1326 return;
1327 }
1328 add_injection(
1329 side_effects,
1330 InjectType::Probe,
1331 Injection::FuncLocProbe {
1332 target_fid: fid,
1333 target_opcode_idx: idx,
1334 mode,
1335 body: instrs.instrs.clone(),
1336 tag: instrs.tag.clone().unwrap_or_default(),
1337 },
1338 );
1339 };
1340
1341 add_inj(InstrumentationMode::Before, before);
1342 add_inj(InstrumentationMode::After, after);
1343 if let Some(alt) = alternate {
1344 add_inj(InstrumentationMode::Alternate, alt);
1345 }
1346 }
1347
1348 pub fn add_instr(&mut self, op: &Operator, val: Operator<'a>) -> bool {
1351 match self.current_mode {
1352 None => {
1353 panic!("Internal error: Current mode is not set...cannot inject instructions!")
1354 }
1355 Some(InstrumentationMode::Before) => {
1356 self.before.instrs.push(val);
1357 false
1358 }
1359 Some(InstrumentationMode::After) => {
1360 self.after.instrs.push(val);
1361 false
1362 }
1363 Some(InstrumentationMode::Alternate) => {
1364 match &mut self.alternate {
1365 None => {
1366 self.alternate = Some(InjectedInstrs {
1367 instrs: vec![val],
1368 tag: None,
1369 })
1370 }
1371 Some(alternate) => alternate.instrs.push(val),
1372 }
1373 false
1374 }
1375 Some(InstrumentationMode::SemanticAfter) => {
1376 if Self::is_block_style_op(op) || Self::is_branching_op(op) {
1377 self.semantic_after.instrs.push(val);
1378 true
1379 } else {
1380 panic!(
1382 "Cannot apply semantic after instrumentation mode to op type: {:?}",
1383 op
1384 );
1385 }
1386 }
1387 Some(InstrumentationMode::BlockEntry) => {
1388 if Self::is_block_style_op(op) {
1389 self.block_entry.instrs.push(val);
1390 true
1391 } else {
1392 panic!(
1394 "Cannot apply block entry instrumentation mode to op type: {:?}",
1395 op
1396 );
1397 }
1398 }
1399 Some(InstrumentationMode::BlockExit) => {
1400 if Self::is_block_style_op(op) {
1401 self.block_exit.instrs.push(val);
1402 true
1403 } else {
1404 panic!(
1406 "Cannot apply block exit instrumentation mode to op type: {:?}",
1407 op
1408 );
1409 }
1410 }
1411 Some(InstrumentationMode::BlockAlt) => {
1412 if Self::is_block_style_op(op) {
1413 match &mut self.block_alt {
1414 None => {
1415 self.block_alt = Some(InjectedInstrs {
1416 instrs: vec![val],
1417 tag: None,
1418 })
1419 }
1420 Some(block_alt) => block_alt.instrs.push(val),
1421 }
1422 true
1423 } else {
1424 panic!(
1426 "Cannot apply block alternate instrumentation mode to op type: {:?}",
1427 op
1428 );
1429 }
1430 }
1431 }
1432 }
1433
1434 pub fn instr_len(&self) -> usize {
1435 match self.current_mode {
1436 None => {
1437 panic!("Current mode is not set...cannot inject instructions!")
1438 }
1439 Some(InstrumentationMode::Before) => self.before.instrs.len(),
1440 Some(InstrumentationMode::After) => self.after.instrs.len(),
1441 Some(InstrumentationMode::Alternate) => match &self.alternate {
1442 None => 0,
1443 Some(alternate) => alternate.instrs.len(),
1444 },
1445 Some(InstrumentationMode::SemanticAfter) => self.semantic_after.instrs.len(),
1446 Some(InstrumentationMode::BlockEntry) => self.block_entry.instrs.len(),
1447 Some(InstrumentationMode::BlockExit) => self.block_exit.instrs.len(),
1448 Some(InstrumentationMode::BlockAlt) => match &self.block_alt {
1449 None => 0,
1450 Some(block_alt) => block_alt.instrs.len(),
1451 },
1452 }
1453 }
1454
1455 pub fn clear_instr(&mut self, mode: InstrumentationMode) {
1456 match mode {
1457 InstrumentationMode::Before => {
1458 self.before.instrs.clear();
1459 }
1460 InstrumentationMode::After => self.after.instrs.clear(),
1461 InstrumentationMode::Alternate => {
1462 self.alternate = None;
1463 }
1464 InstrumentationMode::SemanticAfter => self.semantic_after.instrs.clear(),
1465 InstrumentationMode::BlockEntry => self.block_entry.instrs.clear(),
1466 InstrumentationMode::BlockExit => self.block_exit.instrs.clear(),
1467 InstrumentationMode::BlockAlt => {
1468 self.block_alt = None;
1469 }
1470 }
1471 }
1472
1473 fn is_block_style_op(op: &Operator) -> bool {
1474 matches!(
1475 op,
1476 Operator::Block { .. }
1477 | Operator::Loop { .. }
1478 | Operator::If { .. }
1479 | Operator::Else { .. }
1480 )
1481 }
1482
1483 fn is_branching_op(op: &Operator) -> bool {
1484 matches!(
1485 op,
1486 Operator::Br { .. }
1487 | Operator::BrIf { .. }
1488 | Operator::BrTable { .. }
1489 | Operator::BrOnCast { .. }
1490 | Operator::BrOnCastFail { .. }
1491 | Operator::BrOnNull { .. }
1492 | Operator::BrOnNonNull { .. }
1493 )
1494 }
1495
1496 pub fn get_instr(&self, idx: usize) -> Result<&Operator<'_>> {
1498 match self.current_mode {
1499 None => Err(InstrumentationError(
1500 "Current mode is not set...cannot grab instruction without context!".to_string(),
1501 )),
1502 Some(InstrumentationMode::Before) => Ok(&self.before.instrs[idx]),
1503 Some(InstrumentationMode::After) => Ok(&self.after.instrs[idx]),
1504 Some(InstrumentationMode::Alternate) => match &self.alternate {
1505 None => Err(InstrumentationError(format!(
1506 "No alternate instructions to pull idx '{}' from",
1507 idx
1508 ))),
1509 Some(alternate) => Ok(&alternate.instrs[idx]),
1510 },
1511 Some(InstrumentationMode::SemanticAfter) => Ok(&self.semantic_after.instrs[idx]),
1512 Some(InstrumentationMode::BlockEntry) => Ok(&self.block_entry.instrs[idx]),
1513 Some(InstrumentationMode::BlockExit) => Ok(&self.block_exit.instrs[idx]),
1514 Some(InstrumentationMode::BlockAlt) => match &self.block_alt {
1515 None => Err(InstrumentationError(format!(
1516 "No block alt instructions to pull idx '{}' from",
1517 idx
1518 ))),
1519 Some(block_alt) => Ok(&block_alt.instrs[idx]),
1520 },
1521 }
1522 }
1523
1524 pub fn finish_instr(&mut self) {
1526 self.current_mode = None
1527 }
1528}
1529
1530#[derive(Clone, Debug, Default, Eq, PartialEq)]
1531pub struct InjectedInstrs<'a> {
1532 pub(crate) instrs: Vec<Operator<'a>>,
1533 pub(crate) tag: InjectTag,
1534}
1535impl TagUtils for InjectedInstrs<'_> {
1536 fn get_or_create_tag(&mut self) -> &mut Tag {
1537 self.tag.get_or_insert_default()
1538 }
1539
1540 fn get_tag(&self) -> &Option<Tag> {
1541 &self.tag
1542 }
1543}
1544impl HasInjectTag for InjectedInstrs<'_> {}
1545
1546#[derive(Debug, Clone, Copy)]
1548pub enum Location {
1549 Component {
1550 mod_idx: ModuleID,
1551 func_idx: FunctionID,
1552 instr_idx: usize,
1553 },
1554 Module {
1555 func_idx: FunctionID,
1556 instr_idx: usize,
1557 },
1558}
1559
1560#[derive(Debug, Default, Clone)]
1562pub struct Instructions<'a> {
1563 instructions: Vec<Operator<'a>>,
1564 offsets: Option<Vec<usize>>,
1565 flags: Option<Vec<InstrumentationFlag<'a>>>,
1566}
1567
1568impl<'a> Instructions<'a> {
1569 fn force_flags(&mut self) {
1570 if self.flags.is_none() {
1571 self.flags = Some(vec![
1572 InstrumentationFlag::default();
1573 self.instructions.len()
1574 ]);
1575 }
1576 }
1577
1578 pub fn new(
1579 instructions: Vec<(Operator<'a>, usize)>,
1580 locals_start: usize,
1581 save_offsets: bool,
1582 ) -> Self {
1583 let mut instrs = vec![];
1584 let mut pcs = vec![];
1585 instructions.iter().for_each(|(operator, offset)| {
1586 instrs.push(operator.clone());
1587 pcs.push(*offset - locals_start);
1589 });
1590 Self {
1591 instructions: instrs,
1592 offsets: if save_offsets { Some(pcs) } else { None },
1593 flags: None,
1594 }
1595 }
1596
1597 pub fn get_ops(&self) -> &[Operator<'a>] {
1599 &self.instructions
1600 }
1601
1602 pub fn get_flags(&self) -> Option<&[InstrumentationFlag<'a>]> {
1604 self.flags.as_ref().map(|v| &v[..])
1605 }
1606
1607 pub(crate) fn get_ops_flags_mut(
1609 &mut self,
1610 ) -> (&mut [Operator<'a>], Option<&mut [InstrumentationFlag<'a>]>) {
1611 match &mut self.flags {
1612 Some(flags) => (&mut self.instructions, Some(flags)),
1613 None => (&mut self.instructions, None),
1614 }
1615 }
1616
1617 pub fn get_ops_mut(&mut self) -> Result<&mut Vec<Operator<'a>>> {
1621 if self.flags.is_some() {
1622 return Err(InstrumentationError(
1623 "Cannot get mutable instructions if flags are set. \
1624 Mutating instructions will invalidate instrumentation flags."
1625 .to_string(),
1626 ));
1627 }
1628 Ok(&mut self.instructions)
1629 }
1630
1631 pub fn get_instr_flag(&self, idx: usize) -> Option<&InstrumentationFlag<'a>> {
1632 self.flags.as_ref().and_then(|f| f.get(idx))
1633 }
1634
1635 pub fn push(&mut self, op: Operator<'a>) {
1636 self.instructions.push(op);
1637 if let Some(flags) = &mut self.flags {
1638 flags.push(InstrumentationFlag::default());
1639 }
1640 }
1641
1642 pub fn len(&self) -> usize {
1643 self.instructions.len()
1644 }
1645
1646 pub fn is_empty(&self) -> bool {
1647 self.instructions.is_empty()
1648 }
1649
1650 pub fn add_instr(&mut self, index: usize, op: Operator<'a>) -> bool {
1651 self.force_flags();
1652 self.flags.as_mut().unwrap()[index].add_instr(&self.instructions[index], op)
1653 }
1654
1655 pub fn current_mode(&self, index: usize) -> Option<InstrumentationMode> {
1656 self.flags.as_ref().and_then(|f| f[index].current_mode)
1657 }
1658
1659 pub fn set_current_mode(&mut self, index: usize, mode: InstrumentationMode) {
1660 self.force_flags();
1661 self.flags.as_mut().unwrap()[index].current_mode = Some(mode);
1662 }
1663
1664 pub fn finish_instr(&mut self, index: usize) {
1665 self.force_flags();
1666 self.flags.as_mut().unwrap()[index].finish_instr();
1667 }
1668
1669 pub fn instr_len(&self, index: usize) -> usize {
1670 self.flags
1671 .as_ref()
1672 .map(|f| f[index].instr_len())
1673 .unwrap_or(0)
1674 }
1675
1676 pub fn set_alternate(&mut self, index: usize, alternate: InjectedInstrs<'a>) {
1677 self.force_flags();
1678 self.flags.as_mut().unwrap()[index].alternate = Some(alternate);
1679 }
1680
1681 pub fn set_block_alt(&mut self, index: usize, block_alt: InjectedInstrs<'a>) {
1682 self.force_flags();
1683 self.flags.as_mut().unwrap()[index].block_alt = Some(block_alt);
1684 }
1685
1686 pub fn append_to_tag(&mut self, index: usize, data: Vec<u8>) {
1687 self.force_flags();
1688 self.flags.as_mut().unwrap()[index].append_to_tag(data);
1689 }
1690
1691 pub fn clear_instr(&mut self, idx: usize, mode: InstrumentationMode) {
1692 if let Some(flags) = &mut self.flags {
1693 flags[idx].clear_instr(mode);
1694 }
1695 }
1696
1697 pub fn lookup_pc_offset_for(&self, instr_idx: usize) -> Option<usize> {
1698 if let Some(offsets) = self.offsets.as_ref() {
1699 offsets.get(instr_idx).copied()
1700 } else {
1701 None
1702 }
1703 }
1704}
1705
1706#[derive(Debug, Default, Clone)]
1707pub struct Body<'a> {
1709 pub locals: Vec<(u32, DataType)>,
1715 pub num_locals: u32,
1716 pub instructions: Instructions<'a>,
1717 pub num_instructions: usize,
1718 pub name: Option<String>,
1719}
1720
1721impl<'a, 'b> Body<'a>
1723where
1724 'b: 'a,
1725{
1726 pub fn push_op(&mut self, op: Operator<'b>) {
1728 self.instructions.push(op);
1729 self.num_instructions += 1;
1730 }
1731
1732 pub fn locals_as_vec(&self) -> Vec<DataType> {
1733 let mut locals = vec![];
1734 for (count, ty) in self.locals.iter() {
1735 for _ in 0..*count {
1736 locals.push(*ty);
1737 }
1738 }
1739 locals
1740 }
1741}
1742
1743#[derive(Debug, Clone)]
1746pub struct InitExpr {
1747 pub exprs: Vec<InitInstr>,
1748}
1749
1750#[derive(Debug, Copy, Clone)]
1752pub enum InitInstr {
1753 Value(Value),
1755 Global(GlobalID),
1757 RefNull(RefType),
1759 RefFunc(FunctionID),
1761 StructNew(TypeID),
1763 StructNewDefault(TypeID),
1765 ArrayNew(TypeID),
1767 ArrayNewDefault(TypeID),
1769 RefArrayFixed {
1771 array_type_index: u32,
1772 array_size: u32,
1773 },
1774 RefArrayData {
1776 array_type_index: u32,
1777 array_data_index: u32,
1778 },
1779 RefArrayElem {
1781 array_type_index: u32,
1782 array_elem_index: u32,
1783 },
1784 RefI31,
1785}
1786impl InitInstr {
1787 pub fn fix_id_mapping(
1788 &mut self,
1789 func_mapping: &HashMap<u32, u32>,
1790 global_mapping: &HashMap<u32, u32>,
1791 ) -> types::Result<()> {
1792 match self {
1793 InitInstr::Global(id) => match global_mapping.get(&(*id)) {
1794 Some(new_index) => {
1795 **id = *new_index;
1796 }
1797 None => return Err(InstrumentationError("Deleted global!".to_string())),
1798 },
1799 InitInstr::RefFunc(id) => match func_mapping.get(&(*id)) {
1800 Some(new_index) => {
1801 **id = *new_index;
1802 }
1803 None => return Err(InstrumentationError("Deleted function!".to_string())),
1804 },
1805 _ => {}
1806 }
1807 Ok(())
1808 }
1809}
1810
1811impl InitExpr {
1812 pub fn new(instructions: Vec<InitInstr>) -> Self {
1814 InitExpr {
1815 exprs: instructions,
1816 }
1817 }
1818
1819 pub fn instructions(&self) -> &[InitInstr] {
1820 self.exprs.as_slice()
1821 }
1822
1823 pub(crate) fn eval(init: &ConstExpr) -> Result<InitExpr> {
1824 use wasmparser::Operator::*;
1825 let mut reader = init.get_operators_reader();
1826 let mut instrs = vec![];
1827 loop {
1828 let op = reader.read()?;
1829 let val = match op {
1830 I32Const { value } => InitInstr::Value(Value::I32(value)),
1831 I64Const { value } => InitInstr::Value(Value::I64(value)),
1832 F32Const { value } => InitInstr::Value(Value::F32(f32::from_bits(value.bits()))),
1833 F64Const { value } => InitInstr::Value(Value::F64(f64::from_bits(value.bits()))),
1834 V128Const { value } => InitInstr::Value(Value::V128(v128_to_u128(&value))),
1835 GlobalGet { global_index } => InitInstr::Global(GlobalID(global_index)),
1836 RefNull { hty } => InitInstr::RefNull(RefType::new(true, hty).ok_or_else(|| {
1838 Error::ConversionError(format!(
1839 "ref.null in constant expression references an unrepresentable heap type: {hty:?}"
1840 ))
1841 })?),
1842 RefFunc { function_index } => InitInstr::RefFunc(FunctionID(function_index)),
1843 StructNew { struct_type_index } => InitInstr::StructNew(TypeID(struct_type_index)),
1844 StructNewDefault { struct_type_index } => {
1845 InitInstr::StructNewDefault(TypeID(struct_type_index))
1846 }
1847 ArrayNew { array_type_index } => InitInstr::ArrayNew(TypeID(array_type_index)),
1848 ArrayNewDefault { array_type_index } => {
1849 InitInstr::ArrayNewDefault(TypeID(array_type_index))
1850 }
1851 ArrayNewFixed {
1852 array_type_index,
1853 array_size,
1854 } => InitInstr::RefArrayFixed {
1855 array_type_index,
1856 array_size,
1857 },
1858 ArrayNewData {
1859 array_type_index,
1860 array_data_index,
1861 } => InitInstr::RefArrayData {
1862 array_data_index,
1863 array_type_index,
1864 },
1865 ArrayNewElem {
1866 array_type_index,
1867 array_elem_index,
1868 } => InitInstr::RefArrayElem {
1869 array_type_index,
1870 array_elem_index,
1871 },
1872 RefI31 => InitInstr::RefI31,
1873 End => break,
1874 other => {
1875 return Err(Error::ConversionError(format!(
1876 "unsupported operator in constant expression: {other:?}"
1877 )));
1878 }
1879 };
1880 instrs.push(val);
1881 }
1882 if !reader.eof() {
1883 return Err(Error::ConversionError(
1884 "trailing bytes after `end` in constant expression".to_string(),
1885 ));
1886 }
1887 Ok(InitExpr { exprs: instrs })
1888 }
1889
1890 pub(crate) fn to_wasmencoder_type(&self) -> wasm_encoder::ConstExpr {
1891 let mut bytes = vec![];
1892 for instr in self.exprs.iter() {
1893 match instr {
1894 InitInstr::Value(v) => match v {
1895 Value::I32(v) => wasm_encoder::Instruction::I32Const(*v).encode(&mut bytes),
1896 Value::I64(v) => wasm_encoder::Instruction::I64Const(*v).encode(&mut bytes),
1897 Value::F32(v) => {
1898 wasm_encoder::Instruction::F32Const(Ieee32::from(*v)).encode(&mut bytes)
1899 }
1900 Value::F64(v) => {
1901 wasm_encoder::Instruction::F64Const(Ieee64::from(*v)).encode(&mut bytes)
1902 }
1903 Value::V128(v) => {
1904 wasm_encoder::Instruction::V128Const(*v as i128).encode(&mut bytes)
1905 }
1906 },
1907 InitInstr::Global(g) => {
1908 wasm_encoder::Instruction::GlobalGet(**g).encode(&mut bytes)
1909 }
1910 InitInstr::RefNull(ty) => {
1911 wasm_encoder::Instruction::RefNull(match ty.heap_type() {
1912 HeapType::Abstract { shared, ty } => match ty {
1913 wasmparser::AbstractHeapType::Func => {
1914 wasm_encoder::HeapType::Abstract {
1915 ty: AbstractHeapType::Func,
1916 shared,
1917 }
1918 }
1919 wasmparser::AbstractHeapType::Extern => {
1920 wasm_encoder::HeapType::Abstract {
1921 ty: AbstractHeapType::Extern,
1922 shared,
1923 }
1924 }
1925 wasmparser::AbstractHeapType::Any => wasm_encoder::HeapType::Abstract {
1926 ty: AbstractHeapType::Any,
1927 shared,
1928 },
1929 wasmparser::AbstractHeapType::None => {
1930 wasm_encoder::HeapType::Abstract {
1931 ty: AbstractHeapType::None,
1932 shared,
1933 }
1934 }
1935 wasmparser::AbstractHeapType::NoExtern => {
1936 wasm_encoder::HeapType::Abstract {
1937 ty: AbstractHeapType::NoExtern,
1938 shared,
1939 }
1940 }
1941 wasmparser::AbstractHeapType::NoFunc => {
1942 wasm_encoder::HeapType::Abstract {
1943 ty: AbstractHeapType::NoFunc,
1944 shared,
1945 }
1946 }
1947 wasmparser::AbstractHeapType::Eq => wasm_encoder::HeapType::Abstract {
1948 ty: AbstractHeapType::Eq,
1949 shared,
1950 },
1951 wasmparser::AbstractHeapType::Struct => {
1952 wasm_encoder::HeapType::Abstract {
1953 ty: AbstractHeapType::Struct,
1954 shared,
1955 }
1956 }
1957 wasmparser::AbstractHeapType::Array => {
1958 wasm_encoder::HeapType::Abstract {
1959 ty: AbstractHeapType::Array,
1960 shared,
1961 }
1962 }
1963 wasmparser::AbstractHeapType::I31 => wasm_encoder::HeapType::Abstract {
1964 ty: AbstractHeapType::I31,
1965 shared,
1966 },
1967 wasmparser::AbstractHeapType::Exn => wasm_encoder::HeapType::Abstract {
1968 ty: AbstractHeapType::Exn,
1969 shared,
1970 },
1971 wasmparser::AbstractHeapType::NoExn => {
1972 wasm_encoder::HeapType::Abstract {
1973 ty: AbstractHeapType::NoExn,
1974 shared,
1975 }
1976 }
1977 wasmparser::AbstractHeapType::Cont => {
1978 wasm_encoder::HeapType::Abstract {
1979 ty: AbstractHeapType::Cont,
1980 shared,
1981 }
1982 }
1983 wasmparser::AbstractHeapType::NoCont => {
1984 wasm_encoder::HeapType::Abstract {
1985 ty: AbstractHeapType::NoCont,
1986 shared,
1987 }
1988 }
1989 },
1990 HeapType::Concrete(id) => {
1991 if let Some(mod_id) = id.as_module_index() {
1992 wasm_encoder::HeapType::Concrete(mod_id)
1993 } else if let Some(rg_id) = id.as_rec_group_index() {
1994 wasm_encoder::HeapType::Concrete(rg_id)
1995 } else if let Some(core) = id.as_core_type_id() {
1996 wasm_encoder::HeapType::Concrete(core.index() as u32)
1997 } else {
1998 unimplemented!("Did not unpack concrete type!")
1999 }
2000 }
2001 HeapType::Exact(id) => {
2002 if let Some(mod_id) = id.as_module_index() {
2003 wasm_encoder::HeapType::Exact(mod_id)
2004 } else if let Some(rg_id) = id.as_rec_group_index() {
2005 wasm_encoder::HeapType::Exact(rg_id)
2006 } else if let Some(core) = id.as_core_type_id() {
2007 wasm_encoder::HeapType::Exact(core.index() as u32)
2008 } else {
2009 unimplemented!("Did not unpack exact type!")
2010 }
2011 }
2012 })
2013 .encode(&mut bytes)
2014 }
2015 InitInstr::RefFunc(f) => wasm_encoder::Instruction::RefFunc(**f).encode(&mut bytes),
2016 InitInstr::StructNew(id) => {
2017 wasm_encoder::Instruction::StructNew(**id).encode(&mut bytes);
2018 }
2019 InitInstr::ArrayNew(id) => {
2020 wasm_encoder::Instruction::ArrayNew(**id).encode(&mut bytes);
2021 }
2022
2023 InitInstr::StructNewDefault(id) => {
2024 wasm_encoder::Instruction::StructNewDefault(**id).encode(&mut bytes);
2025 }
2026 InitInstr::ArrayNewDefault(id) => {
2027 wasm_encoder::Instruction::ArrayNewDefault(**id).encode(&mut bytes);
2028 }
2029 InitInstr::RefArrayFixed {
2030 array_type_index,
2031 array_size,
2032 } => {
2033 wasm_encoder::Instruction::ArrayNewFixed {
2034 array_size: *array_size,
2035 array_type_index: *array_type_index,
2036 }
2037 .encode(&mut bytes);
2038 }
2039 InitInstr::RefArrayData {
2040 array_type_index,
2041 array_data_index,
2042 } => {
2043 wasm_encoder::Instruction::ArrayNewData {
2044 array_data_index: *array_data_index,
2045 array_type_index: *array_type_index,
2046 }
2047 .encode(&mut bytes);
2048 }
2049 InitInstr::RefArrayElem {
2050 array_type_index,
2051 array_elem_index,
2052 } => {
2053 wasm_encoder::Instruction::ArrayNewElem {
2054 array_elem_index: *array_elem_index,
2055 array_type_index: *array_type_index,
2056 }
2057 .encode(&mut bytes);
2058 }
2059 InitInstr::RefI31 => wasm_encoder::Instruction::RefI31.encode(&mut bytes),
2060 }
2061 }
2062 wasm_encoder::ConstExpr::raw(bytes)
2063 }
2064}
2065
2066#[derive(Debug, Clone, Copy)]
2068pub enum Value {
2069 I32(i32),
2071 I64(i64),
2073 F32(f32),
2075 F64(f64),
2077 V128(u128),
2079}
2080
2081impl fmt::Display for Value {
2082 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
2083 match self {
2084 Value::I32(i) => i.fmt(f),
2085 Value::I64(i) => i.fmt(f),
2086 Value::F32(i) => i.fmt(f),
2087 Value::F64(i) => i.fmt(f),
2088 Value::V128(i) => i.fmt(f),
2089 }
2090 }
2091}
2092
2093#[derive(Debug, Copy, Clone, PartialEq, Eq)]
2094pub enum BlockType {
2095 Empty,
2097 Type(DataType),
2099 FuncType(TypeID),
2103}
2104
2105impl From<wasmparser::BlockType> for BlockType {
2106 fn from(value: wasmparser::BlockType) -> Self {
2107 match value {
2108 wasmparser::BlockType::Empty => BlockType::Empty,
2109 wasmparser::BlockType::FuncType(u) => BlockType::FuncType(TypeID(u)),
2110 wasmparser::BlockType::Type(val) => BlockType::Type(DataType::from(val)),
2111 }
2112 }
2113}
2114
2115impl From<BlockType> for wasmparser::BlockType {
2116 fn from(ty: BlockType) -> Self {
2117 match ty {
2118 BlockType::Empty => wasmparser::BlockType::Empty,
2119 BlockType::FuncType(u) => wasmparser::BlockType::FuncType(*u),
2120 BlockType::Type(data) => wasmparser::BlockType::Type(ValType::from(&data)),
2121 }
2122 }
2123}
2124
2125#[derive(Clone, Debug, Default)]
2127pub struct CustomSections<'a> {
2128 pub(crate) custom_sections: Vec<CustomSection<'a>>,
2130}
2131
2132impl<'a> CustomSections<'a> {
2133 pub fn new(custom_sections: Vec<(&'a str, &'a [u8])>) -> Self {
2134 CustomSections {
2135 custom_sections: custom_sections
2136 .iter()
2137 .map(|cs| CustomSection::new_borrowed(cs.0, cs.1))
2138 .collect(),
2139 }
2140 }
2141
2142 pub fn get_id(&self, name: String) -> Option<CustomSectionID> {
2144 for (index, section) in self.custom_sections.iter().enumerate() {
2145 if section.name == name {
2146 return Some(CustomSectionID(index as u32));
2147 }
2148 }
2149 None
2150 }
2151
2152 pub fn get_by_id(&self, custom_section_id: CustomSectionID) -> Result<&CustomSection<'_>> {
2154 if *custom_section_id >= self.custom_sections.len() as u32 {
2155 Err(UnknownId("Invalid custom section ID!".into()))
2156 } else {
2157 Ok(&self.custom_sections[*custom_section_id as usize])
2158 }
2159 }
2160
2161 pub fn len(&self) -> usize {
2163 self.custom_sections.len()
2164 }
2165
2166 pub fn is_empty(&self) -> bool {
2168 self.custom_sections.is_empty()
2169 }
2170
2171 pub fn iter(&self) -> Iter<'_, CustomSection<'a>> {
2173 self.custom_sections.iter()
2174 }
2175
2176 pub fn get_section_data_mut(&mut self, section_id: CustomSectionID) -> Option<&mut Vec<u8>> {
2178 if *section_id < self.custom_sections.len() as u32 {
2179 Some(self.custom_sections[*section_id as usize].data.to_mut())
2180 } else {
2181 None
2182 }
2183 }
2184
2185 pub(crate) fn add(&mut self, section: CustomSection<'a>) -> CustomSectionID {
2187 let id = CustomSectionID(self.custom_sections.len() as u32);
2188 self.custom_sections.push(section);
2189 id
2190 }
2191}
2192
2193#[derive(Clone, Debug)]
2195pub struct CustomSection<'a> {
2196 pub name: &'a str,
2197 pub data: Cow<'a, [u8]>,
2198 pub deleted: bool,
2199}
2200
2201impl<'a> CustomSection<'a> {
2202 pub fn new(name: &'a str, data: Vec<u8>) -> Self {
2204 CustomSection {
2205 name,
2206 data: Cow::Owned(data),
2207 deleted: false,
2208 }
2209 }
2210
2211 fn new_borrowed(name: &'a str, data: &'a [u8]) -> Self {
2213 CustomSection {
2214 name,
2215 data: Cow::Borrowed(data),
2216 deleted: false,
2217 }
2218 }
2219}
2220
2221#[allow(clippy::identity_op)]
2222pub(crate) fn v128_to_u128(value: &wasmparser::V128) -> u128 {
2223 let n = value.bytes();
2224 ((n[0] as u128) << 0)
2225 | ((n[1] as u128) << 8)
2226 | ((n[2] as u128) << 16)
2227 | ((n[3] as u128) << 24)
2228 | ((n[4] as u128) << 32)
2229 | ((n[5] as u128) << 40)
2230 | ((n[6] as u128) << 48)
2231 | ((n[7] as u128) << 56)
2232 | ((n[8] as u128) << 64)
2233 | ((n[9] as u128) << 72)
2234 | ((n[10] as u128) << 80)
2235 | ((n[11] as u128) << 88)
2236 | ((n[12] as u128) << 96)
2237 | ((n[13] as u128) << 104)
2238 | ((n[14] as u128) << 112)
2239 | ((n[15] as u128) << 120)
2240}