[Dwarf-Discuss] Location list ranges vs. containing lexical block DW_AT_ranges

Ron Brender ron.brender@charter.net
Sun Mar 28 23:13:47 GMT 2010


Jakub and all,

Your inquiry raises some interesting and puzzling questions. Some of 
them are of the form "How can that possibly be correct?" See my 
interspersed notes below...

Ron

--------------------
Jakub Jelinek wrote:
> Hi!
> 
> We've been discussing recently what can a debug info consumer assume about
> location list ranges (or parts thereof) that are outside of containing
> DW_TAG_lexical_block/DW_TAG_inlined_subroutine DW_AT_ranges.
> As this is something that all the producers and consumers should better
> agree on, I'm raising the thing here.

Very appropriate...

> Consider a lexical block with DW_AT_ranges
> 10 .. 20
> 30 .. 40
> 50 .. 60
> and DW_TAG_variable as child of that DW_TAG_lexical_block.  The compiler
> finds out that the variable (or its value) lives from PC 12 to 22 in
> reg1, from PC 23 to 25 in reg2, from PC 25 to 28 in reg3, from PC 28 to
> 35 again in reg1,  from 48 to 65 in reg2 and from 68 to 95 has its
> value in reg4 - 16.  GCC would emit in this case in .debug_loc
> 12 .. 22 DW_OP_reg1
> 23 .. 25 DW_OP_reg2
> 25 .. 28 DW_OP_reg3
> 28 .. 35 DW_OP_reg1
> 48 .. 65 DW_OP_reg2
> 68 .. 95 DW_OP_breg4 -16 DW_OP_stack_value
> That is unfortunately very large, and for locations where the variable is
> not in lexical scope the debug info consumer shouldn't be able to tell
> anything about the variable, because it is not in scope.

Is this example "real", as in something gcc actually generated? Or is 
contrived for the purposes of discussion here?

I ask because it is important to sort out what it means for a variable 
to "have a value" outside its scope.

Q1: What does it mean for a range to extend beyond the scope of the 
variable?

This can easily occur when the value is still sitting around in a 
register after the scope is closed. Of course, the value is "dead" 
before or at scope end. The value will continue to be available until 
that register is reused for some other purpose.

Q2: What does it mean for a range to begin before the beginning of the 
scope of a variable?

This is a puzzle. The beginning of a variable range is either the 
beginning of the scope (when the value is undefined) or the result of 
the first assignment, which necessarily occurs inside the scope.

The only way that I can image that the range starts before the scope is 
if the variable is assigned from another variable with a larger scope 
and the two variables happen to be allocated to the same register! In 
this case there is no explicit assignment to begin the lifetime--it 
happens implicitly for "free".

Q3: What does it mean for a range to begin *and* end outside of the 
scope of the variable. For example, the

 > 23 .. 25 DW_OP_reg2

This makes no sense to me. If gcc really generated such an example, I 
question whether there is a gcc bug. If not, then lets remove this from 
the discussion--or demonstrate how it could plausibly arise from a 
reasonable compiler implementation.

> Therefore I wrote a GCC patch to crop .debug_loc lists to containing
> lexical scope's DW_AT_ranges (or DW_AT_low_pc..DW_AT_high_pc interval if
> the scope isn't fragmented).  .debug_loc list changed to:
> 12 .. 35 DW_OP_reg1
> 48 .. 65 DW_OP_reg2

This cannot be correct. Just because the value of the variable is 
available in reg1 in 12..22 and also in 28..35 does not mean that the 
value is available in reg1 in 23..27. But that is exactly what this 
description seems to imply.

I think I see where you are going--if the part of a range that is 
outside of the containing scope must be (actively) ignored by a 
debugger, then *any* description for what is happening outside that 
scope is acceptable (neither right nor wrong, because irrelevant).

> but the GDB people complained that this might be undesirable for watchpoints
> on the variable, where if a watchpoint is added on the variable in the first
> fragment that changes to the variable won't be noticed (resp. will be
> noticed in wrong spots) when the variable is not in the scope.

How can a change to a variable possibly occur when it is not in scope? 
My answer--it can't! The place that held the value of the variable when 
it was in scope can surely change, but not because the variable change 
but because some totally irrelevant use of the place is occurring.

One also has to wonder how GDB (or any other debugger) will implement 
watchpoints on a variable allocated in a register. Rarely is there 
hardware that will facilitate this--is simulation the only real 
alternative? In which case, the debugger should dearly want to switch 
from simulation back to real execution as soon as possible after the 
value of the variable is dead, and resume simulation only at the 
beginning of the next lifetime. I think "masking" variable ranges using 
the containing scope helps facilitate this goal. Anything else means the 
debugger has to implement the masking itself one way or another, to no 
useful advantage.

> So, my question for this list is, is the above a kosher optimization the
> debug info producer can do?  Note that the variable resp. its value
> doesn't really live in reg1 from 12 to 35, but only in that range in
> the spots where it is in scope.  If it is valid, then debug info consumers
> need to mask .debug_loc ranges with .debug_ranges ranges to find out
> where a variable is actually live somewhere (of course for most operations
> except watchpoints this works without any efforts - whenever the
> variable is looked up say on PC 23, it won't be found as it is not in scope,
> so its location list won't be even considered.  If it is not valid,
> the debug info producer would need to modify its output such that
> either .debug_loc locations are always masked with the containing
> DW_AT_ranges, or perhaps can say the variable is live in between somewhere,
> but only when it is actually live in there.
> Example of the masking to DW_AT_ranges by the producer would be
> 12 .. 20 DW_OP_reg1
> 30 .. 35 DW_OP_reg1
> 50 .. 60 DW_OP_reg2
> and example of keeping the variable alive in between only when it is
> actually live there would be either the first .debug_loc snippet above (the
> totally unoptimized one), or e.g.
> 12 .. 22 DW_OP_reg1
> 28 .. 35 DW_OP_reg1
> 48 .. 65 DW_OP_reg2
> (i.e. it would just remove location ranges which don't overlap DW_AT_ranges
> at all).  What do other producers resp. consumers do/assume here?

My take is that while the second alternate "should" be viable the first 
is the better description--and the one that perhaps DWARF should 
explicitly and definitively require of producers (if not already). 
Notice that these two have the same representation size (in this 
example) so size is not an advantage either way. It would be interesting 
to see some empirical studies of whether there is a non-trivial size 
advantage either way--I suspect not.





More information about the Dwarf-discuss mailing list