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