mailing list of musl libc
 help / color / mirror / code / Atom feed
* [musl] [PATCH] Add options to configure script to control frame pointer omission and EH unwind information
@ 2023-07-28 11:13 Alastair Houghton
  2023-07-29  5:25 ` alice
  0 siblings, 1 reply; 3+ messages in thread
From: Alastair Houghton @ 2023-07-28 11:13 UTC (permalink / raw)
  To: musl

Hi there,

Musl currently disables frame pointers and (except in debug builds) also disables the emission of EH unwind information, the latter presumably in an effort to save space. The downside of doing both of these things is that it makes it impossible for code to generate reasonable run-time backtraces, since without frame pointers the only way to do a stack walk is the EH unwind data, which has been removed.

These defaults are probably fine for most people, but not everybody wants to build in this configuration, and it would be better to offer some reasonable options here, I think. I attach a patch that adds options to the configure script that allow users of Musl to choose

* Whether to include frame pointers.
* Whether to include EH unwind tables, and if so whether they should support asynchronous unwind or not (asynchronous unwind generates more data in the tables, since the compiler isn’t allowed to make assumptions about which code could throw).

Note that the existing comment in the configure script about the DWARF tables is slightly misleading; the options the configure script uses are to do with EH unwind data (which is for exception handling, in languages that support it, as well as for runtime backtracing), and not with DWARF unwind data.  The two do potentially share some sections and the EH data is stored using DWARF as a format, but it *isn’t* debug information - it’s there for language runtime and library use.

Kind regards,

Alastair.

==== Patch follows ====

diff --git a/configure b/configure
index 853bf05e..a11e0ad8 100755
--- a/configure
+++ b/configure
@@ -10,39 +10,42 @@ VAR=VALUE.  See below for descriptions of some of the useful variables.
 Defaults for the options are specified in brackets.
 
 Configuration:
-  --srcdir=DIR            source directory [detected]
+  --srcdir=DIR             source directory [detected]
 
 Installation directories:
-  --prefix=PREFIX         main installation prefix [/usr/local/musl]
-  --exec-prefix=EPREFIX   installation prefix for executable files [PREFIX]
+  --prefix=PREFIX          main installation prefix [/usr/local/musl]
+  --exec-prefix=EPREFIX    installation prefix for executable files [PREFIX]
 
 Fine tuning of the installation directories:
-  --bindir=DIR            user executables [EPREFIX/bin]
-  --libdir=DIR            library files for the linker [PREFIX/lib]
-  --includedir=DIR        include files for the C compiler [PREFIX/include]
-  --syslibdir=DIR         location for the dynamic linker [/lib]
+  --bindir=DIR             user executables [EPREFIX/bin]
+  --libdir=DIR             library files for the linker [PREFIX/lib]
+  --includedir=DIR         include files for the C compiler [PREFIX/include]
+  --syslibdir=DIR          location for the dynamic linker [/lib]
 
 System types:
-  --target=TARGET         configure to run on target TARGET [detected]
-  --host=HOST             same as --target
-  --build=BUILD           build system type; used only to infer cross-compiling
+  --target=TARGET          configure to run on target TARGET [detected]
+  --host=HOST              same as --target
+  --build=BUILD            build system type; used only to infer cross-compiling
 
 Optional features:
-  --enable-optimize=...   optimize listed components for speed over size [auto]
-  --enable-debug          build with debugging information [disabled]
-  --disable-warnings      build with recommended warnings flags [enabled]
-  --enable-wrapper=...    build given musl toolchain wrapper [auto]
-  --disable-shared        inhibit building shared library [enabled]
-  --disable-static        inhibit building static library [enabled]
+  --enable-optimize=...    optimize listed components for speed over size [auto]
+  --enable-debug           build with debugging information [disabled]
+  --disable-warnings       build with recommended warnings flags [enabled]
+  --enable-wrapper=...     build given musl toolchain wrapper [auto]
+  --disable-shared         inhibit building shared library [enabled]
+  --disable-static         inhibit building static library [enabled]
+  --with-frame-pointers    disable -fomit-frame-pointer [disabled]
+  --with-unwind-tables=... generate EH unwind inforormation [none]
+                           (may be "none", "sync" or "async")
 
 Optional packages:
-  --with-malloc=...       choose malloc implementation [mallocng]
+  --with-malloc=...        choose malloc implementation [mallocng]
 
 Some influential environment variables:
-  CC                      C compiler command [detected]
-  CFLAGS                  C compiler flags [-Os -pipe ...]
-  CROSS_COMPILE           prefix for cross compiler and tools [none]
-  LIBCC                   compiler runtime library [detected]
+  CC                       C compiler command [detected]
+  CFLAGS                   C compiler flags [-Os -pipe ...]
+  CROSS_COMPILE            prefix for cross compiler and tools [none]
+  LIBCC                    compiler runtime library [detected]
 
 Use these variables to override the choices made by configure.
 
@@ -143,6 +146,8 @@ wrapper=auto
 gcc_wrapper=no
 clang_wrapper=no
 malloc_dir=mallocng
+frame_pointers=no
+unwind_tables=none
 
 for arg ; do
 case "$arg" in
@@ -172,6 +177,8 @@ case "$arg" in
 --disable-wrapper|--enable-wrapper=no) wrapper=no ;;
 --enable-gcc-wrapper|--enable-gcc-wrapper=yes) wrapper=yes ; gcc_wrapper=yes ;;
 --disable-gcc-wrapper|--enable-gcc-wrapper=no) wrapper=no ;;
+--with-frame-pointers) frame_pointers=yes ;;
+--with-unwind-tables=*) unwind_tables=${arg#*=} ;;
 --with-malloc=*) malloc_dir=${arg#*=} ;;
 --enable-*|--disable-*|--with-*|--without-*|--*dir=*) ;;
 --host=*|--target=*) target=${arg#*=} ;;
@@ -471,23 +478,46 @@ fi
 tryflag CFLAGS_AUTO -pipe
 
 #
-# If debugging is disabled, omit frame pointer. Modern GCC does this
-# anyway on most archs even when debugging is enabled since the frame
-# pointer is no longer needed for debugging.
+# Unless otherwise specified, omit frame pointers where possible
+# except when debugging is enabled.
 #
-if fnmatch '-g*|*\ -g*' "$CFLAGS_AUTO $CFLAGS" ; then :
+# In general, either frame pointers or unwind information are required
+# if you wish to be able to obtain a reliable backtrace from a crashed
+# program.
+#
+# Neither is required for debugging, as the full debug information
+# will be used in that case.
+#
+if test "$frame_pointers" = yes ; then
+tryflag CFLAGS_AUTO -fno-omit-frame-pointer
+elif fnmatch '-g*|*\ -g*' "$CFLAGS_AUTO $CFLAGS" ; then :
 else
 tryflag CFLAGS_AUTO -fomit-frame-pointer
 fi
 
 #
-# Modern GCC wants to put DWARF tables (used for debugging and
-# unwinding) in the loaded part of the program where they are
-# unstrippable. These options force them back to debug sections (and
-# cause them not to get generated at all if debugging is off).
+# Control the generation of unwind information.  Note that this is not
+# used for debugging; in C it is only used to allow runtime backtracing
+# without frame pointers.  In languages with exceptions, it is used to
+# provide instructions to the unwinder (typically libunwind).
 #
+case "$unwind_tables" in
+none|no)
 tryflag CFLAGS_AUTO -fno-unwind-tables
 tryflag CFLAGS_AUTO -fno-asynchronous-unwind-tables
+;;
+sync|yes)
+tryflag CFLAGS_AUTO -funwind-tables
+tryflag CFLAGS_AUTO -fno-asynchronous-unwind-tables
+;;
+async)
+tryflag CFLAGS_AUTO -funwind-tables
+tryflag CFLAGS_AUTO -fasynchronous-unwind-tables
+;;
+*)
+fail "$0: error: unknown unwind table settings '$unwind_tables'"
+;;
+esac
 
 #
 # Attempt to put each function and each data object in its own


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [musl] [PATCH] Add options to configure script to control frame pointer omission and EH unwind information
  2023-07-28 11:13 [musl] [PATCH] Add options to configure script to control frame pointer omission and EH unwind information Alastair Houghton
@ 2023-07-29  5:25 ` alice
  2023-07-31 14:15   ` Alastair Houghton
  0 siblings, 1 reply; 3+ messages in thread
From: alice @ 2023-07-29  5:25 UTC (permalink / raw)
  To: musl

On Fri Jul 28, 2023 at 11:13 AM UTC, Alastair Houghton wrote:
> Hi there,
>
> Musl currently disables frame pointers and (except in debug builds) also
> disables the emission of EH unwind information, the latter presumably in an
> effort to save space. The downside of doing both of these things is that it
> makes it impossible for code to generate reasonable run-time backtraces, since
> without frame pointers the only way to do a stack walk is the EH unwind data,
> which has been removed.
>
> These defaults are probably fine for most people, but not everybody wants to
> build in this configuration, and it would be better to offer some reasonable
> options here, I think. I attach a patch that adds options to the configure
> script that allow users of Musl to choose
>
> * Whether to include frame pointers.
> * Whether to include EH unwind tables, and if so whether they should support
>   asynchronous unwind or not (asynchronous unwind generates more data in the
>   tables, since the compiler isn’t allowed to make assumptions about which code
>   could throw).
>
> Note that the existing comment in the configure script about the DWARF tables
> is slightly misleading; the options the configure script uses are to do with
> EH unwind data (which is for exception handling, in languages that support it,
> as well as for runtime backtracing), and not with DWARF unwind data.  The two
> do potentially share some sections and the EH data is stored using DWARF as a
> format, but it *isn’t* debug information - it’s there for language runtime and
> library use.

i believe the proposed change, and the rationale for it, had already been
thoroughly discussed and rejected in
https://www.openwall.com/lists/musl/2021/07/16/1

(not exactly the same, and the above isn't as fine grained, but the core of it
is identical)

the core of it is really in (quoting Rich):

> The debugger already can do debugging/unwinding because it has access
> to the debug information (if you've installed it) and there is a
> clear, understood-by-users contract that this information is not an
> inherent part of the program but something optional for external
> debugging tools only.

>>  - libunwind/libexecinfo will start to work and give meaningful backtraces
>
> This is explicitly a reason not to. backtrace() considered harmful.

there is no intent to allow 'runtime use' of this data (i.e. allow backtraces),
outside of what already works with an external debugger.

unrelatedly (to the prior rejection), i believe these days there has been work
on the SFrame format (as opposed to EH), to allow easier backtracing (they
aren't mutually exclusive). maybe that is better to build on these days?

>
> Kind regards,
>
> Alastair.
>

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [musl] [PATCH] Add options to configure script to control frame pointer omission and EH unwind information
  2023-07-29  5:25 ` alice
