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 25namespace mcld { 26 27//===----------------------------------------------------------------------===// 28// ELFReaderIF 29//===----------------------------------------------------------------------===// 30/// getSymType 31ResolveInfo::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 46ResolveInfo::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 74ResolveInfo::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 95FragmentRef* 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 123ResolveInfo::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. 128uint64_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