public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Debug support for global alias variable
@ 2022-03-04 13:44 Natarajan, Kavitha
  2022-03-14 11:15 ` Natarajan, Kavitha
  2022-03-24 13:53 ` Bruno Larsen
  0 siblings, 2 replies; 28+ messages in thread
From: Natarajan, Kavitha @ 2022-03-04 13:44 UTC (permalink / raw)
  To: Natarajan, Kavitha via Gdb-patches

[-- Attachment #1: Type: text/plain, Size: 10822 bytes --]

[AMD Official Use Only]

Hi,

For the below testcase, when compiled with clang compiler, debugger is not able to print alias variable type or value.
$ cat test.c
int oldname = 1;
extern int newname attribute((alias("oldname")));
int main ()
{ return 0; }
$ clang -g -O0 test.c
$ gdb a.out
(gdb) ptype oldname
type = int
(gdb) ptype newname
type = <data variable, no debug info>
(gdb) p oldname
$1 = 1
(gdb) p newname
'newname' has unknown type; cast it to its declared type
This is because clang is not emitting dwarf information for alias variable. I have updated clang patch (originally from https://reviews.llvm.org/D103131) to emit debug info for alias variable as imported entity (DW_TAG_imported_declaration):

https://reviews.llvm.org/D120989

However, gdb cannot handle the imported declaration for alias variables. GCC emits debug info for alias variables as DW_TAG_variable which gdb can handle. The discussions in the llvm bug report bug-50052<https://bugs.llvm.org/show_bug.cgi?id=50052> and above review links talk about why it is appropriate to emit alias variable as DW_TAG_imported_declaration rather than DW_TAG_variable. Refer section "3.2.3 Imported (or Renamed) Declaration Entries" in DWARF 5 specification. It was also previously discussed in gdb forum in the below thread:

https://sourceware.org/pipermail/gdb/2021-June/049509.html

The attached gdb patch can handle DW_TAG_imported_declaration as alias variables. This change fixes the failure in testcase:
           gdb.base/symbol-alias.exp
This testcase is also updated to test nested (recursive) alias, static aliasee and deferred aliasee.

Please review the below gdb patch (also attached).

---
gdb/dwarf2/read.c                       | 113 ++++++++++++++++--------
gdb/testsuite/gdb.base/symbol-alias.exp |  23 ++++-
gdb/testsuite/gdb.base/symbol-alias2.c  |  10 +++
3 files changed, 107 insertions(+), 39 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 10550336063..0f709d9ccc1 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -1132,6 +1132,10 @@ static void add_partial_subprogram (struct partial_die_info *pdi,
                                    CORE_ADDR *lowpc, CORE_ADDR *highpc,
                                    int need_pc, struct dwarf2_cu *cu);

+static void var_decode_location (struct attribute *attr,
+                                 struct symbol *sym,
+                                 struct dwarf2_cu *cu);
+
static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);

static struct partial_die_info *load_partial_dies
@@ -1332,7 +1336,7 @@ static struct using_direct **using_directives (struct dwarf2_cu *cu);

static void read_import_statement (struct die_info *die, struct dwarf2_cu *);

-static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
+static int read_alias (struct die_info *die, struct dwarf2_cu *cu);

static struct type *read_module_type (struct die_info *die,
                                      struct dwarf2_cu *cu);
@@ -9742,9 +9746,11 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
       break;
     case DW_TAG_imported_declaration:
       cu->processing_has_namespace_info = true;
-      if (read_namespace_alias (die, cu))
+      if (((cu->per_cu->lang == language_c)
+            || (cu->per_cu->lang == language_cplus))
+                            && read_alias (die, cu))
        break;
-      /* The declaration is not a global namespace alias.  */
+      /* The declaration is not a global namespace or variable alias. */
       /* Fall through.  */
     case DW_TAG_imported_module:
       cu->processing_has_namespace_info = true;
@@ -10212,18 +10218,20 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
   return retval;
}

-/* Inspect DIE in CU for a namespace alias.  If one exists, record
-   a new symbol for it.
+#define MAX_NESTED_IMPORTED_DECLARATIONS 100
+
+/* Inspect DIE in CU for a namespace alias or a variable
+   with alias attribute. If one exists, record a new symbol
+   for it.

-   Returns 1 if a namespace alias was recorded, 0 otherwise.  */
+   Returns 1 if an alias was recorded, 0 otherwise. */

static int
-read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
+read_alias (struct die_info *die, struct dwarf2_cu *cu)
{
   struct attribute *attr;

-  /* If the die does not have a name, this is not a namespace
-     alias.  */
+  /* The die must have a name for namespace or variable alias */
   attr = dwarf2_attr (die, DW_AT_name, cu);
   if (attr != NULL)
     {
@@ -10232,42 +10240,71 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
       struct dwarf2_cu *imported_cu = cu;

       /* If the compiler has nested DW_AT_imported_declaration DIEs,
-        keep inspecting DIEs until we hit the underlying import.  */
-#define MAX_NESTED_IMPORTED_DECLARATIONS 100
+         keep inspecting DIEs until we hit the underlying import. */
       for (num = 0; num  < MAX_NESTED_IMPORTED_DECLARATIONS; ++num)
-       {
-         attr = dwarf2_attr (d, DW_AT_import, cu);
-         if (attr == NULL)
-           break;
+        {
+          attr = dwarf2_attr (d, DW_AT_import, cu);
+          if (attr == NULL)
+            return 0;

-         d = follow_die_ref (d, attr, &imported_cu);
-         if (d->tag != DW_TAG_imported_declaration)
-           break;
-       }
+          d = follow_die_ref (d, attr, &imported_cu);
+          if (d->tag != DW_TAG_imported_declaration)
+            break;
+        }

       if (num == MAX_NESTED_IMPORTED_DECLARATIONS)
-       {
-         complaint (_("DIE at %s has too many recursively imported "
-                      "declarations"), sect_offset_str (d->sect_off));
-         return 0;
-       }
+        {
+          complaint (_("DIE at %s has too many recursively imported "
+                       "declarations"), sect_offset_str (d->sect_off));
+          return 0;
+        }

       if (attr != NULL)
-       {
-         struct type *type;
-         sect_offset sect_off = attr->get_ref_die_offset ();
-
-         type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
-         if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
-           {
-             /* This declaration is a global namespace alias.  Add
-                a symbol for it whose type is the aliased namespace.  */
-             new_symbol (die, type, cu);
-             return 1;
-           }
-       }
+        {
+          struct type *type;
+          if (d->tag == DW_TAG_variable)
+            {
+             /* This declaration is a global variable alias. Add
+                a symbol for it whose type is same as aliased variable. */
+              type = die_type (d, imported_cu);
+              struct symbol *sym = new_symbol(die, type, cu);
+              attr = dwarf2_attr (d, DW_AT_location, imported_cu);
+              if (attr != nullptr)
+                {
+                  var_decode_location (attr, sym, cu);
+                  return 1;
+                }
+              else
+                {
+                  /* We do not know the address of this symbol.
+                     If it is an external symbol and we have type information
+                     for it, enter the symbol as a LOC_UNRESOLVED symbol.
+                     The address of the variable will then be determined from
+                     the minimal symbol table whenever the variable is
+                     referenced.  */
+                  attr = dwarf2_attr (d, DW_AT_external, imported_cu);
+                  if (attr != nullptr && attr->as_boolean ()
+                      && dwarf2_attr (d, DW_AT_type, imported_cu) != NULL)
+                    {
+                      sym->set_aclass_index (LOC_UNRESOLVED);
+                      return 1;
+                    }
+                }
+            }
+          else
+            {
+              sect_offset sect_off = attr->get_ref_die_offset ();
+              type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
+              if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+                {
+                  /* This declaration is a global namespace alias. Add
+                     a symbol for it whose type is the aliased namespace. */
+                  new_symbol (die, type, cu);
+                  return 1;
+                }
+            }
+        }
     }
-
   return 0;
}

diff --git a/gdb/testsuite/gdb.base/symbol-alias.exp b/gdb/testsuite/gdb.base/symbol-alias.exp
index 2b53cc31053..1259c1daf1d 100644
--- a/gdb/testsuite/gdb.base/symbol-alias.exp
+++ b/gdb/testsuite/gdb.base/symbol-alias.exp
@@ -15,6 +15,7 @@
# along with this program.  If not, see http://www.gnu.org/licenses/.

standard_testfile symbol-alias.c symbol-alias2.c
+set using_clang [test_compiler_info clang*]

if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile $srcfile2]] } {
     return -1
@@ -31,6 +32,26 @@ foreach f {"func" "func_alias"} {
}

# Variables.
-foreach v {"g_var_s" "g_var_s_alias"} {
+foreach v {"g_var_s" "g_var_s_alias" "g_var_s_alias2"} {
     gdb_test "p $v" "= {field1 = 1, field2 = 2}"
}
+
+# Static Variable.
+foreach v {"g_var" "g_var_alias"} {
+    gdb_test "p $v" " = 1"
+}
+
+# Deferred Variable.
+gdb_test "p g_def_var" " = 2"
+gdb_test_multiple "p g_def_var_alias" "p g_def_var_alias" {
+    -re  " = 2.*$gdb_prompt $" {
+        pass "print alias of deferred variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+        if { $using_clang } {
+          xfail "print alias of deferred variable"
+        } else {
+          fail "print alias of deferred variable"
+        }
+    }
+}
diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c b/gdb/testsuite/gdb.base/symbol-alias2.c
index 34f4e121e25..79b3195caf5 100644
--- a/gdb/testsuite/gdb.base/symbol-alias2.c
+++ b/gdb/testsuite/gdb.base/symbol-alias2.c
@@ -23,6 +23,8 @@ struct S

struct S g_var_s = { 1, 2 };

+static int g_var = 1;
+
#ifdef __cplusplus
/* So that the alias attribute below work without having to figure out
    this function's mangled name.  */
@@ -38,3 +40,11 @@ func (void)
struct S *func_alias (void) __attribute__ ((alias ("func")));

extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));
+
+extern struct S g_var_s_alias2 __attribute__ ((alias ("g_var_s_alias")));
+
+extern int g_var_alias __attribute__ ((alias ("g_var")));
+
+extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
+
+int g_def_var = 2;
--


[-- Attachment #2: Debug-support-for-global-variable-alias.patch --]
[-- Type: application/octet-stream, Size: 9375 bytes --]

Subject: [PATCH] Debug support for global variable alias

When clang emits the dwarf information of global variable alias
as DW_TAG_imported_declaration, gdb does not handle it. GDB reads
this tag as C++/fortran imported declaration. Added support to
handle this tag as variable alias.

This change fixes the failure in testcase:
           gdb.base/symbol-alias.exp
This testcase is also updated to test nested (recursive) alias,
static aliasee and deferred aliasee.

---
 gdb/dwarf2/read.c                       | 113 ++++++++++++++++--------
 gdb/testsuite/gdb.base/symbol-alias.exp |  23 ++++-
 gdb/testsuite/gdb.base/symbol-alias2.c  |  10 +++
 3 files changed, 107 insertions(+), 39 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 10550336063..0f709d9ccc1 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -1132,6 +1132,10 @@ static void add_partial_subprogram (struct partial_die_info *pdi,
 				    CORE_ADDR *lowpc, CORE_ADDR *highpc,
 				    int need_pc, struct dwarf2_cu *cu);
 
+static void var_decode_location (struct attribute *attr,
+                                 struct symbol *sym,
+                                 struct dwarf2_cu *cu);
+
 static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);
 
 static struct partial_die_info *load_partial_dies
@@ -1332,7 +1336,7 @@ static struct using_direct **using_directives (struct dwarf2_cu *cu);
 
 static void read_import_statement (struct die_info *die, struct dwarf2_cu *);
 
-static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
+static int read_alias (struct die_info *die, struct dwarf2_cu *cu);
 
 static struct type *read_module_type (struct die_info *die,
 				      struct dwarf2_cu *cu);
@@ -9742,9 +9746,11 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
       break;
     case DW_TAG_imported_declaration:
       cu->processing_has_namespace_info = true;
-      if (read_namespace_alias (die, cu))
+      if (((cu->per_cu->lang == language_c)
+            || (cu->per_cu->lang == language_cplus))
+	                     && read_alias (die, cu))
 	break;
-      /* The declaration is not a global namespace alias.  */
+      /* The declaration is not a global namespace or variable alias. */
       /* Fall through.  */
     case DW_TAG_imported_module:
       cu->processing_has_namespace_info = true;
@@ -10212,18 +10218,20 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
   return retval;
 }
 
-/* Inspect DIE in CU for a namespace alias.  If one exists, record
-   a new symbol for it.
+#define MAX_NESTED_IMPORTED_DECLARATIONS 100
+
+/* Inspect DIE in CU for a namespace alias or a variable
+   with alias attribute. If one exists, record a new symbol
+   for it.
 
-   Returns 1 if a namespace alias was recorded, 0 otherwise.  */
+   Returns 1 if an alias was recorded, 0 otherwise. */
 
 static int
-read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
+read_alias (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct attribute *attr;
 
-  /* If the die does not have a name, this is not a namespace
-     alias.  */
+  /* The die must have a name for namespace or variable alias */
   attr = dwarf2_attr (die, DW_AT_name, cu);
   if (attr != NULL)
     {
@@ -10232,42 +10240,71 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
       struct dwarf2_cu *imported_cu = cu;
 
       /* If the compiler has nested DW_AT_imported_declaration DIEs,
-	 keep inspecting DIEs until we hit the underlying import.  */
-#define MAX_NESTED_IMPORTED_DECLARATIONS 100
+         keep inspecting DIEs until we hit the underlying import. */
       for (num = 0; num  < MAX_NESTED_IMPORTED_DECLARATIONS; ++num)
-	{
-	  attr = dwarf2_attr (d, DW_AT_import, cu);
-	  if (attr == NULL)
-	    break;
+        {
+          attr = dwarf2_attr (d, DW_AT_import, cu);
+          if (attr == NULL)
+            return 0;
 
-	  d = follow_die_ref (d, attr, &imported_cu);
-	  if (d->tag != DW_TAG_imported_declaration)
-	    break;
-	}
+          d = follow_die_ref (d, attr, &imported_cu);
+          if (d->tag != DW_TAG_imported_declaration)
+            break;
+        }
 
       if (num == MAX_NESTED_IMPORTED_DECLARATIONS)
-	{
-	  complaint (_("DIE at %s has too many recursively imported "
-		       "declarations"), sect_offset_str (d->sect_off));
-	  return 0;
-	}
+        {
+          complaint (_("DIE at %s has too many recursively imported "
+                       "declarations"), sect_offset_str (d->sect_off));
+          return 0;
+        }
 
       if (attr != NULL)
-	{
-	  struct type *type;
-	  sect_offset sect_off = attr->get_ref_die_offset ();
-
-	  type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
-	  if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
-	    {
-	      /* This declaration is a global namespace alias.  Add
-		 a symbol for it whose type is the aliased namespace.  */
-	      new_symbol (die, type, cu);
-	      return 1;
-	    }
-	}
+        {
+          struct type *type;
+          if (d->tag == DW_TAG_variable)
+            {
+	      /* This declaration is a global variable alias. Add
+	         a symbol for it whose type is same as aliased variable. */
+              type = die_type (d, imported_cu);
+              struct symbol *sym = new_symbol(die, type, cu);
+              attr = dwarf2_attr (d, DW_AT_location, imported_cu);
+              if (attr != nullptr)
+                {
+                  var_decode_location (attr, sym, cu);
+                  return 1;
+                }
+              else
+                {
+                  /* We do not know the address of this symbol.
+                     If it is an external symbol and we have type information
+                     for it, enter the symbol as a LOC_UNRESOLVED symbol.
+                     The address of the variable will then be determined from
+                     the minimal symbol table whenever the variable is
+                     referenced.  */
+                  attr = dwarf2_attr (d, DW_AT_external, imported_cu);
+                  if (attr != nullptr && attr->as_boolean ()
+                      && dwarf2_attr (d, DW_AT_type, imported_cu) != NULL)
+                    {
+                      sym->set_aclass_index (LOC_UNRESOLVED);
+                      return 1;
+                    }
+                }
+            }
+          else
+            {
+              sect_offset sect_off = attr->get_ref_die_offset ();
+              type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
+              if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+                {
+                  /* This declaration is a global namespace alias. Add
+                     a symbol for it whose type is the aliased namespace. */
+                  new_symbol (die, type, cu);
+                  return 1;
+                }
+            }
+        }
     }
-
   return 0;
 }
 
diff --git a/gdb/testsuite/gdb.base/symbol-alias.exp b/gdb/testsuite/gdb.base/symbol-alias.exp
index 2b53cc31053..1259c1daf1d 100644
--- a/gdb/testsuite/gdb.base/symbol-alias.exp
+++ b/gdb/testsuite/gdb.base/symbol-alias.exp
@@ -15,6 +15,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 standard_testfile symbol-alias.c symbol-alias2.c
+set using_clang [test_compiler_info clang*]
 
 if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile $srcfile2]] } {
     return -1
@@ -31,6 +32,26 @@ foreach f {"func" "func_alias"} {
 }
 
 # Variables.
-foreach v {"g_var_s" "g_var_s_alias"} {
+foreach v {"g_var_s" "g_var_s_alias" "g_var_s_alias2"} {
     gdb_test "p $v" "= {field1 = 1, field2 = 2}"
 }
+
+# Static Variable.
+foreach v {"g_var" "g_var_alias"} {
+    gdb_test "p $v" " = 1"
+}
+
+# Deferred Variable.
+gdb_test "p g_def_var" " = 2"
+gdb_test_multiple "p g_def_var_alias" "p g_def_var_alias" {
+    -re  " = 2.*$gdb_prompt $" {
+        pass "print alias of deferred variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+        if { $using_clang } {
+          xfail "print alias of deferred variable"
+        } else {
+          fail "print alias of deferred variable"
+        }
+    }
+}
diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c b/gdb/testsuite/gdb.base/symbol-alias2.c
index 34f4e121e25..79b3195caf5 100644
--- a/gdb/testsuite/gdb.base/symbol-alias2.c
+++ b/gdb/testsuite/gdb.base/symbol-alias2.c
@@ -23,6 +23,8 @@ struct S
 
 struct S g_var_s = { 1, 2 };
 
+static int g_var = 1;
+
 #ifdef __cplusplus
 /* So that the alias attribute below work without having to figure out
    this function's mangled name.  */
@@ -38,3 +40,11 @@ func (void)
 struct S *func_alias (void) __attribute__ ((alias ("func")));
 
 extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));
+
+extern struct S g_var_s_alias2 __attribute__ ((alias ("g_var_s_alias")));
+
+extern int g_var_alias __attribute__ ((alias ("g_var")));
+
+extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
+
+int g_def_var = 2;
-- 
2.25.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [PATCH] Debug support for global alias variable
  2022-03-04 13:44 [PATCH] Debug support for global alias variable Natarajan, Kavitha
@ 2022-03-14 11:15 ` Natarajan, Kavitha
  2022-03-24  6:36   ` Natarajan, Kavitha
  2022-03-24 13:53 ` Bruno Larsen
  1 sibling, 1 reply; 28+ messages in thread
From: Natarajan, Kavitha @ 2022-03-14 11:15 UTC (permalink / raw)
  To: Natarajan, Kavitha via Gdb-patches
  Cc: Parasuraman, Hariharan, George, Jini Susan

[AMD Official Use Only]

Appreciate your review comments on this patch.

Thanks,
Kavitha

From: Natarajan, Kavitha
Sent: Friday, March 4, 2022 7:15 PM
To: Natarajan, Kavitha via Gdb-patches <gdb-patches@sourceware.org>
Subject: [PATCH] Debug support for global alias variable

Hi,

For the below testcase, when compiled with clang compiler, debugger is not able to print alias variable type or value.
$ cat test.c
int oldname = 1;
extern int newname attribute((alias("oldname")));
int main ()
{ return 0; }
$ clang -g -O0 test.c
$ gdb a.out
(gdb) ptype oldname
type = int
(gdb) ptype newname
type = <data variable, no debug info>
(gdb) p oldname
$1 = 1
(gdb) p newname
'newname' has unknown type; cast it to its declared type
This is because clang is not emitting dwarf information for alias variable. I have updated clang patch (originally from https://reviews.llvm.org/D103131) to emit debug info for alias variable as imported entity (DW_TAG_imported_declaration):

https://reviews.llvm.org/D120989

However, gdb cannot handle the imported declaration for alias variables. GCC emits debug info for alias variables as DW_TAG_variable which gdb can handle. The discussions in the llvm bug report bug-50052<https://bugs.llvm.org/show_bug.cgi?id=50052> and above review links talk about why it is appropriate to emit alias variable as DW_TAG_imported_declaration rather than DW_TAG_variable. Refer section "3.2.3 Imported (or Renamed) Declaration Entries" in DWARF 5 specification. It was also previously discussed in gdb forum in the below thread:

https://sourceware.org/pipermail/gdb/2021-June/049509.html

The attached gdb patch can handle DW_TAG_imported_declaration as alias variables. This change fixes the failure in testcase:
           gdb.base/symbol-alias.exp
This testcase is also updated to test nested (recursive) alias, static aliasee and deferred aliasee.

Please review the below gdb patch (also attached).

---
gdb/dwarf2/read.c                       | 113 ++++++++++++++++--------
gdb/testsuite/gdb.base/symbol-alias.exp |  23 ++++-
gdb/testsuite/gdb.base/symbol-alias2.c  |  10 +++
3 files changed, 107 insertions(+), 39 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 10550336063..0f709d9ccc1 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -1132,6 +1132,10 @@ static void add_partial_subprogram (struct partial_die_info *pdi,
                                    CORE_ADDR *lowpc, CORE_ADDR *highpc,
                                    int need_pc, struct dwarf2_cu *cu);

+static void var_decode_location (struct attribute *attr,
+                                 struct symbol *sym,
+                                 struct dwarf2_cu *cu);
+
static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);

static struct partial_die_info *load_partial_dies
@@ -1332,7 +1336,7 @@ static struct using_direct **using_directives (struct dwarf2_cu *cu);

static void read_import_statement (struct die_info *die, struct dwarf2_cu *);

-static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
+static int read_alias (struct die_info *die, struct dwarf2_cu *cu);

static struct type *read_module_type (struct die_info *die,
                                      struct dwarf2_cu *cu);
@@ -9742,9 +9746,11 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
       break;
     case DW_TAG_imported_declaration:
       cu->processing_has_namespace_info = true;
-      if (read_namespace_alias (die, cu))
+      if (((cu->per_cu->lang == language_c)
+            || (cu->per_cu->lang == language_cplus))
+                            && read_alias (die, cu))
        break;
-      /* The declaration is not a global namespace alias.  */
+      /* The declaration is not a global namespace or variable alias. */
       /* Fall through.  */
     case DW_TAG_imported_module:
       cu->processing_has_namespace_info = true;
@@ -10212,18 +10218,20 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
   return retval;
}

-/* Inspect DIE in CU for a namespace alias.  If one exists, record
-   a new symbol for it.
+#define MAX_NESTED_IMPORTED_DECLARATIONS 100
+
+/* Inspect DIE in CU for a namespace alias or a variable
+   with alias attribute. If one exists, record a new symbol
+   for it.

-   Returns 1 if a namespace alias was recorded, 0 otherwise.  */
+   Returns 1 if an alias was recorded, 0 otherwise. */

static int
-read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
+read_alias (struct die_info *die, struct dwarf2_cu *cu)
{
   struct attribute *attr;

-  /* If the die does not have a name, this is not a namespace
-     alias.  */
+  /* The die must have a name for namespace or variable alias */
   attr = dwarf2_attr (die, DW_AT_name, cu);
   if (attr != NULL)
     {
@@ -10232,42 +10240,71 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
       struct dwarf2_cu *imported_cu = cu;

       /* If the compiler has nested DW_AT_imported_declaration DIEs,
-        keep inspecting DIEs until we hit the underlying import.  */
-#define MAX_NESTED_IMPORTED_DECLARATIONS 100
+         keep inspecting DIEs until we hit the underlying import. */
       for (num = 0; num  < MAX_NESTED_IMPORTED_DECLARATIONS; ++num)
-       {
-         attr = dwarf2_attr (d, DW_AT_import, cu);
-         if (attr == NULL)
-           break;
+        {
+          attr = dwarf2_attr (d, DW_AT_import, cu);
+          if (attr == NULL)
+            return 0;

-         d = follow_die_ref (d, attr, &imported_cu);
-         if (d->tag != DW_TAG_imported_declaration)
-           break;
-       }
+          d = follow_die_ref (d, attr, &imported_cu);
+          if (d->tag != DW_TAG_imported_declaration)
+            break;
+        }

       if (num == MAX_NESTED_IMPORTED_DECLARATIONS)
-       {
-         complaint (_("DIE at %s has too many recursively imported "
-                      "declarations"), sect_offset_str (d->sect_off));
-         return 0;
-       }
+        {
+          complaint (_("DIE at %s has too many recursively imported "
+                       "declarations"), sect_offset_str (d->sect_off));
+          return 0;
+        }

       if (attr != NULL)
-       {
-         struct type *type;
-         sect_offset sect_off = attr->get_ref_die_offset ();
-
-         type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
-         if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
-           {
-             /* This declaration is a global namespace alias.  Add
-                a symbol for it whose type is the aliased namespace.  */
-             new_symbol (die, type, cu);
-             return 1;
-           }
-       }
+        {
+          struct type *type;
+          if (d->tag == DW_TAG_variable)
+            {
+             /* This declaration is a global variable alias. Add
+                a symbol for it whose type is same as aliased variable. */
+              type = die_type (d, imported_cu);
+              struct symbol *sym = new_symbol(die, type, cu);
+              attr = dwarf2_attr (d, DW_AT_location, imported_cu);
+              if (attr != nullptr)
+                {
+                  var_decode_location (attr, sym, cu);
+                  return 1;
+                }
+              else
+                {
+                  /* We do not know the address of this symbol.
+                     If it is an external symbol and we have type information
+                     for it, enter the symbol as a LOC_UNRESOLVED symbol.
+                     The address of the variable will then be determined from
+                     the minimal symbol table whenever the variable is
+                     referenced.  */
+                  attr = dwarf2_attr (d, DW_AT_external, imported_cu);
+                  if (attr != nullptr && attr->as_boolean ()
+                      && dwarf2_attr (d, DW_AT_type, imported_cu) != NULL)
+                    {
+                      sym->set_aclass_index (LOC_UNRESOLVED);
+                      return 1;
+                    }
+                }
+            }
+          else
+            {
+              sect_offset sect_off = attr->get_ref_die_offset ();
+              type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
+              if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+                {
+                  /* This declaration is a global namespace alias. Add
+                     a symbol for it whose type is the aliased namespace. */
+                  new_symbol (die, type, cu);
+                  return 1;
+                }
+            }
+        }
     }
-
   return 0;
}

diff --git a/gdb/testsuite/gdb.base/symbol-alias.exp b/gdb/testsuite/gdb.base/symbol-alias.exp
index 2b53cc31053..1259c1daf1d 100644
--- a/gdb/testsuite/gdb.base/symbol-alias.exp
+++ b/gdb/testsuite/gdb.base/symbol-alias.exp
@@ -15,6 +15,7 @@
# along with this program.  If not, see http://www.gnu.org/licenses/.

standard_testfile symbol-alias.c symbol-alias2.c
+set using_clang [test_compiler_info clang*]

if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile $srcfile2]] } {
     return -1
@@ -31,6 +32,26 @@ foreach f {"func" "func_alias"} {
}

# Variables.
-foreach v {"g_var_s" "g_var_s_alias"} {
+foreach v {"g_var_s" "g_var_s_alias" "g_var_s_alias2"} {
     gdb_test "p $v" "= {field1 = 1, field2 = 2}"
}
+
+# Static Variable.
+foreach v {"g_var" "g_var_alias"} {
+    gdb_test "p $v" " = 1"
+}
+
+# Deferred Variable.
+gdb_test "p g_def_var" " = 2"
+gdb_test_multiple "p g_def_var_alias" "p g_def_var_alias" {
+    -re  " = 2.*$gdb_prompt $" {
+        pass "print alias of deferred variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+        if { $using_clang } {
+          xfail "print alias of deferred variable"
+        } else {
+          fail "print alias of deferred variable"
+        }
+    }
+}
diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c b/gdb/testsuite/gdb.base/symbol-alias2.c
index 34f4e121e25..79b3195caf5 100644
--- a/gdb/testsuite/gdb.base/symbol-alias2.c
+++ b/gdb/testsuite/gdb.base/symbol-alias2.c
@@ -23,6 +23,8 @@ struct S

struct S g_var_s = { 1, 2 };

+static int g_var = 1;
+
#ifdef __cplusplus
/* So that the alias attribute below work without having to figure out
    this function's mangled name.  */
@@ -38,3 +40,11 @@ func (void)
struct S *func_alias (void) __attribute__ ((alias ("func")));

extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));
+
+extern struct S g_var_s_alias2 __attribute__ ((alias ("g_var_s_alias")));
+
+extern int g_var_alias __attribute__ ((alias ("g_var")));
+
+extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
+
+int g_def_var = 2;
--


^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [PATCH] Debug support for global alias variable
  2022-03-14 11:15 ` Natarajan, Kavitha
@ 2022-03-24  6:36   ` Natarajan, Kavitha
  0 siblings, 0 replies; 28+ messages in thread
From: Natarajan, Kavitha @ 2022-03-24  6:36 UTC (permalink / raw)
  To: Natarajan, Kavitha via Gdb-patches
  Cc: Parasuraman, Hariharan, George, Jini Susan

[AMD Official Use Only]

Ping!

From: Natarajan, Kavitha
Sent: Monday, March 14, 2022 4:45 PM
To: 'Natarajan, Kavitha via Gdb-patches' <gdb-patches@sourceware.org>
Cc: Parasuraman, Hariharan <Hariharan.Parasuraman@amd.com>; George, Jini Susan <JiniSusan.George@amd.com>
Subject: RE: [PATCH] Debug support for global alias variable

Appreciate your review comments on this patch.

Thanks,
Kavitha

From: Natarajan, Kavitha
Sent: Friday, March 4, 2022 7:15 PM
To: Natarajan, Kavitha via Gdb-patches <gdb-patches@sourceware.org<mailto:gdb-patches@sourceware.org>>
Subject: [PATCH] Debug support for global alias variable

Hi,

For the below testcase, when compiled with clang compiler, debugger is not able to print alias variable type or value.
$ cat test.c
int oldname = 1;
extern int newname attribute((alias("oldname")));
int main ()
{ return 0; }
$ clang -g -O0 test.c
$ gdb a.out
(gdb) ptype oldname
type = int
(gdb) ptype newname
type = <data variable, no debug info>
(gdb) p oldname
$1 = 1
(gdb) p newname
'newname' has unknown type; cast it to its declared type
This is because clang is not emitting dwarf information for alias variable. I have updated clang patch (originally from https://reviews.llvm.org/D103131) to emit debug info for alias variable as imported entity (DW_TAG_imported_declaration):

https://reviews.llvm.org/D120989

However, gdb cannot handle the imported declaration for alias variables. GCC emits debug info for alias variables as DW_TAG_variable which gdb can handle. The discussions in the llvm bug report bug-50052<https://bugs.llvm.org/show_bug.cgi?id=50052> and above review links talk about why it is appropriate to emit alias variable as DW_TAG_imported_declaration rather than DW_TAG_variable. Refer section "3.2.3 Imported (or Renamed) Declaration Entries" in DWARF 5 specification. It was also previously discussed in gdb forum in the below thread:

https://sourceware.org/pipermail/gdb/2021-June/049509.html

The attached gdb patch can handle DW_TAG_imported_declaration as alias variables. This change fixes the failure in testcase:
           gdb.base/symbol-alias.exp
This testcase is also updated to test nested (recursive) alias, static aliasee and deferred aliasee.

Please review the below gdb patch (also attached).

---
gdb/dwarf2/read.c                       | 113 ++++++++++++++++--------
gdb/testsuite/gdb.base/symbol-alias.exp |  23 ++++-
gdb/testsuite/gdb.base/symbol-alias2.c  |  10 +++
3 files changed, 107 insertions(+), 39 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 10550336063..0f709d9ccc1 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -1132,6 +1132,10 @@ static void add_partial_subprogram (struct partial_die_info *pdi,
                                    CORE_ADDR *lowpc, CORE_ADDR *highpc,
                                    int need_pc, struct dwarf2_cu *cu);

+static void var_decode_location (struct attribute *attr,
+                                 struct symbol *sym,
+                                 struct dwarf2_cu *cu);
+
static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);

static struct partial_die_info *load_partial_dies
@@ -1332,7 +1336,7 @@ static struct using_direct **using_directives (struct dwarf2_cu *cu);

static void read_import_statement (struct die_info *die, struct dwarf2_cu *);

-static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
+static int read_alias (struct die_info *die, struct dwarf2_cu *cu);

static struct type *read_module_type (struct die_info *die,
                                      struct dwarf2_cu *cu);
@@ -9742,9 +9746,11 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
       break;
     case DW_TAG_imported_declaration:
       cu->processing_has_namespace_info = true;
-      if (read_namespace_alias (die, cu))
+      if (((cu->per_cu->lang == language_c)
+            || (cu->per_cu->lang == language_cplus))
+                            && read_alias (die, cu))
        break;
-      /* The declaration is not a global namespace alias.  */
+      /* The declaration is not a global namespace or variable alias. */
       /* Fall through.  */
     case DW_TAG_imported_module:
       cu->processing_has_namespace_info = true;
@@ -10212,18 +10218,20 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
   return retval;
}

-/* Inspect DIE in CU for a namespace alias.  If one exists, record
-   a new symbol for it.
+#define MAX_NESTED_IMPORTED_DECLARATIONS 100
+
+/* Inspect DIE in CU for a namespace alias or a variable
+   with alias attribute. If one exists, record a new symbol
+   for it.

-   Returns 1 if a namespace alias was recorded, 0 otherwise.  */
+   Returns 1 if an alias was recorded, 0 otherwise. */

static int
-read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
+read_alias (struct die_info *die, struct dwarf2_cu *cu)
{
   struct attribute *attr;

-  /* If the die does not have a name, this is not a namespace
-     alias.  */
+  /* The die must have a name for namespace or variable alias */
   attr = dwarf2_attr (die, DW_AT_name, cu);
   if (attr != NULL)
     {
@@ -10232,42 +10240,71 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
       struct dwarf2_cu *imported_cu = cu;

       /* If the compiler has nested DW_AT_imported_declaration DIEs,
-        keep inspecting DIEs until we hit the underlying import.  */
-#define MAX_NESTED_IMPORTED_DECLARATIONS 100
+         keep inspecting DIEs until we hit the underlying import. */
       for (num = 0; num  < MAX_NESTED_IMPORTED_DECLARATIONS; ++num)
-       {
-         attr = dwarf2_attr (d, DW_AT_import, cu);
-         if (attr == NULL)
-           break;
+        {
+          attr = dwarf2_attr (d, DW_AT_import, cu);
+          if (attr == NULL)
+            return 0;

-         d = follow_die_ref (d, attr, &imported_cu);
-         if (d->tag != DW_TAG_imported_declaration)
-           break;
-       }
+          d = follow_die_ref (d, attr, &imported_cu);
+          if (d->tag != DW_TAG_imported_declaration)
+            break;
+        }

       if (num == MAX_NESTED_IMPORTED_DECLARATIONS)
-       {
-         complaint (_("DIE at %s has too many recursively imported "
-                      "declarations"), sect_offset_str (d->sect_off));
-         return 0;
-       }
+        {
+          complaint (_("DIE at %s has too many recursively imported "
+                       "declarations"), sect_offset_str (d->sect_off));
+          return 0;
+        }

       if (attr != NULL)
-       {
-         struct type *type;
-         sect_offset sect_off = attr->get_ref_die_offset ();
-
-         type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
-         if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
-           {
-             /* This declaration is a global namespace alias.  Add
-                a symbol for it whose type is the aliased namespace.  */
-             new_symbol (die, type, cu);
-             return 1;
-           }
-       }
+        {
+          struct type *type;
+          if (d->tag == DW_TAG_variable)
+            {
+             /* This declaration is a global variable alias. Add
+                a symbol for it whose type is same as aliased variable. */
+              type = die_type (d, imported_cu);
+              struct symbol *sym = new_symbol(die, type, cu);
+              attr = dwarf2_attr (d, DW_AT_location, imported_cu);
+              if (attr != nullptr)
+                {
+                  var_decode_location (attr, sym, cu);
+                  return 1;
+                }
+              else
+                {
+                  /* We do not know the address of this symbol.
+                     If it is an external symbol and we have type information
+                     for it, enter the symbol as a LOC_UNRESOLVED symbol.
+                     The address of the variable will then be determined from
+                     the minimal symbol table whenever the variable is
+                     referenced.  */
+                  attr = dwarf2_attr (d, DW_AT_external, imported_cu);
+                  if (attr != nullptr && attr->as_boolean ()
+                      && dwarf2_attr (d, DW_AT_type, imported_cu) != NULL)
+                    {
+                      sym->set_aclass_index (LOC_UNRESOLVED);
+                      return 1;
+                    }
+                }
+            }
+          else
+            {
+              sect_offset sect_off = attr->get_ref_die_offset ();
+              type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
+              if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+                {
+                  /* This declaration is a global namespace alias. Add
+                     a symbol for it whose type is the aliased namespace. */
+                  new_symbol (die, type, cu);
+                  return 1;
+                }
+            }
+        }
     }
-
   return 0;
}

diff --git a/gdb/testsuite/gdb.base/symbol-alias.exp b/gdb/testsuite/gdb.base/symbol-alias.exp
index 2b53cc31053..1259c1daf1d 100644
--- a/gdb/testsuite/gdb.base/symbol-alias.exp
+++ b/gdb/testsuite/gdb.base/symbol-alias.exp
@@ -15,6 +15,7 @@
# along with this program.  If not, see http://www.gnu.org/licenses/.

standard_testfile symbol-alias.c symbol-alias2.c
+set using_clang [test_compiler_info clang*]

if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile $srcfile2]] } {
     return -1
@@ -31,6 +32,26 @@ foreach f {"func" "func_alias"} {
}

# Variables.
-foreach v {"g_var_s" "g_var_s_alias"} {
+foreach v {"g_var_s" "g_var_s_alias" "g_var_s_alias2"} {
     gdb_test "p $v" "= {field1 = 1, field2 = 2}"
}
+
+# Static Variable.
+foreach v {"g_var" "g_var_alias"} {
+    gdb_test "p $v" " = 1"
+}
+
+# Deferred Variable.
+gdb_test "p g_def_var" " = 2"
+gdb_test_multiple "p g_def_var_alias" "p g_def_var_alias" {
+    -re  " = 2.*$gdb_prompt $" {
+        pass "print alias of deferred variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+        if { $using_clang } {
+          xfail "print alias of deferred variable"
+        } else {
+          fail "print alias of deferred variable"
+        }
+    }
+}
diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c b/gdb/testsuite/gdb.base/symbol-alias2.c
index 34f4e121e25..79b3195caf5 100644
--- a/gdb/testsuite/gdb.base/symbol-alias2.c
+++ b/gdb/testsuite/gdb.base/symbol-alias2.c
@@ -23,6 +23,8 @@ struct S

struct S g_var_s = { 1, 2 };

+static int g_var = 1;
+
#ifdef __cplusplus
/* So that the alias attribute below work without having to figure out
    this function's mangled name.  */
@@ -38,3 +40,11 @@ func (void)
struct S *func_alias (void) __attribute__ ((alias ("func")));

extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));
+
+extern struct S g_var_s_alias2 __attribute__ ((alias ("g_var_s_alias")));
+
+extern int g_var_alias __attribute__ ((alias ("g_var")));
+
+extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
+
+int g_def_var = 2;
--


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] Debug support for global alias variable
  2022-03-04 13:44 [PATCH] Debug support for global alias variable Natarajan, Kavitha
  2022-03-14 11:15 ` Natarajan, Kavitha
