wasmer_compiler/types/
section.rs

1/*
2 * ! Remove me once rkyv generates doc-comments for fields or generates an #[allow(missing_docs)]
3 * on their own.
4 */
5#![allow(missing_docs)]
6
7//! This module define the required structures to emit custom
8//! Sections in a `Compilation`.
9//!
10//! The functions that access a custom [`CustomSection`] would need
11//! to emit a custom relocation: `RelocationTarget::CustomSection`, so
12//! it can be patched later by the engine (native or JIT).
13
14use super::relocation::{ArchivedRelocation, Relocation, RelocationLike};
15use crate::lib::std::vec::Vec;
16use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
17#[cfg(feature = "enable-serde")]
18use serde::{Deserialize, Serialize};
19use wasmer_types::entity_impl;
20
21/// Index type of a Section defined inside a WebAssembly `Compilation`.
22#[derive(
23    RkyvSerialize,
24    RkyvDeserialize,
25    Archive,
26    Copy,
27    Clone,
28    PartialEq,
29    Eq,
30    Hash,
31    PartialOrd,
32    Ord,
33    Debug,
34    Default,
35)]
36#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
37#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
38#[rkyv(derive(Debug, Hash, PartialEq, Eq), compare(PartialEq, PartialOrd))]
39pub struct SectionIndex(u32);
40
41entity_impl!(SectionIndex);
42
43/// Custom section Protection.
44///
45/// Determines how a custom section may be used.
46#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
47#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
48#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
49#[rkyv(derive(Debug), compare(PartialEq, PartialOrd))]
50#[repr(u8)]
51pub enum CustomSectionProtection {
52    /// A custom section with read permission.
53    Read,
54
55    /// A custom section with read and execute permissions.
56    ReadExecute,
57}
58
59/// A Section for a `Compilation`.
60///
61/// This is used so compilers can store arbitrary information
62/// in the emitted module.
63#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
64#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
65#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
66#[rkyv(derive(Debug), compare(PartialEq))]
67pub struct CustomSection {
68    /// Memory protection that applies to this section.
69    pub protection: CustomSectionProtection,
70
71    /// Alignment of this section. When missing, the default value for
72    /// each platform shall be used.
73    pub alignment: Option<u64>,
74
75    /// The bytes corresponding to this section.
76    ///
77    /// > Note: These bytes have to be at-least 8-byte aligned
78    /// > (the start of the memory pointer).
79    /// > We might need to create another field for alignment in case it's
80    /// > needed in the future.
81    pub bytes: SectionBody,
82
83    /// Relocations that apply to this custom section.
84    pub relocations: Vec<Relocation>,
85}
86
87/// Any struct that acts like a `CustomSection`.
88#[allow(missing_docs)]
89pub trait CustomSectionLike<'a> {
90    type Relocations: RelocationLike;
91
92    fn protection(&self) -> CustomSectionProtection;
93    fn alignment(&self) -> Option<u64>;
94    fn bytes(&self) -> &[u8];
95    fn relocations(&'a self) -> &[Self::Relocations];
96}
97
98impl<'a> CustomSectionLike<'a> for CustomSection {
99    type Relocations = Relocation;
100
101    fn protection(&self) -> CustomSectionProtection {
102        self.protection.clone()
103    }
104
105    fn alignment(&self) -> Option<u64> {
106        self.alignment
107    }
108
109    fn bytes(&self) -> &[u8] {
110        self.bytes.0.as_ref()
111    }
112
113    fn relocations(&'a self) -> &[Self::Relocations] {
114        self.relocations.as_slice()
115    }
116}
117
118impl<'a> CustomSectionLike<'a> for ArchivedCustomSection {
119    type Relocations = ArchivedRelocation;
120
121    fn protection(&self) -> CustomSectionProtection {
122        let protection = rkyv::deserialize::<CustomSectionProtection, ()>(&self.protection);
123        protection.unwrap()
124    }
125
126    fn alignment(&self) -> Option<u64> {
127        let alignment = rkyv::deserialize::<Option<u64>, ()>(&self.alignment);
128        alignment.unwrap()
129    }
130
131    fn bytes(&self) -> &[u8] {
132        self.bytes.0.as_ref()
133    }
134
135    fn relocations(&'a self) -> &[Self::Relocations] {
136        self.relocations.as_slice()
137    }
138}
139
140/// The bytes in the section.
141#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
142#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
143#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq, Default)]
144#[rkyv(derive(Debug), compare(PartialEq, PartialOrd))]
145pub struct SectionBody(#[cfg_attr(feature = "enable-serde", serde(with = "serde_bytes"))] Vec<u8>);
146
147impl SectionBody {
148    /// Create a new section body with the given contents.
149    pub fn new_with_vec(contents: Vec<u8>) -> Self {
150        Self(contents)
151    }
152
153    /// Returns a raw pointer to the section's buffer.
154    pub fn as_ptr(&self) -> *const u8 {
155        self.0.as_ptr()
156    }
157
158    /// Returns the length of this section in bytes.
159    pub fn len(&self) -> usize {
160        self.0.len()
161    }
162
163    /// Dereferences into the section's buffer.
164    pub fn as_slice(&self) -> &[u8] {
165        self.0.as_slice()
166    }
167
168    /// Returns whether or not the section body is empty.
169    pub fn is_empty(&self) -> bool {
170        self.0.is_empty()
171    }
172}
173
174impl ArchivedSectionBody {
175    /// Returns the length of this section in bytes.
176    pub fn len(&self) -> usize {
177        self.0.len()
178    }
179
180    /// Returns whether or not the section body is empty.
181    pub fn is_empty(&self) -> bool {
182        self.0.is_empty()
183    }
184}