summaryrefslogtreecommitdiffhomepage
path: root/tools/nogo
diff options
context:
space:
mode:
Diffstat (limited to 'tools/nogo')
-rw-r--r--tools/nogo/BUILD11
-rw-r--r--tools/nogo/config.go1
-rw-r--r--tools/nogo/defs.bzl96
-rwxr-xr-xtools/nogo/gentest.sh1
-rw-r--r--tools/nogo/io_bazel_rules_go-visibility.patch25
-rw-r--r--tools/nogo/nogo.go24
6 files changed, 104 insertions, 54 deletions
diff --git a/tools/nogo/BUILD b/tools/nogo/BUILD
index dd4b46f58..3c6be3339 100644
--- a/tools/nogo/BUILD
+++ b/tools/nogo/BUILD
@@ -1,8 +1,15 @@
-load("//tools:defs.bzl", "bzl_library", "go_library")
-load("//tools/nogo:defs.bzl", "nogo_objdump_tool", "nogo_stdlib")
+load("//tools:defs.bzl", "bzl_library", "go_library", "select_goarch", "select_goos")
+load("//tools/nogo:defs.bzl", "nogo_objdump_tool", "nogo_stdlib", "nogo_target")
package(licenses = ["notice"])
+nogo_target(
+ name = "target",
+ goarch = select_goarch(),
+ goos = select_goos(),
+ visibility = ["//visibility:public"],
+)
+
nogo_objdump_tool(
name = "objdump_tool",
visibility = ["//visibility:public"],
diff --git a/tools/nogo/config.go b/tools/nogo/config.go
index 8079618ab..0853f03cf 100644
--- a/tools/nogo/config.go
+++ b/tools/nogo/config.go
@@ -473,6 +473,7 @@ func init() {
"pkg/shim/v2/options/options.go:24",
"pkg/shim/v2/options/options.go:26",
"pkg/shim/v2/runtimeoptions/runtimeoptions.go:16",
+ "pkg/shim/v2/runtimeoptions/runtimeoptions_cri.go", // Generated: exempt all.
"pkg/shim/v2/runtimeoptions/runtimeoptions_test.go:22",
"pkg/shim/v2/service.go:15",
"pkg/shim/v2/service_linux.go:18",
diff --git a/tools/nogo/defs.bzl b/tools/nogo/defs.bzl
index c6fcfd402..543598b52 100644
--- a/tools/nogo/defs.bzl
+++ b/tools/nogo/defs.bzl
@@ -1,10 +1,34 @@
"""Nogo rules."""
-load("//tools/bazeldefs:defs.bzl", "go_context", "go_importpath", "go_rule", "go_test_library")
+load("//tools/bazeldefs:go.bzl", "go_context", "go_importpath", "go_rule", "go_test_library")
-def _nogo_objdump_tool_impl(ctx):
- go_ctx = go_context(ctx)
+NogoTargetInfo = provider(
+ "information about the Go target",
+ fields = {
+ "goarch": "the build architecture (GOARCH)",
+ "goos": "the build OS target (GOOS)",
+ },
+)
+
+def _nogo_target_impl(ctx):
+ return [NogoTargetInfo(
+ goarch = ctx.attr.goarch,
+ goos = ctx.attr.goos,
+ )]
+nogo_target = go_rule(
+ rule,
+ implementation = _nogo_target_impl,
+ attrs = {
+ # goarch is the build architecture. This will normally be provided by a
+ # select statement, but this information is propagated to other rules.
+ "goarch": attr.string(mandatory = True),
+ # goos is similarly the build operating system target.
+ "goos": attr.string(mandatory = True),
+ },
+)
+
+def _nogo_objdump_tool_impl(ctx):
# Construct the magic dump command.
#
# Note that in some cases, the input is being fed into the tool via stdin.
@@ -12,6 +36,8 @@ def _nogo_objdump_tool_impl(ctx):
# we need the tool to handle this case by creating a temporary file.
#
# [1] https://github.com/golang/go/issues/41051
+ nogo_target_info = ctx.attr._nogo_target[NogoTargetInfo]
+ go_ctx = go_context(ctx, goos = nogo_target_info.goos, goarch = nogo_target_info.goarch)
env_prefix = " ".join(["%s=%s" % (key, value) for (key, value) in go_ctx.env.items()])
dumper = ctx.actions.declare_file(ctx.label.name)
ctx.actions.write(dumper, "\n".join([
@@ -42,6 +68,12 @@ def _nogo_objdump_tool_impl(ctx):
nogo_objdump_tool = go_rule(
rule,
implementation = _nogo_objdump_tool_impl,
+ attrs = {
+ "_nogo_target": attr.label(
+ default = "//tools/nogo:target",
+ cfg = "target",
+ ),
+ },
)
# NogoStdlibInfo is the set of standard library facts.
@@ -54,9 +86,9 @@ NogoStdlibInfo = provider(
)
def _nogo_stdlib_impl(ctx):
- go_ctx = go_context(ctx)
-
# Build the standard library facts.
+ nogo_target_info = ctx.attr._nogo_target[NogoTargetInfo]
+ go_ctx = go_context(ctx, goos = nogo_target_info.goos, goarch = nogo_target_info.goarch)
facts = ctx.actions.declare_file(ctx.label.name + ".facts")
findings = ctx.actions.declare_file(ctx.label.name + ".findings")
config = struct(
@@ -70,12 +102,12 @@ def _nogo_stdlib_impl(ctx):
ctx.actions.run(
inputs = [config_file] + go_ctx.stdlib_srcs,
outputs = [facts, findings],
- tools = depset(go_ctx.runfiles.to_list() + ctx.files._objdump_tool),
- executable = ctx.files._nogo[0],
+ tools = depset(go_ctx.runfiles.to_list() + ctx.files._nogo_objdump_tool),
+ executable = ctx.files._nogo_check[0],
mnemonic = "GoStandardLibraryAnalysis",
progress_message = "Analyzing Go Standard Library",
arguments = go_ctx.nogo_args + [
- "-objdump_tool=%s" % ctx.files._objdump_tool[0].path,
+ "-objdump_tool=%s" % ctx.files._nogo_objdump_tool[0].path,
"-stdlib=%s" % config_file.path,
"-findings=%s" % findings.path,
"-facts=%s" % facts.path,
@@ -92,11 +124,17 @@ nogo_stdlib = go_rule(
rule,
implementation = _nogo_stdlib_impl,
attrs = {
- "_nogo": attr.label(
+ "_nogo_check": attr.label(
default = "//tools/nogo/check:check",
+ cfg = "host",
),
- "_objdump_tool": attr.label(
+ "_nogo_objdump_tool": attr.label(
default = "//tools/nogo:objdump_tool",
+ cfg = "host",
+ ),
+ "_nogo_target": attr.label(
+ default = "//tools/nogo:target",
+ cfg = "target",
),
},
)
@@ -113,20 +151,18 @@ NogoInfo = provider(
"findings": "package findings (if relevant)",
"importpath": "package import path",
"binaries": "package binary files",
- "srcs": "original source files (for go_test support)",
- "deps": "original deps (for go_test support)",
+ "srcs": "srcs (for go_test support)",
+ "deps": "deps (for go_test support)",
},
)
def _nogo_aspect_impl(target, ctx):
- go_ctx = go_context(ctx)
-
# If this is a nogo rule itself (and not the shadow of a go_library or
# go_binary rule created by such a rule), then we simply return nothing.
# All work is done in the shadow properties for go rules. For a proto
# library, we simply skip the analysis portion but still need to return a
# valid NogoInfo to reference the generated binary.
- if ctx.rule.kind in ("go_library", "go_binary", "go_test", "go_tool_library"):
+ if ctx.rule.kind in ("go_library", "go_tool_library", "go_binary", "go_test"):
srcs = ctx.rule.files.srcs
deps = ctx.rule.attr.deps
elif ctx.rule.kind in ("go_proto_library", "go_wrap_cc"):
@@ -200,10 +236,13 @@ def _nogo_aspect_impl(target, ctx):
inputs += info.binaries
# Add the standard library facts.
- stdlib_facts = ctx.attr._nogo_stdlib[NogoStdlibInfo].facts
+ stdlib_info = ctx.attr._nogo_stdlib[NogoStdlibInfo]
+ stdlib_facts = stdlib_info.facts
inputs.append(stdlib_facts)
# The nogo tool operates on a configuration serialized in JSON format.
+ nogo_target_info = ctx.attr._nogo_target[NogoTargetInfo]
+ go_ctx = go_context(ctx, goos = nogo_target_info.goos, goarch = nogo_target_info.goarch)
facts = ctx.actions.declare_file(target.label.name + ".facts")
findings = ctx.actions.declare_file(target.label.name + ".findings")
escapes = ctx.actions.declare_file(target.label.name + ".escapes")
@@ -224,13 +263,13 @@ def _nogo_aspect_impl(target, ctx):
ctx.actions.run(
inputs = inputs,
outputs = [facts, findings, escapes],
- tools = depset(go_ctx.runfiles.to_list() + ctx.files._objdump_tool),
- executable = ctx.files._nogo[0],
+ tools = depset(go_ctx.runfiles.to_list() + ctx.files._nogo_objdump_tool),
+ executable = ctx.files._nogo_check[0],
mnemonic = "GoStaticAnalysis",
progress_message = "Analyzing %s" % target.label,
arguments = go_ctx.nogo_args + [
"-binary=%s" % target_objfile.path,
- "-objdump_tool=%s" % ctx.files._objdump_tool[0].path,
+ "-objdump_tool=%s" % ctx.files._nogo_objdump_tool[0].path,
"-package=%s" % config_file.path,
"-findings=%s" % findings.path,
"-facts=%s" % facts.path,
@@ -266,9 +305,22 @@ nogo_aspect = go_rule(
"embed",
],
attrs = {
- "_nogo": attr.label(default = "//tools/nogo/check:check"),
- "_nogo_stdlib": attr.label(default = "//tools/nogo:stdlib"),
- "_objdump_tool": attr.label(default = "//tools/nogo:objdump_tool"),
+ "_nogo_check": attr.label(
+ default = "//tools/nogo/check:check",
+ cfg = "host",
+ ),
+ "_nogo_stdlib": attr.label(
+ default = "//tools/nogo:stdlib",
+ cfg = "host",
+ ),
+ "_nogo_objdump_tool": attr.label(
+ default = "//tools/nogo:objdump_tool",
+ cfg = "host",
+ ),
+ "_nogo_target": attr.label(
+ default = "//tools/nogo:target",
+ cfg = "target",
+ ),
},
)
diff --git a/tools/nogo/gentest.sh b/tools/nogo/gentest.sh
index 033da11ad..0a762f9f6 100755
--- a/tools/nogo/gentest.sh
+++ b/tools/nogo/gentest.sh
@@ -34,6 +34,7 @@ for filename in "$@"; do
continue
fi
while read -r line; do
+ line="${line@Q}"
violations=$((${violations}+1));
echo "echo -e '\\033[0;31m${line}\\033[0;31m\\033[0m'" >> "${output}"
done < "${filename}"
diff --git a/tools/nogo/io_bazel_rules_go-visibility.patch b/tools/nogo/io_bazel_rules_go-visibility.patch
deleted file mode 100644
index 6b64b2e85..000000000
--- a/tools/nogo/io_bazel_rules_go-visibility.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-diff --git a/third_party/org_golang_x_tools-extras.patch b/third_party/org_golang_x_tools-extras.patch
-index 133fbccc..5f0d9a47 100644
---- a/third_party/org_golang_x_tools-extras.patch
-+++ b/third_party/org_golang_x_tools-extras.patch
-@@ -32,7 +32,7 @@ diff -urN c/go/analysis/internal/facts/BUILD.bazel d/go/analysis/internal/facts/
-
- go_library(
- name = "go_default_library",
--@@ -14,6 +14,23 @@
-+@@ -14,6 +14,20 @@
- ],
- )
-
-@@ -43,10 +43,7 @@ diff -urN c/go/analysis/internal/facts/BUILD.bazel d/go/analysis/internal/facts/
- + "imports.go",
- + ],
- + importpath = "golang.org/x/tools/go/analysis/internal/facts",
--+ visibility = [
--+ "//go/analysis:__subpackages__",
--+ "@io_bazel_rules_go//go/tools/builders:__pkg__",
--+ ],
-++ visibility = ["//visibility:public"],
- + deps = [
- + "//go/analysis:go_tool_library",
- + "//go/types/objectpath:go_tool_library",
diff --git a/tools/nogo/nogo.go b/tools/nogo/nogo.go
index 120fdcff5..e19e3c237 100644
--- a/tools/nogo/nogo.go
+++ b/tools/nogo/nogo.go
@@ -264,12 +264,17 @@ func checkStdlib(config *stdlibConfig, ac map[*analysis.Analyzer]matcher) ([]str
// Closure to check a single package.
allFindings := make([]string, 0)
stdlibFacts := make(map[string][]byte)
+ stdlibErrs := make(map[string]error)
var checkOne func(pkg string) error // Recursive.
checkOne = func(pkg string) error {
// Is this already done?
if _, ok := stdlibFacts[pkg]; ok {
return nil
}
+ // Did this fail previously?
+ if _, ok := stdlibErrs[pkg]; ok {
+ return nil
+ }
// Lookup the configuration.
config, ok := packages[pkg]
@@ -283,6 +288,7 @@ func checkStdlib(config *stdlibConfig, ac map[*analysis.Analyzer]matcher) ([]str
// If there's no binary for this package, it is likely
// not built with the distribution. That's fine, we can
// just skip analysis.
+ stdlibErrs[pkg] = err
return nil
}
@@ -299,6 +305,7 @@ func checkStdlib(config *stdlibConfig, ac map[*analysis.Analyzer]matcher) ([]str
if err != nil {
// If we can't analyze a package from the standard library,
// then we skip it. It will simply not have any findings.
+ stdlibErrs[pkg] = err
return nil
}
stdlibFacts[pkg] = factData
@@ -312,7 +319,9 @@ func checkStdlib(config *stdlibConfig, ac map[*analysis.Analyzer]matcher) ([]str
// to evaluate in the order provided here. We do ensure however, that
// all packages are evaluated.
for pkg := range packages {
- checkOne(pkg)
+ if err := checkOne(pkg); err != nil {
+ return nil, nil, err
+ }
}
// Sanity check.
@@ -326,6 +335,11 @@ func checkStdlib(config *stdlibConfig, ac map[*analysis.Analyzer]matcher) ([]str
return nil, nil, fmt.Errorf("error saving stdlib facts: %w", err)
}
+ // Write out all errors.
+ for pkg, err := range stdlibErrs {
+ log.Printf("WARNING: error while processing %v: %v", pkg, err)
+ }
+
// Return all findings.
return allFindings, factData, nil
}
@@ -522,15 +536,15 @@ func Main() {
findings, factData, err = checkPackage(c, analyzerConfig, nil)
// Do we need to do escape analysis?
if *escapesOutput != "" {
- escapes, _, err := checkPackage(c, escapesConfig, nil)
- if err != nil {
- log.Fatalf("error performing escape analysis: %v", err)
- }
f, err := os.OpenFile(*escapesOutput, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
log.Fatalf("unable to open output %q: %v", *escapesOutput, err)
}
defer f.Close()
+ escapes, _, err := checkPackage(c, escapesConfig, nil)
+ if err != nil {
+ log.Fatalf("error performing escape analysis: %v", err)
+ }
for _, escape := range escapes {
fmt.Fprintf(f, "%s\n", escape)
}