FragmentRef.cpp revision f7ac0f19a1c8d0ad14bcf6456ce368b830fea886
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
11cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <cstring>
12cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <cassert>
13cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
14cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <llvm/Support/Casting.h>
1522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <llvm/Support/ManagedStatic.h>
16cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
1722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Fragment/Fragment.h>
1822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/LDSection.h>
1922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/SectionData.h>
2022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/EhFrame.h>
2122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Support/GCFactory.h>
2222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Support/MemoryRegion.h>
2322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Fragment/RegionFragment.h>
2422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Fragment/Stub.h>
25cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
26cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaousing namespace mcld;
27cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
2822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaotypedef GCFactory<FragmentRef, MCLD_SECTIONS_PER_INPUT> FragRefFactory;
29cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
3022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaostatic llvm::ManagedStatic<FragRefFactory> g_FragRefFactory;
31cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
3222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoFragmentRef FragmentRef::g_NullFragmentRef;
33cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
34cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao//===----------------------------------------------------------------------===//
35cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao// FragmentRef
36cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao//===----------------------------------------------------------------------===//
37cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei LiaoFragmentRef::FragmentRef()
38cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  : m_pFragment(NULL), m_Offset(0) {
39cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
40cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
41cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei LiaoFragmentRef::FragmentRef(Fragment& pFrag,
42cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                         FragmentRef::Offset pOffset)
43cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  : m_pFragment(&pFrag), m_Offset(pOffset) {
44cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
45cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
4622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// Create - create a fragment reference for a given fragment.
4722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao///
4822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// @param pFrag - the given fragment
4922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// @param pOffset - the offset, can be larger than the fragment, but can not
5022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao///                  be larger than the section size.
5122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// @return if the offset is legal, return the fragment reference. Otherwise,
5222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// return NULL.
5322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoFragmentRef* FragmentRef::Create(Fragment& pFrag, uint64_t pOffset)
54cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao{
5522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  int64_t offset = pOffset;
5622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  Fragment* frag = &pFrag;
5722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
5822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  while (NULL != frag) {
5922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    offset -= frag->size();
6022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (offset <= 0)
6122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      break;
6222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    frag = frag->getNextNode();
6322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
6422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
6522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
6622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL == frag)
6722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return Null();
6822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
6922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  FragmentRef* result = g_FragRefFactory->allocate();
7022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  new (result) FragmentRef(*frag, offset + frag->size());
7122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
7222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return result;
7322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
7422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
7522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoFragmentRef* FragmentRef::Create(LDSection& pSection, uint64_t pOffset)
7622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
7722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  SectionData* data = NULL;
7822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  switch (pSection.kind()) {
7922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    case LDFileFormat::Relocation:
8022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // No fragment reference refers to a relocation section
8122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      break;
8222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    case LDFileFormat::EhFrame:
8322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      if (pSection.hasEhFrame())
84f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        data = pSection.getEhFrame()->getSectionData();
8522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      break;
8622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    default:
8722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      data = pSection.getSectionData();
8822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      break;
8922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
9022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
9122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL == data || data->empty()) {
9222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return Null();
9322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
9422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
9522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return Create(data->front(), pOffset);
9622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
9722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
9822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid FragmentRef::Clear()
9922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
10022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  g_FragRefFactory->clear();
10122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
10222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
10322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoFragmentRef* FragmentRef::Null()
10422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
10522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return &g_NullFragmentRef;
106cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
107cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
108cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei LiaoFragmentRef& FragmentRef::assign(const FragmentRef& pCopy)
109cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao{
110cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  m_pFragment = const_cast<Fragment*>(pCopy.m_pFragment);
111cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  m_Offset = pCopy.m_Offset;
112cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  return *this;
113cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
114cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
115cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei LiaoFragmentRef& FragmentRef::assign(Fragment& pFrag, FragmentRef::Offset pOffset)
116cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao{
117cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  m_pFragment = &pFrag;
118cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  m_Offset = pOffset;
119cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  return *this;
120cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
121cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
122cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaovoid FragmentRef::memcpy(void* pDest, size_t pNBytes, Offset pOffset) const
123cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao{
124cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // check if the offset is still in a legal range.
125cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  if (NULL == m_pFragment)
126cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    return;
127cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  unsigned int total_offset = m_Offset + pOffset;
128cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  switch(m_pFragment->getKind()) {
129cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    case Fragment::Region: {
130cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      RegionFragment* region_frag = static_cast<RegionFragment*>(m_pFragment);
131cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      unsigned int total_length = region_frag->getRegion().size();
132cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      if (total_length < (total_offset+pNBytes))
133cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao        pNBytes = total_length - total_offset;
134cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
135cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      std::memcpy(pDest, region_frag->getRegion().getBuffer(total_offset), pNBytes);
136cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      return;
137cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    }
13822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    case Fragment::Stub: {
13922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      Stub* stub_frag = static_cast<Stub*>(m_pFragment);
14022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      unsigned int total_length = stub_frag->size();
14122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      if (total_length < (total_offset+pNBytes))
14222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        pNBytes = total_length - total_offset;
14322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      std::memcpy(pDest, stub_frag->getContent() + total_offset, pNBytes);
14422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      return;
14522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
146cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    case Fragment::Alignment:
147cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    case Fragment::Fillment:
148cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    default:
149cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      return;
150cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  }
151cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
152cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
153cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei LiaoFragmentRef::Address FragmentRef::deref()
154cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao{
155cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  if (NULL == m_pFragment)
156cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    return NULL;
157cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  Address base = NULL;
158cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  switch(m_pFragment->getKind()) {
159cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    case Fragment::Region:
160cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      base = static_cast<RegionFragment*>(m_pFragment)->getRegion().getBuffer();
161cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      break;
162cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    case Fragment::Alignment:
163cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    case Fragment::Fillment:
164cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    default:
165cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      return NULL;
166cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  }
167cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  return base + m_Offset;
168cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
169cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
170cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei LiaoFragmentRef::ConstAddress FragmentRef::deref() const
171cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao{
172cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  if (NULL == m_pFragment)
173cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    return NULL;
174cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  ConstAddress base = NULL;
175cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  switch(m_pFragment->getKind()) {
176cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    case Fragment::Region:
177cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      base = static_cast<const RegionFragment*>(m_pFragment)->getRegion().getBuffer();
178cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      break;
179cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    case Fragment::Alignment:
180cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    case Fragment::Fillment:
181cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    default:
182cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      return NULL;
183cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  }
184cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  return base + m_Offset;
185cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
186cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
18722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoFragmentRef::Offset FragmentRef::getOutputOffset() const
18822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
18922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  Offset result = 0;
19022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL != m_pFragment)
19122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    result = m_pFragment->getOffset();
19222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return (result + m_Offset);
19322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
19422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
195