Skip to content

Commit e55144e

Browse files
dylandreimerinkti-mo
authored andcommitted
btf: Add BTF layout header parsing
In kernel 7.1 the BTF header for BTF v1 was extended to now include two optional fields. These fields hold a offset and length for BTF layout information, a new BTF feature. When we encountered a BTF header with these fields set to non-zero values, we would fail to parse the header and thus fail to parse the BTF data altogether. This commit adds support for parsing the new header fields, and ignores them for now. Support for the BTF layout feature will be added in the future, but this change ensures the latest version of the library stays compatible with the latest kernels. Signed-off-by: Dylan Reimerink <dylan.reimerink@isovalent.com>
1 parent d37ad9c commit e55144e

2 files changed

Lines changed: 25 additions & 10 deletions

File tree

btf/btf.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ func loadRawSpec(btf []byte, base *Spec) (*Spec, error) {
204204
baseStrings = base.strings
205205
}
206206

207-
header, bo, err := parseBTFHeader(btf)
207+
header, _, bo, err := parseBTFHeader(btf)
208208
if err != nil {
209209
return nil, fmt.Errorf("parsing .BTF header: %v", err)
210210
}

btf/btf_types.go

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,19 @@ type btfHeader struct {
8484
StringLen uint32
8585
}
8686

87+
type btfLayout struct {
88+
Off uint32
89+
Len uint32
90+
}
91+
8792
// parseBTFHeader parses the header of the .BTF section.
88-
func parseBTFHeader(buf []byte) (*btfHeader, binary.ByteOrder, error) {
93+
func parseBTFHeader(buf []byte) (*btfHeader, *btfLayout, binary.ByteOrder, error) {
8994
var header btfHeader
9095
var bo binary.ByteOrder
9196
for _, order := range []binary.ByteOrder{binary.LittleEndian, binary.BigEndian} {
9297
n, err := binary.Decode(buf, order, &header)
9398
if err != nil {
94-
return nil, nil, fmt.Errorf("read header: %v", err)
99+
return nil, nil, nil, fmt.Errorf("read header: %v", err)
95100
}
96101

97102
if header.Magic != btfMagic {
@@ -104,33 +109,43 @@ func parseBTFHeader(buf []byte) (*btfHeader, binary.ByteOrder, error) {
104109
}
105110

106111
if bo == nil {
107-
return nil, nil, fmt.Errorf("no valid BTF header")
112+
return nil, nil, nil, fmt.Errorf("no valid BTF header")
108113
}
109114

110115
if header.Version != 1 {
111-
return nil, nil, fmt.Errorf("unexpected version %v", header.Version)
116+
return nil, nil, nil, fmt.Errorf("unexpected version %v", header.Version)
112117
}
113118

114119
if header.Flags != 0 {
115-
return nil, nil, fmt.Errorf("unsupported flags %v", header.Flags)
120+
return nil, nil, nil, fmt.Errorf("unsupported flags %v", header.Flags)
116121
}
117122

118123
remainder := int64(header.HdrLen) - int64(binary.Size(&header))
119124
if remainder < 0 {
120-
return nil, nil, errors.New("header length shorter than btfHeader size")
125+
return nil, nil, nil, errors.New("header length shorter than minimum BTF header size")
121126
}
122127

123128
if len(buf) < int(remainder) {
124-
return nil, nil, errors.New("header length exceeds available data")
129+
return nil, nil, nil, errors.New("header length exceeds available data")
130+
}
131+
132+
var layout btfLayout
133+
if remainder >= int64(binary.Size(&btfLayout{})) {
134+
n, err := binary.Decode(buf, bo, &layout)
135+
if err != nil {
136+
return nil, nil, nil, fmt.Errorf("read layout offset and length: %v", err)
137+
}
138+
buf = buf[n:]
139+
remainder -= int64(n)
125140
}
126141

127142
for _, b := range buf[:remainder] {
128143
if b != 0 {
129-
return nil, nil, errors.New("header contains non-zero trailer")
144+
return nil, nil, nil, errors.New("header contains non-zero trailer")
130145
}
131146
}
132147

133-
return &header, bo, nil
148+
return &header, &layout, bo, nil
134149
}
135150

136151
// btfType is equivalent to struct btf_type in Documentation/bpf/btf.rst.

0 commit comments

Comments
 (0)