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