emitElfStatic-x86.C

Go to the documentation of this file.
00001 /*
00002  * See the dyninst/COPYRIGHT file for copyright information.
00003  * 
00004  * We provide the Paradyn Tools (below described as "Paradyn")
00005  * on an AS IS basis, and do not warrant its validity or performance.
00006  * We reserve the right to update, modify, or discontinue this
00007  * software at any time.  We shall have no obligation to supply such
00008  * updates or modifications or any other form of support to you.
00009  * 
00010  * By your use of Paradyn, you understand and agree that we (or any
00011  * other person or entity with proprietary rights in Paradyn) are
00012  * under no obligation to provide either maintenance services,
00013  * update services, notices of latent defects, or correction of
00014  * defects for Paradyn.
00015  * 
00016  * This library is free software; you can redistribute it and/or
00017  * modify it under the terms of the GNU Lesser General Public
00018  * License as published by the Free Software Foundation; either
00019  * version 2.1 of the License, or (at your option) any later version.
00020  * 
00021  * This library is distributed in the hope that it will be useful,
00022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00024  * Lesser General Public License for more details.
00025  * 
00026  * You should have received a copy of the GNU Lesser General Public
00027  * License along with this library; if not, write to the Free Software
00028  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00029  */
00030 
00031 /* 
00032  * holds architecture specific functions for x86 and x86_64 architecture needed for the
00033  * static executable rewriter
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 // Used in an assert so needs to be a macro
00064 #define UNKNOWN_ADDRESS_WIDTH_ASSERT "An unknown address width was encountered, can't continue"
00065 
00066 /* NOTE:
00067  * As most of these functions are defined per architecture, the description of
00068  * each of these functions is in the emitElfStatic header. Comments describing
00069  * the function interface are explicitly left out.
00070  */
00071 
00072 /**
00073  * Specific to x86
00074  *
00075  * Given a relocation, determines if the relocation corresponds to a .ctors or .dtors
00076  * table that requires special consideration. Modifies the passed symbol offset to
00077  * point to the right table, if applicable.
00078  *
00079  * rel          The relocation entry to examine
00080  * globalOffset The offset of the linked code (used for symbol offset calculation)
00081  * lmap         Holds information about .ctors/.dtors tables
00082  * errMsg       Set on error
00083  * symbolOffset Modified by this routine to contain the offset of the table
00084  *
00085  * Returns true, if there are no errors including the case where the relocation 
00086  * entry doesn't reference the .ctors/.dtors tables.
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         // This needs to be: (the location of the .ctors table)
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         // This needs to be: (the location of the .dtors table)
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       // Start of our moved relocation section
00113       symbolOffset = globalOffset + lmap.relRegionOffset;
00114     }
00115     else if (rel.name() == SYMTAB_IREL_END) {
00116       // End of our moved relocation section
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     // Easy case, just use the symbol as given
00130     symbolOffset = rel.getDynSym()->getOffset();
00131   }
00132   else {
00133     // Indirect; the address is the PLT entry (yes, I said PLT)
00134     // associated with this symbol. 
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          * Referring to the SYSV 386 supplement:
00145          *
00146          * All relocations on x86 are one word32 == Elf32_Word
00147          *
00148          * S = symbolOffset
00149          * A = addend
00150          * P = relOffset
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: // this works because the address of the symbol is known at link time
00178             case R_386_PC32:
00179                 relocation = symbolOffset + addend - relOffset;
00180                 break;
00181             case R_386_TLS_LE: // The necessary value is set during storage allocation
00182             case R_386_GLOB_DAT:
00183             case R_386_JMP_SLOT:
00184                 relocation = symbolOffset;
00185                 break;
00186             case R_386_TLS_GD: // The address is computed when the GOT is built
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          * Referring to the SYSV supplement:
00231          *
00232          * There are a few data types used by x86_64 relocations.
00233          *
00234          * word8 = uint8_t
00235          * word16 = uint16_t
00236          * word32 = Elf64_Word
00237          * word64 = Elf64_Xword
00238          *
00239          * S = symbolOffset
00240          * A = addend
00241          * P = relOffset
00242          * Z = symbolSize
00243          *
00244          * x86_64 only uses relocations that contain the addend.
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; // This is set depending on the type of relocation
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: // The address is computed when the GOT is built
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: // The necessary value is set during storage allocation
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: // Load the symbol offset from the GOT
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               // Consistency error; we should never try to process one of these
00346               // ourselves.
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      * Special Case 1
00376      *
00377      * When linking code into stripped binaries, some linked functions will not
00378      * work correctly because they rely on some state being initialized or
00379      * updated in the original binary.
00380      *
00381      * For example, the libc function atexit internally keeps a list of
00382      * functions to call after the main function returns. When main returns,
00383      * this list is processed by libc finalization code. 
00384      * 
00385      * When the original binary is stripped, there is a disconnect between the
00386      * atexit function in the linked code and the original atexit function.
00387      * Consequently, any functionality that relies on atexit will not work
00388      * (i.e. destructors for global C++ objects).
00389      *
00390      * The initial release of the binary rewriter for static binaries doesn't
00391      * provide a solution to this problem. Therefore, a warning needs to be
00392      * generated to alert the user to this outstanding problem.
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 /* The TLS implementation on x86 is Variant 2 */
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> &regionAllocs,
00432         Region *dataTLS, Region *bssTLS) 
00433 {
00434     tlsCleanupVariant2(regionAllocs, dataTLS, bssTLS);
00435 }
00436 
00437 void emitElfStatic::getExcludedSymbolNames(set<string> &symNames) {
00438     /*
00439      * It appears that some .o's have a reference to _GLOBAL_OFFSET_TABLE_
00440      * This symbol is an indication to the linker that a GOT should be 
00441      * created, it isn't a symbol that should be resolved. 
00442      *
00443      * Consequently, a GOT shouldn't always be created when linking 
00444      * the .o's into the target. A GOT is built when certain relocations
00445      * exist that require a GOT.
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     // According to the ELF abi, entries 0, 1, 2 are reserved in a GOT on x86
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     // For each GOT symbol, allocate an entry and copy the value of the
00530     // symbol into the table, additionally store the offset in the GOT
00531     // back into the map
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  * .ctors and .dtors section handling
00548  * 
00549  * .ctors/.dtors sections are not defined by the ELF standard, LSB defines them.
00550  * This is why this implementation is specific to Linux and x86.
00551  *
00552  * Layout of .ctors and .dtors sections on Linux x86
00553  *
00554  * Executable .ctors/.dtors format (size in bytes = n)
00555  *
00556  *  byte 0..3    byte 4..7     byte 8..11        byte n-4..n-1
00557  * 0xffffffff <func. ptr 1> <func. ptr 2> ...  0x00000000
00558  *
00559  * Relocatable file .ctors/.dtors format (size in bytes = n)
00560  *
00561  *   byte 0..3         byte n-4..n-1
00562  * <func. ptr 1> ... <last func. ptr>
00563  *
00564  * The layout is the same on Linux x86_64 except each entry is 8 bytes
00565  * instead of 4. So the header and trailler are the same, but extended to
00566  * 8 bytes.
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      * .ctors sections are processed in reverse order on Linux x86. New .ctors
00586      * sections need to be placed before the original .ctors section
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         // If the map already contains this Region, this is a logic error
00598         if( !result.second ) {
00599             return ~0UL;
00600         }
00601 
00602         retOffset += (*reg_it)->getDiskSize();
00603     }
00604 
00605     if( lmap.originalCtorRegion != NULL ) {
00606         // Account for original .ctors section (minus the header and trailer)
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     /* Give the new Region a header and trailer */
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         /* Determine where the original .ctors section should be placed */
00642         Offset originalOffset = lmap.ctorRegionOffset + lmap.ctorSize - 
00643             trailerSize - (lmap.originalCtorRegion->getDiskSize() - headerSize - trailerSize);
00644 
00645         /* Copy the original .ctors section w/o the header and trailer */
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      * .dtors sections are processed in forward order on Linux x86. So new
00661      * .dtors sections need to be placed after the original .dtors section
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         // Account for the original .dtors section (minus the header and trailer)
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         // If the map already contains this Region, this is a logic error
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     /* Give the new Region a header and trailer */
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         /* Determine where the original .dtors section should be placed */
00716         Offset originalOffset = lmap.dtorRegionOffset + headerSize;
00717 
00718         /* Copy the original .dtors section w/o header and trailer */
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    // Size 0
00733    return lmap.stubRegionOffset;
00734 }
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1