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