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