#include #include #include #include #ifdef ARCH_MM_MMU #include #include #endif typedef struct { Elf32_Word st_name; Elf32_Addr st_value; Elf32_Word st_size; unsigned char st_info; unsigned char st_other; Elf32_Half st_shndx; } Elf32_sym; #ifdef ARCH_MM_MMU void arch_elf_reloc(rt_mmu_info *m_info, void *text_start, void *rel_dyn_start, size_t rel_dyn_size, void *got_start, size_t got_size, Elf32_sym *dynsym) { size_t rel_off; void* addr; if (rel_dyn_size && !dynsym) { return; } for (rel_off = 0; rel_off < rel_dyn_size; rel_off += 8) { uint32_t v1, v2; /* memcpy(&v1, rel_dyn_start + rel_off, 4); memcpy(&v2, rel_dyn_start + rel_off + 4, 4); */ addr = rt_hw_mmu_v2p(m_info, (void*)((char*)rel_dyn_start + rel_off)); addr = (void*)((char*)addr - PV_OFFSET); memcpy(&v1, addr, 4); addr = rt_hw_mmu_v2p(m_info, (void*)((char*)rel_dyn_start + rel_off + 4)); addr = (void*)((char*)addr - PV_OFFSET); memcpy(&v2, addr, 4); addr = rt_hw_mmu_v2p(m_info, (void*)((char*)text_start + v1)); addr = (void*)((char*)addr - PV_OFFSET); if ((v2 & 0xff) == R_ARM_RELATIVE) { // *(uint32_t*)(text_start + v1) += (uint32_t)text_start; *(uint32_t*)addr += (uint32_t)text_start; } else if ((v2 & 0xff) == R_ARM_ABS32) { uint32_t t; t = (v2 >> 8); if (t) /* 0 is UDF */ { // *(uint32_t*)(text_start + v1) = (uint32_t)(text_start + dynsym[t].st_value); *(uint32_t*)addr = (uint32_t)((char*)text_start + dynsym[t].st_value); } } } /* modify got */ if (got_size) { uint32_t *got_item = (uint32_t*)got_start; for (rel_off = 0; rel_off < got_size; rel_off += 4, got_item++) { //*got_item += (uint32_t)text_start; addr = rt_hw_mmu_v2p(m_info, got_item); addr = (void*)((char*)addr - PV_OFFSET); *(uint32_t *)addr += (uint32_t)text_start; } } } #else void arch_elf_reloc(void *text_start, void *rel_dyn_start, size_t rel_dyn_size, void *got_start, size_t got_size, Elf32_sym *dynsym) { size_t rel_off; if (rel_dyn_size && !dynsym) { return; } for (rel_off = 0; rel_off < rel_dyn_size; rel_off += 8) { uint32_t v1, v2; memcpy(&v1, (void*)((char*)rel_dyn_start + rel_off), 4); memcpy(&v2, (void*)((char*)rel_dyn_start + rel_off + 4), 4); if ((v2 & 0xff) == R_ARM_RELATIVE) { *(uint32_t*)((char*)text_start + v1) += (uint32_t)text_start; } else if ((v2 & 0xff) == R_ARM_ABS32) { uint32_t t; t = (v2 >> 8); if (t) /* 0 is UDF */ { *(uint32_t*)((char*)text_start + v1) = (uint32_t)((char*)text_start + dynsym[t].st_value); } } } /* modify got */ if (got_size) { uint32_t *got_item = (uint32_t*)got_start; for (rel_off = 0; rel_off < got_size; rel_off += 4, got_item++) { *got_item += (uint32_t)text_start; } } } #endif