Re: [RFC] Partial support for dwarf3 DW_AT_ranges

Elena Zannoni
2003-01-29T18:09:24Z

Daniel Jacobowitz writes:
> On Fri, Jan 04, 2002 at 12:00:07PM -0500, Elena Zannoni wrote:
> > Richard Henderson writes:
> > > GCC began emitting DW_AT_ranges back in September to deal with
> > > lexical scopes made discontiguous by basic block reordering.
> > >
> > > As of today, it may also create discontiguous lexical scopes
> > > due to scheduling. (Before today under the same circumstances
> > > we'd lose track of which instructions belonged to which scope
> > > and fail to emit any debug information whatsoever.)
> > >
> >
> > Richard, there was some initial effort to deal with this problem
> > in gdb's symbol tables structures back in October.
> > See the thread at:
> > http://sources.redhat.com/ml/gdb-patches/2001-10/msg00304.html
> > However, no real changes have been made to the symbol tables yet.
> >
> > > However, GDB doesn't recognize DW_AT_ranges as a valid way of
> > > marking a lexical scope, which causes it to discard the scope
> > > entirely. Which is probably the least useful thing that could
> > > be done.
> > >
> > > The following does not add proper support for discontiguous
> > > address ranges. I couldn't figure out how to do that in any
> > > way that wasn't horribly invasive. I'm willing to expend a
> > > significant amount of effort on this if someone is willing to
> > > provide some direction.
> > >
> >
> > The thread mentioned above has some initial implementation of an
> > address set for partial symbol tables which would be used in case of
> > non contiguous addr ranges. You should coordinate with Jim.
> >
> > > What this does do is find the "bounding box" of the discontiguous
> > > range and use that. Yes, that will do the wrong thing in some
> > > circumstances, but the current behaviour is wrong under all
> > > circumstances, so it may be a net improvement.
> > >
> >
> > I am OK with committing some initial support. At least now gdb can
> > read the info.
> >
> > I have a few comments on your changes. Maybe I am missing it, but is
> > the -1 value returned by dwarf2_get_pc_bounds used anywhere yet? If
> > not, I would suggest we don't bother with it right now, given that the
> > final solution will probably have to restructure that function again.
> > Also, I would not want to introduce more goto's in gdb. I think that
> > that sequence can be rewritten w/o goto's pretty easily. Also there
> > is some formatting problem (white spaces around operators, full names
> > for variables). Adding some comments on how the .debug_ranges list is
> > organized would be helpful too.
> >
> > I think JimB is the one which has the last say on this however, since
> > he has a patch in the works.
> >
>
> Ping out there, folks.
>
> This lack of support for DW_AT_ranges is responsible for at least one,
> probably two or more of the current PRs about "missing local
> variables". Affected GCC versions have been shipping for some time; at
> least 3.2 generates DW_AT_ranges, maybe earlier.

Yes, I am looking at this patch at the moment, too. The lack of this
feature is creating lots of troubles.

>
> Since nothing ever came of the grand plans to support ranges in the
> symbol table directly, can we at least move forwards on this year-old
> patch? If so, I'll update it for current GDB.
>

If you have time, I'd appreciate it. I have adapted the patch to the
current sources, but even with it, I wasn't able to make Jakub's
example work. The example is in PR 833.
I can send you the diffs I have, if it helps.

Elena

