Home | History | Annotate | Download | only in Fragment
      1 //===- FragmentLinker.cpp -------------------------------------------------===//
      2 //
      3 //                     The MCLinker Project
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file implements the FragmentLinker class
     11 //
     12 //===----------------------------------------------------------------------===//
     13 #include <mcld/Fragment/FragmentLinker.h>
     14 
     15 #include <llvm/Support/Host.h>
     16 #include <llvm/Support/raw_ostream.h>
     17 #include <llvm/Support/Casting.h>
     18 
     19 #include <mcld/LinkerConfig.h>
     20 #include <mcld/Module.h>
     21 #include <mcld/MC/MCLDInput.h>
     22 #include <mcld/LD/BranchIslandFactory.h>
     23 #include <mcld/LD/Resolver.h>
     24 #include <mcld/LD/LDContext.h>
     25 #include <mcld/LD/RelocationFactory.h>
     26 #include <mcld/LD/RelocData.h>
     27 #include <mcld/LD/SectionRules.h>
     28 #include <mcld/Support/MemoryRegion.h>
     29 #include <mcld/Support/MemoryArea.h>
     30 #include <mcld/Support/FileHandle.h>
     31 #include <mcld/Support/MsgHandling.h>
     32 #include <mcld/Target/TargetLDBackend.h>
     33 #include <mcld/Fragment/Relocation.h>
     34 
     35 using namespace mcld;
     36 
     37 //===----------------------------------------------------------------------===//
     38 // FragmentLinker
     39 //===----------------------------------------------------------------------===//
     40 /// Constructor
     41 FragmentLinker::FragmentLinker(const LinkerConfig& pConfig,
     42                                Module& pModule,
     43                                TargetLDBackend& pBackend)
     44 
     45   : m_Config(pConfig),
     46     m_Module(pModule),
     47     m_Backend(pBackend) {
     48 }
     49 
     50 /// Destructor
     51 FragmentLinker::~FragmentLinker()
     52 {
     53 }
     54 
     55 bool FragmentLinker::finalizeSymbols()
     56 {
     57   Module::sym_iterator symbol, symEnd = m_Module.sym_end();
     58   for (symbol = m_Module.sym_begin(); symbol != symEnd; ++symbol) {
     59 
     60     if ((*symbol)->resolveInfo()->isAbsolute() ||
     61         (*symbol)->resolveInfo()->type() == ResolveInfo::File) {
     62       // absolute symbols or symbols with function type should have
     63       // zero value
     64       (*symbol)->setValue(0x0);
     65       continue;
     66     }
     67 
     68     if ((*symbol)->resolveInfo()->type() == ResolveInfo::ThreadLocal) {
     69       m_Backend.finalizeTLSSymbol(**symbol);
     70       continue;
     71     }
     72 
     73     if ((*symbol)->hasFragRef()) {
     74       // set the virtual address of the symbol. If the output file is
     75       // relocatable object file, the section's virtual address becomes zero.
     76       // And the symbol's value become section relative offset.
     77       uint64_t value = (*symbol)->fragRef()->getOutputOffset();
     78       assert(NULL != (*symbol)->fragRef()->frag());
     79       uint64_t addr = (*symbol)->fragRef()->frag()->getParent()->getSection().addr();
     80       (*symbol)->setValue(value + addr);
     81       continue;
     82     }
     83   }
     84 
     85   return true;
     86 }
     87 
     88 //===----------------------------------------------------------------------===//
     89 // Relocation Operations
     90 //===----------------------------------------------------------------------===//
     91 bool FragmentLinker::applyRelocations()
     92 {
     93   // when producing relocatables, no need to apply relocation
     94   if (LinkerConfig::Object == m_Config.codeGenType())
     95     return true;
     96 
     97   // apply all relocations of all inputs
     98   Module::obj_iterator input, inEnd = m_Module.obj_end();
     99   for (input = m_Module.obj_begin(); input != inEnd; ++input) {
    100     LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
    101     for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
    102       // bypass the reloc section if
    103       // 1. its section kind is changed to Ignore. (The target section is a
    104       // discarded group section.)
    105       // 2. it has no reloc data. (All symbols in the input relocs are in the
    106       // discarded group sections)
    107       if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData())
    108         continue;
    109       RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end();
    110       for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
    111         Relocation* relocation = llvm::cast<Relocation>(reloc);
    112         relocation->apply(*m_Backend.getRelocator());
    113       } // for all relocations
    114     } // for all relocation section
    115   } // for all inputs
    116 
    117   // apply relocations created by relaxation
    118   BranchIslandFactory* br_factory = m_Backend.getBRIslandFactory();
    119   BranchIslandFactory::iterator facIter, facEnd = br_factory->end();
    120   for (facIter = br_factory->begin(); facIter != facEnd; ++facIter) {
    121     BranchIsland& island = *facIter;
    122     BranchIsland::reloc_iterator iter, iterEnd = island.reloc_end();
    123     for (iter = island.reloc_begin(); iter != iterEnd; ++iter)
    124       (*iter)->apply(*m_Backend.getRelocator());
    125   }
    126   return true;
    127 }
    128 
    129 
    130 void FragmentLinker::syncRelocationResult(MemoryArea& pOutput)
    131 {
    132   if (LinkerConfig::Object != m_Config.codeGenType())
    133     normalSyncRelocationResult(pOutput);
    134   else
    135     partialSyncRelocationResult(pOutput);
    136   return;
    137 }
    138 
    139 void FragmentLinker::normalSyncRelocationResult(MemoryArea& pOutput)
    140 {
    141   MemoryRegion* region = pOutput.request(0, pOutput.handler()->size());
    142 
    143   uint8_t* data = region->getBuffer();
    144 
    145   // sync all relocations of all inputs
    146   Module::obj_iterator input, inEnd = m_Module.obj_end();
    147   for (input = m_Module.obj_begin(); input != inEnd; ++input) {
    148     LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
    149     for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
    150       // bypass the reloc section if
    151       // 1. its section kind is changed to Ignore. (The target section is a
    152       // discarded group section.)
    153       // 2. it has no reloc data. (All symbols in the input relocs are in the
    154       // discarded group sections)
    155       if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData())
    156         continue;
    157       RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end();
    158       for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
    159         Relocation* relocation = llvm::cast<Relocation>(reloc);
    160 
    161         // bypass the relocation with NONE type. This is to avoid overwrite the
    162         // target result by NONE type relocation if there is a place which has
    163         // two relocations to apply to, and one of it is NONE type. The result
    164         // we want is the value of the other relocation result. For example,
    165         // in .exidx, there are usually an R_ARM_NONE and R_ARM_PREL31 apply to
    166         // the same place
    167         if (0x0 == relocation->type())
    168           continue;
    169         writeRelocationResult(*relocation, data);
    170       } // for all relocations
    171     } // for all relocation section
    172   } // for all inputs
    173 
    174   // sync relocations created by relaxation
    175   BranchIslandFactory* br_factory = m_Backend.getBRIslandFactory();
    176   BranchIslandFactory::iterator facIter, facEnd = br_factory->end();
    177   for (facIter = br_factory->begin(); facIter != facEnd; ++facIter) {
    178     BranchIsland& island = *facIter;
    179     BranchIsland::reloc_iterator iter, iterEnd = island.reloc_end();
    180     for (iter = island.reloc_begin(); iter != iterEnd; ++iter) {
    181       Relocation* reloc = *iter;
    182       writeRelocationResult(*reloc, data);
    183     }
    184   }
    185 
    186   pOutput.clear();
    187 }
    188 
    189 void FragmentLinker::partialSyncRelocationResult(MemoryArea& pOutput)
    190 {
    191   MemoryRegion* region = pOutput.request(0, pOutput.handler()->size());
    192 
    193   uint8_t* data = region->getBuffer();
    194 
    195   // traverse outputs' LDSection to get RelocData
    196   Module::iterator sectIter, sectEnd = m_Module.end();
    197   for (sectIter = m_Module.begin(); sectIter != sectEnd; ++sectIter) {
    198     if (LDFileFormat::Relocation != (*sectIter)->kind())
    199       continue;
    200 
    201     RelocData* reloc_data = (*sectIter)->getRelocData();
    202     RelocData::iterator relocIter, relocEnd = reloc_data->end();
    203     for (relocIter = reloc_data->begin(); relocIter != relocEnd; ++relocIter) {
    204       Relocation* reloc = llvm::cast<Relocation>(relocIter);
    205 
    206       // bypass the relocation with NONE type. This is to avoid overwrite the
    207       // target result by NONE type relocation if there is a place which has
    208       // two relocations to apply to, and one of it is NONE type. The result
    209       // we want is the value of the other relocation result. For example,
    210       // in .exidx, there are usually an R_ARM_NONE and R_ARM_PREL31 apply to
    211       // the same place
    212       if (0x0 == reloc->type())
    213         continue;
    214       writeRelocationResult(*reloc, data);
    215     }
    216   }
    217 
    218   pOutput.clear();
    219 }
    220 
    221 void FragmentLinker::writeRelocationResult(Relocation& pReloc, uint8_t* pOutput)
    222 {
    223   // get output file offset
    224   size_t out_offset =
    225                  pReloc.targetRef().frag()->getParent()->getSection().offset() +
    226                  pReloc.targetRef().getOutputOffset();
    227 
    228   uint8_t* target_addr = pOutput + out_offset;
    229   // byte swapping if target and host has different endian, and then write back
    230   if(llvm::sys::isLittleEndianHost() != m_Config.targets().isLittleEndian()) {
    231      uint64_t tmp_data = 0;
    232 
    233      switch(pReloc.size(*m_Backend.getRelocator())) {
    234        case 8u:
    235          std::memcpy(target_addr, &pReloc.target(), 1);
    236          break;
    237 
    238        case 16u:
    239          tmp_data = mcld::bswap16(pReloc.target());
    240          std::memcpy(target_addr, &tmp_data, 2);
    241          break;
    242 
    243        case 32u:
    244          tmp_data = mcld::bswap32(pReloc.target());
    245          std::memcpy(target_addr, &tmp_data, 4);
    246          break;
    247 
    248        case 64u:
    249          tmp_data = mcld::bswap64(pReloc.target());
    250          std::memcpy(target_addr, &tmp_data, 8);
    251          break;
    252 
    253        default:
    254          break;
    255     }
    256   }
    257   else
    258     std::memcpy(target_addr, &pReloc.target(),
    259                                       pReloc.size(*m_Backend.getRelocator())/8);
    260 }
    261 
    262