1 /*
2 * Copyright 2011-2012, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef ELF_OBJECT_HXX
18 #define ELF_OBJECT_HXX
19
20 #include "ELFHeader.h"
21 #include "ELFReloc.h"
22 #include "ELFSection.h"
23 #include "ELFSectionHeaderTable.h"
24 #include "StubLayout.h"
25 #include "GOT.h"
26 #include "ELF.h"
27
28 #include <llvm/ADT/SmallVector.h>
29
30 #include "utils/rsl_assert.h"
31
32 template <unsigned Bitwidth>
33 template <typename Archiver>
34 inline ELFObject<Bitwidth> *
read(Archiver & AR)35 ELFObject<Bitwidth>::read(Archiver &AR) {
36 llvm::OwningPtr<ELFObjectTy> object(new ELFObjectTy());
37
38 // Read header
39 object->header.reset(ELFHeaderTy::read(AR));
40 if (!object->header) {
41 return 0;
42 }
43
44 // Read section table
45 object->shtab.reset(ELFSectionHeaderTableTy::read(AR, object.get()));
46 if (!object->shtab) {
47 return 0;
48 }
49
50 // Read each section
51 llvm::SmallVector<size_t, 4> progbits_ndx;
52 for (size_t i = 0; i < object->header->getSectionHeaderNum(); ++i) {
53 if ((*object->shtab)[i]->getType() == SHT_PROGBITS) {
54 object->stab.push_back(NULL);
55 progbits_ndx.push_back(i);
56 } else {
57 llvm::OwningPtr<ELFSectionTy> sec(
58 ELFSectionTy::read(AR, object.get(), (*object->shtab)[i]));
59 object->stab.push_back(sec.take());
60 }
61 }
62
63 object->shtab->buildNameMap();
64 ELFSectionSymTabTy *symtab =
65 static_cast<ELFSectionSymTabTy *>(object->getSectionByName(".symtab"));
66 rsl_assert(symtab && "Symtab is required.");
67 symtab->buildNameMap();
68
69 for (size_t i = 0; i < progbits_ndx.size(); ++i) {
70 size_t index = progbits_ndx[i];
71
72 llvm::OwningPtr<ELFSectionTy> sec(
73 ELFSectionTy::read(AR, object.get(), (*object->shtab)[index]));
74 object->stab[index] = sec.take();
75 }
76
77 return object.take();
78 }
79
80 template <unsigned Bitwidth>
getSectionName(size_t i) const81 inline char const *ELFObject<Bitwidth>::getSectionName(size_t i) const {
82 ELFSectionTy const *sec = stab[header->getStringSectionIndex()];
83
84 if (sec) {
85 ELFSectionStrTabTy const &st =
86 static_cast<ELFSectionStrTabTy const &>(*sec);
87 return st[i];
88 }
89
90 return NULL;
91 }
92
93 template <unsigned Bitwidth>
94 inline ELFSection<Bitwidth> const *
getSectionByIndex(size_t i) const95 ELFObject<Bitwidth>::getSectionByIndex(size_t i) const {
96 return stab[i];
97 }
98
99 template <unsigned Bitwidth>
100 inline ELFSection<Bitwidth> *
getSectionByIndex(size_t i)101 ELFObject<Bitwidth>::getSectionByIndex(size_t i) {
102 return stab[i];
103 }
104
105 template <unsigned Bitwidth>
106 inline ELFSection<Bitwidth> const *
getSectionByName(std::string const & str) const107 ELFObject<Bitwidth>::getSectionByName(std::string const &str) const {
108 size_t idx = getSectionHeaderTable()->getByName(str)->getIndex();
109 return stab[idx];
110 }
111
112 template <unsigned Bitwidth>
113 inline ELFSection<Bitwidth> *
getSectionByName(std::string const & str)114 ELFObject<Bitwidth>::getSectionByName(std::string const &str) {
115 ELFObjectTy const *const_this = this;
116 ELFSectionTy const *sptr = const_this->getSectionByName(str);
117 // Const cast for the same API's const and non-const versions.
118 return const_cast<ELFSectionTy *>(sptr);
119 }
120
121
122 template <unsigned Bitwidth>
123 inline void ELFObject<Bitwidth>::
relocateARM(void * (* find_sym)(void * context,char const * name),void * context,ELFSectionRelTableTy * reltab,ELFSectionProgBitsTy * text)124 relocateARM(void *(*find_sym)(void *context, char const *name),
125 void *context,
126 ELFSectionRelTableTy *reltab,
127 ELFSectionProgBitsTy *text) {
128 // FIXME: Should be implement in independent files.
129 rsl_assert(Bitwidth == 32 && "ARM only have 32 bits.");
130
131 ELFSectionSymTabTy *symtab =
132 static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
133 rsl_assert(symtab && "Symtab is required.");
134
135 for (size_t i = 0; i < reltab->size(); ++i) {
136 // FIXME: Can not implement here, use Fixup!
137 ELFRelocTy *rel = (*reltab)[i];
138 ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
139
140 // FIXME: May be not uint32_t *.
141 typedef int32_t Inst_t;
142 Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
143 Inst_t P = (Inst_t)(int64_t)inst;
144 Inst_t A = 0;
145 Inst_t S = (Inst_t)(int64_t)sym->getAddress(EM_ARM);
146 Inst_t T = 0;
147
148 if (sym->isConcreteFunc() && (sym->getValue() & 0x1)) {
149 T = 1;
150 }
151
152 word_t reltype = rel->getType();
153 switch (reltype) {
154 default:
155 rsl_assert(0 && "Not implemented relocation type.");
156 break;
157
158 case R_ARM_ABS32:
159 {
160 if (S == 0 && sym->getType() == STT_NOTYPE) {
161 void *ext_sym = find_sym(context, sym->getName());
162 if (!ext_sym) {
163 missingSymbols = true;
164 }
165 S = (Inst_t)(uintptr_t)ext_sym;
166 sym->setAddress(ext_sym);
167 }
168 A = *inst;
169 *inst = (S + A) | T;
170 }
171 break;
172
173 // FIXME: Predefine relocation codes.
174 case R_ARM_CALL:
175 case R_ARM_THM_CALL:
176 case R_ARM_JUMP24:
177 case R_ARM_THM_JUMP24:
178 {
179 #define SIGN_EXTEND(x, l) (((x)^(1<<((l)-1)))-(1<<(l-1)))
180 if (reltype == R_ARM_CALL || reltype == R_ARM_JUMP24) {
181 A = (Inst_t)(int64_t)SIGN_EXTEND(*inst & 0xFFFFFF, 24);
182 A <<= 2;
183 } else {
184 // Hack for two 16bit.
185 *inst = ((*inst >> 16) & 0xFFFF) | (*inst << 16);
186 Inst_t s = (*inst >> 26) & 0x1u, // 26
187 u = (*inst >> 16) & 0x3FFu, // 25-16
188 l = *inst & 0x7FFu, // 10-0
189 j1 = (*inst >> 13) & 0x1u, // 13
190 j2 = (*inst >> 11) & 0x1u; // 11
191 Inst_t i1 = (~(j1 ^ s)) & 0x1u,
192 i2 = (~(j2 ^ s)) & 0x1u;
193 // [31-25][24][23][22][21-12][11-1][0]
194 // 0 s i1 i2 u l 0
195 A = SIGN_EXTEND((s << 23) | (i1 << 22) | (i2 << 21) | (u << 11) | l, 24);
196 A <<= 1;
197 }
198 #undef SIGN_EXTEND
199
200 void *callee_addr = sym->getAddress(EM_ARM);
201
202 switch (sym->getType()) {
203 default:
204 rsl_assert(0 && "Wrong type for R_ARM_CALL relocation.");
205 abort();
206 break;
207
208 case STT_FUNC:
209 // NOTE: Callee function is in the object file, but it may be
210 // in different PROGBITS section (which may be far call).
211
212 if (callee_addr == 0) {
213 rsl_assert(0 && "We should get function address at previous "
214 "sym->getAddress(EM_ARM) function call.");
215 abort();
216 }
217 break;
218
219 case STT_NOTYPE:
220 // NOTE: Callee function is an external function. Call find_sym
221 // if it has not resolved yet.
222
223 if (callee_addr == 0) {
224 callee_addr = find_sym(context, sym->getName());
225 if (!callee_addr) {
226 missingSymbols = true;
227 }
228 sym->setAddress(callee_addr);
229 }
230 break;
231 }
232
233 // Get the stub for this function
234 StubLayout *stub_layout = text->getStubLayout();
235
236 if (!stub_layout) {
237 llvm::errs() << "unable to get stub layout." << "\n";
238 abort();
239 }
240
241 void *stub = stub_layout->allocateStub(callee_addr);
242
243 if (!stub) {
244 llvm::errs() << "unable to allocate stub." << "\n";
245 abort();
246 }
247
248 //LOGI("Function %s: using stub %p\n", sym->getName(), stub);
249 S = (uint32_t)(uintptr_t)stub;
250
251 if (reltype == R_ARM_CALL || reltype == R_ARM_JUMP24) {
252 // Relocate the R_ARM_CALL relocation type
253 uint32_t result = (S + A - P) >> 2;
254
255 if (result > 0x007FFFFF && result < 0xFF800000) {
256 rsl_assert(0 && "Stub is still too far");
257 abort();
258 }
259
260 *inst = ((result) & 0x00FFFFFF) | (*inst & 0xFF000000);
261 } else {
262 P &= ~0x3; // Base address align to 4 bytes. (For BLX.)
263
264 // Relocate the R_ARM_THM_CALL relocation type
265 uint32_t result = (S + A - P) >> 1;
266
267 if (result > 0x007FFFFF && result < 0xFF800000) {
268 rsl_assert(0 && "Stub is still too far");
269 abort();
270 }
271
272 //*inst &= 0xF800D000u;
273 // Rewrite instruction to BLX. (Stub is always ARM.)
274 *inst &= 0xF800C000u;
275 // [31-25][24][23][22][21-12][11-1][0]
276 // 0 s i1 i2 u l 0
277 Inst_t s = (result >> 23) & 0x1u, // 26
278 u = (result >> 11) & 0x3FFu, // 25-16
279 // For BLX, bit [0] is 0.
280 l = result & 0x7FEu, // 10-0
281 i1 = (result >> 22) & 0x1u,
282 i2 = (result >> 21) & 0x1u;
283 Inst_t j1 = ((~i1) ^ s) & 0x01u, // 13
284 j2 = ((~i2) ^ s) & 0x01u; // 11
285 *inst |= s << 26;
286 *inst |= u << 16;
287 *inst |= l;
288 *inst |= j1 << 13;
289 *inst |= j2 << 11;
290 // Hack for two 16bit.
291 *inst = ((*inst >> 16) & 0xFFFF) | (*inst << 16);
292 }
293 }
294 break;
295 case R_ARM_MOVT_ABS:
296 case R_ARM_MOVW_ABS_NC:
297 case R_ARM_THM_MOVW_ABS_NC:
298 case R_ARM_THM_MOVT_ABS:
299 {
300 if (S == 0 && sym->getType() == STT_NOTYPE) {
301 void *ext_sym = find_sym(context, sym->getName());
302 if (!ext_sym) {
303 missingSymbols = true;
304 }
305 S = (Inst_t)(uintptr_t)ext_sym;
306 sym->setAddress(ext_sym);
307 }
308 if (reltype == R_ARM_MOVT_ABS
309 || reltype == R_ARM_THM_MOVT_ABS) {
310 S >>= 16;
311 }
312
313 if (reltype == R_ARM_MOVT_ABS
314 || reltype == R_ARM_MOVW_ABS_NC) {
315 // No need sign extend.
316 A = ((*inst & 0xF0000) >> 4) | (*inst & 0xFFF);
317 uint32_t result = (S + A);
318 *inst = (((result) & 0xF000) << 4) |
319 ((result) & 0xFFF) |
320 (*inst & 0xFFF0F000);
321 } else {
322 // Hack for two 16bit.
323 *inst = ((*inst >> 16) & 0xFFFF) | (*inst << 16);
324 // imm16: [19-16][26][14-12][7-0]
325 A = (((*inst >> 4) & 0xF000u) |
326 ((*inst >> 15) & 0x0800u) |
327 ((*inst >> 4) & 0x0700u) |
328 ( *inst & 0x00FFu));
329 uint32_t result;
330 if (reltype == R_ARM_THM_MOVT_ABS) {
331 result = (S + A);
332 } else {
333 result = (S + A) | T;
334 }
335 // imm16: [19-16][26][14-12][7-0]
336 *inst &= 0xFBF08F00u;
337 *inst |= (result & 0xF000u) << 4;
338 *inst |= (result & 0x0800u) << 15;
339 *inst |= (result & 0x0700u) << 4;
340 *inst |= (result & 0x00FFu);
341 // Hack for two 16bit.
342 *inst = ((*inst >> 16) & 0xFFFF) | (*inst << 16);
343 }
344 }
345 break;
346 }
347 //llvm::errs() << "S: " << (void *)S << '\n';
348 //llvm::errs() << "A: " << (void *)A << '\n';
349 //llvm::errs() << "P: " << (void *)P << '\n';
350 //llvm::errs() << "S+A: " << (void *)(S+A) << '\n';
351 //llvm::errs() << "S+A-P: " << (void *)(S+A-P) << '\n';
352 }
353 }
354
355 template <unsigned Bitwidth>
356 inline void ELFObject<Bitwidth>::
relocateX86_64(void * (* find_sym)(void * context,char const * name),void * context,ELFSectionRelTableTy * reltab,ELFSectionProgBitsTy * text)357 relocateX86_64(void *(*find_sym)(void *context, char const *name),
358 void *context,
359 ELFSectionRelTableTy *reltab,
360 ELFSectionProgBitsTy *text) {
361 rsl_assert(Bitwidth == 64 && "Only support X86_64.");
362
363 ELFSectionSymTabTy *symtab =
364 static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
365 rsl_assert(symtab && "Symtab is required.");
366
367 for (size_t i = 0; i < reltab->size(); ++i) {
368 // FIXME: Can not implement here, use Fixup!
369 ELFRelocTy *rel = (*reltab)[i];
370 ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
371
372 //typedef uint64_t Inst_t;
373 typedef int32_t Inst_t;
374 Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
375 Inst_t P = (Inst_t)(int64_t)inst;
376 Inst_t A = (Inst_t)(int64_t)rel->getAddend();
377 Inst_t S = (Inst_t)(int64_t)sym->getAddress(EM_X86_64);
378
379 if (S == 0) {
380 S = (Inst_t)(int64_t)find_sym(context, sym->getName());
381 if (!S) {
382 missingSymbols = true;
383 }
384 sym->setAddress((void *)S);
385 }
386
387 switch (rel->getType()) {
388 default:
389 rsl_assert(0 && "Not implemented relocation type.");
390 break;
391
392 // FIXME: XXX: R_X86_64_64 is 64 bit, there is a big problem here.
393 case 1: // R_X86_64_64
394 *inst = (S+A);
395 break;
396
397 case 2: // R_X86_64_PC32
398 *inst = (S+A-P);
399 break;
400
401 case 10: // R_X86_64_32
402 case 11: // R_X86_64_32S
403 *inst = (S+A);
404 break;
405 }
406 }
407 }
408
409 template <unsigned Bitwidth>
410 inline void ELFObject<Bitwidth>::
relocateX86_32(void * (* find_sym)(void * context,char const * name),void * context,ELFSectionRelTableTy * reltab,ELFSectionProgBitsTy * text)411 relocateX86_32(void *(*find_sym)(void *context, char const *name),
412 void *context,
413 ELFSectionRelTableTy *reltab,
414 ELFSectionProgBitsTy *text) {
415 rsl_assert(Bitwidth == 32 && "Only support X86.");
416
417 ELFSectionSymTabTy *symtab =
418 static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
419 rsl_assert(symtab && "Symtab is required.");
420
421 for (size_t i = 0; i < reltab->size(); ++i) {
422 // FIXME: Can not implement here, use Fixup!
423 ELFRelocTy *rel = (*reltab)[i];
424 ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
425
426 //typedef uint64_t Inst_t;
427 typedef int32_t Inst_t;
428 Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
429 Inst_t P = (Inst_t)(uintptr_t)inst;
430 Inst_t A = (Inst_t)(uintptr_t)*inst;
431 Inst_t S = (Inst_t)(uintptr_t)sym->getAddress(EM_386);
432
433 if (S == 0) {
434 S = (Inst_t)(uintptr_t)find_sym(context, sym->getName());
435 if (!S) {
436 missingSymbols = true;
437 }
438 sym->setAddress((void *)S);
439 }
440
441 switch (rel->getType()) {
442 default:
443 rsl_assert(0 && "Not implemented relocation type.");
444 break;
445
446 case R_386_PC32:
447 *inst = (S+A-P);
448 break;
449
450 case R_386_32:
451 *inst = (S+A);
452 break;
453 }
454 }
455 }
456
457 template <unsigned Bitwidth>
458 inline void ELFObject<Bitwidth>::
relocateMIPS(void * (* find_sym)(void * context,char const * name),void * context,ELFSectionRelTableTy * reltab,ELFSectionProgBitsTy * text)459 relocateMIPS(void *(*find_sym)(void *context, char const *name),
460 void *context,
461 ELFSectionRelTableTy *reltab,
462 ELFSectionProgBitsTy *text) {
463 rsl_assert(Bitwidth == 32 && "Only support 32-bit MIPS.");
464
465 ELFSectionSymTabTy *symtab =
466 static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
467 rsl_assert(symtab && "Symtab is required.");
468
469 for (size_t i = 0; i < reltab->size(); ++i) {
470 // FIXME: Can not implement here, use Fixup!
471 ELFRelocTy *rel = (*reltab)[i];
472 ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
473
474 typedef int32_t Inst_t;
475 Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
476 Inst_t P = (Inst_t)(uintptr_t)inst;
477 Inst_t A = (Inst_t)(uintptr_t)*inst;
478 Inst_t S = (Inst_t)(uintptr_t)sym->getAddress(EM_MIPS);
479
480 bool need_stub = false;
481
482 if (S == 0 && strcmp (sym->getName(), "_gp_disp") != 0) {
483 need_stub = true;
484 S = (Inst_t)(uintptr_t)find_sym(context, sym->getName());
485 if (!S) {
486 missingSymbols = true;
487 }
488 sym->setAddress((void *)S);
489 }
490
491 switch (rel->getType()) {
492 default:
493 rsl_assert(0 && "Not implemented relocation type.");
494 break;
495
496 case R_MIPS_NONE:
497 case R_MIPS_JALR: // ignore this
498 break;
499
500 case R_MIPS_16:
501 *inst &= 0xFFFF0000;
502 A = A & 0xFFFF;
503 A = S + (short)A;
504 rsl_assert(A >= -32768 && A <= 32767 && "R_MIPS_16 overflow.");
505 *inst |= (A & 0xFFFF);
506 break;
507
508 case R_MIPS_32:
509 *inst = S + A;
510 break;
511
512 case R_MIPS_26:
513 *inst &= 0xFC000000;
514 if (need_stub == false) {
515 A = (A & 0x3FFFFFF) << 2;
516 if (sym->getBindingAttribute() == STB_LOCAL) { // local binding
517 A |= ((P + 4) & 0xF0000000);
518 A += S;
519 *inst |= ((A >> 2) & 0x3FFFFFF);
520 } else { // external binding
521 if (A & 0x08000000) // Sign extend from bit 27
522 A |= 0xF0000000;
523 A += S;
524 *inst |= ((A >> 2) & 0x3FFFFFF);
525 if (((P + 4) >> 28) != (A >> 28)) { // far local call
526 void *stub = text->getStubLayout()->allocateStub((void *)A);
527 rsl_assert(stub && "cannot allocate stub.");
528 sym->setAddress(stub);
529 S = (int32_t)(intptr_t)stub;
530 *inst |= ((S >> 2) & 0x3FFFFFF);
531 rsl_assert(((P + 4) >> 28) == (S >> 28) && "stub is too far.");
532 }
533 }
534 } else { // shared-library call
535 A = (A & 0x3FFFFFF) << 2;
536 rsl_assert(A == 0 && "R_MIPS_26 addend is not zero.");
537 void *stub = text->getStubLayout()->allocateStub((void *)S);
538 rsl_assert(stub && "cannot allocate stub.");
539 sym->setAddress(stub);
540 S = (int32_t)(intptr_t)stub;
541 *inst |= ((S >> 2) & 0x3FFFFFF);
542 rsl_assert(((P + 4) >> 28) == (S >> 28) && "stub is too far.");
543 }
544 break;
545
546 case R_MIPS_HI16:
547 *inst &= 0xFFFF0000;
548 A = (A & 0xFFFF) << 16;
549 // Find the nearest LO16 relocation type after this entry
550 for (size_t j = i + 1; j < reltab->size(); j++) {
551 ELFRelocTy *this_rel = (*reltab)[j];
552 ELFSymbolTy *this_sym = (*symtab)[this_rel->getSymTabIndex()];
553 if (this_rel->getType() == R_MIPS_LO16 && this_sym == sym) {
554 Inst_t *this_inst = (Inst_t *)&(*text)[this_rel->getOffset()];
555 Inst_t this_A = (Inst_t)(uintptr_t)*this_inst;
556 this_A = this_A & 0xFFFF;
557 A += (short)this_A;
558 break;
559 }
560 }
561 if (strcmp (sym->getName(), "_gp_disp") == 0) {
562 S = (int)(intptr_t)got_address() + GP_OFFSET - (int)P;
563 sym->setAddress((void *)S);
564 }
565 *inst |= (((S + A + (int)0x8000) >> 16) & 0xFFFF);
566 break;
567
568 case R_MIPS_LO16:
569 *inst &= 0xFFFF0000;
570 A = A & 0xFFFF;
571 if (strcmp (sym->getName(), "_gp_disp") == 0) {
572 S = (Inst_t)(intptr_t)sym->getAddress(EM_MIPS);
573 }
574 *inst |= ((S + A) & 0xFFFF);
575 break;
576
577 case R_MIPS_GOT16:
578 case R_MIPS_CALL16:
579 {
580 *inst &= 0xFFFF0000;
581 A = A & 0xFFFF;
582 if (rel->getType() == R_MIPS_GOT16) {
583 if (sym->getBindingAttribute() == STB_LOCAL) {
584 A <<= 16;
585
586 // Find the nearest LO16 relocation type after this entry
587 for (size_t j = i + 1; j < reltab->size(); j++) {
588 ELFRelocTy *this_rel = (*reltab)[j];
589 ELFSymbolTy *this_sym = (*symtab)[this_rel->getSymTabIndex()];
590 if (this_rel->getType() == R_MIPS_LO16 && this_sym == sym) {
591 Inst_t *this_inst = (Inst_t *)&(*text)[this_rel->getOffset()];
592 Inst_t this_A = (Inst_t)(uintptr_t)*this_inst;
593 this_A = this_A & 0xFFFF;
594 A += (short)this_A;
595 break;
596 }
597 }
598 } else {
599 rsl_assert(A == 0 && "R_MIPS_GOT16 addend is not 0.");
600 }
601 } else { // R_MIPS_CALL16
602 rsl_assert(A == 0 && "R_MIPS_CALL16 addend is not 0.");
603 }
604 int got_index = search_got((int)rel->getSymTabIndex(), (void *)(S + A),
605 sym->getBindingAttribute());
606 int got_offset = (got_index << 2) - GP_OFFSET;
607 *inst |= (got_offset & 0xFFFF);
608 }
609 break;
610
611 case R_MIPS_GPREL32:
612 *inst = A + S - ((int)(intptr_t)got_address() + GP_OFFSET);
613 break;
614 }
615 }
616 }
617
618
619 // TODO: Refactor all relocations.
620 template <unsigned Bitwidth>
621 inline void ELFObject<Bitwidth>::
relocate(void * (* find_sym)(void * context,char const * name),void * context)622 relocate(void *(*find_sym)(void *context, char const *name), void *context) {
623 // Init SHNCommonDataSize.
624 // Need refactoring
625 size_t SHNCommonDataSize = 0;
626
627 ELFSectionSymTabTy *symtab =
628 static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
629 rsl_assert(symtab && "Symtab is required.");
630
631 for (size_t i = 0; i < symtab->size(); ++i) {
632 ELFSymbolTy *sym = (*symtab)[i];
633
634 if (sym->getType() != STT_OBJECT) {
635 continue;
636 }
637
638 size_t idx = (size_t)sym->getSectionIndex();
639 switch (idx) {
640 default:
641 if ((*shtab)[idx]->getType() == SHT_NOBITS) {
642 // FIXME(logan): This is a workaround for .lcomm directives
643 // bug of LLVM ARM MC code generator. Remove this when the
644 // LLVM bug is fixed.
645
646 size_t align = 16;
647 SHNCommonDataSize += (size_t)sym->getSize() + align;
648 }
649 break;
650
651 case SHN_COMMON:
652 {
653 size_t align = (size_t)sym->getValue();
654 SHNCommonDataSize += (size_t)sym->getSize() + align;
655 }
656 break;
657
658 case SHN_ABS:
659 case SHN_UNDEF:
660 case SHN_XINDEX:
661 break;
662 }
663 }
664 if (!initSHNCommonDataSize(SHNCommonDataSize)) {
665 rsl_assert("Allocate memory for common variable fail!");
666 // TODO: Refactor object loading to use proper status/error returns.
667 // We mark the object as having missing symbols and return early in this
668 // case to signal a loading error (usually due to running out of
669 // available memory to allocate).
670 missingSymbols = true;
671 return;
672 }
673
674 for (size_t i = 0; i < stab.size(); ++i) {
675 ELFSectionHeaderTy *sh = (*shtab)[i];
676 if (sh->getType() != SHT_REL && sh->getType() != SHT_RELA) {
677 continue;
678 }
679 ELFSectionRelTableTy *reltab =
680 static_cast<ELFSectionRelTableTy *>(stab[i]);
681 rsl_assert(reltab && "Relocation section can't be NULL.");
682
683 const char *reltab_name = sh->getName();
684 const char *need_rel_name;
685 if (sh->getType() == SHT_REL) {
686 need_rel_name = reltab_name + 4;
687 // ".rel.xxxx"
688 // ^ start from here.
689 } else {
690 need_rel_name = reltab_name + 5;
691 }
692
693 ELFSectionProgBitsTy *need_rel =
694 static_cast<ELFSectionProgBitsTy *>(getSectionByName(need_rel_name));
695 rsl_assert(need_rel && "Need be relocated section can't be NULL.");
696
697 switch (getHeader()->getMachine()) {
698 case EM_ARM:
699 relocateARM(find_sym, context, reltab, need_rel);
700 break;
701 case EM_386:
702 relocateX86_32(find_sym, context, reltab, need_rel);
703 break;
704 case EM_X86_64:
705 relocateX86_64(find_sym, context, reltab, need_rel);
706 break;
707 case EM_MIPS:
708 relocateMIPS(find_sym, context, reltab, need_rel);
709 break;
710
711 default:
712 rsl_assert(0 && "Only support ARM, MIPS, X86, and X86_64 relocation.");
713 break;
714 }
715 }
716
717 for (size_t i = 0; i < stab.size(); ++i) {
718 ELFSectionHeaderTy *sh = (*shtab)[i];
719 if (sh->getType() == SHT_PROGBITS || sh->getType() == SHT_NOBITS) {
720 if (stab[i]) {
721 static_cast<ELFSectionBitsTy *>(stab[i])->protect();
722 }
723 }
724 }
725 }
726
727 template <unsigned Bitwidth>
print() const728 inline void ELFObject<Bitwidth>::print() const {
729 header->print();
730 shtab->print();
731
732 for (size_t i = 0; i < stab.size(); ++i) {
733 ELFSectionTy *sec = stab[i];
734 if (sec) {
735 sec->print();
736 }
737 }
738 }
739
740 #endif // ELF_OBJECT_HXX
741