summaryrefslogtreecommitdiffhomepage
path: root/pkg/hostarch
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/hostarch')
-rw-r--r--pkg/hostarch/BUILD42
-rw-r--r--pkg/hostarch/addr_range.go76
-rw-r--r--pkg/hostarch/addr_range_seq_test.go197
-rw-r--r--pkg/hostarch/hostarch_arm64_state_autogen.go6
-rw-r--r--pkg/hostarch/hostarch_state_autogen.go80
-rw-r--r--pkg/hostarch/hostarch_unsafe_state_autogen.go3
-rw-r--r--pkg/hostarch/hostarch_x86_state_autogen.go6
7 files changed, 171 insertions, 239 deletions
diff --git a/pkg/hostarch/BUILD b/pkg/hostarch/BUILD
deleted file mode 100644
index 1e8def4d9..000000000
--- a/pkg/hostarch/BUILD
+++ /dev/null
@@ -1,42 +0,0 @@
-load("//tools:defs.bzl", "go_library", "go_test")
-load("//tools/go_generics:defs.bzl", "go_template_instance")
-
-package(licenses = ["notice"])
-
-go_template_instance(
- name = "addr_range",
- out = "addr_range.go",
- package = "hostarch",
- prefix = "Addr",
- template = "//pkg/segment:generic_range",
- types = {
- "T": "Addr",
- },
-)
-
-go_test(
- name = "hostarch_test",
- size = "small",
- srcs = [
- "addr_range_seq_test.go",
- ],
- library = ":hostarch",
-)
-
-go_library(
- name = "hostarch",
- srcs = [
- "access_type.go",
- "addr.go",
- "addr_range.go",
- "addr_range_seq_unsafe.go",
- "hostarch.go",
- "hostarch_arm64.go",
- "hostarch_x86.go",
- ],
- visibility = ["//:sandbox"],
- deps = [
- "//pkg/gohacks",
- "@org_golang_x_sys//unix:go_default_library",
- ],
-)
diff --git a/pkg/hostarch/addr_range.go b/pkg/hostarch/addr_range.go
new file mode 100644
index 000000000..8a771d6fc
--- /dev/null
+++ b/pkg/hostarch/addr_range.go
@@ -0,0 +1,76 @@
+package hostarch
+
+// A Range represents a contiguous range of T.
+//
+// +stateify savable
+type AddrRange struct {
+ // Start is the inclusive start of the range.
+ Start Addr
+
+ // End is the exclusive end of the range.
+ End Addr
+}
+
+// WellFormed returns true if r.Start <= r.End. All other methods on a Range
+// require that the Range is well-formed.
+//
+//go:nosplit
+func (r AddrRange) WellFormed() bool {
+ return r.Start <= r.End
+}
+
+// Length returns the length of the range.
+//
+//go:nosplit
+func (r AddrRange) Length() Addr {
+ return r.End - r.Start
+}
+
+// Contains returns true if r contains x.
+//
+//go:nosplit
+func (r AddrRange) Contains(x Addr) bool {
+ return r.Start <= x && x < r.End
+}
+
+// Overlaps returns true if r and r2 overlap.
+//
+//go:nosplit
+func (r AddrRange) Overlaps(r2 AddrRange) bool {
+ return r.Start < r2.End && r2.Start < r.End
+}
+
+// IsSupersetOf returns true if r is a superset of r2; that is, the range r2 is
+// contained within r.
+//
+//go:nosplit
+func (r AddrRange) IsSupersetOf(r2 AddrRange) bool {
+ return r.Start <= r2.Start && r.End >= r2.End
+}
+
+// Intersect returns a range consisting of the intersection between r and r2.
+// If r and r2 do not overlap, Intersect returns a range with unspecified
+// bounds, but for which Length() == 0.
+//
+//go:nosplit
+func (r AddrRange) Intersect(r2 AddrRange) AddrRange {
+ if r.Start < r2.Start {
+ r.Start = r2.Start
+ }
+ if r.End > r2.End {
+ r.End = r2.End
+ }
+ if r.End < r.Start {
+ r.End = r.Start
+ }
+ return r
+}
+
+// CanSplitAt returns true if it is legal to split a segment spanning the range
+// r at x; that is, splitting at x would produce two ranges, both of which have
+// non-zero length.
+//
+//go:nosplit
+func (r AddrRange) CanSplitAt(x Addr) bool {
+ return r.Contains(x) && r.Start < x
+}
diff --git a/pkg/hostarch/addr_range_seq_test.go b/pkg/hostarch/addr_range_seq_test.go
deleted file mode 100644
index 5726dfd19..000000000
--- a/pkg/hostarch/addr_range_seq_test.go
+++ /dev/null
@@ -1,197 +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 hostarch
-
-import (
- "testing"
-)
-
-var addrRangeSeqTests = []struct {
- desc string
- ranges []AddrRange
-}{
- {
- desc: "Empty sequence",
- },
- {
- desc: "Single empty AddrRange",
- ranges: []AddrRange{
- {0x10, 0x10},
- },
- },
- {
- desc: "Single non-empty AddrRange of length 1",
- ranges: []AddrRange{
- {0x10, 0x11},
- },
- },
- {
- desc: "Single non-empty AddrRange of length 2",
- ranges: []AddrRange{
- {0x10, 0x12},
- },
- },
- {
- desc: "Multiple non-empty AddrRanges",
- ranges: []AddrRange{
- {0x10, 0x11},
- {0x20, 0x22},
- },
- },
- {
- desc: "Multiple AddrRanges including empty AddrRanges",
- ranges: []AddrRange{
- {0x10, 0x10},
- {0x20, 0x20},
- {0x30, 0x33},
- {0x40, 0x44},
- {0x50, 0x50},
- {0x60, 0x60},
- {0x70, 0x77},
- {0x80, 0x88},
- {0x90, 0x90},
- {0xa0, 0xa0},
- },
- },
-}
-
-func testAddrRangeSeqEqualityWithTailIteration(t *testing.T, ars AddrRangeSeq, wantRanges []AddrRange) {
- var wantLen int64
- for _, ar := range wantRanges {
- wantLen += int64(ar.Length())
- }
-
- var i int
- for !ars.IsEmpty() {
- if gotLen := ars.NumBytes(); gotLen != wantLen {
- t.Errorf("Iteration %d: %v.NumBytes(): got %d, wanted %d", i, ars, gotLen, wantLen)
- }
- if gotN, wantN := ars.NumRanges(), len(wantRanges)-i; gotN != wantN {
- t.Errorf("Iteration %d: %v.NumRanges(): got %d, wanted %d", i, ars, gotN, wantN)
- }
- got := ars.Head()
- if i >= len(wantRanges) {
- t.Errorf("Iteration %d: %v.Head(): got %s, wanted <end of sequence>", i, ars, got)
- } else if want := wantRanges[i]; got != want {
- t.Errorf("Iteration %d: %v.Head(): got %s, wanted %s", i, ars, got, want)
- }
- ars = ars.Tail()
- wantLen -= int64(got.Length())
- i++
- }
- if gotLen := ars.NumBytes(); gotLen != 0 || wantLen != 0 {
- t.Errorf("Iteration %d: %v.NumBytes(): got %d, wanted %d (which should be 0)", i, ars, gotLen, wantLen)
- }
- if gotN := ars.NumRanges(); gotN != 0 {
- t.Errorf("Iteration %d: %v.NumRanges(): got %d, wanted 0", i, ars, gotN)
- }
-}
-
-func TestAddrRangeSeqTailIteration(t *testing.T) {
- for _, test := range addrRangeSeqTests {
- t.Run(test.desc, func(t *testing.T) {
- testAddrRangeSeqEqualityWithTailIteration(t, AddrRangeSeqFromSlice(test.ranges), test.ranges)
- })
- }
-}
-
-func TestAddrRangeSeqDropFirstEmpty(t *testing.T) {
- var ars AddrRangeSeq
- if got, want := ars.DropFirst(1), ars; got != want {
- t.Errorf("%v.DropFirst(1): got %v, wanted %v", ars, got, want)
- }
-}
-
-func TestAddrRangeSeqDropSingleByteIteration(t *testing.T) {
- // Tests AddrRangeSeq iteration using Head/DropFirst, simulating
- // I/O-per-AddrRange.
- for _, test := range addrRangeSeqTests {
- t.Run(test.desc, func(t *testing.T) {
- // Figure out what AddrRanges we expect to see.
- var wantLen int64
- var wantRanges []AddrRange
- for _, ar := range test.ranges {
- wantLen += int64(ar.Length())
- wantRanges = append(wantRanges, ar)
- if ar.Length() == 0 {
- // We "do" 0 bytes of I/O and then call DropFirst(0),
- // advancing to the next AddrRange.
- continue
- }
- // Otherwise we "do" 1 byte of I/O and then call DropFirst(1),
- // advancing the AddrRange by 1 byte, or to the next AddrRange
- // if this one is exhausted.
- for ar.Start++; ar.Length() != 0; ar.Start++ {
- wantRanges = append(wantRanges, ar)
- }
- }
- t.Logf("Expected AddrRanges: %s (%d bytes)", wantRanges, wantLen)
-
- ars := AddrRangeSeqFromSlice(test.ranges)
- var i int
- for !ars.IsEmpty() {
- if gotLen := ars.NumBytes(); gotLen != wantLen {
- t.Errorf("Iteration %d: %v.NumBytes(): got %d, wanted %d", i, ars, gotLen, wantLen)
- }
- got := ars.Head()
- if i >= len(wantRanges) {
- t.Errorf("Iteration %d: %v.Head(): got %s, wanted <end of sequence>", i, ars, got)
- } else if want := wantRanges[i]; got != want {
- t.Errorf("Iteration %d: %v.Head(): got %s, wanted %s", i, ars, got, want)
- }
- if got.Length() == 0 {
- ars = ars.DropFirst(0)
- } else {
- ars = ars.DropFirst(1)
- wantLen--
- }
- i++
- }
- if gotLen := ars.NumBytes(); gotLen != 0 || wantLen != 0 {
- t.Errorf("Iteration %d: %v.NumBytes(): got %d, wanted %d (which should be 0)", i, ars, gotLen, wantLen)
- }
- })
- }
-}
-
-func TestAddrRangeSeqTakeFirstEmpty(t *testing.T) {
- var ars AddrRangeSeq
- if got, want := ars.TakeFirst(1), ars; got != want {
- t.Errorf("%v.TakeFirst(1): got %v, wanted %v", ars, got, want)
- }
-}
-
-func TestAddrRangeSeqTakeFirst(t *testing.T) {
- ranges := []AddrRange{
- {0x10, 0x11},
- {0x20, 0x22},
- {0x30, 0x30},
- {0x40, 0x44},
- {0x50, 0x55},
- {0x60, 0x60},
- {0x70, 0x77},
- }
- ars := AddrRangeSeqFromSlice(ranges).TakeFirst(5)
- want := []AddrRange{
- {0x10, 0x11}, // +1 byte (total 1 byte), not truncated
- {0x20, 0x22}, // +2 bytes (total 3 bytes), not truncated
- {0x30, 0x30}, // +0 bytes (total 3 bytes), no change
- {0x40, 0x42}, // +2 bytes (total 5 bytes), partially truncated
- {0x50, 0x50}, // +0 bytes (total 5 bytes), fully truncated
- {0x60, 0x60}, // +0 bytes (total 5 bytes), "fully truncated" (no change)
- {0x70, 0x70}, // +0 bytes (total 5 bytes), fully truncated
- }
- testAddrRangeSeqEqualityWithTailIteration(t, ars, want)
-}
diff --git a/pkg/hostarch/hostarch_arm64_state_autogen.go b/pkg/hostarch/hostarch_arm64_state_autogen.go
new file mode 100644
index 000000000..444542b30
--- /dev/null
+++ b/pkg/hostarch/hostarch_arm64_state_autogen.go
@@ -0,0 +1,6 @@
+// automatically generated by stateify.
+
+//go:build arm64
+// +build arm64
+
+package hostarch
diff --git a/pkg/hostarch/hostarch_state_autogen.go b/pkg/hostarch/hostarch_state_autogen.go
new file mode 100644
index 000000000..32939e06b
--- /dev/null
+++ b/pkg/hostarch/hostarch_state_autogen.go
@@ -0,0 +1,80 @@
+// automatically generated by stateify.
+
+package hostarch
+
+import (
+ "gvisor.dev/gvisor/pkg/state"
+)
+
+func (a *AccessType) StateTypeName() string {
+ return "pkg/hostarch.AccessType"
+}
+
+func (a *AccessType) StateFields() []string {
+ return []string{
+ "Read",
+ "Write",
+ "Execute",
+ }
+}
+
+func (a *AccessType) beforeSave() {}
+
+// +checklocksignore
+func (a *AccessType) StateSave(stateSinkObject state.Sink) {
+ a.beforeSave()
+ stateSinkObject.Save(0, &a.Read)
+ stateSinkObject.Save(1, &a.Write)
+ stateSinkObject.Save(2, &a.Execute)
+}
+
+func (a *AccessType) afterLoad() {}
+
+// +checklocksignore
+func (a *AccessType) StateLoad(stateSourceObject state.Source) {
+ stateSourceObject.Load(0, &a.Read)
+ stateSourceObject.Load(1, &a.Write)
+ stateSourceObject.Load(2, &a.Execute)
+}
+
+func (v *Addr) StateTypeName() string {
+ return "pkg/hostarch.Addr"
+}
+
+func (v *Addr) StateFields() []string {
+ return nil
+}
+
+func (r *AddrRange) StateTypeName() string {
+ return "pkg/hostarch.AddrRange"
+}
+
+func (r *AddrRange) StateFields() []string {
+ return []string{
+ "Start",
+ "End",
+ }
+}
+
+func (r *AddrRange) beforeSave() {}
+
+// +checklocksignore
+func (r *AddrRange) StateSave(stateSinkObject state.Sink) {
+ r.beforeSave()
+ stateSinkObject.Save(0, &r.Start)
+ stateSinkObject.Save(1, &r.End)
+}
+
+func (r *AddrRange) afterLoad() {}
+
+// +checklocksignore
+func (r *AddrRange) StateLoad(stateSourceObject state.Source) {
+ stateSourceObject.Load(0, &r.Start)
+ stateSourceObject.Load(1, &r.End)
+}
+
+func init() {
+ state.Register((*AccessType)(nil))
+ state.Register((*Addr)(nil))
+ state.Register((*AddrRange)(nil))
+}
diff --git a/pkg/hostarch/hostarch_unsafe_state_autogen.go b/pkg/hostarch/hostarch_unsafe_state_autogen.go
new file mode 100644
index 000000000..419f24913
--- /dev/null
+++ b/pkg/hostarch/hostarch_unsafe_state_autogen.go
@@ -0,0 +1,3 @@
+// automatically generated by stateify.
+
+package hostarch
diff --git a/pkg/hostarch/hostarch_x86_state_autogen.go b/pkg/hostarch/hostarch_x86_state_autogen.go
new file mode 100644
index 000000000..239b6ba6c
--- /dev/null
+++ b/pkg/hostarch/hostarch_x86_state_autogen.go
@@ -0,0 +1,6 @@
+// automatically generated by stateify.
+
+//go:build amd64 || 386
+// +build amd64 386
+
+package hostarch