* [pushed/v2 1/9] gdb/configure: Add --with-libgmp-prefix option
2020-11-15 8:35 ` pushed: " Joel Brobecker
@ 2020-11-15 8:35 ` Joel Brobecker
2020-11-15 15:52 ` Bernd Edlinger
2020-11-15 8:35 ` [pushed/v2 2/9] gdb: Make GMP a required dependency for building GDB Joel Brobecker
` (10 subsequent siblings)
11 siblings, 1 reply; 140+ messages in thread
From: Joel Brobecker @ 2020-11-15 8:35 UTC (permalink / raw)
To: gdb-patches; +Cc: Simon Marchi, Joel Brobecker
This patch allows a user to tell gdb's configure script where
his GMP library is installed.
gdb/ChangeLog:
* configure.ac: Add support for --with-libgmp-prefix.
* Makefile.in (LIBGMP): New variable.
(CLIBS): Include $(LIBGMP).
* configure, config.in: Regenerate
---
gdb/ChangeLog | 7 +
gdb/Makefile.in | 5 +-
gdb/config.in | 3 +
gdb/configure | 488 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
gdb/configure.ac | 5 +
5 files changed, 507 insertions(+), 1 deletion(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a70c5fe..ee1dea3 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,10 @@
+2020-11-15 Joel Brobecker <brobecker@adacore.com>
+
+ * configure.ac: Add support for --with-libgmp-prefix.
+ * Makefile.in (LIBGMP): New variable.
+ (CLIBS): Include $(LIBGMP).
+ * configure, config.in: Regenerate
+
2020-11-14 Andrew Burgess <andrew.burgess@embecosm.com>
PR cli/26879
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index c46935e..c461964 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -203,6 +203,9 @@ LIBXXHASH = @LIBXXHASH@
# Where is libipt? This will be empty if libipt was not available.
LIBIPT = @LIBIPT@
+# Where is libgmp?
+LIBGMP = @LIBGMP@
+
# Where is libmpfr? This will be empty if libmpfr was not available.
LIBMPFR = @LIBMPFR@
@@ -632,7 +635,7 @@ CLIBS = $(SIM) $(READLINE) $(OPCODES) $(LIBCTF) $(BFD) $(ZLIB) \
@LIBS@ @GUILE_LIBS@ @PYTHON_LIBS@ \
$(LIBEXPAT) $(LIBLZMA) $(LIBBABELTRACE) $(LIBIPT) \
$(WIN32LIBS) $(LIBGNU) $(LIBGNU_EXTRA_LIBS) $(LIBICONV) \
- $(LIBMPFR) $(SRCHIGH_LIBS) $(LIBXXHASH) $(PTHREAD_LIBS) \
+ $(LIBMPFR) $(LIBGMP) $(SRCHIGH_LIBS) $(LIBXXHASH) $(PTHREAD_LIBS) \
$(DEBUGINFOD_LIBS)
CDEPS = $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE_DEPS) $(CTF_DEPS) \
$(OPCODES) $(INTL_DEPS) $(LIBIBERTY) $(CONFIG_DEPS) $(LIBGNU) \
diff --git a/gdb/config.in b/gdb/config.in
index 3e741c6..14a77c6 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -229,6 +229,9 @@
/* Define if you have the expat library. */
#undef HAVE_LIBEXPAT
+/* Define if you have the gmp library. */
+#undef HAVE_LIBGMP
+
/* Define to 1 if you have the `libiconvlist' function. */
#undef HAVE_LIBICONVLIST
diff --git a/gdb/configure b/gdb/configure
index 4a03cd9..2bf0856 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -732,6 +732,9 @@ python_prog_path
LTLIBMPFR
LIBMPFR
HAVE_LIBMPFR
+LTLIBGMP
+LIBGMP
+HAVE_LIBGMP
LTLIBEXPAT
LIBEXPAT
HAVE_LIBEXPAT
@@ -896,6 +899,8 @@ with_jit_reader_dir
with_expat
with_libexpat_prefix
with_libexpat_type
+with_libgmp_prefix
+with_libgmp_type
with_mpfr
with_libmpfr_prefix
with_libmpfr_type
@@ -1639,6 +1644,9 @@ Optional Packages:
--with-libexpat-prefix[=DIR] search for libexpat in DIR/include and DIR/lib
--without-libexpat-prefix don't search for libexpat in includedir and libdir
--with-libexpat-type=TYPE type of library to search for (auto/static/shared)
+ --with-libgmp-prefix[=DIR] search for libgmp in DIR/include and DIR/lib
+ --without-libgmp-prefix don't search for libgmp in includedir and libdir
+ --with-libgmp-type=TYPE type of library to search for (auto/static/shared)
--with-mpfr include MPFR support (auto/yes/no)
--with-libmpfr-prefix[=DIR] search for libmpfr in DIR/include and DIR/lib
--without-libmpfr-prefix don't search for libmpfr in includedir and libdir
@@ -9982,6 +9990,486 @@ done
fi
fi
+# Verify that we have a usable GMP library.
+
+
+
+
+
+
+
+
+ use_additional=yes
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+
+# Check whether --with-libgmp-prefix was given.
+if test "${with_libgmp_prefix+set}" = set; then :
+ withval=$with_libgmp_prefix;
+ if test "X$withval" = "Xno"; then
+ use_additional=no
+ else
+ if test "X$withval" = "X"; then
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ else
+ additional_includedir="$withval/include"
+ additional_libdir="$withval/lib"
+ fi
+ fi
+
+fi
+
+
+# Check whether --with-libgmp-type was given.
+if test "${with_libgmp_type+set}" = set; then :
+ withval=$with_libgmp_type; with_libgmp_type=$withval
+else
+ with_libgmp_type=auto
+fi
+
+ lib_type=`eval echo \$with_libgmp_type`
+
+ LIBGMP=
+ LTLIBGMP=
+ INCGMP=
+ rpathdirs=
+ ltrpathdirs=
+ names_already_handled=
+ names_next_round='gmp '
+ while test -n "$names_next_round"; do
+ names_this_round="$names_next_round"
+ names_next_round=
+ for name in $names_this_round; do
+ already_handled=
+ for n in $names_already_handled; do
+ if test "$n" = "$name"; then
+ already_handled=yes
+ break
+ fi
+ done
+ if test -z "$already_handled"; then
+ names_already_handled="$names_already_handled $name"
+ uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'`
+ eval value=\"\$HAVE_LIB$uppername\"
+ if test -n "$value"; then
+ if test "$value" = yes; then
+ eval value=\"\$LIB$uppername\"
+ test -z "$value" || LIBGMP="${LIBGMP}${LIBGMP:+ }$value"
+ eval value=\"\$LTLIB$uppername\"
+ test -z "$value" || LTLIBGMP="${LTLIBGMP}${LTLIBGMP:+ }$value"
+ else
+ :
+ fi
+ else
+ found_dir=
+ found_la=
+ found_so=
+ found_a=
+ if test $use_additional = yes; then
+ if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext" && test x$lib_type != xstatic; then
+ found_dir="$additional_libdir"
+ found_so="$additional_libdir/lib$name.$shlibext"
+ if test -f "$additional_libdir/lib$name.la"; then
+ found_la="$additional_libdir/lib$name.la"
+ fi
+ elif test x$lib_type != xshared; then
+ if test -f "$additional_libdir/lib$name.$libext"; then
+ found_dir="$additional_libdir"
+ found_a="$additional_libdir/lib$name.$libext"
+ if test -f "$additional_libdir/lib$name.la"; then
+ found_la="$additional_libdir/lib$name.la"
+ fi
+ fi
+ fi
+ fi
+ if test "X$found_dir" = "X"; then
+ for x in $LDFLAGS $LTLIBGMP; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ case "$x" in
+ -L*)
+ dir=`echo "X$x" | sed -e 's/^X-L//'`
+ if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext" && test x$lib_type != xstatic; then
+ found_dir="$dir"
+ found_so="$dir/lib$name.$shlibext"
+ if test -f "$dir/lib$name.la"; then
+ found_la="$dir/lib$name.la"
+ fi
+ elif test x$lib_type != xshared; then
+ if test -f "$dir/lib$name.$libext"; then
+ found_dir="$dir"
+ found_a="$dir/lib$name.$libext"
+ if test -f "$dir/lib$name.la"; then
+ found_la="$dir/lib$name.la"
+ fi
+ fi
+ fi
+ ;;
+ esac
+ if test "X$found_dir" != "X"; then
+ break
+ fi
+ done
+ fi
+ if test "X$found_dir" != "X"; then
+ LTLIBGMP="${LTLIBGMP}${LTLIBGMP:+ }-L$found_dir -l$name"
+ if test "X$found_so" != "X"; then
+ if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/lib"; then
+ LIBGMP="${LIBGMP}${LIBGMP:+ }$found_so"
+ else
+ haveit=
+ for x in $ltrpathdirs; do
+ if test "X$x" = "X$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ ltrpathdirs="$ltrpathdirs $found_dir"
+ fi
+ if test "$hardcode_direct" = yes; then
+ LIBGMP="${LIBGMP}${LIBGMP:+ }$found_so"
+ else
+ if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then
+ LIBGMP="${LIBGMP}${LIBGMP:+ }$found_so"
+ haveit=
+ for x in $rpathdirs; do
+ if test "X$x" = "X$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ rpathdirs="$rpathdirs $found_dir"
+ fi
+ else
+ haveit=
+ for x in $LDFLAGS $LIBGMP; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ if test "X$x" = "X-L$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ LIBGMP="${LIBGMP}${LIBGMP:+ }-L$found_dir"
+ fi
+ if test "$hardcode_minus_L" != no; then
+ LIBGMP="${LIBGMP}${LIBGMP:+ }$found_so"
+ else
+ LIBGMP="${LIBGMP}${LIBGMP:+ }-l$name"
+ fi
+ fi
+ fi
+ fi
+ else
+ if test "X$found_a" != "X"; then
+ LIBGMP="${LIBGMP}${LIBGMP:+ }$found_a"
+ else
+ LIBGMP="${LIBGMP}${LIBGMP:+ }-L$found_dir -l$name"
+ fi
+ fi
+ additional_includedir=
+ case "$found_dir" in
+ */lib | */lib/)
+ basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'`
+ additional_includedir="$basedir/include"
+ ;;
+ esac
+ if test "X$additional_includedir" != "X"; then
+ if test "X$additional_includedir" != "X/usr/include"; then
+ haveit=
+ if test "X$additional_includedir" = "X/usr/local/include"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux*) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ for x in $CPPFLAGS $INCGMP; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ if test "X$x" = "X-I$additional_includedir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_includedir"; then
+ INCGMP="${INCGMP}${INCGMP:+ }-I$additional_includedir"
+ fi
+ fi
+ fi
+ fi
+ fi
+ if test -n "$found_la"; then
+ save_libdir="$libdir"
+ case "$found_la" in
+ */* | *\\*) . "$found_la" ;;
+ *) . "./$found_la" ;;
+ esac
+ libdir="$save_libdir"
+ for dep in $dependency_libs; do
+ case "$dep" in
+ -L*)
+ additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
+ if test "X$additional_libdir" != "X/usr/lib"; then
+ haveit=
+ if test "X$additional_libdir" = "X/usr/local/lib"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux*) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ haveit=
+ for x in $LDFLAGS $LIBGMP; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ if test "X$x" = "X-L$additional_libdir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_libdir"; then
+ LIBGMP="${LIBGMP}${LIBGMP:+ }-L$additional_libdir"
+ fi
+ fi
+ haveit=
+ for x in $LDFLAGS $LTLIBGMP; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ if test "X$x" = "X-L$additional_libdir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_libdir"; then
+ LTLIBGMP="${LTLIBGMP}${LTLIBGMP:+ }-L$additional_libdir"
+ fi
+ fi
+ fi
+ fi
+ ;;
+ -R*)
+ dir=`echo "X$dep" | sed -e 's/^X-R//'`
+ if test "$enable_rpath" != no; then
+ haveit=
+ for x in $rpathdirs; do
+ if test "X$x" = "X$dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ rpathdirs="$rpathdirs $dir"
+ fi
+ haveit=
+ for x in $ltrpathdirs; do
+ if test "X$x" = "X$dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ ltrpathdirs="$ltrpathdirs $dir"
+ fi
+ fi
+ ;;
+ -l*)
+ names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
+ ;;
+ *.la)
+ names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
+ ;;
+ *)
+ LIBGMP="${LIBGMP}${LIBGMP:+ }$dep"
+ LTLIBGMP="${LTLIBGMP}${LTLIBGMP:+ }$dep"
+ ;;
+ esac
+ done
+ fi
+ else
+ if test "x$lib_type" = "xauto" || test "x$lib_type" = "xshared"; then
+ LIBGMP="${LIBGMP}${LIBGMP:+ }-l$name"
+ LTLIBGMP="${LTLIBGMP}${LTLIBGMP:+ }-l$name"
+ else
+ LIBGMP="${LIBGMP}${LIBGMP:+ }-l:lib$name.$libext"
+ LTLIBGMP="${LTLIBGMP}${LTLIBGMP:+ }-l:lib$name.$libext"
+ fi
+ fi
+ fi
+ fi
+ done
+ done
+ if test "X$rpathdirs" != "X"; then
+ if test -n "$hardcode_libdir_separator"; then
+ alldirs=
+ for found_dir in $rpathdirs; do
+ alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir"
+ done
+ acl_save_libdir="$libdir"
+ libdir="$alldirs"
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ LIBGMP="${LIBGMP}${LIBGMP:+ }$flag"
+ else
+ for found_dir in $rpathdirs; do
+ acl_save_libdir="$libdir"
+ libdir="$found_dir"
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ LIBGMP="${LIBGMP}${LIBGMP:+ }$flag"
+ done
+ fi
+ fi
+ if test "X$ltrpathdirs" != "X"; then
+ for found_dir in $ltrpathdirs; do
+ LTLIBGMP="${LTLIBGMP}${LTLIBGMP:+ }-R$found_dir"
+ done
+ fi
+
+
+ ac_save_CPPFLAGS="$CPPFLAGS"
+
+ for element in $INCGMP; do
+ haveit=
+ for x in $CPPFLAGS; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ if test "X$x" = "X$element"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element"
+ fi
+ done
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libgmp" >&5
+$as_echo_n "checking for libgmp... " >&6; }
+if ${ac_cv_libgmp+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ac_save_LIBS="$LIBS"
+ LIBS="$LIBS $LIBGMP"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <gmp.h>
+int
+main ()
+{
+mpz_t n;
+ mpz_init (n);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_libgmp=yes
+else
+ ac_cv_libgmp=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LIBS="$ac_save_LIBS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libgmp" >&5
+$as_echo "$ac_cv_libgmp" >&6; }
+ if test "$ac_cv_libgmp" = yes; then
+ HAVE_LIBGMP=yes
+
+$as_echo "#define HAVE_LIBGMP 1" >>confdefs.h
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libgmp" >&5
+$as_echo_n "checking how to link with libgmp... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBGMP" >&5
+$as_echo "$LIBGMP" >&6; }
+ else
+ HAVE_LIBGMP=no
+ CPPFLAGS="$ac_save_CPPFLAGS"
+ LIBGMP=
+ LTLIBGMP=
+ fi
+
+
+
+
+
+
+
# Check whether --with-mpfr was given.
if test "${with_mpfr+set}" = set; then :
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 1b9548e..0264a4f 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -683,6 +683,11 @@ else
fi
fi
+# Verify that we have a usable GMP library.
+AC_LIB_HAVE_LINKFLAGS([gmp], [], [#include <gmp.h>],
+ [mpz_t n;
+ mpz_init (n);])
+
AC_ARG_WITH(mpfr,
AS_HELP_STRING([--with-mpfr], [include MPFR support (auto/yes/no)]),
[], [with_mpfr=auto])
--
2.1.4
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [pushed/v2 1/9] gdb/configure: Add --with-libgmp-prefix option
2020-11-15 8:35 ` [pushed/v2 1/9] gdb/configure: Add --with-libgmp-prefix option Joel Brobecker
@ 2020-11-15 15:52 ` Bernd Edlinger
2020-11-16 3:45 ` Joel Brobecker
0 siblings, 1 reply; 140+ messages in thread
From: Bernd Edlinger @ 2020-11-15 15:52 UTC (permalink / raw)
To: Joel Brobecker, gdb-patches; +Cc: Simon Marchi
[-- Attachment #1: Type: text/plain, Size: 1670 bytes --]
Hi Joel,
On 11/15/20 9:35 AM, Joel Brobecker wrote:
> This patch allows a user to tell gdb's configure script where
> his GMP library is installed.
>
> gdb/ChangeLog:
>
> * configure.ac: Add support for --with-libgmp-prefix.
> * Makefile.in (LIBGMP): New variable.
> (CLIBS): Include $(LIBGMP).
> * configure, config.in: Regenerate
> ---
> gdb/ChangeLog | 7 +
> gdb/Makefile.in | 5 +-
> gdb/config.in | 3 +
> gdb/configure | 488 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> gdb/configure.ac | 5 +
> 5 files changed, 507 insertions(+), 1 deletion(-)
>
I noticed that this does not allow to build gmp in-tree like it is
possible for gcc. I tried to overcome this by the attached patch.
While doing so, I also noticed an incompatibility with the top level
configure stript, which advertises, and passes -with-gmp-include
and -with-gmp-lib if in-tree gmp is found.
So the --with-libgmp-prefix is not that the top level configure
script suggests:
$ ./configure --help | grep gmp
--with-gmp-dir=PATH this option has been REMOVED
--with-gmp=PATH specify prefix directory for the installed GMP
--with-gmp-include=PATH/include plus
--with-gmp-lib=PATH/lib
--with-gmp-include=PATH specify directory for installed GMP include files
--with-gmp-lib=PATH specify directory for the installed GMP library
What do you think, can we allow these traditional configure options
additional to the new --with-libgmp-prefix?
Can we the top level Makefile.def change in binutils-gdb or has this
be checked-in first in gcc?
Thanks
Bernd.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Enable-GDB-build-with-in-tree-GMP.patch --]
[-- Type: text/x-patch; name="0001-Enable-GDB-build-with-in-tree-GMP.patch", Size: 5336 bytes --]
From ec85565bb963df25bdd46db19e1aeadc596c8424 Mon Sep 17 00:00:00 2001
From: Bernd Edlinger <bernd.edlinger@hotmail.de>
Date: Sun, 15 Nov 2020 15:37:22 +0100
Subject: [PATCH] Enable GDB build with in-tree GMP
Add --with-gmp= --with-gmp-include and --with-gmp-lib=
for compatibility with top level configure script.
2020-11-15 Bernd Edlinger <bernd.edlinger@hotmail.de>
* Makefile.def: Prepare for GDB build with intree GMP.
* Makefile.in: Regenerate.
gdb:
2020-11-15 Bernd Edlinger <bernd.edlinger@hotmail.de>
* configure.ac: Add --with-gmp= --with-gmp-include= and --with-gmp-lib=
for compatibility with top level configure script.
* configure: Regenerate.
---
Makefile.def | 4 +++-
Makefile.in | 3 ++-
gdb/configure | 35 +++++++++++++++++++++++++++++++++++
gdb/configure.ac | 16 ++++++++++++++++
4 files changed, 56 insertions(+), 2 deletions(-)
diff --git a/Makefile.def b/Makefile.def
index 089e70a..89aaef5 100644
--- a/Makefile.def
+++ b/Makefile.def
@@ -115,7 +115,8 @@ host_modules= { module= zlib; no_install=true; no_check=true;
host_modules= { module= gnulib; };
host_modules= { module= gdbsupport; };
host_modules= { module= gdbserver; };
-host_modules= { module= gdb; };
+host_modules= { module= gdb;
+ extra_configure_flags='@extra_mpfr_configure_flags@';};
host_modules= { module= expect; };
host_modules= { module= guile; };
host_modules= { module= tk; };
@@ -391,6 +392,7 @@ dependencies = { module=all-intl; on=all-libiconv; };
// Host modules specific to gdb.
dependencies = { module=configure-gdb; on=all-intl; };
+dependencies = { module=configure-gdb; on=all-gmp; };
dependencies = { module=configure-gdb; on=configure-sim; };
dependencies = { module=configure-gdb; on=all-bfd; };
dependencies = { module=configure-gdb; on=all-gnulib; };
diff --git a/Makefile.in b/Makefile.in
index fe34132..93780b7 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -29491,7 +29491,7 @@ configure-gdb:
$$s/$$module_srcdir/configure \
--srcdir=$${topdir}/$$module_srcdir \
$(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \
- --target=${target_alias} \
+ --target=${target_alias} @extra_mpfr_configure_flags@ \
|| exit 1
@endif gdb
@@ -52449,6 +52449,7 @@ configure-libcc1: maybe-configure-gcc
all-libcc1: maybe-all-gcc
all-utils: maybe-all-libiberty
configure-gdb: maybe-all-intl
+configure-gdb: maybe-all-gmp
configure-gdb: maybe-all-bfd
configure-gdb: maybe-all-libiconv
all-gdb: maybe-all-libiberty
diff --git a/gdb/configure b/gdb/configure
index a3e73b4..44bbce3 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -899,6 +899,9 @@ with_jit_reader_dir
with_expat
with_libexpat_prefix
with_libexpat_type
+with_gmp_include
+with_gmp_lib
+with_gmp
with_libgmp_prefix
with_libgmp_type
with_mpfr
@@ -1644,6 +1647,9 @@ Optional Packages:
--with-libexpat-prefix[=DIR] search for libexpat in DIR/include and DIR/lib
--without-libexpat-prefix don't search for libexpat in includedir and libdir
--with-libexpat-type=TYPE type of library to search for (auto/static/shared)
+ --with-gmp-include=DIR GMP include directory
+ --with-gmp-lib=DIR GMP lib directory
+ --with-gmp=DIR GMP install directory
--with-libgmp-prefix[=DIR] search for libgmp in DIR/include and DIR/lib
--without-libgmp-prefix don't search for libgmp in includedir and libdir
--with-libgmp-type=TYPE type of library to search for (auto/static/shared)
@@ -9990,6 +9996,35 @@ done
fi
fi
+
+# Check whether --with-gmp_include was given.
+if test "${with_gmp_include+set}" = set; then :
+ withval=$with_gmp_include; CPPFLAGS="$CPPFLAGS -I$withval"
+fi
+
+
+# Check whether --with-gmp_lib was given.
+if test "${with_gmp_lib+set}" = set; then :
+ withval=$with_gmp_lib; LDFLAGS="$LDFLAGS -L$withval"
+fi
+
+
+# Check whether --with-gmp was given.
+if test "${with_gmp+set}" = set; then :
+ withval=$with_gmp;
+ if test -z "$with_gmp_lib" && test -z "$with_gmp_include" ; then
+ CPPFLAGS="$CPPFLAGS -I$withval/include"
+ LDFLAGS="$LDFLAGS -L$withval/lib"
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "Do not use --with-gmp and --with-gmp-include/--with-gmp-lib options simultaneously.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+
+fi
+
+
# Verify that we have a usable GMP library.
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 32f25d9..a6a7cd3 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -683,6 +683,22 @@ else
fi
fi
+AC_ARG_WITH(gmp_include,
+ [ --with-gmp-include=DIR GMP include directory ],
+ CPPFLAGS="$CPPFLAGS -I$withval")
+AC_ARG_WITH(gmp_lib,
+ [ --with-gmp-lib=DIR GMP lib directory ],
+ LDFLAGS="$LDFLAGS -L$withval")
+AC_ARG_WITH(gmp,
+ [ --with-gmp=DIR GMP install directory ], [
+ if test -z "$with_gmp_lib" && test -z "$with_gmp_include" ; then
+ CPPFLAGS="$CPPFLAGS -I$withval/include"
+ LDFLAGS="$LDFLAGS -L$withval/lib"
+ else
+ AC_MSG_FAILURE([Do not use --with-gmp and --with-gmp-include/--with-gmp-lib options simultaneously.])
+ fi
+ ])
+
# Verify that we have a usable GMP library.
AC_LIB_HAVE_LINKFLAGS([gmp], [], [#include <gmp.h>],
[mpz_t n;
--
1.9.1
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [pushed/v2 1/9] gdb/configure: Add --with-libgmp-prefix option
2020-11-15 15:52 ` Bernd Edlinger
@ 2020-11-16 3:45 ` Joel Brobecker
2020-11-16 14:20 ` Bernd Edlinger
0 siblings, 1 reply; 140+ messages in thread
From: Joel Brobecker @ 2020-11-16 3:45 UTC (permalink / raw)
To: Bernd Edlinger; +Cc: gdb-patches, Simon Marchi
Hi Bernd,
> I noticed that this does not allow to build gmp in-tree like it is
> possible for gcc. I tried to overcome this by the attached patch.
Indeed. It's not something I had considered.
> While doing so, I also noticed an incompatibility with the top level
> configure stript, which advertises, and passes -with-gmp-include
> and -with-gmp-lib if in-tree gmp is found.
>
> So the --with-libgmp-prefix is not that the top level configure
> script suggests:
>
> $ ./configure --help | grep gmp
> --with-gmp-dir=PATH this option has been REMOVED
> --with-gmp=PATH specify prefix directory for the installed GMP
> --with-gmp-include=PATH/include plus
> --with-gmp-lib=PATH/lib
> --with-gmp-include=PATH specify directory for installed GMP include files
> --with-gmp-lib=PATH specify directory for the installed GMP library
>
> What do you think, can we allow these traditional configure options
> additional to the new --with-libgmp-prefix?
Can you check if these options are actually used elsewhere in
the binutils-gdb project? The idea I have in the back of my mind
is to see whether we can use the same options as the ones we've been
using in GDB or not. The fact that we have an AC_LIB_HAVE_LINKFLAGS
macro which takes care of handling dependencies for us tells me
that we are transitioning away from the model above where we add
the options "by hand" in configure.ac, and instead rely on the new
macro.
One thing I did note is that GDB has some options for MPFR support
and in particular, it has --with-mpfr:
--with-mpfr include MPFR support (auto/yes/no)
As you can see, the --with-gmp option you propose is not consistent
with the above.
Unfortunately, in digging further, I found that toplevel configure
*also* has --with-mpfr, with a different meaning:
--with-mpfr=PATH specify prefix directory for installed MPFR package.
Equivalent to --with-mpfr-include=PATH/include plus
--with-mpfr-lib=PATH/lib
The way we expect people to configure GDB is to configure it as
part of the binutils-gdb project, so I don't see how GDB's --with-mpfr
could work, unless the top-level configury is more elaborate than
I remembered.
Depending on the above, perhaps it might be better to actually
to change the top-level configury to advertise the --with-gmp-prefix
options instead of adding parallel support for the old-style
options in GDB's configury. And while at it, perhaps start deprecating
the old-style ones in the top-level configury.
One more note: For me, I think we can handle the question of
in-tree building independently of the question of the configury's
options -- which is good, because I think the latterm might require
a bit of discussion.
> Can we the top level Makefile.def change in binutils-gdb or has this
> be checked-in first in gcc?
That's a good question. I *think* that binutils + GDB now have
ownership, but I might be wrong. Hopefully others know better.
If not, I will ask.
> 2020-11-15 Bernd Edlinger <bernd.edlinger@hotmail.de>
>
> * Makefile.def: Prepare for GDB build with intree GMP.
> * Makefile.in: Regenerate.
>
> gdb:
> 2020-11-15 Bernd Edlinger <bernd.edlinger@hotmail.de>
>
> * configure.ac: Add --with-gmp= --with-gmp-include= and --with-gmp-lib=
> for compatibility with top level configure script.
> * configure: Regenerate.
Looking at your patch, I'm wondering how this would all fit together...
Would it all work automatically (like it does for libiconv, I believe),
or where you planning on having to pass --with-gmp options ?
--
Joel
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [pushed/v2 1/9] gdb/configure: Add --with-libgmp-prefix option
2020-11-16 3:45 ` Joel Brobecker
@ 2020-11-16 14:20 ` Bernd Edlinger
2020-11-17 7:41 ` [PATCH] Enable GDB build with in-tree GMP and MPFR Bernd Edlinger
0 siblings, 1 reply; 140+ messages in thread
From: Bernd Edlinger @ 2020-11-16 14:20 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches, Simon Marchi
On 11/16/20 4:45 AM, Joel Brobecker wrote:
> Hi Bernd,
>
>> I noticed that this does not allow to build gmp in-tree like it is
>> possible for gcc. I tried to overcome this by the attached patch.
>
> Indeed. It's not something I had considered.
>
>> While doing so, I also noticed an incompatibility with the top level
>> configure stript, which advertises, and passes -with-gmp-include
>> and -with-gmp-lib if in-tree gmp is found.
>>
>> So the --with-libgmp-prefix is not that the top level configure
>> script suggests:
>>
>> $ ./configure --help | grep gmp
>> --with-gmp-dir=PATH this option has been REMOVED
>> --with-gmp=PATH specify prefix directory for the installed GMP
>> --with-gmp-include=PATH/include plus
>> --with-gmp-lib=PATH/lib
>> --with-gmp-include=PATH specify directory for installed GMP include files
>> --with-gmp-lib=PATH specify directory for the installed GMP library
>>
>> What do you think, can we allow these traditional configure options
>> additional to the new --with-libgmp-prefix?
>
> Can you check if these options are actually used elsewhere in
> the binutils-gdb project? The idea I have in the back of my mind
> is to see whether we can use the same options as the ones we've been
> using in GDB or not. The fact that we have an AC_LIB_HAVE_LINKFLAGS
> macro which takes care of handling dependencies for us tells me
> that we are transitioning away from the model above where we add
> the options "by hand" in configure.ac, and instead rely on the new
> macro.
>
I think they are also used as configuration options in mpfr
and mpc, and understood by the top level configuration.
$ mpc-1.0.3/configure --help
[...]
--with-mpfr-include=DIR MPFR include directory
--with-mpfr-lib=DIR MPFR lib directory
--with-mpfr=DIR MPFR install directory
--with-gmp-include=DIR GMP include directory
--with-gmp-lib=DIR GMP lib directory
--with-gmp=DIR GMP install directory
[...]
$
[...]
--with-gmp-include=DIR GMP include directory
--with-gmp-lib=DIR GMP lib directory
--with-gmp=DIR GMP install directory
--with-gmp-build=DIR GMP build directory (please read INSTALL file)
[...]
> One thing I did note is that GDB has some options for MPFR support
> and in particular, it has --with-mpfr:
>
> --with-mpfr include MPFR support (auto/yes/no)
>
> As you can see, the --with-gmp option you propose is not consistent
> with the above.
>
Hmm, yes, indeed, the --with-mpfr seems to be hand-crafted, since there is
currently no --with-gmp=[auto/yes/no], (neither before or after my patch).
I think the --with-mpfr might probably cause problems with mpc in-tree build,
if that ever happens.
Of course the this mpfr support does not work with in-tree mpfr either.
For that to work we would need at minimum --with-mpfr-include=DIR and
--with-mpfr-lib=DIR or equivalent, however mpfr is probably not worth the effort.
> Unfortunately, in digging further, I found that toplevel configure
> *also* has --with-mpfr, with a different meaning:
>
> --with-mpfr=PATH specify prefix directory for installed MPFR package.
> Equivalent to --with-mpfr-include=PATH/include plus
> --with-mpfr-lib=PATH/lib
>
> The way we expect people to configure GDB is to configure it as
> part of the binutils-gdb project, so I don't see how GDB's --with-mpfr
> could work, unless the top-level configury is more elaborate than
> I remembered.
>
> Depending on the above, perhaps it might be better to actually
> to change the top-level configury to advertise the --with-gmp-prefix
> options instead of adding parallel support for the old-style
> options in GDB's configury. And while at it, perhaps start deprecating
> the old-style ones in the top-level configury.
>
Of course there is still mpfr's --with-gmp=DIR configuration option.
But there may also be other surprises like this in configure.ac :
*-*-freebsd*)
if test "x$with_gmp" = x && test "x$with_gmp_dir" = x \
&& ! test -d ${srcdir}/gmp \
&& test -f /usr/local/include/gmp.h; then
with_gmp=/usr/local
fi
;;
as you see, this option was already there for a while.
> One more note: For me, I think we can handle the question of
> in-tree building independently of the question of the configury's
> options -- which is good, because I think the latterm might require
> a bit of discussion.
>
>> Can we the top level Makefile.def change in binutils-gdb or has this
>> be checked-in first in gcc?
>
> That's a good question. I *think* that binutils + GDB now have
> ownership, but I might be wrong. Hopefully others know better.
> If not, I will ask.
>
>> 2020-11-15 Bernd Edlinger <bernd.edlinger@hotmail.de>
>>
>> * Makefile.def: Prepare for GDB build with intree GMP.
>> * Makefile.in: Regenerate.
>>
>> gdb:
>> 2020-11-15 Bernd Edlinger <bernd.edlinger@hotmail.de>
>>
>> * configure.ac: Add --with-gmp= --with-gmp-include= and --with-gmp-lib=
>> for compatibility with top level configure script.
>> * configure: Regenerate.
>
> Looking at your patch, I'm wondering how this would all fit together...
> Would it all work automatically (like it does for libiconv, I believe),
> or where you planning on having to pass --with-gmp options ?
>
No, all it needs, is a symlink named "gmp" pointing to gmp's source tree, in the
top level directory, like gcc's contrib/download_prerequisites does.
Once the gmp directory is there the --with-gmp-include and --with-gmp-lib options
are passed to in-tree mpfr if any, and now additionally to gdb.
The --with-gmp=DIR option itself is not needed at all for the in-tree build.
Bernd.
^ permalink raw reply [flat|nested] 140+ messages in thread
* [PATCH] Enable GDB build with in-tree GMP and MPFR
2020-11-16 14:20 ` Bernd Edlinger
@ 2020-11-17 7:41 ` Bernd Edlinger
2020-11-18 3:44 ` Joel Brobecker
0 siblings, 1 reply; 140+ messages in thread
From: Bernd Edlinger @ 2020-11-17 7:41 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches, Simon Marchi
[-- Attachment #1: Type: text/plain, Size: 766 bytes --]
Hi,
this enables GDB build with in-tree GMP and MPFR.
This updated version of my patch added support for in-tree MPFR.
While there is no preexisting --with-gmp configure option in gdb,
this leaves the current --with-mpfr=yes/no/auto as it is, since it seems
to work by accident. The top level config script thinks "no" is
a DIR, and skips the detection of in-tree MPFR in that case, while
gdb honors --with-mpfr=no, so that is what's expected.
The in-tree build works only when no --with-mpfr and no
--with-gmp is given. While it does not advertise --with-gmp-prefix=DIR
and/or --with-mpfr-prefix=DIR with "./configure --help", I'll leave that
for another patch.
Tested on x86_64-pc-linux-gnu and cross-build for arm.
Is it OK for the trunk?
Thanks
Bernd.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Enable-GDB-build-with-in-tree-GMP-and-MPFR.patch --]
[-- Type: text/x-patch; name="0001-Enable-GDB-build-with-in-tree-GMP-and-MPFR.patch", Size: 7186 bytes --]
From 503435680f463cf5ed060ce32b902051cb19e801 Mon Sep 17 00:00:00 2001
From: Bernd Edlinger <bernd.edlinger@hotmail.de>
Date: Sun, 15 Nov 2020 15:37:22 +0100
Subject: [PATCH] Enable GDB build with in-tree GMP and MPFR
With this patch GDB can be built with in-tree GMP and/or
MPFR. This works also for cross-builds.
All that is needed, is a sym-link in the source tree,
like this:
gmp -> ../gmp-6.1.0
mpfr -> ../mpfr-3.1.4
2020-11-15 Bernd Edlinger <bernd.edlinger@hotmail.de>
* Makefile.def: Prepare for GDB build with intree GMP.
* Makefile.in: Regenerate.
gdb:
2020-11-15 Bernd Edlinger <bernd.edlinger@hotmail.de>
* configure.ac: Add --with-gmp=DIR, --with-gmp-include=DIR
and --with-gmp-lib=DIR
as well as --with-mpfr-include=DIR and --with-mpfr-lib=DIR
for compatibility with top level configure script.
* configure: Regenerate.
---
Makefile.def | 5 ++++-
Makefile.in | 4 +++-
gdb/configure | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
gdb/configure.ac | 25 +++++++++++++++++++++++++
4 files changed, 84 insertions(+), 2 deletions(-)
diff --git a/Makefile.def b/Makefile.def
index 089e70a..1b99b42 100644
--- a/Makefile.def
+++ b/Makefile.def
@@ -115,7 +115,8 @@ host_modules= { module= zlib; no_install=true; no_check=true;
host_modules= { module= gnulib; };
host_modules= { module= gdbsupport; };
host_modules= { module= gdbserver; };
-host_modules= { module= gdb; };
+host_modules= { module= gdb;
+ extra_configure_flags='@extra_mpfr_configure_flags@ @extra_mpc_mpfr_configure_flags@';};
host_modules= { module= expect; };
host_modules= { module= guile; };
host_modules= { module= tk; };
@@ -391,6 +392,8 @@ dependencies = { module=all-intl; on=all-libiconv; };
// Host modules specific to gdb.
dependencies = { module=configure-gdb; on=all-intl; };
+dependencies = { module=configure-gdb; on=all-gmp; };
+dependencies = { module=configure-gdb; on=all-mpfr; };
dependencies = { module=configure-gdb; on=configure-sim; };
dependencies = { module=configure-gdb; on=all-bfd; };
dependencies = { module=configure-gdb; on=all-gnulib; };
diff --git a/Makefile.in b/Makefile.in
index fe34132..738fd32 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -29491,7 +29491,7 @@ configure-gdb:
$$s/$$module_srcdir/configure \
--srcdir=$${topdir}/$$module_srcdir \
$(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \
- --target=${target_alias} \
+ --target=${target_alias} @extra_mpfr_configure_flags@ @extra_mpc_mpfr_configure_flags@ \
|| exit 1
@endif gdb
@@ -52449,6 +52449,8 @@ configure-libcc1: maybe-configure-gcc
all-libcc1: maybe-all-gcc
all-utils: maybe-all-libiberty
configure-gdb: maybe-all-intl
+configure-gdb: maybe-all-gmp
+configure-gdb: maybe-all-mpfr
configure-gdb: maybe-all-bfd
configure-gdb: maybe-all-libiconv
all-gdb: maybe-all-libiberty
diff --git a/gdb/configure b/gdb/configure
index a3e73b4..034485d 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -899,8 +899,13 @@ with_jit_reader_dir
with_expat
with_libexpat_prefix
with_libexpat_type
+with_gmp_include
+with_gmp_lib
+with_gmp
with_libgmp_prefix
with_libgmp_type
+with_mpfr_include
+with_mpfr_lib
with_mpfr
with_libmpfr_prefix
with_libmpfr_type
@@ -1644,9 +1649,14 @@ Optional Packages:
--with-libexpat-prefix[=DIR] search for libexpat in DIR/include and DIR/lib
--without-libexpat-prefix don't search for libexpat in includedir and libdir
--with-libexpat-type=TYPE type of library to search for (auto/static/shared)
+ --with-gmp-include=DIR GMP include directory
+ --with-gmp-lib=DIR GMP lib directory
+ --with-gmp=DIR GMP install directory
--with-libgmp-prefix[=DIR] search for libgmp in DIR/include and DIR/lib
--without-libgmp-prefix don't search for libgmp in includedir and libdir
--with-libgmp-type=TYPE type of library to search for (auto/static/shared)
+ --with-mpfr-include=DIR MPFR include directory
+ --with-mpfr-lib=DIR MPFR lib directory
--with-mpfr include MPFR support (auto/yes/no)
--with-libmpfr-prefix[=DIR] search for libmpfr in DIR/include and DIR/lib
--without-libmpfr-prefix don't search for libmpfr in includedir and libdir
@@ -9990,6 +10000,35 @@ done
fi
fi
+
+# Check whether --with-gmp_include was given.
+if test "${with_gmp_include+set}" = set; then :
+ withval=$with_gmp_include; CPPFLAGS="$CPPFLAGS -I$withval"
+fi
+
+
+# Check whether --with-gmp_lib was given.
+if test "${with_gmp_lib+set}" = set; then :
+ withval=$with_gmp_lib; LDFLAGS="$LDFLAGS -L$withval"
+fi
+
+
+# Check whether --with-gmp was given.
+if test "${with_gmp+set}" = set; then :
+ withval=$with_gmp;
+ if test -z "$with_gmp_lib" && test -z "$with_gmp_include" ; then
+ CPPFLAGS="$CPPFLAGS -I$withval/include"
+ LDFLAGS="$LDFLAGS -L$withval/lib"
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "Do not use --with-gmp and --with-gmp-include/--with-gmp-lib options simultaneously.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+
+fi
+
+
# Verify that we have a usable GMP library.
@@ -10474,6 +10513,19 @@ if test "$HAVE_LIBGMP" != yes; then
fi
+# Check whether --with-mpfr_include was given.
+if test "${with_mpfr_include+set}" = set; then :
+ withval=$with_mpfr_include; CPPFLAGS="-I$withval $CPPFLAGS"
+fi
+
+
+# Check whether --with-mpfr_lib was given.
+if test "${with_mpfr_lib+set}" = set; then :
+ withval=$with_mpfr_lib; LDFLAGS="-L$withval $LDFLAGS"
+fi
+
+
+
# Check whether --with-mpfr was given.
if test "${with_mpfr+set}" = set; then :
withval=$with_mpfr;
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 32f25d9..97f43ce 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -683,6 +683,22 @@ else
fi
fi
+AC_ARG_WITH(gmp_include,
+ [ --with-gmp-include=DIR GMP include directory ],
+ CPPFLAGS="$CPPFLAGS -I$withval")
+AC_ARG_WITH(gmp_lib,
+ [ --with-gmp-lib=DIR GMP lib directory ],
+ LDFLAGS="$LDFLAGS -L$withval")
+AC_ARG_WITH(gmp,
+ [ --with-gmp=DIR GMP install directory ], [
+ if test -z "$with_gmp_lib" && test -z "$with_gmp_include" ; then
+ CPPFLAGS="$CPPFLAGS -I$withval/include"
+ LDFLAGS="$LDFLAGS -L$withval/lib"
+ else
+ AC_MSG_FAILURE([Do not use --with-gmp and --with-gmp-include/--with-gmp-lib options simultaneously.])
+ fi
+ ])
+
# Verify that we have a usable GMP library.
AC_LIB_HAVE_LINKFLAGS([gmp], [], [#include <gmp.h>],
[mpz_t n;
@@ -691,6 +707,15 @@ if test "$HAVE_LIBGMP" != yes; then
AC_MSG_ERROR([GMP is missing or unusable])
fi
+AC_ARG_WITH([mpfr_include],
+ [AC_HELP_STRING([--with-mpfr-include=DIR],
+ [MPFR include directory])],
+ [CPPFLAGS="-I$withval $CPPFLAGS"])
+AC_ARG_WITH([mpfr_lib],
+ [AC_HELP_STRING([--with-mpfr-lib=DIR],
+ [MPFR lib directory])],
+ [LDFLAGS="-L$withval $LDFLAGS"])
+
AC_ARG_WITH(mpfr,
AS_HELP_STRING([--with-mpfr], [include MPFR support (auto/yes/no)]),
[], [with_mpfr=auto])
--
1.9.1
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [PATCH] Enable GDB build with in-tree GMP and MPFR
2020-11-17 7:41 ` [PATCH] Enable GDB build with in-tree GMP and MPFR Bernd Edlinger
@ 2020-11-18 3:44 ` Joel Brobecker
2020-11-18 8:14 ` Bernd Edlinger
0 siblings, 1 reply; 140+ messages in thread
From: Joel Brobecker @ 2020-11-18 3:44 UTC (permalink / raw)
To: Bernd Edlinger; +Cc: Simon Marchi, gdb-patches
> this enables GDB build with in-tree GMP and MPFR.
>
> This updated version of my patch added support for in-tree MPFR.
>
> While there is no preexisting --with-gmp configure option in gdb,
> this leaves the current --with-mpfr=yes/no/auto as it is, since it seems
> to work by accident. The top level config script thinks "no" is
> a DIR, and skips the detection of in-tree MPFR in that case, while
> gdb honors --with-mpfr=no, so that is what's expected.
>
> The in-tree build works only when no --with-mpfr and no
> --with-gmp is given. While it does not advertise --with-gmp-prefix=DIR
> and/or --with-mpfr-prefix=DIR with "./configure --help", I'll leave that
> for another patch.
I think we better sort the discrepancy between GCC and GDB
if we can, but this is going to take time. From what you were
explaining before, I believe you can separate this part of
your patch (adding the above to GDB's configury) from the part
where you're adding support for in-tree building?
> Tested on x86_64-pc-linux-gnu and cross-build for arm.
> Is it OK for the trunk?
These are changes in areas I am not familiar with, and wouldn't
have very much time to look into. I talked to Tom yesterday,
and he kindly agreed to take a look.
> From 503435680f463cf5ed060ce32b902051cb19e801 Mon Sep 17 00:00:00 2001
> From: Bernd Edlinger <bernd.edlinger@hotmail.de>
> Date: Sun, 15 Nov 2020 15:37:22 +0100
> Subject: [PATCH] Enable GDB build with in-tree GMP and MPFR
>
> With this patch GDB can be built with in-tree GMP and/or
> MPFR. This works also for cross-builds.
>
> All that is needed, is a sym-link in the source tree,
> like this:
>
> gmp -> ../gmp-6.1.0
> mpfr -> ../mpfr-3.1.4
>
> 2020-11-15 Bernd Edlinger <bernd.edlinger@hotmail.de>
>
> * Makefile.def: Prepare for GDB build with intree GMP.
> * Makefile.in: Regenerate.
I got the answer about approval for toplevel tree changes; we're still
keeping in sync with GCC. However, Tom said that these kinds of changes
are OK to discuss and eventually push locally, before we bring them
to GCC next. It's better the other way around, but discussing them
here is also an option, because it's a minor change taking advantage
of infrastructure that's already in place.
In this particular instance, I would indeed _not_ rush discussing
with GCC, in case the tie with GDB affects the changes we would need
in toplevel.
> gdb:
> 2020-11-15 Bernd Edlinger <bernd.edlinger@hotmail.de>
>
> * configure.ac: Add --with-gmp=DIR, --with-gmp-include=DIR
> and --with-gmp-lib=DIR
> as well as --with-mpfr-include=DIR and --with-mpfr-lib=DIR
> for compatibility with top level configure script.
> * configure: Regenerate.
> ---
> Makefile.def | 5 ++++-
> Makefile.in | 4 +++-
> gdb/configure | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> gdb/configure.ac | 25 +++++++++++++++++++++++++
> 4 files changed, 84 insertions(+), 2 deletions(-)
>
> diff --git a/Makefile.def b/Makefile.def
> index 089e70a..1b99b42 100644
> --- a/Makefile.def
> +++ b/Makefile.def
> @@ -115,7 +115,8 @@ host_modules= { module= zlib; no_install=true; no_check=true;
> host_modules= { module= gnulib; };
> host_modules= { module= gdbsupport; };
> host_modules= { module= gdbserver; };
> -host_modules= { module= gdb; };
> +host_modules= { module= gdb;
> + extra_configure_flags='@extra_mpfr_configure_flags@ @extra_mpc_mpfr_configure_flags@';};
> host_modules= { module= expect; };
> host_modules= { module= guile; };
> host_modules= { module= tk; };
> @@ -391,6 +392,8 @@ dependencies = { module=all-intl; on=all-libiconv; };
>
> // Host modules specific to gdb.
> dependencies = { module=configure-gdb; on=all-intl; };
> +dependencies = { module=configure-gdb; on=all-gmp; };
> +dependencies = { module=configure-gdb; on=all-mpfr; };
> dependencies = { module=configure-gdb; on=configure-sim; };
> dependencies = { module=configure-gdb; on=all-bfd; };
> dependencies = { module=configure-gdb; on=all-gnulib; };
> diff --git a/Makefile.in b/Makefile.in
> index fe34132..738fd32 100644
> --- a/Makefile.in
> +++ b/Makefile.in
> @@ -29491,7 +29491,7 @@ configure-gdb:
> $$s/$$module_srcdir/configure \
> --srcdir=$${topdir}/$$module_srcdir \
> $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \
> - --target=${target_alias} \
> + --target=${target_alias} @extra_mpfr_configure_flags@ @extra_mpc_mpfr_configure_flags@ \
> || exit 1
> @endif gdb
>
> @@ -52449,6 +52449,8 @@ configure-libcc1: maybe-configure-gcc
> all-libcc1: maybe-all-gcc
> all-utils: maybe-all-libiberty
> configure-gdb: maybe-all-intl
> +configure-gdb: maybe-all-gmp
> +configure-gdb: maybe-all-mpfr
> configure-gdb: maybe-all-bfd
> configure-gdb: maybe-all-libiconv
> all-gdb: maybe-all-libiberty
> diff --git a/gdb/configure b/gdb/configure
> index a3e73b4..034485d 100755
> --- a/gdb/configure
> +++ b/gdb/configure
> @@ -899,8 +899,13 @@ with_jit_reader_dir
> with_expat
> with_libexpat_prefix
> with_libexpat_type
> +with_gmp_include
> +with_gmp_lib
> +with_gmp
> with_libgmp_prefix
> with_libgmp_type
> +with_mpfr_include
> +with_mpfr_lib
> with_mpfr
> with_libmpfr_prefix
> with_libmpfr_type
> @@ -1644,9 +1649,14 @@ Optional Packages:
> --with-libexpat-prefix[=DIR] search for libexpat in DIR/include and DIR/lib
> --without-libexpat-prefix don't search for libexpat in includedir and libdir
> --with-libexpat-type=TYPE type of library to search for (auto/static/shared)
> + --with-gmp-include=DIR GMP include directory
> + --with-gmp-lib=DIR GMP lib directory
> + --with-gmp=DIR GMP install directory
> --with-libgmp-prefix[=DIR] search for libgmp in DIR/include and DIR/lib
> --without-libgmp-prefix don't search for libgmp in includedir and libdir
> --with-libgmp-type=TYPE type of library to search for (auto/static/shared)
> + --with-mpfr-include=DIR MPFR include directory
> + --with-mpfr-lib=DIR MPFR lib directory
> --with-mpfr include MPFR support (auto/yes/no)
> --with-libmpfr-prefix[=DIR] search for libmpfr in DIR/include and DIR/lib
> --without-libmpfr-prefix don't search for libmpfr in includedir and libdir
> @@ -9990,6 +10000,35 @@ done
> fi
> fi
>
> +
> +# Check whether --with-gmp_include was given.
> +if test "${with_gmp_include+set}" = set; then :
> + withval=$with_gmp_include; CPPFLAGS="$CPPFLAGS -I$withval"
> +fi
> +
> +
> +# Check whether --with-gmp_lib was given.
> +if test "${with_gmp_lib+set}" = set; then :
> + withval=$with_gmp_lib; LDFLAGS="$LDFLAGS -L$withval"
> +fi
> +
> +
> +# Check whether --with-gmp was given.
> +if test "${with_gmp+set}" = set; then :
> + withval=$with_gmp;
> + if test -z "$with_gmp_lib" && test -z "$with_gmp_include" ; then
> + CPPFLAGS="$CPPFLAGS -I$withval/include"
> + LDFLAGS="$LDFLAGS -L$withval/lib"
> + else
> + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
> +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
> +as_fn_error $? "Do not use --with-gmp and --with-gmp-include/--with-gmp-lib options simultaneously.
> +See \`config.log' for more details" "$LINENO" 5; }
> + fi
> +
> +fi
> +
> +
> # Verify that we have a usable GMP library.
>
>
> @@ -10474,6 +10513,19 @@ if test "$HAVE_LIBGMP" != yes; then
> fi
>
>
> +# Check whether --with-mpfr_include was given.
> +if test "${with_mpfr_include+set}" = set; then :
> + withval=$with_mpfr_include; CPPFLAGS="-I$withval $CPPFLAGS"
> +fi
> +
> +
> +# Check whether --with-mpfr_lib was given.
> +if test "${with_mpfr_lib+set}" = set; then :
> + withval=$with_mpfr_lib; LDFLAGS="-L$withval $LDFLAGS"
> +fi
> +
> +
> +
> # Check whether --with-mpfr was given.
> if test "${with_mpfr+set}" = set; then :
> withval=$with_mpfr;
> diff --git a/gdb/configure.ac b/gdb/configure.ac
> index 32f25d9..97f43ce 100644
> --- a/gdb/configure.ac
> +++ b/gdb/configure.ac
> @@ -683,6 +683,22 @@ else
> fi
> fi
>
> +AC_ARG_WITH(gmp_include,
> + [ --with-gmp-include=DIR GMP include directory ],
> + CPPFLAGS="$CPPFLAGS -I$withval")
> +AC_ARG_WITH(gmp_lib,
> + [ --with-gmp-lib=DIR GMP lib directory ],
> + LDFLAGS="$LDFLAGS -L$withval")
> +AC_ARG_WITH(gmp,
> + [ --with-gmp=DIR GMP install directory ], [
> + if test -z "$with_gmp_lib" && test -z "$with_gmp_include" ; then
> + CPPFLAGS="$CPPFLAGS -I$withval/include"
> + LDFLAGS="$LDFLAGS -L$withval/lib"
> + else
> + AC_MSG_FAILURE([Do not use --with-gmp and --with-gmp-include/--with-gmp-lib options simultaneously.])
> + fi
> + ])
> +
> # Verify that we have a usable GMP library.
> AC_LIB_HAVE_LINKFLAGS([gmp], [], [#include <gmp.h>],
> [mpz_t n;
> @@ -691,6 +707,15 @@ if test "$HAVE_LIBGMP" != yes; then
> AC_MSG_ERROR([GMP is missing or unusable])
> fi
>
> +AC_ARG_WITH([mpfr_include],
> + [AC_HELP_STRING([--with-mpfr-include=DIR],
> + [MPFR include directory])],
> + [CPPFLAGS="-I$withval $CPPFLAGS"])
> +AC_ARG_WITH([mpfr_lib],
> + [AC_HELP_STRING([--with-mpfr-lib=DIR],
> + [MPFR lib directory])],
> + [LDFLAGS="-L$withval $LDFLAGS"])
> +
> AC_ARG_WITH(mpfr,
> AS_HELP_STRING([--with-mpfr], [include MPFR support (auto/yes/no)]),
> [], [with_mpfr=auto])
> --
> 1.9.1
>
--
Joel
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [PATCH] Enable GDB build with in-tree GMP and MPFR
2020-11-18 3:44 ` Joel Brobecker
@ 2020-11-18 8:14 ` Bernd Edlinger
2020-12-01 19:29 ` Bernd Edlinger
0 siblings, 1 reply; 140+ messages in thread
From: Bernd Edlinger @ 2020-11-18 8:14 UTC (permalink / raw)
To: Joel Brobecker; +Cc: Simon Marchi, gdb-patches
On 11/18/20 4:44 AM, Joel Brobecker wrote:
>> this enables GDB build with in-tree GMP and MPFR.
>>
>> This updated version of my patch added support for in-tree MPFR.
>>
>> While there is no preexisting --with-gmp configure option in gdb,
>> this leaves the current --with-mpfr=yes/no/auto as it is, since it seems
>> to work by accident. The top level config script thinks "no" is
>> a DIR, and skips the detection of in-tree MPFR in that case, while
>> gdb honors --with-mpfr=no, so that is what's expected.
>>
>> The in-tree build works only when no --with-mpfr and no
>> --with-gmp is given. While it does not advertise --with-gmp-prefix=DIR
>> and/or --with-mpfr-prefix=DIR with "./configure --help", I'll leave that
>> for another patch.
>
> I think we better sort the discrepancy between GCC and GDB
> if we can, but this is going to take time. From what you were
> explaining before, I believe you can separate this part of
> your patch (adding the above to GDB's configury) from the part
> where you're adding support for in-tree building?
>
99% of the top-level configury is already there, but it needs
still a dependency between gdb and (in-tree) gmp / mpfr,
and pass the options where to find gmp and mpfr to gdb,
I don't know how to actually resolve the differences ATM.
If the top-level configure script advertises GDB-style options
It will at least have to translate them for in-tree MPFR,
MPC, and ISL.
I believe this change is just the bare minimum and will not
cause additional incompatibilities with GCC.
>> Tested on x86_64-pc-linux-gnu and cross-build for arm.
>> Is it OK for the trunk?
>
> These are changes in areas I am not familiar with, and wouldn't
> have very much time to look into. I talked to Tom yesterday,
> and he kindly agreed to take a look.
>
>> From 503435680f463cf5ed060ce32b902051cb19e801 Mon Sep 17 00:00:00 2001
>> From: Bernd Edlinger <bernd.edlinger@hotmail.de>
>> Date: Sun, 15 Nov 2020 15:37:22 +0100
>> Subject: [PATCH] Enable GDB build with in-tree GMP and MPFR
>>
>> With this patch GDB can be built with in-tree GMP and/or
>> MPFR. This works also for cross-builds.
>>
>> All that is needed, is a sym-link in the source tree,
>> like this:
>>
>> gmp -> ../gmp-6.1.0
>> mpfr -> ../mpfr-3.1.4
>>
>> 2020-11-15 Bernd Edlinger <bernd.edlinger@hotmail.de>
>>
>> * Makefile.def: Prepare for GDB build with intree GMP.
>> * Makefile.in: Regenerate.
>
> I got the answer about approval for toplevel tree changes; we're still
> keeping in sync with GCC. However, Tom said that these kinds of changes
> are OK to discuss and eventually push locally, before we bring them
> to GCC next. It's better the other way around, but discussing them
> here is also an option, because it's a minor change taking advantage
> of infrastructure that's already in place.
>
> In this particular instance, I would indeed _not_ rush discussing
> with GCC, in case the tie with GDB affects the changes we would need
> in toplevel.
>
Yep, agreed.
Thanks
Bernd.
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [PATCH] Enable GDB build with in-tree GMP and MPFR
2020-11-18 8:14 ` Bernd Edlinger
@ 2020-12-01 19:29 ` Bernd Edlinger
2020-12-01 19:32 ` Simon Marchi
0 siblings, 1 reply; 140+ messages in thread
From: Bernd Edlinger @ 2020-12-01 19:29 UTC (permalink / raw)
To: Joel Brobecker; +Cc: Simon Marchi, gdb-patches
On 11/18/20 9:14 AM, Bernd Edlinger wrote:
> On 11/18/20 4:44 AM, Joel Brobecker wrote:
>>> this enables GDB build with in-tree GMP and MPFR.
>>>
>>> This updated version of my patch added support for in-tree MPFR.
>>>
>>> While there is no preexisting --with-gmp configure option in gdb,
>>> this leaves the current --with-mpfr=yes/no/auto as it is, since it seems
>>> to work by accident. The top level config script thinks "no" is
>>> a DIR, and skips the detection of in-tree MPFR in that case, while
>>> gdb honors --with-mpfr=no, so that is what's expected.
>>>
>>> The in-tree build works only when no --with-mpfr and no
>>> --with-gmp is given. While it does not advertise --with-gmp-prefix=DIR
>>> and/or --with-mpfr-prefix=DIR with "./configure --help", I'll leave that
>>> for another patch.
>>
>> I think we better sort the discrepancy between GCC and GDB
>> if we can, but this is going to take time. From what you were
>> explaining before, I believe you can separate this part of
>> your patch (adding the above to GDB's configury) from the part
>> where you're adding support for in-tree building?
>>
>
>
> 99% of the top-level configury is already there, but it needs
> still a dependency between gdb and (in-tree) gmp / mpfr,
> and pass the options where to find gmp and mpfr to gdb,
> I don't know how to actually resolve the differences ATM.
> If the top-level configure script advertises GDB-style options
> It will at least have to translate them for in-tree MPFR,
> MPC, and ISL.
>
> I believe this change is just the bare minimum and will not
> cause additional incompatibilities with GCC.
>
>
>>> Tested on x86_64-pc-linux-gnu and cross-build for arm.
>>> Is it OK for the trunk?
>>
>> These are changes in areas I am not familiar with, and wouldn't
>> have very much time to look into. I talked to Tom yesterday,
>> and he kindly agreed to take a look.
>>
>>> From 503435680f463cf5ed060ce32b902051cb19e801 Mon Sep 17 00:00:00 2001
>>> From: Bernd Edlinger <bernd.edlinger@hotmail.de>
>>> Date: Sun, 15 Nov 2020 15:37:22 +0100
>>> Subject: [PATCH] Enable GDB build with in-tree GMP and MPFR
>>>
>>> With this patch GDB can be built with in-tree GMP and/or
>>> MPFR. This works also for cross-builds.
>>>
>>> All that is needed, is a sym-link in the source tree,
>>> like this:
>>>
>>> gmp -> ../gmp-6.1.0
>>> mpfr -> ../mpfr-3.1.4
>>>
>>> 2020-11-15 Bernd Edlinger <bernd.edlinger@hotmail.de>
>>>
>>> * Makefile.def: Prepare for GDB build with intree GMP.
>>> * Makefile.in: Regenerate.
>>
>> I got the answer about approval for toplevel tree changes; we're still
>> keeping in sync with GCC. However, Tom said that these kinds of changes
>> are OK to discuss and eventually push locally, before we bring them
>> to GCC next. It's better the other way around, but discussing them
>> here is also an option, because it's a minor change taking advantage
>> of infrastructure that's already in place.
>>
>> In this particular instance, I would indeed _not_ rush discussing
>> with GCC, in case the tie with GDB affects the changes we would need
>> in toplevel.
>>
>
> Yep, agreed.
>
So, can this patch be applied ?
I would really like to be able to build gdb with in-tree gmp / mpfr,
just as it works for gcc.
Thanks
Bernd.
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [PATCH] Enable GDB build with in-tree GMP and MPFR
2020-12-01 19:29 ` Bernd Edlinger
@ 2020-12-01 19:32 ` Simon Marchi
2020-12-01 19:38 ` Bernd Edlinger
0 siblings, 1 reply; 140+ messages in thread
From: Simon Marchi @ 2020-12-01 19:32 UTC (permalink / raw)
To: Bernd Edlinger, Joel Brobecker; +Cc: gdb-patches
On 2020-12-01 2:29 p.m., Bernd Edlinger wrote:
> I would really like to be able to build gdb with in-tree gmp / mpfr,
> just as it works for gcc.
Pardon my ignorance, but I don't see the gmp nor the mpfr source code in
the binutils-gdb repository. Should it be checked in too?
Simon
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [PATCH] Enable GDB build with in-tree GMP and MPFR
2020-12-01 19:32 ` Simon Marchi
@ 2020-12-01 19:38 ` Bernd Edlinger
2020-12-01 20:29 ` Bernd Edlinger
0 siblings, 1 reply; 140+ messages in thread
From: Bernd Edlinger @ 2020-12-01 19:38 UTC (permalink / raw)
To: Simon Marchi, Joel Brobecker; +Cc: gdb-patches
On 12/1/20 8:32 PM, Simon Marchi wrote:
>
> On 2020-12-01 2:29 p.m., Bernd Edlinger wrote:
>> I would really like to be able to build gdb with in-tree gmp / mpfr,
>> just as it works for gcc.
>
> Pardon my ignorance, but I don't see the gmp nor the mpfr source code in
> the binutils-gdb repository. Should it be checked in too?
>
Aehm, good question.
gcc uses a script ./contrib/download_prerequisites
that *can* be used to download gmp/mpfr and some more.
Maybe I should add a stripped down version of that one?
Bernd.
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [PATCH] Enable GDB build with in-tree GMP and MPFR
2020-12-01 19:38 ` Bernd Edlinger
@ 2020-12-01 20:29 ` Bernd Edlinger
2020-12-01 20:30 ` Simon Marchi
2020-12-14 17:40 ` [PATCH v2] " Bernd Edlinger
0 siblings, 2 replies; 140+ messages in thread
From: Bernd Edlinger @ 2020-12-01 20:29 UTC (permalink / raw)
To: Simon Marchi, Joel Brobecker; +Cc: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 829 bytes --]
Hi Simon,
On 12/1/20 8:38 PM, Bernd Edlinger wrote:
> On 12/1/20 8:32 PM, Simon Marchi wrote:
>>
>> On 2020-12-01 2:29 p.m., Bernd Edlinger wrote:
>>> I would really like to be able to build gdb with in-tree gmp / mpfr,
>>> just as it works for gcc.
>>
>> Pardon my ignorance, but I don't see the gmp nor the mpfr source code in
>> the binutils-gdb repository. Should it be checked in too?
>>
>
>
> Aehm, good question.
> gcc uses a script ./contrib/download_prerequisites
> that *can* be used to download gmp/mpfr and some more.
>
> Maybe I should add a stripped down version of that one?
>
So, this adds the contrib/download_prerequisites script.
It is taken from gcc but does not download mpc and isl,
just gmp and mpfr.
It should work also when building gdb from the release tar.
Is it OK to push?
Thanks
Bernd.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Enable-GDB-build-with-in-tree-GMP-and-MPFR.patch --]
[-- Type: text/x-patch; name="0001-Enable-GDB-build-with-in-tree-GMP-and-MPFR.patch", Size: 16414 bytes --]
From 41fdfbe1633009d2395b4714a6b3bfabb74691ef Mon Sep 17 00:00:00 2001
From: Bernd Edlinger <bernd.edlinger@hotmail.de>
Date: Sun, 15 Nov 2020 15:37:22 +0100
Subject: [PATCH] Enable GDB build with in-tree GMP and MPFR
With this patch GDB can be built with in-tree GMP and/or
MPFR. This works also for cross-builds.
All that is needed, is a sym-link in the source tree,
like this:
gmp -> ../gmp-6.1.0
mpfr -> ../mpfr-3.1.4
2020-11-15 Bernd Edlinger <bernd.edlinger@hotmail.de>
* Makefile.def: Prepare for GDB build with intree GMP.
* Makefile.in: Regenerate.
gdb:
2020-11-15 Bernd Edlinger <bernd.edlinger@hotmail.de>
* configure.ac: Add --with-gmp=DIR, --with-gmp-include=DIR
and --with-gmp-lib=DIR
as well as --with-mpfr-include=DIR and --with-mpfr-lib=DIR
for compatibility with top level configure script.
* configure: Regenerate.
contrib:
2020-11-15 Bernd Edlinger <bernd.edlinger@hotmail.de>
* download_prerequisites: New helper script.
* prerequisites.md5: checksums.
* prerequisites.sha512: checksums.
---
Makefile.def | 5 +-
Makefile.in | 4 +-
contrib/download_prerequisites | 263 +++++++++++++++++++++++++++++++++++++++++
contrib/prerequisites.md5 | 2 +
contrib/prerequisites.sha512 | 2 +
gdb/configure | 52 ++++++++
gdb/configure.ac | 25 ++++
7 files changed, 351 insertions(+), 2 deletions(-)
create mode 100755 contrib/download_prerequisites
create mode 100644 contrib/prerequisites.md5
create mode 100644 contrib/prerequisites.sha512
diff --git a/Makefile.def b/Makefile.def
index 089e70a..1b99b42 100644
--- a/Makefile.def
+++ b/Makefile.def
@@ -115,7 +115,8 @@ host_modules= { module= zlib; no_install=true; no_check=true;
host_modules= { module= gnulib; };
host_modules= { module= gdbsupport; };
host_modules= { module= gdbserver; };
-host_modules= { module= gdb; };
+host_modules= { module= gdb;
+ extra_configure_flags='@extra_mpfr_configure_flags@ @extra_mpc_mpfr_configure_flags@';};
host_modules= { module= expect; };
host_modules= { module= guile; };
host_modules= { module= tk; };
@@ -391,6 +392,8 @@ dependencies = { module=all-intl; on=all-libiconv; };
// Host modules specific to gdb.
dependencies = { module=configure-gdb; on=all-intl; };
+dependencies = { module=configure-gdb; on=all-gmp; };
+dependencies = { module=configure-gdb; on=all-mpfr; };
dependencies = { module=configure-gdb; on=configure-sim; };
dependencies = { module=configure-gdb; on=all-bfd; };
dependencies = { module=configure-gdb; on=all-gnulib; };
diff --git a/Makefile.in b/Makefile.in
index fe34132..738fd32 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -29491,7 +29491,7 @@ configure-gdb:
$$s/$$module_srcdir/configure \
--srcdir=$${topdir}/$$module_srcdir \
$(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \
- --target=${target_alias} \
+ --target=${target_alias} @extra_mpfr_configure_flags@ @extra_mpc_mpfr_configure_flags@ \
|| exit 1
@endif gdb
@@ -52449,6 +52449,8 @@ configure-libcc1: maybe-configure-gcc
all-libcc1: maybe-all-gcc
all-utils: maybe-all-libiberty
configure-gdb: maybe-all-intl
+configure-gdb: maybe-all-gmp
+configure-gdb: maybe-all-mpfr
configure-gdb: maybe-all-bfd
configure-gdb: maybe-all-libiconv
all-gdb: maybe-all-libiberty
diff --git a/contrib/download_prerequisites b/contrib/download_prerequisites
new file mode 100755
index 0000000..a8b78da
--- /dev/null
+++ b/contrib/download_prerequisites
@@ -0,0 +1,263 @@
+#! /bin/sh
+#! -*- coding:utf-8; mode:shell-script; -*-
+
+# Download some prerequisites needed by GDB.
+# Run this from the top level of the GDB source tree and the GDB build will do
+# the right thing. Run it with the `--help` option for more information.
+#
+# (C) 2010-2020 Free Software Foundation
+#
+# 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/.
+
+program='download_prerequisites'
+version='(unversioned)'
+
+# MAINTAINERS: If you update the package versions below, please
+# remember to also update the files `contrib/prerequisites.sha512` and
+# `contrib/prerequisites.md5` with the new checksums.
+
+gmp='gmp-6.1.0.tar.bz2'
+mpfr='mpfr-3.1.4.tar.bz2'
+
+base_url='http://gcc.gnu.org/pub/gcc/infrastructure/'
+
+echo_archives() {
+ echo "${gmp}"
+ echo "${mpfr}"
+}
+
+verify=1
+force=0
+OS=$(uname)
+
+case $OS in
+ "Darwin"|"FreeBSD"|"DragonFly"|"AIX")
+ chksum='shasum -a 512 --check'
+ ;;
+ "OpenBSD")
+ chksum='sha512 -c'
+ ;;
+ *)
+ chksum='sha512sum -c'
+ ;;
+esac
+
+if type wget > /dev/null ; then
+ fetch='wget'
+else
+ fetch='curl -LO'
+fi
+chksum_extension='sha512'
+directory='.'
+
+helptext="usage: ${program} [OPTION...]
+
+Downloads some prerequisites needed by GDB. Run this from the top level of the
+GDB source tree and the GDB build will do the right thing.
+
+The following options are available:
+
+ --directory=DIR download and unpack packages into DIR instead of '.'
+ --force download again overwriting existing packages
+ --no-force do not download existing packages again (default)
+ --verify verify package integrity after download (default)
+ --no-verify don't verify package integrity
+ --sha512 use SHA512 checksum to verify package integrity (default)
+ --md5 use MD5 checksum to verify package integrity
+ --help show this text and exit
+ --version show version information and exit
+"
+
+versiontext="${program} ${version}
+Copyright (C) 2020 Free Software Foundation, Inc.
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+die() {
+ echo "error: $@" >&2
+ exit 1
+}
+
+for arg in "$@"
+do
+ case "${arg}" in
+ --help)
+ echo "${helptext}"
+ exit
+ ;;
+ --version)
+ echo "${versiontext}"
+ exit
+ ;;
+ esac
+done
+unset arg
+
+# Emulate Linux's 'md5 --check' on macOS
+md5_check() {
+ # Store the standard input: a line from contrib/prerequisites.md5:
+ md5_checksum_line=$(cat -)
+ # Grab the text before the first space
+ md5_checksum_expected="${md5_checksum_line%% *}"
+ # Grab the text after the first space
+ file_to_check="${md5_checksum_line##* }"
+ # Calculate the md5 checksum for the downloaded file
+ md5_checksum_output=$(md5 -r "${file_to_check}")
+ # Grab the text before the first space
+ md5_checksum_detected="${md5_checksum_output%% *}"
+ [ "${md5_checksum_expected}" == "${md5_checksum_detected}" ] \
+ || die "Cannot verify integrity of possibly corrupted file ${file_to_check}"
+ echo "${file_to_check}: OK"
+}
+
+
+argnext=
+for arg in "$@"
+do
+ if [ "x${argnext}" = x ]
+ then
+ case "${arg}" in
+ --directory)
+ argnext='directory'
+ ;;
+ --directory=*)
+ directory="${arg#--directory=}"
+ ;;
+ --force)
+ force=1
+ ;;
+ --no-force)
+ force=0
+ ;;
+ --verify)
+ verify=1
+ ;;
+ --no-verify)
+ verify=0
+ ;;
+ --sha512)
+ case $OS in
+ "Darwin")
+ chksum='shasum -a 512 --check'
+ ;;
+ *)
+ chksum='sha512sum --check'
+ ;;
+ esac
+ chksum_extension='sha512'
+ verify=1
+ ;;
+ --md5)
+ case $OS in
+ "Darwin")
+ chksum='md5_check'
+ ;;
+ *)
+ chksum='md5 --check'
+ ;;
+ esac
+ chksum_extension='md5'
+ verify=1
+ ;;
+ -*)
+ die "unknown option: ${arg}"
+ ;;
+ *)
+ die "too many arguments"
+ ;;
+ esac
+ else
+ case "${arg}" in
+ -*)
+ die "Missing argument for option --${argnext}"
+ ;;
+ esac
+ case "${argnext}" in
+ directory)
+ directory="${arg}"
+ ;;
+ *)
+ die "The impossible has happened"
+ ;;
+ esac
+ argnext=
+ fi
+done
+[ "x${argnext}" = x ] || die "Missing argument for option --${argnext}"
+unset arg argnext
+
+[ -e ./gdb/version.in ] \
+ || die "You must run this script in the top-level GDB source directory"
+
+[ -d "${directory}" ] \
+ || die "No such directory: ${directory}"
+
+for ar in $(echo_archives)
+do
+ if [ ${force} -gt 0 ]; then rm -f "${directory}/${ar}"; fi
+ [ -e "${directory}/${ar}" ] \
+ || ( cd "${directory}" && ${fetch} --no-verbose "${base_url}${ar}" ) \
+ || die "Cannot download ${ar} from ${base_url}"
+done
+unset ar
+
+if [ ${verify} -gt 0 ]
+then
+ chksumfile="contrib/prerequisites.${chksum_extension}"
+ [ -r "${chksumfile}" ] || die "No checksums available"
+ for ar in $(echo_archives)
+ do
+ grep "${ar}" "${chksumfile}" \
+ | ( cd "${directory}" && ${chksum} ) \
+ || die "Cannot verify integrity of possibly corrupted file ${ar}"
+ done
+ unset chksumfile
+fi
+unset ar
+
+for ar in $(echo_archives)
+do
+ package="${ar%.tar*}"
+ if [ ${force} -gt 0 ]; then rm -rf "${directory}/${package}"; fi
+ case $ar in
+ *.gz)
+ uncompress='gzip -d'
+ ;;
+ *.bz2)
+ uncompress='bzip2 -d'
+ ;;
+ *)
+ uncompress='cat'
+ ;;
+ esac
+ [ -e "${directory}/${package}" ] \
+ || ( cd "${directory}" && $uncompress <"${ar}" | tar -xf - ) \
+ || die "Cannot extract package from ${ar}"
+ unset package
+done
+unset ar
+
+for ar in $(echo_archives)
+do
+ target="${directory}/${ar%.tar*}/"
+ linkname="${ar%-*}"
+ if [ ${force} -gt 0 ]; then rm -f "${linkname}"; fi
+ [ -e "${linkname}" ] \
+ || ln -s "${target}" "${linkname}" \
+ || die "Cannot create symbolic link ${linkname} --> ${target}"
+ unset target linkname
+done
+unset ar
+
+echo "All prerequisites downloaded successfully."
diff --git a/contrib/prerequisites.md5 b/contrib/prerequisites.md5
new file mode 100644
index 0000000..cf7be0d
--- /dev/null
+++ b/contrib/prerequisites.md5
@@ -0,0 +1,2 @@
+86ee6e54ebfc4a90b643a65e402c4048 gmp-6.1.0.tar.bz2
+b8a2f6b0e68bef46e53da2ac439e1cf4 mpfr-3.1.4.tar.bz2
diff --git a/contrib/prerequisites.sha512 b/contrib/prerequisites.sha512
new file mode 100644
index 0000000..8f05aff
--- /dev/null
+++ b/contrib/prerequisites.sha512
@@ -0,0 +1,2 @@
+3c82aeab9c1596d4da8afac2eec38e429e84f3211e1a572cf8fd2b546493c44c039b922a1133eaaa48bd7f3e11dbe795a384e21ed95cbe3ecc58d7ac02246117 gmp-6.1.0.tar.bz2
+51066066ff2c12ed2198605ecf68846b0c96b548adafa5b80e0c786d0df488411a5e8973358fce7192dc977ad4e68414cf14500e3c39746de62465eb145bb819 mpfr-3.1.4.tar.bz2
diff --git a/gdb/configure b/gdb/configure
index a3e73b4..034485d 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -899,8 +899,13 @@ with_jit_reader_dir
with_expat
with_libexpat_prefix
with_libexpat_type
+with_gmp_include
+with_gmp_lib
+with_gmp
with_libgmp_prefix
with_libgmp_type
+with_mpfr_include
+with_mpfr_lib
with_mpfr
with_libmpfr_prefix
with_libmpfr_type
@@ -1644,9 +1649,14 @@ Optional Packages:
--with-libexpat-prefix[=DIR] search for libexpat in DIR/include and DIR/lib
--without-libexpat-prefix don't search for libexpat in includedir and libdir
--with-libexpat-type=TYPE type of library to search for (auto/static/shared)
+ --with-gmp-include=DIR GMP include directory
+ --with-gmp-lib=DIR GMP lib directory
+ --with-gmp=DIR GMP install directory
--with-libgmp-prefix[=DIR] search for libgmp in DIR/include and DIR/lib
--without-libgmp-prefix don't search for libgmp in includedir and libdir
--with-libgmp-type=TYPE type of library to search for (auto/static/shared)
+ --with-mpfr-include=DIR MPFR include directory
+ --with-mpfr-lib=DIR MPFR lib directory
--with-mpfr include MPFR support (auto/yes/no)
--with-libmpfr-prefix[=DIR] search for libmpfr in DIR/include and DIR/lib
--without-libmpfr-prefix don't search for libmpfr in includedir and libdir
@@ -9990,6 +10000,35 @@ done
fi
fi
+
+# Check whether --with-gmp_include was given.
+if test "${with_gmp_include+set}" = set; then :
+ withval=$with_gmp_include; CPPFLAGS="$CPPFLAGS -I$withval"
+fi
+
+
+# Check whether --with-gmp_lib was given.
+if test "${with_gmp_lib+set}" = set; then :
+ withval=$with_gmp_lib; LDFLAGS="$LDFLAGS -L$withval"
+fi
+
+
+# Check whether --with-gmp was given.
+if test "${with_gmp+set}" = set; then :
+ withval=$with_gmp;
+ if test -z "$with_gmp_lib" && test -z "$with_gmp_include" ; then
+ CPPFLAGS="$CPPFLAGS -I$withval/include"
+ LDFLAGS="$LDFLAGS -L$withval/lib"
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "Do not use --with-gmp and --with-gmp-include/--with-gmp-lib options simultaneously.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+
+fi
+
+
# Verify that we have a usable GMP library.
@@ -10474,6 +10513,19 @@ if test "$HAVE_LIBGMP" != yes; then
fi
+# Check whether --with-mpfr_include was given.
+if test "${with_mpfr_include+set}" = set; then :
+ withval=$with_mpfr_include; CPPFLAGS="-I$withval $CPPFLAGS"
+fi
+
+
+# Check whether --with-mpfr_lib was given.
+if test "${with_mpfr_lib+set}" = set; then :
+ withval=$with_mpfr_lib; LDFLAGS="-L$withval $LDFLAGS"
+fi
+
+
+
# Check whether --with-mpfr was given.
if test "${with_mpfr+set}" = set; then :
withval=$with_mpfr;
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 32f25d9..97f43ce 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -683,6 +683,22 @@ else
fi
fi
+AC_ARG_WITH(gmp_include,
+ [ --with-gmp-include=DIR GMP include directory ],
+ CPPFLAGS="$CPPFLAGS -I$withval")
+AC_ARG_WITH(gmp_lib,
+ [ --with-gmp-lib=DIR GMP lib directory ],
+ LDFLAGS="$LDFLAGS -L$withval")
+AC_ARG_WITH(gmp,
+ [ --with-gmp=DIR GMP install directory ], [
+ if test -z "$with_gmp_lib" && test -z "$with_gmp_include" ; then
+ CPPFLAGS="$CPPFLAGS -I$withval/include"
+ LDFLAGS="$LDFLAGS -L$withval/lib"
+ else
+ AC_MSG_FAILURE([Do not use --with-gmp and --with-gmp-include/--with-gmp-lib options simultaneously.])
+ fi
+ ])
+
# Verify that we have a usable GMP library.
AC_LIB_HAVE_LINKFLAGS([gmp], [], [#include <gmp.h>],
[mpz_t n;
@@ -691,6 +707,15 @@ if test "$HAVE_LIBGMP" != yes; then
AC_MSG_ERROR([GMP is missing or unusable])
fi
+AC_ARG_WITH([mpfr_include],
+ [AC_HELP_STRING([--with-mpfr-include=DIR],
+ [MPFR include directory])],
+ [CPPFLAGS="-I$withval $CPPFLAGS"])
+AC_ARG_WITH([mpfr_lib],
+ [AC_HELP_STRING([--with-mpfr-lib=DIR],
+ [MPFR lib directory])],
+ [LDFLAGS="-L$withval $LDFLAGS"])
+
AC_ARG_WITH(mpfr,
AS_HELP_STRING([--with-mpfr], [include MPFR support (auto/yes/no)]),
[], [with_mpfr=auto])
--
1.9.1
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [PATCH] Enable GDB build with in-tree GMP and MPFR
2020-12-01 20:29 ` Bernd Edlinger
@ 2020-12-01 20:30 ` Simon Marchi
2020-12-02 3:21 ` Joel Brobecker
2020-12-14 17:40 ` [PATCH v2] " Bernd Edlinger
1 sibling, 1 reply; 140+ messages in thread
From: Simon Marchi @ 2020-12-01 20:30 UTC (permalink / raw)
To: Bernd Edlinger, Joel Brobecker; +Cc: gdb-patches
On 2020-12-01 3:29 p.m., Bernd Edlinger wrote:
> Hi Simon,
>
> On 12/1/20 8:38 PM, Bernd Edlinger wrote:
>> On 12/1/20 8:32 PM, Simon Marchi wrote:
>>>
>>> On 2020-12-01 2:29 p.m., Bernd Edlinger wrote:
>>>> I would really like to be able to build gdb with in-tree gmp / mpfr,
>>>> just as it works for gcc.
>>>
>>> Pardon my ignorance, but I don't see the gmp nor the mpfr source code in
>>> the binutils-gdb repository. Should it be checked in too?
>>>
>>
>>
>> Aehm, good question.
>> gcc uses a script ./contrib/download_prerequisites
>> that *can* be used to download gmp/mpfr and some more.
>>
>> Maybe I should add a stripped down version of that one?
>>
>
> So, this adds the contrib/download_prerequisites script.
>
> It is taken from gcc but does not download mpc and isl,
> just gmp and mpfr.
>
> It should work also when building gdb from the release tar.
>
>
> Is it OK to push?
I don't really know how it works, so I am not really the right person to
review it.
Simon
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [PATCH] Enable GDB build with in-tree GMP and MPFR
2020-12-01 20:30 ` Simon Marchi
@ 2020-12-02 3:21 ` Joel Brobecker
2020-12-08 20:39 ` [PING] " Bernd Edlinger
0 siblings, 1 reply; 140+ messages in thread
From: Joel Brobecker @ 2020-12-02 3:21 UTC (permalink / raw)
To: Simon Marchi; +Cc: Bernd Edlinger, gdb-patches
> I don't really know how it works, so I am not really the right person to
> review it.
That's unfortunately my case as well :-(.
--
Joel
^ permalink raw reply [flat|nested] 140+ messages in thread
* [PING] [PATCH] Enable GDB build with in-tree GMP and MPFR
2020-12-02 3:21 ` Joel Brobecker
@ 2020-12-08 20:39 ` Bernd Edlinger
0 siblings, 0 replies; 140+ messages in thread
From: Bernd Edlinger @ 2020-12-08 20:39 UTC (permalink / raw)
To: Joel Brobecker, Simon Marchi
Cc: gdb-patches, Pedro Alves, Eli Zaretskii, Andrew Burgess,
Tom Tromey, Tom de Vries
Hi,
On 12/2/20 4:21 AM, Joel Brobecker wrote:
>> I don't really know how it works, so I am not really the right person to
>> review it.
>
> That's unfortunately my case as well :-(.
>
this is the latest version of the patch:
https://sourceware.org/pipermail/gdb-patches/2020-December/173668.html
So who can review it?
Thanks
Bernd.
^ permalink raw reply [flat|nested] 140+ messages in thread
* [PATCH v2] Enable GDB build with in-tree GMP and MPFR
2020-12-01 20:29 ` Bernd Edlinger
2020-12-01 20:30 ` Simon Marchi
@ 2020-12-14 17:40 ` Bernd Edlinger
2020-12-14 18:47 ` Simon Marchi
1 sibling, 1 reply; 140+ messages in thread
From: Bernd Edlinger @ 2020-12-14 17:40 UTC (permalink / raw)
To: Simon Marchi, Joel Brobecker, Pedro Alves, Eli Zaretskii,
Andrew Burgess, gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1323 bytes --]
Well,
I thought, I should add a few words in the README
about this feature:
diff --git a/gdb/README b/gdb/README
index e65c5ea..db0a774 100644
--- a/gdb/README
+++ b/gdb/README
@@ -488,6 +488,9 @@ more obscure GDB `configure' options are not listed here.
Build GDB using the GMP library installed at the directory DIR.
If your host does not have GMP installed, you can get the latest
version at `https://gmplib.org/'.
+ You can also build GMP in-tree when you use the script
+ ./contrib/download_prerequisites. Note however, that this
+ does only work with a separate build directory.
`--with-mpfr'
Build GDB with GNU MPFR, a library for multiple-precision
@@ -499,6 +502,9 @@ more obscure GDB `configure' options are not listed here.
available, GDB will fall back to using host floating-point
arithmetic. If your host does not have GNU MPFR installed, you
can get the latest version from `https://www.mpfr.org/'.
+ You can also build MPFR in-tree when you use the script
+ ./contrib/download_prerequisites. Note however, that this
+ does only work with a separate build directory.
`--with-python[=PYTHON]'
Build GDB with Python scripting support. (Done by default if
Tested on x86_64-pc-linux-gnu.
Is it OK for trunk?
Thanks
Bernd.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Enable-GDB-build-with-in-tree-GMP-and-MPFR.patch --]
[-- Type: text/x-patch; name="0001-Enable-GDB-build-with-in-tree-GMP-and-MPFR.patch", Size: 17679 bytes --]
From 367fae972e90370540468786f59856cb7581f6b2 Mon Sep 17 00:00:00 2001
From: Bernd Edlinger <bernd.edlinger@hotmail.de>
Date: Sun, 15 Nov 2020 15:37:22 +0100
Subject: [PATCH] Enable GDB build with in-tree GMP and MPFR
With this patch GDB can be built with in-tree GMP and/or
MPFR. This works also for cross-builds.
All that is needed, is a sym-link in the source tree,
like this:
gmp -> ../gmp-6.1.0
mpfr -> ../mpfr-3.1.4
2020-12-10 Bernd Edlinger <bernd.edlinger@hotmail.de>
* Makefile.def: Prepare for GDB build with intree GMP.
* Makefile.in: Regenerate.
gdb:
2020-12-10 Bernd Edlinger <bernd.edlinger@hotmail.de>
* configure.ac: Add --with-gmp=DIR, --with-gmp-include=DIR
and --with-gmp-lib=DIR
as well as --with-mpfr-include=DIR and --with-mpfr-lib=DIR
for compatibility with top level configure script.
* configure: Regenerate.
* README: Mention ./contrib/download_prerequisites.
contrib:
2020-12-10 Bernd Edlinger <bernd.edlinger@hotmail.de>
* download_prerequisites: New helper script.
* prerequisites.md5: checksums.
* prerequisites.sha512: checksums.
---
Makefile.def | 5 +-
Makefile.in | 4 +-
contrib/download_prerequisites | 263 +++++++++++++++++++++++++++++++++++++++++
contrib/prerequisites.md5 | 2 +
contrib/prerequisites.sha512 | 2 +
gdb/README | 6 +
gdb/configure | 52 ++++++++
gdb/configure.ac | 25 ++++
8 files changed, 357 insertions(+), 2 deletions(-)
create mode 100755 contrib/download_prerequisites
create mode 100644 contrib/prerequisites.md5
create mode 100644 contrib/prerequisites.sha512
diff --git a/Makefile.def b/Makefile.def
index 089e70a..1b99b42 100644
--- a/Makefile.def
+++ b/Makefile.def
@@ -115,7 +115,8 @@ host_modules= { module= zlib; no_install=true; no_check=true;
host_modules= { module= gnulib; };
host_modules= { module= gdbsupport; };
host_modules= { module= gdbserver; };
-host_modules= { module= gdb; };
+host_modules= { module= gdb;
+ extra_configure_flags='@extra_mpfr_configure_flags@ @extra_mpc_mpfr_configure_flags@';};
host_modules= { module= expect; };
host_modules= { module= guile; };
host_modules= { module= tk; };
@@ -391,6 +392,8 @@ dependencies = { module=all-intl; on=all-libiconv; };
// Host modules specific to gdb.
dependencies = { module=configure-gdb; on=all-intl; };
+dependencies = { module=configure-gdb; on=all-gmp; };
+dependencies = { module=configure-gdb; on=all-mpfr; };
dependencies = { module=configure-gdb; on=configure-sim; };
dependencies = { module=configure-gdb; on=all-bfd; };
dependencies = { module=configure-gdb; on=all-gnulib; };
diff --git a/Makefile.in b/Makefile.in
index fe34132..738fd32 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -29491,7 +29491,7 @@ configure-gdb:
$$s/$$module_srcdir/configure \
--srcdir=$${topdir}/$$module_srcdir \
$(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \
- --target=${target_alias} \
+ --target=${target_alias} @extra_mpfr_configure_flags@ @extra_mpc_mpfr_configure_flags@ \
|| exit 1
@endif gdb
@@ -52449,6 +52449,8 @@ configure-libcc1: maybe-configure-gcc
all-libcc1: maybe-all-gcc
all-utils: maybe-all-libiberty
configure-gdb: maybe-all-intl
+configure-gdb: maybe-all-gmp
+configure-gdb: maybe-all-mpfr
configure-gdb: maybe-all-bfd
configure-gdb: maybe-all-libiconv
all-gdb: maybe-all-libiberty
diff --git a/contrib/download_prerequisites b/contrib/download_prerequisites
new file mode 100755
index 0000000..0d04030
--- /dev/null
+++ b/contrib/download_prerequisites
@@ -0,0 +1,263 @@
+#! /bin/sh
+#! -*- coding:utf-8; mode:shell-script; -*-
+
+# Download some prerequisites needed by GDB.
+# Run this from the top level of the GDB source tree and the GDB build will do
+# the right thing. Run it with the `--help` option for more information.
+#
+# (C) 2010-2020 Free Software Foundation
+#
+# 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/.
+
+program='download_prerequisites'
+version='(unversioned)'
+
+# MAINTAINERS: If you update the package versions below, please
+# remember to also update the files `contrib/prerequisites.sha512` and
+# `contrib/prerequisites.md5` with the new checksums.
+
+gmp='gmp-6.1.0.tar.bz2'
+mpfr='mpfr-3.1.4.tar.bz2'
+
+base_url='http://gcc.gnu.org/pub/gcc/infrastructure/'
+
+echo_archives() {
+ echo "${gmp}"
+ echo "${mpfr}"
+}
+
+verify=1
+force=0
+OS=$(uname)
+
+case $OS in
+ "Darwin"|"FreeBSD"|"DragonFly"|"AIX")
+ chksum='shasum -a 512 --check'
+ ;;
+ "OpenBSD")
+ chksum='sha512 -c'
+ ;;
+ *)
+ chksum='sha512sum -c'
+ ;;
+esac
+
+if type wget > /dev/null ; then
+ fetch='wget'
+else
+ fetch='curl -LO'
+fi
+chksum_extension='sha512'
+directory='.'
+
+helptext="usage: ${program} [OPTION...]
+
+Downloads some prerequisites needed by GDB. Run this from the top level of the
+GDB source tree and the GDB build will do the right thing.
+
+The following options are available:
+
+ --directory=DIR download and unpack packages into DIR instead of '.'
+ --force download again overwriting existing packages
+ --no-force do not download existing packages again (default)
+ --verify verify package integrity after download (default)
+ --no-verify don't verify package integrity
+ --sha512 use SHA512 checksum to verify package integrity (default)
+ --md5 use MD5 checksum to verify package integrity
+ --help show this text and exit
+ --version show version information and exit
+"
+
+versiontext="${program} ${version}
+Copyright (C) 2020 Free Software Foundation, Inc.
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+die() {
+ echo "error: $@" >&2
+ exit 1
+}
+
+for arg in "$@"
+do
+ case "${arg}" in
+ --help)
+ echo "${helptext}"
+ exit
+ ;;
+ --version)
+ echo "${versiontext}"
+ exit
+ ;;
+ esac
+done
+unset arg
+
+# Emulate Linux's 'md5 --check' on macOS
+md5_check() {
+ # Store the standard input: a line from contrib/prerequisites.md5:
+ md5_checksum_line=$(cat -)
+ # Grab the text before the first space
+ md5_checksum_expected="${md5_checksum_line%% *}"
+ # Grab the text after the first space
+ file_to_check="${md5_checksum_line##* }"
+ # Calculate the md5 checksum for the downloaded file
+ md5_checksum_output=$(md5 -r "${file_to_check}")
+ # Grab the text before the first space
+ md5_checksum_detected="${md5_checksum_output%% *}"
+ [ "${md5_checksum_expected}" == "${md5_checksum_detected}" ] \
+ || die "Cannot verify integrity of possibly corrupted file ${file_to_check}"
+ echo "${file_to_check}: OK"
+}
+
+
+argnext=
+for arg in "$@"
+do
+ if [ "x${argnext}" = x ]
+ then
+ case "${arg}" in
+ --directory)
+ argnext='directory'
+ ;;
+ --directory=*)
+ directory="${arg#--directory=}"
+ ;;
+ --force)
+ force=1
+ ;;
+ --no-force)
+ force=0
+ ;;
+ --verify)
+ verify=1
+ ;;
+ --no-verify)
+ verify=0
+ ;;
+ --sha512)
+ case $OS in
+ "Darwin")
+ chksum='shasum -a 512 --check'
+ ;;
+ *)
+ chksum='sha512sum --check'
+ ;;
+ esac
+ chksum_extension='sha512'
+ verify=1
+ ;;
+ --md5)
+ case $OS in
+ "Darwin")
+ chksum='md5_check'
+ ;;
+ *)
+ chksum='md5 --check'
+ ;;
+ esac
+ chksum_extension='md5'
+ verify=1
+ ;;
+ -*)
+ die "unknown option: ${arg}"
+ ;;
+ *)
+ die "too many arguments"
+ ;;
+ esac
+ else
+ case "${arg}" in
+ -*)
+ die "Missing argument for option --${argnext}"
+ ;;
+ esac
+ case "${argnext}" in
+ directory)
+ directory="${arg}"
+ ;;
+ *)
+ die "The impossible has happened"
+ ;;
+ esac
+ argnext=
+ fi
+done
+[ "x${argnext}" = x ] || die "Missing argument for option --${argnext}"
+unset arg argnext
+
+[ -e ./gdb/version.in ] \
+ || die "You must run this script in the top-level GDB source directory"
+
+[ -d "${directory}" ] \
+ || die "No such directory: ${directory}"
+
+for ar in $(echo_archives)
+do
+ if [ ${force} -gt 0 ]; then rm -f "${directory}/${ar}"; fi
+ [ -e "${directory}/${ar}" ] \
+ || ( cd "${directory}" && ${fetch} --no-verbose "${base_url}${ar}" ) \
+ || die "Cannot download ${ar} from ${base_url}"
+done
+unset ar
+
+if [ ${verify} -gt 0 ]
+then
+ chksumfile="contrib/prerequisites.${chksum_extension}"
+ [ -r "${chksumfile}" ] || die "No checksums available"
+ for ar in $(echo_archives)
+ do
+ grep "${ar}" "${chksumfile}" \
+ | ( cd "${directory}" && ${chksum} ) \
+ || die "Cannot verify integrity of possibly corrupted file ${ar}"
+ done
+ unset chksumfile
+fi
+unset ar
+
+for ar in $(echo_archives)
+do
+ package="${ar%.tar*}"
+ if [ ${force} -gt 0 ]; then rm -rf "${directory}/${package}"; fi
+ case $ar in
+ *.gz)
+ uncompress='gzip -d'
+ ;;
+ *.bz2)
+ uncompress='bzip2 -d'
+ ;;
+ *)
+ uncompress='cat'
+ ;;
+ esac
+ [ -e "${directory}/${package}" ] \
+ || ( cd "${directory}" && $uncompress <"${ar}" | tar -xf - ) \
+ || die "Cannot extract package from ${ar}"
+ unset package
+done
+unset ar
+
+for ar in $(echo_archives)
+do
+ target="${directory}/${ar%.tar*}/"
+ linkname="${ar%-*}"
+ if [ ${force} -gt 0 ]; then rm -f "${linkname}"; fi
+ [ -e "${linkname}" ] \
+ || ln -s "${target}" "${linkname}" \
+ || die "Cannot create symbolic link ${linkname} --> ${target}"
+ unset target linkname
+done
+unset ar
+
+echo "All prerequisites downloaded successfully."
diff --git a/contrib/prerequisites.md5 b/contrib/prerequisites.md5
new file mode 100644
index 0000000..cf7be0d
--- /dev/null
+++ b/contrib/prerequisites.md5
@@ -0,0 +1,2 @@
+86ee6e54ebfc4a90b643a65e402c4048 gmp-6.1.0.tar.bz2
+b8a2f6b0e68bef46e53da2ac439e1cf4 mpfr-3.1.4.tar.bz2
diff --git a/contrib/prerequisites.sha512 b/contrib/prerequisites.sha512
new file mode 100644
index 0000000..8f05aff
--- /dev/null
+++ b/contrib/prerequisites.sha512
@@ -0,0 +1,2 @@
+3c82aeab9c1596d4da8afac2eec38e429e84f3211e1a572cf8fd2b546493c44c039b922a1133eaaa48bd7f3e11dbe795a384e21ed95cbe3ecc58d7ac02246117 gmp-6.1.0.tar.bz2
+51066066ff2c12ed2198605ecf68846b0c96b548adafa5b80e0c786d0df488411a5e8973358fce7192dc977ad4e68414cf14500e3c39746de62465eb145bb819 mpfr-3.1.4.tar.bz2
diff --git a/gdb/README b/gdb/README
index e65c5ea..db0a774 100644
--- a/gdb/README
+++ b/gdb/README
@@ -488,6 +488,9 @@ more obscure GDB `configure' options are not listed here.
Build GDB using the GMP library installed at the directory DIR.
If your host does not have GMP installed, you can get the latest
version at `https://gmplib.org/'.
+ You can also build GMP in-tree when you use the script
+ ./contrib/download_prerequisites. Note however, that this
+ does only work with a separate build directory.
`--with-mpfr'
Build GDB with GNU MPFR, a library for multiple-precision
@@ -499,6 +502,9 @@ more obscure GDB `configure' options are not listed here.
available, GDB will fall back to using host floating-point
arithmetic. If your host does not have GNU MPFR installed, you
can get the latest version from `https://www.mpfr.org/'.
+ You can also build MPFR in-tree when you use the script
+ ./contrib/download_prerequisites. Note however, that this
+ does only work with a separate build directory.
`--with-python[=PYTHON]'
Build GDB with Python scripting support. (Done by default if
diff --git a/gdb/configure b/gdb/configure
index 24e6fbc..67747b3 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -899,8 +899,13 @@ with_jit_reader_dir
with_expat
with_libexpat_prefix
with_libexpat_type
+with_gmp_include
+with_gmp_lib
+with_gmp
with_libgmp_prefix
with_libgmp_type
+with_mpfr_include
+with_mpfr_lib
with_mpfr
with_libmpfr_prefix
with_libmpfr_type
@@ -1644,9 +1649,14 @@ Optional Packages:
--with-libexpat-prefix[=DIR] search for libexpat in DIR/include and DIR/lib
--without-libexpat-prefix don't search for libexpat in includedir and libdir
--with-libexpat-type=TYPE type of library to search for (auto/static/shared)
+ --with-gmp-include=DIR GMP include directory
+ --with-gmp-lib=DIR GMP lib directory
+ --with-gmp=DIR GMP install directory
--with-libgmp-prefix[=DIR] search for libgmp in DIR/include and DIR/lib
--without-libgmp-prefix don't search for libgmp in includedir and libdir
--with-libgmp-type=TYPE type of library to search for (auto/static/shared)
+ --with-mpfr-include=DIR MPFR include directory
+ --with-mpfr-lib=DIR MPFR lib directory
--with-mpfr include MPFR support (auto/yes/no)
--with-libmpfr-prefix[=DIR] search for libmpfr in DIR/include and DIR/lib
--without-libmpfr-prefix don't search for libmpfr in includedir and libdir
@@ -9990,6 +10000,35 @@ done
fi
fi
+
+# Check whether --with-gmp_include was given.
+if test "${with_gmp_include+set}" = set; then :
+ withval=$with_gmp_include; CPPFLAGS="$CPPFLAGS -I$withval"
+fi
+
+
+# Check whether --with-gmp_lib was given.
+if test "${with_gmp_lib+set}" = set; then :
+ withval=$with_gmp_lib; LDFLAGS="$LDFLAGS -L$withval"
+fi
+
+
+# Check whether --with-gmp was given.
+if test "${with_gmp+set}" = set; then :
+ withval=$with_gmp;
+ if test -z "$with_gmp_lib" && test -z "$with_gmp_include" ; then
+ CPPFLAGS="$CPPFLAGS -I$withval/include"
+ LDFLAGS="$LDFLAGS -L$withval/lib"
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "Do not use --with-gmp and --with-gmp-include/--with-gmp-lib options simultaneously.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+
+fi
+
+
# Verify that we have a usable GMP library.
@@ -10474,6 +10513,19 @@ if test "$HAVE_LIBGMP" != yes; then
fi
+# Check whether --with-mpfr_include was given.
+if test "${with_mpfr_include+set}" = set; then :
+ withval=$with_mpfr_include; CPPFLAGS="-I$withval $CPPFLAGS"
+fi
+
+
+# Check whether --with-mpfr_lib was given.
+if test "${with_mpfr_lib+set}" = set; then :
+ withval=$with_mpfr_lib; LDFLAGS="-L$withval $LDFLAGS"
+fi
+
+
+
# Check whether --with-mpfr was given.
if test "${with_mpfr+set}" = set; then :
withval=$with_mpfr;
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 32f25d9..97f43ce 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -683,6 +683,22 @@ else
fi
fi
+AC_ARG_WITH(gmp_include,
+ [ --with-gmp-include=DIR GMP include directory ],
+ CPPFLAGS="$CPPFLAGS -I$withval")
+AC_ARG_WITH(gmp_lib,
+ [ --with-gmp-lib=DIR GMP lib directory ],
+ LDFLAGS="$LDFLAGS -L$withval")
+AC_ARG_WITH(gmp,
+ [ --with-gmp=DIR GMP install directory ], [
+ if test -z "$with_gmp_lib" && test -z "$with_gmp_include" ; then
+ CPPFLAGS="$CPPFLAGS -I$withval/include"
+ LDFLAGS="$LDFLAGS -L$withval/lib"
+ else
+ AC_MSG_FAILURE([Do not use --with-gmp and --with-gmp-include/--with-gmp-lib options simultaneously.])
+ fi
+ ])
+
# Verify that we have a usable GMP library.
AC_LIB_HAVE_LINKFLAGS([gmp], [], [#include <gmp.h>],
[mpz_t n;
@@ -691,6 +707,15 @@ if test "$HAVE_LIBGMP" != yes; then
AC_MSG_ERROR([GMP is missing or unusable])
fi
+AC_ARG_WITH([mpfr_include],
+ [AC_HELP_STRING([--with-mpfr-include=DIR],
+ [MPFR include directory])],
+ [CPPFLAGS="-I$withval $CPPFLAGS"])
+AC_ARG_WITH([mpfr_lib],
+ [AC_HELP_STRING([--with-mpfr-lib=DIR],
+ [MPFR lib directory])],
+ [LDFLAGS="-L$withval $LDFLAGS"])
+
AC_ARG_WITH(mpfr,
AS_HELP_STRING([--with-mpfr], [include MPFR support (auto/yes/no)]),
[], [with_mpfr=auto])
--
1.9.1
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [PATCH v2] Enable GDB build with in-tree GMP and MPFR
2020-12-14 17:40 ` [PATCH v2] " Bernd Edlinger
@ 2020-12-14 18:47 ` Simon Marchi
2020-12-14 21:35 ` Tom Tromey
2020-12-15 15:10 ` Bernd Edlinger
0 siblings, 2 replies; 140+ messages in thread
From: Simon Marchi @ 2020-12-14 18:47 UTC (permalink / raw)
To: Bernd Edlinger, Joel Brobecker, Pedro Alves, Eli Zaretskii,
Andrew Burgess, gdb-patches
I'll give a shot at reviewing this, to make it progress.
Joel, there's a question for you below.
On 2020-12-14 12:40 p.m., Bernd Edlinger wrote:
> Well,
>
> I thought, I should add a few words in the README
> about this feature:
>
> diff --git a/gdb/README b/gdb/README
> index e65c5ea..db0a774 100644
> --- a/gdb/README
> +++ b/gdb/README
> @@ -488,6 +488,9 @@ more obscure GDB `configure' options are not listed here.
> Build GDB using the GMP library installed at the directory DIR.
> If your host does not have GMP installed, you can get the latest
> version at `https://gmplib.org/'.
> + You can also build GMP in-tree when you use the script
> + ./contrib/download_prerequisites. Note however, that this
> + does only work with a separate build directory.
>
> `--with-mpfr'
> Build GDB with GNU MPFR, a library for multiple-precision
> @@ -499,6 +502,9 @@ more obscure GDB `configure' options are not listed here.
> available, GDB will fall back to using host floating-point
> arithmetic. If your host does not have GNU MPFR installed, you
> can get the latest version from `https://www.mpfr.org/'.
> + You can also build MPFR in-tree when you use the script
> + ./contrib/download_prerequisites. Note however, that this
> + does only work with a separate build directory.
>
> `--with-python[=PYTHON]'
> Build GDB with Python scripting support. (Done by default if
>
>
> Tested on x86_64-pc-linux-gnu.
> Is it OK for trunk?
>
>
> Thanks
> Bernd.
>
There is already --with-libgmp-prefix / --without-libgmp-prefix,
provided (I think by):
# Verify that we have a usable GMP library.
AC_LIB_HAVE_LINKFLAGS([gmp], [], [#include <gmp.h>],
[mpz_t n;
mpz_init (n);])
So with this patch, we now have:
--with-gmp-include=DIR GMP include directory
--with-gmp-lib=DIR GMP lib directory
--with-gmp=DIR GMP install directory
--with-libgmp-prefix[=DIR] search for libgmp in DIR/include and DIR/lib
--without-libgmp-prefix don't search for libgmp in includedir and libdir
I think that's getting a bit confusing. That's too many ways to set gmp
paths, with -with-libgmp-prefix and --with-gmp doing the same thing.
If the rest of the binutils/gcc ecosystem already uses --with-gmp,
--with-gmp-include and --with-gmp-lib, I think we should align with
those. Fortunately, we haven't yet shipped a GDB with
--with-libgmp-prefix, so I think it's safe to remove it. It might mean
that we have to stop using AC_LIB_HAVE_LINKFLAGS though, or customize
it. Joel, do you agree?
In this line, in top-level Makefile.def, do you need to also add
something about gmp, and why pass flags about mpc_mpfr (I sincerely
don't know what it is/does)?
host_modules= { module= gdb;
extra_configure_flags='@extra_mpfr_configure_flags@ @extra_mpc_mpfr_configure_flags@';};
In the README, you say:
You can also build GMP in-tree when you use the script
./contrib/download_prerequisites. Note however, that this
does only work with a separate build directory.
That leaves me with some questions:
- do I need to run this script myself before configure?
- if I do, does that mean the build will use the downloaded version,
even if there is a working version on my system?
It would be good to answer those questions in the README text.
An alternative to downloading the pre-requisites would be to check them
in the repo. We do it for readline already: there is a copy in the
repo, which is used by default, but you can specify
--with-system-readline if you want to use the system's readline. We
could do the same with gmp and mpfr. The downside is that we deviate a
bit from how gcc does, the the upside is that it's simpler, IMO.
Note that any change to the files outside GDB will have to be approved
by the binutils folks too. And changes to the top-level Makefile will
have to be replicated to the gcc repo.
Simon
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [PATCH v2] Enable GDB build with in-tree GMP and MPFR
2020-12-14 18:47 ` Simon Marchi
@ 2020-12-14 21:35 ` Tom Tromey
2020-12-14 22:17 ` Simon Marchi
2020-12-15 15:10 ` Bernd Edlinger
1 sibling, 1 reply; 140+ messages in thread
From: Tom Tromey @ 2020-12-14 21:35 UTC (permalink / raw)
To: Simon Marchi
Cc: Bernd Edlinger, Joel Brobecker, Pedro Alves, Eli Zaretskii,
Andrew Burgess, gdb-patches
>>>>> "Simon" == Simon Marchi <simark@simark.ca> writes:
Simon> So with this patch, we now have:
Simon> --with-gmp-include=DIR GMP include directory
Simon> --with-gmp-lib=DIR GMP lib directory
Simon> --with-gmp=DIR GMP install directory
Simon> --with-libgmp-prefix[=DIR] search for libgmp in DIR/include and DIR/lib
Simon> --without-libgmp-prefix don't search for libgmp in includedir and libdir
Simon> I think that's getting a bit confusing. That's too many ways to set gmp
Simon> paths, with -with-libgmp-prefix and --with-gmp doing the same thing.
FWIW we have the same situation with MPFR.
Simon> It might mean that we have to stop using AC_LIB_HAVE_LINKFLAGS
Simon> though, or customize it.
Yes. Perhaps alternatively we could promote its use to the top level.
It's maybe a pain to do that.
Simon> An alternative to downloading the pre-requisites would be to check them
Simon> in the repo. We do it for readline already: there is a copy in the
Simon> repo, which is used by default, but you can specify
Simon> --with-system-readline if you want to use the system's readline. We
Simon> could do the same with gmp and mpfr. The downside is that we deviate a
Simon> bit from how gcc does, the the upside is that it's simpler, IMO.
For me the main difference here is that, historically, we've had to
patch readline. In cases where GDB has never needed to patch a
dependency (libiconv comes to mind), we've haven't bothered.
Tom
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [PATCH v2] Enable GDB build with in-tree GMP and MPFR
2020-12-14 21:35 ` Tom Tromey
@ 2020-12-14 22:17 ` Simon Marchi
2020-12-15 2:33 ` Joel Brobecker
2020-12-15 15:33 ` Bernd Edlinger
0 siblings, 2 replies; 140+ messages in thread
From: Simon Marchi @ 2020-12-14 22:17 UTC (permalink / raw)
To: Tom Tromey
Cc: Bernd Edlinger, Joel Brobecker, Pedro Alves, Eli Zaretskii,
Andrew Burgess, gdb-patches
On 2020-12-14 4:35 p.m., Tom Tromey wrote:
>>>>>> "Simon" == Simon Marchi <simark@simark.ca> writes:
>
> Simon> So with this patch, we now have:
>
> Simon> --with-gmp-include=DIR GMP include directory
> Simon> --with-gmp-lib=DIR GMP lib directory
> Simon> --with-gmp=DIR GMP install directory
> Simon> --with-libgmp-prefix[=DIR] search for libgmp in DIR/include and DIR/lib
> Simon> --without-libgmp-prefix don't search for libgmp in includedir and libdir
>
> Simon> I think that's getting a bit confusing. That's too many ways to set gmp
> Simon> paths, with -with-libgmp-prefix and --with-gmp doing the same thing.
>
> FWIW we have the same situation with MPFR.
:(
> Simon> It might mean that we have to stop using AC_LIB_HAVE_LINKFLAGS
> Simon> though, or customize it.
>
> Yes. Perhaps alternatively we could promote its use to the top level.
> It's maybe a pain to do that.
Perhaps, but --with-{gmp,mpfr} would need to be kept as backwards
compatibility. I think it would be hard to convince the gcc people of
the benefits of such a change.
> Simon> An alternative to downloading the pre-requisites would be to check them
> Simon> in the repo. We do it for readline already: there is a copy in the
> Simon> repo, which is used by default, but you can specify
> Simon> --with-system-readline if you want to use the system's readline. We
> Simon> could do the same with gmp and mpfr. The downside is that we deviate a
> Simon> bit from how gcc does, the the upside is that it's simpler, IMO.
>
> For me the main difference here is that, historically, we've had to
> patch readline. In cases where GDB has never needed to patch a
> dependency (libiconv comes to mind), we've haven't bothered.
Ok, when you put it like that then it doesn't make as much sense to
check the code in the repo.
Thinking about it a bit more, I don't see why gmp and mpfr get this
treatment, what is it that makes them different from other dependencies?
If you want to build GDB with XML support, you download and build expat,
or install it using your package manager. Why can't you do the same
with mpfr/gmp? The only reason for us I can see is "because gcc does
it" and we share the build system with gcc. But otherwise, I'd just
tell people to build/install mpfr and gmp themselves.
Simon
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [PATCH v2] Enable GDB build with in-tree GMP and MPFR
2020-12-14 22:17 ` Simon Marchi
@ 2020-12-15 2:33 ` Joel Brobecker
2020-12-15 14:39 ` Simon Marchi
2020-12-15 15:33 ` Bernd Edlinger
1 sibling, 1 reply; 140+ messages in thread
From: Joel Brobecker @ 2020-12-15 2:33 UTC (permalink / raw)
To: Simon Marchi
Cc: Tom Tromey, Bernd Edlinger, Pedro Alves, Eli Zaretskii,
Andrew Burgess, gdb-patches
> >>>>>> "Simon" == Simon Marchi <simark@simark.ca> writes:
> >
> > Simon> So with this patch, we now have:
> >
> > Simon> --with-gmp-include=DIR GMP include directory
> > Simon> --with-gmp-lib=DIR GMP lib directory
> > Simon> --with-gmp=DIR GMP install directory
> > Simon> --with-libgmp-prefix[=DIR] search for libgmp in DIR/include and DIR/lib
> > Simon> --without-libgmp-prefix don't search for libgmp in includedir and libdir
> >
> > Simon> I think that's getting a bit confusing. That's too many ways to set gmp
> > Simon> paths, with -with-libgmp-prefix and --with-gmp doing the same thing.
> >
> > FWIW we have the same situation with MPFR.
>
> :(
Yeah, my reaction exactly when Bernd made me discover this problem.
There might be other options in the same category; we should
double-check (busy this week, but I can have a look during the weekend
if noone beats me to it).
> > Simon> It might mean that we have to stop using AC_LIB_HAVE_LINKFLAGS
> > Simon> though, or customize it.
> >
> > Yes. Perhaps alternatively we could promote its use to the top level.
> > It's maybe a pain to do that.
>
> Perhaps, but --with-{gmp,mpfr} would need to be kept as backwards
> compatibility. I think it would be hard to convince the gcc people of
> the benefits of such a change.
Here's a radical question: Do we really need to stay in sync with GCC,
at this point? What are the benefits and requirements of doing so?
Because GCC doesn't coordinate with us when they make changes to
the toplevel configury, we're only going to get into these problems
more.
In fact, how much does the toplevel configure really need to do?
Intuitively, it doesn't really need to do very much, if we ignore
all the stuff that's GCC-specific.
A more relevant conundrum, for me, might be to look at keeping
binutils and GDB in sync in terms of the options being used.
And then we have the question of how to provide users who want to
configure parts or all of binutils-gdb what options they can use,
and what they do. I don't know how easy we can do that via the
toplevel configure's --help. One interesting question is: Would
doing so help us avoid inconsistencies with binutils?
So, as you can see, the question is much larger than just GMP/MPFR.
> > Simon> An alternative to downloading the pre-requisites would be to check them
> > Simon> in the repo. We do it for readline already: there is a copy in the
> > Simon> repo, which is used by default, but you can specify
> > Simon> --with-system-readline if you want to use the system's readline. We
> > Simon> could do the same with gmp and mpfr. The downside is that we deviate a
> > Simon> bit from how gcc does, the the upside is that it's simpler, IMO.
> >
> > For me the main difference here is that, historically, we've had to
> > patch readline. In cases where GDB has never needed to patch a
> > dependency (libiconv comes to mind), we've haven't bothered.
>
> Ok, when you put it like that then it doesn't make as much sense to
> check the code in the repo.
>
> Thinking about it a bit more, I don't see why gmp and mpfr get this
> treatment, what is it that makes them different from other dependencies?
> If you want to build GDB with XML support, you download and build expat,
> or install it using your package manager. Why can't you do the same
> with mpfr/gmp? The only reason for us I can see is "because gcc does
> it" and we share the build system with gcc. But otherwise, I'd just
> tell people to build/install mpfr and gmp themselves.
>
> Simon
--
Joel
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [PATCH v2] Enable GDB build with in-tree GMP and MPFR
2020-12-15 2:33 ` Joel Brobecker
@ 2020-12-15 14:39 ` Simon Marchi
2020-12-15 16:24 ` Bernd Edlinger
2020-12-16 7:33 ` Joel Brobecker
0 siblings, 2 replies; 140+ messages in thread
From: Simon Marchi @ 2020-12-15 14:39 UTC (permalink / raw)
To: Joel Brobecker, Simon Marchi
Cc: Tom Tromey, Bernd Edlinger, Pedro Alves, Eli Zaretskii,
Andrew Burgess, gdb-patches
On 2020-12-14 9:33 p.m., Joel Brobecker wrote:
>>> Simon> It might mean that we have to stop using AC_LIB_HAVE_LINKFLAGS
>>> Simon> though, or customize it.
>>>
>>> Yes. Perhaps alternatively we could promote its use to the top level.
>>> It's maybe a pain to do that.
>>
>> Perhaps, but --with-{gmp,mpfr} would need to be kept as backwards
>> compatibility. I think it would be hard to convince the gcc people of
>> the benefits of such a change.
>
> Here's a radical question: Do we really need to stay in sync with GCC,
> at this point? What are the benefits and requirements of doing so?
> Because GCC doesn't coordinate with us when they make changes to
> the toplevel configury, we're only going to get into these problems
> more.
Indeed, it's a bit annoying that the burden of syncing is only on one
side.
What are the original reasons for staying in sync with gcc?
Instead of manually syncing files, I know Pedro already mentioned the
idea of having a single repo with binutils + gcc + gdb, a bit like
LLVM have moved to a big mono repo. Especially with gcc being a C++
program as well, we want to share more. So desyncing from gcc would
make such a move more difficult. But it's just an idea at this point,
so maybe it's not that important.
Otherwise, just for convenience reasons, it would be nice to think more
of gcc + binutils + gdb (an maybe others) as a single toolchain, and
having consistency and no suprises in how you build them is a good thing
for those build and integrate them.
> In fact, how much does the toplevel configure really need to do?
> Intuitively, it doesn't really need to do very much, if we ignore
> all the stuff that's GCC-specific.
I know next to nothing about the top-level configure, because I never
needed to dig into it.
> A more relevant conundrum, for me, might be to look at keeping
> binutils and GDB in sync in terms of the options being used.
>
> And then we have the question of how to provide users who want to
> configure parts or all of binutils-gdb what options they can use,
> and what they do. I don't know how easy we can do that via the
> toplevel configure's --help. One interesting question is: Would
> doing so help us avoid inconsistencies with binutils?
I'm not sure I understand. Do you mean, how do users get to learn about
the configure switches of all projects?
All I know is that you can do "./configure --help=recursive" from the
top-level, but that's not particularly convenient, it just dumps all
the helps from all the configure scripts. It's good if you want to
find / grep.
Simon
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [PATCH v2] Enable GDB build with in-tree GMP and MPFR
2020-12-15 14:39 ` Simon Marchi
@ 2020-12-15 16:24 ` Bernd Edlinger
2020-12-16 7:33 ` Joel Brobecker
1 sibling, 0 replies; 140+ messages in thread
From: Bernd Edlinger @ 2020-12-15 16:24 UTC (permalink / raw)
To: Simon Marchi, Joel Brobecker, Simon Marchi
Cc: Tom Tromey, Pedro Alves, Eli Zaretskii, Andrew Burgess, gdb-patches
On 12/15/20 3:39 PM, Simon Marchi wrote:
> On 2020-12-14 9:33 p.m., Joel Brobecker wrote:
>>>> Simon> It might mean that we have to stop using AC_LIB_HAVE_LINKFLAGS
>>>> Simon> though, or customize it.
>>>>
>>>> Yes. Perhaps alternatively we could promote its use to the top level.
>>>> It's maybe a pain to do that.
>>>
>>> Perhaps, but --with-{gmp,mpfr} would need to be kept as backwards
>>> compatibility. I think it would be hard to convince the gcc people of
>>> the benefits of such a change.
>>
>> Here's a radical question: Do we really need to stay in sync with GCC,
>> at this point? What are the benefits and requirements of doing so?
>> Because GCC doesn't coordinate with us when they make changes to
>> the toplevel configury, we're only going to get into these problems
>> more.
>
> Indeed, it's a bit annoying that the burden of syncing is only on one
> side.
>
> What are the original reasons for staying in sync with gcc?
>
> Instead of manually syncing files, I know Pedro already mentioned the
> idea of having a single repo with binutils + gcc + gdb, a bit like
> LLVM have moved to a big mono repo. Especially with gcc being a C++
> program as well, we want to share more. So desyncing from gcc would
> make such a move more difficult. But it's just an idea at this point,
> so maybe it's not that important.
>
> Otherwise, just for convenience reasons, it would be nice to think more
> of gcc + binutils + gdb (an maybe others) as a single toolchain, and
> having consistency and no suprises in how you build them is a good thing
> for those build and integrate them.
>
>> In fact, how much does the toplevel configure really need to do?
>> Intuitively, it doesn't really need to do very much, if we ignore
>> all the stuff that's GCC-specific.
>
> I know next to nothing about the top-level configure, because I never
> needed to dig into it.
>
One thing, that might be useful here, is making the toplevel
configure script print an error, when GMP is not available,
instead of having the error later when gdb/configure runs.
For instance when the toplevel configure detects gcc needs
to be built, it checks the availability and correct versions if
GMP/MPFR/MPC/ISL while it does nothing when gdb is built.
My patch does not yet touch that logic, but it is probably
a next logical step.
>> A more relevant conundrum, for me, might be to look at keeping
>> binutils and GDB in sync in terms of the options being used.
>>
>> And then we have the question of how to provide users who want to
>> configure parts or all of binutils-gdb what options they can use,
>> and what they do. I don't know how easy we can do that via the
>> toplevel configure's --help. One interesting question is: Would
>> doing so help us avoid inconsistencies with binutils?
>
> I'm not sure I understand. Do you mean, how do users get to learn about
> the configure switches of all projects?
>
> All I know is that you can do "./configure --help=recursive" from the
> top-level, but that's not particularly convenient, it just dumps all
> the helps from all the configure scripts. It's good if you want to
> find / grep.
>
> Simon
>
Bernd.
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [PATCH v2] Enable GDB build with in-tree GMP and MPFR
2020-12-15 14:39 ` Simon Marchi
2020-12-15 16:24 ` Bernd Edlinger
@ 2020-12-16 7:33 ` Joel Brobecker
2020-12-16 18:16 ` Bernd Edlinger
1 sibling, 1 reply; 140+ messages in thread
From: Joel Brobecker @ 2020-12-16 7:33 UTC (permalink / raw)
To: Simon Marchi
Cc: Simon Marchi, Tom Tromey, Bernd Edlinger, Pedro Alves,
Eli Zaretskii, Andrew Burgess, gdb-patches
Hi Simon,
> > Here's a radical question: Do we really need to stay in sync with GCC,
> > at this point? What are the benefits and requirements of doing so?
> > Because GCC doesn't coordinate with us when they make changes to
> > the toplevel configury, we're only going to get into these problems
> > more.
>
> Indeed, it's a bit annoying that the burden of syncing is only on one
> side.
>
> What are the original reasons for staying in sync with gcc?
I don't know. It was like that when I first joined the project
20 years ago. I assumed it was convenient in the CVS days to
have everything under the same "roof", especially for those
who want to rebuild the works, knowing that CVS allowed partial
checkouts for those who diddn't.
> Instead of manually syncing files, I know Pedro already mentioned the
> idea of having a single repo with binutils + gcc + gdb, a bit like
> LLVM have moved to a big mono repo. Especially with gcc being a C++
> program as well, we want to share more. So desyncing from gcc would
> make such a move more difficult. But it's just an idea at this point,
> so maybe it's not that important.
It'd be interesting in knowing more about what it is that we would
be sharing. GCC is absolutely huge (4.5GB), and GDB isn't bad either
(1.2GB). Both GCC and GDB move very fast, so reuniting them would be
causing a large burden both ways for everyone. If we do, I feel
it has to be for strong reasons.
> Otherwise, just for convenience reasons, it would be nice to think more
> of gcc + binutils + gdb (an maybe others) as a single toolchain, and
> having consistency and no suprises in how you build them is a good thing
> for those build and integrate them.
It would be nice, but is that a sufficiently strong reason to break
with the past?
> > In fact, how much does the toplevel configure really need to do?
> > Intuitively, it doesn't really need to do very much, if we ignore
> > all the stuff that's GCC-specific.
>
> I know next to nothing about the top-level configure, because I never
> needed to dig into it.
>
> > A more relevant conundrum, for me, might be to look at keeping
> > binutils and GDB in sync in terms of the options being used.
> >
> > And then we have the question of how to provide users who want to
> > configure parts or all of binutils-gdb what options they can use,
> > and what they do. I don't know how easy we can do that via the
> > toplevel configure's --help. One interesting question is: Would
> > doing so help us avoid inconsistencies with binutils?
>
> I'm not sure I understand. Do you mean, how do users get to learn about
> the configure switches of all projects?
>
> All I know is that you can do "./configure --help=recursive" from the
> top-level, but that's not particularly convenient, it just dumps all
> the helps from all the configure scripts. It's good if you want to
> find / grep.
I didn't know that! This answers my question.
To recap where I am on this discussion: First, I need to be honest
and upfront in saying that I can't seem to be able to summon the energy
to motivate myself towards discussing reunification or even just making
GCC and binutils-gdb more consistent in the naming of the configure
options.
In fact, pending more info, I would still prefer we break the minimal
tie we have left in terms of synchronization with GCC, and use that
to help ourselves simplify and clarify, without breaking the existing
option.
In the meantime, if the group decides after discussion that the name
of the configure options in GDB for GMP are wrong, and must be changed
to follow GCC's lead, then so be it, I will change it. It'll be a bit
of a heartbreaker for me because:
- It breaks consistency with the way we have been handling dependencies
in GDB;
- We won't be able to use this nice macro to implement those options,
and will end up hand-writing them the same way toplevel configure
does (it seems like a lot of code, although I would hope I can
do this better and shorter).
Note that no one has complained about MPFR in the years we've had it...
--
Joel
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [PATCH v2] Enable GDB build with in-tree GMP and MPFR
2020-12-16 7:33 ` Joel Brobecker
@ 2020-12-16 18:16 ` Bernd Edlinger
2020-12-25 12:05 ` Bernd Edlinger
0 siblings, 1 reply; 140+ messages in thread
From: Bernd Edlinger @ 2020-12-16 18:16 UTC (permalink / raw)
To: Joel Brobecker, Simon Marchi
Cc: Simon Marchi, Tom Tromey, Pedro Alves, Eli Zaretskii,
Andrew Burgess, gdb-patches
[-- Attachment #1: Type: text/plain, Size: 5450 bytes --]
On 12/16/20 8:33 AM, Joel Brobecker wrote:
> Hi Simon,
>
>>> Here's a radical question: Do we really need to stay in sync with GCC,
>>> at this point? What are the benefits and requirements of doing so?
>>> Because GCC doesn't coordinate with us when they make changes to
>>> the toplevel configury, we're only going to get into these problems
>>> more.
>>
>> Indeed, it's a bit annoying that the burden of syncing is only on one
>> side.
>>
>> What are the original reasons for staying in sync with gcc?
>
> I don't know. It was like that when I first joined the project
> 20 years ago. I assumed it was convenient in the CVS days to
> have everything under the same "roof", especially for those
> who want to rebuild the works, knowing that CVS allowed partial
> checkouts for those who diddn't.
>
>> Instead of manually syncing files, I know Pedro already mentioned the
>> idea of having a single repo with binutils + gcc + gdb, a bit like
>> LLVM have moved to a big mono repo. Especially with gcc being a C++
>> program as well, we want to share more. So desyncing from gcc would
>> make such a move more difficult. But it's just an idea at this point,
>> so maybe it's not that important.
>
> It'd be interesting in knowing more about what it is that we would
> be sharing. GCC is absolutely huge (4.5GB), and GDB isn't bad either
> (1.2GB). Both GCC and GDB move very fast, so reuniting them would be
> causing a large burden both ways for everyone. If we do, I feel
> it has to be for strong reasons.
>
>> Otherwise, just for convenience reasons, it would be nice to think more
>> of gcc + binutils + gdb (an maybe others) as a single toolchain, and
>> having consistency and no suprises in how you build them is a good thing
>> for those build and integrate them.
>
> It would be nice, but is that a sufficiently strong reason to break
> with the past?
>
>>> In fact, how much does the toplevel configure really need to do?
>>> Intuitively, it doesn't really need to do very much, if we ignore
>>> all the stuff that's GCC-specific.
>>
>> I know next to nothing about the top-level configure, because I never
>> needed to dig into it.
>>
>>> A more relevant conundrum, for me, might be to look at keeping
>>> binutils and GDB in sync in terms of the options being used.
>>>
>>> And then we have the question of how to provide users who want to
>>> configure parts or all of binutils-gdb what options they can use,
>>> and what they do. I don't know how easy we can do that via the
>>> toplevel configure's --help. One interesting question is: Would
>>> doing so help us avoid inconsistencies with binutils?
>>
>> I'm not sure I understand. Do you mean, how do users get to learn about
>> the configure switches of all projects?
>>
>> All I know is that you can do "./configure --help=recursive" from the
>> top-level, but that's not particularly convenient, it just dumps all
>> the helps from all the configure scripts. It's good if you want to
>> find / grep.
>
> I didn't know that! This answers my question.
>
> To recap where I am on this discussion: First, I need to be honest
> and upfront in saying that I can't seem to be able to summon the energy
> to motivate myself towards discussing reunification or even just making
> GCC and binutils-gdb more consistent in the naming of the configure
> options.
>
> In fact, pending more info, I would still prefer we break the minimal
> tie we have left in terms of synchronization with GCC, and use that
> to help ourselves simplify and clarify, without breaking the existing
> option.
>
> In the meantime, if the group decides after discussion that the name
> of the configure options in GDB for GMP are wrong, and must be changed
> to follow GCC's lead, then so be it, I will change it. It'll be a bit
> of a heartbreaker for me because:
> - It breaks consistency with the way we have been handling dependencies
> in GDB;
> - We won't be able to use this nice macro to implement those options,
> and will end up hand-writing them the same way toplevel configure
> does (it seems like a lot of code, although I would hope I can
> do this better and shorter).
> Note that no one has complained about MPFR in the years we've had it...
>
That may be because this does not break anything if it is not available.
I for one did not notice anything before I knew that mpfr could be missing...
I looked at AC_LIB_HAVE_LINKFLAGS and I am surprised that it considers
to look for *.la/*.a/*.so at $prefix/lib directory instead of for instance
simply using pkg-config.
Using prefix/lib and prefix/include is also a bit unexpected, because that
is where I would normally expect the generated libraries from gdb to be
installed, instead of used from to build the gdb package.
And, it is also not clear if the user uses make install DESTDIR=X to install
everyting in X/prefix/..., for instance when prefix=/
So I think the configure flags for GMP can still be changed if we want, but the
AC_LIB_HAVE_LINKFLAGS-style configure flags for MPFR have already been there
for too long to simply remove them now. But I still think that it would
be nice to be more compatible with other configures, maybe at least
understand the --with-gmp-include --with-gmp-lib where there is no equivalent
for at the moment.
However I think I found a way to fix the in-tree build issue without adding
now configure options at all.
How would you like this new patch?
Thanks
Bernd.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Enable-GDB-build-with-in-tree-GMP-and-MPFR.patch --]
[-- Type: text/x-patch; name="0001-Enable-GDB-build-with-in-tree-GMP-and-MPFR.patch", Size: 15197 bytes --]
From f165e60dab1d677fe27915bb49bc897525d22a70 Mon Sep 17 00:00:00 2001
From: Bernd Edlinger <bernd.edlinger@hotmail.de>
Date: Sun, 15 Nov 2020 15:37:22 +0100
Subject: [PATCH] Enable GDB build with in-tree GMP and MPFR
With this patch GDB can be built with in-tree GMP and/or
MPFR. This works also for cross-builds.
All that is needed, is a sym-link in the source tree,
like this:
gmp -> ../gmp-6.1.0
mpfr -> ../mpfr-3.1.4
2020-12-10 Bernd Edlinger <bernd.edlinger@hotmail.de>
* Makefile.def: Prepare for GDB build with intree GMP.
* Makefile.in: Regenerate.
gdb:
2020-12-10 Bernd Edlinger <bernd.edlinger@hotmail.de>
* configure.ac: Detect in-tree GMP and MPFR.
* configure: Regenerate.
* README: Mention ./contrib/download_prerequisites.
contrib:
2020-12-10 Bernd Edlinger <bernd.edlinger@hotmail.de>
* download_prerequisites: New helper script.
* prerequisites.md5: checksums.
* prerequisites.sha512: checksums.
---
Makefile.def | 2 +
Makefile.in | 2 +
contrib/download_prerequisites | 263 +++++++++++++++++++++++++++++++++++++++++
contrib/prerequisites.md5 | 2 +
contrib/prerequisites.sha512 | 2 +
gdb/README | 12 ++
gdb/configure | 20 +++-
gdb/configure.ac | 20 +++-
8 files changed, 315 insertions(+), 8 deletions(-)
create mode 100755 contrib/download_prerequisites
create mode 100644 contrib/prerequisites.md5
create mode 100644 contrib/prerequisites.sha512
diff --git a/Makefile.def b/Makefile.def
index 089e70a..b6872c9 100644
--- a/Makefile.def
+++ b/Makefile.def
@@ -391,6 +391,8 @@ dependencies = { module=all-intl; on=all-libiconv; };
// Host modules specific to gdb.
dependencies = { module=configure-gdb; on=all-intl; };
+dependencies = { module=configure-gdb; on=all-gmp; };
+dependencies = { module=configure-gdb; on=all-mpfr; };
dependencies = { module=configure-gdb; on=configure-sim; };
dependencies = { module=configure-gdb; on=all-bfd; };
dependencies = { module=configure-gdb; on=all-gnulib; };
diff --git a/Makefile.in b/Makefile.in
index fe34132..ead9430 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -52449,6 +52449,8 @@ configure-libcc1: maybe-configure-gcc
all-libcc1: maybe-all-gcc
all-utils: maybe-all-libiberty
configure-gdb: maybe-all-intl
+configure-gdb: maybe-all-gmp
+configure-gdb: maybe-all-mpfr
configure-gdb: maybe-all-bfd
configure-gdb: maybe-all-libiconv
all-gdb: maybe-all-libiberty
diff --git a/contrib/download_prerequisites b/contrib/download_prerequisites
new file mode 100755
index 0000000..0d04030
--- /dev/null
+++ b/contrib/download_prerequisites
@@ -0,0 +1,263 @@
+#! /bin/sh
+#! -*- coding:utf-8; mode:shell-script; -*-
+
+# Download some prerequisites needed by GDB.
+# Run this from the top level of the GDB source tree and the GDB build will do
+# the right thing. Run it with the `--help` option for more information.
+#
+# (C) 2010-2020 Free Software Foundation
+#
+# 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/.
+
+program='download_prerequisites'
+version='(unversioned)'
+
+# MAINTAINERS: If you update the package versions below, please
+# remember to also update the files `contrib/prerequisites.sha512` and
+# `contrib/prerequisites.md5` with the new checksums.
+
+gmp='gmp-6.1.0.tar.bz2'
+mpfr='mpfr-3.1.4.tar.bz2'
+
+base_url='http://gcc.gnu.org/pub/gcc/infrastructure/'
+
+echo_archives() {
+ echo "${gmp}"
+ echo "${mpfr}"
+}
+
+verify=1
+force=0
+OS=$(uname)
+
+case $OS in
+ "Darwin"|"FreeBSD"|"DragonFly"|"AIX")
+ chksum='shasum -a 512 --check'
+ ;;
+ "OpenBSD")
+ chksum='sha512 -c'
+ ;;
+ *)
+ chksum='sha512sum -c'
+ ;;
+esac
+
+if type wget > /dev/null ; then
+ fetch='wget'
+else
+ fetch='curl -LO'
+fi
+chksum_extension='sha512'
+directory='.'
+
+helptext="usage: ${program} [OPTION...]
+
+Downloads some prerequisites needed by GDB. Run this from the top level of the
+GDB source tree and the GDB build will do the right thing.
+
+The following options are available:
+
+ --directory=DIR download and unpack packages into DIR instead of '.'
+ --force download again overwriting existing packages
+ --no-force do not download existing packages again (default)
+ --verify verify package integrity after download (default)
+ --no-verify don't verify package integrity
+ --sha512 use SHA512 checksum to verify package integrity (default)
+ --md5 use MD5 checksum to verify package integrity
+ --help show this text and exit
+ --version show version information and exit
+"
+
+versiontext="${program} ${version}
+Copyright (C) 2020 Free Software Foundation, Inc.
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+die() {
+ echo "error: $@" >&2
+ exit 1
+}
+
+for arg in "$@"
+do
+ case "${arg}" in
+ --help)
+ echo "${helptext}"
+ exit
+ ;;
+ --version)
+ echo "${versiontext}"
+ exit
+ ;;
+ esac
+done
+unset arg
+
+# Emulate Linux's 'md5 --check' on macOS
+md5_check() {
+ # Store the standard input: a line from contrib/prerequisites.md5:
+ md5_checksum_line=$(cat -)
+ # Grab the text before the first space
+ md5_checksum_expected="${md5_checksum_line%% *}"
+ # Grab the text after the first space
+ file_to_check="${md5_checksum_line##* }"
+ # Calculate the md5 checksum for the downloaded file
+ md5_checksum_output=$(md5 -r "${file_to_check}")
+ # Grab the text before the first space
+ md5_checksum_detected="${md5_checksum_output%% *}"
+ [ "${md5_checksum_expected}" == "${md5_checksum_detected}" ] \
+ || die "Cannot verify integrity of possibly corrupted file ${file_to_check}"
+ echo "${file_to_check}: OK"
+}
+
+
+argnext=
+for arg in "$@"
+do
+ if [ "x${argnext}" = x ]
+ then
+ case "${arg}" in
+ --directory)
+ argnext='directory'
+ ;;
+ --directory=*)
+ directory="${arg#--directory=}"
+ ;;
+ --force)
+ force=1
+ ;;
+ --no-force)
+ force=0
+ ;;
+ --verify)
+ verify=1
+ ;;
+ --no-verify)
+ verify=0
+ ;;
+ --sha512)
+ case $OS in
+ "Darwin")
+ chksum='shasum -a 512 --check'
+ ;;
+ *)
+ chksum='sha512sum --check'
+ ;;
+ esac
+ chksum_extension='sha512'
+ verify=1
+ ;;
+ --md5)
+ case $OS in
+ "Darwin")
+ chksum='md5_check'
+ ;;
+ *)
+ chksum='md5 --check'
+ ;;
+ esac
+ chksum_extension='md5'
+ verify=1
+ ;;
+ -*)
+ die "unknown option: ${arg}"
+ ;;
+ *)
+ die "too many arguments"
+ ;;
+ esac
+ else
+ case "${arg}" in
+ -*)
+ die "Missing argument for option --${argnext}"
+ ;;
+ esac
+ case "${argnext}" in
+ directory)
+ directory="${arg}"
+ ;;
+ *)
+ die "The impossible has happened"
+ ;;
+ esac
+ argnext=
+ fi
+done
+[ "x${argnext}" = x ] || die "Missing argument for option --${argnext}"
+unset arg argnext
+
+[ -e ./gdb/version.in ] \
+ || die "You must run this script in the top-level GDB source directory"
+
+[ -d "${directory}" ] \
+ || die "No such directory: ${directory}"
+
+for ar in $(echo_archives)
+do
+ if [ ${force} -gt 0 ]; then rm -f "${directory}/${ar}"; fi
+ [ -e "${directory}/${ar}" ] \
+ || ( cd "${directory}" && ${fetch} --no-verbose "${base_url}${ar}" ) \
+ || die "Cannot download ${ar} from ${base_url}"
+done
+unset ar
+
+if [ ${verify} -gt 0 ]
+then
+ chksumfile="contrib/prerequisites.${chksum_extension}"
+ [ -r "${chksumfile}" ] || die "No checksums available"
+ for ar in $(echo_archives)
+ do
+ grep "${ar}" "${chksumfile}" \
+ | ( cd "${directory}" && ${chksum} ) \
+ || die "Cannot verify integrity of possibly corrupted file ${ar}"
+ done
+ unset chksumfile
+fi
+unset ar
+
+for ar in $(echo_archives)
+do
+ package="${ar%.tar*}"
+ if [ ${force} -gt 0 ]; then rm -rf "${directory}/${package}"; fi
+ case $ar in
+ *.gz)
+ uncompress='gzip -d'
+ ;;
+ *.bz2)
+ uncompress='bzip2 -d'
+ ;;
+ *)
+ uncompress='cat'
+ ;;
+ esac
+ [ -e "${directory}/${package}" ] \
+ || ( cd "${directory}" && $uncompress <"${ar}" | tar -xf - ) \
+ || die "Cannot extract package from ${ar}"
+ unset package
+done
+unset ar
+
+for ar in $(echo_archives)
+do
+ target="${directory}/${ar%.tar*}/"
+ linkname="${ar%-*}"
+ if [ ${force} -gt 0 ]; then rm -f "${linkname}"; fi
+ [ -e "${linkname}" ] \
+ || ln -s "${target}" "${linkname}" \
+ || die "Cannot create symbolic link ${linkname} --> ${target}"
+ unset target linkname
+done
+unset ar
+
+echo "All prerequisites downloaded successfully."
diff --git a/contrib/prerequisites.md5 b/contrib/prerequisites.md5
new file mode 100644
index 0000000..cf7be0d
--- /dev/null
+++ b/contrib/prerequisites.md5
@@ -0,0 +1,2 @@
+86ee6e54ebfc4a90b643a65e402c4048 gmp-6.1.0.tar.bz2
+b8a2f6b0e68bef46e53da2ac439e1cf4 mpfr-3.1.4.tar.bz2
diff --git a/contrib/prerequisites.sha512 b/contrib/prerequisites.sha512
new file mode 100644
index 0000000..8f05aff
--- /dev/null
+++ b/contrib/prerequisites.sha512
@@ -0,0 +1,2 @@
+3c82aeab9c1596d4da8afac2eec38e429e84f3211e1a572cf8fd2b546493c44c039b922a1133eaaa48bd7f3e11dbe795a384e21ed95cbe3ecc58d7ac02246117 gmp-6.1.0.tar.bz2
+51066066ff2c12ed2198605ecf68846b0c96b548adafa5b80e0c786d0df488411a5e8973358fce7192dc977ad4e68414cf14500e3c39746de62465eb145bb819 mpfr-3.1.4.tar.bz2
diff --git a/gdb/README b/gdb/README
index e65c5ea..2b9c382 100644
--- a/gdb/README
+++ b/gdb/README
@@ -488,6 +488,12 @@ more obscure GDB `configure' options are not listed here.
Build GDB using the GMP library installed at the directory DIR.
If your host does not have GMP installed, you can get the latest
version at `https://gmplib.org/'.
+ You can also build GMP in-tree when you use the script
+ ./contrib/download_prerequisites.
+ This must be done before configure. No --with-gmp options must
+ be used when invoking configure in this case.
+ Note however, that this does only work with a separate build
+ directory.
`--with-mpfr'
Build GDB with GNU MPFR, a library for multiple-precision
@@ -499,6 +505,12 @@ more obscure GDB `configure' options are not listed here.
available, GDB will fall back to using host floating-point
arithmetic. If your host does not have GNU MPFR installed, you
can get the latest version from `https://www.mpfr.org/'.
+ You can also build MPFR in-tree when you use the script
+ ./contrib/download_prerequisites.
+ This must be done before configure. No --with-mpfr options must
+ be used when invoking configure in this case.
+ Note however, that this does only work with a separate build
+ directory.
`--with-python[=PYTHON]'
Build GDB with Python scripting support. (Done by default if
diff --git a/gdb/configure b/gdb/configure
index 24e6fbc..2bf8014 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -9991,6 +9991,13 @@ done
fi
# Verify that we have a usable GMP library.
+if test -d "../gmp"; then
+ CPPFLAGS="$CPPFLAGS -I../gmp"
+ LIBGMP="../gmp/.libs/libgmp.a"
+
+$as_echo "#define HAVE_LIBGMP 1" >>confdefs.h
+
+else
@@ -10431,7 +10438,7 @@ int
main ()
{
mpz_t n;
- mpz_init (n);
+ mpz_init (n);
;
return 0;
}
@@ -10469,8 +10476,9 @@ $as_echo "$LIBGMP" >&6; }
-if test "$HAVE_LIBGMP" != yes; then
- as_fn_error $? "GMP is missing or unusable" "$LINENO" 5
+ if test "$HAVE_LIBGMP" != yes; then
+ as_fn_error $? "GMP is missing or unusable" "$LINENO" 5
+ fi
fi
@@ -10490,6 +10498,12 @@ if test "${with_mpfr}" = no; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: MPFR support disabled; some features may be unavailable." >&5
$as_echo "$as_me: WARNING: MPFR support disabled; some features may be unavailable." >&2;}
HAVE_LIBMPFR=no
+elif test -d "../mpfr"; then
+ CPPFLAGS="$CPPFLAGS -I${srcdir}/../mpfr/src"
+ LIBMPFR="../mpfr/src/.libs/libmpfr.a"
+
+$as_echo "#define HAVE_LIBMPFR 1" >>confdefs.h
+
else
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 32f25d9..376643c 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -684,11 +684,17 @@ else
fi
# Verify that we have a usable GMP library.
-AC_LIB_HAVE_LINKFLAGS([gmp], [], [#include <gmp.h>],
- [mpz_t n;
- mpz_init (n);])
-if test "$HAVE_LIBGMP" != yes; then
- AC_MSG_ERROR([GMP is missing or unusable])
+if test -d "../gmp"; then
+ CPPFLAGS="$CPPFLAGS -I../gmp"
+ LIBGMP="../gmp/.libs/libgmp.a"
+ AC_DEFINE(HAVE_LIBGMP, 1, [Define if you have the GMP library.])
+else
+ AC_LIB_HAVE_LINKFLAGS([gmp], [], [#include <gmp.h>],
+ [mpz_t n;
+ mpz_init (n);])
+ if test "$HAVE_LIBGMP" != yes; then
+ AC_MSG_ERROR([GMP is missing or unusable])
+ fi
fi
AC_ARG_WITH(mpfr,
@@ -700,6 +706,10 @@ AC_MSG_RESULT([$with_mpfr])
if test "${with_mpfr}" = no; then
AC_MSG_WARN([MPFR support disabled; some features may be unavailable.])
HAVE_LIBMPFR=no
+elif test -d "../mpfr"; then
+ CPPFLAGS="$CPPFLAGS -I${srcdir}/../mpfr/src"
+ LIBMPFR="../mpfr/src/.libs/libmpfr.a"
+ AC_DEFINE(HAVE_LIBMPFR, 1, [Define if you have the MPFR library.])
else
AC_LIB_HAVE_LINKFLAGS([mpfr], [gmp], [#include <mpfr.h>],
[mpfr_exp_t exp; mpfr_t x;
--
1.9.1
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [PATCH v2] Enable GDB build with in-tree GMP and MPFR
2020-12-16 18:16 ` Bernd Edlinger
@ 2020-12-25 12:05 ` Bernd Edlinger
2020-12-27 22:01 ` Simon Marchi
0 siblings, 1 reply; 140+ messages in thread
From: Bernd Edlinger @ 2020-12-25 12:05 UTC (permalink / raw)
To: Joel Brobecker, Simon Marchi
Cc: Tom Tromey, Pedro Alves, Eli Zaretskii, Andrew Burgess, gdb-patches
[-- Attachment #1: Type: text/plain, Size: 679 bytes --]
Hi everybody,
I have now two possible ways to go forward with the configure options
for gmp and mpfr.
See the attached patches:
Variant 1: implements traditional configure options
--with-gmp-include=DIR, --with-gmp-lib=DIR, --with-gmp=DIR,
--with-mpfr-include=DIR, --with-mpfr-lib=DIR, --with-mpfr=DIR
but does additionally understand --with-libmpfr-prefix=DIR
and --with-mpfr=auto/yes/no.
Variant 2: (I already posted that one) keeps all configure options
as they are now, and just uses the presence of a ../gmp and ../mpfr
directory to override the gmp and mpfr configure flags.
I would be interested in what you think, and which variant you would
prefer.
Thanks
Bernd.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Enable-GDB-build-with-in-tree-GMP-and-MPFR-v1.patch --]
[-- Type: text/x-patch; name="0001-Enable-GDB-build-with-in-tree-GMP-and-MPFR-v1.patch", Size: 60440 bytes --]
From c4dfaa57bc2bfd34d4ea4f4de9148887b10150b6 Mon Sep 17 00:00:00 2001
From: Bernd Edlinger <bernd.edlinger@hotmail.de>
Date: Sun, 15 Nov 2020 15:37:22 +0100
Subject: [PATCH] Enable GDB build with in-tree GMP and MPFR
With this patch GDB can be built with in-tree GMP and/or
MPFR. This works also for cross-builds.
All that is needed, is a sym-link in the source tree,
like this:
gmp -> ../gmp-6.1.0
mpfr -> ../mpfr-3.1.4
2020-12-10 Bernd Edlinger <bernd.edlinger@hotmail.de>
* Makefile.def: Prepare for GDB build with intree GMP.
* Makefile.in: Regenerate.
gdb:
2020-12-10 Bernd Edlinger <bernd.edlinger@hotmail.de>
* configure.ac: Add --with-gmp=DIR, --with-gmp-include=DIR
and --with-gmp-lib=DIR
as well as --with-mpfr-include=DIR and --with-mpfr-lib=DIR
for compatibility with top level configure script.
* configure: Regenerate.
* README: Mention ./contrib/download_prerequisites.
contrib:
2020-12-10 Bernd Edlinger <bernd.edlinger@hotmail.de>
* download_prerequisites: New helper script.
* prerequisites.md5: checksums.
* prerequisites.sha512: checksums.
---
Makefile.def | 5 +-
Makefile.in | 4 +-
contrib/download_prerequisites | 263 ++++++++++
contrib/prerequisites.md5 | 2 +
contrib/prerequisites.sha512 | 2 +
gdb/README | 23 +-
gdb/configure | 1126 ++++++----------------------------------
gdb/configure.ac | 88 +++-
8 files changed, 522 insertions(+), 991 deletions(-)
create mode 100755 contrib/download_prerequisites
create mode 100644 contrib/prerequisites.md5
create mode 100644 contrib/prerequisites.sha512
diff --git a/Makefile.def b/Makefile.def
index 089e70a..1b99b42 100644
--- a/Makefile.def
+++ b/Makefile.def
@@ -115,7 +115,8 @@ host_modules= { module= zlib; no_install=true; no_check=true;
host_modules= { module= gnulib; };
host_modules= { module= gdbsupport; };
host_modules= { module= gdbserver; };
-host_modules= { module= gdb; };
+host_modules= { module= gdb;
+ extra_configure_flags='@extra_mpfr_configure_flags@ @extra_mpc_mpfr_configure_flags@';};
host_modules= { module= expect; };
host_modules= { module= guile; };
host_modules= { module= tk; };
@@ -391,6 +392,8 @@ dependencies = { module=all-intl; on=all-libiconv; };
// Host modules specific to gdb.
dependencies = { module=configure-gdb; on=all-intl; };
+dependencies = { module=configure-gdb; on=all-gmp; };
+dependencies = { module=configure-gdb; on=all-mpfr; };
dependencies = { module=configure-gdb; on=configure-sim; };
dependencies = { module=configure-gdb; on=all-bfd; };
dependencies = { module=configure-gdb; on=all-gnulib; };
diff --git a/Makefile.in b/Makefile.in
index fe34132..738fd32 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -29491,7 +29491,7 @@ configure-gdb:
$$s/$$module_srcdir/configure \
--srcdir=$${topdir}/$$module_srcdir \
$(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \
- --target=${target_alias} \
+ --target=${target_alias} @extra_mpfr_configure_flags@ @extra_mpc_mpfr_configure_flags@ \
|| exit 1
@endif gdb
@@ -52449,6 +52449,8 @@ configure-libcc1: maybe-configure-gcc
all-libcc1: maybe-all-gcc
all-utils: maybe-all-libiberty
configure-gdb: maybe-all-intl
+configure-gdb: maybe-all-gmp
+configure-gdb: maybe-all-mpfr
configure-gdb: maybe-all-bfd
configure-gdb: maybe-all-libiconv
all-gdb: maybe-all-libiberty
diff --git a/contrib/download_prerequisites b/contrib/download_prerequisites
new file mode 100755
index 0000000..0d04030
--- /dev/null
+++ b/contrib/download_prerequisites
@@ -0,0 +1,263 @@
+#! /bin/sh
+#! -*- coding:utf-8; mode:shell-script; -*-
+
+# Download some prerequisites needed by GDB.
+# Run this from the top level of the GDB source tree and the GDB build will do
+# the right thing. Run it with the `--help` option for more information.
+#
+# (C) 2010-2020 Free Software Foundation
+#
+# 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/.
+
+program='download_prerequisites'
+version='(unversioned)'
+
+# MAINTAINERS: If you update the package versions below, please
+# remember to also update the files `contrib/prerequisites.sha512` and
+# `contrib/prerequisites.md5` with the new checksums.
+
+gmp='gmp-6.1.0.tar.bz2'
+mpfr='mpfr-3.1.4.tar.bz2'
+
+base_url='http://gcc.gnu.org/pub/gcc/infrastructure/'
+
+echo_archives() {
+ echo "${gmp}"
+ echo "${mpfr}"
+}
+
+verify=1
+force=0
+OS=$(uname)
+
+case $OS in
+ "Darwin"|"FreeBSD"|"DragonFly"|"AIX")
+ chksum='shasum -a 512 --check'
+ ;;
+ "OpenBSD")
+ chksum='sha512 -c'
+ ;;
+ *)
+ chksum='sha512sum -c'
+ ;;
+esac
+
+if type wget > /dev/null ; then
+ fetch='wget'
+else
+ fetch='curl -LO'
+fi
+chksum_extension='sha512'
+directory='.'
+
+helptext="usage: ${program} [OPTION...]
+
+Downloads some prerequisites needed by GDB. Run this from the top level of the
+GDB source tree and the GDB build will do the right thing.
+
+The following options are available:
+
+ --directory=DIR download and unpack packages into DIR instead of '.'
+ --force download again overwriting existing packages
+ --no-force do not download existing packages again (default)
+ --verify verify package integrity after download (default)
+ --no-verify don't verify package integrity
+ --sha512 use SHA512 checksum to verify package integrity (default)
+ --md5 use MD5 checksum to verify package integrity
+ --help show this text and exit
+ --version show version information and exit
+"
+
+versiontext="${program} ${version}
+Copyright (C) 2020 Free Software Foundation, Inc.
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+die() {
+ echo "error: $@" >&2
+ exit 1
+}
+
+for arg in "$@"
+do
+ case "${arg}" in
+ --help)
+ echo "${helptext}"
+ exit
+ ;;
+ --version)
+ echo "${versiontext}"
+ exit
+ ;;
+ esac
+done
+unset arg
+
+# Emulate Linux's 'md5 --check' on macOS
+md5_check() {
+ # Store the standard input: a line from contrib/prerequisites.md5:
+ md5_checksum_line=$(cat -)
+ # Grab the text before the first space
+ md5_checksum_expected="${md5_checksum_line%% *}"
+ # Grab the text after the first space
+ file_to_check="${md5_checksum_line##* }"
+ # Calculate the md5 checksum for the downloaded file
+ md5_checksum_output=$(md5 -r "${file_to_check}")
+ # Grab the text before the first space
+ md5_checksum_detected="${md5_checksum_output%% *}"
+ [ "${md5_checksum_expected}" == "${md5_checksum_detected}" ] \
+ || die "Cannot verify integrity of possibly corrupted file ${file_to_check}"
+ echo "${file_to_check}: OK"
+}
+
+
+argnext=
+for arg in "$@"
+do
+ if [ "x${argnext}" = x ]
+ then
+ case "${arg}" in
+ --directory)
+ argnext='directory'
+ ;;
+ --directory=*)
+ directory="${arg#--directory=}"
+ ;;
+ --force)
+ force=1
+ ;;
+ --no-force)
+ force=0
+ ;;
+ --verify)
+ verify=1
+ ;;
+ --no-verify)
+ verify=0
+ ;;
+ --sha512)
+ case $OS in
+ "Darwin")
+ chksum='shasum -a 512 --check'
+ ;;
+ *)
+ chksum='sha512sum --check'
+ ;;
+ esac
+ chksum_extension='sha512'
+ verify=1
+ ;;
+ --md5)
+ case $OS in
+ "Darwin")
+ chksum='md5_check'
+ ;;
+ *)
+ chksum='md5 --check'
+ ;;
+ esac
+ chksum_extension='md5'
+ verify=1
+ ;;
+ -*)
+ die "unknown option: ${arg}"
+ ;;
+ *)
+ die "too many arguments"
+ ;;
+ esac
+ else
+ case "${arg}" in
+ -*)
+ die "Missing argument for option --${argnext}"
+ ;;
+ esac
+ case "${argnext}" in
+ directory)
+ directory="${arg}"
+ ;;
+ *)
+ die "The impossible has happened"
+ ;;
+ esac
+ argnext=
+ fi
+done
+[ "x${argnext}" = x ] || die "Missing argument for option --${argnext}"
+unset arg argnext
+
+[ -e ./gdb/version.in ] \
+ || die "You must run this script in the top-level GDB source directory"
+
+[ -d "${directory}" ] \
+ || die "No such directory: ${directory}"
+
+for ar in $(echo_archives)
+do
+ if [ ${force} -gt 0 ]; then rm -f "${directory}/${ar}"; fi
+ [ -e "${directory}/${ar}" ] \
+ || ( cd "${directory}" && ${fetch} --no-verbose "${base_url}${ar}" ) \
+ || die "Cannot download ${ar} from ${base_url}"
+done
+unset ar
+
+if [ ${verify} -gt 0 ]
+then
+ chksumfile="contrib/prerequisites.${chksum_extension}"
+ [ -r "${chksumfile}" ] || die "No checksums available"
+ for ar in $(echo_archives)
+ do
+ grep "${ar}" "${chksumfile}" \
+ | ( cd "${directory}" && ${chksum} ) \
+ || die "Cannot verify integrity of possibly corrupted file ${ar}"
+ done
+ unset chksumfile
+fi
+unset ar
+
+for ar in $(echo_archives)
+do
+ package="${ar%.tar*}"
+ if [ ${force} -gt 0 ]; then rm -rf "${directory}/${package}"; fi
+ case $ar in
+ *.gz)
+ uncompress='gzip -d'
+ ;;
+ *.bz2)
+ uncompress='bzip2 -d'
+ ;;
+ *)
+ uncompress='cat'
+ ;;
+ esac
+ [ -e "${directory}/${package}" ] \
+ || ( cd "${directory}" && $uncompress <"${ar}" | tar -xf - ) \
+ || die "Cannot extract package from ${ar}"
+ unset package
+done
+unset ar
+
+for ar in $(echo_archives)
+do
+ target="${directory}/${ar%.tar*}/"
+ linkname="${ar%-*}"
+ if [ ${force} -gt 0 ]; then rm -f "${linkname}"; fi
+ [ -e "${linkname}" ] \
+ || ln -s "${target}" "${linkname}" \
+ || die "Cannot create symbolic link ${linkname} --> ${target}"
+ unset target linkname
+done
+unset ar
+
+echo "All prerequisites downloaded successfully."
diff --git a/contrib/prerequisites.md5 b/contrib/prerequisites.md5
new file mode 100644
index 0000000..cf7be0d
--- /dev/null
+++ b/contrib/prerequisites.md5
@@ -0,0 +1,2 @@
+86ee6e54ebfc4a90b643a65e402c4048 gmp-6.1.0.tar.bz2
+b8a2f6b0e68bef46e53da2ac439e1cf4 mpfr-3.1.4.tar.bz2
diff --git a/contrib/prerequisites.sha512 b/contrib/prerequisites.sha512
new file mode 100644
index 0000000..8f05aff
--- /dev/null
+++ b/contrib/prerequisites.sha512
@@ -0,0 +1,2 @@
+3c82aeab9c1596d4da8afac2eec38e429e84f3211e1a572cf8fd2b546493c44c039b922a1133eaaa48bd7f3e11dbe795a384e21ed95cbe3ecc58d7ac02246117 gmp-6.1.0.tar.bz2
+51066066ff2c12ed2198605ecf68846b0c96b548adafa5b80e0c786d0df488411a5e8973358fce7192dc977ad4e68414cf14500e3c39746de62465eb145bb819 mpfr-3.1.4.tar.bz2
diff --git a/gdb/README b/gdb/README
index e65c5ea..2146d80 100644
--- a/gdb/README
+++ b/gdb/README
@@ -484,21 +484,32 @@ more obscure GDB `configure' options are not listed here.
not have liblzma installed, you can get the latest version from
`https://tukaani.org/xz/'.
-`--with-libgmp-prefix=DIR'
+`--with-gmp=DIR'
Build GDB using the GMP library installed at the directory DIR.
If your host does not have GMP installed, you can get the latest
version at `https://gmplib.org/'.
-
-`--with-mpfr'
- Build GDB with GNU MPFR, a library for multiple-precision
- floating-point computation with correct rounding. (Done by
- default if GNU MPFR is installed and found at configure time.)
+ You can also build GMP in-tree when you use the script
+ ./contrib/download_prerequisites.
+ This must be done before configure. No --with-gmp options must
+ be used when invoking configure in this case.
+ Note however, that this does only work with a separate build
+ directory.
+
+`--with-mpfr=DIR (or auto/yes/no)'
+ Build GDB with GNU MPFR installed at the directory DIR.
+ For backward compatibility also DIR=auto/yes/no may be used.
This library is used to emulate target floating-point arithmetic
during expression evaluation when the target uses different
floating-point formats than the host. If GNU MPFR is not
available, GDB will fall back to using host floating-point
arithmetic. If your host does not have GNU MPFR installed, you
can get the latest version from `https://www.mpfr.org/'.
+ You can also build MPFR in-tree when you use the script
+ ./contrib/download_prerequisites.
+ This must be done before configure. No --with-mpfr options must
+ be used when invoking configure in this case.
+ Note however, that this does only work with a separate build
+ directory.
`--with-python[=PYTHON]'
Build GDB with Python scripting support. (Done by default if
diff --git a/gdb/configure b/gdb/configure
index 51b4d19..92e4b4d 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -729,12 +729,8 @@ PYTHON_LIBS
PYTHON_CPPFLAGS
PYTHON_CFLAGS
python_prog_path
-LTLIBMPFR
LIBMPFR
-HAVE_LIBMPFR
-LTLIBGMP
LIBGMP
-HAVE_LIBGMP
LTLIBEXPAT
LIBEXPAT
HAVE_LIBEXPAT
@@ -899,11 +895,13 @@ with_jit_reader_dir
with_expat
with_libexpat_prefix
with_libexpat_type
-with_libgmp_prefix
-with_libgmp_type
-with_mpfr
+with_gmp_include
+with_gmp_lib
+with_gmp
with_libmpfr_prefix
-with_libmpfr_type
+with_mpfr_include
+with_mpfr_lib
+with_mpfr
with_python
with_python_libdir
with_guile
@@ -1644,13 +1642,14 @@ Optional Packages:
--with-libexpat-prefix[=DIR] search for libexpat in DIR/include and DIR/lib
--without-libexpat-prefix don't search for libexpat in includedir and libdir
--with-libexpat-type=TYPE type of library to search for (auto/static/shared)
- --with-libgmp-prefix[=DIR] search for libgmp in DIR/include and DIR/lib
- --without-libgmp-prefix don't search for libgmp in includedir and libdir
- --with-libgmp-type=TYPE type of library to search for (auto/static/shared)
- --with-mpfr include MPFR support (auto/yes/no)
- --with-libmpfr-prefix[=DIR] search for libmpfr in DIR/include and DIR/lib
- --without-libmpfr-prefix don't search for libmpfr in includedir and libdir
- --with-libmpfr-type=TYPE type of library to search for (auto/static/shared)
+ --with-gmp-include=DIR GMP include directory
+ --with-gmp-lib=DIR GMP lib directory
+ --with-gmp=DIR GMP install directory
+ --with-libmpfr-prefix=DIR
+ this option has been DEPRECATED
+ --with-mpfr-include=DIR MPFR include directory
+ --with-mpfr-lib=DIR MPFR lib directory
+ --with-mpfr=DIR MFPR install directory (or auto/yes/no)
--with-python[=PYTHON] include python support
(auto/yes/no/<python-program>)
--with-python-libdir[=DIR]
@@ -9990,994 +9989,175 @@ done
fi
fi
-# Verify that we have a usable GMP library.
+# Check whether --with-gmp_include was given.
+if test "${with_gmp_include+set}" = set; then :
+ withval=$with_gmp_include; CPPFLAGS="$CPPFLAGS -I$withval"
+fi
+# Check whether --with-gmp_lib was given.
+if test "${with_gmp_lib+set}" = set; then :
+ withval=$with_gmp_lib; LIBGMP="-L$withval"
+fi
+# Check whether --with-gmp was given.
+if test "${with_gmp+set}" = set; then :
+ withval=$with_gmp;
+ if test -z "$with_gmp_lib" && test -z "$with_gmp_include" ; then
+ CPPFLAGS="$CPPFLAGS -I$withval/include"
+ LIBGMP="-L$withval/lib"
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "Do not use --with-gmp and --with-gmp-include/--with-gmp-lib options simultaneously.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+fi
- use_additional=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GMP" >&5
+$as_echo_n "checking for GMP... " >&6; }
+# Verify that we have a usable GMP library.
+save_LIBS=$LIBS
+LIBS="$LIBS $LIBGMP -lgmp"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <gmp.h>
+int
+main ()
+{
+mpz_t n;
+ mpz_init (n);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ HAVE_LIBGMP=yes
+else
+ HAVE_LIBGMP=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$save_LIBS
+if test "$HAVE_LIBGMP" != yes; then
+ as_fn_error $? "GMP is missing or unusable" "$LINENO" 5
+fi
+LIBGMP="$LIBGMP -lgmp"
- acl_save_prefix="$prefix"
- prefix="$acl_final_prefix"
- acl_save_exec_prefix="$exec_prefix"
- exec_prefix="$acl_final_exec_prefix"
- eval additional_includedir=\"$includedir\"
- eval additional_libdir=\"$libdir\"
+$as_echo "#define HAVE_LIBGMP 1" >>confdefs.h
- exec_prefix="$acl_save_exec_prefix"
- prefix="$acl_save_prefix"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_LIBGMP" >&5
+$as_echo "$HAVE_LIBGMP" >&6; }
-# Check whether --with-libgmp-prefix was given.
-if test "${with_libgmp_prefix+set}" = set; then :
- withval=$with_libgmp_prefix;
- if test "X$withval" = "Xno"; then
- use_additional=no
- else
- if test "X$withval" = "X"; then
+# Check whether --with-libmpfr_prefix was given.
+if test "${with_libmpfr_prefix+set}" = set; then :
+ withval=$with_libmpfr_prefix;
+ if test -z "$with_mpfr" ; then
+ with_mpfr="auto"
+ fi
+ if test x"$with_mpfr" != xauto && test x"$with_mpfr" != xyes && test x"$with_mpfr" != xno ; then
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "Do not use --with-mpfr=DIR and --with-libmpfr-prefix=DIR options simultaneously.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
- acl_save_prefix="$prefix"
- prefix="$acl_final_prefix"
- acl_save_exec_prefix="$exec_prefix"
- exec_prefix="$acl_final_exec_prefix"
+fi
- eval additional_includedir=\"$includedir\"
- eval additional_libdir=\"$libdir\"
+save_CPPFLAGS=$CPPFLAGS
- exec_prefix="$acl_save_exec_prefix"
- prefix="$acl_save_prefix"
+# Check whether --with-mpfr_include was given.
+if test "${with_mpfr_include+set}" = set; then :
+ withval=$with_mpfr_include; CPPFLAGS="$CPPFLAGS -I$withval"
+fi
- else
- additional_includedir="$withval/include"
- additional_libdir="$withval/lib"
+
+# Check whether --with-mpfr_lib was given.
+if test "${with_mpfr_lib+set}" = set; then :
+ withval=$with_mpfr_lib; LIBMPFR="-L$withval"
+fi
+
+
+# Check whether --with-mpfr was given.
+if test "${with_mpfr+set}" = set; then :
+ withval=$with_mpfr;
+ if test -n "$with_libmpfr_prefix" ; then
+ withval=$with_libmpfr_prefix
+ fi
+ if test -z "$with_mpfr_lib" && test -z "$with_mpfr_include" ; then
+ if test x"$withval" != xauto && test x"$withval" != xyes && test x"$withval" != xno ; then
+ CPPFLAGS="$CPPFLAGS -I$withval/include"
+ LIBMPFR="-L$withval/lib"
+ if test -z "$with_libmpfr_prefix" ; then
+ with_mpfr=yes
fi
fi
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "Do not use --with-mpfr and --with-mpfr-include/--with-mpfr-lib options simultaneously.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
fi
-# Check whether --with-libgmp-type was given.
-if test "${with_libgmp_type+set}" = set; then :
- withval=$with_libgmp_type; with_libgmp_type=$withval
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use MPFR" >&5
+$as_echo_n "checking whether to use MPFR... " >&6; }
+if test "${with_mpfr}" = no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: MPFR support disabled; some features may be unavailable." >&5
+$as_echo "$as_me: WARNING: MPFR support disabled; some features may be unavailable." >&2;}
+ HAVE_LIBMPFR=no
+ LIBMPFR=
+ CPPFLAGS=$save_CPPFLAGS
+else
+ save_LIBS=$LIBS
+ LIBS="$LIBS $LIBMPFR -lmpfr $LIBGMP"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <mpfr.h>
+int
+main ()
+{
+mpfr_exp_t exp; mpfr_t x;
+ mpfr_frexp (&exp, x, x, MPFR_RNDN);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ HAVE_LIBMPFR=yes
else
- with_libgmp_type=auto
+ HAVE_LIBMPFR=no
fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LIBS=$save_LIBS
+ if test "$HAVE_LIBMPFR" != yes; then
+ if test "$with_mpfr" = yes; then
+ as_fn_error $? "MPFR is missing or unusable" "$LINENO" 5
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: MPFR is missing or unusable; some features may be unavailable." >&5
+$as_echo "$as_me: WARNING: MPFR is missing or unusable; some features may be unavailable." >&2;}
+ fi
+ LIBMPFR=
+ CPPFLAGS=$save_CPPFLAGS
+ else
+ LIBMPFR="$LIBMPFR -lmpfr"
- lib_type=`eval echo \$with_libgmp_type`
-
- LIBGMP=
- LTLIBGMP=
- INCGMP=
- rpathdirs=
- ltrpathdirs=
- names_already_handled=
- names_next_round='gmp '
- while test -n "$names_next_round"; do
- names_this_round="$names_next_round"
- names_next_round=
- for name in $names_this_round; do
- already_handled=
- for n in $names_already_handled; do
- if test "$n" = "$name"; then
- already_handled=yes
- break
- fi
- done
- if test -z "$already_handled"; then
- names_already_handled="$names_already_handled $name"
- uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'`
- eval value=\"\$HAVE_LIB$uppername\"
- if test -n "$value"; then
- if test "$value" = yes; then
- eval value=\"\$LIB$uppername\"
- test -z "$value" || LIBGMP="${LIBGMP}${LIBGMP:+ }$value"
- eval value=\"\$LTLIB$uppername\"
- test -z "$value" || LTLIBGMP="${LTLIBGMP}${LTLIBGMP:+ }$value"
- else
- :
- fi
- else
- found_dir=
- found_la=
- found_so=
- found_a=
- if test $use_additional = yes; then
- if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext" && test x$lib_type != xstatic; then
- found_dir="$additional_libdir"
- found_so="$additional_libdir/lib$name.$shlibext"
- if test -f "$additional_libdir/lib$name.la"; then
- found_la="$additional_libdir/lib$name.la"
- fi
- elif test x$lib_type != xshared; then
- if test -f "$additional_libdir/lib$name.$libext"; then
- found_dir="$additional_libdir"
- found_a="$additional_libdir/lib$name.$libext"
- if test -f "$additional_libdir/lib$name.la"; then
- found_la="$additional_libdir/lib$name.la"
- fi
- fi
- fi
- fi
- if test "X$found_dir" = "X"; then
- for x in $LDFLAGS $LTLIBGMP; do
-
- acl_save_prefix="$prefix"
- prefix="$acl_final_prefix"
- acl_save_exec_prefix="$exec_prefix"
- exec_prefix="$acl_final_exec_prefix"
- eval x=\"$x\"
- exec_prefix="$acl_save_exec_prefix"
- prefix="$acl_save_prefix"
-
- case "$x" in
- -L*)
- dir=`echo "X$x" | sed -e 's/^X-L//'`
- if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext" && test x$lib_type != xstatic; then
- found_dir="$dir"
- found_so="$dir/lib$name.$shlibext"
- if test -f "$dir/lib$name.la"; then
- found_la="$dir/lib$name.la"
- fi
- elif test x$lib_type != xshared; then
- if test -f "$dir/lib$name.$libext"; then
- found_dir="$dir"
- found_a="$dir/lib$name.$libext"
- if test -f "$dir/lib$name.la"; then
- found_la="$dir/lib$name.la"
- fi
- fi
- fi
- ;;
- esac
- if test "X$found_dir" != "X"; then
- break
- fi
- done
- fi
- if test "X$found_dir" != "X"; then
- LTLIBGMP="${LTLIBGMP}${LTLIBGMP:+ }-L$found_dir -l$name"
- if test "X$found_so" != "X"; then
- if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/lib"; then
- LIBGMP="${LIBGMP}${LIBGMP:+ }$found_so"
- else
- haveit=
- for x in $ltrpathdirs; do
- if test "X$x" = "X$found_dir"; then
- haveit=yes
- break
- fi
- done
- if test -z "$haveit"; then
- ltrpathdirs="$ltrpathdirs $found_dir"
- fi
- if test "$hardcode_direct" = yes; then
- LIBGMP="${LIBGMP}${LIBGMP:+ }$found_so"
- else
- if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then
- LIBGMP="${LIBGMP}${LIBGMP:+ }$found_so"
- haveit=
- for x in $rpathdirs; do
- if test "X$x" = "X$found_dir"; then
- haveit=yes
- break
- fi
- done
- if test -z "$haveit"; then
- rpathdirs="$rpathdirs $found_dir"
- fi
- else
- haveit=
- for x in $LDFLAGS $LIBGMP; do
- acl_save_prefix="$prefix"
- prefix="$acl_final_prefix"
- acl_save_exec_prefix="$exec_prefix"
- exec_prefix="$acl_final_exec_prefix"
- eval x=\"$x\"
- exec_prefix="$acl_save_exec_prefix"
- prefix="$acl_save_prefix"
+$as_echo "#define HAVE_LIBMPFR 1" >>confdefs.h
- if test "X$x" = "X-L$found_dir"; then
- haveit=yes
- break
- fi
- done
- if test -z "$haveit"; then
- LIBGMP="${LIBGMP}${LIBGMP:+ }-L$found_dir"
- fi
- if test "$hardcode_minus_L" != no; then
- LIBGMP="${LIBGMP}${LIBGMP:+ }$found_so"
- else
- LIBGMP="${LIBGMP}${LIBGMP:+ }-l$name"
- fi
- fi
- fi
- fi
- else
- if test "X$found_a" != "X"; then
- LIBGMP="${LIBGMP}${LIBGMP:+ }$found_a"
- else
- LIBGMP="${LIBGMP}${LIBGMP:+ }-L$found_dir -l$name"
- fi
- fi
- additional_includedir=
- case "$found_dir" in
- */lib | */lib/)
- basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'`
- additional_includedir="$basedir/include"
- ;;
- esac
- if test "X$additional_includedir" != "X"; then
- if test "X$additional_includedir" != "X/usr/include"; then
- haveit=
- if test "X$additional_includedir" = "X/usr/local/include"; then
- if test -n "$GCC"; then
- case $host_os in
- linux*) haveit=yes;;
- esac
- fi
- fi
- if test -z "$haveit"; then
- for x in $CPPFLAGS $INCGMP; do
-
- acl_save_prefix="$prefix"
- prefix="$acl_final_prefix"
- acl_save_exec_prefix="$exec_prefix"
- exec_prefix="$acl_final_exec_prefix"
- eval x=\"$x\"
- exec_prefix="$acl_save_exec_prefix"
- prefix="$acl_save_prefix"
-
- if test "X$x" = "X-I$additional_includedir"; then
- haveit=yes
- break
- fi
- done
- if test -z "$haveit"; then
- if test -d "$additional_includedir"; then
- INCGMP="${INCGMP}${INCGMP:+ }-I$additional_includedir"
- fi
- fi
- fi
- fi
- fi
- if test -n "$found_la"; then
- save_libdir="$libdir"
- case "$found_la" in
- */* | *\\*) . "$found_la" ;;
- *) . "./$found_la" ;;
- esac
- libdir="$save_libdir"
- for dep in $dependency_libs; do
- case "$dep" in
- -L*)
- additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
- if test "X$additional_libdir" != "X/usr/lib"; then
- haveit=
- if test "X$additional_libdir" = "X/usr/local/lib"; then
- if test -n "$GCC"; then
- case $host_os in
- linux*) haveit=yes;;
- esac
- fi
- fi
- if test -z "$haveit"; then
- haveit=
- for x in $LDFLAGS $LIBGMP; do
-
- acl_save_prefix="$prefix"
- prefix="$acl_final_prefix"
- acl_save_exec_prefix="$exec_prefix"
- exec_prefix="$acl_final_exec_prefix"
- eval x=\"$x\"
- exec_prefix="$acl_save_exec_prefix"
- prefix="$acl_save_prefix"
-
- if test "X$x" = "X-L$additional_libdir"; then
- haveit=yes
- break
- fi
- done
- if test -z "$haveit"; then
- if test -d "$additional_libdir"; then
- LIBGMP="${LIBGMP}${LIBGMP:+ }-L$additional_libdir"
- fi
- fi
- haveit=
- for x in $LDFLAGS $LTLIBGMP; do
-
- acl_save_prefix="$prefix"
- prefix="$acl_final_prefix"
- acl_save_exec_prefix="$exec_prefix"
- exec_prefix="$acl_final_exec_prefix"
- eval x=\"$x\"
- exec_prefix="$acl_save_exec_prefix"
- prefix="$acl_save_prefix"
-
- if test "X$x" = "X-L$additional_libdir"; then
- haveit=yes
- break
- fi
- done
- if test -z "$haveit"; then
- if test -d "$additional_libdir"; then
- LTLIBGMP="${LTLIBGMP}${LTLIBGMP:+ }-L$additional_libdir"
- fi
- fi
- fi
- fi
- ;;
- -R*)
- dir=`echo "X$dep" | sed -e 's/^X-R//'`
- if test "$enable_rpath" != no; then
- haveit=
- for x in $rpathdirs; do
- if test "X$x" = "X$dir"; then
- haveit=yes
- break
- fi
- done
- if test -z "$haveit"; then
- rpathdirs="$rpathdirs $dir"
- fi
- haveit=
- for x in $ltrpathdirs; do
- if test "X$x" = "X$dir"; then
- haveit=yes
- break
- fi
- done
- if test -z "$haveit"; then
- ltrpathdirs="$ltrpathdirs $dir"
- fi
- fi
- ;;
- -l*)
- names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
- ;;
- *.la)
- names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
- ;;
- *)
- LIBGMP="${LIBGMP}${LIBGMP:+ }$dep"
- LTLIBGMP="${LTLIBGMP}${LTLIBGMP:+ }$dep"
- ;;
- esac
- done
- fi
- else
- if test "x$lib_type" = "xauto" || test "x$lib_type" = "xshared"; then
- LIBGMP="${LIBGMP}${LIBGMP:+ }-l$name"
- LTLIBGMP="${LTLIBGMP}${LTLIBGMP:+ }-l$name"
- else
- LIBGMP="${LIBGMP}${LIBGMP:+ }-l:lib$name.$libext"
- LTLIBGMP="${LTLIBGMP}${LTLIBGMP:+ }-l:lib$name.$libext"
- fi
- fi
- fi
- fi
- done
- done
- if test "X$rpathdirs" != "X"; then
- if test -n "$hardcode_libdir_separator"; then
- alldirs=
- for found_dir in $rpathdirs; do
- alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir"
- done
- acl_save_libdir="$libdir"
- libdir="$alldirs"
- eval flag=\"$hardcode_libdir_flag_spec\"
- libdir="$acl_save_libdir"
- LIBGMP="${LIBGMP}${LIBGMP:+ }$flag"
- else
- for found_dir in $rpathdirs; do
- acl_save_libdir="$libdir"
- libdir="$found_dir"
- eval flag=\"$hardcode_libdir_flag_spec\"
- libdir="$acl_save_libdir"
- LIBGMP="${LIBGMP}${LIBGMP:+ }$flag"
- done
- fi
- fi
- if test "X$ltrpathdirs" != "X"; then
- for found_dir in $ltrpathdirs; do
- LTLIBGMP="${LTLIBGMP}${LTLIBGMP:+ }-R$found_dir"
- done
- fi
-
-
- ac_save_CPPFLAGS="$CPPFLAGS"
-
- for element in $INCGMP; do
- haveit=
- for x in $CPPFLAGS; do
-
- acl_save_prefix="$prefix"
- prefix="$acl_final_prefix"
- acl_save_exec_prefix="$exec_prefix"
- exec_prefix="$acl_final_exec_prefix"
- eval x=\"$x\"
- exec_prefix="$acl_save_exec_prefix"
- prefix="$acl_save_prefix"
-
- if test "X$x" = "X$element"; then
- haveit=yes
- break
- fi
- done
- if test -z "$haveit"; then
- CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element"
- fi
- done
-
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libgmp" >&5
-$as_echo_n "checking for libgmp... " >&6; }
-if ${ac_cv_libgmp+:} false; then :
- $as_echo_n "(cached) " >&6
-else
-
- ac_save_LIBS="$LIBS"
- LIBS="$LIBS $LIBGMP"
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <gmp.h>
-int
-main ()
-{
-mpz_t n;
- mpz_init (n);
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_libgmp=yes
-else
- ac_cv_libgmp=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
- LIBS="$ac_save_LIBS"
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libgmp" >&5
-$as_echo "$ac_cv_libgmp" >&6; }
- if test "$ac_cv_libgmp" = yes; then
- HAVE_LIBGMP=yes
-
-$as_echo "#define HAVE_LIBGMP 1" >>confdefs.h
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libgmp" >&5
-$as_echo_n "checking how to link with libgmp... " >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBGMP" >&5
-$as_echo "$LIBGMP" >&6; }
- else
- HAVE_LIBGMP=no
- CPPFLAGS="$ac_save_CPPFLAGS"
- LIBGMP=
- LTLIBGMP=
- fi
-
-
-
-
-
-
-if test "$HAVE_LIBGMP" != yes; then
- as_fn_error $? "GMP is missing or unusable" "$LINENO" 5
-fi
-
-
-# Check whether --with-mpfr was given.
-if test "${with_mpfr+set}" = set; then :
- withval=$with_mpfr;
-else
- with_mpfr=auto
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use MPFR" >&5
-$as_echo_n "checking whether to use MPFR... " >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_mpfr" >&5
-$as_echo "$with_mpfr" >&6; }
-
-if test "${with_mpfr}" = no; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: MPFR support disabled; some features may be unavailable." >&5
-$as_echo "$as_me: WARNING: MPFR support disabled; some features may be unavailable." >&2;}
- HAVE_LIBMPFR=no
-else
-
-
-
-
-
-
-
-
- use_additional=yes
-
- acl_save_prefix="$prefix"
- prefix="$acl_final_prefix"
- acl_save_exec_prefix="$exec_prefix"
- exec_prefix="$acl_final_exec_prefix"
-
- eval additional_includedir=\"$includedir\"
- eval additional_libdir=\"$libdir\"
-
- exec_prefix="$acl_save_exec_prefix"
- prefix="$acl_save_prefix"
-
-
-# Check whether --with-libmpfr-prefix was given.
-if test "${with_libmpfr_prefix+set}" = set; then :
- withval=$with_libmpfr_prefix;
- if test "X$withval" = "Xno"; then
- use_additional=no
- else
- if test "X$withval" = "X"; then
-
- acl_save_prefix="$prefix"
- prefix="$acl_final_prefix"
- acl_save_exec_prefix="$exec_prefix"
- exec_prefix="$acl_final_exec_prefix"
-
- eval additional_includedir=\"$includedir\"
- eval additional_libdir=\"$libdir\"
-
- exec_prefix="$acl_save_exec_prefix"
- prefix="$acl_save_prefix"
-
- else
- additional_includedir="$withval/include"
- additional_libdir="$withval/lib"
- fi
- fi
-
-fi
-
-
-# Check whether --with-libmpfr-type was given.
-if test "${with_libmpfr_type+set}" = set; then :
- withval=$with_libmpfr_type; with_libmpfr_type=$withval
-else
- with_libmpfr_type=auto
-fi
-
- lib_type=`eval echo \$with_libmpfr_type`
-
- LIBMPFR=
- LTLIBMPFR=
- INCMPFR=
- rpathdirs=
- ltrpathdirs=
- names_already_handled=
- names_next_round='mpfr gmp'
- while test -n "$names_next_round"; do
- names_this_round="$names_next_round"
- names_next_round=
- for name in $names_this_round; do
- already_handled=
- for n in $names_already_handled; do
- if test "$n" = "$name"; then
- already_handled=yes
- break
- fi
- done
- if test -z "$already_handled"; then
- names_already_handled="$names_already_handled $name"
- uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'`
- eval value=\"\$HAVE_LIB$uppername\"
- if test -n "$value"; then
- if test "$value" = yes; then
- eval value=\"\$LIB$uppername\"
- test -z "$value" || LIBMPFR="${LIBMPFR}${LIBMPFR:+ }$value"
- eval value=\"\$LTLIB$uppername\"
- test -z "$value" || LTLIBMPFR="${LTLIBMPFR}${LTLIBMPFR:+ }$value"
- else
- :
- fi
- else
- found_dir=
- found_la=
- found_so=
- found_a=
- if test $use_additional = yes; then
- if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext" && test x$lib_type != xstatic; then
- found_dir="$additional_libdir"
- found_so="$additional_libdir/lib$name.$shlibext"
- if test -f "$additional_libdir/lib$name.la"; then
- found_la="$additional_libdir/lib$name.la"
- fi
- elif test x$lib_type != xshared; then
- if test -f "$additional_libdir/lib$name.$libext"; then
- found_dir="$additional_libdir"
- found_a="$additional_libdir/lib$name.$libext"
- if test -f "$additional_libdir/lib$name.la"; then
- found_la="$additional_libdir/lib$name.la"
- fi
- fi
- fi
- fi
- if test "X$found_dir" = "X"; then
- for x in $LDFLAGS $LTLIBMPFR; do
-
- acl_save_prefix="$prefix"
- prefix="$acl_final_prefix"
- acl_save_exec_prefix="$exec_prefix"
- exec_prefix="$acl_final_exec_prefix"
- eval x=\"$x\"
- exec_prefix="$acl_save_exec_prefix"
- prefix="$acl_save_prefix"
-
- case "$x" in
- -L*)
- dir=`echo "X$x" | sed -e 's/^X-L//'`
- if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext" && test x$lib_type != xstatic; then
- found_dir="$dir"
- found_so="$dir/lib$name.$shlibext"
- if test -f "$dir/lib$name.la"; then
- found_la="$dir/lib$name.la"
- fi
- elif test x$lib_type != xshared; then
- if test -f "$dir/lib$name.$libext"; then
- found_dir="$dir"
- found_a="$dir/lib$name.$libext"
- if test -f "$dir/lib$name.la"; then
- found_la="$dir/lib$name.la"
- fi
- fi
- fi
- ;;
- esac
- if test "X$found_dir" != "X"; then
- break
- fi
- done
- fi
- if test "X$found_dir" != "X"; then
- LTLIBMPFR="${LTLIBMPFR}${LTLIBMPFR:+ }-L$found_dir -l$name"
- if test "X$found_so" != "X"; then
- if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/lib"; then
- LIBMPFR="${LIBMPFR}${LIBMPFR:+ }$found_so"
- else
- haveit=
- for x in $ltrpathdirs; do
- if test "X$x" = "X$found_dir"; then
- haveit=yes
- break
- fi
- done
- if test -z "$haveit"; then
- ltrpathdirs="$ltrpathdirs $found_dir"
- fi
- if test "$hardcode_direct" = yes; then
- LIBMPFR="${LIBMPFR}${LIBMPFR:+ }$found_so"
- else
- if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then
- LIBMPFR="${LIBMPFR}${LIBMPFR:+ }$found_so"
- haveit=
- for x in $rpathdirs; do
- if test "X$x" = "X$found_dir"; then
- haveit=yes
- break
- fi
- done
- if test -z "$haveit"; then
- rpathdirs="$rpathdirs $found_dir"
- fi
- else
- haveit=
- for x in $LDFLAGS $LIBMPFR; do
-
- acl_save_prefix="$prefix"
- prefix="$acl_final_prefix"
- acl_save_exec_prefix="$exec_prefix"
- exec_prefix="$acl_final_exec_prefix"
- eval x=\"$x\"
- exec_prefix="$acl_save_exec_prefix"
- prefix="$acl_save_prefix"
-
- if test "X$x" = "X-L$found_dir"; then
- haveit=yes
- break
- fi
- done
- if test -z "$haveit"; then
- LIBMPFR="${LIBMPFR}${LIBMPFR:+ }-L$found_dir"
- fi
- if test "$hardcode_minus_L" != no; then
- LIBMPFR="${LIBMPFR}${LIBMPFR:+ }$found_so"
- else
- LIBMPFR="${LIBMPFR}${LIBMPFR:+ }-l$name"
- fi
- fi
- fi
- fi
- else
- if test "X$found_a" != "X"; then
- LIBMPFR="${LIBMPFR}${LIBMPFR:+ }$found_a"
- else
- LIBMPFR="${LIBMPFR}${LIBMPFR:+ }-L$found_dir -l$name"
- fi
- fi
- additional_includedir=
- case "$found_dir" in
- */lib | */lib/)
- basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'`
- additional_includedir="$basedir/include"
- ;;
- esac
- if test "X$additional_includedir" != "X"; then
- if test "X$additional_includedir" != "X/usr/include"; then
- haveit=
- if test "X$additional_includedir" = "X/usr/local/include"; then
- if test -n "$GCC"; then
- case $host_os in
- linux*) haveit=yes;;
- esac
- fi
- fi
- if test -z "$haveit"; then
- for x in $CPPFLAGS $INCMPFR; do
-
- acl_save_prefix="$prefix"
- prefix="$acl_final_prefix"
- acl_save_exec_prefix="$exec_prefix"
- exec_prefix="$acl_final_exec_prefix"
- eval x=\"$x\"
- exec_prefix="$acl_save_exec_prefix"
- prefix="$acl_save_prefix"
-
- if test "X$x" = "X-I$additional_includedir"; then
- haveit=yes
- break
- fi
- done
- if test -z "$haveit"; then
- if test -d "$additional_includedir"; then
- INCMPFR="${INCMPFR}${INCMPFR:+ }-I$additional_includedir"
- fi
- fi
- fi
- fi
- fi
- if test -n "$found_la"; then
- save_libdir="$libdir"
- case "$found_la" in
- */* | *\\*) . "$found_la" ;;
- *) . "./$found_la" ;;
- esac
- libdir="$save_libdir"
- for dep in $dependency_libs; do
- case "$dep" in
- -L*)
- additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
- if test "X$additional_libdir" != "X/usr/lib"; then
- haveit=
- if test "X$additional_libdir" = "X/usr/local/lib"; then
- if test -n "$GCC"; then
- case $host_os in
- linux*) haveit=yes;;
- esac
- fi
- fi
- if test -z "$haveit"; then
- haveit=
- for x in $LDFLAGS $LIBMPFR; do
-
- acl_save_prefix="$prefix"
- prefix="$acl_final_prefix"
- acl_save_exec_prefix="$exec_prefix"
- exec_prefix="$acl_final_exec_prefix"
- eval x=\"$x\"
- exec_prefix="$acl_save_exec_prefix"
- prefix="$acl_save_prefix"
-
- if test "X$x" = "X-L$additional_libdir"; then
- haveit=yes
- break
- fi
- done
- if test -z "$haveit"; then
- if test -d "$additional_libdir"; then
- LIBMPFR="${LIBMPFR}${LIBMPFR:+ }-L$additional_libdir"
- fi
- fi
- haveit=
- for x in $LDFLAGS $LTLIBMPFR; do
-
- acl_save_prefix="$prefix"
- prefix="$acl_final_prefix"
- acl_save_exec_prefix="$exec_prefix"
- exec_prefix="$acl_final_exec_prefix"
- eval x=\"$x\"
- exec_prefix="$acl_save_exec_prefix"
- prefix="$acl_save_prefix"
-
- if test "X$x" = "X-L$additional_libdir"; then
- haveit=yes
- break
- fi
- done
- if test -z "$haveit"; then
- if test -d "$additional_libdir"; then
- LTLIBMPFR="${LTLIBMPFR}${LTLIBMPFR:+ }-L$additional_libdir"
- fi
- fi
- fi
- fi
- ;;
- -R*)
- dir=`echo "X$dep" | sed -e 's/^X-R//'`
- if test "$enable_rpath" != no; then
- haveit=
- for x in $rpathdirs; do
- if test "X$x" = "X$dir"; then
- haveit=yes
- break
- fi
- done
- if test -z "$haveit"; then
- rpathdirs="$rpathdirs $dir"
- fi
- haveit=
- for x in $ltrpathdirs; do
- if test "X$x" = "X$dir"; then
- haveit=yes
- break
- fi
- done
- if test -z "$haveit"; then
- ltrpathdirs="$ltrpathdirs $dir"
- fi
- fi
- ;;
- -l*)
- names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
- ;;
- *.la)
- names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
- ;;
- *)
- LIBMPFR="${LIBMPFR}${LIBMPFR:+ }$dep"
- LTLIBMPFR="${LTLIBMPFR}${LTLIBMPFR:+ }$dep"
- ;;
- esac
- done
- fi
- else
- if test "x$lib_type" = "xauto" || test "x$lib_type" = "xshared"; then
- LIBMPFR="${LIBMPFR}${LIBMPFR:+ }-l$name"
- LTLIBMPFR="${LTLIBMPFR}${LTLIBMPFR:+ }-l$name"
- else
- LIBMPFR="${LIBMPFR}${LIBMPFR:+ }-l:lib$name.$libext"
- LTLIBMPFR="${LTLIBMPFR}${LTLIBMPFR:+ }-l:lib$name.$libext"
- fi
- fi
- fi
- fi
- done
- done
- if test "X$rpathdirs" != "X"; then
- if test -n "$hardcode_libdir_separator"; then
- alldirs=
- for found_dir in $rpathdirs; do
- alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir"
- done
- acl_save_libdir="$libdir"
- libdir="$alldirs"
- eval flag=\"$hardcode_libdir_flag_spec\"
- libdir="$acl_save_libdir"
- LIBMPFR="${LIBMPFR}${LIBMPFR:+ }$flag"
- else
- for found_dir in $rpathdirs; do
- acl_save_libdir="$libdir"
- libdir="$found_dir"
- eval flag=\"$hardcode_libdir_flag_spec\"
- libdir="$acl_save_libdir"
- LIBMPFR="${LIBMPFR}${LIBMPFR:+ }$flag"
- done
- fi
- fi
- if test "X$ltrpathdirs" != "X"; then
- for found_dir in $ltrpathdirs; do
- LTLIBMPFR="${LTLIBMPFR}${LTLIBMPFR:+ }-R$found_dir"
- done
- fi
-
-
- ac_save_CPPFLAGS="$CPPFLAGS"
-
- for element in $INCMPFR; do
- haveit=
- for x in $CPPFLAGS; do
-
- acl_save_prefix="$prefix"
- prefix="$acl_final_prefix"
- acl_save_exec_prefix="$exec_prefix"
- exec_prefix="$acl_final_exec_prefix"
- eval x=\"$x\"
- exec_prefix="$acl_save_exec_prefix"
- prefix="$acl_save_prefix"
-
- if test "X$x" = "X$element"; then
- haveit=yes
- break
- fi
- done
- if test -z "$haveit"; then
- CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element"
- fi
- done
-
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libmpfr" >&5
-$as_echo_n "checking for libmpfr... " >&6; }
-if ${ac_cv_libmpfr+:} false; then :
- $as_echo_n "(cached) " >&6
-else
-
- ac_save_LIBS="$LIBS"
- LIBS="$LIBS $LIBMPFR"
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <mpfr.h>
-int
-main ()
-{
-mpfr_exp_t exp; mpfr_t x;
- mpfr_frexp (&exp, x, x, MPFR_RNDN);
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_libmpfr=yes
-else
- ac_cv_libmpfr=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
- LIBS="$ac_save_LIBS"
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libmpfr" >&5
-$as_echo "$ac_cv_libmpfr" >&6; }
- if test "$ac_cv_libmpfr" = yes; then
- HAVE_LIBMPFR=yes
-
-$as_echo "#define HAVE_LIBMPFR 1" >>confdefs.h
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libmpfr" >&5
-$as_echo_n "checking how to link with libmpfr... " >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBMPFR" >&5
-$as_echo "$LIBMPFR" >&6; }
- else
- HAVE_LIBMPFR=no
- CPPFLAGS="$ac_save_CPPFLAGS"
- LIBMPFR=
- LTLIBMPFR=
- fi
-
-
-
-
-
-
- if test "$HAVE_LIBMPFR" != yes; then
- if test "$with_mpfr" = yes; then
- as_fn_error $? "MPFR is missing or unusable" "$LINENO" 5
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: MPFR is missing or unusable; some features may be unavailable." >&5
-$as_echo "$as_me: WARNING: MPFR is missing or unusable; some features may be unavailable." >&2;}
- fi
fi
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_LIBMPFR" >&5
+$as_echo "$HAVE_LIBMPFR" >&6; }
# --------------------- #
# Check for libpython. #
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 28703d7..65e44d9 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -683,35 +683,103 @@ else
fi
fi
+AC_ARG_WITH(gmp_include,
+ AS_HELP_STRING([--with-gmp-include=DIR], [GMP include directory]),
+ [CPPFLAGS="$CPPFLAGS -I$withval"])
+AC_ARG_WITH(gmp_lib,
+ AS_HELP_STRING([--with-gmp-lib=DIR], [GMP lib directory]),
+ [LIBGMP="-L$withval"])
+AC_ARG_WITH(gmp,
+ AS_HELP_STRING([--with-gmp=DIR], [GMP install directory]), [
+ if test -z "$with_gmp_lib" && test -z "$with_gmp_include" ; then
+ CPPFLAGS="$CPPFLAGS -I$withval/include"
+ LIBGMP="-L$withval/lib"
+ else
+ AC_MSG_FAILURE([Do not use --with-gmp and --with-gmp-include/--with-gmp-lib options simultaneously.])
+ fi
+])
+
+AC_MSG_CHECKING([for GMP])
# Verify that we have a usable GMP library.
-AC_LIB_HAVE_LINKFLAGS([gmp], [], [#include <gmp.h>],
- [mpz_t n;
- mpz_init (n);])
+save_LIBS=$LIBS
+LIBS="$LIBS $LIBGMP -lgmp"
+AC_TRY_LINK([#include <gmp.h>],
+ [mpz_t n;
+ mpz_init (n);],
+ [HAVE_LIBGMP=yes], [HAVE_LIBGMP=no])
+LIBS=$save_LIBS
if test "$HAVE_LIBGMP" != yes; then
AC_MSG_ERROR([GMP is missing or unusable])
fi
+LIBGMP="$LIBGMP -lgmp"
+AC_SUBST(LIBGMP)
+AC_DEFINE(HAVE_LIBGMP, 1, [Define if you have the GMP library.])
+AC_MSG_RESULT([$HAVE_LIBGMP])
+AC_ARG_WITH(libmpfr_prefix,
+ AS_HELP_STRING([--with-libmpfr-prefix=DIR], [this option has been DEPRECATED]), [
+ if test -z "$with_mpfr" ; then
+ with_mpfr="auto"
+ fi
+ if test x"$with_mpfr" != xauto && test x"$with_mpfr" != xyes && test x"$with_mpfr" != xno ; then
+ AC_MSG_FAILURE([Do not use --with-mpfr=DIR and --with-libmpfr-prefix=DIR options simultaneously.])
+ fi
+])
+save_CPPFLAGS=$CPPFLAGS
+AC_ARG_WITH(mpfr_include,
+ AS_HELP_STRING([--with-mpfr-include=DIR], [MPFR include directory]),
+ [CPPFLAGS="$CPPFLAGS -I$withval"])
+AC_ARG_WITH(mpfr_lib,
+ AS_HELP_STRING([--with-mpfr-lib=DIR], [MPFR lib directory]),
+ [LIBMPFR="-L$withval"])
AC_ARG_WITH(mpfr,
- AS_HELP_STRING([--with-mpfr], [include MPFR support (auto/yes/no)]),
- [], [with_mpfr=auto])
-AC_MSG_CHECKING([whether to use MPFR])
-AC_MSG_RESULT([$with_mpfr])
+ AS_HELP_STRING([--with-mpfr=DIR],
+ [MFPR install directory (or auto/yes/no)]), [
+ if test -n "$with_libmpfr_prefix" ; then
+ withval=$with_libmpfr_prefix
+ fi
+ if test -z "$with_mpfr_lib" && test -z "$with_mpfr_include" ; then
+ if test x"$withval" != xauto && test x"$withval" != xyes && test x"$withval" != xno ; then
+ CPPFLAGS="$CPPFLAGS -I$withval/include"
+ LIBMPFR="-L$withval/lib"
+ if test -z "$with_libmpfr_prefix" ; then
+ with_mpfr=yes
+ fi
+ fi
+ else
+ AC_MSG_FAILURE([Do not use --with-mpfr and --with-mpfr-include/--with-mpfr-lib options simultaneously.])
+ fi
+])
+AC_MSG_CHECKING([whether to use MPFR])
if test "${with_mpfr}" = no; then
AC_MSG_WARN([MPFR support disabled; some features may be unavailable.])
HAVE_LIBMPFR=no
+ LIBMPFR=
+ CPPFLAGS=$save_CPPFLAGS
else
- AC_LIB_HAVE_LINKFLAGS([mpfr], [gmp], [#include <mpfr.h>],
- [mpfr_exp_t exp; mpfr_t x;
- mpfr_frexp (&exp, x, x, MPFR_RNDN);])
+ save_LIBS=$LIBS
+ LIBS="$LIBS $LIBMPFR -lmpfr $LIBGMP"
+ AC_TRY_LINK([#include <mpfr.h>],
+ [mpfr_exp_t exp; mpfr_t x;
+ mpfr_frexp (&exp, x, x, MPFR_RNDN);],
+ [HAVE_LIBMPFR=yes], [HAVE_LIBMPFR=no])
+ LIBS=$save_LIBS
if test "$HAVE_LIBMPFR" != yes; then
if test "$with_mpfr" = yes; then
AC_MSG_ERROR([MPFR is missing or unusable])
else
AC_MSG_WARN([MPFR is missing or unusable; some features may be unavailable.])
fi
+ LIBMPFR=
+ CPPFLAGS=$save_CPPFLAGS
+ else
+ LIBMPFR="$LIBMPFR -lmpfr"
+ AC_SUBST(LIBMPFR)
+ AC_DEFINE(HAVE_LIBMPFR, 1, [Define if you have the MPFR library.])
fi
fi
+AC_MSG_RESULT([$HAVE_LIBMPFR])
# --------------------- #
# Check for libpython. #
--
1.9.1
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0001-Enable-GDB-build-with-in-tree-GMP-and-MPFR-v2.patch --]
[-- Type: text/x-patch; name="0001-Enable-GDB-build-with-in-tree-GMP-and-MPFR-v2.patch", Size: 15197 bytes --]
From b7cd2ebb1f555397885279a2ace6bd46ca4f5643 Mon Sep 17 00:00:00 2001
From: Bernd Edlinger <bernd.edlinger@hotmail.de>
Date: Sun, 15 Nov 2020 15:37:22 +0100
Subject: [PATCH] Enable GDB build with in-tree GMP and MPFR
With this patch GDB can be built with in-tree GMP and/or
MPFR. This works also for cross-builds.
All that is needed, is a sym-link in the source tree,
like this:
gmp -> ../gmp-6.1.0
mpfr -> ../mpfr-3.1.4
2020-12-10 Bernd Edlinger <bernd.edlinger@hotmail.de>
* Makefile.def: Prepare for GDB build with intree GMP.
* Makefile.in: Regenerate.
gdb:
2020-12-10 Bernd Edlinger <bernd.edlinger@hotmail.de>
* configure.ac: Detect in-tree GMP and MPFR.
* configure: Regenerate.
* README: Mention ./contrib/download_prerequisites.
contrib:
2020-12-10 Bernd Edlinger <bernd.edlinger@hotmail.de>
* download_prerequisites: New helper script.
* prerequisites.md5: checksums.
* prerequisites.sha512: checksums.
---
Makefile.def | 2 +
Makefile.in | 2 +
contrib/download_prerequisites | 263 +++++++++++++++++++++++++++++++++++++++++
contrib/prerequisites.md5 | 2 +
contrib/prerequisites.sha512 | 2 +
gdb/README | 12 ++
gdb/configure | 20 +++-
gdb/configure.ac | 20 +++-
8 files changed, 315 insertions(+), 8 deletions(-)
create mode 100755 contrib/download_prerequisites
create mode 100644 contrib/prerequisites.md5
create mode 100644 contrib/prerequisites.sha512
diff --git a/Makefile.def b/Makefile.def
index 089e70a..b6872c9 100644
--- a/Makefile.def
+++ b/Makefile.def
@@ -391,6 +391,8 @@ dependencies = { module=all-intl; on=all-libiconv; };
// Host modules specific to gdb.
dependencies = { module=configure-gdb; on=all-intl; };
+dependencies = { module=configure-gdb; on=all-gmp; };
+dependencies = { module=configure-gdb; on=all-mpfr; };
dependencies = { module=configure-gdb; on=configure-sim; };
dependencies = { module=configure-gdb; on=all-bfd; };
dependencies = { module=configure-gdb; on=all-gnulib; };
diff --git a/Makefile.in b/Makefile.in
index fe34132..ead9430 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -52449,6 +52449,8 @@ configure-libcc1: maybe-configure-gcc
all-libcc1: maybe-all-gcc
all-utils: maybe-all-libiberty
configure-gdb: maybe-all-intl
+configure-gdb: maybe-all-gmp
+configure-gdb: maybe-all-mpfr
configure-gdb: maybe-all-bfd
configure-gdb: maybe-all-libiconv
all-gdb: maybe-all-libiberty
diff --git a/contrib/download_prerequisites b/contrib/download_prerequisites
new file mode 100755
index 0000000..0d04030
--- /dev/null
+++ b/contrib/download_prerequisites
@@ -0,0 +1,263 @@
+#! /bin/sh
+#! -*- coding:utf-8; mode:shell-script; -*-
+
+# Download some prerequisites needed by GDB.
+# Run this from the top level of the GDB source tree and the GDB build will do
+# the right thing. Run it with the `--help` option for more information.
+#
+# (C) 2010-2020 Free Software Foundation
+#
+# 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/.
+
+program='download_prerequisites'
+version='(unversioned)'
+
+# MAINTAINERS: If you update the package versions below, please
+# remember to also update the files `contrib/prerequisites.sha512` and
+# `contrib/prerequisites.md5` with the new checksums.
+
+gmp='gmp-6.1.0.tar.bz2'
+mpfr='mpfr-3.1.4.tar.bz2'
+
+base_url='http://gcc.gnu.org/pub/gcc/infrastructure/'
+
+echo_archives() {
+ echo "${gmp}"
+ echo "${mpfr}"
+}
+
+verify=1
+force=0
+OS=$(uname)
+
+case $OS in
+ "Darwin"|"FreeBSD"|"DragonFly"|"AIX")
+ chksum='shasum -a 512 --check'
+ ;;
+ "OpenBSD")
+ chksum='sha512 -c'
+ ;;
+ *)
+ chksum='sha512sum -c'
+ ;;
+esac
+
+if type wget > /dev/null ; then
+ fetch='wget'
+else
+ fetch='curl -LO'
+fi
+chksum_extension='sha512'
+directory='.'
+
+helptext="usage: ${program} [OPTION...]
+
+Downloads some prerequisites needed by GDB. Run this from the top level of the
+GDB source tree and the GDB build will do the right thing.
+
+The following options are available:
+
+ --directory=DIR download and unpack packages into DIR instead of '.'
+ --force download again overwriting existing packages
+ --no-force do not download existing packages again (default)
+ --verify verify package integrity after download (default)
+ --no-verify don't verify package integrity
+ --sha512 use SHA512 checksum to verify package integrity (default)
+ --md5 use MD5 checksum to verify package integrity
+ --help show this text and exit
+ --version show version information and exit
+"
+
+versiontext="${program} ${version}
+Copyright (C) 2020 Free Software Foundation, Inc.
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+die() {
+ echo "error: $@" >&2
+ exit 1
+}
+
+for arg in "$@"
+do
+ case "${arg}" in
+ --help)
+ echo "${helptext}"
+ exit
+ ;;
+ --version)
+ echo "${versiontext}"
+ exit
+ ;;
+ esac
+done
+unset arg
+
+# Emulate Linux's 'md5 --check' on macOS
+md5_check() {
+ # Store the standard input: a line from contrib/prerequisites.md5:
+ md5_checksum_line=$(cat -)
+ # Grab the text before the first space
+ md5_checksum_expected="${md5_checksum_line%% *}"
+ # Grab the text after the first space
+ file_to_check="${md5_checksum_line##* }"
+ # Calculate the md5 checksum for the downloaded file
+ md5_checksum_output=$(md5 -r "${file_to_check}")
+ # Grab the text before the first space
+ md5_checksum_detected="${md5_checksum_output%% *}"
+ [ "${md5_checksum_expected}" == "${md5_checksum_detected}" ] \
+ || die "Cannot verify integrity of possibly corrupted file ${file_to_check}"
+ echo "${file_to_check}: OK"
+}
+
+
+argnext=
+for arg in "$@"
+do
+ if [ "x${argnext}" = x ]
+ then
+ case "${arg}" in
+ --directory)
+ argnext='directory'
+ ;;
+ --directory=*)
+ directory="${arg#--directory=}"
+ ;;
+ --force)
+ force=1
+ ;;
+ --no-force)
+ force=0
+ ;;
+ --verify)
+ verify=1
+ ;;
+ --no-verify)
+ verify=0
+ ;;
+ --sha512)
+ case $OS in
+ "Darwin")
+ chksum='shasum -a 512 --check'
+ ;;
+ *)
+ chksum='sha512sum --check'
+ ;;
+ esac
+ chksum_extension='sha512'
+ verify=1
+ ;;
+ --md5)
+ case $OS in
+ "Darwin")
+ chksum='md5_check'
+ ;;
+ *)
+ chksum='md5 --check'
+ ;;
+ esac
+ chksum_extension='md5'
+ verify=1
+ ;;
+ -*)
+ die "unknown option: ${arg}"
+ ;;
+ *)
+ die "too many arguments"
+ ;;
+ esac
+ else
+ case "${arg}" in
+ -*)
+ die "Missing argument for option --${argnext}"
+ ;;
+ esac
+ case "${argnext}" in
+ directory)
+ directory="${arg}"
+ ;;
+ *)
+ die "The impossible has happened"
+ ;;
+ esac
+ argnext=
+ fi
+done
+[ "x${argnext}" = x ] || die "Missing argument for option --${argnext}"
+unset arg argnext
+
+[ -e ./gdb/version.in ] \
+ || die "You must run this script in the top-level GDB source directory"
+
+[ -d "${directory}" ] \
+ || die "No such directory: ${directory}"
+
+for ar in $(echo_archives)
+do
+ if [ ${force} -gt 0 ]; then rm -f "${directory}/${ar}"; fi
+ [ -e "${directory}/${ar}" ] \
+ || ( cd "${directory}" && ${fetch} --no-verbose "${base_url}${ar}" ) \
+ || die "Cannot download ${ar} from ${base_url}"
+done
+unset ar
+
+if [ ${verify} -gt 0 ]
+then
+ chksumfile="contrib/prerequisites.${chksum_extension}"
+ [ -r "${chksumfile}" ] || die "No checksums available"
+ for ar in $(echo_archives)
+ do
+ grep "${ar}" "${chksumfile}" \
+ | ( cd "${directory}" && ${chksum} ) \
+ || die "Cannot verify integrity of possibly corrupted file ${ar}"
+ done
+ unset chksumfile
+fi
+unset ar
+
+for ar in $(echo_archives)
+do
+ package="${ar%.tar*}"
+ if [ ${force} -gt 0 ]; then rm -rf "${directory}/${package}"; fi
+ case $ar in
+ *.gz)
+ uncompress='gzip -d'
+ ;;
+ *.bz2)
+ uncompress='bzip2 -d'
+ ;;
+ *)
+ uncompress='cat'
+ ;;
+ esac
+ [ -e "${directory}/${package}" ] \
+ || ( cd "${directory}" && $uncompress <"${ar}" | tar -xf - ) \
+ || die "Cannot extract package from ${ar}"
+ unset package
+done
+unset ar
+
+for ar in $(echo_archives)
+do
+ target="${directory}/${ar%.tar*}/"
+ linkname="${ar%-*}"
+ if [ ${force} -gt 0 ]; then rm -f "${linkname}"; fi
+ [ -e "${linkname}" ] \
+ || ln -s "${target}" "${linkname}" \
+ || die "Cannot create symbolic link ${linkname} --> ${target}"
+ unset target linkname
+done
+unset ar
+
+echo "All prerequisites downloaded successfully."
diff --git a/contrib/prerequisites.md5 b/contrib/prerequisites.md5
new file mode 100644
index 0000000..cf7be0d
--- /dev/null
+++ b/contrib/prerequisites.md5
@@ -0,0 +1,2 @@
+86ee6e54ebfc4a90b643a65e402c4048 gmp-6.1.0.tar.bz2
+b8a2f6b0e68bef46e53da2ac439e1cf4 mpfr-3.1.4.tar.bz2
diff --git a/contrib/prerequisites.sha512 b/contrib/prerequisites.sha512
new file mode 100644
index 0000000..8f05aff
--- /dev/null
+++ b/contrib/prerequisites.sha512
@@ -0,0 +1,2 @@
+3c82aeab9c1596d4da8afac2eec38e429e84f3211e1a572cf8fd2b546493c44c039b922a1133eaaa48bd7f3e11dbe795a384e21ed95cbe3ecc58d7ac02246117 gmp-6.1.0.tar.bz2
+51066066ff2c12ed2198605ecf68846b0c96b548adafa5b80e0c786d0df488411a5e8973358fce7192dc977ad4e68414cf14500e3c39746de62465eb145bb819 mpfr-3.1.4.tar.bz2
diff --git a/gdb/README b/gdb/README
index e65c5ea..2b9c382 100644
--- a/gdb/README
+++ b/gdb/README
@@ -488,6 +488,12 @@ more obscure GDB `configure' options are not listed here.
Build GDB using the GMP library installed at the directory DIR.
If your host does not have GMP installed, you can get the latest
version at `https://gmplib.org/'.
+ You can also build GMP in-tree when you use the script
+ ./contrib/download_prerequisites.
+ This must be done before configure. No --with-gmp options must
+ be used when invoking configure in this case.
+ Note however, that this does only work with a separate build
+ directory.
`--with-mpfr'
Build GDB with GNU MPFR, a library for multiple-precision
@@ -499,6 +505,12 @@ more obscure GDB `configure' options are not listed here.
available, GDB will fall back to using host floating-point
arithmetic. If your host does not have GNU MPFR installed, you
can get the latest version from `https://www.mpfr.org/'.
+ You can also build MPFR in-tree when you use the script
+ ./contrib/download_prerequisites.
+ This must be done before configure. No --with-mpfr options must
+ be used when invoking configure in this case.
+ Note however, that this does only work with a separate build
+ directory.
`--with-python[=PYTHON]'
Build GDB with Python scripting support. (Done by default if
diff --git a/gdb/configure b/gdb/configure
index 51b4d19..5819002 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -9991,6 +9991,13 @@ done
fi
# Verify that we have a usable GMP library.
+if test -d "../gmp"; then
+ CPPFLAGS="$CPPFLAGS -I../gmp"
+ LIBGMP="../gmp/.libs/libgmp.a"
+
+$as_echo "#define HAVE_LIBGMP 1" >>confdefs.h
+
+else
@@ -10431,7 +10438,7 @@ int
main ()
{
mpz_t n;
- mpz_init (n);
+ mpz_init (n);
;
return 0;
}
@@ -10469,8 +10476,9 @@ $as_echo "$LIBGMP" >&6; }
-if test "$HAVE_LIBGMP" != yes; then
- as_fn_error $? "GMP is missing or unusable" "$LINENO" 5
+ if test "$HAVE_LIBGMP" != yes; then
+ as_fn_error $? "GMP is missing or unusable" "$LINENO" 5
+ fi
fi
@@ -10490,6 +10498,12 @@ if test "${with_mpfr}" = no; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: MPFR support disabled; some features may be unavailable." >&5
$as_echo "$as_me: WARNING: MPFR support disabled; some features may be unavailable." >&2;}
HAVE_LIBMPFR=no
+elif test -d "../mpfr"; then
+ CPPFLAGS="$CPPFLAGS -I${srcdir}/../mpfr/src"
+ LIBMPFR="../mpfr/src/.libs/libmpfr.a"
+
+$as_echo "#define HAVE_LIBMPFR 1" >>confdefs.h
+
else
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 28703d7..f1c233c 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -684,11 +684,17 @@ else
fi
# Verify that we have a usable GMP library.
-AC_LIB_HAVE_LINKFLAGS([gmp], [], [#include <gmp.h>],
- [mpz_t n;
- mpz_init (n);])
-if test "$HAVE_LIBGMP" != yes; then
- AC_MSG_ERROR([GMP is missing or unusable])
+if test -d "../gmp"; then
+ CPPFLAGS="$CPPFLAGS -I../gmp"
+ LIBGMP="../gmp/.libs/libgmp.a"
+ AC_DEFINE(HAVE_LIBGMP, 1, [Define if you have the GMP library.])
+else
+ AC_LIB_HAVE_LINKFLAGS([gmp], [], [#include <gmp.h>],
+ [mpz_t n;
+ mpz_init (n);])
+ if test "$HAVE_LIBGMP" != yes; then
+ AC_MSG_ERROR([GMP is missing or unusable])
+ fi
fi
AC_ARG_WITH(mpfr,
@@ -700,6 +706,10 @@ AC_MSG_RESULT([$with_mpfr])
if test "${with_mpfr}" = no; then
AC_MSG_WARN([MPFR support disabled; some features may be unavailable.])
HAVE_LIBMPFR=no
+elif test -d "../mpfr"; then
+ CPPFLAGS="$CPPFLAGS -I${srcdir}/../mpfr/src"
+ LIBMPFR="../mpfr/src/.libs/libmpfr.a"
+ AC_DEFINE(HAVE_LIBMPFR, 1, [Define if you have the MPFR library.])
else
AC_LIB_HAVE_LINKFLAGS([mpfr], [gmp], [#include <mpfr.h>],
[mpfr_exp_t exp; mpfr_t x;
--
1.9.1
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [PATCH v2] Enable GDB build with in-tree GMP and MPFR
2020-12-25 12:05 ` Bernd Edlinger
@ 2020-12-27 22:01 ` Simon Marchi
2020-12-29 8:36 ` Bernd Edlinger
0 siblings, 1 reply; 140+ messages in thread
From: Simon Marchi @ 2020-12-27 22:01 UTC (permalink / raw)
To: Bernd Edlinger, Joel Brobecker
Cc: Tom Tromey, Pedro Alves, Eli Zaretskii, Andrew Burgess, gdb-patches
On 2020-12-25 7:05 a.m., Bernd Edlinger wrote:
> Hi everybody,
>
> I have now two possible ways to go forward with the configure options
> for gmp and mpfr.
>
> See the attached patches:
>
> Variant 1: implements traditional configure options
> --with-gmp-include=DIR, --with-gmp-lib=DIR, --with-gmp=DIR,
> --with-mpfr-include=DIR, --with-mpfr-lib=DIR, --with-mpfr=DIR
> but does additionally understand --with-libmpfr-prefix=DIR
> and --with-mpfr=auto/yes/no.
>
> Variant 2: (I already posted that one) keeps all configure options
> as they are now, and just uses the presence of a ../gmp and ../mpfr
> directory to override the gmp and mpfr configure flags.
>
> I would be interested in what you think, and which variant you would
> prefer.
>
>
> Thanks
> Bernd.
>
I really don't have a strong opinion about this, but my only strong-ish
opinion is that I want to minimize the complexity of what we add.
I'm already on the fence about the download script and detecting gmp
/ mpfr in-tree, because I think this is complexity we don't need.
It's not difficult for the user to download and build these two
libraries. It's totally fine for a project to have required
dependencies that the user needs to build first...
We already provide --with-libmpfr-prefix and --with-libgmp-prefix.
Any complexity we add (like adding --with-gmp-include and
--with-gmp-lib on top of that) means more combinations to test for
whoever needs to modify that code next, more chances of breaking
something. IMO it is not a net benefit for the project to add
these additional new switches.
Joel convinced me that it's not so important to stay in sync with
gcc for this. So I'd choose the existing solution of using
AC_LIB_HAVE_LINKFLAGS, since that takes care of all the low level
details for us.
Simon
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [PATCH v2] Enable GDB build with in-tree GMP and MPFR
2020-12-27 22:01 ` Simon Marchi
@ 2020-12-29 8:36 ` Bernd Edlinger
2020-12-29 14:50 ` Simon Marchi
0 siblings, 1 reply; 140+ messages in thread
From: Bernd Edlinger @ 2020-12-29 8:36 UTC (permalink / raw)
To: Simon Marchi, Joel Brobecker
Cc: Tom Tromey, Pedro Alves, Eli Zaretskii, Andrew Burgess, gdb-patches
On 12/27/20 11:01 PM, Simon Marchi wrote:
>
>
> On 2020-12-25 7:05 a.m., Bernd Edlinger wrote:
>> Hi everybody,
>>
>> I have now two possible ways to go forward with the configure options
>> for gmp and mpfr.
>>
>> See the attached patches:
>>
>> Variant 1: implements traditional configure options
>> --with-gmp-include=DIR, --with-gmp-lib=DIR, --with-gmp=DIR,
>> --with-mpfr-include=DIR, --with-mpfr-lib=DIR, --with-mpfr=DIR
>> but does additionally understand --with-libmpfr-prefix=DIR
>> and --with-mpfr=auto/yes/no.
>>
>> Variant 2: (I already posted that one) keeps all configure options
>> as they are now, and just uses the presence of a ../gmp and ../mpfr
>> directory to override the gmp and mpfr configure flags.
>>
>> I would be interested in what you think, and which variant you would
>> prefer.
>>
>>
>> Thanks
>> Bernd.
>>
>
> I really don't have a strong opinion about this, but my only strong-ish
> opinion is that I want to minimize the complexity of what we add.
> I'm already on the fence about the download script and detecting gmp
> / mpfr in-tree, because I think this is complexity we don't need.
> It's not difficult for the user to download and build these two
> libraries. It's totally fine for a project to have required
> dependencies that the user needs to build first...
>
> We already provide --with-libmpfr-prefix and --with-libgmp-prefix.
> Any complexity we add (like adding --with-gmp-include and
> --with-gmp-lib on top of that) means more combinations to test for
> whoever needs to modify that code next, more chances of breaking
> something. IMO it is not a net benefit for the project to add
> these additional new switches.
>
> Joel convinced me that it's not so important to stay in sync with
> gcc for this. So I'd choose the existing solution of using
> AC_LIB_HAVE_LINKFLAGS, since that takes care of all the low level
> details for us.
>
> Simon
>
Okay, I also like the second variant better.
Can I assume that you agree to that variant?
If yes, then I should send the patch regarding the
toplevel configury change also to the binutils mailing list,
right?
Thanks
Bernd.
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [PATCH v2] Enable GDB build with in-tree GMP and MPFR
2020-12-29 8:36 ` Bernd Edlinger
@ 2020-12-29 14:50 ` Simon Marchi
2021-01-10 14:12 ` Bernd Edlinger
0 siblings, 1 reply; 140+ messages in thread
From: Simon Marchi @ 2020-12-29 14:50 UTC (permalink / raw)
To: Bernd Edlinger, Joel Brobecker
Cc: Tom Tromey, Pedro Alves, Eli Zaretskii, Andrew Burgess, gdb-patches
On 2020-12-29 3:36 a.m., Bernd Edlinger wrote:
> Okay, I also like the second variant better.
>
> Can I assume that you agree to that variant?
>
> If yes, then I should send the patch regarding the
> toplevel configury change also to the binutils mailing list,
> right?
I do prefer the second variant over the first one, because it's
simpler.
But I prefer having none of them, and just having a built mpfr/gmp
be a prerequisite step to building GDB.
Simon
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [PATCH v2] Enable GDB build with in-tree GMP and MPFR
2020-12-29 14:50 ` Simon Marchi
@ 2021-01-10 14:12 ` Bernd Edlinger
2021-01-10 15:32 ` Simon Marchi
2021-01-11 3:22 ` Joel Brobecker
0 siblings, 2 replies; 140+ messages in thread
From: Bernd Edlinger @ 2021-01-10 14:12 UTC (permalink / raw)
To: Simon Marchi, Joel Brobecker
Cc: Tom Tromey, Pedro Alves, Eli Zaretskii, Andrew Burgess, gdb-patches
On 12/29/20 3:50 PM, Simon Marchi wrote:
> On 2020-12-29 3:36 a.m., Bernd Edlinger wrote:
>> Okay, I also like the second variant better.
>>
>> Can I assume that you agree to that variant?
>>
>> If yes, then I should send the patch regarding the
>> toplevel configury change also to the binutils mailing list,
>> right?
>
> I do prefer the second variant over the first one, because it's
> simpler.
>
> But I prefer having none of them, and just having a built mpfr/gmp
> be a prerequisite step to building GDB.
>
Hmm, I see, but it was argued previously on this list, that it is okay
for GDB to have a mandatory dependency to GMP because GCC has the same
dependency.
However GCC offers exactly the same convenience as it allows GMP
to be optionally built in-tree.
Bernd.
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [PATCH v2] Enable GDB build with in-tree GMP and MPFR
2021-01-10 14:12 ` Bernd Edlinger
@ 2021-01-10 15:32 ` Simon Marchi
2021-01-11 3:22 ` Joel Brobecker
1 sibling, 0 replies; 140+ messages in thread
From: Simon Marchi @ 2021-01-10 15:32 UTC (permalink / raw)
To: Bernd Edlinger, Joel Brobecker
Cc: Tom Tromey, Pedro Alves, Eli Zaretskii, Andrew Burgess, gdb-patches
On 2021-01-10 9:12 a.m., Bernd Edlinger wrote:
> Hmm, I see, but it was argued previously on this list, that it is okay
> for GDB to have a mandatory dependency to GMP because GCC has the same
> dependency.
>
> However GCC offers exactly the same convenience as it allows GMP
> to be optionally built in-tree.
I don't see how that requires us to do the same thing.
Simon
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [PATCH v2] Enable GDB build with in-tree GMP and MPFR
2021-01-10 14:12 ` Bernd Edlinger
2021-01-10 15:32 ` Simon Marchi
@ 2021-01-11 3:22 ` Joel Brobecker
2021-01-16 18:01 ` Bernd Edlinger
1 sibling, 1 reply; 140+ messages in thread
From: Joel Brobecker @ 2021-01-11 3:22 UTC (permalink / raw)
To: Bernd Edlinger; +Cc: Simon Marchi, Pedro Alves, Tom Tromey, gdb-patches
> > But I prefer having none of them, and just having a built mpfr/gmp
> > be a prerequisite step to building GDB.
>
> Hmm, I see, but it was argued previously on this list, that it is okay
> for GDB to have a mandatory dependency to GMP because GCC has the same
> dependency.
I think it was to show that this extra dependency wasn't going to
introduce an unreasonable burden on the developers of some specific
platform. Other that that, I wasn't trying to "follow" GCC.
> However GCC offers exactly the same convenience as it allows GMP
> to be optionally built in-tree.
I wouldn't object to that convenience, but I'm in the same camp as
Simon on that one. I know that this convenience is easier, and
I used to take advantage of something like that for e.g. libiconv;
but I soon realized that I kept rebuilding the same thing over and over
every time I rebuilt everything from scratch. In the end, it took a tiny
bit of effort to build and install that library once, and that was it,
I used that same library build until I had to switch to a different
machine. Maybe those libraries aren't big enough to make that much of
a difference (I haven't checked), but I found in the end that I didn't
really miss the convenience.
Another option if you are on GNU/Linux is to install the system version
together with the corresponding "devel" package. I assume it's not
something that works for you?
--
Joel
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [PATCH v2] Enable GDB build with in-tree GMP and MPFR
2021-01-11 3:22 ` Joel Brobecker
@ 2021-01-16 18:01 ` Bernd Edlinger
0 siblings, 0 replies; 140+ messages in thread
From: Bernd Edlinger @ 2021-01-16 18:01 UTC (permalink / raw)
To: Joel Brobecker; +Cc: Simon Marchi, Pedro Alves, Tom Tromey, gdb-patches
On 1/11/21 4:22 AM, Joel Brobecker wrote:
>>> But I prefer having none of them, and just having a built mpfr/gmp
>>> be a prerequisite step to building GDB.
>>
>> Hmm, I see, but it was argued previously on this list, that it is okay
>> for GDB to have a mandatory dependency to GMP because GCC has the same
>> dependency.
>
> I think it was to show that this extra dependency wasn't going to
> introduce an unreasonable burden on the developers of some specific
> platform. Other that that, I wasn't trying to "follow" GCC.
>
>> However GCC offers exactly the same convenience as it allows GMP
>> to be optionally built in-tree.
>
> I wouldn't object to that convenience, but I'm in the same camp as
> Simon on that one. I know that this convenience is easier, and
> I used to take advantage of something like that for e.g. libiconv;
> but I soon realized that I kept rebuilding the same thing over and over
> every time I rebuilt everything from scratch. In the end, it took a tiny
> bit of effort to build and install that library once, and that was it,
> I used that same library build until I had to switch to a different
> machine. Maybe those libraries aren't big enough to make that much of
> a difference (I haven't checked), but I found in the end that I didn't
> really miss the convenience.
>
> Another option if you are on GNU/Linux is to install the system version
> together with the corresponding "devel" package. I assume it's not
> something that works for you?
>
Sure, but from time to time, I also want to build using a cross-compiler
for an entirely different target. And for that I would like the binary
to be completely self-contained if possible, just like when I build
gcc for a different target.
I don't say it is impossible to set up a statically built cross-gmp for that,
but it is not straight-forward either, and since the top-level configury
handles everything automatically for cross-builds, it is rather simple
in comparison.
Bernd.
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [PATCH v2] Enable GDB build with in-tree GMP and MPFR
2020-12-14 22:17 ` Simon Marchi
2020-12-15 2:33 ` Joel Brobecker
@ 2020-12-15 15:33 ` Bernd Edlinger
1 sibling, 0 replies; 140+ messages in thread
From: Bernd Edlinger @ 2020-12-15 15:33 UTC (permalink / raw)
To: Simon Marchi, Tom Tromey
Cc: Joel Brobecker, Pedro Alves, Eli Zaretskii, Andrew Burgess, gdb-patches
On 12/14/20 11:17 PM, Simon Marchi wrote:
> On 2020-12-14 4:35 p.m., Tom Tromey wrote:
>>>>>>> "Simon" == Simon Marchi <simark@simark.ca> writes:
>>
>> Simon> So with this patch, we now have:
>>
>> Simon> --with-gmp-include=DIR GMP include directory
>> Simon> --with-gmp-lib=DIR GMP lib directory
>> Simon> --with-gmp=DIR GMP install directory
>> Simon> --with-libgmp-prefix[=DIR] search for libgmp in DIR/include and DIR/lib
>> Simon> --without-libgmp-prefix don't search for libgmp in includedir and libdir
>>
>> Simon> I think that's getting a bit confusing. That's too many ways to set gmp
>> Simon> paths, with -with-libgmp-prefix and --with-gmp doing the same thing.
>>
>> FWIW we have the same situation with MPFR.
>
> :(
>> Simon> It might mean that we have to stop using AC_LIB_HAVE_LINKFLAGS
>> Simon> though, or customize it.
>>
>> Yes. Perhaps alternatively we could promote its use to the top level.
>> It's maybe a pain to do that.
>
> Perhaps, but --with-{gmp,mpfr} would need to be kept as backwards
> compatibility. I think it would be hard to convince the gcc people of
> the benefits of such a change.
>
>> Simon> An alternative to downloading the pre-requisites would be to check them
>> Simon> in the repo. We do it for readline already: there is a copy in the
>> Simon> repo, which is used by default, but you can specify
>> Simon> --with-system-readline if you want to use the system's readline. We
>> Simon> could do the same with gmp and mpfr. The downside is that we deviate a
>> Simon> bit from how gcc does, the the upside is that it's simpler, IMO.
>>
>> For me the main difference here is that, historically, we've had to
>> patch readline. In cases where GDB has never needed to patch a
>> dependency (libiconv comes to mind), we've haven't bothered.
>
> Ok, when you put it like that then it doesn't make as much sense to
> check the code in the repo.
>
> Thinking about it a bit more, I don't see why gmp and mpfr get this
> treatment, what is it that makes them different from other dependencies?
> If you want to build GDB with XML support, you download and build expat,
> or install it using your package manager. Why can't you do the same
> with mpfr/gmp? The only reason for us I can see is "because gcc does
> it" and we share the build system with gcc. But otherwise, I'd just
> tell people to build/install mpfr and gmp themselves.
>
I think the difference, is other libraries may be missing,
but there is still a reasonable default in that case, just
when the build starts to fail completely without them, that
makes it inconvenient.
Bernd.
> Simon
>
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [PATCH v2] Enable GDB build with in-tree GMP and MPFR
2020-12-14 18:47 ` Simon Marchi
2020-12-14 21:35 ` Tom Tromey
@ 2020-12-15 15:10 ` Bernd Edlinger
1 sibling, 0 replies; 140+ messages in thread
From: Bernd Edlinger @ 2020-12-15 15:10 UTC (permalink / raw)
To: Simon Marchi, Joel Brobecker, Pedro Alves, Eli Zaretskii,
Andrew Burgess, gdb-patches
On 12/14/20 7:47 PM, Simon Marchi wrote:
> I'll give a shot at reviewing this, to make it progress.
>
> Joel, there's a question for you below.
>
> On 2020-12-14 12:40 p.m., Bernd Edlinger wrote:
>> Well,
>>
>> I thought, I should add a few words in the README
>> about this feature:
>>
>> diff --git a/gdb/README b/gdb/README
>> index e65c5ea..db0a774 100644
>> --- a/gdb/README
>> +++ b/gdb/README
>> @@ -488,6 +488,9 @@ more obscure GDB `configure' options are not listed here.
>> Build GDB using the GMP library installed at the directory DIR.
>> If your host does not have GMP installed, you can get the latest
>> version at `https://gmplib.org/'.
>> + You can also build GMP in-tree when you use the script
>> + ./contrib/download_prerequisites. Note however, that this
>> + does only work with a separate build directory.
>>
>> `--with-mpfr'
>> Build GDB with GNU MPFR, a library for multiple-precision
>> @@ -499,6 +502,9 @@ more obscure GDB `configure' options are not listed here.
>> available, GDB will fall back to using host floating-point
>> arithmetic. If your host does not have GNU MPFR installed, you
>> can get the latest version from `https://www.mpfr.org/'.
>> + You can also build MPFR in-tree when you use the script
>> + ./contrib/download_prerequisites. Note however, that this
>> + does only work with a separate build directory.
>>
>> `--with-python[=PYTHON]'
>> Build GDB with Python scripting support. (Done by default if
>>
>>
>> Tested on x86_64-pc-linux-gnu.
>> Is it OK for trunk?
>>
>>
>> Thanks
>> Bernd.
>>
>
> There is already --with-libgmp-prefix / --without-libgmp-prefix,
> provided (I think by):
>
> # Verify that we have a usable GMP library.
> AC_LIB_HAVE_LINKFLAGS([gmp], [], [#include <gmp.h>],
> [mpz_t n;
> mpz_init (n);])
>
> So with this patch, we now have:
>
> --with-gmp-include=DIR GMP include directory
> --with-gmp-lib=DIR GMP lib directory
> --with-gmp=DIR GMP install directory
> --with-libgmp-prefix[=DIR] search for libgmp in DIR/include and DIR/lib
> --without-libgmp-prefix don't search for libgmp in includedir and libdir
>
> I think that's getting a bit confusing. That's too many ways to set gmp
> paths, with -with-libgmp-prefix and --with-gmp doing the same thing.
>
> If the rest of the binutils/gcc ecosystem already uses --with-gmp,
> --with-gmp-include and --with-gmp-lib, I think we should align with
> those. Fortunately, we haven't yet shipped a GDB with
> --with-libgmp-prefix, so I think it's safe to remove it. It might mean
> that we have to stop using AC_LIB_HAVE_LINKFLAGS though, or customize
> it. Joel, do you agree?
>
> In this line, in top-level Makefile.def, do you need to also add
> something about gmp, and why pass flags about mpc_mpfr (I sincerely
> don't know what it is/does)?
>
> host_modules= { module= gdb;
> extra_configure_flags='@extra_mpfr_configure_flags@ @extra_mpc_mpfr_configure_flags@';};
>
Yes, the names for those macros are a bit funny :-)
I just used existing macros to make the delta smaller in the top level config.
extra_mpfr_configure_flags, are in fact the --with-gmp-include/lib parameters,
that are passed to in-tree mpfr, and
extra_mpc_mpfr_configure_flags, are the --with-mpfr-include/lib parameters,
that are passed to in-tree mpc.
I would like to rename those after merging this change and probably other
changes to the gcc repository, and finally merge the gcc changes
again to the binutils-gdb repository.
The binutils toplevel configure files are 2 years behind gcc.
But I think it is straight forward to make gdb/binutils/gcc build from
the same source tree. I just tried this the other day, and just
had a problem with --disable-source-highlight, but
> In the README, you say:
>
> You can also build GMP in-tree when you use the script
> ./contrib/download_prerequisites. Note however, that this
> does only work with a separate build directory.
>
> That leaves me with some questions:
>
> - do I need to run this script myself before configure?
> - if I do, does that mean the build will use the downloaded version,
> even if there is a working version on my system?
>
> It would be good to answer those questions in the README text.
>
Yes. It is intended as a convenience, when you do not like to install
the libraries on your system, or when you build for a cross-target,
You should do that manually before configure when you would otherwise
run into a build error. I will clarify that README text.
Bernd.
> An alternative to downloading the pre-requisites would be to check them
> in the repo. We do it for readline already: there is a copy in the
> repo, which is used by default, but you can specify
> --with-system-readline if you want to use the system's readline. We
> could do the same with gmp and mpfr. The downside is that we deviate a
> bit from how gcc does, the the upside is that it's simpler, IMO.
>
> Note that any change to the files outside GDB will have to be approved
> by the binutils folks too. And changes to the top-level Makefile will
> have to be replicated to the gcc repo.
>
> Simon
>
^ permalink raw reply [flat|nested] 140+ messages in thread
* [pushed/v2 2/9] gdb: Make GMP a required dependency for building GDB
2020-11-15 8:35 ` pushed: " Joel Brobecker
2020-11-15 8:35 ` [pushed/v2 1/9] gdb/configure: Add --with-libgmp-prefix option Joel Brobecker
@ 2020-11-15 8:35 ` Joel Brobecker
2020-11-15 8:35 ` [pushed/v2 3/9] gmp-utils: New API to simply use of GMP's integer/rational/float objects Joel Brobecker
` (9 subsequent siblings)
11 siblings, 0 replies; 140+ messages in thread
From: Joel Brobecker @ 2020-11-15 8:35 UTC (permalink / raw)
To: gdb-patches; +Cc: Simon Marchi, Joel Brobecker
This commit modifies gdb's configure script to trigger an error
if we cannot find a usable libgmp.
For the record, making this a requirement was discussed in March 2018:
https://sourceware.org/pipermail/gdb-patches/2018-March/147373.html
gdb/ChangeLog:
* configure.ac: Generate an error if a usable GMP library
could not be found.
* configure: Regenerate.
---
gdb/ChangeLog | 6 ++++++
gdb/configure | 3 +++
gdb/configure.ac | 3 +++
3 files changed, 12 insertions(+)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index ee1dea3..8de390a 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,11 @@
2020-11-15 Joel Brobecker <brobecker@adacore.com>
+ * configure.ac: Generate an error if a usable GMP library
+ could not be found.
+ * configure: Regenerate.
+
+2020-11-15 Joel Brobecker <brobecker@adacore.com>
+
* configure.ac: Add support for --with-libgmp-prefix.
* Makefile.in (LIBGMP): New variable.
(CLIBS): Include $(LIBGMP).
diff --git a/gdb/configure b/gdb/configure
index 2bf0856..a3e73b4 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -10469,6 +10469,9 @@ $as_echo "$LIBGMP" >&6; }
+if test "$HAVE_LIBGMP" != yes; then
+ as_fn_error $? "GMP is missing or unusable" "$LINENO" 5
+fi
# Check whether --with-mpfr was given.
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 0264a4f..32f25d9 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -687,6 +687,9 @@ fi
AC_LIB_HAVE_LINKFLAGS([gmp], [], [#include <gmp.h>],
[mpz_t n;
mpz_init (n);])
+if test "$HAVE_LIBGMP" != yes; then
+ AC_MSG_ERROR([GMP is missing or unusable])
+fi
AC_ARG_WITH(mpfr,
AS_HELP_STRING([--with-mpfr], [include MPFR support (auto/yes/no)]),
--
2.1.4
^ permalink raw reply [flat|nested] 140+ messages in thread
* [pushed/v2 3/9] gmp-utils: New API to simply use of GMP's integer/rational/float objects
2020-11-15 8:35 ` pushed: " Joel Brobecker
2020-11-15 8:35 ` [pushed/v2 1/9] gdb/configure: Add --with-libgmp-prefix option Joel Brobecker
2020-11-15 8:35 ` [pushed/v2 2/9] gdb: Make GMP a required dependency for building GDB Joel Brobecker
@ 2020-11-15 8:35 ` Joel Brobecker
2020-11-15 8:35 ` [pushed/v2 4/9] Move uinteger_pow gdb/valarith.c to gdb/utils.c and make it public Joel Brobecker
` (8 subsequent siblings)
11 siblings, 0 replies; 140+ messages in thread
From: Joel Brobecker @ 2020-11-15 8:35 UTC (permalink / raw)
To: gdb-patches; +Cc: Simon Marchi, Joel Brobecker
This API was motivated by a number of reasons:
- GMP's API does not handle "long long" and "unsigned long long",
so using LONGEST and ULONGEST is not straightforward;
- Automate the need to initialize GMP objects before use, and
clear them when no longer used.
However, this API grew also to help with similar matter such
as formatting to a string, and also reading/writing fixed-point
values from byte buffers.
Dedicated unit testing is also added.
gdb/ChangeLog:
* gmp-utils.h, gmp-utils.h: New file.
* unittests/gmp-utils-selftests.c: New file.
* Makefile.in (SUBDIR_UNITTESTS_SRCS): Add
unittests/gmp-utils-selftests.c.
(COMMON_SFILES) Add gmp-utils.c.
(HFILES_NO_SRCDIR): Add gmp-utils.h.
---
gdb/ChangeLog | 9 +
gdb/Makefile.in | 3 +
gdb/gmp-utils.c | 172 ++++++++++++++
gdb/gmp-utils.h | 282 ++++++++++++++++++++++
gdb/unittests/gmp-utils-selftests.c | 460 ++++++++++++++++++++++++++++++++++++
5 files changed, 926 insertions(+)
create mode 100644 gdb/gmp-utils.c
create mode 100644 gdb/gmp-utils.h
create mode 100644 gdb/unittests/gmp-utils-selftests.c
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 8de390a..a029109 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,14 @@
2020-11-15 Joel Brobecker <brobecker@adacore.com>
+ * gmp-utils.h, gmp-utils.h: New file.
+ * unittests/gmp-utils-selftests.c: New file.
+ * Makefile.in (SUBDIR_UNITTESTS_SRCS): Add
+ unittests/gmp-utils-selftests.c.
+ (COMMON_SFILES) Add gmp-utils.c.
+ (HFILES_NO_SRCDIR): Add gmp-utils.h.
+
+2020-11-15 Joel Brobecker <brobecker@adacore.com>
+
* configure.ac: Generate an error if a usable GMP library
could not be found.
* configure: Regenerate.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index c461964..9b48f73 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -446,6 +446,7 @@ SELFTESTS_SRCS = \
unittests/filtered_iterator-selftests.c \
unittests/format_pieces-selftests.c \
unittests/function-view-selftests.c \
+ unittests/gmp-utils-selftests.c \
unittests/lookup_name_info-selftests.c \
unittests/memory-map-selftests.c \
unittests/memrange-selftests.c \
@@ -1059,6 +1060,7 @@ COMMON_SFILES = \
gdb_regex.c \
gdbarch.c \
gdbtypes.c \
+ gmp-utils.c \
gnu-v2-abi.c \
gnu-v3-abi.c \
go-lang.c \
@@ -1304,6 +1306,7 @@ HFILES_NO_SRCDIR = \
gdbthread.h \
gdbtypes.h \
glibc-tdep.h \
+ gmp-utils.h \
gnu-nat.h \
go-lang.h \
gregset.h \
diff --git a/gdb/gmp-utils.c b/gdb/gmp-utils.c
new file mode 100644
index 0000000..db92e57
--- /dev/null
+++ b/gdb/gmp-utils.c
@@ -0,0 +1,172 @@
+/* Copyright (C) 2019-2020 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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 "gmp-utils.h"
+
+/* See gmp-utils.h. */
+
+gdb::unique_xmalloc_ptr<char>
+gmp_string_asprintf (const char *fmt, ...)
+{
+ va_list vp;
+ char *buf;
+
+ va_start (vp, fmt);
+ gmp_vasprintf (&buf, fmt, vp);
+ va_end (vp);
+
+ return gdb::unique_xmalloc_ptr<char> (buf);
+}
+
+/* See gmp-utils.h. */
+
+void
+gdb_mpz::read (const gdb_byte *buf, int len, enum bfd_endian byte_order,
+ bool unsigned_p)
+{
+ mpz_import (val, 1 /* count */, -1 /* order */, len /* size */,
+ byte_order == BFD_ENDIAN_BIG ? 1 : -1 /* endian */,
+ 0 /* nails */, buf /* op */);
+
+ if (!unsigned_p)
+ {
+ /* The value was imported as if it was a positive value,
+ as mpz_import does not handle signs. If the original value
+ was in fact negative, we need to adjust VAL accordingly. */
+ gdb_mpz max;
+
+ mpz_ui_pow_ui (max.val, 2, len * TARGET_CHAR_BIT - 1);
+ if (mpz_cmp (val, max.val) >= 0)
+ mpz_submul_ui (val, max.val, 2);
+ }
+}
+
+/* See gmp-utils.h. */
+
+void
+gdb_mpz::write (gdb_byte *buf, int len, enum bfd_endian byte_order,
+ bool unsigned_p) const
+{
+ gdb_mpz exported_val (val);
+
+ if (mpz_cmp_ui (val, 0) < 0)
+ {
+ /* mpz_export does not handle signed values, so create a positive
+ value whose bit representation as an unsigned of the same length
+ would be the same as our negative value. */
+ gdb_mpz neg_offset;
+
+ mpz_ui_pow_ui (neg_offset.val, 2, len * TARGET_CHAR_BIT);
+ mpz_add (exported_val.val, exported_val.val, neg_offset.val);
+ }
+
+ /* Start by clearing the buffer, as mpz_export only writes as many
+ bytes as it needs (including none, if the value to export is zero. */
+ memset (buf, 0, len);
+ mpz_export (buf, NULL /* count */, -1 /* order */, len /* size */,
+ byte_order == BFD_ENDIAN_BIG ? 1 : -1 /* endian */,
+ 0 /* nails */, exported_val.val);
+}
+
+/* See gmp-utils.h. */
+
+gdb_mpz
+gdb_mpq::get_rounded () const
+{
+ /* Work with a positive number so as to make the "floor" rounding
+ always round towards zero. */
+
+ gdb_mpq abs_val (val);
+ mpq_abs (abs_val.val, abs_val.val);
+
+ /* Convert our rational number into a quotient and remainder,
+ with "floor" rounding, which in our case means rounding
+ towards zero. */
+
+ gdb_mpz quotient, remainder;
+ mpz_fdiv_qr (quotient.val, remainder.val,
+ mpq_numref (abs_val.val), mpq_denref (abs_val.val));
+
+ /* Multiply the remainder by 2, and see if it is greater or equal
+ to abs_val's denominator. If yes, round to the next integer. */
+
+ mpz_mul_ui (remainder.val, remainder.val, 2);
+ if (mpz_cmp (remainder.val, mpq_denref (abs_val.val)) >= 0)
+ mpz_add_ui (quotient.val, quotient.val, 1);
+
+ /* Re-apply the sign if needed. */
+ if (mpq_sgn (val) < 0)
+ mpz_neg (quotient.val, quotient.val);
+
+ return quotient;
+}
+
+/* See gmp-utils.h. */
+
+void
+gdb_mpq::read_fixed_point (const gdb_byte *buf, int len,
+ enum bfd_endian byte_order, bool unsigned_p,
+ const gdb_mpq &scaling_factor)
+{
+ gdb_mpz vz;
+ vz.read (buf, len, byte_order, unsigned_p);
+
+ mpq_set_z (val, vz.val);
+ mpq_mul (val, val, scaling_factor.val);
+}
+
+/* See gmp-utils.h. */
+
+void
+gdb_mpq::write_fixed_point (gdb_byte *buf, int len,
+ enum bfd_endian byte_order, bool unsigned_p,
+ const gdb_mpq &scaling_factor) const
+{
+ gdb_mpq unscaled (val);
+
+ mpq_div (unscaled.val, unscaled.val, scaling_factor.val);
+
+ gdb_mpz unscaled_z = unscaled.get_rounded ();
+ unscaled_z.write (buf, len, byte_order, unsigned_p);
+}
+
+/* A wrapper around xrealloc that we can then register with GMP
+ as the "realloc" function. */
+
+static void *
+xrealloc_for_gmp (void *ptr, size_t old_size, size_t new_size)
+{
+ return xrealloc (ptr, new_size);
+}
+
+/* A wrapper around xfree that we can then register with GMP
+ as the "free" function. */
+
+static void
+xfree_for_gmp (void *ptr, size_t size)
+{
+ xfree (ptr);
+}
+
+void _initialize_gmp_utils ();
+
+void
+_initialize_gmp_utils ()
+{
+ /* Tell GMP to use GDB's memory management routines. */
+ mp_set_memory_functions (xmalloc, xrealloc_for_gmp, xfree_for_gmp);
+}
diff --git a/gdb/gmp-utils.h b/gdb/gmp-utils.h
new file mode 100644
index 0000000..1214b64
--- /dev/null
+++ b/gdb/gmp-utils.h
@@ -0,0 +1,282 @@
+/* Miscellaneous routines making it easier to use GMP within GDB's framework.
+
+ Copyright (C) 2019-2020 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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/>. */
+
+#ifndef GMP_UTILS_H
+#define GMP_UTILS_H
+
+#include "defs.h"
+
+/* Include <stdio.h> and <stdarg.h> ahead of <gmp.h>, so as to get
+ access to GMP's various formatting functions. */
+#include <stdio.h>
+#include <stdarg.h>
+#include <gmp.h>
+#include "gdbsupport/traits.h"
+
+/* Same as gmp_asprintf, but returning a convenient wrapper type. */
+
+gdb::unique_xmalloc_ptr<char> gmp_string_asprintf (const char *fmt, ...);
+
+/* A class to make it easier to use GMP's mpz_t values within GDB. */
+
+struct gdb_mpz
+{
+ mpz_t val;
+
+ /* Constructors. */
+ gdb_mpz () { mpz_init (val); }
+
+ explicit gdb_mpz (const mpz_t &from_val)
+ {
+ mpz_init (val);
+ mpz_set (val, from_val);
+ }
+
+ gdb_mpz (const gdb_mpz &from)
+ {
+ mpz_init (val);
+ mpz_set (val, from.val);
+ }
+
+ /* Initialize using the given integral value.
+
+ The main advantage of this method is that it handles both signed
+ and unsigned types, with no size restriction. */
+ template<typename T, typename = gdb::Requires<std::is_integral<T>>>
+ explicit gdb_mpz (T src)
+ {
+ mpz_init (val);
+ set (src);
+ }
+
+ explicit gdb_mpz (gdb_mpz &&from)
+ {
+ mpz_init (val);
+ mpz_swap (val, from.val);
+ }
+
+
+ gdb_mpz &operator= (const gdb_mpz &from)
+ {
+ mpz_set (val, from.val);
+ return *this;
+ }
+
+ gdb_mpz &operator= (gdb_mpz &&other)
+ {
+ mpz_swap (val, other.val);
+ return *this;
+ }
+
+ template<typename T, typename = gdb::Requires<std::is_integral<T>>>
+ gdb_mpz &operator= (T src)
+ {
+ set (src);
+ return *this;
+ }
+
+ /* Convert VAL to an integer of the given type.
+
+ The return type can signed or unsigned, with no size restriction. */
+ template<typename T> T as_integer () const;
+
+ /* Set VAL by importing the number stored in the byte buffer (BUF),
+ given its size (LEN) and BYTE_ORDER.
+
+ UNSIGNED_P indicates whether the number has an unsigned type. */
+ void read (const gdb_byte *buf, int len, enum bfd_endian byte_order,
+ bool unsigned_p);
+
+ /* Write VAL into BUF as a LEN-bytes number with the given BYTE_ORDER.
+
+ UNSIGNED_P indicates whether the number has an unsigned type. */
+ void write (gdb_byte *buf, int len, enum bfd_endian byte_order,
+ bool unsigned_p) const;
+
+ /* Return a string containing VAL. */
+ gdb::unique_xmalloc_ptr<char> str () const
+ { return gmp_string_asprintf ("%Zd", val); }
+
+ /* The destructor. */
+ ~gdb_mpz () { mpz_clear (val); }
+
+private:
+
+ /* Helper template for constructor and operator=. */
+ template<typename T> void set (T src);
+};
+
+/* A class to make it easier to use GMP's mpq_t values within GDB. */
+
+struct gdb_mpq
+{
+ mpq_t val;
+
+ /* Constructors. */
+ gdb_mpq () { mpq_init (val); }
+
+ explicit gdb_mpq (const mpq_t &from_val)
+ {
+ mpq_init (val);
+ mpq_set (val, from_val);
+ }
+
+ gdb_mpq (const gdb_mpq &from)
+ {
+ mpq_init (val);
+ mpq_set (val, from.val);
+ }
+
+ explicit gdb_mpq (gdb_mpq &&from)
+ {
+ mpq_init (val);
+ mpq_swap (val, from.val);
+ }
+
+ /* Copy assignment operator. */
+ gdb_mpq &operator= (const gdb_mpq &from)
+ {
+ mpq_set (val, from.val);
+ return *this;
+ }
+
+ gdb_mpq &operator= (gdb_mpq &&from)
+ {
+ mpq_swap (val, from.val);
+ return *this;
+ }
+
+ /* Return a string representing VAL as "<numerator> / <denominator>". */
+ gdb::unique_xmalloc_ptr<char> str () const
+ { return gmp_string_asprintf ("%Qd", val); }
+
+ /* Return VAL rounded to the nearest integer. */
+ gdb_mpz get_rounded () const;
+
+ /* Set VAL from the contents of the given buffer (BUF), which
+ contains the unscaled value of a fixed point type object
+ with the given size (LEN) and byte order (BYTE_ORDER).
+
+ UNSIGNED_P indicates whether the number has an unsigned type.
+ SCALING_FACTOR is the scaling factor to apply after having
+ read the unscaled value from our buffer. */
+ void read_fixed_point (const gdb_byte *buf, int len,
+ enum bfd_endian byte_order, bool unsigned_p,
+ const gdb_mpq &scaling_factor);
+
+ /* Write VAL into BUF as a LEN-bytes fixed point value following
+ the given BYTE_ORDER.
+
+ UNSIGNED_P indicates whether the number has an unsigned type.
+ SCALING_FACTOR is the scaling factor to apply before writing
+ the unscaled value to our buffer. */
+ void write_fixed_point (gdb_byte *buf, int len,
+ enum bfd_endian byte_order, bool unsigned_p,
+ const gdb_mpq &scaling_factor) const;
+
+ /* The destructor. */
+ ~gdb_mpq () { mpq_clear (val); }
+};
+
+/* A class to make it easier to use GMP's mpf_t values within GDB.
+
+ Should MPFR become a required dependency, we should probably
+ drop this class in favor of using MPFR. */
+
+struct gdb_mpf
+{
+ mpf_t val;
+
+ /* Constructors. */
+ gdb_mpf () { mpf_init (val); }
+
+ DISABLE_COPY_AND_ASSIGN (gdb_mpf);
+
+ /* Set VAL from the contents of the given buffer (BUF), which
+ contains the unscaled value of a fixed point type object
+ with the given size (LEN) and byte order (BYTE_ORDER).
+
+ UNSIGNED_P indicates whether the number has an unsigned type.
+ SCALING_FACTOR is the scaling factor to apply after having
+ read the unscaled value from our buffer. */
+ void read_fixed_point (const gdb_byte *buf, int len,
+ enum bfd_endian byte_order, bool unsigned_p,
+ const gdb_mpq &scaling_factor)
+ {
+ gdb_mpq tmp_q;
+
+ tmp_q.read_fixed_point (buf, len, byte_order, unsigned_p, scaling_factor);
+ mpf_set_q (val, tmp_q.val);
+ }
+
+ /* The destructor. */
+ ~gdb_mpf () { mpf_clear (val); }
+};
+
+/* See declaration above. */
+
+template<typename T>
+void
+gdb_mpz::set (T src)
+{
+ mpz_import (val, 1 /* count */, -1 /* order */,
+ sizeof (T) /* size */, 0 /* endian (0 = native) */,
+ 0 /* nails */, &src /* op */);
+ if (std::is_signed<T>::value && src < 0)
+ {
+ /* mpz_import does not handle the sign, so our value was imported
+ as an unsigned. Adjust that imported value so as to make it
+ the correct negative value. */
+ gdb_mpz neg_offset;
+
+ mpz_ui_pow_ui (neg_offset.val, 2, sizeof (T) * HOST_CHAR_BIT);
+ mpz_sub (val, val, neg_offset.val);
+ }
+}
+
+/* See declaration above. */
+
+template<typename T>
+T
+gdb_mpz::as_integer () const
+{
+ /* Initialize RESULT, because mpz_export only write the minimum
+ number of bytes, including none if our value is zero! */
+ T result = 0;
+
+ gdb_mpz exported_val (val);
+ if (std::is_signed<T>::value && mpz_cmp_ui (val, 0) < 0)
+ {
+ /* We want to use mpz_export to set the return value, but
+ this function does not handle the sign. So give exported_val
+ a value which is at the same time positive, and has the same
+ bit representation as our negative value. */
+ gdb_mpz neg_offset;
+
+ mpz_ui_pow_ui (neg_offset.val, 2, sizeof (T) * HOST_CHAR_BIT);
+ mpz_add (exported_val.val, exported_val.val, neg_offset.val);
+ }
+
+ mpz_export (&result, NULL /* count */, -1 /* order */,
+ sizeof (T) /* size */, 0 /* endian (0 = native) */,
+ 0 /* nails */, exported_val.val);
+ return result;
+}
+
+#endif
diff --git a/gdb/unittests/gmp-utils-selftests.c b/gdb/unittests/gmp-utils-selftests.c
new file mode 100644
index 0000000..e8c3c5c
--- /dev/null
+++ b/gdb/unittests/gmp-utils-selftests.c
@@ -0,0 +1,460 @@
+/* Self tests of the gmp-utils API.
+
+ Copyright (C) 2019-2020 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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 "gmp-utils.h"
+#include "gdbsupport/selftest.h"
+
+#include <math.h>
+
+namespace selftests {
+
+/* Perform a series of general tests of gdb_mpz's as_integer method.
+
+ This function tries to be reasonably exhaustive, by testing the edges,
+ as well as a resonable set of values including negative ones, zero,
+ and positive values. */
+
+static void
+gdb_mpz_as_integer ()
+{
+ /* Test a range of values, both as LONGEST and ULONGEST. */
+ gdb_mpz v;
+ LONGEST l_expected;
+ ULONGEST ul_expected;
+
+ /* Start with the smallest LONGEST */
+ l_expected = (LONGEST) 1 << (sizeof (LONGEST) * 8 - 1);
+
+ mpz_ui_pow_ui (v.val, 2, sizeof (LONGEST) * 8 - 1);
+ mpz_neg (v.val, v.val);
+
+ SELF_CHECK (v.as_integer<LONGEST> () == l_expected);
+
+ /* Try with a small range of integers including negative, zero,
+ and positive values. */
+ for (int i = -256; i <= 256; i++)
+ {
+ l_expected = (LONGEST) i;
+ mpz_set_si (v.val, i);
+ SELF_CHECK (v.as_integer<LONGEST> () == l_expected);
+
+ if (i >= 0)
+ {
+ ul_expected = (ULONGEST) i;
+ mpz_set_ui (v.val, i);
+ SELF_CHECK (v.as_integer<ULONGEST> () == ul_expected);
+ }
+ }
+
+ /* Try with LONGEST_MAX. */
+ l_expected = LONGEST_MAX;
+ ul_expected = (ULONGEST) l_expected;
+
+ mpz_ui_pow_ui (v.val, 2, sizeof (LONGEST) * 8 - 1);
+ mpz_sub_ui (v.val, v.val, 1);
+
+ SELF_CHECK (v.as_integer<LONGEST> () == l_expected);
+ SELF_CHECK (v.as_integer<ULONGEST> () == ul_expected);
+
+ /* Try with ULONGEST_MAX. */
+ ul_expected = ULONGEST_MAX;
+ mpz_ui_pow_ui (v.val, 2, sizeof (LONGEST) * 8);
+ mpz_sub_ui (v.val, v.val, 1);
+
+ SELF_CHECK (v.as_integer<ULONGEST> () == ul_expected);
+}
+
+/* A helper function to store the given integer value into a buffer,
+ before reading it back into a gdb_mpz. Sets ACTUAL to the value
+ read back, while at the same time setting EXPECTED as the value
+ we would expect to be read back.
+
+ Note that this function does not perform the comparison between
+ EXPECTED and ACTUAL. The caller will do it inside a SELF_CHECK
+ call, allowing the line information shown when the test fails
+ to provide a bit more information about the kind of values
+ that were used when the check failed. This makes the writing
+ of the tests a little more verbose, but the debugging in case
+ of problems should hopefuly be easier. */
+
+template<typename T>
+void
+store_and_read_back (T val, int buf_len, enum bfd_endian byte_order,
+ gdb_mpz &expected, gdb_mpz &actual)
+{
+ gdb_byte *buf;
+
+ expected = val;
+
+ buf = (gdb_byte *) alloca (buf_len);
+ store_integer (buf, buf_len, byte_order, val);
+
+ /* Pre-initialize ACTUAL to something that's not the expected value. */
+ mpz_set (actual.val, expected.val);
+ mpz_sub_ui (actual.val, actual.val, 500);
+
+ actual.read (buf, buf_len, byte_order, !std::is_signed<T>::value);
+}
+
+/* Test the gdb_mpz::read method over a reasonable range of values.
+
+ The testing is done by picking an arbitrary buffer length, after
+ which we test every possible value that this buffer allows, both
+ with signed numbers as well as unsigned ones. */
+
+static void
+gdb_mpz_read_all_from_small ()
+{
+ /* Start with a type whose size is small enough that we can afford
+ to check the complete range. */
+
+ int buf_len = 1;
+ LONGEST l_min = -pow (2, buf_len * 8 - 1);
+ LONGEST l_max = pow (2, buf_len * 8 - 1) - 1;
+
+ for (LONGEST l = l_min; l <= l_max; l++)
+ {
+ gdb_mpz expected, actual;
+
+ store_and_read_back (l, buf_len, BFD_ENDIAN_BIG, expected, actual);
+ SELF_CHECK (mpz_cmp (actual.val, expected.val) == 0);
+
+ store_and_read_back (l, buf_len, BFD_ENDIAN_LITTLE, expected, actual);
+ SELF_CHECK (mpz_cmp (actual.val, expected.val) == 0);
+ }
+
+ /* Do the same as above, but with an unsigned type. */
+ ULONGEST ul_min = 0;
+ ULONGEST ul_max = pow (2, buf_len * 8) - 1;
+
+ for (ULONGEST ul = ul_min; ul <= ul_max; ul++)
+ {
+ gdb_mpz expected, actual;
+
+ store_and_read_back (ul, buf_len, BFD_ENDIAN_BIG, expected, actual);
+ SELF_CHECK (mpz_cmp (actual.val, expected.val) == 0);
+
+ store_and_read_back (ul, buf_len, BFD_ENDIAN_LITTLE, expected, actual);
+ SELF_CHECK (mpz_cmp (actual.val, expected.val) == 0);
+ }
+}
+
+/* Test the gdb_mpz::read the extremes of LONGEST and ULONGEST. */
+
+static void
+gdb_mpz_read_min_max ()
+{
+ gdb_mpz expected, actual;
+
+ /* Start with the smallest LONGEST. */
+
+ LONGEST l_min = (LONGEST) 1 << (sizeof (LONGEST) * 8 - 1);
+
+ store_and_read_back (l_min, sizeof (LONGEST), BFD_ENDIAN_BIG,
+ expected, actual);
+ SELF_CHECK (mpz_cmp (actual.val, expected.val) == 0);
+
+ store_and_read_back (l_min, sizeof (LONGEST), BFD_ENDIAN_LITTLE,
+ expected, actual);
+ SELF_CHECK (mpz_cmp (actual.val, expected.val) == 0);
+
+ /* Same with LONGEST_MAX. */
+
+ LONGEST l_max = LONGEST_MAX;
+
+ store_and_read_back (l_max, sizeof (LONGEST), BFD_ENDIAN_BIG,
+ expected, actual);
+ SELF_CHECK (mpz_cmp (actual.val, expected.val) == 0);
+
+ store_and_read_back (l_max, sizeof (LONGEST), BFD_ENDIAN_LITTLE,
+ expected, actual);
+ SELF_CHECK (mpz_cmp (actual.val, expected.val) == 0);
+
+ /* Same with the smallest ULONGEST. */
+
+ ULONGEST ul_min = 0;
+
+ store_and_read_back (ul_min, sizeof (ULONGEST), BFD_ENDIAN_BIG,
+ expected, actual);
+ SELF_CHECK (mpz_cmp (actual.val, expected.val) == 0);
+
+ store_and_read_back (ul_min, sizeof (ULONGEST), BFD_ENDIAN_LITTLE,
+ expected, actual);
+ SELF_CHECK (mpz_cmp (actual.val, expected.val) == 0);
+
+ /* Same with ULONGEST_MAX. */
+
+ ULONGEST ul_max = ULONGEST_MAX;
+
+ store_and_read_back (ul_max, sizeof (ULONGEST), BFD_ENDIAN_BIG,
+ expected, actual);
+ SELF_CHECK (mpz_cmp (actual.val, expected.val) == 0);
+
+ store_and_read_back (ul_max, sizeof (ULONGEST), BFD_ENDIAN_LITTLE,
+ expected, actual);
+ SELF_CHECK (mpz_cmp (actual.val, expected.val) == 0);
+}
+
+/* A helper function which creates a gdb_mpz object from the given
+ integer VAL, and then writes it using its gdb_mpz::write method.
+
+ The written value is then extracted from the buffer and returned,
+ for comparison with the original.
+
+ Note that this function does not perform the comparison between
+ VAL and the returned value. The caller will do it inside a SELF_CHECK
+ call, allowing the line information shown when the test fails
+ to provide a bit more information about the kind of values
+ that were used when the check failed. This makes the writing
+ of the tests a little more verbose, but the debugging in case
+ of problems should hopefuly be easier. */
+
+template<typename T>
+T
+write_and_extract (T val, int buf_len, enum bfd_endian byte_order)
+{
+ gdb_mpz v (val);
+
+ SELF_CHECK (v.as_integer<T> () == val);
+
+ gdb_byte *buf = (gdb_byte *) alloca (buf_len);
+ v.write (buf, buf_len, byte_order, !std::is_signed<T>::value);
+
+ return extract_integer<T> (buf, buf_len, byte_order);
+}
+
+/* Test the gdb_mpz::write method over a reasonable range of values.
+
+ The testing is done by picking an arbitrary buffer length, after
+ which we test every possible value that this buffer allows. */
+
+static void
+gdb_mpz_write_all_from_small ()
+{
+ int buf_len = 1;
+ LONGEST l_min = -pow (2, buf_len * 8 - 1);
+ LONGEST l_max = pow (2, buf_len * 8 - 1) - 1;
+
+ for (LONGEST l = l_min; l <= l_max; l++)
+ {
+ SELF_CHECK (write_and_extract (l, buf_len, BFD_ENDIAN_BIG) == l);
+ SELF_CHECK (write_and_extract (l, buf_len, BFD_ENDIAN_LITTLE) == l);
+ }
+
+ /* Do the same as above, but with an unsigned type. */
+ ULONGEST ul_min = 0;
+ ULONGEST ul_max = pow (2, buf_len * 8) - 1;
+
+ for (ULONGEST ul = ul_min; ul <= ul_max; ul++)
+ {
+ SELF_CHECK (write_and_extract (ul, buf_len, BFD_ENDIAN_BIG) == ul);
+ SELF_CHECK (write_and_extract (ul, buf_len, BFD_ENDIAN_LITTLE) == ul);
+ }
+}
+
+/* Test the gdb_mpz::write the extremes of LONGEST and ULONGEST. */
+
+static void
+gdb_mpz_write_min_max ()
+{
+ /* Start with the smallest LONGEST. */
+
+ LONGEST l_min = (LONGEST) 1 << (sizeof (LONGEST) * 8 - 1);
+ SELF_CHECK (write_and_extract (l_min, sizeof (LONGEST), BFD_ENDIAN_BIG)
+ == l_min);
+ SELF_CHECK (write_and_extract (l_min, sizeof (LONGEST), BFD_ENDIAN_LITTLE)
+ == l_min);
+
+ /* Same with LONGEST_MAX. */
+
+ LONGEST l_max = LONGEST_MAX;
+ SELF_CHECK (write_and_extract (l_max, sizeof (LONGEST), BFD_ENDIAN_BIG)
+ == l_max);
+ SELF_CHECK (write_and_extract (l_max, sizeof (LONGEST), BFD_ENDIAN_LITTLE)
+ == l_max);
+
+ /* Same with the smallest ULONGEST. */
+
+ ULONGEST ul_min = (ULONGEST) 1 << (sizeof (ULONGEST) * 8 - 1);
+ SELF_CHECK (write_and_extract (ul_min, sizeof (ULONGEST), BFD_ENDIAN_BIG)
+ == ul_min);
+ SELF_CHECK (write_and_extract (ul_min, sizeof (ULONGEST), BFD_ENDIAN_LITTLE)
+ == ul_min);
+
+ /* Same with ULONGEST_MAX. */
+
+ ULONGEST ul_max = ULONGEST_MAX;
+ SELF_CHECK (write_and_extract (ul_max, sizeof (ULONGEST), BFD_ENDIAN_BIG)
+ == ul_max);
+ SELF_CHECK (write_and_extract (ul_max, sizeof (ULONGEST), BFD_ENDIAN_LITTLE)
+ == ul_max);
+}
+
+/* A helper function which stores the signed number, the unscaled value
+ of a fixed point object, into a buffer, and then uses gdb_mpq's
+ read_fixed_point to read it as a fixed_point value, with
+ the given parameters.
+
+ EXPECTED is set to the value we expected to get after the call
+ to read_fixed_point. ACTUAL is the value we actually do get.
+
+ Note that this function does not perform the comparison between
+ EXPECTED and ACTUAL. The caller will do it inside a SELF_CHECK
+ call, allowing the line information shown when the test fails
+ to provide a bit more information about the kind of values
+ that were used when the check failed. This makes the writing
+ of the tests a little more verbose, but the debugging in case
+ of problems should hopefuly be easier. */
+
+static void
+read_fp_test (int unscaled, const gdb_mpq &scaling_factor,
+ enum bfd_endian byte_order,
+ gdb_mpq &expected, gdb_mpq &actual)
+{
+ /* For this kind of testing, we'll use a buffer the same size as
+ our unscaled parameter. */
+ const int len = sizeof (unscaled);
+ gdb_byte buf[len];
+ store_signed_integer (buf, len, byte_order, unscaled);
+
+ actual.read_fixed_point (buf, len, byte_order, 0, scaling_factor);
+
+ mpq_set_si (expected.val, unscaled, 1);
+ mpq_mul (expected.val, expected.val, scaling_factor.val);
+}
+
+/* Perform various tests of the gdb_mpq::read_fixed_point method. */
+
+static void
+gdb_mpq_read_fixed_point ()
+{
+ gdb_mpq expected, actual;
+ gdb_mpq scaling_factor;
+
+ /* Pick an arbitrary scaling_factor; this operation is trivial enough
+ thanks to GMP that the value we use isn't really important. */
+ mpq_set_ui (scaling_factor.val, 3, 5);
+
+ /* Try a few values, both negative and positive... */
+
+ read_fp_test (-256, scaling_factor, BFD_ENDIAN_BIG, expected, actual);
+ SELF_CHECK (mpq_cmp (actual.val, expected.val) == 0);
+ read_fp_test (-256, scaling_factor, BFD_ENDIAN_LITTLE, expected, actual);
+ SELF_CHECK (mpq_cmp (actual.val, expected.val) == 0);
+
+ read_fp_test (-1, scaling_factor, BFD_ENDIAN_BIG, expected, actual);
+ SELF_CHECK (mpq_cmp (actual.val, expected.val) == 0);
+ read_fp_test (-1, scaling_factor, BFD_ENDIAN_LITTLE, expected, actual);
+ SELF_CHECK (mpq_cmp (actual.val, expected.val) == 0);
+
+ read_fp_test (0, scaling_factor, BFD_ENDIAN_BIG, expected, actual);
+ SELF_CHECK (mpq_cmp (actual.val, expected.val) == 0);
+ read_fp_test (0, scaling_factor, BFD_ENDIAN_LITTLE, expected, actual);
+ SELF_CHECK (mpq_cmp (actual.val, expected.val) == 0);
+
+ read_fp_test (1, scaling_factor, BFD_ENDIAN_BIG, expected, actual);
+ SELF_CHECK (mpq_cmp (actual.val, expected.val) == 0);
+ read_fp_test (1, scaling_factor, BFD_ENDIAN_LITTLE, expected, actual);
+ SELF_CHECK (mpq_cmp (actual.val, expected.val) == 0);
+
+ read_fp_test (1025, scaling_factor, BFD_ENDIAN_BIG, expected, actual);
+ SELF_CHECK (mpq_cmp (actual.val, expected.val) == 0);
+ read_fp_test (1025, scaling_factor, BFD_ENDIAN_LITTLE, expected, actual);
+ SELF_CHECK (mpq_cmp (actual.val, expected.val) == 0);
+}
+
+/* A helper function which builds a gdb_mpq object from the given
+ NUMERATOR and DENOMINATOR, and then calls gdb_mpq's write_fixed_point
+ method to write it to a buffer.
+
+ The value written into the buffer is then read back as is,
+ and returned. */
+
+static LONGEST
+write_fp_test (int numerator, unsigned int denominator,
+ const gdb_mpq &scaling_factor,
+ enum bfd_endian byte_order)
+{
+ /* For this testing, we'll use a buffer the size of LONGEST.
+ This is really an arbitrary decision, as long as the buffer
+ is long enough to hold the unscaled values that we'll be
+ writing. */
+ const int len = sizeof (LONGEST);
+ gdb_byte buf[len];
+ memset (buf, 0, len);
+
+ gdb_mpq v;
+ mpq_set_ui (v.val, numerator, denominator);
+ mpq_canonicalize (v.val);
+ v.write_fixed_point (buf, len, byte_order, 0, scaling_factor);
+
+ return extract_unsigned_integer (buf, len, byte_order);
+}
+
+/* Perform various tests of the gdb_mpq::write_fixed_point method. */
+
+static void
+gdb_mpq_write_fixed_point ()
+{
+ /* Pick an arbitrary factor; this operations is sufficiently trivial
+ with the use of GMP that the value of this factor is not really
+ all that important. */
+ gdb_mpq scaling_factor;
+ mpq_set_ui (scaling_factor.val, 1, 3);
+
+ gdb_mpq vq;
+
+ /* Try a few multiples of the scaling factor, both negative,
+ and positive... */
+
+ SELF_CHECK (write_fp_test (-8, 1, scaling_factor, BFD_ENDIAN_BIG) == -24);
+ SELF_CHECK (write_fp_test (-8, 1, scaling_factor, BFD_ENDIAN_LITTLE) == -24);
+
+ SELF_CHECK (write_fp_test (-2, 3, scaling_factor, BFD_ENDIAN_BIG) == -2);
+ SELF_CHECK (write_fp_test (-2, 3, scaling_factor, BFD_ENDIAN_LITTLE) == -2);
+
+ SELF_CHECK (write_fp_test (0, 3, scaling_factor, BFD_ENDIAN_BIG) == 0);
+ SELF_CHECK (write_fp_test (0, 3, scaling_factor, BFD_ENDIAN_LITTLE) == 0);
+
+ SELF_CHECK (write_fp_test (5, 3, scaling_factor, BFD_ENDIAN_BIG) == 5);
+ SELF_CHECK (write_fp_test (5, 3, scaling_factor, BFD_ENDIAN_LITTLE) == 5);
+}
+
+}
+
+void _initialize_gmp_utils_selftests ();
+
+void
+_initialize_gmp_utils_selftests ()
+{
+ selftests::register_test ("gdb_mpz_as_integer",
+ selftests::gdb_mpz_as_integer);
+ selftests::register_test ("gdb_mpz_read_all_from_small",
+ selftests::gdb_mpz_read_all_from_small);
+ selftests::register_test ("gdb_mpz_read_min_max",
+ selftests::gdb_mpz_read_min_max);
+ selftests::register_test ("gdb_mpz_write_all_from_small",
+ selftests::gdb_mpz_write_all_from_small);
+ selftests::register_test ("gdb_mpz_write_min_max",
+ selftests::gdb_mpz_write_min_max);
+ selftests::register_test ("gdb_mpq_read_fixed_point",
+ selftests::gdb_mpq_read_fixed_point);
+ selftests::register_test ("gdb_mpq_write_fixed_point",
+ selftests::gdb_mpq_write_fixed_point);
+}
--
2.1.4
^ permalink raw reply [flat|nested] 140+ messages in thread
* [pushed/v2 4/9] Move uinteger_pow gdb/valarith.c to gdb/utils.c and make it public
2020-11-15 8:35 ` pushed: " Joel Brobecker
` (2 preceding siblings ...)
2020-11-15 8:35 ` [pushed/v2 3/9] gmp-utils: New API to simply use of GMP's integer/rational/float objects Joel Brobecker
@ 2020-11-15 8:35 ` Joel Brobecker
2020-11-15 8:35 ` [pushed/v2 5/9] Add support for printing value of DWARF-based fixed-point type objects Joel Brobecker
` (7 subsequent siblings)
11 siblings, 0 replies; 140+ messages in thread
From: Joel Brobecker @ 2020-11-15 8:35 UTC (permalink / raw)
To: gdb-patches; +Cc: Simon Marchi, Joel Brobecker
This is a generic function which I would like to use in a followup
patch adding support for fixed-point types. So this commit moves it
out of valarith.c into util.c, and makes it non-static.
gdb/ChangeLog:
* utils.h (uinteger_pow): Add declaration.
* utils.c (uinteger_pow): Moved here (without changes)...
* valarith.c (uinteger_pow): ... from here.
---
gdb/ChangeLog | 6 ++++++
gdb/utils.c | 30 ++++++++++++++++++++++++++++++
gdb/utils.h | 7 +++++++
gdb/valarith.c | 31 -------------------------------
4 files changed, 43 insertions(+), 31 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a029109..5aacbf0 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,11 @@
2020-11-15 Joel Brobecker <brobecker@adacore.com>
+ * utils.h (uinteger_pow): Add declaration.
+ * utils.c (uinteger_pow): Moved here (without changes)...
+ * valarith.c (uinteger_pow): ... from here.
+
+2020-11-15 Joel Brobecker <brobecker@adacore.com>
+
* gmp-utils.h, gmp-utils.h: New file.
* unittests/gmp-utils-selftests.c: New file.
* Makefile.in (SUBDIR_UNITTESTS_SRCS): Add
diff --git a/gdb/utils.c b/gdb/utils.c
index ab931c3..3226656 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -709,6 +709,36 @@ myread (int desc, char *addr, int len)
return orglen;
}
+/* See utils.h. */
+
+ULONGEST
+uinteger_pow (ULONGEST v1, LONGEST v2)
+{
+ if (v2 < 0)
+ {
+ if (v1 == 0)
+ error (_("Attempt to raise 0 to negative power."));
+ else
+ return 0;
+ }
+ else
+ {
+ /* The Russian Peasant's Algorithm. */
+ ULONGEST v;
+
+ v = 1;
+ for (;;)
+ {
+ if (v2 & 1L)
+ v *= v1;
+ v2 >>= 1;
+ if (v2 == 0)
+ return v;
+ v1 *= v1;
+ }
+ }
+}
+
void
print_spaces (int n, struct ui_file *file)
{
diff --git a/gdb/utils.h b/gdb/utils.h
index 6948908..a8c65ed 100644
--- a/gdb/utils.h
+++ b/gdb/utils.h
@@ -593,6 +593,13 @@ extern pid_t wait_to_die_with_timeout (pid_t pid, int *status, int timeout);
extern int myread (int, char *, int);
+/* Integer exponentiation: Return V1**V2, where both arguments
+ are integers.
+
+ Requires V1 != 0 if V2 < 0.
+ Returns 1 for 0 ** 0. */
+extern ULONGEST uinteger_pow (ULONGEST v1, LONGEST v2);
+
/* Resource limits used by getrlimit and setrlimit. */
enum resource_limit_kind
diff --git a/gdb/valarith.c b/gdb/valarith.c
index 21b597a..f6caf3d 100644
--- a/gdb/valarith.c
+++ b/gdb/valarith.c
@@ -819,37 +819,6 @@ integer_pow (LONGEST v1, LONGEST v2)
}
}
-/* Integer exponentiation: V1**V2, where both arguments are
- integers. Requires V1 != 0 if V2 < 0. Returns 1 for 0 ** 0. */
-
-static ULONGEST
-uinteger_pow (ULONGEST v1, LONGEST v2)
-{
- if (v2 < 0)
- {
- if (v1 == 0)
- error (_("Attempt to raise 0 to negative power."));
- else
- return 0;
- }
- else
- {
- /* The Russian Peasant's Algorithm. */
- ULONGEST v;
-
- v = 1;
- for (;;)
- {
- if (v2 & 1L)
- v *= v1;
- v2 >>= 1;
- if (v2 == 0)
- return v;
- v1 *= v1;
- }
- }
-}
-
/* Obtain argument values for binary operation, converting from
other types if one of them is not floating point. */
static void
--
2.1.4
^ permalink raw reply [flat|nested] 140+ messages in thread
* [pushed/v2 5/9] Add support for printing value of DWARF-based fixed-point type objects
2020-11-15 8:35 ` pushed: " Joel Brobecker
` (3 preceding siblings ...)
2020-11-15 8:35 ` [pushed/v2 4/9] Move uinteger_pow gdb/valarith.c to gdb/utils.c and make it public Joel Brobecker
@ 2020-11-15 8:35 ` Joel Brobecker
2020-11-15 8:35 ` [pushed/v2 6/9] fix printing of DWARF fixed-point type objects with format modifier Joel Brobecker
` (6 subsequent siblings)
11 siblings, 0 replies; 140+ messages in thread
From: Joel Brobecker @ 2020-11-15 8:35 UTC (permalink / raw)
To: gdb-patches; +Cc: Simon Marchi, Joel Brobecker
This commit introduces a new kind of type, meant to describe
fixed-point types, using a new code added specifically for
this purpose (TYPE_CODE_FIXED_POINT).
It then adds handling of fixed-point base types in the DWARF reader.
And finally, as a first step, this commit adds support for printing
the value of fixed-point type objects.
Note that this commit has a known issue: Trying to print the value
of a fixed-point object with a format letter (e.g. "print /x NAME")
causes the wrong value to be printed because the scaling factor
is not applied. Since the fix for this issue is isolated, and
this is not a regression, the fix will be made in a pach of its own.
This is meant to simplify review and archeology.
Also, other functionalities related to fixed-point type handling
(ptype, arithmetics, etc), will be added piecemeal as well, for
the same reasons (faciliate reviews and archeology). Related to this,
the testcase gdb.ada/fixed_cmp.exp is adjusted to compile the test
program with -fgnat-encodings=all, so as to force the use of GNAT
encodings, rather than rely on the compiler's default to use them.
The intent is to enhance this testcase to also test the pure DWARF
approach using -fgnat-encodings=minimal as soon as the corresponding
suport gets added in. Thus, the modification to the testcase is made
in a way that it prepares this testcase to be tested in both modes.
gdb/ChangeLog:
* ada-valprint.c (ada_value_print_1): Add fixed-point type handling.
* dwarf2/read.c (get_dwarf2_rational_constant)
(get_dwarf2_unsigned_rational_constant, finish_fixed_point_type)
(has_zero_over_zero_small_attribute): New functions.
read_base_type, set_die_type): Add fixed-point type handling.
* gdb-gdb.py.in: Add fixed-point type handling.
* gdbtypes.c: #include "gmp-utils.h".
(create_range_type, set_type_code): Add fixed-point type handling.
(init_fixed_point_type): New function.
(is_integral_type, is_scalar_type): Add fixed-point type handling.
(print_fixed_point_type_info): New function.
(recursive_dump_type, copy_type_recursive): Add fixed-point type
handling.
(fixed_point_type_storage): New typedef.
(fixed_point_objfile_key): New static global.
(allocate_fixed_point_type_info, is_fixed_point_type): New functions.
(fixed_point_type_base_type, fixed_point_scaling_factor): New
functions.
* gdbtypes.h: #include "gmp-utils.h".
(enum type_code) <TYPE_SPECIFIC_FIXED_POINT>: New enum.
(union type_specific) <fixed_point_info>: New field.
(struct fixed_point_type_info): New struct.
(INIT_FIXED_POINT_SPECIFIC, TYPE_FIXED_POINT_INFO): New macros.
(init_fixed_point_type, is_fixed_point_type)
(fixed_point_type_base_type, fixed_point_scaling_factor)
(allocate_fixed_point_type_info): Add declarations.
* valprint.c (generic_val_print_fixed_point): New function.
(generic_value_print): Add fixed-point type handling.
* value.c (value_as_address, unpack_long): Add fixed-point type
handling.
gdb/testsuite/ChangeLog:
* gdb.ada/fixed_cmp.exp: Force compilation to use -fgnat-encodings=all.
* gdb.ada/fixed_points.exp: Add fixed-point variables printing tests.
* gdb.ada/fixed_points/pck.ads, gdb.ada/fixed_points/pck.adb:
New files.
* gdb.ada/fixed_points/fixed_points.adb: Add use of package Pck.
* gdb.dwarf2/dw2-fixed-point.c, gdb.dwarf2/dw2-fixed-point.exp:
New files.
---
gdb/ChangeLog | 33 ++++
gdb/ada-valprint.c | 3 +
gdb/dwarf2/read.c | 211 +++++++++++++++++++++
gdb/gdb-gdb.py.in | 5 +
gdb/gdbtypes.c | 133 ++++++++++++-
gdb/gdbtypes.h | 53 +++++-
gdb/testsuite/ChangeLog | 11 ++
gdb/testsuite/gdb.ada/fixed_cmp.exp | 34 ++--
gdb/testsuite/gdb.ada/fixed_points.exp | 11 ++
.../gdb.ada/fixed_points/fixed_points.adb | 4 +
gdb/testsuite/gdb.ada/fixed_points/pck.adb | 22 +++
gdb/testsuite/gdb.ada/fixed_points/pck.ads | 30 +++
gdb/testsuite/gdb.dwarf2/dw2-fixed-point.c | 49 +++++
gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp | 132 +++++++++++++
gdb/valprint.c | 33 ++++
gdb/value.c | 14 ++
16 files changed, 760 insertions(+), 18 deletions(-)
create mode 100644 gdb/testsuite/gdb.ada/fixed_points/pck.adb
create mode 100644 gdb/testsuite/gdb.ada/fixed_points/pck.ads
create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-fixed-point.c
create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 5aacbf0..16905ac 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,38 @@
2020-11-15 Joel Brobecker <brobecker@adacore.com>
+ * ada-valprint.c (ada_value_print_1): Add fixed-point type handling.
+ * dwarf2/read.c (get_dwarf2_rational_constant)
+ (get_dwarf2_unsigned_rational_constant, finish_fixed_point_type)
+ (has_zero_over_zero_small_attribute): New functions.
+ read_base_type, set_die_type): Add fixed-point type handling.
+ * gdb-gdb.py.in: Add fixed-point type handling.
+ * gdbtypes.c: #include "gmp-utils.h".
+ (create_range_type, set_type_code): Add fixed-point type handling.
+ (init_fixed_point_type): New function.
+ (is_integral_type, is_scalar_type): Add fixed-point type handling.
+ (print_fixed_point_type_info): New function.
+ (recursive_dump_type, copy_type_recursive): Add fixed-point type
+ handling.
+ (fixed_point_type_storage): New typedef.
+ (fixed_point_objfile_key): New static global.
+ (allocate_fixed_point_type_info, is_fixed_point_type): New functions.
+ (fixed_point_type_base_type, fixed_point_scaling_factor): New
+ functions.
+ * gdbtypes.h: #include "gmp-utils.h".
+ (enum type_code) <TYPE_SPECIFIC_FIXED_POINT>: New enum.
+ (union type_specific) <fixed_point_info>: New field.
+ (struct fixed_point_type_info): New struct.
+ (INIT_FIXED_POINT_SPECIFIC, TYPE_FIXED_POINT_INFO): New macros.
+ (init_fixed_point_type, is_fixed_point_type)
+ (fixed_point_type_base_type, fixed_point_scaling_factor)
+ (allocate_fixed_point_type_info): Add declarations.
+ * valprint.c (generic_val_print_fixed_point): New function.
+ (generic_value_print): Add fixed-point type handling.
+ * value.c (value_as_address, unpack_long): Add fixed-point type
+ handling.
+
+2020-11-15 Joel Brobecker <brobecker@adacore.com>
+
* utils.h (uinteger_pow): Add declaration.
* utils.c (uinteger_pow): Moved here (without changes)...
* valarith.c (uinteger_pow): ... from here.
diff --git a/gdb/ada-valprint.c b/gdb/ada-valprint.c
index d7704f0..482069a 100644
--- a/gdb/ada-valprint.c
+++ b/gdb/ada-valprint.c
@@ -1027,6 +1027,9 @@ ada_value_print_1 (struct value *val, struct ui_file *stream, int recurse,
deprecated_set_value_type (val, type);
}
+ if (is_fixed_point_type (type))
+ type = fixed_point_type_base_type (type);
+
switch (type->code ())
{
default:
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 1b43fc8..3c5982629 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -18092,6 +18092,157 @@ read_typedef (struct die_info *die, struct dwarf2_cu *cu)
return this_type;
}
+/* Assuming DIE is a rational DW_TAG_constant, read the DIE's
+ numerator and denominator into NUMERATOR and DENOMINATOR (resp).
+
+ If the numerator and/or numerator attribute is missing,
+ a complaint is filed, and NUMERATOR and DENOMINATOR are left
+ untouched. */
+
+static void
+get_dwarf2_rational_constant (struct die_info *die, struct dwarf2_cu *cu,
+ LONGEST *numerator, LONGEST *denominator)
+{
+ struct attribute *num_attr, *denom_attr;
+
+ num_attr = dwarf2_attr (die, DW_AT_GNU_numerator, cu);
+ if (num_attr == nullptr)
+ complaint (_("DW_AT_GNU_numerator missing in %s DIE at %s"),
+ dwarf_tag_name (die->tag), sect_offset_str (die->sect_off));
+
+ denom_attr = dwarf2_attr (die, DW_AT_GNU_denominator, cu);
+ if (denom_attr == nullptr)
+ complaint (_("DW_AT_GNU_denominator missing in %s DIE at %s"),
+ dwarf_tag_name (die->tag), sect_offset_str (die->sect_off));
+
+ if (num_attr == nullptr || denom_attr == nullptr)
+ return;
+
+ *numerator = num_attr->constant_value (1);
+ *denominator = denom_attr->constant_value (1);
+}
+
+/* Same as get_dwarf2_rational_constant, but extracting an unsigned
+ rational constant, rather than a signed one.
+
+ If the rational constant has a negative value, a complaint
+ is filed, and NUMERATOR and DENOMINATOR are left untouched. */
+
+static void
+get_dwarf2_unsigned_rational_constant (struct die_info *die,
+ struct dwarf2_cu *cu,
+ ULONGEST *numerator,
+ ULONGEST *denominator)
+{
+ LONGEST num = 1, denom = 1;
+
+ get_dwarf2_rational_constant (die, cu, &num, &denom);
+ if (num < 0 && denom < 0)
+ {
+ num = -num;
+ denom = -denom;
+ }
+ else if (num < 0)
+ {
+ complaint (_("unexpected negative value for DW_AT_GNU_numerator"
+ " in DIE at %s"),
+ sect_offset_str (die->sect_off));
+ return;
+ }
+ else if (denom < 0)
+ {
+ complaint (_("unexpected negative value for DW_AT_GNU_denominator"
+ " in DIE at %s"),
+ sect_offset_str (die->sect_off));
+ return;
+ }
+
+ *numerator = num;
+ *denominator = denom;
+}
+
+/* Assuming DIE corresponds to a fixed point type, finish the creation
+ of the corresponding TYPE by setting its TYPE_FIXED_POINT_INFO.
+ CU is the DIE's CU. */
+
+static void
+finish_fixed_point_type (struct type *type, struct die_info *die,
+ struct dwarf2_cu *cu)
+{
+ struct attribute *attr;
+ /* Numerator and denominator of our fixed-point type's scaling factor.
+ The default is a scaling factor of 1, which we use as a fallback
+ when we are not able to decode it (problem with the debugging info,
+ unsupported forms, bug in GDB, etc...). Using that as the default
+ allows us to at least print the unscaled value, which might still
+ be useful to a user. */
+ ULONGEST scale_num = 1;
+ ULONGEST scale_denom = 1;
+
+ gdb_assert (type->code () == TYPE_CODE_FIXED_POINT
+ && TYPE_SPECIFIC_FIELD (type) == TYPE_SPECIFIC_FIXED_POINT);
+
+ attr = dwarf2_attr (die, DW_AT_binary_scale, cu);
+ if (!attr)
+ attr = dwarf2_attr (die, DW_AT_decimal_scale, cu);
+ if (!attr)
+ attr = dwarf2_attr (die, DW_AT_small, cu);
+
+ if (attr == nullptr)
+ {
+ /* Scaling factor not found. Assume a scaling factor of 1,
+ and hope for the best. At least the user will be able to see
+ the encoded value. */
+ complaint (_("no scale found for fixed-point type (DIE at %s)"),
+ sect_offset_str (die->sect_off));
+ }
+ else if (attr->name == DW_AT_binary_scale)
+ {
+ LONGEST scale_exp = attr->constant_value (0);
+ ULONGEST *num_or_denom = scale_exp > 0 ? &scale_num : &scale_denom;
+
+ *num_or_denom = 1 << abs (scale_exp);
+ }
+ else if (attr->name == DW_AT_decimal_scale)
+ {
+ LONGEST scale_exp = attr->constant_value (0);
+ ULONGEST *num_or_denom = scale_exp > 0 ? &scale_num : &scale_denom;
+
+ *num_or_denom = uinteger_pow (10, abs (scale_exp));
+ }
+ else if (attr->name == DW_AT_small)
+ {
+ struct die_info *scale_die;
+ struct dwarf2_cu *scale_cu = cu;
+
+ scale_die = follow_die_ref (die, attr, &scale_cu);
+ if (scale_die->tag == DW_TAG_constant)
+ get_dwarf2_unsigned_rational_constant (scale_die, scale_cu,
+ &scale_num, &scale_denom);
+ else
+ complaint (_("%s DIE not supported as target of DW_AT_small attribute"
+ " (DIE at %s)"),
+ dwarf_tag_name (die->tag), sect_offset_str (die->sect_off));
+ }
+ else
+ {
+ complaint (_("unsupported scale attribute %s for fixed-point type"
+ " (DIE at %s)"),
+ dwarf_attr_name (attr->name),
+ sect_offset_str (die->sect_off));
+ }
+
+ gdb_mpq &scaling_factor = TYPE_FIXED_POINT_INFO (type)->scaling_factor;
+
+ gdb_mpz tmp_z (scale_num);
+ mpz_set (mpq_numref (scaling_factor.val), tmp_z.val);
+
+ tmp_z = scale_denom;
+ mpz_set (mpq_denref (scaling_factor.val), tmp_z.val);
+
+ mpq_canonicalize (scaling_factor.val);
+}
+
/* Allocate a floating-point type of size BITS and name NAME. Pass NAME_HINT
(which may be different from NAME) to the architecture back-end to allow
it to guess the correct format if necessary. */
@@ -18133,6 +18284,32 @@ dwarf2_init_integer_type (struct dwarf2_cu *cu, struct objfile *objfile,
return type;
}
+/* Return true if DIE has a DW_AT_small attribute whose value is
+ a constant rational, where both the numerator and denominator
+ are equal to zero.
+
+ CU is the DIE's Compilation Unit. */
+
+static bool
+has_zero_over_zero_small_attribute (struct die_info *die,
+ struct dwarf2_cu *cu)
+{
+ struct attribute *attr = dwarf2_attr (die, DW_AT_small, cu);
+ if (attr == nullptr)
+ return false;
+
+ struct dwarf2_cu *scale_cu = cu;
+ struct die_info *scale_die
+ = follow_die_ref (die, attr, &scale_cu);
+
+ if (scale_die->tag != DW_TAG_constant)
+ return false;
+
+ LONGEST num = 1, denom = 1;
+ get_dwarf2_rational_constant (scale_die, cu, &num, &denom);
+ return (num == 0 && denom == 0);
+}
+
/* Initialise and return a floating point type of size BITS suitable for
use as a component of a complex number. The NAME_HINT is passed through
when initialising the floating point type and is the name of the complex
@@ -18243,6 +18420,31 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
}
}
+ if ((encoding == DW_ATE_signed_fixed || encoding == DW_ATE_unsigned_fixed)
+ && cu->language == language_ada
+ && has_zero_over_zero_small_attribute (die, cu))
+ {
+ /* brobecker/2018-02-24: This is a fixed point type for which
+ the scaling factor is represented as fraction whose value
+ does not make sense (zero divided by zero), so we should
+ normally never see these. However, there is a small category
+ of fixed point types for which GNAT is unable to provide
+ the scaling factor via the standard DWARF mechanisms, and
+ for which the info is provided via the GNAT encodings instead.
+ This is likely what this DIE is about.
+
+ Ideally, GNAT should be declaring this type the same way
+ it declares other fixed point types when using the legacy
+ GNAT encoding, which is to use a simple signed or unsigned
+ base type. A report to the GNAT team has been created to
+ look into it. In the meantime, pretend this type is a simple
+ signed or unsigned integral, rather than a fixed point type,
+ to avoid any confusion later on as to how to process this type. */
+ encoding = (encoding == DW_ATE_signed_fixed
+ ? DW_ATE_signed
+ : DW_ATE_unsigned);
+ }
+
switch (encoding)
{
case DW_ATE_address:
@@ -18319,6 +18521,14 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
return set_die_type (die, type, cu);
}
break;
+ case DW_ATE_signed_fixed:
+ type = init_fixed_point_type (objfile, bits, 0, name);
+ finish_fixed_point_type (type, die, cu);
+ break;
+ case DW_ATE_unsigned_fixed:
+ type = init_fixed_point_type (objfile, bits, 1, name);
+ finish_fixed_point_type (type, die, cu);
+ break;
default:
complaint (_("unsupported DW_AT_encoding: '%s'"),
@@ -24751,6 +24961,7 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
&& type->code () != TYPE_CODE_METHODPTR
&& type->code () != TYPE_CODE_MEMBERPTR
&& type->code () != TYPE_CODE_METHOD
+ && type->code () != TYPE_CODE_FIXED_POINT
&& !HAVE_GNAT_AUX_INFO (type))
INIT_GNAT_SPECIFIC (type);
diff --git a/gdb/gdb-gdb.py.in b/gdb/gdb-gdb.py.in
index 6594ac1..ff68bd7 100644
--- a/gdb/gdb-gdb.py.in
+++ b/gdb/gdb-gdb.py.in
@@ -229,6 +229,11 @@ class StructMainTypePrettyPrinter:
# tail_call_list is not printed.
elif type_specific_kind == "TYPE_SPECIFIC_SELF_TYPE":
img = "self_type = %s" % type_specific['self_type']
+ elif type_specific_kind == "TYPE_SPECIFIC_FIXED_POINT":
+ # The scaling factor is an opaque structure, so we cannot
+ # decode its value from Python (not without insider knowledge).
+ img = ('scaling_factor: <opaque> (call __gmpz_dump with '
+ ' _mp_num and _mp_den fields if needed)')
else:
img = ("type_specific = ??? (unknown type_secific_kind: %s)"
% type_specific_kind)
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 686edaf..2f92887 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -40,6 +40,7 @@
#include "gdbcore.h"
#include "floatformat.h"
#include <algorithm>
+#include "gmp-utils.h"
/* Initialize BADNESS constants. */
@@ -950,6 +951,8 @@ create_range_type (struct type *result_type, struct type *index_type,
result_type->set_bounds (bounds);
+ if (index_type->code () == TYPE_CODE_FIXED_POINT)
+ result_type->set_is_unsigned (index_type->is_unsigned ());
/* Note that the signed-ness of a range type can't simply be copied
from the underlying type. Consider a case where the underlying
type is 'int', but the range type can hold 0..65535, and where
@@ -957,7 +960,7 @@ create_range_type (struct type *result_type, struct type *index_type,
case, if we copy the underlying type's sign, then reading some
range values will cause an unwanted sign extension. So, we have
some heuristics here instead. */
- if (low_bound->kind () == PROP_CONST && low_bound->const_val () >= 0)
+ else if (low_bound->kind () == PROP_CONST && low_bound->const_val () >= 0)
result_type->set_is_unsigned (true);
/* Ada allows the declaration of range types whose upper bound is
less than the lower bound, so checking the lower bound is not
@@ -3136,6 +3139,9 @@ set_type_code (struct type *type, enum type_code code)
break;
case TYPE_CODE_FUNC:
INIT_FUNC_SPECIFIC (type);
+ break;
+ case TYPE_CODE_FIXED_POINT:
+ INIT_FIXED_POINT_SPECIFIC (type);
break;
}
}
@@ -3352,6 +3358,24 @@ init_pointer_type (struct objfile *objfile,
return t;
}
+/* Allocate a TYPE_CODE_FIXED_POINT type structure associated with OBJFILE.
+ BIT is the pointer type size in bits.
+ UNSIGNED_P should be nonzero if the type is unsigned.
+ NAME is the type name. */
+
+struct type *
+init_fixed_point_type (struct objfile *objfile,
+ int bit, int unsigned_p, const char *name)
+{
+ struct type *t;
+
+ t = init_type (objfile, TYPE_CODE_FIXED_POINT, bit, name);
+ if (unsigned_p)
+ t->set_is_unsigned (true);
+
+ return t;
+}
+
/* See gdbtypes.h. */
unsigned
@@ -3498,6 +3522,7 @@ is_integral_type (struct type *t)
t = check_typedef (t);
return
((t != NULL)
+ && !is_fixed_point_type (t)
&& ((t->code () == TYPE_CODE_INT)
|| (t->code () == TYPE_CODE_ENUM)
|| (t->code () == TYPE_CODE_FLAGS)
@@ -3523,6 +3548,9 @@ is_scalar_type (struct type *type)
{
type = check_typedef (type);
+ if (is_fixed_point_type (type))
+ return 0; /* Implemented as a scalar, but more like a floating point. */
+
switch (type->code ())
{
case TYPE_CODE_ARRAY:
@@ -4887,6 +4915,16 @@ print_gnat_stuff (struct type *type, int spaces)
}
}
+/* Print the contents of the TYPE's type_specific union, assuming that
+ its type-specific kind is TYPE_SPECIFIC_FIXED_POINT. */
+
+static void
+print_fixed_point_type_info (struct type *type, int spaces)
+{
+ printfi_filtered (spaces + 2, "scaling factor: %s\n",
+ fixed_point_scaling_factor (type).str ().get ());
+}
+
static struct obstack dont_print_type_obstack;
/* Print the dynamic_prop PROP. */
@@ -5025,6 +5063,9 @@ recursive_dump_type (struct type *type, int spaces)
case TYPE_CODE_NAMESPACE:
printf_filtered ("(TYPE_CODE_NAMESPACE)");
break;
+ case TYPE_CODE_FIXED_POINT:
+ printf_filtered ("(TYPE_CODE_FIXED_POINT)");
+ break;
default:
printf_filtered ("(UNKNOWN TYPE CODE)");
break;
@@ -5217,6 +5258,12 @@ recursive_dump_type (struct type *type, int spaces)
puts_filtered ("\n");
break;
+ case TYPE_SPECIFIC_FIXED_POINT:
+ printfi_filtered (spaces, "fixed_point_info ");
+ print_fixed_point_type_info (type, spaces);
+ puts_filtered ("\n");
+ break;
+
case TYPE_SPECIFIC_INT:
if (type->bit_size_differs_p ())
{
@@ -5449,6 +5496,11 @@ copy_type_recursive (struct objfile *objfile,
copy_type_recursive (objfile, TYPE_SELF_TYPE (type),
copied_types));
break;
+ case TYPE_SPECIFIC_FIXED_POINT:
+ INIT_FIXED_POINT_SPECIFIC (new_type);
+ TYPE_FIXED_POINT_INFO (new_type)->scaling_factor
+ = TYPE_FIXED_POINT_INFO (type)->scaling_factor;
+ break;
case TYPE_SPECIFIC_INT:
TYPE_SPECIFIC_FIELD (new_type) = TYPE_SPECIFIC_INT;
TYPE_MAIN_TYPE (new_type)->type_specific.int_stuff
@@ -5752,6 +5804,85 @@ append_composite_type_field (struct type *t, const char *name,
append_composite_type_field_aligned (t, name, field, 0);
}
+\f
+
+/* We manage the lifetimes of fixed_point_type_info objects by
+ attaching them to the objfile. Currently, these objects are
+ modified during construction, and GMP does not provide a way to
+ hash the contents of an mpq_t; so it's a bit of a pain to hash-cons
+ them. If we did do this, they could be moved to the per-BFD and
+ shared across objfiles. */
+typedef std::vector<std::unique_ptr<fixed_point_type_info>>
+ fixed_point_type_storage;
+
+/* Key used for managing the storage of fixed-point type info. */
+static const struct objfile_key<fixed_point_type_storage>
+ fixed_point_objfile_key;
+
+/* See gdbtypes.h. */
+
+fixed_point_type_info *
+allocate_fixed_point_type_info (struct type *type)
+{
+ std::unique_ptr<fixed_point_type_info> up (new fixed_point_type_info);
+ fixed_point_type_info *result;
+
+ if (TYPE_OBJFILE_OWNED (type))
+ {
+ fixed_point_type_storage *storage
+ = fixed_point_objfile_key.get (TYPE_OBJFILE (type));
+ if (storage == nullptr)
+ storage = fixed_point_objfile_key.emplace (TYPE_OBJFILE (type));
+ result = up.get ();
+ storage->push_back (std::move (up));
+ }
+ else
+ {
+ /* We just leak the memory, because that's what we do generally
+ for non-objfile-attached types. */
+ result = up.release ();
+ }
+
+ return result;
+}
+
+/* See gdbtypes.h. */
+
+bool
+is_fixed_point_type (struct type *type)
+{
+ while (check_typedef (type)->code () == TYPE_CODE_RANGE)
+ type = TYPE_TARGET_TYPE (check_typedef (type));
+ type = check_typedef (type);
+
+ return type->code () == TYPE_CODE_FIXED_POINT;
+}
+
+/* See gdbtypes.h. */
+
+struct type *
+fixed_point_type_base_type (struct type *type)
+{
+ while (check_typedef (type)->code () == TYPE_CODE_RANGE)
+ type = TYPE_TARGET_TYPE (check_typedef (type));
+ type = check_typedef (type);
+
+ gdb_assert (type->code () == TYPE_CODE_FIXED_POINT);
+ return type;
+}
+
+/* See gdbtypes.h. */
+
+const gdb_mpq &
+fixed_point_scaling_factor (struct type *type)
+{
+ type = fixed_point_type_base_type (type);
+
+ return TYPE_FIXED_POINT_INFO (type)->scaling_factor;
+}
+
+\f
+
static struct gdbarch_data *gdbtypes_data;
const struct builtin_type *
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 4d574e2..5f9ac27 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -52,6 +52,7 @@
#include "gdbsupport/print-utils.h"
#include "dwarf2.h"
#include "gdb_obstack.h"
+#include "gmp-utils.h"
/* Forward declarations for prototypes. */
struct field;
@@ -189,7 +190,10 @@ enum type_code
TYPE_CODE_INTERNAL_FUNCTION,
/* * Methods implemented in extension languages. */
- TYPE_CODE_XMETHOD
+ TYPE_CODE_XMETHOD,
+
+ /* * Fixed Point type. */
+ TYPE_CODE_FIXED_POINT,
};
/* * Some bits for the type's instance_flags word. See the macros
@@ -600,7 +604,8 @@ enum type_specific_kind
/* Note: This is used by TYPE_CODE_FUNC and TYPE_CODE_METHOD. */
TYPE_SPECIFIC_FUNC,
TYPE_SPECIFIC_SELF_TYPE,
- TYPE_SPECIFIC_INT
+ TYPE_SPECIFIC_INT,
+ TYPE_SPECIFIC_FIXED_POINT,
};
union type_owner
@@ -766,6 +771,10 @@ union type_specific
struct type *self_type;
+ /* * For TYPE_CODE_FIXED_POINT types, the info necessary to decode
+ values of that type. */
+ struct fixed_point_type_info *fixed_point_info;
+
/* * An integer-like scalar type may be stored in just part of its
enclosing storage bytes. This structure describes this
situation. */
@@ -1678,6 +1687,14 @@ struct call_site
struct call_site_parameter parameter[1];
};
+/* The type-specific info for TYPE_CODE_FIXED_POINT types. */
+
+struct fixed_point_type_info
+{
+ /* The fixed point type's scaling factor. */
+ gdb_mpq scaling_factor;
+};
+
/* * The default value of TYPE_CPLUS_SPECIFIC(T) points to this shared
static structure. */
@@ -1725,6 +1742,13 @@ extern void allocate_gnat_aux_type (struct type *);
TYPE_ZALLOC (type, \
sizeof (*TYPE_MAIN_TYPE (type)->type_specific.func_stuff)))
+/* "struct fixed_point_type_info" has a field that has a destructor.
+ See allocate_fixed_point_type_info to understand how this is
+ handled. */
+#define INIT_FIXED_POINT_SPECIFIC(type) \
+ (TYPE_SPECIFIC_FIELD (type) = TYPE_SPECIFIC_FIXED_POINT, \
+ TYPE_FIXED_POINT_INFO (type) = allocate_fixed_point_type_info (type))
+
#define TYPE_MAIN_TYPE(thistype) (thistype)->main_type
#define TYPE_TARGET_TYPE(thistype) TYPE_MAIN_TYPE(thistype)->target_type
#define TYPE_POINTER_TYPE(thistype) (thistype)->pointer_type
@@ -1821,6 +1845,9 @@ extern void set_type_vptr_basetype (struct type *, struct type *);
(TYPE_CPLUS_SPECIFIC(thistype)->virtual_field_bits == NULL ? 0 \
: B_TST(TYPE_CPLUS_SPECIFIC(thistype)->virtual_field_bits, (index)))
+#define TYPE_FIXED_POINT_INFO(thistype) \
+ (TYPE_MAIN_TYPE(thistype)->type_specific.fixed_point_info)
+
#define FIELD_NAME(thisfld) ((thisfld).name)
#define FIELD_LOC_KIND(thisfld) ((thisfld).loc_kind)
#define FIELD_BITPOS_LVAL(thisfld) ((thisfld).loc.bitpos)
@@ -2192,6 +2219,8 @@ extern struct type *init_decfloat_type (struct objfile *, int, const char *);
extern struct type *init_complex_type (const char *, struct type *);
extern struct type *init_pointer_type (struct objfile *, int, const char *,
struct type *);
+extern struct type *init_fixed_point_type (struct objfile *, int, int,
+ const char *);
/* Helper functions to construct architecture-owned types. */
extern struct type *arch_type (struct gdbarch *, enum type_code, int,
@@ -2529,6 +2558,26 @@ extern int type_not_allocated (const struct type *type);
extern int type_not_associated (const struct type *type);
+/* Return True if TYPE is a TYPE_CODE_FIXED_POINT or if TYPE is
+ a range type whose base type is a TYPE_CODE_FIXED_POINT. */
+extern bool is_fixed_point_type (struct type *type);
+
+/* Assuming that TYPE is a fixed point type, return its base type.
+
+ In other words, this returns the type after having peeled all
+ intermediate type layers (such as TYPE_CODE_RANGE, for instance).
+ The TYPE_CODE of the type returned is guaranteed to be
+ a TYPE_CODE_FIXED_POINT. */
+extern struct type *fixed_point_type_base_type (struct type *type);
+
+/* Given TYPE, which is a fixed point type, return its scaling factor. */
+extern const gdb_mpq &fixed_point_scaling_factor (struct type *type);
+
+/* Allocate a fixed-point type info for TYPE. This should only be
+ called by INIT_FIXED_POINT_SPECIFIC. */
+extern fixed_point_type_info *allocate_fixed_point_type_info
+ (struct type *type);
+
/* * When the type includes explicit byte ordering, return that.
Otherwise, the byte ordering from gdbarch_byte_order for
get_type_arch is returned. */
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index b1a8f8f..0f629bd 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,14 @@
+2020-11-15 Joel Brobecker <brobecker@adacore.com>
+
+ * gdb.ada/fixed_cmp.exp: Force compilation to use -fgnat-encodings=all.
+ * gdb.ada/fixed_points.exp: Add fixed-point variables printing tests.
+ * gdb.ada/fixed_points/pck.ads, gdb.ada/fixed_points/pck.adb:
+ New files.
+ * gdb.ada/fixed_points/fixed_points.adb: Add use of package Pck.
+
+ * gdb.dwarf2/dw2-fixed-point.c, gdb.dwarf2/dw2-fixed-point.exp:
+ New files.
+
2020-11-14 Andrew Burgess <andrew.burgess@embecosm.com>
PR cli/26879
diff --git a/gdb/testsuite/gdb.ada/fixed_cmp.exp b/gdb/testsuite/gdb.ada/fixed_cmp.exp
index 38e41c4..cfdbb1c 100644
--- a/gdb/testsuite/gdb.ada/fixed_cmp.exp
+++ b/gdb/testsuite/gdb.ada/fixed_cmp.exp
@@ -19,25 +19,29 @@ if { [skip_ada_tests] } { return -1 }
standard_ada_testfile fixed
-if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug ]] != "" } {
- return -1
-}
+foreach_with_prefix gnat_encodings {all} {
+ set flags [list debug additional_flags=-fgnat-encodings=$gnat_encodings]
+
+ if {[gdb_compile_ada "${srcfile}" "${binfile}" executable $flags] != "" } {
+ return -1
+ }
-clean_restart ${testfile}
+ clean_restart ${testfile}
-set bp_location [gdb_get_line_number "STOP" ${testdir}/fixed.adb]
-runto "fixed.adb:$bp_location"
+ set bp_location [gdb_get_line_number "STOP" ${testdir}/fixed.adb]
+ runto "fixed.adb:$bp_location"
-gdb_test "print My_Var > 10.0" \
- "= true"
+ gdb_test "print My_Var > 10.0" \
+ "= true"
-gdb_test "print My_Var > 20.0" \
- "= false"
+ gdb_test "print My_Var > 20.0" \
+ "= false"
-# Do the same, but with integer values.
+ # Do the same, but with integer values.
-gdb_test "print My_Var > 10" \
- "= true"
+ gdb_test "print My_Var > 10" \
+ "= true"
-gdb_test "print My_Var > 20" \
- "= false"
+ gdb_test "print My_Var > 20" \
+ "= false"
+}
diff --git a/gdb/testsuite/gdb.ada/fixed_points.exp b/gdb/testsuite/gdb.ada/fixed_points.exp
index f991f56..655ee95 100644
--- a/gdb/testsuite/gdb.ada/fixed_points.exp
+++ b/gdb/testsuite/gdb.ada/fixed_points.exp
@@ -49,3 +49,14 @@ gdb_test "print Overprecise_Object" \
gdb_test "ptype Overprecise_Object" \
"= delta 0.135791"
+
+# FP*_Var...
+
+gdb_test "print fp1_var" \
+ " = 0.25"
+
+gdb_test "print fp2_var" \
+ " = -0.01"
+
+gdb_test "print fp3_var" \
+ " = 0.1"
diff --git a/gdb/testsuite/gdb.ada/fixed_points/fixed_points.adb b/gdb/testsuite/gdb.ada/fixed_points/fixed_points.adb
index a2720e3..f0a34ba 100644
--- a/gdb/testsuite/gdb.ada/fixed_points/fixed_points.adb
+++ b/gdb/testsuite/gdb.ada/fixed_points/fixed_points.adb
@@ -14,6 +14,7 @@
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
with System;
+with Pck; use Pck;
procedure Fixed_Points is
@@ -59,4 +60,7 @@ begin
Subtype_Object := 1.0/16.0;
New_Type_Object := 1.0/16.0;
Overprecise_Object := Overprecise_Fixed_Point'Small * 2;
+ Do_Nothing (FP1_Var'Address);
+ Do_Nothing (FP2_Var'Address);
+ Do_Nothing (FP3_Var'Address);
end Fixed_Points;
diff --git a/gdb/testsuite/gdb.ada/fixed_points/pck.adb b/gdb/testsuite/gdb.ada/fixed_points/pck.adb
new file mode 100644
index 0000000..16f0384
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/fixed_points/pck.adb
@@ -0,0 +1,22 @@
+-- Copyright 2016-2020 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/>.
+
+package body Pck is
+ procedure Do_Nothing (A : System.Address) is
+ begin
+ null;
+ end Do_Nothing;
+end pck;
+
diff --git a/gdb/testsuite/gdb.ada/fixed_points/pck.ads b/gdb/testsuite/gdb.ada/fixed_points/pck.ads
new file mode 100644
index 0000000..4d900dc
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/fixed_points/pck.ads
@@ -0,0 +1,30 @@
+-- Copyright 2016-2020 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/>.
+
+with System;
+
+package Pck is
+ type FP1_Type is delta 0.1 range -1.0 .. +1.0;
+ FP1_Var : FP1_Type := 0.25;
+
+ type FP2_Type is delta 0.01 digits 14;
+ FP2_Var : FP2_Type := -0.01;
+
+ type FP3_Type is delta 0.1 range 0.0 .. 1.0 with Small => 0.1/3.0;
+ FP3_Var : FP3_Type := 0.1;
+
+ procedure Do_Nothing (A : System.Address);
+end pck;
+
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.c b/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.c
new file mode 100644
index 0000000..d9c811c
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.c
@@ -0,0 +1,49 @@
+/* Copyright 2016-2020 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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 <stdint.h>
+
+/* Simulate an Ada variable declared inside package Pck as follow:
+ type FP1_Type is delta 0.1 range -1.0 .. +1.0;
+ FP1_Var : FP1_Type := 0.25; */
+int8_t pck__fp1_var = 4;
+
+/* Simulate an Ada variable declared inside package Pck as follow:
+ type FP2_Type is delta 0.01 digits 14;
+ FP2_Var : FP2_Type := -0.01; */
+int32_t pck__fp2_var = -1;
+
+/* Simulate an Ada variable declared inside package Pck as follow:
+ type FP3_Type is delta 0.1 range 0.0 .. 1.0 with Small => 0.1/3.0;
+ FP3_Var : FP3_Type := 0.1; */
+int8_t pck__fp3_var = 3;
+
+/* Simulate an Ada variable declared inside package Pck as follow:
+ type FP1_Type is delta 0.1 range -1.0 .. +1.0;
+ FP1_Var : FP1_Type := 1.0; */
+int8_t pck__fp1_range_var = 16;
+
+int
+main (void)
+{
+ pck__fp1_var++;
+ pck__fp2_var++;
+ pck__fp3_var++;
+ pck__fp1_range_var++;
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp b/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp
new file mode 100644
index 0000000..bf88ffe
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp
@@ -0,0 +1,132 @@
+# Copyright 2016-2020 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/>.
+load_lib dwarf.exp
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+if {![dwarf2_support]} {
+ return 0
+}
+
+standard_testfile dw2-fixed-point.c dw2-fixed-point-dw.S
+
+# Make some DWARF for the test.
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+ cu {} {
+ DW_TAG_compile_unit {
+ {DW_AT_language @DW_LANG_Ada95}
+ {DW_AT_name pck.ads}
+ {DW_AT_comp_dir /tmp}
+ } {
+ declare_labels fp1_base_type fp2_base_type fp3_small \
+ fp3_base_type fp1_range_type
+
+ fp1_base_type: DW_TAG_base_type {
+ {DW_AT_byte_size 1 DW_FORM_sdata}
+ {DW_AT_encoding @DW_ATE_signed_fixed}
+ {DW_AT_name pck__fp1_type}
+ {DW_AT_binary_scale -4 DW_FORM_sdata}
+ }
+
+ DW_TAG_variable {
+ {DW_AT_name pck__fp1_var}
+ {DW_AT_type :$fp1_base_type}
+ {DW_AT_location {
+ DW_OP_addr [gdb_target_symbol pck__fp1_var]
+ } SPECIAL_expr}
+ {external 1 flag}
+ }
+
+ fp2_base_type: DW_TAG_base_type {
+ {DW_AT_byte_size 1 DW_FORM_sdata}
+ {DW_AT_encoding @DW_ATE_signed_fixed}
+ {DW_AT_name pck__fp2_type}
+ {DW_AT_decimal_scale -2 DW_FORM_sdata}
+ }
+
+ DW_TAG_variable {
+ {DW_AT_name pck__fp2_var}
+ {DW_AT_type :$fp2_base_type}
+ {DW_AT_location {
+ DW_OP_addr [gdb_target_symbol pck__fp2_var]
+ } SPECIAL_expr}
+ {external 1 flag}
+ }
+
+ fp3_small: DW_TAG_constant {
+ {DW_AT_GNU_numerator 1 DW_FORM_data1}
+ {DW_AT_GNU_denominator 30 DW_FORM_sdata}
+ }
+
+ fp3_base_type: DW_TAG_base_type {
+ {DW_AT_byte_size 1 DW_FORM_sdata}
+ {DW_AT_encoding @DW_ATE_signed_fixed}
+ {DW_AT_name pck__fp3_type}
+ {DW_AT_small :$fp3_small}
+ }
+
+ DW_TAG_variable {
+ {DW_AT_name pck__fp3_var}
+ {DW_AT_type :$fp3_base_type}
+ {DW_AT_location {
+ DW_OP_addr [gdb_target_symbol pck__fp3_var]
+ } SPECIAL_expr}
+ {external 1 flag}
+ }
+
+ fp1_range_type: DW_TAG_subrange_type {
+ {DW_AT_lower_bound 0xf0 DW_FORM_data1}
+ {DW_AT_upper_bound 0x10 DW_FORM_data1}
+ {DW_AT_name foo__fp1_range_type}
+ {DW_AT_type :$fp1_base_type}
+ }
+
+ DW_TAG_variable {
+ {DW_AT_name pck__fp1_range_var}
+ {DW_AT_type :$fp1_range_type}
+ {DW_AT_location {
+ DW_OP_addr [gdb_target_symbol pck__fp1_range_var]
+ } SPECIAL_expr}
+ {external 1 flag}
+ }
+ }
+ }
+}
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} \
+ [list $srcfile $asm_file] {nodebug}] } {
+ return -1
+}
+
+if ![runto_main] {
+ return -1
+}
+
+# Do the testing in Ada mode, since this is the language for which
+# this feature has been implemented, and where we know the language
+# has the concept of fixed-point types.
+gdb_test_no_output "set lang ada"
+
+gdb_test "print pck.fp1_var" \
+ " = 0.25"
+
+gdb_test "print pck.fp2_var" \
+ " = -0.01"
+
+gdb_test "print pck.fp3_var" \
+ " = 0.1"
+
+gdb_test "print pck.fp1_range_var" \
+ " = 1"
diff --git a/gdb/valprint.c b/gdb/valprint.c
index 2d9d1fb..38ae0bd 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -794,6 +794,31 @@ generic_val_print_float (struct type *type, struct ui_file *stream,
print_floating (valaddr, type, stream);
}
+/* generic_val_print helper for TYPE_CODE_FIXED_POINT. */
+
+static void
+generic_val_print_fixed_point (struct value *val, struct ui_file *stream,
+ const struct value_print_options *options)
+{
+ if (options->format)
+ value_print_scalar_formatted (val, options, 0, stream);
+ else
+ {
+ struct type *type = value_type (val);
+
+ const gdb_byte *valaddr = value_contents_for_printing (val);
+ gdb_mpf f;
+
+ f.read_fixed_point (valaddr, TYPE_LENGTH (type),
+ type_byte_order (type), type->is_unsigned (),
+ fixed_point_scaling_factor (type));
+
+ const char *fmt = TYPE_LENGTH (type) < 4 ? "%.11Fg" : "%.17Fg";
+ gdb::unique_xmalloc_ptr<char> str = gmp_string_asprintf (fmt, f.val);
+ fprintf_filtered (stream, "%s", str.get ());
+ }
+}
+
/* generic_value_print helper for TYPE_CODE_COMPLEX. */
static void
@@ -844,6 +869,10 @@ generic_value_print (struct value *val, struct ui_file *stream, int recurse,
struct type *type = value_type (val);
type = check_typedef (type);
+
+ if (is_fixed_point_type (type))
+ type = fixed_point_type_base_type (type);
+
switch (type->code ())
{
case TYPE_CODE_ARRAY:
@@ -909,6 +938,10 @@ generic_value_print (struct value *val, struct ui_file *stream, int recurse,
generic_val_print_float (type, stream, val, options);
break;
+ case TYPE_CODE_FIXED_POINT:
+ generic_val_print_fixed_point (val, stream, options);
+ break;
+
case TYPE_CODE_VOID:
fputs_filtered (decorations->void_name, stream);
break;
diff --git a/gdb/value.c b/gdb/value.c
index c9907fa..a0546af 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -2758,6 +2758,9 @@ value_as_address (struct value *val)
LONGEST
unpack_long (struct type *type, const gdb_byte *valaddr)
{
+ if (is_fixed_point_type (type))
+ type = fixed_point_type_base_type (type);
+
enum bfd_endian byte_order = type_byte_order (type);
enum type_code code = type->code ();
int len = TYPE_LENGTH (type);
@@ -2806,6 +2809,17 @@ unpack_long (struct type *type, const gdb_byte *valaddr)
case TYPE_CODE_DECFLOAT:
return target_float_to_longest (valaddr, type);
+ case TYPE_CODE_FIXED_POINT:
+ {
+ gdb_mpq vq;
+ vq.read_fixed_point (valaddr, len, byte_order, nosign,
+ fixed_point_scaling_factor (type));
+
+ gdb_mpz vz;
+ mpz_tdiv_q (vz.val, mpq_numref (vq.val), mpq_denref (vq.val));
+ return vz.as_integer<LONGEST> ();
+ }
+
case TYPE_CODE_PTR:
case TYPE_CODE_REF:
case TYPE_CODE_RVALUE_REF:
--
2.1.4
^ permalink raw reply [flat|nested] 140+ messages in thread
* [pushed/v2 6/9] fix printing of DWARF fixed-point type objects with format modifier
2020-11-15 8:35 ` pushed: " Joel Brobecker
` (4 preceding siblings ...)
2020-11-15 8:35 ` [pushed/v2 5/9] Add support for printing value of DWARF-based fixed-point type objects Joel Brobecker
@ 2020-11-15 8:35 ` Joel Brobecker
2020-11-15 8:35 ` [pushed/v2 7/9] Add ptype support for DWARF-based fixed-point types Joel Brobecker
` (5 subsequent siblings)
11 siblings, 0 replies; 140+ messages in thread
From: Joel Brobecker @ 2020-11-15 8:35 UTC (permalink / raw)
To: gdb-patches; +Cc: Simon Marchi, Joel Brobecker
Consider a fixed-point type such the scaling factor is 1/16,
as the following Ada code snippet would create:
type FP1_Type is delta 0.1 range -1.0 .. +1.0;
FP1_Var : FP1_Type := 0.25;
Printing the value of this variable with a format modifier yields
the wrong value. E.g.:
(gdb) p /x fp1_var
$6 = 0x4
Since the real value is 0.25, we therefore expected...
(gdb) p /x fp1_var
$6 = 0x0
What happens, in this case, is that the value being printed is
actually the "raw" value of our object, before the scaling factor
gets applied.
This commit fixes the issue by using approach as for float values,
where we convert the value into an integer value, prior to printing,
knowing that the conversion takes the scaling factor into account.
gdb/ChangeLog:
* printcmd.c (print_scalar_formatted): Add fixed-point type
handling when options->format is set.
gdb/testsuite/ChangeLog:
* gdb.dwarf2/dw2-fixed-point.exp: Add "print /x" tests.
---
gdb/ChangeLog | 5 +++++
gdb/printcmd.c | 3 ++-
gdb/testsuite/ChangeLog | 4 ++++
gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp | 12 ++++++++++++
4 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 16905ac..0d322da 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,10 @@
2020-11-15 Joel Brobecker <brobecker@adacore.com>
+ * printcmd.c (print_scalar_formatted): Add fixed-point type
+ handling when options->format is set.
+
+2020-11-15 Joel Brobecker <brobecker@adacore.com>
+
* ada-valprint.c (ada_value_print_1): Add fixed-point type handling.
* dwarf2/read.c (get_dwarf2_rational_constant)
(get_dwarf2_unsigned_rational_constant, finish_fixed_point_type)
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index f7186c2..6651424 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -421,7 +421,8 @@ print_scalar_formatted (const gdb_byte *valaddr, struct type *type,
range case, we want to avoid this, so we store the unpacked value
here for possible use later. */
gdb::optional<LONGEST> val_long;
- if ((type->code () == TYPE_CODE_FLT
+ if (((type->code () == TYPE_CODE_FLT
+ || is_fixed_point_type (type))
&& (options->format == 'o'
|| options->format == 'x'
|| options->format == 't'
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 0f629bd..9b9ffe5 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,9 @@
2020-11-15 Joel Brobecker <brobecker@adacore.com>
+ * gdb.dwarf2/dw2-fixed-point.exp: Add "print /x" tests.
+
+2020-11-15 Joel Brobecker <brobecker@adacore.com>
+
* gdb.ada/fixed_cmp.exp: Force compilation to use -fgnat-encodings=all.
* gdb.ada/fixed_points.exp: Add fixed-point variables printing tests.
* gdb.ada/fixed_points/pck.ads, gdb.ada/fixed_points/pck.adb:
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp b/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp
index bf88ffe..27c549c 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp
@@ -122,11 +122,23 @@ gdb_test_no_output "set lang ada"
gdb_test "print pck.fp1_var" \
" = 0.25"
+gdb_test "print /x pck.fp1_var" \
+ " = 0x0"
+
gdb_test "print pck.fp2_var" \
" = -0.01"
+gdb_test "print /x pck.fp2_var" \
+ " = 0x0"
+
gdb_test "print pck.fp3_var" \
" = 0.1"
+gdb_test "print /x pck.fp3_var" \
+ " = 0x0"
+
gdb_test "print pck.fp1_range_var" \
" = 1"
+
+gdb_test "print /x pck.fp1_range_var" \
+ " = 0x1"
--
2.1.4
^ permalink raw reply [flat|nested] 140+ messages in thread
* [pushed/v2 7/9] Add ptype support for DWARF-based fixed-point types
2020-11-15 8:35 ` pushed: " Joel Brobecker
` (5 preceding siblings ...)
2020-11-15 8:35 ` [pushed/v2 6/9] fix printing of DWARF fixed-point type objects with format modifier Joel Brobecker
@ 2020-11-15 8:35 ` Joel Brobecker
2020-11-15 8:35 ` [pushed/v2 8/9] Add support for fixed-point type arithmetic Joel Brobecker
` (4 subsequent siblings)
11 siblings, 0 replies; 140+ messages in thread
From: Joel Brobecker @ 2020-11-15 8:35 UTC (permalink / raw)
To: gdb-patches; +Cc: Simon Marchi, Joel Brobecker
Note that the ptype information printed for types described
via pure DWARF debug info is slightly less informative as
the one printed when the information is encoded in the type's
name, via the GNAT encoding. As a result, the output in
the case of DWARF-described fixed point types is slightly
different. In pratice, this is no real loss because the information
not available in DWARF has no bearing on how the type is actually
stored in memory.
gdb/ChangeLog:
* ada-typeprint.c (ada_print_type): Add handing of fixed-point
range types.
* c-typeprint.c (c_type_print_varspec_prefix)
(c_type_print_varspec_suffix, c_type_print_base_1): Add
TYPE_CODE_FIXED_POINT handling.
* p-typeprint.c (pascal_type_print_varspec_prefix)
(pascal_type_print_varspec_suffix): Likewise.
* typeprint.c (print_type_fixed_point): New function.
* typeprint.h (print_type_fixed_point): Add declaration.
gdb/testsuite/ChangeLog:
* gdb.ada/fixed_points.exp: Add ptype tests.
* gdb.dwarf2/dw2-fixed-point.exp: Likewise.
---
gdb/ChangeLog | 12 ++++++++
gdb/ada-typeprint.c | 6 ++++
gdb/c-typeprint.c | 6 ++++
gdb/p-typeprint.c | 2 ++
gdb/testsuite/ChangeLog | 5 ++++
gdb/testsuite/gdb.ada/fixed_points.exp | 36 +++++++++++++++++++++++
gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp | 44 ++++++++++++++++++++++++++++
gdb/typeprint.c | 12 ++++++++
gdb/typeprint.h | 5 ++++
9 files changed, 128 insertions(+)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 0d322da..56e54d3 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,17 @@
2020-11-15 Joel Brobecker <brobecker@adacore.com>
+ * ada-typeprint.c (ada_print_type): Add handing of fixed-point
+ range types.
+ * c-typeprint.c (c_type_print_varspec_prefix)
+ (c_type_print_varspec_suffix, c_type_print_base_1): Add
+ TYPE_CODE_FIXED_POINT handling.
+ * p-typeprint.c (pascal_type_print_varspec_prefix)
+ (pascal_type_print_varspec_suffix): Likewise.
+ * typeprint.c (print_type_fixed_point): New function.
+ * typeprint.h (print_type_fixed_point): Add declaration.
+
+2020-11-15 Joel Brobecker <brobecker@adacore.com>
+
* printcmd.c (print_scalar_formatted): Add fixed-point type
handling when options->format is set.
diff --git a/gdb/ada-typeprint.c b/gdb/ada-typeprint.c
index 5388247..8abb65b 100644
--- a/gdb/ada-typeprint.c
+++ b/gdb/ada-typeprint.c
@@ -1046,6 +1046,12 @@ ada_print_type (struct type *type0, const char *varstring,
case TYPE_CODE_RANGE:
if (ada_is_gnat_encoded_fixed_point_type (type))
print_gnat_encoded_fixed_point_type (type, stream);
+ else if (is_fixed_point_type (type))
+ {
+ fprintf_filtered (stream, "<");
+ print_type_fixed_point (type, stream);
+ fprintf_filtered (stream, ">");
+ }
else if (ada_is_modular_type (type))
fprintf_filtered (stream, "mod %s",
int_string (ada_modulus (type), 10, 0, 0, 1));
diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c
index e72fdaa..10631ff 100644
--- a/gdb/c-typeprint.c
+++ b/gdb/c-typeprint.c
@@ -465,6 +465,7 @@ c_type_print_varspec_prefix (struct type *type,
case TYPE_CODE_COMPLEX:
case TYPE_CODE_NAMESPACE:
case TYPE_CODE_DECFLOAT:
+ case TYPE_CODE_FIXED_POINT:
/* These types need no prefix. They are listed here so that
gcc -Wall will reveal any types that haven't been handled. */
break;
@@ -844,6 +845,7 @@ c_type_print_varspec_suffix (struct type *type,
case TYPE_CODE_COMPLEX:
case TYPE_CODE_NAMESPACE:
case TYPE_CODE_DECFLOAT:
+ case TYPE_CODE_FIXED_POINT:
/* These types do not need a suffix. They are listed so that
gcc -Wall will report types that may not have been
considered. */
@@ -1683,6 +1685,10 @@ c_type_print_base_1 (struct type *type, struct ui_file *stream,
fprintf_styled (stream, metadata_style.style (), _("<range type>"));
break;
+ case TYPE_CODE_FIXED_POINT:
+ print_type_fixed_point (type, stream);
+ break;
+
case TYPE_CODE_NAMESPACE:
fputs_filtered ("namespace ", stream);
fputs_filtered (type->name (), stream);
diff --git a/gdb/p-typeprint.c b/gdb/p-typeprint.c
index ef0f254..c2c182a 100644
--- a/gdb/p-typeprint.c
+++ b/gdb/p-typeprint.c
@@ -296,6 +296,7 @@ pascal_type_print_varspec_prefix (struct type *type, struct ui_file *stream,
case TYPE_CODE_STRING:
case TYPE_CODE_COMPLEX:
case TYPE_CODE_TYPEDEF:
+ case TYPE_CODE_FIXED_POINT:
/* These types need no prefix. They are listed here so that
gcc -Wall will reveal any types that haven't been handled. */
break;
@@ -429,6 +430,7 @@ pascal_type_print_varspec_suffix (struct type *type, struct ui_file *stream,
case TYPE_CODE_STRING:
case TYPE_CODE_COMPLEX:
case TYPE_CODE_TYPEDEF:
+ case TYPE_CODE_FIXED_POINT:
/* These types do not need a suffix. They are listed so that
gcc -Wall will report types that may not have been considered. */
break;
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 9b9ffe5..2c7b5c5 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,10 @@
2020-11-15 Joel Brobecker <brobecker@adacore.com>
+ * gdb.ada/fixed_points.exp: Add ptype tests.
+ * gdb.dwarf2/dw2-fixed-point.exp: Likewise.
+
+2020-11-15 Joel Brobecker <brobecker@adacore.com>
+
* gdb.dwarf2/dw2-fixed-point.exp: Add "print /x" tests.
2020-11-15 Joel Brobecker <brobecker@adacore.com>
diff --git a/gdb/testsuite/gdb.ada/fixed_points.exp b/gdb/testsuite/gdb.ada/fixed_points.exp
index 655ee95..1fe2eb2 100644
--- a/gdb/testsuite/gdb.ada/fixed_points.exp
+++ b/gdb/testsuite/gdb.ada/fixed_points.exp
@@ -55,8 +55,44 @@ gdb_test "ptype Overprecise_Object" \
gdb_test "print fp1_var" \
" = 0.25"
+gdb_test_multiple "ptype fp1_var" "" {
+ -re "type = <1-byte fixed point \\(small = 0\\.0625\\)>\r\n$gdb_prompt $" {
+ pass $gdb_test_name
+ }
+ -re "type = delta 0\\.1 <'small = 0\\.0625>\r\n$gdb_prompt $" {
+ # The (legacy) output we obtain when the compiler described
+ # our fixed point types using the GNAT encodings rather than
+ # standard DWARF. OK as well.
+ pass $gdb_test_name
+ }
+}
+
gdb_test "print fp2_var" \
" = -0.01"
+gdb_test_multiple "ptype fp2_var" "" {
+ -re "type = <8-byte fixed point \\(small = 0\\.01\\)>\r\n$gdb_prompt $" {
+ pass $gdb_test_name
+ }
+ -re "type = delta 0\\.01\r\n$gdb_prompt $" {
+ # The (legacy) output we obtain when the compiler described
+ # our fixed point types using the GNAT encodings rather than
+ # standard DWARF. OK as well.
+ pass $gdb_test_name
+ }
+}
+
gdb_test "print fp3_var" \
" = 0.1"
+
+gdb_test_multiple "ptype fp3_var" "" {
+ -re "type = <1-byte fixed point \\(small = 0\\.0333333\\)>\r\n$gdb_prompt $" {
+ pass $gdb_test_name
+ }
+ -re "type = delta 0\\.1 <'small = 0\\.0333333>\r\n$gdb_prompt $" {
+ # The (legacy) output we obtain when the compiler described
+ # our fixed point types using the GNAT encodings rather than
+ # standard DWARF. OK as well.
+ pass $gdb_test_name
+ }
+}
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp b/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp
index 27c549c..33a7e74 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp
@@ -142,3 +142,47 @@ gdb_test "print pck.fp1_range_var" \
gdb_test "print /x pck.fp1_range_var" \
" = 0x1"
+
+# Set the language to LANG and do a ptype test on pck__fp1_var,
+# pck__fp2_var and pck__fp3_var, verifying that the output matches
+# FP1_RE, FP2_RE, FP2_RE (resp.).
+
+proc do_ptype_test {lang fp1_re fp2_re fp3_re fp1_range_re} {
+ with_test_prefix "lang=$lang" {
+ gdb_test_no_output "set language $lang" \
+ "set language to $lang for ptype test"
+
+ gdb_test "ptype pck__fp1_var" $fp1_re
+
+ gdb_test "ptype pck__fp2_var" $fp2_re
+
+ gdb_test "ptype pck__fp3_var" $fp3_re
+
+ if { $lang == "modula-2" || $lang == "pascal" } {
+ setup_xfail "*-*-*" "not supported by language"
+ }
+ gdb_test "ptype pck__fp1_range_var" $fp1_range_re
+ }
+}
+
+do_ptype_test "ada" \
+ " = <1-byte fixed point \\(small = 1/16\\)>" \
+ " = <1-byte fixed point \\(small = 1/100\\)>" \
+ " = <1-byte fixed point \\(small = 1/30\\)>" \
+ " = <1-byte fixed point \\(small = 1/16\\)>"
+
+foreach lang [list "c" "d" "go" "objective-c" "opencl" ] {
+ do_ptype_test $lang \
+ " = 1-byte fixed point \\(small = 1/16\\)" \
+ " = 1-byte fixed point \\(small = 1/100\\)" \
+ " = 1-byte fixed point \\(small = 1/30\\)" \
+ " = <range type>"
+}
+
+foreach lang [list "fortran" "modula-2" "pascal" ] {
+ do_ptype_test $lang \
+ " = pck__fp1_type" \
+ " = pck__fp2_type" \
+ " = pck__fp3_type" \
+ " = <range type>"
+}
diff --git a/gdb/typeprint.c b/gdb/typeprint.c
index acaee44..f947faf 100644
--- a/gdb/typeprint.c
+++ b/gdb/typeprint.c
@@ -662,6 +662,18 @@ print_type_scalar (struct type *type, LONGEST val, struct ui_file *stream)
}
}
+/* See typeprint.h. */
+
+void
+print_type_fixed_point (struct type *type, struct ui_file *stream)
+{
+ gdb::unique_xmalloc_ptr<char> small_img
+ = fixed_point_scaling_factor (type).str ();
+
+ fprintf_filtered (stream, "%s-byte fixed point (small = %s)",
+ pulongest (TYPE_LENGTH (type)), small_img.get ());
+}
+
/* Dump details of a type specified either directly or indirectly.
Uses the same sort of type lookup mechanism as ptype_command()
and whatis_command(). */
diff --git a/gdb/typeprint.h b/gdb/typeprint.h
index 8936b9a..d595cbe 100644
--- a/gdb/typeprint.h
+++ b/gdb/typeprint.h
@@ -151,6 +151,11 @@ class typedef_hash_table
void print_type_scalar (struct type * type, LONGEST, struct ui_file *);
+/* Assuming the TYPE is a fixed point type, print its type description
+ on STREAM. */
+
+void print_type_fixed_point (struct type *type, struct ui_file *stream);
+
void c_type_print_args (struct type *, struct ui_file *, int, enum language,
const struct type_print_options *);
--
2.1.4
^ permalink raw reply [flat|nested] 140+ messages in thread
* [pushed/v2 8/9] Add support for fixed-point type arithmetic
2020-11-15 8:35 ` pushed: " Joel Brobecker
` (6 preceding siblings ...)
2020-11-15 8:35 ` [pushed/v2 7/9] Add ptype support for DWARF-based fixed-point types Joel Brobecker
@ 2020-11-15 8:35 ` Joel Brobecker
2020-11-15 8:35 ` [pushed/v2 9/9] Add support for fixed-point type comparison operators Joel Brobecker
` (3 subsequent siblings)
11 siblings, 0 replies; 140+ messages in thread
From: Joel Brobecker @ 2020-11-15 8:35 UTC (permalink / raw)
To: gdb-patches; +Cc: Simon Marchi, Joel Brobecker
This patch adds support for binary operations on fixed-point values,
as well as for the negative unary operator.
gdb/ChangeLog:
* eval.c (binop_promote): Add fixed-point type handling.
* valarith.c (fixed_point_binop): New function.
(scalar_binop): Add fixed-point type handling.
(value_neg): Add fixed-point type handling.
* valops.c (value_cast_to_fixed_point): New function.
(value_cast): Add fixed-point type handling.
gdb/testsuite/ChangeLog:
* gdb.dwarf2/dw2-fixed-point.exp: Add arithmetic tests.
---
gdb/ChangeLog | 9 +++
gdb/eval.c | 3 +
gdb/testsuite/ChangeLog | 4 ++
gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp | 18 ++++++
gdb/valarith.c | 91 +++++++++++++++++++++++++++-
gdb/valops.c | 74 +++++++++++++++++++++-
6 files changed, 196 insertions(+), 3 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 56e54d3..e9f0afd 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,14 @@
2020-11-15 Joel Brobecker <brobecker@adacore.com>
+ * eval.c (binop_promote): Add fixed-point type handling.
+ * valarith.c (fixed_point_binop): New function.
+ (scalar_binop): Add fixed-point type handling.
+ (value_neg): Add fixed-point type handling.
+ * valops.c (value_cast_to_fixed_point): New function.
+ (value_cast): Add fixed-point type handling.
+
+2020-11-15 Joel Brobecker <brobecker@adacore.com>
+
* ada-typeprint.c (ada_print_type): Add handing of fixed-point
range types.
* c-typeprint.c (c_type_print_varspec_prefix)
diff --git a/gdb/eval.c b/gdb/eval.c
index 8d0c574..308f477 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -430,6 +430,9 @@ binop_promote (const struct language_defn *language, struct gdbarch *gdbarch,
&& !is_integral_type (type2)))
return;
+ if (is_fixed_point_type (type1) || is_fixed_point_type (type2))
+ return;
+
if (type1->code () == TYPE_CODE_DECFLOAT
|| type2->code () == TYPE_CODE_DECFLOAT)
{
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 2c7b5c5..3c53f6c 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,9 @@
2020-11-15 Joel Brobecker <brobecker@adacore.com>
+ * gdb.dwarf2/dw2-fixed-point.exp: Add arithmetic tests.
+
+2020-11-15 Joel Brobecker <brobecker@adacore.com>
+
* gdb.ada/fixed_points.exp: Add ptype tests.
* gdb.dwarf2/dw2-fixed-point.exp: Likewise.
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp b/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp
index 33a7e74..0252195 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp
@@ -143,6 +143,24 @@ gdb_test "print pck.fp1_range_var" \
gdb_test "print /x pck.fp1_range_var" \
" = 0x1"
+gdb_test "print pck.fp1_var + 0.25" \
+ " = 0.5"
+
+gdb_test "print pck.fp2_var - pck.fp2_var" \
+ " = 0"
+
+gdb_test "print pck.fp3_var * 1" \
+ " = 0.1"
+
+gdb_test "print pck.fp3_var / pck.fp3_var" \
+ " = 1"
+
+gdb_test "print pck.fp1_range_var - 0.5" \
+ " = 0.5"
+
+gdb_test "print -pck.fp1_var" \
+ " = -0.25"
+
# Set the language to LANG and do a ptype test on pck__fp1_var,
# pck__fp2_var and pck__fp3_var, verifying that the output matches
# FP1_RE, FP2_RE, FP2_RE (resp.).
diff --git a/gdb/valarith.c b/gdb/valarith.c
index f6caf3d..65a6f13 100644
--- a/gdb/valarith.c
+++ b/gdb/valarith.c
@@ -881,6 +881,84 @@ value_args_as_target_float (struct value *arg1, struct value *arg2,
type2->name ());
}
+/* Assuming at last one of ARG1 or ARG2 is a fixed point value,
+ perform the binary operation OP on these two operands, and return
+ the resulting value (also as a fixed point). */
+
+static struct value *
+fixed_point_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
+{
+ struct type *type1 = check_typedef (value_type (arg1));
+ struct type *type2 = check_typedef (value_type (arg2));
+
+ struct value *val;
+
+ gdb_assert (is_fixed_point_type (type1) || is_fixed_point_type (type2));
+ if (!is_fixed_point_type (type1))
+ {
+ arg1 = value_cast (type2, arg1);
+ type1 = type2;
+ }
+ if (!is_fixed_point_type (type2))
+ {
+ arg2 = value_cast (type1, arg2);
+ type2 = type1;
+ }
+
+ gdb_mpq v1, v2, res;
+ v1.read_fixed_point (value_contents (arg1), TYPE_LENGTH (type1),
+ type_byte_order (type1), type1->is_unsigned (),
+ fixed_point_scaling_factor (type1));
+ v2.read_fixed_point (value_contents (arg2), TYPE_LENGTH (type2),
+ type_byte_order (type2), type2->is_unsigned (),
+ fixed_point_scaling_factor (type2));
+
+#define INIT_VAL_WITH_FIXED_POINT_VAL(RESULT) \
+ do { \
+ val = allocate_value (type1); \
+ (RESULT).write_fixed_point \
+ (value_contents_raw (val), TYPE_LENGTH (type1), \
+ type_byte_order (type1), type1->is_unsigned (), \
+ fixed_point_scaling_factor (type1)); \
+ } while (0)
+
+ switch (op)
+ {
+ case BINOP_ADD:
+ mpq_add (res.val, v1.val, v2.val);
+ INIT_VAL_WITH_FIXED_POINT_VAL (res);
+ break;
+
+ case BINOP_SUB:
+ mpq_sub (res.val, v1.val, v2.val);
+ INIT_VAL_WITH_FIXED_POINT_VAL (res);
+ break;
+
+ case BINOP_MIN:
+ INIT_VAL_WITH_FIXED_POINT_VAL (mpq_cmp (v1.val, v2.val) < 0 ? v1 : v2);
+ break;
+
+ case BINOP_MAX:
+ INIT_VAL_WITH_FIXED_POINT_VAL (mpq_cmp (v1.val, v2.val) > 0 ? v1 : v2);
+ break;
+
+ case BINOP_MUL:
+ mpq_mul (res.val, v1.val, v2.val);
+ INIT_VAL_WITH_FIXED_POINT_VAL (res);
+ break;
+
+ case BINOP_DIV:
+ mpq_div (res.val, v1.val, v2.val);
+ INIT_VAL_WITH_FIXED_POINT_VAL (res);
+ break;
+
+ default:
+ error (_("Integer-only operation on fixed point number."));
+ }
+
+ return val;
+}
+
/* A helper function that finds the type to use for a binary operation
involving TYPE1 and TYPE2. */
@@ -1054,10 +1132,17 @@ scalar_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
|| type2->code () == TYPE_CODE_COMPLEX)
return complex_binop (arg1, arg2, op);
- if ((!is_floating_value (arg1) && !is_integral_type (type1))
- || (!is_floating_value (arg2) && !is_integral_type (type2)))
+ if ((!is_floating_value (arg1)
+ && !is_integral_type (type1)
+ && !is_fixed_point_type (type1))
+ || (!is_floating_value (arg2)
+ && !is_integral_type (type2)
+ && !is_fixed_point_type (type2)))
error (_("Argument to arithmetic operation not a number or boolean."));
+ if (is_fixed_point_type (type1) || is_fixed_point_type (type2))
+ return fixed_point_binop (arg1, arg2, op);
+
if (is_floating_type (type1) || is_floating_type (type2))
{
result_type = promotion_type (type1, type2);
@@ -1753,6 +1838,8 @@ value_neg (struct value *arg1)
if (is_integral_type (type) || is_floating_type (type))
return value_binop (value_from_longest (type, 0), arg1, BINOP_SUB);
+ else if (is_fixed_point_type (type))
+ return value_binop (value_zero (type, not_lval), arg1, BINOP_SUB);
else if (type->code () == TYPE_CODE_ARRAY && type->is_vector ())
{
struct value *tmp, *val = allocate_value (type);
diff --git a/gdb/valops.c b/gdb/valops.c
index 4df2538..0f84a70 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -331,6 +331,60 @@ value_cast_pointers (struct type *type, struct value *arg2,
return arg2;
}
+/* Assuming that TO_TYPE is a fixed point type, return a value
+ corresponding to the cast of FROM_VAL to that type. */
+
+static struct value *
+value_cast_to_fixed_point (struct type *to_type, struct value *from_val)
+{
+ struct type *from_type = value_type (from_val);
+
+ if (from_type == to_type)
+ return from_val;
+
+ gdb_mpq vq;
+
+ /* Extract the value as a rational number. */
+
+ if (is_floating_type (from_type))
+ {
+ double d = target_float_to_host_double (value_contents (from_val),
+ from_type);
+ mpq_set_d (vq.val, d);
+ }
+
+ else if (is_integral_type (from_type) || is_fixed_point_type (from_type))
+ {
+ gdb_mpz vz;
+
+ vz.read (value_contents (from_val), TYPE_LENGTH (from_type),
+ type_byte_order (from_type), from_type->is_unsigned ());
+ mpq_set_z (vq.val, vz.val);
+
+ if (is_fixed_point_type (from_type))
+ mpq_mul (vq.val, vq.val, fixed_point_scaling_factor (from_type).val);
+ }
+
+ else
+ error (_("Invalid conversion from type %s to fixed point type %s"),
+ from_type->name (), to_type->name ());
+
+ /* Divide that value by the scaling factor to obtain the unscaled
+ value, first in rational form, and then in integer form. */
+
+ mpq_div (vq.val, vq.val, fixed_point_scaling_factor (to_type).val);
+ gdb_mpz unscaled = vq.get_rounded ();
+
+ /* Finally, create the result value, and pack the unscaled value
+ in it. */
+ struct value *result = allocate_value (to_type);
+ unscaled.write (value_contents_raw (result),
+ TYPE_LENGTH (to_type), type_byte_order (to_type),
+ to_type->is_unsigned ());
+
+ return result;
+}
+
/* Cast value ARG2 to type TYPE and return as a value.
More general than a C cast: accepts any two types of the same length,
and if ARG2 is an lvalue it can be cast into anything at all. */
@@ -349,6 +403,9 @@ value_cast (struct type *type, struct value *arg2)
if (value_type (arg2) == type)
return arg2;
+ if (is_fixed_point_type (type))
+ return value_cast_to_fixed_point (type, arg2);
+
/* Check if we are casting struct reference to struct reference. */
if (TYPE_IS_REFERENCE (check_typedef (type)))
{
@@ -439,7 +496,8 @@ value_cast (struct type *type, struct value *arg2)
scalar = (code2 == TYPE_CODE_INT || code2 == TYPE_CODE_FLT
|| code2 == TYPE_CODE_DECFLOAT || code2 == TYPE_CODE_ENUM
- || code2 == TYPE_CODE_RANGE);
+ || code2 == TYPE_CODE_RANGE
+ || is_fixed_point_type (type2));
if ((code1 == TYPE_CODE_STRUCT || code1 == TYPE_CODE_UNION)
&& (code2 == TYPE_CODE_STRUCT || code2 == TYPE_CODE_UNION)
@@ -460,6 +518,20 @@ value_cast (struct type *type, struct value *arg2)
value_contents_raw (v), type);
return v;
}
+ else if (is_fixed_point_type (type2))
+ {
+ gdb_mpq fp_val;
+
+ fp_val.read_fixed_point
+ (value_contents (arg2), TYPE_LENGTH (type2),
+ type_byte_order (type2), type2->is_unsigned (),
+ fixed_point_scaling_factor (type2));
+
+ struct value *v = allocate_value (to_type);
+ target_float_from_host_double (value_contents_raw (v),
+ to_type, mpq_get_d (fp_val.val));
+ return v;
+ }
/* The only option left is an integral type. */
if (type2->is_unsigned ())
--
2.1.4
^ permalink raw reply [flat|nested] 140+ messages in thread
* [pushed/v2 9/9] Add support for fixed-point type comparison operators
2020-11-15 8:35 ` pushed: " Joel Brobecker
` (7 preceding siblings ...)
2020-11-15 8:35 ` [pushed/v2 8/9] Add support for fixed-point type arithmetic Joel Brobecker
@ 2020-11-15 8:35 ` Joel Brobecker
2020-11-16 23:48 ` pushed: Add support for DWARF-based fixed point types Pedro Alves
` (2 subsequent siblings)
11 siblings, 0 replies; 140+ messages in thread
From: Joel Brobecker @ 2020-11-15 8:35 UTC (permalink / raw)
To: gdb-patches; +Cc: Simon Marchi, Joel Brobecker
This patch adds support for binary comparison operators with
fixed-point type values.
gdb/ChangeLog:
* valarith.c (fixed_point_binop): Add BINOP_EQUAL and BINOP_LESS
handling.
(value_less): Add fixed-point handling.
gdb/testsuite/ChangeLog:
* gdb.ada/fixed_cmp.exp: Add -fgnat-encodings=minimal testing.
* gdb.dwarf2/dw2-fixed-point.c (pck__fp1_var2): New global.
(main): Add reference to pck__fp1_var2.
* gdb.dwarf2/dw2-fixed-point.exp: Add comparison operator testing.
---
gdb/ChangeLog | 6 ++
gdb/testsuite/ChangeLog | 7 ++
gdb/testsuite/gdb.ada/fixed_cmp.exp | 2 +-
gdb/testsuite/gdb.dwarf2/dw2-fixed-point.c | 7 ++
gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp | 102 +++++++++++++++++++++++++++
gdb/valarith.c | 15 +++-
6 files changed, 137 insertions(+), 2 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index e9f0afd..6d0a0c6 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,11 @@
2020-11-15 Joel Brobecker <brobecker@adacore.com>
+ * valarith.c (fixed_point_binop): Add BINOP_EQUAL and BINOP_LESS
+ handling.
+ (value_less): Add fixed-point handling.
+
+2020-11-15 Joel Brobecker <brobecker@adacore.com>
+
* eval.c (binop_promote): Add fixed-point type handling.
* valarith.c (fixed_point_binop): New function.
(scalar_binop): Add fixed-point type handling.
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 3c53f6c..6ecb04c 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,12 @@
2020-11-15 Joel Brobecker <brobecker@adacore.com>
+ * gdb.ada/fixed_cmp.exp: Add -fgnat-encodings=minimal testing.
+ * gdb.dwarf2/dw2-fixed-point.c (pck__fp1_var2): New global.
+ (main): Add reference to pck__fp1_var2.
+ * gdb.dwarf2/dw2-fixed-point.exp: Add comparison operator testing.
+
+2020-11-15 Joel Brobecker <brobecker@adacore.com>
+
* gdb.dwarf2/dw2-fixed-point.exp: Add arithmetic tests.
2020-11-15 Joel Brobecker <brobecker@adacore.com>
diff --git a/gdb/testsuite/gdb.ada/fixed_cmp.exp b/gdb/testsuite/gdb.ada/fixed_cmp.exp
index cfdbb1c..e2c88b8 100644
--- a/gdb/testsuite/gdb.ada/fixed_cmp.exp
+++ b/gdb/testsuite/gdb.ada/fixed_cmp.exp
@@ -19,7 +19,7 @@ if { [skip_ada_tests] } { return -1 }
standard_ada_testfile fixed
-foreach_with_prefix gnat_encodings {all} {
+foreach_with_prefix gnat_encodings {all minimal} {
set flags [list debug additional_flags=-fgnat-encodings=$gnat_encodings]
if {[gdb_compile_ada "${srcfile}" "${binfile}" executable $flags] != "" } {
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.c b/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.c
index d9c811c..971a7a8 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.c
+++ b/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.c
@@ -23,6 +23,12 @@
int8_t pck__fp1_var = 4;
/* Simulate an Ada variable declared inside package Pck as follow:
+ type FP1_Type is delta 0.1 range -1.0 .. +1.0;
+ FP1_Var2 : FP1_Type := 0.50;
+ Basically, the same as FP1_Var, but with a different value. */
+int8_t pck__fp1_var2 = 8;
+
+/* Simulate an Ada variable declared inside package Pck as follow:
type FP2_Type is delta 0.01 digits 14;
FP2_Var : FP2_Type := -0.01; */
int32_t pck__fp2_var = -1;
@@ -41,6 +47,7 @@ int
main (void)
{
pck__fp1_var++;
+ pck__fp1_var2++;
pck__fp2_var++;
pck__fp3_var++;
pck__fp1_range_var++;
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp b/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp
index 0252195..a82a9af 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp
@@ -49,6 +49,15 @@ Dwarf::assemble $asm_file {
{external 1 flag}
}
+ DW_TAG_variable {
+ {DW_AT_name pck__fp1_var2}
+ {DW_AT_type :$fp1_base_type}
+ {DW_AT_location {
+ DW_OP_addr [gdb_target_symbol pck__fp1_var2]
+ } SPECIAL_expr}
+ {external 1 flag}
+ }
+
fp2_base_type: DW_TAG_base_type {
{DW_AT_byte_size 1 DW_FORM_sdata}
{DW_AT_encoding @DW_ATE_signed_fixed}
@@ -161,6 +170,99 @@ gdb_test "print pck.fp1_range_var - 0.5" \
gdb_test "print -pck.fp1_var" \
" = -0.25"
+gdb_test "print pck.fp1_var = pck.fp1_var" \
+ " = true"
+
+gdb_test "print pck.fp1_var = pck.fp1_var2" \
+ " = false"
+
+gdb_test "print pck.fp1_var /= pck.fp1_var" \
+ " = false"
+
+gdb_test "print pck.fp1_var /= pck.fp1_var2" \
+ " = true"
+
+gdb_test "print pck.fp1_var < pck.fp1_var" \
+ " = false"
+
+gdb_test "print pck.fp1_var < pck.fp1_var2" \
+ " = true"
+
+gdb_test "print pck.fp1_var <= pck.fp1_var2" \
+ " = true"
+
+gdb_test "print pck.fp1_var <= pck.fp1_var" \
+ " = true"
+
+gdb_test "print pck.fp1_var > pck.fp1_var2" \
+ " = false"
+
+gdb_test "print pck.fp1_var2 > pck.fp1_var" \
+ " = true"
+
+gdb_test "print pck.fp1_var >= pck.fp1_var" \
+ " = true"
+
+gdb_test "print pck.fp1_var >= pck.fp1_var2" \
+ " = false"
+
+# Same as above, but with litterals...
+
+gdb_test "print pck.fp1_var = 0.25" \
+ " = true"
+
+gdb_test "print pck.fp1_var = 0.5" \
+ " = false"
+
+gdb_test "print pck.fp1_var = 1" \
+ " = false"
+
+gdb_test "print pck.fp1_var /= 0.25" \
+ " = false"
+
+gdb_test "print pck.fp1_var /= 0.5" \
+ " = true"
+
+gdb_test "print pck.fp1_var /= 1" \
+ " = true"
+
+gdb_test "print pck.fp1_var < 0.25" \
+ " = false"
+
+gdb_test "print pck.fp1_var < 0.5" \
+ " = true"
+
+gdb_test "print pck.fp1_var < 1" \
+ " = true"
+
+gdb_test "print pck.fp1_var <= 0.25" \
+ " = true"
+
+gdb_test "print pck.fp1_var <= 0.5" \
+ " = true"
+
+gdb_test "print pck.fp1_var <= 1" \
+ " = true"
+
+gdb_test "print pck.fp1_var > 0.25" \
+ " = false"
+
+gdb_test "print pck.fp1_var > 0.5" \
+ " = false"
+
+gdb_test "print pck.fp1_var > 1" \
+ " = false"
+
+gdb_test "print pck.fp1_var >= 0.25" \
+ " = true"
+
+gdb_test "print pck.fp1_var >= 0.5" \
+ " = false"
+
+gdb_test "print pck.fp1_var >= 1" \
+ " = false"
+
+
# Set the language to LANG and do a ptype test on pck__fp1_var,
# pck__fp2_var and pck__fp3_var, verifying that the output matches
# FP1_RE, FP2_RE, FP2_RE (resp.).
diff --git a/gdb/valarith.c b/gdb/valarith.c
index 65a6f13..f4497cd 100644
--- a/gdb/valarith.c
+++ b/gdb/valarith.c
@@ -890,7 +890,9 @@ fixed_point_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
{
struct type *type1 = check_typedef (value_type (arg1));
struct type *type2 = check_typedef (value_type (arg2));
+ const struct language_defn *language = current_language;
+ struct gdbarch *gdbarch = get_type_arch (type1);
struct value *val;
gdb_assert (is_fixed_point_type (type1) || is_fixed_point_type (type2));
@@ -952,6 +954,16 @@ fixed_point_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
INIT_VAL_WITH_FIXED_POINT_VAL (res);
break;
+ case BINOP_EQUAL:
+ val = value_from_ulongest (language_bool_type (language, gdbarch),
+ mpq_cmp (v1.val, v2.val) == 0 ? 1 : 0);
+ break;
+
+ case BINOP_LESS:
+ val = value_from_ulongest (language_bool_type (language, gdbarch),
+ mpq_cmp (v1.val, v2.val) < 0 ? 1 : 0);
+ break;
+
default:
error (_("Integer-only operation on fixed point number."));
}
@@ -1774,7 +1786,8 @@ value_less (struct value *arg1, struct value *arg2)
is_int1 = is_integral_type (type1);
is_int2 = is_integral_type (type2);
- if (is_int1 && is_int2)
+ if ((is_int1 && is_int2)
+ || (is_fixed_point_type (type1) && is_fixed_point_type (type2)))
return longest_to_int (value_as_long (value_binop (arg1, arg2,
BINOP_LESS)));
else if ((is_floating_value (arg1) || is_int1)
--
2.1.4
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: pushed: Add support for DWARF-based fixed point types
2020-11-15 8:35 ` pushed: " Joel Brobecker
` (8 preceding siblings ...)
2020-11-15 8:35 ` [pushed/v2 9/9] Add support for fixed-point type comparison operators Joel Brobecker
@ 2020-11-16 23:48 ` Pedro Alves
2020-11-17 14:25 ` Simon Marchi
2020-11-20 14:08 ` pushed: Add support for DWARF-based fixed point types Pedro Alves
2020-11-22 11:56 ` RFA/doco: Various changes related to GMP and fixed point type support Joel Brobecker
11 siblings, 1 reply; 140+ messages in thread
From: Pedro Alves @ 2020-11-16 23:48 UTC (permalink / raw)
To: Joel Brobecker, gdb-patches; +Cc: Simon Marchi
Hi Joel,
On 11/15/20 8:35 AM, Joel Brobecker wrote:
> Hi everyone,
>
> I just finished pusing the following patch series to branch master.
I noticed that a new unit test added by this series is failing for me on
Ubuntu 20.04, which has libgmp.so.10.4.0 :
$ ./gdb -ex "maint selftest gdb_mpq_write_fixed_point"
GNU gdb (GDB) 11.0.50.20201116-git
...
Running selftest gdb_mpq_write_fixed_point.
*** stack smashing detected ***: terminated
Aborted (core dumped)
$
I've built a clean gdb from scratch to confirm.
The test passes on Fedora 27, which has libgmp.so.10.3.2:
$ ./gdb -ex "maint selftest gdb_mpq_write_fixed_point"
GNU gdb (GDB) 11.0.50.20201116-git
Running selftest gdb_mpq_write_fixed_point.
Ran 1 unit tests, 0 failed
Anyone else seeing this?
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: pushed: Add support for DWARF-based fixed point types
2020-11-16 23:48 ` pushed: Add support for DWARF-based fixed point types Pedro Alves
@ 2020-11-17 14:25 ` Simon Marchi
2020-11-18 3:47 ` Joel Brobecker
0 siblings, 1 reply; 140+ messages in thread
From: Simon Marchi @ 2020-11-17 14:25 UTC (permalink / raw)
To: Pedro Alves, Joel Brobecker, gdb-patches
On 2020-11-16 6:48 p.m., Pedro Alves wrote:
> Hi Joel,
>
> On 11/15/20 8:35 AM, Joel Brobecker wrote:
>> Hi everyone,
>>
>> I just finished pusing the following patch series to branch master.
>
> I noticed that a new unit test added by this series is failing for me on
> Ubuntu 20.04, which has libgmp.so.10.4.0 :
>
> $ ./gdb -ex "maint selftest gdb_mpq_write_fixed_point"
> GNU gdb (GDB) 11.0.50.20201116-git
> ...
> Running selftest gdb_mpq_write_fixed_point.
> *** stack smashing detected ***: terminated
> Aborted (core dumped)
> $
>
> I've built a clean gdb from scratch to confirm.
>
> The test passes on Fedora 27, which has libgmp.so.10.3.2:
>
> $ ./gdb -ex "maint selftest gdb_mpq_write_fixed_point"
> GNU gdb (GDB) 11.0.50.20201116-git
> Running selftest gdb_mpq_write_fixed_point.
> Ran 1 unit tests, 0 failed
>
> Anyone else seeing this?
>
I didn't see it in my -O0 compiled GDB, but I do see it in my -O2 compiled GDB.
Simon
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: pushed: Add support for DWARF-based fixed point types
2020-11-17 14:25 ` Simon Marchi
@ 2020-11-18 3:47 ` Joel Brobecker
2020-11-22 13:12 ` [RFA] Add TYPE_CODE_FIXED_POINT handling in print_type_scalar Joel Brobecker
2020-11-22 14:00 ` pushed: Add support for DWARF-based fixed point types Joel Brobecker
0 siblings, 2 replies; 140+ messages in thread
From: Joel Brobecker @ 2020-11-18 3:47 UTC (permalink / raw)
To: Simon Marchi; +Cc: Pedro Alves, gdb-patches
> > $ ./gdb -ex "maint selftest gdb_mpq_write_fixed_point"
> > GNU gdb (GDB) 11.0.50.20201116-git
> > ...
> > Running selftest gdb_mpq_write_fixed_point.
> > *** stack smashing detected ***: terminated
> > Aborted (core dumped)
> > $
> >
> > I've built a clean gdb from scratch to confirm.
> >
> > The test passes on Fedora 27, which has libgmp.so.10.3.2:
> >
> > $ ./gdb -ex "maint selftest gdb_mpq_write_fixed_point"
> > GNU gdb (GDB) 11.0.50.20201116-git
> > Running selftest gdb_mpq_write_fixed_point.
> > Ran 1 unit tests, 0 failed
> >
> > Anyone else seeing this?
> >
>
> I didn't see it in my -O0 compiled GDB, but I do see it in my -O2 compiled GDB.
Hmmm, I'm wondering if this might be indicative of a bug in GDB,
rather than in GMP. I will take a look at it this weekend.
Thanks Pedro and Simon.
--
Joel
^ permalink raw reply [flat|nested] 140+ messages in thread
* [RFA] Add TYPE_CODE_FIXED_POINT handling in print_type_scalar
2020-11-18 3:47 ` Joel Brobecker
@ 2020-11-22 13:12 ` Joel Brobecker
2020-11-22 14:35 ` Simon Marchi
2020-11-22 14:00 ` pushed: Add support for DWARF-based fixed point types Joel Brobecker
1 sibling, 1 reply; 140+ messages in thread
From: Joel Brobecker @ 2020-11-22 13:12 UTC (permalink / raw)
To: gdb-patches; +Cc: Simon Marchi, Joel Brobecker
Hello,
This commit enhances print_type_scalar to include support for
TYPE_CODE_FIXED_POINT. This way, any language falling back to
this function for printing the description of some types
also gets basic ptype support for fixed point types as well.
This fixes a couple of XFAILs in gdb.dwarf2/dw2-fixed-point.exp.
gdb/ChangeLog:
* typeprint.c (print_type_scalar): Add handling of
TYPE_CODE_FIXED_POINT.
gdb/testsuite/ChangeLog:
* gdb.dwarf2/dw2-fixed-point.exp: Fix the expected output of
the "ptype pck__fp1_range_var" test for the module-2 and pascal
languages. Remove the associated setup_xfail.
The ptype output for range types in modula-2 and pascal is a little
odd (the type info is repeated twice around the ".." operator), but
I guess that's how they present range types in those languages.
Tested on x86_64-linux, with the 2 XFAILs replaced by PASSes and
no regression.
OK to push to master?
Thanks,
--
Joel
---
gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp | 28 ++++++++++++++++++----------
gdb/typeprint.c | 4 ++++
2 files changed, 22 insertions(+), 10 deletions(-)
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp b/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp
index a82a9af..67d1d34 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-fixed-point.exp
@@ -278,9 +278,6 @@ proc do_ptype_test {lang fp1_re fp2_re fp3_re fp1_range_re} {
gdb_test "ptype pck__fp3_var" $fp3_re
- if { $lang == "modula-2" || $lang == "pascal" } {
- setup_xfail "*-*-*" "not supported by language"
- }
gdb_test "ptype pck__fp1_range_var" $fp1_range_re
}
}
@@ -299,10 +296,21 @@ foreach lang [list "c" "d" "go" "objective-c" "opencl" ] {
" = <range type>"
}
-foreach lang [list "fortran" "modula-2" "pascal" ] {
- do_ptype_test $lang \
- " = pck__fp1_type" \
- " = pck__fp2_type" \
- " = pck__fp3_type" \
- " = <range type>"
-}
+do_ptype_test "fortran" \
+ " = pck__fp1_type" \
+ " = pck__fp2_type" \
+ " = pck__fp3_type" \
+ " = <range type>"
+
+do_ptype_test "modula-2" \
+ " = pck__fp1_type" \
+ " = pck__fp2_type" \
+ " = pck__fp3_type" \
+ " = \\\[1-byte fixed point \\(small = 1/16\\)\\.\\.1-byte fixed point \\(small = 1/16\\)\\\]"
+
+do_ptype_test "pascal" \
+ " = pck__fp1_type" \
+ " = pck__fp2_type" \
+ " = pck__fp3_type" \
+ " = 1-byte fixed point \\(small = 1/16\\)\\.\\.1-byte fixed point \\(small = 1/16\\)"
+
diff --git a/gdb/typeprint.c b/gdb/typeprint.c
index a3fc9cc..47019a2 100644
--- a/gdb/typeprint.c
+++ b/gdb/typeprint.c
@@ -637,6 +637,10 @@ print_type_scalar (struct type *type, LONGEST val, struct ui_file *stream)
print_type_scalar (TYPE_TARGET_TYPE (type), val, stream);
return;
+ case TYPE_CODE_FIXED_POINT:
+ print_type_fixed_point (type, stream);
+ break;
+
case TYPE_CODE_UNDEF:
case TYPE_CODE_PTR:
case TYPE_CODE_ARRAY:
--
2.1.4
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [RFA] Add TYPE_CODE_FIXED_POINT handling in print_type_scalar
2020-11-22 13:12 ` [RFA] Add TYPE_CODE_FIXED_POINT handling in print_type_scalar Joel Brobecker
@ 2020-11-22 14:35 ` Simon Marchi
2020-11-24 3:04 ` Joel Brobecker
0 siblings, 1 reply; 140+ messages in thread
From: Simon Marchi @ 2020-11-22 14:35 UTC (permalink / raw)
To: Joel Brobecker, gdb-patches
On 2020-11-22 8:12 a.m., Joel Brobecker wrote:
> Hello,
>
> This commit enhances print_type_scalar to include support for
> TYPE_CODE_FIXED_POINT. This way, any language falling back to
> this function for printing the description of some types
> also gets basic ptype support for fixed point types as well.
>
> This fixes a couple of XFAILs in gdb.dwarf2/dw2-fixed-point.exp.
>
> gdb/ChangeLog:
>
> * typeprint.c (print_type_scalar): Add handling of
> TYPE_CODE_FIXED_POINT.
>
> gdb/testsuite/ChangeLog:
>
> * gdb.dwarf2/dw2-fixed-point.exp: Fix the expected output of
> the "ptype pck__fp1_range_var" test for the module-2 and pascal
> languages. Remove the associated setup_xfail.
>
> The ptype output for range types in modula-2 and pascal is a little
> odd (the type info is repeated twice around the ".." operator), but
> I guess that's how they present range types in those languages.
Yeah, it seems like it. Thanks for doing this, the change to handle
fixed point in the generic print_type_scalar function looks good to me.
Simon
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [RFA] Add TYPE_CODE_FIXED_POINT handling in print_type_scalar
2020-11-22 14:35 ` Simon Marchi
@ 2020-11-24 3:04 ` Joel Brobecker
0 siblings, 0 replies; 140+ messages in thread
From: Joel Brobecker @ 2020-11-24 3:04 UTC (permalink / raw)
To: Simon Marchi; +Cc: gdb-patches
> > gdb/ChangeLog:
> >
> > * typeprint.c (print_type_scalar): Add handling of
> > TYPE_CODE_FIXED_POINT.
> >
> > gdb/testsuite/ChangeLog:
> >
> > * gdb.dwarf2/dw2-fixed-point.exp: Fix the expected output of
> > the "ptype pck__fp1_range_var" test for the module-2 and pascal
> > languages. Remove the associated setup_xfail.
> >
> > The ptype output for range types in modula-2 and pascal is a little
> > odd (the type info is repeated twice around the ".." operator), but
> > I guess that's how they present range types in those languages.
>
> Yeah, it seems like it. Thanks for doing this, the change to handle
> fixed point in the generic print_type_scalar function looks good to me.
Thank you Simon. Patch pushed to master.
--
Joel
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: pushed: Add support for DWARF-based fixed point types
2020-11-18 3:47 ` Joel Brobecker
2020-11-22 13:12 ` [RFA] Add TYPE_CODE_FIXED_POINT handling in print_type_scalar Joel Brobecker
@ 2020-11-22 14:00 ` Joel Brobecker
2020-11-22 20:11 ` Simon Marchi
1 sibling, 1 reply; 140+ messages in thread
From: Joel Brobecker @ 2020-11-22 14:00 UTC (permalink / raw)
To: Simon Marchi; +Cc: gdb-patches
> > I didn't see it in my -O0 compiled GDB, but I do see it in my -O2
> > compiled GDB.
>
> Hmmm, I'm wondering if this might be indicative of a bug in GDB,
> rather than in GMP. I will take a look at it this weekend.
I've been able to reproduce the problem, including with a GDB
built at -O0. In order to do so, I had to use the system GCC,
though. Before that, I was using AdaCore's version of GCC and
couldn't reproduce with that.
I'm out of time for this weekend, unfortunately, so it's at the top
of my TODO for next weekend.
--
Joel
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: pushed: Add support for DWARF-based fixed point types
2020-11-22 14:00 ` pushed: Add support for DWARF-based fixed point types Joel Brobecker
@ 2020-11-22 20:11 ` Simon Marchi
2020-11-23 4:27 ` Joel Brobecker
0 siblings, 1 reply; 140+ messages in thread
From: Simon Marchi @ 2020-11-22 20:11 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
On 2020-11-22 9:00 a.m., Joel Brobecker wrote:
> I've been able to reproduce the problem, including with a GDB
> built at -O0. In order to do so, I had to use the system GCC,
> though. Before that, I was using AdaCore's version of GCC and
> couldn't reproduce with that.
>
> I'm out of time for this weekend, unfortunately, so it's at the top
> of my TODO for next weekend.
I didn't find the root cause (and whether GDB using GMP wrong or if it
is a bug in GMP (less likely)), but here's what I found.
Building both GDB and GMP with ASan makes the issue more obvious:
Running selftest gdb_mpq_write_fixed_point.
=================================================================
==3672064==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffd6de06d08 at pc 0x7f185073086d bp 0x7ffd6de068a0 sp 0x7ffd6de06890
WRITE of size 8 at 0x7ffd6de06d08 thread T0
#0 0x7f185073086c in __gmpz_export /home/smarchi/src/gmp-6.2.0+dfsg/mpz/export.c:103
#1 0x557c2db68395 in gdb_mpz::write(unsigned char*, int, bfd_endian, bool) const /home/smarchi/src/binutils-gdb/gdb/gmp-utils.c:80
#2 0x557c2db68d02 in gdb_mpq::write_fixed_point(unsigned char*, int, bfd_endian, bool, gdb_mpq const&) const /home/smarchi/src/binutils-gdb/gdb/gmp-utils.c:144
#3 0x557c2ed2f796 in write_fp_test /home/smarchi/src/binutils-gdb/gdb/unittests/gmp-utils-selftests.c:405
#4 0x557c2ed2f949 in gdb_mpq_write_fixed_point /home/smarchi/src/binutils-gdb/gdb/unittests/gmp-utils-selftests.c:426
#5 0x557c300b280c in selftests::simple_selftest::operator()() const /home/smarchi/src/binutils-gdb/gdbsupport/selftest.cc:43
#6 0x557c300b22e2 in selftests::run_tests(gdb::array_view<char const* const>) /home/smarchi/src/binutils-gdb/gdbsupport/selftest.cc:99
#7 0x557c2dfce6c2 in maintenance_selftest /home/smarchi/src/binutils-gdb/gdb/maint.c:1026
#8 0x557c2d3dbe12 in do_const_cfunc /home/smarchi/src/binutils-gdb/gdb/cli/cli-decode.c:95
#9 0x557c2d3eb02d in cmd_func(cmd_list_element*, char const*, int) /home/smarchi/src/binutils-gdb/gdb/cli/cli-decode.c:2181
#10 0x557c2eb6e985 in execute_command(char const*, int) /home/smarchi/src/binutils-gdb/gdb/top.c:668
#11 0x557c2dfaa4c9 in catch_command_errors /home/smarchi/src/binutils-gdb/gdb/main.c:448
#12 0x557c2dfaacf0 in execute_cmdargs /home/smarchi/src/binutils-gdb/gdb/main.c:533
#13 0x557c2dfae6b1 in captured_main_1 /home/smarchi/src/binutils-gdb/gdb/main.c:1203
#14 0x557c2dfaebc5 in captured_main /home/smarchi/src/binutils-gdb/gdb/main.c:1224
#15 0x557c2dfaecad in gdb_main(captured_main_args*) /home/smarchi/src/binutils-gdb/gdb/main.c:1249
#16 0x557c2cdd0311 in main /home/smarchi/src/binutils-gdb/gdb/gdb.c:32
#17 0x7f184f9850b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
#18 0x557c2cdd00ed in _start (/home/smarchi/build/binutils-gdb-all-targets/gdb/gdb+0x4a2e0ed)
Address 0x7ffd6de06d08 is located in stack of thread T0 at offset 104 in frame
#0 0x557c2ed2f669 in write_fp_test /home/smarchi/src/binutils-gdb/gdb/unittests/gmp-utils-selftests.c:393
This frame has 2 object(s):
[32, 64) 'v' (line 402)
[96, 104) 'buf' (line 399) <== Memory access at offset 104 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow /home/smarchi/src/gmp-6.2.0+dfsg/mpz/export.c:103 in __gmpz_export
We pass mpz_export a buffer of 8 bytes (statically allocated in
write_fp_test), but GMP decides it needs to write 16 bytes, hence the
overflow.
I tried to read the GMP doc, but I am familiar with its concepts, so I
don't really understand if we are using the API correctly or not.
For reference this is how I configured libgmp:
./configure '--prefix=/tmp/gmp-install' 'CFLAGS=-g3 -O0 -fsanitize=address' 'CXXFLAGS=-g3 -O0 -fsanitize=address' 'LDFLAGS=-fsanitize=address'
Simon
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: pushed: Add support for DWARF-based fixed point types
2020-11-22 20:11 ` Simon Marchi
@ 2020-11-23 4:27 ` Joel Brobecker
2020-11-23 16:12 ` Simon Marchi
2020-11-29 15:45 ` RFA: wrap mpz_export into gdb_mpz::safe_export Joel Brobecker
0 siblings, 2 replies; 140+ messages in thread
From: Joel Brobecker @ 2020-11-23 4:27 UTC (permalink / raw)
To: Simon Marchi; +Cc: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1233 bytes --]
> We pass mpz_export a buffer of 8 bytes (statically allocated in
> write_fp_test), but GMP decides it needs to write 16 bytes, hence the
> overflow.
>
> I tried to read the GMP doc, but I am familiar with its concepts, so I
> don't really understand if we are using the API correctly or not.
I found the source of the problem, which was in a way subtle-enough
that you really have to pay attention to these details (which,
luckily, are handled automatically thanks to our minor C++-ification
of GMP in gmp-utils), and yet so obvious once you find it.
Attached is the patch that I will push later today (need to run RSN,
and don't want to make a mistake because I'm rushing).
I think this error might be highlighting a weakness, though. I need
to investigate more, but I'm thinking it might be wise to add some
checks during export that the buffer size is large enough to fit
the value. In other words, I'm thinking of having our own
safe_mpz_export which double-checks the size of the buffer according
to the formula given by the documentation, and raises an error if
too small.
The fact that GMP happily goes beyond the end of the buffer is
a bit unexpected, still. Maybe something to report to the GMP team.
Later!
--
Joel
[-- Attachment #2: 0001-Fix-stack-smashing-error-during-gdb_mpq_write_fixed_.patch --]
[-- Type: text/x-diff, Size: 2944 bytes --]
From 1cb4f9e076dbd87808783e6f4f54b4b22c45d0e5 Mon Sep 17 00:00:00 2001
From: Joel Brobecker <brobecker@adacore.com>
Date: Mon, 23 Nov 2020 08:02:10 +0400
Subject: [PATCH] Fix stack smashing error during gdb_mpq_write_fixed_point
selftest
When building GDB using Ubuntu 20.04's system libgmp and compiler,
running the "maintenance selftest" command triggers the following error:
| Running selftest gdb_mpq_write_fixed_point.
| *** stack smashing detected ***: terminated
| [1] 1092790 abort (core dumped) ./gdb gdb
This happens while trying to construct an mpq_t object (a rational)
from two integers representing the numerator and denominator.
In our test, the numerator is -8, and the denominator is 1.
The problem was that the rational was constructed using the wrong
function. This is what we were doing prior to this patch:
mpq_set_ui (v.val, numerator, denominator);
The 'u' in "ui" stands for *unsigned*, which is wrong because
numerator and denominator's type is "int".
As a result of the above, instead of getting a rational value of -8,
we get a rational with a very large positive value (gmp_printf
says "18446744073709551608").
From there, the test performs an operation which is expected to
write this value into a buffer which was not dimensioned to fit
such a number, thus leading GMP into a buffer overflow.
This was verified by applying the formula that GMP's documentation
gives for the required memory buffer size needed during export:
| When an application is allocating space itself the required size can
| be determined with a calculation like the following. Since
| mpz_sizeinbase always returns at least 1, count here will be at
| least one, which avoids any portability problems with malloc(0),
| though if z is zero no space at all is actually needed (or written).
|
| numb = 8*size - nail;
| count = (mpz_sizeinbase (z, 2) + numb-1) / numb;
| p = malloc (count * size);
With the very large number, mpz_sizeinbase returns 66 and thus
the malloc size becomes 16 bytes instead of the 8 we allocated.
This patch fixes the issue by using the correct "set" function.
gdb/ChangeLog:
* unittests/gmp-utils-selftests.c (write_fp_test): Use mpq_set_si
instead of mpq_set_ui to initialize our GMP rational.
---
gdb/unittests/gmp-utils-selftests.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gdb/unittests/gmp-utils-selftests.c b/gdb/unittests/gmp-utils-selftests.c
index af5bc65d2f9..175ab3f9827 100644
--- a/gdb/unittests/gmp-utils-selftests.c
+++ b/gdb/unittests/gmp-utils-selftests.c
@@ -400,7 +400,7 @@ write_fp_test (int numerator, unsigned int denominator,
memset (buf, 0, len);
gdb_mpq v;
- mpq_set_ui (v.val, numerator, denominator);
+ mpq_set_si (v.val, numerator, denominator);
mpq_canonicalize (v.val);
v.write_fixed_point (buf, len, byte_order, 0, scaling_factor);
--
2.25.1
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: pushed: Add support for DWARF-based fixed point types
2020-11-23 4:27 ` Joel Brobecker
@ 2020-11-23 16:12 ` Simon Marchi
2020-11-24 2:39 ` Joel Brobecker
2020-11-29 15:45 ` RFA: wrap mpz_export into gdb_mpz::safe_export Joel Brobecker
1 sibling, 1 reply; 140+ messages in thread
From: Simon Marchi @ 2020-11-23 16:12 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
On 2020-11-22 11:27 p.m., Joel Brobecker wrote:
>> We pass mpz_export a buffer of 8 bytes (statically allocated in
>> write_fp_test), but GMP decides it needs to write 16 bytes, hence the
>> overflow.
>>
>> I tried to read the GMP doc, but I am familiar with its concepts, so I
>> don't really understand if we are using the API correctly or not.
>
> I found the source of the problem, which was in a way subtle-enough
> that you really have to pay attention to these details (which,
> luckily, are handled automatically thanks to our minor C++-ification
> of GMP in gmp-utils), and yet so obvious once you find it.
> Attached is the patch that I will push later today (need to run RSN,
> and don't want to make a mistake because I'm rushing).
>
> I think this error might be highlighting a weakness, though. I need
> to investigate more, but I'm thinking it might be wise to add some
> checks during export that the buffer size is large enough to fit
> the value. In other words, I'm thinking of having our own
> safe_mpz_export which double-checks the size of the buffer according
> to the formula given by the documentation, and raises an error if
> too small.
>
> The fact that GMP happily goes beyond the end of the buffer is
> a bit unexpected, still. Maybe something to report to the GMP team.
Ah, nice! The explanation in the commit message makes sense, thanks.
And yes, please go wild adding assertions!
Simon
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: pushed: Add support for DWARF-based fixed point types
2020-11-23 16:12 ` Simon Marchi
@ 2020-11-24 2:39 ` Joel Brobecker
0 siblings, 0 replies; 140+ messages in thread
From: Joel Brobecker @ 2020-11-24 2:39 UTC (permalink / raw)
To: Simon Marchi; +Cc: gdb-patches
> > I found the source of the problem, which was in a way subtle-enough
> > that you really have to pay attention to these details (which,
> > luckily, are handled automatically thanks to our minor C++-ification
> > of GMP in gmp-utils), and yet so obvious once you find it.
> > Attached is the patch that I will push later today (need to run RSN,
> > and don't want to make a mistake because I'm rushing).
> >
> > I think this error might be highlighting a weakness, though. I need
> > to investigate more, but I'm thinking it might be wise to add some
> > checks during export that the buffer size is large enough to fit
> > the value. In other words, I'm thinking of having our own
> > safe_mpz_export which double-checks the size of the buffer according
> > to the formula given by the documentation, and raises an error if
> > too small.
> >
> > The fact that GMP happily goes beyond the end of the buffer is
> > a bit unexpected, still. Maybe something to report to the GMP team.
>
> Ah, nice! The explanation in the commit message makes sense, thanks.
My pleasure. I was relieved to find that the main issue was in
the unittest itself! There's still the question of protecting
ourselves from this kind of issue, just in case, but at least
there we know what to be careful of.
I just pushed the patch to master, and will work on catching
those issues over the weekend.
gdb/ChangeLog:
* unittests/gmp-utils-selftests.c (write_fp_test): Use mpq_set_si
instead of mpq_set_ui to initialize our GMP rational.
--
Joel
^ permalink raw reply [flat|nested] 140+ messages in thread
* RFA: wrap mpz_export into gdb_mpz::safe_export...
2020-11-23 4:27 ` Joel Brobecker
2020-11-23 16:12 ` Simon Marchi
@ 2020-11-29 15:45 ` Joel Brobecker
2020-11-29 15:45 ` [RFA 1/2] Fix TARGET_CHAR_BIT/HOST_CHAR_BIT confusion in gmp-utils.c Joel Brobecker
` (2 more replies)
1 sibling, 3 replies; 140+ messages in thread
From: Joel Brobecker @ 2020-11-29 15:45 UTC (permalink / raw)
To: gdb-patches; +Cc: Simon Marchi
Hello,
As discussed earlier this week when we discovered that we need to be
careful before calling mpz_export, the purpose of this patch series is
to introduce a new gdb_mpz method called safe_export that GDB can use
to make sure we don't have any buffer overrun. As it happens, you'll
see from patch #2 that I found a number of areas we could improve.
For the record, I didn't do the following, but I was thinking it would
be nice to poison mpz_export if we could. We can do that as a followup
patch, if we'd like, although I will likely need a bit of help doing so,
because I am not sure how to poison it for the entire GDB except the one
place where it's OK to use it. In the end, it sounds to me like Tom
wants to wrap GDB's usage of gmp into the gdb_mp[xxx] classes, and so,
once we have that, it seems unlikely that someone would unwittingly use
mpz_export directly.
Patch #1 is just something I noticed. Truth be told, I am kind of
second guessing myself on that one... Luckily, it's easy to just
drop it if it turns out I was wrong.
* [RFA 1/2] Fix TARGET_CHAR_BIT/HOST_CHAR_BIT confusion in gmp-utils.c
* [RFA 2/2] gmp-utils: protect gdb_mpz exports against out-of-range
The patches above were tested on x86_64-linux, with both the official
testsuite, as well as AdaCore's testsuite (just in case).
OK to push to master?
Thank you!
--
Joel
^ permalink raw reply [flat|nested] 140+ messages in thread
* [RFA 1/2] Fix TARGET_CHAR_BIT/HOST_CHAR_BIT confusion in gmp-utils.c
2020-11-29 15:45 ` RFA: wrap mpz_export into gdb_mpz::safe_export Joel Brobecker
@ 2020-11-29 15:45 ` Joel Brobecker
2020-11-30 15:42 ` Simon Marchi
2020-11-29 15:45 ` [RFA 2/2] gmp-utils: protect gdb_mpz exports against out-of-range values Joel Brobecker
2020-11-30 12:44 ` RFA: wrap mpz_export into gdb_mpz::safe_export Christian Biesinger
2 siblings, 1 reply; 140+ messages in thread
From: Joel Brobecker @ 2020-11-29 15:45 UTC (permalink / raw)
To: gdb-patches; +Cc: Simon Marchi, Joel Brobecker
In a couple of gdb_mpz methods, we are computing the number of
bits in a gdb::array_view of gdb_byte. Since gdb_byte is defined
using a host-side type (see common-types.h), the number of bits
in a gdb_byte should be HOST_CHAR_BIT, not TARGET_CHAR_BIT.
gdb/ChangeLog:
* gmp-utils.c (gdb_mpz::read): Use HOST_CHAR_BIT instead of
TARGET_CHAR_BIT.
(gdb_mpz::write): Likewise.
---
gdb/gmp-utils.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/gdb/gmp-utils.c b/gdb/gmp-utils.c
index 7994108..e3a3333 100644
--- a/gdb/gmp-utils.c
+++ b/gdb/gmp-utils.c
@@ -56,7 +56,7 @@ gdb_mpz::read (gdb::array_view<const gdb_byte> buf, enum bfd_endian byte_order,
was in fact negative, we need to adjust VAL accordingly. */
gdb_mpz max;
- mpz_ui_pow_ui (max.val, 2, buf.size () * TARGET_CHAR_BIT - 1);
+ mpz_ui_pow_ui (max.val, 2, buf.size () * HOST_CHAR_BIT - 1);
if (mpz_cmp (val, max.val) >= 0)
mpz_submul_ui (val, max.val, 2);
}
@@ -77,7 +77,7 @@ gdb_mpz::write (gdb::array_view<gdb_byte> buf, enum bfd_endian byte_order,
would be the same as our negative value. */
gdb_mpz neg_offset;
- mpz_ui_pow_ui (neg_offset.val, 2, buf.size () * TARGET_CHAR_BIT);
+ mpz_ui_pow_ui (neg_offset.val, 2, buf.size () * HOST_CHAR_BIT);
mpz_add (exported_val.val, exported_val.val, neg_offset.val);
}
--
2.1.4
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [RFA 1/2] Fix TARGET_CHAR_BIT/HOST_CHAR_BIT confusion in gmp-utils.c
2020-11-29 15:45 ` [RFA 1/2] Fix TARGET_CHAR_BIT/HOST_CHAR_BIT confusion in gmp-utils.c Joel Brobecker
@ 2020-11-30 15:42 ` Simon Marchi
2020-12-05 8:05 ` Joel Brobecker
0 siblings, 1 reply; 140+ messages in thread
From: Simon Marchi @ 2020-11-30 15:42 UTC (permalink / raw)
To: Joel Brobecker, gdb-patches
On 2020-11-29 10:45 a.m., Joel Brobecker wrote:
> In a couple of gdb_mpz methods, we are computing the number of
> bits in a gdb::array_view of gdb_byte. Since gdb_byte is defined
> using a host-side type (see common-types.h), the number of bits
> in a gdb_byte should be HOST_CHAR_BIT, not TARGET_CHAR_BIT.
Right, and we are not supposed to use TARGET_CHAR_BIT anymore. The same
GDB could be debugging targets with different target char bit values, so
a build-time constant like TARGET_CHAR_BIT can't work. For those cases,
gdbarch_addressable_memory_unit_size should be used instead.
Simon
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [RFA 1/2] Fix TARGET_CHAR_BIT/HOST_CHAR_BIT confusion in gmp-utils.c
2020-11-30 15:42 ` Simon Marchi
@ 2020-12-05 8:05 ` Joel Brobecker
0 siblings, 0 replies; 140+ messages in thread
From: Joel Brobecker @ 2020-12-05 8:05 UTC (permalink / raw)
To: Simon Marchi; +Cc: gdb-patches
> > In a couple of gdb_mpz methods, we are computing the number of
> > bits in a gdb::array_view of gdb_byte. Since gdb_byte is defined
> > using a host-side type (see common-types.h), the number of bits
> > in a gdb_byte should be HOST_CHAR_BIT, not TARGET_CHAR_BIT.
>
> Right, and we are not supposed to use TARGET_CHAR_BIT anymore. The same
> GDB could be debugging targets with different target char bit values, so
> a build-time constant like TARGET_CHAR_BIT can't work. For those cases,
> gdbarch_addressable_memory_unit_size should be used instead.
Thanks for the review and the explanation, Simon.
I just pushed this patch to master.
--
Joel
^ permalink raw reply [flat|nested] 140+ messages in thread
* [RFA 2/2] gmp-utils: protect gdb_mpz exports against out-of-range values
2020-11-29 15:45 ` RFA: wrap mpz_export into gdb_mpz::safe_export Joel Brobecker
2020-11-29 15:45 ` [RFA 1/2] Fix TARGET_CHAR_BIT/HOST_CHAR_BIT confusion in gmp-utils.c Joel Brobecker
@ 2020-11-29 15:45 ` Joel Brobecker
2020-11-30 15:56 ` Simon Marchi
2020-12-05 8:10 ` [RFAv2 " Joel Brobecker
2020-11-30 12:44 ` RFA: wrap mpz_export into gdb_mpz::safe_export Christian Biesinger
2 siblings, 2 replies; 140+ messages in thread
From: Joel Brobecker @ 2020-11-29 15:45 UTC (permalink / raw)
To: gdb-patches; +Cc: Simon Marchi, Joel Brobecker
The gdb_mpz class currently provides a couple of methods which
essentially export an mpz_t value into either a buffer, or an integral
type. The export is based on using the mpz_export function which
we discovered can be a bit treacherous if used without caution.
In particular, the initial motivation for this patch was to catch
situations where the mpz_t value was so large that it would not fit
in the destination area. mpz_export does not know the size of
the buffer, and therefore can happily write past the end of our buffer.
While designing a solution to the above problem, I also discovered
that we also needed to be careful when exporting signed numbers.
In particular, numbers which are larger than the maximum value
for a given signed type size, but no so large as to fit in the
*unsigned* version with the same size, would end up being exported
incorrectly. This is related to the fact that mpz_export ignores
the sign of the value being exportd, and assumes an unsigned export.
Thus, for such large values, the appears as if mpz_export is able
to fit our value into our buffer, but in fact, it does not.
Also, I noticed that gdb_mpz::write wasn't taking its unsigned_p
parameter, which was a hole.
For all these reasons, a new low-level private method called
"safe_export" has been added to class gdb_mpz, whose goal is
to perform all necessary checks and manipulations for a safe
and correct export. As a bonus, this method allows us to factorize
the handling of negative value exports.
The gdb_mpz::as_integer and gdb_mpz::write methods are then simplified
to take advantage of this new safe_export method.
gdb/ChangeLog:
* gmp-utils.h (gdb_mpz::safe_export): New private method.
(gdb_mpz::as_integer): Reimplement using gdb_mpz::safe_export.
* gmp-utils.c (gdb_mpz::write): Rewrite using gdb_mpz::safe_export.
(gdb_mpz::safe_export): New method.
* unittests/gmp-utils-selftests .c (gdb_mpz_as_integer):
Update function description.
(check_as_integer_raises_out_of_range_error): New function.
(gdb_mpz_as_integer_out_of_range): New function.
(_initialize_gmp_utils_selftests): Register
gdb_mpz_as_integer_out_of_range as a selftest.
---
gdb/gmp-utils.c | 79 ++++++++++++++++++++++++++++++++++---
gdb/gmp-utils.h | 44 ++++++++++++---------
gdb/unittests/gmp-utils-selftests.c | 71 +++++++++++++++++++++++++++++++--
3 files changed, 167 insertions(+), 27 deletions(-)
diff --git a/gdb/gmp-utils.c b/gdb/gmp-utils.c
index e3a3333..f94bdc5 100644
--- a/gdb/gmp-utils.c
+++ b/gdb/gmp-utils.c
@@ -68,9 +68,62 @@ void
gdb_mpz::write (gdb::array_view<gdb_byte> buf, enum bfd_endian byte_order,
bool unsigned_p) const
{
+ this->safe_export
+ (buf, byte_order == BFD_ENDIAN_BIG ? 1 : -1 /* endian */, 0 /* nails */,
+ unsigned_p);
+}
+
+/* See gmp-utils.h. */
+
+void
+gdb_mpz::safe_export (gdb::array_view<gdb_byte> buf,
+ int endian, size_t nails, bool unsigned_p) const
+{
+ gdb_assert (buf.size () > 0);
+
+ if (mpz_sgn (val) == 0)
+ {
+ /* Our value is zero, so no need to call mpz_export to do the work,
+ especially since mpz_export's documentation explicitly says
+ that the function is a noop in this case. Just write zero to
+ BUF ourselves. */
+ memset (buf.data (), 0, buf.size ());
+ return;
+ }
+
+ /* Determine the maximum range of values that our buffer can hold,
+ and verify that VAL is within that range. */
+
+ gdb_mpz lo, hi;
+ const size_t max_usable_bits = buf.size () * HOST_CHAR_BIT - nails;
+ if (unsigned_p)
+ {
+ lo = 0;
+
+ mpz_ui_pow_ui (hi.val, 2, max_usable_bits);
+ mpz_sub_ui (hi.val, hi.val, 1);
+ }
+ else
+ {
+ mpz_ui_pow_ui (lo.val, 2, max_usable_bits - 1);
+ mpz_neg (lo.val, lo.val);
+
+ mpz_ui_pow_ui (hi.val, 2, max_usable_bits - 1);
+ mpz_sub_ui (hi.val, hi.val, 1);
+ }
+
+ if (mpz_cmp (val, lo.val) < 0 || mpz_cmp (val, hi.val) > 0)
+ error (_("Cannot export value %s as %zubits %s integer"
+ " (must be between %s and %s)"),
+ this->str ().c_str (),
+ max_usable_bits,
+ unsigned_p ? _("unsigned") : _("signed"),
+ lo.str ().c_str (),
+ hi.str ().c_str ());
+
gdb_mpz exported_val (val);
- if (mpz_cmp_ui (val, 0) < 0)
+ if (mpz_cmp_ui (exported_val.val, 0) < 0)
{
/* mpz_export does not handle signed values, so create a positive
value whose bit representation as an unsigned of the same length
@@ -81,13 +134,27 @@ gdb_mpz::write (gdb::array_view<gdb_byte> buf, enum bfd_endian byte_order,
mpz_add (exported_val.val, exported_val.val, neg_offset.val);
}
+ /* Do the export into a buffer allocated by GMP itself; that way,
+ we can detect cases where BUF is not large enough to export
+ our value, and thus avoid a buffer overlow. Normally, this should
+ never happen, since we verified earlier that the buffer is large
+ enough to accomodate our value, but doing this allows us to be
+ extra safe with the export.
+
+ After verification that the export behaved as expected, we will
+ copy the data over to BUF. */
+
+ size_t word_countp;
+ gdb::unique_xmalloc_ptr<void> exported
+ (mpz_export (NULL, &word_countp, -1 /* order */, buf.size () /* size */,
+ endian, nails, exported_val.val));
+
+ gdb_assert (word_countp == 1);
+
/* Start by clearing the buffer, as mpz_export only writes as many
- bytes as it needs (including none, if the value to export is zero. */
+ bytes as it needs. */
memset (buf.data (), 0, buf.size ());
- mpz_export (buf.data (), NULL /* count */, -1 /* order */,
- buf.size () /* size */,
- byte_order == BFD_ENDIAN_BIG ? 1 : -1 /* endian */,
- 0 /* nails */, exported_val.val);
+ memcpy (buf.data (), exported.get (), buf.size ());
}
/* See gmp-utils.h. */
diff --git a/gdb/gmp-utils.h b/gdb/gmp-utils.h
index 12e4f8e..c2e591c 100644
--- a/gdb/gmp-utils.h
+++ b/gdb/gmp-utils.h
@@ -121,6 +121,26 @@ struct gdb_mpz
/* Helper template for constructor and operator=. */
template<typename T> void set (T src);
+
+ /* Low-level function to export VAL into BUF as a number whose byte size
+ is the size of BUF.
+
+ If UNSIGNED_P is true, then export VAL into BUF as an unsigned value.
+ Otherwise, export it as a signed value.
+
+ The API is inspired from GMP's mpz_export, hence the naming and types
+ of the following parameters:
+ - ENDIAN should be:
+ . 1 for most significant byte first; or
+ . -1 for least significant byte first; or
+ . 0 for native endianness.
+ - The most significant NAILS bits are unused and set to zero
+ (this can be 0 to use all bits).
+
+ An error is raised if BUF is not large enough to contain the value
+ being exported. */
+ void safe_export (gdb::array_view<gdb_byte> buf,
+ int endian, size_t nails, bool unsigned_p) const;
};
/* A class to make it easier to use GMP's mpq_t values within GDB. */
@@ -258,26 +278,14 @@ template<typename T>
T
gdb_mpz::as_integer () const
{
- /* Initialize RESULT, because mpz_export only write the minimum
- number of bytes, including none if our value is zero! */
- T result = 0;
+ T result;
- gdb_mpz exported_val (val);
- if (std::is_signed<T>::value && mpz_cmp_ui (val, 0) < 0)
- {
- /* We want to use mpz_export to set the return value, but
- this function does not handle the sign. So give exported_val
- a value which is at the same time positive, and has the same
- bit representation as our negative value. */
- gdb_mpz neg_offset;
+ this->safe_export (gdb::make_array_view ((gdb_byte *) &result,
+ sizeof (result)),
+ 0 /* endian (0 = native) */,
+ 0 /* nails */,
+ !std::is_signed<T>::value /* unsigned_p */);
- mpz_ui_pow_ui (neg_offset.val, 2, sizeof (T) * HOST_CHAR_BIT);
- mpz_add (exported_val.val, exported_val.val, neg_offset.val);
- }
-
- mpz_export (&result, NULL /* count */, -1 /* order */,
- sizeof (T) /* size */, 0 /* endian (0 = native) */,
- 0 /* nails */, exported_val.val);
return result;
}
diff --git a/gdb/unittests/gmp-utils-selftests.c b/gdb/unittests/gmp-utils-selftests.c
index 1365905..30c1902 100644
--- a/gdb/unittests/gmp-utils-selftests.c
+++ b/gdb/unittests/gmp-utils-selftests.c
@@ -26,9 +26,10 @@ namespace selftests {
/* Perform a series of general tests of gdb_mpz's as_integer method.
- This function tries to be reasonably exhaustive, by testing the edges,
- as well as a resonable set of values including negative ones, zero,
- and positive values. */
+ This function limits itself to values which are in range (out-of-range
+ values will be tested separately). In doing so, it tries to be reasonably
+ exhaustive, by testing the edges, as well as a resonable set of values
+ including negative ones, zero, and positive values. */
static void
gdb_mpz_as_integer ()
@@ -80,6 +81,68 @@ gdb_mpz_as_integer ()
SELF_CHECK (v.as_integer<ULONGEST> () == ul_expected);
}
+/* A helper function which calls the given gdb_mpz object's as_integer
+ method with the given type T, and verifies that this triggers
+ an error due to VAL's value being out of range for type T. */
+
+template<typename T, typename = gdb::Requires<std::is_integral<T>>>
+static void
+check_as_integer_raises_out_of_range_error (const gdb_mpz &val)
+{
+ try
+ {
+ val.as_integer<T> ();
+ }
+ catch (const gdb_exception_error &ex)
+ {
+ SELF_CHECK (ex.reason == RETURN_ERROR);
+ SELF_CHECK (ex.error == GENERIC_ERROR);
+ SELF_CHECK (strstr (ex.what (), "Cannot export value") != nullptr);
+ return;
+ }
+ /* The expected exception did not get raised. */
+ SELF_CHECK (false);
+}
+
+/* Perform out-of-range tests of gdb_mpz's as_integer method.
+
+ The goal of this function is to verify that gdb_mpz::as_integer
+ handles out-of-range values correctly. */
+
+static void
+gdb_mpz_as_integer_out_of_range ()
+{
+ gdb_mpz v;
+
+ /* Try LONGEST_MIN minus 1. */
+ mpz_ui_pow_ui (v.val, 2, sizeof (LONGEST) * 8 - 1);
+ mpz_neg (v.val, v.val);
+ mpz_sub_ui (v.val, v.val, 1);
+
+ check_as_integer_raises_out_of_range_error<ULONGEST> (v);
+ check_as_integer_raises_out_of_range_error<LONGEST> (v);
+
+ /* Try negative one (-1). */
+ v = -1;
+
+ check_as_integer_raises_out_of_range_error<ULONGEST> (v);
+ SELF_CHECK (v.as_integer<LONGEST> () == (LONGEST) -1);
+
+ /* Try LONGEST_MAX plus 1. */
+ v = LONGEST_MAX;
+ mpz_add_ui (v.val, v.val, 1);
+
+ SELF_CHECK (v.as_integer<ULONGEST> () == (ULONGEST) LONGEST_MAX + 1);
+ check_as_integer_raises_out_of_range_error<LONGEST> (v);
+
+ /* Try ULONGEST_MAX plus 1. */
+ v = ULONGEST_MAX;
+ mpz_add_ui (v.val, v.val, 1);
+
+ check_as_integer_raises_out_of_range_error<ULONGEST> (v);
+ check_as_integer_raises_out_of_range_error<LONGEST> (v);
+}
+
/* A helper function to store the given integer value into a buffer,
before reading it back into a gdb_mpz. Sets ACTUAL to the value
read back, while at the same time setting EXPECTED as the value
@@ -445,6 +508,8 @@ _initialize_gmp_utils_selftests ()
{
selftests::register_test ("gdb_mpz_as_integer",
selftests::gdb_mpz_as_integer);
+ selftests::register_test ("gdb_mpz_as_integer_out_of_range",
+ selftests::gdb_mpz_as_integer_out_of_range);
selftests::register_test ("gdb_mpz_read_all_from_small",
selftests::gdb_mpz_read_all_from_small);
selftests::register_test ("gdb_mpz_read_min_max",
--
2.1.4
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [RFA 2/2] gmp-utils: protect gdb_mpz exports against out-of-range values
2020-11-29 15:45 ` [RFA 2/2] gmp-utils: protect gdb_mpz exports against out-of-range values Joel Brobecker
@ 2020-11-30 15:56 ` Simon Marchi
2020-12-01 3:37 ` Joel Brobecker
2020-12-05 8:10 ` [RFAv2 " Joel Brobecker
1 sibling, 1 reply; 140+ messages in thread
From: Simon Marchi @ 2020-11-30 15:56 UTC (permalink / raw)
To: Joel Brobecker, gdb-patches
On 2020-11-29 10:45 a.m., Joel Brobecker wrote:
> The gdb_mpz class currently provides a couple of methods which
> essentially export an mpz_t value into either a buffer, or an integral
> type. The export is based on using the mpz_export function which
> we discovered can be a bit treacherous if used without caution.
>
> In particular, the initial motivation for this patch was to catch
> situations where the mpz_t value was so large that it would not fit
> in the destination area. mpz_export does not know the size of
> the buffer, and therefore can happily write past the end of our buffer.
>
> While designing a solution to the above problem, I also discovered
> that we also needed to be careful when exporting signed numbers.
> In particular, numbers which are larger than the maximum value
> for a given signed type size, but no so large as to fit in the
> *unsigned* version with the same size, would end up being exported
> incorrectly. This is related to the fact that mpz_export ignores
> the sign of the value being exportd, and assumes an unsigned export.
> Thus, for such large values, the appears as if mpz_export is able
> to fit our value into our buffer, but in fact, it does not.
>
> Also, I noticed that gdb_mpz::write wasn't taking its unsigned_p
> parameter, which was a hole.
>
> For all these reasons, a new low-level private method called
> "safe_export" has been added to class gdb_mpz, whose goal is
> to perform all necessary checks and manipulations for a safe
> and correct export. As a bonus, this method allows us to factorize
> the handling of negative value exports.
>
> The gdb_mpz::as_integer and gdb_mpz::write methods are then simplified
> to take advantage of this new safe_export method.
>
> gdb/ChangeLog:
>
> * gmp-utils.h (gdb_mpz::safe_export): New private method.
> (gdb_mpz::as_integer): Reimplement using gdb_mpz::safe_export.
> * gmp-utils.c (gdb_mpz::write): Rewrite using gdb_mpz::safe_export.
> (gdb_mpz::safe_export): New method.
> * unittests/gmp-utils-selftests .c (gdb_mpz_as_integer):
> Update function description.
> (check_as_integer_raises_out_of_range_error): New function.
> (gdb_mpz_as_integer_out_of_range): New function.
> (_initialize_gmp_utils_selftests): Register
> gdb_mpz_as_integer_out_of_range as a selftest.
> ---
> gdb/gmp-utils.c | 79 ++++++++++++++++++++++++++++++++++---
> gdb/gmp-utils.h | 44 ++++++++++++---------
> gdb/unittests/gmp-utils-selftests.c | 71 +++++++++++++++++++++++++++++++--
> 3 files changed, 167 insertions(+), 27 deletions(-)
>
> diff --git a/gdb/gmp-utils.c b/gdb/gmp-utils.c
> index e3a3333..f94bdc5 100644
> --- a/gdb/gmp-utils.c
> +++ b/gdb/gmp-utils.c
> @@ -68,9 +68,62 @@ void
> gdb_mpz::write (gdb::array_view<gdb_byte> buf, enum bfd_endian byte_order,
> bool unsigned_p) const
> {
> + this->safe_export
> + (buf, byte_order == BFD_ENDIAN_BIG ? 1 : -1 /* endian */, 0 /* nails */,
> + unsigned_p);
> +}
> +
> +/* See gmp-utils.h. */
> +
> +void
> +gdb_mpz::safe_export (gdb::array_view<gdb_byte> buf,
> + int endian, size_t nails, bool unsigned_p) const
Just wondering if you'll ever need to pass a non-zero value for nails.
If not, I think you could simplify the code by just removing it.
> +{
> + gdb_assert (buf.size () > 0);
> +
> + if (mpz_sgn (val) == 0)
> + {
> + /* Our value is zero, so no need to call mpz_export to do the work,
> + especially since mpz_export's documentation explicitly says
> + that the function is a noop in this case. Just write zero to
> + BUF ourselves. */
> + memset (buf.data (), 0, buf.size ());
> + return;
> + }
> +
> + /* Determine the maximum range of values that our buffer can hold,
> + and verify that VAL is within that range. */
> +
> + gdb_mpz lo, hi;
> + const size_t max_usable_bits = buf.size () * HOST_CHAR_BIT - nails;
> + if (unsigned_p)
> + {
> + lo = 0;
> +
> + mpz_ui_pow_ui (hi.val, 2, max_usable_bits);
> + mpz_sub_ui (hi.val, hi.val, 1);
> + }
> + else
> + {
> + mpz_ui_pow_ui (lo.val, 2, max_usable_bits - 1);
> + mpz_neg (lo.val, lo.val);
> +
> + mpz_ui_pow_ui (hi.val, 2, max_usable_bits - 1);
> + mpz_sub_ui (hi.val, hi.val, 1);
> + }
> +
> + if (mpz_cmp (val, lo.val) < 0 || mpz_cmp (val, hi.val) > 0)
> + error (_("Cannot export value %s as %zubits %s integer"
> + " (must be between %s and %s)"),
You might be missing a space before "bits", or maybe it's on purpose.
> + this->str ().c_str (),
> + max_usable_bits,
> + unsigned_p ? _("unsigned") : _("signed"),
> + lo.str ().c_str (),
> + hi.str ().c_str ());
> +
> gdb_mpz exported_val (val);
>
> - if (mpz_cmp_ui (val, 0) < 0)
> + if (mpz_cmp_ui (exported_val.val, 0) < 0)
> {
> /* mpz_export does not handle signed values, so create a positive
> value whose bit representation as an unsigned of the same length
> @@ -81,13 +134,27 @@ gdb_mpz::write (gdb::array_view<gdb_byte> buf, enum bfd_endian byte_order,
> mpz_add (exported_val.val, exported_val.val, neg_offset.val);
> }
>
> + /* Do the export into a buffer allocated by GMP itself; that way,
> + we can detect cases where BUF is not large enough to export
> + our value, and thus avoid a buffer overlow. Normally, this should
> + never happen, since we verified earlier that the buffer is large
> + enough to accomodate our value, but doing this allows us to be
> + extra safe with the export.
> +
> + After verification that the export behaved as expected, we will
> + copy the data over to BUF. */
> +
> + size_t word_countp;
> + gdb::unique_xmalloc_ptr<void> exported
I'd prefer if we didn't use heap allocation unnecessarily. If we get
things right, that isn't necessary. And if we can still assert after
the call that we did indeed get it right, then we'll catch any case
where we didn't.
> + (mpz_export (NULL, &word_countp, -1 /* order */, buf.size () /* size */,
> + endian, nails, exported_val.val));
> +
> + gdb_assert (word_countp == 1);
> +
> /* Start by clearing the buffer, as mpz_export only writes as many
> - bytes as it needs (including none, if the value to export is zero. */
> + bytes as it needs. */
> memset (buf.data (), 0, buf.size ());
> - mpz_export (buf.data (), NULL /* count */, -1 /* order */,
> - buf.size () /* size */,
> - byte_order == BFD_ENDIAN_BIG ? 1 : -1 /* endian */,
> - 0 /* nails */, exported_val.val);
> + memcpy (buf.data (), exported.get (), buf.size ());
The memset just before the memcpy of the same size is useless, as all
the bytes will get overwritten by the memcpy.
> @@ -258,26 +278,14 @@ template<typename T>
> T
> gdb_mpz::as_integer () const
> {
> - /* Initialize RESULT, because mpz_export only write the minimum
> - number of bytes, including none if our value is zero! */
> - T result = 0;
> + T result;
>
> - gdb_mpz exported_val (val);
> - if (std::is_signed<T>::value && mpz_cmp_ui (val, 0) < 0)
> - {
> - /* We want to use mpz_export to set the return value, but
> - this function does not handle the sign. So give exported_val
> - a value which is at the same time positive, and has the same
> - bit representation as our negative value. */
> - gdb_mpz neg_offset;
> + this->safe_export (gdb::make_array_view ((gdb_byte *) &result,
> + sizeof (result)),
I'd suggest using
{(gdb_byte *) &result, sizeof (result)}
to make the array view, as suggested by Pedro earlier.
Simon
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [RFA 2/2] gmp-utils: protect gdb_mpz exports against out-of-range values
2020-11-30 15:56 ` Simon Marchi
@ 2020-12-01 3:37 ` Joel Brobecker
2020-12-01 4:02 ` Simon Marchi
0 siblings, 1 reply; 140+ messages in thread
From: Joel Brobecker @ 2020-12-01 3:37 UTC (permalink / raw)
To: Simon Marchi; +Cc: gdb-patches
Hi Simon,
Thanks for the review! My preliminary answers below..
> > +void
> > +gdb_mpz::safe_export (gdb::array_view<gdb_byte> buf,
> > + int endian, size_t nails, bool unsigned_p) const
>
> Just wondering if you'll ever need to pass a non-zero value for nails.
> If not, I think you could simplify the code by just removing it.
I don't know for sure. What about a scenario where we want to export
to a variable which is held in an area that's not a multiple number
of bytes?
The code isn't dramatically complexified because of it, so perhaps
just keep it by default, and remove it later, if we find that
we never used it?
> > +{
> > + gdb_assert (buf.size () > 0);
> > +
> > + if (mpz_sgn (val) == 0)
> > + {
> > + /* Our value is zero, so no need to call mpz_export to do the work,
> > + especially since mpz_export's documentation explicitly says
> > + that the function is a noop in this case. Just write zero to
> > + BUF ourselves. */
> > + memset (buf.data (), 0, buf.size ());
> > + return;
> > + }
> > +
> > + /* Determine the maximum range of values that our buffer can hold,
> > + and verify that VAL is within that range. */
> > +
> > + gdb_mpz lo, hi;
> > + const size_t max_usable_bits = buf.size () * HOST_CHAR_BIT - nails;
> > + if (unsigned_p)
> > + {
> > + lo = 0;
> > +
> > + mpz_ui_pow_ui (hi.val, 2, max_usable_bits);
> > + mpz_sub_ui (hi.val, hi.val, 1);
> > + }
> > + else
> > + {
> > + mpz_ui_pow_ui (lo.val, 2, max_usable_bits - 1);
> > + mpz_neg (lo.val, lo.val);
> > +
> > + mpz_ui_pow_ui (hi.val, 2, max_usable_bits - 1);
> > + mpz_sub_ui (hi.val, hi.val, 1);
> > + }
> > +
> > + if (mpz_cmp (val, lo.val) < 0 || mpz_cmp (val, hi.val) > 0)
> > + error (_("Cannot export value %s as %zubits %s integer"
> > + " (must be between %s and %s)"),
>
> You might be missing a space before "bits", or maybe it's on purpose.
It was on purpose, as I tend to write "32bit object" or "64bit object".
But if there is a standard way to write these things. A quick google
search indeed seems to indicate that there is large preference for
having a dash (as in "32-bit computing").
So, if people agree, I will change the above to add a dash.
>
> > + this->str ().c_str (),
> > + max_usable_bits,
> > + unsigned_p ? _("unsigned") : _("signed"),
> > + lo.str ().c_str (),
> > + hi.str ().c_str ());
> > +
> > gdb_mpz exported_val (val);
> >
> > - if (mpz_cmp_ui (val, 0) < 0)
> > + if (mpz_cmp_ui (exported_val.val, 0) < 0)
> > {
> > /* mpz_export does not handle signed values, so create a positive
> > value whose bit representation as an unsigned of the same length
> > @@ -81,13 +134,27 @@ gdb_mpz::write (gdb::array_view<gdb_byte> buf, enum bfd_endian byte_order,
> > mpz_add (exported_val.val, exported_val.val, neg_offset.val);
> > }
> >
> > + /* Do the export into a buffer allocated by GMP itself; that way,
> > + we can detect cases where BUF is not large enough to export
> > + our value, and thus avoid a buffer overlow. Normally, this should
> > + never happen, since we verified earlier that the buffer is large
> > + enough to accomodate our value, but doing this allows us to be
> > + extra safe with the export.
> > +
> > + After verification that the export behaved as expected, we will
> > + copy the data over to BUF. */
> > +
> > + size_t word_countp;
> > + gdb::unique_xmalloc_ptr<void> exported
>
> I'd prefer if we didn't use heap allocation unnecessarily. If we get
> things right, that isn't necessary. And if we can still assert after
> the call that we did indeed get it right, then we'll catch any case
> where we didn't.
The problem with what you suggest is that, if we didn't do things right,
by the time we realize it, we'll have already gone through a buffer
overflow, with the associated random and uncontrolled damage. On Ubuntu,
we already know that the overflow causes an abort, so we wouldn't even
get to the point where we'd double-check. For me, this risk is bad enough
that it's well worth this (small) extra allocation. I don't think
this function is going to be called very frequently.
> > + (mpz_export (NULL, &word_countp, -1 /* order */, buf.size () /* size */,
> > + endian, nails, exported_val.val));
> > +
> > + gdb_assert (word_countp == 1);
> > +
> > /* Start by clearing the buffer, as mpz_export only writes as many
> > - bytes as it needs (including none, if the value to export is zero. */
> > + bytes as it needs. */
> > memset (buf.data (), 0, buf.size ());
> > - mpz_export (buf.data (), NULL /* count */, -1 /* order */,
> > - buf.size () /* size */,
> > - byte_order == BFD_ENDIAN_BIG ? 1 : -1 /* endian */,
> > - 0 /* nails */, exported_val.val);
> > + memcpy (buf.data (), exported.get (), buf.size ());
>
> The memset just before the memcpy of the same size is useless, as all
> the bytes will get overwritten by the memcpy.
Indeed. The above comes from my belief that mpz_export only writes
the necessary number of *bytes*, but re-reading the documentation,
I belive it's the necessary number of *words*. I don't know how things
could possibly be working in the case where mpz_export does the memory
allocation otherwise.
Thanks for catching that. I'll remove the extra memset.
> > @@ -258,26 +278,14 @@ template<typename T>
> > T
> > gdb_mpz::as_integer () const
> > {
> > - /* Initialize RESULT, because mpz_export only write the minimum
> > - number of bytes, including none if our value is zero! */
> > - T result = 0;
> > + T result;
> >
> > - gdb_mpz exported_val (val);
> > - if (std::is_signed<T>::value && mpz_cmp_ui (val, 0) < 0)
> > - {
> > - /* We want to use mpz_export to set the return value, but
> > - this function does not handle the sign. So give exported_val
> > - a value which is at the same time positive, and has the same
> > - bit representation as our negative value. */
> > - gdb_mpz neg_offset;
> > + this->safe_export (gdb::make_array_view ((gdb_byte *) &result,
> > + sizeof (result)),
>
> I'd suggest using
>
> {(gdb_byte *) &result, sizeof (result)}
>
> to make the array view, as suggested by Pedro earlier.
I thought I had tried that and got an error, but I will try again.
--
Joel
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [RFA 2/2] gmp-utils: protect gdb_mpz exports against out-of-range values
2020-12-01 3:37 ` Joel Brobecker
@ 2020-12-01 4:02 ` Simon Marchi
2020-12-01 7:11 ` Joel Brobecker
0 siblings, 1 reply; 140+ messages in thread
From: Simon Marchi @ 2020-12-01 4:02 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
On 2020-11-30 10:37 p.m., Joel Brobecker wrote:
> Hi Simon,
>
> Thanks for the review! My preliminary answers below..
>
>>> +void
>>> +gdb_mpz::safe_export (gdb::array_view<gdb_byte> buf,
>>> + int endian, size_t nails, bool unsigned_p) const
>>
>> Just wondering if you'll ever need to pass a non-zero value for nails.
>> If not, I think you could simplify the code by just removing it.
>
> I don't know for sure. What about a scenario where we want to export
> to a variable which is held in an area that's not a multiple number
> of bytes?
>
> The code isn't dramatically complexified because of it, so perhaps
> just keep it by default, and remove it later, if we find that
> we never used it?
Well, I find it more logical to do the other way around, add the
complexity when you need it. Because I'm pretty sure you won't go set
an alarm clock for one year from now, to remember to come back and check
whether or not we are using that feature :). Also, I'm usually not keen
on checking in things that aren't used, because we don't even know if
they work / do what they are intended to do.
If you know things are coming that are going to use it, I'm fine with
leaving it in, but otherwise I just don't see the point. I'll let you
decide.
>>> +{
>>> + gdb_assert (buf.size () > 0);
>>> +
>>> + if (mpz_sgn (val) == 0)
>>> + {
>>> + /* Our value is zero, so no need to call mpz_export to do the work,
>>> + especially since mpz_export's documentation explicitly says
>>> + that the function is a noop in this case. Just write zero to
>>> + BUF ourselves. */
>>> + memset (buf.data (), 0, buf.size ());
>>> + return;
>>> + }
>>> +
>>> + /* Determine the maximum range of values that our buffer can hold,
>>> + and verify that VAL is within that range. */
>>> +
>>> + gdb_mpz lo, hi;
>>> + const size_t max_usable_bits = buf.size () * HOST_CHAR_BIT - nails;
>>> + if (unsigned_p)
>>> + {
>>> + lo = 0;
>>> +
>>> + mpz_ui_pow_ui (hi.val, 2, max_usable_bits);
>>> + mpz_sub_ui (hi.val, hi.val, 1);
>>> + }
>>> + else
>>> + {
>>> + mpz_ui_pow_ui (lo.val, 2, max_usable_bits - 1);
>>> + mpz_neg (lo.val, lo.val);
>>> +
>>> + mpz_ui_pow_ui (hi.val, 2, max_usable_bits - 1);
>>> + mpz_sub_ui (hi.val, hi.val, 1);
>>> + }
>>> +
>>> + if (mpz_cmp (val, lo.val) < 0 || mpz_cmp (val, hi.val) > 0)
>>> + error (_("Cannot export value %s as %zubits %s integer"
>>> + " (must be between %s and %s)"),
>>
>> You might be missing a space before "bits", or maybe it's on purpose.
>
> It was on purpose, as I tend to write "32bit object" or "64bit object".
> But if there is a standard way to write these things. A quick google
> search indeed seems to indicate that there is large preference for
> having a dash (as in "32-bit computing").
>
> So, if people agree, I will change the above to add a dash.
I googled a bit and it turns out that this is a kind of compound
adjective, which requires a hyphen:
https://www.gingersoftware.com/content/grammar-rules/adjectives/compound-adjectives/
Also, the name (bit) should be singular. So I think we should
standardize on "%zu-bit".
>
>>
>>> + this->str ().c_str (),
>>> + max_usable_bits,
>>> + unsigned_p ? _("unsigned") : _("signed"),
>>> + lo.str ().c_str (),
>>> + hi.str ().c_str ());
>>> +
>>> gdb_mpz exported_val (val);
>>>
>>> - if (mpz_cmp_ui (val, 0) < 0)
>>> + if (mpz_cmp_ui (exported_val.val, 0) < 0)
>>> {
>>> /* mpz_export does not handle signed values, so create a positive
>>> value whose bit representation as an unsigned of the same length
>>> @@ -81,13 +134,27 @@ gdb_mpz::write (gdb::array_view<gdb_byte> buf, enum bfd_endian byte_order,
>>> mpz_add (exported_val.val, exported_val.val, neg_offset.val);
>>> }
>>>
>>> + /* Do the export into a buffer allocated by GMP itself; that way,
>>> + we can detect cases where BUF is not large enough to export
>>> + our value, and thus avoid a buffer overlow. Normally, this should
>>> + never happen, since we verified earlier that the buffer is large
>>> + enough to accomodate our value, but doing this allows us to be
>>> + extra safe with the export.
>>> +
>>> + After verification that the export behaved as expected, we will
>>> + copy the data over to BUF. */
>>> +
>>> + size_t word_countp;
>>> + gdb::unique_xmalloc_ptr<void> exported
>>
>> I'd prefer if we didn't use heap allocation unnecessarily. If we get
>> things right, that isn't necessary. And if we can still assert after
>> the call that we did indeed get it right, then we'll catch any case
>> where we didn't.
>
> The problem with what you suggest is that, if we didn't do things right,
> by the time we realize it, we'll have already gone through a buffer
> overflow, with the associated random and uncontrolled damage. On Ubuntu,
> we already know that the overflow causes an abort, so we wouldn't even
> get to the point where we'd double-check. For me, this risk is bad enough
> that it's well worth this (small) extra allocation. I don't think
> this function is going to be called very frequently.
The way I see it is that if we check after the fact, it would be a
gdb_assert. So if we get it wrong, it results in either in a crash or a
failed assertion. Both equally result in a bug report.
But you're right, using the heap allocation makes it so we can't get it
wrong, so that's an advantage. I just thought that we'd get it right
for good now :).
>>> @@ -258,26 +278,14 @@ template<typename T>
>>> T
>>> gdb_mpz::as_integer () const
>>> {
>>> - /* Initialize RESULT, because mpz_export only write the minimum
>>> - number of bytes, including none if our value is zero! */
>>> - T result = 0;
>>> + T result;
>>>
>>> - gdb_mpz exported_val (val);
>>> - if (std::is_signed<T>::value && mpz_cmp_ui (val, 0) < 0)
>>> - {
>>> - /* We want to use mpz_export to set the return value, but
>>> - this function does not handle the sign. So give exported_val
>>> - a value which is at the same time positive, and has the same
>>> - bit representation as our negative value. */
>>> - gdb_mpz neg_offset;
>>> + this->safe_export (gdb::make_array_view ((gdb_byte *) &result,
>>> + sizeof (result)),
>>
>> I'd suggest using
>>
>> {(gdb_byte *) &result, sizeof (result)}
>>
>> to make the array view, as suggested by Pedro earlier.
>
> I thought I had tried that and got an error, but I will try again.
I tried it before making that suggestion and it worked, so if you have
troubles let me know.
Simon
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [RFA 2/2] gmp-utils: protect gdb_mpz exports against out-of-range values
2020-12-01 4:02 ` Simon Marchi
@ 2020-12-01 7:11 ` Joel Brobecker
0 siblings, 0 replies; 140+ messages in thread
From: Joel Brobecker @ 2020-12-01 7:11 UTC (permalink / raw)
To: Simon Marchi; +Cc: gdb-patches
> >>> +void
> >>> +gdb_mpz::safe_export (gdb::array_view<gdb_byte> buf,
> >>> + int endian, size_t nails, bool unsigned_p) const
> >>
> >> Just wondering if you'll ever need to pass a non-zero value for nails.
> >> If not, I think you could simplify the code by just removing it.
> >
> > I don't know for sure. What about a scenario where we want to export
> > to a variable which is held in an area that's not a multiple number
> > of bytes?
> >
> > The code isn't dramatically complexified because of it, so perhaps
> > just keep it by default, and remove it later, if we find that
> > we never used it?
>
> Well, I find it more logical to do the other way around, add the
> complexity when you need it. Because I'm pretty sure you won't go set
> an alarm clock for one year from now, to remember to come back and check
> whether or not we are using that feature :). Also, I'm usually not keen
> on checking in things that aren't used, because we don't even know if
> they work / do what they are intended to do.
>
> If you know things are coming that are going to use it, I'm fine with
> leaving it in, but otherwise I just don't see the point. I'll let you
> decide.
That's no problem. I will remove it.
> Also, the name (bit) should be singular. So I think we should
> standardize on "%zu-bit".
Agreed.
> >>> + /* Do the export into a buffer allocated by GMP itself; that way,
> >>> + we can detect cases where BUF is not large enough to export
> >>> + our value, and thus avoid a buffer overlow. Normally, this should
> >>> + never happen, since we verified earlier that the buffer is large
> >>> + enough to accomodate our value, but doing this allows us to be
> >>> + extra safe with the export.
> >>> +
> >>> + After verification that the export behaved as expected, we will
> >>> + copy the data over to BUF. */
> >>> +
> >>> + size_t word_countp;
> >>> + gdb::unique_xmalloc_ptr<void> exported
> >>
> >> I'd prefer if we didn't use heap allocation unnecessarily. If we get
> >> things right, that isn't necessary. And if we can still assert after
> >> the call that we did indeed get it right, then we'll catch any case
> >> where we didn't.
> >
> > The problem with what you suggest is that, if we didn't do things right,
> > by the time we realize it, we'll have already gone through a buffer
> > overflow, with the associated random and uncontrolled damage. On Ubuntu,
> > we already know that the overflow causes an abort, so we wouldn't even
> > get to the point where we'd double-check. For me, this risk is bad enough
> > that it's well worth this (small) extra allocation. I don't think
> > this function is going to be called very frequently.
>
> The way I see it is that if we check after the fact, it would be a
> gdb_assert. So if we get it wrong, it results in either in a crash or a
> failed assertion. Both equally result in a bug report.
>
> But you're right, using the heap allocation makes it so we can't get it
> wrong, so that's an advantage. I just thought that we'd get it right
> for good now :).
Me too. If GMP had a routine that gave us that information prior to
calling mpz_export, we could use it and verify that we can confidently
call mpz_export without risking a buffer overflow. Right now, we have
a formula provided by the manual, but but given in a way that does not
instill great confidence ("a calculation like the following"). I'm also
concerned with future versions changing the formula and us not noticing.
> >>> @@ -258,26 +278,14 @@ template<typename T>
> >>> T
> >>> gdb_mpz::as_integer () const
> >>> {
> >>> - /* Initialize RESULT, because mpz_export only write the minimum
> >>> - number of bytes, including none if our value is zero! */
> >>> - T result = 0;
> >>> + T result;
> >>>
> >>> - gdb_mpz exported_val (val);
> >>> - if (std::is_signed<T>::value && mpz_cmp_ui (val, 0) < 0)
> >>> - {
> >>> - /* We want to use mpz_export to set the return value, but
> >>> - this function does not handle the sign. So give exported_val
> >>> - a value which is at the same time positive, and has the same
> >>> - bit representation as our negative value. */
> >>> - gdb_mpz neg_offset;
> >>> + this->safe_export (gdb::make_array_view ((gdb_byte *) &result,
> >>> + sizeof (result)),
> >>
> >> I'd suggest using
> >>
> >> {(gdb_byte *) &result, sizeof (result)}
> >>
> >> to make the array view, as suggested by Pedro earlier.
> >
> > I thought I had tried that and got an error, but I will try again.
>
> I tried it before making that suggestion and it worked, so if you have
> troubles let me know.
--
Joel
^ permalink raw reply [flat|nested] 140+ messages in thread
* [RFAv2 2/2] gmp-utils: protect gdb_mpz exports against out-of-range values
2020-11-29 15:45 ` [RFA 2/2] gmp-utils: protect gdb_mpz exports against out-of-range values Joel Brobecker
2020-11-30 15:56 ` Simon Marchi
@ 2020-12-05 8:10 ` Joel Brobecker
2020-12-05 23:26 ` Simon Marchi
1 sibling, 1 reply; 140+ messages in thread
From: Joel Brobecker @ 2020-12-05 8:10 UTC (permalink / raw)
To: gdb-patches; +Cc: Simon Marchi, Joel Brobecker
Hi Simon,
Here is v2 of this patch, taking into account your comments and
suggestions. More precisely:
- Parameter "nails" in gdb_mpz::safe_export has been removed;
- I changed the error message to use "[nnn]-bits" instead of
"[nnn]bits";
- I removed a useless memset in gdb_mpz::safe_export;
- I used the {buf, size} idiom to construct a a gdb::array view
instead of using gdb::make_array_view.
The series was re-tested on x86_64-linux.
OK to push?
---------------------------------------------------------------------------
The gdb_mpz class currently provides a couple of methods which
essentially export an mpz_t value into either a buffer, or an integral
type. The export is based on using the mpz_export function which
we discovered can be a bit treacherous if used without caution.
In particular, the initial motivation for this patch was to catch
situations where the mpz_t value was so large that it would not fit
in the destination area. mpz_export does not know the size of
the buffer, and therefore can happily write past the end of our buffer.
While designing a solution to the above problem, I also discovered
that we also needed to be careful when exporting signed numbers.
In particular, numbers which are larger than the maximum value
for a given signed type size, but no so large as to fit in the
*unsigned* version with the same size, would end up being exported
incorrectly. This is related to the fact that mpz_export ignores
the sign of the value being exportd, and assumes an unsigned export.
Thus, for such large values, the appears as if mpz_export is able
to fit our value into our buffer, but in fact, it does not.
Also, I noticed that gdb_mpz::write wasn't taking its unsigned_p
parameter, which was a hole.
For all these reasons, a new low-level private method called
"safe_export" has been added to class gdb_mpz, whose goal is
to perform all necessary checks and manipulations for a safe
and correct export. As a bonus, this method allows us to factorize
the handling of negative value exports.
The gdb_mpz::as_integer and gdb_mpz::write methods are then simplified
to take advantage of this new safe_export method.
gdb/ChangeLog:
* gmp-utils.h (gdb_mpz::safe_export): New private method.
(gdb_mpz::as_integer): Reimplement using gdb_mpz::safe_export.
* gmp-utils.c (gdb_mpz::write): Rewrite using gdb_mpz::safe_export.
(gdb_mpz::safe_export): New method.
* unittests/gmp-utils-selftests .c (gdb_mpz_as_integer):
Update function description.
(check_as_integer_raises_out_of_range_error): New function.
(gdb_mpz_as_integer_out_of_range): New function.
(_initialize_gmp_utils_selftests): Register
gdb_mpz_as_integer_out_of_range as a selftest.
---
gdb/gmp-utils.c | 79 +++++++++++++++++++++++++++++++++----
gdb/gmp-utils.h | 40 ++++++++++---------
gdb/unittests/gmp-utils-selftests.c | 71 +++++++++++++++++++++++++++++++--
3 files changed, 162 insertions(+), 28 deletions(-)
diff --git a/gdb/gmp-utils.c b/gdb/gmp-utils.c
index e3a3333..6b5c820 100644
--- a/gdb/gmp-utils.c
+++ b/gdb/gmp-utils.c
@@ -68,9 +68,61 @@ void
gdb_mpz::write (gdb::array_view<gdb_byte> buf, enum bfd_endian byte_order,
bool unsigned_p) const
{
+ this->safe_export
+ (buf, byte_order == BFD_ENDIAN_BIG ? 1 : -1 /* endian */, unsigned_p);
+}
+
+/* See gmp-utils.h. */
+
+void
+gdb_mpz::safe_export (gdb::array_view<gdb_byte> buf,
+ int endian, bool unsigned_p) const
+{
+ gdb_assert (buf.size () > 0);
+
+ if (mpz_sgn (val) == 0)
+ {
+ /* Our value is zero, so no need to call mpz_export to do the work,
+ especially since mpz_export's documentation explicitly says
+ that the function is a noop in this case. Just write zero to
+ BUF ourselves. */
+ memset (buf.data (), 0, buf.size ());
+ return;
+ }
+
+ /* Determine the maximum range of values that our buffer can hold,
+ and verify that VAL is within that range. */
+
+ gdb_mpz lo, hi;
+ const size_t max_usable_bits = buf.size () * HOST_CHAR_BIT;
+ if (unsigned_p)
+ {
+ lo = 0;
+
+ mpz_ui_pow_ui (hi.val, 2, max_usable_bits);
+ mpz_sub_ui (hi.val, hi.val, 1);
+ }
+ else
+ {
+ mpz_ui_pow_ui (lo.val, 2, max_usable_bits - 1);
+ mpz_neg (lo.val, lo.val);
+
+ mpz_ui_pow_ui (hi.val, 2, max_usable_bits - 1);
+ mpz_sub_ui (hi.val, hi.val, 1);
+ }
+
+ if (mpz_cmp (val, lo.val) < 0 || mpz_cmp (val, hi.val) > 0)
+ error (_("Cannot export value %s as %zu-bits %s integer"
+ " (must be between %s and %s)"),
+ this->str ().c_str (),
+ max_usable_bits,
+ unsigned_p ? _("unsigned") : _("signed"),
+ lo.str ().c_str (),
+ hi.str ().c_str ());
+
gdb_mpz exported_val (val);
- if (mpz_cmp_ui (val, 0) < 0)
+ if (mpz_cmp_ui (exported_val.val, 0) < 0)
{
/* mpz_export does not handle signed values, so create a positive
value whose bit representation as an unsigned of the same length
@@ -81,13 +133,26 @@ gdb_mpz::write (gdb::array_view<gdb_byte> buf, enum bfd_endian byte_order,
mpz_add (exported_val.val, exported_val.val, neg_offset.val);
}
+ /* Do the export into a buffer allocated by GMP itself; that way,
+ we can detect cases where BUF is not large enough to export
+ our value, and thus avoid a buffer overlow. Normally, this should
+ never happen, since we verified earlier that the buffer is large
+ enough to accomodate our value, but doing this allows us to be
+ extra safe with the export.
+
+ After verification that the export behaved as expected, we will
+ copy the data over to BUF. */
+
+ size_t word_countp;
+ gdb::unique_xmalloc_ptr<void> exported
+ (mpz_export (NULL, &word_countp, -1 /* order */, buf.size () /* size */,
+ endian, 0 /* nails */, exported_val.val));
+
+ gdb_assert (word_countp == 1);
+
/* Start by clearing the buffer, as mpz_export only writes as many
- bytes as it needs (including none, if the value to export is zero. */
- memset (buf.data (), 0, buf.size ());
- mpz_export (buf.data (), NULL /* count */, -1 /* order */,
- buf.size () /* size */,
- byte_order == BFD_ENDIAN_BIG ? 1 : -1 /* endian */,
- 0 /* nails */, exported_val.val);
+ bytes as it needs. */
+ memcpy (buf.data (), exported.get (), buf.size ());
}
/* See gmp-utils.h. */
diff --git a/gdb/gmp-utils.h b/gdb/gmp-utils.h
index 12e4f8e..dae62cf 100644
--- a/gdb/gmp-utils.h
+++ b/gdb/gmp-utils.h
@@ -121,6 +121,24 @@ struct gdb_mpz
/* Helper template for constructor and operator=. */
template<typename T> void set (T src);
+
+ /* Low-level function to export VAL into BUF as a number whose byte size
+ is the size of BUF.
+
+ If UNSIGNED_P is true, then export VAL into BUF as an unsigned value.
+ Otherwise, export it as a signed value.
+
+ The API is inspired from GMP's mpz_export, hence the naming and types
+ of the following parameter:
+ - ENDIAN should be:
+ . 1 for most significant byte first; or
+ . -1 for least significant byte first; or
+ . 0 for native endianness.
+
+ An error is raised if BUF is not large enough to contain the value
+ being exported. */
+ void safe_export (gdb::array_view<gdb_byte> buf,
+ int endian, bool unsigned_p) const;
};
/* A class to make it easier to use GMP's mpq_t values within GDB. */
@@ -258,26 +276,12 @@ template<typename T>
T
gdb_mpz::as_integer () const
{
- /* Initialize RESULT, because mpz_export only write the minimum
- number of bytes, including none if our value is zero! */
- T result = 0;
-
- gdb_mpz exported_val (val);
- if (std::is_signed<T>::value && mpz_cmp_ui (val, 0) < 0)
- {
- /* We want to use mpz_export to set the return value, but
- this function does not handle the sign. So give exported_val
- a value which is at the same time positive, and has the same
- bit representation as our negative value. */
- gdb_mpz neg_offset;
+ T result;
- mpz_ui_pow_ui (neg_offset.val, 2, sizeof (T) * HOST_CHAR_BIT);
- mpz_add (exported_val.val, exported_val.val, neg_offset.val);
- }
+ this->safe_export ({(gdb_byte *) &result, sizeof (result)},
+ 0 /* endian (0 = native) */,
+ !std::is_signed<T>::value /* unsigned_p */);
- mpz_export (&result, NULL /* count */, -1 /* order */,
- sizeof (T) /* size */, 0 /* endian (0 = native) */,
- 0 /* nails */, exported_val.val);
return result;
}
diff --git a/gdb/unittests/gmp-utils-selftests.c b/gdb/unittests/gmp-utils-selftests.c
index 1365905..30c1902 100644
--- a/gdb/unittests/gmp-utils-selftests.c
+++ b/gdb/unittests/gmp-utils-selftests.c
@@ -26,9 +26,10 @@ namespace selftests {
/* Perform a series of general tests of gdb_mpz's as_integer method.
- This function tries to be reasonably exhaustive, by testing the edges,
- as well as a resonable set of values including negative ones, zero,
- and positive values. */
+ This function limits itself to values which are in range (out-of-range
+ values will be tested separately). In doing so, it tries to be reasonably
+ exhaustive, by testing the edges, as well as a resonable set of values
+ including negative ones, zero, and positive values. */
static void
gdb_mpz_as_integer ()
@@ -80,6 +81,68 @@ gdb_mpz_as_integer ()
SELF_CHECK (v.as_integer<ULONGEST> () == ul_expected);
}
+/* A helper function which calls the given gdb_mpz object's as_integer
+ method with the given type T, and verifies that this triggers
+ an error due to VAL's value being out of range for type T. */
+
+template<typename T, typename = gdb::Requires<std::is_integral<T>>>
+static void
+check_as_integer_raises_out_of_range_error (const gdb_mpz &val)
+{
+ try
+ {
+ val.as_integer<T> ();
+ }
+ catch (const gdb_exception_error &ex)
+ {
+ SELF_CHECK (ex.reason == RETURN_ERROR);
+ SELF_CHECK (ex.error == GENERIC_ERROR);
+ SELF_CHECK (strstr (ex.what (), "Cannot export value") != nullptr);
+ return;
+ }
+ /* The expected exception did not get raised. */
+ SELF_CHECK (false);
+}
+
+/* Perform out-of-range tests of gdb_mpz's as_integer method.
+
+ The goal of this function is to verify that gdb_mpz::as_integer
+ handles out-of-range values correctly. */
+
+static void
+gdb_mpz_as_integer_out_of_range ()
+{
+ gdb_mpz v;
+
+ /* Try LONGEST_MIN minus 1. */
+ mpz_ui_pow_ui (v.val, 2, sizeof (LONGEST) * 8 - 1);
+ mpz_neg (v.val, v.val);
+ mpz_sub_ui (v.val, v.val, 1);
+
+ check_as_integer_raises_out_of_range_error<ULONGEST> (v);
+ check_as_integer_raises_out_of_range_error<LONGEST> (v);
+
+ /* Try negative one (-1). */
+ v = -1;
+
+ check_as_integer_raises_out_of_range_error<ULONGEST> (v);
+ SELF_CHECK (v.as_integer<LONGEST> () == (LONGEST) -1);
+
+ /* Try LONGEST_MAX plus 1. */
+ v = LONGEST_MAX;
+ mpz_add_ui (v.val, v.val, 1);
+
+ SELF_CHECK (v.as_integer<ULONGEST> () == (ULONGEST) LONGEST_MAX + 1);
+ check_as_integer_raises_out_of_range_error<LONGEST> (v);
+
+ /* Try ULONGEST_MAX plus 1. */
+ v = ULONGEST_MAX;
+ mpz_add_ui (v.val, v.val, 1);
+
+ check_as_integer_raises_out_of_range_error<ULONGEST> (v);
+ check_as_integer_raises_out_of_range_error<LONGEST> (v);
+}
+
/* A helper function to store the given integer value into a buffer,
before reading it back into a gdb_mpz. Sets ACTUAL to the value
read back, while at the same time setting EXPECTED as the value
@@ -445,6 +508,8 @@ _initialize_gmp_utils_selftests ()
{
selftests::register_test ("gdb_mpz_as_integer",
selftests::gdb_mpz_as_integer);
+ selftests::register_test ("gdb_mpz_as_integer_out_of_range",
+ selftests::gdb_mpz_as_integer_out_of_range);
selftests::register_test ("gdb_mpz_read_all_from_small",
selftests::gdb_mpz_read_all_from_small);
selftests::register_test ("gdb_mpz_read_min_max",
--
2.1.4
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [RFAv2 2/2] gmp-utils: protect gdb_mpz exports against out-of-range values
2020-12-05 8:10 ` [RFAv2 " Joel Brobecker
@ 2020-12-05 23:26 ` Simon Marchi
2020-12-06 4:58 ` Joel Brobecker
0 siblings, 1 reply; 140+ messages in thread
From: Simon Marchi @ 2020-12-05 23:26 UTC (permalink / raw)
To: Joel Brobecker, gdb-patches
On 2020-12-05 3:10 a.m., Joel Brobecker wrote:
> @@ -81,13 +133,26 @@ gdb_mpz::write (gdb::array_view<gdb_byte> buf, enum bfd_endian byte_order,
> mpz_add (exported_val.val, exported_val.val, neg_offset.val);
> }
>
> + /* Do the export into a buffer allocated by GMP itself; that way,
> + we can detect cases where BUF is not large enough to export
> + our value, and thus avoid a buffer overlow. Normally, this should
> + never happen, since we verified earlier that the buffer is large
> + enough to accomodate our value, but doing this allows us to be
> + extra safe with the export.
> +
> + After verification that the export behaved as expected, we will
> + copy the data over to BUF. */
> +
> + size_t word_countp;
> + gdb::unique_xmalloc_ptr<void> exported
> + (mpz_export (NULL, &word_countp, -1 /* order */, buf.size () /* size */,
> + endian, 0 /* nails */, exported_val.val));
> +
> + gdb_assert (word_countp == 1);
> +
> /* Start by clearing the buffer, as mpz_export only writes as many
> - bytes as it needs (including none, if the value to export is zero. */
That comment is now stale.
Otherwise, that LGTM.
Simon
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: [RFAv2 2/2] gmp-utils: protect gdb_mpz exports against out-of-range values
2020-12-05 23:26 ` Simon Marchi
@ 2020-12-06 4:58 ` Joel Brobecker
0 siblings, 0 replies; 140+ messages in thread
From: Joel Brobecker @ 2020-12-06 4:58 UTC (permalink / raw)
To: Simon Marchi; +Cc: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1396 bytes --]
> On 2020-12-05 3:10 a.m., Joel Brobecker wrote:
> > @@ -81,13 +133,26 @@ gdb_mpz::write (gdb::array_view<gdb_byte> buf, enum bfd_endian byte_order,
> > mpz_add (exported_val.val, exported_val.val, neg_offset.val);
> > }
> >
> > + /* Do the export into a buffer allocated by GMP itself; that way,
> > + we can detect cases where BUF is not large enough to export
> > + our value, and thus avoid a buffer overlow. Normally, this should
> > + never happen, since we verified earlier that the buffer is large
> > + enough to accomodate our value, but doing this allows us to be
> > + extra safe with the export.
> > +
> > + After verification that the export behaved as expected, we will
> > + copy the data over to BUF. */
> > +
> > + size_t word_countp;
> > + gdb::unique_xmalloc_ptr<void> exported
> > + (mpz_export (NULL, &word_countp, -1 /* order */, buf.size () /* size */,
> > + endian, 0 /* nails */, exported_val.val));
> > +
> > + gdb_assert (word_countp == 1);
> > +
> > /* Start by clearing the buffer, as mpz_export only writes as many
> > - bytes as it needs (including none, if the value to export is zero. */
>
> That comment is now stale.
Indeed. Thanks for catching that.
> Otherwise, that LGTM.
Thanks Simon. The patch is now in, with the correction above (a copy
of the patch is attached, for the record).
--
Joel
[-- Attachment #2: 0001-gmp-utils-protect-gdb_mpz-exports-against-out-of-ran.patch --]
[-- Type: text/x-diff, Size: 12521 bytes --]
From 63c457b911043aa6ebf3558e2d2050ee53d28a8e Mon Sep 17 00:00:00 2001
From: Joel Brobecker <brobecker@adacore.com>
Date: Sat, 5 Dec 2020 23:56:59 -0500
Subject: [PATCH] gmp-utils: protect gdb_mpz exports against out-of-range
values
The gdb_mpz class currently provides a couple of methods which
essentially export an mpz_t value into either a buffer, or an integral
type. The export is based on using the mpz_export function which
we discovered can be a bit treacherous if used without caution.
In particular, the initial motivation for this patch was to catch
situations where the mpz_t value was so large that it would not fit
in the destination area. mpz_export does not know the size of
the buffer, and therefore can happily write past the end of our buffer.
While designing a solution to the above problem, I also discovered
that we also needed to be careful when exporting signed numbers.
In particular, numbers which are larger than the maximum value
for a given signed type size, but no so large as to fit in the
*unsigned* version with the same size, would end up being exported
incorrectly. This is related to the fact that mpz_export ignores
the sign of the value being exportd, and assumes an unsigned export.
Thus, for such large values, the appears as if mpz_export is able
to fit our value into our buffer, but in fact, it does not.
Also, I noticed that gdb_mpz::write wasn't taking its unsigned_p
parameter, which was a hole.
For all these reasons, a new low-level private method called
"safe_export" has been added to class gdb_mpz, whose goal is
to perform all necessary checks and manipulations for a safe
and correct export. As a bonus, this method allows us to factorize
the handling of negative value exports.
The gdb_mpz::as_integer and gdb_mpz::write methods are then simplified
to take advantage of this new safe_export method.
gdb/ChangeLog:
* gmp-utils.h (gdb_mpz::safe_export): New private method.
(gdb_mpz::as_integer): Reimplement using gdb_mpz::safe_export.
* gmp-utils.c (gdb_mpz::write): Rewrite using gdb_mpz::safe_export.
(gdb_mpz::safe_export): New method.
* unittests/gmp-utils-selftests .c (gdb_mpz_as_integer):
Update function description.
(check_as_integer_raises_out_of_range_error): New function.
(gdb_mpz_as_integer_out_of_range): New function.
(_initialize_gmp_utils_selftests): Register
gdb_mpz_as_integer_out_of_range as a selftest.
---
gdb/ChangeLog | 13 ++++++
gdb/gmp-utils.c | 79 +++++++++++++++++++++++++++++++++----
gdb/gmp-utils.h | 40 ++++++++++---------
gdb/unittests/gmp-utils-selftests.c | 71 +++++++++++++++++++++++++++++++--
4 files changed, 174 insertions(+), 29 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index fd95992..d8b67c6 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,16 @@
+2020-12-06 Joel Brobecker <brobecker@adacore.com>
+
+ * gmp-utils.h (gdb_mpz::safe_export): New private method.
+ (gdb_mpz::as_integer): Reimplement using gdb_mpz::safe_export.
+ * gmp-utils.c (gdb_mpz::write): Rewrite using gdb_mpz::safe_export.
+ (gdb_mpz::safe_export): New method.
+ * unittests/gmp-utils-selftests .c (gdb_mpz_as_integer):
+ Update function description.
+ (check_as_integer_raises_out_of_range_error): New function.
+ (gdb_mpz_as_integer_out_of_range): New function.
+ (_initialize_gmp_utils_selftests): Register
+ gdb_mpz_as_integer_out_of_range as a selftest.
+
2020-12-05 Joel Brobecker <brobecker@adacore.com>
* gmp-utils.c (gdb_mpz::read): Use HOST_CHAR_BIT instead of
diff --git a/gdb/gmp-utils.c b/gdb/gmp-utils.c
index e3a3333..60c915c 100644
--- a/gdb/gmp-utils.c
+++ b/gdb/gmp-utils.c
@@ -68,9 +68,61 @@ void
gdb_mpz::write (gdb::array_view<gdb_byte> buf, enum bfd_endian byte_order,
bool unsigned_p) const
{
+ this->safe_export
+ (buf, byte_order == BFD_ENDIAN_BIG ? 1 : -1 /* endian */, unsigned_p);
+}
+
+/* See gmp-utils.h. */
+
+void
+gdb_mpz::safe_export (gdb::array_view<gdb_byte> buf,
+ int endian, bool unsigned_p) const
+{
+ gdb_assert (buf.size () > 0);
+
+ if (mpz_sgn (val) == 0)
+ {
+ /* Our value is zero, so no need to call mpz_export to do the work,
+ especially since mpz_export's documentation explicitly says
+ that the function is a noop in this case. Just write zero to
+ BUF ourselves. */
+ memset (buf.data (), 0, buf.size ());
+ return;
+ }
+
+ /* Determine the maximum range of values that our buffer can hold,
+ and verify that VAL is within that range. */
+
+ gdb_mpz lo, hi;
+ const size_t max_usable_bits = buf.size () * HOST_CHAR_BIT;
+ if (unsigned_p)
+ {
+ lo = 0;
+
+ mpz_ui_pow_ui (hi.val, 2, max_usable_bits);
+ mpz_sub_ui (hi.val, hi.val, 1);
+ }
+ else
+ {
+ mpz_ui_pow_ui (lo.val, 2, max_usable_bits - 1);
+ mpz_neg (lo.val, lo.val);
+
+ mpz_ui_pow_ui (hi.val, 2, max_usable_bits - 1);
+ mpz_sub_ui (hi.val, hi.val, 1);
+ }
+
+ if (mpz_cmp (val, lo.val) < 0 || mpz_cmp (val, hi.val) > 0)
+ error (_("Cannot export value %s as %zu-bits %s integer"
+ " (must be between %s and %s)"),
+ this->str ().c_str (),
+ max_usable_bits,
+ unsigned_p ? _("unsigned") : _("signed"),
+ lo.str ().c_str (),
+ hi.str ().c_str ());
+
gdb_mpz exported_val (val);
- if (mpz_cmp_ui (val, 0) < 0)
+ if (mpz_cmp_ui (exported_val.val, 0) < 0)
{
/* mpz_export does not handle signed values, so create a positive
value whose bit representation as an unsigned of the same length
@@ -81,13 +133,24 @@ gdb_mpz::write (gdb::array_view<gdb_byte> buf, enum bfd_endian byte_order,
mpz_add (exported_val.val, exported_val.val, neg_offset.val);
}
- /* Start by clearing the buffer, as mpz_export only writes as many
- bytes as it needs (including none, if the value to export is zero. */
- memset (buf.data (), 0, buf.size ());
- mpz_export (buf.data (), NULL /* count */, -1 /* order */,
- buf.size () /* size */,
- byte_order == BFD_ENDIAN_BIG ? 1 : -1 /* endian */,
- 0 /* nails */, exported_val.val);
+ /* Do the export into a buffer allocated by GMP itself; that way,
+ we can detect cases where BUF is not large enough to export
+ our value, and thus avoid a buffer overlow. Normally, this should
+ never happen, since we verified earlier that the buffer is large
+ enough to accomodate our value, but doing this allows us to be
+ extra safe with the export.
+
+ After verification that the export behaved as expected, we will
+ copy the data over to BUF. */
+
+ size_t word_countp;
+ gdb::unique_xmalloc_ptr<void> exported
+ (mpz_export (NULL, &word_countp, -1 /* order */, buf.size () /* size */,
+ endian, 0 /* nails */, exported_val.val));
+
+ gdb_assert (word_countp == 1);
+
+ memcpy (buf.data (), exported.get (), buf.size ());
}
/* See gmp-utils.h. */
diff --git a/gdb/gmp-utils.h b/gdb/gmp-utils.h
index 12e4f8e..dae62cf 100644
--- a/gdb/gmp-utils.h
+++ b/gdb/gmp-utils.h
@@ -121,6 +121,24 @@ struct gdb_mpz
/* Helper template for constructor and operator=. */
template<typename T> void set (T src);
+
+ /* Low-level function to export VAL into BUF as a number whose byte size
+ is the size of BUF.
+
+ If UNSIGNED_P is true, then export VAL into BUF as an unsigned value.
+ Otherwise, export it as a signed value.
+
+ The API is inspired from GMP's mpz_export, hence the naming and types
+ of the following parameter:
+ - ENDIAN should be:
+ . 1 for most significant byte first; or
+ . -1 for least significant byte first; or
+ . 0 for native endianness.
+
+ An error is raised if BUF is not large enough to contain the value
+ being exported. */
+ void safe_export (gdb::array_view<gdb_byte> buf,
+ int endian, bool unsigned_p) const;
};
/* A class to make it easier to use GMP's mpq_t values within GDB. */
@@ -258,26 +276,12 @@ template<typename T>
T
gdb_mpz::as_integer () const
{
- /* Initialize RESULT, because mpz_export only write the minimum
- number of bytes, including none if our value is zero! */
- T result = 0;
-
- gdb_mpz exported_val (val);
- if (std::is_signed<T>::value && mpz_cmp_ui (val, 0) < 0)
- {
- /* We want to use mpz_export to set the return value, but
- this function does not handle the sign. So give exported_val
- a value which is at the same time positive, and has the same
- bit representation as our negative value. */
- gdb_mpz neg_offset;
+ T result;
- mpz_ui_pow_ui (neg_offset.val, 2, sizeof (T) * HOST_CHAR_BIT);
- mpz_add (exported_val.val, exported_val.val, neg_offset.val);
- }
+ this->safe_export ({(gdb_byte *) &result, sizeof (result)},
+ 0 /* endian (0 = native) */,
+ !std::is_signed<T>::value /* unsigned_p */);
- mpz_export (&result, NULL /* count */, -1 /* order */,
- sizeof (T) /* size */, 0 /* endian (0 = native) */,
- 0 /* nails */, exported_val.val);
return result;
}
diff --git a/gdb/unittests/gmp-utils-selftests.c b/gdb/unittests/gmp-utils-selftests.c
index 1365905..30c1902 100644
--- a/gdb/unittests/gmp-utils-selftests.c
+++ b/gdb/unittests/gmp-utils-selftests.c
@@ -26,9 +26,10 @@ namespace selftests {
/* Perform a series of general tests of gdb_mpz's as_integer method.
- This function tries to be reasonably exhaustive, by testing the edges,
- as well as a resonable set of values including negative ones, zero,
- and positive values. */
+ This function limits itself to values which are in range (out-of-range
+ values will be tested separately). In doing so, it tries to be reasonably
+ exhaustive, by testing the edges, as well as a resonable set of values
+ including negative ones, zero, and positive values. */
static void
gdb_mpz_as_integer ()
@@ -80,6 +81,68 @@ gdb_mpz_as_integer ()
SELF_CHECK (v.as_integer<ULONGEST> () == ul_expected);
}
+/* A helper function which calls the given gdb_mpz object's as_integer
+ method with the given type T, and verifies that this triggers
+ an error due to VAL's value being out of range for type T. */
+
+template<typename T, typename = gdb::Requires<std::is_integral<T>>>
+static void
+check_as_integer_raises_out_of_range_error (const gdb_mpz &val)
+{
+ try
+ {
+ val.as_integer<T> ();
+ }
+ catch (const gdb_exception_error &ex)
+ {
+ SELF_CHECK (ex.reason == RETURN_ERROR);
+ SELF_CHECK (ex.error == GENERIC_ERROR);
+ SELF_CHECK (strstr (ex.what (), "Cannot export value") != nullptr);
+ return;
+ }
+ /* The expected exception did not get raised. */
+ SELF_CHECK (false);
+}
+
+/* Perform out-of-range tests of gdb_mpz's as_integer method.
+
+ The goal of this function is to verify that gdb_mpz::as_integer
+ handles out-of-range values correctly. */
+
+static void
+gdb_mpz_as_integer_out_of_range ()
+{
+ gdb_mpz v;
+
+ /* Try LONGEST_MIN minus 1. */
+ mpz_ui_pow_ui (v.val, 2, sizeof (LONGEST) * 8 - 1);
+ mpz_neg (v.val, v.val);
+ mpz_sub_ui (v.val, v.val, 1);
+
+ check_as_integer_raises_out_of_range_error<ULONGEST> (v);
+ check_as_integer_raises_out_of_range_error<LONGEST> (v);
+
+ /* Try negative one (-1). */
+ v = -1;
+
+ check_as_integer_raises_out_of_range_error<ULONGEST> (v);
+ SELF_CHECK (v.as_integer<LONGEST> () == (LONGEST) -1);
+
+ /* Try LONGEST_MAX plus 1. */
+ v = LONGEST_MAX;
+ mpz_add_ui (v.val, v.val, 1);
+
+ SELF_CHECK (v.as_integer<ULONGEST> () == (ULONGEST) LONGEST_MAX + 1);
+ check_as_integer_raises_out_of_range_error<LONGEST> (v);
+
+ /* Try ULONGEST_MAX plus 1. */
+ v = ULONGEST_MAX;
+ mpz_add_ui (v.val, v.val, 1);
+
+ check_as_integer_raises_out_of_range_error<ULONGEST> (v);
+ check_as_integer_raises_out_of_range_error<LONGEST> (v);
+}
+
/* A helper function to store the given integer value into a buffer,
before reading it back into a gdb_mpz. Sets ACTUAL to the value
read back, while at the same time setting EXPECTED as the value
@@ -445,6 +508,8 @@ _initialize_gmp_utils_selftests ()
{
selftests::register_test ("gdb_mpz_as_integer",
selftests::gdb_mpz_as_integer);
+ selftests::register_test ("gdb_mpz_as_integer_out_of_range",
+ selftests::gdb_mpz_as_integer_out_of_range);
selftests::register_test ("gdb_mpz_read_all_from_small",
selftests::gdb_mpz_read_all_from_small);
selftests::register_test ("gdb_mpz_read_min_max",
--
2.1.4
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: RFA: wrap mpz_export into gdb_mpz::safe_export...
2020-11-29 15:45 ` RFA: wrap mpz_export into gdb_mpz::safe_export Joel Brobecker
2020-11-29 15:45 ` [RFA 1/2] Fix TARGET_CHAR_BIT/HOST_CHAR_BIT confusion in gmp-utils.c Joel Brobecker
2020-11-29 15:45 ` [RFA 2/2] gmp-utils: protect gdb_mpz exports against out-of-range values Joel Brobecker
@ 2020-11-30 12:44 ` Christian Biesinger
2 siblings, 0 replies; 140+ messages in thread
From: Christian Biesinger @ 2020-11-30 12:44 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches, Simon Marchi
On Sun, Nov 29, 2020 at 4:46 PM Joel Brobecker <brobecker@adacore.com> wrote:
> For the record, I didn't do the following, but I was thinking it would
> be nice to poison mpz_export if we could. We can do that as a followup
> patch, if we'd like, although I will likely need a bit of help doing so,
> because I am not sure how to poison it for the entire GDB except the one
> place where it's OK to use it. In the end, it sounds to me like Tom
> wants to wrap GDB's usage of gmp into the gdb_mp[xxx] classes, and so,
> once we have that, it seems unlikely that someone would unwittingly use
> mpz_export directly.
Maybe #define mpz_export DO_NOT_USE and #undef it in the one spot?
Christian
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: pushed: Add support for DWARF-based fixed point types
2020-11-15 8:35 ` pushed: " Joel Brobecker
` (9 preceding siblings ...)
2020-11-16 23:48 ` pushed: Add support for DWARF-based fixed point types Pedro Alves
@ 2020-11-20 14:08 ` Pedro Alves
2020-11-20 14:14 ` Joel Brobecker
2020-11-22 11:56 ` RFA/doco: Various changes related to GMP and fixed point type support Joel Brobecker
11 siblings, 1 reply; 140+ messages in thread
From: Pedro Alves @ 2020-11-20 14:08 UTC (permalink / raw)
To: Joel Brobecker, gdb-patches; +Cc: Simon Marchi
Hi Joel,
On 11/15/20 8:35 AM, Joel Brobecker wrote:
> Hi everyone,
>
> I just finished pusing the following patch series to branch master.
>
> - gdb/configure: Add --with-libgmp-prefix option
> - gdb: Make GMP a required dependency for building GDB
> - gmp-utils: New API to simply use of GMP's
> - Move uinteger_pow gdb/valarith.c to gdb/utils.c and
> - Add support for printing value of DWARF-based
> - fix printing of DWARF fixed-point type objects with
> - Add ptype support for DWARF-based fixed-point types
> - Add support for fixed-point type arithmetic
> - Add support for fixed-point type comparison operators
I noticed now that this didn't come with a NEWS entry.
Shouldn't it have one? I.e.:
- mention that GMP is now a dependency for building GDB
- support for fixed point types seems NEWS worthy too
Also, gdb/README documents configure options and we mention --with-mpfr there.
Shouldn't we mention --with-libgmp-prefix there too?
^ permalink raw reply [flat|nested] 140+ messages in thread
* Re: pushed: Add support for DWARF-based fixed point types
2020-11-20 14:08 ` pushed: Add support for DWARF-based fixed point types Pedro Alves
@ 2020-11-20 14:14 ` Joel Brobecker
0 siblings, 0 replies; 140+ messages in thread
From: Joel Brobecker @ 2020-11-20 14:14 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches, Simon Marchi
> I noticed now that this didn't come with a NEWS entry.
>
> Shouldn't it have one? I.e.:
>
> - mention that GMP is now a dependency for building GDB
>
> - support for fixed point types seems NEWS worthy too
>
> Also, gdb/README documents configure options and we mention --with-mpfr there.
> Shouldn't we mention --with-libgmp-prefix there too?
Hmmm, indeed on all counts. Thanks for the reminder, Pedro. I will add
that to the list for this weekend.
--
Joel
^ permalink raw reply [flat|nested] 140+ messages in thread
* RFA/doco: Various changes related to GMP and fixed point type support
2020-11-15 8:35 ` pushed: " Joel Brobecker
` (10 preceding siblings ...)
2020-11-20 14:08 ` pushed: Add support for DWARF-based fixed point types Pedro Alves
@ 2020-11-22 11:56 ` Joel Brobecker
2020-11-22 11:56 ` [RFA/doco 1/4] gdb/NEWS: Document that building GDB now requires GMP Joel Brobecker
` (3 more replies)
11 siblings, 4 replies; 140+ messages in thread
From: Joel Brobecker @ 2020-11-22 11:56 UTC (permalink / raw)
To: gdb-patches
Hello,
This patch series only updates our NEWS and README files, following
some changes I pushed recently (thanks to Pedro for reminding me
of this).
- [RFA/doco 1/4] gdb/NEWS: Document that building GDB now requires GMP
- [RFA/doco 2/4] gdb/NEWS: Document that GDB now supports DWARF-based
- [RFA/doco 3/4] gdb/README: Document the --with-libgmp-prefix
- [RFA/doco 4/4] gdb/README: Fix the URL of the MPFR website (now
OK to push to master?
Thank you!
--
Joel
^ permalink raw reply [flat|nested] 140+ messages in thread
* [RFA/doco 1/4] gdb/NEWS: Document that building GDB now requires GMP
2020-11-22 11:56 ` RFA/doco: Various changes related to GMP and fixed point type support Joel Brobecker
@ 2020-11-22 11:56 ` Joel Brobecker
2020-11-22 15:31 ` Eli Zaretskii
2020-11-22 11:56 ` [RFA/doco 2/4] gdb/NEWS: Document that GDB now supports DWARF-based fixed point types Joel Brobecker
` (2 subsequent siblings)
3 siblings, 1 reply; 140+ messages in thread
From: Joel Brobecker @ 2020-11-22 11:56 UTC (permalink / raw)
To: gdb-patches; +Cc: Pedro Alves, Joel Brobecker
gdb/ChangeLog:
* NEWS: Document that building GDB now requires GMP.
---
gdb/NEWS | 3 +++
1 file changed, 3 insertions(+)
diff --git a/gdb/NEWS b/gdb/NEWS
index d1f721c3953..792f4860975 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,9 @@
*** Changes since GDB 10
+* Building GDB now requires GMP (The GNU Multiple Precision Arithmetic
+ Library).
+
* MI changes
** '-break-insert --qualified' and '-dprintf-insert --qualified'
--
2.25.1
^ permalink raw reply [flat|nested] 140+ messages in thread
* [RFA/doco 2/4] gdb/NEWS: Document that GDB now supports DWARF-based fixed point types
2020-11-22 11:56 ` RFA/doco: Various changes related to GMP and fixed point type support Joel Brobecker
2020-11-22 11:56 ` [RFA/doco 1/4] gdb/NEWS: Document that building GDB now requires GMP Joel Brobecker
@ 2020-11-22 11:56 ` Joel Brobecker
2020-11-22 15:33 ` Eli Zaretskii
2020-11-22 11:56 ` [RFA/doco 3/4] gdb/README: Document the --with-libgmp-prefix configure option Joel Brobecker
2020-11-22 11:56 ` [RFA/doco 4/4] gdb/README: Fix the URL of the MPFR website (now https) Joel Brobecker
3 siblings, 1 reply; 140+ messages in thread
From: Joel Brobecker @ 2020-11-22 11:56 UTC (permalink / raw)
To: gdb-patches; +Cc: Pedro Alves, Joel Brobecker
gdb/ChangeLog:
* NEWS: Add entry documenting support for DWARF-based fixed
point types.
---
gdb/NEWS | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/gdb/NEWS b/gdb/NEWS
index 792f4860975..d75992e78ef 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -24,6 +24,15 @@
$HOME/.gdbinit. On Apple hosts the search order is instead:
$HOME/Library/Preferences/gdb/gdbinit, $HOME/.gdbinit.
+* GDB now supports fixed point types which are described in DWARF
+ as base types with a fixed-point encoding. Additionally, support
+ for the DW_AT_GNU_numerator and DW_AT_GNU_denominator has also
+ been added.
+
+ For Ada, this allows support for fixed point types without requiring
+ the use of the GNAT encoding (based on information added to the type's
+ name following a GNAT-specific format).
+
* New commands
set debug event-loop
--
2.25.1
^ permalink raw reply [flat|nested] 140+ messages in thread
* [RFA/doco 3/4] gdb/README: Document the --with-libgmp-prefix configure option
2020-11-22 11:56 ` RFA/doco: Various changes related to GMP and fixed point type support Joel Brobecker
2020-11-22 11:56 ` [RFA/doco 1/4] gdb/NEWS: Document that building GDB now requires GMP Joel Brobecker
2020-11-22 11:56 ` [RFA/doco 2/4] gdb/NEWS: Document that GDB now supports DWARF-based fixed point types Joel Brobecker
@ 2020-11-22 11:56 ` Joel Brobecker
2020-11-22 15:32 ` Eli Zaretskii
2020-11-22 11:56 ` [RFA/doco 4/4] gdb/README: Fix the URL of the MPFR website (now https) Joel Brobecker
3 siblings, 1 reply; 140+ messages in thread
From: Joel Brobecker @ 2020-11-22 11:56 UTC (permalink / raw)
To: gdb-patches; +Cc: Pedro Alves, Joel Brobecker
gdb/ChangeLog:
* README: Document the --with-libgmp-prefix configure option.
---
gdb/README | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/gdb/README b/gdb/README
index 0ec1605ce5a..a7908453ba7 100644
--- a/gdb/README
+++ b/gdb/README
@@ -484,6 +484,11 @@ more obscure GDB `configure' options are not listed here.
not have liblzma installed, you can get the latest version from
`https://tukaani.org/xz/'.
+`--with-libgmp-prefix=DIR'
+ Build GDB using the GMP library installed at the directory DIR.
+ If your host does not have GMP installed, you can get the latest
+ version at `https://gmplib.org/'.
+
`--with-mpfr'
Build GDB with GNU MPFR, a library for multiple-precision
floating-point computation with correct rounding. (Done by
--
2.25.1
^ permalink raw reply [flat|nested] 140+ messages in thread
* [RFA/doco 4/4] gdb/README: Fix the URL of the MPFR website (now https).
2020-11-22 11:56 ` RFA/doco: Various changes related to GMP and fixed point type support Joel Brobecker
` (2 preceding siblings ...)
2020-11-22 11:56 ` [RFA/doco 3/4] gdb/README: Document the --with-libgmp-prefix configure option Joel Brobecker
@ 2020-11-22 11:56 ` Joel Brobecker
2020-11-22 15:33 ` Eli Zaretskii
3 siblings, 1 reply; 140+ messages in thread
From: Joel Brobecker @ 2020-11-22 11:56 UTC (permalink / raw)
To: gdb-patches; +Cc: Pedro Alves, Joel Brobecker
gdb/ChangeLog:
* README: Fix the URL of the MPFR library.
---
gdb/README | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gdb/README b/gdb/README
index a7908453ba7..e65c5ea7ffa 100644
--- a/gdb/README
+++ b/gdb/README
@@ -498,7 +498,7 @@ more obscure GDB `configure' options are not listed here.
floating-point formats than the host. If GNU MPFR is not
available, GDB will fall back to using host floating-point
arithmetic. If your host does not have GNU MPFR installed, you
- can get the latest version from `http://www.mpfr.org'.
+ can get the latest version from `https://www.mpfr.org/'.
`--with-python[=PYTHON]'
Build GDB with Python scripting support. (Done by default if
--
2.25.1
^ permalink raw reply [flat|nested] 140+ messages in thread