1cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao//===- FragmentRef.cpp --------------------------------------------------===//
2cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao//
3cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao//                     The MCLinker Project
4cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao//
5cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao// This file is distributed under the University of Illinois Open Source
6cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao// License. See LICENSE.TXT for details.
7cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao//
8cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao//===----------------------------------------------------------------------===//
922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Fragment/FragmentRef.h>
10cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
1122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Fragment/Fragment.h>
1222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/LDSection.h>
1322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/SectionData.h>
1422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/EhFrame.h>
1522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Support/GCFactory.h>
1622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Fragment/RegionFragment.h>
1722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Fragment/Stub.h>
18cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
19f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <llvm/ADT/StringRef.h>
20f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <llvm/Support/Casting.h>
21f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <llvm/Support/ManagedStatic.h>
22f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
23f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <cassert>
24f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
25cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaousing namespace mcld;
26cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
2722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaotypedef GCFactory<FragmentRef, MCLD_SECTIONS_PER_INPUT> FragRefFactory;
28cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
2922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaostatic llvm::ManagedStatic<FragRefFactory> g_FragRefFactory;
30cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
3122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoFragmentRef FragmentRef::g_NullFragmentRef;
32cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
33cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao//===----------------------------------------------------------------------===//
34cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao// FragmentRef
35cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao//===----------------------------------------------------------------------===//
36cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei LiaoFragmentRef::FragmentRef()
37cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  : m_pFragment(NULL), m_Offset(0) {
38cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
39cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
40cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei LiaoFragmentRef::FragmentRef(Fragment& pFrag,
41cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                         FragmentRef::Offset pOffset)
42cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  : m_pFragment(&pFrag), m_Offset(pOffset) {
43cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
44cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
4522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// Create - create a fragment reference for a given fragment.
4622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao///
4722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// @param pFrag - the given fragment
4822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// @param pOffset - the offset, can be larger than the fragment, but can not
4922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao///                  be larger than the section size.
5022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// @return if the offset is legal, return the fragment reference. Otherwise,
5122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// return NULL.
5222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoFragmentRef* FragmentRef::Create(Fragment& pFrag, uint64_t pOffset)
53cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao{
5422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  int64_t offset = pOffset;
5522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  Fragment* frag = &pFrag;
5622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
5722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  while (NULL != frag) {
5822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    offset -= frag->size();
5922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (offset <= 0)
6022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      break;
6122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    frag = frag->getNextNode();
6222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
63f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if ((frag != NULL) && (frag->size() != 0)) {
64f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (offset == 0)
65f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      frag = frag->getNextNode();
66f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    else
67f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      offset += frag->size();
68f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
6922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
7022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL == frag)
7122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return Null();
7222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
7322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  FragmentRef* result = g_FragRefFactory->allocate();
74f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  new (result) FragmentRef(*frag, offset);
7522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
7622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return result;
7722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
7822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
7922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoFragmentRef* FragmentRef::Create(LDSection& pSection, uint64_t pOffset)
8022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
8122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  SectionData* data = NULL;
8222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  switch (pSection.kind()) {
8322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    case LDFileFormat::Relocation:
8422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // No fragment reference refers to a relocation section
8522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      break;
8622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    case LDFileFormat::EhFrame:
8722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      if (pSection.hasEhFrame())
88f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        data = pSection.getEhFrame()->getSectionData();
8922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      break;
9022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    default:
9122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      data = pSection.getSectionData();
9222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      break;
9322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
9422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
9522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL == data || data->empty()) {
9622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return Null();
9722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
9822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
9922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return Create(data->front(), pOffset);
10022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
10122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
10222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid FragmentRef::Clear()
10322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
10422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  g_FragRefFactory->clear();
10522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
10622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
10722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoFragmentRef* FragmentRef::Null()
10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
10922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return &g_NullFragmentRef;
110cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
111cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
112cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei LiaoFragmentRef& FragmentRef::assign(const FragmentRef& pCopy)
113cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao{
114cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  m_pFragment = const_cast<Fragment*>(pCopy.m_pFragment);
115cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  m_Offset = pCopy.m_Offset;
116cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  return *this;
117cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
118cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
119cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei LiaoFragmentRef& FragmentRef::assign(Fragment& pFrag, FragmentRef::Offset pOffset)
120cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao{
121cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  m_pFragment = &pFrag;
122cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  m_Offset = pOffset;
123cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  return *this;
124cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
125cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
126cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaovoid FragmentRef::memcpy(void* pDest, size_t pNBytes, Offset pOffset) const
127cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao{
128cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // check if the offset is still in a legal range.
129cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  if (NULL == m_pFragment)
130cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    return;
131cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  unsigned int total_offset = m_Offset + pOffset;
132cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  switch(m_pFragment->getKind()) {
133cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    case Fragment::Region: {
134cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      RegionFragment* region_frag = static_cast<RegionFragment*>(m_pFragment);
135cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      unsigned int total_length = region_frag->getRegion().size();
136cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      if (total_length < (total_offset+pNBytes))
137cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao        pNBytes = total_length - total_offset;
138cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
139f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      std::memcpy(pDest, region_frag->getRegion().begin() + total_offset, pNBytes);
140cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      return;
141cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    }
14222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    case Fragment::Stub: {
14322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      Stub* stub_frag = static_cast<Stub*>(m_pFragment);
14422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      unsigned int total_length = stub_frag->size();
14522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      if (total_length < (total_offset+pNBytes))
14622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        pNBytes = total_length - total_offset;
14722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      std::memcpy(pDest, stub_frag->getContent() + total_offset, pNBytes);
14822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      return;
14922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
150cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    case Fragment::Alignment:
151cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    case Fragment::Fillment:
152cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    default:
153cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      return;
154cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  }
155cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
156cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
15722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoFragmentRef::Offset FragmentRef::getOutputOffset() const
15822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
15922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  Offset result = 0;
16022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL != m_pFragment)
16122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    result = m_pFragment->getOffset();
16222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return (result + m_Offset);
16322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
164