emitElfStatic.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  * XXX
00033  *
00034  * This class is unnecessary. However, at the time of writing, emitElf was
00035  * split into two different classes (one for 32-bit and 64-bit). Instead of
00036  * duplicating code, this class was created to share code between the
00037  * two emitElf classes.
00038  *
00039  * Once the emitElf classes are merged, this class can be merged with the new
00040  * emitElf class.
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 // Section names
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 /* Used by architecture specific functions, but not architecture specific */
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  * NOTE:
00088  * Most of these functions take a reference to a StaticLinkError and a string
00089  * for error reporting purposes. These should prove useful in identifying the
00090  * cause of an error
00091  */
00092 
00093 /**
00094  * Statically links relocatable files into the specified Symtab object, 
00095  * as specified by state in the Symtab object
00096  *
00097  * target       relocatable files will be linked into this Symtab
00098  *
00099  * Returns a pointer to a block of data containing the results of the link
00100  * The caller is responsible for delete'ing this block of data
00101  */
00102 char *emitElfStatic::linkStatic(Symtab *target, 
00103         StaticLinkError &err, string &errMsg) 
00104 {
00105     /* 
00106      * Basic algorithm is:
00107      * - locate defined versions of symbols for undefined symbols in 
00108      *   either the target or relocatable code, produces a list
00109      *   of Symtab objects that contain the defined versions
00110      *
00111      * - Allocate space for all new code and data to be linked into 
00112      *   the target, populates a LinkMap with all allocation 
00113      *   information
00114      *
00115      * - Compute relocations and set their targets to these values
00116      */
00117 
00118     // Holds all information necessary to work with the block of data created by createLinkMap
00119     LinkMap lmap;
00120 
00121     rewrite_printf("START link map output\n");
00122     
00123     // Determine starting location of new Regions
00124     Offset globalOffset = 0;
00125     vector<Region *> newRegs;
00126     if( target->getAllNewRegions(newRegs) ) {
00127         // This is true, only if other regions have already been added
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     // Holds all necessary dependencies, as determined by resolveSymbols
00144     vector<Symtab *> relocatableObjects;
00145     if( !resolveSymbols(target, relocatableObjects, lmap, err, errMsg) ) {
00146         return NULL;
00147     }
00148 
00149     // Lays out all relocatable files into a single contiguous block of data
00150     if( !createLinkMap(target, relocatableObjects, globalOffset, lmap, err, errMsg) ) {
00151         return NULL;
00152     }
00153 
00154     // Copies the data from the relocatable files into the new block of data
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     // Print out the link map for debugging
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     // Now that all symbols are at their final locations, compute and apply relocations
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     // Restore the offset of the modified symbols
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     // Restore the symbols of the modified relocations
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  * Resolves undefined symbols in the specified Symtab object, usually due
00217  * to the addition of new Symbols to the Symtab object. The target Symtab
00218  * object must have a collection of Archives associated with it. These
00219  * Archives will be searched for the defined versions of the undefined 
00220  * symbols in the specified Symtab objects.
00221  *
00222  * target               the Symtab containing the undefined symbols
00223  * relocatableObjects   populated by this function, this collection specifies
00224  *                      all the Symtabs needed to ensure that the target has
00225  *                      no undefined Symbols once the link is performed
00226  */
00227 bool emitElfStatic::resolveSymbols(Symtab *target, 
00228         vector<Symtab *> &relocatableObjects,
00229         LinkMap &lmap,
00230         StaticLinkError &err, string &errMsg) 
00231 {
00232     // Collection of Symtabs that currently need their symbols resolved
00233     set<Symtab *> workSet;
00234 
00235     // Collection of Symtabs that have already had their symbols resolved
00236     // this is necessary to avoid errors related to circular dependencies
00237     set<Symtab *> linkedSet;
00238 
00239     set<string> excludeSymNames;
00240     getExcludedSymbolNames(excludeSymNames);
00241 
00242     // Establish list of libraries to search for symbols
00243     vector<Archive *> libraries;
00244     target->getLinkingResources(libraries);
00245 
00246     // Add all relocatable files explicitly referenced by new symbols, these
00247     // essentially fuel the symbol resolution process
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         // Take a relocatable file off the working set
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         // Build the map of symbols to their relocations
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> &region_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         // Iterate over all undefined symbols, attempting to resolve them
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             // Skip symbols that are don't cares
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             // First, attempt to search the target for the symbol
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                 // search loaded libraries and add any new reloctable files
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                 // Look through the possibleSymtabs for symbol hits
00337                 // Options are:
00338                 // 1) A lot of weak symbols; pick one
00339                 // 2) A lot of weak symbols and a strong symbol: pick strong
00340                 // 3) Multiple strong symbols: fail
00341                 // 4) ... no symbols. Also fail.
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                       // Problem: mismatch between the Archive table and Symtab
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              // We include UNKNOWN symbols in the find; unfortunately that's
00355              // not what we want here. Skip. 
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                          // Two strong symbols: bad
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                    // If it is a weak symbol, it isn't an error that the symbol wasn't resolved
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                    // Consistency check                                                                                            
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                    // Resolve all symbols for this new Symtab, if it hasn't already                                                
00403                    // been done                                                                                                    
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             // Store the found symbol with the related relocations
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             }   /* else
00430                  *
00431                  * Some libraries define a reference to a symbol and then never
00432                  * use it in order to ensure that the object that defines the
00433                  * symbol is linked. Therefore, it is not an error if a symbol doesn't
00434                  * have a relocation.
00435                  */
00436         }
00437 
00438         curObjFilePtr = workSet.begin();
00439     }
00440     
00441     return true;
00442 }
00443 
00444 /**
00445  * Given a collection of Symtab objects, combines the code, data, bss and
00446  * other miscellaneous Regions into groups and places them in a new block
00447  * of data.
00448  * 
00449  * Allocates COMMON symbols in the collection of Symtab objects
00450  * as bss
00451  *
00452  * Creates a new TLS initialization image, combining the target image
00453  * and the image that exists in the collection of Symtab objects
00454  *
00455  * Creates a GOT used for indirect memory accesses that is required by some
00456  * relocations
00457  *
00458  * Creates a new global constructor and/or destructor table if necessary,
00459  * combining tables from the target and collection of Symtab objects
00460  *
00461  * target               New code/data/etc. will be linked into this Symtab
00462  * relocatableObjects   The new code/data/etc.
00463  * globalOffset         The location of the new block of data in the target
00464  * lmap                 The LinkMap to be populated by this function
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     // Used to create a new COMMON block
00475     multimap<Offset, Symbol *> commonAlignments;
00476     Offset commonRegionAlign = 0;
00477 
00478     // Collect all Regions that should be allocated in the new data block
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                             // Determine alignment of combined region
00498                             if( (*reg_it)->getMemAlignment() > lmap.tlsRegionAlign ) {
00499                                 lmap.tlsRegionAlign = (*reg_it)->getMemAlignment();
00500                             }
00501                             break;
00502                         default:
00503                             // ignore any other regions
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                             // Determine alignment of combined region
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                             // Determine alignment of combined region
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                             // Determine alignment of combined region
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                             // Determine alignment of combined region
00548                             if( (*reg_it)->getMemAlignment() > lmap.codeRegionAlign ) {
00549                                 lmap.codeRegionAlign = (*reg_it)->getMemAlignment();
00550                             }
00551                             break;
00552                         default:
00553                             // skip other regions
00554                             continue;
00555                     }
00556                 }
00557 
00558                 // Find symbols that need to be put in the GOT
00559 
00560 #if defined(arch_power) && defined(arch_64bit)
00561         // If statically linked binary, we need to put all the entries in region toc to GOT
00562         if(target->isStaticBinary() && (regionName.compare(".toc") == 0)) {
00563                    // For every symbol in toc
00564                    // Get data of the region and split it into symbols
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                       // If symbol has relocation, add that 
00569                       bool relExist = false;
00570                       vector<relocationEntry> &region_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                          // else create a new symbol 
00583                          // Offset and name is all we care - offset should be value of the symbol
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> &region_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             } // isLoadable
00611            
00612         } //for regions
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                 // Note: the assumption is made that a Symbol cannot 
00619                 // be both TLS and COMMON
00620                 if( (*sym_it)->isCommonStorage() ) {
00621                     // For a symbol in common storage, the offset/value is the alignment
00622                     commonAlignments.insert(make_pair((*sym_it)->getOffset(), *sym_it));
00623 
00624                     // The alignment of a COMMON Region is the maximum alignment
00625                     // needed by one of its symbols
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     // Determine how all the Regions in the relocatable objects will be 
00637     // placed in the rewritten target
00638     Offset currentOffset = 0;
00639 
00640     // Allocate code regions 
00641 
00642     // Since this is the first new Region, the actual globalOffset should be 
00643     // the passed globalOffset plus the padding for this Region
00644     
00645     Offset maxAlign = getGOTAlign(lmap);
00646     if(maxAlign < lmap.codeRegionAlign) maxAlign = lmap.codeRegionAlign;
00647 
00648     globalOffset += computePadding(globalOffset + currentOffset,
00649             maxAlign);
00650 
00651     // Handle PLT entries generated by GNU indirect functions
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     // Allocate space for a GOT Region, if necessary
00673     Offset gotLayoutOffset = 0;
00674     lmap.gotSize = getGOTSize(target, lmap, gotLayoutOffset);
00675     if( lmap.gotSize > 0 ) {
00676       // We may copy the original GOT over; in this case, we have to be sure we skip it
00677       // when we lay out new GOT entries. That's the gotLayoutOffset value. 
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     // Calculate the space necessary for stub code; normally this will be 0,
00687     // but we may need to add code later on. Make room for it now. 
00688     // Note we use code region alignment here. 
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     // Allocate data regions 
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      * Find current TLS Regions in target, also check for multiple TLS Regions
00729      * of the same type => knowing how to construct the TLS image would be
00730      * undefined for multiple TLS Regions of the same type
00731      *
00732      * Find current constructor Regions and destructor Regions.
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     // Allocate the new TLS region, if necessary
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          *  The size of this Region is counted twice: once when collecting the
00793          *  original TLS Regions and once when laying out the image. This is
00794          *  necessary to maintain consistency with the case where there are no
00795          *  new TLS regions in the relocatable objects but existing TLS symbols
00796          *  are used.
00797          */
00798         if( dataTLS != NULL ) {
00799             lmap.tlsSize -= dataTLS->getMemSize();
00800         }
00801 
00802         lmap.tlsSize += currentOffset - lmap.tlsRegionOffset;
00803 
00804         // Adjust offsets for all existing TLS symbols, as their offset
00805         // in the TLS block could have changed
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         // Adjust offsets for all existing TLS symbols, as the offsets required
00835         // by relocation processing are TLS variant dependent
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         // The size of the original TLS image is no longer needed
00851         lmap.tlsSize = 0;
00852     }
00853 
00854 #endif
00855     // Allocate space for a new constructor region, if necessary
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     // Allocate space for a new destructor region, if necessary
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     /* Combine all COMMON symbols into a single block */
00884     if( commonAlignments.size() > 0 ) {
00885         // The alignment of the COMMON Region could be the alignment 
00886         // for the bss Region
00887         if( commonRegionAlign > lmap.bssRegionAlign ) {
00888             lmap.bssRegionAlign = commonRegionAlign;
00889         }
00890 
00891         // The following approach to laying out the COMMON symbols is greedy and
00892         // suboptimal (in terms of space in the target), but it's quick...
00893         Offset commonOffset = currentOffset;
00894 
00895         // Make sure the COMMON Region's alignment is satisfied
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             // Update symbol with place in new linked data
00907             align_it->second->setOffset(globalOffset + commonOffset);
00908             commonOffset += align_it->second->getSize();
00909         }
00910 
00911         // Update the size of COMMON storage
00912         if( commonAlignments.size() > 0 ) {
00913             // A COMMON region is not really complete
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     // Allocate bss regions
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     // Update all relevant symbols with their offsets in the new target
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 // If region has relocations, set offset to got 
00954             vector<relocationEntry> region_rels = result->first->getRelocations();
00955             if(region_rels.size() > 0) {
00956 //          printf(" region %s has relocations %d \n", result->first->getRegionName().c_str(), region_rels.size()); 
00957 /*
00958                             result = lmap.regionAllocs.find((*sym_it)->getRegion());
00959                             regionOffset = result->second.second;
00960 */
00961             }
00962             
00963         
00964                         (*sym_it)->setOffset(symbolOffset);
00965                     }
00966                 }
00967             }
00968         }
00969     }
00970 
00971     /* ASSUMPTION
00972      * At this point, the layout of the new regions is fixed, and
00973      * addresses of all symbols are known (excluding Constructor/Destructor Regions)
00974      */
00975 
00976     // Allocate storage space
00977     lmap.allocatedData = new char[currentOffset];
00978     lmap.allocatedSize = currentOffset;
00979 
00980     // Copy the Regions from the relocatable objects into the new storage space
00981     copyRegions(lmap);
00982 
00983     return true;
00984 }
00985 
00986 /**
00987  * Lays out the specified regions, storing the layout info in the 
00988  * passed map.
00989  *
00990  * regions              A collection of Regions to layout
00991  * regionAllocs         A map of Regions to their layout information
00992  * currentOffset        The starting offset for the passed Regions in
00993  *                      the new storage space
00994  * globalOffset         The location of the new storage space in the
00995  *                      target (used for padding calculation)
00996  */
00997 Offset emitElfStatic::layoutRegions(deque<Region *> &regions, 
00998                                     map<Region *, LinkMap::AllocPair> &regionAllocs,
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         // Skip empty Regions
01006         if( (*copyReg_it)->getMemSize() == 0 ) continue;
01007 
01008         // Make sure the Region is aligned correctly in the new aggregate Region
01009         Offset padding = computePadding(globalOffset + retOffset, (*copyReg_it)->getMemAlignment());
01010         retOffset += padding;
01011 
01012         // Set up mapping for a new Region in the specified storage space
01013         pair<map<Region *, LinkMap::AllocPair>::iterator, bool> result;
01014         result = regionAllocs.insert(make_pair(*copyReg_it, make_pair(padding, retOffset)));
01015 
01016         // If the map already contains this Region, this is a logic error
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  * Adds new combined Regions to the target at the specified globalOffset
01030  *
01031  * target       The Symtab object to which the new Regions will be added
01032  * globalOffset The offset of the first new Region in the target
01033  * lmap         Contains all the information about the LinkMap
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  * Copys the new Regions, as indicated by the LinkMap, into the
01132  * allocated storage space
01133  *
01134  * lmap         Contains all the information necessary to perform the copy
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         // Copy in the Region data
01146         char *rawRegionData = reinterpret_cast<char *>(depRegion->getPtrToRawData());
01147 
01148         if( !depRegion->isBSS() ) {
01149             memcpy(&targetData[regionOffset], rawRegionData, depRegion->getMemSize());
01150         }
01151 
01152         // Set the padded space to a meaningful value
01153         memset(&targetData[regionOffset - padding], getPaddingValue(depRegion->getRegionType()), padding);
01154     }
01155 }
01156 
01157 /**
01158  * Computes the padding necessary to satisfy the specified alignment
01159  *
01160  * candidateOffset      A possible offset for an item
01161  * alignment            The alignment for an item
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  * Given a collection of newly allocated regions in the specified storage space, 
01174  * computes relocations and places the values at the location specified by the
01175  * relocation entry (stored with the Regions)
01176  *
01177  * target               The Symtab object being rewritten
01178  * relocatableObjects   A list of relocatable files being linked into target
01179  * globalOffset         The location of the new storage space in target
01180  * lmap                 Contains all the information necessary to apply relocations
01181  */
01182 bool emitElfStatic::applyRelocations(Symtab *target, vector<Symtab *> &relocatableObjects,
01183                      Offset globalOffset, LinkMap &lmap,
01184                      StaticLinkError &err, string &errMsg) 
01185 {
01186     // Iterate over all relocations in all relocatable files
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         // Relocations are stored with the Region to which they will be applied
01193         // As an ELF example, .rel.text relocations are stored with the Region .text
01194         vector<Region *>::iterator region_it;
01195         for(region_it = allRegions.begin(); region_it != allRegions.end(); ++region_it) {
01196            // Only compute relocations for the new Regions
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                     // Compute destination of relocation
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            if((*region_it)->getRegionName().compare(".toc") == 0){
01240             Offset regOffset = lmap.gotRegionOffset; 
01241                         dest = regOffset + rel_it->rel_addr();
01242                         relOffset = globalOffset + dest;
01243 
01244             if((*rel_it).name().compare("__SYMTABAPI_CTOR_LIST__") == 0) 
01245             {
01246                     printf("\n\tComputing relocations to apply to region: %s @ 0x%lx reloffset %d 0x%lx dest %d 0x%lx  \n\n",
01247                         (*region_it)->getRegionName().c_str(), regOffset, relOffset,relOffset, dest,dest);
01248                     if( !archSpecificRelocation(target, *depObj_it, targetData, *rel_it, dest, 
01249                                 relOffset, globalOffset, lmap, errMsg) ) 
01250                     {
01251                         err = Relocation_Computation_Failure;
01252                         errMsg = "Failed to compute relocation: " + errMsg;
01253                         return false;
01254                     }
01255             }
01256         
01257            }  
01258 */
01259                 }
01260             }
01261         }
01262     }
01263 
01264     rewrite_printf("\n*** Computing relocations added to target.\n\n");
01265 
01266     // Compute relocations added to target 
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         // Don't process relocations for other sections; those get handled by the
01281         // stub code.
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  * A string representation of the StaticLinkError returned by
01299  * other functions
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  * Indicates if a new TLS initialization image has been created
01314  */
01315 bool emitElfStatic::hasRewrittenTLS() const {
01316     return hasRewrittenTLS_;
01317 }
01318 
01319 /** The following functions are all somewhat architecture-specific */
01320 
01321 /* TLS Info
01322  *
01323  * TLS handling is pseudo-architecture dependent. The implementation of the TLS
01324  * functions depend on the implementation of TLS on a specific architecture.
01325  *
01326  * The following material is documented in more detail in the 
01327  * "ELF Handling For TLS" white paper. According to this paper, their are 
01328  * two variants w.r.t. creating a TLS initialization image.
01329  *
01330  * ======================
01331  *
01332  * The first is:
01333  *
01334  *            beginning of image
01335  *            |
01336  *            V                              high address
01337  * +----+-----+----------+---------+---------+
01338  * |    | TCB | image 1  | image 2 | image 3 |
01339  * +----+---- +----------+---------+---------+
01340  *
01341  * where TCB = thread control block, and each image is the
01342  * TLS initialization image for an object (in this context an executable or 
01343  * shared library).
01344  *
01345  * ========================
01346  *
01347  * The second is:
01348  * 
01349  * beginning of image
01350  * | 
01351  * V                                        high address
01352  * +---------+----------+---------+---------+
01353  * | image 3 | image 2  | image 1 |  TCB    |
01354  * +---------+----------+---------+---------+
01355  *
01356  * An image is:
01357  *
01358  * +--------+--------+
01359  * | DATA   |  BSS   |
01360  * +--------+--------+
01361  *
01362  * New TLS data and bss is added to the original initialization image as follows:
01363  *
01364  * +----------+------------------+-------------+------------+-----+
01365  * | NEW DATA | EXPANDED NEW BSS | TARGET DATA | TARGET BSS | TCB |
01366  * +----------+------------------+-------------+------------+-----+
01367  *
01368  * It is important to note that the TARGET DATA and TARGET BSS blocks are not moved.
01369  * This ensures that the modifications to the TLS image are safe.
01370  *
01371  * ==========================
01372  * 
01373  * These are the two variants one would see when working with ELF files. So, an
01374  * architecture either uses variant 1 or 2.
01375  *
01376  */
01377 
01378 /* See architecture specific functions that call these for descriptions of function interface */
01379 
01380 Offset emitElfStatic::tlsLayoutVariant1(Offset globalOffset, Region *dataTLS, Region *bssTLS, LinkMap &lmap)
01381 {
01382     // The original init. image needs to remain in the image 1 slot because
01383     // the TLS data references are relative to that position
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     // Create the image, note new BSS regions are expanded
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     // This is necessary so the offsets of existing TLS symbols can be updated
01401     // in a uniform, architecture independent way
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     // Update the symbols with their offsets relative to the TCB address
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         // It is a programming error if the region for the symbol
01417         // was not passed to this function
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     // The original init. image needs to remain in the image 1 slot because
01438     // the TLS data references are relative to that position
01439     unsigned long tlsBssSize = 0;
01440     if( dataTLS != NULL ) lmap.tlsRegions.push_back(dataTLS);
01441     if( bssTLS != NULL ) tlsBssSize = bssTLS->getMemSize();
01442 
01443     // Create the image, note new BSS regions are expanded
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     // This is necessary so the offsets of existing TLS symbols can be updated
01450     // in a uniform, architecture independent way
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     // Update the symbols with their offsets relative to the TCB address
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         // It is a programming error if the region for the symbol
01466         // was not passed to this function
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 // Note: Variant 1 does not require any modifications, so a separate
01484 // function is not necessary
01485 Offset emitElfStatic::tlsAdjustVariant2(Offset curOffset, Offset tlsSize) {
01486     // For Variant 2, offsets relative to the TCB need to be negative
01487     Offset retOffset = curOffset;
01488     retOffset -= tlsSize;
01489     return retOffset;
01490 }
01491 
01492 void emitElfStatic::tlsCleanupVariant1(map<Region *, LinkMap::AllocPair> &regionAllocs,
01493         Region *, Region *bssTLS) 
01494 {
01495     // Existing BSS TLS region is not copied to the new target data
01496     if( bssTLS != NULL ) regionAllocs.erase(bssTLS);
01497 }
01498 
01499 void emitElfStatic::tlsCleanupVariant2(map<Region *, LinkMap::AllocPair> &regionAllocs,
01500         Region *, Region *bssTLS) 
01501 {
01502     // Existing BSS TLS region is not copied to the new target data
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  * Sort the sections array so that sections with a non-zero
01516  * memory offset come first (and are sorted in increasing
01517  * order of offset). Preserves the ordering of zero-offset
01518  * sections.
01519  *
01520  * If no section has a non-zero offset, the return value will
01521  * be an address in the virtual memory space big enough to
01522  * hold all the loadable sections. Otherwise it will be the
01523  * address of the first non-zero offset section.
01524  *
01525  * NB if we need to create a new segment to hold these sections,
01526  * it needs to be clear up to the next page boundary to avoid
01527  * potentially clobbering other loadable segments.
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         // find a `hole' of appropriate size
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 // There are also some known variables that point to the heap 
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, &regData[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     // Currently, only verified on x86 and x86_64 -- this may work on other architectures
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     // Used to update a Region
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                 // Do nothing
01637                 break;
01638         }
01639     }else{
01640         switch(rel.getRelType()) {
01641             case R_386_RELATIVE:
01642                 // On x86, addends are stored in their target location
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                 // Do nothing
01662                 break;
01663         }
01664     }
01665 
01666     // XXX The GOT also holds a pointer to the DYNAMIC segment -- this is currently not
01667     // updated. However, this appears to be unneeded for regular shared libraries.
01668     
01669     // From the SYS V ABI x86 supplement
01670     // "The table's entry zero is reserved to hold the address of the dynamic structure,
01671     // referenced with the symbol _DYNAMIC. This allows a program, such as the
01672     // dynamic linker, to find its own dynamic structure without having yet processed
01673     // its relocation entries. This is especially important for the dynamic linker, because
01674     // it must initialize itself without relying on other programs to relocate its memory
01675     // image."
01676     
01677     // In order to implement this, would have determine the final address of a new .dynamic
01678     // section before outputting the patched GOT data -- this will require some refactoring.
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 *> &regions, 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     // We'd like the TOC to be GOTbase + 0x8000, so long as that can address the end of the current
01703     // region. 
01704     if ((currentTOC + 0x7ff0) < end) {
01705       // Crud...
01706       // OTOH, we can't reference anything outside the current GOT, so just rebase it
01707       currentTOC = current + 0x8000;
01708     }
01709     // Recheck
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   // For each Symtab
01723   //   For each indirect symbol
01724   //     Allocate a PLT entry for it
01725   //     Add it to entries
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   // Existence is what we care about at this point
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, // jmp *<offset>, %rip
01760              0x68, 0x00, 0x00, 0x00, 0x00, // pushq $0x0
01761              0xe9, 0x00, 0x00, 0x00, 0x00}; // jmpq
01762   unsigned pltEntrySize = 16;
01763   unsigned gotOffset = 2;
01764   // Size of the first instruction for x86 platforms so the math works out right
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   // TODO: implementation
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     // Grab a GOT location
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 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1