Home | History | Annotate | Download | only in Target
      1 //===- ELFDynamic.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/Host.h>
     10 #include <llvm/Support/ErrorHandling.h>
     11 #include <mcld/Target/ELFDynamic.h>
     12 #include <mcld/Target/GNULDBackend.h>
     13 #include <mcld/LD/ELFFileFormat.h>
     14 #include <mcld/MC/MCLDInfo.h>
     15 #include <mcld/Support/MemoryRegion.h>
     16 
     17 using namespace mcld;
     18 using namespace elf_dynamic;
     19 
     20 //===----------------------------------------------------------------------===//
     21 // elf_dynamic::EntryIF
     22 EntryIF::EntryIF()
     23 {
     24 }
     25 
     26 EntryIF::~EntryIF()
     27 {
     28 }
     29 
     30 //===----------------------------------------------------------------------===//
     31 // ELFDynamic
     32 ELFDynamic::ELFDynamic(const GNULDBackend& pParent)
     33   : m_pEntryFactory(NULL), m_Idx(0) {
     34   if (32 == pParent.bitclass() && pParent.isLittleEndian()) {
     35     m_pEntryFactory = new Entry<32, true>();
     36   }
     37   // FIXME: support big-endian and 64-bit machine.
     38 }
     39 
     40 
     41 ELFDynamic::~ELFDynamic()
     42 {
     43   if (NULL != m_pEntryFactory)
     44     delete m_pEntryFactory;
     45 
     46   EntryListType::iterator entry, entryEnd = m_EntryList.end();
     47   for (entry = m_EntryList.begin(); entry != entryEnd; ++entry) {
     48     if (NULL != *entry)
     49       delete (*entry);
     50   }
     51 
     52   entryEnd = m_NeedList.end();
     53   for (entry = m_NeedList.begin(); entry != entryEnd; ++entry) {
     54     if (NULL != *entry)
     55       delete (*entry);
     56   }
     57 }
     58 
     59 size_t ELFDynamic::size() const
     60 {
     61   return (m_NeedList.size() + m_EntryList.size());
     62 }
     63 
     64 size_t ELFDynamic::numOfBytes() const
     65 {
     66   return size()*entrySize();
     67 }
     68 
     69 size_t ELFDynamic::entrySize() const
     70 {
     71   return m_pEntryFactory->size();
     72 }
     73 
     74 void ELFDynamic::reserveOne(uint64_t pTag)
     75 {
     76   assert(NULL != m_pEntryFactory);
     77   m_EntryList.push_back(new elf_dynamic::Entry<32, true>());
     78 }
     79 
     80 void ELFDynamic::applyOne(uint64_t pTag, uint64_t pValue)
     81 {
     82   assert(m_Idx < m_EntryList.size());
     83   m_EntryList[m_Idx]->setValue(pTag, pValue);
     84   ++m_Idx;
     85 }
     86 
     87 
     88 /// reserveEntries - reserve entries
     89 void ELFDynamic::reserveEntries(const MCLDInfo& pLDInfo,
     90                                 const ELFFileFormat& pFormat)
     91 {
     92   if (pLDInfo.output().type() == Output::DynObj) {
     93     reserveOne(llvm::ELF::DT_SONAME); // DT_SONAME
     94 
     95     if (pLDInfo.options().Bsymbolic())
     96       reserveOne(llvm::ELF::DT_SYMBOLIC); // DT_SYMBOLIC
     97   }
     98 
     99   if (pFormat.hasInit())
    100     reserveOne(llvm::ELF::DT_INIT); // DT_INIT
    101 
    102   if (pFormat.hasFini())
    103     reserveOne(llvm::ELF::DT_FINI); // DT_FINI
    104 
    105   if (pFormat.hasInitArray()) {
    106     reserveOne(llvm::ELF::DT_INIT_ARRAY); // DT_INIT_ARRAY
    107     reserveOne(llvm::ELF::DT_INIT_ARRAYSZ); // DT_INIT_ARRAYSZ
    108   }
    109 
    110   if (pFormat.hasFiniArray()) {
    111     reserveOne(llvm::ELF::DT_FINI_ARRAY); // DT_FINI_ARRAY
    112     reserveOne(llvm::ELF::DT_FINI_ARRAYSZ); // DT_FINI_ARRAYSZ
    113   }
    114 
    115   if (pFormat.hasHashTab())
    116     reserveOne(llvm::ELF::DT_HASH); // DT_HASH
    117 
    118   if (pFormat.hasDynSymTab()) {
    119     reserveOne(llvm::ELF::DT_SYMTAB); // DT_SYMTAB
    120     reserveOne(llvm::ELF::DT_SYMENT); // DT_SYMENT
    121   }
    122 
    123   if (pFormat.hasDynStrTab()) {
    124     reserveOne(llvm::ELF::DT_STRTAB); // DT_STRTAB
    125     reserveOne(llvm::ELF::DT_STRSZ); // DT_STRSZ
    126   }
    127 
    128   reserveTargetEntries(pFormat); // DT_PLTGOT
    129 
    130   if (pFormat.hasRelPlt() || pFormat.hasRelaPlt())
    131     reserveOne(llvm::ELF::DT_PLTREL); // DT_PLTREL
    132 
    133   if (pFormat.hasPLT()) {
    134     reserveOne(llvm::ELF::DT_JMPREL); // DT_JMPREL
    135     reserveOne(llvm::ELF::DT_PLTRELSZ); // DT_PLTRELSZ
    136   }
    137 
    138   if (pFormat.hasRelDyn()) {
    139     reserveOne(llvm::ELF::DT_REL); // DT_REL
    140     reserveOne(llvm::ELF::DT_RELSZ); // DT_RELSZ
    141     reserveOne(llvm::ELF::DT_RELENT); // DT_RELENT
    142   }
    143 
    144   if (pFormat.hasRelaDyn()) {
    145     reserveOne(llvm::ELF::DT_RELA); // DT_RELA
    146     reserveOne(llvm::ELF::DT_RELASZ); // DT_RELASZ
    147     reserveOne(llvm::ELF::DT_RELAENT); // DT_RELAENT
    148   }
    149   reserveOne(llvm::ELF::DT_NULL); // for DT_NULL
    150 }
    151 
    152 /// applyEntries - apply entries
    153 void ELFDynamic::applyEntries(const MCLDInfo& pInfo,
    154                               const ELFFileFormat& pFormat)
    155 {
    156   if (pInfo.output().type() == Output::DynObj &&
    157       pInfo.options().Bsymbolic()) {
    158       applyOne(llvm::ELF::DT_SYMBOLIC, 0x0); // DT_SYMBOLIC
    159   }
    160 
    161   if (pFormat.hasInit())
    162     applyOne(llvm::ELF::DT_INIT, pFormat.getInit().addr()); // DT_INIT
    163 
    164   if (pFormat.hasFini())
    165     applyOne(llvm::ELF::DT_FINI, pFormat.getFini().addr()); // DT_FINI
    166 
    167   if (pFormat.hasInitArray()) {
    168     // DT_INIT_ARRAY
    169     applyOne(llvm::ELF::DT_INIT_ARRAY, pFormat.getInitArray().addr());
    170 
    171     // DT_INIT_ARRAYSZ
    172     applyOne(llvm::ELF::DT_INIT_ARRAYSZ, pFormat.getInitArray().size());
    173   }
    174 
    175   if (pFormat.hasFiniArray()) {
    176     // DT_FINI_ARRAY
    177     applyOne(llvm::ELF::DT_FINI_ARRAY, pFormat.getFiniArray().addr());
    178 
    179     // DT_FINI_ARRAYSZ
    180     applyOne(llvm::ELF::DT_FINI_ARRAYSZ, pFormat.getFiniArray().size());
    181   }
    182 
    183   if (pFormat.hasHashTab())
    184     applyOne(llvm::ELF::DT_HASH, pFormat.getHashTab().addr()); // DT_HASH
    185 
    186   if (pFormat.hasDynSymTab()) {
    187     applyOne(llvm::ELF::DT_SYMTAB, pFormat.getDynSymTab().addr()); // DT_SYMTAB
    188     applyOne(llvm::ELF::DT_SYMENT, symbolSize()); // DT_SYMENT
    189   }
    190 
    191   if (pFormat.hasDynStrTab()) {
    192     applyOne(llvm::ELF::DT_STRTAB, pFormat.getDynStrTab().addr()); // DT_STRTAB
    193     applyOne(llvm::ELF::DT_STRSZ, pFormat.getDynStrTab().size()); // DT_STRSZ
    194   }
    195 
    196   applyTargetEntries(pFormat); // DT_PLTGOT
    197 
    198   if (pFormat.hasRelPlt())
    199     applyOne(llvm::ELF::DT_PLTREL, llvm::ELF::DT_REL); // DT_PLTREL
    200   else if (pFormat.hasRelaPlt())
    201     applyOne(llvm::ELF::DT_PLTREL, llvm::ELF::DT_RELA); // DT_PLTREL
    202 
    203   if (pFormat.hasRelPlt()) {
    204     applyOne(llvm::ELF::DT_JMPREL, pFormat.getRelPlt().addr()); // DT_JMPREL
    205     applyOne(llvm::ELF::DT_PLTRELSZ, pFormat.getRelPlt().size()); // DT_PLTRELSZ
    206   }
    207 
    208   if (pFormat.hasRelDyn()) {
    209     applyOne(llvm::ELF::DT_REL, pFormat.getRelDyn().addr()); // DT_REL
    210     applyOne(llvm::ELF::DT_RELSZ, pFormat.getRelDyn().size()); // DT_RELSZ
    211     applyOne(llvm::ELF::DT_RELENT, m_pEntryFactory->relSize()); // DT_RELENT
    212   }
    213 
    214   if (pFormat.hasRelaDyn()) {
    215     applyOne(llvm::ELF::DT_RELA, pFormat.getRelaDyn().addr()); // DT_RELA
    216     applyOne(llvm::ELF::DT_RELASZ, pFormat.getRelaDyn().size()); // DT_RELASZ
    217     applyOne(llvm::ELF::DT_RELAENT, m_pEntryFactory->relaSize()); // DT_RELAENT
    218   }
    219 
    220   applyOne(llvm::ELF::DT_NULL, 0x0); // for DT_NULL
    221 }
    222 
    223 /// symbolSize
    224 size_t ELFDynamic::symbolSize() const
    225 {
    226   return m_pEntryFactory->symbolSize();
    227 }
    228 
    229 /// reserveNeedEntry - reserve on DT_NEED entry.
    230 void ELFDynamic::reserveNeedEntry()
    231 {
    232   m_NeedList.push_back(m_pEntryFactory->clone());
    233 }
    234 
    235 /// emit
    236 void ELFDynamic::emit(const LDSection& pSection, MemoryRegion& pRegion) const
    237 {
    238   if (pRegion.size() < pSection.size()) {
    239     llvm::report_fatal_error(llvm::Twine("the given memory is smaller") +
    240                              llvm::Twine(" than the section's demaind.\n"));
    241   }
    242 
    243   uint8_t* address = (uint8_t*)pRegion.start();
    244   EntryListType::const_iterator entry, entryEnd = m_NeedList.end();
    245   for (entry = m_NeedList.begin(); entry != entryEnd; ++entry)
    246     address += (*entry)->emit(address);
    247 
    248   entryEnd = m_EntryList.end();
    249   for (entry = m_EntryList.begin(); entry != entryEnd; ++entry)
    250     address += (*entry)->emit(address);
    251 }
    252 
    253 void ELFDynamic::applySoname(uint64_t pStrTabIdx)
    254 {
    255   applyOne(llvm::ELF::DT_SONAME, pStrTabIdx); // DT_SONAME
    256 }
    257 
    258