From 1db69b153ea08f982a37df07eb83ad9c5efd97de Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 7 Nov 2014 16:47:49 +0800 Subject: [PATCH] update the research of arm --- trunk/research/arm/jmp.cpp | 34 +++++------ trunk/research/arm/jmp_sp.cpp | 111 ++++++++++++++++++++++++++++------ 2 files changed, 111 insertions(+), 34 deletions(-) diff --git a/trunk/research/arm/jmp.cpp b/trunk/research/arm/jmp.cpp index d9469405d..7f6606cd4 100644 --- a/trunk/research/arm/jmp.cpp +++ b/trunk/research/arm/jmp.cpp @@ -1,48 +1,48 @@ /* # see: https://github.com/winlinvip/simple-rtmp-server/wiki/v1_CN_SrsLinuxArm - arm-linux-gnueabi-g++ -o jmp jmp.cpp -static - arm-linux-gnueabi-strip jmp + g++ -g -O0 -o jmp jmp.cpp + arm-linux-gnueabi-g++ -o jmp jmp.cpp -static + arm-linux-gnueabi-strip jmp */ #include #include +#include #include +bool func1_ok = false, func2_ok = false; jmp_buf env_func1, env_func2; int sum = 0; void func1() { int ret = setjmp(env_func1); - printf("setjmp func1 ret=%d\n", ret); + printf("[func1] setjmp ret=%d, sum++=%d\n", ret, sum++); + func1_ok = true; - if (sum <= 0) { - return; - } - - if (sum++ > 1000) { - return; - } + sleep(1); // jmp to func2 - longjmp(env_func2, 3); + if (func2_ok) { + longjmp(env_func2, 1); + } } void func2() { int ret = setjmp(env_func2); - printf("setjmp func2 ret=%d\n", ret); + printf("[func2] setjmp ret=%d, sum++=%d\n", ret, sum++); + func2_ok = true; - if (sum <= 0) { - return; - } + sleep(1); // jmp to func1 - longjmp(env_func1, 2); + if (func1_ok) { + longjmp(env_func1, 2); + } } int main(int argc, char** argv) { printf("hello, setjmp/longjmp!\n"); func1(); - sum++; func2(); printf("jmp finished, sum=%d\n", sum); return 0; diff --git a/trunk/research/arm/jmp_sp.cpp b/trunk/research/arm/jmp_sp.cpp index 1fb0be89d..b39695c2f 100644 --- a/trunk/research/arm/jmp_sp.cpp +++ b/trunk/research/arm/jmp_sp.cpp @@ -1,39 +1,116 @@ /* # see: https://github.com/winlinvip/simple-rtmp-server/wiki/v1_CN_SrsLinuxArm - arm-linux-gnueabi-g++ -g -o jmp_sp jmp_sp.cpp -static - arm-linux-gnueabi-strip jmp_sp + g++ -g -O0 -o jmp_sp jmp_sp.cpp + arm-linux-gnueabi-g++ -g -o jmp_sp jmp_sp.cpp -static + arm-linux-gnueabi-strip jmp_sp */ #include #include #include -int main(int argc, char** argv) { +jmp_buf env_func1; + +void func1() +{ #if defined(__amd64__) || defined(__x86_64__) - printf("x86_64 sizeof(long int)=%d, sizeof(long)=%d, sizeof(int)=%d\n", (int)sizeof(long int), (int)sizeof(long), (int)sizeof(int)); -#else - printf("arm sizeof(long int)=%d, sizeof(long)=%d, sizeof(int)=%d\n", (int)sizeof(long int), (int)sizeof(long), (int)sizeof(int)); + register long int rsp0 asm("rsp"); + printf("in func1, rsp=%#lx, longjmp to func0\n", rsp0); + + longjmp(env_func1, 0x101); + + printf("func1 terminated\n"); #endif - - jmp_buf env; - - int ret = setjmp(env); - printf("setjmp func1 ret=%d\n", ret); - +} + +void func0(int* pv0, int* pv1) +{ + /** + the definition of jmp_buf: + typedef struct __jmp_buf_tag jmp_buf[1]; + struct __jmp_buf_tag { + __jmp_buf __jmpbuf; + int __mask_was_saved; + __sigset_t __saved_mask; + }; + */ #if defined(__amd64__) || defined(__x86_64__) - // typedef lint64_t __jmp_buf[8]; + /** + here, the __jmp_buf is 8*8=64 bytes + # if __WORDSIZE == 64 + typedef long int __jmp_buf[8]; + */ + /** + the layout for setjmp of x86_64 + # + # The jmp_buf is assumed to contain the following, in order: + # %rbx + # %rsp (post-return) + # %rbp + # %r12 + # %r13 + # %r14 + # %r15 + # + # + */ + register long int rsp0 asm("rsp"); + + int ret = setjmp(env_func1); + printf("setjmp func0 ret=%d, rsp=%#lx\n", ret, rsp0); + printf("after setjmp: "); for (int i = 0; i < 8; i++) { - printf("env[%d]=%#x, ", i, (int)env[0].__jmpbuf[i]); + printf("env[%d]=%#x, ", i, (int)env_func1[0].__jmpbuf[i]); } printf("\n"); #else - // typedef int32_t __jmp_buf[64] __attribute__((__aligned__ (8))); + /** + /usr/arm-linux-gnueabi/include/bits/setjmp.h + #ifndef _ASM + The exact set of registers saved may depend on the particular core + in use, as some coprocessor registers may need to be saved. The C + Library ABI requires that the buffer be 8-byte aligned, and + recommends that the buffer contain 64 words. The first 28 words + are occupied by v1-v6, sl, fp, sp, pc, d8-d15, and fpscr. (Note + that d8-15 require 17 words, due to the use of fstmx.) + typedef int __jmp_buf[64] __attribute__((__aligned__ (8))); + + the layout of setjmp for arm: + 0-5: v1-v6 + 6: sl + 7: fp + 8: sp + 9: pc + 10-26: d8-d15 17words + 27: fpscr + */ + int ret = setjmp(env_func1); + printf("setjmp func1 ret=%d\n", ret); + printf("after setjmp: "); for (int i = 0; i < 64; i++) { - printf("env[%d]=%#x, ", i, (int)env[0].__jmpbuf[i]); + printf("env[%d]=%#x, ", i, (int)env_func1[0].__jmpbuf[i]); } - printf("\n"); + + printf("func0 terminated\n"); #endif +} + +int main(int argc, char** argv) { +#if defined(__amd64__) || defined(__x86_64__) + printf("x86_64 sizeof(long int)=%d, sizeof(long)=%d, sizeof(int)=%d, __WORDSIZE=%d\n", + (int)sizeof(long int), (int)sizeof(long), (int)sizeof(int), (int)__WORDSIZE); +#else + printf("arm sizeof(long int)=%d, sizeof(long)=%d, sizeof(int)=%d\n", + (int)sizeof(long int), (int)sizeof(long), (int)sizeof(int)); +#endif + + int pv0 = 0xf0; + int pv1 = 0xf1; + func0(&pv0, &pv1); + func1(); + + printf("terminated\n"); return 0; }