module.c 59.3 KB
Newer Older
qiuyiuestc's avatar
qiuyiuestc 已提交
1 2 3
/*
 * File      : module.c
 * This file is part of RT-Thread RTOS
D
dzzxzz 已提交
4
 * COPYRIGHT (C) 2006 - 2012, RT-Thread Development Team
qiuyiuestc's avatar
qiuyiuestc 已提交
5
 *
B
Bernard Xiong 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
qiuyiuestc's avatar
qiuyiuestc 已提交
19 20
 *
 * Change Logs:
D
dzzxzz 已提交
21 22 23 24 25 26
 * Date           Author       Notes
 * 2010-01-09     Bernard      first version
 * 2010-04-09     yi.qiu       implement based on first version
 * 2010-10-23     yi.qiu       implement module memory allocator
 * 2011-05-25     yi.qiu       implement module hook function
 * 2011-06-23     yi.qiu       rewrite module memory allocator
27
 * 2012-11-23     Bernard      using RT_DEBUG_LOG instead of rt_kprintf.
B
Bernard Xiong 已提交
28
 * 2012-11-28     Bernard      remove rt_current_module and user
29
 *                             can use rt_module_unload to remove a module.
30
 * 2017-08-20     parai        support intel 386 machine
qiuyiuestc's avatar
qiuyiuestc 已提交
31
 */
qiuyiuestc's avatar
qiuyiuestc 已提交
32

33
#include <rthw.h>
qiuyiuestc's avatar
qiuyiuestc 已提交
34
#include <rtthread.h>
qiuyiuestc's avatar
qiuyiuestc 已提交
35
#include <rtm.h>
qiuyiuestc's avatar
qiuyiuestc 已提交
36

37 38 39 40
#ifdef RT_USING_FINSH
#include <finsh.h>
#endif

qiuyiuestc's avatar
qiuyiuestc 已提交
41
#ifdef RT_USING_MODULE
42
#include "module.h"
qiuyiuestc's avatar
qiuyiuestc 已提交
43

44 45 46 47 48 49 50 51 52 53 54
#define elf_module        ((Elf32_Ehdr *)module_ptr)
#define shdr              ((Elf32_Shdr *)((rt_uint8_t *)module_ptr + elf_module->e_shoff))
#define phdr              ((Elf32_Phdr *)((rt_uint8_t *)module_ptr + elf_module->e_phoff))

#define IS_PROG(s)        (s.sh_type == SHT_PROGBITS)
#define IS_NOPROG(s)      (s.sh_type == SHT_NOBITS)
#define IS_REL(s)         (s.sh_type == SHT_REL)
#define IS_RELA(s)        (s.sh_type == SHT_RELA)
#define IS_ALLOC(s)       (s.sh_flags == SHF_ALLOC)
#define IS_AX(s)          ((s.sh_flags & SHF_ALLOC) && (s.sh_flags & SHF_EXECINSTR))
#define IS_AW(s)          ((s.sh_flags & SHF_ALLOC) && (s.sh_flags & SHF_WRITE))
qiuyiuestc's avatar
qiuyiuestc 已提交
55

56 57 58 59 60 61 62 63 64 65 66 67
#ifdef RT_USING_MODULE_STKSZ
#undef RT_USING_MODULE_STKSZ
#endif

#ifndef RT_USING_MODULE_STKSZ
#define RT_USING_MODULE_STKSZ (4096 * 2)
#endif

#ifndef RT_USING_MODULE_PRIO
#define RT_USING_MODULE_PRIO (RT_THREAD_PRIORITY_MAX - 2)
#endif

68
#ifdef RT_USING_SLAB
69
#define PAGE_COUNT_MAX    256
qiuyiuestc's avatar
qiuyiuestc 已提交
70

qiuyiuestc's avatar
qiuyiuestc 已提交
71 72 73
/* module memory allocator */
struct rt_mem_head
{
74 75
    rt_size_t size;                /* size of memory block */
    struct rt_mem_head *next;      /* next valid memory block */
qiuyiuestc's avatar
qiuyiuestc 已提交
76 77
};

qiuyiuestc's avatar
qiuyiuestc 已提交
78 79
struct rt_page_info
{
80 81
    rt_uint32_t *page_ptr;
    rt_uint32_t npage;
qiuyiuestc's avatar
qiuyiuestc 已提交
82 83 84
};

static void *rt_module_malloc_page(rt_size_t npages);
85 86 87
static void rt_module_free_page(rt_module_t module,
                                void       *page_ptr,
                                rt_size_t   npages);
qiuyiuestc's avatar
qiuyiuestc 已提交
88

qiuyiuestc's avatar
qiuyiuestc 已提交
89
static struct rt_semaphore mod_sem;
90 91
#endif

92
static struct rt_module_symtab *_rt_module_symtab_begin = RT_NULL;
93
static struct rt_module_symtab *_rt_module_symtab_end   = RT_NULL;
qiuyiuestc's avatar
qiuyiuestc 已提交
94

95 96 97 98
#if defined(__IAR_SYSTEMS_ICC__) /* for IAR compiler */
    #pragma section="RTMSymTab"
#endif

99 100 101
/**
 * @ingroup SystemInit
 *
B
bernard.xiong@gmail.com 已提交
102
 * This function will initialize system module
103
 */
B
bernard 已提交
104
int rt_system_module_init(void)
105
{
106
#if defined(__GNUC__) && !defined(__CC_ARM)
107 108
    extern int __rtmsymtab_start;
    extern int __rtmsymtab_end;
109

110 111
    _rt_module_symtab_begin = (struct rt_module_symtab *)&__rtmsymtab_start;
    _rt_module_symtab_end   = (struct rt_module_symtab *)&__rtmsymtab_end;
D
dzzxzz 已提交
112
#elif defined (__CC_ARM)
113 114
    extern int RTMSymTab$$Base;
    extern int RTMSymTab$$Limit;
D
dzzxzz 已提交
115

116
    _rt_module_symtab_begin = (struct rt_module_symtab *)&RTMSymTab$$Base;
117
    _rt_module_symtab_end   = (struct rt_module_symtab *)&RTMSymTab$$Limit;
118 119
#elif defined (__IAR_SYSTEMS_ICC__)
    _rt_module_symtab_begin = __section_begin("RTMSymTab");
120
    _rt_module_symtab_end   = __section_end("RTMSymTab");
qiuyiuestc's avatar
qiuyiuestc 已提交
121
#endif
122

123
#ifdef RT_USING_SLAB
124 125
    /* initialize heap semaphore */
    rt_sem_init(&mod_sem, "module", 1, RT_IPC_FLAG_FIFO);
126
#endif
127
    return 0;
128
}
B
Bernard Xiong 已提交
129
INIT_COMPONENT_EXPORT(rt_system_module_init);
130

131 132 133 134 135 136 137 138 139 140
#ifdef RT_USING_FINSH
void list_symbol(void)
{
    /* find in kernel symbol table */
    struct rt_module_symtab *index;

    for (index = _rt_module_symtab_begin;
         index != _rt_module_symtab_end;
         index ++)
    {
141
        rt_kprintf("%s\n", index->name);
142 143 144 145 146 147 148 149
    }

    return ;
}
FINSH_FUNCTION_EXPORT(list_symbol, list symbol for module);
MSH_CMD_EXPORT(list_symbol, list symbol for module);
#endif

D
dzzxzz 已提交
150
static rt_uint32_t rt_module_symbol_find(const char *sym_str)
151
{
152 153
    /* find in kernel symbol table */
    struct rt_module_symtab *index;
154 155 156 157

    for (index = _rt_module_symtab_begin;
         index != _rt_module_symtab_end;
         index ++)
158 159 160 161 162 163
    {
        if (rt_strcmp(index->name, sym_str) == 0)
            return (rt_uint32_t)index->addr;
    }

    return 0;
164
}
qiuyiuestc's avatar
qiuyiuestc 已提交
165

qiuyiuestc's avatar
qiuyiuestc 已提交
166 167 168
/**
 * This function will return self module object
 *
qiuyiuestc's avatar
qiuyiuestc 已提交
169
 * @return the self module object
qiuyiuestc's avatar
qiuyiuestc 已提交
170
 */
D
dzzxzz 已提交
171
rt_module_t rt_module_self(void)
qiuyiuestc's avatar
qiuyiuestc 已提交
172
{
173
    rt_thread_t tid;
qiuyiuestc's avatar
qiuyiuestc 已提交
174

175 176 177
    tid = rt_thread_self();
    if (tid == RT_NULL)
        return RT_NULL;
qiuyiuestc's avatar
qiuyiuestc 已提交
178

179 180
    /* return current module */
    return (rt_module_t)tid->module_id;
qiuyiuestc's avatar
qiuyiuestc 已提交
181
}
182
RTM_EXPORT(rt_module_self);
qiuyiuestc's avatar
qiuyiuestc 已提交
183

184 185 186
static int rt_module_arm_relocate(struct rt_module *module,
                                  Elf32_Rel        *rel,
                                  Elf32_Addr        sym_val)
qiuyiuestc's avatar
qiuyiuestc 已提交
187
{
188 189 190 191
    Elf32_Addr *where, tmp;
    Elf32_Sword addend, offset;
    rt_uint32_t upper, lower, sign, j1, j2;

192 193 194
    where = (Elf32_Addr *)((rt_uint8_t *)module->module_space
                           + rel->r_offset
                           - module->vstart_addr);
195 196 197 198 199 200
    switch (ELF32_R_TYPE(rel->r_info))
    {
    case R_ARM_NONE:
        break;
    case R_ARM_ABS32:
        *where += (Elf32_Addr)sym_val;
201 202
        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_ABS32: %x -> %x\n",
                                       where, *where));
203 204 205 206 207 208 209 210 211 212 213
        break;
    case R_ARM_PC24:
    case R_ARM_PLT32:
    case R_ARM_CALL:
    case R_ARM_JUMP24:
        addend = *where & 0x00ffffff;
        if (addend & 0x00800000)
            addend |= 0xff000000;
        tmp = sym_val - (Elf32_Addr)where + (addend << 2);
        tmp >>= 2;
        *where = (*where & 0xff000000) | (tmp & 0x00ffffff);
