This is the mail archive of the
dwarf2@corp.sgi.com
mailing list for the dwarf2 project.
Re: location lists
- To: eager at eagercon dot com
- Subject: Re: location lists
- From: todd dot allen at ccur dot com (Todd Allen)
- Date: Thu, 8 Mar 2001 13:34:57 -0700 (MST)
- Cc: dwarf2 at corp dot sgi dot com (dwarf2)
- Reply-To: todd dot allen at ccur dot com (Todd Allen)
>
> May I suggest looking for implementations where no extension is necessary?
>
I'd love to find one. Really. That was my first approach. I thought
location lists would cover it nicely, but I was wrong about that. And I'm
still looking for solutions that are already in the spec. I'm just having
a great deal of difficulty find any that cover the cases I need to cover,
and which aren't so much work as to be prohibitive.
I'm certainly not looking for gratuitous extensions, if that's what you're
thinking.
> > The only different implementation I see is to scrap our compilation model,
> > and start replicating debug information for variables actually declared in
> > other compilation units. I don't see that as an acceptable solution.
> > This problem is far too isolated for such a radical approach.
> >
> > Aside from that, I don't see any solution that can describe this case. To
> > clarify, I'm talking about globals which have "dead zones" where the main
> > in-memory copies are inaccurate because local copies have been created and
> > modified and the changes haven't propagated back to the main in-memory
> > copies.
>
> The problem is not with variables which are declared in other
> compilation units, the problem is with variables which are actually
> used in the current compilation unit and which require more description.
>
> For those cases, generate a Dwarf location entry which describes the
> symbol. When you reference a symbol, look for a description in the current
> context before looking elsewhere.
>
> Unless I'm misunderstanding you, there are only two places where you
> may be refering to a symbol in the debugger. Either you are in a
> context where a copy of the symbol's value exists, or you are not.
> In the former case, you should have an easily found description for
> the symbol. In the later case, none of the (possibly many) location
> descriptions in any of the (possibly many) compilation units have any
> relevance or value. Use .pubnames to find the main in-memory copy.
>
Well, the global in-memory copy described in another compilation unit may
still have relevance. Consider the case where there's a local copy of the
variable that *isn't* modified. In that case, there are two equally
viable locations for the global variable. Then say the user of the
debugger instructs it to modify the global variable while in that code.
You can't modify just the local copy and rely on the local code to update
the global copy with the local one, because the local code knows that it
never modifies the local one. (Obviously, it wasn't expecting the
debugger to get involved.) So, the debugger needs to update *both*
locations for the modification to affect the execution properly.
It seems that a location list would solve this. I worried about this for
a bit, because I went back to the inability to describe locations outside
the current compilation unit for the global. But then I realized that it
wasn't necessary: as long as the location list covers all the PC ranges
for which this local copy is in scope, that's all it needs to do.
But there's a more serious problem with this solution. In Ada, there
really aren't any objects at the outermost scope; they're all nested
within some construct (a package, subroutine, or other entity, which
collectively are called units). In order for a debugger to be able to
cope with fully-specified object names
(e.g. outermostpackage.nestedpackage.object), I have to describe enough of
the foreign hierarchy to get the object nested in the right place. But
having done that, now those units in the foreign hierarchy have been
described in the current compilation unit, and they will be found by the
visibility code instead of their original foreign counterparts all of the
time, not just when looking up the global with the local copy. I suppose
even that could be worked around by making the debugger descend through a
local hierarchy if there is one, and then, if it didn't find what it was
looking for, through the original foreign hierarchy.
Aside: .pubnames is practically useless for Ada. You have to do
hierarchical searches to follow proper Ada semantic visibility
rules, so .pubnames really can only describe outermost (library)
units, no more.
There's another issue, too. Even ignoring entities nested within these
replicated hierarchical units, the hierarchical units themselves will have
attributes which will need to be replicated. For the case of uplevel
referenced variables with local copies, that means that foreign
subroutines have to be replicated in the local compilation unit, along
with all their attributes. In order for that to work, additional ELF
symbols original foreign subroutine have to be made extern, so that they
can be referenced potentially by from any other compilation units that
need to replicate the subroutine and its attributes in order for it to
contain an uplevel referenced variable. And while I'm replicating the
description of a subroutine, is it necessary to replicate its formal
parameters, too? Assuming the same approach I described in the last
section where there's a 2-pass symbol table lookup for variables, then I
don't need to replicate the formals just to be able to look them up from
within the subroutine. But what about the ability to call the subroutine?
I need to know the formals for that, too. (Well, I do in Ada, at least;
maybe other languages are looser.) So, either they have to be replicated
along with the subroutine, or the debugger's visibility code has to be
clever enough to realize that it's looking up a subroutine and to ignore
one that it found in the 1st pass of a symbol table lookup and use the one
in the more-global symbol table lookup if the former has no formal
parameters, and the latter does. Of course, it still has to pay attention
to the subroutine found in the 1st pass when trying to lookup something
nested within it.
So, yes, this solution seems to work without requiring any new DWARF,
although I'm still not 100% confident that there aren't any other issues
with it. (The rate it which I'm thinking up issues about this is still
too high for me to have that kind of confidence.)
But this solution comes at a cost:
1) It will cause the DWARF to be considerably larger, requiring
hierarchical replication.
2) It definitely will entail more work in the compiler to save all
information about each hierarchy that might need to be replicated in
other compilation units.
3) I suspect that it will even entail a lot of work to support it in a
debugger.
Is a nice simple extension so bad, compared to this?
--
Todd Allen
Concurrent Computer Corporation