mirror of
https://github.com/anchore/syft.git
synced 2026-07-05 02:28:25 +02:00
feat: enum feature for SYFT_GOLANG_CAPTURE_SYMBOLS
Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
This commit is contained in:
parent
27f33d0e99
commit
a1831ce3b4
@ -1,6 +1,7 @@
|
|||||||
package options
|
package options
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/anchore/clio"
|
"github.com/anchore/clio"
|
||||||
@ -17,11 +18,12 @@ type golangConfig struct {
|
|||||||
NoProxy string `json:"no-proxy" yaml:"no-proxy" mapstructure:"no-proxy"`
|
NoProxy string `json:"no-proxy" yaml:"no-proxy" mapstructure:"no-proxy"`
|
||||||
MainModuleVersion golangMainModuleVersionConfig `json:"main-module-version" yaml:"main-module-version" mapstructure:"main-module-version"`
|
MainModuleVersion golangMainModuleVersionConfig `json:"main-module-version" yaml:"main-module-version" mapstructure:"main-module-version"`
|
||||||
UsePackagesLib *bool `json:"use-packages-lib" yaml:"use-packages-lib" mapstructure:"use-packages-lib"`
|
UsePackagesLib *bool `json:"use-packages-lib" yaml:"use-packages-lib" mapstructure:"use-packages-lib"`
|
||||||
CaptureSymbols bool `json:"capture-symbols" yaml:"capture-symbols" mapstructure:"capture-symbols"`
|
CaptureSymbols golang.SymbolScope `json:"capture-symbols" yaml:"capture-symbols" mapstructure:"capture-symbols"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ interface {
|
var _ interface {
|
||||||
clio.FieldDescriber
|
clio.FieldDescriber
|
||||||
|
clio.PostLoader
|
||||||
} = (*golangConfig)(nil)
|
} = (*golangConfig)(nil)
|
||||||
|
|
||||||
func (o *golangConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
func (o *golangConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||||
@ -40,13 +42,23 @@ if unset this defaults to $GONOPROXY`)
|
|||||||
always show (devel) as the version. Use these options to control heuristics to guess
|
always show (devel) as the version. Use these options to control heuristics to guess
|
||||||
a more accurate version from the binary.`)
|
a more accurate version from the binary.`)
|
||||||
descriptions.Add(&o.UsePackagesLib, `use the golang.org/x/tools/go/packages library, which executes golang tooling found on the path in addition to potential network access to get the most accurate results`)
|
descriptions.Add(&o.UsePackagesLib, `use the golang.org/x/tools/go/packages library, which executes golang tooling found on the path in addition to potential network access to get the most accurate results`)
|
||||||
descriptions.Add(&o.CaptureSymbols, `capture function symbols from the binary symbol table (pclntab) and attribute them to the owning module`)
|
descriptions.Add(&o.CaptureSymbols, `capture function symbols from the binary symbol table (pclntab). valid values are:
|
||||||
|
"none" (disabled), "stdlib" (only the synthetic stdlib package), and "all" (all module packages plus stdlib)`)
|
||||||
descriptions.Add(&o.MainModuleVersion.FromLDFlags, `look for LD flags that appear to be setting a version (e.g. -X main.version=1.0.0)`)
|
descriptions.Add(&o.MainModuleVersion.FromLDFlags, `look for LD flags that appear to be setting a version (e.g. -X main.version=1.0.0)`)
|
||||||
descriptions.Add(&o.MainModuleVersion.FromBuildSettings, `use the build settings (e.g. vcs.version & vcs.time) to craft a v0 pseudo version
|
descriptions.Add(&o.MainModuleVersion.FromBuildSettings, `use the build settings (e.g. vcs.version & vcs.time) to craft a v0 pseudo version
|
||||||
(e.g. v0.0.0-20220308212642-53e6d0aaf6fb) when a more accurate version cannot be found otherwise`)
|
(e.g. v0.0.0-20220308212642-53e6d0aaf6fb) when a more accurate version cannot be found otherwise`)
|
||||||
descriptions.Add(&o.MainModuleVersion.FromContents, `search for semver-like strings in the binary contents`)
|
descriptions.Add(&o.MainModuleVersion.FromContents, `search for semver-like strings in the binary contents`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *golangConfig) PostLoad() error {
|
||||||
|
parsed := o.CaptureSymbols.Parse()
|
||||||
|
if parsed == "" {
|
||||||
|
return fmt.Errorf("invalid value %q for golang.capture-symbols; valid values are: none, stdlib, all", o.CaptureSymbols)
|
||||||
|
}
|
||||||
|
o.CaptureSymbols = parsed
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type golangMainModuleVersionConfig struct {
|
type golangMainModuleVersionConfig struct {
|
||||||
FromLDFlags bool `json:"from-ld-flags" yaml:"from-ld-flags" mapstructure:"from-ld-flags"`
|
FromLDFlags bool `json:"from-ld-flags" yaml:"from-ld-flags" mapstructure:"from-ld-flags"`
|
||||||
FromContents bool `json:"from-contents" yaml:"from-contents" mapstructure:"from-contents"`
|
FromContents bool `json:"from-contents" yaml:"from-contents" mapstructure:"from-contents"`
|
||||||
|
|||||||
57
cmd/syft/internal/options/golang_test.go
Normal file
57
cmd/syft/internal/options/golang_test.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package options
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/syft/pkg/cataloger/golang"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_golangConfig_PostLoad(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
cfg golangConfig
|
||||||
|
expected golang.SymbolScope
|
||||||
|
wantErr assert.ErrorAssertionFunc
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "normalize all",
|
||||||
|
cfg: golangConfig{CaptureSymbols: "all"},
|
||||||
|
expected: golang.SymbolScopeAll,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "normalize stdlib",
|
||||||
|
cfg: golangConfig{CaptureSymbols: "stdlib"},
|
||||||
|
expected: golang.SymbolScopeStdlib,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty defaults to none",
|
||||||
|
cfg: golangConfig{CaptureSymbols: ""},
|
||||||
|
expected: golang.SymbolScopeNone,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "error on invalid value",
|
||||||
|
cfg: golangConfig{CaptureSymbols: "bogus"},
|
||||||
|
wantErr: assert.Error,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "boolean spellings are not valid",
|
||||||
|
cfg: golangConfig{CaptureSymbols: "true"},
|
||||||
|
wantErr: assert.Error,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if tt.wantErr == nil {
|
||||||
|
tt.wantErr = assert.NoError
|
||||||
|
}
|
||||||
|
err := tt.cfg.PostLoad()
|
||||||
|
tt.wantErr(t, err)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
assert.Equal(t, tt.expected, tt.cfg.CaptureSymbols)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -12,6 +12,8 @@ application: # AUTO-GENERATED - application-level config keys
|
|||||||
description: treat DLL claims or on-disk evidence for child packages as DLL claims or on-disk evidence for any parent package
|
description: treat DLL claims or on-disk evidence for child packages as DLL claims or on-disk evidence for any parent package
|
||||||
- key: dotnet.relax-dll-claims-when-bundling-detected
|
- key: dotnet.relax-dll-claims-when-bundling-detected
|
||||||
description: show all packages from the deps.json if bundling tooling is present as a dependency (e.g. ILRepack)
|
description: show all packages from the deps.json if bundling tooling is present as a dependency (e.g. ILRepack)
|
||||||
|
- key: golang.capture-symbols
|
||||||
|
description: 'capture function symbols from the binary symbol table (pclntab). valid values are: "none" (disabled), "stdlib" (only the synthetic stdlib package), and "all" (all module packages plus stdlib)'
|
||||||
- key: golang.local-mod-cache-dir
|
- key: golang.local-mod-cache-dir
|
||||||
description: specify an explicit go mod cache directory, if unset this defaults to $GOPATH/pkg/mod or $HOME/go/pkg/mod
|
description: specify an explicit go mod cache directory, if unset this defaults to $GOPATH/pkg/mod or $HOME/go/pkg/mod
|
||||||
- key: golang.local-vendor-dir
|
- key: golang.local-vendor-dir
|
||||||
|
|||||||
@ -24,6 +24,9 @@ configs: # AUTO-GENERATED - config structs and their fields
|
|||||||
- key: NoProxy
|
- key: NoProxy
|
||||||
description: NoProxy is a list of glob patterns that match go module names that should not be fetched from the go proxy. When not set, syft will use the GOPRIVATE and GONOPROXY env vars.
|
description: NoProxy is a list of glob patterns that match go module names that should not be fetched from the go proxy. When not set, syft will use the GOPRIVATE and GONOPROXY env vars.
|
||||||
app_key: golang.no-proxy
|
app_key: golang.no-proxy
|
||||||
|
- key: CaptureSymbols
|
||||||
|
description: CaptureSymbols controls extracting function symbols from the binary symbol table (pclntab). Valid values are "none" (disabled), "stdlib" (only the synthetic stdlib package), and "all" (all module packages plus stdlib).
|
||||||
|
app_key: golang.capture-symbols
|
||||||
catalogers:
|
catalogers:
|
||||||
- ecosystem: go # MANUAL
|
- ecosystem: go # MANUAL
|
||||||
name: go-module-binary-cataloger # AUTO-GENERATED
|
name: go-module-binary-cataloger # AUTO-GENERATED
|
||||||
|
|||||||
@ -18,6 +18,34 @@ var (
|
|||||||
directProxiesOnly = []string{directProxyOnly}
|
directProxiesOnly = []string{directProxyOnly}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SymbolScope controls which packages get function symbols (from the binary pclntab) attached to their metadata.
|
||||||
|
type SymbolScope string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// SymbolScopeNone disables symbol capture entirely.
|
||||||
|
SymbolScopeNone SymbolScope = "none"
|
||||||
|
|
||||||
|
// SymbolScopeStdlib captures symbols only for the synthetic "stdlib" package, leaving module packages without symbols.
|
||||||
|
SymbolScopeStdlib SymbolScope = "stdlib"
|
||||||
|
|
||||||
|
// SymbolScopeAll captures symbols for all module packages as well as the synthetic "stdlib" package.
|
||||||
|
SymbolScopeAll SymbolScope = "all"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Parse normalizes a SymbolScope, treating an empty (unset) value as SymbolScopeNone. It returns an empty
|
||||||
|
// SymbolScope to signal an unrecognized value, which callers validate against.
|
||||||
|
func (s SymbolScope) Parse() SymbolScope {
|
||||||
|
switch strings.ToLower(strings.TrimSpace(string(s))) {
|
||||||
|
case string(SymbolScopeAll):
|
||||||
|
return SymbolScopeAll
|
||||||
|
case string(SymbolScopeStdlib):
|
||||||
|
return SymbolScopeStdlib
|
||||||
|
case string(SymbolScopeNone), "":
|
||||||
|
return SymbolScopeNone
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
type CatalogerConfig struct {
|
type CatalogerConfig struct {
|
||||||
// SearchLocalModCacheLicenses enables searching for go package licenses in the local GOPATH mod cache.
|
// SearchLocalModCacheLicenses enables searching for go package licenses in the local GOPATH mod cache.
|
||||||
// app-config: golang.search-local-mod-cache-licenses
|
// app-config: golang.search-local-mod-cache-licenses
|
||||||
@ -49,9 +77,10 @@ type CatalogerConfig struct {
|
|||||||
|
|
||||||
MainModuleVersion MainModuleVersionConfig `yaml:"main-module-version" json:"main-module-version" mapstructure:"main-module-version"`
|
MainModuleVersion MainModuleVersionConfig `yaml:"main-module-version" json:"main-module-version" mapstructure:"main-module-version"`
|
||||||
|
|
||||||
// CaptureSymbols enables extracting function symbols from the binary symbol table (pclntab) and attributing them to the owning module.
|
// CaptureSymbols controls extracting function symbols from the binary symbol table (pclntab). Valid values are
|
||||||
|
// "none" (disabled), "stdlib" (only the synthetic stdlib package), and "all" (all module packages plus stdlib).
|
||||||
// app-config: golang.capture-symbols
|
// app-config: golang.capture-symbols
|
||||||
CaptureSymbols bool `yaml:"capture-symbols" json:"capture-symbols" mapstructure:"capture-symbols"`
|
CaptureSymbols SymbolScope `yaml:"capture-symbols" json:"capture-symbols" mapstructure:"capture-symbols"`
|
||||||
|
|
||||||
// Whether to use the golang.org/x/tools/go/packages, which executes golang tooling found on the path in addition to potential network access
|
// Whether to use the golang.org/x/tools/go/packages, which executes golang tooling found on the path in addition to potential network access
|
||||||
UsePackagesLib bool `json:"use-packages-lib" yaml:"use-packages-lib" mapstructure:"use-packages-lib"`
|
UsePackagesLib bool `json:"use-packages-lib" yaml:"use-packages-lib" mapstructure:"use-packages-lib"`
|
||||||
@ -80,7 +109,7 @@ func DefaultCatalogerConfig() CatalogerConfig {
|
|||||||
UsePackagesLib: true,
|
UsePackagesLib: true,
|
||||||
MainModuleVersion: DefaultMainModuleVersionConfig(),
|
MainModuleVersion: DefaultMainModuleVersionConfig(),
|
||||||
LocalModCacheDir: defaultGoModDir(),
|
LocalModCacheDir: defaultGoModDir(),
|
||||||
CaptureSymbols: false,
|
CaptureSymbols: SymbolScopeNone,
|
||||||
}
|
}
|
||||||
|
|
||||||
// first process the proxy settings
|
// first process the proxy settings
|
||||||
@ -189,7 +218,7 @@ func (g CatalogerConfig) WithMainModuleVersion(input MainModuleVersionConfig) Ca
|
|||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g CatalogerConfig) WithCaptureSymbols(input bool) CatalogerConfig {
|
func (g CatalogerConfig) WithCaptureSymbols(input SymbolScope) CatalogerConfig {
|
||||||
g.CaptureSymbols = input
|
g.CaptureSymbols = input
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,7 +58,7 @@ func Test_Config(t *testing.T) {
|
|||||||
NoProxy: []string{"my.private", "no.proxy"},
|
NoProxy: []string{"my.private", "no.proxy"},
|
||||||
MainModuleVersion: DefaultMainModuleVersionConfig(),
|
MainModuleVersion: DefaultMainModuleVersionConfig(),
|
||||||
UsePackagesLib: true,
|
UsePackagesLib: true,
|
||||||
CaptureSymbols: false,
|
CaptureSymbols: SymbolScopeNone,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -87,7 +87,7 @@ func Test_Config(t *testing.T) {
|
|||||||
NoProxy: []string{"alt.no.proxy"},
|
NoProxy: []string{"alt.no.proxy"},
|
||||||
MainModuleVersion: DefaultMainModuleVersionConfig(),
|
MainModuleVersion: DefaultMainModuleVersionConfig(),
|
||||||
UsePackagesLib: true,
|
UsePackagesLib: true,
|
||||||
CaptureSymbols: false,
|
CaptureSymbols: SymbolScopeNone,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -114,6 +114,29 @@ func Test_Config(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_SymbolScope_Parse(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
input string
|
||||||
|
expected SymbolScope
|
||||||
|
}{
|
||||||
|
{"all", SymbolScopeAll},
|
||||||
|
{"ALL", SymbolScopeAll},
|
||||||
|
{" all ", SymbolScopeAll},
|
||||||
|
{"stdlib", SymbolScopeStdlib},
|
||||||
|
{"Stdlib", SymbolScopeStdlib},
|
||||||
|
{"none", SymbolScopeNone},
|
||||||
|
{"", SymbolScopeNone},
|
||||||
|
{"true", ""},
|
||||||
|
{"false", ""},
|
||||||
|
{"bogus", ""},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.input, func(t *testing.T) {
|
||||||
|
assert.Equal(t, test.expected, SymbolScope(test.input).Parse())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// restoreCache ensures cache settings are restored after test
|
// restoreCache ensures cache settings are restored after test
|
||||||
func restoreCache(t testing.TB) {
|
func restoreCache(t testing.TB) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|||||||
@ -50,7 +50,7 @@ const devel = "(devel)"
|
|||||||
type goBinaryCataloger struct {
|
type goBinaryCataloger struct {
|
||||||
licenseResolver goLicenseResolver
|
licenseResolver goLicenseResolver
|
||||||
mainModuleVersion MainModuleVersionConfig
|
mainModuleVersion MainModuleVersionConfig
|
||||||
captureSymbols bool
|
symbolScope SymbolScope
|
||||||
|
|
||||||
// stdlibSymbols holds the standard-library function symbols discovered per binary (keyed by the
|
// stdlibSymbols holds the standard-library function symbols discovered per binary (keyed by the
|
||||||
// binary's location), populated during parsing and consumed by stdlibProcessor when it builds the
|
// binary's location), populated during parsing and consumed by stdlibProcessor when it builds the
|
||||||
@ -63,7 +63,7 @@ func newGoBinaryCataloger(opts CatalogerConfig) *goBinaryCataloger {
|
|||||||
return &goBinaryCataloger{
|
return &goBinaryCataloger{
|
||||||
licenseResolver: newGoLicenseResolver(binaryCatalogerName, opts),
|
licenseResolver: newGoLicenseResolver(binaryCatalogerName, opts),
|
||||||
mainModuleVersion: opts.MainModuleVersion,
|
mainModuleVersion: opts.MainModuleVersion,
|
||||||
captureSymbols: opts.CaptureSymbols,
|
symbolScope: opts.CaptureSymbols.Parse(),
|
||||||
stdlibSymbols: make(map[file.Coordinates][]string),
|
stdlibSymbols: make(map[file.Coordinates][]string),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -98,7 +98,7 @@ func (c *goBinaryCataloger) parseGoBinary(ctx context.Context, resolver file.Res
|
|||||||
}
|
}
|
||||||
defer internal.CloseAndLogError(reader.ReadCloser, reader.RealPath)
|
defer internal.CloseAndLogError(reader.ReadCloser, reader.RealPath)
|
||||||
|
|
||||||
mods, errs := scanFile(reader.Location, unionReader, c.captureSymbols)
|
mods, errs := scanFile(reader.Location, unionReader, c.symbolScope != SymbolScopeNone)
|
||||||
|
|
||||||
var rels []artifact.Relationship
|
var rels []artifact.Relationship
|
||||||
for _, mod := range mods {
|
for _, mod := range mods {
|
||||||
@ -161,6 +161,12 @@ func (c *goBinaryCataloger) buildGoPkgInfo(ctx context.Context, resolver file.Re
|
|||||||
symbolsByModule, stdlibSymbols := moduleSymbols(mod.symbols, &mod.Main, mod.Deps)
|
symbolsByModule, stdlibSymbols := moduleSymbols(mod.symbols, &mod.Main, mod.Deps)
|
||||||
c.recordStdlibSymbols(location.Coordinates, stdlibSymbols)
|
c.recordStdlibSymbols(location.Coordinates, stdlibSymbols)
|
||||||
|
|
||||||
|
if c.symbolScope != SymbolScopeAll {
|
||||||
|
// only the "all" scope attaches per-module symbols; for the "stdlib" scope we keep just the
|
||||||
|
// recorded stdlib symbols. nil map lookups below then yield nil symbol lists for each module.
|
||||||
|
symbolsByModule = nil
|
||||||
|
}
|
||||||
|
|
||||||
var pkgs []pkg.Package
|
var pkgs []pkg.Package
|
||||||
for _, dep := range mod.Deps {
|
for _, dep := range mod.Deps {
|
||||||
if dep == nil {
|
if dep == nil {
|
||||||
|
|||||||
@ -1422,3 +1422,71 @@ type alwaysErrorReader struct{}
|
|||||||
func (alwaysErrorReader) Read(_ []byte) (int, error) {
|
func (alwaysErrorReader) Read(_ []byte) (int, error) {
|
||||||
return 0, errors.New("read from always error reader")
|
return 0, errors.New("read from always error reader")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_buildGoPkgInfo_symbolScope(t *testing.T) {
|
||||||
|
location := file.NewLocationFromCoordinates(file.Coordinates{RealPath: "/a-path", FileSystemID: "layer-id"})
|
||||||
|
|
||||||
|
// the symbols a binary would carry once scanFile has extracted them: one main-package symbol, one
|
||||||
|
// dependency symbol, and one standard-library symbol. For the "none" scope scanFile never runs, so the
|
||||||
|
// build info carries no symbols at all.
|
||||||
|
populatedSymbols := []binarySymbol{
|
||||||
|
{packagePath: "main", name: "main.main"},
|
||||||
|
{packagePath: "github.com/foo/bar", name: "github.com/foo/bar.Parse"},
|
||||||
|
{packagePath: "net/http", name: "net/http.(*Client).Do"},
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
scope SymbolScope
|
||||||
|
symbols []binarySymbol
|
||||||
|
wantMainSyms []string
|
||||||
|
wantDepSyms []string
|
||||||
|
wantStdlibSyms []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "none captures nothing",
|
||||||
|
scope: SymbolScopeNone,
|
||||||
|
symbols: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "stdlib captures only the stdlib package",
|
||||||
|
scope: SymbolScopeStdlib,
|
||||||
|
symbols: populatedSymbols,
|
||||||
|
wantStdlibSyms: []string{"net/http.(*Client).Do"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "all captures module and stdlib packages",
|
||||||
|
scope: SymbolScopeAll,
|
||||||
|
symbols: populatedSymbols,
|
||||||
|
wantMainSyms: []string{"main.main"},
|
||||||
|
wantDepSyms: []string{"github.com/foo/bar.Parse"},
|
||||||
|
wantStdlibSyms: []string{"net/http.(*Client).Do"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
mod := &extendedBuildInfo{
|
||||||
|
BuildInfo: &debug.BuildInfo{
|
||||||
|
GoVersion: "go1.22.0",
|
||||||
|
Main: debug.Module{Path: "github.com/anchore/syft", Version: "v1.0.0"},
|
||||||
|
Deps: []*debug.Module{{Path: "github.com/foo/bar", Version: "v1.2.3"}},
|
||||||
|
},
|
||||||
|
arch: "amd64",
|
||||||
|
symbols: tt.symbols,
|
||||||
|
}
|
||||||
|
|
||||||
|
c := newGoBinaryCataloger(CatalogerConfig{CaptureSymbols: tt.scope})
|
||||||
|
reader, err := unionreader.GetUnionReader(io.NopCloser(strings.NewReader("")))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
mainPkg, pkgs := c.buildGoPkgInfo(context.Background(), fileresolver.Empty{}, location, mod, mod.arch, reader)
|
||||||
|
require.NotNil(t, mainPkg)
|
||||||
|
require.Len(t, pkgs, 1)
|
||||||
|
|
||||||
|
assert.Equal(t, tt.wantMainSyms, mainPkg.Metadata.(pkg.GolangBinaryBuildinfoEntry).Symbols, "main module symbols")
|
||||||
|
assert.Equal(t, tt.wantDepSyms, pkgs[0].Metadata.(pkg.GolangBinaryBuildinfoEntry).Symbols, "dependency symbols")
|
||||||
|
assert.Equal(t, tt.wantStdlibSyms, c.stdlibSymbolsFor(location.Coordinates), "recorded stdlib symbols")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -25,7 +25,9 @@ type GolangBinaryBuildinfoEntry struct {
|
|||||||
|
|
||||||
// Symbols are the fully qualified function symbols from this module that are compiled into the binary
|
// Symbols are the fully qualified function symbols from this module that are compiled into the binary
|
||||||
// (e.g., "github.com/foo/bar.(*Type).Method"), extracted from the binary symbol table (pclntab).
|
// (e.g., "github.com/foo/bar.(*Type).Method"), extracted from the binary symbol table (pclntab).
|
||||||
// Only captured when the golang cataloger is configured to capture symbols.
|
// Populated only when the golang cataloger's capture-symbols scope covers this package: the "all" scope
|
||||||
|
// populates every module package plus the synthetic stdlib package, while the "stdlib" scope populates
|
||||||
|
// only the stdlib package.
|
||||||
Symbols []string `json:"symbols,omitempty"`
|
Symbols []string `json:"symbols,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user