diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2021-08-22 19:00:43 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2021-11-13 20:39:49 +0000 |
commit | fe6060f10f634930ff71b7c50291ddc610da2475 (patch) | |
tree | 1483580c790bd4d27b6500a7542b5ee00534d3cc /contrib/llvm-project/llvm/lib/InterfaceStub/ELFObjHandler.cpp | |
parent | b61bce17f346d79cecfd8f195a64b10f77be43b1 (diff) | |
parent | 344a3780b2e33f6ca763666c380202b18aab72a3 (diff) |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/InterfaceStub/ELFObjHandler.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/InterfaceStub/ELFObjHandler.cpp | 115 |
1 files changed, 55 insertions, 60 deletions
diff --git a/contrib/llvm-project/llvm/lib/InterfaceStub/ELFObjHandler.cpp b/contrib/llvm-project/llvm/lib/InterfaceStub/ELFObjHandler.cpp index 255d301362eb..112c1cea354a 100644 --- a/contrib/llvm-project/llvm/lib/InterfaceStub/ELFObjHandler.cpp +++ b/contrib/llvm-project/llvm/lib/InterfaceStub/ELFObjHandler.cpp @@ -7,7 +7,7 @@ //===-----------------------------------------------------------------------===/ #include "llvm/InterfaceStub/ELFObjHandler.h" -#include "llvm/InterfaceStub/ELFStub.h" +#include "llvm/InterfaceStub/IFSStub.h" #include "llvm/MC/StringTableBuilder.h" #include "llvm/Object/Binary.h" #include "llvm/Object/ELFObjectFile.h" @@ -27,7 +27,7 @@ using namespace llvm::object; using namespace llvm::ELF; namespace llvm { -namespace elfabi { +namespace ifs { // Simple struct to hold relevant .dynamic entries. struct DynamicEntries { @@ -180,7 +180,7 @@ public: ELFStubBuilder(const ELFStubBuilder &) = delete; ELFStubBuilder(ELFStubBuilder &&) = default; - explicit ELFStubBuilder(const ELFStub &Stub) { + explicit ELFStubBuilder(const IFSStub &Stub) { DynSym.Name = ".dynsym"; DynSym.Align = sizeof(Elf_Addr); DynStr.Name = ".dynstr"; @@ -191,7 +191,7 @@ public: ShStrTab.Align = 1; // Populate string tables. - for (const ELFSymbol &Sym : Stub.Symbols) + for (const IFSSymbol &Sym : Stub.Symbols) DynStr.Content.add(Sym.Name); for (const std::string &Lib : Stub.NeededLibs) DynStr.Content.add(Lib); @@ -213,14 +213,14 @@ public: DynStr.Size = DynStr.Content.getSize(); // Populate dynamic symbol table. - for (const ELFSymbol &Sym : Stub.Symbols) { + for (const IFSSymbol &Sym : Stub.Symbols) { uint8_t Bind = Sym.Weak ? STB_WEAK : STB_GLOBAL; // For non-undefined symbols, value of the shndx is not relevant at link // time as long as it is not SHN_UNDEF. Set shndx to 1, which // points to ".dynsym". uint16_t Shndx = Sym.Undefined ? SHN_UNDEF : 1; DynSym.Content.add(DynStr.Content.getOffset(Sym.Name), Sym.Size, Bind, - (uint8_t)Sym.Type, 0, Shndx); + convertIFSSymbolTypeToELF(Sym.Type), 0, Shndx); } DynSym.Size = DynSym.Content.getSize(); @@ -250,7 +250,8 @@ public: fillStrTabShdr(ShStrTab); // Finish initializing the ELF header. - initELFHeader<ELFT>(ElfHeader, Stub.Arch); + initELFHeader<ELFT>(ElfHeader, + static_cast<uint16_t>(Stub.Target.Arch.getValue())); ElfHeader.e_shstrndx = ShStrTab.Index; ElfHeader.e_shnum = LastSection->Index + 1; ElfHeader.e_shoff = @@ -303,7 +304,10 @@ private: SymTab.Shdr.sh_flags = SHF_ALLOC; SymTab.Shdr.sh_addr = SymTab.Addr; SymTab.Shdr.sh_offset = SymTab.Offset; - SymTab.Shdr.sh_info = SymTab.Size / sizeof(Elf_Sym) > 1 ? 1 : 0; + // Only non-local symbols are included in the tbe file, so .dynsym only + // contains 1 local symbol (the undefined symbol at index 0). The sh_info + // should always be 1. + SymTab.Shdr.sh_info = 1; SymTab.Shdr.sh_size = SymTab.Size; SymTab.Shdr.sh_name = this->ShStrTab.Content.getOffset(SymTab.Name); SymTab.Shdr.sh_addralign = SymTab.Align; @@ -440,37 +444,15 @@ static Error populateDynamic(DynamicEntries &Dyn, return Error::success(); } -/// This function extracts symbol type from a symbol's st_info member and -/// maps it to an ELFSymbolType enum. -/// Currently, STT_NOTYPE, STT_OBJECT, STT_FUNC, and STT_TLS are supported. -/// Other symbol types are mapped to ELFSymbolType::Unknown. -/// -/// @param Info Binary symbol st_info to extract symbol type from. -static ELFSymbolType convertInfoToType(uint8_t Info) { - Info = Info & 0xf; - switch (Info) { - case ELF::STT_NOTYPE: - return ELFSymbolType::NoType; - case ELF::STT_OBJECT: - return ELFSymbolType::Object; - case ELF::STT_FUNC: - return ELFSymbolType::Func; - case ELF::STT_TLS: - return ELFSymbolType::TLS; - default: - return ELFSymbolType::Unknown; - } -} - -/// This function creates an ELFSymbol and populates all members using +/// This function creates an IFSSymbol and populates all members using /// information from a binary ELFT::Sym. /// -/// @param SymName The desired name of the ELFSymbol. +/// @param SymName The desired name of the IFSSymbol. /// @param RawSym ELFT::Sym to extract symbol information from. template <class ELFT> -static ELFSymbol createELFSym(StringRef SymName, +static IFSSymbol createELFSym(StringRef SymName, const typename ELFT::Sym &RawSym) { - ELFSymbol TargetSym{std::string(SymName)}; + IFSSymbol TargetSym{std::string(SymName)}; uint8_t Binding = RawSym.getBinding(); if (Binding == STB_WEAK) TargetSym.Weak = true; @@ -478,9 +460,9 @@ static ELFSymbol createELFSym(StringRef SymName, TargetSym.Weak = false; TargetSym.Undefined = RawSym.isUndefined(); - TargetSym.Type = convertInfoToType(RawSym.st_info); + TargetSym.Type = convertELFSymbolTypeToIFS(RawSym.st_info); - if (TargetSym.Type == ELFSymbolType::Func) { + if (TargetSym.Type == IFSSymbolType::Func) { TargetSym.Size = 0; } else { TargetSym.Size = RawSym.st_size; @@ -488,14 +470,14 @@ static ELFSymbol createELFSym(StringRef SymName, return TargetSym; } -/// This function populates an ELFStub with symbols using information read +/// This function populates an IFSStub with symbols using information read /// from an ELF binary. /// -/// @param TargetStub ELFStub to add symbols to. +/// @param TargetStub IFSStub to add symbols to. /// @param DynSym Range of dynamic symbols to add to TargetStub. /// @param DynStr StringRef to the dynamic string table. template <class ELFT> -static Error populateSymbols(ELFStub &TargetStub, +static Error populateSymbols(IFSStub &TargetStub, const typename ELFT::SymRange DynSym, StringRef DynStr) { // Skips the first symbol since it's the NULL symbol. @@ -508,28 +490,28 @@ static Error populateSymbols(ELFStub &TargetStub, uint8_t Visibility = RawSym.getVisibility(); if (!(Visibility == STV_DEFAULT || Visibility == STV_PROTECTED)) continue; - // Create an ELFSymbol and populate it with information from the symbol + // Create an IFSSymbol and populate it with information from the symbol // table entry. Expected<StringRef> SymName = terminatedSubstr(DynStr, RawSym.st_name); if (!SymName) return SymName.takeError(); - ELFSymbol Sym = createELFSym<ELFT>(*SymName, RawSym); - TargetStub.Symbols.insert(std::move(Sym)); + IFSSymbol Sym = createELFSym<ELFT>(*SymName, RawSym); + TargetStub.Symbols.push_back(std::move(Sym)); // TODO: Populate symbol warning. } return Error::success(); } -/// Returns a new ELFStub with all members populated from an ELFObjectFile. +/// Returns a new IFSStub with all members populated from an ELFObjectFile. /// @param ElfObj Source ELFObjectFile. template <class ELFT> -static Expected<std::unique_ptr<ELFStub>> +static Expected<std::unique_ptr<IFSStub>> buildStub(const ELFObjectFile<ELFT> &ElfObj) { using Elf_Dyn_Range = typename ELFT::DynRange; using Elf_Phdr_Range = typename ELFT::PhdrRange; using Elf_Sym_Range = typename ELFT::SymRange; using Elf_Sym = typename ELFT::Sym; - std::unique_ptr<ELFStub> DestStub = std::make_unique<ELFStub>(); + std::unique_ptr<IFSStub> DestStub = std::make_unique<IFSStub>(); const ELFFile<ELFT> &ElfFile = ElfObj.getELFFile(); // Fetch .dynamic table. Expected<Elf_Dyn_Range> DynTable = ElfFile.dynamicEntries(); @@ -558,7 +540,12 @@ buildStub(const ELFObjectFile<ELFT> &ElfObj) { DynEnt.StrSize); // Populate Arch from ELF header. - DestStub->Arch = ElfFile.getHeader().e_machine; + DestStub->Target.Arch = static_cast<IFSArch>(ElfFile.getHeader().e_machine); + DestStub->Target.BitWidth = + convertELFBitWidthToIFS(ElfFile.getHeader().e_ident[EI_CLASS]); + DestStub->Target.Endianness = + convertELFEndiannessToIFS(ElfFile.getHeader().e_ident[EI_DATA]); + DestStub->Target.ObjectFormat = "ELF"; // Populate SoName from .dynamic entries and dynamic string table. if (DynEnt.SONameOffset.hasValue()) { @@ -606,9 +593,9 @@ buildStub(const ELFObjectFile<ELFT> &ElfObj) { /// the file. /// /// @param FilePath File path for writing the ELF binary. -/// @param Stub Source ELFStub to generate a binary ELF stub from. +/// @param Stub Source InterFace Stub to generate a binary ELF stub from. template <class ELFT> -static Error writeELFBinaryToFile(StringRef FilePath, const ELFStub &Stub, +static Error writeELFBinaryToFile(StringRef FilePath, const IFSStub &Stub, bool WriteIfChanged) { ELFStubBuilder<ELFT> Builder{Stub}; // Write Stub to memory first. @@ -642,7 +629,7 @@ static Error writeELFBinaryToFile(StringRef FilePath, const ELFStub &Stub, return FileBuf->commit(); } -Expected<std::unique_ptr<ELFStub>> readELFFile(MemoryBufferRef Buf) { +Expected<std::unique_ptr<IFSStub>> readELFFile(MemoryBufferRef Buf) { Expected<std::unique_ptr<Binary>> BinOrErr = createBinary(Buf); if (!BinOrErr) { return BinOrErr.takeError(); @@ -663,18 +650,26 @@ Expected<std::unique_ptr<ELFStub>> readELFFile(MemoryBufferRef Buf) { // This function wraps the ELFT writeELFBinaryToFile() so writeBinaryStub() // can be called without having to use ELFType templates directly. -Error writeBinaryStub(StringRef FilePath, const ELFStub &Stub, - ELFTarget OutputFormat, bool WriteIfChanged) { - if (OutputFormat == ELFTarget::ELF32LE) - return writeELFBinaryToFile<ELF32LE>(FilePath, Stub, WriteIfChanged); - if (OutputFormat == ELFTarget::ELF32BE) - return writeELFBinaryToFile<ELF32BE>(FilePath, Stub, WriteIfChanged); - if (OutputFormat == ELFTarget::ELF64LE) - return writeELFBinaryToFile<ELF64LE>(FilePath, Stub, WriteIfChanged); - if (OutputFormat == ELFTarget::ELF64BE) - return writeELFBinaryToFile<ELF64BE>(FilePath, Stub, WriteIfChanged); +Error writeBinaryStub(StringRef FilePath, const IFSStub &Stub, + bool WriteIfChanged) { + assert(Stub.Target.Arch); + assert(Stub.Target.BitWidth); + assert(Stub.Target.Endianness); + if (Stub.Target.BitWidth == IFSBitWidthType::IFS32) { + if (Stub.Target.Endianness == IFSEndiannessType::Little) { + return writeELFBinaryToFile<ELF32LE>(FilePath, Stub, WriteIfChanged); + } else { + return writeELFBinaryToFile<ELF32BE>(FilePath, Stub, WriteIfChanged); + } + } else { + if (Stub.Target.Endianness == IFSEndiannessType::Little) { + return writeELFBinaryToFile<ELF64LE>(FilePath, Stub, WriteIfChanged); + } else { + return writeELFBinaryToFile<ELF64BE>(FilePath, Stub, WriteIfChanged); + } + } llvm_unreachable("invalid binary output target"); } -} // end namespace elfabi +} // end namespace ifs } // end namespace llvm |