214 215
        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_PC24: %x -> %x\n",
                                       where, *where));
216 217 218
        break;
    case R_ARM_REL32:
        *where += sym_val - (Elf32_Addr)where;
219 220 221
        RT_DEBUG_LOG(RT_DEBUG_MODULE,
                     ("R_ARM_REL32: %x -> %x, sym %x, offset %x\n",
                      where, *where, sym_val, rel->r_offset));
222 223 224 225 226
        break;
    case R_ARM_V4BX:
        *where &= 0xf000000f;
        *where |= 0x01a0f000;
        break;
227 228 229 230
#ifdef MODULE_USING_386
    case R_386_GLOB_DAT:
    case R_386_JUMP_SLOT:
#endif
231 232 233
    case R_ARM_GLOB_DAT:
    case R_ARM_JUMP_SLOT:
        *where = (Elf32_Addr)sym_val;
234 235
        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_JUMP_SLOT: 0x%x -> 0x%x 0x%x\n",
                                       where, *where, sym_val));
236 237 238
        break;
#if 0        /* To do */
    case R_ARM_GOT_BREL:
239
        temp   = (Elf32_Addr)sym_val;
240
        *where = (Elf32_Addr)&temp;
241 242
        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_GOT_BREL: 0x%x -> 0x%x 0x%x\n",
                                       where, *where, sym_val));
243
        break;
244 245 246
#endif
#ifdef MODULE_USING_386
    case R_386_RELATIVE:
B
bernard.xiong@gmail.com 已提交
247
#endif
248 249
    case R_ARM_RELATIVE:
        *where = (Elf32_Addr)sym_val + *where;
250 251
        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_RELATIVE: 0x%x -> 0x%x 0x%x\n",
                                       where, *where, sym_val));
252 253 254
        break;
    case R_ARM_THM_CALL:
    case R_ARM_THM_JUMP24:
255 256 257 258 259 260 261
        upper  = *(rt_uint16_t *)where;
        lower  = *(rt_uint16_t *)((Elf32_Addr)where + 2);

        sign   = (upper >> 10) & 1;
        j1     = (lower >> 13) & 1;
        j2     = (lower >> 11) & 1;
        offset = (sign << 24) |
262 263 264 265
                 ((~(j1 ^ sign) & 1) << 23) |
                 ((~(j2 ^ sign) & 1) << 22) |
                 ((upper & 0x03ff) << 12) |
                 ((lower & 0x07ff) << 1);
266
        if (offset & 0x01000000)
267
            offset -= 0x02000000;
268 269
        offset += sym_val - (Elf32_Addr)where;

270 271 272
        if (!(offset & 1) ||
            offset <= (rt_int32_t)0xff000000 ||
            offset >= (rt_int32_t)0x01000000)
273
        {
274
            rt_kprintf("Module: Only Thumb addresses allowed\n");
275

276 277 278 279
            return -1;
        }

        sign = (offset >> 24) & 1;
280 281 282
        j1   = sign ^ (~(offset >> 23) & 1);
        j2   = sign ^ (~(offset >> 22) & 1);
        *(rt_uint16_t *)where = (rt_uint16_t)((upper & 0xf800) |
283 284
                                              (sign << 10) |
                                              ((offset >> 12) & 0x03ff));
285
        *(rt_uint16_t *)(where + 2) = (rt_uint16_t)((lower & 0xd000) |
286 287
                                                    (j1 << 13) | (j2 << 11) |
                                                    ((offset >> 1) & 0x07ff));
288 289 290 291 292 293 294 295
        upper = *(rt_uint16_t *)where;
        lower = *(rt_uint16_t *)((Elf32_Addr)where + 2);
        break;
    default:
        return -1;
    }

    return 0;
qiuyiuestc's avatar
qiuyiuestc 已提交
296 297
}

B
bernard 已提交
298
void rt_module_init_object_container(struct rt_module *module)
qiuyiuestc's avatar
qiuyiuestc 已提交
299
{
300
    RT_ASSERT(module != RT_NULL);
qiuyiuestc's avatar
qiuyiuestc 已提交
301

302 303 304
    /* clear all of object information */
    rt_memset(&module->module_object[0], 0x0, sizeof(module->module_object));

305 306 307 308
    /* initialize object container - thread */
    rt_list_init(&(module->module_object[RT_Object_Class_Thread].object_list));
    module->module_object[RT_Object_Class_Thread].object_size = sizeof(struct rt_thread);
    module->module_object[RT_Object_Class_Thread].type = RT_Object_Class_Thread;
qiuyiuestc's avatar
qiuyiuestc 已提交
309

310 311 312 313
    /* initialize object container - semaphore */
    rt_list_init(&(module->module_object[RT_Object_Class_Semaphore].object_list));
    module->module_object[RT_Object_Class_Semaphore].object_size = sizeof(struct rt_semaphore);
    module->module_object[RT_Object_Class_Semaphore].type = RT_Object_Class_Semaphore;
qiuyiuestc's avatar
qiuyiuestc 已提交
314

315 316 317 318
    /* initialize object container - mutex */
    rt_list_init(&(module->module_object[RT_Object_Class_Mutex].object_list));
    module->module_object[RT_Object_Class_Mutex].object_size = sizeof(struct rt_mutex);
    module->module_object[RT_Object_Class_Mutex].type = RT_Object_Class_Mutex;
qiuyiuestc's avatar
qiuyiuestc 已提交
319

320 321 322 323
    /* initialize object container - event */
    rt_list_init(&(module->module_object[RT_Object_Class_Event].object_list));
    module->module_object[RT_Object_Class_Event].object_size = sizeof(struct rt_event);
    module->module_object[RT_Object_Class_Event].type = RT_Object_Class_Event;
qiuyiuestc's avatar
qiuyiuestc 已提交
324

325 326 327 328
    /* initialize object container - mailbox */
    rt_list_init(&(module->module_object[RT_Object_Class_MailBox].object_list));
    module->module_object[RT_Object_Class_MailBox].object_size = sizeof(struct rt_mailbox);
    module->module_object[RT_Object_Class_MailBox].type = RT_Object_Class_MailBox;
qiuyiuestc's avatar
qiuyiuestc 已提交
329

330 331 332 333
    /* initialize object container - message queue */
    rt_list_init(&(module->module_object[RT_Object_Class_MessageQueue].object_list));
    module->module_object[RT_Object_Class_MessageQueue].object_size = sizeof(struct rt_messagequeue);
    module->module_object[RT_Object_Class_MessageQueue].type = RT_Object_Class_MessageQueue;
qiuyiuestc's avatar
qiuyiuestc 已提交
334

335 336 337 338
    /* initialize object container - memory heap */
    rt_list_init(&(module->module_object[RT_Object_Class_MemHeap].object_list));
    module->module_object[RT_Object_Class_MemHeap].object_size = sizeof(struct rt_memheap);
    module->module_object[RT_Object_Class_MemHeap].type = RT_Object_Class_MemHeap;
339

340 341 342 343
    /* initialize object container - memory pool */
    rt_list_init(&(module->module_object[RT_Object_Class_MemPool].object_list));
    module->module_object[RT_Object_Class_MemPool].object_size = sizeof(struct rt_mempool);
    module->module_object[RT_Object_Class_MemPool].type = RT_Object_Class_MemPool;
qiuyiuestc's avatar
qiuyiuestc 已提交
344

345 346 347 348
    /* initialize object container - device */
    rt_list_init(&(module->module_object[RT_Object_Class_Device].object_list));
    module->module_object[RT_Object_Class_Device].object_size = sizeof(struct rt_device);
    module->module_object[RT_Object_Class_Device].type = RT_Object_Class_Device;
qiuyiuestc's avatar
qiuyiuestc 已提交
349

350 351 352 353
    /* initialize object container - timer */
    rt_list_init(&(module->module_object[RT_Object_Class_Timer].object_list));
    module->module_object[RT_Object_Class_Timer].object_size = sizeof(struct rt_timer);
    module->module_object[RT_Object_Class_Timer].type = RT_Object_Class_Timer;
qiuyiuestc's avatar
qiuyiuestc 已提交
354 355
}

qiuyiuestc's avatar
qiuyiuestc 已提交
356 357 358 359 360 361 362
#ifdef RT_USING_HOOK
static void (*rt_module_load_hook)(rt_module_t module);
static void (*rt_module_unload_hook)(rt_module_t module);

/**
 * @addtogroup Hook
 */
D
dzzxzz 已提交
363

D
dogandog 已提交
364
/**@{*/
qiuyiuestc's avatar
qiuyiuestc 已提交
365 366 367 368 369 370 371 372 373

/**
 * This function will set a hook function, which will be invoked when module
 * be loaded to system.
 *
 * @param hook the hook function
 */
void rt_module_load_sethook(void (*hook)(rt_module_t module))
{
374
    rt_module_load_hook = hook;
qiuyiuestc's avatar
qiuyiuestc 已提交
375 376 377 378 379 380 381 382 383 384
}

/**
 * This function will set a hook function, which will be invoked when module
 * be unloaded from system.
 *
 * @param hook the hook function
 */
void rt_module_unload_sethook(void (*hook)(rt_module_t module))
{
385
    rt_module_unload_hook = hook;
qiuyiuestc's avatar
qiuyiuestc 已提交
386 387
}

D
dogandog 已提交
388
/**@}*/
qiuyiuestc's avatar
qiuyiuestc 已提交
389 390
#endif

391 392
static struct rt_module *_load_shared_object(const char *name,
                                             void       *module_ptr)
