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