Compare commits

...

35 Commits
v1.2 ... master

Author SHA1 Message Date
Ariadne Conill a0323579ac libucontext 1.3.2 2024-10-06 18:37:08 -07:00
Volker Christian 302fbd7452 loongarch64, x86: Fix compile issue by not using trampoline.c but startcontext.S for those two architectures also. 2024-10-06 12:01:38 -07:00
Ariadne Conill d64402737b loongarch64: rewrite makecontext in C
ci/woodpecker/push/woodpecker Pipeline was successful Details
also fix MCONTEXT_PC and MCONTEXT_GREGS so they actually read and write to/from
the correct addresses in the ucontext structure.
2024-08-12 13:17:41 -07:00
Ariadne Conill c3d26b7940 libucontext 1.3.1
ci/woodpecker/push/woodpecker Pipeline was successful Details
ci/woodpecker/tag/woodpecker Pipeline was successful Details
2024-08-07 20:33:42 -07:00
Ariadne Conill e07c8d0ac5 loongarch64: fix return values from getcontext/swapcontext
ci/woodpecker/push/woodpecker Pipeline was successful Details
2024-08-07 20:28:53 -07:00
Ariadne Conill ed663cf0e5 loongarch64: fix assembly warnings
ci/woodpecker/push/woodpecker Pipeline was successful Details
2024-08-07 20:25:18 -07:00
Ariadne Conill f593205e95 build: disable ARM hard float support by default
ci/woodpecker/push/woodpecker Pipeline was successful Details
It appears to be broken.
2024-08-07 20:06:26 -07:00
Ariadne Conill a65049c8d4 arm: disable use of .end directive in assembly
ci/woodpecker/push/woodpecker Pipeline was successful Details
Fixes build failure on GCC 14.
2024-08-07 20:00:15 -07:00
Ariadne Conill 828fc9e950 common-defs: allow override of END assembly macro
ci/woodpecker/push/woodpecker Pipeline was successful Details
GCC 14 on ARM does not recognize the `.end` directive anymore,
it seems.
2024-08-07 19:58:30 -07:00
Ariadne Conill 3e5059e8a1 libucontext 1.3
ci/woodpecker/push/woodpecker Pipeline was successful Details
ci/woodpecker/tag/woodpecker Pipeline was successful Details
2024-08-07 19:41:46 -07:00
Ariadne Conill 570c0c8b32 README: mention that x86-32 does not use the C trampoline anymore
ci/woodpecker/push/woodpecker Pipeline was successful Details
2024-08-07 19:41:17 -07:00
Ariadne Conill 998ae99d61 or1k: fix getcontext/swapcontext return values
ci/woodpecker/push/woodpecker Pipeline was successful Details
2024-08-07 19:28:43 -07:00
Ariadne Conill c2a8b0a9d5 riscv32: fix getcontext/swapcontext return value
ci/woodpecker/push/woodpecker Pipeline was successful Details
2024-08-07 19:19:29 -07:00
Ariadne Conill e603fd7239 riscv64: fix getcontext/swapcontext return values
ci/woodpecker/push/woodpecker Pipeline was successful Details
2024-08-07 19:15:42 -07:00
Ariadne Conill c468c50b7b s390x: fix clobbering of return values in swapcontext
ci/woodpecker/push/woodpecker Pipeline was successful Details
2024-08-07 19:04:45 -07:00
Ariadne Conill c1ecb0ea59 x86: switch back to using x86-specific trampoline
ci/woodpecker/push/woodpecker Pipeline was successful Details
Jumping into the generic trampoline causes the stack pointer to get
clobbered.

Fixes #61
2024-08-07 18:34:53 -07:00
Ariadne Conill 5445f70157 tests: libucontext_posix: quiet compiler warning on glibc
ci/woodpecker/push/woodpecker Pipeline was successful Details
2024-08-07 17:57:16 -07:00
Ariadne Conill 1a2dff93e7 build: migrate to _DEFAULT_SOURCE
ci/woodpecker/push/woodpecker Pipeline was successful Details
2024-08-07 17:54:35 -07:00
L. Pereira 7badd2d5b2 Set _XOPEN_SOURCE when building on Darwin
ci/woodpecker/push/woodpecker Pipeline was successful Details
On non-freestanding builds, including <ucontext.h> on an ARM Darwin
system will produce the following error:

  In file included from include/libucontext/bits.h:6:
  /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/
	usr/include/ucontext.h:51:2: error: The deprecated
	ucontext routines require _XOPEN_SOURCE to be defined

Defining this macro on Darwin systems will make the building pass.
2024-08-07 17:49:36 -07:00
Jim Hauxwell 4975ba9051 fix file copy
ci/woodpecker/push/woodpecker Pipeline was successful Details
2024-08-07 17:48:29 -07:00
Jim Hauxwell b3cbfd9c1a fix parallel build for makefile
The copy for bits.h ran in parallel with the initial CC.  sometimes on
CI the build would fail as the file had not arrived by the time
needed.  Fix matches meson build process.
2024-08-07 17:48:29 -07:00
Sören Tempel d0b03541bf common-trampoline: Ensure omission of frame-pointer
ci/woodpecker/push/woodpecker Pipeline was successful Details
Some architecture-specific implementations of the FETCH_LINKPTR
(e.g. the one for x86) attempt to find the linkptr relative to the
stack pointer. Therefore, they make assumption about the value of
the SP at the point where the FETCH_LINKPTR code is executed. This
means that we don't want the C compiler to mess with our SP.

For this purpose, local variables in this function are currently
declared using the register storage specifier. Additionally, we
need to make sure that a frame pointer is /always/ omitted for
this function. On x86 Alpine, the frame pointer is presently not
omitted with GCC 13 when using -Os, therefore the tests segfault
with -Os on Alpine presently.

Fixes #52
2024-08-07 17:46:50 -07:00
Volker Christian 124a962b39 aarch64: fix return value if getcontext was used to acquire the current context.
x0 hast to be 0 in case setcontext is called with a context acquired by getcontext.
Thus x0=0 must be stored in getcontext.
2024-08-07 17:45:47 -07:00
Volker Christian 9e5de65076 libucontext: Add patch fixing return values of get/set/swapcontext
The arm ABI defines that the value in register r0 is used as the return
value of a function. To indicate success for get/set/swapcontext (return
value of 0) the register r0 must contain zero at the end of the function
call. Thus set r0 to zero and store it in the context. This context
is restored later and indicate successful execution, because r0 is 0.

