Skip to content

Commit 56324bb

Browse files
committed
info: expose bpf_prog_info fields to ProgramInfo
Exposes additional metadata fields from `bpf_prog_info` to `ProgramInfo`: - jited_prog_len - xlated_prog_len - load_time - verified_insns Signed-off-by: tyrone-wu <wudevelops@gmail.com>
1 parent 5976561 commit 56324bb

2 files changed

Lines changed: 90 additions & 4 deletions

File tree

info.go

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,12 @@ type ProgramInfo struct {
116116
haveCreatedByUID bool
117117
btf btf.ID
118118
stats *programStats
119+
loadTime time.Duration
119120

120-
maps []MapID
121-
insns []byte
121+
maps []MapID
122+
insns []byte
123+
jitedSize uint32
124+
verifiedInstructions uint32
122125

123126
lineInfos []byte
124127
numLineInfos uint32
@@ -147,6 +150,9 @@ func newProgramInfoFromFd(fd *sys.FD) (*ProgramInfo, error) {
147150
runCount: info.RunCnt,
148151
recursionMisses: info.RecursionMisses,
149152
},
153+
jitedSize: info.JitedProgLen,
154+
loadTime: time.Duration(info.LoadTime),
155+
verifiedInstructions: info.VerifiedInsns,
150156
}
151157

152158
// Start with a clean struct for the second call, otherwise we may get EFAULT.
@@ -374,6 +380,28 @@ func (pi *ProgramInfo) Instructions() (asm.Instructions, error) {
374380
return insns, nil
375381
}
376382

383+
// JitedSize returns the size of the program's JIT-compiled machine code in bytes, which is the actual code executed on the host's CPU.
384+
//
385+
// Available from 4.13. Reading this metadata requires CAP_SYS_ADMIN or equivalent.
386+
func (pi *ProgramInfo) JitedSize() (uint32, error) {
387+
var err error
388+
if pi.jitedSize == 0 {
389+
err = fmt.Errorf("insufficient permissions or unsupported kernel: %w", ErrNotSupported)
390+
}
391+
return pi.jitedSize, err
392+
}
393+
394+
// TranslatedSize returns the size of the program's translated instructions in bytes, after it has been verified and rewritten by the kernel.
395+
//
396+
// Available from 4.13. Reading this metadata requires CAP_SYS_ADMIN or equivalent.
397+
func (pi *ProgramInfo) TranslatedSize() (int, error) {
398+
var err error
399+
if len(pi.insns) == 0 {
400+
err = fmt.Errorf("insufficient permissions or unsupported kernel: %w", ErrNotSupported)
401+
}
402+
return len(pi.insns), err
403+
}
404+
377405
// MapIDs returns the maps related to the program.
378406
//
379407
// Available from 4.15.
@@ -383,6 +411,25 @@ func (pi *ProgramInfo) MapIDs() ([]MapID, bool) {
383411
return pi.maps, pi.maps != nil
384412
}
385413

414+
// LoadTime returns when the program was loaded since boot time.
415+
//
416+
// Available from 4.15.
417+
//
418+
// The bool return value indicates whether this optional field is available.
419+
func (pi *ProgramInfo) LoadTime() (time.Duration, bool) {
420+
// loadTime and NrMapIds were introduced in the same kernel version.
421+
return pi.loadTime, pi.maps != nil
422+
}
423+
424+
// VerifiedInstructions returns the number verified instructions in the program.
425+
//
426+
// Available from 5.16.
427+
//
428+
// The bool return value indicates whether this optional field is available.
429+
func (pi *ProgramInfo) VerifiedInstructions() (uint32, bool) {
430+
return pi.verifiedInstructions, pi.verifiedInstructions > 0
431+
}
432+
386433
func scanFdInfo(fd *sys.FD, fields map[string]interface{}) error {
387434
fh, err := os.Open(fmt.Sprintf("/proc/self/fdinfo/%d", fd.Int()))
388435
if err != nil {

info_test.go

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,16 +122,55 @@ func TestProgramInfo(t *testing.T) {
122122
}
123123

124124
if name == "proc" {
125+
_, err := info.JitedSize()
126+
qt.Assert(t, qt.IsNotNil(err))
127+
128+
_, err = info.TranslatedSize()
129+
qt.Assert(t, qt.IsNotNil(err))
130+
125131
_, ok := info.CreatedByUID()
126132
qt.Assert(t, qt.IsFalse(ok))
133+
134+
_, ok = info.LoadTime()
135+
qt.Assert(t, qt.IsFalse(ok))
136+
137+
_, ok = info.VerifiedInstructions()
138+
qt.Assert(t, qt.IsFalse(ok))
127139
} else {
128-
uid, ok := info.CreatedByUID()
129-
if testutils.IsKernelLessThan(t, "4.15") {
140+
if jitedSize, err := info.JitedSize(); testutils.IsKernelLessThan(t, "4.13") {
141+
qt.Assert(t, qt.IsNotNil(err))
142+
} else {
143+
qt.Assert(t, qt.IsNil(err))
144+
qt.Assert(t, qt.IsTrue(jitedSize > 0))
145+
}
146+
147+
if xlatedSize, err := info.TranslatedSize(); testutils.IsKernelLessThan(t, "4.13") {
148+
qt.Assert(t, qt.IsNotNil(err))
149+
} else {
150+
qt.Assert(t, qt.IsNil(err))
151+
qt.Assert(t, qt.IsTrue(xlatedSize > 0))
152+
}
153+
154+
if uid, ok := info.CreatedByUID(); testutils.IsKernelLessThan(t, "4.15") {
130155
qt.Assert(t, qt.IsFalse(ok))
131156
} else {
132157
qt.Assert(t, qt.IsTrue(ok))
133158
qt.Assert(t, qt.Equals(uid, uint32(os.Getuid())))
134159
}
160+
161+
if loadTime, ok := info.LoadTime(); testutils.IsKernelLessThan(t, "4.15") {
162+
qt.Assert(t, qt.IsFalse(ok))
163+
} else {
164+
qt.Assert(t, qt.IsTrue(ok))
165+
qt.Assert(t, qt.IsTrue(loadTime > 0))
166+
}
167+
168+
if verifiedInsns, ok := info.VerifiedInstructions(); testutils.IsKernelLessThan(t, "5.16") {
169+
qt.Assert(t, qt.IsFalse(ok))
170+
} else {
171+
qt.Assert(t, qt.IsTrue(ok))
172+
qt.Assert(t, qt.IsTrue(verifiedInsns > 0))
173+
}
135174
}
136175
})
137176
}

0 commit comments

Comments
 (0)