Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 5 Mar 2022 23:33:54 +0100
From:      Dimitry Andric <dim@FreeBSD.org>
To:        Tomoaki AOKI <junchoon@dec.sakura.ne.jp>
Cc:        John Baldwin <jhb@freebsd.org>, Ed Maste <emaste@freebsd.org>, dev-commits-src-branches@freebsd.org, David Chisnall <theraven@FreeBSD.org>
Subject:   Re: git: b2127b6f1ae2 - stable/13 - Install unwind.h into /usr/include
Message-ID:  <682D0394-CDC8-44AB-B9FF-2B969AE2D39A@FreeBSD.org>
In-Reply-To: <7482C54A-1128-4AFF-A74E-53D88334C1D9@FreeBSD.org>
References:  <20220303224535.a0cca57e1f033e930a7f8f9d@dec.sakura.ne.jp> <3166E99F-1616-40D9-BD8B-D18E8104D6FF@FreeBSD.org> <a9863238-04e5-381d-105d-311a2b0c3f56@FreeBSD.org> <6E5AD771-3140-480A-BF20-95B8E8A27189@FreeBSD.org> <20220305113613.7760bb3845cda1c04707fb34@dec.sakura.ne.jp> <7482C54A-1128-4AFF-A74E-53D88334C1D9@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help

--Apple-Mail=_28BBF4CC-1A41-4611-B0D4-5D22F7DBCFD7
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;
	charset=us-ascii

On 5 Mar 2022, at 22:34, Dimitry Andric <dim@FreeBSD.org> wrote:
>=20
> On 5 Mar 2022, at 03:36, Tomoaki AOKI <junchoon@dec.sakura.ne.jp> =
wrote:
...
> So according to the spec, casting the void pointer 'thrown_exception' =
to
> a __cxa_exception pointer, then subtracting 1, should give you the
> original __cxa_exception struct. In this case, it subtracts 8 bytes,
> going from 0x87b5aff00 to 0x87b5afe88.

Ugh, actually this was 120 bytes!


> Now I do exactly the same in the libreoffice frame one below, where =
the
> incoming void pointer 'pExc' is the previous 'thrown_exception' value:
>=20
> (gdb) frame 1
> #1  gcc3::deleteException (pExc=3D0x87b5aff00) at =
bridges/source/cpp_uno/gcc3_linux_x86-64/except.cxx:139
> 139         OUString unoName( toUNOname( header->exceptionType->name() =
) );
> (gdb) print pExc
> $33 =3D (void *) 0x87b5aff00
> (gdb) print static_cast<__cxa_exception*>(pExc)-1
> $34 =3D (__cxa_exception *) 0x87b5afe80
>=20
> So in *this* function, subtracting 1 from a __cxa_exception pointer
> subtracts 16 bytes instead, going from 0x87b5aff00 to 0x87b5afe80!

And this was 128 bytes instead. I think I now know what's going on,
which is that our declaration of __cxa_exception changed its size from
120 bytes to 128 bytes, due to the new unwind headers.

Our libcxxrt cxxabi.h header has:

  struct __cxa_exception
  {
  ... lots of stuff ...
          /** The language-agnostic part of the exception header. */
          _Unwind_Exception unwindHeader;
  };

so the last field is a struct _Unwind_Exception. Our libcxxrt
unwind-itanium.h header has:

  struct _Unwind_Exception
    {
      uint64_t exception_class;
      _Unwind_Exception_Cleanup_Fn exception_cleanup;
      unsigned long private_1;
      unsigned long private_2;
    } ;

while libunwind's version has an __aligned__ attribute at the end:

  struct _Unwind_Exception {
    uint64_t exception_class;
    void (*exception_cleanup)(_Unwind_Reason_Code reason,
                              _Unwind_Exception *exc);
  #if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
    uintptr_t private_[6];
  #else
    uintptr_t private_1; // non-zero means forced unwind
    uintptr_t private_2; // holds sp that phase1 found for phase2 to use
  #endif
  #if __SIZEOF_POINTER__ =3D=3D 4
    // The implementation of _Unwind_Exception uses an attribute mode on =
the
    // above fields which has the side effect of causing this whole =
struct to
    // round up to 32 bytes in size (48 with SEH). To be more explicit, =
we add
    // pad fields added for binary compatibility.
    uint32_t reserved[3];
  #endif
    // The Itanium ABI requires that _Unwind_Exception objects are =
"double-word
    // aligned".  GCC has interpreted this to mean "use the maximum =
useful
    // alignment for the target"; so do we.
  } __attribute__((__aligned__));

(Note that upstream libcxxrt also added the reserved field and aligned
attribute, in https://github.com/libcxxrt/libcxxrt/commit/b9616964 !)

The aligned attribute on _Unwind_Exception causes the enclosing
__cxa_exception struct to *also* be aligned maximally, growing it from
120 to 128 bytes on x86_64.

So this is a bit of a fine mess we are in. There are multiple issues
here:

1) We broke the ABI by increasing __cxa_exception's size.

2) We compile libcxxrt against its *own* unwind headers, so it assumes a
120-byte __cxa_exception size. But all other programs use the libunwind
headers, so they assume a 128 byte __cxa_exception size.

I guess LibreOffice is just a good example which breaks because it does
this deep poking in exception-handling land, which most programs never
go near. That said, LibreOffice also includes the unwind.h header
installed by the libunwind-20201110 port, so that is yet *another*
possible incompatibility!

But I think we must do something about this. The most backward
compatible change would be to *remove* the aligned attribute from our
_Unwind_Exception declaration, so the old __cxa_exception size is
restored. The problem with that is that we have to carry a patch for
libunwind forever.

The other way would be to force libcxxrt to use the libunwind headers
instead of its own, so that at least libcxxrt and libunwind agree on the
size and alignment of all these structures! But that may still lead to
crashes for older consumers.

No easy way out, in any case... :-/

-Dimitry


--Apple-Mail=_28BBF4CC-1A41-4611-B0D4-5D22F7DBCFD7
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filename=signature.asc
Content-Type: application/pgp-signature;
	name=signature.asc
Content-Description: Message signed with OpenPGP

-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.2

iF0EARECAB0WIQR6tGLSzjX8bUI5T82wXqMKLiCWowUCYiPlUgAKCRCwXqMKLiCW
o2HlAJwLP2bK9/Q29JMrbeIz95neJTf4ggCfUQdNUwOVmgkNcpPGZ/9safz51As=
=/Csr
-----END PGP SIGNATURE-----

--Apple-Mail=_28BBF4CC-1A41-4611-B0D4-5D22F7DBCFD7--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?682D0394-CDC8-44AB-B9FF-2B969AE2D39A>