[Dwarf-discuss] Interpretation of FBREG: implied deref of frame_base?

Todd Allen todd.allen
Thu Apr 21 19:47:45 GMT 2005


First off, I apologize if this message gets too pedantic.  I found that
useful as I was writing it.

A location description describes the location of an entity.

I know: duh.  But here's the point: It describes the entity's location, and
not its value.  Of course, it's pretty obvious how to get a value given a
location, but that's a step that's beyond the scope of the location
description.

Don't believe me?  From 2.5: Information about the location of program
objects is provided by location descriptions.

There are two kinds of location: a register and an address.  When
DW_AT_location mentions DW_OP_reg1 by itself, that means the location is r1.
When it mentions an address by itself, that address is the location of the
variable.  When it mentions a dereference of another location (be it a
register or an address), you have to dereference that location to get the
address of the variable.  No matter what sort of dereferencing, calculating,
or whatnot the location description does, the end result is a location.

I know concrete examples are helpful to me, so here's one.  Starting with a
machine state of a hypothetical machine:

   register     current value
   --------------------------
   r0         :             0   (called register 0 by Dwarf)
   r1         :             1   (called register 1 by Dwarf)
   r2         :    0x20000000   (called register 2 by Dwarf)

   address      current value
   --------------------------
   0x20000000 :    0x30000000
   0x30000000 :             4

And some example variables:

   DW_TAG_variable
      DW_AT_name     "fred"
      DW_AT_location DW_OP_reg1
   DW_TAG_variable
      DW_AT_name     "barney"
      DW_AT_location DW_OP_breg2
   DW_TAG_variable
      DW_AT_name     "betty"
      DW_AT_location DW_OP_reg2 DW_OP_deref
   DW_TAG_variable
      DW_AT_name     "wilma"
      DW_AT_location DW_OP_reg2 DW_OP_deref DW_OP_deref
   DW_TAG_variable
      DW_AT_name     "pebbles"
      DW_AT_location DW_OP_addr 0x20000000
   DW_TAG_variable
      DW_AT_name     "bambam"
      DW_AT_location DW_OP_addr 0x20000000 DW_OP_deref

And here is what that means for each variable:

   variable   C-ish location description   location    current value
   -----------------------------------------------------------------
   fred       r1                           r1                      1
   barney     *(r2)                        0x20000000     0x30000000
   betty      *(r2)                        0x20000000     0x30000000
   wilma      **(r2)                       0x30000000              4
   pebbles    0x20000000                   0x20000000     0x30000000
   bambam     *(0x20000000)                0x30000000              4

--------------------------------------------------------------------------------

Now to move on to DW_OP_frame_base.  It computes the "frame base" for the
subroutine.  The standard doesn't say it describes a location, but it does
say that it's a location description, and because a location description
describes a location, that's good enough.

So, as before, there are two kinds of locations: address and register.  

A frame base which is an address is pretty straightforward.  It's an address
somewhere in or near the stack frame that can be used by DW_OP_fbreg.

There's no explicit rule that says DW_AT_frame_base must describe an address,
as opposed to a register.  But I can't imagine a frame base that actually was
a register (and I mean the register itself and not an address in the
register).  Furthermore, this text for DW_OP_fbreg implies that the
DW_AT_frame_base must describe an address:

   The DW_OP_fbreg operation provides a signed LEB128 offset from the address
   specified by the location description in the DW_AT_frame_base attribute.

So, I'd have to deduce that a frame base must be an address, and not a
register.  But, as mentioned above, a location description which is
DW_OP_reg1 by itself means a location which is a register.  So, it and
location descriptions like it would have no defined meaning.

Given that compilers actually are emitting such a location description, and
that its meaning currently is undefined, I don't have a problem with making
it a special case.  But I think it's important that we be clear that it is a
special case.

--------------------------------------------------------------------------------

I know I frequently use the term "dereference" to describe how to get a
value, given a location.  I bet a lot of other people do, too.  I'm not
certain that it's a technically accurate term for it, on the grounds that
"dereference" applies only to pointers, and turns the pointer into the
denoted location.

I'm going to take this opportunity to do a really pedantic analysis of how to
get the value of variable wilma from above, calling out exactly which things
are locations (addresses or registers) and values, and describing the
dereference (DW_OP_deref) operations.  This is to clarify for myself and
others the sense of the terminology I'm using here:

   DW_OP_reg1:  start with register r2.
   DW_OP_deref: get register r2's value, which is 0x20000000;
                interpret value 0x20000000 as address 0x20000000.
   DW_OP_deref: get address 0x20000000's value, which is 0x30000000;
                interpret value 0x30000000 as address 0x30000000.
   (get value): get address 0x30000000's value, which is 4.

Now having said that, I think Ron's use of "dereference" in the special case
for DW_OP_regn in DW_AT_frame_base is just fine.  A dereference is an
operation that takes a pointer and produces a location.  And that's exactly
what a dereference would do in this case: take a pointer (in the register)
and produce a location (the location of the frame base).

On a personal note, I thought that Ron's use of "dereference" helped to
clarify the situation.

--------------------------------------------------------------------------------

And having said all that about dereferencing, I'm now going to point out a
side issue: a Dwarf expression can compute a general value, and if that value
was in memory, you would have to terminate the location description with a
DW_OP_deref (or DW_OP_deref_size).  To accomodate that, the Dwarf standard
would have to permit a looser definition of "dereference" which includes
simply getting a value and not interpreting it as an address.

--------------------------------------------------------------------------------

Now to address some of Chris's points directly:

> Some values are marked with extra semantics of being a "reference" value.

I suppose the term ""reference" value" here is equivalent to my use of
"location".  I assert that DW_AT_location always describes a location,
period.  If you want a value from that location, that's your business and not
the business of DW_AT_location.

> DW_AT_location should always take an expression which calculates a
> machine address.

That's incorrect, since it can have an expression which is just a register,
and that register is not an address, but it is a valid location of an entity.

> DW_AT_value_expr (or something like that) should use an expression to
> calculate the actual value of a variable.

This I agree with completely.  But DW_AT_value_expr does not have a location
description.  It has the more general "Dwarf expression", which is allowed to
describe a value.

> DW_AT_frame_base should act like DW_AT_value_expr.

To translate this into different terms, I think you're arguing that
DW_AT_frame_base should not have a location description, but rather a Dwarf
expression that computes a value which is equivalent to the frame base
address.  I think that that's more confusing than that leaving it as a
location description with Ron's special case for registers.

> If you say that DW_OP_reg7 "names" a register, then DW_OP_plus must
> take arguments that can be either values *or* "names" of registers.

The only place where this would come up would be a location description that
was something like this:

   DW_OP_reg7 DW_OP_lit4 DW_OP_plus

I would consider that a location description whose meaning is undefined.  You
can't add a literal to a register.  You only can add it the value of a
register, i.e. the dereference of the register, like this:

   DW_OP_reg7 DW_OP_deref DW_OP_lit4 DW_OP_plus

Or, more concisely:

   DW_OP_breg7 0 DW_OP_lit4 DW_OP_plus

(I know it could be even more concise than that, but it would defeat the
point of the example.)

-- 
Todd Allen
Concurrent Computer Corporation




More information about the Dwarf-discuss mailing list