* [PATCH] RISC-V: Allow long jumps to __syscall_error [not found] <CGME20220916133037eucas1p2aafce0ab15848778ab6b73afc57396fb@eucas1p2.samsung.com> @ 2022-09-16 13:25 ` Łukasz Stelmach 2022-09-16 17:25 ` Andrew Waterman 0 siblings, 1 reply; 2+ messages in thread From: Łukasz Stelmach @ 2022-09-16 13:25 UTC (permalink / raw) To: libc-alpha Cc: Marek Szyprowski, Łukasz Stelmach, adhemerval.zanella, alistair.francis, aurelien, eggert, jimw, joseph, palmer, k.lewandowsk, jh80.chung, s.rutka __syscall_error may end up farther than 1MiB away from a caller, especially when linking statically large binaries. la+jr allow for 4GiB jumps. Fixes: 36960f0c76 ("RISC-V: Linux Syscall Interface") Fixes: 7f33b09c65 ("RISC-V: Linux ABI") Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com> --- I was compiling and statically linking GNU Guile and I was getting a lot of messages like this: /usr/lib64/libc.a(uname.o): in function `__uname': (.text+0x10): relocation truncated to fit: R_RISCV_JAL against symbol `__syscall_error' defined in .text section in /usr/lib64/libc.a(sysdep.o) And indeed in uname.o there was a relative jump which was marked as R_RISCV_JAL and pointed to __syscall_error. After sucessfully linking the binary with this fix applied __uname and __syscall_error end up 1125000 bytes apart. --8<---------------cut here---------------end--------------->8--- Relocation section '.rela.text' at offset 0x250 contains 4 entries: Offset Info Type Sym. Value Sym. Name + Addend 000000000000 00000000002b R_RISCV_ALIGN 2 000000000002 00000000002b R_RISCV_ALIGN 2 00000000000e 000a00000010 R_RISCV_BRANCH 0000000000000014 .Lsyscall_error__uname + 0 000000000014 000c00000011 R_RISCV_JAL 0000000000000000 __syscall_error + 0 --8<---------------cut here---------------end--------------->8--- --8<---------------cut here---------------end--------------->8--- uname.o: file format elf64-littleriscv Disassembly of section .text: 0000000000000000 <$x>: 0: 0001 nop 2: 0001 nop 0000000000000004 <__uname>: 4: 0a000893 li a7,160 8: 00000073 ecall c: 78fd lui a7,0xfffff e: 00a8e363 bltu a7,a0,14 <.Lsyscall_error__uname> 12: 8082 ret 0000000000000014 <.Lsyscall_error__uname>: 14: fedff06f j 0 <$x> ^^^^ ^^^^^^^^^^^^^^ 18: 8082 ret ... --8<---------------cut here---------------end--------------->8--- I suspect the two nops that the jump points to were meant(?)/could(??) be used (if there were more of them) to be a placeholder for a longer jump. Alas binutils 2.38 can't handle it properly (yet?), so a manual intervention here seems reasonable. I have neither seen any errors regarding code in *context.S and vfork.S files nor tested if the altered code works, but I assume it needs to be fixed as well. sysdeps/unix/sysv/linux/riscv/clone.S | 3 ++- sysdeps/unix/sysv/linux/riscv/getcontext.S | 3 ++- sysdeps/unix/sysv/linux/riscv/setcontext.S | 3 ++- sysdeps/unix/sysv/linux/riscv/swapcontext.S | 3 ++- sysdeps/unix/sysv/linux/riscv/sysdep.h | 3 ++- sysdeps/unix/sysv/linux/riscv/vfork.S | 3 ++- 6 files changed, 12 insertions(+), 6 deletions(-) diff --git a/sysdeps/unix/sysv/linux/riscv/clone.S b/sysdeps/unix/sysv/linux/riscv/clone.S index d7d2915e87..e716285afa 100644 --- a/sysdeps/unix/sysv/linux/riscv/clone.S +++ b/sysdeps/unix/sysv/linux/riscv/clone.S @@ -63,7 +63,8 @@ L (invalid): li a0, -EINVAL /* Something bad happened -- no child created. */ L (error): - j __syscall_error + la t0, __syscall_error + jr t0 END (__clone) /* Load up the arguments to the function. Put this block of code in diff --git a/sysdeps/unix/sysv/linux/riscv/getcontext.S b/sysdeps/unix/sysv/linux/riscv/getcontext.S index 499f70b65d..a4751ae595 100644 --- a/sysdeps/unix/sysv/linux/riscv/getcontext.S +++ b/sysdeps/unix/sysv/linux/riscv/getcontext.S @@ -70,7 +70,8 @@ LEAF (__getcontext) ret -99: j __syscall_error +99: la t0, __syscall_error + jr t0 PSEUDO_END (__getcontext) diff --git a/sysdeps/unix/sysv/linux/riscv/setcontext.S b/sysdeps/unix/sysv/linux/riscv/setcontext.S index e3bc84a2e6..fddd9d843f 100644 --- a/sysdeps/unix/sysv/linux/riscv/setcontext.S +++ b/sysdeps/unix/sysv/linux/riscv/setcontext.S @@ -92,7 +92,8 @@ LEAF (__setcontext) jr t1 -99: j __syscall_error +99: la t0, __syscall_error + jr t0 END (__setcontext) libc_hidden_def (__setcontext) diff --git a/sysdeps/unix/sysv/linux/riscv/swapcontext.S b/sysdeps/unix/sysv/linux/riscv/swapcontext.S index 4da615f6d4..8e29d96595 100644 --- a/sysdeps/unix/sysv/linux/riscv/swapcontext.S +++ b/sysdeps/unix/sysv/linux/riscv/swapcontext.S @@ -118,7 +118,8 @@ LEAF (__swapcontext) jr t1 -99: j __syscall_error +99: la t0, __syscall_error + jr t0 PSEUDO_END (__swapcontext) diff --git a/sysdeps/unix/sysv/linux/riscv/sysdep.h b/sysdeps/unix/sysv/linux/riscv/sysdep.h index 37ff07a0d7..0cd78daf2b 100644 --- a/sysdeps/unix/sysv/linux/riscv/sysdep.h +++ b/sysdeps/unix/sysv/linux/riscv/sysdep.h @@ -102,7 +102,8 @@ # else # define SYSCALL_ERROR_HANDLER(name) \ .Lsyscall_error ## name: \ - j __syscall_error; + la t0, __syscall_error; \ + jr t0; # endif /* Performs a system call, not setting errno. */ diff --git a/sysdeps/unix/sysv/linux/riscv/vfork.S b/sysdeps/unix/sysv/linux/riscv/vfork.S index 0970543619..8f1b2c9b3a 100644 --- a/sysdeps/unix/sysv/linux/riscv/vfork.S +++ b/sysdeps/unix/sysv/linux/riscv/vfork.S @@ -39,7 +39,8 @@ LEAF (__libc_vfork) bltz a0, 1f ret -1: j __syscall_error +1: la t0, __syscall_error + jr t0 END (__libc_vfork) weak_alias (__libc_vfork, vfork) -- 2.30.2 ^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] RISC-V: Allow long jumps to __syscall_error 2022-09-16 13:25 ` [PATCH] RISC-V: Allow long jumps to __syscall_error Łukasz Stelmach @ 2022-09-16 17:25 ` Andrew Waterman 0 siblings, 0 replies; 2+ messages in thread From: Andrew Waterman @ 2022-09-16 17:25 UTC (permalink / raw) To: Łukasz Stelmach Cc: libc-alpha, k.lewandowsk, s.rutka, jh80.chung, alistair.francis, joseph, jimw, aurelien, Marek Szyprowski Use the `tail` pseudoinstruction rather than `la` + `jr`, as this will relax to `j` when within range. On Fri, Sep 16, 2022 at 6:31 AM Łukasz Stelmach via Libc-alpha <libc-alpha@sourceware.org> wrote: > > __syscall_error may end up farther than 1MiB away from a caller, > especially when linking statically large binaries. la+jr allow for > 4GiB jumps. > > Fixes: 36960f0c76 ("RISC-V: Linux Syscall Interface") > Fixes: 7f33b09c65 ("RISC-V: Linux ABI") > Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com> > --- > > I was compiling and statically linking GNU Guile and I was getting a > lot of messages like this: > > /usr/lib64/libc.a(uname.o): in function `__uname': > (.text+0x10): relocation truncated to fit: R_RISCV_JAL against symbol `__syscall_error' defined in .text section in /usr/lib64/libc.a(sysdep.o) > > And indeed in uname.o there was a relative jump which was marked as > R_RISCV_JAL and pointed to __syscall_error. After sucessfully linking > the binary with this fix applied __uname and __syscall_error end up > 1125000 bytes apart. > > --8<---------------cut here---------------end--------------->8--- > Relocation section '.rela.text' at offset 0x250 contains 4 entries: > Offset Info Type Sym. Value Sym. Name + Addend > 000000000000 00000000002b R_RISCV_ALIGN 2 > 000000000002 00000000002b R_RISCV_ALIGN 2 > 00000000000e 000a00000010 R_RISCV_BRANCH 0000000000000014 .Lsyscall_error__uname + 0 > 000000000014 000c00000011 R_RISCV_JAL 0000000000000000 __syscall_error + 0 > --8<---------------cut here---------------end--------------->8--- > > --8<---------------cut here---------------end--------------->8--- > uname.o: file format elf64-littleriscv > > > Disassembly of section .text: > > 0000000000000000 <$x>: > 0: 0001 nop > 2: 0001 nop > > 0000000000000004 <__uname>: > 4: 0a000893 li a7,160 > 8: 00000073 ecall > c: 78fd lui a7,0xfffff > e: 00a8e363 bltu a7,a0,14 <.Lsyscall_error__uname> > 12: 8082 ret > > 0000000000000014 <.Lsyscall_error__uname>: > 14: fedff06f j 0 <$x> > ^^^^ ^^^^^^^^^^^^^^ > 18: 8082 ret > ... > --8<---------------cut here---------------end--------------->8--- > > I suspect the two nops that the jump points to were meant(?)/could(??) be > used (if there were more of them) to be a placeholder for a longer > jump. Alas binutils 2.38 can't handle it properly (yet?), so a manual > intervention here seems reasonable. > > I have neither seen any errors regarding code in *context.S and vfork.S > files nor tested if the altered code works, but I assume it needs to be > fixed as well. > > sysdeps/unix/sysv/linux/riscv/clone.S | 3 ++- > sysdeps/unix/sysv/linux/riscv/getcontext.S | 3 ++- > sysdeps/unix/sysv/linux/riscv/setcontext.S | 3 ++- > sysdeps/unix/sysv/linux/riscv/swapcontext.S | 3 ++- > sysdeps/unix/sysv/linux/riscv/sysdep.h | 3 ++- > sysdeps/unix/sysv/linux/riscv/vfork.S | 3 ++- > 6 files changed, 12 insertions(+), 6 deletions(-) > > diff --git a/sysdeps/unix/sysv/linux/riscv/clone.S b/sysdeps/unix/sysv/linux/riscv/clone.S > index d7d2915e87..e716285afa 100644 > --- a/sysdeps/unix/sysv/linux/riscv/clone.S > +++ b/sysdeps/unix/sysv/linux/riscv/clone.S > @@ -63,7 +63,8 @@ L (invalid): > li a0, -EINVAL > /* Something bad happened -- no child created. */ > L (error): > - j __syscall_error > + la t0, __syscall_error > + jr t0 > END (__clone) > > /* Load up the arguments to the function. Put this block of code in > diff --git a/sysdeps/unix/sysv/linux/riscv/getcontext.S b/sysdeps/unix/sysv/linux/riscv/getcontext.S > index 499f70b65d..a4751ae595 100644 > --- a/sysdeps/unix/sysv/linux/riscv/getcontext.S > +++ b/sysdeps/unix/sysv/linux/riscv/getcontext.S > @@ -70,7 +70,8 @@ LEAF (__getcontext) > > ret > > -99: j __syscall_error > +99: la t0, __syscall_error > + jr t0 > > PSEUDO_END (__getcontext) > > diff --git a/sysdeps/unix/sysv/linux/riscv/setcontext.S b/sysdeps/unix/sysv/linux/riscv/setcontext.S > index e3bc84a2e6..fddd9d843f 100644 > --- a/sysdeps/unix/sysv/linux/riscv/setcontext.S > +++ b/sysdeps/unix/sysv/linux/riscv/setcontext.S > @@ -92,7 +92,8 @@ LEAF (__setcontext) > > jr t1 > > -99: j __syscall_error > +99: la t0, __syscall_error > + jr t0 > > END (__setcontext) > libc_hidden_def (__setcontext) > diff --git a/sysdeps/unix/sysv/linux/riscv/swapcontext.S b/sysdeps/unix/sysv/linux/riscv/swapcontext.S > index 4da615f6d4..8e29d96595 100644 > --- a/sysdeps/unix/sysv/linux/riscv/swapcontext.S > +++ b/sysdeps/unix/sysv/linux/riscv/swapcontext.S > @@ -118,7 +118,8 @@ LEAF (__swapcontext) > jr t1 > > > -99: j __syscall_error > +99: la t0, __syscall_error > + jr t0 > > PSEUDO_END (__swapcontext) > > diff --git a/sysdeps/unix/sysv/linux/riscv/sysdep.h b/sysdeps/unix/sysv/linux/riscv/sysdep.h > index 37ff07a0d7..0cd78daf2b 100644 > --- a/sysdeps/unix/sysv/linux/riscv/sysdep.h > +++ b/sysdeps/unix/sysv/linux/riscv/sysdep.h > @@ -102,7 +102,8 @@ > # else > # define SYSCALL_ERROR_HANDLER(name) \ > .Lsyscall_error ## name: \ > - j __syscall_error; > + la t0, __syscall_error; \ > + jr t0; > # endif > > /* Performs a system call, not setting errno. */ > diff --git a/sysdeps/unix/sysv/linux/riscv/vfork.S b/sysdeps/unix/sysv/linux/riscv/vfork.S > index 0970543619..8f1b2c9b3a 100644 > --- a/sysdeps/unix/sysv/linux/riscv/vfork.S > +++ b/sysdeps/unix/sysv/linux/riscv/vfork.S > @@ -39,7 +39,8 @@ LEAF (__libc_vfork) > bltz a0, 1f > ret > > -1: j __syscall_error > +1: la t0, __syscall_error > + jr t0 > END (__libc_vfork) > > weak_alias (__libc_vfork, vfork) > -- > 2.30.2 > ^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2022-09-16 17:25 UTC | newest] Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- [not found] <CGME20220916133037eucas1p2aafce0ab15848778ab6b73afc57396fb@eucas1p2.samsung.com> 2022-09-16 13:25 ` [PATCH] RISC-V: Allow long jumps to __syscall_error Łukasz Stelmach 2022-09-16 17:25 ` Andrew Waterman
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).