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

MinGW下C++链接pe-parse库报undefined reference错误如何解决

问题背景

开发PE加壳工具需要PE文件解析能力,选择使用C++ pe-parse库,按照官方指引完成库编译构建后,尝试将其链接到简单测试文件时出现链接错误。
测试代码src/main.cpp内容如下:

#include <pe-parse/parse.h>

int main(int ac, char **av)
{
    peparse::parsed_pe *p = peparse::ParsePEFromFile(av[0]);
    return 0;
}

项目目录结构:

.
├── src
│      main.cpp
├── lib
│      pe-parse.lib
├── bin
│      pe-parse.dll
└── include
    └ pe-parse
         nt-headers.h
         parse.h
         to_string.h

环境信息:

  • 使用x64版本MinGW,标识为x86_64-w64-mingw32
  • 构建得到的pe-parse.dll与pe-parse.lib均为pei-x86-64架构,架构匹配
    执行的编译命令:
g++ -Wall -Wextra .\src\main.cpp -I.\include\ -L.\bin\ -lpe-parse

报错信息:

C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
C:\Users\gz\AppData\Local\Temp\ccxml3rK.o:packer.cpp:(.text+0x1f): undefined reference to `peparse::ParsePEFromFile(char const*)'
collect2.exe: error: ld returned 1 exit status

已排查情况:

  • 用nm工具查看pe-parse.lib可检索到目标符号,pe-parse.dll中未查询到对应符号
  • 尝试将编译参数中的-L.\bin\替换为-L.\lib\,问题仍然存在
  • 判断pe-parse.lib是对应DLL的导入库,需要配合DLL完成链接,但始终未找到正确的链接配置方式
根因分析

该问题核心是ABI与库格式不兼容:

  1. 你持有的pe-parse.lib大概率是MSVC编译器生成的导入库,MinGW的GCC链接器无法直接兼容MSVC格式的C符号修饰规则——MSVC和GCC的C符号名修饰规则完全不同,即使CPU架构一致,链接器也无法识别匹配对应符号。
  2. 你在DLL中未查询到对应符号,说明编译pe-parse时要么没有正确配置符号导出规则,要么查询DLL导出符号的工具/方式不对。
解决方案

按优先级选择以下任意一种方案即可:

方案1:用当前MinGW环境重新编译pe-parse(最稳定,推荐)

不要使用MSVC编译产出的.lib和.dll,直接用项目当前使用的同版本MinGW编译pe-parse,从根源消除ABI不兼容问题:

  1. 进入pe-parse源码目录,在MinGW终端下执行cmake构建,开启动态库编译:
    cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON
    cmake --build build
    
  2. 构建完成后,将产出文件按原有目录结构放置:
    • 头文件放入include/pe-parse/目录
    • MinGW格式导入库libpe-parse.dll.a放入lib/目录(注意不是MSVC格式的.lib文件)
    • 动态库pe-parse.dll放入bin/目录
  3. 调整编译命令,指定正确的链接路径:
    g++ -Wall -Wextra .\src\main.cpp -I.\include -L.\lib -lpe-parse
    
    注意:MinGW链接时会自动识别带lib前缀的库文件,-lpe-parse参数会自动匹配libpe-parse.dll.a,不需要手动写全库文件名
  4. 编译完成后,将bin目录下的pe-parse.dll放到生成的可执行文件同目录即可正常运行。

方案2:基于现有DLL手动生成MinGW兼容导入库

如果不想重新编译pe-parse,可以基于已有的DLL生成MinGW可用的导入库:

  1. 先确认DLL确实导出了目标符号,执行objdump -p pe-parse.dll | grep ParsePEFromFile查看,如果能查到导出记录再执行后续步骤;如果查不到,说明原有DLL编译本身存在问题,必须重新编译库。
  2. 生成DLL对应的导出定义文件:
    gendef pe-parse.dll
    
    执行后会在当前目录生成pe-parse.def文件,记录DLL所有导出符号。
  3. 基于def文件生成MinGW格式的导入库:
    dlltool -d pe-parse.def -l libpe-parse.dll.a
    
  4. 将生成的libpe-parse.dll.a放到lib/目录,使用方案1中的编译命令重新编译即可。

方案3:静态链接pe-parse

如果不想额外携带DLL依赖,可以编译静态版本的pe-parse:编译时将cmake参数BUILD_SHARED_LIBS设为OFF,构建完成后会生成libpe-parse.a静态库,链接时直接指定该静态库路径即可,运行时不需要依赖DLL。

注意事项
  • 禁止混用MSVC和MinGW编译的C++动态/静态库,二者除了符号修饰规则不兼容,对象内存布局、异常处理逻辑也存在差异,即使勉强链接成功,运行时也大概率出现崩溃问题。
  • 注意GCC链接参数顺序:库链接参数-lpe-parse要放在源文件参数之后,GCC链接器按从左到右顺序解析符号,库参数放前面会出现符号解析失败的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 05:33:16