From 580ff21224aa5b260a287fdd301541d5e11ce9b3 Mon Sep 17 00:00:00 2001 From: Timo Beckers Date: Fri, 13 Dec 2024 19:08:29 +0100 Subject: [PATCH] bpf2go: generate Go types used in global variables This commit generates Go type declarations for global variables declared in a C BPF program. Some improvements to CollectGlobalTypes were due: - types are now deduplicated by name - types are now selected based on allow-list instead of explicitly rejecting Datasec and Int - the output is sorted by type name - arrays' inner types are now emitted to interact with Variable{Spec} Also added a new btf.QualifiedType(), a subset of btf.UnderlyingType() to remove all qualifiers up to a Typedef, since Typedefs are named, and typically directly point to the anonymous type they alias. Typedefs should only be stripped for evaluating the concrete underlying type, and they should be included when yielding types to the Go renderer. Signed-off-by: Timo Beckers Co-authored-by: Simone Magnani --- btf/format.go | 3 + btf/format_test.go | 1 + btf/types.go | 14 +++++ cmd/bpf2go/gen/types.go | 89 +++++++++++++++++++++++------ cmd/bpf2go/gen/types_test.go | 27 +++++++-- cmd/bpf2go/test/test_bpfeb.go | 23 ++++++++ cmd/bpf2go/test/test_bpfeb.o | Bin 2520 -> 3416 bytes cmd/bpf2go/test/test_bpfel.go | 23 ++++++++ cmd/bpf2go/test/test_bpfel.o | Bin 2520 -> 3416 bytes cmd/bpf2go/testdata/minimal-eb.elf | Bin 2536 -> 3432 bytes cmd/bpf2go/testdata/minimal-el.elf | Bin 2536 -> 3432 bytes cmd/bpf2go/testdata/minimal.c | 21 ++++++- 12 files changed, 175 insertions(+), 26 deletions(-) diff --git a/btf/format.go b/btf/format.go index 5e581b4a8..3e0dedaa2 100644 --- a/btf/format.go +++ b/btf/format.go @@ -161,6 +161,9 @@ func (gf *GoFormatter) writeTypeLit(typ Type, depth int) error { case *Datasec: err = gf.writeDatasecLit(v, depth) + case *Var: + err = gf.writeTypeLit(v.Type, depth) + default: return fmt.Errorf("type %T: %w", v, ErrNotSupported) } diff --git a/btf/format_test.go b/btf/format_test.go index c26e023df..4bf21c0fe 100644 --- a/btf/format_test.go +++ b/btf/format_test.go @@ -137,6 +137,7 @@ func TestGoTypeDeclaration(t *testing.T) { }, "type t struct { _ [4]byte; g uint32; _ [8]byte; }", }, + {&Var{Type: &Int{Size: 4}}, "type t uint32"}, } for _, test := range tests { diff --git a/btf/types.go b/btf/types.go index 44d393067..dbcdf9dd7 100644 --- a/btf/types.go +++ b/btf/types.go @@ -1291,6 +1291,20 @@ func UnderlyingType(typ Type) Type { return &cycle{typ} } +// QualifiedType returns the type with all qualifiers removed. +func QualifiedType(typ Type) Type { + result := typ + for depth := 0; depth <= maxResolveDepth; depth++ { + switch v := (result).(type) { + case qualifier: + result = v.qualify() + default: + return result + } + } + return &cycle{typ} +} + // As returns typ if is of type T. Otherwise it peels qualifiers and Typedefs // until it finds a T. // diff --git a/cmd/bpf2go/gen/types.go b/cmd/bpf2go/gen/types.go index 37dad0c76..115d73423 100644 --- a/cmd/bpf2go/gen/types.go +++ b/cmd/bpf2go/gen/types.go @@ -1,44 +1,95 @@ package gen import ( + "cmp" + "slices" + "github.com/cilium/ebpf" "github.com/cilium/ebpf/btf" ) // CollectGlobalTypes finds all types which are used in the global scope. // -// This currently includes the types of map keys and values. +// This currently includes the types of variables, map keys and values. func CollectGlobalTypes(spec *ebpf.CollectionSpec) []btf.Type { var types []btf.Type - for _, typ := range collectMapTypes(spec.Maps) { - switch btf.UnderlyingType(typ).(type) { - case *btf.Datasec: - // Avoid emitting .rodata, .bss, etc. for now. We might want to - // name these types differently, etc. - continue - case *btf.Int: - // Don't emit primitive types by default. - continue - } + types = collectMapTypes(types, spec.Maps) + types = collectVariableTypes(types, spec.Variables) - types = append(types, typ) - } + slices.SortStableFunc(types, func(a, b btf.Type) int { + return cmp.Compare(a.TypeName(), b.TypeName()) + }) return types } -// collectMapTypes returns a list of all types used as map keys or values. -func collectMapTypes(maps map[string]*ebpf.MapSpec) []btf.Type { - var result []btf.Type +// collectMapTypes collects all types used by MapSpecs. +func collectMapTypes(types []btf.Type, maps map[string]*ebpf.MapSpec) []btf.Type { for _, m := range maps { if m.Key != nil && m.Key.TypeName() != "" { - result = append(result, m.Key) + types = addType(types, m.Key) } if m.Value != nil && m.Value.TypeName() != "" { - result = append(result, m.Value) + types = addType(types, m.Value) } } - return result + + return types +} + +// collectVariableTypes collects all types used by VariableSpecs. +func collectVariableTypes(types []btf.Type, vars map[string]*ebpf.VariableSpec) []btf.Type { + for _, vs := range vars { + v := vs.Type() + if v == nil { + continue + } + + types = addType(types, v.Type) + } + + return types +} + +// addType adds a type to types if not already present. Types that don't need to +// be generated are not added to types. +func addType(types []btf.Type, incoming btf.Type) []btf.Type { + incoming = selectType(incoming) + if incoming == nil { + return types + } + + // Strip only the qualifiers (not typedefs) from the incoming type. Retain + // typedefs since they carry the name of the anonymous type they point to, + // without which we can't generate a named Go type. + incoming = btf.QualifiedType(incoming) + if incoming.TypeName() == "" { + return types + } + + exists := func(existing btf.Type) bool { + return existing.TypeName() == incoming.TypeName() + } + if !slices.ContainsFunc(types, exists) { + types = append(types, incoming) + } + return types +} + +func selectType(t btf.Type) btf.Type { + // Obtain a concrete type with qualifiers and typedefs stripped. + switch ut := btf.UnderlyingType(t).(type) { + case *btf.Struct, *btf.Union, *btf.Enum: + return t + + // Collect the array's element type. Note: qualifiers on array-type variables + // typically appear after the array, e.g. a const volatile int[4] is actually + // an array of const volatile ints. + case *btf.Array: + return selectType(ut.Type) + } + + return nil } diff --git a/cmd/bpf2go/gen/types_test.go b/cmd/bpf2go/gen/types_test.go index bb5866301..286705a98 100644 --- a/cmd/bpf2go/gen/types_test.go +++ b/cmd/bpf2go/gen/types_test.go @@ -8,19 +8,34 @@ import ( "github.com/cilium/ebpf/internal/testutils" "github.com/go-quicktest/qt" + "github.com/google/go-cmp/cmp" ) +func mustAnyTypeByName(t *testing.T, spec *ebpf.CollectionSpec, name string) btf.Type { + t.Helper() + + typ, err := spec.Types.AnyTypeByName(name) + qt.Assert(t, qt.IsNil(err)) + return typ +} + func TestCollectGlobalTypes(t *testing.T) { spec, err := ebpf.LoadCollectionSpec(testutils.NativeFile(t, "../testdata/minimal-%s.elf")) if err != nil { t.Fatal(err) } - map1 := spec.Maps["map1"] + bar := mustAnyTypeByName(t, spec, "bar") + barfoo := mustAnyTypeByName(t, spec, "barfoo") + baz := mustAnyTypeByName(t, spec, "baz") + e := mustAnyTypeByName(t, spec, "e") + ubar := mustAnyTypeByName(t, spec, "ubar") - types := CollectGlobalTypes(spec) - if err != nil { - t.Fatal(err) - } - qt.Assert(t, qt.CmpEquals(types, []btf.Type{map1.Key, map1.Value}, typesEqualComparer)) + got := CollectGlobalTypes(spec) + qt.Assert(t, qt.IsNil(err)) + + want := []btf.Type{bar, barfoo, baz, e, ubar} + qt.Assert(t, qt.CmpEquals(got, want, cmp.Comparer(func(a, b btf.Type) bool { + return a.TypeName() == b.TypeName() + }))) } diff --git a/cmd/bpf2go/test/test_bpfeb.go b/cmd/bpf2go/test/test_bpfeb.go index 28b1b3b2a..be2f2e68d 100644 --- a/cmd/bpf2go/test/test_bpfeb.go +++ b/cmd/bpf2go/test/test_bpfeb.go @@ -12,6 +12,12 @@ import ( "github.com/cilium/ebpf" ) +type testBar struct { + A uint64 + B uint32 + _ [4]byte +} + type testBarfoo struct { Bar int64 Baz bool @@ -19,6 +25,8 @@ type testBarfoo struct { Boo testE } +type testBaz struct{ A uint64 } + type testE uint32 const ( @@ -26,6 +34,11 @@ const ( testEFROOD testE = 1 ) +type testUbar struct { + A uint32 + _ [4]byte +} + // loadTest returns the embedded CollectionSpec for test. func loadTest() (*ebpf.CollectionSpec, error) { reader := bytes.NewReader(_TestBytes) @@ -82,8 +95,13 @@ type testMapSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type testVariableSpecs struct { + AnInt *ebpf.VariableSpec `ebpf:"an_int"` + IntArray *ebpf.VariableSpec `ebpf:"int_array"` MyConstant *ebpf.VariableSpec `ebpf:"my_constant"` + StructArray *ebpf.VariableSpec `ebpf:"struct_array"` StructConst *ebpf.VariableSpec `ebpf:"struct_const"` + StructVar *ebpf.VariableSpec `ebpf:"struct_var"` + UnionVar *ebpf.VariableSpec `ebpf:"union_var"` } // testObjects contains all objects after they have been loaded into the kernel. @@ -119,8 +137,13 @@ func (m *testMaps) Close() error { // // It can be passed to loadTestObjects or ebpf.CollectionSpec.LoadAndAssign. type testVariables struct { + AnInt *ebpf.Variable `ebpf:"an_int"` + IntArray *ebpf.Variable `ebpf:"int_array"` MyConstant *ebpf.Variable `ebpf:"my_constant"` + StructArray *ebpf.Variable `ebpf:"struct_array"` StructConst *ebpf.Variable `ebpf:"struct_const"` + StructVar *ebpf.Variable `ebpf:"struct_var"` + UnionVar *ebpf.Variable `ebpf:"union_var"` } // testPrograms contains all programs after they have been loaded into the kernel. diff --git a/cmd/bpf2go/test/test_bpfeb.o b/cmd/bpf2go/test/test_bpfeb.o index dffb8f859117afb163cae0aa7dd56b09355bd48f..a59e38c274ed68be811441166a3f5b40a23d2afa 100644 GIT binary patch literal 3416 zcmbtWO=ule6uy(!q)F2@^*{Bm(^_pbI@PEp=)!3*!D8fv7?jk-WZuiPefGV1VP;dr-72wfC6#kIQ9@4Iu(%XMrJ^pJD!Ip==o=ia&J zzPvNPxG*&2nE`p`H^`1*umWN1W2=QSP8e_Ukd+5RES^<+|F#k`A?qKC$17)6)OVMh zy8Pefo1fXRlcjgO`ArFH?@EhR0;4N?rCT1JlIfwyt0BrpzfVhneh0!(v{?;x+$82*t=f*G2 z{N(Q>-tCaBi){2R=;c9_d;CFgcUExr``H64^ZX>Zdn!14?t){jzXw)1C+6S=+8>*6TrH$pMV3KSH_BohnuG?*!qQ8-ti%H*X#_e8WI`O3_NsFwNGUrm9a648(r}JKs{5d?>R{9Qhrxc+auxooAkL$37*&nD+wgT8EfzJ-K5ij^yIFXZ;4u z&ss&VtwH8fM;oZt#=zee)!&88vr+vM$c!iFSo=cORR0<}&p`EU$gD;6?;-PBs(u49 z&r;$Wd1D58h&9%#>q`}Vt)g$JzVE>J{)0}F{H+&)BDsWi&60L7x3UmWxmAm~El9Ao z`A%PG|Ch~dduXS9+U?Cw6tAym=t-xs1EebAh6(b1$IjAQT2A@0U?2aN_%D{6b2ZfH z&tkb+St(PXnQ~uo1tMAQa0zk9nG#E8M4gB9q<5lx-69DqW)7F!^Y{`AyPf~<;`9M#p1OpZd-QA9Y(K-R(;3adOroG`rXBCt<8 delta 690 zcmYjOJxc>Y5Z$|EFS*T!QNtxBDNYm%L5aa4jmb5(Du|Fm1&atm0)h(KXfS`kbHLit z*3Qy@poKz;6v4vEGJ=SOZ{i-_gSnaaW_EUVu2<+yUM*&cj+_kQpwJ%_TJ%<*gt3;H>qKF+PA1@ zxU9)DM27F@>_^tnX_-98CkRJ(%}bAEz=QE!!5x9;Jtko2;>ZXug$Btit*fNu73zsQ n2pJnN?xL6g;V!GxPZpGX{>uo71;{1{e!HWhr&_)vFO~lVQ}RwB diff --git a/cmd/bpf2go/test/test_bpfel.go b/cmd/bpf2go/test/test_bpfel.go index a66809533..4fb0c2280 100644 --- a/cmd/bpf2go/test/test_bpfel.go +++ b/cmd/bpf2go/test/test_bpfel.go @@ -12,6 +12,12 @@ import ( "github.com/cilium/ebpf" ) +type testBar struct { + A uint64 + B uint32 + _ [4]byte +} + type testBarfoo struct { Bar int64 Baz bool @@ -19,6 +25,8 @@ type testBarfoo struct { Boo testE } +type testBaz struct{ A uint64 } + type testE uint32 const ( @@ -26,6 +34,11 @@ const ( testEFROOD testE = 1 ) +type testUbar struct { + A uint32 + _ [4]byte +} + // loadTest returns the embedded CollectionSpec for test. func loadTest() (*ebpf.CollectionSpec, error) { reader := bytes.NewReader(_TestBytes) @@ -82,8 +95,13 @@ type testMapSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type testVariableSpecs struct { + AnInt *ebpf.VariableSpec `ebpf:"an_int"` + IntArray *ebpf.VariableSpec `ebpf:"int_array"` MyConstant *ebpf.VariableSpec `ebpf:"my_constant"` + StructArray *ebpf.VariableSpec `ebpf:"struct_array"` StructConst *ebpf.VariableSpec `ebpf:"struct_const"` + StructVar *ebpf.VariableSpec `ebpf:"struct_var"` + UnionVar *ebpf.VariableSpec `ebpf:"union_var"` } // testObjects contains all objects after they have been loaded into the kernel. @@ -119,8 +137,13 @@ func (m *testMaps) Close() error { // // It can be passed to loadTestObjects or ebpf.CollectionSpec.LoadAndAssign. type testVariables struct { + AnInt *ebpf.Variable `ebpf:"an_int"` + IntArray *ebpf.Variable `ebpf:"int_array"` MyConstant *ebpf.Variable `ebpf:"my_constant"` + StructArray *ebpf.Variable `ebpf:"struct_array"` StructConst *ebpf.Variable `ebpf:"struct_const"` + StructVar *ebpf.Variable `ebpf:"struct_var"` + UnionVar *ebpf.Variable `ebpf:"union_var"` } // testPrograms contains all programs after they have been loaded into the kernel. diff --git a/cmd/bpf2go/test/test_bpfel.o b/cmd/bpf2go/test/test_bpfel.o index 1cc5b1e1bf854b14aa56e04f135fe001f8c8760f..9bc2674a3e5ffecc5a82713361f0fb2869c255f6 100644 GIT binary patch literal 3416 zcmbtWO>7%Q6rMO~vD3t9%3t{@-IfA@!WIft6&%<`B%&h7QHY9C4x6>JZB6ZUv|dLw z5+Vl7f$efJMY=!CF%j5{O0}4H}l^7 zyjj1yu(Vhj8#78{=9U>+>NVz*%1{q-H83+k9xQ;P{T5gB_h+qtM*2Uprg`n`YOWQg zk>39=KK~s#$}~TX8$*6;7_0Z0 zk7=-(@E}*fn#UW^xsCw*Cio8UHaG$kvjc8}LDgwAIu7b|2~BE!Q!|j?fkFB0K}?0_ z`^MvD66Ei}py~lM3W7R$H@%iBT;q>cuigde;`IFBu5i6S3+~}~| zev7L<0-sfLXk`w9_X0WQcf^fz2*AhD7l04jLFFf)&slwNN1wNLmG{o7P_REwp$Xu? z+?$*6bJ_zd6nZr1zIP=UN2@zZ_Gg6Xb!0>`|qI>#64i` zkT}nSxn}(jiOxA66`h#6Gyk39=RBsFWF`#HtgM__3tvBbej!|4TV4o56Ps6RwdFOl zxKgXVZ0b>Zq0^xNzisN!Tb<-02UB`%OgP`^v`p6DjLqe^Z?>XVFE;JyN*E_u+Kju< zH=i*VnyoBOO}Epy9B0P&Ph@d7+laF0M7x=ND-f^#+ zrM*UGJw8%-(KIe0p)hPU8*$P_tRdXEU=t-FQw4`nnnrz;ZV$$(=fceNl5X>25^vZw z$S{kl=cs2-x+u;gpe+RNaZ7qhvy+50{d%`+e5?~~+Tp53s=u zHh*EQLv!QZrl0E|F?Z7Y;930=Kv(>?xu378B~K*t<~#?*Ry_BGe!cG+hi^OmbAs2n zmvXRQ#=1;|@Ab;uDoZ}nE<}U0w zHgo#HvH9)$Rcwys_lWNci8gZ#z$CSotvRsQ3-)Hgo}At{RdtGFq!#=vzJhX1fu&x7+^zDf|DSjOG3lr}^vt zABAtX_^0JUZKL0%Vtju4cZ+{j0xip6#^-xgjQcAhy8+x*@>A^8c0VXBbgD Tdropq^7mwM6vSzKJ(qs~;t&*E delta 681 zcmZuu&nrYx6h80Gy!YnaH{;h}W`ud9uuw)8$d9+Nqm&d23x!fMAruyRC| zBU}G~D2knxmF2Kfd}rojlCQpZ?m6GN=bU@qW7}i;q_1VsrXK{AQ$Tgm#BubTRK7_h z{Gf~X8>8a|vO!cYS#_0E$gr=V$=mU~Sth=Wf3R=2@`ycKC=z9%h2SaJ1Anl_cj1rJ z_+~MRy7}I2&P^iPL@|7;2(;~D!^z~D;Wd&?2_0?FcAg7P#yzU24iRsA8Gd%MLuCvt zh=cOlB%UOY`oe6DFFAuIA0}4$E#Y&!n^mQitsPq5DDJNDq8nPvax03`?t_IBaLjj3 znv*JtW^ry;<3@p()KvcfG#3oOTKM{&uY)PRRvBY~pVX95;+&V~E6>l#Vr1^$B~;VT z@T^|zKvWFDTVBE(j`5i4oZdt1zkY%47gP&S3RYJ4cYPjWQqwK#o*|E_{0cVtZ`n|n sor5lrvI_iLb{etR%;zRd2>#$!-?zTkXRSdqF@V~azW|&QkEJ@l0MYnUN&o-= diff --git a/cmd/bpf2go/testdata/minimal-eb.elf b/cmd/bpf2go/testdata/minimal-eb.elf index dafa0302f471fc6449f6c6582122a4f28e1c4178..8a45210acb2a3326b8cbd59fb531eebe144853ba 100644 GIT binary patch literal 3432 zcmbtWO=w(I6uy(+Nz*pJ8coxj~YvAX^cO3GZ)KbRmLthlVgqRkF znRR>MWw0!p*C7vseej#$QSdG}1QW9dZXd@0ItI3W6hPcYio$4{0N=2S&@tPbPT%;& znV;hcXt72zn^Vbp66G=-B-Zbz6*}E{vo*g73b7P8*3x( zFTp*eIH}KruJxUUI3xW(Lpz+g7nn-y=OeU19u>@4$S3S(^O}9GI{6=lD)~#NB>$tZ zSr^&EdFT~@SR>BJZF#0(dmQY;enE0R0eMz(GPVc(MTvb5x*Pif)K^hBW9uFm4^(1o z-Op9=f07IMdkY_)J|yBudVVQ0Rt*>_!-%`BWfOMxiga&2*&dt}nQq){1{I;n< zZYA*sojH3POfZ)uEtB=OB6BV3neDLEjZ8b-38FYln^6by*3)La*~+5SbdvhDC^OSh zZEJnH-fm1|p4mvIv#66b!YrI_H{)hIY*p%JERC{m8hhOThDS! z1%*9t>YFGp2wKg06nBt$A8uT*3FCl;gM%c-6^4yaaYosOws*BH};yE0mwys@5q2i{%sB6tl<;`i%;^-S

