@@ -532,6 +532,64 @@ func (pi *ProgramInfo) KsymAddrs() ([]uintptr, bool) {
532
532
return ptrs , pi .numKsymInfos > 0
533
533
}
534
534
535
+ // ProgramFunctionInfo describes a function of an insn in a program.
536
+ type ProgramFunctionInfo struct {
537
+ // InstructionOffset is the offset of the insn in the program's instructions.
538
+ InstructionOffset uint64
539
+
540
+ // FuncInfo is the BTF function information.
541
+ FuncInfo * btf.Func
542
+ }
543
+
544
+ // FuncInfos returns the function information of bpf programs, including
545
+ // subprograms, of current bpf program.
546
+ //
547
+ // Available from 5.0.
548
+ func (pi * ProgramInfo ) FuncInfos () ([]ProgramFunctionInfo , error ) {
549
+ if pi .numFuncInfos == 0 {
550
+ return nil , nil
551
+ }
552
+
553
+ btfID , ok := pi .BTFID ()
554
+ if ! ok {
555
+ return nil , nil
556
+ }
557
+
558
+ handle , err := btf .NewHandleFromID (btfID )
559
+ if err != nil {
560
+ return nil , fmt .Errorf ("unable to get BTF handle: %w" , err )
561
+ }
562
+ defer handle .Close ()
563
+
564
+ btfSpec , err := handle .Spec (nil )
565
+ if err != nil {
566
+ return nil , fmt .Errorf ("unable to get BTF spec: %w" , err )
567
+ }
568
+
569
+ funcs := make ([]ProgramFunctionInfo , 0 , pi .numFuncInfos )
570
+
571
+ ptr := (* sys .FuncInfo )(unsafe .Pointer (& pi .funcInfos [0 ]))
572
+ funcInfos := unsafe .Slice (ptr , int (pi .numFuncInfos ))
573
+ for _ , funcInfo := range funcInfos {
574
+ btfInfo , err := btfSpec .TypeByID (sys .TypeID (funcInfo .TypeId ))
575
+ if err != nil {
576
+ return nil , fmt .Errorf ("unable to get BTF type: %w" , err )
577
+ }
578
+
579
+ funcBtfInfo , ok := btfInfo .(* btf.Func )
580
+ if ! ok {
581
+ return nil , fmt .Errorf ("unexpected BTF type: %T, expected %T" , btfInfo , funcBtfInfo )
582
+ }
583
+
584
+ funcs = append (funcs , ProgramFunctionInfo {
585
+ InstructionOffset : uint64 (funcInfo .InsnOff ),
586
+ FuncInfo : funcBtfInfo ,
587
+ })
588
+ }
589
+
590
+ return funcs , nil
591
+ }
592
+
535
593
func scanFdInfo (fd * sys.FD , fields map [string ]interface {}) error {
536
594
fh , err := os .Open (fmt .Sprintf ("/proc/self/fdinfo/%d" , fd .Int ()))
537
595
if err != nil {
0 commit comments