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
00052 using namespace Dyninst;
00053 using namespace Dyninst::SymtabAPI;
00054
00055 static const Offset GOT_RESERVED_SLOTS = 3;
00056 static const unsigned X86_WIDTH = 4;
00057 static const unsigned X86_64_WIDTH = 8;
00058
00059 #if defined(os_freebsd)
00060 #define R_X86_64_JUMP_SLOT R_X86_64_JMP_SLOT
00061 #endif
00062
00063
00064 #define UNKNOWN_ADDRESS_WIDTH_ASSERT "An unknown address width was encountered, can't continue"
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 static bool computeCtorDtorAddress(relocationEntry &rel, Offset globalOffset,
00089 LinkMap &lmap, string &errMsg, Offset &symbolOffset)
00090 {
00091 if( rel.name() == SYMTAB_CTOR_LIST_REL ) {
00092
00093 if( lmap.newCtorRegions.size() > 0 ) {
00094 symbolOffset = lmap.ctorRegionOffset + globalOffset;
00095 }else if( lmap.originalCtorRegion != NULL ) {
00096 symbolOffset = lmap.originalCtorRegion->getDiskOffset();
00097 }else{
00098 errMsg = "Failed to locate original .ctors Region -- cannot apply relocation";
00099 return false;
00100 }
00101 }else if( rel.name() == SYMTAB_DTOR_LIST_REL ) {
00102
00103 if( lmap.newDtorRegions.size() > 0 ) {
00104 symbolOffset = lmap.dtorRegionOffset + globalOffset;
00105 }else if( lmap.originalDtorRegion != NULL ) {
00106 symbolOffset = lmap.originalDtorRegion->getDiskOffset();
00107 }else{
00108 errMsg = "Failed to locate original .dtors Region -- cannot apply relocation";
00109 return false;
00110 }
00111 } else if (rel.name() == SYMTAB_IREL_START) {
00112
00113 symbolOffset = globalOffset + lmap.relRegionOffset;
00114 }
00115 else if (rel.name() == SYMTAB_IREL_END) {
00116
00117 symbolOffset = globalOffset + lmap.relRegionOffset + lmap.relSize;
00118 }
00119
00120 return true;
00121 }
00122
00123 bool emitElfStatic::archSpecificRelocation(Symtab *, Symtab *, char *targetData, relocationEntry &rel,
00124 Offset dest, Offset relOffset, Offset globalOffset, LinkMap &lmap,
00125 string &errMsg)
00126 {
00127 Offset symbolOffset = 0;
00128 if (rel.getDynSym()->getType() != Symbol::ST_INDIRECT) {
00129
00130 symbolOffset = rel.getDynSym()->getOffset();
00131 }
00132 else {
00133
00134
00135 auto pltEntry = lmap.pltEntries.find(rel.getDynSym());
00136 if (pltEntry == lmap.pltEntries.end()) {
00137 return false;
00138 }
00139 symbolOffset = pltEntry->second.first + globalOffset;
00140 }
00141
00142 if( X86_WIDTH == addressWidth_ ) {
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 Elf32_Word addend;
00154 if( rel.regionType() == Region::RT_REL ) {
00155 memcpy(&addend, &targetData[dest], sizeof(Elf32_Word));
00156 }else if( rel.regionType() == Region::RT_RELA ) {
00157 addend = rel.addend();
00158 }
00159
00160 if( !computeCtorDtorAddress(rel, globalOffset, lmap, errMsg, symbolOffset) ) {
00161 return false;
00162 }
00163
00164 rewrite_printf("relocation for '%s': TYPE = %s(%lu) S = %lx A = %lx P = %lx\n",
00165 rel.name().c_str(),
00166 relocationEntry::relType2Str(rel.getRelType(), addressWidth_),
00167 rel.getRelType(), symbolOffset, addend, relOffset);
00168
00169 Offset relocation = 0;
00170 map<Symbol *, Offset>::iterator result;
00171 stringstream tmp;
00172
00173 switch(rel.getRelType()) {
00174 case R_386_32:
00175 relocation = symbolOffset + addend;
00176 break;
00177 case R_386_PLT32:
00178 case R_386_PC32:
00179 relocation = symbolOffset + addend - relOffset;
00180 break;
00181 case R_386_TLS_LE:
00182 case R_386_GLOB_DAT:
00183 case R_386_JMP_SLOT:
00184 relocation = symbolOffset;
00185 break;
00186 case R_386_TLS_GD:
00187 case R_386_GOT32:
00188 case R_386_TLS_GOTIE:
00189 result = lmap.gotSymbols.find(rel.getDynSym());
00190 if( result == lmap.gotSymbols.end() ) {
00191 errMsg = "Expected GOT symbol does not exist in GOT symbol mapping";
00192 return false;
00193 }
00194
00195 relocation = result->second;
00196 break;
00197 case R_386_GOTOFF:
00198 relocation = symbolOffset + addend - (lmap.gotRegionOffset + globalOffset);
00199 break;
00200 case R_386_GOTPC:
00201 relocation = globalOffset + lmap.gotRegionOffset + addend - relOffset;
00202 break;
00203 case R_386_TLS_IE:
00204 result = lmap.gotSymbols.find(rel.getDynSym());
00205 if( result == lmap.gotSymbols.end() ) {
00206 errMsg = "Expected GOT symbol does not exist in GOT symbol mapping";
00207 return false;
00208 }
00209
00210 relocation = result->second + lmap.gotRegionOffset + globalOffset;
00211 break;
00212 case R_386_COPY:
00213 case R_386_RELATIVE:
00214 tmp << "ERROR: encountered relocation type(" << rel.getRelType() <<
00215 ") that is meant for use during dynamic linking";
00216 errMsg = tmp.str();
00217 return false;
00218 default:
00219 tmp << "Relocation type " << rel.getRelType()
00220 << " currently unimplemented";
00221 errMsg = tmp.str();
00222 return false;
00223 }
00224
00225 rewrite_printf("relocation = 0x%lx @ 0x%lx\n", relocation, relOffset);
00226
00227 memcpy(&targetData[dest], &relocation, sizeof(Elf32_Word));
00228 }else if( X86_64_WIDTH == addressWidth_ ) {
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 unsigned symbolSize = rel.getDynSym()->getSize();
00247
00248 Elf64_Xword addend = 0;
00249 if( Region::RT_RELA == rel.regionType() ) {
00250 addend = rel.addend();
00251 }
00252
00253 if( !computeCtorDtorAddress(rel, globalOffset, lmap, errMsg, symbolOffset) ) {
00254 return false;
00255 }
00256
00257 rewrite_printf("relocation for '%s': TYPE = %s(%lu) S = %llx A = %llx P = %llx Z = %lx\n",
00258 rel.name().c_str(),
00259 relocationEntry::relType2Str(rel.getRelType(), addressWidth_),
00260 rel.getRelType(),
00261 symbolOffset, addend, relOffset, symbolSize);
00262
00263 Offset relocation = 0;
00264 unsigned fieldSize = 0;
00265 map<Symbol *, Offset>::iterator result;
00266 stringstream tmp;
00267
00268 switch(rel.getRelType()) {
00269 case R_X86_64_64:
00270 fieldSize = sizeof(Elf64_Xword);
00271 relocation = symbolOffset + addend;
00272 break;
00273 case R_X86_64_PLT32:
00274 case R_X86_64_PC32:
00275 fieldSize = sizeof(Elf64_Word);
00276 relocation = symbolOffset + addend - relOffset;
00277 break;
00278 case R_X86_64_GOT32:
00279 fieldSize = sizeof(Elf64_Word);
00280 result = lmap.gotSymbols.find(rel.getDynSym());
00281 if( result == lmap.gotSymbols.end() ) {
00282 errMsg = "Expected GOT symbol does not exist in GOT symbol mapping";
00283 return false;
00284 }
00285
00286 relocation = result->second + addend;
00287 break;
00288 case R_X86_64_TPOFF32:
00289 fieldSize = sizeof(Elf64_Word);
00290 relocation = symbolOffset;
00291 break;
00292 case R_X86_64_GLOB_DAT:
00293 case R_X86_64_JUMP_SLOT:
00294 fieldSize = sizeof(Elf64_Xword);
00295 relocation = symbolOffset;
00296 break;
00297 case R_X86_64_TLSLD:
00298 case R_X86_64_TLSGD:
00299 case R_X86_64_GOTTPOFF:
00300 case R_X86_64_GOTPCREL:
00301 fieldSize = sizeof(Elf64_Word);
00302
00303 result = lmap.gotSymbols.find(rel.getDynSym());
00304 if( result == lmap.gotSymbols.end() ) {
00305 errMsg = "Expected GOT symbol does not exist in GOT symbol mapping";
00306 return false;
00307 }
00308
00309 relocation = result->second + lmap.gotRegionOffset +
00310 globalOffset + addend - relOffset;
00311 break;
00312 case R_X86_64_DTPOFF32:
00313 fieldSize = sizeof(Elf64_Word);
00314 relocation = addend;
00315 break;
00316 case R_X86_64_32:
00317 case R_X86_64_32S:
00318 fieldSize = sizeof(Elf64_Word);
00319 relocation = symbolOffset + addend;
00320 break;
00321 case R_X86_64_16:
00322 fieldSize = sizeof(uint16_t);
00323 relocation = symbolOffset + addend;
00324 break;
00325 case R_X86_64_PC16:
00326 fieldSize = sizeof(uint16_t);
00327 relocation = symbolOffset + addend - relOffset;
00328 break;
00329 case R_X86_64_8:
00330 fieldSize = sizeof(uint8_t);
00331 relocation = symbolOffset + addend;
00332 break;
00333 case R_X86_64_PC8:
00334 fieldSize = sizeof(uint8_t);
00335 relocation = symbolOffset + addend - relOffset;
00336 break;
00337 case R_X86_64_RELATIVE:
00338 case R_X86_64_COPY:
00339 tmp << "ERROR: encountered relocation type(" << rel.getRelType() <<
00340 ") that is meant for use during dynamic linking";
00341 errMsg = tmp.str();
00342 return false;
00343 #if defined(R_X86_64_IRELATIVE)
00344 case R_X86_64_IRELATIVE:
00345
00346
00347 assert(0);
00348 return false;
00349 #endif
00350 case R_X86_64_DTPMOD64:
00351 case R_X86_64_DTPOFF64:
00352 case R_X86_64_TPOFF64:
00353 default:
00354 tmp << "Relocation type " << rel.getRelType()
00355 << " currently unimplemented";
00356 errMsg = tmp.str();
00357 return false;
00358 }
00359
00360 rewrite_printf("relocation = 0x%llx @ 0x%llx\n", relocation, relOffset);
00361
00362 memcpy(&targetData[dest], &relocation, fieldSize);
00363 }else{
00364 assert(!UNKNOWN_ADDRESS_WIDTH_ASSERT);
00365 }
00366
00367 return true;
00368 }
00369
00370 static const string LIBC_ATEXIT_INTERNAL("__cxa_exit");
00371 static const string LIBC_ATEXIT("atexit");
00372
00373 bool emitElfStatic::checkSpecialCaseSymbols(Symtab *member, Symbol *checkSym) {
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 if( isStripped_ ) {
00395 if( LIBC_ATEXIT_INTERNAL == checkSym->getPrettyName() ||
00396 LIBC_ATEXIT == checkSym->getPrettyName() )
00397 {
00398 fprintf(stderr, "WARNING: code in %s(%s) references the libc function %s.\n",
00399 member->getParentArchive()->name().c_str(),
00400 member->memberName().c_str(), checkSym->getPrettyName().c_str());
00401 fprintf(stderr, " Also, the binary to be rewritten is stripped.\n");
00402 fprintf(stderr, " Currently, the combination of these two "
00403 "is unsupported and unexpected behavior may occur.\n");
00404 }
00405 }
00406
00407 return true;
00408 }
00409
00410
00411
00412 Offset emitElfStatic::layoutTLSImage(Offset globalOffset, Region *dataTLS, Region *bssTLS, LinkMap &lmap) {
00413 return tlsLayoutVariant2(globalOffset, dataTLS, bssTLS, lmap);
00414 }
00415
00416 Offset emitElfStatic::adjustTLSOffset(Offset curOffset, Offset tlsSize) {
00417 return tlsAdjustVariant2(curOffset, tlsSize);
00418 }
00419
00420 char emitElfStatic::getPaddingValue(Region::RegionType rtype) {
00421 const char X86_NOP = 0x90;
00422
00423 char retChar = 0;
00424 if( rtype == Region::RT_TEXT || rtype == Region::RT_TEXTDATA ) {
00425 retChar = X86_NOP;
00426 }
00427
00428 return retChar;
00429 }
00430
00431 void emitElfStatic::cleanupTLSRegionOffsets(map<Region *, LinkMap::AllocPair> ®ionAllocs,
00432 Region *dataTLS, Region *bssTLS)
00433 {
00434 tlsCleanupVariant2(regionAllocs, dataTLS, bssTLS);
00435 }
00436
00437 void emitElfStatic::getExcludedSymbolNames(set<string> &symNames) {
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447 symNames.insert("_GLOBAL_OFFSET_TABLE_");
00448 }
00449
00450 bool emitElfStatic::isGOTRelocation(unsigned long relType) {
00451 if( X86_WIDTH == addressWidth_ ) {
00452 switch(relType) {
00453 case R_386_GOT32:
00454 case R_386_TLS_IE:
00455 case R_386_TLS_GOTIE:
00456 case R_386_TLS_LDM:
00457 case R_386_TLS_GD:
00458 return true;
00459 break;
00460 default:
00461 return false;
00462 break;
00463 }
00464 }else if( X86_64_WIDTH == addressWidth_ ) {
00465 switch(relType) {
00466 case R_X86_64_TLSLD:
00467 case R_X86_64_TLSGD:
00468 case R_X86_64_GOTTPOFF:
00469 case R_X86_64_GOT32:
00470 case R_X86_64_GOTPCREL:
00471 return true;
00472 break;
00473 default:
00474 return false;
00475 break;
00476 }
00477 }else{
00478 assert(!UNKNOWN_ADDRESS_WIDTH_ASSERT);
00479 }
00480
00481 return false;
00482 }
00483
00484 Offset emitElfStatic::getGOTSize(Symtab *, LinkMap &lmap, Offset &layoutStart) {
00485 Offset size = 0;
00486 layoutStart = 0;
00487
00488 unsigned slotSize = 0;
00489 if( X86_WIDTH == addressWidth_ ) {
00490 slotSize = sizeof(Elf32_Addr);
00491 }else if( X86_64_WIDTH == addressWidth_ ) {
00492 slotSize = sizeof(Elf64_Addr);
00493 }else{
00494 assert(!UNKNOWN_ADDRESS_WIDTH_ASSERT);
00495 }
00496
00497
00498 if( lmap.gotSymbols.size() > 0 ) {
00499 size = (lmap.gotSymbols.size()+GOT_RESERVED_SLOTS)*slotSize;
00500 }
00501
00502 return size;
00503 }
00504
00505 Offset emitElfStatic::getGOTAlign(LinkMap &) {
00506 if( X86_WIDTH == addressWidth_ ) {
00507 return sizeof(Elf32_Word);
00508 }else if( X86_64_WIDTH == addressWidth_ ) {
00509 return sizeof(Elf64_Xword);
00510 }else{
00511 assert(!UNKNOWN_ADDRESS_WIDTH_ASSERT);
00512 }
00513
00514 return 0;
00515 }
00516
00517 void emitElfStatic::buildGOT(Symtab *, LinkMap &lmap) {
00518 char *targetData = lmap.allocatedData;
00519
00520 unsigned slotSize = 0;
00521 if( X86_WIDTH == addressWidth_ ) {
00522 slotSize = sizeof(Elf32_Addr);
00523 }else if( X86_64_WIDTH == addressWidth_ ) {
00524 slotSize = sizeof(Elf64_Addr);
00525 }else{
00526 assert(!UNKNOWN_ADDRESS_WIDTH_ASSERT);
00527 }
00528
00529
00530
00531
00532 Offset curOffset = GOT_RESERVED_SLOTS*slotSize;
00533 memset(&targetData[lmap.gotRegionOffset], 0, GOT_RESERVED_SLOTS*slotSize);
00534
00535 map<Symbol *, Offset>::iterator sym_it;
00536 for(sym_it = lmap.gotSymbols.begin(); sym_it != lmap.gotSymbols.end(); ++sym_it) {
00537 Offset value = sym_it->first->getOffset();
00538 memcpy(&targetData[lmap.gotRegionOffset + curOffset], &value, slotSize);
00539
00540 sym_it->second = curOffset;
00541
00542 curOffset += slotSize;
00543 }
00544 }
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568 static const Elf64_Word X86_HEADER = 0xffffffff;
00569 static const Elf64_Word X86_TRAILER = 0x00000000;
00570 static const Elf64_Xword X86_64_HEADER = 0xffffffffffffffffULL;
00571 static const Elf64_Xword X86_64_TRAILER = 0x0000000000000000ULL;
00572 static const string DTOR_NAME(".dtors");
00573 static const string CTOR_NAME(".ctors");
00574
00575 bool emitElfStatic::isConstructorRegion(Region *reg) {
00576 return ( CTOR_NAME.compare(reg->getRegionName()) == 0 );
00577 }
00578
00579 bool emitElfStatic::isGOTRegion(Region *) {
00580 return false;
00581 }
00582
00583 Offset emitElfStatic::layoutNewCtorRegion(LinkMap &lmap) {
00584
00585
00586
00587
00588 Offset retOffset = lmap.ctorRegionOffset;
00589 retOffset += addressWidth_;
00590
00591 pair<map<Region *, LinkMap::AllocPair>::iterator, bool> result;
00592
00593 vector<Region *>::iterator reg_it;
00594 for(reg_it = lmap.newCtorRegions.begin(); reg_it != lmap.newCtorRegions.end(); ++reg_it) {
00595 result = lmap.regionAllocs.insert(make_pair(*reg_it, make_pair(0, retOffset)));
00596
00597
00598 if( !result.second ) {
00599 return ~0UL;
00600 }
00601
00602 retOffset += (*reg_it)->getDiskSize();
00603 }
00604
00605 if( lmap.originalCtorRegion != NULL ) {
00606
00607 retOffset += lmap.originalCtorRegion->getDiskSize() - addressWidth_ - addressWidth_;
00608 }
00609 retOffset += addressWidth_;
00610
00611 return retOffset;
00612 }
00613
00614 bool emitElfStatic::createNewCtorRegion(LinkMap &lmap) {
00615 char *targetData = lmap.allocatedData;
00616
00617 if( X86_WIDTH != addressWidth_ && X86_64_WIDTH != addressWidth_ ) {
00618 assert(!UNKNOWN_ADDRESS_WIDTH_ASSERT);
00619 }
00620
00621 unsigned trailerSize, headerSize;
00622
00623
00624 Offset headerOffset = lmap.ctorRegionOffset;
00625 Offset trailerOffset;
00626 if( X86_WIDTH == addressWidth_ ) {
00627 memcpy(&targetData[headerOffset], &X86_HEADER, sizeof(X86_HEADER));
00628 trailerOffset = lmap.ctorRegionOffset + lmap.ctorSize - sizeof(X86_TRAILER);
00629 memcpy(&targetData[trailerOffset], &X86_TRAILER, sizeof(X86_TRAILER));
00630 headerSize = sizeof(X86_HEADER);
00631 trailerSize = sizeof(X86_TRAILER);
00632 }else{
00633 memcpy(&targetData[headerOffset], &X86_64_HEADER, sizeof(X86_64_HEADER));
00634 trailerOffset = lmap.ctorRegionOffset + lmap.ctorSize - sizeof(X86_64_TRAILER);
00635 memcpy(&targetData[trailerOffset], &X86_64_TRAILER, sizeof(X86_64_TRAILER));
00636 headerSize = sizeof(X86_64_HEADER);
00637 trailerSize = sizeof(X86_64_TRAILER);
00638 }
00639
00640 if( lmap.originalCtorRegion != NULL ) {
00641
00642 Offset originalOffset = lmap.ctorRegionOffset + lmap.ctorSize -
00643 trailerSize - (lmap.originalCtorRegion->getDiskSize() - headerSize - trailerSize);
00644
00645
00646 char *rawRegionData = reinterpret_cast<char *>(lmap.originalCtorRegion->getPtrToRawData());
00647 memcpy(&targetData[originalOffset], &rawRegionData[headerSize],
00648 lmap.originalCtorRegion->getDiskSize() - headerSize - trailerSize);
00649 }
00650
00651 return true;
00652 }
00653
00654 bool emitElfStatic::isDestructorRegion(Region *reg) {
00655 return ( DTOR_NAME.compare(reg->getRegionName()) == 0 );
00656 }
00657
00658 Offset emitElfStatic::layoutNewDtorRegion(LinkMap &lmap) {
00659
00660
00661
00662
00663 Offset retOffset = lmap.dtorRegionOffset;
00664 retOffset += addressWidth_;
00665
00666 pair<map<Region *, LinkMap::AllocPair>::iterator, bool> result;
00667 if( lmap.originalDtorRegion != NULL ) {
00668
00669 retOffset += lmap.originalDtorRegion->getDiskSize() - addressWidth_ - addressWidth_;
00670 }
00671
00672 vector<Region *>::iterator reg_it;
00673 for(reg_it = lmap.newDtorRegions.begin(); reg_it != lmap.newDtorRegions.end(); ++reg_it) {
00674 result = lmap.regionAllocs.insert(make_pair(*reg_it, make_pair(0, retOffset)));
00675
00676
00677 if( !result.second ) {
00678 return ~0UL;
00679 }
00680
00681 retOffset += (*reg_it)->getDiskSize();
00682 }
00683
00684 retOffset += addressWidth_;
00685 return retOffset;
00686 }
00687
00688 bool emitElfStatic::createNewDtorRegion(LinkMap &lmap) {
00689 char *targetData = lmap.allocatedData;
00690
00691 if( X86_WIDTH != addressWidth_ && X86_64_WIDTH != addressWidth_ ) {
00692 assert(!UNKNOWN_ADDRESS_WIDTH_ASSERT);
00693 }
00694
00695 unsigned headerSize, trailerSize;
00696
00697
00698 Offset headerOffset = lmap.dtorRegionOffset;
00699 Offset trailerOffset;
00700 if( X86_WIDTH == addressWidth_ ) {
00701 memcpy(&targetData[headerOffset], &X86_HEADER, sizeof(X86_HEADER));
00702 trailerOffset = lmap.dtorRegionOffset + lmap.dtorSize - sizeof(X86_TRAILER);
00703 memcpy(&targetData[trailerOffset], &X86_TRAILER, sizeof(X86_TRAILER));
00704 headerSize = sizeof(X86_HEADER);
00705 trailerSize = sizeof(X86_TRAILER);
00706 }else{
00707 memcpy(&targetData[headerOffset], &X86_64_HEADER, sizeof(X86_64_HEADER));
00708 trailerOffset = lmap.dtorRegionOffset + lmap.dtorSize - sizeof(X86_64_TRAILER);
00709 memcpy(&targetData[trailerOffset], &X86_64_TRAILER, sizeof(X86_64_TRAILER));
00710 headerSize = sizeof(X86_64_HEADER);
00711 trailerSize = sizeof(X86_64_TRAILER);
00712 }
00713
00714 if( lmap.originalDtorRegion != NULL ) {
00715
00716 Offset originalOffset = lmap.dtorRegionOffset + headerSize;
00717
00718
00719 char *rawRegionData = reinterpret_cast<char *>(lmap.originalDtorRegion->getPtrToRawData());
00720 memcpy(&targetData[originalOffset], &rawRegionData[headerSize],
00721 lmap.originalDtorRegion->getDiskSize() - headerSize - trailerSize);
00722 }
00723
00724 return true;
00725 }
00726
00727 bool emitElfStatic::updateTOC(Symtab *, LinkMap &, Offset) {
00728 return true;
00729 }
00730
00731 Offset emitElfStatic::allocStubRegions(LinkMap &lmap, Offset) {
00732
00733 return lmap.stubRegionOffset;
00734 }