Skip to content

Commit

Permalink
info: expose more prog jited info
Browse files Browse the repository at this point in the history
Expose these prog jited info:

1. JITed machine native instructions torvalds/linux@1e2709769086 ("bpf: Add BPF_OBJ_GET_INFO_BY_FD")
2. JITed line info torvalds/linux@c454a46b5efd ("bpf: Add bpf_line_info support")
3. JITed image lengths torvalds/linux@815581c11cc2 ("bpf: get JITed image lengths of functions via syscall")

Signed-off-by: Leon Hwang <[email protected]>
  • Loading branch information
Asphaltt committed Nov 25, 2024
1 parent ab9722b commit a34ec46
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 24 deletions.
164 changes: 143 additions & 21 deletions info.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,40 @@ type programStats struct {
recursionMisses uint64
}

// programJitedInfo holds information about JITed info of a program.
type programJitedInfo struct {
// ksyms holds the ksym addresses of the BPF program, including those of its
// subprograms.
//
// Available from 4.18.
ksyms []uintptr
numKsyms uint32

// insns holds the JITed machine native instructions of the program,
// including those of its subprograms.
//
// Available from 4.13.
insns []byte
numInsns uint32

// lineInfos holds the JITed line infos, which are kernel addresses.
//
// Available from 5.0.
lineInfos []uint64
numLineInfos uint32

// lineInfoRecSize is the size of a single line info record.
//
// Available from 5.0.
lineInfoRecSize uint32

// funcLens holds the insns length of each function.
//
// Available from 4.18.
funcLens []uint32
numFuncLens uint32
}

