2013-04-15 194 views

回答

1

使用dumpbin /exports 'file.dll'名来获取所有符号的装饰/未修饰的名。

4

的VC++编译器知道自己的名字重整方案,那么为什么不使用呢?里面template<typename T> T GetProcAddress(HMODULE h, const char* name),宏__FUNCDNAME__包含这个包括T部分,所以在GetProcAddress<void(*)(int)里面,我们有一个subs与损坏的名称void(*)(int)。由此,我们可以简单地推导出void foo(int);

的错位名称。此代码依赖于VC++宏__FUNCDNAME__ 对于MinGW,您需要将其作为 __PRETTY_FUNCTION__而不是

FARPROC GetProcAddress_CppImpl(HMODULE h, const char* name, std::string const& Signature) 
{ 
    // The signature of T appears twice in the signature of T GetProcAddress<T>(HMODULE, const char*) 
    size_t len = Signature.find("@@YA"); 
    std::string templateParam = Signature.substr(0, len); 
    std::string returnType = Signature.substr(len+4); 
    returnType.resize(templateParam.size()); // Strip off our own arguments (HMODULE and const char*) 
    assert(templateParam == returnType); 
    // templateParam and returnType are _pointers_ to functions (P6), so adjust to function type (Y) 
    std::string funName = "?" + std::string(name) + "@@Y" + templateParam.substr(2); 
    return ::GetProcAddress(h, funName.c_str()); 
} 

template <typename T> 
T GetProcAddress(HMODULE h, const char* name) 
{ 
    // Get our own signature. We use `const char* name` to keep it simple. 
    std::string Signature = __FUNCDNAME__ + 18; // Ignore prefix "[email protected]" 
    return reinterpret_cast<T>(GetProcAddress_CppImpl(h, name, Signature)); 
} 

// Showing the result 

struct Dummy { }; 

__declspec(dllexport) void foo(const char* s) 
{ 
    std::cout << s; 
} 

__declspec(dllexport) void foo(int i, Dummy) 
{ 
    std::cout << "Overloaded foo(), got " << i << std::endl; 
} 

__declspec(dllexport) void foo(std::string const& s) 
{ 
    std::cout << "Overloaded foo(), got " << s << std::endl; 
} 

__declspec(dllexport) int foo(std::map<std::string, double> volatile&) 
{ 
    std::cout << "Overloaded foo(), complex type\n"; 
    return 42; 
} 

int main() 
{ 
    HMODULE h = GetModuleHandleW(0); 
    foo("Hello, "); 
    auto pFoo1 = GetProcAddress<void (*)(const char*)>(h, "foo"); 
    // This templated version of GetProcAddress is typesafe: You can't pass 
    // a float to pFoo1. That is a compile-time error. 
    pFoo1(" world\n"); 
    auto pFoo2 = GetProcAddress<void (*)(int, Dummy)>(h, "foo"); 
    pFoo2(42, Dummy()); // Again, typesafe. 
    auto pFoo3 = GetProcAddress<void (*)(std::string const&)>(h, "foo"); 
    pFoo3("std::string overload\n"); 
    auto pFoo4 = GetProcAddress<int (*)(std::map<std::string, double> volatile&)>(h, "foo"); 
    // pFoo4 != NULL, this overload exists. 
    auto pFoo5 = GetProcAddress<void (*)(float)>(h, "foo"); 
    // pFoo5==NULL - no such overload. 
} 
+0

注意'__PRETTY_FUNCTION__'将不是这样的,因为它不是缺胳膊少腿,它看起来像'T GetProcAddress的(HMODULE,为const char *)与T = blahblah]'。我不确定在GCC下是否存在任何这样的东西,如mangled函数名称宏(不这么认为)。 – Damon

+0

@Damon:你说得对,我误解了文档。确实没有这样的宏,并且''头只提供了一个解压缩函数。 – MSalters

+0

@MSalters有趣,但它没有在函数上工作我尝试了它,因为在dll中,但在你的函数中的错位名称中的反向引用;因为该函数位于命名空间中,并且在相同的命名空间中返回一个类的对象;在返回类型中,命名空间名称get用@ 1 ... –

0

这是不可能的,只需使用GetProcAddress即可。但是,一种方法是枚举该特定模块的所有导出函数,然后执行模式匹配以查找所有重名的名称。

更具体地说,参考this answer here。您需要进行的唯一更改是将TRUE中的MappedAsImage参数和返回值GetModuleHandle中的Base参数传递给ImageDirectoryEntryToData函数调用。

void EnumerateExportedFunctions(HMODULE hModule, vector<string>& slListOfDllFunctions) 
{ 
    DWORD *dNameRVAs(0); 
    _IMAGE_EXPORT_DIRECTORY *ImageExportDirectory; 
    unsigned long cDirSize; 
    _LOADED_IMAGE LoadedImage; 
    string sName; 
    slListOfDllFunctions.clear(); 

    ImageExportDirectory = (_IMAGE_EXPORT_DIRECTORY*) 
     ImageDirectoryEntryToData(hModule, 
     TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &cDirSize); 
    if (ImageExportDirectory != NULL) 
    { 
     dNameRVAs = (DWORD *)ImageRvaToVa(LoadedImage.FileHeader, 
      LoadedImage.MappedAddress, 
     ImageExportDirectory->AddressOfNames, NULL); 
     for(size_t i = 0; i < ImageExportDirectory->NumberOfNames; i++) 
     { 
      sName = (char *)ImageRvaToVa(LoadedImage.FileHeader, 
        LoadedImage.MappedAddress, 
        dNameRVAs[i], NULL); 
     slListOfDllFunctions.push_back(sName); 
     } 
    } 
} 
相关问题