Date: Thu, 18 Oct 2018 16:43:40 -0700 From: Mark Millard <marklmi@yahoo.com> To: FreeBSD Toolchain <freebsd-toolchain@freebsd.org>, FreeBSD <freebsd-hackers@freebsd.org>, freebsd-arch@freebsd.org Cc: FreeBSD PowerPC ML <freebsd-ppc@freebsd.org> Subject: Re: What is incomplete for /lib/libgcc_s.so-based C++ exception handling (where WITH_LLVM_LIBUNWIND= and /usr/local/lib/gcc*/libgcc_s.so are not used) Message-ID: <B8C7F4C3-C077-4166-86D4-180EF23F4905@yahoo.com> In-Reply-To: <0379371E-0541-42DD-93EF-BEE2E9DE3FBC@yahoo.com> References: <0379371E-0541-42DD-93EF-BEE2E9DE3FBC@yahoo.com>
next in thread | previous in thread | raw e-mail | index | archive | help
[I add a note indicating that clang++ does generate examples of DW_CFA_remember_state and DW_CFA_restore_state use for pwoerpc64 that lead to /lib/libgcc_s.so messing up the exception handling.] On 2018-Oct-17, at 1:25 PM, Mark Millard <marklmi@yahoo.com> wrote: > [This summarizes other results without the code > and debugger evidence and such from my recent > explorations. It should be much easier to > follow than my exploration reports.] >=20 > Documents like DWARF5.pdf document the "row" vs. Location > information for Call Frame Information as (also used > for .eh_frame like materials for C++ exception handling): > (CFA: Cannonical Frame Address) >=20 > QUOTE ("Structure of Call Frame Information") > LOC CFA R0 R1...RN >=20 > L0 >=20 > L1 >=20 > ... >=20 > LN > END QUOTE >=20 > Note that the CFA is conceptually one of the > registers in each row, even though it is not a > machine register but a way to calculate the > conceptual register's value from machine > registers. >=20 > The information for the machine registers are > typically based on the earlier CFA value (from > the same row!). Absent a correct CFA cell in > a row, most potential use of that row is likely > messed up. >=20 > One way CFA is found is by adding an offset to > the value of a machine register for the range > in question, Ln up to L(n+1) [or based on the > end of the overall range for the last Ln]. I > will use that for illustration because there > are examples of this in my testing. >=20 > /lib/libgcc_s.so.1 does not implement this > fully for some DW_CFA_* operations: >=20 > QUOTE (note the "every register" reference, so including CFA) > DW_CFA_remember_state >=20 > The DW_CFA_remember_state instruction takes no operands. The required = action is to push the set of rules for every register onto an implicit = stack. >=20 > DW_CFA_restore_state >=20 > The DW_CFA_restore_state instruction takes no operands. The required = action is to pop the set of rules off the implicit stack and place them = in the current row. > END QUOTE >=20 > In other words: push and pop a complete row, > not just machine registers information from > the row. >=20 > For example, the the "cfa_offset" for computing the CFA > value from from a register is not saved and restored. > Nor is which register the offset is based on. (This > can vary, though not in my examples.) In general the > CFA cell is not saved and restored, what ever its > contents. >=20 > So any compiler that produces code depending on > DW_CFA_remember_state and DW_CFA_restore_state > for .eh_frame like material ends up with C++ > exception handling messed up when the > DW_CFA_restore_state should change the CFA to a=20 > non-default one (from the prior > DW_CFA_remember_state). >=20 > This prevents reliable use of throwing C++ exceptions > when building via the likes of devel/powerpc64-gcc > or lang/gcc8 ( when not using > -Wl,-rpath=3D-Wl,-rpath=3D/usr/local/lib/gcc8 so that > /lib/libgcc_s.so.1 ends up being used). One result > can be _Unwind_RaiseException looping looking at > the same frame over and over instead of progressing > to the next frame. For example, this happens via > cfa_offset 0 being used. devel/powerpc64-gcc -O2 > code tends to get that. >=20 >=20 > Notes: >=20 > For powerpc64, clang++ tends to use another register > (%r31) with the old value (of %r1, the stack pointer) > instead of involving the > DW_CFA_remember_state/DW_CFA_restore_state pair > based on just %r1. (clang has other problems > relative to sue for buildworld buildkernel.) /usr/tests/lib/atf/libatf-c++/detail/exceptions_test has examples were clang++ generated use of DW_CFA_remember_state and DW_CFA_restore_state and /lib/libgcc_s.so 's _Unwind_RaiseException ends up stuck looping. There are other examples as well. The problem is not limited to devel/powerpc64-gcc or other g++ use that uses /lib/libgcc_s.so . > Code generation styles matter for if the incomplete > coverage by /lib/libgcc_s.so will be visible or not. >=20 > At this stage, WITH_LLVM_LIBUNWIND=3D builds > targeting powerpc64 do not even compile/assemble > the relevant code, apparently both because of > darwin specific assembler code and FreeBSD's build > not using the C-preprocessor on the .S file as > required. (There could be more to getting it > working.) >=20 > I do not know about other architecture/compiler > (or toolchain) combinations that may not yet be > able to use WITH_LLVM_LIBUNWIND=3D . But I'd > expect a potentially similar status from some. >=20 > A range of modern /usr/local/lib/gcc*/libgcc_s.so > do implement DW_CFA_remember_state/DW_CFA_restore_state > operations and they are put to use. So using the likes > of -Wl,-rpath=3D/usr/local/lib/gcc8 works for g++8 C++ > exception handling (but is problematical for buildworld > buildkernel). >=20 > I made a similar exploration of the issue in around > early 2016 and got basically the same results, not that > I remembered much. But I now have a small source code > example that shows the cfa_offset issue for the likes > of devel/powerpc64-gcc output. >=20 > The standard source for throw_exception in > /lib/libgcc_s.so produces the cfa_offset problem > when devel/powerpc64-gcc is used to buildworld. > This turns all thrown C++ exceptions in to > unbounded looping in _Unwind_RaiseException for > that kind of context. =3D=3D=3D Mark Millard marklmi at yahoo.com ( dsl-only.net went away in early 2018-Mar)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?B8C7F4C3-C077-4166-86D4-180EF23F4905>