ianlancetaylor / libbacktrace

A C library that may be linked into a C/C++ program to produce symbolic backtraces
Other
944 stars 220 forks source link

Improvement of PE stacktraces in case of ASLR #110

Closed Febbe closed 11 months ago

Febbe commented 1 year ago

fixes #103

Instead of generating an empty stacktrace, libbacktrace generates now something like this:

   0# main at C:/Users/Febbe/workspace/test/test/main.cpp:7
   1# __tmainCRTStartup at C:/M/B/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:267
   2# mainCRTStartup at C:/M/B/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:188
   3# register_frame_ctor at :0
   4# register_frame_ctor at :0
   5#

To implement the resolution of addresses with ASLR, it is necessary to look into the Process Environment Block (PEB) of a process. It contains all the required information to map the pc to the functions. To read the PEB, functions from the Windows SDK are required. This is not possible via the POSIX API (:/). The functions defined by would do this for POSIX and ELF, but this is not implemented for PE files in MSYS/Mingw/Cygwin environments. Most of the added code reads the PEB and returns the base addresses.

Somehow it was required to subtract the default base-address, which can be overridden by /BASE in the case ASLR is not used. The variable name of that address is image-base and it was already read from the PE/COFF.

I followed the implementation of the elf files. There, all dynamic libraries were loaded via the dl_iterate_phdr after the main executable file has been parsed. However, for PE on Windows this must be done also for the main file, since it also has a random base address.

Last but not least, there are still some issues with PE/COFF stacktraces: for libraries, no PE/COFF with dwarf has been generated, only the register_frame_ctor is shown. #5 was in my case the start address 0xffffffffffffffff, so it probably should not be shown.

Febbe commented 1 year ago

Looks like @HazardyKnusperkeks fixed this with https://github.com/ianlancetaylor/libbacktrace/issues/82#issuecomment-1340460448

MisterTea commented 11 months ago

@Febbe How does that fix make it into this repo?

Febbe commented 11 months ago

@Febbe How does that fix make it into this repo?

What do you mean?

MisterTea commented 11 months ago

Your PR is open, and the commit you pointed to is in another repo. It looks like the master branch of this repo still does not support ASLR on mingw64?

Febbe commented 11 months ago

Your PR is open, and the commit you pointed to is in another repo. It looks like the master branch of this repo still does not support ASLR on mingw64?

That's right, it seems that the fix is only applied to GCC, which uses libbacktrace for c++23. If you want to have this fixed, you can checkout my fork or apply the patches yourself.

When you want to see it in this repo, you must wait until Ian lance Taylor has the time to apply the patches himself.

ianlancetaylor commented 11 months ago

The patch from https://github.com/ianlancetaylor/libbacktrace/pull/110#issuecomment-1715795506 is already in this repo. It's commit afe2967c773eba6b16dfe2ea5e0bb5cd721516a2. Is there another patch that needs to be brought over? Thanks.

Febbe commented 11 months ago

Those are missing: [PATCH 2/4] libbacktrace: detect executable path on windows [PATCH 3/4] libbacktrace: work with aslr on windows [PATCH 4/4] libbacktrace: get debug information for loaded dlls

Note, that they partially fix my comment regarding the windows executable path in this PR , except that paths longer than 260 characters are ignored.

ianlancetaylor commented 11 months ago

Thanks. Those patches have not been committed upstream. I've been waiting for someone to confirm that the modified version that I wrote works.

https://gcc.gnu.org/pipermail/gcc-patches/2023-January/610540.html https://gcc.gnu.org/pipermail/gcc-patches/2023-February/611407.html

Can you check that modified patch? Thanks.

Febbe commented 11 months ago

I had to modify the patch, because of c1c86fa2f0d9509b99f0d90f240dc71086458af5 and I am not sure, if I ran the tests right, but it looks good except 2 warnings due to unused parameters:

