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