https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93888

            Bug ID: 93888
           Summary: Incorrect DW_AT_location generated for
                    copy-constructed function argument
           Product: gcc
           Version: 10.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: debug
          Assignee: unassigned at gcc dot gnu.org
          Reporter: mgulick at mathworks dot com
  Target Milestone: ---

Created attachment 47889
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=47889&action=edit
reproducer code, gdb test script, makefile and README

Hi,

I have observed that gcc produces an incorrect DW_AT_location list for a
function argument when both of the following are true:

a) The argument is passed by value with the help of a copy constructor
b) The function is inlined

When this occurs, the DW_AT_location list actually ends up pointing to the
address of the data, not the data itself.  Thus, it is either missing a
DW_OP_deref, or contains a gratuitous DW_OP_stack_value.

I have turned off all other optimizations and the issue is still reproducible.

I have observed this issue on all versions of GCC I have available to test,
including the current git master, 8.3, 6.3, 4.9, 4.7, and 4.4.

Here is a sample program:
class K
{
public:
  K() {}
  // Commenting out this copy-constructor makes the test pass
  K ( K const& rhs ) {
    m_storage[0] = 'C';  // 0x43
  }
  // Initialize this array to some known values (0x42)
  char m_storage[ 8 ] = {'B','B','B','B','B','B','B','B'};
};

// Not inlining also fixes the issue
__attribute__((always_inline))
bool func1(const K func1_k) {
  return func1_k.m_storage[0] == 'C';
}

int main() {
  K my_k;
  return func1(my_k);
}

I am compiling this with 'g++ -g -O0 -fvar-tracking ...'.

In gdb, if I break inside 'func1' and print the value of 'func1_k', the wrong
value is printed.  If I instead print '*(K*)func1_k', I get the expected value.

If I ask gdb what the address of func1_k is, I get:

(gdb) info address func1_k
Symbol "func1_k" is multi-location:
  Range 0x40113f-0x401148: a complex DWARF expression:
     0: DW_OP_breg6 -8 [$rbp]
     2: DW_OP_stack_value

I verified with dwarfdump that this matches the value in the .o file, so it
does not appear to be a gdb bug.  I am using the latest gdb 9.1 release.

I have attached a tarball containing the reproduction code, along with a gdb
test script, and a README with additional details.

While this issue itself is relatively minor, there isn't an easy workaround if
you need to debug optimized code.  Also, in the production code where this
issue was found, the value being passed happens to be a boost::optional which
we have a gdb pretty-printer setup for, and this causes the unfortunate
side-effect that running a 'backtrace' command in gdb any time this function is
in the stack (which is pretty much all the time) causes the boost
pretty-printer to try to dereference an invalid value, and gdb segfaults.

I spent some time trying to debug gcc itself, but I got lost very quickly and
was unable to localize where the issue is.  Hopefully this reproduction case is
small-enough to help you determine the source of the error.

Thank you!

-Mike

Reply via email to