@ 2023-07-31 14:15   ` Alastair Houghton
  0 siblings, 0 replies; 3+ messages in thread
From: Alastair Houghton @ 2023-07-31 14:15 UTC (permalink / raw)
  To: musl

> On 29 Jul 2023, at 06:25, alice <alice@ayaya.dev> wrote:
> 
> i believe the proposed change, and the rationale for it, had already been
> thoroughly discussed and rejected in
> https://www.openwall.com/lists/musl/2021/07/16/1

Thanks for the link. That was an interesting read.

> there is no intent to allow 'runtime use' of this data (i.e. allow backtraces),
> outside of what already works with an external debugger.

It’s worth noting (and I think the Alpine folks did mention this in the thread you highlighted) that external debuggers don’t work inside Docker containers, at least by default, and that that cluster operators are unlikely to want to make the changes that would be required to fix that because they create security holes.

At the same time, generating backtraces in e.g. assertion failure routines or from a C++ unhandled exception handler can be a useful thing to do and is not nearly as risky as trying to do that from a SEGV handler.  With no EH frame information and no frame pointers, those backtraces are going to stop the moment they hit musl’s code.  Maybe that’s OK — there aren’t that many things in the C library that involve calling out to user code anyway.

> unrelatedly (to the prior rejection), i believe these days there has been work
> on the SFrame format (as opposed to EH), to allow easier backtracing (they
> aren't mutually exclusive). maybe that is better to build on these days?

As I understand it that’s a Linux kernel thing, and not really applicable outside of that context.

What I was mostly trying to do is get (LLVM) libunwind’s tests to pass out of the box, without having to disable things for musl.  Maybe I just disable those tests for now.

Kind regards,

Alastair.


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2023-07-31 14:16 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-28 11:13 [musl] [PATCH] Add options to configure script to control frame pointer omission and EH unwind information Alastair Houghton
2023-07-29  5:25 ` alice
2023-07-31 14:15   ` Alastair Houghton

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).