ELFReaderIf.cpp revision 6f75755c9204b1d8817ae5a65a2f7e5af0ec3f70
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 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 102FragmentRef* 103ELFReaderIF::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 133ResolveInfo::Visibility 134ELFReaderIF::getSymVisibility(uint8_t pVis) const 135{ 136 return static_cast<ResolveInfo::Visibility>(pVis); 137} 138 139/// getSymValue - get the section offset of the symbol. 140uint64_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