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 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 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