The order registers are stored has changed so that only one additional
instruction (mov r0, #0) needs to be added to fix the return value
bug for get/set/swapcontext.

Signed-off-by: Volker Christian <me@vchrist.at>
2024-08-07 17:44:43 -07:00
Volker Christian 076e69c9c1 libucontext: Add error checking
Add error checking test_libucontext and test_libucontext_posix
to test return values of get/set/swapcontext.

Modifications are inspired by the example program source in the
linux man page of swapcontext

Signed-off-by: Volker Christian <me@vchrist.at>
2024-08-07 17:43:55 -07:00
matoro be80075e95 meson: support building docs
ci/woodpecker/push/woodpecker Pipeline was successful Details
Toggleable with -Ddocs=(true|false), defaults to false.

Requires bumping minimum meson version to 0.59.0, or 0.61.0 to also
include symlinks.
2023-05-18 18:12:55 -07:00
Ariadne Conill 4c2cfc54ac libucontext.h: add C++ externs 2023-05-18 18:11:50 -07:00
L. Pereira 0f625a86ee Fix FREESTANDING install target
When installing a FREESTANDING build, the check for an empty variable
was not being honored because the empty string would evaluate to
nothing.  Put the variable expansion in quotes so that we have an empty
string instead.
2023-05-18 18:10:01 -07:00
Ismael Luceno 8e1397f5a2 Makefile: Make variables Automake-compatible
Also split libdir into shared and static variants to enable installing to
different locations.

Signed-off-by: Ismael Luceno <ismael@iodev.co.uk>
2023-05-18 18:08:07 -07:00
Ariadne Conill 33ff253d52 Merge pull request 'Fixed empty TYPE(__proc) causing linker issues on 32-bit arm' (#36) from rlcamp/libucontext:arm_linker_fix into master
Reviewed-on: #36
2022-03-24 08:57:53 +00:00
Richard Campbell 3044c2b908 Fixed empty TYPE(__proc) causing linker issues on 32-bit arm 2022-03-23 15:18:39 -07:00
Ariadne Conill 128e4fdc4b Merge pull request 'arm_hard_float' (#35) from rlcamp/libucontext:arm_hard_float into master
Reviewed-on: #35
2022-03-23 20:15:32 +00:00
Richard Campbell 5244775fb9 Added note to readme about floating point WIP 2022-03-04 10:41:54 -08:00
Richard Campbell 9abcd8afe0 Added passthrough of FORCE_SOFT_FLOAT and FORCE_HARD_FLOAT Makefile options 2022-03-04 10:40:30 -08:00
Richard Campbell 7bc3e90984 Added arm conditional vfp save/restore 2022-03-04 10:35:25 -08:00
36 changed files with 411 additions and 224 deletions

1
.gitignore vendored
View File

@ -1,4 +1,3 @@
include/libucontext/bits.h
*.o *.o
examples/cooperative_threading examples/cooperative_threading
test_libucontext test_libucontext

View File

@ -17,9 +17,13 @@ ifeq ($(ARCH),$(filter $(ARCH),arm64))
override ARCH = aarch64 override ARCH = aarch64
endif endif
LIBDIR := /lib prefix = /usr
INCLUDEDIR := /usr/include libdir = ${prefix}/lib
PKGCONFIGDIR := /usr/lib/pkgconfig shared_libdir = ${libdir}
static_libdir = ${libdir}
includedir = ${prefix}/include
pkgconfigdir = ${prefix}/lib/pkgconfig
CFLAGS ?= -ggdb3 -O2 -Wall CFLAGS ?= -ggdb3 -O2 -Wall
CPPFLAGS := -Iinclude -Iarch/${ARCH} -Iarch/common CPPFLAGS := -Iinclude -Iarch/${ARCH} -Iarch/common
ifneq ($(shell uname),Darwin) ifneq ($(shell uname),Darwin)
@ -27,12 +31,28 @@ ifneq ($(shell uname),Darwin)
else else
# Darwin does not support aliases # Darwin does not support aliases
EXPORT_UNPREFIXED := no EXPORT_UNPREFIXED := no
CPPFLAGS += -D_XOPEN_SOURCE
endif endif
FREESTANDING := no FREESTANDING := no
ifeq ($(FREESTANDING),yes) ifeq ($(FREESTANDING),yes)
CPPFLAGS += -DFREESTANDING CPPFLAGS += -DFREESTANDING
EXPORT_UNPREFIXED = no EXPORT_UNPREFIXED = no -Iarch/${ARCH}/include
else
CPPFLAGS += -Iarch/common/include
endif
# ARM hard float support is presently broken.
FORCE_SOFT_FLOAT := yes
ifeq ($(FORCE_SOFT_FLOAT),yes)
CPPFLAGS += -DFORCE_SOFT_FLOAT
endif
FORCE_HARD_FLOAT := no
ifeq ($(FORCE_HARD_FLOAT),yes)
CPPFLAGS += -DFORCE_HARD_FLOAT
endif endif
ifeq ($(EXPORT_UNPREFIXED),yes) ifeq ($(EXPORT_UNPREFIXED),yes)
@ -67,18 +87,22 @@ else
endif endif
LIBUCONTEXT_STATIC_NAME = libucontext.a LIBUCONTEXT_STATIC_NAME = libucontext.a
LIBUCONTEXT_PC = libucontext.pc LIBUCONTEXT_PC = libucontext.pc
LIBUCONTEXT_PATH = ${LIBDIR}/${LIBUCONTEXT_SONAME} LIBUCONTEXT_PATH = ${shared_libdir}/${LIBUCONTEXT_SONAME}
LIBUCONTEXT_STATIC_PATH = ${LIBDIR}/${LIBUCONTEXT_STATIC_NAME} LIBUCONTEXT_STATIC_PATH = ${static_libdir}/${LIBUCONTEXT_STATIC_NAME}
LIBUCONTEXT_HEADERS = \ LIBUCONTEXT_HEADERS = \
include/libucontext/libucontext.h \ include/libucontext/libucontext.h
include/libucontext/bits.h ifeq ($(FREESTANDING),yes)
LIBUCONTEXT_HEADERS += arch/${ARCH}/include/libucontext/bits.h
else
LIBUCONTEXT_HEADERS += arch/common/include/libucontext/bits.h
endif
LIBUCONTEXT_EXAMPLES = \ LIBUCONTEXT_EXAMPLES = \
examples/cooperative_threading examples/cooperative_threading
LIBUCONTEXT_POSIX_STATIC_NAME = libucontext_posix.a LIBUCONTEXT_POSIX_STATIC_NAME = libucontext_posix.a
LIBUCONTEXT_POSIX_C_SRC = libucontext_posix.c LIBUCONTEXT_POSIX_C_SRC = libucontext_posix.c
LIBUCONTEXT_POSIX_OBJ = ${LIBUCONTEXT_POSIX_C_SRC:.c=.o} LIBUCONTEXT_POSIX_OBJ = ${LIBUCONTEXT_POSIX_C_SRC:.c=.o}
LIBUCONTEXT_POSIX_PATH = ${LIBDIR}/${LIBUCONTEXT_POSIX_SONAME} LIBUCONTEXT_POSIX_PATH = ${shared_libdir}/${LIBUCONTEXT_POSIX_SONAME}
LIBUCONTEXT_POSIX_STATIC_PATH = ${LIBDIR}/${LIBUCONTEXT_POSIX_STATIC_NAME} LIBUCONTEXT_POSIX_STATIC_PATH = ${static_libdir}/${LIBUCONTEXT_POSIX_STATIC_NAME}
ifeq ($(FREESTANDING),yes) ifeq ($(FREESTANDING),yes)
LIBUCONTEXT_POSIX_NAME = LIBUCONTEXT_POSIX_NAME =
@ -96,10 +120,10 @@ ${LIBUCONTEXT_POSIX_STATIC_NAME}: ${LIBUCONTEXT_STATIC_NAME} ${LIBUCONTEXT_POSIX
${LIBUCONTEXT_POSIX_SONAME}: ${LIBUCONTEXT_POSIX_NAME} ${LIBUCONTEXT_POSIX_SONAME}: ${LIBUCONTEXT_POSIX_NAME}
ln -sf ${LIBUCONTEXT_POSIX_NAME} ${LIBUCONTEXT_POSIX_SONAME} ln -sf ${LIBUCONTEXT_POSIX_NAME} ${LIBUCONTEXT_POSIX_SONAME}
${LIBUCONTEXT_STATIC_NAME}: ${LIBUCONTEXT_HEADERS} ${LIBUCONTEXT_OBJ} ${LIBUCONTEXT_STATIC_NAME}: ${LIBUCONTEXT_OBJ}
$(AR) rcs ${LIBUCONTEXT_STATIC_NAME} ${LIBUCONTEXT_OBJ} $(AR) rcs ${LIBUCONTEXT_STATIC_NAME} ${LIBUCONTEXT_OBJ}
${LIBUCONTEXT_NAME}: ${LIBUCONTEXT_HEADERS} ${LIBUCONTEXT_OBJ} ${LIBUCONTEXT_NAME}: ${LIBUCONTEXT_OBJ}
$(CC) -fPIC -o ${LIBUCONTEXT_NAME} ${LIBUCONTEXT_LINKER_FLAGS} ${LIBUCONTEXT_OBJ} ${LDFLAGS} $(CC) -fPIC -o ${LIBUCONTEXT_NAME} ${LIBUCONTEXT_LINKER_FLAGS} ${LIBUCONTEXT_OBJ} ${LDFLAGS}
${LIBUCONTEXT_SONAME}: ${LIBUCONTEXT_NAME} ${LIBUCONTEXT_SONAME}: ${LIBUCONTEXT_NAME}
@ -107,8 +131,9 @@ ${LIBUCONTEXT_SONAME}: ${LIBUCONTEXT_NAME}
${LIBUCONTEXT_PC}: libucontext.pc.in ${LIBUCONTEXT_PC}: libucontext.pc.in
sed -e s:@LIBUCONTEXT_VERSION@:${LIBUCONTEXT_VERSION}:g \ sed -e s:@LIBUCONTEXT_VERSION@:${LIBUCONTEXT_VERSION}:g \
-e s:@LIBUCONTEXT_LIBDIR@:${LIBDIR}:g \ -e s:@LIBUCONTEXT_SHARED_LIBDIR@:${shared_libdir}:g \
-e s:@LIBUCONTEXT_INCLUDEDIR@:${INCLUDEDIR}:g $< > $@ -e s:@LIBUCONTEXT_STATIC_LIBDIR@:${static_libdir}:g \
-e s:@LIBUCONTEXT_INCLUDEDIR@:${includedir}:g $< > $@
MANPAGES_SYMLINKS_3 = \ MANPAGES_SYMLINKS_3 = \
libucontext_getcontext.3 \ libucontext_getcontext.3 \
@ -127,7 +152,7 @@ MANPAGES = ${MANPAGES_3}
docs: ${MANPAGES} docs: ${MANPAGES}
.c.o: .c.o:
$(CC) -std=gnu99 -D_BSD_SOURCE -fPIC -DPIC ${CFLAGS} ${CPPFLAGS} -c -o $@ $< $(CC) -std=gnu99 -D_DEFAULT_SOURCE -fPIC -DPIC ${CFLAGS} ${CPPFLAGS} -c -o $@ $<
.S.o: .S.o:
$(CC) -fPIC -DPIC ${CFLAGS} ${CPPFLAGS} ${ASFLAGS} -c -o $@ $< $(CC) -fPIC -DPIC ${CFLAGS} ${CPPFLAGS} ${ASFLAGS} -c -o $@ $<
@ -147,9 +172,6 @@ libucontext_obj_clean:
${LIBUCONTEXT_PC}_clean: ${LIBUCONTEXT_PC}_clean:
rm -f ${LIBUCONTEXT_PC} rm -f ${LIBUCONTEXT_PC}
bits_clean:
rm -f include/libucontext/bits.h
${LIBUCONTEXT_POSIX_NAME}_clean: ${LIBUCONTEXT_POSIX_NAME}_clean:
rm -f ${LIBUCONTEXT_POSIX_NAME} rm -f ${LIBUCONTEXT_POSIX_NAME}
@ -180,7 +202,6 @@ clean: ${LIBUCONTEXT_NAME}_clean
clean: ${LIBUCONTEXT_SONAME}_clean clean: ${LIBUCONTEXT_SONAME}_clean
clean: ${LIBUCONTEXT_STATIC_NAME}_clean clean: ${LIBUCONTEXT_STATIC_NAME}_clean
clean: ${LIBUCONTEXT_PC}_clean clean: ${LIBUCONTEXT_PC}_clean
clean: bits_clean
clean: ${LIBUCONTEXT_POSIX_NAME}_clean clean: ${LIBUCONTEXT_POSIX_NAME}_clean
clean: ${LIBUCONTEXT_POSIX_SONAME}_clean clean: ${LIBUCONTEXT_POSIX_SONAME}_clean
clean: ${LIBUCONTEXT_POSIX_STATIC_NAME}_clean clean: ${LIBUCONTEXT_POSIX_STATIC_NAME}_clean
@ -192,13 +213,13 @@ clean: docs_clean
install: all install: all
install -D -m755 ${LIBUCONTEXT_NAME} ${DESTDIR}${LIBUCONTEXT_PATH} install -D -m755 ${LIBUCONTEXT_NAME} ${DESTDIR}${LIBUCONTEXT_PATH}
install -D -m664 ${LIBUCONTEXT_STATIC_NAME} ${DESTDIR}${LIBUCONTEXT_STATIC_PATH} install -D -m664 ${LIBUCONTEXT_STATIC_NAME} ${DESTDIR}${LIBUCONTEXT_STATIC_PATH}
ln -sf ${LIBUCONTEXT_SONAME} ${DESTDIR}${LIBDIR}/${LIBUCONTEXT_NAME} ln -sf ${LIBUCONTEXT_SONAME} ${DESTDIR}${shared_libdir}/${LIBUCONTEXT_NAME}
for i in ${LIBUCONTEXT_HEADERS}; do \ for i in ${LIBUCONTEXT_HEADERS}; do \
destfn=$$(echo $$i | sed s:include/::g); \ destfn=$$(echo $$i | sed s:include/::g); \
install -D -m644 $$i ${DESTDIR}${INCLUDEDIR}/$$destfn; \ install -D -m644 $$i ${DESTDIR}${includedir}/$$destfn; \
done done
install -D -m644 ${LIBUCONTEXT_PC} ${DESTDIR}${PKGCONFIGDIR}/${LIBUCONTEXT_PC} install -D -m644 ${LIBUCONTEXT_PC} ${DESTDIR}${pkgconfigdir}/${LIBUCONTEXT_PC}
if [ -n ${LIBUCONTEXT_POSIX_NAME} ]; then \ if [ -n "${LIBUCONTEXT_POSIX_NAME}" ]; then \
install -D -m755 ${LIBUCONTEXT_POSIX_NAME} ${DESTDIR}${LIBUCONTEXT_POSIX_PATH}; \ install -D -m755 ${LIBUCONTEXT_POSIX_NAME} ${DESTDIR}${LIBUCONTEXT_POSIX_PATH}; \
install -D -m644 ${LIBUCONTEXT_POSIX_STATIC_NAME} ${DESTDIR}${LIBUCONTEXT_POSIX_STATIC_PATH}; \ install -D -m644 ${LIBUCONTEXT_POSIX_STATIC_NAME} ${DESTDIR}${LIBUCONTEXT_POSIX_STATIC_PATH}; \
fi fi
@ -216,7 +237,7 @@ check_libucontext_posix: test_libucontext_posix ${LIBUCONTEXT_POSIX_SONAME} ${LI
env LD_LIBRARY_PATH=$(shell pwd) ./test_libucontext_posix env LD_LIBRARY_PATH=$(shell pwd) ./test_libucontext_posix
test_libucontext_posix: test_libucontext_posix.c ${LIBUCONTEXT_POSIX_NAME} test_libucontext_posix: test_libucontext_posix.c ${LIBUCONTEXT_POSIX_NAME}
$(CC) -std=gnu99 -D_BSD_SOURCE ${CFLAGS} ${CPPFLAGS} $@.c -o $@ -L. -lucontext -lucontext_posix $(CC) -std=gnu99 -D_DEFAULT_SOURCE ${CFLAGS} ${CPPFLAGS} $@.c -o $@ -L. -lucontext -lucontext_posix
endif endif
ifeq ($(EXPORT_UNPREFIXED),yes) ifeq ($(EXPORT_UNPREFIXED),yes)
@ -226,7 +247,7 @@ check_libucontext_bare_posixabi: test_libucontext_bare_posixabi ${LIBUCONTEXT_SO
env LD_LIBRARY_PATH=$(shell pwd) ./test_libucontext_bare_posixabi env LD_LIBRARY_PATH=$(shell pwd) ./test_libucontext_bare_posixabi
test_libucontext_bare_posixabi: test_libucontext_posix.c ${LIBUCONTEXT_NAME} test_libucontext_bare_posixabi: test_libucontext_posix.c ${LIBUCONTEXT_NAME}
$(CC) -std=gnu99 -D_BSD_SOURCE ${CFLAGS} ${CPPFLAGS} test_libucontext_posix.c -o $@ -L. -lucontext $(CC) -std=gnu99 -D_DEFAULT_SOURCE ${CFLAGS} ${CPPFLAGS} test_libucontext_posix.c -o $@ -L. -lucontext
endif endif
check_libucontext: test_libucontext ${LIBUCONTEXT_SONAME} check_libucontext: test_libucontext ${LIBUCONTEXT_SONAME}
@ -235,23 +256,11 @@ check_libucontext: test_libucontext ${LIBUCONTEXT_SONAME}
check: check_libucontext check: check_libucontext
test_libucontext: test_libucontext.c ${LIBUCONTEXT_NAME} test_libucontext: test_libucontext.c ${LIBUCONTEXT_NAME}
$(CC) -std=gnu99 -D_BSD_SOURCE ${CFLAGS} ${CPPFLAGS} $@.c -o $@ -L. -lucontext $(CC) -std=gnu99 -D_DEFAULT_SOURCE ${CFLAGS} ${CPPFLAGS} $@.c -o $@ -L. -lucontext
examples: ${LIBUCONTEXT_EXAMPLES} examples: ${LIBUCONTEXT_EXAMPLES}
examples/cooperative_threading: examples/cooperative_threading.c ${LIBUCONTEXT_NAME} examples/cooperative_threading: examples/cooperative_threading.c ${LIBUCONTEXT_NAME}
$(CC) -std=gnu99 -D_BSD_SOURCE ${CFLAGS} ${CPPFLAGS} $@.c -o $@ -L. -lucontext $(CC) -std=gnu99 -D_DEFAULT_SOURCE ${CFLAGS} ${CPPFLAGS} $@.c -o $@ -L. -lucontext
ifeq ($(FREESTANDING),no)
include/libucontext/bits.h: arch/common/include/libucontext/bits.h
cp $< $@
else
include/libucontext/bits.h: arch/${ARCH}/include/libucontext/bits.h
cp $< $@
endif
PACKAGE_NAME = libucontext PACKAGE_NAME = libucontext
PACKAGE_VERSION = ${LIBUCONTEXT_VERSION} PACKAGE_VERSION = ${LIBUCONTEXT_VERSION}

43
NEWS
View File

@ -1,3 +1,46 @@
Changes from 1.3.1 to 1.3.2
---------------------------
* Rewrite makecontext in C on LoongArch.
* Fix building x86 and loongarch64 variants on Meson.
Patch by Volker Christian.
Changes from 1.3 to 1.3.1
-------------------------
* Disable hard-float support on ARM by default.
* Fix up getcontext/swapcontext return values on LoongArch.
* Fix assembler warnings when building on LoongArch.
Changes from 1.2 to 1.3
-----------------------
* Fix up getcontext/swapcontext return values across a few ports.
Patches contributed for ARM and test suite by Volker Christian.
* Add support for hard-float on ARM.
Patches contributed by Richard Campbell.
* Align build system variables with those used by Automake.
Patch contributed by Ismael Luceno.
* Fix sporadic parallel build failures.
Patches contributed by Jim Hauxwell.
* Ensure frame pointers are omitted when using the C trampoline.
Patch contributed by Sören Tempel.
* Define _XOPEN_SOURCE when building on Darwin.
Patch contributed by L. Pereira.
* Add support for building the manpages with Meson.
Patch contributed by matoro.
* Migrate build from _BSD_SOURCE to _DEFAULT_SOURCE.
Changes from 1.1 to 1.2 Changes from 1.1 to 1.2
----------------------- -----------------------

View File

@ -31,7 +31,7 @@ target to do it.
| riscv64 | ✓ | | ✓ | ✓ | | riscv64 | ✓ | | ✓ | ✓ |
| s390x | ✓ | | ✓ | | | s390x | ✓ | | ✓ | |
| sh | ✓ | | ✓ | ✓ | | sh | ✓ | | ✓ | ✓ |
| x86 | ✓ | | ✓ | | | x86 | ✓ | | ✓ | |
| x86_64 | ✓ | | ✓ | ✓ | | x86_64 | ✓ | | ✓ | ✓ |
@ -101,4 +101,5 @@ ucontext functions:
save/restore FPU registers or vector registers may be added in a later release as a build-time save/restore FPU registers or vector registers may be added in a later release as a build-time
setting -- for now, we assume a soft-float ABI with no optional processor features. In practice, this setting -- for now, we assume a soft-float ABI with no optional processor features. In practice, this
does not really matter, code using these functions are unlikely to be impacted by this design does not really matter, code using these functions are unlikely to be impacted by this design
assumption. assumption. This is a work in progress, as newer compilers will spill even non-floating-point state
through floating point registers when allowed to do so.

View File

@ -1 +1 @@
1.2 1.3.2

View File

@ -22,23 +22,8 @@ ALIAS(__getcontext, libucontext_getcontext)
PROC_NAME(libucontext_getcontext): PROC_NAME(libucontext_getcontext):
str xzr, [x0, #REG_OFFSET(0)] str xzr, [x0, #REG_OFFSET(0)]
/* save GPRs */ /* save x2 and x3 for reuse */
stp x0, x1, [x0, #REG_OFFSET(0)]
stp x2, x3, [x0, #REG_OFFSET(2)] stp x2, x3, [x0, #REG_OFFSET(2)]
stp x4, x5, [x0, #REG_OFFSET(4)]
stp x6, x7, [x0, #REG_OFFSET(6)]
stp x8, x9, [x0, #REG_OFFSET(8)]
stp x10, x11, [x0, #REG_OFFSET(10)]
stp x12, x13, [x0, #REG_OFFSET(12)]
stp x14, x15, [x0, #REG_OFFSET(14)]
stp x16, x17, [x0, #REG_OFFSET(16)]
stp x18, x19, [x0, #REG_OFFSET(18)]
stp x20, x21, [x0, #REG_OFFSET(20)]
stp x22, x23, [x0, #REG_OFFSET(22)]
stp x24, x25, [x0, #REG_OFFSET(24)]
stp x26, x27, [x0, #REG_OFFSET(26)]
stp x28, x29, [x0, #REG_OFFSET(28)]
str x30, [x0, #REG_OFFSET(30)]
/* save current program counter in link register */ /* save current program counter in link register */
str x30, [x0, #PC_OFFSET] str x30, [x0, #PC_OFFSET]
@ -56,6 +41,26 @@ PROC_NAME(libucontext_getcontext):
stp q12, q13, [x2, #208] stp q12, q13, [x2, #208]
stp q14, q15, [x2, #240] stp q14, q15, [x2, #240]
/* save GPRs and return value 0 */
mov x2, x0
mov x0, #0 mov x0, #0
stp x0, x1, [x2, #REG_OFFSET(0)]
/* x2 and x3 have already been saved */
stp x4, x5, [x2, #REG_OFFSET(4)]
stp x6, x7, [x2, #REG_OFFSET(6)]
stp x8, x9, [x2, #REG_OFFSET(8)]
stp x10, x11, [x2, #REG_OFFSET(10)]
stp x12, x13, [x2, #REG_OFFSET(12)]
stp x14, x15, [x2, #REG_OFFSET(14)]
stp x16, x17, [x2, #REG_OFFSET(16)]
stp x18, x19, [x2, #REG_OFFSET(18)]
stp x20, x21, [x2, #REG_OFFSET(20)]
stp x22, x23, [x2, #REG_OFFSET(22)]
stp x24, x25, [x2, #REG_OFFSET(24)]
stp x26, x27, [x2, #REG_OFFSET(26)]
stp x28, x29, [x2, #REG_OFFSET(28)]
str x30, [x2, #REG_OFFSET(30)]
ret ret
END(libucontext_getcontext) END(libucontext_getcontext)

View File

@ -2,8 +2,11 @@
#define REG_SZ (4) #define REG_SZ (4)
#define MCONTEXT_GREGS (32) #define MCONTEXT_GREGS (32)
#define VFP_MAGIC_OFFSET (232)
#define VFP_D8_OFFSET (304)
#define TYPE(__proc) #define TYPE(__proc) .type __proc, %function;
#define END(__proc)
#define FETCH_LINKPTR(dest) \ #define FETCH_LINKPTR(dest) \
asm("movs %0, r4" : "=r" ((dest))) asm("movs %0, r4" : "=r" ((dest)))

View File

@ -22,6 +22,27 @@ FUNC(libucontext_getcontext)
str r13, [r0, #REG_OFFSET(13)] str r13, [r0, #REG_OFFSET(13)]
str r14, [r0, #REG_OFFSET(15)] str r14, [r0, #REG_OFFSET(15)]
#ifndef FORCE_SOFT_FLOAT
#ifndef FORCE_HARD_FLOAT
/* test for vfp, set kernel-defined magic number in uc_regspace */
push {r0-r1,fp,lr}
mov r0, #16
bl getauxval
tst r0, #64
pop {r0-r1,fp,lr}
moveq r2, #0
ldrne r2, =#0x56465001
str r2, [r0, #VFP_MAGIC_OFFSET]
beq 1f
#endif
/* if vfp detected, save d8-d15 */
.fpu vfp
add r1, r0, #VFP_D8_OFFSET
vstmia r1, {d8-d15}
.fpu softvfp
1:
#endif
/* return 0 */ /* return 0 */
mov r0, #0 mov r0, #0
mov pc, lr mov pc, lr

View File

@ -23,6 +23,8 @@ typedef struct libucontext_ucontext {
struct libucontext_ucontext *uc_link; struct libucontext_ucontext *uc_link;
libucontext_stack_t uc_stack; libucontext_stack_t uc_stack;
libucontext_mcontext_t uc_mcontext; libucontext_mcontext_t uc_mcontext;
unsigned long uc_sigmask[128 / sizeof(long)];
unsigned long long uc_regspace[64];
} libucontext_ucontext_t; } libucontext_ucontext_t;
#endif #endif

View File

@ -16,6 +16,22 @@ ALIAS(setcontext, libucontext_setcontext)
ALIAS(__setcontext, libucontext_setcontext) ALIAS(__setcontext, libucontext_setcontext)
FUNC(libucontext_setcontext) FUNC(libucontext_setcontext)
#ifndef FORCE_SOFT_FLOAT
#ifndef FORCE_HARD_FLOAT
/* test for vfp magic number set by getcontext */
ldr r2, [r0, #VFP_MAGIC_OFFSET]
ldr r3, =#0x56465001
cmp r2, r3
bne 1f
#endif
/* if vfp in use, restore d8-d15 from uc_regspace */
.fpu vfp
add r14, r0, #VFP_D8_OFFSET
vldmia r14, {d8-d15}
.fpu softvfp
1:
#endif
/* copy all of the current registers into the ucontext structure */ /* copy all of the current registers into the ucontext structure */
add r14, r0, #REG_OFFSET(0) add r14, r0, #REG_OFFSET(0)
ldmia r14, {r0-r12} ldmia r14, {r0-r12}

View File

@ -16,11 +16,33 @@ ALIAS(swapcontext, libucontext_swapcontext)
ALIAS(__swapcontext, libucontext_swapcontext) ALIAS(__swapcontext, libucontext_swapcontext)
FUNC(libucontext_swapcontext) FUNC(libucontext_swapcontext)
#ifndef FORCE_SOFT_FLOAT
#ifndef FORCE_HARD_FLOAT
/* test for vfp magic number, copy to other ucontext */
ldr r3, [r1, #VFP_MAGIC_OFFSET]
ldr r4, =#0x56465001
str r3, [r0, #VFP_MAGIC_OFFSET]
cmp r3, r4
bne 1f
#endif
/* if vfp in use, save and restore d8-d15 */
.fpu vfp
add r2, r0, #VFP_D8_OFFSET
vstmia r2, {d8-d15}
add r14, r1, #VFP_D8_OFFSET
vldmia r14, {d8-d15}
.fpu softvfp
1:
#endif
/* copy all of the current registers into the ucontext structure */ /* copy all of the current registers into the ucontext structure */
add r2, r0, #REG_OFFSET(0)
stmia r2, {r0-r12}
str r13, [r0,#REG_OFFSET(13)] str r13, [r0,#REG_OFFSET(13)]
str r14, [r0,#REG_OFFSET(15)] str r14, [r0,#REG_OFFSET(15)]
add r2, r0, #REG_OFFSET(0)
/* copy r0 with value 0 to indicate success (return value 0) */
mov r0, #0
stmia r2, {r0-r12}
/* load new registers from the second ucontext structure */ /* load new registers from the second ucontext structure */
add r14, r1, #REG_OFFSET(0) add r14, r1, #REG_OFFSET(0)

View File

@ -40,6 +40,8 @@
ENT(__proc) \ ENT(__proc) \
PROC_NAME(__proc): \ PROC_NAME(__proc): \
SETUP_FRAME(__proc) SETUP_FRAME(__proc)
#ifndef END
#ifdef __clang__ #ifdef __clang__
#define END(__proc) #define END(__proc)
#else #else
@ -47,6 +49,7 @@ PROC_NAME(__proc): \
.end __proc; \ .end __proc; \
.size __proc,.-__proc; .size __proc,.-__proc;
#endif #endif
#endif
#ifdef EXPORT_UNPREFIXED #ifdef EXPORT_UNPREFIXED
#define ALIAS(__alias, __real) \ #define ALIAS(__alias, __real) \

View File

@ -14,7 +14,19 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
/* We need to make sure that the C compiler doesn't push any
* additional data to the stack frame. Otherwise, assumptions
* made by the architecture-specific implementation of the
* FETCH_LINKPTR() macro about the location of the linkptr,
* relative to the stack pointer, will not hold.
*
* Hence, we compile this function with -fomit-frame-pointer
* and use the register storage-class specifier for all local
* vars. Note that the latter is just a "suggestion" (see C99).
*/
__attribute__ ((visibility ("hidden"))) __attribute__ ((visibility ("hidden")))
__attribute__ ((optimize ("omit-frame-pointer")))
void void
libucontext_trampoline(void) libucontext_trampoline(void)
{ {

View File

@ -45,11 +45,17 @@
/* frame pointer is actually $22 */ /* frame pointer is actually $22 */
#define REG_FP (22) #define REG_FP (22)
/* $s0 is $23 */
#define REG_S0 (23)
/* $ra is $1 */
#define REG_RA (1)
/* offset to mc_gregs in ucontext_t */ /* offset to mc_gregs in ucontext_t */
#define MCONTEXT_GREGS (48) #define MCONTEXT_GREGS (184)
/* offset to PC in ucontext_t */ /* offset to PC in ucontext_t */
#define MCONTEXT_PC (40) #define MCONTEXT_PC (176)
/* offset to uc_link in ucontext_t */ /* offset to uc_link in ucontext_t */
#define UCONTEXT_UC_LINK (8) #define UCONTEXT_UC_LINK (8)

View File

@ -35,11 +35,14 @@ FUNC(libucontext_getcontext)
st.d $s8, $a0, REG_OFFSET(31) st.d $s8, $a0, REG_OFFSET(31)
st.d $a2, $a0, REG_OFFSET(3) st.d $a2, $a0, REG_OFFSET(3)
st.d $zero, $a0, REG_OFFSET(4)
st.d $a3, $a0, REG_OFFSET(22) st.d $a3, $a0, REG_OFFSET(22)
st.d $ra, $a0, REG_OFFSET(1) st.d $ra, $a0, REG_OFFSET(1)
st.d $ra, $a0, (MCONTEXT_PC) st.d $ra, $a0, (MCONTEXT_PC)
move $a0, $zero
POP_FRAME(libucontext_getcontext) POP_FRAME(libucontext_getcontext)
jr $ra jr $ra

View File

@ -1,108 +0,0 @@
/*
* Copyright (c) 2021 Peng Fan <fanpeng@loongson.cn>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include "defs.h"
#define LOCALSZ (6)
#define A3_OFF (FRAMESZ - (5 * REG_SZ))
#define A4_OFF (FRAMESZ - (4 * REG_SZ))
#define A5_OFF (FRAMESZ - (3 * REG_SZ))
#define A6_OFF (FRAMESZ - (2 * REG_SZ))
#define A7_OFF (FRAMESZ - (1 * REG_SZ))
ALIAS(makecontext, libucontext_makecontext)
FUNC(libucontext_makecontext)
PUSH_FRAME(libucontext_makecontext)
move $t5, $a0
move $t4, $a1
/* store $a3 through $a7 to the stack frame. */
st.d $a3, $sp, A3_OFF
st.d $a4, $sp, A4_OFF
st.d $a5, $sp, A5_OFF
st.d $a6, $sp, A6_OFF
st.d $a7, $sp, A7_OFF
/* set $zero in the mcontext to 1. */
addi.d $v0, $zero, 1
st.d $v0, $t5, REG_OFFSET(0)
/* ensure the stack is aligned on a quad-word boundary. */
ld.d $t0, $t5, UCONTEXT_STACK_PTR
ld.d $t2, $t5, UCONTEXT_STACK_SIZE
/* the third argument(from zero), that's the first argument of func() */
addi.d $t1, $sp, A3_OFF
add.d $t0, $t0, $t2
addi.d $t7, $zero, ALMASK
and $t0, $t0, $t7
/* number of args */
beq $a2, $zero, no_more_arguments
bltu $a2, $zero, no_more_arguments
/* store register arguments. */
addi.d $t2, $t5, MCONTEXT_GREGS + (4 * REG_SZ)
move $t3, $zero
store_register_arg:
addi.d $t3, $t3, 1
ld.d $v1, $t1, 0
addi.d $t1, $t1, REG_SZ
st.d $v1, $t2, 0
addi.d $t2, $t2, REG_SZ
addi.d $t6, $zero, 8
bltu $t3, $t6, store_register_arg
bgeu $t3, $a2, no_more_arguments
/* make room for stack arguments. */
sub.d $t2, $a2, $t3
addi.d $t6, $zero, 3
sll.d $t2, $t2, $t6
sub.d $t0, $t0, $t2
addi.d $t6, $zero, ALMASK
and $t0, $t0, $t6
/* store stack arguments. */
move $t2, $t0
store_stack_arg:
addi.d $t3, $t3, 1
ld.d $v1, $t1, 0
addi.d $t1, $t1, REG_SZ
st.d $v1, $t2, 0
addi.d $t2, $t2, REG_SZ
bltu $t3, $a2, store_stack_arg
no_more_arguments:
/* trampoline setup. */
la.got $t8, libucontext_trampoline
ld.d $v1, $t5, UCONTEXT_UC_LINK
st.d $v1, $t5, REG_OFFSET(23)
st.d $t0, $t5, REG_OFFSET(3)
st.d $t8, $t5, REG_OFFSET(1)
st.d $t4, $t5, MCONTEXT_PC
POP_FRAME(libucontext_makecontext)
jr $ra
END(libucontext_makecontext)

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2024 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include "defs.h"
#include <libucontext/libucontext.h>
extern void libucontext_trampoline(void);
void
libucontext_makecontext(libucontext_ucontext_t *ucp, void (*func)(void), int argc, ...)
{
libucontext_greg_t *sp, *regp;
va_list va;
int i;
/* set up and align the stack. */
sp = (libucontext_greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
sp -= argc < 8 ? 0 : argc - 8;
sp = (libucontext_greg_t *) (((uintptr_t) sp & -16L));
/* set up the ucontext structure */
ucp->uc_mcontext.__gregs[REG_RA] = (libucontext_greg_t) libucontext_trampoline;
ucp->uc_mcontext.__gregs[REG_S0] = (libucontext_greg_t) ucp->uc_link;
ucp->uc_mcontext.__gregs[REG_SP] = (libucontext_greg_t) sp;
ucp->uc_mcontext.__pc = (libucontext_greg_t) func;
va_start(va, argc);
/* first 8 args go in $a0 through $a7. */
regp = &(ucp->uc_mcontext.__gregs[REG_A0]);
for (i = 0; (i < argc && i < 8); i++)
*regp++ = va_arg (va, libucontext_greg_t);
/* remainder overflows into stack */
for (; i < argc; i++)
*sp++ = va_arg (va, libucontext_greg_t);
va_end(va);
}
#ifdef EXPORT_UNPREFIXED
extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
#endif

View File

@ -49,7 +49,7 @@ FUNC(libucontext_setcontext)
ld.d $t8, $t5, (MCONTEXT_PC) ld.d $t8, $t5, (MCONTEXT_PC)
jr $t8 jr $t8
move $v0, $zero move $a0, $zero
POP_FRAME(libucontext_setcontext) POP_FRAME(libucontext_setcontext)
END(libucontext_setcontext) END(libucontext_setcontext)

View File

@ -39,6 +39,7 @@ FUNC(libucontext_swapcontext)
st.d $s8, $t5, REG_OFFSET(31) st.d $s8, $t5, REG_OFFSET(31)
st.d $a3, $t5, REG_OFFSET(3) st.d $a3, $t5, REG_OFFSET(3)
st.d $zero, $t5, REG_OFFSET(4)
st.d $a4, $t5, REG_OFFSET(22) st.d $a4, $t5, REG_OFFSET(22)
st.d $ra, $t5, REG_OFFSET(1) st.d $ra, $t5, REG_OFFSET(1)
@ -77,7 +78,7 @@ FUNC(libucontext_swapcontext)
ld.d $t8, $t4, (MCONTEXT_PC) ld.d $t8, $t4, (MCONTEXT_PC)
jr $t8 jr $t8
move $v0, $zero move $a0, $zero
fail: fail:
la.global $t8, exit la.global $t8, exit
@ -85,5 +86,5 @@ fail:
POP_FRAME(libucontext_swapcontext) POP_FRAME(libucontext_swapcontext)
jirl $ra, $t8, 0 jirl $ra, $t8, 0
move $v0, $zero move $a0, $zero
END(libucontext_swapcontext) END(libucontext_swapcontext)

View File

@ -19,8 +19,8 @@ FUNC(libucontext_getcontext)
l.sw REG_OFFSET(1)(r3), r1 /* store r1 and r2 */ l.sw REG_OFFSET(1)(r3), r1 /* store r1 and r2 */
l.sw REG_OFFSET(2)(r3), r2 l.sw REG_OFFSET(2)(r3), r2
l.sw REG_OFFSET(9)(r3), r9 /* store r9 to both r9 and r11 in the context */ l.sw REG_OFFSET(9)(r3), r9 /* link register */
l.sw REG_OFFSET(11)(r3), r9 l.sw REG_OFFSET(11)(r3), r0 /* return value is 0 */
l.sw REG_OFFSET(10)(r3), r10 /* store r10 for TLS */ l.sw REG_OFFSET(10)(r3), r10 /* store r10 for TLS */
@ -34,6 +34,6 @@ FUNC(libucontext_getcontext)
l.sw REG_OFFSET(28)(r3), r28 l.sw REG_OFFSET(28)(r3), r28
l.sw REG_OFFSET(30)(r3), r30 l.sw REG_OFFSET(30)(r3), r30
l.jr r9
l.ori r11, r0, 0 l.ori r11, r0, 0
l.jr r9
END(libucontext_getcontext) END(libucontext_getcontext)

View File

@ -20,8 +20,8 @@ FUNC(libucontext_swapcontext)
l.sw REG_OFFSET(1)(r3), r1 /* store r1 and r2 */ l.sw REG_OFFSET(1)(r3), r1 /* store r1 and r2 */
l.sw REG_OFFSET(2)(r3), r2 l.sw REG_OFFSET(2)(r3), r2
l.sw REG_OFFSET(9)(r3), r9 /* store r9 to both r9 and r11 in the context */ l.sw REG_OFFSET(9)(r3), r9 /* link register */
l.sw REG_OFFSET(11)(r3), r9 l.sw REG_OFFSET(11)(r3), r0 /* return value is zero */
l.sw REG_OFFSET(10)(r3), r10 /* store r10 for TLS */ l.sw REG_OFFSET(10)(r3), r10 /* store r10 for TLS */
@ -63,6 +63,6 @@ FUNC(libucontext_swapcontext)
l.lwz r28, REG_OFFSET(28)(r30) l.lwz r28, REG_OFFSET(28)(r30)
l.lwz r30, REG_OFFSET(30)(r30) l.lwz r30, REG_OFFSET(30)(r30)
l.jr r11 /* jump to new starting address */
l.ori r11, r0, 0 l.ori r11, r0, 0
l.jr r9 /* jump to new starting address */
END(libucontext_swapcontext) END(libucontext_swapcontext)

View File

@ -25,8 +25,8 @@ FUNC(libucontext_getcontext)
sw s1, REG_OFFSET(REG_S1)(a0) sw s1, REG_OFFSET(REG_S1)(a0)
/* return register block */ /* return register block */
sw a0, REG_OFFSET(REG_A0)(a0) sw x0, REG_OFFSET(REG_A0)(a0)
sw a1, REG_OFFSET(REG_A1)(a0) sw x0, REG_OFFSET(REG_A1)(a0)
/* second saved register block */ /* second saved register block */
sw s2, REG_OFFSET(REG_S2)(a0) sw s2, REG_OFFSET(REG_S2)(a0)
@ -41,5 +41,6 @@ FUNC(libucontext_getcontext)
sw s11, REG_OFFSET(REG_S11)(a0) sw s11, REG_OFFSET(REG_S11)(a0)
/* done saving, return */ /* done saving, return */
mv a0, x0
ret ret
END(libucontext_getcontext) END(libucontext_getcontext)

View File

@ -28,8 +28,8 @@ FUNC(libucontext_swapcontext)
sw s1, REG_OFFSET(REG_S1)(a0) sw s1, REG_OFFSET(REG_S1)(a0)
/* return register block */ /* return register block */
sw a0, REG_OFFSET(REG_A0)(a0) sw x0, REG_OFFSET(REG_A0)(a0)
sw a1, REG_OFFSET(REG_A1)(a0) sw x0, REG_OFFSET(REG_A1)(a0)
/* second saved register block */ /* second saved register block */
sw s2, REG_OFFSET(REG_S2)(a0) sw s2, REG_OFFSET(REG_S2)(a0)

View File

@ -25,8 +25,8 @@ FUNC(libucontext_getcontext)
sd s1, REG_OFFSET(REG_S1)(a0) sd s1, REG_OFFSET(REG_S1)(a0)
/* return register block */ /* return register block */
sd a0, REG_OFFSET(REG_A0)(a0) sd x0, REG_OFFSET(REG_A0)(a0)
sd a1, REG_OFFSET(REG_A1)(a0) sd x0, REG_OFFSET(REG_A1)(a0)
/* second saved register block */ /* second saved register block */
sd s2, REG_OFFSET(REG_S2)(a0) sd s2, REG_OFFSET(REG_S2)(a0)
@ -41,5 +41,6 @@ FUNC(libucontext_getcontext)
sd s11, REG_OFFSET(REG_S11)(a0) sd s11, REG_OFFSET(REG_S11)(a0)
/* done saving, return */ /* done saving, return */
mv a0, x0
ret ret
END(libucontext_getcontext) END(libucontext_getcontext)

View File

@ -28,8 +28,8 @@ FUNC(libucontext_swapcontext)
sd s1, REG_OFFSET(REG_S1)(a0) sd s1, REG_OFFSET(REG_S1)(a0)
/* return register block */ /* return register block */
sd a0, REG_OFFSET(REG_A0)(a0) sd x0, REG_OFFSET(REG_A0)(a0)
sd a1, REG_OFFSET(REG_A1)(a0) sd x0, REG_OFFSET(REG_A1)(a0)
/* second saved register block */ /* second saved register block */
sd s2, REG_OFFSET(REG_S2)(a0) sd s2, REG_OFFSET(REG_S2)(a0)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, 2020 Ariadne Conill <ariadne@dereferenced.org> * Copyright (c) 2018, 2020, 2024 Ariadne Conill <ariadne@dereferenced.org>
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -19,12 +19,14 @@ FUNC(libucontext_swapcontext)
lgr %r1, %r2 /* use %r1 to save current context to */ lgr %r1, %r2 /* use %r1 to save current context to */
lgr %r0, %r3 /* use %r0 for source context */ lgr %r0, %r3 /* use %r0 for source context */
la %r2, 0 /* zero out future return value */
stam %a0, %a15, AREG_OFFSET(0)(%r1) /* store access registers */ stam %a0, %a15, AREG_OFFSET(0)(%r1) /* store access registers */
stmg %r0, %r15, REG_OFFSET(0)(%r1) /* store general-purpose registers */ stmg %r0, %r15, REG_OFFSET(0)(%r1) /* store general-purpose registers */
lgr %r2, %r0 /* swap %r0 to %r2 (XXX: figure out why it hates loading from %r0) */ lgr %r5, %r0 /* copy %r0 to %r5 so that %r0 doesn't get clobbered */
lam %a2, %a15, AREG_OFFSET(2)(%r2) /* load access registers, but skip %a0 and %a1 which are for TLS */ lam %a2, %a15, AREG_OFFSET(2)(%r5) /* load access registers, but skip %a0 and %a1 which are for TLS */
lmg %r0, %r15, REG_OFFSET(0)(%r2) /* load general-purpose registers */ lmg %r0, %r15, REG_OFFSET(0)(%r5) /* load general-purpose registers */
br %r14 /* return to new link register address */ br %r14 /* return to new link register address */
END(libucontext_swapcontext) END(libucontext_swapcontext)

View File

@ -57,9 +57,6 @@
#define MCONTEXT_GREGS (20) #define MCONTEXT_GREGS (20)
#define FETCH_LINKPTR(dest) \
asm("movl (%%esp, %%ebx, 4), %0" : "=r" ((dest)));
#include "common-defs.h" #include "common-defs.h"
#endif #endif

41
arch/x86/startcontext.S Normal file
View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2018, 2020 Ariadne Conill <ariadne@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include "defs.h"
FUNC(libucontext_trampoline)
/* get the proper context into position and test for NULL */
leal (%esp,%ebx,4), %esp
cmpl $0, (%esp)
/* restore global offset table, exit@plt and libucontext_setcontext@plt need this */
call __i686_get_pc_thunk_bx
addl $_GLOBAL_OFFSET_TABLE_, %ebx
/* if we have no linked context, lets get out of here */
je no_linked_context
/* call setcontext to switch to the linked context */
call libucontext_setcontext@plt
movl %eax, (%esp)
no_linked_context:
/* we are returning into a null context, it seems, so maybe we should exit */
call exit@plt
/* something is really hosed, call hlt to force termination */
hlt
__i686_get_pc_thunk_bx:
mov (%esp), %ebx
ret
END(libucontext_trampoline)

View File

@ -1,3 +0,0 @@
#include "defs.h"
#include <libucontext/libucontext.h>
#include "common-trampoline.c"

21
doc/meson.build Normal file
View File

@ -0,0 +1,21 @@
scdoc = find_program('scdoc', required: true)
custom_target(
'libucontext.3',
output: 'libucontext.3',
input: 'libucontext.scd',
command: [ scdoc ],
feed: true,
capture: true,
install: true,
install_dir: get_option('mandir') / 'man3'
)
if meson.version().version_compare('>=0.61.0')
foreach link : [ 'get', 'make', 'set', 'swap' ]
install_symlink('libucontext_' + link + 'context.3',
pointing_to: 'libucontext.3',
install_dir: get_option('mandir') / 'man3'
)
endforeach
endif

View File

@ -4,9 +4,17 @@
#include <stddef.h> #include <stddef.h>
#include <libucontext/bits.h> #include <libucontext/bits.h>
#ifdef __cplusplus
extern "C" {
#endif
int libucontext_getcontext(libucontext_ucontext_t *); int libucontext_getcontext(libucontext_ucontext_t *);
void libucontext_makecontext(libucontext_ucontext_t *, void (*)(), int, ...); void libucontext_makecontext(libucontext_ucontext_t *, void (*)(), int, ...);
int libucontext_setcontext(const libucontext_ucontext_t *); int libucontext_setcontext(const libucontext_ucontext_t *);
int libucontext_swapcontext(libucontext_ucontext_t *, const libucontext_ucontext_t *); int libucontext_swapcontext(libucontext_ucontext_t *, const libucontext_ucontext_t *);
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@ -1,8 +1,9 @@
libdir=@LIBUCONTEXT_LIBDIR@ libdir=@LIBUCONTEXT_SHARED_LIBDIR@
static_libdir=@LIBUCONTEXT_STATIC_LIBDIR@
includedir=@LIBUCONTEXT_INCLUDEDIR@ includedir=@LIBUCONTEXT_INCLUDEDIR@
Name: libucontext Name: libucontext
Version: @LIBUCONTEXT_VERSION@ Version: @LIBUCONTEXT_VERSION@
Description: ucontext library implementation (standalone) Description: ucontext library implementation (standalone)
Libs: -L${libdir} -lucontext Libs: -L${libdir} -L${static_libdir} -lucontext
Cflags: -I${includedir} Cflags: -I${includedir}

View File

@ -1,7 +1,7 @@
project( project(
'libucontext', 'libucontext',
'c', 'c',
meson_version : '>=0.55.0', meson_version : '>=0.59.0',
default_options: ['c_std=gnu11', 'default_library=both'], default_options: ['c_std=gnu11', 'default_library=both'],
version : run_command('head', files('VERSION')).stdout() version : run_command('head', files('VERSION')).stdout()
) )
@ -40,7 +40,7 @@ if cpu in ['ppc', 'ppc64']
'arch' / cpu / 'retfromsyscall.c' 'arch' / cpu / 'retfromsyscall.c'
] ]
endif endif
if cpu not in ['mips', 'mips64', 'ppc', 'ppc64', 's390x'] if cpu not in ['loongarch64', 'mips', 'mips64', 'ppc', 'ppc64', 's390x', 'x86']
project_source_files += [ project_source_files += [
'arch' / cpu / 'trampoline.c' 'arch' / cpu / 'trampoline.c'
] ]
@ -56,7 +56,7 @@ project_includes = [
] ]
build_args = [ build_args = [
'-D_BSD_SOURCE' '-D_DEFAULT_SOURCE'
] ]
@ -144,9 +144,8 @@ endif
# Docs # Docs
# ==== # ====
# TODO: meson.build for docs if not meson.is_subproject() and get_option('docs')
if not meson.is_subproject() subdir('doc')
#subdir('docs')
endif endif
# ========== # ==========

View File

@ -4,3 +4,5 @@ option('export_unprefixed', type : 'boolean', value : true,
description: 'Export POSIX 2004 ucontext names as alises') description: 'Export POSIX 2004 ucontext names as alises')
option('cpu', type : 'string', value : '', option('cpu', type : 'string', value : '',
description: 'Target CPU architecture for cross compile') description: 'Target CPU architecture for cross compile')
option('docs', type : 'boolean', value : false,
description: 'Build and install man pages')

View File

@ -9,6 +9,9 @@
#include <string.h> #include <string.h>
#include <libucontext/libucontext.h> #include <libucontext/libucontext.h>
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
static libucontext_ucontext_t ctx[3]; static libucontext_ucontext_t ctx[3];
@ -36,7 +39,8 @@ static void f1 (int a, int b, int c, int d, int e, int f, int g, int h, int i, i
printf("looks like all arguments are passed correctly\n"); printf("looks like all arguments are passed correctly\n");
printf("swap back to f2\n"); printf("swap back to f2\n");
libucontext_swapcontext(&ctx[1], &ctx[2]); if (libucontext_swapcontext(&ctx[1], &ctx[2]) != 0)
handle_error("libucontext_swapcontext");
printf("finish f1\n"); printf("finish f1\n");
} }
@ -44,7 +48,8 @@ static void f1 (int a, int b, int c, int d, int e, int f, int g, int h, int i, i
static void f2 (void) { static void f2 (void) {
printf("start f2\n"); printf("start f2\n");
printf("swap to f1\n"); printf("swap to f1\n");
libucontext_swapcontext(&ctx[2], &ctx[1]); if (libucontext_swapcontext(&ctx[2], &ctx[1]) != 0)
handle_error("libucontext_swapcontext");
printf("finish f2, should swap to f1\n"); printf("finish f2, should swap to f1\n");
} }
@ -63,7 +68,8 @@ int main (int argc, const char *argv[]) {
printf("setting up context 1\n"); printf("setting up context 1\n");
libucontext_getcontext(&ctx[1]); if (libucontext_getcontext(&ctx[1]) != 0)
handle_error("libucontext_getcontext");
ctx[1].uc_stack.ss_sp = st1; ctx[1].uc_stack.ss_sp = st1;
ctx[1].uc_stack.ss_size = sizeof st1; ctx[1].uc_stack.ss_size = sizeof st1;
ctx[1].uc_link = &ctx[0]; ctx[1].uc_link = &ctx[0];
@ -83,16 +89,20 @@ int main (int argc, const char *argv[]) {
printf("doing initial swapcontext\n"); printf("doing initial swapcontext\n");
libucontext_swapcontext(&ctx[0], &ctx[2]); if (libucontext_swapcontext(&ctx[0], &ctx[2]) != 0)
handle_error("libucontext_swapcontext");
printf("returned from initial swapcontext\n"); printf("returned from initial swapcontext\n");
/* test ability to use getcontext/setcontext without makecontext */ /* test ability to use getcontext/setcontext without makecontext */
libucontext_getcontext(&ctx[1]); if (libucontext_getcontext(&ctx[1]) != 0)
handle_error("libucontext_getcontext");
printf("done = %d\n", done); printf("done = %d\n", done);
if (done++ == 0) libucontext_setcontext(&ctx[1]); if (done++ == 0)
if (libucontext_setcontext(&ctx[1]) != 0)
handle_error("libucontext_setcontext");
if (done != 2) { if (done != 2) {
fprintf(stderr, "wrong value for done. got %d, expected 2\n", done); fprintf(stderr, "wrong value for done. got %d, expected 2\n", done);
abort(); abort();

View File

@ -9,6 +9,9 @@
#include <string.h> #include <string.h>
#include <ucontext.h> #include <ucontext.h>
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
static ucontext_t ctx[3]; static ucontext_t ctx[3];
@ -36,7 +39,8 @@ static void f1 (int a, int b, int c, int d, int e, int f, int g, int h, int i, i
printf("looks like all arguments are passed correctly\n"); printf("looks like all arguments are passed correctly\n");
printf("swap back to f2\n"); printf("swap back to f2\n");
swapcontext(&ctx[1], &ctx[2]); if (swapcontext(&ctx[1], &ctx[2]) != 0)
handle_error("swapcontext");
printf("finish f1\n"); printf("finish f1\n");
} }
@ -44,7 +48,8 @@ static void f1 (int a, int b, int c, int d, int e, int f, int g, int h, int i, i
static void f2 (void) { static void f2 (void) {
printf("start f2\n"); printf("start f2\n");
printf("swap to f1\n"); printf("swap to f1\n");
swapcontext(&ctx[2], &ctx[1]); if (swapcontext(&ctx[2], &ctx[1]) != 0)
handle_error("swapcontext");
printf("finish f2, should swap to f1\n"); printf("finish f2, should swap to f1\n");
} }
@ -67,7 +72,7 @@ int main (int argc, const char *argv[]) {
ctx[1].uc_stack.ss_sp = st1; ctx[1].uc_stack.ss_sp = st1;
ctx[1].uc_stack.ss_size = sizeof st1; ctx[1].uc_stack.ss_size = sizeof st1;
ctx[1].uc_link = &ctx[0]; ctx[1].uc_link = &ctx[0];
makecontext(&ctx[1], f1, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); makecontext(&ctx[1], (void *) f1, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
printf("setting up context 2\n"); printf("setting up context 2\n");
@ -77,22 +82,25 @@ int main (int argc, const char *argv[]) {
ctx[2].uc_stack.ss_sp = st2; ctx[2].uc_stack.ss_sp = st2;
ctx[2].uc_stack.ss_size = sizeof st2; ctx[2].uc_stack.ss_size = sizeof st2;
ctx[2].uc_link = &ctx[1]; ctx[2].uc_link = &ctx[1];
makecontext(&ctx[2], f2, 0); makecontext(&ctx[2], (void *) f2, 0);
printf("doing initial swapcontext\n"); printf("doing initial swapcontext\n");
swapcontext(&ctx[0], &ctx[2]); if (swapcontext(&ctx[0], &ctx[2]) != 0)
handle_error("swapcontext");
printf("returned from initial swapcontext\n"); printf("returned from initial swapcontext\n");
/* test ability to use getcontext/setcontext without makecontext */ /* test ability to use getcontext/setcontext without makecontext */
getcontext(&ctx[1]); if (getcontext(&ctx[1]) != 0)
handle_error("getcontext");
printf("done = %d\n", done); printf("done = %d\n", done);
if (done++ == 0) setcontext(&ctx[1]); if (done++ == 0)
if (setcontext(&ctx[1]) != 0)
handle_error("setcontext");
if (done != 2) { if (done != 2) {
fprintf(stderr, "wrong value for done. got %d, expected 2\n", done); fprintf(stderr, "wrong value for done. got %d, expected 2\n", done);
abort(); abort();