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