This is the mail archive of the mailing list for the GDB project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[DWARF/RFC] end-address overflow in location description entry

I was wondering if I could have your opinion on the following situation.

We have a global, non-static, variable defined inside a C file.
This C file was compiled with a non-GCC compiler.  The symbol
table places that variable at an address. The debugging info
contains a DW_TAG_variable DIE where the location attribute
points to a location list.  Why the compiler elected to use
a location list rather than a provide a plain address is unknown,
since as far as we can tell, there is no reason to believe that
the variable would have a non-global lifetime.

The fun starts when decoding the location list: It has one single
entry, where the address is correct (identical to the one in the
symbol table), but where the begin/end offsets are 0x0, and 0xffffffff
(the address size is 4, and addresses are unsigned).  The offsets are
then added to the base address, which in this case is the CU low address:

    static const gdb_byte *
    find_location_expression (struct dwarf2_loclist_baton *baton,
                              size_t *locexpr_length, CORE_ADDR pc)
      /* Otherwise, a location expression entry.  */
      low += base_address;
      high += base_address;

With 32bit hosts, high overflows, and we end up doing the equivalent
of "high = base_address - 1", resulting with a null range for that entry.

In the end, what the users sees is:

    (gdb) print my_variable
    $1 = <variable optimized out>

The reason why I'm mentioning this, is because we do have an overflow,
and I'm wondering whether we'd want to do something about it. For
instance, we could try adding the following code, which sets high to
the highest address for the address size if we overflow.  This would
make things a little better for the user, I think.

      if (high < base_address)
        high = base_mask;

But on the other side, we'd still have issues accessing the variable
from units whose code is located before the unit where the variable
is defined. So it's still not great. We could special case the 0/-1
case even further by making it a universal range.  Perhaps something
like this:

     if (low == 0 && high == base_mask)
          *locexpr_length = length;
          return loc_ptr;

Would we be interested in a change of this nature?  For now, I'm ruling
this debugging information as incorrect.  But on the other hand, I cannot
find an easy way for the user to work around the issue and get the address
in an automated way.  So perhaps, in the spirit of being lenient in what
we accept, if the a 0/-1 range is obviously wrong (is it?), then we can
add that special case in GDB.  I think it would be easier to discard this
special case if there was a way to tell GDB to only consider minimal
symbols in the expression...


diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index b2aecf2..3d5606d 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -108,6 +108,9 @@ find_location_expression (struct dwarf2_loclist_baton *baton,
       low += base_address;
       high += base_address;
+      if (high < base_address)
+        high = base_mask;
       length = extract_unsigned_integer (loc_ptr, 2, byte_order);
       loc_ptr += 2;
@@ -2550,6 +2553,9 @@ loclist_describe_location (struct symbol *symbol, CORE_ADDR addr,
       low += base_address;
       high += base_address;
+      if (high < base_address)
+        high = base_mask;
       length = extract_unsigned_integer (loc_ptr, 2, byte_order);
       loc_ptr += 2;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]