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