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 return ResolveInfo::Global; 91 case llvm::ELF::STB_WEAK: 92 return ResolveInfo::Weak; 93 } 94 95 if (pShndx == llvm::ELF::SHN_ABS) 96 return ResolveInfo::Absolute; 97 98 return ResolveInfo::NoneBinding; 99 } 100 101 /// getSymFragmentRef 102 FragmentRef* 103 ELFReaderIF::getSymFragmentRef(Input& pInput, 104 uint16_t pShndx, 105 uint32_t pOffset) const 106 { 107 108 if (Input::DynObj == pInput.type()) 109 return FragmentRef::Null(); 110 111 if (pShndx == llvm::ELF::SHN_UNDEF) 112 return FragmentRef::Null(); 113 114 if (pShndx >= llvm::ELF::SHN_LORESERVE) // including ABS and COMMON 115 return FragmentRef::Null(); 116 117 LDSection* sect_hdr = pInput.context()->getSection(pShndx); 118 119 if (NULL == sect_hdr) 120 unreachable(diag::unreachable_invalid_section_idx) << pShndx 121 << pInput.path().native(); 122 123 if (LDFileFormat::Ignore == sect_hdr->kind()) 124 return FragmentRef::Null(); 125 126 if (LDFileFormat::Group == sect_hdr->kind()) 127 return FragmentRef::Null(); 128 129 return FragmentRef::Create(*sect_hdr, pOffset); 130 } 131 132 /// getSymVisibility 133 ResolveInfo::Visibility 134 ELFReaderIF::getSymVisibility(uint8_t pVis) const 135 { 136 return static_cast<ResolveInfo::Visibility>(pVis); 137 } 138 139 /// getSymValue - get the section offset of the symbol. 140 uint64_t ELFReaderIF::getSymValue(uint64_t pValue, 141 uint16_t pShndx, 142 const Input& pInput) const 143 { 144 if (Input::Object == pInput.type()) { 145 // In relocatable files, st_value holds alignment constraints for a symbol 146 // whose section index is SHN_COMMON 147 if (pShndx == llvm::ELF::SHN_COMMON || pShndx == llvm::ELF::SHN_ABS) { 148 return pValue; 149 } 150 151 // In relocatable files, st_value holds a section offset for a defined symbol. 152 // TODO: 153 // if --just-symbols option are enabled, convert the value from section offset 154 // to virtual address by adding input section's virtual address. 155 // The section's virtual address in relocatable files is normally zero, but 156 // people can use link script to change it. 157 return pValue; 158 } 159 160 // In executable and shared object files, st_value holds a virtual address. 161 // the virtual address is useless during linking. 162 return 0x0; 163 } 164 165