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 28using namespace mcld; 29 30//===----------------------------------------------------------------------===// 31// ELFReaderIF 32//===----------------------------------------------------------------------===// 33/// getSymType 34ResolveInfo::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 49ResolveInfo::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 79ResolveInfo::Binding 80ELFReaderIF::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 101FragmentRef* 102ELFReaderIF::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 132ResolveInfo::Visibility 133ELFReaderIF::getSymVisibility(uint8_t pVis) const 134{ 135 return static_cast<ResolveInfo::Visibility>(pVis); 136} 137 138/// getSymValue - get the section offset of the symbol. 139uint64_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