| //===- RelocationFactory.cpp ----------------------------------------------===// |
| // |
| // The MCLinker Project |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| #include "mcld/LD/RelocationFactory.h" |
| |
| #include "mcld/LinkerConfig.h" |
| #include "mcld/Support/MsgHandling.h" |
| #include "mcld/Target/TargetLDBackend.h" |
| |
| #include <llvm/Support/Host.h> |
| |
| #include <cassert> |
| #include <cstring> |
| |
| namespace mcld { |
| |
| //===----------------------------------------------------------------------===// |
| // RelocationFactory |
| //===----------------------------------------------------------------------===// |
| RelocationFactory::RelocationFactory() |
| : GCFactory<Relocation, MCLD_RELOCATIONS_PER_INPUT>(), m_pConfig(NULL) { |
| } |
| |
| void RelocationFactory::setConfig(const LinkerConfig& pConfig) { |
| m_pConfig = &pConfig; |
| } |
| |
| Relocation* RelocationFactory::produce(RelocationFactory::Type pType, |
| FragmentRef& pFragRef, |
| Address pAddend) { |
| if (m_pConfig == NULL) { |
| fatal(diag::reloc_factory_has_not_config); |
| return NULL; |
| } |
| |
| // target_data is the place where the relocation applys to. |
| // Use TargetDataFactory to generate temporary data, and copy the |
| // content of the fragment into this data. |
| DWord target_data = 0; |
| |
| // byte swapping if the host and target have different endian |
| if (llvm::sys::IsLittleEndianHost != m_pConfig->targets().isLittleEndian()) { |
| uint32_t tmp_data; |
| |
| switch (m_pConfig->targets().bitclass()) { |
| case 32: { |
| pFragRef.memcpy(&tmp_data, 4); |
| tmp_data = mcld::bswap32(tmp_data); |
| target_data = tmp_data; |
| break; |
| } |
| case 64: { |
| pFragRef.memcpy(&target_data, 8); |
| target_data = mcld::bswap64(target_data); |
| break; |
| } |
| default: { |
| fatal(diag::unsupported_bitclass) << m_pConfig->targets().triple().str() |
| << m_pConfig->targets().bitclass(); |
| return NULL; |
| } |
| } // end of switch |
| } else { |
| pFragRef.memcpy(&target_data, (m_pConfig->targets().bitclass() / 8)); |
| } |
| |
| Relocation* result = allocate(); |
| new (result) Relocation(pType, &pFragRef, pAddend, target_data); |
| return result; |
| } |
| |
| Relocation* RelocationFactory::produceEmptyEntry() { |
| Relocation* result = allocate(); |
| new (result) Relocation(0, 0, 0, 0); |
| return result; |
| } |
| |
| void RelocationFactory::destroy(Relocation* pRelocation) { |
| /** GCFactory will recycle the relocation **/ |
| } |
| |
| } // namespace mcld |