从DLL访问Windows CE .EXE符号

时间:2013-12-15 02:53:26

标签: c++ c windows dll

我有一些代码可以在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加载程序隐藏或删除符号?

1 个答案:

答案 0 :(得分:3)

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

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

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