1e8d8bef9SDimitry Andric //===- ELFObjHandler.cpp --------------------------------------------------===// 2e8d8bef9SDimitry Andric // 3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e8d8bef9SDimitry Andric // 7e8d8bef9SDimitry Andric //===-----------------------------------------------------------------------===/ 8e8d8bef9SDimitry Andric 9e8d8bef9SDimitry Andric #include "llvm/InterfaceStub/ELFObjHandler.h" 10fe6060f1SDimitry Andric #include "llvm/InterfaceStub/IFSStub.h" 11e8d8bef9SDimitry Andric #include "llvm/MC/StringTableBuilder.h" 12e8d8bef9SDimitry Andric #include "llvm/Object/Binary.h" 13e8d8bef9SDimitry Andric #include "llvm/Object/ELFObjectFile.h" 14e8d8bef9SDimitry Andric #include "llvm/Object/ELFTypes.h" 15e8d8bef9SDimitry Andric #include "llvm/Support/Errc.h" 16e8d8bef9SDimitry Andric #include "llvm/Support/Error.h" 17e8d8bef9SDimitry Andric #include "llvm/Support/FileOutputBuffer.h" 18e8d8bef9SDimitry Andric #include "llvm/Support/MathExtras.h" 19e8d8bef9SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 20bdd1243dSDimitry Andric #include <optional> 21e8d8bef9SDimitry Andric 22e8d8bef9SDimitry Andric using llvm::object::ELFObjectFile; 23e8d8bef9SDimitry Andric 24e8d8bef9SDimitry Andric using namespace llvm; 25e8d8bef9SDimitry Andric using namespace llvm::object; 26e8d8bef9SDimitry Andric using namespace llvm::ELF; 27e8d8bef9SDimitry Andric 28e8d8bef9SDimitry Andric namespace llvm { 29fe6060f1SDimitry Andric namespace ifs { 30e8d8bef9SDimitry Andric 31e8d8bef9SDimitry Andric // Simple struct to hold relevant .dynamic entries. 32e8d8bef9SDimitry Andric struct DynamicEntries { 33e8d8bef9SDimitry Andric uint64_t StrTabAddr = 0; 34e8d8bef9SDimitry Andric uint64_t StrSize = 0; 35bdd1243dSDimitry Andric std::optional<uint64_t> SONameOffset; 36e8d8bef9SDimitry Andric std::vector<uint64_t> NeededLibNames; 37e8d8bef9SDimitry Andric // Symbol table: 38e8d8bef9SDimitry Andric uint64_t DynSymAddr = 0; 39e8d8bef9SDimitry Andric // Hash tables: 40bdd1243dSDimitry Andric std::optional<uint64_t> ElfHash; 41bdd1243dSDimitry Andric std::optional<uint64_t> GnuHash; 42e8d8bef9SDimitry Andric }; 43e8d8bef9SDimitry Andric 44e8d8bef9SDimitry Andric /// This initializes an ELF file header with information specific to a binary 45e8d8bef9SDimitry Andric /// dynamic shared object. 46e8d8bef9SDimitry Andric /// Offsets, indexes, links, etc. for section and program headers are just 47e8d8bef9SDimitry Andric /// zero-initialized as they will be updated elsewhere. 48e8d8bef9SDimitry Andric /// 49e8d8bef9SDimitry Andric /// @param ElfHeader Target ELFT::Ehdr to populate. 50e8d8bef9SDimitry Andric /// @param Machine Target architecture (e_machine from ELF specifications). 51e8d8bef9SDimitry Andric template <class ELFT> 52e8d8bef9SDimitry Andric static void initELFHeader(typename ELFT::Ehdr &ElfHeader, uint16_t Machine) { 53e8d8bef9SDimitry Andric memset(&ElfHeader, 0, sizeof(ElfHeader)); 54e8d8bef9SDimitry Andric // ELF identification. 55e8d8bef9SDimitry Andric ElfHeader.e_ident[EI_MAG0] = ElfMagic[EI_MAG0]; 56e8d8bef9SDimitry Andric ElfHeader.e_ident[EI_MAG1] = ElfMagic[EI_MAG1]; 57e8d8bef9SDimitry Andric ElfHeader.e_ident[EI_MAG2] = ElfMagic[EI_MAG2]; 58e8d8bef9SDimitry Andric ElfHeader.e_ident[EI_MAG3] = ElfMagic[EI_MAG3]; 59e8d8bef9SDimitry Andric ElfHeader.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32; 60*0fca6ea1SDimitry Andric bool IsLittleEndian = ELFT::Endianness == llvm::endianness::little; 61e8d8bef9SDimitry Andric ElfHeader.e_ident[EI_DATA] = IsLittleEndian ? ELFDATA2LSB : ELFDATA2MSB; 62e8d8bef9SDimitry Andric ElfHeader.e_ident[EI_VERSION] = EV_CURRENT; 63e8d8bef9SDimitry Andric ElfHeader.e_ident[EI_OSABI] = ELFOSABI_NONE; 64e8d8bef9SDimitry Andric 65e8d8bef9SDimitry Andric // Remainder of ELF header. 66e8d8bef9SDimitry Andric ElfHeader.e_type = ET_DYN; 67e8d8bef9SDimitry Andric ElfHeader.e_machine = Machine; 68e8d8bef9SDimitry Andric ElfHeader.e_version = EV_CURRENT; 69e8d8bef9SDimitry Andric ElfHeader.e_ehsize = sizeof(typename ELFT::Ehdr); 70e8d8bef9SDimitry Andric ElfHeader.e_phentsize = sizeof(typename ELFT::Phdr); 71e8d8bef9SDimitry Andric ElfHeader.e_shentsize = sizeof(typename ELFT::Shdr); 72e8d8bef9SDimitry Andric } 73e8d8bef9SDimitry Andric 74e8d8bef9SDimitry Andric namespace { 75e8d8bef9SDimitry Andric template <class ELFT> struct OutputSection { 76e8d8bef9SDimitry Andric using Elf_Shdr = typename ELFT::Shdr; 77e8d8bef9SDimitry Andric std::string Name; 78e8d8bef9SDimitry Andric Elf_Shdr Shdr; 79e8d8bef9SDimitry Andric uint64_t Addr; 80e8d8bef9SDimitry Andric uint64_t Offset; 81e8d8bef9SDimitry Andric uint64_t Size; 82e8d8bef9SDimitry Andric uint64_t Align; 83e8d8bef9SDimitry Andric uint32_t Index; 84e8d8bef9SDimitry Andric bool NoBits = true; 85e8d8bef9SDimitry Andric }; 86e8d8bef9SDimitry Andric 87e8d8bef9SDimitry Andric template <class T, class ELFT> 88e8d8bef9SDimitry Andric struct ContentSection : public OutputSection<ELFT> { 89e8d8bef9SDimitry Andric T Content; 90e8d8bef9SDimitry Andric ContentSection() { this->NoBits = false; } 91e8d8bef9SDimitry Andric }; 92e8d8bef9SDimitry Andric 93e8d8bef9SDimitry Andric // This class just wraps StringTableBuilder for the purpose of adding a 94e8d8bef9SDimitry Andric // default constructor. 95e8d8bef9SDimitry Andric class ELFStringTableBuilder : public StringTableBuilder { 96e8d8bef9SDimitry Andric public: 97e8d8bef9SDimitry Andric ELFStringTableBuilder() : StringTableBuilder(StringTableBuilder::ELF) {} 98e8d8bef9SDimitry Andric }; 99e8d8bef9SDimitry Andric 100e8d8bef9SDimitry Andric template <class ELFT> class ELFSymbolTableBuilder { 101e8d8bef9SDimitry Andric public: 102e8d8bef9SDimitry Andric using Elf_Sym = typename ELFT::Sym; 103e8d8bef9SDimitry Andric 104e8d8bef9SDimitry Andric ELFSymbolTableBuilder() { Symbols.push_back({}); } 105e8d8bef9SDimitry Andric 106e8d8bef9SDimitry Andric void add(size_t StNameOffset, uint64_t StSize, uint8_t StBind, uint8_t StType, 107e8d8bef9SDimitry Andric uint8_t StOther, uint16_t StShndx) { 108e8d8bef9SDimitry Andric Elf_Sym S{}; 109e8d8bef9SDimitry Andric S.st_name = StNameOffset; 110e8d8bef9SDimitry Andric S.st_size = StSize; 111e8d8bef9SDimitry Andric S.st_info = (StBind << 4) | (StType & 0xf); 112e8d8bef9SDimitry Andric S.st_other = StOther; 113e8d8bef9SDimitry Andric S.st_shndx = StShndx; 114e8d8bef9SDimitry Andric Symbols.push_back(S); 115e8d8bef9SDimitry Andric } 116e8d8bef9SDimitry Andric 117e8d8bef9SDimitry Andric size_t getSize() const { return Symbols.size() * sizeof(Elf_Sym); } 118e8d8bef9SDimitry Andric 119e8d8bef9SDimitry Andric void write(uint8_t *Buf) const { 120e8d8bef9SDimitry Andric memcpy(Buf, Symbols.data(), sizeof(Elf_Sym) * Symbols.size()); 121e8d8bef9SDimitry Andric } 122e8d8bef9SDimitry Andric 123e8d8bef9SDimitry Andric private: 124e8d8bef9SDimitry Andric llvm::SmallVector<Elf_Sym, 8> Symbols; 125e8d8bef9SDimitry Andric }; 126e8d8bef9SDimitry Andric 127e8d8bef9SDimitry Andric template <class ELFT> class ELFDynamicTableBuilder { 128e8d8bef9SDimitry Andric public: 129e8d8bef9SDimitry Andric using Elf_Dyn = typename ELFT::Dyn; 130e8d8bef9SDimitry Andric 131e8d8bef9SDimitry Andric size_t addAddr(uint64_t Tag, uint64_t Addr) { 132e8d8bef9SDimitry Andric Elf_Dyn Entry; 133e8d8bef9SDimitry Andric Entry.d_tag = Tag; 134e8d8bef9SDimitry Andric Entry.d_un.d_ptr = Addr; 135e8d8bef9SDimitry Andric Entries.push_back(Entry); 136e8d8bef9SDimitry Andric return Entries.size() - 1; 137e8d8bef9SDimitry Andric } 138e8d8bef9SDimitry Andric 139e8d8bef9SDimitry Andric void modifyAddr(size_t Index, uint64_t Addr) { 140e8d8bef9SDimitry Andric Entries[Index].d_un.d_ptr = Addr; 141e8d8bef9SDimitry Andric } 142e8d8bef9SDimitry Andric 143e8d8bef9SDimitry Andric size_t addValue(uint64_t Tag, uint64_t Value) { 144e8d8bef9SDimitry Andric Elf_Dyn Entry; 145e8d8bef9SDimitry Andric Entry.d_tag = Tag; 146e8d8bef9SDimitry Andric Entry.d_un.d_val = Value; 147e8d8bef9SDimitry Andric Entries.push_back(Entry); 148e8d8bef9SDimitry Andric return Entries.size() - 1; 149e8d8bef9SDimitry Andric } 150e8d8bef9SDimitry Andric 151e8d8bef9SDimitry Andric void modifyValue(size_t Index, uint64_t Value) { 152e8d8bef9SDimitry Andric Entries[Index].d_un.d_val = Value; 153e8d8bef9SDimitry Andric } 154e8d8bef9SDimitry Andric 155e8d8bef9SDimitry Andric size_t getSize() const { 156e8d8bef9SDimitry Andric // Add DT_NULL entry at the end. 157e8d8bef9SDimitry Andric return (Entries.size() + 1) * sizeof(Elf_Dyn); 158e8d8bef9SDimitry Andric } 159e8d8bef9SDimitry Andric 160e8d8bef9SDimitry Andric void write(uint8_t *Buf) const { 161e8d8bef9SDimitry Andric memcpy(Buf, Entries.data(), sizeof(Elf_Dyn) * Entries.size()); 162e8d8bef9SDimitry Andric // Add DT_NULL entry at the end. 163e8d8bef9SDimitry Andric memset(Buf + sizeof(Elf_Dyn) * Entries.size(), 0, sizeof(Elf_Dyn)); 164e8d8bef9SDimitry Andric } 165e8d8bef9SDimitry Andric 166e8d8bef9SDimitry Andric private: 167e8d8bef9SDimitry Andric llvm::SmallVector<Elf_Dyn, 8> Entries; 168e8d8bef9SDimitry Andric }; 169e8d8bef9SDimitry Andric 170e8d8bef9SDimitry Andric template <class ELFT> class ELFStubBuilder { 171e8d8bef9SDimitry Andric public: 172e8d8bef9SDimitry Andric using Elf_Ehdr = typename ELFT::Ehdr; 173e8d8bef9SDimitry Andric using Elf_Shdr = typename ELFT::Shdr; 174e8d8bef9SDimitry Andric using Elf_Phdr = typename ELFT::Phdr; 175e8d8bef9SDimitry Andric using Elf_Sym = typename ELFT::Sym; 176e8d8bef9SDimitry Andric using Elf_Addr = typename ELFT::Addr; 177e8d8bef9SDimitry Andric using Elf_Dyn = typename ELFT::Dyn; 178e8d8bef9SDimitry Andric 179e8d8bef9SDimitry Andric ELFStubBuilder(const ELFStubBuilder &) = delete; 180e8d8bef9SDimitry Andric ELFStubBuilder(ELFStubBuilder &&) = default; 181e8d8bef9SDimitry Andric 182fe6060f1SDimitry Andric explicit ELFStubBuilder(const IFSStub &Stub) { 183e8d8bef9SDimitry Andric DynSym.Name = ".dynsym"; 184e8d8bef9SDimitry Andric DynSym.Align = sizeof(Elf_Addr); 185e8d8bef9SDimitry Andric DynStr.Name = ".dynstr"; 186e8d8bef9SDimitry Andric DynStr.Align = 1; 187e8d8bef9SDimitry Andric DynTab.Name = ".dynamic"; 188e8d8bef9SDimitry Andric DynTab.Align = sizeof(Elf_Addr); 189e8d8bef9SDimitry Andric ShStrTab.Name = ".shstrtab"; 190e8d8bef9SDimitry Andric ShStrTab.Align = 1; 191e8d8bef9SDimitry Andric 192e8d8bef9SDimitry Andric // Populate string tables. 193fe6060f1SDimitry Andric for (const IFSSymbol &Sym : Stub.Symbols) 194e8d8bef9SDimitry Andric DynStr.Content.add(Sym.Name); 195e8d8bef9SDimitry Andric for (const std::string &Lib : Stub.NeededLibs) 196e8d8bef9SDimitry Andric DynStr.Content.add(Lib); 197e8d8bef9SDimitry Andric if (Stub.SoName) 19881ad6265SDimitry Andric DynStr.Content.add(*Stub.SoName); 199e8d8bef9SDimitry Andric 200e8d8bef9SDimitry Andric std::vector<OutputSection<ELFT> *> Sections = {&DynSym, &DynStr, &DynTab, 201e8d8bef9SDimitry Andric &ShStrTab}; 202e8d8bef9SDimitry Andric const OutputSection<ELFT> *LastSection = Sections.back(); 203e8d8bef9SDimitry Andric // Now set the Index and put sections names into ".shstrtab". 204e8d8bef9SDimitry Andric uint64_t Index = 1; 205e8d8bef9SDimitry Andric for (OutputSection<ELFT> *Sec : Sections) { 206e8d8bef9SDimitry Andric Sec->Index = Index++; 207e8d8bef9SDimitry Andric ShStrTab.Content.add(Sec->Name); 208e8d8bef9SDimitry Andric } 209e8d8bef9SDimitry Andric ShStrTab.Content.finalize(); 210e8d8bef9SDimitry Andric ShStrTab.Size = ShStrTab.Content.getSize(); 211e8d8bef9SDimitry Andric DynStr.Content.finalize(); 212e8d8bef9SDimitry Andric DynStr.Size = DynStr.Content.getSize(); 213e8d8bef9SDimitry Andric 214e8d8bef9SDimitry Andric // Populate dynamic symbol table. 215fe6060f1SDimitry Andric for (const IFSSymbol &Sym : Stub.Symbols) { 216e8d8bef9SDimitry Andric uint8_t Bind = Sym.Weak ? STB_WEAK : STB_GLOBAL; 217e8d8bef9SDimitry Andric // For non-undefined symbols, value of the shndx is not relevant at link 218e8d8bef9SDimitry Andric // time as long as it is not SHN_UNDEF. Set shndx to 1, which 219e8d8bef9SDimitry Andric // points to ".dynsym". 220e8d8bef9SDimitry Andric uint16_t Shndx = Sym.Undefined ? SHN_UNDEF : 1; 22181ad6265SDimitry Andric uint64_t Size = Sym.Size.value_or(0); 22281ad6265SDimitry Andric DynSym.Content.add(DynStr.Content.getOffset(Sym.Name), Size, Bind, 223fe6060f1SDimitry Andric convertIFSSymbolTypeToELF(Sym.Type), 0, Shndx); 224e8d8bef9SDimitry Andric } 225e8d8bef9SDimitry Andric DynSym.Size = DynSym.Content.getSize(); 226e8d8bef9SDimitry Andric 227e8d8bef9SDimitry Andric // Poplulate dynamic table. 228e8d8bef9SDimitry Andric size_t DynSymIndex = DynTab.Content.addAddr(DT_SYMTAB, 0); 229e8d8bef9SDimitry Andric size_t DynStrIndex = DynTab.Content.addAddr(DT_STRTAB, 0); 23081ad6265SDimitry Andric DynTab.Content.addValue(DT_STRSZ, DynSym.Size); 231e8d8bef9SDimitry Andric for (const std::string &Lib : Stub.NeededLibs) 232e8d8bef9SDimitry Andric DynTab.Content.addValue(DT_NEEDED, DynStr.Content.getOffset(Lib)); 233e8d8bef9SDimitry Andric if (Stub.SoName) 234e8d8bef9SDimitry Andric DynTab.Content.addValue(DT_SONAME, 23581ad6265SDimitry Andric DynStr.Content.getOffset(*Stub.SoName)); 236e8d8bef9SDimitry Andric DynTab.Size = DynTab.Content.getSize(); 237e8d8bef9SDimitry Andric // Calculate sections' addresses and offsets. 238e8d8bef9SDimitry Andric uint64_t CurrentOffset = sizeof(Elf_Ehdr); 239e8d8bef9SDimitry Andric for (OutputSection<ELFT> *Sec : Sections) { 240e8d8bef9SDimitry Andric Sec->Offset = alignTo(CurrentOffset, Sec->Align); 241e8d8bef9SDimitry Andric Sec->Addr = Sec->Offset; 242e8d8bef9SDimitry Andric CurrentOffset = Sec->Offset + Sec->Size; 243e8d8bef9SDimitry Andric } 244e8d8bef9SDimitry Andric // Fill Addr back to dynamic table. 245e8d8bef9SDimitry Andric DynTab.Content.modifyAddr(DynSymIndex, DynSym.Addr); 246e8d8bef9SDimitry Andric DynTab.Content.modifyAddr(DynStrIndex, DynStr.Addr); 247e8d8bef9SDimitry Andric // Write section headers of string tables. 248e8d8bef9SDimitry Andric fillSymTabShdr(DynSym, SHT_DYNSYM); 249e8d8bef9SDimitry Andric fillStrTabShdr(DynStr, SHF_ALLOC); 250e8d8bef9SDimitry Andric fillDynTabShdr(DynTab); 251e8d8bef9SDimitry Andric fillStrTabShdr(ShStrTab); 252e8d8bef9SDimitry Andric 253e8d8bef9SDimitry Andric // Finish initializing the ELF header. 25481ad6265SDimitry Andric initELFHeader<ELFT>(ElfHeader, static_cast<uint16_t>(*Stub.Target.Arch)); 255e8d8bef9SDimitry Andric ElfHeader.e_shstrndx = ShStrTab.Index; 256e8d8bef9SDimitry Andric ElfHeader.e_shnum = LastSection->Index + 1; 257e8d8bef9SDimitry Andric ElfHeader.e_shoff = 258e8d8bef9SDimitry Andric alignTo(LastSection->Offset + LastSection->Size, sizeof(Elf_Addr)); 259e8d8bef9SDimitry Andric } 260e8d8bef9SDimitry Andric 261e8d8bef9SDimitry Andric size_t getSize() const { 262e8d8bef9SDimitry Andric return ElfHeader.e_shoff + ElfHeader.e_shnum * sizeof(Elf_Shdr); 263e8d8bef9SDimitry Andric } 264e8d8bef9SDimitry Andric 265e8d8bef9SDimitry Andric void write(uint8_t *Data) const { 266e8d8bef9SDimitry Andric write(Data, ElfHeader); 267e8d8bef9SDimitry Andric DynSym.Content.write(Data + DynSym.Shdr.sh_offset); 268e8d8bef9SDimitry Andric DynStr.Content.write(Data + DynStr.Shdr.sh_offset); 269e8d8bef9SDimitry Andric DynTab.Content.write(Data + DynTab.Shdr.sh_offset); 270e8d8bef9SDimitry Andric ShStrTab.Content.write(Data + ShStrTab.Shdr.sh_offset); 271e8d8bef9SDimitry Andric writeShdr(Data, DynSym); 272e8d8bef9SDimitry Andric writeShdr(Data, DynStr); 273e8d8bef9SDimitry Andric writeShdr(Data, DynTab); 274e8d8bef9SDimitry Andric writeShdr(Data, ShStrTab); 275e8d8bef9SDimitry Andric } 276e8d8bef9SDimitry Andric 277e8d8bef9SDimitry Andric private: 278e8d8bef9SDimitry Andric Elf_Ehdr ElfHeader; 279e8d8bef9SDimitry Andric ContentSection<ELFStringTableBuilder, ELFT> DynStr; 280e8d8bef9SDimitry Andric ContentSection<ELFStringTableBuilder, ELFT> ShStrTab; 281e8d8bef9SDimitry Andric ContentSection<ELFSymbolTableBuilder<ELFT>, ELFT> DynSym; 282e8d8bef9SDimitry Andric ContentSection<ELFDynamicTableBuilder<ELFT>, ELFT> DynTab; 283e8d8bef9SDimitry Andric 284e8d8bef9SDimitry Andric template <class T> static void write(uint8_t *Data, const T &Value) { 285e8d8bef9SDimitry Andric *reinterpret_cast<T *>(Data) = Value; 286e8d8bef9SDimitry Andric } 287e8d8bef9SDimitry Andric 288e8d8bef9SDimitry Andric void fillStrTabShdr(ContentSection<ELFStringTableBuilder, ELFT> &StrTab, 289e8d8bef9SDimitry Andric uint32_t ShFlags = 0) const { 290e8d8bef9SDimitry Andric StrTab.Shdr.sh_type = SHT_STRTAB; 291e8d8bef9SDimitry Andric StrTab.Shdr.sh_flags = ShFlags; 292e8d8bef9SDimitry Andric StrTab.Shdr.sh_addr = StrTab.Addr; 293e8d8bef9SDimitry Andric StrTab.Shdr.sh_offset = StrTab.Offset; 294e8d8bef9SDimitry Andric StrTab.Shdr.sh_info = 0; 295e8d8bef9SDimitry Andric StrTab.Shdr.sh_size = StrTab.Size; 296e8d8bef9SDimitry Andric StrTab.Shdr.sh_name = ShStrTab.Content.getOffset(StrTab.Name); 297e8d8bef9SDimitry Andric StrTab.Shdr.sh_addralign = StrTab.Align; 298e8d8bef9SDimitry Andric StrTab.Shdr.sh_entsize = 0; 299e8d8bef9SDimitry Andric StrTab.Shdr.sh_link = 0; 300e8d8bef9SDimitry Andric } 301e8d8bef9SDimitry Andric void fillSymTabShdr(ContentSection<ELFSymbolTableBuilder<ELFT>, ELFT> &SymTab, 302e8d8bef9SDimitry Andric uint32_t ShType) const { 303e8d8bef9SDimitry Andric SymTab.Shdr.sh_type = ShType; 304e8d8bef9SDimitry Andric SymTab.Shdr.sh_flags = SHF_ALLOC; 305e8d8bef9SDimitry Andric SymTab.Shdr.sh_addr = SymTab.Addr; 306e8d8bef9SDimitry Andric SymTab.Shdr.sh_offset = SymTab.Offset; 307fe6060f1SDimitry Andric // Only non-local symbols are included in the tbe file, so .dynsym only 308fe6060f1SDimitry Andric // contains 1 local symbol (the undefined symbol at index 0). The sh_info 309fe6060f1SDimitry Andric // should always be 1. 310fe6060f1SDimitry Andric SymTab.Shdr.sh_info = 1; 311e8d8bef9SDimitry Andric SymTab.Shdr.sh_size = SymTab.Size; 312e8d8bef9SDimitry Andric SymTab.Shdr.sh_name = this->ShStrTab.Content.getOffset(SymTab.Name); 313e8d8bef9SDimitry Andric SymTab.Shdr.sh_addralign = SymTab.Align; 314e8d8bef9SDimitry Andric SymTab.Shdr.sh_entsize = sizeof(Elf_Sym); 315e8d8bef9SDimitry Andric SymTab.Shdr.sh_link = this->DynStr.Index; 316e8d8bef9SDimitry Andric } 317e8d8bef9SDimitry Andric void fillDynTabShdr( 318e8d8bef9SDimitry Andric ContentSection<ELFDynamicTableBuilder<ELFT>, ELFT> &DynTab) const { 319e8d8bef9SDimitry Andric DynTab.Shdr.sh_type = SHT_DYNAMIC; 320e8d8bef9SDimitry Andric DynTab.Shdr.sh_flags = SHF_ALLOC; 321e8d8bef9SDimitry Andric DynTab.Shdr.sh_addr = DynTab.Addr; 322e8d8bef9SDimitry Andric DynTab.Shdr.sh_offset = DynTab.Offset; 323e8d8bef9SDimitry Andric DynTab.Shdr.sh_info = 0; 324e8d8bef9SDimitry Andric DynTab.Shdr.sh_size = DynTab.Size; 325e8d8bef9SDimitry Andric DynTab.Shdr.sh_name = this->ShStrTab.Content.getOffset(DynTab.Name); 326e8d8bef9SDimitry Andric DynTab.Shdr.sh_addralign = DynTab.Align; 327e8d8bef9SDimitry Andric DynTab.Shdr.sh_entsize = sizeof(Elf_Dyn); 328e8d8bef9SDimitry Andric DynTab.Shdr.sh_link = this->DynStr.Index; 329e8d8bef9SDimitry Andric } 330e8d8bef9SDimitry Andric uint64_t shdrOffset(const OutputSection<ELFT> &Sec) const { 331e8d8bef9SDimitry Andric return ElfHeader.e_shoff + Sec.Index * sizeof(Elf_Shdr); 332e8d8bef9SDimitry Andric } 333e8d8bef9SDimitry Andric 334e8d8bef9SDimitry Andric void writeShdr(uint8_t *Data, const OutputSection<ELFT> &Sec) const { 335e8d8bef9SDimitry Andric write(Data + shdrOffset(Sec), Sec.Shdr); 336e8d8bef9SDimitry Andric } 337e8d8bef9SDimitry Andric }; 33881ad6265SDimitry Andric 33981ad6265SDimitry Andric /// This function takes an error, and appends a string of text to the end of 34081ad6265SDimitry Andric /// that error. Since "appending" to an Error isn't supported behavior of an 34181ad6265SDimitry Andric /// Error, this function technically creates a new error with the combined 34281ad6265SDimitry Andric /// message and consumes the old error. 34381ad6265SDimitry Andric /// 34481ad6265SDimitry Andric /// @param Err Source error. 34581ad6265SDimitry Andric /// @param After Text to append at the end of Err's error message. 34681ad6265SDimitry Andric Error appendToError(Error Err, StringRef After) { 34781ad6265SDimitry Andric std::string Message; 34881ad6265SDimitry Andric raw_string_ostream Stream(Message); 34981ad6265SDimitry Andric Stream << Err; 35081ad6265SDimitry Andric Stream << " " << After; 35181ad6265SDimitry Andric consumeError(std::move(Err)); 35281ad6265SDimitry Andric return createError(Stream.str()); 35381ad6265SDimitry Andric } 35481ad6265SDimitry Andric 35581ad6265SDimitry Andric template <class ELFT> class DynSym { 35681ad6265SDimitry Andric using Elf_Shdr_Range = typename ELFT::ShdrRange; 35781ad6265SDimitry Andric using Elf_Shdr = typename ELFT::Shdr; 35881ad6265SDimitry Andric 35981ad6265SDimitry Andric public: 36081ad6265SDimitry Andric static Expected<DynSym> create(const ELFFile<ELFT> &ElfFile, 36181ad6265SDimitry Andric const DynamicEntries &DynEnt) { 36281ad6265SDimitry Andric Expected<Elf_Shdr_Range> Shdrs = ElfFile.sections(); 36381ad6265SDimitry Andric if (!Shdrs) 36481ad6265SDimitry Andric return Shdrs.takeError(); 36581ad6265SDimitry Andric return DynSym(ElfFile, DynEnt, *Shdrs); 36681ad6265SDimitry Andric } 36781ad6265SDimitry Andric 36881ad6265SDimitry Andric Expected<const uint8_t *> getDynSym() { 36981ad6265SDimitry Andric if (DynSymHdr) 37081ad6265SDimitry Andric return ElfFile.base() + DynSymHdr->sh_offset; 37181ad6265SDimitry Andric return getDynamicData(DynEnt.DynSymAddr, "dynamic symbol table"); 37281ad6265SDimitry Andric } 37381ad6265SDimitry Andric 37481ad6265SDimitry Andric Expected<StringRef> getDynStr() { 37581ad6265SDimitry Andric if (DynSymHdr) 37681ad6265SDimitry Andric return ElfFile.getStringTableForSymtab(*DynSymHdr, Shdrs); 37781ad6265SDimitry Andric Expected<const uint8_t *> DataOrErr = getDynamicData( 37881ad6265SDimitry Andric DynEnt.StrTabAddr, "dynamic string table", DynEnt.StrSize); 37981ad6265SDimitry Andric if (!DataOrErr) 38081ad6265SDimitry Andric return DataOrErr.takeError(); 38181ad6265SDimitry Andric return StringRef(reinterpret_cast<const char *>(*DataOrErr), 38281ad6265SDimitry Andric DynEnt.StrSize); 38381ad6265SDimitry Andric } 38481ad6265SDimitry Andric 38581ad6265SDimitry Andric private: 38681ad6265SDimitry Andric DynSym(const ELFFile<ELFT> &ElfFile, const DynamicEntries &DynEnt, 38781ad6265SDimitry Andric Elf_Shdr_Range Shdrs) 38881ad6265SDimitry Andric : ElfFile(ElfFile), DynEnt(DynEnt), Shdrs(Shdrs), 38981ad6265SDimitry Andric DynSymHdr(findDynSymHdr()) {} 39081ad6265SDimitry Andric 39181ad6265SDimitry Andric const Elf_Shdr *findDynSymHdr() { 39281ad6265SDimitry Andric for (const Elf_Shdr &Sec : Shdrs) 39381ad6265SDimitry Andric if (Sec.sh_type == SHT_DYNSYM) { 39481ad6265SDimitry Andric // If multiple .dynsym are present, use the first one. 39581ad6265SDimitry Andric // This behavior aligns with llvm::object::ELFFile::getDynSymtabSize() 39681ad6265SDimitry Andric return &Sec; 39781ad6265SDimitry Andric } 39881ad6265SDimitry Andric return nullptr; 39981ad6265SDimitry Andric } 40081ad6265SDimitry Andric 40181ad6265SDimitry Andric Expected<const uint8_t *> getDynamicData(uint64_t EntAddr, StringRef Name, 40281ad6265SDimitry Andric uint64_t Size = 0) { 40381ad6265SDimitry Andric Expected<const uint8_t *> SecPtr = ElfFile.toMappedAddr(EntAddr); 40481ad6265SDimitry Andric if (!SecPtr) 40581ad6265SDimitry Andric return appendToError( 40681ad6265SDimitry Andric SecPtr.takeError(), 40781ad6265SDimitry Andric ("when locating " + Name + " section contents").str()); 40881ad6265SDimitry Andric Expected<const uint8_t *> SecEndPtr = ElfFile.toMappedAddr(EntAddr + Size); 40981ad6265SDimitry Andric if (!SecEndPtr) 41081ad6265SDimitry Andric return appendToError( 41181ad6265SDimitry Andric SecEndPtr.takeError(), 41281ad6265SDimitry Andric ("when locating " + Name + " section contents").str()); 41381ad6265SDimitry Andric return *SecPtr; 41481ad6265SDimitry Andric } 41581ad6265SDimitry Andric 41681ad6265SDimitry Andric const ELFFile<ELFT> &ElfFile; 41781ad6265SDimitry Andric const DynamicEntries &DynEnt; 41881ad6265SDimitry Andric Elf_Shdr_Range Shdrs; 41981ad6265SDimitry Andric const Elf_Shdr *DynSymHdr; 42081ad6265SDimitry Andric }; 421e8d8bef9SDimitry Andric } // end anonymous namespace 422e8d8bef9SDimitry Andric 423e8d8bef9SDimitry Andric /// This function behaves similarly to StringRef::substr(), but attempts to 424e8d8bef9SDimitry Andric /// terminate the returned StringRef at the first null terminator. If no null 425e8d8bef9SDimitry Andric /// terminator is found, an error is returned. 426e8d8bef9SDimitry Andric /// 427e8d8bef9SDimitry Andric /// @param Str Source string to create a substring from. 428e8d8bef9SDimitry Andric /// @param Offset The start index of the desired substring. 429e8d8bef9SDimitry Andric static Expected<StringRef> terminatedSubstr(StringRef Str, size_t Offset) { 430e8d8bef9SDimitry Andric size_t StrEnd = Str.find('\0', Offset); 431e8d8bef9SDimitry Andric if (StrEnd == StringLiteral::npos) { 432e8d8bef9SDimitry Andric return createError( 433e8d8bef9SDimitry Andric "String overran bounds of string table (no null terminator)"); 434e8d8bef9SDimitry Andric } 435e8d8bef9SDimitry Andric 436e8d8bef9SDimitry Andric size_t StrLen = StrEnd - Offset; 437e8d8bef9SDimitry Andric return Str.substr(Offset, StrLen); 438e8d8bef9SDimitry Andric } 439e8d8bef9SDimitry Andric 440e8d8bef9SDimitry Andric /// This function populates a DynamicEntries struct using an ELFT::DynRange. 441e8d8bef9SDimitry Andric /// After populating the struct, the members are validated with 4424824e7fdSDimitry Andric /// some basic correctness checks. 443e8d8bef9SDimitry Andric /// 444e8d8bef9SDimitry Andric /// @param Dyn Target DynamicEntries struct to populate. 445e8d8bef9SDimitry Andric /// @param DynTable Source dynamic table. 446e8d8bef9SDimitry Andric template <class ELFT> 447e8d8bef9SDimitry Andric static Error populateDynamic(DynamicEntries &Dyn, 448e8d8bef9SDimitry Andric typename ELFT::DynRange DynTable) { 449e8d8bef9SDimitry Andric if (DynTable.empty()) 450e8d8bef9SDimitry Andric return createError("No .dynamic section found"); 451e8d8bef9SDimitry Andric 452e8d8bef9SDimitry Andric // Search .dynamic for relevant entries. 453e8d8bef9SDimitry Andric bool FoundDynStr = false; 454e8d8bef9SDimitry Andric bool FoundDynStrSz = false; 455e8d8bef9SDimitry Andric bool FoundDynSym = false; 456e8d8bef9SDimitry Andric for (auto &Entry : DynTable) { 457e8d8bef9SDimitry Andric switch (Entry.d_tag) { 458e8d8bef9SDimitry Andric case DT_SONAME: 459e8d8bef9SDimitry Andric Dyn.SONameOffset = Entry.d_un.d_val; 460e8d8bef9SDimitry Andric break; 461e8d8bef9SDimitry Andric case DT_STRTAB: 462e8d8bef9SDimitry Andric Dyn.StrTabAddr = Entry.d_un.d_ptr; 463e8d8bef9SDimitry Andric FoundDynStr = true; 464e8d8bef9SDimitry Andric break; 465e8d8bef9SDimitry Andric case DT_STRSZ: 466e8d8bef9SDimitry Andric Dyn.StrSize = Entry.d_un.d_val; 467e8d8bef9SDimitry Andric FoundDynStrSz = true; 468e8d8bef9SDimitry Andric break; 469e8d8bef9SDimitry Andric case DT_NEEDED: 470e8d8bef9SDimitry Andric Dyn.NeededLibNames.push_back(Entry.d_un.d_val); 471e8d8bef9SDimitry Andric break; 472e8d8bef9SDimitry Andric case DT_SYMTAB: 473e8d8bef9SDimitry Andric Dyn.DynSymAddr = Entry.d_un.d_ptr; 474e8d8bef9SDimitry Andric FoundDynSym = true; 475e8d8bef9SDimitry Andric break; 476e8d8bef9SDimitry Andric case DT_HASH: 477e8d8bef9SDimitry Andric Dyn.ElfHash = Entry.d_un.d_ptr; 478e8d8bef9SDimitry Andric break; 479e8d8bef9SDimitry Andric case DT_GNU_HASH: 480e8d8bef9SDimitry Andric Dyn.GnuHash = Entry.d_un.d_ptr; 481e8d8bef9SDimitry Andric } 482e8d8bef9SDimitry Andric } 483e8d8bef9SDimitry Andric 484e8d8bef9SDimitry Andric if (!FoundDynStr) { 485e8d8bef9SDimitry Andric return createError( 486e8d8bef9SDimitry Andric "Couldn't locate dynamic string table (no DT_STRTAB entry)"); 487e8d8bef9SDimitry Andric } 488e8d8bef9SDimitry Andric if (!FoundDynStrSz) { 489e8d8bef9SDimitry Andric return createError( 490e8d8bef9SDimitry Andric "Couldn't determine dynamic string table size (no DT_STRSZ entry)"); 491e8d8bef9SDimitry Andric } 492e8d8bef9SDimitry Andric if (!FoundDynSym) { 493e8d8bef9SDimitry Andric return createError( 494e8d8bef9SDimitry Andric "Couldn't locate dynamic symbol table (no DT_SYMTAB entry)"); 495e8d8bef9SDimitry Andric } 49681ad6265SDimitry Andric if (Dyn.SONameOffset && *Dyn.SONameOffset >= Dyn.StrSize) { 497e8d8bef9SDimitry Andric return createStringError(object_error::parse_failed, 498e8d8bef9SDimitry Andric "DT_SONAME string offset (0x%016" PRIx64 499e8d8bef9SDimitry Andric ") outside of dynamic string table", 500e8d8bef9SDimitry Andric *Dyn.SONameOffset); 501e8d8bef9SDimitry Andric } 502e8d8bef9SDimitry Andric for (uint64_t Offset : Dyn.NeededLibNames) { 503e8d8bef9SDimitry Andric if (Offset >= Dyn.StrSize) { 504e8d8bef9SDimitry Andric return createStringError(object_error::parse_failed, 505e8d8bef9SDimitry Andric "DT_NEEDED string offset (0x%016" PRIx64 506e8d8bef9SDimitry Andric ") outside of dynamic string table", 507e8d8bef9SDimitry Andric Offset); 508e8d8bef9SDimitry Andric } 509e8d8bef9SDimitry Andric } 510e8d8bef9SDimitry Andric 511e8d8bef9SDimitry Andric return Error::success(); 512e8d8bef9SDimitry Andric } 513e8d8bef9SDimitry Andric 514fe6060f1SDimitry Andric /// This function creates an IFSSymbol and populates all members using 515e8d8bef9SDimitry Andric /// information from a binary ELFT::Sym. 516e8d8bef9SDimitry Andric /// 517fe6060f1SDimitry Andric /// @param SymName The desired name of the IFSSymbol. 518e8d8bef9SDimitry Andric /// @param RawSym ELFT::Sym to extract symbol information from. 519e8d8bef9SDimitry Andric template <class ELFT> 520fe6060f1SDimitry Andric static IFSSymbol createELFSym(StringRef SymName, 521e8d8bef9SDimitry Andric const typename ELFT::Sym &RawSym) { 522fe6060f1SDimitry Andric IFSSymbol TargetSym{std::string(SymName)}; 523e8d8bef9SDimitry Andric uint8_t Binding = RawSym.getBinding(); 524e8d8bef9SDimitry Andric if (Binding == STB_WEAK) 525e8d8bef9SDimitry Andric TargetSym.Weak = true; 526e8d8bef9SDimitry Andric else 527e8d8bef9SDimitry Andric TargetSym.Weak = false; 528e8d8bef9SDimitry Andric 529e8d8bef9SDimitry Andric TargetSym.Undefined = RawSym.isUndefined(); 530fe6060f1SDimitry Andric TargetSym.Type = convertELFSymbolTypeToIFS(RawSym.st_info); 531e8d8bef9SDimitry Andric 532fe6060f1SDimitry Andric if (TargetSym.Type == IFSSymbolType::Func) { 533e8d8bef9SDimitry Andric TargetSym.Size = 0; 534e8d8bef9SDimitry Andric } else { 535e8d8bef9SDimitry Andric TargetSym.Size = RawSym.st_size; 536e8d8bef9SDimitry Andric } 537e8d8bef9SDimitry Andric return TargetSym; 538e8d8bef9SDimitry Andric } 539e8d8bef9SDimitry Andric 540fe6060f1SDimitry Andric /// This function populates an IFSStub with symbols using information read 541e8d8bef9SDimitry Andric /// from an ELF binary. 542e8d8bef9SDimitry Andric /// 543fe6060f1SDimitry Andric /// @param TargetStub IFSStub to add symbols to. 544e8d8bef9SDimitry Andric /// @param DynSym Range of dynamic symbols to add to TargetStub. 545e8d8bef9SDimitry Andric /// @param DynStr StringRef to the dynamic string table. 546e8d8bef9SDimitry Andric template <class ELFT> 547fe6060f1SDimitry Andric static Error populateSymbols(IFSStub &TargetStub, 548e8d8bef9SDimitry Andric const typename ELFT::SymRange DynSym, 549e8d8bef9SDimitry Andric StringRef DynStr) { 550e8d8bef9SDimitry Andric // Skips the first symbol since it's the NULL symbol. 551e8d8bef9SDimitry Andric for (auto RawSym : DynSym.drop_front(1)) { 552e8d8bef9SDimitry Andric // If a symbol does not have global or weak binding, ignore it. 553e8d8bef9SDimitry Andric uint8_t Binding = RawSym.getBinding(); 554e8d8bef9SDimitry Andric if (!(Binding == STB_GLOBAL || Binding == STB_WEAK)) 555e8d8bef9SDimitry Andric continue; 556e8d8bef9SDimitry Andric // If a symbol doesn't have default or protected visibility, ignore it. 557e8d8bef9SDimitry Andric uint8_t Visibility = RawSym.getVisibility(); 558e8d8bef9SDimitry Andric if (!(Visibility == STV_DEFAULT || Visibility == STV_PROTECTED)) 559e8d8bef9SDimitry Andric continue; 560fe6060f1SDimitry Andric // Create an IFSSymbol and populate it with information from the symbol 561e8d8bef9SDimitry Andric // table entry. 562e8d8bef9SDimitry Andric Expected<StringRef> SymName = terminatedSubstr(DynStr, RawSym.st_name); 563e8d8bef9SDimitry Andric if (!SymName) 564e8d8bef9SDimitry Andric return SymName.takeError(); 565fe6060f1SDimitry Andric IFSSymbol Sym = createELFSym<ELFT>(*SymName, RawSym); 566fe6060f1SDimitry Andric TargetStub.Symbols.push_back(std::move(Sym)); 567e8d8bef9SDimitry Andric // TODO: Populate symbol warning. 568e8d8bef9SDimitry Andric } 569e8d8bef9SDimitry Andric return Error::success(); 570e8d8bef9SDimitry Andric } 571e8d8bef9SDimitry Andric 572fe6060f1SDimitry Andric /// Returns a new IFSStub with all members populated from an ELFObjectFile. 573e8d8bef9SDimitry Andric /// @param ElfObj Source ELFObjectFile. 574e8d8bef9SDimitry Andric template <class ELFT> 575fe6060f1SDimitry Andric static Expected<std::unique_ptr<IFSStub>> 576e8d8bef9SDimitry Andric buildStub(const ELFObjectFile<ELFT> &ElfObj) { 577e8d8bef9SDimitry Andric using Elf_Dyn_Range = typename ELFT::DynRange; 578e8d8bef9SDimitry Andric using Elf_Sym_Range = typename ELFT::SymRange; 579e8d8bef9SDimitry Andric using Elf_Sym = typename ELFT::Sym; 580fe6060f1SDimitry Andric std::unique_ptr<IFSStub> DestStub = std::make_unique<IFSStub>(); 581e8d8bef9SDimitry Andric const ELFFile<ELFT> &ElfFile = ElfObj.getELFFile(); 582e8d8bef9SDimitry Andric // Fetch .dynamic table. 583e8d8bef9SDimitry Andric Expected<Elf_Dyn_Range> DynTable = ElfFile.dynamicEntries(); 584e8d8bef9SDimitry Andric if (!DynTable) { 585e8d8bef9SDimitry Andric return DynTable.takeError(); 586e8d8bef9SDimitry Andric } 587e8d8bef9SDimitry Andric 588e8d8bef9SDimitry Andric // Collect relevant .dynamic entries. 589e8d8bef9SDimitry Andric DynamicEntries DynEnt; 590e8d8bef9SDimitry Andric if (Error Err = populateDynamic<ELFT>(DynEnt, *DynTable)) 591e8d8bef9SDimitry Andric return std::move(Err); 59281ad6265SDimitry Andric Expected<DynSym<ELFT>> EDynSym = DynSym<ELFT>::create(ElfFile, DynEnt); 59381ad6265SDimitry Andric if (!EDynSym) 59481ad6265SDimitry Andric return EDynSym.takeError(); 595e8d8bef9SDimitry Andric 59681ad6265SDimitry Andric Expected<StringRef> EDynStr = EDynSym->getDynStr(); 59781ad6265SDimitry Andric if (!EDynStr) 59881ad6265SDimitry Andric return EDynStr.takeError(); 599e8d8bef9SDimitry Andric 60081ad6265SDimitry Andric StringRef DynStr = *EDynStr; 601e8d8bef9SDimitry Andric 602e8d8bef9SDimitry Andric // Populate Arch from ELF header. 603fe6060f1SDimitry Andric DestStub->Target.Arch = static_cast<IFSArch>(ElfFile.getHeader().e_machine); 604fe6060f1SDimitry Andric DestStub->Target.BitWidth = 605fe6060f1SDimitry Andric convertELFBitWidthToIFS(ElfFile.getHeader().e_ident[EI_CLASS]); 606fe6060f1SDimitry Andric DestStub->Target.Endianness = 607fe6060f1SDimitry Andric convertELFEndiannessToIFS(ElfFile.getHeader().e_ident[EI_DATA]); 608fe6060f1SDimitry Andric DestStub->Target.ObjectFormat = "ELF"; 609e8d8bef9SDimitry Andric 610e8d8bef9SDimitry Andric // Populate SoName from .dynamic entries and dynamic string table. 61181ad6265SDimitry Andric if (DynEnt.SONameOffset) { 612e8d8bef9SDimitry Andric Expected<StringRef> NameOrErr = 613e8d8bef9SDimitry Andric terminatedSubstr(DynStr, *DynEnt.SONameOffset); 614e8d8bef9SDimitry Andric if (!NameOrErr) { 615e8d8bef9SDimitry Andric return appendToError(NameOrErr.takeError(), "when reading DT_SONAME"); 616e8d8bef9SDimitry Andric } 617e8d8bef9SDimitry Andric DestStub->SoName = std::string(*NameOrErr); 618e8d8bef9SDimitry Andric } 619e8d8bef9SDimitry Andric 620e8d8bef9SDimitry Andric // Populate NeededLibs from .dynamic entries and dynamic string table. 621e8d8bef9SDimitry Andric for (uint64_t NeededStrOffset : DynEnt.NeededLibNames) { 622e8d8bef9SDimitry Andric Expected<StringRef> LibNameOrErr = 623e8d8bef9SDimitry Andric terminatedSubstr(DynStr, NeededStrOffset); 624e8d8bef9SDimitry Andric if (!LibNameOrErr) { 625e8d8bef9SDimitry Andric return appendToError(LibNameOrErr.takeError(), "when reading DT_NEEDED"); 626e8d8bef9SDimitry Andric } 627e8d8bef9SDimitry Andric DestStub->NeededLibs.push_back(std::string(*LibNameOrErr)); 628e8d8bef9SDimitry Andric } 629e8d8bef9SDimitry Andric 630e8d8bef9SDimitry Andric // Populate Symbols from .dynsym table and dynamic string table. 631e8d8bef9SDimitry Andric Expected<uint64_t> SymCount = ElfFile.getDynSymtabSize(); 632e8d8bef9SDimitry Andric if (!SymCount) 633e8d8bef9SDimitry Andric return SymCount.takeError(); 634e8d8bef9SDimitry Andric if (*SymCount > 0) { 635e8d8bef9SDimitry Andric // Get pointer to in-memory location of .dynsym section. 63681ad6265SDimitry Andric Expected<const uint8_t *> DynSymPtr = EDynSym->getDynSym(); 637e8d8bef9SDimitry Andric if (!DynSymPtr) 638e8d8bef9SDimitry Andric return appendToError(DynSymPtr.takeError(), 639e8d8bef9SDimitry Andric "when locating .dynsym section contents"); 640e8d8bef9SDimitry Andric Elf_Sym_Range DynSyms = ArrayRef<Elf_Sym>( 641e8d8bef9SDimitry Andric reinterpret_cast<const Elf_Sym *>(*DynSymPtr), *SymCount); 642e8d8bef9SDimitry Andric Error SymReadError = populateSymbols<ELFT>(*DestStub, DynSyms, DynStr); 643e8d8bef9SDimitry Andric if (SymReadError) 644e8d8bef9SDimitry Andric return appendToError(std::move(SymReadError), 645e8d8bef9SDimitry Andric "when reading dynamic symbols"); 646e8d8bef9SDimitry Andric } 647e8d8bef9SDimitry Andric 648e8d8bef9SDimitry Andric return std::move(DestStub); 649e8d8bef9SDimitry Andric } 650e8d8bef9SDimitry Andric 651e8d8bef9SDimitry Andric /// This function opens a file for writing and then writes a binary ELF stub to 652e8d8bef9SDimitry Andric /// the file. 653e8d8bef9SDimitry Andric /// 654e8d8bef9SDimitry Andric /// @param FilePath File path for writing the ELF binary. 655fe6060f1SDimitry Andric /// @param Stub Source InterFace Stub to generate a binary ELF stub from. 656e8d8bef9SDimitry Andric template <class ELFT> 657fe6060f1SDimitry Andric static Error writeELFBinaryToFile(StringRef FilePath, const IFSStub &Stub, 658e8d8bef9SDimitry Andric bool WriteIfChanged) { 659e8d8bef9SDimitry Andric ELFStubBuilder<ELFT> Builder{Stub}; 660e8d8bef9SDimitry Andric // Write Stub to memory first. 661e8d8bef9SDimitry Andric std::vector<uint8_t> Buf(Builder.getSize()); 662e8d8bef9SDimitry Andric Builder.write(Buf.data()); 663e8d8bef9SDimitry Andric 664e8d8bef9SDimitry Andric if (WriteIfChanged) { 665e8d8bef9SDimitry Andric if (ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrError = 666e8d8bef9SDimitry Andric MemoryBuffer::getFile(FilePath)) { 667e8d8bef9SDimitry Andric // Compare Stub output with existing Stub file. 668e8d8bef9SDimitry Andric // If Stub file unchanged, abort updating. 669e8d8bef9SDimitry Andric if ((*BufOrError)->getBufferSize() == Builder.getSize() && 670e8d8bef9SDimitry Andric !memcmp((*BufOrError)->getBufferStart(), Buf.data(), 671e8d8bef9SDimitry Andric Builder.getSize())) 672e8d8bef9SDimitry Andric return Error::success(); 673e8d8bef9SDimitry Andric } 674e8d8bef9SDimitry Andric } 675e8d8bef9SDimitry Andric 676e8d8bef9SDimitry Andric Expected<std::unique_ptr<FileOutputBuffer>> BufOrError = 677e8d8bef9SDimitry Andric FileOutputBuffer::create(FilePath, Builder.getSize()); 678e8d8bef9SDimitry Andric if (!BufOrError) 679e8d8bef9SDimitry Andric return createStringError(errc::invalid_argument, 680e8d8bef9SDimitry Andric toString(BufOrError.takeError()) + 681e8d8bef9SDimitry Andric " when trying to open `" + FilePath + 682e8d8bef9SDimitry Andric "` for writing"); 683e8d8bef9SDimitry Andric 684e8d8bef9SDimitry Andric // Write binary to file. 685e8d8bef9SDimitry Andric std::unique_ptr<FileOutputBuffer> FileBuf = std::move(*BufOrError); 686e8d8bef9SDimitry Andric memcpy(FileBuf->getBufferStart(), Buf.data(), Buf.size()); 687e8d8bef9SDimitry Andric 688e8d8bef9SDimitry Andric return FileBuf->commit(); 689e8d8bef9SDimitry Andric } 690e8d8bef9SDimitry Andric 691fe6060f1SDimitry Andric Expected<std::unique_ptr<IFSStub>> readELFFile(MemoryBufferRef Buf) { 692e8d8bef9SDimitry Andric Expected<std::unique_ptr<Binary>> BinOrErr = createBinary(Buf); 693e8d8bef9SDimitry Andric if (!BinOrErr) { 694e8d8bef9SDimitry Andric return BinOrErr.takeError(); 695e8d8bef9SDimitry Andric } 696e8d8bef9SDimitry Andric 697e8d8bef9SDimitry Andric Binary *Bin = BinOrErr->get(); 698e8d8bef9SDimitry Andric if (auto Obj = dyn_cast<ELFObjectFile<ELF32LE>>(Bin)) { 699e8d8bef9SDimitry Andric return buildStub(*Obj); 700e8d8bef9SDimitry Andric } else if (auto Obj = dyn_cast<ELFObjectFile<ELF64LE>>(Bin)) { 701e8d8bef9SDimitry Andric return buildStub(*Obj); 702e8d8bef9SDimitry Andric } else if (auto Obj = dyn_cast<ELFObjectFile<ELF32BE>>(Bin)) { 703e8d8bef9SDimitry Andric return buildStub(*Obj); 704e8d8bef9SDimitry Andric } else if (auto Obj = dyn_cast<ELFObjectFile<ELF64BE>>(Bin)) { 705e8d8bef9SDimitry Andric return buildStub(*Obj); 706e8d8bef9SDimitry Andric } 707e8d8bef9SDimitry Andric return createStringError(errc::not_supported, "unsupported binary format"); 708e8d8bef9SDimitry Andric } 709e8d8bef9SDimitry Andric 710e8d8bef9SDimitry Andric // This function wraps the ELFT writeELFBinaryToFile() so writeBinaryStub() 711e8d8bef9SDimitry Andric // can be called without having to use ELFType templates directly. 712fe6060f1SDimitry Andric Error writeBinaryStub(StringRef FilePath, const IFSStub &Stub, 713fe6060f1SDimitry Andric bool WriteIfChanged) { 714fe6060f1SDimitry Andric assert(Stub.Target.Arch); 715fe6060f1SDimitry Andric assert(Stub.Target.BitWidth); 716fe6060f1SDimitry Andric assert(Stub.Target.Endianness); 717fe6060f1SDimitry Andric if (Stub.Target.BitWidth == IFSBitWidthType::IFS32) { 718fe6060f1SDimitry Andric if (Stub.Target.Endianness == IFSEndiannessType::Little) { 719e8d8bef9SDimitry Andric return writeELFBinaryToFile<ELF32LE>(FilePath, Stub, WriteIfChanged); 720fe6060f1SDimitry Andric } else { 721e8d8bef9SDimitry Andric return writeELFBinaryToFile<ELF32BE>(FilePath, Stub, WriteIfChanged); 722fe6060f1SDimitry Andric } 723fe6060f1SDimitry Andric } else { 724fe6060f1SDimitry Andric if (Stub.Target.Endianness == IFSEndiannessType::Little) { 725e8d8bef9SDimitry Andric return writeELFBinaryToFile<ELF64LE>(FilePath, Stub, WriteIfChanged); 726fe6060f1SDimitry Andric } else { 727e8d8bef9SDimitry Andric return writeELFBinaryToFile<ELF64BE>(FilePath, Stub, WriteIfChanged); 728fe6060f1SDimitry Andric } 729fe6060f1SDimitry Andric } 730e8d8bef9SDimitry Andric llvm_unreachable("invalid binary output target"); 731e8d8bef9SDimitry Andric } 732e8d8bef9SDimitry Andric 733fe6060f1SDimitry Andric } // end namespace ifs 734e8d8bef9SDimitry Andric } // end namespace llvm 735