summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2018-06-22 14:44:12 +0200
committerAlexander Graf <agraf@suse.de>2018-09-23 21:55:30 +0200
commit3fcb7147584f8cf5128e1c5eb6b7e49dd86a5473 (patch)
treecfb9d1d68617f94ae1ff2f17c949fc6498689695 /arch
parentaaace4b0860fbe22b2b08f761b3c6ea12af94d5e (diff)
sandbox: Fix setjmp/longjmp
In sandbox, longjmp returns to itself in an endless loop because os_longjmp() calls into longjmp() which is provided by U-Boot which again calls os_longjmp(). Setjmp on the other hand must not return because otherwise the return freees up stack elements that we need during longjmp(). The only straight forward fix that doesn't involve nasty hacks I could find is to directly link against the system setjmp/longjmp implementations. That means we just provide the compiler with hints that the symbol will be available and actually fill them out with versions from libc. This approach should be reasonably platform agnostic Signed-off-by: Alexander Graf <agraf@suse.de> Reviewed-by: Simon Glass <sjg@chromium.org> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch')
-rw-r--r--arch/sandbox/cpu/cpu.c12
-rw-r--r--arch/sandbox/cpu/os.c22
-rw-r--r--arch/sandbox/include/asm/setjmp.h5
3 files changed, 5 insertions, 34 deletions
diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c
index e523223ebf..6098945049 100644
--- a/arch/sandbox/cpu/cpu.c
+++ b/arch/sandbox/cpu/cpu.c
@@ -288,15 +288,3 @@ ulong timer_get_boot_us(void)
return (count - base_count) / 1000;
}
-
-int setjmp(jmp_buf jmp)
-{
- return os_setjmp((ulong *)jmp, sizeof(*jmp));
-}
-
-void longjmp(jmp_buf jmp, int ret)
-{
- os_longjmp((ulong *)jmp, ret);
- while (1)
- ;
-}
diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index ca8d924cd6..bb075042ad 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -631,28 +631,6 @@ void os_localtime(struct rtc_time *rt)
rt->tm_isdst = tm->tm_isdst;
}
-int os_setjmp(ulong *jmp, int size)
-{
- jmp_buf dummy;
-
- /*
- * We cannot rely on the struct name that jmp_buf uses, so use a
- * local variable here
- */
- if (size < sizeof(dummy)) {
- printf("setjmp: jmpbuf is too small (%d bytes, need %d)\n",
- size, sizeof(jmp_buf));
- return -ENOSPC;
- }
-
- return setjmp((struct __jmp_buf_tag *)jmp);
-}
-
-void os_longjmp(ulong *jmp, int ret)
-{
- longjmp((struct __jmp_buf_tag *)jmp, ret);
-}
-
void os_abort(void)
{
abort();
diff --git a/arch/sandbox/include/asm/setjmp.h b/arch/sandbox/include/asm/setjmp.h
index 1fe37c91cc..001c7ea322 100644
--- a/arch/sandbox/include/asm/setjmp.h
+++ b/arch/sandbox/include/asm/setjmp.h
@@ -24,6 +24,11 @@ struct jmp_buf_data {
typedef struct jmp_buf_data jmp_buf[1];
+/*
+ * We have to directly link with the system versions of
+ * setjmp/longjmp, because setjmp must not return as otherwise
+ * the stack may become invalid.
+ */
int setjmp(jmp_buf jmp);
__noreturn void longjmp(jmp_buf jmp, int ret);