-
Notifications
You must be signed in to change notification settings - Fork 697
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
info: expose more prog jited info #1598
base: main
Are you sure you want to change the base?
Conversation
info.go
Outdated
// withBTFSpec calls the provided callback with the BTF spec of the program. | ||
// | ||
// The base argument is used to resolve type IDs in the prog's BTF spec. | ||
func (pi *ProgramInfo) withBTFSpec(base *btf.Spec, cb func(*btf.Spec) error) error { | ||
id, ok := pi.BTFID() | ||
if pi.numFuncInfos == 0 || !ok { | ||
return fmt.Errorf("program created without BTF or unsupported kernel: %w", ErrNotSupported) | ||
} | ||
|
||
h, err := btf.NewHandleFromID(id) | ||
if err != nil { | ||
return fmt.Errorf("get BTF handle: %w", err) | ||
} | ||
defer h.Close() | ||
|
||
spec, err := h.Spec(base) | ||
if err != nil { | ||
return fmt.Errorf("get BTF spec: %w", err) | ||
} | ||
|
||
return cb(spec) | ||
} | ||
|
||
// LineInfos returns the BTF line information of the program. | ||
func (pi *ProgramInfo) LineInfos() (btf.LineInfos, error) { | ||
var li btf.LineInfos | ||
|
||
err := pi.withBTFSpec(nil, func(spec *btf.Spec) error { | ||
var err error | ||
li, err = btf.LoadLineInfos( | ||
bytes.NewReader(pi.lineInfos), | ||
internal.NativeEndian, | ||
pi.numLineInfos, | ||
spec, | ||
) | ||
return err | ||
}) | ||
|
||
return li, err | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps this can be explained better in the docs, but line info is currently already available via the instruction metadata.
insns, err := pi.Instructions()
if err != nil {
return err
}
iter := insns.Iterate()
for iter.Next() {
src := iter.Ins.Source()
if src == nil {
continue
}
if line, ok := src.(*btf.Line); ok {
// Use *btf.Line
}
}
So there should be no need for the line info on its own without the instructions to make sense of it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line info is used for jited_line_info
.
The jited_line_info
is the address of the corresponding jited insn. Then, when decode the jited_prog_insns
with jited_ksyms
, it is able to get the BTF line info for the decoding insn by jited_ksym
+ relative pc, which equals to jited_line_info
.
As a result, it is able to decode jited insns like bpftool prog dump jited PROG
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Furthermore, with such BTF line info for jited_prog_insns
, it is able to reflect a bpf prog address, which is captured by LBR, to line info if the address is a jited_line_info
.
info.go
Outdated
// LineInfos holds the JITed line infos, which are kernel addresses. | ||
// | ||
// Available from 5.0. | ||
LineInfos []uint64 | ||
|
||
// LineInfoRecSize is the size of a single line info record. | ||
// | ||
// Available from 5.0. | ||
LineInfoRecSize uint32 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are already parsing the bytes to uint64, so it doesn't really make sense to also expose LineInfoRecSize
. Its 8 or the API is broken, so it seems that should be something internal.
On that note, wouldn't it be better if the LineInfo were a struct or interface which can be expanded if the kernel ever decides to change things up?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so it doesn't really make sense to also expose
LineInfoRecSize
.
No problem. Let us hide this info, as it is set as 8 bytes in kernel set_info_rec_size():
info->jited_line_info_rec_size = sizeof(__u64);
wouldn't it be better if the LineInfo were a struct or interface which can be expanded if the kernel ever decides to change things up?
No. jited_line_info
is the kernel address for its corresponding jited insn. And it is aligned to uint64 in kernel struct bpf_prog_info:
struct bpf_prog_info {
__aligned_u64 jited_line_info;
}
And in the foreseeable future, its type won't be changed.
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]>
8c0466b
to
d5a4c9e
Compare
For pwru cilium/pwru#451, I'm going to inspect some inner details of bpf progs with LBR. But it requires the JITed info of bpf prog.
Then, expose more prog jited info: