Issue 230412.1: Ambiguity in Static and Dynamic Values of Attributes (was DW_AT_string_length)

Author: Cary Coutant
Champion: Cary Coutant
Date submitted: 2023-04-12
Date revised: 2024-01-30
Date closed: 2024-02-05
Type: Clarification
Status: Accepted
DWARF Version: 6

Background

In Issue 160811.1 for DWARF 5, we added the reference class as an allowed attribute class for DW_AT_string_length, and changed the text in Section 2.19 (Static and Dynamic Values of Attributes) from:

The value of these attributes is determined based on the class as follows:

  • For a constant, the value of the constant is the value of the attribute.

  • For a reference, the value is a reference to another entity which specifies the value of the attribute.

  • For an exprloc, the value is interpreted as a DWARF expression; evaluation of the expression yields the value of the attribute.

to:

The value of these attributes is determined based on the class as follows:

  • For a constant, the value of the constant is the value of the attribute.

  • For a reference, the value is a reference to another debugging information entry. This entry may:

    • describe a constant which is the attribute value,

    • describe a variable which contains the attribute value, or

    • contain a DW_AT_location attribute whose value is a DWARF expression which computes the attribute value (for example, a DW_TAG_dwarf_procedure entry).

  • For an exprloc, the value is interpreted as a DWARF expression; evaluation of the expression yields the value of the attribute.

For the reference class bullet, I have several questions:

  1. In case 1, what do we mean by "This entry may... describe a constant"? Is this referring to a DW_TAG_constant, or to any DIE that might have a DW_AT_const_value attribute? Or either?

  2. In case 2, I read "a variable which contains the attribute value" to mean that we're looking at a DW_TAG_variable DIE (or perhaps DW_TAG_formal_parameter or DW_TAG_member) where the value we're looking for is either: (a) the value given by DW_AT_const_value or (b) stored at the location specified by DW_AT_location. Does this need clarification?

  3. Case 3 seems to overlap with case 2. If the entry contains a DW_AT_location attribute, and is a variable, then we have case 2. But if it's a dwarf procedure, then we say the DW_AT_location attribute "computes the attribute value," which could be interpreted to mean the DWARF expression there computes a value rather than a location where the value is stored. I think that's obviously wrong, but isn't that the implication?

For the exprloc class bullet, it seems to say that the DWARF expression evaluates directly to a value, not a location description. So does that mean DW_OP_reg5, for example, is invalid? I take this to mean that for these attributes, an exprloc form is meant to evaluate to a value, not a location, so the only way to provide a location is via a reference. Sound right?

In Section 4.1, under DW_AT_default_value, the third bullet for references to a DWARF procedure is also unclear as to whether the evaluation of the DWARF procedure should be interpreted as a value or a location. It's clear that a reference to a variable (which is, by definition, a DWARF procedure, if it has a DW_AT_location attribute) refers to the value of that variable. When referring to a DWARF procedure, are we referring to any DWARF procedure other than a variable, or only to DW_TAG_dwarf_procedure entries?

In Section 5.11 (String Type Entries), the DWARF 5 wording is:

The string type entry may also have a DW_AT_string_length attribute whose value is either a reference (see Section 2.19) yielding the length of the string or a location description yielding the location where the length of the string is stored in the program....

I think the phrasing here, "a reference ... yielding the length of the string" is confusing, even with the cross-reference to Section 2.19.

History of Section 2.19

In DWARF 4, the relevant text was simply:

The value of these attributes is determined based on the class as follows:

  • For a constant, the value of the constant is the value of the attribute.

  • For a reference, the value is a reference to another entity which specifies the value of the attribute.

  • For an exprloc, the value is interpreted as a DWARF expression; evaluation of the expression yields the value of the attribute.

In Issue 100805.1, the question was raised of how a reference to another "entity" actually specified the value, and the following replacement text was proposed for the second bullet:

  • For a reference, the value is a reference to another DIE. This DIE may

    • describe a variable which contains the attribute value

    • describes a constant which is the attribute value

    • contain a DWARF expression which computes the attribute value

