编辑推荐
1. 软件调试领域的“百科全书”,围绕软件调试的“生态”系统(ecosystem)、异常(exception)和调试器三条主线,介绍软件调试的相关原理和机制,探讨可调试性(debuggability)的内涵、意义,以及实现软件可调试性的原则和方法,总结软件调试的方法和技巧; 2. 设有“格物致知”实践环节,提供配套资源,可供读者动手实践; 3. 丰富的行业背景知识和人文故事,让读者体验技术的有血有肉、有感情有温度。 第2版卷1新增内容如下: ·关于CPU增加了ARM处理器的相关内容; ·关于操作系统增加了Linux系统的相关内容; ·关于编译器增加了GCC的相关内容; ·关于调试器增加了GDB的相关内容; ·增加了全新的GPU内容。
内容简介
本书堪称是软件调试的“百科全书”。作者围绕软件调试的“生态”系统(ecosystem)、异常(exception)和调试器 3 条主线,介绍软件调试的相关原理和机制,探讨可调试性(debuggability)的内涵、意义以及实现软件可调试性的原则和方法,总结软件调试的方法和技巧。 卷主要围绕硬件技术展开介绍。全书分为4篇,共16章。篇“绪论”(章),介绍了软件调试的概念、基本过程、分类和简要历史,并综述了本书后面将详细介绍的主要调试技术。第二篇“CPU及其调试设施”(第2~7章),以英特尔和ARM架构的CPU为例系统描述了CPU的调试支持。第三篇“GPU及其调试设施”(第8~14章),深入探讨了Nvidia、AMD、英特尔、ARM和Imagination 这五大厂商的GPU。第四篇“可调试性”(5~16章),介绍了提高软件可调试性的意义、基本原则、实例和需要注意的问题,并讨论了如何在软件开发实践中实现可调试性。 本书理论与实践紧密结合,既涵盖了相关的技术背景知识,又针对大量具有代表性和普遍意义的技术细节进行了讨论,是学习软件调试技术的宝贵资料。本书适合所有从事软件开发工作的读者阅读,特别适合从事软件开发、测试、支持的技术人员,从事反病毒、网络安全、版权保护等工作的技术人员,以及高等院校相关专业的教师和学生学习参考。
作者简介
张银奎,靠前知名的调试技术专家。毕业于上海交通大学信息与控制工程系,长期从事软件开发和研究工作,曾在英特尔工作13 年,对 IA-32 架构、操作系统内核、驱动程序,尤其是对软件调试有较深入的研究。著有《软件调试》《格蠹汇编》等畅销、常销技术图书, 格蠹科技(xedge.ai) 创始人,高端调试网站(advdbg.org)创建者。翻译(合译)作品有《二十一世纪机器人》《观止——微软创建NT和未来的夺命狂奔》《数据挖掘原理》《机器学习》《人工智能:复杂问题求解的结构和策略》等。
目录
- 第 一篇 绪论
- 第 1章 软件调试基础 3
- 1.1 简介 3
- 1.1.1 定义 3
- 1.1.2 基本过程 5
- 1.2 基本特征 5
- 1.2.1 难度大 6
- 1.2.2 难以估计完成时间 7
- 1.2.3 广泛的关联性 7
- 1.3 简要历史 8
- 1.3.1 单步执行 8
- 1.3.2 断点指令 10
- 1.3.3 分支监视 11
- 1.4 分类 12
- 1.4.1 按调试目标的系统环境分类 12
- 1.4.2 按目标代码的执行方式分类 12
- 1.4.3 按目标代码的执行模式分类 13
- 1.4.4 按软件所处的阶段分类 13
- 1.4.5 按调试器与调试目标的相对位置分类 14
- 1.4.6 按调试目标的活动性分类 14
- 1.4.7 按调试工具分类 15
- 1.5 调试技术概览 15
- 1.5.1 断点 15
- 1.5.2 单步执行 16
- 1.5.3 输出调试信息 17
- 1.5.4 日志 17
- 1.5.5 事件追踪 17
- 1.5.6 转储文件 18
- 1.5.7 栈回溯 18
- 1.5.8 反汇编 18
- 1.5.9 观察和修改内存数据 19
- 1.5.10 控制被调试进程和线程 19
- 1.6 错误与缺欠 19
- 1.6.1 内因与表象 19
- 1.6.2 谁的bug 20
- 1.6.3 bug的生命周期 21
- 1.6.4 软件错误的开支曲线 21
- 1.7 重要性 23
- 1.7.1 调试与编码的关系 23
- 1.7.2 调试与测试的关系 24
- 1.7.3 调试与逆向工程的关系 24
- 1.7.4 学习调试技术的意义 25
- 1.7.5 调试技术尚未得到应有的重视 25
- 1.8 本章小结 26
- 参考资料 26
- *二篇 CPU及其调试设施
- 第 2章 CPU基础 29
- 2.1 指令和指令集 29
- 2.1.1 基本特征 30
- 2.1.2 寻址方式 31
- 2.1.3 指令的执行过程 32
- 2.2 英特尔架构处理器 33
- 2.2.1 80386处理器 34
- 2.2.2 80486处理器 34
- 2.2.3 奔腾处理器 35
- 2.2.4 P6系列处理器 36
- 2.2.5 奔腾4处理器 38
- 2.2.6 Core 2系列处理器 38
- 2.2.7 Nehalem微架构 39
- 2.2.8 Sandy Bridge微架构 39
- 2.2.9 Ivy Bridge微架构 40
- 2.2.10 Haswell微架构 40
- 2.2.11 Broadwell微架构 41
- 2.2.12 Skylake微架构 41
- 2.2.13 Kaby Lake微架构 41
- 2.3 CPU的操作模式 42
- 2.4 寄存器 44
- 2.4.1 通用数据寄存器 44
- 2.4.2 标志寄存器 45
- 2.4.3 MSR寄存器 46
- 2.4.4 控制寄存器 46
- 2.4.5 其他寄存器 48
- 2.4.6 64位模式时的寄存器 49
- 2.5 理解保护模式 50
- 2.5.1 任务间的保护机制 50
- 2.5.2 任务内的保护 51
- 2.5.3 特权级 52
- 2.5.4 特权指令 53
- 2.6 段机制 54
- 2.6.1 段描述符 54
- 2.6.2 描述符表 56
- 2.6.3 段选择子 56
- 2.6.4 观察段寄存器 57
- 2.7 分页机制 59
- 2.7.1 32位经典分页 60
- 2.7.2 PAE分页 66
- 2.7.3 IA-32e分页 68
- 2.7.4 大内存页 71
- 2.7.5 WinDBG的有关命令 72
- 2.8 PC系统概貌 73
- 2.9 ARM架构基础 75
- 2.9.1 ARM的多重含义 75
- 2.9.2 主要版本 76
- 2.9.3 操作模式和状态 78
- 2.9.4 32位架构核心寄存器 80
- 2.9.5 协处理器 82
- 2.9.6 虚拟内存管理 83
- 2.9.7 伪段支持 87
- 2.9.8 64位ARM架构 88
- 2.10 本章小结 90
- 参考资料 90
- 第3章 中断和异常 91
- 3.1 概念和差异 91
- 3.1.1 中断 91
- 3.1.2 异常 93
- 3.1.3 比较 93
- 3.2 异常的分类 93
- 3.2.1 错误类异常 93
- 3.2.2 陷阱类异常 94
- 3.2.3 中止类异常 95
- 3.3 异常例析 95
- 3.3.1 列表 95
- 3.3.2 错误代码 97
- 3.3.3 示例 97
- 3.4 中断/异常的优先级 99
- 3.5 中断/异常处理 100
- 3.5.1 实模式 100
- 3.5.2 保护模式 101
- 3.5.3 IA-32e模式 109
- 3.6 ARM架构中的异常机制 110
- 3.7 本章小结 112
- 参考资料 113
- 第4章 断点和单步执行 114
- 4.1 软件断点 114
- 4.1.1 INT 3 114
- 4.1.2 在调试器中设置断点 115
- 4.1.3 断点命中 116
- 4.1.4 恢复执行 118
- 4.1.5 特殊用途 118
- 4.1.6 断点API 119
- 4.1.7 系统对INT 3的优待 119
- 4.1.8 观察调试器写入的INT 3指令 121
- 4.1.9 归纳和提示 122
- 4.2 硬件断点 123
- 4.2.1 调试寄存器概览 123
- 4.2.2 调试地址寄存器 124
- 4.2.3 调试控制寄存器 124
- 4.2.4 指令断点 127
- 4.2.5 调试异常 127
- 4.2.6 调试状态寄存器 128
- 4.2.7 示例 129
- 4.2.8 硬件断点的设置方法 132
- 4.2.9 归纳 134
- 4.3 陷阱标志 135
- 4.3.1 单步执行标志 135
- 4.3.2 *级语言的单步执行 136
- 4.3.3 任务状态段陷阱标志 138
- 4.3.4 按分支单步执行标志 138
- 4.4 实模式调试器例析 140
- 4.4.1 Debug.exe 140
- 4.4.2 8086 Monitor 142
- 4.4.3 关键实现 143
- 4.5 反调试示例 145
- 4.6 ARM架构的断点支持 147
- 4.6.1 断点指令 148
- 4.6.2 断点寄存器 149
- 4.6.3 监视点寄存器 153
- 4.6.4 单步跟踪 155
- 4.7 本章小结 156
- 参考资料 157
- 第5章 分支记录和性能监视 158
- 5.1 分支监视概览 159
- 5.2 使用寄存器的分支记录 159
- 5.2.1 LBR 160
- 5.2.2 LBR栈 161
- 5.2.3 示例 161
- 5.2.4 在Windows操作系统中的应用 165
- 5.3 使用内存的分支记录 166
- 5.3.1 DS区 166
- 5.3.2 启用DS机制 168
- 5.3.3 调试控制寄存器 168
- 5.4 DS示例:CpuWhere 169
- 5.4.1 驱动程序 170
- 5.4.2 应用界面 173
- 5.4.3 2.0版本 175
- 5.4.4 局限性和扩展建议 178
- 5.4.5 Linux内核中的BTS驱动 179
- 5.5 性能监视 180
- 5.5.1 奔腾处理器的性能监视机制 181
- 5.5.2 P6处理器的性能监视机制 182
- 5.5.3 P4处理器的性能监视 183
- 5.5.4 架构性的性能监视机制 186
- 5.5.5 酷睿微架构处理器的性能监视机制 187
- 5.5.6 资源 188
- 5.6 实时指令追踪 188
- 5.6.1 工作原理 189
- 5.6.2 RTIT数据包 190
- 5.6.3 Linux支持 191
- 5.7 ARM架构的性能监视设施 192
- 5.7.1 PMUv1和PMUv2 192
- 5.7.2 PMUv3 194
- 5.7.3 示例 194
- 5.7.4 CoreSight 195
- 5.8 本章小结 195
- 参考资料 195
- 第6章 机器检查架构 196
- 6.1 奔腾处理器的机器检查机制 196
- 6.2 MCA 198
- 6.2.1 概览 198
- 6.2.2 MCA的全局寄存器 199
- 6.2.3 MCA的错误报告寄存器 201
- 6.2.4 扩展的机器检查状态寄存器 202
- 6.2.5 MCA错误编码 203
- 6.3 编写MCA软件 205
- 6.3.1 基本算法 205
- 6.3.2 示例 207
- 6.3.3 在Windows系统中的应用 208
- 6.3.4 在Linux系统中的应用 210
- 6.4 本章小结 212
- 参考资料 212
- 第7章 JTAG调试 213
- 7.1 简介 213
- 7.1.1 ICE 213
- 7.1.2 JTAG 214
- 7.2 JTAG原理 215
- 7.2.1 边界扫描链路 215
- 7.2.2 TAP信号 216
- 7.2.3 TAP寄存器 217
- 7.2.4 TAP控制器 217
- 7.2.5 TAP指令 218
- 7.3 JTAG应用 219
- 7.3.1 JTAG调试 220
- 7.3.2 调试端口 221
- 7.4 IA处理器的JTAG支持 221
- 7.4.1 P6处理器的JTAG实现 221
- 7.4.2 探测模式 223
- 7.4.3 ITP接口 223
- 7.4.4 XDP端口 225
- 7.4.5 ITP-XDP调试仪 226
- 7.4.6 直接连接接口 226
- 7.4.7 典型应用 227
- 7.5 ARM处理器的JTAG支持 227
- 7.5.1 ARM调试接口 228
- 7.5.2 调试端口 228
- 7.5.3 访问端口 229
- 7.5.4 被调试器件 229
- 7.5.5 调试接插口 229
- 7.5.6 硬件调试器 231
- 7.5.7 DS-5 232
- 7.6 本章小结 232
- 参考资料 233
- 第三篇 GPU及其调试设施
- 第8章 GPU基础 237
- 8.1 GPU简史 237
- 8.1.1 从显卡说起 237
- 8.1.2 硬件加速 239
- 8.1.3 可编程和通用化 240
- 8.1.4 三轮演进 242
- 8.2 设备身份 243
- 8.2.1 “喂模式” 243
- 8.2.2 内存复制 243
- 8.2.3 超时检测和复位 243
- 8.2.4 与CPU之并立 243
- 8.3 软件接口 244
- 8.3.1 设备寄存器 244
- 8.3.2 批命令缓冲区 245
- 8.3.3 状态模型 245
- 8.4 GPU驱动模型 247
- 8.4.1 WDDM 247
- 8.4.2 DRI和DRM 249
- 8.5 编程技术 250
- 8.5.1 着色器 250
- 8.5.2 Brook和CUDA 251
- 8.5.3 OpenCL 252
- 8.6 调试设施 252
- 8.6.1 输出调试信息 253
- 8.6.2 发布断点 253
- 8.6.3 其他断点 254
- 8.6.4 单步执行 254
- 8.6.5 观察程序状态 254
- 8.7 本章小结 254
- 参考资料 255
- 第9章 Nvidia GPU及其调试设施 256
- 9.1 概要 256
- 9.1.1 一套微架构 256
- 9.1.2 三条产品线 256
- 9.1.3 封闭 257
- 9.2 微架构 257
- 9.2.1 G80(特斯拉1.0微架构) 257
- 9.2.2 GT200(特斯拉2.0微架构) 259
- 9.2.3 GF100(费米微架构) 260
- 9.2.4 GK110(开普勒微架构) 261
- 9.2.5 GM107(麦斯威尔微架构) 263
- 9.2.6 GP104(帕斯卡微架构) 263
- 9.2.7 GV100(伏特微架构) 265
- 9.2.8 持续改进 267
- 9.3 硬件指令集 268
- 9.3.1 SASS 269
- 9.3.2 指令格式 270
- 9.3.3 谓词执行 270
- 9.3.4 计算能力 271
- 9.3.5 GT200的指令集 271
- 9.3.6 GV100的指令集 274
- 9.4 PTX指令集 279
- 9.4.1 汇编和反汇编 280
- 9.4.2 状态空间 282
- 9.4.3 虚拟寄存器 283
- 9.4.4 数据类型 284
- 9.4.5 指令格式 284
- 9.4.6 内嵌汇编 285
- 9.5 CUDA 286
- 9.5.1 源于Brook 286
- 9.5.2 算核 286
- 9.5.3 执行配置 288
- 9.5.4 内置变量 290
- 9.5.5 Warp 291
- 9.5.6 显式并行 292
- 9.6 异常和陷阱 293
- 9.6.1 陷阱指令 293
- 9.6.2 陷阱后缀 293
- 9.6.3 陷阱处理 293
- 9.7 系统调用 296
- 9.7.1 vprintf 296
- 9.7.2 malloc和free 297
- 9.7.3 __assertfail 298
- 9.8 断点指令 299
- 9.8.1 PTX的断点指令 299
- 9.8.2 硬件的断点指令 300
- 9.9 Nsight的断点功能 301
- 9.9.1 源代码断点 301
- 9.9.2 函数断点 301
- 9.9.3 根据线程组和线程编号设置条件断点 302
- 9.10 数据断点 304
- 9.10.1 设置方法 304
- 9.10.2 命中 304
- 9.10.3 数量限制 306
- 9.10.4 设置时机 306
- 9.11 调试符号 306
- 9.11.1 编译选项 306
- 9.11.2 ELF载体 306
- 9.11.3 DWARF 307
- 9.12 CUDA GDB 307
- 9.12.1 通用命令 307
- 9.12.2 扩展 308
- 9.12.3 局限 308
- 9.13 CUDA调试器API 308
- 9.13.1 头文件 309
- 9.13.2 调试事件 309
- 9.13.3 工作原理 310
- 9.14 本章小结 312
- 参考资料 312
- 第 10章 AMD GPU及其调试设施 314
- 10.1 演进简史 314
- 10.1.1 三个发展阶段 314
- 10.1.2 两种产品形态 315
- 10.2 Terascale微架构 315
- 10.2.1 总体结构 315
- 10.2.2 SIMD核心 317
- 10.2.3 VLIW 317
- 10.2.4 四类指令 318
- 10.3 GCN微架构 318
- 10.3.1 逻辑结构 319
- 10.3.2 CU和波阵 319
- 10.3.3 内存层次结构 321
- 10.3.4 工作组 321
- 10.3.5 多执行引擎 323
- 10.4 GCN指令集 323
- 10.4.1 7种指令类型 323
- 10.4.2 指令格式 324
- 10.4.3 不再是VLIW指令 324
- 10.4.4 指令手册 324
- 10.5 编程模型 325
- 10.5.1 地幔 325
- 10.5.2 HSA 326
- 10.5.3 ROCm 326
- 10.5.4 Stream SDK和APP SDK 327
- 10.5.5 Linux系统的驱动 327
- 10.6 异常和陷阱 327
- 10.6.1 9种异常 328
- 10.6.2 启用 328
- 10.6.3 陷阱状态寄存器 328
- 10.6.4 陷阱处理器基地址 329
- 10.6.5 陷阱处理过程 329
- 10.7 控制波阵的调试接口 330
- 10.7.1 5种操作 330
- 10.7.2 指定目标 330
- 10.7.3 发送接口 331
- 10.7.4 限制 332
- 10.8 地址监视 332
- 10.8.1 4种监视模式 332
- 10.8.2 数量限制 333
- 10.8.3 报告命中 333
- 10.8.4 寄存器接口 333
- 10.8.5 用户空间接口 333
- 10.9 单步调试支持 333
- 10.9.1 单步调试模式 334
- 10.9.2 控制方法 334
- 10.10 根据调试条件实现分支跳转的指令 335
- 10.10.1 两个条件标志 335
- 10.10.2 4条指令 335
- 10.11 代码断点 335
- 10.11.1 陷阱指令 336
- 10.11.2 在GPU调试SDK中的使用 336
- 10.12 GPU调试模型和开发套件 337
- 10.12.1 组成 337
- 10.12.2 进程内调试模型 337
- 10.12.3 面向事件的调试接口 339
- 10.13 ROCm-GDB 340
- 10.13.1 源代码 340
- 10.13.2 安装和编译 340
- 10.13.3 常用命令 340
- 10.14 本章小结 341
- 参考资料 342
- 第 11章 英特尔GPU及其调试设施 343
- 11.1 演进简史 343
- 11.1.1 i740 343
- 11.1.2 集成显卡 344
- 11.1.3 G965 345
- 11.1.4 Larabee 345
- 11.1.5 GPU 346
- 11.1.6 第三轮努力 347
- 11.1.7 公开文档 347
- 11.2 GEN微架构 348
- 11.2.1 总体架构 349
- 11.2.2 片区布局 350
- 11.2.3 子片布局 351
- 11.2.4 EU 352
- 11.2.5 经典架构图 353
- 11.3 寄存器接口 354
- 11.3.1 两大类寄存器 354
- 11.3.2 显示功能的寄存器 355
- 11.4 命令流和环形缓冲区 357
- 11.4.1 命令 357
- 11.4.2 环形缓冲区 358
- 11.4.3 环形缓冲区寄存器 359
- 11.5 逻辑环上下文和执行列表 360
- 11.5.1 LRC 360
- 11.5.2 执行链表提交端口 362
- 11.5.3 理解LRC的提交和执行过程 362
- 11.6 GuC和通过GuC提交任务 365
- 11.6.1 加载固件和启动GuC 365
- 11.6.2 以MMIO方式通信 366
- 11.6.3 基于共享内存的命令传递机制 367
- 11.6.4 提交工作任务 367
- 11.7 媒体流水线 368
- 11.7.1 G965的媒体流水线 368
- 11.7.2 MFX引擎 370
- 11.7.3 状态模型 370
- 11.7.4 多种计算方式 371
- 11.8 EU指令集 372
- 11.8.1 寄存器 372
- 11.8.2 寄存器区块 373
- 11.8.3 指令语法 375
- 11.8.4 VLIW和指令级别并行 375
- 11.9 内存管理 377
- 11.9.1 GGTT 377
- 11.9.2 PPGTT 378
- 11.9.3 I915和GMMLIB 379
- 11.10 异常 379
- 11.10.1 异常类型 379
- 11.10.2 系统过程 380
- 11.11 断点支持 381
- 11.11.1 调试控制位 381
- 11.11.2 操作码匹配断点 381
- 11.11.3 IP匹配断点 381
- 11.11.4 初始断点 382
- 11.12 单步执行 382
- 11.13 GT调试器 382
- 11.13.1 架构 382
- 11.13.2 调试事件 384
- 11.13.3 符号管理 385
- 11.13.4 主要功能 385
- 11.13.5 不足 385
- 11.14 本章小结 386
- 参考资料 386
- 第 12章 Mali GPU及其调试设施 387
- 12.1 概况 387
- 12.1.1 源于挪威 387
- 12.1.2 纳入ARM 387
- 12.1.3 三代微架构 388
- 12.1.4 发货*多的图形处理器 388
- 12.1.5 精悍的团队 389
- 12.1.6 封闭的技术文档 389
- 12.1.7 单元化设计 389
- 12.2 Midgard微架构 389
- 12.2.1 逻辑结构 390
- 12.2.2 三流水线着色器核心 390
- 12.2.3 VLIW指令集 392
- 12.3 Bifrost微架构 393
- 12.3.1 逻辑结构 393
- 12.3.2 执行核心 394
- 12.3.3 标量指令集和Warp 395
- 12.4 Mali图形调试器 395
- 12.4.1 双机模式 395
- 12.4.2 面向帧调试 396
- 12.5 Gator 396
- 12.5.1 Gator内核模块(gator.ko) 397
- 12.5.2 Gator文件系统(gatorfs) 397
- 12.5.3 Gator后台服务(gatord) 398
- 12.5.4 Kbase驱动中的gator支持 399
- 12.5.5 含义 399
- 12.6 Kbase驱动的调试设施 399
- 12.6.1 GPU版本报告 399
- 12.6.2 编译选项 400
- 12.6.3 DebugFS下的虚拟文件 401
- 12.6.4 SysFS下的虚拟文件 401
- 12.6.5 基于ftrace的追踪设施 401
- 12.6.6 Kbase的追踪设施 402
- 12.7 其他调试设施 403
- 12.7.1 Caiman 403
- 12.7.2 devlib 404
- 12.7.3 Mali离线编译器 404
- 12.8 缺少的调试设施 405
- 12.8.1 GPGPU调试器 405
- 12.8.2 GPU调试SDK 406
- 12.8.3 反汇编器 406
- 12.8.4 ISA文档 406
- 12.9 本章小结 406
- 参考资料 406
- 第 13章 PowerVR GPU及其调试设施 407
- 13.1 概要 407
- 13.1.1 发展简史 407
- 13.1.2 两条产品线 409
- 13.1.3 基于图块延迟渲染 409
- 13.1.4 Intel GMA 409
- 13.1.5 开放性 410
- 13.2 Rogue微架构 410
- 13.2.1 总体结构 410
- 13.2.2 USC 411
- 13.2.3 ALU流水线 412
- 13.3 参考指令集 413
- 13.3.1 寄存器 414
- 13.3.2 指令组 414
- 13.3.3 指令修饰符 415
- 13.3.4 指令类型 415
- 13.3.5 标量指令 416
- 13.3.6 并行模式 416
- 13.4 软件模型和微内核 417
- 13.4.1 软件模型 417
- 13.4.2 微内核的主要功能 417
- 13.4.3 优点 418
- 13.4.4 存在的问题 418
- 13.5 断点支持 418
- 13.5.1 bpret指令 419
- 13.5.2 数据断点 419
- 13.5.3 ISP断点 420
- 13.6 离线编译和反汇编 420
- 13.6.1 离线编译 420
- 13.6.2 反汇编 421
- 13.7 PVR-GDB 421
- 13.7.1 跟踪调试 421
- 13.7.2 寄存器访问 422
- 13.7.3 其他功能 422
- 13.7.4 全局断点和局限性 422
- 13.8 本章小结 423
- 参考资料 423
- 第 14章 GPU综述 424
- 14.1 比较 424
- 14.1.1 开放性 424
- 14.1.2 工具链 425
- 14.1.3 *发者文档 425
- 14.2 主要矛盾 425
- 14.2.1 专用性和通用性 426
- 14.2.2 强硬件和弱软件 426
- 14.3 发展趋势 426
- 14.3.1 从固定功能单元到通用执行引擎 426
- 14.3.2 从向量指令到标量指令 427
- 14.3.3 从指令并行到线程并行 427
- 14.4 其他GPU 427
- 14.4.1 Adreno 428
- 14.4.2 VideoCore 428
- 14.4.3 图芯GPU 429
- 14.4.4 TI TMS34010 429
- 14.5 学习资料和工具 430
- 14.5.1 文档 430
- 14.5.2 源代码 430
- 14.5.3 工具 431
- 14.6 本章小结 432
- 参考资料 432
- 第四篇 可调试性
- 第 15章 可调试性概览 435
- 15.1 简介 435
- 15.2 观止和未雨绸缪 436
- 15.2.1 NT 3.1的故事 436
- 15.2.2 未雨绸缪 438
- 15.3 基本原则 439
- 15.3.1 *短距离原则 439
- 15.3.2 *小范围原则 439
- 15.3.3 立刻终止原则 440
- 15.3.4 可追溯原则 441
- 15.3.5 可控制原则 442
- 15.3.6 可重复原则 442
- 15.3.7 可观察原则 442
- 15.3.8 易辨识原则 443
- 15.3.9 低海森伯效应原则 443
- 15.4 不可调试代码 444
- 15.4.1 系统的异常分发函数 444
- 15.4.2 提供调试功能的系统函数 444
- 15.4.3 对调试器敏感的函数 445
- 15.4.4 反跟踪和调试的程序 445
- 15.4.5 时间敏感的代码 446
- 15.4.6 应对措施 446
- 15.5 可调试性例析 446
- 15.5.1 健康性检查和BSOD 447
- 15.5.2 可控制性 447
- 15.5.3 公开的符号文件 448
- 15.5.4 WER 448
- 15.5.5 ETW和日志 448
- 15.5.6 性能计数器 449
- 15.5.7 内置的内核调试引擎 449
- 15.5.8 手动触发崩溃 449
- 15.6 与安全、商业秘密和性能的关系 449
- 15.6.1 可调试性与安全性 450
- 15.6.2 可调试性与商业秘密 450
- 15.6.3 可调试性与性能 450
- 15.7 本章小结 450
- 参考资料 451
- 第 16章 可调试性的实现 452
- 16.1 角色和职责 452
- 16.1.1 架构师 452
- 16.1.2 程序员 453
- 16.1.3 测试人员 453
- 16.1.4 产品维护和技术支持工程师 454
- 16.1.5 管理者 454
- 16.2 可调试架构 455
- 16.2.1 日志 455
- 16.2.2 输出调试信息 456
- 16.2.3 转储 457
- 16.2.4 基类 458
- 16.2.5 调试模型 458
- 16.3 通过栈回溯实现可追溯性 459
- 16.3.1 栈回溯的基本原理 459
- 16.3.2 利用DbgHelp函数库回溯栈 461
- 16.3.3 利用RTL函数回溯栈 465
- 16.4 数据的可追溯性 466
- 16.4.1 基于数据断点的方法 466
- 16.4.2 使用对象封装技术来追踪数据变化 471
- 16.5 可观察性的实现 472
- 16.5.1 状态查询 472
- 16.5.2 WMI 473
- 16.5.3 性能计数器 475
- 16.5.4 转储 478
- 16.5.5 打印或者输出调试信息 479
- 16.5.6 日志 480
- 16.6 自检和自动报告 480
- 16.6.1 BIST 480
- 16.6.2 软件自检 481
- 16.6.3 自动报告 482
- 16.7 本章小结 482
- 参考资料 483