aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/InterfaceStub/ELFObjHandler.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-08-22 19:00:43 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-11-13 20:39:49 +0000
commitfe6060f10f634930ff71b7c50291ddc610da2475 (patch)
tree1483580c790bd4d27b6500a7542b5ee00534d3cc /contrib/llvm-project/llvm/lib/InterfaceStub/ELFObjHandler.cpp
parentb61bce17f346d79cecfd8f195a64b10f77be43b1 (diff)
parent344a3780b2e33f6ca763666c380202b18aab72a3 (diff)
Diffstat (limited to 'contrib/llvm-project/llvm/lib/InterfaceStub/ELFObjHandler.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/InterfaceStub/ELFObjHandler.cpp115
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