私はこれを投稿して、次の2つのことを言います。
1)ここで与えられた答えのほとんどは本当に悪く、簡単に壊れてしまいます. C 関数ポインター (関数名を使用) を使用する場合debug
、実行可能ファイルのビルド、および場合によっては他の状況で、関数本体自体を持たないJMP
shimを指す場合があります。これが例です。以下で定義した関数に対して次のことを行うと:
FARPROC pfn = (FARPROC)some_function_with_possibility_to_get_its_size_at_runtime;
pfn
I get (例: )は0x7FF724241893
これを指しますが、これは単なるJMP
指示です:

さらに、コンパイラはこれらのシムのいくつかをネストしたり、関数コードを分岐して、複数のエピローグまたはret
命令を持つようにすることができます。一体、それはret
命令さえも使用しないかもしれません。次に、関数自体がソース コードで定義した順序でコンパイルおよびリンクされるという保証はありません。
これらはすべてアセンブリ言語で実行できますが、C や C++ では実行できません。
2)というわけで、上記は悪いニュースでした。良いニュースは、元の質問に対する答えは、はい、正確な関数サイズを取得する方法(またはハック) があるということですが、次の制限があります。
概念は単純です。SEH がx64 Windows バイナリに実装されている方法を利用します。IMAGE_DIRECTORY_ENTRY_EXCEPTION
コンパイラは、正確な関数サイズを取得するために使用できるPE32+ ヘッダー (オプションのヘッダーのディレクトリ) に各関数の詳細を追加します。(ご参考までに、この情報は、ブロック内の例外のキャッチ、処理、巻き戻しに使用されます。)__try/__except/__finally
簡単な例を次に示します。
//You will have to call this when your app initializes and then
//cache the size somewhere in the global variable because it will not
//change after the executable image is built.
size_t fn_size; //Will receive function size in bytes, or 0 if error
some_function_with_possibility_to_get_its_size_at_runtime(&fn_size);
その後:
#include <Windows.h>
//The function itself has to be defined for two types of a call:
// 1) when you call it just to get its size, and
// 2) for its normal operation
bool some_function_with_possibility_to_get_its_size_at_runtime(size_t* p_getSizeOnly = NULL)
{
//This input parameter will define what we want to do:
if(!p_getSizeOnly)
{
//Do this function's normal work
//...
return true;
}
else
{
//Get this function size
//INFO: Works only in 64-bit builds on Windows!
size_t nFnSz = 0;
//One of the reasons why we have to do this at run-time is
//so that we can get the address of a byte inside
//the function body... we'll get it as this thread context:
CONTEXT context = {0};
RtlCaptureContext(&context);
DWORD64 ImgBase = 0;
RUNTIME_FUNCTION* pRTFn = RtlLookupFunctionEntry(context.Rip, &ImgBase, NULL);
if(pRTFn)
{
nFnSz = pRTFn->EndAddress - pRTFn->BeginAddress;
}
*p_getSizeOnly = nFnSz;
return false;
}
}