qiuyiuestc's avatar
qiuyiuestc 已提交
393
{
394
    rt_module_t module = RT_NULL;
395
    rt_bool_t linked   = RT_FALSE;
396
    rt_uint32_t index, module_size = 0;
397 398
    Elf32_Addr vstart_addr, vend_addr;
    rt_bool_t has_vstart;
399 400 401

    RT_ASSERT(module_ptr != RT_NULL);

402
    if (rt_memcmp(elf_module->e_ident, RTMMAG, SELFMAG) == 0)
403 404 405 406
    {
        /* rtmlinker finished */
        linked = RT_TRUE;
    }
407

408
    /* get the ELF image size */
409 410
    has_vstart = RT_FALSE;
    vstart_addr = vend_addr = RT_NULL;
411 412
    for (index = 0; index < elf_module->e_phnum; index++)
    {
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457
        if (phdr[index].p_type != PT_LOAD)
            continue;

        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("LOAD segment: %d, 0x%p, 0x%08x\n",
                                       index, phdr[index].p_vaddr, phdr[index].p_memsz));

        if (phdr[index].p_memsz < phdr[index].p_filesz)
        {
            rt_kprintf("invalid elf: segment %d: p_memsz: %d, p_filesz: %d\n",
                       index, phdr[index].p_memsz, phdr[index].p_filesz);
            return RT_NULL;
        }
        if (!has_vstart)
        {
            vstart_addr = phdr[index].p_vaddr;
            vend_addr = phdr[index].p_vaddr + phdr[index].p_memsz;
            has_vstart = RT_TRUE;
            if (vend_addr < vstart_addr)
            {
                rt_kprintf("invalid elf: segment %d: p_vaddr: %d, p_memsz: %d\n",
                           index, phdr[index].p_vaddr, phdr[index].p_memsz);
                return RT_NULL;
            }
        }
        else
        {
            if (phdr[index].p_vaddr < vend_addr)
            {
                rt_kprintf("invalid elf: segment should be sorted and not overlapped\n");
                return RT_NULL;
            }
            if (phdr[index].p_vaddr > vend_addr + 16)
            {
                /* There should not be too much padding in the object files. */
                rt_kprintf("warning: too much padding before segment %d\n", index);
            }

            vend_addr = phdr[index].p_vaddr + phdr[index].p_memsz;
            if (vend_addr < phdr[index].p_vaddr)
            {
                rt_kprintf("invalid elf: "
                           "segment %d address overflow\n", index);
                return RT_NULL;
            }
        }
458 459
    }

460 461 462 463 464
    module_size = vend_addr - vstart_addr;

    RT_DEBUG_LOG(RT_DEBUG_MODULE, ("module size: %d, vstart_addr: 0x%p\n",
                                   module_size, vstart_addr));

465 466
    if (module_size == 0)
    {
467
        rt_kprintf("Module: size error\n");
468

469
        return RT_NULL;
470
    }
471 472

    /* allocate module */
473 474 475 476
    module = (struct rt_module *)rt_object_allocate(RT_Object_Class_Module,
                                                    name);
    if (!module)
        return RT_NULL;
477

478 479
    module->vstart_addr = vstart_addr;

480
    module->nref = 0;
481

482 483 484 485
    /* allocate module space */
    module->module_space = rt_malloc(module_size);
    if (module->module_space == RT_NULL)
    {
486
        rt_kprintf("Module: allocate space failed.\n");
487 488 489 490 491 492
        rt_object_delete(&(module->parent));

        return RT_NULL;
    }

    /* zero all space */
493
    rt_memset(module->module_space, 0, module_size);
494 495 496 497 498

    for (index = 0; index < elf_module->e_phnum; index++)
    {
        if (phdr[index].p_type == PT_LOAD)
        {
499
            rt_memcpy(module->module_space + phdr[index].p_vaddr - vstart_addr,
500 501
                      (rt_uint8_t *)elf_module + phdr[index].p_offset,
                      phdr[index].p_filesz);
502 503
        }
    }
504 505

    /* set module entry */
506
    module->module_entry = module->module_space
507
                           + elf_module->e_entry - vstart_addr;
508

509 510 511 512 513 514 515 516
    /* handle relocation section */
    for (index = 0; index < elf_module->e_shnum; index ++)
    {
        rt_uint32_t i, nr_reloc;
        Elf32_Sym *symtab;
        Elf32_Rel *rel;
        rt_uint8_t *strtab;
        static rt_bool_t unsolved = RT_FALSE;
517

518 519
        if (!IS_REL(shdr[index]))
            continue;
520 521 522 523 524

        /* get relocate item */
        rel = (Elf32_Rel *)((rt_uint8_t *)module_ptr + shdr[index].sh_offset);

        /* locate .rel.plt and .rel.dyn section */
525 526 527
        symtab = (Elf32_Sym *)((rt_uint8_t *)module_ptr +
                               shdr[shdr[index].sh_link].sh_offset);
        strtab = (rt_uint8_t *)module_ptr +
528
                 shdr[shdr[shdr[index].sh_link].sh_link].sh_offset;
529
        nr_reloc = (rt_uint32_t)(shdr[index].sh_size / sizeof(Elf32_Rel));
530 531 532 533 534 535

        /* relocate every items */
        for (i = 0; i < nr_reloc; i ++)
        {
            Elf32_Sym *sym = &symtab[ELF32_R_SYM(rel->r_info)];

536 537 538
            RT_DEBUG_LOG(RT_DEBUG_MODULE, ("relocate symbol %s shndx %d\n",
                                           strtab + sym->st_name,
                                           sym->st_shndx));
539

540
            if ((sym->st_shndx != SHT_NULL) ||
541 542 543 544
                (ELF_ST_BIND(sym->st_info) == STB_LOCAL)
#ifdef MODULE_USING_386
                || ( (ELF_ST_BIND(sym->st_info) == STB_GLOBAL) && (ELF_ST_TYPE(sym->st_info) == STT_OBJECT) )
#endif
545
               )
546
            {
547
                rt_module_arm_relocate(module, rel,
548 549 550
                                       (Elf32_Addr)(module->module_space
                                                    + sym->st_value
                                                    - vstart_addr));
551
            }
552
            else if (!linked)
553 554 555
            {
                Elf32_Addr addr;

556 557
                RT_DEBUG_LOG(RT_DEBUG_MODULE, ("relocate symbol: %s\n",
                                               strtab + sym->st_name));
558 559 560 561 562

                /* need to resolve symbol in kernel symbol table */
                addr = rt_module_symbol_find((const char *)(strtab + sym->st_name));
                if (addr == 0)
                {
563
                    rt_kprintf("Module: can't find %s in kernel symbol table\n",
564
                               strtab + sym->st_name);
565
                    unsolved = RT_TRUE;
566
                }
567 568 569 570 571 572 573 574 575 576 577
                else
                    rt_module_arm_relocate(module, rel, addr);
            }
            rel ++;
        }

        if (unsolved)
        {
            rt_object_delete(&(module->parent));

            return RT_NULL;
578
        }
579 580 581 582
    }

    /* construct module symbol table */
    for (index = 0; index < elf_module->e_shnum; index ++)
583
    {
584
        /* find .dynsym section */
585
        rt_uint8_t *shstrab;
586
        shstrab = (rt_uint8_t *)module_ptr +
587
                  shdr[elf_module->e_shstrndx].sh_offset;
588 589 590 591 592 593 594 595
        if (rt_strcmp((const char *)(shstrab + shdr[index].sh_name), ELF_DYNSYM) == 0)
            break;
    }

    /* found .dynsym section */
    if (index != elf_module->e_shnum)
    {
        int i, count = 0;
596
        Elf32_Sym  *symtab = RT_NULL;
597 598
        rt_uint8_t *strtab = RT_NULL;

599
        symtab = (Elf32_Sym *)((rt_uint8_t *)module_ptr + shdr[index].sh_offset);
600 601
        strtab = (rt_uint8_t *)module_ptr + shdr[shdr[index].sh_link].sh_offset;

602
        for (i = 0; i < shdr[index].sh_size / sizeof(Elf32_Sym); i++)
603
        {
604
            if ((ELF_ST_BIND(symtab[i].st_info) == STB_GLOBAL) &&
605 606 607 608 609
                (ELF_ST_TYPE(symtab[i].st_info) == STT_FUNC))
                count ++;
        }

        module->symtab = (struct rt_module_symtab *)rt_malloc
610
                         (count * sizeof(struct rt_module_symtab));
611
        module->nsym = count;
612
        for (i = 0, count = 0; i < shdr[index].sh_size / sizeof(Elf32_Sym); i++)
613 614
        {
            rt_size_t length;
615 616

            if ((ELF_ST_BIND(symtab[i].st_info) != STB_GLOBAL) ||
617 618
                (ELF_ST_TYPE(symtab[i].st_info) != STT_FUNC))
                continue;
619 620 621

            length = rt_strlen((const char *)(strtab + symtab[i].st_name)) + 1;

622
            module->symtab[count].addr =
623 624 625
                (void *)(module->module_space + symtab[i].st_value);
            module->symtab[count].name = rt_malloc(length);
            rt_memset((void *)module->symtab[count].name, 0, length);
626
            rt_memcpy((void *)module->symtab[count].name,
627 628
                      strtab + symtab[i].st_name,
                      length);
629
            count ++;
630
        }
631 632 633
    }

    return module;
634 635
}

636 637
static struct rt_module* _load_relocated_object(const char *name,
                                                void       *module_ptr)
