1
1
package btf
2
2
3
3
import (
4
- "bufio"
5
4
"debug/elf"
6
- "encoding/binary"
7
5
"errors"
8
6
"fmt"
9
7
"io"
@@ -69,11 +67,12 @@ func LoadSpec(file string) (*Spec, error) {
69
67
func LoadSpecFromReader (rd io.ReaderAt ) (* Spec , error ) {
70
68
file , err := internal .NewSafeELFFile (rd )
71
69
if err != nil {
72
- if bo := guessRawBTFByteOrder (rd ); bo != nil {
73
- return loadRawSpec (io .NewSectionReader (rd , 0 , math .MaxInt64 ), bo , nil )
70
+ raw , err := io .ReadAll (io .NewSectionReader (rd , 0 , math .MaxInt64 ))
71
+ if err != nil {
72
+ return nil , fmt .Errorf ("read raw BTF: %w" , err )
74
73
}
75
74
76
- return nil , err
75
+ return loadRawSpec ( raw , nil )
77
76
}
78
77
79
78
return loadSpecFromELF (file )
@@ -170,15 +169,20 @@ func loadSpecFromELF(file *internal.SafeELFFile) (*Spec, error) {
170
169
return nil , err
171
170
}
172
171
173
- if btfSection .ReaderAt == nil {
174
- return nil , fmt .Errorf ("compressed BTF is not supported" )
172
+ rawBTF , err := btfSection .Data ()
173
+ if err != nil {
174
+ return nil , fmt .Errorf ("reading .BTF section: %w" , err )
175
175
}
176
176
177
- spec , err := loadRawSpec (btfSection . ReaderAt , file . ByteOrder , nil )
177
+ spec , err := loadRawSpec (rawBTF , nil )
178
178
if err != nil {
179
179
return nil , err
180
180
}
181
181
182
+ if spec .decoder .byteOrder != file .ByteOrder {
183
+ return nil , fmt .Errorf ("BTF byte order %s does not match ELF byte order %s" , spec .decoder .byteOrder , file .ByteOrder )
184
+ }
185
+
182
186
spec .elf = & elfData {
183
187
sectionSizes ,
184
188
offsets ,
@@ -188,7 +192,7 @@ func loadSpecFromELF(file *internal.SafeELFFile) (*Spec, error) {
188
192
return spec , nil
189
193
}
190
194
191
- func loadRawSpec (btf io. ReaderAt , bo binary. ByteOrder , base * Spec ) (* Spec , error ) {
195
+ func loadRawSpec (btf [] byte , base * Spec ) (* Spec , error ) {
192
196
var (
193
197
baseDecoder * decoder
194
198
baseStrings * stringTable
@@ -200,47 +204,39 @@ func loadRawSpec(btf io.ReaderAt, bo binary.ByteOrder, base *Spec) (*Spec, error
200
204
baseStrings = base .strings
201
205
}
202
206
203
- buf := internal .NewBufferedSectionReader (btf , 0 , math .MaxInt64 )
204
- header , err := parseBTFHeader (buf , bo )
207
+ header , bo , err := parseBTFHeader (btf )
205
208
if err != nil {
206
209
return nil , fmt .Errorf ("parsing .BTF header: %v" , err )
207
210
}
208
211
209
- stringsSection := io .NewSectionReader (btf , header .stringStart (), int64 (header .StringLen ))
210
- rawStrings , err := readStringTable (stringsSection , baseStrings )
212
+ if header .HdrLen > uint32 (len (btf )) {
213
+ return nil , fmt .Errorf ("BTF header length is out of bounds" )
214
+ }
215
+ btf = btf [header .HdrLen :]
216
+
217
+ if int (header .StringOff + header .StringLen ) > len (btf ) {
218
+ return nil , fmt .Errorf ("string table is out of bounds" )
219
+ }
220
+ stringsSection := btf [header .StringOff : header .StringOff + header .StringLen ]
221
+
222
+ rawStrings , err := newStringTable (stringsSection , baseStrings )
211
223
if err != nil {
212
224
return nil , fmt .Errorf ("read string section: %w" , err )
213
225
}
214
226
215
- typesSection := io .NewSectionReader (btf , header .typeStart (), int64 (header .TypeLen ))
216
- rawTypes := make ([]byte , header .TypeLen )
217
- if _ , err := io .ReadFull (typesSection , rawTypes ); err != nil {
218
- return nil , fmt .Errorf ("read type section: %w" , err )
227
+ if int (header .TypeOff + header .TypeLen ) > len (btf ) {
228
+ return nil , fmt .Errorf ("types section is out of bounds" )
219
229
}
230
+ typesSection := btf [header .TypeOff : header .TypeOff + header .TypeLen ]
220
231
221
- decoder , err := newDecoder (rawTypes , bo , rawStrings , baseDecoder )
232
+ decoder , err := newDecoder (typesSection , bo , rawStrings , baseDecoder )
222
233
if err != nil {
223
234
return nil , err
224
235
}
225
236
226
237
return & Spec {decoder , nil }, nil
227
238
}
228
239
229
- func guessRawBTFByteOrder (r io.ReaderAt ) binary.ByteOrder {
230
- buf := new (bufio.Reader )
231
- for _ , bo := range []binary.ByteOrder {
232
- binary .LittleEndian ,
233
- binary .BigEndian ,
234
- } {
235
- buf .Reset (io .NewSectionReader (r , 0 , math .MaxInt64 ))
236
- if _ , err := parseBTFHeader (buf , bo ); err == nil {
237
- return bo
238
- }
239
- }
240
-
241
- return nil
242
- }
243
-
244
240
// fixupDatasec attempts to patch up missing info in Datasecs and its members by
245
241
// supplementing them with information from the ELF headers and symbol table.
246
242
func (elf * elfData ) fixupDatasec (typ Type ) error {
@@ -519,7 +515,12 @@ func LoadSplitSpec(file string, base *Spec) (*Spec, error) {
519
515
// Types from base are used to resolve references in the split BTF.
520
516
// The returned Spec only contains types from the split BTF, not from the base.
521
517
func LoadSplitSpecFromReader (r io.ReaderAt , base * Spec ) (* Spec , error ) {
522
- return loadRawSpec (r , internal .NativeEndian , base )
518
+ raw , err := io .ReadAll (io .NewSectionReader (r , 0 , math .MaxInt64 ))
519
+ if err != nil {
520
+ return nil , fmt .Errorf ("read raw BTF: %w" , err )
521
+ }
522
+
523
+ return loadRawSpec (raw , base )
523
524
}
524
525
525
526
// All iterates over all types.
0 commit comments