PStack
2.0
Stack trace printer for MSVC and GCC binaries
|
A container for a single thread of execution in a process. More...
#include <thread_info.hpp>
Type Definitions | |
typedef void *(__stdcall * | address_to_symbol_func) (HANDLE, DWORD64) |
Function pointer to a function that maps addresses to symbol information. More... | |
typedef DWORD64(__stdcall * | get_module_base_func) (HANDLE, DWORD64) |
Function pointer to a function that determines the module base address from any input address. More... | |
using | stack_trace = std::vector< stack_frame > |
The container for the entire stack trace. More... | |
Construction / Destruction | |
thread_info (process_id_t pid, thread_id_t tid, CREATE_PROCESS_DEBUG_INFO const &info) noexcept | |
Construct an instance of thread_info based on a process. More... | |
thread_info (process_id_t pid, thread_id_t tid, CREATE_THREAD_DEBUG_INFO const &info) noexcept | |
Construct an instance of thread_info. More... | |
Public Accessors | |
process_id_t | get_process_id () const noexcept |
Access the ID of the process that owns this thread. More... | |
HANDLE | get_thread_handle () const noexcept |
Retrieve the system handle to this thread. More... | |
thread_id_t | get_thread_id () const noexcept |
Access the ID of this thread. More... | |
Public Interface | |
stack_trace const & | get_stack_trace (process_info const &proc, address_to_symbol_func address_to_symbol, get_module_base_func get_module_base) const |
Retrieve a list of the stack frames that are active in the current thread. More... | |
Private Utilities | |
static void | generate_stack_trace (HANDLE process_handle, HANDLE thread_handle, address_to_symbol_func address_to_symbol, get_module_base_func get_module_base, std::unique_ptr< stack_trace > *out) |
Generate a stack trace for this thread. More... | |
Member Data | |
HANDLE | m_thread_handle |
The system debug API handle to this thread. | |
thread_id_t const | m_thread_id |
An unique ID for a thread of execution in a process. | |
process_id_t const | m_process_id |
The unique ID of the process that owns this thread. | |
std::unique_ptr< stack_trace > | m_stack_trace |
A list of the stack frames executing in this thread. More... | |
std::once_flag | m_stack_trace_lock |
Mutex for lazy generation of thread_info::m_stack_trace. More... | |
Additional Inherited Members | |
Protected Member Functions inherited from psystem::not_assignable | |
not_assignable & | operator= (not_assignable const &) const =delete |
Delete the basic assignment operator. | |
constexpr | not_assignable () noexcept |
A simple CTOR suitable for noexcept and constexpr uses. | |
~not_assignable () noexcept | |
A simple CTOR suitable for noexcept uses. | |
A container for a single thread of execution in a process.
This thread_info instance represents a thread of execution for a process being debugged. This may be a worker thread, or the main process thread (i.e., the thread containing the system's invocation of main
).
One important piece of data contained in this class is the stack trace. The thread_info makes this data available via get_stack_trace().
typedef void*(__stdcall * psystem::thread_info::address_to_symbol_func) (HANDLE, DWORD64) |
Function pointer to a function that maps addresses to symbol information.
This function type should have the same semantics as the Windows API, SymFunctionTableAccess64
. Form more information, see the MSDN entry for FunctionTableAccessProc64
.
typedef DWORD64(__stdcall * psystem::thread_info::get_module_base_func) (HANDLE, DWORD64) |
Function pointer to a function that determines the module base address from any input address.
This function type should have the same semantics as the Windows API, SymGetModuleBase64
. Form more information, see the MSDN entry for GetModuleBaseProc64
.
using psystem::thread_info::stack_trace = std::vector<stack_frame> |
The container for the entire stack trace.
This type models the Random Access Container concept. Stack frames indeces are zero-based, with the most recently invoked function (i.e., the current frame) at 0.
|
noexcept |
Construct an instance of thread_info based on a process.
This constructor creates the thread_info instance for the main thread of exection for the process.
[in] | pid | The process's unique system ID (PID). |
[in] | tid | This thread's unique system ID (TID). |
[in] | info | Information about the process and its main thread. |
|
noexcept |
Construct an instance of thread_info.
This constructor deals with worker threads, and not the main thread for the process.
[in] | pid | The process's unique system ID (PID). |
[in] | tid | This thread's unique system ID (TID). |
[in] | info | Information about the thread. |
|
staticprivate |
Generate a stack trace for this thread.
This method is part of a lazy initialization for the thread_info::m_stack_trace member variable. It is expected that it be called from the get_stack_trace() method. It is not possible to return a value from std::call_once
, so we've designed it to return data via parameters.
If the parameter, out
is nullptr
, this method simply does nothing.
[in] | process_handle | A process handle for system debug API. |
[in] | thread_handle | A thread handle for system debug API. |
[in] | address_to_symbol | Passed to StackWalk64 . Check MSDN for details. |
[in] | get_module_base | Passed to StackWalk64 . Check MSDN for details. |
[out] | out | This parameter receives the output of the stack trace generation. It may not be nullptr . The new stack_trace instance will only be assigned to out upon successful completion of the method. If the method fails, the value remains what it was when passed into the function. |
psystem::exception::system_exception | If there was an issue while traversing the stack frames. |
|
noexcept |
Access the ID of the process that owns this thread.
thread_info::stack_trace const & psystem::thread_info::get_stack_trace | ( | process_info const & | proc, |
address_to_symbol_func | address_to_symbol, | ||
get_module_base_func | get_module_base | ||
) | const |
Retrieve a list of the stack frames that are active in the current thread.
This method will attempt to generate a stack trace list on the first invocation, and (unless the generation was unsuccessful) any subsequent invocations will simply return that stack_trace
.
[in] | proc | The process owning this thread. Passing the incorrect thread will lead to undefined behavior! |
[in] | address_to_symbol | This parameter must match the PFUNCTION_TABLE_ACCESS_ROUTINE64 type. If this is nullptr , it will use the default SymFunctionTableAccess64 function. |
[in] | get_module_base | This parameter must match the PGET_MODULE_BASE_ROUTINE64 type. If this is nullptr , it will use the default SymGetModuleBase64 function. |
psystem::exception::system_exception | If there was an issue while traversing the stack frames. |
proc
parameter. It's illogical. We are a thread of execution in a process, so why do we need a process passed in? What if they pass a different process? What would that logically even mean??
|
noexcept |
Retrieve the system handle to this thread.
This handle may be used with system debugging and thread inspection functions.
|
noexcept |
Access the ID of this thread.
|
mutableprivate |
A list of the stack frames executing in this thread.
This is expensive to generate, and is only created lazily.
|
mutableprivate |
Mutex for lazy generation of thread_info::m_stack_trace.
The thread_info::m_stack_trace data is generated by the const
member function, get_stack_trace(). Mutable data altered in a const
context should always be protected by a threading guard.