1*10465441SEvalZero /*
2*10465441SEvalZero * Copyright (c) 2006-2018, RT-Thread Development Team
3*10465441SEvalZero *
4*10465441SEvalZero * SPDX-License-Identifier: Apache-2.0
5*10465441SEvalZero *
6*10465441SEvalZero * Change Logs:
7*10465441SEvalZero * Date Author Notes
8*10465441SEvalZero * 2018/08/29 Bernard first version
9*10465441SEvalZero */
10*10465441SEvalZero
11*10465441SEvalZero #include <rthw.h>
12*10465441SEvalZero
13*10465441SEvalZero #include "dlfcn.h"
14*10465441SEvalZero #include "dlmodule.h"
15*10465441SEvalZero #include "dlelf.h"
16*10465441SEvalZero
17*10465441SEvalZero #include <dfs_posix.h>
18*10465441SEvalZero
19*10465441SEvalZero #define DBG_SECTION_NAME "DLMD"
20*10465441SEvalZero #define DBG_ENABLE // enable debug macro
21*10465441SEvalZero #define DBG_LEVEL DBG_INFO
22*10465441SEvalZero #define DBG_COLOR
23*10465441SEvalZero #include <rtdbg.h> // must after of DEBUG_ENABLE or some other options
24*10465441SEvalZero
25*10465441SEvalZero static struct rt_module_symtab *_rt_module_symtab_begin = RT_NULL;
26*10465441SEvalZero static struct rt_module_symtab *_rt_module_symtab_end = RT_NULL;
27*10465441SEvalZero
28*10465441SEvalZero #if defined(__IAR_SYSTEMS_ICC__) /* for IAR compiler */
29*10465441SEvalZero #pragma section="RTMSymTab"
30*10465441SEvalZero #endif
31*10465441SEvalZero
32*10465441SEvalZero /* set the name of module */
_dlmodule_set_name(struct rt_dlmodule * module,const char * path)33*10465441SEvalZero static void _dlmodule_set_name(struct rt_dlmodule *module, const char *path)
34*10465441SEvalZero {
35*10465441SEvalZero int size;
36*10465441SEvalZero struct rt_object *object;
37*10465441SEvalZero const char *first, *end, *ptr;
38*10465441SEvalZero
39*10465441SEvalZero object = &(module->parent);
40*10465441SEvalZero ptr = first = (char *)path;
41*10465441SEvalZero end = path + rt_strlen(path);
42*10465441SEvalZero
43*10465441SEvalZero while (*ptr != '\0')
44*10465441SEvalZero {
45*10465441SEvalZero if (*ptr == '/')
46*10465441SEvalZero first = ptr + 1;
47*10465441SEvalZero if (*ptr == '.')
48*10465441SEvalZero end = ptr - 1;
49*10465441SEvalZero
50*10465441SEvalZero ptr ++;
51*10465441SEvalZero }
52*10465441SEvalZero
53*10465441SEvalZero size = end - first + 1;
54*10465441SEvalZero if (size > RT_NAME_MAX) size = RT_NAME_MAX;
55*10465441SEvalZero
56*10465441SEvalZero rt_strncpy(object->name, first, size);
57*10465441SEvalZero object->name[size] = '\0';
58*10465441SEvalZero }
59*10465441SEvalZero
60*10465441SEvalZero #define RT_MODULE_ARG_MAX 8
_rt_module_split_arg(char * cmd,rt_size_t length,char * argv[])61*10465441SEvalZero static int _rt_module_split_arg(char *cmd, rt_size_t length, char *argv[])
62*10465441SEvalZero {
63*10465441SEvalZero int argc = 0;
64*10465441SEvalZero char *ptr = cmd;
65*10465441SEvalZero
66*10465441SEvalZero while ((ptr - cmd) < length)
67*10465441SEvalZero {
68*10465441SEvalZero /* strip bank and tab */
69*10465441SEvalZero while ((*ptr == ' ' || *ptr == '\t') && (ptr - cmd) < length)
70*10465441SEvalZero *ptr++ = '\0';
71*10465441SEvalZero /* check whether it's the end of line */
72*10465441SEvalZero if ((ptr - cmd) >= length) break;
73*10465441SEvalZero
74*10465441SEvalZero /* handle string with quote */
75*10465441SEvalZero if (*ptr == '"')
76*10465441SEvalZero {
77*10465441SEvalZero argv[argc++] = ++ptr;
78*10465441SEvalZero
79*10465441SEvalZero /* skip this string */
80*10465441SEvalZero while (*ptr != '"' && (ptr - cmd) < length)
81*10465441SEvalZero if (*ptr ++ == '\\') ptr ++;
82*10465441SEvalZero if ((ptr - cmd) >= length) break;
83*10465441SEvalZero
84*10465441SEvalZero /* skip '"' */
85*10465441SEvalZero *ptr ++ = '\0';
86*10465441SEvalZero }
87*10465441SEvalZero else
88*10465441SEvalZero {
89*10465441SEvalZero argv[argc++] = ptr;
90*10465441SEvalZero while ((*ptr != ' ' && *ptr != '\t') && (ptr - cmd) < length)
91*10465441SEvalZero ptr ++;
92*10465441SEvalZero }
93*10465441SEvalZero
94*10465441SEvalZero if (argc >= RT_MODULE_ARG_MAX) break;
95*10465441SEvalZero }
96*10465441SEvalZero
97*10465441SEvalZero return argc;
98*10465441SEvalZero }
99*10465441SEvalZero
100*10465441SEvalZero /* invoked by main thread for exit */
_dlmodule_exit(void)101*10465441SEvalZero static void _dlmodule_exit(void)
102*10465441SEvalZero {
103*10465441SEvalZero struct rt_dlmodule *module;
104*10465441SEvalZero
105*10465441SEvalZero module = dlmodule_self();
106*10465441SEvalZero if (!module) return; /* not a module thread */
107*10465441SEvalZero
108*10465441SEvalZero rt_enter_critical();
109*10465441SEvalZero if (module->stat == RT_DLMODULE_STAT_RUNNING)
110*10465441SEvalZero {
111*10465441SEvalZero struct rt_object *object = RT_NULL;
112*10465441SEvalZero struct rt_list_node *node = RT_NULL;
113*10465441SEvalZero
114*10465441SEvalZero /* set stat to closing */
115*10465441SEvalZero module->stat = RT_DLMODULE_STAT_CLOSING;
116*10465441SEvalZero
117*10465441SEvalZero /* suspend all threads in this module */
118*10465441SEvalZero for (node = module->object_list.next; node != &(module->object_list); node = node->next)
119*10465441SEvalZero {
120*10465441SEvalZero object = rt_list_entry(node, struct rt_object, list);
121*10465441SEvalZero
122*10465441SEvalZero if ((object->type & ~RT_Object_Class_Static) == RT_Object_Class_Thread)
123*10465441SEvalZero {
124*10465441SEvalZero rt_thread_t thread = (rt_thread_t)object;
125*10465441SEvalZero
126*10465441SEvalZero /* stop timer and suspend thread*/
127*10465441SEvalZero if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE ||
128*10465441SEvalZero (thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT)
129*10465441SEvalZero {
130*10465441SEvalZero rt_timer_stop(&(thread->thread_timer));
131*10465441SEvalZero rt_thread_suspend(thread);
132*10465441SEvalZero }
133*10465441SEvalZero }
134*10465441SEvalZero }
135*10465441SEvalZero }
136*10465441SEvalZero rt_exit_critical();
137*10465441SEvalZero
138*10465441SEvalZero return;
139*10465441SEvalZero }
140*10465441SEvalZero
_dlmodule_thread_entry(void * parameter)141*10465441SEvalZero static void _dlmodule_thread_entry(void* parameter)
142*10465441SEvalZero {
143*10465441SEvalZero int argc = 0;
144*10465441SEvalZero char *argv[RT_MODULE_ARG_MAX];
145*10465441SEvalZero
146*10465441SEvalZero struct rt_dlmodule *module = (struct rt_dlmodule*)parameter;
147*10465441SEvalZero
148*10465441SEvalZero if (module == RT_NULL || module->cmd_line == RT_NULL)
149*10465441SEvalZero /* malloc for module_cmd_line failed. */
150*10465441SEvalZero return;
151*10465441SEvalZero
152*10465441SEvalZero if (module->cmd_line)
153*10465441SEvalZero {
154*10465441SEvalZero rt_memset(argv, 0x00, sizeof(argv));
155*10465441SEvalZero argc = _rt_module_split_arg((char *)module->cmd_line, rt_strlen(module->cmd_line), argv);
156*10465441SEvalZero if (argc == 0) goto __exit;
157*10465441SEvalZero }
158*10465441SEvalZero
159*10465441SEvalZero /* set status of module */
160*10465441SEvalZero module->stat = RT_DLMODULE_STAT_RUNNING;
161*10465441SEvalZero
162*10465441SEvalZero LOG_D("run main entry: 0x%p with %s",
163*10465441SEvalZero module->entry_addr,
164*10465441SEvalZero module->cmd_line);
165*10465441SEvalZero
166*10465441SEvalZero if (module->entry_addr)
167*10465441SEvalZero module->entry_addr(argc, argv);
168*10465441SEvalZero
169*10465441SEvalZero __exit:
170*10465441SEvalZero _dlmodule_exit();
171*10465441SEvalZero
172*10465441SEvalZero return ;
173*10465441SEvalZero }
174*10465441SEvalZero
dlmodule_create(void)175*10465441SEvalZero struct rt_dlmodule *dlmodule_create(void)
176*10465441SEvalZero {
177*10465441SEvalZero struct rt_dlmodule *module = RT_NULL;
178*10465441SEvalZero
179*10465441SEvalZero module = (struct rt_dlmodule*) rt_object_allocate(RT_Object_Class_Module, "module");
180*10465441SEvalZero if (module)
181*10465441SEvalZero {
182*10465441SEvalZero module->stat = RT_DLMODULE_STAT_INIT;
183*10465441SEvalZero
184*10465441SEvalZero /* set initial priority and stack size */
185*10465441SEvalZero module->priority = RT_THREAD_PRIORITY_MAX - 1;
186*10465441SEvalZero module->stack_size = 2048;
187*10465441SEvalZero
188*10465441SEvalZero rt_list_init(&(module->object_list));
189*10465441SEvalZero }
190*10465441SEvalZero
191*10465441SEvalZero return module;
192*10465441SEvalZero }
193*10465441SEvalZero
dlmodule_destroy_subthread(struct rt_dlmodule * module,rt_thread_t thread)194*10465441SEvalZero void dlmodule_destroy_subthread(struct rt_dlmodule *module, rt_thread_t thread)
195*10465441SEvalZero {
196*10465441SEvalZero RT_ASSERT(thread->module_id == module);
197*10465441SEvalZero
198*10465441SEvalZero /* lock scheduler to prevent scheduling in cleanup function. */
199*10465441SEvalZero rt_enter_critical();
200*10465441SEvalZero
201*10465441SEvalZero /* remove thread from thread_list (ready or defunct thread list) */
202*10465441SEvalZero rt_list_remove(&(thread->tlist));
203*10465441SEvalZero
204*10465441SEvalZero if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE &&
205*10465441SEvalZero (thread->thread_timer.parent.type == (RT_Object_Class_Static | RT_Object_Class_Timer)))
206*10465441SEvalZero {
207*10465441SEvalZero /* release thread timer */
208*10465441SEvalZero rt_timer_detach(&(thread->thread_timer));
209*10465441SEvalZero }
210*10465441SEvalZero
211*10465441SEvalZero /* change stat */
212*10465441SEvalZero thread->stat = RT_THREAD_CLOSE;
213*10465441SEvalZero
214*10465441SEvalZero /* invoke thread cleanup */
215*10465441SEvalZero if (thread->cleanup != RT_NULL)
216*10465441SEvalZero thread->cleanup(thread);
217*10465441SEvalZero
218*10465441SEvalZero rt_exit_critical();
219*10465441SEvalZero
220*10465441SEvalZero #ifdef RT_USING_SIGNALS
221*10465441SEvalZero rt_thread_free_sig(thread);
222*10465441SEvalZero #endif
223*10465441SEvalZero
224*10465441SEvalZero if (thread->type & RT_Object_Class_Static)
225*10465441SEvalZero {
226*10465441SEvalZero /* detach object */
227*10465441SEvalZero rt_object_detach((rt_object_t)thread);
228*10465441SEvalZero }
229*10465441SEvalZero #ifdef RT_USING_HEAP
230*10465441SEvalZero else
231*10465441SEvalZero {
232*10465441SEvalZero /* release thread's stack */
233*10465441SEvalZero RT_KERNEL_FREE(thread->stack_addr);
234*10465441SEvalZero /* delete thread object */
235*10465441SEvalZero rt_object_delete((rt_object_t)thread);
236*10465441SEvalZero }
237*10465441SEvalZero #endif
238*10465441SEvalZero }
239*10465441SEvalZero
dlmodule_destroy(struct rt_dlmodule * module)240*10465441SEvalZero rt_err_t dlmodule_destroy(struct rt_dlmodule* module)
241*10465441SEvalZero {
242*10465441SEvalZero int i;
243*10465441SEvalZero
244*10465441SEvalZero RT_DEBUG_NOT_IN_INTERRUPT;
245*10465441SEvalZero
246*10465441SEvalZero /* check parameter */
247*10465441SEvalZero if (module == RT_NULL)
248*10465441SEvalZero return -RT_ERROR;
249*10465441SEvalZero
250*10465441SEvalZero /* can not destroy a running module */
251*10465441SEvalZero if (module->stat == RT_DLMODULE_STAT_RUNNING)
252*10465441SEvalZero return -RT_EBUSY;
253*10465441SEvalZero
254*10465441SEvalZero /* do module cleanup */
255*10465441SEvalZero if (module->cleanup_func)
256*10465441SEvalZero {
257*10465441SEvalZero rt_enter_critical();
258*10465441SEvalZero module->cleanup_func(module);
259*10465441SEvalZero rt_exit_critical();
260*10465441SEvalZero }
261*10465441SEvalZero
262*10465441SEvalZero // list_object(&(module->object_list));
263*10465441SEvalZero
264*10465441SEvalZero /* cleanup for all kernel objects inside module*/
265*10465441SEvalZero {
266*10465441SEvalZero struct rt_object *object = RT_NULL;
267*10465441SEvalZero struct rt_list_node *node = RT_NULL;
268*10465441SEvalZero
269*10465441SEvalZero /* detach/delete all threads in this module */
270*10465441SEvalZero for (node = module->object_list.next; node != &(module->object_list); )
271*10465441SEvalZero {
272*10465441SEvalZero int object_type;
273*10465441SEvalZero
274*10465441SEvalZero object = rt_list_entry(node, struct rt_object, list);
275*10465441SEvalZero object_type = object->type & ~RT_Object_Class_Static;
276*10465441SEvalZero
277*10465441SEvalZero /* to next node */
278*10465441SEvalZero node = node->next;
279*10465441SEvalZero
280*10465441SEvalZero if (object->type & RT_Object_Class_Static)
281*10465441SEvalZero {
282*10465441SEvalZero switch (object_type)
283*10465441SEvalZero {
284*10465441SEvalZero case RT_Object_Class_Thread:
285*10465441SEvalZero dlmodule_destroy_subthread(module, (rt_thread_t)object);
286*10465441SEvalZero break;
287*10465441SEvalZero #ifdef RT_USING_SEMAPHORE
288*10465441SEvalZero case RT_Object_Class_Semaphore:
289*10465441SEvalZero rt_sem_detach((rt_sem_t)object);
290*10465441SEvalZero break;
291*10465441SEvalZero #endif
292*10465441SEvalZero #ifdef RT_USING_MUTEX
293*10465441SEvalZero case RT_Object_Class_Mutex:
294*10465441SEvalZero rt_mutex_detach((rt_mutex_t)object);
295*10465441SEvalZero break;
296*10465441SEvalZero #endif
297*10465441SEvalZero #ifdef RT_USING_EVENT
298*10465441SEvalZero case RT_Object_Class_Event:
299*10465441SEvalZero rt_event_detach((rt_event_t)object);
300*10465441SEvalZero break;
301*10465441SEvalZero #endif
302*10465441SEvalZero #ifdef RT_USING_MAILBOX
303*10465441SEvalZero case RT_Object_Class_MailBox:
304*10465441SEvalZero rt_mb_detach((rt_mailbox_t)object);
305*10465441SEvalZero break;
306*10465441SEvalZero #endif
307*10465441SEvalZero #ifdef RT_USING_MESSAGEQUEUE
308*10465441SEvalZero case RT_Object_Class_MessageQueue:
309*10465441SEvalZero rt_mq_detach((rt_mq_t)object);
310*10465441SEvalZero break;
311*10465441SEvalZero #endif
312*10465441SEvalZero #ifdef RT_USING_MEMHEAP
313*10465441SEvalZero case RT_Object_Class_MemHeap:
314*10465441SEvalZero rt_memheap_detach((struct rt_memheap*)object);
315*10465441SEvalZero break;
316*10465441SEvalZero #endif
317*10465441SEvalZero #ifdef RT_USING_MEMPOOL
318*10465441SEvalZero case RT_Object_Class_MemPool:
319*10465441SEvalZero rt_mp_detach((struct rt_mempool*)object);
320*10465441SEvalZero break;
321*10465441SEvalZero #endif
322*10465441SEvalZero case RT_Object_Class_Timer:
323*10465441SEvalZero rt_timer_detach((rt_timer_t)object);
324*10465441SEvalZero break;
325*10465441SEvalZero default:
326*10465441SEvalZero LOG_E("Unsupported oject type in module.");
327*10465441SEvalZero break;
328*10465441SEvalZero }
329*10465441SEvalZero }
330*10465441SEvalZero else
331*10465441SEvalZero {
332*10465441SEvalZero switch (object_type)
333*10465441SEvalZero {
334*10465441SEvalZero case RT_Object_Class_Thread:
335*10465441SEvalZero dlmodule_destroy_subthread(module, (rt_thread_t)object);
336*10465441SEvalZero break;
337*10465441SEvalZero #ifdef RT_USING_SEMAPHORE
338*10465441SEvalZero case RT_Object_Class_Semaphore:
339*10465441SEvalZero rt_sem_delete((rt_sem_t)object);
340*10465441SEvalZero break;
341*10465441SEvalZero #endif
342*10465441SEvalZero #ifdef RT_USING_MUTEX
343*10465441SEvalZero case RT_Object_Class_Mutex:
344*10465441SEvalZero rt_mutex_delete((rt_mutex_t)object);
345*10465441SEvalZero break;
346*10465441SEvalZero #endif
347*10465441SEvalZero #ifdef RT_USING_EVENT
348*10465441SEvalZero case RT_Object_Class_Event:
349*10465441SEvalZero rt_event_delete((rt_event_t)object);
350*10465441SEvalZero break;
351*10465441SEvalZero #endif
352*10465441SEvalZero #ifdef RT_USING_MAILBOX
353*10465441SEvalZero case RT_Object_Class_MailBox:
354*10465441SEvalZero rt_mb_delete((rt_mailbox_t)object);
355*10465441SEvalZero break;
356*10465441SEvalZero #endif
357*10465441SEvalZero #ifdef RT_USING_MESSAGEQUEUE
358*10465441SEvalZero case RT_Object_Class_MessageQueue:
359*10465441SEvalZero rt_mq_delete((rt_mq_t)object);
360*10465441SEvalZero break;
361*10465441SEvalZero #endif
362*10465441SEvalZero #ifdef RT_USING_MEMHEAP
363*10465441SEvalZero /* no delete operation */
364*10465441SEvalZero #endif
365*10465441SEvalZero #ifdef RT_USING_MEMPOOL
366*10465441SEvalZero case RT_Object_Class_MemPool:
367*10465441SEvalZero rt_mp_delete((struct rt_mempool*)object);
368*10465441SEvalZero break;
369*10465441SEvalZero #endif
370*10465441SEvalZero case RT_Object_Class_Timer:
371*10465441SEvalZero rt_timer_delete((rt_timer_t)object);
372*10465441SEvalZero break;
373*10465441SEvalZero default:
374*10465441SEvalZero LOG_E("Unsupported oject type in module.");
375*10465441SEvalZero break;
376*10465441SEvalZero }
377*10465441SEvalZero }
378*10465441SEvalZero }
379*10465441SEvalZero }
380*10465441SEvalZero
381*10465441SEvalZero if (module->cmd_line) rt_free(module->cmd_line);
382*10465441SEvalZero /* release module symbol table */
383*10465441SEvalZero for (i = 0; i < module->nsym; i ++)
384*10465441SEvalZero {
385*10465441SEvalZero rt_free((void *)module->symtab[i].name);
386*10465441SEvalZero }
387*10465441SEvalZero if (module->symtab != RT_NULL)
388*10465441SEvalZero {
389*10465441SEvalZero rt_free(module->symtab);
390*10465441SEvalZero }
391*10465441SEvalZero
392*10465441SEvalZero /* destory module */
393*10465441SEvalZero rt_free(module->mem_space);
394*10465441SEvalZero /* delete module object */
395*10465441SEvalZero rt_object_delete((rt_object_t)module);
396*10465441SEvalZero
397*10465441SEvalZero return RT_EOK;
398*10465441SEvalZero }
399*10465441SEvalZero
dlmodule_self(void)400*10465441SEvalZero struct rt_dlmodule *dlmodule_self(void)
401*10465441SEvalZero {
402*10465441SEvalZero rt_thread_t tid;
403*10465441SEvalZero struct rt_dlmodule *ret = RT_NULL;
404*10465441SEvalZero
405*10465441SEvalZero tid = rt_thread_self();
406*10465441SEvalZero if (tid)
407*10465441SEvalZero {
408*10465441SEvalZero ret = (struct rt_dlmodule*) tid->module_id;
409*10465441SEvalZero }
410*10465441SEvalZero
411*10465441SEvalZero return ret;
412*10465441SEvalZero }
413*10465441SEvalZero
414*10465441SEvalZero /*
415*10465441SEvalZero * Compatible with old API
416*10465441SEvalZero */
rt_module_self(void)417*10465441SEvalZero struct rt_dlmodule *rt_module_self(void)
418*10465441SEvalZero {
419*10465441SEvalZero return dlmodule_self();
420*10465441SEvalZero }
421*10465441SEvalZero
dlmodule_load(const char * filename)422*10465441SEvalZero struct rt_dlmodule* dlmodule_load(const char* filename)
423*10465441SEvalZero {
424*10465441SEvalZero int fd, length = 0;
425*10465441SEvalZero rt_err_t ret = RT_EOK;
426*10465441SEvalZero rt_uint8_t *module_ptr = RT_NULL;
427*10465441SEvalZero struct rt_dlmodule *module = RT_NULL;
428*10465441SEvalZero
429*10465441SEvalZero fd = open(filename, O_RDONLY, 0);
430*10465441SEvalZero if (fd >= 0)
431*10465441SEvalZero {
432*10465441SEvalZero length = lseek(fd, 0, SEEK_END);
433*10465441SEvalZero lseek(fd, 0, SEEK_SET);
434*10465441SEvalZero
435*10465441SEvalZero if (length == 0) goto __exit;
436*10465441SEvalZero
437*10465441SEvalZero module_ptr = (uint8_t*) rt_malloc (length);
438*10465441SEvalZero if (!module_ptr) goto __exit;
439*10465441SEvalZero
440*10465441SEvalZero if (read(fd, module_ptr, length) != length)
441*10465441SEvalZero goto __exit;
442*10465441SEvalZero
443*10465441SEvalZero /* close file and release fd */
444*10465441SEvalZero close(fd);
445*10465441SEvalZero fd = -1;
446*10465441SEvalZero }
447*10465441SEvalZero
448*10465441SEvalZero /* check ELF header */
449*10465441SEvalZero if (rt_memcmp(elf_module->e_ident, RTMMAG, SELFMAG) != 0 &&
450*10465441SEvalZero rt_memcmp(elf_module->e_ident, ELFMAG, SELFMAG) != 0)
451*10465441SEvalZero {
452*10465441SEvalZero rt_kprintf("Module: magic error\n");
453*10465441SEvalZero goto __exit;
454*10465441SEvalZero }
455*10465441SEvalZero
456*10465441SEvalZero /* check ELF class */
457*10465441SEvalZero if (elf_module->e_ident[EI_CLASS] != ELFCLASS32)
458*10465441SEvalZero {
459*10465441SEvalZero rt_kprintf("Module: ELF class error\n");
460*10465441SEvalZero goto __exit;
461*10465441SEvalZero }
462*10465441SEvalZero
463*10465441SEvalZero module = dlmodule_create();
464*10465441SEvalZero if (!module) goto __exit;
465*10465441SEvalZero
466*10465441SEvalZero /* set the name of module */
467*10465441SEvalZero _dlmodule_set_name(module, filename);
468*10465441SEvalZero
469*10465441SEvalZero LOG_D("rt_module_load: %.*s", RT_NAME_MAX, module->parent.name);
470*10465441SEvalZero
471*10465441SEvalZero if (elf_module->e_type == ET_REL)
472*10465441SEvalZero {
473*10465441SEvalZero ret = dlmodule_load_relocated_object(module, module_ptr);
474*10465441SEvalZero }
475*10465441SEvalZero else if (elf_module->e_type == ET_DYN)
476*10465441SEvalZero {
477*10465441SEvalZero ret = dlmodule_load_shared_object(module, module_ptr);
478*10465441SEvalZero }
479*10465441SEvalZero else
480*10465441SEvalZero {
481*10465441SEvalZero rt_kprintf("Module: unsupported elf type\n");
482*10465441SEvalZero goto __exit;
483*10465441SEvalZero }
484*10465441SEvalZero
485*10465441SEvalZero /* check return value */
486*10465441SEvalZero if (ret != RT_EOK) goto __exit;
487*10465441SEvalZero
488*10465441SEvalZero /* release module data */
489*10465441SEvalZero rt_free(module_ptr);
490*10465441SEvalZero
491*10465441SEvalZero /* increase module reference count */
492*10465441SEvalZero module->nref ++;
493*10465441SEvalZero
494*10465441SEvalZero /* deal with cache */
495*10465441SEvalZero #ifdef RT_USING_CACHE
496*10465441SEvalZero rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, module->mem_space, module->mem_size);
497*10465441SEvalZero rt_hw_cpu_icache_ops(RT_HW_CACHE_INVALIDATE, module->mem_space, module->mem_size);
498*10465441SEvalZero #endif
499*10465441SEvalZero
500*10465441SEvalZero /* set module initialization and cleanup function */
501*10465441SEvalZero module->init_func = dlsym(module, "module_init");
502*10465441SEvalZero module->cleanup_func = dlsym(module, "module_cleanup");
503*10465441SEvalZero module->stat = RT_DLMODULE_STAT_INIT;
504*10465441SEvalZero /* do module initialization */
505*10465441SEvalZero if (module->init_func)
506*10465441SEvalZero {
507*10465441SEvalZero module->init_func(module);
508*10465441SEvalZero }
509*10465441SEvalZero
510*10465441SEvalZero return module;
511*10465441SEvalZero
512*10465441SEvalZero __exit:
513*10465441SEvalZero if (fd >= 0) close(fd);
514*10465441SEvalZero if (module_ptr) rt_free(module_ptr);
515*10465441SEvalZero if (module) dlmodule_destroy(module);
516*10465441SEvalZero
517*10465441SEvalZero return RT_NULL;
518*10465441SEvalZero }
519*10465441SEvalZero
dlmodule_exec(const char * pgname,const char * cmd,int cmd_size)520*10465441SEvalZero struct rt_dlmodule* dlmodule_exec(const char* pgname, const char* cmd, int cmd_size)
521*10465441SEvalZero {
522*10465441SEvalZero struct rt_dlmodule *module = RT_NULL;
523*10465441SEvalZero
524*10465441SEvalZero module = dlmodule_load(pgname);
525*10465441SEvalZero if (module)
526*10465441SEvalZero {
527*10465441SEvalZero if (module->entry_addr)
528*10465441SEvalZero {
529*10465441SEvalZero /* exec this module */
530*10465441SEvalZero rt_thread_t tid;
531*10465441SEvalZero
532*10465441SEvalZero module->cmd_line = rt_strdup(cmd);
533*10465441SEvalZero
534*10465441SEvalZero /* check stack size and priority */
535*10465441SEvalZero if (module->priority > RT_THREAD_PRIORITY_MAX) module->priority = RT_THREAD_PRIORITY_MAX - 1;
536*10465441SEvalZero if (module->stack_size < 2048 || module->stack_size > (1024 * 32)) module->stack_size = 2048;
537*10465441SEvalZero
538*10465441SEvalZero tid = rt_thread_create(module->parent.name, _dlmodule_thread_entry, (void*)module,
539*10465441SEvalZero module->stack_size, module->priority, 10);
540*10465441SEvalZero if (tid)
541*10465441SEvalZero {
542*10465441SEvalZero tid->module_id = module;
543*10465441SEvalZero module->main_thread = tid;
544*10465441SEvalZero
545*10465441SEvalZero rt_thread_startup(tid);
546*10465441SEvalZero }
547*10465441SEvalZero else
548*10465441SEvalZero {
549*10465441SEvalZero /* destory dl module */
550*10465441SEvalZero dlmodule_destroy(module);
551*10465441SEvalZero module = RT_NULL;
552*10465441SEvalZero }
553*10465441SEvalZero }
554*10465441SEvalZero }
555*10465441SEvalZero
556*10465441SEvalZero return module;
557*10465441SEvalZero }
558*10465441SEvalZero
dlmodule_exit(int ret_code)559*10465441SEvalZero void dlmodule_exit(int ret_code)
560*10465441SEvalZero {
561*10465441SEvalZero rt_thread_t thread;
562*10465441SEvalZero struct rt_dlmodule *module;
563*10465441SEvalZero
564*10465441SEvalZero module = dlmodule_self();
565*10465441SEvalZero if (!module) return;
566*10465441SEvalZero
567*10465441SEvalZero /* disable scheduling */
568*10465441SEvalZero rt_enter_critical();
569*10465441SEvalZero
570*10465441SEvalZero /* module is not running */
571*10465441SEvalZero if (module->stat != RT_DLMODULE_STAT_RUNNING)
572*10465441SEvalZero {
573*10465441SEvalZero /* restore scheduling */
574*10465441SEvalZero rt_exit_critical();
575*10465441SEvalZero
576*10465441SEvalZero return;
577*10465441SEvalZero }
578*10465441SEvalZero
579*10465441SEvalZero /* set return code */
580*10465441SEvalZero module->ret_code = ret_code;
581*10465441SEvalZero
582*10465441SEvalZero /* do exit for this module */
583*10465441SEvalZero _dlmodule_exit();
584*10465441SEvalZero /* the stat of module was changed to CLOSING in _dlmodule_exit */
585*10465441SEvalZero
586*10465441SEvalZero thread = module->main_thread;
587*10465441SEvalZero if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_CLOSE)
588*10465441SEvalZero {
589*10465441SEvalZero /* main thread already closed */
590*10465441SEvalZero rt_exit_critical();
591*10465441SEvalZero
592*10465441SEvalZero return ;
593*10465441SEvalZero }
594*10465441SEvalZero
595*10465441SEvalZero /* delete thread: insert to defunct thread list */
596*10465441SEvalZero rt_thread_delete(thread);
597*10465441SEvalZero /* enable scheduling */
598*10465441SEvalZero rt_exit_critical();
599*10465441SEvalZero }
600*10465441SEvalZero
dlmodule_symbol_find(const char * sym_str)601*10465441SEvalZero rt_uint32_t dlmodule_symbol_find(const char *sym_str)
602*10465441SEvalZero {
603*10465441SEvalZero /* find in kernel symbol table */
604*10465441SEvalZero struct rt_module_symtab *index;
605*10465441SEvalZero
606*10465441SEvalZero for (index = _rt_module_symtab_begin; index != _rt_module_symtab_end; index ++)
607*10465441SEvalZero {
608*10465441SEvalZero if (rt_strcmp(index->name, sym_str) == 0)
609*10465441SEvalZero return (rt_uint32_t)index->addr;
610*10465441SEvalZero }
611*10465441SEvalZero
612*10465441SEvalZero return 0;
613*10465441SEvalZero }
614*10465441SEvalZero
rt_system_dlmodule_init(void)615*10465441SEvalZero int rt_system_dlmodule_init(void)
616*10465441SEvalZero {
617*10465441SEvalZero #if defined(__GNUC__) && !defined(__CC_ARM)
618*10465441SEvalZero extern int __rtmsymtab_start;
619*10465441SEvalZero extern int __rtmsymtab_end;
620*10465441SEvalZero
621*10465441SEvalZero _rt_module_symtab_begin = (struct rt_module_symtab *)&__rtmsymtab_start;
622*10465441SEvalZero _rt_module_symtab_end = (struct rt_module_symtab *)&__rtmsymtab_end;
623*10465441SEvalZero #elif defined (__CC_ARM)
624*10465441SEvalZero extern int RTMSymTab$$Base;
625*10465441SEvalZero extern int RTMSymTab$$Limit;
626*10465441SEvalZero
627*10465441SEvalZero _rt_module_symtab_begin = (struct rt_module_symtab *)&RTMSymTab$$Base;
628*10465441SEvalZero _rt_module_symtab_end = (struct rt_module_symtab *)&RTMSymTab$$Limit;
629*10465441SEvalZero #elif defined (__IAR_SYSTEMS_ICC__)
630*10465441SEvalZero _rt_module_symtab_begin = __section_begin("RTMSymTab");
631*10465441SEvalZero _rt_module_symtab_end = __section_end("RTMSymTab");
632*10465441SEvalZero #endif
633*10465441SEvalZero
634*10465441SEvalZero return 0;
635*10465441SEvalZero }
636*10465441SEvalZero INIT_COMPONENT_EXPORT(rt_system_dlmodule_init);
637*10465441SEvalZero
638*10465441SEvalZero /**
639*10465441SEvalZero * This function will find the specified module.
640*10465441SEvalZero *
641*10465441SEvalZero * @param name the name of module finding
642*10465441SEvalZero *
643*10465441SEvalZero * @return the module
644*10465441SEvalZero */
dlmodule_find(const char * name)645*10465441SEvalZero struct rt_dlmodule *dlmodule_find(const char *name)
646*10465441SEvalZero {
647*10465441SEvalZero rt_object_t object;
648*10465441SEvalZero struct rt_dlmodule *ret = RT_NULL;
649*10465441SEvalZero
650*10465441SEvalZero object = rt_object_find(name, RT_Object_Class_Module);
651*10465441SEvalZero if (object)
652*10465441SEvalZero {
653*10465441SEvalZero ret = (struct rt_dlmodule*) object;
654*10465441SEvalZero }
655*10465441SEvalZero
656*10465441SEvalZero return ret;
657*10465441SEvalZero }
658*10465441SEvalZero RTM_EXPORT(dlmodule_find);
659*10465441SEvalZero
list_symbols(void)660*10465441SEvalZero int list_symbols(void)
661*10465441SEvalZero {
662*10465441SEvalZero extern int __rtmsymtab_start;
663*10465441SEvalZero extern int __rtmsymtab_end;
664*10465441SEvalZero
665*10465441SEvalZero /* find in kernel symbol table */
666*10465441SEvalZero struct rt_module_symtab *index;
667*10465441SEvalZero
668*10465441SEvalZero for (index = _rt_module_symtab_begin;
669*10465441SEvalZero index != _rt_module_symtab_end;
670*10465441SEvalZero index ++)
671*10465441SEvalZero {
672*10465441SEvalZero rt_kprintf("%s => 0x%08x\n", index->name, index->addr);
673*10465441SEvalZero }
674*10465441SEvalZero
675*10465441SEvalZero return 0;
676*10465441SEvalZero }
677*10465441SEvalZero MSH_CMD_EXPORT(list_symbols, list symbols information);
678*10465441SEvalZero
list_module(void)679*10465441SEvalZero int list_module(void)
680*10465441SEvalZero {
681*10465441SEvalZero struct rt_dlmodule *module;
682*10465441SEvalZero struct rt_list_node *list, *node;
683*10465441SEvalZero struct rt_object_information *info;
684*10465441SEvalZero
685*10465441SEvalZero info = rt_object_get_information(RT_Object_Class_Module);
686*10465441SEvalZero list = &info->object_list;
687*10465441SEvalZero
688*10465441SEvalZero rt_kprintf("module ref address \n");
689*10465441SEvalZero rt_kprintf("-------- -------- ------------\n");
690*10465441SEvalZero for (node = list->next; node != list; node = node->next)
691*10465441SEvalZero {
692*10465441SEvalZero module = (struct rt_dlmodule *)(rt_list_entry(node, struct rt_object, list));
693*10465441SEvalZero rt_kprintf("%-*.*s %-04d 0x%08x\n",
694*10465441SEvalZero RT_NAME_MAX, RT_NAME_MAX, module->parent.name, module->nref, module->mem_space);
695*10465441SEvalZero }
696*10465441SEvalZero
697*10465441SEvalZero return 0;
698*10465441SEvalZero }
699*10465441SEvalZero MSH_CMD_EXPORT(list_module, list modules in system);
700