 This has traditionally been solved by compiling the program at each target machine. This is what is done by VCC and the Python tools that were mentioned before. But of course, this is not an idea solution because in order to compile the tools, we need a compiler in the target machine. So it means that we have to spend some hundreds of megabytes of extra storage there. Also, compiling the programs is a heavy process. It means that if we are running on a very tight schedule machines, we could affect that schedule. And we could be, for instance, kill some process because we are run out of memory of similar issues. And the other thing is that in order to compile the program, we need some time. So the few events that we are getting, the first information that we are getting from the EBBA program could take a bit longer to arrive. And the last problem is a very annoying one is that in order to compile those programs, we need the Linux kernel headers. But those headers are not available on many different distributions. So we have to tell the user to install an additional packages to have the kernel, the Linux kernel headers available, and so on. Fortunately, there is another solution for that. It was already mentioned. This is the compiled ones run everywhere approach. The idea in this case is that instead of chipping source code, we chip the compiled BPF programs. But in order to make those programs to work in different machines, what we have is a mechanism that allows us to update the offset of the structure, of the member of the structure that those programs access around time. So this is like a patching mechanism. So we relocate the program before injecting the program into the kernel. The whole technology behind this is BTF. It stands for BTF type format, that this is representation of the kernel data. So as we can see in the picture, we have the compiled BPF program. We have some BTF information that is exposed by the kernel. And then the loader library takes both of them together and patches the program according to the kernel that we are running. Some more information about BTF. So as I mentioned before, this is a metadata type that describes the different kernel types. This is generated when we compile the kernel. And this is exposed by the kernel when we have this compilation flag enabled. This is just a small example of how the BPF looks like. In this case, the same test structure that I've shown you before. As you can see here, we have information that there is a test structure. We have information about the size of the structure, all the members. And on the bottom, we can see that there is a PID member and we can see the offset. This is the actual information that the loader library uses to perform the relocation of the program. But everything is so good so far. There is a problem. The problem is BTF is not available on all the kernels. This is only available in some releases and when this compilation flag is enabled. This is the reason why BTF Hub was created. So this is a project that exposes BTF information for different distributions that don't support BTF. So BTF Hub takes that information from different debug packages that are provided by different distributions, performs some data processing, and exposes those BTF files from the different kernel versions of different distributions. We can see there, for instance, for Ubuntu, we have for the version 20.04 a lot of different kernel for different BTF files for different kernel versions. So this is how we can use Core together with BTF Hub. So the loader library, the compiler BPF program is the same. What is changing here is that we are not taking the BTF information from the kernel, but we are taking that information from BTF Hub. So what we usually do is that before loading our BPF program into the kernel, we go to a site to get that page. We take the BTF corresponding to our current kernel, we install that on the system, and then we provide that file to the loader library. So we have the information available to perform the relocations. Again, there are some limitations with this approach. Each BTF file is around 5 megabytes. So what it means is that this is not possible to cheap all the BTF files for so many different kernels together with our application. It will require some gigabytes of data. And of course, this is not possible. So the alternative is to download the file from the current kernel from the internet. But of course, taking a file from the internet requires some time. And even worse, in many scenarios, this is not possible to reach an external host to get a file. And this is where BTF Gen comes into play. It turns out that in order to perform the relocations, we don't need to have the full information of all the kernel types. We only need the information of the kernel types that our BPF program is using. So by using BTF Gen, what we are able to do is to take a file, a BTF file, describing all the kernel types. And we are able to generate a small file with only the kernel file, the types that are used by our program. What it means is that we can generate various more BTF files. And we can cheap those together with our program. So this is how BTF Gen works in general. We have different BTF object files, BTF programs. We have BTF files for different kernels. Those could be from BTF Hub or a different source. Please notice that each of them is around 5 megabytes big. Then we put that all together into BTF Gen, and then we generate a small file for each kernel. We did an integration of BTF Gen with the BCC tools. And we found out that in order to support something like 1,000 kernels, we only need something like 100 kilobytes per application. So there is a really small overhead there. So again, everything is the same. The difference here is that the BTF information is not on the internet, is not provided by the operating system. But in this case, we cheap the BTF information for many different kernels together with our application. So yeah, according to the running linux distribution, the kernel version will take the write file and then we provide that file to our loader library. So yeah, I know this is a lightning talk. It was very fast. A lot of details that probably we were not able to catch. But the conclusion that I would like you to take from this is that if you are developing an eBPF project, if you are using eBPF, and you want to cheap those programs, to run those programs in many different distributions, you could use BTF Gen unable to do so. There is a small size overhead that we have to pay, but it's really small. And of course, if you want more information, please go to our blog post where we provide the full details about how we implemented BTF Gen, about how can you use BTF Gen in your project, and so on. And of course, if you have any questions, please reach out. I will be also in luck replying the question for the people that is watching the screen. And before finishing, I would like to thank you the people that made this possible. This was a joint project by different people from different companies, especially to Rafael from Aqua Security. This is the guy behind the BTF Hub project. He helped a lot with implementation of this tool. Also, Lorenzo Fontana and Leonardo Di Donato from Elastic provide valuable feedback. And finally, to the maintainers of eBPF tool that make this possible to have the support available there. And that's it. Thank you.