Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build for nuttx problem, undefined reference to 'setjmp' and 'longjmp' #231

Closed
seanshpark opened this issue Jun 24, 2015 · 25 comments
Closed

Comments

@seanshpark
Copy link
Contributor

With latest JerryScript, cannot build for nuttx cause of

jerry-core/parser/js/parser.cpp:2917: undefined reference to `setjmp'
jerry-core/parser/js/syntax-errors.cpp:67: undefined reference to `longjmp'

How to reproduce: with iotjs build for nuttx. Get latest iotjs source.

cd iotjs
git pull

./tools/build.py --buildtype=release \
--target-arch=arm --target-os=nuttx \
--nuttx-home=/home/(...)/harmony/nuttx/nuttx \
--buildlib --no-checktest

replace --nuttx-home value with your nuttx folder.
Please refer https://github.com/Samsung/iotjs/wiki/Build-for-NuttX page.

@egavrin
Copy link
Contributor

egavrin commented Jun 24, 2015

Which libc is used by NuttX? uClibc++ or Newlib? They definitely should have the proper implementation of setjmp()/longjmp().
As workaround you can borrow our implementation of setjmp()/longjmp() from jerry-libc.

Please refer to this thread http://comments.gmane.org/gmane.comp.embedded.nuttx/8523

Header Files Provided by Your Toolchain.
Certain header files, such as setjmp.h, stdarg.h, and math.h, may still
needed from your toolchain and your compiler may not, however, be able
find these if you compile NuttX without using standard header file.
that is the case, one solution is to copy those header file from

Yes they will be undefined. They are not provided by NuttX. You must provide them your self by
adding the source code or extracting them from your toolchain's C library.

@seanshpark
Copy link
Contributor Author

@egavrin , it's default libc in nuttx. nuttx/nuttx/libc.
can search setjmp but not in libc. I'll try to copy from jerry-libc.

@seanshpark
Copy link
Contributor Author

I've tried this in nuttx but cannot solve. Please help if someone knows how...
error is

AS:  stm32_jerry-hf.S
stm32_jerry-hf.S: Assembler messages:
stm32_jerry-hf.S:14: Error: lo register required -- `stmia r0!,{r4-r11,sp,lr}'
stm32_jerry-hf.S:33: Error: lo register required -- `ldmia r0!,{r4-r11,sp,lr}'
make[2]: *** [stm32_jerry-hf.o] Error 1

Changes: nuttx/configs/stm32f4discovery/src/Makefile

@@ -38,6 +38,11 @@
 CFLAGS += -I$(TOPDIR)/sched

 ASRCS =
+
+ifeq ($(CONFIG_SYSTEM_IOTJS),y)
+ASRCS += stm32_jerry-hf.S
+endif
+
 AOBJS = $(ASRCS:.S=$(OBJEXT))

 CSRCS = stm32_boot.c stm32_bringup.c stm32_spi.c

and configs/stm32f4discovery/src/stm32_jerry-hf.S file copied from jerry-libc

/**
 * setjmp (jmp_buf env)
 *
 * See also:
 *          longjmp
 *
 * @return 0 - if returns from direct call,
 *         nonzero - if returns after longjmp.
 */
        .global setjmp
        .type setjmp, %function
setjmp:
        stmia r0!, {r4 - r11, sp, lr};
        vstm  r0!, {s16 - s31};
        mov   r0, #0;
        bx    lr;
        .size setjmp, . - setjmp

/**
 * longjmp (jmp_buf env, int val)
 *
 * Note:
 *      if val is not 0, then it would be returned from setjmp,
 *      otherwise - 0 would be returned.
 *
 * See also:
 *          setjmp
 */
        .global longjmp
        .type longjmp, %function
longjmp:
        ldmia r0!, {r4 - r11, sp, lr};
        vldm  r0!, {s16 - s31};
        mov   r0, r1;
        cmp   r0, #0;
        bne   1f;
        mov   r0, #1;