@ 2022-03-24 13:53 ` Bruno Larsen
  2022-03-28 15:14   ` Natarajan, Kavitha
  1 sibling, 1 reply; 28+ messages in thread
From: Bruno Larsen @ 2022-03-24 13:53 UTC (permalink / raw)
  To: Natarajan, Kavitha, Natarajan, Kavitha via Gdb-patches

Hello Kavitha!


Thanks for looking at this! I have taken a look and have some comments. I couldn't really test if it fixed the issue since it seems that the patch is not merged yet and I don't really know how to work with LLVM's patch review format, but I have tested for regressions on x86_64 and I see no regressions.

About the patch idea itself, I agree that imported_declaration looks like a good fit for an aliased variable, so I like the general direction of this patch.

Also, I can't approve any patches, but I hope this review helps get the conversation going.

On 3/4/22 10:44, Natarajan, Kavitha via Gdb-patches wrote:
> [AMD Official Use Only]
> 
> Hi,
> 
> For the below testcase, when compiled with clang compiler, debugger is not able to print alias variable type or value.
> $ cat test.c
> int oldname = 1;
> extern int newname attribute((alias("oldname")));
> int main ()
> { return 0; }
> $ clang -g -O0 test.c
> $ gdb a.out
> (gdb) ptype oldname
> type = int
> (gdb) ptype newname
> type = <data variable, no debug info>
> (gdb) p oldname
> $1 = 1
> (gdb) p newname
> 'newname' has unknown type; cast it to its declared type
> This is because clang is not emitting dwarf information for alias variable. I have updated clang patch (originally from https://reviews.llvm.org/D103131) to emit debug info for alias variable as imported entity (DW_TAG_imported_declaration):
> 
> https://reviews.llvm.org/D120989
> 
> However, gdb cannot handle the imported declaration for alias variables. GCC emits debug info for alias variables as DW_TAG_variable which gdb can handle. The discussions in the llvm bug report bug-50052<https://bugs.llvm.org/show_bug.cgi?id=50052> and above review links talk about why it is appropriate to emit alias variable as DW_TAG_imported_declaration rather than DW_TAG_variable. Refer section "3.2.3 Imported (or Renamed) Declaration Entries" in DWARF 5 specification. It was also previously discussed in gdb forum in the below thread:
> 
> https://sourceware.org/pipermail/gdb/2021-June/049509.html
> 
> The attached gdb patch can handle DW_TAG_imported_declaration as alias variables. This change fixes the failure in testcase:
>             gdb.base/symbol-alias.exp
> This testcase is also updated to test nested (recursive) alias, static aliasee and deferred aliasee.

> 
> Please review the below gdb patch (also attached).


> 
> ---
> gdb/dwarf2/read.c                       | 113 ++++++++++++++++--------
> gdb/testsuite/gdb.base/symbol-alias.exp |  23 ++++-
> gdb/testsuite/gdb.base/symbol-alias2.c  |  10 +++
> 3 files changed, 107 insertions(+), 39 deletions(-)
> 
> diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
> index 10550336063..0f709d9ccc1 100644
> --- a/gdb/dwarf2/read.c
> +++ b/gdb/dwarf2/read.c
> @@ -1132,6 +1132,10 @@ static void add_partial_subprogram (struct partial_die_info *pdi,
>                                      CORE_ADDR *lowpc, CORE_ADDR *highpc,
>                                      int need_pc, struct dwarf2_cu *cu);
> 
> +static void var_decode_location (struct attribute *attr,
> +                                 struct symbol *sym,
> +                                 struct dwarf2_cu *cu);
> +

Could you have these have tabs instead of 8 spaces? This goes for all indentations that have at least 8 spaces, by the way.

> static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);
> 
> static struct partial_die_info *load_partial_dies
> @@ -1332,7 +1336,7 @@ static struct using_direct **using_directives (struct dwarf2_cu *cu);
> 
> static void read_import_statement (struct die_info *die, struct dwarf2_cu *);
> 
> -static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
> +static int read_alias (struct die_info *die, struct dwarf2_cu *cu);
> 
> static struct type *read_module_type (struct die_info *die,
>                                        struct dwarf2_cu *cu);
> @@ -9742,9 +9746,11 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
>         break;
>       case DW_TAG_imported_declaration:
>         cu->processing_has_namespace_info = true;

Since we are using imported declarations for more than just namespaces, this line is not necessarily true always. I think read_alias is going to have to do this, but a comment explaining why this case is different to the ones around it is welcome.

> -      if (read_namespace_alias (die, cu))
> +      if (((cu->per_cu->lang == language_c)
> +            || (cu->per_cu->lang == language_cplus))
> +                            && read_alias (die, cu))

Could you align the && with the second open parenthesis of the if line? This would make the whole expression easier to read.

>          break;
> -      /* The declaration is not a global namespace alias.  */
> +      /* The declaration is not a global namespace or variable alias. */

We require 2 spaces after the period, even at the end of comments.

>         /* Fall through.  */
>       case DW_TAG_imported_module:
>         cu->processing_has_namespace_info = true;
> @@ -10212,18 +10218,20 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
>     return retval;
> }
> 
> -/* Inspect DIE in CU for a namespace alias.  If one exists, record
> -   a new symbol for it.
> +#define MAX_NESTED_IMPORTED_DECLARATIONS 100
> +
> +/* Inspect DIE in CU for a namespace alias or a variable
> +   with alias attribute. If one exists, record a new symbol
> +   for it.
> 
> -   Returns 1 if a namespace alias was recorded, 0 otherwise.  */
> +   Returns 1 if an alias was recorded, 0 otherwise. */

Same here.

> 
> static int
> -read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
> +read_alias (struct die_info *die, struct dwarf2_cu *cu)
> {
>     struct attribute *attr;
> 
> -  /* If the die does not have a name, this is not a namespace
> -     alias.  */
> +  /* The die must have a name for namespace or variable alias */

And here. Also, please be sure to add periods at the end of comments.

>     attr = dwarf2_attr (die, DW_AT_name, cu);
>     if (attr != NULL)
>       {
> @@ -10232,42 +10240,71 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
>         struct dwarf2_cu *imported_cu = cu;
> 
>         /* If the compiler has nested DW_AT_imported_declaration DIEs,
> -        keep inspecting DIEs until we hit the underlying import.  */
> -#define MAX_NESTED_IMPORTED_DECLARATIONS 100
> +         keep inspecting DIEs until we hit the underlying import. */

And here.

>         for (num = 0; num  < MAX_NESTED_IMPORTED_DECLARATIONS; ++num)
> -       {
> -         attr = dwarf2_attr (d, DW_AT_import, cu);
> -         if (attr == NULL)
> -           break;
> +        {
> +          attr = dwarf2_attr (d, DW_AT_import, cu);
> +          if (attr == NULL)
> +            return 0;
> 
> -         d = follow_die_ref (d, attr, &imported_cu);
> -         if (d->tag != DW_TAG_imported_declaration)
> -           break;
> -       }
> +          d = follow_die_ref (d, attr, &imported_cu);
> +          if (d->tag != DW_TAG_imported_declaration)
> +            break;
> +        }
> 
>         if (num == MAX_NESTED_IMPORTED_DECLARATIONS)
> -       {
> -         complaint (_("DIE at %s has too many recursively imported "
> -                      "declarations"), sect_offset_str (d->sect_off));
> -         return 0;
> -       }
> +        {
> +          complaint (_("DIE at %s has too many recursively imported "
> +                       "declarations"), sect_offset_str (d->sect_off));
> +          return 0;
> +        }
> 
>         if (attr != NULL)
> -       {
> -         struct type *type;
> -         sect_offset sect_off = attr->get_ref_die_offset ();
> -
> -         type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
> -         if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
> -           {
> -             /* This declaration is a global namespace alias.  Add
> -                a symbol for it whose type is the aliased namespace.  */
> -             new_symbol (die, type, cu);
> -             return 1;
> -           }
> -       }
> +        {
> +          struct type *type;
> +          if (d->tag == DW_TAG_variable)
> +            {
> +             /* This declaration is a global variable alias. Add
> +                a symbol for it whose type is same as aliased variable. */
> +              type = die_type (d, imported_cu);
> +              struct symbol *sym = new_symbol(die, type, cu);
> +              attr = dwarf2_attr (d, DW_AT_location, imported_cu);
> +              if (attr != nullptr)
> +                {
> +                  var_decode_location (attr, sym, cu);
> +                  return 1;
> +                }
> +              else
> +                {
> +                  /* We do not know the address of this symbol.
> +                     If it is an external symbol and we have type information
> +                     for it, enter the symbol as a LOC_UNRESOLVED symbol.
> +                     The address of the variable will then be determined from
> +                     the minimal symbol table whenever the variable is
> +                     referenced.  */
> +                  attr = dwarf2_attr (d, DW_AT_external, imported_cu);
> +                  if (attr != nullptr && attr->as_boolean ()
> +                      && dwarf2_attr (d, DW_AT_type, imported_cu) != NULL)
> +                    {
> +                      sym->set_aclass_index (LOC_UNRESOLVED);
> +                      return 1;

If you look at the original code, you see that if a new symbol was allocated, the return is always 1. I think having a possibility that the symbol can be allocated and we still return 0 could be a problem, but I am not sure. Regardless, by this point (and the if block above) we are pretty sure that the DIE is indeed a namespace variable or a variable alias, so returning 0 if we can't find the location seems wrong, but I am not a DWARF reader expert, so take my ramblings with a grain of salt.

<side note> why is this function returning 1 or 0 as boolean, instead of the function returning bool?</side note>

> +                    }
> +                }
> +            }
> +          else
> +            {
> +              sect_offset sect_off = attr->get_ref_die_offset ();
> +              type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
> +              if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
> +                {
> +                  /* This declaration is a global namespace alias. Add
> +                     a symbol for it whose type is the aliased namespace. */
> +                  new_symbol (die, type, cu);
> +                  return 1;
> +                }
> +            }
> +        }

Is this "else" path being exercised anywhere? For this simple code:

namespace n{
     int i;
     int j;
     void f(){ }
}

using n::i;
using n::f;

int var;
extern int newvar __attribute__((alias("var")));

int main(){
     i = 0;
     return 0;
}

g++ makes the following dwarf information:

  <1><2e>: Abbrev Number: 5 (DW_TAG_namespace)
     <2f>   DW_AT_name        : n
     <31>   DW_AT_decl_file   : 1
     <32>   DW_AT_decl_line   : 1
     <33>   DW_AT_decl_column : 11
     <34>   DW_AT_sibling     : <0x5b>
  <2><38>: Abbrev Number: 1 (DW_TAG_variable)
     <39>   DW_AT_name        : i
     <3b>   DW_AT_decl_file   : 1
     <3b>   DW_AT_decl_line   : 2
     <3c>   DW_AT_decl_column : 9
     <3c>   DW_AT_linkage_name: (indirect string, offset: 0x67): _ZN1n1iE
     <40>   DW_AT_type        : <0x5b>
     <44>   DW_AT_external    : 1
     <44>   DW_AT_declaration : 1
  <2><44>: Abbrev Number: 1 (DW_TAG_variable)
     <45>   DW_AT_name        : j
     <47>   DW_AT_decl_file   : 1
     <47>   DW_AT_decl_line   : 3
     <48>   DW_AT_decl_column : 9
     <48>   DW_AT_linkage_name: (indirect string, offset: 0x70): _ZN1n1jE
     <4c>   DW_AT_type        : <0x5b>
     <50>   DW_AT_external    : 1
     <50>   DW_AT_declaration : 1
  <2><50>: Abbrev Number: 6 (DW_TAG_subprogram)
     <51>   DW_AT_external    : 1
     <51>   DW_AT_name        : f
     <53>   DW_AT_decl_file   : 1
     <54>   DW_AT_decl_line   : 4
     <55>   DW_AT_decl_column : 10
     <56>   DW_AT_linkage_name: (indirect string, offset: 0x5d): _ZN1n1fEv
     <5a>   DW_AT_declaration : 1
  <2><5a>: Abbrev Number: 0
  <1><5b>: Abbrev Number: 7 (DW_TAG_base_type)
     <5c>   DW_AT_byte_size   : 4
     <5d>   DW_AT_encoding    : 5        (signed)
     <5e>   DW_AT_name        : int
  <1><62>: Abbrev Number: 2 (DW_TAG_variable)
     <63>   DW_AT_specification: <0x38>
     <67>   DW_AT_location    : 9 byte block: 3 20 40 40 0 0 0 0 0       (DW_OP_addr: 404020)
  <1><71>: Abbrev Number: 2 (DW_TAG_variable)
     <72>   DW_AT_specification: <0x44>
     <76>   DW_AT_location    : 9 byte block: 3 24 40 40 0 0 0 0 0       (DW_OP_addr: 404024)
  <1><80>: Abbrev Number: 3 (DW_TAG_imported_declaration)
     <81>   DW_AT_decl_file   : 1
     <81>   DW_AT_decl_line   : 7
     <82>   DW_AT_decl_column : 10
     <82>   DW_AT_import      : <0x62>   [Abbrev Number: 2 (DW_TAG_variable)]
  <1><86>: Abbrev Number: 3 (DW_TAG_imported_declaration)
     <87>   DW_AT_decl_file   : 1
     <87>   DW_AT_decl_line   : 8
     <88>   DW_AT_decl_column : 10
     <88>   DW_AT_import      : <0x50>   [Abbrev Number: 6 (DW_TAG_subprogram)]
  <1><8c>: Abbrev Number: 8 (DW_TAG_variable)
     <8d>   DW_AT_name        : var
     <91>   DW_AT_decl_file   : 1
     <92>   DW_AT_decl_line   : 10
     <93>   DW_AT_decl_column : 5
     <94>   DW_AT_type        : <0x5b>
     <98>   DW_AT_external    : 1
     <98>   DW_AT_location    : 9 byte block: 3 28 40 40 0 0 0 0 0       (DW_OP_addr: 404028)
  <1><a2>: Abbrev Number: 9 (DW_TAG_variable)
     <a3>   DW_AT_name        : (indirect string, offset: 0x51): newvar
     <a7>   DW_AT_decl_file   : 1
     <a8>   DW_AT_decl_line   : 11
     <a9>   DW_AT_decl_column : 12
     <aa>   DW_AT_type        : <0x5b>
     <ae>   DW_AT_external    : 1
  <1><ae>: Abbrev Number: 10 (DW_TAG_subprogram)
     <af>   DW_AT_external    : 1
     <af>   DW_AT_name        : (indirect string, offset: 0x58): main
     <b3>   DW_AT_decl_file   : 1
     <b4>   DW_AT_decl_line   : 13
     <b5>   DW_AT_decl_column : 5
     <b6>   DW_AT_type        : <0x5b>
     <ba>   DW_AT_low_pc      : 0x40110d
     <c2>   DW_AT_high_pc     : 0x15
     <ca>   DW_AT_frame_base  : 1 byte block: 9c         (DW_OP_call_frame_cfa)
     <cc>   DW_AT_call_all_calls: 1
  <1><cc>: Abbrev Number: 11 (DW_TAG_subprogram)
     <cd>   DW_AT_specification: <0x50>
     <d1>   DW_AT_low_pc      : 0x401106
     <d9>   DW_AT_high_pc     : 0x7
     <e1>   DW_AT_frame_base  : 1 byte block: 9c         (DW_OP_call_frame_cfa)
     <e3>   DW_AT_call_all_calls: 1
  <1><e3>: Abbrev Number: 0


as you can see, the DW_TAG_imported_declaration's DW_AT_import points at the DW_TAG_variable at the global scope, and even though the details of the variable are inside the namespace, the declaration is global.  And imported functions does not use DW_TAG_imported_declaration, so I can't really see when we would use that else block. I think this is a long winded way of asking "can this be removed?".

>       }
> -
>     return 0;
> }
> 
> diff --git a/gdb/testsuite/gdb.base/symbol-alias.exp b/gdb/testsuite/gdb.base/symbol-alias.exp
> index 2b53cc31053..1259c1daf1d 100644
> --- a/gdb/testsuite/gdb.base/symbol-alias.exp
> +++ b/gdb/testsuite/gdb.base/symbol-alias.exp
> @@ -15,6 +15,7 @@
> # along with this program.  If not, see http://www.gnu.org/licenses/.
> 
> standard_testfile symbol-alias.c symbol-alias2.c
> +set using_clang [test_compiler_info clang*]

Since this is a new feature of clang and some tests run on quite old systems, could you try and detect the clang version, so you can have xfails for all aliases if the clang version doesn't emit this information?

> 
> if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile $srcfile2]] } {
>       return -1
> @@ -31,6 +32,26 @@ foreach f {"func" "func_alias"} {
> }
> 
> # Variables.
> -foreach v {"g_var_s" "g_var_s_alias"} {
> +foreach v {"g_var_s" "g_var_s_alias" "g_var_s_alias2"} {
>       gdb_test "p $v" "= {field1 = 1, field2 = 2}"
> }
> +
> +# Static Variable.
> +foreach v {"g_var" "g_var_alias"} {
> +    gdb_test "p $v" " = 1"
> +}
> +
> +# Deferred Variable.
> +gdb_test "p g_def_var" " = 2"
> +gdb_test_multiple "p g_def_var_alias" "p g_def_var_alias" {
> +    -re  " = 2.*$gdb_prompt $" {
> +        pass "print alias of deferred variable"
> +    }
> +    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
> +        if { $using_clang } {
> +          xfail "print alias of deferred variable"
> +        } else {
> +          fail "print alias of deferred variable"
> +        }
> +    }
> +}
> diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c b/gdb/testsuite/gdb.base/symbol-alias2.c
> index 34f4e121e25..79b3195caf5 100644
> --- a/gdb/testsuite/gdb.base/symbol-alias2.c
> +++ b/gdb/testsuite/gdb.base/symbol-alias2.c
> @@ -23,6 +23,8 @@ struct S
> 
> struct S g_var_s = { 1, 2 };
> 
> +static int g_var = 1;
> +
> #ifdef __cplusplus
> /* So that the alias attribute below work without having to figure out
>      this function's mangled name.  */
> @@ -38,3 +40,11 @@ func (void)
> struct S *func_alias (void) __attribute__ ((alias ("func")));
> 
> extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));
> +
> +extern struct S g_var_s_alias2 __attribute__ ((alias ("g_var_s_alias")));
> +
> +extern int g_var_alias __attribute__ ((alias ("g_var")));
> +
> +extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
> +
> +int g_def_var = 2;
> --
> 


-- 
Cheers!
Bruno Larsen


^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [PATCH] Debug support for global alias variable
  2022-03-24 13:53 ` Bruno Larsen
@ 2022-03-28 15:14   ` Natarajan, Kavitha
  2022-03-29 14:02     ` Bruno Larsen
  0 siblings, 1 reply; 28+ messages in thread
From: Natarajan, Kavitha @ 2022-03-28 15:14 UTC (permalink / raw)
  To: Bruno Larsen, Natarajan, Kavitha via Gdb-patches
  Cc: George, Jini Susan, Parasuraman, Hariharan

[-- Attachment #1: Type: text/plain, Size: 13751 bytes --]

[AMD Official Use Only]

Hello Bruno,

Thanks for reviewing the patch. It helps a lot. Along with my responses to your questions,
I have also attached the new patch with the changes. Please review.

> > --- a/gdb/dwarf2/read.c
> > +++ b/gdb/dwarf2/read.c

> Could you have these have tabs instead of 8 spaces? This goes for all
> indentations that have at least 8 spaces, by the way.

The entire patch is fixed by replacing 8 spaces with tabs.

> Since we are using imported declarations for more than just namespaces,
> this line is not necessarily true always. I think read_alias is going to have to do
> this, but a comment explaining why this case is different to the ones around
> it is welcome.

Added comment and set the flag to false if it is not namespace alias in read_alias function.

> Could you align the && with the second open parenthesis of the if line? This
> would make the whole expression easier to read.

Done.

> We require 2 spaces after the period, even at the end of comments.

Done for the entire patch.

> If you look at the original code, you see that if a new symbol was allocated,
> the return is always 1. I think having a possibility that the symbol can be
> allocated and we still return 0 could be a problem, but I am not sure.
> Regardless, by this point (and the if block above) we are pretty sure that the
> DIE is indeed a namespace variable or a variable alias, so returning 0 if we
> can't find the location seems wrong, but I am not a DWARF reader expert, so
> take my ramblings with a grain of salt.

I agree. The symbol is an imported declaration and a new symbol is created for the same.
I don't see any condition when it doesn't satisfy if or else condition and return false.
I have slightly modified the code so the location is either unresolved or fixed from
the import variable.

> <side note> why is this function returning 1 or 0 as boolean, instead of the
> function returning bool?</side note>

The function shall return bool instead of int. Fixed in the new patch.

> Is this "else" path being exercised anywhere? For this simple code:
>
> namespace n{
>      int i;
>      int j;
>      void f(){ }
> }
>
> using n::i;
> using n::f;
>
> int var;
> extern int newvar __attribute__((alias("var")));
>
> int main(){
>      i = 0;
>      return 0;
> }
>

Imported declaration is emitted for namespace alias. If you declare as below
in the above program:

namespace m = n;

Clang will generate,

<1><23>: Abbrev Number: 2 (DW_TAG_namespace)
       <24>   DW_AT_name        : (indexed string: 0x3): n

[...]

<1><59>: Abbrev Number: 7 (DW_TAG_imported_declaration)
       <5a>   DW_AT_decl_file   : 0
       <5b>   DW_AT_decl_line   : 7
       <5c>   DW_AT_import      : <0x23>   [Abbrev Number: 2 (DW_TAG_namespace)]
       <60>   DW_AT_name        : (indexed string: 0xa): m

This is handled in the "else" path.

> > --- a/gdb/testsuite/gdb.base/symbol-alias.exp
> > +++ b/gdb/testsuite/gdb.base/symbol-alias.exp

> Since this is a new feature of clang and some tests run on quite old systems,
> could you try and detect the clang version, so you can have xfails for all
> aliases if the clang version doesn't emit this information?

Fixed. As of now, the clang version is checked for 14-0-0 and above. Can modify based on the version
in which this fix goes in finally. It should give 5 XFAILs for clang versions without the fix and 1 XFAIL
with the fix.
I have also added one more test point when the location information is missing (g_def_var2_alias2).

---------------
When clang emits the dwarf information of global alias variable
as DW_TAG_imported_declaration, gdb does not handle it. GDB reads
this tag as C++/fortran imported declaration (type alias, namespace
alias and fortran module). Added support to handle this tag as
alias variable.

This change fixes the failure in gdb.base/symbol-alias.exp testcase.
This testcase is also updated to test nested (recursive) alias.

Reviewed by: Bruno Larsen <blarsen@redhat.com>
---
 gdb/dwarf2/read.c                       | 74 +++++++++++++++++--------
 gdb/testsuite/gdb.base/symbol-alias.exp | 57 ++++++++++++++++++-
 gdb/testsuite/gdb.base/symbol-alias2.c  | 16 ++++++
 3 files changed, 121 insertions(+), 26 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index f9c942d91d3..6510dd94ac3 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -1132,6 +1132,10 @@ static void add_partial_subprogram (struct partial_die_info *pdi,
                                    CORE_ADDR *lowpc, CORE_ADDR *highpc,
                                    int need_pc, struct dwarf2_cu *cu);

+static void var_decode_location (struct attribute *attr,
+                                struct symbol *sym,
+                                struct dwarf2_cu *cu);
+
 static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);

 static struct partial_die_info *load_partial_dies
@@ -1332,7 +1336,7 @@ static struct using_direct **using_directives (struct dwarf2_cu *cu);

 static void read_import_statement (struct die_info *die, struct dwarf2_cu *);

-static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
+static bool read_alias (struct die_info *die, struct dwarf2_cu *cu);

 static struct type *read_module_type (struct die_info *die,
                                      struct dwarf2_cu *cu);
@@ -9741,10 +9745,14 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
       read_module (die, cu);
       break;
     case DW_TAG_imported_declaration:
+      /* If the imported declaration is for global variable alias,
+         this flag is set to false in read_alias function.  */
       cu->processing_has_namespace_info = true;
-      if (read_namespace_alias (die, cu))
+      if (((cu->per_cu->lang == language_c)
+          || (cu->per_cu->lang == language_cplus))
+         && read_alias (die, cu))
        break;
-      /* The declaration is not a global namespace alias.  */
+      /* The declaration is not a global namespace or variable alias.  */
       /* Fall through.  */
     case DW_TAG_imported_module:
       cu->processing_has_namespace_info = true;
@@ -10212,18 +10220,20 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
   return retval;
 }

-/* Inspect DIE in CU for a namespace alias.  If one exists, record
-   a new symbol for it.
+#define MAX_NESTED_IMPORTED_DECLARATIONS 100

-   Returns 1 if a namespace alias was recorded, 0 otherwise.  */
+/* Inspect DIE in CU for a namespace alias or a variable
+   with alias attribute. If one exists, record a new symbol
+   for it.

-static int
-read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
+   Returns 1 if an alias was recorded, 0 otherwise.  */
+
+static bool
+read_alias (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct attribute *attr;

-  /* If the die does not have a name, this is not a namespace
-     alias.  */
+  /* The die must have a name for namespace or variable alias.  */
   attr = dwarf2_attr (die, DW_AT_name, cu);
   if (attr != NULL)
     {
@@ -10232,13 +10242,12 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
       struct dwarf2_cu *imported_cu = cu;

       /* If the compiler has nested DW_AT_imported_declaration DIEs,
-        keep inspecting DIEs until we hit the underlying import.  */
-#define MAX_NESTED_IMPORTED_DECLARATIONS 100
+         keep inspecting DIEs until we hit the underlying import.  */
       for (num = 0; num  < MAX_NESTED_IMPORTED_DECLARATIONS; ++num)
        {
          attr = dwarf2_attr (d, DW_AT_import, cu);
          if (attr == NULL)
-           break;
+           return false;

          d = follow_die_ref (d, attr, &imported_cu);
          if (d->tag != DW_TAG_imported_declaration)
@@ -10249,26 +10258,43 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
        {
          complaint (_("DIE at %s has too many recursively imported "
                       "declarations"), sect_offset_str (d->sect_off));
-         return 0;
+         return false;
        }

       if (attr != NULL)
        {
          struct type *type;
-         sect_offset sect_off = attr->get_ref_die_offset ();
-
-         type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
-         if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+         if (d->tag == DW_TAG_variable)
            {
-             /* This declaration is a global namespace alias.  Add
-                a symbol for it whose type is the aliased namespace.  */
-             new_symbol (die, type, cu);
-             return 1;
+             /* This declaration is a global variable alias. Add
+                a symbol for it whose type is same as aliased variable.  */
+             type = die_type (d, imported_cu);
+             struct symbol *sym = new_symbol(die, type, cu);
+             attr = dwarf2_attr (d, DW_AT_location, imported_cu);
+             sym->set_aclass_index (LOC_UNRESOLVED);
+             if (attr != nullptr)
+               {
+                 var_decode_location (attr, sym, cu);
+               }
+             /* Reset the flag as it is not a namespace alias.  */
+             cu->processing_has_namespace_info = false;
+             return true;
+           }
+         else
+           {
+             sect_offset sect_off = attr->get_ref_die_offset ();
+             type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
+             if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+               {
+                 /* This declaration is a global namespace alias. Add
+                    a symbol for it whose type is the aliased namespace.  */
+                 new_symbol (die, type, cu);
+                 return true;
+               }
            }
        }
     }
-
-  return 0;
+  return false;
 }

 /* Return the using directives repository (global or local?) to use in the
diff --git a/gdb/testsuite/gdb.base/symbol-alias.exp b/gdb/testsuite/gdb.base/symbol-alias.exp
index 2b53cc31053..253a60d5403 100644
--- a/gdb/testsuite/gdb.base/symbol-alias.exp
+++ b/gdb/testsuite/gdb.base/symbol-alias.exp
@@ -15,6 +15,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.

 standard_testfile symbol-alias.c symbol-alias2.c
+set using_clang [test_compiler_info {clang-1[4-9]-*-*}]

 if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile $srcfile2]] } {
     return -1
@@ -31,6 +32,58 @@ foreach f {"func" "func_alias"} {
 }

 # Variables.
-foreach v {"g_var_s" "g_var_s_alias"} {
-    gdb_test "p $v" "= {field1 = 1, field2 = 2}"
+gdb_test "p g_var_s" "= {field1 = 1, field2 = 2}"
+foreach v {"g_var_s_alias" "g_var_s_alias2"} {
+    gdb_test_multiple "p $v" "p $v" {
+       -re  " = {field1 = 1, field2 = 2}.*$gdb_prompt $" {
+           pass "print alias of variable $v"
+       }
+       -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+           if { ! $using_clang } {
+               xfail "print alias variable $v"
+           } else {
+               fail "print alias variable $v"
+           }
+       }
+    }
+}
+
+# Static Variable.
+gdb_test "p g_var" " = 1"
+gdb_test_multiple "p g_var_alias" "p g_var_alias" {
+    -re  " = 1.*$gdb_prompt $" {
+       pass "print alias of static variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+       if { ! $using_clang } {
+         xfail "print alias of static variable"
+       } else {
+         fail "print alias of static variable"
+       }
+    }
+}
+
+# Deferred Variable.
+gdb_test "p g_def_var" " = 2"
+gdb_test_multiple "p g_def_var_alias" "p g_def_var_alias" {
+    -re  " = 2.*$gdb_prompt $" {
+       pass "print alias of deferred variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+       xfail "print alias of deferred variable"
+    }
+}
+
+# Alias of deferred Variable alias.
+gdb_test_multiple "p g_def_var2_alias2" "p g_def_var2_alias2" {
+    -re  " = 3.*$gdb_prompt $" {
+       pass "print alias of alias of deferred variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+       if { ! $using_clang } {
+         xfail "print alias of alias of deferred variable"
+       } else {
+         fail "print alias of alias of deferred variable"
+       }
+    }
 }
diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c b/gdb/testsuite/gdb.base/symbol-alias2.c
index 34f4e121e25..41d4b6a53e5 100644
--- a/gdb/testsuite/gdb.base/symbol-alias2.c
+++ b/gdb/testsuite/gdb.base/symbol-alias2.c
@@ -23,6 +23,8 @@ struct S

 struct S g_var_s = { 1, 2 };

+static int g_var = 1;
+
 #ifdef __cplusplus
 /* So that the alias attribute below work without having to figure out
    this function's mangled name.  */
@@ -38,3 +40,17 @@ func (void)
 struct S *func_alias (void) __attribute__ ((alias ("func")));

 extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));
+
+extern struct S g_var_s_alias2 __attribute__ ((alias ("g_var_s_alias")));
+
+extern int g_var_alias __attribute__ ((alias ("g_var")));
+
+extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
+
+int g_def_var = 2;
+
+extern int g_def_var2_alias __attribute__ ((alias ("g_def_var2")));
+
+int g_def_var2 = 3;
+
+extern int g_def_var2_alias2 __attribute__ ((alias ("g_def_var2_alias")));
--

Regards,
Kavitha

[-- Attachment #2: 0002-Debug-support-for-C-global-alias-variable-bruno.patch --]
[-- Type: application/octet-stream, Size: 9385 bytes --]

From d2d2f82d93f38575cb3f6fbd34acb3244cd63502 Mon Sep 17 00:00:00 2001
From: Kavitha Natarajan <kavitha.natarajan@amd.com>
Date: Mon, 28 Mar 2022 09:51:00 +0530
Subject: [PATCH] Debug support for global alias variable

When clang emits the dwarf information of global alias variable
as DW_TAG_imported_declaration, gdb does not handle it. GDB reads
this tag as C++/fortran imported declaration (type alias, namespace
alias and fortran module). Added support to handle this tag as
alias variable.

This change fixes the failure in gdb.base/symbol-alias.exp testcase.
This testcase is also updated to test nested (recursive) alias.

Reviewed by: Bruno Larsen <blarsen@redhat.com>
---
 gdb/dwarf2/read.c                       | 74 +++++++++++++++++--------
 gdb/testsuite/gdb.base/symbol-alias.exp | 57 ++++++++++++++++++-
 gdb/testsuite/gdb.base/symbol-alias2.c  | 16 ++++++
 3 files changed, 121 insertions(+), 26 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index f9c942d91d3..6510dd94ac3 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -1132,6 +1132,10 @@ static void add_partial_subprogram (struct partial_die_info *pdi,
 				    CORE_ADDR *lowpc, CORE_ADDR *highpc,
 				    int need_pc, struct dwarf2_cu *cu);
 
+static void var_decode_location (struct attribute *attr,
+				 struct symbol *sym,
+				 struct dwarf2_cu *cu);
+
 static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);
 
 static struct partial_die_info *load_partial_dies
@@ -1332,7 +1336,7 @@ static struct using_direct **using_directives (struct dwarf2_cu *cu);
 
 static void read_import_statement (struct die_info *die, struct dwarf2_cu *);
 
-static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
+static bool read_alias (struct die_info *die, struct dwarf2_cu *cu);
 
 static struct type *read_module_type (struct die_info *die,
 				      struct dwarf2_cu *cu);
@@ -9741,10 +9745,14 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
       read_module (die, cu);
       break;
     case DW_TAG_imported_declaration:
+      /* If the imported declaration is for global variable alias,
+         this flag is set to false in read_alias function.  */
       cu->processing_has_namespace_info = true;
-      if (read_namespace_alias (die, cu))
+      if (((cu->per_cu->lang == language_c)
+	   || (cu->per_cu->lang == language_cplus))
+	  && read_alias (die, cu))
 	break;
-      /* The declaration is not a global namespace alias.  */
+      /* The declaration is not a global namespace or variable alias.  */
       /* Fall through.  */
     case DW_TAG_imported_module:
       cu->processing_has_namespace_info = true;
@@ -10212,18 +10220,20 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
   return retval;
 }
 
-/* Inspect DIE in CU for a namespace alias.  If one exists, record
-   a new symbol for it.
+#define MAX_NESTED_IMPORTED_DECLARATIONS 100
 
-   Returns 1 if a namespace alias was recorded, 0 otherwise.  */
+/* Inspect DIE in CU for a namespace alias or a variable
+   with alias attribute. If one exists, record a new symbol
+   for it.
 
-static int
-read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
+   Returns 1 if an alias was recorded, 0 otherwise.  */
+
+static bool
+read_alias (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct attribute *attr;
 
-  /* If the die does not have a name, this is not a namespace
-     alias.  */
+  /* The die must have a name for namespace or variable alias.  */
   attr = dwarf2_attr (die, DW_AT_name, cu);
   if (attr != NULL)
     {
@@ -10232,13 +10242,12 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
       struct dwarf2_cu *imported_cu = cu;
 
       /* If the compiler has nested DW_AT_imported_declaration DIEs,
-	 keep inspecting DIEs until we hit the underlying import.  */
-#define MAX_NESTED_IMPORTED_DECLARATIONS 100
+         keep inspecting DIEs until we hit the underlying import.  */
       for (num = 0; num  < MAX_NESTED_IMPORTED_DECLARATIONS; ++num)
 	{
 	  attr = dwarf2_attr (d, DW_AT_import, cu);
 	  if (attr == NULL)
-	    break;
+	    return false;
 
 	  d = follow_die_ref (d, attr, &imported_cu);
 	  if (d->tag != DW_TAG_imported_declaration)
@@ -10249,26 +10258,43 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
 	{
 	  complaint (_("DIE at %s has too many recursively imported "
 		       "declarations"), sect_offset_str (d->sect_off));
-	  return 0;
+	  return false;
 	}
 
       if (attr != NULL)
 	{
 	  struct type *type;
-	  sect_offset sect_off = attr->get_ref_die_offset ();
-
-	  type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
-	  if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+	  if (d->tag == DW_TAG_variable)
 	    {
-	      /* This declaration is a global namespace alias.  Add
-		 a symbol for it whose type is the aliased namespace.  */
-	      new_symbol (die, type, cu);
-	      return 1;
+	      /* This declaration is a global variable alias. Add
+		 a symbol for it whose type is same as aliased variable.  */
+	      type = die_type (d, imported_cu);
+	      struct symbol *sym = new_symbol(die, type, cu);
+	      attr = dwarf2_attr (d, DW_AT_location, imported_cu);
+	      sym->set_aclass_index (LOC_UNRESOLVED);
+	      if (attr != nullptr)
+		{
+		  var_decode_location (attr, sym, cu);
+		}
+	      /* Reset the flag as it is not a namespace alias.  */
+	      cu->processing_has_namespace_info = false;
+	      return true;
+	    }
+	  else
+	    {
+	      sect_offset sect_off = attr->get_ref_die_offset ();
+	      type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
+	      if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+		{
+		  /* This declaration is a global namespace alias. Add
+		     a symbol for it whose type is the aliased namespace.  */
+		  new_symbol (die, type, cu);
+		  return true;
+		}
 	    }
 	}
     }
-
-  return 0;
+  return false;
 }
 
 /* Return the using directives repository (global or local?) to use in the
diff --git a/gdb/testsuite/gdb.base/symbol-alias.exp b/gdb/testsuite/gdb.base/symbol-alias.exp
index 2b53cc31053..253a60d5403 100644
--- a/gdb/testsuite/gdb.base/symbol-alias.exp
+++ b/gdb/testsuite/gdb.base/symbol-alias.exp
@@ -15,6 +15,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 standard_testfile symbol-alias.c symbol-alias2.c
+set using_clang [test_compiler_info {clang-1[4-9]-*-*}]
 
 if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile $srcfile2]] } {
     return -1
@@ -31,6 +32,58 @@ foreach f {"func" "func_alias"} {
 }
 
 # Variables.
-foreach v {"g_var_s" "g_var_s_alias"} {
-    gdb_test "p $v" "= {field1 = 1, field2 = 2}"
+gdb_test "p g_var_s" "= {field1 = 1, field2 = 2}"
+foreach v {"g_var_s_alias" "g_var_s_alias2"} {
+    gdb_test_multiple "p $v" "p $v" {
+	-re  " = {field1 = 1, field2 = 2}.*$gdb_prompt $" {
+	    pass "print alias of variable $v"
+	}
+	-re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+	    if { ! $using_clang } {
+		xfail "print alias variable $v"
+	    } else {
+		fail "print alias variable $v"
+	    }
+	}
+    }
+}
+
+# Static Variable.
+gdb_test "p g_var" " = 1"
+gdb_test_multiple "p g_var_alias" "p g_var_alias" {
+    -re  " = 1.*$gdb_prompt $" {
+	pass "print alias of static variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+	if { ! $using_clang } {
+	  xfail "print alias of static variable"
+	} else {
+	  fail "print alias of static variable"
+	}
+    }
+}
+
+# Deferred Variable.
+gdb_test "p g_def_var" " = 2"
+gdb_test_multiple "p g_def_var_alias" "p g_def_var_alias" {
+    -re  " = 2.*$gdb_prompt $" {
+	pass "print alias of deferred variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+	xfail "print alias of deferred variable"
+    }
+}
+
+# Alias of deferred Variable alias.
+gdb_test_multiple "p g_def_var2_alias2" "p g_def_var2_alias2" {
+    -re  " = 3.*$gdb_prompt $" {
+	pass "print alias of alias of deferred variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+	if { ! $using_clang } {
+	  xfail "print alias of alias of deferred variable"
+	} else {
+	  fail "print alias of alias of deferred variable"
+	}
+    }
 }
diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c b/gdb/testsuite/gdb.base/symbol-alias2.c
index 34f4e121e25..41d4b6a53e5 100644
--- a/gdb/testsuite/gdb.base/symbol-alias2.c
+++ b/gdb/testsuite/gdb.base/symbol-alias2.c
@@ -23,6 +23,8 @@ struct S
 
 struct S g_var_s = { 1, 2 };
 
+static int g_var = 1;
+
 #ifdef __cplusplus
 /* So that the alias attribute below work without having to figure out
    this function's mangled name.  */
@@ -38,3 +40,17 @@ func (void)
 struct S *func_alias (void) __attribute__ ((alias ("func")));
 
 extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));
+
+extern struct S g_var_s_alias2 __attribute__ ((alias ("g_var_s_alias")));
+
+extern int g_var_alias __attribute__ ((alias ("g_var")));
+
+extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
+
+int g_def_var = 2;
+
+extern int g_def_var2_alias __attribute__ ((alias ("g_def_var2")));
+
+int g_def_var2 = 3;
+
+extern int g_def_var2_alias2 __attribute__ ((alias ("g_def_var2_alias")));
-- 
2.25.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] Debug support for global alias variable
  2022-03-28 15:14   ` Natarajan, Kavitha
