gdb/gdb-bz645773-ifort-case-3of...

449 lines
15 KiB
Diff

http://sourceware.org/ml/gdb-patches/2010-11/msg00108.html
Subject: [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__.
Index: gdb-7.2/gdb/dwarf2read.c
===================================================================
--- gdb-7.2.orig/gdb/dwarf2read.c 2010-11-07 05:38:21.000000000 +0100
+++ gdb-7.2/gdb/dwarf2read.c 2010-11-07 05:38:47.000000000 +0100
@@ -55,6 +55,7 @@
#include "gdb_stat.h"
#include "completer.h"
#include "top.h"
+#include <ctype.h>
#include <fcntl.h>
#include "gdb_string.h"
@@ -376,6 +377,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
@@ -621,9 +626,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
@@ -1109,6 +1115,9 @@ static gdb_byte *read_full_die (const st
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 *);
@@ -8589,7 +8598,8 @@ read_partial_die (struct partial_die_inf
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
@@ -11043,7 +11053,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,
@@ -11055,14 +11094,26 @@ dwarf2_canonicalize_name (char *name, st
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. */
@@ -11088,7 +11139,13 @@ dwarf2_name (struct die_info *die, struc
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:
@@ -13743,6 +13800,7 @@ init_one_comp_unit (struct dwarf2_cu *cu
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. */
@@ -13758,6 +13816,13 @@ prepare_one_comp_unit (struct dwarf2_cu
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
Index: gdb-7.2/gdb/testsuite/gdb.dwarf2/dw2-case-insensitive-debug.S
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gdb-7.2/gdb/testsuite/gdb.dwarf2/dw2-case-insensitive-debug.S 2010-11-07 05:38:35.000000000 +0100
@@ -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 */
Index: gdb-7.2/gdb/testsuite/gdb.dwarf2/dw2-case-insensitive.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gdb-7.2/gdb/testsuite/gdb.dwarf2/dw2-case-insensitive.c 2010-11-07 05:38:35.000000000 +0100
@@ -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;
+}
Index: gdb-7.2/gdb/testsuite/gdb.dwarf2/dw2-case-insensitive.exp
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gdb-7.2/gdb/testsuite/gdb.dwarf2/dw2-case-insensitive.exp 2010-11-07 05:38:35.000000000 +0100
@@ -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"
+}
Index: gdb-7.2/gdb/testsuite/gdb.mi/mi-var-child-f.exp
===================================================================
--- gdb-7.2.orig/gdb/testsuite/gdb.mi/mi-var-child-f.exp 2010-01-01 08:32:03.000000000 +0100
+++ gdb-7.2/gdb/testsuite/gdb.mi/mi-var-child-f.exp 2010-11-07 05:38:35.000000000 +0100
@@ -36,7 +36,7 @@ if {[gdb_compile "${srcdir}/${subdir}/${
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\\)\"" \