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