Home | History | Annotate | Download | only in LD
      1 //===- RelocationFactory.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 #include "mcld/LD/RelocationFactory.h"
     10 
     11 #include "mcld/LinkerConfig.h"
     12 #include "mcld/Support/MsgHandling.h"
     13 #include "mcld/Target/TargetLDBackend.h"
     14 
     15 #include <llvm/Support/Host.h>
     16 
     17 #include <cassert>
     18 #include <cstring>
     19 
     20 namespace mcld {
     21 
     22 //===----------------------------------------------------------------------===//
     23 // RelocationFactory
     24 //===----------------------------------------------------------------------===//
     25 RelocationFactory::RelocationFactory()
     26     : GCFactory<Relocation, MCLD_RELOCATIONS_PER_INPUT>(), m_pConfig(NULL) {
     27 }
     28 
     29 void RelocationFactory::setConfig(const LinkerConfig& pConfig) {
     30   m_pConfig = &pConfig;
     31 }
     32 
     33 Relocation* RelocationFactory::produce(RelocationFactory::Type pType,
     34                                        FragmentRef& pFragRef,
     35                                        Address pAddend) {
     36   if (m_pConfig == NULL) {
     37     fatal(diag::reloc_factory_has_not_config);
     38     return NULL;
     39   }
     40 
     41   // target_data is the place where the relocation applys to.
     42   // Use TargetDataFactory to generate temporary data, and copy the
     43   // content of the fragment into this data.
     44   DWord target_data = 0;
     45 
     46   // byte swapping if the host and target have different endian
     47   if (llvm::sys::IsLittleEndianHost != m_pConfig->targets().isLittleEndian()) {
     48     uint32_t tmp_data;
     49 
     50     switch (m_pConfig->targets().bitclass()) {
     51       case 32: {
     52         pFragRef.memcpy(&tmp_data, 4);
     53         tmp_data = mcld::bswap32(tmp_data);
     54         target_data = tmp_data;
     55         break;
     56       }
     57       case 64: {
     58         pFragRef.memcpy(&target_data, 8);
     59         target_data = mcld::bswap64(target_data);
     60         break;
     61       }
     62       default: {
     63         fatal(diag::unsupported_bitclass) << m_pConfig->targets().triple().str()
     64                                           << m_pConfig->targets().bitclass();
     65         return NULL;
     66       }
     67     }  // end of switch
     68   } else {
     69     pFragRef.memcpy(&target_data, (m_pConfig->targets().bitclass() / 8));
     70   }
     71 
     72   Relocation* result = allocate();
     73   new (result) Relocation(pType, &pFragRef, pAddend, target_data);
     74   return result;
     75 }
     76 
     77 Relocation* RelocationFactory::produceEmptyEntry() {
     78   Relocation* result = allocate();
     79   new (result) Relocation(0, 0, 0, 0);
     80   return result;
     81 }
     82 
     83 void RelocationFactory::destroy(Relocation* pRelocation) {
     84   /** GCFactory will recycle the relocation **/
     85 }
     86 
     87 }  // namespace mcld
     88