@@ -179,6 +179,40 @@ type programStats struct {
179
179
recursionMisses uint64
180
180
}
181
181
182
+ // programJitedInfo holds information about JITed info of a program.
183
+ type programJitedInfo struct {
184
+ // ksyms holds the ksym addresses of the BPF program, including those of its
185
+ // subprograms.
186
+ //
187
+ // Available from 4.18.
188
+ ksyms []uintptr
189
+ numKsyms uint32
190
+
191
+ // insns holds the JITed machine native instructions of the program,
192
+ // including those of its subprograms.
193
+ //
194
+ // Available from 4.13.
195
+ insns []byte
196
+ numInsns uint32
197
+
198
+ // lineInfos holds the JITed line infos, which are kernel addresses.
199
+ //
200
+ // Available from 5.0.
201
+ lineInfos []uint64
202
+ numLineInfos uint32
203
+
204
+ // lineInfoRecSize is the size of a single line info record.
205
+ //
206
+ // Available from 5.0.
207
+ lineInfoRecSize uint32
208
+
209
+ // funcLens holds the insns length of each function.
210
+ //
211
+ // Available from 4.18.
212
+ funcLens []uint32
213
+ numFuncLens uint32
214
+ }
215
+
182
216
// ProgramInfo describes a program.
183
217
type ProgramInfo struct {
184
218
Type ProgramType
@@ -199,12 +233,12 @@ type ProgramInfo struct {
199
233
jitedSize uint32
200
234
verifiedInstructions uint32
201
235
236
+ jitedInfo programJitedInfo
237
+
202
238
lineInfos []byte
203
239
numLineInfos uint32
204
240
funcInfos []byte
205
241
numFuncInfos uint32
206
- ksymInfos []uint64
207
- numKsymInfos uint32
208
242
}
209
243
210
244
func newProgramInfoFromFd (fd * sys.FD ) (* ProgramInfo , error ) {
@@ -282,11 +316,37 @@ func newProgramInfoFromFd(fd *sys.FD) (*ProgramInfo, error) {
282
316
makeSecondCall = true
283
317
}
284
318
319
+ pi .jitedInfo .lineInfoRecSize = info .JitedLineInfoRecSize
320
+ if info .JitedProgLen > 0 {
321
+ pi .jitedInfo .numInsns = info .JitedProgLen
322
+ pi .jitedInfo .insns = make ([]byte , info .JitedProgLen )
323
+ info2 .JitedProgLen = info .JitedProgLen
324
+ info2 .JitedProgInsns = sys .NewSlicePointer (pi .jitedInfo .insns )
325
+ makeSecondCall = true
326
+ }
327
+
328
+ if info .NrJitedFuncLens > 0 {
329
+ pi .jitedInfo .numFuncLens = info .NrJitedFuncLens
330
+ pi .jitedInfo .funcLens = make ([]uint32 , info .NrJitedFuncLens )
331
+ info2 .NrJitedFuncLens = info .NrJitedFuncLens
332
+ info2 .JitedFuncLens = sys .NewSlicePointer (pi .jitedInfo .funcLens )
333
+ makeSecondCall = true
334
+ }
335
+
336
+ if info .NrJitedLineInfo > 0 {
337
+ pi .jitedInfo .numLineInfos = info .NrJitedLineInfo
338
+ pi .jitedInfo .lineInfos = make ([]uint64 , info .NrJitedLineInfo )
339
+ info2 .NrJitedLineInfo = info .NrJitedLineInfo
340
+ info2 .JitedLineInfo = sys .NewSlicePointer (pi .jitedInfo .lineInfos )
341
+ info2 .JitedLineInfoRecSize = info .JitedLineInfoRecSize
342
+ makeSecondCall = true
343
+ }
344
+
285
345
if info .NrJitedKsyms > 0 {
286
- pi .ksymInfos = make ([]uint64 , info .NrJitedKsyms )
287
- info2 .JitedKsyms = sys .NewSlicePointer (pi .ksymInfos )
346
+ pi .jitedInfo .numKsyms = info .NrJitedKsyms
347
+ pi .jitedInfo .ksyms = make ([]uintptr , info .NrJitedKsyms )
348
+ info2 .JitedKsyms = sys .NewSlicePointer (pi .jitedInfo .ksyms )
288
349
info2 .NrJitedKsyms = info .NrJitedKsyms
289
- pi .numKsymInfos = info .NrJitedKsyms
290
350
makeSecondCall = true
291
351
}
292
352
@@ -380,6 +440,52 @@ func (pi *ProgramInfo) RecursionMisses() (uint64, bool) {
380
440
return 0 , false
381
441
}
382
442
443
+ // btfSpec returns the BTF spec associated with the program.
444
+ func (pi * ProgramInfo ) btfSpec () (* btf.Spec , error ) {
445
+ id , ok := pi .BTFID ()
446
+ if ! ok {
447
+ return nil , fmt .Errorf ("program created without BTF or unsupported kernel: %w" , ErrNotSupported )
448
+ }
449
+
450
+ h , err := btf .NewHandleFromID (id )
451
+ if err != nil {
452
+ return nil , fmt .Errorf ("get BTF handle: %w" , err )
453
+ }
454
+ defer h .Close ()
455
+
456
+ spec , err := h .Spec (nil )
457
+ if err != nil {
458
+ return nil , fmt .Errorf ("get BTF spec: %w" , err )
459
+ }
460
+
461
+ return spec , nil
462
+ }
463
+
464
+ // LineInfos returns the BTF line information of the program.
465
+ //
466
+ // Available from 5.0.
467
+ //
468
+ // Requires CAP_SYS_ADMIN or equivalent for reading BTF information. Returns
469
+ // ErrNotSupported if the program was created without BTF or if the kernel
470
+ // doesn't support the field.
471
+ func (pi * ProgramInfo ) LineInfos () (btf.LineOffsets , error ) {
472
+ if len (pi .lineInfos ) == 0 {
473
+ return nil , fmt .Errorf ("insufficient permissions or unsupported kernel: %w" , ErrNotSupported )
474
+ }
475
+
476
+ spec , err := pi .btfSpec ()
477
+ if err != nil {
478
+ return nil , err
479
+ }
480
+
481
+ return btf .LoadLineInfos (
482
+ bytes .NewReader (pi .lineInfos ),
483
+ internal .NativeEndian ,
484
+ pi .numLineInfos ,
485
+ spec ,
486
+ )
487
+ }
488
+
383
489
// Instructions returns the 'xlated' instruction stream of the program
384
490
// after it has been verified and rewritten by the kernel. These instructions
385
491
// cannot be loaded back into the kernel as-is, this is mainly used for
@@ -524,11 +630,34 @@ func (pi *ProgramInfo) VerifiedInstructions() (uint32, bool) {
524
630
//
525
631
// The bool return value indicates whether this optional field is available.
526
632
func (pi * ProgramInfo ) KsymAddrs () ([]uintptr , bool ) {
527
- addrs := make ([]uintptr , 0 , len (pi .ksymInfos ))
528
- for _ , addr := range pi .ksymInfos {
529
- addrs = append (addrs , uintptr (addr ))
530
- }
531
- return addrs , pi .numKsymInfos > 0
633
+ return pi .jitedInfo .ksyms , len (pi .jitedInfo .ksyms ) > 0
634
+ }
635
+
636
+ // JitedInsns returns the JITed machine native instructions of the program.
637
+ //
638
+ // Available from 4.13.
639
+ //
640
+ // The bool return value indicates whether this optional field is available.
641
+ func (pi * ProgramInfo ) JitedInsns () ([]byte , bool ) {
642
+ return pi .jitedInfo .insns , len (pi .jitedInfo .insns ) > 0
643
+ }
644
+
645
+ // JitedLineInfos returns the JITed line infos of the program.
646
+ //
647
+ // Available from 5.0.
648
+ //
649
+ // The bool return value indicates whether this optional field is available.
650
+ func (pi * ProgramInfo ) JitedLineInfos () ([]uint64 , bool ) {
651
+ return pi .jitedInfo .lineInfos , len (pi .jitedInfo .lineInfos ) > 0
652
+ }
653
+
654
+ // JitedFuncLens returns the insns length of each function in the JITed program.
655
+ //
656
+ // Available from 4.18.
657
+ //
658
+ // The bool return value indicates whether this optional field is available.
659
+ func (pi * ProgramInfo ) JitedFuncLens () ([]uint32 , bool ) {
660
+ return pi .jitedInfo .funcLens , len (pi .jitedInfo .funcLens ) > 0
532
661
}
533
662
534
663
// FuncInfos returns the offset and function information of all (sub)programs in
@@ -540,20 +669,13 @@ func (pi *ProgramInfo) KsymAddrs() ([]uintptr, bool) {
540
669
// ErrNotSupported if the program was created without BTF or if the kernel
541
670
// doesn't support the field.
542
671
func (pi * ProgramInfo ) FuncInfos () (btf.FuncOffsets , error ) {
543
- id , ok := pi .BTFID ()
544
- if pi .numFuncInfos == 0 || ! ok {
545
- return nil , fmt .Errorf ("program created without BTF or unsupported kernel: %w" , ErrNotSupported )
546
- }
547
-
548
- h , err := btf .NewHandleFromID (id )
549
- if err != nil {
550
- return nil , fmt .Errorf ("get BTF handle: %w" , err )
672
+ if len (pi .funcInfos ) == 0 {
673
+ return nil , fmt .Errorf ("insufficient permissions or unsupported kernel: %w" , ErrNotSupported )
551
674
}
552
- defer h .Close ()
553
675
554
- spec , err := h . Spec ( nil )
676
+ spec , err := pi . btfSpec ( )
555
677
if err != nil {
556
- return nil , fmt . Errorf ( "get BTF spec: %w" , err )
678
+ return nil , err
557
679
}
558
680
559
681
return btf .LoadFuncInfos (
0 commit comments