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 <iostream>

        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
_______________________________________________
freebsd-toolchain@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-toolchain
To unsubscribe, send any mail to "freebsd-toolchain-unsubscr...@freebsd.org"

Reply via email to