@ 2022-03-29 14:02     ` Bruno Larsen
  2022-03-30 11:30       ` Natarajan, Kavitha
  0 siblings, 1 reply; 28+ messages in thread
From: Bruno Larsen @ 2022-03-29 14:02 UTC (permalink / raw)
  To: Natarajan, Kavitha, Natarajan, Kavitha via Gdb-patches
  Cc: George, Jini Susan, Parasuraman, Hariharan

Hello Kavitha,

Thanks for the quick reply

On 3/28/22 12:14, Natarajan, Kavitha wrote:
> [AMD Official Use Only]
> 
> Hello Bruno,
> 
> Thanks for reviewing the patch. It helps a lot. Along with my responses to your questions,
> I have also attached the new patch with the changes. Please review.

<snip>

>> <side note> why is this function returning 1 or 0 as boolean, instead of the
>> function returning bool?</side note>
> 
> The function shall return bool instead of int. Fixed in the new patch.
> 
>> Is this "else" path being exercised anywhere? For this simple code:
>>
>> namespace n{
>>       int i;
>>       int j;
>>       void f(){ }
>> }
>>
>> using n::i;
>> using n::f;
>>
>> int var;
>> extern int newvar __attribute__((alias("var")));
>>
>> int main(){
>>       i = 0;
>>       return 0;
>> }
>>
> 
> Imported declaration is emitted for namespace alias. If you declare as below
> in the above program:
> 
> namespace m = n;
> 
> Clang will generate,
> 
> <1><23>: Abbrev Number: 2 (DW_TAG_namespace)
>         <24>   DW_AT_name        : (indexed string: 0x3): n
> 
> [...]
> 
> <1><59>: Abbrev Number: 7 (DW_TAG_imported_declaration)
>         <5a>   DW_AT_decl_file   : 0
>         <5b>   DW_AT_decl_line   : 7
>         <5c>   DW_AT_import      : <0x23>   [Abbrev Number: 2 (DW_TAG_namespace)]
>         <60>   DW_AT_name        : (indexed string: 0xa): m
> 
> This is handled in the "else" path.

Ah, I didn't even know this was possible! Thanks for enlightening me.

> 
>>> --- a/gdb/testsuite/gdb.base/symbol-alias.exp
>>> +++ b/gdb/testsuite/gdb.base/symbol-alias.exp
> 
>> Since this is a new feature of clang and some tests run on quite old systems,
>> could you try and detect the clang version, so you can have xfails for all
>> aliases if the clang version doesn't emit this information?
> 
> Fixed. As of now, the clang version is checked for 14-0-0 and above. Can modify based on the version
> in which this fix goes in finally. It should give 5 XFAILs for clang versions without the fix and 1 XFAIL
> with the fix.
> I have also added one more test point when the location information is missing (g_def_var2_alias2).
> 
> ---------------
> When clang emits the dwarf information of global alias variable
> as DW_TAG_imported_declaration, gdb does not handle it. GDB reads
> this tag as C++/fortran imported declaration (type alias, namespace
> alias and fortran module). Added support to handle this tag as
> alias variable.
> 
> This change fixes the failure in gdb.base/symbol-alias.exp testcase.
> This testcase is also updated to test nested (recursive) alias.
> 
> Reviewed by: Bruno Larsen <blarsen@redhat.com>

GDB doesn't use R-b tags, I think. The latest one I could find was from 2007.

> ---
>   gdb/dwarf2/read.c                       | 74 +++++++++++++++++--------
>   gdb/testsuite/gdb.base/symbol-alias.exp | 57 ++++++++++++++++++-
>   gdb/testsuite/gdb.base/symbol-alias2.c  | 16 ++++++
>   3 files changed, 121 insertions(+), 26 deletions(-)
> 
> diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
> index f9c942d91d3..6510dd94ac3 100644
> --- a/gdb/dwarf2/read.c
> +++ b/gdb/dwarf2/read.c
> @@ -1132,6 +1132,10 @@ static void add_partial_subprogram (struct partial_die_info *pdi,
>                                      CORE_ADDR *lowpc, CORE_ADDR *highpc,
>                                      int need_pc, struct dwarf2_cu *cu);
> 
> +static void var_decode_location (struct attribute *attr,
> +                                struct symbol *sym,
> +                                struct dwarf2_cu *cu);
> +
>   static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);
> 
>   static struct partial_die_info *load_partial_dies
> @@ -1332,7 +1336,7 @@ static struct using_direct **using_directives (struct dwarf2_cu *cu);
> 
>   static void read_import_statement (struct die_info *die, struct dwarf2_cu *);
> 
> -static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
> +static bool read_alias (struct die_info *die, struct dwarf2_cu *cu);
> 
>   static struct type *read_module_type (struct die_info *die,
>                                        struct dwarf2_cu *cu);
> @@ -9741,10 +9745,14 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
>         read_module (die, cu);
>         break;
>       case DW_TAG_imported_declaration:
> +      /* If the imported declaration is for global variable alias,
> +         this flag is set to false in read_alias function.  */
>         cu->processing_has_namespace_info = true;
> -      if (read_namespace_alias (die, cu))
> +      if (((cu->per_cu->lang == language_c)
> +          || (cu->per_cu->lang == language_cplus))
> +         && read_alias (die, cu))
>          break;
> -      /* The declaration is not a global namespace alias.  */
> +      /* The declaration is not a global namespace or variable alias.  */
>         /* Fall through.  */
>       case DW_TAG_imported_module:
>         cu->processing_has_namespace_info = true;
> @@ -10212,18 +10220,20 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
>     return retval;
>   }
> 
> -/* Inspect DIE in CU for a namespace alias.  If one exists, record
> -   a new symbol for it.
> +#define MAX_NESTED_IMPORTED_DECLARATIONS 100
> 
> -   Returns 1 if a namespace alias was recorded, 0 otherwise.  */
> +/* Inspect DIE in CU for a namespace alias or a variable
> +   with alias attribute. If one exists, record a new symbol
> +   for it.
> 
> -static int
> -read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
> +   Returns 1 if an alias was recorded, 0 otherwise.  */

This comment needs to be updated, now that read_alias returns bool.

> +
> +static bool
> +read_alias (struct die_info *die, struct dwarf2_cu *cu)
>   {
>     struct attribute *attr;
> 
> -  /* If the die does not have a name, this is not a namespace
> -     alias.  */
> +  /* The die must have a name for namespace or variable alias.  */
>     attr = dwarf2_attr (die, DW_AT_name, cu);

Oops, I didn't catch this on my last review. DWARF 5 manual, section 3.2.3 Imported (or Renamed) Declaration Entries, says:

An imported declaration may also have a DW_AT_name attribute whose value is (...) If no name is present, then the name by which the entity is to be known is the same as the name of the entity being imported.

So I think the check and the comment are incorrect (or the spec needs updating). I know this isn't something you added, but since you are changing this function, I think it could be a good time to update this.

>     if (attr != NULL)
>       {
> @@ -10232,13 +10242,12 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
>         struct dwarf2_cu *imported_cu = cu;
> 
>         /* If the compiler has nested DW_AT_imported_declaration DIEs,
> -        keep inspecting DIEs until we hit the underlying import.  */
> -#define MAX_NESTED_IMPORTED_DECLARATIONS 100
> +         keep inspecting DIEs until we hit the underlying import.  */
>         for (num = 0; num  < MAX_NESTED_IMPORTED_DECLARATIONS; ++num)
>          {
>            attr = dwarf2_attr (d, DW_AT_import, cu);
>            if (attr == NULL)
> -           break;
> +           return false;
> 
>            d = follow_die_ref (d, attr, &imported_cu);
>            if (d->tag != DW_TAG_imported_declaration)
> @@ -10249,26 +10258,43 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
>          {
>            complaint (_("DIE at %s has too many recursively imported "
>                         "declarations"), sect_offset_str (d->sect_off));
> -         return 0;
> +         return false;
>          }
> 
>         if (attr != NULL)
>          {
>            struct type *type;
> -         sect_offset sect_off = attr->get_ref_die_offset ();
> -
> -         type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
> -         if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
> +         if (d->tag == DW_TAG_variable)
>              {
> -             /* This declaration is a global namespace alias.  Add
> -                a symbol for it whose type is the aliased namespace.  */
> -             new_symbol (die, type, cu);
> -             return 1;
> +             /* This declaration is a global variable alias. Add
> +                a symbol for it whose type is same as aliased variable.  */
> +             type = die_type (d, imported_cu);
> +             struct symbol *sym = new_symbol(die, type, cu);

Space before (

> +             attr = dwarf2_attr (d, DW_AT_location, imported_cu);
> +             sym->set_aclass_index (LOC_UNRESOLVED);
> +             if (attr != nullptr)
> +               {
> +                 var_decode_location (attr, sym, cu);
> +               }
> +             /* Reset the flag as it is not a namespace alias.  */
> +             cu->processing_has_namespace_info = false;
> +             return true;
> +           }
> +         else
> +           {
> +             sect_offset sect_off = attr->get_ref_die_offset ();
> +             type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
> +             if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
> +               {
> +                 /* This declaration is a global namespace alias. Add
> +                    a symbol for it whose type is the aliased namespace.  */
> +                 new_symbol (die, type, cu);
> +                 return true;
> +               }
>              }
>          }
>       }
> -
> -  return 0;
> +  return false;
>   }
> 
>   /* Return the using directives repository (global or local?) to use in the
> diff --git a/gdb/testsuite/gdb.base/symbol-alias.exp b/gdb/testsuite/gdb.base/symbol-alias.exp
> index 2b53cc31053..253a60d5403 100644
> --- a/gdb/testsuite/gdb.base/symbol-alias.exp
> +++ b/gdb/testsuite/gdb.base/symbol-alias.exp
> @@ -15,6 +15,7 @@
>   # along with this program.  If not, see <http://www.gnu.org/licenses/>.
> 
>   standard_testfile symbol-alias.c symbol-alias2.c
> +set using_clang [test_compiler_info {clang-1[4-9]-*-*}]

I think it would be better if you tested for a failing clang instead. Otherwise you can set an XFAIL for gcc, which could hide a real GDB bug (we don't do much testing with clang, unfortunately).

> 
>   if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile $srcfile2]] } {
>       return -1
> @@ -31,6 +32,58 @@ foreach f {"func" "func_alias"} {
>   }
> 
>   # Variables.
> -foreach v {"g_var_s" "g_var_s_alias"} {
> -    gdb_test "p $v" "= {field1 = 1, field2 = 2}"
> +gdb_test "p g_var_s" "= {field1 = 1, field2 = 2}"
> +foreach v {"g_var_s_alias" "g_var_s_alias2"} {
> +    gdb_test_multiple "p $v" "p $v" {
> +       -re  " = {field1 = 1, field2 = 2}.*$gdb_prompt $" {
> +           pass "print alias of variable $v"
> +       }
> +       -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
> +           if { ! $using_clang } {
> +               xfail "print alias variable $v"
> +           } else {
> +               fail "print alias variable $v"
> +           }
> +       }
> +    }
> +}
> +
> +# Static Variable.
> +gdb_test "p g_var" " = 1"
> +gdb_test_multiple "p g_var_alias" "p g_var_alias" {
> +    -re  " = 1.*$gdb_prompt $" {
> +       pass "print alias of static variable"
> +    }
> +    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
> +       if { ! $using_clang } {
> +         xfail "print alias of static variable"
> +       } else {
> +         fail "print alias of static variable"
> +       }
> +    }
> +}
> +
> +# Deferred Variable.
> +gdb_test "p g_def_var" " = 2"
> +gdb_test_multiple "p g_def_var_alias" "p g_def_var_alias" {
> +    -re  " = 2.*$gdb_prompt $" {
> +       pass "print alias of deferred variable"
> +    }
> +    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
> +       xfail "print alias of deferred variable"

Since GDB + GCC is passing this test, you should also set the xfail only with when using a failing clang.

> +    }
> +}
> +
> +# Alias of deferred Variable alias.
> +gdb_test_multiple "p g_def_var2_alias2" "p g_def_var2_alias2" {
> +    -re  " = 3.*$gdb_prompt $" {
> +       pass "print alias of alias of deferred variable"
> +    }
> +    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
> +       if { ! $using_clang } {
> +         xfail "print alias of alias of deferred variable"
> +       } else {
> +         fail "print alias of alias of deferred variable"
> +       }
> +    }
>   }
> diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c b/gdb/testsuite/gdb.base/symbol-alias2.c
> index 34f4e121e25..41d4b6a53e5 100644
> --- a/gdb/testsuite/gdb.base/symbol-alias2.c
> +++ b/gdb/testsuite/gdb.base/symbol-alias2.c
> @@ -23,6 +23,8 @@ struct S
> 
>   struct S g_var_s = { 1, 2 };
> 
> +static int g_var = 1;
> +
>   #ifdef __cplusplus
>   /* So that the alias attribute below work without having to figure out
>      this function's mangled name.  */
> @@ -38,3 +40,17 @@ func (void)
>   struct S *func_alias (void) __attribute__ ((alias ("func")));
> 
>   extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));
> +
> +extern struct S g_var_s_alias2 __attribute__ ((alias ("g_var_s_alias")));
> +
> +extern int g_var_alias __attribute__ ((alias ("g_var")));
> +
> +extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
> +
> +int g_def_var = 2;
> +
> +extern int g_def_var2_alias __attribute__ ((alias ("g_def_var2")));
> +
> +int g_def_var2 = 3;
> +
> +extern int g_def_var2_alias2 __attribute__ ((alias ("g_def_var2_alias")));
> --
> 
> Regards,
> Kavitha


-- 
Cheers!
Bruno Larsen


^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [PATCH] Debug support for global alias variable
  2022-03-29 14:02     ` Bruno Larsen
@ 2022-03-30 11:30       ` Natarajan, Kavitha
  2022-03-30 12:25         ` Natarajan, Kavitha
  0 siblings, 1 reply; 28+ messages in thread
From: Natarajan, Kavitha @ 2022-03-30 11:30 UTC (permalink / raw)
  To: Bruno Larsen, Natarajan, Kavitha via Gdb-patches
  Cc: George, Jini Susan, Parasuraman, Hariharan

[AMD Official Use Only]

Hello Bruno,

Thanks again for the quick review. I have fixed all your comments. I understand
that you are working on cleanup of gdb.base for clang testing. Now all older clang
versions would XFAIL while the existing FAILs would PASS for clang with this fix.

> > -  /* If the die does not have a name, this is not a namespace
> > -     alias.  */
> > +  /* The die must have a name for namespace or variable alias.  */
> >     attr = dwarf2_attr (die, DW_AT_name, cu);
>
> Oops, I didn't catch this on my last review. DWARF 5 manual, section 3.2.3
> Imported (or Renamed) Declaration Entries, says:
>
> An imported declaration may also have a DW_AT_name attribute whose
> value is (...) If no name is present, then the name by which the entity is to be
> known is the same as the name of the entity being imported.
>
> So I think the check and the comment are incorrect (or the spec needs
> updating). I know this isn't something you added, but since you are changing
> this function, I think it could be a good time to update this.

I have modified the comment. If no name is present, there is no need to create
a new symbol for the namespace or variable alias. So nothing to do in this function
and it returns false. The name of the imported entity is used in this case
("using" statements in your example).

Regards,
Kavitha

^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [PATCH] Debug support for global alias variable
  2022-03-30 11:30       ` Natarajan, Kavitha
@ 2022-03-30 12:25         ` Natarajan, Kavitha
  2022-04-05  6:26           ` Natarajan, Kavitha
                             ` (2 more replies)
  0 siblings, 3 replies; 28+ messages in thread
From: Natarajan, Kavitha @ 2022-03-30 12:25 UTC (permalink / raw)
  To: Bruno Larsen, Natarajan, Kavitha via Gdb-patches
  Cc: George, Jini Susan, Parasuraman, Hariharan

[-- Attachment #1: Type: text/plain, Size: 10497 bytes --]

[AMD Official Use Only]

Sorry, I missed to send the new patch. Please find it below:

---------------------------------------------------------------------
When clang emits the dwarf information of global alias variable
as DW_TAG_imported_declaration, gdb does not handle it. GDB reads
this tag as C++/fortran imported declaration (type alias, namespace
alias and fortran module). Added support to handle this tag as
alias variable.

This change fixes the failure in gdb.base/symbol-alias.exp testcase.
This testcase is also updated to test nested (recursive) alias.
---
 gdb/dwarf2/read.c                       | 75 +++++++++++++++++--------
 gdb/testsuite/gdb.base/symbol-alias.exp | 63 ++++++++++++++++++++-
 gdb/testsuite/gdb.base/symbol-alias2.c  | 16 ++++++
 3 files changed, 128 insertions(+), 26 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index f9c942d91d3..12d66378f79 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -1132,6 +1132,10 @@ static void add_partial_subprogram (struct partial_die_info *pdi,
                                    CORE_ADDR *lowpc, CORE_ADDR *highpc,
                                    int need_pc, struct dwarf2_cu *cu);

+static void var_decode_location (struct attribute *attr,
+                                struct symbol *sym,
+                                struct dwarf2_cu *cu);
+
 static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);

 static struct partial_die_info *load_partial_dies
@@ -1332,7 +1336,7 @@ static struct using_direct **using_directives (struct dwarf2_cu *cu);

 static void read_import_statement (struct die_info *die, struct dwarf2_cu *);

-static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
+static bool read_alias (struct die_info *die, struct dwarf2_cu *cu);

 static struct type *read_module_type (struct die_info *die,
                                      struct dwarf2_cu *cu);
@@ -9741,10 +9745,14 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
       read_module (die, cu);
       break;
     case DW_TAG_imported_declaration:
+      /* If the imported declaration is for global variable alias,
+         this flag is set to false in read_alias function.  */
       cu->processing_has_namespace_info = true;
-      if (read_namespace_alias (die, cu))
+      if (((cu->per_cu->lang == language_c)
+          || (cu->per_cu->lang == language_cplus))
+         && read_alias (die, cu))
        break;
-      /* The declaration is not a global namespace alias.  */
+      /* The declaration is not a global namespace or variable alias.  */
       /* Fall through.  */
     case DW_TAG_imported_module:
       cu->processing_has_namespace_info = true;
@@ -10212,18 +10220,21 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
   return retval;
 }

-/* Inspect DIE in CU for a namespace alias.  If one exists, record
-   a new symbol for it.
+#define MAX_NESTED_IMPORTED_DECLARATIONS 100

-   Returns 1 if a namespace alias was recorded, 0 otherwise.  */
+/* Inspect DIE in CU for a namespace alias or a variable
+   with alias attribute. If one exists, record a new symbol
+   for it.

-static int
-read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
+   Returns "true" if an alias was recorded, "false" otherwise.  */
+
+static bool
+read_alias (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct attribute *attr;

-  /* If the die does not have a name, this is not a namespace
-     alias.  */
+  /* If the die does not have a name, this is not a namespace alias
+     or variable alias.  */
   attr = dwarf2_attr (die, DW_AT_name, cu);
   if (attr != NULL)
     {
@@ -10232,13 +10243,12 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
       struct dwarf2_cu *imported_cu = cu;

       /* If the compiler has nested DW_AT_imported_declaration DIEs,
-        keep inspecting DIEs until we hit the underlying import.  */
-#define MAX_NESTED_IMPORTED_DECLARATIONS 100
+         keep inspecting DIEs until we hit the underlying import.  */
       for (num = 0; num  < MAX_NESTED_IMPORTED_DECLARATIONS; ++num)
        {
          attr = dwarf2_attr (d, DW_AT_import, cu);
          if (attr == NULL)
-           break;
+           return false;

          d = follow_die_ref (d, attr, &imported_cu);
          if (d->tag != DW_TAG_imported_declaration)
@@ -10249,26 +10259,43 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
        {
          complaint (_("DIE at %s has too many recursively imported "
                       "declarations"), sect_offset_str (d->sect_off));
-         return 0;
+         return false;
        }

       if (attr != NULL)
        {
          struct type *type;
-         sect_offset sect_off = attr->get_ref_die_offset ();
-
-         type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
-         if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+         if (d->tag == DW_TAG_variable)
            {
-             /* This declaration is a global namespace alias.  Add
-                a symbol for it whose type is the aliased namespace.  */
-             new_symbol (die, type, cu);
-             return 1;
+             /* This declaration is a global variable alias. Add
+                a symbol for it whose type is same as aliased variable.  */
+             type = die_type (d, imported_cu);
+             struct symbol *sym = new_symbol (die, type, cu);
+             attr = dwarf2_attr (d, DW_AT_location, imported_cu);
+             sym->set_aclass_index (LOC_UNRESOLVED);
+             if (attr != nullptr)
+               {
+                 var_decode_location (attr, sym, cu);
+               }
+             /* Reset the flag as it is not a namespace alias.  */
+             cu->processing_has_namespace_info = false;
+             return true;
+           }
+         else
+           {
+             sect_offset sect_off = attr->get_ref_die_offset ();
+             type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
+             if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+               {
+                 /* This declaration is a global namespace alias. Add
+                    a symbol for it whose type is the aliased namespace.  */
+                 new_symbol (die, type, cu);
+                 return true;
+               }
            }
        }
     }
-
-  return 0;
+  return false;
 }

 /* Return the using directives repository (global or local?) to use in the
diff --git a/gdb/testsuite/gdb.base/symbol-alias.exp b/gdb/testsuite/gdb.base/symbol-alias.exp
index 2b53cc31053..a9487b25f4d 100644
--- a/gdb/testsuite/gdb.base/symbol-alias.exp
+++ b/gdb/testsuite/gdb.base/symbol-alias.exp
@@ -15,6 +15,9 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.

 standard_testfile symbol-alias.c symbol-alias2.c
+set using_clang [test_compiler_info clang-*]
+set old_clang [expr [test_compiler_info {clang-1[0-3]-*-*}] \
+                || [test_compiler_info {clang-[1-9]-*}]]

 if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile $srcfile2]] } {
     return -1
@@ -31,6 +34,62 @@ foreach f {"func" "func_alias"} {
 }

 # Variables.
-foreach v {"g_var_s" "g_var_s_alias"} {
-    gdb_test "p $v" "= {field1 = 1, field2 = 2}"
+gdb_test "p g_var_s" "= {field1 = 1, field2 = 2}"
+foreach v {"g_var_s_alias" "g_var_s_alias2"} {
+    gdb_test_multiple "p $v" "p $v" {
+       -re  " = {field1 = 1, field2 = 2}.*$gdb_prompt $" {
+           pass "print alias of variable $v"
+       }
+       -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+           if { $old_clang } {
+               xfail "print alias variable $v"
+           } else {
+               fail "print alias variable $v"
+           }
+       }
+    }
+}
+
+# Static Variable.
+gdb_test "p g_var" " = 1"
+gdb_test_multiple "p g_var_alias" "p g_var_alias" {
+    -re  " = 1.*$gdb_prompt $" {
+       pass "print alias of static variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+       if { $old_clang } {
+         xfail "print alias of static variable"
+       } else {
+         fail "print alias of static variable"
+       }
+    }
+}
+
+# Deferred Variable.
+gdb_test "p g_def_var" " = 2"
+gdb_test_multiple "p g_def_var_alias" "p g_def_var_alias" {
+    -re  " = 2.*$gdb_prompt $" {
+       pass "print alias of deferred variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+       if { $using_clang } {
+         xfail "print alias of deferred variable"
+       } else {
+         fail "print alias of deferred variable"
+       }
+    }
+}
+
+# Alias of deferred Variable alias.
+gdb_test_multiple "p g_def_var2_alias2" "p g_def_var2_alias2" {
+    -re  " = 3.*$gdb_prompt $" {
+       pass "print alias of alias of deferred variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+       if { $old_clang } {
+         xfail "print alias of alias of deferred variable"
+       } else {
+         fail "print alias of alias of deferred variable"
+       }
+    }
 }
diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c b/gdb/testsuite/gdb.base/symbol-alias2.c
index 34f4e121e25..41d4b6a53e5 100644
--- a/gdb/testsuite/gdb.base/symbol-alias2.c
+++ b/gdb/testsuite/gdb.base/symbol-alias2.c
@@ -23,6 +23,8 @@ struct S

 struct S g_var_s = { 1, 2 };

+static int g_var = 1;
+
 #ifdef __cplusplus
 /* So that the alias attribute below work without having to figure out
    this function's mangled name.  */
@@ -38,3 +40,17 @@ func (void)
 struct S *func_alias (void) __attribute__ ((alias ("func")));

 extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));
+
+extern struct S g_var_s_alias2 __attribute__ ((alias ("g_var_s_alias")));
+
+extern int g_var_alias __attribute__ ((alias ("g_var")));
+
+extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
+
+int g_def_var = 2;
+
+extern int g_def_var2_alias __attribute__ ((alias ("g_def_var2")));
+
+int g_def_var2 = 3;
+
+extern int g_def_var2_alias2 __attribute__ ((alias ("g_def_var2_alias")));
--

Regards,
Kavitha

[-- Attachment #2: 0003-Debug-support-for-C-global-alias-variable-bruno.patch --]
[-- Type: application/octet-stream, Size: 9600 bytes --]

When clang emits the dwarf information of global alias variable
as DW_TAG_imported_declaration, gdb does not handle it. GDB reads
this tag as C++/fortran imported declaration (type alias, namespace
alias and fortran module). Added support to handle this tag as
alias variable.

This change fixes the failure in gdb.base/symbol-alias.exp testcase.
This testcase is also updated to test nested (recursive) alias.
---
 gdb/dwarf2/read.c                       | 75 +++++++++++++++++--------
 gdb/testsuite/gdb.base/symbol-alias.exp | 63 ++++++++++++++++++++-
 gdb/testsuite/gdb.base/symbol-alias2.c  | 16 ++++++
 3 files changed, 128 insertions(+), 26 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index f9c942d91d3..12d66378f79 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -1132,6 +1132,10 @@ static void add_partial_subprogram (struct partial_die_info *pdi,
 				    CORE_ADDR *lowpc, CORE_ADDR *highpc,
 				    int need_pc, struct dwarf2_cu *cu);
 
+static void var_decode_location (struct attribute *attr,
+				 struct symbol *sym,
+				 struct dwarf2_cu *cu);
+
 static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);
 
 static struct partial_die_info *load_partial_dies
@@ -1332,7 +1336,7 @@ static struct using_direct **using_directives (struct dwarf2_cu *cu);
 
 static void read_import_statement (struct die_info *die, struct dwarf2_cu *);
 
-static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
+static bool read_alias (struct die_info *die, struct dwarf2_cu *cu);
 
 static struct type *read_module_type (struct die_info *die,
 				      struct dwarf2_cu *cu);
@@ -9741,10 +9745,14 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
       read_module (die, cu);
       break;
     case DW_TAG_imported_declaration:
+      /* If the imported declaration is for global variable alias,
+         this flag is set to false in read_alias function.  */
       cu->processing_has_namespace_info = true;
-      if (read_namespace_alias (die, cu))
+      if (((cu->per_cu->lang == language_c)
+	   || (cu->per_cu->lang == language_cplus))
+	  && read_alias (die, cu))
 	break;
-      /* The declaration is not a global namespace alias.  */
+      /* The declaration is not a global namespace or variable alias.  */
       /* Fall through.  */
     case DW_TAG_imported_module:
       cu->processing_has_namespace_info = true;
@@ -10212,18 +10220,21 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
   return retval;
 }
 
-/* Inspect DIE in CU for a namespace alias.  If one exists, record
-   a new symbol for it.
+#define MAX_NESTED_IMPORTED_DECLARATIONS 100
 
-   Returns 1 if a namespace alias was recorded, 0 otherwise.  */
+/* Inspect DIE in CU for a namespace alias or a variable
+   with alias attribute. If one exists, record a new symbol
+   for it.
 
-static int
-read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
+   Returns "true" if an alias was recorded, "false" otherwise.  */
+
+static bool
+read_alias (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct attribute *attr;
 
-  /* If the die does not have a name, this is not a namespace
-     alias.  */
+  /* If the die does not have a name, this is not a namespace alias
+     or variable alias.  */
   attr = dwarf2_attr (die, DW_AT_name, cu);
   if (attr != NULL)
     {
@@ -10232,13 +10243,12 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
       struct dwarf2_cu *imported_cu = cu;
 
       /* If the compiler has nested DW_AT_imported_declaration DIEs,
-	 keep inspecting DIEs until we hit the underlying import.  */
-#define MAX_NESTED_IMPORTED_DECLARATIONS 100
+         keep inspecting DIEs until we hit the underlying import.  */
       for (num = 0; num  < MAX_NESTED_IMPORTED_DECLARATIONS; ++num)
 	{
 	  attr = dwarf2_attr (d, DW_AT_import, cu);
 	  if (attr == NULL)
-	    break;
+	    return false;
 
 	  d = follow_die_ref (d, attr, &imported_cu);
 	  if (d->tag != DW_TAG_imported_declaration)
@@ -10249,26 +10259,43 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
 	{
 	  complaint (_("DIE at %s has too many recursively imported "
 		       "declarations"), sect_offset_str (d->sect_off));
-	  return 0;
+	  return false;
 	}
 
       if (attr != NULL)
 	{
 	  struct type *type;
-	  sect_offset sect_off = attr->get_ref_die_offset ();
-
-	  type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
-	  if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+	  if (d->tag == DW_TAG_variable)
 	    {
-	      /* This declaration is a global namespace alias.  Add
-		 a symbol for it whose type is the aliased namespace.  */
-	      new_symbol (die, type, cu);
-	      return 1;
+	      /* This declaration is a global variable alias. Add
+		 a symbol for it whose type is same as aliased variable.  */
+	      type = die_type (d, imported_cu);
+	      struct symbol *sym = new_symbol (die, type, cu);
+	      attr = dwarf2_attr (d, DW_AT_location, imported_cu);
+	      sym->set_aclass_index (LOC_UNRESOLVED);
+	      if (attr != nullptr)
+		{
+		  var_decode_location (attr, sym, cu);
+		}
+	      /* Reset the flag as it is not a namespace alias.  */
+	      cu->processing_has_namespace_info = false;
+	      return true;
+	    }
+	  else
+	    {
+	      sect_offset sect_off = attr->get_ref_die_offset ();
+	      type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
+	      if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+		{
+		  /* This declaration is a global namespace alias. Add
+		     a symbol for it whose type is the aliased namespace.  */
+		  new_symbol (die, type, cu);
+		  return true;
+		}
 	    }
 	}
     }
-
-  return 0;
+  return false;
 }
 
 /* Return the using directives repository (global or local?) to use in the
diff --git a/gdb/testsuite/gdb.base/symbol-alias.exp b/gdb/testsuite/gdb.base/symbol-alias.exp
index 2b53cc31053..a9487b25f4d 100644
--- a/gdb/testsuite/gdb.base/symbol-alias.exp
+++ b/gdb/testsuite/gdb.base/symbol-alias.exp
@@ -15,6 +15,9 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 standard_testfile symbol-alias.c symbol-alias2.c
+set using_clang [test_compiler_info clang-*]
+set old_clang [expr [test_compiler_info {clang-1[0-3]-*-*}] \
+		 || [test_compiler_info {clang-[1-9]-*}]]
 
 if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile $srcfile2]] } {
     return -1
@@ -31,6 +34,62 @@ foreach f {"func" "func_alias"} {
 }
 
 # Variables.
-foreach v {"g_var_s" "g_var_s_alias"} {
-    gdb_test "p $v" "= {field1 = 1, field2 = 2}"
+gdb_test "p g_var_s" "= {field1 = 1, field2 = 2}"
+foreach v {"g_var_s_alias" "g_var_s_alias2"} {
+    gdb_test_multiple "p $v" "p $v" {
+	-re  " = {field1 = 1, field2 = 2}.*$gdb_prompt $" {
+	    pass "print alias of variable $v"
+	}
+	-re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+	    if { $old_clang } {
+		xfail "print alias variable $v"
+	    } else {
+		fail "print alias variable $v"
+	    }
+	}
+    }
+}
+
+# Static Variable.
+gdb_test "p g_var" " = 1"
+gdb_test_multiple "p g_var_alias" "p g_var_alias" {
+    -re  " = 1.*$gdb_prompt $" {
+	pass "print alias of static variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+	if { $old_clang } {
+	  xfail "print alias of static variable"
+	} else {
+	  fail "print alias of static variable"
+	}
+    }
+}
+
+# Deferred Variable.
+gdb_test "p g_def_var" " = 2"
+gdb_test_multiple "p g_def_var_alias" "p g_def_var_alias" {
+    -re  " = 2.*$gdb_prompt $" {
+	pass "print alias of deferred variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+	if { $using_clang } {
+	  xfail "print alias of deferred variable"
+	} else {
+	  fail "print alias of deferred variable"
+	}
+    }
+}
+
+# Alias of deferred Variable alias.
+gdb_test_multiple "p g_def_var2_alias2" "p g_def_var2_alias2" {
+    -re  " = 3.*$gdb_prompt $" {
+	pass "print alias of alias of deferred variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+	if { $old_clang } {
+	  xfail "print alias of alias of deferred variable"
+	} else {
+	  fail "print alias of alias of deferred variable"
+	}
+    }
 }
diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c b/gdb/testsuite/gdb.base/symbol-alias2.c
index 34f4e121e25..41d4b6a53e5 100644
--- a/gdb/testsuite/gdb.base/symbol-alias2.c
+++ b/gdb/testsuite/gdb.base/symbol-alias2.c
@@ -23,6 +23,8 @@ struct S
 
 struct S g_var_s = { 1, 2 };
 
+static int g_var = 1;
+
 #ifdef __cplusplus
 /* So that the alias attribute below work without having to figure out
    this function's mangled name.  */
@@ -38,3 +40,17 @@ func (void)
 struct S *func_alias (void) __attribute__ ((alias ("func")));
 
 extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));
+
+extern struct S g_var_s_alias2 __attribute__ ((alias ("g_var_s_alias")));
+
+extern int g_var_alias __attribute__ ((alias ("g_var")));
+
+extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
+
+int g_def_var = 2;
+
+extern int g_def_var2_alias __attribute__ ((alias ("g_def_var2")));
+
+int g_def_var2 = 3;
+
+extern int g_def_var2_alias2 __attribute__ ((alias ("g_def_var2_alias")));
-- 
2.25.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [PATCH] Debug support for global alias variable
  2022-03-30 12:25         ` Natarajan, Kavitha