1:
        bx    lr;
        .size longjmp, . - setjmp

last line in jerry-libc is

.size longjmu, . - setjmp

is it longjmu vs longjmp typo?

@zherczeg
Copy link
Member

According to: http://e2e.ti.com/support/microcontrollers/stellaris_arm/f/471/p/45181/160958
You should use ".syntax unified".

@seanshpark
Copy link
Contributor Author

@zherczeg , thank you. with some more google search, I've got this code and compile is ok. but don't know it's working or not.


/**
 * setjmp (jmp_buf env)
 *
 * See also:
 *          longjmp
 *
 * @return 0 - if returns from direct call,
 *         nonzero - if returns after longjmp.
 */
        .global setjmp
        .type setjmp, %function
        .syntax unified
        .thumb
setjmp:
        stmia r0!, {r4 - r11, lr};
        vstm  r0!, {s16 - s31};
        mov   r0, #0;
        bx    lr;
        .size setjmp, . - setjmp

/**
 * longjmp (jmp_buf env, int val)
 *
 * Note:
 *      if val is not 0, then it would be returned from setjmp,
 *      otherwise - 0 would be returned.
 *
 * See also:
 *          setjmp
 */
        .global longjmp
        .type longjmp, %function
        .syntax unified
        .thumb
longjmp:
        ldmia r0!, {r4 - r11, lr};
        vldm  r0!, {s16 - s31};
        mov   r0, r1;
        cmp   r0, #0;
        bne   1f;
        mov   r0, #1;
1:
        bx    lr;
        .size longjmp, . - longjmp

@seanshpark
Copy link
Contributor Author

well, get some error.

ICE: Assertion 'al != null_list' failed at /../harmony/iotjs/deps/jerry/jerry-core/parser/js/collections/
array-list.cpp(extract_header):30.
Error: ERR_FAILED_INTERNAL_ASSERTION

@seanshpark
Copy link
Contributor Author

@ruben-ayrapetyan , can you help with hard-float ?
found a code from https://github.com/geeksville/flsq/blob/master/flsq/apm/setjmp.S and it works fine.
I can't find where to put vstm and vldm for _STORE_VFP_S16_S31_IF_HARD_FLOAT and
_LOAD_VFP_S16_S31_IF_HARD_FLOAT.

        .global setjmp
        .type setjmp, %function
        .syntax unified
        .thumb
        .thumb_func
setjmp:
        /* Save registers in jump buffer.  */
        stmia   r0!, {r4, r5, r6, r7}
        mov     r1, r8
        mov     r2, r9
        mov     r3, r10
        mov     r4, fp
        mov     r5, sp
        mov     r6, lr
        stmia   r0!, {r1, r2, r3, r4, r5, r6}
        sub     r0, r0, #40
        /* Restore callee-saved low regs.  */
        ldmia   r0!, {r4, r5, r6, r7}
        /* Return zero.  */
        mov     r0, #0
        bx      lr
        .size setjmp, . - setjmp


        .global longjmp
        .type longjmp, %function
        .syntax unified
        .thumb
        .thumb_func
longjmp:
        /* Restore High regs.  */
        add     r0, r0, #16
        ldmia   r0!, {r2, r3, r4, r5, r6}
        mov     r8, r2
        mov     r9, r3
        mov     r10, r4
        mov     fp, r5
        mov     sp, r6
        ldmia   r0!, {r3} /* lr */
        /* Restore low regs.  */
        sub     r0, r0, #40
        ldmia   r0!, {r4, r5, r6, r7}
        /* Return the result argument, or 1 if it is zero.  */
        mov     r0, r1
        bne     1f
        mov     r0, #1
1:
        bx      r3
        .size longjmp, . - longjmp

I'm not good at ARM asm and can't understand the difference to jerry-libc code.
I tried with saving SP but failed.

@ruben-ayrapetyan
Copy link
Contributor

@seanshpark, vstm / vldm operations could be added in the following way:

