Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ - Get Starting Address of a function from Ending Address / Get size of a function

I am using /Gh and /GH compiler option of visual studio to profile a bunch of code. Two methods used are _penter and _pexit which are called when a function is entered or exited in the code being profiled. Since I need specific functions being profiled/debugged, I use an already defined array FuncTable which contains the addresses of the functions I need to instrument with their names as string. So when a function is entered, the pStack[0], which basically contains the register contents, contains the address to current line of the code being executed. Similarly when a function is exited, pStack[0] contains the address of last line of the code.

THE ISSUE: When a function is entered (_penter is called), I get the address of first line of the function in pStack[0] and hence I can get the function's address by subtracting a constant(-5) and save that to my list to be retrieved later in the _pexit function. But since in _pexit I am getting address to the last line of the function, I need to find the size of the function in order to subtract that size from the address in pStack[0] to reach the starting address of the function and then compare that address to the ones saved in my list. Pasted below is the code.

void _stdcall EnterFunc0(unsigned * pStack)
{
    void      * pCaller;
    pCaller = (void *)(pStack[0] - 5); // pStack[0] is first line, -5 for function address
    Signature * funct = FuncTable;

    while (funct->function)
    {
        const BYTE * func = (const BYTE *)funct->function;
        if ((func == (const BYTE *)pCaller) || ((*func == 0xE9) && ((func + *(DWORD *)(func + 1) + 5) == (const BYTE *)pCaller)))
        {
            Stack_Push(funct->name, funct->returnType, true, pCaller);          
        }
        funct++;
    }

}

extern "C" __declspec(naked) void __cdecl _penter()
{
    _asm
    {
        pushad              // save all general purpose registers
        mov    eax, esp     // current stack pointer
        add    eax, 32      // stack pointer before pushad
        push   eax          // push pointer to return address as parameter to EnterFunc0

        call   EnterFunc0

        popad               // restore general purpose registers
        ret                 // start executing original function
    }
}
void _stdcall ExitFunc0(unsigned * pStack)
{
    if (startRecording) 
    {
        StackEntry * start = top;
        while (start != NULL)
        {
            //**HERE I NEED TO COMPARE THE ADDRESS OF THE FUNCTION WITH THE ONE ALREADY IN MY STACK**
                            if ((void *)(pStack[0] - sizeOfTheFunction) == start->Address)
            {
                OutputDebugString("Function Found\n");
            }
            start = start->next;
        }
    }

}
extern "C" __declspec(naked) void __cdecl _pexit()
{
    _asm
    {
        pushad              // save all general purpose registers
        mov    eax, esp     // current stack pointer
        add    eax, 32      // stack pointer before pushad
        push   eax          // push pointer to return address as parameter to EnterFunc0

        call   ExitFunc0

        popad               // restore general purpose registers
        ret                 // start executing original function
    }
}
like image 742
Taha Rehman Siddiqui Avatar asked Nov 23 '25 05:11

Taha Rehman Siddiqui


1 Answers

You already know the address in your _pexit() function, it was handed to you in the _penter() function. All you have to do is support nested function calls. An std::stack<> is good for that. Use push() to save the address in _penter, retrieve it with top() in your _pexit function and call pop().

No need to know the function body size at all anymore.

like image 134
Hans Passant Avatar answered Nov 24 '25 19:11

Hans Passant



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!