Bug 45153 - DWARF DW_AT_external flag set for undefined variables
Summary: DWARF DW_AT_external flag set for undefined variables
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.4.4
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-debug
Depends on:
Blocks:
 
Reported: 2010-07-31 18:55 UTC by P J P
Modified: 2010-08-13 13:14 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description P J P 2010-07-31 18:55:20 UTC
Hi,

As I understand, the DWARF tag DW_AT_external is meant to indicate whether a variable/function is accessible from outside an object file(compilation unit) containing a given DWARF DIE - Debugging Information Entry.

But it looks like DW_AT_external is also set for variables/functions defined in a different object file, but has a DIE because of linking.

See: http://pastebin.com/vFiBWuhh

It has a small C++ program - greeting.cpp, with it's output and some DWARF information.

As can be seen, the external flag is set for the standard library functions such as - swscanf, ungetwd, or vfwprintf - which are not defined or used in greeting.cpp, but are part of the object file because of linking.

This makes it *difficult* to locate the DIEs describing the functions that are defined and/or used in greeting.cpp.

Thank you.
Comment 1 P J P 2010-08-02 18:38:36 UTC
The following patch to gcc-4.4.4 seems to fix the issue for DW_AT_subprogram DIEs.


$ diff -Naurp gcc-4.4.4/gcc/dwarf2out.c gcc-4.4.4.1/gcc/dwarf2out.c 


--- gcc-4.4.4/gcc/dwarf2out.c   2010-02-10 20:39:06.000000000 +0530
+++ gcc-4.4.4.1/gcc/dwarf2out.c 2010-08-02 15:16:17.495688080 +0530
@@ -13712,7 +13712,7 @@ gen_subprogram_die (tree decl, dw_die_re
     {
       subr_die = new_die (DW_TAG_subprogram, context_die, decl);
 
-      if (TREE_PUBLIC (decl))
+      if (TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl))
        add_AT_flag (subr_die, DW_AT_external, 1);
 
       add_name_and_src_coords_attributes (subr_die, decl);
@@ -14163,7 +14163,7 @@ gen_variable_die (tree decl, tree origin
        add_type_attribute (var_die, type, TREE_READONLY (decl),
                            TREE_THIS_VOLATILE (decl), context_die);
 
-      if (TREE_PUBLIC (decl))
+      if (TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl))
        add_AT_flag (var_die, DW_AT_external, 1);
 
       if (DECL_ARTIFICIAL (decl))
Comment 2 Jakub Jelinek 2010-08-11 09:27:26 UTC
I don't see why any change is needed.  If a function (or variable) isn't defined in the current translation unit, then it necessarily has to be accessible from outside of the translation unit containing it.
Comment 3 P J P 2010-08-11 12:15:34 UTC
DW_AT_external is meant to indicate whether a variable/function, that is defined in the compilation unit, is accessible/visible from the outside of it or not.

It's a subtle difference between `accessible from' and `accessed from' outside.
Comment 4 Jakub Jelinek 2010-08-11 12:46:12 UTC
I don't see the standard saying that anywhere.

"A DW_AT_external attribute, which is a flag, if the name of a variable is visible outside of its enclosing compilation unit."

"If the name of the subroutine described by an entry with the tag DW_TAG_subprogram is visible outside of its containing compilation unit, that entry has a DW_AT_external attribute, which is a flag."

Nothing says that the variable/function has to be defined in that compilation unit.
Comment 5 P J P 2010-08-12 05:30:14 UTC
Doesn't the wording - visible outside of its containing compilation unit - ring any bells?

Secondly, for variables and functions that are not defined in the compilation unit, it doesn't make sense to mark them as - visible/accessible from outside - for, that's more than obvious.

Please see: http://gcc.gnu.org/ml/gcc-help/2010-07/msg00266.html

There is another same thread on dwarf-discuss list, but the archives are not open for the web.

(I think we need a third umpire to pass a reasonable judgement.)
Comment 6 Roland McGrath 2010-08-13 00:43:51 UTC
DW_AT_external is correct for anything that has "global" linkage, whether or not is defined.  The absence of DW_AT_external, in a DIE that is not inside a DW_TAG_subprogram scope, means that it has "file" linkage, like a "static" variable in C/C++ does.  A C++ static member has global linkage, not file linkage.

DW_AT_declaration is used for any DIE that is for a non-defining declaration.  That is a separate axis of consideration than DW_AT_external, which only about the linkage.
Comment 7 P J P 2010-08-13 05:52:58 UTC
You got me confused. What do you mean - "DW_AT_external is correct for anything that has "global" linkage, whether or not is defined." - ?

How do you define "global" linkage, here?

DIEs for static variables/functions don't have DW_AT_external set, though you say they've global linkage.

Also, how does on locate the DIEs for variables/functions that are listed in the .debug_pubnames section($ eu-readelf -wpubnames <file>). The list of variables/functions that are *defined* in the same compilation unit and are *visible/accessible from outside* of it.
Comment 8 Roland McGrath 2010-08-13 08:08:48 UTC
I think you've confused static variables (file scope) with C++ static members (global scope).  At any rate, this is not the place to get an education about DWARF.  You can use the dwarf-discuss mailing list for those questions.

The DIEs you cited are correct for the code.  There is no gcc bug here.
Comment 9 Jakub Jelinek 2010-08-13 08:48:08 UTC
Thus, INVALID.
Comment 10 P J P 2010-08-13 10:37:17 UTC
I think we've stepped away from DW_AT_external.

This "global" linkage theory is not convincing for why DW_AT_external should be set for variables/functions that are defined outside of the compilation unit.
Comment 11 Jonathan Wakely 2010-08-13 10:51:09 UTC
But surely if (as you suggest) swscanf had a DIE without DW_AT_external that would imply it was private to the compilation unit, which would be wrong.

If a non-static function has a DIE, it should include DW_AT_external.


Comment 12 Paolo Carlini 2010-08-13 10:57:05 UTC
.
Comment 13 Jonathan Wakely 2010-08-13 11:05:02 UTC
(In reply to comment #7)
> Also, how does on locate the DIEs for variables/functions that are listed in
> the .debug_pubnames section($ eu-readelf -wpubnames <file>). The list of
> variables/functions that are *defined* in the same compilation unit and are
> *visible/accessible from outside* of it.

Can't you look for DIEs which have DW_AT_external and which have a later DW_AT_specification, which completes the earlier non-defining declaration.

DW_AT_specification tells you it's defined, DW_AT_external tells you it's visible.
Comment 14 P J P 2010-08-13 13:14:20 UTC
> But surely if (as you suggest) swscanf had a DIE without DW_AT_external that
> would imply it was private to the compilation unit, which would be wrong.

  Hmmn...may be.

> DW_AT_specification tells you it's defined, DW_AT_external tells you it's
> visible.

  DW_AT_specification does not seem to be present all the time. It shows up in C++ program, but does not show up in a C program.