Bug 40040 - gfortran invalid DW_AT_location for overridable variables
Summary: gfortran invalid DW_AT_location for overridable variables
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: debug (show other bugs)
Version: 4.4.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks: 24546
  Show dependency treegraph
 
Reported: 2009-05-06 09:22 UTC by Jan Kratochvil
Modified: 2017-07-27 17:53 UTC (History)
6 users (show)

See Also:
Host:
Target: x86_64-unknown-linux-gnu
Build:
Known to work:
Known to fail:
Last reconfirmed: 2013-06-25 00:00:00


Attachments
Preliminary GDB patch. (3.83 KB, patch)
2010-04-20 09:14 UTC, Jan Kratochvil
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Jan Kratochvil 2009-05-06 09:22:51 UTC
Variables in Fortran modules compiled in -fPIC shared libraries will get unique address by a copy relocation to the main executable.  Still .debug_info of the library contains absolute DW_AT_location of the variable - without any indirection through the GOT vector.

Debugger will then print the variable location not in active use.  Current FSF GDB cannot resolve these variables but it was found by a new patch for modules:
http://sourceware.org/gdb/wiki/ArcherBranchManagement
archer-jankratochvil-fortran-module

Assuming no DW_AT_location should exist for such variables.  DW_AT_declaration should be present there as such variables are NOT optimized-out.  Or DW_AT_location using DW_FORM_block* indirecting GOT could be present?

For C the problem does not happen with GCC as it will put there _two_ DIEs and the first one is just a declaration.  Current FSF GDB ignores any non-first DIEs for a named object.  Still the second invalid DIE is redundant + invalid even in the C case.

GNU Fortran (GCC) 4.4.0 20090427 (Red Hat 4.4.0-3)
GNU Fortran (GCC) 4.5.0 20090501 (experimental)

------------------------------------------------------------------------------

cat >lib.f90 <<EOH
module lib
        integer :: var = 1
end module lib
EOH
cat >main.f90 <<EOH
        use lib
        if (var .ne. 1) call abort
end
EOH
F="gfortran -Wall -g"; $F -o lib.so -shared -fPIC lib.f90; $F -o main main.f90 ./lib.so

$ nm -D lib.so | grep var
0000000000200798 D __lib_MOD_var
$ nm -D main | grep var
0000000000600c38 B __lib_MOD_var

$ readelf -a lib.so | approx-grep var
Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [21] .data             PROGBITS         0000000000200798  00000798
       0000000000000004  0000000000000000  WA       0     0     4
Symbol table '.dynsym' contains 11 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     9: 0000000000200798     4 OBJECT  GLOBAL DEFAULT   21 __lib_MOD_var
Symbol table '.symtab' contains 57 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
    50: 0000000000200798     4 OBJECT  GLOBAL DEFAULT   21 __lib_MOD_var

$ readelf -a main | approx-grep var
Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [25] .bss              NOBITS           0000000000600c38  00000c34
       0000000000000018  0000000000000000  WA       0     0     8
Relocation section '.rela.dyn' at offset 0x560 contains 2 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000600c38  000c00000005 R_X86_64_COPY     0000000000600c38 __lib_MOD_var + 0
Symbol table '.dynsym' contains 14 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
    12: 0000000000600c38     4 OBJECT  GLOBAL DEFAULT   25 __lib_MOD_var
Symbol table '.symtab' contains 77 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
    59: 0000000000600c38     4 OBJECT  GLOBAL DEFAULT   25 __lib_MOD_var

$ readelf -wi lib.so | approx-grep var
 <1><2d>: Abbrev Number: 2 (DW_TAG_module)
    <2e>   DW_AT_name        : lib
 <2><38>: Abbrev Number: 3 (DW_TAG_variable)
    <39>   DW_AT_name        : var
    <3f>   DW_AT_type        : <0x4f>
    <43>   DW_AT_external    : 1
    <44>   DW_AT_location    : 9 byte block: 3 98 7 20 0 0 0 0 0        (DW_OP_addr: 200798)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid DW_AT_location

