PStack  2.0
Stack trace printer for MSVC and GCC binaries
psystem::thread_info Class Reference

A container for a single thread of execution in a process. More...

#include <thread_info.hpp>

Inheritance diagram for psystem::thread_info:
Collaboration diagram for psystem::thread_info:

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_tracem_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_assignableoperator= (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.
 

Detailed Description

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().

Author
Matt Bisson
Date
5 August, 2014
Since
PSystem 2.0
Version
PSystem 2.0

Member Typedef Documentation

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.

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.

Constructor & Destructor Documentation

psystem::thread_info::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.

This constructor creates the thread_info instance for the main thread of exection for the process.

Parameters
[in]pidThe process's unique system ID (PID).
[in]tidThis thread's unique system ID (TID).
[in]infoInformation about the process and its main thread.
psystem::thread_info::thread_info ( process_id_t  pid,
thread_id_t  tid,
CREATE_THREAD_DEBUG_INFO const &  info 
)
noexcept

Construct an instance of thread_info.

This constructor deals with worker threads, and not the main thread for the process.

Parameters
[in]pidThe process's unique system ID (PID).
[in]tidThis thread's unique system ID (TID).
[in]infoInformation about the thread.

Member Function Documentation

void psystem::thread_info::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 
)
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.

Parameters
[in]process_handleA process handle for system debug API.
[in]thread_handleA thread handle for system debug API.
[in]address_to_symbolPassed to StackWalk64. Check MSDN for details.
[in]get_module_basePassed to StackWalk64. Check MSDN for details.
[out]outThis 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.
Exceptions
psystem::exception::system_exceptionIf there was an issue while traversing the stack frames.
Todo:
Better way to get this
process_id_t psystem::thread_info::get_process_id ( ) const
noexcept

Access the ID of the process that owns this thread.

Returns
The owning process's system ID (PID).
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.

Parameters
[in]procThe process owning this thread. Passing the incorrect thread will lead to undefined behavior!
[in]address_to_symbolThis parameter must match the PFUNCTION_TABLE_ACCESS_ROUTINE64 type. If this is nullptr, it will use the default SymFunctionTableAccess64 function.
[in]get_module_baseThis parameter must match the PGET_MODULE_BASE_ROUTINE64 type. If this is nullptr, it will use the default SymGetModuleBase64 function.
Returns
A listing of stack frames. This is a reference that will be valid until this instance is destroyed.
Exceptions
psystem::exception::system_exceptionIf there was an issue while traversing the stack frames.
Todo:
Find a way to get rid of the 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??
HANDLE psystem::thread_info::get_thread_handle ( ) const
noexcept

Retrieve the system handle to this thread.

This handle may be used with system debugging and thread inspection functions.

Returns
This handle is valid until the thread_info instance is destroyed.
thread_id_t psystem::thread_info::get_thread_id ( ) const
noexcept

Access the ID of this thread.

Returns
The unique system ID (TID) of this thread.

Member Data Documentation

std::unique_ptr<stack_trace> psystem::thread_info::m_stack_trace
mutableprivate

A list of the stack frames executing in this thread.

This is expensive to generate, and is only created lazily.

std::once_flag psystem::thread_info::m_stack_trace_lock
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.


The documentation for this class was generated from the following files: