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