@ 2022-04-05  6:26           ` Natarajan, Kavitha
  2022-04-05 13:33           ` Bruno Larsen
  2022-04-15 16:06           ` Tom Tromey
  2 siblings, 0 replies; 28+ messages in thread
From: Natarajan, Kavitha @ 2022-04-05  6:26 UTC (permalink / raw)
  To: Bruno Larsen, Natarajan, Kavitha via Gdb-patches
  Cc: George, Jini Susan, Parasuraman, Hariharan

[AMD Official Use Only]

Hi Bruno,

Can you please review the changes that you suggested?

It would be much appreciated if you or someone from gdb community approve the patch
if everything is fine. It will help in progressing the clang patch that generate these debug
information for alias variable.

Thanks,
Kavitha

> -----Original Message-----
> From: Natarajan, Kavitha
> Sent: Wednesday, March 30, 2022 5:56 PM
> To: 'Bruno Larsen' <blarsen@redhat.com>; 'Natarajan, Kavitha via Gdb-
> patches' <gdb-patches@sourceware.org>
> Cc: George, Jini Susan <JiniSusan.George@amd.com>; Parasuraman,
> Hariharan <Hariharan.Parasuraman@amd.com>
> Subject: RE: [PATCH] Debug support for global alias variable
>
> Sorry, I missed to send the new patch. Please find it below:
>
> ---------------------------------------------------------------------
> When clang emits the dwarf information of global alias variable as
> DW_TAG_imported_declaration, gdb does not handle it. GDB reads this tag
> as C++/fortran imported declaration (type alias, namespace alias and fortran
> module). Added support to handle this tag as alias variable.
>
> This change fixes the failure in gdb.base/symbol-alias.exp testcase.
> This testcase is also updated to test nested (recursive) alias.
> ---
>  gdb/dwarf2/read.c                       | 75 +++++++++++++++++--------
>  gdb/testsuite/gdb.base/symbol-alias.exp | 63 ++++++++++++++++++++-
> gdb/testsuite/gdb.base/symbol-alias2.c  | 16 ++++++
>  3 files changed, 128 insertions(+), 26 deletions(-)
>
> diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index
> f9c942d91d3..12d66378f79 100644
> --- a/gdb/dwarf2/read.c
> +++ b/gdb/dwarf2/read.c
> @@ -1132,6 +1132,10 @@ static void add_partial_subprogram (struct
> partial_die_info *pdi,
>                                   CORE_ADDR *lowpc, CORE_ADDR *highpc,
>                                   int need_pc, struct dwarf2_cu *cu);
>
> +static void var_decode_location (struct attribute *attr,
> +                              struct symbol *sym,
> +                              struct dwarf2_cu *cu);
> +
>  static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);
>
>  static struct partial_die_info *load_partial_dies @@ -1332,7 +1336,7 @@
> static struct using_direct **using_directives (struct dwarf2_cu *cu);
>
>  static void read_import_statement (struct die_info *die, struct dwarf2_cu
> *);
>
> -static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
> +static bool read_alias (struct die_info *die, struct dwarf2_cu *cu);
>
>  static struct type *read_module_type (struct die_info *die,
>                                     struct dwarf2_cu *cu);
> @@ -9741,10 +9745,14 @@ process_die (struct die_info *die, struct
> dwarf2_cu *cu)
>        read_module (die, cu);
>        break;
>      case DW_TAG_imported_declaration:
> +      /* If the imported declaration is for global variable alias,
> +         this flag is set to false in read_alias function.  */
>        cu->processing_has_namespace_info = true;
> -      if (read_namespace_alias (die, cu))
> +      if (((cu->per_cu->lang == language_c)
> +        || (cu->per_cu->lang == language_cplus))
> +       && read_alias (die, cu))
>       break;
> -      /* The declaration is not a global namespace alias.  */
> +      /* The declaration is not a global namespace or variable alias.
> + */
>        /* Fall through.  */
>      case DW_TAG_imported_module:
>        cu->processing_has_namespace_info = true; @@ -10212,18 +10220,21
> @@ dwarf2_physname (const char *name, struct die_info *die, struct
> dwarf2_cu *cu)
>    return retval;
>  }
>
> -/* Inspect DIE in CU for a namespace alias.  If one exists, record
> -   a new symbol for it.
> +#define MAX_NESTED_IMPORTED_DECLARATIONS 100
>
> -   Returns 1 if a namespace alias was recorded, 0 otherwise.  */
> +/* Inspect DIE in CU for a namespace alias or a variable
> +   with alias attribute. If one exists, record a new symbol
> +   for it.
>
> -static int
> -read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
> +   Returns "true" if an alias was recorded, "false" otherwise.  */
> +
> +static bool
> +read_alias (struct die_info *die, struct dwarf2_cu *cu)
>  {
>    struct attribute *attr;
>
> -  /* If the die does not have a name, this is not a namespace
> -     alias.  */
> +  /* If the die does not have a name, this is not a namespace alias
> +     or variable alias.  */
>    attr = dwarf2_attr (die, DW_AT_name, cu);
>    if (attr != NULL)
>      {
> @@ -10232,13 +10243,12 @@ read_namespace_alias (struct die_info *die,
> struct dwarf2_cu *cu)
>        struct dwarf2_cu *imported_cu = cu;
>
>        /* If the compiler has nested DW_AT_imported_declaration DIEs,
> -      keep inspecting DIEs until we hit the underlying import.  */
> -#define MAX_NESTED_IMPORTED_DECLARATIONS 100
> +         keep inspecting DIEs until we hit the underlying import.  */
>        for (num = 0; num  < MAX_NESTED_IMPORTED_DECLARATIONS; ++num)
>       {
>         attr = dwarf2_attr (d, DW_AT_import, cu);
>         if (attr == NULL)
> -         break;
> +         return false;
>
>         d = follow_die_ref (d, attr, &imported_cu);
>         if (d->tag != DW_TAG_imported_declaration) @@ -10249,26
> +10259,43 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu
> *cu)
>       {
>         complaint (_("DIE at %s has too many recursively imported "
>                      "declarations"), sect_offset_str (d->sect_off));
> -       return 0;
> +       return false;
>       }
>
>        if (attr != NULL)
>       {
>         struct type *type;
> -       sect_offset sect_off = attr->get_ref_die_offset ();
> -
> -       type = get_die_type_at_offset (sect_off, cu->per_cu, cu-
> >per_objfile);
> -       if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
> +       if (d->tag == DW_TAG_variable)
>           {
> -           /* This declaration is a global namespace alias.  Add
> -              a symbol for it whose type is the aliased namespace.  */
> -           new_symbol (die, type, cu);
> -           return 1;
> +           /* This declaration is a global variable alias. Add
> +              a symbol for it whose type is same as aliased variable.  */
> +           type = die_type (d, imported_cu);
> +           struct symbol *sym = new_symbol (die, type, cu);
> +           attr = dwarf2_attr (d, DW_AT_location, imported_cu);
> +           sym->set_aclass_index (LOC_UNRESOLVED);
> +           if (attr != nullptr)
> +             {
> +               var_decode_location (attr, sym, cu);
> +             }
> +           /* Reset the flag as it is not a namespace alias.  */
> +           cu->processing_has_namespace_info = false;
> +           return true;
> +         }
> +       else
> +         {
> +           sect_offset sect_off = attr->get_ref_die_offset ();
> +           type = get_die_type_at_offset (sect_off, cu->per_cu, cu-
> >per_objfile);
> +           if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
> +             {
> +               /* This declaration is a global namespace alias. Add
> +                  a symbol for it whose type is the aliased namespace.  */
> +               new_symbol (die, type, cu);
> +               return true;
> +             }
>           }
>       }
>      }
> -
> -  return 0;
> +  return false;
>  }
>
>  /* Return the using directives repository (global or local?) to use in the diff --
> git a/gdb/testsuite/gdb.base/symbol-alias.exp
> b/gdb/testsuite/gdb.base/symbol-alias.exp
> index 2b53cc31053..a9487b25f4d 100644
> --- a/gdb/testsuite/gdb.base/symbol-alias.exp
> +++ b/gdb/testsuite/gdb.base/symbol-alias.exp
> @@ -15,6 +15,9 @@
>  # along with this program.  If not, see <http://www.gnu.org/licenses/>.
>
>  standard_testfile symbol-alias.c symbol-alias2.c
> +set using_clang [test_compiler_info clang-*] set old_clang [expr
> +[test_compiler_info {clang-1[0-3]-*-*}] \
> +              || [test_compiler_info {clang-[1-9]-*}]]
>
>  if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile $srcfile2]]
> } {
>      return -1
> @@ -31,6 +34,62 @@ foreach f {"func" "func_alias"} {  }
>
>  # Variables.
> -foreach v {"g_var_s" "g_var_s_alias"} {
> -    gdb_test "p $v" "= {field1 = 1, field2 = 2}"
> +gdb_test "p g_var_s" "= {field1 = 1, field2 = 2}"
> +foreach v {"g_var_s_alias" "g_var_s_alias2"} {
> +    gdb_test_multiple "p $v" "p $v" {
> +     -re  " = {field1 = 1, field2 = 2}.*$gdb_prompt $" {
> +         pass "print alias of variable $v"
> +     }
> +     -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt
> $" {
> +         if { $old_clang } {
> +             xfail "print alias variable $v"
> +         } else {
> +             fail "print alias variable $v"
> +         }
> +     }
> +    }
> +}
> +
> +# Static Variable.
> +gdb_test "p g_var" " = 1"
> +gdb_test_multiple "p g_var_alias" "p g_var_alias" {
> +    -re  " = 1.*$gdb_prompt $" {
> +     pass "print alias of static variable"
> +    }
> +    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
> +     if { $old_clang } {
> +       xfail "print alias of static variable"
> +     } else {
> +       fail "print alias of static variable"
> +     }
> +    }
> +}
> +
> +# Deferred Variable.
> +gdb_test "p g_def_var" " = 2"
> +gdb_test_multiple "p g_def_var_alias" "p g_def_var_alias" {
> +    -re  " = 2.*$gdb_prompt $" {
> +     pass "print alias of deferred variable"
> +    }
> +    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
> +     if { $using_clang } {
> +       xfail "print alias of deferred variable"
> +     } else {
> +       fail "print alias of deferred variable"
> +     }
> +    }
> +}
> +
> +# Alias of deferred Variable alias.
> +gdb_test_multiple "p g_def_var2_alias2" "p g_def_var2_alias2" {
> +    -re  " = 3.*$gdb_prompt $" {
> +     pass "print alias of alias of deferred variable"
> +    }
> +    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
> +     if { $old_clang } {
> +       xfail "print alias of alias of deferred variable"
> +     } else {
> +       fail "print alias of alias of deferred variable"
> +     }
> +    }
>  }
> diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c
> b/gdb/testsuite/gdb.base/symbol-alias2.c
> index 34f4e121e25..41d4b6a53e5 100644
> --- a/gdb/testsuite/gdb.base/symbol-alias2.c
> +++ b/gdb/testsuite/gdb.base/symbol-alias2.c
> @@ -23,6 +23,8 @@ struct S
>
>  struct S g_var_s = { 1, 2 };
>
> +static int g_var = 1;
> +
>  #ifdef __cplusplus
>  /* So that the alias attribute below work without having to figure out
>     this function's mangled name.  */
> @@ -38,3 +40,17 @@ func (void)
>  struct S *func_alias (void) __attribute__ ((alias ("func")));
>
>  extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));
> +
> +extern struct S g_var_s_alias2 __attribute__ ((alias
> +("g_var_s_alias")));
> +
> +extern int g_var_alias __attribute__ ((alias ("g_var")));
> +
> +extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
> +
> +int g_def_var = 2;
> +
> +extern int g_def_var2_alias __attribute__ ((alias ("g_def_var2")));
> +
> +int g_def_var2 = 3;
> +
> +extern int g_def_var2_alias2 __attribute__ ((alias
> +("g_def_var2_alias")));
> --
>
> Regards,
> Kavitha

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] Debug support for global alias variable
  2022-03-30 12:25         ` Natarajan, Kavitha
  2022-04-05  6:26           ` Natarajan, Kavitha
@ 2022-04-05 13:33           ` Bruno Larsen
  2022-04-05 14:02             ` Natarajan, Kavitha
  2022-04-12  8:38             ` Natarajan, Kavitha
  2022-04-15 16:06           ` Tom Tromey
  2 siblings, 2 replies; 28+ messages in thread
From: Bruno Larsen @ 2022-04-05 13:33 UTC (permalink / raw)
  To: Natarajan, Kavitha, Natarajan, Kavitha via Gdb-patches
  Cc: George, Jini Susan, Parasuraman, Hariharan

On 3/30/22 09:25, Natarajan, Kavitha wrote:
> [AMD Official Use Only]
> 
> Sorry, I missed to send the new patch. Please find it below:

Sorry for the delay on the response.

I only noticed one small nit in a comment. Like I said before, can't approve for pushing, but it LGTM.

> 
> ---------------------------------------------------------------------
> When clang emits the dwarf information of global alias variable
> as DW_TAG_imported_declaration, gdb does not handle it. GDB reads
> this tag as C++/fortran imported declaration (type alias, namespace
> alias and fortran module). Added support to handle this tag as
> alias variable.
> 
> This change fixes the failure in gdb.base/symbol-alias.exp testcase.
> This testcase is also updated to test nested (recursive) alias.
> ---
>   gdb/dwarf2/read.c                       | 75 +++++++++++++++++--------
>   gdb/testsuite/gdb.base/symbol-alias.exp | 63 ++++++++++++++++++++-
>   gdb/testsuite/gdb.base/symbol-alias2.c  | 16 ++++++
>   3 files changed, 128 insertions(+), 26 deletions(-)
> 
> diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
> index f9c942d91d3..12d66378f79 100644
> --- a/gdb/dwarf2/read.c
> +++ b/gdb/dwarf2/read.c
> @@ -1132,6 +1132,10 @@ static void add_partial_subprogram (struct partial_die_info *pdi,
>                                      CORE_ADDR *lowpc, CORE_ADDR *highpc,
>                                      int need_pc, struct dwarf2_cu *cu);
> 
> +static void var_decode_location (struct attribute *attr,
> +                                struct symbol *sym,
> +                                struct dwarf2_cu *cu);
> +
>   static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);
> 
>   static struct partial_die_info *load_partial_dies
> @@ -1332,7 +1336,7 @@ static struct using_direct **using_directives (struct dwarf2_cu *cu);
> 
>   static void read_import_statement (struct die_info *die, struct dwarf2_cu *);
> 
> -static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
> +static bool read_alias (struct die_info *die, struct dwarf2_cu *cu);
> 
>   static struct type *read_module_type (struct die_info *die,
>                                        struct dwarf2_cu *cu);
> @@ -9741,10 +9745,14 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
>         read_module (die, cu);
>         break;
>       case DW_TAG_imported_declaration:
> +      /* If the imported declaration is for global variable alias,
> +         this flag is set to false in read_alias function.  */
>         cu->processing_has_namespace_info = true;
> -      if (read_namespace_alias (die, cu))
> +      if (((cu->per_cu->lang == language_c)
> +          || (cu->per_cu->lang == language_cplus))
> +         && read_alias (die, cu))
>          break;
> -      /* The declaration is not a global namespace alias.  */
> +      /* The declaration is not a global namespace or variable alias.  */
>         /* Fall through.  */
>       case DW_TAG_imported_module:
>         cu->processing_has_namespace_info = true;
> @@ -10212,18 +10220,21 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
>     return retval;
>   }
> 
> -/* Inspect DIE in CU for a namespace alias.  If one exists, record
> -   a new symbol for it.
> +#define MAX_NESTED_IMPORTED_DECLARATIONS 100
> 
> -   Returns 1 if a namespace alias was recorded, 0 otherwise.  */
> +/* Inspect DIE in CU for a namespace alias or a variable
> +   with alias attribute. If one exists, record a new symbol
> +   for it.
> 
> -static int
> -read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
> +   Returns "true" if an alias was recorded, "false" otherwise.  */
> +
> +static bool
> +read_alias (struct die_info *die, struct dwarf2_cu *cu)
>   {
>     struct attribute *attr;
> 
> -  /* If the die does not have a name, this is not a namespace
> -     alias.  */
> +  /* If the die does not have a name, this is not a namespace alias
> +     or variable alias.  */
>     attr = dwarf2_attr (die, DW_AT_name, cu);
>     if (attr != NULL)
>       {
> @@ -10232,13 +10243,12 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
>         struct dwarf2_cu *imported_cu = cu;
> 
>         /* If the compiler has nested DW_AT_imported_declaration DIEs,
> -        keep inspecting DIEs until we hit the underlying import.  */
> -#define MAX_NESTED_IMPORTED_DECLARATIONS 100
> +         keep inspecting DIEs until we hit the underlying import.  */

This comment still has 8 spaces instead of a tab. You must have missed it on your pass.

>         for (num = 0; num  < MAX_NESTED_IMPORTED_DECLARATIONS; ++num)
>          {
>            attr = dwarf2_attr (d, DW_AT_import, cu);
>            if (attr == NULL)
> -           break;
> +           return false;
> 
>            d = follow_die_ref (d, attr, &imported_cu);
>            if (d->tag != DW_TAG_imported_declaration)
> @@ -10249,26 +10259,43 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
>          {
>            complaint (_("DIE at %s has too many recursively imported "
>                         "declarations"), sect_offset_str (d->sect_off));
> -         return 0;
> +         return false;
>          }
> 
>         if (attr != NULL)
>          {
>            struct type *type;
> -         sect_offset sect_off = attr->get_ref_die_offset ();
> -
> -         type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
> -         if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
> +         if (d->tag == DW_TAG_variable)
>              {
> -             /* This declaration is a global namespace alias.  Add
> -                a symbol for it whose type is the aliased namespace.  */
> -             new_symbol (die, type, cu);
> -             return 1;
> +             /* This declaration is a global variable alias. Add
> +                a symbol for it whose type is same as aliased variable.  */
> +             type = die_type (d, imported_cu);
> +             struct symbol *sym = new_symbol (die, type, cu);
> +             attr = dwarf2_attr (d, DW_AT_location, imported_cu);
> +             sym->set_aclass_index (LOC_UNRESOLVED);
> +             if (attr != nullptr)
> +               {
> +                 var_decode_location (attr, sym, cu);
> +               }
> +             /* Reset the flag as it is not a namespace alias.  */
> +             cu->processing_has_namespace_info = false;
> +             return true;
> +           }
> +         else
> +           {
> +             sect_offset sect_off = attr->get_ref_die_offset ();
> +             type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
> +             if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
> +               {
> +                 /* This declaration is a global namespace alias. Add
> +                    a symbol for it whose type is the aliased namespace.  */
> +                 new_symbol (die, type, cu);
> +                 return true;
> +               }
>              }
>          }
>       }
> -
> -  return 0;
> +  return false;
>   }
> 
>   /* Return the using directives repository (global or local?) to use in the
> diff --git a/gdb/testsuite/gdb.base/symbol-alias.exp b/gdb/testsuite/gdb.base/symbol-alias.exp
> index 2b53cc31053..a9487b25f4d 100644
> --- a/gdb/testsuite/gdb.base/symbol-alias.exp
> +++ b/gdb/testsuite/gdb.base/symbol-alias.exp
> @@ -15,6 +15,9 @@
>   # along with this program.  If not, see <http://www.gnu.org/licenses/>.
> 
>   standard_testfile symbol-alias.c symbol-alias2.c
> +set using_clang [test_compiler_info clang-*]
> +set old_clang [expr [test_compiler_info {clang-1[0-3]-*-*}] \
> +                || [test_compiler_info {clang-[1-9]-*}]]
> 
>   if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile $srcfile2]] } {
>       return -1
> @@ -31,6 +34,62 @@ foreach f {"func" "func_alias"} {
>   }
> 
>   # Variables.
> -foreach v {"g_var_s" "g_var_s_alias"} {
> -    gdb_test "p $v" "= {field1 = 1, field2 = 2}"
> +gdb_test "p g_var_s" "= {field1 = 1, field2 = 2}"
> +foreach v {"g_var_s_alias" "g_var_s_alias2"} {
> +    gdb_test_multiple "p $v" "p $v" {
> +       -re  " = {field1 = 1, field2 = 2}.*$gdb_prompt $" {
> +           pass "print alias of variable $v"
> +       }
> +       -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
> +           if { $old_clang } {
> +               xfail "print alias variable $v"
> +           } else {
> +               fail "print alias variable $v"
> +           }
> +       }
> +    }
> +}
> +
> +# Static Variable.
> +gdb_test "p g_var" " = 1"
> +gdb_test_multiple "p g_var_alias" "p g_var_alias" {
> +    -re  " = 1.*$gdb_prompt $" {
> +       pass "print alias of static variable"
> +    }
> +    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
> +       if { $old_clang } {
> +         xfail "print alias of static variable"
> +       } else {
> +         fail "print alias of static variable"
> +       }
> +    }
> +}
> +
> +# Deferred Variable.
> +gdb_test "p g_def_var" " = 2"
> +gdb_test_multiple "p g_def_var_alias" "p g_def_var_alias" {
> +    -re  " = 2.*$gdb_prompt $" {
> +       pass "print alias of deferred variable"
> +    }
> +    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
> +       if { $using_clang } {
> +         xfail "print alias of deferred variable"
> +       } else {
> +         fail "print alias of deferred variable"
> +       }
> +    }
> +}
> +
> +# Alias of deferred Variable alias.
> +gdb_test_multiple "p g_def_var2_alias2" "p g_def_var2_alias2" {
> +    -re  " = 3.*$gdb_prompt $" {
> +       pass "print alias of alias of deferred variable"
> +    }
> +    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
> +       if { $old_clang } {
> +         xfail "print alias of alias of deferred variable"
> +       } else {
> +         fail "print alias of alias of deferred variable"
> +       }
> +    }
>   }
> diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c b/gdb/testsuite/gdb.base/symbol-alias2.c
> index 34f4e121e25..41d4b6a53e5 100644
> --- a/gdb/testsuite/gdb.base/symbol-alias2.c
> +++ b/gdb/testsuite/gdb.base/symbol-alias2.c
> @@ -23,6 +23,8 @@ struct S
> 
>   struct S g_var_s = { 1, 2 };
> 
> +static int g_var = 1;
> +
>   #ifdef __cplusplus
>   /* So that the alias attribute below work without having to figure out
>      this function's mangled name.  */
> @@ -38,3 +40,17 @@ func (void)
>   struct S *func_alias (void) __attribute__ ((alias ("func")));
> 
>   extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));
> +
> +extern struct S g_var_s_alias2 __attribute__ ((alias ("g_var_s_alias")));
> +
> +extern int g_var_alias __attribute__ ((alias ("g_var")));
> +
> +extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
> +
> +int g_def_var = 2;
> +
> +extern int g_def_var2_alias __attribute__ ((alias ("g_def_var2")));
> +
> +int g_def_var2 = 3;
> +
> +extern int g_def_var2_alias2 __attribute__ ((alias ("g_def_var2_alias")));
> --
> 
> Regards,
> Kavitha


-- 
Cheers!
Bruno Larsen


^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [PATCH] Debug support for global alias variable
  2022-04-05 13:33           ` Bruno Larsen
@ 2022-04-05 14:02             ` Natarajan, Kavitha
  2022-04-12  8:38             ` Natarajan, Kavitha
  1 sibling, 0 replies; 28+ messages in thread
From: Natarajan, Kavitha @ 2022-04-05 14:02 UTC (permalink / raw)
  To: Bruno Larsen, Natarajan, Kavitha via Gdb-patches
  Cc: George, Jini Susan, Parasuraman, Hariharan

[AMD Official Use Only]

Sorry for my oversight on the spaces. I fixed it.

Thank you so much @Bruno Larsen for taking time to review the patch. Looking for someone to approve the patch.

Regards,
Kavitha

> -----Original Message-----
> From: Bruno Larsen <blarsen@redhat.com>
> Sent: Tuesday, April 5, 2022 7:03 PM
> To: Natarajan, Kavitha <Kavitha.Natarajan@amd.com>; Natarajan, Kavitha
> via Gdb-patches <gdb-patches@sourceware.org>
> Cc: George, Jini Susan <JiniSusan.George@amd.com>; Parasuraman,
> Hariharan <Hariharan.Parasuraman@amd.com>
> Subject: Re: [PATCH] Debug support for global alias variable
>
> [CAUTION: External Email]
>
> On 3/30/22 09:25, Natarajan, Kavitha wrote:
> > [AMD Official Use Only]
> >
> > Sorry, I missed to send the new patch. Please find it below:
>
> Sorry for the delay on the response.
>
> I only noticed one small nit in a comment. Like I said before, can't approve for
> pushing, but it LGTM.
>
> >
> > ---------------------------------------------------------------------
> > When clang emits the dwarf information of global alias variable as
> > DW_TAG_imported_declaration, gdb does not handle it. GDB reads this
> > tag as C++/fortran imported declaration (type alias, namespace alias
> > and fortran module). Added support to handle this tag as alias
> > variable.
> >
> > This change fixes the failure in gdb.base/symbol-alias.exp testcase.
> > This testcase is also updated to test nested (recursive) alias.
> > ---
> >   gdb/dwarf2/read.c                       | 75 +++++++++++++++++--------
> >   gdb/testsuite/gdb.base/symbol-alias.exp | 63 ++++++++++++++++++++-
> >   gdb/testsuite/gdb.base/symbol-alias2.c  | 16 ++++++
> >   3 files changed, 128 insertions(+), 26 deletions(-)
> >
> > diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index
> > f9c942d91d3..12d66378f79 100644
> > --- a/gdb/dwarf2/read.c
> > +++ b/gdb/dwarf2/read.c
> > @@ -1132,6 +1132,10 @@ static void add_partial_subprogram (struct
> partial_die_info *pdi,
> >                                      CORE_ADDR *lowpc, CORE_ADDR *highpc,
> >                                      int need_pc, struct dwarf2_cu
> > *cu);
> >
> > +static void var_decode_location (struct attribute *attr,
> > +                                struct symbol *sym,
> > +                                struct dwarf2_cu *cu);
> > +
> >   static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);
> >
> >   static struct partial_die_info *load_partial_dies @@ -1332,7 +1336,7
> > @@ static struct using_direct **using_directives (struct dwarf2_cu
> > *cu);
> >
> >   static void read_import_statement (struct die_info *die, struct
> > dwarf2_cu *);
> >
> > -static int read_namespace_alias (struct die_info *die, struct
> > dwarf2_cu *cu);
> > +static bool read_alias (struct die_info *die, struct dwarf2_cu *cu);
> >
> >   static struct type *read_module_type (struct die_info *die,
> >                                        struct dwarf2_cu *cu); @@
> > -9741,10 +9745,14 @@ process_die (struct die_info *die, struct dwarf2_cu
> *cu)
> >         read_module (die, cu);
> >         break;
> >       case DW_TAG_imported_declaration:
> > +      /* If the imported declaration is for global variable alias,
> > +         this flag is set to false in read_alias function.  */
> >         cu->processing_has_namespace_info = true;
> > -      if (read_namespace_alias (die, cu))
> > +      if (((cu->per_cu->lang == language_c)
> > +          || (cu->per_cu->lang == language_cplus))
> > +         && read_alias (die, cu))
> >          break;
> > -      /* The declaration is not a global namespace alias.  */
> > +      /* The declaration is not a global namespace or variable alias.
> > + */
> >         /* Fall through.  */
> >       case DW_TAG_imported_module:
> >         cu->processing_has_namespace_info = true; @@ -10212,18
> > +10220,21 @@ dwarf2_physname (const char *name, struct die_info *die,
> struct dwarf2_cu *cu)
> >     return retval;
> >   }
> >
> > -/* Inspect DIE in CU for a namespace alias.  If one exists, record
> > -   a new symbol for it.
> > +#define MAX_NESTED_IMPORTED_DECLARATIONS 100
> >
> > -   Returns 1 if a namespace alias was recorded, 0 otherwise.  */
> > +/* Inspect DIE in CU for a namespace alias or a variable
> > +   with alias attribute. If one exists, record a new symbol
> > +   for it.
> >
> > -static int
> > -read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
> > +   Returns "true" if an alias was recorded, "false" otherwise.  */
> > +
> > +static bool
> > +read_alias (struct die_info *die, struct dwarf2_cu *cu)
> >   {
> >     struct attribute *attr;
> >
> > -  /* If the die does not have a name, this is not a namespace
> > -     alias.  */
> > +  /* If the die does not have a name, this is not a namespace alias
> > +     or variable alias.  */
> >     attr = dwarf2_attr (die, DW_AT_name, cu);
> >     if (attr != NULL)
> >       {
> > @@ -10232,13 +10243,12 @@ read_namespace_alias (struct die_info *die,
> struct dwarf2_cu *cu)
> >         struct dwarf2_cu *imported_cu = cu;
> >
> >         /* If the compiler has nested DW_AT_imported_declaration DIEs,
> > -        keep inspecting DIEs until we hit the underlying import.  */
> > -#define MAX_NESTED_IMPORTED_DECLARATIONS 100
> > +         keep inspecting DIEs until we hit the underlying import.  */
>
> This comment still has 8 spaces instead of a tab. You must have missed it on
> your pass.
>
> >         for (num = 0; num  < MAX_NESTED_IMPORTED_DECLARATIONS;
> ++num)
> >          {
> >            attr = dwarf2_attr (d, DW_AT_import, cu);
> >            if (attr == NULL)
> > -           break;
> > +           return false;
> >
> >            d = follow_die_ref (d, attr, &imported_cu);
> >            if (d->tag != DW_TAG_imported_declaration) @@ -10249,26
> > +10259,43 @@ read_namespace_alias (struct die_info *die, struct
> dwarf2_cu *cu)
> >          {
> >            complaint (_("DIE at %s has too many recursively imported "
> >                         "declarations"), sect_offset_str (d->sect_off));
> > -         return 0;
> > +         return false;
> >          }
> >
> >         if (attr != NULL)
> >          {
> >            struct type *type;
> > -         sect_offset sect_off = attr->get_ref_die_offset ();
> > -
> > -         type = get_die_type_at_offset (sect_off, cu->per_cu, cu-
> >per_objfile);
> > -         if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
> > +         if (d->tag == DW_TAG_variable)
> >              {
> > -             /* This declaration is a global namespace alias.  Add
> > -                a symbol for it whose type is the aliased namespace.  */
> > -             new_symbol (die, type, cu);
> > -             return 1;
> > +             /* This declaration is a global variable alias. Add
> > +                a symbol for it whose type is same as aliased variable.  */
> > +             type = die_type (d, imported_cu);
> > +             struct symbol *sym = new_symbol (die, type, cu);
> > +             attr = dwarf2_attr (d, DW_AT_location, imported_cu);
> > +             sym->set_aclass_index (LOC_UNRESOLVED);
> > +             if (attr != nullptr)
> > +               {
> > +                 var_decode_location (attr, sym, cu);
> > +               }
> > +             /* Reset the flag as it is not a namespace alias.  */
> > +             cu->processing_has_namespace_info = false;
> > +             return true;
> > +           }
> > +         else
> > +           {
> > +             sect_offset sect_off = attr->get_ref_die_offset ();
> > +             type = get_die_type_at_offset (sect_off, cu->per_cu, cu-
> >per_objfile);
> > +             if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
> > +               {
> > +                 /* This declaration is a global namespace alias. Add
> > +                    a symbol for it whose type is the aliased namespace.  */
> > +                 new_symbol (die, type, cu);
> > +                 return true;
> > +               }
> >              }
> >          }
> >       }
> > -
> > -  return 0;
> > +  return false;
> >   }
> >
> >   /* Return the using directives repository (global or local?) to use
> > in the diff --git a/gdb/testsuite/gdb.base/symbol-alias.exp
> > b/gdb/testsuite/gdb.base/symbol-alias.exp
> > index 2b53cc31053..a9487b25f4d 100644
> > --- a/gdb/testsuite/gdb.base/symbol-alias.exp
> > +++ b/gdb/testsuite/gdb.base/symbol-alias.exp
> > @@ -15,6 +15,9 @@
> >   # along with this program.  If not, see
> <https://nam11.safelinks.protection.outlook.com/?url=http%3A%2F%2Fww
> w.gnu.org%2Flicenses%2F&amp;data=04%7C01%7Ckavitha.natarajan%40am
> d.com%7Cee7adda17f644c3ff44c08da1708d555%7C3dd8961fe4884e608e11a8
> 2d994e183d%7C0%7C0%7C637847623963520029%7CUnknown%7CTWFpbGZs
> b3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn
> 0%3D%7C3000&amp;sdata=BiRp7rTFWbGY0AMXSmyy02d5uZwi4P52GJEjiRkb
> g0E%3D&amp;reserved=0>.
> >
> >   standard_testfile symbol-alias.c symbol-alias2.c
> > +set using_clang [test_compiler_info clang-*] set old_clang [expr
> > +[test_compiler_info {clang-1[0-3]-*-*}] \
> > +                || [test_compiler_info {clang-[1-9]-*}]]
> >
> >   if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile
> $srcfile2]] } {
> >       return -1
> > @@ -31,6 +34,62 @@ foreach f {"func" "func_alias"} {
> >   }
> >
> >   # Variables.
> > -foreach v {"g_var_s" "g_var_s_alias"} {
> > -    gdb_test "p $v" "= {field1 = 1, field2 = 2}"
> > +gdb_test "p g_var_s" "= {field1 = 1, field2 = 2}"
> > +foreach v {"g_var_s_alias" "g_var_s_alias2"} {
> > +    gdb_test_multiple "p $v" "p $v" {
> > +       -re  " = {field1 = 1, field2 = 2}.*$gdb_prompt $" {
> > +           pass "print alias of variable $v"
> > +       }
> > +       -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $"
> {
> > +           if { $old_clang } {
> > +               xfail "print alias variable $v"
> > +           } else {
> > +               fail "print alias variable $v"
> > +           }
> > +       }
> > +    }
> > +}
> > +
> > +# Static Variable.
> > +gdb_test "p g_var" " = 1"
> > +gdb_test_multiple "p g_var_alias" "p g_var_alias" {
> > +    -re  " = 1.*$gdb_prompt $" {
> > +       pass "print alias of static variable"
> > +    }
> > +    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
> > +       if { $old_clang } {
> > +         xfail "print alias of static variable"
> > +       } else {
> > +         fail "print alias of static variable"
> > +       }
> > +    }
> > +}
> > +
> > +# Deferred Variable.
> > +gdb_test "p g_def_var" " = 2"
> > +gdb_test_multiple "p g_def_var_alias" "p g_def_var_alias" {
> > +    -re  " = 2.*$gdb_prompt $" {
> > +       pass "print alias of deferred variable"
> > +    }
> > +    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
> > +       if { $using_clang } {
> > +         xfail "print alias of deferred variable"
> > +       } else {
> > +         fail "print alias of deferred variable"
> > +       }
> > +    }
> > +}
> > +
> > +# Alias of deferred Variable alias.
> > +gdb_test_multiple "p g_def_var2_alias2" "p g_def_var2_alias2" {
> > +    -re  " = 3.*$gdb_prompt $" {
> > +       pass "print alias of alias of deferred variable"
> > +    }
> > +    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
> > +       if { $old_clang } {
> > +         xfail "print alias of alias of deferred variable"
> > +       } else {
> > +         fail "print alias of alias of deferred variable"
> > +       }
> > +    }
> >   }
> > diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c
> > b/gdb/testsuite/gdb.base/symbol-alias2.c
> > index 34f4e121e25..41d4b6a53e5 100644
> > --- a/gdb/testsuite/gdb.base/symbol-alias2.c
> > +++ b/gdb/testsuite/gdb.base/symbol-alias2.c
> > @@ -23,6 +23,8 @@ struct S
> >
> >   struct S g_var_s = { 1, 2 };
> >
> > +static int g_var = 1;
> > +
> >   #ifdef __cplusplus
> >   /* So that the alias attribute below work without having to figure out
> >      this function's mangled name.  */ @@ -38,3 +40,17 @@ func (void)
> >   struct S *func_alias (void) __attribute__ ((alias ("func")));
> >
> >   extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));
> > +
> > +extern struct S g_var_s_alias2 __attribute__ ((alias
> > +("g_var_s_alias")));
> > +
> > +extern int g_var_alias __attribute__ ((alias ("g_var")));
> > +
> > +extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
> > +
> > +int g_def_var = 2;
> > +
> > +extern int g_def_var2_alias __attribute__ ((alias ("g_def_var2")));
> > +
> > +int g_def_var2 = 3;
> > +
> > +extern int g_def_var2_alias2 __attribute__ ((alias
> > +("g_def_var2_alias")));
> > --
> >
> > Regards,
> > Kavitha
>
>
> --
> Cheers!
> Bruno Larsen


