devel
Threads by month
- ----- 2026 -----
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- 1 participants
- 1176 discussions
Hello,
I first want to apologize for so many patch versions.
This version of the patch correctly adjusts the offset of the TLS initimage
used by __libc_setup_tls when copying.
I would love feedback on my modifications to libc-tls.c as I had to use a
new global variable defined in reloc_static_pie.c containing the load
address. Originally I attempted to copy how glibc pulls the load address
from a memory map when initializing the TLS, however I could not find a
similar structure available in __libc_setup_tls. I would love to know if
there is a better method which I overlooked.
From 30b435a0b7a7f2d4323eafea2bcebb087cc62462 Mon Sep 17 00:00:00 2001
From: linted <linted(a)users.noreply.github.com>
Date: Sat, 23 Jul 2022 16:25:41 -0400
Subject: [PATCH] Added support for creation of Static Position-Independent
Executables (PIE) on i386, x86_64, and arm.
This patch adds the generation of rcrt1.o which is used by gcc when
compiling with the --static-pie flag.
rcrt1.o differs from crt1.o and Scrt1.o in that it the executable has a
dynamic section but no relocations have been performed prior to _start
being called.
crt1.o assumes there to be no dynamic relocations, and Scrt1.o has all
relocations performed prior to execution by lsdo.
The new reloc_static_pie function handles parsing the dynamic section, and
performing the relocations in a architecture agnostic method.
It also sets _dl_load_base which is used when initalizing TLS to ensure
loading from the proper location.
This allows for easier porting of static-pie support to additional
architectures as only modifications to crt1.S to find the load address are
required.
Signed-off-by: linted <linted(a)users.noreply.github.com>
---
Makerules | 5 +++
extra/Configs/Config.in | 5 +++
libc/misc/internals/Makefile.in | 1 +
libc/misc/internals/reloc_static_pie.c | 47 +++++++++++++++++++++
libc/sysdeps/linux/arm/crt1.S | 19 +++++++++
libc/sysdeps/linux/i386/crt1.S | 20 +++++++++
libc/sysdeps/linux/x86_64/crt1.S | 16 ++++++-
libpthread/nptl/sysdeps/generic/Makefile.in | 4 ++
libpthread/nptl/sysdeps/generic/libc-tls.c | 4 ++
9 files changed, 120 insertions(+), 1 deletion(-)
create mode 100644 libc/misc/internals/reloc_static_pie.c
diff --git a/Makerules b/Makerules
index fd40e6c7b..845d81897 100644
--- a/Makerules
+++ b/Makerules
@@ -405,8 +405,13 @@ else
CRTS=$(top_builddir)lib/$(CRT).o
endif
+ifeq ($(STATIC_PIE),y)
+CRTS+=$(top_builddir)lib/r$(CRT).o
+endif
+
ASFLAGS-$(CRT).o := -DL_$(CRT)
ASFLAGS-S$(CRT).o := $(PIEFLAG) -DL_S$(CRT)
+ASFLAGS-r$(CRT).o := $(PIEFLAG) -DL_r$(CRT)
$(CRTS): $(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/$(CRT).S
$(compile.S)
$(Q)$(STRIPTOOL) -x -R .note -R .comment $@
diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in
index a58ceb265..a49278b30 100644
--- a/extra/Configs/Config.in
+++ b/extra/Configs/Config.in
@@ -301,6 +301,11 @@ config DOPIC
If you wish to build all of uClibc as PIC objects, then answer Y here.
If you are unsure, then you should answer N.
+config STATIC_PIE
+ bool "Add support for Static Position Independent Executables (PIE)"
+ default n
+ depends on DOPIC && !UCLIBC_FORMAT_FDPIC_ELF && (TARGET_arm ||
TARGET_i386 || TARGET_x86_64)
+
config ARCH_HAS_NO_SHARED
bool
diff --git a/libc/misc/internals/Makefile.in
b/libc/misc/internals/Makefile.in
index a8e4e36f9..4a6e73d2d 100644
--- a/libc/misc/internals/Makefile.in
+++ b/libc/misc/internals/Makefile.in
@@ -34,6 +34,7 @@ libc-static-$(UCLIBC_FORMAT_FLAT_SEP_DATA) += \
libc-static-$(UCLIBC_FORMAT_SHARED_FLAT) += \
$(MISC_INTERNALS_OUT)/shared_flat_initfini.o \
$(MISC_INTERNALS_OUT)/shared_flat_add_library.o
+libc-static-$(STATIC_PIE) += $(MISC_INTERNALS_OUT)/reloc_static_pie.o
libc-shared-$(UCLIBC_FORMAT_SHARED_FLAT) += \
$(MISC_INTERNALS_OUT)/shared_flat_initfini.os \
$(MISC_INTERNALS_OUT)/shared_flat_add_library.os
diff --git a/libc/misc/internals/reloc_static_pie.c
b/libc/misc/internals/reloc_static_pie.c
new file mode 100644
index 000000000..578202d23
--- /dev/null
+++ b/libc/misc/internals/reloc_static_pie.c
@@ -0,0 +1,47 @@
+/* Support for relocating static PIE.
+ Copyright (C) 2017-2022 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <link.h>
+#include <elf.h>
+#include <dl-elf.h>
+
+ElfW(Addr) _dl_load_base = NULL;
+
+void
+reloc_static_pie (ElfW(Addr) load_addr);
+
+void
+reloc_static_pie (ElfW(Addr) load_addr)
+{
+ ElfW(Word) relative_count = 0;
+ ElfW(Addr) rel_addr = 0;
+ ElfW(Dyn) * dyn_addr = NULL;
+ unsigned long dynamic_info[DYNAMIC_SIZE] = {0};
+
+ /* Read our own dynamic section and fill in the info array. */
+ dyn_addr = ((void *) load_addr + elf_machine_dynamic ());
+
+ /* Use the underlying function to avoid TLS access before
initialization */
+ __dl_parse_dynamic_info(dyn_addr, dynamic_info, NULL, load_addr);
+
+ /* Perform relocations */
+ relative_count = dynamic_info[DT_RELCONT_IDX];
+ rel_addr = dynamic_info[DT_RELOC_TABLE_ADDR];
+ elf_machine_relative(load_addr, rel_addr, relative_count);
+ _dl_load_base = load_addr;
+}
diff --git a/libc/sysdeps/linux/arm/crt1.S b/libc/sysdeps/linux/arm/crt1.S
index a1d7f0f23..fade1d25c 100644
--- a/libc/sysdeps/linux/arm/crt1.S
+++ b/libc/sysdeps/linux/arm/crt1.S
@@ -246,6 +246,22 @@ _start:
mov lr, #0
#ifdef __ARCH_USE_MMU__
+#ifdef L_rcrt1
+ /* We don't need to save a1 since no dynamic linker should have run */
+ ldr a1, .L_GOT /* Get value at .L_GOT + 0 (offset to GOT)*/
+ adr a2, .L_GOT /* Get address of .L_GOT */
+ ldr a3, .L_GOT+16 /* Get value of _start(GOT) stored in .L_GOT */
+ adr a4, _start /* Get address of _start after relocation
(changes to pc - ~30 or so) */
+ add a1, a1, a2 /* Calculate where the GOT is */
+ ldr a2, [a1, a3] /* GOT + _start(GOT) = offset of _start from
begin of file */
+ sub a1, a4, a2 /* Current addr of _start - offset from beginning
of file = load addr */
+ bl reloc_static_pie
+ mov a1, #0 /* Clean up a1 so that a random address won't get
called at the end of program */
+
+ /* Clear the frame pointer and link register again since it might be
modified by previous call */
+ mov fp, #0
+ mov lr, #0
+#endif
/* Pop argc off the stack and save a pointer to argv */
ldr a2, [sp], #4
mov a3, sp
@@ -309,6 +325,9 @@ _start:
.word _fini(GOT)
.word _init(GOT)
.word main(GOT)
+#ifdef L_rcrt1
+ .word _start(GOT)
+#endif
#endif
#endif
diff --git a/libc/sysdeps/linux/i386/crt1.S b/libc/sysdeps/linux/i386/crt1.S
index 35a6552e8..decc68967 100644
--- a/libc/sysdeps/linux/i386/crt1.S
+++ b/libc/sysdeps/linux/i386/crt1.S
@@ -67,6 +67,9 @@
#endif
.type main,%function
.type __uClibc_main,%function
+#ifdef L_rcrt1
+.type reloc_static_pie,%function
+#endif
_start:
/* Clear the frame pointer. The ABI suggests this be done, to mark
the outermost frame obviously. */
@@ -100,6 +103,23 @@ _start:
pop %ebx
addl $_GLOBAL_OFFSET_TABLE_+[.-.L0],%ebx
+#ifdef L_rcrt1
+ /* We cannot rely on _DYNAMIC being usable here due to RELRO.
+ Instead we calculate the load address based off a symbol
+ that we know will exist, _start. */
+ pushl %ecx /* Save ecx so it won't get clobbered */
+ pushl %ebx /* Save ebx so it won't get clobbered */
+ xorl %ecx, %ecx /* Clear ecx */
+ addl _start@GOT(%ebx), %ecx /* Get the offset of _start */
+ movl _start@GOT(%ebx), %eax /* Get the run time address of _start */
+ subl %ecx, %eax /* Subtract to find the load address */
+ pushl %eax /* Pass the load address */
+ call reloc_static_pie@PLT
+ popl %eax /* Clean up from function call */
+ popl %ebx /* Restore the GOT address */
+ popl %ecx /* restore ecx */
+#endif
+
/* Push address of our own entry points to .fini and .init. */
pushl _fini@GOT(%ebx)
pushl _init@GOT(%ebx)
diff --git a/libc/sysdeps/linux/x86_64/crt1.S
b/libc/sysdeps/linux/x86_64/crt1.S
index 87777dd5d..701cbf2f6 100644
--- a/libc/sysdeps/linux/x86_64/crt1.S
+++ b/libc/sysdeps/linux/x86_64/crt1.S
@@ -80,6 +80,20 @@ _start:
the outermost frame obviously. */
xorl %ebp, %ebp
+#ifdef L_rcrt1
+ pushq %rdi /* save rdi (but should be 0...) */
+ pushq %rdx /* store rdx (rtld_fini) */
+ xorq %rcx, %rcx /* ensure rcx is 0 */
+ addq _start@GOTPCREL(%rip), %rcx /* get offset of _start from
beginning of file */
+ movq _start@GOTPCREL(%rip), %rax /* get run time address of _start */
+ subq %rcx, %rax /* calculate run time load offset */
+ movq %rax, %rdi /* load offset -> param 1 */
+ call reloc_static_pie /* relocate dynamic addrs */
+ xorq %rax, %rax /* cleanup */
+ popq %rdx
+ popq %rdi
+#endif
+
/* Extract the arguments as encoded on the stack and set up
the arguments for __libc_start_main (int (*main) (int, char **, char
**),
int argc, char *argv,
@@ -107,7 +121,7 @@ _start:
which grow downwards). */
pushq %rsp
-#if defined(L_Scrt1)
+#if defined(L_Scrt1) || defined(L_rcrt1)
/* Give address for main() */
movq main@GOTPCREL(%rip), %rdi
diff --git a/libpthread/nptl/sysdeps/generic/Makefile.in
b/libpthread/nptl/sysdeps/generic/Makefile.in
index eb656ee17..a5ba9bbe8 100644
--- a/libpthread/nptl/sysdeps/generic/Makefile.in
+++ b/libpthread/nptl/sysdeps/generic/Makefile.in
@@ -13,6 +13,10 @@ subdirs += libpthread/nptl/sysdeps/generic
libpthread_generic_DIR := $(top_srcdir)libpthread/nptl/sysdeps/generic
libpthread_generic_OUT := $(top_builddir)libpthread/nptl/sysdeps/generic
+ifeq ($(STATIC_PIE),y)
+CFLAGS-libc-tls.c := -DSTATIC_PIE
+endif
+
libpthread_generic_libc_a_CSRC = libc-tls.c
libpthread_generic_libc_a_COBJ = $(patsubst
%.c,$(libpthread_generic_OUT)/%.o,$(libpthread_generic_libc_a_CSRC))
libpthread_generic_libc_a_OBJS = $(libpthread_generic_libc_a_COBJ)
diff --git a/libpthread/nptl/sysdeps/generic/libc-tls.c
b/libpthread/nptl/sysdeps/generic/libc-tls.c
index d746c9a38..0c8c558d0 100644
--- a/libpthread/nptl/sysdeps/generic/libc-tls.c
+++ b/libpthread/nptl/sysdeps/generic/libc-tls.c
@@ -142,6 +142,10 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
initimage = (void *) &__tdata_start;
#else
initimage = (void *) phdr->p_vaddr;
+#if !defined(SHARED) && defined(STATIC_PIE)
+ extern ElfW(Addr) _dl_load_base;
+ initimage += _dl_load_base;
+#endif
#endif
align = phdr->p_align;
if (phdr->p_align > max_align)
--
2.34.1
3
2
Hello,
This is an updated patch for static pie support. I have corrected
formatting and code standard issues which appeared in my previous patches.
I also updated the commit message to be clearer on what is occurring and
why.
-linted
From 92056b7db87be00e6daea59a4f82d022bfc7f223 Mon Sep 17 00:00:00 2001
From: linted <linted(a)users.noreply.github.com>
Date: Sun, 17 Jul 2022 13:38:49 -0400
Subject: [PATCH] Added support for creation of Static Position-Independent
Executables (PIE) on i386, x86_64, and arm.
This patch adds the generation of rcrt1.o which is used by gcc when
compiling with the --static-pie flag.
rcrt1.o differs from crt1.o and Scrt1.o in that it the executable has a
dynamic section but no relocations have been performed prior to _start
being called.
crt1.o assumes there to be no dynamic relocations, and Scrt1.o has all
relocations performed prior to execution by lsdo.
The new reloc_static_pie function handles parsing the elf headers, locating
the dynamic section, and performing the relocations in a architecture
agnostic method.
This allows for easier porting of static-pie support to additional
architectures.
Signed-off-by: linted <linted(a)users.noreply.github.com>
---
Makerules | 5 ++++
extra/Configs/Config.in | 5 ++++
libc/misc/internals/Makefile.in | 1 +
libc/misc/internals/reloc_static_pie.c | 41 ++++++++++++++++++++++++++
libc/sysdeps/linux/arm/crt1.S | 15 ++++++++++
libc/sysdeps/linux/i386/crt1.S | 20 +++++++++++++
libc/sysdeps/linux/x86_64/crt1.S | 16 +++++++++-
7 files changed, 102 insertions(+), 1 deletion(-)
create mode 100644 libc/misc/internals/reloc_static_pie.c
diff --git a/Makerules b/Makerules
index fd40e6c7b..845d81897 100644
--- a/Makerules
+++ b/Makerules
@@ -405,8 +405,13 @@ else
CRTS=$(top_builddir)lib/$(CRT).o
endif
+ifeq ($(STATIC_PIE),y)
+CRTS+=$(top_builddir)lib/r$(CRT).o
+endif
+
ASFLAGS-$(CRT).o := -DL_$(CRT)
ASFLAGS-S$(CRT).o := $(PIEFLAG) -DL_S$(CRT)
+ASFLAGS-r$(CRT).o := $(PIEFLAG) -DL_r$(CRT)
$(CRTS): $(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/$(CRT).S
$(compile.S)
$(Q)$(STRIPTOOL) -x -R .note -R .comment $@
diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in
index a58ceb265..a49278b30 100644
--- a/extra/Configs/Config.in
+++ b/extra/Configs/Config.in
@@ -301,6 +301,11 @@ config DOPIC
If you wish to build all of uClibc as PIC objects, then answer Y here.
If you are unsure, then you should answer N.
+config STATIC_PIE
+ bool "Add support for Static Position Independent Executables (PIE)"
+ default n
+ depends on DOPIC && !UCLIBC_FORMAT_FDPIC_ELF && (TARGET_arm ||
TARGET_i386 || TARGET_x86_64)
+
config ARCH_HAS_NO_SHARED
bool
diff --git a/libc/misc/internals/Makefile.in
b/libc/misc/internals/Makefile.in
index a8e4e36f9..4a6e73d2d 100644
--- a/libc/misc/internals/Makefile.in
+++ b/libc/misc/internals/Makefile.in
@@ -34,6 +34,7 @@ libc-static-$(UCLIBC_FORMAT_FLAT_SEP_DATA) += \
libc-static-$(UCLIBC_FORMAT_SHARED_FLAT) += \
$(MISC_INTERNALS_OUT)/shared_flat_initfini.o \
$(MISC_INTERNALS_OUT)/shared_flat_add_library.o
+libc-static-$(STATIC_PIE) += $(MISC_INTERNALS_OUT)/reloc_static_pie.o
libc-shared-$(UCLIBC_FORMAT_SHARED_FLAT) += \
$(MISC_INTERNALS_OUT)/shared_flat_initfini.os \
$(MISC_INTERNALS_OUT)/shared_flat_add_library.os
diff --git a/libc/misc/internals/reloc_static_pie.c
b/libc/misc/internals/reloc_static_pie.c
new file mode 100644
index 000000000..9a8066b84
--- /dev/null
+++ b/libc/misc/internals/reloc_static_pie.c
@@ -0,0 +1,41 @@
+/* Support for relocating static PIE.
+ Copyright (C) 2017-2022 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <link.h>
+#include <elf.h>
+#include <dl-elf.h>
+
+void
+reloc_static_pie (ElfW(Addr) load_addr)
+{
+ ElfW(Word) relative_count = 0;
+ ElfW(Addr) rel_addr = NULL;
+ ElfW(Dyn) * dyn_addr = NULL;
+ unsigned long dynamic_info[DYNAMIC_SIZE] = {0};
+
+ /* Read our own dynamic section and fill in the info array. */
+ dyn_addr = ((void *) load_addr + elf_machine_dynamic ());
+
+ /* Use the underlying function to avoid TLS access before
initialization */
+ __dl_parse_dynamic_info(dyn_addr, dynamic_info, NULL, load_addr);
+
+ /* Perform relocations */
+ relative_count = dynamic_info[DT_RELCONT_IDX];
+ rel_addr = dynamic_info[DT_RELOC_TABLE_ADDR];
+ elf_machine_relative(load_addr, rel_addr, relative_count);
+}
diff --git a/libc/sysdeps/linux/arm/crt1.S b/libc/sysdeps/linux/arm/crt1.S
index a1d7f0f23..2aa2a5234 100644
--- a/libc/sysdeps/linux/arm/crt1.S
+++ b/libc/sysdeps/linux/arm/crt1.S
@@ -246,6 +246,18 @@ _start:
mov lr, #0
#ifdef __ARCH_USE_MMU__
+#ifdef L_rcrt1
+ /* We don't need to save a1 since no dynamic linker should have run */
+ ldr a1, .L_GOT /* Get value at .L_GOT + 0 (offset to GOT)*/
+ adr a2, .L_GOT /* Get address of .L_GOT */
+ ldr a3, .L_GOT+16 /* get value of _start(GOT) stored in .L_GOT */
+ adr a4, _start /* get address of _start after relocation
(changes to pc - ~30 or so) */
+ add a1, a1, a2 /* calculate where the GOT is */
+ ldr a2, [a1, a3] /* GOT + _start(GOT) = offset of _start from
begin of file */
+ sub a1, a4, a2 /* current addr of _start - offset from beginning
of file = load addr */
+ bl reloc_static_pie
+ mov a1, #0 /* Clean up a1 so that a random address won't get
called at the end of program */
+#endif
/* Pop argc off the stack and save a pointer to argv */
ldr a2, [sp], #4
mov a3, sp
@@ -309,6 +321,9 @@ _start:
.word _fini(GOT)
.word _init(GOT)
.word main(GOT)
+#ifdef L_rcrt1
+ .word _start(GOT)
+#endif
#endif
#endif
diff --git a/libc/sysdeps/linux/i386/crt1.S b/libc/sysdeps/linux/i386/crt1.S
index 35a6552e8..decc68967 100644
--- a/libc/sysdeps/linux/i386/crt1.S
+++ b/libc/sysdeps/linux/i386/crt1.S
@@ -67,6 +67,9 @@
#endif
.type main,%function
.type __uClibc_main,%function
+#ifdef L_rcrt1
+.type reloc_static_pie,%function
+#endif
_start:
/* Clear the frame pointer. The ABI suggests this be done, to mark
the outermost frame obviously. */
@@ -100,6 +103,23 @@ _start:
pop %ebx
addl $_GLOBAL_OFFSET_TABLE_+[.-.L0],%ebx
+#ifdef L_rcrt1
+ /* We cannot rely on _DYNAMIC being usable here due to RELRO.
+ Instead we calculate the load address based off a symbol
+ that we know will exist, _start. */
+ pushl %ecx /* Save ecx so it won't get clobbered */
+ pushl %ebx /* Save ebx so it won't get clobbered */
+ xorl %ecx, %ecx /* Clear ecx */
+ addl _start@GOT(%ebx), %ecx /* Get the offset of _start */
+ movl _start@GOT(%ebx), %eax /* Get the run time address of _start */
+ subl %ecx, %eax /* Subtract to find the load address */
+ pushl %eax /* Pass the load address */
+ call reloc_static_pie@PLT
+ popl %eax /* Clean up from function call */
+ popl %ebx /* Restore the GOT address */
+ popl %ecx /* restore ecx */
+#endif
+
/* Push address of our own entry points to .fini and .init. */
pushl _fini@GOT(%ebx)
pushl _init@GOT(%ebx)
diff --git a/libc/sysdeps/linux/x86_64/crt1.S
b/libc/sysdeps/linux/x86_64/crt1.S
index 87777dd5d..701cbf2f6 100644
--- a/libc/sysdeps/linux/x86_64/crt1.S
+++ b/libc/sysdeps/linux/x86_64/crt1.S
@@ -80,6 +80,20 @@ _start:
the outermost frame obviously. */
xorl %ebp, %ebp
+#ifdef L_rcrt1
+ pushq %rdi /* save rdi (but should be 0...) */
+ pushq %rdx /* store rdx (rtld_fini) */
+ xorq %rcx, %rcx /* ensure rcx is 0 */
+ addq _start@GOTPCREL(%rip), %rcx /* get offset of _start from
beginning of file */
+ movq _start@GOTPCREL(%rip), %rax /* get run time address of _start */
+ subq %rcx, %rax /* calculate run time load offset */
+ movq %rax, %rdi /* load offset -> param 1 */
+ call reloc_static_pie /* relocate dynamic addrs */
+ xorq %rax, %rax /* cleanup */
+ popq %rdx
+ popq %rdi
+#endif
+
/* Extract the arguments as encoded on the stack and set up
the arguments for __libc_start_main (int (*main) (int, char **, char
**),
int argc, char *argv,
@@ -107,7 +121,7 @@ _start:
which grow downwards). */
pushq %rsp
-#if defined(L_Scrt1)
+#if defined(L_Scrt1) || defined(L_rcrt1)
/* Give address for main() */
movq main@GOTPCREL(%rip), %rdi
--
2.34.1
4
10
18 Jul '22
Hello,
Buildroot supports building ARM 32-bit systems for ARMv8 cores (even
though those would more classically run an AArch64 system).
Unfortunately, it seems like uClibc-ng doesn't support this situation,
as it exhibits the following build failure:
CC libpthread/linuxthreads/mutex.os
/tmp/ccn8SFKU.s: Assembler messages:
/tmp/ccn8SFKU.s:162: Error: swp{b} use is obsoleted for ARMv8 and later
/tmp/ccn8SFKU.s:186: Error: swp{b} use is obsoleted for ARMv8 and later
/tmp/ccn8SFKU.s:203: Error: swp{b} use is obsoleted for ARMv8 and later
/tmp/ccn8SFKU.s:224: Error: swp{b} use is obsoleted for ARMv8 and later
make[1]: *** [Makerules:369: libpthread/linuxthreads/mutex.os] Error 1
See
http://autobuild.buildroot.net/results/1e2e5e6c752901a818630d0c0816f43874bf…
for a more detailed log.
This is due to libpthread/linuxthreads/sysdeps/arm/pt-machine.h which
uses the swp instruction that is not allowed on ARMv8.
Best regards,
Thomas
--
Thomas Petazzoni, co-owner and CEO, Bootlin
Embedded Linux and Kernel engineering and training
https://bootlin.com
1
0
Hello,
This is an updated patch for static pie support on i386, x86_64, and arm. I
added dependency checks to ensure it only affects supported architectures.
I also added a check to ensure an MMU is present on arm since there is no
support for FDPIC yet.
2
2
Hello,
I implemented support for static pie generation on i386, x86_64, and arm.
This patch adds the generation of rcrt1.o which is used by gcc when
compiling with the --static-pie flag. The main difference in rcrt1.o is
that it is required to perform dynamic relocations which would normally
occur in ldso. The new reloc_static_pie function handles parsing the elf
headers, locating the dynamic section, and performing the relocations.
2
2
See the C11 standard 7.2 §3
The definition is copied from glibc.
---
include/assert.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/include/assert.h b/include/assert.h
index ee8e85fa2..fd71e833b 100644
--- a/include/assert.h
+++ b/include/assert.h
@@ -76,3 +76,8 @@ __END_DECLS
# endif
#endif /* NDEBUG. */
+
+#if defined __USE_ISOC11 && !defined __cplusplus
+# undef static_assert
+# define static_assert _Static_assert
+#endif
--
2.36.1
2
1
getaddrinfo() returns addresses from, at least, ip(7) and ipv6(7),
but _addr() always uses sin_addr from struct sockaddr_in;
we're saved from wild unsoundness (or incompatibility)
by virtue of struct sockaddr_in6 having an always-0 u32 sin6_flowinfo
at the same offset, so we end up returning 0 anyway,
but in a round-about and definitely unintended way
Instead, limit the request to AF_INET, and fall through to the end
early, returning the default id=0
---
diff -ur uClibc-ng-1.0.41.orig/libc/inet/hostid.c uClibc-ng-1.0.41/libc/inet/hostid.c
--- uClibc-ng-1.0.41.orig/libc/inet/hostid.c 2022-05-20 17:07:47.000000000 +0200
+++ uClibc-ng-1.0.41/libc/inet/hostid.c 2022-06-01 19:09:21.971253011 +0200
@@ -61,8 +61,7 @@
* Mitch
*/
if (gethostname(host, HOST_NAME_MAX) >= 0 && *host) {
- struct addrinfo hints, *results, *addr;
- memset(&hints, 0, sizeof(struct addrinfo));
+ struct addrinfo hints = {.ai_family = AF_INET}, *results, *addr;
if (!getaddrinfo(host, NULL, &hints, &results)) {
for (addr = results; addr; addr = results->ai_next) {
/* Just so it doesn't look exactly like the
2
1
20 Jun '22
Implement getcontext, makecontext, setcontext and swapcontext.
Signed-off-by: Max Filippov <jcmvbkbc(a)gmail.com>
---
Changes v2->v3:
- use explicit SIG_BLOCK in getcontext instead of 0
Changes v1->v2:
- drop wrong comment from __start_context
extra/Configs/Config.xtensa | 3 +-
libc/sysdeps/linux/xtensa/Makefile.arch | 3 +
libc/sysdeps/linux/xtensa/__start_context.S | 100 +++++++++++
libc/sysdeps/linux/xtensa/getcontext.S | 99 +++++++++++
libc/sysdeps/linux/xtensa/makecontext.c | 179 ++++++++++++++++++++
libc/sysdeps/linux/xtensa/setcontext.S | 116 +++++++++++++
libc/sysdeps/linux/xtensa/swapcontext.S | 173 +++++++++++++++++++
libc/sysdeps/linux/xtensa/sysdep.h | 7 +-
libc/sysdeps/linux/xtensa/ucontext_i.sym | 15 ++
9 files changed, 692 insertions(+), 3 deletions(-)
create mode 100644 libc/sysdeps/linux/xtensa/__start_context.S
create mode 100644 libc/sysdeps/linux/xtensa/getcontext.S
create mode 100644 libc/sysdeps/linux/xtensa/makecontext.c
create mode 100644 libc/sysdeps/linux/xtensa/setcontext.S
create mode 100644 libc/sysdeps/linux/xtensa/swapcontext.S
create mode 100644 libc/sysdeps/linux/xtensa/ucontext_i.sym
diff --git a/extra/Configs/Config.xtensa b/extra/Configs/Config.xtensa
index 3ee8817ba1a2..7316c542d896 100644
--- a/extra/Configs/Config.xtensa
+++ b/extra/Configs/Config.xtensa
@@ -10,5 +10,6 @@ config TARGET_ARCH
config FORCE_OPTIONS_FOR_ARCH
bool
default y
- select ARCH_HAS_DEPRECATED_SYSCALLS
select ARCH_ANY_ENDIAN
+ select ARCH_HAS_DEPRECATED_SYSCALLS
+ select ARCH_HAS_UCONTEXT
diff --git a/libc/sysdeps/linux/xtensa/Makefile.arch b/libc/sysdeps/linux/xtensa/Makefile.arch
index 23cd08ee5687..f3a93caaafb1 100644
--- a/libc/sysdeps/linux/xtensa/Makefile.arch
+++ b/libc/sysdeps/linux/xtensa/Makefile.arch
@@ -10,3 +10,6 @@ SSRC-y := bsd-_setjmp.S bsd-setjmp.S setjmp.S clone.S \
sigrestorer.S syscall.S mmap.S windowspill.S __longjmp.S vfork.S
CSRC-$(if $(UCLIBC_HAS_THREADS_NATIVE),,y) += fork.c
+
+CSRC-$(UCLIBC_HAS_CONTEXT_FUNCS) += makecontext.c
+SSRC-$(UCLIBC_HAS_CONTEXT_FUNCS) += setcontext.S getcontext.S swapcontext.S __start_context.S
diff --git a/libc/sysdeps/linux/xtensa/__start_context.S b/libc/sysdeps/linux/xtensa/__start_context.S
new file mode 100644
index 000000000000..a30d7b6188ad
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/__start_context.S
@@ -0,0 +1,100 @@
+/* Copyright (C) 2018 - 2022 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 <sysdep.h>
+
+#if defined(__XTENSA_CALL0_ABI__)
+/*
+ * There's no entry instruction, makecontext sets up ucontext_t as if
+ * getcontext was called above and is about to return here.
+ * Registers on entry to this function:
+ * a12: func to call
+ * a13: ucp->uc_link, next context to activate if func returns
+ * a14: func argc
+ */
+ .literal_position
+
+ENTRY_PREFIX(__start_context)
+
+ beqz a14, 1f
+
+ /* load func arguments 0..1 from stack and free that space */
+ l32i a2, a1, 8
+ l32i a3, a1, 12
+ addi a1, a1, 16
+ bltui a14, 3, 1f
+
+ /* load func arguments 2..5 from stack and free that space */
+ l32i a4, a1, 0
+ l32i a5, a1, 4
+ l32i a6, a1, 8
+ l32i a7, a1, 12
+ addi a1, a1, 16
+ /* func arguments 6..argc - 1 are now at the top of the stack */
+1:
+ callx0 a12
+ beqz a13, 1f
+ mov a2, a13
+ movi a4, JUMPTARGET (setcontext)
+ callx0 a4
+1:
+ movi a4, JUMPTARGET (_exit)
+ movi a2, 0
+ callx0 a4
+ ill
+END(__start_context)
+#elif defined(__XTENSA_WINDOWED_ABI__)
+/*
+ * There's no entry instruction, makecontext sets up ucontext_t as if
+ * getcontext was called above and is about to return here.
+ * Registers on entry to this function:
+ * a2: func to call
+ * a3: ucp->uc_link, next context to activate if func returns
+ * a4: func argc
+ * a5..a7: func arguments 0..2
+ */
+ .literal_position
+
+ENTRY_PREFIX(__start_context)
+
+ mov a10, a5
+ mov a11, a6
+ mov a12, a7
+ bltui a4, 4, 1f
+
+ /* load func arguments 3..5 from stack and free that space */
+ l32i a13, a1, 4
+ l32i a14, a1, 8
+ l32i a15, a1, 12
+ addi a5, a1, 16
+ movsp a1, a5
+ /* func arguments 6..argc - 1 are now at the top of the stack */
+1:
+ callx8 a2
+ beqz a3, 1f
+ mov a6, a3
+ movi a4, JUMPTARGET (setcontext)
+ callx4 a4
+1:
+ movi a4, JUMPTARGET (_exit)
+ movi a6, 0
+ callx4 a4
+ ill
+END(__start_context)
+#else
+#error Unsupported Xtensa ABI
+#endif
diff --git a/libc/sysdeps/linux/xtensa/getcontext.S b/libc/sysdeps/linux/xtensa/getcontext.S
new file mode 100644
index 000000000000..7588a91b33b3
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/getcontext.S
@@ -0,0 +1,99 @@
+/* Copyright (C) 2018 - 2022 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 <sysdep.h>
+#include "ucontext_i.h"
+
+#if defined(__XTENSA_CALL0_ABI__)
+ENTRY(__getcontext)
+ s32i a0, a2, MCONTEXT_SC_PC
+ s32i a1, a2, MCONTEXT_SC_A_0 + 4
+
+ /* save callee-saved registers in the context */
+ s32i a12, a2, MCONTEXT_SC_A_0 + 48
+ s32i a13, a2, MCONTEXT_SC_A_0 + 52
+ s32i a14, a2, MCONTEXT_SC_A_0 + 56
+ s32i a15, a2, MCONTEXT_SC_A_0 + 60
+
+ movi a3, 0
+ addi a4, a2, UCONTEXT_SIGMASK
+ movi a2, SIG_BLOCK
+ movi a5, JUMPTARGET (sigprocmask)
+ jx a5
+END(__getcontext)
+#elif defined(__XTENSA_WINDOWED_ABI__)
+ENTRY(__getcontext)
+ movi a4, __window_spill
+ callx4 a4
+ s32i a0, a2, MCONTEXT_SC_PC
+
+ /* copy registers a0..a3 from spill area */
+ addi a3, a1, -16
+ l32i a4, a3, 0
+ l32i a5, a3, 4
+ l32i a6, a3, 8
+ l32i a7, a3, 12
+ s32i a4, a2, MCONTEXT_SC_A_0 + 0
+ s32i a5, a2, MCONTEXT_SC_A_0 + 4
+ s32i a6, a2, MCONTEXT_SC_A_0 + 8
+ s32i a7, a2, MCONTEXT_SC_A_0 + 12
+
+ /* if it was call4 then register saving is done */
+ extui a4, a0, 30, 2
+ bltui a4, 2, 1f
+
+ /* otherwise load spill overflow area address into a3 */
+ addi a3, a5, -16
+ l32i a3, a3, 4
+ addi a3, a3, -32
+ beqi a4, 2, 2f
+
+ /* copy registers a8..a11 from spill overflow area */
+ addi a3, a3, -16
+ l32i a4, a3, 16
+ l32i a5, a3, 20
+ l32i a6, a3, 24
+ l32i a7, a3, 28
+ s32i a4, a2, MCONTEXT_SC_A_0 + 32
+ s32i a5, a2, MCONTEXT_SC_A_0 + 36
+ s32i a6, a2, MCONTEXT_SC_A_0 + 40
+ s32i a7, a2, MCONTEXT_SC_A_0 + 44
+
+ /* copy registers a4..a7 from spill overflow area */
+2:
+ l32i a4, a3, 0
+ l32i a5, a3, 4
+ l32i a6, a3, 8
+ l32i a7, a3, 12
+ s32i a4, a2, MCONTEXT_SC_A_0 + 16
+ s32i a5, a2, MCONTEXT_SC_A_0 + 20
+ s32i a6, a2, MCONTEXT_SC_A_0 + 24
+ s32i a7, a2, MCONTEXT_SC_A_0 + 28
+1:
+ movi a6, SIG_BLOCK
+ movi a7, 0
+ addi a8, a2, UCONTEXT_SIGMASK
+ movi a4, JUMPTARGET (sigprocmask)
+ callx4 a4
+ mov a2, a6
+ retw
+END(__getcontext)
+#else
+#error Unsupported Xtensa ABI
+#endif
+
+weak_alias (__getcontext, getcontext)
diff --git a/libc/sysdeps/linux/xtensa/makecontext.c b/libc/sysdeps/linux/xtensa/makecontext.c
new file mode 100644
index 000000000000..da26a0130325
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/makecontext.c
@@ -0,0 +1,179 @@
+/* Copyright (C) 2018 - 2022 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 <sysdep.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <string.h>
+#include <ucontext.h>
+
+extern void __start_context (void);
+
+#if defined(__XTENSA_CALL0_ABI__)
+/*
+ * makecontext sets up new stack like this:
+ *
+ * +------------------ stack top (uc_stack.ss_sp + uc_stack.ss_size)
+ * | optional alignment
+ * +------------------ CFA of __start_context, initial sp points here
+ * | optional padding
+ * +------------------ Optional arguments 6..argc - 1
+ * | func arg argc - 1
+ * | func arg argc - 2
+ * | ...
+ * | func arg 6
+ * +------------------ Optional arguments 2..5
+ * | func arg 5
+ * 16 | func arg 4
+ * | func arg 3
+ * | func arg 2
+ * +------------------ Optional arguments 0..1
+ * | func arg 1
+ * 16 | func arg 0
+ * | padding
+ * | padding
+ * +------------------ CFA of pseudo getcontext
+ * |
+ * +------------------ stack bottom (uc_stack.ss_sp)
+ *
+ * When argc is 0 arguments areas are not allocated,
+ * when 1 <= argc < 3 only area for arguments 0..1 is allocated,
+ * when 3 <= argc < 7 areas for arguments 0..1 and 2..5 is allocated,
+ * when argc >= 7 all three arguments areas are allocated.
+ * Arguments 0..5 area is deallocated by the __start_context after
+ * arguments are loaded into registers.
+ * uc_mcontext registers are set as if __start_context made call0
+ * to getcontext, sp points to that pseudo getcontext CFA.
+ * setcontext/swapcontext will arrange for restoring regiters
+ * a1, a12..a15 of __start_context.
+ */
+
+void
+__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
+{
+ unsigned long sp = ((unsigned long) ucp->uc_stack.ss_sp
+ + ucp->uc_stack.ss_size) & -16;
+ int i;
+
+ if (argc > 0)
+ sp -= 4 * (argc + 2);
+ sp &= -16;
+
+ ucp->uc_mcontext.sc_pc = (unsigned long) __start_context;
+ ucp->uc_mcontext.sc_a[1] = sp;
+ ucp->uc_mcontext.sc_a[12] = (unsigned long) func;
+ ucp->uc_mcontext.sc_a[13] = (unsigned long) ucp->uc_link;
+ ucp->uc_mcontext.sc_a[14] = argc;
+
+ if (argc)
+ {
+ va_list ap;
+
+ va_start (ap, argc);
+ for (i = 0; i < argc; ++i)
+ ((int *) sp)[i + 2] = va_arg (ap, int);
+ va_end (ap);
+ }
+}
+#elif defined(__XTENSA_WINDOWED_ABI__)
+/*
+ * makecontext sets up new stack like this:
+ *
+ * +------------------ stack top (uc_stack.ss_sp + uc_stack.ss_size)
+ * | optional alignment
+ * +------------------ CFA of __start_context
+ * 16 | Outermost caller spill area
+ * +------------------
+ * 16 | __start_context overflow area
+ * +------------------ initial sp points here
+ * | optional padding
+ * +------------------ Optional arguments 6..argc - 1
+ * | func arg argc - 1
+ * | func arg argc - 2
+ * | ...
+ * | func arg 6
+ * +------------------ Optional arguments 3..5
+ * | func arg 5
+ * 16 | func arg 4
+ * | func arg 3
+ * | padding
+ * +------------------ CFA of pseudo getcontext
+ * 16 | __start_context caller spill area
+ * +------------------
+ * |
+ * +------------------ stack bottom (uc_stack.ss_sp)
+ *
+ * When argc < 4 both arguments areas are not allocated,
+ * when 4 <= argc < 7 only area for arguments 3..5 is allocated,
+ * when argc >= 7 both arguments areas are allocated.
+ * Arguments 3..5 area is deallocated by the __start_context after
+ * arguments are loaded into registers.
+ * uc_mcontext registers are set as if __start_context made call8
+ * to getcontext, sp points to that pseudo getcontext CFA, spill
+ * area under that sp has a1 pointing to the __start_context CFA
+ * at the top of the stack. setcontext/swapcontext will arrange for
+ * restoring regiters a0..a7 of __start_context.
+ */
+
+void
+__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
+{
+ unsigned long sp = ((unsigned long) ucp->uc_stack.ss_sp
+ + ucp->uc_stack.ss_size - 32) & -16;
+ unsigned long spill0[4] =
+ {
+ 0, sp + 32, 0, 0,
+ };
+ int i;
+
+ memset ((void *) sp, 0, 32);
+
+ if (argc > 2)
+ sp -= 4 * (argc - 2);
+ sp &= -16;
+
+ ucp->uc_mcontext.sc_pc =
+ ((unsigned long) __start_context & 0x3fffffff) + 0x80000000;
+ ucp->uc_mcontext.sc_a[0] = 0;
+ ucp->uc_mcontext.sc_a[1] = sp;
+ ucp->uc_mcontext.sc_a[2] = (unsigned long) func;
+ ucp->uc_mcontext.sc_a[3] = (unsigned long) ucp->uc_link;
+ ucp->uc_mcontext.sc_a[4] = argc;
+
+ if (argc)
+ {
+ va_list ap;
+
+ va_start (ap, argc);
+ for (i = 0; i < argc; ++i)
+ {
+ if (i < 3)
+ ucp->uc_mcontext.sc_a[5 + i] = va_arg (ap, int);
+ else
+ ((int *) sp)[i - 2] = va_arg (ap, int);
+ }
+ va_end (ap);
+ }
+
+ sp -= 16;
+ memcpy ((void *) sp, spill0, sizeof (spill0));
+}
+#else
+#error Unsupported Xtensa ABI
+#endif
+
+weak_alias (__makecontext, makecontext)
diff --git a/libc/sysdeps/linux/xtensa/setcontext.S b/libc/sysdeps/linux/xtensa/setcontext.S
new file mode 100644
index 000000000000..4df7cc049006
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/setcontext.S
@@ -0,0 +1,116 @@
+/* Copyright (C) 2018 - 2022 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 <sysdep.h>
+#include "ucontext_i.h"
+
+#if defined(__XTENSA_CALL0_ABI__)
+ENTRY(__setcontext)
+ addi sp, sp, -16
+ s32i a0, sp, 0
+ s32i a2, sp, 4
+
+ addi a3, a2, UCONTEXT_SIGMASK
+ movi a4, 0
+ movi a2, SIG_SETMASK
+ movi a5, JUMPTARGET (sigprocmask)
+ callx0 a5
+ bnez a2, .Lerror
+
+ l32i a2, sp, 4
+ l32i a0, a2, MCONTEXT_SC_PC
+ l32i a1, a2, MCONTEXT_SC_A_0 + 4
+
+ /* load callee-saved registers from the context */
+ l32i a12, a2, MCONTEXT_SC_A_0 + 48
+ l32i a13, a2, MCONTEXT_SC_A_0 + 52
+ l32i a14, a2, MCONTEXT_SC_A_0 + 56
+ l32i a15, a2, MCONTEXT_SC_A_0 + 60
+ movi a2, 0
+ ret
+.Lerror:
+ l32i a0, sp, 0
+ addi sp, sp, 16
+ ret
+END(__setcontext)
+#elif defined(__XTENSA_WINDOWED_ABI__)
+ENTRY(__setcontext)
+ movi a6, SIG_SETMASK
+ addi a7, a2, UCONTEXT_SIGMASK
+ movi a8, 0
+ movi a4, JUMPTARGET (sigprocmask)
+ callx4 a4
+ bnez a6, .Lerror
+ movi a4, __window_spill
+ callx4 a4
+
+ l32i a0, a2, MCONTEXT_SC_PC
+
+ /* copy registers a0..a3 to spill area */
+ addi a3, a1, -16
+ l32i a4, a2, MCONTEXT_SC_A_0 + 0
+ l32i a5, a2, MCONTEXT_SC_A_0 + 4
+ l32i a6, a2, MCONTEXT_SC_A_0 + 8
+ l32i a7, a2, MCONTEXT_SC_A_0 + 12
+ s32i a4, a3, 0
+ s32i a5, a3, 4
+ s32i a6, a3, 8
+ s32i a7, a3, 12
+
+ /* if it was call4 then register setup is done */
+ extui a4, a0, 30, 2
+ bltui a4, 2, 1f
+
+ /* otherwise load spill overflow area address into a3 */
+ addi a3, a5, -16
+ l32i a3, a3, 4
+ addi a3, a3, -32
+ beqi a4, 2, 2f
+
+ /* copy registers a8..a11 to spill overflow area */
+ addi a3, a3, -16
+ l32i a4, a2, MCONTEXT_SC_A_0 + 32
+ l32i a5, a2, MCONTEXT_SC_A_0 + 36
+ l32i a6, a2, MCONTEXT_SC_A_0 + 40
+ l32i a7, a2, MCONTEXT_SC_A_0 + 44
+ s32i a4, a3, 16
+ s32i a5, a3, 20
+ s32i a6, a3, 24
+ s32i a7, a3, 28
+
+ /* copy registers a4..a7 to spill overflow area */
+2:
+ l32i a4, a2, MCONTEXT_SC_A_0 + 16
+ l32i a5, a2, MCONTEXT_SC_A_0 + 20
+ l32i a6, a2, MCONTEXT_SC_A_0 + 24
+ l32i a7, a2, MCONTEXT_SC_A_0 + 28
+ s32i a4, a3, 0
+ s32i a5, a3, 4
+ s32i a6, a3, 8
+ s32i a7, a3, 12
+1:
+ movi a2, 0
+ retw
+.Lerror:
+ mov a2, a6
+ retw
+END(__setcontext)
+#else
+#error Unsupported Xtensa ABI
+#endif
+
+weak_alias (__setcontext, setcontext)
diff --git a/libc/sysdeps/linux/xtensa/swapcontext.S b/libc/sysdeps/linux/xtensa/swapcontext.S
new file mode 100644
index 000000000000..a215edc6d54a
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/swapcontext.S
@@ -0,0 +1,173 @@
+/* Copyright (C) 2018 - 2022 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 <sysdep.h>
+#include "ucontext_i.h"
+
+#if defined(__XTENSA_CALL0_ABI__)
+ENTRY(__swapcontext)
+ s32i a0, a2, MCONTEXT_SC_PC
+ s32i a1, a2, MCONTEXT_SC_A_0 + 4
+
+ /* save callee-saved registers in the context */
+ s32i a12, a2, MCONTEXT_SC_A_0 + 48
+ s32i a13, a2, MCONTEXT_SC_A_0 + 52
+ s32i a14, a2, MCONTEXT_SC_A_0 + 56
+ s32i a15, a2, MCONTEXT_SC_A_0 + 60
+
+ mov a12, a3
+ mov a13, a2
+
+ addi a3, a3, UCONTEXT_SIGMASK
+ addi a4, a2, UCONTEXT_SIGMASK
+ movi a2, SIG_SETMASK
+ movi a5, JUMPTARGET (sigprocmask)
+ callx0 a5
+ bnez a2, .Lerror
+
+ mov a2, a12
+ l32i a0, a2, MCONTEXT_SC_PC
+ l32i a1, a2, MCONTEXT_SC_A_0 + 4
+
+ /* load callee-saved registers from the context */
+ l32i a12, a2, MCONTEXT_SC_A_0 + 48
+ l32i a13, a2, MCONTEXT_SC_A_0 + 52
+ l32i a14, a2, MCONTEXT_SC_A_0 + 56
+ l32i a15, a2, MCONTEXT_SC_A_0 + 60
+
+ movi a2, 0
+ ret
+.Lerror:
+ l32i a0, a13, MCONTEXT_SC_PC
+ l32i a12, a13, MCONTEXT_SC_A_0 + 48
+ l32i a13, a13, MCONTEXT_SC_A_0 + 52
+ ret
+END(__swapcontext)
+#elif defined(__XTENSA_WINDOWED_ABI__)
+ENTRY(__swapcontext)
+ movi a4, __window_spill
+ callx4 a4
+ mov a9, a3
+ s32i a0, a2, MCONTEXT_SC_PC
+
+ /* copy registers a0..a3 from spill area */
+ addi a3, a1, -16
+ l32i a4, a3, 0
+ l32i a5, a3, 4
+ l32i a6, a3, 8
+ l32i a7, a3, 12
+ s32i a4, a2, MCONTEXT_SC_A_0 + 0
+ s32i a5, a2, MCONTEXT_SC_A_0 + 4
+ s32i a6, a2, MCONTEXT_SC_A_0 + 8
+ s32i a7, a2, MCONTEXT_SC_A_0 + 12
+
+ /* if it was call4 then register saving is done */
+ extui a4, a0, 30, 2
+ bltui a4, 2, 1f
+
+ /* otherwise load spill overflow area address into a3 */
+ addi a3, a5, -16
+ l32i a3, a3, 4
+ addi a3, a3, -32
+ beqi a4, 2, 2f
+
+ /* copy registers a8..a11 from spill overflow area */
+ addi a3, a3, -16
+ l32i a4, a3, 16
+ l32i a5, a3, 20
+ l32i a6, a3, 24
+ l32i a7, a3, 28
+ s32i a4, a2, MCONTEXT_SC_A_0 + 32
+ s32i a5, a2, MCONTEXT_SC_A_0 + 36
+ s32i a6, a2, MCONTEXT_SC_A_0 + 40
+ s32i a7, a2, MCONTEXT_SC_A_0 + 44
+
+ /* copy registers a4..a7 from spill overflow area */
+2:
+ l32i a4, a3, 0
+ l32i a5, a3, 4
+ l32i a6, a3, 8
+ l32i a7, a3, 12
+ s32i a4, a2, MCONTEXT_SC_A_0 + 16
+ s32i a5, a2, MCONTEXT_SC_A_0 + 20
+ s32i a6, a2, MCONTEXT_SC_A_0 + 24
+ s32i a7, a2, MCONTEXT_SC_A_0 + 28
+1:
+ movi a6, SIG_SETMASK
+ addi a7, a9, UCONTEXT_SIGMASK
+ addi a8, a2, UCONTEXT_SIGMASK
+ mov a2, a9
+ movi a4, JUMPTARGET (sigprocmask)
+ callx4 a4
+ bnez a6, .Lerror
+
+ l32i a0, a2, MCONTEXT_SC_PC
+
+ /* copy registers a0..a3 to spill area */
+ addi a3, a1, -16
+ l32i a4, a2, MCONTEXT_SC_A_0 + 0
+ l32i a5, a2, MCONTEXT_SC_A_0 + 4
+ l32i a6, a2, MCONTEXT_SC_A_0 + 8
+ l32i a7, a2, MCONTEXT_SC_A_0 + 12
+ s32i a4, a3, 0
+ s32i a5, a3, 4
+ s32i a6, a3, 8
+ s32i a7, a3, 12
+
+ /* if it was call4 then register setup is done */
+ extui a4, a0, 30, 2
+ bltui a4, 2, 1f
+
+ /* otherwise load spill overflow area address into a3 */
+ addi a3, a5, -16
+ l32i a3, a3, 4
+ addi a3, a3, -32
+ beqi a4, 2, 2f
+
+ /* copy registers a8..a11 to spill overflow area */
+ addi a3, a3, -16
+ l32i a4, a2, MCONTEXT_SC_A_0 + 32
+ l32i a5, a2, MCONTEXT_SC_A_0 + 36
+ l32i a6, a2, MCONTEXT_SC_A_0 + 40
+ l32i a7, a2, MCONTEXT_SC_A_0 + 44
+ s32i a4, a3, 16
+ s32i a5, a3, 20
+ s32i a6, a3, 24
+ s32i a7, a3, 28
+
+ /* copy registers a4..a7 to spill overflow area */
+2:
+ l32i a4, a2, MCONTEXT_SC_A_0 + 16
+ l32i a5, a2, MCONTEXT_SC_A_0 + 20
+ l32i a6, a2, MCONTEXT_SC_A_0 + 24
+ l32i a7, a2, MCONTEXT_SC_A_0 + 28
+ s32i a4, a3, 0
+ s32i a5, a3, 4
+ s32i a6, a3, 8
+ s32i a7, a3, 12
+1:
+ movi a2, 0
+ retw
+.Lerror:
+ mov a2, a6
+ retw
+END(__swapcontext)
+#else
+#error Unsupported Xtensa ABI
+#endif
+
+weak_alias (__swapcontext, swapcontext)
diff --git a/libc/sysdeps/linux/xtensa/sysdep.h b/libc/sysdeps/linux/xtensa/sysdep.h
index 0671f0783477..80b3f30fcc5d 100644
--- a/libc/sysdeps/linux/xtensa/sysdep.h
+++ b/libc/sysdeps/linux/xtensa/sysdep.h
@@ -39,12 +39,15 @@
#endif
-#define ENTRY(name) \
+#define ENTRY_PREFIX(name) \
.globl C_SYMBOL_NAME(name); \
ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name), @function); \
.align ALIGNARG(2); \
LITERAL_POSITION; \
- C_LABEL(name) \
+ C_LABEL(name)
+
+#define ENTRY(name) \
+ ENTRY_PREFIX(name) \
abi_entry(sp, FRAMESIZE);
#define HIDDEN_ENTRY(name) \
diff --git a/libc/sysdeps/linux/xtensa/ucontext_i.sym b/libc/sysdeps/linux/xtensa/ucontext_i.sym
new file mode 100644
index 000000000000..4770c36c9e1d
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/ucontext_i.sym
@@ -0,0 +1,15 @@
+#include <inttypes.h>
+#include <signal.h>
+#include <stddef.h>
+#include <sys/ucontext.h>
+
+SIG_BLOCK
+SIG_SETMASK
+
+-- Offsets of the fields in the ucontext_t structure.
+#define ucontext(member) offsetof (ucontext_t, member)
+#define mcontext(member) ucontext (uc_mcontext.member)
+
+UCONTEXT_SIGMASK ucontext (uc_sigmask)
+MCONTEXT_SC_A_0 mcontext (sc_a[0])
+MCONTEXT_SC_PC mcontext (sc_pc)
--
2.30.2
2
1
17 Jun '22
Implement getcontext, makecontext, setcontext and swapcontext.
Signed-off-by: Max Filippov <jcmvbkbc(a)gmail.com>
---
Changes v1->v2:
- drop wrong comment from __start_context
extra/Configs/Config.xtensa | 3 +-
libc/sysdeps/linux/xtensa/Makefile.arch | 3 +
libc/sysdeps/linux/xtensa/__start_context.S | 100 +++++++++++
libc/sysdeps/linux/xtensa/getcontext.S | 99 +++++++++++
libc/sysdeps/linux/xtensa/makecontext.c | 179 ++++++++++++++++++++
libc/sysdeps/linux/xtensa/setcontext.S | 116 +++++++++++++
libc/sysdeps/linux/xtensa/swapcontext.S | 173 +++++++++++++++++++
libc/sysdeps/linux/xtensa/sysdep.h | 7 +-
libc/sysdeps/linux/xtensa/ucontext_i.sym | 15 ++
9 files changed, 692 insertions(+), 3 deletions(-)
create mode 100644 libc/sysdeps/linux/xtensa/__start_context.S
create mode 100644 libc/sysdeps/linux/xtensa/getcontext.S
create mode 100644 libc/sysdeps/linux/xtensa/makecontext.c
create mode 100644 libc/sysdeps/linux/xtensa/setcontext.S
create mode 100644 libc/sysdeps/linux/xtensa/swapcontext.S
create mode 100644 libc/sysdeps/linux/xtensa/ucontext_i.sym
diff --git a/extra/Configs/Config.xtensa b/extra/Configs/Config.xtensa
index 3ee8817ba1a2..7316c542d896 100644
--- a/extra/Configs/Config.xtensa
+++ b/extra/Configs/Config.xtensa
@@ -10,5 +10,6 @@ config TARGET_ARCH
config FORCE_OPTIONS_FOR_ARCH
bool
default y
- select ARCH_HAS_DEPRECATED_SYSCALLS
select ARCH_ANY_ENDIAN
+ select ARCH_HAS_DEPRECATED_SYSCALLS
+ select ARCH_HAS_UCONTEXT
diff --git a/libc/sysdeps/linux/xtensa/Makefile.arch b/libc/sysdeps/linux/xtensa/Makefile.arch
index 23cd08ee5687..f3a93caaafb1 100644
--- a/libc/sysdeps/linux/xtensa/Makefile.arch
+++ b/libc/sysdeps/linux/xtensa/Makefile.arch
@@ -10,3 +10,6 @@ SSRC-y := bsd-_setjmp.S bsd-setjmp.S setjmp.S clone.S \
sigrestorer.S syscall.S mmap.S windowspill.S __longjmp.S vfork.S
CSRC-$(if $(UCLIBC_HAS_THREADS_NATIVE),,y) += fork.c
+
+CSRC-$(UCLIBC_HAS_CONTEXT_FUNCS) += makecontext.c
+SSRC-$(UCLIBC_HAS_CONTEXT_FUNCS) += setcontext.S getcontext.S swapcontext.S __start_context.S
diff --git a/libc/sysdeps/linux/xtensa/__start_context.S b/libc/sysdeps/linux/xtensa/__start_context.S
new file mode 100644
index 000000000000..a30d7b6188ad
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/__start_context.S
@@ -0,0 +1,100 @@
+/* Copyright (C) 2018 - 2022 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 <sysdep.h>
+
+#if defined(__XTENSA_CALL0_ABI__)
+/*
+ * There's no entry instruction, makecontext sets up ucontext_t as if
+ * getcontext was called above and is about to return here.
+ * Registers on entry to this function:
+ * a12: func to call
+ * a13: ucp->uc_link, next context to activate if func returns
+ * a14: func argc
+ */
+ .literal_position
+
+ENTRY_PREFIX(__start_context)
+
+ beqz a14, 1f
+
+ /* load func arguments 0..1 from stack and free that space */
+ l32i a2, a1, 8
+ l32i a3, a1, 12
+ addi a1, a1, 16
+ bltui a14, 3, 1f
+
+ /* load func arguments 2..5 from stack and free that space */
+ l32i a4, a1, 0
+ l32i a5, a1, 4
+ l32i a6, a1, 8
+ l32i a7, a1, 12
+ addi a1, a1, 16
+ /* func arguments 6..argc - 1 are now at the top of the stack */
+1:
+ callx0 a12
+ beqz a13, 1f
+ mov a2, a13
+ movi a4, JUMPTARGET (setcontext)
+ callx0 a4
+1:
+ movi a4, JUMPTARGET (_exit)
+ movi a2, 0
+ callx0 a4
+ ill
+END(__start_context)
+#elif defined(__XTENSA_WINDOWED_ABI__)
+/*
+ * There's no entry instruction, makecontext sets up ucontext_t as if
+ * getcontext was called above and is about to return here.
+ * Registers on entry to this function:
+ * a2: func to call
+ * a3: ucp->uc_link, next context to activate if func returns
+ * a4: func argc
+ * a5..a7: func arguments 0..2
+ */
+ .literal_position
+
+ENTRY_PREFIX(__start_context)
+
+ mov a10, a5
+ mov a11, a6
+ mov a12, a7
+ bltui a4, 4, 1f
+
+ /* load func arguments 3..5 from stack and free that space */
+ l32i a13, a1, 4
+ l32i a14, a1, 8
+ l32i a15, a1, 12
+ addi a5, a1, 16
+ movsp a1, a5
+ /* func arguments 6..argc - 1 are now at the top of the stack */
+1:
+ callx8 a2
+ beqz a3, 1f
+ mov a6, a3
+ movi a4, JUMPTARGET (setcontext)
+ callx4 a4
+1:
+ movi a4, JUMPTARGET (_exit)
+ movi a6, 0
+ callx4 a4
+ ill
+END(__start_context)
+#else
+#error Unsupported Xtensa ABI
+#endif
diff --git a/libc/sysdeps/linux/xtensa/getcontext.S b/libc/sysdeps/linux/xtensa/getcontext.S
new file mode 100644
index 000000000000..fbb70c3f8720
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/getcontext.S
@@ -0,0 +1,99 @@
+/* Copyright (C) 2018 - 2022 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 <sysdep.h>
+#include "ucontext_i.h"
+
+#if defined(__XTENSA_CALL0_ABI__)
+ENTRY(__getcontext)
+ s32i a0, a2, MCONTEXT_SC_PC
+ s32i a1, a2, MCONTEXT_SC_A_0 + 4
+
+ /* save callee-saved registers in the context */
+ s32i a12, a2, MCONTEXT_SC_A_0 + 48
+ s32i a13, a2, MCONTEXT_SC_A_0 + 52
+ s32i a14, a2, MCONTEXT_SC_A_0 + 56
+ s32i a15, a2, MCONTEXT_SC_A_0 + 60
+
+ movi a3, 0
+ addi a4, a2, UCONTEXT_SIGMASK
+ movi a2, 0
+ movi a5, JUMPTARGET (sigprocmask)
+ jx a5
+END(__getcontext)
+#elif defined(__XTENSA_WINDOWED_ABI__)
+ENTRY(__getcontext)
+ movi a4, __window_spill
+ callx4 a4
+ s32i a0, a2, MCONTEXT_SC_PC
+
+ /* copy registers a0..a3 from spill area */
+ addi a3, a1, -16
+ l32i a4, a3, 0
+ l32i a5, a3, 4
+ l32i a6, a3, 8
+ l32i a7, a3, 12
+ s32i a4, a2, MCONTEXT_SC_A_0 + 0
+ s32i a5, a2, MCONTEXT_SC_A_0 + 4
+ s32i a6, a2, MCONTEXT_SC_A_0 + 8
+ s32i a7, a2, MCONTEXT_SC_A_0 + 12
+
+ /* if it was call4 then register saving is done */
+ extui a4, a0, 30, 2
+ bltui a4, 2, 1f
+
+ /* otherwise load spill overflow area address into a3 */
+ addi a3, a5, -16
+ l32i a3, a3, 4
+ addi a3, a3, -32
+ beqi a4, 2, 2f
+
+ /* copy registers a8..a11 from spill overflow area */
+ addi a3, a3, -16
+ l32i a4, a3, 16
+ l32i a5, a3, 20
+ l32i a6, a3, 24
+ l32i a7, a3, 28
+ s32i a4, a2, MCONTEXT_SC_A_0 + 32
+ s32i a5, a2, MCONTEXT_SC_A_0 + 36
+ s32i a6, a2, MCONTEXT_SC_A_0 + 40
+ s32i a7, a2, MCONTEXT_SC_A_0 + 44
+
+ /* copy registers a4..a7 from spill overflow area */
+2:
+ l32i a4, a3, 0
+ l32i a5, a3, 4
+ l32i a6, a3, 8
+ l32i a7, a3, 12
+ s32i a4, a2, MCONTEXT_SC_A_0 + 16
+ s32i a5, a2, MCONTEXT_SC_A_0 + 20
+ s32i a6, a2, MCONTEXT_SC_A_0 + 24
+ s32i a7, a2, MCONTEXT_SC_A_0 + 28
+1:
+ movi a6, 0
+ movi a7, 0
+ addi a8, a2, UCONTEXT_SIGMASK
+ movi a4, JUMPTARGET (sigprocmask)
+ callx4 a4
+ mov a2, a6
+ retw
+END(__getcontext)
+#else
+#error Unsupported Xtensa ABI
+#endif
+
+weak_alias (__getcontext, getcontext)
diff --git a/libc/sysdeps/linux/xtensa/makecontext.c b/libc/sysdeps/linux/xtensa/makecontext.c
new file mode 100644
index 000000000000..da26a0130325
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/makecontext.c
@@ -0,0 +1,179 @@
+/* Copyright (C) 2018 - 2022 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 <sysdep.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <string.h>
+#include <ucontext.h>
+
+extern void __start_context (void);
+
+#if defined(__XTENSA_CALL0_ABI__)
+/*
+ * makecontext sets up new stack like this:
+ *
+ * +------------------ stack top (uc_stack.ss_sp + uc_stack.ss_size)
+ * | optional alignment
+ * +------------------ CFA of __start_context, initial sp points here
+ * | optional padding
+ * +------------------ Optional arguments 6..argc - 1
+ * | func arg argc - 1
+ * | func arg argc - 2
+ * | ...
+ * | func arg 6
+ * +------------------ Optional arguments 2..5
+ * | func arg 5
+ * 16 | func arg 4
+ * | func arg 3
+ * | func arg 2
+ * +------------------ Optional arguments 0..1
+ * | func arg 1
+ * 16 | func arg 0
+ * | padding
+ * | padding
+ * +------------------ CFA of pseudo getcontext
+ * |
+ * +------------------ stack bottom (uc_stack.ss_sp)
+ *
+ * When argc is 0 arguments areas are not allocated,
+ * when 1 <= argc < 3 only area for arguments 0..1 is allocated,
+ * when 3 <= argc < 7 areas for arguments 0..1 and 2..5 is allocated,
+ * when argc >= 7 all three arguments areas are allocated.
+ * Arguments 0..5 area is deallocated by the __start_context after
+ * arguments are loaded into registers.
+ * uc_mcontext registers are set as if __start_context made call0
+ * to getcontext, sp points to that pseudo getcontext CFA.
+ * setcontext/swapcontext will arrange for restoring regiters
+ * a1, a12..a15 of __start_context.
+ */
+
+void
+__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
+{
+ unsigned long sp = ((unsigned long) ucp->uc_stack.ss_sp
+ + ucp->uc_stack.ss_size) & -16;
+ int i;
+
+ if (argc > 0)
+ sp -= 4 * (argc + 2);
+ sp &= -16;
+
+ ucp->uc_mcontext.sc_pc = (unsigned long) __start_context;
+ ucp->uc_mcontext.sc_a[1] = sp;
+ ucp->uc_mcontext.sc_a[12] = (unsigned long) func;
+ ucp->uc_mcontext.sc_a[13] = (unsigned long) ucp->uc_link;
+ ucp->uc_mcontext.sc_a[14] = argc;
+
+ if (argc)
+ {
+ va_list ap;
+
+ va_start (ap, argc);
+ for (i = 0; i < argc; ++i)
+ ((int *) sp)[i + 2] = va_arg (ap, int);
+ va_end (ap);
+ }
+}
+#elif defined(__XTENSA_WINDOWED_ABI__)
+/*
+ * makecontext sets up new stack like this:
+ *
+ * +------------------ stack top (uc_stack.ss_sp + uc_stack.ss_size)
+ * | optional alignment
+ * +------------------ CFA of __start_context
+ * 16 | Outermost caller spill area
+ * +------------------
+ * 16 | __start_context overflow area
+ * +------------------ initial sp points here
+ * | optional padding
+ * +------------------ Optional arguments 6..argc - 1
+ * | func arg argc - 1
+ * | func arg argc - 2
+ * | ...
+ * | func arg 6
+ * +------------------ Optional arguments 3..5
+ * | func arg 5
+ * 16 | func arg 4
+ * | func arg 3
+ * | padding
+ * +------------------ CFA of pseudo getcontext
+ * 16 | __start_context caller spill area
+ * +------------------
+ * |
+ * +------------------ stack bottom (uc_stack.ss_sp)
+ *
+ * When argc < 4 both arguments areas are not allocated,
+ * when 4 <= argc < 7 only area for arguments 3..5 is allocated,
+ * when argc >= 7 both arguments areas are allocated.
+ * Arguments 3..5 area is deallocated by the __start_context after
+ * arguments are loaded into registers.
+ * uc_mcontext registers are set as if __start_context made call8
+ * to getcontext, sp points to that pseudo getcontext CFA, spill
+ * area under that sp has a1 pointing to the __start_context CFA
+ * at the top of the stack. setcontext/swapcontext will arrange for
+ * restoring regiters a0..a7 of __start_context.
+ */
+
+void
+__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
+{
+ unsigned long sp = ((unsigned long) ucp->uc_stack.ss_sp
+ + ucp->uc_stack.ss_size - 32) & -16;
+ unsigned long spill0[4] =
+ {
+ 0, sp + 32, 0, 0,
+ };
+ int i;
+
+ memset ((void *) sp, 0, 32);
+
+ if (argc > 2)
+ sp -= 4 * (argc - 2);
+ sp &= -16;
+
+ ucp->uc_mcontext.sc_pc =
+ ((unsigned long) __start_context & 0x3fffffff) + 0x80000000;
+ ucp->uc_mcontext.sc_a[0] = 0;
+ ucp->uc_mcontext.sc_a[1] = sp;
+ ucp->uc_mcontext.sc_a[2] = (unsigned long) func;
+ ucp->uc_mcontext.sc_a[3] = (unsigned long) ucp->uc_link;
+ ucp->uc_mcontext.sc_a[4] = argc;
+
+ if (argc)
+ {
+ va_list ap;
+
+ va_start (ap, argc);
+ for (i = 0; i < argc; ++i)
+ {
+ if (i < 3)
+ ucp->uc_mcontext.sc_a[5 + i] = va_arg (ap, int);
+ else
+ ((int *) sp)[i - 2] = va_arg (ap, int);
+ }
+ va_end (ap);
+ }
+
+ sp -= 16;
+ memcpy ((void *) sp, spill0, sizeof (spill0));
+}
+#else
+#error Unsupported Xtensa ABI
+#endif
+
+weak_alias (__makecontext, makecontext)
diff --git a/libc/sysdeps/linux/xtensa/setcontext.S b/libc/sysdeps/linux/xtensa/setcontext.S
new file mode 100644
index 000000000000..4df7cc049006
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/setcontext.S
@@ -0,0 +1,116 @@
+/* Copyright (C) 2018 - 2022 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 <sysdep.h>
+#include "ucontext_i.h"
+
+#if defined(__XTENSA_CALL0_ABI__)
+ENTRY(__setcontext)
+ addi sp, sp, -16
+ s32i a0, sp, 0
+ s32i a2, sp, 4
+
+ addi a3, a2, UCONTEXT_SIGMASK
+ movi a4, 0
+ movi a2, SIG_SETMASK
+ movi a5, JUMPTARGET (sigprocmask)
+ callx0 a5
+ bnez a2, .Lerror
+
+ l32i a2, sp, 4
+ l32i a0, a2, MCONTEXT_SC_PC
+ l32i a1, a2, MCONTEXT_SC_A_0 + 4
+
+ /* load callee-saved registers from the context */
+ l32i a12, a2, MCONTEXT_SC_A_0 + 48
+ l32i a13, a2, MCONTEXT_SC_A_0 + 52
+ l32i a14, a2, MCONTEXT_SC_A_0 + 56
+ l32i a15, a2, MCONTEXT_SC_A_0 + 60
+ movi a2, 0
+ ret
+.Lerror:
+ l32i a0, sp, 0
+ addi sp, sp, 16
+ ret
+END(__setcontext)
+#elif defined(__XTENSA_WINDOWED_ABI__)
+ENTRY(__setcontext)
+ movi a6, SIG_SETMASK
+ addi a7, a2, UCONTEXT_SIGMASK
+ movi a8, 0
+ movi a4, JUMPTARGET (sigprocmask)
+ callx4 a4
+ bnez a6, .Lerror
+ movi a4, __window_spill
+ callx4 a4
+
+ l32i a0, a2, MCONTEXT_SC_PC
+
+ /* copy registers a0..a3 to spill area */
+ addi a3, a1, -16
+ l32i a4, a2, MCONTEXT_SC_A_0 + 0
+ l32i a5, a2, MCONTEXT_SC_A_0 + 4
+ l32i a6, a2, MCONTEXT_SC_A_0 + 8
+ l32i a7, a2, MCONTEXT_SC_A_0 + 12
+ s32i a4, a3, 0
+ s32i a5, a3, 4
+ s32i a6, a3, 8
+ s32i a7, a3, 12
+
+ /* if it was call4 then register setup is done */
+ extui a4, a0, 30, 2
+ bltui a4, 2, 1f
+
+ /* otherwise load spill overflow area address into a3 */
+ addi a3, a5, -16
+ l32i a3, a3, 4
+ addi a3, a3, -32
+ beqi a4, 2, 2f
+
+ /* copy registers a8..a11 to spill overflow area */
+ addi a3, a3, -16
+ l32i a4, a2, MCONTEXT_SC_A_0 + 32
+ l32i a5, a2, MCONTEXT_SC_A_0 + 36
+ l32i a6, a2, MCONTEXT_SC_A_0 + 40
+ l32i a7, a2, MCONTEXT_SC_A_0 + 44
+ s32i a4, a3, 16
+ s32i a5, a3, 20
+ s32i a6, a3, 24
+ s32i a7, a3, 28
+
+ /* copy registers a4..a7 to spill overflow area */
+2:
+ l32i a4, a2, MCONTEXT_SC_A_0 + 16
+ l32i a5, a2, MCONTEXT_SC_A_0 + 20
+ l32i a6, a2, MCONTEXT_SC_A_0 + 24
+ l32i a7, a2, MCONTEXT_SC_A_0 + 28
+ s32i a4, a3, 0
+ s32i a5, a3, 4
+ s32i a6, a3, 8
+ s32i a7, a3, 12
+1:
+ movi a2, 0
+ retw
+.Lerror:
+ mov a2, a6
+ retw
+END(__setcontext)
+#else
+#error Unsupported Xtensa ABI
+#endif
+
+weak_alias (__setcontext, setcontext)
diff --git a/libc/sysdeps/linux/xtensa/swapcontext.S b/libc/sysdeps/linux/xtensa/swapcontext.S
new file mode 100644
index 000000000000..a215edc6d54a
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/swapcontext.S
@@ -0,0 +1,173 @@
+/* Copyright (C) 2018 - 2022 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 <sysdep.h>
+#include "ucontext_i.h"
+
+#if defined(__XTENSA_CALL0_ABI__)
+ENTRY(__swapcontext)
+ s32i a0, a2, MCONTEXT_SC_PC
+ s32i a1, a2, MCONTEXT_SC_A_0 + 4
+
+ /* save callee-saved registers in the context */
+ s32i a12, a2, MCONTEXT_SC_A_0 + 48
+ s32i a13, a2, MCONTEXT_SC_A_0 + 52
+ s32i a14, a2, MCONTEXT_SC_A_0 + 56
+ s32i a15, a2, MCONTEXT_SC_A_0 + 60
+
+ mov a12, a3
+ mov a13, a2
+
+ addi a3, a3, UCONTEXT_SIGMASK
+ addi a4, a2, UCONTEXT_SIGMASK
+ movi a2, SIG_SETMASK
+ movi a5, JUMPTARGET (sigprocmask)
+ callx0 a5
+ bnez a2, .Lerror
+
+ mov a2, a12
+ l32i a0, a2, MCONTEXT_SC_PC
+ l32i a1, a2, MCONTEXT_SC_A_0 + 4
+
+ /* load callee-saved registers from the context */
+ l32i a12, a2, MCONTEXT_SC_A_0 + 48
+ l32i a13, a2, MCONTEXT_SC_A_0 + 52
+ l32i a14, a2, MCONTEXT_SC_A_0 + 56
+ l32i a15, a2, MCONTEXT_SC_A_0 + 60
+
+ movi a2, 0
+ ret
+.Lerror:
+ l32i a0, a13, MCONTEXT_SC_PC
+ l32i a12, a13, MCONTEXT_SC_A_0 + 48
+ l32i a13, a13, MCONTEXT_SC_A_0 + 52
+ ret
+END(__swapcontext)
+#elif defined(__XTENSA_WINDOWED_ABI__)
+ENTRY(__swapcontext)
+ movi a4, __window_spill
+ callx4 a4
+ mov a9, a3
+ s32i a0, a2, MCONTEXT_SC_PC
+
+ /* copy registers a0..a3 from spill area */
+ addi a3, a1, -16
+ l32i a4, a3, 0
+ l32i a5, a3, 4
+ l32i a6, a3, 8
+ l32i a7, a3, 12
+ s32i a4, a2, MCONTEXT_SC_A_0 + 0
+ s32i a5, a2, MCONTEXT_SC_A_0 + 4
+ s32i a6, a2, MCONTEXT_SC_A_0 + 8
+ s32i a7, a2, MCONTEXT_SC_A_0 + 12
+
+ /* if it was call4 then register saving is done */
+ extui a4, a0, 30, 2
+ bltui a4, 2, 1f
+
+ /* otherwise load spill overflow area address into a3 */
+ addi a3, a5, -16
+ l32i a3, a3, 4
+ addi a3, a3, -32
+ beqi a4, 2, 2f
+
+ /* copy registers a8..a11 from spill overflow area */
+ addi a3, a3, -16
+ l32i a4, a3, 16
+ l32i a5, a3, 20
+ l32i a6, a3, 24
+ l32i a7, a3, 28
+ s32i a4, a2, MCONTEXT_SC_A_0 + 32
+ s32i a5, a2, MCONTEXT_SC_A_0 + 36
+ s32i a6, a2, MCONTEXT_SC_A_0 + 40
+ s32i a7, a2, MCONTEXT_SC_A_0 + 44
+
+ /* copy registers a4..a7 from spill overflow area */
+2:
+ l32i a4, a3, 0
+ l32i a5, a3, 4
+ l32i a6, a3, 8
+ l32i a7, a3, 12
+ s32i a4, a2, MCONTEXT_SC_A_0 + 16
+ s32i a5, a2, MCONTEXT_SC_A_0 + 20
+ s32i a6, a2, MCONTEXT_SC_A_0 + 24
+ s32i a7, a2, MCONTEXT_SC_A_0 + 28
+1:
+ movi a6, SIG_SETMASK
+ addi a7, a9, UCONTEXT_SIGMASK
+ addi a8, a2, UCONTEXT_SIGMASK
+ mov a2, a9
+ movi a4, JUMPTARGET (sigprocmask)
+ callx4 a4
+ bnez a6, .Lerror
+
+ l32i a0, a2, MCONTEXT_SC_PC
+
+ /* copy registers a0..a3 to spill area */
+ addi a3, a1, -16
+ l32i a4, a2, MCONTEXT_SC_A_0 + 0
+ l32i a5, a2, MCONTEXT_SC_A_0 + 4
+ l32i a6, a2, MCONTEXT_SC_A_0 + 8
+ l32i a7, a2, MCONTEXT_SC_A_0 + 12
+ s32i a4, a3, 0
+ s32i a5, a3, 4
+ s32i a6, a3, 8
+ s32i a7, a3, 12
+
+ /* if it was call4 then register setup is done */
+ extui a4, a0, 30, 2
+ bltui a4, 2, 1f
+
+ /* otherwise load spill overflow area address into a3 */
+ addi a3, a5, -16
+ l32i a3, a3, 4
+ addi a3, a3, -32
+ beqi a4, 2, 2f
+
+ /* copy registers a8..a11 to spill overflow area */
+ addi a3, a3, -16
+ l32i a4, a2, MCONTEXT_SC_A_0 + 32
+ l32i a5, a2, MCONTEXT_SC_A_0 + 36
+ l32i a6, a2, MCONTEXT_SC_A_0 + 40
+ l32i a7, a2, MCONTEXT_SC_A_0 + 44
+ s32i a4, a3, 16
+ s32i a5, a3, 20
+ s32i a6, a3, 24
+ s32i a7, a3, 28
+
+ /* copy registers a4..a7 to spill overflow area */
+2:
+ l32i a4, a2, MCONTEXT_SC_A_0 + 16
+ l32i a5, a2, MCONTEXT_SC_A_0 + 20
+ l32i a6, a2, MCONTEXT_SC_A_0 + 24
+ l32i a7, a2, MCONTEXT_SC_A_0 + 28
+ s32i a4, a3, 0
+ s32i a5, a3, 4
+ s32i a6, a3, 8
+ s32i a7, a3, 12
+1:
+ movi a2, 0
+ retw
+.Lerror:
+ mov a2, a6
+ retw
+END(__swapcontext)
+#else
+#error Unsupported Xtensa ABI
+#endif
+
+weak_alias (__swapcontext, swapcontext)
diff --git a/libc/sysdeps/linux/xtensa/sysdep.h b/libc/sysdeps/linux/xtensa/sysdep.h
index 0671f0783477..80b3f30fcc5d 100644
--- a/libc/sysdeps/linux/xtensa/sysdep.h
+++ b/libc/sysdeps/linux/xtensa/sysdep.h
@@ -39,12 +39,15 @@
#endif
-#define ENTRY(name) \
+#define ENTRY_PREFIX(name) \
.globl C_SYMBOL_NAME(name); \
ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name), @function); \
.align ALIGNARG(2); \
LITERAL_POSITION; \
- C_LABEL(name) \
+ C_LABEL(name)
+
+#define ENTRY(name) \
+ ENTRY_PREFIX(name) \
abi_entry(sp, FRAMESIZE);
#define HIDDEN_ENTRY(name) \
diff --git a/libc/sysdeps/linux/xtensa/ucontext_i.sym b/libc/sysdeps/linux/xtensa/ucontext_i.sym
new file mode 100644
index 000000000000..4770c36c9e1d
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/ucontext_i.sym
@@ -0,0 +1,15 @@
+#include <inttypes.h>
+#include <signal.h>
+#include <stddef.h>
+#include <sys/ucontext.h>
+
+SIG_BLOCK
+SIG_SETMASK
+
+-- Offsets of the fields in the ucontext_t structure.
+#define ucontext(member) offsetof (ucontext_t, member)
+#define mcontext(member) ucontext (uc_mcontext.member)
+
+UCONTEXT_SIGMASK ucontext (uc_sigmask)
+MCONTEXT_SC_A_0 mcontext (sc_a[0])
+MCONTEXT_SC_PC mcontext (sc_pc)
--
2.30.2
1
0
Implement getcontext, makecontext, setcontext and swapcontext.
Signed-off-by: Max Filippov <jcmvbkbc(a)gmail.com>
---
extra/Configs/Config.xtensa | 3 +-
libc/sysdeps/linux/xtensa/Makefile.arch | 3 +
libc/sysdeps/linux/xtensa/__start_context.S | 103 +++++++++++
libc/sysdeps/linux/xtensa/getcontext.S | 99 +++++++++++
libc/sysdeps/linux/xtensa/makecontext.c | 179 ++++++++++++++++++++
libc/sysdeps/linux/xtensa/setcontext.S | 116 +++++++++++++
libc/sysdeps/linux/xtensa/swapcontext.S | 173 +++++++++++++++++++
libc/sysdeps/linux/xtensa/sysdep.h | 7 +-
libc/sysdeps/linux/xtensa/ucontext_i.sym | 15 ++
9 files changed, 695 insertions(+), 3 deletions(-)
create mode 100644 libc/sysdeps/linux/xtensa/__start_context.S
create mode 100644 libc/sysdeps/linux/xtensa/getcontext.S
create mode 100644 libc/sysdeps/linux/xtensa/makecontext.c
create mode 100644 libc/sysdeps/linux/xtensa/setcontext.S
create mode 100644 libc/sysdeps/linux/xtensa/swapcontext.S
create mode 100644 libc/sysdeps/linux/xtensa/ucontext_i.sym
diff --git a/extra/Configs/Config.xtensa b/extra/Configs/Config.xtensa
index 3ee8817ba1a2..7316c542d896 100644
--- a/extra/Configs/Config.xtensa
+++ b/extra/Configs/Config.xtensa
@@ -10,5 +10,6 @@ config TARGET_ARCH
config FORCE_OPTIONS_FOR_ARCH
bool
default y
- select ARCH_HAS_DEPRECATED_SYSCALLS
select ARCH_ANY_ENDIAN
+ select ARCH_HAS_DEPRECATED_SYSCALLS
+ select ARCH_HAS_UCONTEXT
diff --git a/libc/sysdeps/linux/xtensa/Makefile.arch b/libc/sysdeps/linux/xtensa/Makefile.arch
index 23cd08ee5687..f3a93caaafb1 100644
--- a/libc/sysdeps/linux/xtensa/Makefile.arch
+++ b/libc/sysdeps/linux/xtensa/Makefile.arch
@@ -10,3 +10,6 @@ SSRC-y := bsd-_setjmp.S bsd-setjmp.S setjmp.S clone.S \
sigrestorer.S syscall.S mmap.S windowspill.S __longjmp.S vfork.S
CSRC-$(if $(UCLIBC_HAS_THREADS_NATIVE),,y) += fork.c
+
+CSRC-$(UCLIBC_HAS_CONTEXT_FUNCS) += makecontext.c
+SSRC-$(UCLIBC_HAS_CONTEXT_FUNCS) += setcontext.S getcontext.S swapcontext.S __start_context.S
diff --git a/libc/sysdeps/linux/xtensa/__start_context.S b/libc/sysdeps/linux/xtensa/__start_context.S
new file mode 100644
index 000000000000..f92c01112fa7
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/__start_context.S
@@ -0,0 +1,103 @@
+/* Copyright (C) 2018 - 2022 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 <sysdep.h>
+
+#if defined(__XTENSA_CALL0_ABI__)
+/*
+ * There's no entry instruction, makecontext sets up ucontext_t as if
+ * getcontext was called above and is about to return here.
+ * Registers on entry to this function:
+ * a12: func to call
+ * a13: ucp->uc_link, next context to activate if func returns
+ * a14: func argc
+ * a2..a4: func arguments 0..2
+ *
+ */
+ .literal_position
+
+ENTRY_PREFIX(__start_context)
+
+ beqz a14, 1f
+
+ /* load func arguments 0..1 from stack and free that space */
+ l32i a2, a1, 8
+ l32i a3, a1, 12
+ addi a1, a1, 16
+ bltui a14, 3, 1f
+
+ /* load func arguments 2..5 from stack and free that space */
+ l32i a4, a1, 0
+ l32i a5, a1, 4
+ l32i a6, a1, 8
+ l32i a7, a1, 12
+ addi a1, a1, 16
+ /* func arguments 6..argc - 1 are now at the top of the stack */
+1:
+ callx0 a12
+ beqz a13, 1f
+ mov a2, a13
+ movi a4, JUMPTARGET (setcontext)
+ callx0 a4
+1:
+ movi a4, JUMPTARGET (_exit)
+ movi a2, 0
+ callx0 a4
+ ill
+END(__start_context)
+#elif defined(__XTENSA_WINDOWED_ABI__)
+/*
+ * There's no entry instruction, makecontext sets up ucontext_t as if
+ * getcontext was called above and is about to return here.
+ * Registers on entry to this function:
+ * a2: func to call
+ * a3: ucp->uc_link, next context to activate if func returns
+ * a4: func argc
+ * a5..a7: func arguments 0..2
+ *
+ */
+ .literal_position
+
+ENTRY_PREFIX(__start_context)
+
+ mov a10, a5
+ mov a11, a6
+ mov a12, a7
+ bltui a4, 4, 1f
+
+ /* load func arguments 3..5 from stack and free that space */
+ l32i a13, a1, 4
+ l32i a14, a1, 8
+ l32i a15, a1, 12
+ addi a5, a1, 16
+ movsp a1, a5
+ /* func arguments 6..argc - 1 are now at the top of the stack */
+1:
+ callx8 a2
+ beqz a3, 1f
+ mov a6, a3
+ movi a4, JUMPTARGET (setcontext)
+ callx4 a4
+1:
+ movi a4, JUMPTARGET (_exit)
+ movi a6, 0
+ callx4 a4
+ ill
+END(__start_context)
+#else
+#error Unsupported Xtensa ABI
+#endif
diff --git a/libc/sysdeps/linux/xtensa/getcontext.S b/libc/sysdeps/linux/xtensa/getcontext.S
new file mode 100644
index 000000000000..fbb70c3f8720
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/getcontext.S
@@ -0,0 +1,99 @@
+/* Copyright (C) 2018 - 2022 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 <sysdep.h>
+#include "ucontext_i.h"
+
+#if defined(__XTENSA_CALL0_ABI__)
+ENTRY(__getcontext)
+ s32i a0, a2, MCONTEXT_SC_PC
+ s32i a1, a2, MCONTEXT_SC_A_0 + 4
+
+ /* save callee-saved registers in the context */
+ s32i a12, a2, MCONTEXT_SC_A_0 + 48
+ s32i a13, a2, MCONTEXT_SC_A_0 + 52
+ s32i a14, a2, MCONTEXT_SC_A_0 + 56
+ s32i a15, a2, MCONTEXT_SC_A_0 + 60
+
+ movi a3, 0
+ addi a4, a2, UCONTEXT_SIGMASK
+ movi a2, 0
+ movi a5, JUMPTARGET (sigprocmask)
+ jx a5
+END(__getcontext)
+#elif defined(__XTENSA_WINDOWED_ABI__)
+ENTRY(__getcontext)
+ movi a4, __window_spill
+ callx4 a4
+ s32i a0, a2, MCONTEXT_SC_PC
+
+ /* copy registers a0..a3 from spill area */
+ addi a3, a1, -16
+ l32i a4, a3, 0
+ l32i a5, a3, 4
+ l32i a6, a3, 8
+ l32i a7, a3, 12
+ s32i a4, a2, MCONTEXT_SC_A_0 + 0
+ s32i a5, a2, MCONTEXT_SC_A_0 + 4
+ s32i a6, a2, MCONTEXT_SC_A_0 + 8
+ s32i a7, a2, MCONTEXT_SC_A_0 + 12
+
+ /* if it was call4 then register saving is done */
+ extui a4, a0, 30, 2
+ bltui a4, 2, 1f
+
+ /* otherwise load spill overflow area address into a3 */
+ addi a3, a5, -16
+ l32i a3, a3, 4
+ addi a3, a3, -32
+ beqi a4, 2, 2f
+
+ /* copy registers a8..a11 from spill overflow area */
+ addi a3, a3, -16
+ l32i a4, a3, 16
+ l32i a5, a3, 20
+ l32i a6, a3, 24
+ l32i a7, a3, 28
+ s32i a4, a2, MCONTEXT_SC_A_0 + 32
+ s32i a5, a2, MCONTEXT_SC_A_0 + 36
+ s32i a6, a2, MCONTEXT_SC_A_0 + 40
+ s32i a7, a2, MCONTEXT_SC_A_0 + 44
+
+ /* copy registers a4..a7 from spill overflow area */
+2:
+ l32i a4, a3, 0
+ l32i a5, a3, 4
+ l32i a6, a3, 8
+ l32i a7, a3, 12
+ s32i a4, a2, MCONTEXT_SC_A_0 + 16
+ s32i a5, a2, MCONTEXT_SC_A_0 + 20
+ s32i a6, a2, MCONTEXT_SC_A_0 + 24
+ s32i a7, a2, MCONTEXT_SC_A_0 + 28
+1:
+ movi a6, 0
+ movi a7, 0
+ addi a8, a2, UCONTEXT_SIGMASK
+ movi a4, JUMPTARGET (sigprocmask)
+ callx4 a4
+ mov a2, a6
+ retw
+END(__getcontext)
+#else
+#error Unsupported Xtensa ABI
+#endif
+
+weak_alias (__getcontext, getcontext)
diff --git a/libc/sysdeps/linux/xtensa/makecontext.c b/libc/sysdeps/linux/xtensa/makecontext.c
new file mode 100644
index 000000000000..da26a0130325
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/makecontext.c
@@ -0,0 +1,179 @@
+/* Copyright (C) 2018 - 2022 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 <sysdep.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <string.h>
+#include <ucontext.h>
+
+extern void __start_context (void);
+
+#if defined(__XTENSA_CALL0_ABI__)
+/*
+ * makecontext sets up new stack like this:
+ *
+ * +------------------ stack top (uc_stack.ss_sp + uc_stack.ss_size)
+ * | optional alignment
+ * +------------------ CFA of __start_context, initial sp points here
+ * | optional padding
+ * +------------------ Optional arguments 6..argc - 1
+ * | func arg argc - 1
+ * | func arg argc - 2
+ * | ...
+ * | func arg 6
+ * +------------------ Optional arguments 2..5
+ * | func arg 5
+ * 16 | func arg 4
+ * | func arg 3
+ * | func arg 2
+ * +------------------ Optional arguments 0..1
+ * | func arg 1
+ * 16 | func arg 0
+ * | padding
+ * | padding
+ * +------------------ CFA of pseudo getcontext
+ * |
+ * +------------------ stack bottom (uc_stack.ss_sp)
+ *
+ * When argc is 0 arguments areas are not allocated,
+ * when 1 <= argc < 3 only area for arguments 0..1 is allocated,
+ * when 3 <= argc < 7 areas for arguments 0..1 and 2..5 is allocated,
+ * when argc >= 7 all three arguments areas are allocated.
+ * Arguments 0..5 area is deallocated by the __start_context after
+ * arguments are loaded into registers.
+ * uc_mcontext registers are set as if __start_context made call0
+ * to getcontext, sp points to that pseudo getcontext CFA.
+ * setcontext/swapcontext will arrange for restoring regiters
+ * a1, a12..a15 of __start_context.
+ */
+
+void
+__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
+{
+ unsigned long sp = ((unsigned long) ucp->uc_stack.ss_sp
+ + ucp->uc_stack.ss_size) & -16;
+ int i;
+
+ if (argc > 0)
+ sp -= 4 * (argc + 2);
+ sp &= -16;
+
+ ucp->uc_mcontext.sc_pc = (unsigned long) __start_context;
+ ucp->uc_mcontext.sc_a[1] = sp;
+ ucp->uc_mcontext.sc_a[12] = (unsigned long) func;
+ ucp->uc_mcontext.sc_a[13] = (unsigned long) ucp->uc_link;
+ ucp->uc_mcontext.sc_a[14] = argc;
+
+ if (argc)
+ {
+ va_list ap;
+
+ va_start (ap, argc);
+ for (i = 0; i < argc; ++i)
+ ((int *) sp)[i + 2] = va_arg (ap, int);
+ va_end (ap);
+ }
+}
+#elif defined(__XTENSA_WINDOWED_ABI__)
+/*
+ * makecontext sets up new stack like this:
+ *
+ * +------------------ stack top (uc_stack.ss_sp + uc_stack.ss_size)
+ * | optional alignment
+ * +------------------ CFA of __start_context
+ * 16 | Outermost caller spill area
+ * +------------------
+ * 16 | __start_context overflow area
+ * +------------------ initial sp points here
+ * | optional padding
+ * +------------------ Optional arguments 6..argc - 1
+ * | func arg argc - 1
+ * | func arg argc - 2
+ * | ...
+ * | func arg 6
+ * +------------------ Optional arguments 3..5
+ * | func arg 5
+ * 16 | func arg 4
+ * | func arg 3
+ * | padding
+ * +------------------ CFA of pseudo getcontext
+ * 16 | __start_context caller spill area
+ * +------------------
+ * |
+ * +------------------ stack bottom (uc_stack.ss_sp)
+ *
+ * When argc < 4 both arguments areas are not allocated,
+ * when 4 <= argc < 7 only area for arguments 3..5 is allocated,
+ * when argc >= 7 both arguments areas are allocated.
+ * Arguments 3..5 area is deallocated by the __start_context after
+ * arguments are loaded into registers.
+ * uc_mcontext registers are set as if __start_context made call8
+ * to getcontext, sp points to that pseudo getcontext CFA, spill
+ * area under that sp has a1 pointing to the __start_context CFA
+ * at the top of the stack. setcontext/swapcontext will arrange for
+ * restoring regiters a0..a7 of __start_context.
+ */
+
+void
+__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
+{
+ unsigned long sp = ((unsigned long) ucp->uc_stack.ss_sp
+ + ucp->uc_stack.ss_size - 32) & -16;
+ unsigned long spill0[4] =
+ {
+ 0, sp + 32, 0, 0,
+ };
+ int i;
+
+ memset ((void *) sp, 0, 32);
+
+ if (argc > 2)
+ sp -= 4 * (argc - 2);
+ sp &= -16;
+
+ ucp->uc_mcontext.sc_pc =
+ ((unsigned long) __start_context & 0x3fffffff) + 0x80000000;
+ ucp->uc_mcontext.sc_a[0] = 0;
+ ucp->uc_mcontext.sc_a[1] = sp;
+ ucp->uc_mcontext.sc_a[2] = (unsigned long) func;
+ ucp->uc_mcontext.sc_a[3] = (unsigned long) ucp->uc_link;
+ ucp->uc_mcontext.sc_a[4] = argc;
+
+ if (argc)
+ {
+ va_list ap;
+
+ va_start (ap, argc);
+ for (i = 0; i < argc; ++i)
+ {
+ if (i < 3)
+ ucp->uc_mcontext.sc_a[5 + i] = va_arg (ap, int);
+ else
+ ((int *) sp)[i - 2] = va_arg (ap, int);
+ }
+ va_end (ap);
+ }
+
+ sp -= 16;
+ memcpy ((void *) sp, spill0, sizeof (spill0));
+}
+#else
+#error Unsupported Xtensa ABI
+#endif
+
+weak_alias (__makecontext, makecontext)
diff --git a/libc/sysdeps/linux/xtensa/setcontext.S b/libc/sysdeps/linux/xtensa/setcontext.S
new file mode 100644
index 000000000000..4df7cc049006
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/setcontext.S
@@ -0,0 +1,116 @@
+/* Copyright (C) 2018 - 2022 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 <sysdep.h>
+#include "ucontext_i.h"
+
+#if defined(__XTENSA_CALL0_ABI__)
+ENTRY(__setcontext)
+ addi sp, sp, -16
+ s32i a0, sp, 0
+ s32i a2, sp, 4
+
+ addi a3, a2, UCONTEXT_SIGMASK
+ movi a4, 0
+ movi a2, SIG_SETMASK
+ movi a5, JUMPTARGET (sigprocmask)
+ callx0 a5
+ bnez a2, .Lerror
+
+ l32i a2, sp, 4
+ l32i a0, a2, MCONTEXT_SC_PC
+ l32i a1, a2, MCONTEXT_SC_A_0 + 4
+
+ /* load callee-saved registers from the context */
+ l32i a12, a2, MCONTEXT_SC_A_0 + 48
+ l32i a13, a2, MCONTEXT_SC_A_0 + 52
+ l32i a14, a2, MCONTEXT_SC_A_0 + 56
+ l32i a15, a2, MCONTEXT_SC_A_0 + 60
+ movi a2, 0
+ ret
+.Lerror:
+ l32i a0, sp, 0
+ addi sp, sp, 16
+ ret
+END(__setcontext)
+#elif defined(__XTENSA_WINDOWED_ABI__)
+ENTRY(__setcontext)
+ movi a6, SIG_SETMASK
+ addi a7, a2, UCONTEXT_SIGMASK
+ movi a8, 0
+ movi a4, JUMPTARGET (sigprocmask)
+ callx4 a4
+ bnez a6, .Lerror
+ movi a4, __window_spill
+ callx4 a4
+
+ l32i a0, a2, MCONTEXT_SC_PC
+
+ /* copy registers a0..a3 to spill area */
+ addi a3, a1, -16
+ l32i a4, a2, MCONTEXT_SC_A_0 + 0
+ l32i a5, a2, MCONTEXT_SC_A_0 + 4
+ l32i a6, a2, MCONTEXT_SC_A_0 + 8
+ l32i a7, a2, MCONTEXT_SC_A_0 + 12
+ s32i a4, a3, 0
+ s32i a5, a3, 4
+ s32i a6, a3, 8
+ s32i a7, a3, 12
+
+ /* if it was call4 then register setup is done */
+ extui a4, a0, 30, 2
+ bltui a4, 2, 1f
+
+ /* otherwise load spill overflow area address into a3 */
+ addi a3, a5, -16
+ l32i a3, a3, 4
+ addi a3, a3, -32
+ beqi a4, 2, 2f
+
+ /* copy registers a8..a11 to spill overflow area */
+ addi a3, a3, -16
+ l32i a4, a2, MCONTEXT_SC_A_0 + 32
+ l32i a5, a2, MCONTEXT_SC_A_0 + 36
+ l32i a6, a2, MCONTEXT_SC_A_0 + 40
+ l32i a7, a2, MCONTEXT_SC_A_0 + 44
+ s32i a4, a3, 16
+ s32i a5, a3, 20
+ s32i a6, a3, 24
+ s32i a7, a3, 28
+
+ /* copy registers a4..a7 to spill overflow area */
+2:
+ l32i a4, a2, MCONTEXT_SC_A_0 + 16
+ l32i a5, a2, MCONTEXT_SC_A_0 + 20
+ l32i a6, a2, MCONTEXT_SC_A_0 + 24
+ l32i a7, a2, MCONTEXT_SC_A_0 + 28
+ s32i a4, a3, 0
+ s32i a5, a3, 4
+ s32i a6, a3, 8
+ s32i a7, a3, 12
+1:
+ movi a2, 0
+ retw
+.Lerror:
+ mov a2, a6
+ retw
+END(__setcontext)
+#else
+#error Unsupported Xtensa ABI
+#endif
+
+weak_alias (__setcontext, setcontext)
diff --git a/libc/sysdeps/linux/xtensa/swapcontext.S b/libc/sysdeps/linux/xtensa/swapcontext.S
new file mode 100644
index 000000000000..a215edc6d54a
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/swapcontext.S
@@ -0,0 +1,173 @@
+/* Copyright (C) 2018 - 2022 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 <sysdep.h>
+#include "ucontext_i.h"
+
+#if defined(__XTENSA_CALL0_ABI__)
+ENTRY(__swapcontext)
+ s32i a0, a2, MCONTEXT_SC_PC
+ s32i a1, a2, MCONTEXT_SC_A_0 + 4
+
+ /* save callee-saved registers in the context */
+ s32i a12, a2, MCONTEXT_SC_A_0 + 48
+ s32i a13, a2, MCONTEXT_SC_A_0 + 52
+ s32i a14, a2, MCONTEXT_SC_A_0 + 56
+ s32i a15, a2, MCONTEXT_SC_A_0 + 60
+
+ mov a12, a3
+ mov a13, a2
+
+ addi a3, a3, UCONTEXT_SIGMASK
+ addi a4, a2, UCONTEXT_SIGMASK
+ movi a2, SIG_SETMASK
+ movi a5, JUMPTARGET (sigprocmask)
+ callx0 a5
+ bnez a2, .Lerror
+
+ mov a2, a12
+ l32i a0, a2, MCONTEXT_SC_PC
+ l32i a1, a2, MCONTEXT_SC_A_0 + 4
+
+ /* load callee-saved registers from the context */
+ l32i a12, a2, MCONTEXT_SC_A_0 + 48
+ l32i a13, a2, MCONTEXT_SC_A_0 + 52
+ l32i a14, a2, MCONTEXT_SC_A_0 + 56
+ l32i a15, a2, MCONTEXT_SC_A_0 + 60
+
+ movi a2, 0
+ ret
+.Lerror:
+ l32i a0, a13, MCONTEXT_SC_PC
+ l32i a12, a13, MCONTEXT_SC_A_0 + 48
+ l32i a13, a13, MCONTEXT_SC_A_0 + 52
+ ret
+END(__swapcontext)
+#elif defined(__XTENSA_WINDOWED_ABI__)
+ENTRY(__swapcontext)
+ movi a4, __window_spill
+ callx4 a4
+ mov a9, a3
+ s32i a0, a2, MCONTEXT_SC_PC
+
+ /* copy registers a0..a3 from spill area */
+ addi a3, a1, -16
+ l32i a4, a3, 0
+ l32i a5, a3, 4
+ l32i a6, a3, 8
+ l32i a7, a3, 12
+ s32i a4, a2, MCONTEXT_SC_A_0 + 0
+ s32i a5, a2, MCONTEXT_SC_A_0 + 4
+ s32i a6, a2, MCONTEXT_SC_A_0 + 8
+ s32i a7, a2, MCONTEXT_SC_A_0 + 12
+
+ /* if it was call4 then register saving is done */
+ extui a4, a0, 30, 2
+ bltui a4, 2, 1f
+
+ /* otherwise load spill overflow area address into a3 */
+ addi a3, a5, -16
+ l32i a3, a3, 4
+ addi a3, a3, -32
+ beqi a4, 2, 2f
+
+ /* copy registers a8..a11 from spill overflow area */
+ addi a3, a3, -16
+ l32i a4, a3, 16
+ l32i a5, a3, 20
+ l32i a6, a3, 24
+ l32i a7, a3, 28
+ s32i a4, a2, MCONTEXT_SC_A_0 + 32
+ s32i a5, a2, MCONTEXT_SC_A_0 + 36
+ s32i a6, a2, MCONTEXT_SC_A_0 + 40
+ s32i a7, a2, MCONTEXT_SC_A_0 + 44
+
+ /* copy registers a4..a7 from spill overflow area */
+2:
+ l32i a4, a3, 0
+ l32i a5, a3, 4
+ l32i a6, a3, 8
+ l32i a7, a3, 12
+ s32i a4, a2, MCONTEXT_SC_A_0 + 16
+ s32i a5, a2, MCONTEXT_SC_A_0 + 20
+ s32i a6, a2, MCONTEXT_SC_A_0 + 24
+ s32i a7, a2, MCONTEXT_SC_A_0 + 28
+1:
+ movi a6, SIG_SETMASK
+ addi a7, a9, UCONTEXT_SIGMASK
+ addi a8, a2, UCONTEXT_SIGMASK
+ mov a2, a9
+ movi a4, JUMPTARGET (sigprocmask)
+ callx4 a4
+ bnez a6, .Lerror
+
+ l32i a0, a2, MCONTEXT_SC_PC
+
+ /* copy registers a0..a3 to spill area */
+ addi a3, a1, -16
+ l32i a4, a2, MCONTEXT_SC_A_0 + 0
+ l32i a5, a2, MCONTEXT_SC_A_0 + 4
+ l32i a6, a2, MCONTEXT_SC_A_0 + 8
+ l32i a7, a2, MCONTEXT_SC_A_0 + 12
+ s32i a4, a3, 0
+ s32i a5, a3, 4
+ s32i a6, a3, 8
+ s32i a7, a3, 12
+
+ /* if it was call4 then register setup is done */
+ extui a4, a0, 30, 2
+ bltui a4, 2, 1f
+
+ /* otherwise load spill overflow area address into a3 */
+ addi a3, a5, -16
+ l32i a3, a3, 4
+ addi a3, a3, -32
+ beqi a4, 2, 2f
+
+ /* copy registers a8..a11 to spill overflow area */
+ addi a3, a3, -16
+ l32i a4, a2, MCONTEXT_SC_A_0 + 32
+ l32i a5, a2, MCONTEXT_SC_A_0 + 36
+ l32i a6, a2, MCONTEXT_SC_A_0 + 40
+ l32i a7, a2, MCONTEXT_SC_A_0 + 44
+ s32i a4, a3, 16
+ s32i a5, a3, 20
+ s32i a6, a3, 24
+ s32i a7, a3, 28
+
+ /* copy registers a4..a7 to spill overflow area */
+2:
+ l32i a4, a2, MCONTEXT_SC_A_0 + 16
+ l32i a5, a2, MCONTEXT_SC_A_0 + 20
+ l32i a6, a2, MCONTEXT_SC_A_0 + 24
+ l32i a7, a2, MCONTEXT_SC_A_0 + 28
+ s32i a4, a3, 0
+ s32i a5, a3, 4
+ s32i a6, a3, 8
+ s32i a7, a3, 12
+1:
+ movi a2, 0
+ retw
+.Lerror:
+ mov a2, a6
+ retw
+END(__swapcontext)
+#else
+#error Unsupported Xtensa ABI
+#endif
+
+weak_alias (__swapcontext, swapcontext)
diff --git a/libc/sysdeps/linux/xtensa/sysdep.h b/libc/sysdeps/linux/xtensa/sysdep.h
index 0671f0783477..80b3f30fcc5d 100644
--- a/libc/sysdeps/linux/xtensa/sysdep.h
+++ b/libc/sysdeps/linux/xtensa/sysdep.h
@@ -39,12 +39,15 @@
#endif
-#define ENTRY(name) \
+#define ENTRY_PREFIX(name) \
.globl C_SYMBOL_NAME(name); \
ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name), @function); \
.align ALIGNARG(2); \
LITERAL_POSITION; \
- C_LABEL(name) \
+ C_LABEL(name)
+
+#define ENTRY(name) \
+ ENTRY_PREFIX(name) \
abi_entry(sp, FRAMESIZE);
#define HIDDEN_ENTRY(name) \
diff --git a/libc/sysdeps/linux/xtensa/ucontext_i.sym b/libc/sysdeps/linux/xtensa/ucontext_i.sym
new file mode 100644
index 000000000000..4770c36c9e1d
--- /dev/null
+++ b/libc/sysdeps/linux/xtensa/ucontext_i.sym
@@ -0,0 +1,15 @@
+#include <inttypes.h>
+#include <signal.h>
+#include <stddef.h>
+#include <sys/ucontext.h>
+
+SIG_BLOCK
+SIG_SETMASK
+
+-- Offsets of the fields in the ucontext_t structure.
+#define ucontext(member) offsetof (ucontext_t, member)
+#define mcontext(member) ucontext (uc_mcontext.member)
+
+UCONTEXT_SIGMASK ucontext (uc_sigmask)
+MCONTEXT_SC_A_0 mcontext (sc_a[0])
+MCONTEXT_SC_PC mcontext (sc_pc)
--
2.30.2
1
0