Febbe@DESKTOP-VIRN68C UCRT64 ~/ianlancetaylor/libbacktrace/build
$ ../configure
$ make
$ make test_pecoff.exe
$ ./test_pecoff.exe && (echo successfully) || echo failed
successfully
With output: ``` Febbe@DESKTOP-VIRN68C UCRT64 ~/ianlancetaylor/libbacktrace/build $ ../configure configure: loading site script /etc/config.site checking build system type... x86_64-w64-mingw32 checking host system type... x86_64-w64-mingw32 checking target system type... x86_64-w64-mingw32 checking for gcc... gcc checking whether the C compiler works... yes checking for C compiler default output file name... a.exe checking for suffix of executables... .exe checking whether we are cross compiling... no checking for suffix of object files... o checking whether we are using the GNU C compiler... yes checking whether gcc accepts -g... yes checking for gcc option to accept ISO C89... none needed checking whether gcc understands -c and -o together... yes checking how to run the C preprocessor... gcc -E checking for grep that handles long lines and -e... /usr/bin/grep checking for egrep... /usr/bin/grep -E checking for ANSI C header files... yes checking for sys/types.h... yes checking for sys/stat.h... yes checking for stdlib.h... yes checking for string.h... yes checking for memory.h... yes checking for strings.h... yes checking for inttypes.h... yes checking for stdint.h... yes checking for unistd.h... yes checking minix/config.h usability... no checking minix/config.h presence... no checking for minix/config.h... no checking whether it is safe to define __EXTENSIONS__... yes checking for a BSD-compatible install... /usr/bin/install -c checking whether build environment is sane... yes checking for a thread-safe mkdir -p... /usr/bin/mkdir -p checking for gawk... gawk checking whether make sets $(MAKE)... yes checking whether make supports nested variables... yes checking whether to enable maintainer-specific portions of Makefiles... no checking for gcc... (cached) gcc checking whether we are using the GNU C compiler... (cached) yes checking whether gcc accepts -g... (cached) yes checking for gcc option to accept ISO C89... (cached) none needed checking whether gcc understands -c and -o together... (cached) yes checking for ranlib... ranlib checking for gawk... (cached) gawk checking for dwz... no checking how to print strings... printf checking for a sed that does not truncate output... /usr/bin/sed checking for fgrep... /usr/bin/grep -F checking for ld used by gcc... C:/msys64/ucrt64/x86_64-w64-mingw32/bin/ld.exe checking if the linker (C:/msys64/ucrt64/x86_64-w64-mingw32/bin/ld.exe) is GNU ld... yes checking for BSD- or MS-compatible name lister (nm)... /ucrt64/bin/nm -B checking the name lister (/ucrt64/bin/nm -B) interface... BSD nm checking whether ln -s works... no, using cp -pR checking the maximum length of command line arguments... 8192 checking whether the shell understands some XSI constructs... yes checking whether the shell understands "+="... yes checking for C:/msys64/ucrt64/x86_64-w64-mingw32/bin/ld.exe option to reload object files... -r checking for objdump... objdump checking how to recognize dependent libraries... file_magic ^x86 archive import|^x86 DLL checking for ar... ar checking for strip... strip checking for ranlib... (cached) ranlib checking command to parse /ucrt64/bin/nm -B output from gcc object... ok checking for dlfcn.h... yes checking for objdir... .libs checking if gcc supports -fno-rtti -fno-exceptions... ../configure: line 8298: diff: command not found no checking for gcc option to produce PIC... -DDLL_EXPORT -DPIC checking if gcc PIC flag -DDLL_EXPORT -DPIC works... yes checking if gcc static flag -static works... yes checking if gcc supports -c -o file.o... yes checking if gcc supports -c -o file.o... (cached) yes checking whether the gcc linker (C:/msys64/ucrt64/x86_64-w64-mingw32/bin/ld.exe) supports shared libraries... yes checking dynamic linker characteristics... Win32 ld.exe checking how to hardcode library paths into programs... immediate checking whether stripping libraries is possible... yes checking if libtool supports shared libraries... yes checking whether to build shared libraries... no checking whether to build static libraries... yes checking for special C compiler options needed for large files... no checking for _FILE_OFFSET_BITS value needed for large files... 64 checking unwind.h usability... yes checking unwind.h presence... yes checking for unwind.h... yes checking for _Unwind_Backtrace... yes checking for -funwind-tables option... yes checking for -frandom-seed=string option... yes checking whether gcc supports -W... yes checking whether gcc supports -Wall... yes checking whether gcc supports -Wwrite-strings... yes checking whether gcc supports -Wstrict-prototypes... yes checking whether gcc supports -Wmissing-prototypes... yes checking whether gcc supports -Wold-style-definition... yes checking whether gcc supports -Wmissing-format-attribute... yes checking whether gcc supports -Wcast-qual... yes checking for _Unwind_GetIPInfo... yes checking __sync extensions... yes checking __atomic extensions... yes checking output filetype... pecoff checking sys/mman.h usability... no checking sys/mman.h presence... no checking for sys/mman.h... no checking link.h usability... no checking link.h presence... no checking for link.h... no checking sys/link.h usability... no checking sys/link.h presence... no checking for sys/link.h... no checking mach-o/dyld.h usability... no checking mach-o/dyld.h presence... no checking for mach-o/dyld.h... no checking sys/ldr.h usability... no checking sys/ldr.h presence... no checking for sys/ldr.h... no checking windows.h usability... yes checking windows.h presence... yes checking for windows.h... yes checking for fcntl... no checking whether strnlen is declared... yes checking whether getpagesize is declared... no checking for lstat... no checking for readlink... no checking for getexecname... no checking whether _pgmptr is declared... yes checking for KERN_PROC... no checking for KERN_PROG_ARGS... no checking for clock_gettime... yes checking whether -pthread is supported... yes checking whether -gdwarf-5 is supported... yes checking for compress in -lz... yes checking whether --build-id is supported... yes checking whether --compress-debug-sections is supported... no checking for ZSTD_compress in -lzstd... yes checking whether --compress-debug-sections=zstd is supported... no checking for objcopy... objcopy checking for readelf... readelf checking whether objcopy supports debuglink... yes checking for dsymutil... dsymutil checking for nm... /ucrt64/bin/nm -B checking for xz... xz checking for comm... comm checking for lzma_auto_decoder in -llzma... yes checking whether tests can run... yes checking that generated files are newer than configure... done configure: creating ./config.status config.status: creating Makefile config.status: creating backtrace-supported.h config.status: creating install-debuginfo-for-buildid.sh config.status: creating config.h config.status: executing libtool commands config.status: executing default commands Febbe@DESKTOP-VIRN68C UCRT64 ~/ianlancetaylor/libbacktrace/build $ make make all-am make[1]: Entering directory '/home/Febbe/ianlancetaylor/libbacktrace/build' /bin/sh ./libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I.. -funwind-tables -frandom-seed=atomic.lo -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -O2 -c -o atomic.lo ../atomic.c libtool: compile: gcc -DHAVE_CONFIG_H -I. -I.. -funwind-tables -frandom-seed=atomic.lo -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -O2 -c ../atomic.c -o atomic.o /bin/sh ./libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I.. -funwind-tables -frandom-seed=dwarf.lo -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -O2 -c -o dwarf.lo ../dwarf.c libtool: compile: gcc -DHAVE_CONFIG_H -I. -I.. -funwind-tables -frandom-seed=dwarf.lo -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -O2 -c ../dwarf.c -o dwarf.o /bin/sh ./libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I.. -funwind-tables -frandom-seed=fileline.lo -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -O2 -c -o fileline.lo ../fileline.c libtool: compile: gcc -DHAVE_CONFIG_H -I. -I.. -funwind-tables -frandom-seed=fileline.lo -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -O2 -c ../fileline.c -o fileline.o ../fileline.c: In function 'windows_get_executable_path': ../fileline.c:183:66: warning: unused parameter 'error_callback' [-Wunused-parameter] 183 | windows_get_executable_path (char *buf, backtrace_error_callback error_callback, | ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~ ../fileline.c:184:36: warning: unused parameter 'data' [-Wunused-parameter] 184 | void *data) | ~~~~~~^~~~ /bin/sh ./libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I.. -funwind-tables -frandom-seed=posix.lo -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -O2 -c -o posix.lo ../posix.c libtool: compile: gcc -DHAVE_CONFIG_H -I. -I.. -funwind-tables -frandom-seed=posix.lo -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -O2 -c ../posix.c -o posix.o /bin/sh ./libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I.. -funwind-tables -frandom-seed=print.lo -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -O2 -c -o print.lo ../print.c libtool: compile: gcc -DHAVE_CONFIG_H -I. -I.. -funwind-tables -frandom-seed=print.lo -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -O2 -c ../print.c -o print.o /bin/sh ./libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I.. -funwind-tables -frandom-seed=sort.lo -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -O2 -c -o sort.lo ../sort.c libtool: compile: gcc -DHAVE_CONFIG_H -I. -I.. -funwind-tables -frandom-seed=sort.lo -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -O2 -c ../sort.c -o sort.o /bin/sh ./libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I.. -funwind-tables -frandom-seed=state.lo -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -O2 -c -o state.lo ../state.c libtool: compile: gcc -DHAVE_CONFIG_H -I. -I.. -funwind-tables -frandom-seed=state.lo -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -O2 -c ../state.c -o state.o /bin/sh ./libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I.. -funwind-tables -frandom-seed=backtrace.lo -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -O2 -c -o backtrace.lo ../backtrace.c libtool: compile: gcc -DHAVE_CONFIG_H -I. -I.. -funwind-tables -frandom-seed=backtrace.lo -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -O2 -c ../backtrace.c -o backtrace.o /bin/sh ./libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I.. -funwind-tables -frandom-seed=simple.lo -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -O2 -c -o simple.lo ../simple.c libtool: compile: gcc -DHAVE_CONFIG_H -I. -I.. -funwind-tables -frandom-seed=simple.lo -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -O2 -c ../simple.c -o simple.o /bin/sh ./libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I.. -funwind-tables -frandom-seed=pecoff.lo -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -O2 -c -o pecoff.lo ../pecoff.c libtool: compile: gcc -DHAVE_CONFIG_H -I. -I.. -funwind-tables -frandom-seed=pecoff.lo -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -O2 -c ../pecoff.c -o pecoff.o /bin/sh ./libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I.. -funwind-tables -frandom-seed=read.lo -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -O2 -c -o read.lo ../read.c libtool: compile: gcc -DHAVE_CONFIG_H -I. -I.. -funwind-tables -frandom-seed=read.lo -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -O2 -c ../read.c -o read.o /bin/sh ./libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I.. -funwind-tables -frandom-seed=alloc.lo -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -O2 -c -o alloc.lo ../alloc.c libtool: compile: gcc -DHAVE_CONFIG_H -I. -I.. -funwind-tables -frandom-seed=alloc.lo -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -O2 -c ../alloc.c -o alloc.o /bin/sh ./libtool --tag=CC --mode=link gcc -funwind-tables -frandom-seed=libbacktrace.la -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -O2 -o libbacktrace.la -rpath /ucrt64/lib atomic.lo dwarf.lo fileline.lo posix.lo print.lo sort.lo state.lo backtrace.lo simple.lo pecoff.lo read.lo alloc.lo libtool: link: warning: undefined symbols not allowed in x86_64-w64-mingw32 shared libraries libtool: link: ar cru .libs/libbacktrace.a atomic.o dwarf.o fileline.o posix.o print.o sort.o state.o backtrace.o simple.o pecoff.o read.o alloc.o C:\msys64\ucrt64\bin\ar.exe: `u' modifier ignored since `D' is the default (see `U') libtool: link: ranlib .libs/libbacktrace.a libtool: link: ( cd ".libs" && rm -f "libbacktrace.la" && cp -pR "../libbacktrace.la" "libbacktrace.la" ) make[1]: Leaving directory '/home/Febbe/ianlancetaylor/libbacktrace/build' Febbe@DESKTOP-VIRN68C UCRT64 ~/ianlancetaylor/libbacktrace/build $ make test_pecoff.exe gcc -DHAVE_CONFIG_H -I. -I.. -funwind-tables -frandom-seed=test_pecoff-test_format.o -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -g -O2 -c -o test_pecoff-test_format.o `test -f 'test_format.c' || echo '../'`test_format.c gcc -DHAVE_CONFIG_H -I. -I.. -funwind-tables -frandom-seed=test_pecoff-testlib.o -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -g -O2 -c -o test_pecoff-testlib.o `test -f 'testlib.c' || echo '../'`testlib.c /bin/sh ./libtool --tag=CC --mode=link gcc -funwind-tables -frandom-seed=libbacktrace_noformat.la -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -O2 -o libbacktrace_noformat.la atomic.lo dwarf.lo fileline.lo posix.lo print.lo sort.lo state.lo backtrace.lo simple.lo read.lo alloc.lo libtool: link: ar cru .libs/libbacktrace_noformat.a atomic.o dwarf.o fileline.o posix.o print.o sort.o state.o backtrace.o simple.o read.o alloc.o C:\msys64\ucrt64\bin\ar.exe: `u' modifier ignored since `D' is the default (see `U') libtool: link: ranlib .libs/libbacktrace_noformat.a libtool: link: ( cd ".libs" && rm -f "libbacktrace_noformat.la" && cp -pR "../libbacktrace_noformat.la" "libbacktrace_noformat.la" ) /bin/sh ./libtool --tag=CC --mode=link gcc -funwind-tables -frandom-seed=test_pecoff.exe -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -g -O2 -o test_pecoff.exe test_pecoff-test_format.o test_pecoff-testlib.o libbacktrace_noformat.la pecoff.lo libtool: link: gcc -funwind-tables -frandom-seed=test_pecoff.exe -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wcast-qual -g -g -O2 -o test_pecoff.exe test_pecoff-test_format.o test_pecoff-testlib.o pecoff.o ./.libs/libbacktrace_noformat.a $ ./test_pecoff.exe && (echo successfully) || echo failed successfully ```

Tested it also in PS C:\msys64\home\Febbe\ianlancetaylor\libbacktrace\build> C:\msys64\home\Febbe\ianlancetaylor\libbacktrace\build\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\aaaaaaaaaaaaaaaaaaaaaaaaaaaa\test_pecoff.exe (259 characters, 260 with \0)

~To test longer paths, I have to edit the registry and restart my computer, brb...~ For longer paths, it falls back to the other variants, just like expected (fails with could not find executable to open).

0001-Rebased-Ian-s-patch.patch

HazardyKnusperkeks commented 11 months ago

Thanks. Those patches have not been committed upstream. I've been waiting for someone to confirm that the modified version that I wrote works.

https://gcc.gnu.org/pipermail/gcc-patches/2023-January/610540.html https://gcc.gnu.org/pipermail/gcc-patches/2023-February/611407.html

Can you check that modified patch? Thanks.

I did not come to that, because frankly the GCC review process is tiresome for me. They are basically working (I'm using the patched GCC since my initial proposal), but for GCC 13 I had to adapt Patch 2.