CANN oam-tools asys coretrace 文件解析:命令详解、addr2line 符号化原理与故障定位实战
【免费下载链接】oam-tools本项目为开发者提供故障定位工具,包含故障信息收集,软硬件信息展示,AI core error报错分析等能力,提升故障问题定位效率,文档可在昇腾社区搜索“故障处理简介”(选择社区版)。项目地址: https://gitcode.com/cann/oam-tools
本文聚焦 CANN oam-tools 项目中 asys 工具的核心分析能力之一:coretrace 文件解析。文章围绕asys analyze -r=coretrace的命令格式、全部参数语义、解析输出格式展开,并结合仓库源码说明其基于 addr2line 的符号化解析原理、动态库检索策略与多线程批处理实现。读完本文,你将能够在发生 Device 侧进程异常退出(如 Signal 11)时,独立完成 coretrace 文件的获取、解析与堆栈解读,并具备排查解析结果异常(如出现?或行号偏差)的实战能力。
功能说明:什么是 coretrace 文件解析
coretrace 是 Device 侧系统类日志中的一种维测信息文件,当 Device 侧进程发生异常(例如段错误触发 Signal 11)时,系统会记录下当时的崩溃信号、线程信息以及各线程的调用栈帧地址,形成coretrace.*格式的原始文件。这类文件中的栈帧只有原始地址,无法直接阅读,需要结合对应的动态库(二进制)才能还原出函数名与源代码行号。
asys 工具的 coretrace 解析功能即用于完成这一还原过程:以 coretrace 文件为输入,解析其中每个线程的调用栈,将原始地址转换为“地址 + 函数名 + 二进制名”的可读堆栈,供后续故障定位使用。该能力与 asys 的stackcore 文件解析、coredump 文件解析共同构成 asys 的堆栈类分析家族,且三者共享asys analyze命令框架与--symbol_path符号检索机制。
从仓库结构看,coretrace 解析功能主要由 coretrace_collect.py 中的ParseCoreTrace类实现,并通过 asys_analyze.py 中的AsysAnalyze统一调度。关于 asys 工具的完整功能清单与使用约束,可参见 asys 工具功能及约束。
coretrace 文件的获取方式
coretrace 文件属于 Device 侧系统类日志和维测信息,一般通过以下途径获取:
- 使用 Device 侧日志导出工具(如 msnpureport 工具)执行“单次导出 Device 侧系统类日志和其他维测信息”操作导出 coretrace 文件;
- 通过 asys 自身的故障信息收集功能进行收集,收集到的日志信息中包含 coretrace 文件(该场景下 coretrace 文件收集需要 root 权限,具体权限要求参见asys 工具功能及约束中的信息收集列表)。
获取到 coretrace 文件后,即可使用本文介绍的解析命令将其转换为可读堆栈。
使用前提与注意事项
使用 coretrace 解析功能前,请先确认以下前提条件,否则可能导致解析失败或结果不准确:
- 依赖 addr2line 工具:coretrace 解析功能依赖 Linux 系统自带的
addr2line工具进行堆栈函数名和行号的解析。请确保addr2line已安装,且执行该脚本的用户有权限执行它。若工具缺失,asys 会直接报错退出。这一点与 stackcore 解析不同(stackcore 依赖readelf和addr2line两个工具),coretrace 解析只依赖addr2line。 - 在获取 coretrace 文件的环境中执行解析:需在获取 coretrace 文件(即发生故障)的环境中执行 coretrace 文件解析命令,否则可能因动态库版本不匹配导致解析结果不准确。
- 芯片形态支持限制:
- 仅 Ascend 950PR / Ascend 950DT 支持使用 coretrace 文件解析功能;
- Atlas A3 训练系列产品 / Atlas A3 推理系列产品、Atlas A2 训练系列产品 / Atlas A2 推理系列产品不支持使用 coretrace 文件解析功能;
- Atlas 200I/500 A2 推理产品、Atlas 推理系列产品、Atlas 训练系列产品不支持使用 coretrace 文件解析功能。
- 环境形态限制:asys 工具整体仅支持在 Ascend EP 形态下使用(参见asys 工具功能及约束),coretrace 解析作为
analyze子命令同样遵循该约束。
从源码实现看,ParseCoreTrace.check_tool_exists()会通过check_command("addr2line")校验工具是否存在,不存在时记录错误日志并返回失败(对应日志:The addr2line tool does not exist, install it before using it.)。仓库中的单元测试 test_asys_analyze.py 也覆盖了该场景(test_asys_analyze_coretrace_no_addr2line),验证了工具缺失时解析会失败并输出上述提示。
命令格式
coretrace 解析支持两种输入方式:解析单个文件或解析整个目录(含子目录)下的多个文件。
方式一:解析单个文件
asys analyze -r=coretrace --file=filename --symbol_path=path1,path2 --output=path3方式二:解析指定目录下的多个文件
asys analyze -r=coretrace --path=directory --symbol_path=path1,path2 --output=path3两种方式中--file与--path只能选择其一,不能同时存在。从命令行解析器的源码看,analyze子命令将--file与--path定义在add_mutually_exclusive_group互斥组中,argparse 层面即禁止二者同时出现;且二者均通过ArgChecker.FILE_PATH_EXIST_R校验路径是否存在。
参数说明
coretrace 解析涉及的全部参数如下表所示:
| 参数 | 必选/可选 | 说明 |
|---|---|---|
| r | 必选 | 解析模式,此处设置为coretrace,用于解析 coretrace 格式的文件(coretrace.*文件),供后续定位使用。 |
| file | coretrace 模式下必选 | 用于解析单个文件,此处设置为包含路径的文件名。与path互斥。 |
| path | coretrace 模式下必选 | 指定目录,用于解析指定目录及其子目录下的多个文件。与file二选一,两者不能同时存在。 |
| symbol_path | 可选 | coretrace 模式解析所需要的动态库目录,可传多个目录,用逗号隔开。symbol_path只扫描当前目录下的动态库,按路径 1、路径 2 的顺序查找,不扫描子目录;为防止误解析,建议将相关动态库放在同一个路径下。不指定时,从 coretrace 文件中获取所需要的动态库路径;为防止找不到动态库文件,建议仅在发生 coredump 错误的环境上使用该方式。 |
| output | 可选 | 其值作为 asys 工具的结果输出目录的路径前缀,最终输出目录为{output}/asys_output_timestamp。命令行中不带output参数时,输出结果存放在命令行执行目录下;若output指定值为空、无效字符串、或指定路径目录无写权限、或创建目录失败,则 asys 工具退出执行并报错。 |
关于symbol_path的检索逻辑,源码中有更精确的说明:ParseCoreTrace.get_binary_path()会提取 coretrace 文件中二进制路径的文件名(bin_name_path.split("/")[-1]),然后依次在每个symbol_path目录下拼接该文件名并检查是否存在,命中即返回;全部未命中时会发出警告日志(xxx is not exists.)。因此目录层级较深或不在此目录下的动态库无法被命中,这也是文档建议“将相关动态库放在一个路径下”的原因。
需要特别说明的是,symbol_path参数在仓库的参数定义中同时被stackcore与coretrace两种模式共用,官方 help 文本中标注“仅对 stackcore 有效”属于历史注释,实际 coretrace 解析路径(__atrace_analyze中ParseCoreTrace(self.symbol_path, self.file))同样会读取该参数;未设置时 asys 会提示'--symbol_path' is not set, the default path will be used to analyze.并回退到 coretrace 文件内记录的动态库路径。
使用示例
以下示例解析单个 coretrace 文件,指定两个动态库搜索目录,并将结果输出到$HOME/dfx_info前缀目录下:
asys analyze -r=coretrace --file=coretrace.log-daemon.12335.11.1749181305 --symbol_path=$HOME/test1,$HOME/test2 --output=$HOME/dfx_info批量解析目录场景示例:
asys analyze -r=coretrace --path=$HOME/dfx_logs --symbol_path=$HOME/libs --output=$HOME/dfx_info执行成功后,解析结果将写入{output}/asys_output_timestamp目录。解析过程中,单文件模式下 asys 会先将被解析文件拷贝到输出目录,再在原路径位置进行解析;目录模式下仅会拷贝文件名以coretrace开头的文件(见 asys_analyze.py 中__copy_dir的过滤逻辑),因此目录中混入的其他类型文件不会被误处理。
解析输出说明
解析后的文件示例如下:
Signal 11 pid 12335 PID 12335 TGID 12335 comm log-daemon 0xdfffcac78a68 0x00000000000b4a68: clock_nanosleep at ??:? /usr/lib64/libc.so.6 0xdfffcac7dc4c 0x00000000000b9c48: __nanosleep at ??:? /usr/lib64/libc.so.6 0xdfffcaca6d88 0x00000000000e2d84: usleep at ??:? /usr/lib64/libc.so.6 0xaaaad1e22dec 0x0000000000012de8: ToolSleep at log_system_api.c:704 /var/log-daemon 0xaaaad1e1cb58 0x000000000000cb54: main at log_daemon.c:217 /var/log-daemon 0xdfffcabef040 0x000000000002b03c: __libc_init_first at ??:? /usr/lib64/libc.so.6 0xdfffcabef118 0x000000000002b114: __libc_start_main at ??:? /usr/lib64/libc.so.6 0xaaaad1e1c680 0x000000000000c67c: $x at start.os:? /var/log-daemon PID 12356 TGID 12335 comm adx_get_file_th 0xdfffcaca550c 0x00000000000e150c: ioctl at ??:? /usr/lib64/libc.so.6 0xdfffcbc413fc 0x00000000000543f8: HiIam::AppIoctl(int, unsigned long, void*, unsigned int&, bool) at ??:? /usr/lib64/libiam.so.0.1.0.0 0xdfffcbc415ec 0x00000000000545e8: ioctl at ??:? /usr/lib64/libiam.so.0.1.0.0 0xdfffcb2d61ec 0x000000000006f1e8: mmIoctl at hdc_pcie_drv.c:? /usr/lib64/libascend_hal.so 0xdfffcb2d678c 0x000000000006f788: hdcIoctl at hdc_pcie_drv.c:? /usr/lib64/libascend_hal.so 0xdfffcb2d8550 0x000000000007154c: hdcPcieEpollWait at ??:? /usr/lib64/libascend_hal.so 0xdfffcb2dabf4 0x0000000000073bf0: drvHdcPcieEpollWait at hdc_pcie_epoll.c:? /usr/lib64/libascend_hal.so 0xdfffcb2da7f4 0x00000000000737f0: drvHdcEpollWait at ??:? /usr/lib64/libascend_hal.so 0xaaaad1e6dc60 0x000000000005dc5c: Adx::AdxHdcEpoll::EpollWait(std::vector<Adx::EpollEvent, std::allocator<Adx::EpollEvent> >&, int, int) at ??:? /var/log-daemon 0xaaaad1e6c51c 0x000000000005c518: Adx::AdxServerManager::ComponentWaitEvent() at :? /var/log-daemon 0xaaaad1e6c780 0x000000000005c77c: Adx::AdxServerManager::Run() at ??:? /var/log-daemon 0xaaaad1e6ea0c 0x000000000005ea08: Adx::Runnable::Process(void*) at ??:? /var/log-daemon 0xdfffcac46168 0x0000000000082164: pthread_condattr_setpshared at ??:? /usr/lib64/libc.so.6 0xdfffcacad8dc 0x00000000000e98d8: clone at ??:? /usr/lib64/libc.so.6 ......输出格式解读
文件首行为崩溃信号信息,格式为
Signal <信号号> pid <进程号>,例如Signal 11 pid 12335表示进程因 Signal 11(SIGSEGV,段错误)而崩溃。每个线程的堆栈以
PID <pid> TGID <tgid> comm <线程名>开头,其中PID为线程号(TID),TGID为线程组 ID,comm为线程名。示例中第二个线程PID 12356 TGID 12335 comm adx_get_file_th属于进程 12335 的一个子线程。每个栈帧按
{地址} {函数名} {二进制名}三段式格式输出,例如:0xdfffcac78a68 0x00000000000b4a68: clock_nanosleep at ??:? /usr/lib64/libc.so.6其中第一列为崩溃环境中的运行时地址(对应 coretrace 原始文件中的帧指针
fp),第二列是相对于动态库加载基址的偏移量(即fp - start_addr - shift换算出的地址),随后是该地址解析出的函数名与源码位置(函数名 at 文件:行号),最后一列为所属动态库文件。解析出的ToolSleep at log_system_api.c:704、main at log_daemon.c:217等行即为故障定位中最有价值的业务函数调用点。若函数名获取失败,则该位置显示解析过程中自动计算出来的十六进制偏移值。此时需检查
symbol_path配置目录是否正确,以及该目录下的动态库文件是否正确。
解析原理:从源码看 addr2line 符号化调用链
coretrace 解析的核心实现在 coretrace_collect.py 的ParseCoreTrace类中,其整体调用链为:
格式与前置校验:
start_parse_file()首先校验文件名是否以coretrace开头(否则报错The xxx file is not in coretrace format.),随后校验addr2line是否存在、文件是否为空。内存映射表构建:
parse_line()逐行扫描 coretrace 文件,解析形如start-end的地址区间行,按二进制名归并出内存映射表maps(同一二进制出现多个区间时取最小起始地址与最大结束地址);同时解析Signal、PID等元信息,跳过[<0>]、(deleted)及uburma、davinci_manager相关噪声行。地址换算与符号化:对于每个栈帧地址
fp,parse_addr_src_line()在映射表中定位其所属二进制与加载区间,计算相对偏移delta = hex(fp - start_addr - shift)(其中shift依据帧编号取值,#0帧为 0,其余帧为 4),然后构造 addr2line 命令执行符号化:cmd = [self.__addr2line, "-Cifps", "-e", bin_path, "-a", delta]其中各选项含义为:
-C关闭/开启 demangle(C++ 符号还原为可读形式,如示例中的Adx::AdxHdcEpoll::EpollWait(...))、-i内联函数展开、-f输出函数名、-p美化输出、-s只显示源文件名。命令执行结果即为“函数名 at 文件:行号”文本。异常兜底:若 addr2line 执行失败(捕获
OSError、ValueError)或输出为空,则回退输出自动计算的十六进制偏移,并记录警告日志。
目录批量解析的多线程实现
使用--path解析目录时,ParseCoreTrace.run()通过walk_dir递归收集目录及子目录下所有文件,并为每个文件启动一个守护线程执行解析(见save_file_result与线程列表threads),全部线程结束后统一汇总结果。因此批量解析大量 coretrace 文件时具备一定的并发能力,单文件解析则会通过out_progress_bar显示解析进度。
测试用例印证
仓库单元测试 test_asys_analyze.py 对 coretrace 解析进行了较完整的覆盖,可作为理解行为边界的参考:
test_asys_analyze_coretrace/test_asys_analyze_coretrace_with_binary:验证单文件解析及配合symbol_path指定动态库目录的解析流程;test_asys_analyze_coretrace_run_addr2line_failed:验证 addr2line 执行抛出OSError时解析仍可容错完成;test_asys_analyze_coretrace_no_addr2line:验证 addr2line 缺失时解析失败并输出对应错误日志;test_asys_analyze_coretrace_dir:验证--path目录模式解析;test_asys_analyze_coretrace_other_file/test_asys_analyze_coretrace_empty_file:验证非 coretrace 格式文件与空文件的报错处理;test_asys_analyze_path_output_same:验证--output与--path指向同一目录时工具报错退出(对应 asys_analyze.py 中 “The output directory cannot be the same as the 'path' directory or its subdirectories.” 的校验逻辑)。
常见问题与排查建议
1. 解析结果中出现?字符
解析后的文件如果存在?字符(如??:?、at ??:?),可能由以下原因导致:
- 编译选项问题:该动态库文件编译时没有使用
-g选项,导致文件中未保留调试信息(DWARF 调试段),addr2line 无法定位到行号; - 未添加链接参数:未使用
-rdynamic通知链接器将所有符号添加到动态符号表中,导致动态符号表缺失部分符号; - 未找到动态库:
symbol_path目录中未找到相匹配的动态库,或动态库版本与发生故障时不一致。
排查建议:优先核对symbol_path是否指向了包含正确动态库的目录、目录下动态库是否与故障环境一致;对于自研二进制,确认其编译时开启了-g并添加了-rdynamic。
2. 解析出的行号存在少许偏差
coretrace 解析函数名和行号时,部分动态库解析出的行号会有少许偏差,原因如下:
- 编译选项:不同的编译选项,特别是与调试信息相关的选项,可能会造成影响;
- 优化级别:较高的优化级别(如
-O2、-O3)可能会导致代码的重组和优化(内联、指令重排等),从而使行号与原始源代码的对应关系发生偏差。
排查建议:此类偏差属于编译优化带来的正常现象,定位时以函数名为主、行号作为参考即可;若需精确行号,可尝试使用带调试信息且优化级别较低(如-O0 -g)的构建版本配合解析。
3. 解析失败或结果为空
- 确认
addr2line已安装且当前用户有执行权限; - 确认解析环境与获取 coretrace 文件的环境一致;
- 确认
--file与--path未同时指定(二者互斥); - 确认
--output指向的目录存在且可写(无写权限时 asys 会退出并报错); - 确认输入文件确实是 coretrace 格式(文件名以
coretrace开头)且非空。
与 asys 其他文件解析能力的关系
在 asys 的 analyze 体系中,coretrace 解析与另外两种堆栈解析能力互补使用,可形成完整的故障定位链路:
| 解析模式 | 输入文件 | 依赖工具 | 输出 |
|---|---|---|---|
coredump | 系统 core 文件 | gdb | stackcore 格式的 txt 文件 |
stackcore | stackcore 格式 txt 文件 | readelf、addr2line | 可读堆栈(Thread n (tid, name)格式) |
coretrace | coretrace 格式文件(coretrace.*) | addr2line | 可读堆栈(PID x TGID y comm z格式) |
coredump 解析(coredump 文件解析)可先借助 gdb 将 core 文件转为 stackcore 格式 txt;stackcore 解析(stackcore 文件解析)再进一步将其符号化为可读堆栈;而 coretrace 解析则直接面向 Device 侧导出的 coretrace 原始文件,一步到位完成符号化。三者共享--symbol_path、--output等参数语义与asys analyze命令框架,掌握 coretrace 解析即可触类旁通其余两种模式的用法。
总结
coretrace 文件解析是 asys 工具在 Device 侧进程异常场景下的关键维测能力:一条asys analyze -r=coretrace命令即可将原始崩溃栈帧还原为带函数名与行号的可读堆栈。实际使用时请重点把握三点:确保addr2line可用并在故障环境执行解析、通过--symbol_path精确指定与故障环境一致的动态库目录、结合输出中的?与行号偏差现象反向检查动态库与编译选项。更完整的 asys 使用指导可参阅 asys 工具使用指导,故障信息收集与权限要求参见故障信息收集与asys 工具功能及约束。
【免费下载链接】oam-tools本项目为开发者提供故障定位工具,包含故障信息收集,软硬件信息展示,AI core error报错分析等能力,提升故障问题定位效率,文档可在昇腾社区搜索“故障处理简介”(选择社区版)。项目地址: https://gitcode.com/cann/oam-tools
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考