BTF 布局和"未知"类型支持
在 https://lore.kernel.org/bpf/[email protected]/ 中,为内核和 libbpf 添加了 BTF 布局支持。pahole 在 https://git.kernel.org/pub/scm/devel/pahole/pahole.git/commit/?id=178b76972b1279c062dbc2c48a0b306cc33552b2 中添加了支持。BTF 在解析类型时存在兼容性问题。每种类型都有一个通用的头部,其中列出了其"类型"和可选的"vlen"等信息。然后,可选地跟着一个特定类型的结构和/或一个具有 vlen 长度的数组类型的结构。这意味着解析器需要了解每种"类型"才能继续解析。当遇到未知的 BTF 类型时,我们必须放弃,因为我们不知道要消耗多少字节。BTF 布局解决了这个问题。BTF 编码器可选地包含布局,这是一个数组,告诉我们在通用头部之后总共要消耗多少字节,以及每个 vlen 中要消耗多少字节。数组的索引等于类型值。这意味着即使我们不了解 BTF 类型的字节含义,我们仍然可以继续解析 BTF 并继续在某个程度上正常工作。这似乎是一个有用的支持功能,因为它应该使我们的库更具前瞻性。这意味着我们的库将能够与未来的新内核一起工作,而无需强制性修补,只需在添加新 BTF 类型时继续工作。我们需要决定要支持/容忍未知类型的级别。"支持"有三个级别,按工作量/重构/重新设计的顺序列出如下: 1. 我们使用布局信息容忍未知的 BTF 类型。我们解析包含它们的 BTF,但用户无法使用未知类型。我们不在面向内核的 BTF 中序列化它们,并且通过 BTF 规范查询它们将导致错误。 2. 我们为"未知"类型添加了一个不透明类型,其中存储了从解析器到 BTF 编译器/编码器所需的所有信息。我们的编译器能够为支持它的内核发出包含布局信息的 BTF。这意味着"未知"类型可以成为类型图的部分,用于映射键/值或 CO-RE 重定位,但是由于我们不了解它们,这只适用于没有子类的叶类型。如果"未知"类型需要指向其他类型的有效指针,则生成的 BTF 将是错误的。 3. 当"未知"类型是我们希望加载到内核的 BTF 类型图的一部分时,我们将加载完整的 BTF 规范,因为它是以我们在 ELF 中看到的形式呈现的。这与当前情况相对,我们只进行最小的序列化。通过保留所有具有与原始编码时完全相同 ID 的类型,我们确保"未知"类型中的任何指针都保持有效。 选项 1 和 2 很容易实现。但是,选项 3 与我们当前处理 BTF 的方式有所不同。一方面,我们的目的是尽快更新库,以了解新添加的 BTF 类型。另一方面,我们希望在内核加载的 BTF 类型图中加载完整的 BTF 规范,因为它是以我们在 ELF 中看到的形式呈现的。与当前情况相比,我们只进行最小的序列化。通过保留所有具有与原始编码时完全相同 ID 的类型,我们确保"未知"类型中的任何指针都保持有效。
内容来源: cilium/ebpf