Relocation.cpp revision 37b74a387bb3993387029859c2d9d051c41c724e
15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- Relocation.cpp -----------------------------------------------------===//
25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//                     The MCLinker Project
45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source
65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details.
75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/Relocation.h"
1037b74a387bb3993387029859c2d9d051c41c724eStephen Hines
1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSection.h"
1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSymbol.h"
1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/RelocationFactory.h"
1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/Relocator.h"
1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ResolveInfo.h"
1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/SectionData.h"
1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MsgHandling.h"
18d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
19d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include <llvm/Support/ManagedStatic.h>
205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
23d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaostatic llvm::ManagedStatic<RelocationFactory> g_RelocationFactory;
24d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
25d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===----------------------------------------------------------------------===//
26d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// Relocation Factory Methods
27d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===----------------------------------------------------------------------===//
28d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao/// Initialize - set up the relocation factory
2937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid Relocation::SetUp(const LinkerConfig& pConfig) {
30d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  g_RelocationFactory->setConfig(pConfig);
31d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
32d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
33d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao/// Clear - Clean up the relocation factory
3437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid Relocation::Clear() {
35d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  g_RelocationFactory->clear();
36d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
37d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
38d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao/// Create - produce an empty relocation entry
3937b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocation* Relocation::Create() {
40d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return g_RelocationFactory->produceEmptyEntry();
41d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
42d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
43d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao/// Create - produce a relocation entry
44d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao/// @param pType    [in] the type of the relocation entry
45d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao/// @param pFragRef [in] the place to apply the relocation
46d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao/// @param pAddend  [in] the addend of the relocation entry
4737b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocation* Relocation::Create(Type pType,
4837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                               FragmentRef& pFragRef,
4937b74a387bb3993387029859c2d9d051c41c724eStephen Hines                               Address pAddend) {
50d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return g_RelocationFactory->produce(pType, pFragRef, pAddend);
51d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
52d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
53d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao/// Destroy - destroy a relocation entry
5437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid Relocation::Destroy(Relocation*& pRelocation) {
55d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  g_RelocationFactory->destroy(pRelocation);
56d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  pRelocation = NULL;
57d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
58d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
59d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===----------------------------------------------------------------------===//
60d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// Relocation
61d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===----------------------------------------------------------------------===//
62d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoRelocation::Relocation()
6337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : m_Type(0x0), m_TargetData(0x0), m_pSymInfo(NULL), m_Addend(0x0) {
64d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
65d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoRelocation::Relocation(Relocation::Type pType,
67cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                       FragmentRef* pTargetRef,
685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                       Relocation::Address pAddend,
695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                       Relocation::DWord pTargetData)
7037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : m_Type(pType),
7137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_TargetData(pTargetData),
7237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pSymInfo(NULL),
7337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_Addend(pAddend) {
7437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (pTargetRef != NULL)
7537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    m_TargetAddress.assign(*pTargetRef->frag(), pTargetRef->offset());
765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7837b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocation::~Relocation() {
795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8137b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocation::Address Relocation::place() const {
8222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  Address sect_addr = m_TargetAddress.frag()->getParent()->getSection().addr();
8322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return sect_addr + m_TargetAddress.getOutputOffset();
845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8637b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocation::Address Relocation::symValue() const {
87affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (m_pSymInfo->type() == ResolveInfo::Section &&
88f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      m_pSymInfo->outSymbol()->hasFragRef()) {
89f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    const FragmentRef* fragRef = m_pSymInfo->outSymbol()->fragRef();
90f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    return fragRef->frag()->getParent()->getSection().addr() +
91f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines           fragRef->getOutputOffset();
925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return m_pSymInfo->outSymbol()->value();
945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid Relocation::apply(Relocator& pRelocator) {
97d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::Result result = pRelocator.applyRelocation(*this);
9867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
9967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  switch (result) {
100d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    case Relocator::OK: {
10167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao      // do nothing
10267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao      return;
10367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao    }
104d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    case Relocator::Overflow: {
105d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      error(diag::result_overflow) << pRelocator.getName(type())
10667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao                                   << symInfo()->name();
10767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao      return;
10867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao    }
109d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    case Relocator::BadReloc: {
110d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      error(diag::result_badreloc) << pRelocator.getName(type())
11167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao                                   << symInfo()->name();
11267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao      return;
11367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao    }
11437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case Relocator::Unsupported: {
11567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao      fatal(diag::unsupported_relocation) << type()
11667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao                                          << "mclinker@googlegroups.com";
11767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao      return;
11867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao    }
119d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    case Relocator::Unknown: {
12022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      fatal(diag::unknown_relocation) << type() << symInfo()->name();
12122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      return;
12222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
12337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  }  // end of switch
1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
12637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid Relocation::setType(Type pType) {
1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  m_Type = pType;
1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
13037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid Relocation::setAddend(Address pAddend) {
1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  m_Addend = pAddend;
1325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
13437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid Relocation::setSymInfo(ResolveInfo* pSym) {
1355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  m_pSymInfo = pSym;
1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
13837b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocation::Size Relocation::size(Relocator& pRelocator) const {
1396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return pRelocator.getSize(m_Type);
1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
14237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid Relocation::updateAddend() {
14322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // Update value keep in addend if we meet a section symbol
14422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (m_pSymInfo->type() == ResolveInfo::Section) {
14522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    uint32_t offset = m_pSymInfo->outSymbol()->fragRef()->getOutputOffset();
14622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    m_Addend += offset;
14722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
14937b74a387bb3993387029859c2d9d051c41c724eStephen Hines
15037b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
151