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/LinkerConfig.h>
     15 #include <mcld/Support/MemoryRegion.h>
     16 #include <mcld/Support/MsgHandling.h>
     17 
     18 using namespace mcld;
     19 using namespace elf_dynamic;
     20 
     21 //===----------------------------------------------------------------------===//
     22 // elf_dynamic::EntryIF
     23 //===----------------------------------------------------------------------===//
     24 EntryIF::EntryIF()
     25 {
     26 }
     27 
     28 EntryIF::~EntryIF()
     29 {
     30 }
     31 
     32 //===----------------------------------------------------------------------===//
     33 // ELFDynamic
     34 //===----------------------------------------------------------------------===//
     35 ELFDynamic::ELFDynamic(const GNULDBackend& pParent,
     36                        const LinkerConfig& pConfig)
     37   : m_pEntryFactory(NULL), m_Backend(pParent), m_Config(pConfig), m_Idx(0) {
     38   // FIXME: support big-endian machine.
     39   if (m_Config.targets().is32Bits()) {
     40     if (m_Config.targets().isLittleEndian())
     41       m_pEntryFactory = new Entry<32, true>();
     42   } else if (m_Config.targets().is64Bits()) {
     43     if (m_Config.targets().isLittleEndian())
     44       m_pEntryFactory = new Entry<64, true>();
     45   } else {
     46     fatal(diag::unsupported_bitclass) << m_Config.targets().triple().str()
     47                                       << m_Config.targets().bitclass();
     48   }
     49 }
     50 
     51 
     52 ELFDynamic::~ELFDynamic()
     53 {
     54   if (NULL != m_pEntryFactory)
     55     delete m_pEntryFactory;
     56 
     57   EntryListType::iterator entry, entryEnd = m_EntryList.end();
     58   for (entry = m_EntryList.begin(); entry != entryEnd; ++entry) {
     59     if (NULL != *entry)
     60       delete (*entry);
     61   }
     62 
     63   entryEnd = m_NeedList.end();
     64   for (entry = m_NeedList.begin(); entry != entryEnd; ++entry) {
     65     if (NULL != *entry)
     66       delete (*entry);
     67   }
     68 }
     69 
     70 size_t ELFDynamic::size() const
     71 {
     72   return (m_NeedList.size() + m_EntryList.size());
     73 }
     74 
     75 size_t ELFDynamic::numOfBytes() const
     76 {
     77   return size()*entrySize();
     78 }
     79 
     80 size_t ELFDynamic::entrySize() const
     81 {
     82   return m_pEntryFactory->size();
     83 }
     84 
     85 void ELFDynamic::reserveOne(uint64_t pTag)
     86 {
     87   assert(NULL != m_pEntryFactory);
     88   m_EntryList.push_back(m_pEntryFactory->clone());
     89 }
     90 
     91 void ELFDynamic::applyOne(uint64_t pTag, uint64_t pValue)
     92 {
     93   assert(m_Idx < m_EntryList.size());
     94   m_EntryList[m_Idx]->setValue(pTag, pValue);
     95   ++m_Idx;
     96 }
     97 
     98 /// reserveEntries - reserve entries
     99 void ELFDynamic::reserveEntries(const ELFFileFormat& pFormat)
    100 {
    101   if (LinkerConfig::DynObj == m_Config.codeGenType()) {
    102     reserveOne(llvm::ELF::DT_SONAME); // DT_SONAME
    103 
    104     if (m_Config.options().Bsymbolic())
    105       reserveOne(llvm::ELF::DT_SYMBOLIC); // DT_SYMBOLIC
    106   }
    107 
    108   if (pFormat.hasInit())
    109     reserveOne(llvm::ELF::DT_INIT); // DT_INIT
    110 
    111   if (pFormat.hasFini())
    112     reserveOne(llvm::ELF::DT_FINI); // DT_FINI
    113 
    114   if (pFormat.hasInitArray()) {
    115     reserveOne(llvm::ELF::DT_INIT_ARRAY); // DT_INIT_ARRAY
    116     reserveOne(llvm::ELF::DT_INIT_ARRAYSZ); // DT_INIT_ARRAYSZ
    117   }
    118 
    119   if (pFormat.hasFiniArray()) {
    120     reserveOne(llvm::ELF::DT_FINI_ARRAY); // DT_FINI_ARRAY
    121     reserveOne(llvm::ELF::DT_FINI_ARRAYSZ); // DT_FINI_ARRAYSZ
    122   }
    123 
    124   if (pFormat.hasHashTab())
    125     reserveOne(llvm::ELF::DT_HASH); // DT_HASH
    126 
    127   // FIXME: use llvm enum constant
    128   if (pFormat.hasGNUHashTab())
    129     reserveOne(0x6ffffef5); // DT_GNU_HASH
    130 
    131   if (pFormat.hasDynSymTab()) {
    132     reserveOne(llvm::ELF::DT_SYMTAB); // DT_SYMTAB
    133     reserveOne(llvm::ELF::DT_SYMENT); // DT_SYMENT
    134   }
    135 
    136   if (pFormat.hasDynStrTab()) {
    137     reserveOne(llvm::ELF::DT_STRTAB); // DT_STRTAB
    138     reserveOne(llvm::ELF::DT_STRSZ); // DT_STRSZ
    139   }
    140 
    141   reserveTargetEntries(pFormat); // DT_PLTGOT
    142 
    143   if (pFormat.hasRelPlt() || pFormat.hasRelaPlt())
    144     reserveOne(llvm::ELF::DT_PLTREL); // DT_PLTREL
    145 
    146   if (pFormat.hasPLT()) {
    147     reserveOne(llvm::ELF::DT_JMPREL); // DT_JMPREL
    148     reserveOne(llvm::ELF::DT_PLTRELSZ); // DT_PLTRELSZ
    149   }
    150 
    151   if (pFormat.hasRelDyn()) {
    152     reserveOne(llvm::ELF::DT_REL); // DT_REL
    153     reserveOne(llvm::ELF::DT_RELSZ); // DT_RELSZ
    154     reserveOne(llvm::ELF::DT_RELENT); // DT_RELENT
    155   }
    156 
    157   if (pFormat.hasRelaDyn()) {
    158     reserveOne(llvm::ELF::DT_RELA); // DT_RELA
    159     reserveOne(llvm::ELF::DT_RELASZ); // DT_RELASZ
    160     reserveOne(llvm::ELF::DT_RELAENT); // DT_RELAENT
    161   }
    162 
    163   uint64_t dt_flags = 0x0;
    164   if (m_Config.options().hasOrigin())
    165     dt_flags |= llvm::ELF::DF_ORIGIN;
    166   if (m_Config.options().Bsymbolic())
    167     dt_flags |= llvm::ELF::DF_SYMBOLIC;
    168   if (m_Config.options().hasNow())
    169     dt_flags |= llvm::ELF::DF_BIND_NOW;
    170   if (m_Backend.hasTextRel())
    171     dt_flags |= llvm::ELF::DF_TEXTREL;
    172   if (m_Backend.hasStaticTLS() &&
    173       (LinkerConfig::DynObj == m_Config.codeGenType()))
    174     dt_flags |= llvm::ELF::DF_STATIC_TLS;
    175 
    176   if ((m_Config.options().hasNewDTags() && 0x0 != dt_flags) ||
    177       0 != (dt_flags & llvm::ELF::DF_STATIC_TLS))
    178     reserveOne(llvm::ELF::DT_FLAGS); // DT_FLAGS
    179 
    180   if (m_Backend.hasTextRel())
    181     reserveOne(llvm::ELF::DT_TEXTREL); // DT_TEXTREL
    182 
    183   if (m_Config.options().hasNow()          ||
    184       m_Config.options().hasLoadFltr()     ||
    185       m_Config.options().hasOrigin()       ||
    186       m_Config.options().hasInterPose()    ||
    187       m_Config.options().hasNoDefaultLib() ||
    188       m_Config.options().hasNoDump()       ||
    189       m_Config.options().Bgroup()          ||
    190       ((LinkerConfig::DynObj == m_Config.codeGenType()) &&
    191        (m_Config.options().hasNoDelete()  ||
    192         m_Config.options().hasInitFirst() ||
    193         m_Config.options().hasNoDLOpen()))) {
    194     reserveOne(llvm::ELF::DT_FLAGS_1); // DT_FLAGS_1
    195   }
    196 
    197   reserveOne(llvm::ELF::DT_NULL); // for DT_NULL
    198 }
    199 
    200 /// applyEntries - apply entries
    201 void ELFDynamic::applyEntries(const ELFFileFormat& pFormat)
    202 {
    203   if (LinkerConfig::DynObj == m_Config.codeGenType() &&
    204       m_Config.options().Bsymbolic()) {
    205       applyOne(llvm::ELF::DT_SYMBOLIC, 0x0); // DT_SYMBOLIC
    206   }
    207 
    208   if (pFormat.hasInit())
    209     applyOne(llvm::ELF::DT_INIT, pFormat.getInit().addr()); // DT_INIT
    210 
    211   if (pFormat.hasFini())
    212     applyOne(llvm::ELF::DT_FINI, pFormat.getFini().addr()); // DT_FINI
    213 
    214   if (pFormat.hasInitArray()) {
    215     // DT_INIT_ARRAY
    216     applyOne(llvm::ELF::DT_INIT_ARRAY, pFormat.getInitArray().addr());
    217 
    218     // DT_INIT_ARRAYSZ
    219     applyOne(llvm::ELF::DT_INIT_ARRAYSZ, pFormat.getInitArray().size());
    220   }
    221 
    222   if (pFormat.hasFiniArray()) {
    223     // DT_FINI_ARRAY
    224     applyOne(llvm::ELF::DT_FINI_ARRAY, pFormat.getFiniArray().addr());
    225 
    226     // DT_FINI_ARRAYSZ
    227     applyOne(llvm::ELF::DT_FINI_ARRAYSZ, pFormat.getFiniArray().size());
    228   }
    229 
    230   if (pFormat.hasHashTab())
    231     applyOne(llvm::ELF::DT_HASH, pFormat.getHashTab().addr()); // DT_HASH
    232 
    233   // FIXME: use llvm enum constant
    234   if (pFormat.hasGNUHashTab())
    235     applyOne(0x6ffffef5, pFormat.getGNUHashTab().addr()); // DT_GNU_HASH
    236 
    237   if (pFormat.hasDynSymTab()) {
    238     applyOne(llvm::ELF::DT_SYMTAB, pFormat.getDynSymTab().addr()); // DT_SYMTAB
    239     applyOne(llvm::ELF::DT_SYMENT, symbolSize()); // DT_SYMENT
    240   }
    241 
    242   if (pFormat.hasDynStrTab()) {
    243     applyOne(llvm::ELF::DT_STRTAB, pFormat.getDynStrTab().addr()); // DT_STRTAB
    244     applyOne(llvm::ELF::DT_STRSZ, pFormat.getDynStrTab().size()); // DT_STRSZ
    245   }
    246 
    247   applyTargetEntries(pFormat); // DT_PLTGOT
    248 
    249   if (pFormat.hasRelPlt()) {
    250     applyOne(llvm::ELF::DT_PLTREL, llvm::ELF::DT_REL); // DT_PLTREL
    251     applyOne(llvm::ELF::DT_JMPREL, pFormat.getRelPlt().addr()); // DT_JMPREL
    252     applyOne(llvm::ELF::DT_PLTRELSZ, pFormat.getRelPlt().size()); // DT_PLTRELSZ
    253   }
    254   else if (pFormat.hasRelaPlt()) {
    255     applyOne(llvm::ELF::DT_PLTREL, llvm::ELF::DT_RELA); // DT_PLTREL
    256     applyOne(llvm::ELF::DT_JMPREL, pFormat.getRelaPlt().addr()); // DT_JMPREL
    257     applyOne(llvm::ELF::DT_PLTRELSZ, pFormat.getRelaPlt().size()); // DT_PLTRELSZ
    258   }
    259 
    260   if (pFormat.hasRelDyn()) {
    261     applyOne(llvm::ELF::DT_REL, pFormat.getRelDyn().addr()); // DT_REL
    262     applyOne(llvm::ELF::DT_RELSZ, pFormat.getRelDyn().size()); // DT_RELSZ
    263     applyOne(llvm::ELF::DT_RELENT, m_pEntryFactory->relSize()); // DT_RELENT
    264   }
    265 
    266   if (pFormat.hasRelaDyn()) {
    267     applyOne(llvm::ELF::DT_RELA, pFormat.getRelaDyn().addr()); // DT_RELA
    268     applyOne(llvm::ELF::DT_RELASZ, pFormat.getRelaDyn().size()); // DT_RELASZ
    269     applyOne(llvm::ELF::DT_RELAENT, m_pEntryFactory->relaSize()); // DT_RELAENT
    270   }
    271 
    272   if (m_Backend.hasTextRel()) {
    273     applyOne(llvm::ELF::DT_TEXTREL, 0x0); // DT_TEXTREL
    274 
    275     if (m_Config.options().warnSharedTextrel() &&
    276         LinkerConfig::DynObj == m_Config.codeGenType())
    277       mcld::warning(mcld::diag::warn_shared_textrel);
    278   }
    279 
    280   uint64_t dt_flags = 0x0;
    281   if (m_Config.options().hasOrigin())
    282     dt_flags |= llvm::ELF::DF_ORIGIN;
    283   if (m_Config.options().Bsymbolic())
    284     dt_flags |= llvm::ELF::DF_SYMBOLIC;
    285   if (m_Config.options().hasNow())
    286     dt_flags |= llvm::ELF::DF_BIND_NOW;
    287   if (m_Backend.hasTextRel())
    288     dt_flags |= llvm::ELF::DF_TEXTREL;
    289   if (m_Backend.hasStaticTLS() &&
    290       (LinkerConfig::DynObj == m_Config.codeGenType()))
    291     dt_flags |= llvm::ELF::DF_STATIC_TLS;
    292 
    293   if ((m_Config.options().hasNewDTags() && 0x0 != dt_flags) ||
    294       0 != (dt_flags & llvm::ELF::DF_STATIC_TLS))
    295     applyOne(llvm::ELF::DT_FLAGS, dt_flags); // DT_FLAGS
    296 
    297   uint64_t dt_flags_1 = 0x0;
    298   if (m_Config.options().hasNow())
    299     dt_flags_1 |= llvm::ELF::DF_1_NOW;
    300   if (m_Config.options().hasLoadFltr())
    301     dt_flags_1 |= llvm::ELF::DF_1_LOADFLTR;
    302   if (m_Config.options().hasOrigin())
    303     dt_flags_1 |= llvm::ELF::DF_1_ORIGIN;
    304   if (m_Config.options().hasInterPose())
    305     dt_flags_1 |= llvm::ELF::DF_1_INTERPOSE;
    306   if (m_Config.options().hasNoDefaultLib())
    307     dt_flags_1 |= llvm::ELF::DF_1_NODEFLIB;
    308   if (m_Config.options().hasNoDump())
    309     dt_flags_1 |= llvm::ELF::DF_1_NODUMP;
    310   if (m_Config.options().Bgroup())
    311     dt_flags_1 |= llvm::ELF::DF_1_GROUP;
    312   if (LinkerConfig::DynObj == m_Config.codeGenType()) {
    313     if (m_Config.options().hasNoDelete())
    314       dt_flags_1 |= llvm::ELF::DF_1_NODELETE;
    315     if (m_Config.options().hasInitFirst())
    316       dt_flags_1 |= llvm::ELF::DF_1_INITFIRST;
    317     if (m_Config.options().hasNoDLOpen())
    318       dt_flags_1 |= llvm::ELF::DF_1_NOOPEN;
    319   }
    320   if (0x0 != dt_flags_1)
    321     applyOne(llvm::ELF::DT_FLAGS_1, dt_flags_1); // DT_FLAGS_1
    322 
    323   applyOne(llvm::ELF::DT_NULL, 0x0); // for DT_NULL
    324 }
    325 
    326 /// symbolSize
    327 size_t ELFDynamic::symbolSize() const
    328 {
    329   return m_pEntryFactory->symbolSize();
    330 }
    331 
    332 /// reserveNeedEntry - reserve on DT_NEED entry.
    333 void ELFDynamic::reserveNeedEntry()
    334 {
    335   m_NeedList.push_back(m_pEntryFactory->clone());
    336 }
    337 
    338 /// emit
    339 void ELFDynamic::emit(const LDSection& pSection, MemoryRegion& pRegion) const
    340 {
    341   if (pRegion.size() < pSection.size()) {
    342     llvm::report_fatal_error(llvm::Twine("the given memory is smaller") +
    343                              llvm::Twine(" than the section's demaind.\n"));
    344   }
    345 
    346   uint8_t* address = (uint8_t*)pRegion.start();
    347   EntryListType::const_iterator entry, entryEnd = m_NeedList.end();
    348   for (entry = m_NeedList.begin(); entry != entryEnd; ++entry)
    349     address += (*entry)->emit(address);
    350 
    351   entryEnd = m_EntryList.end();
    352   for (entry = m_EntryList.begin(); entry != entryEnd; ++entry)
    353     address += (*entry)->emit(address);
    354 }
    355 
    356 void ELFDynamic::applySoname(uint64_t pStrTabIdx)
    357 {
    358   applyOne(llvm::ELF::DT_SONAME, pStrTabIdx); // DT_SONAME
    359 }
    360 
    361