Message ID | mvmin1qpd1z.fsf@suse.de |
---|---|
State | New |
Headers | show |
Series | RISC-V: properly terminate call chain | expand |
On Thu, 25 Oct 2018 02:53:44 PDT (-0700), schwab@suse.de wrote: > Mark the ra register as undefined in _start, so that unwinding through > main works correctly. Also, don't use a tail call so that ra points after > the call to __libc_start_main, not after the previous call. > > [BZ #23125] > * sysdeps/riscv/start.S (ENTRY_POINT): Mark ra as undefined. > Don't use tail call. > * elf/tst-unwind-main.c: New file. > * elf/Makefile (tests): Add tst-unwind-main. > (CFLAGS-tst-unwind-main.c): Define. > --- > elf/Makefile | 4 +++- > elf/tst-unwind-main.c | 38 ++++++++++++++++++++++++++++++++++++++ > sysdeps/riscv/start.S | 7 ++++++- > 3 files changed, 47 insertions(+), 2 deletions(-) > create mode 100644 elf/tst-unwind-main.c Thanks. Your original reply to my patch has been the top of my inbox for about 6 months now but I keep getting interrupted before I can actually write up the patch. > diff --git a/elf/Makefile b/elf/Makefile > index 455ec730fc..d277d34b17 100644 > --- a/elf/Makefile > +++ b/elf/Makefile > @@ -187,7 +187,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ > tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \ > tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \ > tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \ > - tst-unwind-ctor > + tst-unwind-ctor tst-unwind-main > # reldep9 > tests-internal += loadtest unload unload2 circleload1 \ > neededtest neededtest2 neededtest3 neededtest4 \ > @@ -1495,3 +1495,5 @@ $(objpfx)tst-libc_dlvsym-static.out: $(objpfx)tst-libc_dlvsym-dso.so > $(objpfx)tst-big-note: $(objpfx)tst-big-note-lib.so > > $(objpfx)tst-unwind-ctor: $(objpfx)tst-unwind-ctor-lib.so > + > +CFLAGS-tst-unwind-main.c += -funwind-tables > diff --git a/elf/tst-unwind-main.c b/elf/tst-unwind-main.c > new file mode 100644 > index 0000000000..d1236032d7 > --- /dev/null > +++ b/elf/tst-unwind-main.c > @@ -0,0 +1,38 @@ > +/* Test unwinding through main. > + Copyright (C) 2018 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <http://www.gnu.org/licenses/>. */ > + > +#include <unwind.h> > +#include <unistd.h> > +#include <support/test-driver.h> > + > +static _Unwind_Reason_Code > +callback (struct _Unwind_Context *ctx, void *arg) > +{ > + return _URC_NO_REASON; > +} > + > +int > +main (void) > +{ > + /* Arrange for this test to be killed if _Unwind_Backtrace runs into an > + endless loop. We cannot use the test driver because the complete > + call chain needs to be compiled with -funwind-tables so that > + _Unwind_Backtrace is able to reach _start. */ > + alarm (DEFAULT_TIMEOUT); > + _Unwind_Backtrace (callback, 0); > +} > diff --git a/sysdeps/riscv/start.S b/sysdeps/riscv/start.S > index 4635ddb5eb..ba3e2cf16c 100644 > --- a/sysdeps/riscv/start.S > +++ b/sysdeps/riscv/start.S > @@ -43,6 +43,10 @@ > __libc_start_main wants this in a5. */ > > ENTRY (ENTRY_POINT) > + /* Terminate call stack by noting ra is undefined. Use a dummy > + .cfi_label to force starting the FDE. */ > + .cfi_label .Ldummy > + cfi_undefined (ra) > call .Lload_gp > mv a5, a0 /* rtld_fini. */ > /* main may be in a shared library. */ > @@ -54,7 +58,8 @@ ENTRY (ENTRY_POINT) > lla a4, __libc_csu_fini > mv a6, sp /* stack_end. */ > > - tail __libc_start_main@plt > + call __libc_start_main@plt > + unimp > END (ENTRY_POINT) > > /* Dynamic links need the global pointer to be initialized prior to calling GCC will emit an 'ebreak' when it sees unreachable code on RISC-V, for example $ cat test.c int main() { int *ptr = 0; return *ptr; } $ riscv64-sifive-elf-gcc test.c -O3 -S -o- .file "test.c" .option nopic .text .section .text.startup,"ax",@progbits .align 1 .globl main .type main, @function main: lw a5,0(zero) ebreak .size main, .-main .ident "GCC: (GNU) 8.1.0" Which results in a SIGBREAK instead of a SIGILL. The decision here was a bit arbitrary, but I think we should keep it consistent between the hand-written assembly and the compiler-generated assembly. Aside from that, this is great. Thanks!
On Okt 29 2018, Palmer Dabbelt <palmer@sifive.com> wrote:
> GCC will emit an 'ebreak' when it sees unreachable code on RISC-V, for example
Pushed with that change.
Andreas.
On Tue, 30 Oct 2018 04:09:00 PDT (-0700), schwab@suse.de wrote: > On Okt 29 2018, Palmer Dabbelt <palmer@sifive.com> wrote: > >> GCC will emit an 'ebreak' when it sees unreachable code on RISC-V, for example > > Pushed with that change. Thanks!
diff --git a/elf/Makefile b/elf/Makefile index 455ec730fc..d277d34b17 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -187,7 +187,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \ tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \ tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \ - tst-unwind-ctor + tst-unwind-ctor tst-unwind-main # reldep9 tests-internal += loadtest unload unload2 circleload1 \ neededtest neededtest2 neededtest3 neededtest4 \ @@ -1495,3 +1495,5 @@ $(objpfx)tst-libc_dlvsym-static.out: $(objpfx)tst-libc_dlvsym-dso.so $(objpfx)tst-big-note: $(objpfx)tst-big-note-lib.so $(objpfx)tst-unwind-ctor: $(objpfx)tst-unwind-ctor-lib.so + +CFLAGS-tst-unwind-main.c += -funwind-tables diff --git a/elf/tst-unwind-main.c b/elf/tst-unwind-main.c new file mode 100644 index 0000000000..d1236032d7 --- /dev/null +++ b/elf/tst-unwind-main.c @@ -0,0 +1,38 @@ +/* Test unwinding through main. + Copyright (C) 2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <unwind.h> +#include <unistd.h> +#include <support/test-driver.h> + +static _Unwind_Reason_Code +callback (struct _Unwind_Context *ctx, void *arg) +{ + return _URC_NO_REASON; +} + +int +main (void) +{ + /* Arrange for this test to be killed if _Unwind_Backtrace runs into an + endless loop. We cannot use the test driver because the complete + call chain needs to be compiled with -funwind-tables so that + _Unwind_Backtrace is able to reach _start. */ + alarm (DEFAULT_TIMEOUT); + _Unwind_Backtrace (callback, 0); +} diff --git a/sysdeps/riscv/start.S b/sysdeps/riscv/start.S index 4635ddb5eb..ba3e2cf16c 100644 --- a/sysdeps/riscv/start.S +++ b/sysdeps/riscv/start.S @@ -43,6 +43,10 @@ __libc_start_main wants this in a5. */ ENTRY (ENTRY_POINT) + /* Terminate call stack by noting ra is undefined. Use a dummy + .cfi_label to force starting the FDE. */ + .cfi_label .Ldummy + cfi_undefined (ra) call .Lload_gp mv a5, a0 /* rtld_fini. */ /* main may be in a shared library. */ @@ -54,7 +58,8 @@ ENTRY (ENTRY_POINT) lla a4, __libc_csu_fini mv a6, sp /* stack_end. */ - tail __libc_start_main@plt + call __libc_start_main@plt + unimp END (ENTRY_POINT) /* Dynamic links need the global pointer to be initialized prior to calling