638
{
639 640 641 642 643 644
    rt_uint32_t index, rodata_addr = 0, bss_addr = 0, data_addr = 0;
    rt_uint32_t module_addr = 0, module_size = 0;
    struct rt_module *module = RT_NULL;
    rt_uint8_t *ptr, *strtab, *shstrab;

    /* get the ELF image size */
645
    for (index = 0; index < elf_module->e_shnum; index ++)
646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674
    {
        /* text */
        if (IS_PROG(shdr[index]) && IS_AX(shdr[index]))
        {
            module_size += shdr[index].sh_size;
            module_addr = shdr[index].sh_addr;
        }
        /* rodata */
        if (IS_PROG(shdr[index]) && IS_ALLOC(shdr[index]))
        {
            module_size += shdr[index].sh_size;
        }
        /* data */
        if (IS_PROG(shdr[index]) && IS_AW(shdr[index]))
        {
            module_size += shdr[index].sh_size;
        }
        /* bss */
        if (IS_NOPROG(shdr[index]) && IS_AW(shdr[index]))
        {
            module_size += shdr[index].sh_size;
        }
    }

    /* no text, data and bss on image */
    if (module_size == 0)
        return RT_NULL;

    /* allocate module */
675
    module = (struct rt_module *)
676
             rt_object_allocate(RT_Object_Class_Module, (const char *)name);
677 678 679
    if (module == RT_NULL)
        return RT_NULL;

680 681
    module->vstart_addr = 0;

682 683 684 685
    /* allocate module space */
    module->module_space = rt_malloc(module_size);
    if (module->module_space == RT_NULL)
    {
686
        rt_kprintf("Module: allocate space failed.\n");
687 688 689 690 691 692 693 694 695 696
        rt_object_delete(&(module->parent));

        return RT_NULL;
    }

    /* zero all space */
    ptr = module->module_space;
    rt_memset(ptr, 0, module_size);

    /* load text and data section */
697
    for (index = 0; index < elf_module->e_shnum; index ++)
698 699 700 701
    {
        /* load text section */
        if (IS_PROG(shdr[index]) && IS_AX(shdr[index]))
        {
702 703 704
            rt_memcpy(ptr,
                      (rt_uint8_t *)elf_module + shdr[index].sh_offset,
                      shdr[index].sh_size);
705 706
            RT_DEBUG_LOG(RT_DEBUG_MODULE, ("load text 0x%x, size %d\n",
                                           ptr, shdr[index].sh_size));
707 708 709 710 711 712
            ptr += shdr[index].sh_size;
        }

        /* load rodata section */
        if (IS_PROG(shdr[index]) && IS_ALLOC(shdr[index]))
        {
713 714 715
            rt_memcpy(ptr,
                      (rt_uint8_t *)elf_module + shdr[index].sh_offset,
                      shdr[index].sh_size);
716
            rodata_addr = (rt_uint32_t)ptr;
717 718 719
            RT_DEBUG_LOG(RT_DEBUG_MODULE,
                         ("load rodata 0x%x, size %d, rodata 0x%x\n",
                          ptr, shdr[index].sh_size, *(rt_uint32_t *)data_addr));
720 721 722 723 724 725
            ptr += shdr[index].sh_size;
        }

        /* load data section */
        if (IS_PROG(shdr[index]) && IS_AW(shdr[index]))
        {
726 727 728
            rt_memcpy(ptr,
                      (rt_uint8_t *)elf_module + shdr[index].sh_offset,
                      shdr[index].sh_size);
729
            data_addr = (rt_uint32_t)ptr;
730 731 732
            RT_DEBUG_LOG(RT_DEBUG_MODULE,
                         ("load data 0x%x, size %d, data 0x%x\n",
                          ptr, shdr[index].sh_size, *(rt_uint32_t *)data_addr));
733 734 735 736 737 738 739 740
            ptr += shdr[index].sh_size;
        }

        /* load bss section */
        if (IS_NOPROG(shdr[index]) && IS_AW(shdr[index]))
        {
            rt_memset(ptr, 0, shdr[index].sh_size);
            bss_addr = (rt_uint32_t)ptr;
741 742
            RT_DEBUG_LOG(RT_DEBUG_MODULE, ("load bss 0x%x, size %d,\n",
                                           ptr, shdr[index].sh_size));
743 744 745 746
        }
    }

    /* set module entry */
747 748
    module->module_entry =
        (rt_uint8_t *)module->module_space + elf_module->e_entry - module_addr;
749 750 751 752 753 754 755

    /* handle relocation section */
    for (index = 0; index < elf_module->e_shnum; index ++)
    {
        rt_uint32_t i, nr_reloc;
        Elf32_Sym *symtab;
        Elf32_Rel *rel;
756

757 758
        if (!IS_REL(shdr[index]))
            continue;
759

760
        /* get relocate item */
761
        rel = (Elf32_Rel *)((rt_uint8_t *)module_ptr + shdr[index].sh_offset);
762 763

        /* locate .dynsym and .dynstr */
764
        symtab   = (Elf32_Sym *)((rt_uint8_t *)module_ptr +
765
                                 shdr[shdr[index].sh_link].sh_offset);
766
        strtab   = (rt_uint8_t *)module_ptr +
767
                   shdr[shdr[shdr[index].sh_link].sh_link].sh_offset;
768
        shstrab  = (rt_uint8_t *)module_ptr +
769
                   shdr[elf_module->e_shstrndx].sh_offset;
770
        nr_reloc = (rt_uint32_t)(shdr[index].sh_size / sizeof(Elf32_Rel));
771 772 773 774 775

        /* relocate every items */
        for (i = 0; i < nr_reloc; i ++)
        {
            Elf32_Sym *sym = &symtab[ELF32_R_SYM(rel->r_info)];
776

777 778
            RT_DEBUG_LOG(RT_DEBUG_MODULE, ("relocate symbol: %s\n",
                                           strtab + sym->st_name));
779 780 781

            if (sym->st_shndx != STN_UNDEF)
            {
782 783
                if ((ELF_ST_TYPE(sym->st_info) == STT_SECTION) ||
                    (ELF_ST_TYPE(sym->st_info) == STT_OBJECT))
784
                {
785
                    if (rt_strncmp((const char *)(shstrab +
786
                                                  shdr[sym->st_shndx].sh_name), ELF_RODATA, 8) == 0)
787 788
                    {
                        /* relocate rodata section */
789
                        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rodata\n"));
790
                        rt_module_arm_relocate(module, rel,
791
                                               (Elf32_Addr)(rodata_addr + sym->st_value));
792
                    }
793
                    else if (rt_strncmp((const char *)
794
                                        (shstrab + shdr[sym->st_shndx].sh_name), ELF_BSS, 5) == 0)
795 796
                    {
                        /* relocate bss section */
797
                        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("bss\n"));
798
                        rt_module_arm_relocate(module, rel,
799
                                               (Elf32_Addr)bss_addr + sym->st_value);
800
                    }
801
                    else if (rt_strncmp((const char *)(shstrab + shdr[sym->st_shndx].sh_name),
802
                                        ELF_DATA, 6) == 0)
803 804
                    {
                        /* relocate data section */
805
                        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("data\n"));
806
                        rt_module_arm_relocate(module, rel,
807
                                               (Elf32_Addr)data_addr + sym->st_value);
808 809 810
                    }
                }
            }
811
            else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC)
812 813
            {
                /* relocate function */
814 815 816 817 818
                rt_module_arm_relocate(module, rel,
                                       (Elf32_Addr)((rt_uint8_t *)
                                                    module->module_space
                                                    - module_addr
                                                    + sym->st_value));
819 820 821 822 823
            }
            else
            {
                Elf32_Addr addr;

824
                if (ELF32_R_TYPE(rel->r_info) != R_ARM_V4BX)
825
                {
826 827
                    RT_DEBUG_LOG(RT_DEBUG_MODULE, ("relocate symbol: %s\n",
                                                   strtab + sym->st_name));
828

829
                    /* need to resolve symbol in kernel symbol table */
830
                    addr = rt_module_symbol_find((const char *)(strtab + sym->st_name));
831 832 833
                    if (addr != (Elf32_Addr)RT_NULL)
                    {
                        rt_module_arm_relocate(module, rel, addr);
834 835
                        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("symbol addr 0x%x\n",
                                                       addr));
836 837
                    }
                    else
838
                        rt_kprintf("Module: can't find %s in kernel symbol table\n",
839
                                   strtab + sym->st_name);
840 841 842
                }
                else
                {
843
                    rt_module_arm_relocate(module, rel,
844
                                           (Elf32_Addr)((rt_uint8_t *)
845 846 847
                                                        module->module_space
                                                        - module_addr
                                                        + sym->st_value));
848 849 850 851 852 853 854
                }
            }
            rel ++;
        }
    }

    return module;
855 856
}

857
#define RT_MODULE_ARG_MAX    8
858
static int _rt_module_split_arg(char *cmd, rt_size_t length, char *argv[])
859 860 861 862 863 864 865
{
    int argc = 0;
    char *ptr = cmd;

    while ((ptr - cmd) < length)
    {
        /* strip bank and tab */
866
        while ((*ptr == ' ' || *ptr == '\t') && (ptr - cmd) < length)
867 868
            *ptr++ = '\0';
        /* check whether it's the end of line */
869
        if ((ptr - cmd) >= length) break;
870 871 872 873 874 875 876

        /* handle string with quote */
        if (*ptr == '"')
        {
            argv[argc++] = ++ptr;

            /* skip this string */
877
            while (*ptr != '"' && (ptr - cmd) < length)
878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897
                if (*ptr ++ == '\\')  ptr ++;
            if ((ptr - cmd) >= length) break;

            /* skip '"' */
            *ptr ++ = '\0';
        }
        else
        {
            argv[argc++] = ptr;
            while ((*ptr != ' ' && *ptr != '\t') && (ptr - cmd) < length)
                ptr ++;
        }

        if (argc >= RT_MODULE_ARG_MAX) break;
    }

    return argc;
}

/* module main thread entry */
898
static void module_main_entry(void *parameter)
899 900 901
{
    int argc;
    char *argv[RT_MODULE_ARG_MAX];
902
    typedef int (*main_func_t)(int argc, char **argv);
903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923

    rt_module_t module = (rt_module_t) parameter;
    if (module == RT_NULL)
        return;

    if (module->module_cmd_line == RT_NULL && module->module_cmd_size != 0)
        /* malloc for module_cmd_line failed. */
        return;

    /* FIXME: we should run some C++ initialize code before jump into the
     * entry. */

    if (module->module_cmd_line == RT_NULL)
    {
        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("run bare entry: 0x%p\n",
                                       module->module_entry));
        ((main_func_t)module->module_entry)(0, RT_NULL);
        return;
    }

    rt_memset(argv, 0x00, sizeof(argv));
