| //===- 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. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file defines how ELF sections are represented. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "IceDefs.h" |
| #include "IceELFSection.h" |
| #include "IceELFStreamer.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(); |
| } |
| |
| // Relocation sections. |
| |
| void ELFRelocationSection::addRelocations(RelocOffsetT BaseOff, |
| const FixupRefList &FixupRefs) { |
| for (const AssemblerFixup *FR : FixupRefs) { |
| Fixups.push_back(*FR); |
| AssemblerFixup &F = Fixups.back(); |
| F.set_position(BaseOff + F.position()); |
| } |
| } |
| |
| size_t ELFRelocationSection::getSectionDataSize( |
| const GlobalContext &Ctx, const ELFSymbolTableSection *SymTab) const { |
| size_t NumWriteableRelocs = 0; |
| for (const AssemblerFixup &Fixup : Fixups) { |
| const ELFSym *Symbol = SymTab->findSymbol(Fixup.symbol(&Ctx)); |
| // TODO(jvoung): When the symbol table finally tracks everything, |
| // just use the Fixups.size() as the count, and remove the |
| // SymTab and Ctx params. |
| if (Symbol) |
| ++NumWriteableRelocs; |
| } |
| return NumWriteableRelocs * Header.sh_entsize; |
| } |
| |
| // Symbol tables. |
| |
| void ELFSymbolTableSection::createDefinedSym(const IceString &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 (Type == 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(const IceString &Name, |
| ELFSection *NullSection) { |
| ELFSym NewSymbol = ELFSym(); |
| NewSymbol.Sym.setBindingAndType(STB_GLOBAL, STT_NOTYPE); |
| NewSymbol.Section = NullSection; |
| NewSymbol.Number = ELFSym::UnknownNumber; |
| GlobalSymbols.insert(std::make_pair(Name, NewSymbol)); |
| } |
| |
| const ELFSym *ELFSymbolTableSection::findSymbol(const IceString &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) { |
| const IceString &Name = KeyValue.first; |
| 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++); |
| } |
| for (auto &KeyValue : GlobalSymbols) { |
| const IceString &Name = KeyValue.first; |
| 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 IceString &Str) { |
| assert(!isLaidOut()); |
| assert(!Str.empty()); |
| StringToIndexMap.insert(std::make_pair(Str, UnknownIndex)); |
| } |
| |
| size_t ELFStringTableSection::getIndex(const IceString &Str) const { |
| assert(isLaidOut()); |
| StringToIndexType::const_iterator It = StringToIndexMap.find(Str); |
| if (It == StringToIndexMap.end()) { |
| llvm_unreachable("String index not found"); |
| return UnknownIndex; |
| } |
| return It->second; |
| } |
| |
| bool ELFStringTableSection::SuffixComparator:: |
| operator()(const IceString &StrA, const IceString &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 |