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