如何阅读本书
本书对一个文件进行逆向工程:
libtpu-0.0.40-cp314轮中的libtpu.so— 一个 781,691,048 字节 (745.5 MiB) ELF64 共享对象,构建 ID89edbbe81c5b328a958fe628a9f2207d(明确的锚点;运行时报告的0.103在二进制文件中不可静态验证,因此请固定到 build-id 和 Wheel0.0.40)。每个页面上的每个地址都是该二进制文件中的绝对虚拟地址,纯粹通过静态分析恢复。每个地址的另一个轮子都会有所不同。
摘要
libtpu.so 是 Google 的 TPU PJRT 插件 — 用于驱动 Cloud TPU 硬件的单个共享对象 JAX、PyTorch/XLA 和 TensorFlow 负载。它是 TPU 相当于 NVIDIA 的 libcuda.so + libnvrtc.so + ptxas 的设备一半,不同之处在于它不是瘦用户模式驱动程序,而是将整个堆栈静态链接到一个 blob 中:XLA 编译器、每种 TPU MLIR 方言、每代 LLO 后端、成本和调度模型、SparseCore 嵌入引擎、片上内存分配器、ICI/DCN 互连结构及其大多数第三方依赖项(libc++、Abseil、protobuf、Eigen、oneDNN、嵌入式 TCMalloc)。结果是一个文件中有 745 MiB 和大约 884,832 个函数。本书重构了该文件的工作原理。
重建“完全”来自二进制文件的静态逆向工程。这里没有源代码,没有运行时跟踪,没有任何声明背后的调试器会话——只有反汇编和反编译的主体,二进制文件自己的(未剥离的)符号表,以及一系列从它们索引的结构边车。每个页面都依赖这种单一出处规则,这也是每个页面固定其版本并将每个事实锚定到地址、偏移量、字符串或标志位的原因。此页面是其余部分的地图:这本书包含什么内容,它是为谁而写,十八个部分是如何排序的,为了给定的目标阅读哪些页面,典型的页面是什么样的,以及在哪里可以找到使锚点解析一目了然的约定。
首先阅读此页面,然后在其旁边打开两个同伴:证据和置信约定 用于“信任程度”任何给定的声明,代号备忘单 用于硅命名,因为几乎每个深层页面都会按 TPU 代索引一些事实,并且各代至少有七个不同的名称。
为了浏览本书,合同是:
- 一个二进制文件,一个出处。 每个计数、地址和偏移量都会跟踪版本引脚中单个 ELF 的静态分析。运行图书馆不会产生任何影响;没有任何内容来自任何源树。
- 按依赖顺序读取,而不是重要性顺序。 这十八个部分遵循数据自己的依赖链 - 芯片 → 编译器 → ISA → 成本 → 调度 → 引擎 → 内存 → 运行时 → 结构 → 可观察性 → 配置 - 因此每个部分仅假设其之前的部分。
- 置信度已发布,而非假设。 表带有置信度列;散文带有内联等级。评级为
Inferred的声明是为您指明方向的脚手架,而不是构建的基础。
| 主题二进制 | libtpu/libtpu.so(在 cp314 Manylinux 轮中),781,691,048 B (745.5 MiB) |
| 构建 ID | 89edbbe81c5b328a958fe628a9f2207d (NT_GNU_BUILD_ID) |
| 报告版本 | 轮子 0.0.40(由 build-id 固定);运行时报告的 0.103 在二进制文件中不可静态验证 - 固定到构建 ID,这是明确的 |
| 这是什么 | Google TPU PJRT 插件 — 编译器 + 运行时 + 驱动程序 + 结构在一个对象中 |
| 恢复功能 | 884,832(881,784 名命名/3,048 名匿名;~93% 已解密) |
| 精灵形状 | 52段,11个程序头,4×PT_LOAD;入口点 0x0(库) |
| 同级对象 | sdk.so — 同一轮中独立的、小得多的支持库 |
| 出处 | 100%静态逆向工程;没有源代码,没有运行时,没有调试器 |
| 结构 | 18 部分 (0–XVII);按以下顺序阅读 |
这本书是什么
每个页面的标准是重新实现等级:从未打开过此二进制文件的有能力的系统或编译器工程师应该能够仅从页面重建记录的组件 - 算法、数据布局、位编码、决策逻辑 - 并告诉哪些部分是确定的,哪些部分是推断的。这是比“解释它的作用”更高的标准,它塑造了一切:页面倾向于带注释的伪代码而不是反编译器转录,分派维度表而不是千行字节转储,以及基本原理(“为什么这是这样形成的”)而不是重述。
这本书不:它不是 JAX-on-TPU 的用户指南,不是应用程序作者的 API 文档,也不是反编译器输出的记录。它不会告诉您如何使用TPU;而是告诉您如何使用TPU;它告诉您驱动 TPU 的二进制文件是如何“构建”的,具体到捆绑位和成本表整数。
注意 — 二进制文件未剥离。大约 99.66% 的函数带有真实符号,约 93% 带有完整的分解的 C++ 名称,直接从对象自己的
.symtab中读取。因此,本书中的 C++ 标识符——xla::、asic_sw::driver::deepsea::、mlir::tpu::、TpuVersionToString——都是观察到的名称,而不是猜测的名称。如果一个名字“不在”二进制中(例如,营销代号“Trillium”和“Ironwood”),那么这本书就是这么说的,而不是发明它。
目标读者
Write-for-one-reader:高级系统或编译器工程师,熟悉 LLVM/MLIR、SSA、ELF 内部结构和 VLIW ISA 编码,想要重新实现级详细信息并愿意验证针对二进制文件的声明。如果您知道什么是 LoopInfo、SelectionDAG、保留表、模数时间表和重定位,那么本书会用您的语言进行讲解;它将每个未知的 TPU 机制教导为与最接近的已知机制的“增量”。只想调用 PJRT API 的读者会发现第二部分至第三部分很有用,而其余部分则比他们需要的要深入得多。
两个二进制事实
轮子运送两个 ELF 对象,它们不是同一件事。 libtpu.so(本书的主题)是 745 MiB PJRT 插件;它静态嵌入整个 C++ 运行时,并且不链接外部 libstdc++。它的兄弟 sdk.so 是一个独立的、小得多的 CPython 扩展/支持库,它确实动态需要 libstdc++ 并带有 protobuf/absl-heavy、libtpu::sdk / tpu::monitoring 命名空间表面。分析涵盖了两者,但本书的绝大多数内容是 libtpu.so;将任何不合格的“二进制文件”视为 libtpu.so。分裂的起源——为什么有两个对象以及符号如何在它们之间流动——由 libtpu.so + sdk.so 所有。
十八部分
本书分为十八个部分(0 到 XVII),顺序为 摘要.md。该顺序是数据自己的依赖链:硅模型参数化编译器,编译器发出 ISA,ISA 有成本,成本驱动调度,等等向外到结构和配置表面。从上到下阅读,每个部分仅假定其之前的部分;一旦确定方向,就可以自由跳跃。
| 零件 | 主题 | 从这里开始 |
|---|---|---|
| 0 — 参考装置 | 方向、证据规则、代号、术语表——结缔组织。 | 编译流程演练 |
| I — 二进制解剖 | 745 MiB ELF:节、段、嵌入式库、调度表、RTTI。 | 取证概述 |
| II — 插件生命周期和 PJRT API | 插件如何加载,以及 JAX/PyTorch 使用的 140 槽 PJRT_Api 结构。 | 生命周期概述 |
| III — Tpu C 垫片层 | PJRT 和 C++ 编译器/运行时之间的内部 Tpu* C ABI。 | 垫片概述 |
| IV — 芯片和硬件代号模型 | 整个编译器参数化的六代 TPU。 | 目标概述 |
| V — 编译器:降低和优化通过 | IR 下降(HLO → MHLO → tpu → LLO)和优化过程。 | 编译器概述 |
| VI — TensorCore ISA 和 LLO 编码 | 462 操作码 LLO IR 和每代 VLIW 捆绑位布局。 | ISA 概述 |
| VII — 成本和延迟模型 | 每条指令的成本 - 二进制中最大的数据表面。 | 成本概览 |
| VIII — 指令调度和捆绑打包 | 使用成本模型并发出有序的打包包的算法。 | 调度概述 |
| IX — SparseCore 和 BarnaCore | 嵌入/稀疏引擎(v5+)及其退役的前身保持完整。 | SparseCore 概述 |
| X — 片上内存和 DMA | HBM/VMEM/SMEM/CMEM 分配器和片内 DMA 描述符。 | 内存概述 |
| XI — 运行时和执行 | 在流上加载并执行已编译的程序。 | 运行时概述 |
| XII — 互连和路由 | ICI 结构和环形-圆环路由求解器。 | ICI 概述 |
| XIII — Pod 上的集体和障碍 | 全减少/全聚集策略和 SFLAG 屏障机械。 | 集体概述 |
| XIV — 超大规模(多主机/DCN) | 多主机引导、队列元数据和跨主机结构。 | 超大规模概述 |
| XV — 分析和遥测 | XSpace/XPlane 跟踪管道和设备遥测模式。 | 分析概述 |
| XVI — 配置和编译旋钮 | xla_* 标志图集、环境变量和编译环境原型。 | 配置概述 |
| 十七 — 附录 | 大型枚举目录(操作码表、内部表、索引)。 | Llo操作码表 |
注意 — 编译器后端故意沿着规范的什么/成本/如何接缝分为三个部分:VI 是存在哪些指令,VII 是它们的成本,VIII 是如何订购和打包它们。在这个二进制文件中,成本模型数据是调度算法数量的几倍,因此将它们合并起来会产生一个难以理解的怪物。相比之下,SparseCore (IX) 是完整的,而不是被分割开来的——它是读者想要的一个独立的引擎。
阅读路径
您很少需要全部 426 页。选择符合您目标的道路;每个部分都是一条简短的有序路线。每条路径都假设您已阅读 证据和置信约定 并且手头有 代号备忘单。
“我只是想确定方向”
从第 0 部分开始,然后浏览两个地图页面。最快的入口是 编译流程演练 - 它通过每个部分端到端跟踪一个 dot 操作,并告诉您哪个深层页面拥有每个阶段。接下来是 子系统图(依赖项 Web)和 取证概述(文件是什么),然后深入了解硅模型的第四部分。
“我想了解编译管道”
按IR顺序读取编译器堆栈:HLO 摄取 → 编译阶段 0–3 → MHLO → XTile → tpu → tpu → LLO 降低,其中HLO 通证注册表为pass框架。然后进入第六部分,了解它发出的 LLO 实际编码的内容。
“我想要 ISA/捆绑字节”
直接进入第六部分。从 ISA 概述 和 LloOpcode 枚举 (462) 开始,了解 捆绑型号,然后阅读目标的每代捆绑包页面(例如 Viperfish 64 字节捆绑包)和每插槽编码页面。操作码和内在目录位于第 XVII 部分:Llo操作码表 (462)、LlvmTpu 内在表 (1356)。
“我想重新实现成本模型/调度程序”
按依赖顺序读取:第 IV 部分为每个代号硅常量 → 第 VI 部分为 ISA → 第 VII 部分为成本数据(成本概览 首先)→ 第 VIII 部分为调度算法 (调度概述)。合并的每代整数位于 每代主控比较矩阵 中。
“我想要 TPU 到 TPU 集体/多主机”
第 IV 部分 → 第 XII 部分(结构 + 路由,从 ICI 概述 开始)→ 第 XIII 部分(集体算法和障碍)→ 第 XIV 部分(多主机/DCN 故事)。
“我想编写或调试 PJRT 消费者”
第二部分用于 PJRT_Api 140槽位重构 和 延长链 (17),第三部分用于其调用的 Tpu C 垫片,第 XI 部分用于执行,第 XV 部分用于分析。
“我想导航二进制文件本身”
第一部分是取证地图。 取证概述 建立容器形状; 精灵解剖走每一段,VA==偏移规则; 调度表分类和RTTI ↔ Vtable 交叉验证解释了如何读取40,313个数据表和160,351个RTTI记录。与 方法论 配对用于提取管道。
注意 — 这本书主要是针对每一代人的。要端到端跟踪一个硅系列,请使用 登陆页面 上的每代交叉索引:它在单行中为每个
TpuVersion0–5 提供系列页面 (IV)、ISA 捆绑包页面 (VI)、MXU 延迟页面和性能网格 (VII)。
页面剖析与约定
每个深层页面都是以相同的方式构建的,因此您只需学习一次形状,然后就可以通过条件反射导航每个页面。开头是一份合同:在概览表的末尾,您知道该组件是什么、它固定到什么版本以及您将能够重新实现什么。
页面骨架
# Title ← a plain noun phrase, one per page
> version-pin blockquote ← fixes the binary so every address is unambiguous
## Abstract ← 2–3 paragraphs of orientation; relates to a known frame
reimplementation contract ← bullets: what a reimplementer must reproduce
at-a-glance table ← the hard anchors: entry points, addresses, sizes, IR level
## <Unit 1> ← one structural unit (a phase, engine, slot, pass)
### Purpose / Entry Point / Algorithm / Function Map / Considerations
--- ← horizontal rule between top-level units
## <Unit 2> …
## Cross-References ← link list, each with a one-line why, closes the page
```text
页面内的兄弟单元以相同的顺序共享相同的 `###` 词汇表 - `Purpose`、`Entry Point`、`Algorithm`(带注释的伪代码,不是原始反编译器输出)、`Function Map`(带有置信度列的表)、 `Considerations`。读者扫描“如何做出决定”时,总会在 `### Algorithm` 下找到它。
### 置信度和标注
因为这是逆向工程,所以每个页面都诚实地说明*二进制文件如何直接支持每个声明*。逆向工程表带有**置信度**列,散文带有内联等级。该量表对证据的直接性而不是合理性进行评分:
| 级 | 含义 |
|---|---|
| **高**(或 **CERTAIN** 对于字节检查计数) | 直接从反编译体或字节精确表中读取。逐字信任。 |
| **中** | 从几个一致的间接指标(调用者、字符串、表位置)推断出来。 |
| **低** | 单一弱指标,无佐证。一个线索,而不是一个事实。 |
| **推断** | 从结构或类比推理,没有直接字节。仅针对方向的假设。 |
标注是带有粗体文本标记的块引号 - 绝不是表情符号。 `> **QUIRK —**` 标记了一个反直觉的事实; `> **GOTCHA —**` 标记了一个陷阱,其中幼稚的实现默默地错误; `> **NOTE —**` 标记澄清; `> **CORRECTION —**` 在先前读取的二进制文件出错的地方记录正确的值,而不是默默地编辑错误。完整的定义——四个等级、标注词汇、引文语法和已知的提取限制——是 [证据和置信约定](evidence-conventions.md) 的主题。阅读该页一次,其他地方的每个标签都带有精确的、预先商定的含义。
> **明白了 —** 分解后的符号名称描述了原作者*命名*函数的内容,不一定是该函数在此构建中执行的操作。当名称与其反编译的主体不一致时,本书会遵循**主体**并标记差异。仅凭名字提出的主张永远不会超越 `Low`;不要将友好的符号视为行为证明。
### 引文语法
锚点遵循一种小的、固定的语法,因此它们可以立即解析。地址是十六进制的绝对虚拟地址(`0xfe21da0`、`sub_E635524`);裸 `sub_ADDR` 是匿名函数的占位符。结构体字段被引用为基址+偏移量(`ctx+0x10`、`Target+0x628`),因为二进制文件没有字段名称 - 偏移量*是*字段的标识。表、开关和字符串由锚点地址以及相关的索引或文字文本引用。所有这一切背后的规则是:每个声明都指向具有相同二进制文件的读者可以独立找到的东西。
---
## 第一站
在任何深入的页面之前,三部分第 0 部分值得一读,另外两页是您将返回的永恒伴侣。
- **[代号备忘单](codename-cheatsheet.md)** — 返回的一张牌。单个 TPU 代在不共享编号的三个独立整数轴(`TpuVersion` 0–5、`DeviceType` 1–13、`TpuVersionProto` 1–6)上至少有七个名称。此页面将每一代的每个名称并排固定到定义它的二进制站点,并警告有关不合一的信息 - 包括 `DeviceType` 12 比 13 *新*。
- **[证据和置信约定](evidence-conventions.md)** — 校准页面。四个置信度级别、标注标记、引文风格,以及最重要的静态分析在结构上“无法”恢复的内容,因此您知道底线在哪里。
- **[方法论](../methodology.md)** — 分析的执行方式:提取管道、IDA sidecar(`functions`、`names`、`strings`、`rtti`、`switches`、`xrefs`、 ...),以及每个页面继承的命名约定。
- **[子系统图](../subsystem-map.md)** — 依赖网络,解释了“为什么”这十八个部分按它们的顺序排列,以及每个部分涵盖哪些域。
- **[术语表](../glossary.md)** — 本书假定的 TPU 词汇:LLO、MXU、XLU、EUP、SCS/TAC/TEC、MRB、SFLAG、ICI/DCN、HBM/VMEM/SMEM/CMEM 等。第一次阅读任何深度页面时请保持打开状态。
以及两张用于扩展的结构图:
- **[取证概述](../forensics/overview.md)** — 745 MiB 文件的经过验证的顶级形状:部分/段普查、功能总体和主要嵌入区域的胶囊图集。每个页面上重复使用的标题数字的来源。
- **[编译流程演练](compile-flow-walkthrough.md)** — 单一最佳入口:从 HLO 跟踪到捆绑字节再到执行的一个 matmul,同时交叉引用每个部分。
> **注意 —** 本书中的每一页尚未写完。索引跟踪状态:标记为*(已写入)*的页面有内容;其余的是等待创作的脚手架存根,未恢复的主题在 [开放边境寄存器](../appendix/open-frontier-register.md) 中进行跟踪。存根链接仍然是一个有效的目的地——它只是意味着深层内容仍在管道中。
---
## 交叉引用
- [证据和置信约定](evidence-conventions.md) — 信任合约:四个置信度等级、标注标记、引文语法和提取限制。它的同伴是“相信多少”。
- [代号备忘单](codename-cheatsheet.md) — 硅命名卡;全书索引的三轴枚举调节。
- [方法论](../methodology.md) - 静态分析管道和每页引用的 sidecar 系列。
- [子系统图](../subsystem-map.md) — 零件订购背后的子系统依赖网络。
- [术语表](../glossary.md) — 深层页面采用的 TPU/LLO/fabric 词汇。
- [取证概述](../forensics/overview.md) — 规范的标题结构计数,根据原始二进制文件进行确认。
- [编译流程演练](compile-flow-walkthrough.md) — 一个操作跟踪每个部分;推荐先深度阅读。
- [libtpu内部结构(落地)](../index.md) — 主索引、每代交叉索引和完整页状态表。