$ readelf -wi main | approx-grep var
 <1><2d>: Abbrev Number: 2 (DW_TAG_subprogram)
    <2f>   DW_AT_name        : (indirect string, offset: 0x9): MAIN__
 <2><50>: Abbrev Number: 4 (DW_TAG_imported_module)
    <53>   DW_AT_import      : <0x58>   [Abbrev Number: 5 (DW_TAG_module)]
 <1><58>: Abbrev Number: 5 (DW_TAG_module)
    <59>   DW_AT_name        : lib
    <5d>   DW_AT_declaration : 1


cat >clib.c <<EOH
int var = 1;

int
func (void)
{
  return var;
}
EOH
cat >cmain.c <<EOH
extern int var;

extern int func (void);

int
main (void)
{
  var = 2;
  return var == func () ? 0 : 1;
}
EOH
C="gcc -Wall -g"; $C -o clib.so -shared -fPIC clib.c; $C -o cmain cmain.c ./clib.so

$ nm -D clib.so | grep var
0000000000200800 D var
$ nm -D cmain | grep var
00000000006009c0 B var

$ readelf -wi clib.so | approx-grep var
 <1><55>: Abbrev Number: 4 (DW_TAG_variable)
    <56>   DW_AT_name        : var
    <5c>   DW_AT_type        : <0x4e>
    <60>   DW_AT_external    : 1
    <61>   DW_AT_declaration : 1
 <1><62>: Abbrev Number: 5 (DW_TAG_variable)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ redundant+invalid DIE
    <63>   DW_AT_name        : var
    <69>   DW_AT_type        : <0x4e>
    <6d>   DW_AT_external    : 1
    <6e>   DW_AT_location    : 9 byte block: 3 0 8 20 0 0 0 0 0         (DW_OP_addr: 200800)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid DW_AT_location
Comment 1 Jakub Jelinek 2009-05-06 10:24:16 UTC
I'd say this is actually a ld bug, not GCC.
GCC emits:
        .uleb128 0x3    # (DIE (0x38) DW_TAG_variable)
        .ascii "var\0"  # DW_AT_name
        .byte   0x1     # DW_AT_decl_file (pr40040lib.f90)
        .byte   0x2     # DW_AT_decl_line
        .long   0x4f    # DW_AT_type
        .byte   0x1     # DW_AT_external
        .byte   0x9     # DW_AT_location
        .byte   0x3     # DW_OP_addr
        .quad   __pr40040lib_MOD_var
and the relocation is preserved even by gas, .rela.debug_info has:
     6: 0000000000200738     4 OBJECT  GLOBAL DEFAULT   19 __pr40040lib_MOD_var
But then ld resolves all relocations in .rela.debug_info locally and throws
away that section, while perhaps best would be to drop most of the relocations
from that section and keep only some, against overridable objects.  Still the question is if .rela.debug_info won't be too large for practical uses.

