[RFC,3/5] configure: Add --enable-sframe option
Checks
Commit Message
From: Claudiu Zissulescu <claudiu.zissulescu-ianculescu@oracle.com>
Enable SFrame stack track information. The --enable-sframe option
allows the glibc build to compile with SFrame stack track
information. Thus, enabling glibc's backtrace to work within glibc.
Signed-off-by: Claudiu Zissulescu <claudiu.zissulescu-ianculescu@oracle.com>
---
Makeconfig | 8 +++-
config.make.in | 1 +
configure | 128 +++++++++++++++++++++++++++++++++++++++++++++++++
configure.ac | 43 +++++++++++++++++
4 files changed, 179 insertions(+), 1 deletion(-)
Comments
On Tue, 18 Mar 2025, claudiu.zissulescu-ianculescu@oracle.com wrote:
> Enable SFrame stack track information. The --enable-sframe option
> allows the glibc build to compile with SFrame stack track
> information. Thus, enabling glibc's backtrace to work within glibc.
A new configure option should be documented in install.texi (with INSTALL
regenerated).
On 18.03.2025 14:03, claudiu.zissulescu-ianculescu@oracle.com wrote:
> Enable SFrame stack track information. The --enable-sframe option
> allows the glibc build to compile with SFrame stack track
> information. Thus, enabling glibc's backtrace to work within glibc.
I am not familiar with this part of Glibc. Should Glibc by itself
determine to be built by default with SFrame stack trace information,
if the toolchain supports it, unless it is configured with
--disable-sframe, or should distributors control this via CFLAGS, e.g.
their distribution default rpmbuild macros?
Thanks and regards,
Jens
Hi Joseph,
Thank you for all your input. I'll try to address all the concerns in my
second attempt,
Claudiu
On 3/18/25 6:27 PM, Joseph Myers wrote:
> On Tue, 18 Mar 2025, claudiu.zissulescu-ianculescu@oracle.com wrote:
>
>> Enable SFrame stack track information. The --enable-sframe option
>> allows the glibc build to compile with SFrame stack track
>> information. Thus, enabling glibc's backtrace to work within glibc.
>
> A new configure option should be documented in install.texi (with INSTALL
> regenerated).
>
On 3/19/25 5:51 PM, Jens Remus wrote:
> On 18.03.2025 14:03, claudiu.zissulescu-ianculescu@oracle.com wrote:
>
>> Enable SFrame stack track information. The --enable-sframe option
>> allows the glibc build to compile with SFrame stack track
>> information. Thus, enabling glibc's backtrace to work within glibc.
>
> I am not familiar with this part of Glibc. Should Glibc by itself
> determine to be built by default with SFrame stack trace information,
> if the toolchain supports it, unless it is configured with
> --disable-sframe, or should distributors control this via CFLAGS, e.g.
> their distribution default rpmbuild macros?
That is my understanding, if a new feature is added, that one is enabled
by default unless specified. But the maintainers will correct me :)
@@ -1011,6 +1011,12 @@ else
+cflags += $(no-fortify-source)
endif
+# Enable SFrame while compiling for stack backtracing.
+ifeq ($(enable-gsframe),yes)
+as-sframe = -Wa,--gsframe
+endif
++cflags += $(as-sframe)
+
# Each sysdeps directory can contain header files that both will be
# used to compile and will be installed. Each can also contain an
# include/ subdirectory, whose header files will be used to compile
@@ -1158,7 +1164,7 @@ endif
ifndef ASFLAGS
ASFLAGS := $(filter -g% -fdebug-prefix-map=%,$(CFLAGS))
endif
-override ASFLAGS += -Werror=undef $(ASFLAGS-config) $(asflags-cpu)
+override ASFLAGS += -Werror=undef $(ASFLAGS-config) $(asflags-cpu) $(as-sframe)
ifndef BUILD_CC
BUILD_CC = $(CC)
@@ -51,6 +51,7 @@ c++-cstdlib-header = @CXX_CSTDLIB_HEADER@
c++-cmath-header = @CXX_CMATH_HEADER@
c++-bits-std_abs-h = @CXX_BITS_STD_ABS_H@
enable-werror = @enable_werror@
+enable-gsframe = @enable_gsframe@
have-z-execstack = @libc_cv_z_execstack@
have-protected-data = @libc_cv_protected_data@
@@ -620,6 +620,8 @@ DEFINES
static_nss
profile
libc_cv_multidir
+enable_gsframe
+READELF_SFRAME
shared
static
ldd_rewrite_script
@@ -808,6 +810,7 @@ enable_mathvec
enable_cet
enable_scv
enable_fortify_source
+enable_sframe
with_cpu
'
ac_precious_vars='build_alias
@@ -1491,6 +1494,8 @@ Optional Features:
Use -D_FORTIFY_SOURCE=[1|2|3] to control code
hardening, defaults to highest possible value
supported by the build compiler.
+ --enable-sframe Enable SFrame stack trace information [default
+ depends on toolchain]
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -4855,6 +4860,16 @@ case "$enable_fortify_source" in
*) as_fn_error $? "Not a valid argument for --enable-fortify-source: \"$enable_fortify_source\"" "$LINENO" 5;;
esac
+# Check whether --enable-sframe was given.
+if test ${enable_sframe+y}
+then :
+ enableval=$enable_sframe; use_sframe=$enableval
+else case e in #(
+ e) use_sframe=notset ;;
+esac
+fi
+
+
# We keep the original values in `$config_*' and never modify them, so we
# can write them unchanged into config.make. Everything else uses
# $machine, $vendor, and $os, and changes them whenever convenient.
@@ -8110,6 +8125,119 @@ fi
config_vars="$config_vars
enable-static-pie = $libc_cv_static_pie"
+# Glibc stacktracer supports SFrame v2 or newer
+libc_cv_readelf_version_ok=yes
+for ac_prog in $READELF
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_READELF_SFRAME+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$READELF_SFRAME"; then
+ ac_cv_prog_READELF_SFRAME="$READELF_SFRAME" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ 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_READELF_SFRAME="$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+READELF_SFRAME=$ac_cv_prog_READELF_SFRAME
+if test -n "$READELF_SFRAME"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $READELF_SFRAME" >&5
+printf "%s\n" "$READELF_SFRAME" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$READELF_SFRAME" && break
+done
+
+if test -z "$READELF_SFRAME"; then
+ ac_verc_fail=yes
+else
+ # Found it, now check the version.
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking version of $READELF_SFRAME" >&5
+printf %s "checking version of $READELF_SFRAME... " >&6; }
+ ac_prog_version=`$READELF_SFRAME --version 2>&1 | sed -n 's/^.*GNU readelf.* \([0-9][0-9]*\.[0-9.]*\).*$/\1/p'`
+ case $ac_prog_version in
+ '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
+ 2.4[1-9]*|2.[5-9][0-9]*|[3-9].*|[1-9][0-9]*)
+ ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
+ *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
+
+ esac
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_prog_version" >&5
+printf "%s\n" "$ac_prog_version" >&6; }
+fi
+if test $ac_verc_fail = yes; then
+ libc_cv_readelf_version_ok=no
+fi
+
+
+# Check the current toolchain for SFrame support
+if test $libc_cv_readelf_version_ok = yes; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for SFrame support" >&5
+printf %s "checking for SFrame support... " >&6; }
+if test ${libc_cv_default_sframe+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat > conftest.c <<EOF
+int test_function(void)
+{
+ return 42;
+}
+EOF
+ libc_cv_default_sframe=no
+ if ${CC} -c conftest.c -o conftest.o -Wa,--gsframe >/dev/null 2>&1 && \
+ # Check if .sframe section is present and if version > 1
+ $READELF --sframe conftest.o | grep "SFRAME_VER" | grep -qv "VERSION_1"; then
+ libc_cv_default_sframe=yes
+ fi
+ rm -f conftest.c conftest.o
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_default_sframe" >&5
+printf "%s\n" "$libc_cv_default_sframe" >&6; }
+fi
+
+# Prevent enabling sframe on non-supporting toolchains
+enable_gsframe=no
+if test $use_sframe$libc_cv_default_sframe = yesyes || \
+ test $use_sframe$libc_cv_default_sframe = notsetyes; then
+ enable_gsframe=yes
+elif test $use_sframe = yes; then
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "toolchain doesn't support SFrame V2 or higher
+See 'config.log' for more details" "$LINENO" 5; }
+fi
+
+
# Set the `multidir' variable by grabbing the variable from the compiler.
# We do it once and save the result in a generated makefile.
libc_cv_multidir=`${CC-cc} $CFLAGS $CPPFLAGS -print-multi-directory`
@@ -426,6 +426,12 @@ case "$enable_fortify_source" in
*) AC_MSG_ERROR([Not a valid argument for --enable-fortify-source: "$enable_fortify_source"]);;
esac
+AC_ARG_ENABLE([sframe],
+ [AS_HELP_STRING([--enable-sframe],
+ [Enable SFrame stack trace information @<:@default depends on toolchain@:>@])],
+ [use_sframe=$enableval],
+ [use_sframe=notset])
+
# We keep the original values in `$config_*' and never modify them, so we
# can write them unchanged into config.make. Everything else uses
# $machine, $vendor, and $os, and changes them whenever convenient.
@@ -1776,6 +1782,43 @@ if test "$libc_cv_static_pie" = "yes"; then
fi
LIBC_CONFIG_VAR([enable-static-pie], [$libc_cv_static_pie])
+# Glibc stacktracer supports SFrame v2 or newer
+libc_cv_readelf_version_ok=yes
+AC_CHECK_PROG_VER(READELF_SFRAME, $READELF, --version,
+ [GNU readelf.* \([0-9][0-9]*\.[0-9.]*\)],
+ [2.4[1-9]*|2.[5-9][0-9]*|[3-9].*|[1-9][0-9]*],
+ libc_cv_readelf_version_ok=no)
+
+# Check the current toolchain for SFrame support
+if test $libc_cv_readelf_version_ok = yes; then
+ AC_CACHE_CHECK([for SFrame support], libc_cv_default_sframe,
+ [dnl
+cat > conftest.c <<EOF
+int test_function(void)
+{
+ return 42;
+}
+EOF
+ libc_cv_default_sframe=no
+ if ${CC} -c conftest.c -o conftest.o -Wa,--gsframe >/dev/null 2>&1 && \
+ # Check if .sframe section is present and if version > 1
+ $READELF --sframe conftest.o | grep "SFRAME_VER" | grep -qv "VERSION_1"; then
+ libc_cv_default_sframe=yes
+ fi
+ rm -f conftest.c conftest.o
+ ])
+fi
+
+# Prevent enabling sframe on non-supporting toolchains
+enable_gsframe=no
+if test $use_sframe$libc_cv_default_sframe = yesyes || \
+ test $use_sframe$libc_cv_default_sframe = notsetyes; then
+ enable_gsframe=yes
+elif test $use_sframe = yes; then
+ AC_MSG_FAILURE([toolchain doesn't support SFrame V2 or higher])
+fi
+AC_SUBST(enable_gsframe)
+
# Set the `multidir' variable by grabbing the variable from the compiler.
# We do it once and save the result in a generated makefile.
libc_cv_multidir=`${CC-cc} $CFLAGS $CPPFLAGS -print-multi-directory`