This is the mail archive of the
dwarf2@corp.sgi.com
mailing list for the dwarf2 project.
Re: location lists revisited
- To: eager at eagercon dot com (Michael Eager)
- Subject: Re: location lists revisited
- From: todd dot allen at ccur dot com (Todd Allen)
- Date: Wed, 21 Mar 2001 09:12:22 -0700 (MST)
- Cc: dwarf2 at corp dot sgi dot com (dwarf2)
- Reply-To: todd dot allen at ccur dot com (Todd Allen)
>
> Todd Allen wrote:
> >
> > Thinking about how I would implement the DWARF replication approach for
> > local copies of global variables has brought me back to my original
> > question about this issue. I don't think the DWARF replication approach,
> > alone, will support it. I'll reiterate the problem with a concrete
> > example in 3 sources:
> >
> > source1.c:
> > int global;
> >
> > function foo()
> > {
> > ...
> > for (; global < ...; global++) {
> > ... global is used ...
> > }
> > ...
> > }
> >
> > source2.c:
> > extern int global;
> >
> > function bar()
> > {
> > ...
> > for (; global < ...; global++) {
> > ... global is used ...
> > }
> > ...
> > }
> >
> > source3.c:
> > /* Notice no extern int global, nor any include files */
> >
> > function unrelated()
> > {
> > ...
> > }
> >
> > Because global is used in a loop in both foo() and bar(), local read/write
> > copies are made in both of those functions.
> >
> > That means that in both source1.o and source2.o, a location list will be
> > generated for global. In source1.o, it will describe the in-memory
> > location for most of the .text in that object file, but will describe the
> > in-register location for the relevant part of foo(). In source2.o, the
> > location list would either do much the same thing, or because global has a
> > non-defining declaration there, it might only describe in the in-register
> > location for the relevant part of bar().
> >
> > Either way, how would a debugger stopped in unrelated() determine the
> > location of global? Certainly, that's something that DWARF should
> > support. (Yes, whether a debugger supports it is a QoI issue, but DWARF
> > shouldn't stand in the way.)
>
> Are you suggesting that when you stop in unrelated(), that the value
> of 'global' is somewhere other than in the global location?
>
Not at all. I'm saying, "how does a debugger know which is the global
location?" Let me be even more explicit with this example by showing an
example DWARF dump for what I at least think is your proposal for how this
should be done:
source1.o:
DIE (0xb) [] 1
DW_TAG_compile_unit
DW_CHILDREN_yes
DW_AT_low_pc(DW_FORM_addr) 0x1000
DW_AT_high_pc(DW_FORM_addr) 0x3000
DW_AT_language(DW_FORM_udata) DW_LANG_C89
DW_AT_name(DW_FORM_string) "source1.c"
DIE (0x86) [] 4
DW_TAG_variable
DW_CHILDREN_no
DW_AT_external(DW_FORM_flag) TRUE
DW_AT_type(DW_FORM_ref_addr) -> int
DW_AT_name(DW_FORM_string) "global"
DW_AT_location(DW_FORM_block) [0x1000..0x1080 => DW_OP_addr global,
0x1080..0x2f00 => DW_OP_reg17,
0x2f00..0x3000 => DW_OP_addr global]
DIE (0x99) [] 2
DW_TAG_subprogram
DW_CHILDREN_no
DW_AT_name(DW_FORM_string) "foo"
DW_AT_external(DW_FORM_flag) TRUE
DW_AT_type(DW_FORM_ref_addr) -> int
DW_AT_low_pc(DW_FORM_addr) 0x1040
DW_AT_high_pc(DW_FORM_addr) 0x3000
DIE (0xa0) [] 0
DW_TAG_padding
DW_CHILDREN_no
source2.o:
DIE (0xb) [] 1
DW_TAG_compile_unit
DW_CHILDREN_yes
DW_AT_low_pc(DW_FORM_addr) 0x4000
DW_AT_high_pc(DW_FORM_addr) 0x7000
DW_AT_language(DW_FORM_udata) DW_LANG_C89
DW_AT_name(DW_FORM_string) "source2.c"
DIE (0x86) [] 4
DW_TAG_variable
DW_CHILDREN_no
DW_AT_declaration(DW_FORM_flag) TRUE
DW_AT_type(DW_FORM_ref_addr) -> int
DW_AT_name(DW_FORM_string) "global"
DW_AT_location(DW_FORM_block) [0x4000..0x4080 => DW_OP_addr global,
0x4080..0x4f00 => DW_OP_reg20,
0x6f00..0x7000 => DW_OP_addr global]
DIE (0x86) [] 2
DW_TAG_subprogram
DW_CHILDREN_no
DW_AT_name(DW_FORM_string) "bar"
DW_AT_external(DW_FORM_flag) TRUE
DW_AT_type(DW_FORM_ref_addr) -> int
DW_AT_low_pc(DW_FORM_addr) 0x4040
DW_AT_high_pc(DW_FORM_addr) 0x7000
DIE (0xa0) [] 0
DW_TAG_padding
DW_CHILDREN_no
source3.o:
DIE (0xb) [] 1
DW_TAG_compile_unit
DW_CHILDREN_yes
DW_AT_low_pc(DW_FORM_addr) 0x8000
DW_AT_high_pc(DW_FORM_addr) 0xb000
DW_AT_language(DW_FORM_udata) DW_LANG_C89
DW_AT_name(DW_FORM_string) "source3.c"
DIE (0x86) [] 2
DW_TAG_subprogram
DW_CHILDREN_no
DW_AT_name(DW_FORM_string) "unrelated"
DW_AT_external(DW_FORM_flag) TRUE
DW_AT_type(DW_FORM_ref_addr) -> int
DW_AT_low_pc(DW_FORM_addr) 0x8040
DW_AT_high_pc(DW_FORM_addr) 0xb000
DIE (0xa6) [] 0
DW_TAG_padding
DW_CHILDREN_no
The only two declarations of global described in the DWARF had to be
described with location lists, because in each object in which they appeared,
they were at different locations in various points in those objects.
(Note that I am using your "non-defining declarations can have location
lists" extension here.) Also, I'm expanding the location lists right in the
dump, because it's easier to understand that way.
So, how does a debugger stopped at a point outside either of those objects
(e.g. at 0x8100), and trying to reference or modify "global" know which
location to use? Probably, it would want to track down the defining
declaration, but that has a location list, and that list doesn't cover the
current pc. How does it know which of the locations is the one that's good
for the pc at which it's stopped?
In this example, it probably could make a good guess that it doesn't want the
register. But that's just a heuristic and I wouldn't want to have to depend
on it.
--
Todd Allen
Concurrent Computer Corporation