summaryrefslogtreecommitdiff
path: root/tools/include/nolibc/arch-s390.h
diff options
context:
space:
mode:
authorWilly Tarreau <w@1wt.eu>2023-01-10 10:24:13 +0300
committerPaul E. McKenney <paulmck@kernel.org>2023-01-11 00:33:55 +0300
commit7f8548589661d5edbde4c343e4971117585da2f5 (patch)
treed059ee6f8f66bca1ef79808d2f395e74f6d2ed0e /tools/include/nolibc/arch-s390.h
parent28ef4c3753a4e57a347b2bf5f598645de966c137 (diff)
downloadlinux-7f8548589661d5edbde4c343e4971117585da2f5.tar.xz
tools/nolibc: make compiler and assembler agree on the section around _start
The out-of-block asm() statement carrying _start does not allow the compiler to know what section the assembly code is being emitted to, and there's no easy way to push/pop the current section and restore it. It sometimes causes issues depending on the include files ordering and compiler optimizations. For example if a variable is declared immediately before the asm() block and another one after, the compiler assumes that the current section is still .bss and doesn't re-emit it, making the second variable appear inside the .text section instead. Forcing .bss at the end of the _start block doesn't work either because at certain optimizations the compiler may reorder blocks and will make some real code appear just after this block. A significant number of solutions were attempted, but many of them were still sensitive to section reordering. In the end, the best way to make sure the compiler and assembler agree on the current section is to place this code inside a function. Here the function is directly called _start and configured not to emit a frame-pointer, hence to have no prologue. If some future architectures would still emit some prologue, another working approach consists in naming the function differently and placing the _start label inside the asm statement. But the current solution is simpler. It was tested with nolibc-test at -O,-O0,-O2,-O3,-Os for arm,arm64,i386, mips,riscv,s390 and x86_64. Signed-off-by: Willy Tarreau <w@1wt.eu> Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Diffstat (limited to 'tools/include/nolibc/arch-s390.h')
-rw-r--r--tools/include/nolibc/arch-s390.h44
1 files changed, 23 insertions, 21 deletions
diff --git a/tools/include/nolibc/arch-s390.h b/tools/include/nolibc/arch-s390.h
index 76bc8fdaf922..2c0b8847c050 100644
--- a/tools/include/nolibc/arch-s390.h
+++ b/tools/include/nolibc/arch-s390.h
@@ -172,27 +172,29 @@ struct sys_stat_struct {
})
/* startup code */
-__asm__ (".section .text\n"
- ".weak _start\n"
- "_start:\n"
- "lg %r2,0(%r15)\n" /* argument count */
- "la %r3,8(%r15)\n" /* argument pointers */
-
- "xgr %r0,%r0\n" /* r0 will be our NULL value */
- /* search for envp */
- "lgr %r4,%r3\n" /* start at argv */
- "0:\n"
- "clg %r0,0(%r4)\n" /* entry zero? */
- "la %r4,8(%r4)\n" /* advance pointer */
- "jnz 0b\n" /* no -> test next pointer */
- /* yes -> r4 now contains start of envp */
-
- "aghi %r15,-160\n" /* allocate new stackframe */
- "xc 0(8,%r15),0(%r15)\n" /* clear backchain */
- "brasl %r14,main\n" /* ret value of main is arg to exit */
- "lghi %r1,1\n" /* __NR_exit */
- "svc 0\n"
- "");
+void __attribute__((weak,noreturn,optimize("omit-frame-pointer"))) _start(void)
+{
+ __asm__ volatile (
+ "lg %r2,0(%r15)\n" /* argument count */
+ "la %r3,8(%r15)\n" /* argument pointers */
+
+ "xgr %r0,%r0\n" /* r0 will be our NULL value */
+ /* search for envp */
+ "lgr %r4,%r3\n" /* start at argv */
+ "0:\n"
+ "clg %r0,0(%r4)\n" /* entry zero? */
+ "la %r4,8(%r4)\n" /* advance pointer */
+ "jnz 0b\n" /* no -> test next pointer */
+ /* yes -> r4 now contains start of envp */
+
+ "aghi %r15,-160\n" /* allocate new stackframe */
+ "xc 0(8,%r15),0(%r15)\n" /* clear backchain */
+ "brasl %r14,main\n" /* ret value of main is arg to exit */
+ "lghi %r1,1\n" /* __NR_exit */
+ "svc 0\n"
+ );
+ __builtin_unreachable();
+}
struct s390_mmap_arg_struct {
unsigned long addr;