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 |
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:
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).
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).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_constxandDW_OP_addrxoperations 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_locationattribute of the debug information entry operand of theDW_OP_call*operations is evaluated with the compilation unit that contains E and not the one that contains theDW_OP_call*operation expression.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.
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 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_addressoperation (see Section 2.5.1.3) which provides access to thread-local storage.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.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 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 number must be consistent with the value of the
DW_AT_num_lanesattribute of the subprogram corresponding to 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 theDW_AT_num_lanesattribute.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_laneoperation (see Section 2.5.1.3), which pushes the value of the current lane.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 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 current frame, there is no current PC.
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.
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_locationfor aDW_TAG_member), the current object is the data object entry (if there is one) that referred to the type entry (e.g., viaDW_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_locationandDW_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.
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_addressoperation 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_cfaoperation 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_locationdescription 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. TheDW_AT_use_locationattribute expects two values to be pushed onto the DWARF expression stack before theDW_AT_use_locationdescription 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
2024-10-22: Revised based on committee discussion.
2024-10-23: Revised based on email discussions; added back-references from later sections.
2024-10-28: Revised 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.
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. Changed "running process" to "current process"; rephrased paragraph about how current PC is used; and other minor edits.