keiths / rpms / gdb

Forked from rpms/gdb 12 days ago
Clone
ba67a79
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=185337
ba67a79
ba67a79
b0ab3a8
currently for trivial nonthreaded helloworld with no debug info up to -ggdb2 you
ba67a79
will get:
ba67a79
        (gdb) p errno
aefb0e1
        [some error]
ba67a79
ba67a79
* with -ggdb2 and less "errno" in fact does not exist anywhere as it was
ba67a79
  compiled to "(*__errno_location ())" and the macro definition is not present.
ba67a79
  Unfortunately gdb will find the TLS symbol and it will try to access it but
ba67a79
  as the program has been compiled without -lpthread the TLS base register
ba67a79
  (%gs on i386) is not setup and it will result in:
ba67a79
        Cannot access memory at address 0x8
ba67a79
aefb0e1
Attached suggestion patch how to deal with the most common "errno" symbol
ba67a79
for the most common under-ggdb3 compiled programs.
ba67a79
ba67a79
ba67a79
b0ab3a8
2007-11-03  Jan Kratochvil  <jan.kratochvil@redhat.com>
ba67a79
b0ab3a8
	* ./gdb/dwarf2read.c (read_partial_die, dwarf2_linkage_name): Prefer
b0ab3a8
	DW_AT_MIPS_linkage_name over DW_AT_name now only for non-C.
ba67a79
b0ab3a8
glibc-debuginfo-2.7-2.x86_64: /usr/lib/debug/lib64/libc.so.6.debug:
b0ab3a8
  <81a2>     DW_AT_name        : (indirect string, offset: 0x280e): __errno_location
b0ab3a8
  <81a8>     DW_AT_MIPS_linkage_name: (indirect string, offset: 0x2808): *__GI___errno_location
