This source file includes following definitions.
- apply_realloc
- apply_import
1
2
3
4
5
6
7
8 #include <stdlib.h>
9 #include <string.h>
10
11 #include "myio.h"
12 #include "elfflt.h"
13
14 extern uint32_t offs_divsi3_skip_div0_test;
15 extern uint32_t offs_div0_from_arm;
16 extern uint32_t offs__aeabi_uidiv;
17
18 int apply_realloc( struct relevant_section* base_sect,
19 struct elf32_rela *rela,
20 struct relevant_section* tgt_sect,
21 struct elf32_sym *sym,
22 int i
23 )
24 {
25 unsigned int type = ELF32_R_TYPE(rela->r_info);
26 uint32_t locoffset = base_sect->flat_offset + rela->r_offset;
27 char* loc = (char*)(flat_buf + locoffset );
28 uint32_t tgt_fulloffset = tgt_sect->flat_offset + sym->st_value;
29
30 int relindex = tgt_sect->number;
31 char symbuf[30];
32 char* symname="";
33 char* reloc_name="";
34 int ret = b_seek_read(strtaboff + sym->st_name, symbuf, sizeof(symbuf));
35 if (ret > 0) { symname=symbuf; symbuf[sizeof(symbuf)-1]=0; }
36
37
38 int32_t offset;
39 uint32_t upper, lower, sign, j1, j2;
40 char* patch_name="";
41
42
43 if (rela->r_offset > base_sect->size - sizeof(uint32_t)) {
44 PRINTERR(stderr, "section %u(%s) reloc %u sym '%s': out of bounds relocation, offset %d size %u\n",
45 relindex, base_sect->name, i, symname,
46 rela->r_offset, base_sect->size);
47 return ELFFLT_OUTOF_RANGE;
48 }
49
50 switch(type) {
51 case R_ARM_ABS32:
52 {
53 uint32_t addend = *(uint32_t*)loc;
54 *(uint32_t*)loc += tgt_fulloffset;
55
56 if ( FLAG_DUMP_RELOC )
57 printf( "R_ARM_ABS32: %p(%s+0x%x=%x): ptr=%x [%s+0x%x+0x%x] sym:%s\n",
58 base_sect->base_addr+rela->r_offset, base_sect->name, rela->r_offset, locoffset,
59 tgt_sect->base_addr + addend + sym->st_value,
60 tgt_sect->name, sym->st_value, addend, symname
61 );
62
63 if ( FLAG_VERBOSE)
64 printf("=== flt%p(reloc+%x: %x): [%x]=0x%x\n",flat_reloc_cur, (char*)flat_reloc_cur-(char*)flat_reloc, (char*)flat_reloc_cur-flat_buf, locoffset, *(uint32_t*)loc);
65 *flat_reloc_cur = locoffset;
66 flat_reloc_cur++;
67 flat_reloc_count++;
68 }
69 break;
70
71 case R_ARM_THM_CALL:
72 case R_ARM_THM_JUMP24:
73 upper = *(uint16_t *)loc;
74 lower = *(uint16_t *)(loc + 2);
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89 sign = (upper >> 10) & 1;
90 j1 = (lower >> 13) & 1;
91 j2 = (lower >> 11) & 1;
92 offset = (sign << 24) | ((~(j1 ^ sign) & 1) << 23) |
93 ((~(j2 ^ sign) & 1) << 22) |
94 ((upper & 0x03ff) << 12) |
95 ((lower & 0x07ff) << 1);
96 if (offset & 0x01000000)
97 offset -= 0x02000000;
98 offset += tgt_fulloffset - locoffset;
99
100
101
102
103
104
105
106
107
108
109 if ((ELF32_ST_TYPE(sym->st_info) == STT_FUNC &&
110 !(offset & 1)) ||
111 offset <= (int32_t)0xff000000 ||
112 offset >= (int32_t)0x01000000) {
113 PRINTERR(stderr, "section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n",
114 relindex, i, symname,
115 ELF32_R_TYPE(rela->r_info), locoffset,
116 sym->st_value);
117 return ELFFLT_OUTOF_RANGE;
118 }
119
120 if ( FLAG_DUMP_RELOC )
121 printf( "R_ARM_THM_CALL: %p(%s+0x%x=%x): %04x %04x ptr=%x [loc%-d] sym:%s\n",
122 base_sect->base_addr+rela->r_offset, base_sect->name, rela->r_offset, locoffset,
123 upper, lower,
124 tgt_sect->base_addr+rela->r_offset+offset, offset,
125 symname);
126
127 sign = (offset >> 24) & 1;
128 j1 = sign ^ (~(offset >> 23) & 1);
129 j2 = sign ^ (~(offset >> 22) & 1);
130 *(uint16_t *)loc = (uint16_t)((upper & 0xf800) | (sign << 10) |
131 ((offset >> 12) & 0x03ff));
132 *(uint16_t *)(loc + 2) = (uint16_t)((lower & 0xd000) |
133 (j1 << 13) | (j2 << 11) |
134 ((offset >> 1) & 0x07ff));
135 break;
136
137 case R_ARM_PC24:
138 case R_ARM_JUMP24:
139 case R_ARM_CALL:
140
141
142
143 patch_name=0;
144 if ( strcmp(symname,"__div0") == 0 )
145 {
146 if ( locoffset == offs_divsi3_skip_div0_test )
147 patch_name=".divsi3_skip_div0_test";
148 else if ( locoffset == offs__aeabi_uidiv )
149 patch_name="__aeabi_uidiv";
150
151 if ( !patch_name ) {
152 PRINTERR( stderr, "%s is requested from unusual place .text+0x%x\n", reloc_name,locoffset-text.flat_offset);
153 return ELFFLT_UNHANDLED_RELOC;
154 }
155
156
157 tgt_fulloffset = (text.flat_offset + offs_div0_from_arm);
158
159 }
160
161 case R_ARM_PLT32:
162
163
164
165
166
167 reloc_name = (type==R_ARM_PC24)?"R_ARM_PC24":"R_ARM_PLT32";
168
169 offset = (*(uint32_t *)loc & 0x00ffffff) << 2;
170 if (offset & 0x02000000)
171 offset -= 0x04000000;
172
173 offset += tgt_fulloffset - locoffset;
174
175
176
177
178
179
180
181
182
183
184
185
186
187 offset >>= 2;
188
189 if ( FLAG_DUMP_RELOC )
190 {
191 printf( "%s: %p(%s+0x%x=%x): %08x ptr=%x [loc%-d] sym:%s\n", reloc_name,
192 base_sect->base_addr+rela->r_offset, base_sect->name, rela->r_offset, locoffset,
193 *(uint32_t *)loc,
194 base_sect->base_addr+rela->r_offset+offset*4, offset*4,
195 symname);
196 if ((type==R_ARM_PC24) && patch_name)
197 printf( "...Patched 0x%x(__div0)->0x%x (__div0_from_arm) for %s\n", sym->st_value, offs_div0_from_arm, patch_name);
198 }
199
200 *(uint32_t *)loc &= 0xff000000;
201 *(uint32_t *)loc |= offset & 0x00ffffff;
202 break;
203 default:
204 PRINTERR(stderr, "Unknown relocation type %d\n",type);
205 return ELFFLT_UNHANDLED_RELOC;
206 }
207
208 return ELFFLT_OK;
209 }
210
211
212
213
214 int apply_import( struct relevant_section* base_sect,
215 struct elf32_rela *rela,
216 int importidx,
217 struct elf32_sym *sym
218 )
219 {
220 unsigned int type = ELF32_R_TYPE(rela->r_info);
221 uint32_t locoffset = base_sect->flat_offset + rela->r_offset;
222 char* loc = (char*)(flat_buf + locoffset );
223
224 char symbuf[30];
225 char* symname="";
226 int ret = b_seek_read(strtaboff + sym->st_name, symbuf, sizeof(symbuf));
227 if (ret > 0) { symname=symbuf; symbuf[sizeof(symbuf)-1]=0; }
228
229 switch(type) {
230 case R_ARM_ABS32:
231 {
232 flat_import_cur->offs = locoffset;
233 flat_import_cur->importidx = importidx;
234
235 if ( FLAG_DUMP_RELOC )
236 printf( "R_ARM_ABS32: %p(%s+0x%x=%x): import_value=%d (sym:%s)+0x%x %d\n",
237 base_sect->base_addr+rela->r_offset, base_sect->name, rela->r_offset, locoffset,
238 importidx, symname, *(uint32_t*)loc, flat_import_count
239 );
240 flat_import_cur++;
241 flat_import_count++;
242 }
243 break;
244
245 default:
246
247 PRINTERR(stderr, "Only R_ARM_ABS32 relocations could be processed as imported symbol (%s). Please compile with -mlong-call or use manual import\n",symname);
248 return ELFFLT_UNHANDLED_RELOC;
249 }
250 return ELFFLT_OK;
251 }