(In reply to Fabian Vogt from comment #31) > FWICT, the BTF is split over vmlinux and the .ko such that it results in a > single complete object if the type and string data parts are combined. So > the offsets in the .ko file depend on the BTF inside vmlinux. If kernel > rebuilds change the BTF somehow, it'll no longer be compatible. Yep I think you're right on the point. There seems to be some mismatch between the base BTF (/sys/kernel/btf/vmlinux) and "splitted" BTF on those kernel that fails to load (.BTF section of the .ko file). The struct member/field in comment 29 that got their name messed happens to have the string data inside .ko, where as those with correct name have the string data inside /sys/kernel/btf/vmlinux. More explanation below. From comment 29 we see usb_device_id, match_flags, bcdDevice_lo, and bcdDevice_hi have their name messed up. All of them happens to have name_off (i.e. name offset, such as 1821813 for bcdDevice_lo) >= than str_len (string length, which is 1821787) field of the base BTF header, which is 1821787. That means the string such as "bcdDevice_lo", is stored in .ko rather than /sys/kernel/btf/vmlinux. > INFO:root:In base BTF file: /sys/kernel/btf/vmlinux > INFO:root:Parsed base btf_header Container({'magic': 60319, 'version': 1, 'flags': 0, 'hdr_len': 24, 'type_off': 0, 'type_len': 2633056, 'str_off': 2633056, 'str_len': 1821787}) > INFO:root:In file: ./ipheth.ko.orig > INFO:root:Parsed btf_header Container({'magic': 60319, 'version': 1, 'flags': 0, 'hdr_len': 24, 'type_off': 0, 'type_len': 1340, 'str_off': 1340, 'str_len': 557}) > [103111] 'usb_device_id': Container({'name_off': 1821787, 'info': Container({'vlen': 13, 'kind_flag': False, 'p': 0, 'kind': 'BTF_KIND_STRUCT'}), 'size': 32, 'type': 32}) > 'idVendor': Container({'name_off': 1224987, 'type': 14, 'offset': 16}) > 'idProduct': Container({'name_off': 1224996, 'type': 14, 'offset': 32}) > 'bcdDevice_lo': Container({'name_off': 1821813, 'type': 14, 'offset': 48}) > 'bcdDevice_hi': Container({'name_off': 1821826, 'type': 14, 'offset': 64}) > 'bDeviceClass': Container({'name_off': 1224926, 'type': 9, 'offset': 80}) > 'bDeviceSubClass': Container({'name_off': 1224939, 'type': 9, 'offset': 88}) > 'bDeviceProtocol': Container({'name_off': 1224955, 'type': 9, 'offset': 96}) > 'bInterfaceClass': Container({'name_off': 1225254, 'type': 9, 'offset': 104}) > 'bInterfaceSubClass': Container({'name_off': 1225270, 'type': 9, 'offset': 112}) > 'bInterfaceProtocol': Container({'name_off': 1225289, 'type': 9, 'offset': 120}) > 'bInterfaceNumber': Container({'name_off': 1225205, 'type': 9, 'offset': 128}) > 'driver_info': Container({'name_off': 1251577, 'type': 2078, 'offset': 192}) > Container({'name_off': 0, 'type': 167772160, 'offset': 103111}) The pseudo code for extracting name is something like if name_off < base_btf->str_len: name = (char *) base_btf + base_btf->hdr_len + base_btf->str_pos + name_off else: # name is messed up in this branch name_off = name_off - base_btf->str_len name = (char *) ko_btf + ko_btf->hdr_len + ko_btf->str_pos + name_off So perhaps either str_len in base BTF or str_post in kernel module BTF is wrong