Earlier quoted context omitted.
If you just give me a .jar do I get those interfaces in a consumable form? Said differently, can I download your .jar and write my own code to interface with it while on a desert island without any other resources?
Yes. If you have a random JAR file, an IDE can introspect it to see what classes are in it and what methods are in those classes. The only exception is if you run it through some kind of obfuscator first.
Extending the Linux Kernel with Built-In Kernel Headers
41–50 of 62 posts
Re: Extending the Linux Kernel with Built-In Kernel Headers
#42It’s a simple and practical solution. It irks me for some reason but I can’t think of something better.
Re: Extending the Linux Kernel with Built-In Kernel Headers
#43It’s a simple and practical solution. It irks me for some reason but I can’t think of something better.
Doesn't necessarily work for the kernel, but GIR and typelibs provide machine-readable descriptions of C APIs: https://github.com/GNOME/gobject-introspection
Apparently the reason it requires running the compiled binaries is that GObject types are only registered at runtime, within so-called "_get_type" functions. For more typical systems, everything needed can be determined at compile time. Too bad there's no portable way to ask a C compiler to dump what it knows about a source file, but if you just want things like struct sizes and field offsets, you can compile a C file that embeds them as global variables, and then extract the variable values. For more advanced introspection there are many less-portable options including Clang's API, GCC-XML, parsing debug info, or writing your own compiler (easier for C; it seems that parts of gobject-introspection work like this).
Anyway, another interesting comparison is DTrace's CTF (Compact Type Format) [2], a simple binary format that describes the kernel's C struct layouts, function signatures, etc. This information is simply converted from compiler-generated debug info [3], but it's stripped down enough that it can be embedded into every kernel without too much size overhead. When the DTrace compiler is invoked to compile a user hook, it parses the CTF data and exposes the types and functions to the user's code (which is written in a custom C-like language).
Ironically, BPF has BTF, which is a very similar-looking format that encodes very similar kinds of data – but is used for a completely different purpose. Specifically, it's only used to encode types and functions defined by BPF programs, to allow the kernel to pretty-print things. But in theory BTF could be repurposed to work like CTF: you would need to generate BTF information for the kernel itself, and then Clang could be extended to support "including" BTF files in place of C headers. However, this option was apparently discussed and rejected [4]. I haven't read the original threads to find out why, but I suspect it might involve:
- Lack of existing tooling to do the above;
- Lower expressivity compared to C headers, e.g. the inability to encode macros (although this could be fixed);
- Desire to use the information for building not just BPF hooks but also full-fledged kernel modules.
[1] https://maxice8.github.io/8-cross-the-gir/
[2] https://github.com/oracle/libdtrace-ctf/blob/master/include/...
[3] https://www.freebsd.org/cgi/man.cgi?query=ctfconvert&sektion...
Re: Extending the Linux Kernel with Built-In Kernel Headers
#44Earlier quoted context omitted.
File this one under: kludges to get around openly user-hostile userland.
How so? Seems like an elegant enough solution to ensure you always have the right headers to build modules against the currently running kernel.
Re: Extending the Linux Kernel with Built-In Kernel Headers
#45Why /sys and not /proc ? After all, the kernel binary itself is under /proc .
Re: Extending the Linux Kernel with Built-In Kernel Headers
#46Why can't they build the eBPF bytecode offline using the correct kernel API and ship the bytecode to the Android device?
Re: Extending the Linux Kernel with Built-In Kernel Headers
#47Shipping the kernel headers is complicated, but somehow a whole C compiler is not? Or doesnt BPF compilation need a C compiler?
Re: Extending the Linux Kernel with Built-In Kernel Headers
#48Earlier quoted context omitted.
Yes. If you have a random JAR file, an IDE can introspect it to see what classes are in it and what methods are in those classes. The only exception is if you run it through some kind of obfuscator first.
Yes but JAR files are basically equivalent to source code parsed and serialised as bytecode with only the most rudimentary optimisations applied. I don't really see a difference between that and carrying gzipped headers with the kernel. Yes, the .class format is cleaner, but it's still very close to what the programmer wrote. Another plus to carrying the header with the kernel is that you can carry the preprocessed h…
1. 1/10 or 1/100 compile time
2. full introspection in regards to the interfaces (the topic of this discussion). the implementation classes could be obfuscated, but the point of an interface (and an API in general) that it is not.
3. one could possibly allow multiple versions of the interface be present on the same machine at the same time. for example, when SomeInterfaceV1 is replaced (or extended) by SomeInterfaceV2, it might be possible to provide an adapter that publishes the older interface for backward compatibility.
these are just random thoughts, because the difference between current systems written in c/c++ and a new architecture that uses interface-based approach is too great, I don't think I can name a real system that uses it in practice.
done the API versioning myself several times with complex applications though.
Re: Extending the Linux Kernel with Built-In Kernel Headers
#49Earlier quoted context omitted.
eBPF is not Turing-complete, but static analysis can absolutely prove things about individual programs in Turing-complete languages.
You can prove some code in Turing complete languages. You can construct non-turing-complete languages which all code can be proven, and that is the point the parent is making.
On the other hand, forbidding loops does make some properties easier to prove for restricted classes of programs. For instance, Linux’s BPF verifier tracks, for each instruction, the minimum and maximum value of each register at that point in the program. It uses that to determine whether array accesses in the program are bounds checked, and complain if not: that way, it doesn’t have to insert its own bounds check, which might be redundant. Doing the same in the presence of loops would require a more expensive algorithm, so forbidding them is a benefit. Yet... Linux’s verifier is sound: it will forbid all programs that could possibly index out of bounds, at least barring bugs. But it is not fully precise: it does not pass all programs that have the property of never indexing out of bounds for any input. For example, you could have a program that takes a 256-bit input and indexes out of bounds only if its SHA-256 hash is a specific value. That program is safe iff there happen to be no 256-bit strings that hash to that value, something that you could theoretically verify – but only by going through all 2^256 possible strings and hashing each of them. Linux does not.
Nor would it be reasonable to, why does that hypothetical matter? Because the ability to prove arbitrary properties about all programs, at the cost of arbitrarily long analysis time, is sort of the main mathematical benefit to non-Turing-completeness. But from a practical standpoint that’s useless. And if you don’t need that – if you only care about the ability to prove things about restricted classes of programs – well, you can achieve that even with loops. After all, that’s what a type system does, and there are plenty of Turing-complete languages with type systems. As I said, disallowing loops makes the job easier in some cases. But that’s more of a matter of degree, not the kind of hard theoretical barrier that “non-Turing-complete = analyzable” makes it sound like. That makes it a less convincing rationale for disallowing them.
Re: Extending the Linux Kernel with Built-In Kernel Headers
#50Earlier quoted context omitted.
squashfs has horrible performance. All requests to the block layer are 512 Bytes. Other filesystems like ext4 make much bigger requests and perform much better in the end despite the compression of squashfs leading to lower overall data volume. Disclaimer: Measured 2 years ago on ARM32, emmc, with a 4.1(?) kernel.
A big part of the problem might be xz decompression, that's been my discovery anyway. https://bugzilla.redhat.com/show_bug.cgi?id=1717728
It was in a previous job. I don't have access to the details anymore. And the kernel was not the newest. But squashfs looked unmaintained already then and that's what they're saying elsewhere in the discussion. So I fear nothing has changed.