@@ -12,7 +12,6 @@ import (
12
12
"math"
13
13
"os"
14
14
"reflect"
15
- "sync"
16
15
17
16
"github.com/cilium/ebpf/internal"
18
17
"github.com/cilium/ebpf/internal/sys"
@@ -31,128 +30,6 @@ var (
31
30
// ID represents the unique ID of a BTF object.
32
31
type ID = sys.BTFID
33
32
34
- // immutableTypes is a set of types which musn't be changed.
35
- type immutableTypes struct {
36
- // All types contained by the spec, not including types from the base in
37
- // case the spec was parsed from split BTF.
38
- types []Type
39
-
40
- // Type IDs indexed by type.
41
- typeIDs map [Type ]TypeID
42
-
43
- // The ID of the first type in types.
44
- firstTypeID TypeID
45
-
46
- // Types indexed by essential name.
47
- // Includes all struct flavors and types with the same name.
48
- namedTypes map [essentialName ][]TypeID
49
-
50
- // Byte order of the types. This affects things like struct member order
51
- // when using bitfields.
52
- byteOrder binary.ByteOrder
53
- }
54
-
55
- func (s * immutableTypes ) typeByID (id TypeID ) (Type , bool ) {
56
- if id < s .firstTypeID {
57
- return nil , false
58
- }
59
-
60
- index := int (id - s .firstTypeID )
61
- if index >= len (s .types ) {
62
- return nil , false
63
- }
64
-
65
- return s .types [index ], true
66
- }
67
-
68
- // mutableTypes is a set of types which may be changed.
69
- type mutableTypes struct {
70
- imm immutableTypes
71
- mu sync.RWMutex // protects copies below
72
- copies map [Type ]Type // map[orig]copy
73
- copiedTypeIDs map [Type ]TypeID // map[copy]origID
74
- }
75
-
76
- // add a type to the set of mutable types.
77
- //
78
- // Copies type and all of its children once. Repeated calls with the same type
79
- // do not copy again.
80
- func (mt * mutableTypes ) add (typ Type , typeIDs map [Type ]TypeID ) Type {
81
- mt .mu .RLock ()
82
- cpy , ok := mt .copies [typ ]
83
- mt .mu .RUnlock ()
84
-
85
- if ok {
86
- // Fast path: the type has been copied before.
87
- return cpy
88
- }
89
-
90
- // modifyGraphPreorder copies the type graph node by node, so we can't drop
91
- // the lock in between.
92
- mt .mu .Lock ()
93
- defer mt .mu .Unlock ()
94
-
95
- return copyType (typ , typeIDs , mt .copies , mt .copiedTypeIDs )
96
- }
97
-
98
- // copy a set of mutable types.
99
- func (mt * mutableTypes ) copy () * mutableTypes {
100
- if mt == nil {
101
- return nil
102
- }
103
-
104
- // Prevent concurrent modification of mt.copiedTypeIDs.
105
- mt .mu .RLock ()
106
- defer mt .mu .RUnlock ()
107
-
108
- mtCopy := & mutableTypes {
109
- mt .imm ,
110
- sync.RWMutex {},
111
- make (map [Type ]Type , len (mt .copies )),
112
- make (map [Type ]TypeID , len (mt .copiedTypeIDs )),
113
- }
114
-
115
- copiesOfCopies := make (map [Type ]Type , len (mt .copies ))
116
- for orig , copy := range mt .copies {
117
- // NB: We make a copy of copy, not orig, so that changes to mutable types
118
- // are preserved.
119
- copyOfCopy := copyType (copy , mt .copiedTypeIDs , copiesOfCopies , mtCopy .copiedTypeIDs )
120
- mtCopy .copies [orig ] = copyOfCopy
121
- }
122
-
123
- return mtCopy
124
- }
125
-
126
- func (mt * mutableTypes ) typeID (typ Type ) (TypeID , error ) {
127
- if _ , ok := typ .(* Void ); ok {
128
- // Equality is weird for void, since it is a zero sized type.
129
- return 0 , nil
130
- }
131
-
132
- mt .mu .RLock ()
133
- defer mt .mu .RUnlock ()
134
-
135
- id , ok := mt .copiedTypeIDs [typ ]
136
- if ! ok {
137
- return 0 , fmt .Errorf ("no ID for type %s: %w" , typ , ErrNotFound )
138
- }
139
-
140
- return id , nil
141
- }
142
-
143
- func (mt * mutableTypes ) typeByID (id TypeID ) (Type , bool ) {
144
- immT , ok := mt .imm .typeByID (id )
145
- if ! ok {
146
- return nil , false
147
- }
148
-
149
- return mt .add (immT , mt .imm .typeIDs ), true
150
- }
151
-
152
- func (mt * mutableTypes ) typeIDsByName (name essentialName ) []TypeID {
153
- return mt .imm .namedTypes [name ]
154
- }
155
-
156
33
type elfData struct {
157
34
sectionSizes map [string ]uint32
158
35
symbolOffsets map [elfSymbol ]uint32
@@ -167,10 +44,7 @@ type elfSymbol struct {
167
44
// Spec allows querying a set of Types and loading the set into the
168
45
// kernel.
169
46
type Spec struct {
170
- * mutableTypes
171
-
172
- // String table from ELF.
173
- strings * stringTable
47
+ * decoder
174
48
175
49
// Additional data from ELF, may be nil.
176
50
elf * elfData
@@ -315,22 +189,14 @@ func loadSpecFromELF(file *internal.SafeELFFile) (*Spec, error) {
315
189
316
190
func loadRawSpec (btf io.ReaderAt , bo binary.ByteOrder , base * Spec ) (* Spec , error ) {
317
191
var (
192
+ baseDecoder * decoder
318
193
baseStrings * stringTable
319
- firstTypeID TypeID
320
194
err error
321
195
)
322
196
323
197
if base != nil {
324
- if base .imm .firstTypeID != 0 {
325
- return nil , fmt .Errorf ("can't use split BTF as base" )
326
- }
327
-
198
+ baseDecoder = base .decoder
328
199
baseStrings = base .strings
329
-
330
- firstTypeID , err = base .nextTypeID ()
331
- if err != nil {
332
- return nil , err
333
- }
334
200
}
335
201
336
202
buf := internal .NewBufferedSectionReader (btf , 0 , math .MaxInt64 )
@@ -351,55 +217,12 @@ func loadRawSpec(btf io.ReaderAt, bo binary.ByteOrder, base *Spec) (*Spec, error
351
217
return nil , fmt .Errorf ("read type section: %w" , err )
352
218
}
353
219
354
- types , err := readAndInflateTypes (rawTypes , bo , header . TypeLen , rawStrings , base )
220
+ decoder , err := newDecoder (rawTypes , bo , rawStrings , baseDecoder )
355
221
if err != nil {
356
222
return nil , err
357
223
}
358
224
359
- typeIDs , typesByName := indexTypes (types , firstTypeID )
360
-
361
- return & Spec {
362
- & mutableTypes {
363
- immutableTypes {
364
- types ,
365
- typeIDs ,
366
- firstTypeID ,
367
- typesByName ,
368
- bo ,
369
- },
370
- sync.RWMutex {},
371
- make (map [Type ]Type ),
372
- make (map [Type ]TypeID ),
373
- },
374
- rawStrings ,
375
- nil ,
376
- }, nil
377
- }
378
-
379
- func indexTypes (types []Type , firstTypeID TypeID ) (map [Type ]TypeID , map [essentialName ][]TypeID ) {
380
- namedTypes := 0
381
- for _ , typ := range types {
382
- if typ .TypeName () != "" {
383
- // Do a pre-pass to figure out how big types by name has to be.
384
- // Most types have unique names, so it's OK to ignore essentialName
385
- // here.
386
- namedTypes ++
387
- }
388
- }
389
-
390
- typeIDs := make (map [Type ]TypeID , len (types ))
391
- typesByName := make (map [essentialName ][]TypeID , namedTypes )
392
-
393
- for i , typ := range types {
394
- id := firstTypeID + TypeID (i )
395
- typeIDs [typ ] = id
396
-
397
- if name := newEssentialName (typ .TypeName ()); name != "" {
398
- typesByName [name ] = append (typesByName [name ], id )
399
- }
400
- }
401
-
402
- return typeIDs , typesByName
225
+ return & Spec {decoder , nil }, nil
403
226
}
404
227
405
228
func guessRawBTFByteOrder (r io.ReaderAt ) binary.ByteOrder {
@@ -525,8 +348,7 @@ func (s *Spec) Copy() *Spec {
525
348
}
526
349
527
350
cpy := & Spec {
528
- s .copy (),
529
- s .strings ,
351
+ s .decoder .Copy (),
530
352
nil ,
531
353
}
532
354
@@ -541,24 +363,14 @@ func (s *Spec) Copy() *Spec {
541
363
return cpy
542
364
}
543
365
544
- // nextTypeID returns the next unallocated type ID or an error if there are no
545
- // more type IDs.
546
- func (s * Spec ) nextTypeID () (TypeID , error ) {
547
- id := s .imm .firstTypeID + TypeID (len (s .imm .types ))
548
- if id < s .imm .firstTypeID {
549
- return 0 , fmt .Errorf ("no more type IDs" )
550
- }
551
- return id , nil
552
- }
553
-
554
366
// TypeByID returns the BTF Type with the given type ID.
555
367
//
556
368
// Returns an error wrapping ErrNotFound if a Type with the given ID
557
369
// does not exist in the Spec.
558
370
func (s * Spec ) TypeByID (id TypeID ) (Type , error ) {
559
- typ , ok := s .typeByID (id )
560
- if ! ok {
561
- return nil , fmt .Errorf ("look up type with ID %d (first ID is %d) : %w" , id , s . imm . firstTypeID , ErrNotFound )
371
+ typ , err := s .decoder . TypeByID (id )
372
+ if err != nil {
373
+ return nil , fmt .Errorf ("inflate type: %w" , err )
562
374
}
563
375
564
376
if s .elf == nil {
@@ -576,7 +388,7 @@ func (s *Spec) TypeByID(id TypeID) (Type, error) {
576
388
//
577
389
// Returns an error wrapping [ErrNotFound] if the type isn't part of the Spec.
578
390
func (s * Spec ) TypeID (typ Type ) (TypeID , error ) {
579
- return s .typeID (typ )
391
+ return s .decoder . TypeID (typ )
580
392
}
581
393
582
394
// AnyTypesByName returns a list of BTF Types with the given name.
@@ -587,7 +399,7 @@ func (s *Spec) TypeID(typ Type) (TypeID, error) {
587
399
//
588
400
// Returns an error wrapping ErrNotFound if no matching Type exists in the Spec.
589
401
func (s * Spec ) AnyTypesByName (name string ) ([]Type , error ) {
590
- typeIDs := s .typeIDsByName (newEssentialName (name ))
402
+ typeIDs := s .TypeIDsByName (newEssentialName (name ))
591
403
if len (typeIDs ) == 0 {
592
404
return nil , fmt .Errorf ("type name %s: %w" , name , ErrNotFound )
593
405
}
@@ -698,7 +510,7 @@ func LoadSplitSpecFromReader(r io.ReaderAt, base *Spec) (*Spec, error) {
698
510
// All iterates over all types.
699
511
func (s * Spec ) All () iter.Seq2 [Type , error ] {
700
512
return func (yield func (Type , error ) bool ) {
701
- for id := s .imm . firstTypeID ; ; id ++ {
513
+ for id := s .firstTypeID ; ; id ++ {
702
514
typ , err := s .TypeByID (id )
703
515
if errors .Is (err , ErrNotFound ) {
704
516
return
0 commit comments