setjmp:

       stmia   r0!, {r1, r2, r3, r4, r5, r6}
 >>       vstm  r0!, {s16 - s31}
 >>       sub   r0, r0, #104     // + 16 * 4 = 64 bytes
        /* Restore callee-saved low regs.  */
        ldmia   r0!, {r4, r5, r6, r7}
        /* Return zero.  */
        mov     r0, #0
        bx      lr

longjmp:

        ldmia   r0!, {r3} /* lr */
        /* Restore low regs.  */
 >>       vldm  r0!, {s16 - s31}
 >>       sub   r0, r0, #104
        ldmia   r0!, {r4, r5, r6, r7}

Could you, please, check the changes?

@seanshpark
Copy link
Contributor Author

@ruben-ayrapetyan , thank you for the code, still error with vstm/vldm when added.
maybe some build configuration needs changes? can you guess anything?

@ruben-ayrapetyan
Copy link
Contributor

@seanshpark, what compiler options do you use for the build? What is the error message?

I've successfully built the code, using arm-none-eabi-g++ v4.8.2 (arm-none-eabi-g++ -mlittle-endian -mthumb -mcpu=cortex-m4 -march=armv7e-m -mfpu=fpv4-sp-d16 -mfloat-abi=hard -c longjmp.s -o longjmp.o):

        .global setjmp
        .type setjmp, %function
        .syntax unified
        .thumb
        .thumb_func
setjmp:
        /* Save registers in jump buffer.  */
        stmia   r0!, {r4, r5, r6, r7}
        mov     r1, r8
        mov     r2, r9
        mov     r3, r10
        mov     r4, fp
        mov     r5, sp
        mov     r6, lr
        stmia   r0!, {r1, r2, r3, r4, r5, r6}
        vstm  r0!, {s16 - s31}
        sub   r0, r0, #104     // + 16 * 4 = 64 bytes
        /* Restore callee-saved low regs.  */
        ldmia   r0!, {r4, r5, r6, r7}
        /* Return zero.  */
        mov     r0, #0
        bx      lr
        .size setjmp, . - setjmp


        .global longjmp
        .type longjmp, %function
        .syntax unified
        .thumb
        .thumb_func
longjmp:
        /* Restore High regs.  */
        add     r0, r0, #16
        ldmia   r0!, {r2, r3, r4, r5, r6}
        mov     r8, r2
        mov     r9, r3
        mov     r10, r4
        mov     fp, r5
        mov     sp, r6
        ldmia   r0!, {r3} /* lr */
        /* Restore low regs.  */
        vldm  r0!, {s16 - s31}
        sub   r0, r0, #104
        ldmia   r0!, {r4, r5, r6, r7}
        /* Return the result argument, or 1 if it is zero.  */
        mov     r0, r1
        bne     1f
        mov     r0, #1
1:
        bx      r3
        .size longjmp, . - longjmp

@seanshpark
Copy link
Contributor Author

@ruben-ayrapetyan , thank you. I've changed something but still there is error running in nuttx + STM32F4Discovery+BB.

ICE: Assertion 'al != null_list' failed at /.../harmony/iotjs/deps/jerry/jerry-core/parser/js/collections/
array-list.cpp(extract_header):30.
Error: ERR_FAILED_INTERNAL_ASSERTION

compile msg:

AS:  stm32_jerry-hf.S
arm-none-eabi-g++ -c -fno-builtin -Wall -Wstrict-prototypes -Wshadow -Os -fno-strict-aliasing
-fno-strength-reduce -fomit-frame-pointer -mcpu=cortex-m4 -mthumb -march=armv7e-m 
-mfpu=fpv4-sp-d16 -mfloat-abi=hard -I. (and includes...)

changed: CC was used for AS so changed to use CXX, in nuttx/tools/Config.mk file

define ASSEMBLE
    @echo "AS: $1"
    $(Q) $(CXX) -c $(AFLAGS) $1 -o $2
    @echo "$(CXX) -c $(AFLAGS) $1 -o $2"
