class FrameFingerprint
Defined at line 68 of file ../../src/developer/debug/zxdb/client/frame_fingerprint.h
A FrameFingerprint is a way to compare stack frames across pause/resumes of the same thread. The
Frame pointers themselves are owned by the Thread and will be destroyed when the thread is
resumed. By saving a FrameFingerprint code can compare whether a future stop is the same or a
subframe of the previous one.
With stack frame pointers, an x64 prologue looks like this:
push rbp
mov rbp, rsp
The stack grows to smaller addresses as stuff is pushed (in this diagram, down). Before the call
say it looks like this:
0x1010 [data]
<
= BP
0x1008 [data]
0x1000 [data]
<
= SP
...... [garbage]
The CALL instruction will make it look like this:
0x1010 [data]
<
= BP (same as before call)
0x1008 [data]
0x1000 [data]
<
= FrameFingerprint.frame_address_
0x0ff8 [ret addr]
<
= SP (new)
And after the called function's prologue it will look like this:
0x1010 [data]
0x1008 [data]
0x1000 [data]
<
= FrameFingerprint.frame_address_
0x0ff8 [ret addr]
0x0ff0 [old BP]
<
= BP, SP (both new)
...... [function locals will be appended starting here]
Ideally we want a consistent way to refer to this stack frame that doesn't change across the
function prologue. GDB and LLDB use a "frame_id" (GDB) / "FrameID" (LLDB) which is a combination
of the "stack_addr" and "code_addr". Together these uniquely identify a stack frame.
Their "code_addr" is the address of the beginning of the function it's currently in (the
destination of the call above). This is easy enough to get from Location.function().
Their "stack_addr" for the function being called in this example will be 0x1000 which is the SP
from right before the call instruction. This is called the frame's "canonical frame address" in
DWARF. We can get this by looking at the previous frame's SP.
Because the inline count depends on other frames, the getter for this object is on the Stack
(Stack::GetFrameFingerprint).
INLINE FUNCTIONS
----------------
The above description deals with physical stack frames. Inline frames share the same physical
stack frame.
To differentiate the depth when inside inline frames of the same functions, the fingerprint also
keeps a depth of inline function calls. The frame address comes from the stack pointer before the
current physical frame.
Public Methods
bool operator== (const FrameFingerprint & other)
Returns true if the input refers to the same frame as this one. This will assert if either
frame is !is_valid().
Defined at line 13 of file ../../src/developer/debug/zxdb/client/frame_fingerprint.cc
std::string ToString ()
For debugging.
Defined at line 17 of file ../../src/developer/debug/zxdb/client/frame_fingerprint.cc
bool Newer (const FrameFingerprint & left, const FrameFingerprint & right)
Computes "left Newer than right". This doesn't use operator
<
or > because it's ambiguous
whether a newer frame is "less" or "greater".
Defined at line 22 of file ../../src/developer/debug/zxdb/client/frame_fingerprint.cc
bool NewerOrEqual (const FrameFingerprint & left, const FrameFingerprint & right)
static
Defined at line 33 of file ../../src/developer/debug/zxdb/client/frame_fingerprint.cc
void FrameFingerprint ()
Defined at line 70 of file ../../src/developer/debug/zxdb/client/frame_fingerprint.h
void FrameFingerprint (uint64_t frame_address, size_t inline_count)
We currently don't have a use for "function begin" so it is not included
here. It may be necessary in the future.
Defined at line 74 of file ../../src/developer/debug/zxdb/client/frame_fingerprint.h
bool is_valid ()
Defined at line 77 of file ../../src/developer/debug/zxdb/client/frame_fingerprint.h