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