Comment # 35 on bug 1194501 from
(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


You are receiving this mail because: