aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/declextract
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2025-01-17 10:39:46 +0100
committerDmitry Vyukov <dvyukov@google.com>2025-01-17 18:09:32 +0000
commit38ee454540b9b41d5cc173871dfbf7dd140e8abc (patch)
treea7f5f04a7a9286f9eeca01520b51012e3606bb99 /pkg/declextract
parent953d1c45a16b7284725e337b47369a8ab111bab4 (diff)
pkg/declextract: move const handling logic from the clang tool
Export raw info about consts from the clang tool, and let the Go part handle it. The less logic is in the clang tool, the better. Also this will allow to remove unused includes when we know which consts we ended up using. The more includes we include, the higher the chances we include something that's broken.
Diffstat (limited to 'pkg/declextract')
-rw-r--r--pkg/declextract/declextract.go53
-rw-r--r--pkg/declextract/entity.go20
-rw-r--r--pkg/declextract/serialization.go4
3 files changed, 52 insertions, 25 deletions
diff --git a/pkg/declextract/declextract.go b/pkg/declextract/declextract.go
index 1f4592523..fdf06b373 100644
--- a/pkg/declextract/declextract.go
+++ b/pkg/declextract/declextract.go
@@ -29,7 +29,7 @@ func Run(out *Output, probe *ifaceprobe.Info, syscallRename map[string][]string,
}
ctx.processFunctions()
ctx.processTypingFacts()
- ctx.processIncludes()
+ ctx.processConsts()
ctx.processEnums()
ctx.processStructs()
ctx.processSyscalls()
@@ -47,6 +47,8 @@ type context struct {
structs map[string]*Struct
funcs map[string]*Function
facts map[string]*typingNode
+ includes []string
+ defines []define
uniqualizer map[string]int
interfaces []*Interface
descriptions *bytes.Buffer
@@ -54,6 +56,11 @@ type context struct {
errs []error
}
+type define struct {
+ Name string
+ Value string
+}
+
func (ctx *context) error(msg string, args ...any) {
ctx.errs = append(ctx.errs, fmt.Errorf(msg, args...))
}
@@ -68,14 +75,7 @@ func (ctx *context) trace(msg string, args ...any) {
}
}
-func (ctx *context) processIncludes() {
- // These additional includes must be at the top, because other kernel headers
- // are broken and won't compile without these additional ones included first.
- ctx.Includes = append([]string{
- "vdso/bits.h",
- "linux/types.h",
- "net/netlink.h",
- }, ctx.Includes...)
+func (ctx *context) processConsts() {
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,
@@ -84,11 +84,40 @@ func (ctx *context) processIncludes() {
"include/uapi/asm-generic/ioctls.h": "asm/ioctls.h",
"include/uapi/asm-generic/sockios.h": "asm/sockios.h",
}
- for i, inc := range ctx.Includes {
- if replace := replaces[inc]; replace != "" {
- ctx.Includes[i] = replace
+ defineDedup := make(map[string]bool)
+ for _, ci := range ctx.Consts {
+ if strings.Contains(ci.Filename, "/uapi/") && !strings.Contains(ci.Filename, "arch/x86/") &&
+ strings.HasSuffix(ci.Filename, ".h") {
+ filename := ci.Filename
+ if replace := replaces[filename]; replace != "" {
+ filename = replace
+ }
+ ctx.includes = append(ctx.includes, filename)
+ continue
}
+ // Remove duplicate defines (even with different values). Unfortunately we get few of these.
+ // There are some syscall numbers (presumably for 32/64 bits), and some macros that
+ // are defined in different files to different values (e.g. WMI_DATA_BE_SVC).
+ // Ideally we somehow rename defines (chosing one random value is never correct).
+ // But for now this helps to prevent compilation errors.
+ if defineDedup[ci.Name] {
+ continue
+ }
+ defineDedup[ci.Name] = true
+ ctx.defines = append(ctx.defines, define{
+ Name: ci.Name,
+ Value: fmt.Sprint(ci.Value),
+ })
}
+ ctx.includes = sortAndDedupSlice(ctx.includes)
+ ctx.defines = sortAndDedupSlice(ctx.defines)
+ // These additional includes must be at the top, because other kernel headers
+ // are broken and won't compile without these additional ones included first.
+ ctx.includes = append([]string{
+ "vdso/bits.h",
+ "linux/types.h",
+ "net/netlink.h",
+ }, ctx.includes...)
}
func (ctx *context) processEnums() {
diff --git a/pkg/declextract/entity.go b/pkg/declextract/entity.go
index 266647ed8..8167d8b99 100644
--- a/pkg/declextract/entity.go
+++ b/pkg/declextract/entity.go
@@ -12,8 +12,7 @@ import (
type Output struct {
Functions []*Function `json:"functions,omitempty"`
- Includes []string `json:"includes,omitempty"`
- Defines []*Define `json:"defines,omitempty"`
+ Consts []*ConstInfo `json:"consts,omitempty"`
Enums []*Enum `json:"enums,omitempty"`
Structs []*Struct `json:"structs,omitempty"`
Syscalls []*Syscall `json:"syscalls,omitempty"`
@@ -36,9 +35,10 @@ type Function struct {
facts map[string]*typingNode
}
-type Define struct {
- Name string `json:"name,omitempty"`
- Value string `json:"value,omitempty"`
+type ConstInfo struct {
+ Name string `json:"name"`
+ Filename string `json:"filename"`
+ Value int64 `json:"value"`
}
type Field struct {
@@ -199,8 +199,7 @@ type EntityGlobalAddr struct {
func (out *Output) Merge(other *Output) {
out.Functions = append(out.Functions, other.Functions...)
- out.Includes = append(out.Includes, other.Includes...)
- out.Defines = append(out.Defines, other.Defines...)
+ out.Consts = append(out.Consts, other.Consts...)
out.Enums = append(out.Enums, other.Enums...)
out.Structs = append(out.Structs, other.Structs...)
out.Syscalls = append(out.Syscalls, other.Syscalls...)
@@ -212,8 +211,7 @@ func (out *Output) Merge(other *Output) {
func (out *Output) SortAndDedup() {
out.Functions = sortAndDedupSlice(out.Functions)
- out.Includes = sortAndDedupSlice(out.Includes)
- out.Defines = sortAndDedupSlice(out.Defines)
+ out.Consts = sortAndDedupSlice(out.Consts)
out.Enums = sortAndDedupSlice(out.Enums)
out.Structs = sortAndDedupSlice(out.Structs)
out.Syscalls = sortAndDedupSlice(out.Syscalls)
@@ -229,8 +227,8 @@ func (out *Output) SetSourceFile(file string, updatePath func(string) string) {
for _, fn := range out.Functions {
fn.File = updatePath(fn.File)
}
- for i, inc := range out.Includes {
- out.Includes[i] = updatePath(inc)
+ for _, ci := range out.Consts {
+ ci.Filename = updatePath(ci.Filename)
}
for _, call := range out.Syscalls {
call.SourceFile = file
diff --git a/pkg/declextract/serialization.go b/pkg/declextract/serialization.go
index d69358679..571336097 100644
--- a/pkg/declextract/serialization.go
+++ b/pkg/declextract/serialization.go
@@ -39,14 +39,14 @@ func (ctx *context) fmt(msg string, args ...any) {
}
func (ctx *context) serializeIncludes() {
- for _, inc := range ctx.Includes {
+ for _, inc := range ctx.includes {
ctx.fmt("include <%s>\n", inc)
}
ctx.fmt("\n")
}
func (ctx *context) serializeDefines() {
- for _, def := range ctx.Defines {
+ for _, def := range ctx.defines {
ctx.fmt("define %v %v\n", def.Name, def.Value)
}
ctx.fmt("\n")