Как Зарегистрировать Стековые фреймы с Windows x64

Словарь толкований добавляет слой ненужной сложности. Вы можете просто сделать это:

d1 = {'inds': [1, 2, 3, 4,], 'vals': [0.28, 0.84, 0.71, 0.03]}
result = dict(zip(d1["inds"],d1["vals"]))
print(result)

{1: 0.28, 2: 0.84, 3: 0.71, 4: 0.03}

Если вы используете Python 3.7, вы можете сделать это тоже:

result = dict(zip(*d1.values()))
25
задан RED SOFT ADAIR 20 January 2010 в 13:33
поделиться

10 ответов

Наконец-то я нашел надежный способ регистрировать фреймы стека в x64, используя функцию Windows CaptureStackBackTrace () . Поскольку я не хотел обновлять свой SDK, я вызываю его через GetProcAddress (LoadLibrary ());

   typedef USHORT (WINAPI *CaptureStackBackTraceType)(__in ULONG, __in ULONG, __out PVOID*, __out_opt PULONG);
   CaptureStackBackTraceType func = (CaptureStackBackTraceType)(GetProcAddress(LoadLibrary("kernel32.dll"), "RtlCaptureStackBackTrace"));

   if(func == NULL)
       return; // WOE 29.SEP.2010

   // Quote from Microsoft Documentation:
   // ## Windows Server 2003 and Windows XP:  
   // ## The sum of the FramesToSkip and FramesToCapture parameters must be less than 63.
   const int kMaxCallers = 62; 

   void* callers[kMaxCallers];
   int count = (func)(0, kMaxCallers, callers, NULL);
   for(i = 0; i < count; i++)
      printf(TraceFile, "*** %d called from %016I64LX\n", i, callers[i]);
18
ответ дан 28 November 2019 в 21:52
поделиться

Мы используем мини-дампы исключительно здесь. Можно генерировать разделенный вниз тот, который просто включает данные стека, и разгрузите отслеживание стека от достойного отладчика позже.

Это не решает Вашу проблему непосредственно, но я думаю, что это предоставит Вам намного лучший механизм создания отчетов вскрытия.

1
ответ дан 28 November 2019 в 21:52
поделиться

Для версии 2008 x 64: на основе https://msdn.microsoft.com/en-us/library/windows/desktop/bb204633%28v=vs.85%29.aspx и RED SOFT ADAIR :

#if defined DEBUG_SAMPLES_MANAGEMENT  

#include "DbgHelp.h"
#include <WinBase.h>
#pragma comment(lib, "Dbghelp.lib")

void printStack( void* sample_address, std::fstream& out )
{
    typedef USHORT (WINAPI *CaptureStackBackTraceType)(__in ULONG, __in ULONG, __out PVOID*, __out_opt PULONG);
    CaptureStackBackTraceType func = (CaptureStackBackTraceType)(GetProcAddress(LoadLibrary(L"kernel32.dll"), "RtlCaptureStackBackTrace"));

    if(func == NULL)
        return; // WOE 29.SEP.2010

    // Quote from Microsoft Documentation:
    // ## Windows Server 2003 and Windows XP:  
    // ## The sum of the FramesToSkip and FramesToCapture parameters must be less than 63.
    const int kMaxCallers = 62; 

    void         * callers_stack[ kMaxCallers ];
    unsigned short frames;
    SYMBOL_INFO  * symbol;
    HANDLE         process;
    process = GetCurrentProcess();
    SymInitialize( process, NULL, TRUE );
    frames               = (func)( 0, kMaxCallers, callers_stack, NULL );
    symbol               = ( SYMBOL_INFO * )calloc( sizeof( SYMBOL_INFO ) + 256 * sizeof( char ), 1 );
    symbol->MaxNameLen   = 255;
    symbol->SizeOfStruct = sizeof( SYMBOL_INFO );

    out << "(" << sample_address << "): " << std::endl;
    const unsigned short  MAX_CALLERS_SHOWN = 6;
    frames = frames < MAX_CALLERS_SHOWN? frames : MAX_CALLERS_SHOWN;
    for( unsigned int i = 0;  i < frames;  i++ )
    {
        SymFromAddr( process, ( DWORD64 )( callers_stack[ i ] ), 0, symbol );
        out << "*** " << i << ": " << callers_stack[i] << " " << symbol->Name << " - 0x" << symbol->Address << std::endl;
    }

    free( symbol );
}
#endif

