Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 24 May 2017 21:03:52 -0700
From:      Mark Millard <markmi@dsl-only.net>
To:        Roman Divacky <rdivacky@freebsd.org>
Cc:        FreeBSD Toolchain <freebsd-toolchain@freebsd.org>, freebsd-ppc@freebsd.org
Subject:   Re: PowerPC64 C++ exceptions with clang/llvm
Message-ID:  <74D091B2-71CD-42DE-8C1E-8E0BDED1EAFD@dsl-only.net>
In-Reply-To: <20170524113441.GA58092@vlakno.cz>
References:  <20170524113441.GA58092@vlakno.cz>

next in thread | previous in thread | raw e-mail | index | archive | help
[So far I've been unable to replicate dwarfump reporting
anything near "0x94 00 00 00 01 00 01 02 ed 14 1b". The
compiled code still gets SIGSEGV: it is only the low
level detail that I'm noting as different. Roman has
more information from me than I show here.]

On 2017-May-24, at 4:34 AM, Roman Divacky <rdivacky@freebsd.org> wrote:

> Hi,
>=20
> Currently C++ exceptions don't work on PowerPC64 when compiled with =
clang. I
> looked at why and discovered the following.
>=20
> With the default gcc unwinder and libstdc++ this simple test program:
>=20
> #include <iostream>
>=20
> 	int main()
> 	{
> 	  try {
> 	    std::cout << "Before\n";
> 	    throw std::exception();
> 	    std::cout << "After\n";
> 	  } catch (...) {
> 	    std::cout << "Exception\n";
> 	  }
> 	}
>=20
> segfaults right after printing "Before\n". This is because the =
.eh_frame is corrupted and
> the personality relocation is wrong:
>=20
> <    1>	version				1
> 	cie section offset		56 0x00000038
> 	augmentation			zPLR
> 	code_alignment_factor		4
> 	data_alignment_factor		-8
> 	return_address_register		65
> 	eh aug data len 0xb bytes 0x94 00 00 00 01 00 01 02 ed 14 1b=20

So far I'm unable to replicate producing anything like
the "large one" as I'll call it.

I get things like:

# clang++ -std=3Dc++11 exception_test_dots.cpp
# dwarfdump -v -v -F a.out | more

.eh_frame
. . .
cie:
<    0> version                         1
. . .
        eh aug data len 0xb bytes 0x94 00 00 00 00 00 01 03 45 14 1b=20
. . .

(No cia<1> at all.)

and like:

# clang++ -B /usr/local/bin/ -std=3Dc++11 exception_test_dots.cpp
# dwarfdump -v -v -F a.out | more

.eh_frame
. . .
cie:
<    0> version                         1
. . .
<    1> version                         1
. . .
        eh aug data len 0xb bytes 0x94 00 00 00 00 00 01 f1 1d 14 1b=20
. . .

My context is head -r317820 on a system built with
the system clang without building gcc 4.2.1 materials.

# uname -paKU
FreeBSD FBSDG5L 12.0-CURRENT FreeBSD 12.0-CURRENT  r317820M  powerpc =
powerpc64 1200030 1200030

# ld --version
GNU ld 2.17.50 [FreeBSD] 2007-07-03
Copyright 2007 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms =
of
the GNU General Public License.  This program has absolutely no =
warranty.

# /usr/local/bin/ld --version
GNU ld (GNU Binutils) 2.27
Copyright (C) 2016 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms =
of
the GNU General Public License version 3 or (at your option) a later =
version.
This program has absolutely no warranty.

(I have avoided 2.28 so far because of the
"return code" consequences on the likes of
aarch64.)

I've tried variations like omitting -std=3Dc++11.
So far I've not found a way to get near:

"0x94 00 00 00 01 00 01 02 ed 14 1b"

but all the experiments get SIGSEGV when
I run the produced program.

(I do not have a gcc 4.2.1 build around and so
do not have libstdc++ on powerpc64.)

> 	bytes of initial instructions	3
> 	cie length			28
> 	initial instructions
> 	 0 DW_CFA_def_cfa r1 0
>=20
> the personality relocation is "00 00 00 01 00 01 02 ed" encoded as pc =
relative. The program segfaults
> because this address is wrong. The 33rd bit is incorrect, the real =
address should be "00 00 00 00 00 01 02 ed".
> The same problem applies for LDSA encoding. Both personality and LDSA =
relocations are produced by CFI instructions
> in the assembler source code.
>=20
> I verified this theory by hacking the gcc unwinder and libsupc++ &=3D =
the address with 0xffffffff; and that made
> the application work. (the full patch can be found at =
http://www.vlakno.cz/~rdivacky/ppc64.exceptions.hack.patch).
>=20
> I checked why this relocation is wrong and it turns out it's our old =
in-tree ld that (wrongly) produces this.
> Our old gcc does not use CFI to produce these and hardcodes the CIE =
manually and produces correct address. And for
> some reason ld is fine with that.
>=20
> When I compile and assemble the above source code using clang++ and =
only use newer ld linker from ports the resulting
> binary is correct and works as expected.
>=20
> So this is a bug in our in-tree ld linker. I don't know why ld has =
this bug but given Mark Millard's report of ld
> being broken for other stuff (kernel iirc) I am not going to bother =
trying to fix it. I suspect it might be related
> to comdats but I didn't really investigate.
>=20
> I didn't try the situation with the LLVM unwinder and libcxxrt, but I =
hope it might be the same.


Side note:

Why I'm at head -r317820 . . .

For TARGET_ARCH=3Dpowerpc I've got a
periodic panic after booting for which
changing the memory layout even a
little bit seems to stop the panic.
(Something less obvious may still be
wrong.)

The panic can take minutes but usually
is more like hours.

Even attempting to add small amounts of
debug code tends to make the problem
invisible.

Thus a binary search for versions is not
in the cards for now.

So I've been focusing on trying for
evidence about what leads to the panic
and I've not been updating any of the
FreeBSD environments that I have around.


=3D=3D=3D
Mark Millard
markmi at dsl-only.net




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?74D091B2-71CD-42DE-8C1E-8E0BDED1EAFD>