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 //===----------------------------------------------------------------------===//
RelocationFactory()25 RelocationFactory::RelocationFactory()
26     : GCFactory<Relocation, MCLD_RELOCATIONS_PER_INPUT>(), m_pConfig(NULL) {
27 }
28 
setConfig(const LinkerConfig & pConfig)29 void RelocationFactory::setConfig(const LinkerConfig& pConfig) {
30   m_pConfig = &pConfig;
31 }
32 
produce(RelocationFactory::Type pType,FragmentRef & pFragRef,Address pAddend)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 
produceEmptyEntry()77 Relocation* RelocationFactory::produceEmptyEntry() {
78   Relocation* result = allocate();
79   new (result) Relocation(0, 0, 0, 0);
80   return result;
81 }
82 
destroy(Relocation * pRelocation)83 void RelocationFactory::destroy(Relocation* pRelocation) {
84   /** GCFactory will recycle the relocation **/
85 }
86 
87 }  // namespace mcld
88