【问题标题】:how to know the method loaded from which DLL如何知道从哪个DLL加载的方法
【发布时间】:2013-08-22 06:42:50
【问题描述】:

在两个 DLL A.dll 和 B.dll 中定义了一个通用方法 foo()。现在,当一个进程 proc.exe 加载两个 DLL 并同时从两个线程调用 foo() 方法时。有什么方法可以知道 foo() 在运行时是从哪个 DLL A.dll 或 B.dll 加载的。我需要此信息用于记录目的。我在互联网上找不到任何相关内容。

GetModuleFileName() 将返回进程名称 proc.exe 而不是 Dll 名称。

【问题讨论】:

  • 您似乎遗漏了一些东西,但我不确定是什么。如果您动态地 加载两个不同的 dll 并使用 GetProcAddress,那么您已经知道正在调用哪个。在另一种情况下,由链接器决定链接到哪个 foo() ,因此在运行时调用。你描述的情况没有意义:exe要么从A或B链接到导入库,要么从两者链接,但在最后一种情况下,仍然只能使用一个 foo() 否则你会在链接过程中得到重复的符号错误..
  • 我上面提到的场景是我遇到的复杂问题的简单版本,以便于理解。 Dll 是通过隐式链接加载的,所以我没有这样做,LoadLibary() 和 GetProcAddress()。如果您在某个进程中注入您的 DLL,并且有许多线程正在运行。当您想解决同步问题时,提问没有意义吗?
  • 没有因为你说的几乎不可能:“方法 foo() 定义在两个 DLL A.dll 和 B.dll 中”。这是多重定义符号的标准配方,所以请解释一下你是如何做到的。如果您使用隐式链接,它将是 A 或 B 但不是两者,因为链接器不允许这样做。看来你把复杂的问题简单化了:]
  • 哦,是的......喜欢未解析的外部符号,多重定义的符号和所有其他链接器的疯狂。有时在导入项目后解决这些问题比更改您来的代码要长;)
  • @stijn 我不知道该怎么做,但我建议通过依赖项在标准 Microsoft Office 安装中查看两个 DLL EMSMDB32.dll(传输提供程序)和 MSPST32.dll(存储提供程序)沃克。这两个 DLL 都有一个公共方法 MSProviderInit()。仅供参考,Outlook 会将它们一起加载。

标签: c++ windows winapi dll


【解决方案1】:

假设你有函数的地址,你应该可以使用下面的方法来确定模块的基地址。

HMODULE ModuleFromAddress(void *address)
{
  MEMORY_BASIC_INFORMATION mbi;
  if (VirtualQuery(address, &mbi, sizeof(mbi)) != 0)
    return (HMODULE)mbi.AllocationBase;
  return NULL;
}

然后将结果输入GetModuleFileName

【讨论】:

【解决方案2】:

调用堆栈(至少在 MS Visual Studio 中)是否准确地说明了这一点? (抱歉,由于声誉限制,无法编写 cmets)

【讨论】:

  • 确实如此,但是访问调用堆栈以提供日志记录是多余的;但就像我的评论一样:我看不到 OP 如何知道它是哪个 foo
【解决方案3】:

你可以找到 foo 所在的地址和每个 dll 加载的地址范围。 Foo 必须在 2 个地址范围之一中。要找出加载 dll 的位置,请检查 Finding the memory address of a loaded DLL in a process in C++。链接中提到的 MODULEINFO 结构提供了起始地址和大小。

【讨论】:

  • 谢谢托拜厄斯。你的回答很有道理,但我认为这样一个微不足道的问题一定有一些简单的方法。
  • 是的,正如 stijin 之前提到的。您静态链接了 dll,您知道自己在调用什么。您告诉链接器在链接期间解决此问题。一切都是众所周知的。可能您的问题有所不同。
猜你喜欢
  • 1970-01-01
  • 2015-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多