Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 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 | //===----------------------------------------------------------------------===// |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 9 | /// |
| 10 | /// \file |
Jim Stichnoth | 92a6e5b | 2015-12-02 16:52:44 -0800 | [diff] [blame] | 11 | /// \brief Defines how ELF sections are represented. |
Andrew Scull | 9612d32 | 2015-07-06 14:53:25 -0700 | [diff] [blame] | 12 | /// |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 13 | //===----------------------------------------------------------------------===// |
| 14 | |
John Porto | 67f8de9 | 2015-06-25 10:14:17 -0700 | [diff] [blame] | 15 | #include "IceELFSection.h" |
Jan Voung | 72984d8 | 2015-01-29 14:42:38 -0800 | [diff] [blame] | 16 | |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 17 | #include "IceDefs.h" |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 18 | #include "IceELFStreamer.h" |
John Porto | 67f8de9 | 2015-06-25 10:14:17 -0700 | [diff] [blame] | 19 | #include "llvm/Support/MathExtras.h" |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 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 | |
Jan Voung | 72984d8 | 2015-01-29 14:42:38 -0800 | [diff] [blame] | 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) { |
Nicolas Capens | 83425de | 2016-11-01 17:18:51 -0400 | [diff] [blame] | 48 | const SizeT RelocAddrSize = typeWidthInBytes(getPointerType()); |
Jan Voung | 72984d8 | 2015-01-29 14:42:38 -0800 | [diff] [blame] | 49 | if (IsRela) { |
| 50 | appendZeros(Str, RelocAddrSize); |
| 51 | return; |
| 52 | } |
Nicolas Capens | 83425de | 2016-11-01 17:18:51 -0400 | [diff] [blame] | 53 | assert(RelocAddrSize == 4 && " writeLE32 assumes RelocAddrSize is 4"); |
Jan Voung | 72984d8 | 2015-01-29 14:42:38 -0800 | [diff] [blame] | 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 | |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 68 | // Relocation sections. |
| 69 | |
Jan Voung | ec27073 | 2015-01-12 17:00:22 -0800 | [diff] [blame] | 70 | void ELFRelocationSection::addRelocations(RelocOffsetT BaseOff, |
Jim Stichnoth | 3e32400 | 2016-03-08 16:18:40 -0800 | [diff] [blame] | 71 | const FixupRefList &FixupRefs, |
| 72 | ELFSymbolTableSection *SymTab) { |
Jan Voung | ec27073 | 2015-01-12 17:00:22 -0800 | [diff] [blame] | 73 | for (const AssemblerFixup *FR : FixupRefs) { |
| 74 | Fixups.push_back(*FR); |
| 75 | AssemblerFixup &F = Fixups.back(); |
| 76 | F.set_position(BaseOff + F.position()); |
Jim Stichnoth | 3e32400 | 2016-03-08 16:18:40 -0800 | [diff] [blame] | 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 | } |
Jan Voung | ec27073 | 2015-01-12 17:00:22 -0800 | [diff] [blame] | 89 | } |
| 90 | } |
| 91 | |
Jan Voung | 261cae3 | 2015-02-01 10:31:03 -0800 | [diff] [blame] | 92 | size_t ELFRelocationSection::getSectionDataSize() const { |
| 93 | return Fixups.size() * Header.sh_entsize; |
Jan Voung | ec27073 | 2015-01-12 17:00:22 -0800 | [diff] [blame] | 94 | } |
| 95 | |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 96 | // Symbol tables. |
| 97 | |
Jim Stichnoth | 467ffe5 | 2016-03-29 15:01:06 -0700 | [diff] [blame] | 98 | void ELFSymbolTableSection::createNullSymbol(ELFSection *NullSection, |
| 99 | GlobalContext *Ctx) { |
Andrew Scull | 57e1268 | 2015-09-16 11:30:19 -0700 | [diff] [blame] | 100 | // The first entry in the symbol table should be a NULL entry, so make sure |
| 101 | // the map is still empty. |
Jan Voung | f644a4b | 2015-03-19 11:57:52 -0700 | [diff] [blame] | 102 | assert(LocalSymbols.empty()); |
Jim Stichnoth | 467ffe5 | 2016-03-29 15:01:06 -0700 | [diff] [blame] | 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); |
Jan Voung | f644a4b | 2015-03-19 11:57:52 -0700 | [diff] [blame] | 108 | } |
| 109 | |
Jim Stichnoth | 467ffe5 | 2016-03-29 15:01:06 -0700 | [diff] [blame] | 110 | void ELFSymbolTableSection::createDefinedSym(GlobalString Name, uint8_t Type, |
| 111 | uint8_t Binding, |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 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; |
Jan Voung | ec27073 | 2015-01-12 17:00:22 -0800 | [diff] [blame] | 118 | NewSymbol.Section = Section; |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 119 | NewSymbol.Number = ELFSym::UnknownNumber; |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 120 | bool Unique; |
Jan Voung | 72984d8 | 2015-01-29 14:42:38 -0800 | [diff] [blame] | 121 | if (Binding == STB_LOCAL) |
Jan Voung | ec27073 | 2015-01-12 17:00:22 -0800 | [diff] [blame] | 122 | Unique = LocalSymbols.insert(std::make_pair(Name, NewSymbol)).second; |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 123 | else |
Jan Voung | ec27073 | 2015-01-12 17:00:22 -0800 | [diff] [blame] | 124 | Unique = GlobalSymbols.insert(std::make_pair(Name, NewSymbol)).second; |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 125 | assert(Unique); |
Jim Stichnoth | dddaf9c | 2014-12-04 14:09:21 -0800 | [diff] [blame] | 126 | (void)Unique; |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 127 | } |
| 128 | |
Jim Stichnoth | 467ffe5 | 2016-03-29 15:01:06 -0700 | [diff] [blame] | 129 | void ELFSymbolTableSection::noteUndefinedSym(GlobalString Name, |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 130 | ELFSection *NullSection) { |
| 131 | ELFSym NewSymbol = ELFSym(); |
| 132 | NewSymbol.Sym.setBindingAndType(STB_GLOBAL, STT_NOTYPE); |
Jan Voung | ec27073 | 2015-01-12 17:00:22 -0800 | [diff] [blame] | 133 | NewSymbol.Section = NullSection; |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 134 | NewSymbol.Number = ELFSym::UnknownNumber; |
Jan Voung | f644a4b | 2015-03-19 11:57:52 -0700 | [diff] [blame] | 135 | bool Unique = GlobalSymbols.insert(std::make_pair(Name, NewSymbol)).second; |
Karl Schimpf | 57d31ac | 2015-10-07 09:53:12 -0700 | [diff] [blame] | 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 | } |
Jan Voung | f644a4b | 2015-03-19 11:57:52 -0700 | [diff] [blame] | 142 | (void)Unique; |
Jan Voung | ec27073 | 2015-01-12 17:00:22 -0800 | [diff] [blame] | 143 | } |
| 144 | |
Jim Stichnoth | 467ffe5 | 2016-03-29 15:01:06 -0700 | [diff] [blame] | 145 | const ELFSym *ELFSymbolTableSection::findSymbol(GlobalString Name) const { |
Jan Voung | ec27073 | 2015-01-12 17:00:22 -0800 | [diff] [blame] | 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; |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 153 | } |
| 154 | |
| 155 | void ELFSymbolTableSection::updateIndices(const ELFStringTableSection *StrTab) { |
| 156 | SizeT SymNumber = 0; |
| 157 | for (auto &KeyValue : LocalSymbols) { |
Jim Stichnoth | 467ffe5 | 2016-03-29 15:01:06 -0700 | [diff] [blame] | 158 | GlobalString Name = KeyValue.first; |
Jan Voung | ec27073 | 2015-01-12 17:00:22 -0800 | [diff] [blame] | 159 | ELFSection *Section = KeyValue.second.Section; |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 160 | Elf64_Sym &SymInfo = KeyValue.second.Sym; |
Jim Stichnoth | 467ffe5 | 2016-03-29 15:01:06 -0700 | [diff] [blame] | 161 | if (Name != NullSymbolName && Name.hasStdString()) |
| 162 | SymInfo.st_name = StrTab->getIndex(Name.toString()); |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 163 | SymInfo.st_shndx = Section->getNumber(); |
| 164 | KeyValue.second.setNumber(SymNumber++); |
| 165 | } |
| 166 | for (auto &KeyValue : GlobalSymbols) { |
Jim Stichnoth | 467ffe5 | 2016-03-29 15:01:06 -0700 | [diff] [blame] | 167 | const std::string &Name = KeyValue.first.toString(); |
Jan Voung | ec27073 | 2015-01-12 17:00:22 -0800 | [diff] [blame] | 168 | ELFSection *Section = KeyValue.second.Section; |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 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 | |
Jim Stichnoth | 467ffe5 | 2016-03-29 15:01:06 -0700 | [diff] [blame] | 189 | void ELFStringTableSection::add(const std::string &Str) { |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 190 | assert(!isLaidOut()); |
| 191 | assert(!Str.empty()); |
| 192 | StringToIndexMap.insert(std::make_pair(Str, UnknownIndex)); |
| 193 | } |
| 194 | |
Jim Stichnoth | 467ffe5 | 2016-03-29 15:01:06 -0700 | [diff] [blame] | 195 | size_t ELFStringTableSection::getIndex(const std::string &Str) const { |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 196 | assert(isLaidOut()); |
| 197 | StringToIndexType::const_iterator It = StringToIndexMap.find(Str); |
| 198 | if (It == StringToIndexMap.end()) { |
Jim Stichnoth | 467ffe5 | 2016-03-29 15:01:06 -0700 | [diff] [blame] | 199 | llvm::report_fatal_error("String index not found: " + Str); |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 200 | return UnknownIndex; |
| 201 | } |
| 202 | return It->second; |
| 203 | } |
| 204 | |
| 205 | bool ELFStringTableSection::SuffixComparator:: |
Jim Stichnoth | 467ffe5 | 2016-03-29 15:01:06 -0700 | [diff] [blame] | 206 | operator()(const std::string &StrA, const std::string &StrB) const { |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 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)) { |
Andrew Scull | 57e1268 | 2015-09-16 11:30:19 -0700 | [diff] [blame] | 233 | // Prev is already in the StringData, and Cur is shorter than Prev based |
| 234 | // on the sort. |
Jan Voung | 08c3bcd | 2014-12-01 17:55:16 -0800 | [diff] [blame] | 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 |