mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Refactor nogo and provide facts render.
This change makes the core nogo package less of a "catch all", and splits functionality into multiple packages. Instead of separate binaries for each function, a single "cli" package is added with subcommands, and the core starlark wrappers are also refactored to minimize redundancy. The new "cli" package also adds support for a "render" command, which allows factors to be rendered via a Go text template. This is useful for debugging, but also allows code generation to be updated to use this mechanism. This eliminates the use of a QEMU wrapper for the older arch_genrule, and allows the use of a native bazel transition to extract facts for the appropriate generated file. In other words, the correct facts will be rendered for generating XXX_arm64.s, even on amd64. PiperOrigin-RevId: 422846459
This commit is contained in:
committed by
gVisor bot
parent
3d578afc8d
commit
0e492a2b5e
@@ -54,7 +54,7 @@ doc(
|
||||
yaml_test(
|
||||
name = "nogo_config_test",
|
||||
srcs = glob(["nogo*.yaml"]),
|
||||
schema = "//tools/nogo:config-schema.json",
|
||||
schema = "//tools/nogo/config:schema.json",
|
||||
)
|
||||
|
||||
yaml_test(
|
||||
|
||||
@@ -196,7 +196,7 @@ nogo-tests:
|
||||
# For unit tests, we take everything in the root, pkg/... and tools/..., and
|
||||
# pull in all directories in runsc except runsc/container.
|
||||
unit-tests: ## Local package unit tests in pkg/..., tools/.., etc.
|
||||
@$(call test,--build_tag_filters=-nogo --test_tag_filters=-nogo --test_filter=-//runsc/container/... //:all pkg/... tools/... runsc/...)
|
||||
@$(call test,--build_tag_filters=-nogo --test_tag_filters=-nogo --test_filter=-//runsc/container/... //:all pkg/... tools/... runsc/... vdso/...)
|
||||
.PHONY: unit-tests
|
||||
|
||||
# See unit-tests: this includes runsc/container.
|
||||
|
||||
@@ -36,8 +36,6 @@ http_archive(
|
||||
name = "io_bazel_rules_go",
|
||||
patch_args = ["-p1"],
|
||||
patches = [
|
||||
# Ensure we don't destroy the facts visibility.
|
||||
"//tools:rules_go_visibility.patch",
|
||||
# Newer versions of the rules_go rules will automatically strip test
|
||||
# binaries of symbols, which we don't want.
|
||||
"//tools:rules_go_symbols.patch",
|
||||
@@ -51,13 +49,6 @@ http_archive(
|
||||
|
||||
http_archive(
|
||||
name = "bazel_gazelle",
|
||||
patch_args = ["-p1"],
|
||||
patches = [
|
||||
# Fix permissions for facts for go_library, not just tool library.
|
||||
# This is actually a no-op with the hacky patch above, but should
|
||||
# slightly future proof this mechanism.
|
||||
"//tools:bazel_gazelle_generate.patch",
|
||||
],
|
||||
sha256 = "62ca106be173579c0a167deb23358fdfe71ffa1e4cfdddf5582af26520f1c66f",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.23.0/bazel-gazelle-v0.23.0.tar.gz",
|
||||
|
||||
+30
-49
@@ -1,69 +1,50 @@
|
||||
load("//tools:defs.bzl", "arch_genrule", "go_library")
|
||||
load("//tools/go_generics:defs.bzl", "go_template", "go_template_instance")
|
||||
load("//tools:defs.bzl", "arch_genrule", "go_library", "select_arch")
|
||||
load("//tools/nogo:defs.bzl", "nogo_facts")
|
||||
|
||||
package(licenses = ["notice"])
|
||||
|
||||
go_template(
|
||||
name = "defs_amd64",
|
||||
srcs = [
|
||||
"defs.go",
|
||||
"defs_amd64.go",
|
||||
"offsets_amd64.go",
|
||||
"x86.go",
|
||||
],
|
||||
visibility = [":__subpackages__"],
|
||||
)
|
||||
exports_files(glob(["*.go"]))
|
||||
|
||||
go_template(
|
||||
name = "defs_arm64",
|
||||
nogo_facts(
|
||||
name = "entry_impl",
|
||||
srcs = [
|
||||
"aarch64.go",
|
||||
"defs.go",
|
||||
"defs_amd64.go",
|
||||
"defs_arm64.go",
|
||||
"offsets_arm64.go",
|
||||
"entry_template.go",
|
||||
"x86.go",
|
||||
],
|
||||
output = "entry_impl.s",
|
||||
template = select_arch(
|
||||
amd64 = "entry_amd64.s",
|
||||
arm64 = "entry_arm64.s",
|
||||
),
|
||||
deps = [
|
||||
"//pkg/abi/linux",
|
||||
"//pkg/cpuid",
|
||||
"//pkg/hostarch",
|
||||
"//pkg/ring0/pagetables",
|
||||
"//pkg/sentry/arch",
|
||||
"//pkg/sentry/arch/fpu",
|
||||
],
|
||||
visibility = [":__subpackages__"],
|
||||
)
|
||||
|
||||
go_template_instance(
|
||||
name = "defs_impl_amd64",
|
||||
out = "defs_impl_amd64.go",
|
||||
package = "ring0",
|
||||
template = ":defs_amd64",
|
||||
)
|
||||
|
||||
go_template_instance(
|
||||
name = "defs_impl_arm64",
|
||||
out = "defs_impl_arm64.go",
|
||||
package = "ring0",
|
||||
template = ":defs_arm64",
|
||||
)
|
||||
|
||||
arch_genrule(
|
||||
name = "entry_impl_amd64",
|
||||
srcs = ["entry_amd64.s"],
|
||||
outs = ["entry_impl_amd64.s"],
|
||||
cmd = "(echo -e '// build +amd64\\n' && QEMU $(location //pkg/ring0/gen_offsets) && cat $(location entry_amd64.s)) > $@",
|
||||
tools = ["//pkg/ring0/gen_offsets"],
|
||||
)
|
||||
|
||||
arch_genrule(
|
||||
name = "entry_impl_arm64",
|
||||
srcs = ["entry_arm64.s"],
|
||||
outs = ["entry_impl_arm64.s"],
|
||||
cmd = "(echo -e '// build +arm64\\n' && QEMU $(location //pkg/ring0/gen_offsets) && cat $(location entry_arm64.s)) > $@",
|
||||
tools = ["//pkg/ring0/gen_offsets"],
|
||||
name = "entry_impl_arch",
|
||||
src = ":entry_impl",
|
||||
template = "entry_impl_%s.s",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "ring0",
|
||||
srcs = [
|
||||
"defs_impl_amd64.go",
|
||||
"defs_impl_arm64.go",
|
||||
"aarch64.go",
|
||||
"defs.go",
|
||||
"defs_amd64.go",
|
||||
"defs_arm64.go",
|
||||
"entry_amd64.go",
|
||||
"entry_arm64.go",
|
||||
"entry_impl_amd64.s",
|
||||
"entry_impl_arm64.s",
|
||||
"kernel.go",
|
||||
"kernel_amd64.go",
|
||||
"kernel_arm64.go",
|
||||
@@ -73,15 +54,15 @@ go_library(
|
||||
"lib_arm64.go",
|
||||
"lib_arm64.s",
|
||||
"ring0.go",
|
||||
"x86.go",
|
||||
":entry_impl_arch",
|
||||
],
|
||||
visibility = ["//pkg/sentry:internal"],
|
||||
deps = [
|
||||
"//pkg/cpuid",
|
||||
"//pkg/hostarch",
|
||||
"//pkg/ring0/pagetables",
|
||||
"//pkg/safecopy",
|
||||
"//pkg/sentry/arch",
|
||||
"//pkg/sentry/arch/fpu",
|
||||
"//pkg/sync",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -137,6 +137,3 @@ type SwitchArchOpts struct {
|
||||
// KernelASID indicates that the kernel ASID to be used on return,
|
||||
KernelASID uint16
|
||||
}
|
||||
|
||||
func init() {
|
||||
}
|
||||
|
||||
+71
-3
@@ -15,9 +15,77 @@
|
||||
#include "funcdata.h"
|
||||
#include "textflag.h"
|
||||
|
||||
// NB: Offsets are programmatically generated (see BUILD).
|
||||
//
|
||||
// This file is concatenated with the definitions.
|
||||
// CPU offsets.
|
||||
#define CPU_REGISTERS {{ .CPU.registers.Offset }}
|
||||
#define CPU_FPU_STATE {{ .CPU.floatingPointState.Offset }}
|
||||
#define CPU_ERROR_CODE ({{ .CPU.CPUArchState.Offset }}+{{ .CPUArchState.errorCode.Offset }})
|
||||
#define CPU_ERROR_TYPE ({{ .CPU.CPUArchState.Offset }}+{{ .CPUArchState.errorType.Offset }})
|
||||
#define CPU_ENTRY ({{ .CPU.CPUArchState.Offset }}+{{ .CPUArchState.kernelEntry.Offset }})
|
||||
#define CPU_HAS_XSAVE ({{ .CPU.CPUArchState.Offset }}+{{ .CPUArchState.hasXSAVE.Offset }})
|
||||
#define CPU_HAS_XSAVEOPT ({{ .CPU.CPUArchState.Offset }}+{{ .CPUArchState.hasXSAVEOPT.Offset }})
|
||||
|
||||
{{ with .kernelEntry }}
|
||||
#define ENTRY_SCRATCH0 {{ .scratch0.Offset }}
|
||||
#define ENTRY_STACK_TOP {{ .stackTop.Offset }}
|
||||
#define ENTRY_CPU_SELF {{ .cpuSelf.Offset }}
|
||||
#define ENTRY_KERNEL_CR3 {{ .kernelCR3.Offset }}
|
||||
{{ end }}
|
||||
|
||||
// Bits.
|
||||
#define _RFLAGS_IF {{ ._RFLAGS_IF.Value }}
|
||||
#define _RFLAGS_IOPL0 {{ ._RFLAGS_IOPL0.Value }}
|
||||
#define _KERNEL_FLAGS {{ .KernelFlagsSet.Value }}
|
||||
|
||||
// Vectors.
|
||||
#define DivideByZero {{ .DivideByZero.Value }}
|
||||
#define Debug {{ .Debug.Value }}
|
||||
#define NMI {{ .NMI.Value }}
|
||||
#define Breakpoint {{ .Breakpoint.Value }}
|
||||
#define Overflow {{ .Overflow.Value }}
|
||||
#define BoundRangeExceeded {{ .BoundRangeExceeded.Value }}
|
||||
#define InvalidOpcode {{ .InvalidOpcode.Value }}
|
||||
#define DeviceNotAvailable {{ .DeviceNotAvailable.Value }}
|
||||
#define DoubleFault {{ .DoubleFault.Value }}
|
||||
#define CoprocessorSegmentOverrun {{ .CoprocessorSegmentOverrun.Value }}
|
||||
#define InvalidTSS {{ .InvalidTSS.Value }}
|
||||
#define SegmentNotPresent {{ .SegmentNotPresent.Value }}
|
||||
#define StackSegmentFault {{ .StackSegmentFault.Value }}
|
||||
#define GeneralProtectionFault {{ .GeneralProtectionFault.Value }}
|
||||
#define PageFault {{ .PageFault.Value }}
|
||||
#define X87FloatingPointException {{ .X87FloatingPointException.Value }}
|
||||
#define AlignmentCheck {{ .AlignmentCheck.Value }}
|
||||
#define MachineCheck {{ .MachineCheck.Value }}
|
||||
#define SIMDFloatingPointException {{ .SIMDFloatingPointException.Value }}
|
||||
#define VirtualizationException {{ .VirtualizationException.Value }}
|
||||
#define SecurityException {{ .SecurityException.Value }}
|
||||
#define SyscallInt80 {{ .SyscallInt80.Value }}
|
||||
#define Syscall {{ .Syscall.Value }}
|
||||
|
||||
{{ with .import.linux.PtraceRegs }}
|
||||
#define PTRACE_R15 {{ .R15.Offset }}
|
||||
#define PTRACE_R14 {{ .R14.Offset }}
|
||||
#define PTRACE_R13 {{ .R13.Offset }}
|
||||
#define PTRACE_R12 {{ .R12.Offset }}
|
||||
#define PTRACE_RBP {{ .Rbp.Offset }}
|
||||
#define PTRACE_RBX {{ .Rbx.Offset }}
|
||||
#define PTRACE_R11 {{ .R11.Offset }}
|
||||
#define PTRACE_R10 {{ .R10.Offset }}
|
||||
#define PTRACE_R9 {{ .R9.Offset }}
|
||||
#define PTRACE_R8 {{ .R8.Offset }}
|
||||
#define PTRACE_RAX {{ .Rax.Offset }}
|
||||
#define PTRACE_RCX {{ .Rcx.Offset }}
|
||||
#define PTRACE_RDX {{ .Rdx.Offset }}
|
||||
#define PTRACE_RSI {{ .Rsi.Offset }}
|
||||
#define PTRACE_RDI {{ .Rdi.Offset }}
|
||||
#define PTRACE_ORIGRAX {{ .Orig_rax.Offset }}
|
||||
#define PTRACE_RIP {{ .Rip.Offset }}
|
||||
#define PTRACE_CS {{ .Cs.Offset }}
|
||||
#define PTRACE_FLAGS {{ .Eflags.Offset }}
|
||||
#define PTRACE_RSP {{ .Rsp.Offset }}
|
||||
#define PTRACE_SS {{ .Ss.Offset }}
|
||||
#define PTRACE_FS_BASE {{ .Fs_base.Offset }}
|
||||
#define PTRACE_GS_BASE {{ .Gs_base.Offset }}
|
||||
{{ end }}
|
||||
|
||||
// Saves a register set.
|
||||
//
|
||||
|
||||
+92
-3
@@ -15,9 +15,98 @@
|
||||
#include "funcdata.h"
|
||||
#include "textflag.h"
|
||||
|
||||
// NB: Offsets are programatically generated (see BUILD).
|
||||
//
|
||||
// This file is concatenated with the definitions.
|
||||
{{ with .CPU }}
|
||||
#define CPU_SELF {{ .self.Offset }}
|
||||
#define CPU_REGISTERS {{ .registers.Offset }}
|
||||
{{ end }}
|
||||
{{ with .CPUArchState }}
|
||||
#define CPU_STACK_TOP ({{ .stack.Offset }} + {{ .stack.Size }})
|
||||
#define CPU_ERROR_CODE {{ .errorCode.Offset }}
|
||||
#define CPU_ERROR_TYPE {{ .errorType.Offset }}
|
||||
#define CPU_FAULT_ADDR {{ .faultAddr.Offset }}
|
||||
#define CPU_FPSTATE_EL0 {{ .el0Fp.Offset }}
|
||||
#define CPU_TTBR0_KVM {{ .ttbr0Kvm.Offset }}
|
||||
#define CPU_TTBR0_APP {{ .ttbr0App.Offset }}
|
||||
#define CPU_VECTOR_CODE {{ .vecCode.Offset }}
|
||||
#define CPU_APP_ADDR {{ .appAddr.Offset }}
|
||||
#define CPU_LAZY_VFP {{ .lazyVFP.Offset }}
|
||||
#define CPU_APP_ASID {{ .appASID.Offset }}
|
||||
{{ end }}
|
||||
|
||||
// Bits.
|
||||
#define _KERNEL_FLAGS {{ .KernelFlagsSet.Value }}
|
||||
|
||||
// Vectors.
|
||||
#define El1Sync {{ .El1Sync.Value }}
|
||||
#define El1Irq {{ .El1Irq.Value }}
|
||||
#define El1Fiq {{ .El1Fiq.Value }}
|
||||
#define El1Err {{ .El1Err.Value }}
|
||||
#define El0Sync {{ .El0Sync.Value }}
|
||||
#define El0Irq {{ .El0Irq.Value }}
|
||||
#define El0Fiq {{ .El0Fiq.Value }}
|
||||
#define El0Err {{ .El0Err.Value }}
|
||||
#define El1SyncDa {{ .El1SyncDa.Value }}
|
||||
#define El1SyncIa {{ .El1SyncIa.Value }}
|
||||
#define El1SyncSpPc {{ .El1SyncSpPc.Value }}
|
||||
#define El1SyncUndef {{ .El1SyncUndef.Value }}
|
||||
#define El1SyncDbg {{ .El1SyncDbg.Value }}
|
||||
#define El1SyncInv {{ .El1SyncInv.Value }}
|
||||
#define El0SyncSVC {{ .El0SyncSVC.Value }}
|
||||
#define El0SyncDa {{ .El0SyncDa.Value }}
|
||||
#define El0SyncIa {{ .El0SyncIa.Value }}
|
||||
#define El0SyncFpsimdAcc {{ .El0SyncFpsimdAcc.Value }}
|
||||
#define El0SyncSveAcc {{ .El0SyncSveAcc.Value }}
|
||||
#define El0SyncFpsimdExc {{ .El0SyncFpsimdExc.Value }}
|
||||
#define El0SyncSys {{ .El0SyncSys.Value }}
|
||||
#define El0SyncSpPc {{ .El0SyncSpPc.Value }}
|
||||
#define El0SyncUndef {{ .El0SyncUndef.Value }}
|
||||
#define El0SyncDbg {{ .El0SyncDbg.Value }}
|
||||
#define El0SyncWfx {{ .El0SyncWfx.Value }}
|
||||
#define El0SyncInv {{ .El0SyncInv.Value }}
|
||||
#define El0ErrNMI {{ .El0ErrNMI.Value }}
|
||||
#define PageFault {{ .PageFault.Value }}
|
||||
#define Syscall {{ .Syscall.Value }}
|
||||
#define VirtualizationException {{ .VirtualizationException.Value }}
|
||||
|
||||
{{ with .import.linux.PtraceRegs }}
|
||||
#define PTRACE_R0 ({{ .Regs.Offset }} + 0*8)
|
||||
#define PTRACE_R1 ({{ .Regs.Offset }} + 1*8)
|
||||
#define PTRACE_R2 ({{ .Regs.Offset }} + 2*8)
|
||||
#define PTRACE_R3 ({{ .Regs.Offset }} + 3*8)
|
||||
#define PTRACE_R4 ({{ .Regs.Offset }} + 4*8)
|
||||
#define PTRACE_R5 ({{ .Regs.Offset }} + 5*8)
|
||||
#define PTRACE_R6 ({{ .Regs.Offset }} + 6*8)
|
||||
#define PTRACE_R7 ({{ .Regs.Offset }} + 7*8)
|
||||
#define PTRACE_R8 ({{ .Regs.Offset }} + 8*8)
|
||||
#define PTRACE_R9 ({{ .Regs.Offset }} + 9*8)
|
||||
#define PTRACE_R10 ({{ .Regs.Offset }} + 10*8)
|
||||
#define PTRACE_R11 ({{ .Regs.Offset }} + 11*8)
|
||||
#define PTRACE_R12 ({{ .Regs.Offset }} + 12*8)
|
||||
#define PTRACE_R13 ({{ .Regs.Offset }} + 13*8)
|
||||
#define PTRACE_R14 ({{ .Regs.Offset }} + 14*8)
|
||||
#define PTRACE_R15 ({{ .Regs.Offset }} + 15*8)
|
||||
#define PTRACE_R16 ({{ .Regs.Offset }} + 16*8)
|
||||
#define PTRACE_R17 ({{ .Regs.Offset }} + 17*8)
|
||||
#define PTRACE_R18 ({{ .Regs.Offset }} + 18*8)
|
||||
#define PTRACE_R19 ({{ .Regs.Offset }} + 19*8)
|
||||
#define PTRACE_R20 ({{ .Regs.Offset }} + 20*8)
|
||||
#define PTRACE_R21 ({{ .Regs.Offset }} + 21*8)
|
||||
#define PTRACE_R22 ({{ .Regs.Offset }} + 22*8)
|
||||
#define PTRACE_R23 ({{ .Regs.Offset }} + 23*8)
|
||||
#define PTRACE_R24 ({{ .Regs.Offset }} + 24*8)
|
||||
#define PTRACE_R25 ({{ .Regs.Offset }} + 25*8)
|
||||
#define PTRACE_R26 ({{ .Regs.Offset }} + 26*8)
|
||||
#define PTRACE_R27 ({{ .Regs.Offset }} + 27*8)
|
||||
#define PTRACE_R28 ({{ .Regs.Offset }} + 28*8)
|
||||
#define PTRACE_R29 ({{ .Regs.Offset }} + 29*8)
|
||||
#define PTRACE_R30 ({{ .Regs.Offset }} + 30*8)
|
||||
#define PTRACE_SP {{ .Sp.Offset }}
|
||||
#define PTRACE_PC {{ .Pc.Offset }}
|
||||
#define PTRACE_PSTATE {{ .Pstate.Offset }}
|
||||
{{ end }}
|
||||
{{ with .import.arch.Registers }}
|
||||
#define PTRACE_TLS {{ .TPIDR_EL0.Offset }}
|
||||
{{ end }}
|
||||
|
||||
// Saves a register set.
|
||||
//
|
||||
|
||||
@@ -12,13 +12,9 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Binary gen_offsets is a helper for generating offset headers.
|
||||
package main
|
||||
package ring0
|
||||
|
||||
import (
|
||||
"os"
|
||||
// Used for template generation.
|
||||
_ "gvisor.dev/gvisor/pkg/abi/linux"
|
||||
)
|
||||
|
||||
func main() {
|
||||
Emit(os.Stdout)
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
load("//tools:defs.bzl", "go_binary")
|
||||
load("//tools/go_generics:defs.bzl", "go_template_instance")
|
||||
|
||||
package(licenses = ["notice"])
|
||||
|
||||
go_template_instance(
|
||||
name = "defs_impl_arm64",
|
||||
out = "defs_impl_arm64.go",
|
||||
package = "main",
|
||||
template = "//pkg/ring0:defs_arm64",
|
||||
)
|
||||
|
||||
go_template_instance(
|
||||
name = "defs_impl_amd64",
|
||||
out = "defs_impl_amd64.go",
|
||||
package = "main",
|
||||
template = "//pkg/ring0:defs_amd64",
|
||||
)
|
||||
|
||||
go_binary(
|
||||
name = "gen_offsets",
|
||||
srcs = [
|
||||
"defs_impl_amd64.go",
|
||||
"defs_impl_arm64.go",
|
||||
"main.go",
|
||||
],
|
||||
# Use the libc malloc to avoid any extra dependencies. This is required to
|
||||
# pass the sentry deps test.
|
||||
system_malloc = True,
|
||||
visibility = [
|
||||
"//pkg/ring0:__pkg__",
|
||||
"//pkg/sentry/platform/kvm:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
"//pkg/cpuid",
|
||||
"//pkg/hostarch",
|
||||
"//pkg/ring0/pagetables",
|
||||
"//pkg/sentry/arch",
|
||||
"//pkg/sentry/arch/fpu",
|
||||
],
|
||||
)
|
||||
@@ -1,104 +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.
|
||||
|
||||
//go:build amd64
|
||||
// +build amd64
|
||||
|
||||
package ring0
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/sentry/arch"
|
||||
)
|
||||
|
||||
// Emit prints architecture-specific offsets.
|
||||
func Emit(w io.Writer) {
|
||||
fmt.Fprintf(w, "// Automatically generated, do not edit.\n")
|
||||
|
||||
c := &CPU{}
|
||||
fmt.Fprintf(w, "\n// CPU offsets.\n")
|
||||
fmt.Fprintf(w, "#define CPU_REGISTERS 0x%02x\n", reflect.ValueOf(&c.registers).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_ERROR_CODE 0x%02x\n", reflect.ValueOf(&c.errorCode).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_ERROR_TYPE 0x%02x\n", reflect.ValueOf(&c.errorType).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_ENTRY 0x%02x\n", reflect.ValueOf(&c.kernelEntry).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_HAS_XSAVE 0x%02x\n", reflect.ValueOf(&c.hasXSAVE).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_HAS_XSAVEOPT 0x%02x\n", reflect.ValueOf(&c.hasXSAVEOPT).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_FPU_STATE 0x%02x\n", reflect.ValueOf(&c.floatingPointState).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
|
||||
e := &kernelEntry{}
|
||||
fmt.Fprintf(w, "\n// CPU entry offsets.\n")
|
||||
fmt.Fprintf(w, "#define ENTRY_SCRATCH0 0x%02x\n", reflect.ValueOf(&e.scratch0).Pointer()-reflect.ValueOf(e).Pointer())
|
||||
fmt.Fprintf(w, "#define ENTRY_STACK_TOP 0x%02x\n", reflect.ValueOf(&e.stackTop).Pointer()-reflect.ValueOf(e).Pointer())
|
||||
fmt.Fprintf(w, "#define ENTRY_CPU_SELF 0x%02x\n", reflect.ValueOf(&e.cpuSelf).Pointer()-reflect.ValueOf(e).Pointer())
|
||||
fmt.Fprintf(w, "#define ENTRY_KERNEL_CR3 0x%02x\n", reflect.ValueOf(&e.kernelCR3).Pointer()-reflect.ValueOf(e).Pointer())
|
||||
|
||||
fmt.Fprintf(w, "\n// Bits.\n")
|
||||
fmt.Fprintf(w, "#define _RFLAGS_IF 0x%02x\n", _RFLAGS_IF)
|
||||
fmt.Fprintf(w, "#define _RFLAGS_IOPL0 0x%02x\n", _RFLAGS_IOPL0)
|
||||
fmt.Fprintf(w, "#define _KERNEL_FLAGS 0x%02x\n", KernelFlagsSet)
|
||||
|
||||
fmt.Fprintf(w, "\n// Vectors.\n")
|
||||
fmt.Fprintf(w, "#define DivideByZero 0x%02x\n", DivideByZero)
|
||||
fmt.Fprintf(w, "#define Debug 0x%02x\n", Debug)
|
||||
fmt.Fprintf(w, "#define NMI 0x%02x\n", NMI)
|
||||
fmt.Fprintf(w, "#define Breakpoint 0x%02x\n", Breakpoint)
|
||||
fmt.Fprintf(w, "#define Overflow 0x%02x\n", Overflow)
|
||||
fmt.Fprintf(w, "#define BoundRangeExceeded 0x%02x\n", BoundRangeExceeded)
|
||||
fmt.Fprintf(w, "#define InvalidOpcode 0x%02x\n", InvalidOpcode)
|
||||
fmt.Fprintf(w, "#define DeviceNotAvailable 0x%02x\n", DeviceNotAvailable)
|
||||
fmt.Fprintf(w, "#define DoubleFault 0x%02x\n", DoubleFault)
|
||||
fmt.Fprintf(w, "#define CoprocessorSegmentOverrun 0x%02x\n", CoprocessorSegmentOverrun)
|
||||
fmt.Fprintf(w, "#define InvalidTSS 0x%02x\n", InvalidTSS)
|
||||
fmt.Fprintf(w, "#define SegmentNotPresent 0x%02x\n", SegmentNotPresent)
|
||||
fmt.Fprintf(w, "#define StackSegmentFault 0x%02x\n", StackSegmentFault)
|
||||
fmt.Fprintf(w, "#define GeneralProtectionFault 0x%02x\n", GeneralProtectionFault)
|
||||
fmt.Fprintf(w, "#define PageFault 0x%02x\n", PageFault)
|
||||
fmt.Fprintf(w, "#define X87FloatingPointException 0x%02x\n", X87FloatingPointException)
|
||||
fmt.Fprintf(w, "#define AlignmentCheck 0x%02x\n", AlignmentCheck)
|
||||
fmt.Fprintf(w, "#define MachineCheck 0x%02x\n", MachineCheck)
|
||||
fmt.Fprintf(w, "#define SIMDFloatingPointException 0x%02x\n", SIMDFloatingPointException)
|
||||
fmt.Fprintf(w, "#define VirtualizationException 0x%02x\n", VirtualizationException)
|
||||
fmt.Fprintf(w, "#define SecurityException 0x%02x\n", SecurityException)
|
||||
fmt.Fprintf(w, "#define SyscallInt80 0x%02x\n", SyscallInt80)
|
||||
fmt.Fprintf(w, "#define Syscall 0x%02x\n", Syscall)
|
||||
|
||||
p := &arch.Registers{}
|
||||
fmt.Fprintf(w, "\n// Ptrace registers.\n")
|
||||
fmt.Fprintf(w, "#define PTRACE_R15 0x%02x\n", reflect.ValueOf(&p.R15).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R14 0x%02x\n", reflect.ValueOf(&p.R14).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R13 0x%02x\n", reflect.ValueOf(&p.R13).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R12 0x%02x\n", reflect.ValueOf(&p.R12).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_RBP 0x%02x\n", reflect.ValueOf(&p.Rbp).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_RBX 0x%02x\n", reflect.ValueOf(&p.Rbx).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R11 0x%02x\n", reflect.ValueOf(&p.R11).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R10 0x%02x\n", reflect.ValueOf(&p.R10).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R9 0x%02x\n", reflect.ValueOf(&p.R9).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R8 0x%02x\n", reflect.ValueOf(&p.R8).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_RAX 0x%02x\n", reflect.ValueOf(&p.Rax).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_RCX 0x%02x\n", reflect.ValueOf(&p.Rcx).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_RDX 0x%02x\n", reflect.ValueOf(&p.Rdx).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_RSI 0x%02x\n", reflect.ValueOf(&p.Rsi).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_RDI 0x%02x\n", reflect.ValueOf(&p.Rdi).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_ORIGRAX 0x%02x\n", reflect.ValueOf(&p.Orig_rax).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_RIP 0x%02x\n", reflect.ValueOf(&p.Rip).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_CS 0x%02x\n", reflect.ValueOf(&p.Cs).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_FLAGS 0x%02x\n", reflect.ValueOf(&p.Eflags).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_RSP 0x%02x\n", reflect.ValueOf(&p.Rsp).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_SS 0x%02x\n", reflect.ValueOf(&p.Ss).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_FS_BASE 0x%02x\n", reflect.ValueOf(&p.Fs_base).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_GS_BASE 0x%02x\n", reflect.ValueOf(&p.Gs_base).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
//go:build arm64
|
||||
// +build arm64
|
||||
|
||||
package ring0
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/sentry/arch"
|
||||
)
|
||||
|
||||
// Emit prints architecture-specific offsets.
|
||||
func Emit(w io.Writer) {
|
||||
fmt.Fprintf(w, "// Automatically generated, do not edit.\n")
|
||||
|
||||
c := &CPU{}
|
||||
fmt.Fprintf(w, "\n// CPU offsets.\n")
|
||||
fmt.Fprintf(w, "#define CPU_SELF 0x%02x\n", reflect.ValueOf(&c.self).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_REGISTERS 0x%02x\n", reflect.ValueOf(&c.registers).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_STACK_TOP 0x%02x\n", reflect.ValueOf(&c.stack[0]).Pointer()-reflect.ValueOf(c).Pointer()+uintptr(len(c.stack)))
|
||||
fmt.Fprintf(w, "#define CPU_ERROR_CODE 0x%02x\n", reflect.ValueOf(&c.errorCode).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_ERROR_TYPE 0x%02x\n", reflect.ValueOf(&c.errorType).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_FAULT_ADDR 0x%02x\n", reflect.ValueOf(&c.faultAddr).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_FPSTATE_EL0 0x%02x\n", reflect.ValueOf(&c.el0Fp).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_TTBR0_KVM 0x%02x\n", reflect.ValueOf(&c.ttbr0Kvm).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_TTBR0_APP 0x%02x\n", reflect.ValueOf(&c.ttbr0App).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_VECTOR_CODE 0x%02x\n", reflect.ValueOf(&c.vecCode).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_APP_ADDR 0x%02x\n", reflect.ValueOf(&c.appAddr).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_LAZY_VFP 0x%02x\n", reflect.ValueOf(&c.lazyVFP).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_APP_ASID 0x%02x\n", reflect.ValueOf(&c.appASID).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
|
||||
fmt.Fprintf(w, "\n// Bits.\n")
|
||||
fmt.Fprintf(w, "#define _KERNEL_FLAGS 0x%02x\n", KernelFlagsSet)
|
||||
|
||||
fmt.Fprintf(w, "\n// Vectors.\n")
|
||||
|
||||
fmt.Fprintf(w, "#define El1Sync 0x%02x\n", El1Sync)
|
||||
fmt.Fprintf(w, "#define El1Irq 0x%02x\n", El1Irq)
|
||||
fmt.Fprintf(w, "#define El1Fiq 0x%02x\n", El1Fiq)
|
||||
fmt.Fprintf(w, "#define El1Err 0x%02x\n", El1Err)
|
||||
|
||||
fmt.Fprintf(w, "#define El0Sync 0x%02x\n", El0Sync)
|
||||
fmt.Fprintf(w, "#define El0Irq 0x%02x\n", El0Irq)
|
||||
fmt.Fprintf(w, "#define El0Fiq 0x%02x\n", El0Fiq)
|
||||
fmt.Fprintf(w, "#define El0Err 0x%02x\n", El0Err)
|
||||
|
||||
fmt.Fprintf(w, "#define El1SyncDa 0x%02x\n", El1SyncDa)
|
||||
fmt.Fprintf(w, "#define El1SyncIa 0x%02x\n", El1SyncIa)
|
||||
fmt.Fprintf(w, "#define El1SyncSpPc 0x%02x\n", El1SyncSpPc)
|
||||
fmt.Fprintf(w, "#define El1SyncUndef 0x%02x\n", El1SyncUndef)
|
||||
fmt.Fprintf(w, "#define El1SyncDbg 0x%02x\n", El1SyncDbg)
|
||||
fmt.Fprintf(w, "#define El1SyncInv 0x%02x\n", El1SyncInv)
|
||||
|
||||
fmt.Fprintf(w, "#define El0SyncSVC 0x%02x\n", El0SyncSVC)
|
||||
fmt.Fprintf(w, "#define El0SyncDa 0x%02x\n", El0SyncDa)
|
||||
fmt.Fprintf(w, "#define El0SyncIa 0x%02x\n", El0SyncIa)
|
||||
fmt.Fprintf(w, "#define El0SyncFpsimdAcc 0x%02x\n", El0SyncFpsimdAcc)
|
||||
fmt.Fprintf(w, "#define El0SyncSveAcc 0x%02x\n", El0SyncSveAcc)
|
||||
fmt.Fprintf(w, "#define El0SyncFpsimdExc 0x%02x\n", El0SyncFpsimdExc)
|
||||
fmt.Fprintf(w, "#define El0SyncSys 0x%02x\n", El0SyncSys)
|
||||
fmt.Fprintf(w, "#define El0SyncSpPc 0x%02x\n", El0SyncSpPc)
|
||||
fmt.Fprintf(w, "#define El0SyncUndef 0x%02x\n", El0SyncUndef)
|
||||
fmt.Fprintf(w, "#define El0SyncDbg 0x%02x\n", El0SyncDbg)
|
||||
fmt.Fprintf(w, "#define El0SyncWfx 0x%02x\n", El0SyncWfx)
|
||||
fmt.Fprintf(w, "#define El0SyncInv 0x%02x\n", El0SyncInv)
|
||||
|
||||
fmt.Fprintf(w, "#define El0ErrNMI 0x%02x\n", El0ErrNMI)
|
||||
|
||||
fmt.Fprintf(w, "#define PageFault 0x%02x\n", PageFault)
|
||||
fmt.Fprintf(w, "#define Syscall 0x%02x\n", Syscall)
|
||||
fmt.Fprintf(w, "#define VirtualizationException 0x%02x\n", VirtualizationException)
|
||||
|
||||
p := &arch.Registers{}
|
||||
fmt.Fprintf(w, "\n// Ptrace registers.\n")
|
||||
fmt.Fprintf(w, "#define PTRACE_R0 0x%02x\n", reflect.ValueOf(&p.Regs[0]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R1 0x%02x\n", reflect.ValueOf(&p.Regs[1]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R2 0x%02x\n", reflect.ValueOf(&p.Regs[2]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R3 0x%02x\n", reflect.ValueOf(&p.Regs[3]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R4 0x%02x\n", reflect.ValueOf(&p.Regs[4]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R5 0x%02x\n", reflect.ValueOf(&p.Regs[5]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R6 0x%02x\n", reflect.ValueOf(&p.Regs[6]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R7 0x%02x\n", reflect.ValueOf(&p.Regs[7]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R8 0x%02x\n", reflect.ValueOf(&p.Regs[8]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R9 0x%02x\n", reflect.ValueOf(&p.Regs[9]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R10 0x%02x\n", reflect.ValueOf(&p.Regs[10]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R11 0x%02x\n", reflect.ValueOf(&p.Regs[11]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R12 0x%02x\n", reflect.ValueOf(&p.Regs[12]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R13 0x%02x\n", reflect.ValueOf(&p.Regs[13]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R14 0x%02x\n", reflect.ValueOf(&p.Regs[14]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R15 0x%02x\n", reflect.ValueOf(&p.Regs[15]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R16 0x%02x\n", reflect.ValueOf(&p.Regs[16]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R17 0x%02x\n", reflect.ValueOf(&p.Regs[17]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R18 0x%02x\n", reflect.ValueOf(&p.Regs[18]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R19 0x%02x\n", reflect.ValueOf(&p.Regs[19]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R20 0x%02x\n", reflect.ValueOf(&p.Regs[20]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R21 0x%02x\n", reflect.ValueOf(&p.Regs[21]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R22 0x%02x\n", reflect.ValueOf(&p.Regs[22]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R23 0x%02x\n", reflect.ValueOf(&p.Regs[23]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R24 0x%02x\n", reflect.ValueOf(&p.Regs[24]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R25 0x%02x\n", reflect.ValueOf(&p.Regs[25]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R26 0x%02x\n", reflect.ValueOf(&p.Regs[26]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R27 0x%02x\n", reflect.ValueOf(&p.Regs[27]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R28 0x%02x\n", reflect.ValueOf(&p.Regs[28]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R29 0x%02x\n", reflect.ValueOf(&p.Regs[29]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_R30 0x%02x\n", reflect.ValueOf(&p.Regs[30]).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_SP 0x%02x\n", reflect.ValueOf(&p.Sp).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_PC 0x%02x\n", reflect.ValueOf(&p.Pc).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_PSTATE 0x%02x\n", reflect.ValueOf(&p.Pstate).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
fmt.Fprintf(w, "#define PTRACE_TLS 0x%02x\n", reflect.ValueOf(&p.TPIDR_EL0).Pointer()-reflect.ValueOf(p).Pointer())
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
load("//tools:defs.bzl", "go_library", "go_test")
|
||||
load("//tools:defs.bzl", "arch_genrule", "go_library", "go_test", "select_arch")
|
||||
load("//tools/go_generics:defs.bzl", "go_template_instance")
|
||||
load("//tools/nogo:defs.bzl", "nogo_facts")
|
||||
|
||||
package(licenses = ["notice"])
|
||||
|
||||
@@ -14,6 +15,37 @@ go_template_instance(
|
||||
},
|
||||
)
|
||||
|
||||
nogo_facts(
|
||||
name = "bluepill_impl",
|
||||
srcs = [
|
||||
"//pkg/ring0:aarch64.go",
|
||||
"//pkg/ring0:defs.go",
|
||||
"//pkg/ring0:defs_amd64.go",
|
||||
"//pkg/ring0:defs_arm64.go",
|
||||
"//pkg/ring0:entry_template.go",
|
||||
"//pkg/ring0:x86.go",
|
||||
],
|
||||
output = "bluepill_impl.s",
|
||||
template = select_arch(
|
||||
amd64 = "bluepill_amd64.s",
|
||||
arm64 = "bluepill_arm64.s",
|
||||
),
|
||||
deps = [
|
||||
"//pkg/abi/linux",
|
||||
"//pkg/cpuid",
|
||||
"//pkg/hostarch",
|
||||
"//pkg/ring0/pagetables",
|
||||
"//pkg/sentry/arch",
|
||||
"//pkg/sentry/arch/fpu",
|
||||
],
|
||||
)
|
||||
|
||||
arch_genrule(
|
||||
name = "bluepill_impl_arch",
|
||||
src = ":bluepill_impl",
|
||||
template = "bluepill_impl_%s.s",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "kvm",
|
||||
srcs = [
|
||||
@@ -26,10 +58,8 @@ go_library(
|
||||
"bluepill_amd64.go",
|
||||
"bluepill_amd64_unsafe.go",
|
||||
"bluepill_arm64.go",
|
||||
"bluepill_arm64.s",
|
||||
"bluepill_arm64_unsafe.go",
|
||||
"bluepill_fault.go",
|
||||
"bluepill_impl_amd64.s",
|
||||
"bluepill_unsafe.go",
|
||||
"context.go",
|
||||
"filters_amd64.go",
|
||||
@@ -51,6 +81,7 @@ go_library(
|
||||
"physical_map_amd64.go",
|
||||
"physical_map_arm64.go",
|
||||
"virtual_map.go",
|
||||
":bluepill_impl_arch",
|
||||
],
|
||||
visibility = ["//pkg/sentry:internal"],
|
||||
deps = [
|
||||
@@ -113,11 +144,3 @@ go_test(
|
||||
"@org_golang_x_sys//unix:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
genrule(
|
||||
name = "bluepill_impl_amd64",
|
||||
srcs = ["bluepill_amd64.s"],
|
||||
outs = ["bluepill_impl_amd64.s"],
|
||||
cmd = "(echo -e '// build +amd64\\n' && $(location //pkg/ring0/gen_offsets) && cat $(SRCS)) > $@",
|
||||
tools = ["//pkg/ring0/gen_offsets"],
|
||||
)
|
||||
|
||||
@@ -19,6 +19,11 @@
|
||||
// This is guaranteed to be zero.
|
||||
#define VCPU_CPU 0x0
|
||||
|
||||
// ENTRY_CPU_SELF is the location of the CPU in the entry struct.
|
||||
//
|
||||
// This is sourced from ring0.
|
||||
#define ENTRY_CPU_SELF {{ .kernelEntry.cpuSelf.Offset }}
|
||||
|
||||
// Context offsets.
|
||||
//
|
||||
// Only limited use of the context is done in the assembly stub below, most is
|
||||
@@ -32,6 +37,7 @@
|
||||
// This is checked as the source of the fault.
|
||||
#define CLI $0xfa
|
||||
|
||||
// System call definitions.
|
||||
#define SYS_MMAP 9
|
||||
|
||||
// See bluepill.go.
|
||||
|
||||
@@ -30,9 +30,11 @@ var (
|
||||
Bool = flag.Bool
|
||||
CommandLine = flag.CommandLine
|
||||
Int = flag.Int
|
||||
Int64 = flag.Int64
|
||||
NewFlagSet = flag.NewFlagSet
|
||||
Parse = flag.Parse
|
||||
String = flag.String
|
||||
StringVar = flag.StringVar
|
||||
Uint = flag.Uint
|
||||
Var = flag.Var
|
||||
)
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
diff --git a/language/go/generate.go b/language/go/generate.go
|
||||
index 2892948..feb4ad6 100644
|
||||
--- a/language/go/generate.go
|
||||
+++ b/language/go/generate.go
|
||||
@@ -691,6 +691,10 @@ func (g *generator) setImportAttrs(r *rule.Rule, importPath string) {
|
||||
}
|
||||
|
||||
func (g *generator) commonVisibility(importPath string) []string {
|
||||
+ if importPath == "golang.org/x/tools/go/analysis/internal/facts" {
|
||||
+ // Imported by nogo main. We add a visibility exception.
|
||||
+ return []string{"//visibility:public"}
|
||||
+ }
|
||||
// If the Bazel package name (rel) contains "internal", add visibility for
|
||||
// subpackages of the parent.
|
||||
// If the import path contains "internal" but rel does not, this is
|
||||
+22
-41
@@ -33,6 +33,28 @@ def select_system(linux = ["__linux__"], darwin = [], **kwargs):
|
||||
"//conditions:default": linux,
|
||||
})
|
||||
|
||||
arch_config = [
|
||||
"//command_line_option:cpu",
|
||||
"//command_line_option:crosstool_top",
|
||||
"//command_line_option:platforms",
|
||||
]
|
||||
|
||||
def arm64_config(settings, attr):
|
||||
return {
|
||||
"//command_line_option:cpu": "aarch64",
|
||||
"//command_line_option:crosstool_top": "@crosstool//:toolchains",
|
||||
"//command_line_option:platforms": "@io_bazel_rules_go//go/toolchain:linux_arm64",
|
||||
}
|
||||
|
||||
def amd64_config(settings, attr):
|
||||
return {
|
||||
"//command_line_option:cpu": "k8",
|
||||
"//command_line_option:crosstool_top": "@crosstool//:toolchains",
|
||||
"//command_line_option:platforms": "@io_bazel_rules_go//go/toolchain:linux_amd64",
|
||||
}
|
||||
|
||||
transition_allowlist = "@bazel_tools//tools/allowlists/function_transition_allowlist"
|
||||
|
||||
def default_installer():
|
||||
return None
|
||||
|
||||
@@ -41,44 +63,3 @@ def default_net_util():
|
||||
|
||||
def coreutil():
|
||||
return [] # Nothing needed.
|
||||
|
||||
def select_native_vs_cross(native = [], amd64 = [], arm64 = [], cross = []):
|
||||
values = {
|
||||
"//tools/bazeldefs:linux_arm64_cross": arm64 + cross,
|
||||
"//tools/bazeldefs:linux_amd64_cross": amd64 + cross,
|
||||
"//conditions:default": native,
|
||||
}
|
||||
return select(values)
|
||||
|
||||
def arch_genrule(name, srcs, outs, cmd, tools):
|
||||
"""Runs a gen command on the target architecture.
|
||||
|
||||
If the target architecture isn't match the host architecture, it will build
|
||||
a command for the target architecture and run it via qemu.
|
||||
|
||||
The native genrule runs the command on the host architecture.
|
||||
|
||||
Args:
|
||||
name: name of generated target.
|
||||
srcs: A list of inputs for this rule.
|
||||
cmd: The command to run. It has to contain " QEMU " before executed binaries.
|
||||
outs: A list of files generated by this rule.
|
||||
tools: A list of tool dependencies for this rule.
|
||||
"""
|
||||
qemu_arm64 = "qemu-aarch64-static"
|
||||
qemu_amd64 = "qemu-x86_64-static"
|
||||
srcs = select_native_vs_cross(
|
||||
cross = srcs + tools,
|
||||
native = srcs,
|
||||
)
|
||||
tools = select_native_vs_cross(
|
||||
cross = [],
|
||||
native = tools,
|
||||
)
|
||||
cmd = select_native_vs_cross(
|
||||
arm64 = cmd.replace("QEMU", qemu_arm64),
|
||||
amd64 = cmd.replace("QEMU", qemu_amd64),
|
||||
native = cmd.replace("QEMU", ""),
|
||||
cross = "",
|
||||
)
|
||||
native.genrule(name = name, srcs = srcs, outs = outs, cmd = cmd, tools = tools)
|
||||
|
||||
@@ -135,17 +135,13 @@ def go_context(ctx, goos = None, goarch = None, std = False):
|
||||
go_ctx = _go_context(ctx)
|
||||
if goos == None:
|
||||
goos = go_ctx.sdk.goos
|
||||
elif goos != go_ctx.sdk.goos:
|
||||
fail("Internal GOOS (%s) doesn't match GoSdk GOOS (%s)." % (goos, go_ctx.sdk.goos))
|
||||
if goarch == None:
|
||||
goarch = go_ctx.sdk.goarch
|
||||
elif goarch != go_ctx.sdk.goarch:
|
||||
fail("Internal GOARCH (%s) doesn't match GoSdk GOARCH (%s)." % (goarch, go_ctx.sdk.goarch))
|
||||
return struct(
|
||||
env = go_ctx.env,
|
||||
go = go_ctx.go,
|
||||
goarch = go_ctx.sdk.goarch,
|
||||
goos = go_ctx.sdk.goos,
|
||||
goarch = goarch,
|
||||
goos = goos,
|
||||
gotags = go_ctx.tags,
|
||||
nogo_args = [],
|
||||
runfiles = depset([go_ctx.go] + go_ctx.sdk.srcs + go_ctx.sdk.tools + go_ctx.stdlib.libs),
|
||||
|
||||
@@ -8,7 +8,7 @@ go_library(
|
||||
nogo = False,
|
||||
visibility = ["//tools/nogo:__subpackages__"],
|
||||
deps = [
|
||||
"//tools/nogo/objdump",
|
||||
"//tools/nogo/flags",
|
||||
"@org_golang_x_tools//go/analysis:go_default_library",
|
||||
"@org_golang_x_tools//go/analysis/passes/buildssa:go_default_library",
|
||||
"@org_golang_x_tools//go/ssa:go_default_library",
|
||||
|
||||
+151
-115
@@ -66,14 +66,17 @@ import (
|
||||
"go/token"
|
||||
"go/types"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/analysis/passes/buildssa"
|
||||
"golang.org/x/tools/go/ssa"
|
||||
"gvisor.dev/gvisor/tools/nogo/objdump"
|
||||
"gvisor.dev/gvisor/tools/nogo/flags"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -177,21 +180,30 @@ type packageEscapeFacts struct {
|
||||
// AFact implements analysis.Fact.AFact.
|
||||
func (*packageEscapeFacts) AFact() {}
|
||||
|
||||
// Analyzer includes specific results.
|
||||
var Analyzer = &analysis.Analyzer{
|
||||
Name: "checkescape",
|
||||
Doc: "escape analysis checks based on +checkescape annotations",
|
||||
Run: runSelectEscapes,
|
||||
Requires: []*analysis.Analyzer{buildssa.Analyzer},
|
||||
FactTypes: []analysis.Fact{(*packageEscapeFacts)(nil)},
|
||||
// objdumpAnalyzer accepts the objdump parameter.
|
||||
type objdumpAnalyzer struct {
|
||||
analysis.Analyzer
|
||||
}
|
||||
|
||||
// EscapeAnalyzer includes all local escape results.
|
||||
var EscapeAnalyzer = &analysis.Analyzer{
|
||||
Name: "checkescape",
|
||||
Doc: "complete local escape analysis results (requires Analyzer facts)",
|
||||
Run: runAllEscapes,
|
||||
Requires: []*analysis.Analyzer{buildssa.Analyzer},
|
||||
// Run implements nogo.binaryAnalyzer.Run.
|
||||
func (ob *objdumpAnalyzer) Run(pass *analysis.Pass, binary io.Reader) (interface{}, error) {
|
||||
return run(pass, binary)
|
||||
}
|
||||
|
||||
// Legacy implements nogo.analyzer.Legacy.
|
||||
func (ob *objdumpAnalyzer) Legacy() *analysis.Analyzer {
|
||||
return &ob.Analyzer
|
||||
}
|
||||
|
||||
// Analyzer includes specific results.
|
||||
var Analyzer = &objdumpAnalyzer{
|
||||
Analyzer: analysis.Analyzer{
|
||||
Name: "checkescape",
|
||||
Doc: "escape analysis checks based on +checkescape annotations",
|
||||
Run: nil, // Must be invoked via Run above.
|
||||
Requires: []*analysis.Analyzer{buildssa.Analyzer},
|
||||
FactTypes: []analysis.Fact{(*packageEscapeFacts)(nil)},
|
||||
},
|
||||
}
|
||||
|
||||
// LinePosition is a low-resolution token.Position.
|
||||
@@ -356,7 +368,65 @@ func MergeAll(others []Escapes) (es Escapes) {
|
||||
//
|
||||
// Note that the map uses <basename.go>:<line> because that is all that is
|
||||
// provided in the objdump format. Since this is all local, it is sufficient.
|
||||
func loadObjdump() (map[string][]string, error) {
|
||||
func loadObjdump(binary io.Reader) (finalResults map[string][]string, finalErr error) {
|
||||
// Do we have a binary? If it's missing, then the nil will simply be
|
||||
// plumbed all the way down here.
|
||||
if binary == nil {
|
||||
return nil, fmt.Errorf("no binary provided")
|
||||
}
|
||||
|
||||
// Construct & start our command. The 'go tool objdump' command
|
||||
// requires a seekable input passed on the command line. Therefore, we
|
||||
// may need to generate a temporary file here.
|
||||
input, ok := binary.(*os.File)
|
||||
if ok {
|
||||
// Ensure that the file is seekable and that the offset is
|
||||
// zero, since we can't control that.
|
||||
if offset, err := input.Seek(0, os.SEEK_CUR); err != nil || offset != 0 {
|
||||
ok = false // Not usable.
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
// Copy to a temporary path.
|
||||
f, err := ioutil.TempFile("", "")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to create temp file: %w", err)
|
||||
}
|
||||
// Ensure the file is deleted.
|
||||
defer os.Remove(f.Name())
|
||||
// Populate the file contents.
|
||||
if _, err := io.Copy(f, binary); err != nil {
|
||||
return nil, fmt.Errorf("unable to populate temp file: %w", err)
|
||||
}
|
||||
// Seek to the beginning.
|
||||
if _, err := f.Seek(0, os.SEEK_SET); err != nil {
|
||||
return nil, fmt.Errorf("unable to seek in temp file: %w", err)
|
||||
}
|
||||
input = f
|
||||
}
|
||||
|
||||
// Execute go tool objdump ggiven the input.
|
||||
cmd := exec.Command(flags.Go, "tool", "objdump", input.Name())
|
||||
cmd.Stderr = os.Stderr
|
||||
pipeOut, pipeErr := cmd.StdoutPipe()
|
||||
if pipeErr != nil {
|
||||
return nil, fmt.Errorf("unable to load objdump: %w", pipeErr)
|
||||
}
|
||||
if startErr := cmd.Start(); startErr != nil {
|
||||
return nil, fmt.Errorf("unable to start objdump: %w", startErr)
|
||||
}
|
||||
|
||||
// Ensure that the command has finished successfully. Note that even if
|
||||
// we parse the first few lines correctly, and early exit could
|
||||
// indicate that the dump was incomplete and we could be missed some
|
||||
// escapes that would have appeared. We need to force failure.
|
||||
defer func() {
|
||||
if waitErr := cmd.Wait(); finalErr == nil && waitErr != nil {
|
||||
// Override the function's return value in this case.
|
||||
finalErr = fmt.Errorf("error running objdump: %v", waitErr)
|
||||
}
|
||||
}()
|
||||
|
||||
// Identify calls by address or name. Note that this is also
|
||||
// constructed dynamically below, as we encounted the addresses.
|
||||
// This is because some of the functions (duffzero) may have
|
||||
@@ -389,83 +459,78 @@ func loadObjdump() (map[string][]string, error) {
|
||||
// Build the map.
|
||||
nextFunc := "" // For funcsAllowed.
|
||||
m := make(map[string][]string)
|
||||
if err := objdump.Load(func(origR io.Reader) error {
|
||||
r := bufio.NewReader(origR)
|
||||
NextLine:
|
||||
for {
|
||||
line, err := r.ReadString('\n')
|
||||
if err != nil && err != io.EOF {
|
||||
return err
|
||||
r := bufio.NewReader(pipeOut)
|
||||
NextLine:
|
||||
for {
|
||||
line, err := r.ReadString('\n')
|
||||
if err != nil && err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
fields := strings.Fields(line)
|
||||
|
||||
// Is this an "allowed" function definition?
|
||||
if len(fields) >= 2 && fields[0] == "TEXT" {
|
||||
nextFunc = strings.TrimSuffix(fields[1], "(SB)")
|
||||
if _, ok := funcsAllowed[nextFunc]; !ok {
|
||||
nextFunc = "" // Don't record addresses.
|
||||
}
|
||||
fields := strings.Fields(line)
|
||||
}
|
||||
if nextFunc != "" && len(fields) > 2 {
|
||||
// Save the given address (in hex form, as it appears).
|
||||
addrsAllowed[fields[1]] = struct{}{}
|
||||
}
|
||||
|
||||
// Is this an "allowed" function definition?
|
||||
if len(fields) >= 2 && fields[0] == "TEXT" {
|
||||
nextFunc = strings.TrimSuffix(fields[1], "(SB)")
|
||||
if _, ok := funcsAllowed[nextFunc]; !ok {
|
||||
nextFunc = "" // Don't record addresses.
|
||||
}
|
||||
// We recognize lines corresponding to actual code (not the
|
||||
// symbol name or other metadata) and annotate them if they
|
||||
// correspond to an explicit CALL instruction. We assume that
|
||||
// the lack of a CALL for a given line is evidence that escape
|
||||
// analysis has eliminated an allocation.
|
||||
//
|
||||
// Lines look like this (including the first space):
|
||||
// gohacks_unsafe.go:33 0xa39 488b442408 MOVQ 0x8(SP), AX
|
||||
if len(fields) >= 5 && line[0] == ' ' {
|
||||
if !strings.Contains(fields[3], "CALL") {
|
||||
continue
|
||||
}
|
||||
if nextFunc != "" && len(fields) > 2 {
|
||||
// Save the given address (in hex form, as it appears).
|
||||
addrsAllowed[fields[1]] = struct{}{}
|
||||
site := fields[0]
|
||||
target := strings.TrimSuffix(fields[4], "(SB)")
|
||||
|
||||
// Ignore strings containing allowed functions.
|
||||
if _, ok := funcsAllowed[target]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// We recognize lines corresponding to actual code (not the
|
||||
// symbol name or other metadata) and annotate them if they
|
||||
// correspond to an explicit CALL instruction. We assume that
|
||||
// the lack of a CALL for a given line is evidence that escape
|
||||
// analysis has eliminated an allocation.
|
||||
//
|
||||
// Lines look like this (including the first space):
|
||||
// gohacks_unsafe.go:33 0xa39 488b442408 MOVQ 0x8(SP), AX
|
||||
if len(fields) >= 5 && line[0] == ' ' {
|
||||
if !strings.Contains(fields[3], "CALL") {
|
||||
continue
|
||||
}
|
||||
site := fields[0]
|
||||
target := strings.TrimSuffix(fields[4], "(SB)")
|
||||
|
||||
// Ignore strings containing allowed functions.
|
||||
if _, ok := funcsAllowed[target]; ok {
|
||||
continue
|
||||
}
|
||||
if _, ok := addrsAllowed[target]; ok {
|
||||
continue
|
||||
}
|
||||
if len(fields) > 5 {
|
||||
// This may be a future relocation. Some
|
||||
// objdump versions describe this differently.
|
||||
// If it contains any of the functions allowed
|
||||
// above as a string, we let it go.
|
||||
softTarget := strings.Join(fields[5:], " ")
|
||||
for name := range funcsAllowed {
|
||||
if strings.Contains(softTarget, name) {
|
||||
continue NextLine
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Does this exist already?
|
||||
existing, ok := m[site]
|
||||
if !ok {
|
||||
existing = make([]string, 0, 1)
|
||||
}
|
||||
for _, other := range existing {
|
||||
if target == other {
|
||||
if _, ok := addrsAllowed[target]; ok {
|
||||
continue
|
||||
}
|
||||
if len(fields) > 5 {
|
||||
// This may be a future relocation. Some
|
||||
// objdump versions describe this differently.
|
||||
// If it contains any of the functions allowed
|
||||
// above as a string, we let it go.
|
||||
softTarget := strings.Join(fields[5:], " ")
|
||||
for name := range funcsAllowed {
|
||||
if strings.Contains(softTarget, name) {
|
||||
continue NextLine
|
||||
}
|
||||
}
|
||||
existing = append(existing, target)
|
||||
m[site] = existing // Update.
|
||||
}
|
||||
if err == io.EOF {
|
||||
break
|
||||
|
||||
// Does this exist already?
|
||||
existing, ok := m[site]
|
||||
if !ok {
|
||||
existing = make([]string, 0, 1)
|
||||
}
|
||||
for _, other := range existing {
|
||||
if target == other {
|
||||
continue NextLine
|
||||
}
|
||||
}
|
||||
existing = append(existing, target)
|
||||
m[site] = existing // Update.
|
||||
}
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Zap any accidental false positives.
|
||||
@@ -489,16 +554,6 @@ type poser interface {
|
||||
Pos() token.Pos
|
||||
}
|
||||
|
||||
// runSelectEscapes runs with only select escapes.
|
||||
func runSelectEscapes(pass *analysis.Pass) (interface{}, error) {
|
||||
return run(pass, false)
|
||||
}
|
||||
|
||||
// runAllEscapes runs with all escapes included.
|
||||
func runAllEscapes(pass *analysis.Pass) (interface{}, error) {
|
||||
return run(pass, true)
|
||||
}
|
||||
|
||||
// findReasons extracts reasons from the function.
|
||||
func findReasons(pass *analysis.Pass, fdecl *ast.FuncDecl) ([]EscapeReason, bool, map[EscapeReason]bool) {
|
||||
// Is there a comment?
|
||||
@@ -575,8 +630,8 @@ func findReasons(pass *analysis.Pass, fdecl *ast.FuncDecl) ([]EscapeReason, bool
|
||||
}
|
||||
|
||||
// run performs the analysis.
|
||||
func run(pass *analysis.Pass, localEscapes bool) (interface{}, error) {
|
||||
calls, callsErr := loadObjdump()
|
||||
func run(pass *analysis.Pass, binary io.Reader) (interface{}, error) {
|
||||
calls, callsErr := loadObjdump(binary)
|
||||
if callsErr != nil {
|
||||
// Note that if this analysis fails, then we don't actually
|
||||
// fail the analyzer itself. We simply report every possible
|
||||
@@ -794,15 +849,6 @@ func run(pass *analysis.Pass, localEscapes bool) (interface{}, error) {
|
||||
loadFunc(fn)
|
||||
}
|
||||
|
||||
if !localEscapes {
|
||||
// Export all findings for future packages. We only do this in
|
||||
// non-local escapes mode, and expect to run this analysis
|
||||
// after the SelectAnalysis.
|
||||
pass.ExportPackageFact(&packageEscapeFacts{
|
||||
Funcs: mergedEscapes,
|
||||
})
|
||||
}
|
||||
|
||||
// Scan all functions for violations.
|
||||
for _, f := range pass.Files {
|
||||
// Scan all declarations.
|
||||
@@ -812,18 +858,8 @@ func run(pass *analysis.Pass, localEscapes bool) (interface{}, error) {
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
var (
|
||||
reasons []EscapeReason
|
||||
local bool
|
||||
testReasons map[EscapeReason]bool
|
||||
)
|
||||
if localEscapes {
|
||||
// Find all hard escapes.
|
||||
reasons = hardReasons
|
||||
} else {
|
||||
// Find all declared reasons.
|
||||
reasons, local, testReasons = findReasons(pass, fdecl)
|
||||
}
|
||||
// Find all declared reasons.
|
||||
reasons, local, testReasons := findReasons(pass, fdecl)
|
||||
|
||||
// Scan for matches.
|
||||
fn := pass.TypesInfo.Defs[fdecl.Name].(*types.Func)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
load("//tools:defs.bzl", "go_library")
|
||||
|
||||
package(licenses = ["notice"])
|
||||
|
||||
go_library(
|
||||
name = "checkinfo",
|
||||
srcs = ["checkinfo.go"],
|
||||
nogo = False,
|
||||
visibility = ["//tools/nogo:__subpackages__"],
|
||||
deps = ["@org_golang_x_tools//go/analysis:go_default_library"],
|
||||
)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user