Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

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

Closed Quuxplusone closed 4 years ago

Quuxplusone commented 5 years ago
Bugzilla Link PR43350
Status RESOLVED FIXED
Importance P enhancement
Reported by Alfredo Dal'Ava Júnior (alfredo.junior@eldorado.org.br)
Reported on 2019-09-18 05:03:13 -0700
Last modified on 2020-01-25 23:14:46 -0800
Version unspecified
Hardware PC Linux
CC chmeeedalf@gmail.com, i@maskray.me, llvm-bugs@lists.llvm.org, luporl@FreeBSD.org, smithp352@googlemail.com
Fixed by commit(s)
Attachments 43350.tar.xz (833636 bytes, application/x-xz)
43350-artifacts.tar.xz (41772 bytes, application/x-xz)
Blocks
Blocked by
See also
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 <iostream>
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)
Quuxplusone commented 5 years ago

Attached 43350.tar.xz (833636 bytes, application/x-xz): Reproduce tar

Quuxplusone commented 5 years ago

Attached 43350-artifacts.tar.xz (41772 bytes, application/x-xz): source, binaries and core

Quuxplusone 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=<optimized out>, env=<optimized out>,
obj=<optimized out>, cleanup=0x5003d254 <rtld_nop_exit>, 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
Quuxplusone commented 5 years ago
(In reply to Alfredo Dal'Ava Júnior from comment #3)

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.
Quuxplusone 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).
Quuxplusone 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
}
Quuxplusone 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?

Quuxplusone commented 4 years ago

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

Tested by Bdragon.