Home | History | Annotate | Download | only in src
      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