llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.42k stars 11.74k forks source link

[PowerPC32] segmentation fault on C++ exception handling #42695

Closed 688cc089-1a96-4cb4-bd77-eaf433fc1da2 closed 4 years ago

688cc089-1a96-4cb4-bd77-eaf433fc1da2 commented 5 years ago
Bugzilla Link 43350
Resolution FIXED
Resolved on Jan 25, 2020 23:14
Version unspecified
OS Linux
Attachments Reproduce tar, source, binaries and core
CC @chmeeedalf,@MaskRay,@luporl,@smithp35

Extended Description

On FreeBSD powerpc64 using 32 bit compatibility libraries (LIB32), C++ exception handling is broken when application is compiled with CLANG9 and linked with LLD9. Same application linked with BFD 2.17 works properly:

include using namespace std;

int main () { try { throw 20; } catch (int e) { cout << "An exception occurred. Exception Nr. " << e << '\n'; } return 0; }

root@alfredo-2:~/test/except # ./except32.bfd An exception occurred. Exception Nr. 20

root@alfredo-2:~/test/except # ./except32.lld Segmentation fault (core dumped)

MaskRay commented 4 years ago

Fixed by https://reviews.llvm.org/D73399 . Will be included in lld 10.

Tested by Bdragon.

688cc089-1a96-4cb4-bd77-eaf433fc1da2 commented 5 years ago

Fangrui,

Now my test environment has LLVM9 fully integrated to FreeBSD base (clang900-import experimental branch) and found that passing arguments -fpic or -fPIC for clang will make it work. Without this application crashes with signal 5 (Trace/BPT trap)"

Should pic/PIC be implicit in this case or does it point to another bug?

MaskRay commented 5 years ago

The problem is similar to a previous bug report. There is no GOT-generating elocation (R_PPC_GOT16 R_PPC_GOT_TLSGD16 R_PPC_GOT_TLSLD16 R_PPC_GOT_TPREL16 ...).

% readelf -d except32.lld | grep PPC_GOT 0x70000000 (PPC_GOT) 0x0

// lld/ELF/SyntheticSections.cpp bool GotSection::isNeeded() const { // We need to emit a GOT even if it's empty if there's a relocation that is // relative to GOT(such as GOTOFFREL). return numEntries || hasGotOffRel; // In our case, numEntries == 0 && !hasGotOffRel }

chmeeedalf commented 5 years ago

The problem is that LLD sets the DT_PPC_GOT to 0, where it should never be a NULL pointer on a ET_EXEC. Glibc, NetBSD ld-elf.so, and FreeBSD's ld-elf.so all key off this being non-NULL to get the real pointer to the GOT. Even on a ET_DYN object, it should never be NULL, because the GOT cannot be at the very beginning of the file (obviously, the very beginning is the header).

688cc089-1a96-4cb4-bd77-eaf433fc1da2 commented 5 years ago

Following the code, segmentation fault actually happens on bctr call at 0x1001086.

0x10010858 <00000000.plt_call32.atexit> lis r11,4099 (r11 is 0x5004ae62) 0x1001085c <00000000.plt_call32.atexit+4> lwz r11,4(r11) (r11 is 0x10030000) 0x10010860 <00000000.plt_call32.atexit+8> mtctr r11 (r11 is 0x39600000) 0x10010864 <00000000.plt_call32.atexit+12> bctr (r11 is 0x39600000)

So, it ends up with r11 = 0x39600000, that's is wrong.

688cc089-1a96-4cb4-bd77-eaf433fc1da2 commented 5 years ago

Reading symbols from except32.lld...done. [New LWP 100600] Core was generated by `./except32.lld'. Program terminated with signal SIGSEGV, Segmentation fault.

​0 0x39600000 in ?? ()

(gdb) bt

​0 0x39600000 in ?? ()

​1 0x100100b4 in _start (argc=1, argv=, env=, obj=, cleanup=0x5003d254 , ps_strings=0x0)

at /root/freebsd/lib/csu/powerpc/crt1.c:87

I set a breakpoint at offset 0x100100ac, as it crashes on next instruction:

0x100100b0 <_start+176> bl 0x10010858 <00000000.plt_call32.atexit>

Context is:

│ │0x10010088 <_start+136> b 0x10010068 <_start+104> │ │0x1001008c <_start+140> cmplwi r8,0 │ │0x10010090 <_start+144> beq 0x1001009c <_start+156> │ │0x10010094 <_start+148> lis r3,4099 │ │0x10010098 <_start+152> stw r8,100(r3) │ │0x1001009c <_start+156> lis r3,4098 │ │0x100100a0 <_start+160> addi r3,r3,20 │ │0x100100a4 <_start+164> cmplwi r3,0 │ │0x100100a8 <_start+168> beq 0x100100b8 <_start+184> │ B+ │0x100100ac <_start+172> mr r3,r7 │

│0x100100b0 <_start+176> bl 0x10010858 <00000000.plt_call32.atexit> │ │0x100100b4 <_start+180> b 0x100100bc <_start+188> │ │0x100100b8 <_start+184> bl 0x10010868 <00000000.plt_call32._init_tls> │ │0x100100bc <_start+188> mr r3,r28 │ │0x100100c0 <_start+192> mr r4,r29 │ │0x100100c4 <_start+196> mr r5,r30

688cc089-1a96-4cb4-bd77-eaf433fc1da2 commented 5 years ago

assigned to @MaskRay