xref: /nrf52832-nimble/rt-thread/components/libc/libdl/dlmodule.c (revision 104654410c56c573564690304ae786df310c91fc)
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