If DW_AT_location isn't provided, how would gdb find that address out?  Using DW_AT_MIPS_linkage_name (currently not emitted) and symbol lookup?
Comment 2 Jan Kratochvil 2009-05-06 10:54:23 UTC
(In reply to comment #1)
> If DW_AT_location isn't provided, how would gdb find that address out?  Using
> DW_AT_MIPS_linkage_name (currently not emitted) and symbol lookup?

The GDB patch now assembles the symbol name from its parent DW_TAG_module as `__modulename_MOD_varname'.  As GDB also has to know the C++ mangling rules I believe this Fortran mangling is can be also used from GDB.

If GDB should never guess the fully qualified names I will have to file at least one more GCC fortran debug/ PR for DW_TAG_imported_declaration which already uses only DW_TAG_variable with DW_AT_declaration and no DW_AT_location.
Comment 3 Tobias Burnus 2009-05-06 16:40:59 UTC
(In reply to comment #2)
> The GDB patch now assembles the symbol name from its parent DW_TAG_module as
> `__modulename_MOD_varname'.  As GDB also has to know the C++ mangling rules I
> believe this Fortran mangling is can be also used from GDB.

Note: The Fortran mangling is highly compiler dependent. Intel's ifort uses "modulename_mp_varname_", sunf95 uses "modulename.varname_", and g95 and NAG f95 use "modulename_MP_varname" (however,  the latter two don't create DW_TAG_module - g95 is based on gcc 4.0.x and NAG f95 uses the system's C compiler).
Comment 4 Roland McGrath 2009-05-06 19:45:08 UTC
Hmm.  I am concerned by the idea of relocs for DWARF sections in final-linked objects.  That is a hassle that consumers have not had to handle before.  (AFAIK only consumers that handle ET_REL pseudo-final objects such as Linux kernel .ko modules cope with reloc sections at all.)

I think what's ideal in the abstract is that the location expression indicates how the variable is really accessed, i.e. loading the address from the GOT or whatever it really does.

That might not always be possible in the defining declaration.  e.g., when the definition is in a CU where there are no accesses, perhaps it can't tell whether other CUs will be using direct addressing (e.g. @GOTOFF) or GOT-indirect.

I read DWARF 3 section 4.1 item 4 to suggest that there should be a defining DW_TAG_variable whose DW_AT_location can be the "base" one, i.e. direct address in the definer, plus non-defining DW_TAG_variable (with DW_AT_declaration) DIEs whose DW_AT_location expressions indicate how the variable is accessed in each scope using it.  So, in the "main program" CU the DW_TAG_variable should have DW_AT_declaration, DW_AT_external, and a DW_AT_location describing the main program's copy (or its GOT lookup if PIC).  In the non-defining accessing CUs in a DSO, there should be a similar DIE whose DW_AT_location describes that DSO's GOT lookup, etc.  If the defining CU also contains accesses, then the defining DW_TAG_variable's DW_AT_location would describe the GOT access if that's what that CU uses, and then no DIE anywhere would have the direct address location expression for the DSO initializer/copy.

I don't know how ready GDB et al are to cope with this, but it seems like the "correct" route to me.  They'd have to find the right DIE for the scope of the access, so it has the appropriate location expression.  For "blind" global lookups, it would have to be sure to use the "dominating" DIE, i.e. choose one somewhere in the main program before the defining definition in the DSO.
Comment 5 Jan Kratochvil 2009-05-06 20:12:57 UTC
(In reply to comment #4)
> I don't know how ready GDB et al are to cope with this,

(For GDB the local definitions containing an address expression are even less problematic than the current declarations requiring mangled symbols resolving.)
Comment 6 Tobias Burnus 2009-08-21 18:40:33 UTC
What is actually the status of this PR? I read through it twice and I still do not know whether this is a GCC bug or a GNU ld bug - and, if the former, how it is supposed to be fixed.
Comment 7 Jan Kratochvil 2010-04-20 09:14:38 UTC
Created attachment 20436 [details]
Preliminary GDB patch.

Tobias, could you add DW_AT_MIPS_linkage name?

You say in Comment 3 the debugger cannot guess the linkage name from DW_AT_namespace hierarchy as it is not standardized across Fortran compilers.

If DW_AT_external is true the GDB patch ignores DW_AT_location and relies on the ELF symbols which would work.  It should IMHO follow Roland's
Re: Cross-CU C++ DIE references vs. mangling
http://sourceware.org/ml/archer/2010-q1/msg00092.html
Comment 8 Jakub Jelinek 2010-04-20 09:21:05 UTC
Please treat DW_AT_linkage_name the same as DW_AT_MIPS_linkage_name, for -gdwarf-4 the patch I've posted yesterday emits the former rather than latter.

Currently the addition of DW_AT_{,MIPS_}linkage_name is guarded with
&& !is_fortran ()
that would probably need to go away.
BTW, should DW_AT_{,MIPS_}linkage_name be also present on DW_TAG_common_block?
If yes, we need to file a request similar to
http://dwarfstd.org/ShowIssue.php?issue=100419.4&type=open
for DW_AT_linkage_name to be allowed on DW_TAG_common_block.
Comment 9 Jan Kratochvil 2010-04-20 12:24:06 UTC
(In reply to comment #8)
> BTW, should DW_AT_{,MIPS_}linkage_name be also present on DW_TAG_common_block?
[...]
> for DW_AT_linkage_name to be allowed on DW_TAG_common_block.

For DW_TAG_common_block:
+      /* SYMBOL_VALUE_ADDRESS never gets used as all its fields are static.  */
There is only important the user-visible DW_AT_name of DW_TAG_common_block.

Then there are child DIEs DW_TAG_variable.  Good point there should be DW_AT_*linkage_name present the same way as normal variables should have it.

http://cvs.fedoraproject.org/viewvc/rpms/gdb/F-13/gdb-fortran-common.patch?content-type=text%2Fplain&view=co

 <2><4a>: Abbrev Number: 3 (DW_TAG_common_block)
    <4b>   DW_AT_name        : (indirect string, offset: 0xd3): fo_o
    <51>   DW_AT_location    : 9 byte block: 3 50 c 60 0 0 0 0 0        (DW_OP_addr: 600c50)
 <3><5f>: Abbrev Number: 4 (DW_TAG_variable)
    <60>   DW_AT_name        : ix
    <65>   DW_AT_type        : <0x114>
    <69>   DW_AT_external    : 1
    <6a>   DW_AT_location    : 9 byte block: 3 50 c 60 0 0 0 0 0        (DW_OP_addr: 600c50)
Comment 10 Jakub Jelinek 2010-04-21 10:31:26 UTC
BTW, gcc stopped emitting with
http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=129882
- PR10220 commit.
Unfortunately that change isn't even mentioned in the ChangeLog entry nor I could find any discussions about it on the mailing list from that time.
Comment 11 Francois-Xavier Coudert 2010-04-21 10:38:53 UTC
(In reply to comment #10)
> Unfortunately that change isn't even mentioned in the ChangeLog entry nor I
> could find any discussions about it on the mailing list from that time.

In the bugzilla PR you reference, there are links to the gcc-patches thread:
http://gcc.gnu.org/ml/gcc-patches/2007-11/msg00120.html
which itself refers to a thread on the gdb list:
http://www.sourceware.org/ml/gdb/2007-10/msg00205.html


Now, if you're refering to this hunk of the change:

--- trunk/gcc/dwarf2out.c	2007/11/04 04:34:47	129881
+++ trunk/gcc/dwarf2out.c	2007/11/04 14:43:45	129882
@@ -11356,7 +11356,8 @@
 	  && TREE_PUBLIC (decl)
 	  && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl)
 	  && !DECL_ABSTRACT (decl)
-	  && !(TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl)))
+	  && !(TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl))
+	  && !is_fortran ())
 	add_AT_string (die, DW_AT_MIPS_linkage_name,
 		       IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
     }