924
    argc = _rt_module_split_arg((char *)module->module_cmd_line,
925 926 927 928 929 930 931 932 933 934 935 936
                                module->module_cmd_size, argv);
    if (argc == 0)
        return;

    RT_DEBUG_LOG(RT_DEBUG_MODULE, ("run main entry: 0x%p with %s\n",
                                   module->module_entry,
                                   module->module_cmd_line));
    /* do the main function */
    ((main_func_t)module->module_entry)(argc, argv);
    return;
}

937
/**
938
 * This function will load a module with a main function from memory and create a
939
 * main thread for it
940 941 942
 *
 * @param name the name of module, which shall be unique
 * @param module_ptr the memory address of module image
943
 * @argc the count of argument
944
 * @argd the argument data, which should be a
945 946 947
 *
 * @return the module object
 */
948 949
rt_module_t rt_module_do_main(const char *name,
                              void *module_ptr,
950
                              const char *cmd_line,
951
                              int line_size)
952
{
953 954 955 956
    rt_module_t module;

    RT_DEBUG_NOT_IN_INTERRUPT;

957
    RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_load: %s\n", name));
958 959

    /* check ELF header */
960 961
    if (rt_memcmp(elf_module->e_ident, RTMMAG, SELFMAG) != 0 &&
        rt_memcmp(elf_module->e_ident, ELFMAG, SELFMAG) != 0)
962
    {
963
        rt_kprintf("Module: magic error\n");
964 965 966 967 968

        return RT_NULL;
    }

    /* check ELF class */
969
    if (elf_module->e_ident[EI_CLASS] != ELFCLASS32)
970
    {
971
        rt_kprintf("Module: ELF class error\n");
972 973 974 975

        return RT_NULL;
    }

976
    if (elf_module->e_type == ET_REL)
977 978 979
    {
        module = _load_relocated_object(name, module_ptr);
    }
980
    else if (elf_module->e_type == ET_DYN)
981 982 983 984 985
    {
        module = _load_shared_object(name, module_ptr);
    }
    else
    {
986
        rt_kprintf("Module: unsupported elf type\n");
987 988 989 990

        return RT_NULL;
    }

991
    if (module == RT_NULL)
992 993 994 995
        return RT_NULL;

    /* init module object container */
    rt_module_init_object_container(module);
996

997 998 999
    if (line_size && cmd_line)
    {
        /* set module argument */
1000
        module->module_cmd_line = (rt_uint8_t *)rt_malloc(line_size + 1);
1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014
        if (module->module_cmd_line)
        {
            rt_memcpy(module->module_cmd_line, cmd_line, line_size);
            module->module_cmd_line[line_size] = '\0';
        }
        module->module_cmd_size = line_size;
    }
    else
    {
        /* initialize an empty command */
        module->module_cmd_line = RT_NULL;
        module->module_cmd_size = 0;
    }

1015 1016 1017 1018
    /* increase module reference count */
    module->nref ++;

    if (elf_module->e_entry != 0)
1019
    {
qiuyiuestc's avatar
qiuyiuestc 已提交
1020
#ifdef RT_USING_SLAB
1021 1022
        /* init module memory allocator */
        module->mem_list = RT_NULL;
qiuyiuestc's avatar
qiuyiuestc 已提交
1023

1024
        /* create page array */
B
Bernard Xiong 已提交
1025
        module->page_array =
1026
            (void *)rt_malloc(PAGE_COUNT_MAX * sizeof(struct rt_page_info));
1027
        module->page_cnt = 0;
1028 1029
#endif

1030
        /* create module thread */
1031
        module->module_thread = rt_thread_create(name,
1032 1033 1034
                                                 module_main_entry, module,
                                                 RT_USING_MODULE_STKSZ,
                                                 RT_USING_MODULE_PRIO, 10);
1035

1036 1037
        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("thread entry 0x%x\n",
                                       module->module_entry));
1038 1039 1040

        /* set module id */
        module->module_thread->module_id = (void *)module;
1041 1042 1043 1044
        module->parent.flag = RT_MODULE_FLAG_WITHENTRY;

        /* startup module thread */
        rt_thread_startup(module->module_thread);
1045
    }
1046 1047 1048 1049
    else
    {
        /* without entry point */
        module->parent.flag |= RT_MODULE_FLAG_WITHOUTENTRY;
1050
    }
qiuyiuestc's avatar
qiuyiuestc 已提交
1051

qiuyiuestc's avatar
qiuyiuestc 已提交
1052
#ifdef RT_USING_HOOK
1053 1054 1055 1056
    if (rt_module_load_hook != RT_NULL)
    {
        rt_module_load_hook(module);
    }
qiuyiuestc's avatar
qiuyiuestc 已提交
1057 1058
#endif

1059
    return module;
1060 1061
}

1062
/**
1063
 * This function will load a module from memory and create a thread for it
1064 1065 1066 1067 1068 1069
 *
 * @param name the name of module, which shall be unique
 * @param module_ptr the memory address of module image
 *
 * @return the module object
 */
1070
rt_module_t rt_module_load(const char *name, void *module_ptr)
1071
{
1072
    return rt_module_do_main(name, module_ptr, RT_NULL, 0);
1073 1074
}

1075 1076
#ifdef RT_USING_DFS
#include <dfs_posix.h>
qiuyiuestc's avatar
qiuyiuestc 已提交
1077

1078
static char *_module_name(const char *path)
qiuyiuestc's avatar
qiuyiuestc 已提交
1079
{
1080
    const char *first, *end, *ptr;
1081
    char *name;
qiuyiuestc's avatar
qiuyiuestc 已提交
1082
    int size;
1083

1084 1085 1086 1087 1088
    ptr   = (char *)path;
    first = ptr;
    end   = path + rt_strlen(path);

    while (*ptr != '\0')
qiuyiuestc's avatar
qiuyiuestc 已提交
1089
    {
1090 1091 1092 1093
        if (*ptr == '/')
            first = ptr + 1;
        if (*ptr == '.')
            end = ptr - 1;
1094

1095
        ptr ++;
qiuyiuestc's avatar
qiuyiuestc 已提交
1096 1097 1098 1099 1100 1101 1102 1103 1104 1105
    }

    size = end - first + 1;
    name = rt_malloc(size);
    rt_strncpy(name, first, size);
    name[size] = '\0';

    return name;
}

qiuyiuestc's avatar
qiuyiuestc 已提交
1106
/**
B
bernard.xiong@gmail.com 已提交
1107
 * This function will load a module from a file
qiuyiuestc's avatar
qiuyiuestc 已提交
1108
 *
B
bernard.xiong@gmail.com 已提交
1109
 * @param path the full path of application module
qiuyiuestc's avatar
qiuyiuestc 已提交
1110 1111 1112
 *
 * @return the module object
 */
D
dzzxzz 已提交
1113
rt_module_t rt_module_open(const char *path)
qiuyiuestc's avatar
qiuyiuestc 已提交
1114
{
1115 1116 1117 1118
    int fd, length;
    struct rt_module *module;
    struct stat s;
    char *buffer, *offset_ptr;
1119
    char *name;
1120 1121 1122 1123 1124 1125

    RT_DEBUG_NOT_IN_INTERRUPT;

    /* check parameters */
    RT_ASSERT(path != RT_NULL);

1126
    if (stat(path, &s) != 0)
1127
    {
1128
        rt_kprintf("Module: access %s failed\n", path);
1129 1130 1131 1132 1133 1134

        return RT_NULL;
    }
    buffer = (char *)rt_malloc(s.st_size);
    if (buffer == RT_NULL)
    {
1135
        rt_kprintf("Module: out of memory\n");
1136 1137 1138 1139 1140 1141 1142 1143

        return RT_NULL;
    }

    offset_ptr = buffer;
    fd = open(path, O_RDONLY, 0);
    if (fd < 0)
    {
1144
        rt_kprintf("Module: open %s failed\n", path);
1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163
        rt_free(buffer);

        return RT_NULL;
    }

    do
    {
        length = read(fd, offset_ptr, 4096);
        if (length > 0)
        {
            offset_ptr += length;
        }
    }while (length > 0);

    /* close fd */
    close(fd);

    if ((rt_uint32_t)offset_ptr - (rt_uint32_t)buffer != s.st_size)
    {
1164
        rt_kprintf("Module: read file failed\n");
1165 1166 1167 1168 1169
        rt_free(buffer);

        return RT_NULL;
    }

1170 1171
    name   = _module_name(path);
    module = rt_module_load(name, (void *)buffer);
1172
    rt_free(buffer);
qiuyiuestc's avatar
qiuyiuestc 已提交
1173
    rt_free(name);
1174 1175

    return module;
qiuyiuestc's avatar
qiuyiuestc 已提交
1176
}
qiuyiuestc's avatar
qiuyiuestc 已提交
1177

1178 1179 1180 1181
/**
 * This function will do a excutable program with main function and parameters.
 *
 * @param path the full path of application module
1182 1183
 * @param cmd_line the command line of program
 * @param size the size of command line of program
1184 1185 1186
 *
 * @return the module object
 */
1187
rt_module_t rt_module_exec_cmd(const char *path, const char *cmd_line, int size)
1188 1189 1190 1191 1192 1193
{
    struct stat s;
    int fd, length;
    char *name, *buffer, *offset_ptr;
    struct rt_module *module = RT_NULL;

1194
    name = buffer = RT_NULL;
1195 1196 1197 1198 1199 1200

    RT_DEBUG_NOT_IN_INTERRUPT;

    /* check parameters */
    RT_ASSERT(path != RT_NULL);

1201
    /* get file size */
1202
    if (stat(path, &s) != 0)
1203 1204 1205 1206 1207
    {
        rt_kprintf("Module: access %s failed\n", path);
        goto __exit;
    }

1208
    /* allocate buffer to save program */
1209 1210 1211 1212
    offset_ptr = buffer = (char *)rt_malloc(s.st_size);
    if (buffer == RT_NULL)
    {
        rt_kprintf("Module: out of memory\n");
1213
        goto __exit;
1214 1215 1216 1217 1218 1219
    }

    fd = open(path, O_RDONLY, 0);
    if (fd < 0)
    {
        rt_kprintf("Module: open %s failed\n", path);
1220
        goto __exit;
1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236
    }

    do
    {
        length = read(fd, offset_ptr, 4096);
        if (length > 0)
        {
            offset_ptr += length;
        }
    }while (length > 0);
    /* close fd */
    close(fd);

    if ((rt_uint32_t)offset_ptr - (rt_uint32_t)buffer != s.st_size)
    {
        rt_kprintf("Module: read file failed\n");
1237
        goto __exit;
1238 1239
    }

1240
    /* get module */
1241
    name   = _module_name(path);
1242
    /* execute module */
1243 1244 1245 1246 1247 1248 1249 1250 1251
    module = rt_module_do_main(name, (void *)buffer, cmd_line, size);

__exit:
    rt_free(buffer);
    rt_free(name);

    return module;
}

