[PATCH 0/2] Problems with gdb.mi/mi-vla-fortran.exp

Andrew Burgess
2015-12-11T21:38:48Z

I recently ran into an issue while running the gdb regression tests,
the symptom was that one of the tests was causing gdb to consume a
large amount of memory, 3G+.

I tracked this down to the test gdb.mi/mi-vla-fortran.exp. The
specific causes of the issue appears to be a bug in gfortran.

In the test we have gdb stop at vla.f90:35, which looks like this:

pvla2 => vla2 ! pvla2-not-associated

Before this point, the pvla2 pointer variable is not associated, and
so, something like:

l = associated(pvla2)

Would return false. In order to determine if pvla2 is associated gdb
makes use of the DWARF DW_AT_associated property which is an attribute
of the DWARF type corresponding to pvla2.

The DW_AT_associated property for the type of pvla2 is this (newlines
added by me for clarity):

DW_AT_associated : 4 byte block: 97 6 30 2e \
(DW_OP_push_object_address; \
DW_OP_deref; DW_OP_lit0; \
DW_OP_ne)

So, take the address of the object (in this case the address is on the
stack), and use that to load an address sized block from memory, and
if that loaded block is not zero, then the the variable (pvla2) is
associated.

The problem is that gfortran does not initialise the block of memory
that the object address points to until the first time that pvla2 is
accessed. Before that time the contents of the memory are undefined,
and if gdb accesses them we will see undefined behaviour.

I've confirmed that above behaviour by using the '-fdump-tree-all'
option to gfortran, then examining the pseudo-C code that is dumped.

From a compiler / code correctness point of view this behaviour is
perfectly understandable, and for performance, this is probably a win,
the problem (as I see it) is that a promise has been made in the
DWARF, which is not being honoured in the code. I think gfortran
either needs more complex DWARF, or to initialise the memory block for
associatable variables earlier on.

Given the above mistake, what follows is just undefined behaviour
kicking in; gdb reads the uninitialised memory, which happens to be
non-zero, so it believes pvla2 is associated, it then tries to figure
out what it's associated with, and reads yet more uninitialised memory.

In this end it figures that pvla2 is pointing at a huge 3G+ array,
which in the gdb.mi/mi-vla-fortran.exp test we gdb to print. This
causes gdb to allocate the 3G+ of memory to hold the contents of the
value.

My question is what to do next from the gdb side of things?

We could leave the test unchanged, arguing that gdb is asking sensible
questions, and it's gfortran that's getting things wrong.

Or we could remove, or comment out, the offending test.

Leaving the test in place unchanged would be a bit of a shame, I know
that 3G of memory isn't much on a lot of machines, but it's still
making my experience running the testsuite pretty painful; I can't be
the only one.

I think that this issue has highlighted a bigger issue that effects
gdb, when dealing with languages that support dynamic types, like
fortran. An incorrect program can result in gdb having invalid type
information, it would be nice if this invalid information did not
cause gdb to do something so obviously wrong that it brings the
maching running gdb down.

The following patches are my attempt to address this issue. The first
adds a mechansim to stop gdb allocating overly large arrays for value
contents, the second enables this mechanism withn the test suite,
while the third makes additional changes to the mi-vla-fortran.exp
test to prevent additional errors that are a consequence of the above
issue.

Thoughts and comments welcome.

Thanks,
Andrew

---

Andrew Burgess (3):
gdb: New set/show max-value-size command.
gdb: Set max-value-size before running tests.
gdb: Guard against undefined behaviour in mi-vla-fortran.exp

gdb/ChangeLog | 11 +++++
gdb/NEWS | 6 +++
gdb/doc/ChangeLog | 4 ++
gdb/doc/gdb.texinfo | 35 +++++++++++++++
gdb/testsuite/ChangeLog | 17 ++++++++
gdb/testsuite/gdb.base/max-value-size.c | 26 +++++++++++
gdb/testsuite/gdb.base/max-value-size.exp | 66 ++++++++++++++++++++++++++++
gdb/testsuite/gdb.mi/mi-vla-fortran.exp | 48 ++++++++++++++-------
gdb/testsuite/lib/gdb.exp | 10 +++++
gdb/testsuite/lib/mi-support.exp | 10 +++++
gdb/value.c | 71 +++++++++++++++++++++++++++++--
11 files changed, 284 insertions(+), 20 deletions(-)
create mode 100644 gdb/testsuite/gdb.base/max-value-size.c
create mode 100644 gdb/testsuite/gdb.base/max-value-size.exp

--
2.5.1