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//===----------------------------------------------------------------------===//
937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/FragmentRef.h"
10cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/Fragment.h"
1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/RegionFragment.h"
1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/Stub.h"
1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/EhFrame.h"
1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSection.h"
1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/SectionData.h"
1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/GCFactory.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
2537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace 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//===----------------------------------------------------------------------===//
3637b74a387bb3993387029859c2d9d051c41c724eStephen HinesFragmentRef::FragmentRef() : m_pFragment(NULL), m_Offset(0) {
37cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
38cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
3937b74a387bb3993387029859c2d9d051c41c724eStephen HinesFragmentRef::FragmentRef(Fragment& pFrag, FragmentRef::Offset pOffset)
4037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : m_pFragment(&pFrag), m_Offset(pOffset) {
41cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
42cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
4322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// Create - create a fragment reference for a given fragment.
4422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao///
4522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// @param pFrag - the given fragment
4622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// @param pOffset - the offset, can be larger than the fragment, but can not
4722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao///                  be larger than the section size.
4822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// @return if the offset is legal, return the fragment reference. Otherwise,
4922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// return NULL.
5037b74a387bb3993387029859c2d9d051c41c724eStephen HinesFragmentRef* FragmentRef::Create(Fragment& pFrag, uint64_t pOffset) {
5122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  int64_t offset = pOffset;
5222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  Fragment* frag = &pFrag;
5322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
5437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  while (frag != NULL) {
5522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    offset -= frag->size();
5622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (offset <= 0)
5722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      break;
5822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    frag = frag->getNextNode();
5922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
60f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if ((frag != NULL) && (frag->size() != 0)) {
61f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (offset == 0)
62f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      frag = frag->getNextNode();
63f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    else
64f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      offset += frag->size();
65f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
6622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
6737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (frag == NULL)
6822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return Null();
6922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
7022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  FragmentRef* result = g_FragRefFactory->allocate();
71f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  new (result) FragmentRef(*frag, offset);
7222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
7322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return result;
7422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
7522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
7637b74a387bb3993387029859c2d9d051c41c724eStephen HinesFragmentRef* FragmentRef::Create(LDSection& pSection, uint64_t pOffset) {
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
9137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (data == NULL || 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
9837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid FragmentRef::Clear() {
9922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  g_FragRefFactory->clear();
10022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
10122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
10237b74a387bb3993387029859c2d9d051c41c724eStephen HinesFragmentRef* FragmentRef::Null() {
10322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return &g_NullFragmentRef;
104cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
105cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
10637b74a387bb3993387029859c2d9d051c41c724eStephen HinesFragmentRef& FragmentRef::assign(const FragmentRef& pCopy) {
107cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  m_pFragment = const_cast<Fragment*>(pCopy.m_pFragment);
108cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  m_Offset = pCopy.m_Offset;
109cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  return *this;
110cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
111cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
11237b74a387bb3993387029859c2d9d051c41c724eStephen HinesFragmentRef& FragmentRef::assign(Fragment& pFrag, FragmentRef::Offset pOffset) {
113cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  m_pFragment = &pFrag;
114cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  m_Offset = pOffset;
115cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  return *this;
116cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
117cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
11837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid FragmentRef::memcpy(void* pDest, size_t pNBytes, Offset pOffset) const {
119cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // check if the offset is still in a legal range.
12037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (m_pFragment == NULL)
121cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    return;
12237b74a387bb3993387029859c2d9d051c41c724eStephen Hines
123cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  unsigned int total_offset = m_Offset + pOffset;
12437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  switch (m_pFragment->getKind()) {
125cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    case Fragment::Region: {
126cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      RegionFragment* region_frag = static_cast<RegionFragment*>(m_pFragment);
127cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      unsigned int total_length = region_frag->getRegion().size();
12837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (total_length < (total_offset + pNBytes))
129cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao        pNBytes = total_length - total_offset;
130cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
13137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      std::memcpy(
13237b74a387bb3993387029859c2d9d051c41c724eStephen Hines          pDest, region_frag->getRegion().begin() + total_offset, pNBytes);
133cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      return;
134cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    }
13522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    case Fragment::Stub: {
13622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      Stub* stub_frag = static_cast<Stub*>(m_pFragment);
13722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      unsigned int total_length = stub_frag->size();
13837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (total_length < (total_offset + pNBytes))
13922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        pNBytes = total_length - total_offset;
14022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      std::memcpy(pDest, stub_frag->getContent() + total_offset, pNBytes);
14122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      return;
14222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
143cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    case Fragment::Alignment:
144cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    case Fragment::Fillment:
145cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    default:
146cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      return;
147cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  }
148cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao}
149cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
15037b74a387bb3993387029859c2d9d051c41c724eStephen HinesFragmentRef::Offset FragmentRef::getOutputOffset() const {
15122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  Offset result = 0;
15237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (m_pFragment != NULL)
15322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    result = m_pFragment->getOffset();
15422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return (result + m_Offset);
15522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
15637b74a387bb3993387029859c2d9d051c41c724eStephen Hines
15737b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
158