^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [PATCH] Debug support for global alias variable
  2022-04-05 13:33           ` Bruno Larsen
  2022-04-05 14:02             ` Natarajan, Kavitha
@ 2022-04-12  8:38             ` Natarajan, Kavitha
  1 sibling, 0 replies; 28+ messages in thread
From: Natarajan, Kavitha @ 2022-04-12  8:38 UTC (permalink / raw)
  To: Bruno Larsen, Natarajan, Kavitha via Gdb-patches
  Cc: George, Jini Susan, Parasuraman, Hariharan

[AMD Official Use Only]

The clang patch that generate the dwarf debug info for global alias variable is
committed to https://github.com/llvm/llvm-project

==============================================================
commit b1ea0191a42074341847d767609f66a26b6d5a41
Author: Kavitha Natarajan <kavitha.natarajan@amd.com>
Date:   Mon Mar 7 12:45:52 2022 +0530

    [clang][DebugInfo] Support debug info for alias variable

    clang to emit DWARF information for global alias variable as
    DW_TAG_imported_declaration. This change also handles nested
    (recursive) imported declarations.

    Reviewed by: dblaikie, aprantl

    Differential Revision: https://reviews.llvm.org/D120989
==============================================================

The clang trunk should be generating DIE for alias variable as DW_ AT_imported_declaration.

Awaiting approval for gdb patch.

Thanks,
Kavitha

> -----Original Message-----
> From: Bruno Larsen <blarsen@redhat.com>
> Sent: Tuesday, April 5, 2022 7:03 PM
> To: Natarajan, Kavitha <Kavitha.Natarajan@amd.com>; Natarajan, Kavitha
> via Gdb-patches <gdb-patches@sourceware.org>
> Cc: George, Jini Susan <JiniSusan.George@amd.com>; Parasuraman,
> Hariharan <Hariharan.Parasuraman@amd.com>
> Subject: Re: [PATCH] Debug support for global alias variable
>
> [CAUTION: External Email]
>
> On 3/30/22 09:25, Natarajan, Kavitha wrote:
> > [AMD Official Use Only]
> >
> > Sorry, I missed to send the new patch. Please find it below:
>
> Sorry for the delay on the response.
>
> I only noticed one small nit in a comment. Like I said before, can't approve for
> pushing, but it LGTM.
>
> >
> > ---------------------------------------------------------------------
> > When clang emits the dwarf information of global alias variable as
> > DW_TAG_imported_declaration, gdb does not handle it. GDB reads this
> > tag as C++/fortran imported declaration (type alias, namespace alias
> > and fortran module). Added support to handle this tag as alias
> > variable.
> >
> > This change fixes the failure in gdb.base/symbol-alias.exp testcase.
> > This testcase is also updated to test nested (recursive) alias.
> > ---
> >   gdb/dwarf2/read.c                       | 75 +++++++++++++++++--------
> >   gdb/testsuite/gdb.base/symbol-alias.exp | 63 ++++++++++++++++++++-
> >   gdb/testsuite/gdb.base/symbol-alias2.c  | 16 ++++++
> >   3 files changed, 128 insertions(+), 26 deletions(-)
> >
> > diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index
> > f9c942d91d3..12d66378f79 100644
> > --- a/gdb/dwarf2/read.c
> > +++ b/gdb/dwarf2/read.c
> > @@ -1132,6 +1132,10 @@ static void add_partial_subprogram (struct
> partial_die_info *pdi,
> >                                      CORE_ADDR *lowpc, CORE_ADDR *highpc,
> >                                      int need_pc, struct dwarf2_cu
> > *cu);
> >
> > +static void var_decode_location (struct attribute *attr,
> > +                                struct symbol *sym,
> > +                                struct dwarf2_cu *cu);
> > +
> >   static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);
> >
> >   static struct partial_die_info *load_partial_dies @@ -1332,7 +1336,7
> > @@ static struct using_direct **using_directives (struct dwarf2_cu
> > *cu);
> >
> >   static void read_import_statement (struct die_info *die, struct
> > dwarf2_cu *);
> >
> > -static int read_namespace_alias (struct die_info *die, struct
> > dwarf2_cu *cu);
> > +static bool read_alias (struct die_info *die, struct dwarf2_cu *cu);
> >
> >   static struct type *read_module_type (struct die_info *die,
> >                                        struct dwarf2_cu *cu); @@
> > -9741,10 +9745,14 @@ process_die (struct die_info *die, struct dwarf2_cu
> *cu)
> >         read_module (die, cu);
> >         break;
> >       case DW_TAG_imported_declaration:
> > +      /* If the imported declaration is for global variable alias,
> > +         this flag is set to false in read_alias function.  */
> >         cu->processing_has_namespace_info = true;
> > -      if (read_namespace_alias (die, cu))
> > +      if (((cu->per_cu->lang == language_c)
> > +          || (cu->per_cu->lang == language_cplus))
> > +         && read_alias (die, cu))
> >          break;
> > -      /* The declaration is not a global namespace alias.  */
> > +      /* The declaration is not a global namespace or variable alias.
> > + */
> >         /* Fall through.  */
> >       case DW_TAG_imported_module:
> >         cu->processing_has_namespace_info = true; @@ -10212,18
> > +10220,21 @@ dwarf2_physname (const char *name, struct die_info *die,
> struct dwarf2_cu *cu)
> >     return retval;
> >   }
> >
> > -/* Inspect DIE in CU for a namespace alias.  If one exists, record
> > -   a new symbol for it.
> > +#define MAX_NESTED_IMPORTED_DECLARATIONS 100
> >
> > -   Returns 1 if a namespace alias was recorded, 0 otherwise.  */
> > +/* Inspect DIE in CU for a namespace alias or a variable
> > +   with alias attribute. If one exists, record a new symbol
> > +   for it.
> >
> > -static int
> > -read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
> > +   Returns "true" if an alias was recorded, "false" otherwise.  */
> > +
> > +static bool
> > +read_alias (struct die_info *die, struct dwarf2_cu *cu)
> >   {
> >     struct attribute *attr;
> >
> > -  /* If the die does not have a name, this is not a namespace
> > -     alias.  */
> > +  /* If the die does not have a name, this is not a namespace alias
> > +     or variable alias.  */
> >     attr = dwarf2_attr (die, DW_AT_name, cu);
> >     if (attr != NULL)
> >       {
> > @@ -10232,13 +10243,12 @@ read_namespace_alias (struct die_info *die,
> struct dwarf2_cu *cu)
> >         struct dwarf2_cu *imported_cu = cu;
> >
> >         /* If the compiler has nested DW_AT_imported_declaration DIEs,
> > -        keep inspecting DIEs until we hit the underlying import.  */
> > -#define MAX_NESTED_IMPORTED_DECLARATIONS 100
> > +         keep inspecting DIEs until we hit the underlying import.  */
>
> This comment still has 8 spaces instead of a tab. You must have missed it on
> your pass.
>
> >         for (num = 0; num  < MAX_NESTED_IMPORTED_DECLARATIONS;
> ++num)
> >          {
> >            attr = dwarf2_attr (d, DW_AT_import, cu);
> >            if (attr == NULL)
> > -           break;
> > +           return false;
> >
> >            d = follow_die_ref (d, attr, &imported_cu);
> >            if (d->tag != DW_TAG_imported_declaration) @@ -10249,26
> > +10259,43 @@ read_namespace_alias (struct die_info *die, struct
> dwarf2_cu *cu)
> >          {
> >            complaint (_("DIE at %s has too many recursively imported "
> >                         "declarations"), sect_offset_str (d->sect_off));
> > -         return 0;
> > +         return false;
> >          }
> >
> >         if (attr != NULL)
> >          {
> >            struct type *type;
> > -         sect_offset sect_off = attr->get_ref_die_offset ();
> > -
> > -         type = get_die_type_at_offset (sect_off, cu->per_cu, cu-
> >per_objfile);
> > -         if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
> > +         if (d->tag == DW_TAG_variable)
> >              {
> > -             /* This declaration is a global namespace alias.  Add
> > -                a symbol for it whose type is the aliased namespace.  */
> > -             new_symbol (die, type, cu);
> > -             return 1;
> > +             /* This declaration is a global variable alias. Add
> > +                a symbol for it whose type is same as aliased variable.  */
> > +             type = die_type (d, imported_cu);
> > +             struct symbol *sym = new_symbol (die, type, cu);
> > +             attr = dwarf2_attr (d, DW_AT_location, imported_cu);
> > +             sym->set_aclass_index (LOC_UNRESOLVED);
> > +             if (attr != nullptr)
> > +               {
> > +                 var_decode_location (attr, sym, cu);
> > +               }
> > +             /* Reset the flag as it is not a namespace alias.  */
> > +             cu->processing_has_namespace_info = false;
> > +             return true;
> > +           }
> > +         else
> > +           {
> > +             sect_offset sect_off = attr->get_ref_die_offset ();
> > +             type = get_die_type_at_offset (sect_off, cu->per_cu, cu-
> >per_objfile);
> > +             if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
> > +               {
> > +                 /* This declaration is a global namespace alias. Add
> > +                    a symbol for it whose type is the aliased namespace.  */
> > +                 new_symbol (die, type, cu);
> > +                 return true;
> > +               }
> >              }
> >          }
> >       }
> > -
> > -  return 0;
> > +  return false;
> >   }
> >
> >   /* Return the using directives repository (global or local?) to use
> > in the diff --git a/gdb/testsuite/gdb.base/symbol-alias.exp
> > b/gdb/testsuite/gdb.base/symbol-alias.exp
> > index 2b53cc31053..a9487b25f4d 100644
> > --- a/gdb/testsuite/gdb.base/symbol-alias.exp
> > +++ b/gdb/testsuite/gdb.base/symbol-alias.exp
> > @@ -15,6 +15,9 @@
> >   # along with this program.  If not, see
> <https://nam11.safelinks.protection.outlook.com/?url=http%3A%2F%2Fww
> w.gnu.org%2Flicenses%2F&amp;data=04%7C01%7Ckavitha.natarajan%40am
> d.com%7Cee7adda17f644c3ff44c08da1708d555%7C3dd8961fe4884e608e11a8
> 2d994e183d%7C0%7C0%7C637847623963520029%7CUnknown%7CTWFpbGZs
> b3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn
> 0%3D%7C3000&amp;sdata=BiRp7rTFWbGY0AMXSmyy02d5uZwi4P52GJEjiRkb
> g0E%3D&amp;reserved=0>.
> >
> >   standard_testfile symbol-alias.c symbol-alias2.c
> > +set using_clang [test_compiler_info clang-*] set old_clang [expr
> > +[test_compiler_info {clang-1[0-3]-*-*}] \
> > +                || [test_compiler_info {clang-[1-9]-*}]]
> >
> >   if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile
> $srcfile2]] } {
> >       return -1
> > @@ -31,6 +34,62 @@ foreach f {"func" "func_alias"} {
> >   }
> >
> >   # Variables.
> > -foreach v {"g_var_s" "g_var_s_alias"} {
> > -    gdb_test "p $v" "= {field1 = 1, field2 = 2}"
> > +gdb_test "p g_var_s" "= {field1 = 1, field2 = 2}"
> > +foreach v {"g_var_s_alias" "g_var_s_alias2"} {
> > +    gdb_test_multiple "p $v" "p $v" {
> > +       -re  " = {field1 = 1, field2 = 2}.*$gdb_prompt $" {
> > +           pass "print alias of variable $v"
> > +       }
> > +       -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $"
> {
> > +           if { $old_clang } {
> > +               xfail "print alias variable $v"
> > +           } else {
> > +               fail "print alias variable $v"
> > +           }
> > +       }
> > +    }
> > +}
> > +
> > +# Static Variable.
> > +gdb_test "p g_var" " = 1"
> > +gdb_test_multiple "p g_var_alias" "p g_var_alias" {
> > +    -re  " = 1.*$gdb_prompt $" {
> > +       pass "print alias of static variable"
> > +    }
> > +    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
> > +       if { $old_clang } {
> > +         xfail "print alias of static variable"
> > +       } else {
> > +         fail "print alias of static variable"
> > +       }
> > +    }
> > +}
> > +
> > +# Deferred Variable.
> > +gdb_test "p g_def_var" " = 2"
> > +gdb_test_multiple "p g_def_var_alias" "p g_def_var_alias" {
> > +    -re  " = 2.*$gdb_prompt $" {
> > +       pass "print alias of deferred variable"
> > +    }
> > +    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
> > +       if { $using_clang } {
> > +         xfail "print alias of deferred variable"
> > +       } else {
> > +         fail "print alias of deferred variable"
> > +       }
> > +    }
> > +}
> > +
> > +# Alias of deferred Variable alias.
> > +gdb_test_multiple "p g_def_var2_alias2" "p g_def_var2_alias2" {
> > +    -re  " = 3.*$gdb_prompt $" {
> > +       pass "print alias of alias of deferred variable"
> > +    }
> > +    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
> > +       if { $old_clang } {
> > +         xfail "print alias of alias of deferred variable"
> > +       } else {
> > +         fail "print alias of alias of deferred variable"
> > +       }
> > +    }
> >   }
> > diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c
> > b/gdb/testsuite/gdb.base/symbol-alias2.c
> > index 34f4e121e25..41d4b6a53e5 100644
> > --- a/gdb/testsuite/gdb.base/symbol-alias2.c
> > +++ b/gdb/testsuite/gdb.base/symbol-alias2.c
> > @@ -23,6 +23,8 @@ struct S
> >
> >   struct S g_var_s = { 1, 2 };
> >
> > +static int g_var = 1;
> > +
> >   #ifdef __cplusplus
> >   /* So that the alias attribute below work without having to figure out
> >      this function's mangled name.  */ @@ -38,3 +40,17 @@ func (void)
> >   struct S *func_alias (void) __attribute__ ((alias ("func")));
> >
> >   extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));
> > +
> > +extern struct S g_var_s_alias2 __attribute__ ((alias
> > +("g_var_s_alias")));
> > +
> > +extern int g_var_alias __attribute__ ((alias ("g_var")));
> > +
> > +extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
> > +
> > +int g_def_var = 2;
> > +
> > +extern int g_def_var2_alias __attribute__ ((alias ("g_def_var2")));
> > +
> > +int g_def_var2 = 3;
> > +
> > +extern int g_def_var2_alias2 __attribute__ ((alias
> > +("g_def_var2_alias")));
> > --
> >
> > Regards,
> > Kavitha
>
>
> --
> Cheers!
> Bruno Larsen


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] Debug support for global alias variable
  2022-03-30 12:25         ` Natarajan, Kavitha
  2022-04-05  6:26           ` Natarajan, Kavitha
  2022-04-05 13:33           ` Bruno Larsen
@ 2022-04-15 16:06           ` Tom Tromey
  2022-04-18 11:04             ` Natarajan, Kavitha
  2 siblings, 1 reply; 28+ messages in thread
From: Tom Tromey @ 2022-04-15 16:06 UTC (permalink / raw)
  To: Natarajan, Kavitha via Gdb-patches
  Cc: Bruno Larsen, Natarajan, Kavitha, George, Jini Susan,
	Parasuraman, Hariharan

>>>>> Natarajan, Kavitha via Gdb-patches <gdb-patches@sourceware.org> writes:

> When clang emits the dwarf information of global alias variable
> as DW_TAG_imported_declaration, gdb does not handle it. GDB reads
> this tag as C++/fortran imported declaration (type alias, namespace
> alias and fortran module). Added support to handle this tag as
> alias variable.

Thank you for the patch.

