|
DWARF Standard
|
230109.1 |
Jakub Jelinek |
Values for optimized out arguments |
Enhancement |
Open |
Jakub Jelinek |
Section 2.5.1.7, pg 38
If some function has arguments that are never used in the function
or which are only used in code which compiler can prove are unreachable
and the function isn't accessible from other object files (or compiler creates
a local clone of a function), then some compilers can choose not to pass
that parameter at all. If that happens, DW_OP_entry_value isn't an option,
because when the argument isn't passed at all, there is no register or memory
location for it.
Consider:
static __attribute__((noinline)) int foo (int x, int y) { int z = x + y; return x; }
int bar (void) { return foo (3, 17) + foo (4, 18) + foo (5, 19); }
where noinline attribute is just used to keep the example sufficiently small
to explain. As y isn't stored anywhere but to a dead variable, there is no
need to pass it at all, so compiler can effectively emit
static int foo_alt (int x) { return x; }
and call it 3 times.
Still users might need to ask in a debugger the value
of y or z variables and it is possible to provide that value.
Unlike DW_OP_entry_value which can be used in debug info consumers in 2 different
ways, one is to find the caller (if possible) and if it can be found, look up
the register or memory referenced in DW_OP_entry_value in the
DW_TAG_call_site_parameter, or (mostly for non-interactive consumers) if we
know in advance we'll need DW_OP_entry_value, put a breakpoint at the start of
the function and collect there a value, then look up the remembered value
when evaluating DW_OP_entry_value, for the case of completely optimized away
arguments the latter method is not an option, there is nothing to remember
at function entry. Still, the optimized away arguments can be found
with the former method.
The following proposal introduces a new DWARF expression Special operation
DW_OP_parameter_ref.
In the above testcase, y would have DW_AT_location of
DW_OP_parameter_ref <y die> DW_OP_stack_ref
and z would have DW_AT_location of
DW_OP_breg5 <0> DW_OP_parameter_ref <y die> DW_OP_plus DW_OP_stack_ref
(where DW_OP_breg5 <0> is just an example from x86_64 how to get value of x).
Then, in the call sites of the 3 foo calls, one would have next to
DW_TAG_call_site_parameter
DW_AT_location DW_OP_reg5 // again x86_64 example where x is passed
DW_AT_call_value DW_OP_lit{3,4,5}
for the call site parameter of x also
DW_TAG_call_site_parameter
DW_AT_call_parameter <y die>
DW_AT_call_value DW_OP_lit{17,18,19}
Changes relative to dwarf6-20221116.pdf:
In 2.5.1.7 add:
3. DW_OP_parameter_ref
The DW_OP_parameter_ref operation pushes the value that the described
parameter would have if it was actually passed. It has a single operand:
In the 32-bit DWARF format, the operand is a 4-byte unsigned value; in the
64-bit DWARF format, it is an 8-byte unsigned value (see Section 7.4
following). The operand is used as the offset of a DW_TAG_formal_parameter
debugging information entry in a .debug_info section.
When evaluating DW_OP_parameter_ref, the consumer can try to virtually
unwind using the Call Frame Information (see Section 6.4 on page 174) and
find DW_TAG_call_site_parameter referencing the same DW_TAG_formal_parameter
debugging information entry through its DW_AT_call_parameter attribute.
In 7.7.1 add to Table 7.9:
DW_OP_parameter_ref ‡ 0xab 1 4- or 8-byte offset of DIE
In D.1.3 add to the end:
DW_OP_parameter_ref y DW_OP_stack_value
The values of parameter y found in DW_TAG_call_site_parameter
of the caller with DW_AT_call_parameter referencing also parameter y.