1//===- FragmentRef.cpp --------------------------------------------------===// 2// 3// The MCLinker Project 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include <mcld/LD/FragmentRef.h> 11 12#include <cstring> 13#include <cassert> 14 15#include <llvm/Support/MathExtras.h> 16#include <llvm/Support/Casting.h> 17 18#include <mcld/LD/AlignFragment.h> 19#include <mcld/LD/FillFragment.h> 20#include <mcld/LD/RegionFragment.h> 21#include <mcld/LD/TargetFragment.h> 22#include <mcld/LD/Layout.h> 23 24using namespace mcld; 25 26//===----------------------------------------------------------------------===// 27// Helper Functions 28//===----------------------------------------------------------------------===// 29/// compunteFragmentSize - compute the specific Fragment size 30uint64_t mcld::computeFragmentSize(const Layout& pLayout, 31 const Fragment& pFrag) 32{ 33 switch (pFrag.getKind()) { 34 case Fragment::Fillment: 35 return static_cast<const FillFragment&>(pFrag).getSize(); 36 37 case Fragment::Alignment: { 38 uint64_t offset = pLayout.getOutputOffset(pFrag); 39 const AlignFragment& align_frag = llvm::cast<AlignFragment>(pFrag); 40 uint64_t size = llvm::OffsetToAlignment(offset, align_frag.getAlignment()); 41 if (size > align_frag.getMaxBytesToEmit()) 42 return 0; 43 return size; 44 } 45 46 case Fragment::Region: 47 return llvm::cast<RegionFragment>(pFrag).getRegion().size(); 48 49 case Fragment::Target: 50 return llvm::cast<TargetFragment>(pFrag).getSize(); 51 52 case Fragment::Relocation: 53 assert(0 && "the size of FT_Reloc fragment is handled by backend"); 54 return 0; 55 56 default: 57 assert(0 && "invalid fragment kind"); 58 return 0; 59 } 60} 61 62//===----------------------------------------------------------------------===// 63// FragmentRef 64//===----------------------------------------------------------------------===// 65FragmentRef::FragmentRef() 66 : m_pFragment(NULL), m_Offset(0) { 67} 68 69FragmentRef::FragmentRef(Fragment& pFrag, 70 FragmentRef::Offset pOffset) 71 : m_pFragment(&pFrag), m_Offset(pOffset) { 72} 73 74FragmentRef::~FragmentRef() 75{ 76 m_pFragment = NULL; 77 m_Offset = 0; 78} 79 80FragmentRef& FragmentRef::assign(const FragmentRef& pCopy) 81{ 82 m_pFragment = const_cast<Fragment*>(pCopy.m_pFragment); 83 m_Offset = pCopy.m_Offset; 84 return *this; 85} 86 87FragmentRef& FragmentRef::assign(Fragment& pFrag, FragmentRef::Offset pOffset) 88{ 89 m_pFragment = &pFrag; 90 m_Offset = pOffset; 91 return *this; 92} 93 94void FragmentRef::memcpy(void* pDest, size_t pNBytes, Offset pOffset) const 95{ 96 // check if the offset is still in a legal range. 97 if (NULL == m_pFragment) 98 return; 99 unsigned int total_offset = m_Offset + pOffset; 100 switch(m_pFragment->getKind()) { 101 case Fragment::Region: { 102 RegionFragment* region_frag = static_cast<RegionFragment*>(m_pFragment); 103 unsigned int total_length = region_frag->getRegion().size(); 104 if (total_length < (total_offset+pNBytes)) 105 pNBytes = total_length - total_offset; 106 107 std::memcpy(pDest, region_frag->getRegion().getBuffer(total_offset), pNBytes); 108 return; 109 } 110 case Fragment::Alignment: 111 case Fragment::Fillment: 112 default: 113 return; 114 } 115} 116 117FragmentRef::Address FragmentRef::deref() 118{ 119 if (NULL == m_pFragment) 120 return NULL; 121 Address base = NULL; 122 switch(m_pFragment->getKind()) { 123 case Fragment::Region: 124 base = static_cast<RegionFragment*>(m_pFragment)->getRegion().getBuffer(); 125 break; 126 case Fragment::Alignment: 127 case Fragment::Fillment: 128 default: 129 return NULL; 130 } 131 return base + m_Offset; 132} 133 134FragmentRef::ConstAddress FragmentRef::deref() const 135{ 136 if (NULL == m_pFragment) 137 return NULL; 138 ConstAddress base = NULL; 139 switch(m_pFragment->getKind()) { 140 case Fragment::Region: 141 base = static_cast<const RegionFragment*>(m_pFragment)->getRegion().getBuffer(); 142 break; 143 case Fragment::Alignment: 144 case Fragment::Fillment: 145 default: 146 return NULL; 147 } 148 return base + m_Offset; 149} 150 151