The minutes from the 6/9/12 meeting have this question: "Should the last clause (the DWARF expression reference) be dropped given that none of us are sure what it means?" Further discussion suggested the possibility that a DWARF procedure could be used for an expression that is used in several places, as a space-savings measure. Another comment mentioned: "Maybe we should make it clear that if we're pointing to a DWARF Procedure that contains an expression to compute the value, it can use the DW_OP_stack_value."

In the 9/18/12 meeting, that sub-bullet was revised to:

  • contain a DWARF expression which computes the attribute value or is a dwarf procedure which computes the attribute value

The final wording in the DWARF 5 document appears to have been editorial:

  • contain a DW_AT_location attribute whose value is a DWARF expression which computes the attribute value (for example, a DW_TAG_dwarf_procedure entry).

This suggests that it was intended that references to variables (or to any "data object") were intended to reference the value of the variable whose location is given, but that references to other entries with a DW_AT_location attribute (e.g., DWARF procedures) were intended to reference the value of the DWARF expression (disregarding the use of the DW_AT_location attribute for the purpose).

In the 1/22/24 meeting, we questioned whether a reference to a DWARF procedure was necessary or ever used by a producer. It was noted that in every case where a reference class form was allowed, an exprval class form was also allowed (subject to verification). Thus, there should be no need to use a reference to a DWARF procedure, when a direct expression could be used, even if that expression is nothing but a DW_OP_call_ref to a DWARF procedure.

References to Section 2.19

Here are the locations in the document where Section 2.19 is explicitly referenced, and the attributes that may have a reference class:

Only DW_AT_string_length allows reference class forms but not exprval. For this attribute a DW_FORM_exprloc is interpreted as locdesc instead. But that still allows an expression that computes the actual value in the form of an implicit location description, and that expression could use DW_OP_call_ref.

Therefore, I propose to drop the wording allowing the use of a reference to a DWARF procedure (that is not a data object or common block).

Proposal

[Section and page numbers refer to the 12/5/23 working draft.]

Section 2.19 Static and Dynamic Values of Attributes, page 57

The second bullet about reference class should be rewritten as:

  • For a reference, the value of the attribute is determined indirectly via a reference to another debugging information entry.

    • If the referenced entry describes a constant (e.g., has a DW_AT_const_value attribute), the attribute value is the value of that constant.

    • If the referenced entry describes a data object (see 4.1) or common block (see 4.2), the attribute value is the value of the data object or common block.

    • If the referenced entry represents a data member (e.g. has either a DW_AT_data_member_location or a DW_AT_data_bit_offset attribute), the attribute value is the value of the data member.

    [non-normative] In previous versions of DWARF, a reference to a DWARF procedure (see 2.16) that is not a data object or common block was allowed. This type of reference was removed in DWARF 6. Instead, a producer may use an exprval or locdesc class form with a DW_OP_call_ref operator to call the DWARF procedure.

For the exprloc class bullet, see issue 230616.1.

Section 4.1 Data Object Entries, page 101

Remove the third bullet under item 9 (about DW_AT_default_value), which reads:

  • If the attribute form is of class reference, and the referenced entry is a DWARF procedure, the default value of the parameter is the value returned by calling that DWARF procedure (using DW_OP_call_ref), interpreted as a value of the type of the formal parameter.

Section 5.11 String Type Entries, page 132

Change:

The string type entry may also have a DW_AT_string_length attribute whose value is either a reference (see Section 2.19) yielding the length of the string or a location description yielding the location where the length of the string is stored in the program.

to:

The string type entry may also have a DW_AT_string_length attribute whose value is either (a) a reference (see Section 2.19) to another debugging information entry that provides the value of or the location of the length of the string, or (b) a location description...


2023-08-01: Revised. Added rules governing size and signedness of attribute values.

2023-11-24: Revised to add data members; added "unless specified otherwise" when talking about attributes giving a size, count, or enumerated value.

2024-01-04: Revised to clarify the use of other attributes of a referenced entry.

2024-01-30: Revised to drop wording allowing a reference to a DWARF procedure.

2024-02-05: Accepted.