mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Ensure that nogo is enabled.
A recent change stopped using the correct file (the export data, not the archive) and checklocks started failing. Unfortunately, this was suppressed, since the filter command was not failing with findings. This change fixes that problem and adds a test to ensure that this cannot happen again. If nogo starts failing to identify problems, the sanity_test in nogo/sanity will also start to fail. This change also requires updating the WORKSPACE to the latest rules_go and Go version, in order to pick up the fixed go_tools. The latest rules_go in turn required an updated bazel, which in turn required a minor change in the coverdata implementation. Fixing the fact propagation brought forward a number of problems with caching for bazel workers. Its unclear whether this was a core worker issue or whether some caching was broken, but the situation was basically undebugable. Instead, the way facts are stored and loaded is optimized to be able to remove the use of workers altogether and ideally make nogo debuggable. PiperOrigin-RevId: 426327186
This commit is contained in:
committed by
gVisor bot
parent
dce4528a1a
commit
a87bb4aae2
@@ -41,6 +41,9 @@ steps:
|
||||
- <<: *common
|
||||
label: ":fire: Smoke tests"
|
||||
command: make smoke-tests
|
||||
- <<: *common
|
||||
label: ":fire: Smoke race tests"
|
||||
command: make smoke-race-tests
|
||||
- wait
|
||||
|
||||
# Check that the Go branch builds.
|
||||
|
||||
@@ -185,11 +185,14 @@ debian: ## Builds the debian packages.
|
||||
@$(call build,-c opt //debian:debian)
|
||||
.PHONY: debian
|
||||
|
||||
smoke-tests: ## Runs a simple smoke test after build runsc.
|
||||
smoke-tests: ## Runs a simple smoke test after building runsc.
|
||||
@$(call run,//runsc,--alsologtostderr --network none --debug --TESTONLY-unsafe-nonroot=true --rootless do true)
|
||||
@$(call run,$(RACE_FLAGS) //runsc:runsc-race,--alsologtostderr --network none --debug --TESTONLY-unsafe-nonroot=true --rootless do true)
|
||||
.PHONY: smoke-tests
|
||||
|
||||
smoke-race-tests: ## Runs a smoke test after build building runsc in race configuration.
|
||||
@$(call run,$(RACE_FLAGS) //runsc:runsc-race,--alsologtostderr --network none --debug --TESTONLY-unsafe-nonroot=true --rootless do true)
|
||||
.PHONY: smoke-race-tests
|
||||
|
||||
nogo-tests:
|
||||
@$(call test,--build_tag_filters=nogo --test_tag_filters=nogo //:all pkg/... tools/...)
|
||||
.PHONY: nogo-tests
|
||||
|
||||
@@ -39,36 +39,52 @@ http_archive(
|
||||
# Newer versions of the rules_go rules will automatically strip test
|
||||
# binaries of symbols, which we don't want.
|
||||
"//tools:rules_go_symbols.patch",
|
||||
# Allow for patching of the go_sdk.
|
||||
"//tools:rules_go_sdk.patch",
|
||||
],
|
||||
sha256 = "8e968b5fcea1d2d64071872b12737bbb5514524ee5f0a4f54f5920266c261acb",
|
||||
sha256 = "d6b2513456fe2229811da7eb67a444be7785f5323c6708b38d851d2b51e54d83",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.28.0/rules_go-v0.28.0.zip",
|
||||
"https://github.com/bazelbuild/rules_go/releases/download/v0.28.0/rules_go-v0.28.0.zip",
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.30.0/rules_go-v0.30.0.zip",
|
||||
"https://github.com/bazelbuild/rules_go/releases/download/v0.30.0/rules_go-v0.30.0.zip",
|
||||
],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "bazel_gazelle",
|
||||
sha256 = "62ca106be173579c0a167deb23358fdfe71ffa1e4cfdddf5582af26520f1c66f",
|
||||
sha256 = "de69a09dc70417580aabf20a28619bb3ef60d038470c7cf8442fafcf627c21cb",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.23.0/bazel-gazelle-v0.23.0.tar.gz",
|
||||
"https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.23.0/bazel-gazelle-v0.23.0.tar.gz",
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.24.0/bazel-gazelle-v0.24.0.tar.gz",
|
||||
"https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.24.0/bazel-gazelle-v0.24.0.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
|
||||
load("@io_bazel_rules_go//go:deps.bzl", "go_download_sdk", "go_rules_dependencies")
|
||||
load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies", "go_repository")
|
||||
|
||||
go_rules_dependencies()
|
||||
|
||||
go_register_toolchains(go_version = "1.16.8")
|
||||
|
||||
load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies", "go_repository")
|
||||
go_download_sdk(
|
||||
name = "go_sdk",
|
||||
# This implements a fix in the types package which dramatically speeds up
|
||||
# analysis. Without this fix, the nogo rules will often fail to run in
|
||||
# time on our continuous integration.
|
||||
patch = "//tools:go_types_memoize.patch",
|
||||
patch_strip = 2,
|
||||
version = "1.17.6",
|
||||
)
|
||||
|
||||
gazelle_dependencies()
|
||||
|
||||
# Some repository below has a transitive dependency on these repositories.
|
||||
# These declarations must precede any later declarations that transitively
|
||||
# depend on older versions, since only the first declaration is considered.
|
||||
# depend on older versions, since only the first declaration is considered. go_repository(
|
||||
go_repository(
|
||||
name = "org_golang_x_tools",
|
||||
importpath = "golang.org/x/tools",
|
||||
sum = "h1:j9KsMiaP1c3B0OTQGth0/k+miLGTgLsAFUCrF2vLcF8=",
|
||||
version = "v0.1.9",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "org_golang_x_sys",
|
||||
importpath = "golang.org/x/sys",
|
||||
@@ -83,6 +99,20 @@ go_repository(
|
||||
version = "v0.0.0-20210503060351-7fd8e65b6420",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "co_honnef_go_tools",
|
||||
importpath = "honnef.co/go/tools",
|
||||
sum = "h1:MNh1AVMyVX23VUHE2O27jm6lNj3vjO5DexS4A1xvnzk=",
|
||||
version = "v0.2.2",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "org_golang_x_oauth2",
|
||||
importpath = "golang.org/x/oauth2",
|
||||
sum = "h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg=",
|
||||
version = "v0.0.0-20211104180415-d3ed0bb246c8",
|
||||
)
|
||||
|
||||
# Load C++ rules.
|
||||
http_archive(
|
||||
name = "rules_cc",
|
||||
@@ -585,11 +615,11 @@ rbe_autoconfig(name = "rbe_default")
|
||||
|
||||
http_archive(
|
||||
name = "rules_pkg",
|
||||
sha256 = "62eeb544ff1ef41d786e329e1536c1d541bb9bcad27ae984d57f18f314018e66",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/rules_pkg/releases/download/0.6.0/rules_pkg-0.6.0.tar.gz",
|
||||
"https://github.com/bazelbuild/rules_pkg/releases/download/0.6.0/rules_pkg-0.6.0.tar.gz",
|
||||
],
|
||||
sha256 = "62eeb544ff1ef41d786e329e1536c1d541bb9bcad27ae984d57f18f314018e66",
|
||||
)
|
||||
|
||||
load("@rules_pkg//:deps.bzl", "rules_pkg_dependencies")
|
||||
@@ -820,13 +850,6 @@ go_repository(
|
||||
version = "v0.0.0-20191024005414-555d28b269f0",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "org_golang_x_tools",
|
||||
importpath = "golang.org/x/tools",
|
||||
sum = "h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA=",
|
||||
version = "v0.1.5",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "org_golang_x_xerrors",
|
||||
importpath = "golang.org/x/xerrors",
|
||||
@@ -848,13 +871,6 @@ go_repository(
|
||||
version = "v1.5.2",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "org_golang_x_oauth2",
|
||||
importpath = "golang.org/x/oauth2",
|
||||
sum = "h1:B333XXssMuKQeBwiNODx4TupZy7bf4sxFZnN2ZOcvUE=",
|
||||
version = "v0.0.0-20211005180243-6b3c2da341f1",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_docker_docker",
|
||||
importpath = "github.com/docker/docker",
|
||||
@@ -974,13 +990,6 @@ go_repository(
|
||||
version = "v0.23.0",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "co_honnef_go_tools",
|
||||
importpath = "honnef.co/go/tools",
|
||||
sum = "h1:/EPr//+UMMXwMTkXvCCoaJDq8cpjMO80Ou+L4PDo2mY=",
|
||||
version = "v0.2.1",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_burntsushi_toml",
|
||||
importpath = "github.com/BurntSushi/toml",
|
||||
|
||||
@@ -4,7 +4,7 @@ go 1.17
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v0.3.1
|
||||
github.com/bazelbuild/rules_go v0.27.0
|
||||
github.com/bazelbuild/rules_go v0.30.0
|
||||
github.com/cenkalti/backoff v1.1.1-0.20190506075156-2146c9339422
|
||||
github.com/containerd/cgroups v1.0.1
|
||||
github.com/containerd/console v1.0.1
|
||||
|
||||
@@ -57,6 +57,8 @@ github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kd
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/bazelbuild/rules_go v0.27.0 h1:KViqR7qKXwz+LrNdIauCDU21kneCk+4DnYjpvlJwH50=
|
||||
github.com/bazelbuild/rules_go v0.27.0/go.mod h1:MC23Dc/wkXEyk3Wpq6lCqz0ZAYOZDw2DR5y3N1q2i7M=
|
||||
github.com/bazelbuild/rules_go v0.30.0 h1:kX4jVcstqrsRqKPJSn2mq2o+TI21edRzEJSrEOMQtr0=
|
||||
github.com/bazelbuild/rules_go v0.30.0/go.mod h1:MC23Dc/wkXEyk3Wpq6lCqz0ZAYOZDw2DR5y3N1q2i7M=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/cenkalti/backoff v1.1.1-0.20190506075156-2146c9339422 h1:8eZxmY1yvxGHzdzTEhI09npjMVGzNAdrqzruTX6jcK4=
|
||||
|
||||
@@ -24,6 +24,6 @@ RUN curl https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud
|
||||
ln -s /google-cloud-sdk/bin/gcloud /usr/bin/gcloud
|
||||
|
||||
# Download the official bazel binary. The APT repository isn't used because there is not packages for arm64.
|
||||
RUN sh -c 'curl -o /usr/local/bin/bazel https://releases.bazel.build/4.0.0/release/bazel-4.0.0-linux-$(uname -m | sed s/aarch64/arm64/) && chmod ugo+x /usr/local/bin/bazel'
|
||||
RUN sh -c 'curl -o /usr/local/bin/bazel https://releases.bazel.build/4.2.1/release/bazel-4.2.1-linux-$(uname -m | sed s/aarch64/arm64/) && chmod ugo+x /usr/local/bin/bazel'
|
||||
WORKDIR /workspace
|
||||
ENTRYPOINT ["/usr/local/bin/bazel"]
|
||||
|
||||
@@ -51,6 +51,20 @@ global:
|
||||
- "may require checklocks annotation for"
|
||||
# Generated proto code creates declarations like 'var start int = iNdEx'
|
||||
- "should omit type .* from declaration; it will be inferred from the right-hand side"
|
||||
external:
|
||||
suppress:
|
||||
# buildssa can't handle certain packages (cmd/...).
|
||||
- "panic recovered: interface conversion: types.Type is nil"
|
||||
- "panic recovered: runtime error: invalid memory address or nil"
|
||||
- "panic recovered: no type for \\*ast.CallExpr"
|
||||
- "panic recovered: interface conversion: types.Type is \\*types.Basic"
|
||||
- "panic recovered: no type for \\*ast.BinaryExpr"
|
||||
- "panic recovered: no type for \\*ast.SelectorExpr"
|
||||
- "panic recovered: no types.Object for ast.Ident SetTypeErrors"
|
||||
- "panic recovered: unexpected CompositeLit type: invalid type"
|
||||
exclude:
|
||||
- ".*/vet/testdata/.*"
|
||||
- ".*/runtime/testdata/.*"
|
||||
internal:
|
||||
suppress:
|
||||
# We use ALL_CAPS for system definitions,
|
||||
@@ -100,6 +114,9 @@ analyzers:
|
||||
exclude: [".*"]
|
||||
errorsas:
|
||||
external: # Enabled.
|
||||
exclude:
|
||||
# Specific broken case.
|
||||
- ".*/cmd/go/internal/modload/list.go"
|
||||
httpresponse:
|
||||
external: # Enabled.
|
||||
loopclosure:
|
||||
@@ -111,6 +128,7 @@ analyzers:
|
||||
exclude:
|
||||
- pkg/sentry/platform/kvm/kvm_test.go # Intentional.
|
||||
- tools/bigquery/bigquery.go # False positive.
|
||||
- "-" # No filename.
|
||||
printf:
|
||||
external: # Enabled.
|
||||
suppress:
|
||||
@@ -157,6 +175,10 @@ analyzers:
|
||||
external: # Enabled.
|
||||
checkescape:
|
||||
external: # Enabled.
|
||||
suppress:
|
||||
# External libraries may not have binaries (e.g. stdlib testdata, etc.),
|
||||
# so these cases can be safely ignored.
|
||||
- "no such file or directory"
|
||||
checklinkname:
|
||||
external: # Enabled.
|
||||
suppress:
|
||||
@@ -168,6 +190,8 @@ analyzers:
|
||||
# targets in the standard library, so we still need to run
|
||||
# checklinkname on stdlib generally.
|
||||
- "linkname to unknown symbol"
|
||||
exclude:
|
||||
- ".*/containerd/sys/subprocess_unsafe_linux.go"
|
||||
SA1019: # Use of deprecated identifier.
|
||||
# disable for now due to misattribution from golang.org/issue/44195.
|
||||
generated:
|
||||
|
||||
+10
-10
@@ -39,7 +39,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// coverageMu must be held while accessing coverdata.Cover. This prevents
|
||||
// coverageMu must be held while accessing coverdata.*. This prevents
|
||||
// concurrent reads/writes from multiple threads collecting coverage data.
|
||||
coverageMu sync.RWMutex
|
||||
|
||||
@@ -61,7 +61,7 @@ const blockBitLength = 16
|
||||
|
||||
// Available returns whether any coverage data is available.
|
||||
func Available() bool {
|
||||
return len(coverdata.Cover.Blocks) > 0
|
||||
return len(coverdata.Blocks) > 0
|
||||
}
|
||||
|
||||
// EnableReport sets up coverage reporting.
|
||||
@@ -102,7 +102,7 @@ func ClearCoverageData() {
|
||||
// We do not use atomic operations while reading/writing to the counters,
|
||||
// which would drastically degrade performance. Slight discrepancies due to
|
||||
// racing is okay for the purposes of kcov.
|
||||
for _, counters := range coverdata.Cover.Counters {
|
||||
for _, counters := range coverdata.Counters {
|
||||
for index := 0; index < len(counters); index++ {
|
||||
counters[index] = 0
|
||||
}
|
||||
@@ -155,7 +155,7 @@ func ConsumeCoverageData(w io.Writer) int {
|
||||
total := 0
|
||||
var pcBuffer [8]byte
|
||||
for fileNum, file := range globalData.files {
|
||||
counters := coverdata.Cover.Counters[file]
|
||||
counters := coverdata.Counters[file]
|
||||
for index := 0; index < len(counters); index++ {
|
||||
// We do not use atomic operations while reading/writing to the counters,
|
||||
// which would drastically degrade performance. Slight discrepancies due to
|
||||
@@ -194,13 +194,13 @@ func InitCoverageData() {
|
||||
globalData.once.Do(func() {
|
||||
// First, order all files. Then calculate synthetic PCs for every block
|
||||
// (using the well-defined ordering for files as well).
|
||||
for file := range coverdata.Cover.Blocks {
|
||||
for file := range coverdata.Blocks {
|
||||
globalData.files = append(globalData.files, file)
|
||||
}
|
||||
sort.Strings(globalData.files)
|
||||
|
||||
for fileNum, file := range globalData.files {
|
||||
blocks := coverdata.Cover.Blocks[file]
|
||||
blocks := coverdata.Blocks[file]
|
||||
pcs := make([]uint64, 0, len(blocks))
|
||||
for blockNum := range blocks {
|
||||
pcs = append(pcs, calculateSyntheticPC(fileNum, blockNum))
|
||||
@@ -226,8 +226,8 @@ func Report() error {
|
||||
|
||||
var err error
|
||||
reportOnce.Do(func() {
|
||||
for file, counters := range coverdata.Cover.Counters {
|
||||
blocks := coverdata.Cover.Blocks[file]
|
||||
for file, counters := range coverdata.Counters {
|
||||
blocks := coverdata.Blocks[file]
|
||||
for i := 0; i < len(counters); i++ {
|
||||
if atomic.LoadUint32(&counters[i]) > 0 {
|
||||
err = writeBlock(reportOutput, file, blocks[i])
|
||||
@@ -260,7 +260,7 @@ func Symbolize(out io.Writer, pc uint64) error {
|
||||
// corresponding synthetic PCs.
|
||||
func WriteAllBlocks(out io.Writer) error {
|
||||
for fileNum, file := range globalData.files {
|
||||
for blockNum, block := range coverdata.Cover.Blocks[file] {
|
||||
for blockNum, block := range coverdata.Blocks[file] {
|
||||
if err := writeBlockWithPC(out, calculateSyntheticPC(fileNum, blockNum), file, block); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -300,7 +300,7 @@ func fileFromIndex(i int) (string, error) {
|
||||
|
||||
// blockFromIndex returns the i-th block in the given file.
|
||||
func blockFromIndex(file string, i int) (testing.CoverBlock, error) {
|
||||
blocks, ok := coverdata.Cover.Blocks[file]
|
||||
blocks, ok := coverdata.Blocks[file]
|
||||
if !ok {
|
||||
return testing.CoverBlock{}, fmt.Errorf("instrumented file %s does not exist", file)
|
||||
}
|
||||
|
||||
@@ -74,7 +74,9 @@ func TestConnectionAbort(t *testing.T) {
|
||||
testObj := primitive.Uint32(rand.Uint32())
|
||||
for i := 0; i < int(numRequests); i++ {
|
||||
req := conn.NewRequest(creds, uint32(i), uint64(i), 0, &testObj)
|
||||
conn.fd.mu.Lock()
|
||||
fut, err := conn.callFutureLocked(task, req)
|
||||
conn.fd.mu.Unlock()
|
||||
if err != nil {
|
||||
t.Fatalf("callFutureLocked failed: %v", err)
|
||||
}
|
||||
|
||||
@@ -303,12 +303,12 @@ func (fs *filesystem) MountOptions() string {
|
||||
return fs.opts.mopts
|
||||
}
|
||||
|
||||
// Fh data returned by newEntry
|
||||
// NewFhData is returned by newEntry.
|
||||
type NewFhData struct {
|
||||
// file handler
|
||||
// fh is the file handler.
|
||||
fh uint64
|
||||
|
||||
// Flags of the file.
|
||||
// flags is the flags of the file.
|
||||
flags uint32
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
load("//tools:defs.bzl", "bzl_library", "go_proto_library")
|
||||
load("//tools:defs.bzl", "bzl_library")
|
||||
|
||||
package(
|
||||
default_visibility = ["//:sandbox"],
|
||||
@@ -53,9 +53,3 @@ genrule(
|
||||
],
|
||||
visibility = ["//:sandbox"],
|
||||
)
|
||||
|
||||
go_proto_library(
|
||||
name = "worker_protocol_go_proto",
|
||||
importpath = "gvisor.dev/bazel/worker_protocol_go_proto",
|
||||
proto = "@bazel_tools//src/main/protobuf:worker_protocol_proto",
|
||||
)
|
||||
|
||||
@@ -11,8 +11,6 @@ go_embed_data = _go_embed_data
|
||||
|
||||
go_path = _go_path
|
||||
|
||||
bazel_worker_proto = "//tools/bazeldefs:worker_protocol_go_proto"
|
||||
|
||||
def _go_proto_or_grpc_library(go_library_func, name, **kwargs):
|
||||
if "importpath" in kwargs:
|
||||
# If importpath is explicit, pass straight through.
|
||||
|
||||
@@ -8,6 +8,7 @@ go_library(
|
||||
nogo = False,
|
||||
visibility = ["//tools/nogo:__subpackages__"],
|
||||
deps = [
|
||||
"//pkg/log",
|
||||
"//tools/nogo/flags",
|
||||
"@org_golang_x_tools//go/analysis:go_default_library",
|
||||
"@org_golang_x_tools//go/analysis/passes/buildssa:go_default_library",
|
||||
|
||||
@@ -67,15 +67,16 @@ import (
|
||||
"go/types"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/analysis/passes/buildssa"
|
||||
"golang.org/x/tools/go/ssa"
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
"gvisor.dev/gvisor/tools/nogo/flags"
|
||||
)
|
||||
|
||||
@@ -165,21 +166,6 @@ var escapingBuiltins = []string{
|
||||
"mallocgc",
|
||||
}
|
||||
|
||||
// packageEscapeFacts is the set of all functions in a package, and whether or
|
||||
// not they recursively pass escape analysis.
|
||||
//
|
||||
// All the type names for receivers are encoded in the full key. The key
|
||||
// represents the fully qualified package and type name used at link time.
|
||||
//
|
||||
// Note that each Escapes object is a summary. Local findings may be reported
|
||||
// using more detailed information.
|
||||
type packageEscapeFacts struct {
|
||||
Funcs map[string]Escapes
|
||||
}
|
||||
|
||||
// AFact implements analysis.Fact.AFact.
|
||||
func (*packageEscapeFacts) AFact() {}
|
||||
|
||||
// objdumpAnalyzer accepts the objdump parameter.
|
||||
type objdumpAnalyzer struct {
|
||||
analysis.Analyzer
|
||||
@@ -202,7 +188,7 @@ var Analyzer = &objdumpAnalyzer{
|
||||
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)},
|
||||
FactTypes: []analysis.Fact{(*Escapes)(nil)},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -252,6 +238,9 @@ type Escapes struct {
|
||||
Omitted [reasonCount]int
|
||||
}
|
||||
|
||||
// AFact implements analysis.Fact.AFact.
|
||||
func (*Escapes) AFact() {}
|
||||
|
||||
// add is called by Add and Merge.
|
||||
func (es *Escapes) add(r EscapeReason, detail string, omitted int, callSites ...CallSite) {
|
||||
if es.CallSites[r] != nil {
|
||||
@@ -407,11 +396,16 @@ func loadObjdump(binary io.Reader) (finalResults map[string][]string, finalErr e
|
||||
|
||||
// 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)
|
||||
pipeOut, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to load objdump: %w", err)
|
||||
}
|
||||
defer pipeOut.Close()
|
||||
pipeErr, err := cmd.StderrPipe()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to load objdump: %w", err)
|
||||
}
|
||||
defer pipeErr.Close()
|
||||
if startErr := cmd.Start(); startErr != nil {
|
||||
return nil, fmt.Errorf("unable to start objdump: %w", startErr)
|
||||
}
|
||||
@@ -421,9 +415,20 @@ func loadObjdump(binary io.Reader) (finalResults map[string][]string, finalErr e
|
||||
// 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 {
|
||||
var (
|
||||
wg sync.WaitGroup
|
||||
buf bytes.Buffer
|
||||
)
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
io.Copy(&buf, pipeErr)
|
||||
}()
|
||||
waitErr := cmd.Wait()
|
||||
wg.Wait()
|
||||
if finalErr == nil && waitErr != nil {
|
||||
// Override the function's return value in this case.
|
||||
finalErr = fmt.Errorf("error running objdump: %v", waitErr)
|
||||
finalErr = fmt.Errorf("error running objdump %s: %v (%s)", input.Name(), waitErr, buf.Bytes())
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -636,7 +641,7 @@ func run(pass *analysis.Pass, binary io.Reader) (interface{}, error) {
|
||||
// Note that if this analysis fails, then we don't actually
|
||||
// fail the analyzer itself. We simply report every possible
|
||||
// escape. In most cases this will work just fine.
|
||||
log.Printf("WARNING: unable to load objdump: %v", callsErr)
|
||||
log.Warningf("unable to load objdump: %v", callsErr)
|
||||
}
|
||||
allEscapes := make(map[string][]Escapes)
|
||||
mergedEscapes := make(map[string]Escapes)
|
||||
@@ -707,40 +712,42 @@ func run(pass *analysis.Pass, binary io.Reader) (interface{}, error) {
|
||||
}
|
||||
switch x := x.Call.Value.(type) {
|
||||
case *ssa.Function:
|
||||
if x.Pkg == nil {
|
||||
// Can't resolve the package.
|
||||
es.Add(unknownPackage, "no package", cs)
|
||||
return
|
||||
}
|
||||
|
||||
// Is this a local function? If yes, call the
|
||||
// function to load the local function. The
|
||||
// local escapes are the escapes found in the
|
||||
// local function.
|
||||
if x.Pkg.Pkg == pass.Pkg {
|
||||
if x.Pkg != nil && x.Pkg.Pkg == pass.Pkg {
|
||||
es.MergeWithCall(loadFunc(x), cs)
|
||||
return
|
||||
}
|
||||
|
||||
// If this package is the atomic package, the implementation
|
||||
// may be replaced by instrinsics that don't have analysis.
|
||||
if x.Pkg.Pkg.Path() == "sync/atomic" {
|
||||
if x.Pkg != nil && x.Pkg.Pkg.Path() == "sync/atomic" {
|
||||
return
|
||||
}
|
||||
|
||||
// Recursively collect information.
|
||||
var imp packageEscapeFacts
|
||||
if !pass.ImportPackageFact(x.Pkg.Pkg, &imp) {
|
||||
var funcEscapes Escapes
|
||||
if !pass.ImportObjectFact(x.Object(), &funcEscapes) {
|
||||
// If this is the unix package, and the
|
||||
// function is RawSyscall, we can also
|
||||
// ignore this case.
|
||||
if x.Pkg != nil && x.Pkg.Pkg.Name() == "unix" && (x.Name() == "RawSyscall" || x.Name() == "RawSyscall6") {
|
||||
return
|
||||
}
|
||||
|
||||
// Unable to import the dependency; we must
|
||||
// declare these as escaping.
|
||||
es.Add(unknownPackage, "no analysis", cs)
|
||||
message := fmt.Sprintf("no analysis for %q", x.Object().String())
|
||||
es.Add(unknownPackage, message, cs)
|
||||
return
|
||||
}
|
||||
|
||||
// The escapes of this instruction are the
|
||||
// escapes of the called function directly.
|
||||
// Note that this may record many escapes.
|
||||
es.MergeWithCall(imp.Funcs[x.RelString(x.Pkg.Pkg)], cs)
|
||||
es.MergeWithCall(funcEscapes, cs)
|
||||
return
|
||||
case *ssa.Builtin:
|
||||
// Ignore elided escapes.
|
||||
@@ -846,7 +853,10 @@ func run(pass *analysis.Pass, binary io.Reader) (interface{}, error) {
|
||||
|
||||
// Complete all local functions.
|
||||
for _, fn := range state.SrcFuncs {
|
||||
loadFunc(fn)
|
||||
funcEscapes := loadFunc(fn)
|
||||
if obj := fn.Object(); obj != nil {
|
||||
pass.ExportObjectFact(obj, &funcEscapes)
|
||||
}
|
||||
}
|
||||
|
||||
// Scan all functions for violations.
|
||||
|
||||
@@ -164,8 +164,8 @@ func (*lockGuardFacts) AFact() {}
|
||||
|
||||
// globalGuard is a global value.
|
||||
type globalGuard struct {
|
||||
// Object indicates the object from which resolution should occur.
|
||||
Object types.Object
|
||||
// ObjectName indicates the object from which resolution should occur.
|
||||
ObjectName string
|
||||
|
||||
// FieldList is the traversal path from object.
|
||||
FieldList fieldList
|
||||
@@ -179,7 +179,7 @@ type ssaPackager interface {
|
||||
// resolveCommon implements resolution for all cases.
|
||||
func (g *globalGuard) resolveCommon(pc *passContext, ls *lockState) resolvedValue {
|
||||
state := pc.pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA)
|
||||
v := state.Pkg.Members[g.Object.Name()].(ssa.Value)
|
||||
v := state.Pkg.Members[g.ObjectName].(ssa.Value)
|
||||
return makeResolvedValue(v, g.FieldList)
|
||||
}
|
||||
|
||||
@@ -627,8 +627,8 @@ func (pc *passContext) findGlobalGuard(pos token.Pos, guardName string) (*global
|
||||
return nil, false
|
||||
}
|
||||
return &globalGuard{
|
||||
Object: globalObj,
|
||||
FieldList: fl,
|
||||
ObjectName: parts[0],
|
||||
FieldList: fl,
|
||||
}, true
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -10,7 +10,7 @@ load("//tools/go_marshal:defs.bzl", "go_marshal", "marshal_deps", "marshal_test_
|
||||
load("//tools/nogo:defs.bzl", "nogo_test")
|
||||
load("//tools/bazeldefs:defs.bzl", _amd64_config = "amd64_config", _arch_config = "arch_config", _arm64_config = "arm64_config", _build_test = "build_test", _bzl_library = "bzl_library", _coreutil = "coreutil", _default_net_util = "default_net_util", _more_shards = "more_shards", _most_shards = "most_shards", _proto_library = "proto_library", _select_arch = "select_arch", _select_system = "select_system", _short_path = "short_path", _transition_allowlist = "transition_allowlist", _version = "version")
|
||||
load("//tools/bazeldefs:cc.bzl", _cc_binary = "cc_binary", _cc_flags_supplier = "cc_flags_supplier", _cc_grpc_library = "cc_grpc_library", _cc_library = "cc_library", _cc_proto_library = "cc_proto_library", _cc_test = "cc_test", _cc_toolchain = "cc_toolchain", _gbenchmark = "gbenchmark", _gbenchmark_internal = "gbenchmark_internal", _grpcpp = "grpcpp", _gtest = "gtest", _vdso_linker_option = "vdso_linker_option")
|
||||
load("//tools/bazeldefs:go.bzl", _bazel_worker_proto = "bazel_worker_proto", _gazelle = "gazelle", _go_binary = "go_binary", _go_embed_data = "go_embed_data", _go_grpc_and_proto_libraries = "go_grpc_and_proto_libraries", _go_library = "go_library", _go_path = "go_path", _go_proto_library = "go_proto_library", _go_rule = "go_rule", _go_test = "go_test", _select_goarch = "select_goarch", _select_goos = "select_goos")
|
||||
load("//tools/bazeldefs:go.bzl", _gazelle = "gazelle", _go_binary = "go_binary", _go_embed_data = "go_embed_data", _go_grpc_and_proto_libraries = "go_grpc_and_proto_libraries", _go_library = "go_library", _go_path = "go_path", _go_proto_library = "go_proto_library", _go_rule = "go_rule", _go_test = "go_test", _select_goarch = "select_goarch", _select_goos = "select_goos")
|
||||
load("//tools/bazeldefs:pkg.bzl", _pkg_deb = "pkg_deb", _pkg_tar = "pkg_tar")
|
||||
load("//tools/bazeldefs:platforms.bzl", _default_platform = "default_platform", _platforms = "platforms")
|
||||
load("//tools/bazeldefs:tags.bzl", "go_suffixes")
|
||||
@@ -47,7 +47,6 @@ select_goos = _select_goos
|
||||
select_goarch = _select_goarch
|
||||
go_embed_data = _go_embed_data
|
||||
go_proto_library = _go_proto_library
|
||||
bazel_worker_proto = _bazel_worker_proto
|
||||
|
||||
# Packaging rules.
|
||||
pkg_deb = _pkg_deb
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
diff '--color=auto' -r -u2 a/go/src/go/types/scope.go b/go/src/go/types/scope.go
|
||||
--- a/go/src/go/types/scope.go 2022-01-06 19:14:25.000000000 +0000
|
||||
+++ b/go/src/go/types/scope.go 2022-02-03 18:50:35.526563967 +0000
|
||||
@@ -24,4 +24,5 @@
|
||||
children []*Scope
|
||||
elems map[string]Object // lazily allocated
|
||||
+ sorted []string // lazily allocated
|
||||
pos, end token.Pos // scope extent; may be invalid
|
||||
comment string // for debugging only
|
||||
@@ -32,5 +33,5 @@
|
||||
// scope, if any. The comment is for debugging only.
|
||||
func NewScope(parent *Scope, pos, end token.Pos, comment string) *Scope {
|
||||
- s := &Scope{parent, nil, nil, pos, end, comment, false}
|
||||
+ s := &Scope{parent, nil, nil, nil, pos, end, comment, false}
|
||||
// don't add children to Universe scope!
|
||||
if parent != nil && parent != Universe {
|
||||
@@ -48,12 +49,14 @@
|
||||
// Names returns the scope's element names in sorted order.
|
||||
func (s *Scope) Names() []string {
|
||||
- names := make([]string, len(s.elems))
|
||||
- i := 0
|
||||
- for name := range s.elems {
|
||||
- names[i] = name
|
||||
- i++
|
||||
+ if len(s.sorted) != len(s.elems) {
|
||||
+ s.sorted = make([]string, len(s.elems))
|
||||
+ i := 0
|
||||
+ for name := range s.elems {
|
||||
+ s.sorted[i] = name
|
||||
+ i++
|
||||
+ }
|
||||
+ sort.Strings(s.sorted)
|
||||
}
|
||||
- sort.Strings(names)
|
||||
- return names
|
||||
+ return s.sorted
|
||||
}
|
||||
|
||||
Only in b/go/src/go/types: scope.go.orig
|
||||
@@ -20,7 +20,6 @@ go_library(
|
||||
"//tools/checkunsafe",
|
||||
"//tools/nogo/facts",
|
||||
"//tools/nogo/flags",
|
||||
"//tools/worker",
|
||||
"@co_honnef_go_tools//staticcheck:go_default_library",
|
||||
"@co_honnef_go_tools//stylecheck:go_default_library",
|
||||
"@org_golang_x_tools//go/analysis:go_default_library",
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package check
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"io"
|
||||
@@ -37,7 +38,11 @@ var findStdPkg = func(path string) (io.ReadCloser, error) {
|
||||
}
|
||||
|
||||
// Attempt to resolve the library, and propagate this error.
|
||||
return os.Open(fmt.Sprintf("%s/pkg/%s_%s/%s.a", root, flags.GOOS, flags.GOARCH, path))
|
||||
f, err := os.Open(fmt.Sprintf("%s/pkg/%s_%s/%s.a", root, flags.GOOS, flags.GOARCH, path))
|
||||
if err != nil && errors.Is(err, os.ErrNotExist) {
|
||||
return nil, ErrSkip
|
||||
}
|
||||
return f, err
|
||||
}
|
||||
|
||||
// releaseTags returns the default release tags.
|
||||
|
||||
+175
-150
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user