Skip to content
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

Attach BTF to generated BPF programs #2804

Merged
merged 2 commits into from
Nov 21, 2023
Merged

Conversation

viktormalik
Copy link
Contributor

@viktormalik viktormalik commented Oct 17, 2023

Modern BPF programs loaded through libbpf should include BTF information describing their structure and data. This is required for some BPF features such as subprograms or kernel functions (kfuncs) to work. It is also a necessary prerequisite for #2334.

This PR is the first step for doing this in bpftrace. We produce standard (DWARF) debug info for our probes which LLVM then converts into proper BTF sections. These are then passed to libbpf upon bpf_prog_load. At the moment, this doesn't add any value but we at least check that libbpf doesn't reject our produced BTF info.

This is the second part of #2710 posted separately to simplify reviewing.

Checklist
  • Language changes are updated in man/adoc/bpftrace.adoc and if needed in docs/reference_guide.md
  • User-visible and non-trivial changes updated in CHANGELOG.md
  • The new behaviour is covered by tests

Copy link
Member

@danobi danobi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems reasonable. I'm not very familiar with llvm debuginfo interface though

src/utils.cpp Outdated Show resolved Hide resolved
src/utils.cpp Show resolved Hide resolved
src/ast/dibuilderbpf.h Show resolved Hide resolved
@viktormalik viktormalik force-pushed the emit-btf branch 2 times, most recently from 45c290f to 000ff11 Compare October 30, 2023 10:16
@viktormalik
Copy link
Contributor Author

@ajor do you want to review this, too?

Copy link
Member

@ajor ajor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, mainly just some nits. I'll do some testing myself to check out the createFile thing.


DIBuilderBPF::DIBuilderBPF(Module &module) : DIBuilder(module)
{
file = createFile("bpftrace", ".");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit unsure about this line but I'm not familiar enough with createFile to be certain.

Does this actually create a file? Does "." mean current working directory? Can this result in permission errors if bpftrace is run from a non-writable directory?

Will do a bit of testing myself.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it creates an actual file. I quickly skimmed the code of createFile and IIUC, it should just create a debug info entry which is required to produce correct debug info for a function. We just need to provide a directory and a file name strings to create it, so we give the current directory and ”bpftrace” for the file name. I think that the strings themselves don't mean anything, we could provide anything.

Copy link
Member

@ajor ajor Nov 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ran bpftrace through strace and can confirm it doesn't create a file at this location. If we print debug output ("-d") then it does attempt to read this file though:

openat(AT_FDCWD, "./bpftrace", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)

I can make bpftrace read arbitrary data by manually creating a file at the expected location. It's not necessarily a problem but feels a bit dodgy to me.

How about we do createFile("", "")? This seems to work and ensures that there can be no real file associated with our DIFile object.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ran bpftrace through strace and can confirm it doesn't create a file at this location. If we print debug output ("-d") then it does attempt to read this file though:


openat(AT_FDCWD, "./bpftrace", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)

Interesting, it's probably trying to open the file when dumping LLVM IR, I've no idea why.

How about we do createFile("", "")? This seems to work and ensures that there can be no real file associated with our DIFile object.

Sure, makes sense to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, unfortunately, we must pass a valid filename, otherwise LLVM IR verification (which we run in codegen tests) complains. I reverted it to the original version.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ran a few more tests and discovered that LLVM dump tries to open the file and either read it (if it's a text file) or mmap it to memory (if it's an ELF). While this shouldn't be harmful, it's certainly an unnecessary operation.

Using ./bpftrace is therefore not ideal as it will exist when running ./bpftrace -e ... and will do an unnecessary mmap of the bpftrace binary. So, I changed it to bpftrace.bpf.o which is less likely to exist.

src/utils.h Outdated Show resolved Hide resolved
src/utils.cpp Outdated Show resolved Hide resolved
0,
StringRef(),
DICompileUnit::DebugEmissionKind::LineTablesOnly);
module_->addModuleFlag(llvm::Module::Warning,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any idea what this is for?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is required by DWARF.

src/ast/dibuilderbpf.cpp Outdated Show resolved Hide resolved
src/ast/dibuilderbpf.cpp Outdated Show resolved Hide resolved
src/attached_probe.cpp Outdated Show resolved Hide resolved
@viktormalik viktormalik force-pushed the emit-btf branch 2 times, most recently from 01ee3be to daab7f9 Compare November 14, 2023 12:50
@viktormalik viktormalik force-pushed the emit-btf branch 4 times, most recently from 82fff69 to 9aa23a6 Compare November 20, 2023 10:46
Delyan Kratunov and others added 2 commits November 20, 2023 12:09
In order for bpftrace to adapt to libbpf style loading of programs and
to support subprograms, it first needs to produce BTF information for
BPF programs. In order for it to produce BTF, it first needs to produce
any debugging info, so that LLVM can convert it into BTF/BTF.ext
sections.

This commit emits subprogram entries for probe definitions. This does
not use any line info but should be sufficient to create func infos down
the road.

Since we're going to generate more and more debug info in future,
introduce a dedicated class DIBuilderBPF for encapsulating related logic
and methods. DIBuilderBPF inherits from llvm::DIBuilder, the
relationship is analogous to the one between IRBuilderBPF and
llvm::IRBuilder.
BTF is not used for any purpose at the moment but it will be used in
future and this way we can at least check that libbpf accepts our
produced BTF.
@viktormalik
Copy link
Contributor Author

I rebased to the current master to run tests with the CI libbpf. I'll wait 24 hours and then merge this, unless there are objections.

@viktormalik viktormalik merged commit 280042e into bpftrace:master Nov 21, 2023
18 checks passed
@viktormalik viktormalik deleted the emit-btf branch January 10, 2024 09:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants