This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch 2/2] iFort compat.: case insensitive symbols (PR 11313)


Hi,

iFort (Intel Fortran compiler) produces DIEs like:

 <1><1dc>: Abbrev Number: 6 (DW_TAG_module)
    <1e0>   DW_AT_name        : MOD1    

But Fortran is case insensitive, therefore GDB lowercases any user input
first.  Symbols cannot match.  gfortran always produces lowercased DIE names.

I was told by Jakub Jelinek GCC frontend will never be properly case
preserving - to output "Mod1" if user stated it in such case in the sources.

Therefore GDB will now lowercase any case insensitive symbol names on their
read-in from DWARF.

ELF symbol tables are currently not touched - their matching to their CU (and
thus to their DW_AT_identifier_case / DW_AT_language) is expensive and it does
not seem to me to be needed for iFort as only the module names are uppercased
there.

For the iFort compatibility there is also needed:
	[new testcase] Regression 7.1->7.2 for iFort [Re: [RFA-v2] dwarf debug format: Support DW_AT_variable_parameter attribute]
	http://sourceware.org/ml/gdb-patches/2010-11/msg00084.html

No regressions on {x86_64,x86_64-m32,i686}-fedora14snapshot-linux-gnu.


Thanks,
Jan


gdb/
2010-11-07  Jan Kratochvil  <jan.kratochvil@redhat.com>

	PR 11313 - case insensitive identifiers in DWARF not in lowercase.
	* dwarf2read.c: Include ctype.h.
	(struct dwarf2_cu) <case_sensitivity>: New.
	(struct attribute) <string_is_canonical>: Update the comment.
	(canonical_case): New declaration.
	(read_partial_die): Call canonical_case.
	(canonical_case): New function.
	(dwarf2_canonicalize_name): Update the function comment.  Call
	canonical_case, adjust the obstack allocation.
	(dwarf2_name): Call canonical_case, set DW_STRING_IS_CANONICAL.
	(init_one_comp_unit, prepare_one_comp_unit): Set cu->case_sensitivity.

gdb/testsuite/
2010-11-07  Jan Kratochvil  <jan.kratochvil@redhat.com>

	PR 11313 - case insensitive identifiers in DWARF not in lowercase.
	* gdb.dwarf2/dw2-case-insensitive-debug.S: New.
	* gdb.dwarf2/dw2-case-insensitive.c: New.
	* gdb.dwarf2/dw2-case-insensitive.exp: New.
	* gdb.mi/mi-var-child-f.exp (mi_runto): Use lowercase main__.

--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -57,6 +57,7 @@
 #include "vec.h"
 #include "c-lang.h"
 #include "valprint.h"
+#include <ctype.h>
 
 #include <fcntl.h>
 #include "gdb_string.h"
@@ -388,6 +389,10 @@ struct dwarf2_cu
      DIEs for namespaces, we don't need to try to infer them
      from mangled names.  */
   unsigned int has_namespace_info : 1;
+
+  /* Are identifiers in this CU case sensitive or should they be lowercased
+     before storing them into GDB symbol tables?  */
+  enum case_sensitivity case_sensitivity;
 };
 
 /* When using the index (and thus not using psymtabs), each CU has an
@@ -638,9 +643,10 @@ struct attribute
     ENUM_BITFIELD(dwarf_attribute) name : 16;
     ENUM_BITFIELD(dwarf_form) form : 15;
 
-    /* Has DW_STRING already been updated by dwarf2_canonicalize_name?  This
-       field should be in u.str (existing only for DW_STRING) but it is kept
-       here for better struct attribute alignment.  */
+    /* Has DW_STRING already been updated by dwarf2_canonicalize_name or
+       canonical_case?  This field should be in u.str (existing only for
+       DW_STRING) but it is kept here for better struct attribute alignment.
+       */
     unsigned int string_is_canonical : 1;
 
     union
