Skip site navigation (1)Skip section navigation (2)
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>