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