Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Jan Kratochvil <jan.kratochvil@redhat.com>
To: Mark Kettenis <mark.kettenis@xs4all.nl>
Cc: drow@false.org, gdb-patches@sourceware.org
Subject: Re: [patch] Fix `return' of long/long-long results with no 	debuginfo
Date: Sat, 21 Feb 2009 12:47:00 -0000	[thread overview]
Message-ID: <20090221000409.GA8771@host0.dyn.jankratochvil.net> (raw)
In-Reply-To: <200902112244.n1BMiK36012947@brahms.sibelius.xs4all.nl>

On Wed, 11 Feb 2009 23:44:21 +0100, Mark Kettenis wrote:
> Thinking a bit more of this now, things all depend on the calling
> convention.  I'm not convinced casting to `long long' is safe in all
> cases, especially on 32-bit big-endian machines.  It really might do
> the wrong thing there, exposing garbage or the wrong 32 bits of the
> 64-bit value.

OK to check-in this patch?

This patch could have a regression on ABI which defines caller saved vs.
callee saved registers depending on the return type of the function.  I do not
believe there exists such ABI.

Regression-tested on GNU/Linux on:
HEAD{x86_64}, 6.8{x86_64(+inf. i386), i386, s390x(+inf. s390), ia64}


Thanks,
Jan


gdb/
2009-02-20  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* stack.c (return_extended_value_cast, return_extended_value): New.
	(return_command): Returned type for functions with no debug info has
	now at least the width of the type of user specified expression while
	it tries to use the largest compatible width.

gdb/testsuite/
2009-02-20  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* gdb.base/return-nodebug.exp, gdb.base/return-nodebug.S: New.

--- gdb/stack.c	11 Feb 2009 16:07:28 -0000	1.185
+++ gdb/stack.c	20 Feb 2009 21:47:34 -0000
@@ -1777,7 +1777,75 @@ down_command (char *count_exp, int from_
   down_silently_base (count_exp);
   print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC);
 }
-\f
+
+/* Verify whether if RETURN_VALUE width gets extended to EXT_TYPE it will still
+   be the same value after reading it back using the RETURN_VALUE type.  */
+
+static int
+return_extended_value_cast (struct value *return_value, struct type *ext_type)
+{
+  struct regcache *current_regcache = get_current_regcache ();
+  struct gdbarch *gdbarch = get_regcache_arch (current_regcache);
+  struct type *return_type = value_type (return_value);
+  struct value *ext_value, *compare_value;
+
+  if (gdbarch_return_value (gdbarch, NULL, ext_type, NULL, NULL, NULL)
+      != RETURN_VALUE_REGISTER_CONVENTION)
+    return 0;
+
+  ext_value = value_cast (ext_type, return_value);
+  gdbarch_return_value (gdbarch, NULL, ext_type,
+			current_regcache, NULL /*read*/,
+			value_contents (ext_value) /*write*/);
+
+  compare_value = allocate_value (return_type);
+  gdbarch_return_value (gdbarch, NULL, return_type, current_regcache,
+			value_contents_raw (compare_value) /*read*/,
+			NULL /*write*/);
+
+  return value_equal (return_value, compare_value);
+}
+
+/* Set RETURN_VALUE extended to the largest type width which will still be the
+   same value after reading it back using the RETURN_VALUE type.  */
+
+static void
+return_extended_value (struct value *return_value)
+{
+  struct type *return_type = value_type (return_value);
+  struct regcache *current_regcache = get_current_regcache ();
+  struct gdbarch *gdbarch = get_regcache_arch (current_regcache);
+  const struct builtin_type *builtins = builtin_type (gdbarch);
+  struct type **extp, *ext_tab[] =
+    {
+      builtins->builtin_long_long,
+      builtins->builtin_long,
+      return_type
+    };
+  unsigned width_tried = 0;
+
+  for (extp = ext_tab; extp < ext_tab + ARRAY_SIZE (ext_tab); extp++)
+    {
+      struct type *ext_type = *extp;
+
+      /* Do not retry extension to the integer of an already tried width.  */
+      if (ext_type != return_type && width_tried == TYPE_LENGTH (ext_type))
+	continue;
+
+      /* Do not extend to non-original smaller (or the same size) type.  */
+      if (ext_type != return_type
+	  && TYPE_LENGTH (ext_type) <= TYPE_LENGTH (return_type))
+	continue;
+
+      gdb_assert (TYPE_LENGTH (return_type) <= TYPE_LENGTH (ext_type));
+      width_tried = TYPE_LENGTH (ext_type);
+      if (return_extended_value_cast (return_value, ext_type))
+	break;
+    }
+
+  /* Ensure at least the attempt with original RETURN_TYPE was successful.  */
+  gdb_assert (extp < ext_tab + ARRAY_SIZE (ext_tab));
+}
 
 void
 return_command (char *retval_exp, int from_tty)
@@ -1806,6 +1874,8 @@ return_command (char *retval_exp, int fr
          the cast fail, this call throws an error.  */
       if (thisfun != NULL)
 	return_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (thisfun));
+      else
+	return_type = value_type (return_value);
       if (return_type == NULL)
 	return_type = builtin_type (get_frame_arch (thisframe))->builtin_int;
       CHECK_TYPEDEF (return_type);
@@ -1862,9 +1932,13 @@ If you continue, the return value that y
       gdb_assert (gdbarch_return_value (gdbarch, func_type, return_type, NULL,
 					NULL, NULL)
 		  == RETURN_VALUE_REGISTER_CONVENTION);
