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