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