diff options
71 files changed, 2471 insertions, 379 deletions
diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c index 701c724..45da83e 100644 --- a/bfd/elfxx-riscv.c +++ b/bfd/elfxx-riscv.c @@ -1187,6 +1187,11 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] = {"a", "+zaamo,+zalrsc", check_implicit_always}, {"xsfvcp", "+zve32x", check_implicit_always}, + {"xsfvqmaccqoq", "+zve32x,+zvl256b", check_implicit_always}, + {"xsfvqmaccqoq", "+zvl256b", check_implicit_always}, + {"xsfvqmaccdod", "+zve32x,+zvl128b", check_implicit_always}, + {"xsfvfnrclipxfqf", "+zve32f", check_implicit_always}, + {"v", "+zve64d,+zvl128b", check_implicit_always}, {"zvfh", "+zvfhmin,+zfhmin", check_implicit_always}, {"zvfhmin", "+zve32f", check_implicit_always}, @@ -1493,6 +1498,9 @@ static struct riscv_supported_ext riscv_supported_vendor_x_ext[] = {"xventanacondops", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, {"xsfvcp", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, {"xsfcease", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, + {"xsfvqmaccqoq", ISA_SPEC_CLASS_DRAFT, 1, 0, 0}, + {"xsfvqmaccdod", ISA_SPEC_CLASS_DRAFT, 1, 0, 0}, + {"xsfvfnrclipxfqf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0}, {NULL, 0, 0, 0, 0} }; @@ -2776,6 +2784,12 @@ riscv_multi_subset_supports (riscv_parse_subset_t *rps, return riscv_subset_supports (rps, "xsfvcp"); case INSN_CLASS_XSFCEASE: return riscv_subset_supports (rps, "xsfcease"); + case INSN_CLASS_XSFVQMACCQOQ: + return riscv_subset_supports (rps, "xsfvqmaccqoq"); + case INSN_CLASS_XSFVQMACCDOD: + return riscv_subset_supports (rps, "xsfvqmaccdod"); + case INSN_CLASS_XSFVFNRCLIPXFQF: + return riscv_subset_supports (rps, "xsfvfnrclipxfqf"); default: rps->error_handler (_("internal: unreachable INSN_CLASS_*")); diff --git a/bfd/version.h b/bfd/version.h index 73c49f4..02df160 100644 --- a/bfd/version.h +++ b/bfd/version.h @@ -16,7 +16,7 @@ In releases, the date is not included in either version strings or sonames. */ -#define BFD_VERSION_DATE 20241120 +#define BFD_VERSION_DATE 20241123 #define BFD_VERSION @bfd_version@ #define BFD_VERSION_STRING @bfd_version_package@ @bfd_version_string@ #define REPORT_BUGS_TO @report_bugs_to@ diff --git a/config/acx.m4 b/config/acx.m4 index 69f4bfa..db54ccf1 100644 --- a/config/acx.m4 +++ b/config/acx.m4 @@ -424,6 +424,16 @@ else fi ]) +# Test for Rust +# We require cargo and rustc for some parts of the rust compiler. +AC_DEFUN([ACX_PROG_CARGO], +[AC_CHECK_PROGS(CARGO, cargo, no) +if test "x$CARGO" != xno; then + have_cargo=yes +else + have_cargo=no +fi]) + # Test for D. AC_DEFUN([ACX_PROG_GDC], [AC_REQUIRE([AC_CHECK_TOOL_PREFIX]) @@ -690,6 +690,8 @@ extra_host_zlib_configure_flags extra_host_libiberty_configure_flags stage1_languages host_libs_picflag +CRAB1_LIBS +enable_libdiagnostics PICFLAG host_shared gcc_host_pie @@ -711,9 +713,10 @@ gmplibs PGO_BUILD_LTO_CFLAGS PGO_BUILD_USE_CFLAGS PGO_BUILD_GEN_CFLAGS -HAVE_CXX11_FOR_BUILD -HAVE_CXX11 +HAVE_CXX14_FOR_BUILD +HAVE_CXX14 do_compare +CARGO GDC GNATMAKE GNATBIND @@ -842,6 +845,7 @@ enable_linker_plugin_configure_flags enable_linker_plugin_flags enable_host_pie enable_host_shared +enable_libdiagnostics enable_stage1_languages enable_objc_gc with_target_bdw_gc @@ -1576,6 +1580,7 @@ Optional Features: plugins [none] --enable-host-pie build position independent host executables --enable-host-shared build host code as shared libraries + --enable-libdiagnostics build libdiagnostics shared library --enable-stage1-languages[=all] choose additional languages to build during stage1. Mostly useful for compiler development @@ -3092,7 +3097,7 @@ case "${ENABLE_GOLD}" in # Check for target supported by gold. case "${target}" in i?86-*-* | x86_64-*-* | sparc*-*-* | powerpc*-*-* | arm*-*-* \ - | aarch64*-*-* | tilegx*-*-* | mips*-*-* | s390*-*-* | loongarch*-*-*) + | aarch64*-*-* | tilegx*-*-* | mips*-*-* | s390*-*-*) configdirs="$configdirs gold" if test x${ENABLE_GOLD} = xdefault; then default_ld=gold @@ -5807,6 +5812,54 @@ else have_gdc=no fi +for ac_prog in cargo +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CARGO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CARGO"; then + ac_cv_prog_CARGO="$CARGO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CARGO="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CARGO=$ac_cv_prog_CARGO +if test -n "$CARGO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CARGO" >&5 +$as_echo "$CARGO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CARGO" && break +done +test -n "$CARGO" || CARGO="no" + +if test "x$CARGO" != xno; then + have_cargo=yes +else + have_cargo=no +fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to compare bootstrapped objects" >&5 $as_echo_n "checking how to compare bootstrapped objects... " >&6; } if ${gcc_cv_prog_cmp_skip+:} false; then : @@ -5885,13 +5938,13 @@ $as_echo "$as_me: WARNING: trying to bootstrap a cross compiler" >&2;} ;; esac -# When bootstrapping with GCC, build stage 1 in C++11 mode to ensure that a -# C++11 compiler can still start the bootstrap. Otherwise, if building GCC, -# require C++11 (or higher). +# When bootstrapping with GCC, build stage 1 in C++14 mode to ensure that a +# C++14 compiler can still start the bootstrap. Otherwise, if building GCC, +# require C++14 (or higher). if test "$enable_bootstrap:$GXX" = "yes:yes"; then - CXX="$CXX -std=c++11" + CXX="$CXX -std=c++14" elif test "$have_compiler" = yes; then - ax_cxx_compile_alternatives="11 0x" ax_cxx_compile_cxx11_required=true + ax_cxx_compile_alternatives="14 1y" ax_cxx_compile_cxx14_required=true ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -5899,9 +5952,9 @@ ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ex ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ac_success=no - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features by default" >&5 -$as_echo_n "checking whether $CXX supports C++11 features by default... " >&6; } -if ${ax_cv_cxx_compile_cxx11+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++14 features by default" >&5 +$as_echo_n "checking whether $CXX supports C++14 features by default... " >&6; } +if ${ax_cv_cxx_compile_cxx14+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -6194,26 +6247,146 @@ namespace cxx11 + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201402L + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_separators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same<T, T> + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same<int, decltype(f(x))>::value, ""); + static_assert(is_same<int&, decltype(g(x))>::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + + + _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : - ax_cv_cxx_compile_cxx11=yes + ax_cv_cxx_compile_cxx14=yes else - ax_cv_cxx_compile_cxx11=no + ax_cv_cxx_compile_cxx14=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_cxx_compile_cxx11" >&5 -$as_echo "$ax_cv_cxx_compile_cxx11" >&6; } - if test x$ax_cv_cxx_compile_cxx11 = xyes; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_cxx_compile_cxx14" >&5 +$as_echo "$ax_cv_cxx_compile_cxx14" >&6; } + if test x$ax_cv_cxx_compile_cxx14 = xyes; then ac_success=yes fi if test x$ac_success = xno; then for alternative in ${ax_cxx_compile_alternatives}; do switch="-std=gnu++${alternative}" - cachevar=`$as_echo "ax_cv_cxx_compile_cxx11_$switch" | $as_tr_sh` - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features with $switch" >&5 -$as_echo_n "checking whether $CXX supports C++11 features with $switch... " >&6; } + cachevar=`$as_echo "ax_cv_cxx_compile_cxx14_$switch" | $as_tr_sh` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++14 features with $switch" >&5 +$as_echo_n "checking whether $CXX supports C++14 features with $switch... " >&6; } if eval \${$cachevar+:} false; then : $as_echo_n "(cached) " >&6 else @@ -6509,6 +6682,126 @@ namespace cxx11 + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201402L + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_separators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same<T, T> + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same<int, decltype(f(x))>::value, ""); + static_assert(is_same<int&, decltype(g(x))>::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + + + _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : eval $cachevar=yes @@ -6535,9 +6828,9 @@ $as_echo "$ac_res" >&6; } if test x$ac_success = xno; then for alternative in ${ax_cxx_compile_alternatives}; do for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do - cachevar=`$as_echo "ax_cv_cxx_compile_cxx11_$switch" | $as_tr_sh` - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features with $switch" >&5 -$as_echo_n "checking whether $CXX supports C++11 features with $switch... " >&6; } + cachevar=`$as_echo "ax_cv_cxx_compile_cxx14_$switch" | $as_tr_sh` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++14 features with $switch" >&5 +$as_echo_n "checking whether $CXX supports C++14 features with $switch... " >&6; } if eval \${$cachevar+:} false; then : $as_echo_n "(cached) " >&6 else @@ -6833,6 +7126,126 @@ namespace cxx11 + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201402L + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_separators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same<T, T> + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same<int, decltype(f(x))>::value, ""); + static_assert(is_same<int&, decltype(g(x))>::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + + + _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : eval $cachevar=yes @@ -6866,41 +7279,41 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu - if test x$ax_cxx_compile_cxx11_required = xtrue; then + if test x$ax_cxx_compile_cxx14_required = xtrue; then if test x$ac_success = xno; then - as_fn_error $? "*** A compiler with support for C++11 language features is required." "$LINENO" 5 + as_fn_error $? "*** A compiler with support for C++14 language features is required." "$LINENO" 5 fi fi if test x$ac_success = xno; then - HAVE_CXX11=0 - { $as_echo "$as_me:${as_lineno-$LINENO}: No compiler with C++11 support was found" >&5 -$as_echo "$as_me: No compiler with C++11 support was found" >&6;} + HAVE_CXX14=0 + { $as_echo "$as_me:${as_lineno-$LINENO}: No compiler with C++14 support was found" >&5 +$as_echo "$as_me: No compiler with C++14 support was found" >&6;} else - HAVE_CXX11=1 + HAVE_CXX14=1 -$as_echo "#define HAVE_CXX11 1" >>confdefs.h +$as_echo "#define HAVE_CXX14 1" >>confdefs.h fi if test "${build}" != "${host}"; then - ax_cxx_compile_alternatives="11 0x" ax_cxx_compile_cxx11_required=true + ax_cxx_compile_alternatives="14 1y" ax_cxx_compile_cxx14_required=true ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ac_success=no - ax_cv_cxx_compile_cxx11_orig_cxx="$CXX" - ax_cv_cxx_compile_cxx11_orig_cxxflags="$CXXFLAGS" - ax_cv_cxx_compile_cxx11_orig_cppflags="$CPPFLAGS" + ax_cv_cxx_compile_cxx14_orig_cxx="$CXX" + ax_cv_cxx_compile_cxx14_orig_cxxflags="$CXXFLAGS" + ax_cv_cxx_compile_cxx14_orig_cppflags="$CPPFLAGS" CXX="$CXX_FOR_BUILD" CXXFLAGS="$CXXFLAGS_FOR_BUILD" CPPFLAGS="$CPPFLAGS_FOR_BUILD" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features by default" >&5 -$as_echo_n "checking whether $CXX supports C++11 features by default... " >&6; } -if ${ax_cv_cxx_compile_cxx11_FOR_BUILD+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++14 features by default" >&5 +$as_echo_n "checking whether $CXX supports C++14 features by default... " >&6; } +if ${ax_cv_cxx_compile_cxx14_FOR_BUILD+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -7193,26 +7606,146 @@ namespace cxx11 + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201402L + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_separators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same<T, T> + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same<int, decltype(f(x))>::value, ""); + static_assert(is_same<int&, decltype(g(x))>::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + + + _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : - ax_cv_cxx_compile_cxx11_FOR_BUILD=yes + ax_cv_cxx_compile_cxx14_FOR_BUILD=yes else - ax_cv_cxx_compile_cxx11_FOR_BUILD=no + ax_cv_cxx_compile_cxx14_FOR_BUILD=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_cxx_compile_cxx11_FOR_BUILD" >&5 -$as_echo "$ax_cv_cxx_compile_cxx11_FOR_BUILD" >&6; } - if test x$ax_cv_cxx_compile_cxx11_FOR_BUILD = xyes; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_cxx_compile_cxx14_FOR_BUILD" >&5 +$as_echo "$ax_cv_cxx_compile_cxx14_FOR_BUILD" >&6; } + if test x$ax_cv_cxx_compile_cxx14_FOR_BUILD = xyes; then ac_success=yes fi if test x$ac_success = xno; then for alternative in ${ax_cxx_compile_alternatives}; do switch="-std=gnu++${alternative}" - cachevar=`$as_echo "ax_cv_cxx_compile_cxx11_FOR_BUILD_$switch" | $as_tr_sh` - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features with $switch" >&5 -$as_echo_n "checking whether $CXX supports C++11 features with $switch... " >&6; } + cachevar=`$as_echo "ax_cv_cxx_compile_cxx14_FOR_BUILD_$switch" | $as_tr_sh` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++14 features with $switch" >&5 +$as_echo_n "checking whether $CXX supports C++14 features with $switch... " >&6; } if eval \${$cachevar+:} false; then : $as_echo_n "(cached) " >&6 else @@ -7508,6 +8041,126 @@ namespace cxx11 + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201402L + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_separators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same<T, T> + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same<int, decltype(f(x))>::value, ""); + static_assert(is_same<int&, decltype(g(x))>::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + + + _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : eval $cachevar=yes @@ -7534,9 +8187,9 @@ $as_echo "$ac_res" >&6; } if test x$ac_success = xno; then for alternative in ${ax_cxx_compile_alternatives}; do for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do - cachevar=`$as_echo "ax_cv_cxx_compile_cxx11_FOR_BUILD_$switch" | $as_tr_sh` - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features with $switch" >&5 -$as_echo_n "checking whether $CXX supports C++11 features with $switch... " >&6; } + cachevar=`$as_echo "ax_cv_cxx_compile_cxx14_FOR_BUILD_$switch" | $as_tr_sh` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++14 features with $switch" >&5 +$as_echo_n "checking whether $CXX supports C++14 features with $switch... " >&6; } if eval \${$cachevar+:} false; then : $as_echo_n "(cached) " >&6 else @@ -7832,6 +8485,126 @@ namespace cxx11 + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201402L + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_separators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same<T, T> + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same<int, decltype(f(x))>::value, ""); + static_assert(is_same<int&, decltype(g(x))>::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + + + _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : eval $cachevar=yes @@ -7861,28 +8634,28 @@ $as_echo "$ac_res" >&6; } CXX_FOR_BUILD="$CXX" CXXFLAGS_FOR_BUILD="$CXXFLAGS" CPPFLAGS_FOR_BUILD="$CPPFLAGS" - CXX="$ax_cv_cxx_compile_cxx11_orig_cxx" - CXXFLAGS="$ax_cv_cxx_compile_cxx11_orig_cxxflags" - CPPFLAGS="$ax_cv_cxx_compile_cxx11_orig_cppflags" + CXX="$ax_cv_cxx_compile_cxx14_orig_cxx" + CXXFLAGS="$ax_cv_cxx_compile_cxx14_orig_cxxflags" + CPPFLAGS="$ax_cv_cxx_compile_cxx14_orig_cppflags" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu - if test x$ax_cxx_compile_cxx11_required = xtrue; then + if test x$ax_cxx_compile_cxx14_required = xtrue; then if test x$ac_success = xno; then - as_fn_error $? "*** A compiler with support for C++11 language features is required." "$LINENO" 5 + as_fn_error $? "*** A compiler with support for C++14 language features is required." "$LINENO" 5 fi fi if test x$ac_success = xno; then - HAVE_CXX11_FOR_BUILD=0 - { $as_echo "$as_me:${as_lineno-$LINENO}: No compiler with C++11 support was found" >&5 -$as_echo "$as_me: No compiler with C++11 support was found" >&6;} + HAVE_CXX14_FOR_BUILD=0 + { $as_echo "$as_me:${as_lineno-$LINENO}: No compiler with C++14 support was found" >&5 +$as_echo "$as_me: No compiler with C++14 support was found" >&6;} else - HAVE_CXX11_FOR_BUILD=1 + HAVE_CXX14_FOR_BUILD=1 -$as_echo "#define HAVE_CXX11_FOR_BUILD 1" >>confdefs.h +$as_echo "#define HAVE_CXX14_FOR_BUILD 1" >>confdefs.h fi @@ -8847,6 +9620,179 @@ fi + +# Check for libdiagnostics support. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable libdiagnostics" >&5 +$as_echo_n "checking whether to enable libdiagnostics... " >&6; } +# Check whether --enable-libdiagnostics was given. +if test "${enable_libdiagnostics+set}" = set; then : + enableval=$enable_libdiagnostics; enable_libdiagnostics=$enableval +else + enable_libdiagnostics=no +fi + + +if test x$enable_libdiagnostics = xyes; then + # Disable libdiagnostics if -enable-host-shared not specified + # but not if building for Mingw. All code in Windows + # is position independent code (PIC). + case $target in + *mingw*) ;; + *) + if test x$host_shared != xyes; then + as_fn_error $? " +Enabling libdiagnostics requires --enable-host-shared. + +--enable-host-shared typically slows the rest of the compiler down by +a few %, so you must explicitly enable it. + +If you want to build both libdiagnostics and the regular compiler, it is often +best to do this via two separate configure/builds, in separate +directories, to avoid imposing the performance cost of +--enable-host-shared on the regular compiler." "$LINENO" 5 + fi + ;; + esac +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_libdiagnostics" >&5 +$as_echo "$enable_libdiagnostics" >&6; } + + + +# Rust requires -ldl and -lpthread if you are using an old glibc that does not include them by +# default, so we check for them here +# We are doing the test here and not in the gcc/configure to be able to nicely disable the +# build of the Rust frontend in case a dep is missing. +missing_rust_dynlibs=none + +save_LIBS="$LIBS" +LIBS= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 +$as_echo_n "checking for library containing dlopen... " >&6; } +if ${ac_cv_search_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_dlopen=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_dlopen+:} false; then : + break +fi +done +if ${ac_cv_search_dlopen+:} false; then : + +else + ac_cv_search_dlopen=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 +$as_echo "$ac_cv_search_dlopen" >&6; } +ac_res=$ac_cv_search_dlopen +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_create" >&5 +$as_echo_n "checking for library containing pthread_create... " >&6; } +if ${ac_cv_search_pthread_create+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_create (); +int +main () +{ +return pthread_create (); + ; + return 0; +} +_ACEOF +for ac_lib in '' pthread; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_pthread_create=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_pthread_create+:} false; then : + break +fi +done +if ${ac_cv_search_pthread_create+:} false; then : + +else + ac_cv_search_pthread_create=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pthread_create" >&5 +$as_echo "$ac_cv_search_pthread_create" >&6; } +ac_res=$ac_cv_search_pthread_create +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +CRAB1_LIBS="$LIBS" +LIBS="$save_LIBS" + +if test "$ac_cv_search_dlopen" = no; then + missing_rust_dynlibs="libdl" +fi + +if test "$ac_cv_search_pthread_create" = no; then + missing_rust_dynlibs="$missing_rust_dynlibs, libpthread" +fi + +CRAB1_LIBS="$CRAB1_LIBS" + + # If we are building PIC/PIE host executables, and we are building dependent # libs (e.g. GMP) in-tree those libs need to be configured to generate PIC # code. @@ -8923,7 +9869,7 @@ if test -d ${srcdir}/gcc; then lang_requires_boot_languages= # set srcdir during sourcing lang_frag to the gcc dir. # Sadly overriding srcdir on the . line doesn't work in plain sh as it - # polutes this shell + # pollutes this shell saved_srcdir=${srcdir} srcdir=${srcdir}/gcc . ${lang_frag} srcdir=${saved_srcdir} @@ -9087,6 +10033,26 @@ $as_echo "$as_me: WARNING: GDC is required to build $language" >&2;} ;; esac + # Disable Rust if we are missing some required C libraries for the Rust runtime. + case ${add_this_lang}:${language}:${missing_rust_dynlibs} in + *:rust:none) + # Nothing to do - we're not missing any C libraries + ;; + yes:rust:*) + as_fn_error $? "some C libraries are required to build $language: $missing_rust_dynlibs" "$LINENO" 5 + add_this_lang=unsupported + ;; + all:rust:*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: some C libraries are required to build $language: $missing_rust_dynlibs" >&5 +$as_echo "$as_me: WARNING: some C libraries are required to build $language: $missing_rust_dynlibs" >&2;} + add_this_lang=unsupported + ;; + *:rust:*) + # Silently disable. + add_this_lang=unsupported + ;; + esac + # Disable jit if -enable-host-shared not specified # but not if building for Mingw. All code in Windows # is position independent code (PIC). @@ -9120,6 +10086,37 @@ $as_echo "$as_me: WARNING: --enable-host-shared required to build $language" >&2 ;; esac + # Pre-conditions to consider whether cargo being supported. + if test x"$have_cargo" = xyes \ + && test x"$build" != x"$host"; then + # Until <https://github.com/Rust-GCC/gccrs/issues/2898> + # "'cargo' should build for the host system" is resolved: + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: use of cargo not yet supported here in Canadian cross configurations" >&5 +$as_echo "$as_me: WARNING: use of cargo not yet supported here in Canadian cross configurations" >&2;} + have_cargo=no + else + # Assume that cargo-produced object files are compatible with what + # we're going to build here. + : + fi + # Disable Rust if cargo is unavailable. + case ${add_this_lang}:${language}:${have_cargo} in + yes:rust:no) + # Specifically requested language; tell them. + as_fn_error $? "cargo is required to build $language" "$LINENO" 5 + ;; + all:rust:no) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cargo is required to build $language" >&5 +$as_echo "$as_me: WARNING: cargo is required to build $language" >&2;} + add_this_lang=unsupported + ;; + *:rust:no) + # Silently disable. + add_this_lang=unsupported + ;; + esac + + # Disable a language that is unsupported by the target. case "${add_this_lang}: $unsupported_languages " in no:*) ;; @@ -10022,6 +11019,15 @@ case "$enable_bootstrap:$ENABLE_GOLD: $configdirs :,$stage1_languages," in ;; esac +# Bootstrapping GCC requires libstdc++-v3 so error out if libstdc++ is disabled with bootstrapping +# Note C++ is always enabled for stage1 now. +case "$enable_bootstrap:${noconfigdirs}" in + yes:*target-libstdc++-v3*) + as_fn_error $? "bootstrapping with --disable-libstdcxx is not supported" "$LINENO" 5 + ;; +esac + + extrasub_build= for module in ${build_configdirs} ; do if test -z "${no_recursion}" \ diff --git a/configure.ac b/configure.ac index 5cd262e..b31f0ea 100644 --- a/configure.ac +++ b/configure.ac @@ -365,7 +365,7 @@ case "${ENABLE_GOLD}" in # Check for target supported by gold. case "${target}" in i?86-*-* | x86_64-*-* | sparc*-*-* | powerpc*-*-* | arm*-*-* \ - | aarch64*-*-* | tilegx*-*-* | mips*-*-* | s390*-*-* | loongarch*-*-*) + | aarch64*-*-* | tilegx*-*-* | mips*-*-* | s390*-*-*) configdirs="$configdirs gold" if test x${ENABLE_GOLD} = xdefault; then default_ld=gold @@ -1432,6 +1432,7 @@ fi ACX_PROG_GNAT ACX_PROG_GDC +ACX_PROG_CARGO ACX_PROG_CMP_IGNORE_INITIAL AC_ARG_ENABLE([bootstrap], @@ -1477,16 +1478,16 @@ case "$have_compiler:$host:$target:$enable_bootstrap" in ;; esac -# When bootstrapping with GCC, build stage 1 in C++11 mode to ensure that a -# C++11 compiler can still start the bootstrap. Otherwise, if building GCC, -# require C++11 (or higher). +# When bootstrapping with GCC, build stage 1 in C++14 mode to ensure that a +# C++14 compiler can still start the bootstrap. Otherwise, if building GCC, +# require C++14 (or higher). if test "$enable_bootstrap:$GXX" = "yes:yes"; then - CXX="$CXX -std=c++11" + CXX="$CXX -std=c++14" elif test "$have_compiler" = yes; then - AX_CXX_COMPILE_STDCXX(11) + AX_CXX_COMPILE_STDCXX(14) if test "${build}" != "${host}"; then - AX_CXX_COMPILE_STDCXX(11, [], [], [_FOR_BUILD]) + AX_CXX_COMPILE_STDCXX(14, [], [], [_FOR_BUILD]) fi fi @@ -2057,6 +2058,64 @@ fi AC_SUBST(PICFLAG) + +# Check for libdiagnostics support. +AC_MSG_CHECKING([whether to enable libdiagnostics]) +AC_ARG_ENABLE(libdiagnostics, +[AS_HELP_STRING([--enable-libdiagnostics], + [build libdiagnostics shared library])], +enable_libdiagnostics=$enableval, +enable_libdiagnostics=no) + +if test x$enable_libdiagnostics = xyes; then + # Disable libdiagnostics if -enable-host-shared not specified + # but not if building for Mingw. All code in Windows + # is position independent code (PIC). + case $target in + *mingw*) ;; + *) + if test x$host_shared != xyes; then + AC_MSG_ERROR([ +Enabling libdiagnostics requires --enable-host-shared. + +--enable-host-shared typically slows the rest of the compiler down by +a few %, so you must explicitly enable it. + +If you want to build both libdiagnostics and the regular compiler, it is often +best to do this via two separate configure/builds, in separate +directories, to avoid imposing the performance cost of +--enable-host-shared on the regular compiler.]) + fi + ;; + esac +fi +AC_MSG_RESULT($enable_libdiagnostics) +AC_SUBST(enable_libdiagnostics) + + +# Rust requires -ldl and -lpthread if you are using an old glibc that does not include them by +# default, so we check for them here +# We are doing the test here and not in the gcc/configure to be able to nicely disable the +# build of the Rust frontend in case a dep is missing. +missing_rust_dynlibs=none + +save_LIBS="$LIBS" +LIBS= +AC_SEARCH_LIBS([dlopen], [dl]) +AC_SEARCH_LIBS([pthread_create], [pthread]) +CRAB1_LIBS="$LIBS" +LIBS="$save_LIBS" + +if test "$ac_cv_search_dlopen" = no; then + missing_rust_dynlibs="libdl" +fi + +if test "$ac_cv_search_pthread_create" = no; then + missing_rust_dynlibs="$missing_rust_dynlibs, libpthread" +fi + +AC_SUBST(CRAB1_LIBS, "$CRAB1_LIBS") + # If we are building PIC/PIE host executables, and we are building dependent # libs (e.g. GMP) in-tree those libs need to be configured to generate PIC # code. @@ -2133,7 +2192,7 @@ if test -d ${srcdir}/gcc; then lang_requires_boot_languages= # set srcdir during sourcing lang_frag to the gcc dir. # Sadly overriding srcdir on the . line doesn't work in plain sh as it - # polutes this shell + # pollutes this shell saved_srcdir=${srcdir} srcdir=${srcdir}/gcc . ${lang_frag} srcdir=${saved_srcdir} @@ -2294,6 +2353,25 @@ if test -d ${srcdir}/gcc; then ;; esac + # Disable Rust if we are missing some required C libraries for the Rust runtime. + case ${add_this_lang}:${language}:${missing_rust_dynlibs} in + *:rust:none) + # Nothing to do - we're not missing any C libraries + ;; + yes:rust:*) + AC_MSG_ERROR([some C libraries are required to build $language: $missing_rust_dynlibs]) + add_this_lang=unsupported + ;; + all:rust:*) + AC_MSG_WARN([some C libraries are required to build $language: $missing_rust_dynlibs]) + add_this_lang=unsupported + ;; + *:rust:*) + # Silently disable. + add_this_lang=unsupported + ;; + esac + # Disable jit if -enable-host-shared not specified # but not if building for Mingw. All code in Windows # is position independent code (PIC). @@ -2326,6 +2404,35 @@ directories, to avoid imposing the performance cost of ;; esac + # Pre-conditions to consider whether cargo being supported. + if test x"$have_cargo" = xyes \ + && test x"$build" != x"$host"; then + # Until <https://github.com/Rust-GCC/gccrs/issues/2898> + # "'cargo' should build for the host system" is resolved: + AC_MSG_WARN([use of cargo not yet supported here in Canadian cross configurations]) + have_cargo=no + else + # Assume that cargo-produced object files are compatible with what + # we're going to build here. + : + fi + # Disable Rust if cargo is unavailable. + case ${add_this_lang}:${language}:${have_cargo} in + yes:rust:no) + # Specifically requested language; tell them. + AC_MSG_ERROR([cargo is required to build $language]) + ;; + all:rust:no) + AC_MSG_WARN([cargo is required to build $language]) + add_this_lang=unsupported + ;; + *:rust:no) + # Silently disable. + add_this_lang=unsupported + ;; + esac + + # Disable a language that is unsupported by the target. case "${add_this_lang}: $unsupported_languages " in no:*) ;; @@ -3141,6 +3248,15 @@ case "$enable_bootstrap:$ENABLE_GOLD: $configdirs :,$stage1_languages," in ;; esac +# Bootstrapping GCC requires libstdc++-v3 so error out if libstdc++ is disabled with bootstrapping +# Note C++ is always enabled for stage1 now. +case "$enable_bootstrap:${noconfigdirs}" in + yes:*target-libstdc++-v3*) + AC_MSG_ERROR([bootstrapping with --disable-libstdcxx is not supported]) + ;; +esac + + extrasub_build= for module in ${build_configdirs} ; do if test -z "${no_recursion}" \ @@ -6,8 +6,9 @@ * On x86 emulation support (for secondary targets) was dropped. -* Add support for RISC-V Zcmp (cm.mva01s, cm.mvsa01), Smrnmi and CORE-V - (xcvbitmanip, xcvsimd) extensions with version 1.0. +* Add support for RISC-V Zcmp (cm.mva01s, cm.mvsa01), Smrnmi, CORE-V + (xcvbitmanip, xcvsimd) extensions with version 1.0 and more SiFive + extensions (xsfvqmaccdod, xsfvqmaccqoq and xsfvfnrclipxfqf). Changes in 2.43: diff --git a/gas/testsuite/gas/riscv/march-help.l b/gas/testsuite/gas/riscv/march-help.l index 4234b05..71cccb7 100644 --- a/gas/testsuite/gas/riscv/march-help.l +++ b/gas/testsuite/gas/riscv/march-help.l @@ -157,3 +157,6 @@ All available -march extensions for RISC-V: xventanacondops 1.0 xsfvcp 1.0 xsfcease 1.0 + xsfvqmaccqoq 1.0 + xsfvqmaccdod 1.0 + xsfvfnrclipxfqf 1.0 diff --git a/gas/testsuite/gas/riscv/march-imply-xsfvfnrclipxfqf.d b/gas/testsuite/gas/riscv/march-imply-xsfvfnrclipxfqf.d new file mode 100644 index 0000000..e77fee0 --- /dev/null +++ b/gas/testsuite/gas/riscv/march-imply-xsfvfnrclipxfqf.d @@ -0,0 +1,6 @@ +#as: -march=rv32i_xsfvfnrclipxfqf -march-attr -misa-spec=20191213 +#readelf: -A +#source: empty.s +Attribute Section: riscv +File Attributes + Tag_RISCV_arch: "rv32i2p1_f2p2_zicsr2p0_zve32f1p0_zve32x1p0_zvl32b1p0_xsfvfnrclipxfqf1p0" diff --git a/gas/testsuite/gas/riscv/march-imply-xsfvqmaccdod.d b/gas/testsuite/gas/riscv/march-imply-xsfvqmaccdod.d new file mode 100644 index 0000000..47e91f8 --- /dev/null +++ b/gas/testsuite/gas/riscv/march-imply-xsfvqmaccdod.d @@ -0,0 +1,6 @@ +#as: -march=rv32i_xsfvqmaccdod -march-attr -misa-spec=20191213 +#readelf: -A +#source: empty.s +Attribute Section: riscv +File Attributes + Tag_RISCV_arch: "rv32i2p1_zicsr2p0_zve32x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0_xsfvqmaccdod1p0" diff --git a/gas/testsuite/gas/riscv/march-imply-xsfvqmaccqoq.d b/gas/testsuite/gas/riscv/march-imply-xsfvqmaccqoq.d new file mode 100644 index 0000000..784a8ac --- /dev/null +++ b/gas/testsuite/gas/riscv/march-imply-xsfvqmaccqoq.d @@ -0,0 +1,6 @@ +#as: -march=rv32i_xsfvqmaccqoq -march-attr -misa-spec=20191213 +#readelf: -A +#source: empty.s +Attribute Section: riscv +File Attributes + Tag_RISCV_arch: "rv32i2p1_zicsr2p0_zve32x1p0_zvl128b1p0_zvl256b1p0_zvl32b1p0_zvl64b1p0_xsfvqmaccqoq1p0" diff --git a/gas/testsuite/gas/riscv/sifive-insns.d b/gas/testsuite/gas/riscv/sifive-insns.d index 610f625..d1917b4 100644 --- a/gas/testsuite/gas/riscv/sifive-insns.d +++ b/gas/testsuite/gas/riscv/sifive-insns.d @@ -36,3 +36,13 @@ Disassembly of section .text: [ ]+[0-9a-f]+:[ ]+fc27b05b[ ]+sf.vc.v.ivw[ ]+0x3,v0,v2,15 [ ]+[0-9a-f]+:[ ]+fc25d05b[ ]+sf.vc.v.fvw[ ]+0x1,v0,v2,fa1 [ ]+[0-9a-f]+:[ ]+30500073[ ]+sf.cease +[ ]+[0-9a-f]+:[ ]+f2c4225b[ ]+sf.vqmaccu.4x8x4[ ]+v4,v8,v12 +[ ]+[0-9a-f]+:[ ]+f6c4225b[ ]+sf.vqmacc.4x8x4[ ]+v4,v8,v12 +[ ]+[0-9a-f]+:[ ]+fac4225b[ ]+sf.vqmaccus.4x8x4[ ]+v4,v8,v12 +[ ]+[0-9a-f]+:[ ]+fec4225b[ ]+sf.vqmaccsu.4x8x4[ ]+v4,v8,v12 +[ ]+[0-9a-f]+:[ ]+b2c4225b[ ]+sf.vqmaccu.2x8x2[ ]+v4,v8,v12 +[ ]+[0-9a-f]+:[ ]+b6c4225b[ ]+sf.vqmacc.2x8x2[ ]+v4,v8,v12 +[ ]+[0-9a-f]+:[ ]+bac4225b[ ]+sf.vqmaccus.2x8x2[ ]+v4,v8,v12 +[ ]+[0-9a-f]+:[ ]+bec4225b[ ]+sf.vqmaccsu.2x8x2[ ]+v4,v8,v12 +[ ]+[0-9a-f]+:[ ]+8a86525b[ ]+sf.vfnrclip.xu.f.qf[ ]+v4,v8,fa2 +[ ]+[0-9a-f]+:[ ]+8e86525b[ ]+sf.vfnrclip.x.f.qf[ ]+v4,v8,fa2 diff --git a/gas/testsuite/gas/riscv/sifive-insns.s b/gas/testsuite/gas/riscv/sifive-insns.s index cdf90c1..5005fb3 100644 --- a/gas/testsuite/gas/riscv/sifive-insns.s +++ b/gas/testsuite/gas/riscv/sifive-insns.s @@ -37,3 +37,28 @@ .option arch, +xsfcease1p0 sf.cease .option pop + + # xsfvqmaccqoq + .option push + .option arch, +xsfvqmaccqoq + sf.vqmaccu.4x8x4 v4, v8, v12 + sf.vqmacc.4x8x4 v4, v8, v12 + sf.vqmaccus.4x8x4 v4, v8, v12 + sf.vqmaccsu.4x8x4 v4, v8, v12 + .option pop + + # xsfvqmaccdod + .option push + .option arch, +xsfvqmaccdod + sf.vqmaccu.2x8x2 v4, v8, v12 + sf.vqmacc.2x8x2 v4, v8, v12 + sf.vqmaccus.2x8x2 v4, v8, v12 + sf.vqmaccsu.2x8x2 v4, v8, v12 + .option pop + + # xsfvfnrclipxfqf + .option push + .option arch, +xsfvfnrclipxfqf + sf.vfnrclip.xu.f.qf v4, v8, f12 + sf.vfnrclip.x.f.qf v4, v8, f12 + .option pop @@ -94,6 +94,10 @@ * New commands +show jit-reader-directory + Show the name of the directory that "jit-reader-load" uses for + relative file names. + set style line-number foreground COLOR set style line-number background COLOR set style line-number intensity VALUE diff --git a/gdb/amd64-windows-tdep.c b/gdb/amd64-windows-tdep.c index df59a44..e3e815e 100644 --- a/gdb/amd64-windows-tdep.c +++ b/gdb/amd64-windows-tdep.c @@ -205,14 +205,12 @@ static void amd64_windows_store_arg_in_reg (struct regcache *regcache, struct value *arg, int regno) { - struct type *type = arg->type (); - const gdb_byte *valbuf = arg->contents ().data (); + gdb::array_view<const gdb_byte> valbuf = arg->contents (); /* We only set 8 bytes, buf if it's a XMM register, 16 bytes are read. */ - std::array<gdb_byte, 16> buf; + std::array<gdb_byte, 16> buf {}; - gdb_assert (type->length () <= 8); - memset (buf.data (), 0, buf.size ()); - memcpy (buf.data (), valbuf, std::min (type->length (), (ULONGEST) 8)); + gdb_assert (valbuf.size () <= 8); + std::copy (valbuf.begin (), valbuf.end (), buf.begin ()); size_t reg_size = regcache_register_size (regcache, regno); gdb_assert (reg_size <= buf.size ()); gdb::array_view<gdb_byte> view (buf); diff --git a/gdb/build-id.c b/gdb/build-id.c index 9d4b005..43a80dd 100644 --- a/gdb/build-id.c +++ b/gdb/build-id.c @@ -223,7 +223,13 @@ build_id_to_debug_bfd_1 (const std::string &original_link, /* Common code for finding BFDs of a given build-id. This function works with both debuginfo files (SUFFIX == ".debug") and executable - files (SUFFIX == ""). */ + files (SUFFIX == ""). + + The build-id will be split into a single byte sub-directory, followed by + the remaining build-id bytes as the filename, i.e. we use the lookup + format: `.build-id/xx/yy....zz`. As a consequence, if BUILD_ID_LEN is + less than 2 (bytes), no results will be found as there are not enough + bytes to form the `yy....zz` part of the lookup filename. */ static gdb_bfd_ref_ptr build_id_to_bfd_suffix (size_t build_id_len, const bfd_byte *build_id, @@ -231,6 +237,16 @@ build_id_to_bfd_suffix (size_t build_id_len, const bfd_byte *build_id, { SEPARATE_DEBUG_FILE_SCOPED_DEBUG_ENTER_EXIT; + if (build_id_len < 2) + { + /* Zero length build-ids are ignored by bfd. */ + gdb_assert (build_id_len > 0); + separate_debug_file_debug_printf + ("Ignoring short build-id `%s' for build-id based lookup", + bin2hex (build_id, build_id_len).c_str ()); + return {}; + } + /* Keep backward compatibility so that DEBUG_FILE_DIRECTORY being "" will cause "/.build-id/..." lookups. */ @@ -249,11 +265,9 @@ build_id_to_bfd_suffix (size_t build_id_len, const bfd_byte *build_id, std::string link = debugdir.get (); link += "/.build-id/"; - if (size > 0) - { - size--; - string_appendf (link, "%02x/", (unsigned) *data++); - } + gdb_assert (size > 1); + size--; + string_appendf (link, "%02x/", (unsigned) *data++); while (size-- > 0) string_appendf (link, "%02x", (unsigned) *data++); diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c index 299064f..0140c71 100644 --- a/gdb/cli/cli-cmds.c +++ b/gdb/cli/cli-cmds.c @@ -923,7 +923,7 @@ run_under_shell (const char *arg, int from_tty) if (pid != -1) { - int ret = gdb::handle_eintr (-1, ::waitpid, pid, &status, 0); + int ret = gdb::waitpid (pid, &status, 0); if (ret == -1) perror_with_name ("Cannot get status of shell command"); } @@ -1551,17 +1551,19 @@ print_disassembly (struct gdbarch *gdbarch, const char *name, static void disassemble_current_function (gdb_disassembly_flags flags) { - frame_info_ptr frame; - struct gdbarch *gdbarch; - CORE_ADDR low, high, pc; - const char *name; - const struct block *block; + frame_info_ptr frame = get_selected_frame (_("No frame selected.")); + struct gdbarch *gdbarch = get_frame_arch (frame); + CORE_ADDR pc = get_frame_address_in_block (frame); - frame = get_selected_frame (_("No frame selected.")); - gdbarch = get_frame_arch (frame); - pc = get_frame_address_in_block (frame); - if (find_pc_partial_function (pc, &name, &low, &high, &block) == 0) + const general_symbol_info *gsi; + const struct block *block; + CORE_ADDR low, high; + if (find_pc_partial_function_sym (pc, &gsi, &low, &high, &block) == 0) error (_("No function contains program counter for selected frame.")); + + gdb_assert (gsi != nullptr); + const char *name = asm_demangle ? gsi->print_name () : gsi->linkage_name (); + #if defined(TUI) /* NOTE: cagney/2003-02-13 The `tui_active' was previously `tui_version'. */ diff --git a/gdb/darwin-nat.c b/gdb/darwin-nat.c index e4243f6..7f6b72b 100644 --- a/gdb/darwin-nat.c +++ b/gdb/darwin-nat.c @@ -70,6 +70,7 @@ #include "gdbsupport/scoped_fd.h" #include "gdbsupport/scoped_restore.h" #include "nat/fork-inferior.h" +#include "gdbsupport/eintr.h" /* Quick overview. Darwin kernel is Mach + BSD derived kernel. Note that they share the @@ -1604,7 +1605,7 @@ darwin_attach_pid (struct inferior *inf) if (!inf->attach_flag) { kill (inf->pid, 9); - waitpid (inf->pid, &status, 0); + gdb::waitpid (inf->pid, &status, 0); } error diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 99720f1..b91b5d6 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -40047,6 +40047,10 @@ reporting an error. A new JIT reader can be loaded by first unloading the current one using @code{jit-reader-unload} and then invoking @code{jit-reader-load}. +@item show jit-reader-directory +This command will show the directory that is used by +@code{jit-reader-load} when a relative file name is specified. + @item jit-reader-unload Unload the currently loaded JIT reader. diff --git a/gdb/event-top.c b/gdb/event-top.c index 38a59ba..cab6c84 100644 --- a/gdb/event-top.c +++ b/gdb/event-top.c @@ -1268,6 +1268,60 @@ handle_sigint (int sig) mark_async_signal_handler (sigint_token); } +/* Copy file descriptors smaller than N from SRC to DST and return DST. + Portable version of FD_COPY. */ + +static fd_set * +fd_copy (fd_set *dst, const fd_set *src, int n) +{ + FD_ZERO (dst); + for (int i = 0; i < n; ++i) + if (FD_ISSET (i, src)) + FD_SET (i, dst); + + return dst; +} + +/* Copy SRC to DST and return DST. */ + +static struct timeval * +timeval_copy (struct timeval *dst, const struct timeval *src) +{ + *dst = *src; + return dst; +} + +/* Version of select that can be used in a loop, since unlike select it keeps + requested and returned values separate. */ + +static int +gdb_select (int n, + const fd_set *req_readfds, fd_set *ret_readfds, + const fd_set *req_writefds, fd_set *ret_writefds, + const fd_set *req_exceptfds, fd_set *ret_exceptfds, + const struct timeval *req_timeout, struct timeval *ret_timeout) +{ + ret_readfds + = (req_readfds == nullptr + ? nullptr + : fd_copy (ret_readfds, req_readfds, n)); + ret_writefds + = (req_writefds == nullptr + ? nullptr + : fd_copy (ret_writefds, req_writefds, n)); + ret_exceptfds + = (req_exceptfds == nullptr + ? nullptr + : fd_copy (ret_exceptfds, req_exceptfds, n)); + + ret_timeout + = (req_timeout == nullptr + ? nullptr + : timeval_copy (ret_timeout, req_timeout)); + + return gdb_select (n, ret_readfds, ret_writefds, ret_exceptfds, ret_timeout); +} + /* See gdb_select.h. */ int @@ -1290,11 +1344,64 @@ interruptible_select (int n, if (n <= fd) n = fd + 1; - do + bool tsan_forced_timeout = false; +#if defined (__SANITIZE_THREAD__) + struct timeval tv; + if (timeout == nullptr) { - res = gdb_select (n, readfds, writefds, exceptfds, timeout); + /* A nullptr timeout means select is blocking, and ThreadSanitizer has + a bug that it considers select non-blocking, and consequently when + intercepting select it will not call signal handlers for pending + signals, and gdb will hang in select waiting for those signal + handlers to be called. + + Filed here ( https://github.com/google/sanitizers/issues/1813 ). + + Work around this by: + - forcing a small timeout, and + - upon timeout calling a function that ThreadSanitizer does consider + blocking: usleep, forcing signal handlers to be called for pending + signals. */ + tv.tv_sec = 0; + tv.tv_usec = 1000; + timeout = &tv; + tsan_forced_timeout = true; } - while (res == -1 && errno == EINTR); +#endif + + { + fd_set ret_readfds, ret_writefds, ret_exceptfds; + struct timeval ret_timeout; + + while (true) + { + res = gdb_select (n, + readfds, &ret_readfds, + writefds, &ret_writefds, + exceptfds, &ret_exceptfds, + timeout, &ret_timeout); + + if (res == -1 && errno == EINTR) + continue; + + if (tsan_forced_timeout && res == 0) + { + usleep (0); + continue; + } + + break; + } + + if (readfds != nullptr) + fd_copy (readfds, &ret_readfds, n); + if (writefds != nullptr) + fd_copy (writefds, &ret_writefds, n); + if (exceptfds != nullptr) + fd_copy (exceptfds, &ret_exceptfds, n); + if (timeout) + timeval_copy (timeout, &ret_timeout); + } if (res == 1 && FD_ISSET (fd, readfds)) { diff --git a/gdb/extension.c b/gdb/extension.c index ec1aa13..47f5691 100644 --- a/gdb/extension.c +++ b/gdb/extension.c @@ -33,6 +33,7 @@ #include "guile/guile.h" #include <array> #include "inferior.h" +#include "gdbsupport/scoped_signal_handler.h" static script_sourcer_func source_gdb_script; static objfile_script_sourcer_func source_gdb_objfile_script; @@ -297,28 +298,6 @@ ext_lang_auto_load_enabled (const struct extension_language_defn *extlang) } -/* RAII class used to temporarily return SIG to its default handler. */ - -template<int SIG> -struct scoped_default_signal -{ - scoped_default_signal () - { m_old_sig_handler = signal (SIG, SIG_DFL); } - - ~scoped_default_signal () - { signal (SIG, m_old_sig_handler); } - - DISABLE_COPY_AND_ASSIGN (scoped_default_signal); - -private: - /* The previous signal handler that needs to be restored. */ - sighandler_t m_old_sig_handler; -}; - -/* Class to temporarily return SIGINT to its default handler. */ - -using scoped_default_sigint = scoped_default_signal<SIGINT>; - /* Functions that iterate over all extension languages. These only iterate over external extension languages, not including GDB's own extension/scripting language, unless otherwise indicated. */ @@ -334,7 +313,7 @@ ext_lang_initialization (void) if (extlang->ops != nullptr && extlang->ops->initialize != NULL) { - scoped_default_sigint set_sigint_to_default_handler; + scoped_signal_handler<SIGINT> set_sigint_to_default_handler (SIG_DFL); extlang->ops->initialize (extlang); } } diff --git a/gdb/fbsd-nat.c b/gdb/fbsd-nat.c index 6da32a4..8e0523d 100644 --- a/gdb/fbsd-nat.c +++ b/gdb/fbsd-nat.c @@ -45,6 +45,7 @@ #include "elf-bfd.h" #include "fbsd-nat.h" #include "fbsd-tdep.h" +#include "gdbsupport/eintr.h" #ifndef PT_GETREGSET #define PT_GETREGSET 42 /* Get a target register set */ @@ -1150,7 +1151,7 @@ fbsd_wait_for_fork_child (pid_t pid) return ptid; int status; - pid_t wpid = waitpid (pid, &status, 0); + pid_t wpid = gdb::waitpid (pid, &status, 0); if (wpid == -1) perror_with_name (("waitpid")); @@ -2156,7 +2157,7 @@ fbsd_nat_target::kill () perror_with_name (("ptrace (PT_KILL)")); int status; - waitpid (pid, &status, 0); + gdb::waitpid (pid, &status, 0); target_mourn_inferior (inferior_ptid); } diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index 6a919bf..eb8ddfc 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -4951,6 +4951,17 @@ i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r, } break; + case 0x74: /* VPCMPEQB */ + case 0x75: /* VPCMPEQB */ + case 0x76: /* VPCMPEQB */ + { + i386_record_modrm (ir); + int reg_offset = ir->reg + vex_r * 8; + record_full_arch_list_add_reg (ir->regcache, + tdep->ymm0_regnum + reg_offset); + } + break; + case 0x78: /* VPBROADCASTB */ case 0x79: /* VPBROADCASTW */ case 0x58: /* VPBROADCASTD */ @@ -4981,6 +4992,25 @@ i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r, break; } + case 0xd7: /* VPMOVMSKB */ + { + i386_record_modrm (ir); + record_full_arch_list_add_reg (ir->regcache, + ir->regmap[X86_RECORD_REAX_REGNUM + + ir->reg + 8 * vex_r]); + } + break; + + case 0xef: /* VPXOR */ + case 0xeb: /* VPOR */ + { + i386_record_modrm (ir); + int reg_offset = ir->reg + vex_r * 8; + record_full_arch_list_add_reg (ir->regcache, + tdep->ymm0_regnum + reg_offset); + break; + } + default: gdb_printf (gdb_stderr, _("Process record does not support VEX instruction 0x%02x " diff --git a/gdb/inf-ptrace.c b/gdb/inf-ptrace.c index 6ef2ea8..56ff2fc 100644 --- a/gdb/inf-ptrace.c +++ b/gdb/inf-ptrace.c @@ -32,6 +32,7 @@ #include "nat/fork-inferior.h" #include "utils.h" #include "gdbarch.h" +#include "gdbsupport/eintr.h" @@ -122,7 +123,7 @@ inf_ptrace_target::mourn_inferior () Do not check whether this succeeds though, since we may be dealing with a process that we attached to. Such a process will only report its exit status to its original parent. */ - waitpid (inferior_ptid.pid (), &status, 0); + gdb::waitpid (inferior_ptid.pid (), &status, 0); inf_child_target::mourn_inferior (); } @@ -227,7 +228,7 @@ inf_ptrace_target::kill () return; ptrace (PT_KILL, pid, (PTRACE_TYPE_ARG3)0, 0); - waitpid (pid, &status, 0); + gdb::waitpid (pid, &status, 0); target_mourn_inferior (inferior_ptid); } @@ -307,12 +308,8 @@ inf_ptrace_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus, { set_sigint_trap (); - do - { - pid = waitpid (ptid.pid (), &status, options); - save_errno = errno; - } - while (pid == -1 && errno == EINTR); + pid = gdb::waitpid (ptid.pid (), &status, options); + save_errno = errno; clear_sigint_trap (); @@ -28,6 +28,7 @@ #include "filenames.h" #include "frame-unwind.h" #include "cli/cli-cmds.h" +#include "cli/cli-style.h" #include "gdbcore.h" #include "inferior.h" #include "observable.h" @@ -1298,6 +1299,16 @@ jit_event_handler (gdbarch *gdbarch, objfile *jiter) } } +/* Implementation of "show jit-reader-directory". */ + +static void +show_jit_reader_directory (const char *args, int from_tty) +{ + gdb_printf (_("JIT reader directory is %ps.\n"), + styled_string (file_name_style.style (), + jit_reader_dir.c_str ())); +} + void _initialize_jit (); void _initialize_jit () @@ -1329,8 +1340,8 @@ _initialize_jit () Load FILE as debug info reader and unwinder for JIT compiled code.\n\ Usage: jit-reader-load FILE\n\ Try to load file FILE as a debug info reader (and unwinder) for\n\ -JIT compiled code. The file is loaded from " JIT_READER_DIR ",\n\ -relocated relative to the GDB executable if required.")); +JIT compiled code. If FILE is not an absolute file name, it is found\n\ +relative to a built-in directory. See \"show jit-reader-directory\".")); set_cmd_completer (c, deprecated_filename_completer); c = add_com ("jit-reader-unload", no_class, @@ -1339,5 +1350,11 @@ Unload the currently loaded JIT debug info reader.\n\ Usage: jit-reader-unload\n\n\ Do \"help jit-reader-load\" for info on loading debug info readers.")); set_cmd_completer (c, noop_completer); + + add_cmd ("jit-reader-directory", class_obscure, + show_jit_reader_directory, + _("Show the JIT reader directory.\n\ +This is the directory used by \"jit-reader-load\" when given\n\ +a relative file name."), &showlist); } } diff --git a/gdb/linux-fork.c b/gdb/linux-fork.c index c457a90..7d3505b 100644 --- a/gdb/linux-fork.c +++ b/gdb/linux-fork.c @@ -32,6 +32,7 @@ #include "nat/gdb_ptrace.h" #include "gdbsupport/gdb_wait.h" +#include "gdbsupport/eintr.h" #include "target/waitstatus.h" #include <dirent.h> #include <ctype.h> @@ -314,7 +315,7 @@ linux_fork_killall (void) /* Use SIGKILL instead of PTRACE_KILL because the former works even if the thread is running, while the later doesn't. */ kill (pid, SIGKILL); - ret = waitpid (pid, &status, 0); + ret = gdb::waitpid (pid, &status, 0); /* We might get a SIGCHLD instead of an exit status. This is aggravated by the first kill above - a child has just died. MVS comment cut-and-pasted from linux-nat. */ @@ -339,7 +340,7 @@ linux_fork_mourn_inferior (void) Do not check whether this succeeds though, since we may be dealing with a process that we attached to. Such a process will only report its exit status to its original parent. */ - waitpid (inferior_ptid.pid (), &status, 0); + gdb::waitpid (inferior_ptid.pid (), &status, 0); /* OK, presumably inferior_ptid is the one who has exited. We need to delete that one from the fork_list, and switch @@ -548,7 +549,7 @@ Please switch to another checkpoint before deleting the current one")); this succeeds though, since we may be dealing with a process that we attached to. Such a process will only report its exit status to its original parent. */ - waitpid (ptid.pid (), &status, 0); + gdb::waitpid (ptid.pid (), &status, 0); return; } diff --git a/gdb/nat/linux-namespaces.c b/gdb/nat/linux-namespaces.c index 9abd3d6..19a05ee 100644 --- a/gdb/nat/linux-namespaces.c +++ b/gdb/nat/linux-namespaces.c @@ -28,6 +28,7 @@ #include <signal.h> #include <sched.h> #include "gdbsupport/scope-exit.h" +#include "gdbsupport/eintr.h" /* See nat/linux-namespaces.h. */ bool debug_linux_namespaces; @@ -722,7 +723,7 @@ mnsh_maybe_mourn_peer (void) return; } - pid = waitpid (helper->pid, &status, WNOHANG); + pid = gdb::waitpid (helper->pid, &status, WNOHANG); if (pid == 0) { /* The helper is still alive. */ diff --git a/gdb/nat/linux-ptrace.c b/gdb/nat/linux-ptrace.c index 9ea0e22..f90183b 100644 --- a/gdb/nat/linux-ptrace.c +++ b/gdb/nat/linux-ptrace.c @@ -22,6 +22,7 @@ #ifdef HAVE_SYS_PROCFS_H #include <sys/procfs.h> #endif +#include "gdbsupport/eintr.h" /* Stores the ptrace options supported by the running kernel. A value of -1 means we did not check for features yet. A value @@ -177,7 +178,7 @@ linux_ptrace_test_ret_to_nx (void) } errno = 0; - got_pid = waitpid (child, &status, 0); + got_pid = gdb::waitpid (child, &status, 0); if (got_pid != child) { warning (_("linux_ptrace_test_ret_to_nx: waitpid returned %ld: %s"), diff --git a/gdb/nat/linux-waitpid.c b/gdb/nat/linux-waitpid.c index 0ac2f9f..f4ae612 100644 --- a/gdb/nat/linux-waitpid.c +++ b/gdb/nat/linux-waitpid.c @@ -51,5 +51,5 @@ status_to_str (int status) int my_waitpid (int pid, int *status, int flags) { - return gdb::handle_eintr (-1, ::waitpid, pid, status, flags); + return gdb::waitpid (pid, status, flags); } diff --git a/gdb/netbsd-nat.c b/gdb/netbsd-nat.c index 90456de..5005cb8 100644 --- a/gdb/netbsd-nat.c +++ b/gdb/netbsd-nat.c @@ -25,6 +25,7 @@ #include "inferior.h" #include "gdbarch.h" #include "gdbsupport/buildargv.h" +#include "gdbsupport/eintr.h" #include <sys/types.h> #include <sys/ptrace.h> @@ -547,12 +548,8 @@ nbsd_wait (ptid_t ptid, struct target_waitstatus *ourstatus, set_sigint_trap (); - do - { - /* The common code passes WNOHANG that leads to crashes, overwrite it. */ - pid = waitpid (ptid.pid (), &status, 0); - } - while (pid == -1 && errno == EINTR); + /* The common code passes WNOHANG that leads to crashes, overwrite it. */ + pid = gdb::waitpid (ptid.pid (), &status, 0); clear_sigint_trap (); diff --git a/gdb/obsd-nat.c b/gdb/obsd-nat.c index 69a21ad..701a365 100644 --- a/gdb/obsd-nat.c +++ b/gdb/obsd-nat.c @@ -27,6 +27,7 @@ #include "inf-ptrace.h" #include "obsd-nat.h" +#include "gdbsupport/eintr.h" /* OpenBSD 5.2 and later include rthreads which uses a thread model that maps userland threads directly onto kernel threads in a 1:1 @@ -105,7 +106,7 @@ obsd_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus, ourstatus->set_forked (ptid_t (pe.pe_other_pid)); /* Make sure the other end of the fork is stopped too. */ - pid_t fpid = waitpid (pe.pe_other_pid, nullptr, 0); + pid_t fpid = gdb::waitpid (pe.pe_other_pid, nullptr, 0); if (fpid == -1) perror_with_name (("waitpid")); diff --git a/gdb/procfs.c b/gdb/procfs.c index c6abe3e..d5177f3 100644 --- a/gdb/procfs.c +++ b/gdb/procfs.c @@ -2062,8 +2062,9 @@ wait_again: { int wait_retval; - /* /proc file not found; presumably child has terminated. */ - wait_retval = ::wait (&wstat); /* "wait" for the child's exit. */ + /* /proc file not found; presumably child has terminated. Wait + for the child's exit. */ + wait_retval = gdb::wait (&wstat); /* Wrong child? */ if (wait_retval != inf->pid) @@ -2150,7 +2151,7 @@ wait_again: } else { - int temp = ::wait (&wstat); + int temp = gdb::wait (&wstat); /* FIXME: shouldn't I make sure I get the right event from the right process? If (for @@ -2560,9 +2561,9 @@ unconditionally_kill_inferior (procinfo *pi) #if 0 int status, ret; - ret = waitpid (pi->pid, &status, 0); + ret = gdb::waitpid (pi->pid, &status, 0); #else - wait (NULL); + gdb::wait (NULL); #endif } } diff --git a/gdb/python/python.c b/gdb/python/python.c index 397431a..3dc56d5 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -2215,6 +2215,9 @@ static struct cmd_list_element *user_show_python_list; static void finalize_python (const struct extension_language_defn *ignore) { + if (!gdb_python_initialized) + return; + struct active_ext_lang_state *previous_active; /* We don't use ensure_python_env here because if we ever ran the @@ -2297,6 +2300,42 @@ gdbpy_gdb_exiting (int exit_code) gdbpy_print_stack (); } +/* Signal handler to convert a SIGABRT into an exception. */ + +static void +catch_python_fatal (int signum) +{ + signal (SIGABRT, catch_python_fatal); + + throw_exception_sjlj (gdb_exception {RETURN_ERROR, GENERIC_ERROR}); +} + +/* Stand-in for Py_IsInitialized (). To be used because after a python fatal + error, no calls into Python are allowed. */ + +static bool py_isinitialized = false; + +/* Call Py_Initialize (), and return true if successful. */ + +static bool ATTRIBUTE_UNUSED +py_initialize () +{ + auto prev_handler = signal (SIGABRT, catch_python_fatal); + SCOPE_EXIT { signal (SIGABRT, prev_handler); }; + + TRY_SJLJ + { + Py_Initialize (); + py_isinitialized = true; + } + CATCH_SJLJ (e, RETURN_MASK_ERROR) + { + } + END_CATCH_SJLJ; + + return py_isinitialized; +} + static bool do_start_initialization () { @@ -2331,17 +2370,20 @@ do_start_initialization () for Python versions that do not duplicate program_name. */ static wchar_t *progname_copy; - std::string oldloc = setlocale (LC_ALL, NULL); - setlocale (LC_ALL, ""); - size_t progsize = strlen (progname.get ()); - progname_copy = XNEWVEC (wchar_t, progsize + 1); - size_t count = mbstowcs (progname_copy, progname.get (), progsize + 1); - if (count == (size_t) -1) - { - fprintf (stderr, "Could not convert python path to string\n"); - return false; - } - setlocale (LC_ALL, oldloc.c_str ()); + { + std::string oldloc = setlocale (LC_ALL, NULL); + SCOPE_EXIT { setlocale (LC_ALL, oldloc.c_str ()); }; + + setlocale (LC_ALL, ""); + size_t progsize = strlen (progname.get ()); + progname_copy = XNEWVEC (wchar_t, progsize + 1); + size_t count = mbstowcs (progname_copy, progname.get (), progsize + 1); + if (count == (size_t) -1) + { + fprintf (stderr, "Could not convert python path to string\n"); + return false; + } + } /* Py_SetProgramName was deprecated in Python 3.11. Use PyConfig mechanisms for Python 3.10 and newer. */ @@ -2350,7 +2392,8 @@ do_start_initialization () remain alive for the duration of the program's execution, so it is not freed after this call. */ Py_SetProgramName (progname_copy); - Py_Initialize (); + if (!py_initialize ()) + return false; #else PyConfig config; @@ -2372,10 +2415,19 @@ do_start_initialization () init_done: PyConfig_Clear (&config); if (PyStatus_Exception (status)) - return false; + { + if (PyStatus_IsError (status)) + gdb_printf (_("Python initialization failed: %s\n"), status.err_msg); + else + gdb_printf (_("Python initialization failed with exit status: %d\n"), + status.exitcode); + return false; + } + py_isinitialized = true; #endif #else - Py_Initialize (); + if (!py_initialize ()) + return false; #endif #if PY_VERSION_HEX < 0x03090000 @@ -2717,8 +2769,21 @@ do_initialize (const struct extension_language_defn *extlang) static void gdbpy_initialize (const struct extension_language_defn *extlang) { - if (!do_start_initialization () && PyErr_Occurred ()) - gdbpy_print_stack (); + if (!do_start_initialization ()) + { + if (py_isinitialized) + { + if (PyErr_Occurred ()) + gdbpy_print_stack (); + + /* We got no use for the Python interpreter anymore. Finalize it + ASAP. */ + Py_Finalize (); + } + + /* Continue with python disabled. */ + return; + } gdbpy_enter enter_py; diff --git a/gdb/record-full.c b/gdb/record-full.c index d48718a..7d7959f 100644 --- a/gdb/record-full.c +++ b/gdb/record-full.c @@ -39,6 +39,7 @@ #include "infrun.h" #include "gdbsupport/gdb_unlinker.h" #include "gdbsupport/byte-vector.h" +#include "gdbsupport/scoped_signal_handler.h" #include "async-event.h" #include "top.h" #include "valprint.h" @@ -1159,6 +1160,7 @@ record_full_wait_1 (struct target_ops *ops, { scoped_restore restore_operation_disable = record_full_gdb_operation_disable_set (); + scoped_signal_handler<SIGINT> interrupt_handler (record_full_sig_handler); if (record_debug) gdb_printf (gdb_stdlog, @@ -1179,7 +1181,6 @@ record_full_wait_1 (struct target_ops *ops, } record_full_get_sig = 0; - signal (SIGINT, record_full_sig_handler); record_full_stop_reason = TARGET_STOPPED_BY_NO_REASON; @@ -1468,8 +1469,6 @@ record_full_wait_1 (struct target_ops *ops, } } - signal (SIGINT, handle_sigint); - return inferior_ptid; } diff --git a/gdb/rs6000-aix-nat.c b/gdb/rs6000-aix-nat.c index 6a20f61..674189b 100644 --- a/gdb/rs6000-aix-nat.c +++ b/gdb/rs6000-aix-nat.c @@ -42,6 +42,7 @@ #include <signal.h> #include <sys/ioctl.h> #include <fcntl.h> +#include "gdbsupport/eintr.h" #include <a.out.h> #include <sys/file.h> @@ -865,12 +866,8 @@ rs6000_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus, { set_sigint_trap (); - do - { - pid = waitpid (ptid.pid (), &status, 0); - save_errno = errno; - } - while (pid == -1 && errno == EINTR); + pid = gdb::waitpid (ptid.pid (), &status, 0); + save_errno = errno; clear_sigint_trap (); diff --git a/gdb/ser-event.c b/gdb/ser-event.c index fe1c460..b039e86 100644 --- a/gdb/ser-event.c +++ b/gdb/ser-event.c @@ -19,6 +19,7 @@ #include "ser-event.h" #include "serial.h" #include "gdbsupport/filestuff.h" +#include "gdbsupport/eintr.h" /* On POSIX hosts, a serial_event is basically an abstraction for the classical self-pipe trick. @@ -62,8 +63,8 @@ serial_event_open (struct serial *scb, const char *name) if (gdb_pipe_cloexec (fds) == -1) internal_error ("creating serial event pipe failed."); - fcntl (fds[0], F_SETFL, O_NONBLOCK); - fcntl (fds[1], F_SETFL, O_NONBLOCK); + gdb::fcntl (fds[0], F_SETFL, O_NONBLOCK); + gdb::fcntl (fds[1], F_SETFL, O_NONBLOCK); scb->fd = fds[0]; state->write_fd = fds[1]; @@ -91,9 +92,9 @@ serial_event_close (struct serial *scb) { struct serial_event_state *state = (struct serial_event_state *) scb->state; - close (scb->fd); + gdb::close (scb->fd); #ifndef USE_WIN32API - close (state->write_fd); + gdb::close (state->write_fd); #else CloseHandle (state->event); #endif @@ -179,14 +180,9 @@ serial_event_set (struct serial_event *event) struct serial *ser = (struct serial *) event; struct serial_event_state *state = (struct serial_event_state *) ser->state; #ifndef USE_WIN32API - int r; char c = '+'; /* Anything. */ - do - { - r = write (state->write_fd, &c, 1); - } - while (r < 0 && errno == EINTR); + gdb::write (state->write_fd, &c, 1); #else SetEvent (state->event); #endif @@ -205,9 +201,9 @@ serial_event_clear (struct serial_event *event) { char c; - r = read (ser->fd, &c, 1); + r = gdb::read (ser->fd, &c, 1); } - while (r > 0 || (r < 0 && errno == EINTR)); + while (r > 0); #else struct serial_event_state *state = (struct serial_event_state *) ser->state; ResetEvent (state->event); diff --git a/gdb/testsuite/gdb.base/bg-exec-sigint-bp-cond.exp b/gdb/testsuite/gdb.base/bg-exec-sigint-bp-cond.exp index ce2231d..79e2177 100644 --- a/gdb/testsuite/gdb.base/bg-exec-sigint-bp-cond.exp +++ b/gdb/testsuite/gdb.base/bg-exec-sigint-bp-cond.exp @@ -16,6 +16,10 @@ # Check that sending GDB a SIGINT while handling execution control # does not interrupt the execution control. +# The way we get the pid of gdb doesn't work with remote host. We get the +# pid of the ssh session on build instead. +require {!is_remote host} + standard_testfile if {[build_executable "failed to prepare" $testfile $srcfile debug]} { @@ -40,39 +44,50 @@ proc test { {after_kill_cond ""} } { set gdb_pid [exp_pid -i [board_info host fileid]] - # Number of times the breakpoint should be hit before stopping. - set num_hits 10 - - # A counter used in the breakpoint's condition to ensure that it - # causes a stop after NUM_HITS hits. - gdb_test "p \$hit_count = 0" " = 0" "reset hit counter" - # Set a breakpoint with a condition that sends a SIGINT to GDB. This # emulates pressing Ctrl-C just while GDB is evaluating the breakpoint # condition. gdb_test \ - "break foo if \$hit_count\+\+ == $num_hits || \$_shell(\"kill -INT $gdb_pid\") != 0 $after_kill_cond" \ + "break foo if \$hit_count\+\+ == 1 || \$_shell(\"kill -INT $gdb_pid\") != 0 $after_kill_cond" \ "Breakpoint .*" \ "break foo if <condition>" - # Number of times we've seen GDB print "Quit" followed by the - # prompt. We should see that exactly $NUM_HITS times. - set quit_count 0 + for { set i 0 } { $i < 10 } { incr i } { + set done 0 + with_test_prefix $i { - gdb_test_multiple "c&" "SIGINT does not interrupt background execution" { - -re "^c&\r\nContinuing\\.\r\n$::gdb_prompt " { - exp_continue - } - -re "^Quit\r\n$::gdb_prompt " { - incr quit_count - verbose -log "quit_count=$quit_count" - exp_continue - } - -re "^\r\nBreakpoint .*return 0;" { - gdb_assert {$quit_count == $num_hits} $gdb_test_name - } - -re ".*Asynchronous execution not supported on this target\..*" { - unsupported "$gdb_test_name (asynchronous execution not supported)" + # A counter used in the breakpoint's condition to ensure that it + # causes a stop after one hit. + gdb_test "p \$hit_count = 0" " = 0" "reset hit counter" + + # Number of times we've seen GDB print "Quit" followed by the + # prompt. We should see that exactly one time. + set quit_count 0 + + gdb_test_multiple "c&" "SIGINT does not interrupt background execution" { + -re "^c&\r\nContinuing\\.\r\n$::gdb_prompt " { + exp_continue + } + -re "^Quit\r\n$::gdb_prompt " { + incr quit_count + verbose -log "quit_count=$quit_count" + exp_continue + } + -re "^\r\nBreakpoint .*return 0;" { + gdb_assert {$quit_count == 1} $gdb_test_name + } + -re ".*Asynchronous execution not supported on this target\..*" { + unsupported "$gdb_test_name (asynchronous execution not supported)" + } + timeout { + set done 1 + fail "$gdb_test_name (timeout)" + } + } + + if { $done } { + break + } } } } diff --git a/gdb/testsuite/gdb.base/jit-reader.exp b/gdb/testsuite/gdb.base/jit-reader.exp index 62f6af2..2a96207 100644 --- a/gdb/testsuite/gdb.base/jit-reader.exp +++ b/gdb/testsuite/gdb.base/jit-reader.exp @@ -109,6 +109,10 @@ proc jit_reader_test {} { gdb_test_no_output "set debug jit 1" } + # Just test that this is installed and prints something. + gdb_test "show jit-reader-directory" \ + "JIT reader directory is .*\\." + gdb_test_no_output "jit-reader-load ${jit_reader_bin}" "jit-reader-load" gdb_run_cmd gdb_test "" "Program received signal SIGTRAP, .*" "expect SIGTRAP" diff --git a/gdb/testsuite/gdb.cp/disasm-func-name.exp b/gdb/testsuite/gdb.cp/disasm-func-name.exp index 0d37fbd..0b5dd15 100644 --- a/gdb/testsuite/gdb.cp/disasm-func-name.exp +++ b/gdb/testsuite/gdb.cp/disasm-func-name.exp @@ -43,3 +43,26 @@ check_disassembly_header "process" "process\\(A\\*, int\\)" check_disassembly_header "A::A" "A::A\\(int\\)" check_disassembly_header "A::get_i" "A::get_i\\(\\) const" check_disassembly_header "A::set_i" "A::set_i\\(int\\)" + +# Place a breakpoint at STOP_LOC and then continue until a breakpoint +# is hit (we assume this is the breakpoint we just created. +# +# Then disassemble the current function, EXPECT should appear in the +# disassembly header as the name of the current function. +proc continue_and_check { stop_loc expected } { + gdb_breakpoint $stop_loc + gdb_continue_to_breakpoint "continue to $stop_loc" + + with_test_prefix "at $stop_loc" { + check_disassembly_header "" $expected + } +} + +# Initially we are already in main. +check_disassembly_header "" "main\\(\\)" + +# Now move forward and check the disassembly at various locations. +continue_and_check "A::A" "A::A\\(int\\)" +continue_and_check "process" "process\\(A\\*, int\\)" +continue_and_check "A::set_i" "A::set_i\\(int\\)" +continue_and_check "A::get_i" "A::get_i\\(\\) const" diff --git a/gdb/testsuite/gdb.dwarf2/short-build-id.exp b/gdb/testsuite/gdb.dwarf2/short-build-id.exp new file mode 100644 index 0000000..f40d5e4 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/short-build-id.exp @@ -0,0 +1,119 @@ +# Copyright 2024 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/>. + +# Create a file with an artificially short (1-byte) build-id, and +# check that GDB doesn't try to load debug information. If we do try +# then we end up loading from: `debug-directory/.build-id/xx/.debug` +# which isn't right. + +load_lib dwarf.exp + +# This test can only be run on targets which support DWARF-2 and use gas. +require dwarf2_support + +# No remote host testing either. +require {!is_remote host} + +standard_testfile main.c + +# Create an assembler file which encodes BUILDID as the build-id. Compile +# this along with the global SRCFILE to create a test executable. +# +# Split the debug information out from the newly created executable and place +# it into the debug file directory. +# +# Load the executable into GDB and check to see if the debug information was +# loaded or not. For this test we are expecting that the debug information +# was not loaded. The reason is that, with short values for BUILDID, GDB ends +# up looking for the debug information in weird locations. +proc run_test { buildid } { + set len [string length $buildid] + + set asm_file [standard_output_file "$::testfile.$len.S"] + Dwarf::assemble $asm_file { + declare_labels int_label int_label2 + + upvar buildid buildid + + build_id $buildid + + cu { label cu_start } { + compile_unit {{language @DW_LANG_C}} { + int_label2: base_type { + {name int} + {byte_size 4 sdata} + {encoding @DW_ATE_signed} + } + + constant { + {name the_int} + {type :$int_label2} + {const_value 99 data1} + } + } + } + + aranges {} cu_start { + arange {} 0 0 + } + } + + set execfile [standard_output_file $::testfile.$len] + + if { [build_executable_from_specs "failed to build" \ + $execfile {debug no-build-id} \ + $::srcfile debug \ + $asm_file {}] } { + return + } + + # Create the debug directory. + set debugdir [standard_output_file "debugdir.$len"] + set build_id_dir $debugdir/.build-id/$buildid + remote_exec host "mkdir -p $build_id_dir" + + # Split out the debug information. + if {[gdb_gnu_strip_debug $execfile no-debuglink]} { + unresolved "failed to split out debug information" + return + } + + # Move the debug information into the debug directory. We place the debug + # information into a file called just '.debug'. GDB should not check this + # file, but at one point GDB would check this file, even though this + # doesn't make much sense. + set execfile_debug ${execfile}.debug + remote_exec host "mv $execfile_debug $build_id_dir/.debug" + + # Start GDB, set the debug-file-directory, and try loading the file. + clean_restart + + gdb_test_no_output "set debug-file-directory $debugdir" \ + "set debug-file-directory" + + gdb_file_cmd $execfile + + gdb_assert { $::gdb_file_cmd_debug_info eq "nodebug" } \ + "no debug should be loaded" + + # For sanity, read something that was encoded in the debug + # information, this should fail. + gdb_test "print the_int" \ + "(?:No symbol table is loaded|No symbol \"the_int\" in current context).*" +} + +foreach_with_prefix buildid { a4 "" } { + run_test $buildid +} diff --git a/gdb/testsuite/gdb.python/py-failed-init.exp b/gdb/testsuite/gdb.python/py-failed-init.exp new file mode 100644 index 0000000..1e0c10d --- /dev/null +++ b/gdb/testsuite/gdb.python/py-failed-init.exp @@ -0,0 +1,31 @@ +# Copyright 2024 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/>. + +require allow_python_tests +require {!is_remote host} + +save_vars { env(PYTHONHOME) } { + setenv PYTHONHOME foo + clean_restart +} + +gdb_test "python print (1)" \ + "Python not initialized" + +gdb_test_multiple "quit" "" { + eof { + pass $gdb_test_name + } +} diff --git a/gdb/testsuite/gdb.reverse/i386-avx-reverse.c b/gdb/testsuite/gdb.reverse/i386-avx-reverse.c index edd931b..5ce363f 100644 --- a/gdb/testsuite/gdb.reverse/i386-avx-reverse.c +++ b/gdb/testsuite/gdb.reverse/i386-avx-reverse.c @@ -210,6 +210,79 @@ vzeroupper_test () return 0; /* end vzeroupper_test */ } +int +vpor_xor_test () +{ + /* start vpor_xor_test. */ + /* Using GDB, load this value onto the register, for ease of testing. + ymm0.v2_int128 = {0x0, 0x12345} + ymm1.v2_int128 = {0x1f1e1d1c1b1a1918, 0x0} + ymm2.v2_int128 = {0x0, 0xbeef} + ymm15.v2_int128 = {0x0, 0xcafeface} + this way it's easy to confirm we're undoing things correctly. */ + + asm volatile ("vpxor %ymm0, %ymm0, %ymm0"); + asm volatile ("vpxor %xmm0, %xmm1, %xmm0"); + asm volatile ("vpxor %ymm2, %ymm15, %ymm1"); + asm volatile ("vpxor %xmm2, %xmm15, %xmm2"); + asm volatile ("vpxor %ymm2, %ymm1, %ymm15"); + + asm volatile ("vpor %ymm0, %ymm0, %ymm0"); + asm volatile ("vpor %xmm0, %xmm1, %xmm0"); + asm volatile ("vpor %ymm2, %ymm15, %ymm1"); + asm volatile ("vpor %xmm2, %xmm15, %xmm2"); + asm volatile ("vpor %ymm2, %ymm1, %ymm15"); + return 0; /* end vpor_xor_test */ +} + +int +vpcmpeq_test () +{ + /* start vpcmpeq_test. */ + /* Using GDB, load these values onto registers for testing. + ymm0.v2_int128 = {0x0, 0x12345} + ymm1.v8_int32 = {0xcafe, 0xbeef, 0xff, 0x1234, 0x0, 0xff00, 0xff0000ff, 0xface0f0f} + ymm2.v8_int32 = {0xcafe0, 0xbeef, 0xff00, 0x12345678, 0x90abcdef, 0xffff00, 0xff, 0xf} + ymm15.v2_int128 = {0xcafeface, 0xcafeface} + this way it's easy to confirm we're undoing things correctly. */ + + /* Test all the vpcmpeq variants on a low register (number 0). */ + asm volatile ("vpcmpeqb %xmm1, %xmm2, %xmm0"); + asm volatile ("vpcmpeqw %xmm1, %xmm2, %xmm0"); + asm volatile ("vpcmpeqd %xmm1, %xmm2, %xmm0"); + + asm volatile ("vpcmpeqb %ymm1, %ymm2, %ymm0"); + asm volatile ("vpcmpeqw %ymm1, %ymm2, %ymm0"); + asm volatile ("vpcmpeqd %ymm1, %ymm2, %ymm0"); + + /* Test all the vpcmpeq variants on a high register (number 15). */ + asm volatile ("vpcmpeqb %xmm1, %xmm2, %xmm15"); + asm volatile ("vpcmpeqw %xmm1, %xmm2, %xmm15"); + asm volatile ("vpcmpeqd %xmm1, %xmm2, %xmm15"); + + asm volatile ("vpcmpeqb %ymm1, %ymm2, %ymm15"); + asm volatile ("vpcmpeqw %ymm1, %ymm2, %ymm15"); + asm volatile ("vpcmpeqd %ymm1, %ymm2, %ymm15"); + return 0; /* end vpcmpeq_test */ +} + +int +vpmovmskb_test () +{ + /* start vpmovmskb_test. */ + /* Using GDB, load these values onto registers for testing. + rbx = 2 + r8 = 3 + r9 = 4 + this way it's easy to confirm we're undoing things correctly. */ + asm volatile ("vpmovmskb %ymm0, %eax"); + asm volatile ("vpmovmskb %ymm0, %ebx"); + + asm volatile ("vpmovmskb %ymm0, %r8"); + asm volatile ("vpmovmskb %ymm0, %r9"); + return 0; /* end vpmovmskb_test */ +} + /* This include is used to allocate the dynamic buffer and have the pointers aligned to a 32-bit boundary, so we can test instructions that require aligned memory. */ @@ -235,5 +308,8 @@ main () vpunpck_test (); vpbroadcast_test (); vzeroupper_test (); + vpor_xor_test (); + vpcmpeq_test (); + vpmovmskb_test (); return 0; /* end of main */ } diff --git a/gdb/testsuite/gdb.reverse/i386-avx-reverse.exp b/gdb/testsuite/gdb.reverse/i386-avx-reverse.exp index 7ed1293..6d89900 100644 --- a/gdb/testsuite/gdb.reverse/i386-avx-reverse.exp +++ b/gdb/testsuite/gdb.reverse/i386-avx-reverse.exp @@ -64,6 +64,19 @@ proc test_one_register {insn register value {prefix ""}} { } # Shorthand to test reversing through one instruction and +# testing if a general purpose register has the expected value. +# Prefix, if included, should end with a colon and space. + +proc test_one_general_register {insn register value {prefix ""}} { + gdb_test "reverse-step" "$insn.*" \ + "${prefix}reverse-step from $insn to test register $register" + + gdb_test "info register $register" \ + "$register\\s+$value.*" \ + "${prefix}verify $register before $insn" +} + +# Shorthand to test reversing through one instruction and # testing if a variable has the expected value. # Prefix, if used, should end with a colon and space. @@ -327,9 +340,106 @@ if {[record_full_function "vzeroupper"] == true} { "Register ymm15h changed: 3405707982" \ "Register rip changed: \[^\r\n\]+" ] \ "verify vzeroupper recording" + + gdb_test "record stop" "Process record is stopped.*" \ + "delete history for vzeroupper_test" } else { untested "couldn't run vzeroupper tests" } gdb_test "finish" "Run till exit from.*vzeroupper_test.*" \ "leaving vzeroupper" + +# Preparation and testing vpxor instructions. +gdb_test_no_output "set \$ymm0.v2_int128 = {0x0, 0x12345}" "set ymm0 for vpor_xor" +gdb_test_no_output "set \$ymm1.v2_int128 = {0x1f1e1d1c1b1a1918, 0x0}" \ + "set ymm1 for vpor_xor" +gdb_test_no_output "set \$ymm2.v2_int128 = {0x0, 0xbeef}" "set ymm2 for vpor_xor" +gdb_test_no_output "set \$ymm15.v2_int128 = {0x0, 0xcafeface}" "set ymm15 for vpor_xor" + +if {[record_full_function "vpor_xor"] == true} { + test_one_register "vpor" "ymm15" "0x0, 0xcafe4421" + test_one_register "vpor" "ymm2" "0x0, 0x0" + test_one_register "vpor" "ymm1" "0x0, 0xcafe4421" + test_one_register "vpor" "ymm0" "0x1f1e1d1c1b1a1918, 0x0" "first: " + test_one_register "vpor" "ymm0" "0x1f1e1d1c1b1a1918, 0x0" "second: " + + test_one_register "vpxor" "ymm15" "0x0, 0xcafeface" + test_one_register "vpxor" "ymm2" "0x0, 0xbeef" + test_one_register "vpxor" "ymm1" "0x1f1e1d1c1b1a1918, 0x0" + test_one_register "vpxor" "ymm0" "0x0, 0x0" "first: " + test_one_register "vpxor" "ymm0" "0x0, 0x12345" "second: " + + gdb_test "record stop" "Process record is stopped.*" \ + "delete history for vpor_xor_test" +} else { + untested "couldn't run vpor_xor tests" +} +gdb_test "finish" "Run till exit from.*vpor_xor_test.*" \ + "leaving vpor_xor" + +# Preparation and testing vpcmpeq instructions. +gdb_test_no_output "set \$ymm0.v2_int128 = {0x12345, 0x12345}" \ + "set ymm0 for vpcmpeq" +gdb_test_no_output \ + "set \$ymm1.v8_int32 = {0xcafe, 0xbeef, 0xff, 0x1234, 0x0, 0xff00, 0xff0000ff, 0xface0f0f}" \ + "set ymm1 for vpcmpeq" +gdb_test_no_output \ + "set \$ymm2.v8_int32 = {0xcafe0, 0xbeef, 0xff00, 0x12345678, 0x90abcdef, 0xffff00, 0xff, 0xf}" \ + "set ymm2 for vpcmpeq" +gdb_test_no_output "set \$ymm15.v2_int128 = {0xcafeface, 0xcafeface}" \ + "set ymm15 for vpcmpeq" + +if {[record_full_function "vpcmpeq"] == true} { + test_one_register "vpcmpeqd" "ymm15" \ + "0xffff0000ffffffff00000000, 0xffff0000ffff00000000" "ymm: " + test_one_register "vpcmpeqw" "ymm15" \ + "0xffff0000ffffffffff000000, 0xff00ffffffff00ffff00000000" "ymm: " + test_one_register "vpcmpeqb" "ymm15" \ + "0xffffffff00000000, 0x0" "ymm: " + test_one_register "vpcmpeqd" "ymm15" \ + "0xffff0000ffffffff00000000, 0x0" "xmm: " + test_one_register "vpcmpeqw" "ymm15" \ + "0xffff0000ffffffffff000000, 0x0" "xmm: " + test_one_register "vpcmpeqb" "ymm15" "0xcafeface, 0xcafeface" "xmm: " + + test_one_register "vpcmpeqd" "ymm0" \ + "0xffff0000ffffffff00000000, 0xffff0000ffff00000000" "ymm: " + test_one_register "vpcmpeqw" "ymm0" \ + "0xffff0000ffffffffff000000, 0xff00ffffffff00ffff00000000" "ymm: " + test_one_register "vpcmpeqb" "ymm0" \ + "0xffffffff00000000, 0x0" "ymm: " + test_one_register "vpcmpeqd" "ymm0" \ + "0xffff0000ffffffff00000000, 0x0" "xmm: " + test_one_register "vpcmpeqw" "ymm0" \ + "0xffff0000ffffffffff000000, 0x0" "xmm: " + test_one_register "vpcmpeqb" "ymm0" "0x12345, 0x12345" "xmm: " + + gdb_test "record stop" "Process record is stopped.*" \ + "delete history for vpcmpeq_test" +} else { + untested "couldn't run vpcmpeq tests" +} +gdb_test "finish" "Run till exit from.*vpcmpeq_test.*" \ + "leaving vpcmpeq" + +# Preparation and testing vpcmpeq instructions. +gdb_test_no_output "set \$rbx = 2" "set rbx for vpmovmskb" +gdb_test_no_output "set \$r8 = 3" "set r8 for vpmovmskb" +gdb_test_no_output "set \$r9 = 4" "set ymm15 for vpmovmskb" + +if {[record_full_function "vpmovmskb"] == true} { + test_one_general_register "vpmovmskb" "r9" "0x4" + test_one_general_register "vpmovmskb" "r8" "0x3" + test_one_general_register "vpmovmskb" "rbx" "0x2" + # Because of the infrastructure of the test, we can't set rax. + # However, it seems to always be set to 0, so this should be fine. + test_one_general_register "vpmovmskb" "rax" "0x0" + + gdb_test "record stop" "Process record is stopped.*" \ + "delete history for vpmovmskb_test" +} else { + untested "couldn't run vpmovmskb tests" +} +gdb_test "finish" "Run till exit from.*vpmovmskb_test.*" \ + "leaving vpmovmskb" diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp index 1002c75..f634897 100644 --- a/gdb/testsuite/lib/dwarf.exp +++ b/gdb/testsuite/lib/dwarf.exp @@ -3008,25 +3008,32 @@ namespace eval Dwarf { proc _note {type name hexdata} { set namelen [expr [string length $name] + 1] + set datalen [expr [string length $hexdata] / 2] # Name size. _op .4byte $namelen # Data size. - _op .4byte [expr [string length $hexdata] / 2] + _op .4byte $datalen # Type. _op .4byte $type # The name. _op .ascii [_quote $name] - # Alignment. + # Alignment (to 4-byte boundary). set align 2 set total [expr {($namelen + (1 << $align) - 1) & -(1 << $align)}] for {set i $namelen} {$i < $total} {incr i} { - _op .byte 0 + _op .byte 0 padding } # The data. foreach {a b} [split $hexdata {}] { _op .byte 0x$a$b } + # Alignment (to 4-byte boundary). + set align 2 + set total [expr {($datalen + (1 << $align) - 1) & -(1 << $align)}] + for {set i $datalen} {$i < $total} {incr i} { + _op .byte 0 padding + } } # Emit a note section holding the given build-id. diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp index 5d4d9db..2b27d7f 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp @@ -2238,8 +2238,10 @@ proc gdb_reinitialize_dir { subdir } { } send_gdb "dir\n" gdb_expect 60 { - -re "Reinitialize source path to empty.*y or n. " { - send_gdb "y\n" answer + -re "Reinitialize source path to empty.*y or n.(\\\s.answered Y; input not from terminal.)?" { + if {![info exists expect_out(1,string)]} { + send_gdb "y\n" answer + } gdb_expect 60 { -re "Source directories searched.*$gdb_prompt $" { send_gdb "dir $subdir\n" diff --git a/gdb/utils.c b/gdb/utils.c index 2932efc..6f2055e 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -19,6 +19,7 @@ #include <ctype.h> #include "gdbsupport/gdb_wait.h" +#include "gdbsupport/scoped_signal_handler.h" #include "event-top.h" #include "gdbthread.h" #include "fnmatch.h" @@ -81,6 +82,7 @@ #include "pager.h" #include "run-on-main-thread.h" #include "gdbsupport/gdb_tilde_expand.h" +#include "gdbsupport/eintr.h" void (*deprecated_error_begin_hook) (void); @@ -3467,35 +3469,19 @@ wait_to_die_with_timeout (pid_t pid, int *status, int timeout) if (timeout > 0) { #ifdef SIGALRM -#if defined (HAVE_SIGACTION) && defined (SA_RESTART) - struct sigaction sa, old_sa; - - sa.sa_handler = sigalrm_handler; - sigemptyset (&sa.sa_mask); - sa.sa_flags = 0; - sigaction (SIGALRM, &sa, &old_sa); -#else - sighandler_t ofunc; - - ofunc = signal (SIGALRM, sigalrm_handler); -#endif + scoped_signal_handler<SIGALRM> alarm_restore (sigalrm_handler); alarm (timeout); #endif - waitpid_result = waitpid (pid, status, 0); + waitpid_result = gdb::waitpid (pid, status, 0); #ifdef SIGALRM alarm (0); -#if defined (HAVE_SIGACTION) && defined (SA_RESTART) - sigaction (SIGALRM, &old_sa, NULL); -#else - signal (SIGALRM, ofunc); -#endif #endif } else - waitpid_result = waitpid (pid, status, WNOHANG); + waitpid_result = gdb::waitpid (pid, status, WNOHANG); if (waitpid_result == pid) return pid; diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c index 37c1f46..abacafe 100644 --- a/gdb/windows-nat.c +++ b/gdb/windows-nat.c @@ -730,7 +730,7 @@ windows_nat_target::fetch_registers (struct regcache *regcache, int r) #ifdef __x86_64__ if (windows_process.wow64_process) { - th->wow64_context.ContextFlags = CONTEXT_DEBUGGER_DR; + th->wow64_context.ContextFlags = WOW64_CONTEXT_ALL; CHECK (Wow64GetThreadContext (th->h, &th->wow64_context)); /* Copy dr values from that thread. But only if there were not modified since last stop. @@ -1290,7 +1290,7 @@ windows_nat_target::windows_continue (DWORD continue_status, int id, { if (th->debug_registers_changed) { - th->wow64_context.ContextFlags |= CONTEXT_DEBUG_REGISTERS; + th->wow64_context.ContextFlags |= WOW64_CONTEXT_DEBUG_REGISTERS; th->wow64_context.Dr0 = windows_process.dr[0]; th->wow64_context.Dr1 = windows_process.dr[1]; th->wow64_context.Dr2 = windows_process.dr[2]; diff --git a/gdbserver/netbsd-low.cc b/gdbserver/netbsd-low.cc index 4e459e6..04e1035 100644 --- a/gdbserver/netbsd-low.cc +++ b/gdbserver/netbsd-low.cc @@ -222,7 +222,7 @@ netbsd_waitpid (ptid_t ptid, struct target_waitstatus *ourstatus, int options = (target_options & TARGET_WNOHANG) ? WNOHANG : 0; pid_t pid - = gdb::handle_eintr (-1, ::waitpid, ptid.pid (), &status, options); + = gdb::waitpid (ptid.pid (), &status, options); if (pid == -1) perror_with_name (_("Child process unexpectedly missing")); @@ -432,7 +432,7 @@ netbsd_process_target::kill (process_info *process) return -1; int status; - if (gdb::handle_eintr (-1, ::waitpid, pid, &status, 0) == -1) + if (gdb::waitpid (pid, &status, 0) == -1) return -1; mourn (process); return 0; @@ -1123,15 +1123,15 @@ netbsd_qxfer_libraries_svr4 (const pid_t pid, const char *annex, static bool elf_64_file_p (const char *file) { - int fd = gdb::handle_eintr (-1, ::open, file, O_RDONLY); + int fd = gdb::open (file, O_RDONLY); if (fd < 0) perror_with_name (("open")); Elf64_Ehdr header; - ssize_t ret = gdb::handle_eintr (-1, ::read, fd, &header, sizeof (header)); + ssize_t ret = gdb::read (fd, &header, sizeof (header)); if (ret == -1) perror_with_name (("read")); - gdb::handle_eintr (-1, ::close, fd); + gdb::close (fd); if (ret != sizeof (header)) error ("Cannot read ELF file header: %s", file); diff --git a/gdbserver/win32-i386-low.cc b/gdbserver/win32-i386-low.cc index 688e012..7898ac1 100644 --- a/gdbserver/win32-i386-low.cc +++ b/gdbserver/win32-i386-low.cc @@ -250,14 +250,17 @@ i386_get_thread_context (windows_thread_info *th) /* Requesting the CONTEXT_EXTENDED_REGISTERS register set fails if the system doesn't support extended registers. */ static DWORD extended_registers = CONTEXT_EXTENDED_REGISTERS; +#ifdef __x86_64__ + static DWORD wow64_extended_registers = WOW64_CONTEXT_EXTENDED_REGISTERS; +#endif again: #ifdef __x86_64__ if (windows_process.wow64_process) - th->wow64_context.ContextFlags = (CONTEXT_FULL - | CONTEXT_FLOATING_POINT - | CONTEXT_DEBUG_REGISTERS - | extended_registers); + th->wow64_context.ContextFlags = (WOW64_CONTEXT_FULL + | WOW64_CONTEXT_FLOATING_POINT + | WOW64_CONTEXT_DEBUG_REGISTERS + | wow64_extended_registers); else #endif th->context.ContextFlags = (CONTEXT_FULL @@ -276,10 +279,23 @@ i386_get_thread_context (windows_thread_info *th) { DWORD e = GetLastError (); - if (extended_registers && e == ERROR_INVALID_PARAMETER) +#ifdef __x86_64__ + if (windows_process.wow64_process) + { + if (wow64_extended_registers && e == ERROR_INVALID_PARAMETER) + { + wow64_extended_registers = 0; + goto again; + } + } + else +#endif { - extended_registers = 0; - goto again; + if (extended_registers && e == ERROR_INVALID_PARAMETER) + { + extended_registers = 0; + goto again; + } } error ("GetThreadContext failure %ld\n", (long) e); diff --git a/gdbsupport/eintr.h b/gdbsupport/eintr.h index e440f93..3980e3f 100644 --- a/gdbsupport/eintr.h +++ b/gdbsupport/eintr.h @@ -21,6 +21,11 @@ #define GDBSUPPORT_EINTR_H #include <cerrno> +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> namespace gdb { @@ -66,6 +71,47 @@ handle_eintr (ErrorValType errval, const Fun &f, const Args &... args) return ret; } +inline pid_t +waitpid (pid_t pid, int *wstatus, int options) +{ + return gdb::handle_eintr (-1, ::waitpid, pid, wstatus, options); +} + +inline int +open (const char *pathname, int flags) +{ + return gdb::handle_eintr (-1, ::open, pathname, flags); +} + +inline pid_t +wait (int *wstatus) +{ + return gdb::handle_eintr (-1, ::wait, wstatus); +} + +inline int +close (int fd) +{ + return gdb::handle_eintr (-1, ::close, fd); +} + +inline ssize_t +read (int fd, void *buf, size_t count) +{ + return gdb::handle_eintr (-1, ::read, fd, buf, count); +} + +template<typename... Args> int fcntl (int fd, int op, Args... args) +{ + return gdb::handle_eintr (-1, ::fcntl, fd, op, args...); +} + +inline ssize_t +write (int fd, const void *buf, size_t count) +{ + return gdb::handle_eintr (-1, ::write, fd, buf, count); +} + } /* namespace gdb */ #endif /* GDBSUPPORT_EINTR_H */ diff --git a/gdbsupport/event-pipe.cc b/gdbsupport/event-pipe.cc index af6c943..120edd1 100644 --- a/gdbsupport/event-pipe.cc +++ b/gdbsupport/event-pipe.cc @@ -19,6 +19,7 @@ #include "gdbsupport/event-pipe.h" #include "gdbsupport/filestuff.h" +#include "gdbsupport/eintr.h" #include <errno.h> #include <fcntl.h> @@ -41,8 +42,8 @@ event_pipe::open_pipe () if (gdb_pipe_cloexec (m_fds) == -1) return false; - if (fcntl (m_fds[0], F_SETFL, O_NONBLOCK) == -1 - || fcntl (m_fds[1], F_SETFL, O_NONBLOCK) == -1) + if (gdb::fcntl (m_fds[0], F_SETFL, O_NONBLOCK) == -1 + || gdb::fcntl (m_fds[1], F_SETFL, O_NONBLOCK) == -1) { close_pipe (); return false; @@ -56,8 +57,8 @@ event_pipe::open_pipe () void event_pipe::close_pipe () { - ::close (m_fds[0]); - ::close (m_fds[1]); + gdb::close (m_fds[0]); + gdb::close (m_fds[1]); m_fds[0] = -1; m_fds[1] = -1; } @@ -72,9 +73,9 @@ event_pipe::flush () do { - ret = read (m_fds[0], &buf, 1); + ret = gdb::read (m_fds[0], &buf, 1); } - while (ret >= 0 || (ret == -1 && errno == EINTR)); + while (ret >= 0); } /* See event-pipe.h. */ @@ -82,18 +83,12 @@ event_pipe::flush () void event_pipe::mark () { - int ret; - /* It doesn't really matter what the pipe contains, as long we end up with something in it. Might as well flush the previous left-overs. */ flush (); - do - { - ret = write (m_fds[1], "+", 1); - } - while (ret == -1 && errno == EINTR); + gdb::write (m_fds[1], "+", 1); /* Ignore EAGAIN. If the pipe is full, the event loop will already be awakened anyway. */ diff --git a/gdbsupport/scoped_signal_handler.h b/gdbsupport/scoped_signal_handler.h new file mode 100644 index 0000000..3dffd79 --- /dev/null +++ b/gdbsupport/scoped_signal_handler.h @@ -0,0 +1,73 @@ +/* RAII class to install a separate handler for a given signal + + Copyright (C) 2024 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 SCOPED_SIGNAL_HANDLER_H +#define SCOPED_SIGNAL_HANDLER_H + +#include <signal.h> + +#undef HAVE_SIGACTION + +/* RAII class to set a signal handler for a scope, that will take care of + unsetting the handler when the scope is left. + This class will try to use sigaction whenever available, following the + recommendation on the man page for signal, and only fallback to signal + if necessary. */ +template <int SIG> +class scoped_signal_handler +{ +public: + scoped_signal_handler (sighandler_t handler) + { +#if defined (HAVE_SIGACTION) + struct sigaction act; + + act.sa_handler = handler; + sigemptyset (&act.sa_mask); + act.sa_flags = 0; + sigaction (SIG, &act, &m_prev_handler); +#else + /* The return of the function call is the previous signal handler, or + SIG_ERR if the function doesn't succeed. */ + m_prev_handler = signal (SIG, handler); + /* According to the GNU libc manual, the only way signal fails is if + the signum given is invalid, so we should be safe to assert. */ + gdb_assert (m_prev_handler != SIG_ERR); +#endif + } + + ~scoped_signal_handler () + { +#if defined (HAVE_SIGACTION) + sigaction (SIG, &m_prev_handler, nullptr); +#else + signal (SIG, m_prev_handler); +#endif + } + + DISABLE_COPY_AND_ASSIGN (scoped_signal_handler); +private: +#if defined (HAVE_SIGACTION) + struct sigaction m_prev_handler; +#else + sighandler_t m_prev_handler; +#endif +}; + +#endif /* SCOPED_SIGNAL_HANDLER_H */ diff --git a/gprofng/common/cpuid.c b/gprofng/common/cpuid.c index 891d547..b4caef5 100644 --- a/gprofng/common/cpuid.c +++ b/gprofng/common/cpuid.c @@ -21,7 +21,9 @@ #if defined(__i386__) || defined(__x86_64) #include <cpuid.h> /* GCC-provided */ #elif defined(__aarch64__) +#if !defined(ATTRIBUTE_UNUSED) #define ATTRIBUTE_UNUSED __attribute__((unused)) +#endif static inline uint_t __attribute_const__ __get_cpuid (unsigned int op ATTRIBUTE_UNUSED, unsigned int *eax, diff --git a/gprofng/libcollector/dispatcher.c b/gprofng/libcollector/dispatcher.c index 4eda18e..6f0364c 100644 --- a/gprofng/libcollector/dispatcher.c +++ b/gprofng/libcollector/dispatcher.c @@ -1280,4 +1280,4 @@ __collector_ext_clone_pthread (int (*fn)(void *), void *child_stack, int flags, // weak symbols: int sigprocmask (int, const sigset_t*, sigset_t*) __attribute__ ((weak, alias ("__collector_sigprocmask"))); int thr_sigsetmask (int, const sigset_t*, sigset_t*) __attribute__ ((weak, alias ("__collector_thr_sigsetmask"))); -int setitimer () __attribute__ ((weak, alias ("_setitimer"))); +__typeof(setitimer) setitimer __attribute__ ((weak, alias ("_setitimer"))); diff --git a/gprofng/libcollector/libcol_util.c b/gprofng/libcollector/libcol_util.c index a73488e..77dc886 100644 --- a/gprofng/libcollector/libcol_util.c +++ b/gprofng/libcollector/libcol_util.c @@ -1427,15 +1427,6 @@ __collector_util_init () err = COL_ERROR_UTIL_INIT; } - ptr = dlsym (libc, "sysinfo"); - if (ptr) - __collector_util_funcs.sysinfo = (long (*)())ptr; - else - { - CALL_UTIL (fprintf)(stderr, "collector_util_init COL_ERROR_UTIL_INIT sysinfo: %s\n", dlerror ()); - err = COL_ERROR_UTIL_INIT; - } - ptr = dlsym (libc, "clearenv"); if (ptr) __collector_util_funcs.clearenv = (int(*)())ptr; diff --git a/gprofng/libcollector/linetrace.c b/gprofng/libcollector/linetrace.c index 66844bc..c81ae1a 100644 --- a/gprofng/libcollector/linetrace.c +++ b/gprofng/libcollector/linetrace.c @@ -1527,7 +1527,7 @@ DCL_FUNC_VER (DCL_POSIX_SPAWNP, posix_spawnp_2_2, posix_spawnp@GLIBC_2.2) DCL_POSIX_SPAWNP (posix_spawnp) /*------------------------------------------------------------- system */ -int system () __attribute__ ((weak, alias ("__collector_system"))); +int system (const char *cmd) __attribute__ ((weak, alias ("__collector_system"))); int __collector_system (const char *cmd) @@ -1582,10 +1582,10 @@ DCL_FUNC_VER (DCL_POPEN, popen_2_0, popen@GLIBC_2.0) DCL_POPEN (popen) /*------------------------------------------------------------- grantpt */ -int grantpt () __attribute__ ((weak, alias ("__collector_grantpt"))); +int grantpt (int fildes) __attribute__ ((weak, alias ("__collector_grantpt"))); int -__collector_grantpt (const int fildes) +__collector_grantpt (int fildes) { if (NULL_PTR (grantpt)) init_lineage_intf (); @@ -1607,10 +1607,10 @@ __collector_grantpt (const int fildes) } /*------------------------------------------------------------- ptsname */ -char *ptsname () __attribute__ ((weak, alias ("__collector_ptsname"))); +char *ptsname (int fildes) __attribute__ ((weak, alias ("__collector_ptsname"))); char * -__collector_ptsname (const int fildes) +__collector_ptsname (int fildes) { if (NULL_PTR (ptsname)) init_lineage_intf (); diff --git a/gprofng/src/collector_module.h b/gprofng/src/collector_module.h index fd888cd..6640f12 100644 --- a/gprofng/src/collector_module.h +++ b/gprofng/src/collector_module.h @@ -107,7 +107,6 @@ typedef struct CollectorUtilFuncs int (*symlink)(const char *s1, const char *s2); int (*syscall)(int number, ...); long (*sysconf)(int name); - long (*sysinfo)(int command, char *buf, long count); time_t (*time)(time_t *tloc); int (*unsetenv)(const char *name); int (*vsnprintf)(char *str, size_t size, const char *format, ...); diff --git a/gprofng/testsuite/gprofng.display/mttest/mttest.c b/gprofng/testsuite/gprofng.display/mttest/mttest.c index e0835c8..3db5b8d 100644 --- a/gprofng/testsuite/gprofng.display/mttest/mttest.c +++ b/gprofng/testsuite/gprofng.display/mttest/mttest.c @@ -171,7 +171,7 @@ void computeJ (workStruct_t *x); void computeK (workStruct_t *x); void addone (workCtr_t *x); void init_arrays (int strat); -void dump_arrays (); +void dump_arrays (hrtime_t real, hrtime_t cpu, int case_index); void *do_work (void *v); void thread_work (); void nothreads (Workblk *array, struct scripttab *k); diff --git a/gprofng/testsuite/gprofng.display/synprog/endcases.c b/gprofng/testsuite/gprofng.display/synprog/endcases.c index a6a1389..6f1c83b 100644 --- a/gprofng/testsuite/gprofng.display/synprog/endcases.c +++ b/gprofng/testsuite/gprofng.display/synprog/endcases.c @@ -40,8 +40,8 @@ static void s_inline_code (int); void ext_inline_code (int); #ifndef NO_INLINE -void xinline_code () __attribute__ ((always_inline)); -void s_inline_code () __attribute__ ((always_inline)); +void xinline_code (int) __attribute__ ((always_inline)); +void s_inline_code (int) __attribute__ ((always_inline)); #endif #include "inc_inline.h" diff --git a/gprofng/testsuite/gprofng.display/synprog/inc_inline.h b/gprofng/testsuite/gprofng.display/synprog/inc_inline.h index da42563..6600eac 100644 --- a/gprofng/testsuite/gprofng.display/synprog/inc_inline.h +++ b/gprofng/testsuite/gprofng.display/synprog/inc_inline.h @@ -19,7 +19,7 @@ MA 02110-1301, USA. */ #ifndef NO_INLINE -void ext_inline_code() __attribute__ ((always_inline)); +void ext_inline_code(int) __attribute__ ((always_inline)); #endif void diff --git a/gprofng/testsuite/gprofng.display/synprog/synprog.c b/gprofng/testsuite/gprofng.display/synprog/synprog.c index cf1bc5b..05920dc 100644 --- a/gprofng/testsuite/gprofng.display/synprog/synprog.c +++ b/gprofng/testsuite/gprofng.display/synprog/synprog.c @@ -528,14 +528,14 @@ reapchildren () int doabort (int k) { - char *nullptr = NULL; + char *p = NULL; char c; /* Log the event */ wlog ("start of doabort", NULL); /* and dereference a NULL */ - c = *nullptr; + c = *p; /* this should never be reached */ return (int) c; diff --git a/include/opcode/riscv-opc.h b/include/opcode/riscv-opc.h index 8165686..253148b 100644 --- a/include/opcode/riscv-opc.h +++ b/include/opcode/riscv-opc.h @@ -3745,6 +3745,28 @@ /* Vendor-specific (SiFive) cease instruction. */ #define MATCH_SF_CEASE 0x30500073 #define MASK_SF_CEASE 0xffffffff +/* SiFive custom int8 matrix-multiply instruction. */ +#define MATCH_SFVQMACCU4X8X4 0xf200205b +#define MASK_SFVQMACCU4X8X4 0xfe00707f +#define MATCH_SFVQMACC4X8X4 0xf600205b +#define MASK_SFVQMACC4X8X4 0xfe00707f +#define MATCH_SFVQMACCUS4X8X4 0xfa00205b +#define MASK_SFVQMACCUS4X8X4 0xfe00707f +#define MATCH_SFVQMACCSU4X8X4 0xfe00205b +#define MASK_SFVQMACCSU4X8X4 0xfe00707f +#define MATCH_SFVQMACCU2X8X2 0xb200205b +#define MASK_SFVQMACCU2X8X2 0xfe00707f +#define MATCH_SFVQMACC2X8X2 0xb600205b +#define MASK_SFVQMACC2X8X2 0xfe00707f +#define MATCH_SFVQMACCUS2X8X2 0xba00205b +#define MASK_SFVQMACCUS2X8X2 0xfe00707f +#define MATCH_SFVQMACCSU2X8X2 0xbe00205b +#define MASK_SFVQMACCSU2X8X2 0xfe00707f +/* FP32-to-int8 Ranged Clip Instructions (Xsfvfnrclipxfqf). */ +#define MATCH_SFVFNRCLIPXUFQF 0x8a00505b +#define MASK_SFVFNRCLIPXUFQF 0xfe00707f +#define MATCH_SFVFNRCLIPXFQF 0x8e00505b +#define MASK_SFVFNRCLIPXFQF 0xfe00707f /* Unprivileged Counter/Timers CSR addresses. */ #define CSR_CYCLE 0xc00 #define CSR_TIME 0xc01 diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h index 5e5131e..fedfdd2 100644 --- a/include/opcode/riscv.h +++ b/include/opcode/riscv.h @@ -554,6 +554,9 @@ enum riscv_insn_class INSN_CLASS_XVENTANACONDOPS, INSN_CLASS_XSFVCP, INSN_CLASS_XSFCEASE, + INSN_CLASS_XSFVQMACCQOQ, + INSN_CLASS_XSFVQMACCDOD, + INSN_CLASS_XSFVFNRCLIPXFQF, }; /* This structure holds information for a particular instruction. */ diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em index 869ffd3..52f59b8 100644 --- a/ld/emultempl/pe.em +++ b/ld/emultempl/pe.em @@ -1747,13 +1747,28 @@ gld${EMULATION_NAME}_after_open (void) /* Microsoft import libraries may contain archive members for one or more DLLs, together with static object files. - Inspect all members that are named *.dll - check whether - they contain .idata sections. Do the renaming of all - archive members that seem to be Microsoft style import - objects. */ + The head and sentinels are regular COFF object files, + while the thunks are special ILF files that get synthesized + by bfd into COFF object files. + + As Microsoft import libraries can be for a module with + almost any file name (*.dll, *.exe, etc), we can't easily + know which archive members to inspect. + + Inspect all members, except ones named *.o or *.obj (which + is the case both for regular static libraries or for GNU + style import libraries). Archive members with file names other + than *.o or *.obj, that do contain .idata sections, are + considered to be Microsoft style import objects, and are + renamed accordingly. + + If this heuristic is wrong and we apply this on archive members + that already have unique names, it shouldn't make any difference + as we only append a suffix on the names. */ pnt = strrchr (bfd_get_filename (is->the_bfd), '.'); - if (pnt != NULL && (fileext_cmp (pnt + 1, "dll") == 0)) + if (pnt != NULL && (fileext_cmp (pnt + 1, "o") != 0 && + fileext_cmp (pnt + 1, "obj") != 0)) { int idata2 = 0, reloc_count = 0, idata = 0; asection *sec; @@ -1768,8 +1783,8 @@ gld${EMULATION_NAME}_after_open (void) reloc_count += sec->reloc_count; } - /* An archive member named .dll, but not having any .idata - sections - apparently not a Microsoft import object + /* An archive member not named .o or .obj, but not having any + .idata sections - apparently not a Microsoft import object after all: Skip renaming it. */ if (!idata) continue; diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em index c225d05..a07403b 100644 --- a/ld/emultempl/pep.em +++ b/ld/emultempl/pep.em @@ -1730,13 +1730,28 @@ gld${EMULATION_NAME}_after_open (void) /* Microsoft import libraries may contain archive members for one or more DLLs, together with static object files. - Inspect all members that are named *.dll - check whether - they contain .idata sections. Do the renaming of all - archive members that seem to be Microsoft style import - objects. */ + The head and sentinels are regular COFF object files, + while the thunks are special ILF files that get synthesized + by bfd into COFF object files. + + As Microsoft import libraries can be for a module with + almost any file name (*.dll, *.exe, etc), we can't easily + know which archive members to inspect. + + Inspect all members, except ones named *.o or *.obj (which + is the case both for regular static libraries or for GNU + style import libraries). Archive members with file names other + than *.o or *.obj, that do contain .idata sections, are + considered to be Microsoft style import objects, and are + renamed accordingly. + + If this heuristic is wrong and we apply this on archive members + that already have unique names, it shouldn't make any difference + as we only append a suffix on the names. */ pnt = strrchr (bfd_get_filename (is->the_bfd), '.'); - if (pnt != NULL && (fileext_cmp (pnt + 1, "dll") == 0)) + if (pnt != NULL && (fileext_cmp (pnt + 1, "o") != 0 && + fileext_cmp (pnt + 1, "obj") != 0)) { int idata2 = 0, reloc_count = 0, idata = 0; asection *sec; @@ -1751,8 +1766,8 @@ gld${EMULATION_NAME}_after_open (void) reloc_count += sec->reloc_count; } - /* An archive member named .dll, but not having any .idata - sections - apparently not a Microsoft import object + /* An archive member not named .o or .obj, but not having any + .idata sections - apparently not a Microsoft import object after all: Skip renaming it. */ if (!idata) continue; diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index 949fec6..83e9120 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,44 @@ +2024-11-19 Evgeny Karpov <evgeny.karpov@microsoft.com> + + * simple-object-coff.c: Add aarch64. + +2024-11-16 Andrew Pinski <quic_apinski@quicinc.com> + + * testsuite/test-demangle.c (get_line): Change K&R style + definition into ANSI C90 definitions. + (fail): Likewise. + (main): Likewise. + +2024-10-31 Mark Wielaard <mark@klomp.org> + + * cplus-dem.c: Change preceeded to preceded. + +2024-10-10 Simon Martin <simon@nasilyan.com> + + * cp-demangle.c (d_dump): Fix compilation when CP_DEMANGLE_DEBUG + is defined. + +2024-09-07 Jakub Jelinek <jakub@redhat.com> + + PR lto/116614 + * simple-object-elf.c (SHN_COMMON): Align comment with neighbouring + comments. + (SHN_HIRESERVE): Use uppercase hex digits instead of lowercase for + consistency. + (simple_object_elf_find_sections): Formatting fixes. + (simple_object_elf_fetch_attributes): Likewise. + (simple_object_elf_attributes_merge): Likewise. + (simple_object_elf_start_write): Likewise. + (simple_object_elf_write_ehdr): Likewise. + (simple_object_elf_write_shdr): Likewise. + (simple_object_elf_write_to_file): Likewise. + (simple_object_elf_copy_lto_debug_section): Likewise. Don't fail for + new_i - 1 >= SHN_LORESERVE, instead arrange in that case to copy + over .symtab_shndx sections, though emit those last and compute their + section content when processing associated .symtab sections. Handle + simple_object_internal_read failure even in the .symtab_shndx reading + case. + 2024-08-05 Andrew Burgess <aburgess@redhat.com> * argv.c (only_whitespace): Delete. diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index fc2cf64..5b1bd5d 100644 --- a/libiberty/cp-demangle.c +++ b/libiberty/cp-demangle.c @@ -655,9 +655,9 @@ d_dump (struct demangle_component *dc, int indent) return; case DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE: { - char suffix[2] = { dc->u.s_extended_builtin.type->suffix, 0 }; + char suffix[2] = { dc->u.s_extended_builtin.suffix, 0 }; printf ("builtin type %s%d%s\n", dc->u.s_extended_builtin.type->name, - dc->u.s_extended_builtin.type->arg, suffix); + dc->u.s_extended_builtin.arg, suffix); } return; case DEMANGLE_COMPONENT_OPERATOR: diff --git a/libiberty/cplus-dem.c b/libiberty/cplus-dem.c index ee9e84f..e67ae93 100644 --- a/libiberty/cplus-dem.c +++ b/libiberty/cplus-dem.c @@ -215,7 +215,7 @@ ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED) goto unknown; /* Most of the demangling will trivially remove chars. Operator names - may add one char but because they are always preceeded by '__' which is + may add one char but because they are always preceded by '__' which is replaced by '.', they eventually never expand the size. A few special names such as '___elabs' add a few chars (at most 7), but they occur only once. */ diff --git a/libiberty/simple-object-coff.c b/libiberty/simple-object-coff.c index e748205..fd3c310 100644 --- a/libiberty/simple-object-coff.c +++ b/libiberty/simple-object-coff.c @@ -219,7 +219,9 @@ static const struct coff_magic_struct coff_magic[] = /* i386. */ { 0x14c, 0, F_EXEC | IMAGE_FILE_SYSTEM | IMAGE_FILE_DLL }, /* x86_64. */ - { 0x8664, 0, F_EXEC | IMAGE_FILE_SYSTEM | IMAGE_FILE_DLL } + { 0x8664, 0, F_EXEC | IMAGE_FILE_SYSTEM | IMAGE_FILE_DLL }, + /* AArch64. */ + { 0xaa64, 0, F_EXEC | IMAGE_FILE_SYSTEM | IMAGE_FILE_DLL } }; /* See if we have a COFF file. */ diff --git a/libiberty/simple-object-elf.c b/libiberty/simple-object-elf.c index c09c216..5e95297 100644 --- a/libiberty/simple-object-elf.c +++ b/libiberty/simple-object-elf.c @@ -128,9 +128,9 @@ typedef struct { #define SHN_UNDEF 0 /* Undefined section */ #define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */ -#define SHN_COMMON 0xFFF2 /* Associated symbol is in common */ +#define SHN_COMMON 0xFFF2 /* Associated symbol is in common */ #define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */ -#define SHN_HIRESERVE 0xffff /* End of reserved indices */ +#define SHN_HIRESERVE 0xFFFF /* End of reserved indices */ /* 32-bit ELF program header. */ @@ -569,8 +569,8 @@ simple_object_elf_find_sections (simple_object_read *sobj, void *data, int *err) { - struct simple_object_elf_read *eor = - (struct simple_object_elf_read *) sobj->data; + struct simple_object_elf_read *eor + = (struct simple_object_elf_read *) sobj->data; const struct elf_type_functions *type_functions = eor->type_functions; unsigned char ei_class = eor->ei_class; size_t shdr_size; @@ -662,8 +662,8 @@ simple_object_elf_fetch_attributes (simple_object_read *sobj, const char **errmsg ATTRIBUTE_UNUSED, int *err ATTRIBUTE_UNUSED) { - struct simple_object_elf_read *eor = - (struct simple_object_elf_read *) sobj->data; + struct simple_object_elf_read *eor + = (struct simple_object_elf_read *) sobj->data; struct simple_object_elf_attributes *ret; ret = XNEW (struct simple_object_elf_attributes); @@ -689,10 +689,10 @@ simple_object_elf_release_read (void *data) static const char * simple_object_elf_attributes_merge (void *todata, void *fromdata, int *err) { - struct simple_object_elf_attributes *to = - (struct simple_object_elf_attributes *) todata; - struct simple_object_elf_attributes *from = - (struct simple_object_elf_attributes *) fromdata; + struct simple_object_elf_attributes *to + = (struct simple_object_elf_attributes *) todata; + struct simple_object_elf_attributes *from + = (struct simple_object_elf_attributes *) fromdata; if (to->ei_data != from->ei_data || to->ei_class != from->ei_class) { @@ -751,8 +751,8 @@ simple_object_elf_start_write (void *attributes_data, const char **errmsg ATTRIBUTE_UNUSED, int *err ATTRIBUTE_UNUSED) { - struct simple_object_elf_attributes *attrs = - (struct simple_object_elf_attributes *) attributes_data; + struct simple_object_elf_attributes *attrs + = (struct simple_object_elf_attributes *) attributes_data; struct simple_object_elf_write *ret; /* We're just going to record the attributes, but we need to make a @@ -769,8 +769,8 @@ static int simple_object_elf_write_ehdr (simple_object_write *sobj, int descriptor, const char **errmsg, int *err) { - struct simple_object_elf_attributes *attrs = - (struct simple_object_elf_attributes *) sobj->data; + struct simple_object_elf_attributes *attrs + = (struct simple_object_elf_attributes *) sobj->data; const struct elf_type_functions* fns; unsigned char cl; size_t ehdr_size; @@ -852,8 +852,8 @@ simple_object_elf_write_shdr (simple_object_write *sobj, int descriptor, size_t sh_entsize, const char **errmsg, int *err) { - struct simple_object_elf_attributes *attrs = - (struct simple_object_elf_attributes *) sobj->data; + struct simple_object_elf_attributes *attrs + = (struct simple_object_elf_attributes *) sobj->data; const struct elf_type_functions* fns; unsigned char cl; size_t shdr_size; @@ -894,8 +894,8 @@ static const char * simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor, int *err) { - struct simple_object_elf_write *eow = - (struct simple_object_elf_write *) sobj->data; + struct simple_object_elf_write *eow + = (struct simple_object_elf_write *) sobj->data; struct simple_object_elf_attributes *attrs = &eow->attrs; unsigned char cl; size_t ehdr_size; @@ -1088,11 +1088,11 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj, char *(*pfn) (const char *), int *err) { - struct simple_object_elf_read *eor = - (struct simple_object_elf_read *) sobj->data; + struct simple_object_elf_read *eor + = (struct simple_object_elf_read *) sobj->data; const struct elf_type_functions *type_functions = eor->type_functions; - struct simple_object_elf_write *eow = - (struct simple_object_elf_write *) dobj->data; + struct simple_object_elf_write *eow + = (struct simple_object_elf_write *) dobj->data; unsigned char ei_class = eor->ei_class; size_t shdr_size; unsigned int shnum; @@ -1106,10 +1106,13 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj, int changed; int *pfnret; const char **pfnname; - unsigned new_i; + unsigned new_i, new_count; unsigned *sh_map; unsigned first_shndx = 0; unsigned int *symtab_indices_shndx; + int pass_symtab_indices_shndx; + unsigned int first_symtab_indices_shndx; + unsigned char **symtab_indices_shndx_buf; shdr_size = (ei_class == ELFCLASS32 ? sizeof (Elf32_External_Shdr) @@ -1179,8 +1182,7 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj, ret = (*pfn) (name); pfnret[i - 1] = ret == NULL ? -1 : 0; pfnname[i - 1] = ret == NULL ? name : ret; - if (first_shndx == 0 - && pfnret[i - 1] == 0) + if (first_shndx == 0 && pfnret[i - 1] == 0) first_shndx = i; /* Remember the indexes of existing SHT_SYMTAB_SHNDX sections. */ @@ -1191,11 +1193,12 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj, unsigned int sh_link; sh_link = ELF_FETCH_FIELD (type_functions, ei_class, Shdr, shdr, sh_link, Elf_Word); - symtab_indices_shndx[sh_link - 1] = i - 1; - /* Always discard the extended index sections, after - copying it will not be needed. This way we don't need to - update it and deal with the ordering constraints of - processing the existing symtab and changing the index. */ + symtab_indices_shndx[sh_link - 1] = i; + /* Discard the extended index sections, after copying it will not + be needed, unless we need more than SHN_LORESERVE - 1 sections + in the output. This way we don't need to update it and deal with + the ordering constraints of processing the existing symtab and + changing the index. */ pfnret[i - 1] = -1; } } @@ -1291,16 +1294,25 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj, else sh_map[i] = new_i++; } + first_symtab_indices_shndx = new_i; + symtab_indices_shndx_buf = NULL; if (new_i - 1 >= SHN_LORESERVE) - { - *err = ENOTSUP; - return "Too many copied sections"; - } - eow->shdrs = XNEWVEC (unsigned char, shdr_size * (new_i - 1)); + for (i = 1; i < shnum; ++i) + if (pfnret[i - 1] == 0 && symtab_indices_shndx[i - 1] != 0) + { + pfnret[symtab_indices_shndx[i - 1] - 1] = 0; + sh_map[symtab_indices_shndx[i - 1]] = new_i++; + } + new_count = new_i; + if (new_count != first_symtab_indices_shndx) + symtab_indices_shndx_buf + = XNEWVEC (unsigned char *, new_count - first_symtab_indices_shndx); + eow->shdrs = XNEWVEC (unsigned char, shdr_size * (new_count - 1)); /* Then perform the actual copying. */ new_i = 0; - for (i = 1; i < shnum; ++i) + pass_symtab_indices_shndx = 0; + for (i = 1; i <= shnum; ++i) { unsigned char *shdr; unsigned int sh_name, sh_type; @@ -1311,11 +1323,30 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj, off_t flags; unsigned char *buf; + if (i == shnum) + { + if (new_count - 1 < SHN_LORESERVE || pass_symtab_indices_shndx) + break; + i = 0; + pass_symtab_indices_shndx = 1; + continue; + } + if (pfnret[i - 1]) continue; - new_i++; shdr = shdrs + (i - 1) * shdr_size; + sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr, + shdr, sh_type, Elf_Word); + if (sh_type == SHT_SYMTAB_SHNDX) + { + if (!pass_symtab_indices_shndx) + continue; + } + else if (pass_symtab_indices_shndx) + continue; + + new_i++; sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr, shdr, sh_name, Elf_Word); if (sh_name >= name_size) @@ -1324,6 +1355,7 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj, XDELETEVEC (names); XDELETEVEC (shdrs); XDELETEVEC (symtab_indices_shndx); + XDELETEVEC (symtab_indices_shndx_buf); return "ELF section name out of range"; } @@ -1332,16 +1364,14 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj, shdr, sh_offset, Elf_Addr); length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr, shdr, sh_size, Elf_Addr); - sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr, - shdr, sh_type, Elf_Word); - dest = simple_object_write_create_section (dobj, pfnname[i - 1], - 0, &errmsg, err); + dest = simple_object_write_create_section (dobj, name, 0, &errmsg, err); if (dest == NULL) { XDELETEVEC (names); XDELETEVEC (shdrs); XDELETEVEC (symtab_indices_shndx); + XDELETEVEC (symtab_indices_shndx_buf); return errmsg; } @@ -1363,6 +1393,7 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj, XDELETEVEC (names); XDELETEVEC (shdrs); XDELETEVEC (symtab_indices_shndx); + XDELETEVEC (symtab_indices_shndx_buf); return errmsg; } @@ -1378,7 +1409,8 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj, /* Read the section index table if present. */ if (symtab_indices_shndx[i - 1] != 0) { - unsigned char *sidxhdr = shdrs + symtab_indices_shndx[i - 1] * shdr_size; + unsigned char *sidxhdr + = shdrs + (symtab_indices_shndx[i - 1] - 1) * shdr_size; off_t sidxoff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr, sidxhdr, sh_offset, Elf_Addr); size_t sidxsz = ELF_FETCH_FIELD (type_functions, ei_class, Shdr, @@ -1388,11 +1420,20 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj, sidxhdr, sh_type, Elf_Word); if (shndx_type != SHT_SYMTAB_SHNDX) return "Wrong section type of a SYMTAB SECTION INDICES section"; - shndx_table = (unsigned *)XNEWVEC (char, sidxsz); - simple_object_internal_read (sobj->descriptor, - sobj->offset + sidxoff, - (unsigned char *)shndx_table, - sidxsz, &errmsg, err); + shndx_table = (unsigned *) XNEWVEC (char, sidxsz); + if (!simple_object_internal_read (sobj->descriptor, + sobj->offset + sidxoff, + (unsigned char *) shndx_table, + sidxsz, &errmsg, err)) + { + XDELETEVEC (buf); + XDELETEVEC (names); + XDELETEVEC (shdrs); + XDELETEVEC (symtab_indices_shndx); + XDELETEVEC (shndx_table); + XDELETEVEC (symtab_indices_shndx_buf); + return errmsg; + } } /* Find a WEAK HIDDEN symbol which name we will use for removed @@ -1407,17 +1448,20 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj, unsigned char *st_other; if (ei_class == ELFCLASS32) { - st_info = &((Elf32_External_Sym *)ent)->st_info; - st_other = &((Elf32_External_Sym *)ent)->st_other; + st_info = &((Elf32_External_Sym *) ent)->st_info; + st_other = &((Elf32_External_Sym *) ent)->st_other; } else { - st_info = &((Elf64_External_Sym *)ent)->st_info; - st_other = &((Elf64_External_Sym *)ent)->st_other; + st_info = &((Elf64_External_Sym *) ent)->st_info; + st_other = &((Elf64_External_Sym *) ent)->st_other; } if (st_shndx == SHN_XINDEX) - st_shndx = type_functions->fetch_Elf_Word - ((unsigned char *)(shndx_table + (ent - buf) / entsize)); + { + unsigned char *ndx_ptr + = (unsigned char *) (shndx_table + (ent - buf) / entsize); + st_shndx = type_functions->fetch_Elf_Word (ndx_ptr); + } if (st_shndx != SHN_COMMON && !(st_shndx != SHN_UNDEF @@ -1442,19 +1486,26 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj, unsigned char *st_info; unsigned char *st_other; int discard = 0; + unsigned char *ndx_ptr = NULL; if (ei_class == ELFCLASS32) { - st_info = &((Elf32_External_Sym *)ent)->st_info; - st_other = &((Elf32_External_Sym *)ent)->st_other; + st_info = &((Elf32_External_Sym *) ent)->st_info; + st_other = &((Elf32_External_Sym *) ent)->st_other; } else { - st_info = &((Elf64_External_Sym *)ent)->st_info; - st_other = &((Elf64_External_Sym *)ent)->st_other; + st_info = &((Elf64_External_Sym *) ent)->st_info; + st_other = &((Elf64_External_Sym *) ent)->st_other; } + if (shndx_table) + ndx_ptr + = (unsigned char *) (shndx_table + (ent - buf) / entsize); + if (st_shndx == SHN_XINDEX) - st_shndx = type_functions->fetch_Elf_Word - ((unsigned char *)(shndx_table + (ent - buf) / entsize)); + { + st_shndx = type_functions->fetch_Elf_Word (ndx_ptr); + type_functions->set_Elf_Word (ndx_ptr, SHN_UNDEF); + } /* Eliminate all COMMONs - this includes __gnu_lto_slim which otherwise cause endless LTO plugin invocation. FIXME: remove the condition once we remove emission @@ -1488,9 +1539,14 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj, defined in the first prevailing section. */ ELF_SET_FIELD (type_functions, ei_class, Sym, ent, st_name, Elf_Word, 0); + st_shndx = sh_map[first_shndx]; + if (st_shndx >= SHN_LORESERVE) + { + type_functions->set_Elf_Word (ndx_ptr, st_shndx); + st_shndx = SHN_XINDEX; + } ELF_SET_FIELD (type_functions, ei_class, Sym, - ent, st_shndx, Elf_Half, - sh_map[first_shndx]); + ent, st_shndx, Elf_Half, st_shndx); } else { @@ -1514,11 +1570,24 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj, } else if (raw_st_shndx < SHN_LORESERVE || raw_st_shndx == SHN_XINDEX) - /* Remap the section reference. */ - ELF_SET_FIELD (type_functions, ei_class, Sym, - ent, st_shndx, Elf_Half, sh_map[st_shndx]); + { + /* Remap the section reference. */ + st_shndx = sh_map[st_shndx]; + if (st_shndx >= SHN_LORESERVE) + { + type_functions->set_Elf_Word (ndx_ptr, st_shndx); + st_shndx = SHN_XINDEX; + } + ELF_SET_FIELD (type_functions, ei_class, Sym, + ent, st_shndx, Elf_Half, st_shndx); + } } - XDELETEVEC (shndx_table); + if (symtab_indices_shndx_buf) + symtab_indices_shndx_buf[sh_map[symtab_indices_shndx[i - 1]] + - first_symtab_indices_shndx] + = (unsigned char *) shndx_table; + else + XDELETEVEC (shndx_table); } else if (sh_type == SHT_GROUP) { @@ -1538,15 +1607,21 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj, /* Adjust the length. */ length = dst - buf; } + else if (sh_type == SHT_SYMTAB_SHNDX) + { + XDELETEVEC (buf); + buf = symtab_indices_shndx_buf[new_i - first_symtab_indices_shndx]; + symtab_indices_shndx_buf[new_i - first_symtab_indices_shndx] = NULL; + } - errmsg = simple_object_write_add_data (dobj, dest, - buf, length, 1, err); + errmsg = simple_object_write_add_data (dobj, dest, buf, length, 1, err); XDELETEVEC (buf); if (errmsg) { XDELETEVEC (names); XDELETEVEC (shdrs); XDELETEVEC (symtab_indices_shndx); + XDELETEVEC (symtab_indices_shndx_buf); return errmsg; } @@ -1586,6 +1661,7 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj, XDELETEVEC (pfnname); XDELETEVEC (symtab_indices_shndx); XDELETEVEC (sh_map); + XDELETEVEC (symtab_indices_shndx_buf); return NULL; } diff --git a/libiberty/testsuite/test-demangle.c b/libiberty/testsuite/test-demangle.c index abe9015..f79cd89 100644 --- a/libiberty/testsuite/test-demangle.c +++ b/libiberty/testsuite/test-demangle.c @@ -49,8 +49,7 @@ static unsigned int lineno; #define LINELEN 80 static void -get_line(buf) - struct line *buf; +get_line(struct line *buf) { char *data = buf->data; size_t alloc = buf->alloced; @@ -134,12 +133,8 @@ protect_end (const char * s) } static void -fail (lineno, opts, in, out, exp) - int lineno; - const char *opts; - const char *in; - const char *out; - const char *exp; +fail (int lineno, const char *opts, const char *in, + const char *out, const char *exp) { printf ("\ FAIL at line %d, options %s:\n\ @@ -170,9 +165,7 @@ exp: %s\n", */ int -main(argc, argv) - int argc; - char **argv; +main(int argc, char **argv) { enum demangling_styles style = auto_demangling; int no_params; diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c index 787beb7..200fe26 100644 --- a/opcodes/riscv-opc.c +++ b/opcodes/riscv-opc.c @@ -3449,6 +3449,20 @@ const struct riscv_opcode riscv_opcodes[] = /* Vendor-specific (SiFive) cease instruction. */ {"sf.cease", 0, INSN_CLASS_XSFCEASE, "", MATCH_SF_CEASE, MASK_SF_CEASE, match_opcode, 0 }, +/* SiFive custom int8 matrix-multiply instructions. */ +{"sf.vqmaccu.4x8x4", 0, INSN_CLASS_XSFVQMACCQOQ, "Vd,Vs,Vt", MATCH_SFVQMACCU4X8X4, MASK_SFVQMACCU4X8X4, match_opcode, 0}, +{"sf.vqmacc.4x8x4", 0, INSN_CLASS_XSFVQMACCQOQ, "Vd,Vs,Vt", MATCH_SFVQMACC4X8X4, MASK_SFVQMACC4X8X4, match_opcode, 0}, +{"sf.vqmaccus.4x8x4", 0, INSN_CLASS_XSFVQMACCQOQ, "Vd,Vs,Vt", MATCH_SFVQMACCUS4X8X4, MASK_SFVQMACCUS4X8X4, match_opcode, 0}, +{"sf.vqmaccsu.4x8x4", 0, INSN_CLASS_XSFVQMACCQOQ, "Vd,Vs,Vt", MATCH_SFVQMACCSU4X8X4, MASK_SFVQMACCSU4X8X4, match_opcode, 0}, +{"sf.vqmaccu.2x8x2", 0, INSN_CLASS_XSFVQMACCDOD, "Vd,Vs,Vt", MATCH_SFVQMACCU2X8X2, MASK_SFVQMACCU2X8X2, match_opcode, 0}, +{"sf.vqmacc.2x8x2", 0, INSN_CLASS_XSFVQMACCDOD, "Vd,Vs,Vt", MATCH_SFVQMACC2X8X2, MASK_SFVQMACC2X8X2, match_opcode, 0}, +{"sf.vqmaccus.2x8x2", 0, INSN_CLASS_XSFVQMACCDOD, "Vd,Vs,Vt", MATCH_SFVQMACCUS2X8X2, MASK_SFVQMACCUS2X8X2, match_opcode, 0}, +{"sf.vqmaccsu.2x8x2", 0, INSN_CLASS_XSFVQMACCDOD, "Vd,Vs,Vt", MATCH_SFVQMACCSU2X8X2, MASK_SFVQMACCSU2X8X2, match_opcode, 0}, + +/* SiFive FP32-to-int8 ranged clip instructions (Xsfvfnrclipxfqf). */ +{"sf.vfnrclip.xu.f.qf", 0, INSN_CLASS_XSFVFNRCLIPXFQF, "Vd,Vt,S", MATCH_SFVFNRCLIPXUFQF, MASK_SFVFNRCLIPXUFQF, match_opcode, 0}, +{"sf.vfnrclip.x.f.qf", 0, INSN_CLASS_XSFVFNRCLIPXFQF, "Vd,Vt,S", MATCH_SFVFNRCLIPXFQF, MASK_SFVFNRCLIPXFQF, match_opcode, 0}, + /* Terminate the list. */ {0, 0, INSN_CLASS_NONE, 0, 0, 0, 0, 0} }; |