添加rtthread相关代码
This commit is contained in:
		
							
								
								
									
										11
									
								
								riscv/rtthread/components/lwp/arch/x86/i386/SConscript
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										11
									
								
								riscv/rtthread/components/lwp/arch/x86/i386/SConscript
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| # RT-Thread building script for component | ||||
|  | ||||
| from building import * | ||||
|  | ||||
| cwd     = GetCurrentDir() | ||||
| src     = Glob('*.c') + Glob('*.S') | ||||
| CPPPATH = [cwd] | ||||
|  | ||||
| group = DefineGroup('lwp-x86-i386', src, depend = ['RT_USING_SMART'], CPPPATH = CPPPATH) | ||||
|  | ||||
| Return('group') | ||||
							
								
								
									
										371
									
								
								riscv/rtthread/components/lwp/arch/x86/i386/lwp_arch.c
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										371
									
								
								riscv/rtthread/components/lwp/arch/x86/i386/lwp_arch.c
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,371 @@ | ||||
| /* | ||||
|  * Copyright (c) 2006-2021, RT-Thread Development Team | ||||
|  * | ||||
|  * SPDX-License-Identifier: Apache-2.0 | ||||
|  * | ||||
|  * Change Logs: | ||||
|  * Date           Author       Notes | ||||
|  * 2021-7-14      JasonHu      first version | ||||
|  */ | ||||
|  | ||||
| #include <rthw.h> | ||||
| #include <stddef.h> | ||||
| #include <rtconfig.h> | ||||
| #include <rtdbg.h> | ||||
|  | ||||
| #ifdef ARCH_MM_MMU | ||||
|  | ||||
| #include <stackframe.h> | ||||
| #include <interrupt.h> | ||||
| #include <segment.h> | ||||
|  | ||||
| #include <mmu.h> | ||||
| #include <page.h> | ||||
| #include <lwp_mm_area.h> | ||||
| #include <lwp_user_mm.h> | ||||
| #include <lwp_arch.h> | ||||
|  | ||||
| #ifdef RT_USING_SIGNALS | ||||
| #include <lwp_signal.h> | ||||
| #endif /* RT_USING_SIGNALS */ | ||||
|  | ||||
| extern size_t g_mmu_table[]; | ||||
|  | ||||
| int arch_expand_user_stack(void *addr) | ||||
| { | ||||
|     int ret = 0; | ||||
|     size_t stack_addr = (size_t)addr; | ||||
|  | ||||
|     stack_addr &= ~PAGE_OFFSET_MASK; | ||||
|     if ((stack_addr >= (size_t)USER_STACK_VSTART) && (stack_addr < (size_t)USER_STACK_VEND)) | ||||
|     { | ||||
|         void *map = lwp_map_user(lwp_self(), (void *)stack_addr, PAGE_SIZE, RT_FALSE); | ||||
|  | ||||
|         if (map || lwp_user_accessable(addr, 1)) | ||||
|         { | ||||
|             ret = 1;    /* map success */ | ||||
|         } | ||||
|         else /* map failed, send signal SIGSEGV */ | ||||
|         { | ||||
| #ifdef RT_USING_SIGNALS | ||||
|             dbg_log(DBG_ERROR, "[fault] thread %s mapped addr %p failed!\n", rt_thread_self()->parent.name, addr); | ||||
|             lwp_thread_kill(rt_thread_self(), SIGSEGV); | ||||
|             ret = 1;    /* return 1, will return back to intr, then check exit */ | ||||
| #endif | ||||
|         } | ||||
|     } | ||||
|     else    /* not stack, send signal SIGSEGV */ | ||||
|     { | ||||
| #ifdef RT_USING_SIGNALS | ||||
|         dbg_log(DBG_ERROR, "[fault] thread %s access unmapped addr %p!\n", rt_thread_self()->parent.name, addr); | ||||
|         lwp_thread_kill(rt_thread_self(), SIGSEGV); | ||||
|         ret = 1;    /* return 1, will return back to intr, then check exit */ | ||||
| #endif | ||||
|     } | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| void *get_thread_kernel_stack_top(rt_thread_t thread) | ||||
| { | ||||
|     return RT_NULL; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * don't support this in i386, it's ok! | ||||
|  */ | ||||
| void *arch_get_user_sp() | ||||
| { | ||||
|     return RT_NULL; | ||||
| } | ||||
|  | ||||
| int arch_user_space_init(struct rt_lwp *lwp) | ||||
| { | ||||
|     rt_size_t *mmu_table; | ||||
|  | ||||
|     mmu_table = (rt_size_t *)rt_pages_alloc_ext(0, PAGE_ANY_AVAILABLE); | ||||
|     if (!mmu_table) | ||||
|     { | ||||
|         return -1; | ||||
|     } | ||||
|     rt_memset(mmu_table, 0, ARCH_PAGE_SIZE); | ||||
|  | ||||
|     lwp->end_heap = USER_HEAP_VADDR; | ||||
|     memcpy(mmu_table, g_mmu_table, ARCH_PAGE_SIZE / 4); | ||||
|     memset((rt_uint8_t *)mmu_table + ARCH_PAGE_SIZE / 4, 0, ARCH_PAGE_SIZE / 4 * 3); | ||||
|     rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, mmu_table, ARCH_PAGE_SIZE); | ||||
|     if (rt_hw_mmu_map_init(&lwp->mmu_info, (void*)USER_VADDR_START, USER_VADDR_TOP - USER_VADDR_START, mmu_table, PV_OFFSET) < 0) | ||||
|     { | ||||
|         rt_pages_free(mmu_table, 0); | ||||
|         return -1; | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| void *arch_kernel_mmu_table_get(void) | ||||
| { | ||||
|     return (void *)((char *)g_mmu_table); | ||||
| } | ||||
|  | ||||
| void arch_user_space_vtable_free(struct rt_lwp *lwp) | ||||
| { | ||||
|     if (lwp && lwp->mmu_info.vtable) | ||||
|     { | ||||
|         rt_pages_free(lwp->mmu_info.vtable, 0); | ||||
|         lwp->mmu_info.vtable = NULL; | ||||
|     } | ||||
| } | ||||
|  | ||||
| void arch_set_thread_area(void *p) | ||||
| { | ||||
|     rt_hw_seg_tls_set((rt_ubase_t) p); | ||||
|     rt_thread_t cur = rt_thread_self(); | ||||
|     cur->thread_idr = p; /* update thread idr after first set */ | ||||
| } | ||||
|  | ||||
| void *arch_get_tidr(void) | ||||
| { | ||||
|     rt_thread_t cur = rt_thread_self(); | ||||
|     if (!cur->lwp)  /* no lwp, don't get thread idr from tls seg */ | ||||
|         return NULL; | ||||
|     return (void *)rt_hw_seg_tls_get();   /* get thread idr from tls seg */ | ||||
| } | ||||
|  | ||||
| void arch_set_tidr(void *p) | ||||
| { | ||||
|     rt_thread_t cur = rt_thread_self(); | ||||
|     if (!cur->lwp) /* no lwp, don't set thread idr to tls seg */ | ||||
|         return; | ||||
|     rt_hw_seg_tls_set((rt_ubase_t) p); /* set tls seg addr as thread idr */ | ||||
| } | ||||
|  | ||||
| static void lwp_user_stack_init(rt_hw_stack_frame_t *frame) | ||||
| { | ||||
|     frame->ds = frame->es = USER_DATA_SEL; | ||||
|     frame->cs = USER_CODE_SEL; | ||||
|     frame->ss = USER_STACK_SEL; | ||||
|     frame->gs = USER_TLS_SEL; | ||||
|     frame->fs = 0;  /* unused */ | ||||
|  | ||||
|     frame->edi = frame->esi = \ | ||||
|     frame->ebp = frame->esp_dummy = 0; | ||||
|     frame->eax = frame->ebx = \ | ||||
|     frame->ecx = frame->edx = 0; | ||||
|  | ||||
|     frame->error_code = 0; | ||||
|     frame->vec_no = 0; | ||||
|  | ||||
|     frame->eflags = (EFLAGS_MBS | EFLAGS_IF_1 | EFLAGS_IOPL_3); | ||||
| } | ||||
|  | ||||
| extern void lwp_switch_to_user(void *frame); | ||||
| /** | ||||
|  * user entry, set frame. | ||||
|  * at the end of execute, we need enter user mode, | ||||
|  * in x86, we can set stack, arg, text entry in a stack frame, | ||||
|  * then pop then into register, final use iret to switch kernel mode to user mode. | ||||
|  */ | ||||
| void arch_start_umode(void *args, const void *text, void *ustack, void *k_stack) | ||||
| { | ||||
|     rt_uint8_t *stk = k_stack; | ||||
|     stk -= sizeof(struct rt_hw_stack_frame); | ||||
|     struct rt_hw_stack_frame *frame = (struct rt_hw_stack_frame *)stk; | ||||
|  | ||||
|     lwp_user_stack_init(frame); | ||||
|     frame->esp = (rt_uint32_t)ustack - 32; | ||||
|     frame->ebx = (rt_uint32_t)args; | ||||
|     frame->eip = (rt_uint32_t)text; | ||||
|     lwp_switch_to_user(frame); | ||||
|     /* should never return */ | ||||
| } | ||||
|  | ||||
| void lwp_exec_user(void *args, void *kernel_stack, void *user_entry) | ||||
| { | ||||
|     arch_start_umode(args, (const void *)user_entry, (void *)USER_STACK_VEND, kernel_stack); | ||||
| } | ||||
|  | ||||
| extern void lwp_thread_return(); | ||||
| extern void lwp_thread_return_end(); | ||||
|  | ||||
| static void *lwp_copy_return_code_to_user_stack(void *ustack) | ||||
| { | ||||
|     size_t size = (size_t)lwp_thread_return_end - (size_t)lwp_thread_return; | ||||
|     void *retcode = (void *)((size_t)ustack - size); | ||||
|     memcpy(retcode, (void *)lwp_thread_return, size); | ||||
|     return retcode; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * when called sys_thread_create, need create a thread, after thread stared, will come here, | ||||
|  * like arch_start_umode, will enter user mode, but we must set thread exit function. it looks like: | ||||
|  * void func(void *arg) | ||||
|  * { | ||||
|  *      ... | ||||
|  * } | ||||
|  * when thread func return, we must call exit code to exit thread, or not the program runs away. | ||||
|  * so we need copy exit code to user and call exit code when func return. | ||||
|  */ | ||||
| void arch_crt_start_umode(void *args, const void *text, void *ustack, void *k_stack) | ||||
| { | ||||
|     RT_ASSERT(ustack != NULL); | ||||
|  | ||||
|     rt_uint8_t *stk; | ||||
|     stk  = (rt_uint8_t *)((rt_uint8_t *)k_stack + sizeof(rt_ubase_t)); | ||||
|     stk  = (rt_uint8_t *)RT_ALIGN_DOWN(((rt_ubase_t)stk), sizeof(rt_ubase_t)); | ||||
|     stk -= sizeof(struct rt_hw_stack_frame); | ||||
|     struct rt_hw_stack_frame *frame = (struct rt_hw_stack_frame *)stk; | ||||
|  | ||||
|     lwp_user_stack_init(frame); | ||||
|  | ||||
|     /* make user thread stack */ | ||||
|     unsigned long *retcode = lwp_copy_return_code_to_user_stack(ustack);    /* copy ret code */ | ||||
|     unsigned long *retstack = (unsigned long *)RT_ALIGN_DOWN(((rt_ubase_t)retcode), sizeof(rt_ubase_t)); | ||||
|  | ||||
|     /** | ||||
|      * x86 call stack | ||||
|      * | ||||
|      * retcode here | ||||
|      * | ||||
|      * arg n | ||||
|      * arg n - 1 | ||||
|      * ... | ||||
|      * arg 2 | ||||
|      * arg 1 | ||||
|      * arg 0 | ||||
|      * eip (caller return addr, point to retcode) | ||||
|      * esp | ||||
|      */ | ||||
|     *(--retstack) = (unsigned long) args;       /* arg */ | ||||
|     *(--retstack) = (unsigned long) retcode;    /* ret eip */ | ||||
|  | ||||
|     frame->esp = (rt_uint32_t)retstack; | ||||
|     frame->eip = (rt_uint32_t)text; | ||||
|     lwp_switch_to_user(frame); | ||||
|     /* should never return */ | ||||
| } | ||||
|  | ||||
| rt_thread_t rt_thread_sp_to_thread(void *spmember_addr) | ||||
| { | ||||
|     return (rt_thread_t)(((rt_ubase_t)spmember_addr) - (offsetof(struct rt_thread, sp))); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * set exec context for fork/clone. | ||||
|  * user_stack(unused) | ||||
|  */ | ||||
| void arch_set_thread_context(void *exit_addr, void *new_thread_stack, void *user_stack, void **thread_sp) | ||||
| { | ||||
|     /** | ||||
|      * thread kernel stack was set to tss.esp0, when intrrupt/syscall occur, | ||||
|      * the stack frame will store in kernel stack top, so we can get the stack | ||||
|      * frame by kernel stack top. | ||||
|      */ | ||||
|     rt_hw_stack_frame_t *frame = (rt_hw_stack_frame_t *)((rt_ubase_t)new_thread_stack - sizeof(rt_hw_stack_frame_t)); | ||||
|  | ||||
|     frame->eax = 0; /* child return 0 */ | ||||
|  | ||||
|     rt_hw_context_t *context = (rt_hw_context_t *) (((rt_uint32_t *)frame) - HW_CONTEXT_MEMBER_NR); | ||||
|     context->eip = (void *)exit_addr;    /* when thread started, jump to intr exit for enter user mode */ | ||||
|     context->ebp = context->ebx = context->esi = context->edi = 0; | ||||
|  | ||||
|     /** | ||||
|      * set sp as the address of first member of rt_hw_context, | ||||
|      * when scheduler call switch, pop stack from context stack. | ||||
|      */ | ||||
|     *thread_sp = (void *)&context->ebp; | ||||
|  | ||||
|     /** | ||||
|      * after set context, the stack like this: | ||||
|      * | ||||
|      * ----------- | ||||
|      * stack frame| eax = 0 | ||||
|      * ----------- | ||||
|      * context(only HW_CONTEXT_MEMBER_NR)| eip = rt_hw_intr_exit | ||||
|      * ----------- | ||||
|      * thread sp  | to <- rt_hw_context_switch(from, to) | ||||
|      * ----------- | ||||
|      */ | ||||
| } | ||||
|  | ||||
| #ifdef RT_USING_SIGNALS | ||||
|  | ||||
| #define SIGNAL_RET_CODE_SIZE    16 | ||||
|  | ||||
| struct rt_signal_frame | ||||
| { | ||||
|     char *ret_addr; /* return addr when handler return */ | ||||
|     int signo;   /* signal for user handler arg  */ | ||||
|     rt_hw_stack_frame_t frame; /* save kernel signal stack */ | ||||
|     char ret_code[SIGNAL_RET_CODE_SIZE];    /* save return code  */ | ||||
| }; | ||||
| typedef struct rt_signal_frame rt_signal_frame_t; | ||||
|  | ||||
| extern void lwp_signal_return(); | ||||
| extern void lwp_signal_return_end(); | ||||
|  | ||||
| void lwp_try_do_signal(rt_hw_stack_frame_t *frame) | ||||
| { | ||||
|     if (!lwp_signal_check()) | ||||
|         return; | ||||
|  | ||||
|     /* 1. backup signal mask */ | ||||
|     int signal = lwp_signal_backup((void *) frame->esp, (void *) frame->eip, (void *) frame->eflags); | ||||
|  | ||||
|     /* 2. get signal handler */ | ||||
|     lwp_sighandler_t handler = lwp_sighandler_get(signal); | ||||
|     if (handler == RT_NULL) /* no handler, ignore  */ | ||||
|     { | ||||
|         lwp_signal_restore(); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     rt_base_t level = rt_hw_interrupt_disable(); | ||||
|     /* 3. backup frame */ | ||||
|     rt_signal_frame_t *sig_frame = (rt_signal_frame_t *)((frame->esp - sizeof(rt_signal_frame_t)) & -8UL); | ||||
|     memcpy(&sig_frame->frame, frame, sizeof(rt_hw_stack_frame_t)); | ||||
|     sig_frame->signo = signal; | ||||
|  | ||||
|     /** | ||||
|      * 4. copy user return code into user stack | ||||
|      * | ||||
|      * save current frame on user stack. the user stack like: | ||||
|      * | ||||
|      * ---------- | ||||
|      * user code stack | ||||
|      * ----------+ -> esp before enter kernel | ||||
|      * signal frame | ||||
|      * ----------+ -> esp when handle signal handler | ||||
|      * signal handler stack | ||||
|      * ---------- | ||||
|      */ | ||||
|     size_t ret_code_size = (size_t)lwp_signal_return_end - (size_t)lwp_signal_return; | ||||
|     memcpy(sig_frame->ret_code, (void *)lwp_signal_return, ret_code_size); | ||||
|     sig_frame->ret_addr = sig_frame->ret_code; | ||||
|  | ||||
|     /* 5. jmp to user execute handler, update frame register info */ | ||||
|     lwp_user_stack_init(frame); | ||||
|     frame->eip = (rt_uint32_t) handler; | ||||
|     frame->esp = (rt_uint32_t) sig_frame; | ||||
|  | ||||
|     rt_hw_interrupt_enable(level); | ||||
| } | ||||
|  | ||||
| void lwp_signal_do_return(rt_hw_stack_frame_t *frame) | ||||
| { | ||||
|     /** | ||||
|      * ASSUME: in x86, each stack push and pop element is 4 byte. so STACK_ELEM_SIZE = sizeof(int) => 4. | ||||
|      * when signal handler return, the stack move to the buttom of signal frame. | ||||
|      * but return will pop eip from esp, then {esp += STACK_ELEM_SIZE}, thus {esp = (signal frame) + STACK_ELEM_SIZE}. | ||||
|      * so {(signal frame) = esp - STACK_ELEM_SIZE} | ||||
|      */ | ||||
|     rt_signal_frame_t *sig_frame = (rt_signal_frame_t *)(frame->esp - sizeof(rt_uint32_t)); | ||||
|     memcpy(frame, &sig_frame->frame, sizeof(rt_hw_stack_frame_t)); | ||||
|  | ||||
|     /** | ||||
|      * restore signal info, but don't use rt_user_context, | ||||
|      * we use sig_frame to restore stack frame | ||||
|      */ | ||||
|     lwp_signal_restore(); | ||||
| } | ||||
| #endif /* RT_USING_SIGNALS */ | ||||
|  | ||||
| #endif  /* ARCH_MM_MMU */ | ||||
							
								
								
									
										49
									
								
								riscv/rtthread/components/lwp/arch/x86/i386/lwp_arch.h
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										49
									
								
								riscv/rtthread/components/lwp/arch/x86/i386/lwp_arch.h
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| /* | ||||
|  * Copyright (c) 2006-2021, RT-Thread Development Team | ||||
|  * | ||||
|  * SPDX-License-Identifier: Apache-2.0 | ||||
|  * | ||||
|  * Change Logs: | ||||
|  * Date           Author       Notes | ||||
|  * 2021-07-18     JasonHu      first version | ||||
|  */ | ||||
|  | ||||
| #ifndef  LWP_ARCH_H__ | ||||
| #define  LWP_ARCH_H__ | ||||
|  | ||||
| #include <lwp.h> | ||||
| #include <lwp_arch_comm.h> | ||||
| #include <stackframe.h> | ||||
|  | ||||
| #ifdef ARCH_MM_MMU | ||||
| #define USER_VADDR_TOP    0xFFFFF000UL | ||||
| #define USER_HEAP_VEND    0xE0000000UL | ||||
| #define USER_HEAP_VADDR   0x90000000UL | ||||
| #define USER_STACK_VSTART 0x80000000UL | ||||
| #define USER_STACK_VEND   USER_HEAP_VADDR | ||||
| #define LDSO_LOAD_VADDR   0x70000000UL | ||||
| #define USER_VADDR_START  0x40000000UL | ||||
| #define USER_LOAD_VADDR   USER_VADDR_START | ||||
|  | ||||
| #define SIGNAL_RETURN_SYSCAL_ID    0xe000 | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| rt_thread_t rt_thread_sp_to_thread(void *spmember_addr); | ||||
|  | ||||
| void lwp_signal_do_return(rt_hw_stack_frame_t *frame); | ||||
|  | ||||
| rt_inline unsigned long rt_hw_ffz(unsigned long x) | ||||
| { | ||||
|     return __builtin_ffsl(~x) - 1; | ||||
| } | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif  /* ARCH_MM_MMU */ | ||||
|  | ||||
| #endif  /*LWP_ARCH_H__*/ | ||||
							
								
								
									
										73
									
								
								riscv/rtthread/components/lwp/arch/x86/i386/lwp_gcc.S
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										73
									
								
								riscv/rtthread/components/lwp/arch/x86/i386/lwp_gcc.S
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,73 @@ | ||||
| /* | ||||
|  * Copyright (c) 2006-2021, RT-Thread Development Team | ||||
|  * | ||||
|  * SPDX-License-Identifier: Apache-2.0 | ||||
|  * | ||||
|  * Change Logs: | ||||
|  * Date           Author       Notes | ||||
|  * 2021-7-14      JasonHu      first version | ||||
|  */ | ||||
|  | ||||
| #include "rtconfig.h" | ||||
|  | ||||
| .section      .text.lwp | ||||
|  | ||||
| /* | ||||
|  * void lwp_switch_to_user(frame); | ||||
|  */ | ||||
| .global lwp_switch_to_user | ||||
| lwp_switch_to_user: | ||||
|     movl 0x4(%esp), %esp | ||||
|     addl $4,%esp    // skip intr no | ||||
|     popal | ||||
|     popl %gs | ||||
|     popl %fs | ||||
|     popl %es | ||||
|     popl %ds | ||||
|     addl $4, %esp   // skip error_code | ||||
|     iret    // enter to user mode | ||||
|  | ||||
| .extern arch_syscall_exit | ||||
| .global sys_fork | ||||
| .global sys_vfork | ||||
| .global arch_fork_exit | ||||
| sys_fork: | ||||
| sys_vfork: | ||||
|     jmp _sys_fork | ||||
| arch_fork_exit: | ||||
|     jmp arch_syscall_exit | ||||
|  | ||||
| .global sys_clone | ||||
| .global arch_clone_exit | ||||
| sys_clone: | ||||
|     jmp _sys_clone | ||||
| arch_clone_exit: | ||||
|     jmp arch_syscall_exit | ||||
|  | ||||
| /** | ||||
|  * rt thread return code | ||||
|  */ | ||||
| .align 4 | ||||
| .global lwp_thread_return | ||||
| lwp_thread_return: | ||||
|     movl $1, %eax   // eax = 1, sys_exit | ||||
|     movl $0, %ebx | ||||
|     int $0x80 | ||||
| .align 4 | ||||
| .global lwp_thread_return_end | ||||
| lwp_thread_return_end: | ||||
|  | ||||
| #ifdef RT_USING_SIGNALS | ||||
| /** | ||||
|  * signal return code | ||||
|  */ | ||||
| .align 4 | ||||
| .global lwp_signal_return | ||||
| lwp_signal_return: | ||||
|     movl $0xe000, %eax // special syscall id for return code | ||||
|     int $0x80 | ||||
| .align 4 | ||||
| .global lwp_signal_return_end | ||||
| lwp_signal_return_end: | ||||
|  | ||||
| #endif /* RT_USING_SIGNALS */ | ||||
							
								
								
									
										41
									
								
								riscv/rtthread/components/lwp/arch/x86/i386/reloc.c
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										41
									
								
								riscv/rtthread/components/lwp/arch/x86/i386/reloc.c
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| /* | ||||
|  * Copyright (c) 2006-2021, RT-Thread Development Team | ||||
|  * | ||||
|  * SPDX-License-Identifier: Apache-2.0 | ||||
|  * | ||||
|  * Change Logs: | ||||
|  * Date           Author       Notes | ||||
|  * 2021-07-28     JasonHu      first version | ||||
|  */ | ||||
|  | ||||
| #include <rtthread.h> | ||||
| #include <stdint.h> | ||||
| #include <string.h> | ||||
| #include <elf.h> | ||||
| #ifdef ARCH_MM_MMU | ||||
| #include <mmu.h> | ||||
| #include <page.h> | ||||
| #endif | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
|     Elf32_Word st_name; | ||||
|     Elf32_Addr st_value; | ||||
|     Elf32_Word st_size; | ||||
|     unsigned char st_info; | ||||
|     unsigned char st_other; | ||||
|     Elf32_Half st_shndx; | ||||
| } Elf32_sym; | ||||
|  | ||||
| #ifdef ARCH_MM_MMU | ||||
| void arch_elf_reloc(rt_mmu_info *m_info, void *text_start, void *rel_dyn_start, size_t rel_dyn_size, void *got_start, size_t got_size, Elf32_sym *dynsym) | ||||
| { | ||||
|  | ||||
| } | ||||
| #else | ||||
|  | ||||
| void arch_elf_reloc(void *text_start, void *rel_dyn_start, size_t rel_dyn_size, void *got_start, size_t got_size, Elf32_sym *dynsym) | ||||
| { | ||||
|  | ||||
| } | ||||
| #endif | ||||
		Reference in New Issue
	
	Block a user