xref: /nrf52832-nimble/rt-thread/components/libc/libdl/dlelf.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 "dlmodule.h"
12*10465441SEvalZero #include "dlelf.h"
13*10465441SEvalZero 
14*10465441SEvalZero #define DBG_SECTION_NAME    "DLMD"
15*10465441SEvalZero #define DBG_ENABLE          // enable debug macro
16*10465441SEvalZero #define DBG_LEVEL           DBG_INFO
17*10465441SEvalZero #define DBG_COLOR
18*10465441SEvalZero #include <rtdbg.h>          // must after of DEBUG_ENABLE or some other options
19*10465441SEvalZero 
dlmodule_load_shared_object(struct rt_dlmodule * module,void * module_ptr)20*10465441SEvalZero rt_err_t dlmodule_load_shared_object(struct rt_dlmodule* module, void *module_ptr)
21*10465441SEvalZero {
22*10465441SEvalZero     rt_bool_t linked   = RT_FALSE;
23*10465441SEvalZero     rt_uint32_t index, module_size = 0;
24*10465441SEvalZero     Elf32_Addr vstart_addr, vend_addr;
25*10465441SEvalZero     rt_bool_t has_vstart;
26*10465441SEvalZero 
27*10465441SEvalZero     RT_ASSERT(module_ptr != RT_NULL);
28*10465441SEvalZero 
29*10465441SEvalZero     if (rt_memcmp(elf_module->e_ident, RTMMAG, SELFMAG) == 0)
30*10465441SEvalZero     {
31*10465441SEvalZero         /* rtmlinker finished */
32*10465441SEvalZero         linked = RT_TRUE;
33*10465441SEvalZero     }
34*10465441SEvalZero 
35*10465441SEvalZero     /* get the ELF image size */
36*10465441SEvalZero     has_vstart = RT_FALSE;
37*10465441SEvalZero     vstart_addr = vend_addr = RT_NULL;
38*10465441SEvalZero     for (index = 0; index < elf_module->e_phnum; index++)
39*10465441SEvalZero     {
40*10465441SEvalZero         if (phdr[index].p_type != PT_LOAD)
41*10465441SEvalZero             continue;
42*10465441SEvalZero 
43*10465441SEvalZero         LOG_D("LOAD segment: %d, 0x%p, 0x%08x", index, phdr[index].p_vaddr, phdr[index].p_memsz);
44*10465441SEvalZero 
45*10465441SEvalZero         if (phdr[index].p_memsz < phdr[index].p_filesz)
46*10465441SEvalZero         {
47*10465441SEvalZero             rt_kprintf("invalid elf: segment %d: p_memsz: %d, p_filesz: %d\n",
48*10465441SEvalZero                        index, phdr[index].p_memsz, phdr[index].p_filesz);
49*10465441SEvalZero             return RT_NULL;
50*10465441SEvalZero         }
51*10465441SEvalZero         if (!has_vstart)
52*10465441SEvalZero         {
53*10465441SEvalZero             vstart_addr = phdr[index].p_vaddr;
54*10465441SEvalZero             vend_addr = phdr[index].p_vaddr + phdr[index].p_memsz;
55*10465441SEvalZero             has_vstart = RT_TRUE;
56*10465441SEvalZero             if (vend_addr < vstart_addr)
57*10465441SEvalZero             {
58*10465441SEvalZero                 rt_kprintf("invalid elf: segment %d: p_vaddr: %d, p_memsz: %d\n",
59*10465441SEvalZero                            index, phdr[index].p_vaddr, phdr[index].p_memsz);
60*10465441SEvalZero                 return RT_NULL;
61*10465441SEvalZero             }
62*10465441SEvalZero         }
63*10465441SEvalZero         else
64*10465441SEvalZero         {
65*10465441SEvalZero             if (phdr[index].p_vaddr < vend_addr)
66*10465441SEvalZero             {
67*10465441SEvalZero                 rt_kprintf("invalid elf: segment should be sorted and not overlapped\n");
68*10465441SEvalZero                 return RT_NULL;
69*10465441SEvalZero             }
70*10465441SEvalZero             if (phdr[index].p_vaddr > vend_addr + 16)
71*10465441SEvalZero             {
72*10465441SEvalZero                 /* There should not be too much padding in the object files. */
73*10465441SEvalZero                 LOG_W("warning: too much padding before segment %d", index);
74*10465441SEvalZero             }
75*10465441SEvalZero 
76*10465441SEvalZero             vend_addr = phdr[index].p_vaddr + phdr[index].p_memsz;
77*10465441SEvalZero             if (vend_addr < phdr[index].p_vaddr)
78*10465441SEvalZero             {
79*10465441SEvalZero                 rt_kprintf("invalid elf: "
80*10465441SEvalZero                            "segment %d address overflow\n", index);
81*10465441SEvalZero                 return RT_NULL;
82*10465441SEvalZero             }
83*10465441SEvalZero         }
84*10465441SEvalZero     }
85*10465441SEvalZero 
86*10465441SEvalZero     module_size = vend_addr - vstart_addr;
87*10465441SEvalZero     LOG_D("module size: %d, vstart_addr: 0x%p", module_size, vstart_addr);
88*10465441SEvalZero     if (module_size == 0)
89*10465441SEvalZero     {
90*10465441SEvalZero         rt_kprintf("Module: size error\n");
91*10465441SEvalZero         return -RT_ERROR;
92*10465441SEvalZero     }
93*10465441SEvalZero 
94*10465441SEvalZero     module->vstart_addr = vstart_addr;
95*10465441SEvalZero     module->nref = 0;
96*10465441SEvalZero 
97*10465441SEvalZero     /* allocate module space */
98*10465441SEvalZero     module->mem_space = rt_malloc(module_size);
99*10465441SEvalZero     if (module->mem_space == RT_NULL)
100*10465441SEvalZero     {
101*10465441SEvalZero         rt_kprintf("Module: allocate space failed.\n");
102*10465441SEvalZero         return -RT_ERROR;
103*10465441SEvalZero     }
104*10465441SEvalZero     module->mem_size = module_size;
105*10465441SEvalZero 
106*10465441SEvalZero     /* zero all space */
107*10465441SEvalZero     rt_memset(module->mem_space, 0, module_size);
108*10465441SEvalZero     for (index = 0; index < elf_module->e_phnum; index++)
109*10465441SEvalZero     {
110*10465441SEvalZero         if (phdr[index].p_type == PT_LOAD)
111*10465441SEvalZero         {
112*10465441SEvalZero             rt_memcpy(module->mem_space + phdr[index].p_vaddr - vstart_addr,
113*10465441SEvalZero                       (rt_uint8_t *)elf_module + phdr[index].p_offset,
114*10465441SEvalZero                       phdr[index].p_filesz);
115*10465441SEvalZero         }
116*10465441SEvalZero     }
117*10465441SEvalZero 
118*10465441SEvalZero     /* set module entry */
119*10465441SEvalZero     module->entry_addr = module->mem_space + elf_module->e_entry - vstart_addr;
120*10465441SEvalZero 
121*10465441SEvalZero     /* handle relocation section */
122*10465441SEvalZero     for (index = 0; index < elf_module->e_shnum; index ++)
123*10465441SEvalZero     {
124*10465441SEvalZero         rt_uint32_t i, nr_reloc;
125*10465441SEvalZero         Elf32_Sym *symtab;
126*10465441SEvalZero         Elf32_Rel *rel;
127*10465441SEvalZero         rt_uint8_t *strtab;
128*10465441SEvalZero         static rt_bool_t unsolved = RT_FALSE;
129*10465441SEvalZero 
130*10465441SEvalZero         if (!IS_REL(shdr[index]))
131*10465441SEvalZero             continue;
132*10465441SEvalZero 
133*10465441SEvalZero         /* get relocate item */
134*10465441SEvalZero         rel = (Elf32_Rel *)((rt_uint8_t *)module_ptr + shdr[index].sh_offset);
135*10465441SEvalZero 
136*10465441SEvalZero         /* locate .rel.plt and .rel.dyn section */
137*10465441SEvalZero         symtab = (Elf32_Sym *)((rt_uint8_t *)module_ptr +
138*10465441SEvalZero                                shdr[shdr[index].sh_link].sh_offset);
139*10465441SEvalZero         strtab = (rt_uint8_t *)module_ptr +
140*10465441SEvalZero                  shdr[shdr[shdr[index].sh_link].sh_link].sh_offset;
141*10465441SEvalZero         nr_reloc = (rt_uint32_t)(shdr[index].sh_size / sizeof(Elf32_Rel));
142*10465441SEvalZero 
143*10465441SEvalZero         /* relocate every items */
144*10465441SEvalZero         for (i = 0; i < nr_reloc; i ++)
145*10465441SEvalZero         {
146*10465441SEvalZero             Elf32_Sym *sym = &symtab[ELF32_R_SYM(rel->r_info)];
147*10465441SEvalZero 
148*10465441SEvalZero             LOG_D("relocate symbol %s shndx %d", strtab + sym->st_name, sym->st_shndx);
149*10465441SEvalZero 
150*10465441SEvalZero             if ((sym->st_shndx != SHT_NULL) ||(ELF_ST_BIND(sym->st_info) == STB_LOCAL))
151*10465441SEvalZero             {
152*10465441SEvalZero                 Elf32_Addr addr;
153*10465441SEvalZero 
154*10465441SEvalZero                 addr = (Elf32_Addr)(module->mem_space + sym->st_value - vstart_addr);
155*10465441SEvalZero                 dlmodule_relocate(module, rel, addr);
156*10465441SEvalZero             }
157*10465441SEvalZero             else if (!linked)
158*10465441SEvalZero             {
159*10465441SEvalZero                 Elf32_Addr addr;
160*10465441SEvalZero 
161*10465441SEvalZero                 LOG_D("relocate symbol: %s", strtab + sym->st_name);
162*10465441SEvalZero                 /* need to resolve symbol in kernel symbol table */
163*10465441SEvalZero                 addr = dlmodule_symbol_find((const char *)(strtab + sym->st_name));
164*10465441SEvalZero                 if (addr == 0)
165*10465441SEvalZero                 {
166*10465441SEvalZero                     LOG_E("Module: can't find %s in kernel symbol table", strtab + sym->st_name);
167*10465441SEvalZero                     unsolved = RT_TRUE;
168*10465441SEvalZero                 }
169*10465441SEvalZero                 else
170*10465441SEvalZero                 {
171*10465441SEvalZero                     dlmodule_relocate(module, rel, addr);
172*10465441SEvalZero                 }
173*10465441SEvalZero             }
174*10465441SEvalZero             rel ++;
175*10465441SEvalZero         }
176*10465441SEvalZero 
177*10465441SEvalZero         if (unsolved)
178*10465441SEvalZero             return -RT_ERROR;
179*10465441SEvalZero     }
180*10465441SEvalZero 
181*10465441SEvalZero     /* construct module symbol table */
182*10465441SEvalZero     for (index = 0; index < elf_module->e_shnum; index ++)
183*10465441SEvalZero     {
184*10465441SEvalZero         /* find .dynsym section */
185*10465441SEvalZero         rt_uint8_t *shstrab;
186*10465441SEvalZero         shstrab = (rt_uint8_t *)module_ptr +
187*10465441SEvalZero                   shdr[elf_module->e_shstrndx].sh_offset;
188*10465441SEvalZero         if (rt_strcmp((const char *)(shstrab + shdr[index].sh_name), ELF_DYNSYM) == 0)
189*10465441SEvalZero             break;
190*10465441SEvalZero     }
191*10465441SEvalZero 
192*10465441SEvalZero     /* found .dynsym section */
193*10465441SEvalZero     if (index != elf_module->e_shnum)
194*10465441SEvalZero     {
195*10465441SEvalZero         int i, count = 0;
196*10465441SEvalZero         Elf32_Sym  *symtab = RT_NULL;
197*10465441SEvalZero         rt_uint8_t *strtab = RT_NULL;
198*10465441SEvalZero 
199*10465441SEvalZero         symtab = (Elf32_Sym *)((rt_uint8_t *)module_ptr + shdr[index].sh_offset);
200*10465441SEvalZero         strtab = (rt_uint8_t *)module_ptr + shdr[shdr[index].sh_link].sh_offset;
201*10465441SEvalZero 
202*10465441SEvalZero         for (i = 0; i < shdr[index].sh_size / sizeof(Elf32_Sym); i++)
203*10465441SEvalZero         {
204*10465441SEvalZero             if ((ELF_ST_BIND(symtab[i].st_info) == STB_GLOBAL) &&
205*10465441SEvalZero                 (ELF_ST_TYPE(symtab[i].st_info) == STT_FUNC))
206*10465441SEvalZero                 count ++;
207*10465441SEvalZero         }
208*10465441SEvalZero 
209*10465441SEvalZero         module->symtab = (struct rt_module_symtab *)rt_malloc
210*10465441SEvalZero                          (count * sizeof(struct rt_module_symtab));
211*10465441SEvalZero         module->nsym = count;
212*10465441SEvalZero         for (i = 0, count = 0; i < shdr[index].sh_size / sizeof(Elf32_Sym); i++)
213*10465441SEvalZero         {
214*10465441SEvalZero             rt_size_t length;
215*10465441SEvalZero 
216*10465441SEvalZero             if ((ELF_ST_BIND(symtab[i].st_info) != STB_GLOBAL) ||
217*10465441SEvalZero                 (ELF_ST_TYPE(symtab[i].st_info) != STT_FUNC))
218*10465441SEvalZero                 continue;
219*10465441SEvalZero 
220*10465441SEvalZero             length = rt_strlen((const char *)(strtab + symtab[i].st_name)) + 1;
221*10465441SEvalZero 
222*10465441SEvalZero             module->symtab[count].addr =
223*10465441SEvalZero                 (void *)(module->mem_space + symtab[i].st_value - module->vstart_addr);
224*10465441SEvalZero             module->symtab[count].name = rt_malloc(length);
225*10465441SEvalZero             rt_memset((void *)module->symtab[count].name, 0, length);
226*10465441SEvalZero             rt_memcpy((void *)module->symtab[count].name,
227*10465441SEvalZero                       strtab + symtab[i].st_name,
228*10465441SEvalZero                       length);
229*10465441SEvalZero             count ++;
230*10465441SEvalZero         }
231*10465441SEvalZero     }
232*10465441SEvalZero 
233*10465441SEvalZero     return RT_EOK;
234*10465441SEvalZero }
235*10465441SEvalZero 
dlmodule_load_relocated_object(struct rt_dlmodule * module,void * module_ptr)236*10465441SEvalZero rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module_ptr)
237*10465441SEvalZero {
238*10465441SEvalZero     rt_uint32_t index, rodata_addr = 0, bss_addr = 0, data_addr = 0;
239*10465441SEvalZero     rt_uint32_t module_addr = 0, module_size = 0;
240*10465441SEvalZero     rt_uint8_t *ptr, *strtab, *shstrab;
241*10465441SEvalZero 
242*10465441SEvalZero     /* get the ELF image size */
243*10465441SEvalZero     for (index = 0; index < elf_module->e_shnum; index ++)
244*10465441SEvalZero     {
245*10465441SEvalZero         /* text */
246*10465441SEvalZero         if (IS_PROG(shdr[index]) && IS_AX(shdr[index]))
247*10465441SEvalZero         {
248*10465441SEvalZero             module_size += shdr[index].sh_size;
249*10465441SEvalZero             module_addr = shdr[index].sh_addr;
250*10465441SEvalZero         }
251*10465441SEvalZero         /* rodata */
252*10465441SEvalZero         if (IS_PROG(shdr[index]) && IS_ALLOC(shdr[index]))
253*10465441SEvalZero         {
254*10465441SEvalZero             module_size += shdr[index].sh_size;
255*10465441SEvalZero         }
256*10465441SEvalZero         /* data */
257*10465441SEvalZero         if (IS_PROG(shdr[index]) && IS_AW(shdr[index]))
258*10465441SEvalZero         {
259*10465441SEvalZero             module_size += shdr[index].sh_size;
260*10465441SEvalZero         }
261*10465441SEvalZero         /* bss */
262*10465441SEvalZero         if (IS_NOPROG(shdr[index]) && IS_AW(shdr[index]))
263*10465441SEvalZero         {
264*10465441SEvalZero             module_size += shdr[index].sh_size;
265*10465441SEvalZero         }
266*10465441SEvalZero     }
267*10465441SEvalZero 
268*10465441SEvalZero     /* no text, data and bss on image */
269*10465441SEvalZero     if (module_size == 0) return RT_NULL;
270*10465441SEvalZero 
271*10465441SEvalZero     module->vstart_addr = 0;
272*10465441SEvalZero 
273*10465441SEvalZero     /* allocate module space */
274*10465441SEvalZero     module->mem_space = rt_malloc(module_size);
275*10465441SEvalZero     if (module->mem_space == RT_NULL)
276*10465441SEvalZero     {
277*10465441SEvalZero         rt_kprintf("Module: allocate space failed.\n");
278*10465441SEvalZero         return -RT_ERROR;
279*10465441SEvalZero     }
280*10465441SEvalZero     module->mem_size = module_size;
281*10465441SEvalZero 
282*10465441SEvalZero     /* zero all space */
283*10465441SEvalZero     ptr = module->mem_space;
284*10465441SEvalZero     rt_memset(ptr, 0, module_size);
285*10465441SEvalZero 
286*10465441SEvalZero     /* load text and data section */
287*10465441SEvalZero     for (index = 0; index < elf_module->e_shnum; index ++)
288*10465441SEvalZero     {
289*10465441SEvalZero         /* load text section */
290*10465441SEvalZero         if (IS_PROG(shdr[index]) && IS_AX(shdr[index]))
291*10465441SEvalZero         {
292*10465441SEvalZero             rt_memcpy(ptr,
293*10465441SEvalZero                       (rt_uint8_t *)elf_module + shdr[index].sh_offset,
294*10465441SEvalZero                       shdr[index].sh_size);
295*10465441SEvalZero             LOG_D("load text 0x%x, size %d", ptr, shdr[index].sh_size);
296*10465441SEvalZero             ptr += shdr[index].sh_size;
297*10465441SEvalZero         }
298*10465441SEvalZero 
299*10465441SEvalZero         /* load rodata section */
300*10465441SEvalZero         if (IS_PROG(shdr[index]) && IS_ALLOC(shdr[index]))
301*10465441SEvalZero         {
302*10465441SEvalZero             rt_memcpy(ptr,
303*10465441SEvalZero                       (rt_uint8_t *)elf_module + shdr[index].sh_offset,
304*10465441SEvalZero                       shdr[index].sh_size);
305*10465441SEvalZero             rodata_addr = (rt_uint32_t)ptr;
306*10465441SEvalZero             LOG_D("load rodata 0x%x, size %d, rodata 0x%x", ptr,
307*10465441SEvalZero                 shdr[index].sh_size, *(rt_uint32_t *)data_addr);
308*10465441SEvalZero             ptr += shdr[index].sh_size;
309*10465441SEvalZero         }
310*10465441SEvalZero 
311*10465441SEvalZero         /* load data section */
312*10465441SEvalZero         if (IS_PROG(shdr[index]) && IS_AW(shdr[index]))
313*10465441SEvalZero         {
314*10465441SEvalZero             rt_memcpy(ptr,
315*10465441SEvalZero                       (rt_uint8_t *)elf_module + shdr[index].sh_offset,
316*10465441SEvalZero                       shdr[index].sh_size);
317*10465441SEvalZero             data_addr = (rt_uint32_t)ptr;
318*10465441SEvalZero             LOG_D("load data 0x%x, size %d, data 0x%x", ptr,
319*10465441SEvalZero                 shdr[index].sh_size, *(rt_uint32_t *)data_addr);
320*10465441SEvalZero             ptr += shdr[index].sh_size;
321*10465441SEvalZero         }
322*10465441SEvalZero 
323*10465441SEvalZero         /* load bss section */
324*10465441SEvalZero         if (IS_NOPROG(shdr[index]) && IS_AW(shdr[index]))
325*10465441SEvalZero         {
326*10465441SEvalZero             rt_memset(ptr, 0, shdr[index].sh_size);
327*10465441SEvalZero             bss_addr = (rt_uint32_t)ptr;
328*10465441SEvalZero             LOG_D("load bss 0x%x, size %d", ptr, shdr[index].sh_size);
329*10465441SEvalZero         }
330*10465441SEvalZero     }
331*10465441SEvalZero 
332*10465441SEvalZero     /* set module entry */
333*10465441SEvalZero     module->entry_addr = (rt_dlmodule_entry_func_t)((rt_uint8_t *)module->mem_space + elf_module->e_entry - module_addr);
334*10465441SEvalZero 
335*10465441SEvalZero     /* handle relocation section */
336*10465441SEvalZero     for (index = 0; index < elf_module->e_shnum; index ++)
337*10465441SEvalZero     {
338*10465441SEvalZero         rt_uint32_t i, nr_reloc;
339*10465441SEvalZero         Elf32_Sym *symtab;
340*10465441SEvalZero         Elf32_Rel *rel;
341*10465441SEvalZero 
342*10465441SEvalZero         if (!IS_REL(shdr[index]))
343*10465441SEvalZero             continue;
344*10465441SEvalZero 
345*10465441SEvalZero         /* get relocate item */
346*10465441SEvalZero         rel = (Elf32_Rel *)((rt_uint8_t *)module_ptr + shdr[index].sh_offset);
347*10465441SEvalZero 
348*10465441SEvalZero         /* locate .dynsym and .dynstr */
349*10465441SEvalZero         symtab   = (Elf32_Sym *)((rt_uint8_t *)module_ptr +
350*10465441SEvalZero                                  shdr[shdr[index].sh_link].sh_offset);
351*10465441SEvalZero         strtab   = (rt_uint8_t *)module_ptr +
352*10465441SEvalZero                    shdr[shdr[shdr[index].sh_link].sh_link].sh_offset;
353*10465441SEvalZero         shstrab  = (rt_uint8_t *)module_ptr +
354*10465441SEvalZero                    shdr[elf_module->e_shstrndx].sh_offset;
355*10465441SEvalZero         nr_reloc = (rt_uint32_t)(shdr[index].sh_size / sizeof(Elf32_Rel));
356*10465441SEvalZero 
357*10465441SEvalZero         /* relocate every items */
358*10465441SEvalZero         for (i = 0; i < nr_reloc; i ++)
359*10465441SEvalZero         {
360*10465441SEvalZero             Elf32_Sym *sym = &symtab[ELF32_R_SYM(rel->r_info)];
361*10465441SEvalZero 
362*10465441SEvalZero             LOG_D("relocate symbol: %s", strtab + sym->st_name);
363*10465441SEvalZero 
364*10465441SEvalZero             if (sym->st_shndx != STN_UNDEF)
365*10465441SEvalZero             {
366*10465441SEvalZero                 Elf32_Addr addr = 0;
367*10465441SEvalZero 
368*10465441SEvalZero                 if ((ELF_ST_TYPE(sym->st_info) == STT_SECTION) ||
369*10465441SEvalZero                     (ELF_ST_TYPE(sym->st_info) == STT_OBJECT))
370*10465441SEvalZero                 {
371*10465441SEvalZero                     if (rt_strncmp((const char *)(shstrab +
372*10465441SEvalZero                                                   shdr[sym->st_shndx].sh_name), ELF_RODATA, 8) == 0)
373*10465441SEvalZero                     {
374*10465441SEvalZero                         /* relocate rodata section */
375*10465441SEvalZero                         LOG_D("rodata");
376*10465441SEvalZero                         addr = (Elf32_Addr)(rodata_addr + sym->st_value);
377*10465441SEvalZero                     }
378*10465441SEvalZero                     else if (rt_strncmp((const char *)
379*10465441SEvalZero                                         (shstrab + shdr[sym->st_shndx].sh_name), ELF_BSS, 5) == 0)
380*10465441SEvalZero                     {
381*10465441SEvalZero                         /* relocate bss section */
382*10465441SEvalZero                         LOG_D("bss");
383*10465441SEvalZero                         addr = (Elf32_Addr)bss_addr + sym->st_value;
384*10465441SEvalZero                     }
385*10465441SEvalZero                     else if (rt_strncmp((const char *)(shstrab + shdr[sym->st_shndx].sh_name),
386*10465441SEvalZero                                         ELF_DATA, 6) == 0)
387*10465441SEvalZero                     {
388*10465441SEvalZero                         /* relocate data section */
389*10465441SEvalZero                         LOG_D("data");
390*10465441SEvalZero                         addr = (Elf32_Addr)data_addr + sym->st_value;
391*10465441SEvalZero                     }
392*10465441SEvalZero 
393*10465441SEvalZero                     if (addr != 0) dlmodule_relocate(module, rel, addr);
394*10465441SEvalZero                 }
395*10465441SEvalZero                 else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC)
396*10465441SEvalZero                 {
397*10465441SEvalZero                     addr = (Elf32_Addr)((rt_uint8_t *) module->mem_space - module_addr + sym->st_value);
398*10465441SEvalZero 
399*10465441SEvalZero                     /* relocate function */
400*10465441SEvalZero                     dlmodule_relocate(module, rel, addr);
401*10465441SEvalZero                 }
402*10465441SEvalZero             }
403*10465441SEvalZero             else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC)
404*10465441SEvalZero             {
405*10465441SEvalZero                 /* relocate function */
406*10465441SEvalZero                 dlmodule_relocate(module, rel,
407*10465441SEvalZero                                        (Elf32_Addr)((rt_uint8_t *)
408*10465441SEvalZero                                                     module->mem_space
409*10465441SEvalZero                                                     - module_addr
410*10465441SEvalZero                                                     + sym->st_value));
411*10465441SEvalZero             }
412*10465441SEvalZero             else
413*10465441SEvalZero             {
414*10465441SEvalZero                 Elf32_Addr addr;
415*10465441SEvalZero 
416*10465441SEvalZero                 if (ELF32_R_TYPE(rel->r_info) != R_ARM_V4BX)
417*10465441SEvalZero                 {
418*10465441SEvalZero                     LOG_D("relocate symbol: %s", strtab + sym->st_name);
419*10465441SEvalZero 
420*10465441SEvalZero                     /* need to resolve symbol in kernel symbol table */
421*10465441SEvalZero                     addr = dlmodule_symbol_find((const char *)(strtab + sym->st_name));
422*10465441SEvalZero                     if (addr != (Elf32_Addr)RT_NULL)
423*10465441SEvalZero                     {
424*10465441SEvalZero                         dlmodule_relocate(module, rel, addr);
425*10465441SEvalZero                         LOG_D("symbol addr 0x%x", addr);
426*10465441SEvalZero                     }
427*10465441SEvalZero                     else
428*10465441SEvalZero                         LOG_E("Module: can't find %s in kernel symbol table",
429*10465441SEvalZero                                    strtab + sym->st_name);
430*10465441SEvalZero                 }
431*10465441SEvalZero                 else
432*10465441SEvalZero                 {
433*10465441SEvalZero                     addr = (Elf32_Addr)((rt_uint8_t *) module->mem_space - module_addr + sym->st_value);
434*10465441SEvalZero                     dlmodule_relocate(module, rel, addr);
435*10465441SEvalZero                 }
436*10465441SEvalZero             }
437*10465441SEvalZero 
438*10465441SEvalZero             rel ++;
439*10465441SEvalZero         }
440*10465441SEvalZero     }
441*10465441SEvalZero 
442*10465441SEvalZero     return RT_EOK;
443*10465441SEvalZero }
444