diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2024-12-02 10:57:36 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2024-12-11 15:22:17 +0000 |
| commit | 38f1ffbd30e38b3215fa81114230ae2948dca8dc (patch) | |
| tree | 2411633f27011259a74e43a65b7d3544f5444f5b /pkg/declextract | |
| parent | 2f981ae0154bd9e967e046692984f0b6e2423a32 (diff) | |
pkg/declextract: refactor netlink generation
Emit all information related to a single netlink family close to each other.
Previously we emitted them scattered and grouped by info type.
That was both inconvinient to emit and inconvinient to read.
NFC.
Diffstat (limited to 'pkg/declextract')
| -rw-r--r-- | pkg/declextract/declextract.go | 1 | ||||
| -rw-r--r-- | pkg/declextract/entity.go | 3 | ||||
| -rw-r--r-- | pkg/declextract/netlink.go | 95 | ||||
| -rw-r--r-- | pkg/declextract/serialization.go | 21 |
4 files changed, 42 insertions, 78 deletions
diff --git a/pkg/declextract/declextract.go b/pkg/declextract/declextract.go index 49a515ddb..f950cee1e 100644 --- a/pkg/declextract/declextract.go +++ b/pkg/declextract/declextract.go @@ -22,7 +22,6 @@ func Run(out *Output, syscallRename map[string][]string) ([]byte, []*Interface, ctx.processStructs() ctx.processSyscalls() ctx.processIouring() - ctx.fabricateNetlinkPolicies() ctx.serialize() ctx.finishInterfaces() diff --git a/pkg/declextract/entity.go b/pkg/declextract/entity.go index 57e589e40..6e9ddac85 100644 --- a/pkg/declextract/entity.go +++ b/pkg/declextract/entity.go @@ -80,9 +80,6 @@ type Struct struct { IsPacked bool `json:"is_packed,omitempty"` Align int `json:"align,omitempty"` Fields []*Field `json:"fields,omitempty"` - - // TODO: remove me. - isVarlen bool } type Enum struct { diff --git a/pkg/declextract/netlink.go b/pkg/declextract/netlink.go index ad80122dc..3f2384cc6 100644 --- a/pkg/declextract/netlink.go +++ b/pkg/declextract/netlink.go @@ -5,69 +5,28 @@ package declextract import ( "fmt" - "sort" "strings" ) -func (ctx *context) fabricateNetlinkPolicies() { +func (ctx *context) serializeNetlink() { + // policyQueue helps to emit policies on their first use. + pq := &policyQueue{ + policies: make(map[string]*NetlinkPolicy), + } for _, pol := range ctx.NetlinkPolicies { - if len(pol.Attrs) == 0 { - continue - } - str := &Struct{ - Name: pol.Name + autoSuffix, - IsUnion: true, - isVarlen: true, - } - for _, attr := range pol.Attrs { - str.Fields = append(str.Fields, &Field{ - Name: attr.Name, - syzType: ctx.nlattrType(attr), - }) - } - ctx.Structs = append(ctx.Structs, str) + pq.policies[pol.Name] = pol } - ctx.Structs = sortAndDedupSlice(ctx.Structs) -} - -func (ctx *context) emitNetlinkTypes() { for _, fam := range ctx.NetlinkFamilies { if isEmptyFamily(fam) { continue } id := stringIdentifier(fam.Name) ctx.fmt("resource genl_%v_family_id%v[int16]\n", id, autoSuffix) - } - for _, fam := range ctx.NetlinkFamilies { - if isEmptyFamily(fam) { - continue - } - id := stringIdentifier(fam.Name) ctx.fmt("type msghdr_%v%v[CMD, POLICY] msghdr_netlink[netlink_msg_t"+ "[genl_%v_family_id%v, genlmsghdr_t[CMD], POLICY]]\n", id, autoSuffix, id, autoSuffix) - } - for _, pol := range ctx.NetlinkPolicies { - if len(pol.Attrs) == 0 { - ctx.fmt("type %v auto_todo\n", pol.Name+autoSuffix) - } - } -} - -func (ctx *context) emitNetlinkGetFamily() { - for _, fam := range ctx.NetlinkFamilies { - if isEmptyFamily(fam) { - continue - } - id := stringIdentifier(fam.Name) ctx.fmt("syz_genetlink_get_family_id%v_%v(name ptr[in, string[\"%v\"]],"+ - " fd sock_nl_generic) genl_%v_family_id%v\n", autoSuffix, id, fam.Name, id, autoSuffix) - } -} + " fd sock_nl_generic) genl_%v_family_id%v\n\n", autoSuffix, id, fam.Name, id, autoSuffix) -func (ctx *context) emitNetlinkSendmsgs() { - var syscalls []string - for _, fam := range ctx.NetlinkFamilies { - id := stringIdentifier(fam.Name) dedup := make(map[string]bool) for _, op := range fam.Ops { // TODO: emit these as well, these are dump commands w/o input arguments. @@ -80,9 +39,10 @@ func (ctx *context) emitNetlinkSendmsgs() { continue } dedup[op.Name] = true - syscalls = append(syscalls, fmt.Sprintf("sendmsg%v_%v(fd sock_nl_generic,"+ + ctx.fmt("sendmsg%v_%v(fd sock_nl_generic,"+ " msg ptr[in, msghdr_%v%v[%v, %v]], f flags[send_flags])\n", - autoSuffix, op.Name, id, autoSuffix, op.Name, op.Policy+autoSuffix)) + autoSuffix, op.Name, id, autoSuffix, op.Name, op.Policy+autoSuffix) + pq.policyUsed(op.Policy) ctx.noteInterface(&Interface{ Type: IfaceNetlinkOp, @@ -94,11 +54,37 @@ func (ctx *context) emitNetlinkSendmsgs() { AutoDescriptions: true, }) } + + for len(pq.pending) != 0 { + pol := pq.pending[0] + pq.pending = pq.pending[1:] + ctx.serializeNetlinkPolicy(pol, pq) + } + } +} + +type policyQueue struct { + policies map[string]*NetlinkPolicy + pending []*NetlinkPolicy +} + +func (pq *policyQueue) policyUsed(name string) { + if pol := pq.policies[name]; pol != nil { + delete(pq.policies, name) + pq.pending = append(pq.pending, pol) + } +} + +func (ctx *context) serializeNetlinkPolicy(pol *NetlinkPolicy, pq *policyQueue) { + if len(pol.Attrs) == 0 { + ctx.fmt("type %v auto_todo\n", pol.Name+autoSuffix) + return } - sort.Strings(syscalls) - for _, call := range syscalls { - ctx.fmt("%s", call) + ctx.fmt("%v [\n", pol.Name+autoSuffix) + for _, attr := range pol.Attrs { + ctx.fmt("%v %v\n", attr.Name, ctx.nlattrType(attr, pq)) } + ctx.fmt("] [varlen]\n") } func isEmptyFamily(fam *NetlinkFamily) bool { @@ -110,7 +96,7 @@ func isEmptyFamily(fam *NetlinkFamily) bool { return true } -func (ctx *context) nlattrType(attr *NetlinkAttr) string { +func (ctx *context) nlattrType(attr *NetlinkAttr, pq *policyQueue) string { nlattr, typ := "nlattr", "" switch attr.Kind { case "NLA_BITFIELD32": @@ -124,6 +110,7 @@ func (ctx *context) nlattrType(attr *NetlinkAttr) string { nlattr = "nlnest" policy := "nl_generic_attr" if attr.NestedPolicy != "" { + pq.policyUsed(attr.NestedPolicy) policy = attr.NestedPolicy + autoSuffix } typ = fmt.Sprintf("array[%v]", policy) diff --git a/pkg/declextract/serialization.go b/pkg/declextract/serialization.go index c737a675c..1bc82a86b 100644 --- a/pkg/declextract/serialization.go +++ b/pkg/declextract/serialization.go @@ -14,8 +14,8 @@ func (ctx *context) serialize() { ctx.fmt(header) ctx.serializeIncludes() ctx.serializeEnums() - ctx.emitNetlinkTypes() ctx.serializeSyscalls() + ctx.serializeNetlink() ctx.serializeStructs() ctx.serializeDefines() } @@ -47,28 +47,12 @@ func (ctx *context) serializeDefines() { } func (ctx *context) serializeSyscalls() { - printedGetFamily, printedSendmsg := false, false for _, call := range ctx.Syscalls { ctx.fmt("%v(", call.Func) for i, arg := range call.Args { ctx.fmt("%v%v %v", comma(i), arg.Name, arg.syzType) } ctx.fmt(")\n") - - if call.Func == "syslog$auto" { - printedGetFamily = true - ctx.emitNetlinkGetFamily() - } - if call.Func == "sendmsg$auto" { - printedSendmsg = true - ctx.emitNetlinkSendmsgs() - } - } - if !printedGetFamily { - ctx.emitNetlinkGetFamily() - } - if !printedSendmsg { - ctx.emitNetlinkSendmsgs() } ctx.fmt("\n") } @@ -102,9 +86,6 @@ func (ctx *context) serializeStructs() { if str.Align != 0 { attrs = append(attrs, fmt.Sprintf("align[%v]", str.Align)) } - if str.isVarlen { - attrs = append(attrs, "varlen") - } if len(attrs) != 0 { ctx.fmt(" [%v]", strings.Join(attrs, ", ")) } |