Вызывается здесь:

#if defined DEBUG_SAMPLES_MANAGEMENT
        if(owner_ != 0)
        {   
            std::fstream& out = owner_->get_debug_file();
            printStack( this, out );   
        }
#endif
1
ответ дан 28 November 2019 в 21:52
поделиться

Наблюдайте это, я не знаю, релевантно ли это:
...
Работа с Ассемблерным кодом Ассемблерного кода проста к порту к AMD64 и 64-разрядному Windows— и стоит усилия по причинам производительности! Например, можно использовать в своих интересах новые 64-разрядные регистры общего назначения (r8-r15), и новую плавающую точку и 128-разрядные регистры точки SSE/SSE2/floating (xmm8-xmm15). Однако существуют новые 64-разрядные стековые фреймы и соглашения о вызовах, необходимо изучить приблизительно в ABI (двоичный интерфейс приложений) спецификации.
...

0
ответ дан 28 November 2019 в 21:52
поделиться

Хитрость в том, чтобы перестать звонить StackWalk64, когда он возвращает 0 в stk.AddrReturn.Offset. Это означает, что в стеке больше нет кадров. Если stk.AddrReturn.Offset не равен нулю, вы можете использовать это значение в качестве адреса возврата.

Если вы продолжите вызывать StackWalk64 после этого, я предполагаю, что он попытается интерпретировать все, что находится в ячейках памяти, как стек и вернет непредсказуемые данные.

0
ответ дан 28 November 2019 в 21:52
поделиться

StackWalk64 является правильным выбором, первый вызов даст Вам адрес вызывающей стороны.

Ваша проблема могла бы состоять в том, что в выпуске у Вас есть большое встраивание продолжения. Обратный адрес не может быть тем, что Вы ожидаете.

редактирование: только необходимо установить AddrPC и AddrFrame. Просто удостоверьтесь, что Ваш rbp и разрыв - те соответствующие Вашему контексту вызываемого.

0
ответ дан 28 November 2019 в 21:52
поделиться

Относительно первой проблемы: отключите «Пропускать кадры стека» в версии выпуска, и «тривиальный» код трассировки стека будет работать.

0
ответ дан 28 November 2019 в 21:52
поделиться

Найденный короткой версией с действительно полезным "CaptureStackBackTraceType"!

Затем разрешенные имена функций "вызывающих сторон []" использование SymFromAddr () , SymInitialize () , который является главным образом версией от Pedro Reis

и наконец demangled функциональные подписи согласно функция к функциям mangle/demangle

ПРИМЕЧАНИЕ: GNU demangler функция abi::__cxa_demangle() ожидает префикс одинарного подчеркивания

0
ответ дан 28 November 2019 в 21:52
поделиться

Что касается RtlCaptureStackBackTrace, я заметил одну вещь в 32-битной Windows: она не работает, если вы передадите в нее слишком большое число для FramesToCapture. Экспериментально я определил 61 как максимальное значение, без какой-либо причины, которую я могу понять!

Не уверен, то же самое в x64, но это может объяснить, почему вы не получаете информации.

0
ответ дан 28 November 2019 в 21:52
поделиться

Разбирая RtlCaptureStackBackTrace() я заметил, что максимальное значение, передаваемое в RtlCaptureStackBackTrace() должно быть: framesToSkip+framesToCapture+1 должно быть меньше 64. В противном случае возвращается 0 и нет других кодов ошибок.

0
ответ дан 28 November 2019 в 21:52
поделиться