github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/marshal/marshal.go (about) 1 // Copyright 2019 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package marshal defines the Marshallable interface for 16 // serialize/deserializing go data structures to/from memory, according to the 17 // Linux ABI. 18 // 19 // Implementations of this interface are typically automatically generated by 20 // tools/go_marshal. See the go_marshal README for details. 21 package marshal 22 23 import ( 24 "io" 25 26 "github.com/SagerNet/gvisor/pkg/hostarch" 27 ) 28 29 // CopyContext defines the memory operations required to marshal to and from 30 // user memory. Typically, kernel.Task is used to provide implementations for 31 // these operations. 32 type CopyContext interface { 33 // CopyScratchBuffer provides a task goroutine-local scratch buffer. See 34 // kernel.CopyScratchBuffer. 35 CopyScratchBuffer(size int) []byte 36 37 // CopyOutBytes writes the contents of b to the task's memory. See 38 // kernel.CopyOutBytes. 39 CopyOutBytes(addr hostarch.Addr, b []byte) (int, error) 40 41 // CopyInBytes reads the contents of the task's memory to b. See 42 // kernel.CopyInBytes. 43 CopyInBytes(addr hostarch.Addr, b []byte) (int, error) 44 } 45 46 // Marshallable represents operations on a type that can be marshalled to and 47 // from memory. 48 // 49 // go-marshal automatically generates implementations for this interface for 50 // types marked as '+marshal'. 51 type Marshallable interface { 52 io.WriterTo 53 54 // SizeBytes is the size of the memory representation of a type in 55 // marshalled form. 56 // 57 // SizeBytes must handle a nil receiver. Practically, this means SizeBytes 58 // cannot deference any fields on the object implementing it (but will 59 // likely make use of the type of these fields). 60 SizeBytes() int 61 62 // MarshalBytes serializes a copy of a type to dst. 63 // Precondition: dst must be at least SizeBytes() in length. 64 MarshalBytes(dst []byte) 65 66 // UnmarshalBytes deserializes a type from src. 67 // Precondition: src must be at least SizeBytes() in length. 68 UnmarshalBytes(src []byte) 69 70 // Packed returns true if the marshalled size of the type is the same as the 71 // size it occupies in memory. This happens when the type has no fields 72 // starting at unaligned addresses (should always be true by default for ABI 73 // structs, verified by automatically generated tests when using 74 // go_marshal), and has no fields marked `marshal:"unaligned"`. 75 // 76 // Packed must return the same result for all possible values of the type 77 // implementing it. Violating this constraint implies the type doesn't have 78 // a static memory layout, and will lead to memory corruption. 79 // Go-marshal-generated code reuses the result of Packed for multiple values 80 // of the same type. 81 Packed() bool 82 83 // MarshalUnsafe serializes a type by bulk copying its in-memory 84 // representation to the dst buffer. This is only safe to do when the type 85 // has no implicit padding, see Marshallable.Packed. When Packed would 86 // return false, MarshalUnsafe should fall back to the safer but slower 87 // MarshalBytes. 88 // Precondition: dst must be at least SizeBytes() in length. 89 MarshalUnsafe(dst []byte) 90 91 // UnmarshalUnsafe deserializes a type by directly copying to the underlying 92 // memory allocated for the object by the runtime. 93 // 94 // This allows much faster unmarshalling of types which have no implicit 95 // padding, see Marshallable.Packed. When Packed would return false, 96 // UnmarshalUnsafe should fall back to the safer but slower unmarshal 97 // mechanism implemented in UnmarshalBytes. 98 // Precondition: src must be at least SizeBytes() in length. 99 UnmarshalUnsafe(src []byte) 100 101 // CopyIn deserializes a Marshallable type from a task's memory. This may 102 // only be called from a task goroutine. This is more efficient than calling 103 // UnmarshalUnsafe on Marshallable.Packed types, as the type being 104 // marshalled does not escape. The implementation should avoid creating 105 // extra copies in memory by directly deserializing to the object's 106 // underlying memory. 107 // 108 // If the copy-in from the task memory is only partially successful, CopyIn 109 // should still attempt to deserialize as much data as possible. See comment 110 // for UnmarshalBytes. 111 CopyIn(cc CopyContext, addr hostarch.Addr) (int, error) 112 113 // CopyOut serializes a Marshallable type to a task's memory. This may only 114 // be called from a task goroutine. This is more efficient than calling 115 // MarshalUnsafe on Marshallable.Packed types, as the type being serialized 116 // does not escape. The implementation should avoid creating extra copies in 117 // memory by directly serializing from the object's underlying memory. 118 // 119 // The copy-out to the task memory may be partially successful, in which 120 // case CopyOut returns how much data was serialized. See comment for 121 // MarshalBytes for implications. 122 CopyOut(cc CopyContext, addr hostarch.Addr) (int, error) 123 124 // CopyOutN is like CopyOut, but explicitly requests a partial 125 // copy-out. Note that this may yield unexpected results for non-packed 126 // types and the caller may only want to allow this for packed types. See 127 // comment on MarshalBytes. 128 // 129 // The limit must be less than or equal to SizeBytes(). 130 CopyOutN(cc CopyContext, addr hostarch.Addr, limit int) (int, error) 131 } 132 133 // go-marshal generates additional functions for a type based on additional 134 // clauses to the +marshal directive. They are documented below. 135 // 136 // Slice API 137 // ========= 138 // 139 // Adding a "slice" clause to the +marshal directive for structs or newtypes on 140 // primitives like this: 141 // 142 // // +marshal slice:FooSlice 143 // type Foo struct { ... } 144 // 145 // Generates four additional functions for marshalling slices of Foos like this: 146 // 147 // // MarshalUnsafeFooSlice is like Foo.MarshalUnsafe, buf for a []Foo. It 148 // // might be more efficient that repeatedly calling Foo.MarshalUnsafe 149 // // over a []Foo in a loop if the type is Packed. 150 // // Preconditions: dst must be at least len(src)*Foo.SizeBytes() in length. 151 // func MarshalUnsafeFooSlice(src []Foo, dst []byte) (int, error) { ... } 152 // 153 // // UnmarshalUnsafeFooSlice is like Foo.UnmarshalUnsafe, buf for a []Foo. It 154 // // might be more efficient that repeatedly calling Foo.UnmarshalUnsafe 155 // // over a []Foo in a loop if the type is Packed. 156 // // Preconditions: src must be at least len(dst)*Foo.SizeBytes() in length. 157 // func UnmarshalUnsafeFooSlice(dst []Foo, src []byte) (int, error) { ... } 158 // 159 // // CopyFooSliceIn copies in a slice of Foo objects from the task's memory. 160 // func CopyFooSliceIn(cc marshal.CopyContext, addr hostarch.Addr, dst []Foo) (int, error) { ... } 161 // 162 // // CopyFooSliceIn copies out a slice of Foo objects to the task's memory. 163 // func CopyFooSliceOut(cc marshal.CopyContext, addr hostarch.Addr, src []Foo) (int, error) { ... } 164 // 165 // The name of the functions are of the format "Copy%sIn" and "Copy%sOut", where 166 // %s is the first argument to the slice clause. This directive is not supported 167 // for newtypes on arrays. 168 // 169 // Note: Partial copies are not supported for Slice API UnmarshalUnsafe and 170 // MarshalUnsafe. 171 // 172 // The slice clause also takes an optional second argument, which must be the 173 // value "inner": 174 // 175 // // +marshal slice:Int32Slice:inner 176 // type Int32 int32 177 // 178 // This is only valid on newtypes on primitives, and causes the generated 179 // functions to accept slices of the inner type instead: 180 // 181 // func CopyInt32SliceIn(cc marshal.CopyContext, addr hostarch.Addr, dst []int32) (int, error) { ... } 182 // 183 // Without "inner", they would instead be: 184 // 185 // func CopyInt32SliceIn(cc marshal.CopyContext, addr hostarch.Addr, dst []Int32) (int, error) { ... } 186 // 187 // This may help avoid a cast depending on how the generated functions are used.