b0ab3a8
b0ab3a8
--- ./gdb/dwarf2read.c	25 Oct 2007 20:54:27 -0000	1.236
b0ab3a8
+++ ./gdb/dwarf2read.c	3 Nov 2007 21:03:43 -0000
b0ab3a8
@@ -5550,8 +5550,8 @@ read_partial_die (struct partial_die_inf
b0ab3a8
 	{
b0ab3a8
 	case DW_AT_name:
b0ab3a8
 
b0ab3a8
-	  /* Prefer DW_AT_MIPS_linkage_name over DW_AT_name.  */
b0ab3a8
-	  if (part_die->name == NULL)
b0ab3a8
+	  /* Prefer DW_AT_MIPS_linkage_name over DW_AT_name for non-C.  */
b0ab3a8
+	  if (cu->language == language_c || part_die->name == NULL)
b0ab3a8
 	    part_die->name = DW_STRING (&attr);
b0ab3a8
 	  break;
b0ab3a8
 	case DW_AT_comp_dir:
b0ab3a8
@@ -5559,7 +5559,9 @@ read_partial_die (struct partial_die_inf
b0ab3a8
 	    part_die->dirname = DW_STRING (&attr);
b0ab3a8
 	  break;
b0ab3a8
 	case DW_AT_MIPS_linkage_name:
b0ab3a8
-	  part_die->name = DW_STRING (&attr);
b0ab3a8
+	  /* Prefer DW_AT_MIPS_linkage_name over DW_AT_name for non-C.  */
b0ab3a8
+	  if (cu->language != language_c || part_die->name == NULL)
b0ab3a8
+	    part_die->name = DW_STRING (&attr);
b0ab3a8
 	  break;
b0ab3a8
 	case DW_AT_low_pc:
b0ab3a8
 	  has_low_pc_attr = 1;
b0ab3a8
@@ -7871,9 +7873,13 @@ dwarf2_linkage_name (struct die_info *di
b0ab3a8
 {
b0ab3a8
   struct attribute *attr;
b0ab3a8
 
b0ab3a8
-  attr = dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu);
b0ab3a8
-  if (attr && DW_STRING (attr))
b0ab3a8
-    return DW_STRING (attr);
b0ab3a8
+  /* Prefer DW_AT_MIPS_linkage_name over DW_AT_name for non-C.  */
b0ab3a8
+  if (cu->language != language_c)
b0ab3a8
+    {
b0ab3a8
+      attr = dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu);
b0ab3a8
+      if (attr && DW_STRING (attr))
b0ab3a8
+	return DW_STRING (attr);
b0ab3a8
+    }
b0ab3a8
   attr = dwarf2_attr (die, DW_AT_name, cu);
b0ab3a8
   if (attr && DW_STRING (attr))
b0ab3a8
     return DW_STRING (attr);
b0ab3a8
b0ab3a8
b0ab3a8
b0ab3a8
diff -u -X /home/jkratoch/.diffi.list -rup gdb-6.7.1/gdb/gdbtypes.c gdb-6.7.1-patched/gdb/gdbtypes.c
b0ab3a8
--- gdb-6.7.1/gdb/gdbtypes.c	2007-11-04 01:43:03.000000000 +0100
b0ab3a8
+++ gdb-6.7.1-patched/gdb/gdbtypes.c	2007-11-04 01:09:31.000000000 +0100
b0ab3a8
@@ -3465,6 +3465,8 @@ gdbtypes_post_init (struct gdbarch *gdba
b0ab3a8
     init_type (TYPE_CODE_INT, 
b0ab3a8
 	       gdbarch_int_bit (current_gdbarch) / TARGET_CHAR_BIT,
b0ab3a8
 	       0, "int", (struct objfile *) NULL);
b0ab3a8
+  builtin_type->builtin_int_ptr =
b0ab3a8
+    make_pointer_type (builtin_type->builtin_int, NULL);
b0ab3a8
   builtin_type->builtin_unsigned_int =
b0ab3a8
     init_type (TYPE_CODE_INT, 
b0ab3a8
 	       gdbarch_int_bit (current_gdbarch) / TARGET_CHAR_BIT,
b0ab3a8
@@ -3559,6 +3561,11 @@ gdbtypes_post_init (struct gdbarch *gdba
b0ab3a8
 	       "<text variable, no debug info>", NULL);
b0ab3a8
   TYPE_TARGET_TYPE (builtin_type->nodebug_text_symbol) =
b0ab3a8
     builtin_type->builtin_int;
b0ab3a8
+  builtin_type->nodebug_text_symbol_errno_location =
b0ab3a8
+    init_type (TYPE_CODE_FUNC, 1, 0, 
b0ab3a8
+	       "<text variable for __errno_location, no debug info>", NULL);
b0ab3a8
+  TYPE_TARGET_TYPE (builtin_type->nodebug_text_symbol_errno_location) =
b0ab3a8
+    builtin_type->builtin_int_ptr;
b0ab3a8
   builtin_type->nodebug_data_symbol =
b0ab3a8
     init_type (TYPE_CODE_INT, 
b0ab3a8
 	       gdbarch_int_bit (gdbarch) / HOST_CHAR_BIT, 0,
b0ab3a8
diff -u -X /home/jkratoch/.diffi.list -rup gdb-6.7.1/gdb/gdbtypes.h gdb-6.7.1-patched/gdb/gdbtypes.h
b0ab3a8
--- gdb-6.7.1/gdb/gdbtypes.h	2007-11-04 01:43:03.000000000 +0100
b0ab3a8
+++ gdb-6.7.1-patched/gdb/gdbtypes.h	2007-11-04 01:07:50.000000000 +0100
b0ab3a8
@@ -1008,6 +1008,7 @@ struct builtin_type
b0ab3a8
 
b0ab3a8
   /* Types used for symbols with no debug information.  */
b0ab3a8
   struct type *nodebug_text_symbol;
b0ab3a8
+  struct type *nodebug_text_symbol_errno_location;
b0ab3a8
   struct type *nodebug_data_symbol;
b0ab3a8
   struct type *nodebug_unknown_symbol;
b0ab3a8
   struct type *nodebug_tls_symbol;
b0ab3a8
@@ -1026,6 +1027,7 @@ struct builtin_type
b0ab3a8
   struct type *builtin_char;
b0ab3a8
   struct type *builtin_short;
b0ab3a8
   struct type *builtin_int;
b0ab3a8
+  struct type *builtin_int_ptr;
b0ab3a8
   struct type *builtin_long;
b0ab3a8
   struct type *builtin_signed_char;
b0ab3a8
   struct type *builtin_unsigned_char;
b0ab3a8
diff -u -X /home/jkratoch/.diffi.list -rup gdb-6.7.1/gdb/parse.c gdb-6.7.1-patched/gdb/parse.c
b0ab3a8
--- gdb-6.7.1/gdb/parse.c	2007-08-23 20:08:36.000000000 +0200
b0ab3a8
+++ gdb-6.7.1-patched/gdb/parse.c	2007-11-04 01:06:59.000000000 +0100
b0ab3a8
@@ -424,7 +424,12 @@ write_exp_msymbol (struct minimal_symbol
b0ab3a8
     case mst_text:
b0ab3a8
     case mst_file_text:
b0ab3a8
     case mst_solib_trampoline:
b0ab3a8
-      write_exp_elt_type (builtin_type (gdbarch)->nodebug_text_symbol);
b0ab3a8
+      if (builtin_type (gdbarch)->nodebug_text_symbol_errno_location != NULL
b0ab3a8
+          && strcmp (SYMBOL_LINKAGE_NAME (msymbol), "__errno_location") == 0)
b0ab3a8
+	write_exp_elt_type (builtin_type (gdbarch)
b0ab3a8
+					  ->nodebug_text_symbol_errno_location);
b0ab3a8
+      else
b0ab3a8
+	write_exp_elt_type (builtin_type (gdbarch)->nodebug_text_symbol);
b0ab3a8
       break;
b0ab3a8
 
b0ab3a8
     case mst_data:
b0ab3a8
diff -u -X /home/jkratoch/.diffi.list -rup gdb-6.7.1/gdb/target.c gdb-6.7.1-patched/gdb/target.c
b0ab3a8
--- gdb-6.7.1/gdb/target.c	2007-11-04 01:43:03.000000000 +0100
b0ab3a8
+++ gdb-6.7.1-patched/gdb/target.c	2007-11-04 01:37:45.000000000 +0100
b0ab3a8
@@ -819,6 +819,25 @@ pop_target (void)
b0ab3a8
   internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
b0ab3a8
 }
b0ab3a8
 
b0ab3a8
+static int
b0ab3a8
+resolve_errno (void *arg)
b0ab3a8
+{
b0ab3a8
+  CORE_ADDR *arg_addr = arg;
b0ab3a8
+  struct expression *expr;
b0ab3a8
+  struct cleanup *old_chain = 0;
b0ab3a8
+  struct value *val;
b0ab3a8
+
b0ab3a8
+  expr = parse_expression ("__errno_location()");
b0ab3a8
+  old_chain = make_cleanup (free_current_contents, &expr;;
b0ab3a8
+  val = evaluate_expression (expr);
b0ab3a8
+  *arg_addr = value_as_address (val);
b0ab3a8
+  release_value (val);
b0ab3a8
+  value_free (val);
b0ab3a8
+  do_cleanups (old_chain);
b0ab3a8
+
b0ab3a8
+  return 1;
b0ab3a8
+}
b0ab3a8
+
b0ab3a8
 /* Using the objfile specified in BATON, find the address for the
b0ab3a8
    current thread's thread-local storage with offset OFFSET.  */
b0ab3a8
 CORE_ADDR
b0ab3a8
@@ -906,7 +925,22 @@ target_translate_tls_address (struct obj
aefb0e1
   /* It wouldn't be wrong here to try a gdbarch method, too; finding
aefb0e1
      TLS is an ABI-specific thing.  But we don't do that yet.  */
aefb0e1
   else
ba67a79
-    error (_("Cannot find thread-local variables on this target"));
ba67a79
+    {
ba67a79
+      struct minimal_symbol *msymbol;
ba67a79
+
ba67a79
+      msymbol = lookup_minimal_symbol ("errno", NULL, NULL);
ba67a79
+      if (msymbol != NULL
ba67a79
+	  && SYMBOL_VALUE_ADDRESS (msymbol) == offset
ba67a79
+	  && SYMBOL_BFD_SECTION (msymbol)->owner == objfile->obfd)
b0ab3a8
+	{
b0ab3a8
+	  if (!catch_errors (resolve_errno, (void *) &addr, "",
b0ab3a8
+	                     RETURN_MASK_ALL))
b0ab3a8
+	    error (_("TLS symbol `errno' not resolved for non-TLS program."
b0ab3a8
+		     "  You should compile the program with `gcc -pthread'."));
b0ab3a8
+	}
b0ab3a8
+      else
b0ab3a8
+	error (_("Cannot find thread-local variables on this target"));
ba67a79
+    }
ba67a79
 
aefb0e1
   return addr;
ba67a79
 }
b0ab3a8
diff -u -X /home/jkratoch/.diffi.list -rup gdb-6.7.1/gdb/testsuite/gdb.dwarf2/dw2-errno.c gdb-6.7.1-patched/gdb/testsuite/gdb.dwarf2/dw2-errno.c
b0ab3a8
--- gdb-6.7.1/gdb/testsuite/gdb.dwarf2/dw2-errno.c	2007-11-04 01:43:41.000000000 +0100
b0ab3a8
+++ gdb-6.7.1-patched/gdb/testsuite/gdb.dwarf2/dw2-errno.c	2007-11-03 23:29:02.000000000 +0100
b0ab3a8
@@ -0,0 +1,28 @@
b0ab3a8
+/* This testcase is part of GDB, the GNU debugger.
b0ab3a8
+
b0ab3a8
+   Copyright 2005, 2007 Free Software Foundation, Inc.
b0ab3a8
+
b0ab3a8
+   This program is free software; you can redistribute it and/or modify
b0ab3a8
+   it under the terms of the GNU General Public License as published by
b0ab3a8
+   the Free Software Foundation; either version 3 of the License, or
b0ab3a8
+   (at your option) any later version.
b0ab3a8
+
b0ab3a8
+   This program is distributed in the hope that it will be useful,
b0ab3a8
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
b0ab3a8
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
b0ab3a8
+   GNU General Public License for more details.
b0ab3a8
+
b0ab3a8
+   You should have received a copy of the GNU General Public License
b0ab3a8
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
b0ab3a8
+
b0ab3a8
+   Please email any bugs, comments, and/or additions to this file to:
b0ab3a8
+   bug-gdb@prep.ai.mit.edu  */
b0ab3a8
+
b0ab3a8
+#include <errno.h>
b0ab3a8
+
b0ab3a8
+int main()
b0ab3a8
+{
b0ab3a8
+  errno = 42;
b0ab3a8
+
b0ab3a8
+  return 0;	/* breakpoint */
b0ab3a8
+}
b0ab3a8
diff -u -X /home/jkratoch/.diffi.list -rup gdb-6.7.1/gdb/testsuite/gdb.dwarf2/dw2-errno.exp gdb-6.7.1-patched/gdb/testsuite/gdb.dwarf2/dw2-errno.exp
b0ab3a8
--- gdb-6.7.1/gdb/testsuite/gdb.dwarf2/dw2-errno.exp	2007-11-04 01:43:39.000000000 +0100
b0ab3a8
+++ gdb-6.7.1-patched/gdb/testsuite/gdb.dwarf2/dw2-errno.exp	2007-11-04 01:41:46.000000000 +0100
b0ab3a8
@@ -0,0 +1,67 @@
b0ab3a8
+# Copyright 2007 Free Software Foundation, Inc.
b0ab3a8
+
b0ab3a8
+# This program is free software; you can redistribute it and/or modify
b0ab3a8
+# it under the terms of the GNU General Public License as published by
b0ab3a8
+# the Free Software Foundation; either version 3 of the License, or
b0ab3a8
+# (at your option) any later version.
b0ab3a8
+#
b0ab3a8
+# This program is distributed in the hope that it will be useful,
b0ab3a8
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
b0ab3a8
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
b0ab3a8
+# GNU General Public License for more details.
b0ab3a8
+#
b0ab3a8
+# You should have received a copy of the GNU General Public License
b0ab3a8
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
b0ab3a8
+
b0ab3a8
+if $tracelevel then {
b0ab3a8
+    strace $tracelevel
b0ab3a8
+}
b0ab3a8
+
b0ab3a8
+set prms_id 0
b0ab3a8
+set bug_id 0
b0ab3a8
+
b0ab3a8
+set testfile dw2-errno
b0ab3a8
+set srcfile ${testfile}.c
b0ab3a8
+set binfile ${objdir}/${subdir}/${testfile}
b0ab3a8
+
b0ab3a8
+proc prep {} {
b0ab3a8
+    global srcdir subdir binfile
b0ab3a8
+    gdb_exit
b0ab3a8
+    gdb_start
b0ab3a8
+    gdb_reinitialize_dir $srcdir/$subdir
b0ab3a8
+    gdb_load ${binfile}
b0ab3a8
+
b0ab3a8
+    runto_main
b0ab3a8
+
b0ab3a8
+    gdb_breakpoint [gdb_get_line_number "breakpoint"]
b0ab3a8
+    gdb_continue_to_breakpoint "breakpoint"
b0ab3a8
+}
b0ab3a8
+
b0ab3a8
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "additional_flags=-g2"] != "" } {
b0ab3a8
+    untested "Couldn't compile test program"
b0ab3a8
+    return -1
b0ab3a8
+}
b0ab3a8
+prep
b0ab3a8
+gdb_test "print errno" ".* = 42" "errno with macros=N threads=N"
b0ab3a8
+
b0ab3a8
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "additional_flags=-g3"] != "" } {
b0ab3a8
+    untested "Couldn't compile test program"
b0ab3a8
+    return -1
b0ab3a8
+}
b0ab3a8
+prep
b0ab3a8
+gdb_test "print errno" ".* = 42" "errno with macros=Y threads=N"
b0ab3a8
+
b0ab3a8
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "additional_flags=-g2"] != "" } {
b0ab3a8
+    return -1
b0ab3a8
+}
b0ab3a8
+prep
b0ab3a8
+gdb_test "print errno" ".* = 42" "errno with macros=N threads=Y"
b0ab3a8
+
b0ab3a8
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "additional_flags=-g3"] != "" } {
b0ab3a8
+    return -1
b0ab3a8
+}
b0ab3a8
+prep
b0ab3a8
+gdb_test "print errno" ".* = 42" "errno with macros=Y threads=Y"
b0ab3a8
+
b0ab3a8
+# TODO: Test the error on resolving ERRNO with only libc loaded.
b0ab3a8
+# Just how to find the current libc filename?