コード例 #1
0
ファイル: callstack.cpp プロジェクト: rconde01/vld
UINT CallStack::isCrtStartupFunction( LPCWSTR functionName ) const
{
    size_t len = wcslen(functionName);

    if (beginWith(functionName, len, L"_malloc_crt")
        || beginWith(functionName, len, L"_calloc_crt")
        || endWith(functionName, len, L"CRT_INIT")
        || endWith(functionName, len, L"initterm_e")
        || beginWith(functionName, len, L"_cinit")
        || beginWith(functionName, len, L"std::`dynamic initializer for '")
        // VS2015
        || beginWith(functionName, len, L"common_initialize_environment_nolock<")
        || beginWith(functionName, len, L"common_configure_argv<")
        || beginWith(functionName, len, L"__acrt_initialize")
        || beginWith(functionName, len, L"__acrt_allocate_buffer_for_argv")
        || beginWith(functionName, len, L"_register_onexit_function")
        ) {
        return CALLSTACK_STATUS_STARTUPCRT;
    }

    if (endWith(functionName, len, L"DllMainCRTStartup")
        || endWith(functionName, len, L"mainCRTStartup")
        || beginWith(functionName, len, L"`dynamic initializer for '")) {
        // When we reach this point there is no reason going further down the stack
        return CALLSTACK_STATUS_NOTSTARTUPCRT;
    }

    return NULL;
}
コード例 #2
0
ファイル: callstack.cpp プロジェクト: viknash/vld
bool CallStack::isInternalModule( const PWSTR filename ) const
{
    size_t len = wcslen(filename);
    return
        // VS2015
        endWith(filename, len, L"\\atlmfc\\include\\atlsimpstr.h") ||
        endWith(filename, len, L"\\atlmfc\\include\\cstringt.h") ||
        endWith(filename, len, L"\\atlmfc\\src\\mfc\\afxmem.cpp") ||
        endWith(filename, len, L"\\atlmfc\\src\\mfc\\strcore.cpp") ||
        endWith(filename, len, L"\\vcstartup\\src\\heap\\new_scalar.cpp") ||
        endWith(filename, len, L"\\vcstartup\\src\\heap\\new_array.cpp") ||
        endWith(filename, len, L"\\vcstartup\\src\\heap\\new_debug.cpp") ||
        endWith(filename, len, L"\\ucrt\\src\\appcrt\\heap\\align.cpp") ||
        endWith(filename, len, L"\\ucrt\\src\\appcrt\\heap\\malloc.cpp") ||
        endWith(filename, len, L"\\ucrt\\src\\appcrt\\heap\\debug_heap.cpp") ||
        // VS2013
        beginWith(filename, len, L"f:\\dd\\vctools\\crt\\crtw32\\") ||
        //endWith(filename, len, L"\\crt\\crtw32\\misc\\dbgheap.c") ||
        //endWith(filename, len, L"\\crt\\crtw32\\misc\\dbgnew.cpp") ||
        //endWith(filename, len, L"\\crt\\crtw32\\misc\\dbgmalloc.c") ||
        //endWith(filename, len, L"\\crt\\crtw32\\misc\\dbgrealloc.c") ||
        //endWith(filename, len, L"\\crt\\crtw32\\heap\\new.cpp") ||
        //endWith(filename, len, L"\\crt\\crtw32\\heap\\new2.cpp") ||
        //endWith(filename, len, L"\\crt\\crtw32\\heap\\malloc.c") ||
        //endWith(filename, len, L"\\crt\\crtw32\\heap\\realloc.c") ||
        //endWith(filename, len, L"\\crt\\crtw32\\heap\\calloc.c") ||
        //endWith(filename, len, L"\\crt\\crtw32\\heap\\calloc_impl.c") ||
        //endWith(filename, len, L"\\crt\\crtw32\\string\\strdup.c") ||
        //endWith(filename, len, L"\\crt\\crtw32\\string\\wcsdup.c") ||
        // VS2010
        endWith(filename, len, L"\\crt\\src\\afxmem.cpp") ||
        endWith(filename, len, L"\\crt\\src\\dbgheap.c") ||
        endWith(filename, len, L"\\crt\\src\\dbgnew.cpp") ||
        endWith(filename, len, L"\\crt\\src\\dbgmalloc.c") ||
        endWith(filename, len, L"\\crt\\src\\dbgcalloc.c") ||
        endWith(filename, len, L"\\crt\\src\\dbgrealloc.c") ||
        endWith(filename, len, L"\\crt\\src\\dbgdel.cp") ||
        endWith(filename, len, L"\\crt\\src\\new.cpp") ||
        endWith(filename, len, L"\\crt\\src\\newaop.cpp") ||
        endWith(filename, len, L"\\crt\\src\\malloc.c") ||
        endWith(filename, len, L"\\crt\\src\\realloc.c") ||
        endWith(filename, len, L"\\crt\\src\\free.c") ||
        endWith(filename, len, L"\\crt\\src\\strdup.c") ||
        endWith(filename, len, L"\\crt\\src\\wcsdup.c") ||
        endWith(filename, len, L"\\vc\\include\\xmemory0") ||
        // default
        (false);
}
コード例 #3
0
ファイル: callstack.cpp プロジェクト: viknash/vld
// isCrtStartupAlloc - Determines whether the memory leak was generated from crt startup code.
// This is not an actual memory leaks as it is freed by crt after the VLD object has been destroyed.
//
//  Return Value:
//
//    true if isCrtStartupModule for any callstack frame returns true.
//
bool CallStack::isCrtStartupAlloc()
{
    if (m_status & CALLSTACK_STATUS_STARTUPCRT) {
        return true;
    } else if (m_status & CALLSTACK_STATUS_NOTSTARTUPCRT) {
        return false;
    }

    IMAGEHLP_LINE64  sourceInfo = { 0 };
    sourceInfo.SizeOfStruct = sizeof(IMAGEHLP_LINE64);

    BYTE symbolBuffer[sizeof(SYMBOL_INFO) + MAX_SYMBOL_NAME_SIZE] = { 0 };
    CriticalSectionLocker<DbgHelp> locker(g_DbgHelp);

    // Iterate through each frame in the call stack.
    for (UINT32 frame = 0; frame < m_size; frame++) {
        // Try to get the source file and line number associated with
        // this program counter address.
        SIZE_T programCounter = (*this)[frame];
        BOOL             foundline = FALSE;
        DWORD            displacement = 0;
        DbgTrace(L"dbghelp32.dll %i: SymGetLineFromAddrW64\n", GetCurrentThreadId());
        foundline = g_DbgHelp.SymGetLineFromAddrW64(g_currentProcess, programCounter, &displacement, &sourceInfo);

        if (foundline) {
            DWORD64 displacement64;
            LPCWSTR functionName = getFunctionName(programCounter, displacement64, (SYMBOL_INFO*)&symbolBuffer, locker);
            if (beginWith(functionName, wcslen(functionName), L"`dynamic initializer for '")) {
                break;
            }

            if (isCrtStartupModule(sourceInfo.FileName)) {
                m_status |= CALLSTACK_STATUS_STARTUPCRT;
                return true;
            }
        }
    }

    m_status |= CALLSTACK_STATUS_NOTSTARTUPCRT;
    return false;
}
コード例 #4
0
ファイル: callstack.cpp プロジェクト: viknash/vld
// Resolve - Creates a nicely formatted rendition of the CallStack, including
//   symbolic information (function names and line numbers) if available. and
//   saves it for later retrieval. This is almost identical to Callstack::dump above.
//
//   Note: The symbol handler must be initialized prior to calling this
//     function.
//
//  - showInternalFrames (IN): If true, then all frames in the CallStack will be
//      dumped. Otherwise, frames internal to the heap will not be dumped.
//
//  Return Value:
//
//    None.
//
int CallStack::resolve(BOOL showInternalFrames)
{
    if (m_resolved)
    {
        // already resolved, no need to do it again
        // resolving twice may report an incorrect module for the stack frames
        // if the memory was leaked in a dynamic library that was already unloaded.
        return 0;
    }

    if (m_status & CALLSTACK_STATUS_STARTUPCRT) {
        // there is no need to resolve a leak that will not be reported
        return 0;
    }

    if (m_status & CALLSTACK_STATUS_INCOMPLETE) {
        // This call stack appears to be incomplete. Using StackWalk64 may be
        // more reliable.
        Report(L"    HINT: The following call stack may be incomplete. Setting \"StackWalkMethod\"\n"
            L"      in the vld.ini file to \"safe\" instead of \"fast\" may result in a more\n"
            L"      complete stack trace.\n");
    }

    int unresolvedFunctionsCount = 0;
    IMAGEHLP_LINE64  sourceInfo = { 0 };
    sourceInfo.SizeOfStruct = sizeof(IMAGEHLP_LINE64);

    bool skipStartupLeaks = !!(g_vld.GetOptions() & VLD_OPT_SKIP_CRTSTARTUP_LEAKS);

    // Use static here to increase performance, and avoid heap allocs.
    // It's thread safe because of g_heapMapLock lock.
    static WCHAR stack_line[MAXREPORTLENGTH + 1] = L"";
    bool isPrevFrameInternal = false;
    bool isDynamicInitializer = false;
    DWORD NumChars = 0;
    CriticalSectionLocker<DbgHelp> locker(g_DbgHelp);

    const size_t max_line_length = MAXREPORTLENGTH + 1;
    m_resolvedCapacity = m_size * max_line_length;
    const size_t allocedBytes = m_resolvedCapacity * sizeof(WCHAR);
    m_resolved = new WCHAR[m_resolvedCapacity];
    if (m_resolved) {
        ZeroMemory(m_resolved, allocedBytes);
    }

    // Iterate through each frame in the call stack.
    for (UINT32 frame = 0; frame < m_size; frame++)
    {
        // Try to get the source file and line number associated with
        // this program counter address.
        SIZE_T programCounter = (*this)[frame];
        DWORD            displacement = 0;

        // It turns out that calls to SymGetLineFromAddrW64 may free the very memory we are scrutinizing here
        // in this method. If this is the case, m_Resolved will be null after SymGetLineFromAddrW64 returns.
        // When that happens there is nothing we can do except crash.
        DbgTrace(L"dbghelp32.dll %i: SymGetLineFromAddrW64\n", GetCurrentThreadId());
        BOOL foundline = g_DbgHelp.SymGetLineFromAddrW64(g_currentProcess, programCounter, &displacement, &sourceInfo, locker);

        if (skipStartupLeaks && foundline && !isDynamicInitializer &&
            !(m_status & CALLSTACK_STATUS_NOTSTARTUPCRT) && isCrtStartupModule(sourceInfo.FileName)) {
            m_status |= CALLSTACK_STATUS_STARTUPCRT;
            delete[] m_resolved;
            m_resolved = NULL;
            m_resolvedCapacity = 0;
            m_resolvedLength = 0;
            return 0;
        }

        bool isFrameInternal = false;
        if (foundline && !showInternalFrames) {
            if (isInternalModule(sourceInfo.FileName)) {
                // Don't show frames in files internal to the heap.
                isFrameInternal = true;
            }
        }

        // show one allocation function for context
        if (NumChars > 0 && !isFrameInternal && isPrevFrameInternal) {
            m_resolvedLength += NumChars;
            if (m_resolved) {
                wcsncat_s(m_resolved, m_resolvedCapacity, stack_line, NumChars);
            }
        }
        isPrevFrameInternal = isFrameInternal;

        DWORD64 displacement64;
        BYTE symbolBuffer[sizeof(SYMBOL_INFO) + MAX_SYMBOL_NAME_SIZE];
        LPCWSTR functionName = getFunctionName(programCounter, displacement64, (SYMBOL_INFO*)&symbolBuffer, locker);

        if (skipStartupLeaks && foundline && beginWith(functionName, wcslen(functionName), L"`dynamic initializer for '")) {
            isDynamicInitializer = true;
        }

        if (!foundline)
            displacement = (DWORD)displacement64;
        NumChars = resolveFunction( programCounter, foundline ? &sourceInfo : NULL,
            displacement, functionName, stack_line, _countof( stack_line ));

        if (NumChars > 0 && !isFrameInternal) {
            m_resolvedLength += NumChars;
            if (m_resolved) {
                wcsncat_s(m_resolved, m_resolvedCapacity, stack_line, NumChars);
            }
        }
    } // end for loop

    m_status |= CALLSTACK_STATUS_NOTSTARTUPCRT;
    return unresolvedFunctionsCount;
}