endef

BTW, can you please describe how's your build and test environment?

@ruben-ayrapetyan
Copy link
Contributor

@seanshpark, thank you for clarification of compiler options.

Could you, please, check size of jmp_buf buffer, used for storage of registers?

If jmp_buf size is enough for all registers, maybe, issue is not directly related to setjmp / longjmp. Could you, please, describe how to reproduce the failure? I'll try to figure out what is the cause.

BTW, can you please describe how's your build and test environment?

In pre-commit testing archive libraries are built, but linkage is not performed. So, pre-commit testing passes successfully.

@seanshpark
Copy link
Contributor Author

@ruben-ayrapetyan ,
I'm don't know how to measure jmp_buf. what I see from the source is

typedef uint64_t jmp_buf[12];

How to reproduce;

  1. get latest iot.js
  2. build for nuttx debug version, follow https://github.com/Samsung/iotjs/wiki/Build-for-NuttX
  3. edit nuttx/configs/stm32f4discovery/src/stm32_jerry-hf.S file so to enable vstm and vldm
  4. build nuttx, flash to STM board
  5. run any code, such as
console.log("hello world");

p.s. I've just deleted last message. how to reproduce was not correct.

@ruben-ayrapetyan
Copy link
Contributor

@seanshpark,
size of the typedef uint64_t jmp_buf[12]; buffer is 96 bytes that is not enough, because, actually, there are 10 * 4 + 16 * 4 = 104 bytes stored. Maybe, it is the cause of the issue.

@seanshpark
Copy link
Contributor Author

@ruben-ayrapetyan , I've changed it to typedef uint64_t jmp_buf[14]; and still same error.
but it was the sequence of push and pop. below code works.

        .global setjmp
        .type setjmp, %function
        .syntax unified
        .thumb
        .thumb_func
setjmp:
        /* Save registers in jump buffer.  */
        vstm    r0!, {s16 - s31}
        sub     r0, r0, #64     // + 16 * 4 = 64 bytes
        stmia   r0!, {r4, r5, r6, r7}
        mov     r1, r8
        mov     r2, r9
        mov     r3, r10
        mov     r4, fp
        mov     r5, sp
        mov     r6, lr
        stmia   r0!, {r1, r2, r3, r4, r5, r6}
        sub     r0, r0, #40
        /* Restore callee-saved low regs.  */
        ldmia   r0!, {r4, r5, r6, r7}
        /* Return zero.  */
        mov     r0, #0
        bx      lr
        .size setjmp, . - setjmp


        .global longjmp
        .type longjmp, %function
        .syntax unified
        .thumb
        .thumb_func
longjmp:
        /* Restore High regs.  */
        vldm    r0!, {s16 - s31}
        add     r0, r0, #16
        ldmia   r0!, {r2, r3, r4, r5, r6}
        mov     r8, r2
        mov     r9, r3
        mov     r10, r4
        mov     fp, r5
        mov     sp, r6
        ldmia   r0!, {r3} /* lr */
        /* Restore low regs.  */
        sub     r0, r0, #40
        ldmia   r0!, {r4, r5, r6, r7}
        vstm    r0!, {s16 - s31}
        sub     r0, r0, #64     // + 16 * 4 = 64 bytes
        /* Return the result argument, or 1 if it is zero.  */
        mov     r0, r1
        bne     1f
        mov     r0, #1
1:
        bx      r3
        .size longjmp, . - longjmp

the sequence in jerry-libc is opposite. have you checked with target board?
I'll make a small PR for [12] to [14].

seanshpark added a commit to seanshpark/jerryscript that referenced this issue Jul 2, 2015
Related issue : jerryscript-project#231

JerryScript-DCO-1.0-Signed-off-by: SaeHie Park [email protected]
@ruben-ayrapetyan
Copy link
Contributor

@ruben-ayrapetyan , I've changed it to typedef uint64_t jmp_buf[14]; and still same error.
but it was the sequence of push and pop. below code works.

