00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <cstdlib>
00037 #include <cstdio>
00038 #include <cassert>
00039 #include <iostream>
00040 #include <set>
00041 #include <map>
00042 #include <sstream>
00043
00044 #include "emitElfStatic.h"
00045 #include "Symtab.h"
00046 #include "Symbol.h"
00047 #include "Archive.h"
00048 #include "Object.h"
00049 #include "Region.h"
00050 #include "debug.h"
00051 #include "common/h/arch-power.h"
00052
00053 using namespace Dyninst;
00054 using namespace Dyninst::SymtabAPI;
00055 using namespace NS_power;
00056
00057 static const unsigned PPC32_WIDTH = 4;
00058 static const unsigned PPC64_WIDTH = 8;
00059
00060 static const Elf64_Word X86_HEADER = 0xffffffff;
00061 static const Elf64_Word X86_TRAILER = 0x00000000;
00062 static const Elf64_Xword X86_64_HEADER = 0xffffffffffffffffULL;
00063 static const Elf64_Xword X86_64_TRAILER = 0x0000000000000000ULL;
00064
00065 static const Offset GOT_RESERVED_SLOTS = 0;
00066
00067 unsigned int setBits(unsigned int target, unsigned int pos, unsigned int len, unsigned int value) {
00068 rewrite_printf("setBits target 0x%lx value 0x%lx pos %d len %d \n", target, value, pos, len);
00069
00070
00071 unsigned int mask, mask1, mask2;
00072 mask1 = ~(~0 << pos);
00073 mask1 = (mask1 << (32-pos));
00074 mask2 = ~(~0 << (32-(pos+len)));
00075 mask = mask1 | mask2;
00076 target = target & mask;
00077 rewrite_printf(" mask1 0x%lx mask2 0x%lx mask 0x%lx target 0x%lx \n", mask1, mask2, mask, target);
00078
00079 if(len != 32)
00080 mask = ~mask;
00081
00082 value = value & mask;
00083 rewrite_printf(" mask 0x%lx value 0x%lx \n", mask, value);
00084 target = target | value;
00085 rewrite_printf( "setBits target 0x%lx value 0x%lx pos %d len %d \n", target, value, pos, len);
00086
00087 return target;
00088 }
00089
00090 unsigned long setBits64(unsigned long target, unsigned int pos, unsigned int len, unsigned long value) {
00091 unsigned long mask;
00092 mask = ~(~0 << len);
00093 mask = (mask << pos);
00094 target = target & mask;
00095 if(len != 32)
00096 mask = ~mask;
00097 value = value & mask;
00098
00099 target = target | value;
00100 return target;
00101 }
00102
00103
00104 #if defined(os_freebsd)
00105 #define R_X86_64_JUMP_SLOT R_X86_64_JMP_SLOT
00106 #endif
00107
00108
00109 #define UNKNOWN_ADDRESS_WIDTH_ASSERT "An unknown address width was encountered, can't continue"
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 static bool computeCtorDtorAddress(relocationEntry &rel, Offset globalOffset,
00134 LinkMap &lmap, string &errMsg, Offset &symbolOffset)
00135 {
00136 if( rel.name() == SYMTAB_CTOR_LIST_REL ) {
00137
00138 if( lmap.newCtorRegions.size() > 0 ) {
00139 symbolOffset = lmap.ctorRegionOffset + globalOffset;
00140 rewrite_printf("new CTOR computeCtorDtorAddress symbolOffset 0x%lx \n", symbolOffset);
00141 }else if( lmap.originalCtorRegion != NULL ) {
00142 symbolOffset = lmap.originalCtorRegion->getMemOffset();
00143 rewrite_printf("original CTOR computeCtorDtorAddress symbolOffset 0x%lx \n", symbolOffset);
00144 }else{
00145 errMsg = "Failed to locate original .ctors Region -- cannot apply relocation";
00146 rewrite_printf("Failed to locate original .ctors Region -- cannot apply relocation\n");
00147 return false;
00148 }
00149 }else if( rel.name() == SYMTAB_DTOR_LIST_REL ) {
00150
00151 if( lmap.newDtorRegions.size() > 0 ) {
00152 symbolOffset = lmap.dtorRegionOffset + globalOffset;
00153 }else if( lmap.originalDtorRegion != NULL ) {
00154 symbolOffset = lmap.originalDtorRegion->getMemOffset();
00155 }else{
00156 errMsg = "Failed to locate original .dtors Region -- cannot apply relocation";
00157 rewrite_printf("Failed to locate original .dtors Region -- cannot apply relocation\n");
00158 return false;
00159 }
00160 }
00161 return true;
00162 }
00163
00164
00165 bool emitElfStatic::archSpecificRelocation(Symtab* targetSymtab, Symtab* srcSymtab,
00166 char *targetData, relocationEntry &rel,
00167 Offset dest, Offset relOffset, Offset globalOffset, LinkMap &lmap,
00168 string &errMsg)
00169 {
00170 if( PPC64_WIDTH == addressWidth_ ) {
00171 Symbol *dynsym = rel.getDynSym();
00172
00173
00174 Offset newTOCoffset = 0;
00175 if (dynsym->getModule()) {
00176 newTOCoffset = dynsym->getSymtab()->getTOCoffset(dynsym->getOffset());
00177 }
00178
00179
00180 Offset curTOCoffset = srcSymtab->getTOCoffset((Offset) 0);
00181
00182 rewrite_printf(" archSpecificRelocation %s\ndynsym %s, reloc offset 0x%lx\n new TOC 0x%lx, cur TOC 0x%x\n dest 0x%lx \n",
00183 rel.name().c_str(),
00184 dynsym->getMangledName().c_str(), relOffset,
00185 newTOCoffset, curTOCoffset, dest);
00186
00187 if (rel.getRelType() == R_PPC64_JMP_SLOT) {
00188
00189
00190
00191
00192
00193
00194
00195 relocationEntry func = rel;
00196 func.setRelType(R_PPC64_GLOB_DAT);
00197 if (!archSpecificRelocation(targetSymtab, srcSymtab, targetData, func,
00198 dest, relOffset, globalOffset, lmap, errMsg)) {
00199 return false;
00200 }
00201 relocationEntry toc = rel;
00202 toc.setRelType(R_PPC64_TOC);
00203
00204 toc.setTargetAddr(toc.target_addr() + 8);
00205 if (!archSpecificRelocation(targetSymtab, srcSymtab, targetData, toc,
00206 dest + 8, relOffset + 8, globalOffset, lmap, errMsg)) {
00207 return false;
00208 }
00209 return true;
00210 }
00211
00212 int relocation_length = sizeof(Elf64_Word)*8;
00213 int relocation_pos = 0;
00214 int branch_pred = -1;
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225 Offset symbolOffset = rel.getDynSym()->getOffset();
00226
00227 Elf64_Word addend;
00228 if( rel.regionType() == Region::RT_REL ) {
00229 memcpy(&addend, &targetData[dest], sizeof(Elf64_Word));
00230 }else if( rel.regionType() == Region::RT_RELA ) {
00231 addend = rel.addend();
00232 }
00233
00234 if(!computeCtorDtorAddress(rel, globalOffset, lmap, errMsg, symbolOffset)) {
00235 return false;
00236 }
00237
00238
00239
00240 if (rel.getRelType() == R_PPC64_REL24 &&
00241 newTOCoffset != curTOCoffset &&
00242 handleInterModuleSpecialCase(targetSymtab, srcSymtab, lmap,
00243 targetData, rel,
00244 newTOCoffset, curTOCoffset, dest,
00245 relOffset, globalOffset)) {
00246 return true;
00247 }
00248
00249
00250 if(rel.getRelType() == R_PPC64_TOC16_DS || rel.getRelType() == R_PPC64_TOC16) {
00251 vector<Region *> allRegions;
00252 srcSymtab->getAllRegions(allRegions);
00253 vector<Region *>::iterator region_it;
00254 for(region_it = allRegions.begin(); region_it != allRegions.end(); ++region_it) {
00255 if((*region_it)->getRegionName().compare(".toc") == 0) {
00256 map<Region *, LinkMap::AllocPair>::iterator result = lmap.regionAllocs.find(*region_it);
00257 if( result != lmap.regionAllocs.end() ) {
00258 Offset regionOffset = result->second.second;
00259 symbolOffset = globalOffset + regionOffset;
00260 rewrite_printf("\tregionOffset 0x%lx symbolOffset 0x%lx \n", regionOffset, symbolOffset);
00261 break;
00262 }
00263 }
00264 }
00265 }
00266
00267 rewrite_printf("\trelocation for '%s': TYPE = %s(%lu) S = %lx A = %lx P = %lx Total 0x%lx \n",
00268 rel.name().c_str(),
00269 relocationEntry::relType2Str(rel.getRelType(), addressWidth_),
00270 rel.getRelType(), symbolOffset, addend, relOffset, symbolOffset+addend);
00271
00272
00273 Offset relocation = 0;
00274 map<Symbol *, Offset>::iterator result;
00275 stringstream tmp;
00276
00277 switch(rel.getRelType()) {
00278
00279 case R_PPC64_ADDR64:
00280 case R_PPC64_GLOB_DAT:
00281
00282 relocation_length = 64;
00283 relocation = symbolOffset + addend;
00284 break;
00285 case R_PPC64_REL24:
00286 case R_PPC64_GOT_TPREL16_DS:
00287
00288 relocation_length = 24;
00289 relocation_pos = 6;
00290
00291 relocation = symbolOffset + addend - relOffset;
00292
00293
00294 break;
00295 case R_PPC64_REL32:
00296
00297 relocation_length = 24;
00298 relocation_pos = 6;
00299 relocation = symbolOffset + addend - relOffset;
00300 break;
00301 case R_PPC64_REL64:
00302
00303 relocation = symbolOffset + addend - relOffset;
00304 break;
00305 case R_PPC64_TLS:
00306 rewrite_printf("TLS - UNIMPLEMENTED\n");
00307 break;
00308 case R_PPC64_TOC16:
00309
00310 relocation_length = 16;
00311 relocation_pos = 0;
00312 relocation = symbolOffset + addend - newTOCoffset;
00313 break;
00314 case R_PPC64_TOC16_DS:
00315
00316 relocation_length = 16;
00317 relocation_pos = 16;
00318 relocation = (symbolOffset + addend - newTOCoffset) >> 2 ;
00319 relocation = relocation << 2;
00320 break;
00321 case R_PPC64_TOC:
00322
00323 relocation_length = 64;
00324 relocation = newTOCoffset;
00325 break;
00326 default:
00327 assert(0);
00328 }
00329 rewrite_printf("\tbefore: relocation = 0x%lx @ 0x%lx target data %lx %lx %lx %lx %lx %lx \n",
00330 relocation, relOffset,targetData[dest-2], targetData[dest-1], targetData[dest], targetData[dest+1], targetData[dest+2], targetData[dest+3]);
00331
00332 if (relocation_length == 64) {
00333 char *td = (targetData + dest - (dest%8));
00334 unsigned long target = *((unsigned long *) td);
00335 target = setBits64(target, relocation_pos, relocation_length, relocation);
00336 memcpy(td, &target, 2*sizeof(Elf64_Word));
00337 } else {
00338 char *td = (targetData + dest - (dest%4));
00339 unsigned int target = *((unsigned int *) td);
00340 target = setBits(target, relocation_pos, relocation_length, relocation);
00341 memcpy(td, &target, sizeof(Elf64_Word));
00342 }
00343
00344 rewrite_printf("\tafter: relocation = 0x%lx @ 0x%lx target data %lx %lx %lx %lx %lx %lx \n", relocation, relOffset,targetData[dest-2], targetData[dest-1], targetData[dest], targetData[dest+1], targetData[dest+2], targetData[dest+3]);
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356 #if 0
00357 switch(0){
00358 case R_PPC64_NONE :
00359 case R_PPC64_ADDR32 :
00360 case R_PPC64_ADDR24 :
00361 case R_PPC64_ADDR16 :
00362 case R_PPC64_ADDR16_LO :
00363 case R_PPC64_ADDR16_HI :
00364 case R_PPC64_ADDR16_HA :
00365 case R_PPC64_ADDR14 :
00366 case R_PPC64_ADDR14_BRTAKEN :
00367 case R_PPC64_ADDR14_BRNTAKEN:
00368 case R_PPC64_REL24 :
00369 case R_PPC64_REL14 :
00370 case R_PPC64_REL14_BRTAKEN :
00371 case R_PPC64_REL14_BRNTAKEN :
00372 case R_PPC64_GOT16 :
00373 case R_PPC64_GOT16_LO :
00374 case R_PPC64_GOT16_HI :
00375 case R_PPC64_GOT16_HA :
00376 case R_PPC64_COPY :
00377 case R_PPC64_GLOB_DAT :
00378 case R_PPC64_JMP_SLOT :
00379 case R_PPC64_RELATIVE :
00380 case R_PPC64_UADDR32 :
00381 case R_PPC64_UADDR16 :
00382 case R_PPC64_REL32 :
00383 case R_PPC64_PLT32 :
00384 case R_PPC64_PLTREL32 :
00385 case R_PPC64_PLT16_LO :
00386 case R_PPC64_PLT16_HI :
00387 case R_PPC64_PLT16_HA :
00388 case R_PPC64_SECTOFF :
00389 case R_PPC64_SECTOFF_LO :
00390 case R_PPC64_SECTOFF_HI :
00391 case R_PPC64_SECTOFF_HA :
00392 case R_PPC64_ADDR30 :
00393 case R_PPC64_ADDR64 :
00394 case R_PPC64_ADDR16_HIGHER :
00395 case R_PPC64_ADDR16_HIGHERA :
00396 case R_PPC64_ADDR16_HIGHEST :
00397 case R_PPC64_ADDR16_HIGHESTA:
00398 case R_PPC64_UADDR64 :
00399 case R_PPC64_REL64 :
00400 case R_PPC64_PLT64 :
00401 case R_PPC64_PLTREL64 :
00402 case R_PPC64_TOC16 :
00403 case R_PPC64_TOC16_LO :
00404 case R_PPC64_TOC16_HI :
00405 case R_PPC64_TOC16_HA :
00406 case R_PPC64_TOC :
00407 case R_PPC64_PLTGOT16 :
00408 case R_PPC64_PLTGOT16_LO :
00409 case R_PPC64_PLTGOT16_HI :
00410 case R_PPC64_PLTGOT16_HA :
00411
00412 case R_PPC64_ADDR16_DS :
00413 case R_PPC64_ADDR16_LO_DS :
00414 case R_PPC64_GOT16_DS :
00415 case R_PPC64_GOT16_LO_DS :
00416 case R_PPC64_PLT16_LO_DS :
00417 case R_PPC64_SECTOFF_DS :
00418 case R_PPC64_SECTOFF_LO_DS :
00419 case R_PPC64_TOC16_DS :
00420 case R_PPC64_TOC16_LO_DS :
00421 case R_PPC64_PLTGOT16_DS :
00422 case R_PPC64_PLTGOT16_LO_DS :
00423
00424
00425 case R_PPC64_TLS :
00426 case R_PPC64_DTPMOD64 :
00427 case R_PPC64_TPREL16 :
00428 case R_PPC64_TPREL16_LO :
00429 case R_PPC64_TPREL16_HI :
00430 case R_PPC64_TPREL16_HA :
00431 case R_PPC64_TPREL64 :
00432 case R_PPC64_DTPREL16 :
00433 case R_PPC64_DTPREL16_LO :
00434 case R_PPC64_DTPREL16_HI :
00435 case R_PPC64_DTPREL16_HA :
00436 case R_PPC64_DTPREL64 :
00437 case R_PPC64_GOT_TLSGD16 :
00438 case R_PPC64_GOT_TLSGD16_LO :
00439 case R_PPC64_GOT_TLSGD16_HI :
00440 case R_PPC64_GOT_TLSGD16_HA :
00441 case R_PPC64_GOT_TLSLD16 :
00442 case R_PPC64_GOT_TLSLD16_LO :
00443 case R_PPC64_GOT_TLSLD16_HI :
00444 case R_PPC64_GOT_TLSLD16_HA :
00445 case R_PPC64_GOT_TPREL16_DS :
00446 case R_PPC64_GOT_TPREL16_LO_DS:
00447 case R_PPC64_GOT_TPREL16_HI :
00448 case R_PPC64_GOT_TPREL16_HA :
00449 case R_PPC64_GOT_DTPREL16_DS:
00450 case R_PPC64_GOT_DTPREL16_LO_DS:
00451 case R_PPC64_GOT_DTPREL16_HI:
00452 case R_PPC64_GOT_DTPREL16_HA:
00453 case R_PPC64_TPREL16_DS :
00454 case R_PPC64_TPREL16_LO_DS :
00455 case R_PPC64_TPREL16_HIGHER :
00456 case R_PPC64_TPREL16_HIGHERA:
00457 case R_PPC64_TPREL16_HIGHEST:
00458 case R_PPC64_TPREL16_HIGHESTA:
00459 case R_PPC64_DTPREL16_DS :
00460 case R_PPC64_DTPREL16_LO_DS :
00461 case R_PPC64_DTPREL16_HIGHER:
00462 case R_PPC64_DTPREL16_HIGHERA:
00463 case R_PPC64_DTPREL16_HIGHEST:
00464 case R_PPC64_DTPREL16_HIGHESTA:
00465
00466
00467 case R_PPC64_NUM :
00468
00469 default:
00470 break;
00471 }
00472 #endif
00473 } else if (PPC32_WIDTH == addressWidth_ ){
00474 int relocation_length = sizeof(Elf32_Word)*8;
00475 int relocation_pos = 0;
00476 int branch_pred = -1;
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487 Offset symbolOffset = rel.getDynSym()->getOffset();
00488
00489 Elf32_Word addend;
00490 if( rel.regionType() == Region::RT_REL ) {
00491 memcpy(&addend, &targetData[dest], sizeof(Elf32_Word));
00492 }else if( rel.regionType() == Region::RT_RELA ) {
00493 addend = rel.addend();
00494 }
00495
00496 if(!computeCtorDtorAddress(rel, globalOffset, lmap, errMsg, symbolOffset)) {
00497 return false;
00498 }
00499
00500 rewrite_printf("relocation for '%s': TYPE = %s(%lu) S = %lx A = %lx P = %lx\n",
00501 rel.name().c_str(),
00502 relocationEntry::relType2Str(rel.getRelType(), addressWidth_),
00503 rel.getRelType(), symbolOffset, addend, relOffset);
00504
00505 Offset relocation = 0;
00506 map<Symbol *, Offset>::iterator result;
00507
00508 stringstream tmp;
00509
00510 switch(rel.getRelType()) {
00511
00512
00513 case R_PPC_NONE:
00514 break;
00515 case R_PPC_ADDR32:
00516 relocation = symbolOffset + addend;
00517 break;
00518 case R_PPC_ADDR24:
00519 relocation_length = 26;
00520 relocation_pos = 2;
00521 relocation = (symbolOffset + addend) >> 2;
00522 break;
00523 case R_PPC_ADDR16:
00524 relocation_length = 16;
00525 relocation_pos = 16;
00526 relocation = symbolOffset + addend;
00527 break;
00528 case R_PPC_ADDR16_LO:
00529 relocation_length = 16;
00530 relocation_pos = 0;
00531 relocation = symbolOffset + addend;
00532 relocation = (relocation & 0xffff);
00533 break;
00534 case R_PPC_ADDR16_HI:
00535 relocation_length = 16;
00536 relocation_pos = 0;
00537 relocation = symbolOffset + addend;
00538 relocation = ((relocation >> 16) & 0xffff);
00539 break;
00540 case R_PPC_ADDR16_HA:
00541 relocation_length = 16;
00542 relocation_pos = 0;
00543 relocation = symbolOffset + addend;
00544 relocation = (((relocation >> 16) + ((relocation & 0x8000)? 1:0)) & 0xffff);
00545 break;
00546 case R_PPC_ADDR14:
00547 relocation_length = 14;
00548 relocation_pos = 16;
00549 relocation = (symbolOffset + addend) >> 2;
00550 break;
00551 case R_PPC_ADDR14_BRTAKEN:
00552 relocation_length = 14;
00553 relocation_pos = 16;
00554 relocation = (symbolOffset + addend) >> 2;
00555
00556 branch_pred = 1;
00557 break;
00558 case R_PPC_ADDR14_BRNTAKEN:
00559 relocation_length = 14;
00560 relocation_pos = 16;
00561 relocation = (symbolOffset + addend) >> 2;
00562
00563 branch_pred = 0;
00564 break;
00565 case R_PPC_REL24:
00566 relocation_length = 24;
00567 relocation_pos = 2;
00568 relocation = (symbolOffset + addend - relOffset) >> 2;
00569 break;
00570 case R_PPC_REL14:
00571 relocation_length = 14;
00572 relocation_pos = 16;
00573 relocation = (symbolOffset + addend - relOffset) >> 2;
00574 break;
00575 case R_PPC_REL14_BRTAKEN:
00576 relocation_length = 14;
00577 relocation_pos = 16;
00578 relocation = (symbolOffset + addend - relOffset) >> 2;
00579 branch_pred = 1;
00580 break;
00581 case R_PPC_REL14_BRNTAKEN:
00582 relocation_length = 14;
00583 relocation_pos = 16;
00584 relocation = (symbolOffset + addend - relOffset) >> 2;
00585 branch_pred = 0;
00586 break;
00587 case R_PPC_GOT16:
00588 result = lmap.gotSymbols.find(rel.getDynSym());
00589 if( result == lmap.gotSymbols.end() ) {
00590 errMsg = "Expected GOT symbol does not exist in GOT symbol mapping";
00591 return false;
00592 }
00593 relocation = result->second;
00594 relocation = (relocation) >> 16;
00595 relocation_length = 16;
00596 relocation_pos = 16;
00597 break;
00598 case R_PPC_GOT16_LO:
00599 result = lmap.gotSymbols.find(rel.getDynSym());
00600 if( result == lmap.gotSymbols.end() ) {
00601 errMsg = "Expected GOT symbol does not exist in GOT symbol mapping";
00602 return false;
00603 }
00604 relocation = result->second;
00605 relocation = (relocation & 0xffff);
00606 relocation_length = 16;
00607 relocation_pos = 0;
00608 break;
00609 case R_PPC_GOT16_HI:
00610 result = lmap.gotSymbols.find(rel.getDynSym());
00611 if( result == lmap.gotSymbols.end() ) {
00612 errMsg = "Expected GOT symbol does not exist in GOT symbol mapping";
00613 return false;
00614 }
00615 relocation = result->second;
00616 relocation = ((relocation >> 16) & 0xffff);
00617 relocation_length = 16;
00618 relocation_pos = 0;
00619 break;
00620 case R_PPC_GOT16_HA:
00621 result = lmap.gotSymbols.find(rel.getDynSym());
00622 if( result == lmap.gotSymbols.end() ) {
00623 errMsg = "Expected GOT symbol does not exist in GOT symbol mapping";
00624 return false;
00625 }
00626 relocation = result->second;
00627 relocation = (((relocation >> 16) + ((relocation & 0x8000)? 1:0)) & 0xffff);
00628 relocation_length = 16;
00629 relocation_pos = 0;
00630 break;
00631 case R_PPC_PLTREL24:
00632 relocation_length = 24;
00633 relocation_pos = 2;
00634 relocation = (symbolOffset + addend - relOffset) >> 2;
00635 break;
00636 case R_PPC_COPY:
00637 break;
00638 case R_PPC_GLOB_DAT:
00639 relocation = symbolOffset + addend;
00640 break;
00641 case R_PPC_JMP_SLOT:
00642 break;
00643 case R_PPC_RELATIVE:
00644 tmp << "ERROR: encountered relocation type(" << rel.getRelType() <<
00645 ") that is meant for use during dynamic linking";
00646 errMsg = tmp.str();
00647 return false;
00648 case R_PPC_LOCAL24PC:
00649 relocation_length = 24;
00650 relocation_pos = 2;
00651 relocation = (symbolOffset + addend - relOffset) >> 2;
00652 break;
00653 case R_PPC_UADDR32:
00654 relocation = symbolOffset + addend ;
00655 break;
00656 case R_PPC_UADDR16:
00657 relocation_length = 16;
00658 relocation_pos = 16;
00659 relocation = symbolOffset + addend;
00660 break;
00661 case R_PPC_REL32:
00662 relocation = symbolOffset + addend - relOffset;
00663 break;
00664 case R_PPC_PLT32:
00665 relocation = symbolOffset + addend;
00666 break;
00667 case R_PPC_PLTREL32:
00668 relocation = symbolOffset + addend - relOffset;
00669 break;
00670 case R_PPC_PLT16_LO:
00671 relocation = symbolOffset + addend;
00672 relocation = (relocation & 0xffff);
00673 break;
00674 case R_PPC_PLT16_HI:
00675 relocation = symbolOffset + addend;
00676 relocation = ((relocation >> 16) & 0xffff);
00677 break;
00678 case R_PPC_PLT16_HA:
00679 relocation = symbolOffset + addend;
00680 relocation = (((relocation >> 16) + ((relocation & 0x8000)? 1:0)) & 0xffff);
00681 break;
00682 case R_PPC_SDAREL16:
00683 case R_PPC_SECTOFF:
00684 case R_PPC_SECTOFF_LO:
00685 case R_PPC_SECTOFF_HI:
00686 case R_PPC_SECTOFF_HA:
00687 tmp << "Relocation type " << rel.getRelType()
00688 << " currently unimplemented";
00689 errMsg = tmp.str();
00690 rewrite_printf(" Relocation type %s currently unimplemented \n", relocationEntry::relType2Str(rel.getRelType(), addressWidth_));
00691 return false;
00692
00693
00694 case R_PPC_TLS:
00695 case R_PPC_DTPMOD32:
00696 case R_PPC_TPREL16:
00697 case R_PPC_TPREL16_LO:
00698 case R_PPC_TPREL16_HI:
00699 case R_PPC_TPREL16_HA:
00700 case R_PPC_TPREL32:
00701 case R_PPC_DTPREL16:
00702 case R_PPC_DTPREL16_LO:
00703 case R_PPC_DTPREL16_HI:
00704 case R_PPC_DTPREL16_HA:
00705 case R_PPC_DTPREL32:
00706 case R_PPC_GOT_TLSGD16:
00707 case R_PPC_GOT_TLSGD16_LO:
00708 case R_PPC_GOT_TLSGD16_HI:
00709 case R_PPC_GOT_TLSGD16_HA:
00710 case R_PPC_GOT_TLSLD16:
00711 case R_PPC_GOT_TLSLD16_LO:
00712 case R_PPC_GOT_TLSLD16_HI:
00713 case R_PPC_GOT_TLSLD16_HA:
00714 case R_PPC_GOT_TPREL16:
00715 case R_PPC_GOT_TPREL16_LO:
00716 case R_PPC_GOT_TPREL16_HI:
00717 case R_PPC_GOT_TPREL16_HA:
00718 case R_PPC_GOT_DTPREL16:
00719 case R_PPC_GOT_DTPREL16_LO:
00720 case R_PPC_GOT_DTPREL16_HI:
00721 case R_PPC_GOT_DTPREL16_HA:
00722 relocation_length = 16;
00723 relocation_pos = 16;
00724 relocation = symbolOffset + addend;
00725 rewrite_printf(" Relocation type %s currently unimplemented \n", relocationEntry::relType2Str(rel.getRelType(), addressWidth_));
00726 break;
00727
00728
00729
00730
00731 case 249:
00732 relocation_length = 16;
00733 relocation_pos = 16;
00734 relocation = symbolOffset + addend - relOffset ;
00735 break;
00736 case 250:
00737 relocation_length = 16;
00738 relocation_pos = 16;
00739 relocation = symbolOffset + addend - relOffset ;
00740 relocation = (relocation & 0xffff);
00741 break;
00742 case 251:
00743 relocation_length = 16;
00744 relocation_pos = 16;
00745 relocation = symbolOffset + addend - relOffset ;
00746 relocation = ((relocation >> 16) & 0xffff);
00747 break;
00748 case 252:
00749 relocation_length = 16;
00750 relocation_pos = 16;
00751 relocation = symbolOffset + addend - relOffset ;
00752 relocation = (((relocation >> 16) + ((relocation & 0x8000)? 1:0)) & 0xffff);
00753 break;
00754
00755
00756 case 255:
00757 break;
00758
00759 default:
00760 tmp << "Relocation type " << rel.getRelType()
00761 << " currently unimplemented";
00762 rewrite_printf(" Relocation type %s currently unimplemented \n", relocationEntry::relType2Str(rel.getRelType(), addressWidth_));
00763 errMsg = tmp.str();
00764 return false;
00765 }
00766
00767 rewrite_printf(" relocation = 0x%lx @ 0x%lx target data 0x%lx %lx %lx %lx \n", relocation, relOffset, targetData[dest], targetData[dest+1], targetData[dest+2], targetData[dest+3]);
00768 if (rel.getRelType() == R_PPC_REL24) {
00769 unsigned int *td = (unsigned int *) targetData;
00770 unsigned int target;
00771 target = td[dest/4];
00772 target = setBits(target, relocation_pos, relocation_length, relocation);
00773 memcpy(&targetData[dest], &target, sizeof(Elf32_Word));
00774 } else {
00775 unsigned int *td = (unsigned int *) targetData;
00776 unsigned int target;
00777 target = td[dest/4];
00778 target = setBits(target, relocation_pos, relocation_length, relocation);
00779 memcpy(&td[dest/4], &target, sizeof(Elf32_Word));
00780
00781 rewrite_printf(" relocation = 0x%lx @ 0x%lx target data 0x%lx %lx %lx %lx \n", relocation, relOffset, targetData[dest], targetData[dest+1], targetData[dest+2], targetData[dest+3]);
00782 }
00783 if (branch_pred >= 0) {
00784 unsigned int *td = (unsigned int *) targetData;
00785 unsigned int target;
00786 target = td[dest/4];
00787 target = setBits(target, 10, 1, branch_pred);
00788 memcpy(&td[dest/4], &target, sizeof(Elf32_Word));
00789 }
00790
00791 } else{
00792 assert(!UNKNOWN_ADDRESS_WIDTH_ASSERT);
00793 }
00794 return true;
00795 }
00796
00797 bool emitElfStatic::checkSpecialCaseSymbols(Symtab *, Symbol *) {
00798 return true;
00799 }
00800
00801
00802
00803 Offset emitElfStatic::layoutTLSImage(Offset globalOffset, Region *dataTLS, Region *bssTLS, LinkMap &lmap) {
00804 return tlsLayoutVariant1(globalOffset, dataTLS, bssTLS, lmap);
00805 }
00806
00807 Offset emitElfStatic::adjustTLSOffset(Offset curOffset, Offset tlsSize) {
00808 return curOffset;
00809 }
00810
00811 char emitElfStatic::getPaddingValue(Region::RegionType rtype) {
00812
00813 return 0x0;
00814 }
00815
00816 void emitElfStatic::cleanupTLSRegionOffsets(map<Region *, LinkMap::AllocPair> ®ionAllocs,
00817 Region *dataTLS, Region *bssTLS)
00818 {
00819 tlsCleanupVariant2(regionAllocs, dataTLS, bssTLS);
00820 }
00821
00822 Offset emitElfStatic::getGOTSize(Symtab *target, LinkMap &lmap, Offset &layoutStart) {
00823 Offset size = 0;
00824
00825 unsigned slotSize = 0;
00826 if( PPC32_WIDTH == addressWidth_ ) {
00827 slotSize = sizeof(Elf32_Addr);
00828 }else if( PPC64_WIDTH == addressWidth_ ) {
00829 slotSize = sizeof(Elf64_Addr);
00830 }else{
00831 assert(!UNKNOWN_ADDRESS_WIDTH_ASSERT);
00832 }
00833
00834
00835 if( lmap.gotSymbolTable.size() > 0 ) {
00836 rewrite_printf("Determining new GOT size: %d symtab entries, %d reserved slots, %d slot size\n",
00837 lmap.gotSymbolTable.size(), GOT_RESERVED_SLOTS, slotSize);
00838 size = (lmap.gotSymbolTable.size()+GOT_RESERVED_SLOTS)*slotSize;
00839 }
00840
00841
00842 #if 0
00843
00844
00845 if (PPC64_WIDTH == addressWidth_) {
00846 rewrite_printf("New GOT size is 0x%lx, adding original GOT size 0x%lx\n", size, target->getObject()->gotSize());
00847 layoutStart = target->getObject()->gotSize();
00848 size += layoutStart;
00849 }
00850 #endif
00851
00852 return size;
00853 }
00854
00855 Offset emitElfStatic::getGOTAlign(LinkMap &) {
00856
00857 if( PPC32_WIDTH == addressWidth_ ) {
00858 return 0;
00859 }
00860 if( PPC32_WIDTH == addressWidth_ ) {
00861 return sizeof(Elf32_Word);
00862 }else if( PPC64_WIDTH == addressWidth_ ) {
00863 return sizeof(Elf64_Xword);
00864 }else{
00865 assert(!UNKNOWN_ADDRESS_WIDTH_ASSERT);
00866 }
00867
00868 return 0;
00869 }
00870
00871 void emitElfStatic::buildGOT(Symtab *target, LinkMap &lmap) {
00872
00873 if( PPC32_WIDTH == addressWidth_ ) {
00874 return;
00875 }
00876 char *targetData = lmap.allocatedData;
00877
00878 unsigned slotSize = 0;
00879 if( PPC32_WIDTH == addressWidth_ ) {
00880 slotSize = sizeof(Elf32_Addr);
00881 }else if( PPC64_WIDTH == addressWidth_ ) {
00882 slotSize = sizeof(Elf64_Addr);
00883 }else{
00884 assert(!UNKNOWN_ADDRESS_WIDTH_ASSERT);
00885 }
00886
00887 Offset curOffset = 0;
00888 #if 0
00889
00890
00891
00892 Region *origGOT = NULL;
00893 if (target->findRegion(origGOT, ".got")) {
00894 memcpy(&targetData[lmap.gotRegionOffset + curOffset], origGOT->getPtrToRawData(), origGOT->getDiskSize());
00895 curOffset += origGOT->getDiskSize();
00896 rewrite_printf("Copying 0x%lx bytes of original GOT to new, curOffset is 0x%lx\n",
00897 origGOT->getDiskSize(), curOffset);
00898 }
00899 #endif
00900
00901
00902
00903
00904 memset(&targetData[lmap.gotRegionOffset], 0, GOT_RESERVED_SLOTS*slotSize);
00905 curOffset += GOT_RESERVED_SLOTS*slotSize;
00906
00907 rewrite_printf("Copied GOT_RESERVED_SLOTS %d, curOffset 0x%lx\n",
00908 GOT_RESERVED_SLOTS, curOffset);
00909
00910 vector<pair<Symbol *, Offset> >::iterator sym_it;
00911 rewrite_printf("Copying in %d symbol table entries\n", lmap.gotSymbolTable.size());
00912
00913 for(sym_it = lmap.gotSymbolTable.begin(); sym_it != lmap.gotSymbolTable.end(); ++sym_it) {
00914 Offset value = sym_it->first->getOffset()+sym_it->second;
00915 memcpy(&targetData[lmap.gotRegionOffset + curOffset], &value, slotSize);
00916
00917 sym_it->second = curOffset;
00918 rewrite_printf(" Building GOT at 0x%lx is 0x%lx name %s Offset 0x%lx addend 0x%lx addr 0x%lx \n",
00919 curOffset, value,
00920 sym_it->first->getPrettyName().c_str(), sym_it->first->getOffset(),
00921 sym_it->second, lmap.gotRegionOffset + curOffset);
00922 curOffset += slotSize;
00923 }
00924 rewrite_printf("curOffset is 0x%lx, calculated GOT size is 0x%lx\n", curOffset, lmap.gotSize);
00925 assert(curOffset == lmap.gotSize);
00926 }
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950 static const string DTOR_NAME(".dtors");
00951 static const string CTOR_NAME(".ctors");
00952 static const string TOC_NAME(".toc");
00953
00954 Offset emitElfStatic::layoutNewCtorRegion(LinkMap &lmap) {
00955
00956
00957
00958
00959
00960 Offset retOffset = lmap.ctorRegionOffset;
00961 retOffset += addressWidth_;
00962
00963 pair<map<Region *, LinkMap::AllocPair>::iterator, bool> result;
00964
00965 vector<Region *>::iterator reg_it;
00966 for(reg_it = lmap.newCtorRegions.begin(); reg_it != lmap.newCtorRegions.end(); ++reg_it) {
00967 result = lmap.regionAllocs.insert(make_pair(*reg_it, make_pair(0, retOffset)));
00968
00969
00970 if( !result.second ) {
00971 return ~0UL;
00972 }
00973
00974 retOffset += (*reg_it)->getDiskSize();
00975 }
00976
00977 if( lmap.originalCtorRegion != NULL ) {
00978
00979 retOffset += lmap.originalCtorRegion->getDiskSize() - addressWidth_ - addressWidth_;
00980 }
00981 retOffset += addressWidth_;
00982
00983 return retOffset;
00984
00985 return 0;
00986 }
00987
00988 bool emitElfStatic::createNewCtorRegion(LinkMap &lmap) {
00989 char *targetData = lmap.allocatedData;
00990
00991 if( PPC32_WIDTH != addressWidth_ && PPC64_WIDTH != addressWidth_ ) {
00992 assert(!UNKNOWN_ADDRESS_WIDTH_ASSERT);
00993 }
00994
00995 unsigned trailerSize, headerSize;
00996
00997
00998 Offset headerOffset = lmap.ctorRegionOffset;
00999 Offset trailerOffset;
01000 if( PPC32_WIDTH == addressWidth_ ) {
01001 memcpy(&targetData[headerOffset], &X86_HEADER, sizeof(X86_HEADER));
01002 trailerOffset = lmap.ctorRegionOffset + lmap.ctorSize - sizeof(X86_TRAILER);
01003 memcpy(&targetData[trailerOffset], &X86_TRAILER, sizeof(X86_TRAILER));
01004 headerSize = sizeof(X86_HEADER);
01005 trailerSize = sizeof(X86_TRAILER);
01006 }else{
01007 memcpy(&targetData[headerOffset], &X86_64_HEADER, sizeof(X86_64_HEADER));
01008 trailerOffset = lmap.ctorRegionOffset + lmap.ctorSize - sizeof(X86_64_TRAILER);
01009 memcpy(&targetData[trailerOffset], &X86_64_TRAILER, sizeof(X86_64_TRAILER));
01010 headerSize = sizeof(X86_64_HEADER);
01011 trailerSize = sizeof(X86_64_TRAILER);
01012 }
01013
01014 if( lmap.originalCtorRegion != NULL ) {
01015
01016 Offset originalOffset = lmap.ctorRegionOffset + lmap.ctorSize -
01017 trailerSize - (lmap.originalCtorRegion->getDiskSize() - headerSize - trailerSize);
01018
01019
01020 char *rawRegionData = reinterpret_cast<char *>(lmap.originalCtorRegion->getPtrToRawData());
01021 memcpy(&targetData[originalOffset], &rawRegionData[headerSize],
01022 lmap.originalCtorRegion->getDiskSize() - headerSize - trailerSize);
01023 }
01024
01025 return true;
01026 }
01027
01028
01029 Offset emitElfStatic::layoutNewDtorRegion(LinkMap &lmap) {
01030
01031
01032
01033
01034
01035 Offset retOffset = lmap.dtorRegionOffset;
01036 retOffset += addressWidth_;
01037
01038 pair<map<Region *, LinkMap::AllocPair>::iterator, bool> result;
01039 if( lmap.originalDtorRegion != NULL ) {
01040
01041 retOffset += lmap.originalDtorRegion->getDiskSize() - addressWidth_ - addressWidth_;
01042 }
01043
01044 vector<Region *>::iterator reg_it;
01045 for(reg_it = lmap.newDtorRegions.begin(); reg_it != lmap.newDtorRegions.end(); ++reg_it) {
01046 result = lmap.regionAllocs.insert(make_pair(*reg_it, make_pair(0, retOffset)));
01047
01048
01049 if( !result.second ) {
01050 return ~0UL;
01051 }
01052
01053 retOffset += (*reg_it)->getDiskSize();
01054 }
01055
01056 retOffset += addressWidth_;
01057 return retOffset;
01058
01059 return 0;
01060 }
01061
01062 bool emitElfStatic::createNewDtorRegion(LinkMap &lmap) {
01063 char *targetData = lmap.allocatedData;
01064
01065 if( PPC32_WIDTH != addressWidth_ && PPC64_WIDTH != addressWidth_ ) {
01066 assert(!UNKNOWN_ADDRESS_WIDTH_ASSERT);
01067 }
01068
01069 unsigned headerSize, trailerSize;
01070
01071
01072 Offset headerOffset = lmap.dtorRegionOffset;
01073 Offset trailerOffset;
01074 if( PPC32_WIDTH == addressWidth_ ) {
01075 memcpy(&targetData[headerOffset], &X86_HEADER, sizeof(X86_HEADER));
01076 trailerOffset = lmap.dtorRegionOffset + lmap.dtorSize - sizeof(X86_TRAILER);
01077 memcpy(&targetData[trailerOffset], &X86_TRAILER, sizeof(X86_TRAILER));
01078 headerSize = sizeof(X86_HEADER);
01079 trailerSize = sizeof(X86_TRAILER);
01080 }else{
01081 memcpy(&targetData[headerOffset], &X86_64_HEADER, sizeof(X86_64_HEADER));
01082 trailerOffset = lmap.dtorRegionOffset + lmap.dtorSize - sizeof(X86_64_TRAILER);
01083 memcpy(&targetData[trailerOffset], &X86_64_TRAILER, sizeof(X86_64_TRAILER));
01084 headerSize = sizeof(X86_64_HEADER);
01085 trailerSize = sizeof(X86_64_TRAILER);
01086 }
01087
01088 if( lmap.originalDtorRegion != NULL ) {
01089
01090 Offset originalOffset = lmap.dtorRegionOffset + headerSize;
01091
01092
01093 char *rawRegionData = reinterpret_cast<char *>(lmap.originalDtorRegion->getPtrToRawData());
01094 memcpy(&targetData[originalOffset], &rawRegionData[headerSize],
01095 lmap.originalDtorRegion->getDiskSize() - headerSize - trailerSize);
01096 }
01097
01098 return true;
01099
01100 }
01101
01102 bool emitElfStatic::isConstructorRegion(Region *reg) {
01103 return ( CTOR_NAME.compare(reg->getRegionName()) == 0 );
01104
01105 }
01106
01107 bool emitElfStatic::isDestructorRegion(Region *reg) {
01108 return ( DTOR_NAME.compare(reg->getRegionName()) == 0 );
01109 }
01110
01111 bool emitElfStatic::isGOTRegion(Region *reg) {
01112
01113 if( PPC32_WIDTH == addressWidth_ ) {
01114 return false;
01115 }
01116 return ( TOC_NAME.compare(reg->getRegionName()) == 0 );
01117 }
01118 bool emitElfStatic::isGOTRelocation(unsigned long relType) {
01119 if( PPC32_WIDTH == addressWidth_ ) {
01120 switch(relType) {
01121 case R_PPC_GOT16:
01122 case R_PPC_GOT16_LO:
01123 case R_PPC_GOT16_HI:
01124 case R_PPC_GOT16_HA:
01125 case R_PPC_GOT_TPREL16:
01126 case R_PPC_TLS:
01127 return true;
01128 break;
01129 default:
01130 return false;
01131 break;
01132 }
01133 } else if( PPC64_WIDTH == addressWidth_) {
01134 switch(relType) {
01135 case R_PPC64_GOT16:
01136 case R_PPC64_GOT16_LO:
01137 case R_PPC64_GOT16_HI:
01138 case R_PPC64_GOT16_HA:
01139 case R_PPC64_TLS:
01140 case R_PPC64_TOC16_DS:
01141 case R_PPC64_TOC16:
01142 return true;
01143 break;
01144 default:
01145 return false;
01146 break;
01147 }
01148 } else{
01149 assert(!UNKNOWN_ADDRESS_WIDTH_ASSERT);
01150 }
01151
01152 return false;
01153 }
01154
01155 void emitElfStatic::getExcludedSymbolNames(set<string> &) {
01156 }
01157
01158 bool emitElfStatic::updateTOC(Symtab *file, LinkMap &lmap, Offset globalOffset) {
01159
01160
01161
01162 return true;
01163
01164
01165 rewrite_printf("Updating TOC in %s\n", file->name().c_str());
01166
01167 Address GOTbase = lmap.gotRegionOffset;
01168
01169 Address oldTOC = file->getTOCoffset((Offset) 0);
01170 Address newTOC = GOTbase + 0x8000 + globalOffset;
01171
01172 Address deltaTOC = newTOC - oldTOC;
01173
01174 rewrite_printf("Set TOC to 0x%lx = 0x%lx + 0x%lx + 0x%lx; old 0x%lx\n", newTOC, GOTbase, 0x8000, globalOffset, oldTOC);
01175
01176
01177
01178
01179
01180 Region *OPD = NULL;
01181 if (!file->findRegion(OPD, ".opd")) return true;
01182
01183 unsigned long *oldData = (unsigned long *) OPD->getPtrToRawData();
01184 unsigned long *newData = (unsigned long *) malloc(OPD->getDiskSize());
01185 memcpy(newData, oldData, OPD->getDiskSize());
01186 OPD->setPtrToRawData(newData, OPD->getDiskSize());
01187
01188
01189
01190
01191 for (unsigned i = 1; i < (OPD->getDiskSize() / sizeof(unsigned long)); i += 3) {
01192 unsigned long oldVal = newData[i];
01193 newData[i] = oldVal + deltaTOC;
01194 }
01195
01196 return true;
01197 }
01198
01199 Offset emitElfStatic::allocStubRegions(LinkMap &lmap, Offset globalOffset) {
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216 Offset relStubOffset = lmap.stubRegionOffset;
01217 rewrite_printf("Allocating stub regions for inter-module calls\n");
01218
01219 for (deque<Region *>::iterator reg_iter = lmap.codeRegions.begin(); reg_iter != lmap.codeRegions.end(); ++reg_iter) {
01220 vector<relocationEntry> region_rels = (*reg_iter)->getRelocations();
01221 rewrite_printf("\t For region %s in %s, %d relocations, %d unique symbols so far\n",
01222 (*reg_iter)->getRegionName().c_str(),
01223 (*reg_iter)->symtab()->name().c_str(),
01224 region_rels.size(),
01225 lmap.stubMap.size());
01226 for (vector<relocationEntry>::iterator rel_iter = region_rels.begin(); rel_iter != region_rels.end(); ++rel_iter) {
01227 relocationEntry &rel = *rel_iter;
01228 if (rel.getRelType() != R_PPC64_REL24) continue;
01229
01230 if (lmap.stubMap.find(rel.getDynSym()) == lmap.stubMap.end()) {
01231 rewrite_printf("\t\tSetting stub offset for %s to 0x%lx\n", rel.getDynSym()->getMangledName().c_str(), relStubOffset);
01232 lmap.stubMap[rel.getDynSym()] = relStubOffset + globalOffset;
01233 relStubOffset += 4*sizeof(unsigned);
01234 }
01235 }
01236 }
01237 rewrite_printf("\t After regions, returning offset 0x%lx = current 0x%lx + stub area 0x%lx\n",
01238 lmap.stubRegionOffset + (16 * lmap.stubMap.size()), lmap.stubRegionOffset, 16*lmap.stubMap.size());
01239 return relStubOffset;
01240 }
01241
01242
01243 bool emitElfStatic::handleInterModuleSpecialCase(Symtab *target,
01244 Symtab *src,
01245 LinkMap &lmap,
01246 char *data,
01247 relocationEntry rel,
01248 Offset newTOC,
01249 Offset oldTOC,
01250 Offset dest,
01251 Offset relOffset,
01252 Offset globalOffset) {
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279 unsigned int *td = (unsigned int *)(data + dest - (dest % 4));
01280 unsigned int &call = td[0];
01281 unsigned int &post = td[1];
01282
01283 instruction callInsn(call);
01284 if (!callInsn.isCall()) {
01285
01286 return false;
01287 }
01288 if (!post != 0x60000000) {
01289
01290 return false;
01291 }
01292
01293 Offset stubOffset = findOrCreateStub(rel.getDynSym(), lmap, newTOC, oldTOC, data, globalOffset);
01294 Offset branchOffset = stubOffset - relOffset;
01295 rewrite_printf("Handling TOC set stub, using stub offset 0x%lx, curr addr 0x%lx so branch is 0x%lx \n",
01296 stubOffset, relOffset, branchOffset);
01297 rewrite_printf("\t Raw original call is 0x%lx...", call);
01298
01299 call = setBits(call, 6, 24, (unsigned) (branchOffset));
01300 rewrite_printf("and patched 0x%lx\n", call);
01301
01302
01303
01304 assert(post == 0x60000000);
01305
01306 post = 0xe8410028;
01307
01308 return true;
01309 }
01310
01311 Offset emitElfStatic::findOrCreateStub(Symbol *sym, LinkMap &lmap, Offset newTOC, Offset oldTOC, char *data, Offset globalOffset) {
01312
01313 std::map<Symbol *, TOCstub>::iterator iter = stubMap.find(sym);
01314 if (iter != stubMap.end() &&
01315 getNewTOC(iter->second) == newTOC &&
01316 getOldTOC(iter->second) == oldTOC) {
01317 return getStubOffset(iter->second);
01318 }
01319
01320
01321 Offset stubOffset = lmap.stubMap[sym];
01322 assert(stubOffset);
01323
01324 unsigned stub[4];
01325 createStub(stub, stubOffset, newTOC, oldTOC, sym->getOffset());
01326
01327 char *td = data + stubOffset - globalOffset;
01328 rewrite_printf("Creating stub at 0x%lx (0x%lx in buffer)\n",
01329 stubOffset, stubOffset - globalOffset);
01330 memcpy(td, stub, 4*sizeof(unsigned));
01331
01332 stubMap[sym] = TOCstub(stubOffset, newTOC, oldTOC);
01333 return stubOffset;
01334 }
01335
01336 void emitElfStatic::createStub(unsigned *stub, Offset stubOffset, Offset newTOC, Offset oldTOC, Offset dest) {
01337
01338 unsigned deltaTOChi = HA((newTOC - oldTOC));
01339 unsigned deltaTOClo = LOW((newTOC - oldTOC));
01340 unsigned deltaAddr = dest - (stubOffset + 3*sizeof(unsigned));
01341
01342 rewrite_printf("Calculating stub:\n\thigh TOC bits 0x%x (from 0x%lx - 0x%lx),\n\tlow TOC bits 0x%x (from 0x%lx - 0x%lx),\n\tbranch offset 0x%x (from 0x%lx - 0x%lx)\n",
01343 deltaTOChi, newTOC, oldTOC,
01344 deltaTOClo, newTOC, oldTOC,
01345 deltaAddr, dest, stubOffset);
01346
01347 stub[0] = 0xf8410028;
01348 stub[1] = 0x3c420000 | (deltaTOChi & 0xffff);
01349 stub[2] = 0x38420000 | (deltaTOClo & 0xffff);
01350
01351 instruction branch;
01352 IFORM_OP_SET(branch, Bop);
01353 IFORM_LI_SET(branch, deltaAddr >> 2);
01354 IFORM_AA_SET(branch, 0);
01355 IFORM_LK_SET(branch, 0);
01356
01357 stub[3] = branch.asInt();
01358
01359 }