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