【问题标题】:Windows CE .EXE symbol access from DLL从 DLL 访问 Windows CE .EXE 符号
【发布时间】:2014-01-02 15:37:04
【问题描述】:

我有一些代码可以在 Unix(Linux 和 Solaris)和 Windows(确切地说是 7)上运行,但不能在 Windows CE 上运行。该代码实现了一个插件框架,并且需要将符号从可执行文件导出到加载的插件中。我无法从主可执行文件中获取加载的插件 (DLL) 来解析符号。

我已将接口简化为主可执行文件中的单个函数,其定义如下:

extern "C" __declspec( dllexport )
const char * translate_name( const char *key ) {
   ...
}

如果我在可执行文件上运行 Dumpbin /EXPORTS,我会将其视为导出符号之一:

81   50 00001474 translate_name = @ILT+1135(_translate_name)

插件需要导出两个函数 xxxLoadPlugin 和 xxxUnloadPlugin 加载后主可执行文件将调用它们以允许它们互连。 xxx 替换为约定的名称前缀(通常是 dll 或 .so 名称)。我有一个测试项目,它创建:

extern "C" __declspec( dllexport ) int testRegisterLibrary( ) {
   return 0;
}

extern "C" __declspec( dllexport ) int testUnregisterLibrary( ) {
   return 0;
}

如果我编译并运行这个模块,一切都会按预期工作。我可以加载 dll,并在调试器中遍历函数。

如果我添加引用 translate_name 的代码,例如:

extern "C" __declspec( dllimport ) const char * translate_name( const char *key );

extern "C" __declspec( dllexport ) int testRegisterLibrary( ) {
   translate_name("test");
   return 0;
}

extern "C" __declspec( dllexport ) int testUnregisterLibrary( ) {
   return 0;
}

DLL 现在将无法加载。使用 dumpbin /IMPORTS 检查创建的 DLL 我看到了:

50 translate_name

translate_name 是从我的主可执行文件导入的唯一符号。如果我尝试使用 GetProcAddress 而不是依赖链接器,如下所示:

extern "C" __declspec( dllexport ) int testRegisterLibrary( ) {
   HMODULE mainModule = GetModuleHandle(NULL);   //handle for main executable
   void *ptr = (void *)GetProcAddress(L"translate_name");
   return 0;
}

extern "C" __declspec( dllexport ) int testUnregisterLibrary( ) {
   return 0;
}

DLL 加载,但“ptr”的值为 NULL(在调试器中检查)。我也尝试过 GetProcAddressA("translate_name"),并使用 "_translate_name" 获得相同的结果。

鉴于此,在 Windows CE 中初始加载程序通过后,可执行文件导出的符号似乎没有保留。同样,这适用于任何正常的 Windows 环境。 Windows CE 是否缺少某些设置?为什么 GetProcAddress 在 dumpbin 说导出的可执行文件中找不到符号? Windows CE 加载程序是否隐藏或删除了符号?

【问题讨论】:

    标签: c++ c windows dll


    【解决方案1】:

    只是为了确认您的发现,这是行不通的。很难在 MSDN 文档中找到不支持的确凿证据,除了 GetProcAddress() 坚持符号必须由 DLL 导出。您无法加载 DLL,当它包含来自 EXE 的导入时,它将失败并显示 ERROR_BAD_EXE_FORMAT。 GetProcAddress() 将始终失败并显示 ERROR_INVALID_HANDLE,即使您将模块句柄强制为 EXE 加载地址。

    没有强有力的证据表明加载程序有意剥离 EXE 的导出表,当您使用调试器查看时,它驻留在内存中。它只是断然拒绝看它。

    您需要解决这个问题并以不同的方式解决这个问题。除了在单独的 DLL 中分离辅助函数之外,一个明显的解决方法是为 xxxLoadPlugin() 入口点提供一个参数,一个指向辅助函数的函数指针表的指针。 COM 中常用的IServiceProvider interface 是一个很好的方法。

    【讨论】:

    • 好吧,这很令人沮丧,但至少不只是我。我很想知道为什么这在 CE 上不起作用,特别是因为链接器很乐意为我的可执行文件生成 .lib 文件。也许其他人会加入。如果没有,我会在几天后接受这个答案。
    猜你喜欢
    • 1970-01-01
    • 2013-11-24
    • 2021-02-02
    • 1970-01-01
    • 1970-01-01
    • 2011-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多