NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: lib/55719 (Unwind tables for signal trampoline on amd64 are incorrect)



On Mon, Oct 19, 2020 at 7:45 AM Kamil Rytarowski <n54%gmx.com@localhost> wrote:
 While there, I'm getting the following backtrace for NetBSD/i386:

 Backtrace 6 stack frames.
 0x8048972 <handler+0x2d> at ./a.out
 0xfbd93010 <__sigtramp_siginfo_2> at /usr/lib/i386/libc.so.12
 0x804899e <run1> at ./a.out
 0x80489a5 <run3> at ./a.out
 0x80489aa <run3+0x5> at ./a.out
 0x80489de <__x86.get_pc_thunk.ax> at ./a.out

 for "gcc -fomit-frame-pointer  -O3 test.c -lexecinfo -m32". Is this
 correct? I don't see <main> over there.

 http://netbsd.org/~kamil/backtrace/libc-i386-PR55719-multiple-frames.txt

Sorry for the slow reply. I finally got the chance to look into this and I think
figured out what is going on. It is a classic case of GCC being too clever. Here
is the disassembly of your test program:

0804899e <run1>:
 804899e:       eb fe                   jmp    804899e <run1>

080489a0 <run2>:
 80489a0:       e8 f9 ff ff ff          call   804899e <run1>

080489a5 <run3>:
 80489a5:       e8 f6 ff ff ff          call   80489a0 <run2>
 80489aa:       66 90                   xchg   %ax,%ax
 80489ac:       66 90                   xchg   %ax,%ax
 80489ae:       66 90                   xchg   %ax,%ax
 80489b0:       e8 eb fa ff ff          call   80484a0 <abort@plt>
 80489b5:       89 fb                   mov    %edi,%ebx
 80489b7:       e8 e4 fa ff ff          call   80484a0 <abort@plt>

080489bc <main>:
 80489bc:       55                      push   %ebp
 80489bd:       89 e5                   mov    %esp,%ebp
 80489bf:       83 e4 f0                and    $0xfffffff0,%esp
 80489c2:       83 ec 10                sub    $0x10,%esp
 80489c5:       c7 44 24 04 45 89 04    movl   $0x8048945,0x4(%esp)
 80489cc:       08
 80489cd:       c7 04 24 02 00 00 00    movl   $0x2,(%esp)
 80489d4:       e8 e7 fa ff ff          call   80484c0 <signal@plt>
 80489d9:       e8 c7 ff ff ff          call   80489a5 <run3>

080489de <__x86.get_pc_thunk.ax>:
 80489de:       8b 04 24                mov    (%esp),%eax
 80489e1:       c3                      ret

Notice how none of the functions have ret instructions. I guess GCC has realized
that all of them terminate in the infinite loop in run1. So when the unwinder
tries to unwind from run3, it ends up falling off the end of main and into
the __x86.get_pc_thunk.ax function instead, due to that (ra + 1) hack we were
discussing previously.

A very simple change to inhibit this optimatization...

diff -u test.c test2.c
--- test.c      2020-11-02 04:49:00.693887594 +0000
+++ test2.c     2020-11-02 04:48:33.693998384 +0000
@@ -14,10 +14,12 @@
         backtrace_symbols_fd (array, size, 2);
 }
+volatile int v;
+
 __attribute__ ((noinline))
 int
 run1(void) {
-       for (;;)
+       for (v = 1; v;)
                 continue;
 }
...results in the correct backtraces:

$ ./a.out
^Cx 2
Backtrace 4 stack frames.
0x8048972 <handler+0x2d> at ./a.out
0xf4c3c0c0 <__sigtramp_siginfo_2> at /usr/lib/i386/libc.so.12
0x80489a8 <run1+0xa> at ./a.out
0x80489ee <main+0x22> at ./a.out

And the assembly, as you would expect, includes the ret instructions:

080489cc <main>:
 80489cc:       55                      push   %ebp
 80489cd:       89 e5                   mov    %esp,%ebp
 80489cf:       83 e4 f0                and    $0xfffffff0,%esp
 80489d2:       83 ec 10                sub    $0x10,%esp
 80489d5:       c7 44 24 04 45 89 04    movl   $0x8048945,0x4(%esp)
 80489dc:       08
 80489dd:       c7 04 24 02 00 00 00    movl   $0x2,(%esp)
 80489e4:       e8 d7 fa ff ff          call   80484c0 <signal@plt>
 80489e9:       e8 c6 ff ff ff          call   80489b4 <run3>
 80489ee:       31 c0                   xor    %eax,%eax
 80489f0:       c9                      leave
 80489f1:       c3                      ret

I'm not sure there is anything that can be done about this. This seems like a flaw
inherent to the design of the DWARF-based unwinders. At the very least, analyzing
and fixing this properly exceeds my expertise.

Thanks again for getting the earlier unwinding patches committed so quickly,
Kamil. gccgo is working great on NetBSD now as a result.

Cheers,
Nikhil



Home | Main Index | Thread Index | Old Index