// ProgramInfo describes a program.
type ProgramInfo struct {
Type ProgramType
Expand All @@ -199,12 +233,12 @@ type ProgramInfo struct {
jitedSize uint32
verifiedInstructions uint32

jitedInfo programJitedInfo

lineInfos []byte
numLineInfos uint32
funcInfos []byte
numFuncInfos uint32
ksymInfos []uint64
numKsymInfos uint32
}

func newProgramInfoFromFd(fd *sys.FD) (*ProgramInfo, error) {
Expand Down Expand Up @@ -282,11 +316,37 @@ func newProgramInfoFromFd(fd *sys.FD) (*ProgramInfo, error) {
makeSecondCall = true
}

pi.jitedInfo.lineInfoRecSize = info.JitedLineInfoRecSize
if info.JitedProgLen > 0 {
pi.jitedInfo.numInsns = info.JitedProgLen
pi.jitedInfo.insns = make([]byte, info.JitedProgLen)
info2.JitedProgLen = info.JitedProgLen
info2.JitedProgInsns = sys.NewSlicePointer(pi.jitedInfo.insns)
makeSecondCall = true
}

if info.NrJitedFuncLens > 0 {
pi.jitedInfo.numFuncLens = info.NrJitedFuncLens
pi.jitedInfo.funcLens = make([]uint32, info.NrJitedFuncLens)
info2.NrJitedFuncLens = info.NrJitedFuncLens
info2.JitedFuncLens = sys.NewSlicePointer(pi.jitedInfo.funcLens)
makeSecondCall = true
}

if info.NrJitedLineInfo > 0 {
pi.jitedInfo.numLineInfos = info.NrJitedLineInfo
pi.jitedInfo.lineInfos = make([]uint64, info.NrJitedLineInfo)
info2.NrJitedLineInfo = info.NrJitedLineInfo
info2.JitedLineInfo = sys.NewSlicePointer(pi.jitedInfo.lineInfos)
info2.JitedLineInfoRecSize = info.JitedLineInfoRecSize
makeSecondCall = true
}

if info.NrJitedKsyms > 0 {
pi.ksymInfos = make([]uint64, info.NrJitedKsyms)
info2.JitedKsyms = sys.NewSlicePointer(pi.ksymInfos)
pi.jitedInfo.numKsyms = info.NrJitedKsyms
pi.jitedInfo.ksyms = make([]uintptr, info.NrJitedKsyms)
info2.JitedKsyms = sys.NewSlicePointer(pi.jitedInfo.ksyms)
info2.NrJitedKsyms = info.NrJitedKsyms
pi.numKsymInfos = info.NrJitedKsyms
makeSecondCall = true
}

Expand Down Expand Up @@ -380,6 +440,52 @@ func (pi *ProgramInfo) RecursionMisses() (uint64, bool) {
return 0, false
}

// btfSpec returns the BTF spec associated with the program.
func (pi *ProgramInfo) btfSpec() (*btf.Spec, error) {
id, ok := pi.BTFID()
if !ok {
return nil, fmt.Errorf("program created without BTF or unsupported kernel: %w", ErrNotSupported)
}

h, err := btf.NewHandleFromID(id)
if err != nil {
return nil, fmt.Errorf("get BTF handle: %w", err)
}
defer h.Close()

spec, err := h.Spec(nil)
if err != nil {
return nil, fmt.Errorf("get BTF spec: %w", err)
}

return spec, nil
}

// LineInfos returns the BTF line information of the program.
//
// Available from 5.0.
//
// Requires CAP_SYS_ADMIN or equivalent for reading BTF information. Returns
// ErrNotSupported if the program was created without BTF or if the kernel
// doesn't support the field.
func (pi *ProgramInfo) LineInfos() (btf.LineOffsets, error) {
if len(pi.lineInfos) == 0 {
return nil, fmt.Errorf("insufficient permissions or unsupported kernel: %w", ErrNotSupported)
}

spec, err := pi.btfSpec()
if err != nil {
return nil, err
}

return btf.LoadLineInfos(
bytes.NewReader(pi.lineInfos),
internal.NativeEndian,
pi.numLineInfos,
spec,
)
}

// Instructions returns the 'xlated' instruction stream of the program
// after it has been verified and rewritten by the kernel. These instructions
// cannot be loaded back into the kernel as-is, this is mainly used for
Expand Down Expand Up @@ -524,11 +630,34 @@ func (pi *ProgramInfo) VerifiedInstructions() (uint32, bool) {
//
// The bool return value indicates whether this optional field is available.
func (pi *ProgramInfo) KsymAddrs() ([]uintptr, bool) {
addrs := make([]uintptr, 0, len(pi.ksymInfos))
for _, addr := range pi.ksymInfos {
addrs = append(addrs, uintptr(addr))
}
return addrs, pi.numKsymInfos > 0
return pi.jitedInfo.ksyms, len(pi.jitedInfo.ksyms) > 0
}

// JitedInsns returns the JITed machine native instructions of the program.
//
// Available from 4.13.
//
// The bool return value indicates whether this optional field is available.
func (pi *ProgramInfo) JitedInsns() ([]byte, bool) {
return pi.jitedInfo.insns, len(pi.jitedInfo.insns) > 0
}

// JitedLineInfos returns the JITed line infos of the program.
//
// Available from 5.0.
//
// The bool return value indicates whether this optional field is available.
func (pi *ProgramInfo) JitedLineInfos() ([]uint64, bool) {
return pi.jitedInfo.lineInfos, len(pi.jitedInfo.lineInfos) > 0
}

// JitedFuncLens returns the insns length of each function in the JITed program.
//
// Available from 4.18.
//
// The bool return value indicates whether this optional field is available.
func (pi *ProgramInfo) JitedFuncLens() ([]uint32, bool) {
return pi.jitedInfo.funcLens, len(pi.jitedInfo.funcLens) > 0
}

// FuncInfos returns the offset and function information of all (sub)programs in
Expand All @@ -540,20 +669,13 @@ func (pi *ProgramInfo) KsymAddrs() ([]uintptr, bool) {
// ErrNotSupported if the program was created without BTF or if the kernel
// doesn't support the field.
func (pi *ProgramInfo) FuncInfos() (btf.FuncOffsets, error) {
id, ok := pi.BTFID()
if pi.numFuncInfos == 0 || !ok {
return nil, fmt.Errorf("program created without BTF or unsupported kernel: %w", ErrNotSupported)
}

h, err := btf.NewHandleFromID(id)
if err != nil {
return nil, fmt.Errorf("get BTF handle: %w", err)
if len(pi.funcInfos) == 0 {
return nil, fmt.Errorf("insufficient permissions or unsupported kernel: %w", ErrNotSupported)
}
defer h.Close()

spec, err := h.Spec(nil)
spec, err := pi.btfSpec()
if err != nil {
return nil, fmt.Errorf("get BTF spec: %w", err)
return nil, err
}

return btf.LoadFuncInfos(
Expand Down
3 changes: 3 additions & 0 deletions internal/cmd/gentypes/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,10 +197,13 @@ import (
"ProgInfo", "bpf_prog_info",
[]patch{
replace(objName, "name"),
replace(pointer, "jited_prog_insns"),
replace(pointer, "xlated_prog_insns"),
replace(pointer, "map_ids"),
replace(pointer, "line_info"),
replace(pointer, "jited_line_info"),
replace(pointer, "jited_ksyms"),
replace(pointer, "jited_func_lens"),
replace(pointer, "func_info"),
replace(btfID, "btf_id", "attach_btf_obj_id"),
replace(typeID, "attach_btf_id"),
Expand Down
6 changes: 3 additions & 3 deletions internal/sys/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,7 @@ type ProgInfo struct {
Tag [8]uint8
JitedProgLen uint32
XlatedProgLen uint32
JitedProgInsns uint64
JitedProgInsns Pointer
XlatedProgInsns Pointer
LoadTime uint64
CreatedByUid uint32
Expand All @@ -734,14 +734,14 @@ type ProgInfo struct {
NrJitedKsyms uint32
NrJitedFuncLens uint32
JitedKsyms Pointer
JitedFuncLens uint64
JitedFuncLens Pointer
BtfId BTFID
FuncInfoRecSize uint32
FuncInfo Pointer
NrFuncInfo uint32
NrLineInfo uint32
LineInfo Pointer
JitedLineInfo uint64
JitedLineInfo Pointer
NrJitedLineInfo uint32
LineInfoRecSize uint32
JitedLineInfoRecSize uint32
Expand Down

0 comments on commit a34ec46

Please sign in to comment.