Issue 241011.1: Expression Evaluation Context

Author: Tony Tye, Cary Coutant
Champion: Cary Coutant
Date submitted: 2024-10-11
Date revised: 2024-12-08
Date closed: 2025-01-06
Type: Clarification
Status: Accepted with editorial changes
DWARF version: 6

Comparing 2024-12-08 with latest. [ Return to the latest version ]


Background
----------

This proposal is editorial in nature: it does not intend to change the
meaning of any DWARF constructs, but merely to clarify aspects of
DWARF expression evaluation that were unclear to the teams implementing
DWARF consumers.

The context within which expression evaluation takes place is not
spelled out in the DWARF document, but mostly left to the reader to
infer based on scattered references throughout the sections on DWARF
expressions. The changes proposed below explicitly define the context
within which expression evaluation takes place.


Proposed Changes
----------------

Insert the following subsection under 2.5 (renumbering subsequent
subsections):

> ### 2.5.1 DWARF Expression Evaluation Context
>
> DWARF expressions and location descriptions (see Section 2.6) are
> evaluated within a context provided by the debugger or other DWARF
> consumer. The context includes the following elements:
>
> 1. Required result kind
>
>     The kind of result required -- either a location or a
>     value -- is determined by the DWARF construct where the expression
>     is found.
>
>     [non-normative] _For example, DWARF attributes with exprval class
>     require a value, and attributes with locdesc class require a
>     location description (see Section 7.5.5)._
>
> 2. Initial stack
>
>     In most cases, the DWARF expression stack is empty at the
>     start of expression evaluation. In certain circumstances,
>     however, one or more values are pushed implicitly onto the
>     stack before evaluation of the expression starts (e.g.,
>     `DW_AT_data_member_location`).
>
> 3. Current compilation unit
>
>     The current compilation unit is the compilation unit debugging
>     information entry that contains the DWARF expression being
>     evaluated.
>
>     A current compilation unit is required for operations that
>     reference debug information associated with the same compilation
>     unit, including indicating if such references use the 32-bit or
>     64-bit DWARF format.
>     ([non-normative] _For example, the `DW_OP_constx` and `DW_OP_addrx`
>     operations require the address size, which is a property of the
>     compilation unit._)
>
>     [non-normative] _Note that this compilation unit might not be the
>     same as the compilation unit determined from the loaded code
>     object corresponding to the current program location. For
>     example, the evaluation of the expression E associated with a
>     `DW_AT_location` attribute of the debug information entry operand
>     of the `DW_OP_call*` operations is evaluated with the compilation
>     unit that contains E and not the one that contains the
>     `DW_OP_call*` operation expression._
>
>     *[Removed:]*  
>     <span class="del">[non-normative] _The DWARF expressions for call frame information
>     (see 6.4 Call Frame Information) operations are restricted to
>     those that do not require a current compilation unit._</span>
>
> 4. Target architecture
>
>     The target architecture is typically provided by the object file
>     containing the DWARF information. It may also be refined by
>     instruction set identifiers in the line number table.
>
>     The target architecture is required for operations that specify
>     architecture-specific entities.
>
>     [non-normative] _Architecture-specific entities include DWARF
>     register identifiers, DWARF address space identifiers, the default
>     address space, and the address space address sizes._
>
> 5. Current thread
>
>     [non-normative] _Many programming environments support the concept of
>     independent threads of execution, where the process and its address
>     space are shared among the threads, but each thread has its own stack,
>     program counter, and possibly its own block of memory for thread-local
>     storage (TLS). These threads may be implemented in user-space or with
>     kernel threads, or by a combination of the two._
>
>     The current thread identifies a current thread of execution. When
>     debugging a multi-threaded program, the current thread may be
>     selected by a user command that focuses on a specific thread, or it
>     may be selected automatically when the running thread stops at a
>     breakpoint.
>
>     [non-normative] _If there is no running process (or an image of a
>     [non-normative] _If there is no current process (or an image of a
>     process, as from a core file), there is no current thread._
>
>     A current thread is required for the `DW_OP_form_tls_address`
>     operation (see Section 2.5.1.3) which provides access to
>     thread-local storage.
>
> 6. Current call frame
>
>     The current call frame identifies an active invocation of a
>     subprogram. It is identified by its address on the call stack (see
>     Section 3.3.5.2). The address is referred to as the frame base or
>     the call frame address (CFA). The call frame information is used
>     to determine the base addresses for the call frames of the current
>     thread’s call stack (see 6.4 Call Frame Information).
>
>     [non-normative] _When debugging a running program or examining a
>     core file, the current frame may be the topmost (most recently
>     activated) frame (e.g., where a breakpoint has triggered), or may
>     be selected by a user command to focus the view on a frame further
>     down the call stack. The current frame provides a view of the
>     state of the running process at a particular point in time._
>
>     The current call frame (if there is one) must be an active call
>     frame in the current call stack.
>
>     A current call frame is required for operations that use the
>     contents of registers (e.g., `DW_OP_reg*`) or frame-local storage
>     (e.g., `DW_OP_fbreg`) so that the debugger can retrieve values
>     from the selected view of the process state.
>
> 7. Current lane
>
>     [non-normative] _On SIMD (Single-Instruction Multiple-Data Stream)
>     and SIMT (Single-Instruction Multiple-Thread) architectures,
>     fine-grained parallel execution can be achieved by dispatching a
>     single instruction across multiple data streams (e.g., a vector or
>     array). Some parallel programming models allow for the
>     vectorization of loops using SIMD instructions. These parallel
>     streams can be considered fine-grain threads of execution, or
>     lanes, where each lane typically shares a common stack, program
>     lanes, where all lanes typically share a common stack, program
>     counter, and register file._
>
>     [non-normative] _In SIMT architectures, control flow may diverge
>     through the use of predication, where each instruction executes
>     only in certain lanes. Some SIMT architectures, however, provide
>     separate stacks and register files for each lane, and the parallel
>     streams of execution may instead be represented as threads
>     (above)._
>
>     The current lane is a SIMD/SIMT lane identifier. This applies to
>     source languages with scalar code that is vectorized by the
>     compiler using a SIMD/SIMT execution model. These implementations
>     map vectorized operations to SIMD/SIMT lanes of execution (see
>     Section 3.3.5.4). When debugging a SIMD/SIMT program, the current
>     lane is typically selected by a user command that focuses on a
>     specific lane.
>
>     The current lane must be consistent with the value of the
>     The current lane number must be consistent with the value of the
>     `DW_AT_num_lanes` attribute of the subprogram corresponding to
>     the current frame and program location. It is consistent if the value
>     the current frame and program location. It is consistent if the lane number
>     is greater than or equal to 0 and less than the, possibly default,
>     value of the `DW_AT_num_lanes` attribute.
>
>     If the current running program is not using a SIMD/SIMT
>     If the current program is not using a SIMD/SIMT
>     execution model, the current lane is always 0.
>
>     A current lane is required for the `DW_OP_push_lane` operation
>     (see Section 2.5.1.3), which pushes the value of the current lane.
>
> 8. Current program counter (PC)
>
>     The current program counter (PC) identifies the current point of
>     execution in the current call frame.
>
>     The PC in each call frame is the is the address of the next
>     The PC in each call frame is the address of the next
>     instruction to be executed in that frame. For the top (most
>     recent) frame on the call stack, this is where execution would
>     resume; for frames lower on the stack, it is where the callee will
>     return. The call frame information is used to obtain the value of
>     the return address register to determine the PC of the other call
>     frames (see 6.4 Call Frame Information).
>
>     If there is no running process, there is no current PC.
>     If there is no current frame, there is no current PC.
>
>     A current PC is required for the evaluation of value lists and
>     The current PC is used during the evaluation of value lists and
>     location lists to select from among multiple program location
>     ranges.
>
>     [non-normative] _When evaluating value lists and location lists
>     when no current pc is available, only default location
>     descriptions may be used._
>
> 9. Current object
>
>     The current object is a data object described by a data object entry
>     (see Section 4.1) that is being inspected. When evaluating
>     expressions that provide attribute values of a data object, the
>     containing debugging information entry is the current object. When
>     evaluating expressions that provide attribute values for a type
>     (e.g., `DW_AT_data_location` for a `DW_TAG_member`), the
>     current object is the data object entry (if there is one) that
>     referred to the type entry (e.g., via `DW_AT_type`).
>
>     A current object is required for the `DW_OP_push_object_address`
>     (see Section 2.5.1.3) operation and by some attributes (e.g.,
>     `DW_AT_data_member_location` and `DW_AT_use_location`) where the
>     object's location is provided as part of the initial stack.
>
> [non-normative] _A DWARF expression for a location description may be
> able to be evaluated without a thread, call frame, lane, program
> counter, or architecture context element. For example, the location of a
> global variable may be able to be evaluated without such context,
> while the location of local variables in a stack frame cannot be
> evaluated without additional context._

> *[Removed:]*  
> <span class="del">The `address_size` fields must match in the headers
> of all the entries in the `.debug_info`, `.debug_addr`, `.debug_line`,
> `.debug_rnglists`, `.debug_rnglists.dwo`, `.debug_loclists`, and
> `.debug_loclists.dwo` sections corresponding to any given program
> counter.</span>


### Section 2.5.2.2 Register Values [was 2.5.1.2]

In item 1, `DW_OP_fbreg`, add "(see Section 2.5.1)" at
the end of the first paragraph.


### Section 2.5.2.3 Stack Operations [was 2.5.1.3]

In item 13, `DW_OP_push_object_address`, add "(see Section 2.5.1)" at
the end of the first sentence.

In item 14, `DW_OP_form_tls_address`, change the first sentence to:

> The `DW_OP_form_tls_address` operation pops a value from the stack, which
> must have an integral type identifier, translates this value into an
> address in the thread-local storage for the current thread (see Section
> 2.5.1), and pushes the address onto the stack together with the generic
> type identifier.

In item 15, `DW_OP_call_frame_cfa`, change the first paragraph to:

> The `DW_OP_call_frame_cfa` operation pushes the value of the current
> call frame address (CFA), obtained from the Call Frame Information (see
> Section 2.5.1 and Section 6.4).

In item 16, `DW_OP_push_lane`, change the last sentence of the first paragraph to:

> See Section 2.5.1 and Section 3.3.5.

Remove following two non-normative paragraphs (which duplicate description
added in 2.5.1.)

### Section 2.6.2 Location Lists

Following the first bulleted list (after "End-of-list"), add the following
paragraph:

> If there is no current PC (see Section 2.5.1), only
> default location description entries will apply.


### Section 5.7.6 Data Member Entries

In bullet 2 under `DW_AT_data_member_location`, add "(see Section 2.5.1)"
at the end of the first paragraph.


### Section 5.14 Pointer to Member Type Entries

In the paragraph beginning "The `DW_AT_use_location` description is used
in conjunction...", add "(see Section 2.5.1)" at the end of the second
sentence:

> The `DW_AT_use_location` description is used in conjunction with the
> location descriptions for a particular object of the given pointer to
> member type and for a particular structure or class instance. The
> `DW_AT_use_location` attribute expects two values to be pushed onto
> the DWARF expression stack before the `DW_AT_use_location` description
> is evaluated (see Section 2.5.1). ...


### Section 6.4.2 Call Frame Instructions

Add the following after the first sentence of the second paragraph:

> The DWARF expressions for call frame information are restricted to
> those operations that do not require a current compilation unit (see
> Section 2.5.1).

---

2024-10-11: [Original proposal][orig]

2024-10-22: Revised based on committee discussion.

2024-10-23: Revised based on email discussions; added back-references
2024-10-23: [Revised][diff1] based on email discussions; added back-references
from later sections.

2024-10-28: Revised based on committee discussion. Added non-normative
2024-10-28: [Revised][diff2] based on committee discussion. Added non-normative
discussion about threads and lanes. Added back-reference from Section 5.14.

2024-12-08: Revised based on committee and off-line discussion.
2024-12-08: [Revised][diff3] based on committee and off-line discussion.
Removed non-normative paragraph about CFI and current compilation unit.
Rewrote sections on current thread, current frame, current lane, and
current PC.
Removed paragraph about `address_size` fields matching.

2025-01-06: Accepted with [editorial changes][diff4].
Changed "running process" to "current process"; rephrased paragraph
about how current PC is used; and other minor edits.