You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SymGetSymFromAddr64仅显示DLL符号,自有代码符号无法获取求助

解决MinGW编译下SymGetSymFromAddr64/SymGetLineFromAddr64无法获取自有代码符号的问题

问题描述

在X64架构机器上调用SymGetSymFromAddr64和SymGetLineFromAddr64打印调用栈,输出如下:

调用栈(MAIN线程):
#0  at (null):0
#1  at (null):0
#2  at (null):0
#3  at (null):0
#4 BaseThreadInitThunk at (null):0
#5 RtlUserThreadStart at (null):0

仅能获取系统DLL的符号,自有代码符号无法返回,SymGetLineFromAddr64完全失效,调用失败时返回“Attempt to access invalid address”错误。代码通过MinGW环境下gcc -g编译。

相关代码:

HANDLE process = GetCurrentProcess();
HANDLE thread  = GetCurrentThread();

SymInitialize (process, NULL, true);

SymSetOptions (SymGetOptions() | SYMOPT_LOAD_LINES);

DWORD image_file = IMAGE_FILE_MACHINE_AMD64;
STACKFRAME64 sf = { .AddrPC     = { .Mode = AddrModeFlat, .Offset = thread_ctx.Rip },
                    .AddrStack  = { .Mode = AddrModeFlat, .Offset = thread_ctx.Rsp },
                    .AddrFrame  = { .Mode = AddrModeFlat, .Offset = thread_ctx.Rbp } };

int frame=0; 
while (StackWalk64 (image_file, process, thread, &sf, &thread_ctx, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL) &&
       sf.AddrPC.Offset) {

    union symbol {
        IMAGEHLP_SYMBOL64;
        char data[sizeof(IMAGEHLP_SYMBOL64) + MAX_SYM_NAME];
    } symbol = { { .SizeOfStruct = sizeof (union symbol), .MaxNameLength = MAX_SYM_NAME } };

    DWORD64 displacement = 0;
    SymGetSymFromAddr64 (process, sf.AddrPC.Offset, &displacement, (PIMAGEHLP_SYMBOL64)&symbol);
    
    IMAGEHLP_LINE64 line = { .SizeOfStruct = sizeof (IMAGEHLP_LINE64) };
    DWORD displacement2 = 0;
    SymGetLineFromAddr64 (process, sf.AddrPC.Offset, &displacement2, &line);
    
    fprintf (stderr, "#%u %s at %s:%u\n", frame++, symbol.Name, line.FileName, (uint32_t)line.LineNumber);
}

CloseHandle (thread);
SymCleanup (process);

解决思路

  • 修正符号生成格式与路径
    MinGW默认用DWARF格式符号,但Windows DbgHelp API优先支持COFF或PDB格式。编译时添加-gcoff生成COFF符号,或用cv2pdb工具将DWARF符号转换为PDB格式;确保符号文件与可执行文件同目录,或在SymInitialize第二个参数指定符号搜索路径。

  • 调整符号初始化顺序
    当前先初始化符号库再设置行加载选项,导致选项未生效。正确顺序是先设置选项再初始化:

    SymSetOptions(SymGetOptions() | SYMOPT_LOAD_LINES | SYMOPT_DEBUG); // SYMOPT_DEBUG可排查加载问题
    BOOL init_ok = SymInitialize(process, NULL, TRUE);
    if (!init_ok) {
        // 用GetLastError()获取初始化失败原因
    }
    
  • 验证栈遍历返回的地址有效性
    错误提示“无效地址”可能是StackWalk64返回的地址不属于当前进程模块。循环中可先检查地址所属模块:

    DWORD64 module_base = SymGetModuleBase64(process, sf.AddrPC.Offset);
    if (module_base == 0) {
        fprintf(stderr, "#%u 无效地址: 0x%llX\n", frame++, sf.AddrPC.Offset);
        continue;
    }
    
  • 添加错误调试输出
    调用符号函数后,通过GetLastError()获取具体错误码,定位问题根源:

    if (!SymGetSymFromAddr64(process, sf.AddrPC.Offset, &displacement, (PIMAGEHLP_SYMBOL64)&symbol)) {
        DWORD err = GetLastError();
        fprintf(stderr, "SymGetSymFromAddr64失败,错误码: %lu\n", err);
    }
    

内容的提问来源于stack exchange,提问作者Divon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 11:47:08