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     if (pShndx == llvm::ELF::SHN_ABS)
     91       return ResolveInfo::Absolute;
     92     return ResolveInfo::Global;
     93   case llvm::ELF::STB_WEAK:
     94     return ResolveInfo::Weak;
     95   }
     96 
     97   return ResolveInfo::NoneBinding;
     98 }
     99 
    100 /// getSymFragmentRef
    101 FragmentRef*
    102 ELFReaderIF::getSymFragmentRef(Input& pInput,
    103                                uint16_t pShndx,
    104                                uint32_t pOffset) const
    105 {
    106 
    107   if (Input::DynObj == pInput.type())
    108     return FragmentRef::Null();
    109 
    110   if (pShndx == llvm::ELF::SHN_UNDEF)
    111     return FragmentRef::Null();
    112 
    113   if (pShndx >= llvm::ELF::SHN_LORESERVE) // including ABS and COMMON
    114     return FragmentRef::Null();
    115 
    116   LDSection* sect_hdr = pInput.context()->getSection(pShndx);
    117 
    118   if (NULL == sect_hdr)
    119     unreachable(diag::unreachable_invalid_section_idx) << pShndx
    120                                                        << pInput.path().native();
    121 
    122   if (LDFileFormat::Ignore == sect_hdr->kind())
    123     return FragmentRef::Null();
    124 
    125   if (LDFileFormat::Group == sect_hdr->kind())
    126     return FragmentRef::Null();
    127 
    128   return FragmentRef::Create(*sect_hdr, pOffset);
    129 }
    130 
    131 /// getSymVisibility
    132 ResolveInfo::Visibility
    133 ELFReaderIF::getSymVisibility(uint8_t pVis) const
    134 {
    135   return static_cast<ResolveInfo::Visibility>(pVis);
    136 }
    137 
    138 /// getSymValue - get the section offset of the symbol.
    139 uint64_t ELFReaderIF::getSymValue(uint64_t pValue,
    140                                   uint16_t pShndx,
    141                                   const Input& pInput) const
    142 {
    143   if (Input::Object == pInput.type()) {
    144     // In relocatable files, st_value holds alignment constraints for a symbol
    145     // whose section index is SHN_COMMON
    146     if (pShndx == llvm::ELF::SHN_COMMON || pShndx == llvm::ELF::SHN_ABS) {
    147       return pValue;
    148     }
    149 
    150     // In relocatable files, st_value holds a section offset for a defined symbol.
    151     // TODO:
    152     // if --just-symbols option are enabled, convert the value from section offset
    153     // to virtual address by adding input section's virtual address.
    154     // The section's virtual address in relocatable files is normally zero, but
    155     // people can use link script to change it.
    156     return pValue;
    157   }
    158 
    159   // In executable and shared object files, st_value holds a virtual address.
    160   // the virtual address is needed for alias identification.
    161   return pValue;
    162 }
    163 
    164