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 switch (rel->getType()) {
153 default:
154 rsl_assert(0 && "Not implemented relocation type.");
155 break;
156
157 case R_ARM_ABS32:
158 {
159 if (S == 0 && sym->getType() == STT_NOTYPE) {
160 void *ext_sym = find_sym(context, sym->getName());
161 if (!ext_sym) {
162 missingSymbols = true;
163 }
164 S = (Inst_t)(uintptr_t)ext_sym;
165 sym->setAddress(ext_sym);
166 }
167 A = *inst;
168 *inst = (S + A) | T;
169 }
170 break;
171
172 // FIXME: Predefine relocation codes.
173 case R_ARM_CALL:
174 case R_ARM_THM_CALL:
175 {
176 #define SIGN_EXTEND(x, l) (((x)^(1<<((l)-1)))-(1<<(l-1)))
177 if (rel->getType() == R_ARM_CALL) {
178 A = (Inst_t)(int64_t)SIGN_EXTEND(*inst & 0xFFFFFF, 24);
179 A <<= 2;
180 } else {
181 // Hack for two 16bit.
182 *inst = ((*inst >> 16) & 0xFFFF) | (*inst << 16);
183 Inst_t s = (*inst >> 26) & 0x1u, // 26
184 u = (*inst >> 16) & 0x3FFu, // 25-16
185 l = *inst & 0x7FFu, // 10-0
186 j1 = (*inst >> 13) & 0x1u, // 13
187 j2 = (*inst >> 11) & 0x1u; // 11
188 Inst_t i1 = (~(j1 ^ s)) & 0x1u,
189 i2 = (~(j2 ^ s)) & 0x1u;
190 // [31-25][24][23][22][21-12][11-1][0]
191 // 0 s i1 i2 u l 0
192 A = SIGN_EXTEND((s << 23) | (i1 << 22) | (i2 << 21) | (u << 11) | l, 24);
193 A <<= 1;
194 }
195 #undef SIGN_EXTEND
196
197 void *callee_addr = sym->getAddress(EM_ARM);
198
199 switch (sym->getType()) {
200 default:
201 rsl_assert(0 && "Wrong type for R_ARM_CALL relocation.");
202 abort();
203 break;
204
205 case STT_FUNC:
206 // NOTE: Callee function is in the object file, but it may be
207 // in different PROGBITS section (which may be far call).
208
209 if (callee_addr == 0) {
210 rsl_assert(0 && "We should get function address at previous "
211 "sym->getAddress(EM_ARM) function call.");
212 abort();
213 }
214 break;
215
216 case STT_NOTYPE:
217 // NOTE: Callee function is an external function. Call find_sym
218 // if it has not resolved yet.
219
220 if (callee_addr == 0) {
221 callee_addr = find_sym(context, sym->getName());
222 if (!callee_addr) {
223 missingSymbols = true;
224 }
225 sym->setAddress(callee_addr);
226 }
227 break;
228 }
229
230 // Get the stub for this function
231 StubLayout *stub_layout = text->getStubLayout();
232
233 if (!stub_layout) {
234 llvm::errs() << "unable to get stub layout." << "\n";
235 abort();
236 }
237
238 void *stub = stub_layout->allocateStub(callee_addr);
239
240 if (!stub) {
241 llvm::errs() << "unable to allocate stub." << "\n";
242 abort();
243 }
244
245 //LOGI("Function %s: using stub %p\n", sym->getName(), stub);
246 S = (uint32_t)(uintptr_t)stub;
247
248 if (rel->getType() == R_ARM_CALL) {
249 // Relocate the R_ARM_CALL relocation type
250 uint32_t result = (S + A - P) >> 2;
251
252 if (result > 0x007FFFFF && result < 0xFF800000) {
253 rsl_assert(0 && "Stub is still too far");
254 abort();
255 }
256
257 *inst = ((result) & 0x00FFFFFF) | (*inst & 0xFF000000);
258 } else {
259 P &= ~0x3; // Base address align to 4 bytes. (For BLX.)
260
261 // Relocate the R_ARM_THM_CALL relocation type
262 uint32_t result = (S + A - P) >> 1;
263
264 if (result > 0x007FFFFF && result < 0xFF800000) {
265 rsl_assert(0 && "Stub is still too far");
266 abort();
267 }
268
269 //*inst &= 0xF800D000u;
270 // Rewrite instruction to BLX. (Stub is always ARM.)
271 *inst &= 0xF800C000u;
272 // [31-25][24][23][22][21-12][11-1][0]
273 // 0 s i1 i2 u l 0
274 Inst_t s = (result >> 23) & 0x1u, // 26
275 u = (result >> 11) & 0x3FFu, // 25-16
276 // For BLX, bit [0] is 0.
277 l = result & 0x7FEu, // 10-0
278 i1 = (result >> 22) & 0x1u,
279 i2 = (result >> 21) & 0x1u;
280 Inst_t j1 = ((~i1) ^ s) & 0x01u, // 13
281 j2 = ((~i2) ^ s) & 0x01u; // 11
282 *inst |= s << 26;
283 *inst |= u << 16;
284 *inst |= l;
285 *inst |= j1 << 13;
286 *inst |= j2 << 11;
287 // Hack for two 16bit.
288 *inst = ((*inst >> 16) & 0xFFFF) | (*inst << 16);
289 }
290 }
291 break;
292 case R_ARM_MOVT_ABS:
293 case R_ARM_MOVW_ABS_NC:
294 case R_ARM_THM_MOVW_ABS_NC:
295 case R_ARM_THM_MOVT_ABS:
296 {
297 if (S == 0 && sym->getType() == STT_NOTYPE) {
298 void *ext_sym = find_sym(context, sym->getName());
299 if (!ext_sym) {
300 missingSymbols = true;
301 }
302 S = (Inst_t)(uintptr_t)ext_sym;
303 sym->setAddress(ext_sym);
304 }
305 if (rel->getType() == R_ARM_MOVT_ABS
306 || rel->getType() == R_ARM_THM_MOVT_ABS) {
307 S >>= 16;
308 }
309
310 if (rel->getType() == R_ARM_MOVT_ABS
311 || rel->getType() == R_ARM_MOVW_ABS_NC) {
312 // No need sign extend.
313 A = ((*inst & 0xF0000) >> 4) | (*inst & 0xFFF);
314 uint32_t result = (S + A);
315 *inst = (((result) & 0xF000) << 4) |
316 ((result) & 0xFFF) |
317 (*inst & 0xFFF0F000);
318 } else {
319 // Hack for two 16bit.
320 *inst = ((*inst >> 16) & 0xFFFF) | (*inst << 16);
321 // imm16: [19-16][26][14-12][7-0]
322 A = (((*inst >> 4) & 0xF000u) |
323 ((*inst >> 15) & 0x0800u) |
324 ((*inst >> 4) & 0x0700u) |
325 ( *inst & 0x00FFu));
326 uint32_t result;
327 if (rel->getType() == R_ARM_THM_MOVT_ABS) {
328 result = (S + A);
329 } else {
330 result = (S + A) | T;
331 }
332 // imm16: [19-16][26][14-12][7-0]
333 *inst &= 0xFBF08F00u;
334 *inst |= (result & 0xF000u) << 4;
335 *inst |= (result & 0x0800u) << 15;
336 *inst |= (result & 0x0700u) << 4;
337 *inst |= (result & 0x00FFu);
338 // Hack for two 16bit.
339 *inst = ((*inst >> 16) & 0xFFFF) | (*inst << 16);
340 }
341 }
342 break;
343 }
344 //llvm::errs() << "S: " << (void *)S << '\n';
345 //llvm::errs() << "A: " << (void *)A << '\n';
346 //llvm::errs() << "P: " << (void *)P << '\n';
347 //llvm::errs() << "S+A: " << (void *)(S+A) << '\n';
348 //llvm::errs() << "S+A-P: " << (void *)(S+A-P) << '\n';
349 }
350 }
351
352 template <unsigned Bitwidth>
353 inline void ELFObject<Bitwidth>::
relocateX86_64(void * (* find_sym)(void * context,char const * name),void * context,ELFSectionRelTableTy * reltab,ELFSectionProgBitsTy * text)354 relocateX86_64(void *(*find_sym)(void *context, char const *name),
355 void *context,
356 ELFSectionRelTableTy *reltab,
357 ELFSectionProgBitsTy *text) {
358 rsl_assert(Bitwidth == 64 && "Only support X86_64.");
359
360 ELFSectionSymTabTy *symtab =
361 static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
362 rsl_assert(symtab && "Symtab is required.");
363
364 for (size_t i = 0; i < reltab->size(); ++i) {
365 // FIXME: Can not implement here, use Fixup!
366 ELFRelocTy *rel = (*reltab)[i];
367 ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
368
369 //typedef uint64_t Inst_t;
370 typedef int32_t Inst_t;
371 Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
372 Inst_t P = (Inst_t)(int64_t)inst;
373 Inst_t A = (Inst_t)(int64_t)rel->getAddend();
374 Inst_t S = (Inst_t)(int64_t)sym->getAddress(EM_X86_64);
375
376 if (S == 0) {
377 S = (Inst_t)(int64_t)find_sym(context, sym->getName());
378 if (!S) {
379 missingSymbols = true;
380 }
381 sym->setAddress((void *)S);
382 }
383
384 switch (rel->getType()) {
385 default:
386 rsl_assert(0 && "Not implemented relocation type.");
387 break;
388
389 // FIXME: XXX: R_X86_64_64 is 64 bit, there is a big problem here.
390 case 1: // R_X86_64_64
391 *inst = (S+A);
392 break;
393
394 case 2: // R_X86_64_PC32
395 *inst = (S+A-P);
396 break;
397
398 case 10: // R_X86_64_32
399 case 11: // R_X86_64_32S
400 *inst = (S+A);
401 break;
402 }
403 }
404 }
405
406 template <unsigned Bitwidth>
407 inline void ELFObject<Bitwidth>::
relocateX86_32(void * (* find_sym)(void * context,char const * name),void * context,ELFSectionRelTableTy * reltab,ELFSectionProgBitsTy * text)408 relocateX86_32(void *(*find_sym)(void *context, char const *name),
409 void *context,
410 ELFSectionRelTableTy *reltab,
411 ELFSectionProgBitsTy *text) {
412 rsl_assert(Bitwidth == 32 && "Only support X86.");
413
414 ELFSectionSymTabTy *symtab =
415 static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
416 rsl_assert(symtab && "Symtab is required.");
417
418 for (size_t i = 0; i < reltab->size(); ++i) {
419 // FIXME: Can not implement here, use Fixup!
420 ELFRelocTy *rel = (*reltab)[i];
421 ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
422
423 //typedef uint64_t Inst_t;
424 typedef int32_t Inst_t;
425 Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
426 Inst_t P = (Inst_t)(uintptr_t)inst;
427 Inst_t A = (Inst_t)(uintptr_t)*inst;
428 Inst_t S = (Inst_t)(uintptr_t)sym->getAddress(EM_386);
429
430 if (S == 0) {
431 S = (Inst_t)(uintptr_t)find_sym(context, sym->getName());
432 if (!S) {
433 missingSymbols = true;
434 }
435 sym->setAddress((void *)S);
436 }
437
438 switch (rel->getType()) {
439 default:
440 rsl_assert(0 && "Not implemented relocation type.");
441 break;
442
443 case R_386_PC32:
444 *inst = (S+A-P);
445 break;
446
447 case R_386_32:
448 *inst = (S+A);
449 break;
450 }
451 }
452 }
453
454 template <unsigned Bitwidth>
455 inline void ELFObject<Bitwidth>::
relocateMIPS(void * (* find_sym)(void * context,char const * name),void * context,ELFSectionRelTableTy * reltab,ELFSectionProgBitsTy * text)456 relocateMIPS(void *(*find_sym)(void *context, char const *name),
457 void *context,
458 ELFSectionRelTableTy *reltab,
459 ELFSectionProgBitsTy *text) {
460 rsl_assert(Bitwidth == 32 && "Only support 32-bit MIPS.");
461
462 ELFSectionSymTabTy *symtab =
463 static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
464 rsl_assert(symtab && "Symtab is required.");
465
466 for (size_t i = 0; i < reltab->size(); ++i) {
467 // FIXME: Can not implement here, use Fixup!
468 ELFRelocTy *rel = (*reltab)[i];
469 ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
470
471 typedef int32_t Inst_t;
472 Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
473 Inst_t P = (Inst_t)(uintptr_t)inst;
474 Inst_t A = (Inst_t)(uintptr_t)*inst;
475 Inst_t S = (Inst_t)(uintptr_t)sym->getAddress(EM_MIPS);
476
477 bool need_stub = false;
478
479 if (S == 0 && strcmp (sym->getName(), "_gp_disp") != 0) {
480 need_stub = true;
481 S = (Inst_t)(uintptr_t)find_sym(context, sym->getName());
482 if (!S) {
483 missingSymbols = true;
484 }
485 sym->setAddress((void *)S);
486 }
487
488 switch (rel->getType()) {
489 default:
490 rsl_assert(0 && "Not implemented relocation type.");
491 break;
492
493 case R_MIPS_NONE:
494 case R_MIPS_JALR: // ignore this
495 break;
496
497 case R_MIPS_16:
498 *inst &= 0xFFFF0000;
499 A = A & 0xFFFF;
500 A = S + (short)A;
501 rsl_assert(A >= -32768 && A <= 32767 && "R_MIPS_16 overflow.");
502 *inst |= (A & 0xFFFF);
503 break;
504
505 case R_MIPS_32:
506 *inst = S + A;
507 break;
508
509 case R_MIPS_26:
510 *inst &= 0xFC000000;
511 if (need_stub == false) {
512 A = (A & 0x3FFFFFF) << 2;
513 if (sym->getBindingAttribute() == STB_LOCAL) { // local binding
514 A |= ((P + 4) & 0xF0000000);
515 A += S;
516 *inst |= ((A >> 2) & 0x3FFFFFF);
517 } else { // external binding
518 if (A & 0x08000000) // Sign extend from bit 27
519 A |= 0xF0000000;
520 A += S;
521 *inst |= ((A >> 2) & 0x3FFFFFF);
522 if (((P + 4) >> 28) != (A >> 28)) { // far local call
523 void *stub = text->getStubLayout()->allocateStub((void *)A);
524 rsl_assert(stub && "cannot allocate stub.");
525 sym->setAddress(stub);
526 S = (int32_t)(intptr_t)stub;
527 *inst |= ((S >> 2) & 0x3FFFFFF);
528 rsl_assert(((P + 4) >> 28) == (S >> 28) && "stub is too far.");
529 }
530 }
531 } else { // shared-library call
532 A = (A & 0x3FFFFFF) << 2;
533 rsl_assert(A == 0 && "R_MIPS_26 addend is not zero.");
534 void *stub = text->getStubLayout()->allocateStub((void *)S);
535 rsl_assert(stub && "cannot allocate stub.");
536 sym->setAddress(stub);
537 S = (int32_t)(intptr_t)stub;
538 *inst |= ((S >> 2) & 0x3FFFFFF);
539 rsl_assert(((P + 4) >> 28) == (S >> 28) && "stub is too far.");
540 }
541 break;
542
543 case R_MIPS_HI16:
544 *inst &= 0xFFFF0000;
545 A = (A & 0xFFFF) << 16;
546 // Find the nearest LO16 relocation type after this entry
547 for (size_t j = i + 1; j < reltab->size(); j++) {
548 ELFRelocTy *this_rel = (*reltab)[j];
549 ELFSymbolTy *this_sym = (*symtab)[this_rel->getSymTabIndex()];
550 if (this_rel->getType() == R_MIPS_LO16 && this_sym == sym) {
551 Inst_t *this_inst = (Inst_t *)&(*text)[this_rel->getOffset()];
552 Inst_t this_A = (Inst_t)(uintptr_t)*this_inst;
553 this_A = this_A & 0xFFFF;
554 A += (short)this_A;
555 break;
556 }
557 }
558 if (strcmp (sym->getName(), "_gp_disp") == 0) {
559 S = (int)(intptr_t)got_address() + GP_OFFSET - (int)P;
560 sym->setAddress((void *)S);
561 }
562 *inst |= (((S + A + (int)0x8000) >> 16) & 0xFFFF);
563 break;
564
565 case R_MIPS_LO16:
566 *inst &= 0xFFFF0000;
567 A = A & 0xFFFF;
568 if (strcmp (sym->getName(), "_gp_disp") == 0) {
569 S = (Inst_t)(intptr_t)sym->getAddress(EM_MIPS);
570 }
571 *inst |= ((S + A) & 0xFFFF);
572 break;
573
574 case R_MIPS_GOT16:
575 case R_MIPS_CALL16:
576 {
577 *inst &= 0xFFFF0000;
578 A = A & 0xFFFF;
579 if (rel->getType() == R_MIPS_GOT16) {
580 if (sym->getBindingAttribute() == STB_LOCAL) {
581 A <<= 16;
582
583 // Find the nearest LO16 relocation type after this entry
584 for (size_t j = i + 1; j < reltab->size(); j++) {
585 ELFRelocTy *this_rel = (*reltab)[j];
586 ELFSymbolTy *this_sym = (*symtab)[this_rel->getSymTabIndex()];
587 if (this_rel->getType() == R_MIPS_LO16 && this_sym == sym) {
588 Inst_t *this_inst = (Inst_t *)&(*text)[this_rel->getOffset()];
589 Inst_t this_A = (Inst_t)(uintptr_t)*this_inst;
590 this_A = this_A & 0xFFFF;
591 A += (short)this_A;
592 break;
593 }
594 }
595 } else {
596 rsl_assert(A == 0 && "R_MIPS_GOT16 addend is not 0.");
597 }
598 } else { // R_MIPS_CALL16
599 rsl_assert(A == 0 && "R_MIPS_CALL16 addend is not 0.");
600 }
601 int got_index = search_got((int)rel->getSymTabIndex(), (void *)(S + A),
602 sym->getBindingAttribute());
603 int got_offset = (got_index << 2) - GP_OFFSET;
604 *inst |= (got_offset & 0xFFFF);
605 }
606 break;
607
608 case R_MIPS_GPREL32:
609 *inst = A + S - ((int)(intptr_t)got_address() + GP_OFFSET);
610 break;
611 }
612 }
613 }
614
615
616 // TODO: Refactor all relocations.
617 template <unsigned Bitwidth>
618 inline void ELFObject<Bitwidth>::
relocate(void * (* find_sym)(void * context,char const * name),void * context)619 relocate(void *(*find_sym)(void *context, char const *name), void *context) {
620 // Init SHNCommonDataSize.
621 // Need refactoring
622 size_t SHNCommonDataSize = 0;
623
624 ELFSectionSymTabTy *symtab =
625 static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
626 rsl_assert(symtab && "Symtab is required.");
627
628 for (size_t i = 0; i < symtab->size(); ++i) {
629 ELFSymbolTy *sym = (*symtab)[i];
630
631 if (sym->getType() != STT_OBJECT) {
632 continue;
633 }
634
635 size_t idx = (size_t)sym->getSectionIndex();
636 switch (idx) {
637 default:
638 if ((*shtab)[idx]->getType() == SHT_NOBITS) {
639 // FIXME(logan): This is a workaround for .lcomm directives
640 // bug of LLVM ARM MC code generator. Remove this when the
641 // LLVM bug is fixed.
642
643 size_t align = 16;
644 SHNCommonDataSize += (size_t)sym->getSize() + align;
645 }
646 break;
647
648 case SHN_COMMON:
649 {
650 size_t align = (size_t)sym->getValue();
651 SHNCommonDataSize += (size_t)sym->getSize() + align;
652 }
653 break;
654
655 case SHN_ABS:
656 case SHN_UNDEF:
657 case SHN_XINDEX:
658 break;
659 }
660 }
661 if (!initSHNCommonDataSize(SHNCommonDataSize)) {
662 rsl_assert("Allocate memory for common variable fail!");
663 }
664
665 for (size_t i = 0; i < stab.size(); ++i) {
666 ELFSectionHeaderTy *sh = (*shtab)[i];
667 if (sh->getType() != SHT_REL && sh->getType() != SHT_RELA) {
668 continue;
669 }
670 ELFSectionRelTableTy *reltab =
671 static_cast<ELFSectionRelTableTy *>(stab[i]);
672 rsl_assert(reltab && "Relocation section can't be NULL.");
673
674 const char *reltab_name = sh->getName();
675 const char *need_rel_name;
676 if (sh->getType() == SHT_REL) {
677 need_rel_name = reltab_name + 4;
678 // ".rel.xxxx"
679 // ^ start from here.
680 } else {
681 need_rel_name = reltab_name + 5;
682 }
683
684 ELFSectionProgBitsTy *need_rel =
685 static_cast<ELFSectionProgBitsTy *>(getSectionByName(need_rel_name));
686 rsl_assert(need_rel && "Need be relocated section can't be NULL.");
687
688 switch (getHeader()->getMachine()) {
689 case EM_ARM:
690 relocateARM(find_sym, context, reltab, need_rel);
691 break;
692 case EM_386:
693 relocateX86_32(find_sym, context, reltab, need_rel);
694 break;
695 case EM_X86_64:
696 relocateX86_64(find_sym, context, reltab, need_rel);
697 break;
698 case EM_MIPS:
699 relocateMIPS(find_sym, context, reltab, need_rel);
700 break;
701
702 default:
703 rsl_assert(0 && "Only support ARM, MIPS, X86, and X86_64 relocation.");
704 break;
705 }
706 }
707
708 for (size_t i = 0; i < stab.size(); ++i) {
709 ELFSectionHeaderTy *sh = (*shtab)[i];
710 if (sh->getType() == SHT_PROGBITS || sh->getType() == SHT_NOBITS) {
711 if (stab[i]) {
712 static_cast<ELFSectionBitsTy *>(stab[i])->protect();
713 }
714 }
715 }
716 }
717
718 template <unsigned Bitwidth>
print() const719 inline void ELFObject<Bitwidth>::print() const {
720 header->print();
721 shtab->print();
722
723 for (size_t i = 0; i < stab.size(); ++i) {
724 ELFSectionTy *sec = stab[i];
725 if (sec) {
726 sec->print();
727 }
728 }
729 }
730
731 #endif // ELF_OBJECT_HXX
732