This page was produced by an automated import process, and may have formatting errors; feel free to fix.

Stack Frames

A frame is a construct that GDB uses to keep track of calling and called functions.

GDB’s frame model, a fresh design, was implemented with the need to support DWARF’s Call Frame Information in mind. In fact, the term “unwind” is taken directly from that specification. Developers wishing to learn more about unwinders, are encouraged to read the DWARF specification, available from [http://www.dwarfstd.org http://www.dwarfstd.org].

GDB’s model is that you find a frame’s registers by “unwinding” them from the next younger frame. That is, ‘get_frame_register’ which returns the value of a register in frame #1 (the next-to-youngest frame), is implemented by calling frame #0’s frame_register_unwind (the youngest frame). But then the obvious question is: how do you access the registers of the youngest frame itself?

To answer this question, GDB has the sentinel frame, the “-1st” frame. Unwinding registers from the sentinel frame gives you the current values of the youngest real frame’s registers. If f is a sentinel frame, then get_frame_type (''f'') ≡ SENTINEL_FRAME. [Selecting-an-Unwinder ]

Selecting an Unwinder

The architecture registers a list of frame unwinders (struct frame_unwind), using the functions frame_unwind_prepend_unwinder and frame_unwind_append_unwinder. Each unwinder includes a sniffer. Whenever GDB needs to unwind a frame (to fetch the previous frame’s registers or the current frame’s ID), it calls registered sniffers in order to find one which recognizes the frame. The first time a sniffer returns non-zero, the corresponding unwinder is assigned to the frame. [Unwinding-the-Frame-ID ]

Unwinding the Frame ID

Every frame has an associated ID, of type struct frame_id. The ID includes the stack base and function start address for the frame. The ID persists through the entire life of the frame, including while other called frames are running; it is used to locate an appropriate struct frame_info from the cache.

Every time the inferior stops, and at various other times, the frame cache is flushed. Because of this, parts of GDB which need to keep track of individual frames cannot use pointers to struct frame_info. A frame ID provides a stable reference to a frame, even when the unwinder must be run again to generate a new struct frame_info for the same frame.

The frame’s unwinder’s this_id method is called to find the ID. Note that this is different from register unwinding, where the next frame’s prev_register is called to unwind this frame’s registers.

Both stack base and function address are required to identify the frame, because a recursive function has the same function address for two consecutive frames and a leaf function may have the same stack address as its caller. On some platforms, a third address is part of the ID to further disambiguate frames—for instance, on IA-64 the separate register stack address is included in the ID.

An invalid frame ID (outer_frame_id) returned from the this_id method means to stop unwinding after this frame.

null_frame_id is another invalid frame ID which should be used when there is no frame. For instance, certain breakpoints are attached to a specific frame, and that frame is identified through its frame ID (we use this to implement the "finish" command). Using null_frame_id as the frame ID for a given breakpoint means that the breakpoint is not specific to any frame. The this_id method should never return null_frame_id. [Unwinding-Registers ]

Unwinding Registers

Each unwinder includes a prev_register method. This method takes a frame, an associated cache pointer, and a register number. It returns a struct value * describing the requested register, as saved by this frame. This is the value of the register that is current in this frame’s caller.

The returned value must have the same type as the register. It may have any lvalue type. In most circumstances one of these routines will generate the appropriate value:

This register was not saved.

This register was copied into another register in this frame. This is also used for unchanged registers; they are “copied” into the same register.

This register was saved in memory.

This register was not saved, but the unwinder can compute the previous value some other way.

Same as frame_unwind_got_constant, except that the value is a target address. This is frequently used for the stack pointer, which is not explicitly saved but has a known offset from this frame’s stack pointer. For architectures with a flat unified address space, this is generally the same as frame_unwind_got_constant.

None: Internals Stack-Frames (last edited 2013-08-20 23:41:25 by StanShebs)

All content (C) 2008 Free Software Foundation. For terms of use, redistribution, and modification, please see the WikiLicense page.