> +      if (((cu->per_cu->lang == language_c)
> +          || (cu->per_cu->lang == language_cplus))

This expression is over-parenthesized.
The inner parens can be removed.

However, I don't understand why this would necessarily be specific to C
or C++.  The old read_namespace_alias wasn't, so doesn't this check
possibly regress for some other language?

> +#define MAX_NESTED_IMPORTED_DECLARATIONS 100

There doesn't seem to be a need to move this.

>        /* If the compiler has nested DW_AT_imported_declaration DIEs,
> -        keep inspecting DIEs until we hit the underlying import.  */
> -#define MAX_NESTED_IMPORTED_DECLARATIONS 100
> +         keep inspecting DIEs until we hit the underlying import.  */

This is an unnecessary change to the indentation.
I think gdb uses tabs, so it's also incorrect.

>        for (num = 0; num  < MAX_NESTED_IMPORTED_DECLARATIONS; ++num)
>         {
>           attr = dwarf2_attr (d, DW_AT_import, cu);
>           if (attr == NULL)
> -           break;
> +           return false;

This change doesn't seem to be needed.

> +             /* This declaration is a global variable alias. Add
> +                a symbol for it whose type is same as aliased variable.  */
> +             type = die_type (d, imported_cu);
> +             struct symbol *sym = new_symbol (die, type, cu);
> +             attr = dwarf2_attr (d, DW_AT_location, imported_cu);
> +             sym->set_aclass_index (LOC_UNRESOLVED);
> +             if (attr != nullptr)
> +               {
> +                 var_decode_location (attr, sym, cu);
> +               }

This is over-braced.

> +             /* Reset the flag as it is not a namespace alias.  */
> +             cu->processing_has_namespace_info = false;

This variable is super weird.  Once it is set to true, it is never
changed back.  In fact, setting it to false here probably will introduce
bugs.

I wonder if processing_has_namespace_info can just be removed.  cu.h
makes it sound extremely obsolete:

  /* When true, the file that we're processing is known to have
     debugging info for C++ namespaces.  GCC 3.3.x did not produce
     this information, but later versions do.  */

Anyway, I think you should just remove this line and the comment
referring to it.

Tom

^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [PATCH] Debug support for global alias variable
  2022-04-15 16:06           ` Tom Tromey
@ 2022-04-18 11:04             ` Natarajan, Kavitha
  2022-04-18 15:03               ` Tom Tromey
  0 siblings, 1 reply; 28+ messages in thread
From: Natarajan, Kavitha @ 2022-04-18 11:04 UTC (permalink / raw)
  To: Tom Tromey, Natarajan, Kavitha via Gdb-patches
  Cc: Bruno Larsen, George, Jini Susan, Parasuraman, Hariharan

[-- Attachment #1: Type: text/plain, Size: 10049 bytes --]

[AMD Official Use Only]

Thank you Tom for reviewing my patch. I am sending the updated patch.

> > +      if (((cu->per_cu->lang == language_c)
> > +          || (cu->per_cu->lang == language_cplus))
>
> This expression is over-parenthesized.
> The inner parens can be removed.
>
> However, I don't understand why this would necessarily be specific to C or
> C++.  The old read_namespace_alias wasn't, so doesn't this check possibly
> regress for some other language?

There doesn't seem to be any impact on other languages as the new symbol is
created only for TYPE_CODE_NAMESPACE in read_namespace_alias function.
However, it could regress with my change. So I have moved this check specific
to my change so that this change is specific to C/C++ global alias variables.

Thanks,
Kavitha
==============================================================
When clang emits the dwarf information of global alias variable
as DW_TAG_imported_declaration, gdb does not handle it. GDB reads
this tag as C++/fortran imported declaration (type alias, namespace
alias and fortran module). Added support to handle this tag as
alias variable.

This change fixes the failure in gdb.base/symbol-alias.exp testcase.
This testcase is also updated to test nested (recursive) alias.
---
 gdb/dwarf2/read.c                       | 62 +++++++++++++++---------
 gdb/testsuite/gdb.base/symbol-alias.exp | 63 ++++++++++++++++++++++++-
 gdb/testsuite/gdb.base/symbol-alias2.c  | 16 +++++++
 3 files changed, 118 insertions(+), 23 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 6dcd446e5f4..b0eed600312 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -957,6 +957,10 @@ static void build_type_psymtabs_reader (cutu_reader *reader,

 static void dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile);

+static void var_decode_location (struct attribute *attr,
+                                struct symbol *sym,
+                                struct dwarf2_cu *cu);
+
 static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);

 static const gdb_byte *read_attribute (const struct die_reader_specs *,
@@ -1134,7 +1138,7 @@ static struct using_direct **using_directives (struct dwarf2_cu *cu);

 static void read_import_statement (struct die_info *die, struct dwarf2_cu *);

-static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
+static bool read_alias (struct die_info *die, struct dwarf2_cu *cu);

 static struct type *read_module_type (struct die_info *die,
                                      struct dwarf2_cu *cu);
@@ -8728,9 +8732,9 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
       break;
     case DW_TAG_imported_declaration:
       cu->processing_has_namespace_info = true;
-      if (read_namespace_alias (die, cu))
+      if (read_alias (die, cu))
        break;
-      /* The declaration is not a global namespace alias.  */
+      /* The declaration is not a global namespace or variable alias.  */
       /* Fall through.  */
     case DW_TAG_imported_module:
       cu->processing_has_namespace_info = true;
@@ -9198,18 +9202,19 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
   return retval;
 }

-/* Inspect DIE in CU for a namespace alias.  If one exists, record
-   a new symbol for it.
+/* Inspect DIE in CU for a namespace alias or a variable
+   with alias attribute. If one exists, record a new symbol
+   for it.

-   Returns 1 if a namespace alias was recorded, 0 otherwise.  */
+   Returns "true" if an alias was recorded, "false" otherwise.  */

-static int
-read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
+static bool
+read_alias (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct attribute *attr;

-  /* If the die does not have a name, this is not a namespace
-     alias.  */
+  /* If the die does not have a name, this is not a namespace alias
+     or variable alias.  */
   attr = dwarf2_attr (die, DW_AT_name, cu);
   if (attr != NULL)
     {
@@ -9235,26 +9240,41 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
        {
          complaint (_("DIE at %s has too many recursively imported "
                       "declarations"), sect_offset_str (d->sect_off));
-         return 0;
+         return false;
        }

       if (attr != NULL)
        {
          struct type *type;
-         sect_offset sect_off = attr->get_ref_die_offset ();
-
-         type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
-         if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+         if (((cu->per_cu->lang == language_c)
+             || (cu->per_cu->lang == language_cplus))
+             && (d->tag == DW_TAG_variable))
            {
-             /* This declaration is a global namespace alias.  Add
-                a symbol for it whose type is the aliased namespace.  */
-             new_symbol (die, type, cu);
-             return 1;
+             /* This declaration is a C/C++ global variable alias. Add
+                a symbol for it whose type is same as aliased variable.  */
+             type = die_type (d, imported_cu);
+             struct symbol *sym = new_symbol (die, type, cu);
+             attr = dwarf2_attr (d, DW_AT_location, imported_cu);
+             sym->set_aclass_index (LOC_UNRESOLVED);
+             if (attr != nullptr)
+               var_decode_location (attr, sym, cu);
+             return true;
+           }
+         else
+           {
+             sect_offset sect_off = attr->get_ref_die_offset ();
+             type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
+             if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+               {
+                 /* This declaration is a global namespace alias. Add
+                    a symbol for it whose type is the aliased namespace.  */
+                 new_symbol (die, type, cu);
+                 return true;
+               }
            }
        }
     }
-
-  return 0;
+  return false;
 }

 /* Return the using directives repository (global or local?) to use in the
diff --git a/gdb/testsuite/gdb.base/symbol-alias.exp b/gdb/testsuite/gdb.base/symbol-alias.exp
index 2b53cc31053..a9487b25f4d 100644
--- a/gdb/testsuite/gdb.base/symbol-alias.exp
+++ b/gdb/testsuite/gdb.base/symbol-alias.exp
@@ -15,6 +15,9 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.

 standard_testfile symbol-alias.c symbol-alias2.c
+set using_clang [test_compiler_info clang-*]
+set old_clang [expr [test_compiler_info {clang-1[0-3]-*-*}] \
+                || [test_compiler_info {clang-[1-9]-*}]]

 if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile $srcfile2]] } {
     return -1
@@ -31,6 +34,62 @@ foreach f {"func" "func_alias"} {
 }

 # Variables.
-foreach v {"g_var_s" "g_var_s_alias"} {
-    gdb_test "p $v" "= {field1 = 1, field2 = 2}"
+gdb_test "p g_var_s" "= {field1 = 1, field2 = 2}"
+foreach v {"g_var_s_alias" "g_var_s_alias2"} {
+    gdb_test_multiple "p $v" "p $v" {
+       -re  " = {field1 = 1, field2 = 2}.*$gdb_prompt $" {
+           pass "print alias of variable $v"
+       }
+       -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+           if { $old_clang } {
+               xfail "print alias variable $v"
+           } else {
+               fail "print alias variable $v"
+           }
+       }
+    }
+}
+
+# Static Variable.
+gdb_test "p g_var" " = 1"
+gdb_test_multiple "p g_var_alias" "p g_var_alias" {
+    -re  " = 1.*$gdb_prompt $" {
+       pass "print alias of static variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+       if { $old_clang } {
+         xfail "print alias of static variable"
+       } else {
+         fail "print alias of static variable"
+       }
+    }
+}
+
+# Deferred Variable.
+gdb_test "p g_def_var" " = 2"
+gdb_test_multiple "p g_def_var_alias" "p g_def_var_alias" {
+    -re  " = 2.*$gdb_prompt $" {
+       pass "print alias of deferred variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+       if { $using_clang } {
+         xfail "print alias of deferred variable"
+       } else {
+         fail "print alias of deferred variable"
+       }
+    }
+}
+
+# Alias of deferred Variable alias.
+gdb_test_multiple "p g_def_var2_alias2" "p g_def_var2_alias2" {
+    -re  " = 3.*$gdb_prompt $" {
+       pass "print alias of alias of deferred variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+       if { $old_clang } {
+         xfail "print alias of alias of deferred variable"
+       } else {
+         fail "print alias of alias of deferred variable"
+       }
+    }
 }
diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c b/gdb/testsuite/gdb.base/symbol-alias2.c
index 34f4e121e25..41d4b6a53e5 100644
--- a/gdb/testsuite/gdb.base/symbol-alias2.c
+++ b/gdb/testsuite/gdb.base/symbol-alias2.c
@@ -23,6 +23,8 @@ struct S

 struct S g_var_s = { 1, 2 };

+static int g_var = 1;
+
 #ifdef __cplusplus
 /* So that the alias attribute below work without having to figure out
    this function's mangled name.  */
@@ -38,3 +40,17 @@ func (void)
 struct S *func_alias (void) __attribute__ ((alias ("func")));

 extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));
+
+extern struct S g_var_s_alias2 __attribute__ ((alias ("g_var_s_alias")));
+
+extern int g_var_alias __attribute__ ((alias ("g_var")));
+
+extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
+
+int g_def_var = 2;
+
+extern int g_def_var2_alias __attribute__ ((alias ("g_def_var2")));
+
+int g_def_var2 = 3;
+
+extern int g_def_var2_alias2 __attribute__ ((alias ("g_def_var2_alias")));
--



[-- Attachment #2: 0005-Debug-support-for-C-global-alias-variable-tom-tromey.patch --]
[-- Type: application/octet-stream, Size: 8595 bytes --]

When clang emits the dwarf information of global alias variable
as DW_TAG_imported_declaration, gdb does not handle it. GDB reads
this tag as C++/fortran imported declaration (type alias, namespace
alias and fortran module). Added support to handle this tag as
alias variable.

This change fixes the failure in gdb.base/symbol-alias.exp testcase.
This testcase is also updated to test nested (recursive) alias.
---
 gdb/dwarf2/read.c                       | 62 +++++++++++++++---------
 gdb/testsuite/gdb.base/symbol-alias.exp | 63 ++++++++++++++++++++++++-
 gdb/testsuite/gdb.base/symbol-alias2.c  | 16 +++++++
 3 files changed, 118 insertions(+), 23 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 6dcd446e5f4..b0eed600312 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -957,6 +957,10 @@ static void build_type_psymtabs_reader (cutu_reader *reader,
 
 static void dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile);
 
+static void var_decode_location (struct attribute *attr,
+				 struct symbol *sym,
+				 struct dwarf2_cu *cu);
+
 static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);
 
 static const gdb_byte *read_attribute (const struct die_reader_specs *,
@@ -1134,7 +1138,7 @@ static struct using_direct **using_directives (struct dwarf2_cu *cu);
 
 static void read_import_statement (struct die_info *die, struct dwarf2_cu *);
 
-static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
+static bool read_alias (struct die_info *die, struct dwarf2_cu *cu);
 
 static struct type *read_module_type (struct die_info *die,
 				      struct dwarf2_cu *cu);
@@ -8728,9 +8732,9 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
       break;
     case DW_TAG_imported_declaration:
       cu->processing_has_namespace_info = true;
-      if (read_namespace_alias (die, cu))
+      if (read_alias (die, cu))
 	break;
-      /* The declaration is not a global namespace alias.  */
+      /* The declaration is not a global namespace or variable alias.  */
       /* Fall through.  */
     case DW_TAG_imported_module:
       cu->processing_has_namespace_info = true;
@@ -9198,18 +9202,19 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
   return retval;
 }
 
-/* Inspect DIE in CU for a namespace alias.  If one exists, record
-   a new symbol for it.
+/* Inspect DIE in CU for a namespace alias or a variable
+   with alias attribute. If one exists, record a new symbol
+   for it.
 
-   Returns 1 if a namespace alias was recorded, 0 otherwise.  */
+   Returns "true" if an alias was recorded, "false" otherwise.  */
 
-static int
-read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
+static bool
+read_alias (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct attribute *attr;
 
-  /* If the die does not have a name, this is not a namespace
-     alias.  */
+  /* If the die does not have a name, this is not a namespace alias
+     or variable alias.  */
   attr = dwarf2_attr (die, DW_AT_name, cu);
   if (attr != NULL)
     {
@@ -9235,26 +9240,41 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
 	{
 	  complaint (_("DIE at %s has too many recursively imported "
 		       "declarations"), sect_offset_str (d->sect_off));
-	  return 0;
+	  return false;
 	}
 
       if (attr != NULL)
 	{
 	  struct type *type;
-	  sect_offset sect_off = attr->get_ref_die_offset ();
-
-	  type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
-	  if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+	  if (((cu->per_cu->lang == language_c)
+	      || (cu->per_cu->lang == language_cplus))
+	      && (d->tag == DW_TAG_variable))
 	    {
-	      /* This declaration is a global namespace alias.  Add
-		 a symbol for it whose type is the aliased namespace.  */
-	      new_symbol (die, type, cu);
-	      return 1;
+	      /* This declaration is a C/C++ global variable alias. Add
+		 a symbol for it whose type is same as aliased variable.  */
+	      type = die_type (d, imported_cu);
+	      struct symbol *sym = new_symbol (die, type, cu);
+	      attr = dwarf2_attr (d, DW_AT_location, imported_cu);
+	      sym->set_aclass_index (LOC_UNRESOLVED);
+	      if (attr != nullptr)
+		var_decode_location (attr, sym, cu);
+	      return true;
+	    }
+	  else
+	    {
+	      sect_offset sect_off = attr->get_ref_die_offset ();
+	      type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
+	      if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+		{
+		  /* This declaration is a global namespace alias. Add
+		     a symbol for it whose type is the aliased namespace.  */
+		  new_symbol (die, type, cu);
+		  return true;
+		}
 	    }
 	}
     }
-
-  return 0;
+  return false;
 }
 
 /* Return the using directives repository (global or local?) to use in the
diff --git a/gdb/testsuite/gdb.base/symbol-alias.exp b/gdb/testsuite/gdb.base/symbol-alias.exp
index 2b53cc31053..a9487b25f4d 100644
--- a/gdb/testsuite/gdb.base/symbol-alias.exp
+++ b/gdb/testsuite/gdb.base/symbol-alias.exp
@@ -15,6 +15,9 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 standard_testfile symbol-alias.c symbol-alias2.c
+set using_clang [test_compiler_info clang-*]
+set old_clang [expr [test_compiler_info {clang-1[0-3]-*-*}] \
+		 || [test_compiler_info {clang-[1-9]-*}]]
 
 if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile $srcfile2]] } {
     return -1
@@ -31,6 +34,62 @@ foreach f {"func" "func_alias"} {
 }
 
 # Variables.
-foreach v {"g_var_s" "g_var_s_alias"} {
-    gdb_test "p $v" "= {field1 = 1, field2 = 2}"
+gdb_test "p g_var_s" "= {field1 = 1, field2 = 2}"
+foreach v {"g_var_s_alias" "g_var_s_alias2"} {
+    gdb_test_multiple "p $v" "p $v" {
+	-re  " = {field1 = 1, field2 = 2}.*$gdb_prompt $" {
+	    pass "print alias of variable $v"
+	}
+	-re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+	    if { $old_clang } {
+		xfail "print alias variable $v"
+	    } else {
+		fail "print alias variable $v"
+	    }
+	}
+    }
+}
+
+# Static Variable.
+gdb_test "p g_var" " = 1"
+gdb_test_multiple "p g_var_alias" "p g_var_alias" {
+    -re  " = 1.*$gdb_prompt $" {
+	pass "print alias of static variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+	if { $old_clang } {
+	  xfail "print alias of static variable"
+	} else {
+	  fail "print alias of static variable"
+	}
+    }
+}
+
+# Deferred Variable.
+gdb_test "p g_def_var" " = 2"
+gdb_test_multiple "p g_def_var_alias" "p g_def_var_alias" {
+    -re  " = 2.*$gdb_prompt $" {
+	pass "print alias of deferred variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+	if { $using_clang } {
+	  xfail "print alias of deferred variable"
+	} else {
+	  fail "print alias of deferred variable"
+	}
+    }
+}
+
+# Alias of deferred Variable alias.
+gdb_test_multiple "p g_def_var2_alias2" "p g_def_var2_alias2" {
+    -re  " = 3.*$gdb_prompt $" {
+	pass "print alias of alias of deferred variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+	if { $old_clang } {
+	  xfail "print alias of alias of deferred variable"
+	} else {
+	  fail "print alias of alias of deferred variable"
+	}
+    }
 }
diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c b/gdb/testsuite/gdb.base/symbol-alias2.c
index 34f4e121e25..41d4b6a53e5 100644
--- a/gdb/testsuite/gdb.base/symbol-alias2.c
+++ b/gdb/testsuite/gdb.base/symbol-alias2.c
@@ -23,6 +23,8 @@ struct S
 
 struct S g_var_s = { 1, 2 };
 
+static int g_var = 1;
+
 #ifdef __cplusplus
 /* So that the alias attribute below work without having to figure out
    this function's mangled name.  */
@@ -38,3 +40,17 @@ func (void)
 struct S *func_alias (void) __attribute__ ((alias ("func")));
 
 extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));
+
+extern struct S g_var_s_alias2 __attribute__ ((alias ("g_var_s_alias")));
+
+extern int g_var_alias __attribute__ ((alias ("g_var")));
+
+extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
+
+int g_def_var = 2;
+
+extern int g_def_var2_alias __attribute__ ((alias ("g_def_var2")));
+
+int g_def_var2 = 3;
+
+extern int g_def_var2_alias2 __attribute__ ((alias ("g_def_var2_alias")));
-- 
2.25.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] Debug support for global alias variable
  2022-04-18 11:04             ` Natarajan, Kavitha
@ 2022-04-18 15:03               ` Tom Tromey
  2022-04-19 12:45                 ` Natarajan, Kavitha
  0 siblings, 1 reply; 28+ messages in thread
From: Tom Tromey @ 2022-04-18 15:03 UTC (permalink / raw)
  To: Natarajan, Kavitha via Gdb-patches
  Cc: Tom Tromey, Natarajan, Kavitha, George, Jini Susan, Parasuraman,
	Hariharan

>>>>> Natarajan, Kavitha via Gdb-patches <gdb-patches@sourceware.org> writes:

> There doesn't seem to be any impact on other languages as the new symbol is
> created only for TYPE_CODE_NAMESPACE in read_namespace_alias function.
> However, it could regress with my change. So I have moved this check specific
> to my change so that this change is specific to C/C++ global alias variables.

Is there a reason not to handle other languages here?

> +         if (((cu->per_cu->lang == language_c)
> +             || (cu->per_cu->lang == language_cplus))
> +             && (d->tag == DW_TAG_variable))

This is over-parenthesized.  However, I still think that the language
checks should probably be removed.  I'd like to get the Ada compiler
using imports like this to represent renamings, though I haven't tried
it yet.

thanks,
Tom

^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [PATCH] Debug support for global alias variable
  2022-04-18 15:03               ` Tom Tromey
@ 2022-04-19 12:45                 ` Natarajan, Kavitha
  2022-04-19 22:59                   ` Tom Tromey
  0 siblings, 1 reply; 28+ messages in thread
From: Natarajan, Kavitha @ 2022-04-19 12:45 UTC (permalink / raw)
  To: Tom Tromey, Natarajan, Kavitha via Gdb-patches
  Cc: George, Jini Susan, Parasuraman, Hariharan

[AMD Official Use Only]

> Is there a reason not to handle other languages here?
>
> > +         if (((cu->per_cu->lang == language_c)
> > +             || (cu->per_cu->lang == language_cplus))
> > +             && (d->tag == DW_TAG_variable))
>
> This is over-parenthesized.  However, I still think that the language checks
> should probably be removed.  I'd like to get the Ada compiler using imports
> like this to represent renamings, though I haven't tried it yet.
>
> thanks,
> Tom

I have tested only with C, C++ and Fortran. Fortran doesn't pass through read_alias()
as fortran imported variables are processed while processing imported modules
itself. But I may not be able to test with other languages than the above said ones.
This is the reason for not exposing the code for other languages. Atleast, I do not see
any regression with gdb testsuites. So, let me know if it is still ok to remove the language
checks.

Regards,
Kavitha

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] Debug support for global alias variable
  2022-04-19 12:45                 ` Natarajan, Kavitha
@ 2022-04-19 22:59                   ` Tom Tromey
  2022-04-20  6:00                     ` Natarajan, Kavitha
  0 siblings, 1 reply; 28+ messages in thread
From: Tom Tromey @ 2022-04-19 22:59 UTC (permalink / raw)
  To: Natarajan, Kavitha
  Cc: Tom Tromey, Natarajan, Kavitha via Gdb-patches, George,
	Jini Susan, Parasuraman, Hariharan

> But I may not be able to test with other languages than the above said ones.
> This is the reason for not exposing the code for other languages. Atleast, I do not see
> any regression with gdb testsuites. So, let me know if it is still ok to remove the language
> checks.

Yes, I think it's fine.  Thank you.

Tom

^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [PATCH] Debug support for global alias variable
  2022-04-19 22:59                   ` Tom Tromey
@ 2022-04-20  6:00                     ` Natarajan, Kavitha
  2022-04-20 10:33                       ` Pedro Alves
  0 siblings, 1 reply; 28+ messages in thread
From: Natarajan, Kavitha @ 2022-04-20  6:00 UTC (permalink / raw)
  To: Tom Tromey, Natarajan, Kavitha via Gdb-patches
  Cc: George, Jini Susan, Parasuraman, Hariharan

[-- Attachment #1: Type: text/plain, Size: 9302 bytes --]

[AMD Official Use Only]

> Yes, I think it's fine.  Thank you.
>
> Tom

Thank you Tom. I am attaching the final patch. Please verify and approve.

Regards,
Kavitha
=================================================================
When clang emits the dwarf information of global alias variable
as DW_TAG_imported_declaration, gdb does not handle it. GDB reads
this tag as C++/fortran imported declaration (type alias, namespace
alias and fortran module). Added support to handle this tag as
alias variable.

This change fixes the failure in gdb.base/symbol-alias.exp testcase.
This testcase is also updated to test nested (recursive) alias.
---
 gdb/dwarf2/read.c                       | 60 ++++++++++++++---------
 gdb/testsuite/gdb.base/symbol-alias.exp | 63 ++++++++++++++++++++++++-
 gdb/testsuite/gdb.base/symbol-alias2.c  | 16 +++++++
 3 files changed, 116 insertions(+), 23 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 6dcd446e5f4..d0c95459d8f 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -957,6 +957,10 @@ static void build_type_psymtabs_reader (cutu_reader *reader,

 static void dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile);

+static void var_decode_location (struct attribute *attr,
+                                struct symbol *sym,
+                                struct dwarf2_cu *cu);
+
 static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);

 static const gdb_byte *read_attribute (const struct die_reader_specs *,
@@ -1134,7 +1138,7 @@ static struct using_direct **using_directives (struct dwarf2_cu *cu);

 static void read_import_statement (struct die_info *die, struct dwarf2_cu *);

-static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
+static bool read_alias (struct die_info *die, struct dwarf2_cu *cu);

 static struct type *read_module_type (struct die_info *die,
                                      struct dwarf2_cu *cu);
@@ -8728,9 +8732,9 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
       break;
     case DW_TAG_imported_declaration:
       cu->processing_has_namespace_info = true;
-      if (read_namespace_alias (die, cu))
+      if (read_alias (die, cu))
        break;
-      /* The declaration is not a global namespace alias.  */
+      /* The declaration is not a global namespace or variable alias.  */
       /* Fall through.  */
     case DW_TAG_imported_module:
       cu->processing_has_namespace_info = true;
@@ -9198,18 +9202,19 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
   return retval;
 }

-/* Inspect DIE in CU for a namespace alias.  If one exists, record
-   a new symbol for it.
+/* Inspect DIE in CU for a namespace alias or a variable
+   with alias attribute. If one exists, record a new symbol
+   for it.

-   Returns 1 if a namespace alias was recorded, 0 otherwise.  */
+   Returns "true" if an alias was recorded, "false" otherwise.  */

-static int
-read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
+static bool
+read_alias (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct attribute *attr;

-  /* If the die does not have a name, this is not a namespace
-     alias.  */
+  /* If the die does not have a name, this is not a namespace alias
+     or variable alias.  */
   attr = dwarf2_attr (die, DW_AT_name, cu);
   if (attr != NULL)
     {
@@ -9235,26 +9240,39 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
        {
          complaint (_("DIE at %s has too many recursively imported "
                       "declarations"), sect_offset_str (d->sect_off));
-         return 0;
+         return false;
        }

       if (attr != NULL)
        {
          struct type *type;
-         sect_offset sect_off = attr->get_ref_die_offset ();
-
-         type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
-         if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+         if (d->tag == DW_TAG_variable)
            {
-             /* This declaration is a global namespace alias.  Add
-                a symbol for it whose type is the aliased namespace.  */
-             new_symbol (die, type, cu);
-             return 1;
+             /* This declaration is a C/C++ global variable alias. Add
+                a symbol for it whose type is same as aliased variable.  */
+             type = die_type (d, imported_cu);
+             struct symbol *sym = new_symbol (die, type, cu);
+             attr = dwarf2_attr (d, DW_AT_location, imported_cu);
+             sym->set_aclass_index (LOC_UNRESOLVED);
+             if (attr != nullptr)
+               var_decode_location (attr, sym, cu);
+             return true;
+           }
+         else
+           {
+             sect_offset sect_off = attr->get_ref_die_offset ();
+             type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
+             if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+               {
+                 /* This declaration is a global namespace alias. Add
+                    a symbol for it whose type is the aliased namespace.  */
+                 new_symbol (die, type, cu);
+                 return true;
+               }
            }
        }
     }
-
-  return 0;
+  return false;
 }

 /* Return the using directives repository (global or local?) to use in the
diff --git a/gdb/testsuite/gdb.base/symbol-alias.exp b/gdb/testsuite/gdb.base/symbol-alias.exp
index 2b53cc31053..a9487b25f4d 100644
--- a/gdb/testsuite/gdb.base/symbol-alias.exp
+++ b/gdb/testsuite/gdb.base/symbol-alias.exp
@@ -15,6 +15,9 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.

 standard_testfile symbol-alias.c symbol-alias2.c
+set using_clang [test_compiler_info clang-*]
+set old_clang [expr [test_compiler_info {clang-1[0-3]-*-*}] \
+                || [test_compiler_info {clang-[1-9]-*}]]

 if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile $srcfile2]] } {
     return -1
@@ -31,6 +34,62 @@ foreach f {"func" "func_alias"} {
 }

 # Variables.
-foreach v {"g_var_s" "g_var_s_alias"} {
-    gdb_test "p $v" "= {field1 = 1, field2 = 2}"
+gdb_test "p g_var_s" "= {field1 = 1, field2 = 2}"
+foreach v {"g_var_s_alias" "g_var_s_alias2"} {
+    gdb_test_multiple "p $v" "p $v" {
+       -re  " = {field1 = 1, field2 = 2}.*$gdb_prompt $" {
+           pass "print alias of variable $v"
+       }
+       -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+           if { $old_clang } {
+               xfail "print alias variable $v"
+           } else {
+               fail "print alias variable $v"
+           }
+       }
+    }
+}
+
+# Static Variable.
+gdb_test "p g_var" " = 1"
+gdb_test_multiple "p g_var_alias" "p g_var_alias" {
+    -re  " = 1.*$gdb_prompt $" {
+       pass "print alias of static variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+       if { $old_clang } {
+         xfail "print alias of static variable"
+       } else {
+         fail "print alias of static variable"
+       }
+    }
+}
+
+# Deferred Variable.
+gdb_test "p g_def_var" " = 2"
+gdb_test_multiple "p g_def_var_alias" "p g_def_var_alias" {
+    -re  " = 2.*$gdb_prompt $" {
+       pass "print alias of deferred variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+       if { $using_clang } {
+         xfail "print alias of deferred variable"
+       } else {
+         fail "print alias of deferred variable"
+       }
+    }
+}
+
+# Alias of deferred Variable alias.
+gdb_test_multiple "p g_def_var2_alias2" "p g_def_var2_alias2" {
+    -re  " = 3.*$gdb_prompt $" {
+       pass "print alias of alias of deferred variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+       if { $old_clang } {
+         xfail "print alias of alias of deferred variable"
+       } else {
+         fail "print alias of alias of deferred variable"
+       }
+    }
 }
diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c b/gdb/testsuite/gdb.base/symbol-alias2.c
index 34f4e121e25..41d4b6a53e5 100644
--- a/gdb/testsuite/gdb.base/symbol-alias2.c
+++ b/gdb/testsuite/gdb.base/symbol-alias2.c
@@ -23,6 +23,8 @@ struct S

 struct S g_var_s = { 1, 2 };

+static int g_var = 1;
+
 #ifdef __cplusplus
 /* So that the alias attribute below work without having to figure out
    this function's mangled name.  */
@@ -38,3 +40,17 @@ func (void)
 struct S *func_alias (void) __attribute__ ((alias ("func")));

 extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));
+
+extern struct S g_var_s_alias2 __attribute__ ((alias ("g_var_s_alias")));
+
+extern int g_var_alias __attribute__ ((alias ("g_var")));
+
+extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
+
+int g_def_var = 2;
+
+extern int g_def_var2_alias __attribute__ ((alias ("g_def_var2")));
+
+int g_def_var2 = 3;
+
+extern int g_def_var2_alias2 __attribute__ ((alias ("g_def_var2_alias")));
--


[-- Attachment #2: 0006-Debug-support-for-C-global-alias-variable-tom-tromey.patch --]
[-- Type: application/octet-stream, Size: 8488 bytes --]

When clang emits the dwarf information of global alias variable
as DW_TAG_imported_declaration, gdb does not handle it. GDB reads
this tag as C++/fortran imported declaration (type alias, namespace
alias and fortran module). Added support to handle this tag as
alias variable.

This change fixes the failure in gdb.base/symbol-alias.exp testcase.
This testcase is also updated to test nested (recursive) alias.
---
 gdb/dwarf2/read.c                       | 60 ++++++++++++++---------
 gdb/testsuite/gdb.base/symbol-alias.exp | 63 ++++++++++++++++++++++++-
 gdb/testsuite/gdb.base/symbol-alias2.c  | 16 +++++++
 3 files changed, 116 insertions(+), 23 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 6dcd446e5f4..d0c95459d8f 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -957,6 +957,10 @@ static void build_type_psymtabs_reader (cutu_reader *reader,
 
 static void dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile);
 
+static void var_decode_location (struct attribute *attr,
+				 struct symbol *sym,
+				 struct dwarf2_cu *cu);
+
 static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);
 
 static const gdb_byte *read_attribute (const struct die_reader_specs *,
@@ -1134,7 +1138,7 @@ static struct using_direct **using_directives (struct dwarf2_cu *cu);
 
 static void read_import_statement (struct die_info *die, struct dwarf2_cu *);
 
-static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
+static bool read_alias (struct die_info *die, struct dwarf2_cu *cu);
 
 static struct type *read_module_type (struct die_info *die,
 				      struct dwarf2_cu *cu);
@@ -8728,9 +8732,9 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
       break;
     case DW_TAG_imported_declaration:
       cu->processing_has_namespace_info = true;
-      if (read_namespace_alias (die, cu))
+      if (read_alias (die, cu))
 	break;
-      /* The declaration is not a global namespace alias.  */
+      /* The declaration is not a global namespace or variable alias.  */
       /* Fall through.  */
     case DW_TAG_imported_module:
       cu->processing_has_namespace_info = true;
@@ -9198,18 +9202,19 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
   return retval;
 }
 
-/* Inspect DIE in CU for a namespace alias.  If one exists, record
-   a new symbol for it.
+/* Inspect DIE in CU for a namespace alias or a variable
+   with alias attribute. If one exists, record a new symbol
+   for it.
 
-   Returns 1 if a namespace alias was recorded, 0 otherwise.  */
+   Returns "true" if an alias was recorded, "false" otherwise.  */
 
-static int
-read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
+static bool
+read_alias (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct attribute *attr;
 
-  /* If the die does not have a name, this is not a namespace
-     alias.  */
+  /* If the die does not have a name, this is not a namespace alias
+     or variable alias.  */
   attr = dwarf2_attr (die, DW_AT_name, cu);
   if (attr != NULL)
     {
@@ -9235,26 +9240,39 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
 	{
 	  complaint (_("DIE at %s has too many recursively imported "
 		       "declarations"), sect_offset_str (d->sect_off));
-	  return 0;
+	  return false;
 	}
 
       if (attr != NULL)
 	{
 	  struct type *type;
-	  sect_offset sect_off = attr->get_ref_die_offset ();
-
-	  type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
-	  if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+	  if (d->tag == DW_TAG_variable)
 	    {
-	      /* This declaration is a global namespace alias.  Add
-		 a symbol for it whose type is the aliased namespace.  */
-	      new_symbol (die, type, cu);
-	      return 1;
+	      /* This declaration is a C/C++ global variable alias. Add
+		 a symbol for it whose type is same as aliased variable.  */
+	      type = die_type (d, imported_cu);
+	      struct symbol *sym = new_symbol (die, type, cu);
+	      attr = dwarf2_attr (d, DW_AT_location, imported_cu);
+	      sym->set_aclass_index (LOC_UNRESOLVED);
+	      if (attr != nullptr)
+		var_decode_location (attr, sym, cu);
+	      return true;
+	    }
+	  else
+	    {
+	      sect_offset sect_off = attr->get_ref_die_offset ();
+	      type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
+	      if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+		{
+		  /* This declaration is a global namespace alias. Add
+		     a symbol for it whose type is the aliased namespace.  */
+		  new_symbol (die, type, cu);
+		  return true;
+		}
 	    }
 	}
     }
-
-  return 0;
+  return false;
 }
 
 /* Return the using directives repository (global or local?) to use in the
diff --git a/gdb/testsuite/gdb.base/symbol-alias.exp b/gdb/testsuite/gdb.base/symbol-alias.exp
index 2b53cc31053..a9487b25f4d 100644
--- a/gdb/testsuite/gdb.base/symbol-alias.exp
+++ b/gdb/testsuite/gdb.base/symbol-alias.exp
@@ -15,6 +15,9 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 standard_testfile symbol-alias.c symbol-alias2.c
+set using_clang [test_compiler_info clang-*]
+set old_clang [expr [test_compiler_info {clang-1[0-3]-*-*}] \
+		 || [test_compiler_info {clang-[1-9]-*}]]
 
 if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile $srcfile2]] } {
     return -1
@@ -31,6 +34,62 @@ foreach f {"func" "func_alias"} {
 }
 
 # Variables.
-foreach v {"g_var_s" "g_var_s_alias"} {
-    gdb_test "p $v" "= {field1 = 1, field2 = 2}"
+gdb_test "p g_var_s" "= {field1 = 1, field2 = 2}"
+foreach v {"g_var_s_alias" "g_var_s_alias2"} {
+    gdb_test_multiple "p $v" "p $v" {
+	-re  " = {field1 = 1, field2 = 2}.*$gdb_prompt $" {
+	    pass "print alias of variable $v"
+	}
+	-re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+	    if { $old_clang } {
+		xfail "print alias variable $v"
+	    } else {
+		fail "print alias variable $v"
+	    }
+	}
+    }
+}
+
+# Static Variable.
+gdb_test "p g_var" " = 1"
+gdb_test_multiple "p g_var_alias" "p g_var_alias" {
+    -re  " = 1.*$gdb_prompt $" {
+	pass "print alias of static variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+	if { $old_clang } {
+	  xfail "print alias of static variable"
+	} else {
+	  fail "print alias of static variable"
+	}
+    }
+}
+
+# Deferred Variable.
+gdb_test "p g_def_var" " = 2"
+gdb_test_multiple "p g_def_var_alias" "p g_def_var_alias" {
+    -re  " = 2.*$gdb_prompt $" {
+	pass "print alias of deferred variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+	if { $using_clang } {
+	  xfail "print alias of deferred variable"
+	} else {
+	  fail "print alias of deferred variable"
+	}
+    }
+}
+
+# Alias of deferred Variable alias.
+gdb_test_multiple "p g_def_var2_alias2" "p g_def_var2_alias2" {
+    -re  " = 3.*$gdb_prompt $" {
+	pass "print alias of alias of deferred variable"
+    }
+    -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {
+	if { $old_clang } {
+	  xfail "print alias of alias of deferred variable"
+	} else {
+	  fail "print alias of alias of deferred variable"
+	}
+    }
 }
diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c b/gdb/testsuite/gdb.base/symbol-alias2.c
index 34f4e121e25..41d4b6a53e5 100644
--- a/gdb/testsuite/gdb.base/symbol-alias2.c
+++ b/gdb/testsuite/gdb.base/symbol-alias2.c
@@ -23,6 +23,8 @@ struct S
 
 struct S g_var_s = { 1, 2 };
 
+static int g_var = 1;
+
 #ifdef __cplusplus
 /* So that the alias attribute below work without having to figure out
    this function's mangled name.  */
@@ -38,3 +40,17 @@ func (void)
 struct S *func_alias (void) __attribute__ ((alias ("func")));
 
 extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));
+
+extern struct S g_var_s_alias2 __attribute__ ((alias ("g_var_s_alias")));
+
+extern int g_var_alias __attribute__ ((alias ("g_var")));
+
+extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
+
+int g_def_var = 2;
+
+extern int g_def_var2_alias __attribute__ ((alias ("g_def_var2")));
+
+int g_def_var2 = 3;
+
+extern int g_def_var2_alias2 __attribute__ ((alias ("g_def_var2_alias")));
-- 


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] Debug support for global alias variable
  2022-04-20  6:00                     ` Natarajan, Kavitha
@ 2022-04-20 10:33                       ` Pedro Alves
  2022-04-20 12:17                         ` Natarajan, Kavitha
  0 siblings, 1 reply; 28+ messages in thread
From: Pedro Alves @ 2022-04-20 10:33 UTC (permalink / raw)
  To: Natarajan, Kavitha, Tom Tromey, Natarajan, Kavitha via Gdb-patches
  Cc: George, Jini Susan, Parasuraman, Hariharan

On 2022-04-20 07:00, Natarajan, Kavitha via Gdb-patches wrote:
> +    gdb_test_multiple "p $v" "p $v" {

The second argument here is the test's name used if gdb_test_multiple hits a FAIL
pattern internally, like an internal error or a timeout.  It should be the same
text used in the pass/fail messages below.  The easy way to do that is to use
$gdb_test_name in the pass/fail calls below.  See example below.

> +       -re  " = {field1 = 1, field2 = 2}.*$gdb_prompt $" {

You can use -re -wrap instead of explicitly matching $gdb_prompt.

> +           pass "print alias of variable $v"
> +       }
> +       -re  ".*has unknown type; cast it to its declared type.*$gdb_prompt $" {

The leading .* is unnecessary.

> +           if { $old_clang } {
> +               xfail "print alias variable $v"
> +           } else {
> +               fail "print alias variable $v"
> +           }
> +       }
> +    }

I believe something like this should work:

    gdb_test_multiple "p $v" "print alias of variable $v" {
       -re -wrap " = {field1 = 1, field2 = 2}" {
           pass $gdb_test_name
       }
       -re -wrap "has unknown type; cast it to its declared type" {
           if { $old_clang } {
               xfail $gdb_test_name
           } else {
               fail $gdb_test_name
           }
       }
    }

Note I also removed some ".*" from the right side of the patterns, I believe they
should be unnecessary.

Could you please go over the patch tweaking the new gdb_test_multiple calls to
follow the same pattern, please?

Thanks for the patch!

^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [PATCH] Debug support for global alias variable
  2022-04-20 10:33                       ` Pedro Alves
@ 2022-04-20 12:17                         ` Natarajan, Kavitha
  2022-04-25 13:10                           ` Natarajan, Kavitha
                                             ` (2 more replies)
  0 siblings, 3 replies; 28+ messages in thread
From: Natarajan, Kavitha @ 2022-04-20 12:17 UTC (permalink / raw)
  To: Pedro Alves, Tom Tromey, Natarajan, Kavitha via Gdb-patches
  Cc: George, Jini Susan, Parasuraman, Hariharan

[AMD Official Use Only]

> Could you please go over the patch tweaking the new gdb_test_multiple
> calls to follow the same pattern, please?
>

Thank you Pedro for your suggestions. I have incorporated the changes for all get_test_multiple
calls and updated the patch.

Regards,
Kavitha
==============================================================================
When clang emits the dwarf information of global alias variable
as DW_TAG_imported_declaration, gdb does not handle it. GDB reads
this tag as C++/fortran imported declaration (type alias, namespace
alias and fortran module). Added support to handle this tag as
alias variable.

This change fixes the failure in gdb.base/symbol-alias.exp testcase.
This testcase is also updated to test nested (recursive) alias.
---
 gdb/dwarf2/read.c                       | 60 ++++++++++++++---------
 gdb/testsuite/gdb.base/symbol-alias.exp | 63 ++++++++++++++++++++++++-
 gdb/testsuite/gdb.base/symbol-alias2.c  | 16 +++++++
 3 files changed, 116 insertions(+), 23 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 6dcd446e5f4..d0c95459d8f 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -957,6 +957,10 @@ static void build_type_psymtabs_reader (cutu_reader *reader,

 static void dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile);

+static void var_decode_location (struct attribute *attr,
+                                struct symbol *sym,
+                                struct dwarf2_cu *cu);
+
 static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);

 static const gdb_byte *read_attribute (const struct die_reader_specs *,
@@ -1134,7 +1138,7 @@ static struct using_direct **using_directives (struct dwarf2_cu *cu);

 static void read_import_statement (struct die_info *die, struct dwarf2_cu *);

-static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
+static bool read_alias (struct die_info *die, struct dwarf2_cu *cu);

 static struct type *read_module_type (struct die_info *die,
                                      struct dwarf2_cu *cu);
@@ -8728,9 +8732,9 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
       break;
     case DW_TAG_imported_declaration:
       cu->processing_has_namespace_info = true;
-      if (read_namespace_alias (die, cu))
+      if (read_alias (die, cu))
        break;
-      /* The declaration is not a global namespace alias.  */
+      /* The declaration is not a global namespace or variable alias.  */
       /* Fall through.  */
     case DW_TAG_imported_module:
       cu->processing_has_namespace_info = true;
@@ -9198,18 +9202,19 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
   return retval;
 }

-/* Inspect DIE in CU for a namespace alias.  If one exists, record
-   a new symbol for it.
+/* Inspect DIE in CU for a namespace alias or a variable
+   with alias attribute. If one exists, record a new symbol
+   for it.

-   Returns 1 if a namespace alias was recorded, 0 otherwise.  */
+   Returns "true" if an alias was recorded, "false" otherwise.  */

-static int
-read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
+static bool
+read_alias (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct attribute *attr;

-  /* If the die does not have a name, this is not a namespace
-     alias.  */
+  /* If the die does not have a name, this is not a namespace alias
+     or variable alias.  */
   attr = dwarf2_attr (die, DW_AT_name, cu);
   if (attr != NULL)
     {
@@ -9235,26 +9240,39 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
        {
          complaint (_("DIE at %s has too many recursively imported "
                       "declarations"), sect_offset_str (d->sect_off));
-         return 0;
+         return false;
        }

       if (attr != NULL)
        {
          struct type *type;
-         sect_offset sect_off = attr->get_ref_die_offset ();
-
-         type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
-         if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+         if (d->tag == DW_TAG_variable)
            {
-             /* This declaration is a global namespace alias.  Add
-                a symbol for it whose type is the aliased namespace.  */
-             new_symbol (die, type, cu);
-             return 1;
+             /* This declaration is a C/C++ global variable alias. Add
+                a symbol for it whose type is same as aliased variable.  */
+             type = die_type (d, imported_cu);
+             struct symbol *sym = new_symbol (die, type, cu);
+             attr = dwarf2_attr (d, DW_AT_location, imported_cu);
+             sym->set_aclass_index (LOC_UNRESOLVED);
+             if (attr != nullptr)
+               var_decode_location (attr, sym, cu);
+             return true;
+           }
+         else
+           {
+             sect_offset sect_off = attr->get_ref_die_offset ();
+             type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
+             if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+               {
+                 /* This declaration is a global namespace alias. Add
+                    a symbol for it whose type is the aliased namespace.  */
+                 new_symbol (die, type, cu);
+                 return true;
+               }
            }
        }
     }
-
-  return 0;
+  return false;
 }

 /* Return the using directives repository (global or local?) to use in the
diff --git a/gdb/testsuite/gdb.base/symbol-alias.exp b/gdb/testsuite/gdb.base/symbol-alias.exp
index 2b53cc31053..1024954b0cb 100644
--- a/gdb/testsuite/gdb.base/symbol-alias.exp
+++ b/gdb/testsuite/gdb.base/symbol-alias.exp
@@ -15,6 +15,9 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.

 standard_testfile symbol-alias.c symbol-alias2.c
+set using_clang [test_compiler_info clang-*]
+set old_clang [expr [test_compiler_info {clang-1[0-3]-*-*}] \
+                || [test_compiler_info {clang-[1-9]-*}]]

 if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile $srcfile2]] } {
     return -1
@@ -31,6 +34,62 @@ foreach f {"func" "func_alias"} {
 }

 # Variables.
-foreach v {"g_var_s" "g_var_s_alias"} {
-    gdb_test "p $v" "= {field1 = 1, field2 = 2}"
+gdb_test "p g_var_s" "= {field1 = 1, field2 = 2}"
+foreach v {"g_var_s_alias" "g_var_s_alias2"} {
+    gdb_test_multiple "p $v" "print alias variable $v" {
+       -re -wrap " = {field1 = 1, field2 = 2}" {
+           pass $gdb_test_name
+       }
+       -re -wrap "has unknown type; cast it to its declared type" {
+           if { $old_clang } {
+               xfail $gdb_test_name
+           } else {
+               fail $gdb_test_name
+           }
+       }
+    }
+}
+
+# Static Variable.
+gdb_test "p g_var" " = 1"
+gdb_test_multiple "p g_var_alias" "print alias of static variable" {
+    -re -wrap " = 1" {
+       pass $gdb_test_name
+    }
+    -re -wrap "has unknown type; cast it to its declared type" {
+       if { $old_clang } {
+         xfail $gdb_test_name
+       } else {
+         fail $gdb_test_name
+       }
+    }
+}
+
+# Deferred Variable.
+gdb_test "p g_def_var" " = 2"
+gdb_test_multiple "p g_def_var_alias" "print alias of deferred variable" {
+    -re -wrap " = 2" {
+       pass $gdb_test_name
+    }
+    -re -wrap "has unknown type; cast it to its declared type" {
+       if { $using_clang } {
+         xfail $gdb_test_name
+       } else {
+         fail $gdb_test_name
+       }
+    }
+}
+
+# Alias of deferred Variable alias.
+gdb_test_multiple "p g_def_var2_alias2" "print alias of alias of deferred variable" {
+    -re -wrap " = 3" {
+       pass $gdb_test_name
+    }
+    -re -wrap "has unknown type; cast it to its declared type" {
+       if { $old_clang } {
+         xfail $gdb_test_name
+       } else {
+         fail $gdb_test_name
+       }
+    }
 }
diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c b/gdb/testsuite/gdb.base/symbol-alias2.c
index 34f4e121e25..41d4b6a53e5 100644
--- a/gdb/testsuite/gdb.base/symbol-alias2.c
+++ b/gdb/testsuite/gdb.base/symbol-alias2.c
@@ -23,6 +23,8 @@ struct S

 struct S g_var_s = { 1, 2 };

+static int g_var = 1;
+
 #ifdef __cplusplus
 /* So that the alias attribute below work without having to figure out
    this function's mangled name.  */
@@ -38,3 +40,17 @@ func (void)
 struct S *func_alias (void) __attribute__ ((alias ("func")));

 extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));
+
+extern struct S g_var_s_alias2 __attribute__ ((alias ("g_var_s_alias")));
+
+extern int g_var_alias __attribute__ ((alias ("g_var")));
+
+extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
+
+int g_def_var = 2;
+
+extern int g_def_var2_alias __attribute__ ((alias ("g_def_var2")));
+
+int g_def_var2 = 3;
+
+extern int g_def_var2_alias2 __attribute__ ((alias ("g_def_var2_alias")));
--
2.25.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [PATCH] Debug support for global alias variable
  2022-04-20 12:17                         ` Natarajan, Kavitha
@ 2022-04-25 13:10                           ` Natarajan, Kavitha
  2022-05-05  9:53                           ` Natarajan, Kavitha
  2022-06-07  9:08                           ` Natarajan, Kavitha
  2 siblings, 0 replies; 28+ messages in thread
From: Natarajan, Kavitha @ 2022-04-25 13:10 UTC (permalink / raw)
  To: Pedro Alves, Tom Tromey, Natarajan, Kavitha via Gdb-patches
  Cc: George, Jini Susan, Parasuraman, Hariharan

[AMD Official Use Only]

Can this patch be pushed to upstream?

