diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2025-01-17 10:39:47 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2025-01-17 18:09:32 +0000 |
| commit | f2cb035c8f931efff4a020b164e657f16f51934b (patch) | |
| tree | 967cd39fb98171cba878893a41ca461ffa993c8c /pkg | |
| parent | 38ee454540b9b41d5cc173871dfbf7dd140e8abc (diff) | |
pkg/declextract: remove unused includes and defines
This is nice on its own, but this will also help to prevent
lots of problems when we export more info from the clang tool in future.
The clang tool does not know what will end up in the final descriptions,
so it exports info about all consts that it encounters.
As the result we pull in lots of includes/defines, and lots of kernel
includes/defines are broken or create problems.
So the fewer we have, the better.
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/ast/ast.go | 2 | ||||
| -rw-r--r-- | pkg/compiler/check.go | 38 | ||||
| -rw-r--r-- | pkg/compiler/consts.go | 13 | ||||
| -rw-r--r-- | pkg/declextract/declextract.go | 15 |
4 files changed, 59 insertions, 9 deletions
diff --git a/pkg/ast/ast.go b/pkg/ast/ast.go index bd2d97c23..7c1db28ea 100644 --- a/pkg/ast/ast.go +++ b/pkg/ast/ast.go @@ -71,7 +71,7 @@ type Include struct { } func (n *Include) Info() (Pos, string, string) { - return n.Pos, tok2str[tokInclude], "" + return n.Pos, tok2str[tokInclude], n.File.Value } type Incdir struct { diff --git a/pkg/compiler/check.go b/pkg/compiler/check.go index 92e3e5e03..fbf84857d 100644 --- a/pkg/compiler/check.go +++ b/pkg/compiler/check.go @@ -676,6 +676,44 @@ func CollectUnused(desc *ast.Description, target *targets.Target, eh ast.ErrorHa return nodes, nil } +// CollectUnusedConsts returns unused defines/includes. This is used only for auto-generated descriptions. +func CollectUnusedConsts(desc *ast.Description, target *targets.Target, includeUse map[string]string, + eh ast.ErrorHandler) ([]ast.Node, error) { + comp := createCompiler(desc, target, eh) + comp.typecheck() + if comp.errors > 0 { + return nil, errors.New("typecheck failed") + } + + var unused []ast.Node + for file, info := range comp.extractConsts() { + if !comp.fileMeta(ast.Pos{File: file}).Automatic { + continue + } + usedDefines := make(map[string]bool) + usedIncludes := make(map[string]bool) + for _, c := range info.Consts { + if c.Used { + usedDefines[c.Name] = true + usedIncludes[includeUse[c.Name]] = true + } + } + for _, decl := range comp.desc.Nodes { + switch n := decl.(type) { + case *ast.Define: + if n.Pos.File == file && !usedDefines[n.Name.Name] { + unused = append(unused, n) + } + case *ast.Include: + if n.Pos.File == file && !usedIncludes[n.File.Value] { + unused = append(unused, n) + } + } + } + } + return unused, nil +} + func (comp *compiler) collectUnused() []ast.Node { var unused []ast.Node diff --git a/pkg/compiler/consts.go b/pkg/compiler/consts.go index bcbd40e52..6ce3f81f1 100644 --- a/pkg/compiler/consts.go +++ b/pkg/compiler/consts.go @@ -23,6 +23,7 @@ type ConstInfo struct { type Const struct { Name string Pos ast.Pos + Used bool // otherwise only defined } func ExtractConsts(desc *ast.Description, target *targets.Target, eh ast.ErrorHandler) map[string]*ConstInfo { @@ -86,7 +87,7 @@ func (comp *compiler) extractConsts() map[string]*ConstInfo { comp.error(pos, "redefining builtin const %v", name) } info.defines[name] = v - comp.addConst(ctx, pos, name) + ctx.addConst(pos, name, false) case *ast.Call: if comp.target.HasCallNumber(n.CallName) { comp.addConst(ctx, pos, comp.target.SyscallPrefix+n.CallName) @@ -178,10 +179,10 @@ func (comp *compiler) addConst(ctx *constContext, pos ast.Pos, name string) { if _, isFlag := comp.intFlags[name]; isFlag { return } - ctx.addConst(pos, name) + ctx.addConst(pos, name, true) for _, instantions := range ctx.instantionStack { for _, pos1 := range instantions { - ctx.addConst(pos1, name) + ctx.addConst(pos1, name, true) } } } @@ -193,11 +194,15 @@ type constInfo struct { incdirArray []string } -func (ctx *constContext) addConst(pos ast.Pos, name string) { +func (ctx *constContext) addConst(pos ast.Pos, name string, used bool) { info := ctx.getConstInfo(pos) + if c := info.consts[name]; c != nil && c.Used { + used = true + } info.consts[name] = &Const{ Pos: pos, Name: name, + Used: used, } } diff --git a/pkg/declextract/declextract.go b/pkg/declextract/declextract.go index fdf06b373..9df449b63 100644 --- a/pkg/declextract/declextract.go +++ b/pkg/declextract/declextract.go @@ -16,7 +16,7 @@ import ( ) func Run(out *Output, probe *ifaceprobe.Info, syscallRename map[string][]string, trace io.Writer) ( - []byte, []*Interface, error) { + []byte, []*Interface, map[string]string, error) { ctx := &context{ Output: out, probe: probe, @@ -29,7 +29,7 @@ func Run(out *Output, probe *ifaceprobe.Info, syscallRename map[string][]string, } ctx.processFunctions() ctx.processTypingFacts() - ctx.processConsts() + includeUse := ctx.processConsts() ctx.processEnums() ctx.processStructs() ctx.processSyscalls() @@ -37,7 +37,7 @@ func Run(out *Output, probe *ifaceprobe.Info, syscallRename map[string][]string, ctx.serialize() ctx.finishInterfaces() - return ctx.descriptions.Bytes(), ctx.interfaces, errors.Join(ctx.errs...) + return ctx.descriptions.Bytes(), ctx.interfaces, includeUse, errors.Join(ctx.errs...) } type context struct { @@ -75,7 +75,7 @@ func (ctx *context) trace(msg string, args ...any) { } } -func (ctx *context) processConsts() { +func (ctx *context) processConsts() map[string]string { replaces := map[string]string{ // Arches may use some includes from asm-generic and some from arch/arm. // If the arch used for extract used asm-generic for a header, @@ -85,6 +85,7 @@ func (ctx *context) processConsts() { "include/uapi/asm-generic/sockios.h": "asm/sockios.h", } defineDedup := make(map[string]bool) + includeUse := make(map[string]string) for _, ci := range ctx.Consts { if strings.Contains(ci.Filename, "/uapi/") && !strings.Contains(ci.Filename, "arch/x86/") && strings.HasSuffix(ci.Filename, ".h") { @@ -93,6 +94,7 @@ func (ctx *context) processConsts() { filename = replace } ctx.includes = append(ctx.includes, filename) + includeUse[ci.Name] = filename continue } // Remove duplicate defines (even with different values). Unfortunately we get few of these. @@ -118,6 +120,11 @@ func (ctx *context) processConsts() { "linux/types.h", "net/netlink.h", }, ctx.includes...) + // Also pretend they are used. + includeUse["__NR_read"] = "vdso/bits.h" + includeUse["__NR_write"] = "linux/types.h" + includeUse["__NR_close"] = "net/netlink.h" + return includeUse } func (ctx *context) processEnums() { |