@seanshpark, the jmp_buf should be defined in setjmp.h in nuttx/nuttx/include folder.

@ruben-ayrapetyan
Copy link
Contributor

Seems that code below writes {s16 - s31} and then overwrites them with {r4, r5, r6, r7}.
So, because of the changes, maybe it doesn't overflow jmp_buf, but maybe context wouldn't be restored successfully with the code:

     /* Save registers in jump buffer.  */
        vstm    r0!, {s16 - s31}
        sub     r0, r0, #64     // + 16 * 4 = 64 bytes
        stmia   r0!, {r4, r5, r6, r7}

@ruben-ayrapetyan
Copy link
Contributor

A test that leads to call of longjmp is a test that raises SyntaxError.

For example:

try
{
  eval ('var var;');
  assert (false);
}
catch (e)
{
 assert (e instanceof SyntaxError);
}

@seanshpark
Copy link
Contributor Author

@ruben-ayrapetyan
I fixed some mistake and the last code is

        .global setjmp
        .type setjmp, %function
        .syntax unified
        .thumb
        .thumb_func
setjmp:
        // Save registers in jump buffer.
        vstm    r0!, {s16 - s31}
        sub     r0, r0, #64     // + 16 * 4 = 64 bytes
        stmia   r0!, {r4, r5, r6, r7}
        mov     r1, r8
        mov     r2, r9
        mov     r3, r10
        mov     r4, fp
        mov     r5, sp
        mov     r6, lr
        stmia   r0!, {r1, r2, r3, r4, r5, r6}
        sub     r0, r0, #40
        // Restore callee-saved low regs.
        ldmia   r0!, {r4, r5, r6, r7}
        // Return zero.
        mov     r0, #0
        bx      lr
        .size setjmp, . - setjmp


        .global longjmp
        .type longjmp, %function
        .syntax unified
        .thumb
        .thumb_func
longjmp:
        // Restore High regs.
        add     r0, r0, #16
        ldmia   r0!, {r2, r3, r4, r5, r6}
        mov     r8, r2
        mov     r9, r3
        mov     r10, r4
        mov     fp, r5
        mov     sp, r6
        ldmia   r0!, {r3} // lr
        // Restore low regs.
        sub     r0, r0, #40
        ldmia   r0!, {r4, r5, r6, r7}
        vldm    r0!, {s16 - s31}
        sub     r0, r0, #64     // + 16 * 4 = 64 bytes
        // Return the result argument, or 1 if it is zero.
        mov     r0, r1
        bne     1f
        mov     r0, #1
1:
        bx      r3
        .size longjmp, . - longjmp

can you please fix the code so that it works ?

@ruben-ayrapetyan
Copy link
Contributor

can you please fix the code so that it works ?

@seanshpark, I would gladly do this, but before this I should finish some activities. I'll do this as soon as possible.

@ruben-ayrapetyan
Copy link
Contributor

@seanshpark, I think that code from #231 (comment) should work if buffer size is enough, but I haven't checked this on board yet. I'll do this as soon as possible.

@seanshpark
Copy link
Contributor Author

@ruben-ayrapetyan , thank you very much. I'll try with adding setjmp.h in nuttx include with the code above tomorrow morning.

@seanshpark
Copy link
Contributor Author

It works with #231 (comment) !

@ruben-ayrapetyan
Copy link
Contributor

@seanshpark, it's great!

seanshpark added a commit to seanshpark/jerryscript that referenced this issue Jul 3, 2015
Related issue : jerryscript-project#231

JerryScript-DCO-1.0-Signed-off-by: SaeHie Park [email protected]
seanshpark added a commit to seanshpark/jerryscript that referenced this issue Jul 3, 2015
Related issue : jerryscript-project#231

JerryScript-DCO-1.0-Signed-off-by: SaeHie Park [email protected]
@seanshpark
Copy link
Contributor Author

I think this issue can be closed cause changes are for nuttx and added to 20150706 patch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants