Repository: cilium/ebpf (go)

Issue:
bpf2go: emit `structs.HostLayout` into generated structs
We recently made a change to make sure our syscall wrappers continue to work on future versions of go, see #1681. Timo points out that we should do the same for bpf2go:

              Looks good, thanks! We should probably also emit these in bpf2go types.

_Originally posted by @ti-mo in https://github.com/cilium/ebpf/pull/1681#pullrequestreview-2620432502_
          
I think it might make sense to just update `GoFormatter` to always include `HostLayout` in structs instead of the hack I did for `gentypes`.

Pull request description:
bpf2go, btf: emit structs.HostLayout in GoFormatter
Types described by BTF essentially follow C rules for laying out a struct. Use the newly introduced structs.HostLayout to hint at the compiler that reordering is not permissible.

Fixes #1686

Patch:
diff --git a/btf/format.go b/btf/format.go
index 3e0deda..7deca33 100644
--- a/btf/format.go
+++ b/btf/format.go
@@ -56,7 +56,7 @@ func (gf *GoFormatter) enumIdentifier(name, element string) string {
 //
 // It encodes https://golang.org/ref/spec#Type_declarations:
 //
-//	type foo struct { bar uint32; }
+//	type foo struct { _ structs.HostLayout; bar uint32; }
 //	type bar int32
 func (gf *GoFormatter) writeTypeDecl(name string, typ Type) error {
 	if name == "" {
@@ -114,7 +114,7 @@ func (gf *GoFormatter) writeType(typ Type, depth int) error {
 //
 // It encodes https://golang.org/ref/spec#TypeLit.
 //
-//	struct { bar uint32; }
+//	struct { _ structs.HostLayout; bar uint32; }
 //	uint32
 func (gf *GoFormatter) writeTypeLit(typ Type, depth int) error {
 	depth++
@@ -208,7 +208,7 @@ func (gf *GoFormatter) writeIntLit(i *Int) error {
 }
 
 func (gf *GoFormatter) writeStructLit(size uint32, members []Member, depth int) error {
-	gf.w.WriteString("struct { ")
+	gf.w.WriteString("struct { _ structs.HostLayout; ")
 
 	prevOffset := uint32(0)
 	skippedBitfield := false
@@ -298,7 +298,7 @@ func (gf *GoFormatter) writeStructField(m Member, depth int) error {
 }
 
 func (gf *GoFormatter) writeDatasecLit(ds *Datasec, depth int) error {
-	gf.w.WriteString("struct { ")
+	gf.w.WriteString("struct { _ structs.HostLayout; ")
 
 	prevOffset := uint32(0)
 	for i, vsi := range ds.Vars {
diff --git a/cmd/bpf2go/gen/output.go b/cmd/bpf2go/gen/output.go
index 9f0fc06..fbda8df 100644
--- a/cmd/bpf2go/gen/output.go
+++ b/cmd/bpf2go/gen/output.go
@@ -161,20 +161,31 @@ func Generate(args GenerateArgs) error {
 		Identifier: args.Identifier,
 	}
 
+	var typeDecls []string
+	needsStructsPkg := false
+	for _, typ := range types {
+		name := typeNames[typ]
+		decl, err := gf.TypeDeclaration(name, typ)
+		if err != nil {
+			return fmt.Errorf("generating %s: %w", name, err)
+		}
+		_, ok := typ.(*btf.Struct)
+		needsStructsPkg = needsStructsPkg || ok
+		typeDecls = append(typeDecls, decl)
+	}
+
 	ctx := struct {
-		*btf.GoFormatter
-		Module      string
-		Package     string
-		Constraints constraint.Expr
-		Name        templateName
-		Maps        map[string]string
-		Variables   map[string]string
-		Programs    map[string]string
-		Types       []btf.Type
-		TypeNames   map[btf.Type]string
-		File        string
+		Module           string
+		Package          string
+		Constraints      constraint.Expr
+		Name             templateName
+		Maps             map[string]string
+		Variables        map[string]string
+		Programs         map[string]string
+		TypeDeclarations []string
+		File             string
+		NeedsStructsPkg  bool
 	}{
-		gf,
 		b2gInt.CurrentModule,
 		args.Package,
 		args.Constraints,
@@ -182,9 +193,9 @@ func Generate(args GenerateArgs) error {
 		maps,
 		variables,
 		programs,
-		types,
-		typeNames,
+		typeDecls,
 		args.ObjectFile,
+		needsStructsPkg,
 	}
 
 	var buf bytes.Buffer
diff --git a/cmd/bpf2go/gen/output.tpl b/cmd/bpf2go/gen/output.tpl
index 474c9c5..350b0ca 100644
--- a/cmd/bpf2go/gen/output.tpl
+++ b/cmd/bpf2go/gen/output.tpl
@@ -8,13 +8,16 @@ import (
 	_ "embed"
 	"fmt"
 	"io"
+{{- if .NeedsStructsPkg }}
+	"structs"
+{{- end }}
 
 	"{{ .Module }}"
 )
 
-{{- if .Types }}
-{{- range $type := .Types }}
-{{ $.TypeDeclaration (index $.TypeNames $type) $type }}
+{{- if .TypeDeclarations }}
+{{- range $type := .TypeDeclarations }}
+{{ $type }}
 
 {{ end }}
 {{- end }}
diff --git a/examples/fentry/bpf_bpfeb.go b/examples/fentry/bpf_bpfeb.go
index 7fab2f4..db8b37b 100644
--- a/examples/fentry/bpf_bpfeb.go
+++ b/examples/fentry/bpf_bpfeb.go
@@ -8,11 +8,13 @@ import (
 	_ "embed"
 	"fmt"
 	"io"
+	"structs"
 
 	"github.com/cilium/ebpf"
 )
 
 type bpfEvent struct {
+	_     structs.HostLayout
 	Comm  [16]uint8
 	Sport uint16
 	Dport uint16
diff --git a/examples/fentry/bpf_bpfel.go b/examples/fentry/bpf_bpfel.go
index 96515ee..69a89fa 100644
--- a/examples/fentry/bpf_bpfel.go
+++ b/examples/fentry/bpf_bpfel.go
@@ -8,11 +8,13 @@ import (
 	_ "embed"
 	"fmt"
 	"io"
+	"structs"
 
 	"github.com/cilium/ebpf"
 )
 
 type bpfEvent struct {
+	_     structs.HostLayout
 	Comm  [16]uint8
 	Sport uint16
 	Dport uint16
diff --git a/examples/ringbuffer/bpf_bpfeb.go b/examples/ringbuffer/bpf_bpfeb.go
index 8e716a8..8ef3284 100644
--- a/examples/ringbuffer/bpf_bpfeb.go
+++ b/examples/ringbuffer/bpf_bpfeb.go
@@ -8,11 +8,13 @@ import (
 	_ "embed"
 	"fmt"
 	"io"
+	"structs"
 
 	"github.com/cilium/ebpf"
 )
 
 type bpfEvent struct {
+	_    structs.HostLayout
 	Pid  uint32
 	Comm [16]uint8
 }
diff --git a/examples/ringbuffer/bpf_bpfel.go b/examples/ringbuffer/bpf_bpfel.go
index 897a938..fbb1c4a 100644
--- a/examples/ringbuffer/bpf_bpfel.go
+++ b/examples/ringbuffer/bpf_bpfel.go
@@ -8,11 +8,13 @@ import (
 	_ "embed"
 	"fmt"
 	"io"
+	"structs"
 
 	"github.com/cilium/ebpf"
 )
 
 type bpfEvent struct {
+	_    structs.HostLayout
 	Pid  uint32
 	Comm [16]uint8
 }
diff --git a/examples/tcprtt/bpf_bpfeb.go b/examples/tcprtt/bpf_bpfeb.go
index 8d320fd..95f71bd 100644
--- a/examples/tcprtt/bpf_bpfeb.go
+++ b/examples/tcprtt/bpf_bpfeb.go
@@ -8,11 +8,13 @@ import (
 	_ "embed"
 	"fmt"
 	"io"
+	"structs"
 
 	"github.com/cilium/ebpf"
 )
 
 type bpfEvent struct {
+	_     structs.HostLayout
 	Sport uint16
 	Dport uint16
 	Saddr uint32
diff --git a/examples/tcprtt/bpf_bpfel.go b/examples/tcprtt/bpf_bpfel.go
index 2efbd26..3112677 100644
--- a/examples/tcprtt/bpf_bpfel.go
+++ b/examples/tcprtt/bpf_bpfel.go
@@ -8,11 +8,13 @@ import (
 	_ "embed"
 	"fmt"
 	"io"
+	"structs"
 
 	"github.com/cilium/ebpf"
 )
 
 type bpfEvent struct {
+	_     structs.HostLayout
 	Sport uint16
 	Dport uint16
 	Saddr uint32
diff --git a/examples/tcprtt_sockops/bpf_bpfeb.go b/examples/tcprtt_sockops/bpf_bpfeb.go
index 870c24c..361a967 100644
--- a/examples/tcprtt_sockops/bpf_bpfeb.go
+++ b/examples/tcprtt_sockops/bpf_bpfeb.go
@@ -8,11 +8,13 @@ import (
 	_ "embed"
 	"fmt"
 	"io"
+	"structs"
 
 	"github.com/cilium/ebpf"
 )
 
 type bpfRttEvent struct {
+	_     structs.HostLayout
 	Sport uint16
 	Dport uint16
 	Saddr uint32
@@ -21,12 +23,14 @@ type bpfRttEvent struct {
 }
 
 type bpfSkInfo struct {
+	_      structs.HostLayout
 	SkKey  bpfSkKey
 	SkType uint8
 	_      [3]byte
 }
 
 type bpfSkKey struct {
+	_          structs.HostLayout
 	LocalIp4   uint32
 	RemoteIp4  uint32
 	LocalPort  uint32
diff --git a/examples/tcprtt_sockops/bpf_bpfel.go b/examples/tcprtt_sockops/bpf_bpfel.go
index dd04d6f..d5e9d86 100644
--- a/examples/tcprtt_sockops/bpf_bpfel.go
+++ b/examples/tcprtt_sockops/bpf_bpfel.go
@@ -8,11 +8,13 @@ import (
 	_ "embed"
 	"fmt"
 	"io"
+	"structs"
 
 	"github.com/cilium/ebpf"
 )
 
 type bpfRttEvent struct {
+	_     structs.HostLayout
 	Sport uint16
 	Dport uint16
 	Saddr uint32
@@ -21,12 +23,14 @@ type bpfRttEvent struct {
 }
 
 type bpfSkInfo struct {
+	_      structs.HostLayout
 	SkKey  bpfSkKey
 	SkType uint8
 	_      [3]byte
 }
 
 type bpfSkKey struct {
+	_          structs.HostLayout
 	LocalIp4   uint32
 	RemoteIp4  uint32
 	LocalPort  uint32
diff --git a/examples/uretprobe/bpf_x86_bpfel.go b/examples/uretprobe/bpf_x86_bpfel.go
index fd8616a..cbdd704 100644
--- a/examples/uretprobe/bpf_x86_bpfel.go
+++ b/examples/uretprobe/bpf_x86_bpfel.go
@@ -8,11 +8,13 @@ import (
 	_ "embed"
 	"fmt"
 	"io"
+	"structs"
 
 	"github.com/cilium/ebpf"
 )
 
 type bpfEvent struct {
+	_    structs.HostLayout
 	Pid  uint32
 	Line [80]uint8
 }
diff --git a/internal/cmd/gentypes/main.go b/internal/cmd/gentypes/main.go
index 66c1175..7171e6a 100644
--- a/internal/cmd/gentypes/main.go
+++ b/internal/cmd/gentypes/main.go
@@ -837,8 +837,6 @@ func outputPatchedStruct(gf *btf.GoFormatter, w *bytes.Buffer, id string, s *btf
 		return err
 	}
 
-	decl = strings.Replace(decl, "struct {", "struct { structs.HostLayout;", 1)
-
 	w.WriteString(decl)
 	w.WriteString("\n\n")
 	return nil
diff --git a/internal/sys/types.go b/internal/sys/types.go
index a76d4a5..2847f17 100644
--- a/internal/sys/types.go
+++ b/internal/sys/types.go
@@ -690,7 +690,7 @@ const (
 )
 
 type BtfInfo struct {
-	structs.HostLayout
+	_         structs.HostLayout
 	Btf       TypedPointer[uint8]
 	BtfSize   uint32
 	Id        BTFID
@@ -700,13 +700,13 @@ type BtfInfo struct {
 }
 
 type FuncInfo struct {
-	structs.HostLayout
+	_       structs.HostLayout
 	InsnOff uint32
 	TypeId  uint32
 }
 
 type LineInfo struct {
-	structs.HostLayout
+	_           structs.HostLayout
 	InsnOff     uint32
 	FileNameOff uint32
 	LineOff     uint32
@@ -714,7 +714,7 @@ type LineInfo struct {
 }
 
 type LinkInfo struct {
-	structs.HostLayout
+	_      structs.HostLayout
 	Type   LinkType
 	Id     LinkID
 	ProgId uint32
@@ -723,7 +723,7 @@ type LinkInfo struct {
 }
 
 type MapInfo struct {
-	structs.HostLayout
+	_                     structs.HostLayout
 	Type                  uint32
 	Id                    MapID
 	KeySize               uint32
@@ -743,7 +743,7 @@ type MapInfo struct {
 }
 
 type ProgInfo struct {
-	structs.HostLayout
+	_                    structs.HostLayout
 	Type                 uint32
 	Id                   uint32
 	Tag                  [8]uint8
@@ -786,7 +786,7 @@ type ProgInfo struct {
 }
 
 type SkLookup struct {
-	structs.HostLayout
+	_              structs.HostLayout
 	Cookie         uint64
 	Family         uint32
 	Protocol       uint32
@@ -802,7 +802,7 @@ type SkLookup struct {
 }
 
 type XdpMd struct {
-	structs.HostLayout
+	_              structs.HostLayout
 	Data           uint32
 	DataEnd        uint32
 	DataMeta       uint32
@@ -812,7 +812,7 @@ type XdpMd struct {
 }
 
 type BtfGetFdByIdAttr struct {
-	structs.HostLayout
+	_  structs.HostLayout
 	Id uint32
 }
 
@@ -825,7 +825,7 @@ func BtfGetFdById(attr *BtfGetFdByIdAttr) (*FD, error) {
 }
 
 type BtfGetNextIdAttr struct {
-	structs.HostLayout
+	_      structs.HostLayout
 	Id     BTFID
 	NextId BTFID
 }
@@ -836,7 +836,7 @@ func BtfGetNextId(attr *BtfGetNextIdAttr) error {
 }
 
 type BtfLoadAttr struct {
-	structs.HostLayout
+	_              structs.HostLayout
 	Btf            TypedPointer[uint8]
 	BtfLogBuf      TypedPointer[uint8]
 	BtfSize        uint32
@@ -856,7 +856,7 @@ func BtfLoad(attr *BtfLoadAttr) (*FD, error) {
 }
 
 type EnableStatsAttr struct {
-	structs.HostLayout
+	_    structs.HostLayout
 	Type uint32
 }
 
@@ -869,7 +869,7 @@ func EnableStats(attr *EnableStatsAttr) (*FD, error) {
 }
 
 type IterCreateAttr struct {
-	structs.HostLayout
+	_      structs.HostLayout
 	LinkFd uint32
 	Flags  uint32
 }
@@ -883,7 +883,7 @@ func IterCreate(attr *IterCreateAttr) (*FD, error) {
 }
 
 type LinkCreateAttr struct {
-	structs.HostLayout
+	_           structs.HostLayout
 	ProgFd      uint32
 	TargetFd    uint32
 	AttachType  AttachType
@@ -901,7 +901,7 @@ func LinkCreate(attr *LinkCreateAttr) (*FD, error) {
 }
 
 type LinkCreateIterAttr struct {
-	structs.HostLayout
+	_           structs.HostLayout
 	ProgFd      uint32
 	TargetFd    uint32
 	AttachType  AttachType
@@ -920,7 +920,7 @@ func LinkCreateIter(attr *LinkCreateIterAttr) (*FD, error) {
 }
 
 type LinkCreateKprobeMultiAttr struct {
-	structs.HostLayout
+	_                structs.HostLayout
 	ProgFd           uint32
 	TargetFd         uint32
 	AttachType       AttachType
@@ -942,7 +942,7 @@ func LinkCreateKprobeMulti(attr *LinkCreateKprobeMultiAttr) (*FD, error) {
 }
 
 type LinkCreateNetfilterAttr struct {
-	structs.HostLayout
+	_              structs.HostLayout
 	ProgFd         uint32
 	TargetFd       uint32
 	AttachType     AttachType
@@ -963,7 +963,7 @@ func LinkCreateNetfilter(attr *LinkCreateNetfilterAttr) (*FD, error) {
 }
 
 type LinkCreateNetkitAttr struct {
-	structs.HostLayout
+	_                structs.HostLayout
 	ProgFd           uint32
 	TargetIfindex    uint32
 	AttachType       AttachType
@@ -983,7 +983,7 @@ func LinkCreateNetkit(attr *LinkCreateNetkitAttr) (*FD, error) {
 }
 
 type LinkCreatePerfEventAttr struct {
-	structs.HostLayout
+	_          structs.HostLayout
 	ProgFd     uint32
 	TargetFd   uint32
 	AttachType AttachType
@@ -1001,7 +1001,7 @@ func LinkCreatePerfEvent(attr *LinkCreatePerfEventAttr) (*FD, error) {
 }
 
 type LinkCreateTcxAttr struct {
-	structs.HostLayout
+	_                structs.HostLayout
 	ProgFd           uint32
 	TargetIfindex    uint32
 	AttachType       AttachType
@@ -1021,7 +1021,7 @@ func LinkCreateTcx(attr *LinkCreateTcxAttr) (*FD, error) {
 }
 
 type LinkCreateTracingAttr struct {
-	structs.HostLayout
+	_           structs.HostLayout
 	ProgFd      uint32
 	TargetFd    uint32
 	AttachType  AttachType
@@ -1041,7 +1041,7 @@ func LinkCreateTracing(attr *LinkCreateTracingAttr) (*FD, error) {
 }
 
 type LinkCreateUprobeMultiAttr struct {
-	structs.HostLayout
+	_                structs.HostLayout
 	ProgFd           uint32
 	TargetFd         uint32
 	AttachType       AttachType
@@ -1065,7 +1065,7 @@ func LinkCreateUprobeMulti(attr *LinkCreateUprobeMultiAttr) (*FD, error) {
 }
 
 type LinkGetFdByIdAttr struct {
-	structs.HostLayout
+	_  structs.HostLayout
 	Id LinkID
 }
 
@@ -1078,7 +1078,7 @@ func LinkGetFdById(attr *LinkGetFdByIdAttr) (*FD, error) {
 }
 
 type LinkGetNextIdAttr struct {
-	structs.HostLayout
+	_      structs.HostLayout
 	Id     LinkID
 	NextId LinkID
 }
@@ -1089,7 +1089,7 @@ func LinkGetNextId(attr *LinkGetNextIdAttr) error {
 }
 
 type LinkUpdateAttr struct {
-	structs.HostLayout
+	_         structs.HostLayout
 	LinkFd    uint32
 	NewProgFd uint32
 	Flags     uint32
@@ -1102,7 +1102,7 @@ func LinkUpdate(attr *LinkUpdateAttr) error {
 }
 
 type MapCreateAttr struct {
-	structs.HostLayout
+	_                     structs.HostLayout
 	MapType               MapType
 	KeySize               uint32
 	ValueSize             uint32
@@ -1130,7 +1130,7 @@ func MapCreate(attr *MapCreateAttr) (*FD, error) {
 }
 
 type MapDeleteBatchAttr struct {
-	structs.HostLayout
+	_         structs.HostLayout
 	InBatch   Pointer
 	OutBatch  Pointer
 	Keys      Pointer
@@ -1147,7 +1147,7 @@ func MapDeleteBatch(attr *MapDeleteBatchAttr) error {
 }
 
 type MapDeleteElemAttr struct {
-	structs.HostLayout
+	_     structs.HostLayout
 	MapFd uint32
 	_     [4]byte
 	Key   Pointer
@@ -1161,7 +1161,7 @@ func MapDeleteElem(attr *MapDeleteElemAttr) error {
 }
 
 type MapFreezeAttr struct {
-	structs.HostLayout
+	_     structs.HostLayout
 	MapFd uint32
 }
 
@@ -1171,7 +1171,7 @@ func MapFreeze(attr *MapFreezeAttr) error {
 }
 
 type MapGetFdByIdAttr struct {
-	structs.HostLayout
+	_  structs.HostLayout
 	Id uint32
 }
 
@@ -1184,7 +1184,7 @@ func MapGetFdById(attr *MapGetFdByIdAttr) (*FD, error) {
 }
 
 type MapGetNextIdAttr struct {
-	structs.HostLayout
+	_      structs.HostLayout
 	Id     uint32
 	NextId uint32
 }
@@ -1195,7 +1195,7 @@ func MapGetNextId(attr *MapGetNextIdAttr) error {
 }
 
 type MapGetNextKeyAttr struct {
-	structs.HostLayout
+	_       structs.HostLayout
 	MapFd   uint32
 	_       [4]byte
 	Key     Pointer
@@ -1208,7 +1208,7 @@ func MapGetNextKey(attr *MapGetNextKeyAttr) error {
 }
 
 type MapLookupAndDeleteBatchAttr struct {
-	structs.HostLayout
+	_         structs.HostLayout
 	InBatch   Pointer
 	OutBatch  Pointer
 	Keys      Pointer
@@ -1225,7 +1225,7 @@ func MapLookupAndDeleteBatch(attr *MapLookupAndDeleteBatchAttr) error {
 }
 
 type MapLookupAndDeleteElemAttr struct {
-	structs.HostLayout
+	_     structs.HostLayout
 	MapFd uint32
 	_     [4]byte
 	Key   Pointer
@@ -1239,7 +1239,7 @@ func MapLookupAndDeleteElem(attr *MapLookupAndDeleteElemAttr) error {
 }
 
 type MapLookupBatchAttr struct {
-	structs.HostLayout
+	_         structs.HostLayout
 	InBatch   Pointer
 	OutBatch  Pointer
 	Keys      Pointer
@@ -1256,7 +1256,7 @@ func MapLookupBatch(attr *MapLookupBatchAttr) error {
 }
 
 type MapLookupElemAttr struct {
-	structs.HostLayout
+	_     structs.HostLayout
 	MapFd uint32
 	_     [4]byte
 	Key   Pointer
@@ -1270,7 +1270,7 @@ func MapLookupElem(attr *MapLookupElemAttr) error {
 }
 
 type MapUpdateBatchAttr struct {
-	structs.HostLayout
+	_         structs.HostLayout
 	InBatch   Pointer
 	OutBatch  Pointer
 	Keys      Pointer
@@ -1287,7 +1287,7 @@ func MapUpdateBatch(attr *MapUpdateBatchAttr) error {
 }
 
 type MapUpdateElemAttr struct {
-	structs.HostLayout
+	_     structs.HostLayout
 	MapFd uint32
 	_     [4]byte
 	Key   Pointer
@@ -1301,7 +1301,7 @@ func MapUpdateElem(attr *MapUpdateElemAttr) error {
 }
 
 type ObjGetAttr struct {
-	structs.HostLayout
+	_         structs.HostLayout
 	Pathname  StringPointer
 	BpfFd     uint32
 	FileFlags uint32
@@ -1318,7 +1318,7 @@ func ObjGet(attr *ObjGetAttr) (*FD, error) {
 }
 
 type ObjGetInfoByFdAttr struct {
-	structs.HostLayout
+	_       structs.HostLayout
 	BpfFd   uint32
 	InfoLen uint32
 	Info    Pointer
@@ -1330,7 +1330,7 @@ func ObjGetInfoByFd(attr *ObjGetInfoByFdAttr) error {
 }
 
 type ObjPinAttr struct {
-	structs.HostLayout
+	_         structs.HostLayout
 	Pathname  StringPointer
 	BpfFd     uint32
 	FileFlags uint32
@@ -1344,7 +1344,7 @@ func ObjPin(attr *ObjPinAttr) error {
 }
 
 type ProgAttachAttr struct {
-	structs.HostLayout
+	_                 structs.HostLayout
 	TargetFdOrIfindex uint32
 	AttachBpfFd       uint32
 	AttachType        uint32
@@ -1360,7 +1360,7 @@ func ProgAttach(attr *ProgAttachAttr) error {
 }
 
 type ProgBindMapAttr struct {
-	structs.HostLayout
+	_      structs.HostLayout
 	ProgFd uint32
 	MapFd  uint32
 	Flags  uint32
@@ -1372,7 +1372,7 @@ func ProgBindMap(attr *ProgBindMapAttr) error {
 }
 
 type ProgDetachAttr struct {
-	structs.HostLayout
+	_                 structs.HostLayout
 	TargetFdOrIfindex uint32
 	AttachBpfFd       uint32
 	AttachType        uint32
@@ -1388,7 +1388,7 @@ func ProgDetach(attr *ProgDetachAttr) error {
 }
 
 type ProgGetFdByIdAttr struct {
-	structs.HostLayout
+	_  structs.HostLayout
 	Id uint32
 }
 
@@ -1401,7 +1401,7 @@ func ProgGetFdById(attr *ProgGetFdByIdAttr) (*FD, error) {
 }
 
 type ProgGetNextIdAttr struct {
-	structs.HostLayout
+	_      structs.HostLayout
 	Id     uint32
 	NextId uint32
 }
@@ -1412,7 +1412,7 @@ func ProgGetNextId(attr *ProgGetNextIdAttr) error {
 }
 
 type ProgLoadAttr struct {
-	structs.HostLayout
+	_                  structs.HostLayout
 	ProgType           ProgType
 	InsnCnt            uint32
 	Insns              TypedPointer[uint8]
@@ -1452,7 +1452,7 @@ func ProgLoad(attr *ProgLoadAttr) (*FD, error) {
 }
 
 type ProgQueryAttr struct {
-	structs.HostLayout
+	_                 structs.HostLayout
 	TargetFdOrIfindex uint32
 	AttachType        AttachType
 	QueryFlags        uint32
@@ -1472,7 +1472,7 @@ func ProgQuery(attr *ProgQueryAttr) error {
 }
 
 type ProgRunAttr struct {
-	structs.HostLayout
+	_           structs.HostLayout
 	ProgFd      uint32
 	Retval      uint32
 	DataSizeIn  uint32
@@ -1497,7 +1497,7 @@ func ProgRun(attr *ProgRunAttr) error {
 }
 
 type RawTracepointOpenAttr struct {
-	structs.HostLayout
+	_      structs.HostLayout
 	Name   StringPointer
 	ProgFd uint32
 	_      [4]byte
@@ -1513,7 +1513,7 @@ func RawTracepointOpen(attr *RawTracepointOpenAttr) (*FD, error) {
 }
 
 type CgroupLinkInfo struct {
-	structs.HostLayout
+	_          structs.HostLayout
 	Type       LinkType
 	Id         LinkID
 	ProgId     uint32
@@ -1524,7 +1524,7 @@ type CgroupLinkInfo struct {
 }
 
 type IterLinkInfo struct {
-	structs.HostLayout
+	_             structs.HostLayout
 	Type          LinkType
 	Id            LinkID
 	ProgId        uint32
@@ -1534,7 +1534,7 @@ type IterLinkInfo struct {
 }
 
 type KprobeLinkInfo struct {
-	structs.HostLayout
+	_             structs.HostLayout
 	Type          LinkType
 	Id            LinkID
 	ProgId        uint32
@@ -1550,7 +1550,7 @@ type KprobeLinkInfo struct {
 }
 
 type KprobeMultiLinkInfo struct {
-	structs.HostLayout
+	_       structs.HostLayout
 	Type    LinkType
 	Id      LinkID
 	ProgId  uint32
@@ -1564,7 +1564,7 @@ type KprobeMultiLinkInfo struct {
 }
 
 type NetNsLinkInfo struct {
-	structs.HostLayout
+	_          structs.HostLayout
 	Type       LinkType
 	Id         LinkID
 	ProgId     uint32
@@ -1575,7 +1575,7 @@ type NetNsLinkInfo struct {
 }
 
 type NetfilterLinkInfo struct {
-	structs.HostLayout
+	_        structs.HostLayout
 	Type     LinkType
 	Id       LinkID
 	ProgId   uint32
@@ -1588,7 +1588,7 @@ type NetfilterLinkInfo struct {
 }
 
 type NetkitLinkInfo struct {
-	structs.HostLayout
+	_          structs.HostLayout
 	Type       LinkType
 	Id         LinkID
 	ProgId     uint32
@@ -1599,7 +1599,7 @@ type NetkitLinkInfo struct {
 }
 
 type PerfEventLinkInfo struct {
-	structs.HostLayout
+	_             structs.HostLayout
 	Type          LinkType
 	Id            LinkID
 	ProgId        uint32
@@ -1608,7 +1608,7 @@ type PerfEventLinkInfo struct {
 }
 
 type RawTracepointLinkInfo struct {
-	structs.HostLayout
+	_         structs.HostLayout
 	Type      LinkType
 	Id        LinkID
 	ProgId    uint32
@@ -1619,7 +1619,7 @@ type RawTracepointLinkInfo struct {
 }
 
 type TcxLinkInfo struct {
-	structs.HostLayout
+	_          structs.HostLayout
 	Type       LinkType
 	Id         LinkID
 	ProgId     uint32
@@ -1630,7 +1630,7 @@ type TcxLinkInfo struct {
 }
 
 type TracingLinkInfo struct {
-	structs.HostLayout
+	_           structs.HostLayout
 	Type        LinkType
 	Id          LinkID
 	ProgId      uint32
@@ -1642,7 +1642,7 @@ type TracingLinkInfo struct {
 }
 
 type XDPLinkInfo struct {
-	structs.HostLayout
+	_       structs.HostLayout
 	Type    LinkType
 	Id      LinkID
 	ProgId  uint32


Test patch:
diff --git a/btf/format_test.go b/btf/format_test.go
index 4bf21c0..78c1a21 100644
--- a/btf/format_test.go
+++ b/btf/format_test.go
@@ -42,7 +42,7 @@ func TestGoTypeDeclaration(t *testing.T) {
 					{Name: "enum", Type: &Enum{Values: []EnumValue{{"BAR", 1}}, Size: 2}, Offset: 0},
 				},
 			},
-			"type t struct { enum uint16; }",
+			"type t struct { _ structs.HostLayout; enum uint16; }",
 		},
 		{&Array{Nelems: 2, Type: &Int{Size: 1}}, "type t [2]uint8"},
 		{
@@ -53,7 +53,7 @@ func TestGoTypeDeclaration(t *testing.T) {
 					{Name: "b", Type: &Int{Size: 8}},
 				},
 			},
-			"type t struct { a uint32; _ [4]byte; }",
+			"type t struct { _ structs.HostLayout; a uint32; _ [4]byte; }",
 		},
 		{
 			&Struct{
@@ -64,7 +64,7 @@ func TestGoTypeDeclaration(t *testing.T) {
 					{Name: "foo", Type: &Int{Size: 8}, Offset: 8 * 8},
 				},
 			},
-			"type t struct { frob uint32; _ [4]byte; foo uint64; }",
+			"type t struct { _ structs.HostLayout; frob uint32; _ [4]byte; foo uint64; }",
 		},
 		{
 			&Struct{
@@ -75,7 +75,7 @@ func TestGoTypeDeclaration(t *testing.T) {
 					{Name: "frob", Type: &Int{Size: 4}, Offset: 8 * 8},
 				},
 			},
-			"type t struct { foo uint64; frob uint32; _ [4]byte; }",
+			"type t struct { _ structs.HostLayout; foo uint64; frob uint32; _ [4]byte; }",
 		},
 		{
 			&Struct{
@@ -86,7 +86,7 @@ func TestGoTypeDeclaration(t *testing.T) {
 					{Name: "frob", Type: &Int{Size: 4}, Offset: 4 * 8},
 				},
 			},
-			"type t struct { _ [4]byte /* unsupported bitfield */; frob uint32; }",
+			"type t struct { _ structs.HostLayout; _ [4]byte /* unsupported bitfield */; frob uint32; }",
 		},
 		{
 			&Struct{
@@ -105,7 +105,7 @@ func TestGoTypeDeclaration(t *testing.T) {
 					{Name: "frob", Type: &Int{Size: 4}, Offset: 4 * 8},
 				},
 			},
-			"type t struct { foo struct { bar uint32; }; frob uint32; }",
+			"type t struct { _ structs.HostLayout; foo struct { _ structs.HostLayout; bar uint32; }; frob uint32; }",
 		},
 		{
 			&Struct{
@@ -124,7 +124,7 @@ func TestGoTypeDeclaration(t *testing.T) {
 					},
 				},
 			},
-			"type t struct { foo uint32; _ [4]byte; }",
+			"type t struct { _ structs.HostLayout; foo uint32; _ [4]byte; }",
 		},
 		{
 			&Datasec{
@@ -135,7 +135,7 @@ func TestGoTypeDeclaration(t *testing.T) {
 					{&Var{Name: "e", Type: &Int{Size: 8}, Linkage: ExternVar}, 8, 8},
 				},
 			},
-			"type t struct { _ [4]byte; g uint32; _ [8]byte; }",
+			"type t struct { _ structs.HostLayout; _ [4]byte; g uint32; _ [8]byte; }",
 		},
 		{&Var{Type: &Int{Size: 4}}, "type t uint32"},
 	}
@@ -175,9 +175,9 @@ func TestGoTypeDeclarationNamed(t *testing.T) {
 		output string
 	}{
 		{e1, []Type{e1}, "type t uint32"},
-		{s1, []Type{e1, s1}, "type t struct { frob E1; }"},
-		{s2, []Type{e1}, "type t struct { frood struct { frob E1; }; }"},
-		{s2, []Type{e1, s1}, "type t struct { frood S1; }"},
+		{s1, []Type{e1, s1}, "type t struct { _ structs.HostLayout; frob E1; }"},
+		{s2, []Type{e1}, "type t struct { _ structs.HostLayout; frood struct { _ structs.HostLayout; frob E1; }; }"},
+		{s2, []Type{e1, s1}, "type t struct { _ structs.HostLayout; frood S1; }"},
 		{td, nil, "type t uint32"},
 		{td, []Type{td}, "type t uint32"},
 		{arr, []Type{td}, "type t [1]TD"},
diff --git a/cmd/bpf2go/test/test_bpfeb.go b/cmd/bpf2go/test/test_bpfeb.go
index a1d0e54..85885e8 100644
--- a/cmd/bpf2go/test/test_bpfeb.go
+++ b/cmd/bpf2go/test/test_bpfeb.go
@@ -8,24 +8,30 @@ import (
 	_ "embed"
 	"fmt"
 	"io"
+	"structs"
 
 	"github.com/cilium/ebpf"
 )
 
 type testBar struct {
+	_ structs.HostLayout
 	A uint64
 	B uint32
 	_ [4]byte
 }
 
 type testBarfoo struct {
+	_   structs.HostLayout
 	Bar int64
 	Baz bool
 	_   [3]byte
 	Boo testE
 }
 
-type testBaz struct{ A uint64 }
+type testBaz struct {
+	_ structs.HostLayout
+	A uint64
+}
 
 type testE uint32
 
@@ -35,6 +41,7 @@ const (
 )
 
 type testUbar struct {
+	_ structs.HostLayout
 	A uint32
 	_ [4]byte
 }
diff --git a/cmd/bpf2go/test/test_bpfel.go b/cmd/bpf2go/test/test_bpfel.go
index 169b88d..5034af1 100644
--- a/cmd/bpf2go/test/test_bpfel.go
+++ b/cmd/bpf2go/test/test_bpfel.go
@@ -8,24 +8,30 @@ import (
 	_ "embed"
 	"fmt"
 	"io"
+	"structs"
 
 	"github.com/cilium/ebpf"
 )
 
 type testBar struct {
+	_ structs.HostLayout
 	A uint64
 	B uint32
 	_ [4]byte
 }
 
 type testBarfoo struct {
+	_   structs.HostLayout
 	Bar int64
 	Baz bool
 	_   [3]byte
 	Boo testE
 }
 
-type testBaz struct{ A uint64 }
+type testBaz struct {
+	_ structs.HostLayout
+	A uint64
+}
 
 type testE uint32
 
@@ -35,6 +41,7 @@ const (
 )
 
 type testUbar struct {
+	_ structs.HostLayout
 	A uint32
 	_ [4]byte
 }