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
00037
00038
00039
00040
00041
00042
00043 #include <cstdlib>
00044 #include <cstdio>
00045 #include <iostream>
00046
00047 #include <algorithm>
00048
00049 #include "emitElfStatic.h"
00050 #include "debug.h"
00051 #include "Object-elf.h"
00052
00053 #if defined(os_freebsd)
00054 #define R_X86_64_JUMP_SLOT R_X86_64_JMP_SLOT
00055 #endif
00056
00057 using namespace Dyninst;
00058 using namespace SymtabAPI;
00059
00060
00061 static const string CODE_NAME(".dyninstCode");
00062 static const string STUB_NAME(".dyninstStub");
00063 static const string DATA_NAME(".dyninstData");
00064 static const string BSS_NAME(".dyninstBss");
00065 static const string GOT_NAME(".dyninstGot");
00066 static const string CTOR_NAME(".dyninstCtors");
00067 static const string DTOR_NAME(".dyninstDtors");
00068 static const string TLS_DATA_NAME(".dyninstTdata");
00069 static const string DEFAULT_COM_NAME(".common");
00070 static const string PLT_NAME(".dyninstPLT");
00071 static const string REL_NAME(".dyninstRELA");
00072 static const string REL_GOT_NAME(".dyninstRELAgot");
00073
00074
00075 const string Dyninst::SymtabAPI::SYMTAB_CTOR_LIST_REL("__SYMTABAPI_CTOR_LIST__");
00076 const string Dyninst::SymtabAPI::SYMTAB_DTOR_LIST_REL("__SYMTABAPI_DTOR_LIST__");
00077 const string Dyninst::SymtabAPI::SYMTAB_IREL_START("__SYMTABAPI_IREL_START__");
00078 const string Dyninst::SymtabAPI::SYMTAB_IREL_END("__SYMTABAPI_IREL_END__");
00079
00080 emitElfStatic::emitElfStatic(unsigned addressWidth, bool isStripped) :
00081 addressWidth_(addressWidth),
00082 isStripped_(isStripped),
00083 hasRewrittenTLS_(false)
00084 {}
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 char *emitElfStatic::linkStatic(Symtab *target,
00103 StaticLinkError &err, string &errMsg)
00104 {
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 LinkMap lmap;
00120
00121 rewrite_printf("START link map output\n");
00122
00123
00124 Offset globalOffset = 0;
00125 vector<Region *> newRegs;
00126 if( target->getAllNewRegions(newRegs) ) {
00127
00128 vector<Region *>::iterator newReg_it;
00129 for(newReg_it = newRegs.begin(); newReg_it != newRegs.end(); ++newReg_it) {
00130 Offset newRegEndAddr = (*newReg_it)->getMemSize() + (*newReg_it)->getDiskOffset();
00131 if( newRegEndAddr > globalOffset ) {
00132 globalOffset = newRegEndAddr;
00133 }
00134 }
00135 }
00136
00137 if( globalOffset == 0 ) {
00138 err = Link_Location_Error;
00139 errMsg = "failed to find location for new code and data.";
00140 return NULL;
00141 }
00142
00143
00144 vector<Symtab *> relocatableObjects;
00145 if( !resolveSymbols(target, relocatableObjects, lmap, err, errMsg) ) {
00146 return NULL;
00147 }
00148
00149
00150 if( !createLinkMap(target, relocatableObjects, globalOffset, lmap, err, errMsg) ) {
00151 return NULL;
00152 }
00153
00154
00155 if( !addNewRegions(target, globalOffset, lmap) ) {
00156 err = Storage_Allocation_Failure;
00157 errMsg = "Failed to create new Regions in original binary";
00158 return NULL;
00159 }
00160
00161 if (!updateTOC(target, lmap, globalOffset)) {
00162 return NULL;
00163 }
00164
00165
00166 rewrite_printf("Global Offset = 0x%lx\n", globalOffset);
00167 if( sym_debug_rewrite ) {
00168 lmap.printAll(cerr, globalOffset);
00169 lmap.printBySymtab(cerr, relocatableObjects, globalOffset);
00170 }
00171
00172
00173 if( !applyRelocations(target, relocatableObjects, globalOffset, lmap, err, errMsg) ) {
00174 if( lmap.allocatedData ) delete lmap.allocatedData;
00175 return NULL;
00176 }
00177
00178 if (!buildPLT(target, globalOffset, lmap, err, errMsg)) {
00179 if (lmap.allocatedData) delete lmap.allocatedData;
00180 return NULL;
00181 }
00182
00183 if (!buildRela(target, globalOffset, lmap, err, errMsg)) {
00184 if (lmap.allocatedData) delete lmap.allocatedData;
00185 return NULL;
00186 }
00187
00188
00189 vector< pair<Symbol *, Offset> >::iterator symOff_it;
00190 for(symOff_it = lmap.origSymbols.begin();
00191 symOff_it != lmap.origSymbols.end();
00192 ++symOff_it)
00193 {
00194 symOff_it->first->setOffset(symOff_it->second);
00195 }
00196
00197
00198 vector< pair<relocationEntry *, Symbol *> >::iterator relSym_it;
00199 for(relSym_it = lmap.origRels.begin();
00200 relSym_it != lmap.origRels.end();
00201 ++relSym_it)
00202 {
00203 relSym_it->first->addDynSym(relSym_it->second);
00204 }
00205
00206 rewrite_printf("\n*** Finished static linking\n\n");
00207
00208 rewrite_printf("END link map output\n");
00209
00210 err = No_Static_Link_Error;
00211 errMsg = "";
00212 return lmap.allocatedData;
00213 }
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 bool emitElfStatic::resolveSymbols(Symtab *target,
00228 vector<Symtab *> &relocatableObjects,
00229 LinkMap &lmap,
00230 StaticLinkError &err, string &errMsg)
00231 {
00232
00233 set<Symtab *> workSet;
00234
00235
00236
00237 set<Symtab *> linkedSet;
00238
00239 set<string> excludeSymNames;
00240 getExcludedSymbolNames(excludeSymNames);
00241
00242
00243 vector<Archive *> libraries;
00244 target->getLinkingResources(libraries);
00245
00246
00247
00248 set<Symtab *> explicitRefs;
00249 target->getExplicitSymtabRefs(explicitRefs);
00250
00251 set<Symtab *>::iterator expObj_it;
00252 for(expObj_it = explicitRefs.begin(); expObj_it != explicitRefs.end();
00253 ++expObj_it)
00254 {
00255 relocatableObjects.push_back(*expObj_it);
00256 workSet.insert(*expObj_it);
00257 linkedSet.insert(*expObj_it);
00258 }
00259
00260 set<Symtab *>::iterator curObjFilePtr = workSet.begin();
00261 while( curObjFilePtr != workSet.end() ) {
00262
00263 Symtab *curObjFile = *curObjFilePtr;
00264 workSet.erase(curObjFile);
00265
00266 rewrite_printf("\n*** Resolving symbols for: %s\n\n",
00267 curObjFile->memberName().c_str());
00268
00269
00270 map<Symbol *, vector<relocationEntry *> > symToRels;
00271 vector<Region *> allRegions;
00272 curObjFile->getAllRegions(allRegions);
00273
00274 vector<Region *>::iterator region_it;
00275 for(region_it = allRegions.begin(); region_it != allRegions.end();
00276 ++region_it)
00277 {
00278 vector<relocationEntry> ®ion_rels = (*region_it)->getRelocations();
00279 vector<relocationEntry>::iterator rel_it;
00280 for( rel_it = region_rels.begin(); rel_it != region_rels.end(); ++rel_it) {
00281 symToRels[rel_it->getDynSym()].push_back(&(*rel_it));
00282 lmap.origRels.push_back(make_pair(&(*rel_it), rel_it->getDynSym()));
00283 }
00284 }
00285
00286
00287 vector<Symbol *> undefSyms;
00288 curObjFile->getAllUndefinedSymbols(undefSyms);
00289
00290 vector<Symbol *>::iterator undefSym_it;
00291 for(undefSym_it = undefSyms.begin(); undefSym_it != undefSyms.end();
00292 ++undefSym_it)
00293 {
00294 Symbol *curUndefSym = *undefSym_it;
00295
00296
00297 if( excludeSymNames.count(curUndefSym->getPrettyName()) ) continue;
00298
00299 if( !checkSpecialCaseSymbols(curObjFile, curUndefSym) ) {
00300 err = Symbol_Resolution_Failure;
00301 errMsg = "special case check failed for symbol: " +
00302 curUndefSym->getMangledName();
00303 return false;
00304 }
00305
00306 Symbol *extSymbol = NULL;
00307
00308
00309 if( !isStripped_ ) {
00310 vector<Symbol *> foundSyms;
00311 if( target->findSymbol(foundSyms, curUndefSym->getMangledName(),
00312 curUndefSym->getType()) )
00313 {
00314 if( foundSyms.size() > 1 ) {
00315 err = Symbol_Resolution_Failure;
00316 errMsg = "ambiguous symbol definition: " +
00317 curUndefSym->getMangledName();
00318 return false;
00319 }
00320
00321 extSymbol = foundSyms[0];
00322
00323 rewrite_printf("Found external symbol %s in target with address = 0x%lx\n",
00324 extSymbol->getPrettyName().c_str(), extSymbol->getOffset());
00325 }
00326 }
00327
00328 if( extSymbol == NULL ) {
00329
00330 vector<Symtab *> possibleSymtabs;
00331
00332 for(auto lib_it = libraries.begin(); lib_it != libraries.end(); ++lib_it) {
00333 (*lib_it)->getMembersBySymbol(curUndefSym->getMangledName(), possibleSymtabs);
00334 }
00335
00336
00337
00338
00339
00340
00341
00342
00343 for (auto iter = possibleSymtabs.begin(); iter != possibleSymtabs.end(); ++iter) {
00344 std::vector<Symbol *> syms;
00345 (*iter)->findSymbol(syms, curUndefSym->getMangledName(), curUndefSym->getType());
00346 if (syms.empty()) {
00347
00348 err = Symbol_Resolution_Failure;
00349 errMsg = "inconsistency found between archive's symbol table and member's symbol table";
00350 return false;
00351 }
00352
00353 for (auto iter2 = syms.begin(); iter2 != syms.end(); ++iter2) {
00354
00355
00356 if ((*iter2)->getType() == Symbol::ST_UNKNOWN) {
00357 continue;
00358 }
00359
00360 if (extSymbol == NULL || extSymbol->getLinkage() == Symbol::SL_WEAK) {
00361 extSymbol = *iter2;
00362 }
00363 else if ((*iter2)->getLinkage() == Symbol::SL_WEAK) {
00364 continue;
00365 }
00366 else {
00367
00368 err = Symbol_Resolution_Failure;
00369 errMsg = "ambiguous symbol definition: " +
00370 curUndefSym->getMangledName();
00371 return false;
00372 }
00373 }
00374 }
00375
00376 if( extSymbol == NULL ) {
00377
00378 if( curUndefSym->getLinkage() == Symbol::SL_WEAK ) {
00379 continue;
00380 }
00381
00382 err = Symbol_Resolution_Failure;
00383 errMsg = "failed to locate symbol '" + curUndefSym->getMangledName()
00384 + "' for object '" + curObjFile->memberName() + "'";
00385 rewrite_printf(" failed to locate symbol %s for %s \n" , curUndefSym->getMangledName().c_str(), curObjFile->memberName().c_str());
00386 return false;
00387 }
00388 Symtab *containingSymtab = extSymbol->getSymtab();
00389
00390 if( !linkedSet.count(containingSymtab) ) {
00391
00392 if( containingSymtab->getAddressWidth() != addressWidth_ ) {
00393 err = Symbol_Resolution_Failure;
00394 errMsg = "symbol (" + curUndefSym->getMangledName() +
00395 ") found in relocatable file that is not compatible"
00396 + " with the target binary";
00397 return false;
00398 }
00399
00400 relocatableObjects.push_back(containingSymtab);
00401
00402
00403
00404
00405 workSet.insert(containingSymtab);
00406 linkedSet.insert(containingSymtab);
00407 }
00408
00409 rewrite_printf("Found external symbol %s in object %s(%s)\n",
00410 extSymbol->getPrettyName().c_str(),
00411 containingSymtab->getParentArchive()->name().c_str(),
00412 containingSymtab->memberName().c_str());
00413 }
00414
00415 if (extSymbol->getType() == Symbol::ST_INDIRECT) {
00416 addIndirectSymbol(extSymbol, lmap);
00417 }
00418
00419
00420 map<Symbol *, vector<relocationEntry *> >::iterator relMap_it;
00421 relMap_it = symToRels.find(curUndefSym);
00422 if( relMap_it != symToRels.end() ) {
00423 vector<relocationEntry *>::iterator rel_it;
00424 for(rel_it = relMap_it->second.begin(); rel_it != relMap_it->second.end();
00425 ++rel_it)
00426 {
00427 (*rel_it)->addDynSym(extSymbol);
00428 }
00429 }
00430
00431
00432
00433
00434
00435
00436 }
00437
00438 curObjFilePtr = workSet.begin();
00439 }
00440
00441 return true;
00442 }
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 bool emitElfStatic::createLinkMap(Symtab *target,
00467 vector<Symtab *> &relocatableObjects,
00468 Offset & globalOffset,
00469 LinkMap &lmap,
00470 StaticLinkError &err, string &errMsg)
00471 {
00472 rewrite_printf("\n*** Allocating storage for relocatable objects\n\n");
00473
00474
00475 multimap<Offset, Symbol *> commonAlignments;
00476 Offset commonRegionAlign = 0;
00477
00478
00479 vector<Symtab *>::iterator obj_it;
00480 for(obj_it = relocatableObjects.begin(); obj_it != relocatableObjects.end(); ++obj_it) {
00481 vector<Region *> regs;
00482 if( !(*obj_it)->getAllRegions(regs) ) {
00483 err = Storage_Allocation_Failure;
00484 errMsg = "failed to locate regions in relocatable object";
00485 return false;
00486 }
00487
00488 vector<Region *>::iterator reg_it;
00489 for(reg_it = regs.begin(); reg_it != regs.end(); ++reg_it) {
00490 string regionName = (*reg_it)->getRegionName();
00491 if( (*reg_it)->isLoadable() && (*reg_it)->getMemSize() > 0) {
00492 if( (*reg_it)->isTLS() ) {
00493 switch((*reg_it)->getRegionType()) {
00494 case Region::RT_DATA:
00495 case Region::RT_BSS:
00496 lmap.tlsRegions.push_back(*reg_it);
00497
00498 if( (*reg_it)->getMemAlignment() > lmap.tlsRegionAlign ) {
00499 lmap.tlsRegionAlign = (*reg_it)->getMemAlignment();
00500 }
00501 break;
00502 default:
00503
00504 break;
00505 }
00506 }else if( isConstructorRegion(*reg_it) ) {
00507 lmap.newCtorRegions.push_back(*reg_it);
00508 if( (*reg_it)->getMemAlignment() > lmap.ctorRegionAlign ) {
00509 lmap.ctorRegionAlign = (*reg_it)->getMemAlignment();
00510 }
00511 }else if( isDestructorRegion(*reg_it) ) {
00512 lmap.newDtorRegions.push_back(*reg_it);
00513 if( (*reg_it)->getMemAlignment() > lmap.dtorRegionAlign ) {
00514 lmap.dtorRegionAlign = (*reg_it)->getMemAlignment();
00515 }
00516 } else if( isGOTRegion(*reg_it) ) {
00517 lmap.gotRegions.push_back(*reg_it);
00518 if( (*reg_it)->getMemAlignment() > lmap.gotRegionAlign ) {
00519 lmap.gotRegionAlign = (*reg_it)->getMemAlignment();
00520 }
00521 }else{
00522 switch((*reg_it)->getRegionType()) {
00523 case Region::RT_TEXT:
00524 lmap.codeRegions.push_back(*reg_it);
00525
00526 if( (*reg_it)->getMemAlignment() > lmap.codeRegionAlign ) {
00527 lmap.codeRegionAlign = (*reg_it)->getMemAlignment();
00528 }
00529 break;
00530 case Region::RT_DATA:
00531 lmap.dataRegions.push_back(*reg_it);
00532
00533 if( (*reg_it)->getMemAlignment() > lmap.dataRegionAlign ) {
00534 lmap.dataRegionAlign = (*reg_it)->getMemAlignment();
00535 }
00536
00537 break;
00538 case Region::RT_BSS:
00539 lmap.bssRegions.push_back(*reg_it);
00540
00541 if( (*reg_it)->getMemAlignment() > lmap.bssRegionAlign ) {
00542 lmap.bssRegionAlign = (*reg_it)->getMemAlignment();
00543 }
00544 break;
00545 case Region::RT_TEXTDATA:
00546 lmap.codeRegions.push_back(*reg_it);
00547
00548 if( (*reg_it)->getMemAlignment() > lmap.codeRegionAlign ) {
00549 lmap.codeRegionAlign = (*reg_it)->getMemAlignment();
00550 }
00551 break;
00552 default:
00553
00554 continue;
00555 }
00556 }
00557
00558
00559
00560 #if defined(arch_power) && defined(arch_64bit)
00561
00562 if(target->isStaticBinary() && (regionName.compare(".toc") == 0)) {
00563
00564
00565 char *rawRegionData = reinterpret_cast<char *>((*reg_it)->getPtrToRawData());
00566 unsigned long numSymbols = (*reg_it)->getMemSize()/8;
00567 for (Offset entry = 0; entry < numSymbols; entry++ ) {
00568
00569 bool relExist = false;
00570 vector<relocationEntry> ®ion_rels = (*reg_it)->getRelocations();
00571 vector<relocationEntry>::iterator rel_it;
00572 for( rel_it = region_rels.begin(); rel_it != region_rels.end(); ++rel_it) {
00573 if(entry*8 == rel_it->rel_addr()) {
00574 lmap.gotSymbolTable.push_back(make_pair(rel_it->getDynSym(), rel_it->addend()));
00575 lmap.gotSymbols.insert(make_pair(rel_it->getDynSym(), rel_it->addend()));
00576 relExist = true;
00577
00578 break;
00579 }
00580 }
00581 if(!relExist) {
00582
00583
00584 Offset soffset = *((unsigned long *) (rawRegionData + entry*8));
00585 Symbol *newsym = new Symbol("dyntoc_entry",
00586 Symbol::ST_UNKNOWN,
00587 Symbol::SL_UNKNOWN,
00588 Symbol::SV_UNKNOWN,
00589 soffset);
00590
00591 lmap.gotSymbolTable.push_back(make_pair(newsym, 0));
00592 lmap.gotSymbols.insert(make_pair(newsym, 0));
00593
00594 }
00595 }
00596
00597 }
00598 #endif
00599 vector<relocationEntry> ®ion_rels = (*reg_it)->getRelocations();
00600 vector<relocationEntry>::iterator rel_it;
00601 for( rel_it = region_rels.begin(); rel_it != region_rels.end(); ++rel_it) {
00602
00603 if(isGOTRelocation(rel_it->getRelType()) ) {
00604 lmap.gotSymbolTable.push_back(make_pair(rel_it->getDynSym(), rel_it->addend()));
00605 lmap.gotSymbols.insert(make_pair(rel_it->getDynSym(), 0));
00606
00607 }
00608
00609 }
00610 }
00611
00612 }
00613
00614 vector<Symbol *> definedSyms;
00615 if( (*obj_it)->getAllDefinedSymbols(definedSyms) ) {
00616 vector<Symbol *>::iterator sym_it;
00617 for(sym_it = definedSyms.begin(); sym_it != definedSyms.end(); ++sym_it) {
00618
00619
00620 if( (*sym_it)->isCommonStorage() ) {
00621
00622 commonAlignments.insert(make_pair((*sym_it)->getOffset(), *sym_it));
00623
00624
00625
00626 if( (*sym_it)->getOffset() > commonRegionAlign ) {
00627 commonRegionAlign = (*sym_it)->getOffset();
00628 }
00629 }else if( (*sym_it)->getType() == Symbol::ST_TLS ) {
00630 lmap.tlsSymbols.push_back(*sym_it);
00631 }
00632 }
00633 }
00634 }
00635
00636
00637
00638 Offset currentOffset = 0;
00639
00640
00641
00642
00643
00644
00645 Offset maxAlign = getGOTAlign(lmap);
00646 if(maxAlign < lmap.codeRegionAlign) maxAlign = lmap.codeRegionAlign;
00647
00648 globalOffset += computePadding(globalOffset + currentOffset,
00649 maxAlign);
00650
00651
00652 lmap.pltRegionAlign = lmap.codeRegionAlign;
00653 lmap.pltRegionOffset = currentOffset;
00654 lmap.pltRegionOffset += computePadding(globalOffset + lmap.pltRegionOffset,
00655 lmap.pltRegionAlign);
00656 currentOffset = allocatePLTEntries(lmap.pltEntries, lmap.pltRegionOffset, lmap.pltSize);
00657
00658 lmap.relRegionAlign = lmap.pltRegionAlign;
00659 lmap.relRegionOffset = currentOffset;
00660 lmap.relRegionOffset += computePadding(globalOffset + lmap.relRegionOffset,
00661 lmap.relRegionAlign);
00662 currentOffset = allocateRelocationSection(lmap.pltEntries, lmap.relRegionOffset,
00663 lmap.relSize, target);
00664
00665 lmap.relGotRegionAlign = lmap.pltRegionAlign;
00666 lmap.relGotRegionOffset = currentOffset;
00667 lmap.relGotRegionOffset += computePadding(globalOffset + lmap.relGotRegionOffset,
00668 lmap.relGotRegionAlign);
00669 currentOffset = allocateRelGOTSection(lmap.pltEntries, lmap.relGotRegionOffset,
00670 lmap.relGotSize);
00671
00672
00673 Offset gotLayoutOffset = 0;
00674 lmap.gotSize = getGOTSize(target, lmap, gotLayoutOffset);
00675 if( lmap.gotSize > 0 ) {
00676
00677
00678 lmap.gotRegionAlign = getGOTAlign(lmap);
00679 lmap.gotRegionOffset = currentOffset;
00680 currentOffset += lmap.gotSize;
00681 layoutRegions(lmap.gotRegions, lmap.regionAllocs,
00682 lmap.gotRegionOffset + gotLayoutOffset, globalOffset);
00683 calculateTOCs(target, lmap.gotRegions, lmap.gotRegionOffset, gotLayoutOffset, globalOffset);
00684 }
00685
00686
00687
00688
00689 lmap.stubRegionOffset = currentOffset;
00690 lmap.stubRegionOffset += computePadding(globalOffset + lmap.stubRegionOffset,
00691 lmap.codeRegionAlign);
00692 rewrite_printf("Before allocStubRegions, currentOffset is 0x%lx\n", currentOffset);
00693 currentOffset = allocStubRegions(lmap, globalOffset);
00694 rewrite_printf("After allocStubRegions, currentOffset is 0x%lx\n", currentOffset);
00695 if( currentOffset == ~0UL ) {
00696 err = Storage_Allocation_Failure;
00697 errMsg = "assumption failed while creating link map";
00698 return false;
00699 }
00700 lmap.stubSize = currentOffset - lmap.stubRegionOffset;
00701
00702 lmap.codeRegionOffset = currentOffset;
00703 lmap.codeRegionOffset += computePadding(globalOffset + lmap.codeRegionOffset,
00704 lmap.codeRegionAlign);
00705 currentOffset = layoutRegions(lmap.codeRegions, lmap.regionAllocs,
00706 lmap.codeRegionOffset, globalOffset);
00707 if( currentOffset == ~0UL ) {
00708 err = Storage_Allocation_Failure;
00709 errMsg = "assumption failed while creating link map";
00710 return false;
00711 }
00712 lmap.codeSize = currentOffset - lmap.codeRegionOffset;
00713
00714
00715 lmap.dataRegionOffset = currentOffset;
00716 lmap.dataRegionOffset += computePadding(globalOffset + lmap.dataRegionOffset,
00717 lmap.dataRegionAlign);
00718 currentOffset = layoutRegions(lmap.dataRegions, lmap.regionAllocs,
00719 lmap.dataRegionOffset, globalOffset);
00720 if( currentOffset == ~0UL ) {
00721 err = Storage_Allocation_Failure;
00722 errMsg = "assumption failed while creating link map";
00723 return false;
00724 }
00725 lmap.dataSize = currentOffset - lmap.dataRegionOffset;
00726
00727
00728
00729
00730
00731
00732
00733
00734 Region *dataTLS = NULL, *bssTLS = NULL;
00735 lmap.tlsSize = 0;
00736
00737 vector<Region *> regions;
00738 if( !target->getAllRegions(regions) ) {
00739 err = Storage_Allocation_Failure;
00740 errMsg = "failed to retrieve regions from target";
00741 return false;
00742 }
00743
00744 vector<Region *>::iterator reg_it;
00745 for(reg_it = regions.begin(); reg_it != regions.end(); ++reg_it) {
00746 if( (*reg_it)->isTLS() ) {
00747 if( (*reg_it)->getRegionType() == Region::RT_DATA ) {
00748 if( dataTLS != NULL ) {
00749 err = Storage_Allocation_Failure;
00750 errMsg = "found more than one TLS data region";
00751 return false;
00752 }
00753 dataTLS = *reg_it;
00754 lmap.tlsSize += dataTLS->getMemSize();
00755 if( dataTLS->getMemAlignment() > lmap.tlsRegionAlign ) {
00756 lmap.tlsRegionAlign = dataTLS->getMemAlignment();
00757 }
00758 }else if( (*reg_it)->getRegionType() == Region::RT_BSS ) {
00759 if( bssTLS != NULL ) {
00760 err = Storage_Allocation_Failure;
00761 errMsg = "found more than one TLS bss region";
00762 return false;
00763 }
00764 bssTLS = *reg_it;
00765 lmap.tlsSize += bssTLS->getMemSize();
00766 if( bssTLS->getMemAlignment() > lmap.tlsRegionAlign ) {
00767 lmap.tlsRegionAlign = bssTLS->getMemAlignment();
00768 }
00769 }
00770 }else if( isConstructorRegion(*reg_it) ) {
00771 lmap.originalCtorRegion = *reg_it;
00772 }else if( isDestructorRegion(*reg_it) ){
00773 lmap.originalDtorRegion = *reg_it;
00774 }
00775 }
00776 #if defined(arch_x86) || defined(arch_x86_64) || defined(arch_power)
00777
00778 if( lmap.tlsRegions.size() > 0 ) {
00779 lmap.tlsRegionOffset = currentOffset;
00780
00781 lmap.tlsRegionOffset += computePadding(lmap.tlsRegionOffset + globalOffset,
00782 lmap.tlsRegionAlign);
00783 currentOffset = layoutTLSImage(globalOffset, dataTLS, bssTLS, lmap);
00784
00785 if( currentOffset == lmap.tlsRegionOffset ) {
00786 err = Storage_Allocation_Failure;
00787 errMsg = "failed to create TLS initialization image";
00788 return false;
00789 }
00790
00791
00792
00793
00794
00795
00796
00797
00798 if( dataTLS != NULL ) {
00799 lmap.tlsSize -= dataTLS->getMemSize();
00800 }
00801
00802 lmap.tlsSize += currentOffset - lmap.tlsRegionOffset;
00803
00804
00805
00806 vector<Symbol *> definedSyms;
00807 if( target->getAllDefinedSymbols(definedSyms) ) {
00808 vector<Symbol *>::iterator sym_it;
00809 for(sym_it = definedSyms.begin(); sym_it != definedSyms.end(); ++sym_it) {
00810 if( (*sym_it)->getType() == Symbol::ST_TLS ) {
00811
00812 map<Region *, LinkMap::AllocPair>::iterator result;
00813 result = lmap.regionAllocs.find((*sym_it)->getRegion());
00814
00815 if( result != lmap.regionAllocs.end() ) {
00816 Offset regionOffset = result->second.second;
00817 Offset symbolOffset = (*sym_it)->getOffset();
00818 lmap.origSymbols.push_back(make_pair(*sym_it, symbolOffset));
00819
00820 symbolOffset += regionOffset - lmap.tlsRegionOffset;
00821 symbolOffset = adjustTLSOffset(symbolOffset, lmap.tlsSize);
00822
00823 (*sym_it)->setOffset(symbolOffset);
00824 }
00825 }
00826 }
00827 }
00828
00829 cleanupTLSRegionOffsets(lmap.regionAllocs, dataTLS, bssTLS);
00830 if( bssTLS != NULL ) lmap.tlsSize -= bssTLS->getMemSize();
00831
00832 hasRewrittenTLS_ = true;
00833 }else{
00834
00835
00836 vector<Symbol *> definedSyms;
00837 if( target->getAllDefinedSymbols(definedSyms) ) {
00838 vector<Symbol *>::iterator sym_it;
00839 for(sym_it = definedSyms.begin(); sym_it != definedSyms.end(); ++sym_it) {
00840 if( (*sym_it)->getType() == Symbol::ST_TLS ) {
00841 Offset symbolOffset = (*sym_it)->getOffset();
00842 lmap.origSymbols.push_back(make_pair(*sym_it, symbolOffset));
00843
00844 symbolOffset = adjustTLSOffset(symbolOffset, lmap.tlsSize);
00845 (*sym_it)->setOffset(symbolOffset);
00846 }
00847 }
00848 }
00849
00850
00851 lmap.tlsSize = 0;
00852 }
00853
00854 #endif
00855
00856 if( lmap.newCtorRegions.size() > 0 ) {
00857 lmap.ctorRegionOffset = currentOffset;
00858 lmap.ctorRegionOffset += computePadding(globalOffset + lmap.ctorRegionOffset,
00859 lmap.ctorRegionAlign);
00860 currentOffset = layoutNewCtorRegion(lmap);
00861 if( currentOffset == ~0UL ) {
00862 err = Storage_Allocation_Failure;
00863 errMsg = "assumption failed while creating link map";
00864 return false;
00865 }
00866 lmap.ctorSize = currentOffset - lmap.ctorRegionOffset;
00867 }
00868
00869
00870 if( lmap.newDtorRegions.size() > 0 ) {
00871 lmap.dtorRegionOffset = currentOffset;
00872 lmap.dtorRegionOffset += computePadding(globalOffset + lmap.dtorRegionOffset,
00873 lmap.dtorRegionAlign);
00874 currentOffset = layoutNewDtorRegion(lmap);
00875 if( currentOffset == ~0UL ) {
00876 err = Storage_Allocation_Failure;
00877 errMsg = "assumption failed while creating link map";
00878 return false;
00879 }
00880 lmap.dtorSize = currentOffset - lmap.dtorRegionOffset;
00881 }
00882
00883
00884 if( commonAlignments.size() > 0 ) {
00885
00886
00887 if( commonRegionAlign > lmap.bssRegionAlign ) {
00888 lmap.bssRegionAlign = commonRegionAlign;
00889 }
00890
00891
00892
00893 Offset commonOffset = currentOffset;
00894
00895
00896 commonOffset += computePadding(globalOffset + commonOffset, lmap.bssRegionAlign);
00897 Offset commonStartOffset = commonOffset;
00898
00899 multimap<Offset, Symbol *>::iterator align_it;
00900 for(align_it = commonAlignments.begin();
00901 align_it != commonAlignments.end(); ++align_it)
00902 {
00903 commonOffset += computePadding(commonOffset, align_it->first);
00904 lmap.origSymbols.push_back(make_pair(align_it->second, align_it->first));
00905
00906
00907 align_it->second->setOffset(globalOffset + commonOffset);
00908 commonOffset += align_it->second->getSize();
00909 }
00910
00911
00912 if( commonAlignments.size() > 0 ) {
00913
00914 lmap.commonStorage = Region::createRegion(0, Region::RP_RW,
00915 Region::RT_BSS, commonOffset - commonStartOffset, 0,
00916 commonOffset - commonStartOffset,
00917 DEFAULT_COM_NAME, NULL, true, false, commonRegionAlign);
00918 lmap.bssRegions.push_front(lmap.commonStorage);
00919 }
00920 }
00921
00922
00923 lmap.bssRegionOffset = currentOffset;
00924 lmap.bssRegionOffset += computePadding(globalOffset + lmap.bssRegionOffset,
00925 lmap.bssRegionAlign);
00926 currentOffset = layoutRegions(lmap.bssRegions, lmap.regionAllocs,
00927 lmap.bssRegionOffset, globalOffset);
00928 if( currentOffset == ~0UL ) {
00929 err = Storage_Allocation_Failure;
00930 errMsg = "assumption failed while creating link map";
00931 return false;
00932 }
00933
00934 lmap.bssSize = currentOffset - lmap.bssRegionOffset;
00935
00936
00937 for(obj_it = relocatableObjects.begin(); obj_it != relocatableObjects.end(); ++obj_it) {
00938 vector<Symbol *> definedSyms;
00939 if( (*obj_it)->getAllDefinedSymbols(definedSyms) ) {
00940 vector<Symbol *>::iterator sym_it;
00941 for(sym_it = definedSyms.begin(); sym_it != definedSyms.end(); ++sym_it) {
00942 if( !(*sym_it)->isCommonStorage()
00943 && (*sym_it)->getType() != Symbol::ST_TLS)
00944 {
00945 map<Region *, LinkMap::AllocPair>::iterator result;
00946 result = lmap.regionAllocs.find((*sym_it)->getRegion());
00947 if( result != lmap.regionAllocs.end() ) {
00948 Offset regionOffset = result->second.second;
00949 Offset symbolOffset = (*sym_it)->getOffset();
00950 lmap.origSymbols.push_back(make_pair(*sym_it, symbolOffset));
00951
00952 symbolOffset += globalOffset + regionOffset;
00953
00954 vector<relocationEntry> region_rels = result->first->getRelocations();
00955 if(region_rels.size() > 0) {
00956
00957
00958
00959
00960
00961 }
00962
00963
00964 (*sym_it)->setOffset(symbolOffset);
00965 }
00966 }
00967 }
00968 }
00969 }
00970
00971
00972
00973
00974
00975
00976
00977 lmap.allocatedData = new char[currentOffset];
00978 lmap.allocatedSize = currentOffset;
00979
00980
00981 copyRegions(lmap);
00982
00983 return true;
00984 }
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997 Offset emitElfStatic::layoutRegions(deque<Region *> ®ions,
00998 map<Region *, LinkMap::AllocPair> ®ionAllocs,
00999 Offset currentOffset, Offset globalOffset)
01000 {
01001 Offset retOffset = currentOffset;
01002
01003 deque<Region *>::iterator copyReg_it;
01004 for(copyReg_it = regions.begin(); copyReg_it != regions.end(); ++copyReg_it) {
01005
01006 if( (*copyReg_it)->getMemSize() == 0 ) continue;
01007
01008
01009 Offset padding = computePadding(globalOffset + retOffset, (*copyReg_it)->getMemAlignment());
01010 retOffset += padding;
01011
01012
01013 pair<map<Region *, LinkMap::AllocPair>::iterator, bool> result;
01014 result = regionAllocs.insert(make_pair(*copyReg_it, make_pair(padding, retOffset)));
01015
01016
01017 if( !result.second ) {
01018 retOffset = ~0UL;
01019 break;
01020 }
01021
01022 retOffset += (*copyReg_it)->getMemSize();
01023 }
01024
01025 return retOffset;
01026 }
01027
01028
01029
01030
01031
01032
01033
01034
01035 bool emitElfStatic::addNewRegions(Symtab *target, Offset globalOffset, LinkMap &lmap) {
01036 char *newTargetData = lmap.allocatedData;
01037
01038 #if defined(arch_x86) || defined(arch_x86_64) || (defined(arch_power) && defined(arch_64bit))
01039 if( lmap.gotSize > 0 ) {
01040 buildGOT(target, lmap);
01041 target->addRegion(globalOffset + lmap.gotRegionOffset,
01042 reinterpret_cast<void *>(&newTargetData[lmap.gotRegionOffset]),
01043 static_cast<unsigned int>(lmap.gotSize),
01044 GOT_NAME, Region::RT_DATA, true, lmap.gotRegionAlign);
01045 }
01046 #endif
01047 if( lmap.pltSize > 0 ) {
01048 target->addRegion(globalOffset + lmap.pltRegionOffset,
01049 reinterpret_cast<void *>(&newTargetData[lmap.pltRegionOffset]),
01050 static_cast<unsigned int>(lmap.pltSize),
01051 PLT_NAME, Region::RT_TEXTDATA, true, lmap.pltRegionAlign);
01052 }
01053
01054 if (lmap.relSize > 0) {
01055 target->addRegion(globalOffset + lmap.relRegionOffset,
01056 reinterpret_cast<void *>(&newTargetData[lmap.relRegionOffset]),
01057 static_cast<unsigned int>(lmap.relSize),
01058 REL_NAME, Region::RT_RELA, true, lmap.relRegionAlign);
01059 }
01060
01061 if (lmap.relGotSize > 0) {
01062 target->addRegion(globalOffset + lmap.relGotRegionOffset,
01063 reinterpret_cast<void *>(&newTargetData[lmap.relGotRegionOffset]),
01064 static_cast<unsigned int>(lmap.relGotSize),
01065 REL_GOT_NAME, Region::RT_TEXTDATA, true, lmap.relGotRegionAlign);
01066 }
01067
01068 if( lmap.codeSize > 0 ) {
01069 target->addRegion(globalOffset + lmap.codeRegionOffset,
01070 reinterpret_cast<void *>(&newTargetData[lmap.codeRegionOffset]),
01071 static_cast<unsigned int>(lmap.codeSize),
01072 CODE_NAME, Region::RT_TEXTDATA, true, lmap.codeRegionAlign);
01073 }
01074 if (lmap.stubSize > 0) {
01075 target->addRegion(globalOffset + lmap.stubRegionOffset,
01076 reinterpret_cast<void *>(&newTargetData[lmap.stubRegionOffset]),
01077 static_cast<unsigned int>(lmap.stubSize),
01078 STUB_NAME, Region::RT_TEXTDATA, true, lmap.codeRegionAlign);
01079 }
01080
01081 if( lmap.dataSize > 0 ) {
01082 target->addRegion(globalOffset + lmap.dataRegionOffset,
01083 reinterpret_cast<void *>(&newTargetData[lmap.dataRegionOffset]),
01084 static_cast<unsigned int>(lmap.dataSize),
01085 DATA_NAME, Region::RT_DATA, true, lmap.dataRegionAlign);
01086 }
01087
01088 #if defined(arch_x86) || defined(arch_x86_64) || defined(arch_power)
01089 if( lmap.tlsSize > 0 ) {
01090 target->addRegion(globalOffset + lmap.tlsRegionOffset,
01091 reinterpret_cast<void *>(&newTargetData[lmap.tlsRegionOffset]),
01092 static_cast<unsigned int>(lmap.tlsSize),
01093 TLS_DATA_NAME, Region::RT_DATA, true, lmap.tlsRegionAlign, true);
01094 }
01095 #endif
01096 if( lmap.newCtorRegions.size() > 0 ) {
01097 if( !createNewCtorRegion(lmap) ) {
01098 return false;
01099 }
01100
01101 target->addRegion(globalOffset + lmap.ctorRegionOffset,
01102 reinterpret_cast<void *>(&newTargetData[lmap.ctorRegionOffset]),
01103 static_cast<unsigned int>(lmap.ctorSize),
01104 CTOR_NAME, Region::RT_DATA, true,
01105 lmap.ctorRegionAlign);
01106 }
01107
01108 if( lmap.newDtorRegions.size() > 0 ) {
01109 if( !createNewDtorRegion(lmap) ) {
01110 return false;
01111 }
01112
01113 target->addRegion(globalOffset + lmap.dtorRegionOffset,
01114 reinterpret_cast<void *>(&newTargetData[lmap.dtorRegionOffset]),
01115 static_cast<unsigned int>(lmap.dtorSize),
01116 DTOR_NAME, Region::RT_DATA, true,
01117 lmap.dtorRegionAlign);
01118 }
01119
01120 if( lmap.bssSize > 0 ) {
01121 target->addRegion(globalOffset + lmap.bssRegionOffset,
01122 reinterpret_cast<void *>(&newTargetData[lmap.bssRegionOffset]),
01123 static_cast<unsigned int>(lmap.bssSize),
01124 BSS_NAME, Region::RT_BSS, true, lmap.bssRegionAlign);
01125 }
01126
01127 return true;
01128 }
01129
01130
01131
01132
01133
01134
01135
01136 void emitElfStatic::copyRegions(LinkMap &lmap) {
01137 char *targetData = lmap.allocatedData;
01138
01139 map<Region *, LinkMap::AllocPair>::iterator regOff_it;
01140 for(regOff_it = lmap.regionAllocs.begin(); regOff_it != lmap.regionAllocs.end(); ++regOff_it) {
01141 Region *depRegion = regOff_it->first;
01142 Offset regionOffset = regOff_it->second.second;
01143 Offset padding = regOff_it->second.first;
01144
01145
01146 char *rawRegionData = reinterpret_cast<char *>(depRegion->getPtrToRawData());
01147
01148 if( !depRegion->isBSS() ) {
01149 memcpy(&targetData[regionOffset], rawRegionData, depRegion->getMemSize());
01150 }
01151
01152
01153 memset(&targetData[regionOffset - padding], getPaddingValue(depRegion->getRegionType()), padding);
01154 }
01155 }
01156
01157
01158
01159
01160
01161
01162
01163 inline
01164 Offset emitElfStatic::computePadding(Offset candidateOffset, Offset alignment) {
01165 Offset padding = 0;
01166 if( alignment != 0 && (candidateOffset % alignment) != 0 ) {
01167 padding = alignment - (candidateOffset % alignment);
01168 }
01169 return padding;
01170 }
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182 bool emitElfStatic::applyRelocations(Symtab *target, vector<Symtab *> &relocatableObjects,
01183 Offset globalOffset, LinkMap &lmap,
01184 StaticLinkError &err, string &errMsg)
01185 {
01186
01187 vector<Symtab *>::iterator depObj_it;
01188 for(depObj_it = relocatableObjects.begin(); depObj_it != relocatableObjects.end(); ++depObj_it) {
01189 vector<Region *> allRegions;
01190 (*depObj_it)->getAllRegions(allRegions);
01191
01192
01193
01194 vector<Region *>::iterator region_it;
01195 for(region_it = allRegions.begin(); region_it != allRegions.end(); ++region_it) {
01196
01197 bool isText = ((*region_it)->getRegionType() == Region::RT_TEXT);
01198 bool isTOC = false;
01199
01200 string regionName = (*region_it)->getRegionName();
01201 if (regionName.compare(0, 4, ".toc") == 0) isTOC = true;
01202
01203 if (!isText && !isTOC) {
01204 continue;
01205 }
01206 map<Region *, LinkMap::AllocPair>::iterator result;
01207 result = lmap.regionAllocs.find(*region_it);
01208 if( result != lmap.regionAllocs.end() ) {
01209
01210 Offset regionOffset = result->second.second;
01211 vector<relocationEntry> region_rels = (*region_it)->getRelocations();
01212
01213 vector<relocationEntry>::iterator rel_it;
01214 for(rel_it = region_rels.begin(); rel_it != region_rels.end(); ++rel_it) {
01215
01216 Offset dest = regionOffset + rel_it->rel_addr();
01217 Offset relOffset = globalOffset + dest;
01218
01219 rewrite_printf("Computing relocations to apply to region: %s (%s) @ 0x%lx reloffset 0x%lx dest 0x%lx \n\n",
01220 (*region_it)->getRegionName().c_str(),
01221 (*region_it)->symtab()->file().c_str(),
01222 regionOffset,
01223 relOffset,
01224 dest);
01225 rewrite_printf("\t RelOffset computed as region 0x%lx + rel_addr 0x%lx + globalOffset 0x%lx\n",
01226 regionOffset, rel_it->rel_addr(), globalOffset);
01227
01228 char *targetData = lmap.allocatedData;
01229
01230 if( !archSpecificRelocation(target, *depObj_it,
01231 targetData, *rel_it, dest,
01232 relOffset, globalOffset, lmap, errMsg) )
01233 {
01234 err = Relocation_Computation_Failure;
01235 errMsg = "Failed to compute relocation: " + errMsg;
01236 return false;
01237 }
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259 }
01260 }
01261 }
01262 }
01263
01264 rewrite_printf("\n*** Computing relocations added to target.\n\n");
01265
01266
01267 vector<Region *> allRegions;
01268 target->getAllRegions(allRegions);
01269
01270 vector<Region *>::iterator reg_it;
01271 for(reg_it = allRegions.begin(); reg_it != allRegions.end(); ++reg_it) {
01272
01273 char *regionData = reinterpret_cast<char *>((*reg_it)->getPtrToRawData());
01274
01275 vector<relocationEntry>::iterator rel_it;
01276 for(rel_it = (*reg_it)->getRelocations().begin();
01277 rel_it != (*reg_it)->getRelocations().end();
01278 ++rel_it)
01279 {
01280
01281
01282 if ((rel_it->rel_addr() < (*reg_it)->getMemOffset()) ||
01283 (rel_it->rel_addr() >= ((*reg_it)->getMemOffset() + (*reg_it)->getMemSize()))) continue;
01284 if( !archSpecificRelocation(target, target, regionData, *rel_it,
01285 rel_it->rel_addr() - (*reg_it)->getDiskOffset(),
01286 rel_it->rel_addr(), globalOffset, lmap, errMsg) )
01287 {
01288 err = Relocation_Computation_Failure;
01289 errMsg = "Failed to compute relocation: " + errMsg;
01290 return false;
01291 }
01292 }
01293 }
01294 return true;
01295 }
01296
01297
01298
01299
01300
01301 string emitElfStatic::printStaticLinkError(StaticLinkError err) {
01302 switch(err) {
01303 CASE_RETURN_STR(No_Static_Link_Error);
01304 CASE_RETURN_STR(Symbol_Resolution_Failure);
01305 CASE_RETURN_STR(Relocation_Computation_Failure);
01306 CASE_RETURN_STR(Storage_Allocation_Failure);
01307 default:
01308 return "unknown error";
01309 }
01310 }
01311
01312
01313
01314
01315 bool emitElfStatic::hasRewrittenTLS() const {
01316 return hasRewrittenTLS_;
01317 }
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380 Offset emitElfStatic::tlsLayoutVariant1(Offset globalOffset, Region *dataTLS, Region *bssTLS, LinkMap &lmap)
01381 {
01382
01383
01384 unsigned long tlsBssSize = 0;
01385 if( dataTLS != NULL ) lmap.tlsRegions.push_back(dataTLS);
01386 if( bssTLS != NULL ) tlsBssSize = bssTLS->getMemSize();
01387 deque<Region *> tlsRegionsVar;
01388
01389 deque<Region *>::iterator copyReg_it;
01390 for(copyReg_it = lmap.tlsRegions.begin(); copyReg_it != lmap.tlsRegions.end(); ++copyReg_it) {
01391 tlsRegionsVar.push_front(*copyReg_it);
01392 }
01393
01394
01395 Offset endOffset = layoutRegions(lmap.tlsRegions,
01396 lmap.regionAllocs, lmap.tlsRegionOffset, globalOffset);
01397 if( endOffset == ~0UL ) return lmap.tlsRegionOffset;
01398 Offset adjustedEnd = endOffset - lmap.tlsRegionOffset;
01399
01400
01401
01402 if( bssTLS != NULL ) {
01403 if( dataTLS != NULL ) {
01404 lmap.regionAllocs.insert(make_pair(bssTLS, lmap.regionAllocs[dataTLS]));
01405 }else{
01406 lmap.regionAllocs.insert(make_pair(bssTLS, make_pair(0, endOffset)));
01407 }
01408 }
01409
01410
01411 vector<Symbol *>::iterator sym_it;
01412 for(sym_it = lmap.tlsSymbols.begin(); sym_it != lmap.tlsSymbols.end(); ++sym_it) {
01413 map<Region *, LinkMap::AllocPair>::iterator result;
01414 result = lmap.regionAllocs.find((*sym_it)->getRegion());
01415
01416
01417
01418 if( result == lmap.regionAllocs.end() ) {
01419 endOffset = lmap.tlsRegionOffset;
01420 break;
01421 }
01422
01423 Offset regionOffset = result->second.second;
01424 Offset symbolOffset = (*sym_it)->getOffset();
01425 lmap.origSymbols.push_back(make_pair((*sym_it), symbolOffset));
01426
01427 symbolOffset += (regionOffset - lmap.tlsRegionOffset) - (adjustedEnd + tlsBssSize);
01428 (*sym_it)->setOffset(symbolOffset);
01429 }
01430
01431 return endOffset;
01432 }
01433
01434 Offset emitElfStatic::tlsLayoutVariant2(Offset globalOffset, Region *dataTLS, Region *bssTLS,
01435 LinkMap &lmap)
01436 {
01437
01438
01439 unsigned long tlsBssSize = 0;
01440 if( dataTLS != NULL ) lmap.tlsRegions.push_back(dataTLS);
01441 if( bssTLS != NULL ) tlsBssSize = bssTLS->getMemSize();
01442
01443
01444 Offset endOffset = layoutRegions(lmap.tlsRegions,
01445 lmap.regionAllocs, lmap.tlsRegionOffset, globalOffset);
01446 if( endOffset == ~0UL ) return lmap.tlsRegionOffset;
01447 Offset adjustedEnd = endOffset - lmap.tlsRegionOffset;
01448
01449
01450
01451 if( bssTLS != NULL ) {
01452 if( dataTLS != NULL ) {
01453 lmap.regionAllocs.insert(make_pair(bssTLS, lmap.regionAllocs[dataTLS]));
01454 }else{
01455 lmap.regionAllocs.insert(make_pair(bssTLS, make_pair(0, endOffset)));
01456 }
01457 }
01458
01459
01460 vector<Symbol *>::iterator sym_it;
01461 for(sym_it = lmap.tlsSymbols.begin(); sym_it != lmap.tlsSymbols.end(); ++sym_it) {
01462 map<Region *, LinkMap::AllocPair>::iterator result;
01463 result = lmap.regionAllocs.find((*sym_it)->getRegion());
01464
01465
01466
01467 if( result == lmap.regionAllocs.end() ) {
01468 endOffset = lmap.tlsRegionOffset;
01469 break;
01470 }
01471
01472 Offset regionOffset = result->second.second;
01473 Offset symbolOffset = (*sym_it)->getOffset();
01474 lmap.origSymbols.push_back(make_pair((*sym_it), symbolOffset));
01475
01476 symbolOffset += (regionOffset - lmap.tlsRegionOffset) - (adjustedEnd + tlsBssSize);
01477 (*sym_it)->setOffset(symbolOffset);
01478 }
01479
01480 return endOffset;
01481 }
01482
01483
01484
01485 Offset emitElfStatic::tlsAdjustVariant2(Offset curOffset, Offset tlsSize) {
01486
01487 Offset retOffset = curOffset;
01488 retOffset -= tlsSize;
01489 return retOffset;
01490 }
01491
01492 void emitElfStatic::tlsCleanupVariant1(map<Region *, LinkMap::AllocPair> ®ionAllocs,
01493 Region *, Region *bssTLS)
01494 {
01495
01496 if( bssTLS != NULL ) regionAllocs.erase(bssTLS);
01497 }
01498
01499 void emitElfStatic::tlsCleanupVariant2(map<Region *, LinkMap::AllocPair> ®ionAllocs,
01500 Region *, Region *bssTLS)
01501 {
01502
01503 if( bssTLS != NULL ) regionAllocs.erase(bssTLS);
01504 }
01505
01506 bool
01507 emitElfUtils::sort_reg(const Region* a, const Region* b)
01508 {
01509 if (a->getMemOffset() == b->getMemOffset())
01510 return a->getMemSize() < b->getMemSize();
01511 return a->getMemOffset() < b->getMemOffset();
01512 }
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529 Address
01530 emitElfUtils::orderLoadableSections(Symtab *obj, vector<Region*> & sections)
01531 {
01532 Address ret = 0;
01533 Address sz = 0;
01534 vector<Region*> nonzero;
01535 vector<Region*> copy(sections);
01536 unsigned insert = sections.size()-1;
01537
01538 for(int i=copy.size()-1;i>=0;--i) {
01539 if(!copy[i]->getMemOffset())
01540 sections[insert--] = copy[i];
01541 else
01542 nonzero.push_back(copy[i]);
01543 sz += copy[i]->getMemSize();
01544 }
01545
01546 assert(nonzero.size() == (insert+1));
01547
01548 std::sort(nonzero.begin(),nonzero.end(),sort_reg);
01549 for(unsigned i=0;i<nonzero.size();++i)
01550 sections[i] = nonzero[i];
01551
01552 if(nonzero.size() > 0)
01553 ret = nonzero[0]->getMemOffset();
01554 else {
01555
01556 sz = (sz + 4096 - 1) & ~(4096-1);
01557 ret = obj->getFreeOffset(sz);
01558 if(!ret) {
01559 fprintf(stderr,"Failed to finde hole of size %lx, bailing\n",sz);
01560 }
01561 }
01562 return ret;
01563 }
01564
01565
01566 bool emitElfUtils::updateHeapVariables(Symtab *obj, unsigned long newSecsEndAddress ) {
01567 unsigned pgSize = (unsigned)getpagesize();
01568 const std::string minbrk(".minbrk");
01569 const std::string curbrk(".curbrk");
01570 std::vector<Symbol *> heapSyms;
01571 obj->findSymbol(heapSyms, minbrk, Symbol::ST_NOTYPE);
01572 obj->findSymbol(heapSyms, curbrk, Symbol::ST_NOTYPE);
01573
01574 std::vector<Symbol *>::iterator heapSymsIter;
01575 for(heapSymsIter = heapSyms.begin();
01576 heapSymsIter != heapSyms.end();
01577 ++heapSymsIter)
01578 {
01579 Region *symRegion = (*heapSymsIter)->getRegion();
01580 Offset symOffset = (*heapSymsIter)->getOffset();
01581 if( symOffset < symRegion->getDiskOffset() ) continue;
01582
01583 Offset regOffset = symOffset - symRegion->getDiskOffset();
01584 unsigned char *regData = reinterpret_cast<unsigned char *>(symRegion->getPtrToRawData());
01585 Offset heapAddr;
01586 memcpy(&heapAddr, ®Data[regOffset], sizeof(Offset));
01587
01588 heapAddr = (newSecsEndAddress & ~(pgSize-1)) + pgSize;
01589
01590 if( !symRegion->patchData(regOffset, &heapAddr, sizeof(Offset)) ) {
01591 rewrite_printf("Failed to update heap address\n");
01592 return false;
01593 }
01594 }
01595
01596 return true;
01597 }
01598
01599 inline
01600 static bool adjustValInRegion(Region *reg, Offset offInReg, Offset addressWidth, int adjust) {
01601 Offset newValue;
01602 unsigned char *oldValues;
01603
01604 oldValues = reinterpret_cast<unsigned char *>(reg->getPtrToRawData());
01605 memcpy(&newValue, &oldValues[offInReg], addressWidth);
01606 newValue += adjust;
01607 return reg->patchData(offInReg, &newValue, addressWidth);
01608 }
01609
01610 bool emitElfUtils::updateRelocation(Symtab *obj, relocationEntry &rel, int library_adjust) {
01611
01612 #if defined(arch_x86) || defined(arch_x86_64)
01613 Region *targetRegion = obj->findEnclosingRegion(rel.rel_addr());
01614 if( NULL == targetRegion ) {
01615 rewrite_printf("Failed to find enclosing Region for relocation");
01616 return false;
01617 }
01618
01619
01620 unsigned addressWidth = obj->getAddressWidth();
01621 if( addressWidth == 8 ) {
01622 switch(rel.getRelType()) {
01623 case R_X86_64_RELATIVE:
01624 rel.setAddend(rel.addend() + library_adjust);
01625 break;
01626 case R_X86_64_JUMP_SLOT:
01627 if( !adjustValInRegion(targetRegion,
01628 rel.rel_addr() - targetRegion->getDiskOffset(),
01629 addressWidth, library_adjust) )
01630 {
01631 rewrite_printf("Failed to update relocation\n");
01632 return false;
01633 }
01634 break;
01635 default:
01636
01637 break;
01638 }
01639 }else{
01640 switch(rel.getRelType()) {
01641 case R_386_RELATIVE:
01642
01643 if( !adjustValInRegion(targetRegion,
01644 rel.rel_addr() - targetRegion->getDiskOffset(),
01645 addressWidth, library_adjust) )
01646 {
01647 rewrite_printf("Failed to update relocation\n");
01648 return false;
01649 }
01650 break;
01651 case R_386_JMP_SLOT:
01652 if( !adjustValInRegion(targetRegion,
01653 rel.rel_addr() - targetRegion->getDiskOffset(),
01654 addressWidth, library_adjust) )
01655 {
01656 rewrite_printf("Failed to update relocation\n");
01657 return false;
01658 }
01659 break;
01660 default:
01661
01662 break;
01663 }
01664 }
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679 #else
01680 rewrite_printf("WARNING: updateRelocation is not implemented on this architecture\n");
01681 #endif
01682
01683 return true;
01684 }
01685
01686 bool emitElfStatic::calculateTOCs(Symtab *target, deque<Region *> ®ions, Offset GOTstart, Offset newStart, Offset globalOffset) {
01687 rewrite_printf("Calculating TOCs for merged GOT sections, base is 0x%lx, new regions at 0x%lx\n",
01688 GOTstart + globalOffset,
01689 GOTstart + newStart + globalOffset);
01690
01691 Offset GOTbase = GOTstart + globalOffset;
01692 Offset current = GOTbase + newStart;
01693 Offset currentTOC = target->getTOCoffset((Offset) 0);
01694 rewrite_printf("\tBase TOC is 0x%lx\n", currentTOC);
01695
01696 for (deque<Region *>::iterator iter = regions.begin(); iter != regions.end(); ++iter) {
01697 Region *reg = *iter;
01698 Symtab *symtab = reg->symtab();
01699
01700 Offset end = current + reg->getDiskSize();
01701
01702
01703
01704 if ((currentTOC + 0x7ff0) < end) {
01705
01706
01707 currentTOC = current + 0x8000;
01708 }
01709
01710 if ((currentTOC + 0x7ff0) < end) {
01711 assert(0 && "Need to implement -bbigtoc equivalent to rewrite this binary!");
01712 }
01713 symtab->setTOCOffset(currentTOC);
01714 current = end;
01715 }
01716 return true;
01717 }
01718
01719 Offset emitElfStatic::allocatePLTEntries(std::map<Symbol *, std::pair<Offset, Offset> > &pltEntries,
01720 Offset pltOffset,
01721 Offset &size) {
01722
01723
01724
01725
01726 #if defined(arch_x86)
01727 unsigned entry_size = 16;
01728 #elif defined(arch_x86_64)
01729 unsigned entry_size = 16;
01730 #elif defined(arch_power)
01731 unsigned entry_size = 0;
01732 #else
01733 #error "Unknown architecture"
01734 #endif
01735
01736 Offset cur = pltOffset;
01737 for (auto iter = pltEntries.begin(); iter != pltEntries.end(); ++iter) {
01738 iter->second.first = cur;
01739 cur += entry_size;
01740 }
01741
01742 size = cur - pltOffset;
01743 return cur;
01744 }
01745
01746 bool emitElfStatic::addIndirectSymbol(Symbol *sym, LinkMap &lmap) {
01747
01748 lmap.pltEntries[sym] = make_pair(0,0);
01749 return true;
01750 }
01751
01752
01753 bool emitElfStatic::buildPLT(Symtab *target, Offset globalOffset,
01754 LinkMap &lmap, StaticLinkError &err,
01755 string &errMsg) {
01756 #if !defined(arch_x86_64)
01757 return lmap.pltEntries.empty();
01758 #else
01759 unsigned char pltEntry[] = {0xff, 0x25, 0x00, 0x00, 0x00, 0x00,
01760 0x68, 0x00, 0x00, 0x00, 0x00,
01761 0xe9, 0x00, 0x00, 0x00, 0x00};
01762 unsigned pltEntrySize = 16;
01763 unsigned gotOffset = 2;
01764
01765 unsigned magicOffset = 6;
01766
01767 char *data = lmap.allocatedData;
01768
01769 unsigned index = 0;
01770 for (auto iter = lmap.pltEntries.begin(); iter != lmap.pltEntries.end(); ++iter) {
01771 char *entry = &(data[iter->second.first]);
01772
01773 memcpy(entry, pltEntry, pltEntrySize);
01774
01775 iter->second.second = lmap.relGotRegionOffset + (index * sizeof(void *)) + globalOffset;
01776 Offset curOffset = globalOffset + iter->second.first;
01777 int val = (int) (iter->second.second - curOffset - magicOffset);
01778
01779 memcpy(entry+gotOffset, &val, sizeof(int));
01780 ++index;
01781 }
01782 return true;
01783 #endif
01784 }
01785
01786 Offset emitElfStatic::allocateRelocationSection(std::map<Symbol *, std::pair<Offset, Offset> > &entries,
01787 Offset relocOffset, Offset &size,
01788 Symtab *target) {
01789 #if defined(arch_x86_64)
01790 unsigned relocSize = sizeof(Elf64_Rela);
01791 #elif defined(arch_x86)
01792 unsigned relocSize = sizeof(Elf32_Rela);
01793 #else
01794 size = 0;
01795 unsigned relocSize = 0;
01796 return relocOffset;
01797 #endif
01798
01799 Offset cur = relocOffset;
01800 Object *obj = target->getObject();
01801
01802 Region *rela = NULL;
01803 target->findRegion(rela, ".rela.plt");
01804
01805 unsigned relocEntries = entries.size() + (rela ? rela->getRelocations().size() : 0);
01806 cur += relocEntries * relocSize;
01807
01808 size = cur - relocOffset;
01809 return cur;
01810 }
01811
01812 Offset emitElfStatic::allocateRelGOTSection(const std::map<Symbol *, std::pair<Offset, Offset> > &entries,
01813 Offset relocOffset, Offset &size) {
01814 #if defined(arch_x86_64)
01815 unsigned relocSize = sizeof(Elf64_Rela);
01816 #else
01817 size = 0;
01818 return relocOffset;
01819 #endif
01820
01821 size = entries.size() * sizeof(void *);
01822 return relocOffset + size;
01823 }
01824
01825
01826 bool emitElfStatic::buildRela(Symtab *target, Offset globalOffset,
01827 LinkMap &lmap, StaticLinkError &err,
01828 string &errMsg) {
01829 if (lmap.relSize == 0) return true;
01830
01831 #if !defined(arch_x86_64)
01832
01833 return false;
01834 #endif
01835
01836 unsigned copied = 0;
01837
01838 char *data = lmap.allocatedData;
01839 Elf64_Rela *relas = (Elf64_Rela *) &(data[lmap.relRegionOffset]);
01840
01841 Region *rela = NULL;
01842 target->findRegion(rela, ".rela.plt");
01843 if (rela) {
01844 memcpy(relas, rela->getPtrToRawData(), rela->getDiskSize());
01845 copied += rela->getDiskSize();
01846 relas = (Elf64_Rela *) &(data[lmap.relRegionOffset + rela->getDiskSize()]);
01847 }
01848
01849 unsigned index = 0;
01850 for (auto iter = lmap.pltEntries.begin(); iter != lmap.pltEntries.end(); ++iter) {
01851
01852 relas[index].r_offset = iter->second.second;
01853 relas[index].r_info = ELF64_R_INFO((unsigned long) STN_UNDEF, R_X86_64_IRELATIVE);
01854 relas[index].r_addend = iter->first->getOffset();
01855 copied += sizeof(Elf64_Rela);
01856 ++index;
01857 }
01858 assert(copied == lmap.relSize);
01859
01860 return true;
01861 }