From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 1814 invoked by alias); 4 Sep 2007 14:19:40 -0000 Received: (qmail 1805 invoked by uid 22791); 4 Sep 2007 14:19:38 -0000 X-Spam-Check-By: sourceware.org Received: from NaN.false.org (HELO nan.false.org) (208.75.86.248) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 04 Sep 2007 14:19:29 +0000 Received: from nan.false.org (localhost [127.0.0.1]) by nan.false.org (Postfix) with ESMTP id 5659D982A2; Tue, 4 Sep 2007 14:19:29 +0000 (GMT) Received: from caradoc.them.org (22.svnf5.xdsl.nauticom.net [209.195.183.55]) by nan.false.org (Postfix) with ESMTP id 2C6539810A; Tue, 4 Sep 2007 14:19:29 +0000 (GMT) Received: from drow by caradoc.them.org with local (Exim 4.67) (envelope-from ) id 1ISZFW-0004L4-49; Tue, 04 Sep 2007 10:19:26 -0400 Date: Tue, 04 Sep 2007 14:19:00 -0000 From: Daniel Jacobowitz To: Mark Kettenis Cc: jan.kratochvil@redhat.com, gdb-patches@sourceware.org Subject: Re: [patch] printf "%p" gdb internal error fix Message-ID: <20070904141926.GA27477@caradoc.them.org> Mail-Followup-To: Mark Kettenis , jan.kratochvil@redhat.com, gdb-patches@sourceware.org References: <20060910172037.GA3886@host0.dyn.jankratochvil.net> <200609101931.k8AJVF4m026090@elgar.sibelius.xs4all.nl> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <200609101931.k8AJVF4m026090@elgar.sibelius.xs4all.nl> User-Agent: Mutt/1.5.15 (2007-04-09) X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2007-09/txt/msg00047.txt.bz2 On Sun, Sep 10, 2006 at 09:31:15PM +0200, Mark Kettenis wrote: > > Date: Sun, 10 Sep 2006 19:20:37 +0200 > > From: Jan Kratochvil > > > > Hi, > > > > (gdb) printf "%p\n", (void *) 7 > > internal error in printf_command > Hmm, this will not do the right thing when you try to print a 64-bit > pointer on a 32-bit host. Better late than never... Here is a patch for %p which does not rely on the size of a host pointer. Instead of using the underlying system's printf, it chooses the same implementation-defined behavior chosen by glibc (%#x for non-zero pointers and "(nil)" for null pointers). I tested this on x86_64-linux and checked it in. -- Daniel Jacobowitz CodeSourcery 2007-09-04 Daniel Jacobowitz * printcmd.c (printf_command): Handle ptr_arg. Correct typo in internal error message. 2007-09-04 Daniel Jacobowitz * gdb.base/display.exp: Add tests for printf %p. Index: printcmd.c =================================================================== RCS file: /cvs/src/src/gdb/printcmd.c,v retrieving revision 1.109 diff -u -p -r1.109 printcmd.c --- printcmd.c 23 Aug 2007 18:08:36 -0000 1.109 +++ printcmd.c 4 Sep 2007 13:59:44 -0000 @@ -2079,9 +2079,68 @@ printf_command (char *arg, int from_tty) printf_filtered (current_substring, val); break; } + case ptr_arg: + { + /* We avoid the host's %p because pointers are too + likely to be the wrong size. The only interesting + modifier for %p is a width; extract that, and then + handle %p as glibc would: %#x or a literal "(nil)". */ + + char *p, *fmt, *fmt_p; +#if defined (CC_HAS_LONG_LONG) && defined (PRINTF_HAS_LONG_LONG) + long long val = value_as_long (val_args[i]); +#else + long val = value_as_long (val_args[i]); +#endif + + fmt = alloca (strlen (current_substring) + 5); + + /* Copy up to the leading %. */ + p = current_substring; + fmt_p = fmt; + while (*p) + { + int is_percent = (*p == '%'); + *fmt_p++ = *p++; + if (is_percent) + { + if (*p == '%') + *fmt_p++ = *p++; + else + break; + } + } + + if (val != 0) + *fmt_p++ = '#'; + + /* Copy any width. */ + while (*p >= '0' && *p < '9') + *fmt_p++ = *p++; + + gdb_assert (*p == 'p' && *(p + 1) == '\0'); + if (val != 0) + { +#if defined (CC_HAS_LONG_LONG) && defined (PRINTF_HAS_LONG_LONG) + *fmt_p++ = 'l'; +#endif + *fmt_p++ = 'l'; + *fmt_p++ = 'x'; + *fmt_p++ = '\0'; + printf_filtered (fmt, val); + } + else + { + *fmt_p++ = 's'; + *fmt_p++ = '\0'; + printf_filtered (fmt, "(nil)"); + } + + break; + } default: internal_error (__FILE__, __LINE__, - _("failed internal consitency check")); + _("failed internal consistency check")); } /* Skip to the next substring. */ current_substring += strlen (current_substring) + 1; Index: testsuite/gdb.base/display.exp =================================================================== RCS file: /cvs/src/src/gdb/testsuite/gdb.base/display.exp,v retrieving revision 1.11 diff -u -p -r1.11 display.exp --- testsuite/gdb.base/display.exp 23 Aug 2007 18:14:16 -0000 1.11 +++ testsuite/gdb.base/display.exp 4 Sep 2007 13:59:45 -0000 @@ -178,6 +178,8 @@ gdb_test "printf \"\\\\!\\a\\f\\r\\t\\v\ gdb_test "printf \"\"" ".*" "re-set term" gdb_test "printf \"\\w\"" ".*Unrecognized escape character.*" gdb_test "printf \"%d\" j" ".*Invalid argument syntax.*" +gdb_test "printf \"%p\\n\", 0" "\\(nil\\)" +gdb_test "printf \"%p\\n\", 1" "0x1" # play with "print", too #