From owner-freebsd-toolchain@freebsd.org Wed May 24 11:44:13 2017 Return-Path: Delivered-To: freebsd-toolchain@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id E4C02D7B51F; Wed, 24 May 2017 11:44:13 +0000 (UTC) (envelope-from rdivacky@vlakno.cz) Received: from vlakno.cz (mail.vlakno.cz [91.217.96.224]) by mx1.freebsd.org (Postfix) with ESMTP id B2202105A; Wed, 24 May 2017 11:44:13 +0000 (UTC) (envelope-from rdivacky@vlakno.cz) Received: by vlakno.cz (Postfix, from userid 1002) id D842E1C7FF01; Wed, 24 May 2017 13:34:41 +0200 (CEST) Date: Wed, 24 May 2017 13:34:41 +0200 From: Roman Divacky To: freebsd-toolchain@freebsd.org Cc: freebsd-ppc@freebsd.org, markmi@dsl-only.net Subject: PowerPC64 C++ exceptions with clang/llvm Message-ID: <20170524113441.GA58092@vlakno.cz> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.8.2 (2017-04-18) X-BeenThere: freebsd-toolchain@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Maintenance of FreeBSD's integrated toolchain List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 24 May 2017 11:44:14 -0000 Hi, Currently C++ exceptions don't work on PowerPC64 when compiled with clang. I looked at why and discovered the following. With the default gcc unwinder and libstdc++ this simple test program: #include int main() { try { std::cout << "Before\n"; throw std::exception(); std::cout << "After\n"; } catch (...) { std::cout << "Exception\n"; } } segfaults right after printing "Before\n". This is because the .eh_frame is corrupted and the personality relocation is wrong: < 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 bytes of initial instructions 3 cie length 28 initial instructions 0 DW_CFA_def_cfa r1 0 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. I verified this theory by hacking the gcc unwinder and libsupc++ &= 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). 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. 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. 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. I didn't try the situation with the LLVM unwinder and libcxxrt, but I hope it might be the same. Thank you, Roman