qiuyiuestc's avatar
qiuyiuestc 已提交
1252 1253
#if defined(RT_USING_FINSH)
#include <finsh.h>
1254
FINSH_FUNCTION_EXPORT_ALIAS(rt_module_open, exec, exec module from a file);
qiuyiuestc's avatar
qiuyiuestc 已提交
1255
#endif
1256

qiuyiuestc's avatar
qiuyiuestc 已提交
1257 1258
#endif

qiuyiuestc's avatar
qiuyiuestc 已提交
1259
/**
1260
 * This function will destroy a module and release its resource.
qiuyiuestc's avatar
qiuyiuestc 已提交
1261
 *
1262
 * @param module the module to be destroyed.
qiuyiuestc's avatar
qiuyiuestc 已提交
1263 1264 1265
 *
 * @return the operation status, RT_EOK on OK; -RT_ERROR on error
 */
1266
rt_err_t rt_module_destroy(rt_module_t module)
qiuyiuestc's avatar
qiuyiuestc 已提交
1267
{
1268 1269 1270 1271 1272 1273 1274 1275
    int i;
    struct rt_object *object;
    struct rt_list_node *list;

    RT_DEBUG_NOT_IN_INTERRUPT;

    /* check parameter */
    RT_ASSERT(module != RT_NULL);
1276
    RT_ASSERT(module->nref == 0);
1277

1278 1279
    RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_destroy: %8.*s\n",
                                   RT_NAME_MAX, module->parent.name));
1280 1281 1282 1283

    /* module has entry point */
    if (!(module->parent.flag & RT_MODULE_FLAG_WITHOUTENTRY))
    {
qiuyiuestc's avatar
qiuyiuestc 已提交
1284
#ifdef RT_USING_SEMAPHORE
1285
        /* delete semaphores */
1286
        list = &module->module_object[RT_Object_Class_Semaphore].object_list;
1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300
        while (list->next != list)
        {
            object = rt_list_entry(list->next, struct rt_object, list);
            if (rt_object_is_systemobject(object) == RT_TRUE)
            {
                /* detach static object */
                rt_sem_detach((rt_sem_t)object);
            }
            else
            {
                /* delete dynamic object */
                rt_sem_delete((rt_sem_t)object);
            }
        }
qiuyiuestc's avatar
qiuyiuestc 已提交
1301 1302 1303
#endif

#ifdef RT_USING_MUTEX
1304
        /* delete mutexs*/
1305
        list = &module->module_object[RT_Object_Class_Mutex].object_list;
1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319
        while (list->next != list)
        {
            object = rt_list_entry(list->next, struct rt_object, list);
            if (rt_object_is_systemobject(object) == RT_TRUE)
            {
                /* detach static object */
                rt_mutex_detach((rt_mutex_t)object);
            }
            else
            {
                /* delete dynamic object */
                rt_mutex_delete((rt_mutex_t)object);
            }
        }
qiuyiuestc's avatar
qiuyiuestc 已提交
1320 1321 1322
#endif

#ifdef RT_USING_EVENT
1323
        /* delete mailboxs */
1324
        list = &module->module_object[RT_Object_Class_Event].object_list;
1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338
        while (list->next != list)
        {
            object = rt_list_entry(list->next, struct rt_object, list);
            if (rt_object_is_systemobject(object) == RT_TRUE)
            {
                /* detach static object */
                rt_event_detach((rt_event_t)object);
            }
            else
            {
                /* delete dynamic object */
                rt_event_delete((rt_event_t)object);
            }
        }
qiuyiuestc's avatar
qiuyiuestc 已提交
1339 1340 1341
#endif

#ifdef RT_USING_MAILBOX
1342
        /* delete mailboxs */
1343
        list = &module->module_object[RT_Object_Class_MailBox].object_list;
1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357
        while (list->next != list)
        {
            object = rt_list_entry(list->next, struct rt_object, list);
            if (rt_object_is_systemobject(object) == RT_TRUE)
            {
                /* detach static object */
                rt_mb_detach((rt_mailbox_t)object);
            }
            else
            {
                /* delete dynamic object */
                rt_mb_delete((rt_mailbox_t)object);
            }
        }
qiuyiuestc's avatar
qiuyiuestc 已提交
1358 1359 1360
#endif

#ifdef RT_USING_MESSAGEQUEUE
1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376
        /* delete msgqueues */
        list = &module->module_object[RT_Object_Class_MessageQueue].object_list;
        while (list->next != list)
        {
            object = rt_list_entry(list->next, struct rt_object, list);
            if (rt_object_is_systemobject(object) == RT_TRUE)
            {
                /* detach static object */
                rt_mq_detach((rt_mq_t)object);
            }
            else
            {
                /* delete dynamic object */
                rt_mq_delete((rt_mq_t)object);
            }
        }
qiuyiuestc's avatar
qiuyiuestc 已提交
1377 1378 1379
#endif

#ifdef RT_USING_MEMPOOL
1380
        /* delete mempools */
1381
        list = &module->module_object[RT_Object_Class_MemPool].object_list;
1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395
        while (list->next != list)
        {
            object = rt_list_entry(list->next, struct rt_object, list);
            if (rt_object_is_systemobject(object) == RT_TRUE)
            {
                /* detach static object */
                rt_mp_detach((rt_mp_t)object);
            }
            else
            {
                /* delete dynamic object */
                rt_mp_delete((rt_mp_t)object);
            }
        }
qiuyiuestc's avatar
qiuyiuestc 已提交
1396 1397 1398
#endif

#ifdef RT_USING_DEVICE
1399
        /* delete devices */
1400
        list = &module->module_object[RT_Object_Class_Device].object_list;
1401 1402 1403 1404 1405
        while (list->next != list)
        {
            object = rt_list_entry(list->next, struct rt_object, list);
            rt_device_unregister((rt_device_t)object);
        }
qiuyiuestc's avatar
qiuyiuestc 已提交
1406 1407
#endif

1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423
        /* delete timers */
        list = &module->module_object[RT_Object_Class_Timer].object_list;
        while (list->next != list)
        {
            object = rt_list_entry(list->next, struct rt_object, list);
            if (rt_object_is_systemobject(object) == RT_TRUE)
            {
                /* detach static object */
                rt_timer_detach((rt_timer_t)object);
            }
            else
            {
                /* delete dynamic object */
                rt_timer_delete((rt_timer_t)object);
            }
        }
1424 1425 1426 1427 1428 1429

        /* delete command line */
        if (module->module_cmd_line != RT_NULL)
        {
            rt_free(module->module_cmd_line);
        }
1430
    }
qiuyiuestc's avatar
qiuyiuestc 已提交
1431

1432
#ifdef RT_USING_SLAB
1433 1434 1435
    if (module->page_cnt > 0)
    {
        struct rt_page_info *page = (struct rt_page_info *)module->page_array;
B
bernard.xiong@gmail.com 已提交
1436

1437
        rt_kprintf("Module: warning - memory still hasn't been free finished\n");
qiuyiuestc's avatar
qiuyiuestc 已提交
1438

1439
        while (module->page_cnt != 0)
1440 1441 1442 1443
        {
            rt_module_free_page(module, page[0].page_ptr, page[0].npage);
        }
    }
1444
#endif
D
dzzxzz 已提交
1445

1446 1447
    /* release module space memory */
    rt_free(module->module_space);
qiuyiuestc's avatar
qiuyiuestc 已提交
1448

1449
    /* release module symbol table */
1450
    for (i = 0; i < module->nsym; i ++)
1451
    {
1452
        rt_free((void *)module->symtab[i].name);
1453
    }
1454 1455
    if (module->symtab != RT_NULL)
        rt_free(module->symtab);
qiuyiuestc's avatar
qiuyiuestc 已提交
1456

qiuyiuestc's avatar
qiuyiuestc 已提交
1457
#ifdef RT_USING_SLAB
1458
    if (module->page_array != RT_NULL)
1459
        rt_free(module->page_array);
qiuyiuestc's avatar
qiuyiuestc 已提交
1460
#endif
qiuyiuestc's avatar
qiuyiuestc 已提交
1461

1462 1463
    /* delete module object */
    rt_object_delete((rt_object_t)module);
qiuyiuestc's avatar
qiuyiuestc 已提交
1464

1465
    return RT_EOK;
qiuyiuestc's avatar
qiuyiuestc 已提交
1466 1467
}

1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482
/**
 * This function will unload a module from memory and release resources
 *
 * @param module the module to be unloaded
 *
 * @return the operation status, RT_EOK on OK; -RT_ERROR on error
 */
rt_err_t rt_module_unload(rt_module_t module)
{
    struct rt_object *object;
    struct rt_list_node *list;

    RT_DEBUG_NOT_IN_INTERRUPT;

    /* check parameter */
1483 1484
    if (module == RT_NULL)
        return -RT_ERROR;
1485

1486
    rt_enter_critical();
1487 1488
    if (!(module->parent.flag & RT_MODULE_FLAG_WITHOUTENTRY))
    {
1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510
        /* delete all sub-threads */
        list = &module->module_object[RT_Object_Class_Thread].object_list;
        while (list->next != list)
        {
            object = rt_list_entry(list->next, struct rt_object, list);
            if (rt_object_is_systemobject(object) == RT_TRUE)
            {
                /* detach static object */
                rt_thread_detach((rt_thread_t)object);
            }
            else
            {
                /* delete dynamic object */
                rt_thread_delete((rt_thread_t)object);
            }
        }

        /* delete the main thread of module */
        if (module->module_thread != RT_NULL)
        {
            rt_thread_delete(module->module_thread);
        }
1511
    }
1512
    rt_exit_critical();
1513 1514

#ifdef RT_USING_HOOK
1515 1516 1517 1518
    if (rt_module_unload_hook != RT_NULL)
    {
        rt_module_unload_hook(module);
    }
1519 1520
#endif

1521
    return RT_EOK;
1522 1523
}

