1//===- MCFragmentRef.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#include <llvm/Support/MathExtras.h> 10#include <mcld/MC/MCFragmentRef.h> 11#include <mcld/MC/MCRegionFragment.h> 12#include <mcld/MC/MCTargetFragment.h> 13#include <mcld/LD/Layout.h> 14#include <cstring> 15#include <cassert> 16 17using namespace mcld; 18 19/// compunteFragmentSize - compute the specific MCFragment size 20uint64_t mcld::computeFragmentSize(const Layout& pLayout, 21 const llvm::MCFragment& pFrag) 22{ 23 switch (pFrag.getKind()) { 24 case llvm::MCFragment::FT_Data: 25 return static_cast<const llvm::MCDataFragment&>(pFrag).getContents().size(); 26 case llvm::MCFragment::FT_Fill: 27 return static_cast<const llvm::MCFillFragment&>(pFrag).getSize(); 28 case llvm::MCFragment::FT_Inst: 29 return static_cast<const llvm::MCInstFragment&>(pFrag).getInstSize(); 30 31 case llvm::MCFragment::FT_LEB: 32 return static_cast<const llvm::MCLEBFragment&>(pFrag).getContents().size(); 33 34 case llvm::MCFragment::FT_Align: { 35 uint64_t offset = pLayout.getOutputOffset(pFrag); 36 const llvm::MCAlignFragment& align_frag = static_cast<const llvm::MCAlignFragment&>(pFrag); 37 uint64_t size = llvm::OffsetToAlignment(offset, align_frag.getAlignment()); 38 if (size > align_frag.getMaxBytesToEmit()) 39 return 0; 40 return size; 41 } 42 43 case llvm::MCFragment::FT_Org: { 44 // TODO 45 assert(0 && "FT_Org: Not implemented yet"); 46 return 0; 47 } 48 49 case llvm::MCFragment::FT_Dwarf: 50 return static_cast<const llvm::MCDwarfLineAddrFragment&>(pFrag).getContents().size(); 51 case llvm::MCFragment::FT_DwarfFrame: 52 return static_cast<const llvm::MCDwarfCallFrameFragment&>(pFrag).getContents().size(); 53 54 case llvm::MCFragment::FT_Region: 55 return static_cast<const MCRegionFragment&>(pFrag).getRegion().size(); 56 57 case llvm::MCFragment::FT_Target: 58 return static_cast<const MCTargetFragment&>(pFrag).getSize(); 59 60 case llvm::MCFragment::FT_Reloc: 61 assert(0 && "the size of FT_Reloc fragment is handled by backend"); 62 return 0; 63 64 default: 65 assert(0 && "invalid fragment kind"); 66 return 0; 67 } 68} 69 70//========================== 71// MCFragmentRef 72MCFragmentRef::MCFragmentRef() 73 : m_pFragment(NULL), m_Offset(0) { 74} 75 76MCFragmentRef::MCFragmentRef(llvm::MCFragment& pFrag, 77 MCFragmentRef::Offset pOffset) 78 : m_pFragment(&pFrag), m_Offset(pOffset) { 79} 80 81MCFragmentRef::~MCFragmentRef() 82{ 83 m_pFragment = NULL; 84 m_Offset = 0; 85} 86 87MCFragmentRef& MCFragmentRef::assign(const MCFragmentRef& pCopy) 88{ 89 m_pFragment = const_cast<llvm::MCFragment*>(pCopy.m_pFragment); 90 m_Offset = pCopy.m_Offset; 91 return *this; 92} 93 94MCFragmentRef& MCFragmentRef::assign(llvm::MCFragment& pFrag, MCFragmentRef::Offset pOffset) 95{ 96 m_pFragment = &pFrag; 97 m_Offset = pOffset; 98 return *this; 99} 100 101void MCFragmentRef::memcpy(void* pDest, size_t pNBytes, Offset pOffset) const 102{ 103 // check if the offset is still in a legal range. 104 if (NULL == m_pFragment) 105 return; 106 unsigned int total_offset = m_Offset + pOffset; 107 switch(m_pFragment->getKind()) { 108 case llvm::MCFragment::FT_Inst: { 109 llvm::MCInstFragment* inst_frag = static_cast<llvm::MCInstFragment*>(m_pFragment); 110 unsigned int total_length = inst_frag->getCode().size(); 111 if (total_length < (total_offset+pNBytes)) 112 pNBytes = total_length - total_offset; 113 114 std::memcpy(pDest, (inst_frag->getCode().data()+total_offset), pNBytes); 115 return; 116 } 117 case llvm::MCFragment::FT_Data: { 118 llvm::MCDataFragment* data_frag = static_cast<llvm::MCDataFragment*>(m_pFragment); 119 unsigned int total_length = data_frag->getContents().size(); 120 if (total_length < (total_offset+pNBytes)) 121 pNBytes = total_length - total_offset; 122 123 std::memcpy(pDest, (data_frag->getContents().data()+total_offset), pNBytes); 124 return; 125 } 126 case llvm::MCFragment::FT_Region: { 127 MCRegionFragment* region_frag = static_cast<mcld::MCRegionFragment*>(m_pFragment); 128 unsigned int total_length = region_frag->getRegion().size(); 129 if (total_length < (total_offset+pNBytes)) 130 pNBytes = total_length - total_offset; 131 132 std::memcpy(pDest, region_frag->getRegion().getBuffer(total_offset), pNBytes); 133 return; 134 } 135 case llvm::MCFragment::FT_Align: 136 case llvm::MCFragment::FT_Fill: 137 case llvm::MCFragment::FT_Org: 138 case llvm::MCFragment::FT_Dwarf: 139 case llvm::MCFragment::FT_DwarfFrame: 140 case llvm::MCFragment::FT_LEB: 141 default: 142 return; 143 } 144} 145 146MCFragmentRef::Address MCFragmentRef::deref() 147{ 148 if (NULL == m_pFragment) 149 return NULL; 150 Address base = NULL; 151 switch(m_pFragment->getKind()) { 152 case llvm::MCFragment::FT_Inst: 153 base = (Address)static_cast<llvm::MCInstFragment*>(m_pFragment)->getCode().data(); 154 break; 155 case llvm::MCFragment::FT_Data: 156 base = (Address)static_cast<llvm::MCDataFragment*>(m_pFragment)->getContents().data(); 157 break; 158 case llvm::MCFragment::FT_Region: 159 base = static_cast<mcld::MCRegionFragment*>(m_pFragment)->getRegion().getBuffer(); 160 break; 161 case llvm::MCFragment::FT_Align: 162 case llvm::MCFragment::FT_Fill: 163 case llvm::MCFragment::FT_Org: 164 case llvm::MCFragment::FT_Dwarf: 165 case llvm::MCFragment::FT_DwarfFrame: 166 case llvm::MCFragment::FT_LEB: 167 default: 168 return NULL; 169 } 170 return base + m_Offset; 171} 172 173MCFragmentRef::ConstAddress MCFragmentRef::deref() const 174{ 175 if (NULL == m_pFragment) 176 return NULL; 177 ConstAddress base = NULL; 178 switch(m_pFragment->getKind()) { 179 case llvm::MCFragment::FT_Inst: 180 base = (ConstAddress)static_cast<const llvm::MCInstFragment*>(m_pFragment)->getCode().data(); 181 break; 182 case llvm::MCFragment::FT_Data: 183 base = (ConstAddress)static_cast<const llvm::MCDataFragment*>(m_pFragment)->getContents().data(); 184 break; 185 case llvm::MCFragment::FT_Region: 186 base = static_cast<const mcld::MCRegionFragment*>(m_pFragment)->getRegion().getBuffer(); 187 break; 188 case llvm::MCFragment::FT_Align: 189 case llvm::MCFragment::FT_Fill: 190 case llvm::MCFragment::FT_Org: 191 case llvm::MCFragment::FT_Dwarf: 192 case llvm::MCFragment::FT_DwarfFrame: 193 case llvm::MCFragment::FT_LEB: 194 default: 195 return NULL; 196 } 197 return base + m_Offset; 198} 199 200