From 17d05df7da13f7b0942e4e6b5f952f66c29338a2 Mon Sep 17 00:00:00 2001 From: Sunil Dora Date: Tue, 24 Mar 2026 09:45:27 -0700 Subject: [PATCH] gdb/ser-unix: add POSIX cfsetispeed/cfsetospeed support for custom baud rates glibc 2.42 and later, and GNU Hurd, accept arbitrary baud rates directly via cfsetispeed and cfsetospeed. This behaviour is expected to be standardized in a future POSIX revision. Introduce a configure-time test (HAVE_CFSETSPEED_ARBITRARY) that detects this capability and add a new platform-agnostic helper set_custom_baudrate_posix. The main dispatcher now prefers the POSIX path when it is available, falling back to the existing Linux (BOTHER) or Darwin (IOSSIOSPEED) implementations otherwise. The HAVE_CUSTOM_BAUDRATE_SUPPORT guard is extended to also cover the new POSIX case. Suggested-by: Kevin Buettner Suggested-by: Maciej W. Rozycki Signed-off-by: Sunil Dora Reviewed-By: Eli Zaretskii Approved-by: Kevin Buettner (cherry picked from commit 7d53467645b0430e94a3cfd13fc3c16ef19efda5) --- gdb/config.in | 3 +++ gdb/configure | 39 ++++++++++++++++++++++++++++++++++++++ gdb/configure.ac | 19 +++++++++++++++++++ gdb/ser-unix.c | 49 +++++++++++++++++++++++++++++++++++++++--------- 4 files changed, 101 insertions(+), 9 deletions(-) diff --git a/gdb/config.in b/gdb/config.in index 62ceb846824..e66127a427d 100644 --- a/gdb/config.in +++ b/gdb/config.in @@ -110,6 +110,9 @@ the CoreFoundation framework. */ #undef HAVE_CFPREFERENCESCOPYAPPVALUE +/* Define if cfsetispeed/cfsetospeed accept arbitrary baud rates. */ +#undef HAVE_CFSETSPEED_ARBITRARY + /* Define if compiling support to gdb compile. */ #undef HAVE_COMPILE diff --git a/gdb/configure b/gdb/configure index 3c321d6220b..ef645210301 100755 --- a/gdb/configure +++ b/gdb/configure @@ -27349,6 +27349,45 @@ _ACEOF fi +# Check whether cfsetispeed/cfsetospeed accept arbitrary baud rates. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cfsetispeed/cfsetospeed accept arbitrary baud rates" >&5 +$as_echo_n "checking whether cfsetispeed/cfsetospeed accept arbitrary baud rates... " >&6; } +if ${gdb_cv_cfsetspeed_arbitrary+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + + #if B9600 != 9600 + #error B-constants are not numeric symbols + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + gdb_cv_cfsetspeed_arbitrary=yes +else + gdb_cv_cfsetspeed_arbitrary=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gdb_cv_cfsetspeed_arbitrary" >&5 +$as_echo "$gdb_cv_cfsetspeed_arbitrary" >&6; } + +if test "$gdb_cv_cfsetspeed_arbitrary" = yes; then + +$as_echo "#define HAVE_CFSETSPEED_ARBITRARY 1" >>confdefs.h + +fi + # Check whether --with-jit-reader-dir was given. diff --git a/gdb/configure.ac b/gdb/configure.ac index 9d3377f3c40..dfa40d34c10 100644 --- a/gdb/configure.ac +++ b/gdb/configure.ac @@ -736,6 +736,25 @@ AC_SEARCH_LIBS(dlopen, dl) # Check for members required by the legacy Linux custom baud rate path. AC_CHECK_MEMBERS([struct termios.c_ospeed], [], [], [[#include ]]) +# Check whether cfsetispeed/cfsetospeed accept arbitrary baud rates. +AC_CACHE_CHECK([whether cfsetispeed/cfsetospeed accept arbitrary baud rates], + [gdb_cv_cfsetspeed_arbitrary], [ + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[#include ]], + [[ + #if B9600 != 9600 + #error B-constants are not numeric symbols + #endif + ]])], + [gdb_cv_cfsetspeed_arbitrary=yes], + [gdb_cv_cfsetspeed_arbitrary=no]) +]) + +if test "$gdb_cv_cfsetspeed_arbitrary" = yes; then + AC_DEFINE([HAVE_CFSETSPEED_ARBITRARY], [1], + [Define if cfsetispeed/cfsetospeed accept arbitrary baud rates.]) +fi + GDB_AC_WITH_DIR([JIT_READER_DIR], [jit-reader-dir], [directory to load the JIT readers from], [${libdir}/gdb]) diff --git a/gdb/ser-unix.c b/gdb/ser-unix.c index ffd721ad599..5ec664df1f3 100644 --- a/gdb/ser-unix.c +++ b/gdb/ser-unix.c @@ -53,9 +53,10 @@ #include "gdbsupport/scoped_ignore_sigttou.h" -#if (defined(HAVE_SYS_IOCTL_H) \ - && ((defined(BOTHER) && defined(HAVE_STRUCT_TERMIOS_C_OSPEED)) \ - || defined(IOSSIOSPEED))) +#if (defined(HAVE_CFSETSPEED_ARBITRARY) \ + || (defined(HAVE_SYS_IOCTL_H) \ + && ((defined(BOTHER) && defined(HAVE_STRUCT_TERMIOS_C_OSPEED)) \ + || defined(IOSSIOSPEED)))) # define HAVE_CUSTOM_BAUDRATE_SUPPORT 1 #endif @@ -508,7 +509,32 @@ set_baudcode_baudrate (struct serial *scb, int baud_code) perror_with_name (_("could not set tty state")); } -#if HAVE_CUSTOM_BAUDRATE_SUPPORT && defined(BOTHER) +#if HAVE_CUSTOM_BAUDRATE_SUPPORT && defined(HAVE_CFSETSPEED_ARBITRARY) + +/* Set a custom baud rate using the POSIX cfsetispeed/cfsetospeed + interface. Supported in glibc 2.42 and later and expected to be + standardized in a future POSIX revision. It is platform-agnostic + and also covers systems like GNU Hurd that do not provide BOTHER. */ + +static void +set_custom_baudrate_posix (int fd, int rate) +{ + struct termios tio; + + if (tcgetattr (fd, &tio) < 0) + perror_with_name (_("Cannot get current baud rate")); + + if (cfsetispeed (&tio, rate) < 0) + perror_with_name (_("Cannot set custom input baud rate")); + + if (cfsetospeed (&tio, rate) < 0) + perror_with_name (_("Cannot set custom output baud rate")); + + if (tcsetattr (fd, TCSANOW, &tio) < 0) + perror_with_name (_("Cannot set custom baud rate")); +} + +#elif HAVE_CUSTOM_BAUDRATE_SUPPORT && defined(BOTHER) /* Set a custom baud rate using the termios BOTHER. */ @@ -555,19 +581,24 @@ set_custom_baudrate_darwin (int fd, int rate) } #endif /* HAVE_CUSTOM_BAUDRATE_SUPPORT - && (defined(BOTHER) || defined(IOSSIOSPEED)) */ + && (defined(HAVE_CFSETSPEED_ARBITRARY) + || defined(BOTHER) + || defined(IOSSIOSPEED)) */ #if HAVE_CUSTOM_BAUDRATE_SUPPORT /* Set a baud rate that differs from the OS B_codes. - This is possible if one of the following macros is available: - - BOTHER (Linux). - - IOSSIOSPEED (Darwin). */ + Prefer the POSIX cfsetispeed/cfsetospeed interface when the host + libc accepts arbitrary baud rates. Otherwise fall back to + Linux-specific (BOTHER) or Darwin-specific (IOSSIOSPEED) + interfaces. */ static void set_custom_baudrate (int fd, int rate) { -#if defined(BOTHER) +#if defined(HAVE_CFSETSPEED_ARBITRARY) + set_custom_baudrate_posix (fd, rate); +#elif defined(BOTHER) set_custom_baudrate_linux (fd, rate); #elif defined(IOSSIOSPEED) set_custom_baudrate_darwin (fd, rate);