qiuyiuestc's avatar
qiuyiuestc 已提交
1524 1525 1526 1527 1528 1529 1530
/**
 * This function will find the specified module.
 *
 * @param name the name of module finding
 *
 * @return the module
 */
D
dzzxzz 已提交
1531
rt_module_t rt_module_find(const char *name)
qiuyiuestc's avatar
qiuyiuestc 已提交
1532
{
1533 1534 1535
    struct rt_object_information *information;
    struct rt_object *object;
    struct rt_list_node *node;
qiuyiuestc's avatar
qiuyiuestc 已提交
1536

1537
    RT_DEBUG_NOT_IN_INTERRUPT;
1538

1539 1540
    /* enter critical */
    rt_enter_critical();
B
bernard.xiong 已提交
1541

1542
    /* try to find device object */
1543 1544
    information = rt_object_get_information(RT_Object_Class_Module);
    RT_ASSERT(information != RT_NULL);
1545
    for (node = information->object_list.next;
1546 1547
         node != &(information->object_list);
         node = node->next)
1548 1549 1550 1551 1552 1553
    {
        object = rt_list_entry(node, struct rt_object, list);
        if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0)
        {
            /* leave critical */
            rt_exit_critical();
B
bernard.xiong 已提交
1554

1555 1556 1557
            return (rt_module_t)object;
        }
    }
B
bernard.xiong 已提交
1558

1559 1560
    /* leave critical */
    rt_exit_critical();
B
bernard.xiong 已提交
1561

1562 1563
    /* not found */
    return RT_NULL;
qiuyiuestc's avatar
qiuyiuestc 已提交
1564
}
1565
RTM_EXPORT(rt_module_find);
qiuyiuestc's avatar
qiuyiuestc 已提交
1566

qiuyiuestc's avatar
qiuyiuestc 已提交
1567 1568 1569 1570 1571 1572 1573 1574 1575
#ifdef RT_USING_SLAB
/*
 * This function will allocate the numbers page with specified size
 * in page memory.
 *
 * @param size the size of memory to be allocated.
 * @note this function is used for RT-Thread Application Module
 */
static void *rt_module_malloc_page(rt_size_t npages)
qiuyiuestc's avatar
qiuyiuestc 已提交
1576
{
1577 1578
    void *chunk;
    struct rt_page_info *page;
1579
    rt_module_t self_module;
1580

1581 1582
    self_module = rt_module_self();
    RT_ASSERT(self_module != RT_NULL);
qiuyiuestc's avatar
qiuyiuestc 已提交
1583

1584 1585 1586
    chunk = rt_page_alloc(npages);
    if (chunk == RT_NULL)
        return RT_NULL;
1587

1588 1589
    page = (struct rt_page_info *)self_module->page_array;
    page[self_module->page_cnt].page_ptr = chunk;
1590
    page[self_module->page_cnt].npage    = npages;
1591
    self_module->page_cnt ++;
qiuyiuestc's avatar
qiuyiuestc 已提交
1592

1593
    RT_ASSERT(self_module->page_cnt <= PAGE_COUNT_MAX);
1594 1595
    RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_malloc_page 0x%x %d\n",
                                   chunk, npages));
D
dzzxzz 已提交
1596

1597
    return chunk;
qiuyiuestc's avatar
qiuyiuestc 已提交
1598
}
qiuyiuestc's avatar
qiuyiuestc 已提交
1599

qiuyiuestc's avatar
qiuyiuestc 已提交
1600
/*
D
dzzxzz 已提交
1601
 * This function will release the previously allocated memory page
qiuyiuestc's avatar
qiuyiuestc 已提交
1602 1603 1604 1605
 * by rt_malloc_page.
 *
 * @param page_ptr the page address to be released.
 * @param npages the number of page shall be released.
B
bernard.xiong@gmail.com 已提交
1606
 *
qiuyiuestc's avatar
qiuyiuestc 已提交
1607 1608
 * @note this function is used for RT-Thread Application Module
 */
1609 1610 1611
static void rt_module_free_page(rt_module_t module,
                                void       *page_ptr,
                                rt_size_t   npages)
qiuyiuestc's avatar
qiuyiuestc 已提交
1612
{
1613 1614
    int i, index;
    struct rt_page_info *page;
1615
    rt_module_t self_module;
1616

1617 1618
    self_module = rt_module_self();
    RT_ASSERT(self_module != RT_NULL);
1619

1620 1621
    RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_free_page 0x%x %d\n",
                                   page_ptr, npages));
1622 1623
    rt_page_free(page_ptr, npages);

1624
    page = (struct rt_page_info *)module->page_array;
1625

1626
    for (i = 0; i < module->page_cnt; i ++)
1627 1628 1629 1630 1631
    {
        if (page[i].page_ptr == page_ptr)
        {
            if (page[i].npage == npages + 1)
            {
1632 1633 1634
                page[i].page_ptr +=
                    npages * RT_MM_PAGE_SIZE / sizeof(rt_uint32_t);
                page[i].npage    -= npages;
1635
            }
1636
            else if (page[i].npage == npages)
1637
            {
1638
                for (index = i; index < module->page_cnt - 1; index ++)
1639 1640
                {
                    page[index].page_ptr = page[index + 1].page_ptr;
1641
                    page[index].npage    = page[index + 1].npage;
1642 1643
                }
                page[module->page_cnt - 1].page_ptr = RT_NULL;
1644
                page[module->page_cnt - 1].npage    = 0;
1645

1646
                module->page_cnt --;
1647 1648 1649
            }
            else
                RT_ASSERT(RT_FALSE);
1650
            self_module->page_cnt --;
1651 1652 1653 1654 1655

            return;
        }
    }

1656
    /* should not get here */
1657
    RT_ASSERT(RT_FALSE);
qiuyiuestc's avatar
qiuyiuestc 已提交
1658
}
qiuyiuestc's avatar
qiuyiuestc 已提交
1659

1660 1661 1662
/**
 * rt_module_malloc - allocate memory block in free list
 */
qiuyiuestc's avatar
qiuyiuestc 已提交
1663 1664
void *rt_module_malloc(rt_size_t size)
{
1665 1666 1667 1668
    struct rt_mem_head *b, *n, *up;
    struct rt_mem_head **prev;
    rt_uint32_t npage;
    rt_size_t nunits;
1669
    rt_module_t self_module;
1670

1671 1672
    self_module = rt_module_self();
    RT_ASSERT(self_module != RT_NULL);
1673

1674
    RT_DEBUG_NOT_IN_INTERRUPT;
1675

1676
    nunits = (size + sizeof(struct rt_mem_head) - 1) /
1677 1678
             sizeof(struct rt_mem_head)
             + 1;
qiuyiuestc's avatar
qiuyiuestc 已提交
1679

1680 1681
    RT_ASSERT(size != 0);
    RT_ASSERT(nunits != 0);
qiuyiuestc's avatar
qiuyiuestc 已提交
1682

1683
    rt_sem_take(&mod_sem, RT_WAITING_FOREVER);
qiuyiuestc's avatar
qiuyiuestc 已提交
1684

1685
    for (prev = (struct rt_mem_head **)&self_module->mem_list;
1686 1687
         (b = *prev) != RT_NULL;
         prev = &(b->next))
1688 1689 1690 1691
    {
        if (b->size > nunits)
        {
            /* split memory */
1692
            n       = b + nunits;
1693 1694 1695
            n->next = b->next;
            n->size = b->size - nunits;
            b->size = nunits;
1696
            *prev   = n;
qiuyiuestc's avatar
qiuyiuestc 已提交
1697

1698 1699
            RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_malloc 0x%x, %d\n",
                                           b + 1, size));
1700
            rt_sem_release(&mod_sem);
D
dzzxzz 已提交
1701

1702 1703
            return (void *)(b + 1);
        }
qiuyiuestc's avatar
qiuyiuestc 已提交
1704

1705 1706 1707 1708
        if (b->size == nunits)
        {
            /* this node fit, remove this node */
            *prev = b->next;
qiuyiuestc's avatar
qiuyiuestc 已提交
1709

1710 1711
            RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_malloc 0x%x, %d\n",
                                           b + 1, size));
B
bernard.xiong@gmail.com 已提交
1712

1713
            rt_sem_release(&mod_sem);
D
dzzxzz 已提交
1714

1715 1716 1717
            return (void *)(b + 1);
        }
    }
qiuyiuestc's avatar
qiuyiuestc 已提交
1718

1719
    /* allocate pages from system heap */
1720
    npage = (size + sizeof(struct rt_mem_head) + RT_MM_PAGE_SIZE - 1) /
1721
            RT_MM_PAGE_SIZE;
1722 1723
    if ((up = (struct rt_mem_head *)rt_module_malloc_page(npage)) == RT_NULL)
        return RT_NULL;
qiuyiuestc's avatar
qiuyiuestc 已提交
1724

1725
    up->size = npage * RT_MM_PAGE_SIZE / sizeof(struct rt_mem_head);
B
bernard.xiong@gmail.com 已提交
1726

1727
    for (prev = (struct rt_mem_head **)&self_module->mem_list;
1728 1729
         (b = *prev) != RT_NULL;
         prev = &(b->next))
1730 1731 1732 1733
    {
        if (b > up + up->size)
            break;
    }
qiuyiuestc's avatar
qiuyiuestc 已提交
1734

1735
    up->next = b;
1736
    *prev    = up;
qiuyiuestc's avatar
qiuyiuestc 已提交
1737

