Home | History | Annotate | Download | only in LD
      1 //===- ELFReader.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 <mcld/LD/ELFReaderIf.h>
     10 
     11 #include <mcld/IRBuilder.h>
     12 #include <mcld/Fragment/FillFragment.h>
     13 #include <mcld/LD/EhFrame.h>
     14 #include <mcld/LD/SectionData.h>
     15 #include <mcld/Target/GNULDBackend.h>
     16 //#include <mcld/Support/MemoryArea.h>
     17 //#include <mcld/Support/MemoryRegion.h>
     18 //#include <mcld/Support/MsgHandling.h>
     19 //#include <mcld/Object/ObjectBuilder.h>
     20 
     21 #include <cstring>
     22 
     23 #include <llvm/ADT/StringRef.h>
     24 #include <llvm/ADT/Twine.h>
     25 #include <llvm/Support/ELF.h>
     26 #include <llvm/Support/Host.h>
     27 
     28 using namespace mcld;
     29 
     30 //===----------------------------------------------------------------------===//
     31 // ELFReaderIF
     32 //===----------------------------------------------------------------------===//
     33 /// getSymType
     34 ResolveInfo::Type ELFReaderIF::getSymType(uint8_t pInfo, uint16_t pShndx) const
     35 {
     36   ResolveInfo::Type result = static_cast<ResolveInfo::Type>(pInfo & 0xF);
     37   if (llvm::ELF::SHN_ABS == pShndx && ResolveInfo::Section == result) {
     38     // In Mips, __gp_disp is a special section symbol. Its name comes from
     39     // .strtab, not .shstrtab. However, it is unique. Only it is also a ABS
     40     // symbol. So here is a tricky to identify __gp_disp and convert it to
     41     // Object symbol.
     42     return ResolveInfo::Object;
     43   }
     44 
     45   return result;
     46 }
     47 
     48 /// getSymDesc
     49 ResolveInfo::Desc ELFReaderIF::getSymDesc(uint16_t pShndx, const Input& pInput) const
     50 {
     51   if (pShndx == llvm::ELF::SHN_UNDEF)
     52     return ResolveInfo::Undefined;
     53 
     54   if (pShndx < llvm::ELF::SHN_LORESERVE) {
     55     // an ELF symbol defined in a section which we are not including
     56     // must be treated as an Undefined.
     57     // @ref Google gold linker: symtab.cc: 1086
     58     if (NULL == pInput.context()->getSection(pShndx) ||
     59         LDFileFormat::Ignore == pInput.context()->getSection(pShndx)->kind())
     60       return ResolveInfo::Undefined;
     61     return ResolveInfo::Define;
     62   }
     63 
     64   if (pShndx == llvm::ELF::SHN_ABS)
     65     return ResolveInfo::Define;
     66 
     67   if (pShndx == llvm::ELF::SHN_COMMON)
     68     return ResolveInfo::Common;
     69 
     70   if (pShndx >= llvm::ELF::SHN_LOPROC &&
     71       pShndx <= llvm::ELF::SHN_HIPROC)
     72     return target().getSymDesc(pShndx);
     73 
     74   // FIXME: ELF weak alias should be ResolveInfo::Indirect
     75   return ResolveInfo::NoneDesc;
     76 }
     77 
     78 /// getSymBinding
     79 ResolveInfo::Binding
     80 ELFReaderIF::getSymBinding(uint8_t pBinding, uint16_t pShndx, uint8_t pVis) const
     81 {
     82 
     83   // TODO:
     84   // if --just-symbols option is enabled, the symbol must covert to Absolute
     85 
     86   switch(pBinding) {
     87   case llvm::ELF::STB_LOCAL:
     88     return ResolveInfo::Local;
     89   case llvm::ELF::STB_GLOBAL:
     90     return ResolveInfo::Global;
     91   case llvm::ELF::STB_WEAK:
     92     return ResolveInfo::Weak;
     93   }
     94 
     95   if (pShndx == llvm::ELF::SHN_ABS)
     96     return ResolveInfo::Absolute;
     97 
     98   return ResolveInfo::NoneBinding;
     99 }
    100 
    101 /// getSymFragmentRef
    102 FragmentRef*
    103 ELFReaderIF::getSymFragmentRef(Input& pInput,
    104                                uint16_t pShndx,
    105                                uint32_t pOffset) const
    106 {
    107 
    108   if (Input::DynObj == pInput.type())
    109     return FragmentRef::Null();
    110 
    111   if (pShndx == llvm::ELF::SHN_UNDEF)
    112     return FragmentRef::Null();
    113 
    114   if (pShndx >= llvm::ELF::SHN_LORESERVE) // including ABS and COMMON
    115     return FragmentRef::Null();
    116 
    117   LDSection* sect_hdr = pInput.context()->getSection(pShndx);
    118 
    119   if (NULL == sect_hdr)
    120     unreachable(diag::unreachable_invalid_section_idx) << pShndx
    121                                                        << pInput.path().native();
    122 
    123   if (LDFileFormat::Ignore == sect_hdr->kind())
    124     return FragmentRef::Null();
    125 
    126   if (LDFileFormat::Group == sect_hdr->kind())
    127     return FragmentRef::Null();
    128 
    129   return FragmentRef::Create(*sect_hdr, pOffset);
    130 }
    131 
    132 /// getSymVisibility
    133 ResolveInfo::Visibility
    134 ELFReaderIF::getSymVisibility(uint8_t pVis) const
    135 {
    136   return static_cast<ResolveInfo::Visibility>(pVis);
    137 }
    138 
    139 /// getSymValue - get the section offset of the symbol.
    140 uint64_t ELFReaderIF::getSymValue(uint64_t pValue,
    141                                   uint16_t pShndx,
    142                                   const Input& pInput) const
    143 {
    144   if (Input::Object == pInput.type()) {
    145     // In relocatable files, st_value holds alignment constraints for a symbol
    146     // whose section index is SHN_COMMON
    147     if (pShndx == llvm::ELF::SHN_COMMON || pShndx == llvm::ELF::SHN_ABS) {
    148       return pValue;
    149     }
    150 
    151     // In relocatable files, st_value holds a section offset for a defined symbol.
    152     // TODO:
    153     // if --just-symbols option are enabled, convert the value from section offset
    154     // to virtual address by adding input section's virtual address.
    155     // The section's virtual address in relocatable files is normally zero, but
    156     // people can use link script to change it.
    157     return pValue;
    158   }
    159 
    160   // In executable and shared object files, st_value holds a virtual address.
    161   // the virtual address is useless during linking.
    162   return 0x0;
    163 }
    164 
    165