> -----Original Message-----
> From: Natarajan, Kavitha
> Sent: Wednesday, April 20, 2022 5:47 PM
> To: Pedro Alves <pedro@palves.net>; Tom Tromey <tom@tromey.com>;
> Natarajan, Kavitha via Gdb-patches <gdb-patches@sourceware.org>
> Cc: George, Jini Susan <JiniSusan.George@amd.com>; Parasuraman,
> Hariharan <Hariharan.Parasuraman@amd.com>
> Subject: RE: [PATCH] Debug support for global alias variable
>
> > Could you please go over the patch tweaking the new gdb_test_multiple
> > calls to follow the same pattern, please?
> >
>
> Thank you Pedro for your suggestions. I have incorporated the changes for all
> get_test_multiple calls and updated the patch.
>
> Regards,
> Kavitha
> ==========================================================
> ====================
> When clang emits the dwarf information of global alias variable as
> DW_TAG_imported_declaration, gdb does not handle it. GDB reads this tag
> as C++/fortran imported declaration (type alias, namespace alias and fortran
> module). Added support to handle this tag as alias variable.
>
> This change fixes the failure in gdb.base/symbol-alias.exp testcase.
> This testcase is also updated to test nested (recursive) alias.
> ---
>  gdb/dwarf2/read.c                       | 60 ++++++++++++++---------
>  gdb/testsuite/gdb.base/symbol-alias.exp | 63
> ++++++++++++++++++++++++-  gdb/testsuite/gdb.base/symbol-alias2.c  |
> 16 +++++++
>  3 files changed, 116 insertions(+), 23 deletions(-)
>
> diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index
> 6dcd446e5f4..d0c95459d8f 100644
> --- a/gdb/dwarf2/read.c
> +++ b/gdb/dwarf2/read.c
> @@ -957,6 +957,10 @@ static void build_type_psymtabs_reader
> (cutu_reader *reader,
>
>  static void dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile);
>
> +static void var_decode_location (struct attribute *attr,
> +                              struct symbol *sym,
> +                              struct dwarf2_cu *cu);
> +
>  static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);
>
>  static const gdb_byte *read_attribute (const struct die_reader_specs *, @@
> -1134,7 +1138,7 @@ static struct using_direct **using_directives (struct
> dwarf2_cu *cu);
>
>  static void read_import_statement (struct die_info *die, struct dwarf2_cu
> *);
>
> -static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
> +static bool read_alias (struct die_info *die, struct dwarf2_cu *cu);
>
>  static struct type *read_module_type (struct die_info *die,
>                                     struct dwarf2_cu *cu);
> @@ -8728,9 +8732,9 @@ process_die (struct die_info *die, struct dwarf2_cu
> *cu)
>        break;
>      case DW_TAG_imported_declaration:
>        cu->processing_has_namespace_info = true;
> -      if (read_namespace_alias (die, cu))
> +      if (read_alias (die, cu))
>       break;
> -      /* The declaration is not a global namespace alias.  */
> +      /* The declaration is not a global namespace or variable alias.
> + */
>        /* Fall through.  */
>      case DW_TAG_imported_module:
>        cu->processing_has_namespace_info = true; @@ -9198,18 +9202,19 @@
> dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu
> *cu)
>    return retval;
>  }
>
> -/* Inspect DIE in CU for a namespace alias.  If one exists, record
> -   a new symbol for it.
> +/* Inspect DIE in CU for a namespace alias or a variable
> +   with alias attribute. If one exists, record a new symbol
> +   for it.
>
> -   Returns 1 if a namespace alias was recorded, 0 otherwise.  */
> +   Returns "true" if an alias was recorded, "false" otherwise.  */
>
> -static int
> -read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
> +static bool
> +read_alias (struct die_info *die, struct dwarf2_cu *cu)
>  {
>    struct attribute *attr;
>
> -  /* If the die does not have a name, this is not a namespace
> -     alias.  */
> +  /* If the die does not have a name, this is not a namespace alias
> +     or variable alias.  */
>    attr = dwarf2_attr (die, DW_AT_name, cu);
>    if (attr != NULL)
>      {
> @@ -9235,26 +9240,39 @@ read_namespace_alias (struct die_info *die,
> struct dwarf2_cu *cu)
>       {
>         complaint (_("DIE at %s has too many recursively imported "
>                      "declarations"), sect_offset_str (d->sect_off));
> -       return 0;
> +       return false;
>       }
>
>        if (attr != NULL)
>       {
>         struct type *type;
> -       sect_offset sect_off = attr->get_ref_die_offset ();
> -
> -       type = get_die_type_at_offset (sect_off, cu->per_cu, cu-
> >per_objfile);
> -       if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
> +       if (d->tag == DW_TAG_variable)
>           {
> -           /* This declaration is a global namespace alias.  Add
> -              a symbol for it whose type is the aliased namespace.  */
> -           new_symbol (die, type, cu);
> -           return 1;
> +           /* This declaration is a C/C++ global variable alias. Add
> +              a symbol for it whose type is same as aliased variable.  */
> +           type = die_type (d, imported_cu);
> +           struct symbol *sym = new_symbol (die, type, cu);
> +           attr = dwarf2_attr (d, DW_AT_location, imported_cu);
> +           sym->set_aclass_index (LOC_UNRESOLVED);
> +           if (attr != nullptr)
> +             var_decode_location (attr, sym, cu);
> +           return true;
> +         }
> +       else
> +         {
> +           sect_offset sect_off = attr->get_ref_die_offset ();
> +           type = get_die_type_at_offset (sect_off, cu->per_cu, cu-
> >per_objfile);
> +           if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
> +             {
> +               /* This declaration is a global namespace alias. Add
> +                  a symbol for it whose type is the aliased namespace.  */
> +               new_symbol (die, type, cu);
> +               return true;
> +             }
>           }
>       }
>      }
> -
> -  return 0;
> +  return false;
>  }
>
>  /* Return the using directives repository (global or local?) to use in the diff --
> git a/gdb/testsuite/gdb.base/symbol-alias.exp
> b/gdb/testsuite/gdb.base/symbol-alias.exp
> index 2b53cc31053..1024954b0cb 100644
> --- a/gdb/testsuite/gdb.base/symbol-alias.exp
> +++ b/gdb/testsuite/gdb.base/symbol-alias.exp
> @@ -15,6 +15,9 @@
>  # along with this program.  If not, see <http://www.gnu.org/licenses/>.
>
>  standard_testfile symbol-alias.c symbol-alias2.c
> +set using_clang [test_compiler_info clang-*] set old_clang [expr
> +[test_compiler_info {clang-1[0-3]-*-*}] \
> +              || [test_compiler_info {clang-[1-9]-*}]]
>
>  if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile $srcfile2]]
> } {
>      return -1
> @@ -31,6 +34,62 @@ foreach f {"func" "func_alias"} {  }
>
>  # Variables.
> -foreach v {"g_var_s" "g_var_s_alias"} {
> -    gdb_test "p $v" "= {field1 = 1, field2 = 2}"
> +gdb_test "p g_var_s" "= {field1 = 1, field2 = 2}"
> +foreach v {"g_var_s_alias" "g_var_s_alias2"} {
> +    gdb_test_multiple "p $v" "print alias variable $v" {
> +     -re -wrap " = {field1 = 1, field2 = 2}" {
> +         pass $gdb_test_name
> +     }
> +     -re -wrap "has unknown type; cast it to its declared type" {
> +         if { $old_clang } {
> +             xfail $gdb_test_name
> +         } else {
> +             fail $gdb_test_name
> +         }
> +     }
> +    }
> +}
> +
> +# Static Variable.
> +gdb_test "p g_var" " = 1"
> +gdb_test_multiple "p g_var_alias" "print alias of static variable" {
> +    -re -wrap " = 1" {
> +     pass $gdb_test_name
> +    }
> +    -re -wrap "has unknown type; cast it to its declared type" {
> +     if { $old_clang } {
> +       xfail $gdb_test_name
> +     } else {
> +       fail $gdb_test_name
> +     }
> +    }
> +}
> +
> +# Deferred Variable.
> +gdb_test "p g_def_var" " = 2"
> +gdb_test_multiple "p g_def_var_alias" "print alias of deferred variable" {
> +    -re -wrap " = 2" {
> +     pass $gdb_test_name
> +    }
> +    -re -wrap "has unknown type; cast it to its declared type" {
> +     if { $using_clang } {
> +       xfail $gdb_test_name
> +     } else {
> +       fail $gdb_test_name
> +     }
> +    }
> +}
> +
> +# Alias of deferred Variable alias.
> +gdb_test_multiple "p g_def_var2_alias2" "print alias of alias of deferred
> variable" {
> +    -re -wrap " = 3" {
> +     pass $gdb_test_name
> +    }
> +    -re -wrap "has unknown type; cast it to its declared type" {
> +     if { $old_clang } {
> +       xfail $gdb_test_name
> +     } else {
> +       fail $gdb_test_name
> +     }
> +    }
>  }
> diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c
> b/gdb/testsuite/gdb.base/symbol-alias2.c
> index 34f4e121e25..41d4b6a53e5 100644
> --- a/gdb/testsuite/gdb.base/symbol-alias2.c
> +++ b/gdb/testsuite/gdb.base/symbol-alias2.c
> @@ -23,6 +23,8 @@ struct S
>
>  struct S g_var_s = { 1, 2 };
>
> +static int g_var = 1;
> +
>  #ifdef __cplusplus
>  /* So that the alias attribute below work without having to figure out
>     this function's mangled name.  */
> @@ -38,3 +40,17 @@ func (void)
>  struct S *func_alias (void) __attribute__ ((alias ("func")));
>
>  extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));
> +
> +extern struct S g_var_s_alias2 __attribute__ ((alias
> +("g_var_s_alias")));
> +
> +extern int g_var_alias __attribute__ ((alias ("g_var")));
> +
> +extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
> +
> +int g_def_var = 2;
> +
> +extern int g_def_var2_alias __attribute__ ((alias ("g_def_var2")));
> +
> +int g_def_var2 = 3;
> +
> +extern int g_def_var2_alias2 __attribute__ ((alias
> +("g_def_var2_alias")));
> --
> 2.25.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [PATCH] Debug support for global alias variable
  2022-04-20 12:17                         ` Natarajan, Kavitha
  2022-04-25 13:10                           ` Natarajan, Kavitha
@ 2022-05-05  9:53                           ` Natarajan, Kavitha
  2022-06-07  9:08                           ` Natarajan, Kavitha
  2 siblings, 0 replies; 28+ messages in thread
From: Natarajan, Kavitha @ 2022-05-05  9:53 UTC (permalink / raw)
  To: Pedro Alves, Tom Tromey, Natarajan, Kavitha via Gdb-patches
  Cc: George, Jini Susan, Parasuraman, Hariharan

[Public]

Ping!

>
> > Could you please go over the patch tweaking the new gdb_test_multiple
> > calls to follow the same pattern, please?
> >
>
> Thank you Pedro for your suggestions. I have incorporated the changes for all
> get_test_multiple calls and updated the patch.
>
> Regards,
> Kavitha

^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [PATCH] Debug support for global alias variable
  2022-04-20 12:17                         ` Natarajan, Kavitha
  2022-04-25 13:10                           ` Natarajan, Kavitha
  2022-05-05  9:53                           ` Natarajan, Kavitha
@ 2022-06-07  9:08                           ` Natarajan, Kavitha
  2022-06-08 16:29                             ` Pedro Alves
  2 siblings, 1 reply; 28+ messages in thread
From: Natarajan, Kavitha @ 2022-06-07  9:08 UTC (permalink / raw)
  To: Pedro Alves, Tom Tromey, Natarajan, Kavitha via Gdb-patches
  Cc: George, Jini Susan, Parasuraman, Hariharan

[AMD Official Use Only]

Ping!

Can I push this patch? Can someone please approve?

Below are the related communications for your reference:
https://sourceware.org/pipermail/gdb-patches/2022-March/186329.html
https://sourceware.org/pipermail/gdb-patches/2022-April/187448.html

I am also attaching the rebased patch here.

Regards,
Kavitha
==============================================================
When clang emits the dwarf information of global alias variable
as DW_TAG_imported_declaration, gdb does not handle it. GDB reads
this tag as C++/fortran imported declaration (type alias, namespace
alias and fortran module). Added support to handle this tag as
alias variable.

This change fixes the failure in gdb.base/symbol-alias.exp testcase.
This testcase is also updated to test nested (recursive) alias.
---
 gdb/dwarf2/read.c                       | 60 ++++++++++++++---------
 gdb/testsuite/gdb.base/symbol-alias.exp | 63 ++++++++++++++++++++++++-
 gdb/testsuite/gdb.base/symbol-alias2.c  | 16 +++++++
 3 files changed, 116 insertions(+), 23 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 848fd5627b8..972af77c5fd 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -894,6 +894,10 @@ static void build_type_psymtabs_reader (cutu_reader *reader,

 static void dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile);

+static void var_decode_location (struct attribute *attr,
+                                struct symbol *sym,
+                                struct dwarf2_cu *cu);
+
 static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);

 static const gdb_byte *read_attribute (const struct die_reader_specs *,
@@ -1071,7 +1075,7 @@ static struct using_direct **using_directives (struct dwarf2_cu *cu);

 static void read_import_statement (struct die_info *die, struct dwarf2_cu *);

-static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
+static bool read_alias (struct die_info *die, struct dwarf2_cu *cu);

 static struct type *read_module_type (struct die_info *die,
                                      struct dwarf2_cu *cu);
@@ -8679,9 +8683,9 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
       break;
     case DW_TAG_imported_declaration:
       cu->processing_has_namespace_info = true;
-      if (read_namespace_alias (die, cu))
+      if (read_alias (die, cu))
        break;
-      /* The declaration is not a global namespace alias.  */
+      /* The declaration is not a global namespace or variable alias.  */
       /* Fall through.  */
     case DW_TAG_imported_module:
       cu->processing_has_namespace_info = true;
@@ -9149,18 +9153,19 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
   return retval;
 }

-/* Inspect DIE in CU for a namespace alias.  If one exists, record
-   a new symbol for it.
+/* Inspect DIE in CU for a namespace alias or a variable
+   with alias attribute. If one exists, record a new symbol
+   for it.

-   Returns 1 if a namespace alias was recorded, 0 otherwise.  */
+   Returns "true" if an alias was recorded, "false" otherwise.  */

-static int
-read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
+static bool
+read_alias (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct attribute *attr;

-  /* If the die does not have a name, this is not a namespace
-     alias.  */
+  /* If the die does not have a name, this is not a namespace alias
+     or variable alias.  */
   attr = dwarf2_attr (die, DW_AT_name, cu);
   if (attr != NULL)
     {
@@ -9186,26 +9191,39 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
        {
          complaint (_("DIE at %s has too many recursively imported "
                       "declarations"), sect_offset_str (d->sect_off));
-         return 0;
+         return false;
        }

       if (attr != NULL)
        {
          struct type *type;
-         sect_offset sect_off = attr->get_ref_die_offset ();
-
-         type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
-         if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+         if (d->tag == DW_TAG_variable)
            {
-             /* This declaration is a global namespace alias.  Add
-                a symbol for it whose type is the aliased namespace.  */
-             new_symbol (die, type, cu);
-             return 1;
+             /* This declaration is a C/C++ global variable alias. Add
+                a symbol for it whose type is same as aliased variable.  */
+             type = die_type (d, imported_cu);
+             struct symbol *sym = new_symbol (die, type, cu);
+             attr = dwarf2_attr (d, DW_AT_location, imported_cu);
+             sym->set_aclass_index (LOC_UNRESOLVED);
+             if (attr != nullptr)
+               var_decode_location (attr, sym, cu);
+             return true;
+           }
+         else
+           {
+             sect_offset sect_off = attr->get_ref_die_offset ();
+             type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
+             if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+               {
+                 /* This declaration is a global namespace alias. Add
+                    a symbol for it whose type is the aliased namespace.  */
+                 new_symbol (die, type, cu);
+                 return true;
+               }
            }
        }
     }
-
-  return 0;
+  return false;
 }

 /* Return the using directives repository (global or local?) to use in the
diff --git a/gdb/testsuite/gdb.base/symbol-alias.exp b/gdb/testsuite/gdb.base/symbol-alias.exp
index 289f49bbc3f..564b43086bc 100644
--- a/gdb/testsuite/gdb.base/symbol-alias.exp
+++ b/gdb/testsuite/gdb.base/symbol-alias.exp
@@ -15,6 +15,9 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.

 standard_testfile symbol-alias.c symbol-alias2.c
+set using_clang [test_compiler_info clang-*]
+set old_clang [expr [test_compiler_info {clang-1[0-3]-*-*}] \
+                || [test_compiler_info {clang-[1-9]-*}]]

 if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile $srcfile2]] } {
     return -1
@@ -31,6 +34,62 @@ foreach f {"func" "func_alias"} {
 }

 # Variables.
-foreach v {"g_var_s" "g_var_s_alias"} {
-    gdb_test "p $v" "= {field1 = 1, field2 = 2}"
+gdb_test "p g_var_s" "= {field1 = 1, field2 = 2}"
+foreach v {"g_var_s_alias" "g_var_s_alias2"} {
+    gdb_test_multiple "p $v" "print alias variable $v" {
+       -re -wrap " = {field1 = 1, field2 = 2}" {
+           pass $gdb_test_name
+       }
+       -re -wrap "has unknown type; cast it to its declared type" {
+           if { $old_clang } {
+               xfail $gdb_test_name
+           } else {
+               fail $gdb_test_name
+           }
+       }
+    }
+}
+
+# Static Variable.
+gdb_test "p g_var" " = 1"
+gdb_test_multiple "p g_var_alias" "print alias of static variable" {
+    -re -wrap " = 1" {
+       pass $gdb_test_name
+    }
+    -re -wrap "has unknown type; cast it to its declared type" {
+       if { $old_clang } {
+         xfail $gdb_test_name
+       } else {
+         fail $gdb_test_name
+       }
+    }
+}
+
+# Deferred Variable.
+gdb_test "p g_def_var" " = 2"
+gdb_test_multiple "p g_def_var_alias" "print alias of deferred variable" {
+    -re -wrap " = 2" {
+       pass $gdb_test_name
+    }
+    -re -wrap "has unknown type; cast it to its declared type" {
+       if { $using_clang } {
+         xfail $gdb_test_name
+       } else {
+         fail $gdb_test_name
+       }
+    }
+}
+
+# Alias of deferred Variable alias.
+gdb_test_multiple "p g_def_var2_alias2" "print alias of alias of deferred variable" {
+    -re -wrap " = 3" {
+       pass $gdb_test_name
+    }
+    -re -wrap "has unknown type; cast it to its declared type" {
+       if { $old_clang } {
+         xfail $gdb_test_name
+       } else {
+         fail $gdb_test_name
+       }
+    }
 }
diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c b/gdb/testsuite/gdb.base/symbol-alias2.c
index 34f4e121e25..41d4b6a53e5 100644
--- a/gdb/testsuite/gdb.base/symbol-alias2.c
+++ b/gdb/testsuite/gdb.base/symbol-alias2.c
@@ -23,6 +23,8 @@ struct S

 struct S g_var_s = { 1, 2 };

+static int g_var = 1;
+
 #ifdef __cplusplus
 /* So that the alias attribute below work without having to figure out
    this function's mangled name.  */
@@ -38,3 +40,17 @@ func (void)
 struct S *func_alias (void) __attribute__ ((alias ("func")));

 extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));
+
+extern struct S g_var_s_alias2 __attribute__ ((alias ("g_var_s_alias")));
+
+extern int g_var_alias __attribute__ ((alias ("g_var")));
+
+extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
+
+int g_def_var = 2;
+
+extern int g_def_var2_alias __attribute__ ((alias ("g_def_var2")));
+
+int g_def_var2 = 3;
+
+extern int g_def_var2_alias2 __attribute__ ((alias ("g_def_var2_alias")));
--



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] Debug support for global alias variable
  2022-06-07  9:08                           ` Natarajan, Kavitha
@ 2022-06-08 16:29                             ` Pedro Alves
  2022-06-09 11:36                               ` Pedro Alves
  0 siblings, 1 reply; 28+ messages in thread
From: Pedro Alves @ 2022-06-08 16:29 UTC (permalink / raw)
  To: Natarajan, Kavitha, Tom Tromey, Natarajan, Kavitha via Gdb-patches
  Cc: George, Jini Susan, Parasuraman, Hariharan

Hi!

I'm building current llvm to give this a try, and I'll merge it after some testing.

Thanks again for the patch, and sorry for the delays.

On 2022-06-07 10:08, Natarajan, Kavitha wrote:
> [AMD Official Use Only]
> 
> Ping!
> 
> Can I push this patch? Can someone please approve?
> 
> Below are the related communications for your reference:
> https://sourceware.org/pipermail/gdb-patches/2022-March/186329.html
> https://sourceware.org/pipermail/gdb-patches/2022-April/187448.html
> 
> I am also attaching the rebased patch here.
> 
> Regards,
> Kavitha
> ==============================================================
> When clang emits the dwarf information of global alias variable
> as DW_TAG_imported_declaration, gdb does not handle it. GDB reads
> this tag as C++/fortran imported declaration (type alias, namespace
> alias and fortran module). Added support to handle this tag as
> alias variable.
> 
> This change fixes the failure in gdb.base/symbol-alias.exp testcase.
> This testcase is also updated to test nested (recursive) alias.
> ---
>  gdb/dwarf2/read.c                       | 60 ++++++++++++++---------
>  gdb/testsuite/gdb.base/symbol-alias.exp | 63 ++++++++++++++++++++++++-
>  gdb/testsuite/gdb.base/symbol-alias2.c  | 16 +++++++
>  3 files changed, 116 insertions(+), 23 deletions(-)
> 
> diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
> index 848fd5627b8..972af77c5fd 100644
> --- a/gdb/dwarf2/read.c
> +++ b/gdb/dwarf2/read.c
> @@ -894,6 +894,10 @@ static void build_type_psymtabs_reader (cutu_reader *reader,
> 
>  static void dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile);
> 
> +static void var_decode_location (struct attribute *attr,
> +                                struct symbol *sym,
> +                                struct dwarf2_cu *cu);
> +
>  static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);
> 
>  static const gdb_byte *read_attribute (const struct die_reader_specs *,
> @@ -1071,7 +1075,7 @@ static struct using_direct **using_directives (struct dwarf2_cu *cu);
> 
>  static void read_import_statement (struct die_info *die, struct dwarf2_cu *);
> 
> -static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
> +static bool read_alias (struct die_info *die, struct dwarf2_cu *cu);
> 
>  static struct type *read_module_type (struct die_info *die,
>                                       struct dwarf2_cu *cu);
> @@ -8679,9 +8683,9 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
>        break;
>      case DW_TAG_imported_declaration:
>        cu->processing_has_namespace_info = true;
> -      if (read_namespace_alias (die, cu))
> +      if (read_alias (die, cu))
>         break;
> -      /* The declaration is not a global namespace alias.  */
> +      /* The declaration is not a global namespace or variable alias.  */
>        /* Fall through.  */
>      case DW_TAG_imported_module:
>        cu->processing_has_namespace_info = true;
> @@ -9149,18 +9153,19 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
>    return retval;
>  }
> 
> -/* Inspect DIE in CU for a namespace alias.  If one exists, record
> -   a new symbol for it.
> +/* Inspect DIE in CU for a namespace alias or a variable
> +   with alias attribute. If one exists, record a new symbol
> +   for it.
> 
> -   Returns 1 if a namespace alias was recorded, 0 otherwise.  */
> +   Returns "true" if an alias was recorded, "false" otherwise.  */
> 
> -static int
> -read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
> +static bool
> +read_alias (struct die_info *die, struct dwarf2_cu *cu)
>  {
>    struct attribute *attr;
> 
> -  /* If the die does not have a name, this is not a namespace
> -     alias.  */
> +  /* If the die does not have a name, this is not a namespace alias
> +     or variable alias.  */
>    attr = dwarf2_attr (die, DW_AT_name, cu);
>    if (attr != NULL)
>      {
> @@ -9186,26 +9191,39 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
>         {
>           complaint (_("DIE at %s has too many recursively imported "
>                        "declarations"), sect_offset_str (d->sect_off));
> -         return 0;
> +         return false;
>         }
> 
>        if (attr != NULL)
>         {
>           struct type *type;
> -         sect_offset sect_off = attr->get_ref_die_offset ();
> -
> -         type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
> -         if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
> +         if (d->tag == DW_TAG_variable)
>             {
> -             /* This declaration is a global namespace alias.  Add
> -                a symbol for it whose type is the aliased namespace.  */
> -             new_symbol (die, type, cu);
> -             return 1;
> +             /* This declaration is a C/C++ global variable alias. Add
> +                a symbol for it whose type is same as aliased variable.  */
> +             type = die_type (d, imported_cu);
> +             struct symbol *sym = new_symbol (die, type, cu);
> +             attr = dwarf2_attr (d, DW_AT_location, imported_cu);
> +             sym->set_aclass_index (LOC_UNRESOLVED);
> +             if (attr != nullptr)
> +               var_decode_location (attr, sym, cu);
> +             return true;
> +           }
> +         else
> +           {
> +             sect_offset sect_off = attr->get_ref_die_offset ();
> +             type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
> +             if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
> +               {
> +                 /* This declaration is a global namespace alias. Add
> +                    a symbol for it whose type is the aliased namespace.  */
> +                 new_symbol (die, type, cu);
> +                 return true;
> +               }
>             }
>         }
>      }
> -
> -  return 0;
> +  return false;
>  }
> 
>  /* Return the using directives repository (global or local?) to use in the
> diff --git a/gdb/testsuite/gdb.base/symbol-alias.exp b/gdb/testsuite/gdb.base/symbol-alias.exp
> index 289f49bbc3f..564b43086bc 100644
> --- a/gdb/testsuite/gdb.base/symbol-alias.exp
> +++ b/gdb/testsuite/gdb.base/symbol-alias.exp
> @@ -15,6 +15,9 @@
>  # along with this program.  If not, see <http://www.gnu.org/licenses/>.
> 
>  standard_testfile symbol-alias.c symbol-alias2.c
> +set using_clang [test_compiler_info clang-*]
> +set old_clang [expr [test_compiler_info {clang-1[0-3]-*-*}] \
> +                || [test_compiler_info {clang-[1-9]-*}]]
> 
>  if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile $srcfile2]] } {
>      return -1
> @@ -31,6 +34,62 @@ foreach f {"func" "func_alias"} {
>  }
> 
>  # Variables.
> -foreach v {"g_var_s" "g_var_s_alias"} {
> -    gdb_test "p $v" "= {field1 = 1, field2 = 2}"
> +gdb_test "p g_var_s" "= {field1 = 1, field2 = 2}"
> +foreach v {"g_var_s_alias" "g_var_s_alias2"} {
> +    gdb_test_multiple "p $v" "print alias variable $v" {
> +       -re -wrap " = {field1 = 1, field2 = 2}" {
> +           pass $gdb_test_name
> +       }
> +       -re -wrap "has unknown type; cast it to its declared type" {
> +           if { $old_clang } {
> +               xfail $gdb_test_name
> +           } else {
> +               fail $gdb_test_name
> +           }
> +       }
> +    }
> +}
> +
> +# Static Variable.
> +gdb_test "p g_var" " = 1"
> +gdb_test_multiple "p g_var_alias" "print alias of static variable" {
> +    -re -wrap " = 1" {
> +       pass $gdb_test_name
> +    }
> +    -re -wrap "has unknown type; cast it to its declared type" {
> +       if { $old_clang } {
> +         xfail $gdb_test_name
> +       } else {
> +         fail $gdb_test_name
> +       }
> +    }
> +}
> +
> +# Deferred Variable.
> +gdb_test "p g_def_var" " = 2"
> +gdb_test_multiple "p g_def_var_alias" "print alias of deferred variable" {
> +    -re -wrap " = 2" {
> +       pass $gdb_test_name
> +    }
> +    -re -wrap "has unknown type; cast it to its declared type" {
> +       if { $using_clang } {
> +         xfail $gdb_test_name
> +       } else {
> +         fail $gdb_test_name
> +       }
> +    }
> +}
> +
> +# Alias of deferred Variable alias.
> +gdb_test_multiple "p g_def_var2_alias2" "print alias of alias of deferred variable" {
> +    -re -wrap " = 3" {
> +       pass $gdb_test_name
> +    }
> +    -re -wrap "has unknown type; cast it to its declared type" {
> +       if { $old_clang } {
> +         xfail $gdb_test_name
> +       } else {
> +         fail $gdb_test_name
> +       }
> +    }
>  }
> diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c b/gdb/testsuite/gdb.base/symbol-alias2.c
> index 34f4e121e25..41d4b6a53e5 100644
> --- a/gdb/testsuite/gdb.base/symbol-alias2.c
> +++ b/gdb/testsuite/gdb.base/symbol-alias2.c
> @@ -23,6 +23,8 @@ struct S
> 
>  struct S g_var_s = { 1, 2 };
> 
> +static int g_var = 1;
> +
>  #ifdef __cplusplus
>  /* So that the alias attribute below work without having to figure out
>     this function's mangled name.  */
> @@ -38,3 +40,17 @@ func (void)
>  struct S *func_alias (void) __attribute__ ((alias ("func")));
> 
>  extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));
> +
> +extern struct S g_var_s_alias2 __attribute__ ((alias ("g_var_s_alias")));
> +
> +extern int g_var_alias __attribute__ ((alias ("g_var")));
> +
> +extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
> +
> +int g_def_var = 2;
> +
> +extern int g_def_var2_alias __attribute__ ((alias ("g_def_var2")));
> +
> +int g_def_var2 = 3;
> +
> +extern int g_def_var2_alias2 __attribute__ ((alias ("g_def_var2_alias")));
> --
> 
> 


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] Debug support for global alias variable
  2022-06-08 16:29                             ` Pedro Alves
@ 2022-06-09 11:36                               ` Pedro Alves
  2022-06-13 11:11                                 ` Natarajan, Kavitha
  0 siblings, 1 reply; 28+ messages in thread
From: Pedro Alves @ 2022-06-09 11:36 UTC (permalink / raw)
  To: Natarajan, Kavitha, Tom Tromey, Natarajan, Kavitha via Gdb-patches
  Cc: George, Jini Susan, Parasuraman, Hariharan

On 2022-06-08 17:29, Pedro Alves wrote:
> Hi!
> 
> I'm building current llvm to give this a try, and I'll merge it after some testing.
> 
> Thanks again for the patch, and sorry for the delays.
> 

I've now given it some testing, and I have some questions.

>>  /* Return the using directives repository (global or local?) to use in the
>> diff --git a/gdb/testsuite/gdb.base/symbol-alias.exp b/gdb/testsuite/gdb.base/symbol-alias.exp
>> index 289f49bbc3f..564b43086bc 100644
>> --- a/gdb/testsuite/gdb.base/symbol-alias.exp
>> +++ b/gdb/testsuite/gdb.base/symbol-alias.exp
>> @@ -15,6 +15,9 @@
>>  # along with this program.  If not, see <http://www.gnu.org/licenses/>.
>>
>>  standard_testfile symbol-alias.c symbol-alias2.c
>> +set using_clang [test_compiler_info clang-*]
>> +set old_clang [expr [test_compiler_info {clang-1[0-3]-*-*}] \
>> +                || [test_compiler_info {clang-[1-9]-*}]]

These could use a short comment (see bottom of this email).

Also, this assumes the fix will be in Clang 14, but Clang 14 has been released recently, and your
fix will only be in Clang 15, right?  I caught this because in addition to testing against current
main LLVM, I tested against a ROCm bundled Clang I had handy, which happens to be based on a LLVM
that identifies as 14, and the tests FAILed, instead of XFAILing.  I think that above we
want "clang-1[0-4]" instead of "clang-1[0-3]", right?

>>
>>  if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile $srcfile2]] } {
>>      return -1
>> @@ -31,6 +34,62 @@ foreach f {"func" "func_alias"} {
>>  }
>>
>>  # Variables.
>> -foreach v {"g_var_s" "g_var_s_alias"} {
>> -    gdb_test "p $v" "= {field1 = 1, field2 = 2}"
>> +gdb_test "p g_var_s" "= {field1 = 1, field2 = 2}"
>> +foreach v {"g_var_s_alias" "g_var_s_alias2"} {
>> +    gdb_test_multiple "p $v" "print alias variable $v" {
>> +       -re -wrap " = {field1 = 1, field2 = 2}" {
>> +           pass $gdb_test_name
>> +       }
>> +       -re -wrap "has unknown type; cast it to its declared type" {
>> +           if { $old_clang } {
>> +               xfail $gdb_test_name
>> +           } else {
>> +               fail $gdb_test_name
>> +           }
>> +       }
>> +    }
>> +}
>> +
>> +# Static Variable.
>> +gdb_test "p g_var" " = 1"
>> +gdb_test_multiple "p g_var_alias" "print alias of static variable" {
>> +    -re -wrap " = 1" {
>> +       pass $gdb_test_name
>> +    }
>> +    -re -wrap "has unknown type; cast it to its declared type" {
>> +       if { $old_clang } {
>> +         xfail $gdb_test_name
>> +       } else {
>> +         fail $gdb_test_name
>> +       }
>> +    }
>> +}
>> +
>> +# Deferred Variable.

I had never heard the term "deferred variable" before.  IIUC, it refers to the case
of the alias aliasing a name that has not been seen in scope yet.  Is this term
"deferred variable" a term you invented, or did you find it elsewhere?  I'm just curious,
and pondering adding a comment.

>> +gdb_test "p g_def_var" " = 2"
>> +gdb_test_multiple "p g_def_var_alias" "print alias of deferred variable" {
>> +    -re -wrap " = 2" {
>> +       pass $gdb_test_name
>> +    }
>> +    -re -wrap "has unknown type; cast it to its declared type" {
>> +       if { $using_clang } {

So all other tests pass with your fixed Clang, but this one will still xfail.
Do you have more information about this?  Strange offhand that "alias of alias" works,
but this one doesn't.  Is there some Clang bug open about this we could add a reference
to here?  If not, could one be created?  If instead you think this is a GDB bug,
then this should be a kfail ("known gdb fail") instead of an xfail, in which case we
should have a bug open in gdb's bugzilla about it so we can reference it here.

>> +         xfail $gdb_test_name
>> +       } else {
>> +         fail $gdb_test_name
>> +       }
>> +    }
>> +}
>> +
>> +# Alias of deferred Variable alias.
>> +gdb_test_multiple "p g_def_var2_alias2" "print alias of alias of deferred variable" {
>> +    -re -wrap " = 3" {
>> +       pass $gdb_test_name
>> +    }
>> +    -re -wrap "has unknown type; cast it to its declared type" {
>> +       if { $old_clang } {
>> +         xfail $gdb_test_name
>> +       } else {
>> +         fail $gdb_test_name
>> +       }
>> +    }
>>  }
>> diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c b/gdb/testsuite/gdb.base/symbol-alias2.c
>> index 34f4e121e25..41d4b6a53e5 100644
>> --- a/gdb/testsuite/gdb.base/symbol-alias2.c
>> +++ b/gdb/testsuite/gdb.base/symbol-alias2.c
>> @@ -23,6 +23,8 @@ struct S
>>
>>  struct S g_var_s = { 1, 2 };
>>
>> +static int g_var = 1;
>> +
>>  #ifdef __cplusplus
>>  /* So that the alias attribute below work without having to figure out
>>     this function's mangled name.  */
>> @@ -38,3 +40,17 @@ func (void)
>>  struct S *func_alias (void) __attribute__ ((alias ("func")));
>>
>>  extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));
>> +
>> +extern struct S g_var_s_alias2 __attribute__ ((alias ("g_var_s_alias")));
>> +
>> +extern int g_var_alias __attribute__ ((alias ("g_var")));
>> +
>> +extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
>> +
>> +int g_def_var = 2;
>> +
>> +extern int g_def_var2_alias __attribute__ ((alias ("g_def_var2")));
>> +
>> +int g_def_var2 = 3;

Offhand, there doesn't seem to be any difference between g_def_var_alias
and g_def_var2_alias?  If we really need both, then I'm thinking this could
use some comment.

>> +
>> +extern int g_def_var2_alias2 __attribute__ ((alias ("g_def_var2_alias")));
>> --
>>
>>
> 

Here's a slightly tweaked version of your patch, that I am aiming at merging, once we resolve
the nits pointed out above.  It just tweaks/adds comments in the code and the commit log,
and tweaks formatting to be a bit more in line with GDB conventions.  Please double check.

From 6a2748a6af5ed9ea266f115f73d603e4d0536db7 Mon Sep 17 00:00:00 2001
From: Kavitha Natarajan <kavitha.natarajan@amd.com>
Date: Mon, 18 Apr 2022 14:53:55 +0530
Subject: [PATCH] Debug support for global alias variable

Starting with (future) Clang 15 (since
https://reviews.llvm.org/D120989), Clang emits the DWARF information
of global alias variables as DW_TAG_imported_declaration.  However,
GDB does not handle it.  It incorrectly always reads this tag as
C++/Fortran imported declaration (type alias, namespace alias and
Fortran module).  This commit adds support to handle this tag as an
alias variable.

This change fixes the failures in the gdb.base/symbol-alias.exp
testcase with current git Clang.  This testcase is also updated to
test nested (recursive) aliases.

Change-Id: Ief83123f8c77b31751c00404c7521c9b86de74dd
---
 gdb/dwarf2/read.c                       | 63 +++++++++++++++--------
 gdb/testsuite/gdb.base/symbol-alias.exp | 66 +++++++++++++++++++++++--
 gdb/testsuite/gdb.base/symbol-alias2.c  | 16 ++++++
 3 files changed, 121 insertions(+), 24 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 696277d931a..66af99df083 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -894,6 +894,10 @@ static void build_type_psymtabs_reader (cutu_reader *reader,
 
 static void dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile);
 
+static void var_decode_location (struct attribute *attr,
+				 struct symbol *sym,
+				 struct dwarf2_cu *cu);
+
 static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);
 
 static const gdb_byte *read_attribute (const struct die_reader_specs *,
@@ -1071,7 +1075,7 @@ static struct using_direct **using_directives (struct dwarf2_cu *cu);
 
 static void read_import_statement (struct die_info *die, struct dwarf2_cu *);
 
-static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
+static bool read_alias (struct die_info *die, struct dwarf2_cu *cu);
 
 static struct type *read_module_type (struct die_info *die,
 				      struct dwarf2_cu *cu);
@@ -8676,9 +8680,10 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
       break;
     case DW_TAG_imported_declaration:
       cu->processing_has_namespace_info = true;
-      if (read_namespace_alias (die, cu))
+      if (read_alias (die, cu))
 	break;
-      /* The declaration is not a global namespace alias.  */
+      /* The declaration is neither a global namespace nor a variable
+	 alias.  */
       /* Fall through.  */
     case DW_TAG_imported_module:
       cu->processing_has_namespace_info = true;
@@ -9146,18 +9151,18 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
   return retval;
 }
 
-/* Inspect DIE in CU for a namespace alias.  If one exists, record
-   a new symbol for it.
+/* Inspect DIE in CU for a namespace alias or a variable with alias
+   attribute.  If one exists, record a new symbol for it.
 
-   Returns 1 if a namespace alias was recorded, 0 otherwise.  */
+   Returns true if an alias was recorded, false otherwise.  */
 
-static int
-read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
+static bool
+read_alias (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct attribute *attr;
 
-  /* If the die does not have a name, this is not a namespace
-     alias.  */
+  /* If the die does not have a name, this is neither a namespace
+     alias nor a variable alias.  */
   attr = dwarf2_attr (die, DW_AT_name, cu);
   if (attr != NULL)
     {
@@ -9183,26 +9188,42 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
 	{
 	  complaint (_("DIE at %s has too many recursively imported "
 		       "declarations"), sect_offset_str (d->sect_off));
-	  return 0;
+	  return false;
 	}
 
       if (attr != NULL)
 	{
 	  struct type *type;
-	  sect_offset sect_off = attr->get_ref_die_offset ();
-
-	  type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
-	  if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+	  if (d->tag == DW_TAG_variable)
 	    {
-	      /* This declaration is a global namespace alias.  Add
-		 a symbol for it whose type is the aliased namespace.  */
-	      new_symbol (die, type, cu);
-	      return 1;
+	      /* This declaration is a C/C++ global variable alias.
+		 Add a symbol for it whose type is the same as the
+		 aliased variable's.  */
+	      type = die_type (d, imported_cu);
+	      struct symbol *sym = new_symbol (die, type, cu);
+	      attr = dwarf2_attr (d, DW_AT_location, imported_cu);
+	      sym->set_aclass_index (LOC_UNRESOLVED);
+	      if (attr != nullptr)
+		var_decode_location (attr, sym, cu);
+	      return true;
+	    }
+	  else
+	    {
+	      sect_offset sect_off = attr->get_ref_die_offset ();
+	      type = get_die_type_at_offset (sect_off, cu->per_cu,
+					     cu->per_objfile);
+	      if (type != nullptr && type->code () == TYPE_CODE_NAMESPACE)
+		{
+		  /* This declaration is a global namespace alias. Add
+		     a symbol for it whose type is the aliased
+		     namespace.  */
+		  new_symbol (die, type, cu);
+		  return true;
+		}
 	    }
 	}
     }
-
-  return 0;
+  return false;
 }
 
 /* Return the using directives repository (global or local?) to use in the
diff --git a/gdb/testsuite/gdb.base/symbol-alias.exp b/gdb/testsuite/gdb.base/symbol-alias.exp
index 289f49bbc3f..a944928b415 100644
--- a/gdb/testsuite/gdb.base/symbol-alias.exp
+++ b/gdb/testsuite/gdb.base/symbol-alias.exp
@@ -15,6 +15,10 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 standard_testfile symbol-alias.c symbol-alias2.c
+set using_clang [test_compiler_info clang-*]
+# Clang versions prior to v15 do not emit debug info for aliases.
+set old_clang [expr [test_compiler_info {clang-1[0-4]-*-*}] \
+		 || [test_compiler_info {clang-[1-9]-*}]]
 
 if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile $srcfile2]] } {
     return -1
@@ -30,7 +34,63 @@ foreach f {"func" "func_alias"} {
     gdb_test "p *${f}()" "= {field1 = 1, field2 = 2}"
 }
 
-# Variables.
-foreach v {"g_var_s" "g_var_s_alias"} {
-    gdb_test "p $v" "= {field1 = 1, field2 = 2}"
+# Extern global variable.
+gdb_test "p g_var_s" "= {field1 = 1, field2 = 2}"
+foreach v {"g_var_s_alias" "g_var_s_alias2"} {
+    gdb_test_multiple "p $v" "print alias variable $v" {
+	-re -wrap " = {field1 = 1, field2 = 2}" {
+	    pass $gdb_test_name
+	}
+	-re -wrap "has unknown type; cast it to its declared type" {
+	    if { $old_clang } {
+		xfail $gdb_test_name
+	    } else {
+		fail $gdb_test_name
+	    }
+	}
+    }
+}
+
+# Static global variable.
+gdb_test "p g_var" " = 1"
+gdb_test_multiple "p g_var_alias" "print alias of static variable" {
+    -re -wrap " = 1" {
+	pass $gdb_test_name
+    }
+    -re -wrap "has unknown type; cast it to its declared type" {
+	if { $old_clang } {
+	  xfail $gdb_test_name
+	} else {
+	  fail $gdb_test_name
+	}
+    }
+}
+
+# Deferred variable.
+gdb_test "p g_def_var" " = 2"
+gdb_test_multiple "p g_def_var_alias" "print alias of deferred variable" {
+    -re -wrap " = 2" {
+	pass $gdb_test_name
+    }
+    -re -wrap "has unknown type; cast it to its declared type" {
+	if { $using_clang } {
+	  xfail $gdb_test_name
+	} else {
+	  fail $gdb_test_name
+	}
+    }
+}
+
+# Alias of deferred variable alias.
+gdb_test_multiple "p g_def_var2_alias2" "print alias of alias of deferred variable" {
+    -re -wrap " = 3" {
+	pass $gdb_test_name
+    }
+    -re -wrap "has unknown type; cast it to its declared type" {
+	if { $old_clang } {
+	  xfail $gdb_test_name
+	} else {
+	  fail $gdb_test_name
+	}
+    }
 }
diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c b/gdb/testsuite/gdb.base/symbol-alias2.c
index 34f4e121e25..41d4b6a53e5 100644
--- a/gdb/testsuite/gdb.base/symbol-alias2.c
+++ b/gdb/testsuite/gdb.base/symbol-alias2.c
@@ -23,6 +23,8 @@ struct S
 
 struct S g_var_s = { 1, 2 };
 
+static int g_var = 1;
+
 #ifdef __cplusplus
 /* So that the alias attribute below work without having to figure out
    this function's mangled name.  */
@@ -38,3 +40,17 @@ func (void)
 struct S *func_alias (void) __attribute__ ((alias ("func")));
 
 extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));
+
+extern struct S g_var_s_alias2 __attribute__ ((alias ("g_var_s_alias")));
+
+extern int g_var_alias __attribute__ ((alias ("g_var")));
+
+extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
+
+int g_def_var = 2;
+
+extern int g_def_var2_alias __attribute__ ((alias ("g_def_var2")));
+
+int g_def_var2 = 3;
+
+extern int g_def_var2_alias2 __attribute__ ((alias ("g_def_var2_alias")));

base-commit: 5ca5b31d6381ba6d0309e6ae0b1527a852d08a4b
-- 
2.36.0


^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [PATCH] Debug support for global alias variable
  2022-06-09 11:36                               ` Pedro Alves
