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 #ifdef __arm__ 15 int dlmodule_relocate(struct rt_dlmodule *module, Elf32_Rel *rel, Elf32_Addr sym_val) 16 { 17 Elf32_Addr *where, tmp; 18 Elf32_Sword addend, offset; 19 rt_uint32_t upper, lower, sign, j1, j2; 20 21 where = (Elf32_Addr *)((rt_uint8_t *)module->mem_space 22 + rel->r_offset 23 - module->vstart_addr); 24 switch (ELF32_R_TYPE(rel->r_info)) 25 { 26 case R_ARM_NONE: 27 break; 28 case R_ARM_ABS32: 29 *where += (Elf32_Addr)sym_val; 30 RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_ABS32: %x -> %x\n", 31 where, *where)); 32 break; 33 case R_ARM_PC24: 34 case R_ARM_PLT32: 35 case R_ARM_CALL: 36 case R_ARM_JUMP24: 37 addend = *where & 0x00ffffff; 38 if (addend & 0x00800000) 39 addend |= 0xff000000; 40 tmp = sym_val - (Elf32_Addr)where + (addend << 2); 41 tmp >>= 2; 42 *where = (*where & 0xff000000) | (tmp & 0x00ffffff); 43 RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_PC24: %x -> %x\n", 44 where, *where)); 45 break; 46 case R_ARM_REL32: 47 *where += sym_val - (Elf32_Addr)where; 48 RT_DEBUG_LOG(RT_DEBUG_MODULE, 49 ("R_ARM_REL32: %x -> %x, sym %x, offset %x\n", 50 where, *where, sym_val, rel->r_offset)); 51 break; 52 case R_ARM_V4BX: 53 *where &= 0xf000000f; 54 *where |= 0x01a0f000; 55 break; 56 57 case R_ARM_GLOB_DAT: 58 case R_ARM_JUMP_SLOT: 59 *where = (Elf32_Addr)sym_val; 60 RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_JUMP_SLOT: 0x%x -> 0x%x 0x%x\n", 61 where, *where, sym_val)); 62 break; 63 #if 0 /* To do */ 64 case R_ARM_GOT_BREL: 65 temp = (Elf32_Addr)sym_val; 66 *where = (Elf32_Addr)&temp; 67 RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_GOT_BREL: 0x%x -> 0x%x 0x%x\n", 68 where, *where, sym_val)); 69 break; 70 #endif 71 72 case R_ARM_RELATIVE: 73 *where = (Elf32_Addr)sym_val + *where; 74 RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_RELATIVE: 0x%x -> 0x%x 0x%x\n", 75 where, *where, sym_val)); 76 break; 77 case R_ARM_THM_CALL: 78 case R_ARM_THM_JUMP24: 79 upper = *(rt_uint16_t *)where; 80 lower = *(rt_uint16_t *)((Elf32_Addr)where + 2); 81 82 sign = (upper >> 10) & 1; 83 j1 = (lower >> 13) & 1; 84 j2 = (lower >> 11) & 1; 85 offset = (sign << 24) | 86 ((~(j1 ^ sign) & 1) << 23) | 87 ((~(j2 ^ sign) & 1) << 22) | 88 ((upper & 0x03ff) << 12) | 89 ((lower & 0x07ff) << 1); 90 if (offset & 0x01000000) 91 offset -= 0x02000000; 92 offset += sym_val - (Elf32_Addr)where; 93 94 if (!(offset & 1) || 95 offset <= (rt_int32_t)0xff000000 || 96 offset >= (rt_int32_t)0x01000000) 97 { 98 rt_kprintf("Module: Only Thumb addresses allowed\n"); 99 100 return -1; 101 } 102 103 sign = (offset >> 24) & 1; 104 j1 = sign ^ (~(offset >> 23) & 1); 105 j2 = sign ^ (~(offset >> 22) & 1); 106 *(rt_uint16_t *)where = (rt_uint16_t)((upper & 0xf800) | 107 (sign << 10) | 108 ((offset >> 12) & 0x03ff)); 109 *(rt_uint16_t *)(where + 2) = (rt_uint16_t)((lower & 0xd000) | 110 (j1 << 13) | (j2 << 11) | 111 ((offset >> 1) & 0x07ff)); 112 upper = *(rt_uint16_t *)where; 113 lower = *(rt_uint16_t *)((Elf32_Addr)where + 2); 114 break; 115 default: 116 return -1; 117 } 118 119 return 0; 120 } 121 #endif 122