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