> > thanks
> > Elena
> >
> >
> > > My test case for this was
> > >
> > > static int foo(int *);
> > > static void bar(int *);
> > >
> > > int main()
> > > {
> > > {
> > > int x = 0, r;
> > > r = foo(&x);
> > > if (__builtin_expect (r, 1))
> > > return 0;
> > > bar (&x);
> > > return 1;
> > > }
> > > }
> > >
> > > static int foo(int *p)
> > > {
> > > *p = 1;
> > > return 0;
> > > }
> > >
> > > static void bar(int *p)
> > > {
> > > *p = 2;
> > > }
> > >
> > > For any GCC target that can emit epilogues as rtl, we will
> > > arrange the code here as
> > >
> > > x = 0
> > > call foo
> > > if r == 0 goto L1
> > > ret = 0
> > > L0:
> > > return ret
> > > L1:
> > > call bar
> > > ret = 1
> > > goto L0
> > >
> > > The lexical scope created by the extra set of braces doesn't
> > > cover the epilogue, so the scope's range is the block before
> > > L0, plus the block after L1.
> > >
> > >
> > > r~
> >
> > > -/* Get low and high pc attributes from a die.
> > > - Return 1 if the attributes are present and valid, otherwise, return 0. */
> > > +/* Get low and high pc attributes from a die. Return 1 if the attributes
> > > + are present and valid, otherwise, return 0. Return -1 if the range is
> > > + discontinuous, i.e. derived from DW_AT_ranges information. */
> > >
> > > static int
> > > -dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, CORE_ADDR *highpc,
> > > - struct objfile *objfile)
> > > +dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
> > > + CORE_ADDR *highpc, struct objfile *objfile,
> > > + const struct comp_unit_head *cu_header)
> > > {
> > > + bfd *obfd = objfile->obfd;
> > > struct attribute *attr;
> > > CORE_ADDR low;
> > > CORE_ADDR high;
> > > + int ret;
> > >
> > > - attr = dwarf_attr (die, DW_AT_low_pc);
> > > - if (attr)
> > > - low = DW_ADDR (attr);
> > > - else
> > > - return 0;
> > > attr = dwarf_attr (die, DW_AT_high_pc);
> > > if (attr)
> > > - high = DW_ADDR (attr);
> > > - else
> > > - return 0;
> > > + {
> > > + high = DW_ADDR (attr);
> > > + attr = dwarf_attr (die, DW_AT_low_pc);
> > > + if (attr)
> > > + low = DW_ADDR (attr);
> > > + else
> > > + return 0;
> > > + ret = 1;
> > > + }
> > > + else if ((attr = dwarf_attr (die, DW_AT_ranges)) != NULL)
> > > + {
> > > + unsigned int addr_size = cu_header->addr_size;
> > > + CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
> > > + unsigned int offset = DW_UNSND (attr);
> > > + CORE_ADDR base;
> > > + int dummy;
> > > + unsigned int i;
> > > + char *buffer;
> > >
> > > + /* The applicable base address is determined by (1) the closest
> > > + preceding base address selection entry in the range list or
> > > + (2) the DW_AT_low_pc of the compilation unit. */
> > > + /* ??? We definitely need some sort of indexed data structure here.
> > > + At minimum we should recognize the common case of there being
> > > + no base address selection entries. */
> > > +
> > > + buffer = dwarf_ranges_buffer + offset;
> > > + for (i = offset; i > 2 * addr_size; )
> > > + {
> > > + CORE_ADDR marker;
> > > +
> > > + i -= 2 * addr_size;
> > > + buffer -= 2 * addr_size;
> > > +
> > > + marker = read_address (obfd, buffer, cu_header, &dummy);
> > > + if ((marker & mask) == mask)
> > > + {
> > > + base = read_address (obfd, buffer+addr_size, cu_header, &dummy);
> > > + goto found_base;
> > > + }
> > > + }
> > > +
> > > + /* ??? Was in dwarf3 draft4, and has since been removed.
> > > + GCC still uses it though. */
> > > + attr = dwarf_attr (cu_header->die, DW_AT_entry_pc);
> > > + if (attr)
> > > + {
> > > + base = DW_ADDR (attr);
> > > + goto found_base;
> > > + }
> > > +
> > > + attr = dwarf_attr (cu_header->die, DW_AT_low_pc);
> > > + if (attr)
> > > + {
> > > + base = DW_ADDR (attr);
> > > + goto found_base;
> > > + }
> > > +
> > > + /* We have no valid base address for the ranges data. */
> > > + return 0;
> > > +
> > > + found_base:
> > > + buffer = dwarf_ranges_buffer + offset;
> > > + low = read_address (obfd, buffer, cu_header, &dummy);
> > > + buffer += addr_size;
> > > + high = read_address (obfd, buffer, cu_header, &dummy);
> > > + buffer += addr_size;
> > > + if (low == 0 && high == 0)
> > > + /* If the first entry is an end-of-list marker, the range
> > > + describes an empty scope, i.e. no instructions. */
> > > + return 0;
> > > +
> > > + while (1)
> > > + {
> > > + CORE_ADDR b, e;
> > > + offset += 2 * addr_size;
> > > +
> > > + b = read_address (obfd, buffer, cu_header, &dummy);
> > > + buffer += addr_size;
> > > + e = read_address (obfd, buffer, cu_header, &dummy);
> > > + buffer += addr_size;
> > > + if (b == 0 && e == 0)
> > > + break;
> > > + if (b < low)
> > > + low = b;
> > > + if (e > high)
> > > + high = e;
> > > + }
> > > +
> > > + low += base;
> > > + high += base;
> > > + ret = -1;
> > > + }
> > > +
> > > if (high < low)
> > > return 0;
> > >
> > > @@ -1800,12 +1908,12 @@ dwarf2_get_pc_bounds (struct die_info *d
> > > labels are not in the output, so the relocs get a value of 0.
> > > If this is a discarded function, mark the pc bounds as invalid,
> > > so that GDB will ignore it. */
> > > - if (low == 0 && (bfd_get_file_flags (objfile->obfd) & HAS_RELOC) == 0)
> > > + if (low == 0 && (bfd_get_file_flags (obfd) & HAS_RELOC) == 0)
> > > return 0;
> > >
> > > *lowpc = low;
> > > *highpc = high;
> > > - return 1;
> > > + return ret;
> > > }
> > >
> > > /* Add an aggregate field to the field list. */
> >
>
> --
> Daniel Jacobowitz
> MontaVista Software Debian GNU/Linux Developer