@ 2022-06-13 11:11                                 ` Natarajan, Kavitha
  2022-06-13 13:54                                   ` Pedro Alves
  0 siblings, 1 reply; 28+ messages in thread
From: Natarajan, Kavitha @ 2022-06-13 11:11 UTC (permalink / raw)
  To: Pedro Alves, Tom Tromey, Natarajan, Kavitha via Gdb-patches
  Cc: George, Jini Susan, Parasuraman, Hariharan

[-- Attachment #1: Type: text/plain, Size: 13401 bytes --]

[AMD Official Use Only - General]

Hi Pedro,

Thanks again for looking into the patch.

> >>  standard_testfile symbol-alias.c symbol-alias2.c
> >> +set using_clang [test_compiler_info clang-*] set old_clang [expr
> >> +[test_compiler_info {clang-1[0-3]-*-*}] \
> >> +                || [test_compiler_info {clang-[1-9]-*}]]
>
> These could use a short comment (see bottom of this email).
>
> Also, this assumes the fix will be in Clang 14, but Clang 14 has been released
> recently, and your fix will only be in Clang 15, right?  I caught this because in
> addition to testing against current main LLVM, I tested against a ROCm
> bundled Clang I had handy, which happens to be based on a LLVM that
> identifies as 14, and the tests FAILed, instead of XFAILing.  I think that above
> we want "clang-1[0-4]" instead of "clang-1[0-3]", right?

Yes, that's right. I had made these changes a while ago and missed to update it
with the version change.

> >> +
> >> +# Deferred Variable.
>
> I had never heard the term "deferred variable" before.  IIUC, it refers to the
> case of the alias aliasing a name that has not been seen in scope yet.  Is this
> term "deferred variable" a term you invented, or did you find it elsewhere?
> I'm just curious, and pondering adding a comment.

Well, if such a term doesn't exist, then I think I would have been influenced by the
clang sources where we refer emitting deferred variable declarations. I shall change
it if it doesn't suit here.

> >> +gdb_test "p g_def_var" " = 2"
> >> +gdb_test_multiple "p g_def_var_alias" "print alias of deferred variable" {
> >> +    -re -wrap " = 2" {
> >> +       pass $gdb_test_name
> >> +    }
> >> +    -re -wrap "has unknown type; cast it to its declared type" {
> >> +       if { $using_clang } {
>
> So all other tests pass with your fixed Clang, but this one will still xfail.
> Do you have more information about this?  Strange offhand that "alias of
> alias" works, but this one doesn't.  Is there some Clang bug open about this
> we could add a reference to here?  If not, could one be created?  If instead
> you think this is a GDB bug, then this should be a kfail ("known gdb fail")
> instead of an xfail, in which case we should have a bug open in gdb's bugzilla
> about it so we can reference it here.

This is a clang bug. For the alias of deferred declaration, clang does not generate
debug information. Clang has to emit the DIE with DW_TAG_imported_declaration tag.
So, this is an expected failure. I can add a comment for the xfail part.

> >> +extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
> >> +
> >> +int g_def_var = 2;
> >> +
> >> +extern int g_def_var2_alias __attribute__ ((alias ("g_def_var2")));
> >> +
> >> +int g_def_var2 = 3;
>
> Offhand, there doesn't seem to be any difference between g_def_var_alias
> and g_def_var2_alias?  If we really need both, then I'm thinking this could
> use some comment.

Yes, they are same. I just wanted to call out the xfail through g_def_var_alias that
no debug information is generated when the aliasee is declared later. In case of
g_def_var2_alias, though its aliasee is declared later, the debug info is generated
(as DW_TAG_variable) when g_def_var2_alias2 accesses it to generate its debug info.
When I am writing this, I am thinking of removing this xfail part itself. Anyway,
g_def_var2_alias would cover the same case when clang is fixed.

> >> +
> >> +extern int g_def_var2_alias2 __attribute__ ((alias
> >> +("g_def_var2_alias")));
> >> --
> >>
> >>
> >
>
> Here's a slightly tweaked version of your patch, that I am aiming at merging,
> once we resolve the nits pointed out above.  It just tweaks/adds comments
> in the code and the commit log, and tweaks formatting to be a bit more in
> line with GDB conventions.  Please double check.

I have made my changes (removing xfail and updating the comments in .exp)
on top of your patch and attached the same.

From 4ec4f0473f2df1468fe25e46c30e4b20b9c207c5 Mon Sep 17 00:00:00 2001
From: Kavitha Natarajan <kavitha.natarajan@amd.com>
Date: Mon, 13 Jun 2022 16:24:24 +0530
Subject: [PATCH] Debug support for global alias variable

Starting with (future) Clang 15 (since
https://reviews.llvm.org/D120989), Clang emits the DWARF information
of global alias variables as DW_TAG_imported_declaration.  However,
GDB does not handle it.  It incorrectly always reads this tag as
C++/Fortran imported declaration (type alias, namespace alias and
Fortran module).  This commit adds support to handle this tag as an
alias variable.

This change fixes the failures in the gdb.base/symbol-alias.exp
testcase with current git Clang.  This testcase is also updated to
test nested (recursive) aliases.
---
 gdb/dwarf2/read.c                       | 63 ++++++++++++++++--------
 gdb/testsuite/gdb.base/symbol-alias.exp | 64 +++++++++++++++++++++++--
 gdb/testsuite/gdb.base/symbol-alias2.c  | 12 +++++
 3 files changed, 115 insertions(+), 24 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 64cb8d421b9..e22e09b4e2b 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -894,6 +894,10 @@ static void build_type_psymtabs_reader (cutu_reader *reader,

 static void dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile);

+static void var_decode_location (struct attribute *attr,
+                                struct symbol *sym,
+                                struct dwarf2_cu *cu);
+
 static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);

 static const gdb_byte *read_attribute (const struct die_reader_specs *,
@@ -1071,7 +1075,7 @@ static struct using_direct **using_directives (struct dwarf2_cu *cu);

 static void read_import_statement (struct die_info *die, struct dwarf2_cu *);

-static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
+static bool read_alias (struct die_info *die, struct dwarf2_cu *cu);

 static struct type *read_module_type (struct die_info *die,
                                      struct dwarf2_cu *cu);
@@ -8664,9 +8668,10 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
       break;
     case DW_TAG_imported_declaration:
       cu->processing_has_namespace_info = true;
-      if (read_namespace_alias (die, cu))
+      if (read_alias (die, cu))
        break;
-      /* The declaration is not a global namespace alias.  */
+      /* The declaration is neither a global namespace nor a variable
+        alias.  */
       /* Fall through.  */
     case DW_TAG_imported_module:
       cu->processing_has_namespace_info = true;
@@ -9134,18 +9139,18 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
   return retval;
 }

-/* Inspect DIE in CU for a namespace alias.  If one exists, record
-   a new symbol for it.
+/* Inspect DIE in CU for a namespace alias or a variable with alias
+   attribute.  If one exists, record a new symbol for it.

-   Returns 1 if a namespace alias was recorded, 0 otherwise.  */
+   Returns true if an alias was recorded, false otherwise.  */

-static int
-read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
+static bool
+read_alias (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct attribute *attr;

-  /* If the die does not have a name, this is not a namespace
-     alias.  */
+  /* If the die does not have a name, this is neither a namespace
+     alias nor a variable alias.  */
   attr = dwarf2_attr (die, DW_AT_name, cu);
   if (attr != NULL)
     {
@@ -9171,26 +9176,42 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
        {
          complaint (_("DIE at %s has too many recursively imported "
                       "declarations"), sect_offset_str (d->sect_off));
-         return 0;
+         return false;
        }

       if (attr != NULL)
        {
          struct type *type;
-         sect_offset sect_off = attr->get_ref_die_offset ();
-
-         type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
-         if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+         if (d->tag == DW_TAG_variable)
            {
-             /* This declaration is a global namespace alias.  Add
-                a symbol for it whose type is the aliased namespace.  */
-             new_symbol (die, type, cu);
-             return 1;
+             /* This declaration is a C/C++ global variable alias.
+                Add a symbol for it whose type is the same as the
+                aliased variable's.  */
+             type = die_type (d, imported_cu);
+             struct symbol *sym = new_symbol (die, type, cu);
+             attr = dwarf2_attr (d, DW_AT_location, imported_cu);
+             sym->set_aclass_index (LOC_UNRESOLVED);
+             if (attr != nullptr)
+               var_decode_location (attr, sym, cu);
+             return true;
+           }
+         else
+           {
+             sect_offset sect_off = attr->get_ref_die_offset ();
+             type = get_die_type_at_offset (sect_off, cu->per_cu,
+                                            cu->per_objfile);
+             if (type != nullptr && type->code () == TYPE_CODE_NAMESPACE)
+               {
+                 /* This declaration is a global namespace alias. Add
+                    a symbol for it whose type is the aliased
+                    namespace.  */
+                 new_symbol (die, type, cu);
+                 return true;
+               }
            }
        }
     }
-
-  return 0;
+  return false;
 }

 /* Return the using directives repository (global or local?) to use in the
diff --git a/gdb/testsuite/gdb.base/symbol-alias.exp b/gdb/testsuite/gdb.base/symbol-alias.exp
index 289f49bbc3f..5f6fa94dd76 100644
--- a/gdb/testsuite/gdb.base/symbol-alias.exp
+++ b/gdb/testsuite/gdb.base/symbol-alias.exp
@@ -15,6 +15,10 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.

 standard_testfile symbol-alias.c symbol-alias2.c
+set using_clang [test_compiler_info clang-*]
+# Clang versions prior to v15 do not emit debug info for aliases.
+set old_clang [expr [test_compiler_info {clang-1[0-4]-*-*}] \
+                || [test_compiler_info {clang-[1-9]-*}]]

 if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile $srcfile2]] } {
     return -1
@@ -30,7 +34,61 @@ foreach f {"func" "func_alias"} {
     gdb_test "p *${f}()" "= {field1 = 1, field2 = 2}"
 }

-# Variables.
-foreach v {"g_var_s" "g_var_s_alias"} {
-    gdb_test "p $v" "= {field1 = 1, field2 = 2}"
+# Extern global variable.
+gdb_test "p g_var_s" "= {field1 = 1, field2 = 2}"
+foreach v {"g_var_s_alias" "g_var_s_alias2"} {
+    gdb_test_multiple "p $v" "print alias variable $v" {
+       -re -wrap " = {field1 = 1, field2 = 2}" {
+           pass $gdb_test_name
+       }
+       -re -wrap "has unknown type; cast it to its declared type" {
+           if { $old_clang } {
+               xfail $gdb_test_name
+           } else {
+               fail $gdb_test_name
+           }
+       }
+    }
+}
+
+# Static global variable.
+gdb_test "p g_var" " = 1"
+gdb_test_multiple "p g_var_alias" "print alias of static variable" {
+    -re -wrap " = 1" {
+       pass $gdb_test_name
+    }
+    -re -wrap "has unknown type; cast it to its declared type" {
+       if { $old_clang } {
+         xfail $gdb_test_name
+       } else {
+         fail $gdb_test_name
+       }
+    }
+}
+
+# Alias of a variable that is declared later in the scope.
+gdb_test "p g_def_var" " = 2"
+gdb_test_multiple "p g_def_var_alias" "print g_def_var_alias" {
+    -re -wrap " = 2" {
+       pass $gdb_test_name
+    }
+    -re -wrap "has unknown type; cast it to its declared type" {
+       if { $old_clang } {
+         xfail $gdb_test_name
+       } else {
+         fail $gdb_test_name
+       }
+    }
+}
+gdb_test_multiple "p g_def_var_alias2" "print g_def_var_alias2" {
+    -re -wrap " = 2" {
+       pass $gdb_test_name
+    }
+    -re -wrap "has unknown type; cast it to its declared type" {
+       if { $old_clang } {
+         xfail $gdb_test_name
+       } else {
+         fail $gdb_test_name
+       }
+    }
 }
diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c b/gdb/testsuite/gdb.base/symbol-alias2.c
index 34f4e121e25..c1c0413ed60 100644
--- a/gdb/testsuite/gdb.base/symbol-alias2.c
+++ b/gdb/testsuite/gdb.base/symbol-alias2.c
@@ -23,6 +23,8 @@ struct S

 struct S g_var_s = { 1, 2 };

+static int g_var = 1;
+
 #ifdef __cplusplus
 /* So that the alias attribute below work without having to figure out
    this function's mangled name.  */
@@ -38,3 +40,13 @@ func (void)
 struct S *func_alias (void) __attribute__ ((alias ("func")));

 extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));
+
+extern struct S g_var_s_alias2 __attribute__ ((alias ("g_var_s_alias")));
+
+extern int g_var_alias __attribute__ ((alias ("g_var")));
+
+extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
+
+int g_def_var = 2;
+
+extern int g_def_var_alias2 __attribute__ ((alias ("g_def_var_alias")));

base-commit: 8025a164287b588f450686a4b81f6001c33e4269
--
2.25.1


[-- Attachment #2: 0010-Debug-support-for-C-global-alias-variable-pedro.patch --]
[-- Type: application/octet-stream, Size: 8495 bytes --]

From 4ec4f0473f2df1468fe25e46c30e4b20b9c207c5 Mon Sep 17 00:00:00 2001
From: Kavitha Natarajan <kavitha.natarajan@amd.com>
Date: Mon, 13 Jun 2022 16:24:24 +0530
Subject: [PATCH] Debug support for global alias variable

Starting with (future) Clang 15 (since
https://reviews.llvm.org/D120989), Clang emits the DWARF information
of global alias variables as DW_TAG_imported_declaration.  However,
GDB does not handle it.  It incorrectly always reads this tag as
C++/Fortran imported declaration (type alias, namespace alias and
Fortran module).  This commit adds support to handle this tag as an
alias variable.

This change fixes the failures in the gdb.base/symbol-alias.exp
testcase with current git Clang.  This testcase is also updated to
test nested (recursive) aliases.
---
 gdb/dwarf2/read.c                       | 63 ++++++++++++++++--------
 gdb/testsuite/gdb.base/symbol-alias.exp | 64 +++++++++++++++++++++++--
 gdb/testsuite/gdb.base/symbol-alias2.c  | 12 +++++
 3 files changed, 115 insertions(+), 24 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 64cb8d421b9..e22e09b4e2b 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -894,6 +894,10 @@ static void build_type_psymtabs_reader (cutu_reader *reader,
 
 static void dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile);
 
+static void var_decode_location (struct attribute *attr,
+				 struct symbol *sym,
+				 struct dwarf2_cu *cu);
+
 static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);
 
 static const gdb_byte *read_attribute (const struct die_reader_specs *,
@@ -1071,7 +1075,7 @@ static struct using_direct **using_directives (struct dwarf2_cu *cu);
 
 static void read_import_statement (struct die_info *die, struct dwarf2_cu *);
 
-static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
+static bool read_alias (struct die_info *die, struct dwarf2_cu *cu);
 
 static struct type *read_module_type (struct die_info *die,
 				      struct dwarf2_cu *cu);
@@ -8664,9 +8668,10 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
       break;
     case DW_TAG_imported_declaration:
       cu->processing_has_namespace_info = true;
-      if (read_namespace_alias (die, cu))
+      if (read_alias (die, cu))
 	break;
-      /* The declaration is not a global namespace alias.  */
+      /* The declaration is neither a global namespace nor a variable
+	 alias.  */
       /* Fall through.  */
     case DW_TAG_imported_module:
       cu->processing_has_namespace_info = true;
@@ -9134,18 +9139,18 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
   return retval;
 }
 
-/* Inspect DIE in CU for a namespace alias.  If one exists, record
-   a new symbol for it.
+/* Inspect DIE in CU for a namespace alias or a variable with alias
+   attribute.  If one exists, record a new symbol for it.
 
-   Returns 1 if a namespace alias was recorded, 0 otherwise.  */
+   Returns true if an alias was recorded, false otherwise.  */
 
-static int
-read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
+static bool
+read_alias (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct attribute *attr;
 
-  /* If the die does not have a name, this is not a namespace
-     alias.  */
+  /* If the die does not have a name, this is neither a namespace
+     alias nor a variable alias.  */
   attr = dwarf2_attr (die, DW_AT_name, cu);
   if (attr != NULL)
     {
@@ -9171,26 +9176,42 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
 	{
 	  complaint (_("DIE at %s has too many recursively imported "
 		       "declarations"), sect_offset_str (d->sect_off));
-	  return 0;
+	  return false;
 	}
 
       if (attr != NULL)
 	{
 	  struct type *type;
-	  sect_offset sect_off = attr->get_ref_die_offset ();
-
-	  type = get_die_type_at_offset (sect_off, cu->per_cu, cu->per_objfile);
-	  if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
+	  if (d->tag == DW_TAG_variable)
 	    {
-	      /* This declaration is a global namespace alias.  Add
-		 a symbol for it whose type is the aliased namespace.  */
-	      new_symbol (die, type, cu);
-	      return 1;
+	      /* This declaration is a C/C++ global variable alias.
+		 Add a symbol for it whose type is the same as the
+		 aliased variable's.  */
+	      type = die_type (d, imported_cu);
+	      struct symbol *sym = new_symbol (die, type, cu);
+	      attr = dwarf2_attr (d, DW_AT_location, imported_cu);
+	      sym->set_aclass_index (LOC_UNRESOLVED);
+	      if (attr != nullptr)
+		var_decode_location (attr, sym, cu);
+	      return true;
+	    }
+	  else
+	    {
+	      sect_offset sect_off = attr->get_ref_die_offset ();
+	      type = get_die_type_at_offset (sect_off, cu->per_cu,
+					     cu->per_objfile);
+	      if (type != nullptr && type->code () == TYPE_CODE_NAMESPACE)
+		{
+		  /* This declaration is a global namespace alias. Add
+		     a symbol for it whose type is the aliased
+		     namespace.  */
+		  new_symbol (die, type, cu);
+		  return true;
+		}
 	    }
 	}
     }
-
-  return 0;
+  return false;
 }
 
 /* Return the using directives repository (global or local?) to use in the
diff --git a/gdb/testsuite/gdb.base/symbol-alias.exp b/gdb/testsuite/gdb.base/symbol-alias.exp
index 289f49bbc3f..5f6fa94dd76 100644
--- a/gdb/testsuite/gdb.base/symbol-alias.exp
+++ b/gdb/testsuite/gdb.base/symbol-alias.exp
@@ -15,6 +15,10 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 standard_testfile symbol-alias.c symbol-alias2.c
+set using_clang [test_compiler_info clang-*]
+# Clang versions prior to v15 do not emit debug info for aliases.
+set old_clang [expr [test_compiler_info {clang-1[0-4]-*-*}] \
+		 || [test_compiler_info {clang-[1-9]-*}]]
 
 if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile $srcfile2]] } {
     return -1
@@ -30,7 +34,61 @@ foreach f {"func" "func_alias"} {
     gdb_test "p *${f}()" "= {field1 = 1, field2 = 2}"
 }
 
-# Variables.
-foreach v {"g_var_s" "g_var_s_alias"} {
-    gdb_test "p $v" "= {field1 = 1, field2 = 2}"
+# Extern global variable.
+gdb_test "p g_var_s" "= {field1 = 1, field2 = 2}"
+foreach v {"g_var_s_alias" "g_var_s_alias2"} {
+    gdb_test_multiple "p $v" "print alias variable $v" {
+	-re -wrap " = {field1 = 1, field2 = 2}" {
+	    pass $gdb_test_name
+	}
+	-re -wrap "has unknown type; cast it to its declared type" {
+	    if { $old_clang } {
+		xfail $gdb_test_name
+	    } else {
+		fail $gdb_test_name
+	    }
+	}
+    }
+}
+
+# Static global variable.
+gdb_test "p g_var" " = 1"
+gdb_test_multiple "p g_var_alias" "print alias of static variable" {
+    -re -wrap " = 1" {
+	pass $gdb_test_name
+    }
+    -re -wrap "has unknown type; cast it to its declared type" {
+	if { $old_clang } {
+	  xfail $gdb_test_name
+	} else {
+	  fail $gdb_test_name
+	}
+    }
+}
+
+# Alias of a variable that is declared later in the scope.
+gdb_test "p g_def_var" " = 2"
+gdb_test_multiple "p g_def_var_alias" "print g_def_var_alias" {
+    -re -wrap " = 2" {
+	pass $gdb_test_name
+    }
+    -re -wrap "has unknown type; cast it to its declared type" {
+	if { $old_clang } {
+	  xfail $gdb_test_name
+	} else {
+	  fail $gdb_test_name
+	}
+    }
+}
+gdb_test_multiple "p g_def_var_alias2" "print g_def_var_alias2" {
+    -re -wrap " = 2" {
+	pass $gdb_test_name
+    }
+    -re -wrap "has unknown type; cast it to its declared type" {
+	if { $old_clang } {
+	  xfail $gdb_test_name
+	} else {
+	  fail $gdb_test_name
+	}
+    }
 }
diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c b/gdb/testsuite/gdb.base/symbol-alias2.c
index 34f4e121e25..c1c0413ed60 100644
--- a/gdb/testsuite/gdb.base/symbol-alias2.c
+++ b/gdb/testsuite/gdb.base/symbol-alias2.c
@@ -23,6 +23,8 @@ struct S
 
 struct S g_var_s = { 1, 2 };
 
+static int g_var = 1;
+
 #ifdef __cplusplus
 /* So that the alias attribute below work without having to figure out
    this function's mangled name.  */
@@ -38,3 +40,13 @@ func (void)
 struct S *func_alias (void) __attribute__ ((alias ("func")));
 
 extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));
+
+extern struct S g_var_s_alias2 __attribute__ ((alias ("g_var_s_alias")));
+
+extern int g_var_alias __attribute__ ((alias ("g_var")));
+
+extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
+
+int g_def_var = 2;
+
+extern int g_def_var_alias2 __attribute__ ((alias ("g_def_var_alias")));

base-commit: 8025a164287b588f450686a4b81f6001c33e4269
-- 
2.25.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] Debug support for global alias variable
  2022-06-13 11:11                                 ` Natarajan, Kavitha
@ 2022-06-13 13:54                                   ` Pedro Alves
  2022-06-13 17:28                                     ` Natarajan, Kavitha
  0 siblings, 1 reply; 28+ messages in thread
From: Pedro Alves @ 2022-06-13 13:54 UTC (permalink / raw)
  To: Natarajan, Kavitha, Tom Tromey, Natarajan, Kavitha via Gdb-patches
  Cc: George, Jini Susan, Parasuraman, Hariharan

On 2022-06-13 12:11, Natarajan, Kavitha wrote:

>>>> +gdb_test "p g_def_var" " = 2"
>>>> +gdb_test_multiple "p g_def_var_alias" "print alias of deferred variable" {
>>>> +    -re -wrap " = 2" {
>>>> +       pass $gdb_test_name
>>>> +    }
>>>> +    -re -wrap "has unknown type; cast it to its declared type" {
>>>> +       if { $using_clang } {
>>
>> So all other tests pass with your fixed Clang, but this one will still xfail.
>> Do you have more information about this?  Strange offhand that "alias of
>> alias" works, but this one doesn't.  Is there some Clang bug open about this
>> we could add a reference to here?  If not, could one be created?  If instead
>> you think this is a GDB bug, then this should be a kfail ("known gdb fail")
>> instead of an xfail, in which case we should have a bug open in gdb's bugzilla
>> about it so we can reference it here.
> 
> This is a clang bug. For the alias of deferred declaration, clang does not generate
> debug information. Clang has to emit the DIE with DW_TAG_imported_declaration tag.
> So, this is an expected failure. I can add a comment for the xfail part.
> 

Alright, thanks for the clarification.

>>>> +extern int g_def_var_alias __attribute__ ((alias ("g_def_var")));
>>>> +
>>>> +int g_def_var = 2;
>>>> +
>>>> +extern int g_def_var2_alias __attribute__ ((alias ("g_def_var2")));
>>>> +
>>>> +int g_def_var2 = 3;
>>
>> Offhand, there doesn't seem to be any difference between g_def_var_alias
>> and g_def_var2_alias?  If we really need both, then I'm thinking this could
>> use some comment.
> 
> Yes, they are same. I just wanted to call out the xfail through g_def_var_alias that
> no debug information is generated when the aliasee is declared later. In case of
> g_def_var2_alias, though its aliasee is declared later, the debug info is generated
> (as DW_TAG_variable) when g_def_var2_alias2 accesses it to generate its debug info.
> When I am writing this, I am thinking of removing this xfail part itself. Anyway,
> g_def_var2_alias would cover the same case when clang is fixed.

OK.  With these explanations, it's clearer.  I think keeping the xfail test was OK
too, it just needed a comment.

But this is fine with me as is.  Just the "using_clang" variable is no longer used,
so should be removed.

Do you have write access, or do you need someone to push your patch?

^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [PATCH] Debug support for global alias variable
  2022-06-13 13:54                                   ` Pedro Alves
@ 2022-06-13 17:28                                     ` Natarajan, Kavitha
  0 siblings, 0 replies; 28+ messages in thread
From: Natarajan, Kavitha @ 2022-06-13 17:28 UTC (permalink / raw)
  To: Pedro Alves, Tom Tromey, Natarajan, Kavitha via Gdb-patches
  Cc: George, Jini Susan, Parasuraman, Hariharan

[AMD Official Use Only - General]

Hi Pedro,

> OK.  With these explanations, it's clearer.  I think keeping the xfail test was
> OK too, it just needed a comment.
>
> But this is fine with me as is.  Just the "using_clang" variable is no longer
> used, so should be removed.
>
> Do you have write access, or do you need someone to push your patch?

I can push the patch. I shall remove "using_clang" variable and push the patch.

Thanks for helping me in improving the patch.

Regards,
Kavitha

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2022-06-13 17:28 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-04 13:44 [PATCH] Debug support for global alias variable Natarajan, Kavitha
2022-03-14 11:15 ` Natarajan, Kavitha
2022-03-24  6:36   ` Natarajan, Kavitha
2022-03-24 13:53 ` Bruno Larsen
2022-03-28 15:14   ` Natarajan, Kavitha
2022-03-29 14:02     ` Bruno Larsen
2022-03-30 11:30       ` Natarajan, Kavitha
2022-03-30 12:25         ` Natarajan, Kavitha
2022-04-05  6:26           ` Natarajan, Kavitha
2022-04-05 13:33           ` Bruno Larsen
2022-04-05 14:02             ` Natarajan, Kavitha
2022-04-12  8:38             ` Natarajan, Kavitha
2022-04-15 16:06           ` Tom Tromey
2022-04-18 11:04             ` Natarajan, Kavitha
2022-04-18 15:03               ` Tom Tromey
2022-04-19 12:45                 ` Natarajan, Kavitha
2022-04-19 22:59                   ` Tom Tromey
2022-04-20  6:00                     ` Natarajan, Kavitha
2022-04-20 10:33                       ` Pedro Alves
2022-04-20 12:17                         ` Natarajan, Kavitha
2022-04-25 13:10                           ` Natarajan, Kavitha
2022-05-05  9:53                           ` Natarajan, Kavitha
2022-06-07  9:08                           ` Natarajan, Kavitha
2022-06-08 16:29                             ` Pedro Alves
2022-06-09 11:36                               ` Pedro Alves
2022-06-13 11:11                                 ` Natarajan, Kavitha
2022-06-13 13:54                                   ` Pedro Alves
2022-06-13 17:28                                     ` Natarajan, Kavitha

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).