|  | //===- subzero/src/IceELFSection.cpp - Representation of ELF sections -----===// | 
|  | // | 
|  | //                        The Subzero Code Generator | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | /// | 
|  | /// \file | 
|  | /// \brief Defines how ELF sections are represented. | 
|  | /// | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "IceELFSection.h" | 
|  |  | 
|  | #include "IceDefs.h" | 
|  | #include "IceELFStreamer.h" | 
|  | #include "llvm/Support/MathExtras.h" | 
|  |  | 
|  | using namespace llvm::ELF; | 
|  |  | 
|  | namespace Ice { | 
|  |  | 
|  | // Text sections. | 
|  |  | 
|  | void ELFTextSection::appendData(ELFStreamer &Str, | 
|  | const llvm::StringRef MoreData) { | 
|  | Str.writeBytes(MoreData); | 
|  | Header.sh_size += MoreData.size(); | 
|  | } | 
|  |  | 
|  | // Data sections. | 
|  |  | 
|  | void ELFDataSection::appendData(ELFStreamer &Str, | 
|  | const llvm::StringRef MoreData) { | 
|  | Str.writeBytes(MoreData); | 
|  | Header.sh_size += MoreData.size(); | 
|  | } | 
|  |  | 
|  | void ELFDataSection::appendZeros(ELFStreamer &Str, SizeT NumBytes) { | 
|  | Str.writeZeroPadding(NumBytes); | 
|  | Header.sh_size += NumBytes; | 
|  | } | 
|  |  | 
|  | void ELFDataSection::appendRelocationOffset(ELFStreamer &Str, bool IsRela, | 
|  | RelocOffsetT RelocOffset) { | 
|  | const SizeT RelocAddrSize = typeWidthInBytes(getPointerType()); | 
|  | if (IsRela) { | 
|  | appendZeros(Str, RelocAddrSize); | 
|  | return; | 
|  | } | 
|  | assert(RelocAddrSize == 4 && " writeLE32 assumes RelocAddrSize is 4"); | 
|  | Str.writeLE32(RelocOffset); | 
|  | Header.sh_size += RelocAddrSize; | 
|  | } | 
|  |  | 
|  | void ELFDataSection::padToAlignment(ELFStreamer &Str, Elf64_Xword Align) { | 
|  | assert(llvm::isPowerOf2_32(Align)); | 
|  | Elf64_Xword AlignDiff = Utils::OffsetToAlignment(Header.sh_size, Align); | 
|  | if (AlignDiff == 0) | 
|  | return; | 
|  | if (Header.sh_type != llvm::ELF::SHT_NOBITS) | 
|  | Str.writeZeroPadding(AlignDiff); | 
|  | Header.sh_size += AlignDiff; | 
|  | } | 
|  |  | 
|  | // Relocation sections. | 
|  |  | 
|  | void ELFRelocationSection::addRelocations(RelocOffsetT BaseOff, | 
|  | const FixupRefList &FixupRefs, | 
|  | ELFSymbolTableSection *SymTab) { | 
|  | for (const AssemblerFixup *FR : FixupRefs) { | 
|  | Fixups.push_back(*FR); | 
|  | AssemblerFixup &F = Fixups.back(); | 
|  | F.set_position(BaseOff + F.position()); | 
|  | assert(!F.valueIsSymbol()); | 
|  | if (!F.isNullSymbol()) { | 
|  | // Do an early lookup in the symbol table.  If the symbol is found, | 
|  | // replace the Constant in the symbol with the ELFSym, and calculate the | 
|  | // final value of the addend.  As such, a local label allocated from the | 
|  | // Assembler arena will be converted to a symbol before the Assembler | 
|  | // arena goes away. | 
|  | if (const ELFSym *Sym = SymTab->findSymbol(F.symbol())) { | 
|  | F.set_addend(F.offset()); | 
|  | F.set_value(Sym); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | size_t ELFRelocationSection::getSectionDataSize() const { | 
|  | return Fixups.size() * Header.sh_entsize; | 
|  | } | 
|  |  | 
|  | // Symbol tables. | 
|  |  | 
|  | void ELFSymbolTableSection::createNullSymbol(ELFSection *NullSection, | 
|  | GlobalContext *Ctx) { | 
|  | // The first entry in the symbol table should be a NULL entry, so make sure | 
|  | // the map is still empty. | 
|  | assert(LocalSymbols.empty()); | 
|  | // Explicitly set the null symbol name to the empty string, so that | 
|  | // GlobalString::operator<() orders the null string first. | 
|  | NullSymbolName = GlobalString::createWithString(Ctx, ""); | 
|  | createDefinedSym(NullSymbolName, STT_NOTYPE, STB_LOCAL, NullSection, 0, 0); | 
|  | NullSymbol = findSymbol(NullSymbolName); | 
|  | } | 
|  |  | 
|  | void ELFSymbolTableSection::createDefinedSym(GlobalString Name, uint8_t Type, | 
|  | uint8_t Binding, | 
|  | ELFSection *Section, | 
|  | RelocOffsetT Offset, SizeT Size) { | 
|  | ELFSym NewSymbol = ELFSym(); | 
|  | NewSymbol.Sym.setBindingAndType(Binding, Type); | 
|  | NewSymbol.Sym.st_value = Offset; | 
|  | NewSymbol.Sym.st_size = Size; | 
|  | NewSymbol.Section = Section; | 
|  | NewSymbol.Number = ELFSym::UnknownNumber; | 
|  | bool Unique; | 
|  | if (Binding == STB_LOCAL) | 
|  | Unique = LocalSymbols.insert(std::make_pair(Name, NewSymbol)).second; | 
|  | else | 
|  | Unique = GlobalSymbols.insert(std::make_pair(Name, NewSymbol)).second; | 
|  | assert(Unique); | 
|  | (void)Unique; | 
|  | } | 
|  |  | 
|  | void ELFSymbolTableSection::noteUndefinedSym(GlobalString Name, | 
|  | ELFSection *NullSection) { | 
|  | ELFSym NewSymbol = ELFSym(); | 
|  | NewSymbol.Sym.setBindingAndType(STB_GLOBAL, STT_NOTYPE); | 
|  | NewSymbol.Section = NullSection; | 
|  | NewSymbol.Number = ELFSym::UnknownNumber; | 
|  | bool Unique = GlobalSymbols.insert(std::make_pair(Name, NewSymbol)).second; | 
|  | if (!Unique) { | 
|  | std::string Buffer; | 
|  | llvm::raw_string_ostream StrBuf(Buffer); | 
|  | StrBuf << "Symbol external and defined: " << Name; | 
|  | llvm::report_fatal_error(StrBuf.str()); | 
|  | } | 
|  | (void)Unique; | 
|  | } | 
|  |  | 
|  | const ELFSym *ELFSymbolTableSection::findSymbol(GlobalString Name) const { | 
|  | auto I = LocalSymbols.find(Name); | 
|  | if (I != LocalSymbols.end()) | 
|  | return &I->second; | 
|  | I = GlobalSymbols.find(Name); | 
|  | if (I != GlobalSymbols.end()) | 
|  | return &I->second; | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | void ELFSymbolTableSection::updateIndices(const ELFStringTableSection *StrTab) { | 
|  | SizeT SymNumber = 0; | 
|  | for (auto &KeyValue : LocalSymbols) { | 
|  | GlobalString Name = KeyValue.first; | 
|  | ELFSection *Section = KeyValue.second.Section; | 
|  | Elf64_Sym &SymInfo = KeyValue.second.Sym; | 
|  | if (Name != NullSymbolName && Name.hasStdString()) | 
|  | SymInfo.st_name = StrTab->getIndex(Name.toString()); | 
|  | SymInfo.st_shndx = Section->getNumber(); | 
|  | KeyValue.second.setNumber(SymNumber++); | 
|  | } | 
|  | for (auto &KeyValue : GlobalSymbols) { | 
|  | const std::string &Name = KeyValue.first.toString(); | 
|  | ELFSection *Section = KeyValue.second.Section; | 
|  | Elf64_Sym &SymInfo = KeyValue.second.Sym; | 
|  | if (!Name.empty()) | 
|  | SymInfo.st_name = StrTab->getIndex(Name); | 
|  | SymInfo.st_shndx = Section->getNumber(); | 
|  | KeyValue.second.setNumber(SymNumber++); | 
|  | } | 
|  | } | 
|  |  | 
|  | void ELFSymbolTableSection::writeData(ELFStreamer &Str, bool IsELF64) { | 
|  | if (IsELF64) { | 
|  | writeSymbolMap<true>(Str, LocalSymbols); | 
|  | writeSymbolMap<true>(Str, GlobalSymbols); | 
|  | } else { | 
|  | writeSymbolMap<false>(Str, LocalSymbols); | 
|  | writeSymbolMap<false>(Str, GlobalSymbols); | 
|  | } | 
|  | } | 
|  |  | 
|  | // String tables. | 
|  |  | 
|  | void ELFStringTableSection::add(const std::string &Str) { | 
|  | assert(!isLaidOut()); | 
|  | assert(!Str.empty()); | 
|  | StringToIndexMap.insert(std::make_pair(Str, UnknownIndex)); | 
|  | } | 
|  |  | 
|  | size_t ELFStringTableSection::getIndex(const std::string &Str) const { | 
|  | assert(isLaidOut()); | 
|  | StringToIndexType::const_iterator It = StringToIndexMap.find(Str); | 
|  | if (It == StringToIndexMap.end()) { | 
|  | llvm::report_fatal_error("String index not found: " + Str); | 
|  | return UnknownIndex; | 
|  | } | 
|  | return It->second; | 
|  | } | 
|  |  | 
|  | bool ELFStringTableSection::SuffixComparator:: | 
|  | operator()(const std::string &StrA, const std::string &StrB) const { | 
|  | size_t LenA = StrA.size(); | 
|  | size_t LenB = StrB.size(); | 
|  | size_t CommonLen = std::min(LenA, LenB); | 
|  | // If there is a difference in the common suffix, use that diff to sort. | 
|  | for (size_t i = 0; i < CommonLen; ++i) { | 
|  | char a = StrA[LenA - i - 1]; | 
|  | char b = StrB[LenB - i - 1]; | 
|  | if (a != b) | 
|  | return a > b; | 
|  | } | 
|  | // If the common suffixes are completely equal, let the longer one come | 
|  | // first, so that it can be laid out first and its characters shared. | 
|  | return LenA > LenB; | 
|  | } | 
|  |  | 
|  | void ELFStringTableSection::doLayout() { | 
|  | assert(!isLaidOut()); | 
|  | llvm::StringRef Prev; | 
|  |  | 
|  | // String table starts with 0 byte. | 
|  | StringData.push_back(0); | 
|  |  | 
|  | for (auto &StringIndex : StringToIndexMap) { | 
|  | assert(StringIndex.second == UnknownIndex); | 
|  | llvm::StringRef Cur = llvm::StringRef(StringIndex.first); | 
|  | if (Prev.endswith(Cur)) { | 
|  | // Prev is already in the StringData, and Cur is shorter than Prev based | 
|  | // on the sort. | 
|  | StringIndex.second = StringData.size() - Cur.size() - 1; | 
|  | continue; | 
|  | } | 
|  | StringIndex.second = StringData.size(); | 
|  | std::copy(Cur.begin(), Cur.end(), back_inserter(StringData)); | 
|  | StringData.push_back(0); | 
|  | Prev = Cur; | 
|  | } | 
|  | } | 
|  |  | 
|  | } // end of namespace Ice |