1

アプリケーションのスタック トレースを出力しようとしています。StackWalk64私のアプリケーションは でリリースされているため、使用できませんoptimization disabled。私たちは誰かが書いたライブラリx86を使用していましたが、似たようなものは見つかりませんでした。以下は、私がウェブ上で見つけたコードです。stracecodeprexx64x86

#include <Windows.h>
#include <DbgHelp.h>
#include <stdio.h>

#define INVALID_FP_RET_ADDR_VALUE 0x00000000
BOOL g_fSymInit;
HANDLE g_hProcess;
BOOL DisplaySymbolDetails(DWORD dwAddress)
{
    DWORD64 displacement = 0;
    ULONG64 buffer[(sizeof(SYMBOL_INFO) +
        MAX_SYM_NAME*sizeof(TCHAR) +
        sizeof(ULONG64) - 1) /
        sizeof(ULONG64)];
    PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
    pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
    pSymbol->MaxNameLen = MAX_SYM_NAME;
    if (SymFromAddr(g_hProcess,dwAddress,&displacement,pSymbol))
    {
        // Try to get the Module details
        IMAGEHLP_MODULE64 moduleinfo;
        moduleinfo.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
        if (SymGetModuleInfo64(g_hProcess,pSymbol->Address,&moduleinfo))
        {
            printf("%s!",moduleinfo.ModuleName);
        }
        else
        {
            printf("<ErrorModuleInfo_%d>!", GetLastError());
        }
        // now print the function name
        if (pSymbol->MaxNameLen > 0)
        {
            printf("%s",pSymbol->Name);
        }
        else
        {
            printf("<Unknown_Function>");
        }
    }
    else
    {
        printf(" <Unable to get symbol details_%d>", GetLastError());
    }
    return TRUE;
}
bool WalkTheStack()
{
    DWORD _ebp = INVALID_FP_RET_ADDR_VALUE;
    DWORD dwIPOfCurrentFunction = (DWORD)&WalkTheStack;
    // Get the current Frame pointer
    __asm
    {
        mov [_ebp], ebp
    }
    // We cannot walk the stack (yet!) without a frame pointer
    if (_ebp == INVALID_FP_RET_ADDR_VALUE)
        return false;
    printf("CurFP\t\t\tRetAddr\n");
    DWORD *pCurFP = (DWORD *)_ebp;
    BOOL fFirstFP = TRUE;
    while (pCurFP != INVALID_FP_RET_ADDR_VALUE)
    {
        // pointer arithmetic works in terms of type pointed to. Thus,
        // "+1" below is equivalent of 4 bytes since we are doing DWORD
        // math.
        DWORD pRetAddrInCaller = (*((DWORD *)(pCurFP + 1)));
        printf("%p\t\t%p ",pCurFP, (DWORD *)pRetAddrInCaller);
        if (g_fSymInit)
        {
            if (fFirstFP)
            {
                fFirstFP = FALSE;
            }
            DisplaySymbolDetails(dwIPOfCurrentFunction);
            // To get the name of the next function up the stack,
            // we use the return address of the current frame
            dwIPOfCurrentFunction = pRetAddrInCaller;
        }
        printf("\n");
        if (pRetAddrInCaller == INVALID_FP_RET_ADDR_VALUE)
        {
            // StackWalk is over now...
            break;
        }
        // move up the stack to our caller
        DWORD pCallerFP = *((DWORD *)pCurFP);
        pCurFP = (DWORD *)pCallerFP;
    }
    return true;
}

int main ( int argc, char **argv) {
    g_fSymInit = FALSE;
    g_hProcess = GetCurrentProcess();
    if (!SymInitialize(g_hProcess, NULL,TRUE)) {
        printf("Unable to initialize symbols!\n\n");    
    } else {
        g_fSymInit = TRUE;
    }
    SymSetOptions(SYMOPT_UNDNAME|SYMOPT_INCLUDE_32BIT_MODULES|SYMOPT_ALLOW_ABSOLUTE_SYMBOLS);
    WalkTheStack();
    return 0;
}

機能させるにはどのような変更が必要ですかx64

4

1 に答える 1

1

あなたがしたいことは、スタックを展開することです。その醜い混乱を修正するのではなく、関連する一般的な原則について説明します。x86 および x86_64 では、ebp/rsp および esp/rsp レジスタは、メモリ位置の暗黙的なリンク リストを形成します。各 esp/rsp は現在のスタック フレームの上部を指し、各 ebp/rbp は前のスタック フレームの下部を指します。この知識があれば、フレームを通り抜けるのはかなり簡単です。

于 2012-09-06T01:22:28.810 に答える