-      gdbarch_return_value (gdbarch, func_type, return_type,
-			    get_current_regcache (), NULL /*read*/,
-			    value_contents (return_value) /*write*/);
+
+      if (thisfun != NULL)
+	gdbarch_return_value (gdbarch, func_type, return_type,
+			      get_current_regcache (), NULL /*read*/,
+			      value_contents (return_value) /*write*/);
+      else
+	return_extended_value (return_value);
     }
 
   /* If we are at the end of a call dummy now, pop the dummy frame
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gdb/testsuite/gdb.base/return-nodebug.c	20 Feb 2009 21:47:34 -0000
@@ -0,0 +1,49 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2009 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/>.  */
+
+#include <stdio.h>
+
+static TYPE
+init (void)
+{
+  return 0;
+}
+
+static TYPE
+func (void)
+{
+  return 31;
+}
+
+static void
+marker (void)
+{
+}
+
+int
+main (void)
+{
+  /* Preinitialize registers to 0 to avoid false PASS by leftover garbage.  */
+  init ();
+
+  printf ("result=" FORMAT "\n", CAST func ());
+
+  /* Cannot `next' with no debug info.  */
+  marker ();
+
+  return 0;
+}
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gdb/testsuite/gdb.base/return-nodebug.exp	20 Feb 2009 21:47:34 -0000
@@ -0,0 +1,54 @@
+# Copyright (C) 2009 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/>.
+
+proc do_test {type} {
+    set typenospace [string map {{ } -} $type]
+
+    global pf_prefix
+    set old_prefix $pf_prefix
+    lappend pf_prefix "$typenospace:"
+
+    if {[runto "func"]} {
+	# Test return from a function with no debug info (symbol; still it may
+	# have a minimal-symbol) if it does not crash.
+	gdb_test "return -1" "#0 .* main \\(.*"			\
+		 "return from function with no debug info"	\
+		 "Make selected stack frame return now\\? \\(y or n\\) " "y"
+
+	# And if it returned the full width of the result.
+	gdb_test "adv marker" "\r\nresult=-1\r\n.* in marker \\(.*" \
+		 "full width of the returned result"
+    }
+
+    set pf_prefix $old_prefix
+}
+
+foreach case {{{signed char} %d (int)}	\
+	      {{short}       %d (int)}	\
+	      {{int}         %d}	\
+	      {{long}        %ld}	\
+	      {{long long}   %lld}}	{
+    set type [lindex $case 0]
+    set format [lindex $case 1]
+    set cast [lindex $case 2]
+
+    set typeesc [string map {{ } {\ }} $type]
+    set typenospace [string map {{ } -} $type]
+
+    if {[prepare_for_testing return-nodebug.exp "return-nodebug-$typenospace" "return-nodebug.c" \
+	 [list "additional_flags=-DFORMAT=\"$format\" -DTYPE=$typeesc -DCAST=$cast"]] == 0} {
+	do_test $type
+    }
+}


  parent reply	other threads:[~2009-02-21  0:04 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-02-11 19:45 Jan Kratochvil
2009-02-11 20:40 ` Mark Kettenis
2009-02-11 20:50   ` Daniel Jacobowitz
2009-02-11 21:23     ` Mark Kettenis
2009-02-11 21:47       ` Jan Kratochvil
2009-02-11 21:58         ` Mark Kettenis
2009-02-11 22:08           ` Jan Kratochvil
2009-02-11 22:38             ` Mark Kettenis
2009-02-11 22:50               ` Jan Kratochvil
2009-03-03 18:10                 ` Tom Tromey
2009-03-04 21:29                   ` Mark Kettenis
2009-03-05  0:15                     ` Tom Tromey
2009-03-09  1:55                       ` Jan Kratochvil
2009-03-09 22:38                         ` Mark Kettenis
2009-03-11 16:49                           ` Joel Brobecker
2009-03-11 20:23                             ` Tom Tromey
2009-03-11 21:48                               ` Joel Brobecker
2009-03-13 19:50                                 ` Jan Kratochvil
2009-03-13 23:00                                   ` Joel Brobecker
2009-03-14 10:45                                   ` Eli Zaretskii
2009-03-14 22:09                                     ` Jan Kratochvil
2009-03-14 22:18                                       ` Eli Zaretskii
2009-03-15  9:22                                       ` Joel Brobecker
2009-03-15 18:15                                         ` Jan Kratochvil
2009-03-18  4:36                                           ` Pedro Alves
2009-03-18 14:44                                             ` Joel Brobecker
2009-03-18 15:39                                             ` Jan Kratochvil
2009-03-18 15:46                                               ` Pedro Alves
2009-02-11 22:44         ` Mark Kettenis
2009-02-12  9:41           ` Jan Kratochvil
2009-02-12 14:36             ` Pierre Muller
2009-02-12 14:44               ` Jan Kratochvil
2009-02-14 21:59             ` Mark Kettenis
2009-02-21 12:47           ` Jan Kratochvil [this message]
2009-02-21 13:44             ` Mark Kettenis
2009-02-21 15:58   ` Jan Kratochvil
2009-02-21 16:21     ` Mark Kettenis
2009-02-21 16:32       ` Jan Kratochvil

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090221000409.GA8771@host0.dyn.jankratochvil.net \
    --to=jan.kratochvil@redhat.com \
    --cc=drow@false.org \
    --cc=gdb-patches@sourceware.org \
    --cc=mark.kettenis@xs4all.nl \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox