1 //===- subzero/src/IceELFSection.cpp - Representation of ELF sections -----===// 2 // 3 // The Subzero Code Generator 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// 10 /// \file 11 /// \brief Defines how ELF sections are represented. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #include "IceELFSection.h" 16 17 #include "IceDefs.h" 18 #include "IceELFStreamer.h" 19 #include "llvm/Support/MathExtras.h" 20 21 using namespace llvm::ELF; 22 23 namespace Ice { 24 25 // Text sections. 26 27 void ELFTextSection::appendData(ELFStreamer &Str, 28 const llvm::StringRef MoreData) { 29 Str.writeBytes(MoreData); 30 Header.sh_size += MoreData.size(); 31 } 32 33 // Data sections. 34 35 void ELFDataSection::appendData(ELFStreamer &Str, 36 const llvm::StringRef MoreData) { 37 Str.writeBytes(MoreData); 38 Header.sh_size += MoreData.size(); 39 } 40 41 void ELFDataSection::appendZeros(ELFStreamer &Str, SizeT NumBytes) { 42 Str.writeZeroPadding(NumBytes); 43 Header.sh_size += NumBytes; 44 } 45 46 void ELFDataSection::appendRelocationOffset(ELFStreamer &Str, bool IsRela, 47 RelocOffsetT RelocOffset) { 48 const SizeT RelocAddrSize = typeWidthInBytes(getPointerType()); 49 if (IsRela) { 50 appendZeros(Str, RelocAddrSize); 51 return; 52 } 53 assert(RelocAddrSize == 4 && " writeLE32 assumes RelocAddrSize is 4"); 54 Str.writeLE32(RelocOffset); 55 Header.sh_size += RelocAddrSize; 56 } 57 58 void ELFDataSection::padToAlignment(ELFStreamer &Str, Elf64_Xword Align) { 59 assert(llvm::isPowerOf2_32(Align)); 60 Elf64_Xword AlignDiff = Utils::OffsetToAlignment(Header.sh_size, Align); 61 if (AlignDiff == 0) 62 return; 63 if (Header.sh_type != llvm::ELF::SHT_NOBITS) 64 Str.writeZeroPadding(AlignDiff); 65 Header.sh_size += AlignDiff; 66 } 67 68 // Relocation sections. 69 70 void ELFRelocationSection::addRelocations(RelocOffsetT BaseOff, 71 const FixupRefList &FixupRefs, 72 ELFSymbolTableSection *SymTab) { 73 for (const AssemblerFixup *FR : FixupRefs) { 74 Fixups.push_back(*FR); 75 AssemblerFixup &F = Fixups.back(); 76 F.set_position(BaseOff + F.position()); 77 assert(!F.valueIsSymbol()); 78 if (!F.isNullSymbol()) { 79 // Do an early lookup in the symbol table. If the symbol is found, 80 // replace the Constant in the symbol with the ELFSym, and calculate the 81 // final value of the addend. As such, a local label allocated from the 82 // Assembler arena will be converted to a symbol before the Assembler 83 // arena goes away. 84 if (const ELFSym *Sym = SymTab->findSymbol(F.symbol())) { 85 F.set_addend(F.offset()); 86 F.set_value(Sym); 87 } 88 } 89 } 90 } 91 92 size_t ELFRelocationSection::getSectionDataSize() const { 93 return Fixups.size() * Header.sh_entsize; 94 } 95 96 // Symbol tables. 97 98 void ELFSymbolTableSection::createNullSymbol(ELFSection *NullSection, 99 GlobalContext *Ctx) { 100 // The first entry in the symbol table should be a NULL entry, so make sure 101 // the map is still empty. 102 assert(LocalSymbols.empty()); 103 // Explicitly set the null symbol name to the empty string, so that 104 // GlobalString::operator<() orders the null string first. 105 NullSymbolName = GlobalString::createWithString(Ctx, ""); 106 createDefinedSym(NullSymbolName, STT_NOTYPE, STB_LOCAL, NullSection, 0, 0); 107 NullSymbol = findSymbol(NullSymbolName); 108 } 109 110 void ELFSymbolTableSection::createDefinedSym(GlobalString Name, uint8_t Type, 111 uint8_t Binding, 112 ELFSection *Section, 113 RelocOffsetT Offset, SizeT Size) { 114 ELFSym NewSymbol = ELFSym(); 115 NewSymbol.Sym.setBindingAndType(Binding, Type); 116 NewSymbol.Sym.st_value = Offset; 117 NewSymbol.Sym.st_size = Size; 118 NewSymbol.Section = Section; 119 NewSymbol.Number = ELFSym::UnknownNumber; 120 bool Unique; 121 if (Binding == STB_LOCAL) 122 Unique = LocalSymbols.insert(std::make_pair(Name, NewSymbol)).second; 123 else 124 Unique = GlobalSymbols.insert(std::make_pair(Name, NewSymbol)).second; 125 assert(Unique); 126 (void)Unique; 127 } 128 129 void ELFSymbolTableSection::noteUndefinedSym(GlobalString Name, 130 ELFSection *NullSection) { 131 ELFSym NewSymbol = ELFSym(); 132 NewSymbol.Sym.setBindingAndType(STB_GLOBAL, STT_NOTYPE); 133 NewSymbol.Section = NullSection; 134 NewSymbol.Number = ELFSym::UnknownNumber; 135 bool Unique = GlobalSymbols.insert(std::make_pair(Name, NewSymbol)).second; 136 if (!Unique) { 137 std::string Buffer; 138 llvm::raw_string_ostream StrBuf(Buffer); 139 StrBuf << "Symbol external and defined: " << Name; 140 llvm::report_fatal_error(StrBuf.str()); 141 } 142 (void)Unique; 143 } 144 145 const ELFSym *ELFSymbolTableSection::findSymbol(GlobalString Name) const { 146 auto I = LocalSymbols.find(Name); 147 if (I != LocalSymbols.end()) 148 return &I->second; 149 I = GlobalSymbols.find(Name); 150 if (I != GlobalSymbols.end()) 151 return &I->second; 152 return nullptr; 153 } 154 155 void ELFSymbolTableSection::updateIndices(const ELFStringTableSection *StrTab) { 156 SizeT SymNumber = 0; 157 for (auto &KeyValue : LocalSymbols) { 158 GlobalString Name = KeyValue.first; 159 ELFSection *Section = KeyValue.second.Section; 160 Elf64_Sym &SymInfo = KeyValue.second.Sym; 161 if (Name != NullSymbolName && Name.hasStdString()) 162 SymInfo.st_name = StrTab->getIndex(Name.toString()); 163 SymInfo.st_shndx = Section->getNumber(); 164 KeyValue.second.setNumber(SymNumber++); 165 } 166 for (auto &KeyValue : GlobalSymbols) { 167 const std::string &Name = KeyValue.first.toString(); 168 ELFSection *Section = KeyValue.second.Section; 169 Elf64_Sym &SymInfo = KeyValue.second.Sym; 170 if (!Name.empty()) 171 SymInfo.st_name = StrTab->getIndex(Name); 172 SymInfo.st_shndx = Section->getNumber(); 173 KeyValue.second.setNumber(SymNumber++); 174 } 175 } 176 177 void ELFSymbolTableSection::writeData(ELFStreamer &Str, bool IsELF64) { 178 if (IsELF64) { 179 writeSymbolMap<true>(Str, LocalSymbols); 180 writeSymbolMap<true>(Str, GlobalSymbols); 181 } else { 182 writeSymbolMap<false>(Str, LocalSymbols); 183 writeSymbolMap<false>(Str, GlobalSymbols); 184 } 185 } 186 187 // String tables. 188 189 void ELFStringTableSection::add(const std::string &Str) { 190 assert(!isLaidOut()); 191 assert(!Str.empty()); 192 StringToIndexMap.insert(std::make_pair(Str, UnknownIndex)); 193 } 194 195 size_t ELFStringTableSection::getIndex(const std::string &Str) const { 196 assert(isLaidOut()); 197 StringToIndexType::const_iterator It = StringToIndexMap.find(Str); 198 if (It == StringToIndexMap.end()) { 199 llvm::report_fatal_error("String index not found: " + Str); 200 return UnknownIndex; 201 } 202 return It->second; 203 } 204 205 bool ELFStringTableSection::SuffixComparator:: 206 operator()(const std::string &StrA, const std::string &StrB) const { 207 size_t LenA = StrA.size(); 208 size_t LenB = StrB.size(); 209 size_t CommonLen = std::min(LenA, LenB); 210 // If there is a difference in the common suffix, use that diff to sort. 211 for (size_t i = 0; i < CommonLen; ++i) { 212 char a = StrA[LenA - i - 1]; 213 char b = StrB[LenB - i - 1]; 214 if (a != b) 215 return a > b; 216 } 217 // If the common suffixes are completely equal, let the longer one come 218 // first, so that it can be laid out first and its characters shared. 219 return LenA > LenB; 220 } 221 222 void ELFStringTableSection::doLayout() { 223 assert(!isLaidOut()); 224 llvm::StringRef Prev; 225 226 // String table starts with 0 byte. 227 StringData.push_back(0); 228 229 for (auto &StringIndex : StringToIndexMap) { 230 assert(StringIndex.second == UnknownIndex); 231 llvm::StringRef Cur = llvm::StringRef(StringIndex.first); 232 if (Prev.endswith(Cur)) { 233 // Prev is already in the StringData, and Cur is shorter than Prev based 234 // on the sort. 235 StringIndex.second = StringData.size() - Cur.size() - 1; 236 continue; 237 } 238 StringIndex.second = StringData.size(); 239 std::copy(Cur.begin(), Cur.end(), back_inserter(StringData)); 240 StringData.push_back(0); 241 Prev = Cur; 242 } 243 } 244 245 } // end of namespace Ice 246