Home | History | Annotate | Download | only in MC
      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 
     17 using namespace mcld;
     18 
     19 /// compunteFragmentSize - compute the specific MCFragment size
     20 uint64_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
     72 MCFragmentRef::MCFragmentRef()
     73   : m_pFragment(NULL), m_Offset(0) {
     74 }
     75 
     76 MCFragmentRef::MCFragmentRef(llvm::MCFragment& pFrag,
     77                              MCFragmentRef::Offset pOffset)
     78   : m_pFragment(&pFrag), m_Offset(pOffset) {
     79 }
     80 
     81 MCFragmentRef::~MCFragmentRef()
     82 {
     83   m_pFragment = NULL;
     84   m_Offset = 0;
     85 }
     86 
     87 MCFragmentRef& 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 
     94 MCFragmentRef& MCFragmentRef::assign(llvm::MCFragment& pFrag, MCFragmentRef::Offset pOffset)
     95 {
     96   m_pFragment = &pFrag;
     97   m_Offset = pOffset;
     98   return *this;
     99 }
    100 
    101 void 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 
    146 MCFragmentRef::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 
    173 MCFragmentRef::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