1738
    rt_sem_release(&mod_sem);
D
dzzxzz 已提交
1739

1740
    return rt_module_malloc(size);
qiuyiuestc's avatar
qiuyiuestc 已提交
1741 1742
}

1743 1744 1745
/**
 * rt_module_free - free memory block in free list
 */
qiuyiuestc's avatar
qiuyiuestc 已提交
1746 1747
void rt_module_free(rt_module_t module, void *addr)
{
1748 1749 1750 1751 1752 1753
    struct rt_mem_head *b, *n, *r;
    struct rt_mem_head **prev;

    RT_DEBUG_NOT_IN_INTERRUPT;

    RT_ASSERT(addr);
1754
    RT_ASSERT((((rt_uint32_t)addr) & (sizeof(struct rt_mem_head) - 1)) == 0);
1755

1756
    RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_free 0x%x\n", addr));
1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779

    rt_sem_take(&mod_sem, RT_WAITING_FOREVER);

    n = (struct rt_mem_head *)addr - 1;
    prev = (struct rt_mem_head **)&module->mem_list;

    while ((b = *prev) != RT_NULL)
    {
        RT_ASSERT(b->size > 0);
        RT_ASSERT(b > n || b + b->size <= n);

        if (b + b->size == n && ((rt_uint32_t)n % RT_MM_PAGE_SIZE != 0))
        {
            if (b + (b->size + n->size) == b->next)
            {
                b->size += b->next->size + n->size;
                b->next = b->next->next;
            }
            else
                b->size += n->size;

            if ((rt_uint32_t)b % RT_MM_PAGE_SIZE == 0)
            {
1780 1781
                int npage =
                    b->size * sizeof(struct rt_page_info) / RT_MM_PAGE_SIZE;
1782 1783 1784 1785
                if (npage > 0)
                {
                    if ((b->size * sizeof(struct rt_page_info) % RT_MM_PAGE_SIZE) != 0)
                    {
1786
                        rt_size_t nunits = npage *
1787 1788
                                           RT_MM_PAGE_SIZE /
                                           sizeof(struct rt_mem_head);
1789
                        /* split memory */
1790
                        r       = b + nunits;
1791 1792
                        r->next = b->next;
                        r->size = b->size - nunits;
1793
                        *prev   = r;
1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816
                    }
                    else
                    {
                        *prev = b->next;
                    }

                    rt_module_free_page(module, b, npage);
                }
            }

            /* unlock */
            rt_sem_release(&mod_sem);

            return;
        }

        if (b == n + n->size)
        {
            n->size = b->size + n->size;
            n->next = b->next;

            if ((rt_uint32_t)n % RT_MM_PAGE_SIZE == 0)
            {
1817 1818
                int npage =
                    n->size * sizeof(struct rt_page_info) / RT_MM_PAGE_SIZE;
1819 1820 1821 1822
                if (npage > 0)
                {
                    if ((n->size * sizeof(struct rt_page_info) % RT_MM_PAGE_SIZE) != 0)
                    {
1823
                        rt_size_t nunits = npage *
1824 1825
                                           RT_MM_PAGE_SIZE /
                                           sizeof(struct rt_mem_head);
1826
                        /* split memory */
1827
                        r       = n + nunits;
1828 1829
                        r->next = n->next;
                        r->size = n->size - nunits;
1830
                        *prev   = r;
1831
                    }
1832 1833
                    else
                        *prev = n->next;
1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861

                    rt_module_free_page(module, n, npage);
                }
            }
            else
            {
                *prev = n;
            }

            /* unlock */
            rt_sem_release(&mod_sem);

            return;
        }
        if (b > n + n->size)
            break;

        prev = &(b->next);
    }

    if ((rt_uint32_t)n % RT_MM_PAGE_SIZE == 0)
    {
        int npage = n->size * sizeof(struct rt_page_info) / RT_MM_PAGE_SIZE;
        if (npage > 0)
        {
            rt_module_free_page(module, n, npage);
            if (n->size % RT_MM_PAGE_SIZE != 0)
            {
1862 1863
                rt_size_t nunits =
                    npage * RT_MM_PAGE_SIZE / sizeof(struct rt_mem_head);
1864
                /* split memory */
1865
                r       = n + nunits;
1866 1867
                r->next = b;
                r->size = n->size - nunits;
1868
                *prev   = r;
1869 1870 1871 1872 1873 1874 1875 1876 1877 1878
            }
            else
            {
                *prev = b;
            }
        }
    }
    else
    {
        n->next = b;
1879
        *prev   = n;
1880 1881 1882 1883
    }

    /* unlock */
    rt_sem_release(&mod_sem);
qiuyiuestc's avatar
qiuyiuestc 已提交
1884 1885
}

1886 1887 1888
/**
 * rt_module_realloc - realloc memory block in free list
 */
qiuyiuestc's avatar
qiuyiuestc 已提交
1889 1890
void *rt_module_realloc(void *ptr, rt_size_t size)
{
1891 1892
    struct rt_mem_head *b, *p, *prev, *tmpp;
    rt_size_t nunits;
1893
    rt_module_t self_module;
1894

1895 1896
    self_module = rt_module_self();
    RT_ASSERT(self_module != RT_NULL);
1897 1898 1899 1900 1901 1902 1903

    RT_DEBUG_NOT_IN_INTERRUPT;

    if (!ptr)
        return rt_module_malloc(size);
    if (size == 0)
    {
1904
        rt_module_free(self_module, ptr);
1905 1906 1907 1908

        return RT_NULL;
    }

1909
    nunits = (size + sizeof(struct rt_mem_head) - 1) /
1910 1911
             sizeof(struct rt_mem_head)
             + 1;
1912 1913 1914 1915 1916 1917 1918 1919 1920
    b = (struct rt_mem_head *)ptr - 1;

    if (nunits <= b->size)
    {
        /* new size is smaller or equal then before */
        if (nunits == b->size)
            return ptr;
        else
        {
1921
            p       = b + nunits;
1922 1923
            p->size = b->size - nunits;
            b->size = nunits;
1924
            rt_module_free(self_module, (void *)(p + 1));
1925 1926 1927 1928 1929 1930 1931

            return (void *)(b + 1);
        }
    }
    else
    {
        /* more space then required */
1932
        prev = (struct rt_mem_head *)self_module->mem_list;
1933 1934 1935 1936
        for (p = prev->next;
             p != (b->size + b) && p != RT_NULL;
             prev = p, p = p->next)
        {
1937
            break;
1938
        }
1939

1940
        /* available block after ap in freelist */
1941 1942 1943
        if (p != RT_NULL &&
            (p->size >= (nunits - (b->size))) &&
            p == (b + b->size))
1944 1945
        {
            /* perfect match */
1946
            if (p->size == (nunits - (b->size)))
1947
            {
1948
                b->size    = nunits;
1949 1950
                prev->next = p->next;
            }
1951
            else  /* more space then required, split block */
1952 1953 1954
            {
                /* pointer to old header */
                tmpp = p;
1955
                p    = b + nunits;
1956 1957 1958

                /* restoring old pointer */
                p->next = tmpp->next;
1959

1960
                /* new size for p */
1961 1962
                p->size    = tmpp->size + b->size - nunits;
                b->size    = nunits;
1963 1964
                prev->next = p;
            }
1965
            self_module->mem_list = (void *)prev;
1966 1967 1968 1969 1970

            return (void *)(b + 1);
        }
        else /* allocate new memory and copy old data */
        {
1971 1972
            if ((p = rt_module_malloc(size)) == RT_NULL)
                return RT_NULL;
1973
            rt_memmove(p, (b + 1), ((b->size) * sizeof(struct rt_mem_head)));
1974
            rt_module_free(self_module, (void *)(b + 1));
1975 1976 1977 1978

            return (void *)(p);
        }
    }
qiuyiuestc's avatar
qiuyiuestc 已提交
1979
}
qiuyiuestc's avatar
qiuyiuestc 已提交
1980 1981 1982

#ifdef RT_USING_FINSH
#include <finsh.h>
1983

D
dzzxzz 已提交
1984
void list_memlist(const char *name)
qiuyiuestc's avatar
qiuyiuestc 已提交
1985
{
1986 1987 1988 1989 1990 1991 1992 1993
    rt_module_t module;
    struct rt_mem_head **prev;
    struct rt_mem_head *b;

    module = rt_module_find(name);
    if (module == RT_NULL)
        return;

1994
    for (prev = (struct rt_mem_head **)&module->mem_list;
1995 1996
         (b = *prev) != RT_NULL;
         prev = &(b->next))
1997 1998 1999
    {
        rt_kprintf("0x%x--%d\n", b, b->size * sizeof(struct rt_mem_head));
    }
qiuyiuestc's avatar
qiuyiuestc 已提交
2000 2001 2002
}
FINSH_FUNCTION_EXPORT(list_memlist, list module free memory information)

D
dzzxzz 已提交
2003
void list_mempage(const char *name)
qiuyiuestc's avatar
qiuyiuestc 已提交
2004
{
2005 2006 2007
    rt_module_t module;
    struct rt_page_info *page;
    int i;
qiuyiuestc's avatar
qiuyiuestc 已提交
2008

2009 2010 2011
    module = rt_module_find(name);
    if (module == RT_NULL)
        return;
qiuyiuestc's avatar
qiuyiuestc 已提交
2012

2013
    page = (struct rt_page_info *)module->page_array;
qiuyiuestc's avatar
qiuyiuestc 已提交
2014

2015
    for (i = 0; i < module->page_cnt; i ++)
2016 2017 2018
    {
        rt_kprintf("0x%x--%d\n", page[i].page_ptr, page[i].npage);
    }
qiuyiuestc's avatar
qiuyiuestc 已提交
2019 2020
}
FINSH_FUNCTION_EXPORT(list_mempage, list module using memory page information)
2021
#endif /* RT_USING_FINSH */
qiuyiuestc's avatar
qiuyiuestc 已提交
2022

2023
#endif /* RT_USING_SLAB */
qiuyiuestc's avatar
qiuyiuestc 已提交
2024 2025

#endif