我需要确定调用者代码是来自EXE还是DLL。
#ifdef DLL_EXPORTS
__declspec(dllexport) void say_hello();
__declspec(dllexport) void getCurrentModuleName();
#else
__declspec(dllimport) void say_hello();
__declspec(dllexport) void getCurrentModuleName();
#endif
#include <cstdio>
#include <windows.h>
#include <Dbghelp.h>
#include <iostream>
#include <tchar.h>
#include "dll.h"
#include "Psapi.h"
__declspec(naked) void *GetStackPointer()
{
__asm
{
mov eax, esp
ret
}
}
void getCurrentModuleName()
{
BOOL result = SymInitialize(GetCurrentProcess(), NULL , TRUE);
DWORD64 dwBaseAddress = SymGetModuleBase64(GetCurrentProcess(), (DWORD64)GetStackPointer());
TCHAR szBuffer[50];
GetModuleBaseName(GetCurrentProcess(), (HMODULE) dwBaseAddress, szBuffer, sizeof(szBuffer));
std::wcout << _T("--->") << szBuffer << std::endl;
}
void say_hello() {
getCurrentModuleName();
}
#include <windows.h>
#include <cstdio>
#include "dll.h"
int main() {
printf ("ENTERING EXE CODE...\n");
getCurrentModuleName();
printf ("ENTERING DLL CODE...\n");
say_hello();
getchar();
}
这是输出。
ENTERING EXE CODE...
--->exe.exe
ENTERING DLL CODE...
--->exe.exe
我希望我能得到
ENTERING EXE CODE...
--->exe.exe
ENTERING DLL CODE...
--->dll.dll
由于最后一个调用者代码来自DLL本身(DLL中的say_hello)
有什么方法可以实现这个目标吗?
答案 0 :(得分:3)
GetStackAddress返回ESP的值,它是对堆栈的引用。堆栈按线程分配,与进程中加载的任何模块无关。 你需要做的是从堆栈中提取,返回地址的值 - 这将是调用模块中的一个地址。
鉴于函数中通常的前缀代码是:
push ebp
mov ebp,esp
sub esp, bytes_of_local_variables
esp会有点随机,但[ebp]应指向前一个ebp,[ebp + 4]应该指向当前帧的返回地址。
所以,你可以试试这个:
__declspec(naked) void *GetReturnAddressAssumingStandardFramePointers()
{
__asm
{
mov eax, [ebp+4]
ret
}
}
只需确保调用的函数不会使用/Oy
进行编译答案 1 :(得分:1)
在这种情况下,使用函数的返回地址,您可以通过直接查看堆栈来确定。其余的答案仍然适用。
答案 2 :(得分:0)
你在DLL中有getCurrentModuleName()
内的堆栈指针,但你需要在getCurrentModuleName()
的开头从堆栈中返回返回的地址,它显示了调用getCurrentModuleName()
的位置。< / p>
答案 3 :(得分:0)
使用EnumProcessModules()。对于每一个调用GetModuleInformation()。将您正在执行的函数的地址(使用函数指针)与MODULEINFO结构的lpBaseOfDll和SizeOfImage成员进行比较。如果它在范围内,你知道这是当前的模块。如果是这样,请使用GetModuleBaseName检索模块的名称。
答案 4 :(得分:0)
这是解决方案。限制是,它最多只能跟踪62帧。
// Must have in order for us to turned address into module name.
SymInitialize(GetCurrentProcess(), NULL , TRUE);
// Limitation of RtlCaptureStackBackTrace.
const int kMaxCallers = 62;
void* callers[kMaxCallers];
int count = RtlCaptureStackBackTrace(0, kMaxCallers, callers, NULL);
for (int i = 0; i < count; i++) {
TCHAR szBuffer[50];
DWORD64 dwBaseAddress = SymGetModuleBase64(GetCurrentProcess(), (DWORD64)callers[i]);
GetModuleBaseName(GetCurrentProcess(), (HMODULE) dwBaseAddress, szBuffer, sizeof(szBuffer));
std::wcout << _T("--->") << szBuffer << std::endl;
}