当 Nginx 或 OpenResty 二进制被 strip 后,用 GDB 做 backtrace 会打印 No symbol table info available,火焰图里则塞满无用的 Unknown 帧。常规解法——安装 nginx-dbg 调试符号包、或用 -g 重新编译——并不总是可行。OpenResty XRay 通过机器学习从被 strip 的二进制中自动重建缺失的调试符号,从而恢复 C 函数和 Lua 函数的名称、源文件与源码行号。这一点在崩溃发生后尤为关键:被 strip 的 worker 进程一旦写出 core dump 文件,就无法再回头补装符号——而借助重建的符号,OpenResty XRay 依然可以自动分析该 core dump 文件,解析出完整的 C 与 Lua 调用栈。

下面我们完整演示:在不安装任何调试符号的前提下,如何端到端分析一个被 strip 过的 OpenResty 进程——包括 CPU 火焰图与 Lua 内存占用。而对于连 core dump 都解释不了的疑难崩溃,重建出的符号同样服务于更深入的取证手段,例如用录制回放在“第一现场”抓住 Nginx worker 崩溃

确认 Nginx 被 strip、调试符号缺失

ps 查看目标进程,确认可执行文件路径(示例为用户自己用源代码编译的 OpenResty)。

ps 查看进程与可执行路径

对主程序执行 file:输出表明二进制已被 strip,没有任何调试符号或符号表。也找不到该程序对应的调试符号安装包。

主程序 file 输出:已 strip

对进程加载的 LuaJIT 动态链接库同样执行 file,可见 LuaJIT 文件的调试符号也是缺失的。

LuaJIT 库 file 输出

自动重建缺失的 Nginx 调试符号——无需重新编译

在浏览器打开 OpenResty XRay 控制台,进入 Guided Analysis,按向导选择要分析的问题类型、目标应用与 worker 进程,语言级别保持 LuaC/C++ 同时选中后开始分析。控制台入口与向导页如下(具体选项组合见视频)。

Guided Analysis 向导

分析开始后,XRay 会检测缺失的调试符号并 自动发起符号重建;重建完成后,会像平常一样并行运行各类分析器。

符号重建任务进行中

结束采样后,界面会生成汇总报告;下文只摘 CPU 与内存两处读法。

分析完成后的报告入口

基于重建符号的 CPU 火焰图:Lua 热路径与 C 源码行

在报告的 CPU 部分,可先展开 Lua 热点,再从关联的 C 侧火焰图查看函数名;在已重建符号的前提下,火焰图能细化到 C 源文件名与行号

C 火焰图中的源文件与行号

C 火焰图中的源文件与行号

Lua 侧会给出占用 CPU 最多的调用路径:本例中 close 函数被 generate 函数调用。generate 是一个 Lua 函数,被定义在 Lua 源文件 lua/report.lua 中。lua/invoice.lua 文件中定义的 generate_monthly_report 调用了前面那个 generate 函数。

Lua 热路径与源文件定位

将鼠标悬停在报告中的 generate 节点上,提示里会给出 完整源路径与行号(如第 11 行);用编辑器打开对应文件即可对照业务逻辑(本例中 generate 涉及查库与生成报告)。

Lua 热路径与源文件定位

在源码中对照报告给出的行号

在源码中对照报告给出的行号

内存:Lua GC 对象引用路径

在内存相关小节中,Lua 层 GC 对象引用路径中,很大一部分的内存被 LuaJIT 垃圾收集器尚未释放的死亡 Lua 对象占用。

Lua GC 引用路径与已加载模块

放大 registry -> ._LOADED 等路径后,可以看到在这条数据引用路径下,table 是当前 Lua 应用已加载的所有 Lua 模块的数据结构。显然,这些加载的 Lua 模块也占了很多的内存。

Lua GC 引用路径与已加载模块

Lua GC 引用路径与已加载模块

持续分析:每日与每周 Insights 报告

除单次 Guided Analysis 外,XRay 也可对在线进程持续产出洞察。切换到 Insights 即可按日、按周查看自动报告,适合长期观察;交互式向导更适合开发与演示场景。

Insights 中的周期报告

常见问题

Nginx 报 “No debugging symbols found” 是什么意思?

意味着 Nginx 或 OpenResty 二进制被 strip 过,或编译时没带 -g,符号表已丢失。此时用 GDB 做 backtrace 会打印 No symbol table info available,profiler 则把函数标为 Unknown。没有符号,就无法把机器地址映射回 C 或 Lua 的函数名、源文件和源码行号。

一定要安装 nginx-dbg 或重新编译 Nginx 才能拿到调试符号吗?

常规做法确实是:安装匹配的 nginx-dbg 调试符号包,或用 -g 重新编译。但当你的构建版本根本没有对应 dbg 包、或无法重新编译正在运行的二进制时,这两条路都走不通。OpenResty XRay 绕开二者:直接从被 strip 的二进制中自动重建缺失的调试符号,既不用装包,也不用重编译。

没有调试符号,能分析被 strip 过的 Nginx / OpenResty 二进制吗?

可以。OpenResty XRay 会先重建缺失的符号,再运行各分析器,因此被 strip 的二进制照样能产出 CPU 火焰图和内存报告,并解析到真实的 C 与 Lua 函数名、源文件和源码行——就像符号一直都在一样。

OpenResty XRay 是如何重建缺失的调试符号的?

分析启动时,OpenResty XRay 会检测有哪些可执行文件缺失符号,并自动触发一次符号重建,利用机器学习从被 strip 的二进制中重构符号。重建完成后,它会并行运行所有相关分析器,把 C 与 Lua 函数都映射回各自的源文件与行号。

关于 OpenResty XRay

OpenResty XRay 是一个动态追踪产品,它可以自动分析运行中的应用,以解决性能问题、行为问题和安全漏洞,并提供可行的建议。在底层实现上,OpenResty XRay 由我们的 Y 语言驱动,可以在不同环境下支持多种不同的运行时,如 Stap+、eBPF+、GDB 和 ODB。

关于作者

章亦春是开源 OpenResty® 项目创始人兼 OpenResty Inc. 公司 CEO 和创始人。

章亦春(Github ID: agentzh),生于中国江苏,现定居美国湾区。他是中国早期开源技术和文化的倡导者和领军人物,曾供职于多家国际知名的高科技企业,如 Cloudflare、雅虎、阿里巴巴, 是 “边缘计算“、”动态追踪 “和 “机器编程 “的先驱,拥有超过 22 年的编程及 16 年的开源经验。作为拥有超过 4000 万全球域名用户的开源项目的领导者。他基于其 OpenResty® 开源项目打造的高科技企业 OpenResty Inc. 位于美国硅谷中心。其主打的两个产品 OpenResty XRay(利用动态追踪技术的非侵入式的故障剖析和排除工具)和 OpenResty Edge(最适合微服务和分布式流量的全能型网关软件),广受全球众多上市及大型企业青睐。在 OpenResty 以外,章亦春为多个开源项目贡献了累计超过百万行代码,其中包括,Linux 内核、Nginx、LuaJITGDBSystemTapLLVM、Perl 等,并编写过 60 多个开源软件库。

关注我们

如果您喜欢本文,欢迎关注我们 OpenResty Inc. 公司的博客网站 。也欢迎扫码关注我们的微信公众号:

我们的微信公众号

翻译

我们提供了英文版原文和中译版(本文)。我们也欢迎读者提供其他语言的翻译版本,只要是全文翻译不带省略,我们都将会考虑采用,非常感谢!