@@ -1135,6 +1141,9 @@ static gdb_byte *read_full_die (const struct die_reader_specs *reader,
 
 static void process_die (struct die_info *, struct dwarf2_cu *);
 
+static char *canonical_case (char *name, struct dwarf2_cu *cu,
+			     struct obstack *obstack);
+
 static char *dwarf2_canonicalize_name (char *, struct dwarf2_cu *,
 				       struct obstack *);
 
@@ -8799,7 +8808,8 @@ read_partial_die (struct partial_die_info *part_die,
 	    case DW_TAG_enumerator:
 	      /* These tags always have simple identifiers already; no need
 		 to canonicalize them.  */
-	      part_die->name = DW_STRING (&attr);
+	      part_die->name = canonical_case (DW_STRING (&attr), cu,
+					       &cu->objfile->objfile_obstack);
 	      break;
 	    default:
 	      part_die->name
@@ -11631,7 +11641,36 @@ sibling_die (struct die_info *die)
   return die->sibling;
 }
 
-/* Get name of a die, return NULL if not found.  */
+/* Convert NAME to the lower case if CU is case_sensitive_off.  Allocate
+   memory on OBSTACK if needed, otherwise return the NAME pointer.  */
+
+static char *
+canonical_case (char *name, struct dwarf2_cu *cu,
+		struct obstack *obstack)
+{
+  char *retval;
+  int i;
+
+  if (cu->case_sensitivity == case_sensitive_on)
+    return name;
+
+  for (i = 0; name[i] != 0; i++)
+    if (tolower (name[i]) != name[i])
+      break;
+  if (name[i] == 0)
+    return name;
+
+  retval = obstack_alloc (obstack, strlen (name) + 1);
+
+  for (i = 0; name[i] != 0; i++)
+    retval[i] = tolower (name[i]);
+  retval[i] = 0;
+
+  return retval;
+}
+
+/* Get name of a die, return NULL if not found.  canonical_case is always
+   already called for the returned string.  */
 
 static char *
 dwarf2_canonicalize_name (char *name, struct dwarf2_cu *cu,
@@ -11643,14 +11682,26 @@ dwarf2_canonicalize_name (char *name, struct dwarf2_cu *cu,
 
       if (canon_name != NULL)
 	{
-	  if (strcmp (canon_name, name) != 0)
-	    name = obsavestring (canon_name, strlen (canon_name),
+	  char *cased_name;
+
+	  cased_name = canonical_case (canon_name, cu, obstack);
+
+	  /* Push CASED_NAME on OBSTACK only if it isn't already pushed there
+	     by canonical_case and if it was allocated using xmalloc by
+	     cp_canonicalize_string.  */
+	  if (strcmp (canon_name, cased_name) == 0
+	      && strcmp (canon_name, name) != 0)
+	    name = obsavestring (cased_name, strlen (cased_name),
 				 obstack);
+	  else
+	    name = cased_name;
 	  xfree (canon_name);
+
+	  return name;
 	}
     }
 
-  return name;
+  return canonical_case (name, cu, obstack);
 }
 
 /* Get name of a die, return NULL if not found.  */
@@ -11672,7 +11723,13 @@ dwarf2_name (struct die_info *die, struct dwarf2_cu *cu)
     case DW_TAG_enumeration_type:
     case DW_TAG_enumerator:
       /* These tags always have simple identifiers already; no need
-	 to canonicalize them.  */
+	 to call dwarf2_canonicalize_name for them.  */
+      if (!DW_STRING_IS_CANONICAL (attr))
+	{
+	  DW_STRING (attr) = canonical_case (DW_STRING (attr), cu,
+					     &cu->objfile->objfile_obstack);
+	  DW_STRING_IS_CANONICAL (attr) = 1;
+	}
       return DW_STRING (attr);
 
     case DW_TAG_subprogram:
@@ -14301,6 +14358,7 @@ init_one_comp_unit (struct dwarf2_cu *cu, struct objfile *objfile)
   memset (cu, 0, sizeof (*cu));
   cu->objfile = objfile;
   obstack_init (&cu->comp_unit_obstack);
+  cu->case_sensitivity = case_sensitive_on;
 }
 
 /* Initiailize basic fields of dwarf_cu CU according to DIE COMP_UNIT_DIE.  */
@@ -14316,6 +14374,13 @@ prepare_one_comp_unit (struct dwarf2_cu *cu, struct die_info *comp_unit_die)
     set_cu_language (DW_UNSND (attr), cu);
   else
     set_cu_language (language_minimal, cu);
+
+  attr = dwarf2_attr (comp_unit_die, DW_AT_identifier_case, cu);
+  if (attr)
+    cu->case_sensitivity = (DW_UNSND (attr) == DW_ID_case_sensitive
+			    ? case_sensitive_on : case_sensitive_off);
+  else
+    cu->case_sensitivity = cu->language_defn->la_case_sensitivity;
 }
 
 /* Release one cached compilation unit, CU.  We unlink it from the tree
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-case-insensitive-debug.S
@@ -0,0 +1,122 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2004, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+	.section .debug_info
+.Lcu1_begin:
+	/* CU header */
+	.4byte	.Lcu1_end - .Lcu1_start		/* Length of Compilation Unit */
+.Lcu1_start:
+	.2byte	2				/* DWARF Version */
+	.4byte	.Labbrev1_begin			/* Offset into abbrev section */
+	.byte	4				/* Pointer size */
+
+	/* CU die */
+	.uleb128 2				/* Abbrev: DW_TAG_compile_unit */
+	.ascii	"file1.txt\0"			/* DW_AT_name */
+	.ascii	"GNU C 3.3.3\0"			/* DW_AT_producer */
+	.byte	2				/* DW_AT_language (DW_LANG_C) */
+	.byte	3				/* DW_AT_identifier_case (DW_ID_case_insensitive) */
+	.4byte		FUNC_attr		/* DW_AT_low_pc */
+	.4byte		FUNC_lang 		/* DW_AT_high_pc */
+
+	.uleb128	3			/* Abbrev: DW_TAG_subprogram */
+	.byte		1			/* DW_AT_external */
+	.ascii		"FUNC_attr\0"		/* DW_AT_name */
+	.4byte		FUNC_attr		/* DW_AT_low_pc */
+	.4byte		FUNC_lang 		/* DW_AT_high_pc */
+
+	.byte		0			/* End of children of CU */
+.Lcu1_end:
+
+.Lcu2_begin:
+	/* CU header */
+	.4byte	.Lcu2_end - .Lcu2_start		/* Length of Compilation Unit */
+.Lcu2_start:
+	.2byte	2				/* DWARF Version */
+	.4byte	.Labbrev1_begin			/* Offset into abbrev section */
+	.byte	4				/* Pointer size */
+
+	/* CU die */
+	.uleb128 1				/* Abbrev: DW_TAG_compile_unit */
+	.ascii	"file1.txt\0"			/* DW_AT_name */
+	.ascii	"GNU C 3.3.3\0"			/* DW_AT_producer */
+	.byte	8				/* DW_AT_language (DW_LANG_Fortran90) */
+	.4byte		FUNC_lang		/* DW_AT_low_pc */
+	.4byte		main			/* DW_AT_high_pc */
+
+	.uleb128	3			/* Abbrev: DW_TAG_subprogram */
+	.byte		1			/* DW_AT_external */
+	.ascii		"FUNC_lang\0"		/* DW_AT_name */
+	.4byte		FUNC_lang		/* DW_AT_low_pc */
+	.4byte		main			/* DW_AT_high_pc */
+
+	.byte		0			/* End of children of CU */
+.Lcu2_end:
+
+/* Abbrev table */
+	.section .debug_abbrev
+.Labbrev1_begin:
+	.uleb128	1			/* Abbrev code */
+	.uleb128	0x11			/* DW_TAG_compile_unit */
+	.byte		1			/* has_children */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x25			/* DW_AT_producer */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x13			/* DW_AT_language */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.uleb128	0x11			/* DW_AT_low_pc */
+	.uleb128	0x1			/* DW_FORM_addr */
+	.uleb128	0x12			/* DW_AT_high_pc */
+	.uleb128	0x1			/* DW_FORM_addr */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.uleb128	2			/* Abbrev code */
+	.uleb128	0x11			/* DW_TAG_compile_unit */
+	.byte		1			/* has_children */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x25			/* DW_AT_producer */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x13			/* DW_AT_language */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.uleb128	0x42			/* DW_AT_identifier_case */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.uleb128	0x11			/* DW_AT_low_pc */
+	.uleb128	0x1			/* DW_FORM_addr */
+	.uleb128	0x12			/* DW_AT_high_pc */
+	.uleb128	0x1			/* DW_FORM_addr */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.uleb128	3			/* Abbrev code */
+	.uleb128	0x2e			/* DW_TAG_subprogram */
+	.byte		0			/* has_children */
+	.uleb128	0x3f			/* DW_AT_external */
+	.uleb128	0xc			/* DW_FORM_flag */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x11			/* DW_AT_low_pc */
+	.uleb128	0x1			/* DW_FORM_addr */
+	.uleb128	0x12			/* DW_AT_high_pc */
+	.uleb128	0x1			/* DW_FORM_addr */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-case-insensitive.c
@@ -0,0 +1,36 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2004, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* This one is DW_LANG_C but it uses DW_ID_case_insensitive.  */
+
+void
+FUNC_attr (void)
+{
+}
+
+/* This one has no DW_AT_identifier_case but it is DW_LANG_Fortran90.  */
+
+void
+FUNC_lang (void)
+{
+}
+
+int
+main()
+{
+  return 0;
+}
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-case-insensitive.exp
@@ -0,0 +1,41 @@
+# Copyright 2010 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+# For now pick a sampling of likely targets.
+if {![istarget *-*-linux*]
+    && ![istarget *-*-gnu*]
+    && ![istarget *-*-elf*]
+    && ![istarget *-*-openbsd*]
+    && ![istarget arm-*-eabi*]
+    && ![istarget powerpc-*-eabi*]} {
+    return 0
+}
+
+set testfile "dw2-case-insensitive"
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} [list ${testfile}.c ${testfile}-debug.S] {nodebug}] } {
+    return -1
+}
+
+gdb_test_no_output "set language fortran"
+
+if {[gdb_breakpoint "fuNC_attr"] == 1} {
+    pass "setting breakpoint at fuNC_attr"
+}
+
+if {[gdb_breakpoint "fuNC_lang"] == 1} {
+    pass "setting breakpoint at fuNC_lang"
+}
--- a/gdb/testsuite/gdb.mi/mi-var-child-f.exp
+++ b/gdb/testsuite/gdb.mi/mi-var-child-f.exp
@@ -36,7 +36,7 @@ if {[gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
 mi_gdb_reinitialize_dir $srcdir/$subdir
 mi_gdb_load ${binfile}
 
-mi_runto MAIN__
+mi_runto main__
 
 mi_gdb_test "-var-create array * array" \
     "\\^done,name=\"array\",numchild=\"3\",value=\".*\",type=\"integer \\(2,-1:1\\)\"" \


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]