// SPDX-License-Identifier: Apache-2.0 // // Reading BTF: struct layouts and function prototypes, from the kernel that // the driver was built for. // // docs/architecture/ldls.md, rule 3½ -- the thing that makes rule 3 comfortable. // // The shim has to agree with a compiled driver about where `pci_driver.probe` // sits, and a compiled driver is not negotiable about it. Writing those // offsets into our source would mean a field-for-field match with Linux's // headers, which *looks* like transcription however it was arrived at. // // It does not have to be in our source. A kernel built with // CONFIG_DEBUG_INFO_BTF publishes `/sys/kernel/btf/vmlinux`: every struct // layout and every function prototype, as generated binary type data // describing the kernel that is installed. LDLS reads it at load time, on the // user's machine, from the user's own kernel. // // Two things follow. The offsets are never ours to have copied, and they are // right for the kernel actually present rather than one we pinned by guessing // -- which is most of what rule 4 was worried about. // // The format is described in Documentation/bpf/btf.rst, which is a published // specification; implementing it from that is the case ../docs/licensing.md §5 // covers. Freestanding, like the rest of ldls/. // --- the format ------------------------------------------------------------- #define BTF_MAGIC 0xeB9F struct btf_header { unsigned short magic; unsigned char version; unsigned char flags; unsigned int hdr_len; // Both offsets are from the end of the header, not from the start of it. unsigned int type_off; unsigned int type_len; unsigned int str_off; unsigned int str_len; }; struct btf_type { unsigned int name_off; // vlen in bits 0-15, kind in bits 24-28, kind_flag in bit 31. unsigned int info; union { unsigned int size; // STRUCT, UNION, ENUM, INT, DATASEC, FLOAT unsigned int type; // PTR, TYPEDEF, CONST, FUNC, VAR, ... } u; }; struct btf_member { unsigned int name_off; unsigned int type; // With kind_flag set this is a bitfield: size in bits 24-31, bit offset in // bits 0-23. Without it, a plain bit offset. unsigned int offset; }; struct btf_param { unsigned int name_off; unsigned int type; }; #define BTF_KIND_INT 1 #define BTF_KIND_PTR 2 #define BTF_KIND_ARRAY 3 #define BTF_KIND_STRUCT 4 #define BTF_KIND_UNION 5 #define BTF_KIND_ENUM 6 #define BTF_KIND_FWD 7 #define BTF_KIND_TYPEDEF 8 #define BTF_KIND_VOLATILE 9 #define BTF_KIND_CONST 10 #define BTF_KIND_RESTRICT 11 #define BTF_KIND_FUNC 12 #define BTF_KIND_FUNC_PROTO 13 #define BTF_KIND_VAR 14 #define BTF_KIND_DATASEC 15 #define BTF_KIND_FLOAT 16 #define BTF_KIND_DECL_TAG 17 #define BTF_KIND_TYPE_TAG 18 #define BTF_KIND_ENUM64 19 #define BTF_INFO_KIND(i) (((i) >> 24) & 0x1f) #define BTF_INFO_VLEN(i) ((i) & 0xffff) #define BTF_INFO_KFLAG(i) (((i) >> 31) & 1) // --- the reader --------------------------------------------------------------- #define BTF_MAXTYPES 262144 // type ids we will index; vmlinux is ~150k struct btf { const unsigned char *img; unsigned long long len; const struct btf_header *h; const unsigned char *types; // start of the type section unsigned int types_len; const char *str; unsigned int str_len; // Type id -> byte offset into the type section. Id 0 is void and has no // entry, so this is 1-based and index 0 is unused. unsigned int *off; // the caller's, ntypes + 1 entries unsigned int ntypes; char err[128]; }; // How many type ids this BTF holds, so the caller can size the index. -1 if // the image is not BTF at all. long btf_count(const void *image, unsigned long long len); // Index it. `off` must have btf_count()+1 entries. int btf_open(struct btf *b, const void *image, unsigned long long len, unsigned int *off, unsigned int noff); // The type id of a named type of a given kind, or 0. int btf_find(struct btf *b, const char *name, int kind); // Byte offset and size of a named member of a struct or union. // // Returns 0 on success. Bitfields are refused rather than rounded: a driver // that reads one needs the bit position, and a byte offset would be a // plausible-looking wrong answer. int btf_member_off(struct btf *b, int struct_id, const char *member, unsigned int *off_bytes, unsigned int *size_bytes); // The value of a named enumerator, searched across every enum in the file. // Constants a driver depends on are not all struct offsets -- see btf.c. int btf_enum_value(struct btf *b, const char *name, long long *val); // Size in bytes of a type, following typedefs and qualifiers. 0 if unknown. unsigned int btf_type_size(struct btf *b, int id); const char *btf_name_of(struct btf *b, int id); int btf_kind_of(struct btf *b, int id); const char *btf_err(const struct btf *b);