Nugget
Bare-metal libraries and examples for the original PlayStation
Loading...
Searching...
No Matches
Classes | Static Public Member Functions | Static Public Attributes | List of all members
psyqo::ShadowStack Class Reference

Shadow call stack, filled in by BUILD=FastDebug. More...

#include <psyqo/shadow-stack.hh>

Classes

struct  Context
 One shadow stack, for one machine stack. More...
 

Static Public Member Functions

static constexpr unsigned depth ()
 
static constexpr uintptr_t entry (unsigned)
 
static constexpr unsigned copy (uintptr_t *, unsigned)
 
static constexpr Context * switchTo (Context *)
 

Static Public Attributes

static constexpr unsigned c_capacity = 64
 
static constexpr bool enabled = false
 

Detailed Description

Shadow call stack, filled in by BUILD=FastDebug.

MIPS GCC does not keep a walkable chain of frame pointers: even with -fno-omit-frame-pointer, where a function saves its caller's frame pointer depends on the size of its frame. So the FastDebug build type compiles everything with -finstrument-functions, and psyqo provides the __cyg_profile_func_enter and __cyg_profile_func_exit hooks, which push and pop the call site of every instrumented function onto a small array. Reading that array from anywhere gives the chain of return addresses that led there, which mipsel-none-elf-addr2line -f -e program.elf turns back into functions and lines. Each entry is a return address, 8 bytes past the jal, so subtract 8 to get the line of the call itself. The hooks cost two calls per function call.

FastDebug also defines PSYQO_SHADOW_STACK. Without it, the hooks are not compiled at all, enabled is false, and the accessors below return zero.

Entry 0 is the outermost call. The stack holds c_capacity entries; deeper calls are counted in depth() but their call sites are not stored, so the pops stay balanced and the innermost frames are the ones that go missing.

Rules for code running under FastDebug:

Member Function Documentation

◆ copy()

static constexpr unsigned psyqo::ShadowStack::copy ( uintptr_t *  ,
unsigned   
)
inlinestaticconstexpr

◆ depth()

static constexpr unsigned psyqo::ShadowStack::depth ( )
inlinestaticconstexpr

◆ entry()

static constexpr uintptr_t psyqo::ShadowStack::entry ( unsigned  )
inlinestaticconstexpr

◆ switchTo()

static constexpr Context * psyqo::ShadowStack::switchTo ( Context *  )
inlinestaticconstexpr

Member Data Documentation

◆ c_capacity

constexpr unsigned psyqo::ShadowStack::c_capacity = 64
staticconstexpr

◆ enabled

constexpr bool psyqo::ShadowStack::enabled = false
staticconstexpr

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