!UMnen8LgV$wE^>3iF2deKu zW-Y4UfXwfy`Y({#ONnpf&FSkt)>yl)FBSB)g1)8tkz?aWk2}}ow%bt2qMZ!KI%-ws zRu(E$4!UISB_vp`y>m14J;<-Ky+!*MsMXqT2VtX;;#N9WyMk0%STmJQuWe_!U0P25 z(qJF|m-v%Q`dkcE{#`8J7gqF~(9E-Bb5Zyi5gIhjCB?p4V8I6TOf>bmD(O64jEY(a=neEih|V%> zIfOZ04PndoJ$kpZ*R@$8rVt2A17LAR2s=!|=P@!NK4#(=N$i4G1_y@oufRtG!dUMg z(^qt%BF7-O86SXH34C}cGnmCU<5+;p)Q=sIay%+JIo&-vJrl<#o%0s8ou1m~MBjI{ z`hdsMqqHtaNkv_k>(tS8wFcIqhIUsJZ;8c&CZWMH!k62l5sr4L7+;b(>Z4c{Ou@NF zK8wekx`ZcvKkK|Qhf15&1bqQ_(rZ;UC;Z>9!M%bWf#pTUp{U}j2;Z1K6B#5SwrP~eYc-ez@G`ss)dIr9yE<}b_(y6cbHBF%OYr~z diff --git a/cmd/bpf2go/testdata/minimal-el.elf b/cmd/bpf2go/testdata/minimal-el.elf index 0acd3be7c464a2824724d1697b918844ed891afc..89b8e9d3a38db740f3382acd676c1dc0d75e7cac 100644 GIT binary patch literal 3432 zcmbtWO=w(I6uy}x?M#|Xn)+A&>T9i9jh$$eAiD6iHo;;vAq`3_^73ZpB^f&NCcJqQ zGJ=?e3qb@of(ylsLN_i15y4HCF1iuix#>c%AnpVgF7*4}JtuSL85H!8^UgWn{q8;I z{!ZSWUtA~*4H=ao^SkLsiW+mh)c5_&_01%hCv)WRxaH;X-ju~BrTs%2nwKxHW?pU> zY5o7^(_c`d4D-XVG1T3DvI0V#@6ZT*?;td6G6g7cb{U02lxHJQj=;Mc3hohd@0FI* zu>Dk~P(=KQZ7b?>BFPAsqyinYZDtmB9O^^opd5c4`YaSuJciH3%r!$C(?^;`iJ1== z%iw3kgI$4Y9k0RXJbdU?=uzk%G=!3~4{bpqrNhP{Y`lH4Dz!2 zh_N>E{(wTt_v7Q{^@v(2ordMUK#FIqC3l4NjKX;#tJUt*?6|412B~K&1Ik zSzh@eVAjp3rE@Sm7pO5iBW|8)5FbUG4?S-?6(55?XZ?dS`htziJa^WGgY`L&&no~h z_NdN*<54)a&gY8se;hd7H*6nnznSI-qUV=B$Et#Zzl>8R2=Sm>0CDy*{7!-pt^w~3 zh2z|pc@{qo2ClC*^W2anbzaS1Q*-wrb&C-k+~N2%ud+sMy3_+22q?Qji>{E z`$@CWXr@tOI_=uEC^a)tb$er`)~e6I&Th76(x{Wx!!(>}HR47qY*uQfltgJaiM>`Y zsI}ux8pf$N?RChz*uzEcBA9zR zNKH5HG&bX?Zf7LjEUTKao|<)897jkyNZ#cFb>l`m4j5LdosOws*7zoE&dO+Ud}BS? z2i{#O-=lRXh5OfoV%sv|9#V;A`v$uQ{R~?A#$@lc#%B>f0bFCYKjXv&#Q!G4_R0;= zLPRGV+?UqpVW+Ye*8*A}&pL6=g~IwN??I>ZmjS-=zs_*Ju2wv;texYWlvw#(8{&HY zH4oo<;^%~~dABlLS^auCf-A4jumdm;A3)8|m^G{ugwW^jP}7N7!#hsQxB6p=X{gto zm}7k9#9W1aCuU7IoS46bKS|8K{C(nkLt)GseJDlaWg8yE>$!M47mrOG8!tQ8WZ*Vb z(r7ouv5uORi>nJ228UfT_Y#sU*WS4q`X1QpoZX`S1!^{TT0vN^C%Bc))vh2_8dgoE z(`#i`ZkLv0UmBUte>VJoOO|+Gj9=w|d^>>l@2bK)FWd+2y(_*OI6n8ul_doK)Zcf> z@bl;PC15-!KGc<4a>YCW`Fq28YJa^4?*n80{2J^5qvY!)*Oku^5X0}~fV?Xa@3kwM zU$Luj4$HqU1W&A*eE(O`KrCPXP3fTbS;B+)Yy2gg{G8Z!lOIT(m(G#=dVGPl!`8nj zg?=D?x&Gv7{kr~VfE||qk{qZ#w7Zhe&;JDu%m0xiT9(et&-W^y|1Ds{i+{FZ_MiuH eONhDY|E<GFkf-@|U;YBluokrd delta 682 zcmZutJugI25S{n-eeAt&*Vkfq1-nFoWXVz~d^|)!L?ohANDz`01cgSPY$GZ!^9K|P zt%(1i6aRpOgib-D;oP?u8*!3z=gyp&xpU{a?ooQ6vJ78uWbj{yXkBryn1pduA_C@F7UXU7Kf4Q67i9j=2tf}_=d3+ zEKq$nfj=pz{)(9@U*!}{K8dfeE%ICt8M(QN7lFN`s=_cOo^0HJGC#N} zZj}i3DLB~;SS z@U3q9K&cpl121k)#CS%wPwgZ2-+S}=J-^a`lCWxZf7jbCPyE=6r6?tj}(Ar_nc+=2{R{0HQ8WMm diff --git a/cmd/bpf2go/testdata/minimal.c b/cmd/bpf2go/testdata/minimal.c index 1639d6ef0..d906d2408 100644 --- a/cmd/bpf2go/testdata/minimal.c +++ b/cmd/bpf2go/testdata/minimal.c @@ -12,6 +12,20 @@ typedef struct { enum e boo; } barfoo; +typedef struct { + uint64_t a; +} baz; + +struct bar { + uint64_t a; + uint32_t b; +}; + +union ubar { + uint32_t a; + uint64_t b; +}; + struct { __uint(type, BPF_MAP_TYPE_HASH); __type(key, enum e); @@ -19,9 +33,14 @@ struct { __uint(max_entries, 1); } map1 __section(".maps"); +volatile const int an_int; volatile const enum e my_constant = FROOD; - +volatile const int int_array[2]; volatile const barfoo struct_const; +volatile const baz struct_array[2]; + +volatile struct bar struct_var; +volatile union ubar union_var; __section("socket") int filter() { return my_constant + struct_const.bar;