well, it looks like it wasn't approved, so I wouldn't be surprised if it's just a something I had testing in my tree that I inadvertently committed at the time. Sorry about that.
Comment 12 Jakub Jelinek 2010-04-21 10:43:13 UTC
Yeah, that's exactly the hunk I'm referring to.  The gdb patch Jan provided relies on DW_AT_MIPS_linkage_name (or DW_AT_linkage_name hopefully for DWARF4) to be provided.  While for most normal Fortran identifiers when modules aren't involved most implementations agree on appending _ at the end, for objects/functions in modules the mangling differs between implementations and
certainly isn't something debug info consumers should hardcode.
Comment 13 Francois-Xavier Coudert 2010-04-21 10:46:11 UTC
I have googled the gcc.gnu.org domain for my name and DW_AT_MIPS_linkage_name, and came up with nothing relevant. So, I never proposed or sought to get this part approved, which confirms it's probably just human error. I am no longer a Fortran maintainer, but I'm sure the reversion will be easily approved.
Comment 14 Jakub Jelinek 2010-04-21 16:49:03 UTC
Subject: Bug 40040

Author: jakub
Date: Wed Apr 21 16:48:41 2010
New Revision: 158612

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=158612
Log:
	PR debug/40040
	* dwarf2out.c (add_name_and_src_coords_attributes): Add
	DW_AT_{,MIPS_}linkage_name even for Fortran decls.

Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/dwarf2out.c

Comment 15 Dominique d'Humieres 2013-06-25 09:15:38 UTC
Is this fixed by revision 158612? If yes, please close this PR as FIXED.
Comment 16 Eric Gallager 2017-07-27 17:53:58 UTC
(In reply to Dominique d'Humieres from comment #15)
> Is this fixed by revision 158612? If yes, please close this PR as FIXED.

No reply, guessing it was.