From 164ec56ef8edb68d282bf2a3e376a8ee6584ffa6 Mon Sep 17 00:00:00 2001 From: shaojinchun Date: Wed, 10 Mar 2021 11:08:21 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E7=BC=96=E8=AF=91=E8=84=9A=E6=9C=AC?= =?UTF-8?q?=E5=8A=A0=E4=B8=8A=E5=AF=B9RT=5FBACKTRACE=5FFUNCTION=5FNAME?= =?UTF-8?q?=E5=AE=8F=E7=9A=84=E5=88=A4=E6=96=AD=E4=BB=A5=E7=A1=AE=E5=AE=9A?= =?UTF-8?q?=E6=98=AF=E5=90=A6=E5=8A=A0-mpoke-function-name=E7=BC=96?= =?UTF-8?q?=E8=AF=91=E9=80=89=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/qemu-vexpress-a9/.config | 2 +- bsp/qemu-vexpress-a9/SConstruct | 16 +++++++++++++--- bsp/qemu-vexpress-a9/rtconfig.h | 1 - libcpu/Kconfig | 2 +- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/bsp/qemu-vexpress-a9/.config b/bsp/qemu-vexpress-a9/.config index 7ebab35cc1..bdf3d406e9 100644 --- a/bsp/qemu-vexpress-a9/.config +++ b/bsp/qemu-vexpress-a9/.config @@ -81,7 +81,7 @@ CONFIG_PV_OFFSET=0xa0000000 # CONFIG_RT_IOREMAP_LATE is not set CONFIG_ARCH_ARM_CORTEX_A=y CONFIG_ARCH_ARM_CORTEX_A9=y -CONFIG_RT_BACKTRACE_FUNCTION_NAME=y +# CONFIG_RT_BACKTRACE_FUNCTION_NAME is not set # # RT-Thread Components diff --git a/bsp/qemu-vexpress-a9/SConstruct b/bsp/qemu-vexpress-a9/SConstruct index e1bc58f2c0..bec21ef46e 100644 --- a/bsp/qemu-vexpress-a9/SConstruct +++ b/bsp/qemu-vexpress-a9/SConstruct @@ -1,6 +1,7 @@ import os import sys import rtconfig +import re if os.getenv('RTT_ROOT'): RTT_ROOT = os.getenv('RTT_ROOT') @@ -11,12 +12,21 @@ sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] from building import * TARGET = 'rtthread.' + rtconfig.TARGET_EXT +TRACE_CONFIG = "" + +content = "" +with open("rtconfig.h") as f: + for line in f.readlines(): + if line.find("RT_BACKTRACE_FUNCTION_NAME") != -1: + for token in line.split(" "): + if re.match(r'RT_BACKTRACE_FUNCTION_NAME$', token, flags=0): + TRACE_CONFIG = " -mpoke-function-name" DefaultEnvironment(tools=[]) env = Environment(tools = ['mingw'], - AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, - CC = rtconfig.CC, CFLAGS = rtconfig.CFLAGS, - CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS + TRACE_CONFIG, + CC = rtconfig.CC, CFLAGS = rtconfig.CFLAGS + TRACE_CONFIG, + CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS + TRACE_CONFIG, AR = rtconfig.AR, ARFLAGS = '-rc', LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) env.PrependENVPath('PATH', rtconfig.EXEC_PATH) diff --git a/bsp/qemu-vexpress-a9/rtconfig.h b/bsp/qemu-vexpress-a9/rtconfig.h index 5e10fe7d2a..bccb164ca9 100644 --- a/bsp/qemu-vexpress-a9/rtconfig.h +++ b/bsp/qemu-vexpress-a9/rtconfig.h @@ -59,7 +59,6 @@ #define PV_OFFSET 0xa0000000 #define ARCH_ARM_CORTEX_A #define ARCH_ARM_CORTEX_A9 -#define RT_BACKTRACE_FUNCTION_NAME /* RT-Thread Components */ diff --git a/libcpu/Kconfig b/libcpu/Kconfig index f339d63624..7bdd1446fa 100644 --- a/libcpu/Kconfig +++ b/libcpu/Kconfig @@ -104,7 +104,7 @@ config ARCH_ARM_CORTEX_A9 select ARCH_ARM_CORTEX_A config RT_BACKTRACE_FUNCTION_NAME - bool "To show function name when backtrace" + bool "To show function name when backtrace. Warning: Don't selet it when use fork/clone!" default n depends on ARCH_ARM_CORTEX_A -- Gitee From e33e50b10309a681c3a10c0b391f54d84da9f024 Mon Sep 17 00:00:00 2001 From: shaojinchun Date: Wed, 10 Mar 2021 13:36:35 +0800 Subject: [PATCH 2/3] add sys_execve support --- components/lwp/arch/arm/cortex-a/lwp_gcc.S | 18 +- components/lwp/lwp.c | 146 +++++----- components/lwp/lwp.h | 49 +++- components/lwp/lwp_pid.c | 124 ++++---- components/lwp/lwp_syscall.c | 312 ++++++++++++++++++--- components/lwp/lwp_tid.c | 7 +- components/lwp/lwp_user_mm.c | 46 +-- libcpu/arm/cortex-a/backtrace.c | 12 + 8 files changed, 524 insertions(+), 190 deletions(-) diff --git a/components/lwp/arch/arm/cortex-a/lwp_gcc.S b/components/lwp/arch/arm/cortex-a/lwp_gcc.S index f15b604c8e..ad2902fedf 100644 --- a/components/lwp/arch/arm/cortex-a/lwp_gcc.S +++ b/components/lwp/arch/arm/cortex-a/lwp_gcc.S @@ -98,6 +98,18 @@ lwp_get_user_sp: cps #Mode_SVC mov pc, lr +/* +void lwp_exec_user(void *args, void *kernel_stack, void *user_entry) +*/ +.global lwp_exec_user +lwp_exec_user: + mov sp, r1 + mov lr, r2 + mov r2, #Mode_USR + msr spsr_cxsf, r2 + ldr r3, =0x80000000 + b ret_to_user + /* * void SVC_Handler(void); */ @@ -107,10 +119,7 @@ vector_swi: push {lr} mrs lr, spsr push {r4, r5, lr} - tst lr, #(1 << 7) /* mask irq ? */ - bne 1f cpsie i -1: push {r0 - r3, r12} and r0, r7, #0xff cmp r0, #0xfe @@ -127,11 +136,8 @@ vector_swi: blx lr svc_exit: - mrs r4, cpsr cpsid i - tst r4, #(1 << 7) /* mask irq ? */ pop {r4, r5, lr} - orrne lr, #(1 << 7) msr spsr_cxsf, lr pop {lr} diff --git a/components/lwp/lwp.c b/components/lwp/lwp.c index 96de9795e6..f659c7d364 100644 --- a/components/lwp/lwp.c +++ b/components/lwp/lwp.c @@ -27,49 +27,6 @@ #define DBG_LVL DBG_WARNING #include -#define AUX_ARRAY_ITEMS_NR 6 - -/* aux key */ -#define AT_NULL 0 -#define AT_IGNORE 1 -#define AT_EXECFD 2 -#define AT_PHDR 3 -#define AT_PHENT 4 -#define AT_PHNUM 5 -#define AT_PAGESZ 6 -#define AT_BASE 7 -#define AT_FLAGS 8 -#define AT_ENTRY 9 -#define AT_NOTELF 10 -#define AT_UID 11 -#define AT_EUID 12 -#define AT_GID 13 -#define AT_EGID 14 -#define AT_CLKTCK 17 -#define AT_PLATFORM 15 -#define AT_HWCAP 16 -#define AT_FPUCW 18 -#define AT_DCACHEBSIZE 19 -#define AT_ICACHEBSIZE 20 -#define AT_UCACHEBSIZE 21 -#define AT_IGNOREPPC 22 -#define AT_SECURE 23 -#define AT_BASE_PLATFORM 24 -#define AT_RANDOM 25 -#define AT_HWCAP2 26 -#define AT_EXECFN 31 - -struct process_aux_item -{ - uint32_t key; - uint32_t value; -}; - -struct process_aux -{ - struct process_aux_item item[AUX_ARRAY_ITEMS_NR]; -}; - #ifdef RT_USING_USERSPACE #ifdef RT_USING_GDBSERVER #include @@ -109,7 +66,7 @@ uint32_t *lwp_get_kernel_sp(void) } #ifdef RT_USING_USERSPACE -static struct process_aux *lwp_argscopy(struct rt_lwp *lwp, int argc, char **argv, char **envp) +struct process_aux *lwp_argscopy(struct rt_lwp *lwp, int argc, char **argv, char **envp) { int size = sizeof(int) * 5; /* store argc, argv, envp, aux, NULL */ int *args; @@ -142,12 +99,16 @@ static struct process_aux *lwp_argscopy(struct rt_lwp *lwp, int argc, char **arg size += sizeof(struct process_aux); if (size > ARCH_PAGE_SIZE) + { return RT_NULL; + } /* args = (int *)lwp_map_user(lwp, 0, size); */ args = (int *)lwp_map_user(lwp, (void *)(KERNEL_VADDR_START - ARCH_PAGE_SIZE), size, 0); if (args == RT_NULL) + { return RT_NULL; + } args_k = (int *)rt_hw_mmu_v2p(&lwp->mmu_info, args); args_k = (int *)((size_t)args_k - PV_OFFSET); @@ -234,7 +195,9 @@ static struct process_aux *lwp_argscopy(struct rt_lwp *lwp, int argc, char **arg args = (int *)rt_malloc(size); if (args == RT_NULL) + { return RT_NULL; + } /* argc, argv[], 0, envp[], 0 */ str = (char *)((size_t)args + (argc + 2 + i + 1 + AUX_ARRAY_ITEMS_NR * 2 + 1) * sizeof(int)); @@ -355,6 +318,36 @@ void lwp_elf_reloc(rt_mmu_info *m_info, void *text_start, void *rel_dyn_start, s void lwp_elf_reloc(void *text_start, void *rel_dyn_start, size_t rel_dyn_size, void *got_start, size_t got_size, Elf_sym *dynsym); #endif +struct map_range +{ + void *start; + size_t size; +}; + +static void expand_map_range(struct map_range *m, void *start, size_t size) +{ + if (!m->start) + { + m->start = start; + m->size = size; + } + else + { + void *end = (void *)((char*)start + size); + void *mend = (void *)((char*)m->start + m->size); + + if (m->start > start) + { + m->start = start; + } + if (mend < end) + { + mend = end; + } + m->size = (char *)mend - (char *)m->start; + } +} + static int load_elf(int fd, int len, struct rt_lwp *lwp, uint8_t *load_addr, struct process_aux *aux) { uint32_t i; @@ -373,6 +366,8 @@ static int load_elf(int fd, int len, struct rt_lwp *lwp, uint8_t *load_addr, str size_t rel_dyn_size = 0; size_t dynsym_off = 0; size_t dynsym_size = 0; + struct map_range text_area = {NULL, 0}; + struct map_range data_area = {NULL, 0}; #ifdef RT_USING_USERSPACE void *pa, *va; #endif @@ -399,17 +394,17 @@ static int load_elf(int fd, int len, struct rt_lwp *lwp, uint8_t *load_addr, str read_len = load_fread(&eheader, 1, sizeof eheader, fd); check_read(read_len, sizeof eheader); - #ifndef ARCH_CPU_64BIT - if (eheader.e_ident[4] != 1) - { /* not 32bit */ - return -RT_ERROR; - } - #else - if (eheader.e_ident[4] != 2) - { /* not 64bit */ - return -RT_ERROR; - } - #endif +#ifndef ARCH_CPU_64BIT + if (eheader.e_ident[4] != 1) + { /* not 32bit */ + return -RT_ERROR; + } +#else + if (eheader.e_ident[4] != 2) + { /* not 64bit */ + return -RT_ERROR; + } +#endif if (eheader.e_ident[6] != 1) { /* ver not 1 */ @@ -483,9 +478,6 @@ static int load_elf(int fd, int len, struct rt_lwp *lwp, uint8_t *load_addr, str off = eheader.e_shoff; for (i = 0; i < eheader.e_shnum; i++, off += sizeof sheader) { - int need_map = 0; - int text = 0; - check_off(off, len); lseek(fd, off, SEEK_SET); read_len = load_fread(&sheader, 1, sizeof sheader, fd); @@ -499,25 +491,38 @@ static int load_elf(int fd, int len, struct rt_lwp *lwp, uint8_t *load_addr, str switch (sheader.sh_type) { case SHT_PROGBITS: - if ((sheader.sh_flags & SHF_EXECINSTR) != 0) + if ((sheader.sh_flags & SHF_WRITE) == 0) { - text = 1; + expand_map_range(&text_area, (void *)sheader.sh_addr, sheader.sh_size); } + else + { + expand_map_range(&data_area, (void *)sheader.sh_addr, sheader.sh_size); + } + break; case SHT_NOBITS: - need_map = 1; + expand_map_range(&data_area, (void *)sheader.sh_addr, sheader.sh_size); break; default: break; } - if (need_map) + } + if (text_area.start) + { + va = lwp_map_user(lwp, text_area.start, text_area.size, 1); + if (!va || (va != text_area.start)) { - /* map user */ - va = lwp_map_user(lwp, (void *)sheader.sh_addr, sheader.sh_size, text); - if (!va || (va != (void *)(size_t)sheader.sh_addr)) - { - result = -RT_ERROR; - goto _exit; - } + result = -RT_ERROR; + goto _exit; + } + } + if (data_area.start) + { + va = lwp_map_user(lwp, data_area.start, data_area.size, 0); + if (!va || (va != data_area.start)) + { + result = -RT_ERROR; + goto _exit; } } #endif @@ -733,7 +738,6 @@ _exit: if (result != RT_EOK) { LOG_E("lwp dynamic load faild, %d", result); - lwp_ref_dec(lwp); } return result; } @@ -896,7 +900,9 @@ pid_t lwp_execve(char *filename, int argc, char **argv, char **envp) int tid = 0; if (filename == RT_NULL) + { return -RT_ERROR; + } lwp = lwp_new(); diff --git a/components/lwp/lwp.h b/components/lwp/lwp.h index 481fb471eb..5f82b7a4c4 100644 --- a/components/lwp/lwp.h +++ b/components/lwp/lwp.h @@ -71,7 +71,7 @@ struct rt_lwp void *text_entry; uint32_t text_size; void *data_entry; - uint32_t *data_size; + uint32_t data_size; int ref; void *args; @@ -116,6 +116,10 @@ void lwp_set_thread_area(void *p); void* rt_cpu_get_thread_idr(void); void rt_cpu_set_thread_idr(void *p); +pid_t lwp_pid_get(void); +void lwp_pid_put(pid_t pid); +void lwp_pid_set_lwp(pid_t pid, struct rt_lwp *lwp); + int lwp_tid_get(void); void lwp_tid_put(int tid); rt_thread_t lwp_tid_get_thread(int tid); @@ -183,4 +187,47 @@ struct __pthread { } #endif +#define AUX_ARRAY_ITEMS_NR 6 + +/* aux key */ +#define AT_NULL 0 +#define AT_IGNORE 1 +#define AT_EXECFD 2 +#define AT_PHDR 3 +#define AT_PHENT 4 +#define AT_PHNUM 5 +#define AT_PAGESZ 6 +#define AT_BASE 7 +#define AT_FLAGS 8 +#define AT_ENTRY 9 +#define AT_NOTELF 10 +#define AT_UID 11 +#define AT_EUID 12 +#define AT_GID 13 +#define AT_EGID 14 +#define AT_CLKTCK 17 +#define AT_PLATFORM 15 +#define AT_HWCAP 16 +#define AT_FPUCW 18 +#define AT_DCACHEBSIZE 19 +#define AT_ICACHEBSIZE 20 +#define AT_UCACHEBSIZE 21 +#define AT_IGNOREPPC 22 +#define AT_SECURE 23 +#define AT_BASE_PLATFORM 24 +#define AT_RANDOM 25 +#define AT_HWCAP2 26 +#define AT_EXECFN 31 + +struct process_aux_item +{ + uint32_t key; + uint32_t value; +}; + +struct process_aux +{ + struct process_aux_item item[AUX_ARRAY_ITEMS_NR]; +}; + #endif diff --git a/components/lwp/lwp_pid.c b/components/lwp/lwp_pid.c index 5906b2461e..3c5d9b5a40 100644 --- a/components/lwp/lwp_pid.c +++ b/components/lwp/lwp_pid.c @@ -36,12 +36,55 @@ PID_CT_ASSERT(pid_max_nr, RT_LWP_MAX_NR > 1); -struct rt_pid_struct +static struct rt_lwp *lwp_pid_ary[RT_LWP_MAX_NR]; +static struct rt_lwp **lwp_pid_free_head = RT_NULL; +static pid_t lwp_pid_ary_alloced = 1; /* 0 is reserved */ + +pid_t lwp_pid_get(void) { - struct rt_lwp* pidmap[RT_LWP_MAX_NR]; - pid_t last_pid; -}; -static struct rt_pid_struct pid_struct = {{0}, 1}; + pid_t ret = 0; + rt_base_t level = rt_hw_interrupt_disable(); + struct rt_lwp **p = lwp_pid_free_head; + + if (p) + { + lwp_pid_free_head = (struct rt_lwp **)*p; + } + else if (lwp_pid_ary_alloced < RT_LWP_MAX_NR) + { + p = lwp_pid_ary + lwp_pid_ary_alloced; + lwp_pid_ary_alloced++; + } + if (p) + { + *p = RT_NULL; + ret = p - lwp_pid_ary; + } + rt_hw_interrupt_enable(level); + return ret; +} + +void lwp_pid_put(pid_t pid) +{ + struct rt_lwp **p = RT_NULL; + rt_base_t level = rt_hw_interrupt_disable(); + + if (pid > 0 && pid < RT_LWP_MAX_NR) + { + p = lwp_pid_ary + pid; + *p = (struct rt_lwp *)lwp_pid_free_head; + lwp_pid_free_head = p; + } + rt_hw_interrupt_enable(level); +} + +void lwp_pid_set_lwp(pid_t pid, struct rt_lwp *lwp) +{ + if (pid > 0 && pid < RT_LWP_MAX_NR) + { + lwp_pid_ary[pid] = lwp; + } +} int libc_stdio_get_console(void); @@ -65,47 +108,18 @@ static void __exit_files(struct rt_lwp *lwp) struct rt_lwp* lwp_new(void) { - uint32_t i; + pid_t pid; rt_base_t level; struct rt_lwp* lwp = RT_NULL; level = rt_hw_interrupt_disable(); - /* first scan */ - for (i = pid_struct.last_pid; i < RT_LWP_MAX_NR; i++) + pid = lwp_pid_get(); + if (pid == 0) { - if (!pid_struct.pidmap[i]) - { - break; - } - } - - /* if first scan failed, scan the pidmap start with 0 */ - if (i >= RT_LWP_MAX_NR) - { - /* 0 is reserved */ - for (i = 1; i < pid_struct.last_pid; i++) - { - if (!pid_struct.pidmap[i]) - { - break; - } - } - } - - if (i >= RT_LWP_MAX_NR) - { - /* if second scan also failed */ - LOG_W("pidmap fulled\n"); - pid_struct.last_pid = 0; + LOG_E("pid slot fulled!\n"); goto out; } - pid_struct.last_pid = (i + 1) % RT_LWP_MAX_NR; - if (pid_struct.last_pid == 0) - { - /* 0 is reserved */ - pid_struct.last_pid++; - } lwp = (struct rt_lwp *)rt_malloc(sizeof(struct rt_lwp)); if (lwp == RT_NULL) { @@ -114,8 +128,8 @@ struct rt_lwp* lwp_new(void) } rt_memset(lwp, 0, sizeof(*lwp)); rt_list_init(&lwp->wait_list); - lwp->pid = i; - pid_struct.pidmap[i] = lwp; + lwp->pid = pid; + lwp_pid_set_lwp(pid, lwp); rt_list_init(&lwp->t_grp); rt_list_init(&lwp->object_list); lwp->address_search_head = RT_NULL; @@ -127,7 +141,7 @@ out: return lwp; } -static void lwp_user_obj_free(struct rt_lwp *lwp) +void lwp_user_obj_free(struct rt_lwp *lwp) { rt_base_t level = 0; struct rt_list_node *list = RT_NULL, *node = RT_NULL; @@ -250,7 +264,7 @@ void lwp_free(struct rt_lwp* lwp) lwp->first_child = child->sibling; if (child->finish) { - pid_struct.pidmap[lwp_to_pid(child)] = RT_NULL; + lwp_pid_put(lwp_to_pid(child)); rt_free(child); } else @@ -283,7 +297,7 @@ void lwp_free(struct rt_lwp* lwp) } else { - pid_struct.pidmap[lwp_to_pid(lwp)] = RT_NULL; + lwp_pid_put(lwp_to_pid(lwp)); rt_free(lwp); } } @@ -333,21 +347,21 @@ struct rt_lwp* lwp_from_pid(pid_t pid) { return NULL; } - return pid_struct.pidmap[pid]; + return lwp_pid_ary[pid]; } pid_t lwp_to_pid(struct rt_lwp* lwp) { if (!lwp) { - return -1; + return 0; } return lwp->pid; } char* lwp_pid2name(int32_t pid) { - struct rt_lwp* lwp; + struct rt_lwp *lwp; char* process_name = RT_NULL; lwp = lwp_from_pid(pid); @@ -359,19 +373,19 @@ char* lwp_pid2name(int32_t pid) return process_name; } -int32_t lwp_name2pid(const char* name) +int32_t lwp_name2pid(const char *name) { - uint32_t pid; + pid_t pid; rt_thread_t main_thread; char* process_name = RT_NULL; - struct rt_lwp* lwp = RT_NULL; for (pid = 1; pid < RT_LWP_MAX_NR; pid++) { /* 0 is reserved */ - if (pid_struct.pidmap[pid]) + struct rt_lwp *lwp = lwp_pid_ary[pid]; + + if (lwp && (lwp < (struct rt_lwp *)&lwp_pid_ary[0] || lwp >= (struct rt_lwp *)&lwp_pid_ary[RT_LWP_MAX_NR])) { - lwp = pid_struct.pidmap[pid]; process_name = strrchr(lwp->cmd, '/'); process_name = process_name? process_name + 1: lwp->cmd; if (!rt_strncmp(name, process_name, RT_NAME_MAX)) @@ -450,7 +464,7 @@ pid_t waitpid(pid_t pid, int *status, int options) } (*lwp_node) = lwp->sibling; - pid_struct.pidmap[pid] = RT_NULL; + lwp_pid_put(pid); rt_free(lwp); } @@ -516,7 +530,6 @@ long list_process(void) int index; int maxlen; rt_ubase_t level; - struct rt_lwp* lwp = RT_NULL; struct rt_thread *thread; struct rt_list_node *node, *list; const char *item_title = "thread"; @@ -575,9 +588,10 @@ long list_process(void) for (index = 0; index < RT_LWP_MAX_NR; index++) { - if (pid_struct.pidmap[index]) + struct rt_lwp *lwp = lwp_pid_ary[index]; + + if (lwp && (lwp < (struct rt_lwp *)&lwp_pid_ary[0] || lwp >= (struct rt_lwp *)&lwp_pid_ary[RT_LWP_MAX_NR])) { - lwp = pid_struct.pidmap[index]; list = &lwp->t_grp; for (node = list->next; node != list; node = node->next) { diff --git a/components/lwp/lwp_syscall.c b/components/lwp/lwp_syscall.c index 6eb2dd4663..4c7feea27a 100644 --- a/components/lwp/lwp_syscall.c +++ b/components/lwp/lwp_syscall.c @@ -19,6 +19,7 @@ #include #ifdef RT_USING_USERSPACE #include +#include #endif #ifdef RT_USING_DFS @@ -413,7 +414,7 @@ ssize_t sys_read(int fd, void *buf, size_t nbyte) if (!lwp_user_accessable((void *)buf, nbyte)) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); return -1; } @@ -452,7 +453,7 @@ ssize_t sys_write(int fd, const void *buf, size_t nbyte) if (!lwp_user_accessable((void *)buf, nbyte)) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); return -1; } @@ -489,7 +490,7 @@ int sys_open(const char *name, int flag, ...) if (!lwp_user_accessable((void *)name, 1)) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); return -1; } @@ -644,7 +645,7 @@ int sys_poll(struct pollfd *fds, nfds_t nfds, int timeout) if (!lwp_user_accessable((void *)fds, nfds * sizeof *fds)) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); return -1; } @@ -701,7 +702,7 @@ int sys_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, s { if (!lwp_user_accessable((void *)readfds, sizeof *readfds)) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); goto quit; } kreadfds = (fd_set *)kmem_get(sizeof *kreadfds); @@ -716,7 +717,7 @@ int sys_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, s { if (!lwp_user_accessable((void *)writefds, sizeof *writefds)) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); goto quit; } kwritefds = (fd_set *)kmem_get(sizeof *kwritefds); @@ -731,7 +732,7 @@ int sys_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, s { if (!lwp_user_accessable((void *)exceptfds, sizeof *exceptfds)) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); goto quit; } kexceptfds = (fd_set *)kmem_get(sizeof *kexceptfds); @@ -784,7 +785,7 @@ int sys_unlink(const char *pathname) if (!lwp_user_accessable((void *)pathname, 1)) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); return -1; } @@ -824,7 +825,7 @@ int sys_nanosleep(const struct timespec *rqtp, struct timespec *rmtp) if (!lwp_user_accessable((void *)rqtp, sizeof *rqtp)) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); return -1; } @@ -837,7 +838,7 @@ int sys_nanosleep(const struct timespec *rqtp, struct timespec *rmtp) { if (!lwp_user_accessable((void *)rmtp, sizeof *rmtp)) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); return -1; } @@ -876,7 +877,7 @@ int sys_gettimeofday(struct timeval *tp, struct timezone *tzp) { if (!lwp_user_accessable((void *)tp, sizeof *tp)) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); return -1; } @@ -1261,7 +1262,7 @@ long sys_clone(void *arg[]) /* check args */ if (!lwp_user_accessable(arg, sizeof(void *[SYS_CLONE_ARGS_NR]))) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); return -1; } @@ -1281,7 +1282,7 @@ long sys_clone(void *arg[]) { if (!lwp_user_accessable(new_tid, sizeof(int))) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); return -1; } } @@ -1559,6 +1560,248 @@ fail: return -1; } +size_t lwp_user_strlen(const char *s, int *err) +{ + size_t len = 0; + + while (1) + { + if (!lwp_user_accessable((void *)(s + len), sizeof(char))) + { + if (err) + { + *err = 1; + } + return 0; + } + if (s[len] == '\0') + { + if (err) + { + *err = 0; + } + return len; + } + len++; + } +} + +struct process_aux *lwp_argscopy(struct rt_lwp *lwp, int argc, char **argv, char **envp); +int lwp_load(const char *filename, struct rt_lwp *lwp, uint8_t *load_addr, size_t addr_size, struct process_aux *aux); +void lwp_exec_user(void *args, void *kernel_stack, void *user_entry); +void lwp_user_obj_free(struct rt_lwp *lwp); + +#define _swap_lwp_data(lwp_used, lwp_new, type, member) \ + do {\ + type tmp;\ + tmp = lwp_used->member;\ + lwp_used->member = lwp_new->member;\ + lwp_new->member = tmp;\ + } while (0) + +int sys_execve(const char *path, char *const argv[], char *const envp[]) +{ + int ret = -1; + int argc = 0; + int envc = 0; + void *page = NULL; + int size = 0; + size_t len; + int access_err; + char **kargv; + char **kenvp; + char *p; + struct rt_lwp *new_lwp = NULL; + struct rt_lwp *lwp; + rt_base_t level; + int uni_thread; + rt_thread_t thread; + struct process_aux *aux; + int i; + + lwp = lwp_self(); + thread = rt_thread_self(); + uni_thread = 1; + level = rt_hw_interrupt_disable(); + if (lwp->t_grp.prev != &thread->sibling) + { + uni_thread = 0; + } + if (lwp->t_grp.next != &thread->sibling) + { + uni_thread = 0; + } + rt_hw_interrupt_enable(level); + if (!uni_thread) + { + rt_set_errno(EINVAL); + goto quit; + } + + if (argv) + { + while (1) + { + if (!lwp_user_accessable((void *)(argv + argc), sizeof(char *))) + { + rt_set_errno(EFAULT); + goto quit; + } + size += sizeof(char *); + if (!argv[argc]) + { + break; + } + len = lwp_user_strlen((const char *)argv[argc], &access_err); + if (access_err) + { + rt_set_errno(EFAULT); + goto quit; + } + size += len + 1; + argc++; + } + size += sizeof(char *); + } + if (envp) + { + while (1) + { + if (!lwp_user_accessable((void *)(envp + envc), sizeof(char *))) + { + rt_set_errno(EFAULT); + goto quit; + } + size += sizeof(char *); + if (!envp[envc]) + { + break; + } + len = lwp_user_strlen((const char *)envp[envc], &access_err); + if (access_err) + { + rt_set_errno(EFAULT); + goto quit; + } + size += len + 1; + envc++; + } + size += sizeof(char *); + } + if (size > ARCH_PAGE_SIZE) + { + rt_set_errno(EINVAL); + goto quit; + } + page = rt_pages_alloc(0); /* 1 page */ + if (!page) + { + rt_set_errno(ENOMEM); + goto quit; + } + + kargv = (char **)page; + kenvp = kargv + argc + 1; + p = (char *)(kenvp + envc + 1); + /* copy argv */ + if (argv) + { + for (i = 0; i < argc; i++) + { + if (argv[i]) + { + kargv[i] = p; + len = rt_strlen(argv[i]) + 1; + rt_memcpy(p, argv[i], len); + p += len; + } + } + kargv[i] = NULL; + } + /* copy envp */ + if (envp) + { + for (i = 0; i < envc; i++) + { + if (envp[i]) + { + kenvp[i] = p; + len = rt_strlen(envp[i]) + 1; + rt_memcpy(p, envp[i], len); + p += len; + } + } + kenvp[i] = NULL; + } + + /* alloc new lwp to operation */ + new_lwp = (struct rt_lwp *)rt_malloc(sizeof(struct rt_lwp)); + if (!new_lwp) + { + rt_set_errno(ENOMEM); + goto quit; + } + rt_memset(new_lwp, 0, sizeof(struct rt_lwp)); + new_lwp->ref = 1; + ret = arch_user_space_init(new_lwp); + if (ret != 0) + { + rt_set_errno(ENOMEM); + goto quit; + } + if ((aux = lwp_argscopy(new_lwp, argc, kargv, kenvp)) == NULL) + { + rt_set_errno(ENOMEM); + goto quit; + } + rt_pages_free(page, 0); + page = NULL; + + ret = lwp_load(path, new_lwp, RT_NULL, 0, aux); + if (ret == RT_EOK) + { + /* load ok, now swap the data of lwp and new_lwp */ + rt_hw_interrupt_disable(); + +#ifdef RT_USING_USERSPACE + _swap_lwp_data(lwp, new_lwp, rt_mmu_info, mmu_info); + _swap_lwp_data(lwp, new_lwp, struct lwp_avl_struct *, map_area); + _swap_lwp_data(lwp, new_lwp, size_t, end_heap); +#endif + _swap_lwp_data(lwp, new_lwp, uint8_t, lwp_type); + _swap_lwp_data(lwp, new_lwp, void *, text_entry); + _swap_lwp_data(lwp, new_lwp, uint32_t, text_size); + _swap_lwp_data(lwp, new_lwp, void *, data_entry); + _swap_lwp_data(lwp, new_lwp, uint32_t, data_size); + + _swap_lwp_data(lwp, new_lwp, void *, args); + + rt_memset(&lwp->signal_mask, 0, sizeof(lwp->signal_mask)); + rt_memset(&lwp->signal_mask_bak, 0, sizeof(lwp->signal_mask_bak)); + rt_memset(lwp->signal_handler, 0, sizeof(lwp->signal_handler)); + + /* to do: clsoe files with flag CLOEXEC */ + + lwp_mmu_switch(thread); + lwp_ref_dec(new_lwp); + lwp_exec_user(lwp->args, + thread->stack_addr + thread->stack_size, + lwp->text_entry); + /* never reach here, so rt_hw_interrupt_enable is not needed */ + } + rt_set_errno(EINVAL); +quit: + if (page) + { + rt_pages_free(page, 0); + } + if (new_lwp) + { + lwp_ref_dec(new_lwp); + } + return -1; +} + rt_err_t sys_thread_delete(rt_thread_t thread) { return rt_thread_delete(thread); @@ -1755,7 +1998,7 @@ int sys_accept(int socket, struct musl_sockaddr *addr, socklen_t *addrlen) { if (!lwp_user_accessable(addrlen, sizeof (socklen_t *))) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); return -1; } lwp_get_from_user(&uaddrlen, addrlen, sizeof (socklen_t *)); @@ -1767,7 +2010,7 @@ int sys_accept(int socket, struct musl_sockaddr *addr, socklen_t *addrlen) if (!lwp_user_accessable(addr, uaddrlen)) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); return -1; } } @@ -1797,7 +2040,7 @@ int sys_bind(int socket, const struct musl_sockaddr *name, socklen_t namelen) if (!lwp_user_accessable((void *)name, namelen)) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); return -1; } lwp_get_from_user(&kname, (void *)name, namelen); @@ -1822,7 +2065,7 @@ int sys_getpeername (int socket, struct musl_sockaddr *name, socklen_t *namelen) if (!lwp_user_accessable(namelen, sizeof (socklen_t *))) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); return -1; } lwp_get_from_user(&unamelen, namelen, sizeof (socklen_t *)); @@ -1834,7 +2077,7 @@ int sys_getpeername (int socket, struct musl_sockaddr *name, socklen_t *namelen) if (!lwp_user_accessable(name, unamelen)) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); return -1; } @@ -1865,7 +2108,7 @@ int sys_getsockname (int socket, struct musl_sockaddr *name, socklen_t *namelen) if (!lwp_user_accessable(namelen, sizeof (socklen_t *))) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); return -1; } lwp_get_from_user(&unamelen, namelen, sizeof (socklen_t *)); @@ -1877,7 +2120,7 @@ int sys_getsockname (int socket, struct musl_sockaddr *name, socklen_t *namelen) if (!lwp_user_accessable(name, unamelen)) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); return -1; } @@ -1915,7 +2158,7 @@ int sys_connect(int socket, const struct musl_sockaddr *name, socklen_t namelen) if (!lwp_user_accessable((void *)name, namelen)) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); return -1; } lwp_get_from_user(&kname, (void *)name, namelen); @@ -1982,7 +2225,7 @@ int sys_recvfrom(int socket, void *mem, size_t len, int flags, if (!lwp_user_accessable((void *)mem, len)) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); return -1; } @@ -2059,7 +2302,7 @@ int sys_sendto(int socket, const void *dataptr, size_t size, int flags, if (!lwp_user_accessable((void *)dataptr, size)) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); return -1; } @@ -2182,7 +2425,7 @@ int sys_sigaction(int sig, const struct sigaction *act, { if (!lwp_user_accessable((void *)oact, sigsetsize)) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); goto out; } pkoact = &koact; @@ -2191,7 +2434,7 @@ int sys_sigaction(int sig, const struct sigaction *act, { if (!lwp_user_accessable((void *)act, sigsetsize)) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); goto out; } kact.__sa_handler._sa_handler = act->sa_handler; @@ -2235,7 +2478,7 @@ int sys_sigprocmask(int how, const sigset_t *sigset, sigset_t *oset, size_t size { if (!lwp_user_accessable((void *)oset, size)) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); return ret; } poldset = &oldset; @@ -2244,7 +2487,7 @@ int sys_sigprocmask(int how, const sigset_t *sigset, sigset_t *oset, size_t size { if (!lwp_user_accessable((void *)sigset, size)) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); return ret; } lwp_get_from_user(&newset, (void *)sigset, size); @@ -2300,7 +2543,7 @@ int sys_thread_sigprocmask(int how, const lwp_sigset_t *sigset, lwp_sigset_t *os { if (!lwp_user_accessable((void *)oset, size)) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); return ret; } poldset = &oldset; @@ -2309,7 +2552,7 @@ int sys_thread_sigprocmask(int how, const lwp_sigset_t *sigset, lwp_sigset_t *os { if (!lwp_user_accessable((void *)sigset, size)) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); return ret; } lwp_get_from_user(&newset, (void *)sigset, sizeof(lwp_sigset_t)); @@ -2632,7 +2875,7 @@ int sys_access(const char *filename, int mode) if (!lwp_user_accessable((void *)filename, 1)) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); return -1; } @@ -2664,7 +2907,7 @@ int sys_pipe(int fd[2]) { if (!lwp_user_accessable((void *)fd, sizeof(int[2]))) { - rt_set_errno(EINVAL); + rt_set_errno(EFAULT); return -1; } return pipe(fd); @@ -2687,7 +2930,7 @@ int sys_clock_settime(clockid_t clk, const struct timespec *ts) if (!lwp_user_accessable((void *)ts, size)) { - return -EINVAL; + return -EFAULT; } kts = kmem_get(size); @@ -2725,7 +2968,7 @@ int sys_clock_gettime(clockid_t clk, struct timespec *ts) if (!lwp_user_accessable((void *)ts, size)) { - return -EINVAL; + return -EFAULT; } kts = kmem_get(size); @@ -2754,7 +2997,7 @@ int sys_clock_getres(clockid_t clk, struct timespec *ts) if (!lwp_user_accessable((void *)ts, size)) { - return -EINVAL; + return -EFAULT; } kts.tv_sec = 1; @@ -2932,6 +3175,7 @@ const static void* func_table[] = (void *)sys_dup2, (void *)sys_rename, /* 135 */ (void *)sys_fork, + (void *)sys_execve, }; const void *lwp_get_sys_api(rt_uint32_t number) diff --git a/components/lwp/lwp_tid.c b/components/lwp/lwp_tid.c index d0e273b677..73510a7a75 100644 --- a/components/lwp/lwp_tid.c +++ b/components/lwp/lwp_tid.c @@ -27,6 +27,11 @@ #define DBG_LVL DBG_INFO #include +#define TID_CT_ASSERT(name, x) \ + struct assert_##name {char ary[2 * (x) - 1];} + +TID_CT_ASSERT(tid_max_nr, LWP_TID_MAX_NR > 1); + static rt_thread_t lwp_tid_ary[LWP_TID_MAX_NR]; static rt_thread_t *lwp_tid_free_head = RT_NULL; static int lwp_tid_ary_alloced = 1; /* 0 is reserved */ @@ -39,7 +44,7 @@ int lwp_tid_get(void) if (p) { - lwp_tid_free_head = (rt_thread_t*)*p; + lwp_tid_free_head = (rt_thread_t *)*p; } else if (lwp_tid_ary_alloced < LWP_TID_MAX_NR) { diff --git a/components/lwp/lwp_user_mm.c b/components/lwp/lwp_user_mm.c index 8bc8522d2e..a46b65931c 100644 --- a/components/lwp/lwp_user_mm.c +++ b/components/lwp/lwp_user_mm.c @@ -136,12 +136,12 @@ void lwp_unmap_user_space(struct rt_lwp *lwp) unmap_range(lwp, (void *)ma->addr, ma->size, pa_need_free); lwp_map_area_remove(&lwp->map_area, ma->addr); } - - #ifdef ARCH_RISCV - rt_pages_free(m_info->vtable, 0); - #else - rt_pages_free(m_info->vtable, 2); - #endif + +#ifdef ARCH_RISCV + rt_pages_free(m_info->vtable, 0); +#else + rt_pages_free(m_info->vtable, 2); +#endif } static void *_lwp_map_user(struct rt_lwp *lwp, void *map_va, size_t map_size, int text) @@ -434,21 +434,21 @@ size_t lwp_get_from_user(void *dst, void *src, size_t size) rt_mmu_info *m_info = RT_NULL; /* check src */ - #ifdef ARCH_RISCV64 - if(src < (void *)USER_VADDR_START) - { - return 0; - } - #else - if (src >= (void*)KERNEL_VADDR_START) - { - return 0; - } - if ((void*)((char*)src + size) > (void*)KERNEL_VADDR_START) - { - return 0; - } - #endif +#ifdef ARCH_RISCV64 + if(src < (void *)USER_VADDR_START) + { + return 0; + } +#else + if (src >= (void *)KERNEL_VADDR_START) + { + return 0; + } + if ((void *)((char *)src + size) > (void *)KERNEL_VADDR_START) + { + return 0; + } +#endif lwp = lwp_self(); if (!lwp) @@ -500,7 +500,7 @@ int lwp_user_accessable(void *addr, size_t size) return 0; } addr_start = addr; - addr_end = (void*)((char*)addr + size); + addr_end = (void *)((char *)addr + size); #ifdef ARCH_RISCV64 if(addr_start < (void *)USER_VADDR_START) @@ -508,7 +508,7 @@ int lwp_user_accessable(void *addr, size_t size) return 0; } #else - if (addr_start >= (void*)KERNEL_VADDR_START) + if (addr_start >= (void *)KERNEL_VADDR_START) { return 0; } diff --git a/libcpu/arm/cortex-a/backtrace.c b/libcpu/arm/cortex-a/backtrace.c index 695e31ca5a..1d4d444aa9 100644 --- a/libcpu/arm/cortex-a/backtrace.c +++ b/libcpu/arm/cortex-a/backtrace.c @@ -17,6 +17,12 @@ #define DBG_LVL DBG_INFO #include +#ifdef RT_USING_USERSPACE +#include +#include +#include +#endif + rt_inline void arm_get_current_stackframe(struct pt_regs *regs, struct stackframe *frame) { frame->fp = frame_pointer(regs); @@ -516,6 +522,12 @@ void rt_unwind(struct rt_hw_exp_stack *regs, unsigned int pc_adj) e_regs.ARM_sp = regs->sp; e_regs.ARM_lr = regs->lr; e_regs.ARM_pc = regs->pc - pc_adj; +#ifdef RT_USING_USERSPACE + if (!lwp_user_accessable((void *)e_regs.ARM_pc, sizeof (void *))) + { + e_regs.ARM_pc = regs->lr - sizeof(void *); + } +#endif rt_kprintf("backtrace:\n"); unwind_backtrace(&e_regs, __exidx_start, __exidx_end); } -- Gitee From 1a1abd486a2a0507546dc5d971c244682ba54128 Mon Sep 17 00:00:00 2001 From: shaojinchun Date: Thu, 11 Mar 2021 14:22:33 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E8=A7=A3=E5=86=B3fork=E5=92=8Cclone?= =?UTF-8?q?=E6=97=B6=E7=94=B1=E4=BA=8E=E5=BC=80=E5=90=AFRT=5FBACKTRACE=5FF?= =?UTF-8?q?UNCTION=5FNAME=E5=90=8E=EF=BC=8C=E6=96=B0=E7=BA=BF=E7=A8=8B?= =?UTF-8?q?=E7=9A=84=E6=A0=88=E6=8C=87=E9=92=88=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/qemu-vexpress-a9/.config | 2 +- bsp/qemu-vexpress-a9/rtconfig.h | 1 + components/lwp/arch/arm/cortex-a/lwp_gcc.S | 55 +++++++++++++--------- components/lwp/lwp.c | 4 +- components/lwp/lwp_syscall.c | 52 ++++++++++---------- libcpu/Kconfig | 2 +- 6 files changed, 64 insertions(+), 52 deletions(-) diff --git a/bsp/qemu-vexpress-a9/.config b/bsp/qemu-vexpress-a9/.config index bdf3d406e9..7ebab35cc1 100644 --- a/bsp/qemu-vexpress-a9/.config +++ b/bsp/qemu-vexpress-a9/.config @@ -81,7 +81,7 @@ CONFIG_PV_OFFSET=0xa0000000 # CONFIG_RT_IOREMAP_LATE is not set CONFIG_ARCH_ARM_CORTEX_A=y CONFIG_ARCH_ARM_CORTEX_A9=y -# CONFIG_RT_BACKTRACE_FUNCTION_NAME is not set +CONFIG_RT_BACKTRACE_FUNCTION_NAME=y # # RT-Thread Components diff --git a/bsp/qemu-vexpress-a9/rtconfig.h b/bsp/qemu-vexpress-a9/rtconfig.h index bccb164ca9..5e10fe7d2a 100644 --- a/bsp/qemu-vexpress-a9/rtconfig.h +++ b/bsp/qemu-vexpress-a9/rtconfig.h @@ -59,6 +59,7 @@ #define PV_OFFSET 0xa0000000 #define ARCH_ARM_CORTEX_A #define ARCH_ARM_CORTEX_A9 +#define RT_BACKTRACE_FUNCTION_NAME /* RT-Thread Components */ diff --git a/components/lwp/arch/arm/cortex-a/lwp_gcc.S b/components/lwp/arch/arm/cortex-a/lwp_gcc.S index ad2902fedf..ee91466ef9 100644 --- a/components/lwp/arch/arm/cortex-a/lwp_gcc.S +++ b/components/lwp/arch/arm/cortex-a/lwp_gcc.S @@ -29,7 +29,7 @@ .text /* - * void lwp_user_entry(args, text, data); + * void lwp_user_entry(args, text, data, kstack); */ .global lwp_user_entry .type lwp_user_entry, % function @@ -39,6 +39,7 @@ lwp_user_entry: orr r9, #Mode_USR cpsid i msr spsr, r9 + mov sp, r3 ldr r3, =0x80000000 ;/* user stack top */ /* set data address. */ @@ -63,32 +64,26 @@ set_user_context: mov pc, lr /* -int lwp_set_thread_context(void *new_thread_stack, void *origin_thread_stack, void *user_stack, void **thread_sp, int tid); +void lwp_set_thread_context(void *exit_addr, void *new_thread_stack, void *user_stack, void **thread_sp); */ .global lwp_set_thread_context lwp_set_thread_context: - sub r12, r1, sp /* origin, r12 = origin sp offset */ - sub r0, r0, r12 /* new sp */ - stmfd r0!, {lr} - stmfd r0!, {lr} - stmfd r0!, {r12} - sub r12, sp, fp /* new, r1 = origin fp offset */ - sub r1, r0, r12 - add r1, #12 /* new fp */ - stmfd r0!, {r1} /* fp */ - stmfd r0!, {r1 - r10} + sub r1, #(10 * 4 + 4 * 4) /* {r4 - r12, lr} , {r4, r5, spsr, u_pc} */ + stmfd r1!, {r0} mov r12, #0 - stmfd r0!, {r12} /* new thread return value */ - mrs r1, cpsr - stmfd r0!, {r1} /* spsr */ - mov r1, #0 - stmfd r0!, {r1} /* now user lr is 0 */ - stmfd r0!, {r2} /* user sp */ + stmfd r1!, {r12} + stmfd r1!, {r1 - r12} + stmfd r1!, {r12} /* new thread return value */ + mrs r12, cpsr + orr r12, #(1 << 7) /* disable irq */ + stmfd r1!, {r12} /* spsr */ + mov r12, #0 + stmfd r1!, {r12} /* now user lr is 0 */ + stmfd r1!, {r2} /* user sp */ #ifdef RT_USING_FPU - stmfd r0!, {r1} /* not use fpu */ + stmfd r1!, {r12} /* not use fpu */ #endif - str r0, [r3] - ldr r0, [sp] + str r1, [r3] mov pc, lr .global lwp_get_user_sp @@ -98,11 +93,29 @@ lwp_get_user_sp: cps #Mode_SVC mov pc, lr +.global sys_fork +.global sys_fork_exit +sys_fork: + push {r4 - r12, lr} + bl _sys_fork +sys_fork_exit: + pop {r4 - r12, lr} + b svc_exit + +.global sys_clone +.global sys_clone_exit +sys_clone: + push {r4 - r12, lr} + bl _sys_clone +sys_clone_exit: + pop {r4 - r12, lr} + b svc_exit /* void lwp_exec_user(void *args, void *kernel_stack, void *user_entry) */ .global lwp_exec_user lwp_exec_user: + cpsid i mov sp, r1 mov lr, r2 mov r2, #Mode_USR diff --git a/components/lwp/lwp.c b/components/lwp/lwp.c index f659c7d364..48a820dc99 100644 --- a/components/lwp/lwp.c +++ b/components/lwp/lwp.c @@ -45,7 +45,7 @@ static const char elf_magic[] = {0x7f, 'E', 'L', 'F'}; -extern void lwp_user_entry(void *args, const void *text, void *data, void *user_stack); +extern void lwp_user_entry(void *args, const void *text, void *data, void *k_stack); extern int libc_stdio_get_console(void); /** @@ -868,7 +868,7 @@ static void lwp_thread_entry(void *parameter) } #endif - lwp_user_entry(lwp->args, lwp->text_entry, lwp->data_entry, RT_NULL); + lwp_user_entry(lwp->args, lwp->text_entry, lwp->data_entry, tid->stack_addr + tid->stack_size); } struct rt_lwp *lwp_self(void) diff --git a/components/lwp/lwp_syscall.c b/components/lwp/lwp_syscall.c index 4c7feea27a..14ea2b1c99 100644 --- a/components/lwp/lwp_syscall.c +++ b/components/lwp/lwp_syscall.c @@ -1239,9 +1239,12 @@ fail: * start_args * */ #define SYS_CLONE_ARGS_NR 7 -int lwp_set_thread_context(void *new_thread_stack, void *origin_thread_stack, - void *user_stack, void **thread_sp, int tid); -long sys_clone(void *arg[]) +int lwp_set_thread_context(void (*exit)(void), void *new_thread_stack, + void *user_stack, void **thread_sp); + +long sys_clone(void *arg[]); +void sys_clone_exit(void); +long _sys_clone(void *arg[]) { rt_base_t level = 0; struct rt_lwp *lwp = 0; @@ -1336,16 +1339,14 @@ long sys_clone(void *arg[]) rt_hw_interrupt_enable(level); /* copy origin stack */ - rt_memcpy(thread->stack_addr, self->stack_addr, ALLOC_KERNEL_STACK_SIZE); + rt_memcpy(thread->stack_addr, self->stack_addr, thread->stack_size); lwp_tid_set_thread(tid, thread); - tid = lwp_set_thread_context((void *)((char *)thread->stack_addr + ALLOC_KERNEL_STACK_SIZE), - (void *)((char *)self->stack_addr + ALLOC_KERNEL_STACK_SIZE), user_stack, &thread->sp, tid); - if (tid) - { - rt_thread_startup(thread); - } + lwp_set_thread_context(sys_clone_exit, + (void *)((char *)thread->stack_addr + thread->stack_size), + user_stack, &thread->sp); + /* new thread never reach there */ + rt_thread_startup(thread); return (long)tid; - fail: lwp_tid_put(tid); if (lwp) @@ -1434,7 +1435,9 @@ static int lwp_copy_files(struct rt_lwp *dst, struct rt_lwp *src) return -1; } -int sys_fork(void) +int sys_fork(void); +void sys_fork_exit(void); +int _sys_fork(void) { rt_base_t level; int tid = 0; @@ -1531,23 +1534,18 @@ int sys_fork(void) user_stack = lwp_get_user_sp(); rt_hw_interrupt_enable(level); - tid = lwp_set_thread_context((void *)((char *)thread->stack_addr + thread->stack_size), - (void *)((char *)self_thread->stack_addr + self_thread->stack_size), user_stack, &thread->sp, tid); - if (tid) - { - level = rt_hw_interrupt_disable(); - if (rt_console_get_foreground() == self_lwp) - { - rt_console_set_foreground(lwp); - } - rt_hw_interrupt_enable(level); - rt_thread_startup(thread); - return lwp_to_pid(lwp); - } - else + lwp_set_thread_context(sys_fork_exit, + (void *)((char *)thread->stack_addr + thread->stack_size), + user_stack, &thread->sp); + /* new thread never reach there */ + level = rt_hw_interrupt_disable(); + if (rt_console_get_foreground() == self_lwp) { - return 0; + rt_console_set_foreground(lwp); } + rt_hw_interrupt_enable(level); + rt_thread_startup(thread); + return lwp_to_pid(lwp); fail: if (tid != 0) { diff --git a/libcpu/Kconfig b/libcpu/Kconfig index 7bdd1446fa..93a534a57d 100644 --- a/libcpu/Kconfig +++ b/libcpu/Kconfig @@ -104,7 +104,7 @@ config ARCH_ARM_CORTEX_A9 select ARCH_ARM_CORTEX_A config RT_BACKTRACE_FUNCTION_NAME - bool "To show function name when backtrace. Warning: Don't selet it when use fork/clone!" + bool "To show function name when backtrace." default n depends on ARCH_ARM_CORTEX_A -- Gitee