summaryrefslogtreecommitdiffhomepage
path: root/pkg
diff options
context:
space:
mode:
authorgVisor bot <gvisor-bot@google.com>2021-05-04 23:55:46 +0000
committergVisor bot <gvisor-bot@google.com>2021-05-04 23:55:46 +0000
commitae3ce097bd142f8d8cf059f2ace92c164421af9c (patch)
treeca3507d14c1f2626119e92622bd6c45834398bbe /pkg
parent3207672c9e2b3f3603f76e7aa801f63cb30a8fe0 (diff)
parent689b369f5788c15f9b018246baa4e318082c0d79 (diff)
Merge release-20210419.0-64-g689b369f5 (automated)
Diffstat (limited to 'pkg')
-rw-r--r--pkg/abi/linux/elf.go50
-rw-r--r--pkg/abi/linux/epoll.go6
-rw-r--r--pkg/abi/linux/file.go5
-rw-r--r--pkg/abi/linux/linux_abi_autogen_unsafe.go391
-rw-r--r--pkg/abi/linux/netdevice.go4
-rw-r--r--pkg/binary/binary.go266
-rw-r--r--pkg/binary/binary_state_autogen.go3
-rw-r--r--pkg/compressio/compressio.go41
-rw-r--r--pkg/sentry/loader/elf.go14
-rw-r--r--pkg/sentry/loader/loader_abi_autogen_unsafe.go13
-rw-r--r--pkg/state/statefile/statefile.go21
11 files changed, 512 insertions, 302 deletions
diff --git a/pkg/abi/linux/elf.go b/pkg/abi/linux/elf.go
index 7c9a02f20..c5713541f 100644
--- a/pkg/abi/linux/elf.go
+++ b/pkg/abi/linux/elf.go
@@ -106,3 +106,53 @@ const (
// NT_ARM_TLS is for ARM TLS register.
NT_ARM_TLS = 0x401
)
+
+// ElfHeader64 is the ELF64 file header.
+//
+// +marshal
+type ElfHeader64 struct {
+ Ident [16]byte // File identification.
+ Type uint16 // File type.
+ Machine uint16 // Machine architecture.
+ Version uint32 // ELF format version.
+ Entry uint64 // Entry point.
+ Phoff uint64 // Program header file offset.
+ Shoff uint64 // Section header file offset.
+ Flags uint32 // Architecture-specific flags.
+ Ehsize uint16 // Size of ELF header in bytes.
+ Phentsize uint16 // Size of program header entry.
+ Phnum uint16 // Number of program header entries.
+ Shentsize uint16 // Size of section header entry.
+ Shnum uint16 // Number of section header entries.
+ Shstrndx uint16 // Section name strings section.
+}
+
+// ElfSection64 is the ELF64 Section header.
+//
+// +marshal
+type ElfSection64 struct {
+ Name uint32 // Section name (index into the section header string table).
+ Type uint32 // Section type.
+ Flags uint64 // Section flags.
+ Addr uint64 // Address in memory image.
+ Off uint64 // Offset in file.
+ Size uint64 // Size in bytes.
+ Link uint32 // Index of a related section.
+ Info uint32 // Depends on section type.
+ Addralign uint64 // Alignment in bytes.
+ Entsize uint64 // Size of each entry in section.
+}
+
+// ElfProg64 is the ELF64 Program header.
+//
+// +marshal
+type ElfProg64 struct {
+ Type uint32 // Entry type.
+ Flags uint32 // Access permission flags.
+ Off uint64 // File offset of contents.
+ Vaddr uint64 // Virtual address in memory image.
+ Paddr uint64 // Physical address (not used).
+ Filesz uint64 // Size of contents in file.
+ Memsz uint64 // Size of contents in memory.
+ Align uint64 // Alignment in memory and file.
+}
diff --git a/pkg/abi/linux/epoll.go b/pkg/abi/linux/epoll.go
index 1121a1a92..67706f5aa 100644
--- a/pkg/abi/linux/epoll.go
+++ b/pkg/abi/linux/epoll.go
@@ -14,10 +14,6 @@
package linux
-import (
- "gvisor.dev/gvisor/pkg/binary"
-)
-
// Event masks.
const (
EPOLLIN = 0x1
@@ -59,4 +55,4 @@ const (
)
// SizeOfEpollEvent is the size of EpollEvent struct.
-var SizeOfEpollEvent = int(binary.Size(EpollEvent{}))
+var SizeOfEpollEvent = (*EpollEvent)(nil).SizeBytes()
diff --git a/pkg/abi/linux/file.go b/pkg/abi/linux/file.go
index e11ca2d62..1e23850a9 100644
--- a/pkg/abi/linux/file.go
+++ b/pkg/abi/linux/file.go
@@ -19,7 +19,6 @@ import (
"strings"
"gvisor.dev/gvisor/pkg/abi"
- "gvisor.dev/gvisor/pkg/binary"
)
// Constants for open(2).
@@ -201,7 +200,7 @@ const (
)
// SizeOfStat is the size of a Stat struct.
-var SizeOfStat = binary.Size(Stat{})
+var SizeOfStat = (*Stat)(nil).SizeBytes()
// Flags for statx.
const (
@@ -268,7 +267,7 @@ type Statx struct {
}
// SizeOfStatx is the size of a Statx struct.
-var SizeOfStatx = binary.Size(Statx{})
+var SizeOfStatx = (*Statx)(nil).SizeBytes()
// FileMode represents a mode_t.
type FileMode uint16
diff --git a/pkg/abi/linux/linux_abi_autogen_unsafe.go b/pkg/abi/linux/linux_abi_autogen_unsafe.go
index 4a267d833..b77c2c972 100644
--- a/pkg/abi/linux/linux_abi_autogen_unsafe.go
+++ b/pkg/abi/linux/linux_abi_autogen_unsafe.go
@@ -27,6 +27,9 @@ var _ marshal.Marshallable = (*ControlMessageCredentials)(nil)
var _ marshal.Marshallable = (*ControlMessageHeader)(nil)
var _ marshal.Marshallable = (*ControlMessageIPPacketInfo)(nil)
var _ marshal.Marshallable = (*DigestMetadata)(nil)
+var _ marshal.Marshallable = (*ElfHeader64)(nil)
+var _ marshal.Marshallable = (*ElfProg64)(nil)
+var _ marshal.Marshallable = (*ElfSection64)(nil)
var _ marshal.Marshallable = (*ErrorName)(nil)
var _ marshal.Marshallable = (*ExtensionName)(nil)
var _ marshal.Marshallable = (*FOwnerEx)(nil)
@@ -814,6 +817,394 @@ func (c *CapUserHeader) WriteTo(writer io.Writer) (int64, error) {
}
// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (e *ElfHeader64) SizeBytes() int {
+ return 48 +
+ 1*16
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (e *ElfHeader64) MarshalBytes(dst []byte) {
+ for idx := 0; idx < 16; idx++ {
+ dst[0] = byte(e.Ident[idx])
+ dst = dst[1:]
+ }
+ hostarch.ByteOrder.PutUint16(dst[:2], uint16(e.Type))
+ dst = dst[2:]
+ hostarch.ByteOrder.PutUint16(dst[:2], uint16(e.Machine))
+ dst = dst[2:]
+ hostarch.ByteOrder.PutUint32(dst[:4], uint32(e.Version))
+ dst = dst[4:]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(e.Entry))
+ dst = dst[8:]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(e.Phoff))
+ dst = dst[8:]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(e.Shoff))
+ dst = dst[8:]
+ hostarch.ByteOrder.PutUint32(dst[:4], uint32(e.Flags))
+ dst = dst[4:]
+ hostarch.ByteOrder.PutUint16(dst[:2], uint16(e.Ehsize))
+ dst = dst[2:]
+ hostarch.ByteOrder.PutUint16(dst[:2], uint16(e.Phentsize))
+ dst = dst[2:]
+ hostarch.ByteOrder.PutUint16(dst[:2], uint16(e.Phnum))
+ dst = dst[2:]
+ hostarch.ByteOrder.PutUint16(dst[:2], uint16(e.Shentsize))
+ dst = dst[2:]
+ hostarch.ByteOrder.PutUint16(dst[:2], uint16(e.Shnum))
+ dst = dst[2:]
+ hostarch.ByteOrder.PutUint16(dst[:2], uint16(e.Shstrndx))
+ dst = dst[2:]
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (e *ElfHeader64) UnmarshalBytes(src []byte) {
+ for idx := 0; idx < 16; idx++ {
+ e.Ident[idx] = src[0]
+ src = src[1:]
+ }
+ e.Type = uint16(hostarch.ByteOrder.Uint16(src[:2]))
+ src = src[2:]
+ e.Machine = uint16(hostarch.ByteOrder.Uint16(src[:2]))
+ src = src[2:]
+ e.Version = uint32(hostarch.ByteOrder.Uint32(src[:4]))
+ src = src[4:]
+ e.Entry = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+ e.Phoff = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+ e.Shoff = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+ e.Flags = uint32(hostarch.ByteOrder.Uint32(src[:4]))
+ src = src[4:]
+ e.Ehsize = uint16(hostarch.ByteOrder.Uint16(src[:2]))
+ src = src[2:]
+ e.Phentsize = uint16(hostarch.ByteOrder.Uint16(src[:2]))
+ src = src[2:]
+ e.Phnum = uint16(hostarch.ByteOrder.Uint16(src[:2]))
+ src = src[2:]
+ e.Shentsize = uint16(hostarch.ByteOrder.Uint16(src[:2]))
+ src = src[2:]
+ e.Shnum = uint16(hostarch.ByteOrder.Uint16(src[:2]))
+ src = src[2:]
+ e.Shstrndx = uint16(hostarch.ByteOrder.Uint16(src[:2]))
+ src = src[2:]
+}
+
+// Packed implements marshal.Marshallable.Packed.
+//go:nosplit
+func (e *ElfHeader64) Packed() bool {
+ return true
+}
+
+// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
+func (e *ElfHeader64) MarshalUnsafe(dst []byte) {
+ gohacks.Memmove(unsafe.Pointer(&dst[0]), unsafe.Pointer(e), uintptr(e.SizeBytes()))
+}
+
+// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
+func (e *ElfHeader64) UnmarshalUnsafe(src []byte) {
+ gohacks.Memmove(unsafe.Pointer(e), unsafe.Pointer(&src[0]), uintptr(e.SizeBytes()))
+}
+
+// CopyOutN implements marshal.Marshallable.CopyOutN.
+//go:nosplit
+func (e *ElfHeader64) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(e)))
+ hdr.Len = e.SizeBytes()
+ hdr.Cap = e.SizeBytes()
+
+ length, err := cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that e
+ // must live until the use above.
+ runtime.KeepAlive(e) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// CopyOut implements marshal.Marshallable.CopyOut.
+//go:nosplit
+func (e *ElfHeader64) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ return e.CopyOutN(cc, addr, e.SizeBytes())
+}
+
+// CopyIn implements marshal.Marshallable.CopyIn.
+//go:nosplit
+func (e *ElfHeader64) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(e)))
+ hdr.Len = e.SizeBytes()
+ hdr.Cap = e.SizeBytes()
+
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that e
+ // must live until the use above.
+ runtime.KeepAlive(e) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// WriteTo implements io.WriterTo.WriteTo.
+func (e *ElfHeader64) WriteTo(writer io.Writer) (int64, error) {
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(e)))
+ hdr.Len = e.SizeBytes()
+ hdr.Cap = e.SizeBytes()
+
+ length, err := writer.Write(buf)
+ // Since we bypassed the compiler's escape analysis, indicate that e
+ // must live until the use above.
+ runtime.KeepAlive(e) // escapes: replaced by intrinsic.
+ return int64(length), err
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (e *ElfProg64) SizeBytes() int {
+ return 56
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (e *ElfProg64) MarshalBytes(dst []byte) {
+ hostarch.ByteOrder.PutUint32(dst[:4], uint32(e.Type))
+ dst = dst[4:]
+ hostarch.ByteOrder.PutUint32(dst[:4], uint32(e.Flags))
+ dst = dst[4:]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(e.Off))
+ dst = dst[8:]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(e.Vaddr))
+ dst = dst[8:]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(e.Paddr))
+ dst = dst[8:]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(e.Filesz))
+ dst = dst[8:]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(e.Memsz))
+ dst = dst[8:]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(e.Align))
+ dst = dst[8:]
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (e *ElfProg64) UnmarshalBytes(src []byte) {
+ e.Type = uint32(hostarch.ByteOrder.Uint32(src[:4]))
+ src = src[4:]
+ e.Flags = uint32(hostarch.ByteOrder.Uint32(src[:4]))
+ src = src[4:]
+ e.Off = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+ e.Vaddr = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+ e.Paddr = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+ e.Filesz = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+ e.Memsz = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+ e.Align = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+}
+
+// Packed implements marshal.Marshallable.Packed.
+//go:nosplit
+func (e *ElfProg64) Packed() bool {
+ return true
+}
+
+// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
+func (e *ElfProg64) MarshalUnsafe(dst []byte) {
+ gohacks.Memmove(unsafe.Pointer(&dst[0]), unsafe.Pointer(e), uintptr(e.SizeBytes()))
+}
+
+// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
+func (e *ElfProg64) UnmarshalUnsafe(src []byte) {
+ gohacks.Memmove(unsafe.Pointer(e), unsafe.Pointer(&src[0]), uintptr(e.SizeBytes()))
+}
+
+// CopyOutN implements marshal.Marshallable.CopyOutN.
+//go:nosplit
+func (e *ElfProg64) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(e)))
+ hdr.Len = e.SizeBytes()
+ hdr.Cap = e.SizeBytes()
+
+ length, err := cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that e
+ // must live until the use above.
+ runtime.KeepAlive(e) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// CopyOut implements marshal.Marshallable.CopyOut.
+//go:nosplit
+func (e *ElfProg64) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ return e.CopyOutN(cc, addr, e.SizeBytes())
+}
+
+// CopyIn implements marshal.Marshallable.CopyIn.
+//go:nosplit
+func (e *ElfProg64) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(e)))
+ hdr.Len = e.SizeBytes()
+ hdr.Cap = e.SizeBytes()
+
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that e
+ // must live until the use above.
+ runtime.KeepAlive(e) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// WriteTo implements io.WriterTo.WriteTo.
+func (e *ElfProg64) WriteTo(writer io.Writer) (int64, error) {
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(e)))
+ hdr.Len = e.SizeBytes()
+ hdr.Cap = e.SizeBytes()
+
+ length, err := writer.Write(buf)
+ // Since we bypassed the compiler's escape analysis, indicate that e
+ // must live until the use above.
+ runtime.KeepAlive(e) // escapes: replaced by intrinsic.
+ return int64(length), err
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
+func (e *ElfSection64) SizeBytes() int {
+ return 64
+}
+
+// MarshalBytes implements marshal.Marshallable.MarshalBytes.
+func (e *ElfSection64) MarshalBytes(dst []byte) {
+ hostarch.ByteOrder.PutUint32(dst[:4], uint32(e.Name))
+ dst = dst[4:]
+ hostarch.ByteOrder.PutUint32(dst[:4], uint32(e.Type))
+ dst = dst[4:]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(e.Flags))
+ dst = dst[8:]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(e.Addr))
+ dst = dst[8:]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(e.Off))
+ dst = dst[8:]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(e.Size))
+ dst = dst[8:]
+ hostarch.ByteOrder.PutUint32(dst[:4], uint32(e.Link))
+ dst = dst[4:]
+ hostarch.ByteOrder.PutUint32(dst[:4], uint32(e.Info))
+ dst = dst[4:]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(e.Addralign))
+ dst = dst[8:]
+ hostarch.ByteOrder.PutUint64(dst[:8], uint64(e.Entsize))
+ dst = dst[8:]
+}
+
+// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
+func (e *ElfSection64) UnmarshalBytes(src []byte) {
+ e.Name = uint32(hostarch.ByteOrder.Uint32(src[:4]))
+ src = src[4:]
+ e.Type = uint32(hostarch.ByteOrder.Uint32(src[:4]))
+ src = src[4:]
+ e.Flags = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+ e.Addr = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+ e.Off = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+ e.Size = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+ e.Link = uint32(hostarch.ByteOrder.Uint32(src[:4]))
+ src = src[4:]
+ e.Info = uint32(hostarch.ByteOrder.Uint32(src[:4]))
+ src = src[4:]
+ e.Addralign = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+ e.Entsize = uint64(hostarch.ByteOrder.Uint64(src[:8]))
+ src = src[8:]
+}
+
+// Packed implements marshal.Marshallable.Packed.
+//go:nosplit
+func (e *ElfSection64) Packed() bool {
+ return true
+}
+
+// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
+func (e *ElfSection64) MarshalUnsafe(dst []byte) {
+ gohacks.Memmove(unsafe.Pointer(&dst[0]), unsafe.Pointer(e), uintptr(e.SizeBytes()))
+}
+
+// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
+func (e *ElfSection64) UnmarshalUnsafe(src []byte) {
+ gohacks.Memmove(unsafe.Pointer(e), unsafe.Pointer(&src[0]), uintptr(e.SizeBytes()))
+}
+
+// CopyOutN implements marshal.Marshallable.CopyOutN.
+//go:nosplit
+func (e *ElfSection64) CopyOutN(cc marshal.CopyContext, addr hostarch.Addr, limit int) (int, error) {
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(e)))
+ hdr.Len = e.SizeBytes()
+ hdr.Cap = e.SizeBytes()
+
+ length, err := cc.CopyOutBytes(addr, buf[:limit]) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that e
+ // must live until the use above.
+ runtime.KeepAlive(e) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// CopyOut implements marshal.Marshallable.CopyOut.
+//go:nosplit
+func (e *ElfSection64) CopyOut(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ return e.CopyOutN(cc, addr, e.SizeBytes())
+}
+
+// CopyIn implements marshal.Marshallable.CopyIn.
+//go:nosplit
+func (e *ElfSection64) CopyIn(cc marshal.CopyContext, addr hostarch.Addr) (int, error) {
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(e)))
+ hdr.Len = e.SizeBytes()
+ hdr.Cap = e.SizeBytes()
+
+ length, err := cc.CopyInBytes(addr, buf) // escapes: okay.
+ // Since we bypassed the compiler's escape analysis, indicate that e
+ // must live until the use above.
+ runtime.KeepAlive(e) // escapes: replaced by intrinsic.
+ return length, err
+}
+
+// WriteTo implements io.WriterTo.WriteTo.
+func (e *ElfSection64) WriteTo(writer io.Writer) (int64, error) {
+ // Construct a slice backed by dst's underlying memory.
+ var buf []byte
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
+ hdr.Data = uintptr(gohacks.Noescape(unsafe.Pointer(e)))
+ hdr.Len = e.SizeBytes()
+ hdr.Cap = e.SizeBytes()
+
+ length, err := writer.Write(buf)
+ // Since we bypassed the compiler's escape analysis, indicate that e
+ // must live until the use above.
+ runtime.KeepAlive(e) // escapes: replaced by intrinsic.
+ return int64(length), err
+}
+
+// SizeBytes implements marshal.Marshallable.SizeBytes.
func (s *SockErrCMsgIPv4) SizeBytes() int {
return 0 +
(*SockExtendedErr)(nil).SizeBytes() +
diff --git a/pkg/abi/linux/netdevice.go b/pkg/abi/linux/netdevice.go
index 0faf015c7..51a39704b 100644
--- a/pkg/abi/linux/netdevice.go
+++ b/pkg/abi/linux/netdevice.go
@@ -14,8 +14,6 @@
package linux
-import "gvisor.dev/gvisor/pkg/binary"
-
const (
// IFNAMSIZ is the size of the name field for IFReq.
IFNAMSIZ = 16
@@ -66,7 +64,7 @@ func (ifr *IFReq) SetName(name string) {
}
// SizeOfIFReq is the binary size of an IFReq struct (40 bytes).
-var SizeOfIFReq = binary.Size(IFReq{})
+var SizeOfIFReq = (*IFReq)(nil).SizeBytes()
// IFMap contains interface hardware parameters.
type IFMap struct {
diff --git a/pkg/binary/binary.go b/pkg/binary/binary.go
deleted file mode 100644
index 25065aef9..000000000
--- a/pkg/binary/binary.go
+++ /dev/null
@@ -1,266 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Package binary translates between select fixed-sized types and a binary
-// representation.
-package binary
-
-import (
- "encoding/binary"
- "fmt"
- "io"
- "reflect"
-)
-
-// LittleEndian is the same as encoding/binary.LittleEndian.
-//
-// It is included here as a convenience.
-var LittleEndian = binary.LittleEndian
-
-// BigEndian is the same as encoding/binary.BigEndian.
-//
-// It is included here as a convenience.
-var BigEndian = binary.BigEndian
-
-// AppendUint16 appends the binary representation of a uint16 to buf.
-func AppendUint16(buf []byte, order binary.ByteOrder, num uint16) []byte {
- buf = append(buf, make([]byte, 2)...)
- order.PutUint16(buf[len(buf)-2:], num)
- return buf
-}
-
-// AppendUint32 appends the binary representation of a uint32 to buf.
-func AppendUint32(buf []byte, order binary.ByteOrder, num uint32) []byte {
- buf = append(buf, make([]byte, 4)...)
- order.PutUint32(buf[len(buf)-4:], num)
- return buf
-}
-
-// AppendUint64 appends the binary representation of a uint64 to buf.
-func AppendUint64(buf []byte, order binary.ByteOrder, num uint64) []byte {
- buf = append(buf, make([]byte, 8)...)
- order.PutUint64(buf[len(buf)-8:], num)
- return buf
-}
-
-// Marshal appends a binary representation of data to buf.
-//
-// data must only contain fixed-length signed and unsigned ints, arrays,
-// slices, structs and compositions of said types. data may be a pointer,
-// but cannot contain pointers.
-func Marshal(buf []byte, order binary.ByteOrder, data interface{}) []byte {
- return marshal(buf, order, reflect.Indirect(reflect.ValueOf(data)))
-}
-
-func marshal(buf []byte, order binary.ByteOrder, data reflect.Value) []byte {
- switch data.Kind() {
- case reflect.Int8:
- buf = append(buf, byte(int8(data.Int())))
- case reflect.Int16:
- buf = AppendUint16(buf, order, uint16(int16(data.Int())))
- case reflect.Int32:
- buf = AppendUint32(buf, order, uint32(int32(data.Int())))
- case reflect.Int64:
- buf = AppendUint64(buf, order, uint64(data.Int()))
-
- case reflect.Uint8:
- buf = append(buf, byte(data.Uint()))
- case reflect.Uint16:
- buf = AppendUint16(buf, order, uint16(data.Uint()))
- case reflect.Uint32:
- buf = AppendUint32(buf, order, uint32(data.Uint()))
- case reflect.Uint64:
- buf = AppendUint64(buf, order, data.Uint())
-
- case reflect.Array, reflect.Slice:
- for i, l := 0, data.Len(); i < l; i++ {
- buf = marshal(buf, order, data.Index(i))
- }
-
- case reflect.Struct:
- for i, l := 0, data.NumField(); i < l; i++ {
- buf = marshal(buf, order, data.Field(i))
- }
-
- default:
- panic("invalid type: " + data.Type().String())
- }
- return buf
-}
-
-// Unmarshal unpacks buf into data.
-//
-// data must be a slice or a pointer and buf must have a length of exactly
-// Size(data). data must only contain fixed-length signed and unsigned ints,
-// arrays, slices, structs and compositions of said types.
-func Unmarshal(buf []byte, order binary.ByteOrder, data interface{}) {
- value := reflect.ValueOf(data)
- switch value.Kind() {
- case reflect.Ptr:
- value = value.Elem()
- case reflect.Slice:
- default:
- panic("invalid type: " + value.Type().String())
- }
- buf = unmarshal(buf, order, value)
- if len(buf) != 0 {
- panic(fmt.Sprintf("buffer too long by %d bytes", len(buf)))
- }
-}
-
-func unmarshal(buf []byte, order binary.ByteOrder, data reflect.Value) []byte {
- switch data.Kind() {
- case reflect.Int8:
- data.SetInt(int64(int8(buf[0])))
- buf = buf[1:]
- case reflect.Int16:
- data.SetInt(int64(int16(order.Uint16(buf))))
- buf = buf[2:]
- case reflect.Int32:
- data.SetInt(int64(int32(order.Uint32(buf))))
- buf = buf[4:]
- case reflect.Int64:
- data.SetInt(int64(order.Uint64(buf)))
- buf = buf[8:]
-
- case reflect.Uint8:
- data.SetUint(uint64(buf[0]))
- buf = buf[1:]
- case reflect.Uint16:
- data.SetUint(uint64(order.Uint16(buf)))
- buf = buf[2:]
- case reflect.Uint32:
- data.SetUint(uint64(order.Uint32(buf)))
- buf = buf[4:]
- case reflect.Uint64:
- data.SetUint(order.Uint64(buf))
- buf = buf[8:]
-
- case reflect.Array, reflect.Slice:
- for i, l := 0, data.Len(); i < l; i++ {
- buf = unmarshal(buf, order, data.Index(i))
- }
-
- case reflect.Struct:
- for i, l := 0, data.NumField(); i < l; i++ {
- if field := data.Field(i); field.CanSet() {
- buf = unmarshal(buf, order, field)
- } else {
- buf = buf[sizeof(field):]
- }
- }
-
- default:
- panic("invalid type: " + data.Type().String())
- }
- return buf
-}
-
-// Size calculates the buffer sized needed by Marshal or Unmarshal.
-//
-// Size only support the types supported by Marshal.
-func Size(v interface{}) uintptr {
- return sizeof(reflect.Indirect(reflect.ValueOf(v)))
-}
-
-func sizeof(data reflect.Value) uintptr {
- switch data.Kind() {
- case reflect.Int8, reflect.Uint8:
- return 1
- case reflect.Int16, reflect.Uint16:
- return 2
- case reflect.Int32, reflect.Uint32:
- return 4
- case reflect.Int64, reflect.Uint64:
- return 8
-
- case reflect.Array, reflect.Slice:
- var size uintptr
- for i, l := 0, data.Len(); i < l; i++ {
- size += sizeof(data.Index(i))
- }
- return size
-
- case reflect.Struct:
- var size uintptr
- for i, l := 0, data.NumField(); i < l; i++ {
- size += sizeof(data.Field(i))
- }
- return size
-
- default:
- panic("invalid type: " + data.Type().String())
- }
-}
-
-// ReadUint16 reads a uint16 from r.
-func ReadUint16(r io.Reader, order binary.ByteOrder) (uint16, error) {
- buf := make([]byte, 2)
- if _, err := io.ReadFull(r, buf); err != nil {
- return 0, err
- }
- return order.Uint16(buf), nil
-}
-
-// ReadUint32 reads a uint32 from r.
-func ReadUint32(r io.Reader, order binary.ByteOrder) (uint32, error) {
- buf := make([]byte, 4)
- if _, err := io.ReadFull(r, buf); err != nil {
- return 0, err
- }
- return order.Uint32(buf), nil
-}
-
-// ReadUint64 reads a uint64 from r.
-func ReadUint64(r io.Reader, order binary.ByteOrder) (uint64, error) {
- buf := make([]byte, 8)
- if _, err := io.ReadFull(r, buf); err != nil {
- return 0, err
- }
- return order.Uint64(buf), nil
-}
-
-// WriteUint16 writes a uint16 to w.
-func WriteUint16(w io.Writer, order binary.ByteOrder, num uint16) error {
- buf := make([]byte, 2)
- order.PutUint16(buf, num)
- _, err := w.Write(buf)
- return err
-}
-
-// WriteUint32 writes a uint32 to w.
-func WriteUint32(w io.Writer, order binary.ByteOrder, num uint32) error {
- buf := make([]byte, 4)
- order.PutUint32(buf, num)
- _, err := w.Write(buf)
- return err
-}
-
-// WriteUint64 writes a uint64 to w.
-func WriteUint64(w io.Writer, order binary.ByteOrder, num uint64) error {
- buf := make([]byte, 8)
- order.PutUint64(buf, num)
- _, err := w.Write(buf)
- return err
-}
-
-// AlignUp rounds a length up to an alignment. align must be a power of 2.
-func AlignUp(length int, align uint) int {
- return (length + int(align) - 1) & ^(int(align) - 1)
-}
-
-// AlignDown rounds a length down to an alignment. align must be a power of 2.
-func AlignDown(length int, align uint) int {
- return length & ^(int(align) - 1)
-}
diff --git a/pkg/binary/binary_state_autogen.go b/pkg/binary/binary_state_autogen.go
deleted file mode 100644
index 4661a5982..000000000
--- a/pkg/binary/binary_state_autogen.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// automatically generated by stateify.
-
-package binary
diff --git a/pkg/compressio/compressio.go b/pkg/compressio/compressio.go
index b094c5662..615d7f134 100644
--- a/pkg/compressio/compressio.go
+++ b/pkg/compressio/compressio.go
@@ -48,12 +48,12 @@ import (
"compress/flate"
"crypto/hmac"
"crypto/sha256"
+ "encoding/binary"
"errors"
"hash"
"io"
"runtime"
- "gvisor.dev/gvisor/pkg/binary"
"gvisor.dev/gvisor/pkg/sync"
)
@@ -130,6 +130,10 @@ type worker struct {
hashPool *hashPool
input chan *chunk
output chan result
+
+ // scratch is a temporary buffer used for marshalling. This is declared
+ // unfront here to avoid reallocation.
+ scratch [4]byte
}
// work is the main work routine; see worker.
@@ -167,7 +171,8 @@ func (w *worker) work(compress bool, level int) {
// Write the hash, if enabled.
if h != nil {
- binary.WriteUint32(h, binary.BigEndian, uint32(c.compressed.Len()))
+ binary.BigEndian.PutUint32(w.scratch[:], uint32(c.compressed.Len()))
+ h.Write(w.scratch[:4])
c.h = h
h = nil
}
@@ -175,7 +180,8 @@ func (w *worker) work(compress bool, level int) {
// Check the hash of the compressed contents.
if h != nil {
h.Write(c.compressed.Bytes())
- binary.WriteUint32(h, binary.BigEndian, uint32(c.compressed.Len()))
+ binary.BigEndian.PutUint32(w.scratch[:], uint32(c.compressed.Len()))
+ h.Write(w.scratch[:4])
io.CopyN(h, bytes.NewReader(c.lastSum), int64(len(c.lastSum)))
sum := h.Sum(nil)
@@ -352,6 +358,10 @@ type Reader struct {
// in is the source.
in io.Reader
+
+ // scratch is a temporary buffer used for marshalling. This is declared
+ // unfront here to avoid reallocation.
+ scratch [4]byte
}
var _ io.Reader = (*Reader)(nil)
@@ -368,14 +378,15 @@ func NewReader(in io.Reader, key []byte) (*Reader, error) {
// Use double buffering for read.
r.init(key, 2*runtime.GOMAXPROCS(0), false, 0)
- var err error
- if r.chunkSize, err = binary.ReadUint32(in, binary.BigEndian); err != nil {
+ if _, err := io.ReadFull(in, r.scratch[:4]); err != nil {
return nil, err
}
+ r.chunkSize = binary.BigEndian.Uint32(r.scratch[:4])
if r.hashPool != nil {
h := r.hashPool.getHash()
- binary.WriteUint32(h, binary.BigEndian, r.chunkSize)
+ binary.BigEndian.PutUint32(r.scratch[:], r.chunkSize)
+ h.Write(r.scratch[:4])
r.lastSum = h.Sum(nil)
r.hashPool.putHash(h)
sum := make([]byte, len(r.lastSum))
@@ -467,8 +478,7 @@ func (r *Reader) Read(p []byte) (int, error) {
// reader. The length is used to limit the reader.
//
// See writer.flush.
- l, err := binary.ReadUint32(r.in, binary.BigEndian)
- if err != nil {
+ if _, err := io.ReadFull(r.in, r.scratch[:4]); err != nil {
// This is generally okay as long as there
// are still buffers outstanding. We actually
// just wait for completion of those buffers here
@@ -488,6 +498,7 @@ func (r *Reader) Read(p []byte) (int, error) {
return done, err
}
}
+ l := binary.BigEndian.Uint32(r.scratch[:4])
// Read this chunk and schedule decompression.
compressed := bufPool.Get().(*bytes.Buffer)
@@ -573,6 +584,10 @@ type Writer struct {
// closed indicates whether the file has been closed.
closed bool
+
+ // scratch is a temporary buffer used for marshalling. This is declared
+ // unfront here to avoid reallocation.
+ scratch [4]byte
}
var _ io.Writer = (*Writer)(nil)
@@ -594,13 +609,15 @@ func NewWriter(out io.Writer, key []byte, chunkSize uint32, level int) (*Writer,
}
w.init(key, 1+runtime.GOMAXPROCS(0), true, level)
- if err := binary.WriteUint32(w.out, binary.BigEndian, chunkSize); err != nil {
+ binary.BigEndian.PutUint32(w.scratch[:], chunkSize)
+ if _, err := w.out.Write(w.scratch[:4]); err != nil {
return nil, err
}
if w.hashPool != nil {
h := w.hashPool.getHash()
- binary.WriteUint32(h, binary.BigEndian, chunkSize)
+ binary.BigEndian.PutUint32(w.scratch[:], chunkSize)
+ h.Write(w.scratch[:4])
w.lastSum = h.Sum(nil)
w.hashPool.putHash(h)
if _, err := io.CopyN(w.out, bytes.NewReader(w.lastSum), int64(len(w.lastSum))); err != nil {
@@ -616,7 +633,9 @@ func (w *Writer) flush(c *chunk) error {
// Prefix each chunk with a length; this allows the reader to safely
// limit reads while buffering.
l := uint32(c.compressed.Len())
- if err := binary.WriteUint32(w.out, binary.BigEndian, l); err != nil {
+
+ binary.BigEndian.PutUint32(w.scratch[:], l)
+ if _, err := w.out.Write(w.scratch[:4]); err != nil {
return err
}
diff --git a/pkg/sentry/loader/elf.go b/pkg/sentry/loader/elf.go
index e92d9fdc3..8fc3e2a79 100644
--- a/pkg/sentry/loader/elf.go
+++ b/pkg/sentry/loader/elf.go
@@ -22,7 +22,6 @@ import (
"gvisor.dev/gvisor/pkg/abi"
"gvisor.dev/gvisor/pkg/abi/linux"
- "gvisor.dev/gvisor/pkg/binary"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/cpuid"
"gvisor.dev/gvisor/pkg/hostarch"
@@ -47,10 +46,10 @@ const (
var (
// header64Size is the size of elf.Header64.
- header64Size = int(binary.Size(elf.Header64{}))
+ header64Size = (*linux.ElfHeader64)(nil).SizeBytes()
// Prog64Size is the size of elf.Prog64.
- prog64Size = int(binary.Size(elf.Prog64{}))
+ prog64Size = (*linux.ElfProg64)(nil).SizeBytes()
)
func progFlagsAsPerms(f elf.ProgFlag) hostarch.AccessType {
@@ -136,7 +135,6 @@ func parseHeader(ctx context.Context, f fullReader) (elfInfo, error) {
log.Infof("Unsupported ELF endianness: %v", endian)
return elfInfo{}, syserror.ENOEXEC
}
- byteOrder := binary.LittleEndian
if version := elf.Version(ident[elf.EI_VERSION]); version != elf.EV_CURRENT {
log.Infof("Unsupported ELF version: %v", version)
@@ -145,7 +143,7 @@ func parseHeader(ctx context.Context, f fullReader) (elfInfo, error) {
// EI_OSABI is ignored by Linux, which is the only OS supported.
os := abi.Linux
- var hdr elf.Header64
+ var hdr linux.ElfHeader64
hdrBuf := make([]byte, header64Size)
_, err = f.ReadFull(ctx, usermem.BytesIOSequence(hdrBuf), 0)
if err != nil {
@@ -156,7 +154,7 @@ func parseHeader(ctx context.Context, f fullReader) (elfInfo, error) {
}
return elfInfo{}, err
}
- binary.Unmarshal(hdrBuf, byteOrder, &hdr)
+ hdr.UnmarshalUnsafe(hdrBuf)
// We support amd64 and arm64.
var a arch.Arch
@@ -213,8 +211,8 @@ func parseHeader(ctx context.Context, f fullReader) (elfInfo, error) {
phdrs := make([]elf.ProgHeader, hdr.Phnum)
for i := range phdrs {
- var prog64 elf.Prog64
- binary.Unmarshal(phdrBuf[:prog64Size], byteOrder, &prog64)
+ var prog64 linux.ElfProg64
+ prog64.UnmarshalUnsafe(phdrBuf[:prog64Size])
phdrBuf = phdrBuf[prog64Size:]
phdrs[i] = elf.ProgHeader{
Type: elf.ProgType(prog64.Type),
diff --git a/pkg/sentry/loader/loader_abi_autogen_unsafe.go b/pkg/sentry/loader/loader_abi_autogen_unsafe.go
new file mode 100644
index 000000000..bfa048912
--- /dev/null
+++ b/pkg/sentry/loader/loader_abi_autogen_unsafe.go
@@ -0,0 +1,13 @@
+// Automatically generated marshal implementation. See tools/go_marshal.
+
+// If there are issues with build tag aggregation, see
+// tools/go_marshal/gomarshal/generator.go:writeHeader(). The build tags here
+// come from the input set of files used to generate this file. This input set
+// is filtered based on pre-defined file suffixes related to build tags, see
+// tools/defs.bzl:calculate_sets().
+
+package loader
+
+import (
+)
+
diff --git a/pkg/state/statefile/statefile.go b/pkg/state/statefile/statefile.go
index bdfb800fb..d27c8c8a8 100644
--- a/pkg/state/statefile/statefile.go
+++ b/pkg/state/statefile/statefile.go
@@ -48,6 +48,7 @@ import (
"compress/flate"
"crypto/hmac"
"crypto/sha256"
+ "encoding/binary"
"encoding/json"
"fmt"
"hash"
@@ -55,7 +56,6 @@ import (
"strings"
"time"
- "gvisor.dev/gvisor/pkg/binary"
"gvisor.dev/gvisor/pkg/compressio"
"gvisor.dev/gvisor/pkg/state/wire"
)
@@ -90,6 +90,13 @@ type WriteCloser interface {
io.Closer
}
+func writeMetadataLen(w io.Writer, val uint64) error {
+ var buf [8]byte
+ binary.BigEndian.PutUint64(buf[:], val)
+ _, err := w.Write(buf[:])
+ return err
+}
+
// NewWriter returns a state data writer for a statefile.
//
// Note that the returned WriteCloser must be closed.
@@ -127,7 +134,7 @@ func NewWriter(w io.Writer, key []byte, metadata map[string]string) (WriteCloser
}
// Metadata length.
- if err := binary.WriteUint64(mw, binary.BigEndian, uint64(len(b))); err != nil {
+ if err := writeMetadataLen(mw, uint64(len(b))); err != nil {
return nil, err
}
// Metadata bytes; io.MultiWriter will return a short write error if
@@ -158,6 +165,14 @@ func MetadataUnsafe(r io.Reader) (map[string]string, error) {
return metadata(r, nil)
}
+func readMetadataLen(r io.Reader) (uint64, error) {
+ var buf [8]byte
+ if _, err := io.ReadFull(r, buf[:]); err != nil {
+ return 0, err
+ }
+ return binary.BigEndian.Uint64(buf[:]), nil
+}
+
// metadata validates the magic header and reads out the metadata from a state
// data stream.
func metadata(r io.Reader, h hash.Hash) (map[string]string, error) {
@@ -183,7 +198,7 @@ func metadata(r io.Reader, h hash.Hash) (map[string]string, error) {
}
}()
- metadataLen, err := binary.ReadUint64(r, binary.BigEndian)
+ metadataLen, err := readMetadataLen(r)
if err != nil {
return nil, err
}