You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
88 lines
2.6 KiB
88 lines
2.6 KiB
//===- 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
|