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 10#include <llvm/Support/ELF.h> 11#include <llvm/ADT/StringRef.h> 12#include <llvm/ADT/Twine.h> 13#include <llvm/Support/Host.h> 14#include <mcld/MC/MCLinker.h> 15#include <mcld/Support/MemoryArea.h> 16#include <mcld/Support/MemoryRegion.h> 17#include <mcld/LD/ELFReader.h> 18#include <mcld/Target/GNULDBackend.h> 19#include <cstring> 20 21using namespace mcld; 22 23//===----------------------------------------------------------------------===// 24// ELFReaderIF 25/// getLDSectionKind 26LDFileFormat::Kind 27ELFReaderIF::getLDSectionKind(uint32_t pType, const char* pName) const 28{ 29 // name rules 30 llvm::StringRef name(pName); 31 if (llvm::StringRef::npos != name.find(".debug")) 32 return LDFileFormat::Debug; 33 if (name.startswith(".comment")) 34 return LDFileFormat::MetaData; 35 if (name.startswith(".interp") || name.startswith(".dynamic")) 36 return LDFileFormat::Note; 37 if (name.startswith(".eh_frame") || 38 name.startswith(".eh_frame_hdr") || 39 name.startswith(".gcc_except_table")) 40 return LDFileFormat::Exception; 41 42 // type rules 43 switch(pType) { 44 case llvm::ELF::SHT_NULL: 45 return LDFileFormat::Null; 46 case llvm::ELF::SHT_INIT_ARRAY: 47 case llvm::ELF::SHT_FINI_ARRAY: 48 case llvm::ELF::SHT_PREINIT_ARRAY: 49 case llvm::ELF::SHT_PROGBITS: 50 return LDFileFormat::Regular; 51 case llvm::ELF::SHT_SYMTAB: 52 case llvm::ELF::SHT_DYNSYM: 53 case llvm::ELF::SHT_STRTAB: 54 return LDFileFormat::NamePool; 55 case llvm::ELF::SHT_RELA: 56 case llvm::ELF::SHT_REL: 57 return LDFileFormat::Relocation; 58 case llvm::ELF::SHT_NOBITS: 59 return LDFileFormat::BSS; 60 case llvm::ELF::SHT_DYNAMIC: 61 case llvm::ELF::SHT_NOTE: 62 return LDFileFormat::Note; 63 case llvm::ELF::SHT_HASH: 64 case llvm::ELF::SHT_SHLIB: 65 return LDFileFormat::MetaData; 66 case llvm::ELF::SHT_GROUP: 67 return LDFileFormat::Group; 68 case llvm::ELF::SHT_GNU_versym: 69 case llvm::ELF::SHT_GNU_verdef: 70 case llvm::ELF::SHT_GNU_verneed: 71 return LDFileFormat::Version; 72 default: 73 if ((pType >= llvm::ELF::SHT_LOPROC && pType <= llvm::ELF::SHT_HIPROC) || 74 (pType >= llvm::ELF::SHT_LOOS && pType <= llvm::ELF::SHT_HIOS) || 75 (pType >= llvm::ELF::SHT_LOUSER && pType <= llvm::ELF::SHT_HIUSER)) 76 return LDFileFormat::Target; 77 llvm::report_fatal_error(llvm::Twine("unsupported ELF section type: ") + 78 llvm::Twine(pType) + llvm::Twine(".\n")); 79 } 80 return LDFileFormat::MetaData; 81} 82 83/// getSymDesc 84ResolveInfo::Desc ELFReaderIF::getSymDesc(uint16_t pShndx, const Input& pInput) const 85{ 86 if (pShndx == llvm::ELF::SHN_UNDEF) 87 return ResolveInfo::Undefined; 88 89 if (pShndx < llvm::ELF::SHN_LORESERVE) { 90 // an ELF symbol defined in a section which we are not including 91 // must be treated as an Undefined. 92 // @ref Google gold linker: symtab.cc: 1086 93 if (NULL == pInput.context()->getSection(pShndx)) 94 return ResolveInfo::Undefined; 95 return ResolveInfo::Define; 96 } 97 98 if (pShndx == llvm::ELF::SHN_ABS) 99 return ResolveInfo::Define; 100 101 if (pShndx == llvm::ELF::SHN_COMMON) 102 return ResolveInfo::Common; 103 104 // FIXME: ELF weak alias should be ResolveInfo::Indirect 105 return ResolveInfo::NoneDesc; 106} 107 108/// getSymBinding 109ResolveInfo::Binding 110ELFReaderIF::getSymBinding(uint8_t pBinding, uint16_t pShndx, uint8_t pVis) const 111{ 112 113 // TODO: 114 // if --just-symbols option is enabled, the symbol must covert to Absolute 115 116 switch(pBinding) { 117 case llvm::ELF::STB_LOCAL: 118 return ResolveInfo::Local; 119 case llvm::ELF::STB_GLOBAL: 120 return ResolveInfo::Global; 121 case llvm::ELF::STB_WEAK: 122 return ResolveInfo::Weak; 123 } 124 125 if (pShndx == llvm::ELF::SHN_ABS) 126 return ResolveInfo::Absolute; 127 128 return ResolveInfo::NoneBinding; 129} 130 131/// getSymFragmentRef 132MCFragmentRef* 133ELFReaderIF::getSymFragmentRef(Input& pInput, 134 MCLinker& pLinker, 135 uint16_t pShndx, 136 uint32_t pOffset) const 137{ 138 139 if (pShndx == llvm::ELF::SHN_UNDEF || pShndx >= llvm::ELF::SHN_LORESERVE) 140 return NULL; 141 142 LDSection* sect_hdr = pInput.context()->getSection(pShndx); 143 144 if (NULL == sect_hdr) { 145 llvm::report_fatal_error(llvm::Twine("section[") + 146 llvm::Twine(pShndx) + 147 llvm::Twine("] is invalid in file `") + 148 pInput.path().native() + 149 llvm::Twine("'.\n")); 150 } 151 152 MCFragmentRef* result = pLinker.getLayout().getFragmentRef(*sect_hdr, pOffset); 153 return result; 154} 155 156/// getSymVisibility 157ResolveInfo::Visibility 158ELFReaderIF::getSymVisibility(uint8_t pVis) const 159{ 160 return static_cast<ResolveInfo::Visibility>(pVis); 161} 162 163/// getSymValue - get the section offset of the symbol. 164uint64_t ELFReaderIF::getSymValue(uint64_t pValue, 165 uint16_t pShndx, 166 const Input& pInput) const 167{ 168 if (Input::Object == pInput.type()) { 169 // In relocatable files, st_value holds alignment constraints for a symbol 170 // whose section index is SHN_COMMON 171 if (pShndx == llvm::ELF::SHN_COMMON || pShndx == llvm::ELF::SHN_ABS) { 172 return pValue; 173 } 174 175 // In relocatable files, st_value holds a section offset for a defined symbol. 176 // TODO: 177 // if --just-symbols option are enabled, convert the value from section offset 178 // to virtual address by adding input section's virtual address. 179 // The section's virtual address in relocatable files is normally zero, but 180 // people can use link script to change it. 181 return pValue; 182 } 183 184 // In executable and shared object files, st_value holds a virtual address. 185 // the virtual address is useless during linking. 186 return 0x0; 187} 188 189