void getStackAsString()

in src/logging_stacktrace.c [50:145]


void getStackAsString(char* destination, size_t destinationSize)
{
    /*lazily call once SymInitialize*/
    LONG state;
    while ((state = InterlockedCompareExchange(&doSymInit, 1, 0)) != 2)
    {
        if (state == 0)
        {
            (void)SymInitialize(GetCurrentProcess(), NULL, TRUE);
            (void)InterlockedExchange(&doSymInit, 2);
        }
    }

    size_t copied;

    /*all following function calls are protected by the same SRW*/
    AcquireSRWLockExclusive(&lockOverSymCalls);

    uint16_t numberOfFrames = CaptureStackBackTrace(1, TRACE_MAX_STACK_FRAMES, stack, NULL);
    if (numberOfFrames == 0)
    {
        (void)snprintf(destination, destinationSize, "!CaptureStackBackTrace returned 0 frames");
    }
    else
    {
        HANDLE process = GetCurrentProcess();

        SYMBOL_INFO_EXTENDED symbolExtended;
        SYMBOL_INFO* symbol = &symbolExtended.symbol;

        symbol->MaxNameLen = TRACE_MAX_SYMBOL_SIZE;
        symbol->SizeOfStruct = sizeof(SYMBOL_INFO);

        for (uint16_t j = 0; j < numberOfFrames; j++)
        {
            DWORD64 address = (DWORD64)(stack[j]);
            DWORD displacement = 0;

            if (!SymFromAddr(process, address, NULL, symbol))
            {
                copied = memcat(destination, destinationSize, SymFromAddrFailed, sizeof(SymFromAddrFailed) - 1);
                destination += copied;
                destinationSize -= copied;
            }
            else
            {
                IMAGEHLP_LINE64 line;
                line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);

                char resultLine[TRACE_MAX_STACK_LINE_AS_STRING_SIZE];

                if (SymGetLineFromAddr64(process, address, &displacement, &line))
                {
                    int snprintfResult = snprintf(resultLine, sizeof(resultLine), "!%s %s:%" PRIu32 "%s", symbol->Name, line.FileName, (uint32_t)line.LineNumber, (j < numberOfFrames - 1) ? "\n" : "");
                    if (!(
                        (snprintfResult >= 0) && /*the returned value is nonnegative [...]*/
                        (snprintfResult < (int)sizeof(resultLine)) /*[...] and less than n.*/
                        ))
                    {
                        copied = memcat(destination, destinationSize, snprintfFailed, sizeof(snprintfFailed) - 1);
                        destination += copied;
                        destinationSize -= copied;
                    }
                    else
                    {
                        copied = memcat(destination, destinationSize, resultLine, snprintfResult);
                        destination += copied;
                        destinationSize -= copied;
                    }
                }
                else
                {
                    int snprintfResult = snprintf(resultLine, sizeof(resultLine), "!%s Address 0x%" PRIX64 "%s", symbol->Name, line.Address, (j < numberOfFrames - 1) ? "\n" : "");
                    if (!(
                        (snprintfResult >= 0) && /*the returned value is nonnegative [...]*/
                        (snprintfResult < (int)sizeof(resultLine)) /*[...] and less than n.*/
                        ))
                    {
                        copied = memcat(destination, destinationSize, snprintfFailed, sizeof(snprintfFailed) - 1);
                        destination += copied;
                        destinationSize -= copied;
                    }
                    else
                    {
                        copied = memcat(destination, destinationSize, resultLine, snprintfResult);
                        destination += copied;
                        destinationSize -= copied;
                    }
                }
            }
        }
        destination[-1] = '\0';
    }

    ReleaseSRWLockExclusive(&lockOverSymCalls);
}