This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: supporting DW_OP_{implicit,stack}_value


> Thanks. BTW. You removed DW_OP_GNU_push_tls_address in 96349f, I assume
> by accident.

D'oh.  Committing too early in the morning.  (Fixed now.)

> That would certainly work for me. You would also need a variant that
> takes a Dwarf_Frame to match up with .debug_frame/.eh_frame.

Nope.  CFI can have arbitrary DWARF expressions, but these are not location
descriptions.  (The new DWARF draft makes this definitional distinction
much more clear than DWARF 3 does.)  DW_OP_implicit_value, like
DW_OP_stack_value and DW_OP_piece, only appears in location descriptions.
It's fortunate IMHO that it's clearly not kosher, but regardless it's hard
to imagine how a situation would ever arise where the compiler wanted to
use DW_OP_implicit_value or DW_OP_piece in CFI.

While I have you here and confused, let me bring up the related idea that
superficially appears opposite to what I just said.  That was:

** consider changing new CFI calls interface for loc/val: use DW_OP_stack_value

What I meant here was the dwarf_frame_register API.  I had wanted to ask
you about this, though it occurs to me that you have probably not used
this call at all since you were just doing DW_OP_call_frame_cfa and not
actually using libdw CFI support for register decoding.  But you're the
closest I've got to a user of the API anyway, so I'd like your opinions.

To recap the background: a DWARF expression is a sequence of stack
operations that computes some target-address-sized value.  A location
description is one of several kinds of things or combinations thereof,
the simplest of which, and a constituent of most of the others, is a
DWARF expression.  The most common kind is a memory location
description, which is a DWARF expression computing an address.
DW_OP_reg* expressions are not DWARF expressions (don't compute a
value), but are one kind of location description.  The new wrinkle is
called "implicit location descriptions", which is a location description
that consists of just DW_OP_implicit_value or is a location description
that consists of a DWARF expression followed by DW_OP_stack_value.
Those are "implicit" because there is no actual location, but instead an
encoded/computed value--so the debugger can report the value but not
change it.  A composite location description is multiple location
descriptions (each being of any of these other sorts) combined via
DW_OP_piece (or DW_OP_bit_piece).  Finally, "a location description" is
either one of those sorts of "single location descriptions", or is a
location list, 

In CFI, there are two kinds of things: registers and the CFA.  (The return
address is treated as a numbered pseudo-register even if there is no "PC
register" as such in the machine's language.)  The CFA is a value (that
happens to be an address), not a memory location where something in
particular is indicated to reside.  Registers are usually stored in memory
locations (or other registers) where they can be expressed as locations
(and can be changed there to affect the caller, etc.), but sometimes are
expressed only as values.

This latter case, "implicit register locations in CFI" exists in DWARF 3
(DW_CFA_val_expression, DW_CFA_val_offset*).  Before the recent draft,
this notion did not exist in location descriptions.  Now, one could
consider DW_CFA_val_expression a redundant way to express what could
have been DW_CFA_expression with an expression using DW_OP_stack_value.
(But note that in the proper definitions as above, the DWARF expressions
that can be embedded in CFI are just DWARF expressions and not location
descriptions, so DW_OP_stack_value there is not actually kosher per the
new draft spec.)

The concept of the libdw dwarf_frame_* API is to translate CFI details
into the terms of a location description, so that higher layers need
contemplate only one representation of "where is this datum stored" for
both callers' registers and program-level objects.  But I devised the
dwarf_frame_* API before these new kinds of value-only location
description existed.  Thus its API explicitly expresses the notion of
value vs location in different ways.

As I mentioned, the CFA is always just a value.  
Hence dwarf_frame_cfa just yields a DWARF expression.

For registers, it can be either a mutable location or a computed value.
There is furthermore the CFI-specific concepts of "undefined" and "same_value".
So dwarf_frame_register's API is complex:

   Returns -1 for errors, 0 if REGNO has an accessible location,
   or 1 if REGNO has only a computable value.  Stores at *NOPS
   the number of operations in the array stored at *OPS.
   With return value 0, this is a DWARF location expression.
   With return value 1, this is a DWARF expression that computes the value.

   Return value 1 with *NOPS zero means CFI says the caller's REGNO is
   "undefined" here, i.e. it's call-clobbered and cannot be recovered.

   Return value 0 with *NOPS zero means CFI says the caller's REGNO is
   "same_value" here, i.e. this frame did not change it; ask the caller
   frame where to find it.

Now it perhaps makes sense to have dwarf_frame_register always yield a
"simple location description".  That is, either a DWARF expression or
register expression indicating an address, or one of those two followed
by DW_OP_stack_value, indicating a read-only computable value.

The CFI "undefined" state is represented naturally by an empty location
description.  It means the same thing: you can't get it because it was
optimized out.

The corner that remains nonobvious is "same_value".  This could be
represented for practical purposes just as a register location
expression {DW_OP_regx,regno} for a call on regno.  But this bothers me
a little because then we hide one bit (literally) of information, a
distinction that can exist in the CFI (even if the semantics of making
that distinction are not clear).  i.e., the CFI could give a register
rule that says it's in the same register, or even a DW_CFA_expression
giving DW_OP_reg* with that register number (though technically that's
not kosher since it's only a DWARF expression, not itself a location
description).  That says "I'm saving it there" vs saying "I haven't
touched it", which is a distinction I can understand in the abstract,
though it's hard to see what it actually means.  But anyway, that amount
of vagueness gives me the inclination to represent "same_value" more
distinctly in the API with something that valid CFI could never encode,
so it's unambiguous.  (I'm still thinking of "in-band" encoding
(i.e. just some choice of Dwarf_Op sequence), so "could never" is not
really true unless we check the expressions for it.)

Off hand my best thoughts are to yield a one-op expression of just
either DW_OP_nop or DW_OP_GNU_uninit.  Neither of these really means
something exactly analogous to this, but moreover neither of them can
validly appear alone as the sole op in a location description.  Hmm.
Maybe DW_OP_stack_value itself is a good choice for the same_value
representation!

So it would be:

extern int dwarf_frame_register (Dwarf_Frame *frame, int regno,
				 Dwarf_Op ops_mem[3], Dwarf_Op **ops)
  __nonnull_attribute__ (3, 4);

Return value -1 for errors, or number of operations at *NOPS.
An op sequence >1 long might end with DW_OP_stack_value,
with the same meaning as in a real location description.
0 means empty location description, i.e. DW_CFA_undefined.
An op sequence of just DW_OP_stack_value alone is a special case
meaning DW_CFA_same_value.


Thoughts?


Thanks,
Roland

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]