On a big application linking with gtk, using the compilation options
-ffunction-sections -fdata-sections and the linker option
-Wl,--gc-sections, --read-var-info=yes gives the following:

    valgrind: m_debuginfo/d3basics.c:973 (vgModuleLocal_evaluate_GX): Assertion 'aMax == ~(Addr)0' failed.

    host stacktrace:
    ==18521==    at 0x38057C54: show_sched_status_wrk (m_libcassert.c:308)
    ==18521==    by 0x38057F50: report_and_quit (m_libcassert.c:367)
    ==18521==    by 0x38058151: vgPlain_assert_fail (m_libcassert.c:432)
    ==18521==    by 0x3813F084: vgModuleLocal_evaluate_GX (d3basics.c:973)
    ==18521==    by 0x38098300: data_address_is_in_var (debuginfo.c:2769)
    ==18521==    by 0x38099E26: vgPlain_get_data_description (debuginfo.c:3298)
    ...

The problem is that -Wl,--gc-sections eliminates the unused functions
but keeps some debug info for the functions or their compilation units.
The dwarf entry has low and high pc, but both are equal to 0.
The dwarf reader of Valgrind is confused by this, as the varstack becomes
empty, while it should not. This then causes local (eliminated) variables
to be put in the global scope, leading afterwards to evaluation errors
when describing any other variables.

The fix is to also push something on the varstack when
a CU that has low and high pc given but with 0 value.
This is similar to the varstack_push done for a CU that has
no low pc, no high pc and no range.
Despite considerable effort to make a small reproducer, the problem
could only be produced with a big executable.
After the fix, everything was working properly.

The wrong behaviour for dwarf entries produce the following trace:
     <2><2ff291a>: Abbrev Number: 23 (DW_TAG_formal_parameter)
         DW_AT_name        : AET	
         DW_AT_decl_file   : 1	
         DW_AT_decl_line   : 243	
         DW_AT_type        : <2ff2811>	
         DW_AT_location    : 18288554	
      Recording this variable, with 1 PC range(s)
    ....
    <2ff291a> addVar: level 0: AET :: EdgeTableEntry*
      Loc=GX(final){[0x0,0x8]=50,[0x9,0x1d]=53,[0x1e,0x26]=51,[0x27,0x29]=53,[0x2a,0x2f]=51,[0x44,0x4a]=53,[0x4d,0x5e]=51,[0x5f,0x62]=53}
      FrB=none
      declared at: gdkpolyreg-generic.c:243
      ACQUIRE for range(s) [0x0,0xffffffff] 

The AET is a formal parameter of a function, but is wrongly added
at level 0, with a PC range covering the full space. It has a Loc GX
which uses non biased program counters (e.g. 0x0,0x8).
This dwarf entry will require a FrB (and registers when evaluating)
but no such things are available (or given) when evaluating a variable
in the global scope.

The fix is to handle compilation units with lo and hi pc == 0x0
similarly to a CU that has no lo and hi pc.
With this fix, valgrind --read-var-info=yes could properly
handle a big application with plenty of eliminated functions.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13941 a5019735-40e9-0310-863c-91ae7b9d1cf9
2 files changed